diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 1e819d35b..2b4f6d556 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -306,10 +306,11 @@ func (bc *Blockchain) init() error { if err != nil { bc.log.Info("no storage version found! creating genesis block") ver = dao.Version{ - StoragePrefix: storage.STStorage, - StateRootInHeader: bc.config.StateRootInHeader, - P2PSigExtensions: bc.config.P2PSigExtensions, - Value: version, + StoragePrefix: storage.STStorage, + StateRootInHeader: bc.config.StateRootInHeader, + P2PSigExtensions: bc.config.P2PSigExtensions, + KeepOnlyLatestState: bc.config.KeepOnlyLatestState, + Value: version, } if err = bc.dao.PutVersion(ver); err != nil { return err @@ -341,6 +342,10 @@ func (bc *Blockchain) init() error { return fmt.Errorf("P2PSigExtensions setting mismatch (old=%t, new=%t", ver.P2PSigExtensions, bc.config.P2PSigExtensions) } + if ver.KeepOnlyLatestState != bc.config.KeepOnlyLatestState { + return fmt.Errorf("KeepOnlyLatestState setting mismatch: old=%v, new=%v", + ver.KeepOnlyLatestState, bc.config.KeepOnlyLatestState) + } bc.dao.Version = ver bc.persistent.Version = ver diff --git a/pkg/core/blockchain_test.go b/pkg/core/blockchain_test.go index 5c2eff93b..a1c20be2a 100644 --- a/pkg/core/blockchain_test.go +++ b/pkg/core/blockchain_test.go @@ -1823,7 +1823,7 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) { binary.LittleEndian.PutUint32(point, uint32(stateSyncPoint)) require.NoError(t, bcSpout.dao.Store.Put(storage.SYSStateSyncPoint.Bytes(), point)) shouldFail := stage == 0x03 // unknown stage - checkNewBlockchainErr(t, boltCfg, bcSpout.dao.Store, shouldFail) + checkNewBlockchainErr(t, spountCfg, bcSpout.dao.Store, shouldFail) }) } } diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index a82519fb5..5387e4752 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -378,15 +378,17 @@ func (dao *Simple) GetBlock(hash util.Uint256) (*block.Block, error) { // Version represents current dao version. type Version struct { - StoragePrefix storage.KeyPrefix - StateRootInHeader bool - P2PSigExtensions bool - Value string + StoragePrefix storage.KeyPrefix + StateRootInHeader bool + P2PSigExtensions bool + KeepOnlyLatestState bool + Value string } const ( stateRootInHeaderBit = 1 << iota p2pSigExtensionsBit + keepOnlyLatestStateBit ) // FromBytes decodes v from a byte-slice. @@ -411,6 +413,7 @@ func (v *Version) FromBytes(data []byte) error { v.StoragePrefix = storage.KeyPrefix(data[i+1]) v.StateRootInHeader = data[i+2]&stateRootInHeaderBit != 0 v.P2PSigExtensions = data[i+2]&p2pSigExtensionsBit != 0 + v.KeepOnlyLatestState = data[i+2]&keepOnlyLatestStateBit != 0 return nil } @@ -423,6 +426,9 @@ func (v *Version) Bytes() []byte { if v.P2PSigExtensions { mask |= p2pSigExtensionsBit } + if v.KeepOnlyLatestState { + mask |= keepOnlyLatestStateBit + } return append([]byte(v.Value), '\x00', byte(v.StoragePrefix), mask) } diff --git a/pkg/core/stateroot/module.go b/pkg/core/stateroot/module.go index e5e7a5439..322e23c8e 100644 --- a/pkg/core/stateroot/module.go +++ b/pkg/core/stateroot/module.go @@ -103,22 +103,10 @@ func (s *Module) Init(height uint32, enableRefCount bool) error { s.validatedHeight.Store(binary.LittleEndian.Uint32(data)) } - var gcKey = []byte{byte(storage.DataMPT), prefixGC} if height == 0 { s.mpt = mpt.NewTrie(nil, enableRefCount, s.Store) - var val byte - if enableRefCount { - val = 1 - } s.currentLocal.Store(util.Uint256{}) - return s.Store.Put(gcKey, []byte{val}) - } - var hasRefCount bool - if v, err := s.Store.Get(gcKey); err == nil { - hasRefCount = v[0] != 0 - } - if hasRefCount != enableRefCount { - return fmt.Errorf("KeepOnlyLatestState setting mismatch: old=%v, new=%v", hasRefCount, enableRefCount) + return nil } r, err := s.getStateRoot(makeStateRootKey(height)) if err != nil { @@ -138,25 +126,15 @@ func (s *Module) CleanStorage() error { if s.localHeight.Load() != 0 { return fmt.Errorf("can't clean MPT data for non-genesis block: expected local stateroot height 0, got %d", s.localHeight.Load()) } - gcKey := []byte{byte(storage.DataMPT), prefixGC} - gcVal, err := s.Store.Get(gcKey) - if err != nil { - return fmt.Errorf("failed to get GC flag: %w", err) - } - // b := s.Store.Batch() s.Store.Seek([]byte{byte(storage.DataMPT)}, func(k, _ []byte) { // #1468, but don't need to copy here, because it is done by Store. b.Delete(k) }) - err = s.Store.PutBatch(b) + err := s.Store.PutBatch(b) if err != nil { return fmt.Errorf("failed to remove outdated MPT-reated items: %w", err) } - err = s.Store.Put(gcKey, gcVal) - if err != nil { - return fmt.Errorf("failed to store GC flag: %w", err) - } currentLocal := s.currentLocal.Load().(util.Uint256) if !currentLocal.Equals(util.Uint256{}) { err := s.addLocalStateRoot(s.Store, &state.MPTRoot{ diff --git a/pkg/core/stateroot/store.go b/pkg/core/stateroot/store.go index 9efcf7c5f..ee5a52f78 100644 --- a/pkg/core/stateroot/store.go +++ b/pkg/core/stateroot/store.go @@ -17,7 +17,6 @@ var ( ) const ( - prefixGC = 0x01 prefixLocal = 0x02 prefixValidated = 0x03 )