-
Notifications
You must be signed in to change notification settings - Fork 632
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
CTransaction.stream_deserialize allows flagbyte != 1 #220
Comments
Hi @dgpv, this looks simple enough to tip my toes in without messing up, so you are referring to: in this library it means raising an exception at around the line you referenced when flagbyte is not 0 and not 1, in particular a ValueError with the string "Unknown transaction optional data", and then adding an invalid tx in the invalid_tx.json file of the tests/data folder. Is there something else to be taken into consideration? |
I've handled it this way: https://github.com/Simplexum/python-bitcointx/blob/e3e3726d53c3948ed249ee79cf2b808c7f875add/bitcointx/core/__init__.py#L1100-L1108 Note that this does not allow a transaction with empty inputs, and the unserialize code in Core allows it, but for the case when both inputs and outputs are empty. AFAIR it checks for empty inputs/outputs in another place. I think there is some fringe case where Core needs to unserialize a transaction with empty inputs and outputs, but I can't remember what it is. I decided to just straightforwardly disallow this and fail for I also did not add a test for this. If you add test data, I might use if for tests in bitcointx. |
Hi, thanks! I gave it a quick try yesterday evening, that approach breaks 6 tests, I think the reason lies in the comment: so there are two ways:
let me know what you think, thanks! python-bitcoinlib/bitcoin/core/__init__.py Lines 432 to 434 in ebc85bf
|
I thought a bit about my solution and decided that it was not entirely adequate, as indeed deserializing empty transactions can be useful in some contexts. So I decided to just copy the logic from the Core: Simplexum@3bd0ce8 This has added benefit that it gets rid of the requirement for the stream to be seekable, as |
Hello, so after reading more in depth, it looks to me the tests want exceptions raised from CheckTransaction python-bitcoinlib/bitcoin/core/__init__.py Line 784 in ebc85bf
To do so, I've added "markerbyte" and "flagbyte" to the class around here: python-bitcoinlib/bitcoin/core/__init__.py Lines 388 to 392 in ebc85bf
and then in stream_deserialize the first if clause remains as is, in the second one I try to deserialise everything if marker=0 regardless of the flag, if that fails, roll back the stream with f.seek and continue as before Inside CheckTransactions there are two new checks:
to test I'm just using a segwit transaction from the bitcoincpp tests and switching the flagbyte to "2": ["Witness with SigHash Single|AnyoneCanPay (same signature as previous)"], to use this as-is (with a 4th element in prevout), we'll need >=3 here
So I'll clean it up and post it, thanks for sharing also Simplexum, that library though is quite different, for instance even if we could remove seek and pos from this deserialisation, it is still used elsewhere. Moreover & 1 and ^=1 may work as intended also in python, but in cpp may have a different meaning, it may work, I didn't test it, it just looked odd to me. |
As far as I know, the semantics of bit manipulation operations is the same, only the bit width in python is not fixed: https://wiki.python.org/moin/BitwiseOperators I don't think that adding a property ( |
Hello, sorry got stuck on something else. I've followed your advice, used only flagbyte, and just sent the pull request with the simple modifications. isn't "x^=1" the same as "x = x^1" in python? I didn't test though, it just caught my eye |
python-bitcoinlib/bitcoin/core/__init__.py
Line 425 in ebc85bf
if flagbyte != 1, then it will try to deserialize as non-witness, whereas Core in
UnserializeTransaction
checks that flags are actually expected (only first bit is expected now) and will dothrow std::ios_base::failure("Unknown transaction optional data");
if there's unexpected bits set in flags.It certainly looks like that the
CTransaction.deserialize()
is not correct and should fail if it sees flagbytes != 1The text was updated successfully, but these errors were encountered: