Example #1
0
        /// <summary>
        /// Get the current status of the block chain.
        /// </summary>
        /// <returns></returns>
        public async Task <ChainStatusDto> GetChainStatusAsync()
        {
            var basicContractZero = _smartContractAddressService.GetZeroSmartContractAddress();

            var chain = await _blockchainService.GetChainAsync();

            var branches        = chain.Branches.ToDictionary(b => HashHelper.Base64ToHash(b.Key).ToHex(), b => b.Value);
            var notLinkedBlocks = chain.NotLinkedBlocks.ToDictionary(b => HashHelper.Base64ToHash(b.Key).ToHex(),
                                                                     b => HashHelper.Base64ToHash(b.Value).ToHex());

            return(new ChainStatusDto
            {
                ChainId = ChainHelper.ConvertChainIdToBase58(chain.Id),
                GenesisContractAddress = basicContractZero?.GetFormatted(),
                Branches = branches,
                NotLinkedBlocks = notLinkedBlocks,
                LongestChainHeight = chain.LongestChainHeight,
                LongestChainHash = chain.LongestChainHash?.ToHex(),
                GenesisBlockHash = chain.GenesisBlockHash.ToHex(),
                LastIrreversibleBlockHash = chain.LastIrreversibleBlockHash?.ToHex(),
                LastIrreversibleBlockHeight = chain.LastIrreversibleBlockHeight,
                BestChainHash = chain.BestChainHash?.ToHex(),
                BestChainHeight = chain.BestChainHeight
            });
        }
Example #2
0
        public async Task RequestCrossChainDataFromOtherChainsAsync()
        {
            var chainIdHeightDict = GetNeededChainIdAndHeightPairs();

            foreach (var chainIdHeightPair in chainIdHeightDict)
            {
                var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainIdHeightPair.Key);
                Logger.LogDebug(
                    $"Try to request from chain {chainIdBased58}, from height {chainIdHeightPair.Value}");
                try
                {
                    var client = await _crossChainClientService.GetConnectedCrossChainClientAsync(chainIdHeightPair.Key);

                    if (client != null)
                    {
                        await client.RequestCrossChainDataAsync(chainIdHeightPair.Value,
                                                                b => _blockCacheEntityProducer.TryAddBlockCacheEntity(b));
                    }
                }
                catch (CrossChainRequestException e)
                {
                    Logger.LogWarning(e, $"Request chain {chainIdBased58} failed.");
                }
            }
        }
        public override async Task RequestIndexingFromParentChain(CrossChainRequest crossChainRequest,
                                                                  IServerStreamWriter <ParentChainBlockData> responseStream, ServerCallContext context)
        {
            Logger.LogTrace(
                $"Parent Chain Server received IndexedInfo message from chain {ChainHelper.ConvertChainIdToBase58(crossChainRequest.FromChainId)}.");
            var requestedHeight = crossChainRequest.NextHeight;
            var remoteChainId   = crossChainRequest.FromChainId;

            while (requestedHeight - crossChainRequest.NextHeight < CrossChainCommunicationConstants.MaximalIndexingCount)
            {
                var parentChainBlockData =
                    await _crossChainResponseService.ResponseParentChainBlockDataAsync(requestedHeight, remoteChainId);

                if (parentChainBlockData == null)
                {
                    break;
                }
                if (context.Status.StatusCode != Status.DefaultSuccess.StatusCode)
                {
                    Logger.LogTrace(
                        $"Disconnected with side chain {ChainHelper.ConvertChainIdToBase58(crossChainRequest.FromChainId)} node.");
                    return;
                }

                Logger.LogTrace($"Response parent chain data {parentChainBlockData.Height}");
                await responseStream.WriteAsync(parentChainBlockData);

                requestedHeight++;
            }
        }
        public override Empty CrossChainCreateToken(CrossChainCreateTokenInput input)
        {
            var tokenContractAddress = State.CrossChainTransferWhiteList[input.FromChainId];

            Assert(tokenContractAddress != null,
                   $"Token contract address of chain {ChainHelper.ConvertChainIdToBase58(input.FromChainId)} not registered.");

            var originalTransaction = Transaction.Parser.ParseFrom(input.TransactionBytes);

            AssertCrossChainTransaction(originalTransaction, tokenContractAddress, nameof(ValidateTokenInfoExists));
            var originalTransactionId = originalTransaction.GetHash();

            CrossChainVerify(originalTransactionId, input.ParentChainHeight, input.FromChainId, input.MerklePath);
            ValidateTokenInfoExistsInput validateTokenInfoExistsInput =
                ValidateTokenInfoExistsInput.Parser.ParseFrom(originalTransaction.Params);

            RegisterTokenInfo(new TokenInfo
            {
                Symbol       = validateTokenInfoExistsInput.Symbol,
                TokenName    = validateTokenInfoExistsInput.TokenName,
                TotalSupply  = validateTokenInfoExistsInput.TotalSupply,
                Decimals     = validateTokenInfoExistsInput.Decimals,
                Issuer       = validateTokenInfoExistsInput.Issuer,
                IsBurnable   = validateTokenInfoExistsInput.IsBurnable,
                IsProfitable = validateTokenInfoExistsInput.IsProfitable,
                IssueChainId = validateTokenInfoExistsInput.IssueChainId
            });
            return(new Empty());
        }
