mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-15 12:51:00 +02:00
mempool and policy support for peg-in inputs
This commit is contained in:
parent
6bad4e9d75
commit
ff5e9cd74d
3 changed files with 33 additions and 4 deletions
|
|
@ -120,6 +120,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||||
|
|
||||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||||
{
|
{
|
||||||
|
if (tx.vin[i].m_is_pegin) {
|
||||||
|
// This deals with p2sh in general only
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);
|
const CTxOut& prev = mapInputs.GetOutputFor(tx.vin[i]);
|
||||||
|
|
||||||
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
|
// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
|
||||||
|
|
@ -169,7 +173,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||||
if (tx.wit.vtxinwit.size() <= i || tx.wit.vtxinwit[i].scriptWitness.IsNull())
|
if (tx.wit.vtxinwit.size() <= i || tx.wit.vtxinwit[i].scriptWitness.IsNull())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
const CTxOut &prev = mapInputs.GetOutputFor(tx.vin[i]);
|
const CTxOut &prev = tx.vin[i].m_is_pegin ? GetPeginOutputFromWitness(tx.wit.vtxinwit[i].m_pegin_witness) : mapInputs.GetOutputFor(tx.vin[i]);
|
||||||
|
|
||||||
// get the scriptPubKey corresponding to this input:
|
// get the scriptPubKey corresponding to this input:
|
||||||
CScript prevScript = prev.scriptPubKey;
|
CScript prevScript = prev.scriptPubKey;
|
||||||
|
|
|
||||||
|
|
@ -709,8 +709,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
|
||||||
parentSigOpCost += it2->GetSigOpCost();
|
parentSigOpCost += it2->GetSigOpCost();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// peg-in inputs are not sanity-checked to be valid
|
||||||
const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
|
const CCoins* coins = pcoins->AccessCoins(txin.prevout.hash);
|
||||||
assert(coins && coins->IsAvailable(txin.prevout.n));
|
assert(txin.m_is_pegin || (coins && coins->IsAvailable(txin.prevout.n)));
|
||||||
}
|
}
|
||||||
// Check whether its inputs are marked in mapNextTx.
|
// Check whether its inputs are marked in mapNextTx.
|
||||||
auto it3 = mapNextTx.find(txin.prevout);
|
auto it3 = mapNextTx.find(txin.prevout);
|
||||||
|
|
|
||||||
|
|
@ -1124,6 +1124,10 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||||
// Note that this does not check for the presence of actual outputs (see the next check for that),
|
// Note that this does not check for the presence of actual outputs (see the next check for that),
|
||||||
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
|
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
|
||||||
BOOST_FOREACH(const CTxIn txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn txin, tx.vin) {
|
||||||
|
// Don't look for coins that only exist in parent chain
|
||||||
|
if (txin.m_is_pegin) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (!pcoinsTip->HaveCoinsInCache(txin.prevout.hash))
|
if (!pcoinsTip->HaveCoinsInCache(txin.prevout.hash))
|
||||||
vHashTxnToUncache.push_back(txin.prevout.hash);
|
vHashTxnToUncache.push_back(txin.prevout.hash);
|
||||||
if (!view.HaveCoins(txin.prevout.hash)) {
|
if (!view.HaveCoins(txin.prevout.hash)) {
|
||||||
|
|
@ -1137,6 +1141,22 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||||
if (!view.HaveInputs(tx))
|
if (!view.HaveInputs(tx))
|
||||||
return state.Invalid(false, REJECT_DUPLICATE, "bad-txns-inputs-spent");
|
return state.Invalid(false, REJECT_DUPLICATE, "bad-txns-inputs-spent");
|
||||||
|
|
||||||
|
// Extract peg-in inputs, pass set to mempool entry. Validity of pegins checked in CheckInputs
|
||||||
|
for (unsigned int i = 0; i < tx.vin.size(); i++) {
|
||||||
|
if (tx.vin[i].m_is_pegin) {
|
||||||
|
// Quick check of pegin witness and prevout to extract db entry
|
||||||
|
if (tx.wit.vtxinwit.size() <= i || tx.wit.vtxinwit[i].m_pegin_witness.stack.size() < 6 || uint256(tx.wit.vtxinwit[i].m_pegin_witness.stack[2]).IsNull() || tx.vin[i].prevout.hash.IsNull()) {
|
||||||
|
return state.Invalid(false, REJECT_INVALID, "pegin-no-witness");
|
||||||
|
}
|
||||||
|
std::pair<uint256, COutPoint> pegin = std::make_pair(uint256(tx.wit.vtxinwit[i].m_pegin_witness.stack[2]), tx.vin[i].prevout);
|
||||||
|
// This assumes non-null prevout and genesis block hash
|
||||||
|
if (view.IsWithdrawSpent(pegin)) {
|
||||||
|
return state.Invalid(false, REJECT_CONFLICT, "pegin-already-claimed");
|
||||||
|
}
|
||||||
|
setPeginsSpent.insert(pegin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Bring the best block into scope
|
// Bring the best block into scope
|
||||||
view.GetBestBlock();
|
view.GetBestBlock();
|
||||||
|
|
||||||
|
|
@ -1171,14 +1191,18 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
|
||||||
double nPriorityDummy = 0;
|
double nPriorityDummy = 0;
|
||||||
pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees);
|
pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees);
|
||||||
|
|
||||||
CAmount inChainInputValue;
|
// Neuter priority in mempool
|
||||||
double dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue);
|
CAmount inChainInputValue = 0;
|
||||||
|
double dPriority = 0;
|
||||||
|
|
||||||
// Keep track of transactions that spend a coinbase, which we re-scan
|
// Keep track of transactions that spend a coinbase, which we re-scan
|
||||||
// during reorgs to ensure COINBASE_MATURITY is still met.
|
// during reorgs to ensure COINBASE_MATURITY is still met.
|
||||||
// Also track withdraw lock spends to allow them through free relay
|
// Also track withdraw lock spends to allow them through free relay
|
||||||
bool fSpendsCoinbase = false;
|
bool fSpendsCoinbase = false;
|
||||||
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
||||||
|
if (txin.m_is_pegin) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
|
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
|
||||||
if (coins->IsCoinBase()) {
|
if (coins->IsCoinBase()) {
|
||||||
fSpendsCoinbase = true;
|
fSpendsCoinbase = true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue