diff --git a/fake.js b/fake.js index f8893dd..655ca5c 100644 --- a/fake.js +++ b/fake.js @@ -32,8 +32,8 @@ const ethUtil = require('ethereumjs-util') * @prop {Buffer} s EC signature parameter */ module.exports = class FakeTransaction extends Transaction { - constructor (data) { - super(data) + constructor (data, opts) { + super(data, opts) var self = this diff --git a/index.js b/index.js index 6e76d65..4be629c 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ 'use strict' const ethUtil = require('ethereumjs-util') -const fees = require('ethereum-common/params.json') +const Common = require('ethereumjs-common') const BN = ethUtil.BN // secp256k1n/2 @@ -41,10 +41,29 @@ const N_DIV_2 = new BN('7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46 * @param {Buffer} data.r EC signature parameter * @param {Buffer} data.s EC signature parameter * @param {Number} data.chainId EIP 155 chainId - mainnet: 1, ropsten: 3 + * + * @param {Array} opts Options + * @param {String|Number} opts.chain The chain for the block [default: 'mainnet'] + * @param {String} opts.hardfork Hardfork for the block [default: null, block number-based behaviour] + * @param {Object} opts.common Alternatively pass a Common instance (ethereumjs-common) instead of setting chain/hardfork directly * */ class Transaction { - constructor (data) { + constructor (data, opts) { + opts = opts || {} + + // instantiate Common class instance based on passed options + if (opts.common) { + if (opts.chain) { + throw new Error('Instantiation with both opts.common and opts.chain parameter not allowed!') + } + this._common = opts.common + } else { + let chain = opts.chain ? opts.chain : 'mainnet' + let hardfork = opts.hardfork ? opts.hardfork : 'byzantium' + this._common = new Common(chain, hardfork) + } + data = data || {} // Define Properties const fields = [{ @@ -133,7 +152,6 @@ class Transaction { // set chainId this._chainId = chainId || data.chainId || 0 - this._homestead = true } /** @@ -216,7 +234,7 @@ class Transaction { verifySignature () { const msgHash = this.hash(false) // All transaction signatures whose s-value is greater than secp256k1n/2 are considered invalid. - if (this._homestead && new BN(this.s).cmp(N_DIV_2) === 1) { + if (this._common.gteHardfork('homestead') && new BN(this.s).cmp(N_DIV_2) === 1) { return false } @@ -254,7 +272,9 @@ class Transaction { const data = this.raw[5] const cost = new BN(0) for (let i = 0; i < data.length; i++) { - data[i] === 0 ? cost.iaddn(fees.txDataZeroGas.v) : cost.iaddn(fees.txDataNonZeroGas.v) + data[i] === 0 + ? cost.iaddn(this._common.param('gasPrices', 'txDataZero')) + : cost.iaddn(this._common.param('gasPrices', 'txDataNonZero')) } return cost } @@ -264,9 +284,9 @@ class Transaction { * @return {BN} */ getBaseFee () { - const fee = this.getDataFee().iaddn(fees.txGas.v) - if (this._homestead && this.toCreationAddress()) { - fee.iaddn(fees.txCreation.v) + const fee = this.getDataFee().iaddn(this._common.param('gasPrices', 'tx')) + if (this._common.gteHardfork('homestead') && this.toCreationAddress()) { + fee.iaddn(this._common.param('gasPrices', 'txCreation')) } return fee } diff --git a/package.json b/package.json index 71c8912..0b81722 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "author": "mjbecze ", "license": "MPL-2.0", "dependencies": { - "ethereum-common": "^0.0.18", + "ethereumjs-common": "^0.6.1", "ethereumjs-util": "^5.0.0" }, "devDependencies": { diff --git a/test/fake.js b/test/fake.js index a8978aa..c9acc15 100644 --- a/test/fake.js +++ b/test/fake.js @@ -1,5 +1,6 @@ const tape = require('tape') const utils = require('ethereumjs-util') +const Common = require('ethereumjs-common') const FakeTransaction = require('../fake.js') // Use private key 0x0000000000000000000000000000000000000000000000000000000000000001 as 'from' Account @@ -61,4 +62,16 @@ tape('[FakeTransaction]: Basic functions', function (t) { var tx = new FakeTransaction(txDataNoFrom) st.equal(utils.bufferToHex(tx.from), txData.from) }) + + t.test('should throw if common and chain options are passed to constructor', function (st) { + var txData = Object.assign({}, txData) + var txOptsInvalid = { + chain: 'mainnet', + common: new Common('mainnet', 'chainstart') + } + st.plan(1) + st.throws( + () => new FakeTransaction(txData, txOptsInvalid) + ) + }) }) diff --git a/test/transactionRunner.js b/test/transactionRunner.js index c85f7d4..c16f90f 100644 --- a/test/transactionRunner.js +++ b/test/transactionRunner.js @@ -1,9 +1,9 @@ const Tx = require('../index.js') const tape = require('tape') const ethUtil = require('ethereumjs-util') +const Common = require('ethereumjs-common') const argv = require('minimist')(process.argv.slice(2)) const testing = require('ethereumjs-testing') -const common = require('ethereum-common/params.json') var txTests = testing.getTests('transaction', argv) @@ -32,10 +32,9 @@ testing.runTests(function (testData, sst, cb) { try { var rawTx = ethUtil.toBuffer(testData.rlp) - var tx = new Tx(rawTx) - if (testData.blocknumber !== String(common.homeSteadForkNumber.v)) { - tx._homestead = false - } + var tx = new Tx(rawTx, { + hardfork: testData.blockNumber >= 1150000 ? 'homestead' : 'chainstart' + }) } catch (e) { sst.equal(undefined, tTx, 'should not have any fields ') cb() @@ -44,6 +43,7 @@ testing.runTests(function (testData, sst, cb) { if (tTx && tx.validate()) { try { + sst.equal(tx._common instanceof Common, true, '_common class attribute') sst.equal(bufferToHex(tx.data), addHexPrefix(addPad(stripHexPrefix(tTx.data))), 'data') sst.equal(normalizeZero(bufferToHex(tx.gasLimit)), tTx.gasLimit, 'gasLimit') sst.equal(normalizeZero(bufferToHex(tx.gasPrice)), tTx.gasPrice, 'gasPrice')