forked from TrueCloudLab/neoneo-go
Merge pull request #1607 from nspcc-dev/compiler/safe
Set `Safe` flag in emitted manifest
This commit is contained in:
commit
1d529dc5b6
10 changed files with 39 additions and 46 deletions
|
@ -363,6 +363,7 @@ func initSmartContract(ctx *cli.Context) error {
|
||||||
m := ProjectConfig{
|
m := ProjectConfig{
|
||||||
Name: contractName,
|
Name: contractName,
|
||||||
SupportedStandards: []string{},
|
SupportedStandards: []string{},
|
||||||
|
SafeMethods: []string{},
|
||||||
Events: []manifest.Event{
|
Events: []manifest.Event{
|
||||||
{
|
{
|
||||||
Name: "Hello world!",
|
Name: "Hello world!",
|
||||||
|
@ -423,6 +424,7 @@ func contractCompile(ctx *cli.Context) error {
|
||||||
o.Name = conf.Name
|
o.Name = conf.Name
|
||||||
o.ContractEvents = conf.Events
|
o.ContractEvents = conf.Events
|
||||||
o.ContractSupportedStandards = conf.SupportedStandards
|
o.ContractSupportedStandards = conf.SupportedStandards
|
||||||
|
o.SafeMethods = conf.SafeMethods
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := compiler.CompileAndSave(src, o)
|
result, err := compiler.CompileAndSave(src, o)
|
||||||
|
@ -646,6 +648,7 @@ func testInvokeScript(ctx *cli.Context) error {
|
||||||
// ProjectConfig contains project metadata.
|
// ProjectConfig contains project metadata.
|
||||||
type ProjectConfig struct {
|
type ProjectConfig struct {
|
||||||
Name string
|
Name string
|
||||||
|
SafeMethods []string
|
||||||
SupportedStandards []string
|
SupportedStandards []string
|
||||||
Events []manifest.Event
|
Events []manifest.Event
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,6 +59,7 @@ func RuntimeNotify(args []interface{}) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t,
|
require.Equal(t,
|
||||||
`name: testContract
|
`name: testContract
|
||||||
|
safemethods: []
|
||||||
supportedstandards: []
|
supportedstandards: []
|
||||||
events:
|
events:
|
||||||
- name: Hello world!
|
- name: Hello world!
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
name: "My awesome token"
|
name: "My awesome token"
|
||||||
supportedstandards: ["NEP-17"]
|
supportedstandards: ["NEP-17"]
|
||||||
|
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply"]
|
||||||
events:
|
events:
|
||||||
- name: Transfer
|
- name: Transfer
|
||||||
parameters:
|
parameters:
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
name: "Awesome NEO Token"
|
name: "Awesome NEO Token"
|
||||||
supportedstandards: ["NEP-17"]
|
supportedstandards: ["NEP-17"]
|
||||||
|
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply"]
|
||||||
events:
|
events:
|
||||||
- name: Transfer
|
- name: Transfer
|
||||||
parameters:
|
parameters:
|
||||||
|
|
|
@ -62,7 +62,7 @@ func NewDeployTx(name string, sender util.Uint160, r gio.Reader) (*transaction.T
|
||||||
return nil, util.Uint160{}, err
|
return nil, util.Uint160{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
m, err := di.ConvertToManifest(name, nil)
|
m, err := di.ConvertToManifest(&compiler.Options{Name: name})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, util.Uint160{}, err
|
return nil, util.Uint160{}, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,9 @@ type Options struct {
|
||||||
|
|
||||||
// The list of standards supported by the contract.
|
// The list of standards supported by the contract.
|
||||||
ContractSupportedStandards []string
|
ContractSupportedStandards []string
|
||||||
|
|
||||||
|
// SafeMethods contains list of methods which will be marked as safe in manifest.
|
||||||
|
SafeMethods []string
|
||||||
}
|
}
|
||||||
|
|
||||||
type buildInfo struct {
|
type buildInfo struct {
|
||||||
|
@ -219,7 +222,7 @@ func CompileAndSave(src string, o *Options) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.ManifestFile != "" {
|
if o.ManifestFile != "" {
|
||||||
m, err := di.ConvertToManifest(o.Name, o.ContractEvents, o.ContractSupportedStandards...)
|
m, err := di.ConvertToManifest(o)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return b, fmt.Errorf("failed to convert debug info to manifest: %w", err)
|
return b, fmt.Errorf("failed to convert debug info to manifest: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -334,49 +334,27 @@ func (d *DebugParam) UnmarshalJSON(data []byte) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToManifestParameter converts DebugParam to manifest.Parameter
|
// ToManifestParameter converts DebugParam to manifest.Parameter
|
||||||
func (d *DebugParam) ToManifestParameter() (manifest.Parameter, error) {
|
func (d *DebugParam) ToManifestParameter() manifest.Parameter {
|
||||||
return manifest.Parameter{
|
return manifest.Parameter{
|
||||||
Name: d.Name,
|
Name: d.Name,
|
||||||
Type: d.TypeSC,
|
Type: d.TypeSC,
|
||||||
}, nil
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToManifestMethod converts MethodDebugInfo to manifest.Method
|
// ToManifestMethod converts MethodDebugInfo to manifest.Method
|
||||||
func (m *MethodDebugInfo) ToManifestMethod() (manifest.Method, error) {
|
func (m *MethodDebugInfo) ToManifestMethod() manifest.Method {
|
||||||
var (
|
var (
|
||||||
result manifest.Method
|
result manifest.Method
|
||||||
err error
|
|
||||||
)
|
)
|
||||||
parameters := make([]manifest.Parameter, len(m.Parameters))
|
parameters := make([]manifest.Parameter, len(m.Parameters))
|
||||||
for i, p := range m.Parameters {
|
for i, p := range m.Parameters {
|
||||||
parameters[i], err = p.ToManifestParameter()
|
parameters[i] = p.ToManifestParameter()
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result.Name = m.Name.Name
|
result.Name = m.Name.Name
|
||||||
result.Offset = int(m.Range.Start)
|
result.Offset = int(m.Range.Start)
|
||||||
result.Parameters = parameters
|
result.Parameters = parameters
|
||||||
result.ReturnType = m.ReturnTypeSC
|
result.ReturnType = m.ReturnTypeSC
|
||||||
return result, nil
|
return result
|
||||||
}
|
|
||||||
|
|
||||||
// ToManifestEvent converts EventDebugInfo to manifest.Event
|
|
||||||
func (e *EventDebugInfo) ToManifestEvent() (manifest.Event, error) {
|
|
||||||
var (
|
|
||||||
result manifest.Event
|
|
||||||
err error
|
|
||||||
)
|
|
||||||
parameters := make([]manifest.Parameter, len(e.Parameters))
|
|
||||||
for i, p := range e.Parameters {
|
|
||||||
parameters[i], err = p.ToManifestParameter()
|
|
||||||
if err != nil {
|
|
||||||
return result, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result.Name = e.Name
|
|
||||||
result.Parameters = parameters
|
|
||||||
return result, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements json.Marshaler interface.
|
// MarshalJSON implements json.Marshaler interface.
|
||||||
|
@ -425,31 +403,31 @@ func parsePairJSON(data []byte, sep string) (string, string, error) {
|
||||||
|
|
||||||
// ConvertToManifest converts contract to the manifest.Manifest struct for debugger.
|
// 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.
|
// Note: manifest is taken from the external source, however it can be generated ad-hoc. See #1038.
|
||||||
func (di *DebugInfo) ConvertToManifest(name string, events []manifest.Event, supportedStandards ...string) (*manifest.Manifest, error) {
|
func (di *DebugInfo) ConvertToManifest(o *Options) (*manifest.Manifest, error) {
|
||||||
if di.MainPkg == "" {
|
|
||||||
return nil, errors.New("no Main method was found")
|
|
||||||
}
|
|
||||||
methods := make([]manifest.Method, 0)
|
methods := make([]manifest.Method, 0)
|
||||||
for _, method := range di.Methods {
|
for _, method := range di.Methods {
|
||||||
if method.IsExported && method.IsFunction && method.Name.Namespace == di.MainPkg {
|
if method.IsExported && method.IsFunction && method.Name.Namespace == di.MainPkg {
|
||||||
mMethod, err := method.ToManifestMethod()
|
mMethod := method.ToManifestMethod()
|
||||||
if err != nil {
|
for i := range o.SafeMethods {
|
||||||
return nil, err
|
if mMethod.Name == o.SafeMethods[i] {
|
||||||
|
mMethod.Safe = true
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
methods = append(methods, mMethod)
|
methods = append(methods, mMethod)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
result := manifest.NewManifest(name)
|
result := manifest.NewManifest(o.Name)
|
||||||
if supportedStandards != nil {
|
if o.ContractSupportedStandards != nil {
|
||||||
result.SupportedStandards = supportedStandards
|
result.SupportedStandards = o.ContractSupportedStandards
|
||||||
}
|
|
||||||
if events == nil {
|
|
||||||
events = make([]manifest.Event, 0)
|
|
||||||
}
|
}
|
||||||
result.ABI = manifest.ABI{
|
result.ABI = manifest.ABI{
|
||||||
Methods: methods,
|
Methods: methods,
|
||||||
Events: events,
|
Events: o.ContractEvents,
|
||||||
|
}
|
||||||
|
if result.ABI.Events == nil {
|
||||||
|
result.ABI.Events = make([]manifest.Event, 0)
|
||||||
}
|
}
|
||||||
result.Permissions = []manifest.Permission{
|
result.Permissions = []manifest.Permission{
|
||||||
{
|
{
|
||||||
|
|
|
@ -150,7 +150,7 @@ func _deploy(isUpdate bool) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run("convert to Manifest", func(t *testing.T) {
|
t.Run("convert to Manifest", func(t *testing.T) {
|
||||||
actual, err := d.ConvertToManifest("MyCTR", nil)
|
actual, err := d.ConvertToManifest(&Options{Name: "MyCTR", SafeMethods: []string{"methodInt", "methodString"}})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
// note: offsets are hard to predict, so we just take them from the output
|
// note: offsets are hard to predict, so we just take them from the output
|
||||||
expected := &manifest.Manifest{
|
expected := &manifest.Manifest{
|
||||||
|
@ -183,12 +183,14 @@ func _deploy(isUpdate bool) {}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
ReturnType: smartcontract.IntegerType,
|
ReturnType: smartcontract.IntegerType,
|
||||||
|
Safe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "methodString",
|
Name: "methodString",
|
||||||
Offset: 101,
|
Offset: 101,
|
||||||
Parameters: []manifest.Parameter{},
|
Parameters: []manifest.Parameter{},
|
||||||
ReturnType: smartcontract.StringType,
|
ReturnType: smartcontract.StringType,
|
||||||
|
Safe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "methodByteArray",
|
Name: "methodByteArray",
|
||||||
|
|
|
@ -128,7 +128,7 @@ func TestAppCall(t *testing.T) {
|
||||||
}`
|
}`
|
||||||
barCtr, di, err := compiler.CompileWithDebugInfo("bar.go", strings.NewReader(srcDeep))
|
barCtr, di, err := compiler.CompileWithDebugInfo("bar.go", strings.NewReader(srcDeep))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
mBar, err := di.ConvertToManifest("Bar", nil)
|
mBar, err := di.ConvertToManifest(&compiler.Options{Name: "Bar"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
barH := hash.Hash160(barCtr)
|
barH := hash.Hash160(barCtr)
|
||||||
|
@ -160,7 +160,7 @@ func TestAppCall(t *testing.T) {
|
||||||
|
|
||||||
inner, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(srcInner))
|
inner, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(srcInner))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
m, err := di.ConvertToManifest("Foo", nil)
|
m, err := di.ConvertToManifest(&compiler.Options{Name: "Foo"})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
ih := hash.Hash160(inner)
|
ih := hash.Hash160(inner)
|
||||||
|
|
|
@ -14,18 +14,22 @@ var nep17 = &manifest.Manifest{
|
||||||
{Type: smartcontract.Hash160Type},
|
{Type: smartcontract.Hash160Type},
|
||||||
},
|
},
|
||||||
ReturnType: smartcontract.IntegerType,
|
ReturnType: smartcontract.IntegerType,
|
||||||
|
Safe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "decimals",
|
Name: "decimals",
|
||||||
ReturnType: smartcontract.IntegerType,
|
ReturnType: smartcontract.IntegerType,
|
||||||
|
Safe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "symbol",
|
Name: "symbol",
|
||||||
ReturnType: smartcontract.StringType,
|
ReturnType: smartcontract.StringType,
|
||||||
|
Safe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "totalSupply",
|
Name: "totalSupply",
|
||||||
ReturnType: smartcontract.IntegerType,
|
ReturnType: smartcontract.IntegerType,
|
||||||
|
Safe: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "transfer",
|
Name: "transfer",
|
||||||
|
|
Loading…
Reference in a new issue