Пример #1
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);
        }
Пример #2
0
        public void CreateUnbalancedTreeTest()
        {
            MerkleTree tree = new MerkleTree();

            tree.AppendLeaf(MerkleHash.Create("abc"));
            tree.AppendLeaf(MerkleHash.Create("def"));
            tree.AppendLeaf(MerkleHash.Create("123"));
            tree.BuildTree();
            Assert.NotNull(tree.RootNode);
        }
Пример #3
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);
        }
Пример #4
0
        public void ConsistencyTest()
        {
            // Start with a tree with 2 leaves:
            MerkleTree tree          = new MerkleTree();
            var        startingNodes = tree.AppendLeaves(new MerkleHash[]
            {
                MerkleHash.Create("1"),
                MerkleHash.Create("2"),
            });

            // startingNodes.ForEachWithIndex((n, i) => n.Text = i.ToString());

            MerkleHash firstRoot = tree.BuildTree();

            List <MerkleHash> oldRoots = new List <MerkleHash>()
            {
                firstRoot
            };

            // Add a new leaf and verify that each time we add a leaf, we can get a consistency check
            // for all the previous leaves.
            for (int i = 2; i < 100; i++)
            {
                tree.AppendLeaf(MerkleHash.Create(i.ToString())); //.Text=i.ToString();
                tree.BuildTree();

                // After adding a leaf, verify that all the old root hashes exist.
                oldRoots.ForEachWithIndex((oldRootHash, n) =>
                {
                    List <MerkleProofHash> proof = tree.ConsistencyProof(n + 2);
                    MerkleHash hash, lhash, rhash;

                    if (proof.Count > 1)
                    {
                        lhash    = proof[proof.Count - 2].Hash;
                        int hidx = proof.Count - 1;
                        hash     = rhash = MerkleTree.ComputeHash(lhash, proof[hidx].Hash);
                        hidx    -= 2;

                        while (hidx >= 0)
                        {
                            lhash = proof[hidx].Hash;
                            hash  = rhash = MerkleTree.ComputeHash(lhash, rhash);

                            --hidx;
                        }
                    }
                    else
                    {
                        hash = proof[0].Hash;
                    }

                    Assert.True(hash == oldRootHash, "Old root hash not found for index " + i + " m = " + (n + 2).ToString());
                });

                // Then we add this root hash as the next old root hash to check.
                oldRoots.Add(tree.RootNode.Hash);
            }
        }
Пример #5
0
 private void BuildMerkleTree()
 {
     merkleTree = new MerkleTree();
     foreach (var txn in Transactions)
     {
         merkleTree.AppendLeaf(MerkleHash.Create(txn.CalculateTransactionHash()));
     }
     merkleTree.BuildTree();
 }
Пример #6
0
        private void BuildMerkleTree()
        {
            _merkleTree = new MerkleTree();
            foreach (ITransaction transaction in Transactions)
            {
                _merkleTree.AppendLeaf(MerkleHash.Create(transaction.CalculateTransactionHash()));
            }

            _merkleTree.BuildTree();
        }
Пример #7
0
        public void BuildMerkleTree()
        {
            merkleTreeObj = new MerkleTree();

            foreach (ITransaction transaction in Transaction)
            {
                merkleTreeObj.AppendLeaf(MerkleHash.Create(transaction.CalculateTransactionHash()));
            }

            merkleTreeObj.BuildTree();
        }
Пример #8
0
        public void CreateTree(MerkleTree tree, int numLeaves)
        {
            List <DemoMerkleNode> leaves = new List <DemoMerkleNode>();

            for (int i = 0; i < numLeaves; i++)
            {
                tree.AppendLeaf(DemoMerkleNode.Create(i.ToString()).SetText(i.ToString("X")));
            }

            tree.BuildTree();
        }
Пример #9
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);
        }
Пример #10
0
        public string GetUnConsolidatedHash(List <string> unCons)
        {
            if (unCons.Count() == 0)
            {
                return(null);
            }

            var mt = new MerkleTree();

            foreach (var hash in unCons)
            {
                mt.AppendLeaf(MerkleHash.Create(hash));
            }

            return(mt.BuildTree().ToString());
        }
Пример #11
0
        public void RootNodeTest()
        {
            var tree = new MerkleTree();

            for (int i = 0; i <= 65; i++)
            {
                tree.AppendLeaf(new MerkleNode(MerkleHash.Create(i.ToString())));
                Assert.Equal(tree.CurrentParent.Root.Hash, tree.RootNode.Hash);
            }

            tree = new MerkleTree();
            for (int i = 0; i <= 65; i++)
            {
                tree.AppendLeaf(new MerkleNode(MerkleHash.Create(i.ToString())));
            }
            Assert.Equal(tree.CurrentParent.Root.Hash, tree.RootNode.Hash);
        }
