Skip to content

Commit 20f9fb3

Browse files
committed
Refactor: Validation: Make parts of IsValidPeginWitness templated
this should not change behavior
1 parent 7a3720a commit 20f9fb3

File tree

1 file changed

+75
-43
lines changed

1 file changed

+75
-43
lines changed

src/validation.cpp

Lines changed: 75 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2359,6 +2359,69 @@ CScript calculate_contract(const CScript& federationRedeemScript, const CScript&
23592359
return scriptDestination;
23602360
}
23612361

2362+
template<typename T>
2363+
static bool GetBlockAndTxFromMerkleBlock(uint256& block_hash, uint256& tx_hash, T& merkle_block, const std::vector<unsigned char>& merkle_block_raw)
2364+
{
2365+
try {
2366+
std::vector<uint256> txHashes;
2367+
std::vector<unsigned int> txIndices;
2368+
CDataStream merkleBlockStream(merkle_block_raw, SER_NETWORK, PROTOCOL_VERSION);
2369+
merkleBlockStream >> merkle_block;
2370+
block_hash = merkle_block.header.GetHash();
2371+
2372+
if (!merkleBlockStream.empty()) {
2373+
return false;
2374+
}
2375+
if (merkle_block.txn.ExtractMatches(txHashes, txIndices) != merkle_block.header.hashMerkleRoot || txHashes.size() != 1) {
2376+
return false;
2377+
}
2378+
tx_hash = txHashes[0];
2379+
} catch (std::exception& e) {
2380+
// Invalid encoding of merkle block
2381+
return false;
2382+
}
2383+
return true;
2384+
}
2385+
2386+
template<typename T>
2387+
static bool CheckPeginTx(const std::vector<unsigned char>& tx_data, T& pegtx, const COutPoint& prevout, const CAmount claim_amount, const CScript& claim_script)
2388+
{
2389+
try {
2390+
CDataStream pegtx_stream(tx_data, SER_NETWORK, PROTOCOL_VERSION);
2391+
pegtx_stream >> pegtx;
2392+
if (!pegtx_stream.empty()) {
2393+
return false;
2394+
}
2395+
} catch (std::exception& e) {
2396+
// Invalid encoding of transaction
2397+
return false;
2398+
}
2399+
2400+
// Check that transaction matches txid
2401+
if (pegtx->GetHash() != prevout.hash) {
2402+
return false;
2403+
}
2404+
2405+
if (prevout.n >= pegtx->vout.size()) {
2406+
return false;
2407+
}
2408+
CAmount amount = pegtx->vout[prevout.n].nValue;
2409+
// Check the transaction nout/value matches
2410+
if (claim_amount != amount) {
2411+
return false;
2412+
}
2413+
2414+
// Check that the witness program matches the p2ch on the p2sh-p2wsh transaction output
2415+
CScript tweaked_fedpegscript = calculate_contract(Params().GetConsensus().fedpegScript, claim_script);
2416+
CScript witness_output(GetScriptForWitness(tweaked_fedpegscript));
2417+
CScript expected_script(CScript() << OP_HASH160 << ToByteVector(CScriptID(witness_output)) << OP_EQUAL);
2418+
if (pegtx->vout[prevout.n].scriptPubKey != expected_script) {
2419+
return false;
2420+
}
2421+
2422+
return true;
2423+
}
2424+
23622425
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& prevout, bool check_depth) {
23632426

23642427
// Format on stack is as follows:
@@ -2409,45 +2472,27 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
24092472
return false;
24102473
}
24112474

2412-
// Get serialized transaction
2413-
Sidechain::Bitcoin::CTransactionRef pegtx;
2414-
try {
2415-
CDataStream pegtx_stream(stack[4], SER_NETWORK, PROTOCOL_VERSION);
2416-
pegtx_stream >> pegtx;
2417-
if (!pegtx_stream.empty()) {
2418-
return false;
2419-
}
2420-
} catch (std::exception& e) {
2421-
// Invalid encoding of transaction
2422-
return false;
2423-
}
2475+
uint256 block_hash;
2476+
uint256 tx_hash;
24242477

24252478
// Get txout proof
24262479
Sidechain::Bitcoin::CMerkleBlock merkle_block;
2427-
std::vector<uint256> txHashes;
2428-
std::vector<unsigned int> txIndices;
2429-
2430-
try {
2431-
CDataStream merkleBlockStream(stack[5], SER_NETWORK, PROTOCOL_VERSION);
2432-
merkleBlockStream >> merkle_block;
2433-
if (!merkleBlockStream.empty() || !CheckBitcoinProof(merkle_block.header.GetHash(), merkle_block.header.nBits)) {
2434-
return false;
2435-
}
2436-
if (merkle_block.txn.ExtractMatches(txHashes, txIndices) != merkle_block.header.hashMerkleRoot || txHashes.size() != 1) {
2437-
return false;
2438-
}
2439-
} catch (std::exception& e) {
2440-
// Invalid encoding of merkle block
2480+
if (!GetBlockAndTxFromMerkleBlock(block_hash, tx_hash, merkle_block, stack[5])) {
2481+
return false;
2482+
}
2483+
// TODO do this before to prevent DoS ?
2484+
if (!CheckBitcoinProof(block_hash, merkle_block.header.nBits)) {
24412485
return false;
24422486
}
24432487

2444-
// Check that transaction matches txid
2445-
if (pegtx->GetHash() != prevout.hash) {
2488+
// Get serialized transaction
2489+
Sidechain::Bitcoin::CTransactionRef pegtx;
2490+
if (!CheckPeginTx(stack[4], pegtx, prevout, value, claim_script)) {
24462491
return false;
24472492
}
24482493

24492494
// Check that the merkle proof corresponds to the txid
2450-
if (prevout.hash != txHashes[0]) {
2495+
if (prevout.hash != tx_hash) {
24512496
return false;
24522497
}
24532498

@@ -2461,22 +2506,9 @@ bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const COutPoint& p
24612506
return false;
24622507
}
24632508

2464-
// Check the transaction nout/value matches
2465-
if (prevout.n >= pegtx->vout.size() || value != pegtx->vout[prevout.n].nValue) {
2466-
return false;
2467-
}
2468-
2469-
// Check that the witness program matches the p2ch on the p2sh-p2wsh transaction output
2470-
CScript tweaked_fedpegscript = calculate_contract(Params().GetConsensus().fedpegScript, claim_script);
2471-
CScript witness_output(GetScriptForWitness(tweaked_fedpegscript));
2472-
CScript expected_script(CScript() << OP_HASH160 << ToByteVector(CScriptID(witness_output)) << OP_EQUAL);
2473-
if (pegtx->vout[prevout.n].scriptPubKey != expected_script) {
2474-
return false;
2475-
}
2476-
24772509
// Finally, validate peg-in via rpc call
24782510
if (check_depth && GetBoolArg("-validatepegin", DEFAULT_VALIDATE_PEGIN)) {
2479-
return IsConfirmedBitcoinBlock(merkle_block.header.GetHash(), Params().GetConsensus().pegin_min_depth);
2511+
return IsConfirmedBitcoinBlock(block_hash, Params().GetConsensus().pegin_min_depth);
24802512
}
24812513
return true;
24822514
}

0 commit comments

Comments
 (0)