feature/default_network_editable
brunobar79 6 years ago
parent e6d64cecf8
commit 2355573340
  1. 73
      app/scripts/eth-ledger-keyring-listener.js

@ -4,11 +4,9 @@ const ethUtil = require('ethereumjs-util')
const sigUtil = require('eth-sig-util') const sigUtil = require('eth-sig-util')
const Transaction = require('ethereumjs-tx') const Transaction = require('ethereumjs-tx')
// HD path differs from eth-hd-keyring - MEW, Parity, Geth and Official Ledger clients use same unusual derivation for Ledger
const hdPathString = `44'/60'/0'` const hdPathString = `44'/60'/0'`
const type = 'Ledger Hardware' const type = 'Ledger Hardware'
const ORIGIN = 'https://localhost:3000' const BRIDGE_URL = 'https://localhost:3000'
const pathBase = 'm' const pathBase = 'm'
const MAX_INDEX = 1000 const MAX_INDEX = 1000
@ -28,18 +26,15 @@ class LedgerKeyring extends EventEmitter {
setupIframe () { setupIframe () {
this.iframe = document.createElement('iframe') this.iframe = document.createElement('iframe')
this.iframe.src = ORIGIN this.iframe.src = BRIDGE_URL
console.log('Injecting ledger iframe')
document.head.appendChild(this.iframe) document.head.appendChild(this.iframe)
} }
sendMessage (msg, cb) { sendMessage (msg, cb) {
console.log('[LEDGER]: SENDING MESSAGE TO IFRAME', msg)
this.iframe.contentWindow.postMessage({...msg, target: 'LEDGER-IFRAME'}, '*') this.iframe.contentWindow.postMessage({...msg, target: 'LEDGER-IFRAME'}, '*')
window.addEventListener('message', ({ origin, data }) => { window.addEventListener('message', ({ origin, data }) => {
if (origin !== ORIGIN) return false if (origin !== BRIDGE_URL) return false
if (data && data.action && data.action === `${msg.action}-reply`) { if (data && data.action && data.action === `${msg.action}-reply`) {
console.log('[LEDGER]: GOT MESAGE FROM IFRAME', data)
cb(data) cb(data)
} }
}) })
@ -75,7 +70,7 @@ class LedgerKeyring extends EventEmitter {
hdPath: this.hdPath, hdPath: this.hdPath,
}, },
}, },
({action, success, payload}) => { ({success, payload}) => {
if (success) { if (success) {
this.hdk.publicKey = new Buffer(payload.publicKey, 'hex') this.hdk.publicKey = new Buffer(payload.publicKey, 'hex')
this.hdk.chainCode = new Buffer(payload.chainCode, 'hex') this.hdk.chainCode = new Buffer(payload.chainCode, 'hex')
@ -87,10 +82,6 @@ class LedgerKeyring extends EventEmitter {
}) })
} }
setAccountToUnlock (index) {
this.unlockedAccount = parseInt(index, 10)
}
addAccounts (n = 1) { addAccounts (n = 1) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -173,36 +164,44 @@ class LedgerKeyring extends EventEmitter {
// tx is an instance of the ethereumjs-transaction class. // tx is an instance of the ethereumjs-transaction class.
async signTransaction (address, tx) { async signTransaction (address, tx) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
this.unlock() this.unlock()
.then(_ => { .then(_ => {
this.sendMessage({
action: 'ledger-sign-transaction', const newTx = new Transaction({
params: {
tx: {
from: this._normalize(address), from: this._normalize(address),
to: this._normalize(tx.to), to: this._normalize(tx.to),
value: this._normalize(tx.value), value: this._normalize(tx.value),
data: this._normalize(tx.data), data: this._normalize(tx.data),
chainId: tx._chainId, chainId: tx._chainId,
nonce: this._fixNonce(this._normalize(tx.nonce)), nonce: this._normalize(tx.nonce),
gasLimit: this._normalize(tx.gasLimit), gasLimit: this._normalize(tx.gasLimit),
gasPrice: this._normalize(tx.gasPrice), gasPrice: this._normalize(tx.gasPrice),
}, v: ethUtil.bufferToHex(tx.getChainId()),
path: this._pathFromAddress(address), r: '0x00',
s: '0x00',
})
this.sendMessage({
action: 'ledger-sign-transaction',
params: {
tx: newTx.serialize().toString('hex'),
hdPath: this._pathFromAddress(address),
}, },
}, },
({action, success, payload}) => { ({success, payload}) => {
if (success) { if (success) {
const signedTx = new Transaction(payload.txData)
// Validate that the signature matches the right address newTx.v = Buffer.from(payload.v, 'hex')
const addressSignedWith = ethUtil.toChecksumAddress(`0x${signedTx.from.toString('hex')}`) newTx.r = Buffer.from(payload.r, 'hex')
const correctAddress = ethUtil.toChecksumAddress(address) newTx.s = Buffer.from(payload.s, 'hex')
if (addressSignedWith !== correctAddress) {
reject('signature doesnt match the right address') const valid = newTx.verifySignature()
if (valid) {
resolve(newTx)
} else {
reject('The transaction signature is not valid')
} }
resolve(signedTx)
} else { } else {
reject(payload) reject(payload)
} }
@ -225,19 +224,18 @@ class LedgerKeyring extends EventEmitter {
this.sendMessage({ this.sendMessage({
action: 'ledger-sign-personal-message', action: 'ledger-sign-personal-message',
params: { params: {
path: this._pathFromAddress(withAccount ), hdPath: this._pathFromAddress(withAccount),
message: bufferMsg, message: bufferMsg,
}, },
}, },
({action, success, payload}) => { ({success, payload}) => {
if (success) { if (success) {
const { result } = payload let v = payload['v'] - 27
let v = result['v'] - 27
v = v.toString(16) v = v.toString(16)
if (v.length < 2) { if (v.length < 2) {
v = `0${v}` v = `0${v}`
} }
const signature = `0x${result['r']}${result['s']}${v}` const signature = `0x${payload['r']}${payload['s']}${v}`
const addressSignedWith = sigUtil.recoverPersonalSignature({data: message, sig: signature}) const addressSignedWith = sigUtil.recoverPersonalSignature({data: message, sig: signature})
if (ethUtil.toChecksumAddress(addressSignedWith) !== ethUtil.toChecksumAddress(withAccount)) { if (ethUtil.toChecksumAddress(addressSignedWith) !== ethUtil.toChecksumAddress(withAccount)) {
reject('signature doesnt match the right address') reject('signature doesnt match the right address')
@ -316,13 +314,6 @@ class LedgerKeyring extends EventEmitter {
return str return str
} }
_fixNonce (nonce) {
if (nonce === '0x') {
return `${nonce}0`
}
return nonce
}
} }
LedgerKeyring.type = type LedgerKeyring.type = type

Loading…
Cancel
Save