mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 10:50:44 +00:00
Preserve set-code auth list in external signer
This commit is contained in:
parent
e3b6d0c86f
commit
47622451dc
4 changed files with 197 additions and 7 deletions
26
accounts/external/backend.go
vendored
26
accounts/external/backend.go
vendored
|
|
@ -198,6 +198,19 @@ type signTransactionResult struct {
|
|||
// by the external signer. For non-legacy transactions, the chain ID of the
|
||||
// transaction overrides the chainID parameter.
|
||||
func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
|
||||
args, err := signTxArgs(account, tx, chainID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var res signTransactionResult
|
||||
if err := api.client.Call(&res, "account_signTransaction", args); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Tx, nil
|
||||
}
|
||||
|
||||
func signTxArgs(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*apitypes.SendTxArgs, error) {
|
||||
data := hexutil.Bytes(tx.Data())
|
||||
var to *common.MixedcaseAddress
|
||||
if tx.To() != nil {
|
||||
|
|
@ -215,9 +228,13 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
|
|||
switch tx.Type() {
|
||||
case types.LegacyTxType, types.AccessListTxType:
|
||||
args.GasPrice = (*hexutil.Big)(tx.GasPrice())
|
||||
case types.DynamicFeeTxType, types.BlobTxType, types.SetCodeTxType:
|
||||
case types.DynamicFeeTxType, types.BlobTxType:
|
||||
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
|
||||
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
|
||||
case types.SetCodeTxType:
|
||||
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
|
||||
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
|
||||
args.AuthorizationList = tx.SetCodeAuthorizations()
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported tx type %d", tx.Type())
|
||||
}
|
||||
|
|
@ -246,12 +263,7 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
|
|||
args.Commitments = sidecar.Commitments
|
||||
args.Proofs = sidecar.Proofs
|
||||
}
|
||||
|
||||
var res signTransactionResult
|
||||
if err := api.client.Call(&res, "account_signTransaction", args); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res.Tx, nil
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (api *ExternalSigner) SignTextWithPassphrase(account accounts.Account, passphrase string, text []byte) ([]byte, error) {
|
||||
|
|
|
|||
81
accounts/external/backend_test.go
vendored
Normal file
81
accounts/external/backend_test.go
vendored
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
// Copyright 2026 The go-ethereum Authors
|
||||
// This file is part of the go-ethereum library.
|
||||
//
|
||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
// for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
package external
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/holiman/uint256"
|
||||
)
|
||||
|
||||
func TestSignTxArgsSetCodeAuthorizationList(t *testing.T) {
|
||||
account := accounts.Account{Address: common.HexToAddress("0x1000000000000000000000000000000000000001")}
|
||||
to := common.HexToAddress("0x2000000000000000000000000000000000000002")
|
||||
auth := types.SetCodeAuthorization{
|
||||
ChainID: *uint256.NewInt(5),
|
||||
Address: common.HexToAddress("0x3000000000000000000000000000000000000003"),
|
||||
Nonce: 9,
|
||||
V: 1,
|
||||
R: *uint256.NewInt(10),
|
||||
S: *uint256.NewInt(11),
|
||||
}
|
||||
tx := types.NewTx(&types.SetCodeTx{
|
||||
ChainID: uint256.NewInt(5),
|
||||
Nonce: 4,
|
||||
GasTipCap: uint256.NewInt(3),
|
||||
GasFeeCap: uint256.NewInt(30),
|
||||
Gas: 21000,
|
||||
To: to,
|
||||
Value: uint256.NewInt(7),
|
||||
Data: []byte{0x01, 0x02},
|
||||
AccessList: types.AccessList{{
|
||||
Address: common.HexToAddress("0x4000000000000000000000000000000000000004"),
|
||||
StorageKeys: []common.Hash{common.HexToHash("0x01")},
|
||||
}},
|
||||
AuthList: []types.SetCodeAuthorization{auth},
|
||||
})
|
||||
args, err := signTxArgs(account, tx, big.NewInt(1))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if args.ChainID == nil || (*big.Int)(args.ChainID).Cmp(big.NewInt(5)) != 0 {
|
||||
t.Fatalf("have chain id %v, want 5", args.ChainID)
|
||||
}
|
||||
if args.MaxFeePerGas == nil || (*big.Int)(args.MaxFeePerGas).Cmp(big.NewInt(30)) != 0 {
|
||||
t.Fatalf("have max fee %v, want 30", args.MaxFeePerGas)
|
||||
}
|
||||
if args.MaxPriorityFeePerGas == nil || (*big.Int)(args.MaxPriorityFeePerGas).Cmp(big.NewInt(3)) != 0 {
|
||||
t.Fatalf("have max priority fee %v, want 3", args.MaxPriorityFeePerGas)
|
||||
}
|
||||
if !reflect.DeepEqual(args.AuthorizationList, []types.SetCodeAuthorization{auth}) {
|
||||
t.Fatalf("have auth list %#v, want %#v", args.AuthorizationList, []types.SetCodeAuthorization{auth})
|
||||
}
|
||||
blob, err := json.Marshal(args)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Contains(blob, []byte(`"authorizationList"`)) {
|
||||
t.Fatalf("marshaled args missing authorizationList: %s", blob)
|
||||
}
|
||||
}
|
||||
|
|
@ -112,6 +112,9 @@ type SendTxArgs struct {
|
|||
Blobs []kzg4844.Blob `json:"blobs,omitempty"`
|
||||
Commitments []kzg4844.Commitment `json:"commitments,omitempty"`
|
||||
Proofs []kzg4844.Proof `json:"proofs,omitempty"`
|
||||
|
||||
// For SetCodeTxType
|
||||
AuthorizationList []types.SetCodeAuthorization `json:"authorizationList,omitempty"`
|
||||
}
|
||||
|
||||
func (args SendTxArgs) String() string {
|
||||
|
|
@ -146,6 +149,27 @@ func (args *SendTxArgs) ToTransaction() (*types.Transaction, error) {
|
|||
}
|
||||
var data types.TxData
|
||||
switch {
|
||||
case args.AuthorizationList != nil:
|
||||
al := types.AccessList{}
|
||||
if args.AccessList != nil {
|
||||
al = *args.AccessList
|
||||
}
|
||||
if to == nil {
|
||||
return nil, errors.New("transaction recipient must be set for set-code transactions")
|
||||
}
|
||||
data = &types.SetCodeTx{
|
||||
To: *to,
|
||||
ChainID: uint256.MustFromBig((*big.Int)(args.ChainID)),
|
||||
Nonce: uint64(args.Nonce),
|
||||
Gas: uint64(args.Gas),
|
||||
GasFeeCap: uint256.MustFromBig((*big.Int)(args.MaxFeePerGas)),
|
||||
GasTipCap: uint256.MustFromBig((*big.Int)(args.MaxPriorityFeePerGas)),
|
||||
Value: uint256.MustFromBig((*big.Int)(&args.Value)),
|
||||
Data: args.data(),
|
||||
AccessList: al,
|
||||
AuthList: args.AuthorizationList,
|
||||
}
|
||||
|
||||
case args.BlobHashes != nil:
|
||||
al := types.AccessList{}
|
||||
if args.AccessList != nil {
|
||||
|
|
|
|||
|
|
@ -17,12 +17,16 @@
|
|||
package apitypes
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto/kzg4844"
|
||||
"github.com/holiman/uint256"
|
||||
|
|
@ -99,6 +103,75 @@ func TestTxArgs(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSetCodeTxArgs(t *testing.T) {
|
||||
to := common.HexToAddress("0x1000000000000000000000000000000000000001")
|
||||
from := common.NewMixedcaseAddress(common.HexToAddress("0x9000000000000000000000000000000000000009"))
|
||||
mixedTo := common.NewMixedcaseAddress(to)
|
||||
input := hexutil.Bytes{0x01, 0x02}
|
||||
chainID := hexutil.Big(*big.NewInt(5))
|
||||
maxFee := hexutil.Big(*big.NewInt(30))
|
||||
maxTip := hexutil.Big(*big.NewInt(3))
|
||||
value := hexutil.Big(*big.NewInt(7))
|
||||
accessList := types.AccessList{{
|
||||
Address: common.HexToAddress("0x2000000000000000000000000000000000000002"),
|
||||
StorageKeys: []common.Hash{common.HexToHash("0x01")},
|
||||
}}
|
||||
auth := types.SetCodeAuthorization{
|
||||
ChainID: *uint256.NewInt(5),
|
||||
Address: common.HexToAddress("0x3000000000000000000000000000000000000003"),
|
||||
Nonce: 9,
|
||||
V: 1,
|
||||
R: *uint256.NewInt(10),
|
||||
S: *uint256.NewInt(11),
|
||||
}
|
||||
args := SendTxArgs{
|
||||
From: from,
|
||||
To: &mixedTo,
|
||||
Gas: 21000,
|
||||
MaxFeePerGas: &maxFee,
|
||||
MaxPriorityFeePerGas: &maxTip,
|
||||
Value: value,
|
||||
Nonce: 4,
|
||||
Input: &input,
|
||||
AccessList: &accessList,
|
||||
ChainID: &chainID,
|
||||
AuthorizationList: []types.SetCodeAuthorization{auth},
|
||||
}
|
||||
blob, err := json.Marshal(args)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !bytes.Contains(blob, []byte(`"authorizationList"`)) {
|
||||
t.Fatalf("marshaled args missing authorizationList: %s", blob)
|
||||
}
|
||||
var decoded SendTxArgs
|
||||
if err := json.Unmarshal(blob, &decoded); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
tx, err := decoded.ToTransaction()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if have, want := tx.Type(), uint8(types.SetCodeTxType); have != want {
|
||||
t.Fatalf("have tx type %d, want %d", have, want)
|
||||
}
|
||||
if have := tx.To(); have == nil || *have != to {
|
||||
t.Fatalf("have to %v, want %v", have, to)
|
||||
}
|
||||
if have, want := tx.ChainId(), big.NewInt(5); have.Cmp(want) != 0 {
|
||||
t.Fatalf("have chain id %v, want %v", have, want)
|
||||
}
|
||||
if !bytes.Equal(tx.Data(), input) {
|
||||
t.Fatalf("have input %x, want %x", tx.Data(), input)
|
||||
}
|
||||
if !reflect.DeepEqual(tx.AccessList(), accessList) {
|
||||
t.Fatalf("have access list %#v, want %#v", tx.AccessList(), accessList)
|
||||
}
|
||||
if !reflect.DeepEqual(tx.SetCodeAuthorizations(), []types.SetCodeAuthorization{auth}) {
|
||||
t.Fatalf("have auth list %#v, want %#v", tx.SetCodeAuthorizations(), []types.SetCodeAuthorization{auth})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBlobTxs(t *testing.T) {
|
||||
blob := kzg4844.Blob{0x1}
|
||||
commitment, err := kzg4844.BlobToCommitment(&blob)
|
||||
|
|
|
|||
Loading…
Reference in a new issue