Merge pull request #1607 from nspcc-dev/compiler/safe

Set `Safe` flag in emitted manifest
This commit is contained in:
Roman Khimov 2020-12-11 14:03:55 +03:00 committed by GitHub
commit 1d529dc5b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 39 additions and 46 deletions

View file

@ -363,6 +363,7 @@ func initSmartContract(ctx *cli.Context) error {
m := ProjectConfig{
Name: contractName,
SupportedStandards: []string{},
SafeMethods: []string{},
Events: []manifest.Event{
{
Name: "Hello world!",
@ -423,6 +424,7 @@ func contractCompile(ctx *cli.Context) error {
o.Name = conf.Name
o.ContractEvents = conf.Events
o.ContractSupportedStandards = conf.SupportedStandards
o.SafeMethods = conf.SafeMethods
}
result, err := compiler.CompileAndSave(src, o)
@ -646,6 +648,7 @@ func testInvokeScript(ctx *cli.Context) error {
// ProjectConfig contains project metadata.
type ProjectConfig struct {
Name string
SafeMethods []string
SupportedStandards []string
Events []manifest.Event
}

View file

@ -59,6 +59,7 @@ func RuntimeNotify(args []interface{}) {
require.NoError(t, err)
require.Equal(t,
`name: testContract
safemethods: []
supportedstandards: []
events:
- name: Hello world!

View file

@ -1,5 +1,6 @@
name: "My awesome token"
supportedstandards: ["NEP-17"]
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply"]
events:
- name: Transfer
parameters:

View file

@ -1,5 +1,6 @@
name: "Awesome NEO Token"
supportedstandards: ["NEP-17"]
safemethods: ["balanceOf", "decimals", "symbol", "totalSupply"]
events:
- name: Transfer
parameters:

View file

@ -62,7 +62,7 @@ func NewDeployTx(name string, sender util.Uint160, r gio.Reader) (*transaction.T
return nil, util.Uint160{}, err
}
m, err := di.ConvertToManifest(name, nil)
m, err := di.ConvertToManifest(&compiler.Options{Name: name})
if err != nil {
return nil, util.Uint160{}, err
}

View file

@ -51,6 +51,9 @@ type Options struct {
// The list of standards supported by the contract.
ContractSupportedStandards []string
// SafeMethods contains list of methods which will be marked as safe in manifest.
SafeMethods []string
}
type buildInfo struct {
@ -219,7 +222,7 @@ func CompileAndSave(src string, o *Options) ([]byte, error) {
}
if o.ManifestFile != "" {
m, err := di.ConvertToManifest(o.Name, o.ContractEvents, o.ContractSupportedStandards...)
m, err := di.ConvertToManifest(o)
if err != nil {
return b, fmt.Errorf("failed to convert debug info to manifest: %w", err)
}

View file

@ -334,49 +334,27 @@ func (d *DebugParam) UnmarshalJSON(data []byte) error {
}
// ToManifestParameter converts DebugParam to manifest.Parameter
func (d *DebugParam) ToManifestParameter() (manifest.Parameter, error) {
func (d *DebugParam) ToManifestParameter() manifest.Parameter {
return manifest.Parameter{
Name: d.Name,
Type: d.TypeSC,
}, nil
}
}
// ToManifestMethod converts MethodDebugInfo to manifest.Method
func (m *MethodDebugInfo) ToManifestMethod() (manifest.Method, error) {
func (m *MethodDebugInfo) ToManifestMethod() manifest.Method {
var (
result manifest.Method
err error
)
parameters := make([]manifest.Parameter, len(m.Parameters))
for i, p := range m.Parameters {
parameters[i], err = p.ToManifestParameter()
if err != nil {
return result, err
}
parameters[i] = p.ToManifestParameter()
}
result.Name = m.Name.Name
result.Offset = int(m.Range.Start)
result.Parameters = parameters
result.ReturnType = m.ReturnTypeSC
return result, nil
}
// 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
return result
}
// 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.
// 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) {
if di.MainPkg == "" {
return nil, errors.New("no Main method was found")
}
func (di *DebugInfo) ConvertToManifest(o *Options) (*manifest.Manifest, error) {
methods := make([]manifest.Method, 0)
for _, method := range di.Methods {
if method.IsExported && method.IsFunction && method.Name.Namespace == di.MainPkg {
mMethod, err := method.ToManifestMethod()
if err != nil {
return nil, err
mMethod := method.ToManifestMethod()
for i := range o.SafeMethods {
if mMethod.Name == o.SafeMethods[i] {
mMethod.Safe = true
break
}
}
methods = append(methods, mMethod)
}
}
result := manifest.NewManifest(name)
if supportedStandards != nil {
result.SupportedStandards = supportedStandards
}
if events == nil {
events = make([]manifest.Event, 0)
result := manifest.NewManifest(o.Name)
if o.ContractSupportedStandards != nil {
result.SupportedStandards = o.ContractSupportedStandards
}
result.ABI = manifest.ABI{
Methods: methods,
Events: events,
Events: o.ContractEvents,
}
if result.ABI.Events == nil {
result.ABI.Events = make([]manifest.Event, 0)
}
result.Permissions = []manifest.Permission{
{

View file

@ -150,7 +150,7 @@ func _deploy(isUpdate bool) {}
}
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)
// note: offsets are hard to predict, so we just take them from the output
expected := &manifest.Manifest{
@ -183,12 +183,14 @@ func _deploy(isUpdate bool) {}
},
},
ReturnType: smartcontract.IntegerType,
Safe: true,
},
{
Name: "methodString",
Offset: 101,
Parameters: []manifest.Parameter{},
ReturnType: smartcontract.StringType,
Safe: true,
},
{
Name: "methodByteArray",

View file

@ -128,7 +128,7 @@ func TestAppCall(t *testing.T) {
}`
barCtr, di, err := compiler.CompileWithDebugInfo("bar.go", strings.NewReader(srcDeep))
require.NoError(t, err)
mBar, err := di.ConvertToManifest("Bar", nil)
mBar, err := di.ConvertToManifest(&compiler.Options{Name: "Bar"})
require.NoError(t, err)
barH := hash.Hash160(barCtr)
@ -160,7 +160,7 @@ func TestAppCall(t *testing.T) {
inner, di, err := compiler.CompileWithDebugInfo("foo.go", strings.NewReader(srcInner))
require.NoError(t, err)
m, err := di.ConvertToManifest("Foo", nil)
m, err := di.ConvertToManifest(&compiler.Options{Name: "Foo"})
require.NoError(t, err)
ih := hash.Hash160(inner)

View file

@ -14,18 +14,22 @@ var nep17 = &manifest.Manifest{
{Type: smartcontract.Hash160Type},
},
ReturnType: smartcontract.IntegerType,
Safe: true,
},
{
Name: "decimals",
ReturnType: smartcontract.IntegerType,
Safe: true,
},
{
Name: "symbol",
ReturnType: smartcontract.StringType,
Safe: true,
},
{
Name: "totalSupply",
ReturnType: smartcontract.IntegerType,
Safe: true,
},
{
Name: "transfer",