sign transactions is pretty close

feature/default_network_editable
Bruno 7 years ago
parent d1880073f6
commit 68d97211ff
  1. 118
      app/scripts/lib/trezorKeyring.js

@ -4,10 +4,11 @@ const ethUtil = require('ethereumjs-util')
const hdPathString = `m/44'/60'/0'/0` const hdPathString = `m/44'/60'/0'/0`
const keyringType = 'Trezor Hardware' const keyringType = 'Trezor Hardware'
const Transaction = require('ethereumjs-tx')
const pathBase = 'm'
const TrezorConnect = require('./trezor-connect.js') const TrezorConnect = require('./trezor-connect.js')
const HDKey = require('hdkey') const HDKey = require('hdkey')
const TREZOR_FIRMWARE_VERSION = '1.4.0' const TREZOR_MIN_FIRMWARE_VERSION = '1.5.2'
const log = require('loglevel') const log = require('loglevel')
class TrezorKeyring extends EventEmitter { class TrezorKeyring extends EventEmitter {
@ -19,7 +20,7 @@ class TrezorKeyring extends EventEmitter {
this.deserialize(opts) this.deserialize(opts)
this.page = 0 this.page = 0
this.perPage = 5 this.perPage = 5
this.accountToUnlock = 0 this.unlockedAccount = 0
} }
serialize () { serialize () {
@ -53,13 +54,13 @@ class TrezorKeyring extends EventEmitter {
reject(response.error || 'Unknown error') reject(response.error || 'Unknown error')
} }
}, },
TREZOR_FIRMWARE_VERSION TREZOR_MIN_FIRMWARE_VERSION
) )
}) })
} }
setAccountToUnlock (index) { setAccountToUnlock (index) {
this.accountToUnlock = parseInt(index, 10) this.unlockedAccount = parseInt(index, 10)
} }
addAccounts (n = 1) { addAccounts (n = 1) {
@ -67,18 +68,13 @@ class TrezorKeyring extends EventEmitter {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
return this.unlock() return this.unlock()
.then(_ => { .then(_ => {
const pathBase = 'm' const from = this.unlockedAccount
const from = this.accountToUnlock
const to = from + 1 const to = from + 1
this.accounts = [] this.accounts = []
for (let i = from; i < to; i++) { for (let i = from; i < to; i++) {
const dkey = this.hdk.derive(`${pathBase}/${i}`)
const address = ethUtil this.accounts.push(this.getEthAddress(pathBase, i))
.publicToAddress(dkey.publicKey, true)
.toString('hex')
this.accounts.push(ethUtil.toChecksumAddress(address))
this.page = 0 this.page = 0
} }
resolve(this.accounts) resolve(this.accounts)
@ -94,19 +90,16 @@ class TrezorKeyring extends EventEmitter {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
return this.unlock() return this.unlock()
.then(_ => { .then(_ => {
const pathBase = 'm'
const from = this.page === 0 ? 0 : (this.page - 1) * this.perPage const from = this.page === 0 ? 0 : (this.page - 1) * this.perPage
const to = from + this.perPage const to = from + this.perPage
const accounts = [] const accounts = []
for (let i = from; i < to; i++) { for (let i = from; i < to; i++) {
const dkey = this.hdk.derive(`${pathBase}/${i}`)
const address = ethUtil
.publicToAddress(dkey.publicKey, true)
.toString('hex')
accounts.push({ accounts.push({
address: ethUtil.toChecksumAddress(address), address: this.getEthAddress(pathBase, i),
balance: 0, balance: 0,
index: i, index: i,
}) })
@ -134,40 +127,75 @@ class TrezorKeyring extends EventEmitter {
return Promise.resolve(this.accounts.slice()) return Promise.resolve(this.accounts.slice())
} }
padLeftEven (hex) {
return hex.length % 2 !== 0 ? `0${hex}` : hex
}
cleanData (buf) {
return this.padLeftEven(ethUtil.bufferToHex(buf).substring(2).toLowerCase())
}
getEthAddress (pathBase, i) {
const dkey = this.hdk.derive(`${pathBase}/${i}`)
const address = ethUtil
.publicToAddress(dkey.publicKey, true)
.toString('hex')
return ethUtil.toChecksumAddress(address)
}
// 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) {
throw new Error('Not supported on this device')
/*
await this.lock.acquire()
try {
// Look before we leap return new Promise((resolve, reject) => {
await this._checkCorrectTrezorAttached() log.debug('sign transaction ', address, tx)
const account = `m/44'/60'/0'/${this.unlockedAccount}`
const txData = {
account,
nonce: this.cleanData(tx.nonce),
gasPrice: this.cleanData(tx.gasPrice),
gasLimit: this.cleanData(tx.gasLimit),
to: this.cleanData(tx.to),
value: this.cleanData(tx.value),
data: this.cleanData(tx.data),
chainId: tx._chainId,
}
let accountId = await this._findAddressId(address) TrezorConnect.ethereumSignTx(
let eth = await this._getEth() txData.account,
tx.v = tx._chainId txData.nonce,
let TrezorSig = await eth.signTransaction( txData.gasPrice,
this._derivePath(accountId), txData.gasLimit,
tx.serialize().toString('hex') txData.to,
) txData.value,
tx.v = parseInt(TrezorSig.v, 16) txData.data === '' ? null : txData.data,
tx.r = '0x' + TrezorSig.r txData.chainId,
tx.s = '0x' + TrezorSig.s response => {
if (response.success) {
tx.v = `0x${response.v.toString(16)}`
tx.r = `0x${response.r}`
tx.s = `0x${response.s}`
log.debug('about to create new tx with data', tx)
// Since look before we leap check is racy, also check that signature is for account expected const signedTx = new Transaction(tx)
let addressSignedWith = ethUtil.bufferToHex(tx.getSenderAddress())
if (addressSignedWith.toLowerCase() !== address.toLowerCase()) { log.debug('signature is valid?', signedTx.verifySignature())
throw new Error(
`Signature is for ${addressSignedWith} but expected ${address} - is the correct Trezor device attached?` const addressSignedWith = ethUtil.toChecksumAddress(`0x${signedTx.from.toString('hex')}`)
) const correctAddress = ethUtil.toChecksumAddress(address)
if (addressSignedWith !== correctAddress) {
// throw new Error('signature doesnt match the right address')
log.error('signature doesnt match the right address', addressSignedWith, correctAddress)
} }
return tx resolve(signedTx)
} finally { } else {
await this.lock.release() throw new Error(response.error || 'Unknown error')
}*/ }
},
TREZOR_MIN_FIRMWARE_VERSION)
})
} }
async signMessage (withAccount, data) { async signMessage (withAccount, data) {

Loading…
Cancel
Save