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);
        }
Ejemplo n.º 2
0
        /// <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> >());
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 6
0
        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);
        }
Ejemplo n.º 8
0
        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()));
            }
        }
Ejemplo n.º 9
0
 /// <inheritdoc />
 public Task PushCurrentBlockTipAsync(BlockTipModel model, CancellationToken cancellation = default(CancellationToken))
 {
     return(this.SendPostRequestAsync(model, FederationGatewayRouteEndPoint.PushCurrentBlockTip, cancellation));
 }
Ejemplo n.º 10
0
        public void Update(BlockTipModel blockTipModel)
        {
            Guard.NotNull(blockTipModel, nameof(blockTipModel));

            this.CurrentLeaderKey = new PubKey(this.orderedFederationPublicKeys[blockTipModel.Height % this.orderedFederationPublicKeys.Count]);
        }