Merge pull request #1544 from nspcc-dev/remove-contract-features

Remove contract features
This commit is contained in:
Roman Khimov 2020-11-16 10:13:05 +03:00 committed by GitHub
commit 7b1902f513
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
35 changed files with 58 additions and 267 deletions

View file

@ -404,7 +404,6 @@ func contractCompile(ctx *cli.Context) error {
if err != nil {
return err
}
o.ContractFeatures = conf.GetFeatures()
o.ContractEvents = conf.Events
o.ContractSupportedStandards = conf.SupportedStandards
}
@ -632,24 +631,10 @@ func testInvokeScript(ctx *cli.Context) error {
// ProjectConfig contains project metadata.
type ProjectConfig struct {
HasStorage bool
IsPayable bool
SupportedStandards []string
Events []manifest.Event
}
// GetFeatures returns smartcontract features from the config.
func (p *ProjectConfig) GetFeatures() smartcontract.PropertyState {
var fs smartcontract.PropertyState
if p.IsPayable {
fs |= smartcontract.IsPayable
}
if p.HasStorage {
fs |= smartcontract.HasStorage
}
return fs
}
func inspect(ctx *cli.Context) error {
in := ctx.String("in")
compile := ctx.Bool("compile")

View file

@ -58,9 +58,7 @@ func RuntimeNotify(args []interface{}) {
manifest, err := ioutil.ReadFile(contractName + "/" + files[1].Name())
require.NoError(t, err)
require.Equal(t,
`hasstorage: false
ispayable: false
supportedstandards: []
`supportedstandards: []
events:
- name: Hello world!
parameters:
@ -69,15 +67,6 @@ events:
`, string(manifest))
}
func TestGetFeatures(t *testing.T) {
cfg := ProjectConfig{
IsPayable: true,
HasStorage: true,
}
f := cfg.GetFeatures()
require.Equal(t, smartcontract.IsPayable|smartcontract.HasStorage, f)
}
func TestParseCosigner(t *testing.T) {
acc := util.Uint160{1, 3, 5, 7}
testCases := map[string]transaction.Signer{

View file

@ -1 +0,0 @@
hasstorage: true

View file

@ -1 +1 @@
{"abi":{"hash":"0x8dff9f223e4622961f410c015dd37052a59892bb","methods":[{"name":"verify","offset":0,"parameters":[],"returntype":"Boolean"}],"events":[]},"groups":[],"features":{"payable":true,"storage":false},"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"safemethods":[],"extra":null}
{"abi":{"hash":"0x8dff9f223e4622961f410c015dd37052a59892bb","methods":[{"name":"verify","offset":0,"parameters":[],"returntype":"Boolean"}],"events":[]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":[],"trusts":[],"safemethods":[],"extra":null}

View file

@ -145,17 +145,12 @@ Deploying a contract to blockchain with neo-go requires a configuration file
with contract's metadata in YAML format, like the following:
```
project:
author: Jack Smith
email: jack@example.com
version: 1.0
name: 'Smart contract'
description: 'Even smarter than Jack himself'
hasstorage: true
hasdynamicinvocation: false
ispayable: false
returntype: ByteArray
parameters: ['String', 'Array']
supportedstandards: []
events:
- name: info
parameters:
- name: message
type: ByteString
```
It's passed to the `deploy` command via `-c` option:

View file

@ -1,5 +1,3 @@
hasstorage: false
ispayable: false
supportedstandards: []
events:
- name: Tx

View file

@ -1,5 +1,3 @@
hasstorage: true
ispayable: false
supportedstandards: []
events:
- name: found storage values

View file

@ -1,5 +1,3 @@
hasstorage: false
ispayable: false
supportedstandards: []
events:
- name: Event

View file

@ -1,4 +1,2 @@
hasstorage: true
ispayable: false
supportedstandards: []
events: []

View file

@ -1,4 +1,2 @@
hasstorage: true
ispayable: false
supportedstandards: []
events: []

View file

@ -1,4 +1,2 @@
hasstorage: true
ispayable: false
supportedstandards: ["NEP-5"]
events: []

View file

@ -1,5 +1,3 @@
hasstorage: true
ispayable: false
supportedstandards: ["NEP-5"]
events:
- name: transfer

View file

@ -13,7 +13,6 @@ import (
"path"
"strings"
"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"
"golang.org/x/tools/go/loader"
@ -35,9 +34,6 @@ type Options struct {
// The name of the output for contract manifest file.
ManifestFile string
// Contract features.
ContractFeatures smartcontract.PropertyState
// Runtime notifications.
ContractEvents []manifest.Event
@ -211,7 +207,7 @@ func CompileAndSave(src string, o *Options) ([]byte, error) {
}
if o.ManifestFile != "" {
m, err := di.ConvertToManifest(o.ContractFeatures, o.ContractEvents, o.ContractSupportedStandards...)
m, err := di.ConvertToManifest(o.ContractEvents, o.ContractSupportedStandards...)
if err != nil {
return b, fmt.Errorf("failed to convert debug info to manifest: %w", err)
}

View file

@ -409,7 +409,7 @@ func parsePairJSON(data []byte, sep string) (string, string, error) {
// ConvertToManifest converts contract to the manifest.Manifest struct for debugger.
// Note: manifest is taken from the external source, however it can be generated ad-hoc. See #1038.
func (di *DebugInfo) ConvertToManifest(fs smartcontract.PropertyState, events []manifest.Event, supportedStandards ...string) (*manifest.Manifest, error) {
func (di *DebugInfo) ConvertToManifest(events []manifest.Event, supportedStandards ...string) (*manifest.Manifest, error) {
if di.MainPkg == "" {
return nil, errors.New("no Main method was found")
}
@ -425,7 +425,6 @@ func (di *DebugInfo) ConvertToManifest(fs smartcontract.PropertyState, events []
}
result := manifest.NewManifest(di.Hash)
result.Features = fs
if supportedStandards != nil {
result.SupportedStandards = supportedStandards
}

View file

@ -149,7 +149,7 @@ func _deploy(isUpdate bool) {}
}
t.Run("convert to Manifest", func(t *testing.T) {
actual, err := d.ConvertToManifest(smartcontract.HasStorage, nil)
actual, err := d.ConvertToManifest(nil)
require.NoError(t, err)
// note: offsets are hard to predict, so we just take them from the output
expected := &manifest.Manifest{
@ -244,8 +244,7 @@ func _deploy(isUpdate bool) {}
},
Events: []manifest.Event{},
},
Groups: []manifest.Group{},
Features: smartcontract.HasStorage,
Groups: []manifest.Group{},
Permissions: []manifest.Permission{
{
Contract: manifest.PermissionDesc{
@ -266,7 +265,6 @@ func _deploy(isUpdate bool) {}
require.ElementsMatch(t, expected.ABI.Methods, actual.ABI.Methods)
require.Equal(t, expected.ABI.Events, actual.ABI.Events)
require.Equal(t, expected.Groups, actual.Groups)
require.Equal(t, expected.Features, actual.Features)
require.Equal(t, expected.Permissions, actual.Permissions)
require.Equal(t, expected.Trusts, actual.Trusts)
require.Equal(t, expected.SafeMethods, actual.SafeMethods)

View file

@ -101,7 +101,7 @@ func TestAppCall(t *testing.T) {
inner, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(srcInner))
require.NoError(t, err)
m, err := di.ConvertToManifest(smartcontract.NoProperties, nil)
m, err := di.ConvertToManifest(nil)
require.NoError(t, err)
ih := hash.Hash160(inner)

View file

@ -377,9 +377,9 @@ func newDeployTx(t *testing.T, name string) (*transaction.Transaction, []byte) {
t.Logf("contractScript: %x", avm)
script := io.NewBufBinWriter()
m, err := di.ConvertToManifest(smartcontract.HasStorage, nil)
m, err := di.ConvertToManifest(nil)
require.NoError(t, err)
bs, err := m.MarshalJSON()
bs, err := json.Marshal(m)
require.NoError(t, err)
emit.Bytes(script.BinWriter, bs)
emit.Bytes(script.BinWriter, avm)

View file

@ -3,6 +3,7 @@ package core
import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"fmt"
"sort"
@ -75,7 +76,7 @@ func createContractStateFromVM(ic *interop.Context) (*state.Contract, error) {
return nil, errGasLimitExceeded
}
var m manifest.Manifest
err := m.UnmarshalJSON(manifestBytes)
err := json.Unmarshal(manifestBytes, &m)
if err != nil {
return nil, fmt.Errorf("unable to retrieve manifest from stack: %w", err)
}
@ -173,7 +174,7 @@ func contractUpdate(ic *interop.Context) error {
// storage items if needed
if manifestBytes != nil {
var newManifest manifest.Manifest
err := newManifest.UnmarshalJSON(manifestBytes)
err := json.Unmarshal(manifestBytes, &newManifest)
if err != nil {
return fmt.Errorf("unable to retrieve manifest from stack: %w", err)
}
@ -182,15 +183,6 @@ func contractUpdate(ic *interop.Context) error {
if !contract.Manifest.IsValid(contract.ScriptHash()) {
return errors.New("failed to check contract script hash against new manifest")
}
if !contract.HasStorage() {
siMap, err := ic.DAO.GetStorageItems(contract.ID)
if err != nil {
return fmt.Errorf("failed to update manifest: %w", err)
}
if len(siMap) != 0 {
return errors.New("old contract shouldn't have storage")
}
}
if err := ic.DAO.PutContractState(contract); err != nil {
return fmt.Errorf("failed to update manifest: %w", err)
}

View file

@ -18,7 +18,6 @@ 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/crypto/keys"
"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/trigger"
"github.com/nspcc-dev/neo-go/pkg/util"
@ -295,7 +294,6 @@ 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(hash.Hash160(script))
m.Features = smartcontract.HasStorage
contractState := &state.Contract{
Script: script,
Manifest: *m,

View file

@ -2,6 +2,7 @@ package core
import (
"crypto/elliptic"
"encoding/json"
"errors"
"fmt"
"math"
@ -99,15 +100,13 @@ func bcGetBlock(ic *interop.Context) error {
// contractToStackItem converts state.Contract to stackitem.Item
func contractToStackItem(cs *state.Contract) (stackitem.Item, error) {
manifest, err := cs.Manifest.MarshalJSON()
manifest, err := json.Marshal(cs.Manifest)
if err != nil {
return nil, err
}
return stackitem.NewArray([]stackitem.Item{
stackitem.NewByteArray(cs.Script),
stackitem.NewByteArray(manifest),
stackitem.NewBool(cs.HasStorage()),
stackitem.NewBool(cs.IsPayable()),
}), nil
}
@ -365,9 +364,6 @@ func storageGetContextInternal(ic *interop.Context, isReadOnly bool) error {
if err != nil {
return err
}
if !contract.HasStorage() {
return errors.New("contract is not allowed to use storage")
}
sc := &StorageContext{
ID: contract.ID,
ReadOnly: isReadOnly,
@ -464,14 +460,12 @@ func contractDestroy(ic *interop.Context) error {
if err != nil {
return err
}
if cs.HasStorage() {
siMap, err := ic.DAO.GetStorageItems(cs.ID)
if err != nil {
return err
}
for k := range siMap {
_ = ic.DAO.DeleteStorageItem(cs.ID, []byte(k))
}
siMap, err := ic.DAO.GetStorageItems(cs.ID)
if err != nil {
return err
}
for k := range siMap {
_ = ic.DAO.DeleteStorageItem(cs.ID, []byte(k))
}
return nil
}

View file

@ -1,6 +1,7 @@
package core
import (
"encoding/json"
"errors"
"math/big"
"testing"
@ -411,7 +412,6 @@ func getTestContractState() (*state.Contract, *state.Contract) {
script := w.Bytes()
h := hash.Hash160(script)
m := manifest.NewManifest(h)
m.Features = smartcontract.HasStorage
m.ABI.Methods = []manifest.Method{
{
Name: "add",
@ -638,7 +638,7 @@ func TestContractCreate(t *testing.T) {
defer bc.Close()
putArgsOnStack := func() {
manifest, err := cs.Manifest.MarshalJSON()
manifest, err := json.Marshal(cs.Manifest)
require.NoError(t, err)
v.Estack().PushVal(manifest)
v.Estack().PushVal(cs.Script)
@ -672,18 +672,12 @@ func compareContractStates(t *testing.T, expected *state.Contract, actual stacki
act, ok := actual.Value().([]stackitem.Item)
require.True(t, ok)
expectedManifest, err := expected.Manifest.MarshalJSON()
expectedManifest, err := json.Marshal(expected.Manifest)
require.NoError(t, err)
require.Equal(t, 4, len(act))
require.Equal(t, 2, len(act))
require.Equal(t, expected.Script, act[0].Value().([]byte))
require.Equal(t, expectedManifest, act[1].Value().([]byte))
hasstorage, err := act[2].TryBool()
require.NoError(t, err)
ispayable, err := act[3].TryBool()
require.NoError(t, err)
require.Equal(t, expected.HasStorage(), hasstorage)
require.Equal(t, expected.IsPayable(), ispayable)
}
func TestContractUpdate(t *testing.T) {
@ -806,27 +800,7 @@ func TestContractUpdate(t *testing.T) {
Hash: util.Uint160{4, 5, 6},
},
}
manifestBytes, err := manifest.MarshalJSON()
require.NoError(t, err)
putArgsOnStack(stackitem.Null{}, manifestBytes)
require.Error(t, contractUpdate(ic))
})
t.Run("update manifest, old contract shouldn't have storage", func(t *testing.T) {
cs.Manifest.Features |= smartcontract.HasStorage
require.NoError(t, ic.DAO.PutContractState(cs))
require.NoError(t, ic.DAO.PutStorageItem(cs.ID, []byte("my_item"), &state.StorageItem{
Value: []byte{1, 2, 3},
IsConst: false,
}))
v.LoadScriptWithHash([]byte{byte(opcode.RET)}, cs.ScriptHash(), smartcontract.All)
manifest := &manifest.Manifest{
ABI: manifest.ABI{
Hash: cs.ScriptHash(),
},
}
manifestBytes, err := manifest.MarshalJSON()
manifestBytes, err := json.Marshal(manifest)
require.NoError(t, err)
putArgsOnStack(stackitem.Null{}, manifestBytes)
@ -834,15 +808,13 @@ func TestContractUpdate(t *testing.T) {
})
t.Run("update manifest, positive", func(t *testing.T) {
cs.Manifest.Features = smartcontract.NoProperties
require.NoError(t, ic.DAO.PutContractState(cs))
manifest := &manifest.Manifest{
ABI: manifest.ABI{
Hash: cs.ScriptHash(),
},
Features: smartcontract.HasStorage,
}
manifestBytes, err := manifest.MarshalJSON()
manifestBytes, err := json.Marshal(manifest)
require.NoError(t, err)
t.Run("empty script", func(t *testing.T) {
@ -875,9 +847,8 @@ func TestContractUpdate(t *testing.T) {
ABI: manifest.ABI{
Hash: hash.Hash160(newScript),
},
Features: smartcontract.HasStorage,
}
newManifestBytes, err := newManifest.MarshalJSON()
newManifestBytes, err := json.Marshal(newManifest)
require.NoError(t, err)
putArgsOnStack(newScript, newManifestBytes)
@ -910,7 +881,7 @@ func TestContractCreateDeploy(t *testing.T) {
v.GasLimit = -1
putArgs := func(cs *state.Contract) {
rawManifest, err := cs.Manifest.MarshalJSON()
rawManifest, err := json.Marshal(cs.Manifest)
require.NoError(t, err)
v.Estack().PushVal(rawManifest)
v.Estack().PushVal(cs.Script)

View file

@ -69,7 +69,6 @@ func isValidRole(r Role) bool {
func newDesignate() *Designate {
s := &Designate{ContractMD: *interop.NewContractMD(designateName)}
s.ContractID = designateContractID
s.Manifest.Features = smartcontract.HasStorage
desc := newDescriptor("getDesignatedByRole", smartcontract.ArrayType,
manifest.NewParameter("role", smartcontract.IntegerType),

View file

@ -104,7 +104,6 @@ func GetOracleResponseScript() []byte {
func newOracle() *Oracle {
o := &Oracle{ContractMD: *interop.NewContractMD(oracleName)}
o.ContractID = oracleContractID
o.Manifest.Features = smartcontract.HasStorage
desc := newDescriptor("request", smartcontract.VoidType,
manifest.NewParameter("url", smartcontract.StringType),

View file

@ -74,7 +74,6 @@ func newPolicy() *Policy {
p := &Policy{ContractMD: *interop.NewContractMD(policyName)}
p.ContractID = policyContractID
p.Manifest.Features |= smartcontract.HasStorage
desc := newDescriptor("getMaxTransactionsPerBlock", smartcontract.IntegerType)
md := newMethodAndPrice(p.getMaxTransactionsPerBlock, 1000000, smartcontract.AllowStates)

View file

@ -50,7 +50,6 @@ func getOracleContractState(h util.Uint160) *state.Contract {
emit.Opcodes(w.BinWriter, opcode.RET)
m := manifest.NewManifest(h)
m.Features = smartcontract.HasStorage
m.ABI.Methods = []manifest.Method{
{
Name: "requestURL",

View file

@ -6,7 +6,6 @@ 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"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/util"
)
@ -48,16 +47,6 @@ func (cs *Contract) createHash() {
cs.scriptHash = hash.Hash160(cs.Script)
}
// HasStorage checks whether the contract has storage property set.
func (cs *Contract) HasStorage() bool {
return (cs.Manifest.Features & smartcontract.HasStorage) != 0
}
// IsPayable checks whether the contract has payable property set.
func (cs *Contract) IsPayable() bool {
return (cs.Manifest.Features & smartcontract.IsPayable) != 0
}
type contractJSON struct {
ID int32 `json:"id"`
Script []byte `json:"script"`

View file

@ -29,7 +29,6 @@ func TestEncodeDecodeContractState(t *testing.T) {
},
ReturnType: smartcontract.BoolType,
}}
m.Features = smartcontract.HasStorage
contract := &Contract{
ID: 123,
Script: script,

View file

@ -10,10 +10,8 @@ import "github.com/nspcc-dev/neo-go/pkg/interop"
// this package. It's similar in function to the Contract class in the Neo .net
// framework.
type Contract struct {
Script []byte
Manifest []byte
HasStorage bool
IsPayable bool
Script []byte
Manifest []byte
}
// Create creates a new contract using a set of input parameters:

View file

@ -327,14 +327,13 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
}
return c.GetContractStateByHash(hash)
},
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","manifest":{"abi":{"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","methods":[],"events":[]},"groups":[],"features":{"payable":false,"storage":true},"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","manifest":{"abi":{"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","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 {
panic(err)
}
m := manifest.NewManifest(hash.Hash160(script))
m.Features = smartcontract.HasStorage
cs := &state.Contract{
ID: 0,
Script: script,
@ -349,14 +348,13 @@ 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":{"abi":{"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","methods":[],"events":[]},"groups":[],"features":{"payable":false,"storage":true},"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","manifest":{"abi":{"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","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 {
panic(err)
}
m := manifest.NewManifest(hash.Hash160(script))
m.Features = smartcontract.HasStorage
cs := &state.Contract{
ID: 0,
Script: script,
@ -371,14 +369,13 @@ 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":{"abi":{"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","methods":[],"events":[]},"groups":[],"features":{"payable":false,"storage":true},"permissions":null,"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","manifest":{"abi":{"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176","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 {
panic(err)
}
m := manifest.NewManifest(hash.Hash160(script))
m.Features = smartcontract.HasStorage
cs := &state.Contract{
ID: 0,
Script: script,
@ -1466,9 +1463,9 @@ func wrapInitResponse(r *request.In, resp string) string {
}
switch name {
case "neo":
response = `{"id":1,"jsonrpc":"2.0","result":{"id":-1,"script":"DANORU9Ba2d4Cw==","manifest":{"abi":{"hash":"0xde5f57d430d3dece511cf975a8d37848cb9e0525","methods":[{"name":"name","offset":0,"parameters":null,"returntype":"String"},{"name":"symbol","offset":0,"parameters":null,"returntype":"String"},{"name":"decimals","offset":0,"parameters":null,"returntype":"Integer"},{"name":"totalSupply","offset":0,"parameters":null,"returntype":"Integer"},{"name":"balanceOf","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer"},{"name":"transfer","offset":0,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}],"returntype":"Boolean"},{"name":"onPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"postPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"unclaimedGas","offset":0,"parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer"},{"name":"registerCandidate","offset":0,"parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"unregisterCandidate","offset":0,"parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"vote","offset":0,"parameters":[{"name":"account","type":"Hash160"},{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"getCandidates","offset":0,"parameters":null,"returntype":"Array"},{"name":"getСommittee","offset":0,"parameters":null,"returntype":"Array"},{"name":"getNextBlockValidators","offset":0,"parameters":null,"returntype":"Array"},{"name":"getGasPerBlock","offset":0,"parameters":null,"returntype":"Integer"},{"name":"setGasPerBlock","offset":0,"parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Boolean"}],"events":[{"name":"Transfer","parameters":null}]},"groups":[],"features":{"payable":false,"storage":false},"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":["NEP-5"],"trusts":[],"safemethods":["name","symbol","decimals","totalSupply","balanceOf","unclaimedGas","getCandidates","getСommittee","getNextBlockValidators"],"extra":null},"hash":"0xde5f57d430d3dece511cf975a8d37848cb9e0525"}}`
response = `{"id":1,"jsonrpc":"2.0","result":{"id":-1,"script":"DANORU9Ba2d4Cw==","manifest":{"abi":{"hash":"0xde5f57d430d3dece511cf975a8d37848cb9e0525","methods":[{"name":"name","offset":0,"parameters":null,"returntype":"String"},{"name":"symbol","offset":0,"parameters":null,"returntype":"String"},{"name":"decimals","offset":0,"parameters":null,"returntype":"Integer"},{"name":"totalSupply","offset":0,"parameters":null,"returntype":"Integer"},{"name":"balanceOf","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer"},{"name":"transfer","offset":0,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}],"returntype":"Boolean"},{"name":"onPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"postPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"unclaimedGas","offset":0,"parameters":[{"name":"account","type":"Hash160"},{"name":"end","type":"Integer"}],"returntype":"Integer"},{"name":"registerCandidate","offset":0,"parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"unregisterCandidate","offset":0,"parameters":[{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"vote","offset":0,"parameters":[{"name":"account","type":"Hash160"},{"name":"pubkey","type":"PublicKey"}],"returntype":"Boolean"},{"name":"getCandidates","offset":0,"parameters":null,"returntype":"Array"},{"name":"getСommittee","offset":0,"parameters":null,"returntype":"Array"},{"name":"getNextBlockValidators","offset":0,"parameters":null,"returntype":"Array"},{"name":"getGasPerBlock","offset":0,"parameters":null,"returntype":"Integer"},{"name":"setGasPerBlock","offset":0,"parameters":[{"name":"gasPerBlock","type":"Integer"}],"returntype":"Boolean"}],"events":[{"name":"Transfer","parameters":null}]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":["NEP-5"],"trusts":[],"safemethods":["name","symbol","decimals","totalSupply","balanceOf","unclaimedGas","getCandidates","getСommittee","getNextBlockValidators"],"extra":null},"hash":"0xde5f57d430d3dece511cf975a8d37848cb9e0525"}}`
case "gas":
response = `{"id":1,"jsonrpc":"2.0","result":{"id":-2,"script":"DANHQVNBa2d4Cw==","manifest":{"abi":{"hash":"0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc","methods":[{"name":"name","offset":0,"parameters":null,"returntype":"String"},{"name":"symbol","offset":0,"parameters":null,"returntype":"String"},{"name":"decimals","offset":0,"parameters":null,"returntype":"Integer"},{"name":"totalSupply","offset":0,"parameters":null,"returntype":"Integer"},{"name":"balanceOf","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer"},{"name":"transfer","offset":0,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}],"returntype":"Boolean"},{"name":"onPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"postPersist","offset":0,"parameters":null,"returntype":"Void"}],"events":[{"name":"Transfer","parameters":null}]},"groups":[],"features":{"payable":false,"storage":false},"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":["NEP-5"],"trusts":[],"safemethods":["name","symbol","decimals","totalSupply","balanceOf"],"extra":null},"hash":"0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"}}`
response = `{"id":1,"jsonrpc":"2.0","result":{"id":-2,"script":"DANHQVNBa2d4Cw==","manifest":{"abi":{"hash":"0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc","methods":[{"name":"name","offset":0,"parameters":null,"returntype":"String"},{"name":"symbol","offset":0,"parameters":null,"returntype":"String"},{"name":"decimals","offset":0,"parameters":null,"returntype":"Integer"},{"name":"totalSupply","offset":0,"parameters":null,"returntype":"Integer"},{"name":"balanceOf","offset":0,"parameters":[{"name":"account","type":"Hash160"}],"returntype":"Integer"},{"name":"transfer","offset":0,"parameters":[{"name":"from","type":"Hash160"},{"name":"to","type":"Hash160"},{"name":"amount","type":"Integer"}],"returntype":"Boolean"},{"name":"onPersist","offset":0,"parameters":null,"returntype":"Void"},{"name":"postPersist","offset":0,"parameters":null,"returntype":"Void"}],"events":[{"name":"Transfer","parameters":null}]},"groups":[],"permissions":[{"contract":"*","methods":"*"}],"supportedstandards":["NEP-5"],"trusts":[],"safemethods":["name","symbol","decimals","totalSupply","balanceOf"],"extra":null},"hash":"0x668e0c1f9d7b70a99dd9e06eadd4c784d641afbc"}}`
default:
response = resp
}

View file

@ -1,6 +1,7 @@
package request
import (
"encoding/json"
"errors"
"fmt"
"strconv"
@ -19,7 +20,7 @@ import (
// with its metadata.
func CreateDeploymentScript(avm []byte, manif *manifest.Manifest) ([]byte, error) {
script := io.NewBufBinWriter()
rawManifest, err := manif.MarshalJSON()
rawManifest, err := json.Marshal(manif)
if err != nil {
return nil, err
}

View file

@ -1,15 +0,0 @@
package smartcontract
// ContractDetails contains contract metadata.
type ContractDetails struct {
Author string
Email string
Version string
ProjectName string `yaml:"name"`
Description string
HasStorage bool
HasDynamicInvocation bool
IsPayable bool
ReturnType ParamType
Parameters []ParamType
}

View file

@ -66,7 +66,7 @@ func (c *WildStrings) Add(v string) { c.Value = append(c.Value, v) }
func (c *WildUint160s) Add(v util.Uint160) { c.Value = append(c.Value, v) }
// MarshalJSON implements json.Marshaler interface.
func (c *WildStrings) MarshalJSON() ([]byte, error) {
func (c WildStrings) MarshalJSON() ([]byte, error) {
if c.IsWildcard() {
return []byte(`"*"`), nil
}
@ -74,7 +74,7 @@ func (c *WildStrings) MarshalJSON() ([]byte, error) {
}
// MarshalJSON implements json.Marshaler interface.
func (c *WildUint160s) MarshalJSON() ([]byte, error) {
func (c WildUint160s) MarshalJSON() ([]byte, error) {
if c.IsWildcard() {
return []byte(`"*"`), nil
}

View file

@ -4,7 +4,6 @@ import (
"encoding/json"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/util"
)
@ -37,31 +36,18 @@ type ABI struct {
// Manifest represens contract metadata.
type Manifest struct {
// ABI is a contract's ABI.
ABI ABI
ABI ABI `json:"abi"`
// Groups is a set of groups to which a contract belongs.
Groups []Group
// Features is a set of contract's features.
Features smartcontract.PropertyState
Permissions []Permission
Groups []Group `json:"groups"`
Permissions []Permission `json:"permissions"`
// SupportedStandards is a list of standards supported by the contract.
SupportedStandards []string
SupportedStandards []string `json:"supportedstandards"`
// Trusts is a set of hashes to a which contract trusts.
Trusts WildUint160s
Trusts WildUint160s `json:"trusts"`
// SafeMethods is a set of names of safe methods.
SafeMethods WildStrings
SafeMethods WildStrings `json:"safemethods"`
// Extra is an implementation-defined user data.
Extra interface{}
}
type manifestAux struct {
ABI *ABI `json:"abi"`
Groups []Group `json:"groups"`
Features map[string]bool `json:"features"`
Permissions []Permission `json:"permissions"`
SupportedStandards []string `json:"supportedstandards"`
Trusts *WildUint160s `json:"trusts"`
SafeMethods *WildStrings `json:"safemethods"`
Extra interface{} `json:"extra"`
Extra interface{} `json:"extra"`
}
// NewManifest returns new manifest with necessary fields initialized.
@ -73,7 +59,6 @@ func NewManifest(h util.Uint160) *Manifest {
Events: []Event{},
},
Groups: []Group{},
Features: smartcontract.NoProperties,
SupportedStandards: []string{},
}
m.Trusts.Restrict()
@ -127,51 +112,6 @@ func (m *Manifest) IsValid(hash util.Uint160) bool {
return true
}
// MarshalJSON implements json.Marshaler interface.
func (m *Manifest) MarshalJSON() ([]byte, error) {
features := make(map[string]bool)
features["storage"] = m.Features&smartcontract.HasStorage != 0
features["payable"] = m.Features&smartcontract.IsPayable != 0
aux := &manifestAux{
ABI: &m.ABI,
Groups: m.Groups,
Features: features,
Permissions: m.Permissions,
SupportedStandards: m.SupportedStandards,
Trusts: &m.Trusts,
SafeMethods: &m.SafeMethods,
Extra: m.Extra,
}
return json.Marshal(aux)
}
// UnmarshalJSON implements json.Unmarshaler interface.
func (m *Manifest) UnmarshalJSON(data []byte) error {
aux := &manifestAux{
ABI: &m.ABI,
Trusts: &m.Trusts,
SafeMethods: &m.SafeMethods,
}
if err := json.Unmarshal(data, aux); err != nil {
return err
}
if aux.Features["storage"] {
m.Features |= smartcontract.HasStorage
}
if aux.Features["payable"] {
m.Features |= smartcontract.IsPayable
}
m.Groups = aux.Groups
m.Permissions = aux.Permissions
m.SupportedStandards = aux.SupportedStandards
m.Extra = aux.Extra
return nil
}
// EncodeBinary implements io.Serializable.
func (m *Manifest) EncodeBinary(w *io.BinWriter) {
data, err := json.Marshal(m)

View file

@ -13,39 +13,33 @@ import (
// https://github.com/neo-project/neo/blob/master/tests/neo.UnitTests/SmartContract/Manifest/UT_ContractManifest.cs#L10
func TestManifest_MarshalJSON(t *testing.T) {
t.Run("default", func(t *testing.T) {
s := `{"groups":[],"features":{"storage":false,"payable":false},"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":[],"extra":null}`
s := `{"groups":[],"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":[],"extra":null}`
m := testUnmarshalMarshalManifest(t, s)
require.Equal(t, DefaultManifest(util.Uint160{}), m)
})
// this vector is missing from original repo
t.Run("features", func(t *testing.T) {
s := `{"groups":[],"features":{"storage":true,"payable":true},"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":[],"extra":null}`
testUnmarshalMarshalManifest(t, s)
})
t.Run("permissions", func(t *testing.T) {
s := `{"groups":[],"features":{"storage":false,"payable":false},"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"0x0000000000000000000000000000000000000000","methods":["method1","method2"]}],"trusts":[],"safemethods":[],"extra":null}`
s := `{"groups":[],"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"0x0000000000000000000000000000000000000000","methods":["method1","method2"]}],"trusts":[],"safemethods":[],"extra":null}`
testUnmarshalMarshalManifest(t, s)
})
t.Run("safe methods", func(t *testing.T) {
s := `{"groups":[],"features":{"storage":false,"payable":false},"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":["balanceOf"],"extra":null}`
s := `{"groups":[],"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":["balanceOf"],"extra":null}`
testUnmarshalMarshalManifest(t, s)
})
t.Run("trust", func(t *testing.T) {
s := `{"groups":[],"features":{"storage":false,"payable":false},"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":["0x0000000000000000000000000000000000000001"],"safemethods":[],"extra":null}`
s := `{"groups":[],"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":["0x0000000000000000000000000000000000000001"],"safemethods":[],"extra":null}`
testUnmarshalMarshalManifest(t, s)
})
t.Run("groups", func(t *testing.T) {
s := `{"groups":[{"pubkey":"03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c","signature":"QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ=="}],"supportedstandards":[],"features":{"storage":false,"payable":false},"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":[],"extra":null}`
s := `{"groups":[{"pubkey":"03b209fd4f53a7170ea4444e0cb0a6bb6a53c2bd016926989cf85f9b0fba17a70c","signature":"QUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQQ=="}],"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":[],"extra":null}`
testUnmarshalMarshalManifest(t, s)
})
t.Run("extra", func(t *testing.T) {
s := `{"groups":[],"features":{"storage":false,"payable":false},"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":[],"extra":{"key":"value"}}`
s := `{"groups":[],"supportedstandards":[],"abi":{"hash":"0x0000000000000000000000000000000000000000","methods":[],"events":[]},"permissions":[{"contract":"*","methods":"*"}],"trusts":[],"safemethods":[],"extra":{"key":"value"}}`
testUnmarshalMarshalManifest(t, s)
})
}

View file

@ -17,16 +17,6 @@ import (
"github.com/nspcc-dev/neo-go/pkg/util"
)
// PropertyState represents contract properties (flags).
type PropertyState byte
// List of supported properties.
const (
HasStorage PropertyState = 1 << iota
IsPayable PropertyState = 1 << 2
NoProperties = 0
)
// Parameter represents a smart contract parameter.
type Parameter struct {
// Type of the parameter.