Proof follows the OP_RETURN in multiple pushes:
| 83 | // Proof follows the OP_RETURN <genesis_block_hash> <destination_scriptpubkey> |
| 84 | // in multiple pushes: <full_pubkey> <proof> |
| 85 | bool ScriptHasValidPAKProof(const CScript& script, const uint256& genesis_hash, const CPAKList& paklist) |
| 86 | { |
| 87 | assert(script.IsPegoutScript(genesis_hash)); |
| 88 | |
| 89 | if (paklist.IsReject()) { |
| 90 | return false; |
| 91 | } |
| 92 | |
| 93 | CScript::const_iterator pc = script.begin(); |
| 94 | std::vector<unsigned char> data; |
| 95 | opcodetype opcode; |
| 96 | |
| 97 | script.GetOp(pc, opcode, data); |
| 98 | script.GetOp(pc, opcode, data); |
| 99 | script.GetOp(pc, opcode, data); |
| 100 | |
| 101 | CScript chain_dest(data.begin(), data.end()); |
| 102 | |
| 103 | // Grab pubkey hash within the extracted sub-script |
| 104 | std::vector<unsigned char> extracted_pubkey_hash; |
| 105 | |
| 106 | // Get full pubkey |
| 107 | if (!script.GetOp(pc, opcode, data) || data.size() != 33 || opcode > OP_PUSHDATA4) { |
| 108 | return false; |
| 109 | } |
| 110 | CPubKey full_pubkey(data.begin(), data.end()); |
| 111 | |
| 112 | // Accept any standard single-key type |
| 113 | if (chain_dest.IsPayToPubkeyHash()) { |
| 114 | extracted_pubkey_hash = std::vector<unsigned char>(chain_dest.begin()+3, chain_dest.begin()+23); |
| 115 | if (full_pubkey.GetID() != uint160(extracted_pubkey_hash)) { |
| 116 | return false; |
| 117 | } |
| 118 | } else if (chain_dest.IsPayToWitnessPubkeyHash()) { |
| 119 | extracted_pubkey_hash = std::vector<unsigned char>(chain_dest.begin()+2, chain_dest.begin()+22); |
| 120 | if (full_pubkey.GetID() != uint160(extracted_pubkey_hash)) { |
| 121 | return false; |
| 122 | } |
| 123 | } else if (chain_dest.IsPayToScriptHash()) { |
| 124 | // Take full_pubkey, and hash it to match against chain_dest |
| 125 | CScript p2wpkh(CScript() << OP_0 << ToByteVector(full_pubkey.GetID())); |
| 126 | unsigned char h160[20]; |
| 127 | CHash160().Write(p2wpkh).Finalize(h160); |
| 128 | if (memcmp(h160, chain_dest.data()+2, sizeof(h160))) { |
| 129 | return false; |
| 130 | } |
| 131 | } else { |
| 132 | return false; |
| 133 | } |
| 134 | |
| 135 | // Parse pubkey |
| 136 | secp256k1_pubkey pubkey; |
| 137 | if (secp256k1_ec_pubkey_parse(secp256k1_ctx_pak, &pubkey, &data[0], data.size()) != 1) { |
| 138 | return false; |
| 139 | } |
| 140 | |
| 141 | if (!script.GetOp(pc, opcode, data) || opcode > OP_PUSHDATA4 || data.size() == 0) { |
| 142 | return false; |
no test coverage detected