
All checks were successful
Gajumaru Serialization Tests / tests (push) Successful in 49m9s
84 lines
2.7 KiB
Markdown
84 lines
2.7 KiB
Markdown
|
|
# Static Serialization
|
|
|
|
The `gmserialization` and `gmser_chain_objects` modules implement the
|
|
static serialization support used in the Gajumaru blockchain.
|
|
|
|
The purpose is to produce fully deterministic serialization, in order
|
|
to maintain predictable hashing.
|
|
|
|
Example:
|
|
|
|
```erlang
|
|
%% deterministic canonical serialization.
|
|
-spec serialize_to_binary(signed_tx()) -> binary_signed_tx().
|
|
serialize_to_binary(#signed_tx{tx = Tx, signatures = Sigs}) ->
|
|
gmser_chain_objects:serialize(
|
|
?SIG_TX_TYPE,
|
|
?SIG_TX_VSN,
|
|
serialization_template(?SIG_TX_VSN),
|
|
[ {signatures, lists:sort(Sigs)}
|
|
, {transaction, aetx:serialize_to_binary(Tx)}
|
|
]).
|
|
|
|
-spec deserialize_from_binary(binary()) -> signed_tx().
|
|
deserialize_from_binary(SignedTxBin) when is_binary(SignedTxBin) ->
|
|
[ {signatures, Sigs}
|
|
, {transaction, TxBin}
|
|
] = gmser_chain_objects:deserialize(
|
|
?SIG_TX_TYPE,
|
|
?SIG_TX_VSN,
|
|
serialization_template(?SIG_TX_VSN),
|
|
SignedTxBin),
|
|
assert_sigs_size(Sigs),
|
|
#signed_tx{ tx = aetx:deserialize_from_binary(TxBin)
|
|
, signatures = Sigs
|
|
}.
|
|
|
|
serialization_template(?SIG_TX_VSN) ->
|
|
[ {signatures, [binary]}
|
|
, {transaction, binary}
|
|
].
|
|
```
|
|
|
|
The terms that can be encoded using these templates are given by
|
|
this type in `gmserialization.erl`:
|
|
|
|
```erlang
|
|
-type encodable_term() :: non_neg_integer()
|
|
| binary()
|
|
| boolean()
|
|
| [encodable_term()] %% Of any length
|
|
| #{atom() => encodable_term()}
|
|
| tuple() %% Any arity, containing encodable_term().
|
|
| gmser_id:id().
|
|
```
|
|
|
|
The template 'language' is defined by these types:
|
|
|
|
```erlang
|
|
-type template() :: [{field_name(), type()}].
|
|
-type field_name() :: atom().
|
|
-type type() :: 'int'
|
|
| 'bool'
|
|
| 'binary'
|
|
| 'id' %% As defined in aec_id.erl
|
|
| [type()] %% Length one in the type. This means a list of any length.
|
|
| #{items := [{field_name(), type()}]} %% Record with named fields
|
|
%% represented as a map.
|
|
%% Encoded as a list in the given
|
|
%% order.
|
|
| tuple(). %% Any arity, containing type(). This means a static size array.
|
|
```
|
|
|
|
The `gmser_chain_objects.erl` module specifies a serialization code for each
|
|
object that can go on-chain. E.g.:
|
|
|
|
```erlang
|
|
tag(signed_tx) -> 11;
|
|
...
|
|
rev_tag(11) -> signed_tx;
|
|
```
|
|
|
|
The `tag` and `vsn` are laid out in the beginning of the serialized object.
|