Example #5
0
        private async Task <bool> ValidateSideChainBlockDataAsync(
            IEnumerable <SideChainBlockData> multiSideChainBlockData,
            Hash blockHash, long blockHeight)
        {
            var sideChainValidatedHeightDict = new Dictionary <int, long>(); // chain id => validated height

            foreach (var sideChainBlockData in multiSideChainBlockData)
            {
                if (!sideChainValidatedHeightDict.TryGetValue(sideChainBlockData.ChainId, out var validatedHeight))
                {
                    var height = await _contractReaderFactory
                                 .Create(new ContractReaderContext
                    {
                        BlockHash       = blockHash,
                        BlockHeight     = blockHeight,
                        ContractAddress = await GetCrossChainContractAddressAsync(new ChainContext
                        {
                            BlockHash   = blockHash,
                            BlockHeight = blockHeight
                        })
                    }).GetSideChainHeight
                                 .CallAsync(
                        new Int32Value()
                    {
                        Value = sideChainBlockData.ChainId
                    });

                    validatedHeight = height?.Value ?? 0;
                }

                var targetHeight = validatedHeight + 1;

                if (targetHeight != sideChainBlockData.Height)
                {
                    // this should not happen if it is good data.
                    return(false);
                }

                var cachedSideChainBlockData =
                    _blockCacheEntityConsumer.Take <SideChainBlockData>(sideChainBlockData.ChainId, targetHeight, false);
                if (cachedSideChainBlockData == null)
                {
                    Logger.LogDebug(
                        $"Side chain data not found. ChainId: {ChainHelper.ConvertChainIdToBase58(sideChainBlockData.ChainId)}, side chain height: {targetHeight}.");
                    return(false);
                }

                if (!cachedSideChainBlockData.Equals(sideChainBlockData))
                {
                    Logger.LogDebug(
                        $"Incorrect side chain data. ChainId: {ChainHelper.ConvertChainIdToBase58(sideChainBlockData.ChainId)}, side chain height: {targetHeight}.");
                    return(false);
                }

                sideChainValidatedHeightDict[sideChainBlockData.ChainId] = sideChainBlockData.Height;
            }

            return(true);
        }
Example #6
0
 public override Task <HandShakeReply> CrossChainHandShake(HandShake request, ServerCallContext context)
 {
     Logger.LogTrace($"Received shake from chain {ChainHelper.ConvertChainIdToBase58(request.FromChainId)}.");
     _ = PublishCrossChainRequestReceivedEvent(request.Host, request.ListeningPort, request.FromChainId);
     return(Task.FromResult(new HandShakeReply {
         Success = true
     }));
 }
Example #7
0
        public async Task CreateClientAsync(CrossChainClientDto crossChainClientDto)
        {
            Logger.LogDebug(
                $"Handle cross chain request received event from chain {ChainHelper.ConvertChainIdToBase58(crossChainClientDto.RemoteChainId)}.");

            crossChainClientDto.LocalChainId = _localChainId;
            await _crossChainClientService.CreateClientAsync(crossChainClientDto);
        }
