123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318(*****************************************************************************)(* *)(* Open Source License *)(* Copyright (c) 2022 Marigold <contact@marigold.dev> *)(* Copyright (c) 2022 Nomadic Labs <contact@nomadic-labs.com> *)(* Copyright (c) 2022 Oxhead Alpha <info@oxhead-alpha.com> *)(* *)(* Permission is hereby granted, free of charge, to any person obtaining a *)(* copy of this software and associated documentation files (the "Software"),*)(* to deal in the Software without restriction, including without limitation *)(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)(* and/or sell copies of the Software, and to permit persons to whom the *)(* Software is furnished to do so, subject to the following conditions: *)(* *)(* The above copyright notice and this permission notice shall be included *)(* in all copies or substantial portions of the Software. *)(* *)(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)(* DEALINGS IN THE SOFTWARE. *)(* *)(*****************************************************************************)openTx_rollup_l2_context_siglettag_size=`Uint8typesigner=Bls_pkofBls.Public_key.t|L2_addrofTx_rollup_l2_address.tmoduleSigner_indexable=Indexable.Make(structtypet=signerletppfmt=function|Bls_pk_->Format.pp_print_stringfmt"<bls_signature>"|L2_addraddr->Tx_rollup_l2_address.ppfmtaddrletcomparexy=match(x,y)with|Bls_pkpk1,Bls_pkpk2->Bls.Public_key.comparepk1pk2|L2_addraddr1,L2_addraddr2->Tx_rollup_l2_address.compareaddr1addr2|L2_addr_,Bls_pk_->-1|Bls_pk_,L2_addr_->1letencoding=letopenData_encodinginunion[case~title:"bls_pk"(Tag0)Bls.Public_key.encoding(functionBls_pkpk->Somepk|_->None)(funpk->Bls_pkpk);case~title:"l2_addr"(Tag1)Tx_rollup_l2_address.encoding(functionL2_addraddr->Someaddr|_->None)(funaddr->L2_addraddr);]end)moduleV1=structtype'statusoperation_content=|Withdrawof{destination:Signature.Public_key_hash.t;ticket_hash:Alpha_context.Ticket_hash.t;qty:Tx_rollup_l2_qty.t;}|Transferof{destination:'statusTx_rollup_l2_address.Indexable.t;ticket_hash:'statusTicket_indexable.t;qty:Tx_rollup_l2_qty.t;}type('signer,'content)operation={signer:'signerSigner_indexable.t;counter:int64;contents:'contentoperation_contentlist;}type('signer,'content)transaction=('signer,'content)operationlisttypesignature=Bls.ttype('signer,'content)t={contents:('signer,'content)transactionlist;aggregated_signature:signature;}(* --- ENCODING ------------------------------------------------------------- *)(* --- [operation_content] *)letcompact_binary_operation_content=letopenData_encoding.Compactinunion[case~title:"withdraw"(obj3(req"destination"(payloadSignature.Public_key_hash.encoding))(req"ticket_hash"(payloadAlpha_context.Ticket_hash.encoding))(req"qty"Tx_rollup_l2_qty.compact_encoding))(function|Withdraw{destination;ticket_hash;qty}->Some(destination,ticket_hash,qty)|_->None)(fun(destination,ticket_hash,qty)->Withdraw{destination;ticket_hash;qty});case~title:"transfer"(obj3(req"destination"(Indexable.compactTx_rollup_l2_address.encoding))(req"ticket_hash"Ticket_indexable.compact)(req"qty"Tx_rollup_l2_qty.compact_encoding))(function|Transfer{destination;ticket_hash;qty}->Some(destination,ticket_hash,qty)|_->None)(fun(destination,ticket_hash,qty)->Transfer{destination;ticket_hash;qty});]letnon_tz4_public_key_hash_encoding=letopenData_encodinginconv_with_guard(funpkh->pkh)(fun(pkh:Signature.public_key_hash)->matchpkhwith|(Ed25519_|Secp256k1_|P256_)aspkh->Okpkh|Bls_->Error"Withdraw to tz4 address is not supported in the deprecated \
encoding.")Signature.Public_key_hash.encoding(** JSON encoding for [operation_content] which allows to represent
withdrawals to tz4 accounts. The [deprecated_] variants are kept for
backward compatibility purpose. *)letjson_operation_content=letopenData_encodinginletwithdraw_deprecateddestination=obj3(req"destination"destination)(req"ticket_hash"Alpha_context.Ticket_hash.encoding)(req"qty"(Compact.make~tag_sizeTx_rollup_l2_qty.compact_encoding))inletwithdraw=merge_objs(obj1(req"direction"(constant"withdraw")))(withdraw_deprecatedSignature.Public_key_hash.encoding)inlettransfer_deprecated=obj3(req"destination"(Indexable.encodingTx_rollup_l2_address.encoding))(req"ticket_hash"(Compact.make~tag_sizeTicket_indexable.compact))(req"qty"(Compact.make~tag_sizeTx_rollup_l2_qty.compact_encoding))inlettransfer=merge_objs(obj1(req"direction"(constant"transfer")))transfer_deprecatedinmatching(function|Withdraw{destination;ticket_hash;qty}->matched0withdraw((),(destination,ticket_hash,qty))|Transfer{destination;ticket_hash;qty}->matched1transfer((),(destination,ticket_hash,qty)))[caseJson_only~title:"withdraw"withdraw(function|Withdraw{destination;ticket_hash;qty}->Some((),(destination,ticket_hash,qty))|_->None)(fun((),(destination,ticket_hash,qty))->Withdraw{destination;ticket_hash;qty});caseJson_only~title:"transfer"transfer(function|Transfer{destination;ticket_hash;qty}->Some((),(destination,ticket_hash,qty))|_->None)(fun((),(destination,ticket_hash,qty))->Transfer{destination;ticket_hash;qty});caseJson_only~title:"deprecated_withdraw"(withdraw_deprecatednon_tz4_public_key_hash_encoding)(function|Withdraw{destination;ticket_hash;qty}->Some(destination,ticket_hash,qty)|_->None)(fun(destination,ticket_hash,qty)->Withdraw{destination;ticket_hash;qty});caseJson_only~title:"deprecated_transfer"transfer_deprecated(function|Transfer{destination;ticket_hash;qty}->Some(destination,ticket_hash,qty)|_->None)(fun(destination,ticket_hash,qty)->Transfer{destination;ticket_hash;qty});]letcompact_operation_content=(* This is equivalent to Data_encoding.Compact.splitted *)Data_encoding.Compact.conv~json:json_operation_content(funx->x)(funx->x)compact_binary_operation_contentletoperation_content_encoding=Data_encoding.Compact.make~tag_sizecompact_operation_contentletcompact_operationencoding_signer=Data_encoding.Compact.(conv(fun{signer;counter;contents}->(signer,counter,contents))(fun(signer,counter,contents)->{signer;counter;contents})@@obj3(req"signer"encoding_signer)(req"counter"int64)(req"contents"@@list~bits:4operation_content_encoding))letoperation_encodingencoding_signer=Data_encoding.Compact.(make~tag_size(compact_operationencoding_signer))letcompact_transactionencoding_signer=Data_encoding.Compact.list~bits:8(operation_encodingencoding_signer)lettransaction_encoding:'a->('b,Indexable.unknown)transactionData_encoding.t=funencoding_signer->Data_encoding.Compact.(make~tag_size(compact_transactionencoding_signer))letcompact_signer_index=Data_encoding.Compact.(convIndexable.to_int32Indexable.index_exnint32)letcompact_signer_either=Signer_indexable.compactletcompact_operation=compact_operationcompact_signer_eitherletcompact_transaction_signer_index=compact_transactioncompact_signer_indexletcompact_transaction=compact_transactioncompact_signer_eitherlettransaction_encoding=transaction_encodingcompact_signer_eitherletcompact~bits:(Indexable.unknown,Indexable.unknown)tData_encoding.Compact.t=Data_encoding.Compact.(conv(fun{aggregated_signature;contents}->(aggregated_signature,contents))(fun(aggregated_signature,contents)->{aggregated_signature;contents})@@obj2(req"aggregated_signature"@@payloadBls.encoding)(req"contents"@@list~bitstransaction_encoding))endtype('signer,'content)t=V1of('signer,'content)V1.t(** We use two bits for the versioning of the layer-2 batches, which
leaves six bits in the shared tag of compact encoding. We use
these six bits to efficiently encode small lists.
To ensure backward compatibility, the value of the label
[tag_bits] cannot be modified. To have more than 3 versions of the
encoding, one would have to use the fourth case to wrap a new
union.
{[
union
~tag_bits:2
~inner_bits:6
[
case "V1" ...;
case "V2" ...;
case "V3" ...;
case "V_next" ...
(union [ case "V4" ... ; ... ]);
]
]} *)letcompact=Data_encoding.Compact.(union~union_tag_bits:2~cases_tag_bits:6[case~title:"V1"(V1.compact~bits:6)(functionV1x->Somex)(funx->V1x);])(** An encoding for [t] that uses a specialized, space-efficient encoding
for the list of transactions. *)letencoding:(Indexable.unknown,Indexable.unknown)tData_encoding.t=Data_encoding.Compact.make~tag_sizecompact