From 11191c0a08f8b939ca12de66231ad232d8fecce1 Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Wed, 13 Jan 2021 15:26:35 +0300 Subject: [PATCH 1/2] nef: support JSON serialization --- pkg/smartcontract/nef/nef.go | 12 ++++++------ pkg/smartcontract/nef/nef_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 6 deletions(-) diff --git a/pkg/smartcontract/nef/nef.go b/pkg/smartcontract/nef/nef.go index 9d1088af8..74476d0ab 100644 --- a/pkg/smartcontract/nef/nef.go +++ b/pkg/smartcontract/nef/nef.go @@ -36,16 +36,16 @@ const ( // File represents compiled contract file structure according to the NEF3 standard. type File struct { - Header Header - Script []byte - Checksum uint32 + Header + Script []byte `json:"script"` + Checksum uint32 `json:"checksum"` } // Header represents File header. type Header struct { - Magic uint32 - Compiler string - Version string + Magic uint32 `json:"magic"` + Compiler string `json:"compiler"` + Version string `json:"version"` } // NewFile returns new NEF3 file with script specified. diff --git a/pkg/smartcontract/nef/nef_test.go b/pkg/smartcontract/nef/nef_test.go index f5236fd64..c0054e461 100644 --- a/pkg/smartcontract/nef/nef_test.go +++ b/pkg/smartcontract/nef/nef_test.go @@ -1,6 +1,9 @@ package nef import ( + "encoding/base64" + "encoding/json" + "strconv" "testing" "github.com/nspcc-dev/neo-go/internal/testserdes" @@ -74,3 +77,28 @@ func TestBytesFromBytes(t *testing.T) { require.NoError(t, err) require.Equal(t, expected, actual) } + +func TestMarshalUnmarshalJSON(t *testing.T) { + expected := &File{ + Header: Header{ + Magic: Magic, + Compiler: "test.compiler", + Version: "test.ver", + }, + Script: []byte{1, 2, 3, 4}, + } + expected.Checksum = expected.CalculateChecksum() + + data, err := json.Marshal(expected) + require.NoError(t, err) + require.JSONEq(t, `{ + "magic":`+strconv.FormatUint(uint64(Magic), 10)+`, + "compiler": "test.compiler", + "version": "test.ver", + "script": "`+base64.StdEncoding.EncodeToString(expected.Script)+`", + "checksum":`+strconv.FormatUint(uint64(expected.Checksum), 10)+`}`, string(data)) + + actual := new(File) + require.NoError(t, json.Unmarshal(data, actual)) + require.Equal(t, expected, actual) +} From 0b26b462348c39ba2eadbc7de22895c3bcffae57 Mon Sep 17 00:00:00 2001 From: Evgeniy Stratonikov Date: Wed, 13 Jan 2021 15:34:10 +0300 Subject: [PATCH 2/2] state: store NEF instead of script for contract NEFs for native contracts are set statically, thus field values are taken from the reference implementation. --- cli/wallet/wallet.go | 2 +- pkg/compiler/interop_test.go | 9 ++++-- pkg/core/blockchain.go | 2 +- pkg/core/helper_test.go | 2 +- pkg/core/interop/context.go | 11 +++++-- pkg/core/interop/contract/call.go | 2 +- pkg/core/interop_neo_test.go | 5 +++- pkg/core/interop_system.go | 2 +- pkg/core/interop_system_test.go | 47 ++++++++++++++++++++---------- pkg/core/native/management.go | 6 ++-- pkg/core/native/management_test.go | 4 +-- pkg/core/native_contract_test.go | 6 ++-- pkg/core/native_management_test.go | 28 +++++++++--------- pkg/core/native_oracle_test.go | 7 ++++- pkg/core/state/contract.go | 15 +++++++--- pkg/core/state/contract_test.go | 39 ++++++++++++++++--------- pkg/rpc/client/rpc_test.go | 23 +++++++++++---- 17 files changed, 138 insertions(+), 72 deletions(-) diff --git a/cli/wallet/wallet.go b/cli/wallet/wallet.go index 5b593f678..f8dc0f44c 100644 --- a/cli/wallet/wallet.go +++ b/cli/wallet/wallet.go @@ -424,7 +424,7 @@ func importDeployed(ctx *cli.Context) error { return cli.NewExitError("contract has no `verify` method", 1) } acc.Address = address.Uint160ToString(cs.Hash) - acc.Contract.Script = cs.Script + acc.Contract.Script = cs.NEF.Script acc.Contract.Parameters = acc.Contract.Parameters[:0] for _, p := range md.Parameters { acc.Contract.Parameters = append(acc.Contract.Parameters, wallet.ContractParam{ diff --git a/pkg/compiler/interop_test.go b/pkg/compiler/interop_test.go index ee618b999..57514d331 100644 --- a/pkg/compiler/interop_test.go +++ b/pkg/compiler/interop_test.go @@ -18,6 +18,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/encoding/address" cinterop "github.com/nspcc-dev/neo-go/pkg/interop" "github.com/nspcc-dev/neo-go/pkg/smartcontract" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "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" @@ -162,15 +163,19 @@ func TestAppCall(t *testing.T) { ih := hash.Hash160(inner) var contractGetter = func(_ dao.DAO, h util.Uint160) (*state.Contract, error) { if h.Equals(ih) { + innerNef, err := nef.NewFile(inner) + require.NoError(t, err) return &state.Contract{ Hash: ih, - Script: inner, + NEF: *innerNef, Manifest: *m, }, nil } else if h.Equals(barH) { + barNef, err := nef.NewFile(barCtr) + require.NoError(t, err) return &state.Contract{ Hash: barH, - Script: barCtr, + NEF: *barNef, Manifest: *mBar, }, nil } diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 8ee28a6f4..5681a2657 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -1667,7 +1667,7 @@ func (bc *Blockchain) initVerificationVM(ic *interop.Context, hash util.Uint160, return ErrInvalidVerificationContract } initMD := cs.Manifest.ABI.GetMethod(manifest.MethodInit) - v.LoadScriptWithHash(cs.Script, hash, smartcontract.ReadStates) + v.LoadScriptWithHash(cs.NEF.Script, hash, smartcontract.ReadStates) v.Jump(v.Context(), md.Offset) if cs.ID <= 0 { diff --git a/pkg/core/helper_test.go b/pkg/core/helper_test.go index f570f4cd9..dca80e2c0 100644 --- a/pkg/core/helper_test.go +++ b/pkg/core/helper_test.go @@ -418,7 +418,7 @@ func addNetworkFee(bc *Blockchain, tx *transaction.Transaction, sender *wallet.A for _, cosigner := range tx.Signers { contract := bc.GetContractState(cosigner.Account) if contract != nil { - netFee, sizeDelta = fee.Calculate(bc.GetBaseExecFee(), contract.Script) + netFee, sizeDelta = fee.Calculate(bc.GetBaseExecFee(), contract.NEF.Script) tx.NetworkFee += netFee size += sizeDelta } diff --git a/pkg/core/interop/context.go b/pkg/core/interop/context.go index ee141cfdf..1fc51562d 100644 --- a/pkg/core/interop/context.go +++ b/pkg/core/interop/context.go @@ -13,6 +13,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "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" @@ -103,7 +104,7 @@ type ContractMD struct { Manifest manifest.Manifest Name string ContractID int32 - Script []byte + NEF nef.File Hash util.Uint160 Methods map[string]MethodAndPrice } @@ -115,7 +116,13 @@ func NewContractMD(name string) *ContractMD { Methods: make(map[string]MethodAndPrice), } - c.Script, c.Hash = state.CreateNativeContractHash(c.Name) + // NEF is now stored in contract state and affects state dump. + // Therefore values are taken from C# node. + c.NEF.Header.Compiler = "ScriptBuilder" + c.NEF.Header.Magic = nef.Magic + c.NEF.Header.Version = "3.0" + c.NEF.Script, c.Hash = state.CreateNativeContractHash(c.Name) + c.NEF.Checksum = c.NEF.CalculateChecksum() c.Manifest = *manifest.DefaultManifest(name) return c diff --git a/pkg/core/interop/contract/call.go b/pkg/core/interop/contract/call.go index c828b6f54..6b33dfbbf 100644 --- a/pkg/core/interop/contract/call.go +++ b/pkg/core/interop/contract/call.go @@ -82,7 +82,7 @@ func callExFromNative(ic *interop.Context, caller util.Uint160, cs *state.Contra } ic.VM.Invocations[cs.Hash]++ - ic.VM.LoadScriptWithCallingHash(caller, cs.Script, cs.Hash, ic.VM.Context().GetCallFlags()&f) + ic.VM.LoadScriptWithCallingHash(caller, cs.NEF.Script, cs.Hash, ic.VM.Context().GetCallFlags()&f) var isNative bool for i := range ic.Natives { if ic.Natives[i].Metadata().Hash.Equals(cs.Hash) { diff --git a/pkg/core/interop_neo_test.go b/pkg/core/interop_neo_test.go index eeb29a22c..53fd9de61 100644 --- a/pkg/core/interop_neo_test.go +++ b/pkg/core/interop_neo_test.go @@ -14,6 +14,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/core/transaction" "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "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" @@ -160,8 +161,10 @@ func createVMAndPushTX(t *testing.T) (*vm.VM, *transaction.Transaction, *interop func createVMAndContractState(t *testing.T) (*vm.VM, *state.Contract, *interop.Context, *Blockchain) { script := []byte("testscript") m := manifest.NewManifest("Test") + ne, err := nef.NewFile(script) + require.NoError(t, err) contractState := &state.Contract{ - Script: script, + NEF: *ne, Hash: hash.Hash160(script), Manifest: *m, ID: 123, diff --git a/pkg/core/interop_system.go b/pkg/core/interop_system.go index 1edeb9012..7fc48ea5f 100644 --- a/pkg/core/interop_system.go +++ b/pkg/core/interop_system.go @@ -338,7 +338,7 @@ func contractIsStandard(ic *interop.Context) error { var result bool cs, _ := ic.GetContract(u) if cs != nil { - result = vm.IsStandardContract(cs.Script) + result = vm.IsStandardContract(cs.NEF.Script) } else { if tx, ok := ic.Container.(*transaction.Transaction); ok { for _, witness := range tx.Scripts { diff --git a/pkg/core/interop_system_test.go b/pkg/core/interop_system_test.go index 1879ad916..b0ff75c2a 100644 --- a/pkg/core/interop_system_test.go +++ b/pkg/core/interop_system_test.go @@ -21,6 +21,7 @@ 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/smartcontract/nef" "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" @@ -226,7 +227,9 @@ func TestContractIsStandard(t *testing.T) { require.NoError(t, err) pub := priv.PublicKey() - err = chain.contracts.Management.PutContractState(ic.DAO, &state.Contract{ID: 42, Hash: pub.GetScriptHash(), Script: pub.GetVerificationScript()}) + ne, err := nef.NewFile(pub.GetVerificationScript()) + require.NoError(t, err) + err = chain.contracts.Management.PutContractState(ic.DAO, &state.Contract{ID: 42, Hash: pub.GetScriptHash(), NEF: *ne}) require.NoError(t, err) v.Estack().PushVal(pub.GetScriptHash().BytesBE()) @@ -235,7 +238,9 @@ func TestContractIsStandard(t *testing.T) { }) t.Run("contract stored, false", func(t *testing.T) { script := []byte{byte(opcode.PUSHT)} - require.NoError(t, chain.contracts.Management.PutContractState(ic.DAO, &state.Contract{ID: 24, Hash: hash.Hash160(script), Script: script})) + ne, err := nef.NewFile(script) + require.NoError(t, err) + require.NoError(t, chain.contracts.Management.PutContractState(ic.DAO, &state.Contract{ID: 24, Hash: hash.Hash160(script), NEF: *ne})) v.Estack().PushVal(crypto.Hash160(script).BytesBE()) require.NoError(t, contractIsStandard(ic)) @@ -343,7 +348,7 @@ func TestStoragePut(t *testing.T) { initVM := func(t *testing.T, key, value []byte, gas int64) { v := ic.SpawnVM() - v.LoadScript(cs.Script) + v.LoadScript(cs.NEF.Script) v.GasLimit = gas v.Estack().PushVal(value) v.Estack().PushVal(key) @@ -392,7 +397,7 @@ func TestStoragePut(t *testing.T) { }) t.Run("item exists and is const", func(t *testing.T) { v := ic.SpawnVM() - v.LoadScript(cs.Script) + v.LoadScript(cs.NEF.Script) v.GasLimit = -1 v.Estack().PushVal(1) v.Estack().PushVal("value") @@ -413,7 +418,7 @@ func TestStorageDelete(t *testing.T) { defer bc.Close() require.NoError(t, bc.contracts.Management.PutContractState(ic.DAO, cs)) - v.LoadScriptWithHash(cs.Script, cs.Hash, smartcontract.All) + v.LoadScriptWithHash(cs.NEF.Script, cs.Hash, smartcontract.All) put := func(key, value string, flag int) { v.Estack().PushVal(flag) v.Estack().PushVal(value) @@ -615,11 +620,15 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) { }, } cs := &state.Contract{ - Script: script, Hash: h, Manifest: *m, ID: 42, } + ne, err := nef.NewFile(script) + if err != nil { + panic(err) + } + cs.NEF = *ne currScript := []byte{byte(opcode.RET)} m = manifest.NewManifest("TestAux") @@ -631,9 +640,13 @@ func getTestContractState(bc *Blockchain) (*state.Contract, *state.Contract) { perm.Methods.Add("justReturn") perm.Methods.Add("getValue") m.Permissions = append(m.Permissions, *perm) + ne, err = nef.NewFile(currScript) + if err != nil { + panic(err) + } return cs, &state.Contract{ - Script: currScript, + NEF: *ne, Hash: hash.Hash160(currScript), Manifest: *m, ID: 123, @@ -666,8 +679,8 @@ func TestContractCall(t *testing.T) { require.NoError(t, bc.contracts.Management.PutContractState(ic.DAO, cs)) require.NoError(t, bc.contracts.Management.PutContractState(ic.DAO, currCs)) - currScript := currCs.Script - h := hash.Hash160(cs.Script) + currScript := currCs.NEF.Script + h := hash.Hash160(cs.NEF.Script) addArgs := stackitem.NewArray([]stackitem.Item{stackitem.Make(1), stackitem.Make(2)}) t.Run("Good", func(t *testing.T) { @@ -823,7 +836,7 @@ func TestMethodCallback(t *testing.T) { t.Run("Invalid", func(t *testing.T) { runInvalid := func(args ...interface{}) func(t *testing.T) { return func(t *testing.T) { - loadScript(ic, currCs.Script, 42) + loadScript(ic, currCs.NEF.Script, 42) for i := range args { ic.VM.Estack().PushVal(args[i]) } @@ -836,7 +849,7 @@ func TestMethodCallback(t *testing.T) { t.Run("DisallowedMethod", runInvalid("ret7", rawHash)) t.Run("Initialize", runInvalid("_initialize", rawHash)) t.Run("NotEnoughArguments", func(t *testing.T) { - loadScript(ic, currCs.Script, 42, "add", rawHash) + loadScript(ic, currCs.NEF.Script, 42, "add", rawHash) require.NoError(t, callback.CreateFromMethod(ic)) ic.VM.Estack().InsertAt(vm.NewElement(stackitem.NewArray([]stackitem.Item{stackitem.Make(1)})), 1) @@ -844,7 +857,7 @@ func TestMethodCallback(t *testing.T) { }) t.Run("CallIsNotAllowed", func(t *testing.T) { ic.SpawnVM() - ic.VM.Load(currCs.Script) + ic.VM.Load(currCs.NEF.Script) ic.VM.Estack().PushVal("add") ic.VM.Estack().PushVal(rawHash) require.NoError(t, callback.CreateFromMethod(ic)) @@ -856,7 +869,7 @@ func TestMethodCallback(t *testing.T) { }) t.Run("Good", func(t *testing.T) { - loadScript(ic, currCs.Script, 42, "add", rawHash) + loadScript(ic, currCs.NEF.Script, 42, "add", rawHash) require.NoError(t, callback.CreateFromMethod(ic)) args := stackitem.NewArray([]stackitem.Item{stackitem.Make(1), stackitem.Make(5)}) @@ -1074,10 +1087,12 @@ func TestRuntimeCheckWitness(t *testing.T) { } contractScript := []byte{byte(opcode.PUSH1), byte(opcode.RET)} contractScriptHash := hash.Hash160(contractScript) + ne, err := nef.NewFile(contractScript) + require.NoError(t, err) contractState := &state.Contract{ - ID: 15, - Hash: contractScriptHash, - Script: contractScript, + ID: 15, + Hash: contractScriptHash, + NEF: *ne, Manifest: manifest.Manifest{ Groups: []manifest.Group{{PublicKey: pk.PublicKey()}}, }, diff --git a/pkg/core/native/management.go b/pkg/core/native/management.go index ef5a5361c..40bbe885f 100644 --- a/pkg/core/native/management.go +++ b/pkg/core/native/management.go @@ -252,7 +252,7 @@ func (m *Management) Deploy(d dao.DAO, sender util.Uint160, neff *nef.File, mani newcontract := &state.Contract{ ID: id, Hash: h, - Script: neff.Script, + NEF: *neff, Manifest: *manif, } err = m.PutContractState(d, newcontract) @@ -292,7 +292,7 @@ func (m *Management) Update(d dao.DAO, hash util.Uint160, neff *nef.File, manif // if NEF was provided, update the contract script if neff != nil { m.markUpdated(hash) - contract.Script = neff.Script + contract.NEF = *neff } // if manifest was provided, update the contract manifest if manif != nil { @@ -415,7 +415,7 @@ func (m *Management) OnPersist(ic *interop.Context) error { cs := &state.Contract{ ID: md.ContractID, Hash: md.Hash, - Script: md.Script, + NEF: md.NEF, Manifest: md.Manifest, } err := m.PutContractState(ic.DAO, cs) diff --git a/pkg/core/native/management_test.go b/pkg/core/native/management_test.go index 0b652d0ed..8d1571baa 100644 --- a/pkg/core/native/management_test.go +++ b/pkg/core/native/management_test.go @@ -30,7 +30,7 @@ func TestDeployGetUpdateDestroyContract(t *testing.T) { require.Equal(t, int32(1), contract.ID) require.Equal(t, uint16(0), contract.UpdateCounter) require.Equal(t, h, contract.Hash) - require.Equal(t, script, contract.Script) + require.Equal(t, ne, &contract.NEF) require.Equal(t, *manif, contract.Manifest) // Double deploy. @@ -44,7 +44,7 @@ func TestDeployGetUpdateDestroyContract(t *testing.T) { require.Equal(t, int32(2), contract2.ID) require.Equal(t, uint16(0), contract2.UpdateCounter) require.Equal(t, state.CreateContractHash(sender2, script), contract2.Hash) - require.Equal(t, script, contract2.Script) + require.Equal(t, ne, &contract2.NEF) require.Equal(t, *manif, contract2.Manifest) refContract, err := mgmt.GetContract(d, h) diff --git a/pkg/core/native_contract_test.go b/pkg/core/native_contract_test.go index 7bcd848a4..a5fdb3fa0 100644 --- a/pkg/core/native_contract_test.go +++ b/pkg/core/native_contract_test.go @@ -172,7 +172,7 @@ func TestNativeContract_Invoke(t *testing.T) { err := chain.contracts.Management.PutContractState(chain.dao, &state.Contract{ ID: 1, - Script: tn.meta.Script, + NEF: tn.meta.NEF, Hash: tn.meta.Hash, Manifest: tn.meta.Manifest, }) @@ -210,7 +210,7 @@ func TestNativeContract_InvokeInternal(t *testing.T) { err := chain.contracts.Management.PutContractState(chain.dao, &state.Contract{ ID: 1, - Script: tn.meta.Script, + NEF: tn.meta.NEF, Manifest: tn.meta.Manifest, }) require.NoError(t, err) @@ -252,7 +252,7 @@ func TestNativeContract_InvokeOtherContract(t *testing.T) { err := chain.contracts.Management.PutContractState(chain.dao, &state.Contract{ ID: 1, Hash: tn.meta.Hash, - Script: tn.meta.Script, + NEF: tn.meta.NEF, Manifest: tn.meta.Manifest, }) require.NoError(t, err) diff --git a/pkg/core/native_management_test.go b/pkg/core/native_management_test.go index ad4a6be68..4a208713d 100644 --- a/pkg/core/native_management_test.go +++ b/pkg/core/native_management_test.go @@ -36,10 +36,10 @@ func TestRestoreAfterDeploy(t *testing.T) { mgmtHash := bc.ManagementContractHash() cs1, _ := getTestContractState(bc) cs1.ID = 1 - cs1.Hash = state.CreateContractHash(testchain.MultisigScriptHash(), cs1.Script) + cs1.Hash = state.CreateContractHash(testchain.MultisigScriptHash(), cs1.NEF.Script) manif1, err := json.Marshal(cs1.Manifest) require.NoError(t, err) - nef1, err := nef.NewFile(cs1.Script) + nef1, err := nef.NewFile(cs1.NEF.Script) require.NoError(t, err) nef1b, err := nef1.Bytes() require.NoError(t, err) @@ -80,10 +80,10 @@ func TestContractDeploy(t *testing.T) { mgmtHash := bc.ManagementContractHash() cs1, _ := getTestContractState(bc) cs1.ID = 1 - cs1.Hash = state.CreateContractHash(testchain.MultisigScriptHash(), cs1.Script) + cs1.Hash = state.CreateContractHash(testchain.MultisigScriptHash(), cs1.NEF.Script) manif1, err := json.Marshal(cs1.Manifest) require.NoError(t, err) - nef1, err := nef.NewFile(cs1.Script) + nef1, err := nef.NewFile(cs1.NEF.Script) require.NoError(t, err) nef1b, err := nef1.Bytes() require.NoError(t, err) @@ -278,7 +278,7 @@ func TestContractUpdate(t *testing.T) { require.NoError(t, err) manif1, err := json.Marshal(cs1.Manifest) require.NoError(t, err) - nef1, err := nef.NewFile(cs1.Script) + nef1, err := nef.NewFile(cs1.NEF.Script) require.NoError(t, err) nef1b, err := nef1.Bytes() require.NoError(t, err) @@ -322,10 +322,9 @@ func TestContractUpdate(t *testing.T) { checkFAULTState(t, res) }) - cs1.Script = append(cs1.Script, byte(opcode.RET)) - nef1, err = nef.NewFile(cs1.Script) - require.NoError(t, err) - nef1b, err = nef1.Bytes() + cs1.NEF.Script = append(cs1.NEF.Script, byte(opcode.RET)) + cs1.NEF.Checksum = cs1.NEF.CalculateChecksum() + nef1b, err = cs1.NEF.Bytes() require.NoError(t, err) cs1.UpdateCounter++ @@ -376,10 +375,9 @@ func TestContractUpdate(t *testing.T) { }) }) - cs1.Script = append(cs1.Script, byte(opcode.ABORT)) - nef1, err = nef.NewFile(cs1.Script) - require.NoError(t, err) - nef1b, err = nef1.Bytes() + cs1.NEF.Script = append(cs1.NEF.Script, byte(opcode.ABORT)) + cs1.NEF.Checksum = cs1.NEF.CalculateChecksum() + nef1b, err = cs1.NEF.Bytes() require.NoError(t, err) cs1.Manifest.Extra = "update me once more" manif1, err = json.Marshal(cs1.Manifest) @@ -471,12 +469,14 @@ func compareContractStates(t *testing.T, expected *state.Contract, actual stacki expectedManifest, err := json.Marshal(expected.Manifest) require.NoError(t, err) + expectedNef, err := expected.NEF.Bytes() + require.NoError(t, err) require.Equal(t, 5, len(act)) require.Equal(t, expected.ID, int32(act[0].Value().(*big.Int).Int64())) require.Equal(t, expected.UpdateCounter, uint16(act[1].Value().(*big.Int).Int64())) require.Equal(t, expected.Hash.BytesBE(), act[2].Value().([]byte)) - require.Equal(t, expected.Script, act[3].Value().([]byte)) + require.Equal(t, expectedNef, act[3].Value().([]byte)) require.Equal(t, expectedManifest, act[4].Value().([]byte)) } diff --git a/pkg/core/native_oracle_test.go b/pkg/core/native_oracle_test.go index 533f25d94..5341b848a 100644 --- a/pkg/core/native_oracle_test.go +++ b/pkg/core/native_oracle_test.go @@ -17,6 +17,7 @@ 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/smartcontract/nef" "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" @@ -83,8 +84,12 @@ func getOracleContractState(h util.Uint160) *state.Contract { m.Permissions = append(m.Permissions, *perm) script := w.Bytes() + ne, err := nef.NewFile(script) + if err != nil { + panic(err) + } return &state.Contract{ - Script: script, + NEF: *ne, Hash: hash.Hash160(script), Manifest: *m, ID: 42, diff --git a/pkg/core/state/contract.go b/pkg/core/state/contract.go index 34a399c26..46e9ef554 100644 --- a/pkg/core/state/contract.go +++ b/pkg/core/state/contract.go @@ -10,6 +10,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/opcode" @@ -21,7 +22,7 @@ type Contract struct { ID int32 `json:"id"` UpdateCounter uint16 `json:"updatecounter"` Hash util.Uint160 `json:"hash"` - Script []byte `json:"script"` + NEF nef.File `json:"nef"` Manifest manifest.Manifest `json:"manifest"` } @@ -50,11 +51,15 @@ func (c *Contract) ToStackItem() (stackitem.Item, error) { if err != nil { return nil, err } + rawNef, err := c.NEF.Bytes() + if err != nil { + return nil, err + } return stackitem.NewArray([]stackitem.Item{ stackitem.Make(c.ID), stackitem.Make(c.UpdateCounter), stackitem.NewByteArray(c.Hash.BytesBE()), - stackitem.NewByteArray(c.Script), + stackitem.NewByteArray(rawNef), stackitem.NewByteArray(manifest), }), nil } @@ -94,8 +99,10 @@ func (c *Contract) FromStackItem(item stackitem.Item) error { if err != nil { return err } - c.Script = make([]byte, len(bytes)) - copy(c.Script, bytes) + c.NEF, err = nef.FileFromBytes(bytes) + if err != nil { + return err + } bytes, err = arr[4].TryBytes() if err != nil { return err diff --git a/pkg/core/state/contract_test.go b/pkg/core/state/contract_test.go index 73d4e5ecf..fffebd670 100644 --- a/pkg/core/state/contract_test.go +++ b/pkg/core/state/contract_test.go @@ -9,6 +9,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/crypto/hash" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/stretchr/testify/require" @@ -37,9 +38,18 @@ func TestEncodeDecodeContractState(t *testing.T) { ID: 123, UpdateCounter: 42, Hash: h, - Script: script, - Manifest: *m, + NEF: nef.File{ + Header: nef.Header{ + Magic: nef.Magic, + Compiler: "neo-go.test", + Version: "test", + }, + Script: script, + Checksum: 0, + }, + Manifest: *m, } + contract.NEF.Checksum = contract.NEF.CalculateChecksum() t.Run("Serializable", func(t *testing.T) { contractDecoded := new(Contract) @@ -67,7 +77,10 @@ func TestContractFromStackItem(t *testing.T) { id = stackitem.Make(42) counter = stackitem.Make(11) chash = stackitem.Make(util.Uint160{1, 2, 3}.BytesBE()) - script = stackitem.Make([]byte{0, 9, 8}) + script = []byte{0, 9, 8} + nefFile, _ = nef.NewFile(script) + rawNef, _ = nefFile.Bytes() + nefItem = stackitem.NewByteArray(rawNef) manifest = manifest.DefaultManifest("stack item") manifestB, _ = json.Marshal(manifest) manifItem = stackitem.Make(manifestB) @@ -77,15 +90,15 @@ func TestContractFromStackItem(t *testing.T) { item stackitem.Item }{ {"not an array", stackitem.Make(1)}, - {"id is not a number", stackitem.Make([]stackitem.Item{manifItem, counter, chash, script, manifItem})}, - {"id is out of range", stackitem.Make([]stackitem.Item{stackitem.Make(math.MaxUint32), counter, chash, script, manifItem})}, - {"counter is not a number", stackitem.Make([]stackitem.Item{id, manifItem, chash, script, manifItem})}, - {"counter is out of range", stackitem.Make([]stackitem.Item{id, stackitem.Make(100500), chash, script, manifItem})}, - {"hash is not a byte string", stackitem.Make([]stackitem.Item{id, counter, stackitem.NewArray(nil), script, manifItem})}, - {"hash is not a hash", stackitem.Make([]stackitem.Item{id, counter, stackitem.Make([]byte{1, 2, 3}), script, manifItem})}, - {"script is not a byte string", stackitem.Make([]stackitem.Item{id, counter, chash, stackitem.NewArray(nil), manifItem})}, - {"manifest is not a byte string", stackitem.Make([]stackitem.Item{id, counter, chash, script, stackitem.NewArray(nil)})}, - {"manifest is not correct", stackitem.Make([]stackitem.Item{id, counter, chash, script, stackitem.Make(100500)})}, + {"id is not a number", stackitem.Make([]stackitem.Item{manifItem, counter, chash, nefItem, manifItem})}, + {"id is out of range", stackitem.Make([]stackitem.Item{stackitem.Make(math.MaxUint32), counter, chash, nefItem, manifItem})}, + {"counter is not a number", stackitem.Make([]stackitem.Item{id, manifItem, chash, nefItem, manifItem})}, + {"counter is out of range", stackitem.Make([]stackitem.Item{id, stackitem.Make(100500), chash, nefItem, manifItem})}, + {"hash is not a byte string", stackitem.Make([]stackitem.Item{id, counter, stackitem.NewArray(nil), nefItem, manifItem})}, + {"hash is not a hash", stackitem.Make([]stackitem.Item{id, counter, stackitem.Make([]byte{1, 2, 3}), nefItem, manifItem})}, + {"nef is not a byte string", stackitem.Make([]stackitem.Item{id, counter, chash, stackitem.NewArray(nil), manifItem})}, + {"manifest is not a byte string", stackitem.Make([]stackitem.Item{id, counter, chash, nefItem, stackitem.NewArray(nil)})}, + {"manifest is not correct", stackitem.Make([]stackitem.Item{id, counter, chash, nefItem, stackitem.Make(100500)})}, } ) for _, cs := range badCases { @@ -96,6 +109,6 @@ func TestContractFromStackItem(t *testing.T) { }) } var c = new(Contract) - err := c.FromStackItem(stackitem.Make([]stackitem.Item{id, counter, chash, script, manifItem})) + err := c.FromStackItem(stackitem.Make([]stackitem.Item{id, counter, chash, nefItem, manifItem})) require.NoError(t, err) } diff --git a/pkg/rpc/client/rpc_test.go b/pkg/rpc/client/rpc_test.go index ec4b24356..aa2b4bca4 100644 --- a/pkg/rpc/client/rpc_test.go +++ b/pkg/rpc/client/rpc_test.go @@ -27,6 +27,7 @@ import ( "github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" + "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "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" @@ -329,7 +330,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ } return c.GetContractStateByHash(hash) }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":749050685},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, result: func(c *Client) interface{} { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { @@ -339,7 +340,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ cs := &state.Contract{ ID: 0, Hash: hash.Hash160(script), - Script: script, + NEF: newTestNEF(script), Manifest: *m, } return cs @@ -350,7 +351,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ invoke: func(c *Client) (interface{}, error) { return c.GetContractStateByAddressOrName("NWiu5oejTu925aeL9Hc1LX8SvaJhE23h15") }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":749050685},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, result: func(c *Client) interface{} { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { @@ -360,7 +361,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ cs := &state.Contract{ ID: 0, Hash: hash.Hash160(script), - Script: script, + NEF: newTestNEF(script), Manifest: *m, } return cs @@ -371,7 +372,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ invoke: func(c *Client) (interface{}, error) { return c.GetContractStateByID(0) }, - serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, + serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go","version":"3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":749050685},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`, result: func(c *Client) interface{} { script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==") if err != nil { @@ -381,7 +382,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{ cs := &state.Contract{ ID: 0, Hash: hash.Hash160(script), - Script: script, + NEF: newTestNEF(script), Manifest: *m, } return cs @@ -1627,3 +1628,13 @@ func TestUninitedClient(t *testing.T) { _, err = c.GetFeePerByte() require.Error(t, err) } + +func newTestNEF(script []byte) nef.File { + var ne nef.File + ne.Header.Magic = nef.Magic + ne.Header.Version = "3.0" + ne.Header.Compiler = "neo-go" + ne.Script = script + ne.Checksum = ne.CalculateChecksum() + return ne +}