Skip to content

Fix: Issueasset tx with blind parameter false is not accepted after t… #1444

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions src/confidential_validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ ScriptError QueueCheck(std::vector<CCheck*>* queue, CCheck* check) {
// Helper function for VerifyAmount(), not exported
static bool VerifyIssuanceAmount(secp256k1_pedersen_commitment& value_commit, secp256k1_generator& asset_gen,
const CAsset& asset, const CConfidentialValue& value, const std::vector<unsigned char>& rangeproof,
std::vector<CCheck*>* checks, const bool store_result)
std::vector<CCheck*>* checks, const bool store_result, const Consensus::Params& consensus_params)
{
// This is used to add in the explicit values
unsigned char explicit_blinds[32];
Expand All @@ -102,7 +102,7 @@ static bool VerifyIssuanceAmount(secp256k1_pedersen_commitment& value_commit, se

// Build value commitment
if (value.IsExplicit()) {
if (!MoneyRange(value.GetAmount()) || value.GetAmount() == 0) {
if ((asset == consensus_params.pegged_asset && !MoneyRange(value.GetAmount())) || value.GetAmount() <= 0) {
return false;
}
if (!rangeproof.empty()) {
Expand Down Expand Up @@ -131,7 +131,7 @@ static bool VerifyIssuanceAmount(secp256k1_pedersen_commitment& value_commit, se
return true;
}

bool VerifyAmounts(const std::vector<CTxOut>& inputs, const CTransaction& tx, std::vector<CCheck*>* checks, const bool store_result) {
bool VerifyAmounts(const std::vector<CTxOut>& inputs, const CTransaction& tx, const Consensus::Params& consensus_params, std::vector<CCheck*>* checks, const bool store_result) {
assert(!tx.IsCoinBase());
assert(inputs.size() == tx.vin.size());

Expand Down Expand Up @@ -257,7 +257,7 @@ bool VerifyAmounts(const std::vector<CTxOut>& inputs, const CTransaction& tx, st
if (i >= tx.witness.vtxinwit.size()) {
return false;
}
if (!VerifyIssuanceAmount(commit, gen, assetID, issuance.nAmount, tx.witness.vtxinwit[i].vchIssuanceAmountRangeproof, checks, store_result)) {
if (!VerifyIssuanceAmount(commit, gen, assetID, issuance.nAmount, tx.witness.vtxinwit[i].vchIssuanceAmountRangeproof, checks, store_result, consensus_params)) {
return false;
}
target_generators.push_back(gen);
Expand All @@ -283,7 +283,7 @@ bool VerifyAmounts(const std::vector<CTxOut>& inputs, const CTransaction& tx, st
if (i >= tx.witness.vtxinwit.size()) {
return false;
}
if (!VerifyIssuanceAmount(commit, gen, assetTokenID, issuance.nInflationKeys, tx.witness.vtxinwit[i].vchInflationKeysRangeproof, checks, store_result)) {
if (!VerifyIssuanceAmount(commit, gen, assetTokenID, issuance.nInflationKeys, tx.witness.vtxinwit[i].vchInflationKeysRangeproof, checks, store_result, consensus_params)) {
return false;
}
target_generators.push_back(gen);
Expand Down
3 changes: 2 additions & 1 deletion src/confidential_validation.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define BITCOIN_CONFIDENTIAL_VALIDATION_H

#include <consensus/amount.h>
#include <consensus/params.h>
#include <asset.h>
#include <coins.h>
#include <primitives/confidential.h>
Expand Down Expand Up @@ -89,7 +90,7 @@ class CSurjectionCheck : public CCheck

ScriptError QueueCheck(std::vector<CCheck*>* queue, CCheck* check);

bool VerifyAmounts(const std::vector<CTxOut>& inputs, const CTransaction& tx, std::vector<CCheck*>* pvChecks, const bool cacheStore);
bool VerifyAmounts(const std::vector<CTxOut>& inputs, const CTransaction& tx, const Consensus::Params& consensusParams, std::vector<CCheck*>* pvChecks, const bool cacheStore);

bool VerifyCoinbaseAmount(const CTransaction& tx, const CAmountMap& mapFees);

Expand Down
4 changes: 2 additions & 2 deletions src/consensus/tx_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& i
return nSigOps;
}

bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& 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)
bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, const Consensus::Params& consensusParams, 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)) {
Expand Down Expand Up @@ -250,7 +250,7 @@ bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state,
}

// Verify that amounts add up.
if (fScriptChecks && !VerifyAmounts(spent_inputs, tx, pvChecks, cacheStore)) {
if (fScriptChecks && !VerifyAmounts(spent_inputs, tx, consensusParams, pvChecks, cacheStore)) {
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-ne-out", "value in != value out");
}
fee_map += GetFeeMap(tx);
Expand Down
2 changes: 1 addition & 1 deletion src/consensus/tx_verify.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ namespace Consensus {
* @param[out] fee_map Set to the transaction fee if successful.
* Preconditions: tx.IsCoinBase() is false.
*/
[[nodiscard] ]bool CheckTxInputs(const CTransaction& tx, TxValidationState& 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);
[[nodiscard] ]bool CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, const Consensus::Params& consensusParams, 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) */
Expand Down
46 changes: 24 additions & 22 deletions src/test/blind_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
CKey key2;
CKey keyDummy;

Consensus::Params consensusParams = Consensus::Params();

// Any asset id will do
CAsset bitcoinID(GetRandHash());
CAsset otherID(GetRandHash());
Expand Down Expand Up @@ -72,32 +74,32 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
tx3.vout.push_back(CTxOut(bitcoinID, 100, CScript() << OP_TRUE));
// Fee outputs are blank scriptpubkeys, and unblinded value/asset
tx3.vout.push_back(CTxOut(bitcoinID, 22, CScript()));
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));

// Malleate the output and check for correct handling of bad commitments
// These will fail IsValid checks
std::vector<unsigned char> asset_copy(tx3.vout[0].nAsset.vchCommitment);
std::vector<unsigned char> value_copy(tx3.vout[0].nValue.vchCommitment);
tx3.vout[0].nAsset.vchCommitment[0] = 122;
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));
tx3.vout[0].nAsset.vchCommitment = asset_copy;
tx3.vout[0].nValue.vchCommitment[0] = 122;
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));
tx3.vout[0].nValue.vchCommitment = value_copy;

// Make sure null values are handled correctly
tx3.vout[0].nAsset.SetNull();
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));
tx3.vout[0].nAsset.vchCommitment = asset_copy;
tx3.vout[0].nValue.SetNull();
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));
tx3.vout[0].nValue.vchCommitment = value_copy;

