github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/trie/proof.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:45</date>
    10  //</624450123149086720>
    11  
    12  
    13  package trie
    14  
    15  import (
    16  	"bytes"
    17  	"fmt"
    18  
    19  	"github.com/ethereum/go-ethereum/common"
    20  	"github.com/ethereum/go-ethereum/crypto"
    21  	"github.com/ethereum/go-ethereum/ethdb"
    22  	"github.com/ethereum/go-ethereum/log"
    23  	"github.com/ethereum/go-ethereum/rlp"
    24  )
    25  
    26  //prove为key构造了一个merkle证明。结果包含所有编码节点
    27  //在键处的值的路径上。值本身也包含在最后一个
    28  //节点,可以通过验证证据来检索。
    29  //
    30  //如果trie不包含键的值,则返回的证明包含所有
    31  //键的最长现有前缀的节点(至少是根节点),结束
    32  //证明没有键的节点。
    33  func (t *Trie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
    34  //收集键路径上的所有节点。
    35  	key = keybytesToHex(key)
    36  	nodes := []node{}
    37  	tn := t.root
    38  	for len(key) > 0 && tn != nil {
    39  		switch n := tn.(type) {
    40  		case *shortNode:
    41  			if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) {
    42  //trie不包含密钥。
    43  				tn = nil
    44  			} else {
    45  				tn = n.Val
    46  				key = key[len(n.Key):]
    47  			}
    48  			nodes = append(nodes, n)
    49  		case *fullNode:
    50  			tn = n.Children[key[0]]
    51  			key = key[1:]
    52  			nodes = append(nodes, n)
    53  		case hashNode:
    54  			var err error
    55  			tn, err = t.resolveHash(n, nil)
    56  			if err != nil {
    57  				log.Error(fmt.Sprintf("Unhandled trie error: %v", err))
    58  				return err
    59  			}
    60  		default:
    61  			panic(fmt.Sprintf("%T: invalid node: %v", tn, tn))
    62  		}
    63  	}
    64  	hasher := newHasher(0, 0, nil)
    65  	defer returnHasherToPool(hasher)
    66  
    67  	for i, n := range nodes {
    68  //别费心检查这里的错误,因为哈瑟惊慌失措
    69  //如果编码不起作用,而且我们没有写入任何数据库。
    70  		n, _, _ = hasher.hashChildren(n, nil)
    71  		hn, _ := hasher.store(n, nil, false)
    72  		if hash, ok := hn.(hashNode); ok || i == 0 {
    73  //如果节点的数据库编码是哈希(或
    74  //根节点),它成为一个证明元素。
    75  			if fromLevel > 0 {
    76  				fromLevel--
    77  			} else {
    78  				enc, _ := rlp.EncodeToBytes(n)
    79  				if !ok {
    80  					hash = crypto.Keccak256(enc)
    81  				}
    82  				proofDb.Put(hash, enc)
    83  			}
    84  		}
    85  	}
    86  	return nil
    87  }
    88  
    89  //prove为key构造了一个merkle证明。结果包含所有编码节点
    90  //在键处的值的路径上。值本身也包含在最后一个
    91  //节点,可以通过验证证据来检索。
    92  //
    93  //如果trie不包含键的值,则返回的证明包含所有
    94  //键的最长现有前缀的节点(至少是根节点),结束
    95  //证明没有键的节点。
    96  func (t *SecureTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
    97  	return t.trie.Prove(key, fromLevel, proofDb)
    98  }
    99  
   100  //验证校对检查Merkle校对。给定的证明必须包含
   101  //用给定的根散列值键入trie。VerifyProof返回一个错误,如果
   102  //证明包含无效的trie节点或错误的值。
   103  func VerifyProof(rootHash common.Hash, key []byte, proofDb DatabaseReader) (value []byte, nodes int, err error) {
   104  	key = keybytesToHex(key)
   105  	wantHash := rootHash
   106  	for i := 0; ; i++ {
   107  		buf, _ := proofDb.Get(wantHash[:])
   108  		if buf == nil {
   109  			return nil, i, fmt.Errorf("proof node %d (hash %064x) missing", i, wantHash)
   110  		}
   111  		n, err := decodeNode(wantHash[:], buf, 0)
   112  		if err != nil {
   113  			return nil, i, fmt.Errorf("bad proof node %d: %v", i, err)
   114  		}
   115  		keyrest, cld := get(n, key)
   116  		switch cld := cld.(type) {
   117  		case nil:
   118  //trie不包含密钥。
   119  			return nil, i, nil
   120  		case hashNode:
   121  			key = keyrest
   122  			copy(wantHash[:], cld)
   123  		case valueNode:
   124  			return cld, i + 1, nil
   125  		}
   126  	}
   127  }
   128  
   129  func get(tn node, key []byte) ([]byte, node) {
   130  	for {
   131  		switch n := tn.(type) {
   132  		case *shortNode:
   133  			if len(key) < len(n.Key) || !bytes.Equal(n.Key, key[:len(n.Key)]) {
   134  				return nil, nil
   135  			}
   136  			tn = n.Val
   137  			key = key[len(n.Key):]
   138  		case *fullNode:
   139  			tn = n.Children[key[0]]
   140  			key = key[1:]
   141  		case hashNode:
   142  			return key, n
   143  		case nil:
   144  			return key, nil
   145  		case valueNode:
   146  			return nil, n
   147  		default:
   148  			panic(fmt.Sprintf("%T: invalid node: %v", tn, tn))
   149  		}
   150  	}
   151  }
   152