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

common/block/blockchain: genesis refactor #1916

Merged
merged 1 commit into from
May 31, 2022

Conversation

ryanio
Copy link
Contributor

@ryanio ryanio commented May 27, 2022

This PR works on the ideas presented in #1833, mainly #1833 (comment) and #1833 (comment).

This PR:

  • Removes stateRoot and hash from Common
  • Moves genesis functionality from Block to Blockchain
  • Moves genesisStates from Common to Blockchain
  • RemovesVM.runBlockchain()
    • unused, except for in BlockchainTestsRunner where we now directly putBlocks and run the blockchain iterator

I haven't run the test suite yet to fix failing tests as I wanted some confirmation that we want to proceed on this path before working on the final touches.

The only downside so far (that I see) is that when setting up a custom chain you used to only need a very portable common but now you have to additionally pass the genesis states into blockchain, but this was easy enough to adjust to in the client by passing an optional blockchain when custom genesis states (or geth genesis) is provided.

Removing stateRoot and hash was also tricky in a few places but I think I overcame the challenges.

@codecov
Copy link

codecov bot commented May 27, 2022

Codecov Report

Merging #1916 (5d90fff) into develop (7765b7e) will increase coverage by 1.80%.
The diff coverage is 67.44%.

❗ Current head 5d90fff differs from pull request most recent head 803300a. Consider uploading reports for the commit 803300a to get more accurate results

Impacted file tree graph

Flag Coverage Δ
block 86.15% <100.00%> (+0.86%) ⬆️
blockchain 81.32% <54.54%> (-1.82%) ⬇️
client ?
common 95.01% <86.95%> (-0.56%) ⬇️
devp2p ?
ethash 90.81% <ø> (ø)
statemanager 84.87% <ø> (+0.62%) ⬆️
trie 80.19% <ø> (ø)
tx 92.09% <ø> (-0.05%) ⬇️
util 87.29% <ø> (ø)
vm 81.09% <100.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

@ryanio ryanio force-pushed the common-blockchain-genesis-refactor branch from 1c65eb5 to 7ca78aa Compare May 27, 2022 01:41
@holgerd77
Copy link
Member

Thanks so much. 🙂

I think I am a fan of continuing on this.

@ryanio ryanio force-pushed the common-blockchain-genesis-refactor branch from 7ca78aa to 30068c6 Compare May 28, 2022 00:30
@ryanio ryanio marked this pull request as ready for review May 28, 2022 01:15
@ryanio
Copy link
Contributor Author

ryanio commented May 28, 2022

Have to look into two ci issues, vm-api browser run timing out (taking too long?) and client cli connection. The PR can still be reviewed for everything else meanwhile.
edit: now resolved

@ryanio ryanio force-pushed the common-blockchain-genesis-refactor branch 3 times, most recently from 6e7785d to a84cc40 Compare May 31, 2022 00:48
@ryanio
Copy link
Contributor Author

ryanio commented May 31, 2022

This is ready for review :)

@ryanio ryanio requested a review from holgerd77 May 31, 2022 01:47
@holgerd77
Copy link
Member

Oh, 1 commit 😬 (thanks a thousand times, otherwise totally great that you got through this!!!).

This will be a bit harsh for review, would have preferred to have this step-by-step on such a large change set. But will try my best. 😋

Copy link
Member

@holgerd77 holgerd77 left a comment

Choose a reason for hiding this comment

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

Ok, this is such a convicing refactor (and it actually looks good on all fronts! 🙂 👍), I will directly take this in.

So so great, now seeing this I totally love the outlook (even more) of finally having these light-weight lower level libraries. Especially for tx this is a great win.