Example #8
0
        /// <summary>
        /// Get information about a given block by block hash. Otionally with the list of its transactions.
        /// </summary>
        /// <param name="blockHash">block hash</param>
        /// <param name="includeTransactions">include transactions or not</param>
        /// <returns></returns>
        public async Task <BlockDto> GetBlockAsync(string blockHash, bool includeTransactions = false)
        {
            Hash realBlockHash;

            try
            {
                realBlockHash = HashHelper.HexStringToHash(blockHash);
            }
            catch
            {
                throw new UserFriendlyException(Error.Message[Error.InvalidBlockHash],
                                                Error.InvalidBlockHash.ToString());
            }

            var block = await GetBlockAsync(realBlockHash);

            if (block == null)
            {
                throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString());
            }

            var blockDto = new BlockDto
            {
                BlockHash = block.GetHash().ToHex(),
                Header    = new BlockHeaderDto
                {
                    PreviousBlockHash            = block.Header.PreviousBlockHash.ToHex(),
                    MerkleTreeRootOfTransactions = block.Header.MerkleTreeRootOfTransactions.ToHex(),
                    MerkleTreeRootOfWorldState   = block.Header.MerkleTreeRootOfWorldState.ToHex(),
                    Extra        = block.Header.ExtraData.ToString(),
                    Height       = block.Header.Height,
                    Time         = block.Header.Time.ToDateTime(),
                    ChainId      = ChainHelper.ConvertChainIdToBase58(block.Header.ChainId),
                    Bloom        = block.Header.Bloom.ToByteArray().ToHex(),
                    SignerPubkey = block.Header.SignerPubkey.ToByteArray().ToHex()
                },
                Body = new BlockBodyDto()
                {
                    TransactionsCount = block.Body.TransactionsCount,
                    Transactions      = new List <string>()
                }
            };

            if (includeTransactions)
            {
                var transactions = block.Body.TransactionIds;
                var txs          = new List <string>();
                foreach (var transactionId in transactions)
                {
                    txs.Add(transactionId.ToHex());
                }

                blockDto.Body.Transactions = txs;
            }

            return(blockDto);
        }
 private async Task ConnectAsync(ICrossChainClient client)
 {
     if (client.IsConnected)
     {
         return;
     }
     Logger.LogDebug($"Try connect with chain {ChainHelper.ConvertChainIdToBase58(client.RemoteChainId)}");
     await client.ConnectAsync();
 }
        public override async Task <ChainInitializationData> RequestChainInitializationDataFromParentChain(SideChainInitializationRequest request, ServerCallContext context)
        {
            Logger.LogTrace(
                $"Received initialization data request from  chain {ChainHelper.ConvertChainIdToBase58(request.ChainId)}");
            var sideChainInitializationResponse =
                await _crossChainResponseService.ResponseChainInitializationDataFromParentChainAsync(request.ChainId);

            return(sideChainInitializationResponse);
        }
        private async Task <List <ParentChainBlockData> > GetNonIndexedParentChainBlockDataAsync(Hash blockHash,
                                                                                                 long blockHeight)
        {
            var parentChainBlockDataList = new List <ParentChainBlockData>();
            var libExists = await _irreversibleBlockStateProvider.ValidateIrreversibleBlockExistingAsync();

            if (!libExists)
            {
                return(parentChainBlockDataList);
            }

            var returnValue = await _readerFactory.Create(blockHash, blockHeight).GetParentChainId
                              .CallAsync(new Empty());

            var parentChainId = returnValue?.Value ?? 0;

            if (parentChainId == 0)
            {
                //Logger.LogTrace("No configured parent chain");
                // no configured parent chain
                return(parentChainBlockDataList);
            }

            int length        = CrossChainConstants.DefaultBlockCacheEntityCount;
            var heightInState = (await _readerFactory.Create(blockHash, blockHeight).GetParentChainHeight
                                 .CallAsync(new Empty())).Value;

            var targetHeight = heightInState + 1;

            Logger.LogTrace($"Target height {targetHeight}");

            var i = 0;

            while (i < length)
            {
                var parentChainBlockData =
                    _blockCacheEntityConsumer.Take <ParentChainBlockData>(parentChainId, targetHeight, false);
                if (parentChainBlockData == null || parentChainBlockData.Height != targetHeight)
                {
                    // no more available parent chain block info
                    break;
                }

                parentChainBlockDataList.Add(parentChainBlockData);
                targetHeight++;
                i++;
            }

            if (parentChainBlockDataList.Count > 0)
            {
                Logger.LogTrace(
                    $"Got height [{parentChainBlockDataList.First().Height} - {parentChainBlockDataList.Last().Height} ]" +
                    $" from parent chain {ChainHelper.ConvertChainIdToBase58(parentChainId)}.");
            }
            return(parentChainBlockDataList);
        }
 public async Task RequestCrossChainDataFromOtherChainsAsync()
 {
     var chainIdHeightDict = _crossChainService.GetNeededChainIdAndHeightPairs();
     
     foreach (var chainIdHeightPair in chainIdHeightDict)
     {
         Logger.LogTrace(
             $"Try to request from chain {ChainHelper.ConvertChainIdToBase58(chainIdHeightPair.Key)}, from height {chainIdHeightPair.Value}");
         await _crossChainClientService.RequestCrossChainDataAsync(chainIdHeightPair.Key, chainIdHeightPair.Value);
     }
 }
 public ChainProfile()
 {
     CreateMap <Kernel.Chain, ChainStatusDto>()
     .ForMember(d => d.ChainId, opt => opt.MapFrom(s => ChainHelper.ConvertChainIdToBase58(s.Id)))
     .ForMember(d => d.Branches,
                opt => opt.MapFrom(s =>
                                   s.Branches.ToDictionary(b => Hash.LoadFromBase64(b.Key).ToHex(), b => b.Value)))
     .ForMember(d => d.NotLinkedBlocks,
                opt => opt.MapFrom(s =>
                                   s.NotLinkedBlocks.ToDictionary(b => Hash.LoadFromBase64(b.Key).ToHex(),
                                                                  b => Hash.LoadFromBase64(b.Value).ToHex())))
     .Ignore(d => d.GenesisContractAddress);
 }
