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

Allow core to set its genesis ledger based on a list of bucket files and a ledger header #4259

Open
MonsieurNicolas opened this issue Mar 22, 2024 · 0 comments

Comments

@MonsieurNicolas
Copy link
Contributor

There are many situations where for testing purpose, being able to spin up a test node/network based on a state that is not the built-in genesis could be useful:

  • fork testing (ie: see what happens when upgrading "pubnet" to a new version of the protocol)
  • seeding of a test network (like "PreviewNet") based on an interesting data set
  • testing for specific, complex conditions
    • complex test setup (like having a full DEX populated)
    • "what if" scenarios, where somebody wants to test what would happen when interacting with a public contract under a specific condition (and with no access to keys, it's harder to setup)
    • advanced state archival tests (reason Support manual closing N ledgers #4040 was opened in the first place)

The way this would work would be:

  1. build a set of bucket files and a ledger header (copied or potentially transformed from somewhere else)
    a. Transformations may be useful here (if there is a way to round trip to json via Rust's serde, the transformation can be done with simple scripts that don't need to understand xdr), for example to adjust state, recompute contract IDs, or adjust archival TTLs
  2. (those commands can be run on multiple nodes if needed, like multiple test validators)
    • create a core instance with "new-db"
    • run a special command "ledger-import" that takes a list of bucket files (representing levels).
      • the command would adjust its internal state (copy bucket files, compute their hashes, build a bucket list, update the lcl to use that bucket list).
      • for simplicity, the ledger sequence number contained in the ledger header that was specified will be ignored (so that the runtime can make the same assumptions than when specifying a custom ledger for genesis in unit tests)
    • at that point the node is at a new "genesis ledger" based on those buckets and ledger header file
  3. start up validators, let them close a few checkpoints
  4. at that point other nodes can join this network as they will "apply buckets" based on what was published (they cannot replay from genesis)

some of downsides:

  • some invariants may be very hard to guarantee, which may cause non-obvious failures. While we could try catch some in classic, in Soroban it's basically impossible to do it (contracts may fail in ways not normally possible). This is the reason we originally didn't want to explore this route, but assuming the type of transformations done on buckets are "sane", this seems manageable
  • merges may not be triggered at the right time, and certain assumptions in state expiration as a consequence may be hard to reason about.
  • replaying from genesis is not possible. failure mode there will be that nodes that try to do that will have a hash mismatch on the very first ledger. As long as those types of setups are done

alternatives we could consider:

  • expose some "write APIs" to the bucketlist. Some test scenarios require fairly complex setup wrt levels, and this would make it necessary to write not just "latest" but into arbitrary levels.. this sounds fairly complicated to manage because of interactions with merges etc.
  • do nothing -- people need to submit transactions and close ledgers to rebuild state. this is the current approach, the downside there is that setting up interesting events may require closing millions of ledgers as to properly spill entries.

Marking as discussion for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants
@MonsieurNicolas and others