-
Notifications
You must be signed in to change notification settings - Fork 790
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
ERA: Add ERA file support package #3853
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files
Flags with carried forward coverage won't be shown. Click here to find out more. |
fa7b491
to
901f82f
Compare
Tests included cover the reading/parsing of era1 files To test the "export history" functions would require a client synced to at least 2 epochs ( To validate the export history functions:
|
@@ -154,6 +155,11 @@ export class Debug { | |||
this.verbosity = middleware(callWithStackTrace(this.verbosity.bind(this), this._rpcDebug), 1, [ | |||
[validators.unsignedInteger], | |||
]) | |||
this.exportHistoryAsEra1 = middleware( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add a parameter for epoch so we only export one epoch at a time? As it currently stands, it's kinda weird that I call exportHistoryAsEra1
and it just sits there and runs.
Or, maybe, better yet, could we just write a helper script that reads the client DB and formats the era files without having to initiate via RPC?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Yes, but since it uses
total_difficulty
it does have to start from block 0 and work forward. - That could work -- I will look into it
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, OK -- I didn't realize that we stored totalDifficulty
per block as a database item. So exporting a single, specific epoch should be possible after all
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still think an ideal scenario would be a standalone script that just reads the DB rather than an RPC call since it's weird for an RPC call to not return the actual data being requested but it gets written to disk separately. Is that much more difficult? Seems like you shoudl be able to pass in the path to the DB and just read things directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be user error but I did the following steps:
- Run the client
- Sync a few hundred thousand blocks.
- Call
debug_exportHistoryAsEra1
I then put the following script together.
import { readERA1, validateERA1 } from '@ethereumjs/era'
import { readFileSync } from 'fs'
const era1 = readFileSync('./epoch-0.era1')
const main = async () => {
console.log(await validateERA1(era1))
const blockReader = await readERA1(era1)
for await (const block of blockReader) {
console.log(block)
}
}
void main()
I get the following error:
Error: invalid data length, got 281474202442495, expected max of 52651
at readEntry (/home/jim/development/ethjs/packages/era/src/e2store.ts:54:11)
at readBlockTupleAtOffset (/home/jim/development/ethjs/packages/era/src/blockTuple.ts:67:23)
at readOtherEntries (/home/jim/development/ethjs/packages/era/src/era1.ts:145:21)
at readAccumulatorRoot (/home/jim/development/ethjs/packages/era/src/era1.ts:157:37)
at validateERA1 (/home/jim/development/ethjs/packages/era/src/era1.ts:168:33)
at main (/home/jim/development/ethjs/packages/client/era.ts:6:23)
at <anonymous> (/home/jim/development/ethjs/packages/client/era.ts:13:6)
Does that mean the era files I exported from the client didn't work right?
Try changing: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This may be user error but I did the following steps:
...
Does that mean the era files I exported from the client didn't work right?Try changing:
const era1 = readFileSync('./epoch-0.era1')
to
const era1 = new Uint8Array(readFileSync('./epoch-0.era1'))
Thanks! I figured it was something silly on my part. Can confirm that this now works.
35a9cf9
to
102453f
Compare
102453f
to
2527150
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Couple of small things to clean up before merging but I like this approach a lot better.
More general question, do we want to house support for the entire e2store file support in this @ethereumjs/era
package or do we have to have the separate one for Ultralight since we need the era
file support for our bridge scripts in Ultralight?
packages/era/tsconfig.prod.esm.json
Outdated
"composite": true | ||
}, | ||
"include": ["src/**/*.ts"], | ||
"references": [{ "path": "../rlp/tsconfig.prod.esm.json" }] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you likely need to add block and blockchain here so we don't end up with weird compilation errors down the line.
Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com>
Made the suggested changes. -- I think ultimately we could bring in the rest of the code from the ultralight era package, and ultralight could import It made sense to me to just start with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Introduces new package "@ethereumjs/era"
Package will include utility functions to enable creation and parsing of ERA files (era, era1, era2, etc.)
era package files
era/src/types.ts
era/src/snappy.ts
era/src/e2store.ts
era/src/exportHistory.ts
ERA1
era1 specs: ethereum/go-ethereum#26621
Era1 stores one epoch of history data along with the hash tree root of the epoch accumulator as an anchor for validation.
Era1 contains 8192 block tuples
A block tuple contains
Era1 also contains the root of an Epoch Accumulator
Epoch Accumulator is an SSZ object used in Portal Network. An Epoch Accumulator is constructed from a list of 8192 Header Records
A Header Record is an object with a blockHash and totalDifficulty.
The accumulator can be reconstructed to validate the contents of era1 against the provided accumulator root.
The accumulator roots are part of a static set of roots that can be externally validated.