Skip to content

Commit

Permalink
contrib: Fixup verify-binaries OS platform parsing
Browse files Browse the repository at this point in the history
Parse platform strings with "-" or '.' correctly such as "linux-gnu" or
"x86_64-linux-gnu.tar.gz" to download the matching files or file. String
partition() is used to tolerate more dashes. Update `VERSION_EXAMPLE`
with a new string parsed correctly now. Fix "-aarch64" interpreted as a
release candidate due to sub-string "rc", causing all downloads to fail.
Now "rc" must immediately follow first "-" to indicate an [-rc] string.
Local variables `version_rc`, `version_os` renamed to `rc`, `platform`.
If "-rcN" is specified, `platform` is reassigned to remove the '-rcN'.

Changes are useful to only download one bitcoin core binary on slow
connections. Making `verify.py pub` more intuitive, robust, and
versatile. Closes #30145

When user types a platform string not found in any filename lets help
and say the platform closest to what they typed in a `f"No files
matched the platform specified. Did you mean: {closest_match}"` log.
Improves UX when unaware how we name our files.
Uses the difflib Python built-in which was already imported elsewhere.

Update test.py to test single file verification
verify-binaries/verify.py can accept an entire filename filter for its
"-platform" parameter now so let us test that it succeeds and downloads
and verifies only one file. `verify.py pub 22.0-x86_64-linux-gnu.tar.gz`
should get and verify only the requested binary. It is placed before the
existing <version> wide verification as it is a faster test and possibly
easier to break.

Update doc with examples now possible after bugfix
Add example to show release candidates now work with "-platform" strings
containing "-" and string provided can be from the middle of filename:
`./contrib/verify-binaries/verify.py --json pub 23.0-rc5-linux-gnu`
Change example 5 to not match example 3.
New examples to show platform can now be provided specifically enough to
download only a single binary down to its file extension:
`./contrib/verify-binaries/verify.py pub 25.2-x86_64-linux`
`./contrib/verify-binaries/verify.py pub 24.1-rc1-darwin`
`./contrib/verify-binaries/verify.py pub 27.0-win64-setup.exe`
This is the most common use if not verifying all files so users see it
as the first example for "only download the binaries for a certain
architecture and/or platform". Downloading one file is intuitively what
most will think this meant and this change delivers on that expectation.

Co-authored-by: stickies-v
  • Loading branch information
BenWestgate authored and janus committed Jul 26, 2024
1 parent abc08c7 commit d10bfd3
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 19 deletions.
10 changes: 6 additions & 4 deletions contrib/verify-binaries/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,23 @@ Get JSON output and don't prompt for user input (no auto key import):

```sh
./contrib/verify-binaries/verify.py --json pub 22.0-x86
./contrib/verify-binaries/verify.py --json pub 23.0-rc5-linux-gnu
```

Rely only on local GPG state and manually specified keys, while requiring a
threshold of at least 10 trusted signatures:
```sh
./contrib/verify-binaries/verify.py \
--trusted-keys 74E2DEF5D77260B98BC19438099BAD163C70FBFA,9D3CC86A72F8494342EA5FD10A41BDC3F4FAFF1C \
--min-good-sigs 10 pub 22.0-x86
--min-good-sigs 10 pub 22.0-linux
```

If you only want to download the binaries for a certain platform, add the corresponding suffix, e.g.:
If you only want to download the binaries for a certain architecture and/or platform, add the corresponding suffix, e.g.:

```sh
./contrib/verify-binaries/verify.py pub 24.0.1-darwin
./contrib/verify-binaries/verify.py pub 23.1-rc1-win64
./contrib/verify-binaries/verify.py pub 25.2-x86_64-linux
./contrib/verify-binaries/verify.py pub 24.1-rc1-darwin
./contrib/verify-binaries/verify.py pub 27.0-win64-setup.exe
```

If you do not want to keep the downloaded binaries, specify the cleanup option.
Expand Down
15 changes: 15 additions & 0 deletions contrib/verify-binaries/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ def main():
expect_code(run_verify('0.32.awefa.12f9h'), 11, "Malformed version should fail")
expect_code(run_verify('22.0 --min-good-sigs 20'), 9, "--min-good-sigs 20 should fail")

print("- testing verification (22.0-x86_64-linux-gnu.tar.gz)", flush=True)
_220_x86_64_linux_gnu = run_verify("--json", "pub", "22.0-x86_64-linux-gnu.tar.gz")
try:
result = json.loads(_220_x86_64_linux_gnu.stdout.decode())
except Exception:
print("failed on 22.0-x86_64-linux-gnu.tar.gz --json:")
print_process_failure(_220_x86_64_linux_gnu)
raise

expect_code(_220_x86_64_linux_gnu, 0, "22.0-x86_64-linux-gnu.tar.gz should succeed")
v = result['verified_binaries']
assert result['good_trusted_sigs']
assert len(v) == 1
assert v['bitcoin-22.0-x86_64-linux-gnu.tar.gz'] == '59ebd25dd82a51638b7a6bb914586201e67db67b919b2a1ff08925a7936d1b16'

print("- testing verification (22.0)", flush=True)
_220 = run_verify("--json", "pub", "22.0")
try:
Expand Down
26 changes: 11 additions & 15 deletions contrib/verify-binaries/verify.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ def bool_from_env(key, default=False) -> bool:


VERSION_FORMAT = "<major>.<minor>[.<patch>][-rc[0-9]][-platform]"
VERSION_EXAMPLE = "22.0-x86_64 or 23.1-rc1-darwin"
VERSION_EXAMPLE = "22.0 or 23.1-rc1-darwin.dmg or 27.0-x86_64-linux-gnu"

parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
Expand Down Expand Up @@ -200,20 +200,14 @@ def bool_from_env(key, default=False) -> bool:
VERSION_EXAMPLE = "22.0-x86_64 or 0.21.0-rc2-osx"

def parse_version_string(version_str):
parts = version_str.split('-')
version_base = parts[0]
version_rc = ""
version_os = ""
if len(parts) == 2: # "<version>-rcN" or "version-platform"
if "rc" in parts[1]:
version_rc = parts[1]
else:
version_os = parts[1]
elif len(parts) == 3: # "<version>-rcN-platform"
version_rc = parts[1]
version_os = parts[2]
# "<version>[-rcN][-platform]"
version_base, _, platform = version_str.partition('-')
rc = ""
if platform.startswith("rc"): # "<version>-rcN[-platform]"
rc, _, platform = platform.partition('-')
# else "<version>" or "<version>-platform"

return version_base, version_rc, version_os
return version_base, rc, platform


def download_with_wget(remote_file, local_file):
Expand Down Expand Up @@ -625,7 +619,9 @@ def cleanup():
# Extract hashes and filenames
hashes_to_verify = parse_sums_file(SUMS_FILENAME, os_filter)
if not hashes_to_verify:
log.error("no files matched the platform specified")
available_versions = ["-".join(line[1].split("-")[2:]) for line in parse_sums_file(SUMS_FILENAME, [])]
closest_match = difflib.get_close_matches(os_filter, available_versions, cutoff=0, n=1)[0]
log.error(f"No files matched the platform specified. Did you mean: {closest_match}")
return ReturnCode.NO_BINARIES_MATCH

# remove binaries that are known not to be hosted by bitcoincore.org
Expand Down

0 comments on commit d10bfd3

Please sign in to comment.