public void WriteParentChainBlockInfo(ParentChainBlockInfo parentChainBlockInfo) { ulong parentChainHeight = parentChainBlockInfo.Height; var currentHeight = _currentParentChainHeight.GetValue(); var target = currentHeight != 0 ? currentHeight + 1: GlobalConfig.GenesisBlockHeight; Api.Assert(target == parentChainHeight, $"Parent chain block info at height {target} is needed, not {parentChainHeight}"); Console.WriteLine("ParentChainBlockInfo.Height is correct."); var key = new UInt64Value { Value = parentChainHeight }; Api.Assert(_parentChainBlockInfo.GetValue(key) == null, $"Already written parent chain block info at height {parentChainHeight}"); Console.WriteLine("Writing ParentChainBlockInfo.."); foreach (var _ in parentChainBlockInfo.IndexedBlockInfo) { BindParentChainHeight(_.Key, parentChainHeight); AddIndexedTxRootMerklePathInParentChain(_.Key, _.Value); } _parentChainBlockInfo.SetValueAsync(key, parentChainBlockInfo).Wait(); _currentParentChainHeight.SetValue(parentChainHeight); // only for debug Console.WriteLine($"WriteParentChainBlockInfo success at {parentChainHeight}"); }
public void Deserialize() { var pcb = new ParentChainBlockInfo { Root = new ParentChainBlockRootInfo { ChainId = Hash.Generate(), Height = 1, SideChainBlockHeadersRoot = Hash.Default, SideChainTransactionsRoot = Hash.Default } }; var bytes = ByteString.CopyFrom(ParamsPacker.Pack(pcb)); /*var aa = new SInt32Value * { * Value = 202 * }; * string ass = ByteString.CopyFrom(aa.ToByteArray()).ToByteArray().ToHex(); * System.Diagnostics.Debug.WriteLine(ass); * var data = ByteArrayHelpers.FromHexString(ass);*/ System.Diagnostics.Debug.WriteLine((ParentChainBlockInfo)(ParamsPacker.Unpack(bytes.ToByteArray(), new[] { typeof(ParentChainBlockInfo) })[0])); }
public async Task MerklePathTest() { Init(); var chainId = Mock.ChainId1; _contract = new SideChainContractShim(Mock, AddressHelpers.GetSystemContractAddress(chainId, SmartContractType.SideChainContract.ToString())); ulong pHeight = 1; ParentChainBlockRootInfo parentChainBlockRootInfo = new ParentChainBlockRootInfo { ChainId = chainId, Height = pHeight, SideChainTransactionsRoot = Hash.Generate(), SideChainBlockHeadersRoot = Hash.Generate() }; ParentChainBlockInfo parentChainBlockInfo = new ParentChainBlockInfo { Root = parentChainBlockRootInfo }; parentChainBlockInfo.IndexedBlockInfo.Add(0, new MerklePath { Path = { Hash.FromString("Block1"), Hash.FromString("Block2"), Hash.FromString("Block3") } }); await _contract.WriteParentChainBLockInfo(parentChainBlockInfo); ChainConfig.Instance.ChainId = chainId.DumpHex(); var crossChainInfo = new CrossChainInfo(Mock.StateStore); var merklepath = crossChainInfo.GetTxRootMerklePathInParentChain(0); Assert.NotNull(merklepath); Assert.Equal(parentChainBlockInfo.IndexedBlockInfo[0], merklepath); var parentHeight = crossChainInfo.GetParentChainCurrentHeight(); Assert.Equal(pHeight, parentHeight); var boundHeight = crossChainInfo.GetBoundParentChainHeight(0); Assert.Equal(parentChainBlockRootInfo.Height, boundHeight); var boundBlockInfo = crossChainInfo.GetBoundParentChainBlockInfo(parentChainBlockRootInfo.Height); Assert.Equal(parentChainBlockInfo, boundBlockInfo); }
/// <summary> /// Validate parent chain block info. /// </summary> /// <returns> /// Return false if validation failed and then that block execution would fail. /// </returns> private bool ValidateParentChainBlockInfoTransaction(ParentChainBlockInfo parentBlockInfo) { try { var cached = _clientManager.TryGetParentChainBlockInfo(parentBlockInfo); if (cached != null) { return(cached.Equals(parentBlockInfo)); } //_logger.Warn("Not found cached parent block info"); return(false); } catch (Exception e) { if (e is ClientShutDownException) { return(true); } _logger.Warn("Parent chain block info validation failed."); return(false); } }
/// <summary> /// Try to take first one in cached queue /// </summary> /// <param name="pcb"> Mining processing if it is null, synchronization processing otherwise.</param> /// <returns> /// return the first one cached by <see cref="ClientToParentChain"/> /// </returns> public ParentChainBlockInfo TryGetParentChainBlockInfo(ParentChainBlockInfo pcb = null) { if (!GrpcLocalConfig.Instance.ClientToParentChain) { throw new ClientShutDownException("Client to parent chain is shut down"); } if (_clientToParentChain == null) { return(null); } var chainId = GrpcRemoteConfig.Instance.ParentChain?.ElementAtOrDefault(0).Key; if (chainId == null) { return(null); } Hash parentChainId = Hash.LoadHex(chainId); ulong targetHeight = GetParentChainTargetHeight(); // _logger?.Trace($"To get pcb at height {targetHeight}"); if (pcb != null && !(pcb.ChainId.Equals(parentChainId) && targetHeight == pcb.Height)) { return(null); } if (!_clientToParentChain.TryTake(WaitingIntervalInMillisecond, targetHeight, out var blockInfo, pcb == null)) { return(null); } if (pcb == null || pcb.Equals(blockInfo)) { return((ParentChainBlockInfo)blockInfo); } _logger.Trace($"Cached parent block info is {blockInfo}"); _logger.Trace($"Parent block info in transaction is {pcb}"); return(null); }
public async Task VerifyTransactionTest() { Init(); var chainId = Mock.ChainId1; ChainConfig.Instance.ChainId = chainId.DumpHex(); _contract = new SideChainContractShim(Mock, AddressHelpers.GetSystemContractAddress(chainId, SmartContractType.SideChainContract.ToString())); ulong pHeight = 1; ParentChainBlockRootInfo pcbr1 = new ParentChainBlockRootInfo { ChainId = chainId, Height = pHeight, SideChainTransactionsRoot = Hash.Generate(), SideChainBlockHeadersRoot = Hash.Generate() }; ParentChainBlockInfo pcb1 = new ParentChainBlockInfo { Root = pcbr1 }; pcb1.IndexedBlockInfo.Add(0, new MerklePath { Path = { Hash.FromString("Block1"), Hash.FromString("Block2"), Hash.FromString("Block3") } }); await _contract.WriteParentChainBLockInfo(pcb1); var crossChainInfo = new CrossChainInfo(Mock.StateStore); var parentHeight = crossChainInfo.GetParentChainCurrentHeight(); Assert.Equal(pHeight, parentHeight); Transaction t1 = new Transaction { From = Address.FromString("1"), To = Address.FromString("2"), MethodName = "test", Sig = new Signature { P = ByteString.Empty, R = ByteString.Empty, }, Params = ByteString.Empty, RefBlockNumber = 0, RefBlockPrefix = ByteString.Empty }; var hashCount = 10; var list1 = new List <Hash> { t1.GetHash() }; for (int i = 0; i < hashCount; i++) { list1.Add(Hash.Generate()); } var bmt1 = new BinaryMerkleTree(); bmt1.AddNodes(list1); var root1 = bmt1.ComputeRootHash(); var sc1BlockInfo = new SideChainBlockInfo { Height = pHeight, BlockHeaderHash = Hash.Generate(), ChainId = Hash.Generate(), TransactionMKRoot = root1 }; Transaction t2 = new Transaction { From = Address.FromString("3"), To = Address.FromString("4"), MethodName = "test", Sig = new Signature { P = ByteString.Empty, R = ByteString.Empty, }, Params = ByteString.Empty, RefBlockNumber = 1, RefBlockPrefix = ByteString.Empty }; var list2 = new List <Hash> { t2.GetHash(), Hash.FromString("d"), Hash.FromString("e"), Hash.FromString("f"), Hash.FromString("a"), Hash.FromString("b"), Hash.FromString("c") }; var bmt2 = new BinaryMerkleTree(); bmt2.AddNodes(list2); var root2 = bmt2.ComputeRootHash(); var sc2BlockInfo = new SideChainBlockInfo { Height = pHeight, BlockHeaderHash = Hash.Generate(), ChainId = Hash.Generate(), TransactionMKRoot = root2 }; var block = new Block { Header = new BlockHeader(), Body = new BlockBody() }; block.Body.IndexedInfo.Add(new List <SideChainBlockInfo> { sc1BlockInfo, sc2BlockInfo }); block.Body.CalculateMerkleTreeRoots(); pHeight = 2; ParentChainBlockRootInfo parentChainBlockRootInfo = new ParentChainBlockRootInfo { ChainId = chainId, Height = pHeight, SideChainTransactionsRoot = block.Body.SideChainTransactionsRoot, SideChainBlockHeadersRoot = Hash.FromString("SideChainBlockHeadersRoot") }; ParentChainBlockInfo parentChainBlockInfo = new ParentChainBlockInfo { Root = parentChainBlockRootInfo }; var tree = block.Body.BinaryMerkleTreeForSideChainTransactionRoots; var pathForTx1 = bmt1.GenerateMerklePath(0); Assert.Equal(root1, pathForTx1.ComputeRootWith(t1.GetHash())); var pathForSc1Block = tree.GenerateMerklePath(0); pathForTx1.Path.AddRange(pathForSc1Block.Path); var pathForTx2 = bmt2.GenerateMerklePath(0); var pathForSc2Block = tree.GenerateMerklePath(1); pathForTx2.Path.AddRange(pathForSc2Block.Path); //parentChainBlockInfo.IndexedBlockInfo.Add(1, tree.GenerateMerklePath(0)); await _contract.WriteParentChainBLockInfo(parentChainBlockInfo); //crossChainInfo = new CrossChainInfo(Mock.StateStore); parentHeight = crossChainInfo.GetParentChainCurrentHeight(); Assert.Equal(pHeight, parentHeight); var b = await _contract.VerifyTransaction(t1.GetHash(), pathForTx1, parentChainBlockRootInfo.Height); Assert.True(b); b = await _contract.VerifyTransaction(t2.GetHash(), pathForTx2, parentChainBlockRootInfo.Height); Assert.True(b); }
/// <summary> /// Get <see cref="ParentChainBlockInfo"/> from executed transaction /// </summary> /// <param name="sysTxns">Executed transactions.</param> /// <param name="traces"></param> /// <param name="parentChainBlockInfo"></param> private void FindCrossChainInfo(List <Transaction> sysTxns, List <TransactionTrace> traces, out ParentChainBlockInfo parentChainBlockInfo) { parentChainBlockInfo = null; var crossChainTx = sysTxns.FirstOrDefault(t => t.Type == TransactionType.CrossChainBlockInfoTransaction); if (crossChainTx == null) { return; } var trace = traces.FirstOrDefault(t => t.TransactionId.Equals(crossChainTx.GetHash())); if (trace == null || trace.ExecutionStatus != ExecutionStatus.ExecutedAndCommitted) { return; } parentChainBlockInfo = (ParentChainBlockInfo)ParamsPacker.Unpack(crossChainTx.Params.ToByteArray(), new[] { typeof(ParentChainBlockInfo) })[0]; }