Example #14
0
        public async Task <bool> ValidateSideChainBlockDataAsync(List <SideChainBlockData> sideChainBlockDataList,
                                                                 Hash blockHash, long blockHeight)
        {
            var sideChainValidatedHeightDict = new Dictionary <int, long>(); // chain id => validated height

            foreach (var sideChainBlockData in sideChainBlockDataList)
            {
                if (!sideChainValidatedHeightDict.TryGetValue(sideChainBlockData.ChainId, out var validatedHeight))
                {
                    var height = await _readerFactory.Create(blockHash, blockHeight).GetSideChainHeight
                                 .CallAsync(
                        new SInt32Value()
                    {
                        Value = sideChainBlockData.ChainId
                    });

                    validatedHeight = height?.Value ?? 0;
                }

                long targetHeight = validatedHeight + 1;

                if (targetHeight != sideChainBlockData.Height)
                {
                    // this should not happen if it is good data.
                    return(false);
                }

                var cachedSideChainBlockData =
                    _blockCacheEntityConsumer.Take <SideChainBlockData>(sideChainBlockData.ChainId, targetHeight, false);
                if (cachedSideChainBlockData == null)
                {
                    throw new ValidateNextTimeBlockValidationException(
                              $"Side chain data not found, chainId: {ChainHelper.ConvertChainIdToBase58(sideChainBlockData.ChainId)}, side chain height: {targetHeight}.");
                }
                if (!cachedSideChainBlockData.Equals(sideChainBlockData))
                {
                    return(false);
                }

                sideChainValidatedHeightDict[sideChainBlockData.ChainId] = sideChainBlockData.Height;
            }

            foreach (var chainIdHeight in sideChainValidatedHeightDict)
            {
                Logger.LogTrace(
                    $"Validated height {chainIdHeight.Value} from  chain {ChainHelper.ConvertChainIdToBase58(chainIdHeight.Key)} ");
            }

            return(true);
        }
        public Task UpdateCrossChainCacheAsync(Hash blockHash, long blockHeight,
                                               ChainIdAndHeightDict chainIdAndHeightDict)
        {
            foreach (var chainIdHeight in chainIdAndHeightDict.IdHeightDict)
            {
                // register new chain
                RegisterNewChain(chainIdHeight.Key, chainIdHeight.Value);

                // clear cross chain cache
                ClearOutOfDateCrossChainCache(chainIdHeight.Key, chainIdHeight.Value);
                Logger.LogDebug(
                    $"Clear chain {ChainHelper.ConvertChainIdToBase58(chainIdHeight.Key)} cache by height {chainIdHeight.Value}");
            }

            return(Task.CompletedTask);
        }
        private async Task <List <ParentChainBlockData> > GetNonIndexedParentChainBlockDataAsync(Hash blockHash, long blockHeight)
        {
            var parentChainBlockDataList = new List <ParentChainBlockData>();
            var returnValue = await _readerFactory.Create(blockHash, blockHeight).GetParentChainId
                              .CallAsync(new Empty());

            var parentChainId = returnValue?.Value ?? 0;

            if (parentChainId == 0)
            {
                //Logger.LogTrace("No configured parent chain");
                // no configured parent chain
                return(parentChainBlockDataList);
            }

            int length        = CrossChainOptions.Value.MaximalCountForIndexingParentChainBlock;
            var heightInState = (await _readerFactory.Create(blockHash, blockHeight).GetParentChainHeight
                                 .CallAsync(new Empty())).Value;

            var targetHeight = heightInState + 1;

            Logger.LogTrace($"Target height {targetHeight}");

            var i = 0;

            while (i < length)
            {
                var parentChainBlockData = _blockCacheEntityConsumer.Take <ParentChainBlockData>(parentChainId, targetHeight, true);
                if (parentChainBlockData == null)
                {
                    // no more available parent chain block info
                    break;
                }

                parentChainBlockDataList.Add(parentChainBlockData);
                targetHeight++;
                i++;
            }

            if (parentChainBlockDataList.Count > 0)
            {
                Logger.LogTrace(
                    $"Got height [{parentChainBlockDataList.First().Height} - {parentChainBlockDataList.Last().Height} ]" +
                    $" from parent chain {ChainHelper.ConvertChainIdToBase58(parentChainId)}.");
            }
            return(parentChainBlockDataList);
        }
        private async Task <bool> ValidateParentChainBlockDataAsync(IEnumerable <ParentChainBlockData> multiParentChainBlockData,
                                                                    Hash blockHash, long blockHeight)
        {
            var parentChainBlockDataList = multiParentChainBlockData.ToList();

            if (parentChainBlockDataList.Count == 0)
            {
                return(true);
            }
            var parentChainId = (await _readerFactory.Create(blockHash, blockHeight).GetParentChainId
                                 .CallAsync(new Empty())).Value;

            if (parentChainId == 0)
            {
                // no configured parent chain
                return(false);
            }

            var length       = parentChainBlockDataList.Count;
            var i            = 0;
            var targetHeight = (await _readerFactory.Create(blockHash, blockHeight).GetParentChainHeight
                                .CallAsync(new Empty())).Value + 1;

            while (i < length)
            {
                var parentChainBlockData =
                    _blockCacheEntityConsumer.Take <ParentChainBlockData>(parentChainId, targetHeight, false);
                if (parentChainBlockData == null)
                {
                    Logger.LogWarning(
                        $"Parent chain data not found. ChainId: {ChainHelper.ConvertChainIdToBase58(parentChainId)}, parent chain height: {targetHeight}.");
                    return(false);
                }

                if (!parentChainBlockDataList[i].Equals(parentChainBlockData))
                {
                    Logger.LogWarning(
                        $"Incorrect parent chain data. ChainId: {ChainHelper.ConvertChainIdToBase58(parentChainId)}, parent chain height: {targetHeight}.");
                    return(false);
                }

                targetHeight++;
                i++;
            }

            return(true);
        }
        public bool TryAddBlockCacheEntity(IBlockCacheEntity blockCacheEntity)
        {
            if (blockCacheEntity == null)
            {
                throw new ArgumentNullException(nameof(blockCacheEntity));
            }
            if (!_crossChainCacheEntityProvider.TryGetChainCacheEntity(blockCacheEntity.ChainId, out var chainCacheEntity))
            {
                return(false);
            }

            var res = chainCacheEntity.TryAdd(blockCacheEntity);

            Logger.LogTrace(
                $"Cached height {blockCacheEntity.Height} from chain {ChainHelper.ConvertChainIdToBase58(blockCacheEntity.ChainId)}, {res}");
            return(res);
        }
        private BlockDto CreateBlockDto(Block block, bool includeTransactions)
        {
            if (block == null)
            {
                throw new UserFriendlyException(Error.Message[Error.NotFound], Error.NotFound.ToString());
            }

            var bloom    = block.Header.Bloom;
            var blockDto = new BlockDto
            {
                BlockHash = block.GetHash().ToHex(),
                Header    = new BlockHeaderDto
                {
                    PreviousBlockHash                = block.Header.PreviousBlockHash.ToHex(),
                    MerkleTreeRootOfTransactions     = block.Header.MerkleTreeRootOfTransactions.ToHex(),
                    MerkleTreeRootOfWorldState       = block.Header.MerkleTreeRootOfWorldState.ToHex(),
                    MerkleTreeRootOfTransactionState = block.Header.MerkleTreeRootOfTransactionStatus.ToHex(),
                    Extra        = block.Header.ExtraData.ToString(),
                    Height       = block.Header.Height,
                    Time         = block.Header.Time.ToDateTime(),
                    ChainId      = ChainHelper.ConvertChainIdToBase58(block.Header.ChainId),
                    Bloom        = bloom.Length == 0 ? ByteString.CopyFrom(new byte[256]).ToBase64(): bloom.ToBase64(),
                    SignerPubkey = block.Header.SignerPubkey.ToByteArray().ToHex()
                },
                Body = new BlockBodyDto()
                {
                    TransactionsCount = block.Body.TransactionsCount,
                    Transactions      = new List <string>()
                }
            };

            if (!includeTransactions)
            {
                return(blockDto);
            }
            var transactions = block.Body.TransactionIds;
            var txs          = new List <string>();

            foreach (var transactionId in transactions)
            {
                txs.Add(transactionId.ToHex());
            }
            blockDto.Body.Transactions = txs;

            return(blockDto);
        }
        public async Task Test()
        {
            var preBlockHeader = await _blockchainService.GetBestChainLastBlockHeaderAsync();

            var chainContext = new ChainContext
            {
                BlockHash   = preBlockHeader.GetHash(),
                BlockHeight = preBlockHeader.Height
            };
            var contractMapping = await ContractAddressService.GetSystemContractNameToAddressMappingAsync(chainContext);

            var crossChainStub = GetTester <CrossChainContractContainer.CrossChainContractStub>(
                contractMapping[CrossChainSmartContractAddressNameProvider.Name], Accounts[0].KeyPair);
            var parentChainId = await crossChainStub.GetParentChainId.CallAsync(new Empty());

            ChainHelper.ConvertChainIdToBase58(parentChainId.Value).ShouldBe("AELF");
        }
