Browse Source

Various improvements to shielded transaction and payment stats gathering

warmup
Jonathan "Duke" Leto 5 years ago
parent
commit
6ddcdc2497
  1. 81
      src/main.cpp

81
src/main.cpp

@ -4767,19 +4767,20 @@ CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
/** Mark a block as having its data received and checked (up to BLOCK_VALID_TRANSACTIONS). */
bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBlockIndex *pindexNew, const CDiskBlockPos& pos)
{
pindexNew->nTx = block.vtx.size();
pindexNew->nChainTx = 0;
pindexNew->nTx = block.vtx.size();
pindexNew->nChainTx = 0;
pindexNew->nChainPayments = 0;
pindexNew->nShieldedTx = 0;
pindexNew->nShieldingTx = 0;
pindexNew->nShieldedTx = 0;
pindexNew->nShieldingTx = 0;
pindexNew->nDeshieldingTx = 0;
CAmount sproutValue = 0;
CAmount saplingValue = 0;
int64_t nShieldedSpends=0,nShieldedOutputs=0;
int64_t nShieldedPayments=0;
int64_t nFullyShielded=0,nShielding=0,nDeshielding=0,nMultipleShieldedInputs=0;
CAmount sproutValue = 0;
CAmount saplingValue = 0;
bool isShieldedTx = false;
int64_t nShieldedSpends=0,nShieldedOutputs=0,nChainPayments=0;
int64_t nShieldedTx=0,nFullyShieldedTx=0,nDeshieldingTx=0,nShieldingTx=0;
int64_t nShieldedPayments=0,nFullyShieldedPayments=0,nShieldingPayments=0,nDeshieldingPayments=0;
bool hasShieldedTx = false;
for (auto tx : block.vtx) {
// Negative valueBalance "takes" money from the transparent value pool
// and adds it to the Sapling value pool. Positive valueBalance "gives"
@ -4791,43 +4792,49 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
sproutValue += js.vpub_old;
sproutValue -= js.vpub_new;
}
nShieldedSpends = tx.vShieldedSpend.size();
nShieldedOutputs = tx.vShieldedOutput.size();
hasShieldedTx = (nShieldedSpends + nShieldedOutputs) > 0 ? true : false;
nShieldedSpends = tx.vShieldedSpend.size();
nShieldedOutputs = tx.vShieldedOutput.size();
isShieldedTx = (nShieldedSpends + nShieldedOutputs) > 0 ? true : false;
if(hasShieldedTx) {
if(isShieldedTx) {
nShieldedTx++;
if(tx.vin.size()==0 && tx.vout.size()==0) {
nFullyShielded++;
nFullyShieldedTx++;
}
if(tx.vin.size()>0) {
nShielding++;
nShieldingTx++;
}
if(tx.vout.size()>0) {
nDeshielding++;
nDeshieldingTx++;
}
if(nShieldedSpends>1) {
nMultipleShieldedInputs++;
}
//TODO: These are at best heuristics. Improve them as much as possible
//TODO: Take into account change addresses
//NOTE: You cannot compare stats generated from different sets of heuristics
//NOTE: These are at best heuristics. Improve them as much as possible
// You cannot compare stats generated from different sets of heuristics
if (nShieldedOutputs >= 1) {
// If there are shielded outputs, count each as a payment
// By default, if there is more than 1 output, we assume 1 change output which is not a payment.
// In the case of multiple outputs which spend inputs exactly, there is no change output and this
// heuristic will undercount payments. Since this edge case is rare, this seems acceptable.
// t->(t,t,z) = 1 shielded payment
// z->(z,z) = 1 shielded payment + shielded change
// t->(z,z) = 1 shielded payment + shielded change
// t->(t,z) = 1 shielded payment + transparent change
// (z,z)->z = 1 shielded payment (has this xtn ever occurred?)
// z->(z,z,z) = 2 shielded payments + shielded change
// Assume that there is always 1 change output when there are more than one
nShieldedPayments += nShieldedOutputs > 1 ? (nShieldedOutputs-1) : 1;
} else if (nShieldedSpends >=1) {
// Shielded inputs with no shielded outputs. We know none are change output because
// change would flow back to the zaddr
// z->t = 1 shielded payment
// (z,z)->z = 1 shielded payment
// z->(t,t) = 1 shielded payment
nShieldedPayments++;
// z->(t,t) = 2 shielded payments
// z->(t,t,t) = 3 shielded payments
nShieldedPayments += tx.vout.size();
}
nChainPayments += nShieldedPayments;
} else {
// No shielded payments, add transparent payments minus a change address
nChainPayments += tx.vout.size() > 1 ? tx.vout.size()-1 : tx.vout.size();
}
}
pindexNew->nSproutValue = sproutValue;
@ -4839,6 +4846,18 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
pindexNew->nUndoPos = 0;
pindexNew->nStatus |= BLOCK_HAVE_DATA;
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
// Store data for later use by gettxchainstats and other RPCs
pindexNew->nChainPayments = nChainPayments;
pindexNew->nShieldedTx = nShieldedTx;
pindexNew->nFullyShieldedTx = nFullyShieldedTx;
pindexNew->nDeshieldingTx = nDeshieldingTx;
pindexNew->nShieldingTx = nShieldingTx;
pindexNew->nShieldedPayments = nShieldedPayments;
pindexNew->nFullyShieldedPayments = nFullyShieldedPayments;
pindexNew->nDeshieldingPayments = nDeshieldingPayments;
pindexNew->nShieldingPayments = nShieldingPayments;
setDirtyBlockIndex.insert(pindexNew);
if (pindexNew->pprev == NULL || pindexNew->pprev->nChainTx) {
@ -4851,10 +4870,6 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
CBlockIndex *pindex = queue.front();
queue.pop_front();
// Keep track of shielded transaction stats
if(hasShieldedTx) {
pindex->nShieldedTx = pindex->nShieldedTx ? 0 : pindex->nShieldedTx + 1;
}
pindex->nChainTx = (pindex->pprev ? pindex->pprev->nChainTx : 0) + pindex->nTx;
if (pindex->pprev) {
if (pindex->pprev->nChainSproutValue && pindex->nSproutValue) {
@ -4892,6 +4907,8 @@ bool ReceivedBlockTransactions(const CBlock &block, CValidationState& state, CBl
}
}
fprintf(stderr, "ht.%d, ShieldedPayments=%d, ShieldedTx=%d, FullyShieldedTx=%d\n",
pindexNew->GetHeight(), nShieldedPayments, nShieldedTx, nFullyShieldedTx );
return true;
}

Loading…
Cancel
Save