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); }