| 144 | |
| 145 | template<typename T> |
| 146 | static bool CheckPeginTx(const std::vector<unsigned char>& tx_data, T& pegtx, const COutPoint& prevout, const CAmount claim_amount, const CScript& claim_script, const std::vector<std::pair<CScript, CScript>>& fedpegscripts) |
| 147 | { |
| 148 | try { |
| 149 | CDataStream pegtx_stream(tx_data, SER_NETWORK, PROTOCOL_VERSION); |
| 150 | pegtx_stream >> pegtx; |
| 151 | if (!pegtx_stream.empty()) { |
| 152 | return false; |
| 153 | } |
| 154 | } catch (std::exception&) { |
| 155 | // Invalid encoding of transaction |
| 156 | return false; |
| 157 | } |
| 158 | |
| 159 | // Check that transaction matches txid |
| 160 | if (pegtx->GetHash() != prevout.hash) { |
| 161 | return false; |
| 162 | } |
| 163 | |
| 164 | if (prevout.n >= pegtx->vout.size()) { |
| 165 | return false; |
| 166 | } |
| 167 | CAmount amount = 0; |
| 168 | if (!GetAmountFromParentChainPegin(amount, *pegtx, prevout.n)) { |
| 169 | return false; |
| 170 | } |
| 171 | // Check the transaction nout/value matches |
| 172 | if (claim_amount != amount) { |
| 173 | return false; |
| 174 | } |
| 175 | |
| 176 | // Check that the witness program matches the p2ch on the (p2sh-)p2wsh |
| 177 | // transaction output. We support multiple scripts as a grace period for peg-in users |
| 178 | for (const auto& scripts : fedpegscripts) { |
| 179 | int fedpeg_version = 0; |
| 180 | std::vector<unsigned char> fedpeg_program; |
| 181 | scripts.first.IsWitnessProgram(fedpeg_version, fedpeg_program); |
| 182 | // We immediately return true if any fedpegscripts are unencumbered |
| 183 | // by currently-known parent chain segwit versions. |
| 184 | // TODO: Refactor for future versionbits deployment of parent-segwit version |
| 185 | if (fedpeg_version > 0) { |
| 186 | return true; |
| 187 | } |
| 188 | CScript tweaked_fedpegscript = calculate_contract(scripts.second, claim_script); |
| 189 | // TODO: Remove script/standard.h dep for GetScriptFor* |
| 190 | CScript expected_script(GetScriptForDestination(WitnessV0ScriptHash(tweaked_fedpegscript))); |
| 191 | if (scripts.first.IsPayToScriptHash()) { |
| 192 | expected_script = GetScriptForDestination(ScriptHash(expected_script)); |
| 193 | } |
| 194 | if (pegtx->vout[prevout.n].scriptPubKey == expected_script) { |
| 195 | return true; |
| 196 | } |
| 197 | } |
| 198 | return false; |
| 199 | } |
| 200 | |
| 201 | template<typename T> |
| 202 | static bool GetBlockAndTxFromMerkleBlock(uint256& block_hash, uint256& tx_hash, unsigned int& tx_index, T& merkle_block, const std::vector<unsigned char>& merkle_block_raw) |
no test coverage detected