Пример #1
0
        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);
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        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();
        }
Пример #4
0
        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);
        }
Пример #5
0
        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 });
                }
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
        }
Пример #8
0
        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);
                }
            }
        }
Пример #9
0
        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);
        }
Пример #10
0
        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));
            }
        }
Пример #11
0
        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);
        }
Пример #12
0
        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);
        }
Пример #13
0
        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;
                        //}
                    }
                }
            }
        }
Пример #14
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));
            }
        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
        }
Пример #17
0
        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);
        }
Пример #18
0
        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);
        }
Пример #19
0
        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);
        }
Пример #20
0
 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;
 }
Пример #21
0
        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);
        }
Пример #22
0
        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);
        }
Пример #23
0
        // 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);
        }
Пример #24
0
        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);
        }
Пример #25
0
        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");
        }
Пример #26
0
        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");
        }
Пример #27
0
        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);
                }
            }
        }
Пример #28
0
        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);
        }
Пример #29
0
        // 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");
        }
Пример #30
0
        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();
        }
Пример #31
0
        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();
        }