Skip to content
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

Open
wants to merge 3 commits into
base: feat/sighash/bitmask
Choose a base branch
from

Conversation

glevco
Copy link
Contributor

@glevco glevco commented Jan 8, 2024

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

@glevco glevco self-assigned this Jan 8, 2024
@glevco glevco added the tests label Jan 8, 2024
@glevco glevco marked this pull request as ready for review January 8, 2024 02:10
Copy link

codecov bot commented Jan 8, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 84.35%. Comparing base (922055e) to head (75790a3).

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.
📢 Have feedback on the report? Share it here.

@glevco glevco force-pushed the feat/sighash/bitmask branch from 9ebcf3e to 9042fd7 Compare January 8, 2024 20:10
@glevco glevco force-pushed the tests/sighash/bitmask branch from 78b027b to 1b44d48 Compare January 8, 2024 20:10
@glevco glevco force-pushed the feat/sighash/bitmask branch 3 times, most recently from 5df23a6 to 9f778fd Compare January 19, 2024 22:13
@glevco glevco force-pushed the tests/sighash/bitmask branch from 1b44d48 to fc82733 Compare January 19, 2024 22:15
Copy link
Member

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?

Copy link
Contributor Author

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
Copy link
Member

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?

Copy link
Contributor Author

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}),
Copy link
Member

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?

Copy link
Contributor Author

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.

storage=self.manager1.tx_storage,
timestamp=token_creation_tx.timestamp + 1
)
self.manager1.cpu_mining_service.resolve(atomic_swap_tx)
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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?

Copy link
Contributor Author

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)
Copy link
Member

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?

Copy link
Contributor Author

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):
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly!

with self.assertRaises(CustomSighashModelInvalid):
op_sighash_bitmask(context)

context.stack = [bytes([0b111]), bytes([0b101])]
Copy link
Member

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.

Copy link
Contributor Author

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

Copy link
Member

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.

Copy link
Contributor Author

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

def test_execute_op_code(self) -> None:
with (
patch('hathor.transaction.scripts.opcode.is_opcode_valid', lambda _: False),
self.assertRaises(ScriptError)
Copy link
Member

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?

Copy link
Contributor Author

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.

Copy link
Member

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.

Copy link
Contributor Author

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())
Copy link
Member

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?

Copy link
Contributor Author

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())
Copy link
Member

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?

Copy link
Contributor Author

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

Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@glevco glevco force-pushed the tests/sighash/bitmask branch from 86d10b4 to 2bf7549 Compare January 30, 2024 01:20
@glevco glevco force-pushed the feat/sighash/bitmask branch from b611297 to 783f397 Compare March 5, 2024 16:11
@glevco glevco added this to the Test Gabriel milestone Aug 8, 2024
@glevco glevco force-pushed the feat/sighash/bitmask branch from 783f397 to ebebb1f Compare August 12, 2024 23:40
@glevco glevco force-pushed the feat/sighash/bitmask branch from ebebb1f to 3c1f9a7 Compare August 20, 2024 21:18
@glevco glevco force-pushed the feat/sighash/bitmask branch from 3c1f9a7 to a457f0a Compare December 9, 2024 23:14
@glevco glevco force-pushed the tests/sighash/bitmask branch from 2bf7549 to ad1def9 Compare December 9, 2024 23:16
@glevco glevco force-pushed the feat/sighash/bitmask branch 2 times, most recently from 6bbc55a to 922055e Compare February 25, 2025 21:02
@glevco glevco force-pushed the tests/sighash/bitmask branch from ad1def9 to 890c630 Compare February 25, 2025 21:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: In Review (WIP)
Development

Successfully merging this pull request may close these issues.

2 participants