mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-29 03:41:45 +00:00
core: fix restoring chain with StateRootInHeader = true
Close #3597 Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
This commit is contained in:
parent
cdbc026c27
commit
85c3b96f82
2 changed files with 76 additions and 3 deletions
|
@ -12,9 +12,11 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/internal/testchain"
|
||||
"github.com/nspcc-dev/neo-go/pkg/config"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/chaindump"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
|
@ -414,3 +416,72 @@ func TestNewBlockchain_InitHardforks(t *testing.T) {
|
|||
}, bc.GetConfig().Hardforks)
|
||||
})
|
||||
}
|
||||
|
||||
type nopCloserStorage struct {
|
||||
storage.Store
|
||||
}
|
||||
|
||||
func (nopCloserStorage) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestBlockchainRestoreStateRootInHeader(t *testing.T) {
|
||||
bc := newTestChainWithCustomCfg(t, func(c *config.Config) {
|
||||
c.ProtocolConfiguration.StateRootInHeader = true
|
||||
})
|
||||
require.NoError(t, bc.AddBlock(bc.newBlock()))
|
||||
require.NoError(t, bc.AddBlock(bc.newBlock()))
|
||||
require.NoError(t, bc.AddBlock(bc.newBlock()))
|
||||
|
||||
w := io.NewBufBinWriter()
|
||||
require.NoError(t, chaindump.Dump(bc, w.BinWriter, 0, 4))
|
||||
require.NoError(t, w.Err)
|
||||
|
||||
data := w.Bytes()
|
||||
fcfg := func(c *config.Config) { c.ProtocolConfiguration.StateRootInHeader = true }
|
||||
initChain := func(st storage.Store) *Blockchain {
|
||||
chain := initTestChain(t, st, fcfg)
|
||||
go chain.Run()
|
||||
return chain
|
||||
}
|
||||
|
||||
t.Run("empty MemoryStore", func(t *testing.T) {
|
||||
bc := initChain(storage.NewMemoryStore())
|
||||
r := io.NewBinReaderFromBuf(data)
|
||||
require.NoError(t, chaindump.Restore(bc, r, 0, 4, nil))
|
||||
bc.Close()
|
||||
})
|
||||
t.Run("not empty MemoryStore, one block", func(t *testing.T) {
|
||||
st := nopCloserStorage{Store: storage.NewMemoryStore()}
|
||||
|
||||
bc := initChain(st)
|
||||
r := io.NewBinReaderFromBuf(data)
|
||||
require.NoError(t, chaindump.Restore(bc, r, 0, 1, nil))
|
||||
expected := bc.stateRoot.CurrentLocalStateRoot()
|
||||
bc.Close()
|
||||
|
||||
bc = initChain(st)
|
||||
actual := bc.stateRoot.CurrentLocalStateRoot()
|
||||
require.Equal(t, expected, actual)
|
||||
r = io.NewBinReaderFromBuf(data)
|
||||
require.NoError(t, chaindump.Restore(bc, r, 1, 1, nil))
|
||||
bc.Close()
|
||||
})
|
||||
t.Run("not empty MemoryStore, multiple blocks", func(t *testing.T) {
|
||||
st := nopCloserStorage{Store: storage.NewMemoryStore()}
|
||||
{
|
||||
bc := initChain(st)
|
||||
r := io.NewBinReaderFromBuf(data)
|
||||
require.NoError(t, chaindump.Restore(bc, r, 0, 2, nil))
|
||||
expected := bc.stateRoot.CurrentLocalStateRoot()
|
||||
bc.Close()
|
||||
|
||||
bc = initChain(st)
|
||||
actual := bc.stateRoot.CurrentLocalStateRoot()
|
||||
require.Equal(t, expected, actual)
|
||||
r = io.NewBinReaderFromBuf(data)
|
||||
require.NoError(t, chaindump.Restore(bc, r, 2, 1, nil))
|
||||
bc.Close()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -183,13 +183,15 @@ func (s *Module) Init(height uint32) error {
|
|||
updateStateHeightMetric(h)
|
||||
}
|
||||
|
||||
if height == 0 {
|
||||
if s.mpt == nil {
|
||||
s.mpt = mpt.NewTrie(nil, s.mode, s.Store)
|
||||
s.currentLocal.Store(util.Uint256{})
|
||||
return nil
|
||||
}
|
||||
r, err := s.getStateRoot(makeStateRootKey(height))
|
||||
if err != nil {
|
||||
if height == 0 {
|
||||
s.currentLocal.Store(util.Uint256{})
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
s.currentLocal.Store(r.Root)
|
||||
|
|
Loading…
Reference in a new issue