mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2025-05-04 09:02:28 +00:00
Merge pull request #1013 from nspcc-dev/neo3/vm/stackitem_refactoring
vm: move StackItem to a separate package
This commit is contained in:
commit
795523f5cd
50 changed files with 2575 additions and 2466 deletions
|
@ -18,11 +18,13 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||
"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/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
@ -573,7 +575,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
|||
return errors.Wrap(err, "failed to persist invocation results")
|
||||
}
|
||||
for _, note := range systemInterop.Notifications {
|
||||
arr, ok := note.Item.Value().([]vm.StackItem)
|
||||
arr, ok := note.Item.Value().([]stackitem.Item)
|
||||
if !ok || len(arr) != 4 {
|
||||
continue
|
||||
}
|
||||
|
@ -605,7 +607,7 @@ func (bc *Blockchain) storeBlock(block *block.Block) error {
|
|||
if !ok {
|
||||
continue
|
||||
}
|
||||
amount = emit.BytesToInt(bs)
|
||||
amount = bigint.FromBytes(bs)
|
||||
}
|
||||
bc.processNEP5Transfer(cache, tx, block, note.ScriptHash, from, to, amount.Int64())
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -60,7 +61,7 @@ type Function struct {
|
|||
}
|
||||
|
||||
// Method is a signature for a native method.
|
||||
type Method = func(ic *Context, args []vm.StackItem) vm.StackItem
|
||||
type Method = func(ic *Context, args []stackitem.Item) stackitem.Item
|
||||
|
||||
// MethodAndPrice is a native-contract method descriptor.
|
||||
type MethodAndPrice struct {
|
||||
|
|
|
@ -9,6 +9,7 @@ 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/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
// ECDSAVerify checks ECDSA signature.
|
||||
|
@ -48,12 +49,12 @@ func ECDSACheckMultisig(ic *interop.Context, v *vm.VM) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func getMessage(ic *interop.Context, item vm.StackItem) []byte {
|
||||
func getMessage(ic *interop.Context, item stackitem.Item) []byte {
|
||||
var msg []byte
|
||||
switch val := item.(type) {
|
||||
case *vm.InteropItem:
|
||||
case *stackitem.Interop:
|
||||
msg = val.Value().(crypto.Verifiable).GetSignedPart()
|
||||
case vm.NullItem:
|
||||
case stackitem.Null:
|
||||
msg = ic.Container.GetSignedPart()
|
||||
default:
|
||||
var err error
|
||||
|
|
|
@ -9,16 +9,17 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func initCHECKMULTISIG(msg []byte, n int) ([]vm.StackItem, []vm.StackItem, map[string]*keys.PublicKey, error) {
|
||||
func initCHECKMULTISIG(msg []byte, n int) ([]stackitem.Item, []stackitem.Item, map[string]*keys.PublicKey, error) {
|
||||
var err error
|
||||
|
||||
keyMap := make(map[string]*keys.PublicKey)
|
||||
pkeys := make([]*keys.PrivateKey, n)
|
||||
pubs := make([]vm.StackItem, n)
|
||||
pubs := make([]stackitem.Item, n)
|
||||
for i := range pubs {
|
||||
pkeys[i], err = keys.NewPrivateKey()
|
||||
if err != nil {
|
||||
|
@ -27,25 +28,25 @@ func initCHECKMULTISIG(msg []byte, n int) ([]vm.StackItem, []vm.StackItem, map[s
|
|||
|
||||
pk := pkeys[i].PublicKey()
|
||||
data := pk.Bytes()
|
||||
pubs[i] = vm.NewByteArrayItem(data)
|
||||
pubs[i] = stackitem.NewByteArray(data)
|
||||
keyMap[string(data)] = pk
|
||||
}
|
||||
|
||||
sigs := make([]vm.StackItem, n)
|
||||
sigs := make([]stackitem.Item, n)
|
||||
for i := range sigs {
|
||||
sig := pkeys[i].Sign(msg)
|
||||
sigs[i] = vm.NewByteArrayItem(sig)
|
||||
sigs[i] = stackitem.NewByteArray(sig)
|
||||
}
|
||||
|
||||
return pubs, sigs, keyMap, nil
|
||||
}
|
||||
|
||||
func subSlice(arr []vm.StackItem, indices []int) []vm.StackItem {
|
||||
func subSlice(arr []stackitem.Item, indices []int) []stackitem.Item {
|
||||
if indices == nil {
|
||||
return arr
|
||||
}
|
||||
|
||||
result := make([]vm.StackItem, len(indices))
|
||||
result := make([]stackitem.Item, len(indices))
|
||||
for i, j := range indices {
|
||||
result[i] = arr[j]
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -66,9 +67,9 @@ func txGetAttributes(ic *interop.Context, v *vm.VM) error {
|
|||
if len(tx.Attributes) > vm.MaxArraySize {
|
||||
return errors.New("too many attributes")
|
||||
}
|
||||
attrs := make([]vm.StackItem, 0, len(tx.Attributes))
|
||||
attrs := make([]stackitem.Item, 0, len(tx.Attributes))
|
||||
for i := range tx.Attributes {
|
||||
attrs = append(attrs, vm.NewInteropItem(&tx.Attributes[i]))
|
||||
attrs = append(attrs, stackitem.NewInterop(&tx.Attributes[i]))
|
||||
}
|
||||
v.Estack().PushVal(attrs)
|
||||
return nil
|
||||
|
@ -84,9 +85,9 @@ func txGetWitnesses(ic *interop.Context, v *vm.VM) error {
|
|||
if len(tx.Scripts) > vm.MaxArraySize {
|
||||
return errors.New("too many outputs")
|
||||
}
|
||||
scripts := make([]vm.StackItem, 0, len(tx.Scripts))
|
||||
scripts := make([]stackitem.Item, 0, len(tx.Scripts))
|
||||
for i := range tx.Scripts {
|
||||
scripts = append(scripts, vm.NewInteropItem(&tx.Scripts[i]))
|
||||
scripts = append(scripts, stackitem.NewInterop(&tx.Scripts[i]))
|
||||
}
|
||||
v.Estack().PushVal(scripts)
|
||||
return nil
|
||||
|
@ -139,7 +140,7 @@ func bcGetAccount(ic *interop.Context, v *vm.VM) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(acc))
|
||||
v.Estack().PushVal(stackitem.NewInterop(acc))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -204,13 +205,13 @@ func storageFind(ic *interop.Context, v *vm.VM) error {
|
|||
return err
|
||||
}
|
||||
|
||||
filteredMap := vm.NewMapItem()
|
||||
filteredMap := stackitem.NewMap()
|
||||
for k, v := range siMap {
|
||||
filteredMap.Add(vm.NewByteArrayItem(append(prefix, []byte(k)...)), vm.NewByteArrayItem(v.Value))
|
||||
filteredMap.Add(stackitem.NewByteArray(append(prefix, []byte(k)...)), stackitem.NewByteArray(v.Value))
|
||||
}
|
||||
sort.Slice(filteredMap.Value().([]vm.MapElement), func(i, j int) bool {
|
||||
return bytes.Compare(filteredMap.Value().([]vm.MapElement)[i].Key.Value().([]byte),
|
||||
filteredMap.Value().([]vm.MapElement)[j].Key.Value().([]byte)) == -1
|
||||
sort.Slice(filteredMap.Value().([]stackitem.MapElement), func(i, j int) bool {
|
||||
return bytes.Compare(filteredMap.Value().([]stackitem.MapElement)[i].Key.Value().([]byte),
|
||||
filteredMap.Value().([]stackitem.MapElement)[j].Key.Value().([]byte)) == -1
|
||||
})
|
||||
|
||||
item := vm.NewMapIterator(filteredMap)
|
||||
|
@ -288,7 +289,7 @@ func contractCreate(ic *interop.Context, v *vm.VM) error {
|
|||
return err
|
||||
}
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(contract))
|
||||
v.Estack().PushVal(stackitem.NewInterop(contract))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -342,7 +343,7 @@ func contractMigrate(ic *interop.Context, v *vm.VM) error {
|
|||
}
|
||||
}
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(contract))
|
||||
v.Estack().PushVal(stackitem.NewInterop(contract))
|
||||
return contractDestroy(ic, v)
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/opcode"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -70,12 +71,12 @@ func TestStorageFind(t *testing.T) {
|
|||
|
||||
t.Run("normal invocation", func(t *testing.T) {
|
||||
v.Estack().PushVal([]byte{0x01})
|
||||
v.Estack().PushVal(vm.NewInteropItem(&StorageContext{ScriptHash: scriptHash}))
|
||||
v.Estack().PushVal(stackitem.NewInterop(&StorageContext{ScriptHash: scriptHash}))
|
||||
|
||||
err := storageFind(context, v)
|
||||
require.NoError(t, err)
|
||||
|
||||
var iter *vm.InteropItem
|
||||
var iter *stackitem.Interop
|
||||
require.NotPanics(t, func() { iter = v.Estack().Top().Interop() })
|
||||
|
||||
require.NoError(t, enumerator.Next(context, v))
|
||||
|
@ -108,7 +109,7 @@ func TestStorageFind(t *testing.T) {
|
|||
|
||||
t.Run("normal invocation, empty result", func(t *testing.T) {
|
||||
v.Estack().PushVal([]byte{0x03})
|
||||
v.Estack().PushVal(vm.NewInteropItem(&StorageContext{ScriptHash: scriptHash}))
|
||||
v.Estack().PushVal(stackitem.NewInterop(&StorageContext{ScriptHash: scriptHash}))
|
||||
|
||||
err := storageFind(context, v)
|
||||
require.NoError(t, err)
|
||||
|
@ -119,7 +120,7 @@ func TestStorageFind(t *testing.T) {
|
|||
|
||||
t.Run("invalid type for StorageContext", func(t *testing.T) {
|
||||
v.Estack().PushVal([]byte{0x01})
|
||||
v.Estack().PushVal(vm.NewInteropItem(nil))
|
||||
v.Estack().PushVal(stackitem.NewInterop(nil))
|
||||
|
||||
require.Error(t, storageFind(context, v))
|
||||
})
|
||||
|
@ -129,7 +130,7 @@ func TestStorageFind(t *testing.T) {
|
|||
invalidHash[0] = ^invalidHash[0]
|
||||
|
||||
v.Estack().PushVal([]byte{0x01})
|
||||
v.Estack().PushVal(vm.NewInteropItem(&StorageContext{ScriptHash: invalidHash}))
|
||||
v.Estack().PushVal(stackitem.NewInterop(&StorageContext{ScriptHash: invalidHash}))
|
||||
|
||||
require.Error(t, storageFind(context, v))
|
||||
})
|
||||
|
@ -151,7 +152,7 @@ func TestHeaderGetVersion_Negative(t *testing.T) {
|
|||
chain := newTestChain(t)
|
||||
defer chain.Close()
|
||||
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), block, nil)
|
||||
v.Estack().PushVal(vm.NewBoolItem(false))
|
||||
v.Estack().PushVal(stackitem.NewBool(false))
|
||||
|
||||
err := headerGetVersion(context, v)
|
||||
require.Errorf(t, err, "value is not a header or block")
|
||||
|
@ -183,7 +184,7 @@ func TestTxGetAttributes(t *testing.T) {
|
|||
|
||||
err := txGetAttributes(context, v)
|
||||
require.NoError(t, err)
|
||||
value := v.Estack().Pop().Value().([]vm.StackItem)
|
||||
value := v.Estack().Pop().Value().([]stackitem.Item)
|
||||
require.Equal(t, tx.Attributes[0].Usage, value[0].Value().(*transaction.Attribute).Usage)
|
||||
}
|
||||
|
||||
|
@ -196,7 +197,7 @@ func TestWitnessGetVerificationScript(t *testing.T) {
|
|||
defer chain.Close()
|
||||
|
||||
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), nil, nil)
|
||||
v.Estack().PushVal(vm.NewInteropItem(&witness))
|
||||
v.Estack().PushVal(stackitem.NewInterop(&witness))
|
||||
err := witnessGetVerificationScript(context, v)
|
||||
require.NoError(t, err)
|
||||
value := v.Estack().Pop().Value().([]byte)
|
||||
|
@ -247,7 +248,7 @@ func TestECDSAVerify(t *testing.T) {
|
|||
tx := transaction.New([]byte{0, 1, 2}, 1)
|
||||
msg := tx.GetSignedPart()
|
||||
sign := priv.Sign(msg)
|
||||
runCase(t, false, true, sign, priv.PublicKey().Bytes(), vm.NewInteropItem(tx))
|
||||
runCase(t, false, true, sign, priv.PublicKey().Bytes(), stackitem.NewInterop(tx))
|
||||
})
|
||||
|
||||
t.Run("signed script container", func(t *testing.T) {
|
||||
|
@ -255,7 +256,7 @@ func TestECDSAVerify(t *testing.T) {
|
|||
msg := tx.GetSignedPart()
|
||||
sign := priv.Sign(msg)
|
||||
ic.Container = tx
|
||||
runCase(t, false, true, sign, priv.PublicKey().Bytes(), vm.NullItem{})
|
||||
runCase(t, false, true, sign, priv.PublicKey().Bytes(), stackitem.Null{})
|
||||
})
|
||||
|
||||
t.Run("missing arguments", func(t *testing.T) {
|
||||
|
@ -282,7 +283,7 @@ func TestECDSAVerify(t *testing.T) {
|
|||
func TestAttrGetData(t *testing.T) {
|
||||
v, tx, context, chain := createVMAndTX(t)
|
||||
defer chain.Close()
|
||||
v.Estack().PushVal(vm.NewInteropItem(&tx.Attributes[0]))
|
||||
v.Estack().PushVal(stackitem.NewInterop(&tx.Attributes[0]))
|
||||
|
||||
err := attrGetData(context, v)
|
||||
require.NoError(t, err)
|
||||
|
@ -293,7 +294,7 @@ func TestAttrGetData(t *testing.T) {
|
|||
func TestAttrGetUsage(t *testing.T) {
|
||||
v, tx, context, chain := createVMAndTX(t)
|
||||
defer chain.Close()
|
||||
v.Estack().PushVal(vm.NewInteropItem(&tx.Attributes[0]))
|
||||
v.Estack().PushVal(stackitem.NewInterop(&tx.Attributes[0]))
|
||||
|
||||
err := attrGetUsage(context, v)
|
||||
require.NoError(t, err)
|
||||
|
@ -304,7 +305,7 @@ func TestAttrGetUsage(t *testing.T) {
|
|||
func TestAccountGetScriptHash(t *testing.T) {
|
||||
v, accState, context, chain := createVMAndAccState(t)
|
||||
defer chain.Close()
|
||||
v.Estack().PushVal(vm.NewInteropItem(accState))
|
||||
v.Estack().PushVal(stackitem.NewInterop(accState))
|
||||
|
||||
err := accountGetScriptHash(context, v)
|
||||
require.NoError(t, err)
|
||||
|
@ -315,7 +316,7 @@ func TestAccountGetScriptHash(t *testing.T) {
|
|||
func TestContractGetScript(t *testing.T) {
|
||||
v, contractState, context, chain := createVMAndContractState(t)
|
||||
defer chain.Close()
|
||||
v.Estack().PushVal(vm.NewInteropItem(contractState))
|
||||
v.Estack().PushVal(stackitem.NewInterop(contractState))
|
||||
|
||||
err := contractGetScript(context, v)
|
||||
require.NoError(t, err)
|
||||
|
@ -326,7 +327,7 @@ func TestContractGetScript(t *testing.T) {
|
|||
func TestContractIsPayable(t *testing.T) {
|
||||
v, contractState, context, chain := createVMAndContractState(t)
|
||||
defer chain.Close()
|
||||
v.Estack().PushVal(vm.NewInteropItem(contractState))
|
||||
v.Estack().PushVal(stackitem.NewInterop(contractState))
|
||||
|
||||
err := contractIsPayable(context, v)
|
||||
require.NoError(t, err)
|
||||
|
@ -341,13 +342,13 @@ func createVMAndPushBlock(t *testing.T) (*vm.VM, *block.Block, *interop.Context,
|
|||
block := newDumbBlock()
|
||||
chain := newTestChain(t)
|
||||
context := chain.newInteropContext(trigger.Application, dao.NewSimple(storage.NewMemoryStore()), block, nil)
|
||||
v.Estack().PushVal(vm.NewInteropItem(block))
|
||||
v.Estack().PushVal(stackitem.NewInterop(block))
|
||||
return v, block, context, chain
|
||||
}
|
||||
|
||||
func createVMAndPushTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interop.Context, *Blockchain) {
|
||||
v, tx, context, chain := createVMAndTX(t)
|
||||
v.Estack().PushVal(vm.NewInteropItem(tx))
|
||||
v.Estack().PushVal(stackitem.NewInterop(tx))
|
||||
return v, tx, context, chain
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -58,7 +59,7 @@ func bcGetBlock(ic *interop.Context, v *vm.VM) error {
|
|||
if err != nil {
|
||||
v.Estack().PushVal([]byte{})
|
||||
} else {
|
||||
v.Estack().PushVal(vm.NewInteropItem(block))
|
||||
v.Estack().PushVal(stackitem.NewInterop(block))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -74,7 +75,7 @@ func bcGetContract(ic *interop.Context, v *vm.VM) error {
|
|||
if err != nil {
|
||||
v.Estack().PushVal([]byte{})
|
||||
} else {
|
||||
v.Estack().PushVal(vm.NewInteropItem(cs))
|
||||
v.Estack().PushVal(stackitem.NewInterop(cs))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -89,7 +90,7 @@ func bcGetHeader(ic *interop.Context, v *vm.VM) error {
|
|||
if err != nil {
|
||||
v.Estack().PushVal([]byte{})
|
||||
} else {
|
||||
v.Estack().PushVal(vm.NewInteropItem(header))
|
||||
v.Estack().PushVal(stackitem.NewInterop(header))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -117,7 +118,7 @@ func bcGetTransaction(ic *interop.Context, v *vm.VM) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(tx))
|
||||
v.Estack().PushVal(stackitem.NewInterop(tx))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -208,9 +209,9 @@ func blockGetTransactions(ic *interop.Context, v *vm.VM) error {
|
|||
if len(block.Transactions) > vm.MaxArraySize {
|
||||
return errors.New("too many transactions")
|
||||
}
|
||||
txes := make([]vm.StackItem, 0, len(block.Transactions))
|
||||
txes := make([]stackitem.Item, 0, len(block.Transactions))
|
||||
for _, tx := range block.Transactions {
|
||||
txes = append(txes, vm.NewInteropItem(tx))
|
||||
txes = append(txes, stackitem.NewInterop(tx))
|
||||
}
|
||||
v.Estack().PushVal(txes)
|
||||
return nil
|
||||
|
@ -229,7 +230,7 @@ func blockGetTransaction(ic *interop.Context, v *vm.VM) error {
|
|||
return errors.New("wrong transaction index")
|
||||
}
|
||||
tx := block.Transactions[index]
|
||||
v.Estack().PushVal(vm.NewInteropItem(tx))
|
||||
v.Estack().PushVal(stackitem.NewInterop(tx))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -247,7 +248,7 @@ func txGetHash(ic *interop.Context, v *vm.VM) error {
|
|||
// engineGetScriptContainer returns transaction that contains the script being
|
||||
// run.
|
||||
func engineGetScriptContainer(ic *interop.Context, v *vm.VM) error {
|
||||
v.Estack().PushVal(vm.NewInteropItem(ic.Container))
|
||||
v.Estack().PushVal(stackitem.NewInterop(ic.Container))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -289,9 +290,9 @@ func runtimeNotify(ic *interop.Context, v *vm.VM) error {
|
|||
// outside of the interop subsystem anyway. I'd probably fail transactions
|
||||
// that emit such broken notifications, but that might break compatibility
|
||||
// with testnet/mainnet, so we're replacing these with error messages.
|
||||
_, err := vm.SerializeItem(item)
|
||||
_, err := stackitem.SerializeItem(item)
|
||||
if err != nil {
|
||||
item = vm.NewByteArrayItem([]byte(fmt.Sprintf("bad notification: %v", err)))
|
||||
item = stackitem.NewByteArray([]byte(fmt.Sprintf("bad notification: %v", err)))
|
||||
}
|
||||
ne := state.NotificationEvent{ScriptHash: v.GetCurrentScriptHash(), Item: item}
|
||||
ic.Notifications = append(ic.Notifications, ne)
|
||||
|
@ -387,7 +388,7 @@ func storageGetContext(ic *interop.Context, v *vm.VM) error {
|
|||
ScriptHash: v.GetCurrentScriptHash(),
|
||||
ReadOnly: false,
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(sc))
|
||||
v.Estack().PushVal(stackitem.NewInterop(sc))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -397,7 +398,7 @@ func storageGetReadOnlyContext(ic *interop.Context, v *vm.VM) error {
|
|||
ScriptHash: v.GetCurrentScriptHash(),
|
||||
ReadOnly: true,
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(sc))
|
||||
v.Estack().PushVal(stackitem.NewInterop(sc))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -467,7 +468,7 @@ func storageContextAsReadOnly(ic *interop.Context, v *vm.VM) error {
|
|||
}
|
||||
stc = stx
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(stc))
|
||||
v.Estack().PushVal(stackitem.NewInterop(stc))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -488,7 +489,7 @@ func contractCallEx(ic *interop.Context, v *vm.VM) error {
|
|||
return contractCallExInternal(ic, v, h, method, args, flags)
|
||||
}
|
||||
|
||||
func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, method vm.StackItem, args vm.StackItem, _ smartcontract.CallFlag) error {
|
||||
func contractCallExInternal(ic *interop.Context, v *vm.VM, h []byte, method stackitem.Item, args stackitem.Item, _ smartcontract.CallFlag) error {
|
||||
u, err := util.Uint160DecodeBytesBE(h)
|
||||
if err != nil {
|
||||
return errors.New("invalid contract hash")
|
||||
|
@ -548,6 +549,6 @@ func contractGetStorageContext(ic *interop.Context, v *vm.VM) error {
|
|||
stc := &StorageContext{
|
||||
ScriptHash: cs.ScriptHash(),
|
||||
}
|
||||
v.Estack().PushVal(vm.NewInteropItem(stc))
|
||||
v.Estack().PushVal(stackitem.NewInterop(stc))
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
|
@ -194,7 +194,7 @@ func (n *NEO) distributeGas(ic *interop.Context, h util.Uint160, acc *state.NEOB
|
|||
return nil
|
||||
}
|
||||
|
||||
func (n *NEO) unclaimedGas(ic *interop.Context, args []vm.StackItem) vm.StackItem {
|
||||
func (n *NEO) unclaimedGas(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
u := toUint160(args[0])
|
||||
end := uint32(toBigInt(args[1]).Int64())
|
||||
bs, err := ic.DAO.GetNEP5Balances(u)
|
||||
|
@ -204,12 +204,12 @@ func (n *NEO) unclaimedGas(ic *interop.Context, args []vm.StackItem) vm.StackIte
|
|||
tr := bs.Trackers[n.Hash]
|
||||
|
||||
gen := ic.Chain.CalculateClaimable(tr.Balance, tr.LastUpdatedBlock, end)
|
||||
return vm.NewBigIntegerItem(big.NewInt(int64(gen)))
|
||||
return stackitem.NewBigInteger(big.NewInt(int64(gen)))
|
||||
}
|
||||
|
||||
func (n *NEO) registerValidator(ic *interop.Context, args []vm.StackItem) vm.StackItem {
|
||||
func (n *NEO) registerValidator(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
err := n.registerValidatorInternal(ic, toPublicKey(args[0]))
|
||||
return vm.NewBoolItem(err == nil)
|
||||
return stackitem.NewBool(err == nil)
|
||||
}
|
||||
|
||||
func (n *NEO) registerValidatorInternal(ic *interop.Context, pub *keys.PublicKey) error {
|
||||
|
@ -226,9 +226,9 @@ func (n *NEO) registerValidatorInternal(ic *interop.Context, pub *keys.PublicKey
|
|||
return ic.DAO.PutStorageItem(n.Hash, key, si)
|
||||
}
|
||||
|
||||
func (n *NEO) vote(ic *interop.Context, args []vm.StackItem) vm.StackItem {
|
||||
func (n *NEO) vote(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
acc := toUint160(args[0])
|
||||
arr := args[1].Value().([]vm.StackItem)
|
||||
arr := args[1].Value().([]stackitem.Item)
|
||||
var pubs keys.PublicKeys
|
||||
for i := range arr {
|
||||
pub := new(keys.PublicKey)
|
||||
|
@ -241,7 +241,7 @@ func (n *NEO) vote(ic *interop.Context, args []vm.StackItem) vm.StackItem {
|
|||
pubs = append(pubs, pub)
|
||||
}
|
||||
err := n.VoteInternal(ic, acc, pubs)
|
||||
return vm.NewBoolItem(err == nil)
|
||||
return stackitem.NewBool(err == nil)
|
||||
}
|
||||
|
||||
// VoteInternal votes from account h for validarors specified in pubs.
|
||||
|
@ -361,19 +361,19 @@ func (n *NEO) GetRegisteredValidators(d dao.DAO) ([]state.Validator, error) {
|
|||
return arr, nil
|
||||
}
|
||||
|
||||
func (n *NEO) getRegisteredValidatorsCall(ic *interop.Context, _ []vm.StackItem) vm.StackItem {
|
||||
func (n *NEO) getRegisteredValidatorsCall(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
validators, err := n.getRegisteredValidators(ic.DAO)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
arr := make([]vm.StackItem, len(validators))
|
||||
arr := make([]stackitem.Item, len(validators))
|
||||
for i := range validators {
|
||||
arr[i] = vm.NewStructItem([]vm.StackItem{
|
||||
vm.NewByteArrayItem([]byte(validators[i].Key)),
|
||||
vm.NewBigIntegerItem(validators[i].Votes),
|
||||
arr[i] = stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte(validators[i].Key)),
|
||||
stackitem.NewBigInteger(validators[i].Votes),
|
||||
})
|
||||
}
|
||||
return vm.NewArrayItem(arr)
|
||||
return stackitem.NewArray(arr)
|
||||
}
|
||||
|
||||
// GetValidatorsInternal returns a list of current validators.
|
||||
|
@ -430,7 +430,7 @@ func (n *NEO) GetValidatorsInternal(bc blockchainer.Blockchainer, d dao.DAO) (ke
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (n *NEO) getValidators(ic *interop.Context, _ []vm.StackItem) vm.StackItem {
|
||||
func (n *NEO) getValidators(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
result, err := n.GetValidatorsInternal(ic.Chain, ic.DAO)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -438,7 +438,7 @@ func (n *NEO) getValidators(ic *interop.Context, _ []vm.StackItem) vm.StackItem
|
|||
return pubsToArray(result)
|
||||
}
|
||||
|
||||
func (n *NEO) getNextBlockValidators(ic *interop.Context, _ []vm.StackItem) vm.StackItem {
|
||||
func (n *NEO) getNextBlockValidators(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
result, err := n.GetNextBlockValidatorsInternal(ic.Chain, ic.DAO)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -460,15 +460,15 @@ func (n *NEO) GetNextBlockValidatorsInternal(bc blockchainer.Blockchainer, d dao
|
|||
return pubs, nil
|
||||
}
|
||||
|
||||
func pubsToArray(pubs keys.PublicKeys) vm.StackItem {
|
||||
arr := make([]vm.StackItem, len(pubs))
|
||||
func pubsToArray(pubs keys.PublicKeys) stackitem.Item {
|
||||
arr := make([]stackitem.Item, len(pubs))
|
||||
for i := range pubs {
|
||||
arr[i] = vm.NewByteArrayItem(pubs[i].Bytes())
|
||||
arr[i] = stackitem.NewByteArray(pubs[i].Bytes())
|
||||
}
|
||||
return vm.NewArrayItem(arr)
|
||||
return stackitem.NewArray(arr)
|
||||
}
|
||||
|
||||
func toPublicKey(s vm.StackItem) *keys.PublicKey {
|
||||
func toPublicKey(s stackitem.Item) *keys.PublicKey {
|
||||
buf, err := s.TryBytes()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -7,11 +7,11 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/core/interop"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
|
||||
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
// prefixAccount is the standard prefix used to store account data.
|
||||
|
@ -86,20 +86,20 @@ func (c *nep5TokenNative) Initialize(_ *interop.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) Name(_ *interop.Context, _ []vm.StackItem) vm.StackItem {
|
||||
return vm.NewByteArrayItem([]byte(c.name))
|
||||
func (c *nep5TokenNative) Name(_ *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
return stackitem.NewByteArray([]byte(c.name))
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) Symbol(_ *interop.Context, _ []vm.StackItem) vm.StackItem {
|
||||
return vm.NewByteArrayItem([]byte(c.symbol))
|
||||
func (c *nep5TokenNative) Symbol(_ *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
return stackitem.NewByteArray([]byte(c.symbol))
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) Decimals(_ *interop.Context, _ []vm.StackItem) vm.StackItem {
|
||||
return vm.NewBigIntegerItem(big.NewInt(c.decimals))
|
||||
func (c *nep5TokenNative) Decimals(_ *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
return stackitem.NewBigInteger(big.NewInt(c.decimals))
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) TotalSupply(ic *interop.Context, _ []vm.StackItem) vm.StackItem {
|
||||
return vm.NewBigIntegerItem(c.getTotalSupply(ic))
|
||||
func (c *nep5TokenNative) TotalSupply(ic *interop.Context, _ []stackitem.Item) stackitem.Item {
|
||||
return stackitem.NewBigInteger(c.getTotalSupply(ic))
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) getTotalSupply(ic *interop.Context) *big.Int {
|
||||
|
@ -107,37 +107,37 @@ func (c *nep5TokenNative) getTotalSupply(ic *interop.Context) *big.Int {
|
|||
if si == nil {
|
||||
return big.NewInt(0)
|
||||
}
|
||||
return emit.BytesToInt(si.Value)
|
||||
return bigint.FromBytes(si.Value)
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) saveTotalSupply(ic *interop.Context, supply *big.Int) error {
|
||||
si := &state.StorageItem{Value: emit.IntToBytes(supply)}
|
||||
si := &state.StorageItem{Value: bigint.ToBytes(supply)}
|
||||
return ic.DAO.PutStorageItem(c.Hash, totalSupplyKey, si)
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) Transfer(ic *interop.Context, args []vm.StackItem) vm.StackItem {
|
||||
func (c *nep5TokenNative) Transfer(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
from := toUint160(args[0])
|
||||
to := toUint160(args[1])
|
||||
amount := toBigInt(args[2])
|
||||
err := c.transfer(ic, from, to, amount)
|
||||
return vm.NewBoolItem(err == nil)
|
||||
return stackitem.NewBool(err == nil)
|
||||
}
|
||||
|
||||
func addrToStackItem(u *util.Uint160) vm.StackItem {
|
||||
func addrToStackItem(u *util.Uint160) stackitem.Item {
|
||||
if u == nil {
|
||||
return vm.NullItem{}
|
||||
return stackitem.Null{}
|
||||
}
|
||||
return vm.NewByteArrayItem(u.BytesBE())
|
||||
return stackitem.NewByteArray(u.BytesBE())
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) emitTransfer(ic *interop.Context, from, to *util.Uint160, amount *big.Int) {
|
||||
ne := state.NotificationEvent{
|
||||
ScriptHash: c.Hash,
|
||||
Item: vm.NewArrayItem([]vm.StackItem{
|
||||
vm.NewByteArrayItem([]byte("Transfer")),
|
||||
Item: stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte("Transfer")),
|
||||
addrToStackItem(from),
|
||||
addrToStackItem(to),
|
||||
vm.NewBigIntegerItem(amount),
|
||||
stackitem.NewBigInteger(amount),
|
||||
}),
|
||||
}
|
||||
ic.Notifications = append(ic.Notifications, ne)
|
||||
|
@ -197,14 +197,14 @@ func (c *nep5TokenNative) transfer(ic *interop.Context, from, to util.Uint160, a
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) balanceOf(ic *interop.Context, args []vm.StackItem) vm.StackItem {
|
||||
func (c *nep5TokenNative) balanceOf(ic *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
h := toUint160(args[0])
|
||||
bs, err := ic.DAO.GetNEP5Balances(h)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
balance := bs.Trackers[c.Hash].Balance
|
||||
return vm.NewBigIntegerItem(big.NewInt(balance))
|
||||
return stackitem.NewBigInteger(big.NewInt(balance))
|
||||
}
|
||||
|
||||
func (c *nep5TokenNative) mint(ic *interop.Context, h util.Uint160, amount *big.Int) {
|
||||
|
@ -269,7 +269,7 @@ func newMethodAndPrice(f interop.Method, price int64, flags smartcontract.CallFl
|
|||
}
|
||||
}
|
||||
|
||||
func toBigInt(s vm.StackItem) *big.Int {
|
||||
func toBigInt(s stackitem.Item) *big.Int {
|
||||
bi, err := s.TryInteger()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -277,7 +277,7 @@ func toBigInt(s vm.StackItem) *big.Int {
|
|||
return bi
|
||||
}
|
||||
|
||||
func toUint160(s vm.StackItem) util.Uint160 {
|
||||
func toUint160(s stackitem.Item) util.Uint160 {
|
||||
buf, err := s.TryBytes()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package native
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/encoding/bigint"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
)
|
||||
|
||||
// MaxValidatorsVoted limits the number of validators that one can vote for.
|
||||
|
@ -41,19 +42,25 @@ func (vc *ValidatorsCount) Bytes() []byte {
|
|||
|
||||
// EncodeBinary implements io.Serializable interface.
|
||||
func (vc *ValidatorsCount) EncodeBinary(w *io.BinWriter) {
|
||||
w.WriteVarUint(uint64(MaxValidatorsVoted))
|
||||
for i := range vc {
|
||||
w.WriteVarBytes(emit.IntToBytes(&vc[i]))
|
||||
w.WriteVarBytes(bigint.ToBytes(&vc[i]))
|
||||
}
|
||||
}
|
||||
|
||||
// DecodeBinary implements io.Serializable interface.
|
||||
func (vc *ValidatorsCount) DecodeBinary(r *io.BinReader) {
|
||||
for i := range vc {
|
||||
count := r.ReadVarUint()
|
||||
if count < 0 || count > MaxValidatorsVoted {
|
||||
r.Err = errors.New("invalid validators count")
|
||||
return
|
||||
}
|
||||
for i := 0; i < int(count); i++ {
|
||||
buf := r.ReadVarBytes()
|
||||
if r.Err != nil {
|
||||
return
|
||||
}
|
||||
vc[i] = *emit.BytesToInt(buf)
|
||||
vc[i] = *bigint.FromBytes(buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -67,7 +67,7 @@ func newTestNative() *testNative {
|
|||
return tn
|
||||
}
|
||||
|
||||
func (tn *testNative) sum(_ *interop.Context, args []vm.StackItem) vm.StackItem {
|
||||
func (tn *testNative) sum(_ *interop.Context, args []stackitem.Item) stackitem.Item {
|
||||
s1, err := args[0].TryInteger()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
|
@ -76,7 +76,7 @@ func (tn *testNative) sum(_ *interop.Context, args []vm.StackItem) vm.StackItem
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return vm.NewBigIntegerItem(s1.Add(s1, s2))
|
||||
return stackitem.NewBigInteger(s1.Add(s1, s2))
|
||||
}
|
||||
|
||||
func TestNativeContract_Invoke(t *testing.T) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
// NEP5BalanceState represents balance state of a NEP5-token.
|
||||
|
@ -44,18 +44,27 @@ func (s *NEP5BalanceState) Bytes() []byte {
|
|||
return w.Bytes()
|
||||
}
|
||||
|
||||
func (s *NEP5BalanceState) toStackItem() stackitem.Item {
|
||||
return stackitem.NewStruct([]stackitem.Item{stackitem.NewBigInteger(&s.Balance)})
|
||||
}
|
||||
|
||||
func (s *NEP5BalanceState) fromStackItem(item stackitem.Item) {
|
||||
s.Balance = *item.(*stackitem.Struct).Value().([]stackitem.Item)[0].Value().(*big.Int)
|
||||
}
|
||||
|
||||
// EncodeBinary implements io.Serializable interface.
|
||||
func (s *NEP5BalanceState) EncodeBinary(w *io.BinWriter) {
|
||||
w.WriteVarBytes(emit.IntToBytes(&s.Balance))
|
||||
si := s.toStackItem()
|
||||
stackitem.EncodeBinaryStackItem(si, w)
|
||||
}
|
||||
|
||||
// DecodeBinary implements io.Serializable interface.
|
||||
func (s *NEP5BalanceState) DecodeBinary(r *io.BinReader) {
|
||||
buf := r.ReadVarBytes()
|
||||
si := stackitem.DecodeBinaryStackItem(r)
|
||||
if r.Err != nil {
|
||||
return
|
||||
}
|
||||
s.Balance = *emit.BytesToInt(buf)
|
||||
s.fromStackItem(si)
|
||||
}
|
||||
|
||||
// NEOBalanceStateFromBytes converts serialized NEOBalanceState to structure.
|
||||
|
@ -85,14 +94,37 @@ func (s *NEOBalanceState) Bytes() []byte {
|
|||
|
||||
// EncodeBinary implements io.Serializable interface.
|
||||
func (s *NEOBalanceState) EncodeBinary(w *io.BinWriter) {
|
||||
s.NEP5BalanceState.EncodeBinary(w)
|
||||
w.WriteU32LE(s.BalanceHeight)
|
||||
w.WriteArray(s.Votes)
|
||||
si := s.toStackItem()
|
||||
stackitem.EncodeBinaryStackItem(si, w)
|
||||
}
|
||||
|
||||
// DecodeBinary implements io.Serializable interface.
|
||||
func (s *NEOBalanceState) DecodeBinary(r *io.BinReader) {
|
||||
s.NEP5BalanceState.DecodeBinary(r)
|
||||
s.BalanceHeight = r.ReadU32LE()
|
||||
r.ReadArray(&s.Votes)
|
||||
si := stackitem.DecodeBinaryStackItem(r)
|
||||
if r.Err != nil {
|
||||
return
|
||||
}
|
||||
s.fromStackItem(si)
|
||||
}
|
||||
|
||||
func (s *NEOBalanceState) toStackItem() stackitem.Item {
|
||||
result := s.NEP5BalanceState.toStackItem().(*stackitem.Struct)
|
||||
result.Append(stackitem.NewBigInteger(big.NewInt(int64(s.BalanceHeight))))
|
||||
votes := make([]stackitem.Item, len(s.Votes))
|
||||
for i, v := range s.Votes {
|
||||
votes[i] = stackitem.NewByteArray(v.Bytes())
|
||||
}
|
||||
result.Append(stackitem.NewArray(votes))
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *NEOBalanceState) fromStackItem(item stackitem.Item) {
|
||||
structItem := item.Value().([]stackitem.Item)
|
||||
s.Balance = *structItem[0].Value().(*big.Int)
|
||||
s.BalanceHeight = uint32(structItem[1].Value().(*big.Int).Int64())
|
||||
votes := structItem[2].Value().([]stackitem.Item)
|
||||
s.Votes = make([]*keys.PublicKey, len(votes))
|
||||
for i, v := range votes {
|
||||
s.Votes[i].DecodeBytes(v.Value().([]byte))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
// NotificationEvent is a tuple of scripthash that emitted the StackItem as a
|
||||
// NotificationEvent is a tuple of scripthash that emitted the Item as a
|
||||
// notification and that item itself.
|
||||
type NotificationEvent struct {
|
||||
ScriptHash util.Uint160
|
||||
Item vm.StackItem
|
||||
Item stackitem.Item
|
||||
}
|
||||
|
||||
// AppExecResult represent the result of the script execution, gathering together
|
||||
|
@ -29,13 +29,13 @@ type AppExecResult struct {
|
|||
// EncodeBinary implements the Serializable interface.
|
||||
func (ne *NotificationEvent) EncodeBinary(w *io.BinWriter) {
|
||||
ne.ScriptHash.EncodeBinary(w)
|
||||
vm.EncodeBinaryStackItem(ne.Item, w)
|
||||
stackitem.EncodeBinaryStackItem(ne.Item, w)
|
||||
}
|
||||
|
||||
// DecodeBinary implements the Serializable interface.
|
||||
func (ne *NotificationEvent) DecodeBinary(r *io.BinReader) {
|
||||
ne.ScriptHash.DecodeBinary(r)
|
||||
ne.Item = vm.DecodeBinaryStackItem(r)
|
||||
ne.Item = stackitem.DecodeBinaryStackItem(r)
|
||||
}
|
||||
|
||||
// EncodeBinary implements the Serializable interface.
|
||||
|
|
|
@ -6,13 +6,13 @@ import (
|
|||
"github.com/nspcc-dev/neo-go/pkg/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/pkg/internal/testserdes"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
func TestEncodeDecodeNotificationEvent(t *testing.T) {
|
||||
event := &NotificationEvent{
|
||||
ScriptHash: random.Uint160(),
|
||||
Item: vm.NewBoolItem(true),
|
||||
Item: stackitem.NewBool(true),
|
||||
}
|
||||
|
||||
testserdes.EncodeDecodeBinary(t, event, new(NotificationEvent))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue