Message Versioning

Status

DECIDED 

Stakeholders
Outcome

Error rendering macro 'jira' : null

Due date

 

OwnerEgor Ivkov

Background

Iroha2 Message Formats in use:

  1. Parity Scale Codec - API (except events); internal p2p messages
  2. 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

  1. Do we need an ability to switch parity codec for another format later?
  2. Is 33% increase in message size acceptable?
    1. Possibly this can be improved by using base85 encoding (though it might take longer to implement)

Assumptions


Risks

None found

Additional Information

Parity Scale Codec Format

base64

base85