public double GetDifficulty(ChainedBlock blockindex) { // Floating point number that is a multiple of the minimum difficulty, // minimum difficulty = 1.0. if (blockindex == null) { if (this.ChainIndex.Tip == null) { return(1.0); } else { blockindex = BlockValidator.GetLastBlockIndex(this.ChainIndex.Tip, false); } } var nShift = (blockindex.Header.Bits >> 24) & 0xff; double dDiff = (double)0x0000ffff / (double)(blockindex.Header.Bits & 0x00ffffff); while (nShift < 29) { dDiff *= 256.0; nShift++; } while (nShift > 29) { dDiff /= 256.0; nShift--; } return(dDiff); }
private static readonly Ethash Ethash = new Ethash(); // temporarily keep reusing the same one as otherwise it would recreate cache for each test protected void Setup(ILogger logger) { _logger = logger; ILogger stateLogger = ShouldLog.State ? _logger : null; _multiDb = new MultiDb(stateLogger); _chain = new BlockStore(); _blockhashProvider = new BlockhashProvider(_chain); _virtualMachines = new Dictionary <EthereumNetwork, IVirtualMachine>(); _stateProviders = new Dictionary <EthereumNetwork, StateProvider>(); _storageProviders = new Dictionary <EthereumNetwork, IStorageProvider>(); _blockValidators = new Dictionary <EthereumNetwork, IBlockValidator>(); EthereumNetwork[] networks = { EthereumNetwork.Frontier, EthereumNetwork.Homestead, EthereumNetwork.Byzantium, EthereumNetwork.SpuriousDragon, EthereumNetwork.TangerineWhistle }; foreach (EthereumNetwork ethereumNetwork in networks) { IEthereumRelease spec = _protocolSpecificationProvider.GetSpec(ethereumNetwork, 1); ISignatureValidator signatureValidator = new SignatureValidator(spec, ChainId.MainNet); ITransactionValidator transactionValidator = new TransactionValidator(spec, signatureValidator); IBlockHeaderValidator headerValidator = new BlockHeaderValidator(_chain, Ethash); IOmmersValidator ommersValidator = new OmmersValidator(_chain, headerValidator); IBlockValidator blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, stateLogger); _blockValidators[ethereumNetwork] = blockValidator; _stateProviders[ethereumNetwork] = new StateProvider(new StateTree(_multiDb.CreateDb()), spec, stateLogger); _storageProviders[ethereumNetwork] = new StorageProvider(_multiDb, _stateProviders[ethereumNetwork], stateLogger); _virtualMachines[ethereumNetwork] = new VirtualMachine( spec, _stateProviders[ethereumNetwork], _storageProviders[ethereumNetwork], _blockhashProvider, ShouldLog.Evm ? logger : null); } }
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 Server Build( NodeConnectionInfo myConnectionInfo, KnownNodeStore knownNodeStore, NodeClientFactory nodeClientFactory, NodeClientStore nodeClientStore, VoteMemoryPool voteMemoryPool, Blockchain blockchain, Miner miner, VoteValidator voteValidator, BlockValidator blockValidator, BlockchainAdder blockchainAdder, IConsole console) { var handshakeService = new NodeService( knownNodeStore, nodeClientFactory, nodeClientStore, voteMemoryPool, blockchain, miner, voteValidator, blockValidator, blockchainAdder, console); var server = new Server { Services = { Node.BindService(handshakeService) }, Ports = { new ServerPort(myConnectionInfo.Ip, myConnectionInfo.Port, ServerCredentials.Insecure) } }; return(server); }
private void CheckState(Block block, ChainedBlock pindexPrev) { uint256 hashProof = 0, hashTarget = 0; uint256 hashBlock = block.GetHash(); if (!block.IsProofOfStake()) { return; // error("CheckStake() : %s is not a proof-of-stake block", hashBlock.GetHex()); } // verify hash target and signature of coinstake tx if (!BlockValidator.CheckProofOfStake(this.chainIndex, this.chainIndex, this.chainIndex, pindexPrev, block.Transactions[1], block.Header.Bits.ToCompact(), out hashProof, out hashTarget)) { return; // error("CheckStake() : proof-of-stake checking failed"); } //// debug print //LogPrintf("CheckStake() : new proof-of-stake block found \n hash: %s \nproofhash: %s \ntarget: %s\n", hashBlock.GetHex(), proofHash.GetHex(), hashTarget.GetHex()); //LogPrintf("%s\n", pblock->ToString()); //LogPrintf("out %s\n", FormatMoney(pblock->vtx[1].GetValueOut())); // Found a solution if (block.Header.HashPrevBlock != this.chainIndex.Tip.HashBlock) { return; // error("CheckStake() : generated block is stale"); } // Process this block the same as if we had received it from another node //this.BlockSyncHub.ReceiveBlocks.TryAdd(new HubReceiveBlockItem {Block = block}); ChainedBlock chainedBlock; if (this.blockReceiver.ProcessBlock(null, block, out chainedBlock)) { if (chainedBlock.ChainWork > this.chainIndex.Tip.ChainWork) { // Track how many getdata requests this block gets if (!this.BlockSyncHub.RequestCount.TryAdd(hashBlock, new RequestCounter())) { throw new MinedBlockException(); } // add to alt tips if (!this.minerService.MinedBlocks.TryAdd(chainedBlock, block)) { throw new MinedBlockException(); } // add to wallet //this.walletWorker.AddBlock(block); // let the wallet processes the transaction //this.Cancellation.Token.WaitHandle.WaitOne(1000); // broadcast it this.BlockSyncHub.BroadcastBlockInventory(new[] { hashBlock }); } } }
public void Test() { IBlockTree blockchain = Substitute.For <IBlockTree>(); HeaderValidator headerValidator = new HeaderValidator(blockchain, NullSealEngine.Instance, null, null); OmmersValidator ommersValidator = new OmmersValidator(blockchain, headerValidator, null); TxValidator txValidator = new TxValidator(ChainId.MainNet); BlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, RopstenSpecProvider.Instance, null); }
public void SetUp() { _blockchainProcessingQueue = Substitute.For <IBlockProcessingQueue>(); _blockchainProcessor = Substitute.For <IBlockchainProcessor>(); _blockTree = Build.A.BlockTree().OfChainLength(10).TestObject; HeaderValidator headerValidator = new HeaderValidator(_blockTree, NullSealEngine.Instance, MainnetSpecProvider.Instance, LimboLogs.Instance); _validator = new BlockValidator(Always.Valid, headerValidator, Always.Valid, MainnetSpecProvider.Instance, LimboLogs.Instance); }
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 void Test() { IBlockTree blockchain = Substitute.For <IBlockTree>(); HeaderValidator headerValidator = new HeaderValidator(new DifficultyCalculator(RopstenSpecProvider.Instance), blockchain, NullSealEngine.Instance, null, null); OmmersValidator ommersValidator = new OmmersValidator(blockchain, headerValidator, null); SignatureValidator signatureValidator = new SignatureValidator(ChainId.MainNet); TransactionValidator transactionValidator = new TransactionValidator(signatureValidator); BlockValidator blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, RopstenSpecProvider.Instance, null); }
public static void CheckBlockSignature() { // validate all block signatures var store = new BlockStore(TestDataLocations.BlockFolderLocation, Network.Main); foreach (var block in store.EnumerateFolder().Take(30000)) { Assert.True(BlockValidator.CheckBlockSignature(block.Item)); } }
public Blockchain CreateBlockchain() { var transactionsRepository = new TransactionsRepository(); var pendingTransactionRepository = new PendingTransactionRepository(); var transactionValidator = new TransactionValidator(transactionsRepository); var blockValidator = new BlockValidator(transactionValidator); var blockRepository = new Blockchain(transactionsRepository, pendingTransactionRepository, blockValidator, transactionValidator); return(blockRepository); }
public ulong GetStakeWeight() { // Choose coins to use var nBalance = this.GetBalance(); if (nBalance <= this.reserveBalance) { return(0); } List <WalletTx> vwtxPrev = new List <WalletTx>(); List <WalletTx> setCoins; long nValueIn = 0; if (!SelectCoinsForStaking(nBalance - this.reserveBalance, (uint)DateTime.UtcNow.ToUnixTimestamp(), out setCoins, out nValueIn)) { return(0); } if (setCoins.Empty()) { return(0); } ulong nWeight = 0; var nCurrentTime = (uint)DateTime.UtcNow.ToUnixTimestamp(); foreach (var pcoin in setCoins) { if (BlockValidator.IsProtocolV3((int)nCurrentTime)) { if (this.GetDepthInMainChain(pcoin) >= BlockValidator.StakeMinConfirmations) { nWeight += pcoin.TxOut.Value; } } else { if (nCurrentTime - pcoin.Transaction.Time > BlockValidator.StakeMinAge) { nWeight += pcoin.TxOut.Value; } } } return(nWeight); }
protected override void Work() { while (this.NotCanceled()) { // this method blocks this.WaitForDownLoadMode(); // take from the blocking collection var broadcastItem = this.BlockSyncHub.GetDataItems.Take(this.Context.CancellationToken); // only processes block types foreach (var source in broadcastItem.Payload.Inventory.Where(inv => inv.Type == InventoryType.MSG_BLOCK)) { var block = this.chainIndex.GetFullBlock(source.Hash); // check if the mined blocs have been requested if (block == null) { block = this.minerService.MinedBlocks.Where(k => k.Key.HashBlock == source.Hash).Select(s => s.Value).FirstOrDefault(); } if (block != null) { // previous versions could accept sigs with high s if (!BlockValidator.IsCanonicalBlockSignature(block, true)) { if (!BlockValidator.EnsureLowS(block.BlockSignatur)) { throw new HubException(); } } broadcastItem.Node.SendMessage(new BlockPayload(block)); //// Trigger them to send a getblocks request for the next batch of inventory //if (broadcastItem.Payload.hash == pfrom->hashContinue) //{ // // Bypass PushInventory, this must send even if redundant, // // and we want it right after the last block so they don't // // wait for other stuff first. // vector<CInv> vInv; // vInv.push_back(CInv(MSG_BLOCK, hashBestChain)); // pfrom->PushMessage("inv", vInv); // pfrom->hashContinue = 0; //} } } } }
public void IndexTheFullChain() { var store = new BlockStore(TestDataLocations.BlockFolderLocation, Network.StratisMain); var indexStore = new IndexedBlockStore(new InMemoryNoSqlRepository(), store); var reindexed = indexStore.ReIndex(); Assert.Equal(103952, reindexed); ConcurrentChain chain = store.GetChain(); foreach (ChainedBlock item in chain.ToEnumerable(false)) { Block block = indexStore.Get(item.HashBlock); Assert.True(BlockValidator.CheckBlock(block)); } }
public void When_more_uncles_than_allowed_returns_false() { TxValidator txValidator = new TxValidator(ChainId.MainNet); ReleaseSpec releaseSpec = new ReleaseSpec(); releaseSpec.MaximumUncleCount = 0; ISpecProvider specProvider = new CustomSpecProvider((0, releaseSpec)); BlockValidator blockValidator = new BlockValidator(txValidator, AlwaysValidHeaderValidator.Instance, AlwaysValidOmmersValidator.Instance, specProvider, LimboLogs.Instance); bool noiseRemoved = blockValidator.ValidateSuggestedBlock(Build.A.Block.TestObject); Assert.True(noiseRemoved); bool result = blockValidator.ValidateSuggestedBlock(Build.A.Block.WithOmmers(Build.A.BlockHeader.TestObject).TestObject); Assert.False(result); }
private List <Output> AvailableCoinsForStaking(uint nSpendTime) { var vCoins = new List <Output>(); foreach (var pcoin in this.walletStore.Wallet.WalletsList.Values) { int nDepth = this.GetDepthInMainChain(pcoin); if (nDepth < 1) { continue; } if (BlockValidator.IsProtocolV3((int)nSpendTime)) { if (nDepth < BlockValidator.StakeMinConfirmations) { continue; } } else { // Filtering by tx timestamp instead of block timestamp may give false positives but never false negatives if (pcoin.Transaction.Time + BlockValidator.StakeMinAge > nSpendTime) { continue; } } if (this.GetBlocksToMaturity(pcoin) > 0) { continue; } //for (int i = 0; i < pcoin.Transaction.Outputs.Count; i++) if (pcoin.SpentTransactionid == uint256.Zero && pcoin.TxOut.Value >= this.minimumInputValue) { // check if the coin is already staking //if (!this.minerService.IsStaking(pcoin.Transactionid, pcoin.OutputIndex)) vCoins.Add(new Output { Depth = nDepth, WalletTx = pcoin }); } } return(vCoins); }
private List <StakeOutput> AvailableCoinsForStaking(List <StakeTx> stakeTxes, uint nSpendTime) { var vCoins = new List <StakeOutput>(); foreach (var pcoin in stakeTxes) { int nDepth = this.GetDepthInMainChain(pcoin); if (nDepth < 1) { continue; } if (BlockValidator.IsProtocolV3((int)nSpendTime)) { if (nDepth < this.network.Consensus.Option <PosConsensusOptions>().StakeMinConfirmations) { continue; } } else { // Filtering by tx timestamp instead of block timestamp may give false positives but never false negatives if (pcoin.UtxoSet.Time + this.network.Consensus.Option <PosConsensusOptions>().StakeMinAge > nSpendTime) { continue; } } if (this.GetBlocksToMaturity(pcoin) > 0) { continue; } if (pcoin.TxOut.Value >= this.minimumInputValue) { // check if the coin is already staking vCoins.Add(new StakeOutput { Depth = nDepth, StakeTx = pcoin }); } } return(vCoins); }
public void Will_not_reject_block_with_bad_total_diff_but_will_reset_diff_to_null() { Context ctx = new Context(); BlockTree remoteBlockTree = Build.A.BlockTree().OfChainLength(10).TestObject; BlockTree localBlockTree = Build.A.BlockTree().OfChainLength(9).TestObject; HeaderValidator headerValidator = new HeaderValidator( localBlockTree, Always.Valid, MainnetSpecProvider.Instance, LimboLogs.Instance); BlockValidator blockValidator = new BlockValidator( Always.Valid, headerValidator, Always.Valid, MainnetSpecProvider.Instance, LimboLogs.Instance); ctx.SyncServer = new SyncServer( new MemDb(), new MemDb(), localBlockTree, NullReceiptStorage.Instance, blockValidator, Always.Valid, ctx.PeerPool, StaticSelector.Full, new SyncConfig(), NullWitnessCollector.Instance, LimboLogs.Instance); Block block = remoteBlockTree.FindBlock(9, BlockTreeLookupOptions.None); block.Header.TotalDifficulty *= 2; ctx.SyncServer.AddNewBlock(block, ctx.NodeWhoSentTheBlock); Assert.AreEqual(localBlockTree.BestSuggestedHeader.Hash, block.Header.Hash); Block parentBlock = remoteBlockTree.FindBlock(8, BlockTreeLookupOptions.None); Assert.AreEqual(parentBlock.TotalDifficulty + block.Difficulty, localBlockTree.BestSuggestedHeader.TotalDifficulty); }
public void ProcessNewBlock() { var TxsSize = 0; var block = new Block(); block.Index = BlockPool.Get().GetBlocks().Keys.Max() + 1; while (pool.Count > 0 && TxsSize < BlockTxLimit) { var next = GetNext(); block.AddTx(next); } if (!BlockValidator.IsValid(block)) { Console.WriteLine("Block is not valid"); return; } BlockPool.Get().AddBlock(block); }
public NodeService( KnownNodeStore knownNodeStore, NodeClientFactory nodeClientFactory, NodeClientStore nodeClientStore, VoteMemoryPool voteMemoryPool, Blockchain blockchain, Miner miner, VoteValidator voteValidator, BlockValidator blockValidator, BlockchainAdder blockchainAdder) { this.knownNodeStore = knownNodeStore; this.nodeClientFactory = nodeClientFactory; this.nodeClientStore = nodeClientStore; this.voteMemoryPool = voteMemoryPool; this.blockchain = blockchain; this.miner = miner; this.voteValidator = voteValidator; this.blockValidator = blockValidator; this.blockchainAdder = blockchainAdder; }
public double GetPoSKernelPS() { int nPoSInterval = 72; double dStakeKernelsTriedAvg = 0; int nStakesHandled = 0, nStakesTime = 0; ChainedBlock pindex = this.ChainIndex.Tip; ChainedBlock pindexPrevStake = null; while (pindex != null && nStakesHandled < nPoSInterval) { // todo: verify this does not require to be set by the block if (pindex.Header.PosParameters.IsProofOfStake()) { if (pindexPrevStake != null) { dStakeKernelsTriedAvg += this.GetDifficulty(pindexPrevStake) * 4294967296.0; nStakesTime += (int)pindexPrevStake.Header.Time - (int)pindex.Header.Time; nStakesHandled++; } pindexPrevStake = pindex; } pindex = pindex.Previous; } double result = 0; if (nStakesTime > 0) { result = dStakeKernelsTriedAvg / nStakesTime; } if (BlockValidator.IsProtocolV2(this.ChainIndex.Height)) { result *= BlockValidator.STAKE_TIMESTAMP_MASK + 1; } return(result); }
public bool CreateCoinStake(List <StakeTx> stakeTxes, ChainedBlock pindexBest, Block block, long nSearchInterval, long fees, ref Transaction txNew, ref Key key) { var pindexPrev = pindexBest; var bnTargetPerCoinDay = new Target(block.Header.Bits).ToCompact(); txNew.Inputs.Clear(); txNew.Outputs.Clear(); // Mark coin stake transaction txNew.Outputs.Add(new TxOut(Money.Zero, new Script())); // Choose coins to use var nBalance = this.GetBalance(stakeTxes).Satoshi; if (nBalance <= this.reserveBalance) { return(false); } List <StakeTx> vwtxPrev = new List <StakeTx>(); List <StakeTx> setCoins; long nValueIn = 0; // Select coins with suitable depth if (!SelectCoinsForStaking(stakeTxes, nBalance - this.reserveBalance, txNew.Time, out setCoins, out nValueIn)) { return(false); } //// check if coins are already staking //// this is different from the c++ implementation //// which pushes the new block to the main chain //// and removes it when a longer chain is found //foreach (var walletTx in setCoins.ToList()) // if (this.minerService.IsStaking(walletTx.TransactionHash, walletTx.OutputIndex)) // setCoins.Remove(walletTx); if (!setCoins.Any()) { return(false); } long nCredit = 0; Script scriptPubKeyKernel = null; // Note: I would expect to see coins sorted by weight on the original implementation // sort the coins from heighest weight setCoins = setCoins.OrderByDescending(o => o.TxOut.Value).ToList(); foreach (var coin in setCoins) { int maxStakeSearchInterval = 60; bool fKernelFound = false; for (uint n = 0; n < Math.Min(nSearchInterval, maxStakeSearchInterval) && !fKernelFound && pindexPrev == this.chain.Tip; n++) { try { var prevoutStake = new OutPoint(coin.UtxoSet.TransactionId, coin.OutputIndex); long nBlockTime = 0; var context = new ContextInformation(new BlockResult { Block = block }, network.Consensus); context.SetStake(); this.posConsensusValidator.StakeValidator.CheckKernel(context, pindexPrev, block.Header.Bits, txNew.Time - n, prevoutStake, ref nBlockTime); var timemaskceck = txNew.Time - n; if ((timemaskceck & PosConsensusValidator.STAKE_TIMESTAMP_MASK) != 0) { continue; } if (context.Stake.HashProofOfStake != null) { scriptPubKeyKernel = coin.TxOut.ScriptPubKey; key = null; // calculate the key type if (PayToPubkeyTemplate.Instance.CheckScriptPubKey(scriptPubKeyKernel)) { var outPubKey = scriptPubKeyKernel.GetDestinationAddress(this.network); key = coin.PrvKey; } else if (PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(scriptPubKeyKernel)) { var outPubKey = scriptPubKeyKernel.GetDestinationAddress(this.network); key = coin.PrvKey; } else { //LogPrint("coinstake", "CreateCoinStake : no support for kernel type=%d\n", whichType); break; // only support pay to public key and pay to address } // create a pubkey script form the current script var scriptPubKeyOut = PayToPubkeyTemplate.Instance.GenerateScriptPubKey(key.PubKey); //scriptPubKeyKernel; txNew.Time -= n; txNew.AddInput(new TxIn(prevoutStake)); nCredit += coin.TxOut.Value; vwtxPrev.Add(coin); txNew.Outputs.Add(new TxOut(0, scriptPubKeyOut)); //LogPrint("coinstake", "CreateCoinStake : added kernel type=%d\n", whichType); fKernelFound = true; break; } } catch (ConsensusErrorException cex) { if (cex.ConsensusError != ConsensusErrors.StakeHashInvalidTarget) { throw; } } } if (fKernelFound) { break; // if kernel is found stop searching } } if (nCredit == 0 || nCredit > nBalance - this.reserveBalance) { return(false); } foreach (var coin in setCoins) { var cointrx = coin; //var coinIndex = coin.Value; // Attempt to add more inputs // Only add coins of the same key/address as kernel if (txNew.Outputs.Count == 2 && ( cointrx.TxOut.ScriptPubKey == scriptPubKeyKernel || cointrx.TxOut.ScriptPubKey == txNew.Outputs[1].ScriptPubKey ) && cointrx.UtxoSet.TransactionId != txNew.Inputs[0].PrevOut.Hash) { long nTimeWeight = BlockValidator.GetWeight((long)cointrx.UtxoSet.Time, (long)txNew.Time); // Stop adding more inputs if already too many inputs if (txNew.Inputs.Count >= 100) { break; } // Stop adding inputs if reached reserve limit if (nCredit + cointrx.TxOut.Value > nBalance - this.reserveBalance) { break; } // Do not add additional significant input if (cointrx.TxOut.Value >= GetStakeCombineThreshold()) { continue; } // Do not add input that is still too young if (BlockValidator.IsProtocolV3((int)txNew.Time)) { // properly handled by selection function } else { if (nTimeWeight < BlockValidator.StakeMinAge) { continue; } } txNew.Inputs.Add(new TxIn(new OutPoint(cointrx.UtxoSet.TransactionId, cointrx.OutputIndex))); nCredit += cointrx.TxOut.Value; vwtxPrev.Add(coin); } } // Calculate coin age reward ulong nCoinAge; if (!this.posConsensusValidator.StakeValidator.GetCoinAge(this.chain, this.coinView, txNew, pindexPrev, out nCoinAge)) { return(false); //error("CreateCoinStake : failed to calculate coin age"); } long nReward = fees + this.posConsensusValidator.GetProofOfStakeReward(pindexPrev.Height); if (nReward <= 0) { return(false); } nCredit += nReward; if (nCredit >= GetStakeSplitThreshold()) { txNew.Outputs.Add(new TxOut(0, txNew.Outputs[1].ScriptPubKey)); //split stake } // Set output amount if (txNew.Outputs.Count == 3) { txNew.Outputs[1].Value = (nCredit / 2 / BlockValidator.CENT) * BlockValidator.CENT; txNew.Outputs[2].Value = nCredit - txNew.Outputs[1].Value; } else { txNew.Outputs[1].Value = nCredit; } // Sign foreach (var walletTx in vwtxPrev) { if (!SignSignature(walletTx, txNew)) { return(false); // error("CreateCoinStake : failed to sign coinstake"); } } // Limit size int nBytes = txNew.GetSerializedSize(ProtocolVersion.ALT_PROTOCOL_VERSION, SerializationType.Network); if (nBytes >= MAX_BLOCK_SIZE_GEN / 5) { return(false); // error("CreateCoinStake : exceeded coinstake size limit"); } // Successfully generated coinstake return(true); }
// To decrease granularity of timestamp // Supposed to be 2^n-1 private bool SignBlock(List <StakeTx> stakeTxes, Block block, ChainedBlock pindexBest, long fees) { // if we are trying to sign // something except proof-of-stake block template if (!block.Transactions[0].Outputs[0].IsEmpty) { return(false); } // if we are trying to sign // a complete proof-of-stake block if (BlockStake.IsProofOfStake(block)) { return(true); } Key key = null; Transaction txCoinStake = new Transaction(); txCoinStake.Time &= ~PosConsensusValidator.STAKE_TIMESTAMP_MASK; long searchTime = txCoinStake.Time; // search to current time if (searchTime > this.lastCoinStakeSearchTime) { long searchInterval = searchTime - this.lastCoinStakeSearchTime; if (this.CreateCoinStake(stakeTxes, pindexBest, block, searchInterval, fees, ref txCoinStake, ref key)) { if (txCoinStake.Time >= BlockValidator.GetPastTimeLimit(pindexBest) + 1) { // make sure coinstake would meet timestamp protocol // as it would be the same as the block timestamp block.Transactions[0].Time = block.Header.Time = txCoinStake.Time; // we have to make sure that we have no future timestamps in // our transactions set foreach (var transaction in block.Transactions) { if (transaction.Time > block.Header.Time) { block.Transactions.Remove(transaction); } } block.Transactions.Insert(1, txCoinStake); block.UpdateMerkleRoot(); // append a signature to our block var signature = key.Sign(block.GetHash()); block.BlockSignatur = new BlockSignature { Signature = signature.ToDER() }; return(true); } } this.LastCoinStakeSearchInterval = searchTime - this.LastCoinStakeSearchTime; this.LastCoinStakeSearchTime = searchTime; } return(false); }
private SyncTestContext CreateSyncManager(int index) { Rlp.RegisterDecoders(typeof(ParityTraceDecoder).Assembly); var logManager = NoErrorLimboLogs.Instance; ConsoleAsyncLogger logger = new ConsoleAsyncLogger(LogLevel.Debug, "PEER " + index + " "); // var logManager = new OneLoggerLogManager(logger); var specProvider = new SingleReleaseSpecProvider(ConstantinopleFix.Instance, MainNetSpecProvider.Instance.ChainId); MemDb traceDb = new MemDb(); MemDb blockDb = new MemDb(); MemDb headerDb = new MemDb(); MemDb blockInfoDb = new MemDb(); StateDb codeDb = new StateDb(); StateDb stateDb = new StateDb(); var stateProvider = new StateProvider(stateDb, codeDb, logManager); stateProvider.CreateAccount(TestItem.AddressA, 10000.Ether()); stateProvider.Commit(specProvider.GenesisSpec); stateProvider.CommitTree(); stateDb.Commit(); var storageProvider = new StorageProvider(stateDb, stateProvider, logManager); var receiptStorage = new InMemoryReceiptStorage(); var ecdsa = new EthereumEcdsa(specProvider, logManager); var txPool = new TxPool(new InMemoryTransactionStorage(), new PendingTransactionThresholdValidator(), new Timestamp(), ecdsa, specProvider, logManager); var tree = new BlockTree(blockDb, headerDb, blockInfoDb, specProvider, txPool, logManager); var blockhashProvider = new BlockhashProvider(tree, LimboLogs.Instance); var virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, logManager); var sealValidator = TestSealValidator.AlwaysValid; var headerValidator = new HeaderValidator(tree, sealValidator, specProvider, logManager); var txValidator = TestTxValidator.AlwaysValid; var ommersValidator = new OmmersValidator(tree, headerValidator, logManager); var blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, logManager); // var blockValidator = TestBlockValidator.AlwaysValid; SyncConfig syncConfig = new SyncConfig(); syncConfig.FastSync = _synchronizerType == SynchronizerType.Fast; var rewardCalculator = new RewardCalculator(specProvider); var txProcessor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, logManager); var blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, txProcessor, stateDb, codeDb, traceDb, stateProvider, storageProvider, txPool, receiptStorage, syncConfig, logManager); var step = new TxSignaturesRecoveryStep(ecdsa, txPool, logManager); var processor = new BlockchainProcessor(tree, blockProcessor, step, logManager, true, true); var nodeStatsManager = new NodeStatsManager(new StatsConfig(), logManager); var syncPeerPool = new EthSyncPeerPool(tree, nodeStatsManager, syncConfig, logManager); StateProvider devState = new StateProvider(stateDb, codeDb, logManager); StorageProvider devStorage = new StorageProvider(stateDb, devState, logManager); var devEvm = new VirtualMachine(devState, devStorage, blockhashProvider, logManager); var devTxProcessor = new TransactionProcessor(specProvider, devState, devStorage, devEvm, logManager); var devBlockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, devTxProcessor, stateDb, codeDb, traceDb, devState, devStorage, txPool, receiptStorage, syncConfig, logManager); var devChainProcessor = new BlockchainProcessor(tree, devBlockProcessor, step, logManager, false, false); var producer = new DevBlockProducer(txPool, devChainProcessor, tree, new Timestamp(), logManager); NodeDataFeed feed = new NodeDataFeed(codeDb, stateDb, logManager); NodeDataDownloader downloader = new NodeDataDownloader(syncPeerPool, feed, logManager); Synchronizer synchronizer = new Synchronizer( tree, blockValidator, sealValidator, syncPeerPool, syncConfig, downloader, logManager); var syncServer = new SyncServer(stateDb, codeDb, tree, receiptStorage, TestSealValidator.AlwaysValid, syncPeerPool, synchronizer, logManager); ManualResetEventSlim waitEvent = new ManualResetEventSlim(); tree.NewHeadBlock += (s, e) => waitEvent.Set(); if (index == 0) { _genesis = Build.A.Block.Genesis.WithStateRoot(stateProvider.StateRoot).TestObject; producer.Start(); } syncPeerPool.Start(); synchronizer.Start(); processor.Start(); tree.SuggestBlock(_genesis); if (!waitEvent.Wait(1000)) { throw new Exception("No genesis"); } SyncTestContext context = new SyncTestContext(); context.Ecdsa = ecdsa; context.BlockchainProcessor = processor; context.PeerPool = syncPeerPool; context.StateProvider = stateProvider; context.Synchronizer = synchronizer; context.SyncServer = syncServer; context.Tree = tree; context.BlockProducer = producer; context.TxPool = txPool; context.Logger = logger; return(context); }
public async Task Can_process_mined_blocks() { int timeMultiplier = 1; // for debugging TimeSpan miningDelay = TimeSpan.FromMilliseconds(50 * timeMultiplier); /* logging & instrumentation */ // OneLoggerLogManager logger = new OneLoggerLogManager(new SimpleConsoleLogger(true)); ILogManager logManager = NullLogManager.Instance; ILogger logger = logManager.GetClassLogger(); /* spec */ FakeSealer sealer = new FakeSealer(miningDelay); RopstenSpecProvider specProvider = RopstenSpecProvider.Instance; /* store & validation */ EthereumEcdsa ecdsa = new EthereumEcdsa(specProvider, logManager); MemDb receiptsDb = new MemDb(); MemDb traceDb = new MemDb(); TxPool txPool = new TxPool(NullTxStorage.Instance, Timestamp.Default, ecdsa, specProvider, new TxPoolConfig(), logManager); IReceiptStorage receiptStorage = new PersistentReceiptStorage(receiptsDb, NullDb.Instance, specProvider, logManager); BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), new MemDb(), specProvider, txPool, logManager); Timestamp timestamp = new Timestamp(); DifficultyCalculator difficultyCalculator = new DifficultyCalculator(specProvider); HeaderValidator headerValidator = new HeaderValidator(blockTree, sealer, specProvider, logManager); OmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, logManager); TxValidator txValidator = new TxValidator(ChainId.Ropsten); BlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, logManager); /* state & storage */ StateDb codeDb = new StateDb(); StateDb stateDb = new StateDb(); StateProvider stateProvider = new StateProvider(stateDb, codeDb, logManager); StorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, logManager); TestTransactionsGenerator generator = new TestTransactionsGenerator(txPool, ecdsa, TimeSpan.FromMilliseconds(5 * timeMultiplier), NullLogManager.Instance); generator.Start(); /* blockchain processing */ BlockhashProvider blockhashProvider = new BlockhashProvider(blockTree, LimboLogs.Instance); VirtualMachine virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, logManager); TransactionProcessor processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, logManager); RewardCalculator rewardCalculator = new RewardCalculator(specProvider); BlockProcessor blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, stateDb, codeDb, traceDb, stateProvider, storageProvider, txPool, receiptStorage, logManager); BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ecdsa, NullTxPool.Instance, LimboLogs.Instance), logManager, false, false); /* load ChainSpec and init */ ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = "chainspec.json"; logManager.GetClassLogger().Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllBytes(path)); foreach (var allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value.Balance); if (allocation.Value.Code != null) { Keccak codeHash = stateProvider.UpdateCode(allocation.Value.Code); stateProvider.UpdateCodeHash(allocation.Key, codeHash, specProvider.GenesisSpec); } } stateProvider.Commit(specProvider.GenesisSpec); chainSpec.Genesis.Header.StateRoot = stateProvider.StateRoot; // TODO: shall it be HeaderSpec and not BlockHeader? chainSpec.Genesis.Header.Hash = BlockHeader.CalculateHash(chainSpec.Genesis.Header); if (chainSpec.Genesis.Hash != new Keccak("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")) { throw new Exception("Unexpected genesis hash"); } /* start processing */ blockTree.SuggestBlock(chainSpec.Genesis); blockchainProcessor.Start(); MinedBlockProducer minedBlockProducer = new MinedBlockProducer(difficultyCalculator, txPool, blockchainProcessor, sealer, blockTree, timestamp, NullLogManager.Instance); minedBlockProducer.Start(); ManualResetEventSlim manualResetEvent = new ManualResetEventSlim(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 6) { manualResetEvent.Set(); } }; manualResetEvent.Wait(miningDelay * 12 * timeMultiplier); await minedBlockProducer.StopAsync(); int previousCount = 0; int totalTx = 0; for (int i = 0; i < 6; i++) { Block block = blockTree.FindBlock(i); logger.Info($"Block {i} with {block.Transactions.Length} txs"); ManualResetEventSlim blockProcessedEvent = new ManualResetEventSlim(false); blockchainProcessor.ProcessingQueueEmpty += (sender, args) => blockProcessedEvent.Set(); blockchainProcessor.SuggestBlock(block, ProcessingOptions.ForceProcessing | ProcessingOptions.StoreReceipts | ProcessingOptions.ReadOnlyChain); blockProcessedEvent.Wait(1000); Tracer tracer = new Tracer(blockchainProcessor, receiptStorage, blockTree, new MemDb()); int currentCount = receiptsDb.Keys.Count; logger.Info($"Current count of receipts {currentCount}"); logger.Info($"Previous count of receipts {previousCount}"); if (block.Transactions.Length > 0) { GethLikeTxTrace trace = tracer.Trace(block.Transactions[0].Hash); Assert.AreSame(GethLikeTxTrace.QuickFail, trace); Assert.AreNotEqual(previousCount, currentCount, $"receipts at block {i}"); totalTx += block.Transactions.Length; } previousCount = currentCount; } Assert.AreNotEqual(0, totalTx, "no tx in blocks"); }
protected async Task RunTest(LegacyBlockchainTest test, Stopwatch stopwatch = null) { TestContext.Write($"Running {test.Name} at {DateTime.UtcNow:HH:mm:ss.ffffff}"); Assert.IsNull(test.LoadFailure, "test data loading failure"); ISnapshotableDb stateDb = new StateDb(); ISnapshotableDb codeDb = new StateDb(); IDb traceDb = new MemDb(); ISpecProvider specProvider; if (test.NetworkAfterTransition != null) { specProvider = new CustomSpecProvider( (0, Frontier.Instance), (1, test.Network), (test.TransitionBlockNumber, test.NetworkAfterTransition)); } else { specProvider = new CustomSpecProvider( (0, Frontier.Instance), // TODO: this thing took a lot of time to find after it was removed!, genesis block is always initialized with Frontier (1, test.Network)); } if (specProvider.GenesisSpec != Frontier.Instance) { Assert.Fail("Expected genesis spec to be Frontier for blockchain tests"); } DifficultyCalculator.Wrapped = new DifficultyCalculator(specProvider); IRewardCalculator rewardCalculator = new RewardCalculator(specProvider); IEthereumEcdsa ecdsa = new EthereumEcdsa(specProvider, _logManager); IStateProvider stateProvider = new StateProvider(stateDb, codeDb, _logManager); ITxPool transactionPool = new TxPool(NullTxStorage.Instance, new Timestamper(), ecdsa, specProvider, new TxPoolConfig(), stateProvider, _logManager); IReceiptStorage receiptStorage = NullReceiptStorage.Instance; var blockInfoDb = new MemDb(); IBlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, transactionPool, _logManager); IBlockhashProvider blockhashProvider = new BlockhashProvider(blockTree, _logManager); ITxValidator txValidator = new TxValidator(ChainId.MainNet); IHeaderValidator headerValidator = new HeaderValidator(blockTree, Sealer, specProvider, _logManager); IOmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, _logManager); IBlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, _logManager); IStorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, _logManager); IVirtualMachine virtualMachine = new VirtualMachine( stateProvider, storageProvider, blockhashProvider, specProvider, _logManager); IBlockProcessor blockProcessor = new BlockProcessor( specProvider, blockValidator, rewardCalculator, new TransactionProcessor( specProvider, stateProvider, storageProvider, virtualMachine, _logManager), stateDb, codeDb, traceDb, stateProvider, storageProvider, transactionPool, receiptStorage, _logManager); IBlockchainProcessor blockchainProcessor = new BlockchainProcessor( blockTree, blockProcessor, new TxSignaturesRecoveryStep(ecdsa, NullTxPool.Instance, _logManager), _logManager, false, false); InitializeTestState(test, stateProvider, storageProvider, specProvider); List <(Block Block, string ExpectedException)> correctRlpsBlocks = new List <(Block, string)>(); for (int i = 0; i < test.Blocks.Length; i++) { try { TestBlockJson testBlockJson = test.Blocks[i]; var rlpContext = Bytes.FromHexString(testBlockJson.Rlp).AsRlpStream(); Block suggestedBlock = Rlp.Decode <Block>(rlpContext); suggestedBlock.Header.SealEngineType = test.SealEngineUsed ? SealEngineType.Ethash : SealEngineType.None; Assert.AreEqual(new Keccak(testBlockJson.BlockHeader.Hash), suggestedBlock.Header.Hash, "hash of the block"); for (int ommerIndex = 0; ommerIndex < suggestedBlock.Ommers.Length; ommerIndex++) { Assert.AreEqual(new Keccak(testBlockJson.UncleHeaders[ommerIndex].Hash), suggestedBlock.Ommers[ommerIndex].Hash, "hash of the ommer"); } correctRlpsBlocks.Add((suggestedBlock, testBlockJson.ExpectedException)); } catch (Exception) { _logger?.Info($"Invalid RLP ({i})"); } } if (correctRlpsBlocks.Count == 0) { Assert.AreEqual(new Keccak(test.GenesisBlockHeader.Hash), test.LastBlockHash); return; } if (test.GenesisRlp == null) { test.GenesisRlp = Rlp.Encode(new Block(JsonToBlockchainTest.Convert(test.GenesisBlockHeader))); } Block genesisBlock = Rlp.Decode <Block>(test.GenesisRlp.Bytes); Assert.AreEqual(new Keccak(test.GenesisBlockHeader.Hash), genesisBlock.Header.Hash, "genesis header hash"); ManualResetEvent genesisProcessed = new ManualResetEvent(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 0) { Assert.AreEqual(genesisBlock.Header.StateRoot, stateProvider.StateRoot, "genesis state root"); genesisProcessed.Set(); } }; blockchainProcessor.Start(); blockTree.SuggestBlock(genesisBlock); genesisProcessed.WaitOne(); for (int i = 0; i < correctRlpsBlocks.Count; i++) { stopwatch?.Start(); try { if (correctRlpsBlocks[i].ExpectedException != null) { _logger.Info($"Expecting block exception: {correctRlpsBlocks[i].ExpectedException}"); } if (correctRlpsBlocks[i].Block.Hash == null) { throw new Exception($"null hash in {test.Name} block {i}"); } // TODO: mimic the actual behaviour where block goes through validating sync manager? if (!test.SealEngineUsed || blockValidator.ValidateSuggestedBlock(correctRlpsBlocks[i].Block)) { blockTree.SuggestBlock(correctRlpsBlocks[i].Block); } else { Console.WriteLine("Invalid block"); } } catch (InvalidBlockException) { } catch (Exception ex) { _logger?.Info(ex.ToString()); } } await blockchainProcessor.StopAsync(true); stopwatch?.Stop(); List <string> differences = RunAssertions(test, blockTree.RetrieveHeadBlock(), storageProvider, stateProvider); // if (differences.Any()) // { // BlockTrace blockTrace = blockchainProcessor.TraceBlock(blockTree.BestSuggested.Hash); // _logger.Info(new UnforgivingJsonSerializer().Serialize(blockTrace, true)); // } Assert.Zero(differences.Count, "differences"); }
private void acrossTime(ulong startTime, ulong timeLen, BlockValidator validator, TimeOperation op) { for (ulong dt = 0; dt < timeLen; ) { int begin; EventToken[,] block; ulong time = startTime + dt; getBaseTime(time, out block, out begin); time -= (ulong)begin; if (!validator(ref block) || block == null) { dt = _history.Keys.Where(t => (t > time)) .DefaultIfEmpty(startTime + timeLen) .Min() - startTime; continue; } _history[time] = block; for (int blockIndex = begin; blockIndex < block.GetLength(1) && dt < timeLen; blockIndex++, dt++) { op(ref block, dt, blockIndex); } } }
private SyncTestContext CreateSyncManager(int index) { var logManager = NoErrorLimboLogs.Instance; ConsoleAsyncLogger logger = new ConsoleAsyncLogger(LogLevel.Debug, "PEER " + index + " "); // var logManager = new OneLoggerLogManager(logger); var specProvider = new SingleReleaseSpecProvider(ConstantinopleFix.Instance, MainnetSpecProvider.Instance.ChainId); var dbProvider = TestMemDbProvider.Init(); IDb blockDb = dbProvider.BlocksDb; IDb headerDb = dbProvider.HeadersDb; IDb blockInfoDb = dbProvider.BlockInfosDb; ISnapshotableDb codeDb = dbProvider.CodeDb; ISnapshotableDb stateDb = dbProvider.StateDb; var stateReader = new StateReader(stateDb, codeDb, logManager); var stateProvider = new StateProvider(stateDb, codeDb, logManager); stateProvider.CreateAccount(TestItem.AddressA, 10000.Ether()); stateProvider.Commit(specProvider.GenesisSpec); stateProvider.CommitTree(); stateProvider.RecalculateStateRoot(); stateDb.Commit(); var storageProvider = new StorageProvider(stateDb, stateProvider, logManager); var receiptStorage = new InMemoryReceiptStorage(); var ecdsa = new EthereumEcdsa(specProvider.ChainId, logManager); var txPool = new TxPool.TxPool(new InMemoryTxStorage(), ecdsa, specProvider, new TxPoolConfig(), stateProvider, logManager); var tree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, NullBloomStorage.Instance, logManager); var blockhashProvider = new BlockhashProvider(tree, LimboLogs.Instance); var virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, specProvider, logManager); var sealValidator = Always.Valid; var headerValidator = new HeaderValidator(tree, sealValidator, specProvider, logManager); var txValidator = Always.Valid; var ommersValidator = new OmmersValidator(tree, headerValidator, logManager); var blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, logManager); ISyncConfig syncConfig = _synchronizerType == SynchronizerType.Fast ? SyncConfig.WithFastSync : SyncConfig.WithFullSyncOnly; var rewardCalculator = new RewardCalculator(specProvider); var txProcessor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, logManager); var blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, txProcessor, stateDb, codeDb, stateProvider, storageProvider, txPool, receiptStorage, logManager); var step = new RecoverSignatures(ecdsa, txPool, specProvider, logManager); var processor = new BlockchainProcessor(tree, blockProcessor, step, logManager, BlockchainProcessor.Options.Default); var nodeStatsManager = new NodeStatsManager(logManager); var syncPeerPool = new SyncPeerPool(tree, nodeStatsManager, 25, logManager); StateProvider devState = new StateProvider(stateDb, codeDb, logManager); StorageProvider devStorage = new StorageProvider(stateDb, devState, logManager); var devEvm = new VirtualMachine(devState, devStorage, blockhashProvider, specProvider, logManager); var devTxProcessor = new TransactionProcessor(specProvider, devState, devStorage, devEvm, logManager); var devBlockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, devTxProcessor, stateDb, codeDb, devState, devStorage, txPool, receiptStorage, logManager); var devChainProcessor = new BlockchainProcessor(tree, devBlockProcessor, step, logManager, BlockchainProcessor.Options.NoReceipts); var transactionSelector = new TxPoolTxSource(txPool, stateReader, logManager); var producer = new DevBlockProducer( transactionSelector, devChainProcessor, stateProvider, tree, processor, txPool, Timestamper.Default, logManager); SyncProgressResolver resolver = new SyncProgressResolver(tree, receiptStorage, stateDb, new MemDb(), syncConfig, logManager); MultiSyncModeSelector selector = new MultiSyncModeSelector(resolver, syncPeerPool, syncConfig, logManager); Synchronizer synchronizer = new Synchronizer( dbProvider, MainnetSpecProvider.Instance, tree, NullReceiptStorage.Instance, blockValidator, sealValidator, syncPeerPool, nodeStatsManager, StaticSelector.Full, syncConfig, logManager); var syncServer = new SyncServer(stateDb, codeDb, tree, receiptStorage, Always.Valid, Always.Valid, syncPeerPool, selector, syncConfig, logManager); ManualResetEventSlim waitEvent = new ManualResetEventSlim(); tree.NewHeadBlock += (s, e) => waitEvent.Set(); if (index == 0) { _genesis = Build.A.Block.Genesis.WithStateRoot(stateProvider.StateRoot).TestObject; producer.Start(); } syncPeerPool.Start(); synchronizer.Start(); processor.Start(); tree.SuggestBlock(_genesis); if (!waitEvent.Wait(1000)) { throw new Exception("No genesis"); } SyncTestContext context = new SyncTestContext(); context.Ecdsa = ecdsa; context.BlockchainProcessor = processor; context.PeerPool = syncPeerPool; context.StateProvider = stateProvider; context.Synchronizer = synchronizer; context.SyncServer = syncServer; context.Tree = tree; context.BlockProducer = producer; context.TxPool = txPool; context.Logger = logger; return(context); }
// It takes dotCover to run it quite long, increased timeouts public async Task Can_process_mined_blocks() { int timeMultiplier = 1; // for debugging TimeSpan miningDelay = TimeSpan.FromMilliseconds(200 * timeMultiplier); /* logging & instrumentation */ // OneLoggerLogManager logger = new OneLoggerLogManager(new SimpleConsoleLogger(true)); ILogManager logManager = LimboLogs.Instance; ILogger logger = logManager.GetClassLogger(); /* spec */ FakeSealer sealer = new FakeSealer(miningDelay); RopstenSpecProvider specProvider = RopstenSpecProvider.Instance; /* state & storage */ StateDb codeDb = new StateDb(); StateDb stateDb = new StateDb(); StateProvider stateProvider = new StateProvider(stateDb, codeDb, logManager); StorageProvider storageProvider = new StorageProvider(stateDb, stateProvider, logManager); /* store & validation */ EthereumEcdsa ecdsa = new EthereumEcdsa(specProvider, logManager); MemDb receiptsDb = new MemDb(); TxPool.TxPool txPool = new TxPool.TxPool(NullTxStorage.Instance, Timestamper.Default, ecdsa, specProvider, new TxPoolConfig(), stateProvider, logManager); IReceiptStorage receiptStorage = new PersistentReceiptStorage(receiptsDb, specProvider, logManager); var blockInfoDb = new MemDb(); BlockTree blockTree = new BlockTree(new MemDb(), new MemDb(), blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), specProvider, txPool, NullBloomStorage.Instance, logManager); Timestamper timestamper = new Timestamper(); DifficultyCalculator difficultyCalculator = new DifficultyCalculator(specProvider); HeaderValidator headerValidator = new HeaderValidator(blockTree, sealer, specProvider, logManager); OmmersValidator ommersValidator = new OmmersValidator(blockTree, headerValidator, logManager); TxValidator txValidator = new TxValidator(ChainId.Ropsten); BlockValidator blockValidator = new BlockValidator(txValidator, headerValidator, ommersValidator, specProvider, logManager); TestTransactionsGenerator generator = new TestTransactionsGenerator(txPool, ecdsa, TimeSpan.FromMilliseconds(50 * timeMultiplier), LimboLogs.Instance); generator.Start(); /* blockchain processing */ BlockhashProvider blockhashProvider = new BlockhashProvider(blockTree, LimboLogs.Instance); VirtualMachine virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, specProvider, logManager); TransactionProcessor processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, logManager); RewardCalculator rewardCalculator = new RewardCalculator(specProvider); BlockProcessor blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, stateDb, codeDb, stateProvider, storageProvider, txPool, receiptStorage, logManager); BlockchainProcessor blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, new TxSignaturesRecoveryStep(ecdsa, NullTxPool.Instance, LimboLogs.Instance), logManager, false); /* load ChainSpec and init */ ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = "chainspec.json"; logManager.GetClassLogger().Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); foreach (var allocation in chainSpec.Allocations) { stateProvider.CreateAccount(allocation.Key, allocation.Value.Balance); if (allocation.Value.Code != null) { Keccak codeHash = stateProvider.UpdateCode(allocation.Value.Code); stateProvider.UpdateCodeHash(allocation.Key, codeHash, specProvider.GenesisSpec); } } stateProvider.Commit(specProvider.GenesisSpec); chainSpec.Genesis.Header.StateRoot = stateProvider.StateRoot; chainSpec.Genesis.Header.Hash = chainSpec.Genesis.Header.CalculateHash(); if (chainSpec.Genesis.Hash != new Keccak("0xafbc3c327d2d18ff2b843e89226ef288fcee379542f854f982e4cfb85916d126")) { throw new Exception("Unexpected genesis hash"); } /* start processing */ blockTree.SuggestBlock(chainSpec.Genesis); blockchainProcessor.Start(); var transactionSelector = new PendingTxSelector(txPool, stateProvider, logManager); MinedBlockProducer minedBlockProducer = new MinedBlockProducer(transactionSelector, blockchainProcessor, sealer, blockTree, blockchainProcessor, stateProvider, timestamper, LimboLogs.Instance, difficultyCalculator); minedBlockProducer.Start(); ManualResetEventSlim manualResetEvent = new ManualResetEventSlim(false); blockTree.NewHeadBlock += (sender, args) => { if (args.Block.Number == 6) { manualResetEvent.Set(); } }; manualResetEvent.Wait(miningDelay * 100); await minedBlockProducer.StopAsync(); int previousCount = 0; int totalTx = 0; for (int i = 0; i < 6; i++) { Block block = blockTree.FindBlock(i, BlockTreeLookupOptions.None); Assert.That(block, Is.Not.Null, $"Block {i} not produced"); logger.Info($"Block {i} with {block.Transactions.Length} txs"); ManualResetEventSlim blockProcessedEvent = new ManualResetEventSlim(false); blockchainProcessor.ProcessingQueueEmpty += (sender, args) => blockProcessedEvent.Set(); blockchainProcessor.Enqueue(block, ProcessingOptions.ForceProcessing | ProcessingOptions.StoreReceipts | ProcessingOptions.ReadOnlyChain); blockProcessedEvent.Wait(miningDelay); GethStyleTracer gethStyleTracer = new GethStyleTracer(blockchainProcessor, receiptStorage, blockTree); int currentCount = receiptsDb.Keys.Count; logger.Info($"Current count of receipts {currentCount}"); logger.Info($"Previous count of receipts {previousCount}"); if (block.Transactions.Length > 0) { Assert.AreNotEqual(previousCount, currentCount, $"receipts at block {i}"); totalTx += block.Transactions.Length; } previousCount = currentCount; } Assert.AreNotEqual(0, totalTx, "no tx in blocks"); }
private static async Task RunBenchmarkBlocks() { Rlp.RegisterDecoders(typeof(ParityTraceDecoder).Assembly); /* logging & instrumentation */ _logManager = new NLogManager("perfTest.logs.txt", null); _logger = _logManager.GetClassLogger(); if (_logger.IsInfo) { _logger.Info("Deleting state DBs"); } DeleteDb(FullStateDbPath); DeleteDb(FullCodeDbPath); DeleteDb(FullReceiptsDbPath); DeleteDb(FullPendingTxsDbPath); if (_logger.IsInfo) { _logger.Info("State DBs deleted"); } /* load spec */ ChainSpecLoader loader = new ChainSpecLoader(new EthereumJsonSerializer()); string path = Path.Combine(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"chainspec", "ropsten.json")); _logger.Info($"Loading ChainSpec from {path}"); ChainSpec chainSpec = loader.Load(File.ReadAllText(path)); _logger.Info($"ChainSpec loaded"); var specProvider = new ChainSpecBasedSpecProvider(chainSpec); IRewardCalculator rewardCalculator = new RewardCalculator(specProvider); var dbProvider = new RocksDbProvider(DbBasePath, DbConfig.Default, _logManager, true, true); var stateDb = dbProvider.StateDb; var codeDb = dbProvider.CodeDb; var traceDb = dbProvider.TraceDb; var blocksDb = dbProvider.BlocksDb; var headersDb = dbProvider.HeadersDb; var blockInfosDb = dbProvider.BlockInfosDb; var receiptsDb = dbProvider.ReceiptsDb; /* state & storage */ var stateProvider = new StateProvider(stateDb, codeDb, _logManager); var storageProvider = new StorageProvider(stateDb, stateProvider, _logManager); var ethereumSigner = new EthereumEcdsa(specProvider, _logManager); var transactionPool = new TxPool( NullTxStorage.Instance, Timestamper.Default, ethereumSigner, specProvider, new TxPoolConfig(), stateProvider, _logManager); var blockInfoRepository = new ChainLevelInfoRepository(blockInfosDb); var blockTree = new UnprocessedBlockTreeWrapper(new BlockTree(blocksDb, headersDb, blockInfosDb, blockInfoRepository, specProvider, transactionPool, _logManager)); var receiptStorage = new InMemoryReceiptStorage(); IBlockDataRecoveryStep recoveryStep = new TxSignaturesRecoveryStep(ethereumSigner, transactionPool, _logManager); /* blockchain processing */ IList <IAdditionalBlockProcessor> blockProcessors = new List <IAdditionalBlockProcessor>(); var blockhashProvider = new BlockhashProvider(blockTree, LimboLogs.Instance); var virtualMachine = new VirtualMachine(stateProvider, storageProvider, blockhashProvider, specProvider, _logManager); var processor = new TransactionProcessor(specProvider, stateProvider, storageProvider, virtualMachine, _logManager); ISealValidator sealValidator; if (specProvider.ChainId == RopstenSpecProvider.Instance.ChainId) { var difficultyCalculator = new DifficultyCalculator(specProvider); sealValidator = new EthashSealValidator(_logManager, difficultyCalculator, new Ethash(_logManager)); } else if (chainSpec.SealEngineType == SealEngineType.Clique) { var snapshotManager = new SnapshotManager(CliqueConfig.Default, blocksDb, blockTree, ethereumSigner, _logManager); sealValidator = new CliqueSealValidator(CliqueConfig.Default, snapshotManager, _logManager); rewardCalculator = NoBlockRewards.Instance; recoveryStep = new CompositeDataRecoveryStep(recoveryStep, new AuthorRecoveryStep(snapshotManager)); } else if (chainSpec.SealEngineType == SealEngineType.AuRa) { var abiEncoder = new AbiEncoder(); var validatorProcessor = new AuRaAdditionalBlockProcessorFactory(dbProvider.StateDb, stateProvider, abiEncoder, processor, blockTree, receiptStorage, _logManager) .CreateValidatorProcessor(chainSpec.AuRa.Validators); sealValidator = new AuRaSealValidator(chainSpec.AuRa, new AuRaStepCalculator(chainSpec.AuRa.StepDuration, new Timestamper()), validatorProcessor, ethereumSigner, _logManager); rewardCalculator = new AuRaRewardCalculator(chainSpec.AuRa, abiEncoder, processor); blockProcessors.Add(validatorProcessor); } else { throw new NotSupportedException(); } /* store & validation */ var headerValidator = new HeaderValidator(blockTree, sealValidator, specProvider, _logManager); var ommersValidator = new OmmersValidator(blockTree, headerValidator, _logManager); var transactionValidator = new TxValidator(chainSpec.ChainId); var blockValidator = new BlockValidator(transactionValidator, headerValidator, ommersValidator, specProvider, _logManager); /* blockchain processing */ var blockProcessor = new BlockProcessor(specProvider, blockValidator, rewardCalculator, processor, stateDb, codeDb, traceDb, stateProvider, storageProvider, transactionPool, receiptStorage, _logManager, blockProcessors); var blockchainProcessor = new BlockchainProcessor(blockTree, blockProcessor, recoveryStep, _logManager, true, false); if (chainSpec.SealEngineType == SealEngineType.AuRa) { stateProvider.CreateAccount(Address.Zero, UInt256.Zero); storageProvider.Commit(); stateProvider.Commit(Homestead.Instance); var finalizationManager = new AuRaBlockFinalizationManager(blockTree, blockInfoRepository, blockProcessor, blockProcessors.OfType <IAuRaValidator>().First(), _logManager); } foreach ((Address address, ChainSpecAllocation allocation) in chainSpec.Allocations) { stateProvider.CreateAccount(address, allocation.Balance); if (allocation.Code != null) { Keccak codeHash = stateProvider.UpdateCode(allocation.Code); stateProvider.UpdateCodeHash(address, codeHash, specProvider.GenesisSpec); } if (allocation.Constructor != null) { Transaction constructorTransaction = new Transaction(true) { SenderAddress = address, Init = allocation.Constructor, GasLimit = chainSpec.Genesis.GasLimit }; processor.Execute(constructorTransaction, chainSpec.Genesis.Header, NullTxTracer.Instance); } } _logger.Info($"Allocations configured, committing..."); stateProvider.Commit(specProvider.GenesisSpec); _logger.Info($"Finalizing genesis..."); chainSpec.Genesis.Header.StateRoot = stateProvider.StateRoot; chainSpec.Genesis.Header.Hash = BlockHeader.CalculateHash(chainSpec.Genesis.Header); if (chainSpec.Genesis.Hash != blockTree.Genesis.Hash) { throw new Exception("Unexpected genesis hash"); } _logger.Info($"Starting benchmark processor..."); /* start processing */ BigInteger totalGas = BigInteger.Zero; Stopwatch stopwatch = new Stopwatch(); Block currentHead; long maxMemory = 0; blockTree.NewHeadBlock += (sender, args) => { currentHead = args.Block; if (currentHead.Number == 0) { return; } maxMemory = Math.Max(maxMemory, GC.GetTotalMemory(false)); totalGas += currentHead.GasUsed; if ((BigInteger)args.Block.Number % 10000 == 9999) { stopwatch.Stop(); long ms = 1_000L * stopwatch.ElapsedTicks / Stopwatch.Frequency; BigInteger number = args.Block.Number + 1; _logger.Warn($"TOTAL after {number} (ms) : " + ms); _logger.Warn($"TOTAL after {number} blocks/s : {(decimal) currentHead.Number / (ms / 1000m),5}"); _logger.Warn($"TOTAL after {number} Mgas/s : {((decimal) totalGas / 1000000) / (ms / 1000m),5}"); _logger.Warn($"TOTAL after {number} max mem : {maxMemory}"); _logger.Warn($"TOTAL after {number} GC (0/1/2) : {GC.CollectionCount(0)}/{GC.CollectionCount(1)}/{GC.CollectionCount(2)}"); _logger.Warn($"Is server GC {number} : {System.Runtime.GCSettings.IsServerGC}"); _logger.Warn($"GC latency mode {number} : {System.Runtime.GCSettings.LatencyMode}"); _logger.Warn($"TOTAL after {number} blocks DB reads : {Store.Metrics.BlocksDbReads}"); _logger.Warn($"TOTAL after {number} blocks DB writes : {Store.Metrics.BlocksDbWrites}"); _logger.Warn($"TOTAL after {number} infos DB reads : {Store.Metrics.BlockInfosDbReads}"); _logger.Warn($"TOTAL after {number} infos DB writes : {Store.Metrics.BlockInfosDbWrites}"); _logger.Warn($"TOTAL after {number} state tree reads : {Store.Metrics.StateTreeReads}"); _logger.Warn($"TOTAL after {number} state tree writes : {Store.Metrics.StateTreeWrites}"); _logger.Warn($"TOTAL after {number} state DB reads : {Store.Metrics.StateDbReads}"); _logger.Warn($"TOTAL after {number} state DB writes : {Store.Metrics.StateDbWrites}"); _logger.Warn($"TOTAL after {number} storage tree reads : {Store.Metrics.StorageTreeReads}"); _logger.Warn($"TOTAL after {number} storage tree writes : {Store.Metrics.StorageTreeWrites}"); _logger.Warn($"TOTAL after {number} tree node hash : {Store.Metrics.TreeNodeHashCalculations}"); _logger.Warn($"TOTAL after {number} tree node RLP decode : {Store.Metrics.TreeNodeRlpDecodings}"); _logger.Warn($"TOTAL after {number} tree node RLP encode : {Store.Metrics.TreeNodeRlpEncodings}"); _logger.Warn($"TOTAL after {number} code DB reads : {Store.Metrics.CodeDbReads}"); _logger.Warn($"TOTAL after {number} code DB writes : {Store.Metrics.CodeDbWrites}"); _logger.Warn($"TOTAL after {number} receipts DB reads : {Store.Metrics.ReceiptsDbReads}"); _logger.Warn($"TOTAL after {number} receipts DB writes : {Store.Metrics.ReceiptsDbWrites}"); _logger.Warn($"TOTAL after {number} other DB reads : {Store.Metrics.OtherDbReads}"); _logger.Warn($"TOTAL after {number} other DB writes : {Store.Metrics.OtherDbWrites}"); _logger.Warn($"TOTAL after {number} EVM exceptions : {Evm.Metrics.EvmExceptions}"); _logger.Warn($"TOTAL after {number} SLOAD opcodes : {Evm.Metrics.SloadOpcode}"); _logger.Warn($"TOTAL after {number} SSTORE opcodes : {Evm.Metrics.SstoreOpcode}"); _logger.Warn($"TOTAL after {number} EXP opcodes : {Evm.Metrics.ModExpOpcode}"); _logger.Warn($"TOTAL after {number} BLOCKHASH opcodes : {Evm.Metrics.BlockhashOpcode}"); _logger.Warn($"TOTAL after {number} EVM calls : {Evm.Metrics.Calls}"); _logger.Warn($"TOTAL after {number} RIPEMD Precompiles : {Evm.Metrics.Ripemd160Precompile}"); _logger.Warn($"TOTAL after {number} SHA256 Precompiles : {Evm.Metrics.Sha256Precompile}"); // disk space stopwatch.Start(); } }; bool isStarted = false; TaskCompletionSource <object> completionSource = new TaskCompletionSource <object>(); blockTree.NewBestSuggestedBlock += (sender, args) => { if (!isStarted) { blockchainProcessor.Process(blockTree.FindBlock(blockTree.Genesis.Hash, BlockTreeLookupOptions.RequireCanonical), ProcessingOptions.None, NullBlockTracer.Instance); stopwatch.Start(); blockchainProcessor.Start(); isStarted = true; } if (args.Block.Number == BlocksToLoad) { completionSource.SetResult(null); } }; await Task.WhenAny(completionSource.Task, blockTree.LoadBlocksFromDb(CancellationToken.None, 0, 10000, BlocksToLoad)); await blockchainProcessor.StopAsync(true).ContinueWith( t => { if (t.IsFaulted) { _logger.Error("processing failed", t.Exception); _logger.Error("inner", t.Exception.InnerException); Console.ReadLine(); } _logger.Info("Block processing completed."); }); stopwatch.Stop(); Console.ReadLine(); }
public static void Main(string[] args) { var password = args[0]; var dbFilepath = args[1]; var port = int.Parse(args[2]); var voterDb = new VoterDatabaseFacade(dbFilepath); var foundMiner = voterDb.TryGetVoterEncryptedKeyPair(password, out var encryptedKeyPair); if (!foundMiner) { Console.WriteLine("incorrect password: you may not mine!"); return; } var blockchain = new Blockchain(); // networking var registrarClientFactory = new RegistrarClientFactory(); var registrarClient = registrarClientFactory.Build(Localhost, RegistrarPort); var registrationRequestFactory = new RegistrationRequestFactory(); var myConnectionInfo = new NodeConnectionInfo(Localhost, port); var knownNodeStore = new KnownNodeStore(); var nodeClientFactory = new NodeClientFactory(); var handshakeRequestFactory = new HandshakeRequestFactory(blockchain); var nodeClientStore = new NodeClientStore(); var nodeServerFactory = new NodeServerFactory(); // votes var protoVoteFactory = new ProtoVoteFactory(); var voteForwarder = new VoteForwarder(nodeClientStore, protoVoteFactory); var voteMemoryPool = new VoteMemoryPool(voteForwarder); // blocks var merkleNodeFactory = new MerkleNodeFactory(); var merkleTreeFactory = new MerkleTreeFactory(merkleNodeFactory); var minerId = encryptedKeyPair.PublicKey.GetBase64String(); var blockFactory = new BlockFactory(merkleTreeFactory, minerId); var protoBlockFactory = new ProtoBlockFactory(protoVoteFactory); var blockForwarder = new BlockForwarder(nodeClientStore, protoBlockFactory); var voteValidator = new VoteValidator(blockchain, voterDb); var blockValidator = new BlockValidator(blockFactory, voteValidator); var blockchainAdder = new BlockchainAdder(blockchain, voteMemoryPool, blockForwarder); // mining var difficultyTarget = TargetFactory.Build(BlockHeader.DefaultBits); var miner = new Miner( blockchain, voteMemoryPool, difficultyTarget, blockFactory, blockchainAdder); // startup var nodeServer = nodeServerFactory.Build( myConnectionInfo, knownNodeStore, nodeClientFactory, nodeClientStore, voteMemoryPool, blockchain, miner, voteValidator, blockValidator, blockchainAdder); var boostrapper = new Bootstrapper( MinNetworkSize, knownNodeStore, nodeClientFactory, handshakeRequestFactory, nodeClientStore, registrarClient, registrationRequestFactory, nodeServer); Console.WriteLine("bootstrapping node network..."); boostrapper.Bootstrap(myConnectionInfo); Console.WriteLine($"{MinNetworkSize} nodes in network! bootstrapping complete"); Console.WriteLine("starting miner..."); miner.Start(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine("Press any key to quit"); Console.ReadKey(); }