public async Task FillExtraData_Test()
        {
            var merkleTreeRoot = HashHelper.ComputeFrom("MerkleTreeRoot");
            var expected       = new CrossChainExtraData {
                TransactionStatusMerkleTreeRoot = merkleTreeRoot
            };
            var header = new BlockHeader
            {
                PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"),
                Height            = 2
            };

            _crossChainTestHelper.AddFakeExtraData(header.PreviousBlockHash, expected);
            var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header);

            Assert.Equal(expected.ToByteString(), bytes);
        }
        private async Task <bool> ValidateCrossChainBlockDataAsync(CrossChainBlockData crossChainBlockData,
                                                                   CrossChainExtraData extraData, IBlock block)
        {
            var txRootHashList = crossChainBlockData.SideChainBlockData.Select(scb => scb.TransactionMerkleTreeRoot).ToList();
            var calculatedSideChainTransactionsRoot = new BinaryMerkleTree().AddNodes(txRootHashList).ComputeRootHash();

            // first check identity with the root in header
            if (extraData != null && !calculatedSideChainTransactionsRoot.Equals(extraData.SideChainTransactionsRoot) ||
                extraData == null && !calculatedSideChainTransactionsRoot.Equals(Hash.Empty))
            {
                return(false);
            }

            // check cache identity
            var res = await _crossChainDataProvider.ValidateSideChainBlockDataAsync(
                crossChainBlockData.SideChainBlockData.ToList(), block.Header.PreviousBlockHash, block.Height - 1) &&
                      await _crossChainDataProvider.ValidateParentChainBlockDataAsync(
                crossChainBlockData.ParentChainBlockData.ToList(), block.Header.PreviousBlockHash, block.Height - 1);

            return(res);
        }
        public async Task FIllExtraData_TransactionPackingDisabled()
        {
            var merkleTreeRoot = HashHelper.ComputeFrom("MerkleTreeRoot");
            var expected       = new CrossChainExtraData {
                TransactionStatusMerkleTreeRoot = merkleTreeRoot
            };
            var header = new BlockHeader
            {
                PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"),
                Height            = 2
            };

            _crossChainTestHelper.AddFakeExtraData(header.PreviousBlockHash, expected);
            await _transactionPackingOptionProvider.SetTransactionPackingOptionAsync(new BlockIndex
            {
                BlockHash   = header.PreviousBlockHash,
                BlockHeight = header.Height - 1
            }, false);

            var bytes = await _crossChainBlockExtraDataProvider.GetBlockHeaderExtraDataAsync(header);

            Assert.Empty(bytes);
        }
        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>();
        }
Exemplo n.º 5
0
        public async Task FillExtraData_Test()
        {
            var fakeMerkleTreeRoot1 = Hash.FromString("fakeMerkleTreeRoot1");
            var fakeMerkleTreeRoot2 = Hash.FromString("fakeMerkleTreeRoot2");
            var fakeMerkleTreeRoot3 = Hash.FromString("fakeMerkleTreeRoot3");

            int chainId1 = ChainHelper.ConvertBase58ToChainId("2112");
            int chainId2 = ChainHelper.ConvertBase58ToChainId("2113");
            int chainId3 = ChainHelper.ConvertBase58ToChainId("2114");
            var fakeSideChainBlockDataList = new List <SideChainBlockData>
            {
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1,
                    ChainId = chainId1
                },
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2,
                    ChainId = chainId2
                },
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3,
                    ChainId = chainId3
                }
            };

            var list1 = new List <SideChainBlockData>();
            var list2 = new List <SideChainBlockData>();
            var list3 = new List <SideChainBlockData>();

            list1.Add(fakeSideChainBlockDataList[0]);
            list2.Add(fakeSideChainBlockDataList[1]);
            list3.Add(fakeSideChainBlockDataList[2]);

            for (int i = 2; i < CrossChainConstants.DefaultBlockCacheEntityCount + 2; i++)
            {
                list1.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1,
                    ChainId = chainId1
                });
                list2.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2,
                    ChainId = chainId2
                });
                list3.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3,
                    ChainId = chainId3
                });
            }

            _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(
                new GetPendingCrossChainIndexingProposalOutput
            {
                Proposer   = SampleAddress.AddressList[0],
                ProposalId = Hash.FromString("ProposalId"),
                ProposedCrossChainBlockData = new CrossChainBlockData
                {
                    SideChainBlockDataList = { list1, list2, list3 }
                },
                ToBeReleased = true,
                ExpiredTime  = TimestampHelper.GetUtcNow().AddSeconds(10)
            });

            _crossChainTestHelper.SetFakeLibHeight(1);
            var header = new BlockHeader
            {
                PreviousBlockHash = Hash.FromString("PreviousHash"),
                Height            = 2
            };

            var sideChainTxMerkleTreeRoot =
                await _crossChainBlockExtraDataProvider.GetExtraDataForFillingBlockHeaderAsync(header);

            var merkleTreeRoot = BinaryMerkleTree
                                 .FromLeafNodes(list1.Concat(list2).Concat(list3).Select(sideChainBlockData =>
                                                                                         sideChainBlockData.TransactionStatusMerkleTreeRoot)).Root;
            var expected = new CrossChainExtraData {
                TransactionStatusMerkleTreeRoot = merkleTreeRoot
            }.ToByteString();

            Assert.Equal(expected, sideChainTxMerkleTreeRoot);
        }