Пример #12
0
        public async Task <MultiBlockAPIResult> GetBlocksByConsolidation(string AccountId, string Signature, string consolidationHash)
        {
            var result = new MultiBlockAPIResult();

            if (!await VerifyClientAsync(AccountId, Signature))
            {
                result.ResultCode = APIResultCodes.APISignatureValidationFailed;
                return(result);
            }

            var consBlock = (await BlockChain.Singleton.FindBlockByHashAsync(consolidationHash)) as ConsolidationBlock;

            if (consBlock == null)
            {
                result.ResultCode = APIResultCodes.BlockNotFound;
                return(result);
            }

            var mt     = new MerkleTree();
            var blocks = new Block[consBlock.blockHashes.Count];

            for (int i = 0; i < blocks.Length; i++)
            {
                blocks[i] = await BlockChain.Singleton.FindBlockByHashAsync(consBlock.blockHashes[i]);

                mt.AppendLeaf(MerkleHash.Create(blocks[i].Hash));
            }
            var merkelTreeHash = mt.BuildTree().ToString();

            if (consBlock.MerkelTreeHash == merkelTreeHash)
            {
                result.SetBlocks(blocks);
                result.ResultCode = APIResultCodes.Success;
                return(result);
            }
            else
            {
                // never replicate error data
                result.ResultCode = APIResultCodes.BlockValidationFailed;
                return(result);
            }
        }
Пример #13
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));
        }
        protected override async Task <APIResultCodes> AuthorizeImplAsync <T>(DagSystem sys, T tblock)
        {
            if (!(tblock is ConsolidationBlock))
            {
                return(APIResultCodes.InvalidBlockType);
            }

            var block = tblock as ConsolidationBlock;

            //// 1. check if the block already exists
            //if (null != await DagSystem.Singleton.Storage.GetBlockByUIndexAsync(block.UIndex))
            //    return APIResultCodes.BlockWithThisUIndexAlreadyExists;

            var lastCons = await sys.Storage.GetLastConsolidationBlockAsync();

            if (block.Height > 1)
            {
                if (lastCons == null)
                {
                    return(APIResultCodes.CouldNotFindLatestBlock);
                }

                // make sure the first hash is ALWAYS the previous consblock (except the first one)
                if (block.blockHashes.First() != lastCons.Hash)
                {
                    return(APIResultCodes.InvalidConsolidationBlockContinuty);
                }

                var allHashes = (await sys.Storage.GetBlockHashesByTimeRangeAsync(lastCons.TimeStamp, block.TimeStamp)).ToList();
                if (block.blockHashes.Count != allHashes.Count)
                {
                    Console.WriteLine($"real count: {allHashes.Count} but block has: {block.blockHashes.Count}");
                    return(APIResultCodes.InvalidConsolidationBlockCount);
                }

                var mineNotYours = allHashes.Except(block.blockHashes).ToList();
                var yoursNotMine = block.blockHashes.Except(allHashes).ToList();
                if (mineNotYours.Any() || yoursNotMine.Any())
                {
                    return(APIResultCodes.InvalidConsolidationBlockHashes);
                }
            }

            // recalculate merkeltree
            // use merkle tree to consolidate all previous blocks, from lastCons.UIndex to consBlock.UIndex -1
            var     mt            = new MerkleTree();
            decimal feeAggregated = 0;

            foreach (var hash in block.blockHashes)
            {
                mt.AppendLeaf(MerkleHash.Create(hash));

                // verify block exists
                if (null == await sys.Storage.FindBlockByHashAsync(hash))
                {
                    return(APIResultCodes.BlockNotFound);
                }

                // aggregate fees
                var transBlock = (await sys.Storage.FindBlockByHashAsync(hash)) as TransactionBlock;
                if (transBlock != null)
                {
                    feeAggregated += transBlock.Fee;
                }
            }

            var mkhash = mt.BuildTree().ToString();

            if (block.MerkelTreeHash != mkhash)
            {
                return(APIResultCodes.InvalidConsolidationMerkleTreeHash);
            }

            if (block.totalFees != feeAggregated.ToBalanceLong())
            {
                return(APIResultCodes.InvalidConsolidationTotalFees);
            }

            // consolidation must come from leader node
            // done in base authorizer already!

            return(await Lyra.Shared.StopWatcher.TrackAsync(() => base.AuthorizeImplAsync(sys, tblock), "ConsolidationBlockAuthorizer->BaseAuthorizer"));
        }
        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);
            }
        }