mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-26 19:43:48 +00:00
rpc: provide cosigners accounts to CreateTxFromScript
We need to define network fee for each of cosigners, and the only way to do it is to access the cosigner's script.
This commit is contained in:
parent
b1b9a8cf66
commit
6c0faa4ea3
11 changed files with 193 additions and 56 deletions
|
@ -14,6 +14,7 @@ import (
|
|||
"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/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/fixedn"
|
||||
"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/vm"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/stackitem"
|
||||
"github.com/nspcc-dev/neo-go/pkg/wallet"
|
||||
"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) {
|
||||
cmd := []string{"neo-go", "contract", "testinvokefunction",
|
||||
"--rpc-endpoint", "http://" + e.RPC.Addr,
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
const (
|
||||
validatorWIF = "KxyjQ8eUa4FHt3Gvioyt1Wz29cTUrE4eTqX3yFSk1YFCsPL8uNsY"
|
||||
validatorAddr = "NVNvVRW5Q5naSx2k2iZm7xRgtRNGuZppAK"
|
||||
multisigAddr = "NUVPACMnKFhpuHjsRjhUvXz1XhqfGZYVtY"
|
||||
|
||||
validatorWallet = "testdata/wallet1_solo.json"
|
||||
)
|
||||
|
|
|
@ -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*$")
|
||||
addr4, err := address.StringToUint160("NbxpLNCCSWZ9BkYpCYT8NfN1uoxq9Rfbrn") // deployed verify.go contract
|
||||
require.NoError(t, err)
|
||||
e.checkNextLine(t, "^Account "+address.Uint160ToString(addr4))
|
||||
e.checkEOF(t)
|
||||
})
|
||||
t.Run("Bad token", func(t *testing.T) {
|
||||
|
|
|
@ -22,6 +22,7 @@ import (
|
|||
"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/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/smartcontract"
|
||||
"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 {
|
||||
var (
|
||||
err error
|
||||
gas fixedn.Fixed8
|
||||
operation string
|
||||
params = make([]smartcontract.Parameter, 0)
|
||||
paramsStart = 1
|
||||
cosigners []transaction.Signer
|
||||
cosignersOffset = 0
|
||||
resp *result.Invoke
|
||||
acc *wallet.Account
|
||||
err error
|
||||
gas fixedn.Fixed8
|
||||
operation string
|
||||
params = make([]smartcontract.Parameter, 0)
|
||||
paramsStart = 1
|
||||
cosigners []transaction.Signer
|
||||
cosignersAccounts []client.SignerAccount
|
||||
cosignersOffset = 0
|
||||
resp *result.Invoke
|
||||
acc *wallet.Account
|
||||
wall *wallet.Wallet
|
||||
)
|
||||
|
||||
args := ctx.Args()
|
||||
|
@ -554,10 +557,20 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
|
||||
if signAndPush {
|
||||
gas = flags.Fixed8FromContext(ctx, "gas")
|
||||
acc, err = getAccFromContext(ctx)
|
||||
acc, wall, err = getAccFromContext(ctx)
|
||||
if err != nil {
|
||||
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)
|
||||
defer cancel()
|
||||
|
@ -579,7 +592,7 @@ func invokeInternal(ctx *cli.Context, signAndPush bool) error {
|
|||
fmt.Fprintln(ctx.App.Writer, errText+". Sending transaction...")
|
||||
}
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
}
|
||||
|
||||
func getAccFromContext(ctx *cli.Context) (*wallet.Account, error) {
|
||||
func getAccFromContext(ctx *cli.Context) (*wallet.Account, *wallet.Wallet, error) {
|
||||
var addr util.Uint160
|
||||
|
||||
wPath := ctx.String("wallet")
|
||||
if len(wPath) == 0 {
|
||||
return nil, cli.NewExitError(errNoWallet, 1)
|
||||
return nil, nil, cli.NewExitError(errNoWallet, 1)
|
||||
}
|
||||
|
||||
wall, err := wallet.NewWalletFromFile(wPath)
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(err, 1)
|
||||
return nil, nil, cli.NewExitError(err, 1)
|
||||
}
|
||||
addrFlag := ctx.Generic("address").(*flags.Address)
|
||||
if addrFlag.IsSet {
|
||||
|
@ -767,20 +780,20 @@ func getAccFromContext(ctx *cli.Context) (*wallet.Account, error) {
|
|||
}
|
||||
acc := wall.GetAccount(addr)
|
||||
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(
|
||||
fmt.Sprintf("Enter account %s password > ", address.Uint160ToString(addr)))
|
||||
if err != nil {
|
||||
return nil, cli.NewExitError(err, 1)
|
||||
return nil, nil, cli.NewExitError(err, 1)
|
||||
}
|
||||
pass := strings.TrimRight(string(rawPass), "\n")
|
||||
err = acc.Decrypt(pass)
|
||||
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.
|
||||
|
@ -795,7 +808,7 @@ func contractDeploy(ctx *cli.Context) error {
|
|||
}
|
||||
gas := flags.Fixed8FromContext(ctx, "gas")
|
||||
|
||||
acc, err := getAccFromContext(ctx)
|
||||
acc, _, err := getAccFromContext(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
4
cli/testdata/verify.go
vendored
4
cli/testdata/verify.go
vendored
|
@ -1,8 +1,10 @@
|
|||
package testdata
|
||||
|
||||
import "github.com/nspcc-dev/neo-go/pkg/interop"
|
||||
|
||||
func Verify() bool {
|
||||
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
1
cli/testdata/verify.yml
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
name: Test verify
|
12
cli/testdata/wallet1_solo.json
vendored
12
cli/testdata/wallet1_solo.json
vendored
|
@ -59,6 +59,18 @@
|
|||
},
|
||||
"lock": false,
|
||||
"isdefault": false
|
||||
},
|
||||
{
|
||||
"address" : "NbxpLNCCSWZ9BkYpCYT8NfN1uoxq9Rfbrn",
|
||||
"key" : "6PYXDze5Ak4HahYKygcNzk6n65ACjWdDCYLSuKgA5KG8vyMJSFboUNSiPD",
|
||||
"label" : "",
|
||||
"contract" : {
|
||||
"script" : "VwEAEUBXAANA",
|
||||
"deployed" : true,
|
||||
"parameters" : []
|
||||
},
|
||||
"lock" : false,
|
||||
"isdefault" : false
|
||||
}
|
||||
],
|
||||
"scrypt": {
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"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/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/util"
|
||||
"github.com/nspcc-dev/neo-go/pkg/vm/emit"
|
||||
|
@ -108,10 +109,14 @@ func handleCandidate(ctx *cli.Context, method string, sysGas int64) error {
|
|||
w := io.NewBufBinWriter()
|
||||
emit.AppCall(w.BinWriter, neoContractHash, method, callflag.States, acc.PrivateKey().PublicKey().Bytes())
|
||||
emit.Opcodes(w.BinWriter, opcode.ASSERT)
|
||||
tx, err := c.CreateTxFromScript(w.Bytes(), acc, sysGas, int64(gas), []transaction.Signer{{
|
||||
Account: acc.Contract.ScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
}})
|
||||
tx, err := c.CreateTxFromScript(w.Bytes(), acc, sysGas, int64(gas), []client.SignerAccount{{
|
||||
Signer: transaction.Signer{
|
||||
Account: acc.Contract.ScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
Account: acc,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
} else if err = acc.SignTx(tx); err != nil {
|
||||
|
@ -171,9 +176,12 @@ func handleVote(ctx *cli.Context) error {
|
|||
emit.AppCall(w.BinWriter, neoContractHash, "vote", callflag.States, addr.BytesBE(), pubArg)
|
||||
emit.Opcodes(w.BinWriter, opcode.ASSERT)
|
||||
|
||||
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas), []transaction.Signer{{
|
||||
Account: acc.Contract.ScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas), []client.SignerAccount{{
|
||||
Signer: transaction.Signer{
|
||||
Account: acc.Contract.ScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
Account: acc,
|
||||
}})
|
||||
if err != nil {
|
||||
return cli.NewExitError(err, 1)
|
||||
|
|
|
@ -24,6 +24,13 @@ type TransferTarget struct {
|
|||
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.
|
||||
func (c *Client) NEP17Decimals(tokenHash util.Uint160) (int64, error) {
|
||||
result, err := c.InvokeFunction(tokenHash, "decimals", []smartcontract.Parameter{}, nil)
|
||||
|
@ -140,9 +147,12 @@ func (c *Client) CreateNEP17MultiTransferTx(acc *wallet.Account, gas int64, reci
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("bad account address: %v", err)
|
||||
}
|
||||
return c.CreateTxFromScript(w.Bytes(), acc, -1, gas, []transaction.Signer{{
|
||||
Account: accAddr,
|
||||
Scopes: transaction.CalledByEntry,
|
||||
return c.CreateTxFromScript(w.Bytes(), acc, -1, gas, []SignerAccount{{
|
||||
Signer: transaction.Signer{
|
||||
Account: accAddr,
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
Account: acc,
|
||||
}})
|
||||
}
|
||||
|
||||
|
@ -150,13 +160,11 @@ func (c *Client) CreateNEP17MultiTransferTx(acc *wallet.Account, gas int64, reci
|
|||
// If sysFee <= 0, it is determined via result of `invokescript` RPC. You should
|
||||
// initialize network magic with Init before calling CreateTxFromScript.
|
||||
func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, netFee int64,
|
||||
cosigners []transaction.Signer) (*transaction.Transaction, error) {
|
||||
from, err := address.StringToUint160(acc.Address)
|
||||
cosigners []SignerAccount) (*transaction.Transaction, error) {
|
||||
signers, accounts, err := getSigners(acc, cosigners)
|
||||
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 {
|
||||
result, err := c.InvokeScript(script, signers)
|
||||
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)
|
||||
}
|
||||
|
||||
err = c.AddNetworkFee(tx, netFee, acc)
|
||||
err = c.AddNetworkFee(tx, netFee, accounts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to add network fee: %w", err)
|
||||
}
|
||||
|
|
|
@ -522,7 +522,7 @@ func (c *Client) SubmitRawOracleResponse(ps request.RawParams) error {
|
|||
// SignAndPushInvocationTx signs and pushes given script as an invocation
|
||||
// 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.
|
||||
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 err error
|
||||
|
||||
|
@ -544,25 +544,33 @@ func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sys
|
|||
return txHash, nil
|
||||
}
|
||||
|
||||
// getSigners returns an array of transaction signers from given sender and cosigners.
|
||||
// If cosigners list already contains sender, the sender will be placed at the start of
|
||||
// the list.
|
||||
func getSigners(sender util.Uint160, cosigners []transaction.Signer) []transaction.Signer {
|
||||
// getSigners returns an array of transaction signers and corresponding accounts from
|
||||
// given sender and cosigners. If cosigners list already contains sender, the sender
|
||||
// will be placed at the start of the list.
|
||||
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{
|
||||
Account: sender,
|
||||
Account: from,
|
||||
Scopes: transaction.None,
|
||||
}
|
||||
for i, c := range cosigners {
|
||||
if c.Account == sender {
|
||||
if i == 0 {
|
||||
return cosigners
|
||||
}
|
||||
s.Scopes = c.Scopes
|
||||
cosigners = append(cosigners[:i], cosigners[i+1:]...)
|
||||
break
|
||||
for _, c := range cosigners {
|
||||
if c.Signer.Account == from {
|
||||
s.Scopes = c.Signer.Scopes
|
||||
continue
|
||||
}
|
||||
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
|
||||
|
|
|
@ -203,10 +203,15 @@ func TestSignAndPushInvocationTx(t *testing.T) {
|
|||
|
||||
priv := testchain.PrivateKey(0)
|
||||
acc := wallet.NewAccountFromPrivateKey(priv)
|
||||
h, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc, 30, 0, []transaction.Signer{{
|
||||
Account: priv.GetScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
}})
|
||||
h, err := c.SignAndPushInvocationTx([]byte{byte(opcode.PUSH1)}, acc, 30, 0, []client.SignerAccount{
|
||||
{
|
||||
Signer: transaction.Signer{
|
||||
Account: priv.GetScriptHash(),
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
Account: acc,
|
||||
},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
mp := chain.GetMemPool()
|
||||
|
|
Loading…
Reference in a new issue