From bd11097cec225805dfdb6d0c4c90aef72471dfd8 Mon Sep 17 00:00:00 2001 From: Gregory Sanders Date: Mon, 17 Jun 2019 16:35:52 -0400 Subject: [PATCH] Add fedpeg_program field in dynafed header --- src/consensus/tx_verify.cpp | 2 +- src/consensus/tx_verify.h | 2 +- src/dynafed.cpp | 5 +++-- src/pegins.cpp | 34 ++++++++++++++++++-------------- src/pegins.h | 7 ++++--- src/primitives/block.cpp | 1 + src/primitives/block.h | 13 ++++++++---- src/rpc/blockchain.cpp | 14 ++++++++++--- src/rpc/rawtransaction.cpp | 2 +- src/test/coins_tests.cpp | 4 ++-- src/test/pegin_witness_tests.cpp | 6 ++++-- src/txmempool.cpp | 4 ++-- src/validation.cpp | 8 ++++---- src/wallet/rpcwallet.cpp | 19 ++++++++++++------ 14 files changed, 75 insertions(+), 46 deletions(-) diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp index ca8eba22a4..fb08d6ab11 100644 --- a/src/consensus/tx_verify.cpp +++ b/src/consensus/tx_verify.cpp @@ -243,7 +243,7 @@ bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fChe } namespace Consensus { -bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set>& setPeginsSpent, std::vector *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector& fedpegscripts) +bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set>& setPeginsSpent, std::vector *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector>& fedpegscripts) { // are the actual inputs available? if (!inputs.HaveInputs(tx)) { diff --git a/src/consensus/tx_verify.h b/src/consensus/tx_verify.h index 9866f9521d..8f390c0bb2 100644 --- a/src/consensus/tx_verify.h +++ b/src/consensus/tx_verify.h @@ -31,7 +31,7 @@ namespace Consensus { * @param[out] fee_map Set to the transaction fee if successful. * Preconditions: tx.IsCoinBase() is false. */ -bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set>& setPeginsSpent, std::vector *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector& fedpegscripts); +bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set>& setPeginsSpent, std::vector *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector>& fedpegscripts); } // namespace Consensus /** Auxiliary functions for transaction validation (ideally should not be exposed) */ diff --git a/src/dynafed.cpp b/src/dynafed.cpp index a1da6b80cc..dc5c1fa539 100644 --- a/src/dynafed.cpp +++ b/src/dynafed.cpp @@ -60,9 +60,10 @@ DynaFedParamEntry ComputeNextBlockFullCurrentParameters(const CBlockIndex* pinde // We need to construct the "full" current parameters of pre-dynafed // consensus - // Convert signblockscript to P2WSH + // Convert signblockscript to P2WSH and fedpeg_program to P2SH-P2WSH CScript p2wsh_signblock_script = GetScriptForDestination(WitnessV0ScriptHash(p_epoch_start->proof.challenge)); - winning_proposal = DynaFedParamEntry(p2wsh_signblock_script, consensus.max_block_signature_size+consensus.signblockscript.size(), consensus.fedpegScript, consensus.first_extension_space); + CScript sh_wsh_fedpeg_program = GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(consensus.fedpegScript)))); + winning_proposal = DynaFedParamEntry(p2wsh_signblock_script, consensus.max_block_signature_size+consensus.signblockscript.size(), sh_wsh_fedpeg_program, consensus.fedpegScript, consensus.first_extension_space); } else { winning_proposal = p_epoch_start->dynafed_params.m_current; } diff --git a/src/pegins.cpp b/src/pegins.cpp index 1755d11ef9..272240c869 100644 --- a/src/pegins.cpp +++ b/src/pegins.cpp @@ -141,7 +141,7 @@ CScript calculate_contract(const CScript& federation_script, const CScript& scri } template -static bool CheckPeginTx(const std::vector& tx_data, T& pegtx, const COutPoint& prevout, const CAmount claim_amount, const CScript& claim_script, const std::vector& fedpegscripts) +static bool CheckPeginTx(const std::vector& tx_data, T& pegtx, const COutPoint& prevout, const CAmount claim_amount, const CScript& claim_script, const std::vector>& fedpegscripts) { try { CDataStream pegtx_stream(tx_data, SER_NETWORK, PROTOCOL_VERSION); @@ -171,12 +171,15 @@ static bool CheckPeginTx(const std::vector& tx_data, T& pegtx, co return false; } - // Check that the witness program matches the p2ch on the p2sh-p2wsh transaction output - // We support multiple scripts as a grace period for peg-in users - for (const auto& fedpegscript : fedpegscripts) { - CScript tweaked_fedpegscript = calculate_contract(fedpegscript, claim_script); - CScript witness_output(GetScriptForWitness(tweaked_fedpegscript)); - CScript expected_script(CScript() << OP_HASH160 << ToByteVector(ScriptHash(CScriptID(witness_output))) << OP_EQUAL); + // Check that the witness program matches the p2ch on the (p2sh-)p2wsh + // transaction output. We support multiple scripts as a grace period for peg-in users + for (const auto& scripts : fedpegscripts) { + CScript tweaked_fedpegscript = calculate_contract(scripts.second, claim_script); + // TODO: Remove script/standard.h dep for GetScriptFor* + CScript expected_script(GetScriptForWitness(tweaked_fedpegscript)); + if (scripts.first.IsPayToScriptHash()) { + expected_script = GetScriptForDestination(ScriptHash(expected_script)); + } if (pegtx->vout[prevout.n].scriptPubKey == expected_script) { return true; } @@ -228,7 +231,7 @@ bool CheckParentProofOfWork(uint256 hash, unsigned int nBits, const Consensus::P return true; } -bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth) { +bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector>& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth) { // 0) Return false if !consensus.has_parent_chain if (!Params().GetConsensus().has_parent_chain) { err_msg = "Parent chain is not enabled on this network."; @@ -447,11 +450,11 @@ bool MatchLiquidWatchman(const CScript& script) return (it == script.end()); } -std::vector GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation) +std::vector> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation) { assert(pblockindex); - std::vector fedpegscripts; + std::vector> fedpegscripts; const int32_t epoch_length = params.dynamic_epoch_length; const int32_t epoch_age = pblockindex->nHeight % epoch_length; @@ -460,7 +463,8 @@ std::vector GetValidFedpegScripts(const CBlockIndex* pblockindex, const // In mempool and general "enforced next block" RPC we need to look ahead one block // to see if we're on a boundary. If so, put that epoch's fedpegscript in place if (nextblock_validation && epoch_age == epoch_length - 1) { - fedpegscripts.push_back(ComputeNextBlockFullCurrentParameters(pblockindex, params).m_fedpegscript); + DynaFedParamEntry next_param = ComputeNextBlockFullCurrentParameters(pblockindex, params); + fedpegscripts.push_back(std::make_pair(next_param.m_fedpeg_program, next_param.m_fedpegscript)); } // Next we walk backwards up to two epoch start blocks @@ -469,17 +473,17 @@ std::vector GetValidFedpegScripts(const CBlockIndex* pblockindex, const if (p_current_epoch_start) { if (!p_current_epoch_start->dynafed_params.IsNull()) { - fedpegscripts.push_back(p_current_epoch_start->dynafed_params.m_current.m_fedpegscript); + fedpegscripts.push_back(std::make_pair(p_current_epoch_start->dynafed_params.m_current.m_fedpeg_program, p_current_epoch_start->dynafed_params.m_current.m_fedpegscript)); } else { - fedpegscripts.push_back(params.fedpegScript); + fedpegscripts.push_back(std::make_pair(GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(params.fedpegScript)))), params.fedpegScript)); } } if (p_prev_epoch_start) { if (!p_prev_epoch_start->dynafed_params.IsNull()) { - fedpegscripts.push_back(p_prev_epoch_start->dynafed_params.m_current.m_fedpegscript); + fedpegscripts.push_back(std::make_pair(p_prev_epoch_start->dynafed_params.m_current.m_fedpeg_program, p_prev_epoch_start->dynafed_params.m_current.m_fedpegscript)); } else { - fedpegscripts.push_back(params.fedpegScript); + fedpegscripts.push_back(std::make_pair(GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(params.fedpegScript)))), params.fedpegScript)); } } diff --git a/src/pegins.h b/src/pegins.h index 07d70e5529..e3e2f80082 100644 --- a/src/pegins.h +++ b/src/pegins.h @@ -19,7 +19,7 @@ bool GetAmountFromParentChainPegin(CAmount& amount, const CTransaction& txBTC, u /** Check whether a parent chain block hash satisfies the proof-of-work requirement specified by nBits */ bool CheckParentProofOfWork(uint256 hash, unsigned int nBits, const Consensus::Params&); /** Checks pegin witness for validity */ -bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth); +bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector>& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth); // Constructs unblinded output to be used in amount and scriptpubkey checks during pegin CTxOut GetPeginOutputFromWitness(const CScriptWitness& pegin_witness); @@ -34,7 +34,8 @@ bool MatchLiquidWatchman(const CScript& script); /** Get full fedpegscripts from two previous epoch starts based on given index * nextblock_validation is false when doing block validation, true for mempool - * or "lookahead" purposes. Newest epochs first. */ -std::vector GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation); + * or "lookahead" purposes. Newest epochs first. The first returned element is the + * scriptPubKey for the script, the second is the witnessScript. */ +std::vector> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation); #endif // BITCOIN_PEGINS_H diff --git a/src/primitives/block.cpp b/src/primitives/block.cpp index ce53055925..2b72449740 100644 --- a/src/primitives/block.cpp +++ b/src/primitives/block.cpp @@ -50,6 +50,7 @@ uint256 DynaFedParamEntry::CalculateRoot() const std::vector leaves; leaves.push_back(SerializeHash(m_signblockscript, SER_GETHASH, 0)); leaves.push_back(SerializeHash(m_signblock_witness_limit, SER_GETHASH, 0)); + leaves.push_back(SerializeHash(m_fedpeg_program, SER_GETHASH, 0)); leaves.push_back(SerializeHash(m_fedpegscript, SER_GETHASH, 0)); leaves.push_back(SerializeHash(m_extension_space, SER_GETHASH, 0)); return ComputeFastMerkleRoot(leaves); diff --git a/src/primitives/block.h b/src/primitives/block.h index 47c399855b..6c3b1a99c3 100644 --- a/src/primitives/block.h +++ b/src/primitives/block.h @@ -61,7 +61,8 @@ public: unsigned char m_serialize_type; // Determines how it is serialized, defaults to null CScript m_signblockscript; uint32_t m_signblock_witness_limit; // Max block signature witness serialized size - CScript m_fedpegscript; + CScript m_fedpeg_program; // The "scriptPubKey" of the fedpegscript + CScript m_fedpegscript; // The witnessScript for witness v0 or undefined otherwise. // No consensus meaning to the particular bytes, currently we interpret as PAK keys, details in pak.h std::vector> m_extension_space; @@ -69,7 +70,7 @@ public: // arguments are given DynaFedParamEntry() { m_signblock_witness_limit = 0; m_serialize_type = 0; }; DynaFedParamEntry(const CScript& signblockscript_in, const uint32_t sbs_wit_limit_in) : m_signblockscript(signblockscript_in), m_signblock_witness_limit(sbs_wit_limit_in) { m_serialize_type = 1; }; - DynaFedParamEntry(const CScript& signblockscript_in, const uint32_t sbs_wit_limit_in, const CScript& fedpegscript_in, const std::vector> extension_space_in) : m_signblockscript(signblockscript_in), m_signblock_witness_limit(sbs_wit_limit_in), m_fedpegscript(fedpegscript_in), m_extension_space(extension_space_in) { m_serialize_type = 2; }; + DynaFedParamEntry(const CScript& signblockscript_in, const uint32_t sbs_wit_limit_in, const CScript& fedpeg_program_in, const CScript& fedpegscript_in, const std::vector> extension_space_in) : m_signblockscript(signblockscript_in), m_signblock_witness_limit(sbs_wit_limit_in), m_fedpeg_program(fedpeg_program_in), m_fedpegscript(fedpegscript_in), m_extension_space(extension_space_in) { m_serialize_type = 2; }; ADD_SERIALIZE_METHODS; @@ -87,6 +88,7 @@ public: case 2: READWRITE(m_signblockscript); READWRITE(m_signblock_witness_limit); + READWRITE(m_fedpeg_program); READWRITE(m_fedpegscript); READWRITE(m_extension_space); break; @@ -102,6 +104,7 @@ public: return m_serialize_type == 0 && m_signblockscript.empty() && m_signblock_witness_limit == 0 && + m_fedpeg_program.empty() && m_fedpegscript.empty() && m_extension_space.empty(); @@ -110,9 +113,10 @@ public: void SetNull() { m_serialize_type = 0; - m_signblockscript = CScript(); + m_signblockscript.clear(); m_signblock_witness_limit = 0; - m_fedpegscript = CScript(); + m_fedpeg_program.clear(); + m_fedpegscript.clear(); m_extension_space.clear(); } @@ -121,6 +125,7 @@ public: return m_serialize_type == other.m_serialize_type && m_signblockscript == other.m_signblockscript && m_signblock_witness_limit == other.m_signblock_witness_limit && + m_fedpeg_program == other.m_fedpeg_program && m_fedpegscript == other.m_fedpegscript && m_extension_space == other.m_extension_space; } diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp index 0d644181fb..00fb218820 100644 --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -2509,6 +2509,11 @@ UniValue getsidechaininfo(const JSONRPCRequest& request) " \"xxxx\", (string) Hex-encoded active fedpegscript\n" " ...\n" " ]\n" + " \"current_fedpeg_programs\": (array) The currently-enforced fedpegscript scriptPubKeys in hex. Prior to a transition this may be P2SH scriptpubkey, otherwise it will be a native segwit script. Results are paired in-order with current_fedpegscripts.\n" + " [\n" + " \"xxxx\", (string) Hex-encoded active fedpegscriptscriptPubKeys\n" + " ...\n" + " ]\n" " \"pegged_asset\" : \"xxxx\", (string) Pegged asset type in hex\n" " \"min_peg_diff\" : \"xxxx\", (string) The minimum difficulty parent chain header target. Peg-in headers that have less work will be rejected as an anti-Dos measure.\n" " \"parent_blockhash\" : \"xxxx\", (string) The parent genesis blockhash as source of pegged-in funds.\n" @@ -2534,11 +2539,14 @@ UniValue getsidechaininfo(const JSONRPCRequest& request) UniValue obj(UniValue::VOBJ); obj.pushKV("fedpegscript", HexStr(consensus.fedpegScript.begin(), consensus.fedpegScript.end())); // We use mempool_validation as true to show what is enforced for *next* block - std::vector fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), consensus, true /* nextblock_validation */); + std::vector> fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), consensus, true /* nextblock_validation */); + UniValue fedpeg_prog_entries(UniValue::VARR); UniValue fedpeg_entries(UniValue::VARR); - for (const auto& script : fedpegscripts) { - fedpeg_entries.push_back(HexStr(script)); + for (const auto& scripts : fedpegscripts) { + fedpeg_prog_entries.push_back(HexStr(scripts.first)); + fedpeg_entries.push_back(HexStr(scripts.second)); } + obj.pushKV("current_fedpeg_programs", fedpeg_prog_entries); obj.pushKV("current_fedpegscripts", fedpeg_entries); obj.pushKV("pegged_asset", consensus.pegged_asset.GetHex()); obj.pushKV("min_peg_diff", consensus.parentChainPowLimit.GetHex()); diff --git a/src/rpc/rawtransaction.cpp b/src/rpc/rawtransaction.cpp index bea157727c..fd996193b4 100644 --- a/src/rpc/rawtransaction.cpp +++ b/src/rpc/rawtransaction.cpp @@ -988,7 +988,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con // Script verification errors UniValue vErrors(UniValue::VARR); - const std::vector fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */); + const auto& fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */); // ELEMENTS: // Track an immature peg-in that's otherwise valid, give warning diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 7633789351..b5be8e04bf 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -17,7 +17,7 @@ #include -int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector& fedpegscripts); +int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector>& fedpegscripts); void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, CTxUndo &txundo, int nHeight); namespace @@ -410,7 +410,7 @@ BOOST_AUTO_TEST_CASE(updatecoins_simulation_test) if (!tx.IsCoinBase()) { const COutPoint &out = tx.vin[0].prevout; Coin coin = undo.vprevout[0]; - std::vector fedpegscripts; + std::vector> fedpegscripts; ApplyTxInUndo(std::move(coin), *(stack.back()), out, tx.vin[0], CScriptWitness(), fedpegscripts); } // Store as a candidate for reconnection diff --git a/src/test/pegin_witness_tests.cpp b/src/test/pegin_witness_tests.cpp index bc9de95088..461b77e43e 100644 --- a/src/test/pegin_witness_tests.cpp +++ b/src/test/pegin_witness_tests.cpp @@ -54,9 +54,11 @@ BOOST_AUTO_TEST_CASE(witness_valid) std::vector fedpegscript_bytes = ParseHex(fedpegscript_str); CScript fedpegscript(fedpegscript_bytes.begin(), fedpegscript_bytes.end()); - std::vector fedpegscripts; + // Test sample was generated as "legacy" with p2sh-p2wsh fedpegscript + CScript fedpeg_program(GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(fedpegscript))))); + std::vector> fedpegscripts; // TODO test with additional scripts - fedpegscripts.push_back(fedpegscript); + fedpegscripts.push_back(std::make_pair(fedpeg_program, fedpegscript)); bool valid = IsValidPeginWitness(witness, fedpegscripts, prevout, err, false); BOOST_CHECK(err == ""); diff --git a/src/txmempool.cpp b/src/txmempool.cpp index 5969b68e27..a4c5f1dee4 100644 --- a/src/txmempool.cpp +++ b/src/txmempool.cpp @@ -591,7 +591,7 @@ void CTxMemPool::removeForBlock(const std::vector& vtx, unsigne continue; } - std::vector fedpegscripts = GetValidFedpegScripts(p_block_index_new, chainparams.GetConsensus(), true /* nextblock_validation */); + const auto& fedpegscripts = GetValidFedpegScripts(p_block_index_new, chainparams.GetConsensus(), true /* nextblock_validation */); for (size_t nIn = 0; nIn < tx.vin.size(); nIn++) { const CTxIn& in = tx.vin[nIn]; std::string err; @@ -638,7 +638,7 @@ static void CheckInputsAndUpdateCoins(const CTxMemPoolEntry& entry, CCoinsViewCa CValidationState state; CAmountMap fee_map; std::set > setPeginsSpent; - std::vector fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */); + const auto& fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */); bool fCheckResult = tx.IsCoinBase() || Consensus::CheckTxInputs(tx, state, mempoolDuplicate, spendheight, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts); assert(fCheckResult); UpdateCoins(tx, mempoolDuplicate, 1000000); diff --git a/src/validation.cpp b/src/validation.cpp index 7aff449575..8b3e7cbf4a 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -700,7 +700,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool } // Used when checking peg-ins - std::vector fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), chainparams.GetConsensus(), true /* nextblock_validation */); + std::vector> fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), chainparams.GetConsensus(), true /* nextblock_validation */); // do all inputs exist? for (unsigned int i = 0; i < tx.vin.size(); i++) { @@ -1634,7 +1634,7 @@ static bool AbortNode(CValidationState& state, const std::string& strMessage, co * @param out The out point that corresponds to the tx input. * @return A DisconnectResult as an int */ -int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector& fedpegscripts) +int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector>& fedpegscripts) { bool fClean = true; @@ -1728,7 +1728,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI } // restore inputs - const std::vector fedpegscripts = GetValidFedpegScripts(pindex, Params().GetConsensus(), false /* nextblock_validation */); + const auto& fedpegscripts = GetValidFedpegScripts(pindex, Params().GetConsensus(), false /* nextblock_validation */); if (i > 0) { // not coinbases CTxUndo &txundo = blockUndo.vtxundo[i-1]; if (txundo.vprevout.size() != tx.vin.size()) { @@ -2145,7 +2145,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl std::set> setPeginsSpentDummy; // Used when checking peg-ins - std::vector fedpegscripts = GetValidFedpegScripts(pindex, chainparams.GetConsensus(), false /* nextblock_validation */); + const auto& fedpegscripts = GetValidFedpegScripts(pindex, chainparams.GetConsensus(), false /* nextblock_validation */); for (unsigned int i = 0; i < block.vtx.size(); i++) { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 7eb3ae9408..34c66c0c69 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -4857,8 +4857,12 @@ UniValue getpeginaddress(const JSONRPCRequest& request) pwallet->AddCScript(dest_script); // Get P2CH deposit address on mainchain from most recent fedpegscript. - const std::vector& fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */); - CTxDestination mainchain_dest(ScriptHash(GetScriptForWitness(calculate_contract(fedpegscripts.front(), dest_script)))); + const auto& fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */); + CTxDestination mainchain_dest(WitnessV0ScriptHash(calculate_contract(fedpegscripts.front().second, dest_script))); + // P2SH-wrapped is the only valid choice for non-dynafed chains + if (!IsDynaFedEnabled(chainActive.Tip(), Params().GetConsensus())) { + mainchain_dest = ScriptHash(GetScriptForDestination(mainchain_dest)); + } UniValue ret(UniValue::VOBJ); @@ -5386,10 +5390,13 @@ extern UniValue signrawtransaction(const JSONRPCRequest& request); extern UniValue sendrawtransaction(const JSONRPCRequest& request); template -unsigned int GetPeginTxnOutputIndex(const T_tx& txn, const CScript& witnessProgram, const std::vector& fedpegscripts) +unsigned int GetPeginTxnOutputIndex(const T_tx& txn, const CScript& witnessProgram, const std::vector>& fedpegscripts) { - for (auto const& fedpegscript : fedpegscripts) { - CScript mainchain_script = GetScriptForDestination(ScriptHash(GetScriptForWitness(calculate_contract(fedpegscript, witnessProgram)))); + for (const auto & scripts : fedpegscripts) { + CScript mainchain_script = GetScriptForWitness(calculate_contract(scripts.second, witnessProgram)); + if (scripts.first.IsPayToScriptHash()) { + mainchain_script = GetScriptForDestination(ScriptHash(mainchain_script)); + } for (unsigned int nOut = 0; nOut < txn.vout.size(); nOut++) if (txn.vout[nOut].scriptPubKey == mainchain_script) { return nOut; @@ -5467,7 +5474,7 @@ static UniValue createrawpegin(const JSONRPCRequest& request, T_tx_ref& txBTCRef CScript witness_script; unsigned int nOut = txBTC.vout.size(); - const std::vector fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */); + const auto fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), Params().GetConsensus(), true /* nextblock_validation */); if (request.params.size() > 2) { const std::string claim_script = request.params[2].get_str(); if (!IsHex(claim_script)) {