-
Notifications
You must be signed in to change notification settings - Fork 69
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
chore: rewrite block payload #1499
Conversation
…ad, enforce maximum ns payload index in ns_iter, rename a few things
…espace_proof in test
On further discussion with @jbearer , I need to investigate whether it's feasible to maintain serialization compatibility. Putting this PR back into draft mode for now. |
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 is unbelievably well thought out. I applaud you.
Most of my comments are very minor and you should feel free to ignore them. The only really important one is the one on NamespaceId
.
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.
Think we're good here 👍
* serialize * Use the correct validated state on restart * Allow undecided state storage to be selectively turned out * PublicHotshotConfig * update hotshot * prepend target directory to PATH * expose state public key * Improve reference object tests * Add round-trip serialization check * Print out a valid serialization if the test fails, so that we can more easily update the test vectors when we change data structures * Generate test vectors from Rust objects * Add tests for ChainConfig, FeeInfo * toml file to public env vars for /env * rm env vars * rm private bind endpoints env vars * rm storage-sql module requirement * Add serialization compatibility test for Hotshot messages * enable config module for sequencer0 * remove l1 provider and account index variables * Move all typos excludes to .typos.toml * More helpful failures from serialization tests * add libp2p key derivation to binary (#1490) * Add bincode serialization compatibility checks * Check in missing files * update builder (#1494) * Avoid always using binaries in target/release (#1498) * Avoid always using binaries in target/release * fix comment * reject txn with namespace > u32::max * --- (#1487) updated-dependencies: - dependency-name: cachix/cachix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * typos: excludes excluded files in precommit hook * Serialize U256 numbers as decimal strings in JSON Adds two functions to be used with `(de)serialize_with`. This avoids having to define a macro, the downside is that it makes it possible to specify `serialize_with` without `deserialize_with`. - Changes the serialization of ChainID and FeeAmount. - Updates reference types. Apparently `chain_config.json` was not sorted before. - Add test to check if a roundtrip works. - Add test well as a test to check that bincode serialization is not affected by the customization. Close #1496 Close #1497 * add ResolvableChainConfig to ValidatedState * get_chain_config * Define a genesis config file This aims to separate onchain data, which must be the same for all nodes (chain ID, base fee, etc) from node-specific configuration. Node configuration continues to be done via environment variables, whereas onchain data is defined in a configuration file which we can distribute to all node operators when launching a network. This should greatly simplify coordination and reduce the frequency of errors due to misconfigured nodes. * Use serde for loading genesis from TOML file A new `FromStringOrInteger` helper in `sequencer_utils` allows us to hook the custom parsing logic for `FeeAmount`, `ChainId`, and `BlockSize` into deserialization, so that all the types that include these (`ChainConfig`, `Genesis`), we can use vanilla deserialization without custom TOML parsing code. The changes to the reference JSON data are acceptable because * They only affect JSON, bincode references are byte-for-byte unchange * We retain full backwards compatibility. See ad hoc tests for this in chain_config.rs and state.rs * Allow genesis file to specify L1 genesis by number or full block * Allow genesis file to specify genesis timestamp * Add file extension to docker genesis path * Use ethers parse_units to parse FeeAmount * Fix argument parsing in integration test * Fix reference header * Include genesis files in sequencer docker The idea is to include a genesis file for all officially supported networks (demo, staging, cappuccino, and eventually mainnet) so that operators can easily connect to the appropriate network just by setting the `ESPRESSO_SEQUENCER_GENESIS_FILE` environment variable to point at the appropriate bundled genesis file. Of course, operators can also connect to an unsupported chain (e.g. private testnet) by including their own genesis file via a volume. * Add genesis files to builder Docker build (#1509) * add genesis files to builder docker build * fix env var * Fix WebSocket timeout handling in nasty-client The server might close an idle connection after 60s. This should not be considered an error. Currently, though, it is causing errors, because our caluclation of idle time is not correct. We are using time since last read, but a read doesn't necessarily mean traffic over the connection. We might be reading a message that was sent long ago and has been sitting in our TCP buffer while the connection has been idle. To more accurately gauge how long the connection has been idle, we use time since the last _blocking_ read. Thus, we are less likely to produce an error, and more likely to just chalk ConnectionReset errors up to a stale stream and refresh the stream and continue. * chain config route * 30mb max block size (#1511) * Remove env vars that are ignored after the genesis change * Sort env vars alphabetically in env endpoint * add test * clippy * add recipe for clippy to justfile * Use `just clippy` in flake.nix * Remove dead code (#1516) This code is no longer used after #1443 (genesis file) * Update architecture diagram (#1445) * Update architecture diagram * add CDN annotations * Add Fee Contract * Add validated state * Re-organize sequencer node and network * Move DB into sequencer node * Add Hotshot Events in Hotshot package * Add sequence diagram, update README * Add sequence diagram step to architecture diagram * Address comments, add brief glossary * Add optimistic rollup dispute to diagram * Add optimistic rollup to architecture diagram --------- Co-authored-by: Rob <rob@espressosys.com> Co-authored-by: Jeb Bearer <jeb.bearer@gmail.com> Co-authored-by: Philippe Camacho <philippe@espressosys.com> * Fix docker demo (#1519) * Fix docker demo - Set stake table capacity to 10 for mock contract. - Log the stake table capacity on prover service startup. - Set a lower prover interval for local demos. - Query all logs in smoke test. By default it only queries the latest block. - Add stake table capacity to public env vars * Generate rust docs and publish (#1518) * Generate rust docs and publish - Fix compilation by adding RUSTDOCFLAGS - Add CI job to publish docs (modified from hotshot) - Add a just recipe - Update README Close #1517 * Change doc CI job name * Fix cross compilation dev shell Put rust env vars into a nix attrset to avoid repeating them many times * Set RUSTFLAGS in doc CI job * longer delay time for fee bridge * broken * remove apersand * one build failure left * remove unused imports * arcing things * fix build * Specifiy fetch requests rate limit for SQL (#1524) * update hotshot query service to 0.1.26 * set env var to 25 * Add backoff to state catchup retry loops * Backoff with jitter * CI: fix docker demo (#1526) * CI: fix docker demo - Rename bridge to espresso-bridge to avoid conflicts with other executable called bridge which often already exist on disk. - Improve output of smoke-test script to make it easier to debug failures in the future. * Allow access to host from within bridge container * Undo unwanted change * Fix local docker image build scripts * Fix copying of genesis data * Add dev-node binary (#1353) Add `espresso-dev-node` binary and friends. Currently docker image includes dev node, postgres and anvil. `builder_port` will be added in follow up (#1522). --------- Co-authored-by: sveitser <sveitser@gmail.com> Co-authored-by: Abdul Basit <baronbasit@gmail.com> Co-authored-by: Abdul Basit <45506001+imabdulbasit@users.noreply.github.com> Co-authored-by: tbro <tbro@users.noreply.github.com> * fix cargo * fix build and versions * point hotshot to main and others to daily-build * pass simple builder config * merge abdul/move-chain-config, hotshot ss/fee-upgrade others abdul/update-hotshot * make clippy happy * update lockfile to point to specific hotshot commit * update builder-core * arc SystemContextHandle * version * bump versions * add upgrades to Genesis and Nodestate * use fee_contract address from updated chain_config * rename upgrade block field to view * update version * update hotshot-query-service to 0.1.29 * tests building now * change clone * update query-service to 0.1.30 * Add env vars for new rate limiting parameters * add methods to SequencerContext for consensus * Chain config persistence * fix: use espresso-bridge instead of bridge for fund-builder * merge main, rebuild, update * Remove unnecessary write lock for submit endpoint The submit endpoint took a write lock on the state by default, since it is a POST endpoint. However, this lock is unnecessary, because internally all we do is send an event, we don't mutate any state. By using `at` instead of `post`, we can manually control the locking, and take just a read lock. This should help significantly in avoiding queues on the API state lock when many transactions are being submitted. * Add `Option<builder_port>` param to dev-node This PR add `Option<builder_port>` param in order to supply known port to `SimpleBuilder`. In addition in changes some variable names in `espresso-dev-node` to avoid confusion. Closes #1522 * lint * [Libp2p upgrade] Load bootstrap info from genesis file (#1505) * libp2p bootstrap info from file * wait for one connection to be initialized * move to new genesis toml * try_from * fix: use instance chain config for genesis validated_state * test for chain config catchup * remove version from NodeState * move proposal.chain_config and state chainconfig check below upgrade * move current version back to NodeState * get upgrade for current_version * update lockfile * add test for chain config upgrade * pass None for builder port * merge main * Implement server side connection limit This change implements a configurable limit on the number of simultaneous HTTP connections allowed by a query server. This should allow us to efficiently filter out requests during periods of high load so that the burden is pushed back onto clients, and the server continues operating within normal limits. This in turn will allow us to turn off or scale back the AWS rate limiter. * Fix dev-node options * test: reference_tests use nontrivial payload, ns_table (#1557) reference_tests use nontrivial payload, ns_table * Update query service * bump query service to 0.1.32 * update hotshot-query-service to 0.1.33 * DRAFT PR: 1470 escape hatch add sliding windows to light client contract (#1493) * added isHotshotLive function * added more tests * remove delayThreshold from LightClient contract, tests and rust tests * improve comments * added the abiity to get the commitment at a certain HotShot blockheight * simplified wasL1Updated function * variable name and function refactor * variable name and function refactor * added setHotShotCommitments function in LightClientMock * updated hotshotheight test * switched wasL1Updated to lagOverEscapeHatchThreshold * updates to getHotShotCommitment function * fix test * return block height as well as block comm root when fetching light client snapshot * update * update query service to 0.1.34 * update migration version to V31 and cleanup * apply_upgrade() and get_chain_config() * update only if chain config is different * return early * Remove the commitment task in dev node (#1555) * Remove the commitment task in dev node * Fix the building dev-node image * Drop created index on merklized state tables * Add logging and metrics for slow HTTP requests * Add queries by payload hash * wip implementing storage * almost done * broken query * Add state validation error types (#1543) Add error types for state validation * return these types from validation functions * update related tests * add wrapper `StateValidation` enum (only for human comprehension) --------- Co-authored-by: tbro <tbro@users.noreply.github.com> * integrate new versions * bump query service * add migration, change name * improve fs interface * add sql gc * update tests to include quorum proposal saving and loadin * typo * typo * typo * Add env var to recover archive after pruning * rename executable * chore: rewrite block payload (#1499) * new struct Payload2 * WIP new fns usize_to_bytes, max_from_byte_len with tests * implement NamespaceBuider * WIP begin implementing from_transactions * dead end: const generics not stable in Rust https://stackoverflow.com/a/72467535 * finish impl for from_transactions, use macro_rules to generalize usize_to_bytes * WIP friendly deserializers * generalized friendly deserializer * usize_from_bytes const generic param, add xxx_from_bytes functions * impl namespace_with_proof and some helpers * WIP test infra for namespace proofs * tweak test * Payload2:namespace_with_proof pass tests (yay) * don't double count dupliate namespace ids * tidy * restore block.rs from main, new file block2.rs * move mod tx_table to separate file payload_bytes.rs * rename block2::Payload2 -> Payload * set Payload::ns_iter() Item to NamespaceId * move namespace iterator to a separate file * rename payload2 -> ns_payload_builder * visibility tweaks for ns_iter * new fn verify_namespace_proof, temporary re-use of old parse_ns_payload, enforce maximum ns payload index in ns_iter, rename a few things * move namespace_with_proof and test to ns_proof.rs, use new verify_namespace_proof in test * move Payload::ns_iter, etc to ns_iter.rs * rename ns_payload_builder -> ns_payload * new mod tx_iter, a proper impl for parse_ns_payload * WIP combined iterator for QueryablePayload * move the combined iterator to iter.rs, delete the extra namespace iterator * stub impl of QueryablePayload for Payload * more stubs, tidy, new file tx_proof.rs * fix bug in TxIter, fix test * impl Payload::transaction with test * move tests to new file test.rs * tidy and comments * NsProof do not store VID common data * tidying and stub * new fn tx_table_range with doc * impl transaction_with_proof, still pretty messy tho * WIP tx proof only for num_txs * fix bug in iter, fix test * test: verify transaction proofs * major rework of ns_iter: new struct NsTable, NsIter::Item is now just usize * newtype NsIndex * TxIndex is now a serialized index, newtype NsPayload with awesome helper methods * fix name _max_from_byte_len2 -> _max_from_byte_len * xxx_from_bytes allow small byte lengths * NsIndex in serialized form like TxIndex * move tx_iter mod into ns_payload to enable private data in TxIndex * rename module ns_iter -> ns_table * tweak todo comments * move ns_payload, ns_proof, tx_proof modules inside ns_table * tidy * put TxIndex in a new mod tx_iter, move NsPayload::read_tx_offset into tx_iter, new method NsPayload::read_tx_offset_pref * add tx table range proof to TxProof * NsPayload now a DST, add newtype NsPayloadOwned so that it's to NsPayload as Vec<T> is to [T] * untested: TxProof::verify check tx table proof * dumbest bug ever * TxProof::verify now check tx payload proof (yay) * tidy: new module ns_iter like tx_iter, new method NsTable::read_ns_offset_prev like NsPayload::read_tx_offset_prev * new struct NsPayloadRange with helpers * WIP tweak tx_payload_range[_relative] * make NsPayloadRange a Range<usize> * WIP prep for experiments with NsPayload * add range field to NsPayload, it can no longer be a DST (boo) * revert back to DST for NsPayload * move tx_payload_range method from NsPayload to NsPayloadRange, add args to make it work * move modules ns_proof, tx_proof from ns_table up to block * move module ns_payload_range to its own file * Index fields private * move module ns_iter to its own file * move module tx_iter to its own file * newtype NumTxs * manual serde impl for NumTxs * NsPayloadRange::tx_payload_range arg type change usize -> NumTxs * new struct TxTableEntries * manual serde impl for TxTableEntries * tidy ns_table * move module num_txs into its own file * move module tx_table_entries to its own file * remove pub(crate) from NsPayloadRange newtype field * add TODOs, ugh Rust is killing me * TxIndex newtype from array to usize * NsIndex newtype from array to usize * move module num_txs up to block, experiment with access key design pattern * move module ns_iter up to block * move module tx_table_entries up to block * move module tx_iter up to block * move module ns_payload up to block * move module ns_payload_range up to block * move some NsTable impls into ns_table module * NsTable member private * move some impl Payload to block module * move NsProof construction from Payload to NsProof * move TxProof construction from Payload to TxProof * move struct Payload to a new module payload * visibility restrictions to payload module * oops * delete num_txs_as_bytes from payload_bytes * delete num_txs_from_bytes from payload_bytes * delete tx_offset_as_bytes from payload_bytes * delete tx_offset_from_bytes from payload_bytes * delete num_nss_as_bytes from payload_bytes * delete num_nss_from_bytes from payload_bytes * delete ns_offset_as_bytes from payload_bytes * delete ns_offset_from_bytes from payload_bytes * delete ns_offset_[as|from]_bytes from payload_bytes * tweak: Payload::ns_payload re-use ns_payload_range * move byte len constants to block module * rename module payload_bytes -> uint_bytes * tidy, minor refactor new function usize_fits * replace NsTable::num_nss_with_duplicates -> in_bounds, reflect the change in NsIter, use it in TxProof; also remove NsPayload::find_ns_id and reorder arg list in TxProof::new * check tx index in TxProof::new, new method NsPayload::in_bounds * WIP new model for NsPayload[Range] * WIP read_tx_offset * new traits AsBytes, BytesReader, new test for TxProof2 * PoC TxTableEntries in the new model * tidy, rename * remove const generic param from AsPayloadBytes trait * new structs NumTxs2, TxTableEntries2 using traits AsPayloadBytes * add tx payload range to TxProof2 * error checking in TxProof::new * TxProof::verify: add ns_table arg, remove ns_payload_range from proof, add error checking * derive serde for types in TxProof2 * delete old type TxProof in favor of TxProof2 * NsProofExistence use NsPayloadOwned2 instead of NsPayloadOwned * Iter use TxIter::new2 instead of new (progress toward switching from NsPayload to NsPayload2) * move NamespacePayloadBuilder to module newtypes * delete module ns_payload_range * delete old modules * newtype NsPayloadByteLen * newtype NumTxsChecked * move tx_table_entries_range_relative into TxTableEntriesRange::new * move module tx_iter into newtypes * impl AsPayloadBytes for TxIndex * WIP test fails: AsPayloadBytes new param T * fix test, but AsPayloadBytes trait is now unusable (boo) * fix TxTableEntries deserialization * delete unneeded stuff * rename a bunch of types in module newtypes * make AsPayloadBytes readable and rename it to FromPayloadBytes * tidy and rename * rename ns_payload[_range]2.rx -> without the 2 * tidy and renaming * newtype PayloadByteLen * tidy and docs * tidy ns_table * tidy payload * fix macro bytes_serde_impl * delete ns_iter.rs, move contents to ns_table.rs * restrict visibility of magic constants to a single file (yay) * tidy ns_payload * replace NsPayloadRange::offset with block_payload_range, simplify NsPayloadBytesRange * tidy tx_proof, rename some things * tidy * new method export_tx, in prep for reduced visibility * fix use statements * new module full_payload * WIP new module namespace_payload * move tx_proof, iter to namespace_payload; add helpers to avoid excessive visibility * new helper Payload::ns_payload * doc for bytes_serde_impl macro * move ns_payload_traits module into newtypes * rename module newtypes -> types * fix build after merge main * WIP swap out block for block2 * WIP fix test_namespace_query for block2 * WIP fix nasty_client except for NsIndex serialization issue * fix nasty-client for new block2, appease clippy * fix reference test for new ns table format * fix test demo, tidy * accounting for block byte length limit * temporary hack to pass tests * set forge-std git submodule to correct commit * fix test_message_compat * failing test for large namespace ids * single-character bug fix (damn that feels good) * fix doctest * update reference tests (again) * add test enforce_max_block_size * delete old block module * tidy TODOs, some general tidying * NsTable::read_ns_id check index in bounds * NsTable::ns_range check index in bounds * use read_ns_id_unchecked in NsIter * revert NsTable::ns_range to unchecked and restrict visibility * revert NsTable::read_ns_id to unchecked * re-arrange methods * NsTable::as_bytes_slice restrict visibility * delete NsTable::as_bytes_slice in favor of Encode trait * delete Payload::as_byte_slice in favor of Encode trait * tidy PayloadByteLen * restrict visibility for NsIter * restrict visibility of PayloadByteLen * restrict visibility of NsPayload * restrict visibility of NsPayloadRange * restrict visibility of NsPayloadBuilder * restrict visibility of TxIndex, TxIter * rename module block2 -> block * rename ns_payload_unchecked -> ns_payload * remove obsolete todo * revert #1504 ; this PR supports arbitrary 8-byte namespace IDs * detailed specification rustdoc for Payload, NsTable * detailed specification in rustdoc for namespace payload * rename Payload::payload -> ns_payloads * NsProof do not prove non-existence * Payload::is_consistent return Result instead of bool, eliminate panic * NsProof::new take NsIndex arg instead of NamespaceId * NamespaceProofQueryData::proof is now optional * fix: NsProof::ns_proof for empty payload should be None * address #1499 (comment) * NsTable field for backwards compatibility * set NS_ID_BYTE_LEN to 4 for backwards compatibility * Payload::builder_commitment hack for backwards compatibility * TODOs for NamespaceId, fix tests in block/test.rs * restore data/ files from main branch * remove obsolete comment * fix doc for NsProof::new as per #1499 (comment) * new method NsTable::read_ns_id_unchecked as per #1499 (comment) * NamespaceId manual Deserialize impl enforce u32::MAX * NamespaceId impl From<u32> as per #1499 (comment) * doc: links to github issues in code comments * 1328 update prover permissions on the light client contract via openzeppelin defender and safe wallets (#1454) * using the safe SDK for transaction proposals with a safe multisig wallet * Add yarn to flake.nix * ts-jest installed locally and env variable name changed * moved the safe sdk scripts into the contracts/script folder * Add @types/jest This allows me to run `yarn jest` without errors * Run prettier on typescript files * Commit yarn lockfile Avoid errors arising from non-reproducible dev enviornments * Add more steps to documentation, add dotenv * Update contracts/script/multisigTransactionProposals/README.md Co-authored-by: Mathis <sveitser@gmail.com> * Update contracts/script/multisigTransactionProposals/safeSDK/disableProverProposal.ts Co-authored-by: Mathis <sveitser@gmail.com> --------- Co-authored-by: sveitser <sveitser@gmail.com> * hotfix: revert field rename Payload::ns_payloads -> raw_payload (#1586) revert field rename Payload::ns_payloads -> raw_payload * test: reference test for Payload (#1588) * cherry-pick new reference test for Payload from gg/payload-serialization-tests * remove Committable impl from Payload, fix reference tests * Update query service * bump * update * block_size is allowed to be equal to `max_block_size` (#1579) Closes #1464 Co-authored-by: tbro <tbro@users.noreply.github.com> * [Prover] Sequencer node stake table initialization (#1600) * query node stake table initialization * fmt * [Libp2p] Bootstrap from env variable instead (#1601) bootstrap from env variable * groan * use Base::instance() * add propose_window, commit and revert in caller, remove header cf commit check * lint * lint * fix migrations version and use propose_window * fix: enforce_max_block_size test * change TestConfig nodes to 5 * set propose window to 10 * use transaction() * remove header cf commit check * update hotshot and cdn * Update CDN in `ab/fee-upgrade` (#1606) * update the CDN * update comment * fix latency calculation * query service update * cargo sort * add commit check back * `try_cast` * clippy * bump * FEATURE: Allow pulling a genesis file from AWS Secrets Manager (#1612) * Enable libp2p (#1621) enable libp2p * feat: enforce namespace table validity at consensus (#1607) * new method NsTable::validate, use it in state::validate_proposal * serde deserialize check NsTable::validate via ugly boilerplate serde-rs/serde#1220 (comment) * add test for invalid byte lengths * rename and tidy doc * Payload::from_transactions use BTreeMap instead of HashMap * NsIter do not skip duplicate entries * NsTable::validate enforce increasing entries, with tests * NsTable::validate enforce correct header, with tests * NsTable::validate disallow 0 namespace id, offset * tweak doc * clippy pacification game with old rust version * more clippy pacification (someone plz update nix) * debug CI * debug-ci: revert BTreeMap to HashMap * debug ci: remove serde validation, restore BTreeMap * restore NsTable serde validation * NsTable::validate tests also check serde round trip * NsTable do not derive Default, fix test_append_and_collect_garbage * restore ns_table.validate() * NamespaceId do not derive Default, Copy, do not impl Namespace, Namespaced, serde deserialize disallow zero * tidy use statements * allow zero NamespaceId (changed my mind) * fix doc NsTable::validate * nice job, idiot * clarify doc on serde derivation for NsTable * clarify doc for NsTable::len * fix: byte length check in NsTable::validate * address #1607 (comment) * make NamespaceId Copy again * fix again: byte length check in NsTable::validate * address #1607 (comment) * Remove old database port config (#1622) * Bump docker/build-push-action from 5 to 6 (#1615) Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6. - [Release notes](https://github.com/docker/build-push-action/releases) - [Commits](docker/build-push-action@v5...v6) --- updated-dependencies: - dependency-name: docker/build-push-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Add prover in dev node (#1583) * Add prover in dev-node * Check the namespace proof * Check vid common endpoint * Fix the getHotShotCommitment in contract * tmp broken build * fix one * fix build * fmt * update query-service * update query-service * Adding configuration changes for builder-core update * Adding configuration changes for builder-core update * fix test and add comments explaining how we fetch the hotshot commitment * feat: Namespace table enforce final offset equals payload length (#1642) * rename validate -> validate_deserialization_invariants, make it private * method NsTable::validate now take PayloadByteLen arg * clippy pacification for PayloadByteLen::is_consistent * new test payload_byte_len * PayloadByteLen::is_consistent don't panic * explainer comment * empty namespace table implies empty block payload, with tests * Fix possible lack of combined network message deduplication (#1643) * fix possible lack of message deduplication * clippy * Make catchup backoff params configurable; adjust defaults Makes the parameters controlling backoff for catchup requests configurable via env var. Adjusts the defaults to retry more quickly when there are few failures and backoff more dramatically when there are many failures. * Remove overly verbose log * Adjust stake table capacity so staging can use real prover contract * Merge main branch. --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Abdul Basit <45506001+imabdulbasit@users.noreply.github.com> Co-authored-by: imabdulbasit <baronbasit@gmail.com> Co-authored-by: Jeb Bearer <jeb@espressosys.com> Co-authored-by: Jeb Bearer <jeb.bearer@gmail.com> Co-authored-by: Brendon Fish <bfish713@gmail.com> Co-authored-by: sveitser <sveitser@gmail.com> Co-authored-by: rob-maron <132852777+rob-maron@users.noreply.github.com> Co-authored-by: Himanshu Goyal <himanshu@espressosys.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Rob <rob@espressosys.com> Co-authored-by: nomaxg <noahgolub2@gmail.com> Co-authored-by: Jarred Parr <jparr721@gmail.com> Co-authored-by: Jeremy <yiliang.he@qq.com> Co-authored-by: tbro <tbro@users.noreply.github.com> Co-authored-by: Gus Gutoski <ggutoski@users.noreply.github.com> Co-authored-by: Alysia Tech <hi@alysia.tech> Co-authored-by: tbro <48967308+tbro@users.noreply.github.com> Co-authored-by: Mat R <1577341+Ancient123@users.noreply.github.com> Co-authored-by: Nathan F Yospe <nyospe@gmail.com>
Closes #1076
This PR:
sequencer/src/block
.serialization compatibility
in comment TODOs.This PR does not:
block/tests.rs
. Deep testing for arbitrary block payloads is deferred to a future PR.Key places to review:
TODO
in code comments. I've checked them all prior to posting this PR. Many are flags to request changes to upstream code such asTODO(QueryablePayload)
. Some are requests for feedback from reviewers.block
. EspeciallyNamespaceProofQueryData
struct inendpoints.rs
as discussed in zulip, plus knock-on changes inapi.rs
,nasty-client.rs
.NamespaceId
struct intons_table.rs
: chore: rewrite block payload #1499 (comment), plus a laundry list of complaints:espresso-sequencer/sequencer/src/transaction.rs
Lines 9 to 28 in ab276e5
Should we allow duplicate namespace IDs in the namespace table? Seens_table.rs
(search "duplicate"), especiallyNsIter
struct. See also discussion in zulipns_table.rs
andtypes.rs
. (Not that you need to read it!)Top-down tour of code
Module:
block
block.rs
: Exposes an API to the rest of this workspace. Currently restricted only toespresso-sequencer/sequencer/src/block.rs
Line 6 in 46bbe9a
I expect in the future we might also need to expose
TxProof
and possibly other items. The goal is to expose as little as possible outsideblock
module.block/full_payload.rs
,block/namespace_payload.rs
: An attempt to impose a hierarchy of isolation/abstraction withinblock
so that it's not just a flat wall of types. (It's difficult to define a natural hierarchy; but this presentation seems not bad to me.)full_payload
: Any code that needs to know the structure of a multi-namespace payload. Contains the all-importantPayload
struct (which implsBlockPayload
,QueryablePayload
traits) plusNsTable
,NsProof
, etc.namespace_payload
: Self-contained implementation of an individual namespace.NsPayload
plusTxProof
, etc.As usual, these modules expose as little as possible. Lots of use of
pub(in crate::block)
to restrict visibility withinblock
module.Isolation of low-level binary format
Low-level details of binary format is isolated as much as possible. All reads from a block payload must use the following 2 modules:
block/full_payload/ns_table.rs
. 3 constants define byte lengths of objects that appear in a namespace table:espresso-sequencer/sequencer/src/block/full_payload/ns_table.rs
Lines 20 to 23 in 46bbe9a
block/namespace_payload/types.rs
(Open to suggestions for a better name.) Similar to the namespace table, 2 constants define byte lengths of objects that appear in a transaction table:espresso-sequencer/sequencer/src/block/namespace_payload/types.rs
Lines 12 to 14 in 46bbe9a
Extensive use of newtypes to prevent bugs
There are many different items floating around: payload byte length, namespace byte length, number of transactions in a namespace, index of a transaction, index of a namespace, byte range for a namespace, byte range for a transaction, etc.
It's easy to accidentally confuse these quantities. Example: accidental use of payload byte length when you intend to use namespace byte length. I've made extensive use of newtypes to prevent nasty bugs that might arise from such accidental misuse.
Example: construct a
TxIter
TxIter::new
has an arg of typeNumTxs
: a newtype wrapper forusize
that indicates the number of transactions in a namespace.NumTxs
callNumTxs::new
, which has args of typeNumTxsUnchecked
andNsPayloadByteLen
.NumTxsUnchecked
callNsPayload::read_num_txs
. This method extracts the declared number of transactions from the transaction table. A transaction table might contain corrupted data, so this quantity might cause a panic if used directly without checking. That's why you cannot construct aTxIter
from aNumTxsUnchecked
-> you must get aNumTxs
.NsPayloadByteLen
to construct aNumTxs
. You get that fromNsPayload::byte_len
orNsPayloadRange::byte_len
. This newtype prevents you from accidentally using the payload byte len instead of the namespace byte len.TxProof
demands many low-level pieces. Given that these pieces must exist forTxProof
, it makes sense to create them, then build higher-level helpers from these low-level tools as needed.NsPayload::read_num_txs
is actually a convenience helper that bundles several lower-level steps.Modules
full_payload
,namespace_payload
Module
full_payload
is relatively simple becauseNsProof
is not very demanding because the correctness of the namespace table is trusted as part of the block header.Module
namespace_payload
is complex becauseTxProof
is very demanding, so let's talk about the contents ofnamespace_payload
:ns_payload.rs
: StructNsPayload
for payload bytes for an individual namespace. No surprises here.ns_payload_range.rs
: NewtypeNsPayloadRange
forRange<usize>
that indicates a subslice of aPayload
for an individual namespace. Lots of important metadata can be obtained from only this range with no need to have a fullNsPayload
. Indeed, in some contexts such asTxProof::verify
a fullNsPayload
is not available so the only option is to rely onNsPayloadRange
.types.rs
: All low-level binary details of a namespace are isolated in this file. Most of the newtypes mentioned above depend on these low-level binary details, so most of those newtypes are also defined here.iter.rs
: A public-facing iteratorIter
over all transactions in a block payload. Under the hood it's a simple Cartesian productNsIter
xTxIter
.NsIter
is defined inns_table.rs
and can be accessed publicly viaNsTable::iter
.TxIter
is defined intypes.rs
and can be accessed viaNsPayload::iter
. ButTxIter
is not publicly accessible outsideblock
.Serialization for fixed-byte-length integers in
uint_bytes.rs
The magic constants defined in
ns_table.rs
,types.rs
indicate the byte length of various items in the payload.Example:
NUM_NSS_BYTE_LEN = 4
indicates that a namespace table shall use 4 bytes to encode the number of namespaces in the block. Perhaps in the future we'll decide that 3 bytes is sufficient to describe this quantity, as we expect the number of namespaces in a single block will never exceed 16 million. In that case, you can changeNUM_NSS_BYTE_LEN
from4
to3
and everything should work perfectly.In order to make the code generic over these constants I had to write my own serialization functions in
uint_bytes.rs
. In pseudocode:Most uses of this serialization are for a
usize
quantity, butNamespaceId
serialization isu64
. The only way to make these functions generic over primitive integer typesusize
,u64
, etc is to put them in a macrouint_bytes_impl
.This file includes other helper functions, extensive rustdoc, and detailed tests. There's also a separate macro
bytes_serde_impl
for customserde
derivation to/from a fixed-length bytes array[u8; N]
.Limitations
This code should work perfectly if all the magic constants are at most
8
. Anything beyond8
exceeds the byte length ofusize
,u64
and so you can expect build failure and/or startup panic if you try it.If you want to accommodate sizes larger than
8
then you'll need to change the implementation of all affected types to use something other thanusize
,u64
. I do not foresee any demand for sizes larger than 8 bytes: typical use is to serialize an integer quantity, and we do not expect any such quantity to exceed 64 bits.A possible exception:
NamespaceId
is an identifier, not a quantity. In the future we might use 32 bytes forNamespaceId
to allow a namespace ID to be a hash output. In that caseNamespaceId
will need modification and can no longer use the functions inuint_bytes.rs
.