Skip to content

Commit 3cf239e

Browse files
committed
bip-325: change signature scheme to be tx-based
1 parent 5cc0c6f commit 3cf239e

File tree

1 file changed

+42
-30
lines changed

1 file changed

+42
-30
lines changed

bip-0325.mediawiki

Lines changed: 42 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -26,36 +26,48 @@ A new type of test network would be more suitable for integration testing by org
2626

2727
A new type of network ("signet"), which takes an additional consensus parameter called the challenge (scriptPubKey). The challenge can be a simple pubkey (P2PKH style), or a k-of-n multisig, or any other script you would want.
2828

29-
The witness commitment of the coinbase transaction is extended to include a secondary commitment (the signature/solution):
30-
31-
1-4 bytes - Push the following (x + 4) bytes
32-
4 bytes - Signet header (0xecc7daa2)
33-
x bytes - Solution (sigScript)
34-
35-
Any push operations that do not start with the 4 byte signet header are ignored. Multiple push operations with the 4 byte signet header are ignored except for the first entry.
36-
37-
Any signature operations contained within the challenge use SHA256d(modifiedBlockHash), i.e. the double-SHA256 digest of the following data as the sighash:
38-
39-
{|class="wikitable" style="text-align: center;"
40-
|-
41-
!Type
42-
!Size
43-
!Name
44-
|-
45-
|Int32||4||nVersion
46-
|-
47-
|Uint256||32||hashPrevBlock
48-
|-
49-
|Uint256||32||modifiedMerkleRoot
50-
|-
51-
|Uint32||4||nTime
52-
|-
53-
|Uint32||4||nBits
54-
|}
55-
56-
The <code>modifiedMerkleRoot</code> hash is obtained by generating the merkle root of the block transactions, with the coinbase witness commitment as is, without the signet extension. This means the merkle root of the block is different from the merkle root in the signet commitment. This is needed, because the signature can never be included in the very message (in this case, a block) that is being signed. Apart from the signature, to facilitate block generation (mining), the block nonce value is the only other component of the block that the signet signature does not commit to. When grinding proof of work, the extended nonce cannot be used as it would invalidate the signature. Instead, simply resigning the same (or an updated) block will give a new search space.
57-
58-
A block is considered fully validated if the above commitment is found, and its solution is valid. It is recommended that this verification is done directly before or after the witness commitment verification, as the data required to do both is approximately the same.
29+
The witness commitment of the coinbase transaction is extended to include a secondary commitment (the signature/solution) of either:
30+
31+
1-4 bytes - Push the following (4 + x + y) bytes
32+
4 bytes - Signet scriptSig header (0xecc7daa2)
33+
x bytes - scriptSig
34+
y bytes - scriptWitness
35+
36+
The scriptSig is serialized by first encoding its length as CompactSize. If the scriptWitness is empty, it is encoded as 0 bytes, otherwise it is encoded in the usual way (see BIP 141 "witness" encoding).
37+
38+
Any push operations that do not start with the 4 byte Signet header are ignored. Multiple push operations with the 4 byte Signet header are ignored except for the first instance of the header.
39+
40+
To sign the block or verify a block signature, two virtual transactions, each with a single input and output are constructed from the block as follows.
41+
42+
The "to_spend" transaction is:
43+
44+
nVersion = 0
45+
nLockTime = 0
46+
vin[0].prevout.hash = 0000...000
47+
vin[0].prevout.n = 0xFFFFFFFF
48+
vin[0].nSequence = 0
49+
vin[0].scriptSig = OP_0 PUSH72[ block_data ]
50+
vin[0].scriptWitness = []
51+
vout[0].nValue = 0
52+
vout[0].scriptPubKey = signet_challenge
53+
54+
where block_data is the serialization of the block's nVersion, hashPrevBlock, signet_merkle_root, and nTime. The <code>signet_merkle_root</code> is obtained by generating the merkle root of the block transactions, after modifying the coinbase witness commitment by replacing the signet solution with an empty solution (that is, the witness commitment includes a four byte push of the Signet header with no additional solution data, and no prior pushes beginning with the Signet header). This means the merkle root of the block is different from the merkle root in the signet commitment. This is needed, because the signature can never be included in the very message (in this case, a block) that is being signed.
55+
56+
The "to_sign" transaction is:
57+
58+
nVersion = 0
59+
nLockTime = 0
60+
vin[0].prevout.hash = to_spend.txid
61+
vin[0].prevout.n = 0
62+
vin[0].nSequence = 0
63+
vout[0].nValue = 0
64+
vout[0].scriptPubKey = signet_challenge
65+
66+
The scriptSig and/or scriptWitness for <code>vin[0]</code> are filled in from the Signet header push above.
67+
68+
To simplify block generation (mining), the signature also does not commit to the the block nonce value, so that rolling the nonce to generate proof-of-work does not also require regenerating signatures. When grinding proof of work, the extended nonce cannot be used as it would invalidate the signature. Instead, simply resigning the same (or an updated) block will give a new search space.
69+
70+
A block is considered fully validated only if the to_sign transaction is a valid spend of the to_spend transaction. It is recommended that this verification is done directly before or after the witness commitment verification, as the data required to do both is approximately the same.
5971

6072
== Genesis Block and Message Start ==
6173

0 commit comments

Comments
 (0)