2016-04-14 18:18:24 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								// Copyright 2015 The go-ethereum Authors
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// This file is part of the go-ethereum library.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								//
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// The go-ethereum library is free software: you can redistribute it and/or modify
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// it under the terms of the GNU Lesser General Public License as published by
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// the Free Software Foundation, either version 3 of the License, or
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// (at your option) any later version.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								//
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// The go-ethereum library is distributed in the hope that it will be useful,
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// but WITHOUT ANY WARRANTY; without even the implied warranty of
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// GNU Lesser General Public License for more details.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								//
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// You should have received a copy of the GNU Lesser General Public License
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								package trie
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								import (
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									"bytes"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									"fmt"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									"github.com/ethereum/go-ethereum/common"
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									"github.com/ethereum/go-ethereum/crypto"
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									"github.com/ethereum/go-ethereum/ethdb"
							 | 
						
					
						
							
								
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									"github.com/ethereum/go-ethereum/log"
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									"github.com/ethereum/go-ethereum/rlp"
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								// Prove constructs a merkle proof for key. The result contains all encoded nodes
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// on the path to the value at key. The value itself is also included in the last
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// node and can be retrieved by verifying the proof.
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								//
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								// If the trie does not contain a value for key, the returned proof contains all
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// nodes of the longest existing prefix of the key (at least the root node), ending
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// with the node that proves the absence of the key.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									// Collect all nodes on the path to key.
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-18 13:25:07 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									key = keybytesToHex(key)
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									nodes := []node{}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									tn := t.root
							 | 
						
					
						
							
								
									
										
										
										
											2015-11-30 13:34:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									for len(key) > 0 && tn != nil {
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										switch n := tn.(type) {
							 | 
						
					
						
							
								
									
										
										
										
											2016-10-14 18:04:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										case *shortNode:
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												// The trie doesn't contain the key.
							 | 
						
					
						
							
								
									
										
										
										
											2015-11-30 13:34:19 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
												tn = nil
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											} else {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												tn = n.Val
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												key = key[len(n.Key):]
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											nodes = append(nodes, n)
							 | 
						
					
						
							
								
									
										
										
										
											2016-10-14 18:04:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										case *fullNode:
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-19 13:24:14 +03:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											tn = n.Children[key[0]]
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											key = key[1:]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											nodes = append(nodes, n)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										case hashNode:
							 | 
						
					
						
							
								
									
										
										
										
											2015-11-25 18:28:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											var err error
							 | 
						
					
						
							
								
									
										
										
										
											2017-06-20 18:26:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											tn, err = t.resolveHash(n, nil)
							 | 
						
					
						
							
								
									
										
										
										
											2015-11-25 18:28:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											if err != nil {
							 | 
						
					
						
							
								
									
										
										
										
											2017-02-22 14:10:07 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
												log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
												return err
							 | 
						
					
						
							
								
									
										
										
										
											2015-11-25 18:28:21 +01:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											}
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										default:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											panic(fmt.Sprintf("%T: invalid node: %v", tn, tn))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									}
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									hasher := newHasher(0, 0, nil)
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
									for i, n := range nodes {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// Don't bother checking for errors here since hasher panics
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										// if encoding doesn't work and we're not writing to any database.
							 | 
						
					
						
							
								
									
										
										
										
											2016-09-25 20:49:02 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										n, _, _ = hasher.hashChildren(n, nil)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										hn, _ := hasher.store(n, nil, false)
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										if hash, ok := hn.(hashNode); ok || i == 0 {
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											// If the node's database encoding is a hash (or is the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											// root node), it becomes a proof element.
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											if fromLevel > 0 {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												fromLevel--
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											} else {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												enc, _ := rlp.EncodeToBytes(n)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												if !ok {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
													hash = crypto.Keccak256(enc)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												proofDb.Put(hash, enc)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											}
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									}
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									return nil
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								// Prove constructs a merkle proof for key. The result contains all encoded nodes
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// on the path to the value at key. The value itself is also included in the last
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// node and can be retrieved by verifying the proof.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								//
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// If the trie does not contain a value for key, the returned proof contains all
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// nodes of the longest existing prefix of the key (at least the root node), ending
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// with the node that proves the absence of the key.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								func (t *SecureTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									return t.trie.Prove(key, fromLevel, proofDb)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// VerifyProof checks merkle proofs. The given proof must contain the value for
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// key in a trie with the given root hash. VerifyProof returns an error if the
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								// proof contains invalid trie nodes or the wrong value.
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
								func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (value []byte, err error, nodes int) {
							 | 
						
					
						
							
								
									
										
										
										
											2017-04-18 13:25:07 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									key = keybytesToHex(key)
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									wantHash := rootHash
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									for i := 0; ; i++ {
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										buf, _ := proofDb.Get(wantHash[:])
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										if buf == nil {
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											return nil, fmt.Errorf("proof node %d (hash %064x) missing", i, wantHash), i
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										n, err := decodeNode(wantHash[:], buf, 0)
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										if err != nil {
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											return nil, fmt.Errorf("bad proof node %d: %v", i, err), i
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										keyrest, cld := get(n, key)
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										switch cld := cld.(type) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										case nil:
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											// The trie doesn't contain the key.
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return nil, nil, i
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										case hashNode:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											key = keyrest
							 | 
						
					
						
							
								
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											copy(wantHash[:], cld)
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										case valueNode:
							 | 
						
					
						
							
								
									
										
										
										
											2017-10-24 15:19:09 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											return cld, nil, i + 1
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								func get(tn node, key []byte) ([]byte, node) {
							 | 
						
					
						
							
								
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
									for {
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										switch n := tn.(type) {
							 | 
						
					
						
							
								
									
										
										
										
											2016-10-14 18:04:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										case *shortNode:
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) {
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
												return nil, nil
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											tn = n.Val
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											key = key[len(n.Key):]
							 | 
						
					
						
							
								
									
										
										
										
											2016-10-14 18:04:33 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										case *fullNode:
							 | 
						
					
						
							
								
									
										
										
										
											2016-05-19 13:24:14 +03:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
											tn = n.Children[key[0]]
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
											key = key[1:]
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										case hashNode:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return key, n
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										case nil:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return key, nil
							 | 
						
					
						
							
								
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 
									 
								 
							 | 
							
								
									
										
									
								
							 | 
							
								
							 | 
							
							
										case valueNode:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											return nil, n
							 | 
						
					
						
							
								
									
										
										
										
											2015-09-09 03:35:41 +02:00
										 
									 
								 
							 | 
							
								
							 | 
							
								
							 | 
							
							
										default:
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
											panic(fmt.Sprintf("%T: invalid node: %v", tn, tn))
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
										}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
									}
							 | 
						
					
						
							| 
								
							 | 
							
								
							 | 
							
								
							 | 
							
							
								}
							 |