accounts: eip-712 signing for ledger (#22378)

* accounts: eip-712 signing for ledger

* address review comments
This commit is contained in:
MrChico
2021-03-22 09:29:32 +01:00
committed by GitHub
parent eaccdba4ab
commit aab35600bc
3 changed files with 128 additions and 1 deletions

View File

@ -67,6 +67,8 @@ type driver interface {
// SignTx sends the transaction to the USB device and waits for the user to confirm
// or deny the transaction.
SignTx(path accounts.DerivationPath, tx *types.Transaction, chainID *big.Int) (common.Address, *types.Transaction, error)
SignTypedMessage(path accounts.DerivationPath, messageHash []byte, domainHash []byte) ([]byte, error)
}
// wallet represents the common functionality shared by all USB hardware
@ -524,7 +526,46 @@ func (w *wallet) signHash(account accounts.Account, hash []byte) ([]byte, error)
// SignData signs keccak256(data). The mimetype parameter describes the type of data being signed
func (w *wallet) SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error) {
return w.signHash(account, crypto.Keccak256(data))
// Unless we are doing 712 signing, simply dispatch to signHash
if !(mimeType == accounts.MimetypeTypedData && len(data) == 66 && data[0] == 0x19 && data[1] == 0x01) {
return w.signHash(account, crypto.Keccak256(data))
}
// dispatch to 712 signing if the mimetype is TypedData and the format matches
w.stateLock.RLock() // Comms have own mutex, this is for the state fields
defer w.stateLock.RUnlock()
// If the wallet is closed, abort
if w.device == nil {
return nil, accounts.ErrWalletClosed
}
// Make sure the requested account is contained within
path, ok := w.paths[account.Address]
if !ok {
return nil, accounts.ErrUnknownAccount
}
// All infos gathered and metadata checks out, request signing
<-w.commsLock
defer func() { w.commsLock <- struct{}{} }()
// Ensure the device isn't screwed with while user confirmation is pending
// TODO(karalabe): remove if hotplug lands on Windows
w.hub.commsLock.Lock()
w.hub.commsPend++
w.hub.commsLock.Unlock()
defer func() {
w.hub.commsLock.Lock()
w.hub.commsPend--
w.hub.commsLock.Unlock()
}()
// Sign the transaction
signature, err := w.driver.SignTypedMessage(path, data[2:34], data[34:66])
if err != nil {
return nil, err
}
return signature, nil
}
// SignDataWithPassphrase implements accounts.Wallet, attempting to sign the given