예제 #1
0
        private OutputMsg getOutputMsg(BlockPoolItem node, string outputTxHash, int outputIndex, out long blockHeight)
        {
            foreach (var tx in node.Block.Transactions)
            {
                if (tx.Hash == outputTxHash && tx.Outputs.Count > outputIndex)
                {
                    var msg = tx.Outputs[outputIndex];
                    blockHeight = node.Block.Header.Height;
                    return(msg);
                }
            }

            foreach (var child in node.Children)
            {
                long height;
                var  msg = this.getOutputMsg(child, outputTxHash, outputIndex, out height);

                if (msg != null)
                {
                    blockHeight = height;
                    return(msg);
                }
            }

            blockHeight = -1;
            return(null);
        }
예제 #2
0
        public BlockPoolItem AddChild(BlockPoolItem child)
        {
            child.Parent = this;
            this.Children.Add(child);

            return(child);
        }
예제 #3
0
        private void getOutputsByAccountId(BlockPoolItem node, string accountId, Dictionary <string, List <OutputMsg> > dict)
        {
            foreach (var tx in node.Block.Transactions)
            {
                if (!dict.ContainsKey(tx.Hash))
                {
                    dict.Add(tx.Hash, new List <OutputMsg>());
                }

                foreach (var output in tx.Outputs)
                {
                    var publicKeyHash = Script.GetPublicKeyHashFromLockScript(output.LockScript);
                    var id            = AccountIdHelper.CreateAccountAddressByPublicKeyHash(Base16.Decode(publicKeyHash));

                    if (id == accountId)
                    {
                        dict[tx.Hash].Add(output);
                    }
                }
            }

            foreach (var child in node.Children)
            {
                getOutputsByAccountId(child, accountId, dict);
            }
        }
예제 #4
0
        private bool checkUTXOSpent(BlockPoolItem node, string currentTxHash, string outputTxHash, int outputIndex)
        {
            foreach (var tx in node.Block.Transactions)
            {
                if (tx.Hash == currentTxHash)
                {
                    continue;
                }

                foreach (var input in tx.Inputs)
                {
                    if (input.OutputTransactionHash == outputTxHash && input.OutputIndex == outputIndex)
                    {
                        return(true);
                    }
                }
            }

            foreach (var child in node.Children)
            {
                var result = this.checkUTXOSpent(child, currentTxHash, outputTxHash, outputIndex);

                if (result)
                {
                    return(true);
                }
            }

            return(false);
        }
예제 #5
0
        private void countNodes(BlockPoolItem node, ref int count)
        {
            count++;

            foreach (var child in node.Children)
            {
                countNodes(child, ref count);
            }
        }
예제 #6
0
        private void reculculateTotalDifficulty(BlockPoolItem node, long difficulty)
        {
            node.TotalDifficulty = difficulty;

            if (node.Parent != null)
            {
                reculculateTotalDifficulty(node.Parent, difficulty + new POW(node.Parent.Block.Header.Height).ConvertBitsToDifficulty(node.Parent.Block.Header.Bits));
            }
        }
예제 #7
0
        private void recalculateDeep(BlockPoolItem node, int deep)
        {
            node.Depth = deep;

            if (node.Parent != null)
            {
                recalculateDeep(node.Parent, deep + 1);
            }
        }
예제 #8
0
 public BlockPoolItem GetRootByNode(BlockPoolItem node)
 {
     if (node.Parent == null)
     {
         return(node);
     }
     else
     {
         return(GetRootByNode(node.Parent));
     }
 }
예제 #9
0
 private void getBlockByHeight(BlockPoolItem item, long height, List <BlockPoolItem> items)
 {
     if (item.Block.Header.Height == height)
     {
         items.Add(item);
     }
     else
     {
         foreach (var child in item.Children)
         {
             this.getBlockByHeight(child, height, items);
         }
     }
 }
예제 #10
0
 public void GetLeavesByNode(BlockPoolItem node, List <BlockPoolItem> leaves)
 {
     if (node.Children.Count == 0)
     {
         this.Leaves.Add(node);
     }
     else
     {
         foreach (var child in node.Children)
         {
             this.GetLeavesByNode(child, leaves);
         }
     }
 }
예제 #11
0
        public BlockMsg GetLatestBlock()
        {
            BlockPoolItem selectedNode = this.Leaves.OrderByDescending(l => l.Block.Header.Height).
                                         ThenBy(l => l.Block.Header.Timestamp).FirstOrDefault();

            if (selectedNode != null)
            {
                return(selectedNode.Block);
            }
            else
            {
                return(null);
            }
        }
예제 #12
0
 private BlockPoolItem searchNodeByHash(BlockPoolItem node, string prevHash)
 {
     if (node.Block.Header.Hash == prevHash)
     {
         return(node);
     }
     else
     {
         if (node.Parent != null)
         {
             return(searchNodeByHash(node.Parent, prevHash));
         }
         else
         {
             return(null);
         }
     }
 }
예제 #13
0
        private BlockMsg getBlockByHash(BlockPoolItem node, string hash)
        {
            if (node.Block.Header.Hash == hash)
            {
                return(node.Block);
            }
            else
            {
                foreach (var child in node.Children)
                {
                    var msg = this.getBlockByHash(child, hash);

                    if (msg != null)
                    {
                        return(msg);
                    }
                }
            }

            return(null);
        }