// Bad nonce values will result in failure to deserialize
tx3.vout[0].nNonce.SetNull();
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));
tx3.vout[0].nNonce.vchCommitment = tx3.vout[0].nValue.vchCommitment;
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));

// Try to blind with a single non-fee output, which fails as its blinding factor ends up being zero.
std::vector<uint256> input_blinds;
Expand Down Expand Up @@ -125,7 +127,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
BOOST_CHECK(BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, tx3) == 2);
BOOST_CHECK(!tx3.vout[0].nValue.IsExplicit());
BOOST_CHECK(!tx3.vout[2].nValue.IsExplicit());
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));

CAmount unblinded_amount;
BOOST_CHECK(UnblindConfidentialPair(key2, tx3.vout[0].nValue, tx3.vout[0].nAsset, tx3.vout[0].nNonce, op_true, tx3.witness.vtxoutwit[0].vchRangeproof, unblinded_amount, blind3, unblinded_id, asset_blind) == 0);
Expand All @@ -144,7 +146,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
blind_ozz = tx3.vout[0];

tx3.vout[1].nValue = CConfidentialValue(tx3.vout[1].nValue.GetAmount() - 1);
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx3), consensusParams, nullptr, false));
}

{
Expand All @@ -162,7 +164,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
tx4.vout.push_back(CTxOut(bitcoinID, 30, CScript() << OP_TRUE));
tx4.vout.push_back(CTxOut(bitcoinID, 40, CScript() << OP_TRUE));
tx4.vout.push_back(CTxOut(bitcoinID, 111+100-30-40, CScript()));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), nullptr, false)); // Spends a blinded coin with no blinded outputs to compensate.
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), consensusParams, nullptr, false)); // Spends a blinded coin with no blinded outputs to compensate.

