Exemple #1
0
        public static bool CheckKernel(IBlockRepository blockStore, ITransactionRepository trasnactionStore,
                                       IBlockTransactionMapStore mapStore, StakeChain stakeChain,
                                       ChainedBlock pindexPrev, uint nBits, long nTime, OutPoint prevout, ref long pBlockTime)
        {
            uint256 hashProofOfStake = null, targetProofOfStake = null;

            var txPrev = trasnactionStore.Get(prevout.Hash);

            if (txPrev == null)
            {
                return(false);
            }

            // Read block header
            var blockHashPrev = mapStore.GetBlockHash(prevout.Hash);
            var block  = blockHashPrev == null ? null : blockStore.GetBlock(blockHashPrev);

            if (block == null)
            {
                return(false);
            }

            if (IsProtocolV3((int)nTime))
            {
                int nDepth = 0;
                if (IsConfirmedInNPrevBlocks(blockStore, txPrev, pindexPrev, StakeMinConfirmations - 1, ref nDepth))
                {
                    return(false);                    // tx.DoS(100, error("CheckProofOfStake() : tried to stake at depth %d", nDepth + 1));
                }
            }
            else
            {
                var nTimeBlockFrom = block.Header.Time;
                if (nTimeBlockFrom + StakeMinAge > nTime)
                {
                    return(false);                    // error("CheckProofOfStake() : min age violation");
                }
            }

            var prevBlockStake = stakeChain.Get(pindexPrev.HashBlock);

            if (prevBlockStake == null)
            {
                return(false);                // the stake proof of the previous block is not set
            }
            // todo: check this unclear logic
            //if (pBlockTime)
            //	pBlockTime = block.Header.Time;

            return(CheckStakeKernelHash(pindexPrev, nBits, block, txPrev, prevBlockStake, prevout, (uint)nTime, out hashProofOfStake, out targetProofOfStake, false));
        }
Exemple #2
0
        // Check kernel hash target and coinstake signature
        public static bool CheckProofOfStake(IBlockRepository blockStore, ITransactionRepository trasnactionStore, IBlockTransactionMapStore mapStore,
                                             ChainedBlock pindexPrev, BlockStake prevBlockStake, Transaction tx, uint nBits, out uint256 hashProofOfStake, out uint256 targetProofOfStake)
        {
            targetProofOfStake = null; hashProofOfStake = null;

            // todo: Comments on this mehtod:
            // the store objects (IBlockRepository and  ITransactionRepository) should be a singleton instance of
            // the BlockValidator and would be initiated as part of a Dependency Injection freamwork

            if (!tx.IsCoinStake)
            {
                return(false);                // error("CheckProofOfStake() : called on non-coinstake %s", tx.GetHash().ToString());
            }
            // Kernel (input 0) must match the stake hash target per coin age (nBits)
            var txIn = tx.Inputs[0];

            // First try finding the previous transaction in database
            var txPrev = trasnactionStore.Get(txIn.PrevOut.Hash);

            if (txPrev == null)
            {
                return(false);                // tx.DoS(1, error("CheckProofOfStake() : INFO: read txPrev failed"));  // previous transaction not in main chain, may occur during initial download
            }
            // Verify signature
            if (!VerifySignature(txPrev, tx, 0, ScriptVerify.None))
            {
                return(false);                // tx.DoS(100, error("CheckProofOfStake() : VerifySignature failed on coinstake %s", tx.GetHash().ToString()));
            }
            // Read block header
            var blockHashPrev = mapStore.GetBlockHash(txIn.PrevOut.Hash);
            var block         = blockHashPrev == null ? null : blockStore.GetBlock(blockHashPrev);

            if (block == null)
            {
                return(false);                //fDebug? error("CheckProofOfStake() : read block failed") : false; // unable to read block of previous transaction
            }
            // Min age requirement
            if (IsProtocolV3((int)tx.Time))
            {
                int nDepth = 0;
                if (IsConfirmedInNPrevBlocks(blockStore, txPrev, pindexPrev, StakeMinConfirmations - 1, ref nDepth))
                {
                    return(false);                    // tx.DoS(100, error("CheckProofOfStake() : tried to stake at depth %d", nDepth + 1));
                }
            }
            else
            {
                var nTimeBlockFrom = block.Header.Time;
                if (nTimeBlockFrom + StakeMinAge > tx.Time)
                {
                    return(false);                    // error("CheckProofOfStake() : min age violation");
                }
            }

            if (!CheckStakeKernelHash(pindexPrev, nBits, block, txPrev, prevBlockStake, txIn.PrevOut, tx.Time, out hashProofOfStake, out targetProofOfStake, false))
            {
                return(false);                // tx.DoS(1, error("CheckProofOfStake() : INFO: check kernel failed on coinstake %s, hashProof=%s", tx.GetHash().ToString(), hashProofOfStake.ToString())); // may occur during initial download or if behind on block chain sync
            }
            return(true);
        }