Exemplo n.º 6
0
 public void AddFakeExtraData(Hash previousHash, CrossChainExtraData crossChainExtraData)
 {
     _fakeCrossChainExtraData.Add(previousHash, crossChainExtraData);
 }
Exemplo n.º 7
0
        private bool ValidateBlockExtraDataAsync(CrossChainBlockData crossChainBlockData, CrossChainExtraData extraData)
        {
            var txRootHashList = crossChainBlockData.SideChainBlockData.Select(scb => scb.TransactionStatusMerkleTreeRoot).ToList();
            var calculatedSideChainTransactionsRoot = BinaryMerkleTree.FromLeafNodes(txRootHashList).Root;

            return(calculatedSideChainTransactionsRoot.Equals(extraData.TransactionStatusMerkleTreeRoot));
        }
        public async Task FillExtraData_Test()
        {
            var fakeMerkleTreeRoot1 = Hash.FromString("fakeMerkleTreeRoot1");
            var fakeMerkleTreeRoot2 = Hash.FromString("fakeMerkleTreeRoot2");
            var fakeMerkleTreeRoot3 = Hash.FromString("fakeMerkleTreeRoot3");

            int chainId1 = ChainHelper.ConvertBase58ToChainId("2112");
            int chainId2 = ChainHelper.ConvertBase58ToChainId("2113");
            int chainId3 = ChainHelper.ConvertBase58ToChainId("2114");
            var fakeSideChainBlockDataList = new List <SideChainBlockData>
            {
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1,
                    ChainId = chainId1
                },
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2,
                    ChainId = chainId2
                },
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3,
                    ChainId = chainId3
                }
            };

            var list1 = new List <IBlockCacheEntity>();
            var list2 = new List <IBlockCacheEntity>();
            var list3 = new List <IBlockCacheEntity>();

            list1.Add(fakeSideChainBlockDataList[0]);
            list2.Add(fakeSideChainBlockDataList[1]);
            list3.Add(fakeSideChainBlockDataList[2]);

            for (int i = 2; i < CrossChainConstants.MinimalBlockCacheEntityCount + 2; i++)
            {
                list1.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1,
                    ChainId = chainId1
                });
                list2.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2,
                    ChainId = chainId2
                });
                list3.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3,
                    ChainId = chainId3
                });
            }

            AddFakeCacheData(new Dictionary <int, List <IBlockCacheEntity> >
            {
                { chainId1, list1 },
                { chainId2, list2 },
                { chainId3, list3 }
            });

            _crossChainTestHelper.AddFakeSideChainIdHeight(chainId1, 0);
            _crossChainTestHelper.AddFakeSideChainIdHeight(chainId2, 0);
            _crossChainTestHelper.AddFakeSideChainIdHeight(chainId3, 0);
            _crossChainTestHelper.SetFakeLibHeight(1);
            var header = new BlockHeader
            {
                PreviousBlockHash = Hash.FromString("PreviousHash"),
                Height            = 2
            };

            var sideChainTxMerkleTreeRoot =
                await _crossChainBlockExtraDataProvider.GetExtraDataForFillingBlockHeaderAsync(header);

            var merkleTreeRoot = BinaryMerkleTree
                                 .FromLeafNodes(fakeSideChainBlockDataList.Select(sideChainBlockData =>
                                                                                  sideChainBlockData.TransactionStatusMerkleTreeRoot)).Root;
            var expected = new CrossChainExtraData {
                TransactionStatusMerkleTreeRoot = merkleTreeRoot
            }.ToByteString();

            Assert.Equal(expected, sideChainTxMerkleTreeRoot);
        }
Exemplo n.º 9
0
        public async Task FillExtraData_Test()
        {
            var fakeMerkleTreeRoot1 = HashHelper.ComputeFrom("fakeMerkleTreeRoot1");
            var fakeMerkleTreeRoot2 = HashHelper.ComputeFrom("fakeMerkleTreeRoot2");
            var fakeMerkleTreeRoot3 = HashHelper.ComputeFrom("fakeMerkleTreeRoot3");

            int chainId1 = ChainHelper.ConvertBase58ToChainId("2112");
            int chainId2 = ChainHelper.ConvertBase58ToChainId("2113");
            int chainId3 = ChainHelper.ConvertBase58ToChainId("2114");
            var fakeSideChainBlockDataList = new List <SideChainBlockData>
            {
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1,
                    ChainId = chainId1
                },
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2,
                    ChainId = chainId2
                },
                new SideChainBlockData
                {
                    Height = 1,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3,
                    ChainId = chainId3
                }
            };

            var list1 = new List <SideChainBlockData>();
            var list2 = new List <SideChainBlockData>();
            var list3 = new List <SideChainBlockData>();

            list1.Add(fakeSideChainBlockDataList[0]);
            list2.Add(fakeSideChainBlockDataList[1]);
            list3.Add(fakeSideChainBlockDataList[2]);

            for (int i = 2; i < CrossChainConstants.DefaultBlockCacheEntityCount + 2; i++)
            {
                list1.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot1,
                    ChainId = chainId1
                });
                list2.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot2,
                    ChainId = chainId2
                });
                list3.Add(new SideChainBlockData
                {
                    Height = i,
                    TransactionStatusMerkleTreeRoot = fakeMerkleTreeRoot3,
                    ChainId = chainId3
                });
            }

            _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId1,
                                                                           CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0],
                                                                                                                    HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData
            {
                SideChainBlockDataList = { list1 }
            }));

            _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId2,
                                                                           CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0],
                                                                                                                    HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData
            {
                SideChainBlockDataList = { list2 }
            }));

            _crossChainTestHelper.AddFakePendingCrossChainIndexingProposal(chainId3,
                                                                           CreatePendingChainIndexingProposalStatus(SampleAddress.AddressList[0],
                                                                                                                    HashHelper.ComputeFrom("ProposalId"), new CrossChainBlockData
            {
                SideChainBlockDataList = { list3 }
            })
                                                                           );

            _crossChainTestHelper.SetFakeLibHeight(1);
            var header = new BlockHeader
            {
                PreviousBlockHash = HashHelper.ComputeFrom("PreviousHash"),
                Height            = 2
            };

            var sideChainTxMerkleTreeRoot =
                await _crossChainIndexingDataService.PrepareExtraDataForNextMiningAsync(header.PreviousBlockHash,
                                                                                        header.Height - 1);

            var merkleTreeRoot = BinaryMerkleTree
                                 .FromLeafNodes(list1.Concat(list2).Concat(list3).Select(sideChainBlockData =>
                                                                                         sideChainBlockData.TransactionStatusMerkleTreeRoot)).Root;
            var expected = new CrossChainExtraData {
                TransactionStatusMerkleTreeRoot = merkleTreeRoot
            }.ToByteString();

            Assert.Equal(expected, sideChainTxMerkleTreeRoot);
        }
        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>();
        }