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

Support for custom genesis via EIP1085 #1299

Merged
merged 6 commits into from
Nov 22, 2018

Conversation

pipermerriam
Copy link
Member

@pipermerriam pipermerriam commented Sep 17, 2018

Continuation of #1247

fixes #722

What was wrong?

Trinity should be able to run custom chains beyond just mainnet and ropsten.

How was it fixed?

Now mainnet and ropsten are done in the same way that a custom chain would be, via an EIP1085 genesis file. There is now a new cli option --genesis which can be used to specify either the raw JSON string or a filesystem path to a JSON document.

Cute Animal Picture

put a cute animal picture link inside the parentheses

@pipermerriam
Copy link
Member Author

Don't bother looking at this. It's piling up into 3-4 separate PRs that need to be untangled.

@voith
Copy link
Contributor

voith commented Sep 28, 2018

@pipermerriam from what I read, EIP1085 doesn't seem to be finalised.
Do you have any timeline for this PR to land. And even if it lands do you think the spec will remian unchanged? I'm asking because I'd like to integrate this into eth-teser as part of ethereum/eth-tester#129.

@pipermerriam
Copy link
Member Author

@voith no idea on either (this PR or finalization of spec). I don't think that should block you however from moving forward with using it in eth-tester. Make sure the API is marked in some way as experimental and subject to breaking changes.

"pattern": "^0x([0-9a-fA-F]{2})+$"
},
"chainId": {
"title": "The chain ID",
Copy link
Contributor

Choose a reason for hiding this comment

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

"The EIP 155 chain ID" :) -- since everyone confuses the two.

}
},
"Accounts": {
"title": "Genesis block parameters",
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor: looks like copy-paste left-over, here and below, in Account.

@pipermerriam
Copy link
Member Author

Latest and greatest is pretty nice in some ways. It completely eliminates trinity.chains.mainnet and trinity.nodes.mainnet, making all chains completely generic (no special cased classes for mainnet/ropsten).

However, in doing this, we end up with errors when calls to chain.get_vm_configuration() happen because the dynamic chain classes aren't pickleable.

My current plan to remedy this is to make heavier use of the TrinityConfig object since it responsible for constructing the dynamic Chain classes, and to change some APIs to instead rely on getting the vm_configuration from that object (which is pickleable).

@pipermerriam pipermerriam force-pushed the piper/custom-genesis branch 2 times, most recently from 3e06920 to 4397e2b Compare October 18, 2018 18:40
@pipermerriam
Copy link
Member Author

pipermerriam commented Oct 18, 2018

More updates on this:

@carver and @cburgdorf

This is now yielding some interesting and fundamental flaws with how we currently do multiprocess communication, but I think it's a good thing. The concise issue is that with the introduction of custom genesis configurations, we end up with un-pickleable VM classes since they must be dynamically constructed based on the genesis configuration (this is primaily due to the dao fork, but even without this we'd have the same problem with POA networks since we'll have to inject the proper consensus engine).

That means all of Chain.get_vm_configuration(), Chain.get_vm, Chain.get_vm_class_for_block_number and probably a number of others can no longer be called across the multiprocessing boundary. I think the proper way to fix this is to do some or all of the following.

  1. Remove the chain object from the things served up by the database process and require local chain instances in each process (thought the underlying database connection may still be across process boundaries)
  2. Switch to RocksDB which allows for multiple database connections at which point we can potentially get rid of the database process entirely.

I see the potential for this to break some things, specifically surrounding our assumptions about where processing will happen and thus which calls are safe to make within the networking process without risking blocking too long and timing out with all of our peers.

Also, this further validates the event bus work that @cburgdorf has been doing with really explicitly and well defined communications which cross process boundaries.

@carver
Copy link
Contributor

carver commented Oct 18, 2018

require local chain instances in each process

This sounds right to me. I believe I've done all the necessary work on Chain to make this fairly painless (no local state, all state depends on the database). The only necessary change was removing the canonical head attribute into the MiningChain.

genesis_params=chain_config.genesis_params,
genesis_state=chain_config.genesis_state,
genesis_params=genesis_params,
genesis_state=genesis_state,
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe some of this logic that is just dumping in data from chain_config could be pushed inside chain_config, so the API could be:

chain = chain_config.launch_genesis(base_db)

If you like it

chain = chain_config.full_chain_class.from_genesis(
AtomicDB(MemoryDB()),
chain_config.genesis_params.to_dict(),
{address: account.to_dict() for address, account in chain_config.genesis_state.items()}
Copy link
Contributor

Choose a reason for hiding this comment

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

Here too.

@pipermerriam pipermerriam mentioned this pull request Oct 19, 2018
@pipermerriam pipermerriam force-pushed the piper/custom-genesis branch 3 times, most recently from 7f26a03 to 8b75601 Compare October 22, 2018 21:25
@pipermerriam
Copy link
Member Author

Working on rebasing and splitting this up but also pleased to report that a basic test of this code seems to be working right now.

@veox
Copy link
Contributor

veox commented Nov 21, 2018

PR still missing Cute Animal Pic.

@cburgdorf
Copy link
Contributor

@veox fixed!

Copy link
Contributor

@carver carver left a comment

Choose a reason for hiding this comment

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

Obviously needs a rebase and/or squashing since there are dirty commits.

The only thing that might need more discussion is: what's happening in the transaction validator? At best, something is unclear, but it appears broken.

chain = chain_config.initialize_chain(AtomicDB(MemoryDB()))

if network_id == MAINNET_NETWORK_ID:
assert chain_config.chain_id == MainnetChain.chain_id
Copy link
Contributor

Choose a reason for hiding this comment

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

Outside of the if block, you could test that the chain config ended up with the network ID it was created with, like:

assert chain_config.network_id == network_id



def test_initialize_database(trinity_config, chaindb):
@pytest.fixture
def chaindb(trinity_config, base_db):
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like trinity_config arg can be dropped.

chain = chain_class(header_db, peer_chain=event_bus_light_peer_chain)
else:
chain = chain_config.light_chain_class(header_db, peer_chain=event_bus_light_peer_chain)
elif trinity_config.is_full_mode:
Copy link
Contributor

Choose a reason for hiding this comment

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

I find this is_x_mode approach strange, in that it requires N is_x_mode attributes, one for each possible mode. I don't see a problem with the old sync_mode approach. If we're looking for more type-safety, sync_mode could be an Enum value instead of a str.

Copy link
Contributor

Choose a reason for hiding this comment

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

If we're looking for more type-safety, sync_mode could be an Enum value instead of a str.

With just two options, I don't feel strongly here but in general I agree that an Enum is nicer. Will change that.

Copy link
Member Author

Choose a reason for hiding this comment

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

@carver I found myself needing to import the enum/constant anywhere that I wanted to check sync mode, thus arose the creation of the is_x_mode. I don't feel strongly, but it was done to clean up the call sites.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, I don't really have strong feelings at 2-3 modes, it just stands out as a little odd. By the time it gets to 5+ I would start to feel unhappy about it I guess.


if initial_tx_validation_block_number is None:
self._initial_tx_class = self._get_tx_class_for_block_number(
initial_tx_validation_block_number
Copy link
Contributor

Choose a reason for hiding this comment

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

This reads super strange to me. I think it's broken, but even if it's not, it's weird. If the block number is None then look up the transaction class by the number None? Maybe the if test is supposed to be reversed.

A couple layers down the stack, it looks like it breaks when trying to validate that None is a block number.

Looks like we might need a test for each of these if/else blocks, too.

Copy link
Contributor

Choose a reason for hiding this comment

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

I will add test for this. I think you are right with it being broken currently.

Choose a reason for hiding this comment

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

Done. Setup[ Robot| 2021 coming up/ Countdown.

@cburgdorf
Copy link
Contributor

@carver Thanks for reviewing this!

Obviously needs a rebase and/or squashing since there are dirty commits.

Yep, will just squash this all together into one commit that adds custom genesis support

The only thing that might need more discussion is: what's happening in the transaction validator? At best, something is unclear, but it appears broken.

I think you are right. Will add tests for this (tomorrow)

Copy link
Member Author

@pipermerriam pipermerriam left a comment

Choose a reason for hiding this comment

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

Mostly just suggestions on how this can be split up into some smaller pieces.

eth/chains/mainnet/constants.py Show resolved Hide resolved
eth/chains/ropsten/constants.py Show resolved Hide resolved
eth/tools/builder/chain/builders.py Show resolved Hide resolved
trinity/nodes/base.py Show resolved Hide resolved
@FrankSzendzielarz
Copy link
Member

Ping me please when custom genesis / config is ready to play with. I am adding Trinity to Hive.

@cburgdorf cburgdorf force-pushed the piper/custom-genesis branch 4 times, most recently from defffaf to 59f64a6 Compare November 22, 2018 11:45
@cburgdorf
Copy link
Contributor

I didn't branch things out into multiple PRs but I sliced semantic commits that can be reviewed in isolation and should make it easier to follow.

I also added tests for the transaction validation stuff and corrected the functionality (it was indeed buggy).

I did not change the is_full_mode / is_light_mode stuff yet because the SYNC_LIGHT / SYNC_FULL constants are used at multiple places across the code base and if we refactor that to use an enum (I think we should) I would bloat this PR even more. I can send a follow up PR to refactor that.

@carver do you like to give this another review?

@cburgdorf cburgdorf force-pushed the piper/custom-genesis branch 2 times, most recently from 5402298 to 97342a3 Compare November 22, 2018 16:31
@carver
Copy link
Contributor

carver commented Nov 22, 2018

I did not change the is_full_mode / is_light_mode stuff yet ... would bloat this PR even more

Yup, totally reasonable.

It's Thanksgiving, so I'll be mostly offline. I'll give a optimistic 👍 since you mentioned that this merge is needed to let master run a regular sync.

@cburgdorf
Copy link
Contributor

@carver thanks! Happy Thanksgiving 🦃

@cburgdorf cburgdorf merged commit 2e674ce into ethereum:master Nov 22, 2018
@cburgdorf
Copy link
Contributor

@FrankSzendzielarz This is now merged. Let me know if you run into any issues trying it out 🎉

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.

Make trinity conform to standard genesis.json standard from EIP-1085
7 participants