github.com/igggame/nebulas-go@v2.1.0+incompatible/common/trie/iterator.go (about)

     1  // Copyright (C) 2017 go-nebulas authors
     2  //
     3  // This file is part of the go-nebulas library.
     4  //
     5  // the go-nebulas library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // the go-nebulas library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    13  // GNU General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU General Public License
    16  // along with the go-nebulas library.  If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  
    19  package trie
    20  
    21  import (
    22  	"errors"
    23  
    24  	"github.com/nebulasio/go-nebulas/crypto/hash"
    25  )
    26  
    27  // errors constants
    28  var (
    29  	ErrNotIterable = errors.New("leaf node is not iterable")
    30  )
    31  
    32  // IteratorState represents the intermediate statue in iterator
    33  type IteratorState struct {
    34  	node  *node
    35  	pos   int
    36  	route []byte
    37  }
    38  
    39  // Iterator to traverse leaf node in a trie
    40  type Iterator struct {
    41  	stack []*IteratorState
    42  	value []byte
    43  	key   []byte
    44  	root  *Trie
    45  }
    46  
    47  func validElementsInBranchNode(offset int, node *node) []int {
    48  	var valid []int
    49  	ty, _ := node.Type()
    50  	if ty != branch {
    51  		return valid
    52  	}
    53  	for i := offset; i < 16; i++ {
    54  		if node.Val[i] != nil && len(node.Val[i]) > 0 {
    55  			valid = append(valid, i)
    56  		}
    57  	}
    58  	return valid
    59  }
    60  
    61  // Iterator return an iterator
    62  func (t *Trie) Iterator(prefix []byte) (*Iterator, error) {
    63  	rootHash, curRoute, err := t.getSubTrieWithMaxCommonPrefix(prefix)
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  	node, err := t.fetchNode(rootHash)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	pos := -1
    73  	valid := validElementsInBranchNode(0, node)
    74  	if len(valid) > 0 {
    75  		pos = valid[0]
    76  	}
    77  
    78  	return &Iterator{
    79  		root:  t,
    80  		stack: []*IteratorState{&IteratorState{node, pos, curRoute}},
    81  		value: nil,
    82  		key:   nil,
    83  	}, nil
    84  }
    85  
    86  func (t *Trie) getSubTrieWithMaxCommonPrefix(prefix []byte) ([]byte, []byte, error) {
    87  	curRootHash := t.rootHash
    88  	curRoute := keyToRoute(prefix)
    89  
    90  	route := []byte{}
    91  	for len(curRoute) > 0 {
    92  		rootNode, err := t.fetchNode(curRootHash)
    93  		if err != nil {
    94  			return nil, nil, err
    95  		}
    96  		flag, err := rootNode.Type()
    97  		if err != nil {
    98  			return nil, nil, err
    99  		}
   100  		switch flag {
   101  		case branch:
   102  			curRootHash = rootNode.Val[curRoute[0]]
   103  			route = append(route, []byte{curRoute[0]}...)
   104  			curRoute = curRoute[1:]
   105  		case ext:
   106  			path := rootNode.Val[1]
   107  			next := rootNode.Val[2]
   108  			matchLen := prefixLen(path, curRoute)
   109  			if matchLen != len(path) && matchLen != len(curRoute) {
   110  				return nil, nil, ErrNotFound
   111  			}
   112  			route = append(route, path...)
   113  			curRootHash = next
   114  			curRoute = curRoute[matchLen:]
   115  		case leaf:
   116  			path := rootNode.Val[1]
   117  			matchLen := prefixLen(path, curRoute)
   118  			if matchLen != len(path) && matchLen != len(curRoute) {
   119  				return nil, nil, ErrNotFound
   120  			}
   121  			curRootHash = rootNode.Hash
   122  			curRoute = curRoute[matchLen:]
   123  			if len(curRoute) > 0 {
   124  				return nil, nil, ErrNotFound
   125  			}
   126  		default:
   127  			return nil, nil, errors.New("unknown node type")
   128  		}
   129  	}
   130  	return curRootHash, route, nil
   131  }
   132  
   133  func (it *Iterator) push(node *node, pos int, route []byte) {
   134  	it.stack = append(it.stack, &IteratorState{node, pos, route})
   135  }
   136  
   137  func (it *Iterator) pop() (*IteratorState, error) {
   138  	size := len(it.stack)
   139  	if size == 0 {
   140  		return nil, errors.New("empty stack")
   141  	}
   142  	state := it.stack[size-1]
   143  	it.stack = it.stack[0 : size-1]
   144  	return state, nil
   145  }
   146  
   147  // Next return if there is next leaf node
   148  func (it *Iterator) Next() (bool, error) {
   149  	state, err := it.pop()
   150  	if err != nil {
   151  		return false, nil
   152  	}
   153  	node := state.node
   154  	pos := state.pos
   155  	route := state.route
   156  	ty, err := node.Type()
   157  	for {
   158  		switch ty {
   159  		case branch:
   160  			valid := validElementsInBranchNode(pos, node)
   161  			if len(valid) == 0 {
   162  				return false, errors.New("empty branch node")
   163  			}
   164  			if len(valid) > 1 {
   165  				//curRoute := append(route, []byte{byte(valid[1])}...)
   166  				it.push(node, valid[1], route)
   167  			}
   168  			route = append(route, []byte{byte(valid[0])}...)
   169  			node, err = it.root.fetchNode(node.Val[valid[0]])
   170  			if err != nil {
   171  				return false, err
   172  			}
   173  			ty, err = node.Type()
   174  		case ext:
   175  			route = append(route, node.Val[1]...)
   176  			node, err = it.root.fetchNode(node.Val[2])
   177  			if err != nil {
   178  				return false, err
   179  			}
   180  			ty, err = node.Type()
   181  		case leaf:
   182  			it.value = node.Val[2]
   183  			it.key = append(route, node.Val[1]...)
   184  			return true, nil
   185  		default:
   186  			return false, err
   187  		}
   188  		pos = 0
   189  	}
   190  }
   191  
   192  // Key return current leaf node's key
   193  func (it *Iterator) Key() []byte {
   194  	return routeToKey(it.key)
   195  }
   196  
   197  // Value return current leaf node's value
   198  func (it *Iterator) Value() []byte {
   199  	return it.value
   200  }
   201  
   202  // HashDomains for each variable in contract
   203  // each domain will represented as 6 bytes, support 4 level domain at most
   204  // such as,
   205  // 4a56b7 000000 000000 000000,
   206  // 4a56b8 1c9812 000000 000000,
   207  // 4a56b8 3a1289 000000 000000,
   208  // support iterator with same prefix
   209  func HashDomains(domains ...string) []byte {
   210  	if len(domains) > 24/6 {
   211  		panic("only support 4 level domain at most")
   212  	}
   213  	key := [24]byte{0}
   214  	for k, v := range domains {
   215  		domain := hash.Sha3256([]byte(v))[0:6]
   216  		for i := 0; i < len(domain); i++ {
   217  			key[k*6+i] = domain[i]
   218  		}
   219  	}
   220  	return key[:]
   221  }
   222  
   223  // HashDomainsPrefix is same as HashDomains, but without tail zeros
   224  func HashDomainsPrefix(domains ...string) []byte {
   225  	if len(domains) > 24/6 {
   226  		panic("only support 4 level domain at most")
   227  	}
   228  	key := []byte{}
   229  	for _, v := range domains {
   230  		domain := hash.Sha3256([]byte(v))[0:6]
   231  		key = append(key, domain...)
   232  	}
   233  	return key[:]
   234  }