-
Notifications
You must be signed in to change notification settings - Fork 28
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
tests(sighash): add sighash bitmask tests [part 2/7] #912
base: feat/sighash/bitmask
Are you sure you want to change the base?
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## feat/sighash/bitmask #912 +/- ##
========================================================
+ Coverage 84.12% 84.35% +0.22%
========================================================
Files 321 321
Lines 24601 24601
Branches 3773 3773
========================================================
+ Hits 20696 20751 +55
+ Misses 3168 3113 -55
Partials 737 737 ☔ View full report in Codecov by Sentry. |
9ebcf3e
to
9042fd7
Compare
78b027b
to
1b44d48
Compare
5df23a6
to
9f778fd
Compare
1b44d48
to
fc82733
Compare
tests/tx/scripts/test_p2pkh.py
Outdated
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.
Should we test the the script regex can correctly match all these cases?
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.
The script regex is only made to match output scripts, isn't it? It wouldn't match any of those input data
|
||
def test_defaults() -> None: | ||
settings = Mock() | ||
settings.MAX_NUM_OUTPUTS = 99 |
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.
Why not test using the current value?
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 doing it like this asserts that the code is correctly retrieving information from settings, instead of having a hardcoded value that happens to be the same as the one we have in settings. I added a test for the current value in 2bf7549, though
(0b00, set()), | ||
(0b01, {0}), | ||
(0b10, {1}), | ||
(0b11, {0, 1}), |
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.
Should we add one more 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.
You mean testing 0b111
, for example? That would raise an exception, as the test tx only has 2 outputs. This error is checked in test_sighash.py
.
tests/tx/scripts/test_sighash.py
Outdated
storage=self.manager1.tx_storage, | ||
timestamp=token_creation_tx.timestamp + 1 | ||
) | ||
self.manager1.cpu_mining_service.resolve(atomic_swap_tx) |
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.
Why are you resolving the tx here if it's gonna be modified just after this point?
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.
Because the tx is going to be verified on line 99, so it needs to be resolved.
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.
But you are modifying the transaction on line 90, so the hash will become invalid again. Am I missing something?
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 passes the verification like this anyway. But I moved it closer to the verification line in 9147127
) | ||
|
||
# At this point, the tx is partial. The inputs are valid, but they're mismatched with outputs | ||
self.manager1.verification_service.verifiers.tx.verify_inputs(atomic_swap_tx) |
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.
Shouldn't it fail since there's no sighash all?
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 requirement is only implemented in Part 7: #917
with self.assertRaises(MissingStackItems): | ||
op_sighash_bitmask(ScriptContext(stack=[b''], extras=Mock(), logs=[], settings=Mock())) | ||
|
||
with self.assertRaises(AssertionError): |
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.
Why would it be an assertion error? Is it because they are not bytes?
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.
Exactly!
tests/tx/test_scripts.py
Outdated
with self.assertRaises(CustomSighashModelInvalid): | ||
op_sighash_bitmask(context) | ||
|
||
context.stack = [bytes([0b111]), bytes([0b101])] |
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.
Maybe add tests with different endianness.
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.
What do you mean? Endianness has no meaning in this context as this string of bits is never interpreted as a number, it's simply a string of bits
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 meant that 0b1101
should be different from 0b1011
.
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.
Ah ok, done in 75790a3
tests/tx/test_scripts.py
Outdated
def test_execute_op_code(self) -> None: | ||
with ( | ||
patch('hathor.transaction.scripts.opcode.is_opcode_valid', lambda _: False), | ||
self.assertRaises(ScriptError) |
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.
Should it be an INVALID_OPCODE
or UNKNOWN_OPCODE
?
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 those have different meanings. An unknown opcode is a concept that already exists, for example, a number that doesn't represent any option in the Opcode
enum. An invalid opcode, however, is a new concept introduced by this project. It's an opcode that we now exists, but it's not activated (valid) yet.
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 got it. But shouldn't we capture the more specific exception? We have to be very careful in these changes because it's a critical part of the full node.
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.
Got it, I added assertions for the exception message in 75790a3
patch('hathor.transaction.scripts.opcode.is_opcode_valid', lambda _: True), | ||
self.assertRaises(ScriptError) | ||
): | ||
execute_op_code(opcode=Opcode.OP_0, context=Mock()) |
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.
What are we testing here?
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 when is_opcode_valid
returns True
, execution must fail if it's not a "function opcode". I added a comment for it in 2bf7549
execute_op_code(opcode=Opcode.OP_0, context=Mock()) | ||
|
||
with patch('hathor.transaction.scripts.opcode.op_dup') as op_mock: | ||
execute_op_code(opcode=Opcode.OP_DUP, context=Mock()) |
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.
What are we testing here?
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 the function associated with a valid opcode is correctly called. I added a comment for it in 2bf7549
tests/tx/scripts/__init__.py
Outdated
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.
Maybe add tests to make sure that a sighash all will mark all inputs and outputs as selected at least once.
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 is implemented in Part 7: https://github.com/HathorNetwork/hathor-core/pull/917/files
86d10b4
to
2bf7549
Compare
b611297
to
783f397
Compare
783f397
to
ebebb1f
Compare
ebebb1f
to
3c1f9a7
Compare
3c1f9a7
to
a457f0a
Compare
2bf7549
to
ad1def9
Compare
6bbc55a
to
922055e
Compare
ad1def9
to
890c630
Compare
Depends on #911
Motivation
The previous PR introduced the structure for sighash types, including sighash bitmask for P2PKH scripts. It fixed existing tests, but did not introduce any new tests. This PR does this.
Acceptance Criteria