diff --git a/internal/fakechain/fakechain.go b/internal/fakechain/fakechain.go index cbf5b95cb..9d89e91d2 100644 --- a/internal/fakechain/fakechain.go +++ b/internal/fakechain/fakechain.go @@ -290,7 +290,7 @@ func (chain *FakeChain) GetStateRoot(height uint32) (*state.MPTRootState, error) } // GetStorageItem implements Blockchainer interface. -func (chain *FakeChain) GetStorageItem(id int32, key []byte) *state.StorageItem { +func (chain *FakeChain) GetStorageItem(id int32, key []byte) state.StorageItem { panic("TODO") } @@ -300,7 +300,7 @@ func (chain *FakeChain) GetTestVM(t trigger.Type, tx *transaction.Transaction, b } // GetStorageItems implements Blockchainer interface. -func (chain *FakeChain) GetStorageItems(id int32) (map[string]*state.StorageItem, error) { +func (chain *FakeChain) GetStorageItems(id int32) (map[string]state.StorageItem, error) { panic("TODO") } diff --git a/pkg/compiler/syscall_test.go b/pkg/compiler/syscall_test.go index fdb2f7228..ace3adb1b 100644 --- a/pkg/compiler/syscall_test.go +++ b/pkg/compiler/syscall_test.go @@ -98,7 +98,6 @@ func TestSyscallExecution(t *testing.T) { "storage.GetContext": {interopnames.SystemStorageGetContext, nil, false}, "storage.GetReadOnlyContext": {interopnames.SystemStorageGetReadOnlyContext, nil, false}, "storage.Put": {interopnames.SystemStoragePut, []string{sctx, b, b}, true}, - "storage.PutEx": {interopnames.SystemStoragePutEx, []string{sctx, b, b, "storage.PutConstant"}, true}, "storage.ConvertContextToReadOnly": {interopnames.SystemStorageAsReadOnly, []string{sctx}, false}, "crypto.ECDsaSecp256r1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256r1, []string{b, pub, sig}, false}, "crypto.ECDsaSecp256k1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256k1, []string{b, pub, sig}, false}, diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 1ed1d8665..988b864f4 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1124,12 +1124,12 @@ func (bc *Blockchain) GetAppExecResults(hash util.Uint256, trig trigger.Type) ([ } // GetStorageItem returns an item from storage. -func (bc *Blockchain) GetStorageItem(id int32, key []byte) *state.StorageItem { +func (bc *Blockchain) GetStorageItem(id int32, key []byte) state.StorageItem { return bc.dao.GetStorageItem(id, key) } // GetStorageItems returns all storage items for a given contract id. -func (bc *Blockchain) GetStorageItems(id int32) (map[string]*state.StorageItem, error) { +func (bc *Blockchain) GetStorageItems(id int32) (map[string]state.StorageItem, error) { return bc.dao.GetStorageItems(id) } diff --git a/pkg/core/blockchainer/blockchainer.go b/pkg/core/blockchainer/blockchainer.go index 24ed60289..be17fd192 100644 --- a/pkg/core/blockchainer/blockchainer.go +++ b/pkg/core/blockchainer/blockchainer.go @@ -56,8 +56,8 @@ type Blockchainer interface { GetStandByValidators() keys.PublicKeys GetStateProof(root util.Uint256, key []byte) ([][]byte, error) GetStateRoot(height uint32) (*state.MPTRootState, error) - GetStorageItem(id int32, key []byte) *state.StorageItem - GetStorageItems(id int32) (map[string]*state.StorageItem, error) + GetStorageItem(id int32, key []byte) state.StorageItem + 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) SetOracle(service services.Oracle) diff --git a/pkg/core/dao/cacheddao_test.go b/pkg/core/dao/cacheddao_test.go index ee8211ade..db45c7cb1 100644 --- a/pkg/core/dao/cacheddao_test.go +++ b/pkg/core/dao/cacheddao_test.go @@ -32,15 +32,15 @@ func TestCachedCachedDao(t *testing.T) { id := int32(random.Int(0, 1024)) key := []byte("qwerty") - si := &state.StorageItem{Value: []byte("poiuyt")} + si := state.StorageItem("poiuyt") require.NoError(t, ccdao.PutStorageItem(id, key, si)) resi := ccdao.GetStorageItem(id, key) assert.Equal(t, si, resi) resi = cdao.GetStorageItem(id, key) - assert.Equal(t, (*state.StorageItem)(nil), resi) + assert.Equal(t, state.StorageItem(nil), resi) resi = pdao.GetStorageItem(id, key) - assert.Equal(t, (*state.StorageItem)(nil), resi) + assert.Equal(t, state.StorageItem(nil), resi) cnt, err := ccdao.Persist() assert.NoError(t, err) @@ -48,7 +48,7 @@ func TestCachedCachedDao(t *testing.T) { resi = cdao.GetStorageItem(id, key) assert.Equal(t, si, resi) resi = pdao.GetStorageItem(id, key) - assert.Equal(t, (*state.StorageItem)(nil), resi) + assert.Equal(t, state.StorageItem(nil), resi) cnt, err = cdao.Persist() assert.NoError(t, err) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index b7ad486a5..af40a37f6 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -48,9 +48,9 @@ type DAO interface { GetNEP17TransferLog(acc util.Uint160, index uint32) (*state.NEP17TransferLog, error) GetStateRoot(height uint32) (*state.MPTRootState, error) PutStateRoot(root *state.MPTRootState) error - GetStorageItem(id int32, key []byte) *state.StorageItem - GetStorageItems(id int32) (map[string]*state.StorageItem, error) - GetStorageItemsWithPrefix(id int32, prefix []byte) (map[string]*state.StorageItem, error) + GetStorageItem(id int32, key []byte) state.StorageItem + GetStorageItems(id int32) (map[string]state.StorageItem, error) + GetStorageItemsWithPrefix(id int32, prefix []byte) (map[string]state.StorageItem, error) GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error) GetVersion() (string, error) GetWrapped() DAO @@ -61,7 +61,7 @@ type DAO interface { PutCurrentHeader(hashAndIndex []byte) error PutNEP17Balances(acc util.Uint160, bs *state.NEP17Balances) error PutNEP17TransferLog(acc util.Uint160, index uint32, lg *state.NEP17TransferLog) error - PutStorageItem(id int32, key []byte, si *state.StorageItem) error + PutStorageItem(id int32, key []byte, si state.StorageItem) error PutVersion(v string) error Seek(id int32, prefix []byte, f func(k, v []byte)) StoreAsBlock(block *block.Block, buf *io.BufBinWriter) error @@ -359,33 +359,19 @@ func (dao *Simple) PutStateRoot(r *state.MPTRootState) error { } // GetStorageItem returns StorageItem if it exists in the given store. -func (dao *Simple) GetStorageItem(id int32, key []byte) *state.StorageItem { +func (dao *Simple) GetStorageItem(id int32, key []byte) state.StorageItem { b, err := dao.Store.Get(makeStorageItemKey(id, key)) if err != nil { return nil } - r := io.NewBinReaderFromBuf(b) - - si := &state.StorageItem{} - si.DecodeBinary(r) - if r.Err != nil { - return nil - } - - return si + return b } // PutStorageItem puts given StorageItem for given id with given // key into the given store. -func (dao *Simple) PutStorageItem(id int32, key []byte, si *state.StorageItem) error { +func (dao *Simple) PutStorageItem(id int32, key []byte, si state.StorageItem) error { stKey := makeStorageItemKey(id, key) - buf := io.NewBufBinWriter() - si.EncodeBinary(buf.BinWriter) - if buf.Err != nil { - return buf.Err - } - v := buf.Bytes() - return dao.Store.Put(stKey, v) + return dao.Store.Put(stKey, si) } // DeleteStorageItem drops storage item for the given id with the @@ -396,31 +382,22 @@ func (dao *Simple) DeleteStorageItem(id int32, key []byte) error { } // GetStorageItems returns all storage items for a given id. -func (dao *Simple) GetStorageItems(id int32) (map[string]*state.StorageItem, error) { +func (dao *Simple) GetStorageItems(id int32) (map[string]state.StorageItem, error) { return dao.GetStorageItemsWithPrefix(id, nil) } // GetStorageItemsWithPrefix returns all storage items with given id for a // given scripthash. -func (dao *Simple) GetStorageItemsWithPrefix(id int32, prefix []byte) (map[string]*state.StorageItem, error) { - var siMap = make(map[string]*state.StorageItem) - var err error +func (dao *Simple) GetStorageItemsWithPrefix(id int32, prefix []byte) (map[string]state.StorageItem, error) { + var siMap = make(map[string]state.StorageItem) saveToMap := func(k, v []byte) { - if err != nil { - return - } - r := io.NewBinReaderFromBuf(v) - si := &state.StorageItem{} - si.DecodeBinary(r) - if r.Err != nil { - err = r.Err - return - } // Cut prefix and hash. // Must copy here, #1468. key := make([]byte, len(k)) copy(key, k) + si := make(state.StorageItem, len(v)) + copy(si, v) siMap[string(key)] = si } dao.Seek(id, prefix, saveToMap) diff --git a/pkg/core/dao/dao_test.go b/pkg/core/dao/dao_test.go index 97b1ddb54..f17117ccc 100644 --- a/pkg/core/dao/dao_test.go +++ b/pkg/core/dao/dao_test.go @@ -64,7 +64,7 @@ func TestPutGetStorageItem(t *testing.T) { dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) id := int32(random.Int(0, 1024)) key := []byte{0} - storageItem := &state.StorageItem{Value: []uint8{}} + storageItem := state.StorageItem{} err := dao.PutStorageItem(id, key, storageItem) require.NoError(t, err) gotStorageItem := dao.GetStorageItem(id, key) @@ -75,7 +75,7 @@ func TestDeleteStorageItem(t *testing.T) { dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) id := int32(random.Int(0, 1024)) key := []byte{0} - storageItem := &state.StorageItem{Value: []uint8{}} + storageItem := state.StorageItem{} err := dao.PutStorageItem(id, key, storageItem) require.NoError(t, err) err = dao.DeleteStorageItem(id, key) diff --git a/pkg/core/interop/interopnames/names.go b/pkg/core/interop/interopnames/names.go index c15dba958..d342284f1 100644 --- a/pkg/core/interop/interopnames/names.go +++ b/pkg/core/interop/interopnames/names.go @@ -46,7 +46,6 @@ const ( SystemStorageGetContext = "System.Storage.GetContext" SystemStorageGetReadOnlyContext = "System.Storage.GetReadOnlyContext" SystemStoragePut = "System.Storage.Put" - SystemStoragePutEx = "System.Storage.PutEx" SystemStorageAsReadOnly = "System.Storage.AsReadOnly" NeoCryptoVerifyWithECDsaSecp256r1 = "Neo.Crypto.VerifyWithECDsaSecp256r1" NeoCryptoVerifyWithECDsaSecp256k1 = "Neo.Crypto.VerifyWithECDsaSecp256k1" @@ -101,7 +100,6 @@ var names = []string{ SystemStorageGetContext, SystemStorageGetReadOnlyContext, SystemStoragePut, - SystemStoragePutEx, SystemStorageAsReadOnly, NeoCryptoVerifyWithECDsaSecp256r1, NeoCryptoVerifyWithECDsaSecp256k1, diff --git a/pkg/core/interop_neo.go b/pkg/core/interop_neo.go index 98671e6ef..39220a0ee 100644 --- a/pkg/core/interop_neo.go +++ b/pkg/core/interop_neo.go @@ -49,7 +49,7 @@ func storageFind(ic *interop.Context) error { filteredMap := stackitem.NewMap() for k, v := range siMap { - filteredMap.Add(stackitem.NewByteArray(append(prefix, []byte(k)...)), stackitem.NewByteArray(v.Value)) + filteredMap.Add(stackitem.NewByteArray(append(prefix, []byte(k)...)), stackitem.NewByteArray(v)) } sort.Slice(filteredMap.Value().([]stackitem.MapElement), func(i, j int) bool { return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte), diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index 613dae823..8d2976960 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -51,31 +51,15 @@ func TestStorageFind(t *testing.T) { skeys := [][]byte{{0x01, 0x02}, {0x02, 0x01}, {0x01, 0x01}, {0x04, 0x00}, {0x05, 0x00}, {0x06}, {0x07}, {0x08}} - items := []*state.StorageItem{ - { - Value: []byte{0x01, 0x02, 0x03, 0x04}, - }, - { - Value: []byte{0x04, 0x03, 0x02, 0x01}, - }, - { - Value: []byte{0x03, 0x04, 0x05, 0x06}, - }, - { - Value: []byte{byte(stackitem.ByteArrayT), 2, 0xCA, 0xFE}, - }, - { - Value: []byte{0xFF, 0xFF}, - }, - { - Value: rawArr, - }, - { - Value: rawArr0, - }, - { - Value: rawArr1, - }, + items := []state.StorageItem{ + []byte{0x01, 0x02, 0x03, 0x04}, + []byte{0x04, 0x03, 0x02, 0x01}, + []byte{0x03, 0x04, 0x05, 0x06}, + []byte{byte(stackitem.ByteArrayT), 2, 0xCA, 0xFE}, + []byte{0xFF, 0xFF}, + rawArr, + rawArr0, + rawArr1, } require.NoError(t, chain.contracts.Management.PutContractState(chain.dao, contractState)) @@ -121,11 +105,11 @@ func TestStorageFind(t *testing.T) { testFind(t, 0x01, istorage.FindDefault, []stackitem.Item{ stackitem.NewStruct([]stackitem.Item{ stackitem.NewByteArray(skeys[2]), - stackitem.NewByteArray(items[2].Value), + stackitem.NewByteArray(items[2]), }), stackitem.NewStruct([]stackitem.Item{ stackitem.NewByteArray(skeys[0]), - stackitem.NewByteArray(items[0].Value), + stackitem.NewByteArray(items[0]), }), }) }) @@ -144,13 +128,13 @@ func TestStorageFind(t *testing.T) { }) t.Run("values only", func(t *testing.T) { testFind(t, 0x01, istorage.FindValuesOnly, []stackitem.Item{ - stackitem.NewByteArray(items[2].Value), - stackitem.NewByteArray(items[0].Value), + stackitem.NewByteArray(items[2]), + stackitem.NewByteArray(items[0]), }) }) t.Run("deserialize values", func(t *testing.T) { testFind(t, 0x04, istorage.FindValuesOnly|istorage.FindDeserialize, []stackitem.Item{ - stackitem.NewByteArray(items[3].Value[2:]), + stackitem.NewByteArray(items[3][2:]), }) t.Run("invalid", func(t *testing.T) { v.Estack().PushVal(istorage.FindDeserialize) diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index 11f58482e..bfd04fed0 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -73,10 +73,6 @@ func storageDelete(ic *interop.Context) error { } ic.VM.AddGas(ic.Chain.GetPolicer().GetStoragePrice()) key := ic.VM.Estack().Pop().Bytes() - si := ic.DAO.GetStorageItem(stc.ID, key) - if si != nil && si.IsConst { - return errors.New("storage item is constant") - } return ic.DAO.DeleteStorageItem(stc.ID, key) } @@ -89,8 +85,8 @@ func storageGet(ic *interop.Context) error { } key := ic.VM.Estack().Pop().Bytes() si := ic.DAO.GetStorageItem(stc.ID, key) - if si != nil && si.Value != nil { - ic.VM.Estack().PushVal(si.Value) + if si != nil { + ic.VM.Estack().PushVal([]byte(si)) } else { ic.VM.Estack().PushVal(stackitem.Null{}) } @@ -122,7 +118,7 @@ func storageGetContextInternal(ic *interop.Context, isReadOnly bool) error { return nil } -func putWithContextAndFlags(ic *interop.Context, stc *StorageContext, key []byte, value []byte, isConst bool) error { +func putWithContext(ic *interop.Context, stc *StorageContext, key []byte, value []byte) error { if len(key) > MaxStorageKeyLen { return errors.New("key is too big") } @@ -133,30 +129,25 @@ func putWithContextAndFlags(ic *interop.Context, stc *StorageContext, key []byte return errors.New("StorageContext is read only") } si := ic.DAO.GetStorageItem(stc.ID, key) - if si != nil && si.IsConst { - return errors.New("storage item exists and is read-only") - } - sizeInc := 1 + sizeInc := len(value) if si == nil { - si = &state.StorageItem{} + si = state.StorageItem{} sizeInc = len(key) + len(value) } else if len(value) != 0 { - if len(value) <= len(si.Value) { + if len(value) <= len(si) { sizeInc = (len(value)-1)/4 + 1 - } else { - sizeInc = (len(si.Value)-1)/4 + 1 + len(value) - len(si.Value) + } else if len(si) != 0 { + sizeInc = (len(si)-1)/4 + 1 + len(value) - len(si) } } if !ic.VM.AddGas(int64(sizeInc) * ic.Chain.GetPolicer().GetStoragePrice()) { return errGasLimitExceeded } - si.Value = value - si.IsConst = isConst - return ic.DAO.PutStorageItem(stc.ID, key, si) + return ic.DAO.PutStorageItem(stc.ID, key, value) } -// storagePutInternal is a unified implementation of storagePut and storagePutEx. -func storagePutInternal(ic *interop.Context, getFlag bool) error { +// storagePut puts key-value pair into the storage. +func storagePut(ic *interop.Context) error { stcInterface := ic.VM.Estack().Pop().Value() stc, ok := stcInterface.(*StorageContext) if !ok { @@ -164,21 +155,7 @@ func storagePutInternal(ic *interop.Context, getFlag bool) error { } key := ic.VM.Estack().Pop().Bytes() value := ic.VM.Estack().Pop().Bytes() - var flag int - if getFlag { - flag = int(ic.VM.Estack().Pop().BigInt().Int64()) - } - return putWithContextAndFlags(ic, stc, key, value, int(Constant)&flag != 0) -} - -// storagePut puts key-value pair into the storage. -func storagePut(ic *interop.Context) error { - return storagePutInternal(ic, false) -} - -// storagePutEx puts key-value pair with given flags into the storage. -func storagePutEx(ic *interop.Context) error { - return storagePutInternal(ic, true) + return putWithContext(ic, stc, key, value) } // storageContextAsReadOnly sets given context to read-only mode. diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index ff9e936df..ff2d090f8 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -277,21 +277,6 @@ func TestStoragePut(t *testing.T) { initVM(t, []byte{1}, make([]byte, MaxStorageValueLen+1), -1) require.Error(t, storagePut(ic)) }) - t.Run("item exists and is const", func(t *testing.T) { - v := ic.SpawnVM() - v.LoadScript(cs.NEF.Script) - v.GasLimit = -1 - v.Estack().PushVal(1) - v.Estack().PushVal("value") - v.Estack().PushVal("key") - require.NoError(t, storageGetContext(ic)) - require.NoError(t, storagePutEx(ic)) - - v.Estack().PushVal("new") - v.Estack().PushVal("key") - require.NoError(t, storageGetContext(ic)) - require.Error(t, storagePut(ic)) - }) }) } @@ -301,16 +286,14 @@ func TestStorageDelete(t *testing.T) { require.NoError(t, bc.contracts.Management.PutContractState(ic.DAO, cs)) v.LoadScriptWithHash(cs.NEF.Script, cs.Hash, callflag.All) put := func(key, value string, flag int) { - v.Estack().PushVal(flag) v.Estack().PushVal(value) v.Estack().PushVal(key) require.NoError(t, storageGetContext(ic)) - require.NoError(t, storagePutEx(ic)) + require.NoError(t, storagePut(ic)) } put("key1", "value1", 0) put("key2", "value2", 0) put("key3", "value3", 0) - put("key4", "value4", 1) t.Run("good", func(t *testing.T) { v.Estack().PushVal("key1") @@ -328,11 +311,6 @@ func TestStorageDelete(t *testing.T) { require.NoError(t, storageContextAsReadOnly(ic)) require.Error(t, storageDelete(ic)) }) - t.Run("constant item", func(t *testing.T) { - v.Estack().PushVal("key4") - require.NoError(t, storageGetContext(ic)) - require.Error(t, storageDelete(ic)) - }) } // getTestContractState returns 2 contracts second of which is allowed to call the first. diff --git a/pkg/core/interops.go b/pkg/core/interops.go index 750a21ba5..9b961ccff 100644 --- a/pkg/core/interops.go +++ b/pkg/core/interops.go @@ -82,8 +82,6 @@ var systemInterops = []interop.Function{ RequiredFlags: callflag.ReadStates}, {Name: interopnames.SystemStoragePut, Func: storagePut, Price: 0, RequiredFlags: callflag.WriteStates, ParamCount: 3}, // These don't have static price in C# code. - {Name: interopnames.SystemStoragePutEx, Func: storagePutEx, Price: 0, RequiredFlags: callflag.WriteStates, - ParamCount: 4}, {Name: interopnames.SystemStorageAsReadOnly, Func: storageContextAsReadOnly, Price: 1 << 4, RequiredFlags: callflag.ReadStates, ParamCount: 1}, } diff --git a/pkg/core/interops_test.go b/pkg/core/interops_test.go index 8f793bd5c..efed8f7cd 100644 --- a/pkg/core/interops_test.go +++ b/pkg/core/interops_test.go @@ -39,7 +39,6 @@ func TestUnexpectedNonInterops(t *testing.T) { storageFind, storageGet, storagePut, - storagePutEx, } for _, f := range funcs { for k, v := range vals { diff --git a/pkg/core/native/designate.go b/pkg/core/native/designate.go index 385faaee3..c7d225861 100644 --- a/pkg/core/native/designate.go +++ b/pkg/core/native/designate.go @@ -257,7 +257,7 @@ func (s *Designate) GetDesignatedByRole(d dao.DAO, r Role, index uint32) (keys.P } var ns NodeList var bestIndex uint32 - var resSi *state.StorageItem + var resSi state.StorageItem for k, si := range kvs { if len(k) < 4 { continue @@ -269,7 +269,7 @@ func (s *Designate) GetDesignatedByRole(d dao.DAO, r Role, index uint32) (keys.P } } if resSi != nil { - reader := io.NewBinReaderFromBuf(resSi.Value) + reader := io.NewBinReaderFromBuf(resSi) ns.DecodeBinary(reader) if reader.Err != nil { return nil, 0, reader.Err @@ -324,8 +324,7 @@ func (s *Designate) DesignateAsRole(ic *interop.Context, r Role, pubs keys.Publi } sort.Sort(pubs) s.rolesChangedFlag.Store(true) - si = &state.StorageItem{Value: NodeList(pubs).Bytes()} - return ic.DAO.PutStorageItem(s.ID, key, si) + return ic.DAO.PutStorageItem(s.ID, key, NodeList(pubs).Bytes()) } func (s *Designate) getRole(item stackitem.Item) (Role, bool) { diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index eb4582df2..2e74518e8 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -480,16 +480,8 @@ func (m *Management) InitializeCache(d dao.DAO) error { var initErr error d.Seek(m.ID, []byte{prefixContract}, func(_, v []byte) { - var r = io.NewBinReaderFromBuf(v) - var si state.StorageItem - si.DecodeBinary(r) - if r.Err != nil { - initErr = r.Err - return - } - var cs state.Contract - r = io.NewBinReaderFromBuf(si.Value) + r := io.NewBinReaderFromBuf(v) cs.DecodeBinary(r) if r.Err != nil { initErr = r.Err @@ -546,10 +538,10 @@ func (m *Management) getNextContractID(d dao.DAO) (int32, error) { return 0, errors.New("nextAvailableID is not initialized") } - id := bigint.FromBytes(si.Value) + id := bigint.FromBytes(si) ret := int32(id.Int64()) id.Add(id, intOne) - si.Value = bigint.ToPreallocatedBytes(id, si.Value) + si = bigint.ToPreallocatedBytes(id, si) return ret, d.PutStorageItem(m.ID, keyNextAvailableID, si) } diff --git a/pkg/core/native/management_test.go b/pkg/core/native/management_test.go index 05a9894c1..61002accf 100644 --- a/pkg/core/native/management_test.go +++ b/pkg/core/native/management_test.go @@ -79,7 +79,7 @@ func TestManagement_Initialize(t *testing.T) { t.Run("invalid contract state", func(t *testing.T) { d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false) mgmt := newManagement() - require.NoError(t, d.PutStorageItem(mgmt.ID, []byte{prefixContract}, &state.StorageItem{Value: []byte{0xFF}})) + require.NoError(t, d.PutStorageItem(mgmt.ID, []byte{prefixContract}, state.StorageItem{0xFF})) require.Error(t, mgmt.InitializeCache(d)) }) } diff --git a/pkg/core/native/name_service.go b/pkg/core/native/name_service.go index ab724eb7c..23d263156 100644 --- a/pkg/core/native/name_service.go +++ b/pkg/core/native/name_service.go @@ -259,8 +259,7 @@ func (n *NameService) setPrice(ic *interop.Context, args []stackitem.Item) stack } n.checkCommittee(ic) - si := &state.StorageItem{Value: bigint.ToBytes(price)} - err := ic.DAO.PutStorageItem(n.ID, []byte{prefixDomainPrice}, si) + err := ic.DAO.PutStorageItem(n.ID, []byte{prefixDomainPrice}, bigint.ToBytes(price)) if err != nil { panic(err) } @@ -273,7 +272,7 @@ func (n *NameService) getPrice(ic *interop.Context, _ []stackitem.Item) stackite func (n *NameService) getPriceInternal(d dao.DAO) *big.Int { si := d.GetStorageItem(n.ID, []byte{prefixDomainPrice}) - return bigint.FromBytes(si.Value) + return bigint.FromBytes(si) } func (n *NameService) parseName(item stackitem.Item) (string, []string, []byte) { @@ -337,7 +336,7 @@ func (n *NameService) register(ic *interop.Context, args []stackitem.Item) stack n.mint(ic, token) err := ic.DAO.PutStorageItem(n.ID, makeExpirationKey(token.Expiration, token.ID()), - &state.StorageItem{Value: []byte{0}}) + state.StorageItem{0}) if err != nil { panic(err) } @@ -367,8 +366,7 @@ func (n *NameService) renew(ic *interop.Context, args []stackitem.Item) stackite } binary.BigEndian.PutUint32(key[1:], token.Expiration) - si := &state.StorageItem{Value: []byte{0}} - err = ic.DAO.PutStorageItem(n.ID, key, si) + err = ic.DAO.PutStorageItem(n.ID, key, state.StorageItem{0}) if err != nil { panic(err) } @@ -441,7 +439,7 @@ func (n *NameService) setRecord(ic *interop.Context, args []stackitem.Item) stac panic("not witnessed by admin") } key := makeRecordKey(domain, name, rt) - si := &state.StorageItem{Value: []byte(data)} + si := state.StorageItem(data) if err := ic.DAO.PutStorageItem(n.ID, key, si); err != nil { panic(err) } @@ -478,7 +476,7 @@ func (n *NameService) getRecord(ic *interop.Context, args []stackitem.Item) stac if si == nil { return stackitem.Null{} } - return stackitem.NewByteArray(si.Value) + return stackitem.NewByteArray(si) } func (n *NameService) deleteRecord(ic *interop.Context, args []stackitem.Item) stackitem.Item { @@ -535,13 +533,7 @@ func (n *NameService) getRecordsInternal(d dao.DAO, name string) map[RecordType] res := make(map[RecordType]string) d.Seek(n.ID, key, func(k, v []byte) { rt := RecordType(k[len(k)-1]) - var si state.StorageItem - r := io.NewBinReaderFromBuf(v) - si.DecodeBinary(r) - if r.Err != nil { - panic(r.Err) - } - res[rt] = string(si.Value) + res[rt] = string(v) }) return res } diff --git a/pkg/core/native/native_gas.go b/pkg/core/native/native_gas.go index 719706eb1..30e52f704 100644 --- a/pkg/core/native/native_gas.go +++ b/pkg/core/native/native_gas.go @@ -41,7 +41,7 @@ func newGAS() *GAS { } func (g *GAS) increaseBalance(_ *interop.Context, _ util.Uint160, si *state.StorageItem, amount *big.Int) error { - acc, err := state.NEP17BalanceStateFromBytes(si.Value) + acc, err := state.NEP17BalanceStateFromBytes(*si) if err != nil { return err } @@ -52,9 +52,9 @@ func (g *GAS) increaseBalance(_ *interop.Context, _ util.Uint160, si *state.Stor } acc.Balance.Add(&acc.Balance, amount) if acc.Balance.Sign() != 0 { - si.Value = acc.Bytes() + *si = acc.Bytes() } else { - si.Value = nil + *si = nil } return nil } diff --git a/pkg/core/native/native_neo.go b/pkg/core/native/native_neo.go index 24ec29dd9..17b35acdc 100644 --- a/pkg/core/native/native_neo.go +++ b/pkg/core/native/native_neo.go @@ -20,7 +20,6 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/encoding/bigint" - "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" @@ -172,7 +171,7 @@ func (n *NEO) Initialize(ic *interop.Context) error { return err } - err = ic.DAO.PutStorageItem(n.ID, prefixCommittee, &state.StorageItem{Value: cvs.Bytes()}) + err = ic.DAO.PutStorageItem(n.ID, prefixCommittee, cvs.Bytes()) if err != nil { return err } @@ -192,7 +191,7 @@ func (n *NEO) Initialize(ic *interop.Context) error { gr := &gasRecord{{Index: index, GASPerBlock: *value}} n.gasPerBlock.Store(*gr) n.gasPerBlockChanged.Store(false) - err = ic.DAO.PutStorageItem(n.ID, []byte{prefixVotersCount}, &state.StorageItem{Value: []byte{}}) + err = ic.DAO.PutStorageItem(n.ID, []byte{prefixVotersCount}, state.StorageItem{}) if err != nil { return err } @@ -206,7 +205,7 @@ func (n *NEO) Initialize(ic *interop.Context) error { func (n *NEO) InitializeCache(bc blockchainer.Blockchainer, d dao.DAO) error { var committee = keysWithVotes{} si := d.GetStorageItem(n.ID, prefixCommittee) - if err := committee.DecodeBytes(si.Value); err != nil { + if err := committee.DecodeBytes(si); err != nil { return err } if err := n.updateCache(committee, bc); err != nil { @@ -244,8 +243,7 @@ func (n *NEO) updateCommittee(ic *interop.Context) error { if !votesChanged { // We need to put in storage anyway, as it affects dumps committee := n.committee.Load().(keysWithVotes) - si := &state.StorageItem{Value: committee.Bytes()} - return ic.DAO.PutStorageItem(n.ID, prefixCommittee, si) + return ic.DAO.PutStorageItem(n.ID, prefixCommittee, committee.Bytes()) } _, cvs, err := n.computeCommitteeMembers(ic.Chain, ic.DAO) @@ -256,8 +254,7 @@ func (n *NEO) updateCommittee(ic *interop.Context) error { return err } n.votesChanged.Store(false) - si := &state.StorageItem{Value: cvs.Bytes()} - return ic.DAO.PutStorageItem(n.ID, prefixCommittee, si) + return ic.DAO.PutStorageItem(n.ID, prefixCommittee, cvs.Bytes()) } // ShouldUpdateCommittee returns true if committee is updated at block h. @@ -295,7 +292,6 @@ func (n *NEO) PostPersist(ic *interop.Context) error { voterReward.Div(voterReward, big.NewInt(100)) var cs = n.committee.Load().(keysWithVotes) - var si = new(state.StorageItem) var key = make([]byte, 38) for i := range cs { if cs[i].Votes.Sign() > 0 { @@ -312,8 +308,7 @@ func (n *NEO) PostPersist(ic *interop.Context) error { binary.BigEndian.PutUint32(key[34:], ic.Block.Index+1) - si.Value = bigint.ToBytes(tmp) - if err := ic.DAO.PutStorageItem(n.ID, key, si); err != nil { + if err := ic.DAO.PutStorageItem(n.ID, key, bigint.ToBytes(tmp)); err != nil { return err } } @@ -334,19 +329,13 @@ func (n *NEO) PostPersist(ic *interop.Context) error { func (n *NEO) getGASPerVote(d dao.DAO, key []byte, index ...uint32) []big.Int { var max = make([]uint32, len(index)) var reward = make([]big.Int, len(index)) - var si state.StorageItem d.Seek(n.ID, key, func(k, v []byte) { if len(k) == 4 { num := binary.BigEndian.Uint32(k) for i, ind := range index { if max[i] < num && num <= ind { max[i] = num - r := io.NewBinReaderFromBuf(v) - si.DecodeBinary(r) - if r.Err != nil { - return - } - reward[i] = *bigint.FromBytes(si.Value) + reward[i] = *bigint.FromBytes(v) } } } @@ -355,7 +344,7 @@ func (n *NEO) getGASPerVote(d dao.DAO, key []byte, index ...uint32) []big.Int { } func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.StorageItem, amount *big.Int) error { - acc, err := state.NEOBalanceStateFromBytes(si.Value) + acc, err := state.NEOBalanceStateFromBytes(*si) if err != nil { return err } @@ -366,7 +355,7 @@ func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.Sto return err } if amount.Sign() == 0 { - si.Value = acc.Bytes() + *si = acc.Bytes() return nil } if err := n.ModifyAccountVotes(acc, ic.DAO, amount, false); err != nil { @@ -379,9 +368,9 @@ func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.Sto } acc.Balance.Add(&acc.Balance, amount) if acc.Balance.Sign() != 0 { - si.Value = acc.Bytes() + *si = acc.Bytes() } else { - si.Value = nil + *si = nil } return nil } @@ -426,7 +415,7 @@ func (n *NEO) getSortedGASRecordFromDAO(d dao.DAO) (gasRecord, error) { for indexBytes, gasValue := range grMap { gr[i] = gasIndexPair{ Index: binary.BigEndian.Uint32([]byte(indexBytes)), - GASPerBlock: *bigint.FromBytes(gasValue.Value), + GASPerBlock: *bigint.FromBytes(gasValue), } i++ } @@ -533,7 +522,7 @@ func (n *NEO) CalculateBonus(d dao.DAO, acc util.Uint160, end uint32) (*big.Int, if si == nil { return nil, storage.ErrKeyNotFound } - st, err := state.NEOBalanceStateFromBytes(si.Value) + st, err := state.NEOBalanceStateFromBytes(si) if err != nil { return nil, err } @@ -611,15 +600,14 @@ func (n *NEO) registerCandidate(ic *interop.Context, args []stackitem.Item) stac func (n *NEO) RegisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey) error { key := makeValidatorKey(pub) si := ic.DAO.GetStorageItem(n.ID, key) + var c *candidate if si == nil { - c := &candidate{Registered: true} - si = &state.StorageItem{Value: c.Bytes()} + c = &candidate{Registered: true} } else { - c := new(candidate).FromBytes(si.Value) + c = new(candidate).FromBytes(si) c.Registered = true - si.Value = c.Bytes() } - return ic.DAO.PutStorageItem(n.ID, key, si) + return ic.DAO.PutStorageItem(n.ID, key, c.Bytes()) } func (n *NEO) unregisterCandidate(ic *interop.Context, args []stackitem.Item) stackitem.Item { @@ -642,14 +630,13 @@ func (n *NEO) UnregisterCandidateInternal(ic *interop.Context, pub *keys.PublicK return nil } n.validators.Store(keys.PublicKeys(nil)) - c := new(candidate).FromBytes(si.Value) + c := new(candidate).FromBytes(si) c.Registered = false ok, err := n.dropCandidateIfZero(ic.DAO, pub, c) if ok { return err } - si.Value = c.Bytes() - return ic.DAO.PutStorageItem(n.ID, key, si) + return ic.DAO.PutStorageItem(n.ID, key, c.Bytes()) } func (n *NEO) vote(ic *interop.Context, args []stackitem.Item) stackitem.Item { @@ -675,7 +662,7 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.Public if si == nil { return errors.New("invalid account") } - acc, err := state.NEOBalanceStateFromBytes(si.Value) + acc, err := state.NEOBalanceStateFromBytes(si) if err != nil { return err } @@ -698,8 +685,7 @@ func (n *NEO) VoteInternal(ic *interop.Context, h util.Uint160, pub *keys.Public if err := n.ModifyAccountVotes(acc, ic.DAO, &acc.Balance, true); err != nil { return err } - si.Value = acc.Bytes() - return ic.DAO.PutStorageItem(n.ID, key, si) + return ic.DAO.PutStorageItem(n.ID, key, acc.Bytes()) } // ModifyAccountVotes modifies votes of the specified account by value (can be negative). @@ -712,7 +698,7 @@ func (n *NEO) ModifyAccountVotes(acc *state.NEOBalanceState, d dao.DAO, value *b if si == nil { return errors.New("invalid validator") } - cd := new(candidate).FromBytes(si.Value) + cd := new(candidate).FromBytes(si) cd.Votes.Add(&cd.Votes, value) if !isNewVote { ok, err := n.dropCandidateIfZero(d, acc.VoteTo, cd) @@ -723,8 +709,7 @@ func (n *NEO) ModifyAccountVotes(acc *state.NEOBalanceState, d dao.DAO, value *b return errors.New("validator must be registered") } n.validators.Store(keys.PublicKeys(nil)) - si.Value = cd.Bytes() - return d.PutStorageItem(n.ID, key, si) + return d.PutStorageItem(n.ID, key, cd.Bytes()) } return nil } @@ -736,7 +721,7 @@ func (n *NEO) getCandidates(d dao.DAO, sortByKey bool) ([]keyWithVotes, error) { } arr := make([]keyWithVotes, 0, len(siMap)) for key, si := range siMap { - c := new(candidate).FromBytes(si.Value) + c := new(candidate).FromBytes(si) if c.Registered { arr = append(arr, keyWithVotes{Key: key, Votes: &c.Votes}) } @@ -817,9 +802,9 @@ func (n *NEO) modifyVoterTurnout(d dao.DAO, amount *big.Int) error { if si == nil { return errors.New("voters count not found") } - votersCount := bigint.FromBytes(si.Value) + votersCount := bigint.FromBytes(si) votersCount.Add(votersCount, amount) - si.Value = bigint.ToBytes(votersCount) + si = bigint.ToPreallocatedBytes(votersCount, si) return d.PutStorageItem(n.ID, key, si) } @@ -854,7 +839,7 @@ func (n *NEO) computeCommitteeMembers(bc blockchainer.Blockchainer, d dao.DAO) ( if si == nil { return nil, nil, errors.New("voters count not found") } - votersCount := bigint.FromBytes(si.Value) + votersCount := bigint.FromBytes(si) // votersCount / totalSupply must be >= 0.2 votersCount.Mul(votersCount, big.NewInt(effectiveVoterTurnout)) voterTurnout := votersCount.Div(votersCount, n.getTotalSupply(d)) @@ -926,9 +911,5 @@ func (n *NEO) putGASRecord(dao dao.DAO, index uint32, value *big.Int) error { key := make([]byte, 5) key[0] = prefixGASPerBlock binary.BigEndian.PutUint32(key[1:], index) - si := &state.StorageItem{ - Value: bigint.ToBytes(value), - IsConst: false, - } - return dao.PutStorageItem(n.ID, key, si) + return dao.PutStorageItem(n.ID, key, bigint.ToBytes(value)) } diff --git a/pkg/core/native/native_nep17.go b/pkg/core/native/native_nep17.go index 6cad29c4d..2dd171ac3 100644 --- a/pkg/core/native/native_nep17.go +++ b/pkg/core/native/native_nep17.go @@ -100,12 +100,11 @@ func (c *nep17TokenNative) getTotalSupply(d dao.DAO) *big.Int { if si == nil { return big.NewInt(0) } - return bigint.FromBytes(si.Value) + return bigint.FromBytes(si) } func (c *nep17TokenNative) saveTotalSupply(d dao.DAO, supply *big.Int) error { - si := &state.StorageItem{Value: bigint.ToBytes(supply)} - return d.PutStorageItem(c.ID, totalSupplyKey, si) + return d.PutStorageItem(c.ID, totalSupplyKey, bigint.ToBytes(supply)) } func (c *nep17TokenNative) Transfer(ic *interop.Context, args []stackitem.Item) stackitem.Item { @@ -168,14 +167,14 @@ func (c *nep17TokenNative) updateAccBalance(ic *interop.Context, acc util.Uint16 if amount.Sign() <= 0 { return errors.New("insufficient funds") } - si = new(state.StorageItem) + si = state.StorageItem{} } - err := c.incBalance(ic, acc, si, amount) + err := c.incBalance(ic, acc, &si, amount) if err != nil { return err } - if si.Value == nil { + if si == nil { err = ic.DAO.DeleteStorageItem(c.ID, key) } else { err = ic.DAO.PutStorageItem(c.ID, key, si) @@ -253,13 +252,13 @@ func (c *nep17TokenNative) addTokens(ic *interop.Context, h util.Uint160, amount key := makeAccountKey(h) si := ic.DAO.GetStorageItem(c.ID, key) if si == nil { - si = new(state.StorageItem) + si = state.StorageItem{} } - if err := c.incBalance(ic, h, si, amount); err != nil { + if err := c.incBalance(ic, h, &si, amount); err != nil { panic(err) } var err error - if si.Value == nil { + if si == nil { err = ic.DAO.DeleteStorageItem(c.ID, key) } else { err = ic.DAO.PutStorageItem(c.ID, key, si) diff --git a/pkg/core/native/nonfungible.go b/pkg/core/native/nonfungible.go index 4883f73c9..5d93392c6 100644 --- a/pkg/core/native/nonfungible.go +++ b/pkg/core/native/nonfungible.go @@ -141,12 +141,11 @@ func (n *nonfungible) TotalSupply(d dao.DAO) *big.Int { if si == nil { panic(errors.New("total supply is not initialized")) } - return bigint.FromBytes(si.Value) + return bigint.FromBytes(si) } func (n *nonfungible) setTotalSupply(d dao.DAO, ts *big.Int) { - si := &state.StorageItem{Value: bigint.ToBytes(ts)} - err := d.PutStorageItem(n.ID, nftTotalSupplyKey, si) + err := d.PutStorageItem(n.ID, nftTotalSupplyKey, bigint.ToBytes(ts)) if err != nil { panic(err) } @@ -222,7 +221,7 @@ func (n *nonfungible) tokens(ic *interop.Context, args []stackitem.Item) stackit } filteredMap := stackitem.NewMap() for k, v := range siMap { - filteredMap.Add(stackitem.NewByteArray(append(prefix, []byte(k)...)), stackitem.NewByteArray(v.Value)) + filteredMap.Add(stackitem.NewByteArray(append(prefix, []byte(k)...)), stackitem.NewByteArray(v)) } sort.Slice(filteredMap.Value().([]stackitem.MapElement), func(i, j int) bool { return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte), diff --git a/pkg/core/native/oracle.go b/pkg/core/native/oracle.go index cd6fce0ad..e6029cc62 100644 --- a/pkg/core/native/oracle.go +++ b/pkg/core/native/oracle.go @@ -166,8 +166,7 @@ func (o *Oracle) PostPersist(ic *interop.Context) error { if len(*idList) == 0 { err = ic.DAO.DeleteStorageItem(o.ID, idKey) } else { - si := &state.StorageItem{Value: idList.Bytes()} - err = ic.DAO.PutStorageItem(o.ID, idKey, si) + err = ic.DAO.PutStorageItem(o.ID, idKey, idList.Bytes()) } if err != nil { return err @@ -303,10 +302,10 @@ func (o *Oracle) RequestInternal(ic *interop.Context, url string, filter *string callingHash := ic.VM.GetCallingScriptHash() o.GAS.mint(ic, o.Hash, gas, false) si := ic.DAO.GetStorageItem(o.ID, prefixRequestID) - itemID := bigint.FromBytes(si.Value) + itemID := bigint.FromBytes(si) id := itemID.Uint64() itemID.Add(itemID, intOne) - si.Value = bigint.ToPreallocatedBytes(itemID, si.Value) + si = bigint.ToPreallocatedBytes(itemID, si) if err := ic.DAO.PutStorageItem(o.ID, prefixRequestID, si); err != nil { return err } @@ -357,9 +356,8 @@ func (o *Oracle) RequestInternal(ic *interop.Context, url string, filter *string // PutRequestInternal puts oracle request with the specified id to d. func (o *Oracle) PutRequestInternal(id uint64, req *state.OracleRequest, d dao.DAO) error { - reqItem := &state.StorageItem{Value: req.Bytes()} reqKey := makeRequestKey(id) - if err := d.PutStorageItem(o.ID, reqKey, reqItem); err != nil { + if err := d.PutStorageItem(o.ID, reqKey, req.Bytes()); err != nil { return err } o.newRequests[id] = req @@ -374,8 +372,7 @@ func (o *Oracle) PutRequestInternal(id uint64, req *state.OracleRequest, d dao.D return fmt.Errorf("there are too many pending requests for %s url", req.URL) } *lst = append(*lst, id) - si := &state.StorageItem{Value: lst.Bytes()} - return d.PutStorageItem(o.ID, key, si) + return d.PutStorageItem(o.ID, key, lst.Bytes()) } // GetScriptHash returns script hash or oracle nodes. @@ -429,7 +426,7 @@ func (o *Oracle) getRequests(d dao.DAO) (map[uint64]*state.OracleRequest, error) if len(k) != 8 { return nil, errors.New("invalid request ID") } - r := io.NewBinReaderFromBuf(si.Value) + r := io.NewBinReaderFromBuf(si) req := new(state.OracleRequest) req.DecodeBinary(r) if r.Err != nil { diff --git a/pkg/core/native/policy.go b/pkg/core/native/policy.go index 67b00c4bd..368d4926c 100644 --- a/pkg/core/native/policy.go +++ b/pkg/core/native/policy.go @@ -325,9 +325,7 @@ func (p *Policy) blockAccount(ic *interop.Context, args []stackitem.Item) stacki key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...) p.lock.Lock() defer p.lock.Unlock() - err := ic.DAO.PutStorageItem(p.ID, key, &state.StorageItem{ - Value: []byte{}, - }) + err := ic.DAO.PutStorageItem(p.ID, key, state.StorageItem{}) if err != nil { panic(err) } diff --git a/pkg/core/native/util.go b/pkg/core/native/util.go index 30d5e9e8a..af7ffd6e7 100644 --- a/pkg/core/native/util.go +++ b/pkg/core/native/util.go @@ -22,7 +22,7 @@ func getSerializableFromDAO(id int32, d dao.DAO, key []byte, item io.Serializabl if si == nil { return storage.ErrKeyNotFound } - r := io.NewBinReaderFromBuf(si.Value) + r := io.NewBinReaderFromBuf(si) item.DecodeBinary(r) return r.Err } @@ -33,9 +33,7 @@ func putSerializableToDAO(id int32, d dao.DAO, key []byte, item io.Serializable) if w.Err != nil { return w.Err } - return d.PutStorageItem(id, key, &state.StorageItem{ - Value: w.Bytes(), - }) + return d.PutStorageItem(id, key, w.Bytes()) } func getInt64WithKey(id int32, d dao.DAO, key []byte, defaultValue int64) int64 { @@ -43,14 +41,12 @@ func getInt64WithKey(id int32, d dao.DAO, key []byte, defaultValue int64) int64 if si == nil { return defaultValue } - return int64(binary.LittleEndian.Uint64(si.Value)) + return int64(binary.LittleEndian.Uint64(si)) } func setInt64WithKey(id int32, dao dao.DAO, key []byte, value int64) error { - si := &state.StorageItem{ - Value: make([]byte, 8), - } - binary.LittleEndian.PutUint64(si.Value, uint64(value)) + si := make(state.StorageItem, 8) + binary.LittleEndian.PutUint64(si, uint64(value)) return dao.PutStorageItem(id, key, si) } @@ -59,20 +55,17 @@ func getUint32WithKey(id int32, dao dao.DAO, key []byte, defaultValue uint32) ui if si == nil { return defaultValue } - return binary.LittleEndian.Uint32(si.Value) + return binary.LittleEndian.Uint32(si) } func setUint32WithKey(id int32, dao dao.DAO, key []byte, value uint32) error { - si := &state.StorageItem{ - Value: make([]byte, 4), - } - binary.LittleEndian.PutUint32(si.Value, value) + si := make(state.StorageItem, 4) + binary.LittleEndian.PutUint32(si, value) return dao.PutStorageItem(id, key, si) } func setIntWithKey(id int32, dao dao.DAO, key []byte, value int64) error { - si := &state.StorageItem{Value: bigint.ToBytes(big.NewInt(value))} - return dao.PutStorageItem(id, key, si) + return dao.PutStorageItem(id, key, bigint.ToBytes(big.NewInt(value))) } func getIntWithKey(id int32, dao dao.DAO, key []byte) int64 { @@ -81,7 +74,7 @@ func getIntWithKey(id int32, dao dao.DAO, key []byte) int64 { panic(fmt.Errorf("item with id = %d and key = %s is not initialized", id, hex.EncodeToString(key))) } - return bigint.FromBytes(si.Value).Int64() + return bigint.FromBytes(si).Int64() } // makeUint160Key creates a key from account script hash. diff --git a/pkg/core/native_management_test.go b/pkg/core/native_management_test.go index 294a94154..ceaf4b204 100644 --- a/pkg/core/native_management_test.go +++ b/pkg/core/native_management_test.go @@ -553,7 +553,7 @@ func TestContractDestroy(t *testing.T) { cs1.Manifest.Permissions = []manifest.Permission{*manifest.NewPermission(manifest.PermissionWildcard)} err := bc.contracts.Management.PutContractState(bc.dao, cs1) require.NoError(t, err) - err = bc.dao.PutStorageItem(cs1.ID, []byte{1, 2, 3}, &state.StorageItem{Value: []byte{3, 2, 1}}) + err = bc.dao.PutStorageItem(cs1.ID, []byte{1, 2, 3}, state.StorageItem{3, 2, 1}) require.NoError(t, err) require.NoError(t, bc.dao.UpdateMPT()) diff --git a/pkg/core/native_oracle_test.go b/pkg/core/native_oracle_test.go index d1564451d..16f792c0c 100644 --- a/pkg/core/native_oracle_test.go +++ b/pkg/core/native_oracle_test.go @@ -180,7 +180,7 @@ func TestOracle_Request(t *testing.T) { si := ic.DAO.GetStorageItem(cs.ID, []byte("lastOracleResponse")) require.NotNil(t, si) - item, err := stackitem.DeserializeItem(si.Value) + item, err := stackitem.DeserializeItem(si) require.NoError(t, err) arr, ok := item.Value().([]stackitem.Item) require.True(t, ok) diff --git a/pkg/core/state/storage_item.go b/pkg/core/state/storage_item.go index 95f1f1c6c..ba9777cf8 100644 --- a/pkg/core/state/storage_item.go +++ b/pkg/core/state/storage_item.go @@ -1,23 +1,4 @@ package state -import ( - "github.com/nspcc-dev/neo-go/pkg/io" -) - // StorageItem is the value to be stored with read-only flag. -type StorageItem struct { - Value []byte - IsConst bool -} - -// EncodeBinary implements Serializable interface. -func (si *StorageItem) EncodeBinary(w *io.BinWriter) { - w.WriteVarBytes(si.Value) - w.WriteBool(si.IsConst) -} - -// DecodeBinary implements Serializable interface. -func (si *StorageItem) DecodeBinary(r *io.BinReader) { - si.Value = r.ReadVarBytes() - si.IsConst = r.ReadBool() -} +type StorageItem []byte diff --git a/pkg/core/state/storage_item_test.go b/pkg/core/state/storage_item_test.go deleted file mode 100644 index 0da9c2a31..000000000 --- a/pkg/core/state/storage_item_test.go +++ /dev/null @@ -1,16 +0,0 @@ -package state - -import ( - "testing" - - "github.com/nspcc-dev/neo-go/internal/testserdes" -) - -func TestEncodeDecodeStorageItem(t *testing.T) { - storageItem := &StorageItem{ - Value: []byte{}, - IsConst: false, - } - - testserdes.EncodeDecodeBinary(t, storageItem, new(StorageItem)) -} diff --git a/pkg/encoding/bigint/bigint.go b/pkg/encoding/bigint/bigint.go index 9b77fae65..ed562821d 100644 --- a/pkg/encoding/bigint/bigint.go +++ b/pkg/encoding/bigint/bigint.go @@ -19,6 +19,9 @@ func FromBytes(data []byte) *big.Int { n := new(big.Int) size := len(data) if size == 0 { + if data == nil { + panic("nil slice provided to `FromBytes`") + } return big.NewInt(0) } diff --git a/pkg/interop/storage/storage.go b/pkg/interop/storage/storage.go index c9775ebfa..08392de20 100644 --- a/pkg/interop/storage/storage.go +++ b/pkg/interop/storage/storage.go @@ -38,16 +38,6 @@ const ( PickField1 FindFlags = 1 << 5 ) -// PutFlags represents flag of `PutEx` syscall. -type PutFlags byte - -const ( - // PutDefault is a storage flag for non-constant items. - PutDefault PutFlags = 0 - // PutConstant is a storage flag for constant items. - PutConstant PutFlags = 0x01 -) - // ConvertContextToReadOnly returns new context from the given one, but with // writing capability turned off, so that you could only invoke Get and Find // using this new Context. If Context is already read-only this function is a @@ -79,15 +69,6 @@ func Put(ctx Context, key interface{}, value interface{}) { neogointernal.Syscall3NoReturn("System.Storage.Put", ctx, key, value) } -// PutEx is an advanced version of Put which saves given value with given key -// and given ReadOnly flag in the storage using given Context. `flag` argument -// can either be odd for constant storage items or even for variable storage items. -// Refer to Put function description for details on how to pass the remaining -// arguments. This function uses `System.Storage.PutEx` syscall. -func PutEx(ctx Context, key interface{}, value interface{}, flag PutFlags) { - neogointernal.Syscall4NoReturn("System.Storage.PutEx", ctx, key, value, flag) -} - // Get retrieves value stored for the given key using given Context. See Put // documentation on possible key and value types. If the value is not present in // the database it returns nil. This function uses `System.Storage.Get` syscall. diff --git a/pkg/rpc/server/server.go b/pkg/rpc/server/server.go index db9878fb4..db22543d7 100644 --- a/pkg/rpc/server/server.go +++ b/pkg/rpc/server/server.go @@ -862,13 +862,7 @@ func (s *Server) verifyProof(ps request.Params) (interface{}, *response.Error) { vp := new(result.VerifyProof) val, ok := mpt.VerifyProof(root, p.Key, p.Proof) if ok { - var si state.StorageItem - r := io.NewBinReaderFromBuf(val) - si.DecodeBinary(r) - if r.Err != nil { - return nil, response.NewInternalServerError("invalid item in trie", r.Err) - } - vp.Value = si.Value + vp.Value = val } return vp, nil } @@ -927,7 +921,7 @@ func (s *Server) getStorage(ps request.Params) (interface{}, *response.Error) { return "", nil } - return item.Value, nil + return []byte(item), nil } func (s *Server) getrawtransaction(reqParams request.Params) (interface{}, *response.Error) {