@ -56,9 +56,8 @@ func returnToPool(st *StackTrie) {
type StackTrie struct {
type StackTrie struct {
nodeType uint8 // node type (as in branch, ext, leaf)
nodeType uint8 // node type (as in branch, ext, leaf)
val [ ] byte // value contained by this node if it's a leaf
val [ ] byte // value contained by this node if it's a leaf
key [ ] byte // key chunk covered by this (full|ext) node
key [ ] byte // key chunk covered by this (leaf|ext) node
keyOffset int // offset of the key chunk inside a full key
children [ 16 ] * StackTrie // list of children (for branch and exts)
children [ 16 ] * StackTrie // list of children (for fullnodes and exts)
db ethdb . KeyValueWriter // Pointer to the commit db, can be nil
db ethdb . KeyValueWriter // Pointer to the commit db, can be nil
}
}
@ -93,12 +92,10 @@ func (st *StackTrie) MarshalBinary() (data []byte, err error) {
Nodetype uint8
Nodetype uint8
Val [ ] byte
Val [ ] byte
Key [ ] byte
Key [ ] byte
KeyOffset uint8
} {
} {
st . nodeType ,
st . nodeType ,
st . val ,
st . val ,
st . key ,
st . key ,
uint8 ( st . keyOffset ) ,
} ) ; err != nil {
} ) ; err != nil {
return nil , err
return nil , err
}
}
@ -129,13 +126,11 @@ func (st *StackTrie) unmarshalBinary(r io.Reader) error {
Nodetype uint8
Nodetype uint8
Val [ ] byte
Val [ ] byte
Key [ ] byte
Key [ ] byte
KeyOffset uint8
}
}
gob . NewDecoder ( r ) . Decode ( & dec )
gob . NewDecoder ( r ) . Decode ( & dec )
st . nodeType = dec . Nodetype
st . nodeType = dec . Nodetype
st . val = dec . Val
st . val = dec . Val
st . key = dec . Key
st . key = dec . Key
st . keyOffset = int ( dec . KeyOffset )
var hasChild = make ( [ ] byte , 1 )
var hasChild = make ( [ ] byte , 1 )
for i := range st . children {
for i := range st . children {
@ -160,20 +155,18 @@ func (st *StackTrie) setDb(db ethdb.KeyValueWriter) {
}
}
}
}
func newLeaf ( ko int , k ey , val [ ] byte , db ethdb . KeyValueWriter ) * StackTrie {
func newLeaf ( key , val [ ] byte , db ethdb . KeyValueWriter ) * StackTrie {
st := stackTrieFromPool ( db )
st := stackTrieFromPool ( db )
st . nodeType = leafNode
st . nodeType = leafNode
st . keyOffset = ko
st . key = append ( st . key , key ... )
st . key = append ( st . key , key [ ko : ] ... )
st . val = val
st . val = val
return st
return st
}
}
func newExt ( ko int , k ey [ ] byte , child * StackTrie , db ethdb . KeyValueWriter ) * StackTrie {
func newExt ( key [ ] byte , child * StackTrie , db ethdb . KeyValueWriter ) * StackTrie {
st := stackTrieFromPool ( db )
st := stackTrieFromPool ( db )
st . nodeType = extNode
st . nodeType = extNode
st . keyOffset = ko
st . key = append ( st . key , key ... )
st . key = append ( st . key , key [ ko : ] ... )
st . children [ 0 ] = child
st . children [ 0 ] = child
return st
return st
}
}
@ -211,17 +204,18 @@ func (st *StackTrie) Reset() {
st . children [ i ] = nil
st . children [ i ] = nil
}
}
st . nodeType = emptyNode
st . nodeType = emptyNode
st . keyOffset = 0
}
}
// Helper function that, given a full key, determines the index
// Helper function that, given a full key, determines the index
// at which the chunk pointed by st.keyOffset is different from
// at which the chunk pointed by st.keyOffset is different from
// the same chunk in the full key.
// the same chunk in the full key.
func ( st * StackTrie ) getDiffIndex ( key [ ] byte ) int {
func ( st * StackTrie ) getDiffIndex ( key [ ] byte ) int {
diffindex := 0
for idx , nibble := range st . key {
for ; diffindex < len ( st . key ) && st . key [ diffindex ] == key [ st . keyOffset + diffindex ] ; diffindex ++ {
if nibble != key [ idx ] {
return idx
}
}
return diffindex
}
return len ( st . key )
}
}
// Helper function to that inserts a (key, value) pair into
// Helper function to that inserts a (key, value) pair into
@ -229,7 +223,7 @@ func (st *StackTrie) getDiffIndex(key []byte) int {
func ( st * StackTrie ) insert ( key , value [ ] byte ) {
func ( st * StackTrie ) insert ( key , value [ ] byte ) {
switch st . nodeType {
switch st . nodeType {
case branchNode : /* Branch */
case branchNode : /* Branch */
idx := int ( key [ st . keyOffset ] )
idx := int ( key [ 0 ] )
// Unresolve elder siblings
// Unresolve elder siblings
for i := idx - 1 ; i >= 0 ; i -- {
for i := idx - 1 ; i >= 0 ; i -- {
if st . children [ i ] != nil {
if st . children [ i ] != nil {
@ -241,10 +235,10 @@ func (st *StackTrie) insert(key, value []byte) {
}
}
// Add new child
// Add new child
if st . children [ idx ] == nil {
if st . children [ idx ] == nil {
st . children [ idx ] = stackTrieFromPool ( st . db )
st . children [ idx ] = newLeaf ( key [ 1 : ] , value , st . db )
st . children [ idx ] . keyOffset = st . keyOffset + 1
} else {
st . children [ idx ] . insert ( key [ 1 : ] , value )
}
}
st . children [ idx ] . insert ( key , value )
case extNode : /* Ext */
case extNode : /* Ext */
// Compare both key chunks and see where they differ
// Compare both key chunks and see where they differ
diffidx := st . getDiffIndex ( key )
diffidx := st . getDiffIndex ( key )
@ -257,7 +251,7 @@ func (st *StackTrie) insert(key, value []byte) {
if diffidx == len ( st . key ) {
if diffidx == len ( st . key ) {
// Ext key and key segment are identical, recurse into
// Ext key and key segment are identical, recurse into
// the child node.
// the child node.
st . children [ 0 ] . insert ( key , value )
st . children [ 0 ] . insert ( key [ diffidx : ] , value )
return
return
}
}
// Save the original part. Depending if the break is
// Save the original part. Depending if the break is
@ -266,7 +260,7 @@ func (st *StackTrie) insert(key, value []byte) {
// node directly.
// node directly.
var n * StackTrie
var n * StackTrie
if diffidx < len ( st . key ) - 1 {
if diffidx < len ( st . key ) - 1 {
n = newExt ( diffidx + 1 , st . key , st . children [ 0 ] , st . db )
n = newExt ( st . key [ diffidx + 1 : ] , st . children [ 0 ] , st . db )
} else {
} else {
// Break on the last byte, no need to insert
// Break on the last byte, no need to insert
// an extension node: reuse the current node
// an extension node: reuse the current node
@ -288,15 +282,14 @@ func (st *StackTrie) insert(key, value []byte) {
// node.
// node.
st . children [ 0 ] = stackTrieFromPool ( st . db )
st . children [ 0 ] = stackTrieFromPool ( st . db )
st . children [ 0 ] . nodeType = branchNode
st . children [ 0 ] . nodeType = branchNode
st . children [ 0 ] . keyOffset = st . keyOffset + diffidx
p = st . children [ 0 ]
p = st . children [ 0 ]
}
}
// Create a leaf for the inserted part
// Create a leaf for the inserted part
o := newLeaf ( st . keyOffset + diffidx + 1 , key , value , st . db )
o := newLeaf ( key [ diffidx + 1 : ] , value , st . db )
// Insert both child leaves where they belong:
// Insert both child leaves where they belong:
origIdx := st . key [ diffidx ]
origIdx := st . key [ diffidx ]
newIdx := key [ diffidx + st . keyOffset ]
newIdx := key [ diffidx ]
p . children [ origIdx ] = n
p . children [ origIdx ] = n
p . children [ newIdx ] = o
p . children [ newIdx ] = o
st . key = st . key [ : diffidx ]
st . key = st . key [ : diffidx ]
@ -330,7 +323,6 @@ func (st *StackTrie) insert(key, value []byte) {
st . nodeType = extNode
st . nodeType = extNode
st . children [ 0 ] = NewStackTrie ( st . db )
st . children [ 0 ] = NewStackTrie ( st . db )
st . children [ 0 ] . nodeType = branchNode
st . children [ 0 ] . nodeType = branchNode
st . children [ 0 ] . keyOffset = st . keyOffset + diffidx
p = st . children [ 0 ]
p = st . children [ 0 ]
}
}
@ -339,11 +331,11 @@ func (st *StackTrie) insert(key, value []byte) {
// The child leave will be hashed directly in order to
// The child leave will be hashed directly in order to
// free up some memory.
// free up some memory.
origIdx := st . key [ diffidx ]
origIdx := st . key [ diffidx ]
p . children [ origIdx ] = newLeaf ( diffidx + 1 , st . key , st . val , st . db )
p . children [ origIdx ] = newLeaf ( st . key [ diffidx + 1 : ] , st . val , st . db )
p . children [ origIdx ] . hash ( )
p . children [ origIdx ] . hash ( )
newIdx := key [ diffidx + st . keyOffset ]
newIdx := key [ diffidx ]
p . children [ newIdx ] = newLeaf ( p . keyOffset + 1 , key , value , st . db )
p . children [ newIdx ] = newLeaf ( key [ diffidx + 1 : ] , value , st . db )
// Finally, cut off the key part that has been passed
// Finally, cut off the key part that has been passed
// over to the children.
// over to the children.
@ -351,7 +343,7 @@ func (st *StackTrie) insert(key, value []byte) {
st . val = nil
st . val = nil
case emptyNode : /* Empty */
case emptyNode : /* Empty */
st . nodeType = leafNode
st . nodeType = leafNode
st . key = key [ st . keyOffset : ]
st . key = key
st . val = value
st . val = value
case hashedNode :
case hashedNode :
panic ( "trying to insert into hash" )
panic ( "trying to insert into hash" )