Merge pull request #938 from nspcc-dev/fix/appcall

vm: remove APPCALL, TAILCALL
This commit is contained in:
Roman Khimov 2020-05-08 13:11:02 +03:00 committed by GitHub
commit b83ee77698
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
36 changed files with 297 additions and 376 deletions

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4",
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4",
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",
@ -44,11 +44,11 @@
"isDefault": false
},
{
"address": "ANg3mmstMr7qtY8TgdKM777WSLKCNFbawM",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "AUhsL7QeeomkuzxZexPTa11xNXrbsBrGVc",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "110c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2110b683073b3bb",
"script": "110c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc2110b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "Aaidx8VxYVjpD6knF8toWG7WquQjQFWcZB",
"key": "6PYMZM16cgdQ9GH5ejEPFqehuZ3Lp16W4fW7LyoBdUuVyeMeom7z8wP5QV",
"address": "AJjSSuKdC88zWvXnZQbEfL21cm74pGJhsF",
"key": "6PYLZTVkK3RoPU8PSAUPHfnu4Py2JcJfeT92FS77DDakRRLcrNu2uCY46Q",
"label": "",
"contract": {
"script": "0c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0b680a906ad4",
"script": "0c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYMZM16cgdQ9GH5ejEPFqehuZ3Lp16W4fW7LyoBdUuVyeMeom7z8wP5QV",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYLZTVkK3RoPU8PSAUPHfnu4Py2JcJfeT92FS77DDakRRLcrNu2uCY46Q",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "Ae6y4Jx6rjwGu6Vtf6y1piTN3dnhCs6Gp4",
"key": "6PYSeHjvJFBn4FVccKHtaq2Hrvqa3aj9EDq5XSnWszvagRyxRmmRijqV6r",
"address": "AbrcCqhFRvewc3Xg2FZMY4nFaNM78kiNGv",
"key": "6PYUdV8YSMWxmJ6rjaUHBp8GazLwLCB5J69yy2Afgpjovescorhc5zS4Zy",
"label": "",
"contract": {
"script": "0c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee6990b680a906ad4",
"script": "0c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee6990b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYSeHjvJFBn4FVccKHtaq2Hrvqa3aj9EDq5XSnWszvagRyxRmmRijqV6r",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYUdV8YSMWxmJ6rjaUHBp8GazLwLCB5J69yy2Afgpjovescorhc5zS4Zy",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "ANysJU18KPh6jBBcrGby9bPAHxFmAeL1q3",
"key": "6PYNWeXTgyP88XsqDLUdjnCNHypSD8wYLURE78226LU9gYNiSGL1grjFC9",
"address": "APw5jfiLG2VpvTzMhCKvfmWdGfWfTmNC7x",
"key": "6PYVsJVu8LVaAUHi5hEpWVpWpdy9bWRk1x3RSp7ijCVkCoqyk9NjZT9NhM",
"label": "",
"contract": {
"script": "0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620b680a906ad4",
"script": "0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYNWeXTgyP88XsqDLUdjnCNHypSD8wYLURE78226LU9gYNiSGL1grjFC9",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYVsJVu8LVaAUHi5hEpWVpWpdy9bWRk1x3RSp7ijCVkCoqyk9NjZT9NhM",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -1081,16 +1081,12 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
case "SHA256":
emit.Syscall(c.prog.BinWriter, "Neo.Crypto.SHA256")
case "AppCall":
numArgs := len(expr.Args) - 1
c.emitReverse(numArgs)
emit.Opcode(c.prog.BinWriter, opcode.APPCALL)
c.emitReverse(len(expr.Args))
buf := c.getByteArray(expr.Args[0])
if len(buf) != 20 {
c.prog.Err = errors.New("invalid script hash")
}
c.prog.WriteBytes(buf)
emit.Syscall(c.prog.BinWriter, "System.Contract.Call")
case "Equals":
emit.Opcode(c.prog.BinWriter, opcode.EQUAL)
case "FromAddress":
@ -1112,16 +1108,14 @@ func (c *codegen) convertBuiltin(expr *ast.CallExpr) {
// transformArgs returns a list of function arguments
// which should be put on stack.
// There are special cases for builtins:
// 1. When using AppCall, script hash is a part of the instruction so
// it should be emitted after APPCALL.
// 2. With FromAddress, parameter conversion is happening at compile-time
// 1. With FromAddress, parameter conversion is happening at compile-time
// so there is no need to push parameters on stack and perform an actual call
// 3. With panic, generated code depends on if argument was nil or a string so
// 2. With panic, generated code depends on if argument was nil or a string so
// it should be handled accordingly.
func transformArgs(fun ast.Expr, args []ast.Expr) []ast.Expr {
switch f := fun.(type) {
case *ast.SelectorExpr:
if f.Sel.Name == "AppCall" || f.Sel.Name == "FromAddress" {
if f.Sel.Name == "FromAddress" {
return args[1:]
}
case *ast.Ident:

View file

@ -6,10 +6,17 @@ import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/compiler"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/core/dao"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/storage"
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/vm"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
)
func TestFromAddress(t *testing.T) {
@ -51,6 +58,14 @@ func TestFromAddress(t *testing.T) {
})
}
func spawnVM(t *testing.T, ic *interop.Context, src string) *vm.VM {
b, err := compiler.Compile(strings.NewReader(src))
require.NoError(t, err)
v := core.SpawnVM(ic)
v.Load(b)
return v
}
func TestAppCall(t *testing.T) {
srcInner := `
package foo
@ -62,19 +77,13 @@ func TestAppCall(t *testing.T) {
inner, err := compiler.Compile(strings.NewReader(srcInner))
require.NoError(t, err)
ih := hash.Hash160(inner)
getScript := func(u util.Uint160) ([]byte, bool) {
if u.Equals(ih) {
return inner, true
}
return nil, false
}
ic := interop.NewContext(trigger.Application, nil, dao.NewSimple(storage.NewMemoryStore()), nil, nil, nil, zaptest.NewLogger(t))
require.NoError(t, ic.DAO.PutContractState(&state.Contract{Script: inner}))
ih := hash.Hash160(inner)
t.Run("valid script", func(t *testing.T) {
src := getAppCallScript(fmt.Sprintf("%#v", ih.BytesBE()))
v := vmAndCompile(t, src)
v.SetScriptGetter(getScript)
v := spawnVM(t, ic, src)
require.NoError(t, v.Run())
assertResult(t, v, []byte{1, 2, 3, 4})
@ -85,9 +94,7 @@ func TestAppCall(t *testing.T) {
h[0] = ^h[0]
src := getAppCallScript(fmt.Sprintf("%#v", h.BytesBE()))
v := vmAndCompile(t, src)
v.SetScriptGetter(getScript)
v := spawnVM(t, ic, src)
require.Error(t, v.Run())
})
@ -111,9 +118,7 @@ func TestAppCall(t *testing.T) {
}
`
v := vmAndCompile(t, src)
v.SetScriptGetter(getScript)
v := spawnVM(t, ic, src)
require.NoError(t, v.Run())
assertResult(t, v, []byte{1, 2, 3, 4})

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4",
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "Aaidx8VxYVjpD6knF8toWG7WquQjQFWcZB",
"key": "6PYMZM16cgdQ9GH5ejEPFqehuZ3Lp16W4fW7LyoBdUuVyeMeom7z8wP5QV",
"address": "AJjSSuKdC88zWvXnZQbEfL21cm74pGJhsF",
"key": "6PYLZTVkK3RoPU8PSAUPHfnu4Py2JcJfeT92FS77DDakRRLcrNu2uCY46Q",
"label": "",
"contract": {
"script": "0c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0b680a906ad4",
"script": "0c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYMZM16cgdQ9GH5ejEPFqehuZ3Lp16W4fW7LyoBdUuVyeMeom7z8wP5QV",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYLZTVkK3RoPU8PSAUPHfnu4Py2JcJfeT92FS77DDakRRLcrNu2uCY46Q",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "Ae6y4Jx6rjwGu6Vtf6y1piTN3dnhCs6Gp4",
"key": "6PYSeHjvJFBn4FVccKHtaq2Hrvqa3aj9EDq5XSnWszvagRyxRmmRijqV6r",
"address": "AbrcCqhFRvewc3Xg2FZMY4nFaNM78kiNGv",
"key": "6PYUdV8YSMWxmJ6rjaUHBp8GazLwLCB5J69yy2Afgpjovescorhc5zS4Zy",
"label": "",
"contract": {
"script": "0c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee6990b680a906ad4",
"script": "0c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee6990b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYSeHjvJFBn4FVccKHtaq2Hrvqa3aj9EDq5XSnWszvagRyxRmmRijqV6r",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYUdV8YSMWxmJ6rjaUHBp8GazLwLCB5J69yy2Afgpjovescorhc5zS4Zy",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "ANysJU18KPh6jBBcrGby9bPAHxFmAeL1q3",
"key": "6PYNWeXTgyP88XsqDLUdjnCNHypSD8wYLURE78226LU9gYNiSGL1grjFC9",
"address": "APw5jfiLG2VpvTzMhCKvfmWdGfWfTmNC7x",
"key": "6PYVsJVu8LVaAUHi5hEpWVpWpdy9bWRk1x3RSp7ijCVkCoqyk9NjZT9NhM",
"label": "",
"contract": {
"script": "0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620b680a906ad4",
"script": "0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYNWeXTgyP88XsqDLUdjnCNHypSD8wYLURE78226LU9gYNiSGL1grjFC9",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYVsJVu8LVaAUHi5hEpWVpWpdy9bWRk1x3RSp7ijCVkCoqyk9NjZT9NhM",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -1616,7 +1616,7 @@ func ScriptFromWitness(hash util.Uint160, witness *transaction.Witness) ([]byte,
if len(verification) == 0 {
bb := io.NewBufBinWriter()
emit.AppCall(bb.BinWriter, hash, false)
emit.AppCall(bb.BinWriter, hash)
verification = bb.Bytes()
} else if h := witness.ScriptHash(); hash != h {
return nil, errors.New("witness hash mismatch")

View file

@ -20,8 +20,6 @@ func getPrice(v *vm.VM, op opcode.Opcode, parameter []byte) util.Fixed8 {
}
switch op {
case opcode.APPCALL, opcode.TAILCALL:
return toFixed8(10)
case opcode.SYSCALL:
interopID := vm.GetInteropID(parameter)
return getSyscallPrice(v, interopID)

View file

@ -84,6 +84,16 @@ type ContractMD struct {
Methods map[string]MethodAndPrice
}
// GetContract returns script of the contract with the specified hash.
func (ic *Context) GetContract(h util.Uint160) ([]byte, bool) {
cs, err := ic.DAO.GetContractState(h)
if err != nil {
return nil, false
}
hasDynamicInvoke := (cs.Properties & smartcontract.HasDynamicInvoke) != 0
return cs.Script, hasDynamicInvoke
}
// NewContractMD returns Contract with the specified list of methods.
func NewContractMD(name string) *ContractMD {
c := &ContractMD{

View file

@ -11,6 +11,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"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"
@ -470,6 +471,39 @@ func storageContextAsReadOnly(ic *interop.Context, v *vm.VM) error {
return nil
}
// contractCall calls a contract.
func contractCall(ic *interop.Context, v *vm.VM) error {
h := v.Estack().Pop().Bytes()
method := v.Estack().Pop().Item()
args := v.Estack().Pop().Item()
return contractCallExInternal(ic, v, h, method, args, smartcontract.All)
}
// contractCallEx calls a contract with flags.
func contractCallEx(ic *interop.Context, v *vm.VM) error {
h := v.Estack().Pop().Bytes()
method := v.Estack().Pop().Item()
args := v.Estack().Pop().Item()
flags := smartcontract.CallFlag(int32(v.Estack().Pop().BigInt().Int64()))
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 {
u, err := util.Uint160DecodeBytesBE(h)
if err != nil {
return errors.New("invalid contract hash")
}
script, _ := ic.GetContract(u)
if script == nil {
return errors.New("contract not found")
}
// TODO perform flags checking after #923
v.LoadScript(script)
v.Estack().PushVal(args)
v.Estack().PushVal(method)
return nil
}
// contractDestroy destroys a contract.
func contractDestroy(ic *interop.Context, v *vm.VM) error {
if ic.Trigger != trigger.Application {

View file

@ -16,8 +16,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/core/interop/iterator"
"github.com/nspcc-dev/neo-go/pkg/core/interop/runtime"
"github.com/nspcc-dev/neo-go/pkg/core/native"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"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"
)
@ -26,22 +24,11 @@ import (
// up for current blockchain.
func SpawnVM(ic *interop.Context) *vm.VM {
vm := vm.New()
bc := ic.Chain.(*Blockchain)
vm.SetScriptGetter(func(hash util.Uint160) ([]byte, bool) {
if c := bc.contracts.ByHash(hash); c != nil {
meta := c.Metadata()
return meta.Script, (meta.Manifest.Features&smartcontract.HasDynamicInvoke != 0)
}
cs, err := ic.DAO.GetContractState(hash)
if err != nil {
return nil, false
}
hasDynamicInvoke := (cs.Properties & smartcontract.HasDynamicInvoke) != 0
return cs.Script, hasDynamicInvoke
})
vm.RegisterInteropGetter(getSystemInterop(ic))
vm.RegisterInteropGetter(getNeoInterop(ic))
vm.RegisterInteropGetter(bc.contracts.GetNativeInterop(ic))
if ic.Chain != nil {
vm.RegisterInteropGetter(ic.Chain.(*Blockchain).contracts.GetNativeInterop(ic))
}
return vm
}
@ -84,6 +71,8 @@ var systemInterops = []interop.Function{
{Name: "System.Blockchain.GetHeight", Func: bcGetHeight, Price: 1},
{Name: "System.Blockchain.GetTransaction", Func: bcGetTransaction, Price: 200},
{Name: "System.Blockchain.GetTransactionHeight", Func: bcGetTransactionHeight, Price: 100},
{Name: "System.Contract.Call", Func: contractCall, Price: 1},
{Name: "System.Contract.CallEx", Func: contractCallEx, Price: 1},
{Name: "System.Contract.Destroy", Func: contractDestroy, Price: 1},
{Name: "System.Contract.GetStorageContext", Func: contractGetStorageContext, Price: 1},
{Name: "System.ExecutionEngine.GetCallingScriptHash", Func: engineGetCallingScriptHash, Price: 1},

View file

@ -5,6 +5,8 @@ import (
"fmt"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/vm"
)
@ -15,8 +17,23 @@ func Deploy(ic *interop.Context, _ *vm.VM) error {
}
for _, native := range ic.Natives {
if err := native.Initialize(ic); err != nil {
md := native.Metadata()
ps := md.Manifest.ABI.EntryPoint.Parameters
params := make([]smartcontract.ParamType, len(ps))
for i := range ps {
params[i] = ps[i].Type
}
cs := &state.Contract{
Script: md.Script,
ParamList: params,
ReturnType: md.Manifest.ABI.EntryPoint.ReturnType,
}
if err := ic.DAO.PutContractState(cs); err != nil {
return err
}
if err := native.Initialize(ic); err != nil {
return fmt.Errorf("initializing %s native contract: %v", md.ServiceName, err)
}
}

View file

@ -5,6 +5,7 @@ import (
"testing"
"github.com/nspcc-dev/neo-go/pkg/core/interop"
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -85,6 +86,9 @@ func TestNativeContract_Invoke(t *testing.T) {
tn := newTestNative()
chain.registerNative(tn)
err := chain.dao.PutContractState(&state.Contract{Script: tn.meta.Script})
require.NoError(t, err)
w := io.NewBufBinWriter()
emit.AppCallWithOperationAndArgs(w.BinWriter, tn.Metadata().Hash, "sum", int64(14), int64(28))
script := w.Bytes()

View file

@ -20,14 +20,14 @@ func TestGenesisBlockMainNet(t *testing.T) {
// have been changed. Consequently, hash of the genesis block has been changed.
// Update expected genesis block hash for better times.
// Old hash is "d42561e3d30e15be6400b6df2f328e02d2bf6354c41dce433bc57687c82144bf"
expect := "8eb36fe47f07a795a1783a9f066603db66c5b76cf878650b1e137c114f46c0cc"
expect := "56bb42c251ea2b216c5ee8306e94fe040613bc626a3813aa32fe07e7607b3a1a"
assert.Equal(t, expect, block.Hash().StringLE())
}
func TestGetConsensusAddressMainNet(t *testing.T) {
var (
consensusAddr = "APtiVEdLi5GEmQ8CL5RcCE7BNcsPsxeXh7"
consensusScript = "590c459950f1d83e67ee11fcef202a6ebb8b1a77"
consensusAddr = "ASEhJHr51ZMQUqmUbPC5uiuJwwvedwC48F"
consensusScript = "72c3d9b3bbf776698694cd2c73fa597a10c31294"
)
cfg, err := config.Load("../../config", config.ModeMainNet)

View file

@ -89,7 +89,7 @@ func TestPubkeyToAddress(t *testing.T) {
pubKey, err := NewPublicKeyFromString("031ee4e73a17d8f76dc02532e2620bcb12425b33c0c9f9694cc2caa8226b68cad4")
require.NoError(t, err)
actual := pubKey.Address()
expected := "AbjmXh5RXBMvzYcv7LCmUgrX4sWk1QBJMK"
expected := "AJhhwPRwjUmQhEmwPBrq4CVTMRq7u4S4in"
require.Equal(t, expected, actual)
}

View file

@ -14,28 +14,28 @@ type Ktype struct {
// Arr contains a set of known keys in Ktype format.
var Arr = []Ktype{
{
Address: "AZdm8Dt15QFTrYkMYRrZsTmpx4jbeLtPFj",
Address: "AHF4z1wiN9EabrS4eZK9JngmmRYxkfNbLA",
PrivateKey: "7d128a6d096f0c14c3a25a2b0c41cf79661bfcb4a8cc95aaaea28bde4d732344",
PublicKey: "02028a99826edc0c97d18e22b6932373d908d323aa7f92656a77ec26e8861699ef",
Wif: "L1QqQJnpBwbsPGAuutuzPTac8piqvbR1HRjrY5qHup48TBCBFe4g",
Passphrase: "city of zion",
EncryptedWif: "6PYRQrhDFP6hM7Pb4cqJ7T1Erh1XabLDEs42fENU4Htvsdgt6SmShDbCLR",
EncryptedWif: "6PYV843ZXHHRKhHbTTKqBxGXbYm8ZvpcZdmcMasZe2n8scuPBBkmdDZk1J",
},
{
Address: "AHPNXvNiGGx43DBTEs9j1z9CjYSSC11jpe",
Address: "AM41GdiGK6eFJ7PZhd6yxsvFVWnsh9xUfg",
PrivateKey: "9ab7e154840daca3a2efadaf0df93cd3a5b51768c632f5433f86909d9b994a69",
PublicKey: "031d8e1630ce640966967bc6d95223d21f44304133003140c3b52004dc981349c9",
Wif: "L2QTooFoDFyRFTxmtiVHt5CfsXfVnexdbENGDkkrrgTTryiLsPMG",
Passphrase: "我的密码",
EncryptedWif: "6PYKuvXj1Yq9ZjsVNVyNrAHVHrAqg6BLxUoTdpZX5NFkG5Akq79dPYYm7c",
EncryptedWif: "6PYWUjTHVYg1iYVAR5B3E6BqbrcsYPVnHzpdHcjSE1emEYN9vqCGHtBBcx",
},
{
Address: "AGo5guykksq8uRxfWyC8dAnTMoz62yUWcn",
Address: "AP75QGPdWJceuMCVBiz1GN9Tj3XeU2uerB",
PrivateKey: "3edee7036b8fd9cef91de47386b191dd76db2888a553e7736bb02808932a915b",
PublicKey: "02232ce8d2e2063dce0451131851d47421bfc4fc1da4db116fca5302c0756462fa",
Wif: "KyKvWLZsNwBJx5j9nurHYRwhYfdQUu9tTEDsLCUHDbYBL8cHxMiG",
Passphrase: "MyL33tP@33w0rd",
EncryptedWif: "6PYQUTBmYbWZukmBTuvTkbjSmz7m5XkEzsyJBk32ZhvC7AbVUpArb1yeMv",
EncryptedWif: "6PYKssa8ZJE6LKvZ7TYomhwSs8jSvDuiPFcBwDVyeyYbgaXxRwtvKjYTe7",
},
{
Address: "xdf4UGKevVrMR1j3UkPsuoYKSC4ocoAkKx",
@ -43,7 +43,7 @@ var Arr = []Ktype{
PublicKey: "zz232ce8d2e2063dce0451131851d47421bfc4fc1da4db116fca5302c0756462fa",
Wif: "zzKvWLZsNwBJx5j9nurHYRwhYfdQUu9tTEDsLCUHDbYBL8cHxMiG",
Passphrase: "zzL33tP@33w0rd",
EncryptedWif: "6PYQUTBmYbWZukmBTuvTkbjSmz7m5XkEzsyJBk32ZhvC7AbVUpArb1yeMv",
EncryptedWif: "6PYKssa8ZJE6LKvZ7TYomhwSs8jSvDuiPFcBwDVyeyYbgaXxRwtvKjYTe7",
Invalid: true,
},
}

View file

@ -210,7 +210,7 @@ func CreateFunctionInvocationScript(contract util.Uint160, params Params) ([]byt
}
}
emit.AppCall(script.BinWriter, contract, false)
emit.AppCall(script.BinWriter, contract)
return script.Bytes(), nil
}
@ -224,6 +224,6 @@ func CreateInvocationScript(contract util.Uint160, funcParams []Param) ([]byte,
if err != nil {
return nil, err
}
emit.AppCall(script.BinWriter, contract, false)
emit.AppCall(script.BinWriter, contract)
return script.Bytes(), nil
}

View file

@ -19,43 +19,43 @@ func TestInvocationScriptCreationGood(t *testing.T) {
ps Params
script string
}{{
script: "676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "transfer"}},
script: "0c087472616e73666572676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c087472616e736665720c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: NumberT, Value: 42}},
script: "0c023432676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c0234320c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{}}},
script: "10c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "10c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.ByteArrayType, Value: Param{Type: StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
script: "0c1450befd26fdf6e4d957c11e078b24ebce6291456f11c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c1450befd26fdf6e4d957c11e078b24ebce6291456f11c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.SignatureType, Value: Param{Type: StringT, Value: "4edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f"}}}}}},
script: "0c404edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f11c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c404edf5005771de04619235d5a4c7a9a11bb78e008541f1da7725f654c33380a3c87e2959a025da706d7255cb3a3fa07ebe9c6559d0d9e6213c68049168eb1056f11c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.StringType, Value: Param{Type: StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
script: "0c283530626566643236666466366534643935376331316530373862323465626365363239313435366611c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c283530626566643236666466366534643935376331316530373862323465626365363239313435366611c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.Hash160Type, Value: Param{Type: StringT, Value: "50befd26fdf6e4d957c11e078b24ebce6291456f"}}}}}},
script: "0c146f459162ceeb248b071ec157d9e4f6fd26fdbe5011c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c146f459162ceeb248b071ec157d9e4f6fd26fdbe5011c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.Hash256Type, Value: Param{Type: StringT, Value: "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7"}}}}}},
script: "0c20e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6011c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c20e72d286979ee6cb1b7e65dfddfb2e384100b8d148e7758de42e4168b71792c6011c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.PublicKeyType, Value: Param{Type: StringT, Value: "03c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c1"}}}}}},
script: "0c2103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c111c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "0c2103c089d7122b840a4935234e82e26ae5efd0c2acb627239dc9f207311337b6f2c111c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.IntegerType, Value: Param{Type: NumberT, Value: 42}}}}}},
script: "002a11c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "002a11c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.BoolType, Value: Param{Type: StringT, Value: "true"}}}}}},
script: "1111c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "1111c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}, {
ps: Params{{Type: StringT, Value: "a"}, {Type: ArrayT, Value: []Param{{Type: FuncParamT, Value: FuncParam{Type: smartcontract.BoolType, Value: Param{Type: StringT, Value: "false"}}}}}},
script: "1011c00c0161676f459162ceeb248b071ec157d9e4f6fd26fdbe50",
script: "1011c00c01610c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52",
}}
for _, ps := range paramScripts {
script, err := CreateFunctionInvocationScript(contract, ps.ps)

View file

@ -48,18 +48,18 @@ type rpcTestCase struct {
check func(t *testing.T, e *executor, result interface{})
}
const testContractHash = "2077e1382aab3983aa342e68f7bbc94e69f204b9"
const testContractHash = "a4bea0d56fad00a972135d54b381516205d78484"
var rpcTestCases = map[string][]rpcTestCase{
"getapplicationlog": {
{
name: "positive",
params: `["16c26d67f06770a5b0cda4b1c5ccc28d12c0197c7239a7fe30c2eb523b58f54d"]`,
params: `["c296c0929350d051b9b40cace54db5a3eac4b730a8851e958795d44918f23c08"]`,
result: func(e *executor) interface{} { return &result.ApplicationLog{} },
check: func(t *testing.T, e *executor, acc interface{}) {
res, ok := acc.(*result.ApplicationLog)
require.True(t, ok)
expectedTxHash, err := util.Uint256DecodeStringLE("16c26d67f06770a5b0cda4b1c5ccc28d12c0197c7239a7fe30c2eb523b58f54d")
expectedTxHash, err := util.Uint256DecodeStringLE("c296c0929350d051b9b40cace54db5a3eac4b730a8851e958795d44918f23c08")
require.NoError(t, err)
assert.Equal(t, expectedTxHash, res.TxHash)
assert.Equal(t, 1, len(res.Executions))
@ -473,7 +473,7 @@ var rpcTestCases = map[string][]rpcTestCase{
params: `["` + testchain.MultisigAddress() + `"]`,
result: func(*executor) interface{} {
// hash of the issueTx
h, _ := util.Uint256DecodeStringBE("99bd2bb2791887ddd3f64dac70ac15339956c76e7c306a1202372ff24fe30635")
h, _ := util.Uint256DecodeStringBE("3b76c9b726ffa9074a69441bf946c4c70b83474b3cf522ea3ba9dcd71c1a3db8")
amount := util.Fixed8FromInt64(1 * 8) // (endHeight - startHeight) * genAmount[0]
return &result.ClaimableInfo{
Spents: []result.Claimable{
@ -532,7 +532,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"gettransactionheight": {
{
name: "positive",
params: `["1f08a32642a43e3f06b3b9a9355ed274c52de85a886841a2aef7edd94d1dc3f6"]`,
params: `["a05ea6d90b761ec5430f29d25036fdad04efe731b6a5906f4fd1e19048dee0f2"]`,
result: func(e *executor) interface{} {
h := 1
return &h
@ -647,7 +647,7 @@ var rpcTestCases = map[string][]rpcTestCase{
check: func(t *testing.T, e *executor, inv interface{}) {
res, ok := inv.(*result.Invoke)
require.True(t, ok)
assert.Equal(t, "0c06717765727479676f459162ceeb248b071ec157d9e4f6fd26fdbe50", res.Script)
assert.Equal(t, "0c067177657274790c146f459162ceeb248b071ec157d9e4f6fd26fdbe5041627d5b52", res.Script)
assert.NotEqual(t, "", res.State)
assert.NotEqual(t, 0, res.GasConsumed)
},
@ -744,7 +744,7 @@ var rpcTestCases = map[string][]rpcTestCase{
"sendrawtransaction": {
{
name: "positive",
params: `["80000b00000075a94799633ed955dd85a8af314a5b435ab51903b0040000000001e53e6c239e3d8441f623ea7b48cdea60c6ae0426a8bac04296002babfeafe5a4010001dcb7e70846bb5a6828205b81b579562f0e2c15f7b3badd68d485b035882fc17d0030d3dec386230075a94799633ed955dd85a8af314a5b435ab5190301420c408378eb6bdba1f14540cf2920a4d49c52327f617dc861a21d1c085346aaae2abd410e28dc6a03471a78e71246696a591b9677a71144dfba557d1c781c8c97e350290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4"]`,
params: `["80000b000000316e851039019d39dfc2c37d6c3fee19fd580987b0040000000001241a237db30af3b33d29518288e0c9b542475733f78f4c6d7416cba89c1f1a67010001dcb7e70846bb5a6828205b81b579562f0e2c15f7b3badd68d485b035882fc17d0030d3dec3862300316e851039019d39dfc2c37d6c3fee19fd58098701420c40c3c3fedb73e36a8e78bae80ba07c20b34f5af6bba36dccbe0cdc7d4e1237f85eec36e63cb762e1e6ce031a6c752e1ce19a3994d15191a6b75f1a02ede7f9d117290c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4"]`,
result: func(e *executor) interface{} {
v := true
return &v

Binary file not shown.

Binary file not shown.

View file

@ -113,8 +113,6 @@ func (c *Context) Next() (opcode.Opcode, []byte, error) {
opcode.JMPGTL, opcode.JMPGEL, opcode.JMPLTL, opcode.JMPLEL,
opcode.CALLL, opcode.SYSCALL:
numtoread = 4
case opcode.APPCALL, opcode.TAILCALL:
numtoread = 20
default:
if instr <= opcode.PUSHINT256 {
numtoread = 1 << instr

View file

@ -141,35 +141,31 @@ func Jmp(w *io.BinWriter, op opcode.Opcode, label uint16) {
Instruction(w, op, buf)
}
// AppCall emits an appcall, if tailCall is true, tailCall opcode will be
// emitted instead.
func AppCall(w *io.BinWriter, scriptHash util.Uint160, tailCall bool) {
op := opcode.APPCALL
if tailCall {
op = opcode.TAILCALL
}
Instruction(w, op, scriptHash.BytesBE())
// AppCall emits call to provided contract.
func AppCall(w *io.BinWriter, scriptHash util.Uint160) {
Bytes(w, scriptHash.BytesBE())
Syscall(w, "System.Contract.Call")
}
// AppCallWithOperationAndArgs emits an APPCALL with the given operation and arguments.
func AppCallWithOperationAndArgs(w *io.BinWriter, scriptHash util.Uint160, operation string, args ...interface{}) {
Array(w, args...)
String(w, operation)
AppCall(w, scriptHash, false)
AppCall(w, scriptHash)
}
// AppCallWithOperationAndData emits an appcall with the given operation and data.
func AppCallWithOperationAndData(w *io.BinWriter, scriptHash util.Uint160, operation string, data []byte) {
Bytes(w, data)
String(w, operation)
AppCall(w, scriptHash, false)
AppCall(w, scriptHash)
}
// AppCallWithOperation emits an appcall with the given operation.
func AppCallWithOperation(w *io.BinWriter, scriptHash util.Uint160, operation string) {
Bool(w, false)
String(w, operation)
AppCall(w, scriptHash, false)
AppCall(w, scriptHash)
}
func isInstructionJmp(op opcode.Opcode) bool {

View file

@ -70,6 +70,9 @@ const (
ASSERT Opcode = 0x38
THROW Opcode = 0x3A
RET Opcode = 0x40
SYSCALL Opcode = 0x41
// Stack
DEPTH Opcode = 0x43
DROP Opcode = 0x45
@ -88,11 +91,6 @@ const (
REVERSE4 Opcode = 0x54
REVERSEN Opcode = 0x55
RET Opcode = 0x66
APPCALL Opcode = 0x67
SYSCALL Opcode = 0x68
TAILCALL Opcode = 0x69
// Old stack opcodes
DUPFROMALTSTACK Opcode = 0x6A
TOALTSTACK Opcode = 0x6B

View file

@ -62,6 +62,8 @@ func _() {
_ = x[ABORT-55]
_ = x[ASSERT-56]
_ = x[THROW-58]
_ = x[RET-64]
_ = x[SYSCALL-65]
_ = x[DEPTH-67]
_ = x[DROP-69]
_ = x[NIP-70]
@ -78,10 +80,6 @@ func _() {
_ = x[REVERSE3-83]
_ = x[REVERSE4-84]
_ = x[REVERSEN-85]
_ = x[RET-102]
_ = x[APPCALL-103]
_ = x[SYSCALL-104]
_ = x[TAILCALL-105]
_ = x[DUPFROMALTSTACK-106]
_ = x[TOALTSTACK-107]
_ = x[FROMALTSTACK-108]
@ -143,7 +141,7 @@ func _() {
_ = x[CONVERT-219]
}
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLABORTASSERTTHROWDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENRETAPPCALLSYSCALLTAILCALLDUPFROMALTSTACKTOALTSTACKFROMALTSTACKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT"
const _Opcode_name = "PUSHINT8PUSHINT16PUSHINT32PUSHINT64PUSHINT128PUSHINT256PUSHNULLPUSHDATA1PUSHDATA2PUSHDATA4PUSHM1PUSH0PUSH1PUSH2PUSH3PUSH4PUSH5PUSH6PUSH7PUSH8PUSH9PUSH10PUSH11PUSH12PUSH13PUSH14PUSH15PUSH16NOPJMPJMPLJMPIFJMPIFLJMPIFNOTJMPIFNOTLJMPEQJMPEQLJMPNEJMPNELJMPGTJMPGTLJMPGEJMPGELJMPLTJMPLTLJMPLEJMPLELCALLCALLLABORTASSERTTHROWRETSYSCALLDEPTHDROPNIPXDROPCLEARDUPOVERPICKTUCKSWAPOLDPUSH1ROLLREVERSE3REVERSE4REVERSENDUPFROMALTSTACKTOALTSTACKFROMALTSTACKCATSUBSTRLEFTRIGHTINVERTANDORXOREQUALNOTEQUALSIGNABSNEGATEINCDECADDSUBMULDIVMODSHLSHRNOTBOOLANDBOOLORNZNUMEQUALNUMNOTEQUALLTLTEGTGTEMINMAXWITHINPACKUNPACKNEWARRAY0NEWARRAYNEWARRAYTNEWSTRUCT0NEWSTRUCTNEWMAPSIZEHASKEYKEYSVALUESPICKITEMAPPENDSETITEMREVERSEITEMSREMOVECLEARITEMSISNULLISTYPECONVERT"
var _Opcode_map = map[Opcode]string{
0: _Opcode_name[0:8],
@ -198,84 +196,82 @@ var _Opcode_map = map[Opcode]string{
55: _Opcode_name[301:306],
56: _Opcode_name[306:312],
58: _Opcode_name[312:317],
67: _Opcode_name[317:322],
69: _Opcode_name[322:326],
70: _Opcode_name[326:329],
72: _Opcode_name[329:334],
73: _Opcode_name[334:339],
74: _Opcode_name[339:342],
75: _Opcode_name[342:346],
77: _Opcode_name[346:350],
78: _Opcode_name[350:354],
80: _Opcode_name[354:358],
81: _Opcode_name[358:366],
82: _Opcode_name[366:370],
83: _Opcode_name[370:378],
84: _Opcode_name[378:386],
85: _Opcode_name[386:394],
102: _Opcode_name[394:397],
103: _Opcode_name[397:404],
104: _Opcode_name[404:411],
105: _Opcode_name[411:419],
106: _Opcode_name[419:434],
107: _Opcode_name[434:444],
108: _Opcode_name[444:456],
126: _Opcode_name[456:459],
127: _Opcode_name[459:465],
128: _Opcode_name[465:469],
129: _Opcode_name[469:474],
144: _Opcode_name[474:480],
145: _Opcode_name[480:483],
146: _Opcode_name[483:485],
147: _Opcode_name[485:488],
151: _Opcode_name[488:493],
152: _Opcode_name[493:501],
153: _Opcode_name[501:505],
154: _Opcode_name[505:508],
155: _Opcode_name[508:514],
156: _Opcode_name[514:517],
157: _Opcode_name[517:520],
158: _Opcode_name[520:523],
159: _Opcode_name[523:526],
160: _Opcode_name[526:529],
161: _Opcode_name[529:532],
162: _Opcode_name[532:535],
168: _Opcode_name[535:538],
169: _Opcode_name[538:541],
170: _Opcode_name[541:544],
171: _Opcode_name[544:551],
172: _Opcode_name[551:557],
177: _Opcode_name[557:559],
179: _Opcode_name[559:567],
180: _Opcode_name[567:578],
181: _Opcode_name[578:580],
182: _Opcode_name[580:583],
183: _Opcode_name[583:585],
184: _Opcode_name[585:588],
185: _Opcode_name[588:591],
186: _Opcode_name[591:594],
187: _Opcode_name[594:600],
192: _Opcode_name[600:604],
193: _Opcode_name[604:610],
194: _Opcode_name[610:619],
195: _Opcode_name[619:627],
196: _Opcode_name[627:636],
197: _Opcode_name[636:646],
198: _Opcode_name[646:655],
200: _Opcode_name[655:661],
202: _Opcode_name[661:665],
203: _Opcode_name[665:671],
204: _Opcode_name[671:675],
205: _Opcode_name[675:681],
206: _Opcode_name[681:689],
207: _Opcode_name[689:695],
208: _Opcode_name[695:702],
209: _Opcode_name[702:714],
210: _Opcode_name[714:720],
211: _Opcode_name[720:730],
216: _Opcode_name[730:736],
217: _Opcode_name[736:742],
219: _Opcode_name[742:749],
64: _Opcode_name[317:320],
65: _Opcode_name[320:327],
67: _Opcode_name[327:332],
69: _Opcode_name[332:336],
70: _Opcode_name[336:339],
72: _Opcode_name[339:344],
73: _Opcode_name[344:349],
74: _Opcode_name[349:352],
75: _Opcode_name[352:356],
77: _Opcode_name[356:360],
78: _Opcode_name[360:364],
80: _Opcode_name[364:368],
81: _Opcode_name[368:376],
82: _Opcode_name[376:380],
83: _Opcode_name[380:388],
84: _Opcode_name[388:396],
85: _Opcode_name[396:404],
106: _Opcode_name[404:419],
107: _Opcode_name[419:429],
108: _Opcode_name[429:441],
126: _Opcode_name[441:444],
127: _Opcode_name[444:450],
128: _Opcode_name[450:454],
129: _Opcode_name[454:459],
144: _Opcode_name[459:465],
145: _Opcode_name[465:468],
146: _Opcode_name[468:470],
147: _Opcode_name[470:473],
151: _Opcode_name[473:478],
152: _Opcode_name[478:486],
153: _Opcode_name[486:490],
154: _Opcode_name[490:493],
155: _Opcode_name[493:499],
156: _Opcode_name[499:502],
157: _Opcode_name[502:505],
158: _Opcode_name[505:508],
159: _Opcode_name[508:511],
160: _Opcode_name[511:514],
161: _Opcode_name[514:517],
162: _Opcode_name[517:520],
168: _Opcode_name[520:523],
169: _Opcode_name[523:526],
170: _Opcode_name[526:529],
171: _Opcode_name[529:536],
172: _Opcode_name[536:542],
177: _Opcode_name[542:544],
179: _Opcode_name[544:552],
180: _Opcode_name[552:563],
181: _Opcode_name[563:565],
182: _Opcode_name[565:568],
183: _Opcode_name[568:570],
184: _Opcode_name[570:573],
185: _Opcode_name[573:576],
186: _Opcode_name[576:579],
187: _Opcode_name[579:585],
192: _Opcode_name[585:589],
193: _Opcode_name[589:595],
194: _Opcode_name[595:604],
195: _Opcode_name[604:612],
196: _Opcode_name[612:621],
197: _Opcode_name[621:631],
198: _Opcode_name[631:640],
200: _Opcode_name[640:646],
202: _Opcode_name[646:650],
203: _Opcode_name[650:656],
204: _Opcode_name[656:660],
205: _Opcode_name[660:666],
206: _Opcode_name[666:674],
207: _Opcode_name[674:680],
208: _Opcode_name[680:687],
209: _Opcode_name[687:699],
210: _Opcode_name[699:705],
211: _Opcode_name[705:715],
216: _Opcode_name[715:721],
217: _Opcode_name[721:727],
219: _Opcode_name[727:734],
}
func (i Opcode) String() string {

View file

@ -71,9 +71,6 @@ type VM struct {
// callback to get interop price
getPrice func(*VM, opcode.Opcode, []byte) util.Fixed8
// callback to get scripts.
getScript func(util.Uint160) ([]byte, bool)
istack *Stack // invocation stack.
estack *Stack // execution stack.
astack *Stack // alt stack.
@ -95,7 +92,6 @@ type VM struct {
func New() *VM {
vm := &VM{
getInterop: make([]InteropGetterFunc, 0, 3), // 3 functions is typical for our default usage.
getScript: nil,
state: haltState,
istack: NewStack("invocation"),
@ -204,8 +200,6 @@ func (v *VM) PrintOps() {
desc = fmt.Sprintf("%d (%d/%x)", ctx.ip+int(offset), offset, parameter)
case opcode.SYSCALL:
desc = fmt.Sprintf("%q", parameter)
case opcode.APPCALL, opcode.TAILCALL:
desc = fmt.Sprintf("%x", parameter)
default:
if utf8.Valid(parameter) {
desc = fmt.Sprintf("%x (%q)", parameter, parameter)
@ -477,11 +471,6 @@ func (v *VM) SetCheckedHash(h []byte) {
copy(v.checkhash, h)
}
// SetScriptGetter sets the script getter for CALL instructions.
func (v *VM) SetScriptGetter(gs func(util.Uint160) ([]byte, bool)) {
v.getScript = gs
}
// GetInteropID converts instruction parameter to an interop ID.
func GetInteropID(parameter []byte) uint32 {
return binary.LittleEndian.Uint32(parameter)
@ -520,25 +509,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
}
}
switch op {
case opcode.APPCALL, opcode.TAILCALL:
isZero := true
for i := range parameter {
if parameter[i] != 0 {
isZero = false
break
}
}
if !isZero {
break
}
parameter = v.estack.Pop().Bytes()
if !ctx.hasDynamicInvoke {
panic("contract is not allowed to make dynamic invocations")
}
}
if op <= opcode.PUSHINT256 {
v.estack.PushVal(emit.BytesToInt(parameter))
return
@ -1175,31 +1145,6 @@ func (v *VM) execute(ctx *Context, op opcode.Opcode, parameter []byte) (err erro
panic(fmt.Sprintf("failed to invoke syscall: %s", err))
}
case opcode.APPCALL, opcode.TAILCALL:
if v.getScript == nil {
panic("no getScript callback is set up")
}
if op == opcode.APPCALL {
v.checkInvocationStackSize()
}
hash, err := util.Uint160DecodeBytesBE(parameter)
if err != nil {
panic(err)
}
script, hasDynamicInvoke := v.getScript(hash)
if script == nil {
panic("could not find script")
}
if op == opcode.TAILCALL {
_ = v.istack.Pop()
}
v.loadScriptWithHash(script, hash, hasDynamicInvoke)
case opcode.RET:
oldCtx := v.istack.Pop().Value().(*Context)
rvcount := oldCtx.rvcount

View file

@ -1413,69 +1413,6 @@ func TestSIGN(t *testing.T) {
t.Run("ByteArray", getTestFuncForVM(prog, 1, []byte{0, 1}))
}
func TestAppCall(t *testing.T) {
prog := []byte{byte(opcode.APPCALL)}
hash := util.Uint160{1, 2}
prog = append(prog, hash.BytesBE()...)
prog = append(prog, byte(opcode.RET))
vm := load(prog)
vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) {
if in.Equals(hash) {
return makeProgram(opcode.DEPTH), true
}
return nil, false
})
vm.estack.PushVal(2)
runVM(t, vm)
elem := vm.estack.Pop() // depth should be 1
assert.Equal(t, int64(1), elem.BigInt().Int64())
}
func TestAppCallDynamicBad(t *testing.T) {
prog := []byte{byte(opcode.APPCALL)}
hash := util.Uint160{}
prog = append(prog, hash.BytesBE()...)
prog = append(prog, byte(opcode.RET))
vm := load(prog)
vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) {
if in.Equals(hash) {
return makeProgram(opcode.DEPTH), true
}
return nil, false
})
vm.estack.PushVal(2)
vm.estack.PushVal(hash.BytesBE())
checkVMFailed(t, vm)
}
func TestAppCallDynamicGood(t *testing.T) {
prog := []byte{byte(opcode.APPCALL)}
zeroHash := util.Uint160{}
hash := util.Uint160{1, 2, 3}
prog = append(prog, zeroHash.BytesBE()...)
prog = append(prog, byte(opcode.RET))
vm := load(prog)
vm.SetScriptGetter(func(in util.Uint160) ([]byte, bool) {
if in.Equals(hash) {
return makeProgram(opcode.DEPTH), true
}
return nil, false
})
vm.estack.PushVal(42)
vm.estack.PushVal(42)
vm.estack.PushVal(hash.BytesBE())
vm.Context().hasDynamicInvoke = true
runVM(t, vm)
elem := vm.estack.Pop() // depth should be 2
assert.Equal(t, int64(2), elem.BigInt().Int64())
}
func TestSimpleCall(t *testing.T) {
buf := io.NewBufBinWriter()
w := buf.BinWriter

View file

@ -113,13 +113,13 @@ func TestAccount_ConvertMultisig(t *testing.T) {
t.Run("1/1 multisig", func(t *testing.T) {
pubs := convertPubs(t, hexs[:1])
require.NoError(t, a.ConvertMultisig(1, pubs))
require.Equal(t, "ANg3mmstMr7qtY8TgdKM777WSLKCNFbawM", a.Address)
require.Equal(t, "AUhsL7QeeomkuzxZexPTa11xNXrbsBrGVc", a.Address)
})
t.Run("3/4 multisig", func(t *testing.T) {
pubs := convertPubs(t, hexs)
require.NoError(t, a.ConvertMultisig(3, pubs))
require.Equal(t, "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy", a.Address)
require.Equal(t, "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL", a.Address)
})
}

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4",
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",

View file

@ -2,11 +2,11 @@
"version": "1.0",
"accounts": [
{
"address": "ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b680a906ad4",
"script": "0c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20b410a906ad4",
"parameters": [
{
"name": "parameter0",
@ -19,11 +19,11 @@
"isDefault": false
},
{
"address": "Ad1wDxzcRiRSryvJobNV211Tv7UUiziPXy",
"key": "6PYNTeMkEZ1Q2MCqkPMgvC2kvRzH6f1sz4Sj9cGcLG4iYb43yQcpThAeap",
"address": "AXSvJVzydxXuL9da4GVwK25zdesCrVKkHL",
"key": "6PYMnbn4qBT8v156ii3nijRo2hQD1YHWkFXN7NKCrAZRzJDU1ych1sh2Wj",
"label": "",
"contract": {
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b683073b3bb",
"script": "130c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0c2102a7bc55fe8684e0119768d104ba30795bdcc86619e864add26156723ed185cd620c2102b3622bf4017bdfe317c58aed5f4c753f206b7db896046fa7d774bbc4bf7f8dc20c2103d90c07df63e690ce77912e10ab51acc944b66860237b608c4f8f8309e71ee699140b413073b3bb",
"parameters": [
{
"name": "parameter0",
@ -44,11 +44,11 @@
"isDefault": false
},
{
"address": "Aaidx8VxYVjpD6knF8toWG7WquQjQFWcZB",
"key": "6PYMZM16cgdQ9GH5ejEPFqehuZ3Lp16W4fW7LyoBdUuVyeMeom7z8wP5QV",
"address": "AJjSSuKdC88zWvXnZQbEfL21cm74pGJhsF",
"key": "6PYLZTVkK3RoPU8PSAUPHfnu4Py2JcJfeT92FS77DDakRRLcrNu2uCY46Q",
"label": "",
"contract": {
"script": "0c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0b680a906ad4",
"script": "0c2102103a7f7dd016558597f7960d27c516a4394fd968b9e65155eb4b013e4040406e0b410a906ad4",
"parameters": [
{
"name": "parameter0",

View file

@ -181,14 +181,14 @@ func TestWalletGetChangeAddress(t *testing.T) {
require.NoError(t, err)
sh := w1.GetChangeAddress()
// No default address, the first one is used.
expected, err := address.StringToUint160("ASW1VhcukJRrukCXRipY4BE9d9zy4mAYsR")
expected, err := address.StringToUint160("ALHF9wsXZVEuCGgmDA6ZNsCLtrb4A1g4yG")
require.NoError(t, err)
require.Equal(t, expected, sh)
w2, err := NewWalletFromFile("testdata/wallet2.json")
require.NoError(t, err)
sh = w2.GetChangeAddress()
// Default address.
expected, err = address.StringToUint160("Aaidx8VxYVjpD6knF8toWG7WquQjQFWcZB")
expected, err = address.StringToUint160("AJjSSuKdC88zWvXnZQbEfL21cm74pGJhsF")
require.NoError(t, err)
require.Equal(t, expected, sh)
}