github.com/intfoundation/intchain@v0.0.0-20220727031208-4316ad31ca73/trie/proof_test.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package trie
    18  
    19  import (
    20  	"bytes"
    21  	crand "crypto/rand"
    22  	mrand "math/rand"
    23  	"testing"
    24  	"time"
    25  
    26  	"github.com/intfoundation/intchain/common"
    27  	"github.com/intfoundation/intchain/crypto"
    28  	"github.com/intfoundation/intchain/intdb/memorydb"
    29  )
    30  
    31  func init() {
    32  	mrand.Seed(time.Now().Unix())
    33  }
    34  
    35  // makeProvers creates Merkle trie provers based on different implementations to
    36  // test all variations.
    37  func makeProvers(trie *Trie) []func(key []byte) *memorydb.Database {
    38  	var provers []func(key []byte) *memorydb.Database
    39  
    40  	// Create a direct trie based Merkle prover
    41  	provers = append(provers, func(key []byte) *memorydb.Database {
    42  		proof := memorydb.New()
    43  		trie.Prove(key, 0, proof)
    44  		return proof
    45  	})
    46  	// Create a leaf iterator based Merkle prover
    47  	provers = append(provers, func(key []byte) *memorydb.Database {
    48  		proof := memorydb.New()
    49  		if it := NewIterator(trie.NodeIterator(key)); it.Next() && bytes.Equal(key, it.Key) {
    50  			for _, p := range it.Prove() {
    51  				proof.Put(crypto.Keccak256(p), p)
    52  			}
    53  		}
    54  		return proof
    55  	})
    56  	return provers
    57  }
    58  
    59  func TestProof(t *testing.T) {
    60  	trie, vals := randomTrie(500)
    61  	root := trie.Hash()
    62  	for i, prover := range makeProvers(trie) {
    63  		for _, kv := range vals {
    64  			proof := prover(kv.k)
    65  			if proof == nil {
    66  				t.Fatalf("prover %d: missing key %x while constructing proof", i, kv.k)
    67  			}
    68  			val, _, err := VerifyProof(root, kv.k, proof)
    69  			if err != nil {
    70  				t.Fatalf("prover %d: failed to verify proof for key %x: %v\nraw proof: %x", i, kv.k, err, proof)
    71  			}
    72  			if !bytes.Equal(val, kv.v) {
    73  				t.Fatalf("prover %d: verified value mismatch for key %x: have %x, want %x", i, kv.k, val, kv.v)
    74  			}
    75  		}
    76  	}
    77  }
    78  
    79  func TestOneElementProof(t *testing.T) {
    80  	trie := new(Trie)
    81  	updateString(trie, "k", "v")
    82  	for i, prover := range makeProvers(trie) {
    83  		proof := prover([]byte("k"))
    84  		if proof == nil {
    85  			t.Fatalf("prover %d: nil proof", i)
    86  		}
    87  		if proof.Len() != 1 {
    88  			t.Errorf("prover %d: proof should have one element", i)
    89  		}
    90  		val, _, err := VerifyProof(trie.Hash(), []byte("k"), proof)
    91  		if err != nil {
    92  			t.Fatalf("prover %d: failed to verify proof: %v\nraw proof: %x", i, err, proof)
    93  		}
    94  		if !bytes.Equal(val, []byte("v")) {
    95  			t.Fatalf("prover %d: verified value mismatch: have %x, want 'k'", i, val)
    96  		}
    97  	}
    98  }
    99  
   100  func TestBadProof(t *testing.T) {
   101  	trie, vals := randomTrie(800)
   102  	root := trie.Hash()
   103  	for i, prover := range makeProvers(trie) {
   104  		for _, kv := range vals {
   105  			proof := prover(kv.k)
   106  			if proof == nil {
   107  				t.Fatalf("prover %d: nil proof", i)
   108  			}
   109  			it := proof.NewIterator()
   110  			for i, d := 0, mrand.Intn(proof.Len()); i <= d; i++ {
   111  				it.Next()
   112  			}
   113  			key := it.Key()
   114  			val, _ := proof.Get(key)
   115  			proof.Delete(key)
   116  			it.Release()
   117  
   118  			mutateByte(val)
   119  			proof.Put(crypto.Keccak256(val), val)
   120  
   121  			if _, _, err := VerifyProof(root, kv.k, proof); err == nil {
   122  				t.Fatalf("prover %d: expected proof to fail for key %x", i, kv.k)
   123  			}
   124  		}
   125  	}
   126  }
   127  
   128  // Tests that missing keys can also be proven. The test explicitly uses a single
   129  // entry trie and checks for missing keys both before and after the single entry.
   130  func TestMissingKeyProof(t *testing.T) {
   131  	trie := new(Trie)
   132  	updateString(trie, "k", "v")
   133  
   134  	for i, key := range []string{"a", "j", "l", "z"} {
   135  		proof := memorydb.New()
   136  		trie.Prove([]byte(key), 0, proof)
   137  
   138  		if proof.Len() != 1 {
   139  			t.Errorf("test %d: proof should have one element", i)
   140  		}
   141  		val, _, err := VerifyProof(trie.Hash(), []byte(key), proof)
   142  		if err != nil {
   143  			t.Fatalf("test %d: failed to verify proof: %v\nraw proof: %x", i, err, proof)
   144  		}
   145  		if val != nil {
   146  			t.Fatalf("test %d: verified value mismatch: have %x, want nil", i, val)
   147  		}
   148  	}
   149  }
   150  
   151  // mutateByte changes one byte in b.
   152  func mutateByte(b []byte) {
   153  	for r := mrand.Intn(len(b)); ; {
   154  		new := byte(mrand.Intn(255))
   155  		if new != b[r] {
   156  			b[r] = new
   157  			break
   158  		}
   159  	}
   160  }
   161  
   162  func BenchmarkProve(b *testing.B) {
   163  	trie, vals := randomTrie(100)
   164  	var keys []string
   165  	for k := range vals {
   166  		keys = append(keys, k)
   167  	}
   168  
   169  	b.ResetTimer()
   170  	for i := 0; i < b.N; i++ {
   171  		kv := vals[keys[i%len(keys)]]
   172  		proofs := memorydb.New()
   173  		if trie.Prove(kv.k, 0, proofs); proofs.Len() == 0 {
   174  			b.Fatalf("zero length proof for %x", kv.k)
   175  		}
   176  	}
   177  }
   178  
   179  func BenchmarkVerifyProof(b *testing.B) {
   180  	trie, vals := randomTrie(100)
   181  	root := trie.Hash()
   182  	var keys []string
   183  	var proofs []*memorydb.Database
   184  	for k := range vals {
   185  		keys = append(keys, k)
   186  		proof := memorydb.New()
   187  		trie.Prove([]byte(k), 0, proof)
   188  		proofs = append(proofs, proof)
   189  	}
   190  
   191  	b.ResetTimer()
   192  	for i := 0; i < b.N; i++ {
   193  		im := i % len(keys)
   194  		if _, _, err := VerifyProof(root, []byte(keys[im]), proofs[im]); err != nil {
   195  			b.Fatalf("key %x: %v", keys[im], err)
   196  		}
   197  	}
   198  }
   199  
   200  func randomTrie(n int) (*Trie, map[string]*kv) {
   201  	trie := new(Trie)
   202  	vals := make(map[string]*kv)
   203  	for i := byte(0); i < 100; i++ {
   204  		value := &kv{common.LeftPadBytes([]byte{i}, 32), []byte{i}, false}
   205  		value2 := &kv{common.LeftPadBytes([]byte{i + 10}, 32), []byte{i}, false}
   206  		trie.Update(value.k, value.v)
   207  		trie.Update(value2.k, value2.v)
   208  		vals[string(value.k)] = value
   209  		vals[string(value2.k)] = value2
   210  	}
   211  	for i := 0; i < n; i++ {
   212  		value := &kv{randBytes(32), randBytes(20), false}
   213  		trie.Update(value.k, value.v)
   214  		vals[string(value.k)] = value
   215  	}
   216  	return trie, vals
   217  }
   218  
   219  func randBytes(n int) []byte {
   220  	r := make([]byte, n)
   221  	crand.Read(r)
   222  	return r
   223  }