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 new file mode 100644 index 0000000..00ea8a0 --- /dev/null +++ b/asn1/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/GajumaruSerialization.erl b/asn1/GajumaruSerialization.erl new file mode 100644 index 0000000..1fed3af --- /dev/null +++ b/asn1/GajumaruSerialization.erl @@ -0,0 +1,1402 @@ +%% 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,[der,{outdir,"asn1"},{i,"."},{i,"asn1"}]}]). + +-export([encoding_rule/0,maps/0,bit_string_format/0, + legacy_erlang_types/0]). +-export(['dialyzer-suppressions'/1]). +-export([ +enc_GajumaruData/2, +enc_Content/2, +enc_TemplateFields/2, +enc_TemplateField/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_Content/2, +dec_TemplateFields/2, +dec_TemplateField/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('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. + + +%%================================ +%% 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 = decode_integer(V1, [131072]), + +%%------------------------------------------------- +%% attribute vsn(2) with type INTEGER +%%------------------------------------------------- +[V2|Tlv3] = Tlv2, +Term2 = decode_integer(V2, [131073]), + +%%------------------------------------------------- +%% 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. + + +%%================================ +%% 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>>]); + 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, [])}; + + +%% '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. + + +%%================================ +%% 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/GajumaruSerialization.hrl b/asn1/GajumaruSerialization.hrl new file mode 100644 index 0000000..4c5d52e --- /dev/null +++ b/asn1/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/detect_demo.erl b/asn1/detect_demo.erl new file mode 100644 index 0000000..c938688 --- /dev/null +++ b/asn1/detect_demo.erl @@ -0,0 +1,27 @@ +-module(detect_demo). +-export([run/0]). + +run() -> + application:ensure_all_started(gmserialization), + code:add_path("asn1"), + + Sample = {'GajumaruData', 10, 1, + {templateFields, [ + {'TemplateField', <<"foo">>, {intValue, 42}}, + {'TemplateField', <<"bar">>, {binaryValue, <<"hello">>}} + ]}}, + + {ok, Der} = 'GajumaruSerialization':encode('GajumaruData', Sample), + io:format("DER first byte: ~p (0x~2.16.0B)~n", [binary:at(Der,0), binary:at(Der,0)]), + + {ok, _Dec} = 'GajumaruSerialization':decode('GajumaruData', Der), + io:format("DER roundtrip OK~n"), + + Legacy = gmser_chain_objects:serialize(account, 1, + [{foo,int},{bar,binary}], + [{foo,42},{bar,<<"hello">>}]), + <> = binary:part(Legacy,0,1), + <> = binary:part(Der,0,1), + io:format("Legacy 0x~2.16.0B (>= 0xC0 -> legacy: ~p)~n", [L0, L0 >= 16#C0]), + io:format("DER 0x~2.16.0B (< 0xC0 -> new DER: ~p)~n", [D0, D0 < 16#C0]), + ok. diff --git a/asn1/size_comparison.erl b/asn1/size_comparison.erl new file mode 100644 index 0000000..17d3969 --- /dev/null +++ b/asn1/size_comparison.erl @@ -0,0 +1,114 @@ +-module(size_comparison). +-export([run/0]). + +run() -> + application:ensure_all_started(gmserialization), + code:add_path("asn1"), + + io:format("=== Size Comparison: Legacy RLP vs DER ===~n~n"), + + Compare = fun(Desc, LegacyBin, DerBin) -> + L = byte_size(LegacyBin), + D = byte_size(DerBin), + Overhead = D - L, + Pct = case L of 0 -> 0; _ -> round(Overhead * 100 / L) end, + io:format("~s~n", [Desc]), + io:format(" Legacy: ~p bytes ~w~n", [L, LegacyBin]), + Show = binary:part(DerBin, 0, min(18, D)), + io:format(" DER: ~p bytes ~w~n", [D, Show]), + io:format(" Overhead: +~p bytes (~p%)~n~n", [Overhead, Pct]) + end, + + %% Case 1: tag+vsn + small int + small binary + T1 = [{foo,int},{bar,binary}], + V1 = [{foo,1},{bar,<<2>>}], + Leg1 = gmser_chain_objects:serialize(account, 1, T1, V1), + DerVal1 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"foo">>, {intValue, 1}}, + {'TemplateField', <<"bar">>, {binaryValue, <<2>>}} + ]}}, + {ok, Der1} = 'GajumaruSerialization':encode('GajumaruData', DerVal1), + Compare("Case 1: tag+vsn + small int + tiny binary (2 fields)", Leg1, Der1), + + %% Case 2: zero + empty binary + V2 = [{foo,0},{bar,<<>>}], + Leg2 = gmser_chain_objects:serialize(account, 1, T1, V2), + DerVal2 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"foo">>, {intValue, 0}}, + {'TemplateField', <<"bar">>, {binaryValue, <<>>}} + ]}}, + {ok, Der2} = 'GajumaruSerialization':encode('GajumaruData', DerVal2), + Compare("Case 2: zero int + empty binary", Leg2, Der2), + + %% Case 3: list of ints + T3 = [{xs,[int]}], + V3 = [{xs,[1,2,3]}], + Leg3 = gmser_chain_objects:serialize(account, 1, T3, V3), + DerVal3 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"xs">>, {listValue, [ + {intValue,1},{intValue,2},{intValue,3} + ]}} + ]}}, + {ok, Der3} = 'GajumaruSerialization':encode('GajumaruData', DerVal3), + Compare("Case 3: list of 3 small ints", Leg3, Der3), + + %% Case 4: tuple (int, binary) + T4 = [{p,{int,binary}}], + V4 = [{p,{42,<<"hi">>}}], + Leg4 = gmser_chain_objects:serialize(account, 1, T4, V4), + DerVal4 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"p">>, {tupleValue, [ + {intValue,42}, {binaryValue,<<"hi">>} + ]}} + ]}}, + {ok, Der4} = 'GajumaruSerialization':encode('GajumaruData', DerVal4), + Compare("Case 4: fixed tuple (int + 2-byte binary)", Leg4, Der4), + + %% Case 5: 256-byte payload + Bin5 = crypto:strong_rand_bytes(256), + T5 = [{data,binary}], + V5 = [{data,Bin5}], + Leg5 = gmser_chain_objects:serialize(account, 1, T5, V5), + DerVal5 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"data">>, {binaryValue, Bin5}} + ]}}, + {ok, Der5} = 'GajumaruSerialization':encode('GajumaruData', DerVal5), + Compare("Case 5: 256-byte binary payload only", Leg5, Der5), + + %% Case 6: Concrete SignedTx style (no field names in DER) + T6 = [{signatures,[binary]},{tx,binary}], + V6 = [{signatures,[<<"sig1">>,<<"sig2">>]},{tx,<<"txbody123">>}], + Leg6 = gmser_chain_objects:serialize(signed_tx, 1, T6, V6), + DerVal6 = {'GajumaruData', 11, 1, {signedTx, {'SignedTx', + [<<"sig1">>, <<"sig2">>], <<"txbody123">>}}}, + {ok, Der6} = 'GajumaruSerialization':encode('GajumaruData', DerVal6), + Compare("Case 6: SignedTx-like (concrete DER, no names)", Leg6, Der6), + + %% Case 7: 33-byte id-like value + IdBin = <<1, 0:256>>, + T7 = [{owner,binary}], + V7 = [{owner,IdBin}], + Leg7 = gmser_chain_objects:serialize(account, 1, T7, V7), + DerVal7 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"owner">>, {binaryValue, IdBin}} + ]}}, + {ok, Der7} = 'GajumaruSerialization':encode('GajumaruData', DerVal7), + Compare("Case 7: 33-byte value (id-like)", Leg7, Der7), + + %% Case 8: Deeper nesting / more fields + T8 = [{a,int},{b,binary},{c,[int]},{d,{int,int}}], + V8 = [{a,123456},{b,<<"abcdef">>},{c,[10,20,30]},{d,{7,8}}], + Leg8 = gmser_chain_objects:serialize(account, 1, T8, V8), + DerVal8 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"a">>, {intValue, 123456}}, + {'TemplateField', <<"b">>, {binaryValue, <<"abcdef">>}}, + {'TemplateField', <<"c">>, {listValue, [{intValue,10},{intValue,20},{intValue,30}]}}, + {'TemplateField', <<"d">>, {tupleValue, [{intValue,7},{intValue,8}]}} + ]}}, + {ok, Der8} = 'GajumaruSerialization':encode('GajumaruData', DerVal8), + Compare("Case 8: 4 fields mixed (int, bin, list, tuple)", Leg8, Der8), + + io:format("=== Analysis ===~n"), + io:format("Note: Generic templateFields path includes IA5String field names.~n"), + io:format("Concrete types (e.g. SignedTx) avoid name overhead.~n"), + ok. 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_api_encoder.erl b/src/gmser_api_encoder.erl index 9013b66..267b0be 100644 --- a/src/gmser_api_encoder.erl +++ b/src/gmser_api_encoder.erl @@ -36,6 +36,7 @@ | transaction | tx_hash | account_pubkey + | {account_pubkey, 0..6} | account_seckey | associate_chain | entry @@ -107,8 +108,12 @@ safe_decode_keypair(#{<<"pub">> := EncPub, <<"priv">> := EncPriv}) -> -spec encode(known_type(), payload() | gmser_id:id()) -> encoded(). encode(id_hash, Payload) -> - {IdType, Val} = gmser_id:specialize(Payload), - encode(id2type(IdType), Val); + case gmser_id:to_map(Payload) of + #{type := account, subtype := SubT, value := Val} -> + encode({account_pubkey, SubT}, Val); + #{type := IdType, value := Val} -> + encode(id2type(IdType), Val) + end; encode(Type, Payload) -> case type_size_check(Type, Payload) of ok -> @@ -237,17 +242,16 @@ id2type(associate_chain) -> associate_chain; id2type(channel) -> channel; id2type(commitment) -> commitment; id2type(contract) -> contract_pubkey; -id2type(contract_source) -> contract_source; id2type(name) -> name; id2type(native_token) -> native_token; id2type(entry) -> entry. +type2id({account_pubkey, SubT}) -> {account, SubT}; type2id(account_pubkey) -> account; type2id(associate_chain) -> associate_chain; type2id(channel) -> channel; type2id(commitment) -> commitment; type2id(contract_pubkey) -> contract; -type2id(contract_source) -> contract_source; type2id(name) -> name; type2id(native_token) -> native_token; type2id(entry) -> entry. @@ -266,6 +270,7 @@ type2enc(contract_store_value) -> ?BASE64; type2enc(contract_source) -> ?BASE64; type2enc(transaction) -> ?BASE64; type2enc(tx_hash) -> ?BASE58; +type2enc({account_pubkey, _}) -> ?BASE58; type2enc(account_pubkey) -> ?BASE58; type2enc(account_seckey) -> ?BASE58; type2enc(associate_chain) -> ?BASE58; @@ -298,6 +303,13 @@ type2pfx(contract_store_value) -> <<"cv">>; type2pfx(contract_source) -> <<"cx">>; type2pfx(transaction) -> <<"tx">>; type2pfx(tx_hash) -> <<"th">>; +type2pfx({account_pubkey,0}) -> <<"a0">>; +type2pfx({account_pubkey,1}) -> <<"a1">>; +type2pfx({account_pubkey,2}) -> <<"a2">>; +type2pfx({account_pubkey,3}) -> <<"a3">>; +type2pfx({account_pubkey,4}) -> <<"a4">>; +type2pfx({account_pubkey,5}) -> <<"a5">>; +type2pfx({account_pubkey,6}) -> <<"a6">>; type2pfx(account_pubkey) -> <<"ak">>; type2pfx(account_seckey) -> <<"sk">>; type2pfx(associate_chain) -> <<"ac">>; @@ -329,6 +341,13 @@ pfx2type(<<"ct">>) -> contract_pubkey; pfx2type(<<"cx">>) -> contract_source; pfx2type(<<"tx">>) -> transaction; pfx2type(<<"th">>) -> tx_hash; +pfx2type(<<"a0">>) -> {account_pubkey, 0}; +pfx2type(<<"a1">>) -> {account_pubkey, 1}; +pfx2type(<<"a2">>) -> {account_pubkey, 2}; +pfx2type(<<"a3">>) -> {account_pubkey, 3}; +pfx2type(<<"a4">>) -> {account_pubkey, 4}; +pfx2type(<<"a5">>) -> {account_pubkey, 5}; +pfx2type(<<"a6">>) -> {account_pubkey, 6}; pfx2type(<<"ak">>) -> account_pubkey; pfx2type(<<"sk">>) -> account_seckey; pfx2type(<<"ac">>) -> associate_chain; @@ -363,6 +382,7 @@ byte_size_for_type(contract_source) -> not_applicable; byte_size_for_type(transaction) -> not_applicable; byte_size_for_type(tx_hash) -> 32; byte_size_for_type(account_pubkey) -> 32; +byte_size_for_type({account_pubkey, _}) -> 32; byte_size_for_type(account_seckey) -> 32; byte_size_for_type(associate_chain) -> 32; byte_size_for_type(signature) -> 64; diff --git a/src/gmser_asn1_rlp.erl b/src/gmser_asn1_rlp.erl new file mode 100644 index 0000000..674d167 --- /dev/null +++ b/src/gmser_asn1_rlp.erl @@ -0,0 +1,315 @@ +%%%------------------------------------------------------------------- +%%% @copyright (C) 2026, QPQ AG (experiment) +%%% @doc +%%% Thin RLP production layer driven by ASN.1-shaped values. +%%% +%%% This module implements a "thin translation" from structures that +%%% mirror the ASN.1 definitions in asn1/GajumaruSerialization.asn +%%% to the exact same RLP wire format produced by the legacy +%%% gmserialization + gmser_rlp + gmser_chain_objects stack. +%%% +%%% Goal: +%%% - Use ASN.1 as a formal, multi-language-friendly schema. +%%% - Keep the compact legacy RLP on the wire (no DER bloat). +%%% - Provide a reference implementation that other languages can +%%% port (types from ASN.1 compiler + this thin RLP emitter). +%%% +%%% The layer does NOT use the ASN.1 BER/DER codec at runtime for +%%% the wire format. It walks ASN.1-like Erlang terms and emits +%%% RLP using the same rules as gmserialization:encode_field/2 +%%% and gmser_rlp:encode/1. +%%% +%%% Supported shapes (matching the ASN.1 value notation): +%%% {'GajumaruData', Tag, Vsn, Content} +%%% Content is a CHOICE: +%%% {templateFields, [ {'TemplateField', Name, Value}, ... ]} +%%% {signedTx, {'SignedTx', Sigs, Tx}} +%%% {account, {'Account', Foo, Bar}} +%%% ... +%%% Value is one of: +%%% {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]} +%%% {tupleValue, [Value]} % or tuple, both accepted +%%% {idValue, ...} % basic support +%%% +%%% For templateFields (used for generic/static equivalence), field +%%% *names* are ignored on the wire (matching legacy static behavior +%%% where only values are sent in template order). +%%% +%%% Equivalence with legacy is the primary contract of this module. +%%% @end +%%%------------------------------------------------------------------- + +-module(gmser_asn1_rlp). +-vsn("0.1.0-experiment"). + +-export([encode/1]). + +%% For tests and other-language ports, these helpers are useful +-export([encode_basic/2, + encode_asn1_value/1]). + +-ifdef(TEST). +-include_lib("eunit/include/eunit.hrl"). +-endif. + +%%%=================================================================== +%%% API +%%%=================================================================== + +-spec encode(term()) -> binary(). +encode({'GajumaruData', Tag, Vsn, Content}) -> + TagB = encode_basic(int, Tag), + VsnB = encode_basic(int, Vsn), + Payload = encode_content(Content), + gmser_rlp:encode([TagB, VsnB | Payload]); +encode(Other) -> + error({unsupported_asn1_top_level, Other}). + +%%%=================================================================== +%%% Internal: content (the CHOICE after tag/vsn) +%%%=================================================================== + +encode_content({templateFields, FieldList}) when is_list(FieldList) -> + %% For wire compatibility with legacy static serialization we + %% emit only the values (in order). Names are not sent on the wire. + [encode_asn1_value(Val) || {_, _Name, Val} <- FieldList]; + +encode_content({signedTx, {'SignedTx', Sigs, Tx}}) -> + SigsEnc = [encode_basic(binary, S) || S <- Sigs], + TxEnc = encode_basic(binary, Tx), + [SigsEnc, TxEnc]; + +encode_content({account, {'Account', Foo, Bar}}) -> + [encode_basic(int, Foo), encode_basic(binary, Bar)]; + +encode_content({contract, Contract}) -> + encode_contract(Contract); + +encode_content(Other) -> + error({unsupported_content_choice, Other}). + +encode_contract({v1, {'ContractV1', Hash, TypeInfo, ByteCode}}) -> + [encode_basic(binary, Hash), + [encode_type_info_v1(TI) || TI <- TypeInfo], + encode_basic(binary, ByteCode)]; + +encode_contract({v2, {'ContractV2', Hash, TypeInfo, ByteCode, CompilerVsn}}) -> + [encode_basic(binary, Hash), + [encode_type_info_v1(TI) || TI <- TypeInfo], + encode_basic(binary, ByteCode), + encode_basic(binary, CompilerVsn)]; + +encode_contract({v3, {'ContractV3', Hash, TypeInfo, ByteCode, CompilerVsn, Payable}}) -> + [encode_basic(binary, Hash), + [encode_type_info_v3(TI) || TI <- TypeInfo], + encode_basic(binary, ByteCode), + encode_basic(binary, CompilerVsn), + encode_basic(bool, Payable)]. + +encode_type_info_v1({_TypeInfoV1, H, N, A, O}) -> + [encode_basic(binary, H), + encode_basic(binary, N), + encode_basic(binary, A), + encode_basic(binary, O)]; +encode_type_info_v1(T) when is_tuple(T), tuple_size(T) =:= 4 -> + %% Accept plain 4-tuple as well for convenience + [encode_basic(binary, element(I, T)) || I <- lists:seq(1,4)]. + +encode_type_info_v3({_TypeInfoV3, H, N, P, A, O}) -> + [encode_basic(binary, H), + encode_basic(binary, N), + encode_basic(bool, P), + encode_basic(binary, A), + encode_basic(binary, O)]; +encode_type_info_v3(T) when is_tuple(T), tuple_size(T) =:= 5 -> + %% TypeInfoV3 layout: binary, binary, bool, binary, binary + [encode_basic(binary, element(1,T)), + encode_basic(binary, element(2,T)), + encode_basic(bool, element(3,T)), + encode_basic(binary, element(4,T)), + encode_basic(binary, element(5,T))]. + +%%%=================================================================== +%%% Value encoding (recursive, mirrors ASN.1 Value CHOICE) +%%%=================================================================== + +-spec encode_asn1_value(term()) -> binary() | [term()]. +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) -> + [encode_asn1_value(E) || E <- L]; +encode_asn1_value({tupleValue, T}) when is_list(T) -> + [encode_asn1_value(E) || E <- T]; +encode_asn1_value({tupleValue, T}) when is_tuple(T) -> + [encode_asn1_value(E) || E <- tuple_to_list(T)]; +encode_asn1_value({idValue, {'Id', Type, Val}}) -> + %% Basic support: encode as the legacy 33-byte id form if possible, + %% otherwise fall back to treating the value as binary. + try + Id = gmser_id:create(decode_id_tag(Type), Val), + gmser_id:encode(Id) + catch _:_ -> + encode_basic(binary, Val) + end; +encode_asn1_value({idValue, Bin}) when is_binary(Bin) -> + %% Convenience: bare 33-byte id value + encode_basic(binary, Bin); +encode_asn1_value(Other) -> + error({unsupported_asn1_value, Other}). + +decode_id_tag(1) -> account; +decode_id_tag(2) -> name; +decode_id_tag(3) -> commitment; +decode_id_tag(5) -> contract; +decode_id_tag(6) -> channel; +decode_id_tag(7) -> associate_chain; +decode_id_tag(8) -> native_token; +decode_id_tag(9) -> entry; +decode_id_tag(T) when is_integer(T) -> error({unknown_id_tag, T}). + +%%%=================================================================== +%%% Basic encoders matching gmserialization rules +%%%=================================================================== + +-spec encode_basic(atom(), term()) -> binary(). +encode_basic(int, X) when is_integer(X), X >= 0 -> + binary:encode_unsigned(X); +encode_basic(binary, X) when is_binary(X) -> + X; +encode_basic(bool, true) -> <<1:8>>; +encode_basic(bool, false) -> <<0:8>>; +encode_basic(id, Val) -> + try gmser_id:encode(Val) + catch _:_ -> error({illegal, id, Val}) + end; +encode_basic(Type, Val) -> + error({unsupported_basic_type, Type, Val}). + +%%%=================================================================== +%%% EUnit equivalence tests +%%%=================================================================== + +-ifdef(TEST). + +%% These tests assert that encoding an ASN.1-shaped value produces +%% *exactly* the same bytes as the legacy gmserialization stack. +%% This is the key property for a thin RLP production layer. + +equivalence_simple_fields_test() -> + 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">>, {uint32Value, 1}}, + {'TemplateField', <<"bar">>, {binaryValue, <<2>>}} + ]}}, + New = encode(Asn1), + ?assertEqual(Legacy, New), + %% Also check we can roundtrip via legacy decoder + Dec = gmser_chain_objects:deserialize(account, 1, T, New), + ?assertEqual(V, Dec). + +equivalence_zero_and_empty_test() -> + T = [{foo, int}, {bar, binary}], + V = [{foo, 0}, {bar, <<>>}], + Legacy = gmser_chain_objects:serialize(account, 1, T, V), + + Asn1 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"foo">>, {bigIntValue, 0}}, + {'TemplateField', <<"bar">>, {binaryValue, <<>>}} + ]}}, + ?assertEqual(Legacy, encode(Asn1)). + +equivalence_list_field_test() -> + T = [{xs, [int]}], + V = [{xs, [1,2,3]}], + Legacy = gmser_chain_objects:serialize(account, 1, T, V), + + Asn1 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"xs">>, {listValue, [ + {bigIntValue, 1}, {bigIntValue, 2}, {bigIntValue, 3} + ]}} + ]}}, + ?assertEqual(Legacy, encode(Asn1)). + +equivalence_tuple_field_test() -> + T = [{p, {int, binary}}], + V = [{p, {42, <<"hi">>}}], + Legacy = gmser_chain_objects:serialize(account, 1, T, V), + + Asn1 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"p">>, {tupleValue, [ + {bigIntValue, 42}, {binaryValue, <<"hi">>} + ]}} + ]}}, + ?assertEqual(Legacy, encode(Asn1)). + +equivalence_signed_tx_concrete_test() -> + T = [{signatures, [binary]}, {tx, binary}], + V = [{signatures, [<<"sig1">>, <<"sig2">>]}, {tx, <<"txbody123">>}], + Legacy = gmser_chain_objects:serialize(signed_tx, 1, T, V), + + Asn1 = {'GajumaruData', 11, 1, {signedTx, {'SignedTx', + [<<"sig1">>, <<"sig2">>], <<"txbody123">>}}}, + ?assertEqual(Legacy, encode(Asn1)). + +equivalence_list_of_tuples_test() -> + %% Corresponds to type_info style: list of 4-tuples + T = [{type_info, [{binary, binary, binary, binary}]}], + V = [{type_info, [ + {<<"h1">>, <<"n1">>, <<"a1">>, <<"o1">>}, + {<<"h2">>, <<"n2">>, <<"a2">>, <<"o2">>} + ]}], + Legacy = gmser_chain_objects:serialize(account, 1, T, V), + + Asn1 = {'GajumaruData', 10, 1, {templateFields, [ + {'TemplateField', <<"type_info">>, {listValue, [ + {tupleValue, [{binaryValue,<<"h1">>},{binaryValue,<<"n1">>}, + {binaryValue,<<"a1">>},{binaryValue,<<"o1">>}]}, + {tupleValue, [{binaryValue,<<"h2">>},{binaryValue,<<"n2">>}, + {binaryValue,<<"a2">>},{binaryValue,<<"o2">>}]} + ]}} + ]}}, + ?assertEqual(Legacy, encode(Asn1)). + +equivalence_contract_v3_test() -> + T = [ {source_hash, binary} + , {type_info, [{binary, binary, bool, binary, binary}]} + , {byte_code, binary} + , {compiler_version, binary} + , {payable, bool} + ], + TI = [{<<"h">>, <<"n">>, true, <<"a">>, <<"o">>}], + V = [ {source_hash, <<"hash">>} + , {type_info, TI} + , {byte_code, <<"code">>} + , {compiler_version, <<"vsn">>} + , {payable, true} + ], + Legacy = gmser_chain_objects:serialize(contract, 3, T, V), + + Asn1 = {'GajumaruData', 40, 3, {contract, {v3, {'ContractV3', + <<"hash">>, + [ {<<"h">>, <<"n">>, true, <<"a">>, <<"o">>} ], + <<"code">>, + <<"vsn">>, + true + }}}}, + ?assertEqual(Legacy, encode(Asn1)). + +-endif. diff --git a/src/gmser_chain_objects.erl b/src/gmser_chain_objects.erl index 4c89e07..aa3a7ab 100644 --- a/src/gmser_chain_objects.erl +++ b/src/gmser_chain_objects.erl @@ -100,6 +100,8 @@ tag(ac_deposit_tx) -> 94; tag(ac_update_cops_tx) -> 95; tag(ac_rollup_tx) -> 96; tag(ac_proposal_tx) -> 97; +tag(ac_receipt) -> 98; +tag(ac_acct_state) -> 99; tag(key_block) -> 100; tag(micro_block) -> 101; tag(light_micro_block) -> 102; @@ -115,7 +117,16 @@ tag(entry) -> 140; tag(entry_create_tx) -> 141; tag(entry_transfer_tx) -> 142; tag(entry_destroy_tx) -> 143; -tag(pof) -> 200. +tag(account_key_store) -> 144; +tag(account_create_tx) -> 145; +tag(account_sig_store) -> 146; +tag(auth_tx) -> 147; +tag(proposal_gossip_tx) -> 148; +tag(account_auth_update_tx) -> 149; +tag(pof) -> 200; +%% Gajumaru AC side transactions +tag(ac_side_withdraw_tx) -> 300; +tag(ac_side_rollup_tx) -> 301. rev_tag(10) -> account; rev_tag(11) -> signed_tx; @@ -179,6 +190,8 @@ rev_tag(94) -> ac_deposit_tx; rev_tag(95) -> ac_update_cops_tx; rev_tag(96) -> ac_rollup_tx; rev_tag(97) -> ac_proposal_tx; +rev_tag(98) -> ac_receipt; +rev_tag(99) -> ac_acct_state; rev_tag(100) -> key_block; rev_tag(101) -> micro_block; rev_tag(102) -> light_micro_block; @@ -194,4 +207,13 @@ rev_tag(140) -> entry; rev_tag(141) -> entry_create_tx; rev_tag(142) -> entry_transfer_tx; rev_tag(143) -> entry_destroy_tx; -rev_tag(200) -> pof. +rev_tag(144) -> account_key_store; +rev_tag(145) -> account_create_tx; +rev_tag(146) -> account_sig_store; +rev_tag(147) -> auth_tx; +rev_tag(148) -> proposal_gossip_tx; +rev_tag(149) -> account_auth_update_tx; +rev_tag(200) -> pof; +%% Gajumaru AC side transactions +rev_tag(300) -> ac_side_withdraw_tx; +rev_tag(301) -> ac_side_rollup_tx. diff --git a/src/gmser_id.erl b/src/gmser_id.erl index 80a592a..7655ec4 100644 --- a/src/gmser_id.erl +++ b/src/gmser_id.erl @@ -14,6 +14,9 @@ , specialize/1 , specialize/2 , specialize_type/1 + , is_account/1 + , account_pubkey/1 + , to_map/1 , is_id/1 ]). @@ -29,15 +32,20 @@ , val }). --type tag() :: 'account' - | 'associate_chain' - | 'channel' - | 'commitment' - | 'contract' - | 'contract_source' - | 'name' - | 'native_token' - | 'entry'. +-type subtype() :: 0..6. +-type id_map() :: #{ type := simple_tag() + , subtype => subtype() + , value := binary() }. + +-type tag() :: {'account', subtype()} | simple_tag(). +-type simple_tag() :: 'account' + | 'associate_chain' + | 'channel' + | 'commitment' + | 'contract' + | 'name' + | 'native_token' + | 'entry'. -type val() :: <<_:256>>. -type id() :: #id{}. @@ -57,7 +65,8 @@ ___TAG___ =:= contract; ___TAG___ =:= channel; ___TAG___ =:= associate_chain; - ___TAG___ =:= entry + ___TAG___ =:= entry; + ___TAG___ =:= native_token ). -define(IS_VAL(___VAL___), byte_size(___VAL___) =:= 32). @@ -69,6 +78,8 @@ create(Tag, Val) when ?IS_TAG(Tag), ?IS_VAL(Val) -> #id{ tag = Tag , val = Val}; +create({account,I}, Val) when is_binary(Val), I >= 0, I =< 6 -> + #id{ tag = {account, I}, val = Val}; create(Tag, Val) when ?IS_VAL(Val) -> error({illegal_tag, Tag}); create(Tag, Val) when ?IS_TAG(Tag)-> @@ -78,28 +89,66 @@ create(Tag, Val) -> -spec specialize(id()) -> {tag(), val()}. +specialize(#id{tag = {Tag,_}, val = Val}) -> + {Tag, Val}; specialize(#id{tag = Tag, val = Val}) -> {Tag, Val}. -spec specialize(id(), tag()) -> val(). +specialize(#id{tag = {Tag, _}, val = Val}, Tag) when is_binary(Val) -> + Val; specialize(#id{tag = Tag, val = Val}, Tag) when ?IS_TAG(Tag), ?IS_VAL(Val) -> Val. -spec specialize_type(id()) -> tag(). +specialize_type(#id{tag = {Tag, _}}) when ?IS_TAG(Tag) -> + Tag; specialize_type(#id{tag = Tag}) when ?IS_TAG(Tag) -> Tag. +-spec is_account(id() | term()) -> boolean(). +is_account(#id{tag = account}) -> + true; +is_account(#id{tag = {account, _}}) -> + true; +is_account(_) -> + false. + +-spec account_pubkey(id()) -> val(). +account_pubkey(#id{tag = account, val = Val}) when ?IS_VAL(Val) -> + Val; +account_pubkey(#id{tag = {account, _}, val = Val}) when ?IS_VAL(Val) -> + Val. + +-spec to_map(id()) -> id_map(). +to_map(#id{tag = {Tag, SubType}, val = Val}) when ?IS_TAG(Tag) -> + #{ type => Tag + , subtype => SubType + , value => Val }; +to_map(#id{tag = Tag, val = Val}) when ?IS_TAG(Tag) -> + #{ type => Tag + , value => Val }. + + -spec is_id(term()) -> boolean(). is_id(#id{}) -> true; is_id(_) -> false. -spec encode(id()) -> binary(). +encode(#id{tag = {account, N}, val = Val}) when N =< 2#111_1111 -> + Ext = 2#1000_0000 bor N, + <>; encode(#id{tag = Tag, val = Val}) -> Res = <<(encode_tag(Tag)):?TAG_SIZE/unit:8, Val/binary>>, true = ?SERIALIZED_SIZE =:= byte_size(Res), Res. -spec decode(binary()) -> id(). +decode(<>) when Ext >= 2#1000_0000 -> + %% Extended account id type + Type = Ext band 2#0111_1111, + #id{ tag = {account, Type} + , val = Rest }; decode(<>) -> #id{ tag = decode_tag(Tag) , val = Val}. 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); diff --git a/test/gmser_api_encoder_tests.erl b/test/gmser_api_encoder_tests.erl index a5d7e13..df62fa9 100644 --- a/test/gmser_api_encoder_tests.erl +++ b/test/gmser_api_encoder_tests.erl @@ -194,7 +194,16 @@ known_types() -> Forms = get_forms(), [{type, _, union, Types}] = [Def || {attribute, _, type, {known_type, Def, []}} <- Forms], - [Name || {atom,_, Name} <- Types]. + lists:flatmap(fun known_type_entry/1, Types). + +known_type_entry({atom, _, Name}) -> + [Name]; +known_type_entry({type, _, tuple, + [{atom, _, account_pubkey}, + {type, _, range, [{integer, _, Lo}, {integer, _, Hi}]}]}) -> + [{account_pubkey, N} || N <- lists:seq(Lo, Hi)]; +known_type_entry(Other) -> + error({unsupported_known_type, Other}). mapped_prefixes() -> Forms = get_forms(), diff --git a/test/gmser_id_tests.erl b/test/gmser_id_tests.erl new file mode 100644 index 0000000..6ac5aa8 --- /dev/null +++ b/test/gmser_id_tests.erl @@ -0,0 +1,44 @@ +-module(gmser_id_tests). + +-include_lib("eunit/include/eunit.hrl"). + +-define(PUBKEY, <<12345:32/unit:8>>). + +is_account_test() -> + {"is_account recognizes standard and extended account ids", + fun() -> + ?assert(gmser_id:is_account(gmser_id:create(account, ?PUBKEY))), + ?assert(gmser_id:is_account(gmser_id:create({account, 0}, ?PUBKEY))), + ?assert(gmser_id:is_account(gmser_id:create({account, 5}, ?PUBKEY))), + ?assertNot(gmser_id:is_account(gmser_id:create(contract, ?PUBKEY))), + ?assertNot(gmser_id:is_account(not_an_id)) + end}. + +account_pubkey_test() -> + {"account_pubkey returns the 32-byte account hash", + fun() -> + ?assertEqual(?PUBKEY, + gmser_id:account_pubkey(gmser_id:create(account, ?PUBKEY))), + ?assertEqual(?PUBKEY, + gmser_id:account_pubkey(gmser_id:create({account, 3}, ?PUBKEY))), + ?assertEqual(?PUBKEY, + gmser_id:account_pubkey(gmser_id:create({account, 6}, ?PUBKEY))) + end}. + +account_pubkey_matches_specialize_test() -> + {"account_pubkey agrees with specialize/2 for account ids", + fun() -> + Id = gmser_id:create({account, 2}, ?PUBKEY), + ?assertEqual(gmser_id:specialize(Id, account), + gmser_id:account_pubkey(Id)) + end}. + +extended_account_roundtrip_test() -> + {"extended account ids round-trip through encode/decode", + fun() -> + Id = gmser_id:create({account, 4}, ?PUBKEY), + ?assert(gmser_id:is_account(Id)), + Id1 = gmser_id:decode(gmser_id:encode(Id)), + ?assertEqual(?PUBKEY, gmser_id:account_pubkey(Id1)), + ?assertEqual(account, gmser_id:specialize_type(Id1)) + end}. \ No newline at end of file