aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Evans <jacob@dekz.net>2018-07-02 09:07:51 +0800
committerJacob Evans <jacob@dekz.net>2018-07-02 09:09:32 +0800
commitb9165c03af40983d885af2b18e729f11746de91d (patch)
treeafb8542d10c4d79f1265ffa04b05e03f3f0d6222
parent6bb2203f790923a83f6f0665d47d29a90817b371 (diff)
downloaddexon-sol-tools-b9165c03af40983d885af2b18e729f11746de91d.tar
dexon-sol-tools-b9165c03af40983d885af2b18e729f11746de91d.tar.gz
dexon-sol-tools-b9165c03af40983d885af2b18e729f11746de91d.tar.bz2
dexon-sol-tools-b9165c03af40983d885af2b18e729f11746de91d.tar.lz
dexon-sol-tools-b9165c03af40983d885af2b18e729f11746de91d.tar.xz
dexon-sol-tools-b9165c03af40983d885af2b18e729f11746de91d.tar.zst
dexon-sol-tools-b9165c03af40983d885af2b18e729f11746de91d.zip
Use PrivateKeySubprovider inside eth lightwallet
There's a loss of information when hex encoding and passing to eth light wallet (chain id is lost). This results in a different signature. While it may work on testnets it is not sufficient for our test cases. We can export the private key and use it in our PrivateKeyWalletSubprovider
-rw-r--r--packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts40
-rw-r--r--packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts74
-rw-r--r--packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts14
3 files changed, 57 insertions, 71 deletions
diff --git a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
index 64d984996..b594ffb24 100644
--- a/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
+++ b/packages/subproviders/src/subproviders/eth_lightwallet_subprovider.ts
@@ -2,11 +2,13 @@ import { assert } from '@0xproject/assert';
import { addressUtils } from '@0xproject/utils';
import * as lightwallet from 'eth-lightwallet';
import EthereumTx = require('ethereumjs-tx');
+import * as ethUtil from 'ethereumjs-util';
import * as _ from 'lodash';
import { PartialTxParams, WalletSubproviderErrors } from '../types';
import { BaseWalletSubprovider } from './base_wallet_subprovider';
+import { PrivateKeyWalletSubprovider } from './private_key_wallet';
/*
* This class implements the web3-provider-engine subprovider interface and forwards
@@ -42,17 +44,14 @@ export class EthLightwalletSubprovider extends BaseWalletSubprovider {
* @return Signed transaction hex string
*/
public async signTransactionAsync(txParams: PartialTxParams): Promise<string> {
- if (_.isUndefined(txParams.from) || !addressUtils.isAddress(txParams.from)) {
- throw new Error(WalletSubproviderErrors.FromAddressMissingOrInvalid);
- }
-
- const tx = new EthereumTx(txParams);
- const txHex = tx.serialize().toString('hex');
- let signedTxHex: string = lightwallet.signing.signTx(this._keystore, this._pwDerivedKey, txHex, txParams.from);
-
- signedTxHex = `0x${signedTxHex}`;
-
- return signedTxHex;
+ // Lightwallet loses the chain id information when hex encoding the transaction
+ // this results in a different signature on certain networks. PrivateKeyWallet
+ // respects this as it uses the parameters passed in
+ let privKey = this._keystore.exportPrivateKey(txParams.from, this._pwDerivedKey);
+ const privKeyWallet = new PrivateKeyWalletSubprovider(privKey);
+ const privKeySignature = await privKeyWallet.signTransactionAsync(txParams);
+ privKey = '';
+ return privKeySignature;
}
/**
* Sign a personal Ethereum signed message. The signing account will be the account
@@ -65,19 +64,10 @@ export class EthLightwalletSubprovider extends BaseWalletSubprovider {
* @return Signature hex string (order: rsv)
*/
public async signPersonalMessageAsync(data: string, address: string): Promise<string> {
- if (_.isUndefined(data)) {
- throw new Error(WalletSubproviderErrors.DataMissingForSignPersonalMessage);
- }
- assert.isHexString('data', data);
- assert.isETHAddressHex('address', address);
- const result: ECSignatureBuffer = lightwallet.signing.signMsgHash(
- this._keystore,
- this._pwDerivedKey,
- data,
- address,
- );
-
- const signature = lightwallet.signing.concatSig(result);
- return signature;
+ let privKey = this._keystore.exportPrivateKey(address, this._pwDerivedKey);
+ const privKeyWallet = new PrivateKeyWalletSubprovider(privKey);
+ privKey = '';
+ const result = privKeyWallet.signPersonalMessageAsync(data, address);
+ return result;
}
}
diff --git a/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts b/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts
index c0adb9225..f17c21f02 100644
--- a/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts
+++ b/packages/subproviders/test/unit/eth_lightwallet_subprovider_test.ts
@@ -1,34 +1,32 @@
import * as chai from 'chai';
import * as lightwallet from 'eth-lightwallet';
import { JSONRPCResponsePayload } from 'ethereum-types';
+import * as ethUtils from 'ethereumjs-util';
import Web3ProviderEngine = require('web3-provider-engine');
import { EthLightwalletSubprovider } from '../../src';
import { DoneCallback } from '../../src/types';
import { chaiSetup } from '../chai_setup';
+import { fixtureData } from '../utils/fixture_data';
import { ganacheSubprovider } from '../utils/ganache_subprovider';
import { reportCallbackErrors } from '../utils/report_callback_errors';
chaiSetup.configure();
const expect = chai.expect;
-const FAKE_ADDRESS = '0x44be42fd88e22387c43ba9b75941aa3e680dae25';
-const NUM_GENERATED_ADDRESSES = 10;
+const DEFAULT_NUM_ACCOUNTS = 10;
const PASSWORD = 'supersecretpassword99';
-const SEED_PHRASE = 'dilemma hollow outer pony cube season start stereo surprise when edit blast';
const SALT = 'kvODghzs7Ff1uqHyI0P3wI4Hso4w4iWT2e9qmrWz0y4';
-const HD_PATH_STRING = `m/44'/60'/0'`;
describe('EthLightwalletSubprovider', () => {
let ethLightwalletSubprovider: EthLightwalletSubprovider;
before(async () => {
const options = {
password: PASSWORD,
- seedPhrase: SEED_PHRASE,
+ seedPhrase: fixtureData.TEST_RPC_MNEMONIC,
salt: SALT,
- hdPathString: HD_PATH_STRING,
+ hdPathString: fixtureData.TESTRPC_BASE_DERIVATION_PATH,
};
-
const createVaultAsync = async (vaultOptions: lightwallet.VaultOptions) => {
return new Promise<lightwallet.keystore>(resolve => {
lightwallet.keystore.createVault(vaultOptions, (err: Error, vaultKeystore) => {
@@ -53,7 +51,7 @@ describe('EthLightwalletSubprovider', () => {
const pwDerivedKey: Uint8Array = await deriveKeyFromPasswordAsync(keystore);
// Generate 10 addresses
- keystore.generateNewAddress(pwDerivedKey, NUM_GENERATED_ADDRESSES);
+ keystore.generateNewAddress(pwDerivedKey, DEFAULT_NUM_ACCOUNTS);
ethLightwalletSubprovider = new EthLightwalletSubprovider(keystore, pwDerivedKey);
});
@@ -61,22 +59,20 @@ describe('EthLightwalletSubprovider', () => {
describe('success cases', () => {
it('returns a list of accounts', async () => {
const accounts = await ethLightwalletSubprovider.getAccountsAsync();
- expect(accounts[0]).to.be.equal(FAKE_ADDRESS);
- expect(accounts.length).to.be.equal(NUM_GENERATED_ADDRESSES);
+ expect(accounts[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
+ expect(accounts[1]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_1);
+ expect(accounts.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
});
it('signs a personal message hash', async () => {
- const signingAccount = (await ethLightwalletSubprovider.getAccountsAsync())[0];
-
- // Keccak-256 hash of 'hello world'
- const messageHash = '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad';
- const ecSignatureHex = await ethLightwalletSubprovider.signPersonalMessageAsync(
- messageHash,
- signingAccount,
- );
- expect(ecSignatureHex).to.be.equal(
- // tslint:disable-next-line:max-line-length
- '0xa46b696c1aa8f91dbb33d1a66f6440bf3cf334c9dc45dc389668c1e60e2db31e259400b41f31632fa994837054c5345c88dc455c13931332489029adee6fd24d1b',
- );
+ const accounts = await ethLightwalletSubprovider.getAccountsAsync();
+ const signingAccount = accounts[0];
+ const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
+ const ecSignatureHex = await ethLightwalletSubprovider.signPersonalMessageAsync(data, signingAccount);
+ expect(ecSignatureHex).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
+ });
+ it('signs a transaction', async () => {
+ const txHex = await ethLightwalletSubprovider.signTransactionAsync(fixtureData.TX_DATA);
+ expect(txHex).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
});
});
});
@@ -98,52 +94,38 @@ describe('EthLightwalletSubprovider', () => {
};
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
expect(err).to.be.a('null');
- expect(response.result.length).to.be.equal(NUM_GENERATED_ADDRESSES);
- expect(response.result[0]).to.be.equal(FAKE_ADDRESS);
+ expect(response.result[0]).to.be.equal(fixtureData.TEST_RPC_ACCOUNT_0);
+ expect(response.result.length).to.be.equal(DEFAULT_NUM_ACCOUNTS);
done();
});
provider.sendAsync(payload, callback);
});
it('signs a personal message hash with eth_sign', (done: DoneCallback) => {
- // Keccak-256 hash of 'hello world'
- const messageHash = '0x47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad';
+ const data = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
+ const account = fixtureData.TEST_RPC_ACCOUNT_0;
const payload = {
jsonrpc: '2.0',
method: 'eth_sign',
- params: ['0x44be42fd88e22387c43ba9b75941aa3e680dae25', messageHash],
+ params: [account, data],
id: 1,
};
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
expect(err).to.be.a('null');
- expect(response.result).to.be.equal(
- // tslint:disable-next-line:max-line-length
- '0xa46b696c1aa8f91dbb33d1a66f6440bf3cf334c9dc45dc389668c1e60e2db31e259400b41f31632fa994837054c5345c88dc455c13931332489029adee6fd24d1b',
- );
+ expect(response.result).to.be.equal(fixtureData.PERSONAL_MESSAGE_SIGNED_RESULT);
done();
});
provider.sendAsync(payload, callback);
});
it('signs a transaction', (done: DoneCallback) => {
- const tx = {
- to: '0xafa3f8684e54059998bc3a7b0d2b0da075154d66',
- value: '0x00',
- gasPrice: '0x00',
- nonce: '0x00',
- gas: '0x00',
- from: '0x44be42fd88e22387c43ba9b75941aa3e680dae25',
- };
const payload = {
jsonrpc: '2.0',
method: 'eth_signTransaction',
- params: [tx],
+ params: [fixtureData.TX_DATA],
id: 1,
};
const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
- const expectedResponseLength = 192;
-
expect(err).to.be.a('null');
- expect(response.result.raw.length).to.be.equal(expectedResponseLength);
- expect(response.result.raw.substr(0, 2)).to.be.equal('0x');
+ expect(response.result.raw).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
done();
});
provider.sendAsync(payload, callback);
@@ -155,7 +137,7 @@ describe('EthLightwalletSubprovider', () => {
const payload = {
jsonrpc: '2.0',
method: 'eth_sign',
- params: ['0x0000000000000000000000000000000000000000', nonHexMessage],
+ params: [fixtureData.TEST_RPC_ACCOUNT_0, nonHexMessage],
id: 1,
};
const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
@@ -170,7 +152,7 @@ describe('EthLightwalletSubprovider', () => {
const payload = {
jsonrpc: '2.0',
method: 'personal_sign',
- params: [nonHexMessage, '0x0000000000000000000000000000000000000000'],
+ params: [nonHexMessage, fixtureData.TEST_RPC_ACCOUNT_0],
id: 1,
};
const callback = reportCallbackErrors(done)((err: Error, _response: JSONRPCResponsePayload) => {
diff --git a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts
index a41ad7790..ab321bcff 100644
--- a/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts
+++ b/packages/subproviders/test/unit/private_key_wallet_subprovider_test.ts
@@ -60,6 +60,20 @@ describe('PrivateKeyWalletSubprovider', () => {
});
provider.sendAsync(payload, callback);
});
+ it('signs a transaction', (done: DoneCallback) => {
+ const payload = {
+ jsonrpc: '2.0',
+ method: 'eth_signTransaction',
+ params: [fixtureData.TX_DATA],
+ id: 1,
+ };
+ const callback = reportCallbackErrors(done)((err: Error, response: JSONRPCResponsePayload) => {
+ expect(err).to.be.a('null');
+ expect(response.result.raw).to.be.equal(fixtureData.TX_DATA_SIGNED_RESULT);
+ done();
+ });
+ provider.sendAsync(payload, callback);
+ });
it('signs a personal message with eth_sign', (done: DoneCallback) => {
const messageHex = ethUtils.bufferToHex(ethUtils.toBuffer(fixtureData.PERSONAL_MESSAGE_STRING));
const payload = {