Beispiel #1
0
        private void Parse()
        {
            if (this.children != null)
            {
                return;
            }

            Resolve();

            LList list = this.parsed_rlp == null?RLP.DecodeLazyList(this.rlp) : this.parsed_rlp;

            if (list != null && list.Count == 2)
            {
                this.children = new object[2];
                TrieKey key = TrieKey.FromPacked(list.GetBytes(0));
                this.children[0] = key;
                if (key.IsTerminal)
                {
                    this.children[1] = list.GetBytes(1);
                }
                else
                {
                    this.children[1] = list.IsList(1) ? new TrieNode(this.reference, list.GetList(1)) : new TrieNode(this.reference, list.GetBytes(1));
                }
            }
            else
            {
                this.children   = new object[17];
                this.parsed_rlp = list;
            }
        }
Beispiel #2
0
        public void ScanTree(TrieNode node, TrieKey key, IScanAction scan_action)
        {
            if (node != null)
            {
                if (node.Hash != null)
                {
                    scan_action.OnNode(node.Hash, node);
                }

                if (node.NodeType == TrieNode.TrieNodeType.BranchNode)
                {
                    if (node.BranchNodeGetValue() != null)
                    {
                        scan_action.OnValue(node.Hash, node, key.ToNormal(), node.BranchNodeGetValue());
                    }

                    for (int i = 0; i < 16; i++)
                    {
                        ScanTree(node.BranchNodeGetChild(i), key.Concat(TrieKey.SingleHex(i)), scan_action);
                    }
                }
                else if (node.NodeType == TrieNode.TrieNodeType.KVNodeNode)
                {
                    ScanTree(node.KVNodeGetChildNode(), key.Concat(node.KVNodeGetKey()), scan_action);
                }
                else
                {
                    scan_action.OnValue(node.Hash, node, key.Concat(node.KVNodeGetKey()).ToNormal(), node.KVNodeGetValue());
                }
            }
        }
Beispiel #3
0
        public byte[] Get(TrieNode node, TrieKey key)
        {
            if (node == null)
            {
                return(null);
            }

            if (node.NodeType == TrieNode.TrieNodeType.BranchNode)
            {
                if (key.IsEmpty)
                {
                    return(node.BranchNodeGetValue());
                }
                TrieNode child = node.BranchNodeGetChild(key.GetHex(0));
                return(Get(child, key.Shift(1)));
            }
            else
            {
                TrieKey k = key.MatchAndShift(node.KVNodeGetKey());
                if (k == null)
                {
                    return(null);
                }

                if (node.NodeType == TrieNode.TrieNodeType.KVNodeValue)
                {
                    return(k.IsEmpty ? node.KVNodeGetValue() : null);
                }
                else
                {
                    return(Get(node.KVNodeGetChildNode(), k));
                }
            }
        }
Beispiel #4
0
        public static TrieKey SingleHex(int hex)
        {
            TrieKey ret = new TrieKey(new byte[1], 1, false);

            ret.SetHex(0, hex);
            return(ret);
        }
Beispiel #5
0
        public override bool Equals(object obj)
        {
            if (obj == null)
            {
                return(false);
            }
            if (GetType() != obj.GetType())
            {
                return(false);
            }
            TrieKey k   = (TrieKey)obj;
            int     len = GetLength();

            if (len != k.GetLength())
            {
                return(false);
            }
            for (int i = 0; i < len; i++)
            {
                if (GetHex(i) != k.GetHex(i))
                {
                    return(false);
                }
            }
            return(IsTerminal == k.IsTerminal);
        }
Beispiel #6
0
        public void Delete(byte[] key)
        {
            TrieKey k = TrieKey.FromNormal(key);

            if (this.root != null)
            {
                this.root = Delete(this.root, k);
            }
        }
Beispiel #7
0
        public byte[] Get(byte[] key)
        {
            if (!HasRoot)
            {
                return(null);
            }

            return(Get(root, TrieKey.FromNormal(key)));
        }
Beispiel #8
0
        public TrieKey GetCommonPrefix(TrieKey k)
        {
            int prefix_length = 0;
            int thisLength    = GetLength();
            int klen          = k.GetLength();

            while (prefix_length < thisLength && prefix_length < klen && GetHex(prefix_length) == k.GetHex(prefix_length))
            {
                prefix_length++;
            }
            byte[]  prefix_key = new byte[(prefix_length + 1) >> 1];
            TrieKey ret        = new TrieKey(prefix_key, (prefix_length & 1) == 0 ? 0 : 1,
                                             prefix_length == GetLength() && prefix_length == k.GetLength() && terminal && k.IsTerminal);

            for (int i = 0; i < prefix_length; i++)
            {
                ret.SetHex(i, k.GetHex(i));
            }
            return(ret);
        }
Beispiel #9
0
        public TrieKey MatchAndShift(TrieKey k)
        {
            int len  = GetLength();
            int klen = k.GetLength();

            if (len < klen)
            {
                return(null);
            }

            if ((this.off & 1) == (k.off & 1))
            {
                // optimization to compare whole keys bytes
                if ((this.off & 1) == 1 && GetHex(0) != k.GetHex(0))
                {
                    return(null);
                }
                int idx1 = (this.off + 1) >> 1;
                int idx2 = (k.off + 1) >> 1;
                int l    = klen >> 1;
                for (int i = 0; i < l; i++, idx1++, idx2++)
                {
                    if (this.key[idx1] != k.key[idx2])
                    {
                        return(null);
                    }
                }
            }
            else
            {
                for (int i = 0; i < klen; i++)
                {
                    if (GetHex(i) != k.GetHex(i))
                    {
                        return(null);
                    }
                }
            }
            return(Shift(klen));
        }
Beispiel #10
0
        public void Put(byte[] key, byte[] value)
        {
            TrieKey k = TrieKey.FromNormal(key);

            if (this.root == null)
            {
                if (value != null && value.Length > 0)
                {
                    this.root = new TrieNode(this, k, value);
                }
            }
            else
            {
                if (value == null || value.Length == 0)
                {
                    this.root = Delete(this.root, k);
                }
                else
                {
                    this.root = Insert(root, k, value);
                }
            }
        }
Beispiel #11
0
        public TrieKey Concat(TrieKey k)
        {
            if (IsTerminal)
            {
                throw new System.Exception("Can' append to terminal key: " + this + " + " + k);
            }
            int len     = GetLength();
            int klen    = k.GetLength();
            int new_len = len + klen;

            byte[]  newKeyBytes = new byte[(new_len + 1) >> 1];
            TrieKey ret         = new TrieKey(newKeyBytes, new_len & 1, k.IsTerminal);

            for (int i = 0; i < len; i++)
            {
                ret.SetHex(i, GetHex(i));
            }
            for (int i = 0; i < klen; i++)
            {
                ret.SetHex(len + i, k.GetHex(i));
            }
            return(ret);
        }
Beispiel #12
0
 public TrieNode(Trie reference, TrieKey key, object value_or_node)
     : this(reference, new object[] { key, value_or_node })
 {
     this.reference = reference;
     dirty          = true;
 }
Beispiel #13
0
        private TrieNode Insert(TrieNode node, TrieKey key, object node_or_value)
        {
            if (node.NodeType == TrieNode.TrieNodeType.BranchNode)
            {
                if (key.IsEmpty)
                {
                    return(node.BranchNodeSetValue((byte[])node_or_value));
                }
                TrieNode child = node.BranchNodeGetChild(key.GetHex(0));
                if (child != null)
                {
                    return(node.BranchNodeSetChild(key.GetHex(0), Insert(child, key.Shift(1), node_or_value)));
                }
                else
                {
                    TrieKey  child_key = key.Shift(1);
                    TrieNode new_child;
                    if (!child_key.IsEmpty)
                    {
                        new_child = new TrieNode(this, child_key, node_or_value);
                    }
                    else
                    {
                        new_child = node_or_value is TrieNode ? (TrieNode)node_or_value : new TrieNode(this, child_key, node_or_value);
                    }
                    return(node.BranchNodeSetChild(key.GetHex(0), new_child));
                }
            }
            else
            {
                TrieKey current_node_key = node.KVNodeGetKey();
                TrieKey common_prefix    = key.GetCommonPrefix(current_node_key);
                if (common_prefix.IsEmpty)
                {
                    TrieNode new_branch = new TrieNode(this);
                    Insert(new_branch, current_node_key, node.KVNodeGetValueOrNode());
                    Insert(new_branch, key, node_or_value);
                    node.Dispose();
                    return(new_branch);
                }
                else if (common_prefix.Equals(key))
                {
                    return(node.KVNodeSetValueOrNode(node_or_value));
                }
                else if (common_prefix.Equals(current_node_key))
                {
                    Insert(node.KVNodeGetChildNode(), key.Shift(common_prefix.GetLength()), node_or_value);
                    return(node.Invalidate());
                }
                else
                {
                    TrieNode new_branch = new TrieNode(this);
                    TrieNode newKvNode  = new TrieNode(this, common_prefix, new_branch);

                    Insert(newKvNode, current_node_key, node.KVNodeGetValueOrNode());
                    Insert(newKvNode, key, node_or_value);
                    node.Dispose();
                    return(newKvNode);
                }
            }
        }
Beispiel #14
0
 public void ScanTree(IScanAction scan_action)
 {
     ScanTree(this.root, TrieKey.Empty(false), scan_action);
 }
Beispiel #15
0
        public TrieNode Delete(TrieNode node, TrieKey key)
        {
            TrieNode kv_node = null;

            if (node.NodeType == TrieNode.TrieNodeType.BranchNode)
            {
                if (key.IsEmpty)
                {
                    node.BranchNodeSetValue(null);
                }
                else
                {
                    int      index = key.GetHex(0);
                    TrieNode child = node.BranchNodeGetChild(index);
                    if (child == null)
                    {
                        return(node);
                    }

                    TrieNode new_node = Delete(child, key.Shift(1));
                    node.BranchNodeSetChild(index, new_node);
                    if (new_node != null)
                    {
                        return(node);
                    }
                }

                int compact_index = node.BranchNodeCompactIndex();
                if (compact_index < 0)
                {
                    return(node);
                }

                node.Dispose();
                if (compact_index == 16)
                {
                    return(new TrieNode(this, TrieKey.Empty(true), node.BranchNodeGetValue()));
                }
                else
                {
                    kv_node = new TrieNode(this, TrieKey.SingleHex(compact_index), node.BranchNodeGetChild(compact_index));
                }
            }
            else
            {
                TrieKey k = key.MatchAndShift(node.KVNodeGetKey());
                if (k == null)
                {
                    return(node);
                }
                else if (node.NodeType == TrieNode.TrieNodeType.KVNodeValue)
                {
                    if (k.IsEmpty)
                    {
                        node.Dispose();
                        return(null);
                    }
                    else
                    {
                        return(node);
                    }
                }
                else
                {
                    TrieNode child = Delete(node.KVNodeGetChildNode(), k);
                    if (child == null)
                    {
                        throw new System.Exception("Shouldn't happen");
                    }

                    kv_node = node.KVNodeSetValueOrNode(child);
                }
            }

            TrieNode new_child = kv_node.KVNodeGetChildNode();

            if (new_child.NodeType != TrieNode.TrieNodeType.BranchNode)
            {
                TrieKey  new_key  = kv_node.KVNodeGetKey().Concat(new_child.KVNodeGetKey());
                TrieNode new_node = new TrieNode(this, new_key, new_child.KVNodeGetValueOrNode());
                new_child.Dispose();
                kv_node.Dispose();

                return(new_node);
            }
            else
            {
                return(kv_node);
            }
        }