public ConsensusStats(CoinViewStack stack, CoinView coinView, ConsensusLoop consensusLoop, ChainBehavior.ChainState chainState, ConcurrentChain chain, IConnectionManager connectionManager) { stack = new CoinViewStack(coinView); this.cache = stack.Find <CachedCoinView>(); this.dbreeze = stack.Find <DBreezeCoinView>(); this.bottom = stack.Bottom; this.consensusLoop = consensusLoop; this.lookaheadPuller = this.consensusLoop.Puller as LookaheadBlockPuller; this.lastSnapshot = consensusLoop.Validator.PerformanceCounter.Snapshot(); this.lastSnapshot2 = this.dbreeze?.PerformanceCounter.Snapshot(); this.lastSnapshot3 = this.cache?.PerformanceCounter.Snapshot(); this.chainState = chainState; this.chain = chain; this.connectionManager = connectionManager; }
// ppcoin: total coin age spent in transaction, in the unit of coin-days. // Only those coins meeting minimum age requirement counts. As those // transactions not in main chain are not currently indexed so we // might not find out about their coin age. Older transactions are // guaranteed to be in main chain by sync-checkpoint. This rule is // introduced to help nodes establish a consistent view of the coin // age (trust score) of competing branches. public bool GetCoinAge(ConcurrentChain chain, CachedCoinView cachedCoinView, Transaction trx, ChainedBlock pindexPrev, out ulong nCoinAge) { BigInteger bnCentSecond = BigInteger.Zero; // coin age in the unit of cent-seconds nCoinAge = 0; if (trx.IsCoinBase) { return(true); } foreach (var txin in trx.Inputs) { var coins = cachedCoinView.FetchCoinsAsync(new[] { txin.PrevOut.Hash }).GetAwaiter().GetResult(); if (coins == null || coins.UnspentOutputs.Length != 1) { continue; } var prevBlock = chain.GetBlock(coins.BlockHash); var prevUtxo = coins.UnspentOutputs[0]; // First try finding the previous transaction in database //Transaction txPrev = trasnactionStore.Get(txin.PrevOut.Hash); //if (txPrev == null) // continue; // previous transaction not in main chain if (trx.Time < prevUtxo.Time) { return(false); // Transaction timestamp violation } if (IsProtocolV3((int)trx.Time)) { if (IsConfirmedInNPrevBlocks(prevUtxo, pindexPrev, this.consensusOptions.StakeMinConfirmations - 1)) { //LogPrint("coinage", "coin age skip nSpendDepth=%d\n", nSpendDepth + 1); continue; // only count coins meeting min confirmations requirement } } else { // Read block header //var block = blockStore.GetBlock(txPrev.GetHash()); //if (block == null) // return false; // unable to read block of previous transaction if (prevBlock.Header.Time + this.consensusOptions.StakeMinAge > trx.Time) { continue; // only count coins meeting min age requirement } } long nValueIn = prevUtxo._Outputs[txin.PrevOut.N].Value; var multiplier = BigInteger.ValueOf((trx.Time - prevUtxo.Time) / Money.CENT); bnCentSecond = bnCentSecond.Add(BigInteger.ValueOf(nValueIn).Multiply(multiplier)); //bnCentSecond += new BigInteger(nValueIn) * (trx.Time - txPrev.Time) / CENT; //LogPrint("coinage", "coin age nValueIn=%d nTimeDiff=%d bnCentSecond=%s\n", nValueIn, nTime - txPrev.nTime, bnCentSecond.ToString()); } BigInteger bnCoinDay = bnCentSecond.Multiply(BigInteger.ValueOf(Money.CENT / Money.COIN / (24 * 60 * 60))); //BigInteger bnCoinDay = bnCentSecond * CENT / COIN / (24 * 60 * 60); //LogPrint("coinage", "coin age bnCoinDay=%s\n", bnCoinDay.ToString()); nCoinAge = new Target(bnCoinDay).ToCompact(); return(true); }