Skip to content

Commit 8cccd96

Browse files
author
Tural Devrishev
committed
smartcontract: add support NEP-25
Close #3595. Signed-off-by: Tural Devrishev <[email protected]>
1 parent 3d162dc commit 8cccd96

File tree

25 files changed

+1397
-480
lines changed

25 files changed

+1397
-480
lines changed

cli/smartcontract/generate_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ func TestGenerateRPCBindings_Errors(t *testing.T) {
686686
}
687687

688688
t.Run("event", func(t *testing.T) {
689-
check(t, "invalid6", false, "error during generation: named type `SomeStruct` has two fields with identical resulting binding name `Field`")
689+
check(t, "invalid6", false, "error during generation: named type `invalid6.SomeStruct` has two fields with identical resulting binding name `Field`")
690690
})
691691
t.Run("autogen event", func(t *testing.T) {
692692
check(t, "invalid7", true, "error during generation: named type `invalid7.SomeStruct` has two fields with identical resulting binding name `Field`")

cli/smartcontract/smart_contract.go

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import (
2121
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
2222
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
2323
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
24-
"github.com/nspcc-dev/neo-go/pkg/smartcontract/binding"
2524
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
2625
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
2726
"github.com/nspcc-dev/neo-go/pkg/util"
@@ -419,15 +418,13 @@ func initSmartContract(ctx *cli.Context) error {
419418
SourceURL: "http://example.com/",
420419
SupportedStandards: []string{},
421420
SafeMethods: []string{},
422-
Events: []compiler.HybridEvent{
421+
Events: []manifest.Event{
423422
{
424423
Name: "Hello world!",
425-
Parameters: []compiler.HybridParameter{
424+
Parameters: []manifest.Parameter{
426425
{
427-
Parameter: manifest.Parameter{
428-
Name: "args",
429-
Type: smartcontract.ArrayType,
430-
},
426+
Name: "args",
427+
Type: smartcontract.ArrayType,
431428
},
432429
},
433430
},
@@ -517,7 +514,10 @@ func contractCompile(ctx *cli.Context) error {
517514
NoEventsCheck: ctx.Bool("no-events"),
518515
NoPermissionsCheck: ctx.Bool("no-permissions"),
519516

520-
GuessEventTypes: ctx.Bool("guess-eventtypes"),
517+
CollectedNamedTypes: make(map[string]manifest.ExtendedType),
518+
}
519+
if ctx.Bool("guess-eventtypes") {
520+
o.GuessedNamedTypes = make(map[string]manifest.ExtendedType)
521521
}
522522

523523
if len(confFile) != 0 {
@@ -528,7 +528,6 @@ func contractCompile(ctx *cli.Context) error {
528528
o.Name = conf.Name
529529
o.SourceURL = conf.SourceURL
530530
o.ContractEvents = conf.Events
531-
o.DeclaredNamedTypes = conf.NamedTypes
532531
o.ContractSupportedStandards = conf.SupportedStandards
533532
o.Permissions = make([]manifest.Permission, len(conf.Permissions))
534533
for i := range conf.Permissions {
@@ -760,10 +759,10 @@ type ProjectConfig struct {
760759
SourceURL string
761760
SafeMethods []string
762761
SupportedStandards []string
763-
Events []compiler.HybridEvent
762+
Events []manifest.Event
764763
Permissions []permission
765-
Overloads map[string]string `yaml:"overloads,omitempty"`
766-
NamedTypes map[string]binding.ExtendedType `yaml:"namedtypes,omitempty"`
764+
Overloads map[string]string `yaml:"overloads,omitempty"`
765+
NamedTypes map[string]manifest.ExtendedType `yaml:"namedtypes,omitempty"`
767766
}
768767

769768
func inspect(ctx *cli.Context) error {

cli/smartcontract/testdata/rpcbindings/invalid5/invalid.yml

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ events:
77
extendedtype:
88
base: Array
99
name: invalid5.NamedStruct
10-
namedtypes:
11-
invalid5.NamedStruct:
12-
base: Array
13-
name: invalid5.NamedStruct
14-
fields:
15-
- field: SomeInt
16-
base: Integer
10+
fields:
11+
- field: SomeInt
12+
base: Integer

cli/smartcontract/testdata/rpcbindings/invalid6/invalid.yml

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,3 @@ events:
77
extendedtype:
88
base: Struct
99
name: SomeStruct
10-
namedtypes:
11-
SomeStruct:
12-
base: Struct
13-
name: SomeStruct
14-
fields:
15-
- field: Field
16-
base: Integer
17-
- field: field
18-
base: Integer

cli/smartcontract/testdata/rpcbindings/notifications/config_extended.yml

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ events:
2626
extendedtype:
2727
base: Struct
2828
name: crazyStruct
29+
fields:
30+
- field: I
31+
base: Integer
32+
- field: B
33+
base: Boolean
2934
- name: "SomeArray"
3035
parameters:
3136
- name: a
@@ -43,18 +48,6 @@ events:
4348
extendedtype:
4449
base: Struct
4550
name: simpleStruct
46-
namedtypes:
47-
crazyStruct:
48-
base: Struct
49-
name: crazyStruct
50-
fields:
51-
- field: I
52-
base: Integer
53-
- field: B
54-
base: Boolean
55-
simpleStruct:
56-
base: Struct
57-
name: simpleStruct
58-
fields:
59-
- field: i
60-
base: Integer
51+
fields:
52+
- field: i
53+
base: Integer

cli/smartcontract/testdata/verify.bindings.yml

Lines changed: 0 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -125,111 +125,6 @@ overrides:
125125
syscall4.name: string
126126
toBlockSR: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.BlockSR'
127127
verify: bool
128-
namedtypes:
129-
ledger.Block:
130-
base: Array
131-
name: ledger.Block
132-
fields:
133-
- field: Hash
134-
base: Hash256
135-
- field: Version
136-
base: Integer
137-
- field: PrevHash
138-
base: Hash256
139-
- field: MerkleRoot
140-
base: Hash256
141-
- field: Timestamp
142-
base: Integer
143-
- field: Nonce
144-
base: Integer
145-
- field: Index
146-
base: Integer
147-
- field: NextConsensus
148-
base: Hash160
149-
- field: TransactionsLength
150-
base: Integer
151-
ledger.BlockSR:
152-
base: Array
153-
name: ledger.BlockSR
154-
fields:
155-
- field: Hash
156-
base: Hash256
157-
- field: Version
158-
base: Integer
159-
- field: PrevHash
160-
base: Hash256
161-
- field: MerkleRoot
162-
base: Hash256
163-
- field: Timestamp
164-
base: Integer
165-
- field: Nonce
166-
base: Integer
167-
- field: Index
168-
base: Integer
169-
- field: NextConsensus
170-
base: Hash160
171-
- field: TransactionsLength
172-
base: Integer
173-
- field: PrevStateRoot
174-
base: Hash256
175-
ledger.Transaction:
176-
base: Array
177-
name: ledger.Transaction
178-
fields:
179-
- field: Hash
180-
base: Hash256
181-
- field: Version
182-
base: Integer
183-
- field: Nonce
184-
base: Integer
185-
- field: Sender
186-
base: Hash160
187-
- field: SysFee
188-
base: Integer
189-
- field: NetFee
190-
base: Integer
191-
- field: ValidUntilBlock
192-
base: Integer
193-
- field: Script
194-
base: ByteArray
195-
ledger.TransactionSigner:
196-
base: Array
197-
name: ledger.TransactionSigner
198-
fields:
199-
- field: Account
200-
base: Hash160
201-
- field: Scopes
202-
base: Integer
203-
- field: AllowedContracts
204-
base: Array
205-
value:
206-
base: Hash160
207-
- field: AllowedGroups
208-
base: Array
209-
value:
210-
base: PublicKey
211-
- field: Rules
212-
base: Array
213-
value:
214-
base: Array
215-
name: ledger.WitnessRule
216-
ledger.WitnessCondition:
217-
base: Array
218-
name: ledger.WitnessCondition
219-
fields:
220-
- field: Type
221-
base: Integer
222-
- field: Value
223-
base: Any
224-
ledger.WitnessRule:
225-
base: Array
226-
name: ledger.WitnessRule
227-
fields:
228-
- field: Action
229-
base: Integer
230-
- field: Condition
231-
base: Array
232-
name: ledger.WitnessCondition
233128
types:
234129
call.args:
235130
base: Array

internal/testchain/transaction.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ func NewDeployTx(bc Ledger, name string, sender util.Uint160, r gio.Reader, conf
7878
o.Name = conf.Name
7979
o.SourceURL = conf.SourceURL
8080
o.ContractEvents = conf.Events
81-
o.DeclaredNamedTypes = conf.NamedTypes
8281
o.ContractSupportedStandards = conf.SupportedStandards
8382
o.Permissions = make([]manifest.Permission, len(conf.Permissions))
8483
for i := range conf.Permissions {

pkg/compiler/codegen.go

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -671,8 +671,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
671671
if id.Name != "_" {
672672
if !isMapKeyCheck {
673673
if len(t.Values) == 0 {
674-
c.emitDefault(c.typeOf(t.Type))
674+
typ := c.typeOf(t.Type)
675+
c.collectNamedTypes(typ)
676+
c.emitDefault(typ)
675677
} else if i == 0 || !multiRet {
678+
c.collectNamedTypes(c.typeOf(t.Values[i]))
676679
ast.Walk(c, t.Values[i])
677680
}
678681
}
@@ -725,6 +728,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
725728
}
726729
if !isAssignOp && !isMapKeyCheck {
727730
for i := range n.Rhs {
731+
c.collectNamedTypes(c.typeOf(n.Rhs[i]))
728732
ast.Walk(c, n.Rhs[i])
729733
}
730734
}
@@ -972,6 +976,20 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
972976
t := c.typeOf(n)
973977
switch typ := t.Underlying().(type) {
974978
case *types.Struct:
979+
named, isNamed := t.(*types.Named)
980+
if c.buildInfo.options != nil {
981+
if !isNamed {
982+
name := "unnamed"
983+
if c.buildInfo.options.CollectedNamedTypes != nil {
984+
for c.buildInfo.options.CollectedNamedTypes[name].Name == name {
985+
name = name + "X"
986+
}
987+
_ = c.genStructExtended(typ, name, c.buildInfo.options.CollectedNamedTypes)
988+
}
989+
} else if !isInteropPath(named.String()) {
990+
_ = c.genStructExtended(typ, named.Obj().Pkg().Name()+"."+named.Obj().Name(), c.buildInfo.options.CollectedNamedTypes)
991+
}
992+
}
975993
c.convertStruct(n, false)
976994
case *types.Map:
977995
c.convertMap(n)
@@ -2161,6 +2179,52 @@ func (c *codegen) checkGetMapValueWithOKFlag(expr ast.Expr) bool {
21612179
return ok
21622180
}
21632181

2182+
func (c *codegen) collectNamedTypes(t types.Type) {
2183+
if c.buildInfo.options == nil {
2184+
return
2185+
}
2186+
var (
2187+
seen = make(map[types.Type]bool)
2188+
walk func(types.Type)
2189+
)
2190+
walk = func(tt types.Type) {
2191+
if tt == nil || seen[tt] {
2192+
return
2193+
}
2194+
seen[tt] = true
2195+
2196+
switch x := tt.(type) {
2197+
case *types.Pointer:
2198+
walk(x.Elem())
2199+
case *types.Slice:
2200+
walk(x.Elem())
2201+
case *types.Map:
2202+
walk(x.Key())
2203+
walk(x.Elem())
2204+
case *types.Struct:
2205+
name := "unnamed"
2206+
if c.buildInfo.options.CollectedNamedTypes != nil {
2207+
for c.buildInfo.options.CollectedNamedTypes[name].Name == name {
2208+
name = name + "X"
2209+
}
2210+
_ = c.genStructExtended(x, name, c.buildInfo.options.CollectedNamedTypes)
2211+
}
2212+
for i := range x.NumFields() {
2213+
walk(x.Field(i).Type())
2214+
}
2215+
case *types.Named:
2216+
if typ, ok := x.Underlying().(*types.Struct); ok && !isInteropPath(x.String()) {
2217+
_ = c.genStructExtended(typ, x.Obj().Pkg().Path()+"."+x.Obj().Name(), c.buildInfo.options.CollectedNamedTypes)
2218+
for i := range typ.NumFields() {
2219+
walk(typ.Field(i).Type())
2220+
}
2221+
}
2222+
}
2223+
}
2224+
2225+
walk(t)
2226+
}
2227+
21642228
func (c *codegen) emitGetMapValueWithOKFlag(expr ast.Expr) {
21652229
var (
21662230
idxExpr = expr.(*ast.IndexExpr)

0 commit comments

Comments
 (0)