Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
                }
            }
        }
Example #4
0
        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);
        }
Example #5
0
        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);
            }
        }