Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

utils.serializeTransaction ignores “chain ID” part of “v” #708

Closed
3sGgpQ8H opened this issue Jan 20, 2020 · 6 comments
Closed

utils.serializeTransaction ignores “chain ID” part of “v” #708

3sGgpQ8H opened this issue Jan 20, 2020 · 6 comments
Labels
enhancement New feature or improvement.

Comments

@3sGgpQ8H
Copy link

3sGgpQ8H commented Jan 20, 2020

When utils.serializeTransaction(tx, sig) is used to serialize signed transaction, the function could distort sig.v value passed: strip “chain ID” part from passed sig.v value and replace it with value derived from passed “tx.chainIdparameter. This is counter-intuitive and error prone. Moreover, this logic is applied even iftxdoes not havechainId` field at all (the function serialized pre EIP-155 transaction in such case).

In my opinion, once sig.v value is explicitly provided by the user, this value should go into serialized transaction as is. If this value does not match with tx.chainId value, explicitly provided, then exception should be thrown. There should be some way to clearly distinguish situations when chain ID is not provided by the user from other situations, when user explicitly provided that he wants to serialized pre EIP-155 transaction with no chain ID.

With current implementation, if one has all nine parts of a signed transaction and wants to serialize this transaction, he has to manually calculate chain ID from v and pass ten parameters to utils.serializeTransaction(tx, sig), otherwise his v value will most probably be distorted (replaced with 27 or 28, effectively stripping chain ID information).

@ricmoo
Copy link
Member

ricmoo commented Jan 20, 2020

I think this makes sense for the most part, I’ll think about it more and look into it tomorrow for v5. It is true that of chainId and v disagree, there should be an error.

For the signature, there should be no need to compute the v manually though, since you can just ensure recoveryParam is correct and it will determine the v for you. Or it should at least. I’ll build out a larger suite of tests tomorrow to follow the various allowed combinations. I added a bunch of tests recently to v5 to make sure the splitSignature could recreate a full signature from valid fragments (e.g. defining vs should be able to reconstruct v, s and recoveryParam). But it looks like the chainId is in fact ignored when serializing.

@ricmoo ricmoo added the discussion Questions, feedback and general information. label Jan 20, 2020
@ricmoo ricmoo added enhancement New feature or improvement. on-deck This Enhancement or Bug is currently being worked on. and removed discussion Questions, feedback and general information. labels Feb 2, 2020
@ricmoo
Copy link
Member

ricmoo commented Feb 4, 2020

The logic I'm thinking right now:

  • If there is no chainId in the transaction, but the signature has a v which is over 28, then it will be serialized as EIP-155 with the computed chainId.
  • If there is any mismatch between the transaction.chainId and signature, the world ends and an exception is thrown.

Does that seem ifair?

@3sGgpQ8H
Copy link
Author

3sGgpQ8H commented Feb 5, 2020

  • If there is no chainId in the transaction, but the signature has a v which is over 28, then it will be serialized as EIP-155 with the computed chainId.

Absence of chainId in transaction may mean either that user does not want to pass chain ID separately as it is already encoded into v, or that user explicitly wants to encode pre EIP-155 transaction. In the former case proposed behavior is OK, while in the latter case an exception should be thrown. I suggest to treat undefined chainId as “unspecified”, and false/null/"" chainId as explicit pre EIP-155 intention.

  • If there is any mismatch between the transaction.chainId and signature, the world ends and an exception is thrown.

This sounds fine.

@ricmoo
Copy link
Member

ricmoo commented Feb 6, 2020

Hmmm... I don't really like undefined and null having different meanings. I do it sometimes, but very rarely, and usually in contained/internal ways...

I think it is ok that if chainId is unspecified and the siguature uses a canonical v, that no EIP-155 is expected, but if chainId or non-canonical v is specified to use EIP-155, no?

If a chainId of 0 is provided, then non-EIP-155 is forced and a v mismatch will throw.

Basically, I never want to "guess" what is intended, but I do want to make sure a person can be as expressive as desired and to have sane defaults.

Did you check out the changes? :)

@3sGgpQ8H
Copy link
Author

3sGgpQ8H commented Feb 7, 2020

When I wrote false/null/"" I didn't mean that all these value should mean the same. I meant that there should be special value for chainId to explicitly specify that the user wants to encode pre EIP-155 transaction, and this value should differ from "unspecified" chain ID. Is zero is not a valid chain ID in terms of EIP-155, then zero is probably the best choice for such value.

@ricmoo ricmoo removed the on-deck This Enhancement or Bug is currently being worked on. label Mar 13, 2020
@ricmoo
Copy link
Member

ricmoo commented Mar 13, 2020

I think the new incarnation of serializeTransaction addresses the concerns, so I'm going to close this, but if you disagree, please feel free to re-open.

Thanks! :)

@ricmoo ricmoo closed this as completed Mar 13, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or improvement.
Projects
None yet
Development

No branches or pull requests

2 participants