Message Versioning
Background
Iroha2 Message Formats in use:
- Parity Scale Codec - API (except events); internal p2p messages
- JSON - API web socket events; genesis block
Problem
Iroha2 development will continue after the initial version is published and several networks might be already live. When the new versions are ready, the networks will start upgrading the nodes, to not disrupt the network at the time of an upgrade, nodes have to know the version in messages. Nodes might choose to support several older message formats, conditionally handling the logic.
Also client libraries need to be aware with what version of the API they are interacting, to properly report if they do not support this version, and conditionally handle versions that they do support.
Solution
JSON Based API
For JSON based API the solution is straight forward - the `version` field will be added to the message:
{
"payload": {.. valid json},
"version": 1
}
Parity Scale Codec Messages
With Parity Scale Codec it is not possible to do it in the same simple way. As there are no field names and delimiters there, everything is position and size based. Therefore we need to prefix messages with the version information.
The primitive that according to scale serialization rules allows us to do it is Enum.
pub enum VersionedMessage {
V1(MessageV1),
V2(MessageV2),
...
}
This Rust data structure would translate into the following at the time of serialization:
VersionedMessage::V1(...) → 0x00..
VersionedMessage::V2(...) → 0x01..
...
In this way during deserialization we will be able to tell by prefix what is the message version here and if we support it or not.
Alternative
There is an alternative for Parity Scale Codec messages versioning. We can wrap parity-scale-codec encoded bytes in JSON and supply a version there. This will also allow us to switch to other formats in the future if needed. But this comes at a cost of 33%-36% bigger messages due to suboptimal base64 encoding that we have to use inside of JSON to represent bytes.
{
"payload": "base64 encoded bytes",
"format": "parity-scale-codec",
"version": 1
}
Also if we choose this alternative the implementation of the versioning will be more coherent as both for JSON and Parity Scale Codec messages we will use the same JSON versioning message wrappers.
Concerns
- Do we need an ability to switch parity codec for another format later?
- Is 33% increase in message size acceptable?
- Possibly this can be improved by using base85 encoding (though it might take longer to implement)
Assumptions
Risks
None found