Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

accounts/usbwallet: support dynamic tx for ledger #30180

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions accounts/usbwallet/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -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...)
Expand All @@ -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 {
Copy link
Contributor Author

@shrimalmadhur shrimalmadhur Jul 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this is need for DynamicTx. Does this bug exist in DynamicTx too or it only exist in EIP155?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The workaround can be left in place for all tx types. It's just a way of modifying the transfer so it doesn't trigger a certain bug in the firmware.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fjl this doesn't seems to work for other tx. This could very well be due to the way typed tx are formed.

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...)
}

I am not sure how to handle this bug here.
Ledger throws error

transaction type not supported

Copy link
Contributor

@holiman holiman Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, I was going to ask you to show some snippet from ledger-docs or something, to demonstrate that they do accept this format, where you prepend the type into the payload like this.

But, seeing as the ledger throws transaction type not supported -- doesn't this mean that this PR is moot, and that the ledger (at least with the software version you are using) does not support signing non-legacy transactions?

Copy link
Contributor Author

@shrimalmadhur shrimalmadhur Aug 28, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@holiman So the error transaction type not supported appears when I apply for ; len(payload)%chunk <= ledgerEip155Size; chunk-- logic for non legacy tx. If I don't do it - Ledger signing works. I have tested with my Ledger nano S. Let me find relevant ledger code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for ; len(payload)%chunk <= ledgerEip155Size; chunk-- {
}
}

for len(payload) > 0 {
Expand Down Expand Up @@ -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 {
Expand Down