-
Notifications
You must be signed in to change notification settings - Fork 6
Draft: Changes BIP-360 to use tapscript #21
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
base: p2qrh
Are you sure you want to change the base?
Conversation
<source> | ||
script witness stack = [pubkey, signature] # len(pubkey) > 520 bytes and len(signature) > 520 bytes | ||
tapscript = [OP_DUP, OP_HASH256, OP_PUSHDATA HASH256(expected_pubkey), OP_EQUALVERIFY, OP_CHECKSIG_SLH, OP_VERIFY] | ||
</source> |
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 OP_HASH256
or OP_SHA256
? If one over the other, why?
P2WSH uses OP_SHA256
, and I'm unsure about tapscript.
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 prefer HASH256 to avoid having to worry about length extension.
tapscript uses tagged hash which is SHA256 with a tag to do domain separation. We might want to use tagged hash for this.
HashWriter TaggedHash(const std::string& tag)
{
HashWriter writer{};
uint256 taghash;
CSHA256().Write((const unsigned char*)tag.data(), tag.size()).Finalize(taghash.begin());
writer << taghash << taghash;
return writer;
}
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 prefer HASH256 to avoid having to worry about length extension.
If I understand right, I agree. It definitely should be 256 bit length.
My curiosity would be that P2QRH would be the first script to use HASH256 rather than SHA256.
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.
If I understand right, I agree. It definitely should be 256 bit length.
I'm talking about this https://en.wikipedia.org/wiki/Length_extension_attack It doesn't actually matter but it is nice not have to think about. It has been argued this was why P2SH used HASH160.
My curiosity would be that P2QRH would be the first script to use HASH256 rather than SHA256.
As written, it wouldn't be part of the P2QRH standard.
That said, I've been considering preventing OP_DUP from duplicating stack elements larger than 520 bytes. If that change was made then OP_CHECKSIG_SLH would be computing the hash and then it would become part of the standard. It might make sense to use SHA256 or tagged hash.
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.
Interesting. Thank you
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.
Great work so far! Just got a few changes and questions.
bip-0360.mediawiki
Outdated
of securely storing Bitcoins in a cold wallet for very long periods of time (50 to 100 years). | ||
|
||
For PQ signatures we considered the NIST approved SLH-DSA (SPHINCS+), ML-DSA (CRYSTALS-Dilithium), | ||
and FN-DSA (FALCON). Of these three algorithms, SLH-DSA has the largest signature size, but is the most conservative |
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.
Would it make sense to mention our investigation into SQIsign here too?
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 is a good idea, I'll add something.
I attended a talk on SQIsign a few days ago. It appears rapid progress is being made on SQIsign's performance and code complexity. It is still too early to tell, but things are looking better for SQIsign
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.
Would love to see some viable code for that so we can compare! I tried FastSQISignHD and the C was kind of a shitshow. All the key functions were commented out, and even after reenabling them, it revealed a bunch more work that needed to be done.
https://github.com/Pierrick-Dartois/SQISignHD-lib
This was a couple months ago, though, and it seems some more work has been done since.
A P2QRH script witness stack differs in only one way from a P2TR script witness stack. P2QRH does not limit the size | ||
of the witness stack elements to 520 bytes. This is needed because PQ signatures and public keys can be larger than | ||
520 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.
Should we just increase the limit to the largest signature size (SLH-DSA) ?
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's a good idea.
Co-authored-by: Hunter Beast <[email protected]>
|
||
== Specification == | ||
|
||
We define the signature scheme and transaction structure as follows. | ||
|
||
=== Descriptor Format === |
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.
Wondering the rationale for removing this section on Descriptor Format ?
Seems like it would be useful when creating p2qrh compliant wallets.
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 is being reworked and no longer fit the current plan. I want to finish the specification first and then revisit it
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.
Just some small edits to the excellent recent SQIsign addition.
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.
Just noticed CI was failing. I fixed the bug I introduced.
, Ethan Heilman
also needs to be added to the README right next to Hunter Beast
.
Co-authored-by: Hunter Beast <[email protected]>
Co-authored-by: Hunter Beast <[email protected]>
This is a draft of changes that move BIP-360 from using an witness attestation containing PQ signatures to instead using tapscript with a very P2TR like output format. The reason for this change was that much the witness attestation construction was intended to prevent PQ signatures and public keys from being as storage mechanisms, e.g. used to store JPEGs onchain by requiring that any PQ public key or PQ signature which was stored on-chain must successfully verify. Unfortunately research showed that requiring verification did not prevent using public keys and signatures for storage for details see: jpeg resistance of various post-quantum signature schemes, Westerbaan (2025). This PR abandons this earlier approach in favor of backwards compatibility with tapscript.
Changes:
TODOs:
Must be resolved before merging
assumes no stack element sizes greater than 520 bytes.
Open Questions
Drop version byte in the control block?
Currently the P2QRH control block consists of the version byte and the merkle path. The version byte is very similar to the header byte in a P2TR control block. The header byte has two purposes, specify the parity of the public key and providing versioning.
For:
Against:
How to fix DUP + no witness stack element size attack
If we remove the witness stack element size limit for P2QRH and then someone runs a tapscript consisting of
DUP DUP DUP DUP ... DUP
they can amplify the memory usage but duplicating a very large stack element.This is limited to the maximum number of stack elements on the stack
BIP-342 Tapscript Resource Limits
This creates an amplification factor of 1,000.
Assume biggest value possible 3.999mb bytes. Such a transaction use 4,000mb and would be ~3,999,000+1,000 = 4mb bytes in size. ~1000x amplification
SLH-DSA signatures are 17,088 bytes. This means that a transaction spend that can push 17,088 bytes on the stack can at most use memory 17,088,000 (17mb). Such a transaction would be ~17,088+1,000 = 18 kb bytes in size. ~1000x amplification
Current tapscript allows would use 520kb for a transaction which is 520+1,000 = 1.5kb. 346x amplification
Thus, removing this limit is not catastrophic. It is only 3 times worse than the present day. Still, not great.
New opcode OP_DUPHASH256
This approach would change the code of OP_DUP to prevent duplicating any stack element larger than 520 bytes. This would not be a consensus change as currently there is no way to put an object larger than 520 bytes on the stack.
Second, we would introduce an opcode OP_DUPHASH256 which duplicates a stack element of any size and then immediately hashes it. This allows a stack elements greater than 520 bytes to be compared to a hash without removing it from the stack. This functionality is needed to commit to PQ public keys in tapscript.
OP_CHECKSIG_VERIFY variants for PQ signatures?
Currently the specification only creates the OP_CHECKSIG for PQ signatures. Do want a OP_CHECKSIG_ML_VERIFY and OP_CHECKSIG_SHL_VERIFY?
I'm leaning toward no since users can get the same functionality with OP_VERIFY.
The yes argument is that script writers will expect OP_CHECKSIG_ML_VERIFY to exist.
OP_CHECKSIGADD variants for PQ signatures?
I'm leaning toward a strong yes:
Closed Questions
Should P2QRH and PQ Signatures opcodes be separate BIPs: Yes
The case for:
The case against:
Sighash tag specific to signature algorithm? Yes
Currently BIP-360 proposes using the tag "TapSighash" in the tagged hash of the sighash for PQ signatures. I can see an argument that the sighash should be specific to the signature algorithm used to prevent signatures from one algorithm being used for an algorithm.