Scheme generation of model-objects
Background
- Iroha 2 peer receive messages from it clients primarily serialized in SCALE codec, but also some endpoint accept JSON messages
- Iroha 2 has some client libraries in development (Rust, Java/Kotlin, JavaScript, Python)
- Scale codec do not need the name of the properties and containers, but JSON do need
Problem
Iroha 2 has a lot of model-objects that peer can receive as input from blockchain clients and can respond with. Currently Iroha 2 in the active development process and set of this model-objects changes very often. These changes must be reflected in the Iroha 2 client's library and it requires a lot of affords to keep client's implementation up to date.
Solution
We can generate a scheme which would introspect details of object-models. The scheme brings such benefits:
- Code generation of models and serialization/deserialization tests
- Type safe checks in clients code (if programming language support type safety)
Basically we can consider 3 types of items
1. Scalars
In SCALE integers can be encoded as fixed-width integer and compact integer. Compact integer itself has 4 modes. So generally we have 5 ways to serde integer (1 fixed-width + 4 modes of compact integers)
{ "u8": { "Int": "FixedWidth" }, "iroha_introspect::Compact<u8>": { "Int": "Compact" } }
2. Built-in basic types
- bool: no tricks here
- String
{ "alloc::string::String": "String", "bool": "Bool" }
3. Built-in containers
Option / Result / Map / Vec : basically we are interested in only inner values of the container
{ "core::option::Option<iroha_data_model::isi::Instruction>": { "Option": "iroha_data_model::isi::Instruction" }, "core::result::Result<i32, i32>": { "Result": { "ok": "i32", "err": "i32" } }, "alloc::collections::BTreeMap<alloc::string::String, i32>": { "Map": { "key": "alloc::string::String", "value": "i32" } }, "alloc::vec::Vec<i32>": { "Vec": "i32" } }
4. Custom containers
- Named structures – structures which have field names
- Unnamed structures – structures with no field names (like zero sized structures in rust, or tuples, or struct WrappedTuple(i32, i32))
- Enums
{ "iroha_crypto::PublicKey": { "NamedStruct": { "declarations": [ { "name": "digest_function", "ty": "alloc::string::String" }, { "name": "payload", "ty": "alloc::vec::Vec<u8>" } ] } }, "iroha_data_model::account::SignatureCheckCondition": { "UnnamedStruct": { "types": [ "iroha_data_model::expression::EvaluatesTo<bool>" ] } }, "iroha_data_model::events::pipeline::EntityType": { "Enum": { "variants": [ { "name": "Block", "discriminant": 0, "ty": null }, { "name": "Transaction", "discriminant": 1, "ty": null } ] } }, }
Concerns
Currently we are not support polymorphism via TraitObjects, but it can be implemented if necessary
Additional Information
- Scale codec description in Substrate docs [https://substrate.dev/docs/en/knowledgebase/advanced/codec]
- Scale codec Github page [https://github.com/paritytech/parity-scale-codec]