Skip to content
This repository has been archived by the owner on Oct 28, 2021. It is now read-only.

Refactor transaction replay protection implementation #5742

Merged
merged 5 commits into from
Sep 25, 2019
Merged

Conversation

gumb0
Copy link
Member

@gumb0 gumb0 commented Sep 11, 2019

I got rid of the magic value -4 which was used to represent transactions without replay protection (-4 was used because inserting it into formulas CHAIN_ID * 2 + 35 / CHAIN_ID * 2 + 35 conveniently produced valid values 27 / 28 for transactions without replay protection)
Instead of this I represent chainID with optional<uint64_t>

For reference replay protection spec is in https://eips.ethereum.org/EIPS/eip-155

This is quite independent of the change to 64 bit in EVMC and CHAINID implementation #5740 (works and passes the tests without it), but I'd merge this after the Chain ID size decision is finalized.

@gumb0 gumb0 force-pushed the refactor-chainid branch 3 times, most recently from e3c8950 to b2560a0 Compare September 16, 2019 15:36
@codecov-io
Copy link

codecov-io commented Sep 16, 2019

Codecov Report

Merging #5742 into master will increase coverage by <.01%.
The diff coverage is 95.83%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #5742      +/-   ##
==========================================
+ Coverage   63.71%   63.71%   +<.01%     
==========================================
  Files         357      356       -1     
  Lines       30502    30517      +15     
  Branches     3392     3392              
==========================================
+ Hits        19434    19444      +10     
- Misses       9841     9845       +4     
- Partials     1227     1228       +1

BOOST_THROW_EXCEPTION(InvalidSignature());

m_vrs = SignatureStruct{r, s, static_cast<byte>(v - (m_chainId * 2 + 35))};
auto const recoveryID =
m_chainId.has_value() ? byte{v - (*m_chainId * 2 + 35)} : byte{v - 27};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This silently truncates a uint256 to byte.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added a check above to cap m_chainId at 64 bit. Given how chainID is calculated there, expression here inside byte{...} can only be either 0 or 1

auto const chainId = (v - 35) / 2;
if (chainId > std::numeric_limits<uint64_t>::max())
BOOST_THROW_EXCEPTION(InvalidSignature());
m_chainId = static_cast<byte>(chainId);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why casted to byte?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh should be unit64_t, sorry

int m_chainId = -4; ///< EIP155 value for calculating transaction hash https://github.com/ethereum/EIPs/issues/155
/// EIP155 value for calculating transaction hash
/// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md
boost::optional<uint64_t> m_chainId;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use std::optional now that we can build C++17 on Windows? Or should we just convert all boost::optional to std::optional in one go at some point in the future?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We still build with C++11 standard at the moment (it should be a separate PR when we want to switch; I'm not sure whether AppVeyor supports it)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be fine in VS 2017.

@@ -41,19 +41,48 @@ BOOST_AUTO_TEST_CASE(TransactionGasRequired)

BOOST_AUTO_TEST_CASE(TransactionWithEmptyRecepient)
{
// recipient RLP is 0x80 (empty array)
// recepient RLP is 0x80 (empty array)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Nit) The old spelling is the correct one? https://www.merriam-webster.com/dictionary/recipient

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh thanks, my mistake

@gumb0
Copy link
Member Author

gumb0 commented Sep 18, 2019

@fubuloubu The test vectors here might be useful in case you plan to submit a separate proposal to fix the size of ChainID to 64 bit in EIP-155 signing rules
48a46c1#diff-fb674f25a4fbb780be5f264a0c9a9d76R71-R105

(I wanted to create reference Transaction tests out of them, but it doesn't look possible with current test format)

@fubuloubu
Copy link

Thanks!

It's looking clear that the restriction to uint64 might not be implemented for Istanbul (preferring EIP-155's potentially unlimited size for chain ID), so it is good that this is separated out.

@chfast
Copy link
Member

chfast commented Sep 24, 2019

Merge?

@gumb0
Copy link
Member Author

gumb0 commented Sep 25, 2019

Yeah I think it's safe to merge this regardless of the decisions around chain ID width

@gumb0 gumb0 merged commit c084e6b into master Sep 25, 2019
@gumb0 gumb0 deleted the refactor-chainid branch September 25, 2019 09:45
dimalit added a commit to skalenetwork/skaled that referenced this pull request Nov 13, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants