2018-02-09 16:08:50 +00:00
package smartcontract
import (
2018-03-05 08:53:09 +00:00
"encoding/hex"
"encoding/json"
2020-08-06 14:44:08 +00:00
"errors"
2018-03-05 08:53:09 +00:00
"fmt"
2018-08-25 14:40:15 +00:00
"os"
"path/filepath"
2020-03-11 18:11:51 +00:00
"strings"
2018-03-05 08:53:09 +00:00
2021-04-21 07:54:10 +00:00
"github.com/nspcc-dev/neo-go/cli/cmdargs"
2020-03-11 18:11:51 +00:00
"github.com/nspcc-dev/neo-go/cli/flags"
2020-08-31 09:22:09 +00:00
"github.com/nspcc-dev/neo-go/cli/input"
2020-06-17 21:15:13 +00:00
"github.com/nspcc-dev/neo-go/cli/options"
2022-10-06 19:59:47 +00:00
"github.com/nspcc-dev/neo-go/cli/txctx"
2022-06-23 13:50:21 +00:00
cliwallet "github.com/nspcc-dev/neo-go/cli/wallet"
2020-03-03 14:21:42 +00:00
"github.com/nspcc-dev/neo-go/pkg/compiler"
2020-11-18 20:10:48 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/state"
2020-06-11 08:45:17 +00:00
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
2020-03-11 18:11:51 +00:00
"github.com/nspcc-dev/neo-go/pkg/encoding/address"
2022-07-22 16:09:29 +00:00
"github.com/nspcc-dev/neo-go/pkg/neorpc/result"
2022-08-07 12:17:52 +00:00
"github.com/nspcc-dev/neo-go/pkg/rpcclient/actor"
2022-09-08 16:05:32 +00:00
"github.com/nspcc-dev/neo-go/pkg/rpcclient/invoker"
2022-08-16 15:17:07 +00:00
"github.com/nspcc-dev/neo-go/pkg/rpcclient/management"
2020-03-03 14:21:42 +00:00
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
2020-06-09 13:12:58 +00:00
"github.com/nspcc-dev/neo-go/pkg/smartcontract/manifest"
2020-06-25 16:21:49 +00:00
"github.com/nspcc-dev/neo-go/pkg/smartcontract/nef"
2020-03-03 14:21:42 +00:00
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm"
2020-03-11 18:11:51 +00:00
"github.com/nspcc-dev/neo-go/pkg/wallet"
2018-02-09 16:08:50 +00:00
"github.com/urfave/cli"
2021-09-25 10:09:55 +00:00
"gopkg.in/yaml.v3"
2018-02-09 16:08:50 +00:00
)
2022-06-23 13:50:21 +00:00
// addressFlagName is a flag name used for address-related operations. It should be
// the same within the smartcontract package, thus, use this constant.
const addressFlagName = "address, a"
2018-08-25 14:40:15 +00:00
var (
2022-06-23 13:50:21 +00:00
errNoInput = errors . New ( "no input file was found, specify an input file with the '--in or -i' flag" )
errNoConfFile = errors . New ( "no config file was found, specify a config file with the '--config' or '-c' flag" )
errNoManifestFile = errors . New ( "no manifest file was found, specify manifest file with '--manifest' or '-m' flag" )
errNoMethod = errors . New ( "no method specified for function invocation command" )
errNoWallet = errors . New ( "no wallet parameter found, specify it with the '--wallet' or '-w' flag or specify wallet config file with the '--wallet-config' flag" )
errConflictingWalletFlags = errors . New ( "--wallet flag conflicts with --wallet-config flag, please, provide one of them to specify wallet location" )
errNoScriptHash = errors . New ( "no smart contract hash was provided, specify one as the first argument" )
errNoSmartContractName = errors . New ( "no name was provided, specify the '--name or -n' flag" )
errFileExist = errors . New ( "A file with given smart-contract name already exists" )
2019-11-29 15:16:46 +00:00
2020-03-11 18:11:51 +00:00
walletFlag = cli . StringFlag {
Name : "wallet, w" ,
2022-06-23 13:50:21 +00:00
Usage : "wallet to use to get the key for transaction signing; conflicts with --wallet-config flag" ,
}
walletConfigFlag = cli . StringFlag {
Name : "wallet-config" ,
Usage : "path to wallet config to use to get the key for transaction signing; conflicts with --wallet flag" ,
2020-03-11 18:11:51 +00:00
}
addressFlag = flags . AddressFlag {
2022-06-23 13:50:21 +00:00
Name : addressFlagName ,
2020-03-11 18:11:51 +00:00
Usage : "address to use as transaction signee (and gas source)" ,
2019-11-29 15:59:55 +00:00
}
2018-08-25 14:40:15 +00:00
)
2022-01-14 11:18:33 +00:00
// ModVersion contains `pkg/interop` module version
// suitable to be used in go.mod.
var ModVersion string
2019-11-29 15:11:49 +00:00
const (
2018-08-25 14:40:15 +00:00
// smartContractTmpl is written to a file when used with `init` command.
2021-05-12 20:17:03 +00:00
// %s is parsed to be the smartContractName.
2018-08-25 14:40:15 +00:00
smartContractTmpl = ` package % s
2020-03-03 14:21:42 +00:00
import "github.com/nspcc-dev/neo-go/pkg/interop/runtime"
2018-08-25 14:40:15 +00:00
2020-08-10 13:01:56 +00:00
var notificationName string
// init initializes notificationName before calling any other smart-contract method
func init ( ) {
notificationName = "Hello world!"
}
// RuntimeNotify sends runtime notification with "Hello world!" name
2023-04-03 10:34:24 +00:00
func RuntimeNotify ( args [ ] any ) {
2020-08-10 13:01:56 +00:00
runtime . Notify ( notificationName , args )
2018-08-25 14:40:15 +00:00
} `
2018-02-24 09:10:45 +00:00
)
2019-10-19 20:58:45 +00:00
// NewCommands returns 'contract' command.
func NewCommands ( ) [ ] cli . Command {
2020-06-17 21:15:13 +00:00
testInvokeScriptFlags := [ ] cli . Flag {
cli . StringFlag {
Name : "in, i" ,
2020-06-25 16:21:49 +00:00
Usage : "Input location of the .nef file that needs to be invoked" ,
2020-06-17 21:15:13 +00:00
} ,
2022-09-08 16:05:32 +00:00
options . Historic ,
2020-06-17 21:15:13 +00:00
}
testInvokeScriptFlags = append ( testInvokeScriptFlags , options . RPC ... )
2022-09-08 16:05:32 +00:00
testInvokeFunctionFlags := [ ] cli . Flag { options . Historic }
testInvokeFunctionFlags = append ( testInvokeFunctionFlags , options . RPC ... )
2020-06-17 21:15:13 +00:00
invokeFunctionFlags := [ ] cli . Flag {
walletFlag ,
2022-06-23 13:50:21 +00:00
walletConfigFlag ,
2020-06-17 21:15:13 +00:00
addressFlag ,
2022-10-06 19:59:47 +00:00
txctx . GasFlag ,
txctx . SysGasFlag ,
txctx . OutFlag ,
txctx . ForceFlag ,
2020-06-17 21:15:13 +00:00
}
invokeFunctionFlags = append ( invokeFunctionFlags , options . RPC ... )
2021-04-22 12:14:02 +00:00
deployFlags := append ( invokeFunctionFlags , [ ] cli . Flag {
cli . StringFlag {
Name : "in, i" ,
Usage : "Input file for the smart contract (*.nef)" ,
} ,
cli . StringFlag {
Name : "manifest, m" ,
Usage : "Manifest input file (*.manifest.json)" ,
} ,
} ... )
2019-10-19 20:58:45 +00:00
return [ ] cli . Command { {
2018-02-09 16:08:50 +00:00
Name : "contract" ,
Usage : "compile - debug - deploy smart contracts" ,
Subcommands : [ ] cli . Command {
{
2022-08-05 13:23:50 +00:00
Name : "compile" ,
Usage : "compile a smart contract to a .nef file" ,
UsageText : "neo-go contract compile -i path [-o nef] [-v] [-d] [-m manifest] [-c yaml] [--bindings file] [--no-standards] [--no-events] [--no-permissions]" ,
2023-05-12 10:49:31 +00:00
Description : ` Compiles given smart contract to a . nef file and emits other associated
information ( manifest , bindings configuration , debug information files ) if
asked to . If none of -- out , -- manifest , -- config , -- bindings flags are specified ,
then the output filenames for these flags will be guessed using the contract
name or path provided via -- in option by trimming / adding corresponding suffixes
to the common part of the path . In the latter case the configuration filepath
will be guessed from the -- in option using the same rule . " ` ,
Action : contractCompile ,
2018-02-15 15:35:49 +00:00
Flags : [ ] cli . Flag {
2018-02-24 09:10:45 +00:00
cli . StringFlag {
Name : "in, i" ,
2023-05-12 10:49:31 +00:00
Usage : "Input file for the smart contract to be compiled (*.go file or directory)" ,
2018-02-24 09:10:45 +00:00
} ,
2018-02-15 15:35:49 +00:00
cli . StringFlag {
Name : "out, o" ,
Usage : "Output of the compiled contract" ,
} ,
2018-03-25 16:21:00 +00:00
cli . BoolFlag {
2020-04-06 12:32:06 +00:00
Name : "verbose, v" ,
Usage : "Print out additional information after a compiling" ,
2018-03-25 16:21:00 +00:00
} ,
2020-04-02 12:38:53 +00:00
cli . StringFlag {
2020-04-08 10:11:44 +00:00
Name : "debug, d" ,
2020-04-02 12:38:53 +00:00
Usage : "Emit debug info in a separate file" ,
} ,
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
cli . StringFlag {
2020-06-25 13:10:08 +00:00
Name : "manifest, m" ,
Usage : "Emit contract manifest (*.manifest.json) file into separate file using configuration input file (*.yml)" ,
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
} ,
cli . StringFlag {
Name : "config, c" ,
Usage : "Configuration input file (*.yml)" ,
} ,
2020-11-24 10:38:24 +00:00
cli . BoolFlag {
Name : "no-standards" ,
Usage : "do not check compliance with supported standards" ,
} ,
2020-11-24 13:36:35 +00:00
cli . BoolFlag {
Name : "no-events" ,
Usage : "do not check emitted events with the manifest" ,
} ,
2021-06-24 15:36:40 +00:00
cli . BoolFlag {
Name : "no-permissions" ,
Usage : "do not check if invoked contracts are allowed in manifest" ,
} ,
2022-02-11 12:16:15 +00:00
cli . StringFlag {
Name : "bindings" ,
Usage : "output file for smart-contract bindings configuration" ,
} ,
2018-02-15 15:35:49 +00:00
} ,
2018-02-09 16:08:50 +00:00
} ,
2019-11-20 13:07:43 +00:00
{
2021-04-16 14:48:00 +00:00
Name : "deploy" ,
Usage : "deploy a smart contract (.nef with description)" ,
2021-07-01 16:03:30 +00:00
UsageText : "neo-go contract deploy -r endpoint -w wallet [-a address] [-g gas] [-e sysgas] --in contract.nef --manifest contract.manifest.json [--out file] [--force] [data]" ,
2020-03-11 17:32:06 +00:00
Description : ` Deploys given contract into the chain . The gas parameter is for additional
2021-04-16 15:04:19 +00:00
gas to be added as a network fee to prioritize the transaction . The data
parameter is an optional parameter to be passed to ' _deploy ' method .
2020-03-11 17:32:06 +00:00
` ,
2019-11-20 13:07:43 +00:00
Action : contractDeploy ,
2020-06-17 21:15:13 +00:00
Flags : deployFlags ,
2019-11-29 15:59:55 +00:00
} ,
2021-10-25 11:48:21 +00:00
generateWrapperCmd ,
2022-10-26 20:27:24 +00:00
generateRPCWrapperCmd ,
2019-11-29 15:59:55 +00:00
{
Name : "invokefunction" ,
Usage : "invoke deployed contract on the blockchain" ,
2021-07-01 16:03:30 +00:00
UsageText : "neo-go contract invokefunction -r endpoint -w wallet [-a address] [-g gas] [-e sysgas] [--out file] [--force] scripthash [method] [arguments...] [--] [signers...]" ,
2020-06-11 08:45:17 +00:00
Description : ` Executes given ( as a script hash ) deployed script with the given method ,
2020-07-29 16:57:38 +00:00
arguments and signers . Sender is included in the list of signers by default
2020-10-01 12:26:51 +00:00
with None witness scope . If you ' d like to change default sender ' s scope ,
2020-07-29 16:57:38 +00:00
specify it via signers parameter . See testinvokefunction documentation for
the details about parameters . It differs from testinvokefunction in that this
command sends an invocation transaction to the network .
2019-11-29 15:59:55 +00:00
` ,
Action : invokeFunction ,
2020-06-17 21:15:13 +00:00
Flags : invokeFunctionFlags ,
2019-11-20 13:07:43 +00:00
} ,
2019-11-27 09:52:15 +00:00
{
Name : "testinvokefunction" ,
Usage : "invoke deployed contract on the blockchain (test mode)" ,
2022-09-08 16:05:32 +00:00
UsageText : "neo-go contract testinvokefunction -r endpoint [--historic index/hash] scripthash [method] [arguments...] [--] [signers...]" ,
2020-06-11 08:45:17 +00:00
Description : ` Executes given ( as a script hash ) deployed script with the given method ,
2020-07-29 16:57:38 +00:00
arguments and signers ( sender is not included by default ) . If no method is given
"" is passed to the script , if no arguments are given , an empty array is
passed , if no signers are given no array is passed . If signers are specified ,
the first one of them is treated as a sender . All of the given arguments are
encapsulated into array before invoking the script . The script thus should
follow the regular convention of smart contract arguments ( method string and
an array of other arguments ) .
2019-11-27 09:52:15 +00:00
2022-10-10 11:00:26 +00:00
` + cmdargs.ParamsParsingDoc + `
2020-06-11 08:45:17 +00:00
2022-10-11 11:59:51 +00:00
` + cmdargs.SignersParsingDoc + `
2019-11-27 09:52:15 +00:00
` ,
Action : testInvokeFunction ,
2022-09-08 16:05:32 +00:00
Flags : testInvokeFunctionFlags ,
2019-11-27 09:52:15 +00:00
} ,
2018-03-05 08:53:09 +00:00
{
2020-06-11 08:45:17 +00:00
Name : "testinvokescript" ,
2020-06-25 16:21:49 +00:00
Usage : "Invoke compiled AVM code in NEF format on the blockchain (test mode, not creating a transaction for it)" ,
2022-09-08 16:05:32 +00:00
UsageText : "neo-go contract testinvokescript -r endpoint -i input.nef [--historic index/hash] [signers...]" ,
2020-06-25 16:21:49 +00:00
Description : ` Executes given compiled AVM instructions in NEF format with the given set of
2020-07-29 16:57:38 +00:00
signers not included sender by default . See testinvokefunction documentation
for the details about parameters .
2020-06-11 08:45:17 +00:00
` ,
2019-11-26 14:00:43 +00:00
Action : testInvokeScript ,
2020-06-17 21:15:13 +00:00
Flags : testInvokeScriptFlags ,
2018-03-05 08:53:09 +00:00
} ,
2018-08-25 14:40:15 +00:00
{
2022-08-05 13:23:50 +00:00
Name : "init" ,
Usage : "initialize a new smart-contract in a directory with boiler plate code" ,
UsageText : "neo-go contract init -n name [--skip-details]" ,
Action : initSmartContract ,
2018-08-25 14:40:15 +00:00
Flags : [ ] cli . Flag {
cli . StringFlag {
Name : "name, n" ,
Usage : "name of the smart-contract to be initialized" ,
} ,
2018-10-16 06:33:29 +00:00
cli . BoolFlag {
Name : "skip-details, skip" ,
Usage : "skip filling in the projects and contract details" ,
} ,
2018-08-25 14:40:15 +00:00
} ,
} ,
2018-10-23 08:23:03 +00:00
{
2022-08-05 13:23:50 +00:00
Name : "inspect" ,
Usage : "creates a user readable dump of the program instructions" ,
UsageText : "neo-go contract inspect -i file [-c]" ,
Action : inspect ,
2018-10-23 08:23:03 +00:00
Flags : [ ] cli . Flag {
2019-10-29 09:56:44 +00:00
cli . BoolFlag {
Name : "compile, c" ,
Usage : "compile input file (it should be go code then)" ,
} ,
2018-10-23 08:23:03 +00:00
cli . StringFlag {
Name : "in, i" ,
2020-06-25 16:21:49 +00:00
Usage : "input file of the program (either .go or .nef)" ,
2018-10-23 08:23:03 +00:00
} ,
} ,
} ,
2020-12-17 12:41:53 +00:00
{
2022-08-05 13:23:50 +00:00
Name : "calc-hash" ,
Usage : "calculates hash of a contract after deployment" ,
UsageText : "neo-go contract calc-hash -i nef -m manifest -s address" ,
Action : calcHash ,
2020-12-17 12:41:53 +00:00
Flags : [ ] cli . Flag {
2021-04-16 09:09:59 +00:00
flags . AddressFlag {
2020-12-17 12:41:53 +00:00
Name : "sender, s" ,
Usage : "sender script hash or address" ,
} ,
cli . StringFlag {
Name : "in" ,
Usage : "path to NEF file" ,
} ,
2021-01-22 09:22:48 +00:00
cli . StringFlag {
Name : "manifest, m" ,
Usage : "path to manifest file" ,
} ,
2020-12-17 12:41:53 +00:00
} ,
} ,
2021-08-02 08:10:26 +00:00
{
Name : "manifest" ,
Usage : "manifest-related commands" ,
Subcommands : [ ] cli . Command {
{
2022-08-05 13:23:50 +00:00
Name : "add-group" ,
Usage : "adds group to the manifest" ,
UsageText : "neo-go contract manifest add-group -w wallet [--wallet-config path] -n nef -m manifest -a address -s address" ,
Action : manifestAddGroup ,
2021-08-02 08:10:26 +00:00
Flags : [ ] cli . Flag {
walletFlag ,
2022-06-23 13:50:21 +00:00
walletConfigFlag ,
2021-08-02 08:10:26 +00:00
cli . StringFlag {
Name : "sender, s" ,
Usage : "deploy transaction sender" ,
} ,
2022-06-23 13:50:21 +00:00
flags . AddressFlag {
Name : addressFlagName , // use the same name for handler code unification.
2021-08-02 08:10:26 +00:00
Usage : "account to sign group with" ,
} ,
cli . StringFlag {
Name : "nef, n" ,
Usage : "path to the NEF file" ,
} ,
cli . StringFlag {
Name : "manifest, m" ,
Usage : "path to the manifest" ,
} ,
} ,
} ,
} ,
} ,
2018-02-09 16:08:50 +00:00
} ,
2019-10-19 20:58:45 +00:00
} }
2018-02-09 16:08:50 +00:00
}
2018-08-25 14:40:15 +00:00
// initSmartContract initializes a given directory with some boiler plate code.
func initSmartContract ( ctx * cli . Context ) error {
2022-08-05 10:32:37 +00:00
if err := cmdargs . EnsureNone ( ctx ) ; err != nil {
return err
}
2018-10-16 06:33:29 +00:00
contractName := ctx . String ( "name" )
if contractName == "" {
2018-08-25 14:40:15 +00:00
return cli . NewExitError ( errNoSmartContractName , 1 )
}
// Check if the file already exists, if yes, exit
2018-10-16 06:33:29 +00:00
if _ , err := os . Stat ( contractName ) ; err == nil {
2018-08-25 14:40:15 +00:00
return cli . NewExitError ( errFileExist , 1 )
}
2018-10-16 06:33:29 +00:00
basePath := contractName
2021-11-17 11:14:22 +00:00
contractName = filepath . Base ( contractName )
2018-08-25 14:40:15 +00:00
fileName := "main.go"
// create base directory
2018-10-16 06:33:29 +00:00
if err := os . Mkdir ( basePath , os . ModePerm ) ; err != nil {
2018-08-25 14:40:15 +00:00
return cli . NewExitError ( err , 1 )
}
2020-08-04 09:55:36 +00:00
m := ProjectConfig {
2020-11-20 08:02:58 +00:00
Name : contractName ,
2021-09-23 21:19:37 +00:00
SourceURL : "http://example.com/" ,
2020-08-04 09:55:36 +00:00
SupportedStandards : [ ] string { } ,
2020-12-10 14:55:52 +00:00
SafeMethods : [ ] string { } ,
2020-08-10 13:01:56 +00:00
Events : [ ] manifest . Event {
{
Name : "Hello world!" ,
Parameters : [ ] manifest . Parameter {
{
Name : "args" ,
Type : smartcontract . ArrayType ,
} ,
} ,
} ,
} ,
2021-06-02 07:50:17 +00:00
Permissions : [ ] permission { permission ( * manifest . NewPermission ( manifest . PermissionWildcard ) ) } ,
2020-08-04 09:55:36 +00:00
}
2020-06-09 13:12:58 +00:00
b , err := yaml . Marshal ( m )
if err != nil {
return cli . NewExitError ( err , 1 )
}
2022-02-22 16:27:32 +00:00
if err := os . WriteFile ( filepath . Join ( basePath , "neo-go.yml" ) , b , 0644 ) ; err != nil {
2020-06-09 13:12:58 +00:00
return cli . NewExitError ( err , 1 )
2018-10-16 06:33:29 +00:00
}
2022-01-14 11:18:33 +00:00
ver := ModVersion
if ver == "" {
ver = "latest"
}
2021-12-02 14:44:53 +00:00
gm := [ ] byte ( "module " + contractName + `
require (
2022-01-14 11:18:33 +00:00
github . com / nspcc - dev / neo - go / pkg / interop ` + ver + `
2021-12-02 14:44:53 +00:00
) ` )
2022-02-22 16:27:32 +00:00
if err := os . WriteFile ( filepath . Join ( basePath , "go.mod" ) , gm , 0644 ) ; err != nil {
2021-12-02 14:44:53 +00:00
return cli . NewExitError ( err , 1 )
}
2018-10-16 06:33:29 +00:00
data := [ ] byte ( fmt . Sprintf ( smartContractTmpl , contractName ) )
2022-02-22 16:27:32 +00:00
if err := os . WriteFile ( filepath . Join ( basePath , fileName ) , data , 0644 ) ; err != nil {
2018-08-25 14:40:15 +00:00
return cli . NewExitError ( err , 1 )
}
2018-10-16 06:33:29 +00:00
2020-08-28 09:11:19 +00:00
fmt . Fprintf ( ctx . App . Writer , "Successfully initialized smart contract [%s]\n" , contractName )
2018-10-16 06:33:29 +00:00
2018-08-25 14:40:15 +00:00
return nil
}
2018-02-09 16:08:50 +00:00
func contractCompile ( ctx * cli . Context ) error {
2022-08-05 10:32:37 +00:00
if err := cmdargs . EnsureNone ( ctx ) ; err != nil {
return err
}
2018-02-24 09:10:45 +00:00
src := ctx . String ( "in" )
if len ( src ) == 0 {
2018-03-05 08:53:09 +00:00
return cli . NewExitError ( errNoInput , 1 )
2018-02-15 15:35:49 +00:00
}
2020-06-25 13:10:08 +00:00
manifestFile := ctx . String ( "manifest" )
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
confFile := ctx . String ( "config" )
2020-06-30 11:21:58 +00:00
debugFile := ctx . String ( "debug" )
2023-05-12 10:49:31 +00:00
out := ctx . String ( "out" )
2023-05-16 11:00:44 +00:00
bindings := ctx . String ( "bindings" )
if len ( confFile ) == 0 && ( len ( manifestFile ) != 0 || len ( debugFile ) != 0 || len ( bindings ) != 0 ) {
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
return cli . NewExitError ( errNoConfFile , 1 )
}
2023-05-12 10:49:31 +00:00
autocomplete := len ( manifestFile ) == 0 &&
len ( confFile ) == 0 &&
len ( out ) == 0 &&
len ( bindings ) == 0
if autocomplete {
var root string
fileInfo , err := os . Stat ( src )
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "failed to stat source file or directory: %w" , err ) , 1 )
}
if fileInfo . IsDir ( ) {
base := filepath . Base ( fileInfo . Name ( ) )
if base == string ( filepath . Separator ) {
base = "contract"
}
root = filepath . Join ( src , base )
} else {
root = strings . TrimSuffix ( src , ".go" )
}
manifestFile = root + ".manifest.json"
confFile = root + ".yml"
out = root + ".nef"
bindings = root + ".bindings.yml"
}
2018-02-15 15:35:49 +00:00
2018-02-19 09:24:28 +00:00
o := & compiler . Options {
2023-05-12 10:49:31 +00:00
Outfile : out ,
2020-04-02 12:38:53 +00:00
2020-06-30 11:21:58 +00:00
DebugInfo : debugFile ,
2020-06-25 13:10:08 +00:00
ManifestFile : manifestFile ,
2023-05-16 11:00:44 +00:00
BindingsFile : bindings ,
2020-11-24 10:38:24 +00:00
2021-06-24 15:36:40 +00:00
NoStandardCheck : ctx . Bool ( "no-standards" ) ,
NoEventsCheck : ctx . Bool ( "no-events" ) ,
NoPermissionsCheck : ctx . Bool ( "no-permissions" ) ,
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
}
if len ( confFile ) != 0 {
2021-03-22 09:21:48 +00:00
conf , err := ParseContractConfig ( confFile )
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
if err != nil {
return err
}
2020-11-20 08:02:58 +00:00
o . Name = conf . Name
2021-09-23 21:19:37 +00:00
o . SourceURL = conf . SourceURL
2020-08-11 08:21:54 +00:00
o . ContractEvents = conf . Events
2020-08-04 09:55:36 +00:00
o . ContractSupportedStandards = conf . SupportedStandards
2021-06-02 07:50:17 +00:00
o . Permissions = make ( [ ] manifest . Permission , len ( conf . Permissions ) )
for i := range conf . Permissions {
o . Permissions [ i ] = manifest . Permission ( conf . Permissions [ i ] )
}
2020-12-10 14:55:52 +00:00
o . SafeMethods = conf . SafeMethods
2021-10-16 11:10:17 +00:00
o . Overloads = conf . Overloads
2018-02-15 15:35:49 +00:00
}
2019-11-22 14:16:52 +00:00
result , err := compiler . CompileAndSave ( src , o )
if err != nil {
2018-02-24 09:10:45 +00:00
return cli . NewExitError ( err , 1 )
}
2020-04-06 12:33:44 +00:00
if ctx . Bool ( "verbose" ) {
2020-08-28 09:11:19 +00:00
fmt . Fprintln ( ctx . App . Writer , hex . EncodeToString ( result ) )
2020-04-06 12:33:44 +00:00
}
2018-03-25 16:21:00 +00:00
2018-02-24 09:10:45 +00:00
return nil
2018-02-09 16:08:50 +00:00
}
2020-12-17 12:41:53 +00:00
func calcHash ( ctx * cli . Context ) error {
2022-08-05 10:32:37 +00:00
if err := cmdargs . EnsureNone ( ctx ) ; err != nil {
return err
}
2021-04-16 09:09:59 +00:00
sender := ctx . Generic ( "sender" ) . ( * flags . Address )
if ! sender . IsSet {
return cli . NewExitError ( "sender is not set" , 1 )
2020-12-17 12:41:53 +00:00
}
p := ctx . String ( "in" )
if p == "" {
return cli . NewExitError ( errors . New ( "no .nef file was provided" ) , 1 )
}
2021-01-22 09:22:48 +00:00
mpath := ctx . String ( "manifest" )
if mpath == "" {
return cli . NewExitError ( errors . New ( "no manifest file provided" ) , 1 )
}
2022-02-22 16:27:32 +00:00
f , err := os . ReadFile ( p )
2020-12-17 12:41:53 +00:00
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "can't read .nef file: %w" , err ) , 1 )
}
nefFile , err := nef . FileFromBytes ( f )
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "can't unmarshal .nef file: %w" , err ) , 1 )
}
2022-02-22 16:27:32 +00:00
manifestBytes , err := os . ReadFile ( mpath )
2021-01-22 09:22:48 +00:00
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "failed to read manifest file: %w" , err ) , 1 )
}
m := & manifest . Manifest { }
err = json . Unmarshal ( manifestBytes , m )
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "failed to restore manifest file: %w" , err ) , 1 )
}
2021-04-16 09:09:59 +00:00
fmt . Fprintln ( ctx . App . Writer , "Contract hash:" , state . CreateContractHash ( sender . Uint160 ( ) , nefFile . Checksum , m . Name ) . StringLE ( ) )
2020-12-17 12:41:53 +00:00
return nil
}
2019-11-27 09:52:15 +00:00
func testInvokeFunction ( ctx * cli . Context ) error {
2020-06-10 08:31:01 +00:00
return invokeInternal ( ctx , false )
2019-11-29 15:59:55 +00:00
}
func invokeFunction ( ctx * cli . Context ) error {
2020-06-10 08:31:01 +00:00
return invokeInternal ( ctx , true )
2019-11-29 15:59:55 +00:00
}
2020-06-10 08:31:01 +00:00
func invokeInternal ( ctx * cli . Context , signAndPush bool ) error {
2019-11-29 15:59:55 +00:00
var (
2021-04-22 12:14:02 +00:00
err error
exitErr * cli . ExitError
operation string
2023-04-03 10:34:24 +00:00
params [ ] any
2021-04-22 12:14:02 +00:00
paramsStart = 1
2022-09-08 16:05:32 +00:00
scParams [ ] smartcontract . Parameter
2021-04-22 12:14:02 +00:00
cosigners [ ] transaction . Signer
cosignersOffset = 0
2019-11-29 15:59:55 +00:00
)
2019-11-28 16:40:13 +00:00
2019-11-27 09:52:15 +00:00
args := ctx . Args ( )
if ! args . Present ( ) {
return cli . NewExitError ( errNoScriptHash , 1 )
}
2021-02-17 14:48:41 +00:00
script , err := flags . ParseAddress ( args [ 0 ] )
2020-07-02 13:38:33 +00:00
if err != nil {
2020-08-06 16:09:57 +00:00
return cli . NewExitError ( fmt . Errorf ( "incorrect script hash: %w" , err ) , 1 )
2020-07-02 13:38:33 +00:00
}
2020-06-10 08:31:01 +00:00
if len ( args ) <= 1 {
return cli . NewExitError ( errNoMethod , 1 )
2019-11-27 09:52:15 +00:00
}
2020-06-10 08:31:01 +00:00
operation = args [ 1 ]
paramsStart ++
2019-11-28 16:40:13 +00:00
if len ( args ) > paramsStart {
2022-09-08 16:05:32 +00:00
cosignersOffset , scParams , err = cmdargs . ParseParams ( args [ paramsStart : ] , true )
2020-08-26 09:08:17 +00:00
if err != nil {
return cli . NewExitError ( err , 1 )
2019-11-27 09:52:15 +00:00
}
2023-04-03 10:34:24 +00:00
params = make ( [ ] any , len ( scParams ) )
2022-09-08 16:05:32 +00:00
for i := range scParams {
params [ i ] = scParams [ i ]
}
2019-11-27 09:52:15 +00:00
}
2020-08-26 09:08:17 +00:00
cosignersStart := paramsStart + cosignersOffset
2021-04-21 07:54:10 +00:00
cosigners , exitErr = cmdargs . GetSignersFromContext ( ctx , cosignersStart )
if exitErr != nil {
return exitErr
2020-06-11 08:45:17 +00:00
}
2021-08-02 10:42:15 +00:00
var (
acc * wallet . Account
w * wallet . Wallet
)
if signAndPush {
acc , w , err = getAccFromContext ( ctx )
if err != nil {
return cli . NewExitError ( err , 1 )
}
2022-09-01 18:44:49 +00:00
defer w . Close ( )
2021-08-02 10:42:15 +00:00
}
2022-09-08 12:57:27 +00:00
return invokeWithArgs ( ctx , acc , w , script , operation , params , cosigners )
2021-04-22 12:14:02 +00:00
}
2023-04-03 10:34:24 +00:00
func invokeWithArgs ( ctx * cli . Context , acc * wallet . Account , wall * wallet . Wallet , script util . Uint160 , operation string , params [ ] any , cosigners [ ] transaction . Signer ) error {
2021-04-22 12:14:02 +00:00
var (
2022-08-19 17:53:16 +00:00
err error
signersAccounts [ ] actor . SignerAccount
resp * result . Invoke
signAndPush = acc != nil
2022-09-08 16:05:32 +00:00
inv * invoker . Invoker
2022-08-19 17:53:16 +00:00
act * actor . Actor
2021-04-22 12:14:02 +00:00
)
2019-11-29 15:59:55 +00:00
if signAndPush {
2022-08-19 17:53:16 +00:00
signersAccounts , err = cmdargs . GetSignersAccounts ( acc , wall , cosigners , transaction . None )
2021-04-21 12:22:13 +00:00
if err != nil {
2022-09-08 12:57:27 +00:00
return cli . NewExitError ( fmt . Errorf ( "invalid signers: %w" , err ) , 1 )
2021-03-02 12:43:09 +00:00
}
2019-11-29 15:59:55 +00:00
}
2020-06-17 21:15:13 +00:00
gctx , cancel := options . GetTimeoutContext ( ctx )
defer cancel ( )
c , err := options . GetRPCClient ( gctx , ctx )
2019-11-27 09:52:15 +00:00
if err != nil {
2022-09-08 12:57:27 +00:00
return err
2019-11-27 09:52:15 +00:00
}
2022-08-07 12:17:52 +00:00
if signAndPush {
2022-08-19 17:53:16 +00:00
act , err = actor . New ( c , signersAccounts )
2022-08-07 12:17:52 +00:00
if err != nil {
2022-09-08 12:57:27 +00:00
return cli . NewExitError ( fmt . Errorf ( "failed to create RPC actor: %w" , err ) , 1 )
2022-08-07 12:17:52 +00:00
}
2022-09-08 16:05:32 +00:00
inv = & act . Invoker
} else {
inv , err = options . GetInvoker ( c , ctx , cosigners )
if err != nil {
return err
}
2022-08-07 12:17:52 +00:00
}
2022-02-01 09:46:30 +00:00
out := ctx . String ( "out" )
2022-09-08 16:05:32 +00:00
resp , err = inv . Call ( script , operation , params ... )
2019-11-27 09:52:15 +00:00
if err != nil {
2022-09-08 12:57:27 +00:00
return cli . NewExitError ( err , 1 )
2019-11-27 09:52:15 +00:00
}
2022-02-01 09:46:30 +00:00
if resp . State != "HALT" {
2022-06-29 12:12:24 +00:00
errText := fmt . Sprintf ( "Warning: %s VM state returned from the RPC node: %s" , resp . State , resp . FaultException )
2022-08-06 13:36:11 +00:00
if ! signAndPush {
2022-09-08 12:57:27 +00:00
return cli . NewExitError ( errText , 1 )
2022-06-29 12:09:11 +00:00
}
2022-08-31 06:51:57 +00:00
action := "send"
process := "Sending"
2022-08-06 13:36:11 +00:00
if out != "" {
2022-08-31 06:51:57 +00:00
action = "save"
process = "Saving"
2022-02-01 09:46:30 +00:00
}
2020-12-04 07:59:46 +00:00
if ! ctx . Bool ( "force" ) {
2022-09-08 12:57:27 +00:00
return cli . NewExitError ( errText + ".\nUse --force flag to " + action + " the transaction anyway." , 1 )
2020-10-12 09:45:38 +00:00
}
2022-06-29 12:12:24 +00:00
fmt . Fprintln ( ctx . App . Writer , errText + ".\n" + process + " transaction..." )
2020-10-12 09:45:38 +00:00
}
2022-08-06 13:36:11 +00:00
if ! signAndPush {
b , err := json . MarshalIndent ( resp , "" , " " )
2022-02-21 10:41:14 +00:00
if err != nil {
2022-09-08 12:57:27 +00:00
return cli . NewExitError ( err , 1 )
2020-10-02 13:13:17 +00:00
}
2022-08-06 13:36:11 +00:00
fmt . Fprintln ( ctx . App . Writer , string ( b ) )
2022-10-06 19:59:47 +00:00
return nil
2019-11-27 09:52:15 +00:00
}
2022-10-06 19:59:47 +00:00
if len ( resp . Script ) == 0 {
return cli . NewExitError ( errors . New ( "no script returned from the RPC node" ) , 1 )
}
tx , err := act . MakeUnsignedUncheckedRun ( resp . Script , resp . GasConsumed , nil )
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "failed to create tx: %w" , err ) , 1 )
}
return txctx . SignAndSend ( ctx , act , acc , tx )
2019-11-27 09:52:15 +00:00
}
2019-11-26 14:00:43 +00:00
func testInvokeScript ( ctx * cli . Context ) error {
2018-03-05 08:53:09 +00:00
src := ctx . String ( "in" )
if len ( src ) == 0 {
return cli . NewExitError ( errNoInput , 1 )
}
2018-03-25 16:21:00 +00:00
2022-02-22 16:27:32 +00:00
b , err := os . ReadFile ( src )
2018-03-05 08:53:09 +00:00
if err != nil {
return cli . NewExitError ( err , 1 )
}
2020-06-25 16:21:49 +00:00
nefFile , err := nef . FileFromBytes ( b )
if err != nil {
2020-08-06 14:44:08 +00:00
return cli . NewExitError ( fmt . Errorf ( "failed to restore .nef file: %w" , err ) , 1 )
2020-06-25 16:21:49 +00:00
}
2018-03-05 08:53:09 +00:00
2021-04-21 07:54:10 +00:00
signers , exitErr := cmdargs . GetSignersFromContext ( ctx , 0 )
if exitErr != nil {
return exitErr
2020-06-11 08:45:17 +00:00
}
2020-06-17 21:15:13 +00:00
gctx , cancel := options . GetTimeoutContext ( ctx )
defer cancel ( )
2022-09-08 16:05:32 +00:00
_ , inv , err := options . GetRPCWithInvoker ( gctx , ctx , signers )
2018-03-05 08:53:09 +00:00
if err != nil {
2020-06-17 21:15:13 +00:00
return err
2018-03-05 08:53:09 +00:00
}
2022-09-08 16:05:32 +00:00
resp , err := inv . Run ( nefFile . Script )
2018-03-05 08:53:09 +00:00
if err != nil {
return cli . NewExitError ( err , 1 )
}
2020-02-20 18:08:22 +00:00
b , err = json . MarshalIndent ( resp , "" , " " )
2018-03-05 08:53:09 +00:00
if err != nil {
return cli . NewExitError ( err , 1 )
}
2020-08-28 09:11:19 +00:00
fmt . Fprintln ( ctx . App . Writer , string ( b ) )
2018-03-05 08:53:09 +00:00
return nil
}
2019-11-20 09:29:37 +00:00
// ProjectConfig contains project metadata.
type ProjectConfig struct {
2020-11-20 08:02:58 +00:00
Name string
2021-09-23 21:19:37 +00:00
SourceURL string
2020-12-10 14:55:52 +00:00
SafeMethods [ ] string
2020-08-04 09:55:36 +00:00
SupportedStandards [ ] string
Events [ ] manifest . Event
2021-06-02 07:50:17 +00:00
Permissions [ ] permission
2021-10-16 11:10:17 +00:00
Overloads map [ string ] string ` yaml:"overloads,omitempty" `
2018-10-16 06:33:29 +00:00
}
2018-10-23 08:23:03 +00:00
func inspect ( ctx * cli . Context ) error {
2022-08-05 10:32:37 +00:00
if err := cmdargs . EnsureNone ( ctx ) ; err != nil {
return err
}
2019-10-29 09:56:44 +00:00
in := ctx . String ( "in" )
compile := ctx . Bool ( "compile" )
if len ( in ) == 0 {
2018-10-23 08:23:03 +00:00
return cli . NewExitError ( errNoInput , 1 )
}
2020-08-12 09:22:16 +00:00
var (
b [ ] byte
err error
)
2019-10-29 09:56:44 +00:00
if compile {
2020-08-10 15:23:45 +00:00
b , err = compiler . Compile ( in , nil )
2019-10-29 09:56:44 +00:00
if err != nil {
2020-08-06 14:44:08 +00:00
return cli . NewExitError ( fmt . Errorf ( "failed to compile: %w" , err ) , 1 )
2019-10-29 09:56:44 +00:00
}
2020-06-25 16:21:49 +00:00
} else {
2022-02-22 16:27:32 +00:00
f , err := os . ReadFile ( in )
2020-08-12 09:22:16 +00:00
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "failed to read .nef file: %w" , err ) , 1 )
}
nefFile , err := nef . FileFromBytes ( f )
2020-06-25 16:21:49 +00:00
if err != nil {
2020-08-06 14:44:08 +00:00
return cli . NewExitError ( fmt . Errorf ( "failed to restore .nef file: %w" , err ) , 1 )
2020-06-25 16:21:49 +00:00
}
b = nefFile . Script
2019-10-29 09:56:44 +00:00
}
v := vm . New ( )
v . LoadScript ( b )
2020-12-01 13:52:23 +00:00
v . PrintOps ( ctx . App . Writer )
2019-10-29 09:56:44 +00:00
2018-10-23 08:23:03 +00:00
return nil
}
2019-11-20 13:07:43 +00:00
2021-03-02 12:43:09 +00:00
func getAccFromContext ( ctx * cli . Context ) ( * wallet . Account , * wallet . Wallet , error ) {
2020-03-11 18:11:51 +00:00
var addr util . Uint160
wPath := ctx . String ( "wallet" )
2022-06-23 13:50:21 +00:00
walletConfigPath := ctx . String ( "wallet-config" )
if len ( wPath ) != 0 && len ( walletConfigPath ) != 0 {
return nil , nil , errConflictingWalletFlags
}
if len ( wPath ) == 0 && len ( walletConfigPath ) == 0 {
return nil , nil , errNoWallet
}
var pass * string
if len ( walletConfigPath ) != 0 {
cfg , err := cliwallet . ReadWalletConfig ( walletConfigPath )
if err != nil {
return nil , nil , err
}
wPath = cfg . Path
pass = & cfg . Password
2019-11-29 15:59:55 +00:00
}
2020-03-11 18:11:51 +00:00
wall , err := wallet . NewWalletFromFile ( wPath )
if err != nil {
2022-06-23 13:50:21 +00:00
return nil , nil , err
2020-03-11 18:11:51 +00:00
}
addrFlag := ctx . Generic ( "address" ) . ( * flags . Address )
if addrFlag . IsSet {
addr = addrFlag . Uint160 ( )
} else {
addr = wall . GetChangeAddress ( )
}
2021-08-02 08:10:26 +00:00
2022-06-23 13:50:21 +00:00
acc , err := getUnlockedAccount ( wall , addr , pass )
2021-08-02 08:10:26 +00:00
return acc , wall , err
}
2022-06-23 13:50:21 +00:00
func getUnlockedAccount ( wall * wallet . Wallet , addr util . Uint160 , pass * string ) ( * wallet . Account , error ) {
2020-03-11 18:11:51 +00:00
acc := wall . GetAccount ( addr )
if acc == nil {
2022-06-23 13:50:21 +00:00
return nil , fmt . Errorf ( "wallet contains no account for '%s'" , address . Uint160ToString ( addr ) )
2021-08-02 08:10:26 +00:00
}
2022-09-01 14:54:00 +00:00
if acc . CanSign ( ) {
2021-08-02 08:10:26 +00:00
return acc , nil
2020-03-11 18:11:51 +00:00
}
2022-06-23 13:50:21 +00:00
if pass == nil {
rawPass , err := input . ReadPassword (
fmt . Sprintf ( "Enter account %s password > " , address . Uint160ToString ( addr ) ) )
if err != nil {
return nil , fmt . Errorf ( "Error reading password: %w" , err )
}
trimmed := strings . TrimRight ( string ( rawPass ) , "\n" )
pass = & trimmed
2020-03-11 18:11:51 +00:00
}
2022-06-23 13:50:21 +00:00
err := acc . Decrypt ( * pass , wall . Scrypt )
2019-11-29 15:59:55 +00:00
if err != nil {
2022-06-23 13:50:21 +00:00
return nil , err
2019-11-29 15:59:55 +00:00
}
2021-08-02 08:10:26 +00:00
return acc , nil
2019-11-29 15:59:55 +00:00
}
2019-11-20 13:07:43 +00:00
// contractDeploy deploys contract.
func contractDeploy ( ctx * cli . Context ) error {
2021-08-02 10:47:19 +00:00
nefFile , f , err := readNEFFile ( ctx . String ( "in" ) )
2019-11-20 13:07:43 +00:00
if err != nil {
return cli . NewExitError ( err , 1 )
}
2020-06-30 11:24:07 +00:00
2022-08-22 10:41:57 +00:00
m , manifestBytes , err := readManifest ( ctx . String ( "manifest" ) , util . Uint160 { } )
2020-06-30 11:24:07 +00:00
if err != nil {
2020-08-06 14:44:08 +00:00
return cli . NewExitError ( fmt . Errorf ( "failed to read manifest file: %w" , err ) , 1 )
2020-06-30 11:24:07 +00:00
}
2019-11-20 13:07:43 +00:00
2023-04-03 10:34:24 +00:00
var appCallParams = [ ] any { f , manifestBytes }
2022-09-08 16:05:32 +00:00
2021-10-12 09:55:56 +00:00
signOffset , data , err := cmdargs . ParseParams ( ctx . Args ( ) , true )
2021-04-22 12:14:02 +00:00
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "unable to parse 'data' parameter: %w" , err ) , 1 )
}
if len ( data ) > 1 {
return cli . NewExitError ( "'data' should be represented as a single parameter" , 1 )
}
if len ( data ) != 0 {
appCallParams = append ( appCallParams , data [ 0 ] )
2021-04-16 15:04:19 +00:00
}
2021-08-02 10:42:15 +00:00
acc , w , err := getAccFromContext ( ctx )
if err != nil {
return cli . NewExitError ( fmt . Errorf ( "can't get sender address: %w" , err ) , 1 )
}
2022-09-01 18:44:49 +00:00
defer w . Close ( )
2022-09-08 12:57:27 +00:00
sender := acc . ScriptHash ( )
2021-08-02 10:42:15 +00:00
2021-10-12 09:55:56 +00:00
cosigners , sgnErr := cmdargs . GetSignersFromContext ( ctx , signOffset )
if sgnErr != nil {
return err
} else if len ( cosigners ) == 0 {
cosigners = [ ] transaction . Signer { {
Account : acc . Contract . ScriptHash ( ) ,
Scopes : transaction . CalledByEntry ,
} }
}
2021-08-02 10:42:15 +00:00
2022-09-08 12:57:27 +00:00
extErr := invokeWithArgs ( ctx , acc , w , management . Hash , "deploy" , appCallParams , cosigners )
2021-04-22 12:14:02 +00:00
if extErr != nil {
return extErr
2020-07-02 13:22:49 +00:00
}
2019-11-29 14:59:07 +00:00
2021-01-22 09:22:48 +00:00
hash := state . CreateContractHash ( sender , nefFile . Checksum , m . Name )
2020-11-18 20:10:48 +00:00
fmt . Fprintf ( ctx . App . Writer , "Contract: %s\n" , hash . StringLE ( ) )
2019-11-20 13:07:43 +00:00
return nil
}
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
2021-03-22 09:21:48 +00:00
// ParseContractConfig reads contract configuration file (.yaml) and returns unmarshalled ProjectConfig.
func ParseContractConfig ( confFile string ) ( ProjectConfig , error ) {
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
conf := ProjectConfig { }
2022-02-22 16:27:32 +00:00
confBytes , err := os . ReadFile ( confFile )
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
if err != nil {
return conf , cli . NewExitError ( err , 1 )
}
err = yaml . Unmarshal ( confBytes , & conf )
if err != nil {
2020-08-06 16:09:57 +00:00
return conf , cli . NewExitError ( fmt . Errorf ( "bad config: %w" , err ) , 1 )
compiler: add ability to generate .abi.json file
A part of integration with NEO Blockchain Toolkit (see #902). To be
able to deploy smart-contract compiled with neo-go compiler via NEO
Express, we have to generate additional .abi.json file. This file
contains the following information:
- hash of the compiled contract
- smart-contract metadata (title, description, version, author,
email, has-storage, has-dynamic-invoke, is-payable)
- smart-contract entry point
- functions
- events
However, this .abi.json file is slightly different from the one,
described in manifest.go, so we have to add auxilaury stractures for
json marshalling. The .abi.json format used by NEO-Express is described
[here](https://github.com/neo-project/neo-devpack-dotnet/blob/master/src/Neo.Compiler.MSIL/FuncExport.cs#L66).
2020-04-28 16:39:01 +00:00
}
return conf , nil
}