aboutsummaryrefslogtreecommitdiffstats
path: root/internal/ethapi
diff options
context:
space:
mode:
authorMartin Holst Swende <martin@swende.se>2018-01-27 01:32:43 +0800
committerPéter Szilágyi <peterke@gmail.com>2018-01-27 01:32:43 +0800
commit722bac84fa503199b9c485c1a3e2bfba03bc487d (patch)
tree96a3a7072a6724817b72fe2584a3b852cf327945 /internal/ethapi
parent23bca0f374b3e1ccfa19bfeb86d06a0aca82184b (diff)
downloaddexon-722bac84fa503199b9c485c1a3e2bfba03bc487d.tar.gz
dexon-722bac84fa503199b9c485c1a3e2bfba03bc487d.tar.zst
dexon-722bac84fa503199b9c485c1a3e2bfba03bc487d.zip
ethapi: add personal.signTransaction (#15971)
* ethapi: add personal.signTransaction * ethapi: refactor to minimize duplicate code * ethapi: make nonce,gas,gasPrice obligatory in signTransaction
Diffstat (limited to 'internal/ethapi')
-rw-r--r--internal/ethapi/api.go74
1 files changed, 54 insertions, 20 deletions
diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go
index 55bd5aa1b..48eb91b67 100644
--- a/internal/ethapi/api.go
+++ b/internal/ethapi/api.go
@@ -333,28 +333,19 @@ func (s *PrivateAccountAPI) LockAccount(addr common.Address) bool {
return fetchKeystore(s.am).Lock(addr) == nil
}
-// SendTransaction will create a transaction from the given arguments and
-// tries to sign it with the key associated with args.To. If the given passwd isn't
-// able to decrypt the key it fails.
-func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
+// signTransactions sets defaults and signs the given transation
+// NOTE: the caller needs to ensure that the nonceLock is held, if applicable,
+// and release it after the transaction has been submitted to the tx pool
+func (s *PrivateAccountAPI) signTransaction(ctx context.Context, args SendTxArgs, passwd string) (*types.Transaction, error) {
// Look up the wallet containing the requested signer
account := accounts.Account{Address: args.From}
-
wallet, err := s.am.Find(account)
if err != nil {
- return common.Hash{}, err
- }
-
- if args.Nonce == nil {
- // Hold the addresse's mutex around signing to prevent concurrent assignment of
- // the same nonce to multiple accounts.
- s.nonceLock.LockAddr(args.From)
- defer s.nonceLock.UnlockAddr(args.From)
+ return nil, err
}
-
// Set some sanity defaults and terminate on failure
if err := args.setDefaults(ctx, s.b); err != nil {
- return common.Hash{}, err
+ return nil, err
}
// Assemble the transaction and sign with the wallet
tx := args.toTransaction()
@@ -363,13 +354,53 @@ func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs
if config := s.b.ChainConfig(); config.IsEIP155(s.b.CurrentBlock().Number()) {
chainID = config.ChainId
}
- signed, err := wallet.SignTxWithPassphrase(account, passwd, tx, chainID)
+ return wallet.SignTxWithPassphrase(account, passwd, tx, chainID)
+}
+
+// SendTransaction will create a transaction from the given arguments and
+// tries to sign it with the key associated with args.To. If the given passwd isn't
+// able to decrypt the key it fails.
+func (s *PrivateAccountAPI) SendTransaction(ctx context.Context, args SendTxArgs, passwd string) (common.Hash, error) {
+ if args.Nonce == nil {
+ // Hold the addresse's mutex around signing to prevent concurrent assignment of
+ // the same nonce to multiple accounts.
+ s.nonceLock.LockAddr(args.From)
+ defer s.nonceLock.UnlockAddr(args.From)
+ }
+ signed, err := s.signTransaction(ctx, args, passwd)
if err != nil {
return common.Hash{}, err
}
return submitTransaction(ctx, s.b, signed)
}
+// SignTransaction will create a transaction from the given arguments and
+// tries to sign it with the key associated with args.To. If the given passwd isn't
+// able to decrypt the key it fails. The transaction is returned in RLP-form, not broadcast
+// to other nodes
+func (s *PrivateAccountAPI) SignTransaction(ctx context.Context, args SendTxArgs, passwd string) (*SignTransactionResult, error) {
+ // No need to obtain the noncelock mutex, since we won't be sending this
+ // tx into the transaction pool, but right back to the user
+ if args.Gas == nil {
+ return nil, fmt.Errorf("gas not specified")
+ }
+ if args.GasPrice == nil {
+ return nil, fmt.Errorf("gasPrice not specified")
+ }
+ if args.Nonce == nil {
+ return nil, fmt.Errorf("nonce not specified")
+ }
+ signed, err := s.signTransaction(ctx, args, passwd)
+ if err != nil {
+ return nil, err
+ }
+ data, err := rlp.EncodeToBytes(signed)
+ if err != nil {
+ return nil, err
+ }
+ return &SignTransactionResult{data, signed}, nil
+}
+
// signHash is a helper function that calculates a hash for the given message that can be
// safely used to calculate a signature from.
//
@@ -1221,11 +1252,14 @@ type SignTransactionResult struct {
// The node needs to have the private key of the account corresponding with
// the given from address and it needs to be unlocked.
func (s *PublicTransactionPoolAPI) SignTransaction(ctx context.Context, args SendTxArgs) (*SignTransactionResult, error) {
+ if args.Gas == nil {
+ return nil, fmt.Errorf("gas not specified")
+ }
+ if args.GasPrice == nil {
+ return nil, fmt.Errorf("gasPrice not specified")
+ }
if args.Nonce == nil {
- // Hold the addresse's mutex around signing to prevent concurrent assignment of
- // the same nonce to multiple accounts.
- s.nonceLock.LockAddr(args.From)
- defer s.nonceLock.UnlockAddr(args.From)
+ return nil, fmt.Errorf("nonce not specified")
}
if err := args.setDefaults(ctx, s.b); err != nil {
return nil, err