| 66 | } |
| 67 | |
| 68 | std::optional<SignetTxs> SignetTxs::Create(const CBlock& block, const CScript& challenge) |
| 69 | { |
| 70 | CMutableTransaction tx_to_spend; |
| 71 | tx_to_spend.nVersion = 0; |
| 72 | tx_to_spend.nLockTime = 0; |
| 73 | tx_to_spend.vin.emplace_back(COutPoint(), CScript(OP_0), 0); |
| 74 | tx_to_spend.vout.emplace_back(CAsset(), 0, challenge); |
| 75 | |
| 76 | CMutableTransaction tx_spending; |
| 77 | tx_spending.nVersion = 0; |
| 78 | tx_spending.nLockTime = 0; |
| 79 | tx_spending.vin.emplace_back(COutPoint(), CScript(), 0); |
| 80 | tx_spending.witness.vtxinwit.resize(1); |
| 81 | tx_spending.vout.emplace_back(CAsset(), 0, CScript(OP_RETURN)); |
| 82 | |
| 83 | // can't fill any other fields before extracting signet |
| 84 | // responses from block coinbase tx |
| 85 | |
| 86 | // find and delete signet signature |
| 87 | if (block.vtx.empty()) return std::nullopt; // no coinbase tx in block; invalid |
| 88 | CMutableTransaction modified_cb(*block.vtx.at(0)); |
| 89 | |
| 90 | const int cidx = GetWitnessCommitmentIndex(block); |
| 91 | if (cidx == NO_WITNESS_COMMITMENT) { |
| 92 | return std::nullopt; // require a witness commitment |
| 93 | } |
| 94 | |
| 95 | CScript& witness_commitment = modified_cb.vout.at(cidx).scriptPubKey; |
| 96 | |
| 97 | std::vector<uint8_t> signet_solution; |
| 98 | if (!FetchAndClearCommitmentSection(SIGNET_HEADER, witness_commitment, signet_solution)) { |
| 99 | // no signet solution -- allow this to support OP_TRUE as trivial block challenge |
| 100 | } else { |
| 101 | try { |
| 102 | SpanReader v{SER_NETWORK, INIT_PROTO_VERSION, signet_solution}; |
| 103 | v >> tx_spending.vin[0].scriptSig; |
| 104 | v >> tx_spending.witness.vtxinwit[0].scriptWitness.stack; |
| 105 | if (!v.empty()) return std::nullopt; // extraneous data encountered |
| 106 | } catch (const std::exception&) { |
| 107 | return std::nullopt; // parsing error |
| 108 | } |
| 109 | } |
| 110 | uint256 signet_merkle = ComputeModifiedMerkleRoot(modified_cb, block); |
| 111 | |
| 112 | std::vector<uint8_t> block_data; |
| 113 | CVectorWriter writer(SER_NETWORK, INIT_PROTO_VERSION, block_data, 0); |
| 114 | writer << block.nVersion; |
| 115 | writer << block.hashPrevBlock; |
| 116 | writer << signet_merkle; |
| 117 | writer << block.nTime; |
| 118 | tx_to_spend.vin[0].scriptSig << block_data; |
| 119 | tx_spending.vin[0].prevout = COutPoint(tx_to_spend.GetHash(), 0); |
| 120 | |
| 121 | return SignetTxs{tx_to_spend, tx_spending}; |
| 122 | } |
| 123 | |
| 124 | // Signet block solution checker |
| 125 | bool CheckSignetBlockSolution(const CBlock& block, const Consensus::Params& consensusParams) |
nothing calls this directly
no test coverage detected