ethereumjs / ethereumjs-tx

Project is in active development and has been moved to the EthereumJS VM monorepo.
https://github.com/ethereumjs/ethereumjs-vm/tree/master/packages/tx
Mozilla Public License 2.0
779 stars 235 forks source link

A possible simplification of this library #154

Closed alcuadrado closed 4 years ago

alcuadrado commented 5 years ago

I created this draft PR to show one possibility of what can be done in response to what we are discussing in #151.

I based this PR in #149, as doing so makes things easier.

Note that this is just a proof of concept and I haven't updated the tests, nor haven't paid much attention to this refactor's correctness yet.

alcuadrado commented 5 years ago

I kept working on this and made it pass all tests, with the exception of FakeTransaction and its tests.

I copied part of the behavior of the previous implementation to make the tests pass, and I'm now completely puzzled about a few things:

I think this proposal may look good if these two things are figured out.

lgtm-com[bot] commented 5 years ago

This pull request introduces 1 alert when merging 7d16f0133c9405428464b6cd0850c230dec83def into ed4b695869d23bd377a2b5a5a263b776e8e513b4 - view on LGTM.com

new alerts:


Comment posted by LGTM.com

s1na commented 5 years ago

Thanks for pursuing this! I think this is a great start. A few comments:

  1. I overheard in #AllCoreDevs that folks are considering modifying the tx format for the Istanbul hardfork. I'd suggest we wait a bit before committing to a new design.
  2. I liked the static factory methods, and making things like unsigned eip155 message, etc. explicit, and it actually gave me another idea (haven't thought about it in detail): having a tx interface, multiple tx implementations and a factory class which instantiates a tx implementation based on given data. The implementations are something like BaseUnsignedTx, BaseSignedTx, EIP155UnsignedTx, etc. (they can inherit most of logic from eachother). Users shouldn't know which implementation they're interacting with.
  3. I'm myself for immutability, but an argument against it (in the case of this PR) is that fields like this._from and this._senderPubKey act as a cache, avoiding the costly call to getSenderPublicKey and ecrecover, and I know that at least the VM tries to get the sender address multiple times in a row. Although this caching can be pushed to e.g. to VM, I'd be okay with that.
  4. Regarding your questions, I'm not sure myself and would have to investigate. But one way of finding out whether they're consensus rules is to integrate the changes in VM and see if tests start to fail.
alcuadrado commented 5 years ago
  1. I overheard in #AllCoreDevs that folks are considering modifying the tx format for the Istanbul hardfork. I'd suggest we wait a bit before committing to a new design.

Sure. As mentioned in #153, this PR is mostly to discuss possible alternatives. No need to rush it.

  1. I liked the static factory methods, and making things like unsigned eip155 message, etc. explicit, and it actually gave me another idea (haven't thought about it in detail): having a tx interface, multiple tx implementations and a factory class which instantiates a tx implementation based on given data. The implementations are something like BaseUnsignedTx, BaseSignedTx, EIP155UnsignedTx, etc. (they can inherit most of logic from eachother). Users shouldn't know which implementation they're interacting with.

This is possible if we go for a more immutable alternative. Things like tx.sign(pk) can't work this way. This would work const signedTx : Transaction = unsignedTx.sign(pk). (note: The type annotation isn't needed)

TBH I'm not a big fan of classic OOP design, where business logic is encoded in the class hierarchy. My feeling is that it prioritizes code simplicity at the expense of making the big picture harder to see and comprehend. I don't hate it either, and there are places where it makes sense, so I think it's an alternative worth exploring.

  1. I'm myself for immutability, but an argument against it (in the case of this PR) is that fields like this._from and this._senderPubKey act as a cache, avoiding the costly call to getSenderPublicKey and ecrecover, and I know that at least the VM tries to get the sender address multiple times in a row. Although this caching can be pushed to e.g. to VM, I'd be okay with that.

I just removed it temporarily to make things easier. I'm ok with caching things if they are common and slow operations. Without defineProperties it's easier to implement the cache correctly.

  1. Regarding your questions, I'm not sure myself and would have to investigate. But one way of finding out whether they're consensus rules is to integrate the changes in VM and see if tests start to fail.

Section 4.2 of the yellow paper defines this. I barely skimmed it for now. Will read it in detail later.

evertonfraga commented 4 years ago

This repo is moving to a monorepo structure. Please keep any work related to this PR there: https://github.com/ethereumjs/ethereumjs-vm/