Exemple #3
0
        public const uint ModifierInterval     = 10 * 60; // time to elapse before new modifier is computed

        public static bool CheckAndComputeStake(IBlockRepository blockStore, ITransactionRepository trasnactionStore, IBlockTransactionMapStore mapStore, StakeChain stakeChain,
                                                ChainBase chainIndex, ChainedBlock pindex, Block block, out BlockStake blockStake)
        {
            if (block.GetHash() != pindex.HashBlock)
            {
                throw new ArgumentException();
            }

            blockStake = new BlockStake(block);

            uint256 hashProof = null;

            // Verify hash target and signature of coinstake tx
            if (BlockStake.IsProofOfStake(block))
            {
                var pindexPrev = pindex.Previous;

                var prevBlockStake = stakeChain.Get(pindexPrev.HashBlock);
                if (prevBlockStake == null)
                {
                    return(false);                    // the stake proof of the previous block is not set
                }
                uint256 targetProofOfStake;
                if (!CheckProofOfStake(blockStore, trasnactionStore, mapStore, pindexPrev, prevBlockStake, block.Transactions[1],
                                       pindex.Header.Bits.ToCompact(), out hashProof, out targetProofOfStake))
                {
                    return(false);                    // error("AcceptBlock() : check proof-of-stake failed for block %s", hash.ToString());
                }
            }

            // PoW is checked in CheckBlock()
            if (BlockStake.IsProofOfWork(block))
            {
                hashProof = pindex.Header.GetPoWHash();
            }

            // todo: is this the same as chain work?
            // compute chain trust score
            //pindexNew.nChainTrust = (pindexNew->pprev ? pindexNew->pprev->nChainTrust : 0) + pindexNew->GetBlockTrust();

            // compute stake entropy bit for stake modifier
            if (!blockStake.SetStakeEntropyBit(blockStake.GetStakeEntropyBit()))
            {
                return(false);                //error("AddToBlockIndex() : SetStakeEntropyBit() failed");
            }
            // Record proof hash value
            blockStake.HashProof = hashProof;

            // compute stake modifier
            return(ComputeStakeModifier(chainIndex, pindex, blockStake, stakeChain));
        }
Exemple #4
0
        // 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 static bool GetCoinAge(IBlockRepository blockStore, ITransactionRepository trasnactionStore, IBlockTransactionMapStore mapStore,
                                      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)
            {
                // 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 < txPrev.Time)
                {
                    return(false);                     // Transaction timestamp violation
                }
                if (IsProtocolV3((int)trx.Time))
                {
                    int nSpendDepth = 0;
                    if (IsConfirmedInNPrevBlocks(blockStore, txPrev, pindexPrev, StakeMinConfirmations - 1, ref nSpendDepth))
                    {
                        //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 (block.Header.Time + StakeMinAge > trx.Time)
                    {
                        continue;                         // only count coins meeting min age requirement
                    }
                }

                long nValueIn   = txPrev.Outputs[txin.PrevOut.N].Value;
                var  multiplier = BigInteger.ValueOf((trx.Time - txPrev.Time) / 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(CENT / 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);
        }