dao: add KeepOnlyLatestState setting to dao.Version

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgeniy Stratonikov 2021-10-22 11:09:47 +03:00
parent f7e2d3d717
commit f1767f361d
5 changed files with 22 additions and 34 deletions

View file

@ -306,10 +306,11 @@ func (bc *Blockchain) init() error {
if err != nil { if err != nil {
bc.log.Info("no storage version found! creating genesis block") bc.log.Info("no storage version found! creating genesis block")
ver = dao.Version{ ver = dao.Version{
StoragePrefix: storage.STStorage, StoragePrefix: storage.STStorage,
StateRootInHeader: bc.config.StateRootInHeader, StateRootInHeader: bc.config.StateRootInHeader,
P2PSigExtensions: bc.config.P2PSigExtensions, P2PSigExtensions: bc.config.P2PSigExtensions,
Value: version, KeepOnlyLatestState: bc.config.KeepOnlyLatestState,
Value: version,
} }
if err = bc.dao.PutVersion(ver); err != nil { if err = bc.dao.PutVersion(ver); err != nil {
return err return err
@ -341,6 +342,10 @@ func (bc *Blockchain) init() error {
return fmt.Errorf("P2PSigExtensions setting mismatch (old=%t, new=%t", return fmt.Errorf("P2PSigExtensions setting mismatch (old=%t, new=%t",
ver.P2PSigExtensions, bc.config.P2PSigExtensions) 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.dao.Version = ver
bc.persistent.Version = ver bc.persistent.Version = ver

View file

@ -1823,7 +1823,7 @@ func TestBlockchain_InitWithIncompleteStateJump(t *testing.T) {
binary.LittleEndian.PutUint32(point, uint32(stateSyncPoint)) binary.LittleEndian.PutUint32(point, uint32(stateSyncPoint))
require.NoError(t, bcSpout.dao.Store.Put(storage.SYSStateSyncPoint.Bytes(), point)) require.NoError(t, bcSpout.dao.Store.Put(storage.SYSStateSyncPoint.Bytes(), point))
shouldFail := stage == 0x03 // unknown stage shouldFail := stage == 0x03 // unknown stage
checkNewBlockchainErr(t, boltCfg, bcSpout.dao.Store, shouldFail) checkNewBlockchainErr(t, spountCfg, bcSpout.dao.Store, shouldFail)
}) })
} }
} }

View file

@ -378,15 +378,17 @@ func (dao *Simple) GetBlock(hash util.Uint256) (*block.Block, error) {
// Version represents current dao version. // Version represents current dao version.
type Version struct { type Version struct {
StoragePrefix storage.KeyPrefix StoragePrefix storage.KeyPrefix
StateRootInHeader bool StateRootInHeader bool
P2PSigExtensions bool P2PSigExtensions bool
Value string KeepOnlyLatestState bool
Value string
} }
const ( const (
stateRootInHeaderBit = 1 << iota stateRootInHeaderBit = 1 << iota
p2pSigExtensionsBit p2pSigExtensionsBit
keepOnlyLatestStateBit
) )
// FromBytes decodes v from a byte-slice. // 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.StoragePrefix = storage.KeyPrefix(data[i+1])
v.StateRootInHeader = data[i+2]&stateRootInHeaderBit != 0 v.StateRootInHeader = data[i+2]&stateRootInHeaderBit != 0
v.P2PSigExtensions = data[i+2]&p2pSigExtensionsBit != 0 v.P2PSigExtensions = data[i+2]&p2pSigExtensionsBit != 0
v.KeepOnlyLatestState = data[i+2]&keepOnlyLatestStateBit != 0
return nil return nil
} }
@ -423,6 +426,9 @@ func (v *Version) Bytes() []byte {
if v.P2PSigExtensions { if v.P2PSigExtensions {
mask |= p2pSigExtensionsBit mask |= p2pSigExtensionsBit
} }
if v.KeepOnlyLatestState {
mask |= keepOnlyLatestStateBit
}
return append([]byte(v.Value), '\x00', byte(v.StoragePrefix), mask) return append([]byte(v.Value), '\x00', byte(v.StoragePrefix), mask)
} }

View file

@ -103,22 +103,10 @@ func (s *Module) Init(height uint32, enableRefCount bool) error {
s.validatedHeight.Store(binary.LittleEndian.Uint32(data)) s.validatedHeight.Store(binary.LittleEndian.Uint32(data))
} }
var gcKey = []byte{byte(storage.DataMPT), prefixGC}
if height == 0 { if height == 0 {
s.mpt = mpt.NewTrie(nil, enableRefCount, s.Store) s.mpt = mpt.NewTrie(nil, enableRefCount, s.Store)
var val byte
if enableRefCount {
val = 1
}
s.currentLocal.Store(util.Uint256{}) s.currentLocal.Store(util.Uint256{})
return s.Store.Put(gcKey, []byte{val}) return nil
}
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)
} }
r, err := s.getStateRoot(makeStateRootKey(height)) r, err := s.getStateRoot(makeStateRootKey(height))
if err != nil { if err != nil {
@ -138,25 +126,15 @@ func (s *Module) CleanStorage() error {
if s.localHeight.Load() != 0 { 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()) 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() b := s.Store.Batch()
s.Store.Seek([]byte{byte(storage.DataMPT)}, func(k, _ []byte) { s.Store.Seek([]byte{byte(storage.DataMPT)}, func(k, _ []byte) {
// #1468, but don't need to copy here, because it is done by Store. // #1468, but don't need to copy here, because it is done by Store.
b.Delete(k) b.Delete(k)
}) })
err = s.Store.PutBatch(b) err := s.Store.PutBatch(b)
if err != nil { if err != nil {
return fmt.Errorf("failed to remove outdated MPT-reated items: %w", err) 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) currentLocal := s.currentLocal.Load().(util.Uint256)
if !currentLocal.Equals(util.Uint256{}) { if !currentLocal.Equals(util.Uint256{}) {
err := s.addLocalStateRoot(s.Store, &state.MPTRoot{ err := s.addLocalStateRoot(s.Store, &state.MPTRoot{

View file

@ -17,7 +17,6 @@ var (
) )
const ( const (
prefixGC = 0x01
prefixLocal = 0x02 prefixLocal = 0x02
prefixValidated = 0x03 prefixValidated = 0x03
) )