core: convert (*Blockchain).JumpToState to a callback

We don't need this method to be exposed, the only its user is the
StateSync module. At the same time StateSync module manages its state by
itself which guarantees that (*Blockchain).jumpToState will be called
with proper StateSync stage.
This commit is contained in:
Anna Shaleva 2021-08-25 16:24:20 +03:00
parent 6381173293
commit 0e0b55350a
5 changed files with 9 additions and 31 deletions

View file

@ -307,11 +307,6 @@ func (chain *FakeChain) GetStateSyncModule() blockchainer.StateSync {
return &FakeStateSync{}
}
// JumpToState implements Blockchainer interface.
func (chain *FakeChain) JumpToState(module blockchainer.StateSync) error {
panic("TODO")
}
// GetStorageItem implements Blockchainer interface.
func (chain *FakeChain) GetStorageItem(id int32, key []byte) state.StorageItem {
panic("TODO")
@ -504,11 +499,6 @@ func (s *FakeStateSync) Traverse(root util.Uint256, process func(node mpt.Node,
panic("TODO")
}
// GetJumpHeight implements StateSync interface.
func (s *FakeStateSync) GetJumpHeight() (uint32, error) {
panic("TODO")
}
// GetUnknownMPTNodesBatch implements StateSync interface.
func (s *FakeStateSync) GetUnknownMPTNodesBatch(limit int) []util.Uint256 {
panic("TODO")

View file

@ -411,17 +411,13 @@ func (bc *Blockchain) init() error {
return bc.updateExtensibleWhitelist(bHeight)
}
// JumpToState is an atomic operation that changes Blockchain state to the one
// jumpToState is an atomic operation that changes Blockchain state to the one
// specified by the state sync point p. All the data needed for the jump must be
// collected by the state sync module.
func (bc *Blockchain) JumpToState(module blockchainer.StateSync) error {
func (bc *Blockchain) jumpToState(p uint32) error {
bc.lock.Lock()
defer bc.lock.Unlock()
p, err := module.GetJumpHeight()
if err != nil {
return fmt.Errorf("failed to get jump height: %w", err)
}
if p+1 >= uint32(len(bc.headerHashes)) {
return fmt.Errorf("invalid state sync point")
}
@ -792,7 +788,7 @@ func (bc *Blockchain) GetStateModule() blockchainer.StateRoot {
// GetStateSyncModule returns new state sync service instance.
func (bc *Blockchain) GetStateSyncModule() blockchainer.StateSync {
return statesync.NewModule(bc, bc.log, bc.dao)
return statesync.NewModule(bc, bc.log, bc.dao, bc.jumpToState)
}
// storeBlock performs chain update using the block given, it executes all

View file

@ -60,7 +60,6 @@ type Blockchainer interface {
GetStorageItems(id int32) (map[string]state.StorageItem, error)
GetTestVM(t trigger.Type, tx *transaction.Transaction, b *block.Block) *vm.VM
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
JumpToState(module StateSync) error
SetOracle(service services.Oracle)
mempool.Feer // fee interface
ManagementContractHash() util.Uint160

View file

@ -12,7 +12,6 @@ type StateSync interface {
Init(currChainHeight uint32) error
IsActive() bool
IsInitialized() bool
GetJumpHeight() (uint32, error)
GetUnknownMPTNodesBatch(limit int) []util.Uint256
NeedHeaders() bool
NeedMPTNodes() bool

View file

@ -79,10 +79,12 @@ type Module struct {
mptpool *Pool
billet *mpt.Billet
jumpCallback func(p uint32) error
}
// NewModule returns new instance of statesync module.
func NewModule(bc blockchainer.Blockchainer, log *zap.Logger, s *dao.Simple) *Module {
func NewModule(bc blockchainer.Blockchainer, log *zap.Logger, s *dao.Simple, jumpCallback func(p uint32) error) *Module {
if !(bc.GetConfig().P2PStateExchangeExtensions && bc.GetConfig().RemoveUntraceableBlocks) {
return &Module{
dao: s,
@ -97,6 +99,7 @@ func NewModule(bc blockchainer.Blockchainer, log *zap.Logger, s *dao.Simple) *Mo
syncInterval: uint32(bc.GetConfig().StateSyncInterval),
mptpool: NewPool(),
syncStage: none,
jumpCallback: jumpCallback,
}
}
@ -141,7 +144,7 @@ func (s *Module) Init(currChainHeight uint32) error {
// We've reached this point, so chain has genesis block only. As far as we can't ruin
// current chain's state until new state is completely fetched, outdated state-related data
// will be removed from storage during (*Blockchain).JumpToState(...) execution.
// will be removed from storage during (*Blockchain).jumpToState(...) execution.
// All we need to do right now is to remove genesis-related MPT nodes.
err = s.bc.GetStateModule().CleanStorage()
if err != nil {
@ -401,7 +404,7 @@ func (s *Module) checkSyncIsCompleted() {
}
s.log.Info("state is in sync",
zap.Uint32("state sync point", s.syncPoint))
err := s.bc.JumpToState(s)
err := s.jumpCallback(s.syncPoint)
if err != nil {
s.log.Fatal("failed to jump to the latest state sync point", zap.Error(err))
}
@ -465,15 +468,6 @@ func (s *Module) Traverse(root util.Uint256, process func(node mpt.Node, nodeByt
return b.Traverse(process, false)
}
// GetJumpHeight returns state sync point to jump to. It is not protected by mutex and should be called
// under the module lock.
func (s *Module) GetJumpHeight() (uint32, error) {
if s.syncStage != headersSynced|mptSynced|blocksSynced {
return 0, errors.New("state sync module has wong state to perform state jump")
}
return s.syncPoint, nil
}
// GetUnknownMPTNodesBatch returns set of currently unknown MPT nodes (`limit` at max).
func (s *Module) GetUnknownMPTNodesBatch(limit int) []util.Uint256 {
s.lock.RLock()