Skip to content

Commit

Permalink
use new version of ethereumjs/tx
Browse files Browse the repository at this point in the history
  • Loading branch information
brad-decker committed Jun 14, 2021
1 parent 22c2d26 commit 9876df0
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 26 deletions.
70 changes: 61 additions & 9 deletions app/scripts/controllers/transactions/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import EventEmitter from 'safe-event-emitter';
import { ObservableStore } from '@metamask/obs-store';
import { bufferToHex, keccak, toBuffer } from 'ethereumjs-util';
import Transaction from 'ethereumjs-tx';
import EthQuery from 'ethjs-query';
import { ethErrors } from 'eth-rpc-errors';
import abi from 'human-standard-token-abi';
import Common from '@ethereumjs/common';
import { TransactionFactory } from '@ethereumjs/tx';
import { ethers } from 'ethers';
import NonceTracker from 'nonce-tracker';
import log from 'loglevel';
Expand All @@ -29,6 +30,8 @@ import TxGasUtil from './tx-gas-utils';
import PendingTransactionTracker from './pending-tx-tracker';
import * as txUtils from './lib/util';

const HARDFORK = 'berlin';

const hstInterface = new ethers.utils.Interface(abi);

const MAX_MEMSTORE_TX_LIST_SIZE = 100; // Number of transactions (by unique nonces) to keep in memory
Expand All @@ -53,7 +56,7 @@ const MAX_MEMSTORE_TX_LIST_SIZE = 100; // Number of transactions (by unique nonc
@param {Object} opts.networkStore - an observable store for network number
@param {Object} opts.blockTracker - An instance of eth-blocktracker
@param {Object} opts.provider - A network provider.
@param {Function} opts.signTransaction - function the signs an ethereumjs-tx
@param {Function} opts.signTransaction - function the signs an @ethereumjs/tx
@param {Object} opts.getPermittedAccounts - get accounts that an origin has permissions for
@param {Function} opts.signTransaction - ethTx signer that returns a rawTx
@param {number} [opts.txHistoryLimit] - number *optional* for limiting how many transactions are in state
Expand All @@ -65,6 +68,7 @@ export default class TransactionController extends EventEmitter {
super();
this.networkStore = opts.networkStore || new ObservableStore({});
this._getCurrentChainId = opts.getCurrentChainId;
this.getProviderConfig = opts.getProviderConfig;
this.preferencesStore = opts.preferencesStore || new ObservableStore({});
this.provider = opts.provider;
this.getPermittedAccounts = opts.getPermittedAccounts;
Expand Down Expand Up @@ -146,6 +150,49 @@ export default class TransactionController extends EventEmitter {
return integerChainId;
}

/**
* @ethereumjs/tx uses @ethereumjs/common as a configuration tool for
* specifying which chain, network, hardfork and EIPs to support for
* a transaction. By referencing this configuration, and analyzing the fields
* specified in txParams, @ethereumjs/tx is able to determine which EIP-2718
* transaction type to use.
* @returns {Common} common configuration object
*/
getCommonConfiguration() {
// type will be one of our default network names or 'rpc'. the default
// network names are sufficient configuration, simply pass the name as the
// chain argument in the constructor.
const { type, nickname } = this.getProviderConfig();

if (type === 'rpc') {
// For 'rpc' we need to use the same basic configuration as mainnet,
// since we only support EVM compatible chains, and then override the
// name, chainId and networkId properties. This is done using the
// `forCustomChain` static method on the Common class.
const chainId = this._getCurrentChainId();
const networkId = this.networkStore.getState();

const customChainParams = {
name: nickname,
chainId: parseInt(chainId, 16),
// It is improbable for a transaction to be signed while the network
// is loading for two reasons.
// 1. Pending, unconfirmed transactions are wiped on network change
// 2. The UI is unusable (loading indicator) when network is loading.
// seeing the networkId to 0 is for type safety and to explicity lead
// the transaction to failing if a user is able to get to this branch
// on a custom network that requires valid network id. I have not ran
// into this limitation on any network I have attempted, even when
// hardcoding networkId to 'loading'.
networkId: networkId === 'loading' ? 0 : parseInt(networkId, 10),
};

return Common.forCustomChain('mainnet', customChainParams, HARDFORK);
}

return new Common({ chain: type, hardfork: HARDFORK });
}

/**
Adds a tx to the txlist
@emits ${txMeta.id}:unapproved
Expand Down Expand Up @@ -561,17 +608,22 @@ export default class TransactionController extends EventEmitter {
const txMeta = this.txStateManager.getTransaction(txId);
// add network/chain id
const chainId = this.getChainId();
const txParams = { ...txMeta.txParams, chainId };
const txParams = {
...txMeta.txParams,
chainId,
gasLimit: txMeta.txParams.gas,
};
// sign tx
const fromAddress = txParams.from;
const ethTx = new Transaction(txParams);
await this.signEthTx(ethTx, fromAddress);
const common = this.getCommonConfiguration();
const unsignedEthTx = TransactionFactory.fromTxData(txParams, { common });
const signedEthTx = await this.signEthTx(unsignedEthTx, fromAddress);

// add r,s,v values for provider request purposes see createMetamaskMiddleware
// and JSON rpc standard for further explanation
txMeta.r = bufferToHex(ethTx.r);
txMeta.s = bufferToHex(ethTx.s);
txMeta.v = bufferToHex(ethTx.v);
txMeta.r = signedEthTx.r.toString(16);
txMeta.s = signedEthTx.s.toString(16);
txMeta.v = signedEthTx.v.toString(16);

this.txStateManager.updateTransaction(
txMeta,
Expand All @@ -580,7 +632,7 @@ export default class TransactionController extends EventEmitter {

// set state to signed
this.txStateManager.setTxStatusSigned(txMeta.id);
const rawTx = bufferToHex(ethTx.serialize());
const rawTx = bufferToHex(signedEthTx.serialize());
return rawTx;
}

Expand Down
14 changes: 9 additions & 5 deletions app/scripts/controllers/transactions/index.test.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { strict as assert } from 'assert';
import EventEmitter from 'events';
import { toBuffer } from 'ethereumjs-util';
import EthTx from 'ethereumjs-tx';
import { TransactionFactory } from '@ethereumjs/tx';
import { ObservableStore } from '@metamask/obs-store';
import sinon from 'sinon';

Expand All @@ -20,6 +20,9 @@ import TransactionController from '.';
const noop = () => true;
const currentNetworkId = '42';
const currentChainId = '0x2a';
const providerConfig = {
type: 'kovan',
};

const VALID_ADDRESS = '0x0000000000000000000000000000000000000000';
const VALID_ADDRESS_TWO = '0x0000000000000000000000000000000000000001';
Expand All @@ -36,6 +39,7 @@ describe('Transaction Controller', function () {
};
provider = createTestProviderTools({ scaffold: providerResultStub })
.provider;

fromAccount = getTestAccounts()[0];
const blockTrackerStub = new EventEmitter();
blockTrackerStub.getCurrentBlock = noop;
Expand All @@ -50,9 +54,9 @@ describe('Transaction Controller', function () {
blockTracker: blockTrackerStub,
signTransaction: (ethTx) =>
new Promise((resolve) => {
ethTx.sign(fromAccount.key);
resolve();
resolve(ethTx.sign(fromAccount.key));
}),
getProviderConfig: () => providerConfig,
getPermittedAccounts: () => undefined,
getCurrentChainId: () => currentChainId,
getParticipateInMetrics: () => false,
Expand Down Expand Up @@ -519,8 +523,8 @@ describe('Transaction Controller', function () {
noop,
);
const rawTx = await txController.signTransaction('1');
const ethTx = new EthTx(toBuffer(rawTx));
assert.equal(ethTx.getChainId(), 42);
const ethTx = TransactionFactory.fromSerializedData(toBuffer(rawTx));
assert.equal(ethTx.common.chainIdBN().toNumber(), 42);
});
});

Expand Down
13 changes: 10 additions & 3 deletions app/scripts/controllers/transactions/tx-gas-utils.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { strict as assert } from 'assert';
import Transaction from 'ethereumjs-tx';
import { TransactionFactory } from '@ethereumjs/tx';
import Common from '@ethereumjs/common';
import { hexToBn, bnToHex } from '../../lib/util';
import TxUtils from './tx-gas-utils';

Expand Down Expand Up @@ -31,8 +32,14 @@ describe('txUtils', function () {
nonce: '0x3',
chainId: 42,
};
const ethTx = new Transaction(txParams);
assert.equal(ethTx.getChainId(), 42, 'chainId is set from tx params');
const ethTx = TransactionFactory.fromTxData(txParams, {
common: new Common({ chain: 'kovan' }),
});
assert.equal(
ethTx.common.chainIdBN().toNumber(),
42,
'chainId is set from tx params',
);
});
});

Expand Down
3 changes: 3 additions & 0 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,9 @@ export default class MetamaskController extends EventEmitter {
getPermittedAccounts: this.permissionsController.getAccounts.bind(
this.permissionsController,
),
getProviderConfig: this.networkController.getProviderConfig.bind(
this.networkController,
),
networkStore: this.networkController.networkStore,
getCurrentChainId: this.networkController.getCurrentChainId.bind(
this.networkController,
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@
"3box": "^1.10.2",
"@babel/runtime": "^7.5.5",
"@download/blockies": "^1.0.3",
"@ethereumjs/common": "^2.3.1",
"@ethereumjs/tx": "^3.2.1",
"@formatjs/intl-relativetimeformat": "^5.2.6",
"@fortawesome/fontawesome-free": "^5.13.0",
"@lavamoat/preinstall-always-fail": "^1.0.0",
Expand Down Expand Up @@ -137,7 +139,6 @@
"eth-trezor-keyring": "^0.6.0",
"ethereum-ens-network-map": "^1.0.2",
"ethereumjs-abi": "^0.6.4",
"ethereumjs-tx": "1.3.7",
"ethereumjs-util": "^7.0.10",
"ethereumjs-wallet": "^0.6.4",
"ethers": "^5.0.8",
Expand Down
50 changes: 42 additions & 8 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1521,6 +1521,22 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"

"@ethereumjs/common@^2.3.1":
version "2.3.1"
resolved "https://registry.yarnpkg.com/@ethereumjs/common/-/common-2.3.1.tgz#d692e3aff5adb35dd587dd1e6caab69e0ed2fa0b"
integrity sha512-V8hrULExoq0H4HFs3cCmdRGbgmipmlNzak6Xg34nHYfQyqkSdrCuflvYjyWmsNpI8GtrcZhzifAbgX/1C1Cjwg==
dependencies:
crc-32 "^1.2.0"
ethereumjs-util "^7.0.10"

"@ethereumjs/tx@^3.2.1":
version "3.2.1"
resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-3.2.1.tgz#65f5f1c11541764f08377a94ba4b0dcbbd67739e"
integrity sha512-i9V39OtKvwWos1uVNZxdVhd7zFOyzFLjgt69CoiOY0EmXugS0HjO3uxpLBSglDKFMRriuGqw6ddKEv+RP1UNEw==
dependencies:
"@ethereumjs/common" "^2.3.1"
ethereumjs-util "^7.0.10"

"@ethersproject/abi@5.0.0-beta.153":
version "5.0.0-beta.153"
resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.0.0-beta.153.tgz#43a37172b33794e4562999f6e2d555b7599a8eee"
Expand Down Expand Up @@ -8358,6 +8374,14 @@ cpy@^8.1.1:
p-filter "^2.1.0"
p-map "^3.0.0"

crc-32@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.0.tgz#cb2db6e29b88508e32d9dd0ec1693e7b41a18208"
integrity sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==
dependencies:
exit-on-epipe "~1.0.1"
printj "~1.1.0"

crdts@~0.1.2:
version "0.1.5"
resolved "https://registry.yarnpkg.com/crdts/-/crdts-0.1.5.tgz#89413e8adfc3ab943300a890ee6392db5ba60c06"
Expand Down Expand Up @@ -10874,14 +10898,6 @@ ethereumjs-common@^1.1.0, ethereumjs-common@^1.3.2, ethereumjs-common@^1.5.0:
resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-1.5.1.tgz#4e75042473a64daec0ed9fe84323dd9576aa5dba"
integrity sha512-aVUPRLgmXORGXXEVkFYgPhr9TGtpBY2tGhZ9Uh0A3lIUzUDr1x6kQx33SbjPUkLkX3eniPQnIL/2psjkjrOfcQ==

ethereumjs-tx@1.3.7, ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3, ethereumjs-tx@^1.3.4, ethereumjs-tx@^1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a"
integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==
dependencies:
ethereum-common "^0.0.18"
ethereumjs-util "^5.0.0"

ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-2.1.2.tgz#5dfe7688bf177b45c9a23f86cf9104d47ea35fed"
Expand All @@ -10890,6 +10906,14 @@ ethereumjs-tx@2.1.2, ethereumjs-tx@^2.1.1, ethereumjs-tx@^2.1.2:
ethereumjs-common "^1.5.0"
ethereumjs-util "^6.0.0"

ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3, ethereumjs-tx@^1.3.4, ethereumjs-tx@^1.3.7:
version "1.3.7"
resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a"
integrity sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==
dependencies:
ethereum-common "^0.0.18"
ethereumjs-util "^5.0.0"

ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0:
version "6.2.1"
resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69"
Expand Down Expand Up @@ -11393,6 +11417,11 @@ exit-hook@^1.0.0:
resolved "https://registry.yarnpkg.com/exit-hook/-/exit-hook-1.1.1.tgz#f05ca233b48c05d54fff07765df8507e95c02ff8"
integrity sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=

exit-on-epipe@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz#0bdd92e87d5285d267daa8171d0eb06159689692"
integrity sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==

exit@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c"
Expand Down Expand Up @@ -21012,6 +21041,11 @@ pretty-hrtime@^1.0.0, pretty-hrtime@^1.0.3:
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
integrity sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=

printj@~1.1.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/printj/-/printj-1.1.2.tgz#d90deb2975a8b9f600fb3a1c94e3f4c53c78a222"
integrity sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==

priorityqueue@~0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/priorityqueue/-/priorityqueue-0.2.1.tgz#f57e623f20237f30c142d4cb45fafed9e7d51403"
Expand Down

0 comments on commit 9876df0

Please sign in to comment.