private async Task <TransactionResult> ExecuteTransactionAsync(Transaction transaction) { var blockchainService = _serviceProvider.GetRequiredService <IBlockchainService>(); var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); var miningService = _serviceProvider.GetRequiredService <IMiningService>(); var blockAttachService = _serviceProvider.GetRequiredService <IBlockAttachService>(); var blockTimeProvider = _serviceProvider.GetRequiredService <IBlockTimeProvider>(); var transactionResultService = _serviceProvider.GetRequiredService <ITransactionResultService>(); var block = await miningService.MineAsync( new RequestMiningDto { PreviousBlockHash = preBlock.GetHash(), PreviousBlockHeight = preBlock.Height, BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue) }, new List <Transaction> { transaction }, blockTimeProvider.GetBlockTime()); await blockchainService.AddTransactionsAsync(new List <Transaction> { transaction }); await blockchainService.AddBlockAsync(block); await blockAttachService.AttachBlockAsync(block); return(await transactionResultService.GetTransactionResultAsync(transaction.GetHash())); }
public async Task TriggerConsensusAsync(ChainContext chainContext) { var now = TimestampHelper.GetUtcNow(); _blockTimeProvider.SetBlockTime(now); Logger.LogTrace($"Set block time to utc now: {now:hh:mm:ss.ffffff}. Trigger."); var triggerInformation = _triggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); // Upload the consensus command. _consensusCommand = await _readerFactory.Create(chainContext) .GetConsensusCommand.CallAsync(triggerInformation); Logger.LogDebug($"Updated consensus command: {_consensusCommand}"); // Update next mining time, also block time of both getting consensus extra data and txs. _nextMiningTime = TimestampHelper.GetUtcNow().AddMilliseconds(_consensusCommand .NextBlockMiningLeftMilliseconds); // Initial consensus scheduler. var blockMiningEventData = new ConsensusRequestMiningEventData(chainContext.BlockHash, chainContext.BlockHeight, _nextMiningTime, TimestampHelper.DurationFromMilliseconds(_consensusCommand.LimitMillisecondsOfMiningBlock)); _consensusScheduler.CancelCurrentEvent(); _consensusScheduler.NewEvent(_consensusCommand.NextBlockMiningLeftMilliseconds, blockMiningEventData); Logger.LogTrace($"Set next mining time to: {_nextMiningTime:hh:mm:ss.ffffff}"); }
public Task BroadcastTransactionAsync(Transaction transaction) { var beforeEnqueue = TimestampHelper.GetUtcNow(); _taskQueueManager.Enqueue(async() => { var execTime = TimestampHelper.GetUtcNow(); if (execTime > beforeEnqueue + TimestampHelper.DurationFromMilliseconds(NetworkConstants.TransactionQueueJobTimeout)) { Logger.LogWarning($"Transaction too old: {execTime - beforeEnqueue}"); return; } foreach (var peer in _peerPool.GetPeers()) { try { await peer.SendTransactionAsync(transaction); } catch (NetworkException ex) { Logger.LogError(ex, "Error while sending transaction."); await HandleNetworkException(peer, ex); } } }, NetworkConstants.TransactionBroadcastQueueName); return(Task.CompletedTask); }
private async Task <Block> ExecuteAsync(Transaction transaction, long previousBlockHeight, Hash previousBlockHash) { var transactionList = new List <Transaction>(); if (transaction != null) { transactionList.Add(transaction); } var block = await _miningService.MineAsync( new RequestMiningDto { PreviousBlockHash = previousBlockHash, PreviousBlockHeight = previousBlockHeight, BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue) }, transactionList, DateTime.UtcNow.ToTimestamp()); if (transaction != null) { await _blockchainService.AddTransactionsAsync(new List <Transaction> { transaction }); } await _blockchainService.AddBlockAsync(block); return(block); }
private async Task <BlockExecutedSet> MineAsync(List <Transaction> txs, Timestamp blockTime, Hash preBlockHash, long preBlockHeight) { var blockchainService = Application.ServiceProvider.GetRequiredService <IBlockchainService>(); var miningService = Application.ServiceProvider.GetRequiredService <IMiningService>(); var blockAttachService = Application.ServiceProvider.GetRequiredService <IBlockAttachService>(); var executedBlockSet = await miningService.MineAsync(new RequestMiningDto { PreviousBlockHash = preBlockHash, PreviousBlockHeight = preBlockHeight, BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), TransactionCountLimit = int.MaxValue }, txs, blockTime ?? DateTime.UtcNow.ToTimestamp()); var block = executedBlockSet.Block; await blockchainService.AddTransactionsAsync(txs); await blockchainService.AddBlockAsync(block); await blockAttachService.AttachBlockAsync(block); return(executedBlockSet); }
public async Task <TransactionResult> ExecuteAsync(Transaction transaction) { var blockTimeProvider = _serviceProvider.GetRequiredService <IBlockTimeProvider>(); var blockchainService = _serviceProvider.GetRequiredService <IBlockchainService>(); var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); var miningService = _serviceProvider.GetRequiredService <IMiningService>(); var blockAttachService = _serviceProvider.GetRequiredService <IBlockAttachService>(); var transactions = new List <Transaction> { transaction }; var blockExecutedSet = await miningService.MineAsync( new RequestMiningDto { PreviousBlockHash = preBlock.GetHash(), PreviousBlockHeight = preBlock.Height, BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), TransactionCountLimit = int.MaxValue }, transactions, blockTimeProvider.GetBlockTime()); var block = blockExecutedSet.Block; await blockchainService.AddTransactionsAsync(transactions); await blockchainService.AddBlockAsync(block); await blockAttachService.AttachBlockAsync(block); return(blockExecutedSet.TransactionResultMap[transaction.GetHash()]); }
public async Task Mine_Test() { var chain = await _blockchainService.GetChainAsync(); Timestamp blockTime; BlockExecutedSet miningResult; { blockTime = TimestampHelper.GetUtcNow().AddSeconds(-4); miningResult = await _miningService.MineAsync(new RequestMiningDto { BlockExecutionTime = TimestampHelper.DurationFromSeconds(1), PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight, TransactionCountLimit = 100 }, _kernelTestHelper.GenerateTransactions(10), blockTime); await CheckMiningResultAsync(miningResult, blockTime, 0); } { blockTime = TimestampHelper.GetUtcNow().AddSeconds(4); miningResult = await _miningService.MineAsync(new RequestMiningDto { BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(int.MaxValue), PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight, TransactionCountLimit = 100 }, _kernelTestHelper.GenerateTransactions(10), blockTime); await CheckMiningResultAsync(miningResult, blockTime, 10); } { blockTime = TimestampHelper.GetUtcNow(); miningResult = await _miningService.MineAsync(new RequestMiningDto { BlockExecutionTime = TimestampHelper.DurationFromSeconds(4), PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight, TransactionCountLimit = 100 }, _kernelTestHelper.GenerateTransactions(10), blockTime); await CheckMiningResultAsync(miningResult, blockTime, 10); } { blockTime = TimestampHelper.GetUtcNow(); miningResult = await _miningService.MineAsync(new RequestMiningDto { BlockExecutionTime = TimestampHelper.DurationFromSeconds(4), PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight, TransactionCountLimit = 5 }, _kernelTestHelper.GenerateTransactions(10), blockTime); await CheckMiningResultAsync(miningResult, blockTime, 4); } }
private bool CheckAgeLimit(Timestamp enqueueTime, long ageLimit) { if (enqueueTime != null && TimestampHelper.GetUtcNow() > enqueueTime + TimestampHelper.DurationFromMilliseconds(ageLimit)) { Logger.LogTrace($"Enqueue time is more then limit : {enqueueTime}"); return(false); } return(true); }
public async Task <HandshakeValidationResult> ValidateHandshakeAsync(Handshake handshake) { var pubkey = handshake.HandshakeData.Pubkey.ToHex(); if (_networkOptions.AuthorizedPeers == AuthorizedPeers.Authorized && !_networkOptions.AuthorizedKeys.Contains(pubkey)) { return(HandshakeValidationResult.Unauthorized); } var chainId = _blockchainService.GetChainId(); if (handshake.HandshakeData.ChainId != chainId) { Logger.LogWarning($"Chain is is incorrect: {handshake.HandshakeData.ChainId}."); return(HandshakeValidationResult.InvalidChainId); } if (handshake.HandshakeData.Version != KernelConstants.ProtocolVersion) { Logger.LogWarning($"Version is is incorrect: {handshake.HandshakeData.Version}."); return(HandshakeValidationResult.InvalidVersion); } var now = TimestampHelper.GetUtcNow(); if (now > handshake.HandshakeData.Time + TimestampHelper.DurationFromMilliseconds(NetworkConstants.HandshakeTimeout)) { Logger.LogWarning($"Handshake is expired: {handshake.HandshakeData.Time}, reference now: {now}."); return(HandshakeValidationResult.HandshakeTimeout); } byte[] handshakePubkey = handshake.HandshakeData.Pubkey.ToByteArray(); var validData = CryptoHelper.VerifySignature(handshake.Signature.ToByteArray(), Hash.FromMessage(handshake.HandshakeData).ToByteArray(), handshakePubkey); if (!validData) { Logger.LogWarning("Handshake signature is incorrect."); return(HandshakeValidationResult.InvalidSignature); } var nodePubKey = await _accountService.GetPublicKeyAsync(); if (handshakePubkey.BytesEqual(nodePubKey)) { Logger.LogWarning("Self connection detected."); return(HandshakeValidationResult.SelfConnection); } return(HandshakeValidationResult.Ok); }
/// <summary> /// Basically update the consensus scheduler with latest consensus command. /// </summary> /// <param name="chainContext"></param> /// <returns></returns> public async Task TriggerConsensusAsync(ChainContext chainContext) { var now = TimestampHelper.GetUtcNow(); _blockTimeProvider.SetBlockTime(now); Logger.LogDebug($"Set block time to utc now: {now.ToDateTime():hh:mm:ss.ffffff}. Trigger."); var triggerInformation = _triggerInformationProvider.GetTriggerInformationForConsensusCommand(new BytesValue()); Logger.LogDebug($"Mining triggered, chain context: {chainContext.BlockHeight} - {chainContext.BlockHash}"); // Upload the consensus command. var contractReaderContext = await _consensusReaderContextService.GetContractReaderContextAsync(chainContext); _consensusCommand = await _contractReaderFactory .Create(contractReaderContext).GetConsensusCommand .CallAsync(triggerInformation); if (_consensusCommand == null) { Logger.LogWarning("Consensus command is null."); return; } Logger.LogDebug($"Updated consensus command: {_consensusCommand}"); // Update next mining time, also block time of both getting consensus extra data and txs. _nextMiningTime = _consensusCommand.ArrangedMiningTime; var leftMilliseconds = _consensusCommand.ArrangedMiningTime - TimestampHelper.GetUtcNow(); leftMilliseconds = leftMilliseconds.Seconds > ConsensusConstants.MaximumLeftMillisecondsForNextBlock ? new Duration { Seconds = ConsensusConstants.MaximumLeftMillisecondsForNextBlock } : leftMilliseconds; // Update consensus scheduler. var blockMiningEventData = new ConsensusRequestMiningEventData(chainContext.BlockHash, chainContext.BlockHeight, _nextMiningTime, TimestampHelper.DurationFromMilliseconds(_consensusCommand.LimitMillisecondsOfMiningBlock), _consensusCommand.MiningDueTime); _consensusScheduler.CancelCurrentEvent(); _consensusScheduler.NewEvent(leftMilliseconds.Milliseconds(), blockMiningEventData); Logger.LogDebug($"Set next mining time to: {_nextMiningTime.ToDateTime():hh:mm:ss.ffffff}"); }
public Task BroadcastAnnounceAsync(BlockHeader blockHeader, bool hasFork) { var blockHash = blockHeader.GetHash(); if (!TryAddKnownBlock(blockHeader)) { return(Task.CompletedTask); } if (IsOldBlock(blockHeader)) { return(Task.CompletedTask); } var announce = new BlockAnnouncement { BlockHash = blockHash, BlockHeight = blockHeader.Height, HasFork = hasFork }; var beforeEnqueue = TimestampHelper.GetUtcNow(); _taskQueueManager.Enqueue(async() => { var execTime = TimestampHelper.GetUtcNow(); if (execTime > beforeEnqueue + TimestampHelper.DurationFromMilliseconds(NetworkConstants.AnnouncementQueueJobTimeout)) { Logger.LogWarning($"Announcement too old: {execTime - beforeEnqueue}"); return; } foreach (var peer in _peerPool.GetPeers()) { try { await peer.SendAnnouncementAsync(announce); } catch (NetworkException ex) { Logger.LogError(ex, $"Error while announcing to {peer}."); await HandleNetworkException(peer, ex); } } }, NetworkConstants.AnnouncementBroadcastQueueName); return(Task.CompletedTask); }
public async Task RequestMining_Test() { var chain = await _blockchainService.GetChainAsync(); var request = new ConsensusRequestMiningDto { BlockTime = TimestampHelper.GetUtcNow(), BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(499), PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight }; var block = await _miningRequestService.RequestMiningAsync(request); block.ShouldBeNull(); request = new ConsensusRequestMiningDto { BlockTime = TimestampHelper.GetUtcNow().AddMilliseconds(-501), BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(350), PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight }; block = await _miningRequestService.RequestMiningAsync(request); block.ShouldBeNull(); request = new ConsensusRequestMiningDto { BlockTime = TimestampHelper.GetUtcNow().AddMilliseconds(-400), BlockExecutionTime = TimestampHelper.DurationFromMilliseconds(500), MiningDueTime = TimestampHelper.GetUtcNow().AddMilliseconds(350), PreviousBlockHash = chain.BestChainHash, PreviousBlockHeight = chain.BestChainHeight }; block = await _miningRequestService.RequestMiningAsync(request); block.ShouldNotBeNull(); block.Header.PreviousBlockHash.ShouldBe(chain.BestChainHash); block.Header.Height.ShouldBe(chain.BestChainHeight + 1); block.Header.Time.ShouldBe(request.BlockTime); }
public async Task <Block> MinedOneBlock(Hash previousBlockHash = null, long previousBlockHeight = 0) { if (previousBlockHash == null || previousBlockHeight == 0) { var chain = await _blockchainService.GetChainAsync(); previousBlockHash = chain.BestChainHash; previousBlockHeight = chain.BestChainHeight; } var block = await _minerService.MineAsync(previousBlockHash, previousBlockHeight, TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(4000)); await _blockchainService.AddBlockAsync(block); await _blockAttachService.AttachBlockAsync(block); return(block); }
/// <summary> /// Mine a block with given normal txs and system txs. /// Normal txs will use tx pool while system txs not. /// </summary> /// <param name="txs"></param> /// <returns></returns> public async Task <Block> MineAsync(List <Transaction> txs) { await AddTransactionsAsync(txs); var blockchainService = Application.ServiceProvider.GetRequiredService <IBlockchainService>(); var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); var minerService = Application.ServiceProvider.GetRequiredService <IMinerService>(); var blockAttachService = Application.ServiceProvider.GetRequiredService <IBlockAttachService>(); var block = await minerService.MineAsync(preBlock.GetHash(), preBlock.Height, DateTime.UtcNow.ToTimestamp(), TimestampHelper.DurationFromMilliseconds(int.MaxValue)); await blockchainService.AddBlockAsync(block); await blockAttachService.AttachBlockAsync(block); return(block); }
public async Task ExecuteAsync(Transaction transaction) { var blockTimeProvider = _serviceProvider.GetRequiredService<IBlockTimeProvider>(); var txHub = _serviceProvider.GetRequiredService<ITxHub>(); await txHub.HandleTransactionsReceivedAsync(new TransactionsReceivedEvent { Transactions = new List<Transaction> {transaction} }); var blockchainService = _serviceProvider.GetRequiredService<IBlockchainService>(); var preBlock = await blockchainService.GetBestChainLastBlockHeaderAsync(); var minerService = _serviceProvider.GetRequiredService<IMinerService>(); var blockAttachService = _serviceProvider.GetRequiredService<IBlockAttachService>(); var block = await minerService.MineAsync(preBlock.GetHash(), preBlock.Height, blockTimeProvider.GetBlockTime(), TimestampHelper.DurationFromMilliseconds(int.MaxValue)); await blockchainService.AddBlockAsync(block); await blockAttachService.AttachBlockAsync(block); }
public async Task DoHandshake_InvalidHandshake_Test() { AElfPeerEndpointHelper.TryParse(NetworkTestConstants.GoodPeerEndpoint, out var endpoint); var handshake = CreateHandshake(); handshake.HandshakeData.ChainId = 100; var result = await _connectionService.DoHandshakeAsync(endpoint, handshake); result.Error.ShouldBe(HandshakeError.ChainMismatch); handshake = CreateHandshake(); handshake.HandshakeData.Version = 100; result = await _connectionService.DoHandshakeAsync(endpoint, handshake); result.Error.ShouldBe(HandshakeError.ProtocolMismatch); handshake = CreateHandshake(); handshake.HandshakeData.Time = handshake.HandshakeData.Time - TimestampHelper.DurationFromMilliseconds( NetworkConstants.HandshakeTimeout + 1000); result = await _connectionService.DoHandshakeAsync(endpoint, handshake); result.Error.ShouldBe(HandshakeError.SignatureTimeout); handshake = CreateHandshake(); handshake.HandshakeData.Pubkey = ByteString.CopyFrom(CryptoHelper.GenerateKeyPair().PublicKey); result = await _connectionService.DoHandshakeAsync(endpoint, handshake); result.Error.ShouldBe(HandshakeError.WrongSignature); handshake = await _handshakeProvider.GetHandshakeAsync(); result = await _connectionService.DoHandshakeAsync(endpoint, handshake); result.Error.ShouldBe(HandshakeError.ConnectionRefused); }
private async Task <Block> MineAsync(List <Transaction> txs, Timestamp blockTime, Hash preBlockHash, long preBlockHeight) { await AddTransactionsAsync(txs); var blockchainService = Application.ServiceProvider.GetRequiredService <IBlockchainService>(); var minerService = Application.ServiceProvider.GetRequiredService <IMinerService>(); var blockAttachService = Application.ServiceProvider.GetRequiredService <IBlockAttachService>(); var block = await minerService.MineAsync(preBlockHash, preBlockHeight, blockTime ?? DateTime.UtcNow.ToTimestamp(), TimestampHelper.DurationFromMilliseconds(int.MaxValue)); await blockchainService.AddBlockAsync(block); await blockAttachService.AttachBlockAsync(block); return(block); }
public async Task MineWithTxHubAsync() { var txCount = 0; var preBlockHash = _chain.BestChainHash; var preBlockHeight = _chain.BestChainHeight; while (txCount < TransactionCount) { var blockExecutedSet = await _minerService.MineAsync(preBlockHash, preBlockHeight, TimestampHelper.GetUtcNow(), TimestampHelper.DurationFromMilliseconds(4000)); txCount += blockExecutedSet.TransactionIds.Count(); _transactionIdList.AddRange(blockExecutedSet.TransactionIds.ToList()); await BlockchainService.SetBestChainAsync(_chain, preBlockHeight, preBlockHash); await TransactionPoolService.CleanByTransactionIdsAsync(blockExecutedSet.TransactionIds); await TransactionPoolService.UpdateTransactionPoolByBestChainAsync(preBlockHash, preBlockHeight); } }
public void DurationFromMilliseconds_Test() { var result = TimestampHelper.DurationFromMilliseconds(1000); result.Seconds.ShouldBe(1); }
internal async Task DoReconnectionJobAsync() { CheckNtpClockDrift(); await _networkService.CheckPeersHealthAsync(); var peersToConnect = _reconnectionService.GetPeersReadyForReconnection(TimestampHelper.GetUtcNow()); if (peersToConnect.Count <= 0) { return; } foreach (var peerToConnect in peersToConnect) { string peerEndpoint = peerToConnect.Endpoint; if (!AElfPeerEndpointHelper.TryParse(peerEndpoint, out var parsed)) { if (!_reconnectionService.CancelReconnection(peerEndpoint)) { Logger.LogWarning($"Invalid {peerEndpoint}."); } continue; } // check that we haven't already reconnected to this node if (_peerPool.FindPeerByEndpoint(parsed) != null) { Logger.LogDebug($"Peer {peerEndpoint} already in the pool, no need to reconnect."); if (!_reconnectionService.CancelReconnection(peerEndpoint)) { Logger.LogDebug($"Could not find to {peerEndpoint}."); } continue; } Logger.LogDebug($"Starting reconnection to {peerToConnect.Endpoint}."); var connected = false; try { connected = await _networkService.AddPeerAsync(peerEndpoint); } catch (Exception ex) { // down the stack the AddPeerAsync rethrows any exception, // in order to continue this job, Exception has to be catched for now. Logger.LogInformation(ex, $"Could not re-connect to {peerEndpoint}."); } if (connected) { Logger.LogDebug($"Reconnection to {peerEndpoint} succeeded."); if (!_reconnectionService.CancelReconnection(peerEndpoint)) { Logger.LogDebug($"Could not find {peerEndpoint}."); } } else { var timeExtension = _networkOptions.PeerReconnectionPeriod * (int)Math.Pow(2, ++peerToConnect.RetryCount); peerToConnect.NextAttempt = TimestampHelper.GetUtcNow().AddMilliseconds(timeExtension); // if the option is set, verify that the next attempt does not exceed // the maximum reconnection time. if (_networkOptions.MaximumReconnectionTime != 0) { var maxReconnectionDate = peerToConnect.DisconnectionTime + TimestampHelper.DurationFromMilliseconds(_networkOptions.MaximumReconnectionTime); if (peerToConnect.NextAttempt > maxReconnectionDate) { _reconnectionService.CancelReconnection(peerEndpoint); Logger.LogDebug($"Maximum reconnection time reached {peerEndpoint}, " + $"next was {peerToConnect.NextAttempt}."); continue; } } Logger.LogDebug($"Could not connect to {peerEndpoint}, next attempt {peerToConnect.NextAttempt}, " + $"current retries {peerToConnect.RetryCount}."); } } void CheckNtpClockDrift() { try { _networkService.CheckNtpDrift(); } catch (Exception) { // swallow any exception, we are not interested in anything else than valid checks. } } }