Example #21
0
 public void GetChainId_By_SerialNumber_Test()
 {
     // Have tested all the conditions (195112UL ~ 11316496UL), To save time, just do some random test
     //var base58HashSet = new HashSet<string>();
     //var intHashSet = new HashSet<int>();
     // for (var i = ; i < 11316496UL; i++)
     for (var i = 0; i < 1000; i++)
     {
         var chainId      = 2111;
         var base58String = ChainHelper.ConvertChainIdToBase58(chainId);
         base58String.Length.ShouldBe(4);
         var newChainId = ChainHelper.ConvertBase58ToChainId(base58String);
         newChainId.ShouldBe(chainId);
         // Uncomment this for go through all conditions
         // base58HashSet.Add(base58String).ShouldBe(true);
         // intHashSet.Add(newChainId).ShouldBe(true);
     }
 }
Example #22
0
        public override Task <HandShakeReply> CrossChainHandShake(HandShake request, ServerCallContext context)
        {
            Logger.LogDebug($"Received shake from chain {ChainHelper.ConvertChainIdToBase58(request.ChainId)}.");

            if (!GrpcUriHelper.TryParsePrefixedEndpoint(context.Peer, out IPEndPoint peerEndpoint))
            {
                return(Task.FromResult(new HandShakeReply
                {
                    Status = HandShakeReply.Types.HandShakeStatus.InvalidHandshakeRequest
                }));
            }

            _ = PublishCrossChainRequestReceivedEvent(peerEndpoint.Address.ToString(), request.ListeningPort,
                                                      request.ChainId);
            return(Task.FromResult(new HandShakeReply {
                Status = HandShakeReply.Types.HandShakeStatus.Success
            }));
        }
        public async Task <bool> ValidateParentChainBlockDataAsync(List <ParentChainBlockData> parentChainBlockDataList,
                                                                   Hash blockHash, long blockHeight)
        {
            if (parentChainBlockDataList.Count == 0)
            {
                return(true);
            }
            var parentChainId = (await _readerFactory.Create(blockHash, blockHeight).GetParentChainId
                                 .CallAsync(new Empty())).Value;

            if (parentChainId == 0)
            {
                // no configured parent chain
                return(false);
            }

            var length = parentChainBlockDataList.Count;

            var i = 0;

            var targetHeight = (await _readerFactory.Create(blockHash, blockHeight).GetParentChainHeight
                                .CallAsync(new Empty())).Value + 1;

            while (i < length)
            {
                var parentChainBlockData =
                    _blockCacheEntityConsumer.Take <ParentChainBlockData>(parentChainId, targetHeight, false);
                if (parentChainBlockData == null)
                {
                    throw new ValidateNextTimeBlockValidationException(
                              $"Parent chain data not found, chainId: {ChainHelper.ConvertChainIdToBase58(parentChainId)}, parent chain height: {targetHeight}.");
                }

                if (!parentChainBlockDataList[i].Equals(parentChainBlockData))
                {
                    return(false);
                }

                targetHeight++;
                i++;
            }

            return(true);
        }
