mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-11-29 23:33:37 +00:00
core: provide monotonically increasing ID for contracts
ID is a contract identifier which doesn't change during migration. It is also used as a part of storage context instead of contract hash.
This commit is contained in:
parent
20616cc97f
commit
a03af55732
4 changed files with 45 additions and 1 deletions
|
@ -31,6 +31,7 @@ type DAO interface {
|
||||||
GetHeaderHashes() ([]util.Uint256, error)
|
GetHeaderHashes() ([]util.Uint256, error)
|
||||||
GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error)
|
GetNEP5Balances(acc util.Uint160) (*state.NEP5Balances, error)
|
||||||
GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error)
|
GetNEP5TransferLog(acc util.Uint160, index uint32) (*state.NEP5TransferLog, error)
|
||||||
|
GetNextContractID() (int32, error)
|
||||||
GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem
|
GetStorageItem(scripthash util.Uint160, key []byte) *state.StorageItem
|
||||||
GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error)
|
GetStorageItems(hash util.Uint160) (map[string]*state.StorageItem, error)
|
||||||
GetStorageItemsWithPrefix(hash util.Uint160, prefix []byte) (map[string]*state.StorageItem, error)
|
GetStorageItemsWithPrefix(hash util.Uint160, prefix []byte) (map[string]*state.StorageItem, error)
|
||||||
|
@ -45,6 +46,7 @@ type DAO interface {
|
||||||
PutCurrentHeader(hashAndIndex []byte) error
|
PutCurrentHeader(hashAndIndex []byte) error
|
||||||
PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error
|
PutNEP5Balances(acc util.Uint160, bs *state.NEP5Balances) error
|
||||||
PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error
|
PutNEP5TransferLog(acc util.Uint160, index uint32, lg *state.NEP5TransferLog) error
|
||||||
|
PutNextContractID(id int32) error
|
||||||
PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error
|
PutStorageItem(scripthash util.Uint160, key []byte, si *state.StorageItem) error
|
||||||
PutVersion(v string) error
|
PutVersion(v string) error
|
||||||
StoreAsBlock(block *block.Block) error
|
StoreAsBlock(block *block.Block) error
|
||||||
|
@ -169,6 +171,27 @@ func (dao *Simple) DeleteContractState(hash util.Uint160) error {
|
||||||
return dao.Store.Delete(key)
|
return dao.Store.Delete(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetNextContractID returns id for the next contract and increases stored id.
|
||||||
|
func (dao *Simple) GetNextContractID() (int32, error) {
|
||||||
|
key := storage.SYSContractID.Bytes()
|
||||||
|
data, err := dao.Store.Get(key)
|
||||||
|
if err != nil {
|
||||||
|
if err == storage.ErrKeyNotFound {
|
||||||
|
err = nil
|
||||||
|
}
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
return int32(binary.LittleEndian.Uint32(data)), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// PutNextContractID sets next contract id to id.
|
||||||
|
func (dao *Simple) PutNextContractID(id int32) error {
|
||||||
|
key := storage.SYSContractID.Bytes()
|
||||||
|
data := make([]byte, 4)
|
||||||
|
binary.LittleEndian.PutUint32(data, uint32(id))
|
||||||
|
return dao.Store.Put(key, data)
|
||||||
|
}
|
||||||
|
|
||||||
// -- end contracts.
|
// -- end contracts.
|
||||||
|
|
||||||
// -- start nep5 balances.
|
// -- start nep5 balances.
|
||||||
|
|
|
@ -82,6 +82,17 @@ func TestDeleteContractState(t *testing.T) {
|
||||||
require.Nil(t, gotContractState)
|
require.Nil(t, gotContractState)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSimple_GetNextContractID(t *testing.T) {
|
||||||
|
dao := NewSimple(storage.NewMemoryStore())
|
||||||
|
id, err := dao.GetNextContractID()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, 0, id)
|
||||||
|
require.NoError(t, dao.PutNextContractID(10))
|
||||||
|
id, err = dao.GetNextContractID()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.EqualValues(t, 10, id)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPutGetAppExecResult(t *testing.T) {
|
func TestPutGetAppExecResult(t *testing.T) {
|
||||||
dao := NewSimple(storage.NewMemoryStore())
|
dao := NewSimple(storage.NewMemoryStore())
|
||||||
hash := random.Uint256()
|
hash := random.Uint256()
|
||||||
|
|
|
@ -98,7 +98,16 @@ func contractCreate(ic *interop.Context, v *vm.VM) error {
|
||||||
contract, err := ic.DAO.GetContractState(newcontract.ScriptHash())
|
contract, err := ic.DAO.GetContractState(newcontract.ScriptHash())
|
||||||
if contract != nil {
|
if contract != nil {
|
||||||
return errors.New("contract already exists")
|
return errors.New("contract already exists")
|
||||||
} else if err := ic.DAO.PutContractState(newcontract); err != nil {
|
}
|
||||||
|
id, err := ic.DAO.GetNextContractID()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
newcontract.ID = id
|
||||||
|
if err := ic.DAO.PutNextContractID(id); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := ic.DAO.PutContractState(newcontract); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
v.Estack().PushVal(stackitem.NewInterop(newcontract))
|
v.Estack().PushVal(stackitem.NewInterop(newcontract))
|
||||||
|
|
|
@ -18,6 +18,7 @@ const (
|
||||||
IXHeaderHashList KeyPrefix = 0x80
|
IXHeaderHashList KeyPrefix = 0x80
|
||||||
SYSCurrentBlock KeyPrefix = 0xc0
|
SYSCurrentBlock KeyPrefix = 0xc0
|
||||||
SYSCurrentHeader KeyPrefix = 0xc1
|
SYSCurrentHeader KeyPrefix = 0xc1
|
||||||
|
SYSContractID KeyPrefix = 0xc2
|
||||||
SYSVersion KeyPrefix = 0xf0
|
SYSVersion KeyPrefix = 0xf0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue