public override void Execute() { // load headers form file (or genesis) if (File.Exists(this.Context.Config.File("headers.dat"))) { this.logger.LogInformation("Loading headers form disk..."); this.ChainIndex.Load(File.ReadAllBytes(this.Context.Config.File("headers.dat"))); } else { this.logger.LogInformation("Loading headers no file found..."); var genesis = this.Context.Network.GetGenesis(); this.ChainIndex.SetTip(new ChainedBlock(genesis.Header, 0)); // validate the block to generate the pos params BlockValidator.CheckAndComputeStake(this.ChainIndex, this.ChainIndex, this.ChainIndex, this.ChainIndex, this.ChainIndex.Tip, genesis); //this.ChainIndex.ValidateBlock(genesis); } // load the index chain this will // add each block index to memory for fast lookup this.ChainIndex.Initialize(this.Context); // sync the headers chain this.logger.LogInformation("Sync chain headers with network..."); this.chainSyncService.SyncChain(); // persist the chain this.logger.LogInformation("Persist headers..."); this.chainSyncService.SaveToDisk(); }
public void CheckBlockProofOfStake() { var totalblocks = 5000; // fill only a small portion so test wont be too long var mainStore = new BlockStore(TestDataLocations.BlockFolderLocation, Network.Main); // create the stores var store = CreateBlockStore(); var index = 0; var blockStore = new NoSqlBlockRepository(); foreach (var storedBlock in mainStore.Enumerate(false).Take(totalblocks)) { store.Append(storedBlock.Item); blockStore.PutAsync(storedBlock.Item); index++; } // build the chain var chain = store.GetChain(); // fill the transaction store var trxStore = new NoSqlTransactionRepository(); var mapStore = new BlockTransactionMapStore(); foreach (var chainedBlock in chain.ToEnumerable(false).Take(totalblocks)) { var block = blockStore.GetBlock(chainedBlock.HashBlock); foreach (var blockTransaction in block.Transactions) { trxStore.Put(blockTransaction); mapStore.PutAsync(blockTransaction.GetHash(), block.GetHash()); } } RPCClient client = null; // new RPCClient(new NetworkCredential("rpcuser", "rpcpassword"), new Uri("http://127.0.0.1:" + Network.Main.RPCPort), Network.Main); // validate the stake trasnaction foreach (var item in chain.ToEnumerable(false).Take(totalblocks).ToList()) { var block = blockStore.GetBlock(item.HashBlock); Assert.True(BlockValidator.CheckAndComputeStake(blockStore, trxStore, mapStore, chain, item, block)); if (item.Height == 1125) { var g = block.ToHex(); } if (client != null) { var fetched = client.GetRPCBlock(item.HashBlock).Result; Assert.Equal(uint256.Parse(fetched.modifierv2), item.Header.PosParameters.StakeModifierV2); Assert.Equal(uint256.Parse(fetched.proofhash), item.Header.PosParameters.HashProof); } } }
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); }