Page MenuHomePhabricator

[ecash-coinselect] Fix byte count calculation logic
ClosedPublic

Authored by emack on Aug 16 2023, 02:39.

Details

Summary

T3225

This diff fixes bytecount related logic and unit tests, including contextual comments.

Test Plan

npm test

Diff Detail

Repository
rABC Bitcoin ABC
Lint
Lint Not Applicable
Unit
Tests Not Applicable

Event Timeline

There are a very large number of changes, so older changes are hidden. Show Older Changes
Fabien requested changes to this revision.Aug 23 2023, 08:18
Fabien added inline comments.
modules/ecash-coinselect/src/utxo.js
164 ↗(On Diff #41904)

imo the fact that this is p2pkh only should be reflected in the function name

180 ↗(On Diff #41904)
183 ↗(On Diff #41904)
184 ↗(On Diff #41904)

padding ? It's signedness

185 ↗(On Diff #41904)
186 ↗(On Diff #41904)

same

191 ↗(On Diff #41904)

you should not use the average value, but since low S is enforced as a standardness rule, it's fair to use 72 bytes as an upper limit (sighash included).

193 ↗(On Diff #41904)

That's wrong. DER signature can be < 71 bytes due to r and S encoding:
https://bitcoin.stackexchange.com/questions/112662/what-is-the-probability-of-an-ecdsa-signature-being-less-than-71-bytes

It's just unlikely; also that doesn't change the conclusion.

201 ↗(On Diff #41904)

OK (didn't check) but this has nothing to do in this function that computes the size of a p2pkh only tx

204 ↗(On Diff #41904)

Would be nice to have the option to choose but this might be added later.

229 ↗(On Diff #41904)

That's wrong.

modules/ecash-coinselect/test/utxo.test.js
52 ↗(On Diff #41904)

The way you computed it, this sentence is wrong.

70 ↗(On Diff #41904)

Dito

88 ↗(On Diff #41904)

dito

This revision now requires changes to proceed.Aug 23 2023, 08:18
emack marked 14 inline comments as done.

Responding to feedback

modules/ecash-coinselect/src/utxo.js
164 ↗(On Diff #41904)

Updated function name

180 ↗(On Diff #41904)

Updated comment

183 ↗(On Diff #41904)

Updated comment

184 ↗(On Diff #41904)

Updated comment

186 ↗(On Diff #41904)

Updated comment

191 ↗(On Diff #41904)

Updated comment

193 ↗(On Diff #41904)

Updated comment based on minimum size of DER signatures being 64 bytes from the article above, which would make the minimum scriptSig 100 bytes for a minimum p2pkh input byte size of 140 bytes.

201 ↗(On Diff #41904)

Removed comment.

204 ↗(On Diff #41904)

Added to backlog via T3270.

229 ↗(On Diff #41904)

Corrected to reflect length of the pk_script, which is 25 bytes in length and safe under uint8 (1 byte).
Also verified the max pk_script length is 10k bytes as noted here, which is safe under uint16 (3 bytes).

image.png (168×872 px, 16 KB)

modules/ecash-coinselect/test/utxo.test.js
52 ↗(On Diff #41904)

Updated verification via online tx size calculator

70 ↗(On Diff #41904)

Updated verification via online tx size calculator

88 ↗(On Diff #41904)

Updated verification via online tx size calculator

Fabien requested changes to this revision.Aug 24 2023, 12:46
Fabien added inline comments.
modules/ecash-coinselect/src/utxo.js
31 ↗(On Diff #41912)

I don't see anything in that function that checks the utxos are p2pkh

175–176 ↗(On Diff #41912)
222 ↗(On Diff #41912)

Why do you link an old version of bitcoin ?? Also this comment is really irrelevant, describing what is not in the code is useless. The relevant part is only the line below

164 ↗(On Diff #41904)

it's not updated ?

193 ↗(On Diff #41904)

That's not the minimum technically, it's just statistically irrelevant to consider lower signatures

modules/ecash-coinselect/test/utxo.test.js
52 ↗(On Diff #41904)

Do you understand why I said it was wrong in your case ? Having the raw tx hex was much nicer that using a 3rd party lib to check your implementation. I have no idea if that lib is correct.

This revision now requires changes to proceed.Aug 24 2023, 12:46
emack marked 6 inline comments as done.

Responding to feedback

modules/ecash-coinselect/src/utxo.js
31 ↗(On Diff #41912)

reverted

175–176 ↗(On Diff #41912)

Updated

222 ↗(On Diff #41912)

Removed redundant info

164 ↗(On Diff #41904)

Updated for real this time

193 ↗(On Diff #41904)

Updated

modules/ecash-coinselect/test/utxo.test.js
52 ↗(On Diff #41904)

Reverted back to raw tx hex.
After reviewing calcP2pkhByteCount, the range isn't just based on the input count, it should be inputCount + outputCount on the basis that the variances are in P2PKH_IN_SIZE and P2PKH_OUT_SIZE.

Fabien requested changes to this revision.Aug 24 2023, 16:07
Fabien added inline comments.
modules/ecash-coinselect/test/utxo.test.js
52 ↗(On Diff #41904)

Except that there is no variance in the scriptpubkey. Where is the variance ?

This revision now requires changes to proceed.Aug 24 2023, 16:07
emack requested review of this revision.Aug 25 2023, 02:57
emack marked an inline comment as done.
emack added inline comments.
modules/ecash-coinselect/test/utxo.test.js
52 ↗(On Diff #41904)

yup you're right, all values in P2PKH_OUT_SIZE is fixed, I was thinking about FRAMEWORK_BYTES where there is variance based on the amount of inputs and outputs.
The only other variance I can see is the signature (64-73 bytes) in P2PKH_IN_SIZE. i.e. the bytecount upper range would be + (inputCount * 9)?

modules/ecash-coinselect/test/utxo.test.js
52 ↗(On Diff #41904)

The only other variance I can see is the signature (64-73 bytes) in P2PKH_IN_SIZE. i.e. the bytecount upper range would be + (inputCount * 9)?

Yes, the only variance is the signature size, but it can't be 73 bytes (because you're accounting for the sighash byte separately). Your way of counting is to use the worst case as per fee computation, i.e. the max possible size. So your evaluation CANNOT be less than the real size, it can only be over-evaluated. And realistically there is very little chance than you get a signature with a size which is not 71 or 72 bytes (unless it's a schnorr signature, but they are still rare). So in your case it's fair to consider that you can over-evaluate by 1 byte per input (but not under-evaluate, which was why I told you it was wrong to begin with).

Please make it very clear in a comment why you can have this error and why you choose that range.

emack marked an inline comment as done.

Updated unit tests to reflect byte size calculations

Fabien requested changes to this revision.Aug 25 2023, 12:32

It looks good now, so the only thing that remains is to get rid of the boilerplate. Create a function that takes the raw tx in the test to avoid repeating the comment and the asserts all over the place, and it's good to go.

This revision now requires changes to proceed.Aug 25 2023, 12:32

Added isWithinByteCountRange function

Ok, can you please split this in 2 pieces ? The actual byte count bug fix first, which should be green easily as it's been heavily reviewed here, then the input accounting for op_return in another diff based on this ? This diff has more to do with the byte count calculation than the feature change now. Also please update the title and summary accordingly.

Backed out OP_RETURN related logic, leaving only the bytecount calculation fixes

emack retitled this revision from [ecash-coinselect] Update getInputUtxos to support custom outputs and OP_RETURN bytecounts to [ecash-coinselect] Fix byte count calculation logic.Aug 25 2023, 14:46
emack edited the summary of this revision. (Show Details)

Code lgtm but I see there is not test on CI, can you please add the CI config for this lib ? In another diff ofc

You can rebase after D14415 is landed. Also feel free to review.

Fabien requested changes to this revision.Aug 25 2023, 21:44

Clearing my queue

This revision now requires changes to proceed.Aug 25 2023, 21:44
This revision is now accepted and ready to land.Aug 26 2023, 00:11