Esempio n. 1
0
        /// <summary>
        /// Check PoW and that the blocks connect correctly
        /// </summary>
        /// <param name="network">The network being used</param>
        /// <returns>True if PoW is correct</returns>
        public bool Validate(Network network)
        {
            if (network == null)
            {
                throw new ArgumentNullException("network");
            }
            if (Height != 0 && Previous == null)
            {
                return(false);
            }

            if (Block.BlockSignature)
            {
                return(BlockStake.Validate(network, this));
            }

            var heightCorrect   = Height == 0 || Height == Previous.Height + 1;
            var genesisCorrect  = Height != 0 || HashBlock == network.GetGenesis().GetHash();
            var hashPrevCorrect = Height == 0 || Header.HashPrevBlock == Previous.HashBlock;
            var hashCorrect     = HashBlock == Header.GetHash();
            var workCorrect     = CheckProofOfWorkAndTarget(network);

            return(heightCorrect && genesisCorrect && hashPrevCorrect && hashCorrect && workCorrect);
        }
Esempio n. 2
0
 public static bool CheckProofOfStake(this Block block)
 {
     return(BlockStake.CheckProofOfStake(block));
 }
Esempio n. 3
0
 public Target GetWorkRequired(ChainedBlock chainedBlock, BlockStake blockStake, Consensus consensus)
 {
     return(BlockValidator.GetNextTargetRequired(this, chainedBlock.Previous, consensus, blockStake.IsProofOfStake()));
 }
Esempio n. 4
0
 public bool CheckPowPosAndTarget(ChainedBlock chainedBlock, BlockStake blockStake, Network network)
 {
     return(this.CheckPowPosAndTarget(chainedBlock, blockStake, network.Consensus));
 }
Esempio n. 5
0
 public abstract void Set(uint256 blockid, BlockStake blockStake);
Esempio n. 6
0
 public static bool Check(Block block)
 {
     return(block.CheckMerkleRoot() && BlockStake.CheckProofOfWork(block) && BlockStake.CheckProofOfStake(block));
 }
Esempio n. 7
0
        public static bool ComputeStakeModifier(ChainBase chainIndex, ChainedBlock pindex, BlockStake blockStake, StakeChain stakeChain)
        {
            var pindexPrev     = pindex.Previous;
            var blockStakePrev = pindexPrev == null ? null : stakeChain.Get(pindexPrev.HashBlock);

            // compute stake modifier
            ulong nStakeModifier;
            bool  fGeneratedStakeModifier;

            if (!ComputeNextStakeModifier(stakeChain, chainIndex, pindexPrev, out nStakeModifier, out fGeneratedStakeModifier))
            {
                return(false);                //error("AddToBlockIndex() : ComputeNextStakeModifier() failed");
            }
            blockStake.SetStakeModifier(nStakeModifier, fGeneratedStakeModifier);
            blockStake.StakeModifierV2 = ComputeStakeModifierV2(
                pindexPrev, blockStakePrev, blockStake.IsProofOfWork() ? pindex.HashBlock : blockStake.PrevoutStake.Hash);

            return(true);
        }
