github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/trie/proof_test.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  //</624450123203612672>
    11  
    12  
    13  package trie
    14  
    15  import (
    16  	"bytes"
    17  	crand "crypto/rand"
    18  	mrand "math/rand"
    19  	"testing"
    20  	"time"
    21  
    22  	"github.com/ethereum/go-ethereum/common"
    23  	"github.com/ethereum/go-ethereum/crypto"
    24  	"github.com/ethereum/go-ethereum/ethdb"
    25  )
    26  
    27  func init() {
    28  	mrand.Seed(time.Now().Unix())
    29  }
    30  
    31  //makeprovers根据不同的实现创建merkle trie provers
    32  //测试所有变化。
    33  func makeProvers(trie *Trie) []func(key []byte) *ethdb.MemDatabase {
    34  	var provers []func(key []byte) *ethdb.MemDatabase
    35  
    36  //创建直接基于trie的merkle prover
    37  	provers = append(provers, func(key []byte) *ethdb.MemDatabase {
    38  		proof := ethdb.NewMemDatabase()
    39  		trie.Prove(key, 0, proof)
    40  		return proof
    41  	})
    42  //创建基于叶迭代器的merkle prover
    43  	provers = append(provers, func(key []byte) *ethdb.MemDatabase {
    44  		proof := ethdb.NewMemDatabase()
    45  		if it := NewIterator(trie.NodeIterator(key)); it.Next() && bytes.Equal(key, it.Key) {
    46  			for _, p := range it.Prove() {
    47  				proof.Put(crypto.Keccak256(p), p)
    48  			}
    49  		}
    50  		return proof
    51  	})
    52  	return provers
    53  }
    54  
    55  func TestProof(t *testing.T) {
    56  	trie, vals := randomTrie(500)
    57  	root := trie.Hash()
    58  	for i, prover := range makeProvers(trie) {
    59  		for _, kv := range vals {
    60  			proof := prover(kv.k)
    61  			if proof == nil {
    62  				t.Fatalf("prover %d: missing key %x while constructing proof", i, kv.k)
    63  			}
    64  			val, _, err := VerifyProof(root, kv.k, proof)
    65  			if err != nil {
    66  				t.Fatalf("prover %d: failed to verify proof for key %x: %v\nraw proof: %x", i, kv.k, err, proof)
    67  			}
    68  			if !bytes.Equal(val, kv.v) {
    69  				t.Fatalf("prover %d: verified value mismatch for key %x: have %x, want %x", i, kv.k, val, kv.v)
    70  			}
    71  		}
    72  	}
    73  }
    74  
    75  func TestOneElementProof(t *testing.T) {
    76  	trie := new(Trie)
    77  	updateString(trie, "k", "v")
    78  	for i, prover := range makeProvers(trie) {
    79  		proof := prover([]byte("k"))
    80  		if proof == nil {
    81  			t.Fatalf("prover %d: nil proof", i)
    82  		}
    83  		if proof.Len() != 1 {
    84  			t.Errorf("prover %d: proof should have one element", i)
    85  		}
    86  		val, _, err := VerifyProof(trie.Hash(), []byte("k"), proof)
    87  		if err != nil {
    88  			t.Fatalf("prover %d: failed to verify proof: %v\nraw proof: %x", i, err, proof)
    89  		}
    90  		if !bytes.Equal(val, []byte("v")) {
    91  			t.Fatalf("prover %d: verified value mismatch: have %x, want 'k'", i, val)
    92  		}
    93  	}
    94  }
    95  
    96  func TestBadProof(t *testing.T) {
    97  	trie, vals := randomTrie(800)
    98  	root := trie.Hash()
    99  	for i, prover := range makeProvers(trie) {
   100  		for _, kv := range vals {
   101  			proof := prover(kv.k)
   102  			if proof == nil {
   103  				t.Fatalf("prover %d: nil proof", i)
   104  			}
   105  			key := proof.Keys()[mrand.Intn(proof.Len())]
   106  			val, _ := proof.Get(key)
   107  			proof.Delete(key)
   108  
   109  			mutateByte(val)
   110  			proof.Put(crypto.Keccak256(val), val)
   111  
   112  			if _, _, err := VerifyProof(root, kv.k, proof); err == nil {
   113  				t.Fatalf("prover %d: expected proof to fail for key %x", i, kv.k)
   114  			}
   115  		}
   116  	}
   117  }
   118  
   119  //还可以证明缺少密钥的测试。测试显式使用
   120  //条目检索并检查单个条目前后是否有丢失的键。
   121  func TestMissingKeyProof(t *testing.T) {
   122  	trie := new(Trie)
   123  	updateString(trie, "k", "v")
   124  
   125  	for i, key := range []string{"a", "j", "l", "z"} {
   126  		proof := ethdb.NewMemDatabase()
   127  		trie.Prove([]byte(key), 0, proof)
   128  
   129  		if proof.Len() != 1 {
   130  			t.Errorf("test %d: proof should have one element", i)
   131  		}
   132  		val, _, err := VerifyProof(trie.Hash(), []byte(key), proof)
   133  		if err != nil {
   134  			t.Fatalf("test %d: failed to verify proof: %v\nraw proof: %x", i, err, proof)
   135  		}
   136  		if val != nil {
   137  			t.Fatalf("test %d: verified value mismatch: have %x, want nil", i, val)
   138  		}
   139  	}
   140  }
   141  
   142  //突变字节改变了B中的一个字节。
   143  func mutateByte(b []byte) {
   144  	for r := mrand.Intn(len(b)); ; {
   145  		new := byte(mrand.Intn(255))
   146  		if new != b[r] {
   147  			b[r] = new
   148  			break
   149  		}
   150  	}
   151  }
   152  
   153  func BenchmarkProve(b *testing.B) {
   154  	trie, vals := randomTrie(100)
   155  	var keys []string
   156  	for k := range vals {
   157  		keys = append(keys, k)
   158  	}
   159  
   160  	b.ResetTimer()
   161  	for i := 0; i < b.N; i++ {
   162  		kv := vals[keys[i%len(keys)]]
   163  		proofs := ethdb.NewMemDatabase()
   164  		if trie.Prove(kv.k, 0, proofs); len(proofs.Keys()) == 0 {
   165  			b.Fatalf("zero length proof for %x", kv.k)
   166  		}
   167  	}
   168  }
   169  
   170  func BenchmarkVerifyProof(b *testing.B) {
   171  	trie, vals := randomTrie(100)
   172  	root := trie.Hash()
   173  	var keys []string
   174  	var proofs []*ethdb.MemDatabase
   175  	for k := range vals {
   176  		keys = append(keys, k)
   177  		proof := ethdb.NewMemDatabase()
   178  		trie.Prove([]byte(k), 0, proof)
   179  		proofs = append(proofs, proof)
   180  	}
   181  
   182  	b.ResetTimer()
   183  	for i := 0; i < b.N; i++ {
   184  		im := i % len(keys)
   185  		if _, _, err := VerifyProof(root, []byte(keys[im]), proofs[im]); err != nil {
   186  			b.Fatalf("key %x: %v", keys[im], err)
   187  		}
   188  	}
   189  }
   190  
   191  func randomTrie(n int) (*Trie, map[string]*kv) {
   192  	trie := new(Trie)
   193  	vals := make(map[string]*kv)
   194  	for i := byte(0); i < 100; i++ {
   195  		value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false}
   196  		value2 := &kv{common.LeftPadBytes([]byte{i + 10}, 32), []byte{i}, false}
   197  		trie.Update(value.k, value.v)
   198  		trie.Update(value2.k, value2.v)
   199  		vals[string(value.k)] = value
   200  		vals[string(value2.k)] = value2
   201  	}
   202  	for i := 0; i < n; i++ {
   203  		value := &kv{randBytes(32), randBytes(20), false}
   204  		trie.Update(value.k, value.v)
   205  		vals[string(value.k)] = value
   206  	}
   207  	return trie, vals
   208  }
   209  
   210  func randBytes(n int) []byte {
   211  	r := make([]byte, n)
   212  	crand.Read(r)
   213  	return r
   214  }
   215