Allow gas and gas input as argument on signing TTXX (#1000)
* Allow gas and gas input as argument on signing TTXX * Two different bindings ApproveSignRequest and ApproveSignRequestWithArgs
This commit is contained in:
parent
2b193de5c1
commit
c82d5635b6
|
@ -175,3 +175,14 @@ func (cs *commandSet) ApproveSignRequest(id, password string) (string, error) {
|
|||
}
|
||||
return result.Response.Hex(), nil
|
||||
}
|
||||
|
||||
// ApproveSignRequest instructs API to complete sending of a given transaction.
|
||||
// gas and gasPrice will be overrided with the given values before signing the
|
||||
// transaction.
|
||||
func (cs *commandSet) ApproveSignRequestWithArgs(id, password string, gas, gasPrice int64) (string, error) {
|
||||
result := cs.statusAPI.ApproveSignRequestWithArgs(id, password, gas, gasPrice)
|
||||
if result.Error != nil {
|
||||
return "", result.Error
|
||||
}
|
||||
return result.Response.Hex(), nil
|
||||
}
|
||||
|
|
|
@ -158,10 +158,17 @@ func (api *StatusAPI) SendTransaction(ctx context.Context, args transactions.Sen
|
|||
}
|
||||
|
||||
// ApproveSignRequest instructs backend to complete sending of a given transaction
|
||||
func (api *StatusAPI) ApproveSignRequest(id string, password string) sign.Result {
|
||||
func (api *StatusAPI) ApproveSignRequest(id, password string) sign.Result {
|
||||
return api.b.ApproveSignRequest(id, password)
|
||||
}
|
||||
|
||||
// ApproveSignRequestWithArgs instructs backend to complete sending of a given transaction
|
||||
// gas and gasPrice will be overrided with the given values before signing the
|
||||
// transaction.
|
||||
func (api *StatusAPI) ApproveSignRequestWithArgs(id, password string, gas, gasPrice int64) sign.Result {
|
||||
return api.b.ApproveSignRequestWithArgs(id, password, gas, gasPrice)
|
||||
}
|
||||
|
||||
// ApproveSignRequests instructs backend to complete sending of multiple transactions
|
||||
func (api *StatusAPI) ApproveSignRequests(ids []string, password string) map[string]sign.Result {
|
||||
return api.b.ApproveSignRequests(ids, password)
|
||||
|
|
|
@ -251,9 +251,17 @@ func (b *StatusBackend) getVerifiedAccount(password string) (*account.SelectedEx
|
|||
return selectedAccount, nil
|
||||
}
|
||||
|
||||
// ApproveSignRequest instructs backend to complete sending of a given transaction
|
||||
func (b *StatusBackend) ApproveSignRequest(id string, password string) sign.Result {
|
||||
return b.pendingSignRequests.Approve(id, password, b.getVerifiedAccount)
|
||||
// ApproveSignRequest instructs backend to complete sending of a given transaction.
|
||||
func (b *StatusBackend) ApproveSignRequest(id, password string) sign.Result {
|
||||
return b.pendingSignRequests.Approve(id, password, nil, b.getVerifiedAccount)
|
||||
}
|
||||
|
||||
// ApproveSignRequestWithArgs instructs backend to complete sending of a given transaction.
|
||||
// gas and gasPrice will be overrided with the given values before signing the
|
||||
// transaction.
|
||||
func (b *StatusBackend) ApproveSignRequestWithArgs(id, password string, gas, gasPrice int64) sign.Result {
|
||||
args := prepareTxArgs(gas, gasPrice)
|
||||
return b.pendingSignRequests.Approve(id, password, &args, b.getVerifiedAccount)
|
||||
}
|
||||
|
||||
// ApproveSignRequests instructs backend to complete sending of multiple transactions
|
||||
|
|
|
@ -2,10 +2,12 @@ package api
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"math/rand"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/status-im/status-go/geth/node"
|
||||
"github.com/status-im/status-go/geth/params"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
@ -243,4 +245,56 @@ func TestBackendCallRPCConcurrently(t *testing.T) {
|
|||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestPrepareTxArgs(t *testing.T) {
|
||||
var flagtests = []struct {
|
||||
description string
|
||||
gas int64
|
||||
gasPrice int64
|
||||
expectedGas *hexutil.Uint64
|
||||
expectedGasPrice *hexutil.Big
|
||||
}{
|
||||
{
|
||||
description: "Empty gas and gas price",
|
||||
gas: 0,
|
||||
gasPrice: 0,
|
||||
expectedGas: nil,
|
||||
expectedGasPrice: nil,
|
||||
},
|
||||
{
|
||||
description: "Non empty gas and gas price",
|
||||
gas: 1,
|
||||
gasPrice: 2,
|
||||
expectedGas: func() *hexutil.Uint64 {
|
||||
x := hexutil.Uint64(1)
|
||||
return &x
|
||||
}(),
|
||||
expectedGasPrice: (*hexutil.Big)(big.NewInt(2)),
|
||||
},
|
||||
{
|
||||
description: "Empty gas price",
|
||||
gas: 1,
|
||||
gasPrice: 0,
|
||||
expectedGas: func() *hexutil.Uint64 {
|
||||
x := hexutil.Uint64(1)
|
||||
return &x
|
||||
}(),
|
||||
expectedGasPrice: nil,
|
||||
},
|
||||
{
|
||||
description: "Empty gas",
|
||||
gas: 0,
|
||||
gasPrice: 2,
|
||||
expectedGas: nil,
|
||||
expectedGasPrice: (*hexutil.Big)(big.NewInt(2)),
|
||||
},
|
||||
}
|
||||
for _, tt := range flagtests {
|
||||
t.Run(tt.description, func(t *testing.T) {
|
||||
args := prepareTxArgs(tt.gas, tt.gasPrice)
|
||||
assert.Equal(t, tt.expectedGas, args.Gas)
|
||||
assert.Equal(t, tt.expectedGasPrice, args.GasPrice)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(adam): add concurrent tests for: SendTransaction, ApproveSignRequest, DiscardSignRequest
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/status-im/status-go/sign"
|
||||
)
|
||||
|
||||
// prepareTxArgs given gas and gasPrice will prepare a valid sign.TxArgs.
|
||||
func prepareTxArgs(gas, gasPrice int64) (args sign.TxArgs) {
|
||||
if gas > 0 {
|
||||
g := hexutil.Uint64(gas)
|
||||
args.Gas = &g
|
||||
}
|
||||
if gasPrice > 0 {
|
||||
gp := (*hexutil.Big)(big.NewInt(gasPrice))
|
||||
args.GasPrice = gp
|
||||
}
|
||||
return
|
||||
}
|
|
@ -72,7 +72,8 @@ func (t *Transactor) SendTransaction(ctx context.Context, args SendTxArgs) (geth
|
|||
ctx = context.Background()
|
||||
}
|
||||
|
||||
completeFunc := func(acc *account.SelectedExtKey, password string) (sign.Response, error) {
|
||||
completeFunc := func(acc *account.SelectedExtKey, password string, signArgs *sign.TxArgs) (sign.Response, error) {
|
||||
t.mergeSignTxArgsOntoSendTxArgs(signArgs, &args)
|
||||
hash, err := t.validateAndPropagate(acc, args)
|
||||
return sign.Response(hash.Bytes()), err
|
||||
}
|
||||
|
@ -197,8 +198,21 @@ func (t *Transactor) validateAndPropagate(selectedAccount *account.SelectedExtKe
|
|||
}
|
||||
ctx, cancel = context.WithTimeout(context.Background(), t.rpcCallTimeout)
|
||||
defer cancel()
|
||||
|
||||
if err := t.sender.SendTransaction(ctx, signedTx); err != nil {
|
||||
return hash, err
|
||||
}
|
||||
return signedTx.Hash(), nil
|
||||
}
|
||||
|
||||
func (t *Transactor) mergeSignTxArgsOntoSendTxArgs(signArgs *sign.TxArgs, args *SendTxArgs) {
|
||||
if signArgs == nil {
|
||||
return
|
||||
}
|
||||
if signArgs.Gas != nil {
|
||||
args.Gas = signArgs.Gas
|
||||
}
|
||||
if signArgs.GasPrice != nil {
|
||||
args.GasPrice = signArgs.GasPrice
|
||||
}
|
||||
}
|
||||
|
|
|
@ -76,24 +76,30 @@ func (s *TxQueueTestSuite) TearDownTest() {
|
|||
}
|
||||
|
||||
var (
|
||||
testGas = hexutil.Uint64(defaultGas + 1)
|
||||
testGasPrice = (*hexutil.Big)(big.NewInt(10))
|
||||
testNonce = hexutil.Uint64(10)
|
||||
testGas = hexutil.Uint64(defaultGas + 1)
|
||||
testGasPrice = (*hexutil.Big)(big.NewInt(10))
|
||||
testOverridenGas = hexutil.Uint64(defaultGas + 2)
|
||||
testOverridenGasPrice = (*hexutil.Big)(big.NewInt(20))
|
||||
testNonce = hexutil.Uint64(10)
|
||||
)
|
||||
|
||||
func (s *TxQueueTestSuite) setupTransactionPoolAPI(args SendTxArgs, returnNonce, resultNonce hexutil.Uint64, account *account.SelectedExtKey, txErr error) {
|
||||
func (s *TxQueueTestSuite) setupTransactionPoolAPI(args SendTxArgs, returnNonce, resultNonce hexutil.Uint64, account *account.SelectedExtKey, txErr error, signArgs *sign.TxArgs) {
|
||||
// Expect calls to gas functions only if there are no user defined values.
|
||||
// And also set the expected gas and gas price for RLP encoding the expected tx.
|
||||
var usedGas hexutil.Uint64
|
||||
var usedGasPrice *big.Int
|
||||
s.txServiceMock.EXPECT().GetTransactionCount(gomock.Any(), account.Address, gethrpc.PendingBlockNumber).Return(&returnNonce, nil)
|
||||
if args.GasPrice == nil {
|
||||
if signArgs != nil && signArgs.GasPrice != nil {
|
||||
usedGasPrice = (*big.Int)(signArgs.GasPrice)
|
||||
} else if args.GasPrice == nil {
|
||||
usedGasPrice = (*big.Int)(testGasPrice)
|
||||
s.txServiceMock.EXPECT().GasPrice(gomock.Any()).Return(usedGasPrice, nil)
|
||||
} else {
|
||||
usedGasPrice = (*big.Int)(args.GasPrice)
|
||||
}
|
||||
if args.Gas == nil {
|
||||
if signArgs != nil && signArgs.Gas != nil {
|
||||
usedGas = *signArgs.Gas
|
||||
} else if args.Gas == nil {
|
||||
s.txServiceMock.EXPECT().EstimateGas(gomock.Any(), gomock.Any()).Return(testGas, nil)
|
||||
usedGas = testGas
|
||||
} else {
|
||||
|
@ -129,29 +135,80 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
|
|||
AccountKey: &keystore.Key{PrivateKey: key},
|
||||
}
|
||||
testCases := []struct {
|
||||
name string
|
||||
gas *hexutil.Uint64
|
||||
gasPrice *hexutil.Big
|
||||
name string
|
||||
gas *hexutil.Uint64
|
||||
gasPrice *hexutil.Big
|
||||
signTxArgs *sign.TxArgs
|
||||
}{
|
||||
{
|
||||
"noGasDef",
|
||||
nil,
|
||||
nil,
|
||||
s.defaultSignTxArgs(),
|
||||
},
|
||||
{
|
||||
"gasDefined",
|
||||
&testGas,
|
||||
nil,
|
||||
s.defaultSignTxArgs(),
|
||||
},
|
||||
{
|
||||
"gasPriceDefined",
|
||||
nil,
|
||||
testGasPrice,
|
||||
s.defaultSignTxArgs(),
|
||||
},
|
||||
{
|
||||
"inputPassedInLegacyDataField",
|
||||
nil,
|
||||
testGasPrice,
|
||||
s.defaultSignTxArgs(),
|
||||
},
|
||||
{
|
||||
"overrideGas",
|
||||
nil,
|
||||
nil,
|
||||
&sign.TxArgs{
|
||||
Gas: &testGas,
|
||||
},
|
||||
},
|
||||
{
|
||||
"overridePreExistingGas",
|
||||
&testGas,
|
||||
nil,
|
||||
&sign.TxArgs{
|
||||
Gas: &testOverridenGas,
|
||||
},
|
||||
},
|
||||
{
|
||||
"overridePreExistingGasPrice",
|
||||
nil,
|
||||
testGasPrice,
|
||||
&sign.TxArgs{
|
||||
GasPrice: testOverridenGasPrice,
|
||||
},
|
||||
},
|
||||
{
|
||||
"nilSignTransactionSpecificArgs",
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
"overridePreExistingGasWithNil",
|
||||
&testGas,
|
||||
nil,
|
||||
&sign.TxArgs{
|
||||
Gas: nil,
|
||||
},
|
||||
},
|
||||
{
|
||||
"overridePreExistingGasPriceWithNil",
|
||||
nil,
|
||||
testGasPrice,
|
||||
&sign.TxArgs{
|
||||
GasPrice: nil,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -164,7 +221,7 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
|
|||
Gas: testCase.gas,
|
||||
GasPrice: testCase.gasPrice,
|
||||
}
|
||||
s.setupTransactionPoolAPI(args, testNonce, testNonce, selectedAccount, nil)
|
||||
s.setupTransactionPoolAPI(args, testNonce, testNonce, selectedAccount, nil, testCase.signTxArgs)
|
||||
|
||||
w := make(chan struct{})
|
||||
var sendHash gethcommon.Hash
|
||||
|
@ -184,7 +241,7 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
|
|||
|
||||
req := s.manager.pendingSignRequests.First()
|
||||
s.NotNil(req)
|
||||
approveResult := s.manager.pendingSignRequests.Approve(req.ID, "", simpleVerifyFunc(selectedAccount))
|
||||
approveResult := s.manager.pendingSignRequests.Approve(req.ID, "", testCase.signTxArgs, simpleVerifyFunc(selectedAccount))
|
||||
s.NoError(approveResult.Error)
|
||||
s.NoError(WaitClosed(w, time.Second))
|
||||
|
||||
|
@ -195,6 +252,10 @@ func (s *TxQueueTestSuite) TestCompleteTransaction() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *TxQueueTestSuite) defaultSignTxArgs() *sign.TxArgs {
|
||||
return &sign.TxArgs{}
|
||||
}
|
||||
|
||||
func (s *TxQueueTestSuite) TestAccountMismatch() {
|
||||
selectedAccount := &account.SelectedExtKey{
|
||||
Address: account.FromAddress(TestConfig.Account2.Address),
|
||||
|
@ -218,7 +279,7 @@ func (s *TxQueueTestSuite) TestAccountMismatch() {
|
|||
|
||||
req := s.manager.pendingSignRequests.First()
|
||||
s.NotNil(req)
|
||||
result := s.manager.pendingSignRequests.Approve(req.ID, "", simpleVerifyFunc(selectedAccount))
|
||||
result := s.manager.pendingSignRequests.Approve(req.ID, "", s.defaultSignTxArgs(), simpleVerifyFunc(selectedAccount))
|
||||
s.EqualError(result.Error, ErrInvalidCompleteTxSender.Error())
|
||||
|
||||
// Transaction should stay in the queue as mismatched accounts
|
||||
|
@ -279,7 +340,7 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
|
|||
if req == nil {
|
||||
time.Sleep(time.Millisecond)
|
||||
} else {
|
||||
s.manager.pendingSignRequests.Approve(req.ID, "", simpleVerifyFunc(selectedAccount)) // nolint: errcheck
|
||||
s.manager.pendingSignRequests.Approve(req.ID, "", s.defaultSignTxArgs(), simpleVerifyFunc(selectedAccount)) // nolint: errcheck
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
@ -289,7 +350,7 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
|
|||
From: account.FromAddress(TestConfig.Account1.Address),
|
||||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
}
|
||||
s.setupTransactionPoolAPI(args, nonce, hexutil.Uint64(i), selectedAccount, nil)
|
||||
s.setupTransactionPoolAPI(args, nonce, hexutil.Uint64(i), selectedAccount, nil, nil)
|
||||
|
||||
_, err := s.manager.SendTransaction(context.Background(), args)
|
||||
s.NoError(err)
|
||||
|
@ -303,7 +364,7 @@ func (s *TxQueueTestSuite) TestLocalNonce() {
|
|||
To: account.ToAddress(TestConfig.Account2.Address),
|
||||
}
|
||||
|
||||
s.setupTransactionPoolAPI(args, nonce, nonce, selectedAccount, nil)
|
||||
s.setupTransactionPoolAPI(args, nonce, nonce, selectedAccount, nil, nil)
|
||||
|
||||
_, err := s.manager.SendTransaction(context.Background(), args)
|
||||
s.NoError(err)
|
||||
|
@ -349,7 +410,7 @@ func (s *TxQueueTestSuite) TestContractCreation() {
|
|||
if req == nil {
|
||||
time.Sleep(time.Millisecond)
|
||||
} else {
|
||||
s.manager.pendingSignRequests.Approve(req.ID, "", simpleVerifyFunc(selectedAccount)) // nolint: errcheck
|
||||
s.manager.pendingSignRequests.Approve(req.ID, "", s.defaultSignTxArgs(), simpleVerifyFunc(selectedAccount)) // nolint: errcheck
|
||||
break
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import (
|
|||
"github.com/status-im/status-go/geth/params"
|
||||
"github.com/status-im/status-go/logutils"
|
||||
"github.com/status-im/status-go/profiling"
|
||||
"github.com/status-im/status-go/sign"
|
||||
"gopkg.in/go-playground/validator.v9"
|
||||
)
|
||||
|
||||
|
@ -206,11 +207,27 @@ func Logout() *C.char {
|
|||
return makeJSONResponse(err)
|
||||
}
|
||||
|
||||
//ApproveSignRequest instructs backend to complete sending of a given transaction
|
||||
//ApproveSignRequestWithArgs instructs backend to complete sending of a given transaction.
|
||||
// gas and gasPrice will be overrided with the given values before signing the
|
||||
// transaction.
|
||||
//export ApproveSignRequestWithArgs
|
||||
func ApproveSignRequestWithArgs(id, password *C.char, gas, gasPrice C.int) *C.char {
|
||||
result := statusAPI.ApproveSignRequestWithArgs(C.GoString(id), C.GoString(password), int64(gas), int64(gasPrice))
|
||||
|
||||
return prepareApproveSignRequestResponse(result, id)
|
||||
}
|
||||
|
||||
//ApproveSignRequest instructs backend to complete sending of a given transaction.
|
||||
//export ApproveSignRequest
|
||||
func ApproveSignRequest(id, password *C.char) *C.char {
|
||||
result := statusAPI.ApproveSignRequest(C.GoString(id), C.GoString(password))
|
||||
|
||||
return prepareApproveSignRequestResponse(result, id)
|
||||
}
|
||||
|
||||
// prepareApproveSignRequestResponse based on a sign.Result prepares the binding
|
||||
// response.
|
||||
func prepareApproveSignRequestResponse(result sign.Result, id *C.char) *C.char {
|
||||
errString := ""
|
||||
if result.Error != nil {
|
||||
fmt.Fprintln(os.Stderr, result.Error)
|
||||
|
|
|
@ -88,7 +88,7 @@ func (api *PublicAPI) Sign(context context.Context, rpcParams ...interface{}) (i
|
|||
}
|
||||
|
||||
func (api *PublicAPI) completeFunc(context context.Context, metadata metadata) sign.CompleteFunc {
|
||||
return func(acc *account.SelectedExtKey, password string) (response sign.Response, err error) {
|
||||
return func(acc *account.SelectedExtKey, password string, signArgs *sign.TxArgs) (response sign.Response, err error) {
|
||||
response = sign.EmptyResponse
|
||||
|
||||
err = api.validateAccount(metadata, acc)
|
||||
|
|
|
@ -67,7 +67,7 @@ func (rs *PendingRequests) First() *Request {
|
|||
}
|
||||
|
||||
// Approve a signing request by it's ID. Requires a valid password and a verification function.
|
||||
func (rs *PendingRequests) Approve(id string, password string, verify verifyFunc) Result {
|
||||
func (rs *PendingRequests) Approve(id string, password string, args *TxArgs, verify verifyFunc) Result {
|
||||
rs.log.Info("complete sign request", "id", id)
|
||||
request, err := rs.tryLock(id)
|
||||
if err != nil {
|
||||
|
@ -81,7 +81,7 @@ func (rs *PendingRequests) Approve(id string, password string, verify verifyFunc
|
|||
return newErrResult(err)
|
||||
}
|
||||
|
||||
response, err := request.completeFunc(selectedAccount, password)
|
||||
response, err := request.completeFunc(selectedAccount, password, args)
|
||||
rs.log.Info("completed sign request ", "id", request.ID, "response", response, "err", err)
|
||||
|
||||
rs.complete(request, response, err)
|
||||
|
|
|
@ -3,12 +3,14 @@ package sign
|
|||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/big"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/keystore"
|
||||
gethcommon "github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
|
||||
"github.com/status-im/status-go/geth/account"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
@ -19,6 +21,11 @@ const (
|
|||
wrongPassword = "password-wrong"
|
||||
)
|
||||
|
||||
var (
|
||||
overridenGas = hexutil.Uint64(90002)
|
||||
overridenGasPrice = (*hexutil.Big)(big.NewInt(20))
|
||||
)
|
||||
|
||||
func testVerifyFunc(password string) (*account.SelectedExtKey, error) {
|
||||
if password == correctPassword {
|
||||
return nil, nil
|
||||
|
@ -40,9 +47,13 @@ func (s *PendingRequestsSuite) SetupTest() {
|
|||
s.pendingRequests = NewPendingRequests()
|
||||
}
|
||||
|
||||
func (s *PendingRequestsSuite) defaultSignTxArgs() *TxArgs {
|
||||
return &TxArgs{}
|
||||
}
|
||||
|
||||
func (s *PendingRequestsSuite) defaultCompleteFunc() CompleteFunc {
|
||||
hash := gethcommon.Hash{1}
|
||||
return func(acc *account.SelectedExtKey, password string) (Response, error) {
|
||||
return func(acc *account.SelectedExtKey, password string, args *TxArgs) (Response, error) {
|
||||
s.Nil(acc, "account should be `nil`")
|
||||
s.Equal(correctPassword, password)
|
||||
return hash.Bytes(), nil
|
||||
|
@ -51,7 +62,7 @@ func (s *PendingRequestsSuite) defaultCompleteFunc() CompleteFunc {
|
|||
|
||||
func (s *PendingRequestsSuite) delayedCompleteFunc() CompleteFunc {
|
||||
hash := gethcommon.Hash{1}
|
||||
return func(acc *account.SelectedExtKey, password string) (Response, error) {
|
||||
return func(acc *account.SelectedExtKey, password string, args *TxArgs) (Response, error) {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
s.Nil(acc, "account should be `nil`")
|
||||
s.Equal(correctPassword, password)
|
||||
|
@ -59,9 +70,20 @@ func (s *PendingRequestsSuite) delayedCompleteFunc() CompleteFunc {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *PendingRequestsSuite) overridenCompleteFunc() CompleteFunc {
|
||||
hash := gethcommon.Hash{1}
|
||||
return func(acc *account.SelectedExtKey, password string, args *TxArgs) (Response, error) {
|
||||
s.Nil(acc, "account should be `nil`")
|
||||
s.Equal(correctPassword, password)
|
||||
s.Equal(&overridenGas, args.Gas)
|
||||
s.Equal(overridenGasPrice, args.GasPrice)
|
||||
return hash.Bytes(), nil
|
||||
}
|
||||
}
|
||||
|
||||
func (s *PendingRequestsSuite) errorCompleteFunc(err error) CompleteFunc {
|
||||
hash := gethcommon.Hash{1}
|
||||
return func(acc *account.SelectedExtKey, password string) (Response, error) {
|
||||
return func(acc *account.SelectedExtKey, password string, args *TxArgs) (Response, error) {
|
||||
s.Nil(acc, "account should be `nil`")
|
||||
return hash.Bytes(), err
|
||||
}
|
||||
|
@ -77,13 +99,13 @@ func (s *PendingRequestsSuite) TestGet() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *PendingRequestsSuite) testComplete(password string, hash gethcommon.Hash, completeFunc CompleteFunc) (string, error) {
|
||||
func (s *PendingRequestsSuite) testComplete(password string, hash gethcommon.Hash, completeFunc CompleteFunc, signArgs *TxArgs) (string, error) {
|
||||
req, err := s.pendingRequests.Add(context.Background(), "", nil, completeFunc)
|
||||
s.NoError(err)
|
||||
|
||||
s.True(s.pendingRequests.Has(req.ID), "sign request should exist")
|
||||
|
||||
result := s.pendingRequests.Approve(req.ID, password, testVerifyFunc)
|
||||
result := s.pendingRequests.Approve(req.ID, password, signArgs, testVerifyFunc)
|
||||
|
||||
if s.pendingRequests.Has(req.ID) {
|
||||
// transient error
|
||||
|
@ -96,7 +118,7 @@ func (s *PendingRequestsSuite) testComplete(password string, hash gethcommon.Has
|
|||
}
|
||||
|
||||
func (s *PendingRequestsSuite) TestCompleteSuccess() {
|
||||
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.defaultCompleteFunc())
|
||||
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.defaultCompleteFunc(), s.defaultSignTxArgs())
|
||||
s.NoError(err, "no errors should be there")
|
||||
|
||||
s.False(s.pendingRequests.Has(id), "sign request should not exist")
|
||||
|
@ -104,7 +126,7 @@ func (s *PendingRequestsSuite) TestCompleteSuccess() {
|
|||
|
||||
func (s *PendingRequestsSuite) TestCompleteTransientError() {
|
||||
hash := gethcommon.Hash{}
|
||||
id, err := s.testComplete(wrongPassword, hash, s.errorCompleteFunc(keystore.ErrDecrypt))
|
||||
id, err := s.testComplete(wrongPassword, hash, s.errorCompleteFunc(keystore.ErrDecrypt), s.defaultSignTxArgs())
|
||||
s.Equal(keystore.ErrDecrypt, err, "error value should be preserved")
|
||||
|
||||
s.True(s.pendingRequests.Has(id))
|
||||
|
@ -117,7 +139,7 @@ func (s *PendingRequestsSuite) TestCompleteError() {
|
|||
hash := gethcommon.Hash{1}
|
||||
expectedError := errors.New("test")
|
||||
|
||||
id, err := s.testComplete(correctPassword, hash, s.errorCompleteFunc(expectedError))
|
||||
id, err := s.testComplete(correctPassword, hash, s.errorCompleteFunc(expectedError), s.defaultSignTxArgs())
|
||||
|
||||
s.Equal(expectedError, err, "error value should be preserved")
|
||||
|
||||
|
@ -125,10 +147,10 @@ func (s *PendingRequestsSuite) TestCompleteError() {
|
|||
}
|
||||
|
||||
func (s PendingRequestsSuite) TestMultipleComplete() {
|
||||
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.defaultCompleteFunc())
|
||||
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.defaultCompleteFunc(), s.defaultSignTxArgs())
|
||||
s.NoError(err, "no errors should be there")
|
||||
|
||||
result := s.pendingRequests.Approve(id, correctPassword, testVerifyFunc)
|
||||
result := s.pendingRequests.Approve(id, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
|
||||
|
||||
s.Equal(ErrSignReqNotFound, result.Error)
|
||||
}
|
||||
|
@ -144,7 +166,7 @@ func (s PendingRequestsSuite) TestConcurrentComplete() {
|
|||
|
||||
for i := 10; i > 0; i-- {
|
||||
go func() {
|
||||
result := s.pendingRequests.Approve(req.ID, correctPassword, testVerifyFunc)
|
||||
result := s.pendingRequests.Approve(req.ID, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
|
||||
if result.Error == nil {
|
||||
atomic.AddInt32(&approved, 1)
|
||||
}
|
||||
|
@ -167,7 +189,7 @@ func (s PendingRequestsSuite) TestWaitSuccess() {
|
|||
s.True(s.pendingRequests.Has(req.ID), "sign request should exist")
|
||||
|
||||
go func() {
|
||||
result := s.pendingRequests.Approve(req.ID, correctPassword, testVerifyFunc)
|
||||
result := s.pendingRequests.Approve(req.ID, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
|
||||
s.NoError(result.Error)
|
||||
}()
|
||||
|
||||
|
@ -201,7 +223,7 @@ func (s PendingRequestsSuite) TestWaitFail() {
|
|||
s.True(s.pendingRequests.Has(req.ID), "sign request should exist")
|
||||
|
||||
go func() {
|
||||
result := s.pendingRequests.Approve(req.ID, correctPassword, testVerifyFunc)
|
||||
result := s.pendingRequests.Approve(req.ID, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
|
||||
s.Equal(expectedError, result.Error)
|
||||
}()
|
||||
|
||||
|
@ -218,7 +240,18 @@ func (s PendingRequestsSuite) TestWaitTimeout() {
|
|||
result := s.pendingRequests.Wait(req.ID, 0*time.Second)
|
||||
s.Equal(ErrSignReqTimedOut, result.Error)
|
||||
|
||||
// Try approving the timeouted request, it will fail
|
||||
result = s.pendingRequests.Approve(req.ID, correctPassword, testVerifyFunc)
|
||||
// Try approving the timed out request, it will fail
|
||||
result = s.pendingRequests.Approve(req.ID, correctPassword, s.defaultSignTxArgs(), testVerifyFunc)
|
||||
s.NotNil(result.Error)
|
||||
}
|
||||
|
||||
func (s *PendingRequestsSuite) TestCompleteSuccessWithOverridenGas() {
|
||||
txArgs := TxArgs{
|
||||
Gas: &overridenGas,
|
||||
GasPrice: overridenGasPrice,
|
||||
}
|
||||
id, err := s.testComplete(correctPassword, gethcommon.Hash{1}, s.overridenCompleteFunc(), &txArgs)
|
||||
s.NoError(err, "no errors should be there")
|
||||
|
||||
s.False(s.pendingRequests.Has(id), "sign request should not exist")
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@ package sign
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pborman/uuid"
|
||||
"github.com/status-im/status-go/geth/account"
|
||||
)
|
||||
|
||||
// CompleteFunc is a function that is called after the sign request is approved.
|
||||
type CompleteFunc func(account *account.SelectedExtKey, password string) (Response, error)
|
||||
type CompleteFunc func(account *account.SelectedExtKey, password string, completeArgs *TxArgs) (Response, error)
|
||||
|
||||
// Meta represents any metadata that could be attached to a signing request.
|
||||
// It will be JSON-serialized and used in notifications to the API consumer.
|
||||
|
@ -25,6 +26,12 @@ type Request struct {
|
|||
result chan Result
|
||||
}
|
||||
|
||||
// TxArgs represents the arguments to submit when signing a transaction
|
||||
type TxArgs struct {
|
||||
Gas *hexutil.Uint64 `json:"gas"`
|
||||
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||
}
|
||||
|
||||
func newRequest(ctx context.Context, method string, meta Meta, completeFunc CompleteFunc) *Request {
|
||||
return &Request{
|
||||
ID: uuid.New(),
|
||||
|
|
Loading…
Reference in New Issue