smartcontract: support dynamic contract hash for bindings

Allow dynamic contract hash for contract bindings.

Close #3007

Signed-off-by: Ekaterina Pavlova <ekt@morphbits.io>
This commit is contained in:
Ekaterina Pavlova 2024-04-09 01:02:05 +03:00
parent 8913542f93
commit c5dbecb754
5 changed files with 523 additions and 39 deletions

View file

@ -25,6 +25,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/neorpc/result" "github.com/nspcc-dev/neo-go/pkg/neorpc/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest" "github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef" "github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/trigger"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem" "github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
"github.com/nspcc-dev/neo-go/pkg/vm/vmstate" "github.com/nspcc-dev/neo-go/pkg/vm/vmstate"
@ -145,18 +146,7 @@ func Blocks() []*alias.Block {
cmd = append(cmd, "--in", ctrPath, "--bindings", bindingsPath) cmd = append(cmd, "--in", ctrPath, "--bindings", bindingsPath)
// Replace `pkg/interop` in go.mod to avoid getting an actual module version. // Replace `pkg/interop` in go.mod to avoid getting an actual module version.
goMod := filepath.Join(ctrPath, "go.mod") require.NoError(t, updateGoMod(ctrPath, "myimport.com/testcontract", "../../pkg/interop"))
data, err := os.ReadFile(goMod)
require.NoError(t, err)
i := bytes.IndexByte(data, '\n')
data = append([]byte("module myimport.com/testcontract"), data[i:]...)
wd, err := os.Getwd()
require.NoError(t, err)
data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...)
data = append(data, filepath.Join(wd, "../../pkg/interop")...)
require.NoError(t, os.WriteFile(goMod, data, os.ModePerm))
cmd = append(cmd, "--config", cfgPath, cmd = append(cmd, "--config", cfgPath,
"--out", filepath.Join(tmpDir, "out.nef"), "--out", filepath.Join(tmpDir, "out.nef"),
@ -176,7 +166,7 @@ func Blocks() []*alias.Block {
bs, err := os.ReadFile(outPath) bs, err := os.ReadFile(outPath)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]; DO NOT EDIT. require.Equal(t, `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
// Package testcontract contains wrappers for testcontract contract. // Package testcontract contains wrappers for testcontract contract.
package testcontract package testcontract
@ -213,6 +203,84 @@ func ToMap(a []testcontract.MyPair) map[int]string {
`, string(bs)) `, string(bs))
} }
// updateGoMod updates the go.mod file located in the specified directory.
// It sets the module name and replaces the neo-go interop package path with
// the provided one to avoid getting an actual module version.
func updateGoMod(dir, moduleName, neoGoPath string) error {
goModPath := filepath.Join(dir, "go.mod")
data, err := os.ReadFile(goModPath)
if err != nil {
return fmt.Errorf("failed to read go.mod: %w", err)
}
i := bytes.IndexByte(data, '\n')
if i == -1 {
return fmt.Errorf("unexpected go.mod format")
}
updatedData := append([]byte("module "+moduleName), data[i:]...)
wd, err := os.Getwd()
if err != nil {
return fmt.Errorf("failed to get working directory: %w", err)
}
replacementPath := filepath.Join(wd, neoGoPath)
updatedData = append(updatedData, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "+replacementPath+" \n"...)
if err := os.WriteFile(goModPath, updatedData, os.ModePerm); err != nil {
return fmt.Errorf("failed to write updated go.mod: %w", err)
}
return nil
}
func TestDynamicWrapper(t *testing.T) {
// For proper contract init. The actual version as it will be replaced.
smartcontract.ModVersion = "v0.0.0"
tmpDir := t.TempDir()
e := testcli.NewExecutor(t, true)
ctrPath := "../smartcontract/testdata"
verifyHash := testcli.DeployContract(t, e, filepath.Join(ctrPath, "verify.go"), filepath.Join(ctrPath, "verify.yml"), testcli.ValidatorWallet, testcli.ValidatorAddr, testcli.ValidatorPass)
helperContract := `package testcontract
import (
"github.com/nspcc-dev/neo-go/pkg/interop"
verify "myimport.com/testcontract/bindings"
)
func CallVerifyContract(h interop.Hash160) bool{
contractInstance := verify.NewContract(h)
return contractInstance.Verify()
}`
helperDir := filepath.Join(tmpDir, "helper")
e.Run(t, "neo-go", "contract", "init", "--name", helperDir)
require.NoError(t, updateGoMod(helperDir, "myimport.com/testcontract", "../../pkg/interop"))
require.NoError(t, os.WriteFile(filepath.Join(helperDir, "main.go"), []byte(helperContract), os.ModePerm))
require.NoError(t, os.Mkdir(filepath.Join(helperDir, "bindings"), os.ModePerm))
e.Run(t, "neo-go", "contract", "generate-wrapper",
"--config", filepath.Join(ctrPath, "verify.bindings.yml"), "--manifest", filepath.Join(ctrPath, "verify.manifest.json"),
"--out", filepath.Join(helperDir, "bindings", "testdata.go"))
e.Run(t, "neo-go", "contract", "compile", "--in", filepath.Join(helperDir, "main.go"), "--config", filepath.Join(helperDir, "neo-go.yml"))
helperHash := testcli.DeployContract(t, e, filepath.Join(helperDir, "main.go"), filepath.Join(helperDir, "neo-go.yml"), testcli.ValidatorWallet, testcli.ValidatorAddr, testcli.ValidatorPass)
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://"+e.RPC.Addresses()[0],
"--wallet", testcli.ValidatorWallet, "--address", testcli.ValidatorAddr, "--force", "--await", helperHash.StringLE(), "callVerifyContract", verifyHash.StringLE())
tx, _ := e.CheckTxPersisted(t, "Sent invocation transaction ")
aer, err := e.Chain.GetAppExecResults(tx.Hash(), trigger.Application)
require.NoError(t, err)
require.Equal(t, aer[0].Stack[0].Value().(bool), true)
}
func TestContractInitAndCompile(t *testing.T) { func TestContractInitAndCompile(t *testing.T) {
// For proper contract init. The actual version as it will be replaced. // For proper contract init. The actual version as it will be replaced.
smartcontract.ModVersion = "v0.0.0" smartcontract.ModVersion = "v0.0.0"
@ -265,15 +333,7 @@ func TestContractInitAndCompile(t *testing.T) {
}) })
// Replace `pkg/interop` in go.mod to avoid getting an actual module version. // Replace `pkg/interop` in go.mod to avoid getting an actual module version.
goMod := filepath.Join(ctrPath, "go.mod") require.NoError(t, updateGoMod(ctrPath, "myimport.com/testcontract", "../../pkg/interop"))
data, err := os.ReadFile(goMod)
require.NoError(t, err)
wd, err := os.Getwd()
require.NoError(t, err)
data = append(data, "\nreplace github.com/nspcc-dev/neo-go/pkg/interop => "...)
data = append(data, filepath.Join(wd, "../../pkg/interop")...)
require.NoError(t, os.WriteFile(goMod, data, os.ModePerm))
cmd = append(cmd, "--config", cfgPath) cmd = append(cmd, "--config", cfgPath)

View file

@ -30,17 +30,22 @@ var generatorFlags = []cli.Flag{
}, },
cli.StringFlag{ cli.StringFlag{
Name: "hash", Name: "hash",
Usage: "Smart-contract hash", Usage: "Smart-contract hash. If not passed, the wrapper will be designed for dynamic hash usage",
}, },
} }
var generateWrapperCmd = cli.Command{ var generateWrapperCmd = cli.Command{
Name: "generate-wrapper", Name: "generate-wrapper",
Usage: "generate wrapper to use in other contracts", Usage: "generate wrapper to use in other contracts",
UsageText: "neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]", UsageText: "neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]",
Description: ``, Description: `Generates a Go wrapper to use it in other smart contracts. If the
Action: contractGenerateWrapper, --hash flag is provided, CALLT instruction is used for the target contract
Flags: generatorFlags, invocation as an optimization of the wrapper contract code. If omitted, the
generated wrapper will be designed for dynamic hash usage, allowing
the hash to be specified at runtime.
`,
Action: contractGenerateWrapper,
Flags: generatorFlags,
} }
var generateRPCWrapperCmd = cli.Command{ var generateRPCWrapperCmd = cli.Command{
@ -52,15 +57,15 @@ var generateRPCWrapperCmd = cli.Command{
} }
func contractGenerateWrapper(ctx *cli.Context) error { func contractGenerateWrapper(ctx *cli.Context) error {
return contractGenerateSomething(ctx, binding.Generate, false) return contractGenerateSomething(ctx, binding.Generate)
} }
func contractGenerateRPCWrapper(ctx *cli.Context) error { func contractGenerateRPCWrapper(ctx *cli.Context) error {
return contractGenerateSomething(ctx, rpcbinding.Generate, true) return contractGenerateSomething(ctx, rpcbinding.Generate)
} }
// contractGenerateSomething reads generator parameters and calls the given callback. // contractGenerateSomething reads generator parameters and calls the given callback.
func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error, allowEmptyHash bool) error { func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error) error {
if err := cmdargs.EnsureNone(ctx); err != nil { if err := cmdargs.EnsureNone(ctx); err != nil {
return err return err
} }
@ -73,8 +78,6 @@ func contractGenerateSomething(ctx *cli.Context, cb func(binding.Config) error,
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1) return cli.NewExitError(fmt.Errorf("invalid contract hash: %w", err), 1)
} }
} else if !allowEmptyHash {
return cli.NewExitError("contract hash must be provided via --hash flag", 1)
} }
m, _, err := readManifest(ctx.String("manifest"), h) m, _, err := readManifest(ctx.String("manifest"), h)
if err != nil { if err != nil {

View file

@ -151,7 +151,7 @@ callflags:
"--hash", h.StringLE(), "--hash", h.StringLE(),
})) }))
const expected = `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]; DO NOT EDIT. const expected = `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
// Package wrapper contains wrappers for MyContract contract. // Package wrapper contains wrappers for MyContract contract.
package wrapper package wrapper
@ -233,6 +233,99 @@ func MyFunc(in map[int]mycontract.Input) []mycontract.Output {
data, err := os.ReadFile(outFile) data, err := os.ReadFile(outFile)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, expected, string(data)) require.Equal(t, expected, string(data))
require.NoError(t, app.Run([]string{"", "generate-wrapper",
"--manifest", manifestFile,
"--config", cfgPath,
"--out", outFile,
}))
expectedWithDynamicHash := `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
// Package wrapper contains wrappers for MyContract contract.
package wrapper
import (
"github.com/heyitsme/mycontract"
"github.com/nspcc-dev/neo-go/pkg/interop"
"github.com/nspcc-dev/neo-go/pkg/interop/contract"
"github.com/nspcc-dev/neo-go/pkg/interop/iterator"
"github.com/nspcc-dev/neo-go/pkg/interop/native/ledger"
"github.com/nspcc-dev/neo-go/pkg/interop/storage"
)
// Contract represents the MyContract smart contract.
type Contract struct {
Hash interop.Hash160
}
// NewContract returns a new Contract instance with the specified hash.
func NewContract(hash interop.Hash160) Contract {
return Contract{Hash: hash}
}
// Sum invokes ` + "`sum`" + ` method of contract.
func (c Contract) Sum(first int, second int) int {
return contract.Call(c.Hash, "sum", contract.All, first, second).(int)
}
// Sum2 invokes ` + "`sum`" + ` method of contract.
func (c Contract) Sum2(first int, second int, third int) int {
return contract.Call(c.Hash, "sum", contract.All, first, second, third).(int)
}
// Sum3 invokes ` + "`sum3`" + ` method of contract.
func (c Contract) Sum3() int {
return contract.Call(c.Hash, "sum3", contract.ReadOnly).(int)
}
// Zum invokes ` + "`zum`" + ` method of contract.
func (c Contract) Zum(typev int, typev_ int, funcv int) int {
return contract.Call(c.Hash, "zum", contract.All, typev, typev_, funcv).(int)
}
// JustExecute invokes ` + "`justExecute`" + ` method of contract.
func (c Contract) JustExecute(arr []any) {
contract.Call(c.Hash, "justExecute", contract.All, arr)
}
// GetPublicKey invokes ` + "`getPublicKey`" + ` method of contract.
func (c Contract) GetPublicKey() interop.PublicKey {
return contract.Call(c.Hash, "getPublicKey", contract.All).(interop.PublicKey)
}
// OtherTypes invokes ` + "`otherTypes`" + ` method of contract.
func (c Contract) OtherTypes(ctr interop.Hash160, tx interop.Hash256, sig interop.Signature, data any) bool {
return contract.Call(c.Hash, "otherTypes", contract.All, ctr, tx, sig, data).(bool)
}
// SearchStorage invokes ` + "`searchStorage`" + ` method of contract.
func (c Contract) SearchStorage(ctx storage.Context) iterator.Iterator {
return contract.Call(c.Hash, "searchStorage", contract.All, ctx).(iterator.Iterator)
}
// GetFromMap invokes ` + "`getFromMap`" + ` method of contract.
func (c Contract) GetFromMap(intMap map[string]int, indices []string) []int {
return contract.Call(c.Hash, "getFromMap", contract.All, intMap, indices).([]int)
}
// DoSomething invokes ` + "`doSomething`" + ` method of contract.
func (c Contract) DoSomething(bytes []byte, str string) any {
return contract.Call(c.Hash, "doSomething", contract.ReadStates, bytes, str).(any)
}
// GetBlockWrapper invokes ` + "`getBlockWrapper`" + ` method of contract.
func (c Contract) GetBlockWrapper() ledger.Block {
return contract.Call(c.Hash, "getBlockWrapper", contract.All).(ledger.Block)
}
// MyFunc invokes ` + "`myFunc`" + ` method of contract.
func (c Contract) MyFunc(in map[int]mycontract.Input) []mycontract.Output {
return contract.Call(c.Hash, "myFunc", contract.All, in).([]mycontract.Output)
}
`
data, err = os.ReadFile(outFile)
require.NoError(t, err)
require.Equal(t, expectedWithDynamicHash, string(data))
} }
func TestGenerateValidPackageName(t *testing.T) { func TestGenerateValidPackageName(t *testing.T) {
@ -267,7 +360,7 @@ func TestGenerateValidPackageName(t *testing.T) {
data, err := os.ReadFile(outFile) data, err := os.ReadFile(outFile)
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]; DO NOT EDIT. require.Equal(t, `// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
// Package myspacecontract contains wrappers for My space contract contract. // Package myspacecontract contains wrappers for My space contract contract.
package myspacecontract package myspacecontract

297
cli/smartcontract/testdata/verify.bindings.yml vendored Executable file
View file

@ -0,0 +1,297 @@
package: testdata
hash: "0x0000000000000000000000000000000000000000"
overrides:
burnGas.gas: int
call: any
call.args: '[]any'
call.f: any
call.method: string
call.scriptHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
callWithToken: any
callWithToken.args: '[]any'
callWithToken.flags: int
callWithToken.method: string
callWithToken.scriptHash: string
callWithTokenNoRet.args: '[]any'
callWithTokenNoRet.flags: int
callWithTokenNoRet.method: string
callWithTokenNoRet.scriptHash: string
checkWitness: bool
checkWitness.hashOrKey: '[]byte'
createMultisigAccount: '[]byte'
createMultisigAccount.m: int
createMultisigAccount.pubs: '[]github.com/nspcc-dev/neo-go/pkg/interop.PublicKey'
createStandardAccount: '[]byte'
createStandardAccount.pub: github.com/nspcc-dev/neo-go/pkg/interop.PublicKey
currentHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
currentIndex: int
currentSigners: '[]github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.TransactionSigner'
equals: bool
equals.b: any
gasLeft: int
getAddressVersion: int
getBlock: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.Block'
getBlock.indexOrHash: any
getCallFlags: any
getCallingScriptHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
getEntryScriptHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
getExecutingScriptHash: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
getInvocationCounter: int
getNetwork: int
getNotifications: '[][]any'
getNotifications.h: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
getRandom: int
getScriptContainer: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.Transaction'
getTime: int
getTransaction: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.Transaction'
getTransaction.hash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
getTransactionFromBlock: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.Transaction'
getTransactionFromBlock.indexOrHash: any
getTransactionFromBlock.txIndex: int
getTransactionHeight: int
getTransactionHeight.hash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
getTransactionSigners: '[]github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.TransactionSigner'
getTransactionSigners.hash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
getTransactionVMState: int
getTransactionVMState.hash: github.com/nspcc-dev/neo-go/pkg/interop.Hash256
getTrigger: int
loadScript: any
loadScript.args: '[]any'
loadScript.f: any
loadScript.script: '[]byte'
log.message: string
notify.args: '[]any'
notify.name: string
onNEP11Payment.amount: int
onNEP11Payment.data: any
onNEP11Payment.from: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
onNEP11Payment.token: '[]byte'
onNEP17Payment.amount: int
onNEP17Payment.data: any
onNEP17Payment.from: github.com/nspcc-dev/neo-go/pkg/interop.Hash160
opcode0NoReturn.op: string
opcode1: any
opcode1NoReturn.arg: any
opcode1NoReturn.op: string
opcode1.arg: any
opcode1.op: string
opcode2: any
opcode2NoReturn.arg1: any
opcode2NoReturn.arg2: any
opcode2NoReturn.op: string
opcode2.arg1: any
opcode2.arg2: any
opcode2.op: string
opcode3: any
opcode3.arg1: any
opcode3.arg2: any
opcode3.arg3: any
opcode3.op: string
platform: '[]byte'
syscall0: any
syscall0NoReturn.name: string
syscall0.name: string
syscall1: any
syscall1NoReturn.arg: any
syscall1NoReturn.name: string
syscall1.arg: any
syscall1.name: string
syscall2: any
syscall2NoReturn.arg1: any
syscall2NoReturn.arg2: any
syscall2NoReturn.name: string
syscall2.arg1: any
syscall2.arg2: any
syscall2.name: string
syscall3: any
syscall3NoReturn.arg1: any
syscall3NoReturn.arg2: any
syscall3NoReturn.arg3: any
syscall3NoReturn.name: string
syscall3.arg1: any
syscall3.arg2: any
syscall3.arg3: any
syscall3.name: string
syscall4: any
syscall4NoReturn.arg1: any
syscall4NoReturn.arg2: any
syscall4NoReturn.arg3: any
syscall4NoReturn.arg4: any
syscall4NoReturn.name: string
syscall4.arg1: any
syscall4.arg2: any
syscall4.arg3: any
syscall4.arg4: any
syscall4.name: string
toBlockSR: '*github.com/nspcc-dev/neo-go/pkg/interop/native/ledger.BlockSR'
verify: bool
namedtypes:
ledger.Block:
base: Array
name: ledger.Block
fields:
- field: Hash
base: Hash256
- field: Version
base: Integer
- field: PrevHash
base: Hash256
- field: MerkleRoot
base: Hash256
- field: Timestamp
base: Integer
- field: Nonce
base: Integer
- field: Index
base: Integer
- field: NextConsensus
base: Hash160
- field: TransactionsLength
base: Integer
ledger.BlockSR:
base: Array
name: ledger.BlockSR
fields:
- field: Hash
base: Hash256
- field: Version
base: Integer
- field: PrevHash
base: Hash256
- field: MerkleRoot
base: Hash256
- field: Timestamp
base: Integer
- field: Nonce
base: Integer
- field: Index
base: Integer
- field: NextConsensus
base: Hash160
- field: TransactionsLength
base: Integer
- field: PrevStateRoot
base: Hash256
ledger.Transaction:
base: Array
name: ledger.Transaction
fields:
- field: Hash
base: Hash256
- field: Version
base: Integer
- field: Nonce
base: Integer
- field: Sender
base: Hash160
- field: SysFee
base: Integer
- field: NetFee
base: Integer
- field: ValidUntilBlock
base: Integer
- field: Script
base: ByteArray
ledger.TransactionSigner:
base: Array
name: ledger.TransactionSigner
fields:
- field: Account
base: Hash160
- field: Scopes
base: Integer
- field: AllowedContracts
base: Array
value:
base: Hash160
- field: AllowedGroups
base: Array
value:
base: PublicKey
- field: Rules
base: Array
value:
base: Array
name: ledger.WitnessRule
ledger.WitnessCondition:
base: Array
name: ledger.WitnessCondition
fields:
- field: Type
base: Integer
- field: Value
base: Any
ledger.WitnessRule:
base: Array
name: ledger.WitnessRule
fields:
- field: Action
base: Integer
- field: Condition
base: Array
name: ledger.WitnessCondition
types:
call.args:
base: Array
value:
base: Any
call.f:
base: InteropInterface
interface: iterator
callWithToken.args:
base: Array
value:
base: Any
callWithTokenNoRet.args:
base: Array
value:
base: Any
createMultisigAccount.pubs:
base: Array
value:
base: PublicKey
currentSigners:
base: Array
value:
base: Array
name: ledger.TransactionSigner
getBlock:
base: Array
name: ledger.Block
getCallFlags:
base: InteropInterface
interface: iterator
getNotifications:
base: Array
value:
base: Array
value:
base: Any
getScriptContainer:
base: Array
name: ledger.Transaction
getTransaction:
base: Array
name: ledger.Transaction
getTransactionFromBlock:
base: Array
name: ledger.Transaction
getTransactionSigners:
base: Array
value:
base: Array
name: ledger.TransactionSigner
loadScript.args:
base: Array
value:
base: Any
loadScript.f:
base: InteropInterface
interface: iterator
notify.args:
base: Array
value:
base: Any
toBlockSR:
base: Array
name: ledger.BlockSR

View file

@ -19,7 +19,7 @@ import (
) )
const srcTmpl = ` const srcTmpl = `
{{- define "METHOD" -}} {{- define "FUNCTION" -}}
// {{.Name}} {{.Comment}} // {{.Name}} {{.Comment}}
func {{.Name}}({{range $index, $arg := .Arguments -}} func {{.Name}}({{range $index, $arg := .Arguments -}}
{{- if ne $index 0}}, {{end}} {{- if ne $index 0}}, {{end}}
@ -33,7 +33,21 @@ func {{.Name}}({{range $index, $arg := .Arguments -}}
{{- end}} {{- end}}
} }
{{- end -}} {{- end -}}
// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> --hash <hash> [--config <config>]; DO NOT EDIT. {{- define "METHOD" -}}
// {{.Name}} {{.Comment}}
func (c Contract) {{.Name}}({{range $index, $arg := .Arguments -}}
{{- if ne $index 0}}, {{end}}
{{- .Name}} {{.Type}}
{{- end}}) {{if .ReturnType }}{{ .ReturnType}} {
return contract.Call(c.Hash, "{{ .NameABI }}", contract.{{ .CallFlag }}
{{- range $arg := .Arguments -}}, {{.Name}}{{end}}).({{ .ReturnType }})
{{- else -}} {
contract.Call(c.Hash, "{{ .NameABI }}", contract.{{ .CallFlag }}
{{- range $arg := .Arguments -}}, {{.Name}}{{end}})
{{- end}}
}
{{- end -}}
// Code generated by neo-go contract generate-wrapper --manifest <file.json> --out <file.go> [--hash <hash>] [--config <config>]; DO NOT EDIT.
// Package {{.PackageName}} contains wrappers for {{.ContractName}} contract. // Package {{.PackageName}} contains wrappers for {{.ContractName}} contract.
package {{.PackageName}} package {{.PackageName}}
@ -42,10 +56,25 @@ import (
{{range $m := .Imports}} "{{ $m }}" {{range $m := .Imports}} "{{ $m }}"
{{end}}) {{end}})
{{if .Hash}}
// Hash contains contract hash in big-endian form. // Hash contains contract hash in big-endian form.
const Hash = "{{ .Hash }}" const Hash = "{{ .Hash }}"
{{range $m := .Methods}} {{range $m := .Methods}}
{{template "FUNCTION" $m }}
{{end}}
{{else}}
// Contract represents the {{.ContractName}} smart contract.
type Contract struct {
Hash interop.Hash160
}
// NewContract returns a new Contract instance with the specified hash.
func NewContract(hash interop.Hash160) Contract {
return Contract{Hash: hash}
}
{{range $m := .Methods}}
{{template "METHOD" $m }} {{template "METHOD" $m }}
{{end}}
{{end}}` {{end}}`
type ( type (
@ -127,7 +156,9 @@ func NewConfig() Config {
func Generate(cfg Config) error { func Generate(cfg Config) error {
ctr := TemplateFromManifest(cfg, scTypeToGo) ctr := TemplateFromManifest(cfg, scTypeToGo)
ctr.Imports = append(ctr.Imports, "github.com/nspcc-dev/neo-go/pkg/interop/contract") ctr.Imports = append(ctr.Imports, "github.com/nspcc-dev/neo-go/pkg/interop/contract")
ctr.Imports = append(ctr.Imports, "github.com/nspcc-dev/neo-go/pkg/interop/neogointernal") if ctr.Hash != "" {
ctr.Imports = append(ctr.Imports, "github.com/nspcc-dev/neo-go/pkg/interop/neogointernal")
}
sort.Strings(ctr.Imports) sort.Strings(ctr.Imports)
return FExecute(srcTemplate, cfg.Output, ctr) return FExecute(srcTemplate, cfg.Output, ctr)