Repository: ethereum/go-ethereum (language: go)

Issue:
Support LondonSigner in Ledger USBWallet
# Rationale

Why should this feature exist?
Currently Ledger only support LegacyTx and I want it to support DynamicTx as the LegacyTx is well, Legacy.
https://github.com/ethereum/go-ethereum/blob/f59d013e4064adbb092b323781104c07550a8bff/accounts/usbwallet/ledger.go#L379-L387

What are the use-cases?
Can use EIP1559 dynamic fee tx

# Implementation

Do you have ideas regarding the implementation of this feature? 
No - I have been reading the code and trying to see what all changes I will have to make, but I can give it a shot.

From what I understand this block needs to support typed transactions as ethereum app on ledger supports parsing that. https://github.com/ethereum/go-ethereum/blob/f59d013e4064adbb092b323781104c07550a8bff/accounts/usbwallet/ledger.go#L336-L343

I still don't know how to deal with this though https://github.com/ethereum/go-ethereum/blob/f59d013e4064adbb092b323781104c07550a8bff/accounts/usbwallet/ledger.go#L353-L357

Are you willing to implement this feature? 
Yes


Discussion / hints:

Fix patch:
diff --git a/accounts/usbwallet/ledger.go b/accounts/usbwallet/ledger.go
index 81836b3717ac..2be6edd44f8a 100644
--- a/accounts/usbwallet/ledger.go
+++ b/accounts/usbwallet/ledger.go
@@ -338,8 +338,22 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
 			return common.Address{}, nil, err
 		}
 	} else {
-		if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil {
-			return common.Address{}, nil, err
+		if tx.Type() == types.DynamicFeeTxType {
+			if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasTipCap(), tx.GasFeeCap(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
+				return common.Address{}, nil, err
+			}
+			// append type to transaction
+			txrlp = append([]byte{tx.Type()}, txrlp...)
+		} else if tx.Type() == types.AccessListTxType {
+			if txrlp, err = rlp.EncodeToBytes([]interface{}{chainID, tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), tx.AccessList()}); err != nil {
+				return common.Address{}, nil, err
+			}
+			// append type to transaction
+			txrlp = append([]byte{tx.Type()}, txrlp...)
+		} else if tx.Type() == types.LegacyTxType {
+			if txrlp, err = rlp.EncodeToBytes([]interface{}{tx.Nonce(), tx.GasPrice(), tx.Gas(), tx.To(), tx.Value(), tx.Data(), chainID, big.NewInt(0), big.NewInt(0)}); err != nil {
+				return common.Address{}, nil, err
+			}
 		}
 	}
 	payload := append(path, txrlp...)
@@ -353,7 +367,9 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
 	// Chunk size selection to mitigate an underlying RLP deserialization issue on the ledger app.
 	// https://github.com/LedgerHQ/app-ethereum/issues/409
 	chunk := 255
-	for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
+	if tx.Type() == types.LegacyTxType {
+		for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
+		}
 	}
 
 	for len(payload) > 0 {
@@ -381,8 +397,11 @@ func (w *ledgerDriver) ledgerSign(derivationPath []uint32, tx *types.Transaction
 	if chainID == nil {
 		signer = new(types.HomesteadSigner)
 	} else {
-		signer = types.NewEIP155Signer(chainID)
-		signature[64] -= byte(chainID.Uint64()*2 + 35)
+		signer = types.LatestSignerForChainID(chainID)
+		// For non-legacy transactions, V is 0 or 1, no need to subtract here.
+		if tx.Type() == types.LegacyTxType {
+			signature[64] -= byte(chainID.Uint64()*2 + 35)
+		}
 	}
 	signed, err := tx.WithSignature(signer, signature)
 	if err != nil {


Test patch: