-
-
Notifications
You must be signed in to change notification settings - Fork 677
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
Multisig fix in legacy #4396
Multisig fix in legacy #4396
Conversation
4839e37
to
c9adb55
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.
- fixtures are missing (
tests/update_fixtures.py ci
should work) - I'm getting some failures on hardware that I'm not seeing in emulator, e.g.:
Not 100% sure this is because of this PR, would appreciate someone else checking. Needs fix(legacy): uint64 protobuf field decoding #4535 in order to work on HW.
FAILED tests/device_tests/bitcoin/test_multisig_change.py::test_sorted_multisig_change_match_first - AssertionError: Expected responses: FAILED tests/device_tests/bitcoin/test_multisig_change.py::test_multisig_change_match_second - AssertionError: Expected responses: FAILED tests/device_tests/bitcoin/test_multisig_change.py::test_multisig_change_match_first - AssertionError: Expected responses: FAILED tests/device_tests/bitcoin/test_bcash.py::test_send_bch_multisig_change - AssertionError: Expected responses:
I hopefully fixed it in bc0ecfe. |
bc0ecfe
to
bedff6e
Compare
I squashed the fixup commits, rebased on top of the main branch and added fixtures. |
My trezor one device is somewhat broken so I was only able to run |
Can confirm that all multisig tests now pass on my T1. But I don't understand where the problem was - shouldn't |
To be honest, I'm not certain. However, based on how the code is carefully written (see, for example, this), I thought that EDITED: Changed example. |
I think the property is set to zeroes if unset by wire, but still I prefer to have the code explicit rather than implicit to be on the safe side once this behaviour changes in future versions of nanopb or something like that.
Also this might be the culprit in some cases like we've seen recently. So explicit code is better. |
Yep I think it's |
SHA256_CTX ctx = {0}; | ||
sha256_Init(&ctx); | ||
sha256_Update(&ctx, (const uint8_t *)&(multisig->m), sizeof(uint32_t)); | ||
sha256_Update(&ctx, (const uint8_t *)&(pubkeys_order), sizeof(uint32_t)); |
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.
...that means that this code is wrong, right?
what we want is, pseudocode:
MultisigPubkeysOrder pubkeys_order = ...
sha256_Update(multisig->m, sizeof(multisig->m);
sha256_Update(pubkeys_order, sizeof(pubkeys_order));
...
etc for this whole block.
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.
I believe the code is correct now. The only difference from your pseudocode is that I cast MultisigPubkeysOrder
to uint32_t
.
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.
my point is that we're magically relying on all the things being u32-sized, with no actual proof in the code (which was the source of the previous bug)
the code is correct now, but could break again in theory
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.
I have no problem changing uint32_t
to MultisigPubkeysOrder
. However, I don't still understand what you mean by "but could break again in theory". My code doesn't rely on MultisigPubkeysOrder
to be uint32_t
.
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.
In this case, it is not important, but generally, I think my solution is better because it ensures that the resulting hash is the same on both the emulator and the hardware.
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.
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.
I think both the requirement that the hash result stays stable as well as resilience to member size changes are valid.
From this POV it would be best to go with
sha256_Update(multisig->m, sizeof(multisig->m));
followed by a static assert that sizeof(multisig->m) == sizeof(uint32_t)
. As it's a matter of taste I'd say let's merge this PR as it is so we don't hold up the release, and continue in another PR.
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.
Okay, I understand now. I initially thought you were only referring to pubkeys_order
, but you are also talking about m
and others.
I tested it and can confirm that the size of |
This pull request backports #4351 to legacy.