rpc/client: use CreateTxFromScript
where possible
There is substantial overlap between `CreateTxFromScript` and `SignAndPushInvocationTx`. This commit refactors both of them to reuse common code.
This commit is contained in:
parent
16b10ab918
commit
6bdaefcfa4
4 changed files with 54 additions and 46 deletions
|
@ -100,7 +100,7 @@ func handleCandidate(ctx *cli.Context, method string) error {
|
||||||
w := io.NewBufBinWriter()
|
w := io.NewBufBinWriter()
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, method, acc.PrivateKey().PublicKey().Bytes())
|
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, method, acc.PrivateKey().PublicKey().Bytes())
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
||||||
tx, err := c.CreateTxFromScript(w.Bytes(), acc, int64(gas))
|
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(err, 1)
|
return cli.NewExitError(err, 1)
|
||||||
} else if err = acc.SignTx(tx); err != nil {
|
} else if err = acc.SignTx(tx); err != nil {
|
||||||
|
@ -155,7 +155,7 @@ func handleVote(ctx *cli.Context) error {
|
||||||
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, "vote", addr.BytesBE(), pubArg)
|
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, "vote", addr.BytesBE(), pubArg)
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
||||||
|
|
||||||
tx, err := c.CreateTxFromScript(w.Bytes(), acc, int64(gas))
|
tx, err := c.CreateTxFromScript(w.Bytes(), acc, -1, int64(gas))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cli.NewExitError(err, 1)
|
return cli.NewExitError(err, 1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,39 +134,38 @@ func (c *Client) CreateNEP5MultiTransferTx(acc *wallet.Account, gas int64, recip
|
||||||
recipients[i].Address, recipients[i].Amount)
|
recipients[i].Address, recipients[i].Amount)
|
||||||
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
emit.Opcode(w.BinWriter, opcode.ASSERT)
|
||||||
}
|
}
|
||||||
return c.CreateTxFromScript(w.Bytes(), acc, gas)
|
return c.CreateTxFromScript(w.Bytes(), acc, -1, gas)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateTxFromScript creates transaction and properly sets cosigners and NetworkFee.
|
// CreateTxFromScript creates transaction and properly sets cosigners and NetworkFee.
|
||||||
func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, gas int64) (*transaction.Transaction, error) {
|
// If sysFee <= 0, it is determined via result of `invokescript` RPC.
|
||||||
|
func (c *Client) CreateTxFromScript(script []byte, acc *wallet.Account, sysFee, netFee int64,
|
||||||
|
cosigners ...transaction.Signer) (*transaction.Transaction, error) {
|
||||||
from, err := address.StringToUint160(acc.Address)
|
from, err := address.StringToUint160(acc.Address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("bad account address: %v", err)
|
return nil, fmt.Errorf("bad account address: %v", err)
|
||||||
}
|
}
|
||||||
result, err := c.InvokeScript(script, []transaction.Signer{
|
|
||||||
{
|
signers := getSigners(from, cosigners)
|
||||||
Account: from,
|
if sysFee < 0 {
|
||||||
Scopes: transaction.CalledByEntry,
|
result, err := c.InvokeScript(script, signers)
|
||||||
},
|
if err != nil {
|
||||||
})
|
return nil, fmt.Errorf("can't add system fee to transaction: %w", err)
|
||||||
if err != nil {
|
}
|
||||||
return nil, fmt.Errorf("can't add system fee to transaction: %w", err)
|
sysFee = result.GasConsumed
|
||||||
}
|
|
||||||
tx := transaction.New(c.opts.Network, script, result.GasConsumed)
|
|
||||||
tx.Signers = []transaction.Signer{
|
|
||||||
{
|
|
||||||
Account: from,
|
|
||||||
Scopes: transaction.CalledByEntry,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
tx.ValidUntilBlock, err = c.CalculateValidUntilBlock()
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("can't calculate validUntilBlock: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.AddNetworkFee(tx, gas, acc)
|
tx := transaction.New(c.opts.Network, script, sysFee)
|
||||||
|
tx.Signers = signers
|
||||||
|
|
||||||
|
tx.ValidUntilBlock, err = c.CalculateValidUntilBlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't add network fee to transaction: %w", err)
|
return nil, fmt.Errorf("failed to add validUntilBlock to transaction: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = c.AddNetworkFee(tx, netFee, acc)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to add network fee: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tx, nil
|
return tx, nil
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
||||||
"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/core/transaction"
|
"github.com/nspcc-dev/neo-go/pkg/core/transaction"
|
||||||
"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/request"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/request"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
"github.com/nspcc-dev/neo-go/pkg/rpc/response/result"
|
||||||
|
@ -410,26 +409,7 @@ func (c *Client) SignAndPushInvocationTx(script []byte, acc *wallet.Account, sys
|
||||||
var txHash util.Uint256
|
var txHash util.Uint256
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
tx := transaction.New(c.opts.Network, script, sysfee)
|
tx, err := c.CreateTxFromScript(script, acc, sysfee, int64(netfee), cosigners...)
|
||||||
tx.SystemFee = sysfee
|
|
||||||
|
|
||||||
addr, err := address.StringToUint160(acc.Address)
|
|
||||||
if err != nil {
|
|
||||||
return txHash, fmt.Errorf("failed to get address: %w", err)
|
|
||||||
}
|
|
||||||
tx.Signers = getSigners(addr, cosigners)
|
|
||||||
|
|
||||||
validUntilBlock, err := c.CalculateValidUntilBlock()
|
|
||||||
if err != nil {
|
|
||||||
return txHash, fmt.Errorf("failed to add validUntilBlock to transaction: %w", err)
|
|
||||||
}
|
|
||||||
tx.ValidUntilBlock = validUntilBlock
|
|
||||||
|
|
||||||
err = c.AddNetworkFee(tx, int64(netfee), acc)
|
|
||||||
if err != nil {
|
|
||||||
return txHash, fmt.Errorf("failed to add network fee: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = acc.SignTx(tx); err != nil {
|
if err = acc.SignTx(tx); err != nil {
|
||||||
return txHash, fmt.Errorf("failed to sign tx: %w", err)
|
return txHash, fmt.Errorf("failed to sign tx: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -169,3 +169,32 @@ func TestPing(t *testing.T) {
|
||||||
httpSrv.Close()
|
httpSrv.Close()
|
||||||
require.Error(t, c.Ping())
|
require.Error(t, c.Ping())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCreateTxFromScript(t *testing.T) {
|
||||||
|
chain, rpcSrv, httpSrv := initServerWithInMemoryChain(t)
|
||||||
|
defer chain.Close()
|
||||||
|
defer rpcSrv.Shutdown()
|
||||||
|
|
||||||
|
c, err := client.New(context.Background(), httpSrv.URL, client.Options{Network: testchain.Network()})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
priv := testchain.PrivateKey(0)
|
||||||
|
acc, err := wallet.NewAccountFromWIF(priv.WIF())
|
||||||
|
require.NoError(t, err)
|
||||||
|
t.Run("NoSystemFee", func(t *testing.T) {
|
||||||
|
tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, -1, 10)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, tx.ValidUntilBlock > chain.BlockHeight())
|
||||||
|
require.EqualValues(t, 30, tx.SystemFee) // PUSH1
|
||||||
|
require.True(t, len(tx.Signers) == 1)
|
||||||
|
require.Equal(t, acc.PrivateKey().GetScriptHash(), tx.Signers[0].Account)
|
||||||
|
})
|
||||||
|
t.Run("ProvideSystemFee", func(t *testing.T) {
|
||||||
|
tx, err := c.CreateTxFromScript([]byte{byte(opcode.PUSH1)}, acc, 123, 10)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.True(t, tx.ValidUntilBlock > chain.BlockHeight())
|
||||||
|
require.EqualValues(t, 123, tx.SystemFee)
|
||||||
|
require.True(t, len(tx.Signers) == 1)
|
||||||
|
require.Equal(t, acc.PrivateKey().GetScriptHash(), tx.Signers[0].Account)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue