Add fedpeg_program field in dynafed header

This commit is contained in:
Gregory Sanders 2019-06-17 16:35:52 -04:00
parent 4ad2b8018d
commit bd11097cec
14 changed files with 75 additions and 46 deletions

View file

@ -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<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<CScript>& fedpegscripts)
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<std::pair<CScript, CScript>>& fedpegscripts)
{
// are the actual inputs available?
if (!inputs.HaveInputs(tx)) {

View file

@ -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<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<CScript>& fedpegscripts);
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmountMap& fee_map, std::set<std::pair<uint256, COutPoint>>& setPeginsSpent, std::vector<CCheck*> *pvChecks, const bool cacheStore, bool fScriptChecks, const std::vector<std::pair<CScript, CScript>>& fedpegscripts);
} // namespace Consensus
/** Auxiliary functions for transaction validation (ideally should not be exposed) */

View file

@ -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;
}

View file

@ -141,7 +141,7 @@ CScript calculate_contract(const CScript& federation_script, const CScript& scri
}
template<typename T>
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<CScript>& fedpegscripts)
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)
{
try {
CDataStream pegtx_stream(tx_data, SER_NETWORK, PROTOCOL_VERSION);
@ -171,12 +171,15 @@ static bool CheckPeginTx(const std::vector<unsigned char>& 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<CScript>& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth) {
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector<std::pair<CScript, CScript>>& 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<CScript> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation)
std::vector<std::pair<CScript, CScript>> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation)
{
assert(pblockindex);
std::vector<CScript> fedpegscripts;
std::vector<std::pair<CScript, CScript>> 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<CScript> 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<CScript> 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));
}
}

View file

@ -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<CScript>& fedpegscripts, const COutPoint& prevout, std::string& err_msg, bool check_depth);
bool IsValidPeginWitness(const CScriptWitness& pegin_witness, const std::vector<std::pair<CScript, CScript>>& 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<CScript> 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<std::pair<CScript, CScript>> GetValidFedpegScripts(const CBlockIndex* pblockindex, const Consensus::Params& params, bool nextblock_validation);
#endif // BITCOIN_PEGINS_H

View file

@ -50,6 +50,7 @@ uint256 DynaFedParamEntry::CalculateRoot() const
std::vector<uint256> 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);

View file

@ -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<std::vector<unsigned char>> 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<std::vector<unsigned char>> 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<std::vector<unsigned char>> 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;
}

View file

@ -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<CScript> fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), consensus, true /* nextblock_validation */);
std::vector<std::pair<CScript, CScript>> 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());

View file

@ -988,7 +988,7 @@ UniValue SignTransaction(interfaces::Chain& chain, CMutableTransaction& mtx, con
// Script verification errors
UniValue vErrors(UniValue::VARR);
const std::vector<CScript> 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

View file

@ -17,7 +17,7 @@
#include <boost/test/unit_test.hpp>
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector<CScript>& fedpegscripts);
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector<std::pair<CScript, CScript>>& 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<CScript> fedpegscripts;
std::vector<std::pair<CScript, CScript>> fedpegscripts;
ApplyTxInUndo(std::move(coin), *(stack.back()), out, tx.vin[0], CScriptWitness(), fedpegscripts);
}
// Store as a candidate for reconnection

View file

@ -54,9 +54,11 @@ BOOST_AUTO_TEST_CASE(witness_valid)
std::vector<unsigned char> fedpegscript_bytes = ParseHex(fedpegscript_str);
CScript fedpegscript(fedpegscript_bytes.begin(), fedpegscript_bytes.end());
std::vector<CScript> fedpegscripts;
// Test sample was generated as "legacy" with p2sh-p2wsh fedpegscript
CScript fedpeg_program(GetScriptForDestination(ScriptHash(GetScriptForDestination(WitnessV0ScriptHash(fedpegscript)))));
std::vector<std::pair<CScript, CScript>> 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 == "");

View file

@ -591,7 +591,7 @@ void CTxMemPool::removeForBlock(const std::vector<CTransactionRef>& vtx, unsigne
continue;
}
std::vector<CScript> 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<std::pair<uint256, COutPoint> > setPeginsSpent;
std::vector<CScript> 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);

View file

@ -700,7 +700,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool
}
// Used when checking peg-ins
std::vector<CScript> fedpegscripts = GetValidFedpegScripts(chainActive.Tip(), chainparams.GetConsensus(), true /* nextblock_validation */);
std::vector<std::pair<CScript, CScript>> 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<CScript>& fedpegscripts)
int ApplyTxInUndo(Coin&& undo, CCoinsViewCache& view, const COutPoint& out, const CTxIn& txin, const CScriptWitness& pegin_witness, const std::vector<std::pair<CScript, CScript>>& fedpegscripts)
{
bool fClean = true;
@ -1728,7 +1728,7 @@ DisconnectResult CChainState::DisconnectBlock(const CBlock& block, const CBlockI
}
// restore inputs
const std::vector<CScript> 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<std::pair<uint256, COutPoint>> setPeginsSpentDummy;
// Used when checking peg-ins
std::vector<CScript> 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++)
{

View file

@ -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<CScript>& 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<typename T_tx>
unsigned int GetPeginTxnOutputIndex(const T_tx& txn, const CScript& witnessProgram, const std::vector<CScript>& fedpegscripts)
unsigned int GetPeginTxnOutputIndex(const T_tx& txn, const CScript& witnessProgram, const std::vector<std::pair<CScript, CScript>>& 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<CScript> 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)) {