public void ReceiveCurrentBlockTip_Should_Call_LeaderProdvider_Update() { var controller = new FederationGatewayController( this.loggerFactory, this.maturedBlockReceiver, this.maturedBlocksRequester, this.leaderProvider, this.chain, GetMaturedBlocksProvider(), this.depositExtractor, this.leaderReceiver); var model = new BlockTipModel(TestingValues.GetUint256(), TestingValues.GetPositiveInt(), TestingValues.GetPositiveInt()); var leaderProviderCallCount = 0; this.leaderProvider.When(x => x.Update(Arg.Any <BlockTipModel>())).Do(info => { leaderProviderCallCount++; }); IActionResult result = controller.ReceiveCurrentBlockTip(model); result.Should().BeOfType <OkResult>(); leaderProviderCallCount.Should().Be(1); }
/// <summary> /// When a block is received it is passed to the monitor. /// </summary> /// <param name="chainedHeaderBlock">The new block.</param> public void OnBlockReceived(ChainedHeaderBlock chainedHeaderBlock) { this.walletSyncManager.ProcessBlock(chainedHeaderBlock.Block); // Cancel previous sending to avoid first sending new tip and then sending older tip. if ((this.pushBlockTipTask != null) && !this.pushBlockTipTask.IsCompleted) { this.cancellationSource.Cancel(); this.pushBlockTipTask.GetAwaiter().GetResult(); this.pushBlockTipTask = null; this.cancellationSource = null; } var blockTipModel = new BlockTipModel(chainedHeaderBlock.ChainedHeader.HashBlock, chainedHeaderBlock.ChainedHeader.Height, (int)this.depositExtractor.MinimumDepositConfirmations); // There is no reason to wait for the message to be sent. // Awaiting REST API call will only slow this callback. // Callbacks never supposed to do any IO calls or web requests. // Instead we start sending the message and if next block was connected faster than the message was sent we // are canceling it and sending the next tip. // Receiver of this message doesn't care if we are not providing tips for every block we connect, // it just requires to know about out latest state. this.cancellationSource = new CancellationTokenSource(); this.pushBlockTipTask = Task.Run(async() => await this.federationGatewayClient.PushCurrentBlockTipAsync(blockTipModel, this.cancellationSource.Token).ConfigureAwait(false)); IReadOnlyList <IWithdrawal> withdrawals = this.withdrawalExtractor.ExtractWithdrawalsFromBlock( chainedHeaderBlock.Block, chainedHeaderBlock.ChainedHeader.Height); this.withdrawalReceiver.ReceiveWithdrawals(withdrawals); }
public async Task SendBlockTip_Should_Log_Error_When_Failing_To_Send_IBlockTipAsync() { var blockTip = new BlockTipModel(TestingValues.GetUint256(), TestingValues.GetPositiveInt(), TestingValues.GetPositiveInt()); HttpResponseMessage result = await this.createClient(true).PushCurrentBlockTipAsync(blockTip).ConfigureAwait(false); Assert.False(result.IsSuccessStatusCode); }
public async Task SendBlockTip_Should_Be_Able_To_Send_IBlockTipAsync() { var blockTip = new BlockTipModel(TestingValues.GetUint256(), TestingValues.GetPositiveInt(), TestingValues.GetPositiveInt()); await this.createClient().PushCurrentBlockTipAsync(blockTip).ConfigureAwait(false); this.logger.Received(0).Log <object>(LogLevel.Error, 0, Arg.Any <object>(), Arg.Any <Exception>(), Arg.Any <Func <object, Exception, string> >()); }
public static IBlockTip PrepareBlockTip() { uint256 blockHash = TestingValues.GetUint256(); int blockHeight = TestingValues.GetPositiveInt(); int matureConfirmation = TestingValues.GetPositiveInt(); var blockTip = new BlockTipModel(blockHash, blockHeight, matureConfirmation); return(blockTip); }
public async Task SendBlockTip_Should_Log_Error_When_Failing_To_Send_IBlockTipAsync() { TestingHttpClient.PrepareFailingHttpClient(ref this.messageHandler, ref this.httpClient, ref this.httpClientFactory); var restSender = new RestBlockTipSender(this.loggerFactory, this.federationSettings, this.httpClientFactory); var blockTip = new BlockTipModel(TestingValues.GetUint256(), TestingValues.GetPositiveInt(), TestingValues.GetPositiveInt()); await restSender.SendBlockTipAsync(blockTip).ConfigureAwait(false); this.logger.Received(1).Log <object>(LogLevel.Error, 0, Arg.Any <object>(), Arg.Is <Exception>(e => e != null), Arg.Any <Func <object, Exception, string> >()); }
public void ReceiveCurrentBlockTip_Should_Call_LeaderProdvider_Update() { FederationGatewayController controller = this.CreateController(); var model = new BlockTipModel(TestingValues.GetUint256(), TestingValues.GetPositiveInt(), TestingValues.GetPositiveInt()); int leaderProviderCallCount = 0; this.leaderProvider.When(x => x.Update(Arg.Any <BlockTipModel>())).Do(info => { leaderProviderCallCount++; }); IActionResult result = controller.PushCurrentBlockTip(model); result.Should().BeOfType <OkResult>(); leaderProviderCallCount.Should().Be(1); }
public IActionResult PushCurrentBlockTip([FromBody] BlockTipModel blockTip) { Guard.NotNull(blockTip, nameof(blockTip)); if (!this.ModelState.IsValid) { return(BuildErrorResponse(this.ModelState)); } try { this.leaderProvider.Update(new BlockTipModel(blockTip.Hash, blockTip.Height, blockTip.MatureConfirmations)); this.leaderReceiver.PushLeader(this.leaderProvider); return(this.Ok()); } catch (Exception e) { this.logger.LogError("Exception thrown calling /api/FederationGateway/{0}: {1}.", FederationGatewayRouteEndPoint.PushCurrentBlockTip, e.Message); return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, $"Could not select the next federated leader: {e.Message}", e.ToString())); } }
/// <inheritdoc /> public Task PushCurrentBlockTipAsync(BlockTipModel model, CancellationToken cancellation = default(CancellationToken)) { return(this.SendPostRequestAsync(model, FederationGatewayRouteEndPoint.PushCurrentBlockTip, cancellation)); }
public void Update(BlockTipModel blockTipModel) { Guard.NotNull(blockTipModel, nameof(blockTipModel)); this.CurrentLeaderKey = new PubKey(this.orderedFederationPublicKeys[blockTipModel.Height % this.orderedFederationPublicKeys.Count]); }