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()
|
||||
emit.AppCallWithOperationAndArgs(w.BinWriter, client.NeoContractHash, method, acc.PrivateKey().PublicKey().Bytes())
|
||||
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 {
|
||||
return cli.NewExitError(err, 1)
|
||||
} 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.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 {
|
||||
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)
|
||||
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.
|
||||
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)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("bad account address: %v", err)
|
||||
}
|
||||
result, err := c.InvokeScript(script, []transaction.Signer{
|
||||
{
|
||||
Account: from,
|
||||
Scopes: transaction.CalledByEntry,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't add system fee to transaction: %w", err)
|
||||
}
|
||||
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)
|
||||
|
||||
signers := getSigners(from, cosigners)
|
||||
if sysFee < 0 {
|
||||
result, err := c.InvokeScript(script, signers)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("can't add system fee to transaction: %w", err)
|
||||
}
|
||||
sysFee = result.GasConsumed
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"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/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/rpc/request"
|
||||
"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 err error
|
||||
|
||||
tx := transaction.New(c.opts.Network, script, sysfee)
|
||||
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)
|
||||
}
|
||||
|
||||
tx, err := c.CreateTxFromScript(script, acc, sysfee, int64(netfee), cosigners...)
|
||||
if err = acc.SignTx(tx); err != nil {
|
||||
return txHash, fmt.Errorf("failed to sign tx: %w", err)
|
||||
}
|
||||
|
|
|
@ -169,3 +169,32 @@ func TestPing(t *testing.T) {
|
|||
httpSrv.Close()
|
||||
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