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