# ASN.1 for Static Serialization - Compact Wire Format ## Goal Use portable ASN.1 techniques to produce the most compact *deterministic* (stable/idempotent for hashing) wire format for gmserialization **static** encoding, based on existing templates. Focus is on the wire format itself (not RLP translation for legacy, which is deferred). ## Approach - The `asn1/GajumaruSerialization.asn` is the single source of truth (abstract syntax). - Use **Unaligned PER (UPER)** as the standard compact canonical encoding rule provided by the ASN.1 framework. - Portable across languages/tools that support ASN.1 UPER. - Deterministic for a fixed schema (no extensibility, consistent packing). - Optimize the schema for packing: - Constrain INTEGER ranges. - Provide `staticFields` (SEQUENCE OF Value) -- no field names (names are never on the wire for static case). - Provide `CompactStatic` top-level type to avoid unnecessary CHOICE overhead for the common static path. - Concrete SEQUENCEs for well-known objects (SignedTx, ContractV* etc.) when possible. - Encode with the generated ASN.1 module: ` 'GajumaruSerialization':encode('CompactStatic', Value) `. ## Results (example sizes) Using current optimized UPER: - Tiny object (tag/vsn + int + 1-byte bin): 9 bytes (legacy RLP = 5) - List of 3 ints: 13 bytes (legacy = 7) - Signed tx example: 11 bytes (legacy = 7) - 256-byte payload: ~263 bytes (legacy ~264) -- matches or slightly better PER/UPER overhead is mainly the structural tags for the generic case. Concrete types and `staticFields` + `CompactStatic` minimize it. Compared to DER (previous orientation): dramatically better (e.g. tiny case was ~36B in DER). ## Usage in Erlang (for the compact format) ```erlang % Build value according to schema (using staticFields for best compactness) Value = {'CompactStatic', Tag, Vsn, [ {'intValue', 42}, {'binaryValue', <<"data">>} % ... ]}, {ok, CompactBytes} = 'GajumaruSerialization':encode('CompactStatic', Value). ``` Compile the schema with: ``` asn1ct:compile("GajumaruSerialization.asn", [uper]). ``` ## Schema Notes - `staticFields` should be used for generic static templates (mirrors legacy positional encoding). - Concrete types (e.g. `signedTx`) are preferred when the structure is fixed. - `TemplateFields` (with names) is kept for debug/transition but not optimal for wire size. - The model directly reflects the static `template()` types from `gmserialization.erl`. ## Portability Any language with an ASN.1 UPER codec can produce and consume the exact same bytes by using the schema and the same value construction rules. ## Stability - UPER encoding of this schema is stable (tested roundtrip + re-encode identical). - No random/padding choices. - Same input value always produces identical bytes. ## Limitations / Future - For very small objects, hand-crafted RLP is still smaller because it has almost no structural overhead. - If an even more compact custom encoding is desired while keeping the model, a custom "encoding rule" can be implemented driven by the schema (similar to how the RLP layer works, but targeting a new bit-packed format). - Dynamic encoder (gmser_dyn) is out of scope. See also: `asn1/GajumaruSerialization.asn`, `asn1_compact/`, tests in `src/gmser_asn1_rlp.erl` (for value shapes), `doc/static.md`.