prepare: Can use original UTXO snapshot signature.

Prints UTXO snapshot hashing progress.
Add signature of snapshot hashes.
Add PGP keys for Nicolas Dorier.
This commit is contained in:
tecnovert 2025-02-02 11:07:28 +02:00
parent 6165cbc4c3
commit 05ffa5e3ac
3 changed files with 241 additions and 32 deletions

View file

@ -47,6 +47,7 @@ from basicswap.bin.run import (
getWalletBinName,
)
PARTICL_VERSION = os.getenv("PARTICL_VERSION", "23.2.7.0")
PARTICL_VERSION_TAG = os.getenv("PARTICL_VERSION_TAG", "")
PARTICL_LINUX_EXTRA = os.getenv("PARTICL_LINUX_EXTRA", "nousb")
@ -132,6 +133,7 @@ expected_key_ids = {
"pasta": ("52527BEDABE87984", "E2F3D7916E722D38"),
"reuben": ("1290A1D0FA7EE109",),
"nav_builder": ("2782262BF6E7FADB",),
"nicolasdorier": ("6618763EF09186FE", "223FDA69DEBEA82D", "62FE85647DEDDA2E"),
"decred_release": ("6D897EDF518A031D",),
"Calin_Culianu": ("21810A542031C02C",),
}
@ -529,6 +531,23 @@ def havePubkey(gpg, key_id):
return False
def getFileHash(file_path, print_progress: bool = False) -> str:
h = hashlib.sha256()
if print_progress:
reporthook = make_reporthook(0, logger)
total_size: int = os.stat(file_path).st_size
block_num: int = 0
block_size: int = 1024 * 1024
with open(file_path, "rb") as fp:
while data_chunk := fp.read(block_size):
h.update(data_chunk)
block_num += 1
if print_progress:
reporthook(block_num, block_size, total_size)
return h.hexdigest()
def downloadPIVXParams(output_dir):
# util/fetch-params.sh
@ -549,10 +568,8 @@ def downloadPIVXParams(output_dir):
url = urllib.parse.urljoin(source_url, k)
path = os.path.join(output_dir, k)
downloadFile(url, path)
hasher = hashlib.sha256()
with open(path, "rb") as fp:
hasher.update(fp.read())
file_hash = hasher.hexdigest()
file_hash = getFileHash(path)
logger.info("%s hash: %s", k, file_hash)
assert file_hash == v
finally:
@ -1010,23 +1027,17 @@ def prepareCore(coin, version_data, settings, data_dir, extra_opts={}):
if not os.path.exists(assert_sig_path):
downloadFile(assert_sig_url, assert_sig_path)
hasher = hashlib.sha256()
with open(release_path, "rb") as fp:
hasher.update(fp.read())
release_hash = hasher.digest()
logger.info("%s hash: %s", release_filename, release_hash.hex())
release_hash = getFileHash(release_path)
logger.info(f"{release_filename} hash: {release_hash}")
with (
open(assert_path, "rb", 0) as fp,
mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ) as s,
):
if s.find(bytes(release_hash.hex(), "utf-8")) == -1:
if s.find(bytes(release_hash, "utf-8")) == -1:
raise ValueError(
"Error: release hash %s not found in assert file."
% (release_hash.hex())
f"Error: Release hash {release_hash} not found in assert file."
)
else:
logger.info("Found release hash in assert file.")
logger.info("Found release hash in assert file.")
if SKIP_GPG_VALIDATION:
logger.warning(
@ -2029,36 +2040,52 @@ def signal_handler(sig, frame):
def check_btc_fastsync_data(base_dir, sync_filename):
logger.info("Validating signature for: " + sync_filename)
asc_filename = sync_filename + ".asc"
asc_filename = "utxo-snapshot-bitcoin-mainnet-hashes.asc"
asc_file_path = os.path.join(base_dir, asc_filename)
sync_file_path = os.path.join(base_dir, sync_filename)
if not os.path.exists(asc_file_path):
if BITCOIN_FASTSYNC_SIG_URL:
try:
downloadFile(BITCOIN_FASTSYNC_SIG_URL, asc_file_path)
except Exception as e:
logging.warning(f"Download failed: {e}")
elif not os.path.exists(asc_file_path):
base_path = getBasePath()
local_path = os.path.join(base_path, "pgp", "sigs", asc_filename)
if os.path.exists(local_path):
shutil.copyfile(local_path, asc_file_path)
if not os.path.exists(asc_file_path):
raise ValueError("Unable to find snapshot assert file.")
logger.info(f"Hashing {sync_filename}:")
utxo_snapshot_hash = getFileHash(sync_file_path, print_progress=True)
logger.info(f"{sync_filename} hash: {utxo_snapshot_hash}")
with (
open(asc_file_path, "rb", 0) as fp,
mmap.mmap(fp.fileno(), 0, access=mmap.ACCESS_READ) as s,
):
if s.find(bytes(utxo_snapshot_hash, "utf-8")) == -1:
raise ValueError(
f"Error: Snapshot hash {utxo_snapshot_hash} not found in assert file."
)
logger.info("Found snapshot hash in assert file.")
if not os.path.exists(asc_file_path):
asc_file_urls = []
if BITCOIN_FASTSYNC_SIG_URL:
asc_file_urls.append(BITCOIN_FASTSYNC_SIG_URL)
for url in asc_file_urls:
try:
downloadFile(url, asc_file_path)
break
except Exception as e:
logging.warning(f"Download failed: {e}")
if not os.path.exists(asc_file_path):
raise ValueError("Unable to find snapshot signature file.")
gpg = gnupg.GPG()
pubkey_filename = "{}_{}.pgp".format("particl", "tecnovert")
pubkeyurls = []
if not havePubkey(gpg, expected_key_ids["tecnovert"][0]):
importPubkey(gpg, pubkey_filename, pubkeyurls)
with open(asc_file_path, "rb") as fp:
verified = gpg.verify_file(fp, sync_file_path)
ensureValidSignatureBy(verified, "tecnovert")
verified = gpg.verify_file(fp)
if isValidSignature(verified) and verified.key_id in expected_key_ids["tecnovert"]:
ensureValidSignatureBy(verified, "tecnovert")
else:
pubkey_filename = "nicolasdorier.asc"
if not havePubkey(gpg, expected_key_ids["nicolasdorier"][0]):
importPubkey(gpg, pubkey_filename, pubkeyurls)
with open(asc_file_path, "rb") as fp:
verified = gpg.verify_file(fp)
ensureValidSignatureBy(verified, "nicolasdorier")
def ensure_coin_valid(coin: str, test_disabled: bool = True) -> None:

View file

@ -0,0 +1,161 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: https://keybase.io/nicolasdorier
Version: Keybase Go 2.6.0 (linux)
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
=sNb2
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: https://keybase.io/nicolasdorier
Version: Keybase Go 5.0.0 (windows)
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
=ut7t
-----END PGP PUBLIC KEY BLOCK-----
-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: https://keybase.io/nicolasdorier
Version: Keybase Go 5.0.0 (windows)
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
=n82A
-----END PGP PUBLIC KEY BLOCK-----

View file

@ -0,0 +1,21 @@
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
725a049bc5a9fd60b05bba4d4825d35115d99f05ab5b7716d4507c295d05172d utxo-snapshot-bitcoin-mainnet-820852.tar
744c42885df700513331a978b289d9c9d5b27e0cf1147f2f5a287b4492ff940c utxo-snapshot-bitcoin-mainnet-867690.tar
-----BEGIN PGP SIGNATURE-----
iQIzBAEBCAAdFiEEjlF9wS7BzDf2QjqKE/E2UcnPDWsFAmedUAYACgkQE/E2UcnP
DWs1Vw/+P3CGP9LLVv2deNocBFunUz+7aDZsQiykSI8ws50ssJ5PsAg5VSl4CbCl
owWOdQVJiDUh7daP0jr+bt3X2FY5ORBb1TGlvfCHE+vLfEFDnTpLXouSCclP0cv8
Ci8zQFKSI5Pf6uSMpALgQZxBgNU/0IegAQbpuJI4nrQXTKHJcMqtw1LtnmcreESO
MsSiGCXnC1R+xGQjptfvbzXaQVrin7ctYA9zjN4CGbjNChzr+ywT8dht2RKoLYyP
OrEys7d8EIaw/ktRvRmyk6O7KmnvUhf0uuFlDq+eTiBIpQoUEovCow1YYKaWkIRB
r4JBJJ34AB+XC2hgi5jpJNub/wKgVBm0iy79zZOSILP3ymbn3iJGg4ifUF0YeZCU
ufYkYi3iTJDpwYr0tylZmBiwsWNcbUhB+WTNX7ogCW70ZuhrF0PJQRPmhI34vsE/
qg3n0/hNNsypy0epRd33KSOvrSmaoTKLtCax9Osnt+F+yTYjD5EPqkQuzlJl+fDe
VvjWO5XHuaRvzijBrJQz6r5V4e/0ioNa8FTRqWmMTO1wHmxF5glpozyKycv9+bsB
IL9F1IQjhPkSVI7Hw8bsURpfH4mV+9eZJJDIvBf1/0gDctsBdsI5+5jxZjup769Q
AmMsGeZoplm/eUofQ9hItWcVitPhisDmC3wDR71UKM0b9FF6IUY=
=YUjt
-----END PGP SIGNATURE-----