-
Notifications
You must be signed in to change notification settings - Fork 37.7k
test: get_previous_releases.py
: M1/M2 macs can't run unsigned arm64 binaries; self-sign when needed
#26694
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
test: get_previous_releases.py
: M1/M2 macs can't run unsigned arm64 binaries; self-sign when needed
#26694
Conversation
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers. ReviewsSee the guideline for information on the review process.
If your review is incorrectly listed, please react with 👎 to this comment and the bot will ignore it on the next update. |
test/get_previous_releases.py
Outdated
@@ -108,6 +108,10 @@ def download_binary(tag, args) -> int: | |||
platform = args.platform | |||
if tag < "v23" and platform in ["x86_64-apple-darwin", "arm64-apple-darwin"]: | |||
platform = "osx64" | |||
elif tag == "v23.0" and platform == "arm64-apple-darwin": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this not affect 24 and later as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it already affects the current v24.0.1 arm64 tarball. But that is not yet being pulled into the get_previous_releases.py
list and I figured it's possible/likely(?) that a subsequent v24.x release will have the proper signing before any v24 is part of this backwards compatibility list.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See also #26586
Once there is a pull with a fix, it can set the tag here. But I am not aware of a pull/plan yet, so it seems best to avoid assuming it.
Approach NACK. Why not using self-signing:
? |
@hebasto I just confirmed that manual self-signing works. If that's the preferred workaround, I'd still rather have that step automated in I'll wait a bit for more feedback to come in. If I do end up altering the approach in this PR, is it preferable to just amend the title and description or is it better to close this PR and open a new one? |
This is what I meant :)
The former. |
Automated self signing sounds good to me (after the hash is verified). |
get_previous_releases.py
: M1/M2 macs can't run the unsigned v23.0 arm64 binary; fall back to x86_64 binaryget_previous_releases.py
: M1/M2 macs can't run unsigned arm64 binaries; self-sign when needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Concept ACK
@kdmukai you may want to squash these commits, and use a commit message that makes it clear what this is about when you later look it up on the master branch, e.g. test: self-sign bitcoind binary on arm64 macOS
.
Also, don't use @ name in the commit message, because that results in spam notifications for that person when altcoins cherry-pick it.
test/get_previous_releases.py
Outdated
|
||
# Is it already signed? | ||
result = subprocess.run(['codesign', '-v', '-d', binary_path], capture_output=True) | ||
if "code object is not signed at all" in result.stderr.decode("utf-8"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems brittle. Is there a return code we can use?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agreed. But success or error (e.g. using an unrecognized flag) both return 1
.
The output ends up in stderr
in either case, too. Unfortunately.
Approach ACK. |
test/get_previous_releases.py
Outdated
|
||
if tag >= "v23" and platform == "arm64-apple-darwin": | ||
# Starting with v23.0 there are arm64 binaries for ARM (M1/M2) macs, but they have to be signed to run | ||
binary_path = '{cwd}/{tag}/bin/bitcoind'.format(cwd=os.getcwd(), tag=tag) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For new code f-strings are recommended:
Use
f'{x}'
for string formatting in preference to'{}'.format(x)
or'%s' % x
.
See:
test/get_previous_releases.py
Outdated
@@ -148,6 +148,24 @@ def download_binary(tag, args) -> int: | |||
ret = subprocess.run(['tar', '-zxf', tarball, '-C', tag, | |||
'--strip-components=1', | |||
'bitcoin-{tag}'.format(tag=tag[1:])]).returncode | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extra spaces must be removed to pass ./test/lint/lint-whitespace.py
:
See: https://api.cirrus-ci.com/v1/task/6542625554038784/logs/lint.log
See: https://github.com/bitcoin/bitcoin/blob/master/CONTRIBUTING.md#squashing-commits |
cf5f65d
to
647d8df
Compare
Squashed! |
test/get_previous_releases.py
Outdated
subprocess.run(['codesign', '-s', '-', binary_path], capture_output=True) | ||
|
||
# Confirm success | ||
result = subprocess.run(['codesign', '-v', '-d', binary_path], capture_output=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capture_output
is Python 3.7 syntax (so this fails with Python 3.6.15)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Gah. Updated and tested against python 3.6.15.
test/get_previous_releases.py
Outdated
result = subprocess.run(['codesign', '-v', '-d', binary_path], capture_output=True) | ||
if "code object is not signed at all" in result.stderr.decode("utf-8"): | ||
# Have to self-sign the binary | ||
subprocess.run(['codesign', '-s', '-', binary_path], capture_output=True) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This nicely returns 0 for me on Intel, but I haven't checked the failure mode.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're right. It returns 1 if the -v
check doesn't find a signature, but the subsequent calls do return 0 (on successful self-sign and on verifying that new signature).
This will allow me to simplify the checks and not rely on the stderr messages. Update coming.
5eb76c6
to
f112c53
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functional tests can be run with substitution of bitcoind
with bitcoin-qt
or bitcoin-node
using the BITCOIND
variable. Does it make sense to sign not only bitcoind
binary?
test/get_previous_releases.py
Outdated
if ret: | ||
return ret |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those lines seem to follow the tar
invocation, as it is currently on the master branch. It is reasonable to exit early if the tar
command fails.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I'll update and can also capture any stderr
details if the extraction fails.
test/get_previous_releases.py
Outdated
@@ -148,6 +148,27 @@ def download_binary(tag, args) -> int: | |||
ret = subprocess.run(['tar', '-zxf', tarball, '-C', tag, | |||
'--strip-components=1', | |||
'bitcoin-{tag}'.format(tag=tag[1:])]).returncode | |||
|
|||
if tag >= "v23" and platform == "arm64-apple-darwin": | |||
# Starting with v23.0 there are arm64 binaries for ARM (M1/M2) macs, but they have to be signed to run |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Mentioning of exact models, i.e. M1/M2, does not look future proof. Maybe pointing at arm64 architecture is enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be useful to keep the "marketing" terms around for a bit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Until I started getting into Docker I hadn't been all that aware of cpu architecture details. I wouldn't have immediately associated arm64
with an M1 mac.
But I don't feel strongly either way about the comment.
So far there are no tarballs with |
412eb47
to
cf79920
Compare
Updated.
|
aabddc0
to
c9ebfb6
Compare
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested c9ebfb6 on mac M1. Binaries got signed.
While moving in the right direction, I reckon this change is not complete, because without Rosetta it is still not possible to run ./test/functional/wallet_backwards_compatibility.py
on arm64. Perhaps, it makes sense do disable some releases in the latter, doesn't it? Maybe in a follow up?
cdf6fdc
to
7121fd8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK dc12f2e
…'t run unsigned arm64 binaries; self-sign when needed dc12f2e test: improve error msg on previous release tarball extraction failure (kdmukai) 7121fd8 test: self-sign previous release binaries for arm64 macOS (kdmukai) Pull request description: ## The Problem If you run `test/get_previous_releases.py -b` on an M1 or M2 mac, you'll get an unsigned v23.0 binary in the arm64 tarball. macOS [sets stricter requirements on ARM binaries](https://news.ycombinator.com/item?id=26996578) so the unsigned arm64 binary is apparently completely unusable without being signed/notarized(?). This means that any test that depends on a previous release (e.g. `wallet_backwards_compatibility.py`) will fail because the v23.0 node cannot launch: ``` TestFramework (ERROR): Assertion failed Traceback (most recent call last): File "/Users/kdmukai/dev/bitcoin-core/test/functional/test_framework/test_framework.py", line 563, in start_nodes node.wait_for_rpc_connection() File "/Users/kdmukai/dev/bitcoin-core/test/functional/test_framework/test_node.py", line 231, in wait_for_rpc_connection raise FailedToStartError(self._node_msg( test_framework.test_node.FailedToStartError: [node 2] bitcoind exited with status -9 during initialization ``` This can also be confirmed by downloading bitcoin-23.0-arm64-apple-darwin.tar.gz (https://bitcoincore.org/bin/bitcoin-core-23.0/) and trying to run any of the binaries manually on an M1 or M2 mac. ## Solution in this PR (UPDATED) Per @ hebasto, we can self-sign the arm64 binaries. This PR checks each binary in the previous release's "bin/" and verifies if the arm64 binary is signed. If not, attempt to self-sign and confirm success. (note: an earlier version of this PR downloaded the x86_64 binary as a workaround but this approach has been discarded) ## Longer term solution If possible, produce signed arm64 binaries in a future v23.x tarball? Note that this same problem affects the new v24.0.1 arm64 tarball so perhaps a signed v24.x.x tarball would also be ideal? That being said, this PR will check all current and future arm64 binaries and self-sign as needed, so perhaps we need not worry about pre-signing the tarball binaries. And I did test a version of `get_previous_releases.py` that includes the new v24.0.1 binaries and it successfully self-signed both v23.0 and v24.0.1, as expected. ## Further info: Somewhat related to: bitcoin#15774 (comment) And @ fanquake noted on IRC that you can confirm which binaries are or are not signed via: ``` $ codesign -v -d bitcoin-qt bitcoin-qt: code object is not signed at all ``` ACKs for top commit: hebasto: ACK dc12f2e Tree-SHA512: 644895f8e97f5ffb3c4754c1db2c48abd77fa100c2058e3c896af04806596fc2b9c807a3f3a2add5be53301ad40ca2b8171585bd254e691f6eb38714d938396b
…'t run unsigned arm64 binaries; self-sign when needed dc12f2e test: improve error msg on previous release tarball extraction failure (kdmukai) 7121fd8 test: self-sign previous release binaries for arm64 macOS (kdmukai) Pull request description: ## The Problem If you run `test/get_previous_releases.py -b` on an M1 or M2 mac, you'll get an unsigned v23.0 binary in the arm64 tarball. macOS [sets stricter requirements on ARM binaries](https://news.ycombinator.com/item?id=26996578) so the unsigned arm64 binary is apparently completely unusable without being signed/notarized(?). This means that any test that depends on a previous release (e.g. `wallet_backwards_compatibility.py`) will fail because the v23.0 node cannot launch: ``` TestFramework (ERROR): Assertion failed Traceback (most recent call last): File "/Users/kdmukai/dev/bitcoin-core/test/functional/test_framework/test_framework.py", line 563, in start_nodes node.wait_for_rpc_connection() File "/Users/kdmukai/dev/bitcoin-core/test/functional/test_framework/test_node.py", line 231, in wait_for_rpc_connection raise FailedToStartError(self._node_msg( test_framework.test_node.FailedToStartError: [node 2] bitcoind exited with status -9 during initialization ``` This can also be confirmed by downloading bitcoin-23.0-arm64-apple-darwin.tar.gz (https://bitcoincore.org/bin/bitcoin-core-23.0/) and trying to run any of the binaries manually on an M1 or M2 mac. ## Solution in this PR (UPDATED) Per @ hebasto, we can self-sign the arm64 binaries. This PR checks each binary in the previous release's "bin/" and verifies if the arm64 binary is signed. If not, attempt to self-sign and confirm success. (note: an earlier version of this PR downloaded the x86_64 binary as a workaround but this approach has been discarded) ## Longer term solution If possible, produce signed arm64 binaries in a future v23.x tarball? Note that this same problem affects the new v24.0.1 arm64 tarball so perhaps a signed v24.x.x tarball would also be ideal? That being said, this PR will check all current and future arm64 binaries and self-sign as needed, so perhaps we need not worry about pre-signing the tarball binaries. And I did test a version of `get_previous_releases.py` that includes the new v24.0.1 binaries and it successfully self-signed both v23.0 and v24.0.1, as expected. ## Further info: Somewhat related to: bitcoin#15774 (comment) And @ fanquake noted on IRC that you can confirm which binaries are or are not signed via: ``` $ codesign -v -d bitcoin-qt bitcoin-qt: code object is not signed at all ``` ACKs for top commit: hebasto: ACK dc12f2e Tree-SHA512: 644895f8e97f5ffb3c4754c1db2c48abd77fa100c2058e3c896af04806596fc2b9c807a3f3a2add5be53301ad40ca2b8171585bd254e691f6eb38714d938396b
…'t run unsigned arm64 binaries; self-sign when needed dc12f2e test: improve error msg on previous release tarball extraction failure (kdmukai) 7121fd8 test: self-sign previous release binaries for arm64 macOS (kdmukai) Pull request description: ## The Problem If you run `test/get_previous_releases.py -b` on an M1 or M2 mac, you'll get an unsigned v23.0 binary in the arm64 tarball. macOS [sets stricter requirements on ARM binaries](https://news.ycombinator.com/item?id=26996578) so the unsigned arm64 binary is apparently completely unusable without being signed/notarized(?). This means that any test that depends on a previous release (e.g. `wallet_backwards_compatibility.py`) will fail because the v23.0 node cannot launch: ``` TestFramework (ERROR): Assertion failed Traceback (most recent call last): File "/Users/kdmukai/dev/bitcoin-core/test/functional/test_framework/test_framework.py", line 563, in start_nodes node.wait_for_rpc_connection() File "/Users/kdmukai/dev/bitcoin-core/test/functional/test_framework/test_node.py", line 231, in wait_for_rpc_connection raise FailedToStartError(self._node_msg( test_framework.test_node.FailedToStartError: [node 2] bitcoind exited with status -9 during initialization ``` This can also be confirmed by downloading bitcoin-23.0-arm64-apple-darwin.tar.gz (https://bitcoincore.org/bin/bitcoin-core-23.0/) and trying to run any of the binaries manually on an M1 or M2 mac. ## Solution in this PR (UPDATED) Per @ hebasto, we can self-sign the arm64 binaries. This PR checks each binary in the previous release's "bin/" and verifies if the arm64 binary is signed. If not, attempt to self-sign and confirm success. (note: an earlier version of this PR downloaded the x86_64 binary as a workaround but this approach has been discarded) ## Longer term solution If possible, produce signed arm64 binaries in a future v23.x tarball? Note that this same problem affects the new v24.0.1 arm64 tarball so perhaps a signed v24.x.x tarball would also be ideal? That being said, this PR will check all current and future arm64 binaries and self-sign as needed, so perhaps we need not worry about pre-signing the tarball binaries. And I did test a version of `get_previous_releases.py` that includes the new v24.0.1 binaries and it successfully self-signed both v23.0 and v24.0.1, as expected. ## Further info: Somewhat related to: bitcoin#15774 (comment) And @ fanquake noted on IRC that you can confirm which binaries are or are not signed via: ``` $ codesign -v -d bitcoin-qt bitcoin-qt: code object is not signed at all ``` ACKs for top commit: hebasto: ACK dc12f2e Tree-SHA512: 644895f8e97f5ffb3c4754c1db2c48abd77fa100c2058e3c896af04806596fc2b9c807a3f3a2add5be53301ad40ca2b8171585bd254e691f6eb38714d938396b
…'t run unsigned arm64 binaries; self-sign when needed dc12f2e test: improve error msg on previous release tarball extraction failure (kdmukai) 7121fd8 test: self-sign previous release binaries for arm64 macOS (kdmukai) Pull request description: ## The Problem If you run `test/get_previous_releases.py -b` on an M1 or M2 mac, you'll get an unsigned v23.0 binary in the arm64 tarball. macOS [sets stricter requirements on ARM binaries](https://news.ycombinator.com/item?id=26996578) so the unsigned arm64 binary is apparently completely unusable without being signed/notarized(?). This means that any test that depends on a previous release (e.g. `wallet_backwards_compatibility.py`) will fail because the v23.0 node cannot launch: ``` TestFramework (ERROR): Assertion failed Traceback (most recent call last): File "/Users/kdmukai/dev/bitcoin-core/test/functional/test_framework/test_framework.py", line 563, in start_nodes node.wait_for_rpc_connection() File "/Users/kdmukai/dev/bitcoin-core/test/functional/test_framework/test_node.py", line 231, in wait_for_rpc_connection raise FailedToStartError(self._node_msg( test_framework.test_node.FailedToStartError: [node 2] bitcoind exited with status -9 during initialization ``` This can also be confirmed by downloading bitcoin-23.0-arm64-apple-darwin.tar.gz (https://bitcoincore.org/bin/bitcoin-core-23.0/) and trying to run any of the binaries manually on an M1 or M2 mac. ## Solution in this PR (UPDATED) Per @ hebasto, we can self-sign the arm64 binaries. This PR checks each binary in the previous release's "bin/" and verifies if the arm64 binary is signed. If not, attempt to self-sign and confirm success. (note: an earlier version of this PR downloaded the x86_64 binary as a workaround but this approach has been discarded) ## Longer term solution If possible, produce signed arm64 binaries in a future v23.x tarball? Note that this same problem affects the new v24.0.1 arm64 tarball so perhaps a signed v24.x.x tarball would also be ideal? That being said, this PR will check all current and future arm64 binaries and self-sign as needed, so perhaps we need not worry about pre-signing the tarball binaries. And I did test a version of `get_previous_releases.py` that includes the new v24.0.1 binaries and it successfully self-signed both v23.0 and v24.0.1, as expected. ## Further info: Somewhat related to: bitcoin#15774 (comment) And @ fanquake noted on IRC that you can confirm which binaries are or are not signed via: ``` $ codesign -v -d bitcoin-qt bitcoin-qt: code object is not signed at all ``` ACKs for top commit: hebasto: ACK dc12f2e Tree-SHA512: 644895f8e97f5ffb3c4754c1db2c48abd77fa100c2058e3c896af04806596fc2b9c807a3f3a2add5be53301ad40ca2b8171585bd254e691f6eb38714d938396b
backport: bitcoin#24603, bitcoin#26694, bitcoin#24669, bitcoin#22546, bitcoin#22199, bitcoin#25817 (mac build)
The Problem
If you run
test/get_previous_releases.py -b
on an M1 or M2 mac, you'll get an unsigned v23.0 binary in the arm64 tarball. macOS sets stricter requirements on ARM binaries so the unsigned arm64 binary is apparently completely unusable without being signed/notarized(?).This means that any test that depends on a previous release (e.g.
wallet_backwards_compatibility.py
) will fail because the v23.0 node cannot launch:This can also be confirmed by downloading bitcoin-23.0-arm64-apple-darwin.tar.gz (https://bitcoincore.org/bin/bitcoin-core-23.0/) and trying to run any of the binaries manually on an M1 or M2 mac.
Solution in this PR
(UPDATED) Per @ hebasto, we can self-sign the arm64 binaries. This PR checks each binary in the previous release's "bin/" and verifies if the arm64 binary is signed. If not, attempt to self-sign and confirm success.
(note: an earlier version of this PR downloaded the x86_64 binary as a workaround but this approach has been discarded)
Longer term solution
If possible, produce signed arm64 binaries in a future v23.x tarball?
Note that this same problem affects the new v24.0.1 arm64 tarball so perhaps a signed v24.x.x tarball would also be ideal?
That being said, this PR will check all current and future arm64 binaries and self-sign as needed, so perhaps we need not worry about pre-signing the tarball binaries. And I did test a version of
get_previous_releases.py
that includes the new v24.0.1 binaries and it successfully self-signed both v23.0 and v24.0.1, as expected.Further info:
Somewhat related to: #15774 (comment)
And @ fanquake noted on IRC that you can confirm which binaries are or are not signed via: