Merge pull request #1819 from nspcc-dev/fix/constant
core/state: remove `IsConst` from `StorageItem`
This commit is contained in:
commit
f087775160
32 changed files with 134 additions and 331 deletions
|
@ -290,7 +290,7 @@ func (chain *FakeChain) GetStateRoot(height uint32) (*state.MPTRootState, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageItem implements Blockchainer interface.
|
// 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")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +300,7 @@ func (chain *FakeChain) GetTestVM(t trigger.Type, tx *transaction.Transaction, b
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageItems implements Blockchainer interface.
|
// 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")
|
panic("TODO")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,6 @@ func TestSyscallExecution(t *testing.T) {
|
||||||
"storage.GetContext": {interopnames.SystemStorageGetContext, nil, false},
|
"storage.GetContext": {interopnames.SystemStorageGetContext, nil, false},
|
||||||
"storage.GetReadOnlyContext": {interopnames.SystemStorageGetReadOnlyContext, nil, false},
|
"storage.GetReadOnlyContext": {interopnames.SystemStorageGetReadOnlyContext, nil, false},
|
||||||
"storage.Put": {interopnames.SystemStoragePut, []string{sctx, b, b}, true},
|
"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},
|
"storage.ConvertContextToReadOnly": {interopnames.SystemStorageAsReadOnly, []string{sctx}, false},
|
||||||
"crypto.ECDsaSecp256r1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256r1, []string{b, pub, sig}, false},
|
"crypto.ECDsaSecp256r1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256r1, []string{b, pub, sig}, false},
|
||||||
"crypto.ECDsaSecp256k1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256k1, []string{b, pub, sig}, false},
|
"crypto.ECDsaSecp256k1Verify": {interopnames.NeoCryptoVerifyWithECDsaSecp256k1, []string{b, pub, sig}, false},
|
||||||
|
|
|
@ -1124,12 +1124,12 @@ func (bc *Blockchain) GetAppExecResults(hash util.Uint256, trig trigger.Type) ([
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageItem returns an item from storage.
|
// 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)
|
return bc.dao.GetStorageItem(id, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageItems returns all storage items for a given contract id.
|
// 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)
|
return bc.dao.GetStorageItems(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -56,8 +56,8 @@ type Blockchainer interface {
|
||||||
GetStandByValidators() keys.PublicKeys
|
GetStandByValidators() keys.PublicKeys
|
||||||
GetStateProof(root util.Uint256, key []byte) ([][]byte, error)
|
GetStateProof(root util.Uint256, key []byte) ([][]byte, error)
|
||||||
GetStateRoot(height uint32) (*state.MPTRootState, error)
|
GetStateRoot(height uint32) (*state.MPTRootState, error)
|
||||||
GetStorageItem(id int32, key []byte) *state.StorageItem
|
GetStorageItem(id int32, key []byte) state.StorageItem
|
||||||
GetStorageItems(id int32) (map[string]*state.StorageItem, error)
|
GetStorageItems(id int32) (map[string]state.StorageItem, error)
|
||||||
GetTestVM(t trigger.Type, tx *transaction.Transaction, b *block.Block) *vm.VM
|
GetTestVM(t trigger.Type, tx *transaction.Transaction, b *block.Block) *vm.VM
|
||||||
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
GetTransaction(util.Uint256) (*transaction.Transaction, uint32, error)
|
||||||
SetOracle(service services.Oracle)
|
SetOracle(service services.Oracle)
|
||||||
|
|
|
@ -32,15 +32,15 @@ func TestCachedCachedDao(t *testing.T) {
|
||||||
|
|
||||||
id := int32(random.Int(0, 1024))
|
id := int32(random.Int(0, 1024))
|
||||||
key := []byte("qwerty")
|
key := []byte("qwerty")
|
||||||
si := &state.StorageItem{Value: []byte("poiuyt")}
|
si := state.StorageItem("poiuyt")
|
||||||
require.NoError(t, ccdao.PutStorageItem(id, key, si))
|
require.NoError(t, ccdao.PutStorageItem(id, key, si))
|
||||||
resi := ccdao.GetStorageItem(id, key)
|
resi := ccdao.GetStorageItem(id, key)
|
||||||
assert.Equal(t, si, resi)
|
assert.Equal(t, si, resi)
|
||||||
|
|
||||||
resi = cdao.GetStorageItem(id, key)
|
resi = cdao.GetStorageItem(id, key)
|
||||||
assert.Equal(t, (*state.StorageItem)(nil), resi)
|
assert.Equal(t, state.StorageItem(nil), resi)
|
||||||
resi = pdao.GetStorageItem(id, key)
|
resi = pdao.GetStorageItem(id, key)
|
||||||
assert.Equal(t, (*state.StorageItem)(nil), resi)
|
assert.Equal(t, state.StorageItem(nil), resi)
|
||||||
|
|
||||||
cnt, err := ccdao.Persist()
|
cnt, err := ccdao.Persist()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
@ -48,7 +48,7 @@ func TestCachedCachedDao(t *testing.T) {
|
||||||
resi = cdao.GetStorageItem(id, key)
|
resi = cdao.GetStorageItem(id, key)
|
||||||
assert.Equal(t, si, resi)
|
assert.Equal(t, si, resi)
|
||||||
resi = pdao.GetStorageItem(id, key)
|
resi = pdao.GetStorageItem(id, key)
|
||||||
assert.Equal(t, (*state.StorageItem)(nil), resi)
|
assert.Equal(t, state.StorageItem(nil), resi)
|
||||||
|
|
||||||
cnt, err = cdao.Persist()
|
cnt, err = cdao.Persist()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
@ -48,9 +48,9 @@ type DAO interface {
|
||||||
GetNEP17TransferLog(acc util.Uint160, index uint32) (*state.NEP17TransferLog, error)
|
GetNEP17TransferLog(acc util.Uint160, index uint32) (*state.NEP17TransferLog, error)
|
||||||
GetStateRoot(height uint32) (*state.MPTRootState, error)
|
GetStateRoot(height uint32) (*state.MPTRootState, error)
|
||||||
PutStateRoot(root *state.MPTRootState) error
|
PutStateRoot(root *state.MPTRootState) error
|
||||||
GetStorageItem(id int32, key []byte) *state.StorageItem
|
GetStorageItem(id int32, key []byte) state.StorageItem
|
||||||
GetStorageItems(id int32) (map[string]*state.StorageItem, error)
|
GetStorageItems(id int32) (map[string]state.StorageItem, error)
|
||||||
GetStorageItemsWithPrefix(id int32, prefix []byte) (map[string]*state.StorageItem, error)
|
GetStorageItemsWithPrefix(id int32, prefix []byte) (map[string]state.StorageItem, error)
|
||||||
GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error)
|
GetTransaction(hash util.Uint256) (*transaction.Transaction, uint32, error)
|
||||||
GetVersion() (string, error)
|
GetVersion() (string, error)
|
||||||
GetWrapped() DAO
|
GetWrapped() DAO
|
||||||
|
@ -61,7 +61,7 @@ type DAO interface {
|
||||||
PutCurrentHeader(hashAndIndex []byte) error
|
PutCurrentHeader(hashAndIndex []byte) error
|
||||||
PutNEP17Balances(acc util.Uint160, bs *state.NEP17Balances) error
|
PutNEP17Balances(acc util.Uint160, bs *state.NEP17Balances) error
|
||||||
PutNEP17TransferLog(acc util.Uint160, index uint32, lg *state.NEP17TransferLog) 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
|
PutVersion(v string) error
|
||||||
Seek(id int32, prefix []byte, f func(k, v []byte))
|
Seek(id int32, prefix []byte, f func(k, v []byte))
|
||||||
StoreAsBlock(block *block.Block, buf *io.BufBinWriter) error
|
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.
|
// 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))
|
b, err := dao.Store.Get(makeStorageItemKey(id, key))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
r := io.NewBinReaderFromBuf(b)
|
return b
|
||||||
|
|
||||||
si := &state.StorageItem{}
|
|
||||||
si.DecodeBinary(r)
|
|
||||||
if r.Err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return si
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutStorageItem puts given StorageItem for given id with given
|
// PutStorageItem puts given StorageItem for given id with given
|
||||||
// key into the given store.
|
// 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)
|
stKey := makeStorageItemKey(id, key)
|
||||||
buf := io.NewBufBinWriter()
|
return dao.Store.Put(stKey, si)
|
||||||
si.EncodeBinary(buf.BinWriter)
|
|
||||||
if buf.Err != nil {
|
|
||||||
return buf.Err
|
|
||||||
}
|
|
||||||
v := buf.Bytes()
|
|
||||||
return dao.Store.Put(stKey, v)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteStorageItem drops storage item for the given id with the
|
// 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.
|
// 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)
|
return dao.GetStorageItemsWithPrefix(id, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetStorageItemsWithPrefix returns all storage items with given id for a
|
// GetStorageItemsWithPrefix returns all storage items with given id for a
|
||||||
// given scripthash.
|
// given scripthash.
|
||||||
func (dao *Simple) GetStorageItemsWithPrefix(id int32, prefix []byte) (map[string]*state.StorageItem, error) {
|
func (dao *Simple) GetStorageItemsWithPrefix(id int32, prefix []byte) (map[string]state.StorageItem, error) {
|
||||||
var siMap = make(map[string]*state.StorageItem)
|
var siMap = make(map[string]state.StorageItem)
|
||||||
var err error
|
|
||||||
|
|
||||||
saveToMap := func(k, v []byte) {
|
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.
|
// Cut prefix and hash.
|
||||||
// Must copy here, #1468.
|
// Must copy here, #1468.
|
||||||
key := make([]byte, len(k))
|
key := make([]byte, len(k))
|
||||||
copy(key, k)
|
copy(key, k)
|
||||||
|
si := make(state.StorageItem, len(v))
|
||||||
|
copy(si, v)
|
||||||
siMap[string(key)] = si
|
siMap[string(key)] = si
|
||||||
}
|
}
|
||||||
dao.Seek(id, prefix, saveToMap)
|
dao.Seek(id, prefix, saveToMap)
|
||||||
|
|
|
@ -64,7 +64,7 @@ func TestPutGetStorageItem(t *testing.T) {
|
||||||
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
|
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
|
||||||
id := int32(random.Int(0, 1024))
|
id := int32(random.Int(0, 1024))
|
||||||
key := []byte{0}
|
key := []byte{0}
|
||||||
storageItem := &state.StorageItem{Value: []uint8{}}
|
storageItem := state.StorageItem{}
|
||||||
err := dao.PutStorageItem(id, key, storageItem)
|
err := dao.PutStorageItem(id, key, storageItem)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
gotStorageItem := dao.GetStorageItem(id, key)
|
gotStorageItem := dao.GetStorageItem(id, key)
|
||||||
|
@ -75,7 +75,7 @@ func TestDeleteStorageItem(t *testing.T) {
|
||||||
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
|
dao := NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
|
||||||
id := int32(random.Int(0, 1024))
|
id := int32(random.Int(0, 1024))
|
||||||
key := []byte{0}
|
key := []byte{0}
|
||||||
storageItem := &state.StorageItem{Value: []uint8{}}
|
storageItem := state.StorageItem{}
|
||||||
err := dao.PutStorageItem(id, key, storageItem)
|
err := dao.PutStorageItem(id, key, storageItem)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
err = dao.DeleteStorageItem(id, key)
|
err = dao.DeleteStorageItem(id, key)
|
||||||
|
|
|
@ -46,7 +46,6 @@ const (
|
||||||
SystemStorageGetContext = "System.Storage.GetContext"
|
SystemStorageGetContext = "System.Storage.GetContext"
|
||||||
SystemStorageGetReadOnlyContext = "System.Storage.GetReadOnlyContext"
|
SystemStorageGetReadOnlyContext = "System.Storage.GetReadOnlyContext"
|
||||||
SystemStoragePut = "System.Storage.Put"
|
SystemStoragePut = "System.Storage.Put"
|
||||||
SystemStoragePutEx = "System.Storage.PutEx"
|
|
||||||
SystemStorageAsReadOnly = "System.Storage.AsReadOnly"
|
SystemStorageAsReadOnly = "System.Storage.AsReadOnly"
|
||||||
NeoCryptoVerifyWithECDsaSecp256r1 = "Neo.Crypto.VerifyWithECDsaSecp256r1"
|
NeoCryptoVerifyWithECDsaSecp256r1 = "Neo.Crypto.VerifyWithECDsaSecp256r1"
|
||||||
NeoCryptoVerifyWithECDsaSecp256k1 = "Neo.Crypto.VerifyWithECDsaSecp256k1"
|
NeoCryptoVerifyWithECDsaSecp256k1 = "Neo.Crypto.VerifyWithECDsaSecp256k1"
|
||||||
|
@ -101,7 +100,6 @@ var names = []string{
|
||||||
SystemStorageGetContext,
|
SystemStorageGetContext,
|
||||||
SystemStorageGetReadOnlyContext,
|
SystemStorageGetReadOnlyContext,
|
||||||
SystemStoragePut,
|
SystemStoragePut,
|
||||||
SystemStoragePutEx,
|
|
||||||
SystemStorageAsReadOnly,
|
SystemStorageAsReadOnly,
|
||||||
NeoCryptoVerifyWithECDsaSecp256r1,
|
NeoCryptoVerifyWithECDsaSecp256r1,
|
||||||
NeoCryptoVerifyWithECDsaSecp256k1,
|
NeoCryptoVerifyWithECDsaSecp256k1,
|
||||||
|
|
|
@ -49,7 +49,7 @@ func storageFind(ic *interop.Context) error {
|
||||||
|
|
||||||
filteredMap := stackitem.NewMap()
|
filteredMap := stackitem.NewMap()
|
||||||
for k, v := range siMap {
|
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 {
|
sort.Slice(filteredMap.Value().([]stackitem.MapElement), func(i, j int) bool {
|
||||||
return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte),
|
return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte),
|
||||||
|
|
|
@ -51,31 +51,15 @@ func TestStorageFind(t *testing.T) {
|
||||||
|
|
||||||
skeys := [][]byte{{0x01, 0x02}, {0x02, 0x01}, {0x01, 0x01},
|
skeys := [][]byte{{0x01, 0x02}, {0x02, 0x01}, {0x01, 0x01},
|
||||||
{0x04, 0x00}, {0x05, 0x00}, {0x06}, {0x07}, {0x08}}
|
{0x04, 0x00}, {0x05, 0x00}, {0x06}, {0x07}, {0x08}}
|
||||||
items := []*state.StorageItem{
|
items := []state.StorageItem{
|
||||||
{
|
[]byte{0x01, 0x02, 0x03, 0x04},
|
||||||
Value: []byte{0x01, 0x02, 0x03, 0x04},
|
[]byte{0x04, 0x03, 0x02, 0x01},
|
||||||
},
|
[]byte{0x03, 0x04, 0x05, 0x06},
|
||||||
{
|
[]byte{byte(stackitem.ByteArrayT), 2, 0xCA, 0xFE},
|
||||||
Value: []byte{0x04, 0x03, 0x02, 0x01},
|
[]byte{0xFF, 0xFF},
|
||||||
},
|
rawArr,
|
||||||
{
|
rawArr0,
|
||||||
Value: []byte{0x03, 0x04, 0x05, 0x06},
|
rawArr1,
|
||||||
},
|
|
||||||
{
|
|
||||||
Value: []byte{byte(stackitem.ByteArrayT), 2, 0xCA, 0xFE},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Value: []byte{0xFF, 0xFF},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Value: rawArr,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Value: rawArr0,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Value: rawArr1,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(t, chain.contracts.Management.PutContractState(chain.dao, contractState))
|
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{
|
testFind(t, 0x01, istorage.FindDefault, []stackitem.Item{
|
||||||
stackitem.NewStruct([]stackitem.Item{
|
stackitem.NewStruct([]stackitem.Item{
|
||||||
stackitem.NewByteArray(skeys[2]),
|
stackitem.NewByteArray(skeys[2]),
|
||||||
stackitem.NewByteArray(items[2].Value),
|
stackitem.NewByteArray(items[2]),
|
||||||
}),
|
}),
|
||||||
stackitem.NewStruct([]stackitem.Item{
|
stackitem.NewStruct([]stackitem.Item{
|
||||||
stackitem.NewByteArray(skeys[0]),
|
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) {
|
t.Run("values only", func(t *testing.T) {
|
||||||
testFind(t, 0x01, istorage.FindValuesOnly, []stackitem.Item{
|
testFind(t, 0x01, istorage.FindValuesOnly, []stackitem.Item{
|
||||||
stackitem.NewByteArray(items[2].Value),
|
stackitem.NewByteArray(items[2]),
|
||||||
stackitem.NewByteArray(items[0].Value),
|
stackitem.NewByteArray(items[0]),
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
t.Run("deserialize values", func(t *testing.T) {
|
t.Run("deserialize values", func(t *testing.T) {
|
||||||
testFind(t, 0x04, istorage.FindValuesOnly|istorage.FindDeserialize, []stackitem.Item{
|
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) {
|
t.Run("invalid", func(t *testing.T) {
|
||||||
v.Estack().PushVal(istorage.FindDeserialize)
|
v.Estack().PushVal(istorage.FindDeserialize)
|
||||||
|
|
|
@ -73,10 +73,6 @@ func storageDelete(ic *interop.Context) error {
|
||||||
}
|
}
|
||||||
ic.VM.AddGas(ic.Chain.GetPolicer().GetStoragePrice())
|
ic.VM.AddGas(ic.Chain.GetPolicer().GetStoragePrice())
|
||||||
key := ic.VM.Estack().Pop().Bytes()
|
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)
|
return ic.DAO.DeleteStorageItem(stc.ID, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,8 +85,8 @@ func storageGet(ic *interop.Context) error {
|
||||||
}
|
}
|
||||||
key := ic.VM.Estack().Pop().Bytes()
|
key := ic.VM.Estack().Pop().Bytes()
|
||||||
si := ic.DAO.GetStorageItem(stc.ID, key)
|
si := ic.DAO.GetStorageItem(stc.ID, key)
|
||||||
if si != nil && si.Value != nil {
|
if si != nil {
|
||||||
ic.VM.Estack().PushVal(si.Value)
|
ic.VM.Estack().PushVal([]byte(si))
|
||||||
} else {
|
} else {
|
||||||
ic.VM.Estack().PushVal(stackitem.Null{})
|
ic.VM.Estack().PushVal(stackitem.Null{})
|
||||||
}
|
}
|
||||||
|
@ -122,7 +118,7 @@ func storageGetContextInternal(ic *interop.Context, isReadOnly bool) error {
|
||||||
return nil
|
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 {
|
if len(key) > MaxStorageKeyLen {
|
||||||
return errors.New("key is too big")
|
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")
|
return errors.New("StorageContext is read only")
|
||||||
}
|
}
|
||||||
si := ic.DAO.GetStorageItem(stc.ID, key)
|
si := ic.DAO.GetStorageItem(stc.ID, key)
|
||||||
if si != nil && si.IsConst {
|
sizeInc := len(value)
|
||||||
return errors.New("storage item exists and is read-only")
|
|
||||||
}
|
|
||||||
sizeInc := 1
|
|
||||||
if si == nil {
|
if si == nil {
|
||||||
si = &state.StorageItem{}
|
si = state.StorageItem{}
|
||||||
sizeInc = len(key) + len(value)
|
sizeInc = len(key) + len(value)
|
||||||
} else if len(value) != 0 {
|
} else if len(value) != 0 {
|
||||||
if len(value) <= len(si.Value) {
|
if len(value) <= len(si) {
|
||||||
sizeInc = (len(value)-1)/4 + 1
|
sizeInc = (len(value)-1)/4 + 1
|
||||||
} else {
|
} else if len(si) != 0 {
|
||||||
sizeInc = (len(si.Value)-1)/4 + 1 + len(value) - len(si.Value)
|
sizeInc = (len(si)-1)/4 + 1 + len(value) - len(si)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !ic.VM.AddGas(int64(sizeInc) * ic.Chain.GetPolicer().GetStoragePrice()) {
|
if !ic.VM.AddGas(int64(sizeInc) * ic.Chain.GetPolicer().GetStoragePrice()) {
|
||||||
return errGasLimitExceeded
|
return errGasLimitExceeded
|
||||||
}
|
}
|
||||||
si.Value = value
|
return ic.DAO.PutStorageItem(stc.ID, key, value)
|
||||||
si.IsConst = isConst
|
|
||||||
return ic.DAO.PutStorageItem(stc.ID, key, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storagePutInternal is a unified implementation of storagePut and storagePutEx.
|
// storagePut puts key-value pair into the storage.
|
||||||
func storagePutInternal(ic *interop.Context, getFlag bool) error {
|
func storagePut(ic *interop.Context) error {
|
||||||
stcInterface := ic.VM.Estack().Pop().Value()
|
stcInterface := ic.VM.Estack().Pop().Value()
|
||||||
stc, ok := stcInterface.(*StorageContext)
|
stc, ok := stcInterface.(*StorageContext)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -164,21 +155,7 @@ func storagePutInternal(ic *interop.Context, getFlag bool) error {
|
||||||
}
|
}
|
||||||
key := ic.VM.Estack().Pop().Bytes()
|
key := ic.VM.Estack().Pop().Bytes()
|
||||||
value := ic.VM.Estack().Pop().Bytes()
|
value := ic.VM.Estack().Pop().Bytes()
|
||||||
var flag int
|
return putWithContext(ic, stc, key, value)
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storageContextAsReadOnly sets given context to read-only mode.
|
// storageContextAsReadOnly sets given context to read-only mode.
|
||||||
|
|
|
@ -277,21 +277,6 @@ func TestStoragePut(t *testing.T) {
|
||||||
initVM(t, []byte{1}, make([]byte, MaxStorageValueLen+1), -1)
|
initVM(t, []byte{1}, make([]byte, MaxStorageValueLen+1), -1)
|
||||||
require.Error(t, storagePut(ic))
|
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))
|
require.NoError(t, bc.contracts.Management.PutContractState(ic.DAO, cs))
|
||||||
v.LoadScriptWithHash(cs.NEF.Script, cs.Hash, callflag.All)
|
v.LoadScriptWithHash(cs.NEF.Script, cs.Hash, callflag.All)
|
||||||
put := func(key, value string, flag int) {
|
put := func(key, value string, flag int) {
|
||||||
v.Estack().PushVal(flag)
|
|
||||||
v.Estack().PushVal(value)
|
v.Estack().PushVal(value)
|
||||||
v.Estack().PushVal(key)
|
v.Estack().PushVal(key)
|
||||||
require.NoError(t, storageGetContext(ic))
|
require.NoError(t, storageGetContext(ic))
|
||||||
require.NoError(t, storagePutEx(ic))
|
require.NoError(t, storagePut(ic))
|
||||||
}
|
}
|
||||||
put("key1", "value1", 0)
|
put("key1", "value1", 0)
|
||||||
put("key2", "value2", 0)
|
put("key2", "value2", 0)
|
||||||
put("key3", "value3", 0)
|
put("key3", "value3", 0)
|
||||||
put("key4", "value4", 1)
|
|
||||||
|
|
||||||
t.Run("good", func(t *testing.T) {
|
t.Run("good", func(t *testing.T) {
|
||||||
v.Estack().PushVal("key1")
|
v.Estack().PushVal("key1")
|
||||||
|
@ -328,11 +311,6 @@ func TestStorageDelete(t *testing.T) {
|
||||||
require.NoError(t, storageContextAsReadOnly(ic))
|
require.NoError(t, storageContextAsReadOnly(ic))
|
||||||
require.Error(t, storageDelete(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.
|
// getTestContractState returns 2 contracts second of which is allowed to call the first.
|
||||||
|
|
|
@ -82,8 +82,6 @@ var systemInterops = []interop.Function{
|
||||||
RequiredFlags: callflag.ReadStates},
|
RequiredFlags: callflag.ReadStates},
|
||||||
{Name: interopnames.SystemStoragePut, Func: storagePut, Price: 0, RequiredFlags: callflag.WriteStates,
|
{Name: interopnames.SystemStoragePut, Func: storagePut, Price: 0, RequiredFlags: callflag.WriteStates,
|
||||||
ParamCount: 3}, // These don't have static price in C# code.
|
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,
|
{Name: interopnames.SystemStorageAsReadOnly, Func: storageContextAsReadOnly, Price: 1 << 4,
|
||||||
RequiredFlags: callflag.ReadStates, ParamCount: 1},
|
RequiredFlags: callflag.ReadStates, ParamCount: 1},
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,6 @@ func TestUnexpectedNonInterops(t *testing.T) {
|
||||||
storageFind,
|
storageFind,
|
||||||
storageGet,
|
storageGet,
|
||||||
storagePut,
|
storagePut,
|
||||||
storagePutEx,
|
|
||||||
}
|
}
|
||||||
for _, f := range funcs {
|
for _, f := range funcs {
|
||||||
for k, v := range vals {
|
for k, v := range vals {
|
||||||
|
|
|
@ -257,7 +257,7 @@ func (s *Designate) GetDesignatedByRole(d dao.DAO, r Role, index uint32) (keys.P
|
||||||
}
|
}
|
||||||
var ns NodeList
|
var ns NodeList
|
||||||
var bestIndex uint32
|
var bestIndex uint32
|
||||||
var resSi *state.StorageItem
|
var resSi state.StorageItem
|
||||||
for k, si := range kvs {
|
for k, si := range kvs {
|
||||||
if len(k) < 4 {
|
if len(k) < 4 {
|
||||||
continue
|
continue
|
||||||
|
@ -269,7 +269,7 @@ func (s *Designate) GetDesignatedByRole(d dao.DAO, r Role, index uint32) (keys.P
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if resSi != nil {
|
if resSi != nil {
|
||||||
reader := io.NewBinReaderFromBuf(resSi.Value)
|
reader := io.NewBinReaderFromBuf(resSi)
|
||||||
ns.DecodeBinary(reader)
|
ns.DecodeBinary(reader)
|
||||||
if reader.Err != nil {
|
if reader.Err != nil {
|
||||||
return nil, 0, reader.Err
|
return nil, 0, reader.Err
|
||||||
|
@ -324,8 +324,7 @@ func (s *Designate) DesignateAsRole(ic *interop.Context, r Role, pubs keys.Publi
|
||||||
}
|
}
|
||||||
sort.Sort(pubs)
|
sort.Sort(pubs)
|
||||||
s.rolesChangedFlag.Store(true)
|
s.rolesChangedFlag.Store(true)
|
||||||
si = &state.StorageItem{Value: NodeList(pubs).Bytes()}
|
return ic.DAO.PutStorageItem(s.ID, key, NodeList(pubs).Bytes())
|
||||||
return ic.DAO.PutStorageItem(s.ID, key, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Designate) getRole(item stackitem.Item) (Role, bool) {
|
func (s *Designate) getRole(item stackitem.Item) (Role, bool) {
|
||||||
|
|
|
@ -480,16 +480,8 @@ func (m *Management) InitializeCache(d dao.DAO) error {
|
||||||
|
|
||||||
var initErr error
|
var initErr error
|
||||||
d.Seek(m.ID, []byte{prefixContract}, func(_, v []byte) {
|
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
|
var cs state.Contract
|
||||||
r = io.NewBinReaderFromBuf(si.Value)
|
r := io.NewBinReaderFromBuf(v)
|
||||||
cs.DecodeBinary(r)
|
cs.DecodeBinary(r)
|
||||||
if r.Err != nil {
|
if r.Err != nil {
|
||||||
initErr = r.Err
|
initErr = r.Err
|
||||||
|
@ -546,10 +538,10 @@ func (m *Management) getNextContractID(d dao.DAO) (int32, error) {
|
||||||
return 0, errors.New("nextAvailableID is not initialized")
|
return 0, errors.New("nextAvailableID is not initialized")
|
||||||
|
|
||||||
}
|
}
|
||||||
id := bigint.FromBytes(si.Value)
|
id := bigint.FromBytes(si)
|
||||||
ret := int32(id.Int64())
|
ret := int32(id.Int64())
|
||||||
id.Add(id, intOne)
|
id.Add(id, intOne)
|
||||||
si.Value = bigint.ToPreallocatedBytes(id, si.Value)
|
si = bigint.ToPreallocatedBytes(id, si)
|
||||||
return ret, d.PutStorageItem(m.ID, keyNextAvailableID, si)
|
return ret, d.PutStorageItem(m.ID, keyNextAvailableID, si)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,7 @@ func TestManagement_Initialize(t *testing.T) {
|
||||||
t.Run("invalid contract state", func(t *testing.T) {
|
t.Run("invalid contract state", func(t *testing.T) {
|
||||||
d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
|
d := dao.NewSimple(storage.NewMemoryStore(), netmode.UnitTestNet, false)
|
||||||
mgmt := newManagement()
|
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))
|
require.Error(t, mgmt.InitializeCache(d))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -259,8 +259,7 @@ func (n *NameService) setPrice(ic *interop.Context, args []stackitem.Item) stack
|
||||||
}
|
}
|
||||||
|
|
||||||
n.checkCommittee(ic)
|
n.checkCommittee(ic)
|
||||||
si := &state.StorageItem{Value: bigint.ToBytes(price)}
|
err := ic.DAO.PutStorageItem(n.ID, []byte{prefixDomainPrice}, bigint.ToBytes(price))
|
||||||
err := ic.DAO.PutStorageItem(n.ID, []byte{prefixDomainPrice}, si)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
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 {
|
func (n *NameService) getPriceInternal(d dao.DAO) *big.Int {
|
||||||
si := d.GetStorageItem(n.ID, []byte{prefixDomainPrice})
|
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) {
|
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)
|
n.mint(ic, token)
|
||||||
err := ic.DAO.PutStorageItem(n.ID,
|
err := ic.DAO.PutStorageItem(n.ID,
|
||||||
makeExpirationKey(token.Expiration, token.ID()),
|
makeExpirationKey(token.Expiration, token.ID()),
|
||||||
&state.StorageItem{Value: []byte{0}})
|
state.StorageItem{0})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -367,8 +366,7 @@ func (n *NameService) renew(ic *interop.Context, args []stackitem.Item) stackite
|
||||||
}
|
}
|
||||||
|
|
||||||
binary.BigEndian.PutUint32(key[1:], token.Expiration)
|
binary.BigEndian.PutUint32(key[1:], token.Expiration)
|
||||||
si := &state.StorageItem{Value: []byte{0}}
|
err = ic.DAO.PutStorageItem(n.ID, key, state.StorageItem{0})
|
||||||
err = ic.DAO.PutStorageItem(n.ID, key, si)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -441,7 +439,7 @@ func (n *NameService) setRecord(ic *interop.Context, args []stackitem.Item) stac
|
||||||
panic("not witnessed by admin")
|
panic("not witnessed by admin")
|
||||||
}
|
}
|
||||||
key := makeRecordKey(domain, name, rt)
|
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 {
|
if err := ic.DAO.PutStorageItem(n.ID, key, si); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -478,7 +476,7 @@ func (n *NameService) getRecord(ic *interop.Context, args []stackitem.Item) stac
|
||||||
if si == nil {
|
if si == nil {
|
||||||
return stackitem.Null{}
|
return stackitem.Null{}
|
||||||
}
|
}
|
||||||
return stackitem.NewByteArray(si.Value)
|
return stackitem.NewByteArray(si)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NameService) deleteRecord(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
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)
|
res := make(map[RecordType]string)
|
||||||
d.Seek(n.ID, key, func(k, v []byte) {
|
d.Seek(n.ID, key, func(k, v []byte) {
|
||||||
rt := RecordType(k[len(k)-1])
|
rt := RecordType(k[len(k)-1])
|
||||||
var si state.StorageItem
|
res[rt] = string(v)
|
||||||
r := io.NewBinReaderFromBuf(v)
|
|
||||||
si.DecodeBinary(r)
|
|
||||||
if r.Err != nil {
|
|
||||||
panic(r.Err)
|
|
||||||
}
|
|
||||||
res[rt] = string(si.Value)
|
|
||||||
})
|
})
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,7 +41,7 @@ func newGAS() *GAS {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GAS) increaseBalance(_ *interop.Context, _ util.Uint160, si *state.StorageItem, amount *big.Int) error {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -52,9 +52,9 @@ func (g *GAS) increaseBalance(_ *interop.Context, _ util.Uint160, si *state.Stor
|
||||||
}
|
}
|
||||||
acc.Balance.Add(&acc.Balance, amount)
|
acc.Balance.Add(&acc.Balance, amount)
|
||||||
if acc.Balance.Sign() != 0 {
|
if acc.Balance.Sign() != 0 {
|
||||||
si.Value = acc.Bytes()
|
*si = acc.Bytes()
|
||||||
} else {
|
} else {
|
||||||
si.Value = nil
|
*si = nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
"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/crypto/keys"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
"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"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||||
|
@ -172,7 +171,7 @@ func (n *NEO) Initialize(ic *interop.Context) error {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -192,7 +191,7 @@ func (n *NEO) Initialize(ic *interop.Context) error {
|
||||||
gr := &gasRecord{{Index: index, GASPerBlock: *value}}
|
gr := &gasRecord{{Index: index, GASPerBlock: *value}}
|
||||||
n.gasPerBlock.Store(*gr)
|
n.gasPerBlock.Store(*gr)
|
||||||
n.gasPerBlockChanged.Store(false)
|
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 {
|
if err != nil {
|
||||||
return err
|
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 {
|
func (n *NEO) InitializeCache(bc blockchainer.Blockchainer, d dao.DAO) error {
|
||||||
var committee = keysWithVotes{}
|
var committee = keysWithVotes{}
|
||||||
si := d.GetStorageItem(n.ID, prefixCommittee)
|
si := d.GetStorageItem(n.ID, prefixCommittee)
|
||||||
if err := committee.DecodeBytes(si.Value); err != nil {
|
if err := committee.DecodeBytes(si); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := n.updateCache(committee, bc); err != nil {
|
if err := n.updateCache(committee, bc); err != nil {
|
||||||
|
@ -244,8 +243,7 @@ func (n *NEO) updateCommittee(ic *interop.Context) error {
|
||||||
if !votesChanged {
|
if !votesChanged {
|
||||||
// We need to put in storage anyway, as it affects dumps
|
// We need to put in storage anyway, as it affects dumps
|
||||||
committee := n.committee.Load().(keysWithVotes)
|
committee := n.committee.Load().(keysWithVotes)
|
||||||
si := &state.StorageItem{Value: committee.Bytes()}
|
return ic.DAO.PutStorageItem(n.ID, prefixCommittee, committee.Bytes())
|
||||||
return ic.DAO.PutStorageItem(n.ID, prefixCommittee, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_, cvs, err := n.computeCommitteeMembers(ic.Chain, ic.DAO)
|
_, cvs, err := n.computeCommitteeMembers(ic.Chain, ic.DAO)
|
||||||
|
@ -256,8 +254,7 @@ func (n *NEO) updateCommittee(ic *interop.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
n.votesChanged.Store(false)
|
n.votesChanged.Store(false)
|
||||||
si := &state.StorageItem{Value: cvs.Bytes()}
|
return ic.DAO.PutStorageItem(n.ID, prefixCommittee, cvs.Bytes())
|
||||||
return ic.DAO.PutStorageItem(n.ID, prefixCommittee, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ShouldUpdateCommittee returns true if committee is updated at block h.
|
// 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))
|
voterReward.Div(voterReward, big.NewInt(100))
|
||||||
|
|
||||||
var cs = n.committee.Load().(keysWithVotes)
|
var cs = n.committee.Load().(keysWithVotes)
|
||||||
var si = new(state.StorageItem)
|
|
||||||
var key = make([]byte, 38)
|
var key = make([]byte, 38)
|
||||||
for i := range cs {
|
for i := range cs {
|
||||||
if cs[i].Votes.Sign() > 0 {
|
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)
|
binary.BigEndian.PutUint32(key[34:], ic.Block.Index+1)
|
||||||
|
|
||||||
si.Value = bigint.ToBytes(tmp)
|
if err := ic.DAO.PutStorageItem(n.ID, key, bigint.ToBytes(tmp)); err != nil {
|
||||||
if err := ic.DAO.PutStorageItem(n.ID, key, si); err != nil {
|
|
||||||
return err
|
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 {
|
func (n *NEO) getGASPerVote(d dao.DAO, key []byte, index ...uint32) []big.Int {
|
||||||
var max = make([]uint32, len(index))
|
var max = make([]uint32, len(index))
|
||||||
var reward = make([]big.Int, len(index))
|
var reward = make([]big.Int, len(index))
|
||||||
var si state.StorageItem
|
|
||||||
d.Seek(n.ID, key, func(k, v []byte) {
|
d.Seek(n.ID, key, func(k, v []byte) {
|
||||||
if len(k) == 4 {
|
if len(k) == 4 {
|
||||||
num := binary.BigEndian.Uint32(k)
|
num := binary.BigEndian.Uint32(k)
|
||||||
for i, ind := range index {
|
for i, ind := range index {
|
||||||
if max[i] < num && num <= ind {
|
if max[i] < num && num <= ind {
|
||||||
max[i] = num
|
max[i] = num
|
||||||
r := io.NewBinReaderFromBuf(v)
|
reward[i] = *bigint.FromBytes(v)
|
||||||
si.DecodeBinary(r)
|
|
||||||
if r.Err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
reward[i] = *bigint.FromBytes(si.Value)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -366,7 +355,7 @@ func (n *NEO) increaseBalance(ic *interop.Context, h util.Uint160, si *state.Sto
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if amount.Sign() == 0 {
|
if amount.Sign() == 0 {
|
||||||
si.Value = acc.Bytes()
|
*si = acc.Bytes()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err := n.ModifyAccountVotes(acc, ic.DAO, amount, false); err != 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)
|
acc.Balance.Add(&acc.Balance, amount)
|
||||||
if acc.Balance.Sign() != 0 {
|
if acc.Balance.Sign() != 0 {
|
||||||
si.Value = acc.Bytes()
|
*si = acc.Bytes()
|
||||||
} else {
|
} else {
|
||||||
si.Value = nil
|
*si = nil
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -426,7 +415,7 @@ func (n *NEO) getSortedGASRecordFromDAO(d dao.DAO) (gasRecord, error) {
|
||||||
for indexBytes, gasValue := range grMap {
|
for indexBytes, gasValue := range grMap {
|
||||||
gr[i] = gasIndexPair{
|
gr[i] = gasIndexPair{
|
||||||
Index: binary.BigEndian.Uint32([]byte(indexBytes)),
|
Index: binary.BigEndian.Uint32([]byte(indexBytes)),
|
||||||
GASPerBlock: *bigint.FromBytes(gasValue.Value),
|
GASPerBlock: *bigint.FromBytes(gasValue),
|
||||||
}
|
}
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
@ -533,7 +522,7 @@ func (n *NEO) CalculateBonus(d dao.DAO, acc util.Uint160, end uint32) (*big.Int,
|
||||||
if si == nil {
|
if si == nil {
|
||||||
return nil, storage.ErrKeyNotFound
|
return nil, storage.ErrKeyNotFound
|
||||||
}
|
}
|
||||||
st, err := state.NEOBalanceStateFromBytes(si.Value)
|
st, err := state.NEOBalanceStateFromBytes(si)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
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 {
|
func (n *NEO) RegisterCandidateInternal(ic *interop.Context, pub *keys.PublicKey) error {
|
||||||
key := makeValidatorKey(pub)
|
key := makeValidatorKey(pub)
|
||||||
si := ic.DAO.GetStorageItem(n.ID, key)
|
si := ic.DAO.GetStorageItem(n.ID, key)
|
||||||
|
var c *candidate
|
||||||
if si == nil {
|
if si == nil {
|
||||||
c := &candidate{Registered: true}
|
c = &candidate{Registered: true}
|
||||||
si = &state.StorageItem{Value: c.Bytes()}
|
|
||||||
} else {
|
} else {
|
||||||
c := new(candidate).FromBytes(si.Value)
|
c = new(candidate).FromBytes(si)
|
||||||
c.Registered = true
|
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 {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
n.validators.Store(keys.PublicKeys(nil))
|
n.validators.Store(keys.PublicKeys(nil))
|
||||||
c := new(candidate).FromBytes(si.Value)
|
c := new(candidate).FromBytes(si)
|
||||||
c.Registered = false
|
c.Registered = false
|
||||||
ok, err := n.dropCandidateIfZero(ic.DAO, pub, c)
|
ok, err := n.dropCandidateIfZero(ic.DAO, pub, c)
|
||||||
if ok {
|
if ok {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
si.Value = c.Bytes()
|
return ic.DAO.PutStorageItem(n.ID, key, c.Bytes())
|
||||||
return ic.DAO.PutStorageItem(n.ID, key, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *NEO) vote(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
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 {
|
if si == nil {
|
||||||
return errors.New("invalid account")
|
return errors.New("invalid account")
|
||||||
}
|
}
|
||||||
acc, err := state.NEOBalanceStateFromBytes(si.Value)
|
acc, err := state.NEOBalanceStateFromBytes(si)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err := n.ModifyAccountVotes(acc, ic.DAO, &acc.Balance, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
si.Value = acc.Bytes()
|
return ic.DAO.PutStorageItem(n.ID, key, acc.Bytes())
|
||||||
return ic.DAO.PutStorageItem(n.ID, key, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ModifyAccountVotes modifies votes of the specified account by value (can be negative).
|
// 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 {
|
if si == nil {
|
||||||
return errors.New("invalid validator")
|
return errors.New("invalid validator")
|
||||||
}
|
}
|
||||||
cd := new(candidate).FromBytes(si.Value)
|
cd := new(candidate).FromBytes(si)
|
||||||
cd.Votes.Add(&cd.Votes, value)
|
cd.Votes.Add(&cd.Votes, value)
|
||||||
if !isNewVote {
|
if !isNewVote {
|
||||||
ok, err := n.dropCandidateIfZero(d, acc.VoteTo, cd)
|
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")
|
return errors.New("validator must be registered")
|
||||||
}
|
}
|
||||||
n.validators.Store(keys.PublicKeys(nil))
|
n.validators.Store(keys.PublicKeys(nil))
|
||||||
si.Value = cd.Bytes()
|
return d.PutStorageItem(n.ID, key, cd.Bytes())
|
||||||
return d.PutStorageItem(n.ID, key, si)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -736,7 +721,7 @@ func (n *NEO) getCandidates(d dao.DAO, sortByKey bool) ([]keyWithVotes, error) {
|
||||||
}
|
}
|
||||||
arr := make([]keyWithVotes, 0, len(siMap))
|
arr := make([]keyWithVotes, 0, len(siMap))
|
||||||
for key, si := range siMap {
|
for key, si := range siMap {
|
||||||
c := new(candidate).FromBytes(si.Value)
|
c := new(candidate).FromBytes(si)
|
||||||
if c.Registered {
|
if c.Registered {
|
||||||
arr = append(arr, keyWithVotes{Key: key, Votes: &c.Votes})
|
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 {
|
if si == nil {
|
||||||
return errors.New("voters count not found")
|
return errors.New("voters count not found")
|
||||||
}
|
}
|
||||||
votersCount := bigint.FromBytes(si.Value)
|
votersCount := bigint.FromBytes(si)
|
||||||
votersCount.Add(votersCount, amount)
|
votersCount.Add(votersCount, amount)
|
||||||
si.Value = bigint.ToBytes(votersCount)
|
si = bigint.ToPreallocatedBytes(votersCount, si)
|
||||||
return d.PutStorageItem(n.ID, key, 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 {
|
if si == nil {
|
||||||
return nil, nil, errors.New("voters count not found")
|
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 / totalSupply must be >= 0.2
|
||||||
votersCount.Mul(votersCount, big.NewInt(effectiveVoterTurnout))
|
votersCount.Mul(votersCount, big.NewInt(effectiveVoterTurnout))
|
||||||
voterTurnout := votersCount.Div(votersCount, n.getTotalSupply(d))
|
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 := make([]byte, 5)
|
||||||
key[0] = prefixGASPerBlock
|
key[0] = prefixGASPerBlock
|
||||||
binary.BigEndian.PutUint32(key[1:], index)
|
binary.BigEndian.PutUint32(key[1:], index)
|
||||||
si := &state.StorageItem{
|
return dao.PutStorageItem(n.ID, key, bigint.ToBytes(value))
|
||||||
Value: bigint.ToBytes(value),
|
|
||||||
IsConst: false,
|
|
||||||
}
|
|
||||||
return dao.PutStorageItem(n.ID, key, si)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,12 +100,11 @@ func (c *nep17TokenNative) getTotalSupply(d dao.DAO) *big.Int {
|
||||||
if si == nil {
|
if si == nil {
|
||||||
return big.NewInt(0)
|
return big.NewInt(0)
|
||||||
}
|
}
|
||||||
return bigint.FromBytes(si.Value)
|
return bigint.FromBytes(si)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nep17TokenNative) saveTotalSupply(d dao.DAO, supply *big.Int) error {
|
func (c *nep17TokenNative) saveTotalSupply(d dao.DAO, supply *big.Int) error {
|
||||||
si := &state.StorageItem{Value: bigint.ToBytes(supply)}
|
return d.PutStorageItem(c.ID, totalSupplyKey, bigint.ToBytes(supply))
|
||||||
return d.PutStorageItem(c.ID, totalSupplyKey, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *nep17TokenNative) Transfer(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
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 {
|
if amount.Sign() <= 0 {
|
||||||
return errors.New("insufficient funds")
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if si.Value == nil {
|
if si == nil {
|
||||||
err = ic.DAO.DeleteStorageItem(c.ID, key)
|
err = ic.DAO.DeleteStorageItem(c.ID, key)
|
||||||
} else {
|
} else {
|
||||||
err = ic.DAO.PutStorageItem(c.ID, key, si)
|
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)
|
key := makeAccountKey(h)
|
||||||
si := ic.DAO.GetStorageItem(c.ID, key)
|
si := ic.DAO.GetStorageItem(c.ID, key)
|
||||||
if si == nil {
|
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)
|
panic(err)
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
if si.Value == nil {
|
if si == nil {
|
||||||
err = ic.DAO.DeleteStorageItem(c.ID, key)
|
err = ic.DAO.DeleteStorageItem(c.ID, key)
|
||||||
} else {
|
} else {
|
||||||
err = ic.DAO.PutStorageItem(c.ID, key, si)
|
err = ic.DAO.PutStorageItem(c.ID, key, si)
|
||||||
|
|
|
@ -141,12 +141,11 @@ func (n *nonfungible) TotalSupply(d dao.DAO) *big.Int {
|
||||||
if si == nil {
|
if si == nil {
|
||||||
panic(errors.New("total supply is not initialized"))
|
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) {
|
func (n *nonfungible) setTotalSupply(d dao.DAO, ts *big.Int) {
|
||||||
si := &state.StorageItem{Value: bigint.ToBytes(ts)}
|
err := d.PutStorageItem(n.ID, nftTotalSupplyKey, bigint.ToBytes(ts))
|
||||||
err := d.PutStorageItem(n.ID, nftTotalSupplyKey, si)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -222,7 +221,7 @@ func (n *nonfungible) tokens(ic *interop.Context, args []stackitem.Item) stackit
|
||||||
}
|
}
|
||||||
filteredMap := stackitem.NewMap()
|
filteredMap := stackitem.NewMap()
|
||||||
for k, v := range siMap {
|
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 {
|
sort.Slice(filteredMap.Value().([]stackitem.MapElement), func(i, j int) bool {
|
||||||
return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte),
|
return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte),
|
||||||
|
|
|
@ -166,8 +166,7 @@ func (o *Oracle) PostPersist(ic *interop.Context) error {
|
||||||
if len(*idList) == 0 {
|
if len(*idList) == 0 {
|
||||||
err = ic.DAO.DeleteStorageItem(o.ID, idKey)
|
err = ic.DAO.DeleteStorageItem(o.ID, idKey)
|
||||||
} else {
|
} else {
|
||||||
si := &state.StorageItem{Value: idList.Bytes()}
|
err = ic.DAO.PutStorageItem(o.ID, idKey, idList.Bytes())
|
||||||
err = ic.DAO.PutStorageItem(o.ID, idKey, si)
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -303,10 +302,10 @@ func (o *Oracle) RequestInternal(ic *interop.Context, url string, filter *string
|
||||||
callingHash := ic.VM.GetCallingScriptHash()
|
callingHash := ic.VM.GetCallingScriptHash()
|
||||||
o.GAS.mint(ic, o.Hash, gas, false)
|
o.GAS.mint(ic, o.Hash, gas, false)
|
||||||
si := ic.DAO.GetStorageItem(o.ID, prefixRequestID)
|
si := ic.DAO.GetStorageItem(o.ID, prefixRequestID)
|
||||||
itemID := bigint.FromBytes(si.Value)
|
itemID := bigint.FromBytes(si)
|
||||||
id := itemID.Uint64()
|
id := itemID.Uint64()
|
||||||
itemID.Add(itemID, intOne)
|
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 {
|
if err := ic.DAO.PutStorageItem(o.ID, prefixRequestID, si); err != nil {
|
||||||
return err
|
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.
|
// PutRequestInternal puts oracle request with the specified id to d.
|
||||||
func (o *Oracle) PutRequestInternal(id uint64, req *state.OracleRequest, d dao.DAO) error {
|
func (o *Oracle) PutRequestInternal(id uint64, req *state.OracleRequest, d dao.DAO) error {
|
||||||
reqItem := &state.StorageItem{Value: req.Bytes()}
|
|
||||||
reqKey := makeRequestKey(id)
|
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
|
return err
|
||||||
}
|
}
|
||||||
o.newRequests[id] = req
|
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)
|
return fmt.Errorf("there are too many pending requests for %s url", req.URL)
|
||||||
}
|
}
|
||||||
*lst = append(*lst, id)
|
*lst = append(*lst, id)
|
||||||
si := &state.StorageItem{Value: lst.Bytes()}
|
return d.PutStorageItem(o.ID, key, lst.Bytes())
|
||||||
return d.PutStorageItem(o.ID, key, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetScriptHash returns script hash or oracle nodes.
|
// 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 {
|
if len(k) != 8 {
|
||||||
return nil, errors.New("invalid request ID")
|
return nil, errors.New("invalid request ID")
|
||||||
}
|
}
|
||||||
r := io.NewBinReaderFromBuf(si.Value)
|
r := io.NewBinReaderFromBuf(si)
|
||||||
req := new(state.OracleRequest)
|
req := new(state.OracleRequest)
|
||||||
req.DecodeBinary(r)
|
req.DecodeBinary(r)
|
||||||
if r.Err != nil {
|
if r.Err != nil {
|
||||||
|
|
|
@ -325,9 +325,7 @@ func (p *Policy) blockAccount(ic *interop.Context, args []stackitem.Item) stacki
|
||||||
key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...)
|
key := append([]byte{blockedAccountPrefix}, hash.BytesBE()...)
|
||||||
p.lock.Lock()
|
p.lock.Lock()
|
||||||
defer p.lock.Unlock()
|
defer p.lock.Unlock()
|
||||||
err := ic.DAO.PutStorageItem(p.ID, key, &state.StorageItem{
|
err := ic.DAO.PutStorageItem(p.ID, key, state.StorageItem{})
|
||||||
Value: []byte{},
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ func getSerializableFromDAO(id int32, d dao.DAO, key []byte, item io.Serializabl
|
||||||
if si == nil {
|
if si == nil {
|
||||||
return storage.ErrKeyNotFound
|
return storage.ErrKeyNotFound
|
||||||
}
|
}
|
||||||
r := io.NewBinReaderFromBuf(si.Value)
|
r := io.NewBinReaderFromBuf(si)
|
||||||
item.DecodeBinary(r)
|
item.DecodeBinary(r)
|
||||||
return r.Err
|
return r.Err
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,7 @@ func putSerializableToDAO(id int32, d dao.DAO, key []byte, item io.Serializable)
|
||||||
if w.Err != nil {
|
if w.Err != nil {
|
||||||
return w.Err
|
return w.Err
|
||||||
}
|
}
|
||||||
return d.PutStorageItem(id, key, &state.StorageItem{
|
return d.PutStorageItem(id, key, w.Bytes())
|
||||||
Value: w.Bytes(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getInt64WithKey(id int32, d dao.DAO, key []byte, defaultValue int64) int64 {
|
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 {
|
if si == nil {
|
||||||
return defaultValue
|
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 {
|
func setInt64WithKey(id int32, dao dao.DAO, key []byte, value int64) error {
|
||||||
si := &state.StorageItem{
|
si := make(state.StorageItem, 8)
|
||||||
Value: make([]byte, 8),
|
binary.LittleEndian.PutUint64(si, uint64(value))
|
||||||
}
|
|
||||||
binary.LittleEndian.PutUint64(si.Value, uint64(value))
|
|
||||||
return dao.PutStorageItem(id, key, si)
|
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 {
|
if si == nil {
|
||||||
return defaultValue
|
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 {
|
func setUint32WithKey(id int32, dao dao.DAO, key []byte, value uint32) error {
|
||||||
si := &state.StorageItem{
|
si := make(state.StorageItem, 4)
|
||||||
Value: make([]byte, 4),
|
binary.LittleEndian.PutUint32(si, value)
|
||||||
}
|
|
||||||
binary.LittleEndian.PutUint32(si.Value, value)
|
|
||||||
return dao.PutStorageItem(id, key, si)
|
return dao.PutStorageItem(id, key, si)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setIntWithKey(id int32, dao dao.DAO, key []byte, value int64) error {
|
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, bigint.ToBytes(big.NewInt(value)))
|
||||||
return dao.PutStorageItem(id, key, si)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getIntWithKey(id int32, dao dao.DAO, key []byte) int64 {
|
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)))
|
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.
|
// makeUint160Key creates a key from account script hash.
|
||||||
|
|
|
@ -553,7 +553,7 @@ func TestContractDestroy(t *testing.T) {
|
||||||
cs1.Manifest.Permissions = []manifest.Permission{*manifest.NewPermission(manifest.PermissionWildcard)}
|
cs1.Manifest.Permissions = []manifest.Permission{*manifest.NewPermission(manifest.PermissionWildcard)}
|
||||||
err := bc.contracts.Management.PutContractState(bc.dao, cs1)
|
err := bc.contracts.Management.PutContractState(bc.dao, cs1)
|
||||||
require.NoError(t, err)
|
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, err)
|
||||||
require.NoError(t, bc.dao.UpdateMPT())
|
require.NoError(t, bc.dao.UpdateMPT())
|
||||||
|
|
||||||
|
|
|
@ -180,7 +180,7 @@ func TestOracle_Request(t *testing.T) {
|
||||||
|
|
||||||
si := ic.DAO.GetStorageItem(cs.ID, []byte("lastOracleResponse"))
|
si := ic.DAO.GetStorageItem(cs.ID, []byte("lastOracleResponse"))
|
||||||
require.NotNil(t, si)
|
require.NotNil(t, si)
|
||||||
item, err := stackitem.DeserializeItem(si.Value)
|
item, err := stackitem.DeserializeItem(si)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
arr, ok := item.Value().([]stackitem.Item)
|
arr, ok := item.Value().([]stackitem.Item)
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
|
|
@ -1,23 +1,4 @@
|
||||||
package state
|
package state
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// StorageItem is the value to be stored with read-only flag.
|
// StorageItem is the value to be stored with read-only flag.
|
||||||
type StorageItem struct {
|
type StorageItem []byte
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
|
@ -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))
|
|
||||||
}
|
|
|
@ -19,6 +19,9 @@ func FromBytes(data []byte) *big.Int {
|
||||||
n := new(big.Int)
|
n := new(big.Int)
|
||||||
size := len(data)
|
size := len(data)
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
|
if data == nil {
|
||||||
|
panic("nil slice provided to `FromBytes`")
|
||||||
|
}
|
||||||
return big.NewInt(0)
|
return big.NewInt(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,16 +38,6 @@ const (
|
||||||
PickField1 FindFlags = 1 << 5
|
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
|
// ConvertContextToReadOnly returns new context from the given one, but with
|
||||||
// writing capability turned off, so that you could only invoke Get and Find
|
// 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
|
// 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)
|
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
|
// 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
|
// 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.
|
// the database it returns nil. This function uses `System.Storage.Get` syscall.
|
||||||
|
|
|
@ -862,13 +862,7 @@ func (s *Server) verifyProof(ps request.Params) (interface{}, *response.Error) {
|
||||||
vp := new(result.VerifyProof)
|
vp := new(result.VerifyProof)
|
||||||
val, ok := mpt.VerifyProof(root, p.Key, p.Proof)
|
val, ok := mpt.VerifyProof(root, p.Key, p.Proof)
|
||||||
if ok {
|
if ok {
|
||||||
var si state.StorageItem
|
vp.Value = val
|
||||||
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
|
|
||||||
}
|
}
|
||||||
return vp, nil
|
return vp, nil
|
||||||
}
|
}
|
||||||
|
@ -927,7 +921,7 @@ func (s *Server) getStorage(ps request.Params) (interface{}, *response.Error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return item.Value, nil
|
return []byte(item), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Server) getrawtransaction(reqParams request.Params) (interface{}, *response.Error) {
|
func (s *Server) getrawtransaction(reqParams request.Params) (interface{}, *response.Error) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue