diff --git a/notes/upgrade_examples b/notes/upgrade_examples new file mode 100644 index 00000000..62501163 --- /dev/null +++ b/notes/upgrade_examples @@ -0,0 +1,97 @@ + +Upgrade Issues/Examples + +- Authenticated encryption + - currently, first exchange is random 32-byte pubkeys, no protocol identification + - should be a struct like `{ AuthEncVersion, ConnectionType } + - should AuthEncVersion just be P2PVersion? + +- NodeInfo + - Make it a bunch of structs, since we can easily add fields to the end of structs + - If we want to change the high level structure, we would need code to: + - first read out the version by deserializing into `{ Version }` or possibly { {Version} }` + - then unmarshal again but into the correct struct version + - So we'd have structs like `NodeInfoV6` and `NodeInfoV7`. Both would have `Version` as first field, but otherwise could be totally different. + - Note the NodeInfo is embedded in RPC response types, so if there's a new version, it will break the RPC response. We either would need to: + - keep using the old version in the RPC response + - offer both versions some how (?!) + - could be included in the same response + - or do we version the endpoints? + +- New reactor messages + - Increment the P2PVersion and don't send the new msgs to peers below that version + +- Updated reactor message: + - Can add fields, but generally just make new ones + - If a field type was updated, also bump P2P version (?) + +Examples of Updates to Block: + +- Add new field to header + - eg v5 has a field that v4 doesnt + - v5 nodes accept v4 headers without the field + - v4 nodes accept v5 headers with the field, just ignoring it + - v5 nodes enforce rules on v5 headers + +- Change how a hash is computed in the header + - eg v5 uses hash of X, v4 uses hash of Y + - structs are compatible, but verification will fail + - v5 could verify hashes in v4 headers + - would require version info to be threaded through more data structures + - eg. make `.Hash()` depend on a version number + - eg. version the data types themselves (eg. `ValidatorV4`, `ValidatorV5`) + - v4 headers could not verify v5 headers + + +State +- not really part of protocol (we don't hash it) +- used in many places +- persisted to disk +- can easily add fields +- we should put a version at the top + + + +In general we have the following kinds of changes: + +- Adding fields + - Easy, just do it + +- Re-arranging fields or changing field types + - Read the version first + - Then deserialize into the correct versioned type + - Code may need to support multiple versions of a type (eg. two versions of Vote or Header) + +- Merklizing ... + +- New types + + + + + +## Older notes / Example Scenarios + +- Starting two versions of a new network, both named "gaia-8000", but with different initial state. + - The ChainID will include `gaia-8000` and some reference to the initial state (eg. its hash) +- A single network, but peers are running different compatible protocol versions, eg. + - to support a new reactor or new reactor message type + - like HasBlockPart in the consensus, or BatchOfTxs in the mempool + - should still be able to talk to some peers that cant understand these messages + - to add fields to a reactor message type + - Amino should allow this + - NOTE: the field will have to fit in the existing "maxMsgSize" and other versions have to be able to ignore it and be compatible .. + - to soft fork - ie. implement some form of additional restrictions on the ruleset + - NOT to add fields to hashed datastructures or change the state machine since these things need to be verified and integrity driven and + thus require incompatible upgrades +- A single network upgrades to an incompatible protocol version + - to add a new field to the header + - Amino is supposed to allow us to add new fields, but we don't actually want to do + this in a way that supports peers that haven't upgraded because we need to verify + - Could be a new merkle root of something we want, the proposer, or some application data + - to remove some fields from the Commit structure eg. so it just contains a signature + - to execute blocks before proposing them so the AppHash is included in the block (not the next one) + - to add a new transaction type to the state machine + - to change the way the state machine processes an existing transaction + - to change the state of the state machine at some height +