예제 #14
0
        private TransactionMsg getTransactionByHash(BlockPoolItem node, string transactionHash)
        {
            foreach (var tx in node.Block.Transactions)
            {
                if (tx.Hash == transactionHash)
                {
                    return(tx);
                }
            }

            foreach (var child in node.Children)
            {
                var msg = this.getTransactionByHash(child, transactionHash);

                if (msg != null)
                {
                    return(msg);
                }
            }

            return(null);
        }
예제 #15
0
        public BlockMsg GetVerifiedBlock()
        {
            try
            {
                BlockPoolItem selectedNode = this.RootList.Where(r => r.Block.Header.PreviousBlockHash == this.LastDBBlockHash).
                                             OrderByDescending(r => r.Depth).
                                             ThenByDescending(r => r.TotalDifficulty).
                                             FirstOrDefault();

                if (selectedNode != null && selectedNode.Depth + 1 > BlockSetting.VERIFIED_BLOCKS)
                {
                    return(selectedNode.Block);
                }
                else
                {
                    return(null);
                }
            }
            catch (Exception)
            {
                return(null);
            }
        }
예제 #16
0
        public BlockMsg SearchBlockByHash(string hash)
        {
            BlockPoolItem result = null;

            foreach (var node in Leaves)
            {
                result = searchNodeByHash(node, hash);

                if (result != null)
                {
                    break;
                }
            }

            if (result != null)
            {
                return(result.Block);
            }
            else
            {
                return(null);
            }
        }
예제 #17
0
        public void AddBlock(BlockMsg block)
        {
            var newNode = new BlockPoolItem(block);

            //Check with root list
            for (int i = 0; i < this.RootList.Count; i++)
            {
                if (RootList[i].Block.Header.PreviousBlockHash == block.Header.Hash)
                {
                    newNode.AddChild(this.RootList[i]);
                    RootList.RemoveAt(i);
                    break;
                }
            }

            //Search in leaves
            for (int i = 0; i < this.Leaves.Count; i++)
            {
                var leaf = this.Leaves[i];

                if (leaf.Block.Header.Hash == block.Header.PreviousBlockHash)
                {
                    //add new node into leaves, and remove parent from leaves
                    leaf.AddChild(newNode);
                    Leaves.RemoveAt(i);
                    break;
                }
            }

            //Search in parents
            if (newNode.Parent == null)
            {
                for (int i = 0; i < Leaves.Count; i++)
                {
                    var leaf   = Leaves[i];
                    var result = searchNodeByHash(leaf, block.Header.PreviousBlockHash);

                    if (result != null)
                    {
                        result.AddChild(newNode);
                        //Leaves.Add(child);
                        //Leaves.RemoveAt(i);
                        break;
                    }
                }
            }

            if (newNode.Parent == null)
            {
                this.RootList.Add(newNode);
            }

            if (newNode.Children.Count == 0)
            {
                this.Leaves.Add(newNode);
            }

            this.recalculateDeep();

            if (block.Header.Height > this.LatestHeight)
            {
                this.LatestHeight = block.Header.Height;
            }
        }
예제 #18
0
        public void TakeOutVerifiedBlock()
        {
            //get the node with max depth in the root list
            BlockPoolItem selectedNode = this.RootList.Where(r => r.Block.Header.PreviousBlockHash == this.LastDBBlockHash).
                                         OrderByDescending(r => r.Depth).
                                         ThenByDescending(r => r.TotalDifficulty).
                                         FirstOrDefault();

            if (selectedNode.Children.Count == 0)
            {
                return;
            }

            for (int i = this.RootList.Count; i > 0; i--)
            {
                var root = this.RootList[i - 1];

                //remove the nodes that block height same with or less than selected node
                if (root.Block.Header.PreviousBlockHash == selectedNode.Block.Header.PreviousBlockHash ||
                    root.Block.Header.Height <= selectedNode.Block.Header.Height)
                {
                    if (root.Block.Header.Hash == selectedNode.Block.Header.Hash)
                    {
                        //get the max depth child node
                        var childNode = selectedNode.Children.
                                        OrderByDescending(c => c.Depth).
                                        ThenByDescending(r => r.TotalDifficulty).
                                        FirstOrDefault();
                        this.RootList[i - 1] = childNode;


                        for (int j = root.Children.Count; j > 0; j--)
                        {
                            var child = root.Children[j - 1];

                            //remove other children nodes
                            if (child.Block.Header.Hash != childNode.Block.Header.Hash)
                            {
                                var leaves = new List <BlockPoolItem>();
                                this.GetLeavesByNode(child, leaves);

                                //remove leaves of current child node
                                foreach (var leaf in leaves)
                                {
                                    this.Leaves.Remove(leaf);
                                }
                            }

                            root.Children.RemoveAt(j - 1);
                            child = null;
                        }
                    }
                    else
                    {
                        var leaves = new List <BlockPoolItem>();
                        this.GetLeavesByNode(root, leaves);

                        //remove the leaves of current node
                        foreach (var leaf in leaves)
                        {
                            this.Leaves.Remove(leaf);
                        }

                        this.RootList.RemoveAt(i - 1);
                        root = null;
                    }

                    break;
                }
            }

            //update db block hash and height
            this.LastDBBlockHash = selectedNode.Block.Header.Hash;
            this.DBHeight        = selectedNode.Block.Header.Height;
        }