3.3 KiB
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.asnis 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
CompactStatictop-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)
% 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
staticFieldsshould 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 fromgmserialization.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.