Merge pull request #1665 from nspcc-dev/nefstate

Store NEF in contract state
This commit is contained in:
Roman Khimov 2021-01-14 10:14:38 +03:00 committed by GitHub
commit 36b5751262
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 172 additions and 78 deletions

View file

@ -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{

View file

@ -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
}

View file

@ -1670,7 +1670,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 {

View file

@ -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
}

View file

@ -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

View file

@ -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) {

View file

@ -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,

View file

@ -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 {

View file

@ -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()}},
},

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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))
}

View file

@ -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,

View file

@ -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

View file

@ -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)
}

View file

@ -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
}

View file

@ -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.

View file

@ -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)
}