Example #24
0
        public void TestChainIdGeneration()
        {
            {
                var chainId        = ChainHelper.GetChainId(0);
                var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId);
                chainIdBased58.ShouldBe("2111");

                var convertedChainId = ChainHelper.ConvertBase58ToChainId(chainIdBased58);
                convertedChainId.ShouldBe(chainId);
            }

            {
                var chainId        = ChainHelper.GetChainId(1);
                var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId);
                chainIdBased58.ShouldBe("2112");

                var convertedChainId = ChainHelper.ConvertBase58ToChainId(chainIdBased58);
                convertedChainId.ShouldBe(chainId);
            }

            {
                var chainIdMaxValue        = ChainHelper.GetChainId(long.MaxValue);
                var chainIdBased58MaxValue = ChainHelper.ConvertChainIdToBase58(chainIdMaxValue);
                chainIdBased58MaxValue.ShouldBe("mR59");

                var convertedChainIdMaxValue = ChainHelper.ConvertBase58ToChainId(chainIdBased58MaxValue);
                convertedChainIdMaxValue.ShouldBe(chainIdMaxValue);

                var chainIdMinValue = ChainHelper.GetChainId(long.MinValue);
                chainIdMinValue.ShouldBe(chainIdMaxValue);
                var chainIdBased58MinValue = ChainHelper.ConvertChainIdToBase58(chainIdMaxValue);
                chainIdBased58MinValue.ShouldBe(chainIdBased58MaxValue);
                var convertedChainIdMinValue = ChainHelper.ConvertBase58ToChainId(chainIdBased58MinValue);
                convertedChainIdMinValue.ShouldBe(convertedChainIdMaxValue);
            }

            {
                var chainIdAElf    = ChainHelper.ConvertBase58ToChainId("AELF");
                var chainId        = ChainHelper.GetChainId(chainIdAElf + 1);
                var chainIdBased58 = ChainHelper.ConvertChainIdToBase58(chainId);
                chainIdBased58.ShouldBe("tDVV");
            }
        }
Example #25
0
        public async Task UpdateWithLibAsync(Hash blockHash, long blockHeight)
        {
            if (CrossChainConfigOptions.CurrentValue.CrossChainDataValidationIgnored ||
                blockHeight <= AElfConstants.GenesisBlockHeight)
            {
                return;
            }

            var chainIdHeightPairs = await GetAllChainIdHeightPairsAsync(blockHash, blockHeight);

            foreach (var chainIdHeight in chainIdHeightPairs.IdHeightDict)
            {
                // register new chain
                _crossChainCacheEntityService.RegisterNewChain(chainIdHeight.Key, chainIdHeight.Value);

                // clear cross chain cache
                _crossChainCacheEntityService.ClearOutOfDateCrossChainCache(chainIdHeight.Key, chainIdHeight.Value);
                Logger.LogDebug(
                    $"Clear chain {ChainHelper.ConvertChainIdToBase58(chainIdHeight.Key)} cache by height {chainIdHeight.Value}");
            }
        }
Example #26
0
        public override async Task RequestIndexingFromParentChain(CrossChainRequest crossChainRequest,
                                                                  IServerStreamWriter <ParentChainBlockData> responseStream, ServerCallContext context)
        {
            Logger.LogDebug(
                $"Parent Chain Server received IndexedInfo message from chain {ChainHelper.ConvertChainIdToBase58(crossChainRequest.ChainId)}.");
            var requestedHeight = crossChainRequest.NextHeight;
            var remoteChainId   = crossChainRequest.ChainId;

            while (requestedHeight - crossChainRequest.NextHeight < GrpcCrossChainConstants.MaximalIndexingCount)
            {
                var parentChainBlockData =
                    await _crossChainResponseService.ResponseParentChainBlockDataAsync(requestedHeight, remoteChainId);

                if (parentChainBlockData == null)
                {
                    break;
                }

                if (context.Status.StatusCode != Status.DefaultSuccess.StatusCode)
                {
                    Logger.LogTrace(
                        $"Disconnected with side chain {ChainHelper.ConvertChainIdToBase58(crossChainRequest.ChainId)} node.");
                    return;
                }

                try
                {
                    await responseStream.WriteAsync(parentChainBlockData);

                    requestedHeight++;
                }
                catch (InvalidOperationException)
                {
                    Logger.LogWarning("Failed to write into server side stream.");
                    return;
                }
            }
        }
        public BlockProfile()
        {
            CreateMap <Block, BlockDto>()
            .ForMember(d => d.BlockHash, opt => opt.MapFrom(s => s.GetHash()))
            .ForMember(destination => destination.BlockSize, opt => opt.MapFrom(source => source.CalculateSize()));

            CreateMap <BlockHeader, BlockHeaderDto>()
            .ForMember(d => d.MerkleTreeRootOfTransactionState,
                       opt => opt.MapFrom(s => s.MerkleTreeRootOfTransactionStatus.ToHex()))
            .ForMember(d => d.Extra, opt => opt.MapFrom(s => s.ExtraData.ToString()))
            .ForMember(d => d.Time, opt => opt.MapFrom(s => s.Time.ToDateTime()))
            .ForMember(d => d.ChainId,
                       opt => opt.MapFrom(s => ChainHelper.ConvertChainIdToBase58(s.ChainId)))
            .ForMember(d => d.Bloom,
                       opt => opt.MapFrom(s =>
                                          s.Bloom.Length == 0
                            ? ByteString.CopyFrom(new byte[256]).ToBase64()
                            : s.Bloom.ToBase64()))
            .ForMember(d => d.SignerPubkey,
                       opt => opt.MapFrom(s => s.SignerPubkey.ToByteArray().ToHex(false)));

            CreateMap <BlockBody, BlockBodyDto>()
            .ForMember(d => d.Transactions, opt => opt.MapFrom <BlockBodyResolver>());
        }
        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>();
        }
