github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/core/chaindump/dump_test.go (about) 1 package chaindump_test 2 3 import ( 4 "errors" 5 "testing" 6 7 "github.com/nspcc-dev/neo-go/internal/basicchain" 8 "github.com/nspcc-dev/neo-go/pkg/config" 9 "github.com/nspcc-dev/neo-go/pkg/core/block" 10 "github.com/nspcc-dev/neo-go/pkg/core/chaindump" 11 "github.com/nspcc-dev/neo-go/pkg/io" 12 "github.com/nspcc-dev/neo-go/pkg/neotest" 13 "github.com/nspcc-dev/neo-go/pkg/neotest/chain" 14 "github.com/stretchr/testify/require" 15 ) 16 17 func TestBlockchain_DumpAndRestore(t *testing.T) { 18 t.Run("no state root", func(t *testing.T) { 19 testDumpAndRestore(t, func(c *config.Blockchain) { 20 c.StateRootInHeader = false 21 c.P2PSigExtensions = true 22 }, nil) 23 }) 24 t.Run("with state root", func(t *testing.T) { 25 testDumpAndRestore(t, func(c *config.Blockchain) { 26 c.StateRootInHeader = true 27 c.P2PSigExtensions = true 28 }, nil) 29 }) 30 t.Run("remove untraceable", func(t *testing.T) { 31 // Dump can only be created if all blocks and transactions are present. 32 testDumpAndRestore(t, func(c *config.Blockchain) { 33 c.P2PSigExtensions = true 34 }, func(c *config.Blockchain) { 35 c.MaxTraceableBlocks = 2 36 c.Ledger.RemoveUntraceableBlocks = true 37 c.P2PSigExtensions = true 38 }) 39 }) 40 } 41 42 func testDumpAndRestore(t *testing.T, dumpF, restoreF func(c *config.Blockchain)) { 43 if restoreF == nil { 44 restoreF = dumpF 45 } 46 47 bc, validators, committee := chain.NewMultiWithCustomConfig(t, dumpF) 48 e := neotest.NewExecutor(t, bc, validators, committee) 49 50 basicchain.Init(t, "../../../", e) 51 require.True(t, bc.BlockHeight() > 5) // ensure that test is valid 52 53 w := io.NewBufBinWriter() 54 require.NoError(t, chaindump.Dump(bc, w.BinWriter, 0, bc.BlockHeight()+1)) 55 require.NoError(t, w.Err) 56 57 buf := w.Bytes() 58 t.Run("invalid start", func(t *testing.T) { 59 bc2, _, _ := chain.NewMultiWithCustomConfig(t, restoreF) 60 61 r := io.NewBinReaderFromBuf(buf) 62 require.Error(t, chaindump.Restore(bc2, r, 2, 1, nil)) 63 }) 64 t.Run("good", func(t *testing.T) { 65 bc2, _, _ := chain.NewMultiWithCustomConfig(t, dumpF) 66 67 r := io.NewBinReaderFromBuf(buf) 68 require.NoError(t, chaindump.Restore(bc2, r, 0, 2, nil)) 69 require.Equal(t, uint32(1), bc2.BlockHeight()) 70 71 r = io.NewBinReaderFromBuf(buf) // new reader because start is relative to dump 72 require.NoError(t, chaindump.Restore(bc2, r, 2, 1, nil)) 73 t.Run("check handler", func(t *testing.T) { 74 lastIndex := uint32(0) 75 errStopped := errors.New("stopped") 76 f := func(b *block.Block) error { 77 lastIndex = b.Index 78 if b.Index >= bc.BlockHeight()-1 { 79 return errStopped 80 } 81 return nil 82 } 83 require.NoError(t, chaindump.Restore(bc2, r, 0, 1, f)) 84 require.Equal(t, bc2.BlockHeight(), lastIndex) 85 86 r = io.NewBinReaderFromBuf(buf) 87 err := chaindump.Restore(bc2, r, 4, bc.BlockHeight()-bc2.BlockHeight(), f) 88 require.ErrorIs(t, err, errStopped) 89 require.Equal(t, bc.BlockHeight()-1, lastIndex) 90 }) 91 }) 92 }