std::vector<uint256> input_blinds;
std::vector<uint256> input_asset_blinds;
Expand Down Expand Up @@ -202,7 +204,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
tx4.vout.push_back(CTxOut(bitcoinID, 50, CScript() << OP_TRUE));
// Fee
tx4.vout.push_back(CTxOut(bitcoinID, 111+100-30-40-50, CScript()));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), nullptr, false)); // Spends a blinded coin with no blinded outputs to compensate.
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), consensusParams, nullptr, false)); // Spends a blinded coin with no blinded outputs to compensate.

std::vector<uint256> input_blinds;
std::vector<uint256> input_asset_blinds;
Expand Down Expand Up @@ -231,7 +233,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
BOOST_CHECK(tx4.vout[1].nValue.IsExplicit());
BOOST_CHECK(!tx4.vout[2].nValue.IsExplicit());
// This one broken
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx4), nullptr, false));
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(tx4), consensusParams, nullptr, false));

CAmount unblinded_amount;
CAsset asset_out;
Expand Down Expand Up @@ -261,7 +263,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
BOOST_CHECK(UnblindConfidentialPair(key2, tx4.vout[2].nValue, tx4.vout[2].nAsset, tx4.vout[2].nNonce, op_true, tx4.witness.vtxoutwit[2].vchRangeproof, unblinded_amount, blind4, asset_out, asset_blinder_out) == 0);

tx4.vout[3].nValue = CConfidentialValue(tx4.vout[3].nValue.GetAmount() - 1);
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx4), consensusParams, nullptr, false));

// Check wallet borromean-based rangeproof results against expected args
size_t proof_size = DEFAULT_RANGEPROOF_SIZE;
Expand Down Expand Up @@ -298,7 +300,7 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
tx5.vout.push_back(CTxOut(otherID, 1, CScript()));

// Blinds don't balance
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx5), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(tx5), consensusParams, nullptr, false));

// Blinding setup stuff
std::vector<uint256> input_blinds;
Expand All @@ -324,27 +326,27 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)

// No blinding keys for fees, bails out blinding nothing, still invalid due to imbalance
BOOST_CHECK(BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, txtemp) == -1);
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), consensusParams, nullptr, false));
// Last will be implied blank keys
output_pubkeys.resize(4);

// Blind transaction, verify amounts
txtemp = tx5;
BOOST_CHECK(BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, txtemp) == 4);
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false));
BOOST_CHECK(VerifyAmounts(inputs, CTransaction(txtemp), consensusParams, nullptr, false));

// Transaction may not have spendable 0-value output
txtemp.vout.push_back(CTxOut(CAsset(), 0, CScript() << OP_TRUE));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), consensusParams, nullptr, false));

// Create imbalance by removing fees, should still be able to blind
txtemp = tx5;
txtemp.vout.resize(5);
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), consensusParams, nullptr, false));
txtemp.vout.resize(4);
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), consensusParams, nullptr, false));
BOOST_CHECK(BlindTransaction(input_blinds, input_asset_blinds, input_assets, input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, txtemp) == 4);
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), consensusParams, nullptr, false));

