Merge pull request #1797 from nspcc-dev/rpc/fix-createtxfromscript

rpc, cli: allow to provide cosigners accounts to (*Client).CreateTxFromScript
This commit is contained in:
Roman Khimov 2021-03-04 11:28:09 +03:00 committed by GitHub
commit 0e7bb5cc77
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 197 additions and 60 deletions

View file

@ -14,6 +14,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/config" "github.com/nspcc-dev/neo-go/pkg/config"
"github.com/nspcc-dev/neo-go/pkg/core/interop/storage" "github.com/nspcc-dev/neo-go/pkg/core/interop/storage"
"github.com/nspcc-dev/neo-go/pkg/core/state" "github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
@ -22,6 +23,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm" "github.com/nspcc-dev/neo-go/pkg/vm"
"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/wallet"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@ -275,6 +277,78 @@ func TestComlileAndInvokeFunction(t *testing.T) {
}) })
}) })
t.Run("real invoke and save tx", func(t *testing.T) {
txout := path.Join(tmpDir, "test_contract_tx.json")
nefName = path.Join(tmpDir, "verify.nef")
manifestName = path.Join(tmpDir, "verify.manifest.json")
e.Run(t, "neo-go", "contract", "compile",
"--in", "testdata/verify.go",
"--config", "testdata/verify.yml",
"--out", nefName, "--manifest", manifestName)
e.In.WriteString("one\r")
e.Run(t, "neo-go", "contract", "deploy",
"--rpc-endpoint", "http://"+e.RPC.Addr,
"--wallet", validatorWallet, "--address", validatorAddr,
"--in", nefName, "--manifest", manifestName)
line, err := e.Out.ReadString('\n')
require.NoError(t, err)
line = strings.TrimSpace(strings.TrimPrefix(line, "Contract: "))
hVerify, err := util.Uint160DecodeStringLE(line)
require.NoError(t, err)
e.checkTxPersisted(t)
cmd = []string{"neo-go", "contract", "invokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr,
"--out", txout,
"--wallet", validatorWallet, "--address", validatorAddr,
}
t.Run("without cosigner", func(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, append(cmd, hVerify.StringLE(), "verify")...)
})
t.Run("with cosigner", func(t *testing.T) {
t.Run("cosigner is sender", func(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, append(cmd, hVerify.StringLE(), "verify", "--", validatorAddr+":Global")...)
})
acc, err := wallet.NewAccount()
require.NoError(t, err)
pk, err := keys.NewPrivateKey()
require.NoError(t, err)
acc.ConvertMultisig(2, keys.PublicKeys{acc.PrivateKey().PublicKey(), pk.PublicKey()})
t.Run("cosigner is multisig account", func(t *testing.T) {
t.Run("missing in the wallet", func(t *testing.T) {
e.In.WriteString("one\r")
e.RunWithError(t, append(cmd, hVerify.StringLE(), "verify", "--", acc.Address)...)
})
t.Run("good", func(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, append(cmd, hVerify.StringLE(), "verify", "--", multisigAddr)...)
})
})
t.Run("cosigner is deployed contract", func(t *testing.T) {
t.Run("missing in the wallet", func(t *testing.T) {
e.In.WriteString("one\r")
e.RunWithError(t, append(cmd, hVerify.StringLE(), "verify", "--", h.StringLE())...)
})
t.Run("good", func(t *testing.T) {
e.In.WriteString("one\r")
e.Run(t, append(cmd, hVerify.StringLE(), "verify", "--", hVerify.StringLE())...)
})
})
})
})
t.Run("test Storage.Find", func(t *testing.T) { t.Run("test Storage.Find", func(t *testing.T) {
cmd := []string{"neo-go", "contract", "testinvokefunction", cmd := []string{"neo-go", "contract", "testinvokefunction",
"--rpc-endpoint", "http://" + e.RPC.Addr, "--rpc-endpoint", "http://" + e.RPC.Addr,

View file

@ -32,6 +32,7 @@ import (
const ( const (
validatorWIF = "KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY" validatorWIF = "KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY"
validatorAddr = "NVNvVRW5Q5naSx2k2iZm7xRgtRNGuZppAK" validatorAddr = "NVNvVRW5Q5naSx2k2iZm7xRgtRNGuZppAK"
multisigAddr = "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY"
validatorWallet = "testdata/wallet1_solo.json" validatorWallet = "testdata/wallet1_solo.json"
) )

View file

@ -83,6 +83,11 @@ func TestNEP17Balance(t *testing.T) {
e.checkNextLine(t, "^\\s*Updated\\s*:\\s*"+strconv.FormatUint(uint64(index), 10)) e.checkNextLine(t, "^\\s*Updated\\s*:\\s*"+strconv.FormatUint(uint64(index), 10))
} }
} }
e.checkNextLine(t, "^\\s*$")
addr4, err := address.StringToUint160("NbxpLNCCSWZ9BkYpCYT8NfN1uoxq9Rfbrn") // deployed verify.go contract
require.NoError(t, err)
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr4))
e.checkEOF(t) e.checkEOF(t)
}) })
t.Run("Bad token", func(t *testing.T) { t.Run("Bad token", func(t *testing.T) {

View file

@ -22,6 +22,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/encoding/fixedn" "github.com/nspcc-dev/neo-go/pkg/encoding/fixedn"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result" "github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
"github.com/nspcc-dev/neo-go/pkg/smartcontract" "github.com/nspcc-dev/neo-go/pkg/smartcontract"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
@ -509,15 +510,17 @@ func invokeFunction(ctx *cli.Context) error {
func invokeInternal(ctx *cli.Context, signAndPush bool) error { func invokeInternal(ctx *cli.Context, signAndPush bool) error {
var ( var (
err error err error
gas fixedn.Fixed8 gas fixedn.Fixed8
operation string operation string
params = make([]smartcontract.Parameter, 0) params = make([]smartcontract.Parameter, 0)
paramsStart = 1 paramsStart = 1
cosigners []transaction.Signer cosigners []transaction.Signer
cosignersOffset = 0 cosignersAccounts []client.SignerAccount
resp *result.Invoke cosignersOffset = 0
acc *wallet.Account resp *result.Invoke
acc *wallet.Account
wall *wallet.Wallet
) )
args := ctx.Args() args := ctx.Args()
@ -554,10 +557,20 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
if signAndPush { if signAndPush {
gas = flags.Fixed8FromContext(ctx, "gas") gas = flags.Fixed8FromContext(ctx, "gas")
acc, err = getAccFromContext(ctx) acc, wall, err = getAccFromContext(ctx)
if err != nil { if err != nil {
return err return err
} }
for i := range cosigners {
cosignerAcc := wall.GetAccount(cosigners[i].Account)
if cosignerAcc == nil {
return cli.NewExitError(fmt.Errorf("can't calculate network fee: no account was found in the wallet for cosigner #%d", i), 1)
}
cosignersAccounts = append(cosignersAccounts, client.SignerAccount{
Signer: cosigners[i],
Account: cosignerAcc,
})
}
} }
gctx, cancel := options.GetTimeoutContext(ctx) gctx, cancel := options.GetTimeoutContext(ctx)
defer cancel() defer cancel()
@ -579,7 +592,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
fmt.Fprintln(ctx.App.Writer, errText+". Sending transaction...") fmt.Fprintln(ctx.App.Writer, errText+". Sending transaction...")
} }
if out := ctx.String("out"); out != "" { if out := ctx.String("out"); out != "" {
tx, err := c.CreateTxFromScript(resp.Script, acc, resp.GasConsumed, int64(gas), cosigners...) tx, err := c.CreateTxFromScript(resp.Script, acc, resp.GasConsumed, int64(gas), cosignersAccounts)
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("failed to create tx: %w", err), 1) return cli.NewExitError(fmt.Errorf("failed to create tx: %w", err), 1)
} }
@ -593,7 +606,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
if len(resp.Script) == 0 { if len(resp.Script) == 0 {
return cli.NewExitError(errors.New("no script returned from the RPC node"), 1) return cli.NewExitError(errors.New("no script returned from the RPC node"), 1)
} }
txHash, err := c.SignAndPushInvocationTx(resp.Script, acc, resp.GasConsumed, gas, cosigners) txHash, err := c.SignAndPushInvocationTx(resp.Script, acc, resp.GasConsumed, gas, cosignersAccounts)
if err != nil { if err != nil {
return cli.NewExitError(fmt.Errorf("failed to push invocation tx: %w", err), 1) return cli.NewExitError(fmt.Errorf("failed to push invocation tx: %w", err), 1)
} }
@ -747,17 +760,17 @@ func inspect(ctx *cli.Context) error {
return nil return nil
} }
func getAccFromContext(ctx *cli.Context) (*wallet.Account, error) { func getAccFromContext(ctx *cli.Context) (*wallet.Account, *wallet.Wallet, error) {
var addr util.Uint160 var addr util.Uint160
wPath := ctx.String("wallet") wPath := ctx.String("wallet")
if len(wPath) == 0 { if len(wPath) == 0 {
return nil, cli.NewExitError(errNoWallet, 1) return nil, nil, cli.NewExitError(errNoWallet, 1)
} }
wall, err := wallet.NewWalletFromFile(wPath) wall, err := wallet.NewWalletFromFile(wPath)
if err != nil { if err != nil {
return nil, cli.NewExitError(err, 1) return nil, nil, cli.NewExitError(err, 1)
} }
addrFlag := ctx.Generic("address").(*flags.Address) addrFlag := ctx.Generic("address").(*flags.Address)
if addrFlag.IsSet { if addrFlag.IsSet {
@ -767,20 +780,20 @@ func getAccFromContext(ctx *cli.Context) (*wallet.Account, error) {
} }
acc := wall.GetAccount(addr) acc := wall.GetAccount(addr)
if acc == nil { if acc == nil {
return nil, cli.NewExitError(fmt.Errorf("wallet contains no account for '%s'", address.Uint160ToString(addr)), 1) return nil, nil, cli.NewExitError(fmt.Errorf("wallet contains no account for '%s'", address.Uint160ToString(addr)), 1)
} }
rawPass, err := input.ReadPassword( rawPass, err := input.ReadPassword(
fmt.Sprintf("Enter account %s password > ", address.Uint160ToString(addr))) fmt.Sprintf("Enter account %s password > ", address.Uint160ToString(addr)))
if err != nil { if err != nil {
return nil, cli.NewExitError(err, 1) return nil, nil, cli.NewExitError(err, 1)
} }
pass := strings.TrimRight(string(rawPass), "\n") pass := strings.TrimRight(string(rawPass), "\n")
err = acc.Decrypt(pass) err = acc.Decrypt(pass)
if err != nil { if err != nil {
return nil, cli.NewExitError(err, 1) return nil, nil, cli.NewExitError(err, 1)
} }
return acc, nil return acc, wall, nil
} }
// contractDeploy deploys contract. // contractDeploy deploys contract.
@ -795,7 +808,7 @@ func contractDeploy(ctx *cli.Context) error {
} }
gas := flags.Fixed8FromContext(ctx, "gas") gas := flags.Fixed8FromContext(ctx, "gas")
acc, err := getAccFromContext(ctx) acc, _, err := getAccFromContext(ctx)
if err != nil { if err != nil {
return err return err
} }

View file

@ -1,8 +1,10 @@
package testdata package testdata
import "github.com/nspcc-dev/neo-go/pkg/interop"
func Verify() bool { func Verify() bool {
return true return true
} }
func OnNEP17Payment(from []byte, amount int, data interface{}) { func OnNEP17Payment(from interop.Hash160, amount int, data interface{}) {
} }

1
cli/testdata/verify.yml vendored Normal file
View file

@ -0,0 +1 @@
name: Test verify

View file

@ -59,6 +59,18 @@
}, },
"lock": false, "lock": false,
"isdefault": false "isdefault": false
},
{
"address" : "NbxpLNCCSWZ9BkYpCYT8NfN1uoxq9Rfbrn",
"key" : "6PYXDze5Ak4HahYKygcNzk6n65ACjWdDCYLSuKgA5KG8vyMJSFboUNSiPD",
"label" : "",
"contract" : {
"script" : "VwEAEUBXAANA",
"deployed" : true,
"parameters" : []
},
"lock" : false,
"isdefault" : false
} }
], ],
"scrypt": { "scrypt": {

View file

@ -11,6 +11,7 @@ import (
"github.com/nspcc-dev/neo-go/pkg/crypto/keys" "github.com/nspcc-dev/neo-go/pkg/crypto/keys"
"github.com/nspcc-dev/neo-go/pkg/encoding/address" "github.com/nspcc-dev/neo-go/pkg/encoding/address"
"github.com/nspcc-dev/neo-go/pkg/io" "github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/rpc/client"
"github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag" "github.com/nspcc-dev/neo-go/pkg/smartcontract/callflag"
"github.com/nspcc-dev/neo-go/pkg/util" "github.com/nspcc-dev/neo-go/pkg/util"
"github.com/nspcc-dev/neo-go/pkg/vm/emit" "github.com/nspcc-dev/neo-go/pkg/vm/emit"
@ -108,9 +109,13 @@ func handleCandidate(ctx *cli.Context, method string, sysGas int64) error {
w := io.NewBufBinWriter() w := io.NewBufBinWriter()
emit.AppCall(w.BinWriter, neoContractHash, method, callflag.States, acc.PrivateKey().PublicKey().Bytes()) emit.AppCall(w.BinWriter, neoContractHash, method, callflag.States, acc.PrivateKey().PublicKey().Bytes())
emit.Opcodes(w.BinWriter, opcode.ASSERT) emit.Opcodes(w.BinWriter, opcode.ASSERT)
tx, err := c.CreateTxFromScript(w.Bytes(), acc, sysGas, int64(gas), transaction.Signer{ tx, err := c.CreateTxFromScript(w.Bytes(), acc, sysGas, int64(gas), []client.SignerAccount{{
Account: acc.Contract.ScriptHash(), Signer: transaction.Signer{
Scopes: transaction.CalledByEntry, Account: acc.Contract.ScriptHash(),
Scopes: transaction.CalledByEntry,
},
Account: acc,
},
}) })
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(err, 1)
@ -171,10 +176,13 @@ func handleVote(ctx *cli.Context) error {
emit.AppCall(w.BinWriter, neoContractHash, "vote", callflag.States, addr.BytesBE(), pubArg) emit.AppCall(w.BinWriter, neoContractHash, "vote", callflag.States, addr.BytesBE(), pubArg)
emit.Opcodes(w.BinWriter, opcode.ASSERT) emit.Opcodes(w.BinWriter, opcode.ASSERT)
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas), transaction.Signer{ tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas), []client.SignerAccount{{
Account: acc.Contract.ScriptHash(), Signer: transaction.Signer{
Scopes: transaction.CalledByEntry, Account: acc.Contract.ScriptHash(),
}) Scopes: transaction.CalledByEntry,
},
Account: acc,
}})
if err != nil { if err != nil {
return cli.NewExitError(err, 1) return cli.NewExitError(err, 1)
} }

View file

@ -24,6 +24,13 @@ type TransferTarget struct {
Amount int64 Amount int64
} }
// SignerAccount represents combination of the transaction.Signer and the
// corresponding wallet.Account.
type SignerAccount struct {
Signer transaction.Signer
Account *wallet.Account
}
// NEP17Decimals invokes `decimals` NEP17 method on a specified contract. // NEP17Decimals invokes `decimals` NEP17 method on a specified contract.
func (c *Client) NEP17Decimals(tokenHash util.Uint160) (int64, error) { func (c *Client) NEP17Decimals(tokenHash util.Uint160) (int64, error) {
result, err := c.InvokeFunction(tokenHash, "decimals", []smartcontract.Parameter{}, nil) result, err := c.InvokeFunction(tokenHash, "decimals", []smartcontract.Parameter{}, nil)
@ -140,23 +147,24 @@ func (c *Client) CreateNEP17MultiTransferTx(acc *wallet.Account, gas int64, reci
if err != nil { if err != nil {
return nil, fmt.Errorf("bad account address: %v", err) return nil, fmt.Errorf("bad account address: %v", err)
} }
return c.CreateTxFromScript(w.Bytes(), acc, -1, gas, transaction.Signer{ return c.CreateTxFromScript(w.Bytes(), acc, -1, gas, []SignerAccount{{
Account: accAddr, Signer: transaction.Signer{
Scopes: transaction.CalledByEntry, Account: accAddr,
}) Scopes: transaction.CalledByEntry,
},
Account: acc,
}})
} }
// CreateTxFromScript creates transaction and properly sets cosigners and NetworkFee. // CreateTxFromScript creates transaction and properly sets cosigners and NetworkFee.
// If sysFee <= 0, it is determined via result of `invokescript` RPC. You should // If sysFee <= 0, it is determined via result of `invokescript` RPC. You should
// initialize network magic with Init before calling CreateTxFromScript. // initialize network magic with Init before calling CreateTxFromScript.
func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, netFee int64, func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, netFee int64,
cosigners ...transaction.Signer) (*transaction.Transaction, error) { cosigners []SignerAccount) (*transaction.Transaction, error) {
from, err := address.StringToUint160(acc.Address) signers, accounts, err := getSigners(acc, cosigners)
if err != nil { if err != nil {
return nil, fmt.Errorf("bad account address: %v", err) return nil, fmt.Errorf("failed to construct tx signers: %w", err)
} }
signers := getSigners(from, cosigners)
if sysFee < 0 { if sysFee < 0 {
result, err := c.InvokeScript(script, signers) result, err := c.InvokeScript(script, signers)
if err != nil { if err != nil {
@ -179,7 +187,7 @@ func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee,
return nil, fmt.Errorf("failed to add validUntilBlock to transaction: %w", err) return nil, fmt.Errorf("failed to add validUntilBlock to transaction: %w", err)
} }
err = c.AddNetworkFee(tx, netFee, acc) err = c.AddNetworkFee(tx, netFee, accounts...)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to add network fee: %w", err) return nil, fmt.Errorf("failed to add network fee: %w", err)
} }

View file

@ -522,11 +522,11 @@ func (c *Client) SubmitRawOracleResponse(ps request.RawParams) error {
// SignAndPushInvocationTx signs and pushes given script as an invocation // SignAndPushInvocationTx signs and pushes given script as an invocation
// transaction using given wif to sign it and spending the amount of gas // transaction using given wif to sign it and spending the amount of gas
// specified. It returns a hash of the invocation transaction and an error. // specified. It returns a hash of the invocation transaction and an error.
func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sysfee int64, netfee fixedn.Fixed8, cosigners []transaction.Signer) (util.Uint256, error) { func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sysfee int64, netfee fixedn.Fixed8, cosigners []SignerAccount) (util.Uint256, error) {
var txHash util.Uint256 var txHash util.Uint256
var err error var err error
tx, err := c.CreateTxFromScript(script, acc, sysfee, int64(netfee), cosigners...) tx, err := c.CreateTxFromScript(script, acc, sysfee, int64(netfee), cosigners)
if err != nil { if err != nil {
return txHash, fmt.Errorf("failed to create tx: %w", err) return txHash, fmt.Errorf("failed to create tx: %w", err)
} }
@ -544,25 +544,33 @@ func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sys
return txHash, nil return txHash, nil
} }
// getSigners returns an array of transaction signers from given sender and cosigners. // getSigners returns an array of transaction signers and corresponding accounts from
// If cosigners list already contains sender, the sender will be placed at the start of // given sender and cosigners. If cosigners list already contains sender, the sender
// the list. // will be placed at the start of the list.
func getSigners(sender util.Uint160, cosigners []transaction.Signer) []transaction.Signer { func getSigners(sender *wallet.Account, cosigners []SignerAccount) ([]transaction.Signer, []*wallet.Account, error) {
var (
signers []transaction.Signer
accounts []*wallet.Account
)
from, err := address.StringToUint160(sender.Address)
if err != nil {
return nil, nil, fmt.Errorf("bad sender account address: %v", err)
}
s := transaction.Signer{ s := transaction.Signer{
Account: sender, Account: from,
Scopes: transaction.None, Scopes: transaction.None,
} }
for i, c := range cosigners { for _, c := range cosigners {
if c.Account == sender { if c.Signer.Account == from {
if i == 0 { s.Scopes = c.Signer.Scopes
return cosigners continue
}
s.Scopes = c.Scopes
cosigners = append(cosigners[:i], cosigners[i+1:]...)
break
} }
signers = append(signers, c.Signer)
accounts = append(accounts, c.Account)
} }
return append([]transaction.Signer{s}, cosigners...) signers = append([]transaction.Signer{s}, signers...)
accounts = append([]*wallet.Account{sender}, accounts...)
return signers, accounts, nil
} }
// SignAndPushP2PNotaryRequest creates and pushes P2PNotary request constructed from the main // SignAndPushP2PNotaryRequest creates and pushes P2PNotary request constructed from the main

View file

@ -203,10 +203,15 @@ func TestSignAndPushInvocationTx(t *testing.T) {
priv := testchain.PrivateKey(0) priv := testchain.PrivateKey(0)
acc := wallet.NewAccountFromPrivateKey(priv) acc := wallet.NewAccountFromPrivateKey(priv)
h, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc, 30, 0, []transaction.Signer{{ h, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc, 30, 0, []client.SignerAccount{
Account: priv.GetScriptHash(), {
Scopes: transaction.CalledByEntry, Signer: transaction.Signer{
}}) Account: priv.GetScriptHash(),
Scopes: transaction.CalledByEntry,
},
Account: acc,
},
})
require.NoError(t, err) require.NoError(t, err)
mp := chain.GetMemPool() mp := chain.GetMemPool()
@ -347,7 +352,7 @@ func TestCreateTxFromScript(t *testing.T) {
priv := testchain.PrivateKey(0) priv := testchain.PrivateKey(0)
acc := wallet.NewAccountFromPrivateKey(priv) acc := wallet.NewAccountFromPrivateKey(priv)
t.Run("NoSystemFee", func(t *testing.T) { t.Run("NoSystemFee", func(t *testing.T) {
tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, -1, 10) tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, -1, 10, nil)
require.NoError(t, err) require.NoError(t, err)
require.True(t, tx.ValidUntilBlock > chain.BlockHeight()) require.True(t, tx.ValidUntilBlock > chain.BlockHeight())
require.EqualValues(t, 30, tx.SystemFee) // PUSH1 require.EqualValues(t, 30, tx.SystemFee) // PUSH1
@ -355,7 +360,7 @@ func TestCreateTxFromScript(t *testing.T) {
require.Equal(t, acc.PrivateKey().GetScriptHash(), tx.Signers[0].Account) require.Equal(t, acc.PrivateKey().GetScriptHash(), tx.Signers[0].Account)
}) })
t.Run("ProvideSystemFee", func(t *testing.T) { t.Run("ProvideSystemFee", func(t *testing.T) {
tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, 123, 10) tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, 123, 10, nil)
require.NoError(t, err) require.NoError(t, err)
require.True(t, tx.ValidUntilBlock > chain.BlockHeight()) require.True(t, tx.ValidUntilBlock > chain.BlockHeight())
require.EqualValues(t, 123, tx.SystemFee) require.EqualValues(t, 123, tx.SystemFee)