Esempio n. 8
0
        // Stratis kernel protocol
        // coinstake must meet hash target according to the protocol:
        // kernel (input 0) must meet the formula
        //     hash(nStakeModifier + txPrev.block.nTime + txPrev.nTime + txPrev.vout.hash + txPrev.vout.n + nTime) < bnTarget * nWeight
        // this ensures that the chance of getting a coinstake is proportional to the
        // amount of coins one owns.
        // The reason this hash is chosen is the following:
        //   nStakeModifier: scrambles computation to make it very difficult to precompute
        //                   future proof-of-stake
        //   txPrev.block.nTime: prevent nodes from guessing a good timestamp to
        //                       generate transaction for future advantage,
        //                       obsolete since v3
        //   txPrev.nTime: slightly scrambles computation
        //   txPrev.vout.hash: hash of txPrev, to reduce the chance of nodes
        //                     generating coinstake at the same time
        //   txPrev.vout.n: output number of txPrev, to reduce the chance of nodes
        //                  generating coinstake at the same time
        //   nTime: current timestamp
        //   block/tx hash should not be used here as they can be generated in vast
        //   quantities so as to generate blocks faster, degrading the system back into
        //   a proof-of-work situation.
        //
        private static bool CheckStakeKernelHashV2(ChainedBlock pindexPrev, uint nBits, uint nTimeBlockFrom, BlockStake prevBlockStake,
                                                   Transaction txPrev, OutPoint prevout, uint nTimeTx, out uint256 hashProofOfStake, out uint256 targetProofOfStake, bool fPrintProofOfStake)
        {
            targetProofOfStake = null; hashProofOfStake = null;

            if (nTimeTx < txPrev.Time)        // Transaction timestamp violation
            {
                return(false);                //error("CheckStakeKernelHash() : nTime violation");
            }
            // Base target
            var bnTarget = new Target(nBits).ToBigInteger();

            // Weighted target
            var nValueIn = txPrev.Outputs[prevout.N].Value.Satoshi;
            var bnWeight = BigInteger.ValueOf(nValueIn);

            bnTarget = bnTarget.Multiply(bnWeight);

            // todo: investigate this issue, is the convertion to uint256 similar to the c++ implementation
            //targetProofOfStake = Target.ToUInt256(bnTarget);

            var     nStakeModifier       = prevBlockStake.StakeModifier;   //pindexPrev.Header.BlockStake.StakeModifier;
            uint256 bnStakeModifierV2    = prevBlockStake.StakeModifierV2; //pindexPrev.Header.BlockStake.StakeModifierV2;
            int     nStakeModifierHeight = pindexPrev.Height;
            var     nStakeModifierTime   = pindexPrev.Header.Time;

            // Calculate hash
            using (var ms = new MemoryStream())
            {
                var serializer = new BitcoinStream(ms, true);
                if (IsProtocolV3((int)nTimeTx))
                {
                    serializer.ReadWrite(bnStakeModifierV2);
                }
                else
                {
                    serializer.ReadWrite(nStakeModifier);
                    serializer.ReadWrite(nTimeBlockFrom);
                }

                serializer.ReadWrite(txPrev.Time);
                serializer.ReadWrite(prevout.Hash);
                serializer.ReadWrite(prevout.N);
                serializer.ReadWrite(nTimeTx);

                hashProofOfStake = Hashes.Hash256(ms.ToArray());
            }

            if (fPrintProofOfStake)
            {
                //LogPrintf("CheckStakeKernelHash() : using modifier 0x%016x at height=%d timestamp=%s for block from timestamp=%s\n",
                //	nStakeModifier, nStakeModifierHeight,
                //	DateTimeStrFormat(nStakeModifierTime),

                //	DateTimeStrFormat(nTimeBlockFrom));

                //LogPrintf("CheckStakeKernelHash() : check modifier=0x%016x nTimeBlockFrom=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n",
                //	nStakeModifier,
                //	nTimeBlockFrom, txPrev.nTime, prevout.n, nTimeTx,
                //	hashProofOfStake.ToString());
            }

            // Now check if proof-of-stake hash meets target protocol
            var hashProofOfStakeTarget = new BigInteger(hashProofOfStake.ToBytes(false));

            if (hashProofOfStakeTarget.CompareTo(bnTarget) > 0)
            {
                return(false);
            }

            //  if (fDebug && !fPrintProofOfStake)
            //  {
            //		LogPrintf("CheckStakeKernelHash() : using modifier 0x%016x at height=%d timestamp=%s for block from timestamp=%s\n",
            //		nStakeModifier, nStakeModifierHeight,
            //		DateTimeStrFormat(nStakeModifierTime),

            //		DateTimeStrFormat(nTimeBlockFrom));

            //		LogPrintf("CheckStakeKernelHash() : pass modifier=0x%016x nTimeBlockFrom=%u nTimeTxPrev=%u nPrevout=%u nTimeTx=%u hashProof=%s\n",
            //		nStakeModifier,
            //		nTimeBlockFrom, txPrev.nTime, prevout.n, nTimeTx,
            //		hashProofOfStake.ToString());
            //  }

            return(true);
        }
Esempio n. 9
0
        private static bool CheckStakeKernelHash(ChainedBlock pindexPrev, uint nBits, Block blockFrom, Transaction txPrev, BlockStake prevBlockStake,
                                                 OutPoint prevout, uint nTimeTx, out uint256 hashProofOfStake, out uint256 targetProofOfStake, bool fPrintProofOfStake)
        {
            targetProofOfStake = null; hashProofOfStake = null;

            if (IsProtocolV2(pindexPrev.Height + 1))
            {
                return(CheckStakeKernelHashV2(pindexPrev, nBits, blockFrom.Header.Time, prevBlockStake, txPrev, prevout, nTimeTx, out hashProofOfStake, out targetProofOfStake, fPrintProofOfStake));
            }
            else
            {
                return(CheckStakeKernelHashV1());
            }
        }
