public async Task StopAsync() { await(BlockchainProcessor?.StopAsync() ?? Task.CompletedTask); await(BlockProducer?.StopAsync() ?? Task.CompletedTask); await(PeerPool?.StopAsync() ?? Task.CompletedTask); await(Synchronizer?.StopAsync() ?? Task.CompletedTask); Logger?.Flush(); }
public BeaconNodeApiAdapter(ILogger <BeaconNodeApiAdapter> logger, BeaconNodeConfiguration beaconNodeConfiguration, BlockProducer blockProducer) { _logger = logger; _beaconNodeConfiguration = beaconNodeConfiguration; _blockProducer = blockProducer; }
public async Task AddBlock(params Transaction[] transactions) { foreach (Transaction transaction in transactions) { TxPool.AddTransaction(transaction, TxHandlingOptions.None); } Timestamper.Add(TimeSpan.FromSeconds(1)); BlockProducer.BuildNewBlock(); await _resetEvent.WaitOneAsync(CancellationToken.None); }
private async Task AddBlockInternal(params Transaction[] transactions) { await _oneAtATime.WaitOneAsync(CancellationToken.None); foreach (Transaction transaction in transactions) { TxPool.AddTransaction(transaction, TxHandlingOptions.None); } Timestamper.Add(TimeSpan.FromSeconds(1)); BlockProducer.BuildNewBlock(); }
public virtual void Dispose() { BlockProducer?.StopAsync(); CodeDb?.Dispose(); StateDb?.Dispose(); }
private Round GenerateNextRoundOrder() { try { var infosOfNextRound = new Round(); var signatureDict = new Dictionary <Hash, string>(); var orderDict = new Dictionary <int, string>(); var blockProducerCount = _miners.Nodes.Count; foreach (var node in _miners.Nodes) { var s = this[node].Signature; if (s == null) { s = Hash.Generate(); } signatureDict[s] = node; } foreach (var sig in signatureDict.Keys) { var sigNum = BitConverter.ToUInt64( BitConverter.IsLittleEndian ? sig.Value.Reverse().ToArray() : sig.Value.ToArray(), 0); var order = Math.Abs(GetModulus(sigNum, blockProducerCount)); if (orderDict.ContainsKey(order)) { for (var i = 0; i < blockProducerCount; i++) { if (!orderDict.ContainsKey(i)) { order = i; } } } orderDict.Add(order, signatureDict[sig]); } var blockTimeSlot = ExtraBlockTimeSlot; //Maybe because something happened with setting extra block time slot. if (blockTimeSlot.ToDateTime().AddMilliseconds(ConsensusConfig.Instance.DPoSMiningInterval * 1.5) < GetTimestampOfUtcNow().ToDateTime()) { blockTimeSlot = GetTimestampOfUtcNow(); } for (var i = 0; i < orderDict.Count; i++) { var bpInfoNew = new BlockProducer { TimeSlot = GetTimestampWithOffset(blockTimeSlot, i * ConsensusConfig.Instance.DPoSMiningInterval + ConsensusConfig.Instance.DPoSMiningInterval * 2), Order = i + 1 }; infosOfNextRound.BlockProducers[orderDict[i]] = bpInfoNew; } infosOfNextRound.RoundNumber = CurrentRoundNumber.Value + 1; return(infosOfNextRound); } catch (Exception e) { _logger?.Error(e, "Failed to generate info of next round"); return(new Round()); } }
public AElfDPoSInformation GenerateInfoForFirstTwoRounds() { var dict = new Dictionary <string, int>(); // First round foreach (var node in _miners.Nodes) { dict.Add(node, node[0]); } var sortedMiningNodes = from obj in dict orderby obj.Value descending select obj.Key; var enumerable = sortedMiningNodes.ToList(); var infosOfRound1 = new Round(); var selected = _miners.Nodes.Count / 2; for (var i = 0; i < enumerable.Count; i++) { var bpInfo = new BlockProducer { IsEBP = false }; if (i == selected) { bpInfo.IsEBP = true; } bpInfo.Order = i + 1; bpInfo.Signature = Hash.Generate(); bpInfo.TimeSlot = GetTimestampOfUtcNow(i * ConsensusConfig.Instance.DPoSMiningInterval + GlobalConfig.AElfWaitFirstRoundTime); infosOfRound1.BlockProducers.Add(enumerable[i], bpInfo); } // Second round dict = new Dictionary <string, int>(); foreach (var node in _miners.Nodes) { dict.Add(node, node[0]); } sortedMiningNodes = from obj in dict orderby obj.Value descending select obj.Key; enumerable = sortedMiningNodes.ToList(); var infosOfRound2 = new Round(); var addition = enumerable.Count * ConsensusConfig.Instance.DPoSMiningInterval + ConsensusConfig.Instance.DPoSMiningInterval; selected = _miners.Nodes.Count / 2; for (var i = 0; i < enumerable.Count; i++) { var bpInfo = new BlockProducer { IsEBP = false }; if (i == selected) { bpInfo.IsEBP = true; } bpInfo.TimeSlot = GetTimestampOfUtcNow(i * ConsensusConfig.Instance.DPoSMiningInterval + addition + GlobalConfig.AElfWaitFirstRoundTime); bpInfo.Order = i + 1; infosOfRound2.BlockProducers.Add(enumerable[i], bpInfo); } infosOfRound1.RoundNumber = 1; infosOfRound2.RoundNumber = 2; var dPoSInfo = new AElfDPoSInformation { Rounds = { infosOfRound1, infosOfRound2 } }; return(dPoSInfo); }
public async Task BasicNewBlock() { // Arrange int numberOfValidators = 64; int genesisTime = 1578009600; IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); IConfigurationRoot configuration = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary <string, string> { ["QuickStart:ValidatorCount"] = $"{numberOfValidators}", ["QuickStart:GenesisTime"] = $"{genesisTime}" }) .Build(); testServiceCollection.AddBeaconNodeQuickStart(configuration); testServiceCollection.AddBeaconNodeEth1Bridge(configuration); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); Eth1BridgeWorker eth1BridgeWorker = testServiceProvider.GetServices <IHostedService>().OfType <Eth1BridgeWorker>().First(); await eth1BridgeWorker.ExecuteEth1GenesisAsync(CancellationToken.None); IBeaconNodeApi beaconNode = testServiceProvider.GetService <IBeaconNodeApi>(); ApiResponse <Fork> forkResponse = await beaconNode.GetNodeForkAsync(CancellationToken.None); Fork fork = forkResponse.Content; fork.CurrentVersion.ShouldBe(new ForkVersion(new byte[4] { 0x00, 0x00, 0x00, 0x01 })); // Act BlockProducer blockProducer = testServiceProvider.GetService <BlockProducer>(); Slot targetSlot = new Slot(1); // With QuickStart64, proposer for Slot 1 is validator index 29, 0xa98ed496... QuickStartMockEth1GenesisProvider quickStartMockEth1GenesisProvider = (QuickStartMockEth1GenesisProvider)testServiceProvider.GetService <IEth1GenesisProvider>(); byte[] privateKey = quickStartMockEth1GenesisProvider.GeneratePrivateKey(29); BlsSignature randaoReveal = GetEpochSignature(testServiceProvider, privateKey, fork.CurrentVersion, targetSlot); // value for quickstart 20/64, fork 0, slot 1 randaoReveal.ToString().StartsWith("0x932f8730"); BeaconBlock newBlock = await blockProducer.NewBlockAsync(targetSlot, randaoReveal, CancellationToken.None); // Assert newBlock.Slot.ShouldBe(targetSlot); newBlock.Body.RandaoReveal.ShouldBe(randaoReveal); newBlock.ParentRoot.ToString().ShouldStartWith("0x4d4e9a16"); newBlock.Body.Eth1Data.DepositCount.ShouldBe((ulong)numberOfValidators); newBlock.Body.Eth1Data.DepositRoot.ToString().ShouldStartWith("0x66687aad"); newBlock.StateRoot.ToString().ShouldStartWith("0x0138b69f"); newBlock.Body.Attestations.Count.ShouldBe(0); newBlock.Body.Deposits.Count.ShouldBe(0); }
protected virtual async Task <TestBlockchain> Build(ISpecProvider specProvider = null, UInt256?initialValues = null) { Timestamper = new ManualTimestamper(new DateTime(2020, 2, 15, 12, 50, 30, DateTimeKind.Utc)); JsonSerializer = new EthereumJsonSerializer(); SpecProvider = specProvider ?? MainnetSpecProvider.Instance; EthereumEcdsa = new EthereumEcdsa(ChainId.Mainnet, LogManager); ITxStorage txStorage = new InMemoryTxStorage(); DbProvider = await TestMemDbProvider.InitAsync(); TrieStore = new TrieStore(StateDb.Innermost, LogManager); State = new StateProvider(TrieStore, DbProvider.CodeDb, LogManager); State.CreateAccount(TestItem.AddressA, (initialValues ?? InitialValue)); State.CreateAccount(TestItem.AddressB, (initialValues ?? InitialValue)); State.CreateAccount(TestItem.AddressC, (initialValues ?? InitialValue)); byte[] code = Bytes.FromHexString("0xabcd"); Keccak codeHash = Keccak.Compute(code); State.UpdateCode(code); State.UpdateCodeHash(TestItem.AddressA, codeHash, SpecProvider.GenesisSpec); Storage = new StorageProvider(TrieStore, State, LogManager); Storage.Set(new StorageCell(TestItem.AddressA, UInt256.One), Bytes.FromHexString("0xabcdef")); Storage.Commit(); State.Commit(SpecProvider.GenesisSpec); State.CommitTree(0); IDb blockDb = new MemDb(); IDb headerDb = new MemDb(); IDb blockInfoDb = new MemDb(); BlockTree = new BlockTree(blockDb, headerDb, blockInfoDb, new ChainLevelInfoRepository(blockInfoDb), SpecProvider, NullBloomStorage.Instance, LimboLogs.Instance); TransactionComparerProvider = new TransactionComparerProvider(specProvider, BlockTree); TxPool = CreateTxPool(txStorage); new OnChainTxWatcher(BlockTree, TxPool, SpecProvider, LimboLogs.Instance); ReceiptStorage = new InMemoryReceiptStorage(); VirtualMachine virtualMachine = new VirtualMachine(State, Storage, new BlockhashProvider(BlockTree, LogManager), SpecProvider, LogManager); TxProcessor = new TransactionProcessor(SpecProvider, State, Storage, virtualMachine, LogManager); BlockProcessor = CreateBlockProcessor(); BlockPreprocessorStep = new RecoverSignatures(EthereumEcdsa, TxPool, SpecProvider, LogManager); BlockchainProcessor chainProcessor = new BlockchainProcessor(BlockTree, BlockProcessor, BlockPreprocessorStep, LogManager, Nethermind.Blockchain.Processing.BlockchainProcessor.Options.Default); BlockchainProcessor = chainProcessor; BlockProcessingQueue = chainProcessor; chainProcessor.Start(); ReadOnlyTrieStore = TrieStore.AsReadOnly(); StateReader = new StateReader(ReadOnlyTrieStore, CodeDb, LogManager); TxPoolTxSource txPoolTxSource = CreateTxPoolTxSource(); ISealer sealer = new NethDevSealEngine(TestItem.AddressD); IStateProvider producerStateProvider = new StateProvider(ReadOnlyTrieStore, CodeDb, LogManager); BlockProducer = CreateTestBlockProducer(txPoolTxSource, chainProcessor, producerStateProvider, sealer); BlockProducer.Start(); _resetEvent = new SemaphoreSlim(0); _suggestedBlockResetEvent = new ManualResetEvent(true); BlockTree.NewHeadBlock += (s, e) => { _resetEvent.Release(1); }; BlockProducer.LastProducedBlockChanged += (s, e) => { _suggestedBlockResetEvent.Set(); }; var genesis = GetGenesisBlock(); BlockTree.SuggestBlock(genesis); await _resetEvent.WaitAsync(); //if (!await _resetEvent.WaitAsync(1000)) // { // throw new InvalidOperationException("Failed to process genesis in 1s."); // } await AddBlocksOnStart(); return(this); }
public async Task BasicNewBlock() { // Arrange int numberOfValidators = 64; int genesisTime = 1578009600; IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); IConfigurationRoot configuration = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary <string, string> { ["QuickStart:ValidatorCount"] = $"{numberOfValidators}", ["QuickStart:GenesisTime"] = $"{genesisTime}" }) .Build(); testServiceCollection.AddBeaconNodeQuickStart(configuration); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); QuickStart quickStart = (QuickStart)testServiceProvider.GetService <INodeStart>(); await quickStart.InitializeNodeAsync(); IBeaconNodeApi beaconNode = testServiceProvider.GetService <IBeaconNodeApi>(); Core2.Containers.Fork fork = await beaconNode.GetNodeForkAsync(CancellationToken.None); fork.CurrentVersion.ShouldBe(new ForkVersion()); // Act BlockProducer blockProducer = testServiceProvider.GetService <BlockProducer>(); Slot targetSlot = new Slot(1); // With QuickStart64, proposer for Slot 1 is validator index 20, 0xa1c76af1... byte[] privateKey = quickStart.GeneratePrivateKey(20); BlsSignature randaoReveal = GetEpochSignature(testServiceProvider, privateKey, fork.CurrentVersion, targetSlot); // value for quickstart 20/64, fork 0, slot 1 randaoReveal.ToString().ShouldBe("0xa3426b6391a29c88f2280428d5fdae9e20f4c75a8d38d0714e3aa5b9e55594dbd555c4bc685191e83d39158c3be9744d06adc34b21d2885998a206e3b3fd435eab424cf1c01b8fd562deb411348a601e83d7332d8774d1fd3bf8b88d7a33c67c"); BeaconBlock newBlock = await blockProducer.NewBlockAsync(targetSlot, randaoReveal); // Assert newBlock.Slot.ShouldBe(targetSlot); newBlock.Body.RandaoReveal.ShouldBe(randaoReveal); Hash32 expectedParentRoot = new Hash32("0x91b06cbcd6dc97b89dc8b95e0b01a497932683b182e6c722ddfa10cd005b2180"); newBlock.ParentRoot.ShouldBe(expectedParentRoot); newBlock.Body.Eth1Data.DepositCount.ShouldBe((ulong)numberOfValidators); Hash32 expectedEth1DataDepositRoot = new Hash32("0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925"); newBlock.Body.Eth1Data.DepositRoot.ShouldBe(expectedEth1DataDepositRoot); Hash32 expectedStateRoot = new Hash32("0xe05ccf6347cac0b0dab0ad0d5c941fe7c7e2ed4c69550ed9a628bc9d62914242"); newBlock.StateRoot.ShouldBe(expectedStateRoot); newBlock.Signature.ShouldBe(new BlsSignature(new byte[96])); // signature should be empty newBlock.Body.Attestations.Count.ShouldBe(0); newBlock.Body.Deposits.Count.ShouldBe(0); }
public IDisposable SubscribeAElfDPoSMiningProcess(BlockProducer infoOfMe, Timestamp extraBlockTimeSlot) { // _logger?.Trace("Extra block time slot of current round: " + // extraBlockTimeSlot.ToDateTime().ToLocalTime().ToString("HH:mm:ss")); // if (extraBlockTimeSlot.ToDateTime() < DateTime.UtcNow) // { // extraBlockTimeSlot = extraBlockTimeSlot.ToDateTime() // .AddMilliseconds(GlobalConfig.AElfDPoSMiningInterval * (GlobalConfig.BlockProducerNumber + 2)) // .ToTimestamp(); // _logger?.Trace("Extra block time slot changed to: " + // extraBlockTimeSlot.ToDateTime().ToString("HH:mm:ss")); // } var nopObservable = Observable .Timer(TimeSpan.FromSeconds(0)) .Select(_ => ConsensusBehavior.NoOperationPerformed); var timeSlot = infoOfMe.TimeSlot; var now = DateTime.UtcNow.ToTimestamp(); var distanceToProduceNormalBlock = (timeSlot - now).Seconds; IObservable <ConsensusBehavior> produceNormalBlock; if (distanceToProduceNormalBlock >= 0) { produceNormalBlock = Observable .Timer(TimeSpan.FromSeconds(distanceToProduceNormalBlock)) .Select(_ => ConsensusBehavior.PublishOutValueAndSignature); if (distanceToProduceNormalBlock >= 0) { _logger?.Trace($"Will produce normal block after {distanceToProduceNormalBlock} seconds"); } } else { distanceToProduceNormalBlock = 0; produceNormalBlock = nopObservable; } var distanceToPublishInValue = (extraBlockTimeSlot - now).Seconds; IObservable <ConsensusBehavior> publishInValue; if (distanceToPublishInValue >= 0) { var after = distanceToPublishInValue - distanceToProduceNormalBlock; publishInValue = Observable .Timer(TimeSpan.FromSeconds(after)) .Select(_ => ConsensusBehavior.PublishInValue); if (distanceToPublishInValue >= 0) { _logger?.Trace($"Will publish in value after {distanceToPublishInValue} seconds"); } } else { publishInValue = nopObservable; } IObservable <ConsensusBehavior> produceExtraBlock; if (distanceToPublishInValue < 0 && GlobalConfig.BlockProducerNumber != 1) { produceExtraBlock = nopObservable; if (GlobalConfig.BlockProducerNumber != 1) { produceExtraBlock = nopObservable; } } else if (infoOfMe.IsEBP) { var after = distanceToPublishInValue + ConsensusConfig.Instance.DPoSMiningInterval / 1000; produceExtraBlock = Observable .Timer(TimeSpan.FromMilliseconds(ConsensusConfig.Instance.DPoSMiningInterval)) .Select(_ => ConsensusBehavior.UpdateAElfDPoS); if (after >= 0) { _logger?.Trace($"Will produce extra block after {after} seconds"); } } else { var after = distanceToPublishInValue + ConsensusConfig.Instance.DPoSMiningInterval / 1000 + ConsensusConfig.Instance.DPoSMiningInterval * infoOfMe.Order / 1000 + ConsensusConfig.Instance.DPoSMiningInterval / 750; produceExtraBlock = Observable .Timer(TimeSpan.FromMilliseconds(ConsensusConfig.Instance.DPoSMiningInterval + ConsensusConfig.Instance.DPoSMiningInterval * infoOfMe.Order + ConsensusConfig.Instance.DPoSMiningInterval / 2)) .Select(_ => ConsensusBehavior.UpdateAElfDPoS); if (after >= 0) { _logger?.Trace($"Will help to produce extra block after {after} seconds"); } } return(Observable.Return(ConsensusBehavior.NoOperationPerformed) .Concat(produceNormalBlock) .Concat(publishInValue) .Concat(produceExtraBlock) .SubscribeOn(NewThreadScheduler.Default) .Subscribe(this)); }
public async Task BasicNewBlock() { // Arrange int numberOfValidators = 64; int genesisTime = 1578009600; IServiceCollection testServiceCollection = TestSystem.BuildTestServiceCollection(useStore: true); IConfigurationRoot configuration = new ConfigurationBuilder() .AddInMemoryCollection(new Dictionary <string, string> { ["QuickStart:ValidatorCount"] = $"{numberOfValidators}", ["QuickStart:GenesisTime"] = $"{genesisTime}" }) .Build(); testServiceCollection.AddQuickStart(configuration); testServiceCollection.AddSingleton <IHostEnvironment>(Substitute.For <IHostEnvironment>()); ServiceProvider testServiceProvider = testServiceCollection.BuildServiceProvider(); QuickStart quickStart = (QuickStart)testServiceProvider.GetService <INodeStart>(); await quickStart.InitializeNodeAsync(); IBeaconNodeApi beaconNode = testServiceProvider.GetService <IBeaconNodeApi>(); Core2.Containers.Fork fork = await beaconNode.GetNodeForkAsync(); fork.CurrentVersion.ShouldBe(new ForkVersion()); // Act BlockProducer blockProducer = testServiceProvider.GetService <BlockProducer>(); Slot targetSlot = new Slot(1); // With QuickStart64, proposer for Slot 1 is validator index 20, 0xa1c76af1... byte[] privateKey = quickStart.GeneratePrivateKey(20); BlsSignature randaoReveal = GetEpochSignature(testServiceProvider, privateKey, fork.CurrentVersion, targetSlot); // value for quickstart 20/64, fork 0, slot 1 randaoReveal.ToString().ShouldBe("0xa3426b6391a29c88f2280428d5fdae9e20f4c75a8d38d0714e3aa5b9e55594dbd555c4bc685191e83d39158c3be9744d06adc34b21d2885998a206e3b3fd435eab424cf1c01b8fd562deb411348a601e83d7332d8774d1fd3bf8b88d7a33c67c"); BeaconBlock newBlock = await blockProducer.NewBlockAsync(targetSlot, randaoReveal); // Assert newBlock.Slot.ShouldBe(targetSlot); newBlock.Body.RandaoReveal.ShouldBe(randaoReveal); Hash32 expectedParentRoot = new Hash32(Bytes.FromHexString("0x3111350140726cc0501223143ae5c7baad7f5a06764fcc7d444a657016e7d616")); newBlock.ParentRoot.ShouldBe(expectedParentRoot); newBlock.Body.Eth1Data.DepositCount.ShouldBe((ulong)numberOfValidators); Hash32 expectedEth1DataDepositRoot = new Hash32(Bytes.FromHexString("0x66687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925")); newBlock.Body.Eth1Data.DepositRoot.ShouldBe(expectedEth1DataDepositRoot); Hash32 expectedStateRoot = new Hash32(Bytes.FromHexString("0x9c7d3e5180f95175691511fd56f8a610299f0b5a682b6fe178230493d74f6d13")); newBlock.StateRoot.ShouldBe(expectedStateRoot); newBlock.Signature.ShouldBe(new BlsSignature(new byte[96])); // signature should be empty newBlock.Body.Attestations.Count.ShouldBe(0); newBlock.Body.Deposits.Count.ShouldBe(0); }