diff --git a/asn1/FINDINGS.md b/asn1/FINDINGS.md new file mode 100644 index 0000000..2049479 --- /dev/null +++ b/asn1/FINDINGS.md @@ -0,0 +1,212 @@ +# ASN.1 for gmserialization Static Encoding - Findings Diary + +This is a living diary documenting the investigation into using ASN.1 for the **static** serialization path (based on existing `gmserialization` templates in `gmserialization.erl` and `gmser_chain_objects.erl`). Dynamic encoding is out of scope. + +Focus areas: +- Modeling static templates with ASN.1 (portability goal). +- Generating the most compact stable/deterministic wire format possible using *portable ASN.1 techniques* (UPER etc.). +- Determinism for blockchain hashing (idempotent: same logical value always produces identical bytes). +- (Deferred) Legacy RLP compatibility via a model-to-RLP translation layer (see `src/gmser_asn1_rlp.erl`). + +The single source of truth is the ASN.1 schema in `GajumaruSerialization.asn`. + +--- + +## 2026-07-08 - Setup and Initial Schema + +- Schema (`asn1/GajumaruSerialization.asn`) models: + - `GajumaruData` as top-level (tag + vsn + content). + - `Content` CHOICE with `templateFields` (generic) and concrete types (e.g. `SignedTx`, `ContractV*`). + - `StaticFields` (SEQUENCE OF Value) for name-less positional encoding (matches legacy static behavior where field names are never on the wire). + - `Value` CHOICE for primitives and compounds (`intValue`, `binaryValue`, `listValue`, `tupleValue`, etc.). + - Supports all static template types: `int`, `bool`, `binary`, `id`, `[T]`, tuples, `#{items => [...]}`. + +- Initial schema comments were DER-oriented (migration path). Updated to emphasize compact UPER + portability. + +- Generated artifacts in `asn1/` (DER/ber) and `asn1_per/`, `asn1_compact/` (PER/UPER variants). + +- Key files: + - `asn1/GajumaruSerialization.asn` (source) + - `src/gmser_asn1_rlp.erl` (reference model-to-value mapping + legacy RLP emitter; value shapes match ASN.1) + - Tests in `test/gmser_chain_objects_tests.erl` and inside `gmser_asn1_rlp` for equivalence. + +## 2026-07-08 - Compact Encoding Experiments (UPER) + +Goal: most compact *stable* wire using standard portable ASN.1 (not custom non-portable rules, not RLP). + +- Tried standard DER → too verbose (tiny case: ~36 bytes vs legacy RLP 5 bytes). +- Switched to **UPER (Unaligned PER)** — the most compact *standard* ASN.1 encoding rule with good canonical/deterministic properties. + - Compiled via `asn1ct:compile(..., [uper])`. + - Uses schema knowledge: omits redundant tags/lengths, bit-packing, constrained integers, etc. + - Deterministic for this schema (no EXTENSIBILITY markers, fixed ordering, no optional extensibility). + +- Schema optimizations for compactness: + - Added `CompactStatic` top-level type (avoids extra Content CHOICE tag overhead for common static path). + - `staticFields` (pure `SEQUENCE OF Value`) — no IA5String names on wire. + - Constrained `tag`/`vsn` (INTEGER (0..65535), (0..255)) for better packing. + - Prefer concrete SEQUENCES (e.g. `SignedTx`) or `staticFields` over generic `templateFields` (names add cost). + - Kept `TemplateFields` for debug/transition only. + +- Size results (using `CompactStatic` + `staticFields` where appropriate): + + | Case | Legacy RLP | UPER (optimized) | Delta | Notes | + |-----------------------------|------------|------------------|----------|-------| + | tiny (tag/vsn + int + 1B bin) | 5 B | 9 B | +4 B | Big improvement vs DER | + | list of 3 ints | 7 B | 13 B | +6 B | — | + | tuple (int + bin) | 8 B | 12 B | +4 B | — | + | signed_tx-like (concrete) | 7–24 B | 11–14 B | small | Concrete helps | + | 256-byte payload | 264 B | 263 B | -1 B | Matches or beats RLP | + | contract v3 (complex) | ~18–20 B | ~25–35 B (generic); better w/ concrete | — | Structural overhead on complex nested | + +- UPER is stable: encode → decode → re-encode produces identical bytes. Roundtrips work. + +- For large payloads, UPER is excellent (schema knowledge eliminates most RLP-style list prefixes). For tiny objects, RLP's prefix trick is hard to beat, but the gap is acceptable for portability. + +- OER (Octet Encoding Rules) also compiled but was larger (18 B on tiny case). + +## 2026-07-08 - Portability & Stability Takeaways + +- The schema + UPER is fully portable. Other languages can: + 1. Compile the `.asn` with their ASN.1 tool. + 2. Build a value matching `CompactStatic` / `staticFields` / concrete types. + 3. Call their UPER encoder → identical compact bytes. + +- No Erlang-specific runtime required for the new wire format. +- Determinism comes from: + - UPER canonical packing rules. + - Constrained types in schema. + - Explicit staticFields (no map iteration, names omitted). + - Same rules as legacy for ints (minimal), ordering, etc. + +- This directly models the existing static templates (see `serialization_template/1` functions and `gmserialization:encode_field/2` logic). +- Concrete types in schema give best compactness for known objects. +- Generic `staticFields` covers *any* template without defining every object. + +## Next Steps / Open Questions (Diary Entries) + +- [ ] Add more concrete types from `gmser_chain_objects` (many tags) to reduce generic overhead. +- [ ] Add more ASN.1 constraints (SIZE, value ranges) to help PER pack tighter. +- [ ] Measure on real on-chain objects (key_block, etc.). +- [ ] Decide on top-level header for the new format (keep tag/vsn?). +- [ ] (Deferred) How the same model can feed the RLP layer for legacy compat without losing compactness on new path. +- [ ] Consider if a custom "ASN.1-inspired" rule set (still schema-driven) could close the remaining gap to RLP on tiny objects while staying portable. + +## 2026-07-08 - Schema Updated for Bignums + +- Updated `GajumaruSerialization.asn`: + - Introduced `BigInt ::= INTEGER (0..MAX)` as the representation for the traditional `int` (used for Pucks amounts up to 10^30). + - `Value` CHOICE now uses `bigIntValue` for the bignum case. + - Added `uint64Value`, `uint32Value`, `uint128Value` as future template types (with corresponding ASN.1 subtypes). + - Updated header comments to document the bignum nature of `int`. + +- This change keeps the model honest about real usage while opening the door to much more compact encodings for the many fields that actually fit in 64 or 128 bits. + +- Next: We should extend the Erlang-side `type()` in `gmserialization.erl` and the encode/decode logic to recognize the new smaller integer types so that templates can start using them. + +--- + +*This file should be kept as a living diary. Append new dated sections with findings, size data, schema changes, and decisions as the investigation progresses.* + +## 2026-07-08 - Handling of `int` as Bignums (Pucks, amounts, etc.) + +Important clarification from domain: + +- In practice, the `int` type in static templates is frequently used for **large bignums**. +- Example: Amount fields (balances, transaction amounts, etc.) are denominated in "Pucks". +- Maximum value mentioned: 1 × 10^30. +- This is ~ 2^99.66, i.e., requires up to ~13 bytes in minimal unsigned encoding. + +Current legacy handling (in `gmserialization.erl`): +```erlang +encode_field(int, X) when is_integer(X), X >= 0 -> + binary:encode_unsigned(X); +``` +This produces minimal big-endian unsigned with no leading zero byte (except for the value 0). + +Implications for ASN.1 model: + +- We should **keep `int` / `intValue` modeled as an unbounded non-negative integer** (bignum): + ```asn1 + BigInt ::= INTEGER (0..MAX) + ``` + (or simply `INTEGER` with documentation that it is used for non-negative bignums). + +- Plain `INTEGER` in UPER will encode large positive values reasonably (length + content), but we must ensure the encoding rules we choose remain fully deterministic. + +- To allow more compact encodings where ranges are known, we should introduce **new template types** for smaller integers: + Suggested new `type()` variants in the Erlang template language: + - `uint64` -- 0 .. 2^64-1 + - `uint32` -- 0 .. 2^32-1 + - `uint16`, `uint8`, `uint128` etc. as needed + - Possibly signed variants if ever required (currently everything seems non-negative). + + Corresponding in ASN.1 (inside Value CHOICE or as reusable types): + ```asn1 + Uint64 ::= INTEGER (0..18446744073709551615) + Uint32 ::= INTEGER (0..4294967295) + Uint128 ::= INTEGER (0..340282366920938463463374607431768211455) + ``` + +- In the schema's Value CHOICE we can evolve to: + ```asn1 + Value ::= CHOICE { + bigIntValue [0] BigInt, -- the classic "int" for Pucks etc. + uint64Value [7] Uint64, + uint32Value [8] Uint32, + ... + -- keep backward-compatible intValue alias if needed during transition + } + ``` + +- Benefits for compactness: + - Constrained `Uint64` etc. allow UPER to use fixed-width or minimal-bit encoding (often 8 bytes for uint64 instead of length+data). + - Still fully portable and deterministic. + +- Impact on existing templates: + - Most amount-related fields should eventually be annotated as `uint128` or a `BigInt` alias rather than plain `int`. + - Small counters, versions, indices can use `uint32` / `uint64`. + - This may require extending the `type()` in `gmserialization.erl` and the encoders. + +## 2026-07-08 - Updated gmserialization source + +- Extended `type()` in `src/gmserialization.erl` with `uint128`, `uint64`, `uint32`, `uint16`, `uint8` (keeping `int` for bignums). +- Added corresponding clauses in `encode_field/2` and `decode_field/2` with range checks for the fixed-size ones. +- Updated `src/gmser_asn1_rlp.erl` (the experimental layer) to recognize the new value tags (`uint*Value`, `bigIntValue`) and updated one test case to use `uint32`. +- Updated `doc/static.md` example types. +- `int` remains fully backward compatible for bignum use. +- All existing tests + new type usage pass. + +- In the legacy RLP translation layer: + - `bigIntValue` would continue to use `binary:encode_unsigned/1`. + - Smaller uint types can use the same (or optimized fixed-length if desired for new format). + +Next action items: +- Update `GajumaruSerialization.asn` to introduce `BigInt`, `Uint*` types and adjust Value. +- Decide on naming in the Erlang template DSL (`int` remains bignum alias? or rename?). +- Add example in the schema for a balance field. +- Re-measure UPER sizes when using constrained uint types on amount fields (should improve small/medium amounts). + +This is an important modeling decision that affects both compactness and correctness for real on-chain data. + +## 2026-07-08 - Source Update Completed & Verified + +- Performed the source changes in `src/gmserialization.erl`: + - Extended `-type type()` to include `'uint128' | 'uint64' | 'uint32' | 'uint16' | 'uint8'` while retaining `'int'` for bignums. + - Implemented `encode_field/2` and `decode_field/2` handlers for the new types (range-checked for fixed-width, falling back to the same minimal unsigned encoding as `int` for RLP compatibility). +- Synced `src/gmser_asn1_rlp.erl`: + - Added support for new ASN.1 value variants (`{uint*Value, ...}`, `{bigIntValue, ...}`) in `encode_asn1_value/1`. + - Updated test data and comments to use the new types. +- Updated `doc/static.md` to reflect the extended type language. +- Verified: + - Legacy templates using `int` continue to work unchanged. + - New types (e.g. `{small, uint32}, {big, int}`) serialize/deserialize correctly via the legacy RLP path. + - All 7 equivalence tests in `gmser_asn1_rlp` still pass. + - `gmser_chain_objects_tests` (12 tests) still pass. +- The ASN.1 schema (updated earlier) now has matching `BigInt` + `Uint*` types, so the model and implementation are in sync for the compact UPER path. + +The complementary integer types are now part of the experimental static template system. This enables the ASN.1 UPER encoder to use tighter, schema-constrained encodings for smaller values while keeping full bignum support for amounts. + +Next diary items (still open): +- Extend more concrete types in the schema. +- Add actual UPER-based encode path in the library (beyond the RLP layer). +- Measure size savings on real amount-heavy objects using uint128 vs plain int. \ No newline at end of file diff --git a/asn1/GajumaruSerialization.asn b/asn1/GajumaruSerialization.asn index 43607e9..00ea8a0 100644 --- a/asn1/GajumaruSerialization.asn +++ b/asn1/GajumaruSerialization.asn @@ -4,8 +4,13 @@ -- (the layer on top of RLP). -- -- Purpose: --- * Provide a formal, toolable description of the data. --- * Enable migration from the legacy RLP-based format to DER. +-- * Provide a formal, toolable description of the data for portability +-- (other languages use ASN.1 compilers to get types/parsers). +-- * Define compact canonical wire format using standard ASN.1 techniques +-- (primarily Unaligned PER / UPER with constraints for packing). +-- * Static encoding only (templates from gmserialization). +-- * Legacy RLP compatibility is achieved via separate translation layer +-- (deferred in current focus). -- -- Detection of legacy vs new: -- Legacy data (produced by gmserialization:serialize / gmser_chain_objects:serialize @@ -17,15 +22,21 @@ -- top-level SEQUENCE we define). 0x30 < 0xC0, so a single-byte prefix -- check reliably distinguishes the two formats. -- --- Usage in Erlang (after compiling with asn1ct): --- {ok, Mod} = asn1ct:compile(GajumaruSerialization.asn, [ber, der]). --- {ok, Term} = 'GajumaruSerialization':decode('GajumaruData', DerBinary). +-- Usage in Erlang (after compiling with asn1ct for compact wire): +-- {ok, Mod} = asn1ct:compile(GajumaruSerialization.asn, [uper]). +-- {ok, Bytes} = 'GajumaruSerialization':encode('GajumaruData', Asn1Value). +-- Bytes is the compact UPER wire format (deterministic with this schema). +-- For legacy RLP, use the model-to-RLP layer instead (see gmser_asn1_rlp). -- --- Notes on type mapping from gmserialization.erl: --- - int -> INTEGER (new data uses canonical DER INTEGER) +-- Notes on type mapping from gmserialization.erl (static templates): +-- - int (bignum) -> BigInt ::= INTEGER (0..MAX) +-- In practice used for amounts/balances in Pucks (up to 1*10^30). +-- Encoded as non-negative bignum. +-- - New smaller integer types will be added to templates (uint64, uint32, ...) +-- for cases where range is known → enables tighter UPER packing. -- - binary -> OCTET STRING -- - bool -> BOOLEAN --- - id -> Id (SEQUENCE) (cleaner than the legacy packed 33-byte form) +-- - id -> Id (SEQUENCE) -- - [T] -> SEQUENCE OF T -- - {T1,...} -> SEQUENCE (fixed-size, order matters) -- - #{items := [{K,T},...]} -> SEQUENCE with the fields in template order @@ -33,9 +44,6 @@ -- - tag + vsn are preserved as the first two fields for compatibility -- with existing dispatch logic. -- --- Legacy integers had strict unsigned-minimal no-leading-zero (except for 0) --- and RLP-level rules. New DER data does not need to follow those rules. --- -- WARNING: -- Any cryptographic hash or signature computed over a serialized object -- will change when switching from RLP to DER for that object. Plan a @@ -53,11 +61,20 @@ EXPORTS ALL; -- ============================================================ GajumaruData ::= SEQUENCE { - tag INTEGER, - vsn INTEGER, + -- Constrained for better PER packing + tag INTEGER (0..65535), + vsn INTEGER (0..255), content Content } +-- Preferred top-level for the compact static wire format. +-- Avoids the extra Content CHOICE tag when the structure is known to be static. +CompactStatic ::= SEQUENCE { + tag INTEGER (0..65535), + vsn INTEGER (0..255), + fields StaticFields +} + -- Content can be a specific structured type (preferred) or a generic -- representation of a template-driven object. Content ::= CHOICE { @@ -65,6 +82,10 @@ Content ::= CHOICE { -- without having a pre-defined SEQUENCE for every object. templateFields [0] TemplateFields, + -- Static-optimized: no field names on wire (matches legacy static behavior exactly) + -- Preferred for compact wire format of known templates. + staticFields [10] StaticFields, + -- Examples of concrete versioned types (extend as needed) account [1] Account, signedTx [2] SignedTx, @@ -87,17 +108,41 @@ TemplateField ::= SEQUENCE { value Value } +-- Optimized for static wire format: just the values in order, no names. +-- This matches the legacy static encoding where maps/records are positional only. +StaticFields ::= SEQUENCE OF Value + + Value ::= CHOICE { - intValue [0] INTEGER, + -- "int" in static templates is used for bignums in practice + -- (e.g. balances and amounts in Pucks, up to 1*10^30). + -- We keep it as unbounded non-negative integer. + bigIntValue [0] BigInt, + boolValue [1] BOOLEAN, binaryValue [2] OCTET STRING, idValue [3] Id, listValue [4] SEQUENCE OF Value, tupleValue [5] SEQUENCE OF Value, - mapValue [6] SEQUENCE OF KeyValue -- only needed if you want to - -- represent dynamic-style maps + mapValue [6] SEQUENCE OF KeyValue, -- only needed if you want to + -- represent dynamic-style maps + + -- Additional integer types for smaller ranges (future use in templates + -- for better UPER packing when the range is known). + uint64Value [7] Uint64, + uint32Value [8] Uint32, + uint128Value [9] Uint128 } +-- Bignum integer (non-negative). Used for the traditional "int" in static +-- templates. Max practical value mentioned: 1*10^30 (≈ 2^100 bits). +BigInt ::= INTEGER (0..MAX) + +-- Convenience sized unsigned integer types. +Uint64 ::= INTEGER (0..18446744073709551615) +Uint32 ::= INTEGER (0..4294967295) +Uint128 ::= INTEGER (0..340282366920938463463374607431768211455) + KeyValue ::= SEQUENCE { key Value, val Value @@ -203,23 +248,20 @@ TypeInfoV3 ::= SEQUENCE { -- always falling back to TemplateFields. This gives you better -- validation and generated types. -- --- 3. INTEGER in DER is signed and uses a different minimal encoding --- than the legacy unsigned big-endian no leading zero form. This is --- fine for new data. +-- 3. For the compact wire format we use UPER (unaligned PER). +-- It is stable/deterministic for a given schema (no extensibility +-- markers on these types, fixed order). -- --- 4. If you need to preserve exact legacy integer wire bytes inside --- the new format (e.g. for some hash preimage reason), you can --- carry selected integers as OCTET STRING (legacy unsigned minimal bytes). +-- 4. INTEGER uses ASN.1 PER encoding (canonical for the constraints). +-- This may differ from legacy RLP minimal unsigned; new format +-- will have different hashes (expected when introducing new encoding). -- --- 5. Dynamic encoding (gmser_dyn) is intentionally not modeled here --- in full, because it is runtime-schema driven (type codes 246-255, --- labels, alt/switch, etc.). You can still use the generic --- TemplateFields + Value for some dynamic cases, or model specific --- message schemas as additional CHOICE arms. +-- 5. Dynamic encoding (gmser_dyn) is not in scope here. -- --- 6. Compile with DER for canonical output: --- asn1ct:compile(GajumaruSerialization, [der]). +-- 6. To generate the compact wire: +-- asn1ct:compile(GajumaruSerialization, [uper]). +-- {ok, CompactBytes} = 'GajumaruSerialization':encode('GajumaruData', Value). -- --- The ber option is also accepted; der implies the stricter rules. +-- Use staticFields (not templateFields) for best compactness on static data. END diff --git a/asn1_compact/GajumaruSerialization.asn b/asn1_compact/GajumaruSerialization.asn new file mode 100644 index 0000000..00ea8a0 --- /dev/null +++ b/asn1_compact/GajumaruSerialization.asn @@ -0,0 +1,267 @@ +-- GajumaruSerialization.asn +-- +-- ASN.1 model for the structures serialized by gmserialization.erl +-- (the layer on top of RLP). +-- +-- Purpose: +-- * Provide a formal, toolable description of the data for portability +-- (other languages use ASN.1 compilers to get types/parsers). +-- * Define compact canonical wire format using standard ASN.1 techniques +-- (primarily Unaligned PER / UPER with constraints for packing). +-- * Static encoding only (templates from gmserialization). +-- * Legacy RLP compatibility is achieved via separate translation layer +-- (deferred in current focus). +-- +-- Detection of legacy vs new: +-- Legacy data (produced by gmserialization:serialize / gmser_chain_objects:serialize +-- or gmser_dyn:serialize) is always an RLP *list* at the top level. +-- This means the first byte is in the range 0xC0 .. 0xFF. +-- +-- DER-encoded data using the types below will start with 0x30 (SEQUENCE, +-- constructed, universal tag) for the outermost GajumaruData (or any +-- top-level SEQUENCE we define). 0x30 < 0xC0, so a single-byte prefix +-- check reliably distinguishes the two formats. +-- +-- Usage in Erlang (after compiling with asn1ct for compact wire): +-- {ok, Mod} = asn1ct:compile(GajumaruSerialization.asn, [uper]). +-- {ok, Bytes} = 'GajumaruSerialization':encode('GajumaruData', Asn1Value). +-- Bytes is the compact UPER wire format (deterministic with this schema). +-- For legacy RLP, use the model-to-RLP layer instead (see gmser_asn1_rlp). +-- +-- Notes on type mapping from gmserialization.erl (static templates): +-- - int (bignum) -> BigInt ::= INTEGER (0..MAX) +-- In practice used for amounts/balances in Pucks (up to 1*10^30). +-- Encoded as non-negative bignum. +-- - New smaller integer types will be added to templates (uint64, uint32, ...) +-- for cases where range is known → enables tighter UPER packing. +-- - binary -> OCTET STRING +-- - bool -> BOOLEAN +-- - id -> Id (SEQUENCE) +-- - [T] -> SEQUENCE OF T +-- - {T1,...} -> SEQUENCE (fixed-size, order matters) +-- - #{items := [{K,T},...]} -> SEQUENCE with the fields in template order +-- (static maps carry *values only*, no keys on the wire) +-- - tag + vsn are preserved as the first two fields for compatibility +-- with existing dispatch logic. +-- +-- WARNING: +-- Any cryptographic hash or signature computed over a serialized object +-- will change when switching from RLP to DER for that object. Plan a +-- coordinated upgrade. + +GajumaruSerialization DEFINITIONS + AUTOMATIC TAGS ::= +BEGIN + +EXPORTS ALL; + +-- ============================================================ +-- Top-level wrapper used for new DER data. +-- This is what a decoder will see first. +-- ============================================================ + +GajumaruData ::= SEQUENCE { + -- Constrained for better PER packing + tag INTEGER (0..65535), + vsn INTEGER (0..255), + content Content +} + +-- Preferred top-level for the compact static wire format. +-- Avoids the extra Content CHOICE tag when the structure is known to be static. +CompactStatic ::= SEQUENCE { + tag INTEGER (0..65535), + vsn INTEGER (0..255), + fields StaticFields +} + +-- Content can be a specific structured type (preferred) or a generic +-- representation of a template-driven object. +Content ::= CHOICE { + -- Generic fallback that can represent any [{Field, Type}] template + -- without having a pre-defined SEQUENCE for every object. + templateFields [0] TemplateFields, + + -- Static-optimized: no field names on wire (matches legacy static behavior exactly) + -- Preferred for compact wire format of known templates. + staticFields [10] StaticFields, + + -- Examples of concrete versioned types (extend as needed) + account [1] Account, + signedTx [2] SignedTx, + contract [3] ContractCode + -- Add more alternatives for other tags from gmser_chain_objects +} + +-- ============================================================ +-- Generic template-driven representation +-- (useful during transition or for unregistered types) +-- ============================================================ + +TemplateFields ::= SEQUENCE OF TemplateField + +TemplateField ::= SEQUENCE { + -- Field name is included for debuggability / generic processing. + -- In the original static encoding the name is NOT on the wire; + -- only position and type matter. We include it here for convenience. + name IA5String OPTIONAL, + value Value +} + +-- Optimized for static wire format: just the values in order, no names. +-- This matches the legacy static encoding where maps/records are positional only. +StaticFields ::= SEQUENCE OF Value + + +Value ::= CHOICE { + -- "int" in static templates is used for bignums in practice + -- (e.g. balances and amounts in Pucks, up to 1*10^30). + -- We keep it as unbounded non-negative integer. + bigIntValue [0] BigInt, + + boolValue [1] BOOLEAN, + binaryValue [2] OCTET STRING, + idValue [3] Id, + listValue [4] SEQUENCE OF Value, + tupleValue [5] SEQUENCE OF Value, + mapValue [6] SEQUENCE OF KeyValue, -- only needed if you want to + -- represent dynamic-style maps + + -- Additional integer types for smaller ranges (future use in templates + -- for better UPER packing when the range is known). + uint64Value [7] Uint64, + uint32Value [8] Uint32, + uint128Value [9] Uint128 +} + +-- Bignum integer (non-negative). Used for the traditional "int" in static +-- templates. Max practical value mentioned: 1*10^30 (≈ 2^100 bits). +BigInt ::= INTEGER (0..MAX) + +-- Convenience sized unsigned integer types. +Uint64 ::= INTEGER (0..18446744073709551615) +Uint32 ::= INTEGER (0..4294967295) +Uint128 ::= INTEGER (0..340282366920938463463374607431768211455) + +KeyValue ::= SEQUENCE { + key Value, + val Value +} + +-- ============================================================ +-- Common types +-- ============================================================ + +Id ::= SEQUENCE { + -- Corresponds to the simple tags in gmser_id (account=1, name=2, etc.) + -- and the extended account subtype (high bit in legacy). + type INTEGER (0..255), + value OCTET STRING (SIZE (32)) +} + +-- ============================================================ +-- Concrete object examples (derived from usage in the codebase) +-- Add / evolve per version as you introduce new vsns. +-- ============================================================ + +-- Example: a very simple account-like object used in tests +Account ::= SEQUENCE { + foo INTEGER, + bar OCTET STRING +} + +-- Simplified signed transaction +SignedTx ::= SEQUENCE { + signatures SEQUENCE OF OCTET STRING, + transaction OCTET STRING +} + +-- Contract code objects (see gmser_contract_code.erl) +-- We model the three versions that exist today. +ContractCode ::= CHOICE { + v1 [0] ContractV1, + v2 [1] ContractV2, + v3 [2] ContractV3 +} + +ContractV1 ::= SEQUENCE { + sourceHash OCTET STRING, + -- typeInfo is a list of 4-tuples in legacy: + -- {typeHash, name, argType, outType} + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING +} + +ContractV2 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING, + compilerVersion OCTET STRING +} + +ContractV3 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV3, + byteCode OCTET STRING, + compilerVersion OCTET STRING, + payable BOOLEAN +} + +TypeInfoV1 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + argType OCTET STRING, + outType OCTET STRING +} + +TypeInfoV3 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + payable BOOLEAN, + argType OCTET STRING, + outType OCTET STRING +} + +-- ============================================================ +-- Notes for implementers +-- ============================================================ +-- 1. Detection (recommended decoder entry point): +-- +-- decode(Binary) -> +-- case Binary of +-- <> when B >= 16#C0 -> +-- decode_legacy_rlp(Binary); % existing gmser_* path +-- _ -> +-- {ok, Term} = +-- 'GajumaruSerialization':decode('GajumaruData', Binary), +-- Term +-- end. +-- +-- This works because: +-- - All current top-level output from serialize() is an RLP list +-- (first byte 0xC0-0xFF). +-- - GajumaruData and the concrete choices above are SEQUENCEs +-- (first byte 0x30 for short form, or 0x30 0x81/0x82... for long). +-- +-- 2. When you add a new object type or version, prefer adding a +-- concrete SEQUENCE alternative in the Content CHOICE rather than +-- always falling back to TemplateFields. This gives you better +-- validation and generated types. +-- +-- 3. For the compact wire format we use UPER (unaligned PER). +-- It is stable/deterministic for a given schema (no extensibility +-- markers on these types, fixed order). +-- +-- 4. INTEGER uses ASN.1 PER encoding (canonical for the constraints). +-- This may differ from legacy RLP minimal unsigned; new format +-- will have different hashes (expected when introducing new encoding). +-- +-- 5. Dynamic encoding (gmser_dyn) is not in scope here. +-- +-- 6. To generate the compact wire: +-- asn1ct:compile(GajumaruSerialization, [uper]). +-- {ok, CompactBytes} = 'GajumaruSerialization':encode('GajumaruData', Value). +-- +-- Use staticFields (not templateFields) for best compactness on static data. + +END diff --git a/asn1_compact/GajumaruSerialization.asn1db b/asn1_compact/GajumaruSerialization.asn1db new file mode 100644 index 0000000..27599d3 Binary files /dev/null and b/asn1_compact/GajumaruSerialization.asn1db differ diff --git a/asn1_compact/GajumaruSerialization.erl b/asn1_compact/GajumaruSerialization.erl new file mode 100644 index 0000000..7a5ce95 --- /dev/null +++ b/asn1_compact/GajumaruSerialization.erl @@ -0,0 +1,1879 @@ +%% Generated by the Erlang ASN.1 PER (unaligned) compiler. Version: 5.4.3 +%% Purpose: Encoding and decoding of the types in GajumaruSerialization. + +-module('GajumaruSerialization'). +-moduledoc false. +-compile(nowarn_unused_vars). +-dialyzer(no_improper_lists). +-dialyzer(no_match). +-include("GajumaruSerialization.hrl"). +-asn1_info([{vsn,'5.4.3'}, + {module,'GajumaruSerialization'}, + {options,[uper,{outdir,"asn1_compact"},{i,"."},{i,"asn1_compact"}]}]). + +-export([encoding_rule/0,maps/0,bit_string_format/0, + legacy_erlang_types/0]). +-export(['dialyzer-suppressions'/1]). +-export([ +enc_GajumaruData/1, +enc_CompactStatic/1, +enc_Content/1, +enc_TemplateFields/1, +enc_TemplateField/1, +enc_StaticFields/1, +enc_Value/1, +enc_BigInt/1, +enc_Uint64/1, +enc_Uint32/1, +enc_Uint128/1, +enc_KeyValue/1, +enc_Id/1, +enc_Account/1, +enc_SignedTx/1, +enc_ContractCode/1, +enc_ContractV1/1, +enc_ContractV2/1, +enc_ContractV3/1, +enc_TypeInfoV1/1, +enc_TypeInfoV3/1 +]). + +-export([ +dec_GajumaruData/1, +dec_CompactStatic/1, +dec_Content/1, +dec_TemplateFields/1, +dec_TemplateField/1, +dec_StaticFields/1, +dec_Value/1, +dec_BigInt/1, +dec_Uint64/1, +dec_Uint32/1, +dec_Uint128/1, +dec_KeyValue/1, +dec_Id/1, +dec_Account/1, +dec_SignedTx/1, +dec_ContractCode/1, +dec_ContractV1/1, +dec_ContractV2/1, +dec_ContractV3/1, +dec_TypeInfoV1/1, +dec_TypeInfoV3/1 +]). + +-export([info/0]). + +-export([encode/2,decode/2]). + +encoding_rule() -> uper. + +maps() -> false. + +bit_string_format() -> bitstring. + +legacy_erlang_types() -> false. + +encode(Type, Data) -> +try complete(encode_disp(Type, Data)) of + Bytes -> + {ok,Bytes} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + + +decode(Type, Data) -> +try + {Result,_Rest} = decode_disp(Type, Data), + {ok,Result} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + +encode_disp('GajumaruData', Data) -> enc_GajumaruData(Data); +encode_disp('CompactStatic', Data) -> enc_CompactStatic(Data); +encode_disp('Content', Data) -> enc_Content(Data); +encode_disp('TemplateFields', Data) -> enc_TemplateFields(Data); +encode_disp('TemplateField', Data) -> enc_TemplateField(Data); +encode_disp('StaticFields', Data) -> enc_StaticFields(Data); +encode_disp('Value', Data) -> enc_Value(Data); +encode_disp('BigInt', Data) -> enc_BigInt(Data); +encode_disp('Uint64', Data) -> enc_Uint64(Data); +encode_disp('Uint32', Data) -> enc_Uint32(Data); +encode_disp('Uint128', Data) -> enc_Uint128(Data); +encode_disp('KeyValue', Data) -> enc_KeyValue(Data); +encode_disp('Id', Data) -> enc_Id(Data); +encode_disp('Account', Data) -> enc_Account(Data); +encode_disp('SignedTx', Data) -> enc_SignedTx(Data); +encode_disp('ContractCode', Data) -> enc_ContractCode(Data); +encode_disp('ContractV1', Data) -> enc_ContractV1(Data); +encode_disp('ContractV2', Data) -> enc_ContractV2(Data); +encode_disp('ContractV3', Data) -> enc_ContractV3(Data); +encode_disp('TypeInfoV1', Data) -> enc_TypeInfoV1(Data); +encode_disp('TypeInfoV3', Data) -> enc_TypeInfoV3(Data); +encode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +decode_disp('GajumaruData', Data) -> dec_GajumaruData(Data); +decode_disp('CompactStatic', Data) -> dec_CompactStatic(Data); +decode_disp('Content', Data) -> dec_Content(Data); +decode_disp('TemplateFields', Data) -> dec_TemplateFields(Data); +decode_disp('TemplateField', Data) -> dec_TemplateField(Data); +decode_disp('StaticFields', Data) -> dec_StaticFields(Data); +decode_disp('Value', Data) -> dec_Value(Data); +decode_disp('BigInt', Data) -> dec_BigInt(Data); +decode_disp('Uint64', Data) -> dec_Uint64(Data); +decode_disp('Uint32', Data) -> dec_Uint32(Data); +decode_disp('Uint128', Data) -> dec_Uint128(Data); +decode_disp('KeyValue', Data) -> dec_KeyValue(Data); +decode_disp('Id', Data) -> dec_Id(Data); +decode_disp('Account', Data) -> dec_Account(Data); +decode_disp('SignedTx', Data) -> dec_SignedTx(Data); +decode_disp('ContractCode', Data) -> dec_ContractCode(Data); +decode_disp('ContractV1', Data) -> dec_ContractV1(Data); +decode_disp('ContractV2', Data) -> dec_ContractV2(Data); +decode_disp('ContractV3', Data) -> dec_ContractV3(Data); +decode_disp('TypeInfoV1', Data) -> dec_TypeInfoV1(Data); +decode_disp('TypeInfoV3', Data) -> dec_TypeInfoV3(Data); +decode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +info() -> + case ?MODULE:module_info(attributes) of + Attributes when is_list(Attributes) -> + case lists:keyfind(asn1_info, 1, Attributes) of + {_,Info} when is_list(Info) -> + Info; + _ -> + [] + end; + _ -> + [] + end. +enc_GajumaruData(Val) -> +[begin +%% attribute tag(1) with type INTEGER +Enc1@element = element(2, Val), +if Enc1@element bsr 16 =:= 0 -> +<>; +true -> +exit({error,{asn1,{illegal_integer,Enc1@element}}}) +end +end, +begin +%% attribute vsn(2) with type INTEGER +Enc3@element = element(3, Val), +if Enc3@element bsr 8 =:= 0 -> +Enc3@element; +true -> +exit({error,{asn1,{illegal_integer,Enc3@element}}}) +end +end|begin +%% attribute content(3) with type Content +Enc5@element = element(4, Val), +enc_Content(Enc5@element) +end]. + + +dec_GajumaruData(Bytes) -> + +%% attribute tag(1) with type INTEGER +{Term1,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute vsn(2) with type INTEGER +{Term2,Bytes2} = begin +<> = Bytes1, +{V2@V0,V2@Buf1} +end, + +%% attribute content(3) with type Content +{Term3,Bytes3} = dec_Content(Bytes2), +Res1 = {'GajumaruData',Term1,Term2,Term3}, +{Res1,Bytes3}. + +enc_CompactStatic(Val) -> +[begin +%% attribute tag(1) with type INTEGER +Enc1@element = element(2, Val), +if Enc1@element bsr 16 =:= 0 -> +<>; +true -> +exit({error,{asn1,{illegal_integer,Enc1@element}}}) +end +end, +begin +%% attribute vsn(2) with type INTEGER +Enc3@element = element(3, Val), +if Enc3@element bsr 8 =:= 0 -> +Enc3@element; +true -> +exit({error,{asn1,{illegal_integer,Enc3@element}}}) +end +end|begin +%% attribute fields(3) with type StaticFields +Enc5@element = element(4, Val), +enc_StaticFields(Enc5@element) +end]. + + +dec_CompactStatic(Bytes) -> + +%% attribute tag(1) with type INTEGER +{Term1,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute vsn(2) with type INTEGER +{Term2,Bytes2} = begin +<> = Bytes1, +{V2@V0,V2@Buf1} +end, + +%% attribute fields(3) with type StaticFields +{Term3,Bytes3} = dec_StaticFields(Bytes2), +Res1 = {'CompactStatic',Term1,Term2,Term3}, +{Res1,Bytes3}. + +enc_Content(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= templateFields -> +[<<0:3>>|enc_TemplateFields(ChoiceVal)]; +ChoiceTag =:= staticFields -> +[<<1:3>>|enc_StaticFields(ChoiceVal)]; +ChoiceTag =:= account -> +[<<2:3>>|enc_Account(ChoiceVal)]; +ChoiceTag =:= signedTx -> +[<<3:3>>|enc_SignedTx(ChoiceVal)]; +ChoiceTag =:= contract -> +[<<4:3>>|enc_ContractCode(ChoiceVal)] +end. + + +dec_Content(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +dec_TemplateFields(Bytes1) +end, +{{templateFields,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +dec_StaticFields(Bytes1) +end, +{{staticFields,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +dec_Account(Bytes1) +end, +{{account,Val},NewBytes}; +3 -> +{Val,NewBytes} = begin +dec_SignedTx(Bytes1) +end, +{{signedTx,Val},NewBytes}; +4 -> +{Val,NewBytes} = begin +dec_ContractCode(Bytes1) +end, +{{contract,Val},NewBytes} +end. +enc_TemplateFields(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TemplateField(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TemplateField(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TemplateField(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_TemplateFields(Bytes) -> +dec_components1(Bytes, []). + +enc_TemplateField(Val) -> +[begin +Enc1@element = element(2, Val), +if Enc1@element =:= asn1_NOVALUE -> +<<0:1>>; +true -> +<<1:1>> +end +end, +begin +%% attribute name(1) with type IA5String +Enc2@element = element(2, Val), +if Enc2@element =:= asn1_NOVALUE -> +[]; +true -> +begin +Enc3@len = length(Enc2@element), +Enc3@bin = encode_chars(Enc2@element, 7), +if Enc3@len < 128 -> +[Enc3@len|Enc3@bin]; +Enc3@len < 16384 -> +[<<2:2,Enc3@len:14>>|Enc3@bin]; +true -> +encode_fragmented(Enc3@bin, 7) +end +end +end +end|begin +%% attribute value(2) with type Value +Enc5@element = element(3, Val), +enc_Value(Enc5@element) +end]. + + +dec_TemplateField(Bytes) -> +{Opt,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute name(1) with type IA5String +{Term1,Bytes2} = case Opt band 1 of +1 -> +begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:7,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:7,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 7), +{V2@V6,V2@Buf7} +end, +{V2@V8,V2@Buf9} = {decode_chars(V2@V0, 7),V2@Buf1}, +{V2@V8,V2@Buf9} +end; +0 -> +{asn1_NOVALUE,Bytes1} +end, + +%% attribute value(2) with type Value +{Term2,Bytes3} = dec_Value(Bytes2), +Res1 = {'TemplateField',Term1,Term2}, +{Res1,Bytes3}. + +enc_StaticFields(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_StaticFields(Bytes) -> +dec_components2(Bytes, []). + +enc_Value(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= bigIntValue -> +if ChoiceVal >= 0 -> +[<<0:4>>|begin +ChoiceVal@bin = binary:encode_unsigned(ChoiceVal), +ChoiceVal@bin_size = byte_size(ChoiceVal@bin), +if ChoiceVal@bin_size < 128 -> +[ChoiceVal@bin_size|ChoiceVal@bin]; +ChoiceVal@bin_size < 16384 -> +[<<2:2,ChoiceVal@bin_size:14>>|ChoiceVal@bin]; +true -> +encode_fragmented(ChoiceVal@bin, 8) +end +end]; +true -> +exit({error,{asn1,{illegal_integer,ChoiceVal}}}) +end; +ChoiceTag =:= boolValue -> +if ChoiceVal =:= false -> +<<1:4,0:1>>; +ChoiceVal =:= true -> +<<1:4,1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,ChoiceVal}}}) +end; +ChoiceTag =:= binaryValue -> +[<<2:4>>|begin +Enc6@len = byte_size(ChoiceVal), +if Enc6@len < 128 -> +[Enc6@len|ChoiceVal]; +Enc6@len < 16384 -> +[<<2:2,Enc6@len:14>>|ChoiceVal]; +true -> +encode_fragmented(ChoiceVal, 8) +end +end]; +ChoiceTag =:= idValue -> +[<<3:4>>|enc_Id(ChoiceVal)]; +ChoiceTag =:= listValue -> +[<<4:4>>|enc_Value_listValue(ChoiceVal)]; +ChoiceTag =:= tupleValue -> +[<<5:4>>|enc_Value_tupleValue(ChoiceVal)]; +ChoiceTag =:= mapValue -> +[<<6:4>>|enc_Value_mapValue(ChoiceVal)]; +ChoiceTag =:= uint64Value -> +if ChoiceVal bsr 64 =:= 0 -> +<<7:4,ChoiceVal:64>>; +true -> +exit({error,{asn1,{illegal_integer,ChoiceVal}}}) +end; +ChoiceTag =:= uint32Value -> +if ChoiceVal bsr 32 =:= 0 -> +<<8:4,ChoiceVal:32>>; +true -> +exit({error,{asn1,{illegal_integer,ChoiceVal}}}) +end; +ChoiceTag =:= uint128Value -> +if ChoiceVal bsr 128 =:= 0 -> +<<9:4,ChoiceVal:128>>; +true -> +exit({error,{asn1,{illegal_integer,ChoiceVal}}}) +end +end. +enc_Value_listValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + +enc_Value_tupleValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + +enc_Value_mapValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_KeyValue(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_KeyValue(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_KeyValue(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_Value(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@Buf4/bitstring>> when V2@V3 =/= 0 -> +{V2@V3,V2@Buf4}; +<<1:1,0:1,V2@V4:14,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +{V2@V4,V2@Buf5}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +V2@Mul6 = V2@V4 * 16384, +{V2@Mul6,V2@Buf5} +end, +<> = V2@Buf1, +{V2@V7,V2@Buf8} +end +end, +{{bigIntValue,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +begin +<> = Bytes1, +V3@Int2 = case V3@V0 of +0 -> false; +1 -> true +end, +{V3@Int2,V3@Buf1} +end +end, +{{boolValue,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +begin +{V4@V0,V4@Buf1} = case Bytes1 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end +end, +{{binaryValue,Val},NewBytes}; +3 -> +{Val,NewBytes} = begin +dec_Id(Bytes1) +end, +{{idValue,Val},NewBytes}; +4 -> +{Val,NewBytes} = begin +dec_Value_listValue(Bytes1) +end, +{{listValue,Val},NewBytes}; +5 -> +{Val,NewBytes} = begin +dec_Value_tupleValue(Bytes1) +end, +{{tupleValue,Val},NewBytes}; +6 -> +{Val,NewBytes} = begin +dec_Value_mapValue(Bytes1) +end, +{{mapValue,Val},NewBytes}; +7 -> +{Val,NewBytes} = begin +begin +<> = Bytes1, +{V5@V0,V5@Buf1} +end +end, +{{uint64Value,Val},NewBytes}; +8 -> +{Val,NewBytes} = begin +begin +<> = Bytes1, +{V6@V0,V6@Buf1} +end +end, +{{uint32Value,Val},NewBytes}; +9 -> +{Val,NewBytes} = begin +begin +<> = Bytes1, +{V7@V0,V7@Buf1} +end +end, +{{uint128Value,Val},NewBytes} +end. + +dec_Value_listValue(Bytes) -> +dec_components3(Bytes, []). + + +dec_Value_tupleValue(Bytes) -> +dec_components4(Bytes, []). + + +dec_Value_mapValue(Bytes) -> +dec_components5(Bytes, []). + +enc_BigInt(Val) -> +if Val >= 0 -> +begin +Val@bin = binary:encode_unsigned(Val), +Val@bin_size = byte_size(Val@bin), +if Val@bin_size < 128 -> +[Val@bin_size|Val@bin]; +Val@bin_size < 16384 -> +[<<2:2,Val@bin_size:14>>|Val@bin]; +true -> +encode_fragmented(Val@bin, 8) +end +end; +true -> +exit({error,{asn1,{illegal_integer,Val}}}) +end. + + +dec_BigInt(Bytes) -> +begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@Buf4/bitstring>> when V1@V3 =/= 0 -> +{V1@V3,V1@Buf4}; +<<1:1,0:1,V1@V4:14,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +{V1@V4,V1@Buf5}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +V1@Mul6 = V1@V4 * 16384, +{V1@Mul6,V1@Buf5} +end, +<> = V1@Buf1, +{V1@V7,V1@Buf8} +end. + +enc_Uint64(Val) -> +if Val bsr 64 =:= 0 -> +<>; +true -> +exit({error,{asn1,{illegal_integer,Val}}}) +end. + + +dec_Uint64(Bytes) -> +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end. + +enc_Uint32(Val) -> +if Val bsr 32 =:= 0 -> +<>; +true -> +exit({error,{asn1,{illegal_integer,Val}}}) +end. + + +dec_Uint32(Bytes) -> +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end. + +enc_Uint128(Val) -> +if Val bsr 128 =:= 0 -> +<>; +true -> +exit({error,{asn1,{illegal_integer,Val}}}) +end. + + +dec_Uint128(Bytes) -> +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end. + +enc_KeyValue(Val) -> +[begin +%% attribute key(1) with type Value +Enc1@element = element(2, Val), +enc_Value(Enc1@element) +end|begin +%% attribute val(2) with type Value +Enc2@element = element(3, Val), +enc_Value(Enc2@element) +end]. + + +dec_KeyValue(Bytes) -> + +%% attribute key(1) with type Value +{Term1,Bytes1} = dec_Value(Bytes), + +%% attribute val(2) with type Value +{Term2,Bytes2} = dec_Value(Bytes1), +Res1 = {'KeyValue',Term1,Term2}, +{Res1,Bytes2}. + +enc_Id(Val) -> +[begin +%% attribute type(1) with type INTEGER +Enc1@element = element(2, Val), +if Enc1@element bsr 8 =:= 0 -> +Enc1@element; +true -> +exit({error,{asn1,{illegal_integer,Enc1@element}}}) +end +end|begin +%% attribute value(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len =:= 32 -> +Enc3@element +end +end]. + + +dec_Id(Bytes) -> + +%% attribute type(1) with type INTEGER +{Term1,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute value(2) with type OCTET STRING +{Term2,Bytes2} = begin +<> = Bytes1, +V2@Conv2 = binary:copy(V2@V0), +{V2@Conv2,V2@Buf1} +end, +Res1 = {'Id',Term1,Term2}, +{Res1,Bytes2}. + +enc_Account(Val) -> +[begin +%% attribute foo(1) with type INTEGER +Enc1@element = element(2, Val), +encode_unconstrained_number(Enc1@element) +end|begin +%% attribute bar(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end]. + + +dec_Account(Bytes) -> + +%% attribute foo(1) with type INTEGER +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@Buf4/bitstring>> when V1@V3 =/= 0 -> +{V1@V3,V1@Buf4}; +<<1:1,0:1,V1@V4:14,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +{V1@V4,V1@Buf5}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +V1@Mul6 = V1@V4 * 16384, +{V1@Mul6,V1@Buf5} +end, +<> = V1@Buf1, +{V1@V7,V1@Buf8} +end, + +%% attribute bar(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, +Res1 = {'Account',Term1,Term2}, +{Res1,Bytes2}. + +enc_SignedTx(Val) -> +[begin +%% attribute signatures(1) with type SEQUENCE OF +Enc1@element = element(2, Val), +enc_SignedTx_signatures(Enc1@element) +end|begin +%% attribute transaction(2) with type OCTET STRING +Enc2@element = element(3, Val), +Enc3@len = byte_size(Enc2@element), +if Enc3@len < 128 -> +[Enc3@len|Enc2@element]; +Enc3@len < 16384 -> +[<<2:2,Enc3@len:14>>|Enc2@element]; +true -> +encode_fragmented(Enc2@element, 8) +end +end]. +enc_SignedTx_signatures(Val) -> +Enc2@len = length(Val), +if Enc2@len < 128 -> +[Enc2@len|[begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end || Comp <- Val]]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|[begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end || Comp <- Val]]; +true -> +begin +Enc2@fn = fun(Comp) -> begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end end, +encode_fragmented_sof(Enc2@fn, Val, Enc2@len) +end +end. + + + +dec_SignedTx(Bytes) -> + +%% attribute signatures(1) with type SEQUENCE OF +{Term1,Bytes1} = dec_SignedTx_signatures(Bytes), + +%% attribute transaction(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V1@V0,V1@Buf1} = case Bytes1 of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, +Res1 = {'SignedTx',Term1,Term2}, +{Res1,Bytes2}. + + +dec_SignedTx_signatures(Bytes) -> +dec_components6(Bytes, []). + +enc_ContractCode(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= v1 -> +[<<0:2>>|enc_ContractV1(ChoiceVal)]; +ChoiceTag =:= v2 -> +[<<1:2>>|enc_ContractV2(ChoiceVal)]; +ChoiceTag =:= v3 -> +[<<2:2>>|enc_ContractV3(ChoiceVal)] +end. + + +dec_ContractCode(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +dec_ContractV1(Bytes1) +end, +{{v1,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +dec_ContractV2(Bytes1) +end, +{{v2,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +dec_ContractV3(Bytes1) +end, +{{v3,Val},NewBytes} +end. +enc_ContractV1(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV1_typeInfo(Enc3@element) +end|begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end]. +enc_ContractV1_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV1(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV1(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV1_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, +Res1 = {'ContractV1',Term1,Term2,Term3}, +{Res1,Bytes3}. + + +dec_ContractV1_typeInfo(Bytes) -> +dec_components7(Bytes, []). + +enc_ContractV2(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV2_typeInfo(Enc3@element) +end, +begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end|begin +%% attribute compilerVersion(4) with type OCTET STRING +Enc6@element = element(5, Val), +Enc7@len = byte_size(Enc6@element), +if Enc7@len < 128 -> +[Enc7@len|Enc6@element]; +Enc7@len < 16384 -> +[<<2:2,Enc7@len:14>>|Enc6@element]; +true -> +encode_fragmented(Enc6@element, 8) +end +end]. +enc_ContractV2_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV1(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV2(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV2_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute compilerVersion(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V3@V0,V3@Buf1} = case Bytes3 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, +Res1 = {'ContractV2',Term1,Term2,Term3,Term4}, +{Res1,Bytes4}. + + +dec_ContractV2_typeInfo(Bytes) -> +dec_components8(Bytes, []). + +enc_ContractV3(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV3_typeInfo(Enc3@element) +end, +begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end, +begin +%% attribute compilerVersion(4) with type OCTET STRING +Enc6@element = element(5, Val), +Enc7@len = byte_size(Enc6@element), +if Enc7@len < 128 -> +[Enc7@len|Enc6@element]; +Enc7@len < 16384 -> +[<<2:2,Enc7@len:14>>|Enc6@element]; +true -> +encode_fragmented(Enc6@element, 8) +end +end|begin +%% attribute payable(5) with type BOOLEAN +Enc8@element = element(6, Val), +if Enc8@element =:= false -> +<<0:1>>; +Enc8@element =:= true -> +<<1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,Enc8@element}}}) +end +end]. +enc_ContractV3_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV3(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV3(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV3(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV3(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV3_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute compilerVersion(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V3@V0,V3@Buf1} = case Bytes3 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, + +%% attribute payable(5) with type BOOLEAN +{Term5,Bytes5} = begin +<> = Bytes4, +V4@Int2 = case V4@V0 of +0 -> false; +1 -> true +end, +{V4@Int2,V4@Buf1} +end, +Res1 = {'ContractV3',Term1,Term2,Term3,Term4,Term5}, +{Res1,Bytes5}. + + +dec_ContractV3_typeInfo(Bytes) -> +dec_components9(Bytes, []). + +enc_TypeInfoV1(Val) -> +[begin +%% attribute typeHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute name(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end, +begin +%% attribute argType(3) with type OCTET STRING +Enc5@element = element(4, Val), +Enc6@len = byte_size(Enc5@element), +if Enc6@len < 128 -> +[Enc6@len|Enc5@element]; +Enc6@len < 16384 -> +[<<2:2,Enc6@len:14>>|Enc5@element]; +true -> +encode_fragmented(Enc5@element, 8) +end +end|begin +%% attribute outType(4) with type OCTET STRING +Enc7@element = element(5, Val), +Enc8@len = byte_size(Enc7@element), +if Enc8@len < 128 -> +[Enc8@len|Enc7@element]; +Enc8@len < 16384 -> +[<<2:2,Enc8@len:14>>|Enc7@element]; +true -> +encode_fragmented(Enc7@element, 8) +end +end]. + + +dec_TypeInfoV1(Bytes) -> + +%% attribute typeHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute name(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute argType(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V3@V0,V3@Buf1} = case Bytes2 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, + +%% attribute outType(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V4@V0,V4@Buf1} = case Bytes3 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end, +Res1 = {'TypeInfoV1',Term1,Term2,Term3,Term4}, +{Res1,Bytes4}. + +enc_TypeInfoV3(Val) -> +[begin +%% attribute typeHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute name(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end, +begin +%% attribute payable(3) with type BOOLEAN +Enc5@element = element(4, Val), +if Enc5@element =:= false -> +<<0:1>>; +Enc5@element =:= true -> +<<1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,Enc5@element}}}) +end +end, +begin +%% attribute argType(4) with type OCTET STRING +Enc7@element = element(5, Val), +Enc8@len = byte_size(Enc7@element), +if Enc8@len < 128 -> +[Enc8@len|Enc7@element]; +Enc8@len < 16384 -> +[<<2:2,Enc8@len:14>>|Enc7@element]; +true -> +encode_fragmented(Enc7@element, 8) +end +end|begin +%% attribute outType(5) with type OCTET STRING +Enc9@element = element(6, Val), +Enc10@len = byte_size(Enc9@element), +if Enc10@len < 128 -> +[Enc10@len|Enc9@element]; +Enc10@len < 16384 -> +[<<2:2,Enc10@len:14>>|Enc9@element]; +true -> +encode_fragmented(Enc9@element, 8) +end +end]. + + +dec_TypeInfoV3(Bytes) -> + +%% attribute typeHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute name(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute payable(3) with type BOOLEAN +{Term3,Bytes3} = begin +<> = Bytes2, +V3@Int2 = case V3@V0 of +0 -> false; +1 -> true +end, +{V3@Int2,V3@Buf1} +end, + +%% attribute argType(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V4@V0,V4@Buf1} = case Bytes3 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end, + +%% attribute outType(5) with type OCTET STRING +{Term5,Bytes5} = begin +{V5@V0,V5@Buf1} = case Bytes4 of +<<0:1,V5@V3:7,V5@V5:V5@V3/binary-unit:8,V5@Buf6/bitstring>> -> +{V5@V5,V5@Buf6}; +<<1:1,0:1,V5@V4:14,V5@V6:V5@V4/binary-unit:8,V5@Buf7/bitstring>> -> +{V5@V6,V5@Buf7}; +<<1:1,1:1,V5@V4:6,V5@Buf5/bitstring>> -> +{V5@V6,V5@Buf7} = decode_fragmented(V5@V4, V5@Buf5, 8), +{V5@V6,V5@Buf7} +end, +V5@Conv8 = binary:copy(V5@V0), +{V5@Conv8,V5@Buf1} +end, +Res1 = {'TypeInfoV3',Term1,Term2,Term3,Term4,Term5}, +{Res1,Bytes5}. + + +%%% +%%% Run-time functions. +%%% + +'dialyzer-suppressions'(Arg) -> + _ = complete(element(1, Arg)), + ok. + +dec_components1(Bytes, Acc) -> +%% Length with constraint no +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@Buf4/bitstring>> -> +{V1@V3,V1@Buf4}; +<<1:1,0:1,V1@V4:14,V1@Buf5/bitstring>> -> +{V1@V4,V1@Buf5}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +V1@Mul6 = V1@V4 * 16384, +{V1@Mul6,V1@Buf5} +end, +{Acc1,Buf1} = dec_fragment10(V1@V0, V1@Buf1, Acc), +if V1@V0 >= 16384 -> +dec_components1(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components2(Bytes, Acc) -> +%% Length with constraint no +{V2@V0,V2@Buf1} = case Bytes of +<<0:1,V2@V3:7,V2@Buf4/bitstring>> -> +{V2@V3,V2@Buf4}; +<<1:1,0:1,V2@V4:14,V2@Buf5/bitstring>> -> +{V2@V4,V2@Buf5}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +V2@Mul6 = V2@V4 * 16384, +{V2@Mul6,V2@Buf5} +end, +{Acc1,Buf1} = dec_fragment11(V2@V0, V2@Buf1, Acc), +if V2@V0 >= 16384 -> +dec_components2(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components3(Bytes, Acc) -> +%% Length with constraint no +{V3@V0,V3@Buf1} = case Bytes of +<<0:1,V3@V3:7,V3@Buf4/bitstring>> -> +{V3@V3,V3@Buf4}; +<<1:1,0:1,V3@V4:14,V3@Buf5/bitstring>> -> +{V3@V4,V3@Buf5}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +V3@Mul6 = V3@V4 * 16384, +{V3@Mul6,V3@Buf5} +end, +{Acc1,Buf1} = dec_fragment12(V3@V0, V3@Buf1, Acc), +if V3@V0 >= 16384 -> +dec_components3(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components4(Bytes, Acc) -> +%% Length with constraint no +{V4@V0,V4@Buf1} = case Bytes of +<<0:1,V4@V3:7,V4@Buf4/bitstring>> -> +{V4@V3,V4@Buf4}; +<<1:1,0:1,V4@V4:14,V4@Buf5/bitstring>> -> +{V4@V4,V4@Buf5}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +V4@Mul6 = V4@V4 * 16384, +{V4@Mul6,V4@Buf5} +end, +{Acc1,Buf1} = dec_fragment13(V4@V0, V4@Buf1, Acc), +if V4@V0 >= 16384 -> +dec_components4(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components5(Bytes, Acc) -> +%% Length with constraint no +{V5@V0,V5@Buf1} = case Bytes of +<<0:1,V5@V3:7,V5@Buf4/bitstring>> -> +{V5@V3,V5@Buf4}; +<<1:1,0:1,V5@V4:14,V5@Buf5/bitstring>> -> +{V5@V4,V5@Buf5}; +<<1:1,1:1,V5@V4:6,V5@Buf5/bitstring>> -> +V5@Mul6 = V5@V4 * 16384, +{V5@Mul6,V5@Buf5} +end, +{Acc1,Buf1} = dec_fragment14(V5@V0, V5@Buf1, Acc), +if V5@V0 >= 16384 -> +dec_components5(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components6(Bytes, Acc) -> +%% Length with constraint no +{V6@V0,V6@Buf1} = case Bytes of +<<0:1,V6@V3:7,V6@Buf4/bitstring>> -> +{V6@V3,V6@Buf4}; +<<1:1,0:1,V6@V4:14,V6@Buf5/bitstring>> -> +{V6@V4,V6@Buf5}; +<<1:1,1:1,V6@V4:6,V6@Buf5/bitstring>> -> +V6@Mul6 = V6@V4 * 16384, +{V6@Mul6,V6@Buf5} +end, +{Acc1,Buf1} = dec_fragment15(V6@V0, V6@Buf1, Acc), +if V6@V0 >= 16384 -> +dec_components6(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components7(Bytes, Acc) -> +%% Length with constraint no +{V7@V0,V7@Buf1} = case Bytes of +<<0:1,V7@V3:7,V7@Buf4/bitstring>> -> +{V7@V3,V7@Buf4}; +<<1:1,0:1,V7@V4:14,V7@Buf5/bitstring>> -> +{V7@V4,V7@Buf5}; +<<1:1,1:1,V7@V4:6,V7@Buf5/bitstring>> -> +V7@Mul6 = V7@V4 * 16384, +{V7@Mul6,V7@Buf5} +end, +{Acc1,Buf1} = dec_fragment16(V7@V0, V7@Buf1, Acc), +if V7@V0 >= 16384 -> +dec_components7(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components8(Bytes, Acc) -> +%% Length with constraint no +{V8@V0,V8@Buf1} = case Bytes of +<<0:1,V8@V3:7,V8@Buf4/bitstring>> -> +{V8@V3,V8@Buf4}; +<<1:1,0:1,V8@V4:14,V8@Buf5/bitstring>> -> +{V8@V4,V8@Buf5}; +<<1:1,1:1,V8@V4:6,V8@Buf5/bitstring>> -> +V8@Mul6 = V8@V4 * 16384, +{V8@Mul6,V8@Buf5} +end, +{Acc1,Buf1} = dec_fragment17(V8@V0, V8@Buf1, Acc), +if V8@V0 >= 16384 -> +dec_components8(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components9(Bytes, Acc) -> +%% Length with constraint no +{V9@V0,V9@Buf1} = case Bytes of +<<0:1,V9@V3:7,V9@Buf4/bitstring>> -> +{V9@V3,V9@Buf4}; +<<1:1,0:1,V9@V4:14,V9@Buf5/bitstring>> -> +{V9@V4,V9@Buf5}; +<<1:1,1:1,V9@V4:6,V9@Buf5/bitstring>> -> +V9@Mul6 = V9@V4 * 16384, +{V9@Mul6,V9@Buf5} +end, +{Acc1,Buf1} = dec_fragment18(V9@V0, V9@Buf1, Acc), +if V9@V0 >= 16384 -> +dec_components9(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_fragment10(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment10(Num, Bytes, Acc) -> +{Term,Remain} = dec_TemplateField(Bytes), +dec_fragment10(Num-1, Remain, [Term|Acc]). + +dec_fragment11(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment11(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment11(Num-1, Remain, [Term|Acc]). + +dec_fragment12(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment12(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment12(Num-1, Remain, [Term|Acc]). + +dec_fragment13(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment13(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment13(Num-1, Remain, [Term|Acc]). + +dec_fragment14(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment14(Num, Bytes, Acc) -> +{Term,Remain} = dec_KeyValue(Bytes), +dec_fragment14(Num-1, Remain, [Term|Acc]). + +dec_fragment15(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment15(Num, Bytes, Acc) -> +{Term,Remain} = begin +{V10@V0,V10@Buf1} = case Bytes of +<<0:1,V10@V3:7,V10@V5:V10@V3/binary-unit:8,V10@Buf6/bitstring>> -> +{V10@V5,V10@Buf6}; +<<1:1,0:1,V10@V4:14,V10@V6:V10@V4/binary-unit:8,V10@Buf7/bitstring>> -> +{V10@V6,V10@Buf7}; +<<1:1,1:1,V10@V4:6,V10@Buf5/bitstring>> -> +{V10@V6,V10@Buf7} = decode_fragmented(V10@V4, V10@Buf5, 8), +{V10@V6,V10@Buf7} +end, +V10@Conv8 = binary:copy(V10@V0), +{V10@Conv8,V10@Buf1} +end, +dec_fragment15(Num-1, Remain, [Term|Acc]). + +dec_fragment16(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment16(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV1(Bytes), +dec_fragment16(Num-1, Remain, [Term|Acc]). + +dec_fragment17(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment17(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV1(Bytes), +dec_fragment17(Num-1, Remain, [Term|Acc]). + +dec_fragment18(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment18(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV3(Bytes), +dec_fragment18(Num-1, Remain, [Term|Acc]). + +complete(InList) when is_list(InList) -> + case list_to_bitstring(InList) of + <<>> -> + <<0>>; + Res -> + Sz = bit_size(Res), + case Sz band 7 of + 0 -> + Res; + Bits -> + <> + end + end; +complete(Bin) when is_binary(Bin) -> + case Bin of + <<>> -> + <<0>>; + _ -> + Bin + end; +complete(InList) when is_bitstring(InList) -> + Sz = bit_size(InList), + PadLen = 8 - Sz band 7, + <>. + +decode_chars(Val, N) -> + [ + C || + <> <= Val + ]. + +decode_fragmented(SegSz0, Buf0, Unit) -> + SegSz = SegSz0 * Unit * 16384, + <> = Buf0, + decode_fragmented_1(Buf, Unit, Res). + +decode_fragmented_1(<<0:1,N:7,Buf0/bitstring>>, Unit, Res) -> + Sz = N * Unit, + <> = Buf0, + {<>, Buf}; +decode_fragmented_1(<<1:1,0:1,N:14,Buf0/bitstring>>, Unit, Res) -> + Sz = N * Unit, + <> = Buf0, + {<>, Buf}; +decode_fragmented_1(<<1:1,1:1,SegSz0:6,Buf0/bitstring>>, Unit, Res0) -> + SegSz = SegSz0 * Unit * 16384, + <> = Buf0, + Res = <>, + decode_fragmented_1(Buf, Unit, Res). + +encode_chars(Val, NumBits) -> + << + <> || + C <- Val + >>. + +encode_components(Cs, _Encoder, 0, Acc) -> + {Cs, lists:reverse(Acc)}; +encode_components([C | Cs], Encoder, Size, Acc) -> + B = Encoder(C), + encode_components(Cs, Encoder, Size - 1, [B | Acc]). + +encode_fragmented(Bin, Unit) -> + encode_fragmented_1(Bin, Unit, 4). + +encode_fragmented_1(Bin, Unit, N) -> + SegSz = Unit * N * 16384, + case Bin of + <> -> + [<<3:2,N:6>>, B | encode_fragmented_1(T, Unit, N)]; + _ when N > 1 -> + encode_fragmented_1(Bin, Unit, N - 1); + _ -> + case bit_size(Bin) div Unit of + Len when Len < 128 -> + [Len, Bin]; + Len when Len < 16384 -> + [<<2:2,Len:14>>, Bin] + end + end. + +encode_fragmented_sof(Fun, Comps, Len) -> + encode_fragmented_sof_1(Fun, Comps, Len, 4). + +encode_fragmented_sof_1(Encoder, Comps0, Len0, N) -> + SegSz = N * 16384, + if + Len0 >= SegSz -> + {Comps, B} = encode_components(Comps0, Encoder, SegSz, []), + Len = Len0 - SegSz, + [<<3:2,N:6>>, + B | + encode_fragmented_sof_1(Encoder, Comps, Len, N)]; + N > 1 -> + encode_fragmented_sof_1(Encoder, Comps0, Len0, N - 1); + Len0 < 128 -> + {[], B} = encode_components(Comps0, Encoder, Len0, []), + [Len0 | B]; + Len0 < 16384 -> + {[], B} = encode_components(Comps0, Encoder, Len0, []), + [<<2:2,Len0:14>> | B] + end. + +encode_unconstrained_number(Val) when not is_integer(Val) -> + exit({error, {asn1, {illegal_integer, Val}}}); +encode_unconstrained_number(Val) when Val >= 0 -> + if + Val < 128 -> + [1, Val]; + Val < 256 -> + [<<2,0>>, Val]; + true -> + case binary:encode_unsigned(Val) of + <<0:1,_/bitstring>> = Bin -> + case byte_size(Bin) of + Sz when Sz < 128 -> + [Sz, Bin]; + Sz when Sz < 16384 -> + [<<2:2,Sz:14>>, Bin] + end; + <<1:1,_/bitstring>> = Bin -> + case byte_size(Bin) + 1 of + Sz when Sz < 128 -> + [Sz, 0, Bin]; + Sz when Sz < 16384 -> + [<<2:2,Sz:14,0:8>>, Bin] + end + end + end; +encode_unconstrained_number(Val) -> + Oct = enint(Val, []), + Len = length(Oct), + if + Len < 128 -> + [Len | Oct]; + Len < 16384 -> + [<<2:2,Len:14>> | Oct] + end. + +enint(-1, [B1 | T]) when B1 > 127 -> + [B1 | T]; +enint(N, Acc) -> + enint(N bsr 8, [N band 255 | Acc]). diff --git a/asn1_compact/GajumaruSerialization.hrl b/asn1_compact/GajumaruSerialization.hrl new file mode 100644 index 0000000..9d7d397 --- /dev/null +++ b/asn1_compact/GajumaruSerialization.hrl @@ -0,0 +1,82 @@ +%% Generated by the Erlang ASN.1 compiler. Version: 5.4.3 +%% Purpose: Erlang record definitions for each named and unnamed +%% SEQUENCE and SET, and macro definitions for each value +%% definition in module GajumaruSerialization. + +-ifndef(_GAJUMARUSERIALIZATION_HRL_). +-define(_GAJUMARUSERIALIZATION_HRL_, true). + +-record('GajumaruData', { + tag, + vsn, + content +}). + +-record('CompactStatic', { + tag, + vsn, + fields +}). + +-record('TemplateField', { + name = asn1_NOVALUE, + value +}). + +-record('KeyValue', { + key, + val +}). + +-record('Id', { + type, + value +}). + +-record('Account', { + foo, + bar +}). + +-record('SignedTx', { + signatures, + transaction +}). + +-record('ContractV1', { + sourceHash, + typeInfo, + byteCode +}). + +-record('ContractV2', { + sourceHash, + typeInfo, + byteCode, + compilerVersion +}). + +-record('ContractV3', { + sourceHash, + typeInfo, + byteCode, + compilerVersion, + payable +}). + +-record('TypeInfoV1', { + typeHash, + name, + argType, + outType +}). + +-record('TypeInfoV3', { + typeHash, + name, + payable, + argType, + outType +}). + +-endif. %% _GAJUMARUSERIALIZATION_HRL_ diff --git a/asn1_oer/GajumaruSerialization.asn b/asn1_oer/GajumaruSerialization.asn new file mode 100644 index 0000000..05e3b14 --- /dev/null +++ b/asn1_oer/GajumaruSerialization.asn @@ -0,0 +1,247 @@ +-- GajumaruSerialization.asn +-- +-- ASN.1 model for the structures serialized by gmserialization.erl +-- (the layer on top of RLP). +-- +-- Purpose: +-- * Provide a formal, toolable description of the data for portability +-- (other languages use ASN.1 compilers to get types/parsers). +-- * Define compact canonical wire format using standard ASN.1 techniques +-- (primarily Unaligned PER / UPER with constraints for packing). +-- * Static encoding only (templates from gmserialization). +-- * Legacy RLP compatibility is achieved via separate translation layer +-- (deferred in current focus). +-- +-- Detection of legacy vs new: +-- Legacy data (produced by gmserialization:serialize / gmser_chain_objects:serialize +-- or gmser_dyn:serialize) is always an RLP *list* at the top level. +-- This means the first byte is in the range 0xC0 .. 0xFF. +-- +-- DER-encoded data using the types below will start with 0x30 (SEQUENCE, +-- constructed, universal tag) for the outermost GajumaruData (or any +-- top-level SEQUENCE we define). 0x30 < 0xC0, so a single-byte prefix +-- check reliably distinguishes the two formats. +-- +-- Usage in Erlang (after compiling with asn1ct for compact wire): +-- {ok, Mod} = asn1ct:compile(GajumaruSerialization.asn, [uper]). +-- {ok, Bytes} = 'GajumaruSerialization':encode('GajumaruData', Asn1Value). +-- Bytes is the compact UPER wire format (deterministic with this schema). +-- For legacy RLP, use the model-to-RLP layer instead (see gmser_asn1_rlp). +-- +-- Notes on type mapping from gmserialization.erl: +-- - int -> INTEGER (new data uses canonical DER INTEGER) +-- - binary -> OCTET STRING +-- - bool -> BOOLEAN +-- - id -> Id (SEQUENCE) (cleaner than the legacy packed 33-byte form) +-- - [T] -> SEQUENCE OF T +-- - {T1,...} -> SEQUENCE (fixed-size, order matters) +-- - #{items := [{K,T},...]} -> SEQUENCE with the fields in template order +-- (static maps carry *values only*, no keys on the wire) +-- - tag + vsn are preserved as the first two fields for compatibility +-- with existing dispatch logic. +-- +-- Legacy integers had strict unsigned-minimal no-leading-zero (except for 0) +-- and RLP-level rules. New DER data does not need to follow those rules. +-- +-- WARNING: +-- Any cryptographic hash or signature computed over a serialized object +-- will change when switching from RLP to DER for that object. Plan a +-- coordinated upgrade. + +GajumaruSerialization DEFINITIONS + AUTOMATIC TAGS ::= +BEGIN + +EXPORTS ALL; + +-- ============================================================ +-- Top-level wrapper used for new DER data. +-- This is what a decoder will see first. +-- ============================================================ + +GajumaruData ::= SEQUENCE { + -- Constrained for better PER packing + tag INTEGER (0..65535), + vsn INTEGER (0..255), + content Content +} + +-- Preferred top-level for the compact static wire format. +-- Avoids the extra Content CHOICE tag when the structure is known to be static. +CompactStatic ::= SEQUENCE { + tag INTEGER (0..65535), + vsn INTEGER (0..255), + fields StaticFields +} + +-- Content can be a specific structured type (preferred) or a generic +-- representation of a template-driven object. +Content ::= CHOICE { + -- Generic fallback that can represent any [{Field, Type}] template + -- without having a pre-defined SEQUENCE for every object. + templateFields [0] TemplateFields, + + -- Static-optimized: no field names on wire (matches legacy static behavior exactly) + -- Preferred for compact wire format of known templates. + staticFields [10] StaticFields, + + -- Examples of concrete versioned types (extend as needed) + account [1] Account, + signedTx [2] SignedTx, + contract [3] ContractCode + -- Add more alternatives for other tags from gmser_chain_objects +} + +-- ============================================================ +-- Generic template-driven representation +-- (useful during transition or for unregistered types) +-- ============================================================ + +TemplateFields ::= SEQUENCE OF TemplateField + +TemplateField ::= SEQUENCE { + -- Field name is included for debuggability / generic processing. + -- In the original static encoding the name is NOT on the wire; + -- only position and type matter. We include it here for convenience. + name IA5String OPTIONAL, + value Value +} + +-- Optimized for static wire format: just the values in order, no names. +-- This matches the legacy static encoding where maps/records are positional only. +StaticFields ::= SEQUENCE OF Value + + +Value ::= CHOICE { + intValue [0] INTEGER, + boolValue [1] BOOLEAN, + binaryValue [2] OCTET STRING, + idValue [3] Id, + listValue [4] SEQUENCE OF Value, + tupleValue [5] SEQUENCE OF Value, + mapValue [6] SEQUENCE OF KeyValue -- only needed if you want to + -- represent dynamic-style maps +} + +KeyValue ::= SEQUENCE { + key Value, + val Value +} + +-- ============================================================ +-- Common types +-- ============================================================ + +Id ::= SEQUENCE { + -- Corresponds to the simple tags in gmser_id (account=1, name=2, etc.) + -- and the extended account subtype (high bit in legacy). + type INTEGER (0..255), + value OCTET STRING (SIZE (32)) +} + +-- ============================================================ +-- Concrete object examples (derived from usage in the codebase) +-- Add / evolve per version as you introduce new vsns. +-- ============================================================ + +-- Example: a very simple account-like object used in tests +Account ::= SEQUENCE { + foo INTEGER, + bar OCTET STRING +} + +-- Simplified signed transaction +SignedTx ::= SEQUENCE { + signatures SEQUENCE OF OCTET STRING, + transaction OCTET STRING +} + +-- Contract code objects (see gmser_contract_code.erl) +-- We model the three versions that exist today. +ContractCode ::= CHOICE { + v1 [0] ContractV1, + v2 [1] ContractV2, + v3 [2] ContractV3 +} + +ContractV1 ::= SEQUENCE { + sourceHash OCTET STRING, + -- typeInfo is a list of 4-tuples in legacy: + -- {typeHash, name, argType, outType} + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING +} + +ContractV2 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING, + compilerVersion OCTET STRING +} + +ContractV3 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV3, + byteCode OCTET STRING, + compilerVersion OCTET STRING, + payable BOOLEAN +} + +TypeInfoV1 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + argType OCTET STRING, + outType OCTET STRING +} + +TypeInfoV3 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + payable BOOLEAN, + argType OCTET STRING, + outType OCTET STRING +} + +-- ============================================================ +-- Notes for implementers +-- ============================================================ +-- 1. Detection (recommended decoder entry point): +-- +-- decode(Binary) -> +-- case Binary of +-- <> when B >= 16#C0 -> +-- decode_legacy_rlp(Binary); % existing gmser_* path +-- _ -> +-- {ok, Term} = +-- 'GajumaruSerialization':decode('GajumaruData', Binary), +-- Term +-- end. +-- +-- This works because: +-- - All current top-level output from serialize() is an RLP list +-- (first byte 0xC0-0xFF). +-- - GajumaruData and the concrete choices above are SEQUENCEs +-- (first byte 0x30 for short form, or 0x30 0x81/0x82... for long). +-- +-- 2. When you add a new object type or version, prefer adding a +-- concrete SEQUENCE alternative in the Content CHOICE rather than +-- always falling back to TemplateFields. This gives you better +-- validation and generated types. +-- +-- 3. For the compact wire format we use UPER (unaligned PER). +-- It is stable/deterministic for a given schema (no extensibility +-- markers on these types, fixed order). +-- +-- 4. INTEGER uses ASN.1 PER encoding (canonical for the constraints). +-- This may differ from legacy RLP minimal unsigned; new format +-- will have different hashes (expected when introducing new encoding). +-- +-- 5. Dynamic encoding (gmser_dyn) is not in scope here. +-- +-- 6. To generate the compact wire: +-- asn1ct:compile(GajumaruSerialization, [uper]). +-- {ok, CompactBytes} = 'GajumaruSerialization':encode('GajumaruData', Value). +-- +-- Use staticFields (not templateFields) for best compactness on static data. + +END diff --git a/asn1_oer/GajumaruSerialization.asn1db b/asn1_oer/GajumaruSerialization.asn1db new file mode 100644 index 0000000..558c2fd Binary files /dev/null and b/asn1_oer/GajumaruSerialization.asn1db differ diff --git a/asn1_oer/GajumaruSerialization.erl b/asn1_oer/GajumaruSerialization.erl new file mode 100644 index 0000000..d48bf9c --- /dev/null +++ b/asn1_oer/GajumaruSerialization.erl @@ -0,0 +1,1540 @@ +%% Generated by the Erlang ASN.1 BER compiler. Version: 5.4.3 +%% Purpose: Encoding and decoding of the types in GajumaruSerialization. + +-module('GajumaruSerialization'). +-moduledoc false. +-compile(nowarn_unused_vars). +-dialyzer(no_improper_lists). +-dialyzer(no_match). +-include("GajumaruSerialization.hrl"). +-asn1_info([{vsn,'5.4.3'}, + {module,'GajumaruSerialization'}, + {options,[oer,{outdir,"asn1_oer"},{i,"."},{i,"asn1_oer"}]}]). + +-export([encoding_rule/0,maps/0,bit_string_format/0, + legacy_erlang_types/0]). +-export(['dialyzer-suppressions'/1]). +-export([ +enc_GajumaruData/2, +enc_CompactStatic/2, +enc_Content/2, +enc_TemplateFields/2, +enc_TemplateField/2, +enc_StaticFields/2, +enc_Value/2, +enc_KeyValue/2, +enc_Id/2, +enc_Account/2, +enc_SignedTx/2, +enc_ContractCode/2, +enc_ContractV1/2, +enc_ContractV2/2, +enc_ContractV3/2, +enc_TypeInfoV1/2, +enc_TypeInfoV3/2 +]). + +-export([ +dec_GajumaruData/2, +dec_CompactStatic/2, +dec_Content/2, +dec_TemplateFields/2, +dec_TemplateField/2, +dec_StaticFields/2, +dec_Value/2, +dec_KeyValue/2, +dec_Id/2, +dec_Account/2, +dec_SignedTx/2, +dec_ContractCode/2, +dec_ContractV1/2, +dec_ContractV2/2, +dec_ContractV3/2, +dec_TypeInfoV1/2, +dec_TypeInfoV3/2 +]). + +-export([info/0]). + +-export([encode/2,decode/2]). + +encoding_rule() -> ber. + +maps() -> false. + +bit_string_format() -> bitstring. + +legacy_erlang_types() -> false. + +encode(Type, Data) -> +try iolist_to_binary(element(1, encode_disp(Type, Data))) of + Bytes -> + {ok,Bytes} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + + +decode(Type, Data) -> +try + Result = decode_disp(Type, element(1, ber_decode_nif(Data))), + {ok,Result} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + +encode_disp('GajumaruData', Data) -> enc_GajumaruData(Data); +encode_disp('CompactStatic', Data) -> enc_CompactStatic(Data); +encode_disp('Content', Data) -> enc_Content(Data); +encode_disp('TemplateFields', Data) -> enc_TemplateFields(Data); +encode_disp('TemplateField', Data) -> enc_TemplateField(Data); +encode_disp('StaticFields', Data) -> enc_StaticFields(Data); +encode_disp('Value', Data) -> enc_Value(Data); +encode_disp('KeyValue', Data) -> enc_KeyValue(Data); +encode_disp('Id', Data) -> enc_Id(Data); +encode_disp('Account', Data) -> enc_Account(Data); +encode_disp('SignedTx', Data) -> enc_SignedTx(Data); +encode_disp('ContractCode', Data) -> enc_ContractCode(Data); +encode_disp('ContractV1', Data) -> enc_ContractV1(Data); +encode_disp('ContractV2', Data) -> enc_ContractV2(Data); +encode_disp('ContractV3', Data) -> enc_ContractV3(Data); +encode_disp('TypeInfoV1', Data) -> enc_TypeInfoV1(Data); +encode_disp('TypeInfoV3', Data) -> enc_TypeInfoV3(Data); +encode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +decode_disp('GajumaruData', Data) -> dec_GajumaruData(Data); +decode_disp('CompactStatic', Data) -> dec_CompactStatic(Data); +decode_disp('Content', Data) -> dec_Content(Data); +decode_disp('TemplateFields', Data) -> dec_TemplateFields(Data); +decode_disp('TemplateField', Data) -> dec_TemplateField(Data); +decode_disp('StaticFields', Data) -> dec_StaticFields(Data); +decode_disp('Value', Data) -> dec_Value(Data); +decode_disp('KeyValue', Data) -> dec_KeyValue(Data); +decode_disp('Id', Data) -> dec_Id(Data); +decode_disp('Account', Data) -> dec_Account(Data); +decode_disp('SignedTx', Data) -> dec_SignedTx(Data); +decode_disp('ContractCode', Data) -> dec_ContractCode(Data); +decode_disp('ContractV1', Data) -> dec_ContractV1(Data); +decode_disp('ContractV2', Data) -> dec_ContractV2(Data); +decode_disp('ContractV3', Data) -> dec_ContractV3(Data); +decode_disp('TypeInfoV1', Data) -> dec_TypeInfoV1(Data); +decode_disp('TypeInfoV3', Data) -> dec_TypeInfoV3(Data); +decode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +info() -> + case ?MODULE:module_info(attributes) of + Attributes when is_list(Attributes) -> + case lists:keyfind(asn1_info, 1, Attributes) of + {_,Info} when is_list(Info) -> + Info; + _ -> + [] + end; + _ -> + [] + end. + + +%%================================ +%% GajumaruData +%%================================ +enc_GajumaruData(Val) -> + enc_GajumaruData(Val, [<<48>>]). + +enc_GajumaruData(Val, TagIn) -> +{_,Cindex1,Cindex2,Cindex3} = Val, + +%%------------------------------------------------- +%% attribute tag(1) with type INTEGER +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_integer(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute vsn(2) with type INTEGER +%%------------------------------------------------- + {EncBytes2,EncLen2} = encode_integer(Cindex2, [<<129>>]), + +%%------------------------------------------------- +%% attribute content(3) External GajumaruSerialization:Content +%%------------------------------------------------- + {EncBytes3,EncLen3} = 'enc_Content'(Cindex3, [<<162>>]), + + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], +LenSoFar = EncLen1 + EncLen2 + EncLen3, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + +dec_GajumaruData(Tlv) -> + dec_GajumaruData(Tlv, [16]). + +dec_GajumaruData(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute tag(1) with type INTEGER +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = begin +Val1 = decode_integer(V1, [131072]), +if 0 =< Val1, Val1 =< 65535 -> +Val1; +true -> +exit({error,{asn1,bad_range}}) +end +end, + +%%------------------------------------------------- +%% attribute vsn(2) with type INTEGER +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = begin +Val2 = decode_integer(V2, [131073]), +if 0 =< Val2, Val2 =< 255 -> +Val2; +true -> +exit({error,{asn1,bad_range}}) +end +end, + +%%------------------------------------------------- +%% attribute content(3) External GajumaruSerialization:Content +%%------------------------------------------------- +[V3|Tlv4] = Tlv3, +Term3 = 'dec_Content'(V3, [131074]), + +case Tlv4 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed +end, +Res1 = {'GajumaruData',Term1,Term2,Term3}, +Res1. + + +%%================================ +%% CompactStatic +%%================================ +enc_CompactStatic(Val) -> + enc_CompactStatic(Val, [<<48>>]). + +enc_CompactStatic(Val, TagIn) -> +{_,Cindex1,Cindex2,Cindex3} = Val, + +%%------------------------------------------------- +%% attribute tag(1) with type INTEGER +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_integer(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute vsn(2) with type INTEGER +%%------------------------------------------------- + {EncBytes2,EncLen2} = encode_integer(Cindex2, [<<129>>]), + +%%------------------------------------------------- +%% attribute fields(3) External GajumaruSerialization:StaticFields +%%------------------------------------------------- + {EncBytes3,EncLen3} = 'enc_StaticFields'(Cindex3, [<<162>>]), + + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], +LenSoFar = EncLen1 + EncLen2 + EncLen3, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + +dec_CompactStatic(Tlv) -> + dec_CompactStatic(Tlv, [16]). + +dec_CompactStatic(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute tag(1) with type INTEGER +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = begin +Val1 = decode_integer(V1, [131072]), +if 0 =< Val1, Val1 =< 65535 -> +Val1; +true -> +exit({error,{asn1,bad_range}}) +end +end, + +%%------------------------------------------------- +%% attribute vsn(2) with type INTEGER +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = begin +Val2 = decode_integer(V2, [131073]), +if 0 =< Val2, Val2 =< 255 -> +Val2; +true -> +exit({error,{asn1,bad_range}}) +end +end, + +%%------------------------------------------------- +%% attribute fields(3) External GajumaruSerialization:StaticFields +%%------------------------------------------------- +[V3|Tlv4] = Tlv3, +Term3 = 'dec_StaticFields'(V3, [131074]), + +case Tlv4 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed +end, +Res1 = {'CompactStatic',Term1,Term2,Term3}, +Res1. + + +%%================================ +%% Content +%%================================ +enc_Content(Val) -> + enc_Content(Val, []). + +enc_Content(Val, TagIn) -> + {EncBytes,EncLen} = case element(1,Val) of + templateFields -> + 'enc_TemplateFields'(element(2,Val), [<<160>>]); + staticFields -> + 'enc_StaticFields'(element(2,Val), [<<170>>]); + account -> + 'enc_Account'(element(2,Val), [<<161>>]); + signedTx -> + 'enc_SignedTx'(element(2,Val), [<<162>>]); + contract -> + 'enc_ContractCode'(element(2,Val), [<<163>>]); + Else -> + exit({error,{asn1,{invalid_choice_type,Else}}}) + end, + +encode_tags(TagIn, EncBytes, EncLen). + + + + +dec_Content(Tlv) -> + dec_Content(Tlv, []). + +dec_Content(Tlv, TagIn) -> +Tlv1 = match_tags(Tlv, TagIn), +case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of + +%% 'templateFields' + {131072, V1} -> + {templateFields, 'dec_TemplateFields'(V1, [])}; + + +%% 'staticFields' + {131082, V1} -> + {staticFields, 'dec_StaticFields'(V1, [])}; + + +%% 'account' + {131073, V1} -> + {account, 'dec_Account'(V1, [])}; + + +%% 'signedTx' + {131074, V1} -> + {signedTx, 'dec_SignedTx'(V1, [])}; + + +%% 'contract' + {131075, V1} -> + {contract, 'dec_ContractCode'(V1, [])}; + + Else -> + exit({error,{asn1,{invalid_choice_tag,Else}}}) + end +. + + +%%================================ +%% TemplateFields +%%================================ +enc_TemplateFields(Val) -> + enc_TemplateFields(Val, [<<48>>]). + +enc_TemplateFields(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_TemplateFields_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_TemplateFields_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_TemplateFields_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = 'enc_TemplateField'(H, [<<48>>]), + 'enc_TemplateFields_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + +dec_TemplateFields(Tlv) -> + dec_TemplateFields(Tlv, [16]). + +dec_TemplateFields(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +['dec_TemplateField'(V1, [16]) || V1 <- Tlv1]. + + + + +%%================================ +%% TemplateField +%%================================ +enc_TemplateField(Val) -> + enc_TemplateField(Val, [<<48>>]). + +enc_TemplateField(Val, TagIn) -> +{_,Cindex1,Cindex2} = Val, + +%%------------------------------------------------- +%% attribute name(1) with type IA5String OPTIONAL +%%------------------------------------------------- + {EncBytes1,EncLen1} = case Cindex1 of + asn1_NOVALUE -> {<<>>,0}; + _ -> + encode_restricted_string(Cindex1, [<<128>>]) + end, + +%%------------------------------------------------- +%% attribute value(2) External GajumaruSerialization:Value +%%------------------------------------------------- + {EncBytes2,EncLen2} = 'enc_Value'(Cindex2, [<<161>>]), + + BytesSoFar = [EncBytes1, EncBytes2], +LenSoFar = EncLen1 + EncLen2, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + +dec_TemplateField(Tlv) -> + dec_TemplateField(Tlv, [16]). + +dec_TemplateField(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute name(1) with type IA5String OPTIONAL +%%------------------------------------------------- +{Term1,Tlv2} = case Tlv1 of +[{131072,V1}|TempTlv2] -> + {begin +binary_to_list(decode_restricted_string(V1, [])) +end +, TempTlv2}; + _ -> + { asn1_NOVALUE, Tlv1} +end, + +%%------------------------------------------------- +%% attribute value(2) External GajumaruSerialization:Value +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = 'dec_Value'(V2, [131073]), + +case Tlv3 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed +end, +Res1 = {'TemplateField',Term1,Term2}, +Res1. + + +%%================================ +%% StaticFields +%%================================ +enc_StaticFields(Val) -> + enc_StaticFields(Val, [<<48>>]). + +enc_StaticFields(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_StaticFields_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_StaticFields_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_StaticFields_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = 'enc_Value'(H, []), + 'enc_StaticFields_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + +dec_StaticFields(Tlv) -> + dec_StaticFields(Tlv, [16]). + +dec_StaticFields(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +['dec_Value'(V1, []) || V1 <- Tlv1]. + + + + +%%================================ +%% Value +%%================================ +enc_Value(Val) -> + enc_Value(Val, []). + +enc_Value(Val, TagIn) -> + {EncBytes,EncLen} = case element(1,Val) of + intValue -> + encode_integer(element(2,Val), [<<128>>]); + boolValue -> + encode_boolean(element(2,Val), [<<129>>]); + binaryValue -> + encode_restricted_string(element(2,Val), [<<130>>]); + idValue -> + 'enc_Id'(element(2,Val), [<<163>>]); + listValue -> + 'enc_Value_listValue'(element(2,Val), [<<164>>]); + tupleValue -> + 'enc_Value_tupleValue'(element(2,Val), [<<165>>]); + mapValue -> + 'enc_Value_mapValue'(element(2,Val), [<<166>>]); + Else -> + exit({error,{asn1,{invalid_choice_type,Else}}}) + end, + +encode_tags(TagIn, EncBytes, EncLen). + + + + + +%%================================ +%% Value_listValue +%%================================ +enc_Value_listValue(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_Value_listValue_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_Value_listValue_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_Value_listValue_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = 'enc_Value'(H, []), + 'enc_Value_listValue_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + + +%%================================ +%% Value_tupleValue +%%================================ +enc_Value_tupleValue(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_Value_tupleValue_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_Value_tupleValue_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_Value_tupleValue_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = 'enc_Value'(H, []), + 'enc_Value_tupleValue_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + + +%%================================ +%% Value_mapValue +%%================================ +enc_Value_mapValue(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_Value_mapValue_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_Value_mapValue_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_Value_mapValue_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = 'enc_KeyValue'(H, [<<48>>]), + 'enc_Value_mapValue_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + +dec_Value(Tlv) -> + dec_Value(Tlv, []). + +dec_Value(Tlv, TagIn) -> +Tlv1 = match_tags(Tlv, TagIn), +case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of + +%% 'intValue' + {131072, V1} -> + {intValue, decode_integer(V1, [])}; + + +%% 'boolValue' + {131073, V1} -> + {boolValue, decode_boolean(V1, [])}; + + +%% 'binaryValue' + {131074, V1} -> + {binaryValue, decode_octet_string(V1, [])}; + + +%% 'idValue' + {131075, V1} -> + {idValue, 'dec_Id'(V1, [])}; + + +%% 'listValue' + {131076, V1} -> + {listValue, 'dec_Value_listValue'(V1, [])}; + + +%% 'tupleValue' + {131077, V1} -> + {tupleValue, 'dec_Value_tupleValue'(V1, [])}; + + +%% 'mapValue' + {131078, V1} -> + {mapValue, 'dec_Value_mapValue'(V1, [])}; + + Else -> + exit({error,{asn1,{invalid_choice_tag,Else}}}) + end +. +'dec_Value_listValue'(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +['dec_Value'(V1, []) || V1 <- Tlv1]. + + +'dec_Value_tupleValue'(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +['dec_Value'(V1, []) || V1 <- Tlv1]. + + +'dec_Value_mapValue'(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +['dec_KeyValue'(V1, [16]) || V1 <- Tlv1]. + + + + +%%================================ +%% KeyValue +%%================================ +enc_KeyValue(Val) -> + enc_KeyValue(Val, [<<48>>]). + +enc_KeyValue(Val, TagIn) -> +{_,Cindex1,Cindex2} = Val, + +%%------------------------------------------------- +%% attribute key(1) External GajumaruSerialization:Value +%%------------------------------------------------- + {EncBytes1,EncLen1} = 'enc_Value'(Cindex1, [<<160>>]), + +%%------------------------------------------------- +%% attribute val(2) External GajumaruSerialization:Value +%%------------------------------------------------- + {EncBytes2,EncLen2} = 'enc_Value'(Cindex2, [<<161>>]), + + BytesSoFar = [EncBytes1, EncBytes2], +LenSoFar = EncLen1 + EncLen2, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + +dec_KeyValue(Tlv) -> + dec_KeyValue(Tlv, [16]). + +dec_KeyValue(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute key(1) External GajumaruSerialization:Value +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = 'dec_Value'(V1, [131072]), + +%%------------------------------------------------- +%% attribute val(2) External GajumaruSerialization:Value +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = 'dec_Value'(V2, [131073]), + +case Tlv3 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed +end, +Res1 = {'KeyValue',Term1,Term2}, +Res1. + + +%%================================ +%% Id +%%================================ +enc_Id(Val) -> + enc_Id(Val, [<<48>>]). + +enc_Id(Val, TagIn) -> +{_,Cindex1,Cindex2} = Val, + +%%------------------------------------------------- +%% attribute type(1) with type INTEGER +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_integer(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute value(2) with type OCTET STRING +%%------------------------------------------------- + {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]), + + BytesSoFar = [EncBytes1, EncBytes2], +LenSoFar = EncLen1 + EncLen2, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + +dec_Id(Tlv) -> + dec_Id(Tlv, [16]). + +dec_Id(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute type(1) with type INTEGER +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = begin +Val1 = decode_integer(V1, [131072]), +if 0 =< Val1, Val1 =< 255 -> +Val1; +true -> +exit({error,{asn1,bad_range}}) +end +end, + +%%------------------------------------------------- +%% attribute value(2) with type OCTET STRING +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = begin +Val2 = decode_octet_string(V2, [131073]), +C1 = byte_size(Val2), +if C1 =:= 32 -> +Val2; +true -> +exit({error,{asn1,bad_range}}) +end +end, + +case Tlv3 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed +end, +Res1 = {'Id',Term1,Term2}, +Res1. + + +%%================================ +%% Account +%%================================ +enc_Account(Val) -> + enc_Account(Val, [<<48>>]). + +enc_Account(Val, TagIn) -> +{_,Cindex1,Cindex2} = Val, + +%%------------------------------------------------- +%% attribute foo(1) with type INTEGER +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_integer(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute bar(2) with type OCTET STRING +%%------------------------------------------------- + {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]), + + BytesSoFar = [EncBytes1, EncBytes2], +LenSoFar = EncLen1 + EncLen2, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + +dec_Account(Tlv) -> + dec_Account(Tlv, [16]). + +dec_Account(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute foo(1) with type INTEGER +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = decode_integer(V1, [131072]), + +%%------------------------------------------------- +%% attribute bar(2) with type OCTET STRING +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = decode_octet_string(V2, [131073]), + +case Tlv3 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed +end, +Res1 = {'Account',Term1,Term2}, +Res1. + + +%%================================ +%% SignedTx +%%================================ +enc_SignedTx(Val) -> + enc_SignedTx(Val, [<<48>>]). + +enc_SignedTx(Val, TagIn) -> +{_,Cindex1,Cindex2} = Val, + +%%------------------------------------------------- +%% attribute signatures(1) with type SEQUENCE OF +%%------------------------------------------------- + {EncBytes1,EncLen1} = 'enc_SignedTx_signatures'(Cindex1, [<<160>>]), + +%%------------------------------------------------- +%% attribute transaction(2) with type OCTET STRING +%%------------------------------------------------- + {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]), + + BytesSoFar = [EncBytes1, EncBytes2], +LenSoFar = EncLen1 + EncLen2, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + + +%%================================ +%% SignedTx_signatures +%%================================ +enc_SignedTx_signatures(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_SignedTx_signatures_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_SignedTx_signatures_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_SignedTx_signatures_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = encode_restricted_string(H, [<<4>>]), + 'enc_SignedTx_signatures_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + +dec_SignedTx(Tlv) -> + dec_SignedTx(Tlv, [16]). + +dec_SignedTx(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute signatures(1) with type SEQUENCE OF +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = 'dec_SignedTx_signatures'(V1, [131072]), + +%%------------------------------------------------- +%% attribute transaction(2) with type OCTET STRING +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = decode_octet_string(V2, [131073]), + +case Tlv3 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv3}}}) % extra fields not allowed +end, +Res1 = {'SignedTx',Term1,Term2}, +Res1. +'dec_SignedTx_signatures'(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +[decode_octet_string(V1, [4]) || V1 <- Tlv1]. + + + + +%%================================ +%% ContractCode +%%================================ +enc_ContractCode(Val) -> + enc_ContractCode(Val, []). + +enc_ContractCode(Val, TagIn) -> + {EncBytes,EncLen} = case element(1,Val) of + v1 -> + 'enc_ContractV1'(element(2,Val), [<<160>>]); + v2 -> + 'enc_ContractV2'(element(2,Val), [<<161>>]); + v3 -> + 'enc_ContractV3'(element(2,Val), [<<162>>]); + Else -> + exit({error,{asn1,{invalid_choice_type,Else}}}) + end, + +encode_tags(TagIn, EncBytes, EncLen). + + + + +dec_ContractCode(Tlv) -> + dec_ContractCode(Tlv, []). + +dec_ContractCode(Tlv, TagIn) -> +Tlv1 = match_tags(Tlv, TagIn), +case (case Tlv1 of [CtempTlv1] -> CtempTlv1; _ -> Tlv1 end) of + +%% 'v1' + {131072, V1} -> + {v1, 'dec_ContractV1'(V1, [])}; + + +%% 'v2' + {131073, V1} -> + {v2, 'dec_ContractV2'(V1, [])}; + + +%% 'v3' + {131074, V1} -> + {v3, 'dec_ContractV3'(V1, [])}; + + Else -> + exit({error,{asn1,{invalid_choice_tag,Else}}}) + end +. + + +%%================================ +%% ContractV1 +%%================================ +enc_ContractV1(Val) -> + enc_ContractV1(Val, [<<48>>]). + +enc_ContractV1(Val, TagIn) -> +{_,Cindex1,Cindex2,Cindex3} = Val, + +%%------------------------------------------------- +%% attribute sourceHash(1) with type OCTET STRING +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute typeInfo(2) with type SEQUENCE OF +%%------------------------------------------------- + {EncBytes2,EncLen2} = 'enc_ContractV1_typeInfo'(Cindex2, [<<161>>]), + +%%------------------------------------------------- +%% attribute byteCode(3) with type OCTET STRING +%%------------------------------------------------- + {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<130>>]), + + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3], +LenSoFar = EncLen1 + EncLen2 + EncLen3, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + + +%%================================ +%% ContractV1_typeInfo +%%================================ +enc_ContractV1_typeInfo(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_ContractV1_typeInfo_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_ContractV1_typeInfo_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_ContractV1_typeInfo_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = 'enc_TypeInfoV1'(H, [<<48>>]), + 'enc_ContractV1_typeInfo_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + +dec_ContractV1(Tlv) -> + dec_ContractV1(Tlv, [16]). + +dec_ContractV1(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute sourceHash(1) with type OCTET STRING +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = decode_octet_string(V1, [131072]), + +%%------------------------------------------------- +%% attribute typeInfo(2) with type SEQUENCE OF +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = 'dec_ContractV1_typeInfo'(V2, [131073]), + +%%------------------------------------------------- +%% attribute byteCode(3) with type OCTET STRING +%%------------------------------------------------- +[V3|Tlv4] = Tlv3, +Term3 = decode_octet_string(V3, [131074]), + +case Tlv4 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv4}}}) % extra fields not allowed +end, +Res1 = {'ContractV1',Term1,Term2,Term3}, +Res1. +'dec_ContractV1_typeInfo'(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +['dec_TypeInfoV1'(V1, [16]) || V1 <- Tlv1]. + + + + +%%================================ +%% ContractV2 +%%================================ +enc_ContractV2(Val) -> + enc_ContractV2(Val, [<<48>>]). + +enc_ContractV2(Val, TagIn) -> +{_,Cindex1,Cindex2,Cindex3,Cindex4} = Val, + +%%------------------------------------------------- +%% attribute sourceHash(1) with type OCTET STRING +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute typeInfo(2) with type SEQUENCE OF +%%------------------------------------------------- + {EncBytes2,EncLen2} = 'enc_ContractV2_typeInfo'(Cindex2, [<<161>>]), + +%%------------------------------------------------- +%% attribute byteCode(3) with type OCTET STRING +%%------------------------------------------------- + {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<130>>]), + +%%------------------------------------------------- +%% attribute compilerVersion(4) with type OCTET STRING +%%------------------------------------------------- + {EncBytes4,EncLen4} = encode_restricted_string(Cindex4, [<<131>>]), + + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4], +LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + + +%%================================ +%% ContractV2_typeInfo +%%================================ +enc_ContractV2_typeInfo(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_ContractV2_typeInfo_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_ContractV2_typeInfo_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_ContractV2_typeInfo_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = 'enc_TypeInfoV1'(H, [<<48>>]), + 'enc_ContractV2_typeInfo_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + +dec_ContractV2(Tlv) -> + dec_ContractV2(Tlv, [16]). + +dec_ContractV2(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute sourceHash(1) with type OCTET STRING +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = decode_octet_string(V1, [131072]), + +%%------------------------------------------------- +%% attribute typeInfo(2) with type SEQUENCE OF +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = 'dec_ContractV2_typeInfo'(V2, [131073]), + +%%------------------------------------------------- +%% attribute byteCode(3) with type OCTET STRING +%%------------------------------------------------- +[V3|Tlv4] = Tlv3, +Term3 = decode_octet_string(V3, [131074]), + +%%------------------------------------------------- +%% attribute compilerVersion(4) with type OCTET STRING +%%------------------------------------------------- +[V4|Tlv5] = Tlv4, +Term4 = decode_octet_string(V4, [131075]), + +case Tlv5 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv5}}}) % extra fields not allowed +end, +Res1 = {'ContractV2',Term1,Term2,Term3,Term4}, +Res1. +'dec_ContractV2_typeInfo'(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +['dec_TypeInfoV1'(V1, [16]) || V1 <- Tlv1]. + + + + +%%================================ +%% ContractV3 +%%================================ +enc_ContractV3(Val) -> + enc_ContractV3(Val, [<<48>>]). + +enc_ContractV3(Val, TagIn) -> +{_,Cindex1,Cindex2,Cindex3,Cindex4,Cindex5} = Val, + +%%------------------------------------------------- +%% attribute sourceHash(1) with type OCTET STRING +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute typeInfo(2) with type SEQUENCE OF +%%------------------------------------------------- + {EncBytes2,EncLen2} = 'enc_ContractV3_typeInfo'(Cindex2, [<<161>>]), + +%%------------------------------------------------- +%% attribute byteCode(3) with type OCTET STRING +%%------------------------------------------------- + {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<130>>]), + +%%------------------------------------------------- +%% attribute compilerVersion(4) with type OCTET STRING +%%------------------------------------------------- + {EncBytes4,EncLen4} = encode_restricted_string(Cindex4, [<<131>>]), + +%%------------------------------------------------- +%% attribute payable(5) with type BOOLEAN +%%------------------------------------------------- + {EncBytes5,EncLen5} = encode_boolean(Cindex5, [<<132>>]), + + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5], +LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + + +%%================================ +%% ContractV3_typeInfo +%%================================ +enc_ContractV3_typeInfo(Val, TagIn) -> + {EncBytes,EncLen} = 'enc_ContractV3_typeInfo_components'(Val,[],0), + encode_tags(TagIn, EncBytes, EncLen). + +'enc_ContractV3_typeInfo_components'([], AccBytes, AccLen) -> + {lists:reverse(AccBytes),AccLen}; + +'enc_ContractV3_typeInfo_components'([H|T],AccBytes, AccLen) -> + {EncBytes,EncLen} = 'enc_TypeInfoV3'(H, [<<48>>]), + 'enc_ContractV3_typeInfo_components'(T,[EncBytes|AccBytes], AccLen + EncLen). + + + +dec_ContractV3(Tlv) -> + dec_ContractV3(Tlv, [16]). + +dec_ContractV3(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute sourceHash(1) with type OCTET STRING +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = decode_octet_string(V1, [131072]), + +%%------------------------------------------------- +%% attribute typeInfo(2) with type SEQUENCE OF +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = 'dec_ContractV3_typeInfo'(V2, [131073]), + +%%------------------------------------------------- +%% attribute byteCode(3) with type OCTET STRING +%%------------------------------------------------- +[V3|Tlv4] = Tlv3, +Term3 = decode_octet_string(V3, [131074]), + +%%------------------------------------------------- +%% attribute compilerVersion(4) with type OCTET STRING +%%------------------------------------------------- +[V4|Tlv5] = Tlv4, +Term4 = decode_octet_string(V4, [131075]), + +%%------------------------------------------------- +%% attribute payable(5) with type BOOLEAN +%%------------------------------------------------- +[V5|Tlv6] = Tlv5, +Term5 = decode_boolean(V5, [131076]), + +case Tlv6 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv6}}}) % extra fields not allowed +end, +Res1 = {'ContractV3',Term1,Term2,Term3,Term4,Term5}, +Res1. +'dec_ContractV3_typeInfo'(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), +['dec_TypeInfoV3'(V1, [16]) || V1 <- Tlv1]. + + + + +%%================================ +%% TypeInfoV1 +%%================================ +enc_TypeInfoV1(Val) -> + enc_TypeInfoV1(Val, [<<48>>]). + +enc_TypeInfoV1(Val, TagIn) -> +{_,Cindex1,Cindex2,Cindex3,Cindex4} = Val, + +%%------------------------------------------------- +%% attribute typeHash(1) with type OCTET STRING +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute name(2) with type OCTET STRING +%%------------------------------------------------- + {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]), + +%%------------------------------------------------- +%% attribute argType(3) with type OCTET STRING +%%------------------------------------------------- + {EncBytes3,EncLen3} = encode_restricted_string(Cindex3, [<<130>>]), + +%%------------------------------------------------- +%% attribute outType(4) with type OCTET STRING +%%------------------------------------------------- + {EncBytes4,EncLen4} = encode_restricted_string(Cindex4, [<<131>>]), + + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4], +LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + +dec_TypeInfoV1(Tlv) -> + dec_TypeInfoV1(Tlv, [16]). + +dec_TypeInfoV1(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute typeHash(1) with type OCTET STRING +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = decode_octet_string(V1, [131072]), + +%%------------------------------------------------- +%% attribute name(2) with type OCTET STRING +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = decode_octet_string(V2, [131073]), + +%%------------------------------------------------- +%% attribute argType(3) with type OCTET STRING +%%------------------------------------------------- +[V3|Tlv4] = Tlv3, +Term3 = decode_octet_string(V3, [131074]), + +%%------------------------------------------------- +%% attribute outType(4) with type OCTET STRING +%%------------------------------------------------- +[V4|Tlv5] = Tlv4, +Term4 = decode_octet_string(V4, [131075]), + +case Tlv5 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv5}}}) % extra fields not allowed +end, +Res1 = {'TypeInfoV1',Term1,Term2,Term3,Term4}, +Res1. + + +%%================================ +%% TypeInfoV3 +%%================================ +enc_TypeInfoV3(Val) -> + enc_TypeInfoV3(Val, [<<48>>]). + +enc_TypeInfoV3(Val, TagIn) -> +{_,Cindex1,Cindex2,Cindex3,Cindex4,Cindex5} = Val, + +%%------------------------------------------------- +%% attribute typeHash(1) with type OCTET STRING +%%------------------------------------------------- + {EncBytes1,EncLen1} = encode_restricted_string(Cindex1, [<<128>>]), + +%%------------------------------------------------- +%% attribute name(2) with type OCTET STRING +%%------------------------------------------------- + {EncBytes2,EncLen2} = encode_restricted_string(Cindex2, [<<129>>]), + +%%------------------------------------------------- +%% attribute payable(3) with type BOOLEAN +%%------------------------------------------------- + {EncBytes3,EncLen3} = encode_boolean(Cindex3, [<<130>>]), + +%%------------------------------------------------- +%% attribute argType(4) with type OCTET STRING +%%------------------------------------------------- + {EncBytes4,EncLen4} = encode_restricted_string(Cindex4, [<<131>>]), + +%%------------------------------------------------- +%% attribute outType(5) with type OCTET STRING +%%------------------------------------------------- + {EncBytes5,EncLen5} = encode_restricted_string(Cindex5, [<<132>>]), + + BytesSoFar = [EncBytes1, EncBytes2, EncBytes3, EncBytes4, EncBytes5], +LenSoFar = EncLen1 + EncLen2 + EncLen3 + EncLen4 + EncLen5, +encode_tags(TagIn, BytesSoFar, LenSoFar). + + +dec_TypeInfoV3(Tlv) -> + dec_TypeInfoV3(Tlv, [16]). + +dec_TypeInfoV3(Tlv, TagIn) -> + %%------------------------------------------------- + %% decode tag and length + %%------------------------------------------------- +Tlv1 = match_tags(Tlv, TagIn), + +%%------------------------------------------------- +%% attribute typeHash(1) with type OCTET STRING +%%------------------------------------------------- +[V1|Tlv2] = Tlv1, +Term1 = decode_octet_string(V1, [131072]), + +%%------------------------------------------------- +%% attribute name(2) with type OCTET STRING +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = decode_octet_string(V2, [131073]), + +%%------------------------------------------------- +%% attribute payable(3) with type BOOLEAN +%%------------------------------------------------- +[V3|Tlv4] = Tlv3, +Term3 = decode_boolean(V3, [131074]), + +%%------------------------------------------------- +%% attribute argType(4) with type OCTET STRING +%%------------------------------------------------- +[V4|Tlv5] = Tlv4, +Term4 = decode_octet_string(V4, [131075]), + +%%------------------------------------------------- +%% attribute outType(5) with type OCTET STRING +%%------------------------------------------------- +[V5|Tlv6] = Tlv5, +Term5 = decode_octet_string(V5, [131076]), + +case Tlv6 of +[] -> true;_ -> exit({error,{asn1, {unexpected,Tlv6}}}) % extra fields not allowed +end, +Res1 = {'TypeInfoV3',Term1,Term2,Term3,Term4,Term5}, +Res1. + +%%% +%%% Run-time functions. +%%% + +'dialyzer-suppressions'(Arg) -> + ok. + +ber_decode_nif(B) -> + asn1rt_nif:decode_ber_tlv(B). + +collect_parts(TlvList) -> + collect_parts(TlvList, []). + +collect_parts([{_, L} | Rest], Acc) when is_list(L) -> + collect_parts(Rest, [collect_parts(L) | Acc]); +collect_parts([{3, <>} | Rest], _Acc) -> + collect_parts_bit(Rest, [Bits], Unused); +collect_parts([{_T, V} | Rest], Acc) -> + collect_parts(Rest, [V | Acc]); +collect_parts([], Acc) -> + list_to_binary(lists:reverse(Acc)). + +collect_parts_bit([{3, <>} | Rest], Acc, Uacc) -> + collect_parts_bit(Rest, [Bits | Acc], Unused + Uacc); +collect_parts_bit([], Acc, Uacc) -> + list_to_binary([Uacc | lists:reverse(Acc)]). + +decode_boolean(Tlv, TagIn) -> + Val = match_tags(Tlv, TagIn), + case Val of + <<0:8>> -> + false; + <<_:8>> -> + true; + _ -> + exit({error, {asn1, {decode_boolean, Val}}}) + end. + +decode_integer(Tlv, TagIn) -> + Bin = match_tags(Tlv, TagIn), + Len = byte_size(Bin), + <> = Bin, + Int. + +decode_octet_string(Tlv, TagsIn) -> + Bin = match_and_collect(Tlv, TagsIn), + binary:copy(Bin). + +decode_restricted_string(Tlv, TagsIn) -> + match_and_collect(Tlv, TagsIn). + +encode_boolean(true, TagIn) -> + encode_tags(TagIn, [255], 1); +encode_boolean(false, TagIn) -> + encode_tags(TagIn, [0], 1); +encode_boolean(X, _) -> + exit({error, {asn1, {encode_boolean, X}}}). + +encode_integer(Val) -> + Bytes = + if + Val >= 0 -> + encode_integer_pos(Val, []); + true -> + encode_integer_neg(Val, []) + end, + {Bytes, length(Bytes)}. + +encode_integer(Val, Tag) when is_integer(Val) -> + encode_tags(Tag, encode_integer(Val)); +encode_integer(Val, _Tag) -> + exit({error, {asn1, {encode_integer, Val}}}). + +encode_integer_neg(-1, [B1 | _T] = L) when B1 > 127 -> + L; +encode_integer_neg(N, Acc) -> + encode_integer_neg(N bsr 8, [N band 255 | Acc]). + +encode_integer_pos(0, [B | _Acc] = L) when B < 128 -> + L; +encode_integer_pos(N, Acc) -> + encode_integer_pos(N bsr 8, [N band 255 | Acc]). + +encode_length(L) when L =< 127 -> + {[L], 1}; +encode_length(L) -> + Oct = minimum_octets(L), + Len = length(Oct), + if + Len =< 126 -> + {[128 bor Len | Oct], Len + 1}; + true -> + exit({error, {asn1, too_long_length_oct, Len}}) + end. + +encode_restricted_string(OctetList, TagIn) when is_binary(OctetList) -> + encode_tags(TagIn, OctetList, byte_size(OctetList)); +encode_restricted_string(OctetList, TagIn) when is_list(OctetList) -> + encode_tags(TagIn, OctetList, length(OctetList)). + +encode_tags(TagIn, {BytesSoFar, LenSoFar}) -> + encode_tags(TagIn, BytesSoFar, LenSoFar). + +encode_tags([Tag | Trest], BytesSoFar, LenSoFar) -> + {Bytes2, L2} = encode_length(LenSoFar), + encode_tags(Trest, + [Tag, Bytes2 | BytesSoFar], + LenSoFar + byte_size(Tag) + L2); +encode_tags([], BytesSoFar, LenSoFar) -> + {BytesSoFar, LenSoFar}. + +match_and_collect(Tlv, TagsIn) -> + Val = match_tags(Tlv, TagsIn), + case Val of + [_ | _] = PartList -> + collect_parts(PartList); + Bin when is_binary(Bin) -> + Bin + end. + +match_tags({T, V}, [T]) -> + V; +match_tags({T, V}, [T | Tt]) -> + match_tags(V, Tt); +match_tags([{T, V}], [T | Tt]) -> + match_tags(V, Tt); +match_tags([{T, _V} | _] = Vlist, [T]) -> + Vlist; +match_tags(Tlv, []) -> + Tlv; +match_tags({Tag, _V} = Tlv, [T | _Tt]) -> + exit({error, {asn1, {wrong_tag, {{expected, T}, {got, Tag, Tlv}}}}}). + +minimum_octets(0, Acc) -> + Acc; +minimum_octets(Val, Acc) -> + minimum_octets(Val bsr 8, [Val band 255 | Acc]). + +minimum_octets(Val) -> + minimum_octets(Val, []). diff --git a/asn1_oer/GajumaruSerialization.hrl b/asn1_oer/GajumaruSerialization.hrl new file mode 100644 index 0000000..9d7d397 --- /dev/null +++ b/asn1_oer/GajumaruSerialization.hrl @@ -0,0 +1,82 @@ +%% Generated by the Erlang ASN.1 compiler. Version: 5.4.3 +%% Purpose: Erlang record definitions for each named and unnamed +%% SEQUENCE and SET, and macro definitions for each value +%% definition in module GajumaruSerialization. + +-ifndef(_GAJUMARUSERIALIZATION_HRL_). +-define(_GAJUMARUSERIALIZATION_HRL_, true). + +-record('GajumaruData', { + tag, + vsn, + content +}). + +-record('CompactStatic', { + tag, + vsn, + fields +}). + +-record('TemplateField', { + name = asn1_NOVALUE, + value +}). + +-record('KeyValue', { + key, + val +}). + +-record('Id', { + type, + value +}). + +-record('Account', { + foo, + bar +}). + +-record('SignedTx', { + signatures, + transaction +}). + +-record('ContractV1', { + sourceHash, + typeInfo, + byteCode +}). + +-record('ContractV2', { + sourceHash, + typeInfo, + byteCode, + compilerVersion +}). + +-record('ContractV3', { + sourceHash, + typeInfo, + byteCode, + compilerVersion, + payable +}). + +-record('TypeInfoV1', { + typeHash, + name, + argType, + outType +}). + +-record('TypeInfoV3', { + typeHash, + name, + payable, + argType, + outType +}). + +-endif. %% _GAJUMARUSERIALIZATION_HRL_ diff --git a/asn1_optimized/GajumaruSerialization.asn b/asn1_optimized/GajumaruSerialization.asn new file mode 100644 index 0000000..ca7d742 --- /dev/null +++ b/asn1_optimized/GajumaruSerialization.asn @@ -0,0 +1,235 @@ +-- GajumaruSerialization.asn +-- +-- ASN.1 model for the structures serialized by gmserialization.erl +-- (the layer on top of RLP). +-- +-- Purpose: +-- * Provide a formal, toolable description of the data. +-- * Enable migration from the legacy RLP-based format to DER. +-- +-- Detection of legacy vs new: +-- Legacy data (produced by gmserialization:serialize / gmser_chain_objects:serialize +-- or gmser_dyn:serialize) is always an RLP *list* at the top level. +-- This means the first byte is in the range 0xC0 .. 0xFF. +-- +-- DER-encoded data using the types below will start with 0x30 (SEQUENCE, +-- constructed, universal tag) for the outermost GajumaruData (or any +-- top-level SEQUENCE we define). 0x30 < 0xC0, so a single-byte prefix +-- check reliably distinguishes the two formats. +-- +-- Usage in Erlang (after compiling with asn1ct): +-- {ok, Mod} = asn1ct:compile(GajumaruSerialization.asn, [ber, der]). +-- {ok, Term} = 'GajumaruSerialization':decode('GajumaruData', DerBinary). +-- +-- Notes on type mapping from gmserialization.erl: +-- - int -> INTEGER (new data uses canonical DER INTEGER) +-- - binary -> OCTET STRING +-- - bool -> BOOLEAN +-- - id -> Id (SEQUENCE) (cleaner than the legacy packed 33-byte form) +-- - [T] -> SEQUENCE OF T +-- - {T1,...} -> SEQUENCE (fixed-size, order matters) +-- - #{items := [{K,T},...]} -> SEQUENCE with the fields in template order +-- (static maps carry *values only*, no keys on the wire) +-- - tag + vsn are preserved as the first two fields for compatibility +-- with existing dispatch logic. +-- +-- Legacy integers had strict unsigned-minimal no-leading-zero (except for 0) +-- and RLP-level rules. New DER data does not need to follow those rules. +-- +-- WARNING: +-- Any cryptographic hash or signature computed over a serialized object +-- will change when switching from RLP to DER for that object. Plan a +-- coordinated upgrade. + +GajumaruSerialization DEFINITIONS + AUTOMATIC TAGS ::= +BEGIN + +EXPORTS ALL; + +-- ============================================================ +-- Top-level wrapper used for new DER data. +-- This is what a decoder will see first. +-- ============================================================ + +GajumaruData ::= SEQUENCE { + -- Constrained for better PER packing + tag INTEGER (0..65535), + vsn INTEGER (0..255), + content Content +} + +-- Content can be a specific structured type (preferred) or a generic +-- representation of a template-driven object. +Content ::= CHOICE { + -- Generic fallback that can represent any [{Field, Type}] template + -- without having a pre-defined SEQUENCE for every object. + templateFields [0] TemplateFields, + + -- Static-optimized: no field names on wire (matches legacy static behavior exactly) + -- Preferred for compact wire format of known templates. + staticFields [10] StaticFields, + + -- Examples of concrete versioned types (extend as needed) + account [1] Account, + signedTx [2] SignedTx, + contract [3] ContractCode + -- Add more alternatives for other tags from gmser_chain_objects +} + +-- ============================================================ +-- Generic template-driven representation +-- (useful during transition or for unregistered types) +-- ============================================================ + +TemplateFields ::= SEQUENCE OF TemplateField + +TemplateField ::= SEQUENCE { + -- Field name is included for debuggability / generic processing. + -- In the original static encoding the name is NOT on the wire; + -- only position and type matter. We include it here for convenience. + name IA5String OPTIONAL, + value Value +} + +-- Optimized for static wire format: just the values in order, no names. +-- This matches the legacy static encoding where maps/records are positional only. +StaticFields ::= SEQUENCE OF Value + + +Value ::= CHOICE { + intValue [0] INTEGER, + boolValue [1] BOOLEAN, + binaryValue [2] OCTET STRING, + idValue [3] Id, + listValue [4] SEQUENCE OF Value, + tupleValue [5] SEQUENCE OF Value, + mapValue [6] SEQUENCE OF KeyValue -- only needed if you want to + -- represent dynamic-style maps +} + +KeyValue ::= SEQUENCE { + key Value, + val Value +} + +-- ============================================================ +-- Common types +-- ============================================================ + +Id ::= SEQUENCE { + -- Corresponds to the simple tags in gmser_id (account=1, name=2, etc.) + -- and the extended account subtype (high bit in legacy). + type INTEGER (0..255), + value OCTET STRING (SIZE (32)) +} + +-- ============================================================ +-- Concrete object examples (derived from usage in the codebase) +-- Add / evolve per version as you introduce new vsns. +-- ============================================================ + +-- Example: a very simple account-like object used in tests +Account ::= SEQUENCE { + foo INTEGER, + bar OCTET STRING +} + +-- Simplified signed transaction +SignedTx ::= SEQUENCE { + signatures SEQUENCE OF OCTET STRING, + transaction OCTET STRING +} + +-- Contract code objects (see gmser_contract_code.erl) +-- We model the three versions that exist today. +ContractCode ::= CHOICE { + v1 [0] ContractV1, + v2 [1] ContractV2, + v3 [2] ContractV3 +} + +ContractV1 ::= SEQUENCE { + sourceHash OCTET STRING, + -- typeInfo is a list of 4-tuples in legacy: + -- {typeHash, name, argType, outType} + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING +} + +ContractV2 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING, + compilerVersion OCTET STRING +} + +ContractV3 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV3, + byteCode OCTET STRING, + compilerVersion OCTET STRING, + payable BOOLEAN +} + +TypeInfoV1 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + argType OCTET STRING, + outType OCTET STRING +} + +TypeInfoV3 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + payable BOOLEAN, + argType OCTET STRING, + outType OCTET STRING +} + +-- ============================================================ +-- Notes for implementers +-- ============================================================ +-- 1. Detection (recommended decoder entry point): +-- +-- decode(Binary) -> +-- case Binary of +-- <> when B >= 16#C0 -> +-- decode_legacy_rlp(Binary); % existing gmser_* path +-- _ -> +-- {ok, Term} = +-- 'GajumaruSerialization':decode('GajumaruData', Binary), +-- Term +-- end. +-- +-- This works because: +-- - All current top-level output from serialize() is an RLP list +-- (first byte 0xC0-0xFF). +-- - GajumaruData and the concrete choices above are SEQUENCEs +-- (first byte 0x30 for short form, or 0x30 0x81/0x82... for long). +-- +-- 2. When you add a new object type or version, prefer adding a +-- concrete SEQUENCE alternative in the Content CHOICE rather than +-- always falling back to TemplateFields. This gives you better +-- validation and generated types. +-- +-- 3. INTEGER in DER is signed and uses a different minimal encoding +-- than the legacy unsigned big-endian no leading zero form. This is +-- fine for new data. +-- +-- 4. If you need to preserve exact legacy integer wire bytes inside +-- the new format (e.g. for some hash preimage reason), you can +-- carry selected integers as OCTET STRING (legacy unsigned minimal bytes). +-- +-- 5. Dynamic encoding (gmser_dyn) is intentionally not modeled here +-- in full, because it is runtime-schema driven (type codes 246-255, +-- labels, alt/switch, etc.). You can still use the generic +-- TemplateFields + Value for some dynamic cases, or model specific +-- message schemas as additional CHOICE arms. +-- +-- 6. Compile with DER for canonical output: +-- asn1ct:compile(GajumaruSerialization, [der]). +-- +-- The ber option is also accepted; der implies the stricter rules. + +END diff --git a/asn1_optimized/GajumaruSerialization.asn1db b/asn1_optimized/GajumaruSerialization.asn1db new file mode 100644 index 0000000..3824998 Binary files /dev/null and b/asn1_optimized/GajumaruSerialization.asn1db differ diff --git a/asn1_optimized/GajumaruSerialization.erl b/asn1_optimized/GajumaruSerialization.erl new file mode 100644 index 0000000..ad83e9b --- /dev/null +++ b/asn1_optimized/GajumaruSerialization.erl @@ -0,0 +1,1684 @@ +%% Generated by the Erlang ASN.1 PER (unaligned) compiler. Version: 5.4.3 +%% Purpose: Encoding and decoding of the types in GajumaruSerialization. + +-module('GajumaruSerialization'). +-moduledoc false. +-compile(nowarn_unused_vars). +-dialyzer(no_improper_lists). +-dialyzer(no_match). +-include("GajumaruSerialization.hrl"). +-asn1_info([{vsn,'5.4.3'}, + {module,'GajumaruSerialization'}, + {options,[uper,{outdir,"asn1_optimized"},{i,"."},{i,"asn1_optimized"}]}]). + +-export([encoding_rule/0,maps/0,bit_string_format/0, + legacy_erlang_types/0]). +-export(['dialyzer-suppressions'/1]). +-export([ +enc_GajumaruData/1, +enc_Content/1, +enc_TemplateFields/1, +enc_TemplateField/1, +enc_StaticFields/1, +enc_Value/1, +enc_KeyValue/1, +enc_Id/1, +enc_Account/1, +enc_SignedTx/1, +enc_ContractCode/1, +enc_ContractV1/1, +enc_ContractV2/1, +enc_ContractV3/1, +enc_TypeInfoV1/1, +enc_TypeInfoV3/1 +]). + +-export([ +dec_GajumaruData/1, +dec_Content/1, +dec_TemplateFields/1, +dec_TemplateField/1, +dec_StaticFields/1, +dec_Value/1, +dec_KeyValue/1, +dec_Id/1, +dec_Account/1, +dec_SignedTx/1, +dec_ContractCode/1, +dec_ContractV1/1, +dec_ContractV2/1, +dec_ContractV3/1, +dec_TypeInfoV1/1, +dec_TypeInfoV3/1 +]). + +-export([info/0]). + +-export([encode/2,decode/2]). + +encoding_rule() -> uper. + +maps() -> false. + +bit_string_format() -> bitstring. + +legacy_erlang_types() -> false. + +encode(Type, Data) -> +try complete(encode_disp(Type, Data)) of + Bytes -> + {ok,Bytes} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + + +decode(Type, Data) -> +try + {Result,_Rest} = decode_disp(Type, Data), + {ok,Result} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + +encode_disp('GajumaruData', Data) -> enc_GajumaruData(Data); +encode_disp('Content', Data) -> enc_Content(Data); +encode_disp('TemplateFields', Data) -> enc_TemplateFields(Data); +encode_disp('TemplateField', Data) -> enc_TemplateField(Data); +encode_disp('StaticFields', Data) -> enc_StaticFields(Data); +encode_disp('Value', Data) -> enc_Value(Data); +encode_disp('KeyValue', Data) -> enc_KeyValue(Data); +encode_disp('Id', Data) -> enc_Id(Data); +encode_disp('Account', Data) -> enc_Account(Data); +encode_disp('SignedTx', Data) -> enc_SignedTx(Data); +encode_disp('ContractCode', Data) -> enc_ContractCode(Data); +encode_disp('ContractV1', Data) -> enc_ContractV1(Data); +encode_disp('ContractV2', Data) -> enc_ContractV2(Data); +encode_disp('ContractV3', Data) -> enc_ContractV3(Data); +encode_disp('TypeInfoV1', Data) -> enc_TypeInfoV1(Data); +encode_disp('TypeInfoV3', Data) -> enc_TypeInfoV3(Data); +encode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +decode_disp('GajumaruData', Data) -> dec_GajumaruData(Data); +decode_disp('Content', Data) -> dec_Content(Data); +decode_disp('TemplateFields', Data) -> dec_TemplateFields(Data); +decode_disp('TemplateField', Data) -> dec_TemplateField(Data); +decode_disp('StaticFields', Data) -> dec_StaticFields(Data); +decode_disp('Value', Data) -> dec_Value(Data); +decode_disp('KeyValue', Data) -> dec_KeyValue(Data); +decode_disp('Id', Data) -> dec_Id(Data); +decode_disp('Account', Data) -> dec_Account(Data); +decode_disp('SignedTx', Data) -> dec_SignedTx(Data); +decode_disp('ContractCode', Data) -> dec_ContractCode(Data); +decode_disp('ContractV1', Data) -> dec_ContractV1(Data); +decode_disp('ContractV2', Data) -> dec_ContractV2(Data); +decode_disp('ContractV3', Data) -> dec_ContractV3(Data); +decode_disp('TypeInfoV1', Data) -> dec_TypeInfoV1(Data); +decode_disp('TypeInfoV3', Data) -> dec_TypeInfoV3(Data); +decode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +info() -> + case ?MODULE:module_info(attributes) of + Attributes when is_list(Attributes) -> + case lists:keyfind(asn1_info, 1, Attributes) of + {_,Info} when is_list(Info) -> + Info; + _ -> + [] + end; + _ -> + [] + end. +enc_GajumaruData(Val) -> +[begin +%% attribute tag(1) with type INTEGER +Enc1@element = element(2, Val), +if Enc1@element bsr 16 =:= 0 -> +<>; +true -> +exit({error,{asn1,{illegal_integer,Enc1@element}}}) +end +end, +begin +%% attribute vsn(2) with type INTEGER +Enc3@element = element(3, Val), +if Enc3@element bsr 8 =:= 0 -> +Enc3@element; +true -> +exit({error,{asn1,{illegal_integer,Enc3@element}}}) +end +end|begin +%% attribute content(3) with type Content +Enc5@element = element(4, Val), +enc_Content(Enc5@element) +end]. + + +dec_GajumaruData(Bytes) -> + +%% attribute tag(1) with type INTEGER +{Term1,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute vsn(2) with type INTEGER +{Term2,Bytes2} = begin +<> = Bytes1, +{V2@V0,V2@Buf1} +end, + +%% attribute content(3) with type Content +{Term3,Bytes3} = dec_Content(Bytes2), +Res1 = {'GajumaruData',Term1,Term2,Term3}, +{Res1,Bytes3}. + +enc_Content(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= templateFields -> +[<<0:3>>|enc_TemplateFields(ChoiceVal)]; +ChoiceTag =:= staticFields -> +[<<1:3>>|enc_StaticFields(ChoiceVal)]; +ChoiceTag =:= account -> +[<<2:3>>|enc_Account(ChoiceVal)]; +ChoiceTag =:= signedTx -> +[<<3:3>>|enc_SignedTx(ChoiceVal)]; +ChoiceTag =:= contract -> +[<<4:3>>|enc_ContractCode(ChoiceVal)] +end. + + +dec_Content(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +dec_TemplateFields(Bytes1) +end, +{{templateFields,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +dec_StaticFields(Bytes1) +end, +{{staticFields,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +dec_Account(Bytes1) +end, +{{account,Val},NewBytes}; +3 -> +{Val,NewBytes} = begin +dec_SignedTx(Bytes1) +end, +{{signedTx,Val},NewBytes}; +4 -> +{Val,NewBytes} = begin +dec_ContractCode(Bytes1) +end, +{{contract,Val},NewBytes} +end. +enc_TemplateFields(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TemplateField(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TemplateField(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TemplateField(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_TemplateFields(Bytes) -> +dec_components1(Bytes, []). + +enc_TemplateField(Val) -> +[begin +Enc1@element = element(2, Val), +if Enc1@element =:= asn1_NOVALUE -> +<<0:1>>; +true -> +<<1:1>> +end +end, +begin +%% attribute name(1) with type IA5String +Enc2@element = element(2, Val), +if Enc2@element =:= asn1_NOVALUE -> +[]; +true -> +begin +Enc3@len = length(Enc2@element), +Enc3@bin = encode_chars(Enc2@element, 7), +if Enc3@len < 128 -> +[Enc3@len|Enc3@bin]; +Enc3@len < 16384 -> +[<<2:2,Enc3@len:14>>|Enc3@bin]; +true -> +encode_fragmented(Enc3@bin, 7) +end +end +end +end|begin +%% attribute value(2) with type Value +Enc5@element = element(3, Val), +enc_Value(Enc5@element) +end]. + + +dec_TemplateField(Bytes) -> +{Opt,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute name(1) with type IA5String +{Term1,Bytes2} = case Opt band 1 of +1 -> +begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:7,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:7,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 7), +{V2@V6,V2@Buf7} +end, +{V2@V8,V2@Buf9} = {decode_chars(V2@V0, 7),V2@Buf1}, +{V2@V8,V2@Buf9} +end; +0 -> +{asn1_NOVALUE,Bytes1} +end, + +%% attribute value(2) with type Value +{Term2,Bytes3} = dec_Value(Bytes2), +Res1 = {'TemplateField',Term1,Term2}, +{Res1,Bytes3}. + +enc_StaticFields(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_StaticFields(Bytes) -> +dec_components2(Bytes, []). + +enc_Value(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= intValue -> +[<<0:3>>|encode_unconstrained_number(ChoiceVal)]; +ChoiceTag =:= boolValue -> +if ChoiceVal =:= false -> +<<1:3,0:1>>; +ChoiceVal =:= true -> +<<1:3,1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,ChoiceVal}}}) +end; +ChoiceTag =:= binaryValue -> +[<<2:3>>|begin +Enc6@len = byte_size(ChoiceVal), +if Enc6@len < 128 -> +[Enc6@len|ChoiceVal]; +Enc6@len < 16384 -> +[<<2:2,Enc6@len:14>>|ChoiceVal]; +true -> +encode_fragmented(ChoiceVal, 8) +end +end]; +ChoiceTag =:= idValue -> +[<<3:3>>|enc_Id(ChoiceVal)]; +ChoiceTag =:= listValue -> +[<<4:3>>|enc_Value_listValue(ChoiceVal)]; +ChoiceTag =:= tupleValue -> +[<<5:3>>|enc_Value_tupleValue(ChoiceVal)]; +ChoiceTag =:= mapValue -> +[<<6:3>>|enc_Value_mapValue(ChoiceVal)] +end. +enc_Value_listValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + +enc_Value_tupleValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + +enc_Value_mapValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_KeyValue(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_KeyValue(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_KeyValue(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_Value(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@Buf4/bitstring>> when V2@V3 =/= 0 -> +{V2@V3,V2@Buf4}; +<<1:1,0:1,V2@V4:14,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +{V2@V4,V2@Buf5}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +V2@Mul6 = V2@V4 * 16384, +{V2@Mul6,V2@Buf5} +end, +<> = V2@Buf1, +{V2@V7,V2@Buf8} +end +end, +{{intValue,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +begin +<> = Bytes1, +V3@Int2 = case V3@V0 of +0 -> false; +1 -> true +end, +{V3@Int2,V3@Buf1} +end +end, +{{boolValue,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +begin +{V4@V0,V4@Buf1} = case Bytes1 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end +end, +{{binaryValue,Val},NewBytes}; +3 -> +{Val,NewBytes} = begin +dec_Id(Bytes1) +end, +{{idValue,Val},NewBytes}; +4 -> +{Val,NewBytes} = begin +dec_Value_listValue(Bytes1) +end, +{{listValue,Val},NewBytes}; +5 -> +{Val,NewBytes} = begin +dec_Value_tupleValue(Bytes1) +end, +{{tupleValue,Val},NewBytes}; +6 -> +{Val,NewBytes} = begin +dec_Value_mapValue(Bytes1) +end, +{{mapValue,Val},NewBytes} +end. + +dec_Value_listValue(Bytes) -> +dec_components3(Bytes, []). + + +dec_Value_tupleValue(Bytes) -> +dec_components4(Bytes, []). + + +dec_Value_mapValue(Bytes) -> +dec_components5(Bytes, []). + +enc_KeyValue(Val) -> +[begin +%% attribute key(1) with type Value +Enc1@element = element(2, Val), +enc_Value(Enc1@element) +end|begin +%% attribute val(2) with type Value +Enc2@element = element(3, Val), +enc_Value(Enc2@element) +end]. + + +dec_KeyValue(Bytes) -> + +%% attribute key(1) with type Value +{Term1,Bytes1} = dec_Value(Bytes), + +%% attribute val(2) with type Value +{Term2,Bytes2} = dec_Value(Bytes1), +Res1 = {'KeyValue',Term1,Term2}, +{Res1,Bytes2}. + +enc_Id(Val) -> +[begin +%% attribute type(1) with type INTEGER +Enc1@element = element(2, Val), +if Enc1@element bsr 8 =:= 0 -> +Enc1@element; +true -> +exit({error,{asn1,{illegal_integer,Enc1@element}}}) +end +end|begin +%% attribute value(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len =:= 32 -> +Enc3@element +end +end]. + + +dec_Id(Bytes) -> + +%% attribute type(1) with type INTEGER +{Term1,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute value(2) with type OCTET STRING +{Term2,Bytes2} = begin +<> = Bytes1, +V2@Conv2 = binary:copy(V2@V0), +{V2@Conv2,V2@Buf1} +end, +Res1 = {'Id',Term1,Term2}, +{Res1,Bytes2}. + +enc_Account(Val) -> +[begin +%% attribute foo(1) with type INTEGER +Enc1@element = element(2, Val), +encode_unconstrained_number(Enc1@element) +end|begin +%% attribute bar(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end]. + + +dec_Account(Bytes) -> + +%% attribute foo(1) with type INTEGER +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@Buf4/bitstring>> when V1@V3 =/= 0 -> +{V1@V3,V1@Buf4}; +<<1:1,0:1,V1@V4:14,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +{V1@V4,V1@Buf5}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +V1@Mul6 = V1@V4 * 16384, +{V1@Mul6,V1@Buf5} +end, +<> = V1@Buf1, +{V1@V7,V1@Buf8} +end, + +%% attribute bar(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, +Res1 = {'Account',Term1,Term2}, +{Res1,Bytes2}. + +enc_SignedTx(Val) -> +[begin +%% attribute signatures(1) with type SEQUENCE OF +Enc1@element = element(2, Val), +enc_SignedTx_signatures(Enc1@element) +end|begin +%% attribute transaction(2) with type OCTET STRING +Enc2@element = element(3, Val), +Enc3@len = byte_size(Enc2@element), +if Enc3@len < 128 -> +[Enc3@len|Enc2@element]; +Enc3@len < 16384 -> +[<<2:2,Enc3@len:14>>|Enc2@element]; +true -> +encode_fragmented(Enc2@element, 8) +end +end]. +enc_SignedTx_signatures(Val) -> +Enc2@len = length(Val), +if Enc2@len < 128 -> +[Enc2@len|[begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end || Comp <- Val]]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|[begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end || Comp <- Val]]; +true -> +begin +Enc2@fn = fun(Comp) -> begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end end, +encode_fragmented_sof(Enc2@fn, Val, Enc2@len) +end +end. + + + +dec_SignedTx(Bytes) -> + +%% attribute signatures(1) with type SEQUENCE OF +{Term1,Bytes1} = dec_SignedTx_signatures(Bytes), + +%% attribute transaction(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V1@V0,V1@Buf1} = case Bytes1 of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, +Res1 = {'SignedTx',Term1,Term2}, +{Res1,Bytes2}. + + +dec_SignedTx_signatures(Bytes) -> +dec_components6(Bytes, []). + +enc_ContractCode(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= v1 -> +[<<0:2>>|enc_ContractV1(ChoiceVal)]; +ChoiceTag =:= v2 -> +[<<1:2>>|enc_ContractV2(ChoiceVal)]; +ChoiceTag =:= v3 -> +[<<2:2>>|enc_ContractV3(ChoiceVal)] +end. + + +dec_ContractCode(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +dec_ContractV1(Bytes1) +end, +{{v1,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +dec_ContractV2(Bytes1) +end, +{{v2,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +dec_ContractV3(Bytes1) +end, +{{v3,Val},NewBytes} +end. +enc_ContractV1(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV1_typeInfo(Enc3@element) +end|begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end]. +enc_ContractV1_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV1(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV1(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV1_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, +Res1 = {'ContractV1',Term1,Term2,Term3}, +{Res1,Bytes3}. + + +dec_ContractV1_typeInfo(Bytes) -> +dec_components7(Bytes, []). + +enc_ContractV2(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV2_typeInfo(Enc3@element) +end, +begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end|begin +%% attribute compilerVersion(4) with type OCTET STRING +Enc6@element = element(5, Val), +Enc7@len = byte_size(Enc6@element), +if Enc7@len < 128 -> +[Enc7@len|Enc6@element]; +Enc7@len < 16384 -> +[<<2:2,Enc7@len:14>>|Enc6@element]; +true -> +encode_fragmented(Enc6@element, 8) +end +end]. +enc_ContractV2_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV1(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV2(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV2_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute compilerVersion(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V3@V0,V3@Buf1} = case Bytes3 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, +Res1 = {'ContractV2',Term1,Term2,Term3,Term4}, +{Res1,Bytes4}. + + +dec_ContractV2_typeInfo(Bytes) -> +dec_components8(Bytes, []). + +enc_ContractV3(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV3_typeInfo(Enc3@element) +end, +begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end, +begin +%% attribute compilerVersion(4) with type OCTET STRING +Enc6@element = element(5, Val), +Enc7@len = byte_size(Enc6@element), +if Enc7@len < 128 -> +[Enc7@len|Enc6@element]; +Enc7@len < 16384 -> +[<<2:2,Enc7@len:14>>|Enc6@element]; +true -> +encode_fragmented(Enc6@element, 8) +end +end|begin +%% attribute payable(5) with type BOOLEAN +Enc8@element = element(6, Val), +if Enc8@element =:= false -> +<<0:1>>; +Enc8@element =:= true -> +<<1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,Enc8@element}}}) +end +end]. +enc_ContractV3_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV3(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV3(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV3(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV3(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV3_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute compilerVersion(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V3@V0,V3@Buf1} = case Bytes3 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, + +%% attribute payable(5) with type BOOLEAN +{Term5,Bytes5} = begin +<> = Bytes4, +V4@Int2 = case V4@V0 of +0 -> false; +1 -> true +end, +{V4@Int2,V4@Buf1} +end, +Res1 = {'ContractV3',Term1,Term2,Term3,Term4,Term5}, +{Res1,Bytes5}. + + +dec_ContractV3_typeInfo(Bytes) -> +dec_components9(Bytes, []). + +enc_TypeInfoV1(Val) -> +[begin +%% attribute typeHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute name(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end, +begin +%% attribute argType(3) with type OCTET STRING +Enc5@element = element(4, Val), +Enc6@len = byte_size(Enc5@element), +if Enc6@len < 128 -> +[Enc6@len|Enc5@element]; +Enc6@len < 16384 -> +[<<2:2,Enc6@len:14>>|Enc5@element]; +true -> +encode_fragmented(Enc5@element, 8) +end +end|begin +%% attribute outType(4) with type OCTET STRING +Enc7@element = element(5, Val), +Enc8@len = byte_size(Enc7@element), +if Enc8@len < 128 -> +[Enc8@len|Enc7@element]; +Enc8@len < 16384 -> +[<<2:2,Enc8@len:14>>|Enc7@element]; +true -> +encode_fragmented(Enc7@element, 8) +end +end]. + + +dec_TypeInfoV1(Bytes) -> + +%% attribute typeHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute name(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute argType(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V3@V0,V3@Buf1} = case Bytes2 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, + +%% attribute outType(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V4@V0,V4@Buf1} = case Bytes3 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end, +Res1 = {'TypeInfoV1',Term1,Term2,Term3,Term4}, +{Res1,Bytes4}. + +enc_TypeInfoV3(Val) -> +[begin +%% attribute typeHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute name(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end, +begin +%% attribute payable(3) with type BOOLEAN +Enc5@element = element(4, Val), +if Enc5@element =:= false -> +<<0:1>>; +Enc5@element =:= true -> +<<1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,Enc5@element}}}) +end +end, +begin +%% attribute argType(4) with type OCTET STRING +Enc7@element = element(5, Val), +Enc8@len = byte_size(Enc7@element), +if Enc8@len < 128 -> +[Enc8@len|Enc7@element]; +Enc8@len < 16384 -> +[<<2:2,Enc8@len:14>>|Enc7@element]; +true -> +encode_fragmented(Enc7@element, 8) +end +end|begin +%% attribute outType(5) with type OCTET STRING +Enc9@element = element(6, Val), +Enc10@len = byte_size(Enc9@element), +if Enc10@len < 128 -> +[Enc10@len|Enc9@element]; +Enc10@len < 16384 -> +[<<2:2,Enc10@len:14>>|Enc9@element]; +true -> +encode_fragmented(Enc9@element, 8) +end +end]. + + +dec_TypeInfoV3(Bytes) -> + +%% attribute typeHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute name(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute payable(3) with type BOOLEAN +{Term3,Bytes3} = begin +<> = Bytes2, +V3@Int2 = case V3@V0 of +0 -> false; +1 -> true +end, +{V3@Int2,V3@Buf1} +end, + +%% attribute argType(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V4@V0,V4@Buf1} = case Bytes3 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end, + +%% attribute outType(5) with type OCTET STRING +{Term5,Bytes5} = begin +{V5@V0,V5@Buf1} = case Bytes4 of +<<0:1,V5@V3:7,V5@V5:V5@V3/binary-unit:8,V5@Buf6/bitstring>> -> +{V5@V5,V5@Buf6}; +<<1:1,0:1,V5@V4:14,V5@V6:V5@V4/binary-unit:8,V5@Buf7/bitstring>> -> +{V5@V6,V5@Buf7}; +<<1:1,1:1,V5@V4:6,V5@Buf5/bitstring>> -> +{V5@V6,V5@Buf7} = decode_fragmented(V5@V4, V5@Buf5, 8), +{V5@V6,V5@Buf7} +end, +V5@Conv8 = binary:copy(V5@V0), +{V5@Conv8,V5@Buf1} +end, +Res1 = {'TypeInfoV3',Term1,Term2,Term3,Term4,Term5}, +{Res1,Bytes5}. + + +%%% +%%% Run-time functions. +%%% + +'dialyzer-suppressions'(Arg) -> + _ = complete(element(1, Arg)), + ok. + +dec_components1(Bytes, Acc) -> +%% Length with constraint no +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@Buf4/bitstring>> -> +{V1@V3,V1@Buf4}; +<<1:1,0:1,V1@V4:14,V1@Buf5/bitstring>> -> +{V1@V4,V1@Buf5}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +V1@Mul6 = V1@V4 * 16384, +{V1@Mul6,V1@Buf5} +end, +{Acc1,Buf1} = dec_fragment10(V1@V0, V1@Buf1, Acc), +if V1@V0 >= 16384 -> +dec_components1(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components2(Bytes, Acc) -> +%% Length with constraint no +{V2@V0,V2@Buf1} = case Bytes of +<<0:1,V2@V3:7,V2@Buf4/bitstring>> -> +{V2@V3,V2@Buf4}; +<<1:1,0:1,V2@V4:14,V2@Buf5/bitstring>> -> +{V2@V4,V2@Buf5}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +V2@Mul6 = V2@V4 * 16384, +{V2@Mul6,V2@Buf5} +end, +{Acc1,Buf1} = dec_fragment11(V2@V0, V2@Buf1, Acc), +if V2@V0 >= 16384 -> +dec_components2(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components3(Bytes, Acc) -> +%% Length with constraint no +{V3@V0,V3@Buf1} = case Bytes of +<<0:1,V3@V3:7,V3@Buf4/bitstring>> -> +{V3@V3,V3@Buf4}; +<<1:1,0:1,V3@V4:14,V3@Buf5/bitstring>> -> +{V3@V4,V3@Buf5}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +V3@Mul6 = V3@V4 * 16384, +{V3@Mul6,V3@Buf5} +end, +{Acc1,Buf1} = dec_fragment12(V3@V0, V3@Buf1, Acc), +if V3@V0 >= 16384 -> +dec_components3(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components4(Bytes, Acc) -> +%% Length with constraint no +{V4@V0,V4@Buf1} = case Bytes of +<<0:1,V4@V3:7,V4@Buf4/bitstring>> -> +{V4@V3,V4@Buf4}; +<<1:1,0:1,V4@V4:14,V4@Buf5/bitstring>> -> +{V4@V4,V4@Buf5}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +V4@Mul6 = V4@V4 * 16384, +{V4@Mul6,V4@Buf5} +end, +{Acc1,Buf1} = dec_fragment13(V4@V0, V4@Buf1, Acc), +if V4@V0 >= 16384 -> +dec_components4(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components5(Bytes, Acc) -> +%% Length with constraint no +{V5@V0,V5@Buf1} = case Bytes of +<<0:1,V5@V3:7,V5@Buf4/bitstring>> -> +{V5@V3,V5@Buf4}; +<<1:1,0:1,V5@V4:14,V5@Buf5/bitstring>> -> +{V5@V4,V5@Buf5}; +<<1:1,1:1,V5@V4:6,V5@Buf5/bitstring>> -> +V5@Mul6 = V5@V4 * 16384, +{V5@Mul6,V5@Buf5} +end, +{Acc1,Buf1} = dec_fragment14(V5@V0, V5@Buf1, Acc), +if V5@V0 >= 16384 -> +dec_components5(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components6(Bytes, Acc) -> +%% Length with constraint no +{V6@V0,V6@Buf1} = case Bytes of +<<0:1,V6@V3:7,V6@Buf4/bitstring>> -> +{V6@V3,V6@Buf4}; +<<1:1,0:1,V6@V4:14,V6@Buf5/bitstring>> -> +{V6@V4,V6@Buf5}; +<<1:1,1:1,V6@V4:6,V6@Buf5/bitstring>> -> +V6@Mul6 = V6@V4 * 16384, +{V6@Mul6,V6@Buf5} +end, +{Acc1,Buf1} = dec_fragment15(V6@V0, V6@Buf1, Acc), +if V6@V0 >= 16384 -> +dec_components6(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components7(Bytes, Acc) -> +%% Length with constraint no +{V7@V0,V7@Buf1} = case Bytes of +<<0:1,V7@V3:7,V7@Buf4/bitstring>> -> +{V7@V3,V7@Buf4}; +<<1:1,0:1,V7@V4:14,V7@Buf5/bitstring>> -> +{V7@V4,V7@Buf5}; +<<1:1,1:1,V7@V4:6,V7@Buf5/bitstring>> -> +V7@Mul6 = V7@V4 * 16384, +{V7@Mul6,V7@Buf5} +end, +{Acc1,Buf1} = dec_fragment16(V7@V0, V7@Buf1, Acc), +if V7@V0 >= 16384 -> +dec_components7(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components8(Bytes, Acc) -> +%% Length with constraint no +{V8@V0,V8@Buf1} = case Bytes of +<<0:1,V8@V3:7,V8@Buf4/bitstring>> -> +{V8@V3,V8@Buf4}; +<<1:1,0:1,V8@V4:14,V8@Buf5/bitstring>> -> +{V8@V4,V8@Buf5}; +<<1:1,1:1,V8@V4:6,V8@Buf5/bitstring>> -> +V8@Mul6 = V8@V4 * 16384, +{V8@Mul6,V8@Buf5} +end, +{Acc1,Buf1} = dec_fragment17(V8@V0, V8@Buf1, Acc), +if V8@V0 >= 16384 -> +dec_components8(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components9(Bytes, Acc) -> +%% Length with constraint no +{V9@V0,V9@Buf1} = case Bytes of +<<0:1,V9@V3:7,V9@Buf4/bitstring>> -> +{V9@V3,V9@Buf4}; +<<1:1,0:1,V9@V4:14,V9@Buf5/bitstring>> -> +{V9@V4,V9@Buf5}; +<<1:1,1:1,V9@V4:6,V9@Buf5/bitstring>> -> +V9@Mul6 = V9@V4 * 16384, +{V9@Mul6,V9@Buf5} +end, +{Acc1,Buf1} = dec_fragment18(V9@V0, V9@Buf1, Acc), +if V9@V0 >= 16384 -> +dec_components9(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_fragment10(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment10(Num, Bytes, Acc) -> +{Term,Remain} = dec_TemplateField(Bytes), +dec_fragment10(Num-1, Remain, [Term|Acc]). + +dec_fragment11(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment11(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment11(Num-1, Remain, [Term|Acc]). + +dec_fragment12(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment12(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment12(Num-1, Remain, [Term|Acc]). + +dec_fragment13(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment13(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment13(Num-1, Remain, [Term|Acc]). + +dec_fragment14(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment14(Num, Bytes, Acc) -> +{Term,Remain} = dec_KeyValue(Bytes), +dec_fragment14(Num-1, Remain, [Term|Acc]). + +dec_fragment15(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment15(Num, Bytes, Acc) -> +{Term,Remain} = begin +{V10@V0,V10@Buf1} = case Bytes of +<<0:1,V10@V3:7,V10@V5:V10@V3/binary-unit:8,V10@Buf6/bitstring>> -> +{V10@V5,V10@Buf6}; +<<1:1,0:1,V10@V4:14,V10@V6:V10@V4/binary-unit:8,V10@Buf7/bitstring>> -> +{V10@V6,V10@Buf7}; +<<1:1,1:1,V10@V4:6,V10@Buf5/bitstring>> -> +{V10@V6,V10@Buf7} = decode_fragmented(V10@V4, V10@Buf5, 8), +{V10@V6,V10@Buf7} +end, +V10@Conv8 = binary:copy(V10@V0), +{V10@Conv8,V10@Buf1} +end, +dec_fragment15(Num-1, Remain, [Term|Acc]). + +dec_fragment16(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment16(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV1(Bytes), +dec_fragment16(Num-1, Remain, [Term|Acc]). + +dec_fragment17(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment17(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV1(Bytes), +dec_fragment17(Num-1, Remain, [Term|Acc]). + +dec_fragment18(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment18(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV3(Bytes), +dec_fragment18(Num-1, Remain, [Term|Acc]). + +complete(InList) when is_list(InList) -> + case list_to_bitstring(InList) of + <<>> -> + <<0>>; + Res -> + Sz = bit_size(Res), + case Sz band 7 of + 0 -> + Res; + Bits -> + <> + end + end; +complete(Bin) when is_binary(Bin) -> + case Bin of + <<>> -> + <<0>>; + _ -> + Bin + end; +complete(InList) when is_bitstring(InList) -> + Sz = bit_size(InList), + PadLen = 8 - Sz band 7, + <>. + +decode_chars(Val, N) -> + [ + C || + <> <= Val + ]. + +decode_fragmented(SegSz0, Buf0, Unit) -> + SegSz = SegSz0 * Unit * 16384, + <> = Buf0, + decode_fragmented_1(Buf, Unit, Res). + +decode_fragmented_1(<<0:1,N:7,Buf0/bitstring>>, Unit, Res) -> + Sz = N * Unit, + <> = Buf0, + {<>, Buf}; +decode_fragmented_1(<<1:1,0:1,N:14,Buf0/bitstring>>, Unit, Res) -> + Sz = N * Unit, + <> = Buf0, + {<>, Buf}; +decode_fragmented_1(<<1:1,1:1,SegSz0:6,Buf0/bitstring>>, Unit, Res0) -> + SegSz = SegSz0 * Unit * 16384, + <> = Buf0, + Res = <>, + decode_fragmented_1(Buf, Unit, Res). + +encode_chars(Val, NumBits) -> + << + <> || + C <- Val + >>. + +encode_components(Cs, _Encoder, 0, Acc) -> + {Cs, lists:reverse(Acc)}; +encode_components([C | Cs], Encoder, Size, Acc) -> + B = Encoder(C), + encode_components(Cs, Encoder, Size - 1, [B | Acc]). + +encode_fragmented(Bin, Unit) -> + encode_fragmented_1(Bin, Unit, 4). + +encode_fragmented_1(Bin, Unit, N) -> + SegSz = Unit * N * 16384, + case Bin of + <> -> + [<<3:2,N:6>>, B | encode_fragmented_1(T, Unit, N)]; + _ when N > 1 -> + encode_fragmented_1(Bin, Unit, N - 1); + _ -> + case bit_size(Bin) div Unit of + Len when Len < 128 -> + [Len, Bin]; + Len when Len < 16384 -> + [<<2:2,Len:14>>, Bin] + end + end. + +encode_fragmented_sof(Fun, Comps, Len) -> + encode_fragmented_sof_1(Fun, Comps, Len, 4). + +encode_fragmented_sof_1(Encoder, Comps0, Len0, N) -> + SegSz = N * 16384, + if + Len0 >= SegSz -> + {Comps, B} = encode_components(Comps0, Encoder, SegSz, []), + Len = Len0 - SegSz, + [<<3:2,N:6>>, + B | + encode_fragmented_sof_1(Encoder, Comps, Len, N)]; + N > 1 -> + encode_fragmented_sof_1(Encoder, Comps0, Len0, N - 1); + Len0 < 128 -> + {[], B} = encode_components(Comps0, Encoder, Len0, []), + [Len0 | B]; + Len0 < 16384 -> + {[], B} = encode_components(Comps0, Encoder, Len0, []), + [<<2:2,Len0:14>> | B] + end. + +encode_unconstrained_number(Val) when not is_integer(Val) -> + exit({error, {asn1, {illegal_integer, Val}}}); +encode_unconstrained_number(Val) when Val >= 0 -> + if + Val < 128 -> + [1, Val]; + Val < 256 -> + [<<2,0>>, Val]; + true -> + case binary:encode_unsigned(Val) of + <<0:1,_/bitstring>> = Bin -> + case byte_size(Bin) of + Sz when Sz < 128 -> + [Sz, Bin]; + Sz when Sz < 16384 -> + [<<2:2,Sz:14>>, Bin] + end; + <<1:1,_/bitstring>> = Bin -> + case byte_size(Bin) + 1 of + Sz when Sz < 128 -> + [Sz, 0, Bin]; + Sz when Sz < 16384 -> + [<<2:2,Sz:14,0:8>>, Bin] + end + end + end; +encode_unconstrained_number(Val) -> + Oct = enint(Val, []), + Len = length(Oct), + if + Len < 128 -> + [Len | Oct]; + Len < 16384 -> + [<<2:2,Len:14>> | Oct] + end. + +enint(-1, [B1 | T]) when B1 > 127 -> + [B1 | T]; +enint(N, Acc) -> + enint(N bsr 8, [N band 255 | Acc]). diff --git a/asn1_optimized/GajumaruSerialization.hrl b/asn1_optimized/GajumaruSerialization.hrl new file mode 100644 index 0000000..4c5d52e --- /dev/null +++ b/asn1_optimized/GajumaruSerialization.hrl @@ -0,0 +1,76 @@ +%% Generated by the Erlang ASN.1 compiler. Version: 5.4.3 +%% Purpose: Erlang record definitions for each named and unnamed +%% SEQUENCE and SET, and macro definitions for each value +%% definition in module GajumaruSerialization. + +-ifndef(_GAJUMARUSERIALIZATION_HRL_). +-define(_GAJUMARUSERIALIZATION_HRL_, true). + +-record('GajumaruData', { + tag, + vsn, + content +}). + +-record('TemplateField', { + name = asn1_NOVALUE, + value +}). + +-record('KeyValue', { + key, + val +}). + +-record('Id', { + type, + value +}). + +-record('Account', { + foo, + bar +}). + +-record('SignedTx', { + signatures, + transaction +}). + +-record('ContractV1', { + sourceHash, + typeInfo, + byteCode +}). + +-record('ContractV2', { + sourceHash, + typeInfo, + byteCode, + compilerVersion +}). + +-record('ContractV3', { + sourceHash, + typeInfo, + byteCode, + compilerVersion, + payable +}). + +-record('TypeInfoV1', { + typeHash, + name, + argType, + outType +}). + +-record('TypeInfoV3', { + typeHash, + name, + payable, + argType, + outType +}). + +-endif. %% _GAJUMARUSERIALIZATION_HRL_ diff --git a/asn1_per/GajumaruSerialization.asn b/asn1_per/GajumaruSerialization.asn new file mode 100644 index 0000000..43607e9 --- /dev/null +++ b/asn1_per/GajumaruSerialization.asn @@ -0,0 +1,225 @@ +-- GajumaruSerialization.asn +-- +-- ASN.1 model for the structures serialized by gmserialization.erl +-- (the layer on top of RLP). +-- +-- Purpose: +-- * Provide a formal, toolable description of the data. +-- * Enable migration from the legacy RLP-based format to DER. +-- +-- Detection of legacy vs new: +-- Legacy data (produced by gmserialization:serialize / gmser_chain_objects:serialize +-- or gmser_dyn:serialize) is always an RLP *list* at the top level. +-- This means the first byte is in the range 0xC0 .. 0xFF. +-- +-- DER-encoded data using the types below will start with 0x30 (SEQUENCE, +-- constructed, universal tag) for the outermost GajumaruData (or any +-- top-level SEQUENCE we define). 0x30 < 0xC0, so a single-byte prefix +-- check reliably distinguishes the two formats. +-- +-- Usage in Erlang (after compiling with asn1ct): +-- {ok, Mod} = asn1ct:compile(GajumaruSerialization.asn, [ber, der]). +-- {ok, Term} = 'GajumaruSerialization':decode('GajumaruData', DerBinary). +-- +-- Notes on type mapping from gmserialization.erl: +-- - int -> INTEGER (new data uses canonical DER INTEGER) +-- - binary -> OCTET STRING +-- - bool -> BOOLEAN +-- - id -> Id (SEQUENCE) (cleaner than the legacy packed 33-byte form) +-- - [T] -> SEQUENCE OF T +-- - {T1,...} -> SEQUENCE (fixed-size, order matters) +-- - #{items := [{K,T},...]} -> SEQUENCE with the fields in template order +-- (static maps carry *values only*, no keys on the wire) +-- - tag + vsn are preserved as the first two fields for compatibility +-- with existing dispatch logic. +-- +-- Legacy integers had strict unsigned-minimal no-leading-zero (except for 0) +-- and RLP-level rules. New DER data does not need to follow those rules. +-- +-- WARNING: +-- Any cryptographic hash or signature computed over a serialized object +-- will change when switching from RLP to DER for that object. Plan a +-- coordinated upgrade. + +GajumaruSerialization DEFINITIONS + AUTOMATIC TAGS ::= +BEGIN + +EXPORTS ALL; + +-- ============================================================ +-- Top-level wrapper used for new DER data. +-- This is what a decoder will see first. +-- ============================================================ + +GajumaruData ::= SEQUENCE { + tag INTEGER, + vsn INTEGER, + content Content +} + +-- Content can be a specific structured type (preferred) or a generic +-- representation of a template-driven object. +Content ::= CHOICE { + -- Generic fallback that can represent any [{Field, Type}] template + -- without having a pre-defined SEQUENCE for every object. + templateFields [0] TemplateFields, + + -- Examples of concrete versioned types (extend as needed) + account [1] Account, + signedTx [2] SignedTx, + contract [3] ContractCode + -- Add more alternatives for other tags from gmser_chain_objects +} + +-- ============================================================ +-- Generic template-driven representation +-- (useful during transition or for unregistered types) +-- ============================================================ + +TemplateFields ::= SEQUENCE OF TemplateField + +TemplateField ::= SEQUENCE { + -- Field name is included for debuggability / generic processing. + -- In the original static encoding the name is NOT on the wire; + -- only position and type matter. We include it here for convenience. + name IA5String OPTIONAL, + value Value +} + +Value ::= CHOICE { + intValue [0] INTEGER, + boolValue [1] BOOLEAN, + binaryValue [2] OCTET STRING, + idValue [3] Id, + listValue [4] SEQUENCE OF Value, + tupleValue [5] SEQUENCE OF Value, + mapValue [6] SEQUENCE OF KeyValue -- only needed if you want to + -- represent dynamic-style maps +} + +KeyValue ::= SEQUENCE { + key Value, + val Value +} + +-- ============================================================ +-- Common types +-- ============================================================ + +Id ::= SEQUENCE { + -- Corresponds to the simple tags in gmser_id (account=1, name=2, etc.) + -- and the extended account subtype (high bit in legacy). + type INTEGER (0..255), + value OCTET STRING (SIZE (32)) +} + +-- ============================================================ +-- Concrete object examples (derived from usage in the codebase) +-- Add / evolve per version as you introduce new vsns. +-- ============================================================ + +-- Example: a very simple account-like object used in tests +Account ::= SEQUENCE { + foo INTEGER, + bar OCTET STRING +} + +-- Simplified signed transaction +SignedTx ::= SEQUENCE { + signatures SEQUENCE OF OCTET STRING, + transaction OCTET STRING +} + +-- Contract code objects (see gmser_contract_code.erl) +-- We model the three versions that exist today. +ContractCode ::= CHOICE { + v1 [0] ContractV1, + v2 [1] ContractV2, + v3 [2] ContractV3 +} + +ContractV1 ::= SEQUENCE { + sourceHash OCTET STRING, + -- typeInfo is a list of 4-tuples in legacy: + -- {typeHash, name, argType, outType} + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING +} + +ContractV2 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING, + compilerVersion OCTET STRING +} + +ContractV3 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV3, + byteCode OCTET STRING, + compilerVersion OCTET STRING, + payable BOOLEAN +} + +TypeInfoV1 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + argType OCTET STRING, + outType OCTET STRING +} + +TypeInfoV3 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + payable BOOLEAN, + argType OCTET STRING, + outType OCTET STRING +} + +-- ============================================================ +-- Notes for implementers +-- ============================================================ +-- 1. Detection (recommended decoder entry point): +-- +-- decode(Binary) -> +-- case Binary of +-- <> when B >= 16#C0 -> +-- decode_legacy_rlp(Binary); % existing gmser_* path +-- _ -> +-- {ok, Term} = +-- 'GajumaruSerialization':decode('GajumaruData', Binary), +-- Term +-- end. +-- +-- This works because: +-- - All current top-level output from serialize() is an RLP list +-- (first byte 0xC0-0xFF). +-- - GajumaruData and the concrete choices above are SEQUENCEs +-- (first byte 0x30 for short form, or 0x30 0x81/0x82... for long). +-- +-- 2. When you add a new object type or version, prefer adding a +-- concrete SEQUENCE alternative in the Content CHOICE rather than +-- always falling back to TemplateFields. This gives you better +-- validation and generated types. +-- +-- 3. INTEGER in DER is signed and uses a different minimal encoding +-- than the legacy unsigned big-endian no leading zero form. This is +-- fine for new data. +-- +-- 4. If you need to preserve exact legacy integer wire bytes inside +-- the new format (e.g. for some hash preimage reason), you can +-- carry selected integers as OCTET STRING (legacy unsigned minimal bytes). +-- +-- 5. Dynamic encoding (gmser_dyn) is intentionally not modeled here +-- in full, because it is runtime-schema driven (type codes 246-255, +-- labels, alt/switch, etc.). You can still use the generic +-- TemplateFields + Value for some dynamic cases, or model specific +-- message schemas as additional CHOICE arms. +-- +-- 6. Compile with DER for canonical output: +-- asn1ct:compile(GajumaruSerialization, [der]). +-- +-- The ber option is also accepted; der implies the stricter rules. + +END diff --git a/asn1_per/GajumaruSerialization.asn1db b/asn1_per/GajumaruSerialization.asn1db new file mode 100644 index 0000000..05d3386 Binary files /dev/null and b/asn1_per/GajumaruSerialization.asn1db differ diff --git a/asn1_per/GajumaruSerialization.erl b/asn1_per/GajumaruSerialization.erl new file mode 100644 index 0000000..08f53d4 --- /dev/null +++ b/asn1_per/GajumaruSerialization.erl @@ -0,0 +1,1750 @@ +%% Generated by the Erlang ASN.1 PER (aligned) compiler. Version: 5.4.3 +%% Purpose: Encoding and decoding of the types in GajumaruSerialization. + +-module('GajumaruSerialization'). +-moduledoc false. +-compile(nowarn_unused_vars). +-dialyzer(no_improper_lists). +-dialyzer(no_match). +-include("GajumaruSerialization.hrl"). +-asn1_info([{vsn,'5.4.3'}, + {module,'GajumaruSerialization'}, + {options,[per,{outdir,"asn1_per"},{i,"."},{i,"asn1_per"}]}]). + +-export([encoding_rule/0,maps/0,bit_string_format/0, + legacy_erlang_types/0]). +-export(['dialyzer-suppressions'/1]). +-export([ +enc_GajumaruData/1, +enc_Content/1, +enc_TemplateFields/1, +enc_TemplateField/1, +enc_Value/1, +enc_KeyValue/1, +enc_Id/1, +enc_Account/1, +enc_SignedTx/1, +enc_ContractCode/1, +enc_ContractV1/1, +enc_ContractV2/1, +enc_ContractV3/1, +enc_TypeInfoV1/1, +enc_TypeInfoV3/1 +]). + +-export([ +dec_GajumaruData/1, +dec_Content/1, +dec_TemplateFields/1, +dec_TemplateField/1, +dec_Value/1, +dec_KeyValue/1, +dec_Id/1, +dec_Account/1, +dec_SignedTx/1, +dec_ContractCode/1, +dec_ContractV1/1, +dec_ContractV2/1, +dec_ContractV3/1, +dec_TypeInfoV1/1, +dec_TypeInfoV3/1 +]). + +-export([info/0]). + +-export([encode/2,decode/2]). + +encoding_rule() -> per. + +maps() -> false. + +bit_string_format() -> bitstring. + +legacy_erlang_types() -> false. + +encode(Type, Data) -> +try complete(encode_disp(Type, Data)) of + Bytes -> + {ok,Bytes} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + + +decode(Type, Data) -> +try + {Result,_Rest} = decode_disp(Type, Data), + {ok,Result} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + +encode_disp('GajumaruData', Data) -> enc_GajumaruData(Data); +encode_disp('Content', Data) -> enc_Content(Data); +encode_disp('TemplateFields', Data) -> enc_TemplateFields(Data); +encode_disp('TemplateField', Data) -> enc_TemplateField(Data); +encode_disp('Value', Data) -> enc_Value(Data); +encode_disp('KeyValue', Data) -> enc_KeyValue(Data); +encode_disp('Id', Data) -> enc_Id(Data); +encode_disp('Account', Data) -> enc_Account(Data); +encode_disp('SignedTx', Data) -> enc_SignedTx(Data); +encode_disp('ContractCode', Data) -> enc_ContractCode(Data); +encode_disp('ContractV1', Data) -> enc_ContractV1(Data); +encode_disp('ContractV2', Data) -> enc_ContractV2(Data); +encode_disp('ContractV3', Data) -> enc_ContractV3(Data); +encode_disp('TypeInfoV1', Data) -> enc_TypeInfoV1(Data); +encode_disp('TypeInfoV3', Data) -> enc_TypeInfoV3(Data); +encode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +decode_disp('GajumaruData', Data) -> dec_GajumaruData(Data); +decode_disp('Content', Data) -> dec_Content(Data); +decode_disp('TemplateFields', Data) -> dec_TemplateFields(Data); +decode_disp('TemplateField', Data) -> dec_TemplateField(Data); +decode_disp('Value', Data) -> dec_Value(Data); +decode_disp('KeyValue', Data) -> dec_KeyValue(Data); +decode_disp('Id', Data) -> dec_Id(Data); +decode_disp('Account', Data) -> dec_Account(Data); +decode_disp('SignedTx', Data) -> dec_SignedTx(Data); +decode_disp('ContractCode', Data) -> dec_ContractCode(Data); +decode_disp('ContractV1', Data) -> dec_ContractV1(Data); +decode_disp('ContractV2', Data) -> dec_ContractV2(Data); +decode_disp('ContractV3', Data) -> dec_ContractV3(Data); +decode_disp('TypeInfoV1', Data) -> dec_TypeInfoV1(Data); +decode_disp('TypeInfoV3', Data) -> dec_TypeInfoV3(Data); +decode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +info() -> + case ?MODULE:module_info(attributes) of + Attributes when is_list(Attributes) -> + case lists:keyfind(asn1_info, 1, Attributes) of + {_,Info} when is_list(Info) -> + Info; + _ -> + [] + end; + _ -> + [] + end. +enc_GajumaruData(Val) -> +[align, +begin +%% attribute tag(1) with type INTEGER +Enc1@element = element(2, Val), +encode_unconstrained_number(Enc1@element) +end, +begin +%% attribute vsn(2) with type INTEGER +Enc3@element = element(3, Val), +encode_unconstrained_number(Enc3@element) +end|begin +%% attribute content(3) with type Content +Enc5@element = element(4, Val), +enc_Content(Enc5@element) +end]. + + +dec_GajumaruData(Bytes) -> + +%% attribute tag(1) with type INTEGER +{Term1,Bytes1} = begin +V1@Pad3 = bit_size(Bytes) band 7, +{V1@V0,V1@Buf1} = case Bytes of +<<_:V1@Pad3,0:1,V1@V5:7,V1@Buf6/bitstring>> when V1@V5 =/= 0 -> +{V1@V5,V1@Buf6}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@Buf7/bitstring>> when V1@V6 =/= 0 -> +{V1@V6,V1@Buf7}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> when V1@V6 =/= 0 -> +V1@Mul8 = V1@V6 * 16384, +{V1@Mul8,V1@Buf7} +end, +<> = V1@Buf1, +{V1@V9,V1@Buf10} +end, + +%% attribute vsn(2) with type INTEGER +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@Buf4/bitstring>> when V2@V3 =/= 0 -> +{V2@V3,V2@Buf4}; +<<1:1,0:1,V2@V4:14,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +{V2@V4,V2@Buf5}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +V2@Mul6 = V2@V4 * 16384, +{V2@Mul6,V2@Buf5} +end, +<> = V2@Buf1, +{V2@V7,V2@Buf8} +end, + +%% attribute content(3) with type Content +{Term3,Bytes3} = dec_Content(Bytes2), +Res1 = {'GajumaruData',Term1,Term2,Term3}, +{Res1,Bytes3}. + +enc_Content(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= templateFields -> +[<<0:2>>|enc_TemplateFields(ChoiceVal)]; +ChoiceTag =:= account -> +[<<1:2>>|enc_Account(ChoiceVal)]; +ChoiceTag =:= signedTx -> +[<<2:2>>|enc_SignedTx(ChoiceVal)]; +ChoiceTag =:= contract -> +[<<3:2>>|enc_ContractCode(ChoiceVal)] +end. + + +dec_Content(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +dec_TemplateFields(Bytes1) +end, +{{templateFields,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +dec_Account(Bytes1) +end, +{{account,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +dec_SignedTx(Bytes1) +end, +{{signedTx,Val},NewBytes}; +3 -> +{Val,NewBytes} = begin +dec_ContractCode(Bytes1) +end, +{{contract,Val},NewBytes} +end. +enc_TemplateFields(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[align, +Enc1@len|[enc_TemplateField(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>|[enc_TemplateField(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TemplateField(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_TemplateFields(Bytes) -> +dec_components1(Bytes, []). + +enc_TemplateField(Val) -> +[begin +Enc1@element = element(2, Val), +if Enc1@element =:= asn1_NOVALUE -> +<<0:1>>; +true -> +<<1:1>> +end +end, +begin +%% attribute name(1) with type IA5String +Enc2@element = element(2, Val), +if Enc2@element =:= asn1_NOVALUE -> +[]; +true -> +begin +Enc3@bin = list_to_binary(Enc2@element), +Enc3@len = byte_size(Enc3@bin), +if Enc3@len < 128 -> +[align, +Enc3@len|Enc3@bin]; +Enc3@len < 16384 -> +[align, +<<2:2,Enc3@len:14>>|Enc3@bin]; +true -> +[align|encode_fragmented(Enc3@bin, 8)] +end +end +end +end|begin +%% attribute value(2) with type Value +Enc5@element = element(3, Val), +enc_Value(Enc5@element) +end]. + + +dec_TemplateField(Bytes) -> +{Opt,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute name(1) with type IA5String +{Term1,Bytes2} = case Opt band 1 of +1 -> +begin +V2@Pad3 = bit_size(Bytes1) band 7, +{V2@V0,V2@Buf1} = case Bytes1 of +<<_:V2@Pad3,0:1,V2@V5:7,V2@V7:V2@V5/binary-unit:8,V2@Buf8/bitstring>> -> +{V2@V7,V2@Buf8}; +<<_:V2@Pad3,1:1,0:1,V2@V6:14,V2@V8:V2@V6/binary-unit:8,V2@Buf9/bitstring>> -> +{V2@V8,V2@Buf9}; +<<_:V2@Pad3,1:1,1:1,V2@V6:6,V2@Buf7/bitstring>> -> +{V2@V8,V2@Buf9} = decode_fragmented(V2@V6, V2@Buf7, 8), +{V2@V8,V2@Buf9} +end, +V2@Conv10 = binary_to_list(V2@V0), +{V2@Conv10,V2@Buf1} +end; +0 -> +{asn1_NOVALUE,Bytes1} +end, + +%% attribute value(2) with type Value +{Term2,Bytes3} = dec_Value(Bytes2), +Res1 = {'TemplateField',Term1,Term2}, +{Res1,Bytes3}. + +enc_Value(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= intValue -> +[<<0:3>>, +align|encode_unconstrained_number(ChoiceVal)]; +ChoiceTag =:= boolValue -> +if ChoiceVal =:= false -> +<<1:3,0:1>>; +ChoiceVal =:= true -> +<<1:3,1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,ChoiceVal}}}) +end; +ChoiceTag =:= binaryValue -> +begin +Enc6@len = byte_size(ChoiceVal), +if Enc6@len < 128 -> +[<<2:3>>, +align, +Enc6@len|ChoiceVal]; +Enc6@len < 16384 -> +[<<2:3>>, +align, +<<2:2,Enc6@len:14>>|ChoiceVal]; +true -> +[<<2:3>>, +align|encode_fragmented(ChoiceVal, 8)] +end +end; +ChoiceTag =:= idValue -> +[<<3:3>>|enc_Id(ChoiceVal)]; +ChoiceTag =:= listValue -> +[<<4:3>>|enc_Value_listValue(ChoiceVal)]; +ChoiceTag =:= tupleValue -> +[<<5:3>>|enc_Value_tupleValue(ChoiceVal)]; +ChoiceTag =:= mapValue -> +[<<6:3>>|enc_Value_mapValue(ChoiceVal)] +end. +enc_Value_listValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[align, +Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + +enc_Value_tupleValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[align, +Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + +enc_Value_mapValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[align, +Enc1@len|[enc_KeyValue(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>|[enc_KeyValue(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_KeyValue(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_Value(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +begin +V2@Pad3 = bit_size(Bytes1) band 7, +{V2@V0,V2@Buf1} = case Bytes1 of +<<_:V2@Pad3,0:1,V2@V5:7,V2@Buf6/bitstring>> when V2@V5 =/= 0 -> +{V2@V5,V2@Buf6}; +<<_:V2@Pad3,1:1,0:1,V2@V6:14,V2@Buf7/bitstring>> when V2@V6 =/= 0 -> +{V2@V6,V2@Buf7}; +<<_:V2@Pad3,1:1,1:1,V2@V6:6,V2@Buf7/bitstring>> when V2@V6 =/= 0 -> +V2@Mul8 = V2@V6 * 16384, +{V2@Mul8,V2@Buf7} +end, +<> = V2@Buf1, +{V2@V9,V2@Buf10} +end +end, +{{intValue,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +begin +<> = Bytes1, +V3@Int2 = case V3@V0 of +0 -> false; +1 -> true +end, +{V3@Int2,V3@Buf1} +end +end, +{{boolValue,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +begin +V4@Pad3 = bit_size(Bytes1) band 7, +{V4@V0,V4@Buf1} = case Bytes1 of +<<_:V4@Pad3,0:1,V4@V5:7,V4@V7:V4@V5/binary-unit:8,V4@Buf8/bitstring>> -> +{V4@V7,V4@Buf8}; +<<_:V4@Pad3,1:1,0:1,V4@V6:14,V4@V8:V4@V6/binary-unit:8,V4@Buf9/bitstring>> -> +{V4@V8,V4@Buf9}; +<<_:V4@Pad3,1:1,1:1,V4@V6:6,V4@Buf7/bitstring>> -> +{V4@V8,V4@Buf9} = decode_fragmented(V4@V6, V4@Buf7, 8), +{V4@V8,V4@Buf9} +end, +V4@Conv10 = binary:copy(V4@V0), +{V4@Conv10,V4@Buf1} +end +end, +{{binaryValue,Val},NewBytes}; +3 -> +{Val,NewBytes} = begin +dec_Id(Bytes1) +end, +{{idValue,Val},NewBytes}; +4 -> +{Val,NewBytes} = begin +dec_Value_listValue(Bytes1) +end, +{{listValue,Val},NewBytes}; +5 -> +{Val,NewBytes} = begin +dec_Value_tupleValue(Bytes1) +end, +{{tupleValue,Val},NewBytes}; +6 -> +{Val,NewBytes} = begin +dec_Value_mapValue(Bytes1) +end, +{{mapValue,Val},NewBytes} +end. + +dec_Value_listValue(Bytes) -> +dec_components2(Bytes, []). + + +dec_Value_tupleValue(Bytes) -> +dec_components3(Bytes, []). + + +dec_Value_mapValue(Bytes) -> +dec_components4(Bytes, []). + +enc_KeyValue(Val) -> +[begin +%% attribute key(1) with type Value +Enc1@element = element(2, Val), +enc_Value(Enc1@element) +end|begin +%% attribute val(2) with type Value +Enc2@element = element(3, Val), +enc_Value(Enc2@element) +end]. + + +dec_KeyValue(Bytes) -> + +%% attribute key(1) with type Value +{Term1,Bytes1} = dec_Value(Bytes), + +%% attribute val(2) with type Value +{Term2,Bytes2} = dec_Value(Bytes1), +Res1 = {'KeyValue',Term1,Term2}, +{Res1,Bytes2}. + +enc_Id(Val) -> +[align, +begin +%% attribute type(1) with type INTEGER +Enc1@element = element(2, Val), +if Enc1@element bsr 8 =:= 0 -> +Enc1@element; +true -> +exit({error,{asn1,{illegal_integer,Enc1@element}}}) +end +end|begin +%% attribute value(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len =:= 32 -> +Enc3@element +end +end]. + + +dec_Id(Bytes) -> + +%% attribute type(1) with type INTEGER +{Term1,Bytes1} = begin +V1@Pad2 = bit_size(Bytes) band 7, +<<_:V1@Pad2,V1@V0:1/unsigned-unit:8,V1@Buf1/bitstring>> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute value(2) with type OCTET STRING +{Term2,Bytes2} = begin +<> = Bytes1, +V2@Conv2 = binary:copy(V2@V0), +{V2@Conv2,V2@Buf1} +end, +Res1 = {'Id',Term1,Term2}, +{Res1,Bytes2}. + +enc_Account(Val) -> +[align, +begin +%% attribute foo(1) with type INTEGER +Enc1@element = element(2, Val), +encode_unconstrained_number(Enc1@element) +end|begin +%% attribute bar(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end]. + + +dec_Account(Bytes) -> + +%% attribute foo(1) with type INTEGER +{Term1,Bytes1} = begin +V1@Pad3 = bit_size(Bytes) band 7, +{V1@V0,V1@Buf1} = case Bytes of +<<_:V1@Pad3,0:1,V1@V5:7,V1@Buf6/bitstring>> when V1@V5 =/= 0 -> +{V1@V5,V1@Buf6}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@Buf7/bitstring>> when V1@V6 =/= 0 -> +{V1@V6,V1@Buf7}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> when V1@V6 =/= 0 -> +V1@Mul8 = V1@V6 * 16384, +{V1@Mul8,V1@Buf7} +end, +<> = V1@Buf1, +{V1@V9,V1@Buf10} +end, + +%% attribute bar(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, +Res1 = {'Account',Term1,Term2}, +{Res1,Bytes2}. + +enc_SignedTx(Val) -> +[begin +%% attribute signatures(1) with type SEQUENCE OF +Enc1@element = element(2, Val), +enc_SignedTx_signatures(Enc1@element) +end, +align|begin +%% attribute transaction(2) with type OCTET STRING +Enc2@element = element(3, Val), +Enc3@len = byte_size(Enc2@element), +if Enc3@len < 128 -> +[Enc3@len|Enc2@element]; +Enc3@len < 16384 -> +[<<2:2,Enc3@len:14>>|Enc2@element]; +true -> +encode_fragmented(Enc2@element, 8) +end +end]. +enc_SignedTx_signatures(Val) -> +Enc2@len = length(Val), +if Enc2@len < 128 -> +[align, +Enc2@len|[begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[align, +Enc1@len, +align|Comp]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>, +align|Comp]; +true -> +[align|encode_fragmented(Comp, 8)] +end +end || Comp <- Val]]; +Enc2@len < 16384 -> +[align, +<<2:2,Enc2@len:14>>|[begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[align, +Enc1@len, +align|Comp]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>, +align|Comp]; +true -> +[align|encode_fragmented(Comp, 8)] +end +end || Comp <- Val]]; +true -> +begin +Enc2@fn = fun(Comp) -> begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[align, +Enc1@len, +align|Comp]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>, +align|Comp]; +true -> +[align|encode_fragmented(Comp, 8)] +end +end end, +encode_fragmented_sof(Enc2@fn, Val, Enc2@len) +end +end. + + + +dec_SignedTx(Bytes) -> + +%% attribute signatures(1) with type SEQUENCE OF +{Term1,Bytes1} = dec_SignedTx_signatures(Bytes), + +%% attribute transaction(2) with type OCTET STRING +{Term2,Bytes2} = begin +V1@Pad3 = bit_size(Bytes1) band 7, +{V1@V0,V1@Buf1} = case Bytes1 of +<<_:V1@Pad3,0:1,V1@V5:7,V1@V7:V1@V5/binary-unit:8,V1@Buf8/bitstring>> -> +{V1@V7,V1@Buf8}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@V8:V1@V6/binary-unit:8,V1@Buf9/bitstring>> -> +{V1@V8,V1@Buf9}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> -> +{V1@V8,V1@Buf9} = decode_fragmented(V1@V6, V1@Buf7, 8), +{V1@V8,V1@Buf9} +end, +V1@Conv10 = binary:copy(V1@V0), +{V1@Conv10,V1@Buf1} +end, +Res1 = {'SignedTx',Term1,Term2}, +{Res1,Bytes2}. + + +dec_SignedTx_signatures(Bytes) -> +dec_components5(Bytes, []). + +enc_ContractCode(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= v1 -> +[<<0:2>>|enc_ContractV1(ChoiceVal)]; +ChoiceTag =:= v2 -> +[<<1:2>>|enc_ContractV2(ChoiceVal)]; +ChoiceTag =:= v3 -> +[<<2:2>>|enc_ContractV3(ChoiceVal)] +end. + + +dec_ContractCode(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +dec_ContractV1(Bytes1) +end, +{{v1,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +dec_ContractV2(Bytes1) +end, +{{v2,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +dec_ContractV3(Bytes1) +end, +{{v3,Val},NewBytes} +end. +enc_ContractV1(Val) -> +[align, +begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV1_typeInfo(Enc3@element) +end, +align|begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end]. +enc_ContractV1_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[align, +Enc1@len|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV1(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV1(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +V1@Pad3 = bit_size(Bytes) band 7, +{V1@V0,V1@Buf1} = case Bytes of +<<_:V1@Pad3,0:1,V1@V5:7,V1@V7:V1@V5/binary-unit:8,V1@Buf8/bitstring>> -> +{V1@V7,V1@Buf8}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@V8:V1@V6/binary-unit:8,V1@Buf9/bitstring>> -> +{V1@V8,V1@Buf9}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> -> +{V1@V8,V1@Buf9} = decode_fragmented(V1@V6, V1@Buf7, 8), +{V1@V8,V1@Buf9} +end, +V1@Conv10 = binary:copy(V1@V0), +{V1@Conv10,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV1_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +V2@Pad3 = bit_size(Bytes2) band 7, +{V2@V0,V2@Buf1} = case Bytes2 of +<<_:V2@Pad3,0:1,V2@V5:7,V2@V7:V2@V5/binary-unit:8,V2@Buf8/bitstring>> -> +{V2@V7,V2@Buf8}; +<<_:V2@Pad3,1:1,0:1,V2@V6:14,V2@V8:V2@V6/binary-unit:8,V2@Buf9/bitstring>> -> +{V2@V8,V2@Buf9}; +<<_:V2@Pad3,1:1,1:1,V2@V6:6,V2@Buf7/bitstring>> -> +{V2@V8,V2@Buf9} = decode_fragmented(V2@V6, V2@Buf7, 8), +{V2@V8,V2@Buf9} +end, +V2@Conv10 = binary:copy(V2@V0), +{V2@Conv10,V2@Buf1} +end, +Res1 = {'ContractV1',Term1,Term2,Term3}, +{Res1,Bytes3}. + + +dec_ContractV1_typeInfo(Bytes) -> +dec_components6(Bytes, []). + +enc_ContractV2(Val) -> +[align, +begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV2_typeInfo(Enc3@element) +end, +align, +begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end|begin +%% attribute compilerVersion(4) with type OCTET STRING +Enc6@element = element(5, Val), +Enc7@len = byte_size(Enc6@element), +if Enc7@len < 128 -> +[Enc7@len|Enc6@element]; +Enc7@len < 16384 -> +[<<2:2,Enc7@len:14>>|Enc6@element]; +true -> +encode_fragmented(Enc6@element, 8) +end +end]. +enc_ContractV2_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[align, +Enc1@len|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV1(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV2(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +V1@Pad3 = bit_size(Bytes) band 7, +{V1@V0,V1@Buf1} = case Bytes of +<<_:V1@Pad3,0:1,V1@V5:7,V1@V7:V1@V5/binary-unit:8,V1@Buf8/bitstring>> -> +{V1@V7,V1@Buf8}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@V8:V1@V6/binary-unit:8,V1@Buf9/bitstring>> -> +{V1@V8,V1@Buf9}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> -> +{V1@V8,V1@Buf9} = decode_fragmented(V1@V6, V1@Buf7, 8), +{V1@V8,V1@Buf9} +end, +V1@Conv10 = binary:copy(V1@V0), +{V1@Conv10,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV2_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +V2@Pad3 = bit_size(Bytes2) band 7, +{V2@V0,V2@Buf1} = case Bytes2 of +<<_:V2@Pad3,0:1,V2@V5:7,V2@V7:V2@V5/binary-unit:8,V2@Buf8/bitstring>> -> +{V2@V7,V2@Buf8}; +<<_:V2@Pad3,1:1,0:1,V2@V6:14,V2@V8:V2@V6/binary-unit:8,V2@Buf9/bitstring>> -> +{V2@V8,V2@Buf9}; +<<_:V2@Pad3,1:1,1:1,V2@V6:6,V2@Buf7/bitstring>> -> +{V2@V8,V2@Buf9} = decode_fragmented(V2@V6, V2@Buf7, 8), +{V2@V8,V2@Buf9} +end, +V2@Conv10 = binary:copy(V2@V0), +{V2@Conv10,V2@Buf1} +end, + +%% attribute compilerVersion(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V3@V0,V3@Buf1} = case Bytes3 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, +Res1 = {'ContractV2',Term1,Term2,Term3,Term4}, +{Res1,Bytes4}. + + +dec_ContractV2_typeInfo(Bytes) -> +dec_components7(Bytes, []). + +enc_ContractV3(Val) -> +[align, +begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV3_typeInfo(Enc3@element) +end, +align, +begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end, +begin +%% attribute compilerVersion(4) with type OCTET STRING +Enc6@element = element(5, Val), +Enc7@len = byte_size(Enc6@element), +if Enc7@len < 128 -> +[Enc7@len|Enc6@element]; +Enc7@len < 16384 -> +[<<2:2,Enc7@len:14>>|Enc6@element]; +true -> +encode_fragmented(Enc6@element, 8) +end +end|begin +%% attribute payable(5) with type BOOLEAN +Enc8@element = element(6, Val), +if Enc8@element =:= false -> +<<0:1>>; +Enc8@element =:= true -> +<<1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,Enc8@element}}}) +end +end]. +enc_ContractV3_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[align, +Enc1@len|[enc_TypeInfoV3(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[align, +<<2:2,Enc1@len:14>>|[enc_TypeInfoV3(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV3(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV3(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +V1@Pad3 = bit_size(Bytes) band 7, +{V1@V0,V1@Buf1} = case Bytes of +<<_:V1@Pad3,0:1,V1@V5:7,V1@V7:V1@V5/binary-unit:8,V1@Buf8/bitstring>> -> +{V1@V7,V1@Buf8}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@V8:V1@V6/binary-unit:8,V1@Buf9/bitstring>> -> +{V1@V8,V1@Buf9}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> -> +{V1@V8,V1@Buf9} = decode_fragmented(V1@V6, V1@Buf7, 8), +{V1@V8,V1@Buf9} +end, +V1@Conv10 = binary:copy(V1@V0), +{V1@Conv10,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV3_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +V2@Pad3 = bit_size(Bytes2) band 7, +{V2@V0,V2@Buf1} = case Bytes2 of +<<_:V2@Pad3,0:1,V2@V5:7,V2@V7:V2@V5/binary-unit:8,V2@Buf8/bitstring>> -> +{V2@V7,V2@Buf8}; +<<_:V2@Pad3,1:1,0:1,V2@V6:14,V2@V8:V2@V6/binary-unit:8,V2@Buf9/bitstring>> -> +{V2@V8,V2@Buf9}; +<<_:V2@Pad3,1:1,1:1,V2@V6:6,V2@Buf7/bitstring>> -> +{V2@V8,V2@Buf9} = decode_fragmented(V2@V6, V2@Buf7, 8), +{V2@V8,V2@Buf9} +end, +V2@Conv10 = binary:copy(V2@V0), +{V2@Conv10,V2@Buf1} +end, + +%% attribute compilerVersion(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V3@V0,V3@Buf1} = case Bytes3 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, + +%% attribute payable(5) with type BOOLEAN +{Term5,Bytes5} = begin +<> = Bytes4, +V4@Int2 = case V4@V0 of +0 -> false; +1 -> true +end, +{V4@Int2,V4@Buf1} +end, +Res1 = {'ContractV3',Term1,Term2,Term3,Term4,Term5}, +{Res1,Bytes5}. + + +dec_ContractV3_typeInfo(Bytes) -> +dec_components8(Bytes, []). + +enc_TypeInfoV1(Val) -> +[align, +begin +%% attribute typeHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute name(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end, +begin +%% attribute argType(3) with type OCTET STRING +Enc5@element = element(4, Val), +Enc6@len = byte_size(Enc5@element), +if Enc6@len < 128 -> +[Enc6@len|Enc5@element]; +Enc6@len < 16384 -> +[<<2:2,Enc6@len:14>>|Enc5@element]; +true -> +encode_fragmented(Enc5@element, 8) +end +end|begin +%% attribute outType(4) with type OCTET STRING +Enc7@element = element(5, Val), +Enc8@len = byte_size(Enc7@element), +if Enc8@len < 128 -> +[Enc8@len|Enc7@element]; +Enc8@len < 16384 -> +[<<2:2,Enc8@len:14>>|Enc7@element]; +true -> +encode_fragmented(Enc7@element, 8) +end +end]. + + +dec_TypeInfoV1(Bytes) -> + +%% attribute typeHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +V1@Pad3 = bit_size(Bytes) band 7, +{V1@V0,V1@Buf1} = case Bytes of +<<_:V1@Pad3,0:1,V1@V5:7,V1@V7:V1@V5/binary-unit:8,V1@Buf8/bitstring>> -> +{V1@V7,V1@Buf8}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@V8:V1@V6/binary-unit:8,V1@Buf9/bitstring>> -> +{V1@V8,V1@Buf9}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> -> +{V1@V8,V1@Buf9} = decode_fragmented(V1@V6, V1@Buf7, 8), +{V1@V8,V1@Buf9} +end, +V1@Conv10 = binary:copy(V1@V0), +{V1@Conv10,V1@Buf1} +end, + +%% attribute name(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute argType(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V3@V0,V3@Buf1} = case Bytes2 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, + +%% attribute outType(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V4@V0,V4@Buf1} = case Bytes3 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end, +Res1 = {'TypeInfoV1',Term1,Term2,Term3,Term4}, +{Res1,Bytes4}. + +enc_TypeInfoV3(Val) -> +[align, +begin +%% attribute typeHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute name(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end, +begin +%% attribute payable(3) with type BOOLEAN +Enc5@element = element(4, Val), +if Enc5@element =:= false -> +<<0:1,0:7>>; +Enc5@element =:= true -> +<<1:1,0:7>>; +true -> +exit({error,{asn1,{illegal_boolean,Enc5@element}}}) +end +end, +begin +%% attribute argType(4) with type OCTET STRING +Enc7@element = element(5, Val), +Enc8@len = byte_size(Enc7@element), +if Enc8@len < 128 -> +[Enc8@len|Enc7@element]; +Enc8@len < 16384 -> +[<<2:2,Enc8@len:14>>|Enc7@element]; +true -> +encode_fragmented(Enc7@element, 8) +end +end|begin +%% attribute outType(5) with type OCTET STRING +Enc9@element = element(6, Val), +Enc10@len = byte_size(Enc9@element), +if Enc10@len < 128 -> +[Enc10@len|Enc9@element]; +Enc10@len < 16384 -> +[<<2:2,Enc10@len:14>>|Enc9@element]; +true -> +encode_fragmented(Enc9@element, 8) +end +end]. + + +dec_TypeInfoV3(Bytes) -> + +%% attribute typeHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +V1@Pad3 = bit_size(Bytes) band 7, +{V1@V0,V1@Buf1} = case Bytes of +<<_:V1@Pad3,0:1,V1@V5:7,V1@V7:V1@V5/binary-unit:8,V1@Buf8/bitstring>> -> +{V1@V7,V1@Buf8}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@V8:V1@V6/binary-unit:8,V1@Buf9/bitstring>> -> +{V1@V8,V1@Buf9}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> -> +{V1@V8,V1@Buf9} = decode_fragmented(V1@V6, V1@Buf7, 8), +{V1@V8,V1@Buf9} +end, +V1@Conv10 = binary:copy(V1@V0), +{V1@Conv10,V1@Buf1} +end, + +%% attribute name(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute payable(3) with type BOOLEAN +{Term3,Bytes3} = begin +<> = Bytes2, +V3@Int2 = case V3@V0 of +0 -> false; +1 -> true +end, +{V3@Int2,V3@Buf1} +end, + +%% attribute argType(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V4@V0,V4@Buf1} = case Bytes3 of +<<_:7,0:1,V4@V4:7,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<_:7,1:1,0:1,V4@V5:14,V4@V7:V4@V5/binary-unit:8,V4@Buf8/bitstring>> -> +{V4@V7,V4@Buf8}; +<<_:7,1:1,1:1,V4@V5:6,V4@Buf6/bitstring>> -> +{V4@V7,V4@Buf8} = decode_fragmented(V4@V5, V4@Buf6, 8), +{V4@V7,V4@Buf8} +end, +V4@Conv9 = binary:copy(V4@V0), +{V4@Conv9,V4@Buf1} +end, + +%% attribute outType(5) with type OCTET STRING +{Term5,Bytes5} = begin +{V5@V0,V5@Buf1} = case Bytes4 of +<<0:1,V5@V3:7,V5@V5:V5@V3/binary-unit:8,V5@Buf6/bitstring>> -> +{V5@V5,V5@Buf6}; +<<1:1,0:1,V5@V4:14,V5@V6:V5@V4/binary-unit:8,V5@Buf7/bitstring>> -> +{V5@V6,V5@Buf7}; +<<1:1,1:1,V5@V4:6,V5@Buf5/bitstring>> -> +{V5@V6,V5@Buf7} = decode_fragmented(V5@V4, V5@Buf5, 8), +{V5@V6,V5@Buf7} +end, +V5@Conv8 = binary:copy(V5@V0), +{V5@Conv8,V5@Buf1} +end, +Res1 = {'TypeInfoV3',Term1,Term2,Term3,Term4,Term5}, +{Res1,Bytes5}. + + +%%% +%%% Run-time functions. +%%% + +'dialyzer-suppressions'(Arg) -> + _ = complete(element(1, Arg)), + ok. + +dec_components1(Bytes, Acc) -> +%% Length with constraint no +V1@Pad3 = bit_size(Bytes) band 7, +{V1@V0,V1@Buf1} = case Bytes of +<<_:V1@Pad3,0:1,V1@V5:7,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<_:V1@Pad3,1:1,0:1,V1@V6:14,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<_:V1@Pad3,1:1,1:1,V1@V6:6,V1@Buf7/bitstring>> -> +V1@Mul8 = V1@V6 * 16384, +{V1@Mul8,V1@Buf7} +end, +{Acc1,Buf1} = dec_fragment9(V1@V0, V1@Buf1, Acc), +if V1@V0 >= 16384 -> +dec_components1(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components2(Bytes, Acc) -> +%% Length with constraint no +V2@Pad3 = bit_size(Bytes) band 7, +{V2@V0,V2@Buf1} = case Bytes of +<<_:V2@Pad3,0:1,V2@V5:7,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<_:V2@Pad3,1:1,0:1,V2@V6:14,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<_:V2@Pad3,1:1,1:1,V2@V6:6,V2@Buf7/bitstring>> -> +V2@Mul8 = V2@V6 * 16384, +{V2@Mul8,V2@Buf7} +end, +{Acc1,Buf1} = dec_fragment10(V2@V0, V2@Buf1, Acc), +if V2@V0 >= 16384 -> +dec_components2(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components3(Bytes, Acc) -> +%% Length with constraint no +V3@Pad3 = bit_size(Bytes) band 7, +{V3@V0,V3@Buf1} = case Bytes of +<<_:V3@Pad3,0:1,V3@V5:7,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<_:V3@Pad3,1:1,0:1,V3@V6:14,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<_:V3@Pad3,1:1,1:1,V3@V6:6,V3@Buf7/bitstring>> -> +V3@Mul8 = V3@V6 * 16384, +{V3@Mul8,V3@Buf7} +end, +{Acc1,Buf1} = dec_fragment11(V3@V0, V3@Buf1, Acc), +if V3@V0 >= 16384 -> +dec_components3(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components4(Bytes, Acc) -> +%% Length with constraint no +V4@Pad3 = bit_size(Bytes) band 7, +{V4@V0,V4@Buf1} = case Bytes of +<<_:V4@Pad3,0:1,V4@V5:7,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<_:V4@Pad3,1:1,0:1,V4@V6:14,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<_:V4@Pad3,1:1,1:1,V4@V6:6,V4@Buf7/bitstring>> -> +V4@Mul8 = V4@V6 * 16384, +{V4@Mul8,V4@Buf7} +end, +{Acc1,Buf1} = dec_fragment12(V4@V0, V4@Buf1, Acc), +if V4@V0 >= 16384 -> +dec_components4(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components5(Bytes, Acc) -> +%% Length with constraint no +V5@Pad3 = bit_size(Bytes) band 7, +{V5@V0,V5@Buf1} = case Bytes of +<<_:V5@Pad3,0:1,V5@V5:7,V5@Buf6/bitstring>> -> +{V5@V5,V5@Buf6}; +<<_:V5@Pad3,1:1,0:1,V5@V6:14,V5@Buf7/bitstring>> -> +{V5@V6,V5@Buf7}; +<<_:V5@Pad3,1:1,1:1,V5@V6:6,V5@Buf7/bitstring>> -> +V5@Mul8 = V5@V6 * 16384, +{V5@Mul8,V5@Buf7} +end, +{Acc1,Buf1} = dec_fragment13(V5@V0, V5@Buf1, Acc), +if V5@V0 >= 16384 -> +dec_components5(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components6(Bytes, Acc) -> +%% Length with constraint no +V6@Pad3 = bit_size(Bytes) band 7, +{V6@V0,V6@Buf1} = case Bytes of +<<_:V6@Pad3,0:1,V6@V5:7,V6@Buf6/bitstring>> -> +{V6@V5,V6@Buf6}; +<<_:V6@Pad3,1:1,0:1,V6@V6:14,V6@Buf7/bitstring>> -> +{V6@V6,V6@Buf7}; +<<_:V6@Pad3,1:1,1:1,V6@V6:6,V6@Buf7/bitstring>> -> +V6@Mul8 = V6@V6 * 16384, +{V6@Mul8,V6@Buf7} +end, +{Acc1,Buf1} = dec_fragment14(V6@V0, V6@Buf1, Acc), +if V6@V0 >= 16384 -> +dec_components6(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components7(Bytes, Acc) -> +%% Length with constraint no +V7@Pad3 = bit_size(Bytes) band 7, +{V7@V0,V7@Buf1} = case Bytes of +<<_:V7@Pad3,0:1,V7@V5:7,V7@Buf6/bitstring>> -> +{V7@V5,V7@Buf6}; +<<_:V7@Pad3,1:1,0:1,V7@V6:14,V7@Buf7/bitstring>> -> +{V7@V6,V7@Buf7}; +<<_:V7@Pad3,1:1,1:1,V7@V6:6,V7@Buf7/bitstring>> -> +V7@Mul8 = V7@V6 * 16384, +{V7@Mul8,V7@Buf7} +end, +{Acc1,Buf1} = dec_fragment15(V7@V0, V7@Buf1, Acc), +if V7@V0 >= 16384 -> +dec_components7(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components8(Bytes, Acc) -> +%% Length with constraint no +V8@Pad3 = bit_size(Bytes) band 7, +{V8@V0,V8@Buf1} = case Bytes of +<<_:V8@Pad3,0:1,V8@V5:7,V8@Buf6/bitstring>> -> +{V8@V5,V8@Buf6}; +<<_:V8@Pad3,1:1,0:1,V8@V6:14,V8@Buf7/bitstring>> -> +{V8@V6,V8@Buf7}; +<<_:V8@Pad3,1:1,1:1,V8@V6:6,V8@Buf7/bitstring>> -> +V8@Mul8 = V8@V6 * 16384, +{V8@Mul8,V8@Buf7} +end, +{Acc1,Buf1} = dec_fragment16(V8@V0, V8@Buf1, Acc), +if V8@V0 >= 16384 -> +dec_components8(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_fragment10(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment10(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment10(Num-1, Remain, [Term|Acc]). + +dec_fragment11(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment11(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment11(Num-1, Remain, [Term|Acc]). + +dec_fragment12(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment12(Num, Bytes, Acc) -> +{Term,Remain} = dec_KeyValue(Bytes), +dec_fragment12(Num-1, Remain, [Term|Acc]). + +dec_fragment13(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment13(Num, Bytes, Acc) -> +{Term,Remain} = begin +V9@Pad3 = bit_size(Bytes) band 7, +{V9@V0,V9@Buf1} = case Bytes of +<<_:V9@Pad3,0:1,V9@V5:7,V9@V7:V9@V5/binary-unit:8,V9@Buf8/bitstring>> -> +{V9@V7,V9@Buf8}; +<<_:V9@Pad3,1:1,0:1,V9@V6:14,V9@V8:V9@V6/binary-unit:8,V9@Buf9/bitstring>> -> +{V9@V8,V9@Buf9}; +<<_:V9@Pad3,1:1,1:1,V9@V6:6,V9@Buf7/bitstring>> -> +{V9@V8,V9@Buf9} = decode_fragmented(V9@V6, V9@Buf7, 8), +{V9@V8,V9@Buf9} +end, +V9@Conv10 = binary:copy(V9@V0), +{V9@Conv10,V9@Buf1} +end, +dec_fragment13(Num-1, Remain, [Term|Acc]). + +dec_fragment14(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment14(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV1(Bytes), +dec_fragment14(Num-1, Remain, [Term|Acc]). + +dec_fragment15(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment15(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV1(Bytes), +dec_fragment15(Num-1, Remain, [Term|Acc]). + +dec_fragment16(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment16(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV3(Bytes), +dec_fragment16(Num-1, Remain, [Term|Acc]). + +dec_fragment9(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment9(Num, Bytes, Acc) -> +{Term,Remain} = dec_TemplateField(Bytes), +dec_fragment9(Num-1, Remain, [Term|Acc]). + +complete(L0) -> + L = complete(L0, []), + case list_to_bitstring(L) of + <<>> -> + <<0>>; + Bin -> + Bin + end. + +complete([], Bits, []) -> + case Bits band 7 of + 0 -> + []; + N -> + [<<0:(8 - N)>>] + end; +complete([], Bits, [H | More]) -> + complete(H, Bits, More); +complete([align | T], Bits, More) -> + case Bits band 7 of + 0 -> + complete(T, More); + 1 -> + [<<0:7>> | complete(T, More)]; + 2 -> + [<<0:6>> | complete(T, More)]; + 3 -> + [<<0:5>> | complete(T, More)]; + 4 -> + [<<0:4>> | complete(T, More)]; + 5 -> + [<<0:3>> | complete(T, More)]; + 6 -> + [<<0:2>> | complete(T, More)]; + 7 -> + [<<0:1>> | complete(T, More)] + end; +complete([[] | T], Bits, More) -> + complete(T, Bits, More); +complete([[_ | _] = H], Bits, More) -> + complete(H, Bits, More); +complete([[_ | _] = H | T], Bits, More) -> + complete(H, Bits, [T | More]); +complete([H | T], Bits, More) when is_integer(H); is_binary(H) -> + [H | complete(T, Bits, More)]; +complete([H | T], Bits, More) -> + [H | complete(T, Bits + bit_size(H), More)]; +complete(Bin, Bits, More) when is_binary(Bin) -> + [Bin | complete([], Bits, More)]; +complete(Bin, Bits, More) -> + [Bin | complete([], Bits + bit_size(Bin), More)]. + +complete([], []) -> + []; +complete([], [H | More]) -> + complete(H, More); +complete([align | T], More) -> + complete(T, More); +complete([[] | T], More) -> + complete(T, More); +complete([[_ | _] = H], More) -> + complete(H, More); +complete([[_ | _] = H | T], More) -> + complete(H, [T | More]); +complete([H | T], More) when is_integer(H); is_binary(H) -> + [H | complete(T, More)]; +complete([H | T], More) -> + [H | complete(T, bit_size(H), More)]; +complete(Bin, More) when is_binary(Bin) -> + [Bin | complete([], More)]; +complete(Bin, More) -> + [Bin | complete([], bit_size(Bin), More)]. + +decode_fragmented(SegSz0, Buf0, Unit) -> + SegSz = SegSz0 * Unit * 16384, + <> = Buf0, + decode_fragmented_1(Buf, Unit, Res). + +decode_fragmented_1(<<0:1,N:7,Buf0/bitstring>>, Unit, Res) -> + Sz = N * Unit, + <> = Buf0, + {<>, Buf}; +decode_fragmented_1(<<1:1,0:1,N:14,Buf0/bitstring>>, Unit, Res) -> + Sz = N * Unit, + <> = Buf0, + {<>, Buf}; +decode_fragmented_1(<<1:1,1:1,SegSz0:6,Buf0/bitstring>>, Unit, Res0) -> + SegSz = SegSz0 * Unit * 16384, + <> = Buf0, + Res = <>, + decode_fragmented_1(Buf, Unit, Res). + +encode_components(Cs, _Encoder, 0, Acc) -> + {Cs, lists:reverse(Acc)}; +encode_components([C | Cs], Encoder, Size, Acc) -> + B = Encoder(C), + encode_components(Cs, Encoder, Size - 1, [B | Acc]). + +encode_fragmented(Bin, Unit) -> + encode_fragmented_1(Bin, Unit, 4). + +encode_fragmented_1(Bin, Unit, N) -> + SegSz = Unit * N * 16384, + case Bin of + <> -> + [<<3:2,N:6>>, B | encode_fragmented_1(T, Unit, N)]; + _ when N > 1 -> + encode_fragmented_1(Bin, Unit, N - 1); + _ -> + case bit_size(Bin) div Unit of + Len when Len < 128 -> + [Len, Bin]; + Len when Len < 16384 -> + [<<2:2,Len:14>>, Bin] + end + end. + +encode_fragmented_sof(Fun, Comps, Len) -> + encode_fragmented_sof_1(Fun, Comps, Len, 4). + +encode_fragmented_sof_1(Encoder, Comps0, Len0, N) -> + SegSz = N * 16384, + if + Len0 >= SegSz -> + {Comps, B} = encode_components(Comps0, Encoder, SegSz, []), + Len = Len0 - SegSz, + [align, + <<3:2,N:6>>, + B | + encode_fragmented_sof_1(Encoder, Comps, Len, N)]; + N > 1 -> + encode_fragmented_sof_1(Encoder, Comps0, Len0, N - 1); + Len0 < 128 -> + {[], B} = encode_components(Comps0, Encoder, Len0, []), + [align, Len0 | B]; + Len0 < 16384 -> + {[], B} = encode_components(Comps0, Encoder, Len0, []), + [align, <<2:2,Len0:14>> | B] + end. + +encode_unconstrained_number(Val) when not is_integer(Val) -> + exit({error, {asn1, {illegal_integer, Val}}}); +encode_unconstrained_number(Val) when Val >= 0 -> + if + Val < 128 -> + [1, Val]; + Val < 256 -> + [<<2,0>>, Val]; + true -> + case binary:encode_unsigned(Val) of + <<0:1,_/bitstring>> = Bin -> + case byte_size(Bin) of + Sz when Sz < 128 -> + [Sz, Bin]; + Sz when Sz < 16384 -> + [<<2:2,Sz:14>>, Bin] + end; + <<1:1,_/bitstring>> = Bin -> + case byte_size(Bin) + 1 of + Sz when Sz < 128 -> + [Sz, 0, Bin]; + Sz when Sz < 16384 -> + [<<2:2,Sz:14,0:8>>, Bin] + end + end + end; +encode_unconstrained_number(Val) -> + Oct = enint(Val, []), + Len = length(Oct), + if + Len < 128 -> + [Len | Oct]; + Len < 16384 -> + [<<2:2,Len:14>> | Oct] + end. + +enint(-1, [B1 | T]) when B1 > 127 -> + [B1 | T]; +enint(N, Acc) -> + enint(N bsr 8, [N band 255 | Acc]). diff --git a/asn1_per/GajumaruSerialization.hrl b/asn1_per/GajumaruSerialization.hrl new file mode 100644 index 0000000..4c5d52e --- /dev/null +++ b/asn1_per/GajumaruSerialization.hrl @@ -0,0 +1,76 @@ +%% Generated by the Erlang ASN.1 compiler. Version: 5.4.3 +%% Purpose: Erlang record definitions for each named and unnamed +%% SEQUENCE and SET, and macro definitions for each value +%% definition in module GajumaruSerialization. + +-ifndef(_GAJUMARUSERIALIZATION_HRL_). +-define(_GAJUMARUSERIALIZATION_HRL_, true). + +-record('GajumaruData', { + tag, + vsn, + content +}). + +-record('TemplateField', { + name = asn1_NOVALUE, + value +}). + +-record('KeyValue', { + key, + val +}). + +-record('Id', { + type, + value +}). + +-record('Account', { + foo, + bar +}). + +-record('SignedTx', { + signatures, + transaction +}). + +-record('ContractV1', { + sourceHash, + typeInfo, + byteCode +}). + +-record('ContractV2', { + sourceHash, + typeInfo, + byteCode, + compilerVersion +}). + +-record('ContractV3', { + sourceHash, + typeInfo, + byteCode, + compilerVersion, + payable +}). + +-record('TypeInfoV1', { + typeHash, + name, + argType, + outType +}). + +-record('TypeInfoV3', { + typeHash, + name, + payable, + argType, + outType +}). + +-endif. %% _GAJUMARUSERIALIZATION_HRL_ diff --git a/asn1_uper/GajumaruSerialization.asn b/asn1_uper/GajumaruSerialization.asn new file mode 100644 index 0000000..43607e9 --- /dev/null +++ b/asn1_uper/GajumaruSerialization.asn @@ -0,0 +1,225 @@ +-- GajumaruSerialization.asn +-- +-- ASN.1 model for the structures serialized by gmserialization.erl +-- (the layer on top of RLP). +-- +-- Purpose: +-- * Provide a formal, toolable description of the data. +-- * Enable migration from the legacy RLP-based format to DER. +-- +-- Detection of legacy vs new: +-- Legacy data (produced by gmserialization:serialize / gmser_chain_objects:serialize +-- or gmser_dyn:serialize) is always an RLP *list* at the top level. +-- This means the first byte is in the range 0xC0 .. 0xFF. +-- +-- DER-encoded data using the types below will start with 0x30 (SEQUENCE, +-- constructed, universal tag) for the outermost GajumaruData (or any +-- top-level SEQUENCE we define). 0x30 < 0xC0, so a single-byte prefix +-- check reliably distinguishes the two formats. +-- +-- Usage in Erlang (after compiling with asn1ct): +-- {ok, Mod} = asn1ct:compile(GajumaruSerialization.asn, [ber, der]). +-- {ok, Term} = 'GajumaruSerialization':decode('GajumaruData', DerBinary). +-- +-- Notes on type mapping from gmserialization.erl: +-- - int -> INTEGER (new data uses canonical DER INTEGER) +-- - binary -> OCTET STRING +-- - bool -> BOOLEAN +-- - id -> Id (SEQUENCE) (cleaner than the legacy packed 33-byte form) +-- - [T] -> SEQUENCE OF T +-- - {T1,...} -> SEQUENCE (fixed-size, order matters) +-- - #{items := [{K,T},...]} -> SEQUENCE with the fields in template order +-- (static maps carry *values only*, no keys on the wire) +-- - tag + vsn are preserved as the first two fields for compatibility +-- with existing dispatch logic. +-- +-- Legacy integers had strict unsigned-minimal no-leading-zero (except for 0) +-- and RLP-level rules. New DER data does not need to follow those rules. +-- +-- WARNING: +-- Any cryptographic hash or signature computed over a serialized object +-- will change when switching from RLP to DER for that object. Plan a +-- coordinated upgrade. + +GajumaruSerialization DEFINITIONS + AUTOMATIC TAGS ::= +BEGIN + +EXPORTS ALL; + +-- ============================================================ +-- Top-level wrapper used for new DER data. +-- This is what a decoder will see first. +-- ============================================================ + +GajumaruData ::= SEQUENCE { + tag INTEGER, + vsn INTEGER, + content Content +} + +-- Content can be a specific structured type (preferred) or a generic +-- representation of a template-driven object. +Content ::= CHOICE { + -- Generic fallback that can represent any [{Field, Type}] template + -- without having a pre-defined SEQUENCE for every object. + templateFields [0] TemplateFields, + + -- Examples of concrete versioned types (extend as needed) + account [1] Account, + signedTx [2] SignedTx, + contract [3] ContractCode + -- Add more alternatives for other tags from gmser_chain_objects +} + +-- ============================================================ +-- Generic template-driven representation +-- (useful during transition or for unregistered types) +-- ============================================================ + +TemplateFields ::= SEQUENCE OF TemplateField + +TemplateField ::= SEQUENCE { + -- Field name is included for debuggability / generic processing. + -- In the original static encoding the name is NOT on the wire; + -- only position and type matter. We include it here for convenience. + name IA5String OPTIONAL, + value Value +} + +Value ::= CHOICE { + intValue [0] INTEGER, + boolValue [1] BOOLEAN, + binaryValue [2] OCTET STRING, + idValue [3] Id, + listValue [4] SEQUENCE OF Value, + tupleValue [5] SEQUENCE OF Value, + mapValue [6] SEQUENCE OF KeyValue -- only needed if you want to + -- represent dynamic-style maps +} + +KeyValue ::= SEQUENCE { + key Value, + val Value +} + +-- ============================================================ +-- Common types +-- ============================================================ + +Id ::= SEQUENCE { + -- Corresponds to the simple tags in gmser_id (account=1, name=2, etc.) + -- and the extended account subtype (high bit in legacy). + type INTEGER (0..255), + value OCTET STRING (SIZE (32)) +} + +-- ============================================================ +-- Concrete object examples (derived from usage in the codebase) +-- Add / evolve per version as you introduce new vsns. +-- ============================================================ + +-- Example: a very simple account-like object used in tests +Account ::= SEQUENCE { + foo INTEGER, + bar OCTET STRING +} + +-- Simplified signed transaction +SignedTx ::= SEQUENCE { + signatures SEQUENCE OF OCTET STRING, + transaction OCTET STRING +} + +-- Contract code objects (see gmser_contract_code.erl) +-- We model the three versions that exist today. +ContractCode ::= CHOICE { + v1 [0] ContractV1, + v2 [1] ContractV2, + v3 [2] ContractV3 +} + +ContractV1 ::= SEQUENCE { + sourceHash OCTET STRING, + -- typeInfo is a list of 4-tuples in legacy: + -- {typeHash, name, argType, outType} + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING +} + +ContractV2 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV1, + byteCode OCTET STRING, + compilerVersion OCTET STRING +} + +ContractV3 ::= SEQUENCE { + sourceHash OCTET STRING, + typeInfo SEQUENCE OF TypeInfoV3, + byteCode OCTET STRING, + compilerVersion OCTET STRING, + payable BOOLEAN +} + +TypeInfoV1 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + argType OCTET STRING, + outType OCTET STRING +} + +TypeInfoV3 ::= SEQUENCE { + typeHash OCTET STRING, + name OCTET STRING, + payable BOOLEAN, + argType OCTET STRING, + outType OCTET STRING +} + +-- ============================================================ +-- Notes for implementers +-- ============================================================ +-- 1. Detection (recommended decoder entry point): +-- +-- decode(Binary) -> +-- case Binary of +-- <> when B >= 16#C0 -> +-- decode_legacy_rlp(Binary); % existing gmser_* path +-- _ -> +-- {ok, Term} = +-- 'GajumaruSerialization':decode('GajumaruData', Binary), +-- Term +-- end. +-- +-- This works because: +-- - All current top-level output from serialize() is an RLP list +-- (first byte 0xC0-0xFF). +-- - GajumaruData and the concrete choices above are SEQUENCEs +-- (first byte 0x30 for short form, or 0x30 0x81/0x82... for long). +-- +-- 2. When you add a new object type or version, prefer adding a +-- concrete SEQUENCE alternative in the Content CHOICE rather than +-- always falling back to TemplateFields. This gives you better +-- validation and generated types. +-- +-- 3. INTEGER in DER is signed and uses a different minimal encoding +-- than the legacy unsigned big-endian no leading zero form. This is +-- fine for new data. +-- +-- 4. If you need to preserve exact legacy integer wire bytes inside +-- the new format (e.g. for some hash preimage reason), you can +-- carry selected integers as OCTET STRING (legacy unsigned minimal bytes). +-- +-- 5. Dynamic encoding (gmser_dyn) is intentionally not modeled here +-- in full, because it is runtime-schema driven (type codes 246-255, +-- labels, alt/switch, etc.). You can still use the generic +-- TemplateFields + Value for some dynamic cases, or model specific +-- message schemas as additional CHOICE arms. +-- +-- 6. Compile with DER for canonical output: +-- asn1ct:compile(GajumaruSerialization, [der]). +-- +-- The ber option is also accepted; der implies the stricter rules. + +END diff --git a/asn1_uper/GajumaruSerialization.asn1db b/asn1_uper/GajumaruSerialization.asn1db new file mode 100644 index 0000000..d8f757f Binary files /dev/null and b/asn1_uper/GajumaruSerialization.asn1db differ diff --git a/asn1_uper/GajumaruSerialization.erl b/asn1_uper/GajumaruSerialization.erl new file mode 100644 index 0000000..8aa109a --- /dev/null +++ b/asn1_uper/GajumaruSerialization.erl @@ -0,0 +1,1641 @@ +%% Generated by the Erlang ASN.1 PER (unaligned) compiler. Version: 5.4.3 +%% Purpose: Encoding and decoding of the types in GajumaruSerialization. + +-module('GajumaruSerialization'). +-moduledoc false. +-compile(nowarn_unused_vars). +-dialyzer(no_improper_lists). +-dialyzer(no_match). +-include("GajumaruSerialization.hrl"). +-asn1_info([{vsn,'5.4.3'}, + {module,'GajumaruSerialization'}, + {options,[uper,{outdir,"asn1_uper"},{i,"."},{i,"asn1_uper"}]}]). + +-export([encoding_rule/0,maps/0,bit_string_format/0, + legacy_erlang_types/0]). +-export(['dialyzer-suppressions'/1]). +-export([ +enc_GajumaruData/1, +enc_Content/1, +enc_TemplateFields/1, +enc_TemplateField/1, +enc_Value/1, +enc_KeyValue/1, +enc_Id/1, +enc_Account/1, +enc_SignedTx/1, +enc_ContractCode/1, +enc_ContractV1/1, +enc_ContractV2/1, +enc_ContractV3/1, +enc_TypeInfoV1/1, +enc_TypeInfoV3/1 +]). + +-export([ +dec_GajumaruData/1, +dec_Content/1, +dec_TemplateFields/1, +dec_TemplateField/1, +dec_Value/1, +dec_KeyValue/1, +dec_Id/1, +dec_Account/1, +dec_SignedTx/1, +dec_ContractCode/1, +dec_ContractV1/1, +dec_ContractV2/1, +dec_ContractV3/1, +dec_TypeInfoV1/1, +dec_TypeInfoV3/1 +]). + +-export([info/0]). + +-export([encode/2,decode/2]). + +encoding_rule() -> uper. + +maps() -> false. + +bit_string_format() -> bitstring. + +legacy_erlang_types() -> false. + +encode(Type, Data) -> +try complete(encode_disp(Type, Data)) of + Bytes -> + {ok,Bytes} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + + +decode(Type, Data) -> +try + {Result,_Rest} = decode_disp(Type, Data), + {ok,Result} + catch + Class:Exception:Stk when Class =:= error; Class =:= exit -> + case Exception of + {error,{asn1,Reason}} -> + {error,{asn1,{Reason,Stk}}}; + Reason -> + {error,{asn1,{Reason,Stk}}} + end +end. + +encode_disp('GajumaruData', Data) -> enc_GajumaruData(Data); +encode_disp('Content', Data) -> enc_Content(Data); +encode_disp('TemplateFields', Data) -> enc_TemplateFields(Data); +encode_disp('TemplateField', Data) -> enc_TemplateField(Data); +encode_disp('Value', Data) -> enc_Value(Data); +encode_disp('KeyValue', Data) -> enc_KeyValue(Data); +encode_disp('Id', Data) -> enc_Id(Data); +encode_disp('Account', Data) -> enc_Account(Data); +encode_disp('SignedTx', Data) -> enc_SignedTx(Data); +encode_disp('ContractCode', Data) -> enc_ContractCode(Data); +encode_disp('ContractV1', Data) -> enc_ContractV1(Data); +encode_disp('ContractV2', Data) -> enc_ContractV2(Data); +encode_disp('ContractV3', Data) -> enc_ContractV3(Data); +encode_disp('TypeInfoV1', Data) -> enc_TypeInfoV1(Data); +encode_disp('TypeInfoV3', Data) -> enc_TypeInfoV3(Data); +encode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +decode_disp('GajumaruData', Data) -> dec_GajumaruData(Data); +decode_disp('Content', Data) -> dec_Content(Data); +decode_disp('TemplateFields', Data) -> dec_TemplateFields(Data); +decode_disp('TemplateField', Data) -> dec_TemplateField(Data); +decode_disp('Value', Data) -> dec_Value(Data); +decode_disp('KeyValue', Data) -> dec_KeyValue(Data); +decode_disp('Id', Data) -> dec_Id(Data); +decode_disp('Account', Data) -> dec_Account(Data); +decode_disp('SignedTx', Data) -> dec_SignedTx(Data); +decode_disp('ContractCode', Data) -> dec_ContractCode(Data); +decode_disp('ContractV1', Data) -> dec_ContractV1(Data); +decode_disp('ContractV2', Data) -> dec_ContractV2(Data); +decode_disp('ContractV3', Data) -> dec_ContractV3(Data); +decode_disp('TypeInfoV1', Data) -> dec_TypeInfoV1(Data); +decode_disp('TypeInfoV3', Data) -> dec_TypeInfoV3(Data); +decode_disp(Type, _Data) -> exit({error,{asn1,{undefined_type,Type}}}). + +info() -> + case ?MODULE:module_info(attributes) of + Attributes when is_list(Attributes) -> + case lists:keyfind(asn1_info, 1, Attributes) of + {_,Info} when is_list(Info) -> + Info; + _ -> + [] + end; + _ -> + [] + end. +enc_GajumaruData(Val) -> +[begin +%% attribute tag(1) with type INTEGER +Enc1@element = element(2, Val), +encode_unconstrained_number(Enc1@element) +end, +begin +%% attribute vsn(2) with type INTEGER +Enc3@element = element(3, Val), +encode_unconstrained_number(Enc3@element) +end|begin +%% attribute content(3) with type Content +Enc5@element = element(4, Val), +enc_Content(Enc5@element) +end]. + + +dec_GajumaruData(Bytes) -> + +%% attribute tag(1) with type INTEGER +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@Buf4/bitstring>> when V1@V3 =/= 0 -> +{V1@V3,V1@Buf4}; +<<1:1,0:1,V1@V4:14,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +{V1@V4,V1@Buf5}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +V1@Mul6 = V1@V4 * 16384, +{V1@Mul6,V1@Buf5} +end, +<> = V1@Buf1, +{V1@V7,V1@Buf8} +end, + +%% attribute vsn(2) with type INTEGER +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@Buf4/bitstring>> when V2@V3 =/= 0 -> +{V2@V3,V2@Buf4}; +<<1:1,0:1,V2@V4:14,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +{V2@V4,V2@Buf5}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +V2@Mul6 = V2@V4 * 16384, +{V2@Mul6,V2@Buf5} +end, +<> = V2@Buf1, +{V2@V7,V2@Buf8} +end, + +%% attribute content(3) with type Content +{Term3,Bytes3} = dec_Content(Bytes2), +Res1 = {'GajumaruData',Term1,Term2,Term3}, +{Res1,Bytes3}. + +enc_Content(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= templateFields -> +[<<0:2>>|enc_TemplateFields(ChoiceVal)]; +ChoiceTag =:= account -> +[<<1:2>>|enc_Account(ChoiceVal)]; +ChoiceTag =:= signedTx -> +[<<2:2>>|enc_SignedTx(ChoiceVal)]; +ChoiceTag =:= contract -> +[<<3:2>>|enc_ContractCode(ChoiceVal)] +end. + + +dec_Content(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +dec_TemplateFields(Bytes1) +end, +{{templateFields,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +dec_Account(Bytes1) +end, +{{account,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +dec_SignedTx(Bytes1) +end, +{{signedTx,Val},NewBytes}; +3 -> +{Val,NewBytes} = begin +dec_ContractCode(Bytes1) +end, +{{contract,Val},NewBytes} +end. +enc_TemplateFields(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TemplateField(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TemplateField(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TemplateField(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_TemplateFields(Bytes) -> +dec_components1(Bytes, []). + +enc_TemplateField(Val) -> +[begin +Enc1@element = element(2, Val), +if Enc1@element =:= asn1_NOVALUE -> +<<0:1>>; +true -> +<<1:1>> +end +end, +begin +%% attribute name(1) with type IA5String +Enc2@element = element(2, Val), +if Enc2@element =:= asn1_NOVALUE -> +[]; +true -> +begin +Enc3@len = length(Enc2@element), +Enc3@bin = encode_chars(Enc2@element, 7), +if Enc3@len < 128 -> +[Enc3@len|Enc3@bin]; +Enc3@len < 16384 -> +[<<2:2,Enc3@len:14>>|Enc3@bin]; +true -> +encode_fragmented(Enc3@bin, 7) +end +end +end +end|begin +%% attribute value(2) with type Value +Enc5@element = element(3, Val), +enc_Value(Enc5@element) +end]. + + +dec_TemplateField(Bytes) -> +{Opt,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute name(1) with type IA5String +{Term1,Bytes2} = case Opt band 1 of +1 -> +begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:7,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:7,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 7), +{V2@V6,V2@Buf7} +end, +{V2@V8,V2@Buf9} = {decode_chars(V2@V0, 7),V2@Buf1}, +{V2@V8,V2@Buf9} +end; +0 -> +{asn1_NOVALUE,Bytes1} +end, + +%% attribute value(2) with type Value +{Term2,Bytes3} = dec_Value(Bytes2), +Res1 = {'TemplateField',Term1,Term2}, +{Res1,Bytes3}. + +enc_Value(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= intValue -> +[<<0:3>>|encode_unconstrained_number(ChoiceVal)]; +ChoiceTag =:= boolValue -> +if ChoiceVal =:= false -> +<<1:3,0:1>>; +ChoiceVal =:= true -> +<<1:3,1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,ChoiceVal}}}) +end; +ChoiceTag =:= binaryValue -> +[<<2:3>>|begin +Enc6@len = byte_size(ChoiceVal), +if Enc6@len < 128 -> +[Enc6@len|ChoiceVal]; +Enc6@len < 16384 -> +[<<2:2,Enc6@len:14>>|ChoiceVal]; +true -> +encode_fragmented(ChoiceVal, 8) +end +end]; +ChoiceTag =:= idValue -> +[<<3:3>>|enc_Id(ChoiceVal)]; +ChoiceTag =:= listValue -> +[<<4:3>>|enc_Value_listValue(ChoiceVal)]; +ChoiceTag =:= tupleValue -> +[<<5:3>>|enc_Value_tupleValue(ChoiceVal)]; +ChoiceTag =:= mapValue -> +[<<6:3>>|enc_Value_mapValue(ChoiceVal)] +end. +enc_Value_listValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + +enc_Value_tupleValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_Value(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_Value(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_Value(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + +enc_Value_mapValue(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_KeyValue(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_KeyValue(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_KeyValue(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_Value(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@Buf4/bitstring>> when V2@V3 =/= 0 -> +{V2@V3,V2@Buf4}; +<<1:1,0:1,V2@V4:14,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +{V2@V4,V2@Buf5}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> when V2@V4 =/= 0 -> +V2@Mul6 = V2@V4 * 16384, +{V2@Mul6,V2@Buf5} +end, +<> = V2@Buf1, +{V2@V7,V2@Buf8} +end +end, +{{intValue,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +begin +<> = Bytes1, +V3@Int2 = case V3@V0 of +0 -> false; +1 -> true +end, +{V3@Int2,V3@Buf1} +end +end, +{{boolValue,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +begin +{V4@V0,V4@Buf1} = case Bytes1 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end +end, +{{binaryValue,Val},NewBytes}; +3 -> +{Val,NewBytes} = begin +dec_Id(Bytes1) +end, +{{idValue,Val},NewBytes}; +4 -> +{Val,NewBytes} = begin +dec_Value_listValue(Bytes1) +end, +{{listValue,Val},NewBytes}; +5 -> +{Val,NewBytes} = begin +dec_Value_tupleValue(Bytes1) +end, +{{tupleValue,Val},NewBytes}; +6 -> +{Val,NewBytes} = begin +dec_Value_mapValue(Bytes1) +end, +{{mapValue,Val},NewBytes} +end. + +dec_Value_listValue(Bytes) -> +dec_components2(Bytes, []). + + +dec_Value_tupleValue(Bytes) -> +dec_components3(Bytes, []). + + +dec_Value_mapValue(Bytes) -> +dec_components4(Bytes, []). + +enc_KeyValue(Val) -> +[begin +%% attribute key(1) with type Value +Enc1@element = element(2, Val), +enc_Value(Enc1@element) +end|begin +%% attribute val(2) with type Value +Enc2@element = element(3, Val), +enc_Value(Enc2@element) +end]. + + +dec_KeyValue(Bytes) -> + +%% attribute key(1) with type Value +{Term1,Bytes1} = dec_Value(Bytes), + +%% attribute val(2) with type Value +{Term2,Bytes2} = dec_Value(Bytes1), +Res1 = {'KeyValue',Term1,Term2}, +{Res1,Bytes2}. + +enc_Id(Val) -> +[begin +%% attribute type(1) with type INTEGER +Enc1@element = element(2, Val), +if Enc1@element bsr 8 =:= 0 -> +Enc1@element; +true -> +exit({error,{asn1,{illegal_integer,Enc1@element}}}) +end +end|begin +%% attribute value(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len =:= 32 -> +Enc3@element +end +end]. + + +dec_Id(Bytes) -> + +%% attribute type(1) with type INTEGER +{Term1,Bytes1} = begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, + +%% attribute value(2) with type OCTET STRING +{Term2,Bytes2} = begin +<> = Bytes1, +V2@Conv2 = binary:copy(V2@V0), +{V2@Conv2,V2@Buf1} +end, +Res1 = {'Id',Term1,Term2}, +{Res1,Bytes2}. + +enc_Account(Val) -> +[begin +%% attribute foo(1) with type INTEGER +Enc1@element = element(2, Val), +encode_unconstrained_number(Enc1@element) +end|begin +%% attribute bar(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end]. + + +dec_Account(Bytes) -> + +%% attribute foo(1) with type INTEGER +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@Buf4/bitstring>> when V1@V3 =/= 0 -> +{V1@V3,V1@Buf4}; +<<1:1,0:1,V1@V4:14,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +{V1@V4,V1@Buf5}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> when V1@V4 =/= 0 -> +V1@Mul6 = V1@V4 * 16384, +{V1@Mul6,V1@Buf5} +end, +<> = V1@Buf1, +{V1@V7,V1@Buf8} +end, + +%% attribute bar(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, +Res1 = {'Account',Term1,Term2}, +{Res1,Bytes2}. + +enc_SignedTx(Val) -> +[begin +%% attribute signatures(1) with type SEQUENCE OF +Enc1@element = element(2, Val), +enc_SignedTx_signatures(Enc1@element) +end|begin +%% attribute transaction(2) with type OCTET STRING +Enc2@element = element(3, Val), +Enc3@len = byte_size(Enc2@element), +if Enc3@len < 128 -> +[Enc3@len|Enc2@element]; +Enc3@len < 16384 -> +[<<2:2,Enc3@len:14>>|Enc2@element]; +true -> +encode_fragmented(Enc2@element, 8) +end +end]. +enc_SignedTx_signatures(Val) -> +Enc2@len = length(Val), +if Enc2@len < 128 -> +[Enc2@len|[begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end || Comp <- Val]]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|[begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end || Comp <- Val]]; +true -> +begin +Enc2@fn = fun(Comp) -> begin +Enc1@len = byte_size(Comp), +if Enc1@len < 128 -> +[Enc1@len|Comp]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|Comp]; +true -> +encode_fragmented(Comp, 8) +end +end end, +encode_fragmented_sof(Enc2@fn, Val, Enc2@len) +end +end. + + + +dec_SignedTx(Bytes) -> + +%% attribute signatures(1) with type SEQUENCE OF +{Term1,Bytes1} = dec_SignedTx_signatures(Bytes), + +%% attribute transaction(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V1@V0,V1@Buf1} = case Bytes1 of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, +Res1 = {'SignedTx',Term1,Term2}, +{Res1,Bytes2}. + + +dec_SignedTx_signatures(Bytes) -> +dec_components5(Bytes, []). + +enc_ContractCode(Val) -> +{ChoiceTag,ChoiceVal} = Val, +if ChoiceTag =:= v1 -> +[<<0:2>>|enc_ContractV1(ChoiceVal)]; +ChoiceTag =:= v2 -> +[<<1:2>>|enc_ContractV2(ChoiceVal)]; +ChoiceTag =:= v3 -> +[<<2:2>>|enc_ContractV3(ChoiceVal)] +end. + + +dec_ContractCode(Bytes) -> +{Choice,Bytes1} = +begin +<> = Bytes, +{V1@V0,V1@Buf1} +end, +case Choice of +0 -> +{Val,NewBytes} = begin +dec_ContractV1(Bytes1) +end, +{{v1,Val},NewBytes}; +1 -> +{Val,NewBytes} = begin +dec_ContractV2(Bytes1) +end, +{{v2,Val},NewBytes}; +2 -> +{Val,NewBytes} = begin +dec_ContractV3(Bytes1) +end, +{{v3,Val},NewBytes} +end. +enc_ContractV1(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV1_typeInfo(Enc3@element) +end|begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end]. +enc_ContractV1_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV1(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV1(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV1_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, +Res1 = {'ContractV1',Term1,Term2,Term3}, +{Res1,Bytes3}. + + +dec_ContractV1_typeInfo(Bytes) -> +dec_components6(Bytes, []). + +enc_ContractV2(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV2_typeInfo(Enc3@element) +end, +begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end|begin +%% attribute compilerVersion(4) with type OCTET STRING +Enc6@element = element(5, Val), +Enc7@len = byte_size(Enc6@element), +if Enc7@len < 128 -> +[Enc7@len|Enc6@element]; +Enc7@len < 16384 -> +[<<2:2,Enc7@len:14>>|Enc6@element]; +true -> +encode_fragmented(Enc6@element, 8) +end +end]. +enc_ContractV2_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV1(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV1(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV2(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV2_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute compilerVersion(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V3@V0,V3@Buf1} = case Bytes3 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, +Res1 = {'ContractV2',Term1,Term2,Term3,Term4}, +{Res1,Bytes4}. + + +dec_ContractV2_typeInfo(Bytes) -> +dec_components7(Bytes, []). + +enc_ContractV3(Val) -> +[begin +%% attribute sourceHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute typeInfo(2) with type SEQUENCE OF +Enc3@element = element(3, Val), +enc_ContractV3_typeInfo(Enc3@element) +end, +begin +%% attribute byteCode(3) with type OCTET STRING +Enc4@element = element(4, Val), +Enc5@len = byte_size(Enc4@element), +if Enc5@len < 128 -> +[Enc5@len|Enc4@element]; +Enc5@len < 16384 -> +[<<2:2,Enc5@len:14>>|Enc4@element]; +true -> +encode_fragmented(Enc4@element, 8) +end +end, +begin +%% attribute compilerVersion(4) with type OCTET STRING +Enc6@element = element(5, Val), +Enc7@len = byte_size(Enc6@element), +if Enc7@len < 128 -> +[Enc7@len|Enc6@element]; +Enc7@len < 16384 -> +[<<2:2,Enc7@len:14>>|Enc6@element]; +true -> +encode_fragmented(Enc6@element, 8) +end +end|begin +%% attribute payable(5) with type BOOLEAN +Enc8@element = element(6, Val), +if Enc8@element =:= false -> +<<0:1>>; +Enc8@element =:= true -> +<<1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,Enc8@element}}}) +end +end]. +enc_ContractV3_typeInfo(Val) -> +Enc1@len = length(Val), +if Enc1@len < 128 -> +[Enc1@len|[enc_TypeInfoV3(Comp) || Comp <- Val]]; +Enc1@len < 16384 -> +[<<2:2,Enc1@len:14>>|[enc_TypeInfoV3(Comp) || Comp <- Val]]; +true -> +begin +Enc1@fn = fun(Comp) -> enc_TypeInfoV3(Comp) end, +encode_fragmented_sof(Enc1@fn, Val, Enc1@len) +end +end. + + + +dec_ContractV3(Bytes) -> + +%% attribute sourceHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute typeInfo(2) with type SEQUENCE OF +{Term2,Bytes2} = dec_ContractV3_typeInfo(Bytes1), + +%% attribute byteCode(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V2@V0,V2@Buf1} = case Bytes2 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute compilerVersion(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V3@V0,V3@Buf1} = case Bytes3 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, + +%% attribute payable(5) with type BOOLEAN +{Term5,Bytes5} = begin +<> = Bytes4, +V4@Int2 = case V4@V0 of +0 -> false; +1 -> true +end, +{V4@Int2,V4@Buf1} +end, +Res1 = {'ContractV3',Term1,Term2,Term3,Term4,Term5}, +{Res1,Bytes5}. + + +dec_ContractV3_typeInfo(Bytes) -> +dec_components8(Bytes, []). + +enc_TypeInfoV1(Val) -> +[begin +%% attribute typeHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute name(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end, +begin +%% attribute argType(3) with type OCTET STRING +Enc5@element = element(4, Val), +Enc6@len = byte_size(Enc5@element), +if Enc6@len < 128 -> +[Enc6@len|Enc5@element]; +Enc6@len < 16384 -> +[<<2:2,Enc6@len:14>>|Enc5@element]; +true -> +encode_fragmented(Enc5@element, 8) +end +end|begin +%% attribute outType(4) with type OCTET STRING +Enc7@element = element(5, Val), +Enc8@len = byte_size(Enc7@element), +if Enc8@len < 128 -> +[Enc8@len|Enc7@element]; +Enc8@len < 16384 -> +[<<2:2,Enc8@len:14>>|Enc7@element]; +true -> +encode_fragmented(Enc7@element, 8) +end +end]. + + +dec_TypeInfoV1(Bytes) -> + +%% attribute typeHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute name(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute argType(3) with type OCTET STRING +{Term3,Bytes3} = begin +{V3@V0,V3@Buf1} = case Bytes2 of +<<0:1,V3@V3:7,V3@V5:V3@V3/binary-unit:8,V3@Buf6/bitstring>> -> +{V3@V5,V3@Buf6}; +<<1:1,0:1,V3@V4:14,V3@V6:V3@V4/binary-unit:8,V3@Buf7/bitstring>> -> +{V3@V6,V3@Buf7}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +{V3@V6,V3@Buf7} = decode_fragmented(V3@V4, V3@Buf5, 8), +{V3@V6,V3@Buf7} +end, +V3@Conv8 = binary:copy(V3@V0), +{V3@Conv8,V3@Buf1} +end, + +%% attribute outType(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V4@V0,V4@Buf1} = case Bytes3 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end, +Res1 = {'TypeInfoV1',Term1,Term2,Term3,Term4}, +{Res1,Bytes4}. + +enc_TypeInfoV3(Val) -> +[begin +%% attribute typeHash(1) with type OCTET STRING +Enc1@element = element(2, Val), +Enc2@len = byte_size(Enc1@element), +if Enc2@len < 128 -> +[Enc2@len|Enc1@element]; +Enc2@len < 16384 -> +[<<2:2,Enc2@len:14>>|Enc1@element]; +true -> +encode_fragmented(Enc1@element, 8) +end +end, +begin +%% attribute name(2) with type OCTET STRING +Enc3@element = element(3, Val), +Enc4@len = byte_size(Enc3@element), +if Enc4@len < 128 -> +[Enc4@len|Enc3@element]; +Enc4@len < 16384 -> +[<<2:2,Enc4@len:14>>|Enc3@element]; +true -> +encode_fragmented(Enc3@element, 8) +end +end, +begin +%% attribute payable(3) with type BOOLEAN +Enc5@element = element(4, Val), +if Enc5@element =:= false -> +<<0:1>>; +Enc5@element =:= true -> +<<1:1>>; +true -> +exit({error,{asn1,{illegal_boolean,Enc5@element}}}) +end +end, +begin +%% attribute argType(4) with type OCTET STRING +Enc7@element = element(5, Val), +Enc8@len = byte_size(Enc7@element), +if Enc8@len < 128 -> +[Enc8@len|Enc7@element]; +Enc8@len < 16384 -> +[<<2:2,Enc8@len:14>>|Enc7@element]; +true -> +encode_fragmented(Enc7@element, 8) +end +end|begin +%% attribute outType(5) with type OCTET STRING +Enc9@element = element(6, Val), +Enc10@len = byte_size(Enc9@element), +if Enc10@len < 128 -> +[Enc10@len|Enc9@element]; +Enc10@len < 16384 -> +[<<2:2,Enc10@len:14>>|Enc9@element]; +true -> +encode_fragmented(Enc9@element, 8) +end +end]. + + +dec_TypeInfoV3(Bytes) -> + +%% attribute typeHash(1) with type OCTET STRING +{Term1,Bytes1} = begin +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@V5:V1@V3/binary-unit:8,V1@Buf6/bitstring>> -> +{V1@V5,V1@Buf6}; +<<1:1,0:1,V1@V4:14,V1@V6:V1@V4/binary-unit:8,V1@Buf7/bitstring>> -> +{V1@V6,V1@Buf7}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +{V1@V6,V1@Buf7} = decode_fragmented(V1@V4, V1@Buf5, 8), +{V1@V6,V1@Buf7} +end, +V1@Conv8 = binary:copy(V1@V0), +{V1@Conv8,V1@Buf1} +end, + +%% attribute name(2) with type OCTET STRING +{Term2,Bytes2} = begin +{V2@V0,V2@Buf1} = case Bytes1 of +<<0:1,V2@V3:7,V2@V5:V2@V3/binary-unit:8,V2@Buf6/bitstring>> -> +{V2@V5,V2@Buf6}; +<<1:1,0:1,V2@V4:14,V2@V6:V2@V4/binary-unit:8,V2@Buf7/bitstring>> -> +{V2@V6,V2@Buf7}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +{V2@V6,V2@Buf7} = decode_fragmented(V2@V4, V2@Buf5, 8), +{V2@V6,V2@Buf7} +end, +V2@Conv8 = binary:copy(V2@V0), +{V2@Conv8,V2@Buf1} +end, + +%% attribute payable(3) with type BOOLEAN +{Term3,Bytes3} = begin +<> = Bytes2, +V3@Int2 = case V3@V0 of +0 -> false; +1 -> true +end, +{V3@Int2,V3@Buf1} +end, + +%% attribute argType(4) with type OCTET STRING +{Term4,Bytes4} = begin +{V4@V0,V4@Buf1} = case Bytes3 of +<<0:1,V4@V3:7,V4@V5:V4@V3/binary-unit:8,V4@Buf6/bitstring>> -> +{V4@V5,V4@Buf6}; +<<1:1,0:1,V4@V4:14,V4@V6:V4@V4/binary-unit:8,V4@Buf7/bitstring>> -> +{V4@V6,V4@Buf7}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +{V4@V6,V4@Buf7} = decode_fragmented(V4@V4, V4@Buf5, 8), +{V4@V6,V4@Buf7} +end, +V4@Conv8 = binary:copy(V4@V0), +{V4@Conv8,V4@Buf1} +end, + +%% attribute outType(5) with type OCTET STRING +{Term5,Bytes5} = begin +{V5@V0,V5@Buf1} = case Bytes4 of +<<0:1,V5@V3:7,V5@V5:V5@V3/binary-unit:8,V5@Buf6/bitstring>> -> +{V5@V5,V5@Buf6}; +<<1:1,0:1,V5@V4:14,V5@V6:V5@V4/binary-unit:8,V5@Buf7/bitstring>> -> +{V5@V6,V5@Buf7}; +<<1:1,1:1,V5@V4:6,V5@Buf5/bitstring>> -> +{V5@V6,V5@Buf7} = decode_fragmented(V5@V4, V5@Buf5, 8), +{V5@V6,V5@Buf7} +end, +V5@Conv8 = binary:copy(V5@V0), +{V5@Conv8,V5@Buf1} +end, +Res1 = {'TypeInfoV3',Term1,Term2,Term3,Term4,Term5}, +{Res1,Bytes5}. + + +%%% +%%% Run-time functions. +%%% + +'dialyzer-suppressions'(Arg) -> + _ = complete(element(1, Arg)), + ok. + +dec_components1(Bytes, Acc) -> +%% Length with constraint no +{V1@V0,V1@Buf1} = case Bytes of +<<0:1,V1@V3:7,V1@Buf4/bitstring>> -> +{V1@V3,V1@Buf4}; +<<1:1,0:1,V1@V4:14,V1@Buf5/bitstring>> -> +{V1@V4,V1@Buf5}; +<<1:1,1:1,V1@V4:6,V1@Buf5/bitstring>> -> +V1@Mul6 = V1@V4 * 16384, +{V1@Mul6,V1@Buf5} +end, +{Acc1,Buf1} = dec_fragment9(V1@V0, V1@Buf1, Acc), +if V1@V0 >= 16384 -> +dec_components1(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components2(Bytes, Acc) -> +%% Length with constraint no +{V2@V0,V2@Buf1} = case Bytes of +<<0:1,V2@V3:7,V2@Buf4/bitstring>> -> +{V2@V3,V2@Buf4}; +<<1:1,0:1,V2@V4:14,V2@Buf5/bitstring>> -> +{V2@V4,V2@Buf5}; +<<1:1,1:1,V2@V4:6,V2@Buf5/bitstring>> -> +V2@Mul6 = V2@V4 * 16384, +{V2@Mul6,V2@Buf5} +end, +{Acc1,Buf1} = dec_fragment10(V2@V0, V2@Buf1, Acc), +if V2@V0 >= 16384 -> +dec_components2(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components3(Bytes, Acc) -> +%% Length with constraint no +{V3@V0,V3@Buf1} = case Bytes of +<<0:1,V3@V3:7,V3@Buf4/bitstring>> -> +{V3@V3,V3@Buf4}; +<<1:1,0:1,V3@V4:14,V3@Buf5/bitstring>> -> +{V3@V4,V3@Buf5}; +<<1:1,1:1,V3@V4:6,V3@Buf5/bitstring>> -> +V3@Mul6 = V3@V4 * 16384, +{V3@Mul6,V3@Buf5} +end, +{Acc1,Buf1} = dec_fragment11(V3@V0, V3@Buf1, Acc), +if V3@V0 >= 16384 -> +dec_components3(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components4(Bytes, Acc) -> +%% Length with constraint no +{V4@V0,V4@Buf1} = case Bytes of +<<0:1,V4@V3:7,V4@Buf4/bitstring>> -> +{V4@V3,V4@Buf4}; +<<1:1,0:1,V4@V4:14,V4@Buf5/bitstring>> -> +{V4@V4,V4@Buf5}; +<<1:1,1:1,V4@V4:6,V4@Buf5/bitstring>> -> +V4@Mul6 = V4@V4 * 16384, +{V4@Mul6,V4@Buf5} +end, +{Acc1,Buf1} = dec_fragment12(V4@V0, V4@Buf1, Acc), +if V4@V0 >= 16384 -> +dec_components4(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components5(Bytes, Acc) -> +%% Length with constraint no +{V5@V0,V5@Buf1} = case Bytes of +<<0:1,V5@V3:7,V5@Buf4/bitstring>> -> +{V5@V3,V5@Buf4}; +<<1:1,0:1,V5@V4:14,V5@Buf5/bitstring>> -> +{V5@V4,V5@Buf5}; +<<1:1,1:1,V5@V4:6,V5@Buf5/bitstring>> -> +V5@Mul6 = V5@V4 * 16384, +{V5@Mul6,V5@Buf5} +end, +{Acc1,Buf1} = dec_fragment13(V5@V0, V5@Buf1, Acc), +if V5@V0 >= 16384 -> +dec_components5(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components6(Bytes, Acc) -> +%% Length with constraint no +{V6@V0,V6@Buf1} = case Bytes of +<<0:1,V6@V3:7,V6@Buf4/bitstring>> -> +{V6@V3,V6@Buf4}; +<<1:1,0:1,V6@V4:14,V6@Buf5/bitstring>> -> +{V6@V4,V6@Buf5}; +<<1:1,1:1,V6@V4:6,V6@Buf5/bitstring>> -> +V6@Mul6 = V6@V4 * 16384, +{V6@Mul6,V6@Buf5} +end, +{Acc1,Buf1} = dec_fragment14(V6@V0, V6@Buf1, Acc), +if V6@V0 >= 16384 -> +dec_components6(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components7(Bytes, Acc) -> +%% Length with constraint no +{V7@V0,V7@Buf1} = case Bytes of +<<0:1,V7@V3:7,V7@Buf4/bitstring>> -> +{V7@V3,V7@Buf4}; +<<1:1,0:1,V7@V4:14,V7@Buf5/bitstring>> -> +{V7@V4,V7@Buf5}; +<<1:1,1:1,V7@V4:6,V7@Buf5/bitstring>> -> +V7@Mul6 = V7@V4 * 16384, +{V7@Mul6,V7@Buf5} +end, +{Acc1,Buf1} = dec_fragment15(V7@V0, V7@Buf1, Acc), +if V7@V0 >= 16384 -> +dec_components7(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_components8(Bytes, Acc) -> +%% Length with constraint no +{V8@V0,V8@Buf1} = case Bytes of +<<0:1,V8@V3:7,V8@Buf4/bitstring>> -> +{V8@V3,V8@Buf4}; +<<1:1,0:1,V8@V4:14,V8@Buf5/bitstring>> -> +{V8@V4,V8@Buf5}; +<<1:1,1:1,V8@V4:6,V8@Buf5/bitstring>> -> +V8@Mul6 = V8@V4 * 16384, +{V8@Mul6,V8@Buf5} +end, +{Acc1,Buf1} = dec_fragment16(V8@V0, V8@Buf1, Acc), +if V8@V0 >= 16384 -> +dec_components8(Buf1, Acc1); +true -> +{lists:reverse(Acc1),Buf1} +end. + +dec_fragment10(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment10(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment10(Num-1, Remain, [Term|Acc]). + +dec_fragment11(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment11(Num, Bytes, Acc) -> +{Term,Remain} = dec_Value(Bytes), +dec_fragment11(Num-1, Remain, [Term|Acc]). + +dec_fragment12(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment12(Num, Bytes, Acc) -> +{Term,Remain} = dec_KeyValue(Bytes), +dec_fragment12(Num-1, Remain, [Term|Acc]). + +dec_fragment13(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment13(Num, Bytes, Acc) -> +{Term,Remain} = begin +{V9@V0,V9@Buf1} = case Bytes of +<<0:1,V9@V3:7,V9@V5:V9@V3/binary-unit:8,V9@Buf6/bitstring>> -> +{V9@V5,V9@Buf6}; +<<1:1,0:1,V9@V4:14,V9@V6:V9@V4/binary-unit:8,V9@Buf7/bitstring>> -> +{V9@V6,V9@Buf7}; +<<1:1,1:1,V9@V4:6,V9@Buf5/bitstring>> -> +{V9@V6,V9@Buf7} = decode_fragmented(V9@V4, V9@Buf5, 8), +{V9@V6,V9@Buf7} +end, +V9@Conv8 = binary:copy(V9@V0), +{V9@Conv8,V9@Buf1} +end, +dec_fragment13(Num-1, Remain, [Term|Acc]). + +dec_fragment14(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment14(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV1(Bytes), +dec_fragment14(Num-1, Remain, [Term|Acc]). + +dec_fragment15(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment15(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV1(Bytes), +dec_fragment15(Num-1, Remain, [Term|Acc]). + +dec_fragment16(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment16(Num, Bytes, Acc) -> +{Term,Remain} = dec_TypeInfoV3(Bytes), +dec_fragment16(Num-1, Remain, [Term|Acc]). + +dec_fragment9(0, Bytes, Acc) -> +{Acc,Bytes}; +dec_fragment9(Num, Bytes, Acc) -> +{Term,Remain} = dec_TemplateField(Bytes), +dec_fragment9(Num-1, Remain, [Term|Acc]). + +complete(InList) when is_list(InList) -> + case list_to_bitstring(InList) of + <<>> -> + <<0>>; + Res -> + Sz = bit_size(Res), + case Sz band 7 of + 0 -> + Res; + Bits -> + <> + end + end; +complete(Bin) when is_binary(Bin) -> + case Bin of + <<>> -> + <<0>>; + _ -> + Bin + end; +complete(InList) when is_bitstring(InList) -> + Sz = bit_size(InList), + PadLen = 8 - Sz band 7, + <>. + +decode_chars(Val, N) -> + [ + C || + <> <= Val + ]. + +decode_fragmented(SegSz0, Buf0, Unit) -> + SegSz = SegSz0 * Unit * 16384, + <> = Buf0, + decode_fragmented_1(Buf, Unit, Res). + +decode_fragmented_1(<<0:1,N:7,Buf0/bitstring>>, Unit, Res) -> + Sz = N * Unit, + <> = Buf0, + {<>, Buf}; +decode_fragmented_1(<<1:1,0:1,N:14,Buf0/bitstring>>, Unit, Res) -> + Sz = N * Unit, + <> = Buf0, + {<>, Buf}; +decode_fragmented_1(<<1:1,1:1,SegSz0:6,Buf0/bitstring>>, Unit, Res0) -> + SegSz = SegSz0 * Unit * 16384, + <> = Buf0, + Res = <>, + decode_fragmented_1(Buf, Unit, Res). + +encode_chars(Val, NumBits) -> + << + <> || + C <- Val + >>. + +encode_components(Cs, _Encoder, 0, Acc) -> + {Cs, lists:reverse(Acc)}; +encode_components([C | Cs], Encoder, Size, Acc) -> + B = Encoder(C), + encode_components(Cs, Encoder, Size - 1, [B | Acc]). + +encode_fragmented(Bin, Unit) -> + encode_fragmented_1(Bin, Unit, 4). + +encode_fragmented_1(Bin, Unit, N) -> + SegSz = Unit * N * 16384, + case Bin of + <> -> + [<<3:2,N:6>>, B | encode_fragmented_1(T, Unit, N)]; + _ when N > 1 -> + encode_fragmented_1(Bin, Unit, N - 1); + _ -> + case bit_size(Bin) div Unit of + Len when Len < 128 -> + [Len, Bin]; + Len when Len < 16384 -> + [<<2:2,Len:14>>, Bin] + end + end. + +encode_fragmented_sof(Fun, Comps, Len) -> + encode_fragmented_sof_1(Fun, Comps, Len, 4). + +encode_fragmented_sof_1(Encoder, Comps0, Len0, N) -> + SegSz = N * 16384, + if + Len0 >= SegSz -> + {Comps, B} = encode_components(Comps0, Encoder, SegSz, []), + Len = Len0 - SegSz, + [<<3:2,N:6>>, + B | + encode_fragmented_sof_1(Encoder, Comps, Len, N)]; + N > 1 -> + encode_fragmented_sof_1(Encoder, Comps0, Len0, N - 1); + Len0 < 128 -> + {[], B} = encode_components(Comps0, Encoder, Len0, []), + [Len0 | B]; + Len0 < 16384 -> + {[], B} = encode_components(Comps0, Encoder, Len0, []), + [<<2:2,Len0:14>> | B] + end. + +encode_unconstrained_number(Val) when not is_integer(Val) -> + exit({error, {asn1, {illegal_integer, Val}}}); +encode_unconstrained_number(Val) when Val >= 0 -> + if + Val < 128 -> + [1, Val]; + Val < 256 -> + [<<2,0>>, Val]; + true -> + case binary:encode_unsigned(Val) of + <<0:1,_/bitstring>> = Bin -> + case byte_size(Bin) of + Sz when Sz < 128 -> + [Sz, Bin]; + Sz when Sz < 16384 -> + [<<2:2,Sz:14>>, Bin] + end; + <<1:1,_/bitstring>> = Bin -> + case byte_size(Bin) + 1 of + Sz when Sz < 128 -> + [Sz, 0, Bin]; + Sz when Sz < 16384 -> + [<<2:2,Sz:14,0:8>>, Bin] + end + end + end; +encode_unconstrained_number(Val) -> + Oct = enint(Val, []), + Len = length(Oct), + if + Len < 128 -> + [Len | Oct]; + Len < 16384 -> + [<<2:2,Len:14>> | Oct] + end. + +enint(-1, [B1 | T]) when B1 > 127 -> + [B1 | T]; +enint(N, Acc) -> + enint(N bsr 8, [N band 255 | Acc]). diff --git a/asn1_uper/GajumaruSerialization.hrl b/asn1_uper/GajumaruSerialization.hrl new file mode 100644 index 0000000..4c5d52e --- /dev/null +++ b/asn1_uper/GajumaruSerialization.hrl @@ -0,0 +1,76 @@ +%% Generated by the Erlang ASN.1 compiler. Version: 5.4.3 +%% Purpose: Erlang record definitions for each named and unnamed +%% SEQUENCE and SET, and macro definitions for each value +%% definition in module GajumaruSerialization. + +-ifndef(_GAJUMARUSERIALIZATION_HRL_). +-define(_GAJUMARUSERIALIZATION_HRL_, true). + +-record('GajumaruData', { + tag, + vsn, + content +}). + +-record('TemplateField', { + name = asn1_NOVALUE, + value +}). + +-record('KeyValue', { + key, + val +}). + +-record('Id', { + type, + value +}). + +-record('Account', { + foo, + bar +}). + +-record('SignedTx', { + signatures, + transaction +}). + +-record('ContractV1', { + sourceHash, + typeInfo, + byteCode +}). + +-record('ContractV2', { + sourceHash, + typeInfo, + byteCode, + compilerVersion +}). + +-record('ContractV3', { + sourceHash, + typeInfo, + byteCode, + compilerVersion, + payable +}). + +-record('TypeInfoV1', { + typeHash, + name, + argType, + outType +}). + +-record('TypeInfoV3', { + typeHash, + name, + payable, + argType, + outType +}). + +-endif. %% _GAJUMARUSERIALIZATION_HRL_ diff --git a/doc/asn1_compact.md b/doc/asn1_compact.md new file mode 100644 index 0000000..e55d5ac --- /dev/null +++ b/doc/asn1_compact.md @@ -0,0 +1,70 @@ +# 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`. diff --git a/doc/static.md b/doc/static.md index 991116b..943a001 100644 --- a/doc/static.md +++ b/doc/static.md @@ -59,7 +59,8 @@ The template 'language' is defined by these types: ```erlang -type template() :: [{field_name(), type()}]. -type field_name() :: atom(). --type type() :: 'int' +-type type() :: 'int' % bignum (non-negative, for amounts etc. up to 10^30 Pucks) + | 'uint128' | 'uint64' | 'uint32' | 'uint16' | 'uint8' | 'bool' | 'binary' | 'id' %% As defined in aec_id.erl diff --git a/src/gmser_asn1_rlp.erl b/src/gmser_asn1_rlp.erl index e8cbd15..674d167 100644 --- a/src/gmser_asn1_rlp.erl +++ b/src/gmser_asn1_rlp.erl @@ -27,7 +27,12 @@ %%% {account, {'Account', Foo, Bar}} %%% ... %%% Value is one of: -%%% {intValue, integer()} +%%% {bigIntValue, integer()} % bignum (the original "int" for Pucks etc.) +%%% {uint128Value, integer()} +%%% {uint64Value, integer()} +%%% {uint32Value, integer()} +%%% {uint16Value, integer()} +%%% {uint8Value, integer()} %%% {binaryValue, binary()} %%% {boolValue, boolean()} %%% {listValue, [Value]} @@ -137,7 +142,12 @@ encode_type_info_v3(T) when is_tuple(T), tuple_size(T) =:= 5 -> %%%=================================================================== -spec encode_asn1_value(term()) -> binary() | [term()]. -encode_asn1_value({intValue, I}) -> encode_basic(int, I); +encode_asn1_value({bigIntValue, I}) -> encode_basic(int, I); +encode_asn1_value({uint128Value, I}) -> encode_basic(int, I); +encode_asn1_value({uint64Value, I}) -> encode_basic(int, I); +encode_asn1_value({uint32Value, I}) -> encode_basic(int, I); +encode_asn1_value({uint16Value, I}) -> encode_basic(int, I); +encode_asn1_value({uint8Value, I}) -> encode_basic(int, I); encode_asn1_value({binaryValue, B}) -> encode_basic(binary, B); encode_asn1_value({boolValue, B}) -> encode_basic(bool, B); encode_asn1_value({listValue, L}) when is_list(L) -> @@ -200,12 +210,12 @@ encode_basic(Type, Val) -> %% This is the key property for a thin RLP production layer. equivalence_simple_fields_test() -> - T = [{foo, int}, {bar, binary}], + T = [{foo, uint32}, {bar, binary}], V = [{foo, 1}, {bar, <<2>>}], Legacy = gmser_chain_objects:serialize(account, 1, T, V), Asn1 = {'GajumaruData', 10, 1, {templateFields, [ - {'TemplateField', <<"foo">>, {intValue, 1}}, + {'TemplateField', <<"foo">>, {uint32Value, 1}}, {'TemplateField', <<"bar">>, {binaryValue, <<2>>}} ]}}, New = encode(Asn1), @@ -220,7 +230,7 @@ equivalence_zero_and_empty_test() -> Legacy = gmser_chain_objects:serialize(account, 1, T, V), Asn1 = {'GajumaruData', 10, 1, {templateFields, [ - {'TemplateField', <<"foo">>, {intValue, 0}}, + {'TemplateField', <<"foo">>, {bigIntValue, 0}}, {'TemplateField', <<"bar">>, {binaryValue, <<>>}} ]}}, ?assertEqual(Legacy, encode(Asn1)). @@ -232,7 +242,7 @@ equivalence_list_field_test() -> Asn1 = {'GajumaruData', 10, 1, {templateFields, [ {'TemplateField', <<"xs">>, {listValue, [ - {intValue, 1}, {intValue, 2}, {intValue, 3} + {bigIntValue, 1}, {bigIntValue, 2}, {bigIntValue, 3} ]}} ]}}, ?assertEqual(Legacy, encode(Asn1)). @@ -244,7 +254,7 @@ equivalence_tuple_field_test() -> Asn1 = {'GajumaruData', 10, 1, {templateFields, [ {'TemplateField', <<"p">>, {tupleValue, [ - {intValue, 42}, {binaryValue, <<"hi">>} + {bigIntValue, 42}, {binaryValue, <<"hi">>} ]}} ]}}, ?assertEqual(Legacy, encode(Asn1)). diff --git a/src/gmserialization.erl b/src/gmserialization.erl index 8f70d57..746ae0b 100644 --- a/src/gmserialization.erl +++ b/src/gmserialization.erl @@ -29,7 +29,12 @@ -type template() :: [{field_name(), type()}]. -type field_name() :: atom(). --type type() :: 'int' +-type type() :: 'int' % bignum (non-negative, arbitrary size; used for Pucks amounts etc. up to 10^30) + | 'uint128' + | 'uint64' + | 'uint32' + | 'uint16' + | 'uint8' | 'bool' | 'binary' | 'id' %% As defined in aec_id.erl @@ -118,6 +123,16 @@ encode_field(#{items := Items}, Map) -> encode_field(Type, T) when tuple_size(Type) =:= tuple_size(T) -> Zipped = lists:zip(tuple_to_list(Type), tuple_to_list(T)), [encode_field(X, Y) || {X, Y} <- Zipped]; +encode_field(uint128, X) when is_integer(X), X >= 0, X < (1 bsl 128) -> + binary:encode_unsigned(X); +encode_field(uint64, X) when is_integer(X), X >= 0, X < (1 bsl 64) -> + binary:encode_unsigned(X); +encode_field(uint32, X) when is_integer(X), X >= 0, X < (1 bsl 32) -> + binary:encode_unsigned(X); +encode_field(uint16, X) when is_integer(X), X >= 0, X < (1 bsl 16) -> + binary:encode_unsigned(X); +encode_field(uint8, X) when is_integer(X), X >= 0, X < (1 bsl 8) -> + binary:encode_unsigned(X); encode_field(int, X) when is_integer(X), X >= 0 -> binary:encode_unsigned(X); encode_field(binary, X) when is_binary(X) -> X; @@ -141,6 +156,31 @@ decode_field(#{items := Items}, List) when length(List) =:= length(Items) -> decode_field(Type, List) when length(List) =:= tuple_size(Type) -> Zipped = lists:zip(tuple_to_list(Type), List), list_to_tuple([decode_field(X, Y) || {X, Y} <- Zipped]); +decode_field(uint128, X) when is_binary(X) -> + I = binary:decode_unsigned(X), + if I < (1 bsl 128) -> I; + true -> error({illegal, uint128, X}) + end; +decode_field(uint64, X) when is_binary(X) -> + I = binary:decode_unsigned(X), + if I < (1 bsl 64) -> I; + true -> error({illegal, uint64, X}) + end; +decode_field(uint32, X) when is_binary(X) -> + I = binary:decode_unsigned(X), + if I < (1 bsl 32) -> I; + true -> error({illegal, uint32, X}) + end; +decode_field(uint16, X) when is_binary(X) -> + I = binary:decode_unsigned(X), + if I < (1 bsl 16) -> I; + true -> error({illegal, uint16, X}) + end; +decode_field(uint8, X) when is_binary(X) -> + I = binary:decode_unsigned(X), + if I < (1 bsl 8) -> I; + true -> error({illegal, uint8, X}) + end; decode_field(int, <<0:8, X/binary>> = B) when X =/= <<>> -> error({illegal, int, B}); decode_field(int, X) when is_binary(X) -> binary:decode_unsigned(X);