Esempio n. 10
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));
        }
Esempio n. 11
0
        // a method to check a block, this may be moved to the full node.
        public static bool CheckBlock(Block block, bool checkPow = true, bool checkMerkleRoot = true, bool checkSig = true)
        {
            // These are checks that are independent of context
            // that can be verified before saving an orphan block.

            // Size limits
            if (!block.Transactions.Any() || block.GetSerializedSize() > MAX_BLOCK_SIZE)
            {
                return(false);                // DoS(100, error("CheckBlock() : size limits failed"));
            }
            // Check proof of work matches claimed amount
            if (checkPow && BlockStake.IsProofOfWork(block) && !block.CheckProofOfWork())
            {
                return(false);                //DoS(50, error("CheckBlock() : proof of work failed"));
            }
            // Check timestamp
            if (block.Header.Time > FutureDriftV2(DateTime.UtcNow.Ticks)) //GetAdjustedTime()))
            {
                return(false);                                            //error("CheckBlock() : block timestamp too far in he future");
            }
            // First transaction must be coinbase, the rest must not be
            if (!block.Transactions[0].IsCoinBase)
            {
                return(false);                //  DoS(100, error("CheckBlock() : first tx is not coinbase"));
            }
            if (block.Transactions.Skip(1).Any(t => t.IsCoinBase))
            {
                return(false);                //DoS(100, error("CheckBlock() : more than one coinbase"));
            }
            if (BlockStake.IsProofOfStake(block))
            {
                // Coinbase output should be empty if proof-of-stake block
                if (block.Transactions[0].Outputs.Count != 1 || !block.Transactions[0].Outputs[0].IsEmpty)
                {
                    return(false);                    // DoS(100, error("CheckBlock() : coinbase output not empty for proof-of-stake block"));
                }
                // Second transaction must be coinstake, the rest must not be
                if (!block.Transactions[1].IsCoinStake)
                {
                    return(false);                    // DoS(100, error("CheckBlock() : second tx is not coinstake"));
                }
                if (block.Transactions.Skip(2).Any(t => t.IsCoinStake))
                {
                    return(false);                    //DoS(100, error("CheckBlock() : more than one coinstake"));
                }
            }

            // Check proof-of-stake block signature
            if (checkSig && !CheckBlockSignature(block))
            {
                return(false);                //DoS(100, error("CheckBlock() : bad proof-of-stake block signature"));
            }
            // Check transactions
            foreach (var transaction in block.Transactions)
            {
                if (transaction.Check() != TransactionCheckResult.Success)
                {
                    return(false);                    // DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed"));
                }
                // ppcoin: check transaction timestamp
                if (block.Header.Time < transaction.Time)
                {
                    return(false);                    // DoS(50, error("CheckBlock() : block timestamp earlier than transaction timestamp"));
                }
            }

            // Check for duplicate txids. This is caught by ConnectInputs(),
            // but catching it earlier avoids a potential DoS attack:
            var set = new HashSet <uint256>();

            if (block.Transactions.Select(t => t.GetHash()).Any(h => !set.Add(h)))
            {
                return(false);                //DoS(100, error("CheckBlock() : duplicate transaction"));
            }
            // todo: check if this is legacy from older implementtions and actually needed
            //uint nSigOps = 0;
            //foreach (var transaction in block.Transactions)
            //{
            //	nSigOps += GetLegacySigOpCount(transaction);
            //}
            //if (nSigOps > MAX_BLOCK_SIGOPS)
            //	return DoS(100, error("CheckBlock() : out-of-bounds SigOpCount"));

            // Check merkle root
            if (checkMerkleRoot && !block.CheckMerkleRoot())
            {
                return(false);                //DoS(100, error("CheckBlock() : hashMerkleRoot mismatch"));
            }
            return(true);
        }
Esempio n. 12
0
 public sealed override void Set(uint256 blockid, BlockStake blockStake)
 {
     // throw if item already exists
     this.items.Add(blockid, blockStake);
 }