txtemp = tx5;
// Remove other input, make surjection proof impossible for 2 "otherID" outputs
Expand All @@ -363,9 +365,9 @@ BOOST_AUTO_TEST_CASE(naive_blinding_test)
t_input_asset_blinds.resize(1);
t_input_assets.resize(1);
t_input_amounts.resize(1);
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), consensusParams, nullptr, false));
BOOST_CHECK(BlindTransaction(t_input_blinds, t_input_asset_blinds, t_input_assets, t_input_amounts, output_blinds, output_asset_blinds, output_pubkeys, vDummy, vDummy, txtemp) == 2);
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), nullptr, false));
BOOST_CHECK(!VerifyAmounts(inputs, CTransaction(txtemp), consensusParams, nullptr, false));
}
}
BOOST_AUTO_TEST_SUITE_END()
3 changes: 2 additions & 1 deletion src/test/fuzz/coins_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ void initialize_coins_view()
FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
{
FuzzedDataProvider fuzzed_data_provider{buffer.data(), buffer.size()};
const Consensus::Params& consensus_params = Params().GetConsensus();
CCoinsView backend_coins_view;
CCoinsViewCache coins_view_cache{&backend_coins_view};
COutPoint random_out_point;
Expand Down Expand Up @@ -252,7 +253,7 @@ FUZZ_TARGET_INIT(coins_view, initialize_coins_view)
}
std::vector<std::pair<CScript, CScript>> fedpegscripts; // ELEMENTS: we ought to populate this and have a more useful fuzztest
std::set<std::pair<uint256, COutPoint> > setPeginsSpent;
if (Consensus::CheckTxInputs(transaction, state, coins_view_cache, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, std::numeric_limits<int>::max()), tx_fee_map, setPeginsSpent, NULL, false, true, fedpegscripts)) {
if (Consensus::CheckTxInputs(transaction, state, coins_view_cache, consensus_params, fuzzed_data_provider.ConsumeIntegralInRange<int>(0, std::numeric_limits<int>::max()), tx_fee_map, setPeginsSpent, NULL, false, true, fedpegscripts)) {
assert(MoneyRange(tx_fee_map));
}
},
Expand Down
8 changes: 5 additions & 3 deletions src/test/pegin_witness_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ BOOST_AUTO_TEST_CASE(witness_valid)

std::string err;

const Consensus::Params& consensusParams = Params().GetConsensus();

std::vector<unsigned char> fedpegscript_bytes = ParseHex(fedpegscript_str);
CScript fedpegscript(fedpegscript_bytes.begin(), fedpegscript_bytes.end());
// Test sample was generated as "legacy" with p2sh-p2wsh fedpegscript
Expand Down Expand Up @@ -123,15 +125,15 @@ BOOST_AUTO_TEST_CASE(witness_valid)
CCoinsViewCache coins(&coinsDummy);
// Get the latest block index to look up fedpegscripts
// For these tests, should be genesis-block-hardcoded consensus.fedpegscript
BOOST_CHECK(Consensus::CheckTxInputs(tx, state, coins, 0, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts));
BOOST_CHECK(Consensus::CheckTxInputs(tx, state, coins, consensusParams, 0, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts));
BOOST_CHECK(setPeginsSpent.size() == 1);
setPeginsSpent.clear();

// Strip pegin_witness
CMutableTransaction mtxn(tx);
mtxn.witness.vtxinwit[0].m_pegin_witness.SetNull();
CTransaction tx2(mtxn);
BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, coins, 0, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts));
BOOST_CHECK(!Consensus::CheckTxInputs(tx2, state, coins, consensusParams, 0, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts));
BOOST_CHECK(setPeginsSpent.empty());

// Invalidate peg-in (and spending) authorization by pegin marker.
Expand All @@ -140,7 +142,7 @@ BOOST_AUTO_TEST_CASE(witness_valid)
CMutableTransaction mtxn2(tx);
mtxn2.vin[0].m_is_pegin = false;
CTransaction tx3(mtxn2);
BOOST_CHECK(!Consensus::CheckTxInputs(tx3, state, coins, 0, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts));
BOOST_CHECK(!Consensus::CheckTxInputs(tx3, state, coins, consensusParams, 0, fee_map, setPeginsSpent, NULL, false, true, fedpegscripts));
BOOST_CHECK(setPeginsSpent.empty());


Expand Down
2 changes: 1 addition & 1 deletion src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ void CTxMemPool::check(const CBlockIndex* active_chain_tip, const CCoinsViewCach
const auto& fedpegscripts = GetValidFedpegScripts(active_chain_tip, Params().GetConsensus(), true /* nextblock_validation */);
bool cacheStore = true;
bool fScriptChecks = true;
assert(Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate, spendheight, fee_map, setPeginsSpent, nullptr, cacheStore, fScriptChecks, fedpegscripts));
assert(Consensus::CheckTxInputs(tx, dummy_state, mempoolDuplicate, Params().GetConsensus(), spendheight, fee_map, setPeginsSpent, nullptr, cacheStore, fScriptChecks, fedpegscripts));
for (const auto& input: tx.vin) mempoolDuplicate.SpendCoin(input.prevout);
AddCoins(mempoolDuplicate, tx, std::numeric_limits<int>::max());
}
Expand Down
Loading