Example #1
0
        public bool ProcessBlock(Node node, Block block, out ChainedBlock chainedBlock)
        {
            chainedBlock = null;
            var blockHash = block.GetHash();


            // ppcoin: check proof-of-stake
            // Limited duplicity on stake: prevents block flood attack
            // Duplicate stake allowed only when there is orphan child block
            //if (!fReindex && !fImporting && pblock->IsProofOfStake() && setStakeSeen.count(pblock->GetProofOfStake()) && !mapOrphanBlocksByPrev.count(hash))
            //	return error("ProcessBlock() : duplicate proof-of-stake (%s, %d) for block %s", pblock->GetProofOfStake().first.ToString(), pblock->GetProofOfStake().second, hash.ToString());

            if (block.Header.HashPrevBlock != this.chainIndex.Tip.HashBlock)
            {
                // Extra checks to prevent "fill up memory by spamming with bogus blocks"
                //const CBlockIndex* pcheckpoint = Checkpoints::AutoSelectSyncCheckpoint();
                //var deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
                //if (deltaTime < 0)
                //{
                //	if (pfrom)
                //		pfrom->Misbehaving(1);
                //	return error("ProcessBlock() : block with timestamp before last checkpoint");
                //}
            }

            if (!BlockValidator.IsCanonicalBlockSignature(block, false))
            {
                //if (node != null && (int)node.Version >= CANONICAL_BLOCK_SIG_VERSION)
                //node.Misbehaving(100);

                //return false; //error("ProcessBlock(): bad block signature encoding");
            }

            if (!BlockValidator.IsCanonicalBlockSignature(block, true))
            {
                //if (pfrom && pfrom->nVersion >= CANONICAL_BLOCK_SIG_LOW_S_VERSION)
                //{
                //	pfrom->Misbehaving(100);
                //	return error("ProcessBlock(): bad block signature encoding (low-s)");
                //}

                if (!BlockValidator.EnsureLowS(block.BlockSignatur))
                {
                    return(false);                    // error("ProcessBlock(): EnsureLowS failed");
                }
            }

            // Preliminary checks
            if (!BlockValidator.CheckBlock(block))
            {
                return(false);                //error("ProcessBlock() : CheckBlock FAILED");
            }
            var prevChainedBlock = this.chainIndex.GetAnyTip(block.Header.HashPrevBlock);

            if (prevChainedBlock == null)
            {
                throw new InvalidBlockException();
            }

            chainedBlock = new ChainedBlock(block.Header, blockHash, prevChainedBlock);

            if (!block.Header.PosParameters.IsSet())
            {
                chainedBlock.Header.PosParameters = block.SetPosParams();
            }

            // ensure the previous chainedBlock has
            // the POS parameters set if not load its
            // block and set the pos params
            if (!prevChainedBlock.Header.PosParameters.IsSet())
            {
                var prevBlock = this.chainIndex.GetFullBlock(prevChainedBlock.HashBlock);
                prevChainedBlock.Header.PosParameters = prevBlock.Header.PosParameters;
            }

            // do some checks
            if (!chainedBlock.Validate(this.Context.Network))
            {
                return(false);
            }

            // todo: implement this checks

            //if (IsProtocolV2(nHeight) && nVersion < 7)
            //	return DoS(100, error("AcceptBlock() : reject too old nVersion = %d", nVersion));
            //else if (!IsProtocolV2(nHeight) && nVersion > 6)
            //	return DoS(100, error("AcceptBlock() : reject too new nVersion = %d", nVersion));

            //if (IsProofOfWork() && nHeight > Params().LastPOWBlock())
            //	return DoS(100, error("AcceptBlock() : reject proof-of-work at height %d", nHeight));

            //// Check coinbase timestamp
            //if (GetBlockTime() > FutureDrift((int64_t)vtx[0].nTime, nHeight))
            //	return DoS(50, error("AcceptBlock() : coinbase timestamp is too early"));

            // Check coinstake timestamp
            if (block.IsProofOfStake() && !BlockValidator.CheckCoinStakeTimestamp(chainedBlock.Height, block.Header.Time, block.Transactions[1].Time))
            {
                return(false);                //DoS(50, error("AcceptBlock() : coinstake timestamp violation nTimeBlock=%d nTimeTx=%u", GetBlockTime(), vtx[1].nTime));
            }
            //// Check proof-of-work or proof-of-stake
            //if (nBits != GetNextTargetRequired(pindexPrev, IsProofOfStake()))
            //	return DoS(100, error("AcceptBlock() : incorrect %s", IsProofOfWork() ? "proof-of-work" : "proof-of-stake"));

            //// Check timestamp against prev
            //if (GetBlockTime() <= pindexPrev->GetPastTimeLimit() || FutureDrift(GetBlockTime(), nHeight) < pindexPrev->GetBlockTime())
            //	return error("AcceptBlock() : block's timestamp is too early");

            //// Check that all transactions are finalized
            //BOOST_FOREACH(const CTransaction&tx, vtx)
            //     if (!IsFinalTx(tx, nHeight, GetBlockTime()))
            //	return DoS(10, error("AcceptBlock() : contains a non-final transaction"));

            //// Check that the block chain matches the known block chain up to a checkpoint
            //if (!Checkpoints::CheckHardened(nHeight, hash))
            //	return DoS(100, error("AcceptBlock() : rejected by hardened checkpoint lock-in at %d", nHeight));



            if (!BlockValidator.CheckAndComputeStake(this.chainIndex, this.chainIndex, this.chainIndex, this.chainIndex, chainedBlock, block))
            {
                return(false);
            }

            // all validations passed
            return(true);
        }