Skip to content

Commit

Permalink
mempool and policy support for peg-in inputs
Browse files Browse the repository at this point in the history
  • Loading branch information
instagibbs committed Nov 6, 2017
1 parent 6bad4e9 commit ff5e9cd
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 4 deletions.
6 changes: 5 additions & 1 deletion src/policy/policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)

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]);

// Biggest 'standard' txin is a 15-of-15 P2SH multisig with compressed
Expand Down Expand Up @@ -169,7 +173,7 @@ bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
if (tx.wit.vtxinwit.size() <= i || tx.wit.vtxinwit[i].scriptWitness.IsNull())
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:
CScript prevScript = prev.scriptPubKey;
Expand Down
3 changes: 2 additions & 1 deletion src/txmempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -709,8 +709,9 @@ void CTxMemPool::check(const CCoinsViewCache *pcoins) const
parentSigOpCost += it2->GetSigOpCost();
}
} else {
// peg-in inputs are not sanity-checked to be valid
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.
auto it3 = mapNextTx.find(txin.prevout);
Expand Down
28 changes: 26 additions & 2 deletions src/validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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),
// and only helps with filling in pfMissingInputs (to determine missing vs spent).
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))
vHashTxnToUncache.push_back(txin.prevout.hash);
if (!view.HaveCoins(txin.prevout.hash)) {
Expand All @@ -1137,6 +1141,22 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
if (!view.HaveInputs(tx))
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
view.GetBestBlock();

Expand Down Expand Up @@ -1171,14 +1191,18 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C
double nPriorityDummy = 0;
pool.ApplyDeltas(hash, nPriorityDummy, nModifiedFees);

CAmount inChainInputValue;
double dPriority = view.GetPriority(tx, chainActive.Height(), inChainInputValue);
// Neuter priority in mempool
CAmount inChainInputValue = 0;
double dPriority = 0;

// Keep track of transactions that spend a coinbase, which we re-scan
// during reorgs to ensure COINBASE_MATURITY is still met.
// Also track withdraw lock spends to allow them through free relay
bool fSpendsCoinbase = false;
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
if (txin.m_is_pegin) {
continue;
}
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
if (coins->IsCoinBase()) {
fSpendsCoinbase = true;
Expand Down

0 comments on commit ff5e9cd

Please sign in to comment.