Merge pull request #1139 from nspcc-dev/fix-deployment-sysfee-and-invokes

Fix deployment sysfee and invokes
This commit is contained in:
Roman Khimov 2020-07-03 10:11:23 +03:00 committed by GitHub
commit 6cd166fb7a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 63 additions and 50 deletions

View file

@ -399,8 +399,10 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
if !args.Present() {
return cli.NewExitError(errNoScriptHash, 1)
}
script := args[0]
script, err := util.Uint160DecodeStringLE(args[0])
if err != nil {
return cli.NewExitError(fmt.Errorf("incorrect script hash: %v", err), 1)
}
if len(args) <= 1 {
return cli.NewExitError(errNoMethod, 1)
}
@ -510,8 +512,7 @@ func testInvokeScript(ctx *cli.Context) error {
return err
}
scriptHex := hex.EncodeToString(nefFile.Script)
resp, err := c.InvokeScript(scriptHex, cosigners)
resp, err := c.InvokeScript(nefFile.Script, cosigners)
if err != nil {
return cli.NewExitError(err, 1)
}
@ -654,12 +655,17 @@ func contractDeploy(ctx *cli.Context) error {
return err
}
txScript, sysfee, err := request.CreateDeploymentScript(nefFile.Script, m)
txScript, err := request.CreateDeploymentScript(nefFile.Script, m)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to create deployment script: %v", err), 1)
}
// It doesn't require any cosigners.
invRes, err := c.InvokeScript(txScript, nil)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to test-invoke deployment script: %v", err), 1)
}
txHash, err := c.SignAndPushInvocationTx(txScript, acc, sysfee, gas)
txHash, err := c.SignAndPushInvocationTx(txScript, acc, invRes.GasConsumed, gas)
if err != nil {
return cli.NewExitError(fmt.Errorf("failed to push invocation tx: %v", err), 1)
}

View file

@ -1,7 +1,6 @@
package client
import (
"encoding/hex"
"errors"
"fmt"
@ -25,7 +24,7 @@ var (
// NEP5Decimals invokes `decimals` NEP5 method on a specified contract.
func (c *Client) NEP5Decimals(tokenHash util.Uint160) (int64, error) {
result, err := c.InvokeFunction(tokenHash.StringLE(), "decimals", []smartcontract.Parameter{}, nil)
result, err := c.InvokeFunction(tokenHash, "decimals", []smartcontract.Parameter{}, nil)
if err != nil {
return 0, err
} else if result.State != "HALT" || len(result.Stack) == 0 {
@ -37,7 +36,7 @@ func (c *Client) NEP5Decimals(tokenHash util.Uint160) (int64, error) {
// NEP5Name invokes `name` NEP5 method on a specified contract.
func (c *Client) NEP5Name(tokenHash util.Uint160) (string, error) {
result, err := c.InvokeFunction(tokenHash.StringLE(), "name", []smartcontract.Parameter{}, nil)
result, err := c.InvokeFunction(tokenHash, "name", []smartcontract.Parameter{}, nil)
if err != nil {
return "", err
} else if result.State != "HALT" || len(result.Stack) == 0 {
@ -49,7 +48,7 @@ func (c *Client) NEP5Name(tokenHash util.Uint160) (string, error) {
// NEP5Symbol invokes `symbol` NEP5 method on a specified contract.
func (c *Client) NEP5Symbol(tokenHash util.Uint160) (string, error) {
result, err := c.InvokeFunction(tokenHash.StringLE(), "symbol", []smartcontract.Parameter{}, nil)
result, err := c.InvokeFunction(tokenHash, "symbol", []smartcontract.Parameter{}, nil)
if err != nil {
return "", err
} else if result.State != "HALT" || len(result.Stack) == 0 {
@ -61,7 +60,7 @@ func (c *Client) NEP5Symbol(tokenHash util.Uint160) (string, error) {
// NEP5TotalSupply invokes `totalSupply` NEP5 method on a specified contract.
func (c *Client) NEP5TotalSupply(tokenHash util.Uint160) (int64, error) {
result, err := c.InvokeFunction(tokenHash.StringLE(), "totalSupply", []smartcontract.Parameter{}, nil)
result, err := c.InvokeFunction(tokenHash, "totalSupply", []smartcontract.Parameter{}, nil)
if err != nil {
return 0, err
} else if result.State != "HALT" || len(result.Stack) == 0 {
@ -73,7 +72,7 @@ func (c *Client) NEP5TotalSupply(tokenHash util.Uint160) (int64, error) {
// NEP5BalanceOf invokes `balanceOf` NEP5 method on a specified contract.
func (c *Client) NEP5BalanceOf(tokenHash util.Uint160) (int64, error) {
result, err := c.InvokeFunction(tokenHash.StringLE(), "balanceOf", []smartcontract.Parameter{}, nil)
result, err := c.InvokeFunction(tokenHash, "balanceOf", []smartcontract.Parameter{}, nil)
if err != nil {
return 0, err
} else if result.State != "HALT" || len(result.Stack) == 0 {
@ -127,7 +126,7 @@ func (c *Client) CreateNEP5TransferTx(acc *wallet.Account, to util.Uint160, toke
},
}
result, err := c.InvokeScript(hex.EncodeToString(script), []transaction.Cosigner{
result, err := c.InvokeScript(script, []transaction.Cosigner{
{
Account: from,
Scopes: transaction.Global,

View file

@ -29,7 +29,7 @@ func (c *Client) GetFeePerByte() (int64, error) {
}
func (c *Client) invokeNativePolicyMethod(operation string) (int64, error) {
result, err := c.InvokeFunction(PolicyContractHash.StringLE(), operation, []smartcontract.Parameter{}, nil)
result, err := c.InvokeFunction(PolicyContractHash, operation, []smartcontract.Parameter{}, nil)
if err != nil {
return 0, err
} else if result.State != "HALT" || len(result.Stack) == 0 {
@ -41,7 +41,7 @@ func (c *Client) invokeNativePolicyMethod(operation string) (int64, error) {
// GetBlockedAccounts invokes `getBlockedAccounts` method on a native Policy contract.
func (c *Client) GetBlockedAccounts() (native.BlockedAccounts, error) {
result, err := c.InvokeFunction(PolicyContractHash.StringLE(), "getBlockedAccounts", []smartcontract.Parameter{}, nil)
result, err := c.InvokeFunction(PolicyContractHash, "getBlockedAccounts", []smartcontract.Parameter{}, nil)
if err != nil {
return nil, err
} else if result.State != "HALT" || len(result.Stack) == 0 {

View file

@ -349,36 +349,38 @@ func (c *Client) GetVersion() (*result.Version, error) {
// InvokeScript returns the result of the given script after running it true the VM.
// NOTE: This is a test invoke and will not affect the blockchain.
func (c *Client) InvokeScript(script string, cosigners []transaction.Cosigner) (*result.Invoke, error) {
var (
params request.RawParams
resp = &result.Invoke{}
)
if cosigners != nil {
params = request.NewRawParams(script, cosigners)
} else {
params = request.NewRawParams(script)
}
if err := c.performRequest("invokescript", params, resp); err != nil {
return nil, err
}
return resp, nil
func (c *Client) InvokeScript(script []byte, cosigners []transaction.Cosigner) (*result.Invoke, error) {
var p = request.NewRawParams(hex.EncodeToString(script))
return c.invokeSomething("invokescript", p, cosigners)
}
// InvokeFunction returns the results after calling the smart contract scripthash
// with the given operation and parameters.
// NOTE: this is test invoke and will not affect the blockchain.
func (c *Client) InvokeFunction(script, operation string, params []smartcontract.Parameter, cosigners []transaction.Cosigner) (*result.Invoke, error) {
var (
p request.RawParams
resp = &result.Invoke{}
)
func (c *Client) InvokeFunction(contract util.Uint160, operation string, params []smartcontract.Parameter, cosigners []transaction.Cosigner) (*result.Invoke, error) {
var p = request.NewRawParams(contract.StringLE(), operation, params)
return c.invokeSomething("invokefunction", p, cosigners)
}
// invokeSomething is an inner wrapper for Invoke* functions
func (c *Client) invokeSomething(method string, p request.RawParams, cosigners []transaction.Cosigner) (*result.Invoke, error) {
var resp = new(result.Invoke)
if cosigners != nil {
p = request.NewRawParams(script, operation, params, cosigners)
} else {
p = request.NewRawParams(script, operation, params)
p.Values = append(p.Values, cosigners)
}
if err := c.performRequest("invokefunction", p, resp); err != nil {
if err := c.performRequest(method, p, resp); err != nil {
// Retry with old-fashioned hashes (see neo/neo-modules#260).
if cosigners != nil {
var hashes = make([]util.Uint160, len(cosigners))
for i := range cosigners {
hashes[i] = cosigners[i].Account
}
p.Values[len(p.Values)-1] = hashes
err = c.performRequest(method, p, resp)
if err == nil {
return resp, nil
}
}
return nil, err
}
return resp, nil

View file

@ -616,7 +616,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
if err != nil {
panic(err)
}
return c.InvokeFunction("af7c7328eee5a275a3bcaee2bf0cf662b5e739be", "balanceOf", []smartcontract.Parameter{
contr, err := util.Uint160DecodeStringLE("af7c7328eee5a275a3bcaee2bf0cf662b5e739be")
if err != nil {
panic(err)
}
return c.InvokeFunction(contr, "balanceOf", []smartcontract.Parameter{
{
Type: smartcontract.Hash160Type,
Value: hash,
@ -649,7 +653,11 @@ var rpcClientTestCases = map[string][]rpcClientTestCase{
{
name: "positive",
invoke: func(c *Client) (interface{}, error) {
return c.InvokeScript("00046e616d656724058e5e1b6008847cd662728549088a9ee82191", []transaction.Cosigner{{
script, err := hex.DecodeString("00046e616d656724058e5e1b6008847cd662728549088a9ee82191")
if err != nil {
panic(err)
}
return c.InvokeScript(script, []transaction.Cosigner{{
Account: util.Uint160{1, 2, 3},
}})
},
@ -952,13 +960,13 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
{
name: "invokefunction_invalid_params_error",
invoke: func(c *Client) (interface{}, error) {
return c.InvokeFunction("", "", []smartcontract.Parameter{}, nil)
return c.InvokeFunction(util.Uint160{}, "", []smartcontract.Parameter{}, nil)
},
},
{
name: "invokescript_invalid_params_error",
invoke: func(c *Client) (interface{}, error) {
return c.InvokeScript("", nil)
return c.InvokeScript([]byte{}, nil)
},
},
{
@ -1134,13 +1142,13 @@ var rpcClientErrorCases = map[string][]rpcClientErrorCase{
{
name: "invokefunction_unmarshalling_error",
invoke: func(c *Client) (interface{}, error) {
return c.InvokeFunction("", "", []smartcontract.Parameter{}, nil)
return c.InvokeFunction(util.Uint160{}, "", []smartcontract.Parameter{}, nil)
},
},
{
name: "invokescript_unmarshalling_error",
invoke: func(c *Client) (interface{}, error) {
return c.InvokeScript("", nil)
return c.InvokeScript([]byte{}, nil)
},
},
{

View file

@ -5,7 +5,6 @@ import (
"fmt"
"strconv"
"github.com/nspcc-dev/neo-go/pkg/core"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/smartcontract"
@ -16,18 +15,17 @@ import (
)
// CreateDeploymentScript returns a script that deploys given smart contract
// with its metadata and system fee require for this.
func CreateDeploymentScript(avm []byte, manif *manifest.Manifest) ([]byte, int64, error) {
// with its metadata.
func CreateDeploymentScript(avm []byte, manif *manifest.Manifest) ([]byte, error) {
script := io.NewBufBinWriter()
rawManifest, err := manif.MarshalJSON()
if err != nil {
return nil, 0, err
return nil, err
}
emit.Bytes(script.BinWriter, rawManifest)
emit.Bytes(script.BinWriter, avm)
emit.Syscall(script.BinWriter, "System.Contract.Create")
sysfee := int64(core.StoragePrice * (len(avm) + len(rawManifest)))
return script.Bytes(), sysfee, nil
return script.Bytes(), nil
}
// expandArrayIntoScript pushes all FuncParam parameters from the given array