From 67da83aca51d30df9ba2d00b9ec694422626a3ad Mon Sep 17 00:00:00 2001
From: Martin Holst Swende <martin@swende.se>
Date: Wed, 21 Apr 2021 13:03:33 +0200
Subject: [PATCH] accounts/external, signer/core: add support for EIP-2930
 transactions (#22585)

This adds support for signing EIP-2930 with clef.
---
 accounts/external/backend.go | 14 ++++++++++++++
 signer/core/api.go           |  8 ++++++++
 signer/core/cliui.go         | 12 ++++++++++++
 signer/core/types.go         | 34 +++++++++++++++++++++++++++++++---
 4 files changed, 65 insertions(+), 3 deletions(-)

diff --git a/accounts/external/backend.go b/accounts/external/backend.go
index 17a747db0..de241385c 100644
--- a/accounts/external/backend.go
+++ b/accounts/external/backend.go
@@ -212,6 +212,20 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
 		To:       to,
 		From:     common.NewMixedcaseAddress(account.Address),
 	}
+	// We should request the default chain id that we're operating with
+	// (the chain we're executing on)
+	if chainID != nil {
+		args.ChainID = (*hexutil.Big)(chainID)
+	}
+	// However, if the user asked for a particular chain id, then we should
+	// use that instead.
+	if tx.Type() != types.LegacyTxType && tx.ChainId() != nil {
+		args.ChainID = (*hexutil.Big)(tx.ChainId())
+	}
+	if tx.Type() == types.AccessListTxType {
+		accessList := tx.AccessList()
+		args.AccessList = &accessList
+	}
 	var res signTransactionResult
 	if err := api.client.Call(&res, "account_signTransaction", args); err != nil {
 		return nil, err
diff --git a/signer/core/api.go b/signer/core/api.go
index 968dcfb2e..3811162f8 100644
--- a/signer/core/api.go
+++ b/signer/core/api.go
@@ -534,6 +534,14 @@ func (api *SignerAPI) SignTransaction(ctx context.Context, args SendTxArgs, meth
 			return nil, err
 		}
 	}
+	if args.ChainID != nil {
+		requestedChainId := (*big.Int)(args.ChainID)
+		if api.chainID.Cmp(requestedChainId) != 0 {
+			log.Error("Signing request with wrong chain id", "requested", requestedChainId, "configured", api.chainID)
+			return nil, fmt.Errorf("requested chainid %d does not match the configuration of the signer",
+				requestedChainId)
+		}
+	}
 	req := SignTxRequest{
 		Transaction: args,
 		Meta:        MetadataFromContext(ctx),
diff --git a/signer/core/cliui.go b/signer/core/cliui.go
index cbfb56c9d..e0375483c 100644
--- a/signer/core/cliui.go
+++ b/signer/core/cliui.go
@@ -118,6 +118,18 @@ func (ui *CommandlineUI) ApproveTx(request *SignTxRequest) (SignTxResponse, erro
 	fmt.Printf("gas:      %v (%v)\n", request.Transaction.Gas, uint64(request.Transaction.Gas))
 	fmt.Printf("gasprice: %v wei\n", request.Transaction.GasPrice.ToInt())
 	fmt.Printf("nonce:    %v (%v)\n", request.Transaction.Nonce, uint64(request.Transaction.Nonce))
+	if chainId := request.Transaction.ChainID; chainId != nil {
+		fmt.Printf("chainid:  %v\n", chainId)
+	}
+	if list := request.Transaction.AccessList; list != nil {
+		fmt.Printf("Accesslist\n")
+		for i, el := range *list {
+			fmt.Printf(" %d. %v\n", i, el.Address)
+			for j, slot := range el.StorageKeys {
+				fmt.Printf("   %d. %v\n", j, slot)
+			}
+		}
+	}
 	if request.Transaction.Data != nil {
 		d := *request.Transaction.Data
 		if len(d) > 0 {
diff --git a/signer/core/types.go b/signer/core/types.go
index 58b377c8d..e952a2120 100644
--- a/signer/core/types.go
+++ b/signer/core/types.go
@@ -76,6 +76,10 @@ type SendTxArgs struct {
 	// We accept "data" and "input" for backwards-compatibility reasons.
 	Data  *hexutil.Bytes `json:"data"`
 	Input *hexutil.Bytes `json:"input,omitempty"`
+
+	// For non-legacy transactions
+	AccessList *types.AccessList `json:"accessList,omitempty"`
+	ChainID    *hexutil.Big      `json:"chainId,omitempty"`
 }
 
 func (args SendTxArgs) String() string {
@@ -93,8 +97,32 @@ func (args *SendTxArgs) toTransaction() *types.Transaction {
 	} else if args.Input != nil {
 		input = *args.Input
 	}
-	if args.To == nil {
-		return types.NewContractCreation(uint64(args.Nonce), (*big.Int)(&args.Value), uint64(args.Gas), (*big.Int)(&args.GasPrice), input)
+	var to *common.Address
+	if args.To != nil {
+		_to := args.To.Address()
+		to = &_to
+	}
+	var data types.TxData
+	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.NewTransaction(uint64(args.Nonce), args.To.Address(), (*big.Int)(&args.Value), (uint64)(args.Gas), (*big.Int)(&args.GasPrice), input)
+	return types.NewTx(data)
 }
-- 
GitLab