cmd/clef, signer: support for eip-1559 txs in clef (#22966)
This commit is contained in:
parent
c503f98f6d
commit
7a00378e2b
|
@ -208,10 +208,15 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
|
||||||
Nonce: hexutil.Uint64(tx.Nonce()),
|
Nonce: hexutil.Uint64(tx.Nonce()),
|
||||||
Value: hexutil.Big(*tx.Value()),
|
Value: hexutil.Big(*tx.Value()),
|
||||||
Gas: hexutil.Uint64(tx.Gas()),
|
Gas: hexutil.Uint64(tx.Gas()),
|
||||||
GasPrice: hexutil.Big(*tx.GasPrice()),
|
|
||||||
To: to,
|
To: to,
|
||||||
From: common.NewMixedcaseAddress(account.Address),
|
From: common.NewMixedcaseAddress(account.Address),
|
||||||
}
|
}
|
||||||
|
if tx.GasFeeCap() != nil {
|
||||||
|
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
|
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
|
||||||
|
} else {
|
||||||
|
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
|
||||||
|
}
|
||||||
// We should request the default chain id that we're operating with
|
// We should request the default chain id that we're operating with
|
||||||
// (the chain we're executing on)
|
// (the chain we're executing on)
|
||||||
if chainID != nil {
|
if chainID != nil {
|
||||||
|
|
|
@ -929,7 +929,7 @@ func testExternalUI(api *core.SignerAPI) {
|
||||||
Value: hexutil.Big(*big.NewInt(6)),
|
Value: hexutil.Big(*big.NewInt(6)),
|
||||||
From: common.NewMixedcaseAddress(a),
|
From: common.NewMixedcaseAddress(a),
|
||||||
To: &to,
|
To: &to,
|
||||||
GasPrice: hexutil.Big(*big.NewInt(5)),
|
GasPrice: (*hexutil.Big)(big.NewInt(5)),
|
||||||
Gas: 1000,
|
Gas: 1000,
|
||||||
Input: nil,
|
Input: nil,
|
||||||
}
|
}
|
||||||
|
@ -1065,7 +1065,7 @@ func GenDoc(ctx *cli.Context) {
|
||||||
Value: hexutil.Big(*big.NewInt(6)),
|
Value: hexutil.Big(*big.NewInt(6)),
|
||||||
From: common.NewMixedcaseAddress(a),
|
From: common.NewMixedcaseAddress(a),
|
||||||
To: nil,
|
To: nil,
|
||||||
GasPrice: hexutil.Big(*big.NewInt(5)),
|
GasPrice: (*hexutil.Big)(big.NewInt(5)),
|
||||||
Gas: 1000,
|
Gas: 1000,
|
||||||
Input: nil,
|
Input: nil,
|
||||||
}})
|
}})
|
||||||
|
@ -1081,7 +1081,7 @@ func GenDoc(ctx *cli.Context) {
|
||||||
Value: hexutil.Big(*big.NewInt(6)),
|
Value: hexutil.Big(*big.NewInt(6)),
|
||||||
From: common.NewMixedcaseAddress(a),
|
From: common.NewMixedcaseAddress(a),
|
||||||
To: nil,
|
To: nil,
|
||||||
GasPrice: hexutil.Big(*big.NewInt(5)),
|
GasPrice: (*hexutil.Big)(big.NewInt(5)),
|
||||||
Gas: 1000,
|
Gas: 1000,
|
||||||
Input: nil,
|
Input: nil,
|
||||||
}})
|
}})
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "account_signTransaction",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"from": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192",
|
||||||
|
"to": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192",
|
||||||
|
"gas": "0x333",
|
||||||
|
"maxFeePerGas": "0x123",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"value": "0x10",
|
||||||
|
"data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 67
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "account_signTransaction",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"from": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192",
|
||||||
|
"to": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192",
|
||||||
|
"gas": "0x333",
|
||||||
|
"maxPriorityFeePerGas": "0x123",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"value": "0x10",
|
||||||
|
"data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 67
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "account_signTransaction",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"from": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192",
|
||||||
|
"to": "0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192",
|
||||||
|
"gas": "0x333",
|
||||||
|
"maxPriorityFeePerGas": "0x123",
|
||||||
|
"maxFeePerGas": "0x123",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"value": "0x10",
|
||||||
|
"data": "0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 67
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "account_signTransaction",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"from":"0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192",
|
||||||
|
"to":"0x8a8eafb1cf62bfbeb1741769dae1a9dd47996192",
|
||||||
|
"gas": "0x333",
|
||||||
|
"gasPrice": "0x123",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"value": "0x10",
|
||||||
|
"data":
|
||||||
|
"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 67
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"method": "account_signTransaction",
|
||||||
|
"params": [
|
||||||
|
{
|
||||||
|
"from":"0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192",
|
||||||
|
"to":"0x8A8eAFb1cf62BfBeb1741769DAE1a9dd47996192",
|
||||||
|
"gas": "0x333",
|
||||||
|
"gasPrice": "0x123",
|
||||||
|
"nonce": "0x0",
|
||||||
|
"value": "0x10",
|
||||||
|
"data":
|
||||||
|
"0x4401a6e40000000000000000000000000000000000000000000000000000000000000012"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"id": 67
|
||||||
|
}
|
|
@ -265,3 +265,9 @@ func (args *TransactionArgs) toTransaction() *types.Transaction {
|
||||||
}
|
}
|
||||||
return types.NewTx(data)
|
return types.NewTx(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToTransaction converts the arguments to a transaction.
|
||||||
|
// This assumes that setDefaults has been called.
|
||||||
|
func (args *TransactionArgs) ToTransaction() *types.Transaction {
|
||||||
|
return args.toTransaction()
|
||||||
|
}
|
||||||
|
|
|
@ -456,6 +456,16 @@ func (api *SignerAPI) newAccount() (common.Address, error) {
|
||||||
// it also returns 'true' if the transaction was modified, to make it possible to configure the signer not to allow
|
// it also returns 'true' if the transaction was modified, to make it possible to configure the signer not to allow
|
||||||
// UI-modifications to requests
|
// UI-modifications to requests
|
||||||
func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
|
func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
|
||||||
|
var intPtrModified = func(a, b *hexutil.Big) bool {
|
||||||
|
aBig := (*big.Int)(a)
|
||||||
|
bBig := (*big.Int)(b)
|
||||||
|
if aBig != nil && bBig != nil {
|
||||||
|
return aBig.Cmp(bBig) != 0
|
||||||
|
}
|
||||||
|
// One or both of them are nil
|
||||||
|
return a != b
|
||||||
|
}
|
||||||
|
|
||||||
modified := false
|
modified := false
|
||||||
if f0, f1 := original.Transaction.From, new.Transaction.From; !reflect.DeepEqual(f0, f1) {
|
if f0, f1 := original.Transaction.From, new.Transaction.From; !reflect.DeepEqual(f0, f1) {
|
||||||
log.Info("Sender-account changed by UI", "was", f0, "is", f1)
|
log.Info("Sender-account changed by UI", "was", f0, "is", f1)
|
||||||
|
@ -469,9 +479,17 @@ func logDiff(original *SignTxRequest, new *SignTxResponse) bool {
|
||||||
modified = true
|
modified = true
|
||||||
log.Info("Gas changed by UI", "was", g0, "is", g1)
|
log.Info("Gas changed by UI", "was", g0, "is", g1)
|
||||||
}
|
}
|
||||||
if g0, g1 := big.Int(original.Transaction.GasPrice), big.Int(new.Transaction.GasPrice); g0.Cmp(&g1) != 0 {
|
if a, b := original.Transaction.GasPrice, new.Transaction.GasPrice; intPtrModified(a, b) {
|
||||||
|
log.Info("GasPrice changed by UI", "was", a, "is", b)
|
||||||
|
modified = true
|
||||||
|
}
|
||||||
|
if a, b := original.Transaction.MaxPriorityFeePerGas, new.Transaction.MaxPriorityFeePerGas; intPtrModified(a, b) {
|
||||||
|
log.Info("maxPriorityFeePerGas changed by UI", "was", a, "is", b)
|
||||||
|
modified = true
|
||||||
|
}
|
||||||
|
if a, b := original.Transaction.MaxFeePerGas, new.Transaction.MaxFeePerGas; intPtrModified(a, b) {
|
||||||
|
log.Info("maxFeePerGas changed by UI", "was", a, "is", b)
|
||||||
modified = true
|
modified = true
|
||||||
log.Info("GasPrice changed by UI", "was", g0, "is", g1)
|
|
||||||
}
|
}
|
||||||
if v0, v1 := big.Int(original.Transaction.Value), big.Int(new.Transaction.Value); v0.Cmp(&v1) != 0 {
|
if v0, v1 := big.Int(original.Transaction.Value), big.Int(new.Transaction.Value); v0.Cmp(&v1) != 0 {
|
||||||
modified = true
|
modified = true
|
||||||
|
|
|
@ -234,7 +234,7 @@ func mkTestTx(from common.MixedcaseAddress) core.SendTxArgs {
|
||||||
From: from,
|
From: from,
|
||||||
To: &to,
|
To: &to,
|
||||||
Gas: gas,
|
Gas: gas,
|
||||||
GasPrice: gasPrice,
|
GasPrice: &gasPrice,
|
||||||
Value: value,
|
Value: value,
|
||||||
Data: &data,
|
Data: &data,
|
||||||
Nonce: nonce}
|
Nonce: nonce}
|
||||||
|
|
|
@ -116,7 +116,12 @@ func (ui *CommandlineUI) ApproveTx(request *SignTxRequest) (SignTxResponse, erro
|
||||||
fmt.Printf("from: %v\n", request.Transaction.From.String())
|
fmt.Printf("from: %v\n", request.Transaction.From.String())
|
||||||
fmt.Printf("value: %v wei\n", weival)
|
fmt.Printf("value: %v wei\n", weival)
|
||||||
fmt.Printf("gas: %v (%v)\n", request.Transaction.Gas, uint64(request.Transaction.Gas))
|
fmt.Printf("gas: %v (%v)\n", request.Transaction.Gas, uint64(request.Transaction.Gas))
|
||||||
|
if request.Transaction.MaxFeePerGas != nil {
|
||||||
|
fmt.Printf("maxFeePerGas: %v wei\n", request.Transaction.MaxFeePerGas.ToInt())
|
||||||
|
fmt.Printf("maxPriorityFeePerGas: %v wei\n", request.Transaction.MaxPriorityFeePerGas.ToInt())
|
||||||
|
} else {
|
||||||
fmt.Printf("gasprice: %v wei\n", request.Transaction.GasPrice.ToInt())
|
fmt.Printf("gasprice: %v wei\n", request.Transaction.GasPrice.ToInt())
|
||||||
|
}
|
||||||
fmt.Printf("nonce: %v (%v)\n", request.Transaction.Nonce, uint64(request.Transaction.Nonce))
|
fmt.Printf("nonce: %v (%v)\n", request.Transaction.Nonce, uint64(request.Transaction.Nonce))
|
||||||
if chainId := request.Transaction.ChainID; chainId != nil {
|
if chainId := request.Transaction.ChainID; chainId != nil {
|
||||||
fmt.Printf("chainid: %v\n", chainId)
|
fmt.Printf("chainid: %v\n", chainId)
|
||||||
|
|
|
@ -77,11 +77,12 @@ func (tx *GnosisSafeTx) ToTypedData() TypedData {
|
||||||
// ArgsForValidation returns a SendTxArgs struct, which can be used for the
|
// ArgsForValidation returns a SendTxArgs struct, which can be used for the
|
||||||
// common validations, e.g. look up 4byte destinations
|
// common validations, e.g. look up 4byte destinations
|
||||||
func (tx *GnosisSafeTx) ArgsForValidation() *SendTxArgs {
|
func (tx *GnosisSafeTx) ArgsForValidation() *SendTxArgs {
|
||||||
|
gp := hexutil.Big(tx.GasPrice)
|
||||||
args := &SendTxArgs{
|
args := &SendTxArgs{
|
||||||
From: tx.Safe,
|
From: tx.Safe,
|
||||||
To: &tx.To,
|
To: &tx.To,
|
||||||
Gas: hexutil.Uint64(tx.SafeTxGas.Uint64()),
|
Gas: hexutil.Uint64(tx.SafeTxGas.Uint64()),
|
||||||
GasPrice: hexutil.Big(tx.GasPrice),
|
GasPrice: &gp,
|
||||||
Value: hexutil.Big(tx.Value),
|
Value: hexutil.Big(tx.Value),
|
||||||
Nonce: hexutil.Uint64(tx.Nonce.Uint64()),
|
Nonce: hexutil.Uint64(tx.Nonce.Uint64()),
|
||||||
Data: tx.Data,
|
Data: tx.Data,
|
||||||
|
|
|
@ -19,12 +19,12 @@ package core
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/internal/ethapi"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValidationInfo struct {
|
type ValidationInfo struct {
|
||||||
|
@ -66,14 +66,21 @@ func (v *ValidationMessages) getWarnings() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendTxArgs represents the arguments to submit a transaction
|
// SendTxArgs represents the arguments to submit a transaction
|
||||||
|
// This struct is identical to ethapi.TransactionArgs, except for the usage of
|
||||||
|
// common.MixedcaseAddress in From and To
|
||||||
type SendTxArgs struct {
|
type SendTxArgs struct {
|
||||||
From common.MixedcaseAddress `json:"from"`
|
From common.MixedcaseAddress `json:"from"`
|
||||||
To *common.MixedcaseAddress `json:"to"`
|
To *common.MixedcaseAddress `json:"to"`
|
||||||
Gas hexutil.Uint64 `json:"gas"`
|
Gas hexutil.Uint64 `json:"gas"`
|
||||||
GasPrice hexutil.Big `json:"gasPrice"`
|
GasPrice *hexutil.Big `json:"gasPrice"`
|
||||||
|
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
|
||||||
|
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
|
||||||
Value hexutil.Big `json:"value"`
|
Value hexutil.Big `json:"value"`
|
||||||
Nonce hexutil.Uint64 `json:"nonce"`
|
Nonce hexutil.Uint64 `json:"nonce"`
|
||||||
|
|
||||||
// We accept "data" and "input" for backwards-compatibility reasons.
|
// We accept "data" and "input" for backwards-compatibility reasons.
|
||||||
|
// "input" is the newer name and should be preferred by clients.
|
||||||
|
// Issue detail: https://github.com/ethereum/go-ethereum/issues/15628
|
||||||
Data *hexutil.Bytes `json:"data"`
|
Data *hexutil.Bytes `json:"data"`
|
||||||
Input *hexutil.Bytes `json:"input,omitempty"`
|
Input *hexutil.Bytes `json:"input,omitempty"`
|
||||||
|
|
||||||
|
@ -91,38 +98,22 @@ func (args SendTxArgs) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (args *SendTxArgs) toTransaction() *types.Transaction {
|
func (args *SendTxArgs) toTransaction() *types.Transaction {
|
||||||
var input []byte
|
txArgs := ethapi.TransactionArgs{
|
||||||
if args.Data != nil {
|
Gas: &args.Gas,
|
||||||
input = *args.Data
|
GasPrice: args.GasPrice,
|
||||||
} else if args.Input != nil {
|
MaxFeePerGas: args.MaxFeePerGas,
|
||||||
input = *args.Input
|
MaxPriorityFeePerGas: args.MaxPriorityFeePerGas,
|
||||||
|
Value: &args.Value,
|
||||||
|
Nonce: &args.Nonce,
|
||||||
|
Data: args.Data,
|
||||||
|
Input: args.Input,
|
||||||
|
AccessList: args.AccessList,
|
||||||
|
ChainID: args.ChainID,
|
||||||
}
|
}
|
||||||
var to *common.Address
|
// Add the To-field, if specified
|
||||||
if args.To != nil {
|
if args.To != nil {
|
||||||
_to := args.To.Address()
|
to := args.To.Address()
|
||||||
to = &_to
|
txArgs.To = &to
|
||||||
}
|
}
|
||||||
var data types.TxData
|
return txArgs.ToTransaction()
|
||||||
if args.AccessList == nil {
|
|
||||||
data = &types.LegacyTx{
|
|
||||||
To: to,
|
|
||||||
Nonce: uint64(args.Nonce),
|
|
||||||
Gas: uint64(args.Gas),
|
|
||||||
GasPrice: (*big.Int)(&args.GasPrice),
|
|
||||||
Value: (*big.Int)(&args.Value),
|
|
||||||
Data: input,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
data = &types.AccessListTx{
|
|
||||||
To: to,
|
|
||||||
ChainID: (*big.Int)(args.ChainID),
|
|
||||||
Nonce: uint64(args.Nonce),
|
|
||||||
Gas: uint64(args.Gas),
|
|
||||||
GasPrice: (*big.Int)(&args.GasPrice),
|
|
||||||
Value: (*big.Int)(&args.Value),
|
|
||||||
Data: input,
|
|
||||||
AccessList: *args.AccessList,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return types.NewTx(data)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,16 @@ func (db *Database) ValidateTransaction(selector *string, tx *core.SendTxArgs) (
|
||||||
if bytes.Equal(tx.To.Address().Bytes(), common.Address{}.Bytes()) {
|
if bytes.Equal(tx.To.Address().Bytes(), common.Address{}.Bytes()) {
|
||||||
messages.Crit("Transaction recipient is the zero address")
|
messages.Crit("Transaction recipient is the zero address")
|
||||||
}
|
}
|
||||||
|
switch {
|
||||||
|
case tx.GasPrice == nil && tx.MaxFeePerGas == nil:
|
||||||
|
messages.Crit("Neither 'gasPrice' nor 'maxFeePerGas' specified.")
|
||||||
|
case tx.GasPrice == nil && tx.MaxPriorityFeePerGas == nil:
|
||||||
|
messages.Crit("Neither 'gasPrice' nor 'maxPriorityFeePerGas' specified.")
|
||||||
|
case tx.GasPrice != nil && tx.MaxFeePerGas != nil:
|
||||||
|
messages.Crit("Both 'gasPrice' and 'maxFeePerGas' specified.")
|
||||||
|
case tx.GasPrice != nil && tx.MaxPriorityFeePerGas != nil:
|
||||||
|
messages.Crit("Both 'gasPrice' and 'maxPriorityFeePerGas' specified.")
|
||||||
|
}
|
||||||
// Semantic fields validated, try to make heads or tails of the call data
|
// Semantic fields validated, try to make heads or tails of the call data
|
||||||
db.ValidateCallData(selector, data, messages)
|
db.ValidateCallData(selector, data, messages)
|
||||||
return messages, nil
|
return messages, nil
|
||||||
|
|
|
@ -60,7 +60,7 @@ func dummyTxArgs(t txtestcase) *core.SendTxArgs {
|
||||||
To: to,
|
To: to,
|
||||||
Value: value,
|
Value: value,
|
||||||
Nonce: n,
|
Nonce: n,
|
||||||
GasPrice: gasPrice,
|
GasPrice: &gasPrice,
|
||||||
Gas: gas,
|
Gas: gas,
|
||||||
Data: data,
|
Data: data,
|
||||||
Input: input,
|
Input: input,
|
||||||
|
|
|
@ -437,7 +437,7 @@ func dummyTx(value hexutil.Big) *core.SignTxRequest {
|
||||||
To: to,
|
To: to,
|
||||||
Value: value,
|
Value: value,
|
||||||
Nonce: n,
|
Nonce: n,
|
||||||
GasPrice: gasPrice,
|
GasPrice: &gasPrice,
|
||||||
Gas: gas,
|
Gas: gas,
|
||||||
},
|
},
|
||||||
Callinfo: []core.ValidationInfo{
|
Callinfo: []core.ValidationInfo{
|
||||||
|
|
Loading…
Reference in New Issue