github.com/aigarnetwork/aigar@v0.0.0-20191115204914-d59a6eb70f8e/trie/proof_test.go (about)

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