Will merge.

) {
baseFeePerGas = BigInt(this._common.genesis().baseFeePerGas!)
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Ok, I wondered a bit along seeing this how much people are using this functionality and if they will or will not miss this, but: I guess in case this is requested, we can very well add some less intrusive helpers (e.g. - similar to what we thought about for Common, allow passing in a genesis json + stateRoot + hash to create a block), which would be a non-breaking addition. So I think we can go with this.

const rlp = Buffer.from(testDataGenesis.test.genesis_rlp_hex, 'hex')
const hash = Buffer.from(testDataGenesis.test.genesis_hash, 'hex')
const block = Block.fromRLPSerializedBlock(rlp, { common })
st.ok(block.hash().equals(hash), 'genesis hash match')
Copy link
Member

Choose a reason for hiding this comment

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

Ah, nice replacement. 🙂

* }
* ```
*/
genesisState?: GenesisState
Copy link
Member

Choose a reason for hiding this comment

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

Ok, just followed this along just to get some confirmation: so if one now would want to run a VM with/upon some custom genesis state, one would create a Blockchain object first with this genesis state and passes this into the VM along initialization. Seems a reasonable replacement to me for this eventual use case.

@@ -115,7 +143,8 @@ export default class Blockchain implements BlockchainInterface {
db: LevelUp
dbManager: DBManager

private _genesis?: Buffer // the genesis hash of this blockchain
private _genesisBlock?: Block /** The genesis block of this blockchain */
Copy link
Member

Choose a reason for hiding this comment

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

This is actually also a nice replacement to have the Block here and not level down to just the hash (why?).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we have the whole block now so I figure it's nicer to cache it, as the hash can still be accessed, and it makes life easier e.g. in the client chain that returns genesis() as the genesis block. there might be more uses for the other fields in the future.

stateRoot = Buffer.from(
'd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544',
'hex'
)
Copy link
Member

Choose a reason for hiding this comment

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

👍

Great optimization!

const blocks: Block[] = []
const genesisBlock = Block.genesis({ header: { gasLimit: 8000000 } })
Copy link
Member

Choose a reason for hiding this comment

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

Oh, impressive, that this can be so easily replaced in the tests by the generic functions, seems specifically using genesis() wasn't necessary at all here in most cases?

Copy link
Contributor Author

@ryanio ryanio May 31, 2022

Choose a reason for hiding this comment

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

heh yeah since the block number still defaults to zero, we weren't losing much, as there were not very many cases where we needed the actual genesis params.

})
return genesisParams
get genesis() {
return this.blockchain.genesisBlock()
Copy link
Member

Choose a reason for hiding this comment

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

👍

max === 0 ? Buffer.from([]) : intToBuffer(max),
skip === 0 ? Buffer.from([]) : intToBuffer(skip),
!reverse ? Buffer.from([]) : Buffer.from([1]),
],
Copy link
Member

Choose a reason for hiding this comment

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

Just out of interest and because I can't spot right away: why did this code needed to change in this context?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

this is related to the RLP v3 changes, not sure why it just popped up in my PR, but when doing bufArrToArr we need all fields to be Buffer, otherwise if it is is a plain number it didn't convert correctly to Uint8Array.

common.setHardforkByBlockNumber(0)
return BlockHeader.fromHeaderData(headerData, { common })
}

Copy link
Member

Choose a reason for hiding this comment

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

Ugh. This is just falling off the cliff? How great is this? 😀

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yeah! some great simplifications through the process here

}
return this._calcForkHash(hardfork)
if (!genesisHash) throw new Error('genesisHash required for forkHash calculation')
return this._calcForkHash(hardfork, genesisHash)
}
Copy link
Member

Choose a reason for hiding this comment

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

That's a great modified forkHash version.

@holgerd77 holgerd77 force-pushed the common-blockchain-genesis-refactor branch from a84cc40 to 803300a Compare May 31, 2022 10:40
@holgerd77
Copy link
Member

Rebased this via UI after local test rebase.

@holgerd77 holgerd77 merged commit e0a659d into develop May 31, 2022
@holgerd77 holgerd77 deleted the common-blockchain-genesis-refactor branch May 31, 2022 11:02
@ryanio ryanio mentioned this pull request May 31, 2022
g11tech pushed a commit that referenced this pull request Jun 2, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants