github.com/core-coin/go-core/v2@v2.1.9/core/state/snapshot/generate_test.go (about)

     1  // Copyright 2019 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core 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-core 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-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package snapshot
    18  
    19  import (
    20  	"math/big"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/core-coin/go-core/v2/xcbdb/memorydb"
    25  
    26  	"github.com/core-coin/go-core/v2/common"
    27  	"github.com/core-coin/go-core/v2/rlp"
    28  	"github.com/core-coin/go-core/v2/trie"
    29  )
    30  
    31  // Tests that snapshot generation errors out correctly in case of a missing trie
    32  // node in the account trie.
    33  func TestGenerateCorruptAccountTrie(t *testing.T) {
    34  	// We can't use statedb to make a test trie (circular dependency), so make
    35  	// a fake one manually. We're going with a small account trie of 3 accounts,
    36  	// without any storage slots to keep the test smaller.
    37  	var (
    38  		diskdb = memorydb.New()
    39  		triedb = trie.NewDatabase(diskdb)
    40  	)
    41  	tr, _ := trie.NewSecure(common.Hash{}, triedb)
    42  	acc := &Account{Balance: big.NewInt(1), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
    43  	val, _ := rlp.EncodeToBytes(acc)
    44  	tr.Update([]byte("acc-1"), val) // 0xc7a30f39aff471c95d8a837497ad0e49b65be475cc0953540f80cfcdbdcd9074
    45  
    46  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
    47  	val, _ = rlp.EncodeToBytes(acc)
    48  	tr.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
    49  
    50  	acc = &Account{Balance: big.NewInt(3), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
    51  	val, _ = rlp.EncodeToBytes(acc)
    52  	tr.Update([]byte("acc-3"), val) // 0x19ead688e907b0fab07176120dceec244a72aff2f0aa51e8b827584e378772f4
    53  	tr.Commit(nil)                  // Root: 0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978
    54  
    55  	// Delete an account trie leaf and ensure the generator chokes
    56  	triedb.Commit(common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), false, nil)
    57  	diskdb.Delete(common.HexToHash("0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7").Bytes())
    58  
    59  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xa04693ea110a31037fb5ee814308a6f1d76bdab0b11676bdf4541d2de55ba978"), nil)
    60  	select {
    61  	case <-snap.genPending:
    62  		// Snapshot generation succeeded
    63  		t.Errorf("Snapshot generated against corrupt account trie")
    64  
    65  	case <-time.After(250 * time.Millisecond):
    66  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
    67  	}
    68  	// Signal abortion to the generator and wait for it to tear down
    69  	stop := make(chan *generatorStats)
    70  	snap.genAbort <- stop
    71  	<-stop
    72  }
    73  
    74  // Tests that snapshot generation errors out correctly in case of a missing root
    75  // trie node for a storage trie. It's similar to internal corruption but it is
    76  // handled differently inside the generator.
    77  func TestGenerateMissingStorageTrie(t *testing.T) {
    78  	// We can't use statedb to make a test trie (circular dependency), so make
    79  	// a fake one manually. We're going with a small account trie of 3 accounts,
    80  	// two of which also has the same 3-slot storage trie attached.
    81  	var (
    82  		diskdb = memorydb.New()
    83  		triedb = trie.NewDatabase(diskdb)
    84  	)
    85  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
    86  	stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
    87  	stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
    88  	stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
    89  	stTrie.Commit(nil)                              // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
    90  
    91  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
    92  	acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
    93  	val, _ := rlp.EncodeToBytes(acc)
    94  	accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
    95  
    96  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
    97  	val, _ = rlp.EncodeToBytes(acc)
    98  	accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
    99  
   100  	acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   101  	val, _ = rlp.EncodeToBytes(acc)
   102  	accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   103  	accTrie.Commit(nil)                  // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
   104  
   105  	// We can only corrupt the disk database, so flush the tries out
   106  	triedb.Reference(
   107  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   108  		common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"),
   109  	)
   110  	triedb.Reference(
   111  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   112  		common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"),
   113  	)
   114  	triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil)
   115  
   116  	// Delete a storage trie root and ensure the generator chokes
   117  	diskdb.Delete(common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67").Bytes())
   118  
   119  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), nil)
   120  	select {
   121  	case <-snap.genPending:
   122  		// Snapshot generation succeeded
   123  		t.Errorf("Snapshot generated against corrupt storage trie")
   124  
   125  	case <-time.After(250 * time.Millisecond):
   126  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   127  	}
   128  	// Signal abortion to the generator and wait for it to tear down
   129  	stop := make(chan *generatorStats)
   130  	snap.genAbort <- stop
   131  	<-stop
   132  }
   133  
   134  // Tests that snapshot generation errors out correctly in case of a missing trie
   135  // node in a storage trie.
   136  func TestGenerateCorruptStorageTrie(t *testing.T) {
   137  	// We can't use statedb to make a test trie (circular dependency), so make
   138  	// a fake one manually. We're going with a small account trie of 3 accounts,
   139  	// two of which also has the same 3-slot storage trie attached.
   140  	var (
   141  		diskdb = memorydb.New()
   142  		triedb = trie.NewDatabase(diskdb)
   143  	)
   144  	stTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   145  	stTrie.Update([]byte("key-1"), []byte("val-1")) // 0x1314700b81afc49f94db3623ef1df38f3ed18b73a1b7ea2f6c095118cf6118a0
   146  	stTrie.Update([]byte("key-2"), []byte("val-2")) // 0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371
   147  	stTrie.Update([]byte("key-3"), []byte("val-3")) // 0x51c71a47af0695957647fb68766d0becee77e953df17c29b3c2f25436f055c78
   148  	stTrie.Commit(nil)                              // Root: 0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67
   149  
   150  	accTrie, _ := trie.NewSecure(common.Hash{}, triedb)
   151  	acc := &Account{Balance: big.NewInt(1), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   152  	val, _ := rlp.EncodeToBytes(acc)
   153  	accTrie.Update([]byte("acc-1"), val) // 0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e
   154  
   155  	acc = &Account{Balance: big.NewInt(2), Root: emptyRoot.Bytes(), CodeHash: emptyCode.Bytes()}
   156  	val, _ = rlp.EncodeToBytes(acc)
   157  	accTrie.Update([]byte("acc-2"), val) // 0x65145f923027566669a1ae5ccac66f945b55ff6eaeb17d2ea8e048b7d381f2d7
   158  
   159  	acc = &Account{Balance: big.NewInt(3), Root: stTrie.Hash().Bytes(), CodeHash: emptyCode.Bytes()}
   160  	val, _ = rlp.EncodeToBytes(acc)
   161  	accTrie.Update([]byte("acc-3"), val) // 0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2
   162  	accTrie.Commit(nil)                  // Root: 0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd
   163  
   164  	// We can only corrupt the disk database, so flush the tries out
   165  	triedb.Reference(
   166  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   167  		common.HexToHash("0x9250573b9c18c664139f3b6a7a8081b7d8f8916a8fcc5d94feec6c29f5fd4e9e"),
   168  	)
   169  	triedb.Reference(
   170  		common.HexToHash("0xddefcd9376dd029653ef384bd2f0a126bb755fe84fdcc9e7cf421ba454f2bc67"),
   171  		common.HexToHash("0x50815097425d000edfc8b3a4a13e175fc2bdcfee8bdfbf2d1ff61041d3c235b2"),
   172  	)
   173  	triedb.Commit(common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), false, nil)
   174  
   175  	// Delete a storage trie leaf and ensure the generator chokes
   176  	diskdb.Delete(common.HexToHash("0x18a0f4d79cff4459642dd7604f303886ad9d77c30cf3d7d7cedb3a693ab6d371").Bytes())
   177  
   178  	snap := generateSnapshot(diskdb, triedb, 16, common.HexToHash("0xe3712f1a226f3782caca78ca770ccc19ee000552813a9f59d479f8611db9b1fd"), nil)
   179  	select {
   180  	case <-snap.genPending:
   181  		// Snapshot generation succeeded
   182  		t.Errorf("Snapshot generated against corrupt storage trie")
   183  
   184  	case <-time.After(250 * time.Millisecond):
   185  		// Not generated fast enough, hopefully blocked inside on missing trie node fail
   186  	}
   187  	// Signal abortion to the generator and wait for it to tear down
   188  	stop := make(chan *generatorStats)
   189  	snap.genAbort <- stop
   190  	<-stop
   191  }