Closed danjm closed 5 years ago
@holgerd77 This might be ready to go, depending on whether we want to resolve the following:
This implemenation of transactionRunner.js
will flag the transactions this._homestead
property as false when running the hardfork tests other than "Homestead". However, there is some behaviour of ethereumjs-tx
that should hold true for Homestead and all future hard forks.
For instance, that All transaction signatures whose s-value is greater than secp256k1n/2 are considered invalid
has been true since Homestead. In our codebase, this condition only invalidates a tx if this._homestead
is true. As such, tests for other hardforks that expect invalidity due to violation of this condition will not currently pass.
To see an example of this, run npm run test:node -- -t --file=TransactionWithHighGas | tap-spec
this._homestead
defaults to true. Is it assumed that it will only be set to false if ethereumjs-tx
is being used prior to the Homestead hardfork?
If not, we need to explicitly handle these other forks in some way.
Hi Dan, thanks for the update! This whole this._homestead
thing is totally legacy and should be replaced. Can you cross-coordinate with this https://github.com/ethereumjs/ethereumjs-tx/pull/130 PR currently in progress? I think this would be a perfect match. We should optimally make sure that all hardfork specific logic is supported, or minimally then explicitly limit (using the common library) to that set of hardforks that ARE supported.
Would probably be optimal to have this PR merged and then work here on top of the hardfork and chain integration work.
I put "blocked" in the title as the latest commit makes this PR dependent on #130
Once that is merged, I will rebase here
@holgerd77 This is ready for final review and merge. I'll confirm tomorrow, but the latest changes likely make https://github.com/ethereumjs/ethereumjs-tx/pull/132 redundant.
Great! 👍
Also: can you still confirm regarding #132?
@holgerd77 I've closed #132, this PR covers the important pieces of it
In addition to the above changes, I am going to give myself one more task before I merge:
Oops, my latest update broke the build. I will fix it.
Sounds good, let me know once this is ready for re-review!
What's the status of this?
~@holgerd77 This is now complete, but there is a caveat that may mean another change is necessary: this PR have introduces three breaking changes with regards to how this._chaindId
is set.~
Previously chainId
was calculated this way:
// calculate chainId from signature
let sigV = ethUtil.bufferToInt(this.v)
let chainId = Math.floor((sigV - 35) / 2)
if (chainId < 0) chainId = 0
// set chainId
this._chainId = chainId || data.chainId || 0
~After this PR it is just: this._chainId = this._common.chainId()
(where this._common.chainId() depends on passed opts.chain
params)~
~So, the caller is explicitly required to set the opts.chain
property if they want the chainId to be something other than the default associated with mainnet (i.e. 1
).~
~This means two breaking changes:
(1) this._chainId
will no longer be calculated from the v
value included in the data
param passed to the constructor.
(2) a specific chain id cannot be included in the data
param passed to the constructor
(3) The chainId
will now default to 1
instead of 0
if no other info is specified~
~This is in line with this comment https://github.com/ethereumjs/ethereumjs-tx/pull/131#discussion_r262700210, but goes a step further to include the removal of calculation of chainId from v and the defaulting to 0 (which seems to be more aligned with the specification https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md#specification)~
@holgerd77 I have revised this PR so that my previous comment is no longer true: there are no longer breaking changes.
Instead, this PR updates the codebase to support the new way of setting chainId and the legacy approach:
if (opts.chain || opts.common) {
this._chainId = this._common.chainId()
} else {
this._chainId = chainId || data.chainId || 0
}
Developers that us opts.chain or opts.common will be able to explicitly set chainId to a value of their choice. Developers that do not set it will have it set by default according to the existing rules:
// calculate chainId from signature
let sigV = ethUtil.bufferToInt(this.v)
let chainId = Math.floor((sigV - 35) / 2)
if (chainId < 0) chainId = 0
I've decided to leave support for the use of data.chainId
(despite your comment) as I think it would be better to give notice of the deprecation before breaking the functionality. Of course, if you think it is okay given this will be a major version upgrade, then it is easy to remove this entirely.
Meanwhile, this PR includes an update to run all transaction tests on mainnet, which seems to be an assumption baked into those tests.
Also not that https://github.com/ethereumjs/ethereumjs-tx/pull/143 is based off this PR. Among other things, it addresses an outstanding issue with this PR.
I believe this PR is now complete and ready to merge, notwithstanding the a possible decision on the removal of data.chainId
from the constructor, as described above.
Trusting your choices here, will try to do a short-term final review. I am thinking a bit if you guys want to completely take over responsibility for the continued work and directly do cross-reviews with e.g. @chikeichan and eventually new contributors from Nomic, I think you are understanding this library at least as good as me anyhow. And I would rather watch from the sideline and try to make sure it fits into overall strategy, modernization efforts and technical guidelines.
So Jacky e.g., if you want to do a review on this and then merge, feel free (but generally: please take reviews seriously, you can very well take 1-2 hours for this and also put this in the timesheet, this is as important as the work itself).
Best Holger
Or @s1na could eventually also do a review on this
I reviewed this PR today, and it looks good. Note that this is my first review here, so I may be missing something. I didn't make any comment on style either, as I'm still getting used to the ethereumjs's standards.
The only thing that raised my attention is that after this PR the function hash
doesn't include the _chainId
info when being used to sign new transactions. I don't know if this is intentional, as there's #143, but I haven't seen it yet. I belive this may be a bug, as sign
is encoding the v
like EIP155 dictates anyway.
I created this test which can be added to test/api.js
as an example of the issue raised in the previous paragraph. It is failing in this branch and passing in master.
t.test('EIP155 hashing when singing', function (st) {
txFixtures.slice(0, 3).forEach(function (txData) {
const tx = new Transaction(txData.raw.slice(0, 6), {chain: 1})
var privKey = new Buffer(txData.privateKey, 'hex')
tx.sign(privKey)
st.equal(
tx.getSenderAddress().toString("hex"),
txData.sendersAddress,
'computed sender address should equal the fixture\'s one'
)
});
st.end()
})
reviewed coding style and structure - LGTM! I also agree with the decision to not introduce breaking changes without a waring period.
And thanks for the detailed review @alcuadrado - @danjm can you please take a look at the hash
function tests @alcuadrado added?
Great catch @alcuadrado. That bug has been addressed on https://github.com/ethereumjs/ethereumjs-tx/pull/143
I just pushed the test you wrote to that branch. It passed for me locally.
Ok, will now merge here myself so that we can move on on top of the work here.
Opening this PR instead of https://github.com/ethereumjs/ethereumjs-tx/pull/126 as this branch is in the main repo.
fixes #115
Updates the transactionRunner.js tests as per the changes and instructions described here: ethereum/tests#373
Each test is run for each of the hardforks. If the
tx
is defined but has an invalid signature after creation, the test passes if the test data for the given hardfork is empty. If thetx
is undefined after creation, the test passes if the test data for the given hardfork is empty. If thetx
has a sender and hash that matches that in the test data for the given hard fork, the test passes.This PR also adds the ability to run a single test by passing an exact filename match. For example:
npm run test:node -- -t --file=TransactionWithHighGas | tap-spec