dao: include settings in Version

Signed-off-by: Evgeniy Stratonikov <evgeniy@nspcc.ru>
This commit is contained in:
Evgeniy Stratonikov 2021-10-20 17:19:16 +03:00
parent 856385b106
commit 6c5a7d9b29
3 changed files with 63 additions and 14 deletions

View file

@ -45,7 +45,7 @@ import (
// Tuning parameters. // Tuning parameters.
const ( const (
headerBatchCount = 2000 headerBatchCount = 2000
version = "0.1.5" version = "0.2.0"
defaultInitialGAS = 52000000_00000000 defaultInitialGAS = 52000000_00000000
defaultMemPoolSize = 50000 defaultMemPoolSize = 50000
@ -311,7 +311,8 @@ func (bc *Blockchain) init() error {
ver, err := bc.dao.GetVersion() ver, err := bc.dao.GetVersion()
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")
if err = bc.dao.PutVersion(version); err != nil { v := dao.Version{Prefix: storage.STStorage, Value: version}
if err = bc.dao.PutVersion(v); err != nil {
return err return err
} }
genesisBlock, err := createGenesisBlock(bc.config) genesisBlock, err := createGenesisBlock(bc.config)
@ -328,9 +329,11 @@ func (bc *Blockchain) init() error {
} }
return bc.storeBlock(genesisBlock, nil) return bc.storeBlock(genesisBlock, nil)
} }
if ver != version { if ver.Value != version {
return fmt.Errorf("storage version mismatch betweeen %s and %s", version, ver) return fmt.Errorf("storage version mismatch betweeen %s and %s", version, ver.Value)
} }
bc.dao.StoragePrefix = ver.Prefix
bc.persistent.StoragePrefix = ver.Prefix // not strictly needed but we better be consistent here
// At this point there was no version found in the storage which // At this point there was no version found in the storage which
// implies a creating fresh storage with the version specified // implies a creating fresh storage with the version specified

View file

@ -50,7 +50,7 @@ type DAO interface {
GetStorageItems(id int32) ([]state.StorageItemWithKey, error) GetStorageItems(id int32) ([]state.StorageItemWithKey, error)
GetStorageItemsWithPrefix(id int32, prefix []byte) ([]state.StorageItemWithKey, error) GetStorageItemsWithPrefix(id int32, prefix []byte) ([]state.StorageItemWithKey, error)
GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error) GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error)
GetVersion() (string, error) GetVersion() (Version, error)
GetWrapped() DAO GetWrapped() DAO
HasTransaction(hash util.Uint256) error HasTransaction(hash util.Uint256) error
Persist() (int, error) Persist() (int, error)
@ -63,7 +63,7 @@ type DAO interface {
PutStateSyncPoint(p uint32) error PutStateSyncPoint(p uint32) error
PutStateSyncCurrentBlockHeight(h uint32) error PutStateSyncCurrentBlockHeight(h uint32) error
PutStorageItem(id int32, key []byte, si state.StorageItem) error PutStorageItem(id int32, key []byte, si state.StorageItem) error
PutVersion(v string) error PutVersion(v Version) error
Seek(id int32, prefix []byte, f func(k, v []byte)) Seek(id int32, prefix []byte, f func(k, v []byte))
SeekAsync(ctx context.Context, id int32, prefix []byte) chan storage.KeyValue SeekAsync(ctx context.Context, id int32, prefix []byte) chan storage.KeyValue
StoreAsBlock(block *block.Block, buf *io.BufBinWriter) error StoreAsBlock(block *block.Block, buf *io.BufBinWriter) error
@ -378,11 +378,46 @@ func (dao *Simple) GetBlock(hash util.Uint256) (*block.Block, error) {
return block, nil return block, nil
} }
// Version represents current dao version.
type Version struct {
Prefix storage.KeyPrefix
Value string
}
// FromBytes decodes v from a byte-slice.
func (v *Version) FromBytes(data []byte) error {
if len(data) == 0 {
return errors.New("missing version")
}
i := 0
for ; i < len(data) && data[i] != '\x00'; i++ {
}
if i == len(data) {
v.Value = string(data)
return nil
}
v.Value = string(data[:i])
v.Prefix = storage.KeyPrefix(data[i+1])
return nil
}
// Bytes encodes v to a byte-slice.
func (v *Version) Bytes() []byte {
return append([]byte(v.Value), '\x00', byte(v.Prefix))
}
// GetVersion attempts to get the current version stored in the // GetVersion attempts to get the current version stored in the
// underlying store. // underlying store.
func (dao *Simple) GetVersion() (string, error) { func (dao *Simple) GetVersion() (Version, error) {
version, err := dao.Store.Get(storage.SYSVersion.Bytes()) var version Version
return string(version), err
data, err := dao.Store.Get(storage.SYSVersion.Bytes())
if err == nil {
err = version.FromBytes(data)
}
return version, err
} }
// GetCurrentBlockHeight returns the current block height found in the // GetCurrentBlockHeight returns the current block height found in the
@ -485,8 +520,9 @@ func (dao *Simple) GetTransaction(hash util.Uint256) (*transaction.Transaction,
} }
// PutVersion stores the given version in the underlying store. // PutVersion stores the given version in the underlying store.
func (dao *Simple) PutVersion(v string) error { func (dao *Simple) PutVersion(v Version) error {
return dao.Store.Put(storage.SYSVersion.Bytes(), []byte(v)) dao.StoragePrefix = v.Prefix
return dao.Store.Put(storage.SYSVersion.Bytes(), v.Bytes())
} }
// PutCurrentHeader stores current header. // PutCurrentHeader stores current header.

View file

@ -115,16 +115,26 @@ func TestGetVersion_NoVersion(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore(), false, false) dao := NewSimple(storage.NewMemoryStore(), false, false)
version, err := dao.GetVersion() version, err := dao.GetVersion()
require.Error(t, err) require.Error(t, err)
require.Equal(t, "", version) require.Equal(t, "", version.Value)
} }
func TestGetVersion(t *testing.T) { func TestGetVersion(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore(), false, false) dao := NewSimple(storage.NewMemoryStore(), false, false)
err := dao.PutVersion("testVersion") err := dao.PutVersion(Version{Prefix: 0x42, Value: "testVersion"})
require.NoError(t, err) require.NoError(t, err)
version, err := dao.GetVersion() version, err := dao.GetVersion()
require.NoError(t, err) require.NoError(t, err)
require.NotNil(t, version) require.EqualValues(t, 0x42, version.Prefix)
require.Equal(t, "testVersion", version.Value)
t.Run("old format", func(t *testing.T) {
dao := NewSimple(storage.NewMemoryStore(), false, false)
require.NoError(t, dao.Store.Put(storage.SYSVersion.Bytes(), []byte("0.1.2")))
version, err := dao.GetVersion()
require.NoError(t, err)
require.Equal(t, "0.1.2", version.Value)
})
} }
func TestGetCurrentHeaderHeight_NoHeader(t *testing.T) { func TestGetCurrentHeaderHeight_NoHeader(t *testing.T) {