Skip to content

Commit 4906c99

Browse files
hackmodgballet
andauthored
accounts/usbwallet: full 32bit chainId support for Trezor (#17439)
This fix allows Trezor to support full 32bit chainId in geth, with the next version of firmware. For `chainId > 2147483630` case, Trezor returns signature bit only. - Trezor returns only signature parity for `chainId > 2147483630` case. - for `chainId == 2147483630` case, Trezor returns `MAX_UINT32` or `0`, but it doesn't matter. (`2147483630 * 2 + 35` = `4294967295`(`MAX_UINT32`)) chainId | returned signature_v | compatible issue ---------|------------------------|-------------------- 0 < chainId <= 255 | chainId * 2 + 35 + v | no issue (firmware `1.6.2` for Trezor one) 255 < chainId <= 2147483630 | chainId * 2 + 35 + v | ***fixed.*** *firmware `1.6.3`* chainId > 2147483630 | v | *firmware `1.6.3`* Please see also: full 32bit chainId support for Trezor - Trezor one: trezor/trezor-mcu#399 ***merged*** - Trezor model T: trezor/trezor-core#311 ***merged*** --------- Signed-off-by: Guillaume Ballet <[email protected]> Co-authored-by: Guillaume Ballet <[email protected]>
1 parent 2547bb2 commit 4906c99

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

accounts/usbwallet/trezor.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"errors"
2626
"fmt"
2727
"io"
28+
"math"
2829
"math/big"
2930

3031
"github.com/ethereum/go-ethereum/accounts"
@@ -249,7 +250,11 @@ func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction
249250
}
250251
}
251252
// Extract the Ethereum signature and do a sanity validation
252-
if len(response.GetSignatureR()) == 0 || len(response.GetSignatureS()) == 0 || response.GetSignatureV() == 0 {
253+
if len(response.GetSignatureR()) == 0 || len(response.GetSignatureS()) == 0 {
254+
return common.Address{}, nil, errors.New("reply lacks signature")
255+
} else if response.GetSignatureV() == 0 && int(chainID.Int64()) <= (math.MaxUint32-36)/2 {
256+
// for chainId >= (MaxUint32-36)/2, Trezor returns signature bit only
257+
// https://github.com/trezor/trezor-mcu/pull/399
253258
return common.Address{}, nil, errors.New("reply lacks signature")
254259
}
255260
signature := append(append(response.GetSignatureR(), response.GetSignatureS()...), byte(response.GetSignatureV()))
@@ -261,7 +266,11 @@ func (w *trezorDriver) trezorSign(derivationPath []uint32, tx *types.Transaction
261266
} else {
262267
// Trezor backend does not support typed transactions yet.
263268
signer = types.NewEIP155Signer(chainID)
264-
signature[64] -= byte(chainID.Uint64()*2 + 35)
269+
// if chainId is above (MaxUint32 - 36) / 2 then the final v values is returned
270+
// directly. Otherwise, the returned value is 35 + chainid * 2.
271+
if signature[64] > 1 && int(chainID.Int64()) <= (math.MaxUint32-36)/2 {
272+
signature[64] -= byte(chainID.Uint64()*2 + 35)
273+
}
265274
}
266275

267276
// Inject the final signature into the transaction and sanity check the sender

0 commit comments

Comments
 (0)