private async Task <bool> VerifyConsolidationBlock(ConsolidationBlock consBlock, long latestHeight = -1) { _log.LogInformation($"VerifyConsolidationBlock: {consBlock.Height}/{latestHeight}"); var myConsBlock = await FindBlockByHashAsync(consBlock.Hash) as ConsolidationBlock; if (myConsBlock == null) { return(false); } var mt = new MerkleTree(); foreach (var hash in myConsBlock.blockHashes) { var myBlock = await FindBlockByHashAsync(hash); if (myBlock == null) { return(false); } mt.AppendLeaf(MerkleHash.Create(hash)); } var merkelTreeHash = mt.BuildTree().ToString(); return(consBlock.MerkelTreeHash == merkelTreeHash); }
public ConsolidationBlock CreateConsolidationGenesisBlock(ServiceBlock svcGen, LyraTokenGenesisBlock lyraGen, PoolFactoryBlock pf) { var consBlock = new ConsolidationBlock { createdBy = ProtocolSettings.Default.StandbyValidators[0], blockHashes = new List <string>() { svcGen.Hash, lyraGen.Hash, pf.Hash }, totalBlockCount = 3 // not including self }; consBlock.TimeStamp = DateTime.UtcNow.AddSeconds(-18); var mt = new MerkleTree(); mt.AppendLeaf(MerkleHash.Create(svcGen.Hash)); mt.AppendLeaf(MerkleHash.Create(lyraGen.Hash)); mt.AppendLeaf(MerkleHash.Create(pf.Hash)); consBlock.MerkelTreeHash = mt.BuildTree().ToString(); consBlock.ServiceHash = svcGen.Hash; consBlock.totalFees = lyraGen.Fee.ToBalanceLong(); consBlock.InitializeBlock(null, _sys.PosWallet.PrivateKey, _sys.PosWallet.AccountId); return(consBlock); }
private async Task SyncManyBlocksAsync(LyraClientForNode client, ConsolidationBlock consBlock) { _log.LogInformation($"Syncing Consolidations {consBlock.Height} / {consBlock.Hash.Shorten()} "); var blocksResult = await client.GetBlocksByConsolidation(consBlock.Hash); if (blocksResult.ResultCode == APIResultCodes.Success) { foreach (var block in blocksResult.GetBlocks()) { var localBlock = await FindBlockByHashAsync(block.Hash); if (localBlock != null) { await RemoveBlockAsync(block.Hash); } await AddBlockAsync(block); } } }
public ConsolidationBlock GetConsolidationGenesisBlock(ServiceBlock svcGen, LyraTokenGenesisBlock lyraGen) { var consBlock = new ConsolidationBlock { blockHashes = new List <string>() { svcGen.Hash, lyraGen.Hash }, totalBlockCount = 2 // not including self }; var mt = new MerkleTree(); mt.AppendLeaf(MerkleHash.Create(svcGen.Hash)); mt.AppendLeaf(MerkleHash.Create(lyraGen.Hash)); consBlock.MerkelTreeHash = mt.BuildTree().ToString(); consBlock.ServiceHash = svcGen.Hash; consBlock.InitializeBlock(null, NodeService.Instance.PosWallet.PrivateKey, NodeService.Instance.PosWallet.AccountId); return(consBlock); }
private async Task <bool> SyncAndVerifyConsolidationBlockAsync(ILyraAPI client, ConsolidationBlock consBlock) { _log.LogInformation($"Sync and verify consolidation block height {consBlock.Height}"); foreach (var hash in consBlock.blockHashes) { if (!await SyncOneBlockAsync(client, hash)) { return(false); } } if (null != await _sys.Storage.FindBlockByHashAsync(consBlock.Hash)) { await _sys.Storage.RemoveBlockAsync(consBlock.Hash); } var mt = new MerkleTree(); foreach (var hash1 in consBlock.blockHashes) { mt.AppendLeaf(MerkleHash.Create(hash1)); } var merkelTreeHash = mt.BuildTree().ToString(); if (consBlock.MerkelTreeHash != merkelTreeHash) { _log.LogWarning($"SyncAndVerifyConsolidationBlock: consMerkelTree: {consBlock.MerkelTreeHash} mine: {merkelTreeHash}"); return(false); } // make sure no extra blocks here if (consBlock.Height > 1) { var prevConsHash = consBlock.blockHashes.First(); var prevConsResult = await client.GetBlockByHashAsync(_sys.PosWallet.AccountId, prevConsHash, null); if (prevConsResult.ResultCode != APIResultCodes.Success) { _log.LogWarning($"SyncAndVerifyConsolidationBlock: prevConsResult.ResultCode: {prevConsResult.ResultCode}"); return(false); } var prevConsBlock = prevConsResult.GetBlock() as ConsolidationBlock; if (prevConsBlock == null) { _log.LogWarning($"SyncAndVerifyConsolidationBlock: prevConsBlock: null"); return(false); } var blocksInTimeRange = await _sys.Storage.GetBlockHashesByTimeRangeAsync(prevConsBlock.TimeStamp, consBlock.TimeStamp); var q = blocksInTimeRange.Where(a => !consBlock.blockHashes.Contains(a)); foreach (var extraBlock in q) { await _sys.Storage.RemoveBlockAsync(extraBlock); } } return(await _sys.Storage.AddBlockAsync(consBlock)); }
private void GenerateConsolidateBlock() { var authGenesis = BlockChain.Singleton.GetLastServiceBlock(); var lastCons = BlockChain.Singleton.GetSyncBlock(); var consBlock = new ConsolidationBlock { UIndex = _UIndexSeed++, NetworkId = authGenesis.NetworkId, ShardId = authGenesis.ShardId, ServiceHash = authGenesis.Hash, SvcAccountID = NodeService.Instance.PosWallet.AccountId }; // use merkle tree to consolidate all previous blocks, from lastCons.UIndex to consBlock.UIndex -1 var mt = new MerkleTree(); for (var ndx = lastCons.UIndex; ndx < consBlock.UIndex; ndx++) // TODO: handling "losing" block here { var block = BlockChain.Singleton.GetBlockByUIndex(ndx); if (block == null) { // block lost _log.LogError($"Block lost for No. {ndx}. Try to resync with other seeds..."); // triggering a resync Mode = ConsensusWorkingMode.OutofSyncWaiting; LyraSystem.Singleton.TheBlockchain.Tell(new BlockChain.NeedSync { ToUIndex = ndx }); return; } var mhash = MerkleHash.Create(block.UHash); mt.AppendLeaf(mhash); } consBlock.MerkelTreeHash = mt.BuildTree().ToString(); consBlock.InitializeBlock(lastCons, NodeService.Instance.PosWallet.PrivateKey, authGenesis.NetworkId, authGenesis.ShardId, NodeService.Instance.PosWallet.AccountId); //consBlock.UHash = SignableObject.CalculateHash($"{consBlock.UIndex}|{consBlock.Index}|{consBlock.Hash}"); //consBlock.Authorizations = new List<AuthorizationSignature>(); //consBlock.Authorizations.Add(new AuthorizationSignature //{ // Key = NodeService.Instance.PosWallet.AccountId, // Signature = Signatures.GetSignature(NodeService.Instance.PosWallet.PrivateKey, consBlock.Hash + consBlock.ServiceHash, NodeService.Instance.PosWallet.AccountId) //}); //BlockChain.Singleton.AddBlock(consBlock); //// broadcast to whole network //var msg = new ChatMsg(NodeService.Instance.PosWallet.AccountId, JsonConvert.SerializeObject(consBlock)); //msg.MsgType = ChatMessageType.BlockConsolidation; //Send2P2pNetwork(msg); // no, we do consensus AuthorizingMsg msg = new AuthorizingMsg { From = NodeService.Instance.PosWallet.AccountId, Block = consBlock, MsgType = ChatMessageType.AuthorizerPrePrepare }; var state = CreateAuthringState(msg); var localAuthResult = LocalAuthorizingAsync(msg); state.AddAuthResult(localAuthResult); if (!localAuthResult.IsSuccess) { _log.LogError("Fatal Error: Consolidate block local authorization failed."); } else { Send2P2pNetwork(msg); Send2P2pNetwork(localAuthResult); } }
private void StartInit() { if (0 == GetBlockCount() && NodeService.Instance.PosWallet.AccountId == ProtocolSettings.Default.StandbyValidators[0]) { // do genesis var authGenesis = new ServiceBlock { Index = 1, UIndex = 1, NetworkId = _nodeConfig.Lyra.NetworkId, ShardId = "Primary", TransferFee = 1, TokenGenerationFee = 100, TradeFee = 0.1m, SvcAccountID = NodeService.Instance.PosWallet.AccountId }; authGenesis.InitializeBlock(null, NodeService.Instance.PosWallet.PrivateKey, _nodeConfig.Lyra.NetworkId, authGenesis.ShardId, NodeService.Instance.PosWallet.AccountId); authGenesis.UHash = SignableObject.CalculateHash($"{authGenesis.UIndex}|{authGenesis.Index}|{authGenesis.Hash}"); authGenesis.Authorizations = new List <AuthorizationSignature>(); authGenesis.Authorizations.Add(new AuthorizationSignature { Key = NodeService.Instance.PosWallet.AccountId, Signature = Signatures.GetSignature(NodeService.Instance.PosWallet.PrivateKey, authGenesis.Hash, NodeService.Instance.PosWallet.AccountId) }); // TODO: add more seed's auth info _store.AddBlock(authGenesis); // the first consolidate block var consBlock = new ConsolidationBlock { UIndex = 2, NetworkId = authGenesis.NetworkId, ShardId = authGenesis.ShardId, ServiceHash = authGenesis.Hash, SvcAccountID = NodeService.Instance.PosWallet.AccountId }; consBlock.InitializeBlock(authGenesis, NodeService.Instance.PosWallet.PrivateKey, _nodeConfig.Lyra.NetworkId, authGenesis.ShardId, NodeService.Instance.PosWallet.AccountId); consBlock.UHash = SignableObject.CalculateHash($"{consBlock.UIndex}|{consBlock.Index}|{consBlock.Hash}"); consBlock.Authorizations = new List <AuthorizationSignature>(); consBlock.Authorizations.Add(new AuthorizationSignature { Key = NodeService.Instance.PosWallet.AccountId, Signature = Signatures.GetSignature(NodeService.Instance.PosWallet.PrivateKey, consBlock.Hash + consBlock.ServiceHash, NodeService.Instance.PosWallet.AccountId) }); _store.AddBlock(consBlock); // tell consensus what happened InSyncing = false; var board = new BillBoard(); board.Add(NodeService.Instance.PosWallet.AccountId); // add me! LyraSystem.Singleton.Consensus.Tell(board); LyraSystem.Singleton.Consensus.Tell(new ConsensusService.BlockChainSynced()); _log.LogInformation("Service Genesis Completed."); } else { SyncBlocksFromSeeds(0); } }