The most commonly used transaction mode in bitcoin: the composition of the signed content "message" in P2P KH
1, Unlocking and locking script (P2PKH: payment to public key hash)
The figure above shows the unlocking process of P2P KH transaction. It is also the most commonly used transaction mode of bitcoin.
Record the generation of sig.
2, Creation of transactions
1. Whether the available UTXO traversing its own address is greater than the amount of the transaction. 2 Calculation of transaction fee 3 if utxo > = fee + amount is available, start organizing transactions. 1> Generate TxOut output one by one and add it to the array (including transfer address and change address). 2> TxIn is generated from UTXO and added to the array. 3> Sign the TxIn in the TxIn array one by one. 4> Send transaction information.
TxIn is signed one by one, including the following types:
The following table information is taken from: btcd source parsing signature mechanism (1) - basic knowledge
"Signature types", more accurately known as Signature Hash Types, mainly include four basic types: sighash ũ all, sighash ũ none, sighash ũ single, sighash ũ anyonecanpay
Basic types | Simple description | purpose |
---|---|---|
SIGHASH_ALL | message contains all output | Default type, most widely used |
SIGHASH_NONE | message does not contain any output | Allow anyone to spend this money by building output |
SIGHASH_SINGLE | message contains a specific (corresponding to the input) output | Ensure that your output is not tampered with, but allow other people's output to be changed |
SIGHASH_ANYONECANPAY | message contains the current input | Allow anyone to build input, that is, allow anyone to enter amount into the transaction |
It's easy to find that the first three (sighash ﹐ all, sighash ﹐ none, sighash ﹐ single) are mainly used to limit output, while sighash ﹐ anyonecanpay is used to limit input. In any signature, you need to specify one of the first three (optionally) to be decorated with sighash ﹣ anyonecanpay.
classification | Combination type | Simple description | purpose |
---|---|---|---|
No modification class | SIGHASH_ALL | message contains all input and output | Default type, most widely used |
No modification class | SIGHASH_NONE | message contains all input, not any output | Allow anyone to spend this money by building output |
No modification class | SIGHASH_SINGLE | message contains all input and specific (corresponding to input) output | Ensure that your output is not tampered with, but allow other people's output to be changed |
Modified class | SIGHASH_ALL | SIGHASH_ANYONECANPAY | message contains all output and current input | Often used to fund "crowdfunding" |
Modified class | SIGHASH_NONE | SIGHASH_ANYONECANPAY | message contains only the current input, not any output | Allow anyone to enter the amount and anyone to spend it |
Modified class | SIGHASH_SINGLE | SIGHASH_ANYONECANPAY | message contains only the current input and the corresponding output | Allow anyone to input the amount, and ensure that the corresponding output is not tampered with |
Here we focus on the most common form, SIGHASH_ALL
3, Organization process of signature content (message) (sighash_alltype)
1 hashPrevouts; // All the transaction id(hash) and sequence n of UTXO referenced in the input (vin array) are summed up and the hash obtained by sha256 is done. 2 hashSequence; // After summarizing all the nsequences in the above figure, do the hash obtained by sha256. 3 hashOutputs; // After the nValue and scriptPubKey of all output (vout array) are summarized, the hash obtained by sha256 is done.
In addition to the above three variables, there are other information components, including nVersion, Nin (how many inputs in total), and so on.
4, Source related
Function call process:
Where Solver( )Function to get whether the script locking mode is P2PKH or P2SH, etc.
CWallet::CreateTransaction(… ) -> ProduceSignature(… ) -> SignStep(… ) -> Solver(… ) ->Sign1(… ) -> TransactionSignatureCreator::CreateSig(… ) -> SignatureHash(… )And CKey::Sign( );
Here is the SignatureHash() function
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache) { assert(nIn < txTo.vin.size()); if (sigversion == SIGVERSION_WITNESS_V0) { uint256 hashPrevouts; uint256 hashSequence; uint256 hashOutputs; const bool cacheready = cache && cache->ready; // Obtain the above three main data if (!(nHashType & SIGHASH_ANYONECANPAY)) { hashPrevouts = cacheready ? cache->hashPrevouts : GetPrevoutHash(txTo); } if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { hashSequence = cacheready ? cache->hashSequence : GetSequenceHash(txTo); } if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) { hashOutputs = cacheready ? cache->hashOutputs : GetOutputsHash(txTo); } else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) { CHashWriter ss(SER_GETHASH, 0); ss << txTo.vout[nIn]; hashOutputs = ss.GetHash(); } // Summarize all used signature data (message) including the above three main data CHashWriter ss(SER_GETHASH, 0); // Version ss << txTo.nVersion; // Input prevouts/nSequence (none/all, depending on flags) ss << hashPrevouts; ss << hashSequence; // The input being signed (replacing the scriptSig with scriptCode + amount) // The prevout may already be contained in hashPrevout, and the nSequence // may already be contain in hashSequence. ss << txTo.vin[nIn].prevout; ss << scriptCode; ss << amount; ss << txTo.vin[nIn].nSequence; // Outputs (none/one/all, depending on flags) ss << hashOutputs; // Locktime ss << txTo.nLockTime; // Sighash type ss << nHashType; return ss.GetHash(); }
The generation process of three main data: hashPrevouts, hashSequence, and hashOutputs:
uint256 GetPrevoutHash(const CTransaction& txTo) { CHashWriter ss(SER_GETHASH, 0); for (const auto& txin : txTo.vin) { ss << txin.prevout; // prevout is of type COutPoint } return ss.GetHash(); } class COutPoint { public: uint256 hash; uint32_t n; ... ADD_SERIALIZE_METHODS; template <typename Stream, typename Operation> // Serialize hash and n into byte stream s inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(hash); READWRITE(n); } ... }; uint256 GetSequenceHash(const CTransaction& txTo) { CHashWriter ss(SER_GETHASH, 0); for (const auto& txin : txTo.vin) { ss << txin.nSequence; // nSequence is of type int } return ss.GetHash(); } uint256 GetOutputsHash(const CTransaction& txTo) { CHashWriter ss(SER_GETHASH, 0); for (const auto& txout : txTo.vout) { ss << txout; // txout is of type CTxOut } return ss.GetHash(); } class CTxOut { public: CAmount nValue; CScript scriptPubKey; ... ADD_SERIALIZE_METHODS; template <typename Stream, typename Operation> // Serialize nValue and scriptPubKey into byte streams inline void SerializationOp(Stream& s, Operation ser_action) { READWRITE(nValue); READWRITE(scriptPubKey); } ... };
CKey::Sign() function is the process of signing using secp256k1 elliptic curve encryption function library:
bool CKey::Sign(const uint256 &hash, std::vector<unsigned char>& vchSig, uint32_t test_case) const { if (!fValid) return false; vchSig.resize(72); size_t nSigLen = 72; unsigned char extra_entropy[32] = {0}; WriteLE32(extra_entropy, test_case); secp256k1_ecdsa_signature sig; int ret = secp256k1_ecdsa_sign(secp256k1_context_sign, &sig, hash.begin(), begin(), secp256k1_nonce_function_rfc6979, test_case ? extra_entropy : nullptr); assert(ret); secp256k1_ecdsa_signature_serialize_der(secp256k1_context_sign, (unsigned char*)vchSig.data(), &nSigLen, &sig); vchSig.resize(nSigLen); return true; }
After obtaining all the contents that need to be signed through the SignatureHash() function, call the Key::Sign() function to sign. Then update the signature information to the scriptSig field in vin, and it is finished.
*Note: This article is for personal notes. If there is something wrong, please correct it.
Welcome to the official account of idler's casual talk. We look forward to sharing technology with you.