forked from TrueCloudLab/neoneo-go
Merge pull request #1704 from nspcc-dev/binary_manifest
core: serialise manifest as stackitem
This commit is contained in:
commit
e4b5b59663
13 changed files with 905 additions and 17 deletions
|
@ -23,7 +23,6 @@ func TestDeployGetUpdateDestroyContract(t *testing.T) {
|
|||
ne, err := nef.NewFile(script)
|
||||
require.NoError(t, err)
|
||||
manif := manifest.NewManifest("Test")
|
||||
require.NoError(t, err)
|
||||
|
||||
h := state.CreateContractHash(sender, ne.Checksum, manif.Name)
|
||||
|
||||
|
|
|
@ -534,7 +534,7 @@ func compareContractStates(t *testing.T, expected *state.Contract, actual stacki
|
|||
act, ok := actual.Value().([]stackitem.Item)
|
||||
require.True(t, ok)
|
||||
|
||||
expectedManifest, err := json.Marshal(expected.Manifest)
|
||||
expectedManifest, err := expected.Manifest.ToStackItem()
|
||||
require.NoError(t, err)
|
||||
expectedNef, err := expected.NEF.Bytes()
|
||||
require.NoError(t, err)
|
||||
|
@ -544,7 +544,7 @@ func compareContractStates(t *testing.T, expected *state.Contract, actual stacki
|
|||
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, expectedNef, act[3].Value().([]byte))
|
||||
require.Equal(t, expectedManifest, act[4].Value().([]byte))
|
||||
require.Equal(t, expectedManifest, act[4])
|
||||
}
|
||||
|
||||
func TestMinimumDeploymentFee(t *testing.T) {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math"
|
||||
"math/big"
|
||||
|
@ -47,11 +46,11 @@ func (c *Contract) EncodeBinary(w *io.BinWriter) {
|
|||
|
||||
// ToStackItem converts state.Contract to stackitem.Item
|
||||
func (c *Contract) ToStackItem() (stackitem.Item, error) {
|
||||
manifest, err := json.Marshal(c.Manifest)
|
||||
rawNef, err := c.NEF.Bytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rawNef, err := c.NEF.Bytes()
|
||||
m, err := c.Manifest.ToStackItem()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -60,7 +59,7 @@ func (c *Contract) ToStackItem() (stackitem.Item, error) {
|
|||
stackitem.Make(c.UpdateCounter),
|
||||
stackitem.NewByteArray(c.Hash.BytesBE()),
|
||||
stackitem.NewByteArray(rawNef),
|
||||
stackitem.NewByteArray(manifest),
|
||||
m,
|
||||
}), nil
|
||||
}
|
||||
|
||||
|
@ -103,11 +102,13 @@ func (c *Contract) FromStackItem(item stackitem.Item) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
bytes, err = arr[4].TryBytes()
|
||||
m := new(manifest.Manifest)
|
||||
err = m.FromStackItem(arr[4])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(bytes, &c.Manifest)
|
||||
c.Manifest = *m
|
||||
return nil
|
||||
}
|
||||
|
||||
// CreateContractHash creates deployed contract hash from transaction sender
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package state
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
|
@ -90,8 +89,7 @@ func TestContractFromStackItem(t *testing.T) {
|
|||
rawNef, _ = nefFile.Bytes()
|
||||
nefItem = stackitem.NewByteArray(rawNef)
|
||||
manifest = manifest.DefaultManifest("stack item")
|
||||
manifestB, _ = json.Marshal(manifest)
|
||||
manifItem = stackitem.Make(manifestB)
|
||||
manifItem, _ = manifest.ToStackItem()
|
||||
|
||||
badCases = []struct {
|
||||
name string
|
||||
|
@ -105,8 +103,8 @@ func TestContractFromStackItem(t *testing.T) {
|
|||
{"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)})},
|
||||
{"manifest is not an array", stackitem.Make([]stackitem.Item{id, counter, chash, nefItem, stackitem.NewByteArray(nil)})},
|
||||
{"manifest is not correct", stackitem.Make([]stackitem.Item{id, counter, chash, nefItem, stackitem.NewArray([]stackitem.Item{stackitem.Make(100500)})})},
|
||||
}
|
||||
)
|
||||
for _, cs := range badCases {
|
||||
|
|
|
@ -330,7 +330,7 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
|
|||
}
|
||||
return c.GetContractStateByHash(hash)
|
||||
},
|
||||
serverResponse: `{"id":1,"jsonrpc":"2.0","result":{"id":0,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"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-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==")
|
||||
if err != nil {
|
||||
|
@ -351,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,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"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-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==")
|
||||
if err != nil {
|
||||
|
@ -372,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,"nef":{"magic":860243278,"compiler":"neo-go-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"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-3.0","script":"VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==","checksum":2512077441},"manifest":{"name":"Test","abi":{"methods":[],"events":[]},"groups":[],"permissions":[],"trusts":[],"supportedstandards":[],"safemethods":[],"extra":null},"hash":"0x1b4357bff5a01bdf2a6581247cf9ed1e24629176"}}`,
|
||||
result: func(c *Client) interface{} {
|
||||
script, err := base64.StdEncoding.DecodeString("VgJXHwIMDWNvbnRyYWN0IGNhbGx4eVMTwEEFB5IWIXhKDANQdXSXJyQAAAAQVUGEGNYNIXJqeRDOeRHOU0FSoUH1IUURQCOPAgAASgwLdG90YWxTdXBwbHmXJxEAAABFAkBCDwBAI28CAABKDAhkZWNpbWFsc5cnDQAAAEUSQCNWAgAASgwEbmFtZZcnEgAAAEUMBFJ1YmxAIzwCAABKDAZzeW1ib2yXJxEAAABFDANSVUJAIyECAABKDAliYWxhbmNlT2aXJ2IAAAAQVUGEGNYNIXN5EM50bMoAFLQnIwAAAAwPaW52YWxpZCBhZGRyZXNzEVVBNtNSBiFFENsgQGtsUEEfLnsHIXUMCWJhbGFuY2VPZmxtUxPAQQUHkhYhRW1AI7IBAABKDAh0cmFuc2ZlcpcnKwEAABBVQYQY1g0hdnkQzncHbwfKABS0JyoAAAAMFmludmFsaWQgJ2Zyb20nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRHOdwhvCMoAFLQnKAAAAAwUaW52YWxpZCAndG8nIGFkZHJlc3MRVUE201IGIUUQ2yBAeRLOdwlvCRC1JyIAAAAMDmludmFsaWQgYW1vdW50EVVBNtNSBiFFENsgQG5vB1BBHy57ByF3Cm8Kbwm1JyYAAAAMEmluc3VmZmljaWVudCBmdW5kcxFVQTbTUgYhRRDbIEBvCm8Jn3cKbm8HbwpTQVKhQfUhbm8IUEEfLnsHIXcLbwtvCZ53C25vCG8LU0FSoUH1IQwIdHJhbnNmZXJvB28IbwlUFMBBBQeSFiFFEUAjewAAAEoMBGluaXSXJ1AAAAAQVUGEGNYNIXcMEFVBh8PSZCF3DQJAQg8Adw5vDG8Nbw5TQVKhQfUhDAh0cmFuc2ZlcgwA2zBvDW8OVBTAQQUHkhYhRRFAIyMAAAAMEWludmFsaWQgb3BlcmF0aW9uQTbTUgY6IwUAAABFQA==")
|
||||
if err != nil {
|
||||
|
|
|
@ -2,10 +2,12 @@ package manifest
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"math"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/io"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -65,6 +67,7 @@ func NewManifest(name string) *Manifest {
|
|||
Events: []Event{},
|
||||
},
|
||||
Groups: []Group{},
|
||||
Permissions: []Permission{},
|
||||
SupportedStandards: []string{},
|
||||
}
|
||||
m.Trusts.Restrict()
|
||||
|
@ -138,3 +141,181 @@ func (m *Manifest) DecodeBinary(r *io.BinReader) {
|
|||
r.Err = err
|
||||
}
|
||||
}
|
||||
|
||||
// ToStackItem converts Manifest to stackitem.Item.
|
||||
func (m *Manifest) ToStackItem() (stackitem.Item, error) {
|
||||
groups := make([]stackitem.Item, len(m.Groups))
|
||||
for i := range m.Groups {
|
||||
groups[i] = m.Groups[i].ToStackItem()
|
||||
}
|
||||
supportedStandards := make([]stackitem.Item, len(m.SupportedStandards))
|
||||
for i := range m.SupportedStandards {
|
||||
supportedStandards[i] = stackitem.Make(m.SupportedStandards[i])
|
||||
}
|
||||
abi := m.ABI.ToStackItem()
|
||||
permissions := make([]stackitem.Item, len(m.Permissions))
|
||||
for i := range m.Permissions {
|
||||
permissions[i] = m.Permissions[i].ToStackItem()
|
||||
}
|
||||
trusts := stackitem.Item(stackitem.Null{})
|
||||
if !m.Trusts.IsWildcard() {
|
||||
tItems := make([]stackitem.Item, len(m.Trusts.Value))
|
||||
for i := range m.Trusts.Value {
|
||||
tItems[i] = stackitem.NewByteArray(m.Trusts.Value[i].BytesBE())
|
||||
}
|
||||
trusts = stackitem.Make(tItems)
|
||||
}
|
||||
extra := stackitem.Make("null")
|
||||
if m.Extra != nil {
|
||||
e, err := json.Marshal(m.Extra)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
extra = stackitem.NewByteArray(e)
|
||||
}
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.Make(m.Name),
|
||||
stackitem.Make(groups),
|
||||
stackitem.Make(supportedStandards),
|
||||
abi,
|
||||
stackitem.Make(permissions),
|
||||
trusts,
|
||||
extra,
|
||||
}), nil
|
||||
}
|
||||
|
||||
// FromStackItem converts stackitem.Item to Manifest.
|
||||
func (m *Manifest) FromStackItem(item stackitem.Item) error {
|
||||
var err error
|
||||
if item.Type() != stackitem.StructT {
|
||||
return errors.New("invalid Manifest stackitem type")
|
||||
}
|
||||
str := item.Value().([]stackitem.Item)
|
||||
if len(str) != 7 {
|
||||
return errors.New("invalid stackitem length")
|
||||
}
|
||||
m.Name, err = stackitem.ToString(str[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if str[1].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid Groups stackitem type")
|
||||
}
|
||||
groups := str[1].Value().([]stackitem.Item)
|
||||
m.Groups = make([]Group, len(groups))
|
||||
for i := range groups {
|
||||
group := new(Group)
|
||||
err := group.FromStackItem(groups[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Groups[i] = *group
|
||||
}
|
||||
if str[2].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid SupportedStandards stackitem type")
|
||||
}
|
||||
supportedStandards := str[2].Value().([]stackitem.Item)
|
||||
m.SupportedStandards = make([]string, len(supportedStandards))
|
||||
for i := range supportedStandards {
|
||||
m.SupportedStandards[i], err = stackitem.ToString(supportedStandards[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
abi := new(ABI)
|
||||
if err := abi.FromStackItem(str[3]); err != nil {
|
||||
return err
|
||||
}
|
||||
m.ABI = *abi
|
||||
if str[4].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid Permissions stackitem type")
|
||||
}
|
||||
permissions := str[4].Value().([]stackitem.Item)
|
||||
m.Permissions = make([]Permission, len(permissions))
|
||||
for i := range permissions {
|
||||
p := new(Permission)
|
||||
if err := p.FromStackItem(permissions[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Permissions[i] = *p
|
||||
}
|
||||
if _, ok := str[5].(stackitem.Null); ok {
|
||||
m.Trusts.Restrict()
|
||||
} else {
|
||||
if str[5].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid Trusts stackitem type")
|
||||
}
|
||||
trusts := str[5].Value().([]stackitem.Item)
|
||||
m.Trusts = WildUint160s{Value: make([]util.Uint160, len(trusts))}
|
||||
for i := range trusts {
|
||||
bytes, err := trusts[i].TryBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Trusts.Value[i], err = util.Uint160DecodeBytesBE(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
extra, err := str[6].TryBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if string(extra) == "null" {
|
||||
return nil
|
||||
}
|
||||
return json.Unmarshal(extra, &m.Extra)
|
||||
}
|
||||
|
||||
// ToStackItem converts ABI to stackitem.Item.
|
||||
func (a *ABI) ToStackItem() stackitem.Item {
|
||||
methods := make([]stackitem.Item, len(a.Methods))
|
||||
for i := range a.Methods {
|
||||
methods[i] = a.Methods[i].ToStackItem()
|
||||
}
|
||||
events := make([]stackitem.Item, len(a.Events))
|
||||
for i := range a.Events {
|
||||
events[i] = a.Events[i].ToStackItem()
|
||||
}
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.Make(methods),
|
||||
stackitem.Make(events),
|
||||
})
|
||||
}
|
||||
|
||||
// FromStackItem converts stackitem.Item to ABI.
|
||||
func (a *ABI) FromStackItem(item stackitem.Item) error {
|
||||
if item.Type() != stackitem.StructT {
|
||||
return errors.New("invalid ABI stackitem type")
|
||||
}
|
||||
str := item.Value().([]stackitem.Item)
|
||||
if len(str) != 2 {
|
||||
return errors.New("invalid ABI stackitem length")
|
||||
}
|
||||
if str[0].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid Methods stackitem type")
|
||||
}
|
||||
methods := str[0].Value().([]stackitem.Item)
|
||||
a.Methods = make([]Method, len(methods))
|
||||
for i := range methods {
|
||||
m := new(Method)
|
||||
if err := m.FromStackItem(methods[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Methods[i] = *m
|
||||
}
|
||||
if str[1].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid Events stackitem type")
|
||||
}
|
||||
events := str[1].Value().([]stackitem.Item)
|
||||
a.Events = make([]Event, len(events))
|
||||
for i := range events {
|
||||
e := new(Event)
|
||||
if err := e.FromStackItem(events[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
a.Events[i] = *e
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -2,10 +2,13 @@ package manifest
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -146,3 +149,184 @@ func TestIsValid(t *testing.T) {
|
|||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestManifestToStackItem(t *testing.T) {
|
||||
check := func(t *testing.T, expected *Manifest) {
|
||||
item, err := expected.ToStackItem()
|
||||
require.NoError(t, err)
|
||||
actual := new(Manifest)
|
||||
require.NoError(t, actual.FromStackItem(item))
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
t.Run("default", func(t *testing.T) {
|
||||
expected := DefaultManifest("manifest")
|
||||
check(t, expected)
|
||||
})
|
||||
|
||||
t.Run("full", func(t *testing.T) {
|
||||
pk, _ := keys.NewPrivateKey()
|
||||
expected := &Manifest{
|
||||
Name: "manifest",
|
||||
ABI: ABI{
|
||||
Methods: []Method{{
|
||||
Name: "method",
|
||||
Offset: 15,
|
||||
Parameters: []Parameter{{
|
||||
Name: "param",
|
||||
Type: smartcontract.StringType,
|
||||
}},
|
||||
ReturnType: smartcontract.BoolType,
|
||||
Safe: true,
|
||||
}},
|
||||
Events: []Event{{
|
||||
Name: "event",
|
||||
Parameters: []Parameter{{
|
||||
Name: "param",
|
||||
Type: smartcontract.BoolType,
|
||||
}},
|
||||
}},
|
||||
},
|
||||
Groups: []Group{{
|
||||
PublicKey: pk.PublicKey(),
|
||||
Signature: []byte{1, 2, 3},
|
||||
}},
|
||||
Permissions: []Permission{*NewPermission(PermissionWildcard)},
|
||||
SupportedStandards: []string{"NEP-17"},
|
||||
Trusts: WildUint160s{
|
||||
Value: []util.Uint160{{1, 2, 3}},
|
||||
},
|
||||
Extra: "some extra data",
|
||||
}
|
||||
check(t, expected)
|
||||
})
|
||||
}
|
||||
|
||||
func TestManifest_FromStackItemErrors(t *testing.T) {
|
||||
errCases := map[string]stackitem.Item{
|
||||
"not a struct": stackitem.NewArray([]stackitem.Item{}),
|
||||
"invalid length": stackitem.NewStruct([]stackitem.Item{}),
|
||||
"invalid name type": stackitem.NewStruct([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid groups type": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid group": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{stackitem.Null{}}), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid supported standards type": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{}), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid supported standard": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{stackitem.Null{}}), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid ABI": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{}), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid Permissions type": stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{})}),
|
||||
stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid permission": stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{})}),
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Null{}}), stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid Trusts type": stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{})}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewInterop(nil), stackitem.Null{}}),
|
||||
"invalid trust": stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{})}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.Null{}}), stackitem.Null{}}),
|
||||
"invalid Uint160 trust": stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{})}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{stackitem.NewByteArray([]byte{1, 2, 3})}), stackitem.Null{}}),
|
||||
"invalid extra type": stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{})}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.Null{}}),
|
||||
"invalid extra": stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{})}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewArray([]stackitem.Item{}),
|
||||
stackitem.NewByteArray([]byte("not a json"))}),
|
||||
}
|
||||
for name, errCase := range errCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
p := new(Manifest)
|
||||
require.Error(t, p.FromStackItem(errCase))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestABI_ToStackItemFromStackItem(t *testing.T) {
|
||||
a := &ABI{
|
||||
Methods: []Method{{
|
||||
Name: "mur",
|
||||
Offset: 5,
|
||||
Parameters: []Parameter{{Name: "p1", Type: smartcontract.BoolType}},
|
||||
ReturnType: smartcontract.StringType,
|
||||
Safe: true,
|
||||
}},
|
||||
Events: []Event{{
|
||||
Name: "mur",
|
||||
Parameters: []Parameter{{Name: "p1", Type: smartcontract.BoolType}},
|
||||
}},
|
||||
}
|
||||
expected := stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte("mur")),
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte("p1")),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(smartcontract.BoolType))),
|
||||
}),
|
||||
}),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(smartcontract.StringType))),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(5))),
|
||||
stackitem.NewBool(true),
|
||||
}),
|
||||
}),
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte("mur")),
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte("p1")),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(smartcontract.BoolType))),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
CheckToFromStackItem(t, a, expected)
|
||||
}
|
||||
|
||||
func TestABI_FromStackItemErrors(t *testing.T) {
|
||||
errCases := map[string]stackitem.Item{
|
||||
"not a struct": stackitem.NewArray([]stackitem.Item{}),
|
||||
"invalid length": stackitem.NewStruct([]stackitem.Item{}),
|
||||
"invalid methods type": stackitem.NewStruct([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Null{}}),
|
||||
"invalid method": stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{stackitem.Null{}}), stackitem.Null{}}),
|
||||
"invalid events type": stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.Null{}}),
|
||||
"invalid event": stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewArray([]stackitem.Item{stackitem.Null{}})}),
|
||||
}
|
||||
for name, errCase := range errCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
p := new(ABI)
|
||||
require.Error(t, p.FromStackItem(errCase))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
package manifest
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"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/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
// Parameter represents smartcontract's parameter's definition.
|
||||
|
@ -84,3 +87,172 @@ func (g *Group) UnmarshalJSON(data []byte) error {
|
|||
g.Signature = aux.Signature
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToStackItem converts Group to stackitem.Item.
|
||||
func (g *Group) ToStackItem() stackitem.Item {
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray(g.PublicKey.Bytes()),
|
||||
stackitem.NewByteArray(g.Signature),
|
||||
})
|
||||
}
|
||||
|
||||
// FromStackItem converts stackitem.Item to Group.
|
||||
func (g *Group) FromStackItem(item stackitem.Item) error {
|
||||
if item.Type() != stackitem.StructT {
|
||||
return errors.New("invalid Group stackitem type")
|
||||
}
|
||||
group := item.Value().([]stackitem.Item)
|
||||
if len(group) != 2 {
|
||||
return errors.New("invalid Group stackitem length")
|
||||
}
|
||||
pKey, err := group[0].TryBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.PublicKey, err = keys.NewPublicKeyFromBytes(pKey, elliptic.P256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sig, err := group[1].TryBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
g.Signature = sig
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToStackItem converts Method to stackitem.Item.
|
||||
func (m *Method) ToStackItem() stackitem.Item {
|
||||
params := make([]stackitem.Item, len(m.Parameters))
|
||||
for i := range m.Parameters {
|
||||
params[i] = m.Parameters[i].ToStackItem()
|
||||
}
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.Make(m.Name),
|
||||
stackitem.Make(params),
|
||||
stackitem.Make(int(m.ReturnType)),
|
||||
stackitem.Make(m.Offset),
|
||||
stackitem.Make(m.Safe),
|
||||
})
|
||||
}
|
||||
|
||||
// FromStackItem converts stackitem.Item to Method.
|
||||
func (m *Method) FromStackItem(item stackitem.Item) error {
|
||||
var err error
|
||||
if item.Type() != stackitem.StructT {
|
||||
return errors.New("invalid Method stackitem type")
|
||||
}
|
||||
method := item.Value().([]stackitem.Item)
|
||||
if len(method) != 5 {
|
||||
return errors.New("invalid Method stackitem length")
|
||||
}
|
||||
m.Name, err = stackitem.ToString(method[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if method[1].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid Params stackitem type")
|
||||
}
|
||||
params := method[1].Value().([]stackitem.Item)
|
||||
m.Parameters = make([]Parameter, len(params))
|
||||
for i := range params {
|
||||
p := new(Parameter)
|
||||
if err := p.FromStackItem(params[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
m.Parameters[i] = *p
|
||||
}
|
||||
rTyp, err := method[2].TryInteger()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.ReturnType, err = smartcontract.ConvertToParamType(int(rTyp.Int64()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
offset, err := method[3].TryInteger()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Offset = int(offset.Int64())
|
||||
safe, err := method[4].TryBool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
m.Safe = safe
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToStackItem converts Parameter to stackitem.Item.
|
||||
func (p *Parameter) ToStackItem() stackitem.Item {
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.Make(p.Name),
|
||||
stackitem.Make(int(p.Type)),
|
||||
})
|
||||
}
|
||||
|
||||
// FromStackItem converts stackitem.Item to Parameter.
|
||||
func (p *Parameter) FromStackItem(item stackitem.Item) error {
|
||||
var err error
|
||||
if item.Type() != stackitem.StructT {
|
||||
return errors.New("invalid Parameter stackitem type")
|
||||
}
|
||||
param := item.Value().([]stackitem.Item)
|
||||
if len(param) != 2 {
|
||||
return errors.New("invalid Parameter stackitem length")
|
||||
}
|
||||
p.Name, err = stackitem.ToString(param[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
typ, err := param[1].TryInteger()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Type, err = smartcontract.ConvertToParamType(int(typ.Int64()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToStackItem converts Event to stackitem.Item.
|
||||
func (e *Event) ToStackItem() stackitem.Item {
|
||||
params := make([]stackitem.Item, len(e.Parameters))
|
||||
for i := range e.Parameters {
|
||||
params[i] = e.Parameters[i].ToStackItem()
|
||||
}
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.Make(e.Name),
|
||||
stackitem.Make(params),
|
||||
})
|
||||
}
|
||||
|
||||
// FromStackItem converts stackitem.Item to Event.
|
||||
func (e *Event) FromStackItem(item stackitem.Item) error {
|
||||
var err error
|
||||
if item.Type() != stackitem.StructT {
|
||||
return errors.New("invalid Event stackitem type")
|
||||
}
|
||||
event := item.Value().([]stackitem.Item)
|
||||
if len(event) != 2 {
|
||||
return errors.New("invalid Event stackitem length")
|
||||
}
|
||||
e.Name, err = stackitem.ToString(event[0])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if event[1].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid Params stackitem type")
|
||||
}
|
||||
params := event[1].Value().([]stackitem.Item)
|
||||
e.Parameters = make([]Parameter, len(params))
|
||||
for i := range params {
|
||||
p := new(Parameter)
|
||||
if err := p.FromStackItem(params[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
e.Parameters[i] = *p
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
144
pkg/smartcontract/manifest/method_test.go
Normal file
144
pkg/smartcontract/manifest/method_test.go
Normal file
|
@ -0,0 +1,144 @@
|
|||
package manifest
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestMethod_ToStackItemFromStackItem(t *testing.T) {
|
||||
m := &Method{
|
||||
Name: "mur",
|
||||
Offset: 5,
|
||||
Parameters: []Parameter{{Name: "p1", Type: smartcontract.BoolType}},
|
||||
ReturnType: smartcontract.StringType,
|
||||
Safe: true,
|
||||
}
|
||||
expected := stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte(m.Name)),
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte(m.Parameters[0].Name)),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(m.Parameters[0].Type))),
|
||||
}),
|
||||
}),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(m.ReturnType))),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(m.Offset))),
|
||||
stackitem.NewBool(m.Safe),
|
||||
})
|
||||
CheckToFromStackItem(t, m, expected)
|
||||
}
|
||||
|
||||
func TestMethod_FromStackItemErrors(t *testing.T) {
|
||||
errCases := map[string]stackitem.Item{
|
||||
"not a struct": stackitem.NewArray([]stackitem.Item{}),
|
||||
"invalid length": stackitem.NewStruct([]stackitem.Item{}),
|
||||
"invalid name type": stackitem.NewStruct([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid parameters type": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid parameter": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{stackitem.NewStruct([]stackitem.Item{})}), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid return type": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{}), stackitem.Null{}, stackitem.Null{}, stackitem.Null{}}),
|
||||
"invalid offset": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{}), stackitem.NewBigInteger(big.NewInt(1)), stackitem.NewInterop(nil), stackitem.Null{}}),
|
||||
"invalid safe": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{}), stackitem.NewBigInteger(big.NewInt(1)), stackitem.NewBigInteger(big.NewInt(5)), stackitem.NewInterop(nil)}),
|
||||
}
|
||||
for name, errCase := range errCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
p := new(Method)
|
||||
require.Error(t, p.FromStackItem(errCase))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestParameter_ToStackItemFromStackItem(t *testing.T) {
|
||||
p := &Parameter{
|
||||
Name: "param",
|
||||
Type: smartcontract.StringType,
|
||||
}
|
||||
expected := stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte(p.Name)),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(p.Type))),
|
||||
})
|
||||
CheckToFromStackItem(t, p, expected)
|
||||
}
|
||||
|
||||
func TestParameter_FromStackItemErrors(t *testing.T) {
|
||||
errCases := map[string]stackitem.Item{
|
||||
"not a struct": stackitem.NewArray([]stackitem.Item{}),
|
||||
"invalid length": stackitem.NewStruct([]stackitem.Item{}),
|
||||
"invalid name type": stackitem.NewStruct([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Null{}}),
|
||||
"invalid type type": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.Null{}}),
|
||||
"invalid type value": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewBigInteger(big.NewInt(-100500))}),
|
||||
}
|
||||
for name, errCase := range errCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
p := new(Parameter)
|
||||
require.Error(t, p.FromStackItem(errCase))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEvent_ToStackItemFromStackItem(t *testing.T) {
|
||||
m := &Event{
|
||||
Name: "mur",
|
||||
Parameters: []Parameter{{Name: "p1", Type: smartcontract.BoolType}},
|
||||
}
|
||||
expected := stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte(m.Name)),
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte(m.Parameters[0].Name)),
|
||||
stackitem.NewBigInteger(big.NewInt(int64(m.Parameters[0].Type))),
|
||||
}),
|
||||
}),
|
||||
})
|
||||
CheckToFromStackItem(t, m, expected)
|
||||
}
|
||||
|
||||
func TestEvent_FromStackItemErrors(t *testing.T) {
|
||||
errCases := map[string]stackitem.Item{
|
||||
"not a struct": stackitem.NewArray([]stackitem.Item{}),
|
||||
"invalid length": stackitem.NewStruct([]stackitem.Item{}),
|
||||
"invalid name type": stackitem.NewStruct([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Null{}}),
|
||||
"invalid parameters type": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.Null{}}),
|
||||
"invalid parameter": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{}), stackitem.NewArray([]stackitem.Item{stackitem.NewStruct([]stackitem.Item{})})}),
|
||||
}
|
||||
for name, errCase := range errCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
p := new(Event)
|
||||
require.Error(t, p.FromStackItem(errCase))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroup_ToStackItemFromStackItem(t *testing.T) {
|
||||
pk, _ := keys.NewPrivateKey()
|
||||
g := &Group{
|
||||
PublicKey: pk.PublicKey(),
|
||||
Signature: []byte{1, 2, 3},
|
||||
}
|
||||
expected := stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray(pk.PublicKey().Bytes()),
|
||||
stackitem.NewByteArray([]byte{1, 2, 3}),
|
||||
})
|
||||
CheckToFromStackItem(t, g, expected)
|
||||
}
|
||||
|
||||
func TestGroup_FromStackItemErrors(t *testing.T) {
|
||||
pk, _ := keys.NewPrivateKey()
|
||||
errCases := map[string]stackitem.Item{
|
||||
"not a struct": stackitem.NewArray([]stackitem.Item{}),
|
||||
"invalid length": stackitem.NewStruct([]stackitem.Item{}),
|
||||
"invalid pub type": stackitem.NewStruct([]stackitem.Item{stackitem.NewInterop(nil), stackitem.Null{}}),
|
||||
"invalid pub bytes": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{1}), stackitem.Null{}}),
|
||||
"invalid sig type": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray(pk.Bytes()), stackitem.NewInterop(nil)}),
|
||||
}
|
||||
for name, errCase := range errCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
p := new(Group)
|
||||
require.Error(t, p.FromStackItem(errCase))
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package manifest
|
||||
|
||||
import (
|
||||
"crypto/elliptic"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
@ -8,6 +9,7 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
)
|
||||
|
||||
// PermissionType represents permission type.
|
||||
|
@ -171,3 +173,91 @@ func (d *PermissionDesc) UnmarshalJSON(data []byte) error {
|
|||
}
|
||||
return errors.New("unknown permission")
|
||||
}
|
||||
|
||||
// ToStackItem converts Permission to stackitem.Item.
|
||||
func (p *Permission) ToStackItem() stackitem.Item {
|
||||
var (
|
||||
contract stackitem.Item
|
||||
methods stackitem.Item
|
||||
)
|
||||
switch p.Contract.Type {
|
||||
case PermissionWildcard:
|
||||
contract = stackitem.Null{}
|
||||
case PermissionHash:
|
||||
contract = stackitem.NewByteArray(p.Contract.Hash().BytesBE())
|
||||
case PermissionGroup:
|
||||
contract = stackitem.NewByteArray(p.Contract.Group().Bytes())
|
||||
}
|
||||
if p.Methods.IsWildcard() {
|
||||
methods = stackitem.Null{}
|
||||
} else {
|
||||
m := make([]stackitem.Item, len(p.Methods.Value))
|
||||
for i := range p.Methods.Value {
|
||||
m[i] = stackitem.Make(p.Methods.Value[i])
|
||||
}
|
||||
methods = stackitem.Make(m)
|
||||
}
|
||||
return stackitem.NewStruct([]stackitem.Item{
|
||||
contract,
|
||||
methods,
|
||||
})
|
||||
}
|
||||
|
||||
// FromStackItem converts stackitem.Item to Permission.
|
||||
func (p *Permission) FromStackItem(item stackitem.Item) error {
|
||||
var err error
|
||||
if item.Type() != stackitem.StructT {
|
||||
return errors.New("invalid Permission stackitem type")
|
||||
}
|
||||
str := item.Value().([]stackitem.Item)
|
||||
if len(str) != 2 {
|
||||
return errors.New("invalid Permission stackitem length")
|
||||
}
|
||||
if _, ok := str[0].(stackitem.Null); ok {
|
||||
p.Contract = PermissionDesc{
|
||||
Type: PermissionWildcard,
|
||||
}
|
||||
} else {
|
||||
byteArr, err := str[0].TryBytes()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch len(byteArr) {
|
||||
case util.Uint160Size:
|
||||
hash, _ := util.Uint160DecodeBytesBE(byteArr)
|
||||
p.Contract = PermissionDesc{
|
||||
Type: PermissionHash,
|
||||
Value: hash,
|
||||
}
|
||||
case 33:
|
||||
pKey, err := keys.NewPublicKeyFromBytes(byteArr, elliptic.P256())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.Contract = PermissionDesc{
|
||||
Type: PermissionGroup,
|
||||
Value: pKey,
|
||||
}
|
||||
default:
|
||||
return errors.New("invalid Contract ByteArray length")
|
||||
}
|
||||
}
|
||||
if _, ok := str[1].(stackitem.Null); ok {
|
||||
p.Methods = WildStrings{Value: nil}
|
||||
} else {
|
||||
if str[1].Type() != stackitem.ArrayT {
|
||||
return errors.New("invalid Methods stackitem type")
|
||||
}
|
||||
methods := str[1].Value().([]stackitem.Item)
|
||||
p.Methods = WildStrings{
|
||||
Value: make([]string, len(methods)),
|
||||
}
|
||||
for i := range methods {
|
||||
p.Methods.Value[i], err = stackitem.ToString(methods[i])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@ package manifest
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/nspcc-dev/neo-go/internal/random"
|
||||
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -92,3 +94,67 @@ func testMarshalUnmarshal(t *testing.T, expected, actual interface{}) {
|
|||
require.NoError(t, json.Unmarshal(data, actual))
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestPermission_ToStackItemFromStackItem(t *testing.T) {
|
||||
t.Run("wildcard", func(t *testing.T) {
|
||||
p := NewPermission(PermissionWildcard)
|
||||
expected := stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.Null{},
|
||||
stackitem.Null{},
|
||||
})
|
||||
CheckToFromStackItem(t, p, expected)
|
||||
})
|
||||
|
||||
t.Run("hash", func(t *testing.T) {
|
||||
p := NewPermission(PermissionHash, util.Uint160{1, 2, 3})
|
||||
p.Methods = WildStrings{Value: []string{"a"}}
|
||||
expected := stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray(util.Uint160{1, 2, 3}.BytesBE()),
|
||||
stackitem.NewArray([]stackitem.Item{
|
||||
stackitem.NewByteArray([]byte("a")),
|
||||
}),
|
||||
})
|
||||
CheckToFromStackItem(t, p, expected)
|
||||
})
|
||||
|
||||
t.Run("group", func(t *testing.T) {
|
||||
pk, _ := keys.NewPrivateKey()
|
||||
p := NewPermission(PermissionGroup, pk.PublicKey())
|
||||
expected := stackitem.NewStruct([]stackitem.Item{
|
||||
stackitem.NewByteArray(pk.PublicKey().Bytes()),
|
||||
stackitem.Null{},
|
||||
})
|
||||
CheckToFromStackItem(t, p, expected)
|
||||
})
|
||||
}
|
||||
|
||||
type Interoperable interface {
|
||||
ToStackItem() stackitem.Item
|
||||
FromStackItem(stackitem.Item) error
|
||||
}
|
||||
|
||||
func CheckToFromStackItem(t *testing.T, source Interoperable, expected stackitem.Item) {
|
||||
actual := source.ToStackItem()
|
||||
require.Equal(t, expected, actual)
|
||||
actualSource := reflect.New(reflect.TypeOf(source).Elem()).Interface().(Interoperable)
|
||||
require.NoError(t, actualSource.FromStackItem(actual))
|
||||
require.Equal(t, source, actualSource)
|
||||
}
|
||||
|
||||
func TestPermission_FromStackItemErrors(t *testing.T) {
|
||||
errCases := map[string]stackitem.Item{
|
||||
"not a struct": stackitem.NewArray([]stackitem.Item{}),
|
||||
"invalid length": stackitem.NewStruct([]stackitem.Item{}),
|
||||
"invalid contract type": stackitem.NewStruct([]stackitem.Item{stackitem.NewArray([]stackitem.Item{}), stackitem.NewBool(false)}),
|
||||
"invalid contract length": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray([]byte{1, 2, 3}), stackitem.NewBool(false)}),
|
||||
"invalid contract pubkey": stackitem.NewStruct([]stackitem.Item{stackitem.NewByteArray(make([]byte, 33)), stackitem.NewBool(false)}),
|
||||
"invalid methods type": stackitem.NewStruct([]stackitem.Item{stackitem.Null{}, stackitem.NewBool(false)}),
|
||||
"invalid method name": stackitem.NewStruct([]stackitem.Item{stackitem.Null{}, stackitem.NewArray([]stackitem.Item{stackitem.NewArray([]stackitem.Item{})})}),
|
||||
}
|
||||
for name, errCase := range errCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
p := new(Permission)
|
||||
require.Error(t, p.FromStackItem(errCase))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,24 @@ const (
|
|||
VoidType ParamType = 0xff
|
||||
)
|
||||
|
||||
// validParamTypes contains a map of known ParamTypes
|
||||
var validParamTypes = map[ParamType]bool{
|
||||
UnknownType: true,
|
||||
AnyType: true,
|
||||
BoolType: true,
|
||||
IntegerType: true,
|
||||
ByteArrayType: true,
|
||||
StringType: true,
|
||||
Hash160Type: true,
|
||||
Hash256Type: true,
|
||||
PublicKeyType: true,
|
||||
SignatureType: true,
|
||||
ArrayType: true,
|
||||
MapType: true,
|
||||
InteropInterfaceType: true,
|
||||
VoidType: true,
|
||||
}
|
||||
|
||||
// String implements the stringer interface.
|
||||
func (pt ParamType) String() string {
|
||||
switch pt {
|
||||
|
@ -268,3 +286,11 @@ func inferParamType(val string) ParamType {
|
|||
// Anything can be a string.
|
||||
return StringType
|
||||
}
|
||||
|
||||
// ConvertToParamType converts provided value to parameter type if it's a valid type.
|
||||
func ConvertToParamType(val int) (ParamType, error) {
|
||||
if validParamTypes[ParamType(val)] {
|
||||
return ParamType(val), nil
|
||||
}
|
||||
return UnknownType, errors.New("unknown parameter type")
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseParamType(t *testing.T) {
|
||||
|
@ -315,3 +316,29 @@ func mustHex(s string) []byte {
|
|||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestConvertToParamType(t *testing.T) {
|
||||
for _, expected := range []ParamType{
|
||||
UnknownType,
|
||||
AnyType,
|
||||
BoolType,
|
||||
IntegerType,
|
||||
ByteArrayType,
|
||||
StringType,
|
||||
Hash160Type,
|
||||
Hash256Type,
|
||||
PublicKeyType,
|
||||
SignatureType,
|
||||
ArrayType,
|
||||
MapType,
|
||||
InteropInterfaceType,
|
||||
VoidType,
|
||||
} {
|
||||
actual, err := ConvertToParamType(int(expected))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, actual)
|
||||
}
|
||||
|
||||
_, err := ConvertToParamType(0x01)
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue