Skip to content

Conversation

@oneeman
Copy link
Contributor

@oneeman oneeman commented Mar 11, 2021

Description

This PR implements CIP35 as specified at https://github.com/celo-org/celo-proposals/blob/master/CIPs/cip-0035.md.

Summary of changes:

  • Transaction type has a new field EthCompatible to distinguish between normal transactions (with the Celo-only fields) and ethereum-compatible ones (without those fields)
  • When decoding transactions of RLP, it identifies the type based on the number of fields the RLP list has
  • When encoding transactions to RLP, it encodes them to have either 9 or 12 fields depending on the value of EthCompatible
  • When generating or verifying transaction signatures, the signing data used is determined by the value of EthCompatible
  • When serializing to or deserializing from JSON, the EthCompatible field is encoded as ethCompatible.
  • When validating transactions (whether in the tx pool or in the state transition function), reject them if either
    (a) EthCompatible is true but Donut has not been activated,
    (b) EthCompatible is true but they have non-trivial values for any of the Celo-only fields (which can't happen if decoding from RLP, but can if decoding from JSON), or
    (c) Donut has been activated but the transaction doesn't use replay protection (EIP-155)

Other changes

  • Fix an upstream bug in RLP decoding (fixed upstream by rlp: handle case of normal EOF in Stream.readFull() ethereum/go-ethereum#22336)
  • Remove the rlp:nil tag from txdata.GatewayFee. This tag is not respected for *big.Int values, and so its presence was misleading.
  • Point the CI to use the celo-monorepo branch oneeman/cip35-e2e-tests. This was not strictly speaking necessary, since I have a PR on celo-monorepo pointing at this branch, the tests will execute there. Regardless, this change will be reverted to point it back to master

Tested

  • Unit tests for serialization an deserialization of transactions (for both RLP and JSON)
  • e2e tests (see Add e2e tests for CIP35 (eth-compatible transactions) celo-monorepo#7418) which cover combinations of scenarios such as pre-Donut vs post-Donut, eth-compatible vs normal transactions, sending to a full node or a light client, including vs not including Celo-only fields, sending using eth_sendTransaction vs using eth_sendRawTransaction.

Backwards compatibility

  • Transaction and other types like it (e.g. RPCTransaction) have a new field. However, as the zero value for boolean fields is false (which means normal Celo transactions), no changes should be required for software importing celo-blockchain packages as a library.
  • When Donut is activated, a new transaction type will be valid which isn't currently
  • When Donut is activated, transactions without EIP-155 replay protection (i.e. using the chain id) will be rejected. However, all known Celo wallets and all up to date Ethereum wallets use replay protection, so this isn't likely to affect anyone.
  • Before and after Donut, transactions serialized to JSON will have a new boolean field, ethCompatible. This should not break existing software as additional fields are generally ignored during JSON parsing. In particular, contractkit is not affected, as may be seen in the e2e tests.

Or Neeman added 2 commits March 11, 2021 14:16
Big ints are encoded and decoded as RLP scalars, which are not nullable.  The 'nil' tag had no effect, so this commit removes it.
Or Neeman added 4 commits March 12, 2021 11:16
@oneeman oneeman requested a review from mcortesi March 15, 2021 21:24
@oneeman oneeman marked this pull request as ready for review March 15, 2021 21:25
@oneeman oneeman requested review from a team, hbandura and nategraf as code owners March 15, 2021 21:25
Copy link
Contributor

@mcortesi mcortesi left a comment

Choose a reason for hiding this comment

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

Left some comments

tx.data.Payload,
s.chainId, uint(0), uint(0),
})
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

golang lint rules would ask you to remove the else claus and just return

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Turns out we don't have golint (or any drop-in replacement) enabled in our golangci config. If I add it, it gives a ton of errors of different sorts (including some of this rule, e.g. https://github.com/celo-org/celo-blockchain/blob/master/rpc/client.go#L392-L396)

Personally, I am not a fan of this if/else lint rule. I remember when I first used golint I didn't like it and also didn't like that golint doesn't let you disable individual rules. But if you like that rule I can change them.

tx.data.Amount,
tx.data.Payload,
})
} else {
Copy link
Contributor

Choose a reason for hiding this comment

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

same

// Update all fork indicator by next pending block number.
next := new(big.Int).Add(newHead.Number, big.NewInt(1))
pool.istanbul = pool.chainconfig.IsIstanbul(next)
pool.donut = pool.chainconfig.IsDonut(next)
Copy link
Contributor

Choose a reason for hiding this comment

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

do we call validateTx after this is enabled? Or old tx will continue to existt on the txpool?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point! validateTx() is only called when adding a transaction. For later on it only checks a subset of what validateTx() checks, and this should be checked as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added a commit making it so that unprotected transactions are removed when Donut is activated. I still need to add a test for it, though.

Copy link

@nategraf nategraf left a comment

Choose a reason for hiding this comment

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

Gave this a look and didn't have any comments beyond what @mcortesi already added 👍

@oneeman
Copy link
Contributor Author

oneeman commented Mar 18, 2021

Added a test for pool.handleDonutActivation. Ready for final review

Copy link
Contributor

@trianglesphere trianglesphere left a comment

Choose a reason for hiding this comment

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

What's here looks good to me. Looks like there's a tx pool conflict, and the CI branches need to be straightened out, but otherwise everything looks ready.

Conflicts:
	core/types/transaction.go
@oneeman
Copy link
Contributor Author

oneeman commented Mar 22, 2021

What's here looks good to me. Looks like there's a tx pool conflict, and the CI branches need to be straightened out, but otherwise everything looks ready.

Thanks! Merged in master and resolved the conflict.

@oneeman
Copy link
Contributor Author

oneeman commented Mar 22, 2021

Pointed the CI back to monorepo master. This means the new e2e tests won't run, but they will after the corresponding PR on monorepo is merged (I believe this is a chicken-and-egg scenario, but I could be wrong)

@oneeman oneeman merged commit 021d106 into master Mar 23, 2021
@oneeman oneeman deleted the oneeman/cip35 branch March 23, 2021 15:09
mergify bot pushed a commit to celo-org/celo-monorepo that referenced this pull request Mar 23, 2021
### Description

This PR adds e2e tests for CIP35 (support for eth-compatible transactions), to be included in the Donut hard fork.

### Other changes

* Modifies the `GenesisConfig` type to allow `null` values for `churritoBlock` and `donutBlock`, which indicate the forks are not to be activated.  This is necessary because mycelo (used in the new e2e tests) defaults to activating them, so in order to have them not activated we must be able to specify `null` in the config rather than `undefined` (which means no override).
* Sets CI to use the branch `oneeman/cip35` of `celo-blockchain`.  This should be reverted to `master` once that branch has been merged, before merging this PR.  So I added the "do not merge" label to this PR, to ensure it's not merged until that is done.
* Moves the mnemonic used for e2e tests out of the function it was in to be a top-level exported constant.  This lets the e2e tests use the mnemonic directly if they need to (and also allows them to derive the validator's address rather than hard-code it and relying on the mnemonic not having changed).
* Adds support for `verbose: true` when using mycelo to create a genesis file (to not hide mycelo's console output if verbose is true)

### Tested

* e2e tests as part of CI

### Related issues

- PR on celo-blockchain: celo-org/celo-blockchain#1431

### Backwards compatibility

No issues, but will need to point back to `celo-blockchain`'s master before merging.
trianglesphere pushed a commit that referenced this pull request Mar 25, 2021
Starting at the Donut hard-fork activation: (a) adds support for ethereum-compatible transactions as specified in CIP35, (b) make replay protection (using EIP-155) mandatory.

* Remove rlp:"nil" tag from txdata.GatewayFee. Big ints are encoded and decoded as RLP scalars, which are not nullable.  The 'nil' tag had no effect, so this commit removes it.
* rlp: handle case of normal EOF in Stream.readFull()
* Add support for eth-compatible transactions
* Make replay protection mandatory once Donut is activated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants