forked from TrueCloudLab/neoneo-go
core: initialize natives cache wrt NativeActivations
If the contract was deployed then cache must be initialized after in-memory data reset. If the contract isn't active yet, then no cache will be initialized on deploy (i.e. on call to Initialize() method by native Management). Close #2984. Signed-off-by: Anna Shaleva <shaleva.ann@nspcc.ru>
This commit is contained in:
parent
33c971b0e4
commit
edb2d46d5b
2 changed files with 73 additions and 3 deletions
|
@ -1012,9 +1012,14 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage)
|
||||||
|
|
||||||
func (bc *Blockchain) initializeNativeCache(blockHeight uint32, d *dao.Simple) error {
|
func (bc *Blockchain) initializeNativeCache(blockHeight uint32, d *dao.Simple) error {
|
||||||
for _, c := range bc.contracts.Contracts {
|
for _, c := range bc.contracts.Contracts {
|
||||||
err := c.InitializeCache(blockHeight, d)
|
for _, h := range c.Metadata().UpdateHistory {
|
||||||
if err != nil {
|
if blockHeight >= h { // check that contract was deployed.
|
||||||
return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err)
|
err := c.InitializeCache(blockHeight, d)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to initialize cache for %s: %w", c.Metadata().Name, err)
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -299,6 +299,71 @@ func TestBlockchain_StartFromExistingDB(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This test enables Notary native contract at non-zero height and checks that no
|
||||||
|
// Notary cache initialization is performed before that height on node restart.
|
||||||
|
func TestBlockchain_InitializeNativeCacheWrtNativeActivations(t *testing.T) {
|
||||||
|
const notaryEnabledHeight = 3
|
||||||
|
ps, path := newLevelDBForTestingWithPath(t, "")
|
||||||
|
customConfig := func(c *config.Blockchain) {
|
||||||
|
c.P2PSigExtensions = true
|
||||||
|
c.NativeUpdateHistories = make(map[string][]uint32)
|
||||||
|
for _, n := range []string{
|
||||||
|
nativenames.Neo,
|
||||||
|
nativenames.Gas,
|
||||||
|
nativenames.Designation,
|
||||||
|
nativenames.Management,
|
||||||
|
nativenames.CryptoLib,
|
||||||
|
nativenames.Ledger,
|
||||||
|
nativenames.Management,
|
||||||
|
nativenames.Oracle,
|
||||||
|
nativenames.Policy,
|
||||||
|
nativenames.StdLib,
|
||||||
|
nativenames.Notary,
|
||||||
|
} {
|
||||||
|
if n == nativenames.Notary {
|
||||||
|
c.NativeUpdateHistories[n] = []uint32{notaryEnabledHeight}
|
||||||
|
} else {
|
||||||
|
c.NativeUpdateHistories[n] = []uint32{0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bc, validators, committee, err := chain.NewMultiWithCustomConfigAndStoreNoCheck(t, customConfig, ps)
|
||||||
|
require.NoError(t, err)
|
||||||
|
go bc.Run()
|
||||||
|
e := neotest.NewExecutor(t, bc, validators, committee)
|
||||||
|
e.AddNewBlock(t)
|
||||||
|
bc.Close() // Ensure persist is done and persistent store is properly closed.
|
||||||
|
|
||||||
|
ps, _ = newLevelDBForTestingWithPath(t, path)
|
||||||
|
|
||||||
|
// If NativeActivations are not taken into account during native cache initialization,
|
||||||
|
// bs.init() will panic on Notary cache initialization as it's not deployed yet.
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
bc, _, _, err = chain.NewMultiWithCustomConfigAndStoreNoCheck(t, customConfig, ps)
|
||||||
|
require.NoError(t, err)
|
||||||
|
})
|
||||||
|
go bc.Run()
|
||||||
|
defer bc.Close()
|
||||||
|
e = neotest.NewExecutor(t, bc, validators, committee)
|
||||||
|
h := e.Chain.BlockHeight()
|
||||||
|
|
||||||
|
// Notary isn't initialized yet, so accessing Notary cache should panic.
|
||||||
|
require.Panics(t, func() {
|
||||||
|
_ = e.Chain.GetMaxNotValidBeforeDelta()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Ensure Notary will be properly initialized and accessing Notary cache works
|
||||||
|
// as expected.
|
||||||
|
for i := 0; i < notaryEnabledHeight; i++ {
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
e.AddNewBlock(t)
|
||||||
|
}, h+uint32(i)+1)
|
||||||
|
}
|
||||||
|
require.NotPanics(t, func() {
|
||||||
|
_ = e.Chain.GetMaxNotValidBeforeDelta()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func TestBlockchain_AddHeaders(t *testing.T) {
|
func TestBlockchain_AddHeaders(t *testing.T) {
|
||||||
bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
|
bc, acc := chain.NewSingleWithCustomConfig(t, func(c *config.Blockchain) {
|
||||||
c.StateRootInHeader = true
|
c.StateRootInHeader = true
|
||||||
|
|
Loading…
Reference in a new issue