Example #29
0
        private void ProposeCrossChainBlockData(CrossChainDataDto crossChainDataDto, Address proposer)
        {
            var crossChainIndexingController = GetCrossChainIndexingController();

            foreach (var chainId in crossChainDataDto.GetChainIdList())
            {
                Assert(!TryGetIndexingProposal(chainId, out _), "Chain indexing already proposed.");
                var proposalToken =
                    HashHelper.ConcatAndCompute(Context.PreviousBlockHash, ConvertChainIdToHash(chainId));
                var proposalCreationInput = new CreateProposalBySystemContractInput
                {
                    ProposalInput = new CreateProposalInput
                    {
                        Params = new AcceptCrossChainIndexingProposalInput
                        {
                            ChainId = chainId
                        }.ToByteString(),
                    ContractMethodName = nameof(AcceptCrossChainIndexingProposal),
                    ExpiredTime        =
                            Context.CurrentBlockTime.AddSeconds(CrossChainIndexingProposalExpirationTimePeriod),
                    OrganizationAddress = crossChainIndexingController.OwnerAddress,
                    ToAddress           = Context.Self,
                    Token = proposalToken
                    },
                    OriginProposer = Context.Sender
                };

                Context.SendInline(crossChainIndexingController.ContractAddress,
                                   nameof(AuthorizationContractContainer.AuthorizationContractReferenceState
                                          .CreateProposalBySystemContract), proposalCreationInput);

                var proposedCrossChainBlockData = new CrossChainBlockData();
                if (crossChainDataDto.ParentChainToBeIndexedData.TryGetValue(chainId,
                                                                             out var parentChainToBeIndexedData))
                {
                    proposedCrossChainBlockData.ParentChainBlockDataList.Add(parentChainToBeIndexedData);
                }
                else if (crossChainDataDto.SideChainToBeIndexedData.TryGetValue(chainId,
                                                                                out var sideChainToBeIndexedData))
                {
                    proposedCrossChainBlockData.SideChainBlockDataList.Add(sideChainToBeIndexedData);
                }

                var crossChainIndexingProposal = new ChainIndexingProposal
                {
                    ChainId  = chainId,
                    Proposer = proposer,
                    ProposedCrossChainBlockData = proposedCrossChainBlockData
                };
                var proposalId = Context.GenerateId(crossChainIndexingController.ContractAddress, proposalToken);
                crossChainIndexingProposal.ProposalId = proposalId;
                SetCrossChainIndexingProposalStatus(crossChainIndexingProposal,
                                                    CrossChainIndexingProposalStatus.Pending);
                Context.Fire(new CrossChainIndexingDataProposedEvent
                {
                    ProposedCrossChainData = proposedCrossChainBlockData,
                    ProposalId             = proposalId
                });

                Context.LogDebug(() =>
                                 $"Proposed cross chain data for chain {ChainHelper.ConvertChainIdToBase58(chainId)}");
            }
        }
        private async Task <List <SideChainBlockData> > GetNonIndexedSideChainBlockDataAsync(Hash blockHash,
                                                                                             long blockHeight)
        {
            var sideChainBlockDataList           = new List <SideChainBlockData>();
            var sideChainIndexingInformationList = await _readerFactory.Create(blockHash, blockHeight)
                                                   .GetSideChainIndexingInformationList.CallAsync(new Empty());

            foreach (var sideChainIndexingInformation in sideChainIndexingInformationList.IndexingInformationList)
            {
                var libDto = await _irreversibleBlockStateProvider.GetLastIrreversibleBlockHashAndHeightAsync();

                var sideChainId = sideChainIndexingInformation.ChainId;
                var sideChainHeightInLibValue = await _readerFactory.Create(libDto.BlockHash, libDto.BlockHeight)
                                                .GetSideChainHeight.CallAsync(new Int32Value {
                    Value = sideChainId
                });

                long toBeIndexedCount;
                long targetHeight;
                var  sideChainHeightInLib = sideChainHeightInLibValue?.Value ?? 0;
                if (sideChainHeightInLib > 0)
                {
                    targetHeight     = sideChainIndexingInformation.IndexedHeight + 1;
                    toBeIndexedCount = CrossChainConstants.DefaultBlockCacheEntityCount;
                    Logger.LogTrace(
                        $"Target height {targetHeight} of side chain " +
                        $"{ChainHelper.ConvertChainIdToBase58(sideChainId)}.");
                }
                else if (sideChainIndexingInformation.IndexedHeight > 0)
                {
                    toBeIndexedCount = 0;
                    targetHeight     = sideChainIndexingInformation.IndexedHeight + 1;
                }
                else
                {
                    toBeIndexedCount = 1;
                    targetHeight     = AElfConstants.GenesisBlockHeight;
                    Logger.LogTrace(
                        $"Target height {targetHeight} of side chain " +
                        $"{ChainHelper.ConvertChainIdToBase58(sideChainId)}.");
                }

                var sideChainBlockDataFromCache = new List <SideChainBlockData>();

                var i = 0;
                while (i < toBeIndexedCount)
                {
                    var sideChainBlockData =
                        _blockCacheEntityConsumer.Take <SideChainBlockData>(sideChainIndexingInformation.ChainId,
                                                                            targetHeight, targetHeight == AElfConstants.GenesisBlockHeight);
                    if (sideChainBlockData == null || sideChainBlockData.Height != targetHeight)
                    {
                        // no more available side chain block info
                        break;
                    }

                    sideChainBlockDataFromCache.Add(sideChainBlockData);
                    targetHeight++;
                    i++;
                }

                if (sideChainBlockDataFromCache.Count > 0)
                {
                    Logger.LogTrace(
                        $"Got height [{sideChainBlockDataFromCache.First().Height} - {sideChainBlockDataFromCache.Last().Height} ]" +
                        $" from side chain {ChainHelper.ConvertChainIdToBase58(sideChainIndexingInformation.ChainId)}.");
                    sideChainBlockDataList.AddRange(sideChainBlockDataFromCache);
                }
            }

            return(sideChainBlockDataList);
        }