# Cosmos External State Sync Strawman ## Meta For write access to this document, contact @michaelfig (`michaelfig#8707` on Cosmos Community Discord or [Agoric Discord](https://agoric.com)) Bikeshedding welcome after basic agreement has been reached on the concepts. ## Scope The current Cosmos "state sync" assumes that the multistore is the only representation for consensus state. Some Cosmos chains commit to external state in the AppHash, but store the actual data outside of the Cosmos multistore. That external data was generated exclusively by transactions processed by the Cosmos SDK, and is valuable because the multistore is not an efficient way to index or represent all the data our chains need to process future blocks. We wish to intelligently transfer and/or reconstruct that data during "state sync", allowing new nodes to avoid replaying the transactions that generated the external data (which in the worst case may go all the way back to genesis). ## Desiderata - External state syncs are implemented per Cosmos module and can be concurrent - Transferred data can be optimised for transport and need not be the same as the raw external data - TODO: The module callbacks are idiomatic Go. @michaelfig is not an expert. ## Concerns - Paraphrasing @ethanfrey: does state sync already correctly prevent pruning on the server side for state data that is in transit? ## Strawman Proposal ### Sender side 1. First choose the multistore state to transfer. 2. Create an `sdk.Context` corresponding to that chosen multistore read-only state, block height, etc. 3. Call `BeginReadState(sdk.Context ctx)` on (example) `x/mymod` with that Context 4. `BeginReadState` returns a ChunkedReadable object that the state sync can drive with: - `func ReadChunk(ctx sdk.Context, ...`, which returns an error if the chunk cannot be read, or the chunk data - `Done(ctx sdk.Context)` which declares the state has been successfully sent - `Abort(ctx sdk.Context, err error)` to declare the transfer has failed ### Receiver side 1. First transfer the multistore data. 2. Create an `sdk.Context` corresponding to that transferred multistore read-only state, block height, etc. 3. Call `x/mymod`'s `BeginWriteState(sdk.Context ctx)` with that Context 4. `BeginWriteState` returns a ChunkedWritable object that the state sync can drive with: - `func WriteChunk(ctx sdk.Context, chunkSpec...) error`, which returns an error if the chunk is already known to be incorrect, or nil if accepted - `func Done(ctx sdk.Context) error`, which returns an error, or nil if the data has been installed correctly and corresponds to the Context (such as block height agrees and content hashes in the multistore verify correctly) - `func Abort(ctx sdk.Context, err error) error`, to clean up a failed transfer ## References https://github.com/cosmos/cosmos-sdk/issues/7340 for original discussion. ## Motivated by - CosmWasm - uploaded binaries compressed and stored on disk - Provenance - ??? - Agoric - JS VM state stored in multiple formats