public override void ConfigureServices(ServiceConfigurationContext context)
        {
            base.ConfigureServices(context);

            var dictionary = new Dictionary <long, Hash>
            {
                { 1, Hash.FromString("1") },
                { 2, Hash.FromString("2") },
                { 3, Hash.FromString("3") }
            };

            Configure <GrpcCrossChainConfigOption>(option =>
            {
                option.ListeningPort         = 5001;
                option.ParentChainServerIp   = "127.0.0.1";
                option.ParentChainServerPort = 5000;
            });

            Configure <CrossChainConfigOptions>(option =>
            {
                option.ParentChainId = ChainHelper.ConvertChainIdToBase58(ChainHelper.GetChainId(1));
            });

            context.Services.AddTransient(provider =>
            {
                var kernelTestHelper      = context.Services.GetRequiredServiceLazy <KernelTestHelper>();
                var mockBlockChainService = new Mock <IBlockchainService>();
                mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(() =>
                {
                    var chain = new Chain {
                        LastIrreversibleBlockHeight = 10
                    };
                    return(Task.FromResult(chain));
                });
                mockBlockChainService.Setup(m =>
                                            m.GetBlockHashByHeightAsync(It.IsAny <Chain>(), It.IsAny <long>(), It.IsAny <Hash>()))
                .Returns <Chain, long, Hash>((chain, height, hash) =>
                {
                    if (height > 0 && height <= 3)
                    {
                        return(Task.FromResult(dictionary[height]));
                    }
                    return(Task.FromResult <Hash>(null));
                });
                mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny <Hash>())).Returns <Hash>(hash =>
                {
                    foreach (var kv in dictionary)
                    {
                        if (kv.Value.Equals(hash))
                        {
                            var block = kernelTestHelper.Value.GenerateBlock(kv.Key - 1, dictionary[kv.Key - 1]);
                            return(Task.FromResult(block));
                        }
                    }

                    return(Task.FromResult <Block>(null));
                });
                return(mockBlockChainService.Object);
            });

            context.Services.AddTransient(provider =>
            {
                var mockBlockExtraDataService = new Mock <IBlockExtraDataService>();
                mockBlockExtraDataService
                .Setup(m => m.GetExtraDataFromBlockHeader(It.IsAny <string>(), It.IsAny <BlockHeader>())).Returns(
                    () =>
                {
                    var crossExtraData = new CrossChainExtraData()
                    {
                        TransactionStatusMerkleTreeRoot = Hash.FromString("SideChainBlockHeadersRoot"),
                    };
                    return(ByteString.CopyFrom(crossExtraData.ToByteArray()));
                });
                return(mockBlockExtraDataService.Object);
            });

            context.Services.AddTransient(provider =>
            {
                var mockCrossChainIndexingDataService = new Mock <ICrossChainIndexingDataService>();
                mockCrossChainIndexingDataService
                .Setup(m => m.GetIndexedCrossChainBlockDataAsync(It.IsAny <Hash>(), It.IsAny <long>()))
                .Returns(() =>
                {
                    var crossChainBlockData = new CrossChainBlockData
                    {
                        SideChainBlockDataList =
                        {
                            new SideChainBlockData
                            {
                                ChainId = 123, Height = 1,
                                TransactionStatusMerkleTreeRoot = Hash.FromString("fakeTransactionMerkleTree")
                            }
                        }
                    };
                    return(Task.FromResult(crossChainBlockData));
                });
                mockCrossChainIndexingDataService
                .Setup(m => m.GetIndexedSideChainBlockDataAsync(It.IsAny <Hash>(), It.IsAny <long>())).Returns(
                    () =>
                {
                    var indexedSideChainBlockData = new IndexedSideChainBlockData
                    {
                        SideChainBlockDataList =
                        {
                            new SideChainBlockData
                            {
                                ChainId = 123, Height = 1,
                                TransactionStatusMerkleTreeRoot = Hash.FromString("fakeTransactionMerkleTree")
                            }
                        }
                    };
                    return(Task.FromResult(indexedSideChainBlockData));
                });
                return(mockCrossChainIndexingDataService.Object);
            });

            context.Services.AddTransient(provider =>
            {
                var mockCrossChainClientProvider = new Mock <ICrossChainClientProvider>();
                mockCrossChainClientProvider.Setup(m => m.CreateCrossChainClient(It.IsAny <CrossChainClientDto>()))
                .Returns(() =>
                {
                    var mockCrossChainClient = new Mock <ICrossChainClient>();
                    mockCrossChainClient.Setup(m => m.RequestChainInitializationDataAsync(It.IsAny <int>())).Returns(
                        () =>
                    {
                        var chainInitialization = new ChainInitializationData
                        {
                            CreationHeightOnParentChain = 1
                        };
                        return(Task.FromResult(chainInitialization));
                    });
                    mockCrossChainClient.Setup(m =>
                                               m.RequestCrossChainDataAsync(It.IsAny <long>(),
                                                                            It.IsAny <Func <IBlockCacheEntity, bool> >()))
                    .Returns(() =>
                    {
                        var chainInitialization = new ChainInitializationData
                        {
                            CreationHeightOnParentChain = 1
                        };
                        return(Task.FromResult(chainInitialization));
                    });
                    return(mockCrossChainClient.Object);
                });
                return(mockCrossChainClientProvider.Object);
            });

            context.Services.AddSingleton <CrossChainPlugin>();

            context.Services.AddSingleton <IConsensusExtraDataNameProvider, MockConsensusExtraDataProvider>();
        }
        public override void ConfigureServices(ServiceConfigurationContext context)
        {
            base.ConfigureServices(context);
            context.Services.AddSingleton <CrossChainCommunicationTestHelper>();

            Configure <CrossChainConfigOptions>(option =>
            {
                option.ParentChainId = ChainHelper.ConvertChainIdToBase58(ChainHelper.GetChainId(1));
            });

            context.Services.AddTransient(provider =>
            {
                var kernelTestHelper = context.Services.GetRequiredServiceLazy <KernelTestHelper>();
                var crossChainCommunicationTestHelper =
                    context.Services.GetRequiredServiceLazy <CrossChainCommunicationTestHelper>().Value;
                var mockBlockChainService = new Mock <IBlockchainService>();
                mockBlockChainService.Setup(m => m.GetChainAsync()).Returns(() =>
                {
                    var chain = new Chain {
                        LastIrreversibleBlockHeight = 10
                    };
                    return(Task.FromResult(chain));
                });
                mockBlockChainService.Setup(m =>
                                            m.GetBlockHashByHeightAsync(It.IsAny <Chain>(), It.IsAny <long>(), It.IsAny <Hash>()))
                .Returns <Chain, long, Hash>((chain, height, hash) =>
                                             Task.FromResult(crossChainCommunicationTestHelper.GetBlockHashByHeight(height)));
                mockBlockChainService.Setup(m => m.GetBlockByHashAsync(It.IsAny <Hash>())).Returns <Hash>(hash =>
                {
                    if (!crossChainCommunicationTestHelper.TryGetHeightByHash(hash, out var height))
                    {
                        return(Task.FromResult <Block>(null));
                    }
                    var block = kernelTestHelper.Value.GenerateBlock(height - 1,
                                                                     crossChainCommunicationTestHelper.GetBlockHashByHeight(height - 1));
                    return(Task.FromResult(block));
                });
                return(mockBlockChainService.Object);
            });

            context.Services.AddTransient(provider =>
            {
                var crossChainCommunicationTestHelper =
                    context.Services.GetRequiredServiceLazy <CrossChainCommunicationTestHelper>().Value;
                var mockBlockExtraDataService = new Mock <IBlockExtraDataService>();
                mockBlockExtraDataService
                .Setup(m => m.GetExtraDataFromBlockHeader(It.IsAny <string>(), It.IsAny <BlockHeader>())).Returns(
                    () =>
                {
                    var crossExtraData = new CrossChainExtraData
                    {
                        TransactionStatusMerkleTreeRoot = BinaryMerkleTree
                                                          .FromLeafNodes(
                            crossChainCommunicationTestHelper.IndexedSideChainBlockData
                            .SideChainBlockDataList.Select(scb => scb.TransactionStatusMerkleTreeRoot))
                                                          .Root,
                    };
                    return(ByteString.CopyFrom(crossExtraData.ToByteArray()));
                });
                return(mockBlockExtraDataService.Object);
            });

            context.Services.AddTransient(provider =>
            {
                var crossChainCommunicationTestHelper =
                    context.Services.GetRequiredServiceLazy <CrossChainCommunicationTestHelper>().Value;

                var mockCrossChainIndexingDataService = new Mock <ICrossChainIndexingDataService>();
                var irreversibleBlockStateProvider    =
                    context.Services.GetRequiredServiceLazy <IIrreversibleBlockStateProvider>();

                mockCrossChainIndexingDataService.Setup(service => service.GetNonIndexedBlockAsync(It.IsAny <long>()))
                .Returns <long>(async height => await irreversibleBlockStateProvider.Value
                                .GetNotIndexedIrreversibleBlockByHeightAsync(height));

                mockCrossChainIndexingDataService
                .Setup(m => m.GetIndexedSideChainBlockDataAsync(It.IsAny <Hash>(), It.IsAny <long>())).Returns(
                    () =>
                {
                    var indexedSideChainBlockData = crossChainCommunicationTestHelper.IndexedSideChainBlockData;
                    return(Task.FromResult(indexedSideChainBlockData));
                });
                return(mockCrossChainIndexingDataService.Object);
            });

            context.Services.AddTransient(provider =>
            {
                var crossChainCommunicationTestHelper =
                    context.Services.GetRequiredServiceLazy <CrossChainCommunicationTestHelper>().Value;
                var mockCrossChainClientProvider = new Mock <ICrossChainClientProvider>();
                ICrossChainClient client;
                mockCrossChainClientProvider
                .Setup(m => m.TryGetClient(It.IsAny <int>(), out client))
                .Callback(new TryGetClientCallback((int chainId, out ICrossChainClient crossChainClient) =>
                {
                    if (!crossChainCommunicationTestHelper.TryGetCrossChainClientCreationContext(chainId, out _))
                    {
                        crossChainClient = null;
                        return;
                    }

                    bool isConnected = crossChainCommunicationTestHelper.CheckClientConnected(chainId);
                    crossChainClient = MockCrossChainClient(chainId, isConnected,
                                                            entity =>
                    {
                        crossChainCommunicationTestHelper.SetClientConnected(-1, true);
                        return(true);
                    });
                }))
                .Returns <int, ICrossChainClient>((chainId, client) =>
                                                  crossChainCommunicationTestHelper.TryGetCrossChainClientCreationContext(chainId, out _));

                mockCrossChainClientProvider
                .Setup(c => c.AddOrUpdateClient(It.IsAny <CrossChainClientCreationContext>()))
                .Returns <CrossChainClientCreationContext>(
                    crossChainClientCreationContext => CreateAndAddClient(crossChainCommunicationTestHelper, crossChainClientCreationContext));

                mockCrossChainClientProvider.Setup(c =>
                                                   c.CreateChainInitializationDataClient(It.IsAny <CrossChainClientCreationContext>())).Returns <CrossChainClientCreationContext>(
                    crossChainClientCreationContext => CreateAndAddClient(crossChainCommunicationTestHelper, crossChainClientCreationContext));
                return(mockCrossChainClientProvider.Object);
            });

            context.Services.AddSingleton <IConsensusExtraDataKeyProvider, MockConsensusExtraDataProvider>();
        }