! / 0 0 0 0 4686 `  ::::MMMMMBBBB%%%%%%%%%%%%%%%########################################################################################################### g g g 5z N N N N N z ض ض ض ض ض ض ض ض ض ض 7 7 7 7%^^^^^^^^^^^^^^^yyyyNZNZNZNZNZNZNZ555555555555~))))))))))))))))jjb58tobinb58digits_mapb58encb58digits_orderedRMD160_initRMD160_compressRMD160_finishRMD160_processRMD160_hashbech32_encodebech32_decodesegwit_addr_encodesegwit_addr_decodehex2bufbuf2hexB64encoded_lenB64decoded_lenis_url64U64decodeU64encodeb45encodeb45decodeis_base45sha256_rawmnemonic_from_datamnemonic_to_bitsmnemonic_check_and_bitsmnemonic_wordlistzen_unsetzen_setenvzen_add_functionzen_add_classzen_extensionszenroom_zpack_lenzenroom_zpackinspect_leninspectzencode_debug_lenzencode_debugzencode_data_lenzencode_datazencode_qp_lenzencode_qpzencode_petition_lenzencode_petitioncrypto_petition_lencrypto_petitionstatemachine_lenstatemachinezencode_lenzencodezencode_given_lenzencode_givencrypto_lagrange_interpolation_lencrypto_lagrange_interpolationzenroom_octet_lenzenroom_octetzencode_secshare_lenzencode_secsharezenroom_common_lenzenroom_commoncrypto_bitcoin_lencrypto_bitcoinzencode_dictionary_lenzencode_dictionaryzencode_hash_lenzencode_hashinit_leninitzencode_credential_lenzencode_credentialmsgpack_lenmsgpackcrypto_schnorr_signature_lencrypto_schnorr_signaturejson_lenjsontimetable_lentimetablecbor_lencborzencode_schnorr_lenzencode_schnorrzenroom_bench_lenzenroom_benchzencode_when_lenzencode_whenzencode_verify_lenzencode_verifyzenroom_json_lenzenroom_jsonzenroom_cbor_lenzenroom_cborzencode_array_lenzencode_arrayzenroom_ecdh_lenzenroom_ecdhstats_lenstatszencode_random_lenzencode_randomhdwallet_lenhdwalletcrypto_elgamal_lencrypto_elgamalzenroom_hash_lenzenroom_hashzenroom_ecp_lenzenroom_ecpzencode_http_lenzencode_httpcrypto_credential_lencrypto_credentialzencode_then_lenzencode_thenzenroom_ecp2_lenzenroom_ecp2zencode_bitcoin_lenzencode_bitcoincrypto_ethereum_lencrypto_ethereumzencode_reflow_lenzencode_reflowsemver_lensemverzencode_dp3t_lenzencode_dp3tzenroom_big_lenzenroom_bigzencode_ethereum_lenzencode_ethereumzencode_keyring_lenzencode_keyringzencode_ecdh_lenzencode_ecdhzenroom_msgpack_lenzenroom_msgpackzencode_w3c_lenzencode_w3cnopzen_exitcodezen_load_stringzen_exec_extensionzen_requirelualibszen_require_overridezen_lua_initlua_fatalluaopen_ioluaL_loadbufferxmutt_vsnprintfmutt_snprintfrandombytesrepl_readrepl_flushrepl_writerepl_promptrepl_loopluaopen_aesbig_new_bitsizebig_initdbig_init_octet_to_bigbig_argbig_destroybig_dupnew_octet_from_bigluaopen_bigstb_c_lexer_initstb_c_lexer_get_locationstb_c_lexer_get_tokenzen_conf_parsezconf_rngseedzconf_printfecdh_destroyECDHecdh_argluaopen_ecdhluaopen_qp_ecp2_to_octetecp2_newecp2_argecp2_destroyecp2_dupluaopen_ecp2ecp_newecp_argecp_destroyecp_dup_fp_to_big_ecp_to_octetluaopen_ecpzencode_tracebackset_colornoticeANSI_RESETANSI_GREENfuncerrorANSI_REDlerroractwarningANSI_YELLOWANSI_CYANANSI_MAGENTAANSI_BLUEfp12_newfp12_argfp12_destroyfp12_dupluaopen_fp12hash_newhash_arghash_destroyluaopen_hashzen_zstd_compresszen_zstd_decompresszen_write_err_vazen_write_out_vazen_write_errzen_write_outzen_add_iozen_memory_alloczen_memory_realloczen_memory_freesystem_allocsystem_reallocsystem_freezen_memory_managero_destroyis_base64push_octet_to_hex_stringis_base58is_hexis_bino_newo_argto_hexo_duppush_buffer_to_octetluaopen_octetzen_add_parseruntime_random256rng_alloczen_add_randomz_set_separatorsz_vsprintfcbz_sprintfz_vsnprintfz_snprintfz_vsprintfzen_initZzen_teardownzen_exec_zencodeEXITCODEzen_exec_scriptzencode_execzenroom_execzencode_exec_tobufzenroom_exec_tobufecdh_initecdh_add// 620 ` .._src_base58.c.o/ .._src_rmd160.c.o/ .._src_segwit_addr.c.o/ .._src_cortex_m.c.o/ .._src_encoding.c.o/ .._src_lua_functions.c.o/ .._src_lualibs_detected.c.o/ .._src_lua_modules.c.o/ .._src_lua_shims.c.o/ .._src_mutt_sprintf.c.o/ .._src_randombytes.c.o/ .._src_zen_aes.c.o/ .._src_zen_big.c.o/ .._src_zen_config.c.o/ .._src_zen_ecdh.c.o/ .._src_zen_qp.c.o/ .._src_zen_ecp2.c.o/ .._src_zen_ecp.c.o/ .._src_zen_error.c.o/ .._src_zen_fp12.c.o/ .._src_zen_hash.c.o/ .._src_zen_io.c.o/ .._src_zen_memory.c.o/ .._src_zen_octet.c.o/ .._src_zen_parse.c.o/ .._src_zen_random.c.o/ .._src_zenroom.c.o/ .._src_zen_ecdh_factory.c.o/ /0 0 0 0 644 14408 ` ELF>2@@UIHAWIAVAUATSHHHH}HdH%(HEHHEHIHHIHH%H)HH9tHH$H9uH)HLl$E1LIHHEEEMu HIMtJ1LLMLM1MufDGHI9;<1tI9L\;IOTxdfDH tNMt'LҋHHHk:HHÉBH HI9u܅uDA#EuM9)AIy1HUdH+%(He[A\A]A^A_]AAEA}HE1I9v6I)ILJ<HHֈpP@p@pH9uIH}H]HH)HufHHIH9t;tIM3HL(H}EHU< HH@rH9u6ADUIHAWIAVAUATE1SH8H}dH%(HE1Hu5DIL9#C<#tH(\(IM)MiLHHHHHBILrHHHHHH)H9tHH$H9u%H)HL1HHML]HLEHML9L]LELA =O#IDAI9wB +HIH%k:)LB +Icw- 3HIH%k:) 3HHH9w҅uHIM9uE1B<+u IM9uK &L)I9MM9HEM)H5J @B+B*IM9uHEHIHUdH+%(He[A\A]A^A_]@1NLFH1H}L1HMHM\HLZHH9tHH$H9uHHL$A$HLE123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz  !"#$%&'()*+,-./0123456789 fAintO%u&O*b-Ai|  A  . A: . T!`5sHe b58sses2js?5binupvHiw 5jw 5w5w5x 5buf~ uAE h _ VrUsT0Q~EWh _ VrUT1Q|}5o A'H( bin''!e b58'5'A5) 5*(+-, 5-2t.Hc/Ti0 5j0 51 2T3 bAuUsrU}T0Q~2$}VO TEA9r H 5 4:!; 9 IB: ; 9 II~$ > 4:!; 9 IB&I !I:!; 9 IB 1B I :!; 9 IB :!;!99!I !I/ 4:!; 9 I?.?:!; 9!'I@z4I4B1RB UX!Y W H}H}!I/H}% $ >  4: ; 9 I.?: ;9 'I<I1&.?: ; 9 'I 4.?<n: ; .?<nU U U UT _ T _ T _Q[ Q  Q [ Q QR R  R R RQ[ Q  Q [ Q QPzPRs}"8$z"PPRP Pz z#z z]T}] ] T ]]QQ Q Q 00|\^ ^ ^ 1 s s sQ]T] ] ] 0Q^ 10 0S S 1 U UUUUUUT_TT_T_OQOSQSQSQ%R%YRYYY9=P=at9OQOSQSQSQ 9UUUUPPUUQUL^^^^}}}PR0Us {"{QQ {"U43210sUU s"sUP3qU"3qU"#q 3"U"^~003w333\\\0UPUPUL~~~~,f(    ]   'O 8=6 J= K< W,7u WY  YXN .+;JJ M[ %..: LJ= =;u^Mtn.   L-..J QA W<QfW< <i<S,J 6.  GM.<<"sX"I""  X zFN8Z\  > V> X, IJK< .J-=I[XXX[9X/Iw f t<  I<K <&= JX&O wJ <1JXX <.=J w  <KfJ <.=J =;1J2&J X#tJZJ< X X "JZ  L  uX <t ^f.1^<XK J X  fJ=&X__uint8_tsize_tb58szhighb58u__destbinszpuint64_tint8_tcarrystrlendatazerocountsize__builtin_memsetlong unsigned intshort unsigned intoutiszb58digits_orderedb58_maxint_t__stack_chk_failunsigned charmemsetb58digits_map__uint32_tb58encunsigned intchar__chbinub58tobinGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionuint8_tbytesleftb58_almostmaxint_maskb58_almostmaxint_tzeromaskshort int__uint64_tbinszuint32_tlong int__len__int8_tsigned charzcountouti../src/base58.c/home/alby/dev/Zenroom/meson/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include../src/base58.cbase58.cstring_fortified.hstddef.htypes.hstdint-intn.hstdint-uintn.hstring.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx ,EF BJ A ,LEF BIH  E     !7@EV];base58.cb58tobinstrlenmemset_GLOBAL_OFFSET_TABLE_b58digits_map__stack_chk_failb58encb58digits_ordered  +* * b  '  * 1 F6  D qR ^ e j Ux ^}  "  ,  8  = /  4 @I U f v E      C 7 L  q 7   /   ?  |, 0 = CA 5F P T wY jc g l [v z    !    Z T u q    ! # , 0 5 Xf    (   I ;    7      % -) . 8 < A qK O \ ` m q ~          K E Q m a  F W !` i Os w `~   " -& J* Q. t2 < A F K P U Z _ d n P.symtab.strtab.shstrtab.rela.text.data.bss.rodata.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @f@h!&,1 >9@(" J X m0h@H/0 |,@x/h 0v0q0& x@00H   o1/19 0 0 0 644 31560 ` ELF>Hu@@HdH%(HD$H#EgGHHܺvT2HGHD$dH+%(uHff.AWIHAVAUATUSHXEPdH%(HT$H1ҋEHA3xA \$ A3x NE1ApEh AxDpL$$A A1AE1AAP ADEH EDD1DxDt$(D|$DDP DDT$,EDEA A1D1DDX1C4+ D1A A1 DD1A xA1|$ DAD1A X$DDHA1Dp,\$Dx4DL$DEA1D` D|$Aɉ A 1Dd$ADD`0D1D 1X(1A Չ D11 1D1 1DE1DAA1DEDH8A1AωA A1D D1hNS 1|$ эNS 1 B<:B=NST$4 ʉ|$0 1|$ANS4L$$M\A1DA!A 1ЋT$,D B*$M\DAA1E!AA1 AՋT$AA͍ $M\E1D!1ʉD$  8$M\D1A!D1A NjD$ 0$M\A1DD!1֋T$ ȍ $M\1A!1  DF+$M\A1D!1DAA1$M\ A 1AD!1 =$M\A1D!1׋T$ DB*$M\AA1AA!A1 AA AA $M\E1DDT$!1ʉA;$M\ D1!D1A2$M\AA A1DDT$$D!1 A $M\1!1 ΋L$( DB)$M\AA1A!A1 A͉ A AՍ>pmD 1ыT$ :>pmD 1A A>pmA AD D1‹D$,0>pm A A1ƋD$ DF(>pmD 1DAA >pmA ȉ A AD1ыT$ :>pmDDT$ 1C*>pmDA AA A AA1ADAAA6>pmD 1֋T$ :>pmDA A A1D A >pm D1ʉD$( 0>pm A A1DDF+>pm 1DAՋT$ A ȍ >pm A AD1D A;>pm 1NjD$ DB(>pmA AAA A1A1AŋD$AA0vmzDD!1֋T$  :vmzD1A!1A E1DA vmz!D1ʉD$$ 0vmz 1A!A11ƋD$, DF(vmzD!1DAAvmzA ȉD1A!D1 =vmzA1D!1NjD$  DB(vmzA A1AA!A1A1AŋD$AA0vmzDD!1A >0X>+0aa@ bb@cc@*ddA eeAaaaB bbbBcccB*dddC eeeC 1R10 9H  H f .I~4:!; 9 IB$ > :!;9 IB1B: ; 9 IH}H} .?:!;9!'@z 4:!;9 IB :!;!99!I  !I 4:!;9 I.?:!; 9!'@z:!; 9 IB%  $ > H}4: ;9 IBI!I/ 1RBUX YW 1RBX YW : ; 9 IB.?: ; 9 'I 4.?<n4,-U--U--U--U,-T--T--T--T,,0,-P--p++U+,^,,U,,U,,^++T++S++sp"++sp"#+,sp",, sp"@,,S,,S++Q+,],,Q,,Q,,]++p2%++p2%#+,p|2%#++Q+,],,Q,,Q,,]()U)+\++U++U++\()T)*U++T()Q)*S*+Q++Q++Q()R)*V*+R++V++R))0))P))R)*T**p**P++0))@))0))**@**0**`U(X((U`TP(TuQU4xx'x 'xs"";$  # %!x"UT\TQTQ t'r'q"QQTQpt'rt'"qt'rt'"QQpt'rt'"qt'rt'"QQQpt'rt'"qt'rt'"QQt  Q p r!t'" q r!t'" qr!t'" Q Q Q p r!t'" q r!t'" qr!t'" Q Q Q p r!t'" q r!t'" qr!t'" Q Q pr'tp'" Q Q Qpr'tp'"QQQpr'tp'"QQQ t u!r'"QQ_ t q!r'"PPTT q !p'r"TTQ(uUYx] ry'q't"Vxx'x 'xs"";$  # %!x"xx'x 'xs"";$  # %!x"x'z'xp"">$  # %!x "'}'x ~""?$  # %!z"y'q't"V\V yu'r'v"VVTV tu''v"RRURtu'pu'"ru'pu'"RRURtu'pu'"ru'pu'"RRURtu'pu'"ru'pu'"R R t p!u'" r p!u'" rp!u'" R R U u  R t p!u'" r p!u'" rp!u'" R R U u  R t p!u'" r p!u'" rp!u'" R R U u  R tp'ut'" R R Rtp'ut'"RRRtp'ut'"RRR p t!u'"RRR u t!q'p"RR u q!'r"PPPr !'"4r !'"6$  # %!"4 !'"6$  # %!"ZxZ[ yu'r't" {u'r't"lxx'x 'xs"";$  # %!x"x'z'xp"">$  # %!x "u'r't"Qqxx'x 'xs"";$  # %!x"x'z'xp"">$  # %!x "u'r'p z""QQRQR uq't'r"__PPuq'tq'"PPQPuq'tq'"PPQPuq'tq'"pq'tq'"PPQ P u t!q'" p t!q'" pt!q'" P P Q q  P u t!q'" p t!q'" pt!q'" P P Q q  P u t!q'" p t!q'" pt!q'" P P Q q  P ut'qu'" P P P ut'qu'" PPPut'qu'"PP_pt'qp'"UUU  p!t'u"QQ_ t u!q'p"___ q r!u't"u x Rxx'x 'xs"";$  # %!x"xx'x 'xs"";$  # %!x"x'z'xp"">$  # %!x "'}'x ~""?$  # %!z"RYYTTqr'ur'"tr'ur'"TTRTqr'ur'"TTRTqr'ur'"TTRT q u!r'" tu!r'" T T R r  T q u!r'" T T R r  T q u!r'" T T R r  T q u!r'" T T T qu'rq'" T TTqu'rq'"TTTqp'rq'u"TTT r q!p'"TTT r p!u't"QQQ p t!r'u"QU':$  # %!'([((:$  # %!((~:$  # %!uxxz'u't"?xx'x 'xs"";$  # %!x"x'z't"Y[cxx'x 'xs"";$  # %!x"x'z'xp"">$  # %!x "YURUUUrp'qp'"up'qp'"UUUrp'qp'"up'qp'"UUUrp'qp'"up'qp'"UUPUrp'qp'"U U P p  U r q!p'" u q!p'" uq!p'" U U P p  U r q!p'" u q!p'" uq!p'" U U P p  U r q!p'" u q!p'" uq!p'" U U U rq'pr'" U UUrq'pr'"UUUrq'r'u"PPP u r!q'"PPU  r!p'q"U  r!p'q"UU  p!t'u"RRR(_(( uQx!x  x!x'~"x"#旊tx'~"x"#旊!x  x!x'~"x"#旊T>x  x!x'~"x"#旊8$  # %!x"T z q!u't" } q!u't"PP]] u t!p'q"]]] u p!r'}"QQU}q'r}'p"UUUqt'rq'u"PPRRup'qu'r"TTRr T u q!r'p" t q!r'p" tq!r'p"TTRr T q }!r't"PPRz  R t p!}'q" r p!}'q" rp!}'q" R R ] }  !R!!p}'u}'r"!!Q!"Q""]""]""ru'qu'p"""}u'qu'p"""]"#]##U##]#$qu'tu'}"$$zu'tu'}"$$P$$P$$U$%P%%T%&T&&[&&[&& rp'u'{"&' yp'u'{"''Q''Q'(QuUYx]r p!q'z"}"#旊uq'z"}"#旊r p!q'z"}"#旊0r p!q'x:$  # %!"z"#旊0r }!q'x:$  # %!"z"#旊UU r q!t'u" r z!t'u"P r z!t'u"PRR t u!p'q"R t u!p'q"RRp}'tp'r"QQTTrq'}r'p"TTTqu'}q't"PPP r u!}'p" z u!}'p" zu!}'p"QQ]z ] r q!u'p" }q!u'p"]]Uu ] q t!u'}"P P U z  !U!!}t'pt'q"!!U!!U!!T!"U""pt'rt'u"""Q"#Q##T##T##ur'qr'p"##tr'qr'p"##T#$T$$R$$T$$ ur'q't"$$ |r'q't"%%\%%\%%V%%\&&Q&&T&&Q&'UZxZt r!p'"z"#旊qp'"z"#旊z x!x  x!x'~"x"#旊8$  # %!x"'y"x"#旊9$  # %!x "t !p'"z"#旊x:$  # %! x!x  x!x'~"x"#旊8$  # %!x"'y"x"#旊9$  # %!x "t !p'x:$  # %!""#旊QTT } r!q'p"TTT } q!u't"PP]]tp'ut'q"]]]pr'up'}"QQUU}q'r}'p"U}q'r}'p"UU } r!t'q"U } r!t'q"UTt U p r!t'u"QQTz T u q!r'p" t q!r'p" tq!r'p"T T R r  T qr'}r't" !P!!P!!R!"R""t}'p}'q"""R""t}'p}'q"""R""]"#R##p}'u}'r"##Q#$Q$$Z$$Q$$rp'up'}"$$Q$%Q%%T%%Q%% pt'r'q"%%U%%U%&[&&U&&R&'Y''R'(Pu x } t!r'q"x "#旊pr'q"x "#旊Sx  x!x'~"x"#旊8$  # %!x"} !r'q"x "#旊Vx  x!x'~"x"#旊8$  # %!x"} !r'"x "#旊P]x  x!x'~"x"#旊8$  # %!x"x:$  # %! !x:$  # %! x!x  x!x'~"x"#旊8$  # %!x"'y"x"#旊9$  # %!x "'"x "#旊9$  # %!x:$  # %!"Z] u p!r'}"QQZU r }!q'p"UUqt'rq'u"PPRRup'tu'q"RRRp}'tp'r"QQQRZz R t p!}'q" r p!}'q" rp!}'q"RR} R p u!}'r"QQ]z  ] r q!u'p" } q!u'p" }q!u'p" ] !]!!]!"qu'tu'}"""P""P""U"#U##}t'pt'q"##ut'pt'q"##U##U##T#$U$$pt'rt'}"$$ut'rt'}"$$U$$U$$\%%U%% t|'p'u"%%R%% t|'p'u"%%R&&R&& {q't'r"&&P&&P&&V&'P'' qu'y'p"''T''T''Z'( z"((P((xuxrt'y"x"#旊z x!t'y"x"#旊Rrz x!x  x!x'~"x"#旊8$  # %!x"'y"x"#旊9$  # %!x "x:$  # %! x!x  x!x'~"x"#旊8$  # %!x"'y"x"#旊9$  # %!x "R t u!p'q"RRR t p!}'r"QQTTrq'}r'p"TTTqu'}q't"PP]]tp'ut'q"]]pt'up'r"]]] q t!u'}"PPU } p!t'q" u p!t'q" up!t'q"UUTt  U p r!t'u" Q !Q!!T!!T!!ur'qr'p"!!tr'qr'p"!!T!"T"#qr'}r't"##P##P##R#$R$$tq'pq'}"$$rq'pq'}"$$R$$R$%R%%P%&P&&T&&R&'T'' ur'q't"''Y''Y''P'(YQUQRU,"(()))))))) O  1 xv z> {yf/I<!<*J$<.d^L<ZfY~ %u<=;/:KKZtrtL Xy   uJhL+ XJX.v  XXJY$.K$XK$XFJnIXXmessagesize_tlong int__destlswlenhashcodebyteunsigned charstrptrlong unsigned intshort unsigned intRMD160_init__stack_chk_failmemset__uint32_tmswlenunsigned intMDbuf__chGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionlong long intcharshort intRMD160_finish__lenlengthRMD160_hashuint32_tRMD160_processsigned charnbytesdwordRMD160_compress/home/alby/dev/Zenroom/meson../src/rmd160.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include../src/rmd160.crmd160.cstring_fortified.hstddef.htypes.hstdint-uintn.hrmd160.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx RH D A L8 FHB B(A0A8D 8A0A(B BBBA 8&FOK G(F (A ABBE @FEE A(A0G 0A(A BBBA fH T E    R'` 7p&ETPfrmd160.cRMD160_init__stack_chk_failRMD160_compressRMD160_finishRMD160_processRMD160_hashN h ( e   ! H       * / = ID M 4T [[ b n |   s  /  P    & ? 7 h b #; AX c g l w {     K E  { q%L. 4pK V Z _ Bj n s ~    - # e W        , ,) - 6 : C G M,li `           ;    , * .  = A P O T c $g :$v C*z ) `0 /l n  u4 q4R      z z " -& J* Q. t8 = B G L Q V ``X p <`p P.symtab.strtab.shstrtab.rela.text.data.bss.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@e&,61@f B P4eMR0`@`r0 t}R&R @rP 0n_0fa0Xb&~bb b @sxc  @e`Xt/38 0 0 0 644 20760 ` ELF>J@@HdH%(HD$1?Љу%Wj;mP&11ȉ1ȉb*3B=11HT$dH+%(uHAWAVAUIATUHSH(D&H $DD$ dH%(HD$1E|HDE1+fAFv-DBT;1IGt:IDAF߃]v1HT$dH+%(`H([]A\A]A^A_DH$IDHZwf.HDEeD#I1EuH$AE1MeHtLIL-I'DSIH1ADAD$I9t]t : ; 9 II  !I :!; 9 IB 41B H} &II!I/ 4:!; 9 I4:!; 9 IB.?:!; 9 'I@z:!; 9 I:!;!9 I( 4:!; 9 I1RB UX!Y W  U U.:!; 9 'I !% $ > > I: ; 9 .?: ; 9 'I<.?: ;9 'I< .?: ; 9 '<!4: ; 9 I"1RB X Y W #H}$4I4%.: ; 9 'I@z&.?<n  U } T \T\ Q SQS R _R_ X X P ]]]0055Z{~}2z}" z}" z}" z}" z}" ~~ZZZ88SS\\0TTTT05URUR U U T Z T Q Q R S R X R t X 0 P p P 1 X Q $0+# 1 8 t t X1 S 5   0 T T 0 R rx R OU T Q^Q^ Q ^ QR_R _1UQU1QPU U P U 1 P0^~^^0| |"S S 0 1PV V} v"} v"00    0010  0P\P\ ^ ^U]]}]\|\QU]\TSSTTQVVvVQVRRXXXXX1UUUPUUUPU1PU0_P_P06s7s6s0q|| q"q|06s^^^ 0+ U QUUQUXRXUI%,T    \]  3 3-L3:=g/-= ;/;Y%d*/0 X<*e0/; =;=e*e/0m"wmG ;X R J Y.X fy. m /Jx Ry<  K JY.kJXg X/ Y0I= H0K= I /\I XKX? +X=%J I / Y  Jtl X-J1QJY0X -K $.$J-6=<s[ g l XX/^XX2^>t[^9KX=JJu" - "; "I1 $Jus  o< \X gL < t J.X fJt YYW =  i Xgto6. N.>  = I$= JK X/ 4XW4K <-[K% 5x%| z<<    X Y J Y% ZJu Y(X5(J Y < :  ] O '    ! Q% 9* 4 8 = G K P Z ^ c Im Xq Hv '   7  %5#? :(? I M \ P` Fe To s wx      T :    o  i     m"m: > CTatTef   ( I M Z ^ c q u   " 2& O* V. 2 < A F K P U Z _ d n <@@.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.8.rodata.str1.1.rodata.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@/&=,=12@!@2aO \ z W@`1xhQ{ v@F 0@F0 X_`@ Gh0&90) 0+&>+@+  `+H@Hx,p /I/62 0 0 0 644 2744 ` ELF>@@a int$ > % $ > -% unsigned intlong unsigned intsigned charshort unsigned intshort intGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionunsigned charlong intcharlong long int/home/alby/dev/Zenroom/meson../src/cortex_m.c/home/alby/dev/Zenroom/meson../src/cortex_m.cGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNU   cortex_m.c  H   !  (  6 = +D K R >Y `  " /, L.symtab.strtab.shstrtab.text.data.bss.rela.debug_info.debug_abbrev.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property@!@'@1@e,@P=&P K@d1_@0 p0){0E^0&   @/83 0 0 0 644 111672 ` ELF>@@HdH%(HD$1Ht`I1H=E1JMcȃHcAH C HcHuHD$dH+%(uDHf.E1fDHIdH%(HD$1Ht@?456789:;<=@@@@@@@ @@@@?@ !"#$%&'()*+,-./0123@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@0123456789abcdef  l) .     &.  (: )*int *A +   u V i  H,H    OE-.lG /I$hJ$wK(0L hHHHO MPH H7 5*HC* UH@EVU H-p H 1   2    )  : j9jK *)len8C  z   TU}T~QsUUT9U~TvQ~K H 3R\%"%2iW nW&f\jg kgkigbig"&hlH 289221len2; 7?iAjA idxA pB  =!   ]UTTQ Q $ &R! I  fU~T|9UvTsQ+U|K4((len('(2 ) |i+)U|UvUvT}K src i    K ݁9 src'ij   t cde  5cdK  src'len0ij W t K'l src(len1ipKlf lsrcl' m n o p K 5 .`e in`cb6d K[;O len[KYO lenYK'8{ dst8buf8%len87i9ch:.K. dst.hex.$i/j/K"M MM#"9 999" J7K&0:EP8R=!!9(&0:E(P '   U}K:###I~H}4:!; 9 IB:!; 9 IB&II1B!I/ : ; 9 I  !I 4:!; 9 IB $ >  I:!; 9!I414: ; 9 IH}.?:!; 9!'I@z:!;9 IB4:!;9 IB4:!;9 I4:!;9 IB41B7I.?:!;9 'I@z:!;9 IB1RB UX!YW H}:!; 9 IB U.?:!;9! '< 4:!;9 I!1".?:!; 9!'I !4#.?<n:! ;!$ :!; 9!I8 %:!;!9 I&4:!;9!I'.?:!; 9!'@z(41)% *$ > + ,!I/-&. : ; 9 / : ; 9 I8 0 : ; 9 I81.?: ; 9 'I<2.?: ;9 'I<3.?: ;9 'I 4.?: ;9 '@z54: ; 9 I64: ; 9 I7.1@z81UX YW 9 U:.?<nc UUTSTSTQ]Q]PP\\SS v $ &SU]UUU^UTTTVTTQSQSQQS0__0p}# p}# 0Tt1$T^P^VTT\U^USUT\TQ]Q]0sUUU0Q00T0UU UYUYU TTTT 0Rr}RR 0VXxX 0Z1Z1 TTTTtp""8$8&#r $ &t""8$8&#r $ &t""8$8&s"8$8&#r $ &t""8$8&P#r $ &t""8$8&$r $ &T""8$8&$r $ &T""8$8& U Z U Z U U T  T  Q S Q S s S Q 0 u 0 0 R r T R x q q Q 0 ^ P ^ Q P T s"8$8&UR UT U T U TQY y Q0Qq}QURr|R r r~ R r r R rUZUTQTQTTUQq|QQZTtt~TpppPppPZpPTuTTQTQTUU0XUu}UUu~p~UUXUTTQQ0PRUtp",U,^Z^vUvUUTT/0/CXCRxR^Xv0/0/<Q/X< / KK/;KW<YWK J]Y .<3ftCf",<17<<<]<<JtKzf <, <,oJ t< Jg <> <F,J w:G,J:J5<<YH,J[YF,X:J,J:J5<<KYH,X>$= yJ rJ=  J .X6 6FY6 @.:=:=";7K";<<u$7J$JG<$JG<*J>=G>>/;;K;=(;J(JK<(JK<.J<.uJ<pY<uI"<t<g[;%<K;I8<%<8<%<H<+f. .u)f <x=x%J%J< <X5 $5SJ]f<.$.Zs>3J YZ8(K ?.9/<& <K; f<u;<&  F  X<<P >#y %X=%s <Ye=W<& =< 0:Ls; /, f,w< <)t=Y)V'<K=: Z!< @8'<!KK ZrL = ;vJ  <Ku JJfJJgo'    pX<  ?p. <+#f<#<<. .JX y..   <H - e  8 tPkS[vV0,<=t JX:  / t fJX Y @ t<X'g<t xfv<Z  }< 8L} tXz I+1+!XIVI> <:\ ~<<~X  b XP ftj0Y z&2KzXY Jf e?.c&Yz4 s J  [t  X  g'.!.'X.'<!<. L !8 lJ tJ Y0<XT,X}  } JXK1gKI;Y;Y;H LH:trf }fftu./| |<KY hN .V<',.?!hlenstrcmpsize_tchecksumis_base45HASH256_init__uint8_tbufin__chhextablewordslong long intsigned charmnemobitslong intHASH256_processmemcpyhash256uint16_tbytes__uint32_tmnemonic_wordlistunsigned intalpha_U64long unsigned intwordlistmnemonic_from_datadatashort unsigned intGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionstrlen__srcstrcpy__builtin_memcpymlendecodedsha256_rawhexesb45decodebufout__destU64encodeis_url64dest__memcpy_chkdest_lenerrorb45encodeint32_tunsigned charmnemonic_check_and_bits__builtin_strcpymnemonic_bits_lenshort int__builtin___memcpy_chkmnemonic_to_bits__stack_chk_failuint32_tlengthcharU64decode__uint16_tnprbytesalpha_b45HASH256_hash__int32_tB64decoded_lenwordhashbuf2hexasciitablemnemonicmemset_bufuint8_thex2bufb45table__lenresultB64encoded_lencurrent_word/home/alby/dev/Zenroom/meson../src/encoding.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/includemilagro-crypto-c/include/usr/include../src/encoding.cencoding.cstring_fortified.htypes.hstdint-intn.hstdint-uintn.hstddef.hamcl.hbip39_english.hstring.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx H m K 8{H m A TOH A A p;H m A eH W A fET ) AE lH B F HFBB B(A0A8K`" 8D0A(B BBBH 849FEA A(D@ (D ABBJ pH  F 8FED A(Jo (A ABBA H8FBB B(A0A8Dw 8A0A(B BBBE HFBB B(A0A8D 8A0A(B BBBD @`*FFE A(A0G`_ 0D(A BBBD 9H k A  &@A0.:e@   CHPa{iOx`;efl9P 8 % 6= *U\ 9encoding.chextablehexesasciitablealpha_U64alpha_b45b45table.LC0hex2buf__stack_chk_failbuf2hexB64encoded_lenB64decoded_lenis_url64U64decodeU64encodeb45encodeb45decodeis_base45sha256_rawHASH256_initHASH256_processHASH256_hashmnemonic_from_data__memcpy_chkstrcpystrlenmnemonic_to_bitsstrcmpmnemonic_check_and_bitsmemcpymnemonic_wordlist(  [ ! r <X <X K  & ! " #A    %L &T '    )n  (F +W          ( !0 (8 /@ 8H ?P EX L` Uh ]p dx l q z                   ( 0 8 @ H P X !` %h -p 3x 9 ? G M S W ] c j p v ~           ( 0 8 @ H P X ` h p x   ! % + 3 : @ H N S Z _ e k o u {     ( 0 8 @ H P X ` h p x          ! ' . 3 : ? F N V \ b h  m( u0 {8 @ H P X ` h p x                  $ ) 0 6  =( D0 L8 R@ WH ]P eX j` qh xp x                       ( 0 8 @ H #P (X -` 3h 8p >x E L S X _ f j n v |             ( 0 8 @ H P X ` h p x    % , 3 : A G K T Y ` f k s y      ( 0 8 @ H P X ` h p x             " ) 0 7 ;  C  I  R  Y  `(  f0  n8  s@  {H  P  X  `  h  p  x                                      $  +  2  :(  B0  H8  N@  TH  ]P  dX  l`  qh  wp  }x                                             (  0   8   @   H  " P  ) X  . `  3 h  ; p  A x  H  P  U  ]  c  j  r  z                  (  0  8  @  H  P   X  `   h   p   x  %  ,  2  7  =  C  J  P  V  \  c  i  n  v  |           (  0  8  @  H  P  X  `  h  p  x             #  )  -  4  9  ?  F  M  R  [  `  d  i  p  w ( ~ 0 8 @ H P X ` h p x                  "  +  2  9  >  F  N  U  \ ( d 0 k 8 r @ z H  P X ` h p x                   !  (  0  6  =  F ( J 0 O 8 W @ ^ H e P l X r ` w h | p x                      ( 0 8 @ H P %X *` 0h 7p <x A F N V [ ` h o s y             ( 0 8 @ H P X ` h p x  # * 2 9 @ H N U \ c j q w ~        ( 0 8 @ H P X ` h p x        ) 0 8 ? G P X ` f l q x    ( 0 8 @ H P X ` h p x              # ) 0 8 > G O X  `( d0 i8 n@ uH {P X ` h p x                       ( 0 '8 ,@ 3H 8P >X D` Jh Qp Wx ] a f l p u z                ( 0 8 @ H P X ` h p x ! & * 0 8 = D K P W _ d h o w ~       ( 0 8 @ H P X ` h p x          " ( 0 6 < B H M R W _ d  i( o0 w8 ~@ H P X ` h p x                     #  (( /0 78 <@ BH IP NX T` \h `p ex j q v }                   ( 0 8 @ H P X ` h p "x ( 1 6 < A G K P V ] c k r w ~        ( 0 8 @ H P X ` h p x        ' - 6 = F M U \ c k s z    ( 0 8 @ H P X ` h p x           ! ( , 1 9 ? E K O T Y  a( e0 k8 q@ vH }P X ` h p x                       ( 0 #8 (@ 1H 8P >X D` Jh Pp Xx ] a f n t y                     (  0  8  @  H  P  X  `  h  p  x  !  '  ,  1  8  =  D  I  P  U  Z  b  h  m  s  z  ! ! ! !  ! (! 0! 8! @! H! P! X! `! h! p! x! ! ! ! ! ! ! ! ! ! ! ! %! -! 4! :! A! G" N" U" \" e " j(" o0" v8" |@" H" P" X" `" h" p" x" " " " " " " " " " " " " " " " " # # %# ,# 3 # <(# A0# I8# O@# TH# \P# bX# i`# qh# xp# x# # # # # # # # # # # # # # # # # $ $ $ $  $ ($ 0$ 8$ #@$ )H$ .P$ 5X$ :`$ Ch$ Jp$ Qx$ Z$ `$ e$ l$ s$ {$ $ $ $ $ $ $ $ $ $ $ % % % %  % (% 0% 8% @% H% P% X% `% h% p% x% "% *% 1% 8% >% C% K% P% X% _% e% i% q% x% ~% % & & & &  & (& 0& 8& @& H& P& X& `& h& p& x& & & & & & & & & & & #& (& .& 6& =& D& K' Q' Y' _' h ' n(' u0' ~8' @' H' P' X' `' h' p' x' ' ' ' ' ' ' ' ' ' ' ' ' '  ' '  '  (  ( & ( - ( 2 ( 9 (( ? 0( D 8( J @( O H( W P( ^ X( f `( l h( q p( y x(  ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ) ) ) ) ! ) !() !0) !8) !@) #!H) (!P) 0!X) 5!`) #+ E#+ M#+ U#+ ]#+ e#+ n#+ t#+ y#, ~#, #, #, # , #(, #0, #8, #@, #H, #P, #X, #`, #h, #p, #x, #, #, #, #, #, #, #, #, $, $, $, $, $, %$, -$, 4$, ;$- C$- J$- R$- Y$ - `$(- g$0- n$8- v$@- }$H- $P- $X- $`- $h- $p- $x- $- $- $- $- $- $- $- $- $- $- $- $- %- %- %- %- #%. *%. 2%. 9%. A% . H%(. O%0. V%8. ]%@. a%H. h%P. m%X. r%`. w%h. }%p. %x. %. %. %. %. %. %. %. %. %. %. %. %. %. %. %. %. %/ %/ %/ %/ & / &(/ &0/ &8/ &@/ &H/ $&P/ )&X/ -&`/ 4&h/ :&p/ >&x/ E&/ M&/ R&/ W&/ ]&/ d&/ j&/ o&/ v&/ {&/ &/ &/ &/ &/ &/ &/ &0 &0 &0 &0 & 0 &(0 &00 &80 &@0 &H0 &P0 &X0 &`0 'h0 'p0 'x0 '0 '0 '0 ''0 ,'0 3'0 :'0 B'0 K'0 P'0 U'0 ]'0 d'0 i'0 q'0 x'0 ~'1 '1 '1 '1 ' 1 '(1 '01 '81 '@1 'H1 'P1 'X1 '`1 'h1 'p1 'x1 '1 '1 '1 '1 (1 (1 (1 (1 (1 #(1 )(1 0(1 6(1 >(1 B(1 J(1 O(2 T(2 Z(2 `(2 e( 2 l((2 q(02 w(82 ~(@2 (H2 (P2 (X2 (`2 (h2 (p2 (x2 (2 (2 (2 (2 (2 (2 (2 (2 (2 (2 (2 (2 (2 (2 )2 )2 )3 )3 )3 )3 %) 3 +)(3 1)03 7)83 =)@3 D)H3 J)P3 P)X3 U)`3 [)h3 `)p3 e)x3 l)3 s)3 x)3 })3 )3 )3 )3 )3 )3 )3 )3 )3 )3 )3 )3 )3 )4 )4 )4 )4 ) 4 )(4 )04 )84 )@4 *H4 *P4 *X4 *`4 *h4 &*p4 -*x4 3*4 8*4 ?*4 E*4 K*4 S*4 Y*4 _*4 d*4 j*4 q*4 x*4 |*4 *4 *4 *4 *5 *5 *5 *5 * 5 *(5 *05 *85 *@5 *H5 *P5 *X5 *`5 *h5 *p5 *x5 *5 +5 +5 +5 +5 +5 "+5 (+5 1+5 8+5 ?+5 F+5 O+5 W+5 ]+5 e+5 k+6 s+6 z+6 +6 + 6 +(6 +06 +86 +@6 +H6 +P6 +X6 +`6 +h6 +p6 +x6 +6 +6 +6 +6 +6 +6 ,6 ,6 ,6 ,6 ,6 &,6 +,6 1,6 7,6 =,6 C,7 H,7 N,7 U,7 [, 7 b,(7 j,07 p,87 w,@7 },H7 ,P7 ,X7 ,`7 ,h7 ,p7 ,x7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,7 ,8 -8 -8 -8 - 8 -(8 -08 %-88 *-@8 2-H8 8-P8 ?-X8 E-`8 K-h8 S-p8 Z-x8 _-8 e-8 j-8 q-8 v-8 {-8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -8 -9 -9 -9 -9 - 9 -(9 -09 -89 -@9 -H9 .P9 .X9 .`9 .h9 .p9 $.x9 *.9 2.9 9.9 ?.9 D.9 H.9 N.9 T.9 \.9 c.9 i.9 r.9 w.9 }.9 .9 .9 .: .: .: .: . : .(: .0: .8: .@: .H: .P: .X: .`: .h: .p: .x: .: .: .: /: /: /: /: /: "/: )/: 0/: 7/: =/: B/: H/: L/: Q/; Y/; ^/; g/; n/ ; v/(; |/0; /8; /@; /H; /P; /X; /`; /h; /p; /x; /; /; /; /; /; /; /; /; /; 0; 0; 0; 0; 0; 0; "0; '0< .0< 60< <0< D0 < K0(< R00< X08< ^0@< e0H< k0P< o0X< v0`< |0h< 0p< 0x< 0< 0< 0< 0< 0< 0< 0< 0< 0< 0< 0< 0< 0< 0< 0< 0< 1= 1= 1= 1= 1 = $1(= *10= /18= 51@= <1H= B1P= H1X= N1`= T1h= Y1p= a1x= h1= m1= t1= y1= 1= 1= 1= 1= 1= 1= 1= 1= 1= 1= 1= 1= 1> 1> 1> 1> 1 > 1(> 10> 18> 1@> 1H> 2P> 2X> 2`> 2h> 2p> !2x> &2> ,2> 22> 72> =2> B2> J2> O2> U2> Z2> _2> d2> h2> o2> t2> y2> ~2? 2? 2? 2? 2 ? 2(? 20? 28? 2@? 2H? 2P? 2X? 2`? 2h? 2p? 2x? 2? 2? 2? 2? 2? 2? 3? 3? 3? 3? 3? 3? "3? (3? .3? 33? 83  -  * 1 = D K R eW 3e j 0v [  | ! }     ) 6 A W[ z   H  ! 0 = [ h @ D      N * &; F ] p {      , "  ^ V w   ~ Q     ? ' 7 ; D H Q U ZJ { [     w Q m xP  q    2 & o c w          " 0 -4 '= F `[ I_ Ch dl bq H  k q o } yP  X , : BY d h x |     y    E  A E  S (W "\ mg Fk @p { b ^ ' R ~ t       m ? 5  n f% ,6 : G K X \ a k \o Zu K j d  s  R   - % \ N   # ( d2 '6 !;  D tN AR =X a tk To Pu  ?  R x r       -   & ( R2 6 E I N =X \ a 1k 1 o  t ;~      v I      =  e `9 - = ' B P Y z P ~ H _ ~  z t             A  E  T $ X  e ? i 5 v h z ^    8   8 C   8   )  -  6  :  k v v     N  F  |  p          $   I   D  B  P  N  ] " [ ( >r L P U Y ^ Wb g k     G     " /& L* S. v2 6 @ E J O T Y  ^ c #h *m :r C|;d <Xt`8tP  d  .symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.rela.data.rel.ro.local.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @ @&),)12)<3@A M@H@ H@eHp`@؇h qSg @@ 0@0 @0@020N0h& @php8 nث/104 0 0 0 644 18632 ` ELF>HB@@AUATIUHSHdH%(HD$1txH1HLLHHHLcHH;.ut.LHHtOILHM)LHVHtHLfLIf1HT$dH+%(uH[]A\A]bATIUHHdH%(HD$1LHHD$dH+%(u H1]A\ATUHHdH%(HD$1Ht]:IHt2LH1HT$dH+%(uCH]A\1LH5H5ATIUHdH%(HD$1HHu2HHt*1HD$dH+%(u+HLH]A\HD$dH+%(uH]A\AU>I1ATIUHLSHdH%(H$Hzenroom.IH|$HT$H$1HLHIHLH8HH5H8HH8HH8H1LH8HذHH8xHLH8upHH8HH8HH8H1HH8H$dH+%(H[]A\A]ÐHH8HذH8H1LH8HtHLH5H81HH8HLH8setenv: NULL string detected__index_LOADEDname conflict for module '%s'setenv: empty value for key: %s  intrhr<<ffC7\Xh Xy: !":;W\ Xqh<} Xh= Xh~> Xh C !luaDfEfFfHhI J (K 0Mh8N @O HP PRfXS`TXVXWXXfZ K[ q\ ]r%"C?_#Z B%XbX ~XXXX$hX XX"XDX>X^X uXXX cXFX X>X X5 #Mfc uV?VhW#W;%X?{& YD ' U{T|Q R  pT T T T}Q0 T}Q 1u T Q|(T Q ^@T ]T Q1zTvQ0^T >T}Q2 T0Q|1"T Q|T 1T Q| rP(C)=L2idx9X>0>;X*e?4}; L4"5%6# UvTTQ0+M- UUTQ (X! L( key($h val(/h UvTQM UvT|5 T Q|5 T  "XP L" key"#hc} UvM UvT| ,h m -P? a i s./^R UvT bt UvT0Q1 UvT|Q} UvT  UvT  UvT Q ^ UvT 4 U|T.X UvT|Q}~v UvT G UvT ^ UvT  U|  01I~IH} : ; 9 I8  !I$ > : ; 9 I.?: ; 9 'I< .?: ; 9 '< H} 1B :!; 9 IB 'I:!; 9 IB: ; 9 I :!;!I8 .?:!;9!'<7I&II.?:!; 9!'@zI~:!;!=9 I.?:!; 9!'I@z% $ >   : ; < : ; 9   : ; 9 ! : ; 9 I8 "!I/ #4: ; 9 I?<$.?: ;9 'I<%4: ; 9 I&1RB UX Y W 'H}(!I/).: ; 9 'I *4: ; 9 I+H},.?: ; 9 'I 4-.1@z.41B/1 0.?<n: ; 1.?<n4UT\U \TVT VQ]Q ] T\{UVUUUUTTTTQ\TQ\Q\UVUUVUVT\T\TTQQQTQQQUVUVT\T\)U)VUUV)T)TTT)Q)\\Q\)SPSPSS,"f   < IKoXY(<(f<  Y utJ J/J . lfXX(NfYf. 4Z[1Y /JXtY tY {. ffuIg -gf DgDW=D- 0<DP /Q< /QX+ S -t<S<<<<<<=< X%K<..p.M<Y<=<<Rdebuglevelsize_tlua_rotategp_offsetluaL_error__builtin___strncat_chkstrncat__src__strncat_chklong long intsigned charlua_pushvaluelong intzen_lua_findtablezen_add_functionlua_CFunctionstderr_buflua_pushstringzenroom_tlua_pushlstringunsigned intstdout_posstrlenrandom_generatoroverflow_arg_arealong unsigned intstderr_lenclassmetavsprintf_tlua_createtablestrchrnameshort unsigned intzen_add_classGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionstderr_fullrandom_externalsprintfvsnprintf_tfnamelua_setfielduserdatalua_getfieldmethodsluaL_newmetatableluaL_Reg__destlua_typelua_Statezstd_czstd_dlua_setglobalfloatvsnprintflua_pushnilstdout_bufsprintf_tunsigned charshort int__lenlua_settablereg_save_area__stack_chk_failzen_unsetstdout_lenfunc_namecharfuncrandom_seedstdout_fulllua_settopvsprintfsnprintferrorlevellua_rawgetlua_Integer_classsnprintf_tfp_offsetzen_setenvlua_pushcclosureluaL_setfuncsszhintstderr_poslua_rawgeti__va_list_tag/home/alby/dev/Zenroom/meson../src/lua_functions.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include../lib/lua53/src/usr/include../src/lua_functions.clua_functions.cstring_fortified.hstddef.hlua.hlauxlib.hzenroom.hstring.hzen_error.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx 8?BBD D(D@ (A ABBD (XPFDG0t CBA (FAG0F ABI 4}FDD0C GBF T ABA @FLD G(G4 (A ABBB ?   /49>%C-HScs@P 0} 1?Mcewlua_functions.czen_lua_findtable.constprop.0.LC1.LC0.LC2.LC3.LC4lua_settoplua_createtablelua_pushlstringlua_pushvaluelua_settablelua_rotatestrchrlua_rawgetlua_typestrlen__stack_chk_failzen_unsetlua_pushnillua_setglobalzen_setenvlua_pushstringfunczen_add_functionlua_pushcclosurezen_add_class__strncat_chk_GLOBAL_OFFSET_TABLE_ZluaL_newmetatableluaL_setfuncslua_getfieldlua_rawgetiluaL_errorlua_setfield9HVcp1;bm! ""$i$&*(+)5=!M]m*|+*1,S]-m.    * 1 G8 ? F >M tT Ub u  u  # , r        - ; L =r  e   + 28 E R _ l Py ^ d   p       & 4 fH c p      # '? i_ v  I e   8 6 N d &v {      E =  m e [         E/RAgqQaq% )A^{ 5Ea-q2Q t  W 0       0 "m . < -E d vh hw {          (" + @J 9N 1] aa Yf f~ q  J  R _       & * 5 =S Lu Z g t   5 Y w    5 ? X 2   " 4& Q* X. {2 6 @ E J O T Y ^ c h *m 3w \@0.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.str1.8.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@(&,12K@2  T@ O@(-`:n8L0~@>0 |&@(?0;0?0 &#!(! H!(@@xp"h &8A /130 0 0 0 644 384088 ` ELF>@@zenroom_zpackinspectzencode_debugzencode_datazencode_qpzencode_petitioncrypto_petitionstatemachinezencodezencode_givencrypto_lagrange_interpolationzenroom_octetzencode_secsharezenroom_commoncrypto_bitcoinzencode_dictionaryzencode_hashinitzencode_credentialmsgpackcrypto_schnorr_signaturejsontimetablecborzencode_schnorrzenroom_benchzencode_whenzencode_verifyzenroom_jsonzenroom_cborzencode_arrayzenroom_ecdhstatszencode_randomhdwalletcrypto_elgamalzenroom_hashzenroom_ecpzencode_httpcrypto_credentialzencode_thenzenroom_ecp2zencode_bitcoincrypto_ethereumzencode_reflowsemverzencode_dp3tzenroom_bigzencode_ethereumzencode_keyringzencode_ecdhzenroom_msgpackzencode_w3c--[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Wednesday, 14th July 2021 --]] ZEN.add_schema( { -- flexible verifiable credential -- only internal 'jws' member has peculiar encoding verifiable_credential = function(obj) ZEN.CODEC.verifiable_credential = { name = 'verifiable_credential', encoding = 'string', zentype = 'schema', luatype = 'table' } return (deepmap(OCTET.from_string, obj)) end } ) -- return { r , s } table suitable for signature verification local function jws_octet_to_signature(obj) local toks = strtok(OCTET.to_string(obj), '[^.]*') -- header parsing may be skipped -- local header = JSON.decode( OCTET.from_url64(toks[1]):to_string() ) local res = {} res.r, res.s = OCTET.chop(OCTET.from_url64(toks[3]), 32) return (res) end -- return octet string suitable for JWS encapsulation local function jws_signature_to_octet(obj, algo) local header = OCTET.from_string( JSON.encode( { alg = algo or 'ES256K', -- default secp256k1 b64 = true, crit = 'b64' } ) ) return (OCTET.to_url64(header) .. '..' .. OCTET.to_url64(obj.r .. obj.s)) end When( "set the verification method in '' to ''", function(vc, meth) local cred = have(vc) ZEN.assert(cred.proof, 'The object is not signed: ' .. vc) local m = have(meth) ACK[vc].proof.verificationMethod = m end ) When( "get the verification method in ''", function(vc) empty 'verification_method' local cred = have(vc) ZEN.assert(cred.proof, 'The object is not signed: ' .. vc) ACK.verification_method = cred.proof.verificationMethod end ) When( "sign the verifiable credential named ''", function(vc) local cred = have(vc) local sk = havekey'ecdh' -- assuming secp256k1 ZEN.assert(not cred.proof,'The object is already signed: ' .. vc) local proof = { type = 'Zenroom v'..ZENROOM_VERSION.original, -- "Signature", -- TODO: check what to write here for secp256k1 -- created = "2018-06-18T21:19:10Z", proofPurpose = 'authenticate' -- assertionMethod", -- TODO: check } local cred_str = JSON.encode(cred) proof.jws = jws_signature_to_octet( ECDH.sign(sk, OCTET.from_string(cred_str)) ) ACK[vc].proof = deepmap(OCTET.from_string, proof) end ) IfWhen( "verify the verifiable credential named ''", function(vc) local cred = have(vc) local public_key = have 'ecdh public key' ZEN.assert(cred.proof, 'The object has no signature: ' .. vc) ZEN.assert( cred.proof.jws, 'The object has no signature: ' .. vc ) local sign = jws_octet_to_signature(cred.proof.jws) -- omit the proof subtable from verification local proof = cred.proof cred.proof = nil local cred_str = JSON.encode(cred) -- restore proof in HEAP (cred is still a pointer here) cred.proof = proof -- if public_key is a table then use the first value: support 'from' -- extraction, but not multiple keys local pub if luatype(public_key) == 'table' then _, pub = next(public_key) else pub = public_key end ZEN.assert( ECDH.verify(pub, OCTET.from_string(cred_str), sign), 'The signature does not validate: ' .. vc ) end ) --[[ --This file is part of zenroom -- --Copyright (C) 2022 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt --]] -- required by zenroom_zpack local mpack = require_once'msgpack' local pack, unpack = string.pack, string.unpack local to_octenv = OCTET.to_url64 local from_octenv = OCTET.from_url64 -- userdata codes available -- 0xc{7,8,9} mpack.encoder_functions['zenroom.octet'] = function(v) return pack('>Bs4', 0xc7, to_octenv(v)) end mpack.encoder_functions['zenroom.big'] = function(v) return pack('>Bs4', 0xc8, to_octenv(v:octet())) end -- reserved for zenroom 3.0 -- mpack.encoder_functions['zenroom.float'] = function(v) -- return pack('>Bs4', 0xc9, to_octenv(v:octet())) end -- 0xd{4,5,6,7,8} mpack.encoder_functions['zenroom.ecp'] = function(v) return pack('>Bs4', 0xd4, to_octenv(v:octet())) end mpack.encoder_functions['zenroom.ecp2'] = function(v) return pack('>Bs4', 0xd5, to_octenv(v:octet())) end local function decode_octet(data, offset) local value, pos = string.unpack('>s4', data, offset) return from_octenv(value), pos end local function decode_big(data, offset) local value, pos = string.unpack('>s4', data, offset) return BIG.new(from_octenv(value)), pos end local function decode_ecp(data, offset) local value, pos = string.unpack('>s4', data, offset) return ECP.new(from_octenv(value)), pos end local function decode_ecp2(data, offset) local value, pos = string.unpack('>s4', data, offset) return ECP2.new(from_octenv(value)), pos end mpack.decoder_functions[0xc7] = decode_octet mpack.decoder_functions[0xc8] = decode_big mpack.decoder_functions[0xd4] = decode_ecp mpack.decoder_functions[0xd5] = decode_ecp2 return mpack --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 9th April 2022 --]] -- defined outside because reused across different schemas local function public_key_f(o) local res = CONF.input.encoding.fun(o) ZEN.assert( ECDH.pubcheck(res), 'Public key is not a valid point on curve' ) return res end local function signature_f(o) return { r = ZEN.get(o, 'r'), s = ZEN.get(o, 's') } end local function warn_keypair() warn("Use of 'keypair' is deprecated in favor of 'keyring'") warn("Examples: I have my 'keyring' or I create the keyring") end ZEN.add_schema( { -- keypair (ECDH) public_key = public_key_f, ecdh_public_key = public_key_f, secret_message = function(obj) return { checksum = ZEN.get(obj, 'checksum'), header = ZEN.get(obj, 'header'), iv = ZEN.get(obj, 'iv'), text = ZEN.get(obj, 'text') } end, signature = signature_f, ecdh_signature = signature_f } ) When( "create the ecdh key", function() initkeyring'ecdh' ACK.keyring.ecdh = ECDH.keygen().private end ) When( "create the ecdh public key", function() empty'ecdh public key' local sk = havekey'ecdh' ACK.ecdh_public_key = ECDH.pubgen(sk) end ) When("create the ecdh key with secret key ''",function(sec) local sk = have(sec) initkeyring'ecdh' ECDH.pubgen(sk) ACK.keyring.ecdh = sk end) When("create the ecdh key with secret ''",function(sec) local sk = have(sec) initkeyring'ecdh' ECDH.pubgen(sk) ACK.keyring.ecdh = sk end) -- encrypt with a header and secret When( "encrypt the secret message '' with ''", function(msg, sec) local text = have(msg) local sk = have(sec) empty'secret message' -- KDF2 sha256 on all secrets local secret = KDF(sk) ACK.secret_message = { header = ACK.header or OCTET.from_string('DefaultHeader'), iv = O.random(32) } ACK.secret_message.text, ACK.secret_message.checksum = ECDH.aead_encrypt( secret, text, ACK.secret_message.iv, ACK.secret_message.header ) new_codec('secret message', { zentype = 'dictionary' }) end ) -- decrypt with a secret When( "decrypt the text of '' with ''", function(msg, sec) local sk = have(sec) local text = have(msg) empty'text' empty'checksum' local secret = KDF(sk) -- KDF2 sha256 on all secrets, this way the -- secret is always 256 bits, safe for direct aead_decrypt ACK.text, ACK.checksum = ECDH.aead_decrypt( secret, text.text, text.iv, text.header ) ZEN.assert( ACK.checksum == text.checksum, 'Decryption error: authentication failure, checksum mismatch' ) end ) -- check various locations to find the public key local function _pubkey_compat(_key) local pubkey = ACK[_key] if not pubkey then local pubkey_arr pubkey_arr = ACK.public_key or ACK.public_key_session or ACK.ecdh_public_key if luatype(pubkey_arr) == 'table' then pubkey = pubkey_arr[_key] else pubkey = pubkey_arr end ZEN.assert(pubkey, 'Public key not found for: ' .. _key) end return pubkey end -- encrypt to a single public key When( "encrypt the secret message of '' for ''", function(msg, _key) local sk = havekey'ecdh' have(msg) local pk = _pubkey_compat(_key) empty'secret message' local key = ECDH.session(sk, pk) ACK.secret_message = { header = ACK.header or OCTET.from_string('DefaultHeader'), iv = O.random(32) } ACK.secret_message.text, ACK.secret_message.checksum = ECDH.aead_encrypt( key, ACK[msg], ACK.secret_message.iv, ACK.secret_message.header ) new_codec('secret message', { zentype = 'dictionary' }) end ) When( "decrypt the text of '' from ''", function(secret, _key) local sk = havekey'ecdh' have(secret) local pk = _pubkey_compat(_key) local message = ACK[secret][_key] or ACK[secret] local session = ECDH.session(sk, pk) local checksum ACK.text, checksum = ECDH.aead_decrypt(session, message.text, message.iv, message.header) ZEN.assert( checksum == message.checksum, 'Failed verification of integrity for secret message' ) end ) -- sign a message and verify local function _signing(msg, var) local sk = havekey'ecdh' empty(var) local obj = have(msg) ACK[var] = ECDH.sign(sk, ZEN.serialize(obj)) ZEN.CODEC.signature = CONF.output.encoding.name end local function _verifying(msg, sig, by) local pk = _pubkey_compat(by) local obj = have(msg) local s = have(sig) ZEN.assert( ECDH.verify(pk, ZEN.serialize(obj), s), 'The signature by ' .. by .. ' is not authentic' ) end When( "create the signature of ''", function(msg) _signing(msg, 'signature') end) When( "create the ecdh signature of ''", function(msg) _signing(msg, 'ecdh_signature') end) IfWhen( "verify the '' has a signature in '' by ''", _verifying ) IfWhen( "verify the '' has a ecdh signature in '' by ''", _verifying ) --[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Friday, 12th November 2021 --]] -- DESCRIPTION: Special keys schema has optional members common to -- multiple scenarios, it provides a common interface to create keys, -- verifiers and check their existance. It does not use the keys, that's -- up to the specific scenarios. One single scenario may require and use -- the same key types (one or more) as others do, for instance reflow -- uses bls and credential, petition uses credential and ecdh. function initkeyring(ktype) if luatype(ACK.keyring) == 'table' then -- TODO: check that curve types match elseif ACK.keyring == nil then -- initialise empty ACK.keyring ACK.keyring = {} -- TODO: save curve types new_codec('keyring', { zentype = 'schema', luatype = 'table', encoding = 'complex' }) else error('Keyring table is corrupted', 2) end -- if ktype is specified then check overwriting if ktype then ZEN.assert( not ACK.keyring[uscore(ktype)], 'Cannot overwrite existing key: ' .. ktype ) end end When("create the keyring", function() empty'keyring' initkeyring() end) -- KNOWN KEY TYPES FOUND IN ACK.keyring local keytypes = { ecdh = true, credential = true, issuer = true, bls = true, reflow = true, bitcoin = true, testnet = true, ethereum = true, dilithium = true, schnorr = true, kyber = true, ntrup = true } function havekey(ktype) local kname = uscore(ktype) ZEN.assert(keytypes[kname], 'Unknown key type: ' .. ktype) -- check that keys exist and are a table initkeyring() local res = ACK.keyring[kname] ZEN.assert(res, 'Key not found: ' .. ktype) return res end local function nop(x) return(x) end -- the length of the kyber, dilithium and ntrup keys can be found in Zenroom/src/zen_qp.c local function dilithium_f(o) ZEN.assert(#o == 2528, 'Dilithium key length` is not correct') return o end local function kyber_f(o) ZEN.assert(#o == 1632, 'Kyber key length is not correct') return o end local function ntrup_f(o) ZEN.assert(#o == 1763, 'Ntrup key length is not correct') return o end local function _keyring_import(obj) -- ecdh_curve -- bls_curve local res = {} if obj.ecdh then res.ecdh = ZEN.get(obj, 'ecdh') end if obj.credential then res.credential = ZEN.get(obj, 'credential', INT.new) end if obj.issuer then res.issuer = { x = ZEN.get(obj.issuer, 'x', INT.new), y = ZEN.get(obj.issuer, 'y', INT.new) } end if obj.bls then res.bls = ZEN.get(obj, 'bls', INT.new) end if obj.reflow then res.reflow = ZEN.get(obj, 'reflow', INT.new) end if obj.bitcoin then res.bitcoin = ZEN.get(obj, 'bitcoin', BTC.wif_to_sk, O.from_base58) end if obj.testnet then res.testnet = ZEN.get(obj, 'testnet', BTC.wif_to_sk, O.from_base58) end if obj.ethereum then res.ethereum = ZEN.get(obj, 'ethereum', nop, O.from_hex) end if obj.dilithium then res.dilithium = ZEN.get(obj, 'dilithium', dilithium_f) end if obj.kyber then res.kyber = ZEN.get(obj, 'kyber', kyber_f) end if obj.schnorr then res.schnorr = ZEN.get(obj, 'schnorr') end if obj.ntrup then res.ntrup = ZEN.get(obj, 'ntrup', ntrup_f) end return (res) end local function _default_export(obj) local fun = guess_outcast(CONF.output.encoding.name) return fun(obj) end local function _keyring_export(obj) -- ecdh_curve -- bls_curve local res = {} if obj.ecdh then res.ecdh = _default_export(obj.ecdh) end if obj.credential then res.credential = _default_export(obj.credential) end if obj.issuer then local fun = guess_outcast(CONF.output.encoding.name) res.issuer = deepmap(fun, obj.issuer) end if obj.bls then res.bls = _default_export(obj.bls) end if obj.reflow then res.reflow = _default_export(obj.reflow) end if obj.bitcoin then res.bitcoin = O.to_base58( BTC.sk_to_wif(obj.bitcoin, 'bitcoin') ) end if obj.testnet then res.testnet = O.to_base58( BTC.sk_to_wif(obj.testnet, 'testnet') ) end if obj.ethereum then res.ethereum = O.to_hex(obj.ethereum) end if obj.dilithium then res.dilithium = _default_export(obj.dilithium) end if obj.kyber then res.kyber = _default_export(obj.kyber) end if obj.schnorr then res.schnorr = _default_export(obj.schnorr) end if obj.ntrup then res.ntrup = _default_export(obj.ntrup) end return (res) end ZEN.add_schema( { keyring = { import = _keyring_import, export = _keyring_export } } ) --[[ --This file is part of zenroom -- --Copyright (C) 2022 Dyne.org foundation --designed, written and maintained by Alberto Lerda and Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Sunday, 10th April 2022 --]] ETH = require_once'crypto_ethereum' local function big_wei_to_str_wei(x) return x:decimal() end local function str_wei_to_big_wei(x) return BIG.from_decimal(tostring(x)) end -- TODO: these conversions are slow weimult = BIG.new(10):modpower(BIG.new(18), ECP.order()) gweimult = BIG.new(10):modpower(BIG.new(9), ECP.order()) local function str_gwei_to_big_wei(x) return ( BIG.from_decimal(tostring(x)) * gweimult ) end local function big_wei_to_str_gwei(x) return ( x / gweimult ):decimal() end local function str_eth_to_big_wei(x) return ( BIG.from_decimal(tostring(x)) * weimult ) end local function big_wei_to_str_eth(x) return ( ( x / weimult ):decimal() ) end local function import_eth_tx(obj) local res = { } res.nonce = ZEN.get(obj, 'nonce', INT.from_decimal, tostring) res.gas_price = ZEN.get(obj, 'gas_price', INT.from_decimal, tostring) res.gas_limit = ZEN.get(obj, 'gas_limit', INT.from_decimal, tostring) res.value = ZEN.get(obj, 'value', INT.from_decimal, tostring) res.to = ZEN.get(obj, 'to', O.from_hex, tostring) if obj.data then res.data = ZEN.get(obj, 'data', O.from_hex, tostring) else res.data = O.new() end if obj.v then res.v = ZEN.get(obj, 'v', O.from_hex) end if obj.r then res.r = ZEN.get(obj, 'r', O.from_hex) end if obj.s then res.s = ZEN.get(obj, 's', O.from_hex) end return res end local function export_eth_tx(obj) local res = { } res.nonce = obj.nonce:decimal() res.gas_price = obj.gas_price:decimal() res.gas_limit = obj.gas_limit:decimal() res.to = obj.to:hex() if #obj.value == 0 then res.value = '0' elseif type(obj.value) == 'zenroom.big' then res.value = obj.value:decimal() else error("invalid value type: "..type(obj.value)) end if obj.data then res.data = obj.data:octet():hex() end if obj.v then res.v = obj.v:octet():hex() end if obj.r then res.r = obj.r:octet():hex() end if obj.s then res.s = obj.s:octet():hex() end return res end ZEN.add_schema( { ethereum_public_key = { import = O.from_hex, export = O.to_hex }, ethereum_address = { import = O.from_hex, export = O.to_hex }, ethereum_nonce = function(obj) return ZEN.get(obj, '.', INT.new, tonumber) end, ethereum_transaction = { import = import_eth_tx, export = export_eth_tx }, signed_ethereum_transaction = { import = O.from_hex, export = O.to_hex }, gas_price = { import = str_wei_to_big_wei, export = big_wei_to_str_wei }, gas_limit = { import = str_wei_to_big_wei, export = big_wei_to_str_wei }, ethereum_value = { import = str_eth_to_big_wei, export = big_wei_to_str_eth }, gwei_value = { import = str_gwei_to_big_wei, export = big_wei_to_str_gwei }, wei_value = { import = str_wei_to_big_wei, export = big_wei_to_str_wei } }) When('create the ethereum key', function() initkeyring'ethereum' ACK.keyring.ethereum = ECDH.keygen().private end) When('create the ethereum address', function() empty'ethereum address' local pk = ACK.ethereum_public_key if not pk then pk = ECDH.pubgen( havekey'ethereum' ) end ACK.ethereum_address = ETH.address_from_public_key(pk) new_codec('ethereum address', { zentype = 'element', encoding = 'hex' }) end) When("create the ethereum transaction of '' to ''", function(quantity, destaddr) empty'ethereum transaction' local tx = { } tx.gas_price = have'gas price' tx.gas_limit = have'gas limit' tx.nonce = have'ethereum nonce' tx.value = have(quantity) tx.to = have(destaddr) tx.data = O.new() ACK.ethereum_transaction = tx new_codec('ethereum transaction', { zentype = 'schema', encoding = 'complex'}) end) When("create the ethereum transaction to ''", function(destaddr) empty'ethereum transaction' local tx = { } tx.gas_price = have'gas price' tx.gas_limit = have'gas limit' tx.nonce = have'ethereum nonce' tx.value = O.new() tx.data = O.new() tx.to = have(destaddr) ACK.ethereum_transaction = tx new_codec('ethereum transaction', { zentype = 'schema', encoding = 'complex'}) end) -- we can store only strings (for the moment) When("use the ethereum transaction to store ''", function(obj) local content = have(obj) local tx = have'ethereum transaction' ZEN.assert(not tx.data or #tx.data == 0, "Cannot overwrite transaction data") tx.data = ETH.make_storage_data(content) end) When("create the string from the ethereum bytes named ''", function(obj) empty'string' local data = have(obj):octet() local eth_decoder = ETH.contract_return_factory({ 'bytes' }) local result = eth_decoder(data) ZEN.assert(#result == 1, "Wrong data format") ACK.string = O.from_str(result[1]) new_codec('string', { encoding = 'string'}) end) -- TODO: more contract methods -- use the ethereum transaction to store '' -- use the ethereum transaction to transfer '' to '' -- use the ethereum transaction to elect '' -- use the ethereum transaction to vote '' When("create the signed ethereum transaction", function() local sk = havekey'ethereum' local tx = have'ethereum transaction' tx.v = INT.new(1337) -- default local testnet ACK.signed_ethereum_transaction = ETH.encodeSignedTransaction(sk, tx) new_codec('signed ethereum transaction', { zentype = 'schema', encoding = 'complex'}) end) When("create the signed ethereum transaction for chain ''", function(chainid) local sk = havekey'ethereum' local tx = have'ethereum transaction' local cid = tonumber(chainid) if not cid then cid = INT.new(O.from_string(tostring(chainid))) else cid = INT.new(cid) end ZEN.assert(cid, "Invalid chain id: "..chainid) if not tx.data then tx.data = O.new() end if not tx.value then tx.value = O.new() end tx.v = cid tx.r = O.new() tx.s = O.new() ACK.signed_ethereum_transaction = ETH.encodeSignedTransaction(sk, tx) new_codec('signed ethereum transaction', { zentype = 'schema', encoding = 'complex'}) end) When("verify the signed ethereum transaction from ''", function(pubkey) local pk = have(pubkey) local rawtx = have'signed ethereum transaction' local tx = ETH.decodeTransaction(rawtx) -- TODO: check decode errors ZEN.assert( ETH.verifySignatureTransaction(pk, tx) ) end) When("create the ethereum key with secret key ''",function(sec) local sk = have(sec) initkeyring'ethereum' ECDH.pubgen(sk) ACK.keyring.ethereum = sk end) When("create the ethereum key with secret ''",function(sec) local sk = have(sec) initkeyring'ethereum' ECDH.pubgen(sk) ACK.keyring.ethereum = sk end)Ilocal big = require'big' -- optimization: we could implement it in C function big.sqrt(num) local two = BIG.new(2) local xn = num local xnn; if xn ~= BIG.new(0) then xnn = (xn + (num / xn)) / two while xnn < xn do xn = xnn xnn = (xn + (num / xn)) / two end end return xn end return big g --[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] -- Decentralized Privacy-Preserving Proximity Tracing scenarion in Zencode SHA256 = HASH.new('sha256') -- ZEN.add_schema({ -- -- secret_day_key = function(obj) -- -- ZEN.assert(#obj == 32, "Secret day key has wrong size (not 32 bytes / 256 bits)") -- -- return obj -- -- end -- -- TODO: -- -- list of infected (array of 32 byte random hashes) -- -- ephemeral ids (array of 16 byte AES-GCM checksums) -- }) When("renew the secret day key to a new day", function() ZEN.assert(ACK.secret_day_key, "Secret day key not found") local sk = SHA256:process(ACK.secret_day_key) ZEN.assert(sk, "Error renewing secret day key (SHA256)") ACK.secret_day_key = sk end) When("create the ephemeral ids for today", function() ZEN.assert(ACK.secret_day_key, "Secret day key not found") ZEN.assert(ACK.broadcast_key, "Broadcast key not found") ZEN.assert(type(ACK.epoch) == 'number', "Epoch length (minutes) not found") local PRF = SHA256:hmac(ACK.secret_day_key, ACK.broadcast_key) local epd = (24*60)/ACK.epoch -- num epochs per day local zero = OCTET.zero(epd*16) -- 0 byte buffer ACK.ephemeral_ids = { } for i = 0,epd,1 do local PRG = AES.ctr(PRF, zero, O.from_number(i)) local l,r = OCTET.chop(PRG,16) table.insert(ACK.ephemeral_ids, l) end end) When("create the proximity tracing of infected ids", function() ZEN.assert(type(ACK.epoch) == 'number', "Number of moments not found") ZEN.assert(type(ACK.list_of_infected) == 'table', "List of infected not found") ZEN.assert(type(ACK.ephemeral_ids) == 'table', "List of ephemeral ids not found") ZEN.assert(ACK.broadcast_key, "Broadcast key not found") ACK.proximity_tracing = { } local epd = (24*60)/ACK.epoch -- num epochs per day local zero = OCTET.zero(epd*16) -- 0 byte buffer for n,sk in ipairs(ACK.list_of_infected) do local PRF = SHA256:hmac(sk, ACK.broadcast_key) for i = 0,epd,1 do local PRG = OCTET.chop( AES.ctr(PRF, zero, O.from_number(i)), 16) for nn,eph in next, ACK.ephemeral_ids, nil do if eph == PRG then table.insert(ACK.proximity_tracing, sk) end end end end end) local semver = { _VERSION = '1.2.2', _DESCRIPTION = 'semver for Lua', _URL = 'https://github.com/kikito/semver.lua' -- _LICENSE = [[ -- MIT LICENSE -- Copyright (c) 2015 Enrique García Cota -- Copyright (c) 2019-2021 Dyne.org foundation -- Permission is hereby granted, free of charge, to any person obtaining a -- copy of tother 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 tother 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. -- ]] } local function checkPositiveInteger(number, name) assert(number >= 0, name .. ' must be a valid positive number') assert(math.floor(number) == number, name .. ' must be an integer') end local function present(value) return value and value ~= '' end -- splitByDot("a.bbc.d") == {"a", "bbc", "d"} local function splitByDot(str) str = str or "" local t, count = {}, 0 str:gsub("([^%.]+)", function(c) count = count + 1 t[count] = c end) return t end local function parsePrereleaseAndBuildWithSign(str) local prereleaseWithSign, buildWithSign = str:match("^(-[^+]+)(+.+)$") if not (prereleaseWithSign and buildWithSign) then prereleaseWithSign = str:match("^(-.+)$") buildWithSign = str:match("^(+.+)$") end assert(prereleaseWithSign or buildWithSign, ("The parameter %q must begin with + or - to denote a prerelease or a build"):format(str)) return prereleaseWithSign, buildWithSign end local function parsePrerelease(prereleaseWithSign) if prereleaseWithSign then local prerelease = prereleaseWithSign:match("^-(%w[%.%w-]*)$") assert(prerelease, ("The prerelease %q is not a slash followed by alphanumerics, dots and slashes"):format(prereleaseWithSign)) return prerelease end end local function parseBuild(buildWithSign) if buildWithSign then local build = buildWithSign:match("^%+(%w[%.%w-]*)$") assert(build, ("The build %q is not a + sign followed by alphanumerics, dots and slashes"):format(buildWithSign)) return build end end local function parsePrereleaseAndBuild(str) if not present(str) then return nil, nil end local prereleaseWithSign, buildWithSign = parsePrereleaseAndBuildWithSign(str) local prerelease = parsePrerelease(prereleaseWithSign) local build = parseBuild(buildWithSign) return prerelease, build end local function parseVersion(str) local sMajor, sMinor, sPatch, sPrereleaseAndBuild = str:match("^(%d+)%.?(%d*)%.?(%d*)(.-)$") assert(type(sMajor) == 'string', ("Could not extract version number(s) from %q"):format(str)) local major, minor, patch = tonumber(sMajor), tonumber(sMinor), tonumber(sPatch) local prerelease, build = parsePrereleaseAndBuild(sPrereleaseAndBuild) return major, minor, patch, prerelease, build end -- return 0 if a == b, -1 if a < b, and 1 if a > b local function compare(a,b) return a == b and 0 or a < b and -1 or 1 end local function compareIds(myId, otherId) if myId == otherId then return 0 elseif not myId then return -1 elseif not otherId then return 1 end local selfNumber, otherNumber = tonumber(myId), tonumber(otherId) if selfNumber and otherNumber then -- numerical comparison return compare(selfNumber, otherNumber) -- numericals are always smaller than alphanums elseif selfNumber then return -1 elseif otherNumber then return 1 else return compare(myId, otherId) -- alphanumerical comparison end end local function smallerIdList(myIds, otherIds) local myLength = #myIds local comparison for i=1, myLength do comparison = compareIds(myIds[i], otherIds[i]) if comparison ~= 0 then return comparison == -1 end -- if comparison == 0, continue loop end return myLength < #otherIds end local function smallerPrerelease(mine, other) if mine == other or not mine then return false elseif not other then return true end return smallerIdList(splitByDot(mine), splitByDot(other)) end local methods = {} function methods:nextMajor() return semver(self.major + 1, 0, 0) end function methods:nextMinor() return semver(self.major, self.minor + 1, 0) end function methods:nextPatch() return semver(self.major, self.minor, self.patch + 1) end local mt = { __index = methods } function mt:__eq(other) return self.major == other.major and self.minor == other.minor and self.patch == other.patch and self.prerelease == other.prerelease -- notice that build is ignored for precedence in semver 2.0.0 end function mt:__lt(other) if self.major ~= other.major then return self.major < other.major end if self.minor ~= other.minor then return self.minor < other.minor end if self.patch ~= other.patch then return self.patch < other.patch end return smallerPrerelease(self.prerelease, other.prerelease) -- notice that build is ignored for precedence in semver 2.0.0 end -- This works like the "pessimisstic operator" in Rubygems. -- if a and b are versions, a ^ b means "b is backwards-compatible with a" -- in other words, "it's safe to upgrade from a to b" function mt:__pow(other) if self.major == 0 then return self == other end return self.major == other.major and self.minor <= other.minor end local function new(major, minor, patch, prerelease, build) assert(major, "At least one parameter is needed") local result = { } if type(major) == 'string' then result.original = major major,minor,patch,prerelease,build = parseVersion(major) end patch = patch or 0 minor = minor or 0 checkPositiveInteger(major, "major") checkPositiveInteger(minor, "minor") checkPositiveInteger(patch, "patch") result.major = major result.minor = minor result.patch = patch result.prerelease = prerelease result.build = build return setmetatable(result, mt) end setmetatable(semver, { __call = function(_, ...) return new(...) end }) semver._VERSION= semver(semver._VERSION) return semver /--[[ --This file is part of zenroom -- --Copyright (C) 2020-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Sunday, 10th April 2022 --]] load_scenario('zencode_credential') ABC = require_once('crypto_credential') G2 = ECP2.generator() local function import_reflow_seal_fingerprints_f(o) if not o then return {} end local rawarr = deepmap(CONF.input.encoding.fun, o) local arr = {} for _, v in ipairs(rawarr) do table.insert(arr, ECP.new(v)) end return arr end local function import_reflow_seal_f(obj) local f if obj.fingerprints then f = import_reflow_seal_fingerprints_f(obj.fingerprints) else f = nil end return { identity = ZEN.get(obj, 'identity', ECP.new), SM = ZEN.get(obj, 'SM', ECP.new), verifier = ZEN.get(obj, 'verifier', ECP2.new), fingerprints = f } end ZEN.add_schema( { reflow_public_key = function(obj) return ZEN.get(obj, '.', ECP2.new) end, reflow_seal = import_reflow_seal_f, reflow_signature = function(obj) return { identity = ZEN.get(obj, 'identity', ECP.new), signature = ZEN.get(obj, 'signature', ECP.new), proof = import_credential_proof_f(obj.proof), zeta = ZEN.get(obj, 'zeta', ECP.new) } end, reflow_identity = function(obj) return ZEN.get(obj, '.', ECP.new) end, material_passport = function(obj) return { seal = import_reflow_seal_f(obj.seal), proof = import_credential_proof_f(obj.proof), zeta = ZEN.get(obj, 'zeta', ECP.new) } end } ) local function _makeuid(src) local uid if luatype(src) == 'table' then uid = ECP.hashtopoint(ZEN.serialize(src)) else uid = ECP.hashtopoint(src) end return(uid) end When( 'create the reflow key', function() -- keygen: δ = r.O ; γ = δ.G2 initkeyring 'reflow' ACK.keyring.reflow = INT.random() -- BLS secret signing key end ) When("create the reflow key with secret key ''", function(sec) local sk = have(sec) initkeyring'reflow' ACK.keyring.reflow = INT.new(sk) end) When("create the reflow key with secret ''", function(sec) local sk = have(sec) initkeyring'reflow' ACK.keyring.reflow = INT.new(sk) end) When( 'create the reflow public key', function() empty 'reflow public key' havekey 'reflow' ACK.reflow_public_key = G2 * ACK.keyring.reflow end ) When( "aggregate the reflow public key from array ''", function(arr) empty 'reflow public key' local s = have(arr) ZEN.assert(#s ~= 0, "Empty array: "..arr) local val for k, v in pairs(s) do if k == 'reflow_public_key' then val = v -- tolerate about named arrays elseif v.reflow_public_key then val = v.reflow_public_key else ZEN.assert(false, "Reflow public key not found in array: " ..arr.."["..#s.."] at key "..k) end if not ACK.reflow_public_key then ACK.reflow_public_key = val else ACK.reflow_public_key = ACK.reflow_public_key + val end end end ) When( "create the reflow identity of ''", function(doc) empty 'reflow identity' ACK.reflow_identity = _makeuid(have(doc)) end ) When( "create the reflow identity of objects in ''", function(doc) empty 'reflow identity' local arr = have(doc) ZEN.assert(luatype(arr)=='table', "Object is not an array or dictionary: "..doc) local first = { } for k,v in pairs(arr) do -- if reflow_id already present then check if ECP and use that if v.reflow_identity then local rid = ECP.new(v.reflow_identity) ZEN.assert(not rid:isinfinity(), "Object "..doc.."["..k.."] has an invalid reflow identity") table.insert(first, rid) else table.insert(first, _makeuid(v)) end end local res for _,v in pairs(first) do if not res then res = v else res = res + v end end ACK.reflow_identity = res end ) local function _create_reflow_seal_f(uid) empty 'reflow seal' have(uid) have 'reflow public key' local UID = ACK[uid] ZEN.assert(type(UID) == 'zenroom.ecp', "Invalid reflow identity: " ..uid.." ("..type(UID)..")") local r = INT.random() ACK.reflow_seal = { identity = UID, SM = UID * r, verifier = ACK.reflow_public_key + G2 * r } end When( "create the reflow seal with identity ''", _create_reflow_seal_f) When("create the reflow seal", function() _create_reflow_seal_f('reflow identity') end) When( 'create the reflow signature', function() empty 'reflow signature' have 'reflow seal' have 'issuer public key' havekey 'reflow' havekey 'credential' -- aggregate all credentials local pubcred = false for _, v in pairs(ACK.issuer_public_key) do if not pubcred then pubcred = v else pubcred = { ['alpha'] = pubcred.alpha + v.alpha, ['beta'] = pubcred.beta + v.beta } end end local p, z = ABC.prove_cred_uid( pubcred, ACK.credentials, ACK.keyring.credential, ACK.reflow_seal.identity ) ACK.reflow_signature = { identity = ACK.reflow_seal.identity, signature = ACK.reflow_seal.identity * ACK.keyring.reflow, proof = p, zeta = z } end ) When( 'prepare credentials for verification', function() have 'credential' local res = false for _, v in pairs(ACK.issuer_public_key) do if not res then res = {alpha = v.alpha, beta = v.beta} else res.alpha = res.alpha + v.alpha res.beta = res.beta + v.beta end end ACK.verifiers = res end ) IfWhen( 'verify the reflow signature credential', function() have 'reflow_signature' have 'verifiers' have 'reflow_seal' ZEN.assert( ABC.verify_cred_uid( ACK.verifiers, ACK.reflow_signature.proof, ACK.reflow_signature.zeta, ACK.reflow_seal.identity ), 'Signature has an invalid credential to sign' ) end ) IfWhen( 'check the reflow signature fingerprint is new', function() have 'reflow_signature' have 'reflow_seal' if not ACK.reflow_seal.fingerprints then return end ZEN.assert( not ACK.reflow_seal.fingerprints[ACK.reflow_signature.zeta], 'Signature fingerprint is not new' ) end ) When( 'add the reflow fingerprint to the reflow seal', function() have 'reflow_signature' have 'reflow_seal' if not ACK.reflow_seal.fingerprints then ACK.reflow_seal.fingerprints = { ACK.reflow_signature.zeta } else table.insert( ACK.reflow_seal.fingerprints, ACK.reflow_signature.zeta ) end end ) When( 'add the reflow signature to the reflow seal', function() have 'reflow_seal' have 'reflow_signature' ACK.reflow_seal.SM = ACK.reflow_seal.SM + ACK.reflow_signature.signature end ) IfWhen( 'verify the reflow seal is valid', function() have 'reflow_seal' ZEN.assert( ECP2.miller(ACK.reflow_seal.verifier, ACK.reflow_seal.identity) == ECP2.miller(G2, ACK.reflow_seal.SM), "reflow seal doesn't validates" ) end ) When( "aggregate the reflow seal array in ''", function(arr) have(arr) empty 'reflow seal' local dst = {} for _, v in pairs(ACK[arr]) do if not dst.UID then dst.UID = v.UID else dst.UID = dst.UID + v.UID end if not dst.SM then dst.SM = v.SM else dst.SM = dst.SM + v.SM end if not dst.verifier then dst.verifier = v.verifier else dst.verifier = dst.verifier + v.verifier end end ACK.reflow_seal = dst end ) -------------------- -- MATERIAL PASSPORT -- -- Simplified flow to generate and verify material passports, which -- are a particular use-case of reflow signatures. Statements here do -- implicit things and reduce complexity of operations, in particular -- there is no multi-party computation in this process so credential -- use is omitted. -- aggregation supports single element arrays and fixes off-by-one local function _aggregate_array(arr) assert(isarray(arr), "Cannot aggregate invalid array", 2) local res = arr[1] if #arr > 1 then for i = 2, #arr do res = res + arr[i] end end return(res) end When( "create the material passport of ''", function(obj) local key = havekey'reflow' local cred = have'credentials' local id = have'reflow identity' local issuer_pub = have'issuer public key' -- object to sign local src = have(obj) empty('material passport') -- append agent id to track and trace if not ACK.fingerprints then ACK.fingerprints = { } end table.insert(ACK.fingerprints, id) -- calculate object uid local UID = _makeuid(src) -- reflow unique ID of object -- calculate signing uid (aggregation of all fingerprints) local SID = UID + _aggregate_array(ACK.fingerprints) local r = INT.random() -- blinding factor local p, z = ABC.prove_cred_uid(issuer_pub, cred, ACK.keyring.credential, SID) ACK.material_passport = { seal = { identity = UID, fingerprints = ACK.fingerprints, -- optional SM = (SID * r) + (SID * key), -- blinding factor verifier = (G2 * r) + (G2 * key) }, proof = p, zeta = z } end) IfWhen( "verify the material passport of ''", function(obj) local src = have(obj) local mp = have'material passport' local pub = have'issuer public key' ZEN.assert(mp.seal.fingerprints, "No fingerprints found in material passport seal: "..obj) local UID = _makeuid(src) ZEN.assert(UID == mp.seal.identity, "Object does not match material passport identity (needs track and trace?): "..obj) local SID = UID + _aggregate_array(mp.seal.fingerprints) ZEN.assert( ECP2.miller(mp.seal.verifier, SID) == ECP2.miller(G2, mp.seal.SM), "Object matches, but seal is invalid: "..obj) ZEN.assert( ABC.verify_cred_uid(pub, mp.proof, mp.zeta, SID), "Object and seal are valid, but proof of issuance fails: "..obj) end) -- Complex check calculates UID of object and compares to seal, if -- correct then validates, else searches for .track array of seals and -- calculates aggregated UID, if correct then validates IfWhen( "verify the material passport of '' is valid", function(obj) have(obj) have(obj..'.seal') -- TODO end) +--[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Alberto Lerda -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --]] local ETH = {} -- number to octet (n2o), were number is a big integer -- in RLP the 0 is reppresented as the empty octet function ETH.n2o(num) if num == INT.new(0) then return O.new() else return num:octet() end end -- idem for octet to number (o2n) function ETH.o2n(o) if #o == 0 then return INT.new(0) else return INT.new(o) end end -- the empty octect is encoded as nil -- a table contains in the first position (i.e. 1) the number of elements function ETH.encodeRLP(data) local header = nil local res = nil local byt = nil if type(data) == 'zenroom.big' then data = ETH.n2o(data) end if type(data) == 'table' then -- empty octet res = O.new() for _, v in pairs(data) do res = res .. ETH.encodeRLP(v) end if #res < 56 then res = INT.new(192+#res):octet() .. res else -- Length of the result to be saved before the bytes themselves byt = INT.new(#res):octet() header = INT.new(247+#byt):octet() .. byt end elseif iszen(type(data)) then res = data:octet() -- index single bytes of an octet local byt = INT.new(0) if #res > 0 then byt = INT.new( res:chop(1) ) end if #res ~= 1 or byt >= INT.new(128) then if #res < 56 then header = INT.new(128+#res):octet() else -- Length of the result to be saved before the bytes themselves byt = INT.new(#res):octet() header = INT.new(183+#byt):octet() .. byt end end else error("Invalid data type for ETH RLP encoder: "..type(data)) end if header then res = header .. res end return res end -- i is the position from which we start to parse -- return a table with -- * res which is the content read -- * idx which is the position of the next byte to read local function decodeRLPgeneric(rlp, i) local byt, res, idx local u128 u128 = INT.new(128) byt = rlp:sub(i, i) idx=i+1 bytInt = tonumber(byt:hex(), 16) if bytInt < 128 then res = byt elseif bytInt <= 183 then idx = i+bytInt-128+1 if bytInt == 128 then res = O.new() else res = rlp:sub(i+1, idx-1) end elseif bytInt < 192 then local sizeEnd = bytInt-183; local size = tonumber(rlp:sub(i+1, i+sizeEnd):hex(), 16) idx = i+sizeEnd+size+1 res = rlp:sub(i+sizeEnd+1, idx-1) else -- it is a tuple local j if bytInt <= 247 then idx = i+bytInt-192+1 -- total number of bytes else -- decode big endian encoding local sizeEnd sizeEnd = bytInt-247; local size = tonumber(rlp:sub(i+1, i+sizeEnd):hex(), 16) idx = i+sizeEnd+size+1 i=i+sizeEnd end i=i+1 -- initial position j=1 -- index inside res res = {} -- decode the tuple in a table while i < idx do local readNext readNext = decodeRLPgeneric(rlp, i) res[j] = readNext.res j = j+1 i = readNext.idx end end return { res=res, idx=idx } end function ETH.decodeRLP(rlp) return decodeRLPgeneric(rlp, 1).res end function ETH.encodeTransaction(tx) local fields = {tx["nonce"], tx["gas_price"], tx["gas_limit"], tx["to"], tx["value"], tx["data"], tx["v"], tx["r"], tx["s"]} return ETH.encodeRLP(fields) end function ETH.decodeTransaction(rlp) local t = ETH.decodeRLP(rlp) return { nonce=ETH.o2n(t[1]), gas_price=ETH.o2n(t[2]), gas_limit=ETH.o2n(t[3]), to=t[4], value=ETH.o2n(t[5]), data=t[6], v=ETH.o2n(t[7]), r=t[8], s=t[9] } end -- modify the input transaction function ETH.encodeSignedTransaction(sk, tx) local H, txHash, sig, pk, x, y, two, res H = HASH.new('keccak256') txHash = H:process(ETH.encodeTransaction(tx)) sig, y_parity = ECDH.sign_ecdh(sk, txHash) two = INT.new(2) res = tx res.v = two * INT.new(tx.v) + INT.new(35) if y_parity then res.v = res.v + INT.new(1) end res.r = INT.new(sig.r) res.s = INT.new(sig.s) return ETH.encodeTransaction(res) end -- Verify the signature of a transaction which implements EIP-155 -- Simple replay attack protection -- https://github.com/ethereum/EIPs/blob/master/EIPS/eip-155.md function ETH.verifySignatureTransaction(pk, txSigned) local fields, H, txHash, tx fields = {"nonce", "gasPrice", "gasLimit", "to", "value", "data"} -- construct the transaction which was signed tx = {} for _, v in pairs(fields) do tx[v] = txSigned[v] end tx["v"] = (txSigned["v"]-INT.new(35))/INT.new(2) tx["r"] = O.new() tx["s"] = O.new() H = HASH.new('keccak256') txHash = H:process(ETH.encodeTransaction(tx)) sig = { r=txSigned["r"], s=txSigned["s"] } return ECDH.verify_hashed(pk, txHash, sig, #txHash) end -- Assume we are given a smart contract with a function with the -- following signature -- function writeString(string memory) -- We send a string and the smart contract signals an event -- Smart contract -- // SPDX-License-Identifier: GPL-3.0 -- pragma solidity ^0.8.4; -- contract SaveString { -- event StringSaveEvent(address user, string content); -- function writeString(string memory content) public { -- emit StringSaveEvent(msg.sender, content); -- } -- } -- Taken from https://docs.soliditylang.org/en/v0.5.6/abi-spec.html#function-selector-and-argument-encoding function ETH.make_storage_data(src) local fId, offset, paddingLength, padding, bytLen, paddingLen -- local H = HASH.new('keccak256') -- string.sub(hex(H:process('storage(string)')), 1, 8) fId = O.from_hex('b374012b') -- dynamic parameter are saved at the end of string, this is at which offset they are saved offset = O.from_hex('0000000000000000000000000000000000000000000000000000000000000020') -- length as a 256 unsigned integer bytLen = INT.new(#src):octet() paddingLength = 32-#bytLen paddingLen = O.zero(paddingLength) paddingLength = #src % 32 if paddingLength > 0 then paddingLength = 32 - paddingLength padding = O.zero(paddingLength) else padding = O.new() end -- done with padding return fId .. offset .. paddingLen .. bytLen .. src .. padding end -- generate an ethereum keypair function ETH.keygen() local kp = ECDH.keygen() -- the address is the keccak hash of the x concatenated with -- the y of the public key (without 04 at the beginning!) -- Taken from https://github.com/ethereumbook/ethereumbook/blob/develop/04keys-addresses.asciidoc -- in the section Ethereum Address -- or in the Yellow Paper -- Warning: we take only the last 20bytes of the hash (...) return { address=ETH.address_from_public_key(kp.public), private=kp.private, } end function ETH.address_from_public_key(pk) local H = HASH.new('keccak256') return H:process(pk:sub(2, #pk)):sub(13, 32) end -- Really simple data encoder, it only works with elementary types (for -- example ERC-20 only uses this kind of data types) function ETH.data_contract_factory(fz_name, params) local H = HASH.new('keccak256') if type(params) ~= 'table' then params = {} end local signature = fz_name .. '(' .. table.concat(params, ",") .. ')' local f_id = O.from_hex(string.sub(hex(H:process(signature)), 1, 8)) return function(...) local args = table.pack(...) local res = f_id for i, v in ipairs(params) do -- I don't check the range of values (for bool the input should be 0 or 1), -- while for int should be 0 ... 2^()-1 if string.match(v, 'uint%d+') or v == 'address' then res = res .. BIG.new(args[i]):fixed(32) elseif v == 'bool' then res = res .. BIG.new(fif(args[i], 1, 0)):fixed(32) end end return res end end function ETH.contract_return_factory(params) if type(params) ~= 'table' then params = {} end -- @param val string or octet with the value returned by the contract return function(val) if type(val) == 'string' then val = string.gsub(val, '^0x', '') val = O.from_hex(val) end assert(type(val) == 'zenroom.octet') local res = {} for i, v in ipairs(params) do -- I don't check the range of values (for bool the input should be 0 or 1), -- while for int should be 0 ... 2^()-1 if v == 'address' or string.match(v, '^uint%d+$') then table.insert(res, BIG.new(val:sub(32 * (i-1)+1, 32 * i))) elseif v == 'bool' then table.insert(res, BIG.new(val:sub(32 * (i-1)+1, 32 * i)) ~= BIG.new(0)) elseif v == 'string' or v == 'bytes' then -- TODO: don't know the maximum size of argument -- there could be an overflow local offset = tonumber(val:sub(32 * (i-1)+1, 32 * i):hex(), 16) local slen = tonumber(val:sub(1+offset, 32+offset):hex(), 16) local s = val:sub(1+offset+32, offset+32+slen):string() if v == 'string' then s = s:string() end table.insert(res, s) else assert(false, "Unknown data type") end end return res end end -- methods with the modifier "view" have to be executed (locally) with -- eth_call, they don't change the blockchain -- the i property are the input parameter -- the o property is (are) the output return types local ERC20_SIGNATURES = { balanceOf = { i={'address'}, o={'uint256'}, view=true }, transfer = { i={'address', 'uint256'}, o={'bool'} }, approve = { i={'address', 'uint256'}, o={'bool'} }, allowance = { i={'address', 'address'}, view=true, o={'uint256'} }, transferFrom = { i={'address', 'address', 'uint256'}, o={'bool'} }, decimals = { o={'uint8'}, view=true }, name = { o={'string'}, view=true }, symbol = { o={'string'}, view=true }, totalSupply = { o={'uint256'}, view=true }, } ETH.erc20 = {} for k, v in pairs(ERC20_SIGNATURES) do ETH.erc20[k] = ETH.data_contract_factory(k, v.i) end ETH.erc20return = {} for k, v in pairs(ERC20_SIGNATURES) do ETH.erc20return[k] = ETH.contract_return_factory(v.o) end local FAUCET_SIGNATURES = { transfer = { i={'address'} }, } ETH.faucet = {} for k, v in pairs(FAUCET_SIGNATURES) do ETH.faucet[k] = ETH.data_contract_factory(k, v.i) end return ETH --[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Alberto Lerda and Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 9th April 2022 --]] local btc -- mostly loaded at init if not BTC then btc = require_once('crypto_bitcoin') else btc = BTC end -- TODO: any mean to verify that the content of address and txid is valid local function _get_addr(obj) local res = ZEN.get(obj, '.', O.from_base58, tostring) if not res then error("invalid segwit address",2) end return res end local function _bitcoin_unspent_import(obj) local res = {} for _,v in pairs(obj) do -- compatibility with electrum and bitcoin core local n_amount = fif( v.amount, 'amount', 'value') local n_txid = fif( v.txid, 'txid', 'prevout_hash') local n_vout = fif( v.vout, 'vout', 'prevout_n') local address if v.address then address = ZEN.get(v,'address', O.from_segwit, tostring) end local amount = ZEN.get(v,n_amount, btc.value_btc_to_satoshi, tostring) local txid = ZEN.get(v,n_txid, OCTET.from_hex, tostring) local vout = v[n_vout] -- number table.insert(res, { address = address, amount = amount, txid = txid, vout = vout }) end return(res) end local function _bitcoin_unspent_export(obj) local res = { } for _,v in pairs(obj) do -- to_segwit: octet, version number(0), 'bc' or 'tc' local address = v.address:segwit(0, 'tb') local amount = btc.value_satoshi_to_btc(v.amount) local txid = v.txid:hex() local vout = v.vout table.insert(res, { address = address, amount = amount, txid = txid, vout = vout }) end return res end local function _satoshi_unspent_import(obj) local res = {} for _,v in pairs(obj) do -- compatibility with electrum and bitcoin core table.insert(res, { amount = ZEN.get(v,'value', BIG.from_decimal, tostring), txid = ZEN.get(v,'txid', OCTET.from_hex, tostring), vout = v.vout }) end return(res) end local function _satoshi_unspent_export(obj) local res = { } for _,v in pairs(obj) do -- to_segwit: octet, version number(0), 'bc' or 'tc' local address = v.address:segwit(0, 'tb') local amount = BIG.to_decimal(v.amount) local txid = v.txid:hex() local vout = v.vout table.insert(res, { amount = amount, txid = txid, vout = vout }) end return res end local function _address_import(obj) return { raw = ZEN.get(obj, '.', O.from_segwit, tostring) } end local function _address_export(obj) return O.to_segwit(obj.raw, obj.version, O.to_string(obj.network)) end local function _wif_import(obj) return ZEN.get(obj, '.', BTC.wif_to_sk, O.from_base58) end local function _wif_bitcoin_export(obj) return O.to_base58( BTC.sk_to_wif( obj, 'bitcoin') ) end local function _wif_testnet_export(obj) return O.to_base58( BTC.sk_to_wif( obj, 'testnet') ) end ZEN.add_schema( { bitcoin_key = { import = _wif_import, export = _wif_bitcoin_export }, testnet_key = { import = _wif_import, export = _wif_testnet_export }, satoshi_amount = function(obj) return ZEN.get(obj, '.', BIG.from_decimal, tostring) end, satoshi_fee = function(obj) return ZEN.get(obj, '.', BIG.from_decimal, tostring) end, satoshi_unspent = { import = _satoshi_unspent_import, export = _satoshi_unspent_export }, bitcoin_unspent = { import = _bitcoin_unspent_import, export = _bitcoin_unspent_export }, testnet_unspent = { import = _bitcoin_unspent_import, export = _bitcoin_unspent_export }, bitcoin_address = { import = _address_import, export = _address_export }, testnet_address = { import = _address_import, export = _address_export }, }) -- generate a keypair in "bitcoin" format (only x coord, 03 prepended) local function _keygen(name) initkeyring(name) local kp = ECDH.keygen() ACK.keyring[name] = kp.private end When('create the bitcoin key', function() _keygen('bitcoin') end) When('create the testnet key', function() _keygen('testnet') end) local function _import_wif(sec, name) local sk = have(sec) local res if #sk == 32+6 then -- wif btc.wif_to_sk(sk) -- checks res = sk elseif #sk == 32 then res = sk -- TODO: import from hdwallet xpriv format else error("Invalid "..name.." key size for "..sec..": "..#sk) end initkeyring(name) ACK.keyring[name] = res end When("create the bitcoin key with secret key ''", function(sec) _import_wif(sec, 'bitcoin') end) When("create the testnet key with secret key ''", function(sec) _import_wif(sec, 'testnet') end) When("create the bitcoin key with secret ''", function(sec) _import_wif(sec, 'bitcoin') end) When("create the testnet key with secret ''", function(sec) _import_wif(sec, 'testnet') end) local function _get_pub(name) empty(name..' public key') local sk = havekey(name) ACK[name..'_public_key'] = ECDH.sk_to_pubc(sk) new_codec(name..' public key', { zentype = 'schema' }) end When("create the bitcoin public key", function() _get_pub('bitcoin') end) When("create the testnet public key", function() _get_pub('testnet') end) local function _create_addr(name,pfx) empty(name..' address') local pk if ACK[name..'_public_key'] then pk = have(name..' public key') else pk = ECDH.sk_to_pubc( havekey(name) ) end ACK[name..'_address'] = { raw = btc.address_from_public_key(pk), version = 0, network = O.from_string(pfx) } new_codec(name..' address', { zentype = 'schema', encoding = 'complex' }) end When("create the bitcoin address", function() _create_addr('bitcoin','bc') end) When("create the testnet address", function() _create_addr('testnet','tb') end) local function _create_tx(name, recipient) local to = have(recipient or 'recipient') if not to then error("Cannot create "..name.." transaction: recipient not specified") end local q = have'satoshi amount' local fee = have'satoshi fee' local unspent = have(name..' unspent') local tx = btc.build_tx_from_unspent(unspent, to, q, fee, ACK.sender) ZEN.assert(tx, "Not enough "..name.." in the unspent list") ACK[name..'_transaction'] = tx end When('create the bitcoin transaction', function() _create_tx('bitcoin') end) When('create the testnet transaction', function() _create_tx('testnet') end) When("create the bitcoin transaction to ''", function(recipient) _create_tx('bitcoin', recipient) end) When("create the testnet transaction to ''", function(recipient) _create_tx('testnet', recipient) end) local function _sign_tx(name) local sk = havekey(name) local tx = have(name..'_transaction') ZEN.assert(not tx.witness, "The "..name.." transaction is already signed") tx.witness = btc.build_witness(tx, sk) end When("sign the bitcoin transaction", function() _sign_tx('bitcoin') end) When("sign the testnet transaction", function() _sign_tx('testnet') end) local function _toraw_tx(name) local tx = have(name..' transaction') empty(name..' raw transaction') ACK[name..'_raw_transaction'] = btc.build_raw_transaction(tx) end When("create the bitcoin raw transaction", function() _toraw_tx('bitcoin') end) When("create the testnet raw transaction", function() _toraw_tx('testnet') end) --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local ecp2 = require'ecp2' require'fp12' -- FP12 implicit function ecp2.hashtopoint(s) return ecp2.mapit(sha512(s)) end function ecp2.random() return ecp2.mapit(OCTET.random(64)) end return ecp2 --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Sunday, 10th April 2022 --]] --- THEN combinations: -- the -- the from -- the as -- the in -- my -- my from -- my as -- the from as -- the from in -- the as in -- the from as in -- my from as ---------------------- -- executes a guess_outcast and then operates it -- sch may be fed with check_codec() result (name of encoding) local function then_outcast(val, sch) if not val then error("Then outcast called on empty variable", 2) end local fun = guess_outcast(sch) local lt = luatype(val) -- handle simple conversions if lt ~= 'table' then return fun(val) end local codec = ZEN.CODEC[sch] if not codec or codec and codec.zentype ~= 'schema' then return deepmap(fun, val) end -- if object name and schema name differ, get correct schema if codec.name ~= sch then fun = guess_outcast(codec.name) end -- handle schema conversions if codec.encoding and codec.encoding == 'complex' then -- complex if not isdictionary(val) then error('Complex schema value is not a dictionary: '..sch, 2) end return fun(val) else -- schema not complex local res = fun(val) local enc = guess_outcast( codec.encoding ) if luatype(res) == 'table' then return deepmap(enc, res) else return enc(res) end end error("Then outcast cannot handle data: "..sch,2) end local function then_insert(dest, val, key) if not ACK[dest] then OUT[dest] = val elseif luatype(OUT[dest]) == 'table' then if isarray(OUT[dest]) then table.insert(OUT[dest], val) else assert(key, 'Then statement targets dictionary with empty key: '..dest) OUT[dest][key] = val end else -- extend string to array local tmp = OUT[dest] OUT[dest] = { tmp } table.insert(OUT[dest], val) end end local function iterate_data(t) local a = {} for k,v in lua_pairs(t) do if k ~= 'keyring' then table.insert(a, n) end end local i = 0 -- iterator variable return function () -- iterator function i = i + 1 return a[i], t[a[i]] end end Then("nothing", function() return end) -- nop to terminate if Then("print string ''", function(k) if not OUT.output then OUT.output = {} end table.insert(OUT.output, k) -- raw string value end) Then("print ''", function(name) local val = have(name) OUT[name] = then_outcast( val, check_codec(name) ) end) Then("print '' as ''",function(k, s) local val = have(k) OUT[k] = then_outcast( val, s ) end) Then("print '' from ''",function(k, f) local val = have({f,k}) -- use array to check in depth OUT[k] = then_outcast( val, check_codec(f) ) end) Then("print '' from '' as ''",function(k, f, s) local val = have({f,k}) -- use array to check in depth OUT[k] = then_outcast( val, s ) end) Then("print '' from '' as '' in ''",function(k, f, s, d) local val = have({f,k}) -- use array to check in depth then_insert( d, then_outcast( val, s ), k) end) Then("print '' as '' in ''",function(k, s, d) local val = have(k) -- use array to check in depth then_insert( d, then_outcast( val, s ), k) end) Then("print my '' from '' as ''",function(k, f, s) Iam() local val = have({f,k}) -- use array to check in depth then_insert( WHO, then_outcast( val, s ), k) end) Then("print my '' from ''",function(k, f) Iam() local val = have({f,k}) -- use array to check in depth -- my statements always print to a dictionary named after WHO if not OUT[WHO] then OUT[WHO] = { } end OUT[WHO][k] = then_outcast( val, check_codec(f) ) end) Then("print my '' as ''",function(k, s) Iam() local val = have(k) -- use array to check in depth then_insert( WHO, then_outcast( val, s ), k) end) Then("print my ''",function(k) Iam() local val = have(k) -- my statements always print to a dictionary named after WHO if not OUT[WHO] then OUT[WHO] = { } end OUT[WHO][k] = then_outcast( val, check_codec(k) ) end) Then('print keyring',function() OUT.keyring = ZEN.schemas.keyring.export(ACK.keyring) end) Then('print my keyring',function() Iam() OUT[WHO] = { keyring = ZEN.schemas.keyring.export(ACK.keyring) } end) -- data -- data as -- data from -- data from as -- my data -- my data as -- my data from -- my data from as Then('print data',function() for k, v in pairs(ACK) do OUT[k] = then_outcast(v, check_codec(k)) end end ) Then("print data as ''",function(e) local fun for k, v in pairs(ACK) do OUT[k] = then_outcast(v, e) end end ) Then("print data from ''", function(src) local obj = have(src) for k,v in pairs(obj) do ACK[k] = true -- to legitimate new_codec creation OUT[k] = then_outcast( v, check_codec(src) ) end end) Then("print data from '' as ''", function(src, e) local obj = have(src) for k,v in pairs(obj) do ACK[k] = true -- to legitimate new_codec creation OUT[k] = then_outcast( v, e ) end end) Then('print my data',function() Iam() -- sanity checks OUT[WHO] = { } for k, v in pairs(ACK) do OUT[WHO][k] = then_outcast( v, check_codec(k) ) end end) Then("print my data as ''",function(e) Iam() -- sanity checks OUT[WHO] = { } for k, v in pairs(ACK) do OUT[WHO][k] = then_outcast( v, e ) end end ) Then("print my data from ''",function(src) Iam() -- sanity checks OUT[WHO] = { } local obj = have(src) for k, v in pairs(obj) do OUT[WHO][k] = then_outcast( v, check_codec(k) ) end end ) Then("print my data from '' as ''",function(src, e) Iam() -- sanity checks OUT[WHO] = { } local obj = have(src) for k, v in pairs(obj) do OUT[WHO][k] = then_outcast( v, e ) end end ) Then("print object named by ''", function(name) local val = have(name):string() local real_name = have(val) OUT[val] = then_outcast( real_name, check_codec(val) ) end) q--[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --Written by Denis Roio and Alberto Sonnino -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] -- Zero-Knowledge proof scheme based on Coconut -- -- Coconut is a selective disclosure credential scheme supporting public -- and private attributes, re-randomization, and multiple unlinkable -- selective attribute revelations. local credential = {} local G1 = ECP.generator() -- return value local G2 = ECP2.generator() -- return value -- local zero-knowledge proof verifications local function make_pi_s(gamma, commit, k, r, m) local wk = INT.random() local wm = INT.random() local wr = INT.random() local Aw = G1 * wk local Bw = gamma * wk + commit * wm local Cw = G1 * wr + SALT * wm local c = ZKP_challenge({commit, Aw, Bw, Cw}) -- return pi_s return { commit = c, rk = wk - c * k, rm = wm - c * m, rr = wr - c * r } end function credential.verify_pi_s(l) local Aw = l.sign.a * l.pi_s.commit + G1 * l.pi_s.rk local Bw = l.sign.b * l.pi_s.commit + l.public * l.pi_s.rk + l.commit * l.pi_s.rm local Cw = l.commit * l.pi_s.commit + G1 * l.pi_s.rr + SALT * l.pi_s.rm -- return a bool for assert return l.pi_s.commit == ZKP_challenge({l.commit, Aw, Bw, Cw}) end -- Public Coconut API function credential.issuer_keygen() return { x = INT.random(), y = INT.random() } end function credential.aggregate_keys(keys) local agg_alpha = keys[1].alpha local agg_beta = keys[1].beta if #keys > 1 then for i = 2, #keys do agg_alpha = agg_alpha + keys[i].alpha agg_beta = agg_beta + keys[i].beta end end -- return aggkeys return { alpha = agg_alpha, beta = agg_beta } end function credential.prepare_blind_sign(secret) local gamma = G1 * secret local m = INT.new(sha256(secret)) % ECP.order() -- ElGamal commitment local r = INT.random() local commit = G1 * r + SALT * m local k = INT.random() local sign = { a = G1 * k, b = gamma * k + commit * m } -- calculate zero knowledge proofs local pi_s = make_pi_s(gamma, commit, k, r, m) -- return Lambda return { commit = commit, sign = sign, pi_s = pi_s, public = gamma } end function credential.blind_sign(sk, Lambda) assert( credential.verify_pi_s(Lambda), 'Zero knowledge proof does not verify (Lambda.pi_s)', 2 ) local h = Lambda.commit local a_tilde = Lambda.sign.a * sk.y local b_tilde = h * sk.x + Lambda.sign.b * sk.y -- sigma tilde return { h = h, a_tilde = a_tilde, b_tilde = b_tilde } end function credential.aggregate_creds(sk, sigma_tilde) local agg_s = sigma_tilde[1].b_tilde - sigma_tilde[1].a_tilde * sk -- ElGamal verify commitment if #sigma_tilde > 1 then for i = 2, #sigma_tilde do agg_s = agg_s + sigma_tilde[i].b_tilde - sigma_tilde[i].a_tilde * sk end end -- aggregated sigma return { h = sigma_tilde[1].h, s = agg_s } end function credential.prove_cred(verify, sigma, secret) local m = INT.new(sha256(secret)) % ECP.order() local r = INT.random() local r_prime = INT.random() local sigma_prime = { h_prime = sigma.h * r_prime, s_prime = sigma.s * r_prime } local kappa = verify.alpha + verify.beta * m + G2 * r local nu = sigma_prime.h_prime * r local wm = INT.random() local wr = INT.random() local challenge = ZKP_challenge( { verify.alpha, verify.beta, verify.alpha + G2 * wr + verify.beta * wm, -- Aw sigma_prime.h_prime * wr } ) -- Bw -- return Theta return { kappa = kappa, nu = nu, sigma_prime = sigma_prime, pi_v = { c = challenge, rr = wr - r * challenge, rm = wm - m * challenge } } end function credential.verify_cred(verify, Theta) if #verify == 1 then verify = verify[1] end -- single element in array -- verify pi_v local Aw = Theta.kappa * Theta.pi_v.c + G2 * Theta.pi_v.rr + verify.alpha * (BIG.new(1) - Theta.pi_v.c) + verify.beta * Theta.pi_v.rm local Bw = Theta.nu * Theta.pi_v.c + Theta.sigma_prime.h_prime * Theta.pi_v.rr -- check zero knowledge proof assert( Theta.pi_v.c == ZKP_challenge({verify.alpha, verify.beta, Aw, Bw}), 'credential verification: invalid challenge', 2 ) assert( not Theta.sigma_prime.h_prime:isinf(), 'credential verification: invalid signature (infinite sigma)', 2 ) assert( ECP2.miller(Theta.kappa, Theta.sigma_prime.h_prime) == ECP2.miller(G2, Theta.sigma_prime.s_prime + Theta.nu), 'credential verification: invalid signature (miller loop)', 2 ) return true end function credential.prove_cred_uid(vk, sigma, secret, uid) local m = INT.new(sha256(secret)) % ECP.order() local r = INT.random() -- material local r_prime = INT.random() local sigma_prime = { h_prime = sigma.h * r_prime, s_prime = sigma.s * r_prime } local kappa = vk.alpha + vk.beta * m + G2 * r local nu = sigma_prime.h_prime * r local zeta = m * ECP.hashtopoint(uid) -- proof -- -- create the witnessess local wm = INT.random() local wr = INT.random() -- compute the witnessess commitments local Aw = vk.alpha + vk.beta * wm + G2 * wr local Bw = sigma_prime.h_prime * wr local Cw = wm * ECP.hashtopoint(uid) -- create the challenge local c = ZKP_challenge({vk.alpha, vk.beta, Aw, Bw, Cw}) -- create responses local pi_v = { c = c, rm = wm - m * c, rr = wr - r * c } local Theta = { kappa = kappa, nu = nu, sigma_prime = sigma_prime, pi_v = pi_v } return Theta, zeta end function credential.verify_cred_uid(vk, theta, zeta, uid) -- recompute witnessess commitments local Aw = theta.kappa * theta.pi_v.c + G2 * theta.pi_v.rr + vk.alpha * (BIG.new(1) - theta.pi_v.c) + vk.beta * theta.pi_v.rm local Bw = theta.pi_v.rr * theta.sigma_prime.h_prime + theta.nu * theta.pi_v.c local Cw = theta.pi_v.rm * ECP.hashtopoint(uid) + zeta * theta.pi_v.c -- compute the challenge prime assert( theta.pi_v.c == ZKP_challenge({vk.alpha, vk.beta, Aw, Bw, Cw}), 'credential verification: invalid challenge for UID', 2 ) -- verify signature -- assert( not theta.sigma_prime.h_prime:isinf(), 'credential verification: invalid signature (infinite sigma) for UID', 2 ) assert( ECP2.miller(theta.kappa, theta.sigma_prime.h_prime) == ECP2.miller(G2, theta.sigma_prime.s_prime + theta.nu), 'credential verification: invalid signature (miller loop) for UID', 2 ) return true end return credential ~--[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 27th November 2021 --]] local _UNRESERVED = "A-Za-z0-9%-._~" local _GEN_DELIMS = ":/?#%[%]@" local _SUB_DELIMS = "!$&'()*+,;=" local _RESERVED = _GEN_DELIMS .. _SUB_DELIMS local _REG_NAME = "^[" .. _UNRESERVED .. "%%" .. _SUB_DELIMS .. "]*$" local _IP_FUTURE_LITERAL = "^v[0-9A-Fa-f]+%." .. "[" .. _UNRESERVED .. _SUB_DELIMS .. "]+$" local function _normalize_percent_encoding (s) if s:find("%%$") or s:find("%%.$") then error("unfinished percent encoding at end of URI '" .. s .. "'") end return s:gsub("%%(..)", function (hex) if not hex:find("^[0-9A-Fa-f][0-9A-Fa-f]$") then error("invalid percent encoding '%" .. hex .. "' in URI '" .. s .. "'") end -- Never percent-encode unreserved characters, and always use uppercase -- hexadecimal for percent encoding. RFC 3986 section 6.2.2.2. local char = string.char(tonumber("0x" .. hex)) return char:find("^[" .. _UNRESERVED .. "]") and char or "%" .. hex:upper() end) end local function _is_ip4_literal (s) if not s:find("^[0-9]+%.[0-9]+%.[0-9]+%.[0-9]+$") then return false end for dec_octet in s:gmatch("[0-9]+") do if dec_octet:len() > 3 or dec_octet:find("^0.") or tonumber(dec_octet) > 255 then return false end end return true end local function _is_ip6_literal (s) local had_elipsis = false -- true when '::' found local num_chunks = 0 while s ~= "" do num_chunks = num_chunks + 1 local p1, p2 = s:find("::?") local chunk if p1 then chunk = s:sub(1, p1 - 1) s = s:sub(p2 + 1) if p2 ~= p1 then -- found '::' if had_elipsis then return false end -- two of '::' had_elipsis = true if chunk == "" then num_chunks = num_chunks - 1 end else if chunk == "" then return false end -- ':' at start if s == "" then return false end -- ':' at end end else chunk = s s = "" end -- Chunk is neither 4-digit hex num, nor IPv4address in last chunk. if (not chunk:find("^[0-9a-f]+$") or chunk:len() > 4) and (s ~= "" or not _is_ip4_literal(chunk)) and chunk ~= "" then return false end -- IPv4address in last position counts for two chunks of hex digits. if chunk:len() > 4 then num_chunks = num_chunks + 1 end end if had_elipsis then if num_chunks > 7 then return false end else if num_chunks ~= 8 then return false end end return true end local function _is_valid_host (host) if string.find(host,"^%[.*%]$") then local ip_literal = host:sub(2, -2) if ip_literal:find("^v") then if not ip_literal:find(_IP_FUTURE_LITERAL) then return "invalid IPvFuture literal '" .. ip_literal .. "'" end else if not _is_ip6_literal(ip_literal) then return "invalid IPv6 address '" .. ip_literal .. "'" end end elseif not _is_ip4_literal(host) and not host:find(_REG_NAME) then return "invalid host value '" .. host .. "'" end return nil end When("create the url from ''", function(src) local obj = have(src) local url = obj:str():lower() empty'url' local proto if url:sub(1,7)=='http://' then proto = 'http://' end if url:sub(1,8)=='https://' then proto = 'https://' end ZEN.assert(proto, "Invalid http prefix in url: "..obj:str()) local toks = strtok(url, '[^/]+') -- second is the host local res = _is_valid_host(toks[2]) ZEN.assert(not res, res) ACK.url = obj new_codec('url',{zentype='element',content='url', encoding='string'}) end) When("append '' as http request to ''", function(ele, dst) local arg = have(ele):str():lower() local url = have(dst):str():lower() local codec = ZEN.CODEC[dst] ZEN.assert(codec.content=='url', "Cannot append http request to invalid url: "..dst) local separator = fif( url:find('?'), '&', '?' ) ACK[dst] = O.from_string( url .. separator .. _normalize_percent_encoding(ele) .. '=' .. _normalize_percent_encoding(arg) ) end) --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local ecp = require'ecp' function ecp.hashtopoint(s) return ecp.mapit(sha512(s)) end function ecp.random() return ecp.mapit(OCTET.random(64)) end return ecp --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local hash = require'hash' -- when using facility functions, global hashers are created only once SHA256 = nil SHA512 = nil local function init(bits) local h if bits == 256 or bits == 32 then if SHA256==nil then SHA256 = hash.new('sha256') end h = SHA256 elseif bits == 512 or bits == 64 then if SHA512==nil then SHA512 = hash.new('sha512') end h = SHA512 else error("HASH bits not supported: "..bits) end return h end function sha256(data) return init(256):process(data) end function sha512(data) return init(512):process(data) end function KDF(data, bits) local b = bits or 256 return init(b):kdf2(data) end function hash.dsha256(msg) local SHA256 = HASH.new('sha256') return SHA256:process(SHA256:process(msg)) end function hash.hash160(msg) local SHA256 = HASH.new('sha256') local RMD160 = HASH.new('ripemd160') return RMD160:process(SHA256:process(msg)) end return hash --[[ --This file is part of zenroom -- --Copyright (C) 2020-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] -- Elgamal based Additive Homomorphic commitment scheme local elgah = { _VERSION = 'crypto_elgamal.lua 0.5', _URL = 'https://zenroom.dyne.org', _DESCRIPTION = 'Elgamal based Additive Homomorphic commitment scheme ', _LICENSE = [[ Licensed under the terms of the GNU Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ]] } local G = ECP.generator() -- return value local O = ECP.order() -- return value -- stateful challenge hardcoded string local hs = ECP.hashtopoint(str([[ Jaromil started writing this code on Tuesday 21st January 2020 ]] .. elgah._LICENSE)) local challenge = G:octet() .. hs:octet() local function to_challenge(list) local ser = serialize(list) return INT.new( sha256( challenge .. ser.octets .. OCTET.from_string(ser.strings))) end function elgah.keygen() local res = { private = INT.random() } res.public = G * res.private return(res) end function elgah.new(pub, m) -- sign == vote local k = INT.random() local hsm = hs * m -- optimisation -- vote encryption local enc_v = { left = G * k, right = pub * k + hsm } -- opposite of vote encryption local enc_v_neg = { left = enc_v.left:negative(), right = enc_v.right:negative() + hs } -- commitment to the vote local r = INT.random() local cv = G * r + hsm -- proof -- create the witnesess local wk = INT.random() local wm = INT.random() local wr = INT.random() local hswm = hs * wm -- optimisation -- compute the witnessess commitments local Aw = G * wk local Bw = pub * wk + hswm local Cw = G * wr + hswm -- create the challenge local c = to_challenge({enc_v.left, enc_v.right, cv, Aw, Bw, Cw}) -- create responses local rk = wk - c * k local rm = wm - c * m local rr = wr - c * r local pi = { c = c, rk = rk, rm = rm, rr = rr } -- signature's Theta return { value = { pos = enc_v, neg = enc_v_neg }, -- left/right tuples cv = cv, -- ecp pi = pi } -- pi end function elgah.verify(pub, theta) -- recompute witnessess commitment ZEN.assert(theta.pi, "ELGAH.verify 1st argument has no proof") ZEN.assert(theta.value,"ELGAH.verify 2nd argument has no value") local value = theta.value.pos local Aw = G * theta.pi.rk + value.left * theta.pi.c local Bw = pub * theta.pi.rk + hs * theta.pi.rm + value.right * theta.pi.c local Cw = G * theta.pi.rr + hs * theta.pi.rm + theta.cv * theta.pi.c -- verify challenge ZEN.assert(theta.pi.c == to_challenge( {value.left, value.right, theta.cv, Aw, Bw, Cw }), "ELGAH.verify: challenge fails") return true end function elgah.zero() return { pos = { left = ECP.infinity(), right = ECP.infinity() }, neg = { left = ECP.infinity(), right = ECP.infinity() } } end function elgah.add(pub, a, b) elgah.verify(pub, a) local pos = { left = nil, right = nil } local neg = { left = nil, right = nil } pos.left = a.value.pos.left + b.pos.left pos.right = a.value.pos.right + b.pos.right neg.left = a.value.neg.left + b.neg.left neg.right = a.value.neg.right + b.neg.right return { pos = pos, neg = neg } end function elgah.sub(pub, a, b) elgah.verify(pub, a) local pos = { left = nil, right = nil } local neg = { left = nil, right = nil } pos.left = a.value.pos.left - b.pos.left pos.right = a.value.pos.right - b.pos.right neg.left = a.value.neg.left - b.neg.left neg.right = a.value.neg.right - b.neg.right return { pos = pos, neg = neg } end function elgah.tally(pub, priv, n) local wx = INT.random() local Aw = { wx:modneg(O) * n.pos.left, wx:modneg(O) * n.neg.left } local c = to_challenge(Aw) local rx = wx - c * priv local dec = { pos = n.pos.left * priv:modneg(O), neg = n.neg.left * priv:modneg(O) } -- return pi_tally return { dec = dec, rx = rx, c = c } end function elgah.verify_tally(tally, value) local rxneg = tally.rx:modneg(O) local Aw = { rxneg * value.pos.left + tally.c * tally.dec.pos, rxneg * value.neg.left + tally.c * tally.dec.neg } ZEN.assert(tally.c == to_challenge(Aw), "ELGAH.verify_tally: challenge fails") return true end function elgah.count(tally, value, max) elgah.verify_tally(tally, value) local restab = { } max = max or 1000 for idx=1,max do restab[(BIG.new(idx) * hs):octet():url64()] = idx end local res = { pos = value.pos.right + tally.dec.pos, neg = value.neg.right + tally.dec.neg } return restab[res.pos:octet():url64()] end return elgah --[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Alberto Lerda -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --]] local HDW = {} -- an extended key is a table with the fields -- secret, chain_code, level, fingerprint_parent, child_number -- a private key may have public=nil -- a public key have secret=nil -- parse extended key -- @param data octet to be parsed -- @return extended key function HDW.parse_extkey(data) data = O.from_base58(data) -- check checksum assert(#data == 82 and data:sub(#data-3, #data) == HASH.dsha256(data:sub(1, #data-4)):chop(4), "Wrong input key", 2) local extkey = {} local i = 1 version = data:sub(i,i+3) i = i + 4 assert(version == HDW.MAINPK or version == HDW.MAINSK or version == HDW.TESTPK or version == HDW.TESTSK, "Unknown version", 2) local public = HDW.isPublic(version) extkey.level = tonumber(data:sub(i,i):hex(), 16) i = i + 1 extkey.fingerprint_parent = data:sub(i, i+3) i = i + 4 -- big endian 4 bytes integer extkey.child_number = BIG.new(data:sub(i, i+3)) i = i + 4 extkey.chain_code = data:sub(i, i+31) i = i + 32 if public then extkey.public = data:sub(i,i+32) else extkey.secret = data:sub(i+1,i+32) end return extkey end HDW.MAINPK = O.from_hex('0488B21E') HDW.TESTPK = O.from_hex('043587CF') HDW.MAINSK = O.from_hex('0488ADE4') HDW.TESTSK = O.from_hex('04358394') function HDW.isPublic(version) return version == HDW.MAINPK or version == HDW.TESTPK end function HDW.getPublic(extkey) if not extkey.public then extkey.public = ECDH.sk_to_pubc(extkey.secret) end assert(extkey.public ~= nil) return extkey.public end function HDW.format_extkey(extkey, version) local data = O.new() assert(version == HDW.MAINPK or version == HDW.MAINSK or version == HDW.TESTPK or version == HDW.TESTSKK, "Unknown version", 2) local public = HDW.isPublic(version) data = data .. version data = data .. O.from_hex(string.format("%02x", extkey.level)) data = data .. BIG.new(extkey.fingerprint_parent):fixed(4) data = data .. BIG.new(extkey.child_number):fixed(4) data = data .. extkey.chain_code if public then data = data .. HDW.getPublic(extkey) else assert(extkey.secret, "From a public key it is not possible to print a private key") data = data .. O.from_hex('00') .. extkey.secret end local check = HASH.dsha256(data):sub(1,4) data = data .. check return data:base58() end -- Child key derivation private key -- @param parent_key extended key object -- @param i index function HDW.ckd_priv(parent_key, i) local newkey = {} local l local s512 = HASH.new('sha512') local pk -- check validity of index assert(i <= BIG.new(O.from_hex('ffffffff')), "Invalid index") -- we cannot derive a private key from a public key assert(parent_key.secret, "Cannot derive a private key from a public key") newkey.child_number = i local i_oct = i:octet() if #i_oct < 4 then i_oct = O.zero(4 - #i_oct) .. i_oct end if i >= BIG.new(O.from_hex('80000000')) then l = O.zero(1) .. parent_key.secret .. i_oct; else pk = HDW.getPublic(parent_key) l = pk .. i_oct; end l = HASH.hmac(s512, parent_key.chain_code, l) lL = BIG.new(l:sub( 1,32)) lR = l:sub(33,64) -- On BIP32 there is a mod, if I add it, it doesn't work -- TODO improve arithmetics modulo order of curve secp256k1 newkey.secret = ((lL + BIG.new(parent_key.secret)) % (BIG.new(O.from_hex('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141')))):octet() -- check if lR >= order curve, in that case return ckd_priv(parent_key, i+1) if newkey.secret == INT.new(0) then return ckd_priv(parent_key, i+1) end -- compute fingerprint -- parent_key is a private key pk = HDW.getPublic(parent_key) newkey.fingerprint_parent = HASH.hash160(pk):sub(1,4) newkey.chain_code = lR newkey.level = parent_key.level + 1 return newkey end -- the "neutered" version, as it removes the ability to sign transactions function HDW.neutered(parent_key) local newkey = {} for k, v in pairs(parent_key) do newkey[k] = v end HDW.getPublic(newkey) newkey.secret = nil return newkey end -- Child key derivation public key -- @param parent_key extended key object -- @param i it is only defined for non-hardened child keys (i <= 0x80000000) function HDW.ckd_pub(parent_key, i) local newkey = {} local l, lR, lL local s512 = HASH.new('sha512') -- check validity of index --assert(i <= BIG.new(O.from_hex('ffffffff')), "Invalid index") assert(i < BIG.new(O.from_hex('80000000')), "Public key derivation is only defined for non-hardened child keys") if parent_key.secret then newkey = HDW.neutered(HDW.ckd_priv(parent_key, i)) else pk = HDW.getPublic(parent_key) newkey.child_number = i l = parent_key.public .. i:fixed(4) l = HASH.hmac(s512, parent_key.chain_code, l) lL = BIG.new(l:sub( 1,32)) lR = l:sub(33,64) local nG = ECDH.pubgen(lL) -- = n * G newkey.public = ECDH.compress_public_key(ECDH.add(nG, parent_key.public)) -- check if lR >= order curve, in that case return ckd_priv(parent_key, i+1) if newkey.secret == INT.new(0) then return ckd_priv(parent_key, i+1) end newkey.fingerprint_parent = HASH.hash160(pk):sub(1,4) newkey.chain_code = lR newkey.level = parent_key.level + 1 end return newkey end function HDW.master_key_generation(seed) if not seed then seed = O.random(32) end local s512 = HASH.new('sha512') local l = HASH.hmac(s512, O.from_string('Bitcoin seed'), seed) local lL = l:sub( 1,32) -- check Ll < order of the curve local lR = l:sub(33,64) return { secret = lL, chain_code = lR, level = 0, fingerprint_parent = O.from_hex('00000000'), child_number = O.from_hex('00000000'), } end -- Implements the default wallet layout -- only external keys are supported -- @param parent_key parent private key -- @param i bignum i >= 0 and i <= 80000000 -- @param wallet bignum or the string '' (the dafult wallet), optional -- @param nohardened by default child keys are hardened (if there is not the parameter -- nohardned = nil which is the same as false) function HDW.standard_child(parent_key, i, wallet, nohardened) local HARDNED = BIG.new(O.from_hex('80000000')) assert(i < HARDNED) if not nohardened then i = i + HARDNED end if not wallet or wallet=='' then wallet = INT.new(0) end assert(wallet < HARDNED) wallet_key = HDW.ckd_priv(parent_key, wallet+HARDNED) external_key = HDW.ckd_priv(wallet_key, INT.new(0)) address_key = HDW.ckd_priv(external_key, i) return address_key end function HDW.mnemonic_master_key(mnemonic, password) return HDW.master_key_generation(HASH.mnemonic_seed(mnemonic, password)) end return HDW /--[[ --This file is part of zenroom -- --Copyright (C) 2018-2022 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 27th November 2021 --]] -- random operations, mostly on arrays and schemas supported When("create the random ''", function(dest) ZEN.assert(not ACK[dest], "Cannot overwrite existing value: "..dest) ACK[dest] = OCTET.random(32) -- TODO: right now hardcoded 256 bit random secrets end) function shuffle_array_f(tab) -- do not enforce CODEC detection since some schemas are also 1st level arrays local count = isarray(tab) ZEN.assert( count > 0, "Randomized object is not an array") local res = { } for i = count,2,-1 do local r = (random_int16() % i)+1 table.insert(res,tab[r]) -- limit 16bit lenght for arrays table.remove(tab, r) end table.insert(res,tab[1]) return res end -- random and hashing operations When("create the random object of '' bits", function(n) empty'random object' local bits = tonumber(n) ZEN.assert(bits, 'Invalid number of bits: ' .. n) ACK.random_object = OCTET.random(math.ceil(bits / 8)) new_codec('random_object', { zentype = 'element' }) end ) When("create the random object of '' bytes",function(n) empty'random object' local bytes = math.ceil(tonumber(n)) ZEN.assert(bytes, 'Invalid number of bytes: ' .. n) ACK.random_object = OCTET.random(bytes) new_codec('random_object', { zentype = 'element' }) end ) When("randomize the '' array", function(arr) local A = ACK[arr] ZEN.assert(A, "Object not found: "..arr) -- ZEN.assert(ZEN.CODEC[arr].zentype == 'array', "Object is not an array: "..arr) ACK[arr] = shuffle_array_f(A) end) When("create the array of '' random objects", function(s) ZEN.assert(not ACK.array, "Cannot overwrite existing object: ".."array") ACK.array = { } for i = s,1,-1 do table.insert(ACK.array,OCTET.random(64)) end new_codec('array', { luatype = 'table', zentype = 'array'}) end) When("create the array of '' random objects of '' bits", function(s, b) empty'array' ACK.array = { } local q = tonumber(s) ZEN.assert(q, "Argument is not a number: "..s) local bits = tonumber(b) local bytes = math.ceil(bits/8) for i = q,1,-1 do table.insert(ACK.array,OCTET.random(bytes)) end new_codec('array', { luatype = 'table', zentype = 'array'}) end) When("create the array of '' random objects of '' bytes", function(s, b) empty'array' ACK.array = { } local q = tonumber(s) ZEN.assert(q, "Argument is not a number: "..s) local bytes = math.ceil(tonumber(b)) for i = q,1,-1 do table.insert(ACK.array,OCTET.random(bytes)) end new_codec('array', { luatype = 'table', zentype = 'array'}) end) When("create the array of '' random numbers", function(s) ZEN.assert(not ACK.array, "Cannot overwrite existing object: ".."array") ACK.array = { } for i = s,1,-1 do table.insert(ACK.array,tonumber(random_int16())) end new_codec('array', { luatype = 'table', zentype = 'array', encoding = 'number' }) end) When("create the array of '' random numbers modulo ''", function(s,m) ZEN.assert(not ACK.array, "Cannot overwrite existing object: ".."array") ACK.array = { } for i = s,1,-1 do table.insert(ACK.array,math.floor(random_int16() % m)) end new_codec('array', { luatype = 'table', zentype = 'array', encoding = 'number' }) end) When("pick the random object in ''", function(arr) local A = have(arr) empty'random object' ZEN.assert(luatype(A) == 'table', "Object is not a table: "..arr) local tmp = { } local keys = { } for k,v in pairs(A) do table.insert(keys, k) table.insert(tmp, v) end local r = (random_int16() % #tmp) +1 ACK.random_object = tmp[r] new_codec('random_object', {name=keys[r]}) end) When("create the random dictionary with '' random objects from ''", function(num, from) local n = tonumber(num) if not n then n = tonumber(have(num)) end ZEN.assert(n, "Not a number and object not found"..num) local src = have(from) local dst = { } ZEN.assert(luatype(src) == 'table', "Object is not a table: "..from) for k,v in pairs(src) do if n == 0 then break end if tonumber(k) then table.insert(dst, v) else dst[k] = v end n = n - 1 end ACK.random_dictionary = dst new_codec('random_dictionary') end)  --[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Alberto Lerda -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --]] -- Tables supplied as arguments are not changed. -- Table to hold statistical functions stats={} -- Get the mean value of a table function stats.average( t ) local zero = BIG.new(0) local one = BIG.new(1) local sum = zero local count = zero for k,v in pairs(t) do local t = type(v) if t == 'number' then v = BIG.from_decimal(tostring(v)) elseif iszen(t) then v = BIG.from_decimal(v:octet():string()) else error("Unknown type for number", 2) end if type(v) == 'zenroom.big' then local newsum = sum + v count = count + one ZEN.assert(newsum > sum, "Overflow in sum") sum = newsum end end ZEN.assert(count > zero, "No numbers in array") return (sum / count) end -- Get the variance of a table function stats.variance( t ) local zero = BIG.new(0) local one = BIG.new(1) local m local vm local sum = zero local count = zero local result m = stats.average( t ) for k,v in pairs(t) do local t = type(v) if t == 'number' then v = BIG.from_decimal(tostring(v)) elseif iszen(t) then v = BIG.from_decimal(v:octet():string()) else error("Unknown type for number", 2) end if type(v) == 'zenroom.big' then local newsum vm = v - m newsum = sum + (vm * vm) ZEN.assert(newsum > sum, "Overflow in sum") count = count + one sum = newsum end end ZEN.assert(count > one, "Not enough numbers (at least 2)") result = sum / (count-one) return result end function stats.standardDeviation( t ) return BIG.sqrt(stats.variance( t )) end return stats - --[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Alberto Lerda and Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local ecdh = require'ecdh' function ecdh.compress_public_key(public) local x, y = ECDH.pubxy(public) local pfx = fif( BIG.parity(BIG.new(y) ), OCTET.from_hex('03'), OCTET.from_hex('02') ) local pk = pfx .. x return pk end function ecdh.uncompress_public_key(public) local p = BIG.new(O.from_hex('fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f')) local e = BIG.new(O.from_hex('3fffffffffffffffffffffffffffffffffffffffffffffffffffffffbfffff0c')) local parity = public:sub(1,1) assert(parity == O.from_hex('02') or parity == O.from_hex('03')) local x = BIG.new(public:sub(2, #public)) -- y*y = x*x*x + 7 local rhs = BIG.mod(BIG.modmul(BIG.modmul(x,x,p),x,p)+BIG.new(7),p) local sqrt_rhs = rhs:modpower(e, p) assert(BIG.modmul(sqrt_rhs,sqrt_rhs, p) == rhs) if sqrt_rhs:parity() ~= (parity == O.from_hex('03')) then -- this is a xor sqrt_rhs = sqrt_rhs:modneg(p) end return O.from_hex('04') .. x .. sqrt_rhs end -- it is similar to sign eth, s < order/2 function ecdh.sign_ecdh(sk, data) local o = ECDH.order() local sig, y, sig_s sig, y = ECDH.sign_hashed(sk, data, #data) sig_s = INT.new(sig.s) if sig_s > INT.shr(o, 1) then sig_s = INT.modsub(o, sig_s, o) sig.s = sig_s:octet():pad(32) y = not y end return sig, y end -- Compute the compressed public key (pubc) from the secret key function ecdh.sk_to_pubc(sk) if not #sk == 32 then error("Invalid ecdh private key size: "..#sk) end return( ECDH.compress_public_key( ECDH.pubgen(sk) ) ) end return ecdh +--[[ --This file is part of zenroom -- --Copyright (C) 2018-2022 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 27th November 2021 --]] local stats = require('stats') -- array operations local function check_container(name) ZEN.assert(ACK[name], "Invalid container, not found: "..name) ZEN.assert(luatype(ACK[name]) == 'table', "Invalid container, not a table: "..name) if ZEN.CODEC[name] then ZEN.assert(ZEN.CODEC[name].zentype ~= 'element', "Invalid container: "..name.." is a "..ZEN.CODEC[name].zentype) else xxx("Object has no CODEC registration: "..name) end end local function check_element(name) local o = ACK[name] ZEN.assert(o, "Invalid element, not found: "..name) ZEN.assert(iszen(type(o)), "Invalid element, not a zenroom object: "..name.." ("..type(o)..")") if ZEN.CODEC[name] then ZEN.assert(ZEN.CODEC[name].zentype == 'element', "Invalid element: "..name.." is a "..ZEN.CODEC[name].zentype) else xxx("Object has no CODEC registration: "..name) end return o end local function _when_remove_dictionary(ele, from) -- ele is just the name (key) of object to remove local dict = have(from) ZEN.assert(dict, "Dictionary not found: "..from) if dict[ele] then ACK[from][ele] = nil -- remove from dictionary elseif ZEN.CODEC[ele].name ~= ele and dict[ZEN.CODEC[ele].name] then -- it may be a copy or random object with different name ACK[from][ZEN.CODEC[ele].name] = nil else error("Object not found in dictionary: "..ele.." in "..from) end end local function _when_remove_array(ele, from) local obj = have(ele) local arr = have(from) local found = false local newdest = { } for k,v in next,arr,nil do if not (v == obj) then table.insert(newdest,v) else found = true end end ZEN.assert(found, "Element to be removed not found in array") ACK[from] = newdest end When("remove the '' from ''", function(ele,from) local codec = ZEN.CODEC[from] ZEN.assert(codec, "No codec registration for target: "..from) if codec.zentype == 'dictionary' or codec.zentype == 'schema' then _when_remove_dictionary(ele, from) elseif codec.zentype == 'array' then _when_remove_array(ele, from) else I.warn({ CODEC = codec}) error("Invalid codec registration for target: "..from) end end) When("create the new array", function() ACK.new_array = { } new_codec('new array', {zentype='array', luatype='table'}) end) When("create the length of ''", function(arr) local obj = have(arr) ACK.length = #obj new_codec('length', {luatype='number',zentype='element'}) end) When("create the size of ''", function(arr) local obj = have(arr) ACK.size = #obj new_codec('size', {zentype='element',luatype='number'}) end) When("create the copy of element '' in array ''", function(pos, arr) ZEN.assert(ACK[arr], "No array found in: "..arr) ZEN.assert(isarray(ACK[arr]), "Not an array: "..arr) local num = tonumber(pos) ZEN.assert(num, "Argument is not a position number: "..pos) ZEN.assert(ACK[arr][num], "No element found in: "..arr.."["..pos.."]") ACK.copy = ACK[arr][num] -- TODO: support nested arrays or dictionaries new_codec('copy',{zentype='element',luatype=luatype(ACK.copy)},arr) end) When("insert string '' in ''", function(st, dest) local d = have(dest) ZEN.assert(luatype(d) == 'table', "Invalid destination, not a table: "..dest) ZEN.assert(ZEN.CODEC[dest].zentype == 'array', "Invalid destination, not an array: "..dest) table.insert(ACK[dest], O.from_string(st)) end) When("insert '' in ''", function(ele, dest) local d = have(dest) local e = have(ele) ZEN.assert(luatype(d) == 'table', "Invalid destination, not a table: "..dest) ZEN.assert(ZEN.CODEC[dest].zentype ~= 'element', "Invalid destination, not a container: "..dest) if ZEN.CODEC[dest].zentype == 'array' then table.insert(ACK[dest], e) elseif ZEN.CODEC[dest].zentype == 'dictionary' then ACK[dest][ele] = e elseif ZEN.CODEC[dest].zentype == 'schema' then ACK[dest][ele] = e else ZEN.assert(false, "Invalid destination type: " ..ZEN.CODEC[dest].zentype) end ZEN.CODEC[dest][ele] = ZEN.CODEC[ele] ACK[ele] = nil ZEN.CODEC[ele] = nil end) -- When("insert the '' in ''", function(ele,arr) -- ZEN.assert(ACK[ele], "Element not found: "..ele) -- ZEN.assert(ACK[arr], "Array not found: "..arr) -- ZEN.assert(ZEN.CODEC[arr].zentype == 'array', -- "Object is not an array: "..arr) -- table.insert(ACK[arr], ACK[ele]) -- end) IfWhen("the '' is not found in ''", function(ele, arr) local obj = ACK[ele] ZEN.assert(obj, "Element not found: "..ele) ZEN.assert(ACK[arr], "Array not found: "..arr) if ZEN.CODEC[arr].zentype == 'array' then for k,v in pairs(ACK[arr]) do ZEN.assert(v ~= obj, "Element '"..ele.."' is contained inside: "..arr) end elseif ZEN.CODEC[arr].zentype == 'dictionary' then for k,v in pairs(ACK[arr]) do local val = k if luatype(k) == 'string' then val = O.from_string(k) end ZEN.assert(val ~= obj, "Element '"..ele.."' is contained inside: "..arr) end else ZEN.assert(false, "Invalid container type: "..arr.." is "..ZEN.CODEC[arr].zentype) end end) IfWhen("the '' is found in ''", function(ele, arr) local obj = ACK[ele] ZEN.assert(obj, "Element not found: "..ele) ZEN.assert(ACK[arr], "Array not found: "..arr) local found = false if ZEN.CODEC[arr].zentype == 'array' then for k,v in pairs(ACK[arr]) do if v == obj then found = true end end elseif ZEN.CODEC[arr].zentype == 'dictionary' then for k,v in pairs(ACK[arr]) do local val = k if luatype(k) == 'string' then val = O.from_string(k) end if val == obj then found = true end end else ZEN.assert(false, "Invalid container type: "..arr.." is "..ZEN.CODEC[arr].zentype) end ZEN.assert(found, "The content of element '"..ele.."' is not found inside: "..arr) end) IfWhen("the '' is found in '' at least '' times", function(ele, arr, times) local obj = have(ele) ZEN.assert( luatype(obj) ~= 'table', "Invalid use of table in object comparison: "..ele) local num = have(times) ZEN.assert( luatype(num) == 'number', "Not a number: "..times) local list = have(arr) ZEN.assert( luatype(list) == 'table', "Not a table: "..arr) ZEN.assert( isarray(list), "Not an array: "..arr) local found = 0 for _,v in pairs(list) do if v == obj then found = found + 1 end end ZEN.assert(found >= num, "Object "..ele.." found only "..found.." times instead of "..num.." in array "..arr) end) local function _aggr_array(arr) local A = have(arr) local codec = ZEN.CODEC[arr] ZEN.assert(codec.zentype == 'array' or (codec.zentype == 'schema' and codec.encoding == 'array'), "Object is not a valid array: "..arr) local count = isarray(A) ZEN.assert( count > 0, "Array is empty or invalid: "..arr) local res, par if luatype(A[1]) == 'number' then res = 0 for k,v in next,A,nil do res = res + tonumber(v) end par = {encoding='number',zentype='element'} elseif type(A[1]) == 'zenroom.big' then res = BIG.new(0) for k,v in next,A,nil do res = res + v end par = {zentype = 'element'} elseif type(A[1]) == 'zenroom.ecp' then res = ECP.generator() for k,v in next,A,nil do res = res + v end par = {zentype = 'element'} elseif type(A[1]) == 'zenroom.ecp2' then res = ECP2.generator() for k,v in next,A,nil do res = res + v end par = {zentype = 'element'} else error("Unknown aggregation for type: "..type(A[1])) end return res, par end When("create the aggregation of array ''", function(arr) empty'aggregation' local params ACK.aggregation, params = _aggr_array(arr) new_codec('aggregation', params) end) When("create the sum value of elements in array ''", function(arr) empty'sum value' local params ACK.sum_value, params = _aggr_array(arr) new_codec('sum value', params) end) When("create the average of elements in array ''", function(arr) empty'average' local data = have(arr) ACK.average = O.from_string(stats.average(data):decimal()) new_codec('average', { encoding="string" }) end) When("create the variance of elements in array ''", function(arr) empty'variance' local data = have(arr) ACK.variance = O.from_string(stats.variance(data):decimal()) new_codec('variance', { encoding="string" }) end) When("create the standard deviation of elements in array ''", function(arr) empty'standard_deviation' local data = have(arr) ACK.standard_deviation = O.from_string(stats.standardDeviation(data):decimal()) new_codec('standard_deviation', { encoding="string" }) end) When("create the flat array of contents in ''", function(dic) local codec = ZEN.CODEC[dic] ZEN.assert(codec.zentype == 'array' or codec.zentype == 'dictionary', "Target is not a valid: "..dic) local data = have(dic) ZEN.assert(luatype(data) == 'table', "Invalid array: "..dic) empty'flat array' ACK.flat_array = {} deepmap(function(v, k, res) table.insert(res, v) end, data, ACK.flat_array) new_codec('flat array', { encoding="string" }) end) local function _keys_flat_array(data, res) for k, item in pairs(data) do if type(k) == 'string' then k = O.from_string(k) end table.insert(res, k) if luatype(item) == 'table' then _keys_flat_array(item, res) end end end When("create the flat array of keys in ''", function(dic) local codec = ZEN.CODEC[dic] ZEN.assert(codec.zentype == 'array' or codec.zentype == 'dictionary', "Target is not a valid: "..dic) local data = have(dic) ZEN.assert(luatype(data) == 'table', "Invalid target: "..dic) empty'flat array' ACK.flat_array = {} _keys_flat_array(data, ACK.flat_array) new_codec('flat array', { encoding="string" }) end) When("create the array of objects named by '' found in ''", function(name, dict) ZEN.assert(isdictionary(dict), "Second argument is not a dictionary") local n = have(name):octet():string() local src = have(dict) empty'array' ACK.array = { } deepmap(function(v,k,res) if k == n then table.insert(res, v) end end, src, ACK.array) new_codec('array', { encoding='string', zentype='array' }) end) --[[ --This file is part of zenroom -- --Copyright (C) 2019-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local _cbor = require('cbor') _cbor.decode = _cbor.raw_decode _cbor.encode = function(tab) -- encodes zencode types according to CODEC assert(luatype(tab) == 'table', "CBOR encode argument needs to be a table") local fun local res = { } for k,v in pairs(tab) do fun = guess_outcast( check_codec(k) ) if luatype(v) == 'table' then res[k] = deepmap(fun, v) else res[k] = fun(v) end end return _cbor.raw_encode( res ) end _cbor.auto = function(obj) local t = luatype(obj) if t == 'table' then -- export table to JSON return _cbor.encode(obj) elseif t == 'string' then -- import JSON string to table return _cbor.decode(obj) else error("CBOR.auto unrecognised input type: "..t, 3) return nil end end return _cbor --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Friday, 12th November 2021 --]] local J = require('json') J.decode = function(data) if not data then error("JSON.decode called without argument", 2) end assert(#data > 1,"JSON.decode argument is empty string") assert(luatype(data) == "string", "JSON.decode argument of unsopported type: "..luatype(data)) local res = {} local right = tostring(data) local left local tmp while right do left, right = jsontok(right) -- function in zen_parser.c if not left then break end tmp = JSON.raw_decode(left) if luatype(tmp) == 'table' then for k,v in pairs(tmp) do -- adds all unnamed array elements into 'array' if luatype(k)=='number' then res.array = fif(res.array, res.array, {}) table.insert(res.array, v) else res[k] = v end end else error("JSON decode has not returned a table", 2) end end return res end J.encode = function(tab,enc) return JSON.raw_encode( -- process encodes zencode types -- it is part of inspect.lua INSPECT.process(tab, enc or CONF.output.encoding.name) ) end J.auto = function(obj) local t = type(obj) if t == 'table' then -- export table to JSON return JSON.encode(obj) elseif t == 'string' then -- import JSON string to table return JSON.decode(obj) else error("JSON.auto unrecognised input type: "..t, 3) return nil end end return J !--[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Sunday, 11th July 2021 --]] -- generic comparison using overloaded __eq on values local function _eq(left, right) if luatype(left) == 'number' and luatype(right) == 'number' then return (left == right) elseif luatype(left) == 'table' and luatype(right) == 'table' then if(#left ~= #right) then return false end -- optimization return (ZEN.serialize(left) == ZEN.serialize(right)) elseif iszen(type(left)) and iszen(type(right)) then return (left:octet() == right:octet()) else error("Comparison between incompatible types: " ..type(left).." and "..type(right), 2) end end local function _neq(left, right) if luatype(left) == 'number' and luatype(right) == 'number' then return (left ~= right) elseif luatype(left) == 'table' and luatype(right) == 'table' then if(#left ~= #right) then return true end -- optimization return (ZEN.serialize(left) ~= ZEN.serialize(right)) elseif iszen(type(left)) and iszen(type(right)) then return (left:octet() ~= right:octet()) else error("Comparison between incompatible types: " ..type(left).." and "..type(right), 2) end end IfWhen( "verify '' is equal to ''", function(l, r) local left = have(l) local right = have(r) ZEN.assert( _eq(left, right), 'Verification fail: elements are not equal: ' .. l .. ' == ' .. r ) end ) IfWhen( "verify '' is not equal to ''", function(l, r) local left = have(l) local right = have(r) ZEN.assert( _neq(left, right), 'Verification fail: elements are equal: ' .. l .. ' == ' .. r ) end ) -- comparison inside dictionary IfWhen( "verify '' is equal to '' in ''", function(l, tr, tt) local left = have(l) local tab = have(tt) local right = tab[tr] ZEN.assert( _eq(left, right), 'Verification fail: elements are not equal: ' .. l .. ' == ' .. tt .. '.' .. tr ) end ) IfWhen( "verify '' is not equal to '' in ''", function(l, tr, tt) local left = have(l) local tab = have(tt) local right = tab[tr] ZEN.assert( _neq(left, right), 'Verification fail: elements are equal: ' .. l .. ' == ' .. tt .. '.' .. tr ) end ) -- check a tuple of numbers before comparison, convert to BIG or number local function numcheck(left, right) local al, ar -- if left == nil then error('1st argument of numerical comparison is nil', 2) end local tl = type(left) if not iszen(tl) then if tl ~= 'number' then error('1st argument invalid numeric type: ' .. tl, 2) end end if tl == 'zenroom.octet' then al = BIG.new(left) elseif tl == 'zenroom.big' or tl == 'number' then al = left else al = left:octet() end -- if right == nil then error('2nd argument of numerical comparison is nil', 2) end local tr = type(right) if not iszen(tr) then if tr ~= 'number' then error('2nd argument invalid numeric type: ' .. tr, 2) end end if tr == 'zenroom.octet' then ar = BIG.new(right) elseif tr == 'zenroom.big' or tr == 'number' then ar = right else ar = right:octet() end return al, ar end IfWhen( "number '' is less than ''", function(left, right) local l, r = numcheck(ACK[left], ACK[right]) ZEN.assert( l < r, 'Comparison fail: ' .. left .. ' is not less than ' .. right ) end ) IfWhen( "number '' is less or equal than ''", function(left, right) local l, r = numcheck(ACK[left], ACK[right]) ZEN.assert( l <= r, 'Comparison fail: ' .. left .. ' is not less or equal than ' .. right ) end ) IfWhen( "number '' is more than ''", function(left, right) local l, r = numcheck(ACK[left], ACK[right]) ZEN.assert( r < l, 'Comparison fail: ' .. left .. ' is not more than ' .. right ) end ) IfWhen( "number '' is more or equal than ''", function(left, right) local l, r = numcheck(ACK[left], ACK[right]) ZEN.assert( r <= l, 'Comparison fail: ' .. left .. ' is not more or equal than ' .. right ) end ) -- TODO: substitute with RFC2047 compliant code (take from jaromail) local function validemail(str) if str == nil then return nil end if (type(str) ~= 'string') then error('Expected string') return nil end local lastAt = str:find('[^%@]+$') local localPart = str:sub(1, (lastAt - 2)) -- Returns the substring before '@' symbol local domainPart = str:sub(lastAt, #str) -- Returns the substring after '@' symbol -- we werent able to split the email properly if localPart == nil then return nil, 'Local name is invalid' end if domainPart == nil then return nil, 'Domain is invalid' end -- local part is maxed at 64 characters if #localPart > 64 then return nil, 'Local name must be less than 64 characters' end -- domains are maxed at 253 characters if #domainPart > 253 then return nil, 'Domain must be less than 253 characters' end -- somthing is wrong if lastAt >= 65 then return nil, 'Invalid @ symbol usage' end if string.sub(domainPart, 1, 1) == '.' then return false, 'first character in domainPart is a dot' end -- quotes are only allowed at the beginning of a the local name local quotes = localPart:find('["]') if type(quotes) == 'number' and quotes > 1 then return nil, 'Invalid usage of quotes' end -- no @ symbols allowed outside quotes if localPart:find('%@+') and quotes == nil then return nil, 'Invalid @ symbol usage in local part' end -- no dot found in domain name if not domainPart:find('%.') then return nil, 'No TLD found in domain' end -- only 1 period in succession allowed if domainPart:find('%.%.') then return nil, 'Too many periods in domain' end if localPart:find('%.%.') then return nil, 'Too many periods in local part' end -- just a general match if not str:match('[%w]*[%p]*%@+[%w]*[%.]?[%w]*') then return nil, 'Email pattern test failed' end if (lastAt == nil) then lastAt = #str + 1 end -- all our tests passed, so we are ok return true end IfWhen( "verify '' is a email", function(name) local A = ACK[name] ZEN.assert(A, 'Object not found: ' .. name) local res, err = validemail(O.to_string(A)) ZEN.assert(res, err) end ) IfWhen( "verify '' contains a list of emails", function(name) local A = ACK[name] ZEN.assert(A, 'Object not found: ' .. name) ZEN.assert( luatype(A) == 'table', 'Object is not a container: ' .. name ) local res, err for k, v in pairs(A) do res, err = validemail(O.to_string(v)) ZEN.assert(res, (err or 'OK') .. ' on email: ' .. O.to_string(v)) end end ) IfWhen("the elements in '' are equal", function(obj_name) local obj = have(obj_name) local all_equal = true local first = nil local first_idx = nil for k,v in pairs(obj) do if first == nil then first = v first_idx = k else ZEN.assert(_eq(first, v), "Verification failed: the elements in position " .. k .. " and " .. first_idx .. "are not equal") end end end) IfWhen("the elements in '' are not equal", function(obj_name) local obj = have(obj_name) local first = nil local first_idx = nil for k,v in pairs(obj) do if first == nil then first = v first_idx = k else if _neq(first, v) then -- at least two elements are different return true end end end ZEN.assert(false, "Verification failed: all elements are equal") end) %2--[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Friday, 26th November 2021 --]] --- WHEN -- nop to terminate IF blocks When("done", function() end) IfWhen("'' is found", function(n) have(n) end) IfWhen("'' is not found", function(n) ZEN.assert(ACK[n] == nil, "Object should not be found: "..n) end) When("append '' to ''", function(src, dest) local val = have(src) local dst = have(dest) -- if the destination is a number, fix the encoding to string if luatype(dst) == 'number' then dst = tostring(dst) ZEN.CODEC[dest].encoding = "string" ZEN.CODEC[dest].luatype = "string" ZEN.CODEC[dest].zentype = "element" end dst = dst .. val if luatype(dst) == 'string' then ACK[dest] = O.from_string(dst) else ACK[dest] = dst end end) When("create the ''", function(dest) empty (dest) ACK[dest] = { } ZEN.CODEC[dest] = guess_conversion(ACK[dest], dest) ZEN.CODEC[dest].name = dest end) When("create the '' named ''", function(sch, name) empty(name) ACK[name] = { } ZEN.CODEC[name] = guess_conversion(ACK[name], sch) ZEN.CODEC[name].name = name end) -- simplified exception for I write: import encoding from_string ... When("write string '' in ''", function(content, dest) empty(dest) ACK[dest] = O.from_string(content) ZEN.CODEC[dest] = new_codec(dest, {encoding = 'string', luatype = 'string', zentype = 'element' }) end) -- ... and from a number When("write number '' in ''", function(content, dest) empty(dest) -- TODO: detect number base 10 local num = tonumber(content) ZEN.assert(num, "Cannot convert value to number: "..content) if num > 2147483647 then error('Overflow of number object over 32bit signed size') -- TODO: maybe support unsigned native here end ACK[dest] = num ZEN.CODEC[dest] = new_codec(dest, {encoding = 'number', luatype = 'number', zentype = 'element' }) end) When("create the number from ''", function(from) empty'number' local get = have(from) local num = tonumber(O.to_string(get)) ZEN.assert(num, "Cannot convert object to number: "..from) if num > 2147483647 then error('Overflow of number object over 32bit signed size') -- TODO: maybe support unsigned native here end ACK.number = num ZEN.CODEC.number = new_codec('number', {encoding = 'number', luatype = 'number', zentype = 'element' }) end) When("set '' to '' as ''", function(dest, content, format) empty(dest) local guess = input_encoding(format) guess.raw = content guess.name = dest if format == 'number' then ACK[dest] = tonumber( operate_conversion(guess) ) else ACK[dest] = operate_conversion(guess) end -- ZEN.CODEC[dest] = new_codec(dest, { luatype = luatype(ACK[dest]), zentype = 'element' }) end) When("create the cbor of ''", function(src) have(src) empty'cbor' ACK.cbor = OCTET.from_string( CBOR.encode(ACK[src]) ) end) When("create the json of ''", function(src) have(src) empty'json' ACK.json = OCTET.from_string( JSON.encode(ACK[src]) ) end) -- numericals When("set '' to '' base ''", function(dest, content, base) empty(dest) local bas = tonumber(base) ZEN.assert(bas, "Invalid numerical conversion for base: "..base) local num = tonumber(content,bas) ZEN.assert(num, "Invalid numerical conversion for value: "..content) ACK[dest] = num ZEN.CODEC[dest] = new_codec(dest, {encoding = 'number', luatype = 'number', zentype = 'element' }) end) local function _delete_f(name) have(name) ACK[name] = nil ZEN.CODEC[name] = nil end When("delete ''", _delete_f) When("remove ''", _delete_f) When("rename the '' to ''", function(old,new) have(old) empty(new) ACK[new] = ACK[old] ACK[old] = nil ZEN.CODEC[new] = ZEN.CODEC[old] ZEN.CODEC[old] = nil end) When("rename '' to ''", function(old,new) have(old) empty(new) ACK[new] = ACK[old] ACK[old] = nil ZEN.CODEC[new] = ZEN.CODEC[old] ZEN.CODEC[old] = nil end) When("rename the object named by '' to ''", function(old,new) local oldo = have(old) local olds = oldo:octet():string() have(olds) empty(new) ACK[new] = ACK[olds] ACK[olds] = nil ZEN.CODEC[new] = ZEN.CODEC[olds] ZEN.CODEC[olds] = nil end) When("rename '' to named by ''", function(old,new) have(old) local newo = have(new) local news = newo:octet():string() empty(news) ACK[news] = ACK[old] ACK[old] = nil ZEN.CODEC[news] = ZEN.CODEC[old] ZEN.CODEC[old] = nil end) When("rename the object named by '' to named by ''", function(old,new) local oldo = have(old) local olds = oldo:octet():string() have(olds) local newo = have(new) local news = newo:octet():string() empty(news) ACK[news] = ACK[olds] ACK[olds] = nil ZEN.CODEC[news] = ZEN.CODEC[olds] ZEN.CODEC[olds] = nil end) When("copy the '' to ''", function(old,new) have(old) empty(new) ACK[new] = deepcopy(ACK[old]) new_codec(new, { }, old) end) When("copy '' to ''", function(old,new) have(old) empty(new) ACK[new] = deepcopy(ACK[old]) new_codec(new, { }, old) end) When("copy contents of '' in ''", function(src,dst) local obj = have(src) have(dst) for k, v in pairs(obj) do ACK[dst][k] = v -- no deepcopy -- no new codec (using dst) end end) When("copy contents of '' named '' in ''", function(src,name,dst) local obj = have(src) have(dst) for k, v in pairs(obj) do if k == name then ACK[dst][k] = v -- no deepcopy end -- no new codec (using dst) end end) When("copy the '' in '' to ''", function(old,inside,new) ZEN.assert(ACK[inside][old], "Object not found: "..old.." inside "..inside) empty(new) ACK[new] = deepcopy(ACK[inside][old]) new_codec(new, { }, inside) end) When("split the rightmost '' bytes of ''", function(len, src) local obj = have(src) empty'rightmost' local s = tonumber(len) ZEN.assert(s, "Invalid number arg #1: "..type(len)) local l,r = OCTET.chop(obj,#obj-s) ACK.rightmost = r ACK[src] = l new_codec('rightmost', { }, src) end) When("split the leftmost '' bytes of ''", function(len, src) local obj = have(src) empty'leftmost' local s = tonumber(len) ZEN.assert(s, "Invalid number arg #1: "..type(len)) local l,r = OCTET.chop(obj,s) ACK.leftmost = l ACK[src] = r new_codec('leftmost', { }, src) end) local function _numinput(num) local t = type(num) if not iszen(t) then if t == 'table' then -- TODO: only numbers supported, not zenroom.big local aggr = 0 for _,v in pairs(num) do aggr = aggr + _numinput(v) end return aggr, false elseif t ~= 'number' then error('Invalid numeric type: ' .. t, 2) end return num, false end if t == 'zenroom.octet' then return BIG.new(num), true elseif t == 'zenroom.big' then return num, true else return BIG.new(num:octet()), true -- may give internal errors end error("Invalid number", 2) return nil, false end -- escape math function overloads for pointers local function _add(l,r) return(l + r) end local function _sub(l,r) return(l - r) end local function _mul(l,r) return(l * r) end local function _div(l,r) return(l / r) end local function _mod(l,r) return(l % r) end local function _math_op(op, l, r) local left, lz = _numinput(l) local right, rz = _numinput(r) if lz ~= rz then error("Incompatible numeric arguments", 2) end local codec ACK.result = true -- new_codec checks existance if lz and rz then codec = new_codec('result', {encoding = CONF.output.encoding.name, luatype = 'string', zentype = 'big' }) else codec = new_codec('result', {encoding = 'number', luatype = 'number', zentype = 'element' }) end return op(left, right), codec end When("create the result of '' inverted sign", function(left) local l = have(left) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_sub, 0, l) end) When("create the result of '' + ''", function(left,right) local l = have(left) local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_add, l, r) end) When("create the result of '' in '' + ''", function(left, dict, right) local d = have(dict) local l = d[left] local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_add, l, r) end) When("create the result of '' in '' + '' in ''", function(left, ldict, right, rdict) local ld = have(ldict) local l = ld[left] local rd = have(rdict) local r = rd[right] empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_add, l, r) end) When("create the result of '' - ''", function(left,right) local l = have(left) local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_sub, l, r) end) When("create the result of '' in '' - ''", function(left, dict, right) local d = have(dict) local l = d[left] local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_sub, l, r) end) When("create the result of '' in '' - '' in ''", function(left, ldict, right, rdict) local ld = have(ldict) local l = ld[left] local rd = have(rdict) local r = rd[right] empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_sub, l, r) end) When("create the result of '' * ''", function(left,right) local l = have(left) local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_mul, l, r) end) When("create the result of '' in '' * ''", function(left, dict, right) local d = have(dict) local l = d[left] local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_mul, l, r) end) When("create the result of '' * '' in ''", function(left, right, dict) local l = have(left) local d = have(dict) local r = d[right] empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_mul, l, r) end) When("create the result of '' in '' * '' in ''", function(left, ldict, right, rdict) local ld = have(ldict) local l = ld[left] local rd = have(rdict) local r = rd[right] empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_mul, l, r) end) When("create the result of '' / ''", function(left,right) local l = have(left) local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_div, l, r) end) When("create the result of '' in '' / ''", function(left, dict, right) local d = have(dict) local l = d[left] local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_div, l, r) end) When("create the result of '' / '' in ''", function(left, right, dict) local l = have(left) local d = have(dict) local r = d[right] empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_div, l, r) end) When("create the result of '' in '' / '' in ''", function(left, ldict, right, rdict) local ld = have(ldict) local l = ld[left] local rd = have(rdict) local r = rd[right] empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_div, l, r) end) When("create the result of '' % ''", function(left,right) local l = have(left) local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_mod, l, r) end) When("create the result of '' in '' % ''", function(left, dict, right) local d = have(dict) local l = d[left] local r = have(right) empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_mod, l, r) end) When("create the result of '' in '' % '' in ''", function(left, ldict, right, rdict) local ld = have(ldict) local l = ld[left] local rd = have(rdict) local r = rd[right] empty 'result' ACK.result, ZEN.CODEC.result = _math_op(_mod, l, r) end) -- TODO: -- When("set '' as '' with ''", function(dest, format, content) end) -- When("append '' as '' to ''", function(content, format, dest) end) -- When("write '' as '' in ''", function(content, dest) end) -- implicit conversion as string -- https://github.com/dyne/Zenroom/issues/175 When("remove zero values in ''", function(target) have(target) ACK[target] = deepmap(function(v) if luatype(v) == 'number' then if v == 0 then return nil else return v end else return v end end, ACK[target]) end) -- When("remove all empty strings in ''", function(target) -- have(target) -- ACK[target] = deepmap(function(v) if trim(v) == '' then return nil end, ACK[target]) -- end) --[[ --This file is part of zenroom -- --Copyright (C) 2019-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local bench = { } bench.entropy = function() act("Benchmark: entropy of random generators (Shannon ratios)") -- use standard ECP size local s = #ECP.random():octet() return { SEED = RNGSEED:entropy(), PRNG = OCTET.random(256):entropy(), OCTET = OCTET.random(s):entropy(), BIG = BIG.random():octet():entropy(), ECP = ECP.random():octet():entropy(), ECP2 = ECP2.random():octet():entropy() } end bench.random_hamming_freq = function (s, q) local _s = s or 97 local _q = q or 5000 act("Benchmark: hamming distance between random, arguments: ".._s.." ".._q) -- ECP coordinates are 97 bytes local new = O.random(_s) local tot = 0 local old for i=_q,1,-1 do old = new new = O.random(_s) tot = tot + O.hamming(old,new) end return tot / _q end bench.random_kdf = function() act("Benchmark: KDF2 SHA256 and SHA512 on random") -- KDF2 input can be any, output local r = O.random(64) HASH.kdf2(HASH.new('SHA256'),r) HASH.kdf2(HASH.new('SHA512'),r) end -- find primes local square = {} for i=0,9 do square[i]=i*i end local function sqrsum(n) local sum = 0 while n > 0 do sum, n = sum + square[n % 10], math.floor(n / 10) end return sum end local function isHappy(n) while n ~= 1 and n ~= 4 do n = sqrsum(n) end return n == 1 end local prime_numbers = { 2, 3 } local function isPrime(n) if n == 1 then return true end for _,i in ipairs(prime_numbers) do if n == i then return true end if n%i == 0 then return false end end for i = prime_numbers[#prime_numbers], math.floor(n/2)+1, 2 do if n%i == 0 then return false end end if n > prime_numbers[#prime_numbers] then table.insert(prime_numbers, n) end return true end bench.math = function(a, b, c) local _a = a or 50000 local _b = b or _a+50000 local _c = c or 1 act("Benchmark: math based prime number, args: ".._a.." ".._b.." ".._c) local res = { } for n=_a,_b,_c do if isHappy(n) and isPrime(n) then table.insert(res, n) end end return res end function bench.bit32(N) N = N or 1000 act("Benchmark: bit32 based Mandelbrot generation, iterations: "..N) local bit = bit32 local bor, band = bit.bor, bit.band local shl, shr, rol = bit.lshift, bit.rshift, bit.lrotate local char, unpack = string.char, table.unpack local M, buf = 2/N, {} for y=0,N-1 do local Ci, b, p = y*M-1, -16777216, 0 local Ciq = Ci*Ci for x=0,N-1,2 do local Cr, Cr2 = x*M-1.5, (x+1)*M-1.5 local Zr, Zi, Zrq, Ziq = Cr, Ci, Cr*Cr, Ciq local Zr2, Zi2, Zrq2, Ziq2 = Cr2, Ci, Cr2*Cr2, Ciq b = rol(b, 2) for i=1,49 do Zi = Zr*Zi*2 + Ci; Zi2 = Zr2*Zi2*2 + Ci Zr = Zrq-Ziq + Cr; Zr2 = Zrq2-Ziq2 + Cr2 Ziq = Zi*Zi; Ziq2 = Zi2*Zi2 Zrq = Zr*Zr; Zrq2 = Zr2*Zr2 if band(b, 2) ~= 0 and Zrq+Ziq > 4.0 then b = band(b, -3) end if band(b, 1) ~= 0 and Zrq2+Ziq2 > 4.0 then b = band(b, -2) end if band(b, 3) == 0 then break end end if b >= 0 then p = p + 1; buf[p] = b; b = -16777216; end end if b ~= -16777216 then if band(N, 1) ~= 0 then b = shr(b, 1) end p = p + 1; buf[p] = shl(b, 8-band(N, 7)) end -- write(char(unpack(buf, 1, p))) -- write('.') end -- print('.') end return bench --[[ --This file is part of zenroom -- --Copyright (C) 2022 Dyne.org foundation --designed, written and maintained by Alberto Lerda and Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --]] local SCH = require'crypto_schnorr_signature' local function schnorr_public_key_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( SCH.pubcheck(res), 'Schnorr public key is not valid' ) return res end local function schnorr_signature_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( SCH.sigcheck(res), 'Schnorr signature is not valid' ) return res end -- check various locations to find the public key -- Given I have a 's' from 't' --> ACK.s[t] local function _pubkey_compat(_key) local pubkey = ACK[_key] if not pubkey then local pubkey_arr = ACK.schnorr_public_key if luatype(pubkey_arr) == 'table' then pubkey = pubkey_arr[_key] else pubkey = pubkey_arr end ZEN.assert( pubkey, 'Public key not found for: ' .. _key ) end return pubkey end ZEN.add_schema( { schnorr_public_key = schnorr_public_key_f, schnorr_signature = schnorr_signature_f } ) -- generate the private key When('create the schnorr key',function() initkeyring'schnorr' ACK.keyring.schnorr = SCH.keygen() end) -- generate the public key When('create the schnorr public key',function() empty'schnorr public key' local sk = havekey'schnorr' ACK.schnorr_public_key = SCH.pubgen(sk) new_codec('schnorr public key', { zentype = 'element'}) end) When("create the schnorr public key with secret key ''",function(sec) local sk = have(sec) initkeyring'schnorr' ACK.keyring.schnorr = sk empty'schnorr public key' ACK.schnorr_public_key = SCH.pubgen(sk) new_codec('schnorr public key', { zentype = 'element'}) end) When("create the schnorr key with secret key ''",function(sec) local sk = have(sec) initkeyring'schnorr' SCH.pubgen(sk) -- use pubgen as check ACK.keyring.schnorr = sk end) When("create the schnorr key with secret ''",function(sec) local sk = have(sec) initkeyring'schnorr' SCH.pubgen(sk) -- use pubgen as check ACK.keyring.schnorr = sk end) -- generate the sign for a msg and verify When("create the schnorr signature of ''",function(doc) local sk = havekey'schnorr' local obj = have(doc) empty'schnorr signature' ACK.schnorr_signature = SCH.sign(sk, ZEN.serialize(obj)) new_codec('schnorr signature', { zentype = 'element'}) end) IfWhen("verify the '' has a schnorr signature in '' by ''",function(doc, sig, by) local pk = _pubkey_compat(by) local obj = have(doc) local s = have(sig) ZEN.assert( SCH.verify(pk, ZEN.serialize(obj), s), 'The schnorr signature by '..by..' is not authentic' ) end) 8-- Concise Binary Object Representation (CBOR) -- RFC 7049 -- local function softreq(pkg, field) -- -- local ok, mod = pcall(require, pkg); -- -- if not ok then return end -- if field then return [field]; end -- return mod; -- end -- local dostring = function (s) -- local ok, f = pcall(loadstring or load, s); -- luacheck: read globals loadstring -- if ok and f then return f(); end -- end local setmetatable = setmetatable; local getmetatable = getmetatable; local dbg_getmetatable = debug.getmetatable; local assert = assert; local error = error; local type = type; local pairs = pairs; local ipairs = ipairs; local tostring = tostring; local s_char = string.char; local t_concat = table.concat; local t_sort = table.sort; local m_floor = math.floor; local m_abs = math.abs; local m_huge = math.huge; local m_max = math.max; local maxint = math.maxinteger or 9007199254740992; local minint = math.mininteger or -9007199254740992; local NaN = 0/0; local m_frexp = math.frexp; local m_ldexp = math.ldexp or function (x, exp) return x * 2.0 ^ exp; end; local m_type = math.type or function (n) return n % 1 == 0 and n <= maxint and n >= minint and "integer" or "float" end; local s_pack = string.pack -- or softreq("struct", "pack"); local s_unpack = string.unpack -- or softreq("struct", "unpack"); local b_rshift = bit32.rshift -- softreq("bit32", "rshift") or softreq("bit", "rshift") or -- dostring "return function(a,b) return a >> b end" or -- function (a, b) return m_max(0, m_floor(a / (2 ^ b))); end; -- sanity check if s_pack and s_pack(">I2", 0) ~= "\0\0" then s_pack = nil; end if s_unpack and s_unpack(">I2", "\1\2\3\4") ~= 0x102 then s_unpack = nil; end local encoder = {}; local function encode(obj, opts) return encoder[type(obj)](obj, opts); end -- Major types 0, 1 and length encoding for others local function integer(num, m) if m == 0 and num < 0 then -- negative integer, major type 1 num, m = - num - 1, 32; end if num < 24 then return s_char(m + num); elseif num < 2 ^ 8 then return s_char(m + 24, num); elseif num < 2 ^ 16 then return s_char(m + 25, b_rshift(num, 8), num % 0x100); elseif num < 2 ^ 32 then return s_char(m + 26, b_rshift(num, 24) % 0x100, b_rshift(num, 16) % 0x100, b_rshift(num, 8) % 0x100, num % 0x100); elseif num < 2 ^ 64 then local high = m_floor(num / 2 ^ 32); num = num % 2 ^ 32; return s_char(m + 27, b_rshift(high, 24) % 0x100, b_rshift(high, 16) % 0x100, b_rshift(high, 8) % 0x100, high % 0x100, b_rshift(num, 24) % 0x100, b_rshift(num, 16) % 0x100, b_rshift(num, 8) % 0x100, num % 0x100); end error "int too large"; end if s_pack then function integer(num, m) local fmt; m = m or 0; if num < 24 then fmt, m = ">B", m + num; elseif num < 256 then fmt, m = ">BB", m + 24; elseif num < 65536 then fmt, m = ">BI2", m + 25; elseif num < 4294967296 then fmt, m = ">BI4", m + 26; else fmt, m = ">BI8", m + 27; end return s_pack(fmt, m, num); end end local simple_mt = {}; function simple_mt:__tostring() return self.name or ("simple(%d)"):format(self.value); end function simple_mt:__tocbor() return self.cbor or integer(self.value, 224); end local function simple(value, name, cbor) assert(value >= 0 and value <= 255, "bad argument #1 to 'simple' (integer in range 0..255 expected)"); return setmetatable({ value = value, name = name, cbor = cbor }, simple_mt); end local tagged_mt = {}; function tagged_mt:__tostring() return ("%d(%s)"):format(self.tag, tostring(self.value)); end function tagged_mt:__tocbor() return integer(self.tag, 192) .. encode(self.value); end local function tagged(tag, value) assert(tag >= 0, "bad argument #1 to 'tagged' (positive integer expected)"); return setmetatable({ tag = tag, value = value }, tagged_mt); end local null = simple(22, "null"); -- explicit null local undefined = simple(23, "undefined"); -- undefined or nil local BREAK = simple(31, "break", "\255"); -- Number types dispatch function encoder.number(num) return encoder[m_type(num)](num); end -- Major types 0, 1 function encoder.integer(num) if num < 0 then return integer(-1 - num, 32); end return integer(num, 0); end -- Major type 7 function encoder.float(num) if num ~= num then -- NaN shortcut return "\251\127\255\255\255\255\255\255\255"; end local sign = (num > 0 or 1 / num > 0) and 0 or 1; num = m_abs(num) if num == m_huge then return s_char(251, sign * 128 + 128 - 1) .. "\240\0\0\0\0\0\0"; end local fraction, exponent = m_frexp(num) if fraction == 0 then return s_char(251, sign * 128) .. "\0\0\0\0\0\0\0"; end fraction = fraction * 2; exponent = exponent + 1024 - 2; if exponent <= 0 then fraction = fraction * 2 ^ (exponent - 1) exponent = 0; else fraction = fraction - 1; end return s_char(251, sign * 2 ^ 7 + m_floor(exponent / 2 ^ 4) % 2 ^ 7, exponent % 2 ^ 4 * 2 ^ 4 + m_floor(fraction * 2 ^ 4 % 0x100), m_floor(fraction * 2 ^ 12 % 0x100), m_floor(fraction * 2 ^ 20 % 0x100), m_floor(fraction * 2 ^ 28 % 0x100), m_floor(fraction * 2 ^ 36 % 0x100), m_floor(fraction * 2 ^ 44 % 0x100), m_floor(fraction * 2 ^ 52 % 0x100) ) end if s_pack then function encoder.float(num) return s_pack(">Bd", 251, num); end end -- Major type 2 - byte strings function encoder.bytestring(s) return integer(#s, 64) .. s; end -- Major type 3 - UTF-8 strings function encoder.utf8string(s) return integer(#s, 96) .. s; end -- Lua strings are byte strings encoder.string = encoder.bytestring; function encoder.boolean(bool) return bool and "\245" or "\244"; end encoder["nil"] = function() return "\246"; end function encoder.userdata(ud, opts) local mt = dbg_getmetatable(ud); if mt then local encode_ud = opts and opts[mt] or mt.__tocbor; if encode_ud then return encode_ud(ud, opts); end end error "can't encode userdata"; end function encoder.table(t, opts) local mt = getmetatable(t); if mt then local encode_t = opts and opts[mt] or mt.__tocbor; if encode_t then return encode_t(t, opts); end end -- the table is encoded as an array iff when we iterate over it, -- we see successive integer keys starting from 1. The lua -- language doesn't actually guarantee that this will be the case -- when we iterate over a table with successive integer keys, but -- due an implementation detail in PUC Rio Lua, this is what we -- usually observe. See the Lua manual regarding the # (length) -- operator. In the case that this does not happen, we will fall -- back to a map with integer keys, which becomes a bit larger. local array, map, i, p = { integer(#t, 128) }, { "\191" }, 1, 2; local is_array = true; for k, v in pairs(t) do is_array = is_array and i == k; i = i + 1; local encoded_v = encode(v, opts); array[i] = encoded_v; map[p], p = encode(k, opts), p + 1; map[p], p = encoded_v, p + 1; end -- map[p] = "\255"; map[1] = integer(i - 1, 160); return t_concat(is_array and array or map); end -- Array or dict-only encoders, which can be set as __tocbor metamethod function encoder.array(t, opts) local array = { }; for i, v in ipairs(t) do array[i] = encode(v, opts); end return integer(#array, 128) .. t_concat(array); end function encoder.map(t, opts) local map, p, len = { "\191" }, 2, 0; for k, v in pairs(t) do map[p], p = encode(k, opts), p + 1; map[p], p = encode(v, opts), p + 1; len = len + 1; end -- map[p] = "\255"; map[1] = integer(len, 160); return t_concat(map); end encoder.dict = encoder.map; -- COMPAT function encoder.ordered_map(t, opts) local map = {}; if not t[1] then -- no predefined order local i = 0; for k in pairs(t) do i = i + 1; map[i] = k; end t_sort(map); end for i, k in ipairs(t[1] and t or map) do map[i] = encode(k, opts) .. encode(t[k], opts); end return integer(#map, 160) .. t_concat(map); end -- stringify the function hex address encoder['function'] = function(f) local val = strtok(tostring(f))[2] return integer(#val, 64) .. val end -- Decoder -- Reads from a file-handle like object local function read_bytes(fh, len) return fh:read(len); end local function read_byte(fh) return fh:read(1):byte(); end local function read_length(fh, mintyp) if mintyp < 24 then return mintyp; elseif mintyp < 28 then local out = 0; for _ = 1, 2 ^ (mintyp - 24) do out = out * 256 + read_byte(fh); end return out; else error "invalid length"; end end local decoder = {}; local function read_type(fh) local byte = read_byte(fh); return b_rshift(byte, 5), byte % 32; end local function read_object(fh, opts) local typ, mintyp = read_type(fh); return decoder[typ](fh, mintyp, opts); end local function read_integer(fh, mintyp) return read_length(fh, mintyp); end local function read_negative_integer(fh, mintyp) return -1 - read_length(fh, mintyp); end local function read_string(fh, mintyp) if mintyp ~= 31 then return read_bytes(fh, read_length(fh, mintyp)); end local out = {}; local i = 1; local v = read_object(fh); while v ~= BREAK do out[i], i = v, i + 1; v = read_object(fh); end return t_concat(out); end local function read_unicode_string(fh, mintyp) return read_string(fh, mintyp); -- local str = read_string(fh, mintyp); -- if have_utf8 and not utf8.len(str) then -- TODO How to handle this? -- end -- return str; end local function read_array(fh, mintyp, opts) local out = {}; if mintyp == 31 then local i = 1; local v = read_object(fh, opts); while v ~= BREAK do out[i], i = v, i + 1; v = read_object(fh, opts); end else local len = read_length(fh, mintyp); for i = 1, len do out[i] = read_object(fh, opts); end end return out; end local function read_map(fh, mintyp, opts) local out = {}; local k; if mintyp == 31 then local i = 1; k = read_object(fh, opts); while k ~= BREAK do out[k], i = read_object(fh, opts), i + 1; k = read_object(fh, opts); end else local len = read_length(fh, mintyp); for _ = 1, len do k = read_object(fh, opts); out[k] = read_object(fh, opts); end end return out; end local tagged_decoders = {}; local function read_semantic(fh, mintyp, opts) local tag = read_length(fh, mintyp); local value = read_object(fh, opts); local postproc = opts and opts[tag] or tagged_decoders[tag]; if postproc then return postproc(value); end return tagged(tag, value); end local function read_half_float(fh) local exponent = read_byte(fh); local fraction = read_byte(fh); local sign = exponent < 128 and 1 or -1; -- sign is highest bit fraction = fraction + (exponent * 256) % 1024; -- copy two(?) bits from exponent to fraction exponent = b_rshift(exponent, 2) % 32; -- remove sign bit and two low bits from fraction; if exponent == 0 then return sign * m_ldexp(fraction, -24); elseif exponent ~= 31 then return sign * m_ldexp(fraction + 1024, exponent - 25); elseif fraction == 0 then return sign * m_huge; else return NaN; end end local function read_float(fh) local exponent = read_byte(fh); local fraction = read_byte(fh); local sign = exponent < 128 and 1 or -1; -- sign is highest bit exponent = exponent * 2 % 256 + b_rshift(fraction, 7); fraction = fraction % 128; fraction = fraction * 256 + read_byte(fh); fraction = fraction * 256 + read_byte(fh); if exponent == 0 then return sign * m_ldexp(exponent, -149); elseif exponent ~= 0xff then return sign * m_ldexp(fraction + 2 ^ 23, exponent - 150); elseif fraction == 0 then return sign * m_huge; else return NaN; end end local function read_double(fh) local exponent = read_byte(fh); local fraction = read_byte(fh); local sign = exponent < 128 and 1 or -1; -- sign is highest bit exponent = exponent % 128 * 16 + b_rshift(fraction, 4); fraction = fraction % 16; fraction = fraction * 256 + read_byte(fh); fraction = fraction * 256 + read_byte(fh); fraction = fraction * 256 + read_byte(fh); fraction = fraction * 256 + read_byte(fh); fraction = fraction * 256 + read_byte(fh); fraction = fraction * 256 + read_byte(fh); if exponent == 0 then return sign * m_ldexp(exponent, -149); elseif exponent ~= 0xff then return sign * m_ldexp(fraction + 2 ^ 52, exponent - 1075); elseif fraction == 0 then return sign * m_huge; else return NaN; end end if s_unpack then function read_float(fh) return s_unpack(">f", read_bytes(fh, 4)) end function read_double(fh) return s_unpack(">d", read_bytes(fh, 8)) end end local function read_simple(fh, value, opts) if value == 24 then value = read_byte(fh); end if value == 20 then return false; elseif value == 21 then return true; elseif value == 22 then return null; elseif value == 23 then return undefined; elseif value == 25 then return read_half_float(fh); elseif value == 26 then return read_float(fh); elseif value == 27 then return read_double(fh); elseif value == 31 then return BREAK; end if opts and opts.simple then return opts.simple(value); end return simple(value); end decoder[0] = read_integer; decoder[1] = read_negative_integer; decoder[2] = read_string; decoder[3] = read_unicode_string; decoder[4] = read_array; decoder[5] = read_map; decoder[6] = read_semantic; decoder[7] = read_simple; -- opts.more(n) -> want more data -- opts.simple -> decode simple value -- opts[int] -> tagged decoder local function decode(s, opts) local fh = {}; local pos = 1; local more; if type(opts) == "function" then more = opts; elseif type(opts) == "table" then more = opts.more; elseif opts ~= nil then error(("bad argument #2 to 'decode' (function or table expected, got %s)"):format(type(opts))); end if type(more) ~= "function" then function more() error "input too short"; end end function fh:read(bytes) local ret = s:sub(pos, pos + bytes - 1); if #ret < bytes then ret = more(bytes - #ret, fh, opts); if ret then self:write(ret); end return self:read(bytes); end pos = pos + bytes; return ret; end function fh:write(bytes) -- luacheck: no self s = s .. bytes; if pos > 256 then s = s:sub(pos + 1); pos = 1; end return #bytes; end return read_object(fh, opts); end return { -- en-/decoder functions raw_encode = encode; raw_decode = decode; -- tables of per-type en-/decoders type_encoders = encoder; type_decoders = decoder; -- special treatment for tagged values tagged_decoders = tagged_decoders; -- constructors for annotated types simple = simple; tagged = tagged; -- pre-defined simple values null = null; undefined = undefined; }; S2local strformat = string.format local floor = math.floor local function idiv(n, d) return floor(n / d) end local c_locale = { abday = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; day = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}; abmon = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; mon = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}; am_pm = {"AM", "PM"}; } --- ISO-8601 week logic -- ISO 8601 weekday as number with Monday as 1 (1-7) local function iso_8601_weekday(wday) if wday == 1 then return 7 else return wday - 1 end end local iso_8601_week do -- Years that have 53 weeks according to ISO-8601 local long_years = {} for _, v in ipairs { 4, 9, 15, 20, 26, 32, 37, 43, 48, 54, 60, 65, 71, 76, 82, 88, 93, 99, 105, 111, 116, 122, 128, 133, 139, 144, 150, 156, 161, 167, 172, 178, 184, 189, 195, 201, 207, 212, 218, 224, 229, 235, 240, 246, 252, 257, 263, 268, 274, 280, 285, 291, 296, 303, 308, 314, 320, 325, 331, 336, 342, 348, 353, 359, 364, 370, 376, 381, 387, 392, 398 } do long_years[v] = true end local function is_long_year(year) return long_years[year % 400] end function iso_8601_week(self) local wday = iso_8601_weekday(self.wday) local n = self.yday - wday local year = self.year if n < -3 then year = year - 1 if is_long_year(year) then return year, 53, wday else return year, 52, wday end elseif n >= 361 and not is_long_year(year) then return year + 1, 1, wday else return year, idiv(n + 10, 7), wday end end end --- Specifiers local t = {} function t:a(locale) return "%s", locale.abday[self.wday] end function t:A(locale) return "%s", locale.day[self.wday] end function t:b(locale) return "%s", locale.abmon[self.month] end function t:B(locale) return "%s", locale.mon[self.month] end function t:c(locale) return "%.3s %.3s%3d %.2d:%.2d:%.2d %d", locale.abday[self.wday], locale.abmon[self.month], self.day, self.hour, self.min, self.sec, self.year end -- Century function t:C() return "%02d", idiv(self.year, 100) end function t:d() return "%02d", self.day end -- Short MM/DD/YY date, equivalent to %m/%d/%y function t:D() return "%02d/%02d/%02d", self.month, self.day, self.year % 100 end function t:e() return "%2d", self.day end -- Short YYYY-MM-DD date, equivalent to %Y-%m-%d function t:F() return "%d-%02d-%02d", self.year, self.month, self.day end -- Week-based year, last two digits (00-99) function t:g() return "%02d", iso_8601_week(self) % 100 end -- Week-based year function t:G() return "%d", iso_8601_week(self) end t.h = t.b function t:H() return "%02d", self.hour end function t:I() return "%02d", (self.hour-1) % 12 + 1 end function t:j() return "%03d", self.yday end function t:m() return "%02d", self.month end function t:M() return "%02d", self.min end -- New-line character ('\n') function t:n() -- luacheck: ignore 212 return "\n" end function t:p(locale) return self.hour < 12 and locale.am_pm[1] or locale.am_pm[2] end -- TODO: should respect locale function t:r(locale) return "%02d:%02d:%02d %s", (self.hour-1) % 12 + 1, self.min, self.sec, self.hour < 12 and locale.am_pm[1] or locale.am_pm[2] end -- 24-hour HH:MM time, equivalent to %H:%M function t:R() return "%02d:%02d", self.hour, self.min end function t:s() return "%d", self:timestamp() end function t:S() return "%02d", self.sec end -- Horizontal-tab character ('\t') function t:t() -- luacheck: ignore 212 return "\t" end -- ISO 8601 time format (HH:MM:SS), equivalent to %H:%M:%S function t:T() return "%02d:%02d:%02d", self.hour, self.min, self.sec end function t:u() return "%d", iso_8601_weekday(self.wday) end -- Week number with the first Sunday as the first day of week one (00-53) function t:U() return "%02d", idiv(self.yday - self.wday + 7, 7) end -- ISO 8601 week number (00-53) function t:V() return "%02d", select(2, iso_8601_week(self)) end -- Weekday as a decimal number with Sunday as 0 (0-6) function t:w() return "%d", self.wday - 1 end -- Week number with the first Monday as the first day of week one (00-53) function t:W() return "%02d", idiv(self.yday - iso_8601_weekday(self.wday) + 7, 7) end -- TODO make t.x and t.X respect locale t.x = t.D t.X = t.T function t:y() return "%02d", self.year % 100 end function t:Y() return "%d", self.year end -- TODO timezones function t:z() -- luacheck: ignore 212 return "+0000" end function t:Z() -- luacheck: ignore 212 return "GMT" end -- A literal '%' character. t["%"] = function(self) -- luacheck: ignore 212 return "%%" end local function strftime(format_string, timetable) return (string.gsub(format_string, "%%([EO]?)(.)", function(locale_modifier, specifier) local func = t[specifier] if func then return strformat(func(timetable, c_locale)) else error("invalid conversation specifier '%"..locale_modifier..specifier.."'", 3) end end)) end local function asctime(timetable) -- Equivalent to the format string "%c\n" return strformat(t.c(timetable, c_locale)) .. "\n" end local strformat = string.format local mon_lengths = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} -- Number of days in year until start of month; not corrected for leap years local months_to_days_cumulative = {0} for i = 2, 12 do months_to_days_cumulative[i] = months_to_days_cumulative[i-1] + mon_lengths[i-1] end -- For Sakamoto's Algorithm (day of week) local sakamoto = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4}; local function is_leap(y) if (y % 4) ~= 0 then return false elseif (y % 100) ~= 0 then return true else return (y % 400) == 0 end end local function month_length(m, y) if m == 2 then return is_leap(y) and 29 or 28 else return mon_lengths[m] end end local function leap_years_since(year) return idiv(year, 4) - idiv(year, 100) + idiv(year, 400) end local function day_of_year(day, month, year) local yday = months_to_days_cumulative[month] if month > 2 and is_leap(year) then yday = yday + 1 end return yday + day end local function day_of_week(day, month, year) if month < 3 then year = year - 1 end return(year + leap_years_since(year) + sakamoto[month] + day) % 7 + 1 end local function borrow(tens, units, base) local frac = tens % 1 units = units + frac * base tens = tens - frac return tens, units end local function carry(tens, units, base) if units >= base then tens = tens + idiv(units, base) units = units % base elseif units < 0 then tens = tens + idiv(units, base) units = (base + units) % base end return tens, units end -- Modify parameters so they all fit within the "normal" range local function normalise(year, month, day, hour, min, sec) -- `month` and `day` start from 1, need -1 and +1 so it works modulo month, day = month - 1, day - 1 -- Convert everything (except seconds) to an integer -- by propagating fractional components down. year , month = borrow(year , month, 12) -- Carry from month to year first, so we get month length correct in next line around leap years year , month = carry(year, month, 12) month, day = borrow(month, day , month_length(floor(month + 1), year)) day , hour = borrow(day , hour , 24) hour , min = borrow(hour , min , 60) min , sec = borrow(min , sec , 60) -- Propagate out of range values up -- e.g. if `min` is 70, `hour` increments by 1 and `min` becomes 10 -- This has to happen for all columns after borrowing, as lower radixes may be pushed out of range min , sec = carry(min , sec , 60) -- TODO: consider leap seconds? hour , min = carry(hour, min , 60) day , hour = carry(day , hour, 24) -- Ensure `day` is not underflowed -- Add a whole year of days at a time, this is later resolved by adding months -- TODO[OPTIMIZE]: This could be slow if `day` is far out of range while day < 0 do month = month - 1 if month < 0 then year = year - 1 month = 11 end day = day + month_length(month + 1, year) end year, month = carry(year, month, 12) -- TODO[OPTIMIZE]: This could potentially be slow if `day` is very large while true do local i = month_length(month + 1, year) if day < i then break end day = day - i month = month + 1 if month >= 12 then month = 0 year = year + 1 end end -- Now we can place `day` and `month` back in their normal ranges -- e.g. month as 1-12 instead of 0-11 month, day = month + 1, day + 1 return year, month, day, hour, min, sec end local leap_years_since_1970 = leap_years_since(1970) local function timestamp(year, month, day, hour, min, sec) year, month, day, hour, min, sec = normalise(year, month, day, hour, min, sec) local days_since_epoch = day_of_year(day, month, year) + 365 * (year - 1970) -- Each leap year adds one day + (leap_years_since(year - 1) - leap_years_since_1970) - 1 return days_since_epoch * (60*60*24) + hour * (60*60) + min * 60 + sec end local timetable_methods = {} function timetable_methods:unpack() return assert(self.year , "year required"), assert(self.month, "month required"), assert(self.day , "day required"), self.hour or 12, self.min or 0, self.sec or 0, self.yday, self.wday end function timetable_methods:normalise() local year, month, day year, month, day, self.hour, self.min, self.sec = normalise(self:unpack()) self.day = day self.month = month self.year = year self.yday = day_of_year(day, month, year) self.wday = day_of_week(day, month, year) return self end timetable_methods.normalize = timetable_methods.normalise -- American English function timetable_methods:timestamp() return timestamp(self:unpack()) end function timetable_methods:rfc_3339() local year, month, day, hour, min, fsec = self:unpack() local sec, msec = borrow(fsec, 0, 1000) msec = math.floor(msec) return strformat("%04u-%02u-%02uT%02u:%02u:%02d.%03d", year, month, day, hour, min, sec, msec) end function timetable_methods:strftime(format_string) return strftime(format_string, self) end local timetable_mt local function coerce_arg(t) if getmetatable(t) == timetable_mt then return t:timestamp() end return t end timetable_mt = { __index = timetable_methods; __tostring = timetable_methods.rfc_3339; __eq = function(a, b) return a:timestamp() == b:timestamp() end; __lt = function(a, b) return a:timestamp() < b:timestamp() end; __sub = function(a, b) return coerce_arg(a) - coerce_arg(b) end; } local function cast_timetable(tm) return setmetatable(tm, timetable_mt) end local function new_timetable(year, month, day, hour, min, sec, yday, wday) return cast_timetable { year = year; month = month; day = day; hour = hour; min = min; sec = sec; yday = yday; wday = wday; } end function timetable_methods:clone() return new_timetable(self:unpack()) end local function new_from_timestamp(ts) if type(ts) ~= "number" then error("bad argument #1 to 'new_from_timestamp' (number expected, got " .. type(ts) .. ")", 2) end return new_timetable(1970, 1, 1, 0, 0, ts):normalise() end --- Parse an RFC 3339 datetime at the given position -- Returns a time table and the `tz_offset` -- Return value is not normalised (this preserves a leap second) -- If the timestamp is only partial (i.e. missing "Z" or time offset) then `tz_offset` will be nil -- TODO: Validate components are within their boundarys (e.g. 1 <= month <= 12) local function rfc_3339(str, init) local year, month, day, hour, min, sec, patt_end = str:match("^(%d%d%d%d)%-(%d%d)%-(%d%d)[Tt](%d%d%.?%d*):(%d%d):(%d%d)()", init) -- luacheck: ignore 631 if not year then return nil, "Invalid RFC 3339 timestamp" end year = tonumber(year, 10) month = tonumber(month, 10) day = tonumber(day, 10) hour = tonumber(hour, 10) min = tonumber(min, 10) sec = tonumber(sec, 10) local tt = new_timetable(year, month, day, hour, min, sec) local tz_offset if str:match("^[Zz]", patt_end) then tz_offset = 0 else local hour_offset, min_offset = str:match("^([+-]%d%d):(%d%d)", patt_end) if hour_offset then tz_offset = tonumber(hour_offset, 10) * 3600 + tonumber(min_offset, 10) * 60 else -- luacheck: ignore 542 -- Invalid RFC 3339 timestamp offset (should be Z or (+/-)hour:min) -- tz_offset will be nil end end return tt, tz_offset end return { -- used in zenroom from_string = rfc_3339; to_string = function(a) return a:normalise():rfc_3339() end; from_seconds = new_from_timestamp; to_seconds = function(a) return a:normalise():timestamp() end; -- original from luatz is_leap = is_leap; day_of_year = day_of_year; day_of_week = day_of_week; normalise = normalise; timestamp = timestamp; new = new_timetable; new_from_timestamp = new_from_timestamp; cast = cast_timetable; timetable_mt = timetable_mt; } L)-- -- json.lua -- -- Copyright (c) 2019 rxi -- Copyright (c) 2020-2021 Dyne.org foundation -- -- 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. -- local json = { _version = "0.1.2" } ------------------------------------------------------------------------------- -- Encode ------------------------------------------------------------------------------- local encode local escape_char_map = { [ "\\" ] = "\\\\", [ "\"" ] = "\\\"", [ "\b" ] = "\\b", [ "\f" ] = "\\f", [ "\n" ] = "\\n", [ "\r" ] = "\\r", [ "\t" ] = "\\t", } local escape_char_map_inv = { [ "\\/" ] = "/" } for k, v in pairs(escape_char_map) do escape_char_map_inv[v] = k end local function escape_char(c) return escape_char_map[c] or string.format("\\u%04x", c:byte()) end local function encode_nil(val) return "null" end local function encode_table(val, stack) local res = {} stack = stack or {} -- Circular reference? if stack[val] then error("circular reference") end stack[val] = true if rawget(val, 1) ~= nil or next(val) == nil then -- Treat as array -- check keys are valid and it is not sparse local n = 0 for k in pairs(val) do if type(k) ~= "number" then error("invalid table: mixed or invalid key types") end n = n + 1 end if n ~= #val then warn("JSON encoding error: "..type(val)) error("invalid table: sparse array (n="..n..", #val="..#val..")") end -- Encode for i, v in sort_ipairs(val) do table.insert(res, encode(v, stack)) end stack[val] = nil return "[" .. table.concat(res, ",") .. "]" else -- Treat as an object for k, v in sort_pairs(val) do if type(k) ~= "string" then error("invalid table: mixed or invalid key types") end table.insert(res, encode(k, stack) .. ":" .. encode(v, stack)) end stack[val] = nil return "{" .. table.concat(res, ",") .. "}" end end local function encode_string(val) return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"' end local function encode_number(val) -- Check for NaN, -inf and inf -- if val ~= val or val <= -math.huge or val >= math.huge then -- error("unexpected number value '" .. tostring(val) .. "'") -- end -- return string.format("%.14g", val) return val end local function encode_function(val) -- return hex function address as string return '"' .. strtok(tostring(val))[2] .. '"' end local type_func_map = { [ "nil" ] = encode_nil, [ "table" ] = encode_table, [ "string" ] = encode_string, [ "number" ] = encode_number, [ "function"] = encode_function, [ "boolean" ] = tostring, } encode = function(val, stack) local t = type(val) local f = type_func_map[t] if f then return f(val, stack) end error("unexpected type '" .. t .. "'") end function json.raw_encode(val) return(encode(val)) -- sort -- local out = "{ " -- for k,v in sort_pairs(val) do -- out = out .. '"'..k..'": ' -- out = out .. encode(v).."," -- end -- return(out:sub(1,-2) .. "}") end ------------------------------------------------------------------------------- -- Decode ------------------------------------------------------------------------------- local parse local function create_set(...) local res = {} for i = 1, select("#", ...) do res[ select(i, ...) ] = true end return res end local space_chars = create_set(" ", "\t", "\r", "\n") local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",") local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u") local literals = create_set("true", "false", "null") local literal_map = { [ "true" ] = true, [ "false" ] = false, [ "null" ] = nil, } local function next_char(str, idx, set, negate) for i = idx, #str do if set[str:sub(i, i)] ~= negate then return i end end return #str + 1 end local function decode_error(str, idx, msg) local line_count = 1 local col_count = 1 for i = 1, idx - 1 do col_count = col_count + 1 if str:sub(i, i) == "\n" then line_count = line_count + 1 col_count = 1 end end error( string.format("The JSON input is not valid: %s at line %d col %d", msg, line_count, col_count) ) end local function codepoint_to_utf8(n) -- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa local f = math.floor if n <= 0x7f then return string.char(n) elseif n <= 0x7ff then return string.char(f(n / 64) + 192, n % 64 + 128) elseif n <= 0xffff then return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128) elseif n <= 0x10ffff then return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128, f(n % 4096 / 64) + 128, n % 64 + 128) end error( string.format("invalid unicode codepoint '%x'", n) ) end local function parse_unicode_escape(s) local n1 = tonumber( s:sub(3, 6), 16 ) local n2 = tonumber( s:sub(9, 12), 16 ) -- Surrogate pair? if n2 then return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000) else return codepoint_to_utf8(n1) end end local function parse_string(str, i) local has_unicode_escape = false local has_surrogate_escape = false local has_escape = false local last for j = i + 1, #str do local x = str:byte(j) if x < 32 then decode_error(str, j, "control character in string") end if last == 92 then -- "\\" (escape char) if x == 117 then -- "u" (unicode escape sequence) local hex = str:sub(j + 1, j + 5) if not hex:find("%x%x%x%x") then decode_error(str, j, "invalid unicode escape in string") end if hex:find("^[dD][89aAbB]") then has_surrogate_escape = true else has_unicode_escape = true end else local c = string.char(x) if not escape_chars[c] then decode_error(str, j, "invalid escape char '" .. c .. "' in string") end has_escape = true end last = nil elseif x == 34 then -- '"' (end of string) local s = str:sub(i + 1, j - 1) if has_surrogate_escape then s = s:gsub("\\u[dD][89aAbB]..\\u....", parse_unicode_escape) end if has_unicode_escape then s = s:gsub("\\u....", parse_unicode_escape) end if has_escape then s = s:gsub("\\.", escape_char_map_inv) end return s, j + 1 else last = x end end decode_error(str, i, "expected closing quote for string") end local function parse_number(str, i) local x = next_char(str, i, delim_chars) local s = str:sub(i, x - 1) local n = tonumber(s) if not n then decode_error(str, i, "invalid number '" .. s .. "'") end return n, x end local function parse_literal(str, i) local x = next_char(str, i, delim_chars) local word = str:sub(i, x - 1) if not literals[word] then decode_error(str, i, "invalid literal '" .. word .. "'") end return literal_map[word], x end local function parse_array(str, i) local res = {} local n = 1 i = i + 1 while 1 do local x i = next_char(str, i, space_chars, true) -- Empty / end of array? if str:sub(i, i) == "]" then i = i + 1 break end -- Read token x, i = parse(str, i) res[n] = x n = n + 1 -- Next token i = next_char(str, i, space_chars, true) local chr = str:sub(i, i) i = i + 1 if chr == "]" then break end if chr ~= "," then decode_error(str, i, "expected ']' or ','") end end return res, i end local function parse_object(str, i) local res = {} i = i + 1 while 1 do local key, val i = next_char(str, i, space_chars, true) -- Empty / end of object? if str:sub(i, i) == "}" then i = i + 1 break end -- Read key if str:sub(i, i) ~= '"' then decode_error(str, i, "expected string for key") end key, i = parse(str, i) -- Read ':' delimiter i = next_char(str, i, space_chars, true) if str:sub(i, i) ~= ":" then decode_error(str, i, "expected ':' after key") end i = next_char(str, i + 1, space_chars, true) -- Read value val, i = parse(str, i) -- Set res[key] = val -- Next token i = next_char(str, i, space_chars, true) local chr = str:sub(i, i) i = i + 1 if chr == "}" then break end if chr ~= "," then decode_error(str, i, "expected '}' or ','") end end return res, i end local char_func_map = { [ '"' ] = parse_string, [ "0" ] = parse_number, [ "1" ] = parse_number, [ "2" ] = parse_number, [ "3" ] = parse_number, [ "4" ] = parse_number, [ "5" ] = parse_number, [ "6" ] = parse_number, [ "7" ] = parse_number, [ "8" ] = parse_number, [ "9" ] = parse_number, [ "-" ] = parse_number, [ "t" ] = parse_literal, [ "f" ] = parse_literal, [ "n" ] = parse_literal, [ "[" ] = parse_array, [ "{" ] = parse_object, } parse = function(str, idx) local chr = str:sub(idx, idx) local f = char_func_map[chr] if f then return f(str, idx) end decode_error(str, idx, "unexpected character '" .. chr .. "'") end function json.raw_decode(str) if type(str) ~= "string" then error("expected argument of type string, got " .. type(str)) end local res, idx = parse(str, next_char(str, 1, space_chars, true)) idx = next_char(str, idx, space_chars, true) if idx <= #str then decode_error(str, idx, "trailing garbage") end return res end return json --[[ --This file is part of zenroom -- --Copyright (C) 2020-2021 Dyne.org foundation --Implementation by Alberto Ibrisevic and Denis Roio --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Matteo Cristino --on Thursday, 24th March 2021 --]] local schnorr = {} -- prime modulus of the coordinates of ECP and order of the curve p = ECP.prime() o = ECP.order() -- generator of the curve G = ECP.generator() -- method for obtaining a valid EC secret key that is chosen at random function schnorr.keygen() local sk, d repeat sk = OCTET.random(32) d = BIG.new(sk) if o <= d then d = BIG.new(0) end --guaranties that the generated keypair is valid until (d ~= BIG.new(0)) return sk end -- given a valid secret key, extracts the related public key not encoded (i.e. as the point P=(P:x(), P:y())) local function pubpoint_gen(sk) assert(sk, "no secret key found") assert(#sk == 32, 'invalid secret key: length is not of 32B') local d = BIG.new(sk) assert(d ~= BIG.new(0), 'invalid secret key, is zero') assert(d <= o, 'invalid secret key, overflow with curve order') local P = d*G return P end -- given a valid secret key, extracts the related encoded public key -- @param sk a 32 Byte OCTET, secret key -- @return a 48 Byte OCTET, public key function schnorr.pubgen(sk) if iszen(type(sk)) then sk = sk:octet() end local P = pubpoint_gen(sk) local pk = (P:x()):octet():pad(48) return pk end -- validation of the public key done in two steps: -- 1.check the point is on the curve -- 2.check the point is not infinte -- @param pk a 48 Byte OCTET, public key -- @return true if the public key is valid, otherwise false function schnorr.pubcheck(pk) if iszen(type(pk)) then pk = pk:octet() end local P = ECP.new(BIG.new(pk)) return ECP.validate(P) and not ECP.isinf(P) end -- validation of the private key done in two steps: -- 1.check the length -- 2.check that it is grater than 0 and lower than the order of the curve -- @param sk a 32 Byte OCTET, secret key -- @return true if the secret key is valid, otherwise false function schnorr.seccheck(sk) if iszen(type(sk)) then sk = sk:octet() end local d = BIG.new(sk) return (#sk == 32) and (d ~= BIG.new(0)) and (d <= o) end -- validation of the signature (sig=(r,s)) done in three steps: -- 1.check the length of the signature -- 2.check that r is lower than p -- 3.check that s is lower than o -- @param sig a 80 Byte OCTET, signature ('sig=(r,s)') -- @return true if the signature is valid, otherwise false function schnorr.sigcheck(sig) if sig and (#sig == 80) then local r_arr, s_arr = OCTET.chop(sig,48) local r = BIG.new(r_arr) local s = BIG.new(s_arr) return (r <= p) and (s <= o) end return false end -- method for obtaining an hash digest using a (UTF-8) encoded tag name together with the data to process -- N.B1: By doing this, we make sure hashes used in one context can't be reinterpreted in another one, -- in such a way that collisions across contexts can be assumed to be infeasible. -- N.B2: tag names can be customized at will local function hash_tag(tag, data) local h = sha256(O.str(tag)) return sha256(h..h..data) end -- signing algorithm -- @param sk a 32 Byte OCTET, secret key -- @param m an arbitrary long OCTET, message -- @return an 80 Byte OCTET, signature '(r,s)'', r is 48 Byte long and s is 32 Byte long function schnorr.sign(sk, m) if iszen(type(sk)) then sk = sk:octet() end local d = BIG.new(sk) local P = pubpoint_gen(sk) --for convention we need that P has even y-coordinate --N.B: we don't change the point with the new one, but only store the coefficient d needed to obtain it if P:y():parity() then d = o - d end local k repeat local a = OCTET.random(32) local h = hash_tag("BIP0340/aux", a) local t = OCTET.xor(d:octet(), h) local rand = hash_tag("BIP0340/nonce", t..((P:x()):octet())..m) k = BIG.new(rand) % o --maybe it is not needed since o is bigger until k ~= BIG.new(0) local R = k*G if R:y():parity() then k = o - k end --also here we store only the coefficient k, /wo changing the point R local e = BIG.new(hash_tag("BIP0340/challenge", ((R:x()):octet())..((P:x()):octet())..m)) % o local r = (R:x()):octet():pad(48) --padding is fundamental, otherwise we could lose non-significant zeros local s = BIG.mod(k + e*d, o):octet():pad(32) local sig = r..s assert(schnorr.verify(P:x(),m,sig), "Invalid signature") --comment this line if it is unnecessary return sig end -- verification algortihm -- @param pk a 48 Byte OCTET, public key -- @param m an arbitrary long OCTET, message -- @param sig an 80 Byte OCTET, signature ('sig=(r,s)') -- @return true if verification passes, false otherwise function schnorr.verify(pk, m, sig) if iszen(type(pk)) then pk = pk:octet() end --the follwing "lifts" pk to an ECP with x = pk and y is even local P = ECP.new(BIG.new(pk)) assert(P, "lifting failed") local r_arr, s_arr = OCTET.chop(sig,48) local r = BIG.new(r_arr) assert(r <= p, "Verification failed, r overflows p") local s = BIG.new(s_arr) assert(s <= o, "Verification failed, s overflows o") local e = BIG.new(hash_tag("BIP0340/challenge", r:octet()..(P:x()):octet()..m)) % o local R = (s*G) - (e*P) --if the signature is valid the result will be k*G as expected assert(not ECP.isinf(R), "Verification failed, point to infinity") assert(not R:y():parity() , "Verification failed, y is odd") assert((R:x() == r), "Verification failed") return true end return schnorr -- TODO: batch verification (--[[---------------------------------------------------------------------------- MessagePack encoder / decoder written in pure Lua 5.3 / Lua 5.4 written by Sebastian Steinhauer This is free and unencumbered software released into the public domain. Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law. 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 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. For more information, please refer to --]]---------------------------------------------------------------------------- local pack, unpack = string.pack, string.unpack local mtype, utf8len = math.type, utf8.len local tconcat, tunpack = table.concat, table.unpack local ssub = string.sub local type, pcall, pairs, select = type, pcall, pairs, select --[[---------------------------------------------------------------------------- Encoder --]]---------------------------------------------------------------------------- local encode_value -- forward declaration local function is_an_array(value) local expected = 1 for k in pairs(value) do if k ~= expected then return false end expected = expected + 1 end return true end local encoder_functions = { ['nil'] = function() return pack('B', 0xc0) end, ['boolean'] = function(value) if value then return pack('B', 0xc3) else return pack('B', 0xc2) end end, ['number'] = function(value) if mtype(value) == 'integer' then if value >= 0 then if value < 128 then return pack('B', value) elseif value <= 0xff then return pack('BB', 0xcc, value) elseif value <= 0xffff then return pack('>BI2', 0xcd, value) elseif value <= 0xffffffff then return pack('>BI4', 0xce, value) else return pack('>BI8', 0xcf, value) end else if value >= -32 then return pack('B', 0xe0 + (value + 32)) elseif value >= -128 then return pack('Bb', 0xd0, value) elseif value >= -32768 then return pack('>Bi2', 0xd1, value) elseif value >= -2147483648 then return pack('>Bi4', 0xd2, value) else return pack('>Bi8', 0xd3, value) end end else local test = unpack('f', pack('f', value)) if test == value then -- check if we can use float return pack('>Bf', 0xca, value) else return pack('>Bd', 0xcb, value) end end end, ['string'] = function(value) local len = #value if utf8len(value) then -- check if it is a real utf8 string or just byte junk if len < 32 then return pack('B', 0xa0 + len) .. value elseif len < 256 then return pack('>Bs1', 0xd9, value) elseif len < 65536 then return pack('>Bs2', 0xda, value) else return pack('>Bs4', 0xdb, value) end else -- encode it as byte-junk :) if len < 256 then return pack('>Bs1', 0xc4, value) elseif len < 65536 then return pack('>Bs2', 0xc5, value) else return pack('>Bs4', 0xc6, value) end end end, ['table'] = function(value) if is_an_array(value) then -- it seems to be a proper Lua array local elements = {} for i, v in pairs(value) do elements[i] = encode_value(v) end local length = #elements if length < 16 then return pack('>B', 0x90 + length) .. tconcat(elements) elseif length < 65536 then return pack('>BI2', 0xdc, length) .. tconcat(elements) else return pack('>BI4', 0xdd, length) .. tconcat(elements) end else -- encode as a map local elements = {} for k, v in pairs(value) do elements[#elements + 1] = encode_value(k) elements[#elements + 1] = encode_value(v) end local length = #elements // 2 if length < 16 then return pack('>B', 0x80 + length) .. tconcat(elements) elseif length < 65536 then return pack('>BI2', 0xde, length) .. tconcat(elements) else return pack('>BI4', 0xdf, length) .. tconcat(elements) end end end, } encode_value = function(value) return encoder_functions[type(value)](value) end local function encode(...) local data = {} for i = 1, select('#', ...) do data[#data + 1] = encode_value(select(i, ...)) end return tconcat(data) end --[[---------------------------------------------------------------------------- Decoder --]]---------------------------------------------------------------------------- local decode_value -- forward declaration local function decode_array(data, position, length) local elements, value = {} for i = 1, length do value, position = decode_value(data, position) elements[i] = value end return elements, position end local function decode_map(data, position, length) local elements, key, value = {} for i = 1, length do key, position = decode_value(data, position) value, position = decode_value(data, position) elements[key] = value end return elements, position end local decoder_functions = { [0xc0] = function(data, position) return nil, position end, [0xc2] = function(data, position) return false, position end, [0xc3] = function(data, position) return true, position end, [0xc4] = function(data, position) return unpack('>s1', data, position) end, [0xc5] = function(data, position) return unpack('>s2', data, position) end, [0xc6] = function(data, position) return unpack('>s4', data, position) end, -- 0xc7 - 0xc9 for userdata [0xca] = function(data, position) return unpack('>f', data, position) end, [0xcb] = function(data, position) return unpack('>d', data, position) end, [0xcc] = function(data, position) return unpack('>B', data, position) end, [0xcd] = function(data, position) return unpack('>I2', data, position) end, [0xce] = function(data, position) return unpack('>I4', data, position) end, [0xcf] = function(data, position) return unpack('>I8', data, position) end, [0xd0] = function(data, position) return unpack('>b', data, position) end, [0xd1] = function(data, position) return unpack('>i2', data, position) end, [0xd2] = function(data, position) return unpack('>i4', data, position) end, [0xd3] = function(data, position) return unpack('>i8', data, position) end, -- 0xd4 - 0xd8 for userdata [0xd9] = function(data, position) return unpack('>s1', data, position) end, [0xda] = function(data, position) return unpack('>s2', data, position) end, [0xdb] = function(data, position) return unpack('>s4', data, position) end, [0xdc] = function(data, position) local length length, position = unpack('>I2', data, position) return decode_array(data, position, length) end, [0xdd] = function(data, position) local length length, position = unpack('>I4', data, position) return decode_array(data, position, length) end, [0xde] = function(data, position) local length length, position = unpack('>I2', data, position) return decode_map(data, position, length) end, [0xdf] = function(data, position) local length length, position = unpack('>I4', data, position) return decode_map(data, position, length) end, } -- add fix-array, fix-map, fix-string, fix-int stuff for i = 0x00, 0x7f do decoder_functions[i] = function(data, position) return i, position end end for i = 0x80, 0x8f do decoder_functions[i] = function(data, position) return decode_map(data, position, i - 0x80) end end for i = 0x90, 0x9f do decoder_functions[i] = function(data, position) return decode_array(data, position, i - 0x90) end end for i = 0xa0, 0xbf do decoder_functions[i] = function(data, position) local length = i - 0xa0 return ssub(data, position, position + length - 1), position + length end end for i = 0xe0, 0xff do decoder_functions[i] = function(data, position) return -32 + (i - 0xe0), position end end decode_value = function(data, position) local byte, value byte, position = unpack('B', data, position) value, position = decoder_functions[byte](data, position) return value, position end --[[---------------------------------------------------------------------------- Interface --]]---------------------------------------------------------------------------- return { _AUTHOR = 'Sebastian Steinhauer ', _VERSION = '0.6.1', encoder_functions = encoder_functions, decoder_functions = decoder_functions, -- primary encode function encode = function(...) local data, ok = {} for i = 1, select('#', ...) do ok, data[i] = pcall(encode_value, select(i, ...)) if not ok then return nil, 'cannot encode MessagePack' end end return tconcat(data) end, -- encode just one value encode_one = function(value) local ok, data = pcall(encode_value, value) if ok then return data else return nil, 'cannot encode MessagePack' end end, -- primary decode function decode = function(data, position) local values, value, ok = {} position = position or 1 while position <= #data do ok, value, position = pcall(decode_value, data, position) if ok then values[#values + 1] = value else return nil, 'cannot decode MessagePack' end end return tunpack(values) end, -- decode just one value decode_one = function(data, position) local value, ok ok, value, position = pcall(decode_value, data, position or 1) if ok then return value, position else return nil, 'cannot decode MessagePack' end end, } --[[---------------------------------------------------------------------------- --]]---------------------------------------------------------------------------- R--[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 9th April 2022 --]] -- ABC/COCONUT implementation in Zencode local CRED = require_once('crypto_credential') -- local G1 = ECP.generator() local G2 = ECP2.generator() -- exported function (non local) for use in zencode_petition function import_credential_proof_f(obj) return { nu = ZEN.get(obj, 'nu', ECP.new), kappa = ZEN.get(obj, 'kappa', ECP2.new), pi_v = { c = ZEN.get(obj.pi_v, 'c', INT.new), rm = ZEN.get(obj.pi_v, 'rm', INT.new), rr = ZEN.get(obj.pi_v, 'rr', INT.new) }, sigma_prime = { h_prime = ZEN.get(obj.sigma_prime, 'h_prime', ECP.new), s_prime = ZEN.get(obj.sigma_prime, 's_prime', ECP.new) } } end function key_import_issuer_verifier_f(obj) return { alpha = ZEN.get(obj, 'alpha', ECP2.new), beta = ZEN.get(obj, 'beta', ECP2.new) } end -- credential keypair operations When('create the credential key',function() initkeyring'credential' ACK.keyring.credential = INT.random() end) When("create the credential key with secret key ''",function(sec) initkeyring'credential' local secret = have(sec) ACK.keyring.credential = INT.new(secret) end) When("create the credential key with secret ''",function(sec) initkeyring'credential' local secret = have(sec) ACK.keyring.credential = INT.new(secret) end) When( 'create the issuer key', function() initkeyring'issuer' ACK.keyring.issuer = CRED.issuer_keygen() end ) When( 'create the issuer public key', function() havekey'issuer' ACK.issuer_public_key = { alpha = G2 * ACK.keyring.issuer.x, beta = G2 * ACK.keyring.issuer.y } end ) -- request credential signatures ZEN.add_schema( { issuer_public_key = key_import_issuer_verifier_f, -- lambda credential_request = function(obj) local req = { sign = { a = ZEN.get(obj.sign, 'a', ECP.new), b = ZEN.get(obj.sign, 'b', ECP.new) }, pi_s = { rr = ZEN.get(obj.pi_s, 'rr', INT.new), rm = ZEN.get(obj.pi_s, 'rm', INT.new), rk = ZEN.get(obj.pi_s, 'rk', INT.new), commit = ZEN.get(obj.pi_s, 'commit', INT.new) }, commit = ZEN.get(obj, 'commit', ECP.new), public = ZEN.get(obj, 'public', ECP.new) } ZEN.assert( CRED.verify_pi_s(req), 'Error in credential request: proof is invalid (verify_pi_s)' ) return req end } ) When( 'create the credential request', function() havekey'credential' ACK.credential_request = CRED.prepare_blind_sign(ACK.keyring.credential) end ) -- issuer's signature of credentials ZEN.add_schema( { -- sigmatilde credential_signature = function(obj) return { h = ZEN.get(obj, 'h', ECP.new), b_tilde = ZEN.get(obj, 'b_tilde', ECP.new), a_tilde = ZEN.get(obj, 'a_tilde', ECP.new) } end, -- aggsigma: aggregated signatures of ca issuers credentials = function(obj) return { h = ZEN.get(obj, 'h', ECP.new), s = ZEN.get(obj, 's', ECP.new) } end } ) When( 'create the credential signature', function() have 'credential request' havekey'issuer' ACK.credential_signature = CRED.blind_sign(ACK.keyring.issuer, ACK.credential_request) ACK.verifier = { alpha = G2 * ACK.keyring.issuer.x, beta = G2 * ACK.keyring.issuer.y } end ) When( 'create the credentials', function() have 'credential signature' havekey'credential' -- prepare output with an aggregated sigma credential -- requester signs the sigma with private key ACK.credentials = CRED.aggregate_creds(ACK.keyring.credential, {ACK.credential_signature}) end ) ZEN.add_schema( { -- theta: blind proof of certification credential_proof = function(obj) return { nu = ZEN.get(obj, 'nu', ECP.new), kappa = ZEN.get(obj, 'kappa', ECP2.new), pi_v = { c = ZEN.get(obj.pi_v, 'c', INT.new), rm = ZEN.get(obj.pi_v, 'rm', INT.new), rr = ZEN.get(obj.pi_v, 'rr', INT.new) }, sigma_prime = { h_prime = ZEN.get(obj.sigma_prime, 'h_prime', ECP.new), s_prime = ZEN.get(obj.sigma_prime, 's_prime', ECP.new) } } end } ) When( 'aggregate the issuer public keys', function() have 'issuer public key' if not ACK.verifiers then ACK.verifiers = {} end for k, v in pairs(ACK.issuer_public_key) do ACK.verifiers[k] = v end -- TODO: aggregate all array end ) When( 'create the credential proof', function() have 'verifiers' have 'credentials' empty 'credential proof' havekey'credential' ACK.credential_proof = CRED.prove_cred(ACK.verifiers, ACK.credentials, ACK.keyring.credential) end ) IfWhen( 'verify the credential proof', function() have 'credential proof' have 'verifiers' ZEN.assert( CRED.verify_cred(ACK.verifiers, ACK.credential_proof), 'Credential proof does not validate' ) end ) -- This file is part of Zenroom (https://zenroom.dyne.org) -- -- Copyright (C) 2018-2022 Dyne.org foundation designed, written and -- maintained by Denis Roio -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU Affero General Public License as -- published by the Free Software Foundation, either version 3 of the -- License, or (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, but -- WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -- Affero General Public License for more details. -- -- You should have received a copy of the GNU Affero General Public -- License along with this program. If not, see -- . -- init script embedded at compile time. executed in -- zen_load_extensions(L) usually after zen_init() -- -- remap fatal and error function fatal(msg) if type(msg) == 'string' then warn(trim(msg), 2) end debug.traceback() -- if ZEN_traceback ~= "" then ZEN:debug() end if DEBUG > 1 then -- TODO: ZEN:backtrace() and traceback as sorted array warn(ZEN_traceback) end if DEBUG > 2 then -- TODO: ZEN:dump() I.warn( { HEAP = { IN = IN, TMP = TMP, ACK = ACK, OUT = OUT } } ) end ZEN:debug() msg = msg or 'fatal error' error(msg, 2) end -- global REQUIRED = {} -- avoid duplicating requires (internal includes) function require_once(ninc) local class = REQUIRED[ninc] local _res if not class then _res, class = pcall( function() return require(ninc) end ) assert(_res, class) REQUIRED[ninc] = class end return class end SCENARIOS = {} function load_scenario(scen) local s = SCENARIOS[scen] if not s then local _res, _err _res, _err = pcall( function() require(scen) end) assert(_res, _err) SCENARIOS[scen] = true end end -- error = zen_error -- from zen_io -- ZEN = { assert = assert } -- zencode shim when not loaded require('zenroom_common') INSPECT = require('inspect') CBOR = require('zenroom_cbor') JSON = require('zenroom_json') OCTET = require('zenroom_octet') BIG = require('zenroom_big') ECDH = require('zenroom_ecdh') -- ECDH public keys cannot function as ECP because of IANA 7303 AES = require'aes' ECP = require('zenroom_ecp') ECP2 = require('zenroom_ecp2') HASH = require('zenroom_hash') O = OCTET -- alias INT = BIG -- alias I = INSPECT -- alias H = HASH -- alias PAIR = ECP2 -- alias PAIR.ate = ECP2.miller --alias MPACK = require('zenroom_msgpack') ZPACK = require('zenroom_zpack') BENCH = require('zenroom_bench') MACHINE = require('statemachine') TIME = require('timetable') -- BITCOIN primitives are imported by default BTC = require('crypto_bitcoin') V = require('semver') ZENROOM_VERSION = V(VERSION) ZEN = require('zencode') -- the global ZEN context -- base zencode functions and schemas load_scenario('zencode_data') -- pick/in, conversions etc. load_scenario('zencode_given') load_scenario('zencode_when') load_scenario('zencode_hash') -- when extension load_scenario('zencode_array') -- when extension load_scenario('zencode_random') -- when extension load_scenario('zencode_dictionary') -- when extension load_scenario('zencode_verify') -- when extension load_scenario('zencode_then') load_scenario('zencode_keyring') -- this is to evaluate expressions or derivate a column -- it would execute lua code inside the zencode and is -- therefore dangerous, switched off by default -- require('zencode_eval') load_scenario('zencode_debug') -- bitcoin is loaded by default load_scenario('zencode_bitcoin') -- scenario are loaded on-demand -- scenarios can only implement "When ..." steps _G['Given'] = nil _G['Then'] = nil ----------- -- defaults _G['CONF'] = { input = { encoding = input_encoding('base64'), format = { fun = JSON.auto, name = 'json' }, tagged = false }, output = { encoding = { fun = guess_outcast('base64'), name = 'base64' }, format = { fun = JSON.auto, name = 'json' }, versioning = false }, debug = { encoding = { fun = guess_outcast('hex'), name = 'hex' } }, parser = {strict_match = true}, heap = { check_collision = true }, hash = 'sha256', } -- turn on heapguard when DEBUG or linux-debug build if DEBUG > 1 or MAKETARGET == "linux-debug" then _G['CONF'].heapguard = true else _G['CONF'].heapguard = false end -- do not modify _G['LICENSE'] = [[ Licensed under the terms of the GNU Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ]] _G['COPYRIGHT'] = [[ Forked by Jaromil on 18 January 2020 from Coconut Petition ]] SALT = ECP.hashtopoint(OCTET.from_string(COPYRIGHT .. LICENSE)) -- Calculate a system-wide crypto challenge for ZKP operations -- returns a BIG INT -- this is a sort of salted hash for advanced ZKP operations and -- should not be changed. It may be made configurable in future. function ZKP_challenge(list) local challenge = ECP.generator():octet() .. ECP2.generator():octet() .. SALT:octet() local ser = serialize(list) return INT.new( sha256(challenge .. ser.octets .. OCTET.from_string(ser.strings)) ) % ECP.order() end collectgarbage 'collect' ;--[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Friday, 26th November 2021 --]] -- hashing single strings When( "create the hash of ''", function(s) local src = have(s) if luatype(src) == 'table' then src = ZEN.serialize(src) -- serialize tables using zenroom's algo end ACK.hash = HASH.new(CONF.hash):process(src) new_codec('hash', { zentype = 'element' }) end ) When( "create the hash of '' using ''", function(s, h) local src = have(s) if luatype(src) == 'table' then src = ZEN.serialize(src) end if strcasecmp(h, 'sha256') then ACK.hash = sha256(src) elseif strcasecmp(h, 'sha512') then ACK.hash = sha512(src) end ZEN.assert(ACK.hash, 'Invalid hash: ' .. h) new_codec('hash', { zentype = 'element' }) end ) When( "create the hash to point '' of each object in ''", function(what, arr) local F = _G[what] ZEN.assert( luatype(F.hashtopoint) == 'function', 'Hash type ' .. what .. ' is invalid (no hashtopoint)' ) local A = have(arr) local count = isarray(A) ZEN.assert(count > 0, 'Object is not an array: ' .. arr) ACK.hash_to_point = deepmap(F.hashtopoint, A) new_codec('hash_to_point', { luatype='table', zentype='array' }) end ) When( "create the hashes of each object in ''", function(arr) local A = have(arr) local count = isarray(A) ZEN.assert(count > 0, 'Object is not an array: ' .. arr) ACK.hashes = deepmap(sha256, A) new_codec('hashes', { luatype='table', zentype='array' }) end ) -- HMAC from RFC2104. When( "create the HMAC of '' with key ''", function(obj, key) local src = have(obj) if luatype(src) == 'table' then src = ZEN.serialize(src) end local hkey = have(key) -- static int hash_hmac(lua_State *L) { -- hash *h = hash_arg(L,1); -- octet *k = o_arg(L, 2); -- octet *in = o_arg(L, 3); ACK.HMAC = HASH.new(CONF.hash):hmac(hkey, obj) new_codec('HMAC', { zentype = 'element' }) end ) When( "create the key derivation of ''", function(obj) local src = have(obj) if luatype(src) == 'table' then src = ZEN.serialize(src) end ACK.key_derivation = HASH.new(CONF.hash):kdf(src) new_codec('key_derivation', { zentype = 'element' }) end ) When( "create the key derivation of '' with password ''", function(obj, salt) local src = have(obj) if luatype(src) == 'table' then src = ZEN.serialize(src) end local pass = have(salt) ACK.key_derivation = HASH.new('sha512'):pbkdf2(src, {salt = pass, iterations = 5000, length = 32}) new_codec('key derivation', { zentype = 'element' }) end ) 8$--[[ --This file is part of zenroom -- --Copyright (C) 2020-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Wednesday, 6th October 2021 --]] -- this is a map reduce function processing a single argument as -- values found, it uses function pointers and conditions from the -- params structure. -- param.target = key name of the value to find -- param.op = single argument function to run on found value -- param.cmp = dual argument comparison for dictionary eligibility -- param.conditions = k/v list of elements to compare in dictionary local function dicts_reduce(dicts, params) local found local arr for ak,av in pairs(dicts) do if luatype(av) == 'table' then found = false -- apply params filters, boolean just check key presence if params.conditions and params.cmp then for pk,pv in pairs(params.conditions) do local tv = av[pk] if tv then if params.cmp(tv, pv) then found = true end end end else found = true end -- no filters, apply everywhere -- apply sum of selected key/value if found then for k,v in pairs(av) do if k == params.target then params.op(v) end end end end -- av is a table end end When("create the new dictionary", function() empty'new dictionary' ACK.new_dictionary = { } new_codec('new dictionary', { zentype = 'dictionary' }) end) When("create the new dictionary named ''", function(name) empty(name) ACK[name] = { } new_codec(name, { zentype = 'dictionary' }) end) When("create the array of elements named '' for dictionaries in ''", function(name, dict) empty'array' local src = have(dict) ZEN.assert(luatype(src)=='table', "Object is not a table: "..dict) local res = { } for k, v in pairs(src) do if k == name then table.insert(res, v) end -- dict is most oftern an array of dictionaries for kk, vv in pairs(v) do if kk == name then table.insert(res, vv) end end end ACK.array = res new_codec('array', {luatype='table',zentype='array'}, dict) end) When("create the pruned dictionary of ''", function(dict) empty'pruned dictionary' local d = have(dict) ZEN.assert(luatype(d) == 'table', 'Object is not a table: '..dict) ACK.pruned_dictionary = prune(d) new_codec('pruned dictionary', nil, dict) end) When("find the max value '' for dictionaries in ''", function(name, arr) ZEN.assert(luatype(have(arr)) == 'table', 'Object is not a table: '..arr) empty'max value' local max = 0 local params = { target = name, op = function(v) if max < v then max = v end end } dicts_reduce(ACK[arr],params) -- optimization? operate directly on ACK ZEN.assert(max, "No max value "..name.." found across dictionaries in"..arr) ACK.max_value = max new_codec('max value', { zentype = 'element', -- introduce scalar? luatype = 'number' }, arr) -- clone array's encoding end) When("find the min value '' for dictionaries in ''", function(name, arr) ZEN.assert(luatype(have(arr)) == 'table', 'Object is not a table: '..arr) empty'min value' local min -- init min with any value for k,v in pairs(ACK[arr]) do min = v[name] -- suppose existance of key break end local params = { target = name, op = function(v) if v < min then min = v end end } dicts_reduce(ACK[arr],params) ACK.min_value = min new_codec('min value', { zentype = 'element', -- introduce scalar? luatype = 'number' }, arr) -- clone array's encoding end) When("create the sum value '' for dictionaries in ''", function(name,arr) ZEN.assert(luatype(have(arr)) == 'table', 'Object is not a table: '..arr) empty'sum value' local sum -- result of reduction local params = { target = name, op = function(v) if not sum then sum = v else sum = sum + v end end } dicts_reduce(ACK[arr], params) ZEN.assert(sum, "No sum of value "..name .." found across dictionaries in "..arr) ACK.sum_value = sum new_codec('sum value', { zentype = type(sum), -- introduce scalar? }) -- clone array's encoding end) When("create the sum value '' for dictionaries in '' where '' > ''", function(name,arr, left, right) ZEN.assert(luatype(have(arr)) == 'table', 'Object is not a table: '..arr) have(right) empty'sum value' local sum = 0 -- result of reduction local params = { target = name, conditions = { }, cmp = function(l,r) return l > r end, op = function(v) sum = sum + v end } params.conditions[left] = ACK[right] -- used in cmp dicts_reduce(ACK[arr], params) ZEN.assert(sum, "No sum of value "..name .." found across dictionaries in"..arr) ACK.sum_value = sum new_codec('sum value', { zentype = 'element', -- introduce scalar? luatype = 'number' }, arr) -- clone array's encoding end) When("find the '' for dictionaries in '' where '' = ''",function(name, arr, left, right) ZEN.assert(luatype(have(arr)) == 'table', 'Object is not a table: '..arr) have(right) empty(name) local val = { } local params = { target = name, conditions = { }, cmp = function(l,r) return l == r end, op = function(v) table.insert(val, v) end } params.conditions[left] = ACK[right] dicts_reduce(ACK[arr], params) ZEN.assert(val, "No value found "..name.." across dictionaries in "..arr) ACK[name] = val new_codec(name, { luatype = 'table', zentype = 'array' }, arr) end) local function create_copy_f(root, in1, in2) local r = have(root) empty'copy' ZEN.assert(luatype(r) == 'table', "Object is not a table:"..root) ZEN.assert(in1, "Undefined key or index: "..in1.." in "..root) local res if tonumber(in1) then ZEN.assert(isarray(r), "Invalid index "..in1.." as object is not an array: "..root) else ZEN.assert(isdictionary(r), "Invalid key "..in1.." as object is not a dictionary:"..root) end ACK.copy = r[in1] ZEN.assert(ACK.copy, "Member not found: "..in1.." in "..root) if in2 then if tonumber(in2) then ZEN.assert(isarray(ACK.copy), "Invalid index "..in2.." as object is not an array: "..in1.." in "..root) else ZEN.assert(isdictionary(ACK.copy), "Invalid key "..in2.." as object is not a dictionary:"..in1.." in "..root) end ACK.copy = ACK.copy[in2] ZEN.assert(ACK.copy, "Member not found: "..in2.." in "..in1.." in "..root) end new_codec('copy', { luatype = luatype(ACK.copy) }, root) if ZEN.CODEC.copy.luatype == 'table' then if isdictionary(ACK.copy) then ZEN.CODEC.copy.zentype = 'dictionary' elseif isarray(ACK.copy) then ZEN.CODEC.copy.zentype = 'array' else ZEN.assert(false, "Unknown zentype for lua table element: "..dict.."."..name) end else ZEN.CODEC.copy.zentype = 'element' end end When("create the copy of '' from dictionary ''", function(name, dict) create_copy_f(dict, name) end) When("create the copy of '' from ''", function(name, dict) create_copy_f(dict, name) end) When("create the copy of '' in ''", function(name, dict) create_copy_f(dict, name) end) When("create the copy of '' in '' in ''", function(obj, branch, root) create_copy_f(root, branch, obj) end) When("create the copy of object named by '' from dictionary ''", function(name, dict) local label = have(name) create_copy_f(dict, label:string()) end) When("for each dictionary in '' append '' to ''", function(arr, right, left) local dicts = have(arr) ZEN.assert(luatype(dicts) == 'table', 'Object is not a table: '..arr) for kk,vv in pairs(dicts) do local l, r for k,v in pairs(vv) do if k == right then r = v end if k == left then l = v end end ZEN.assert(l, "Object not found: "..kk.."."..left) ZEN.assert(r, "Object not found: "..kk.."."..right) vv[left] = l..r end end) When("move '' in ''", function(src, dict) local s = have(src) local d = have(dict) ZEN.assert(luatype(d) == 'table', "Object is not a table: "..dict) ZEN.assert(ZEN.CODEC[dict].zentype == 'dictionary' or ZEN.CODEC[dict].zentype == 'schema', "Object is not a schema or dictionary: "..dict) d[src] = s ACK[src] = nil end) When("filter '' fields from ''", function(filters, target) local t = have(target) ZEN.assert(isdictionary(target), "Object is not a dictionary: "..target) local f = have(filters) ZEN.assert(isarray(filters), "Object is not an array: "..filters) if isarray(t) then -- array of dictionaries for ak,av in pairs(t) do for k,_ in pairs(av) do keep = false for _, fv in pairs(f) do if fv:str() == k then keep = true end end if not keep then t[ak][k] = nil end end end else for k,_ in pairs(t) do for _, fv in pairs(f) do if k ~= fv then t[k] = nil end end end end end) H--[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Alberto Lerda -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --]] local btc = {} -- A bitcoin address is unique given the public key -- address = RIPEMD160(SHA256(public_key)) -- the composition of RIPEMD160 and SHA256 is known as HASH160 function btc.address_from_public_key(public_key) return HASH.hash160(public_key) end -- The user knows his private key in the WIF format (base58) -- This function compute the bytes of the private key (an octet) -- from the WIF format -- @param wif Private key in WIF format -- @return Private key octet function btc.wif_to_sk(wif) if not type(wif) == 'zenroom.octet' then error("invalid bitcoin key type, not an octet: "..type(wif), 3) end local len = #wif if not (len == 32+6) then error("Invalid bitcoin key, wrong WIF size: "..len.." bytes", 3) end local ver = wif:chop(1):hex() if not(ver == 'ef' or ver == '80') then error("Invalid bitcoin key version: "..ver, 3) end local compress = wif:sub(34,34):hex() if not(compress == '01') then error("Invalid bitcoin key compression byte: "..wif:sub(len, len):hex(), 3) end local data = wif:sub(1, len-4) local check = HASH.dsha256(data):chop(4) if not(wif:sub(len-3, len) == check) then error("Invalid bitcoin key: checksum mismatch", 3) end return wif:sub(2,len-5) end -- 0x80 = Mainnet -- 0xEF = Testnet function btc.sk_to_wif(sk, vs) local ver if vs == 'testnet' then ver = O.from_hex('EF') else ver = O.from_hex('80') end local res = ver..sk res = res..O.from_hex('01') -- compressed public key res = res..HASH.dsha256(res):chop(4) -- checksum return res end -- variable length encoding for integer based on the -- actual length of the number function btc.encode_compact_size(n) local res, padding, prefix, le -- littleEndian; if type(n) ~= "zenroom.big" then n = INT.new(n) end padding = 0 res = O.new() if n <= INT.new(252) then res = n:octet() else le = n:octet():reverse() prefix = O.new() if n <= INT.new('0xffff') then prefix = O.from_hex('fd') padding = 2 elseif n <= INT.new('0xffffffff') then prefix = O.from_hex('fe') padding = 4 elseif n <= INT.new('0xffffffffffffffff') then prefix = O.from_hex('ff') padding = 8 else padding = #le end res = prefix .. le padding = padding - #le end if padding > 0 then res = res .. O.zero(padding) end return res end local function decode_compact_size_at_index(raw, i) local b1 b1 = tonumber(raw:sub(i,i):hex(), 16) local s, e -- start and end index if b1 < 0xfd then s, e = 1, 1 elseif b1 == 0xfd then s, e = 2, 3 elseif b1 == 0xfe then s, e = 2, 5 else s, e = 2, 9 end return INT.new(raw:sub(i+s-1, i+e-1)), i+e end -- fixed size encoding for integer function btc.to_uint(num, nbytes) if type(num) ~= "zenroom.big" then num = INT.new(num) end num = num:octet():reverse() if #num < nbytes then num = num .. O.zero(nbytes - #num) end return num end -- read little endian number from transaction raw at position i local function read_uint(raw, i, nbytes) return tonumber(raw:sub(i,i+nbytes-1):reverse():hex(), 16), i+nbytes end -- The sender address is not in the raw transaction function btc.decode_raw_transaction(raw, sender_address, amounts_spent) local SCRIPT_SIZE_LIMIT = BIG.from_decimal('10000') local tx local i=1 local scriptBytes tx = {} -- version (little endian) tx.version, i = read_uint(raw, i, 4) assert(tx.version == 1 or tx.version == 2) -- check if this is segwit, BIP 141 segwit = (raw:sub(i, i+1) == O.from_hex('0001')) if segwit then i=i+2 end -- read txin local n_txin n_txin, i = decode_compact_size_at_index(raw, i) tx.txIn = {} for j=1,tonumber(n_txin:octet():hex(), 16),1 do local currIn = {} -- previous output currIn.txid = raw:sub(i, i+32-1):reverse() i=i+32 currIn.vout, i = read_uint(raw, i, 4) currIn.amountSpent = amounts_spent[j] scriptBytes, i = decode_compact_size_at_index(raw, i) assert(scriptBytes < SCRIPT_SIZE_LIMIT) scriptBytes = tonumber(scriptBytes:octet():hex(), 16) if scriptBytes > 0 then -- empty script i = i + scriptBytes end currIn.sequence = raw:sub(i, i+3):reverse() i = i + 4 currIn.address = sender_address table.insert(tx.txIn, currIn) end -- read txout n_txout, i = decode_compact_size_at_index(raw, i) tx.txOut = {} for j=1,tonumber(n_txout:octet():hex(), 16),1 do local currOut = {} currOut.amount = BIG.new(raw:sub(i,i+8-1):reverse()) i=i+8 scriptBytes, i = decode_compact_size_at_index(raw, i) assert(scriptBytes < SCRIPT_SIZE_LIMIT) scriptBytes = tonumber(scriptBytes:octet():hex(), 16) if scriptBytes > 0 then -- decode the script -- the script is 00 ADDRESS_LEN ADDRESS -- test segwit ver 0 script assert(raw:sub(i,i) == O.from_hex('00')) local addressLen = tonumber(raw:sub(i+1,i+1):hex(), 16) assert(2+addressLen == scriptBytes) currOut.address = raw:sub(i+2, i+scriptBytes-1) i = i + scriptBytes end table.insert(tx.txOut, currOut) end -- read witness (if segwit) if segwit then tx.witness = {} for j=1,#tx.txIn,1 do stackSize, i = decode_compact_size_at_index(raw, i) stackSize = tonumber(stackSize:octet():hex(), 16) items = {} for k=1,stackSize,1 do itemBytes, i = decode_compact_size_at_index(raw, i) itemBytes = tonumber(itemBytes:octet():hex(), 16) item = raw:sub(i, i+itemBytes-1) i=i+itemBytes table.insert(items, item) end table.insert(tx.witness, items) end end -- read nlocktime tx.nLockTime, i = read_uint(raw, i, 4) return tx end -- create an octet which is a raw transaction -- works only with Bech32 v0 addresses -- with not coinbase input -- @param tx table which reppresent a transaction -- @return octet raw transaction function btc.build_raw_transaction(tx) local raw, script raw = O.new() sigwit = (tx["witness"] and #tx["witness"]>0) -- version raw = raw .. O.from_hex('02000000') if sigwit then -- marker + flags raw = raw .. O.from_hex('0001') end raw = raw .. btc.encode_compact_size(INT.new(#tx.txIn)) -- txIn for _, v in pairs(tx.txIn) do -- outpoint (hash and index of the transaction) raw = raw .. v.txid:reverse() .. btc.to_uint(v.vout, 4) -- the script depends on the signature script = O.new() raw = raw .. btc.encode_compact_size(#script) .. script -- Sequence number disabled raw = raw .. O.from_hex('ffffffff') end raw = raw .. btc.encode_compact_size(INT.new(#tx.txOut)) -- txOut for k, v in pairs(tx.txOut) do --raw = raw .. btc.to_uint(v.amount, 8) assert(v.address, "Address not found in txout["..k.."]") local amount = O.new(v.amount) raw = raw .. amount:reverse() if #v.amount < 8 then raw = raw .. O.zero(8 - #amount) end -- fixed script to send bitcoins -- OP_DUP OP_HASH160 20byte --script = O.from_hex('76a914') --script = script .. v.address -- OP_EQUALVERIFY OP_CHECKSIG --script = script .. O.from_hex('88ac') -- Bech32 script = O.from_hex('0014') -- readBech32Address(v.address) script = script .. fif(v.address.raw, v.address.raw, v.address) raw = raw .. btc.encode_compact_size(#script) .. script end if sigwit then -- Documentation https://bitcoincore.org/en/segwit_wallet_dev/ -- The documentation talks about "stack items" but it doesn't specify -- which are they, I think that It depends on the type of transaction -- (P2SH or P2PKH) -- The size of witnesses is not necessary because it is equal to the number of -- txin --raw = raw .. btc.encode_compact_size(#tx["witness"]) for _, v in pairs(tx["witness"]) do -- encode all the stack items for the witness raw = raw .. btc.encode_compact_size(#v) for _, s in pairs(v) do raw = raw .. btc.encode_compact_size(#s) raw = raw .. s end end end raw = raw .. O.from_hex('00000000') return raw end local function encode_with_prepend(bytes) if tonumber(bytes:sub(1,1):hex(), 16) >= 0x80 then bytes = O.from_hex('00') .. bytes end return bytes end -- DER is the format used by bitcoin to encode -- ECDSA signatures -- @param sig signature table (with r and s) -- @return octet encoded with DER format function btc.encode_der_signature(sig) local res, tmp; res = O.new() -- r tmp = encode_with_prepend(sig.r) res = res .. O.from_hex('02') .. INT.new(#tmp):octet() .. tmp -- s tmp = encode_with_prepend(sig.s) res = res .. O.from_hex('02') .. INT.new(#tmp):octet() .. tmp res = O.from_hex('30') .. INT.new(#res):octet() .. res return res end local function read_number_from_der(raw, pos) local size assert(raw:sub(pos, pos) == O.from_hex('02')) pos= pos+1 size = tonumber(raw:sub(pos, pos):hex(), 16) pos = pos +1 -- If the first byte is a 0 do not consider it if raw:sub(pos, pos) == O.from_hex('00') then pos = pos +1 size = size -1 end data = raw:sub(pos, pos+size-1) return { data, pos+size } end -- DER is the format used by bitcoin to encode -- ECDSA signatures -- @param raw octet encoded with DER format -- @return signature table (with r and s) function btc.decode_der_signature(raw) local sig, tmp, size; sig = {} assert(raw:chop(1) == O.from_hex('30')) size = tonumber(raw:sub(2,2):hex(), 16) tmp = read_number_from_der(raw, 3) sig.r = tmp[1] tmp = tmp[2] tmp = read_number_from_der(raw, tmp) sig.s = tmp[1] return sig end -- Hash required in the raw transaction (is exposed to be able to use it -- in the tests) local function _hash_prevouts(tx) local raw local H H = HASH.new('sha256') raw = O.new() for _, v in pairs(tx.txIn) do raw = raw .. v.txid:reverse() .. btc.to_uint(v.vout, 4) end return H:process(H:process(raw)) end -- Hash required in the raw transaction (is exposed to be able to use it -- in the tests) local function _hash_sequence(tx) local raw local H local seq H = HASH.new('sha256') raw = O.new() for _, v in pairs(tx.txIn) do seq = v['sequence'] if not seq then -- default value, not enabled seq = O.from_hex('ffffffff') end raw = raw .. btc.to_uint(seq, 4) end return H:process(H:process(raw)) end -- Hash required in the raw transaction (is exposed to be able to use it -- in the tests) local function _hash_outputs(tx) local raw local H H = HASH.new('sha256') raw = O.new() for _, v in pairs(tx.txOut) do amount = O.new(v.amount) raw = raw .. amount:reverse() if #v.amount < 8 then raw = raw .. O.zero(8 - #amount) end -- This is specific to Bech32 addresses, we should be able to verify the kind of address raw = raw .. O.from_hex('160014') .. fif( v.address.raw, v.address.raw, v.address) end return H:process(H:process(raw)) end -- BIP0143 -- Double SHA256 of the serialization of: -- 1. nVersion of the transaction (4-byte little endian) -- 2. hash_prevouts (32-byte hash) -- 3. hash_sequence (32-byte hash) -- 4. outpoint (32-byte hash + 4-byte little endian) -- 5. scriptCode of the input (serialized as scripts inside CTxOuts) -- 6. value of the output spent by this input (8-byte little endian) -- 7. nSequence of the input (4-byte little endian) -- 8. hash_outputs (32-byte hash) -- 9. nLocktime of the transaction (4-byte little endian) -- 10. sighash type of the signature (4-byte little endian) local function build_transaction_to_sign(tx, i) local raw local amount local address = fif(tx.txIn[i].address.raw, tx.txIn[i].address.raw, tx.txIn[i].address) assert(address, "Cannot sign or verify transaction: no address provided") raw = O.new() -- 1. nVersion of the transaction (4-byte little endian) raw = raw .. btc.to_uint(tx.version, 4) -- 2. hash_prevouts (32-byte hash) raw = raw .. _hash_prevouts(tx) -- 3. hash_sequence (32-byte hash) raw = raw .. _hash_sequence(tx) -- 4. outpoint (32-byte hash + 4-byte little endian) raw = raw .. tx.txIn[i].txid:reverse() .. btc.to_uint(tx.txIn[i].vout, 4) -- 5. scriptCode of the input (serialized as scripts inside CTxOuts) raw = raw .. O.from_hex('1976a914') .. address .. O.from_hex('88ac') -- 6. value of the output spent by this input (8-byte little endian) amount = O.new(tx.txIn[i].amountSpent) raw = raw .. amount:reverse() if #amount < 8 then raw = raw .. O.zero(8 - #amount) end -- 7. nSequence of the input (4-byte little endian) raw = raw .. tx.txIn[i].sequence:reverse() -- 8. hash_outputs (32-byte hash) raw = raw .. _hash_outputs(tx) -- 9. nLocktime of the transaction (4-byte little endian) raw = raw .. btc.to_uint(tx.nLockTime, 4) -- 10. sighash type of the signature (4-byte little endian) raw = raw .. btc.to_uint(tx.nHashType, 4) return raw end -- Here I sign the transaction function btc.build_witness(tx, sk) local pk = ECDH.compress_public_key(ECDH.pubgen(sk)) local witness = {} for i=1,#tx.txIn,1 do if tx.txIn[i].sigwit then -- fill address generated from sk if not present in txin local rawTx = build_transaction_to_sign(tx, i) local sigHash = HASH.dsha256(rawTx) local sig = ECDH.sign_ecdh(sk, sigHash) witness[i] = { btc.encode_der_signature(sig) .. O.from_hex('01'), pk } else witness[i] = O.zero(1) end end return witness end function btc.verify_witness(tx) tx.nHashType = O.from_hex('00000001') if tx.witness == nil then return false end for i, v in pairs(tx.witness) do local rawTx = build_transaction_to_sign(tx, i) local sigHash = HASH.dsha256(rawTx) local sig = btc.decode_der_signature(v[1]) if not ECDH.verify_hashed(ECDH.uncompress_public_key(v[2]), sigHash, sig, #sigHash) then return false end end return true end -- Pay attention to the amount, it has to be multiplied for 10^8 -- @param unspent list of unspent transactions -- @param to receiver bitcoin address (must be segwit/Bech32!) -- @param amount satoshi to transfer (BIG integer) -- @param fee satoshi of fee we want to pay -- @return nil if the transaction cannot built -- (for example if there are not enough founds) function btc.build_tx_from_unspent(unspent, to, amount, fee, from) local tx, i, currentAmount tx = { version=2, txIn = {}, txOut = {}, nLockTime=0, nHashType=O.from_hex('00000001') } i=1 currentAmount = INT.new(0) while i <= #unspent and currentAmount < amount+fee do assert(unspent[i].address or from, "No sender address specified") -- amount should be already converted to a zenroom type, if not -- then we assume it is a string value expressed in satoshis local amount = unspent[i].amount if not iszen( type( amount ) ) then amount = BIG.from_decimal( amount ) end currentAmount = currentAmount + amount tx.txIn[i] = { txid = unspent[i].txid, vout = unspent[i].vout, sigwit = O.from_hex('01'), -- this should be true address = unspent[i].address or from, amountSpent = amount, sequence = O.from_hex('ffffffff'), --scriptPubKey = unspent[i].scriptPubKey } i=i+1 end if currentAmount < amount+fee or i==1 then -- Not enough BTC return nil end -- Add exactly two outputs, one for the receiver and one for the exceding amount tx.txOut[1] = { amount = amount, address = to } if currentAmount > amount+fee then tx.txOut[2] = { amount = currentAmount-amount-fee, address = tx.txIn[1].address } end return tx end -- 1 BTC = 1e8 satoshi -- @param value number of BTC as string (digits with a dot) -- @return number of sathosi as zenroom.big function btc.value_btc_to_satoshi(value) pos = value:find("%.") decimals = value:sub(pos+1, #value) if #decimals > 8 then error("Satoshi is the smallest unit of measure") end decimals = decimals .. string.rep("0", 8-#decimals) return BIG.from_decimal(value:sub(1, pos-1) .. decimals) end -- 1 BTC = 1e8 satoshi -- @param value number of sathosi as zenroom.big -- @return number of BTC as string (digits with a dot) function btc.value_satoshi_to_btc(value) local str_value = value:decimal() local len = #str_value local str_btc; if len <= 8 then str_btc = '0.'; for i=1,8-len,1 do str_btc = str_btc .. '0' end str_btc = str_btc .. str_value else str_btc = string.sub(str_value, 1, len-8) .. '.' .. string.sub(str_value, len-7, len) end str_btc = string.gsub(str_btc, '%.?0*$', '') return str_btc end -- function rawTransactionFromJSON(data, sk) -- local obj = JSON.decode(data) -- local sk = btc.read_wif_private_key(sk) -- for k, v in pairs(obj.unspent) do -- v.txid = O.from_hex(v.txid) -- v.amount = valueSatoshiToBTC(v.amount) -- end -- local tx = btc.build_tx_from_unspent(obj.unspent, sk, obj.to, btc.big_from_string(obj.amount), btc.big_from_string(obj.fee)) -- tx.witness = btc.build_witness(tx, sk) -- local rawTx = btc.build_raw_transaction(tx) -- return rawTx -- end return btc --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 13th November 2021 --]] -- override type to recognize zenroom's types luatype = type _G['type'] = function(var) local simple = luatype(var) if simple == "userdata" then local meta = getmetatable(var) if meta then return(meta.__name) else return("unknown") end else return(simple) end end -- TODO: optimise in C function iszen(n) for _ in n:gmatch("zenroom") do return true end return false end -- workaround for a ternary conditional operator function fif(condition, if_true, if_false) if condition then return if_true else return if_false end end function uscore(input) local it = luatype(input) if it == 'string' then return string.gsub(input, ' ', '_') elseif it == 'number' then return input else error("Underscore transform not a string or number: "..it, 2) end end function space(input) local it = luatype(input) if it == 'string' then return string.gsub(input, '_', ' ') elseif it == 'number' then return input else error("Whitespace transform not a string or number: "..it, 2) end end -- debugging facility function xxx(s, n) n = n or 3 if DEBUG >= n then printerr("LUA "..s) end end -- sorted iterator for deterministic ordering of tables -- from: https://www.lua.org/pil/19.3.html _G["lua_pairs"] = _G["pairs"] _G["lua_ipairs"] = _G["ipairs"] local function _pairs(t) local a = {} for n in lua_pairs(t) do table.insert(a, n) end table.sort(a) local i = 0 -- iterator variable return function () -- iterator function i = i + 1 -- if a[i] == nil then return nil return a[i], t[a[i]] end end local function _ipairs(t) local a = {} for n in lua_ipairs(t) do table.insert(a, n) end table.sort(a) local i = 0 -- iterator variable return function () -- iterator function i = i + 1 -- if a[i] == nil then return nil return a[i] end end -- Switch to deterministic (sorted) table iterators: this breaks lua -- tests in particular those stressing i/pairs and pack/unpack, which -- are anyway unnecessary corner cases in zenroom, which exits cleanly -- and signaling a stack overflow. Please report back if this -- generates problems leading to the pairs for loop in function above. _G["sort_pairs"] = _pairs _G["sort_ipairs"] = _pairs function deepcopy(orig) local orig_type = type(orig) local copy if orig_type == 'table' then copy = {} for orig_key, orig_value in next, orig, nil do copy[deepcopy(orig_key)] = deepcopy(orig_value) end setmetatable(copy, deepcopy(getmetatable(orig))) else -- number, string, boolean, etc copy = orig end return copy end -- deep recursive map on a tree structure -- for usage see test/deepmap.lua -- operates only on strings, passes numbers through function deepmap(fun,t,...) local luatype = luatype if luatype(fun) ~= 'function' then error("Internal error: deepmap 1st argument is not a function", 3) return nil end -- if luatype(t) == 'number' then -- return t end if luatype(t) ~= 'table' then error("Internal error: deepmap 2nd argument is not a table", 3) return nil end local res = {} for k,v in pairs(t) do if luatype(v) == 'table' then res[k] = deepmap(fun,v,...) -- recursion else res[k] = fun(v,k,...) end end return setmetatable(res, getmetatable(t)) end function isarray(obj) if not obj then warn("Argument of isarray() is nil") return false end if luatype(obj) == 'string' then -- seach HEAD for ACK[obj] and check its CODEC local o = ACK[obj] if not o then return false end if luatype(o) ~= 'table' then return false end if ZEN.CODEC[obj].zentype == 'array' then return true end return false end if luatype(obj) ~= 'table' then -- warn("Argument of isarray() is not a table") return false end local count = 0 for k, v in pairs(obj) do -- check that all keys are numbers -- don't check sparse ratio (cjson's lua_array_length) if luatype(k) ~= "number" then return false end count = count + 1 end return count end function isdictionary(obj) if not obj then warn("Argument of isdictionary() is nil") return false end if luatype(obj) == 'string' then -- seach HEAD for ACK[obj] and check its CODEC local o = ACK[obj] if not o then return false end if luatype(o) ~= 'table' then return false end if ZEN.CODEC[obj].zentype == 'dictionary' or ZEN.CODEC[obj].zentype == 'schema' then return true end -- TRUE return false end -- check the object itself if luatype(obj) ~= 'table' then return false end -- error("Argument is not a table: "..type(obj) local count = 0 for k, v in pairs(obj) do -- check that all keys are not numbers -- don't check sparse ratio (cjson's lua_array_length) if luatype(k) ~= "string" then return false end count = count + 1 end return count end function array_contains(arr, obj) assert(luatype(arr) == 'table', "Internal error: array_contains argument is not a table") for k, v in pairs(arr) do assert(luatype(k) == 'number', "Internal error: array_contains argument is not an array") if v == obj then return true end end return false end function help(module) if module == nil then print("usage: help(module)") print("example > help(octet)") print("example > help(ecdh)") print("example > help(ecp)") return end for k,v in pairs(module) do if type(v)~='table' and string.sub(k,1,1)~='_' then print("class method: "..k) end end -- local inst = module.new() -- if inst == nil then return end -- for s,f in pairs(getmetatable(inst)) do -- if(string.sub(s,1,2)~='__') then print("object method: "..s) end -- end end -- TODO: optimize in C using strtok local function split(src,pat) local tbl = {} src:gsub(pat, function(x) tbl[#tbl+1]=x end) return tbl end function strtok(src, pat) if not src then return { } end pat = pat or "%S+" ZEN.assert(luatype(src) == "string", "strtok error: argument is not a string") return split(src, pat) end -- assert all values in table are converted to zenroom types -- used in zencode when transitioning out of given memory function zenguard(val) local tv = type(val) if not (tv == 'number' or tv == 'boolean' or iszen(tv)) then I.print(ZEN.heap().ACK) -- xxx("Invalid value: "..val) debug_heap_dump() error("Zenguard detected an invalid value in HEAP: type "..type(val), 2) return nil end end 4--[[ --This file is part of zenroom -- --Copyright (C) 2020-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] -- Lagrange interpolation implementation in Zencode LAG = require_once('crypto_lagrange_interpolation') function single_share_f(o) local obj = deepmap(CONF.input.encoding.fun, o) return { x = ZEN.get(obj, 'x', BIG.new), y = ZEN.get(obj, 'y', BIG.new) } end ZEN.add_schema({ -- single share single_share = single_share_f, -- array of single shares secret_shares = function(obj) local res = { } for k,v in pairs(obj) do res[k] = single_share_f(v) end return res end }) When("create the secret shares of '' with '' quorum ''", function(sec, tot, q) local soct = have(sec) -- this check is relative to the BIG size, established by curve's size -- it is made inside the crypto function, but could also be made here -- local sbig = BIG.new(soct) % ECP.order() -- ZEN.assert(sbig:octet() == soct, "Secret too big to share: "..#soct.." bytes") local total = tonumber(tot) ZEN.assert(total, "Total shares is not a number: "..tot) local quorum = tonumber(q) ZEN.assert(quorum, "Quorum shares is not a number: "..q) ACK.secret_shares = LAG.create_shared_secret(total,quorum,soct) end) When("compose the secret using ''", function(shares) local sh = have(shares) ACK.secret = LAG.compose_shared_secret(sh) end) --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local octet = require'octet' --- implicit convertion functions going both ways -- if input is an encoded string, will become an octet -- if input is a non-encoded string, it will become a base64 string -- if input is an octet, will become an encoded string function hex(data) local t = type(data) if(t == "string") then if O.is_hex(data) then return O.from_hex(data) else return O.from_str(data):hex() end elseif(t == "number") then return data elseif(t == "table") then return data elseif iszen(t) then return data:octet():hex() -- any zenroom type to octet end end function str(data) local t = type(data) if(t == "string") and data ~= "" then if OCTET.is_url64(data) then -- return decoded string format for JSON.decode return OCTET.from_url64(data):str() elseif OCTET.is_base64(data) then -- return decoded string format for JSON.decode return OCTET.from_base64(data):str() elseif OCTET.is_base58(data) then -- return decoded string format for JSON.decode return OCTET.from_base58(data):str() elseif OCTET.is_hex(data) then -- return decoded string format for JSON.decode return OCTET.from_hex(data):str() elseif OCTET.is_bin(data) then -- return decoded string format for JSON.decode return OCTET.from_bin(data):str() else -- its already a string (we suppose, this is not deterministic) return data end elseif iszen(t) then return data:octet():str() else error("automatic str() conversion failed for type: "..t) end end function bin(data) local t = type(data) if(t == "string") then if O.is_bin(data) then return O.from_bin(data) else return O.from_str(data):bin() end elseif(t == "number") then return data elseif(t == "table") then return data elseif iszen(t) then return data:octet():bin() -- any zenroom type to octet end end function base64(data) if not data then error("Internal data conversion on nil",2) end local t = type(data) if(t == "string") then if O.is_base64(data) then return O.from_base64(data) else return O.from_str(data):base64() end elseif(t == "number") then return data elseif(t == "table") then return data elseif iszen(t) then return data:octet():base64() -- any zenroom type to octet end end function url64(data) if not data then error("Internal data conversion on nil",2) end local t = type(data) if(t == "string") then if O.is_url64(data) then return O.from_url64(data) else return O.from_str(data):url64() end elseif(t == "number") then return data elseif(t == "table") then return data elseif iszen(t) then return data:octet():url64() -- any zenroom type to octet end end function base58(data) local t = type(data) if(t == "string") then if O.is_base58(data) then return O.from_base58(data) else return O.from_str(data):base58() end elseif iszen(t) then return data:octet():base58() -- any zenroom type to octet end end return octet --[[ --This file is part of zenroom -- --Copyright (C) 2020-2021 Dyne.org foundation -- Implementation by Alberto Ibrisevich and Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Alberto Lerda --on Tuesday, 04th October 2021 --]] local li = { _VERSION = 'crypto_lagrange_interpolation.lua 1.0', _URL = 'https://zenroom.dyne.org', _DESCRIPTION = 'Secret Sharing based on BIG INT using Lagrange Interpolation over 1st order elliptic curves",Attribute-based credential system supporting multiple unlinkable private attribute revelations', _LICENSE = [[ Licensed under the terms of the GNU Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ]] } -- the biggest prime less than 2^(32*8) -- computed with -- i:=2^(32*8); -- while i ge 2^(31*8) do -- if IsPrime(i) then -- print(i); -- break; -- end if; -- i:=i-1; -- end while; -- at http://magma.maths.usyd.edu.au/calc/ -- 115792089237316195423570985008687907853269984665640564039457584007913129639747 octP = O.from_hex('ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43') P = BIG.new(octP) assert(P:octet() == octP) function li.create_shared_secret(total, quorum, secret) if quorum >= total then error('Error calling create_shared_secret: quorum ('..quorum..') must be smaller than total ('..total..')', 2) end -- check that BIG can contain the whole secret, depends from curve's size and the choosen prime P local secbig = BIG.new(secret) if secbig:octet() ~= secret or secbig > P then error('Secret exceeds maximum BIG size: '..#O..' bytes or the size of the choosen prime') end secbig = secbig % P -- generation of the coefficients of the secret polynomial local coeff = { } -- take last argument or create random if secret then coeff[1] = BIG.new(secret) else coeff[1] = BIG.modrand(P) end for i=2,quorum,1 do coeff[i] = BIG.modrand(P) end --generation of the shares local shares = { } for i=1,total,1 do local x repeat x = BIG.modrand(P) if x ~=0 then --checking for duplicates in shares for _, k in pairs(shares) do if x == k then x = 0 end end end until x ~= 0 --this part provides trivial unleakability: x coordinate is never zero local y = coeff[1] --a_0 local x_n = BIG.new(1) for n=2,quorum,1 do x_n = x_n:modmul(x, P) -- x^(n-1) y = BIG.add(y, coeff[n]:modmul(x_n, P)) y = BIG.mod(y, P) -- +a_(n-1)x^(n-1) end table.insert(shares, {x = x, y = y}) end -- for i,total -- overwrite secret for secure disposal return shares, coeff[1] end function li.compose_shared_secret(shares) local sec = BIG.new(0) local num local den local quorum = #shares for i = 1,quorum,1 do num = BIG.new(1) if quorum % 2 == 0 then num = P - num end den = BIG.new(1) for j = 1,quorum,1 do if j~=i then num = num:modmul(shares[j].x, P) den = den:modmul((shares[i].x):modsub(shares[j].x, P), P) end end sec = BIG.add(sec, (shares[i].y):modmul(num:moddiv(den, P), P)) sec = BIG.mod(sec, P) end return sec end return li ;&--[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 13th November 2021 --]] -- TODO: use strict table -- https://stevedonovan.github.io/Penlight/api/libraries/pl.strict.html -- the main security concern in this Zencode module is that no data -- passes without validation from IN to ACK or from inline input. -- GIVEN local function gc() TMP = {} collectgarbage 'collect' end -- safely take any zenroom object as index local function _index_to_string(what) local t = type(what) if t == 'string' then return what elseif iszen(t) then return what:octet():string() end error("Invalid type to index variable in heap: "..t, 3) return nil end --- -- Pick a generic data structure from the IN memory -- space. Looks for named data on the first and second level and makes -- it ready in TMP for @{validate} or @{ack}. -- -- @function pick(name, data, encoding) -- @param what string descriptor of the data object -- @param conv[opt] optional encoding spec (default CONF.input.encoding) -- @return true or false local function pick(what, conv) local guess local data local raw local name = _index_to_string(what) raw = KIN[name] or IN[name] if not raw then error("Cannot find '" .. name .. "' anywhere (null value?)", 2) end if raw == '' then error("Found empty string in '" .. name) end -- if not conv and ZEN.schemas[what] then conv = what end TMP = guess_conversion(raw, conv or name) if not TMP then error('Cannot guess any conversion for: ' .. luatype(raw) .. ' ' .. (conv or name or '(nil)')) end TMP.name = name TMP.schema = conv assert(ZEN.OK) if DEBUG > 1 then ZEN:ftrace('pick found ' .. name .. '('..TMP.zentype..')') end end --- -- Pick a data structure named 'what' contained under a 'section' key -- of the at the root of the IN memory space. Looks for named -- data at the first and second level underneath IN[section] and moves -- it to TMP[what][section], ready for @{validate} or @{ack}. If -- TMP[what] exists already, every new entry is added as a key/value -- -- @function pickin(section, name) -- @param section string descriptor of the section containing the data -- @param what string descriptor of the data object -- @param conv string explicit conversion or schema to use -- @param fail bool bail out or continue on error -- @return true or false local function pickin(section, what, conv, fail) ZEN.assert(section, 'No section specified') local root -- section local raw -- data pointer local bail -- fail local name = _index_to_string(what) root = KIN[section] if root then raw = root[name] if raw then goto found end end root = IN[section] if root then raw = root[name] if raw then goto found end end -- TODO: check all corner cases to make sure TMP[name] is a k/v map ::found:: if not raw then error("Cannot find '" .. name .. "' inside '" .. section .. "' (null value?)",2) end if raw == '' then error("Found empty string '" .. name .."' inside '"..section.."'", 2) end -- conv = conv or name -- if not conv and ZEN.schemas[name] then conv = name end -- if no encoding provided then conversion is same as name (schemas etc.) TMP = guess_conversion(raw, conv or name) TMP.name = name TMP.root = section TMP.schema = conv assert(ZEN.OK) if DEBUG > 1 then ZEN:ftrace('pickin found ' .. name .. ' in ' .. section) end end local function ack_table(key, val) ZEN.assert( type(key) == 'string', 'ZEN:table_add arg #1 is not a string' ) ZEN.assert( type(val) == 'string', 'ZEN:table_add arg #2 is not a string' ) if not ACK[key] then ACK[key] = {} end ACK[key][val] = operate_conversion(TMP) ZEN.CODEC[key] = { name = TMP.name, luatype = 'table', zentype = 'dictionary', encoding = TMP.encoding, root = TMP.root } -- name of schema may differ from name of object if TMP.schema and ( TMP.schema ~= TMP.encoding ) then ZEN.CODEC[key].schema = TMP.schema end end --- -- Final step inside the Given block towards the When: -- pass on a data structure into the ACK memory space, ready for -- processing. It requires the data to be present in TMP[name] and -- typically follows a @{pick}. In some restricted cases it is used -- inside a When block following the inline insertion of data -- from zencode. -- -- @function ack(name) -- @param name string key of the data object in TMP[name] local function ack(what) local name = _index_to_string(what) ZEN.assert(TMP, 'No valid object found: ' .. name) -- CODEC[what] = CODEC[what] or { -- name = guess.name, -- istable = guess.istable, -- isschema = guess.isschema } ZEN.assert( not ACK[name], 'Destination already exists, cannot overwrite: ' .. name, 2 ) assert(ZEN.OK) ACK[name] = operate_conversion(TMP) -- also creates codec insice operate conversion -- name of schema may differ from name of object if TMP.schema and ( TMP.schema ~= TMP.encoding ) then ZEN.CODEC[name].schema = TMP.schema end -- ACK[name] already holds an object -- not a table? -- if not (dsttype == 'table') then -- convert single object to array -- ACK[name] = { ACK[name] } -- table.insert(ACK[name], operate_conversion(TMP)) -- goto done -- end -- -- it is a table already -- if isarray(ACK[name]) then -- plain array -- table.insert(ACK[name], operate_conversion(TMP)) -- goto done -- else -- associative map (dictionary) -- table.insert(ACK[name], operate_conversion(TMP)) -- TODO: associative map insertion -- goto done -- end -- ::done:: -- assert(ZEN.OK) end Given( 'nothing', function() ZEN.assert( (next(IN) == nil) and (next(KIN) == nil), 'Undesired data passed as input' ) end ) -- maybe TODO: Given all valid data -- convert and import data only when is known by schema and passes validation -- ignore all other data structures that are not known by schema or don't pass validation Given( "am ''", function(name) Iam(name) end ) Given( "my name is in a '' named ''", function(sc, name) pick(name, sc) assert(TMP.name, 'No name found in: ' .. name) Iam(O.to_string(operate_conversion(TMP))) end ) Given( "my name is in a '' named '' in ''", function(sc, name, struct) pickin(struct, name, sc) assert(TMP.name, 'No name found in: '..name) Iam(O.to_string(operate_conversion(TMP))) end ) -- variable names: -- s = schema of variable (or encoding) -- n = name of variable -- t = table containing the variable -- TODO: I have a '' as '' Given( "a ''", function(n) pick(n) ack(n) gc() end ) Given( "a '' in ''", function(s, t) pickin(t, s) ack(s) -- save it in ACK.obj gc() end ) -- public keys for keyring arrays -- returns a special array for upcoming session: -- public_key_session : { name : value } Given( "a '' public key from ''", function(s, t) -- if not pickin(t, s, nil, false) then -- pickin(s, t) -- end pickin(t, s..'_public_key', s..'_public_key', false) ack_table('public_key_session', t) end ) Given( "a '' from ''", function(s, t) -- if not pickin(t, s, nil, false) then -- pickin(s, t) -- end pickin(t, s, s, false) ack_table(s, t) gc() end ) Given( "a '' named ''", function(s, n) -- ZEN.assert(encoder, "Invalid input encoding for '"..n.."': "..s) pick(n, s) ack(n) gc() end ) Given( "a '' named by ''", function(s, n) -- local name = have(n) local name = _index_to_string(KIN[n] or IN[n]) -- ZEN.assert(encoder, "Invalid input encoding for '"..n.."': "..s) pick(name, s) ack(name) gc() end ) Given( "a '' named '' in ''", function(s, n, t) pickin(t, n, s) ack(n) -- save it in ACK.name gc() end ) Given( "a '' named by '' in ''", function(s, n, t) local name = _index_to_string(KIN[n] or IN[n]) pickin(t, name, s) ack(name) -- save it in ACK.name gc() end ) Given( "my ''", function(n) ZEN.assert(WHO, 'No identity specified, use: Given I am ...') pickin(WHO, n) ack(n) gc() end ) Given( "my '' named ''", function(s, n) -- ZEN.assert(encoder, "Invalid input encoding for '"..n.."': "..s) pickin(WHO, n, s) ack(n) gc() end ) Given( "my '' named by ''", function(s, n) -- ZEN.assert(encoder, "Invalid input encoding for '"..n.."': "..s) local name = _index_to_string(KIN[n] or IN[n]) pickin(WHO, name, s) ack(name) gc() end ) Given( "a '' is valid", function(n) pick(n) gc() end ) Given( "my '' is valid", function(n) pickin(WHO, n) gc() end ) O--[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 13th November 2021 --]] ---

Zencode language parser

-- -- Zencode is a Domain -- Specific Language (DSL) made to be understood by humans. Its -- purpose is detailed in the -- Zencode Whitepaper and DECODE EU project. -- -- @module ZEN -- -- @author Denis "Jaromil" Roio -- @license AGPLv3 -- @copyright Dyne.org foundation 2018-2020 -- -- The Zenroom VM is capable of parsing specific scenarios written in -- Zencode and execute high-level cryptographic operations described -- in them; this is to facilitate the integration of complex -- operations in software and the non-literate understanding of what a -- distributed application does. -- -- This section doesn't provide the documentation on how to write -- Zencode. Refer to the links above to learn it. This documentation -- continues to illustrate internals: how the Zencode direct-syntax -- parser is made, how it integrates in the Zenroom memory model. -- This is also the reference implementation to learn how to code -- Zencode simple scenario using Zeroom's Lua. -- -- @module ZEN local zencode = { given_steps = {}, when_steps = {}, if_steps = {}, then_steps = {}, schemas = {}, branch = false, branch_valid = false, id = 0, AST = {}, traceback = {}, -- execution backtrace eval_cache = {}, -- zencode_eval if...then conditions checks = {version = false}, -- version, scenario checked, etc. OK = true -- set false by asserts } -- set_sentence -- set_rule local function set_sentence(self, event, from, to, ctx) local index = self.current if self.current == 'whenif' then index = 'when' end if self.current == 'thenif' then index = 'then' end local reg = ctx.Z[index .. '_steps'] ctx.Z.OK = false xxx('Zencode parser from: ' .. from .. " to: "..to, 3) assert(reg,'Callback register not found: ' .. self.current) assert(#reg,'Callback register empty: '..self.current) local gsub = string.gsub -- optimization -- TODO: optimize in C -- remove '' contents, lower everything, expunge prefixes -- ignore 'the' only in Then statements local tt = gsub(ctx.msg, "'(.-)'", "''") -- msg trimmed on parse tt = gsub(tt, ' I ', ' ', 1) -- eliminate first person pronoun tt = tt:lower() -- lowercase all statement if to == 'then' then tt = gsub(tt, ' the ', ' ', 1) end if to == 'given' then tt = gsub(tt, ' the ', ' a ', 1) tt = gsub(tt, ' have ', ' ', 1) end -- prefixes found at beginning of statement tt = gsub(tt, '^when ', '', 1) tt = gsub(tt, '^then ', '', 1) tt = gsub(tt, '^given ', '', 1) tt = gsub(tt, '^if ', '', 1) tt = gsub(tt, '^and ', '', 1) -- TODO: expunge only first 'and' -- generic particles tt = gsub(tt, '^that ', ' ', 1) tt = gsub(tt, ' valid ', ' ', 1) -- backward compat tt = gsub(tt, ' known as ', ' ', 1) tt = gsub(tt, ' all ', ' ', 1) tt = gsub(tt, ' inside ', ' in ', 1) -- equivalence tt = gsub(tt, '^an ', 'a ', 1) tt = gsub(tt, ' +', ' ') -- eliminate multiple internal spaces -- TODO: OPTIMIZE here to avoid iteration over all zencode language every time for pattern, func in pairs(reg) do if (type(func) ~= 'function') then error('Zencode function missing: ' .. pattern, 2) return false end -- xxx(tt .. ' == ' ..pattern) if strcasecmp(tt, pattern) then local args = {} -- handle multiple arguments in same string for arg in string.gmatch(ctx.msg, "'(.-)'") do -- convert all spaces to underscore in argument strings arg = uscore(arg, ' ', '_') table.insert(args, arg) end ctx.Z.id = ctx.Z.id + 1 -- AST data prototype table.insert( ctx.Z.AST, { id = ctx.Z.id, -- ordered number args = args, -- array of vars source = ctx.msg, -- source text section = self.current, from = from, to = to, hook = func } ) -- function ctx.Z.OK = true break end end if not ctx.Z.OK and CONF.parser.strict_match then debug_traceback() exitcode(1) error('Zencode pattern not found ('..index..'): ' .. trim(ctx.msg), 1) return false elseif not ctx.Z.OK and not CONF.parser.strict_match then warn('Zencode pattern ignored: ' .. trim(ctx.msg), 1) end end local function set_rule(text) local res = false local tr = text.msg:gsub(' +', ' ') -- eliminate multiple internal spaces local rule = strtok(trim(tr):lower()) if rule[2] == 'check' and rule[3] == 'version' and rule[4] then -- TODO: check version of running VM -- elseif rule[2] == 'load' and rule[3] then -- act("zencode extension: "..rule[3]) -- require("zencode_"..rule[3]) local ver = V(rule[4]) -- SEMVER if ver == ZENROOM_VERSION then act('Zencode version match: ' .. ZENROOM_VERSION.original) res = true elseif ver < ZENROOM_VERSION then warn('Zencode written for an older version: ' .. ver.original) res = true elseif ver > ZENROOM_VERSION then warn('Zencode written for a newer version: ' .. ver.original) res = true else error('Version check error: ' .. rule[4]) end text.Z.checks.version = res elseif rule[2] == 'input' and rule[3] then -- rule input encoding|format '' if rule[3] == 'encoding' and rule[4] then CONF.input.encoding = input_encoding(rule[4]) res = true and CONF.input.encoding elseif rule[3] == 'format' and rule[4] then CONF.input.format = get_format(rule[4]) res = true and CONF.input.format elseif rule[3] == 'untagged' then res = true CONF.input.tagged = false end elseif rule[2] == 'output' and rule[3] then -- TODO: rule debug [ format | encoding ] -- rule input encoding|format '' if rule[3] == 'encoding' then CONF.output.encoding = { fun = guess_outcast(rule[4]), name = rule[4] } res = true and CONF.output.encoding elseif rule[3] == 'format' then CONF.output.format = get_format(rule[4]) res = true and CONF.output.format elseif rule[3] == 'versioning' then CONF.output.versioning = true res = true elseif strcasecmp(rule[3], 'ast') then CONF.output.AST = true res = true end elseif rule[2] == 'unknown' and rule[3] then if rule[3] == 'ignore' then CONF.parser.strict_match = false res = true end elseif rule[2] == 'collision' and rule[3] then if rule[3] == 'ignore' then CONF.heap.check_collision = false res = true end -- alias of unknown ignore for specific callers elseif rule[2] == 'caller' and rule[3] then if rule[3] == 'restroom-mw' then CONF.parser.strict_match = false CONF.heap.check_collision = false res = true end elseif rule[2] == 'set' and rule[4] then CONF[rule[3]] = fif( tonumber(rule[4]), tonumber(rule[4]), fif( rule[4]=='true', true, fif( rule[4]=='false', false, rule[4]))) res = true end if not res then error('Rule invalid: ' .. text.msg, 3) else act(text.msg) end return res end local function new_state_machine() -- stateDiagram -- [*] --> Given -- Given --> When -- When --> Then -- state branch { -- IF -- when then -- -- -- EndIF -- } -- When --> branch -- branch --> When -- Then --> [*] local machine = MACHINE.create( { initial = 'init', events = { {name = 'enter_rule', from = {'init', 'rule', 'scenario'}, to = 'rule'}, {name = 'enter_scenario', from = {'init', 'rule', 'scenario'}, to = 'scenario'}, {name = 'enter_given', from = {'init', 'rule', 'scenario'}, to = 'given'}, {name = 'enter_given', from = {'given'}, to = 'given'}, {name = 'enter_when', from = {'given', 'when', 'then', 'endif'}, to = 'when'}, {name = 'enter_then', from = {'given', 'when', 'then', 'endif'}, to = 'then'}, {name = 'enter_if', from = {'if', 'given', 'when', 'then', 'endif'}, to = 'if'}, {name = 'enter_whenif', from = {'if', 'whenif', 'thenif'}, to = 'whenif'}, {name = 'enter_thenif', from = {'if', 'whenif', 'thenif'}, to = 'thenif'}, {name = 'enter_endif', from = {'whenif', 'thenif'}, to = 'endif'}, {name = 'enter_and', from = 'given', to = 'given'}, {name = 'enter_and', from = 'when', to = 'when'}, {name = 'enter_and', from = 'then', to = 'then'}, {name = 'enter_and', from = 'whenif', to = 'whenif'}, {name = 'enter_and', from = 'thenif', to = 'thenif'}, {name = 'enter_and', from = 'if', to = 'if'} }, -- graph TD -- Given --> When -- IF --> When -- Then --> When -- Given --> IF -- When --> IF -- Then --> IF -- IF --> Then -- When --> Then -- Given --> Then callbacks = { -- msg is a table: { msg = "string", Z = ZEN (self) } onscenario = function(self, event, from, to, msg) -- first word until the colon local scenarios = strtok(string.match(trim(msg.msg):lower(), '[^:]+')) for k, scen in ipairs(scenarios) do if k ~= 1 then -- skip first (prefix) load_scenario('zencode_' .. trimq(scen)) ZEN:trace('Scenario ' .. scen) return end end end, onrule = function(self, event, from, to, msg) -- process rules immediately if msg then set_rule(msg) end end, ongiven = set_sentence, onwhen = set_sentence, onif = set_sentence, onendif = set_sentence, onthen = set_sentence, onand = set_sentence, onwhenif = set_sentence, onthenif = set_sentence } } ) return machine end -- Zencode HEAP globals IN = {} -- Given processing, import global DATA from json KIN = {} -- Given processing, import global KEYS from json TMP = TMP or {} -- Given processing, temp buffer for ack*->validate->push* ACK = ACK or {} -- When processing, destination for push* OUT = OUT or {} -- print out AST = AST or {} -- AST of parsed Zencode WHO = nil -- init statements zencode.endif_steps = { endif = function() return end } --nop function Given(text, fn) assert( not ZEN.given_steps[text], 'Conflicting GIVEN statement loaded by scenario: ' .. text, 2 ) ZEN.given_steps[text] = fn end function When(text, fn) assert( not ZEN.when_steps[text], 'Conflicting WHEN statement loaded by scenario: ' .. text, 2 ) ZEN.when_steps[text] = fn end function IfWhen(text, fn) assert( not ZEN.if_steps[text], 'Conflicting IF-WHEN statement loaded by scenario: ' .. text, 2 ) assert( not ZEN.when_steps[text], 'Conflicting IF-WHEN statement loaded by scenario: ' .. text, 2 ) ZEN.if_steps[text] = fn ZEN.when_steps[text] = fn end function Then(text, fn) assert( not ZEN.then_steps[text], 'Conflicting THEN statement loaded by scenario : ' .. text, 2 ) ZEN.then_steps[text] = fn end --- -- Declare 'my own' name that will refer all uses of the 'my' pronoun -- to structures contained under this name. -- -- @function Iam(name) -- @param name own name to be saved in WHO function Iam(name) if name then ZEN.assert(not WHO, 'Identity already defined in WHO') ZEN.assert(type(name) == 'string', 'Own name not a string') WHO = name else ZEN.assert(WHO, 'No identity specified in WHO') end assert(ZEN.OK) end -- init schemas function zencode.add_schema(arr) local _illegal_schemas = { -- const whoami = true } for k, v in pairs(arr) do -- check overwrite / duplicate to avoid scenario namespace clash if ZEN.schemas[k] then error('Add schema denied, already registered schema: ' .. k, 2) end if _illegal_schemas[k] then error('Add schema denied, reserved name: ' .. k, 2) end ZEN.schemas[k] = v end end function have(obj) -- accepts arrays for depth checks local res if luatype(obj) == 'table' then local prev = ACK for k, v in ipairs(obj) do res = prev[uscore(v)] if not res then error('Cannot find object: ' .. v, 2) end prev = res end else res = ACK[uscore(obj)] if not res then error('Cannot find object: ' .. obj, 2) end end return res end function empty(obj) -- convert all spaces to underscore in argument if ACK[uscore(obj)] then error('Cannot overwrite existing object: ' .. obj, 2) end end --------------------------------------------------------------- -- ZENCODE PARSER local function zencode_iscomment(b) local x = string.char(b:byte(1)) if x == '#' then return true else return false end end local function zencode_isempty(b) if b == nil or b == '' then return true else return false end end -- returns an iterator for newline termination local function zencode_newline_iter(text) s = trim(text) -- implemented in zen_io.c if s:sub(-1) ~= '\n' then s = s .. '\n' end return s:gmatch('(.-)\n') -- iterators return functions end function zencode:begin() self.id = 0 self.AST = {} self.eval_cache = {} self.checks = {version = false} -- version, scenario checked, etc. self.OK = true -- set false by asserts self.traceback = {} -- Reset HEAP self.machine = {} IN = {} -- Given processing, import global DATA from json KIN = {} -- Given processing, import global KEYS from json TMP = {} -- Given processing, temp buffer for ack*->validate->push* ACK = {} -- When processing, destination for push* OUT = {} -- print out AST = {} -- AST of parsed Zencode self.CODEC = {} -- saves input conversions for to decode using same WHO = nil collectgarbage 'collect' -- Zencode init traceback self.machine = new_state_machine() end function zencode:parse(text) if #text < 9 then -- strlen("and debug") == 9 warn("Zencode text too short to parse") return false end local linenum=0 -- xxx(text,3) local prefix local branching = false local parse_prefix = parse_prefix -- optimization for line in zencode_newline_iter(text) do linenum = linenum + 1 local tline = trim(line) -- saves trims in isempty / iscomment if zencode_isempty(tline) then goto continue end if zencode_iscomment(tline) then goto continue end -- xxx('Line: '.. text, 3) -- max length for single zencode line is #define MAX_LINE -- hard-coded inside zenroom.h prefix = parse_prefix(line) -- trim is included assert(prefix, "Invalid Zencode line "..linenum..": "..line) self.OK = true exitcode(0) if prefix == 'if' then branching = true end if branching and (prefix == 'when') then prefix = prefix..'if' end if branching and (prefix == 'then') then prefix = prefix..'if' end if prefix == 'endif' then branching = false end -- try to enter the machine state named in prefix -- xxx("Zencode machine enter_"..prefix..": "..text, 3) local fm = self.machine["enter_"..prefix] assert(fm, "Invalid Zencode line "..linenum..": '"..line.."'") assert(fm(self.machine, { msg = tline, Z = self }), line.."\n ".. "Invalid transition from: "..self.machine.current) ::continue:: end collectgarbage'collect' return true end function zencode:trace(src) -- take current line of zencode local tr = trim(src) -- TODO: tabbing, ugly but ok for now if string.sub(tr, 1, 1) == '[' then table.insert(self.traceback, tr) else table.insert(self.traceback, ' . ' .. tr) end end -- trace function execution also on success function zencode:ftrace(src) -- take current line of zencode table.insert(self.traceback, ' D ZEN:' .. trim(src)) end -- log zencode warning in traceback function zencode:wtrace(src) -- take current line of zencode table.insert(self.traceback, ' W ZEN:' .. trim(src)) end local function IN_uscore(i) -- convert all element keys of IN to underscore local res = {} for k,v in pairs(i) do if luatype(v) == 'table' then res[uscore(k)] = IN_uscore(v) -- recursion else res[uscore(k)] = v end end return setmetatable(res, getmetatable(i)) end -- return true: caller skip execution and go to ::continue:: -- return false: execute statement local function manage_branching(x) if x.section == 'if' then --xxx("START conditional execution: "..x.source, 2) if not ZEN.branch then ZEN.branch_valid = true end ZEN.branch = true return false end if x.section == 'endif' then --xxx("END conditional execution: "..x.source, 2) ZEN.branch = false return true end if not ZEN.branch then return false end if not ZEN.branch_valid then --xxx('skip execution in false conditional branch: '..x.source, 2) return true end return false end function zencode:run() -- runtime checks if not ZEN.checks.version then warn( 'Zencode is missing version check, please add: rule check version N.N.N' ) end -- HEAP setup IN = {} -- import global DATA from json if DATA then -- if plain array conjoin into associative IN = CONF.input.format.fun(DATA) or {} DATA = nil end KIN = {} -- import global KEYS from json if KEYS then KIN = CONF.input.format.fun(KEYS) or {} KEYS = nil end collectgarbage 'collect' -- convert all spaces in keys to underscore IN = IN_uscore(IN) KIN = IN_uscore(KIN) -- check name collisions between DATA and KEYS if CONF.heap.check_collision then for k in pairs(IN) do if KIN[k] then error("Object name collision in input: "..k) end end end -- EXEC zencode for _, x in pairs(self.AST) do -- ZEN:trace(x.source) if manage_branching(x) then goto continue end -- trigger upon switch to when or then section if x.from == 'given' and x.to ~= 'given' then -- delete IN memory KIN = {} IN = {} collectgarbage 'collect' end -- HEAP integrity guard if CONF.heapguard then -- guard ACK's contents on section switch deepmap(zenguard, ACK) end ZEN.OK = true exitcode(0) local ok, err = pcall(x.hook, table.unpack(x.args)) if not ok or not ZEN.OK then if err then ZEN:trace('[!] ' .. err) end fatal(x.source) -- traceback print inside end collectgarbage 'collect' ::continue:: end -- PRINT output ZEN:trace('--- Zencode execution completed') if type(OUT) == 'table' then ZEN:trace('<<< Encoding { OUT } to JSON ') -- this is all already encoded -- needs to be formatted -- was used CONF.output.format.fun -- suspended until more formats are implemented print( JSON.encode(OUT) ) ZEN:trace('>>> Encoding successful') else -- this should never occur in zencode, OUT is always a table ZEN:trace('<<< Printing OUT (plain format, not a table)') print(OUT) end end function zencode.serialize(A) local t = luatype(A) if t == 'table' then local res res = serialize(A) return OCTET.from_string(res.strings) .. res.octets elseif t == 'number' then return O.from_string(tostring(A)) elseif t == 'string' then return O.from_string(A) else local zt = type(A) if not iszen(zt) then error('Cannot convert value to octet: '..zt, 2) end -- all zenroom types have :octet() method to export return A:octet() end error('Unknown type, cannot convert to octet: '..type(A), 2) end function zencode.heap() return ({ IN = IN, KIN = KIN, TMP = TMP, ACK = ACK, OUT = OUT }) end function zencode.debug() debug_traceback() debug_heap_dump() -- I.warn(ZEN.traceback) -- I.warn({ HEAP = { IN = IN, -- TMP = TMP, -- ACK = ACK, -- OUT = OUT }}) end function zencode.debug_json() write( JSON.encode( { TRACE = ZEN.traceback, HEAP = { IN = IN, TMP = TMP, ACK = ACK, OUT = OUT } } ) ) end function zencode.assert(condition, errmsg) if condition then return true else ZEN.branch_valid = false end -- in conditional branching ZEN.assert doesn't quit if ZEN.branch then ZEN:trace(errmsg) xxx(errmsg) else -- ZEN.debug() -- prints all data in memory ZEN:trace('ERR ' .. errmsg) ZEN.OK = false exitcode(1) error(errmsg, 3) end end return zencode local machine = {} machine.__index = machine local NONE = "none" local ASYNC = "async" local function call_handler(handler, params) if handler then return handler(table.unpack(params)) end end local function create_transition(name) local can, to, from, params local function transition(self, ...) if self.asyncState == NONE then can, to = self:can(name) from = self.current params = { self, name, from, to, ...} if not can then return false end self.currentTransitioningEvent = name local beforeReturn = call_handler(self["onbefore" .. name], params) local leaveReturn = call_handler(self["onleave" .. from], params) if beforeReturn == false or leaveReturn == false then return false end self.asyncState = name .. "WaitingOnLeave" if leaveReturn ~= ASYNC then transition(self, ...) end return true elseif self.asyncState == name .. "WaitingOnLeave" then self.current = to local enterReturn = call_handler(self["onenter" .. to] or self["on" .. to], params) self.asyncState = name .. "WaitingOnEnter" if enterReturn ~= ASYNC then transition(self, ...) end return true elseif self.asyncState == name .. "WaitingOnEnter" then call_handler(self["onafter" .. name] or self["on" .. name], params) call_handler(self["onstatechange"], params) self.asyncState = NONE self.currentTransitioningEvent = nil return true else if string.find(self.asyncState, "WaitingOnLeave") or string.find(self.asyncState, "WaitingOnEnter") then self.asyncState = NONE transition(self, ...) return true end end self.currentTransitioningEvent = nil return false end return transition end local function add_to_map(map, event) if type(event.from) == 'string' then map[event.from] = event.to else for _, from in ipairs(event.from) do map[from] = event.to end end end function machine.create(options) assert(options.events) local fsm = {} setmetatable(fsm, machine) fsm.options = options fsm.current = options.initial or 'none' fsm.asyncState = NONE fsm.events = {} for _, event in ipairs(options.events or {}) do local name = event.name fsm[name] = fsm[name] or create_transition(name) fsm.events[name] = fsm.events[name] or { map = {} } add_to_map(fsm.events[name].map, event) end for name, callback in pairs(options.callbacks or {}) do fsm[name] = callback end return fsm end function machine:is(state) return self.current == state end function machine:can(e) local event = self.events[e] local to = event and event.map[self.current] or event.map['*'] return to ~= nil, to end function machine:cannot(e) return not self:can(e) end function machine:todot(filename) local dotfile = io.open(filename,'w') dotfile:write('digraph {\n') local transition = function(event,from,to) dotfile:write(string.format('%s -> %s [label=%s];\n',from,to,event)) end for _, event in pairs(self.options.events) do if type(event.from) == 'table' then for _, from in ipairs(event.from) do transition(event.name,from,event.to) end else transition(event.name,event.from,event.to) end end dotfile:write('}\n') dotfile:close() end function machine:transition(event) if self.currentTransitioningEvent == event then return self[self.currentTransitioningEvent](self) end end function machine:cancelTransition(event) if self.currentTransitioningEvent == event then self.asyncState = NONE self.currentTransitioningEvent = nil end end machine.NONE = NONE machine.ASYNC = ASYNC return machine !--[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --Coconut implementation by Alberto Sonnino and Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local petition = { } local G1 = ECP.generator() local O = ECP.order() function petition.prove_sign_petition(pub, m) -- sign == vote local k = INT.random() -- vote encryption local enc_v = { left = G1 * k, right = pub * k + SALT * m } -- opposite of vote encryption local enc_v_neg = { left = enc_v.left:negative(), right = enc_v.right:negative() + SALT } -- commitment to the vote local r1 = INT.random() local r2 = r1 * (BIG.new(1) - m) local cv = G1 * m + SALT * r1 -- proof -- create the witnesess local wk = INT.random() local wm = INT.random() local wr1 = INT.random() local wr2 = INT.random() -- compute the witnessess commitments local Aw = G1*wk local Bw = pub*wk + SALT*wm local Cw = G1*wm + SALT*wr1 local Dw = cv*wm + SALT*wr2 -- create the challenge local c = ZKP_challenge({enc_v.left, enc_v.right, cv, Aw, Bw, Cw, Dw}) % O -- create responses local rk = wk - c * k local rm = wm - c * m local rr1 = wr1 - c * r1 local rr2 = wr2 - c * r2 local pi_vote = { c = c, rk = rk, rm = rm, rr1 = rr1, rr2 = rr2 } -- signature's Theta return { scores = { pos = enc_v, neg = enc_v_neg }, -- left/right tuples cv = cv, -- ecp pi_vote = pi_vote } -- pi end function petition.verify_sign_petition(pub, theta) -- recompute witnessess commitment local scores = theta.scores.pos -- only positive, not negative? local Aw = G1 * theta.pi_vote.rk + scores.left * theta.pi_vote.c local Bw = pub * theta.pi_vote.rk + SALT * theta.pi_vote.rm + scores.right * theta.pi_vote.c local Cw = G1 * theta.pi_vote.rm + SALT * theta.pi_vote.rr1 + theta.cv * theta.pi_vote.c local Dw = theta.cv * theta.pi_vote.rm + SALT * theta.pi_vote.rr2 + theta.cv * theta.pi_vote.c -- verify challenge ZEN.assert(theta.pi_vote.c == ZKP_challenge( {scores.left, scores.right, theta.cv, Aw, Bw, Cw, Dw }), "verify_sign_petition: challenge fails") return true end function petition.prove_tally_petition(sk, scores) local wx = INT.random() local Aw = { wx:modneg(O) * scores.pos.left, wx:modneg(O) * scores.neg.left } local c = ZKP_challenge(Aw) local rx = wx - c * sk local dec = { pos = scores.pos.left * sk:modneg(O), neg = scores.neg.left * sk:modneg(O) } -- return pi_tally return { dec = dec, rx = rx, c = c } end function petition.verify_tally_petition(scores, pi_tally) local rxneg = pi_tally.rx:modneg(O) local Aw = { rxneg*scores.pos.left + pi_tally.c * pi_tally.dec.pos, rxneg*scores.neg.left + pi_tally.c * pi_tally.dec.neg } ZEN.assert(pi_tally.c == ZKP_challenge(Aw), "verify_tally_petition: challenge fails") return true end function petition.count_signatures_petition(scores, pi_tally) local restab = { } for idx=1,1000 do -- if idx ~= 0 then -- not zero restab[(BIG.new(idx) * SALT):octet():hex()] = idx -- end end local res = { pos = scores.pos.right + pi_tally.dec.pos, neg = scores.neg.right + pi_tally.dec.neg } return { pos = restab[res.pos:octet():hex()], neg = restab[res.neg:octet():hex()] } end return petitiond--[[ --This file is part of zenroom -- --Copyright (C) 2020-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Tuesday, 20th July 2021 --]] local CRED = require_once'crypto_credential' local PET = require_once'crypto_petition' local function petition_scores_f(o) local obj = deepmap(CONF.input.encoding.fun, o) return ({ pos = { left = ZEN.get(obj.pos, 'left', ECP.new), right = ZEN.get(obj.pos, 'right', ECP.new) }, neg = { left = ZEN.get(obj.neg, 'left', ECP.new), right = ZEN.get(obj.neg, 'right', ECP.new) } }) end -- petition ZEN.add_schema( { petition_scores = petition_scores_f, petition = function(obj) local res = { uid = ZEN.get(obj, 'uid'), scores = petition_scores_f(obj.scores) } if obj.owner then res.owner = ZEN.get(obj, 'owner', ECP.new) end if obj.issuer_public_key then res.issuer_public_key = key_import_issuer_verifier_f(obj.issuer_public_key) end if obj.list then res.list = deepmap( function(o) return ZEN.get(o, '.', ECP.new) end, obj.list ) end if obj.signature then res.signature = { r = ZEN.get(obj.signature, 'r'), s = ZEN.get(obj.signature, 's') } end return res end, petition_signature = function(obj) return { -- from zencode_credential proof = import_credential_proof_f(obj.proof), uid_signature = ZEN.get(obj, 'uid_signature', ECP.new), uid_petition = ZEN.get(obj, 'uid_petition') } end, petition_tally = function(obj) local dec = {} dec.neg = ZEN.get(obj.dec, 'neg', ECP.new) dec.pos = ZEN.get(obj.dec, 'pos', ECP.new) return { uid = ZEN.get(obj, 'uid'), c = ZEN.get(obj, 'c', INT.new), dec = dec, rx = ZEN.get(obj, 'rx', INT.new) } end } ) When( "create the petition ''", function(uid) havekey'credential' -- ZEN.assert(ACK.keyring.credential,"Credential key not found") ACK.petition = { uid = OCTET.from_string(uid), -- TODO: take UID from HEAP not STACK owner = ECP.generator() * ACK.keyring.credential, scores = { pos = { left = ECP.infinity(), right = ECP.infinity() }, neg = { left = ECP.infinity(), right = ECP.infinity() } } } ZEN.CODEC.petition = { name = 'petition', encoding = check_codec('petition'), zentype = 'schema' } -- generate an ECDH signature of the (encoded) petition using the -- credential keys -- ecdh = ECDH.new() -- ecdh:private(ACK.cred_kp.private) -- ACK.petition_ecdh_sign = { ecdh:sign(MSG.pack(OUT.petition)) } -- OUT.petition_ecdh_sign = map(ACK.petition_ecdh_sign, hex) end ) When( 'verify the new petition to be empty', function() ZEN.assert( ECP.isinf(ACK.petition.scores.pos.left), 'Invalid new petition: positive left score is not zero' ) ZEN.assert( ECP.isinf(ACK.petition.scores.pos.right), 'Invalid new petition: positive right score is not zero' ) ZEN.assert( ECP.isinf(ACK.petition.scores.neg.left), 'Invalid new petition: negative left score is not zero' ) ZEN.assert( ECP.isinf(ACK.petition.scores.neg.right), 'Invalid new petition: negative right score is not zero' ) end ) When( "create the petition signature ''", function(uid) have'credentials' have'issuer public key' havekey'credential' local Theta local zeta local ack_uid = OCTET.from_string(uid) Theta, zeta = CRED.prove_cred_uid( ACK.issuer_public_key, ACK.credentials, ACK.keyring.credential, ack_uid ) ACK.petition_signature = { proof = Theta, uid_signature = zeta, -- ECP uid_petition = ack_uid } end ) IfWhen( 'verify the signature proof is correct', function() ZEN.assert( CRED.verify_cred_uid( ACK.issuer_public_key, ACK.petition_signature.proof, ACK.petition_signature.uid_signature, ACK.petition_signature.uid_petition ), 'Petition signature is invalid' ) end ) IfWhen( 'the petition signature is not a duplicate', function() if luatype(ACK.petition.list) == 'table' then ZEN.assert( (not array_contains( ACK.petition.list, ACK.petition_signature.uid_signature )), 'Duplicate petition signature detected' ) else ACK.petition.list = {} end table.insert(ACK.petition.list, ACK.petition_signature.uid_signature) end ) IfWhen( 'the petition signature is just one more', function() -- verify that the signature is +1 (no other value supported) ACK.petition_signature.one = PET.prove_sign_petition(ACK.petition.owner, BIG.new(1)) ZEN.assert( PET.verify_sign_petition( ACK.petition.owner, ACK.petition_signature.one ), 'ABC petition signature adds more than one signature' ) end ) When( 'add the signature to the petition', function() -- add the signature to the petition count local scores = ACK.petition.scores local psign = ACK.petition_signature.one scores.pos.left = scores.pos.left + psign.scores.pos.left scores.pos.right = scores.pos.right + psign.scores.pos.right scores.neg.left = scores.neg.left + psign.scores.neg.left scores.neg.right = scores.neg.right + psign.scores.neg.right -- TODO: ZEN:push({'petition' ,'scores'} ACK.petition.scores = scores end ) When( 'create a petition tally', function() havekey'credential' ZEN.assert(ACK.petition, 'Petition not found') ACK.petition_tally = PET.prove_tally_petition( ACK.keyring.credential, ACK.petition.scores ) ACK.petition_tally.uid = ACK.petition.uid end ) When( 'count the petition results', function() ZEN.assert(ACK.petition, 'Petition not found') ZEN.assert(ACK.petition_tally, 'Tally not found') ZEN.assert( ACK.petition_tally.uid == ACK.petition.uid, 'Tally does not correspond to petition' ) ACK.petition_results = PET.count_signatures_petition( ACK.petition.scores, ACK.petition_tally ).pos end ) /--[[ --This file is part of zenroom -- --Copyright (C) 2022 Dyne.org foundation --designed, written and maintained by Alberto Lerda and Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Matteo Cristino --on Friday, 19th April 2022 --]] local QP = require'qp' local function dilithium_public_key_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( QP.sigpubcheck(res), 'Dilithium public key length is not correct' ) return res end local function dilithium_signature_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( QP.signature_check(res), 'Dilithium signature length is not correcr' ) return res end local function kyber_public_key_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( QP.kempubcheck(res), 'Kyber public key length is not correct' ) return res end local function kyber_secret_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( QP.kemsscheck(res), 'Kyber secret lentgth is not correct' ) return res end local function kyber_ciphertext_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( QP.kemctcheck(res), 'Kyber ciphertext length is not correct' ) return res end local function kyber_import_kem(obj) local res = {} res.kyber_secret = kyber_secret_f(obj.kyber_secret) res.kyber_ciphertext = kyber_ciphertext_f(obj.kyber_ciphertext) return res end local function ntrup_public_key_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( QP.ntrup_pubcheck(res), 'NTRUP public key length is not correct' ) return res end local function ntrup_secret_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( QP.ntrup_sscheck(res), 'NTRUP secret lentgth is not correct' ) return res end local function ntrup_ciphertext_f(obj) local res = ZEN.get(obj, '.') ZEN.assert( QP.ntrup_ctcheck(res), 'NTRUP ciphertext length is not correct' ) return res end local function ntrup_import_kem(obj) local res = {} res.ntrup_secret = ntrup_secret_f(obj.ntrup_secret) res.ntrup_ciphertext = ntrup_ciphertext_f(obj.ntrup_ciphertext) return res end -- check various locations to find the public key -- algo can be either 'dilithium' or 'kyber' -- Given I have a 's' from 't' --> ACK.s[t] local function _pubkey_compat(_key, algo) local pubkey = ACK[_key] if not pubkey then local pubkey_arr = ACK[algo..'_public_key'] if luatype(pubkey_arr) == 'table' then pubkey = pubkey_arr[_key] else pubkey = pubkey_arr end ZEN.assert( pubkey, 'Public key not found for: ' .. _key ) end return pubkey end ZEN.add_schema( { dilithium_public_key = dilithium_public_key_f, dilithium_signature = dilithium_signature_f, kyber_public_key = kyber_public_key_f, kyber_secret = kyber_secret_f, kyber_ciphertext = kyber_ciphertext_f, kyber_kem = kyber_import_kem, ntrup_public_key = ntrup_public_key_f, ntrup_secret = ntrup_secret_f, ntrup_ciphertext = ntrup_ciphertext_f, ntrup_kem = ntrup_import_kem } ) --# DILITHIUM #-- -- generate the private key When('create the dilithium key',function() initkeyring'dilithium' ACK.keyring.dilithium = QP.sigkeygen().private end) -- generate the public key When('create the dilithium public key',function() empty'dilithium public key' local sk = havekey'dilithium' ACK.dilithium_public_key = QP.sigpubgen(sk) new_codec('dilithium public key', { zentype = 'element'}) end) When("create the dilithium public key with secret key ''",function(sec) local sk = have(sec) initkeyring'dilithium' ACK.keyring.dilithium = sk empty'dilithium public key' ACK.dilithium_public_key = QP.sigpubgen(sk) new_codec('dilithium public key', { zentype = 'element'}) end) -- generate the sign for a msg and verify When("create the dilithium signature of ''",function(doc) local sk = havekey'dilithium' local obj = have(doc) empty'dilithium signature' ACK.dilithium_signature = QP.sign(sk, ZEN.serialize(obj)) new_codec('dilithium signature', { zentype = 'element'}) end) IfWhen("verify the '' has a dilithium signature in '' by ''",function(msg, sig, by) local pk = _pubkey_compat(by, 'dilithium') local m = have(msg) local s = have(sig) ZEN.assert( QP.verify(pk, s, ZEN.serialize(m)), 'The signature by '..by..' is not authentic' ) end) --# KYBER #-- -- generate the private key When('create the kyber key',function() initkeyring'kyber' ACK.keyring.kyber = QP.kemkeygen().private end) -- generate the public key When('create the kyber public key',function() empty'kyber public key' local sk = havekey'kyber' ACK.kyber_public_key = QP.kempubgen(sk) new_codec('kyber public key', { zentype = 'element'}) end) When("create the kyber public key with secret key ''",function(sec) local sk = have(sec) initkeyring'kyber' ACK.keyring.kyber = sk empty'kyber public key' ACK.kyber_public_key = QP.kempubgen(sk) new_codec('kyber public key', { zentype = 'element'}) end) -- create a secret message and its ciphertext When("create the kyber kem for ''",function(pub) local pk = _pubkey_compat(pub, 'kyber') empty'kyber kem' ACK.kyber_kem = {} local enc = QP.enc(pk) ACK.kyber_kem.kyber_ciphertext = enc.cipher ACK.kyber_kem.kyber_secret = enc.secret new_codec('kyber kem', { zentype = 'schema'}) end) -- create the secret starting from a ciphertext When("create the kyber secret from ''",function(secret) local sk = havekey'kyber' local sec = have(secret) empty 'kyber secret' ACK.kyber_secret = QP.dec(sk, sec) new_codec('kyber secret', { zentype = 'element'}) end) --# NTRUP #-- -- generate the private key When('create the ntrup key',function() initkeyring'ntrup' ACK.keyring.ntrup = QP.ntrup_keygen().private end) -- generate the public key When('create the ntrup public key',function() empty'ntrup public key' local sk = havekey'ntrup' ACK.ntrup_public_key = QP.ntrup_pubgen(sk) new_codec('ntrup public key', { zentype = 'element'}) end) When("create the ntrup public key with secret key ''",function(sec) local sk = have(sec) initkeyring'ntrup' ACK.keyring.ntrup = sk empty'ntrup public key' ACK.ntrup_public_key = QP.ntrup_pubgen(sk) new_codec('ntrup public key', { zentype = 'element'}) end) -- create a secret message and its ciphertext When("create the ntrup kem for ''",function(pub) local pk = _pubkey_compat(pub, 'ntrup') empty'ntrup kem' ACK.ntrup_kem = {} local enc = QP.ntrup_enc(pk) ACK.ntrup_kem.ntrup_ciphertext = enc.cipher ACK.ntrup_kem.ntrup_secret = enc.secret new_codec('ntrup kem', { zentype = 'schema'}) end) -- create the secret starting from a ciphertext When("create the ntrup secret from ''",function(ciphertext) local sk = havekey'ntrup' local ct = have(ciphertext) empty'ntrup secret' ACK.ntrup_secret = QP.ntrup_dec(sk, ct) new_codec('ntrup secret', { zentype = 'element'}) end) J --[[ --This file is part of zenroom -- --Copyright (C) 2018-2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 13th November 2021 --]] --- Zencode data internals -- Used in scenario's schema declarations to cast to zenroom. type ZEN.get = function(obj, key, conversion, encoding) if type(key) ~= 'string' then error('ZEN.get key is not a string', 2) end if conversion and type(conversion) ~= 'function' then error('ZEN.get invalid conversion function', 2) end if encoding and type(encoding) ~= 'function' then error('ZEN.get invalid encoding function', 2) end local k if not obj then -- take from IN root -- does not support to pick in WHO (use of 'my') k = KIN[key] or IN[key] else if key == '.' then k = obj else k = obj[key] end end if not k then error('Key not found in object conversion: ' .. key, 2) end local res = nil local t = type(k) if iszen(t) and conversion then res = conversion(k) goto ok end if iszen(t) and not conversion then res = k goto ok end if t == 'string' then if encoding then res = encoding(k) else res = CONF.input.encoding.fun(k) end if conversion then res = conversion(res) end goto ok end if t == 'number' then res = k end if t == 'table' then res = deepmap(encoding or CONF.input.encoding.fun, k) if conversion then res = deepmap(conversion, res) end end ::ok:: assert( ZEN.OK and res, 'ZEN.get on invalid key: ' .. key .. ' (' .. t .. ')', 2) return res end -- return leftmost and rightmost if definition string indicates -- a lua table: dictionary, array or schema local function expect_table(definition) local toks = strtok(definition, '[^_]+') local res = { rightmost = toks[#toks] } if res.rightmost == 'array' or res.rightmost == 'dictionary' then res.leftwords = '' -- concat all left words in toks minus the last for i = 1, #toks - 2 do res.leftwords = res.leftwords .. toks[i] .. '_' end res.leftwords = uscore( res.leftwords .. toks[#toks - 1] ) -- no trailing underscore return res end -- schemas may or may be not tables end --- Given block (IN read-only memory) -- @section Given --- -- Guess how to convert the object, using what format or schema -- check the definition string (coming straight from zencode) -- considering the type of the object: -- ``` -- type def conv -- ------------------------------------------------------ -- schema schema_f(===, default_encoding) -- str format input_encoding(format) -- num input_encoding(number) -- table f dict deepmap(table, input_encoding(f)) -- table f array deepmap(table, input_encoding(f)) -- ``` -- returns a table with function pointers and string desc that -- will be used by @{operate_conversion} -- { fun = conversion function pointer -- conversion = conversion string description -- check = check function pointer -- raw = raw data pointer -- (name) = key name of data (set externally) -- (root) = root section name (set externally) -- luatype = type of raw data for lua -- zentype = type of data for zenroom (array, dict, element, schema) -- } function guess_conversion(obj, definition) local t local objtype = luatype(obj) local res if not definition then error("Cannot take undefined object, found a "..type(obj), 3) end -- a defined schema overrides any other conversion t = ZEN.schemas[definition] if t then -- complex schema is a table specfying in/out conversions as: {import=fun, export=fun} local c = fif(luatype(t)=='table', 'complex', CONF.output.encoding.name) -- default is always the configured output encoding return ({ fun = t, zentype = 'schema', luatype = objtype, raw = obj, encoding = c }) end if objtype == 'string' then if expect_table(definition) then error("Cannot take object: expected '"..definition.."' but found '"..objtype.."' (not a table)",3) end res = input_encoding(definition) res.luatype = 'string' res.zentype = 'element' res.raw = obj return (res) end -- definition: value_encoding .. data_type -- value_encoding: base64, hex, etc. -- data_type: array, dictionary, structure if objtype == 'table' then local def = expect_table(definition) if not def then -- check if the last word is among zentype collections error("Cannot take object: expected '"..definition .."' but found '"..objtype.."' (not a dictionary or array)",3) end -- schema type in array or dict t = ZEN.schemas[ def.leftwords ] if t then return ({ fun = t, zentype = 'schema', schema = def.leftwords, luatype = objtype, raw = obj, encoding = def.rightmost }) end -- normal type in input encoding: string, base64 etc. res = input_encoding(def.leftwords) if res then res.luatype = 'table' res.zentype = def.rightmost -- zentypes couples with table res.raw = obj return (res) end error("Cannot take object: invalid "..def.rightmost.." with encoding "..def.leftwords, 3) return nil end if objtype == 'number' or tonumber(obj) then if expect_table(definition) then error("Cannot take object: expected '"..definition.."' but found '"..objtype.."' (not a table)",3) elseif definition ~= 'number' then error("Cannot take object: expected '"..definition.."' but found '"..objtype.."'",3) end res = input_encoding(objtype) res.luatype = 'number' res.zentype = 'element' if obj > 2147483647 then error('Overflow of number object over 32bit signed size', 3) -- TODO: maybe support unsigned native here end res.raw = obj -- any type of additional conversion from a native number -- detected at input can happen here, for instance using a new -- native unsigned integer return (res) end error('Cannot take object: invalid conversion for type '..objtype..': '..definition, 3) return nil end -- takes a data object and the guessed structure, operates the -- conversion and returns the resulting raw data to be used inside the -- WHEN block in HEAP. function operate_conversion(guessed) if not guessed.fun then error('No conversion operation guessed', 2) return nil end -- carry guessed detection in CODEC ZEN.CODEC[guessed.name] = { name = guessed.name, encoding = guessed.encoding, zentype = guessed.zentype, luatype = guessed.luatype, root = guessed.root } -- TODO: make xxx print to stderr! -- xxx('Operating conversion on: '..guessed.name) if guessed.zentype == 'schema' then -- error('Invalid schema conversion for encoding: '..guessed.encoding, 2) local res = {} if guessed.encoding == 'array' then for _,v in pairs(guessed.raw) do table.insert(res, guessed.fun(v)) end return(res) elseif guessed.encoding == 'dictionary' then for k, v in pairs(guessed.raw) do res[k] = guessed.fun(v[guessed.schema]) end return (res) elseif guessed.encoding == 'complex' then return guessed.fun.import(guessed.raw) else return guessed.fun(guessed.raw) end elseif guessed.luatype == 'table' then -- TODO: better error checking on deepmap? if luatype(guessed.check) == 'function' then deepmap(guessed.check, guessed.raw) end return deepmap(guessed.fun, guessed.raw) else -- object if guessed.check then guessed.check(guessed.raw) end return guessed.fun(guessed.raw) end end -- factory function to generate a function and return its pointer the -- function is generated using another pointer to function which is -- the encoder, plus it applies common safety checks for data types -- that must be excluded for encoding, as for instance numbers and -- booleans. -- arguments: encoder's name, conversion and check functions local function f_factory_encoder(encoder_n, encoder_f, encoder_c) return { fun = function(data) local dt = luatype(data) if dt == 'number' then return data elseif dt == 'boolean' then return data end return encoder_f(data) end, encoding = encoder_n, check = encoder_c } end -- gets a string and returns the associated function, string and prefix -- comes before schema check function input_encoding(what) if not luatype(what) == 'string' then error("Call to input_encoding argument is not a string: "..type(what),2) end if what == 'u64' or what == 'url64' then return f_factory_encoder('url64', O.from_url64, O.is_url64) elseif what == 'b64' or what =='base64' then return f_factory_encoder('base64', O.from_base64, O.is_base64) elseif what == 'b58' or what =='base58' then return f_factory_encoder('base58', O.from_base58, O.is_base58) elseif what == 'hex' then return f_factory_encoder('hex', O.from_hex, O.is_hex) elseif what == 'bin' or what == 'binary' then return f_factory_encoder('binary', O.from_bin, O.is_bin) elseif what == 'str' or what == 'string' then -- string has no check function return f_factory_encoder('string', O.from_string, nil) elseif what =='mnemonic' then -- mnemonic has no check function (TODO:) return f_factory_encoder('mnemonic', O.from_mnemonic, nil) elseif what == 'num' or what == 'number' then return f_factory_encoder('number', function(data) return tonumber(data) end, function(data) if not tonumber(data) then error("Invalid encoding, not a number: " ..type(data), 3) end end) end error("Input encoding not found: " .. what, 2) return nil end -- factory function returns a small outcast function that applies -- return guessed.fun(guessed.raw)safety checks on values like -- exceptions for numbers and booleans local function f_factory_outcast(fun) return function(data) local dt = luatype(data) if dt == 'table' then error("invalid table conversion",2) end -- passthrough native number data if dt == 'number' or dt == 'boolean' then return data elseif iszen(dt) and dt ~= 'zenroom.octet' then -- leverage first class citizen method on zenroom data return fun(data:octet()) end return fun(data) end end -- takes a string returns the function, good for use in deepmap(fun,table) function guess_outcast(cast) if not cast then error('guess_outcast called with nil argument', 2) end if luatype(cast) ~= 'string' then error('guess_outcast called with wrong argument: '..type(cast), 3) end if cast == 'string' then return f_factory_outcast(O.to_string) elseif cast == 'hex' then return f_factory_outcast(O.to_hex) elseif cast == 'base64' then return f_factory_outcast(O.to_base64) elseif cast == 'url64' then return f_factory_outcast(O.to_url64) elseif cast == 'base58' then return f_factory_outcast(O.to_base58) elseif cast == 'binary' or cast == 'bin' then return f_factory_outcast(O.to_bin) elseif cast == 'mnemonic' then return f_factory_outcast(O.to_mnemonic) elseif cast == 'number' then return f_factory_outcast(tonumber) elseif cast == 'boolean' then return function(data) return data end end -- try schemas local fun = ZEN.schemas[uscore(cast, ' ', '_')] if luatype(fun) == 'table' then -- complex schema encoding assert(luatype(fun.export) == 'function', "Guess outcast cannot find schema export") return fun.export else return CONF.output.encoding.fun end error('Invalid output conversion: ' .. cast, 2) return nil end function get_format(what) if what == 'json' or what == 'JSON' then return { fun = JSON.auto, name = 'json' } elseif what == 'cbor' or what == 'CBOR' then return { fun = CBOR.auto, name = 'cbor' } end error("Conversion format not supported: "..what, 2) return nil end -- CODEC format: -- { name: string, -- encoding: encoder name string or 'complex' handled by schema -- zentype: zencode type: element, array, dictionary or schema -- luatype: lua type (string, number, table or userdata) -- schema: schema name used to import (may differ from name) -- } -- return: name of codec encoding function check_codec(name) if not ZEN.CODEC then return CONF.output.encoding.name end if not ZEN.CODEC[name] then xxx('Object has no CODEC registration: ' .. name) return CONF.output.encoding.name end local codec = ZEN.CODEC[name] if codec.zentype == 'schema' and codec.encoding == 'complex' then local sch = codec.schema or codec.name local s = ZEN.schemas[sch] if not s then error("Schema not found: "..name, 2) end if luatype(s) == 'function' then error("Simple schema found instead of complex: "..name, 2) end assert(s.export, "Complex export function for schema not found: "..name) assert(luatype(s.export) == 'function', "Complex export for schema is not a function: "..name) return name -- name of schema itself as it contains export else return codec.encoding or CONF.output.encoding.name end return CONF.output.encoding.name end function new_codec(cname, parameters, clone) if not cname then error("Missing name in new codec", 2) end local name = fif(luatype(cname) == 'string', uscore(cname), cname) -- may be a numerical index if not ACK[name] then error("Cannot create codec, object not found: "..name, 2) end if ZEN.CODEC[name] then error("Cannot overwrite ZEN.CODEC."..name, 2) end local res if clone and not ZEN.CODEC[clone] then error("Clone not found in ZEN.CODEC."..clone, 2) end if ZEN.CODEC[clone] then res = deepcopy(ZEN.CODEC[clone]) res.name = name else res = { name = name } end -- overwrite with paramenters in argument if parameters then for k,v in pairs(parameters) do res[k] = v end end -- detect zentype and luatype if not res.luatype then res.luatype = luatype(ACK[name]) end if not res.zentype then if res.luatype == 'table' then if isdictionary(ACK[name]) then res.zentype = 'dictionary' elseif isarray(ACK[name]) then res.zentype = 'array' else error("Unknown zentype for lua table: "..name, 2) end else res.zentype = 'element' end end ZEN.CODEC[name] = res return(res) -- redundant, should not use return value for efficiency end -- Crawls a whole table structure and collects all strings and octets -- contained in its keys and values. Converts numbers to -- strings. Structure returned is: -- { octets = zenroom.octet -- strings = string } -- calling function may want to convert all to octet or string -- -- apply a function on all keys and values of a tree structure -- uses sorted listing for deterministic order local function sort_apply(fun,t,...) if luatype(fun) ~= 'function' then error("Internal error: apply 1st argument is not a function", 3) return nil end -- if luatype(t) == 'number' then -- return t end if luatype(t) ~= 'table' then error("Internal error: apply 2nd argument is not a table", 3) return nil end for k,v in sort_pairs(t) do -- OPTIMIZATION: was sort_pairs if luatype(v) == 'table' then sort_apply(fun,v,...) -- recursion else fun(v,k,...) end end end function serialize(tab) assert(luatype(tab) == 'table', 'Cannot serialize: not a table', 2) local octets = OCTET.zero(1) local strings = { 'K' } sort_apply( function(v, k) table.insert(strings, tostring(k)) if iszen(type(v)) then -- TODO: optimize octet concatenation in C -- to avoid reallocation of new octets in this loop -- should count total length allocate one and insert octets = octets.. v:octet() else -- number table.insert(strings, tostring(v)) end end, tab ) return { octets = octets, -- string concatenation is optimized strings = table.concat(strings) } end -- eliminate all empty string objects "" and all empty dictionaries -- (containing only empy objects), uses recursion into tables function prune(tab) assert(luatype(tab) == 'table', 'Cannot prune: not a table', 2) local pruned_values = deepmap(function(v) if #v == 0 then return nil else return v end end, tab) local function prune_in(ttab) local res = { } local next = next local luatype = luatype for k,v in pairs(ttab) do if luatype(v) == 'table' then if next(v) == nil then res[k] = nil -- {} to nil else res[k] = prune_in(v) -- recursion end else res[k] = v end end return setmetatable(res, getmetatable(ttab)) end pruned_tables = prune_in(pruned_values) return pruned_tables end --- -- Compare equality of two data objects (TODO: octet, ECP, etc.) -- @function ZEN:eq(first, second) --- -- Check that the first object is greater than the second (TODO) -- @function ZEN:gt(first, second) --- -- Check that the first object is lesser than the second (TODO) -- @function ZEN:lt(first, second) --- Then block (OUT write-only memory) -- @section Then --- -- Move a generic data structure from ACK to OUT memory space, ready -- for its final JSON encoding and print out. -- @function ZEN:out(name) --- -- Move 'my own' data structure from ACK to OUT.whoami memory space, -- ready for its final JSON encoding and print out. -- @function ZEN:outmy(name) | --[[ --This file is part of zenroom -- --Copyright (C) 2021 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt -- --Last modified by Denis Roio --on Saturday, 13th November 2021 --]] -- limit output of string if too long function limit(anystr) local t = luatype(anystr) ZEN.assert(t=='string',"Argument to limit on-screen not a string") if #anystr > 32 then return(string.sub(anystr,1,32).."..") end return(anystr) end -- debug functions function debug_traceback() for k,v in pairs(ZEN.traceback) do warn(v) end end Given("backtrace", function() debug_traceback() end) When("backtrace", function() debug_traceback() end) Then("backtrace", function() debug_traceback() end) Given("trace", function() debug_traceback() end) When("trace", function() debug_traceback() end) Then("trace", function() debug_traceback() end) function debug_heap_dump() local HEAP = ZEN.heap() I.warn({a_GIVEN_in = HEAP.IN, b_GIVEN_in = HEAP.KIN, c_WHEN_ack = HEAP.ACK, d_THEN_out = HEAP.OUT}) end function debug_heap_schema() I.schema({SCHEMA = ZEN.heap()}) -- print only keys without values end -- local function debug_obj_dump() -- local function debug_obj_schema() Given("debug", function() ZEN.debug() end) When("debug", function() ZEN.debug() end) Then("debug", function() ZEN.debug() end) Given("schema", function() debug_heap_schema() end) When("schema", function() debug_heap_schema() end) Then("schema", function() debug_heap_schema() end) function debug_codec() I.warn({CODEC = ZEN.CODEC}) end Given("codec", function() debug_codec() end) When("codec", function() debug_codec() end) Then("codec", function() debug_codec() end) Given("config", function() I.warn(_G["CONF"]) end) When("config", function() I.warn(_G["CONF"]) end) Then("config", function() I.warn(_G["CONF"]) end):---

Debug inspection facility

-- -- The INSPECT class provides a number of functions to ease -- development and debugging. It mainly consists of an advanced -- @{print} function that can represent complex data structures (Lua -- tables) and tag their encoding formats and size. Another @{spy} -- function prints the same as pass-through. -- -- @module INSPECT -- @version inspect.lua 3.1.0 -- @author Kikito github.com/kikito/inspect.lua -- @license MIT local inspect ={ _VERSION = 'inspect.lua 3.1.0', _URL = 'http://github.com/kikito/inspect.lua', _DESCRIPTION = 'human-readable representations of tables' -- _LICENSE = [[ -- MIT LICENSE -- Copyright (c) 2013 Enrique García Cota -- Copyright (c) 2018-2021 Dyne.org foundation -- 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. -- ]] } local tostring = tostring inspect.KEY = setmetatable({}, {__tostring = function() return 'inspect.KEY' end}) inspect.METATABLE = setmetatable({}, {__tostring = function() return 'inspect.METATABLE' end}) --- -- Convert a data object to the desired format (argument name provided -- as string), or use CONF.encoding when called without argument -- -- @function export_obj(object, format) -- @param object data element to be converted -- @param format pointer to a converter function -- @return object converted to format local function export_arr(object, format) ZEN.assert( iszen(type(object)), 'export_arr called on a ' .. type(object) ) local conv_f = nil local ft = type(format) if format and ft == 'function' then conv_f = format goto ok end if format and ft == 'string' then conv_f = guess_outcast(format) goto ok end if not CONF.output.encoding then error('CONF.output.encoding is not configured', 2) end conv_f = CONF.debug.encoding.fun -- fallback to configured conversion function ::ok:: ZEN.assert( type(conv_f) == 'function', 'export_arr conversion function not configured' ) return conv_f(object) -- TODO: protected call? deepmap? end local function export_obj(object, format) -- CONF { encoding = , -- encoding_prefix = "u64" } assert(object, 'export_obj object not found') if luatype(object) == 'table' then local tres = {} for k, v in pairs(object) do -- only flat tables support recursion table.insert(tres, export_arr(v, format)) end return tres end return export_arr(object, format) end -- Apostrophizes the string if it has quotes, but not aphostrophes -- Otherwise, it returns a regular quoted string local function smartQuote(str) if str:match('"') and not str:match("'") then return "'" .. str .. "'" end return '"' .. str:gsub('"', '\\"') .. '"' end -- \a => '\\a', \0 => '\\0', 31 => '\31' local shortControlCharEscapes = { ["\a"] = "\\a", ["\b"] = "\\b", ["\f"] = "\\f", ["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t", ["\v"] = "\\v" } local longControlCharEscapes = {} -- \a => nil, \0 => \000, 31 => \031 for i=0, 31 do local ch = string.char(i) if not shortControlCharEscapes[ch] then shortControlCharEscapes[ch] = "\\"..i longControlCharEscapes[ch] = string.format("\\%03d", i) end end local function escape(str) return (str:gsub("\\", "\\\\") :gsub("(%c)%f[0-9]", longControlCharEscapes) :gsub("%c", shortControlCharEscapes)) end local function isIdentifier(str) return type(str) == 'string' and str:match( "^[_%a][_%a%d]*$" ) end local function isSequenceKey(k, sequenceLength) return type(k) == 'number' and 1 <= k and k <= sequenceLength and math.floor(k) == k end local defaultTypeOrders = { ['number'] = 1, ['boolean'] = 2, ['string'] = 3, ['table'] = 4, ['function'] = 5, ['userdata'] = 6, ['thread'] = 7 } local function sortKeys(a, b) local ta, tb = type(a), type(b) -- strings and numbers are sorted numerically/alphabetically if ta == tb and (ta == 'string' or ta == 'number') then return a < b end local dta, dtb = defaultTypeOrders[ta], defaultTypeOrders[tb] -- Two default types are compared according to the defaultTypeOrders table if dta and dtb then return defaultTypeOrders[ta] < defaultTypeOrders[tb] elseif dta then return true -- default types before custom ones elseif dtb then return false -- custom types after default ones end -- custom types are sorted out alphabetically return ta < tb end -- For implementation reasons, the behavior of rawlen & # is "undefined" when -- tables aren't pure sequences. So we implement our own # operator. local function getSequenceLength(t) local len = 1 local v = rawget(t,len) while v ~= nil do len = len + 1 v = rawget(t,len) end return len - 1 end local function getNonSequentialKeys(t) local keys = {} local sequenceLength = getSequenceLength(t) for k,_ in pairs(t) do if not isSequenceKey(k, sequenceLength) then table.insert(keys, k) end end table.sort(keys, sortKeys) return keys, sequenceLength end local function getToStringResultSafely(t, mt) local __tostring = type(mt) == 'table' and rawget(mt, '__tostring') local str, ok if type(__tostring) == 'function' then ok, str = pcall(__tostring, t) str = ok and str or 'error: ' .. tostring(str) end if type(str) == 'string' and #str > 0 then return str end end local function countTableAppearances(t, tableAppearances) tableAppearances = tableAppearances or {} if type(t) == 'table' then if not tableAppearances[t] then tableAppearances[t] = 1 for k,v in pairs(t) do countTableAppearances(k, tableAppearances) countTableAppearances(v, tableAppearances) end countTableAppearances(getmetatable(t), tableAppearances) else tableAppearances[t] = tableAppearances[t] + 1 end end return tableAppearances end local copySequence = function(s) local copy, len = {}, #s for i=1, len do copy[i] = s[i] end return copy, len end local function makePath(path, ...) local keys = {...} local newPath, len = copySequence(path) for i=1, #keys do newPath[len + i] = keys[i] end return newPath end local function processRecursive(process, item, path, visited) if item == nil then return nil end if visited[item] then return visited[item] end local processed = process(item, path) if type(processed) == 'table' then local processedCopy = {} visited[item] = processedCopy local processedKey for k,v in pairs(processed) do processedKey = processRecursive(process, k, makePath(path, k, inspect.KEY), visited) if processedKey ~= nil then processedCopy[processedKey] = processRecursive(process, v, makePath(path, processedKey), visited) end end local mt = processRecursive(process, getmetatable(processed), makePath(path, inspect.METATABLE), visited) if type(mt) ~= 'table' then mt = nil end -- ignore not nil/table __metatable field setmetatable(processedCopy, mt) processed = processedCopy end return processed end ------------------------------------------------------------------- local Inspector = {} local Inspector_mt = {__index = Inspector} function Inspector:puts(...) local args = {...} local buffer = self.buffer local len = #buffer for i=1, #args do len = len + 1 buffer[len] = args[i] end end function Inspector:down(f) self.level = self.level + 1 f() self.level = self.level - 1 end function Inspector:tabify() self:puts(self.newline, string.rep(self.indent, self.level)) end function Inspector:alreadyVisited(v) return self.ids[v] ~= nil end function Inspector:getId(v) local id = self.ids[v] if not id then local tv = type(v) id = (self.maxIds[tv] or 0) + 1 self.maxIds[tv] = id self.ids[v] = id end return tostring(id) end function Inspector:putKey(k) if isIdentifier(k) then return self:puts(k) end self:puts("[") self:putValue(k) self:puts("]") end function Inspector:putTable(t, exp) if t == inspect.KEY or t == inspect.METATABLE then self:puts(tostring(t)) -- self:puts("["..#t.."]") elseif self:alreadyVisited(t) then self:puts('') -- self:puts("["..#t.."]") elseif self.level >= self.depth then self:puts('{...}') else if self.tableAppearances[t] > 1 then self:puts('<', self:getId(t), '>') end local nonSequentialKeys, sequenceLength = getNonSequentialKeys(t) local mt = getmetatable(t) local toStringResult = getToStringResultSafely(t, mt) self:puts('{') self:down(function() if toStringResult then self:puts(' -- ', escape(toStringResult)) if sequenceLength >= 1 then self:tabify() end end local count = 0 for i=1, sequenceLength do if count > 0 then self:puts(',') end self:puts(' ') self:putValue(t[i], exp) count = count + 1 end for _,k in ipairs(nonSequentialKeys) do if count > 0 then self:puts(',') end self:tabify() self:putKey(k) self:puts(' = ') self:putValue(t[k], exp) count = count + 1 end if type(mt) == 'table' then if count > 0 then self:puts(',') end self:tabify() self:puts(' = ') self:putValue(mt, exp) end end) if #nonSequentialKeys > 0 or type(mt) == 'table' then -- result is multi-lined. Justify closing } self:tabify() elseif sequenceLength > 0 then -- array tables have one extra space before closing } self:puts(' ') end self:puts('}') end end function Inspector:putValue(v, exp) local tv = type(v) local exporter = exp or export_obj if tv == 'string' then self:puts(smartQuote(escape(v))) elseif tv == 'number' or tv == 'boolean' or tv == 'nil' or tv == 'cdata' or tv == 'ctype' then self:puts(tostring(v)) elseif tv == 'table' then if #v > 0 then self:puts("["..#v.."] ") end self:putTable(v, exporter) elseif iszen(tv) then if tv == "zenroom.octet" then if #v == 0 then self:puts("octet[0] (null)") else self:puts("octet[" .. #v .. "] " .. exporter(v)) end elseif tv == "zenroom.big" then local i = v:octet() self:puts("int[" .. #i.. "] " .. exporter(i)) elseif tv == "zenroom.ecp" then local i = v:octet() if v == "Infinity" or v == ECP.infinity() then self:puts("ecp[...] (Infinity)") else self:puts("ecp[" .. #i.. "] " .. exporter(i)) end elseif tv == "zenroom.ecp2" then local i = v:octet() if v == "Infinity" or v == ECP2.infinity() then self:puts("ecp[...] (Infinity)") else self:puts("ecp2[" ..#i.. "] ".. exporter(i)) end elseif tv == "zenroom.fp12" then local i = v:octet() self:puts("fp12[" ..#i.. "] ".. exporter(i)) elseif tv == "zenroom.ecdh" then local pk = v:public() local sk = v:private() if not pk and not sk then self:puts("ecdh keyring is empty\n") else if pk then self:puts("ecdh.public["..#pk.."] ".. exporter(pk).."\n") end if sk then self:puts("ecdh.private["..#sk.."] ".. exporter(sk).."\n") end end else self:puts(exporter(v:octet())) end else self:puts('<',tv,' ',self:getId(v),'>') end end ------------------------------------------------------------------- function inspect.inspect(root, options) options = options or {} local depth = options.depth or math.huge local newline = options.newline or '\n' local indent = options.indent or ' ' local process = options.process local schema = options.schema or false if process then root = processRecursive(process, root, {}, {}) end local inspector = setmetatable({ depth = depth, level = 0, buffer = {}, ids = {}, maxIds = {}, newline = newline, indent = indent, tableAppearances = countTableAppearances(root) }, Inspector_mt) -- option schema only (don't print contents) if schema then local _f = function(_) return("") end inspector:putValue(root, _f) else inspector:putValue(root) end return table.concat(inspector.buffer) end -- apply conversion wrapper to all values of a table function inspect.process(item, format) return processRecursive(function(item) if iszen(type(item)) then return export_obj(item, format) else return item end end, item, {}, {}) end --- Print all contents of a table in a tree representation, works with -- complex data structures and prints to STDOUT. -- -- @function INSPECT.print(object) -- @param object complex table data structure function inspect.print(root, options) print(inspect.inspect(root, options)) return root end --- Print the prototype (no contents only schema) of a table in a tree --- representation, works with complex data structures and prints to --- STDOUT. -- -- @function INSPECT.schema(object) -- @param object complex table data structure function inspect.schema(root, options) warn(inspect.inspect(root, { schema = true })) return root end --- Print all contents of a table to STDERR. Works same way as @{print}. -- -- @function INSPECT.warn(object) -- @param object complex table data structure function inspect.warn(root, options) if luatype(options) == 'string' then warn('Spy on: '..options) warn(inspect.inspect(root, {})) else warn(inspect.inspect(root, options)) end return root end --- Print all contents of a table to STDERR and return same object as --- passthrough. Works same way as @{print}. -- -- @function INSPECT.spy(object) -- @param object complex table data structure -- @return object itself (passthrough for nesting) inspect.spy = inspect.warn setmetatable(inspect, { __call = function(_, ...) return inspect.print(...) end }) return inspect --[[ --This file is part of zenroom -- --Copyright (C) 2022 Dyne.org foundation --designed, written and maintained by Denis Roio -- --This program is free software: you can redistribute it and/or modify --it under the terms of the GNU Affero General Public License v3.0 -- --This program is distributed in the hope that it will be useful, --but WITHOUT ANY WARRANTY; without even the implied warranty of --MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --GNU Affero General Public License for more details. -- --Along with this program you should have received a copy of the --GNU Affero General Public License v3.0 --If not, see http://www.gnu.org/licenses/agpl.txt --]] local mpack = MPACK -- require_once'zenroom_msgpack' local zpack = { } zpack.encode = function(src) local tmp = mpack.encode(src) return compress( O.from_rawlen(tmp, #tmp) ) end zpack.decode = function(src) return mpack.decode( O.to_string( decompress(src) ) ) end return zpack  % int?`g ss, xF  b, F :f  O, FJ{ 9SJ  , F J{$ R , F.V  , Fc , FR AR _, Fc , FO J, F:&N , FZIZ , F  , F3   , F    4#, FbHQ8#b =), F7$A) H,, F:L, ~-, F(-( P/, FjQYT/j 1, F(!1 4, F4 6, F0K)60 :, FrR2a:r G>, F8K>  C, F C "D, F8'&D8 yE, Fz$2i}Ez I, F!I L, FL IM, F@/MM@ M, F +qM nQ, F, rQ 8R, F  r t, F  t t, F.t. Iv, o 5Mv_ 4:!;9 I?&II!I/$ >  :!; 9!I8 4:!; 9 I? !I %  $ >   : ; 9  : ; 9 I !I/ ;3 zencode_whenzencode_dictionaryzencode_random_lenzencode_lenzenroom_ecp_lenzenroom_ecdh_lenzenroom_common_lenmsgpackinitzencode_dp3tstats_lentimetable_lenzencode_dictionary_lenstatemachine_lencrypto_elgamalzencode_petition_lenzenroom_octetsigned charzenroom_msgpacksemverzencode_debugzencode_qplong intzencode_ethereum_lenstatszencodezenroom_commonzencode_data_lenzencode_thenhdwalletzencode_datazencode_array_lenunsigned intzencode_hash_lenzencode_verifycrypto_schnorr_signature_lenlong unsigned intzencode_arrayzenroom_json_lennamezenroom_ecdhzencode_dp3t_lensizeshort unsigned intzenroom_cborGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionzencode_credentialzencode_w3czenroom_hash_lenzencode_reflow_lenzencode_when_lenzencode_qp_lencrypto_ethereumzencode_httpzencode_ethereumzenroom_big_lenmsgpack_lencrypto_bitcoin_lenzencode_reflowtimetablezen_extensionszenroom_benchzenroom_hashzencode_randomzenroom_jsoncrypto_bitcoinzencode_credential_lenzencode_keyringzencode_bitcoin_lencrypto_ethereum_lenfloatinspectcrypto_credential_lenunsigned charcrypto_credentialcrypto_elgamal_lenzenroom_ecpshort intzencode_w3c_lencborzencode_schnorr_lenzen_extension_tzenroom_octet_lenjson_lenzencode_then_lenzenroom_zpack_lenzencode_keyring_lenzenroom_ecp2_lenzencode_hashzenroom_zpackcharhdwallet_lenzencode_debug_lenstatemachinezencode_bitcoinzencode_secsharecrypto_lagrange_interpolation_lenzencode_verify_lenjsoncrypto_lagrange_interpolationcrypto_petitionzencode_secshare_lenzencode_given_lencrypto_petition_lencodezencode_http_lenzencode_petitioncrypto_schnorr_signatureinit_leninspect_lenzencode_givenzencode_ecdh_lenzenroom_msgpack_lenzenroom_cbor_lensemver_lenzencode_schnorrzencode_ecdhzenroom_bigzenroom_bench_lencbor_lenzenroom_ecp2/home/alby/dev/Zenroom/meson../src/lualibs_detected.c/home/alby/dev/Zenroom/meson../src../src/lualibs_detected.clua_functions.hlualibs_detected.cGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNU  #z5zC?O@:Wp6i6| wP`J /d\`! E#EO+=;&Km4@4 Ho,o8$?paPa;]KfKk`66R- A (  oL)H`S2L```8hSS CC'T8`%2E`X!gxxL`0@ +- Т /q q)[<[ KT\TiQy Qt==~ q +?+Ob/qn|n c cg aaIDE/0<@%<9@IY lualibs_detected.czen_extensionszenroom_zpack_lenzenroom_zpackinspect_leninspectzencode_debug_lenzencode_debugzencode_data_lenzencode_datazencode_qp_lenzencode_qpzencode_petition_lenzencode_petitioncrypto_petition_lencrypto_petitionstatemachine_lenstatemachinezencode_lenzencodezencode_given_lenzencode_givencrypto_lagrange_interpolation_lencrypto_lagrange_interpolationzenroom_octet_lenzenroom_octetzencode_secshare_lenzencode_secsharezenroom_common_lenzenroom_commoncrypto_bitcoin_lencrypto_bitcoinzencode_dictionary_lenzencode_dictionaryzencode_hash_lenzencode_hashinit_leninitzencode_credential_lenzencode_credentialcrypto_schnorr_signature_lencrypto_schnorr_signaturetimetable_lentimetablezencode_schnorr_lenzencode_schnorrzenroom_bench_lenzenroom_benchzencode_when_lenzencode_whenzencode_verify_lenzencode_verifyzenroom_json_lenzenroom_jsonzenroom_cbor_lenzenroom_cborzencode_array_lenzencode_arrayzenroom_ecdh_lenzenroom_ecdhstats_lenstatszencode_random_lenzencode_randomhdwallet_lenhdwalletcrypto_elgamal_lencrypto_elgamalzenroom_hash_lenzenroom_hashzenroom_ecp_lenzenroom_ecpzencode_http_lenzencode_httpcrypto_credential_lencrypto_credentialzencode_then_lenzencode_thenzenroom_ecp2_lenzenroom_ecp2zencode_bitcoin_lenzencode_bitcoincrypto_ethereum_lencrypto_ethereumzencode_reflow_lenzencode_reflowsemver_lensemverzencode_dp3t_lenzencode_dp3tzenroom_big_lenzenroom_bigzencode_ethereum_lenzencode_ethereumzencode_keyring_lenzencode_keyringzencode_ecdh_lenzencode_ecdhzenroom_msgpack_lenzenroom_msgpackzencode_w3c_lenzencode_w3c    ( 08 @H$PX`1hpx<M]jr (!0"8@#H$PX%`&hp'x()*+,-./01243495 6(C0788@HH9P:XX`;h<pfx=>s?@ABCDEFGHIJ K(L08M@NHPOXP`hQpRxSTUV WXYZ)[\6]^F_` V(a0b8e@cHdPlXe`fhypgxhijklmnopqr     ! ( 4 ;B N _U \ c o y I 7 Z  I     $ 1 P "]f s   v 0  #, 9X en {   _ 3 !+4 A` cmv )   Y " !& g3$< `I#h Uu&~ %  ( ' * ). {;,D  Q+p 6}. d- s0 / 2  16 ^C4L kY3x 6 5 08 7 p : 59> K<T a; > y= @ K? HB &'AF rSD\ TiC F E <H OG Y J" / IN 9[ Ld  q K  N  M  P  O ,! R* U7 QV  c Tl ?y S  V  U  X  W ) Z2 t? Y^ k \t  [  ^  ]  `  _$ 1 b: fG af s d| e c  f I e  h  g, 9 jB DO in {{ l  k  n / m   p @o4 IArJ  Wqp } " 7& T0 [5 u: .symtab.strtab.shstrtab.text.data.bss.rodata.str1.1.rela.data.rel.rodata.rela.debug_info.debug_abbrev.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property@!@'@,2@@  ;@hJ@~ WR@Pcv9 q@( Y?@@x 00Y0& 8  e/159 0 0 0 644 26424 ` ELF>x_@@HH5dH%(HD$1HD$dH+%(u1HHdH%(HD$1HT$D$t),HHD$dH+%(u1HDff.AUE1IATUHHdH%(HD$1Aăt-thtCHD$dH+%(upHD]A\A]fDLHH1H5LHH1H5LHH1H5ff.UHSHHdH%(HD$1HHCHsHH tn1ҾHH5HH1H H1HH5HH81HT$dH+%(uWH[]E11ɺ1HH1HH5벐HH51AUIATUSHdH%(HD$1HHLIHHH+HuafHkHHtKLHuHSHLHT$dH+%(zH[]A\A]@H-H}Hu6fDH}HHt#LuHLf.H5LH5L5H5L7H5LH5L%H5L*H5L/H5L4H5L9HLLHLL1LH5Lp1fHH51HLLHLLHLLoHLLSHLL7HLLHLL1LH5L1rUHSH5HdH%(HD$11҅t?H5HHHD$dH+%(u$H[]H5Hf.ATH5IUSHdH%(HD$1H-H}HtMH@H}HHt3HuHD$dH+%(uRHHL[]A\@1ҾL1H5LHD$dH+%(u H1[]A\illegal instruction: require%s syntax error: %s%s out of memory: %sNULL variable in %sloaded %s%s%s %soctetecdhaesecpecp2bigfp12hashqp_Gloading lua initialisationinitError loading lua init scriptexitcoderequirecoroutinetablestringmathutf8debug%s garbage collection error: %srequired extension not found: %szen_requirezen_exec_extensionzen_load_string : Aint kww 1.3k6 7 8 9 : (; 0< 8= @@ HA PB XDG`FLhHkpIktJ ~xMVN]OQQaY [k\u]L^ M_ .`kbz+B a ::fp  :. Ww7Xbhkm k&k.X &! 0"0 ]  &  &H n k , ] :>   7k%kk<kcXXkikx&kk &&: k9 k7 k8 k 6 k#5 k94 kO3 ke1 k{ t k&&j&k k&& k&k+ # M&!Gkk kc& ${&Xk&.&&-k$k*k!kkk)k LpU|T {Ts"UUU|T2Q0GU|T  k' L%2r7 7 ]UvT <UvT Q0%UvT < UvT   X7 : ' kd Ltnkdn x UUT1Qd k(  L len .@s&p#O p u UvT|$U}TvR1 U}T1Q@{ T| U}Tv{ U|T {8 U|T {] U|T { U|T { U|T { U|T { U|T { U|T {; U|T ^ U}T|R1 U}T|R1 U}T Q|G U0T Q  U}T|R1# U}T|R1F U}T|R1i U}T|R1 U}T|R1 U}T|R1 U}T|R1 U}T Q|   : ]%nopk@ LG~UUT  dk  Ld# pd7  UvUvT Q0cAUvT GsUvT Q   UvT0Q1R0X0UvT GT Q    : Nk LN N/&O.O.&resPk {UvTTQQR}X0cUvT Q R}cQUvT Q R}cUvT Q R}   : &I~IH} : ; 9 I8 .?: ; 9 'I< !I: ; 9 I$ >  &I I :!; 9 IB H} !I/ .?: ; 9 '<.?:!; 9!'I@z4:!; 9 IB<:!; 9 IB : ; 9 4: ; 9 I?<4I4'I4:!; 9!I4:!; 9 I%  $ > : ; 9 !4: ; 9 I? .?: ;9 'I<!.?: ;9 '<"H}# $H}%.?: ; 9 'I@z&.?<n U \ U U \U\ V T U V U V T S T S@fUfUgaU]U ] U ]P\ \ P \ \V S#U#@UUVUVUVTSTSUVUVTTQQR]R]P\P\P\P\,`  sY  = V(4 k47X> t..xtFWG[/:0 !J J# /J w== m.X 0&&//J&JYL> X).^XJJZK k                nf= Q.b#~= w>  >vtJY-K ~ g sY JJYK  Ek. ) __off_t_IO_read_ptr_chainstrcmpsize_tluaopen_coroutine_shortbufluaopen_utf8luaopen_math_IO_buf_base__func__zen_exec_extensionluaopen_string_codecvtlong long intsigned charlua_KContextluaopen_aes_fileno_IO_read_endluaopen_fp12long int_flags_IO_buf_end_cur_column_IO_codecvtlua_CFunctionzen_require_old_offset_offsetlua_tolstring_IO_markerunsigned int_freeres_buflong unsigned int_IO_write_ptrnamesizeshort unsigned intstrcasecmpGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionlerror_IO_save_baseluaopen_octetlua_KFunctionintptr_t_lockluaopen_ecp2_flags2_modeluaopen_ecdhluaopen_hashEXITCODEluaopen_qpzen_extensionscustom_require_restrictedluaL_Reg_IO_write_end_IO_lock_t_IO_FILEzen_lua_initlua_Statezen_load_stringfloaterrorfflush_markerslua_tonumberxluaopen_ecpluaopen_debugrestrictedunsigned charshort int_IO_wide_datalua_callk_vtable_offsetzen_extension_tFILE__stack_chk_faillua_Numbercharfunclua_getglobalzen_exitcodelua_settop__off64_t_IO_read_base_IO_save_endluaL_requiref__pad5_unused2stderrcodewarninglualibszen_require_override_IO_backup_basecustom_requireluaopen_tableluaopen_big_freeres_listluaL_setfuncs_wide_datalua_gc_IO_write_baseluaL_loadbufferx/home/alby/dev/Zenroom/meson../src/lua_modules.c/home/alby/dev/Zenroom/meson../src/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits/usr/include/x86_64-linux-gnu/bits/types/usr/include../lib/lua53/src../src/lua_modules.clua_modules.cstddef.htypes.hstruct_FILE.hFILE.hstdint.hlua.hlauxlib.hlua_functions.hstdio.hzen_error.hstrings.hstring.hlualib.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx @H r A 8dH J F 0TFHA G0{  DBBG (EDG0 AAI 8(FEA A(D@ (A ABBE (EDM0K FAH DFKA D0_  GABI t  CABA  0 % 0@0L0  ]b1glqdvg{ZFmsx| @@d$-=Naov}( p &3@H]ky@lua_modules.c__func__.4__func__.3__func__.2custom_require_restricted.1custom_require.0.LC0.LC2.LC1.LC3.LC6.LC7.LC5.LC4.LC8.LC9.LC10.LC11.LC12.LC13.LC14.LC15.LC16.LC17.LC18.LC19.LC20.LC21noplerror__stack_chk_failzen_exitcodelua_tonumberx_GLOBAL_OFFSET_TABLE_EXITCODEzen_load_stringluaL_loadbufferxzen_exec_extensionlua_tolstringstderrfflushlua_callkfunczen_requirelualibsstrcmpluaL_requirefzen_extensionsstrcasecmpluaopen_qpluaopen_octetluaopen_ecpluaopen_ecdhluaopen_aesluaopen_ecp2luaopen_bigluaopen_fp12luaopen_hashwarningzen_require_overridelua_getgloballuaL_setfuncslua_settopzen_lua_initlua_gcluaopen_coroutineluaopen_tableluaopen_stringluaopen_mathluaopen_utf8luaopen_debug  )<*c,v*.*0 ,"'16 ,BG1V ,bg1n*/31 )*4 5@6OT7c jo)y*3*9: ;;*<a=p2======  =$!,=;"C=R*>b;s*?;7 )*@;*A;*B;*C+;7*DG;S*Ec;o*F;#G*$I <JK# +J2*I%g7n*<~&=M')*2+8@H+PX(NO (P08Q@HRP XS   * / #= D qR Y ` g z   } M ^     X  E ` * 7 D Q ^ k x  D    <  P  F * ~  ! / ,; SC fg q    t t B   * 1 <> K R^ <o |        9 Q& r= 8^ Wy       $ : P f |     X  R! H d | g  F S   ** g3@R V  c Vg Rlk  %D mH eM W [ ` k t " @ @/   6= eF @e i    g  8    m     ) D- B2 O PS LX v   e t  m / s9 T x^ y |       0  G2 < f_   Z  F   $ G /j K g    1P lT hY$u@ v  z   m 8dB]gj tDXZsF }! ~*I M R \ ` e o s x  8 0 h X m 0+1  0K5B 0Rkmz 0r 1 1W9 " 2& O* V. 2 6 : D I N  S X ] +b 2g ;l Aq Kv [{ c o y  <@X @.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.str1.8.rela.data.rel.ro.rodata.rela.data.rel.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@h7 &H,H12H@2XATp O@@a @n` p i@A  } x@BH .@ [U 0@8[0 d@h[@0#x0a)0*&++ 8+`@],( x4P^'/183 0 0 0 644 19040 ` ELF>C@@HdH%(HD$HFHt)HHHFHT$dH+%(uHfD1ff.@HdH%(HD$HUDHHdH%(HD$111H1H5HH5HHHH1H5HHHD$dH+%(u H]H(dH%(HD$1H4$H5HT$HHT$dH+%(uH(FILE*__indexCE  A       !int  { mtWt7 -tt nciX   top l_Gk ci p ( 0 8 3@ -H Pz X E ` mmmnnyXX  X.\mbh=BmQQmbgmQm%sQO5{OOO55 m m(m,m0Q4Q5{6{78sx "#Q{A; H\s] top^ _s_suj' k 8l f@mXB  !1"x5#Q H H  U- V-tt V V $ d} gc e - p f O b gm f h1 i i n j k2  q r}tt_ rm s &% 45 56^ /^ 0-tt0 0  1   2   3H u7 88  -tt         H         (  -0pc .!& l }tt_m  m ' nk8tvk  l     (H        LM NmOm Pab ce' kfVgctxh%)`E ld cin*8  ud O     (0 @HP T U V W -X ` -h -p -x - - - - - Hmm1 $   ) +mt9 , I -9 AI A_ A4AQ _ E u - m & s'( 5)  A 3 6 .m% QO< Qm/Y Qmp Qm0>m Qc Q m Qmm' Q51 6 QmJmJ LJ-QJ<JI5K.K@2lsL P UUT QPRRXX?@mgL@'Q3gNB4t p VUvT  Y tUvT < UvT Q  UvT Q0% UvT Uva.CTD /UvT0Q0 YUvT Q0?59 6L9$Q7*QL*%Qud*.O*:8ls+ ? 9 -?L Q UUT2: : ; 9 I8 I : ;9 I8 I~ !I: ; 9 I(  : ; 9 I8 $ >  : ; 9 I H}  : ; 9  : ;9 I!I/ &II.?: ; 9 '<:!; 9 IB:!; 9 IB'I : ;9  :! ;9 I8 H} :! ;9 I< :! ;9 I :!; 9!4:!; 9!I.?:!; 9!'I@zH}%   !$ > "5I#'$ : ; 9 % : ;9 & : ;9 ' : ;9 (> I: ; 9 ) : ; 9 * : ; 9 + : ; 9 I8, : ; 9 I8-4: ; 9 I?<..?: ;9 'I</.?: ;9 '<0.?: ; 9 'I<1.?: ; 9 '<24: ; 9 I31RB X Y W 41B5.: ; 9 ' 6: ; 9 I7.: ; 9 'I@z84: ; 9 I9.?: ; 9 '@z:.?<nUUTPTQQRRXXUVUVVPUPQUPTPQT;Q;BQBLQLQQ`UU,Iy  @ ) Y= ;NX o WX* Y*Wu*X w=  FK  sY metatablelua_Alloc__stack_chk_failstacksizelua_fatalsizearraygcrunningsweepgcistailcallEXITCODEflagslua_TValuepreviousgckindunsigned intnextversionTM_SHLnuseTM_SHRl_memgcfinnumlastlinedefinedGCObjectTM_LENTM_BXORnresultslsizenodefuncmodehookcountallgcTM_BNOTTM_MODTM_MODEgrayagainisvarargTM_DIVglobal_StatehnextfloatshrlenluaD_throweventluaL_Regbaseshort_srcCallInfoflibluaopen_ioInstructiontotalbytesNodebase_ciGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectiontobefnzStkIdcurrentlinestack_lastluaL_loadbufferxGCmemtravlua_Statelua_createtablesize_tnparamslua_loadsig_atomic_ti_keylua_DebugbuffTM_POWTM_CALLTM_EQcharstrtlua_CFunctionlua_settopi_ciptrdiff_tallowhooki_vallua_ReadererrorJmpstatusGCdebtstringtablecurrentwhiteallweaklua_HookpaniclinedefinedTM_GCTM_NEWINDEXlua_KContextlnglenTKeyUpValold_errfuncopenupvalsavedpclua_Numberl_registryTM_MULValuesizevalue_extrastrcacheTM_INDEXlua_setfieldseedmainthreadarrayLoadSintptr_tTM_UNMTM_IDIVmarkednamewhatweakerrfuncTM_ADDshort intlua_pushvalueoldpclong intlastfreehashgrayTableephemeronluaL_setfuncslua_KFunctionlu_bytenodeTM_BANDiolibgetSsourceluaL_newmetatablenamestacklong unsigned int__sig_atomic_tGCestimateTM_BORmemerrmsgunsigned charlua_longjmpTM_LEwhatfinobjTM_LTnCcallslu_memgcpauseTM_NcreatemetanupsTStringsigned chargcstepmullua_Integershort unsigned intfixedgcbasehookcountTM_SUBgcstateluaL_checkversion_twupsdoubletmnamefreallochookcallstatusTValuehookmaskgclistTM_CONCAT/home/alby/dev/Zenroom/meson../src/lua_shims.c/home/alby/dev/Zenroom/meson../src/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits/usr/include../lib/lua53/src/usr/include/x86_64-linux-gnu/bits/types../src/lua_shims.clua_shims.cstddef.htypes.hstdint.hlua.hlstate.hlauxlib.hllimits.hlobject.hsig_atomic_t.hldo.hltm.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx QH y G 8-H LEL  FA pJH0| A  Q  "',=`-G]fq|PJlua_shims.cgetSiolibflib.LC0.LC1.LC2__stack_chk_faillua_fatal_GLOBAL_OFFSET_TABLE_EXITCODEluaD_throwluaopen_ioluaL_checkversion_lua_createtableluaL_setfuncsluaL_newmetatablelua_pushvaluelua_setfieldlua_settopluaL_loadbufferxlua_loadM~* %E|   * 1 _6 D wK T [ <b i w ~ 2  Z     + 8 E qR _ l y     % W    d  ! 0& 2 <W % t    w  l ) 7 SE S a o }  < U  U    ' z4 L PY f y } l  }   3      3 >~ > o I    Y   ) P7 eE d q    i  9  ;   " / C I^ m    n   _   *  ,  e 7! #' - E3 9 @? E K Q W ] c i o u ${      D    F R L` y     7 , u  l C  M" / < 2I V c p } O   &  z   V` Lv  `  D  H    & J= hZ q Z   t l  P$ ( - 7 (; "@ DJ FN BS l] \a Xf p rt n       ) - 2MWu )0KZIh  N     D  Q /`   %@ D  " 0& M* T. }2 6 : D I N S X ] b &g /l 9q Cv M{ \ b` <`PtP.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.rodata.cst4.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@%&,12@ HZIU@P'f]t0@(@0 /M@X@(0|0Qh0 &  !@B`! $B/205 0 0 0 644 33688 ` ELF>|@@AWIAVAUATUSHHH(dH%(HD$1D\$`Dl$hEDHE1A@uHAAA+fA McLd$H-HHDDH1AITA HHL9ƒHuADDDIcE9DAMA)E)DH1EHAIɃAA9DL1EtI9HHEt&fDI9v0HHHAuAI9v Ic HHHEuޅtfI9v HHHuHD$dH+%(H([]A\A]A^A_DufDF41A A)f.AVAUATUHSHHJH dH%(HD$1HD$uFHD$Ht HUH9v+HT$dH+%({H []A\A]A^fDD/ҐL%L-HD$1%tH9vHHt@tHD$mLq1ɍPw IcL>PE1ɀ w$CDLPAIV.I֍PЀ v<*<.AIVIUAIVAIVAIVAIVjfDAIvRIp@ h1HIvTPA$IƋ3/HC3Ht$QARHHH|$bXZH|$AIN$IƋSSIIIHD$H9v%HHD$IƋ3/HC3LE~ xD9ALMA81HcA<0uA)AIEE19'HD$DJA)N\)I) L9SH9vDHED EuHD$D9HD$)A) @9 H9v HAAA xIƋ/ƒHSHD$H913t/SHC3LcHt$QA RL13@tXO/HC3DHt$AQR1 3@t>5/HC3DHt$AQRj13@t/3HC3D#1/ ЃHCHHT$18C=C<*/ЃHCAIvIA6IF@%@SwL@Ic4L>IA6@lI@P%@SY@IctL>A6IF@IƸɋ/w0ЃHCDAIVIHCHCHPHSHCHPHSAvIF@IƸTHCHpHs/HC3LQ/HC3LHCHpHsj  ? :!int(b"k{{:#$cV%Astr$.fmt6&'ret .(ap  ~  #L )@ 6 , Y UUTTQ1R XQY~d A/ Cstr'.fmt:GC   5T H < 0 ` j *u       @+Hwk_S H{wk_S a          H wk_S H ;wk_S,Hwk_S HXwk_S  P  P  PUQvd {.>.cK.- F *:. OAmin"Amax+A.4A A  /  A A A A Hwk_S Huwk_S H wk_S H wk_S Hz wk_Sd  : *:. Amin#Amax,AAAcntA0.  ). = MCch O minAmaxA A A A . numi  numm  numq  1numu  HOA2RAY __sR__nR. R  RC341B$ > 41B !I:!;9 IBI~:!;9 I:!;9 IB 1RBUX!YW  1RBX!YW  4:!;9 IB : ; 9 I 4:!; 9 I4:!;9 I :!;!I8 41: ; 9 IH} 1U:!;9 I4:!; 9 I I!I/ 7I.?:!;9!'I@zH} U.:!;9! ' !4:!;!9 I:!; 9!I % !$ > "I# : ; $ %&I&'4: ;9 IB(4: ;9 I)1*41+1RBUX Y W ,1RBUX YW -.: ;9 '@z.: ;9 I/4: ;9 I0.: ; 9 'I 1 2.?: ; 9 'I 43.?<n: ; 4.?<n"UUTTQXQ p $ &~TTUUUUUUTVTVTVQrQRSRSSSSRRrRr^Q^QQQQQT^TP ^ R P ^ P ^ ~ P ^ P ^ P ^TP~^P^Q^^~P^P^P^P^P^^P^P^P^TVVTVVUUUUUUQQQPPPPPPPPPP~ Q ~ ~ ~ ~ ~PPT~pTTPPT~T~~p~p~~p~~p~~p~~p~~p~ Z Z ZZZZZ 00YY0 Y 0 Y Y YYYYYYYYYY   Q Qq $0 $+( Q    Q Q Q QQQQQQ QQQQQQ0QQQ 0001261111144 0566636 00RRRRRRR R  0 R R R R  RRRRRRRRRRRRR 000003 0 3 3 3 3 3 0 0 000003210024333QV@U % V @ U QQQQ YYY RRR XX VVVV @@@@ UUUU Y y $0 $+( t TYy $0 $+(tT 0 P0 0 Y Y0rR00 Z V @ U   V @ U V@U q Q V @ UUSUSTTQZQZQqRqRRRXXXYX^y^YYyYY88[0 $0*([0 $0*('^0^^^0-0^8^R^UPURURU'0rR__0_'0YR0QqQRQqQRrQ0Q'0{[{[0['^0}  $0.  $0.0  $0.^^ZZTTSS0ZTS $ &"`ZTS ZTS ZTS,?     J ;   ;t}< JJ}uXf =u J1JfY  JYJVJ):< [ Xt< I=K_o I=Ko I=Kk I=Kc I=Kg?J@J;<< u I <K@J<Y@<tJK~<q<<]  .= Z    <= i. G 9.= Z    <Xp <<X <<(X  <= ; YL GCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx HFBEB B(A0A8J` 8A0A(B BBBF lh/ FBB A(D0KPO 0A(A BBBG XG`QXAPXG`HPA XA`B D XA`E K A F  !"&7P/ F Tmutt_sprintf.cfmtint.LC0.LC1.LC2__stack_chk_failmutt_vsnprintfmutt_snprintf__vsnprintf_chkt { B@ 1  ;  <@ HLPT X$\(`,0h48p<t@DHLPTX\`dhlptx|  !)E159=AEIMQUY]aei muy} $(,048<@3DHLPTGX\`dhjlptx|4L#'+/37;?CGKOSW[_cgkosw{  B $(,048<@DHLPTX\` dhlptx|   n  #  + / 3 7 | K G K 1S V [    $(,048<@DH L PTX\`!dh)lEp1t5x9|=AEIMQUY]aeimuy}5Il 4 $N(,0  >  * / %= BK OR 9W c T| i X n   6       $ (  - 8 &< "L >P 8b Yf W   k i z v  " ?  P; ? D O S c  g l w 0{ (} , V P  l  x   , \    T .   6   ! * ' .  ?I KY  ]  f  j  s & w $  2  0  <  :  H  F  R  P  ^  \ . V n  f       !  *  .  7  ;  D  H  Q 0 U ( Z Vc ] g M p  t  }     /  -  9  7  C  A  O  M   Y  W  e  c % o ) m 2 { 6 y @ J kW  [  d  h  q  u  ~     v                   65 I 7T *` Gl   *     G     '   U M  y u  * . 3 C ,N /R !W #b sf ck 1|    x    f   s      + ' > : Q M d `()(E uI sR V _ c l p zL !        pp        $ . J N W  [ d h q u { F   * G    b 1 *= I U k v    G A 1M Z ^ e i  " 3& P* W. z8 = B G L Q [P lP .symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rela.rodata.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @? @D& , 12 )E 4@@E8Rn M@^x^JlF&l10|@8z0 1S2 @hz 0\=0)@0A&=A@A `A@{HPB Dd{/230 0 0 0 644 6240 ` ELF>`@@AWAVAUATUSHdH%(HD$1Hu)E1HD$dH+%(uwHD[]A\A]A^A_@IIE1K,7I9IFfD8u1HH>1LcAtExMM)uvC  inthCE <o% X XXbuffn#t[ U >TvQsR0 = X( buf:f nFt t tretX8 Xo8C'( $ > II~41B&I !I:!; 9 IB H} :!; 9 I 4:!; 9 I %  $ >  : ; 9 I.?: ; 9 '<.?: ; 9 'I<.?: ; 9 I<.?: ; 9 'I@z1X YW 1B1 1UH}.: ; 9 'I 4: ; 9 I4I4 .?: ; 9 I<I!I/ .?<n'U'LULYUY_U'T'LTLYTYTY]}|]Y^pSr\\,eiE   X<& ~f  Z HtXV fgY = x B  " 2& O* V. 8 = B G L V .symtab.strtab.shstrtab.rela.text.data.bss.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@ H&,6G1@ hB=Pe0`@80 t@h 00s0< &b h  h@X P  @ Ep.._src_repl.c.o/0 0 0 644 15912 ` ELF>h7@@ATIPUHdH%(HD$11PHHLHHDHHD$dH+%(u H]A\fHdH%(HD$HH8HD$dH+%(u1Hff.@UHHdH%(HD$1HH$HPw*HƿHD$dH+%(u H1]DH5H1SHH5HdH%(HD$1HHDPH1HT$dH+%(uH[USHPH(dH%(HD$1HHuOHHu1HHuHD$ D$ HT$dH+%(uH([]Error: LUA string too longzen! zen>  Lint___C < < ~ ~7;*/XD<PUXo={X>X C !luaD~E~F~HI J (K 0M8N @O HP PR~XS`TXVXWXX~Z [ D\ o]C?_" 1 3X 6  7  8  9  : ( ; 0 < 8 = @ @ H A P B X D` Fh HXp IXt J fx M5 NJ O Q Y r [ \ ] ^ ~ _  `X b # +CC$   Xz9X% $Q /qX XX~X~ X~&* ~ (~? KX ZKLretOX(U PUsTvU0TvUv ?mC ret?X'?#len@ AnopDX(w F U0TsQ P5U1TU $0.(Q5 4Xx lua4)len5 `6nop:XQUvT1Q`U19 UvT  .XA_ lua.q #Xww lua#$len& *w ' U0TvQ P(3 U PQ U|Tvi Uv +$  X~%, : ; 9 I8 II~ !I: ; 9 IH}$ > H} 1B .?: ; 9 'I< .?:!; 9 'I@z :!; 9 IB :!;!I8 <'I4:!; 9 IBI!I/ 4:!; 9 IB:!;!$9 I.?: ;9 'I<.?:!; 9!n'I<4:!; 9!IH}% $ >  &I& : ;   : ; 9 ! : ; 9 I8 " : ; 9 #: ; 9 $4: ; 9 I?<%.?: ; 9 '<&.?: ;9 '<': ; 9 IB(1RB X Y W )4: ; 9 I*1RB UX Y W +.?: ; 9 'I 4,.?<nUSUS0PVPV0P0PLUUTSTS0PT U $0.( PS0UVUVPPUUUq\qrUrw\#5059P9oVrwV5C0CLP5C P59P9CV5C0,L(25:@C  " VX   X v= Xz l<y YY.  tY +Z VtJ faY 2)  u)SJ   WK Y^   KJ X  VJ Y< HtYKJ xJX6sprintf_tstdout_fullprompt_IO_FILE__read_chk_IO_save_endshort intsize_tmallocstderr_fulllua_pushlstring_offset__fd_IO_write_ptr_flagsrandom_seed_IO_buf_basessize_tGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionstderr_pos_markers_IO_read_end_freeres_bufwrite_codecvt__nbytesline__buffloatluaL_checklstringFILEdebuglevel_IO_markerlong long intrepl_prompt__ssize_t_lockstderr_buflong intrandom_generatorfp_offset_cur_columnrepl_flushgp_offsetsnprintffflush_old_offsetsprintfunsigned charzenroom_t_IO_save_basereadsigned charvsprintf_trandom_externalunsigned intzstd_d_shortbufrepl_writestdout_len_IO_write_base_unused2_IO_read_ptrzen_exec_script__pad5__read_chk_warn_IO_buf_endreg_save_areavsnprintfcharsnprintf_tvsnprintf_t_wide_data_freeres_listvsprintfzstd_cerrorleveluserdatalong unsigned int__va_list_tag_IO_write_end__off64_toverflow_arg_area_filenoshort unsigned int_chainstdout_pos_mode__off_t_IO_backup_base_flags2_IO_codecvt_IO_read_base_vtable_offset_IO_wide_dataerrorrepl_read__read_alias__stack_chk_failfreestderr_lenstdout_bufstdoutrepl_loop_IO_lock_tlua_State/home/alby/dev/Zenroom/meson../src/repl.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/include/usr/lib/gcc/x86_64-linux-gnu/11/include../lib/lua53/src/usr/include/x86_64-linux-gnu/bits/types../src/repl.crepl.cunistd.htypes.hunistd.hstddef.hlua.hzenroom.hstruct_FILE.hFILE.hlauxlib.hstdio.hzen_error.hstdlib.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx (wFID0V FBA HAH s A dxEL F CF mES N AA ,EAL@h AAD    w.3DAOelsx~xPmrepl.c.LC0repl_readmalloclua_pushlstringfree__stack_chk_failrepl_flush_GLOBAL_OFFSET_TABLE_stdoutfflushrepl_writeluaL_checklstringerrorrepl_promptrepl_loopzen_exec_script$6IQs*3 =D[} H    * 1 8 /? F M T >b %g Zs    H   ` ?  l     E p        I% 2 ? L lY Vf .s       j  z    ,, 9 F S ` m z `  b 1 w B ' r z I    # r0 = J W d Iq T~ #    z   9 : R r s   P & &   b) O@ Ji m  r | > 4 m c"L P= A F Q U d h m w {    ' % 1 /6D No Bs :  f bA H U < y@ uE R ` j         5        : (4 MR Uj wx  z     " +& H* O. r2 6 : D I N S X ] b g %l +q 5v C{ J T \ h LhP.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @L@(&,12@M H@!Yf l g@H30  0|@x30 9O@3@0W 0wq0& 0@5x  `6/254 0 0 0 644 19456 ` ELF>E@@AVAUATUHSHdH%(H$1HHH5BHIHHIHA$ ~QHKI-MD$LLHHHHsLL(@H5H1H5H11H$dH+%(H[]A\A]A^DHH5H1HH5H1HH5H1HH5H1ff.AWAVAUATUHSH(dH%(HD$1IHA$H5BHIHHIHAU ~kHIHJAHpHHHIHILLLL(@H5H1H5H11HT$dH+%(H([]A\A]A^A_ÐHH5H1HH5H1HH5H1HD$HH1H5LL$fHH5H1HH5H1ff.AWAVAUATUHSH(dH%(HD$1IHA$H5BHIHHIHAU ~kHIHJAHpHHHIHILLLL(@H5H1H5H11HT$dH+%(H([]A\A]A^A_ÐHH5H1HH5H1HH5H1HD$HH1H5LL$fHH5H1HH5H1ff.HxH H=dH%(HD$hHHHt$HL$@HD$PHD$XH$HD$HD$HyHD$HHD$ HAHD$(HHD$0HiHD$8HD$HHD$hdH+%(u HxNULL variable in %sAES-CTR process abortedECDH decryption abortedECDH encryption abortedgcm_encryptgcm_decryptctr_processctraesAES.ctr_process accepts only keys of 16 or 32 bytes, this is %uAES.ctr_process accepts an iv of 12 bytes minimum, this is %uECDH.aead_decrypt accepts only keys of 16,24,32, this is %uECDH.aead_decrypt accepts an iv of 12 bytes minimum, this is %uECDH.aead_encrypt accepts only keys of 16,24,32, this is %uECDH.aead_encrypt accepts an iv of 12 bytes minimum, this is %ugcm_encryptgcm_decryptctr_processb  intC*5||k7hC   !" o Nk C Nr C  C o of   .; | .  len C max C val w 0  1 0KJ ^^ ~^w C^CCww $CC !.w..CLU TQ\  .  .CVL#f  a {keyinivoutUvT1UvT2UvT3U{T-~UvT}c+U~KCU~[UvUvT UvT Q UvT Q UvT Q HUvT Q \ f . VnCd Ln#f kpinvivxh~outt21UvT1NUvT2kUvT3UvT40Uv0UvT@U|T}QR~XsUv*UvT \UvT Q UvT Q UvT Q UvT Q $ UvT Q V UvT Q \ GC\ LG#f kIinOivQhWoutYt[) UvT1F UvT2c UvT3 UvT40 Uv0 UvT@ U|T}QR~Xs Uv" UvT T UvT Q  UvT Q  UvT Q  UvT Q  UvT Q N UvT Q \ !I~H}I4:!; 9! IB$ > &I: ; 9 I !I : ; 9 I8 :!; 9 I8 I !I/ .?: ; 9 '<.?: ; 9 'I<:!; 9 IBH}.:!; 9! 'I@z4I4.?:!;9 'I<4:!; 9!I% $ > <'I : ; 9  : ; 9  : ; 9 I8 : ; 9 .?: ;9 '<.?: ; 9 'I@z 4: ; 9 I!.?<n  U U2U2VUV6?P?SSPSdmPm]P]}P\P\PSPSUVUVP\P\P^P^P]P]P__P_PSSPSPPYU V U VP \ P \P ^ P ^P ] P ] P _ _ P _ P S S P S P P Y ,gb  & i&U/X</s<J\ yt 4p....&T. h&V X<Ks<  J] %= vt  ..k... X%-..&B.h&VX<Ks<  J]% = vt  ..k... X%,..?. tut Julu FYaes_methodsAES_GCM_ENCRYPTlerrorAES_endAES_GCM_DECRYPTrkeyfloatlong long intunsigned charluaL_Reg__uint32_tshort unsigned intctr_processo_dup__stack_chk_failamcl_aesfkeylong unsigned intAES_initfunco_new__func__lua_Stateunsigned intchargcm_decryptmodeGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionocteterroro_argnameaes_classzen_add_classshort intuint32_tlong intluaopen_aessigned charlua_CFunctionAMCL_AES_encryptgcm_encrypt/home/alby/dev/Zenroom/meson../src/zen_aes.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits../lib/lua53/srcmilagro-crypto-c/include../src/zen_aes.czen_aes.ctypes.hstdint-uintn.hlua.hlauxlib.hamcl.hzen_octet.hzen_error.hlua_functions.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx DFGB A(D0G 0A(A BBBF HdFGB B(A0D8D` 8A0A(B BBBB HFGB B(A0D8D` 8A0A(B BBBB H A   ". 9E   PU@Z_din,sx@}D\ht zen_aes.cctr_process__func__.2gcm_decrypt__func__.1gcm_encrypt__func__.0.LC1.LC3.LC2.LC0.LC4.LC6.LC5.LC7.LC9.LC8.LC13.LC14.LC10.LC11.LC12o_argAES_inito_dupAMCL_AES_encryptAES_endlerror__stack_chk_failo_newAES_GCM_DECRYPTAES_GCM_ENCRYPTluaopen_aeszen_add_class/ D] v !"#$%&3 :D&S Zd&s z& &'  4 V p(()%& &# *4&C JT&h ty& & &'  "; T v ((*%&# *4&C JT&c jt& & & &' 'o,'   * 1 8 ? R TY v` $g l k     @ 0 b   b F< I V ;     +1 L #d >      4 ?^ b g u   * " # C QG GT zX re i w { 3az,D\wH h   2? Il u       2 * W O ~ t     2O8lZt!,+FS ]8x X }    % @ M  W e On      '  L D q i       * ?G Xd z      D# 8> K  U Xp }  x          8 E  O ] a  " .& K* R. u2 < A F K P U Z _ d i s h.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.str1.8.rodata.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@p(&,12@2O ,\< f W@@1(hv0@hB0 k@B0F[0 0!&!! !@D`#8  H'&xD/274 0 0 0 644 130528 ` ELF>`@@ATUHSHHdH%(H$1H~H{f}(C(t[f"Hm fLc HLLHH$dH+%(/H[]A\fHuHH{H$dH+%(HsH}H[]A\H{ ?H51H|$H|$"H~ H5H|$H|$f.L$HsLH5f}(C(HufHl$HC(fH51ff.U1H1HdH%(HD$1HHHHHH0HHH8HHHpHHHHD$dH+%(u H]fDAT0UHHdH%(HD$1IH|HذHH841A$big3fAD$AD$AD$ fAT$(ID$ID$ HD$dH+%(u)HL]A\@HH5H1HdH%(HD$1f(t!HD$dH+%(u.H H@HD$dH+%(u HHff.SHHdH%(HD$1Ht5f(tf1H511HT$dH+%(uYH[fDH uf(uĿ8C0HC1fC(8H51fDUHSHdH%(HD$1HHtFHC~HK1HcЃ9CHD$dH+%(u(H[]fHH5H1UHSHdH%(HD$1HHHt>HH{H5HHPXHD$dH+%(u*H[]@HH5H1AW1ҾAVAUIATUSHHdH%(HD$81IHLIHLIA<$M1H%fI@LcMA>tdIwHIH A60@ vLHL1H5H5L11f.IHT$8dH+%(uKHH[]A\A]A^A_HH5L1HLfSHHdH%(HD$1H tUf(Hu[pfS(C`HC pHT$dH+%(H[fDHtf(uf.pfC(HsHC HH{H{C`gH{ \1H51eDH51Hff.ATUHSHHdH%(HD$01/wmHH} ~dH} E1HSH} IcAD9#HD$dH+%(u}HD[]A\H51E1DHH}~H}E1f.HSH}IcAD9#sfAUHAATUHHdH%(HD$1IHtIHxt"HD$dH+%(HL]A\A]ÐI|$ uH5H1E1fDHHDHIHt3HIHt;LHLHiH5H1PfHH5H1UHSHdH%(HD$1fx(Ht?Hx HtH{tH5H1HD$dH+%(u1H1[]HxHtH{ tH5H1UHSHdH%(HD$1HHt9H{1H@HD$dH+%(u)H[]HH5H1fAUATUHSHdH%(HD$1HHf{(HIHfA|$(u\HIHMHHK It$I}HT$dH+%(H[]A\A]ÐH5H11H5H11HH5H1*HH5H1.HH5H13ff.ATUHSHdH%(HD$1HHHIHtff{(u fA|$(t6H5H11HT$dH+%(upH[]A\f.It$H{H뾐HH5H1}HH5H1Hff.AWAVAUATUHSHdH%(H$1IHOHHHVHIH]HsHHHIHZLHl$@L$I~I~IuHL$LfLH~6IL$$t^I~HHHLHH$dH+%(H[]A\A]A^A_DHHLLHHHUDHH5H1HH5H1HH5H1HH5H1ff.AUATUHSHdH%(HD$1IHtmHIHtxHHHHIUIt$H{HD$dH+%(H[]A\A]fDHH5H1vHH5H1HHHp@HH5H1Off.AWAVAUATUHSHdH%(H$1IHHHHHIHmHIHLfA|$(u@f{(MD$Hl$@LHf{(u%L$HsLf{(Il$ tLc LHL$ xQLHLIVI}LH$dH+%(VHĨ[]A\A]A^A_DHLLIIVLLIvI}LfDHsLIt$I}HSIvI}]HH5H1dHH5H1HIH{@HH5H1ZHH5H1 IT$HsL$ LIvLIvI}LAUATUHSHHdH%(HD$81HHHIHf{(u fA|$(t8H5H11HT$8dH+%(HH[]A\A]fDHsILHHHtiHIT$H{LH{HH5H1SHH5H1HH5H1zff.AUATUHSHHdH%(HD$81HHHIHf{(u fA|$(t8H5H11HT$8dH+%(HH[]A\A]fDHsILHHHtiHIT$H{LH{HH5H1SHH5H1HH5H1zff.AVAUATUHSH@dH%(HD$81HHHIHHIHf{(ufA}(u fA|$(t=H5H11HT$8dH+%(H@[]A\A]A^fHsILHHHHIUH{LIL$H{HH5H1>HH5H1HH5H1HH5H1Vff.AVAUATUHSHĀdH%(HD$x1HHHIHHHIHf{(ufA|$(ufx(t7H5H11HT$xdH+%(BH[]A\A]A^HsILIt$Ld$@LHHHHIMH{LLH{yDHH5H1HH5H1HsILIt$Ld$@LHHHt?HH{H THH5H1 HH5H1fATUHHdH%(HD$1IHt@LHpIHD$dH+%(u/H]A\HH5H1ATUHHdH%(HD$1IHt0LHHD$dH+%(u(H]A\ÐHH5H1AUATUHHdH%(HD$1IHtVHIHtaLHL{1H@HD$dH+%(uMH]A\A]@HH5H1fDHH5H1fAUATUHHdH%(HD$1IHtVHIHtaLHLHHD$dH+%(uPH]A\A]HH5H1fDHH5H1fAUATUHHdH%(HD$1IHtVHIHtaLHL1H@HD$dH+%(uMH]A\A]@HH5H1fDHH5H1fAUATUHSHdH%(HD$1HHHHHHtef{(uFHIHHsI|$ HT$dH+%(8H[]A\A]H5H11HIHf{(uxfA|$(uoHIHLIT$HsI}H I}XHH5H1H5H11HH5H1HH5H1$HH5H1(ff.AWAVAUATUSHH|$dH%(H$1IHI~Ld$H\$P1L$L$IvLHHL L&HLHߺ LHIvH~ʍ}HcIŅuP0fAEH|$LLH$dH+%(HĘ[]A\A]A^A_1H$T@LHLH$0AL$LLLLLLLLcMtCA91DHcHcփLL9DD@:9 H|$HH514ff.ATUHSHdH%(HD$1IHtWHHHHt_HIt$H{HHPXHD$dH+%(uMH[]A\DHH5H1fDHH5H1fAUHATUHSHdH%(HD$1HtiHHIHMHI|$AHsHHPXHD$dH+%(HD[]A\A]fDHT$HDd$Etdf*/fA~HHHHH{fAnA,fH{XHIHAU0nHIHLLHA HH5H1H5H10f.0H5H1DHH5H1HH5H1,HH5H1)ff.ATSHH(dH%(HD$1Ht]f{(IHt3Hs I|$ HD$dH+%(uGH(L[A\DHsI|$HH5H|$H|$ff.AUATUHSHdH%(HD$1HHHT$HDd$EfHH*D,IHf{(I|$uAI|$DAHD$dH+%(HD[]A\A]I|$DAfDH5H1DHH5H1HH5H1>ff.AUATUHSHdH%(HD$x1IHHHHf{(LHIHfA}(u;HsI|$HT$xdH+%(HĈ[]A\A]fDIu HHHSI|$H뱐H5H11HH5H1>HH5H1HH5H1 fDAUATUHSHdH%(HD$x1IHHHHf{(fA|$(uQLHIHHsI|$HT$xdH+%(HĈ[]A\A]DHIHMIt$ HHHSI}HDH5H11yHH5H1HH5H1HH5H1HH5H17ff.ATUHSHdH%(HD$1HHtgf{(uHHIHtpLHsI|$ HT$dH+%(ubH[]A\@H5H11HH5H1|HH5H1sfDAVAUATUHSHdH%(H$1IHQHHHXHIHtfA|$(C(u7fIt$ILf{(u#Ld$pHsL@f{(Mt$ tLc LLLxII} LLI} H$dH+%(#H[]A\A]A^DH5H11LHsI|$It$I}HSI}H5I}iDHH5H1HH5H1HIH@HH5H1oIT$HsLd$pLI}H5LJff.fAUATUHSHdH%(H$1IH;HIHBHHHfA}(u fA|$(t}1H5HfA}(Im fA|$(t{Md$ HH{ LHH{ H$dH+%(H[]A\A]@HH{IT$IuH{It$Ld$pLsfHIuHH@HH5H1HH5H1HH5H1fDAVIAUATUHSHĀdH%(HD$x1f~(H~ H Hu ILLuLIH Eƒx16bit)Import of octet to BIG limit exceeded (%u > %u bytes)the number of bits to shift has to be a numberdivision not supported with double big modulusmodulus cannot be a double big (dmod)cannot make square root of a double big numberSubtraction error: arg1 smaller than arg2 (consider use of :modsub)Invalid BIG number, cannot convert to octetO.from_number input is not a numberBIG too big for conversion to integerNumber conversion bigger than 32bit, BIG truncated to 4 bytesnewbigbig_from_decimal_stringbig_modrandbig_randomlua_bigmaxluabig_to_octetbig_to_hexbig_to_decimal_stringbig_addbig_subbig_mulbig_modbig_divbig_eqbig_ltbig_ltebig_concatbig_bitsbig_bytesbig_to_intbig_sqrbig_modmulbig_moddivbig_modsqrbig_modnegbig_modsubbig_modinvbig_modpowerbig_jacobibig_montybig_paritybig_to_fixed_octetbig_shiftrnew_octet_from_bigbig_dupbig_argbig_newG^+ 7,int ).. *J-$.!J!J!! Q f w 7/ X5 \. h<A .PP$U0  U !0d "d ; .U < .U =  .$U$ >5: .XU$ Crlua D E F H I  J ( K 0 M8 N @ O H P P RX Sr` T. V. W. X Z  [  \  ])Q? _XQ ira  .T X .\ `QQ  Dlen .max .val   :\lQ \ ;}Q< &g (PXES ) 8 *% 00len..val   "_(&big%&libxmyo<zqx r8 .valb &ecpn1Z8UP._   P.U7P..!NPNDUnPU  .   V b< P  .  K  cNN = {NN 9          #  @  ]  .y #   . .    . P$  .5  B W n P.  . . P.. P ] .$ P. .!    o .0 . G  ^  E .t  u .  N Pr Q .   $ PU#- U  .D   .[ &s PU    P.N P. .. P.U @% P.U.A P..a P.U| P. PU W . Q . . '.m LP} x { _ U TxQ{]} Qm  Q  .BsL"Pcs  i.Dn .rsYQUvT1 tUvT2QDXUvTs0  T} t T}| UvT | 3UvT Q | eUvT Q ]"Q x .gL"Pcs YUvT1n W 'Uv| YUvT Q ] .L"Pys msxsYUvT1YUvT2[5UvTMUsy| UvT Q | UvT Q [Uv| UvT Q ] .vL"Pxs ysYUvT1YUvT2| UvT   Uv| 6UvT Q | hUvT Q ] .BqL"Pys ns tPxsYUvT1Y:UvT2| _UvT G xU[UvTUsT}0 | UvT Q | 1UvT Q | cUvT Q ] q.BlLq"Pyrs nss twPxysYUvT1Y5UvT2| ZUvT G sU[UvTUsT}0 | UvT Q | ,UvT Q | ^UvT Q ] a.La"Pybs divcsmodds thPxjsY)UvT1YFUvT2YcUvT3| UvT G U[UvTUsT~0 | (UvT Q | ZUvT Q | UvT Q | UvT Q ] D.LD"PyEs zFsnGs7 t1LP~ t2L PxOs| UvT G U~G U[UvTUs | UvT Q , t1VP~ t2V PxYsT~Q|0 G U~G U[UvTUs | UvT Q YIUvT1YfUvT2 UvT3Q | UvT Q | UvT Q ] +.ZL+Pl,s r-sd1s  t3q~ U~ .T~YUvT1Y UvT2X(UvT}| ZUvT | UvT Q | UvT Q | UvT Q ]Q .}!LPls rs7 d!s t"q~[UvTU} U~# T~ | UvT Q  d%sXp UvT| | UvT Q Y UvT1Y UvT2| !UvT | =!UvT Q | o!UvT Q ] .R^#L !Ps sn# msdsY"UvT1Y3"UvT2[K"UvTc"U}5 | "UvT | "UvT | "UvT Q | #UvT Q | P#UvT Q ]n#Q ^# .$LPls dsY#UvT1[$UvS*$U|{| \$UvT | $UvT Q | $UvT Q ] .X(L$Pxsh( nsmsP}ressP~P~& tmpP%UTvQvG %UvT0 &Us UsT1Y8&UvT1YU&UvT2Yr&UvT3G &U}[&UvT&U~ &T1G &U~ 'U~/'UsT}G'Qvd'UsT1'UsT}| 'UvT Q | 'UvT Q | (UvT Q | J(UvT Q ]h(Q X( .&+LPls udrsds)eoutC)Uv[)U| | )UvT  | UvT Q Y)UvT1 )UvT2Q Y*UvT2[+*UvTC*U}0 | *UvT Q | *UvT | *UvT Q | +UvT Q ] .+L"Press [+UvT+Us| +UvT Q ] .7-L#PsG- ressY,UvT1[,UvT,Us| ,UvT Q | )-UvT Q ]G-Q 7- ~.X1L~"Pls rsmsdsQ/_l_r llq| lrq}. t q~ tmP|@q.UT|Qv#.U|T Q|/ t q~@.U~TvQ| #T~ /U| 6/U} ]UvT|5/ tP~/U~/U~ Q~Y/UvT1Y/UvT2Y0UvT3[+0UvTC0U}| 0UvT Q | 0UvT Q [0Uv| 1UvT Q | J1UvT Q ] `.34L`Plas rbsdcs2_le_re lleq} lreq~ :2U} S2U~Sk2U}]2U~T|@2T~Q| | UvT )(3 trP~3U~ Q~YE3UvT1Yb3UvT2[z3UvT3U}0 | 3UvT Q | *4UvT Q [B4Uv| t4UvT Q ] N. 7LNPlOs rPsdQs5_lT_rT llTq} lrTq~ p5UvT S5Us5TvQ|  5U~ U}Y5UvT1Y6UvT2[46UvTL6Us0 | 6UvT Q | 6UvT Q | 6UvT Q ] D.p8LDPlEs rFsresH.Y7UvT1Y7UvT2Q;7UvT|Q}W 7Uv| 08UvT Q | b8UvT Q ] ;.9L;Pl<s9 r=sres?.Y 9UvT1Y(9UvT2Q;L9UvT|Q}W d9Uv| 9UvT Q | 9UvT Q ]9Q9 2.Q;L2Pl3s9 r4sres6.Y:UvT1Y:UvT2Q;:UvT|Q}W :Uv| ;UvT Q | C;UvT Q ] #.G=L#%Pl#-sr#5sres$.<_l'_r' ll'q} lr'q~ !<Uv 9<U|]W<UvT| p<U~ U}0 0 "| <U}T | <U}T | =T | 9=T ] .2>L"Pas o Nres Y=U|T1kK>U|Tv >U|T [ C>U|T  a>U|Tv| >U|T | >U|T Q | >U|T Q ] .@L "Pa s o  NY?UvT1kK?UvT| ?UvT 7?UvT|| @UvT Q ] .:eBL"Pls rsol Nor Nd NY@UvT1Y@UvT2kKAUvT} 1AUvT kKOAUvT| mAUvT  AUvcAU|T~KAU|T}| AUvT Q | %BUvT Q | WBUvT Q ] .8CL'PcsHC YBUvT1kKBUvT|| *CUvT Q ]HCQ8C .FL-PnumsF P|P} tenP}i.j.s|D resP~G DDU}TsgDUsT}Q: 0 Us;E tmpP~ q~G DUvT|DUvTnDU~ EU~T| .U|T~QcEt YEU|T10 G EU| EU}EU}T1 EU}FU}T:.FUs LFUv $ &SlFU|T}s FU}^ FU|| FU|T Q ]FQF .B8IL*P .numsHI o N i.Dlen ..G N U|T}D@Hi.j.t XHU|YuHU|T1kKHU|Tv HU|T2QD HU|T3| HU|T | *IU|T Q ]HIQ8I i.nVKLi/PsjUnumlsfK ip.J resrPG JUv&JTvQ: ^JU}T Q R| | U}T JU}T1Q0[JU}TJU 0 | KU}T Q  HKU}T1Q ]fKQVK':N NL:&Pc:.si;.o< NHI L tC q~ LU~ 1LU~ ILU~t fLU}T8 | U~T Q BM tRP~G LU~0 LU~ LU~ MU}T8 | U~T Q jjMp`. ^ MU| MU~| MU~T Q | MU0T ] .2;QLP9 ud tn$.Dn% o1 Nc5sEOresss[NUvT OU| | UvT Q Oc)s[xOUvTOUs [ OUvT  | UvT Q  (PUvT2Q  KPUvT1QD hPUvT1[PUv\PUvQ} PUvT R0| PUvT Q | -QUvT Q ] .RL"Pbs c .[QUvTQUs| RUvT Q ]#.SL#PhRUvT0Q0 RUvT>RUvT1Q  RUvTLRUvT1Q  SUvT0>SUvT1Q  \SUvT8SUvT1Q  SUvTpSUvT1Q ].Tns(  9TUp QTUp s  TU0T  TU0T ].Uns*0U( U8 TUU0T  xUU0T ]#.hVL!Pdsn# YUUvT1_WVU| (VUv| ZVUvT Q ]#.JWL PdsZW YVUvT1_WVU| WUv| .?: ;9 'I<4:!; 9 IB4:!;9 I .?:!; 9 'I@z : ; 9! 4:!;9 IB 'I! :!;!I8 "H}#.:!; 9! 'I@z$7I%4: ; 9 I?<&: ;!#9!I'.?:!;9 'I@z(4:!; 9 IB)1B*:!; 9!I+% ,$ > - . : ; /<0 : ; 9 14: ; 9 I?<24: ; 9 I34I441RB UX Y W 5.?: ; 9 'I 46.?<n76nnUnoUJKUKLVLLULMVKKPKLSLLSLLPLMSKKp.5LLp.5KK]LL]LM]KKPKK\LL\LMPMM\UVUVPSPS U !V!!U!"V P !\!!P!"\ P !]!"P""]!!P!!S""P""SUVUVPSSPSP\\P\\'(U((V((U(*V((P((S()S))S))P))S((P((\()\))P))\)*\))P))S)*P**S**U*+V++U+,V**P*+S++S,,S,,P,,S*+P++\+,\,,P,,\,,\++P+,S,,P,,S--U-.V..U.0V--P-.S..S//S//P//S--P-.]./]//P/0]--P-.\./\//P//\/0\..P./S/0P00S00U01V11U14V00P01S12S22P23S00P01\12\22P24\11P11]11P12]33P34]22P22S33P33S33P33S34P44SMMUMNVNNUNPVMMPMN]NO]OOPOP]MNPNNSNOSOOPOOSOPSNNPNN\NO\OOPOP\PPUPQVQQUQSVPPPPQ\QR\RRPRR\SS\PPPPQSQRSRRPRRSRSSQQPQR]SS]QQPQQ\RSPSS\UVUVPSSPSP\\P\P]]SSUSTVTTUTUVSSPSTSTTSTTPTUSTTPTT\TUPUU\UVU VP]]P ]PSSP SP\\P \P^^ P ^;;U;<V<<U<>V;;P;<S<=S==P=>S;<P<<P<<P<<P<=\=>\>>P>>\==P==]>>P>>];<P<<P<<P<<\>>P>>\ U V U V P S SCCUCDVDDUDDVCCPCD\DDPDD\CCPCDSDDS"#U#$V$$U$$V$%U%'V''U##P#$\%&\&&P&'\##P#%S%&S&&S&'P''S##P#%^%&^&&P&&^''^##P#%]%&]&&P&&]'']$$|$$V$$}$$\%%\UUUUWVWWUWYVUUPUV\WX\XXPXY\UUPUWSWXSXXPXYSVVPVW]WX]XYPYY]VV}VV^VV~VW\WW\YZUZZVZ[U[[V[\U\]V]]UZZPZ[][\]\\P\]]ZZPZ[\[\\\]P]]\ZZPZ[S[\S\\P\\S]]SZ[V[\V\\}[[\\\~66U67V77U77V66P67\77P77\66P67]77P77]77P88U88V89U99V88P88\99P99\88P89]99P99]88P99U9:V::U:;V9:P::\::P:;\::P::]:;P;;]::P/U/UU}U/T/RVRTVTVTVTVT/Q/SQSQSQSzPRVV}_\~ggUgh\hhUhi\ggPghVhiViiPiiVggPghSiiPiiSiiShhVhh q8$8&hhVhhq8$8&8$q8$8&!hhVhh!s8$8&8$s#8$8&!@$r!hhVllUlmVmmUmmVllPll\mmPmm\llPlm\mm\ijUjkVkkUklVjjPjj]kkPkk]jjPjj\kkPkk\jjPjk^kl^jjPjk]kl]jjPjk\klPll\mmUmnVnnUnnVmmPmn\nnPnn\??U?C|??P?@^AA^BCPCC^@@0@@V@@v@@V@@1@@0AAVAASABsBBSBBPBBpBBP@@0BB0BBTBBtBBT@@P@A]AAPAB]CC]BBUbbUbd\ddUdg\ccPcc]dd]de]fg]ccPccVddVdeVffVfgPggVccPcdSdfSffTffSggSccaddadddeaffacc1dd1ddPde1cc5.dd5.de5.eePefTdd0ddVddvddVddQddqddQddU U ] U ] P \ \P\ P _ P__ 0 S s S]]U]^^^_U_`^``U`a^aaUab^bbU]]T]_V__T_aVaaTaaVaaTabV^^p^^Q^^p^^P^^s__0__P__p__P``p``Q``p``P``s^^P^_\``P``\aaPaa\aaPaa\bbPbb\bbPbb\^_0__pr__TDEUEFVFFUFIVEEPEESFFPGGSFFp.5GGp.5GHp.5GGPGG]HH]HHPHI]GGPGG\GGTHIPII\EEPEE\GG\EESFFPFGSHHPHHS U V U V P S P S 0 P p PUVUVUSUSppUSU S 844U45V55U55V44P45\55P55\55U56V66U66V55P56\66P66\UUUUUUUVUVPSPSIIUIJUJJUJJHJJUIITIJSJJTJJSIIPIJ\JJPJJ\JJ\UVUVT]T]TPP\P\\P]P]PP\P\P\UVUVP\P\\UUUUUUTVTTVTVQSQQSQS0\|\0\|\,79Nz   ###$%%$$%%111233223334;<<<>>??@@ABBBBBEEGHFFFGHHHHPQRSQRSSVWWWZ[\\]^bb^^^^`abbeeefu 8 /  JJ f .tJJ ق  +w%t>< XJgI &}Y&-=&-JY===== ~gWX==Q 0X P.</g  t.uX.Y  .4fu @ F > HXX  txY  .Jtt tw rKg v  t%* X<Y tJ<%<)<tY 7.y%f X<(Y (U2}fg2s X=   ; u <Y t  < gJ<g  Yt.JkJ.<X~t t tYWK Y sK \ot tYWKZ HL>Y Vv fn 7~"   <Y<Y gI1J1J:LJ,  Xt ztu o<Y gI0J0J:LJ, "t g"s X=Ytqf ;Y J ! Y <Y Y zt.tf ZV Y W=/JXYtf JXYt2% Y%W X<Y G.w$~ g$W X<  $ Y a o q..$%. g%W X< Yt 1J .u }..'~. g'W / X<   A XnYwZ. K  V hJ$ ...w׭fc....%. g%W X<Y Y <!< ..zt..Y .%}. g%W / X<   <ZVht<X.JiXQ $X.k ;Yt!e ..Y ..Q%f g%W X< t 6.y Y vt...%d. g%W X< t 6.y Y vt...%c. g%W X<  t& 6..y K vt....%U. g%W X<  gt%uY ...mf!   h..! Yft. .t$z g$W X<Y$<Z..x#vf g#W X<Y!.+.w"f g"W X<Y Z ..yX..z!o g!W X<Y Z <<.Y..y..z!o g!W X<Y Z ..yX..z" g"W X< gYw< X  mXY t <t  i. x...0}.g0W uX"<L\],pYʃ/ h:Y %  %Q <KlXX Ƀ)`2 fw<Y t A 7] 7J8M w  =>= 8 =;=  J= = z"OJ<&g&WX<Y (Y .b.(!|j!YZeX<) el!X W rZh  ZdJ <J[  eY )ef < Y u...$~.Y Y W=;/Yt.bYwXt t%g%W X <!X   Q yfOZ X<YW2Y d[ yY axY  o. . "~. g"W X<   Y Jzt  w q..."a g"W X<   Y x %  v .. .%"V. g"W X<Yy Y YJ xt q.."~ g"W/ X<  <tJ.tf.JM Y Jl t! f..Y .Y|"R  g"W/ X<  JX$XS!y ...1}XJX " <XttK=V< yXJJ/<X.J,X31f%J<)<JfK  h  JP  <XttK=V<yYX= g.t w.q."-". Y =X"<  =Y Wi  g<f  [J fG0 X KY  uK;? <9= I == .m\Z:h. e= 1%X).%J).IJ. tM t.  !J- JJ=ItJ JJ J[=o "z.%%. g%W X< & K-=XJ</XJ</XJ</X<uJ&u.. %\. g%W X< =Y=Y * Y...uJ..*.% g%W X<Y  =Y.a.y*f g*W X<Y..wf/<<$f%stdout_poszenroom_tOCT_joctetBIG_384_29gp_offsetbig_modpowerbig_methodsluaL_testudataBIG_384_29_modmullerrorlua_tobooleanBIG_384_29_randomnumbig_initbig_jacobibig_modmulpush_octet_to_hex_stringunsigned intlua_gettopBIG_384_29_jacobiBIG_384_29_rcopyn_argsluabig_to_octetzero__int32_tBIG_384_29_pmulBIG_384_29_addstderr_lenBIG_384_29_dscopybig_dupo_argbig_shiftrocteterrorfuncBIG_384_29_sqrmodulusbig_modsqrbig_destroybig_paritybig_lteBIG_384_29_daddBIG_384_29_dnbitsdoublesizestdout_fullint_nBIG_384_29_paritylua_tolstringbig_classstderr_bufuint32_tstrcpysprintf_tPAIR_BLS381_G1mulfloatzstd_czstd_dluaL_RegBIG_384_29_invmodpbig_modsnprintf_tdividendMConst_BLS381warningoverflow_arg_areaECP_BLS381GNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionbig_divdebuglevel__destlua_getfieldbig_montylua_Statelua_createtablesize_tdbig_initBIG_384_29_iszilchBIG_384_29_sdivCURVE_Order_BLS381newbigerrorlevelbig_to_intbig_modnegBIG_384_29_zerostderr_posbig_to_hexuserdatarandom_externalBIG_384_29_modnegBIG_384_29_decBIG_384_29_dzerobig_modsubvsprintfBIG_384_29_normcharBIG_384_29_dsubvsnprintf_tlua_CFunctionsafenumlua_settopFP_BLS381BIG_384_29_dnormlua_setmetatableo_newvsprintf_tbig_concatbig_addbitspool_ptrpadded_octlong long intborrowlua_biginfocsprngbig_ltbig_to_decimal_stringlua_bigmaxdvalbig_modrandlua_NumberBIG_384_29_shrsnprintfsizelua_pushintegerBIG_384_29_dshltotlenBIG_384_29_dshrbig_endianint_lenlua_setfieldpoollua_pushstringbig_from_decimal_stringluaL_argerrorBIG_384_29_modBIG_384_29_montybig_mulsprintfBIG_384_29_dmodbig_eqbig_bytesstderr_fullbig_arg_compare_bigsshort intbig_moddivlong intbig_randomBIG_384_29_ddivBIG_384_29_moddiv__stack_chk_failBIG_384_29_dcopyBIG_384_29_diszilchBIG_384_29_fshl__va_list_tagBIG_384_29_fshrlua_newuserdataBIG_384_29_complua_tointegerxfp_offsetbig_sqrnamebig_bitsBIG_384_29_dcompstdout_lenBIG_384_29_nbitsBIG_384_29_subzen_memory_alloclong unsigned intreg_save_areaint32_tten_powerchunksize_bitsizeunsigned char__uint32_tnew_octet_from_bigstdout_buf__srcbig_to_fixed_octetDBIG_384_29zen_add_classluaopen_bigrandom_generatorrandom_seed_octet_to_bigzen_memory_freesigned charlua_Integershort unsigned intsafenOCT_copy__func__powerxdoubleBIG_384_29_inchalflenlua_pushbooleanbig_newbig_modinvrndptrvsnprintfBIG_384_29_copyecp_dupBIG_384_29_modsqrbig_sub/home/alby/dev/Zenroom/meson../src/zen_big.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include../lib/lua53/srcmilagro-crypto-c/include../src/zen_big.czen_big.cstring_fortified.htypes.hstddef.hstdint-intn.hstdint-uintn.hlua.hlauxlib.hzenroom.hamcl.hbig_384_29.hfp_BLS381.hzen_big.hecp_BLS381.hzen_ecp.hzen_octet.hpair_BLS381.hlua_functions.hzen_memory.hzen_error.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx @BAD J  AABD D  AABH `EK  FA (FFG0 DBE bH o I X E EG D AG (EDD0Y FAC ( EDD0W FAE LLnFIB E(A0A8D 8A0A(B BBBD EG d AG 0FAD G0~  DABI 0FLA G0|  DBBB ((EID0Y CAA (TEID0K FAD 8RFGA D(D@ (A ABBB 0FFD D0m  AABK LFGB B(A0D8G& 8F0A(B BBBF 8@FGA D(D@x (F ABBG L|FGB B(A0D8G 8F0A(B BBBF 8BFGA D(Dpu (A ABBG 8BFGA D(Dpu (A ABBG @DFGB A(D0Dp 0A(A BBBJ @FGB A(D0D 0A(A BBBD (FFG0L FBI (FFG0C FBB 0$FGA G0d  FBBE 0XFGA G0a  FBBH 0FGA G0d  FBBE 8FGA D(D@ (A ABBA LFGB B(A0A8G  8F0A(B BBBD 0LFFD D0e  FABF 82FNA D(D@s (D ABBG (FAG@N DBF 8BFGA D(D@ (D ABBH 8$ZFGA D(G (A ABBG 8`FGA D(G (A ABBF 0FFD D0c  AABE @3FGB A(D0G 0A(A BBBF 8FGA D(G (F ABBE DPFEB A(D0D 0D(A BBBJ @BFBB D(A0DP 0D(A BBBF 02FIA D0  FABD 8 :FGB A(G@ (F BBBD (L FFG0W FBF (x FFG0| FBI  Kr A  %1<H G@R8 ]nu   R    0p P ` B"P .0B9@ EP0 \ g  s }  0 !( $p"2+6B`%BM Y&Zam(u)*3,P1B32 4:  6p *6:`   EKQW0]4c;iCoLuW{c`o `Hx8 h #)8/h5;AGM8S Yh_ek q "/@bI[l}@'7`EUep m| $7GWfu$0AQap. @7 zen_big.c_compare_bigslua_biginfo__func__.37lua_bigmax__func__.4big_random__func__.3big_from_decimal_string__func__.1__func__.36big_parity__func__.30big_monty__func__.29big_jacobi__func__.28big_modpower__func__.27big_modinv__func__.26big_modsub__func__.25big_modneg__func__.24big_modsqr__func__.23big_moddiv__func__.22big_modmul__func__.21big_bytes__func__.18big_bits__func__.17big_lte__func__.15big_lt__func__.14big_eq__func__.13big_mul__func__.10big_to_decimal_string__func__.7big_modrand__func__.2newbig__func__.0__func__.35big_shiftr__func__.32big_div__func__.12big_mod__func__.11big_sqr__func__.20big_sub__func__.9big_add__func__.8__func__.33big_to_fixed_octet__func__.31big_to_int__func__.19big_concat__func__.16big_to_hex__func__.6luabig_to_octet__func__.5.LC49.LC48.LC50.LC51.LC52.LC53.LC54.LC55.LC56.LC58.LC57.LC60.LC59.LC61.LC63.LC64.LC62.LC66.LC65.LC67.LC69.LC68.LC70.LC71.LC72.LC74.LC73.LC75.LC76.LC77.LC78.LC79.LC80.LC81.LC82.LC83.LC84.LC85.LC86.LC87.LC88.LC89.LC90.LC91.LC92.LC94.LC93.LC96.LC95.LC99BIG_384_29_dnormBIG_384_29_dcompBIG_384_29_normBIG_384_29_complerrorBIG_384_29_dscopy__stack_chk_faillua_createtablelua_pushintegerlua_setfieldbig_newlua_newuserdatalua_getfieldlua_setmetatable_bitsizeBIG_384_29_dnbitsBIG_384_29_nbitszen_memory_allocfunc_GLOBAL_OFFSET_TABLE_ZCURVE_Order_BLS381BIG_384_29_randomnumlua_tolstringBIG_384_29_zeroBIG_384_29_incBIG_384_29_copyBIG_384_29_pmulluaL_argerrordbig_initzen_memory_free_octet_to_bigBIG_384_29_dshlBIG_384_29_fshlbig_argluaL_testudatao_arglua_settopbig_destroywarningBIG_384_29_paritylua_pushbooleanMConst_BLS381BIG_384_29_montyBIG_384_29_jacobiBIG_384_29_modmulBIG_384_29_decBIG_384_29_shrBIG_384_29_invmodpBIG_384_29_dsubBIG_384_29_dmodBIG_384_29_subBIG_384_29_modBIG_384_29_modnegBIG_384_29_modsqrBIG_384_29_moddivecp_dupPAIR_BLS381_G1mullua_pushstringBIG_384_29_dzeroBIG_384_29_ddivBIG_384_29_iszilchlua_tointegerxbig_dupBIG_384_29_dcopyBIG_384_29_rcopyBIG_384_29_dshrBIG_384_29_sdivBIG_384_29_sqrBIG_384_29_daddBIG_384_29_addnew_octet_from_bigBIG_384_29_diszilcho_newBIG_384_29_fshrlua_gettoplua_tobooleanOCT_copyOCT_joctetpush_octet_to_hex_stringluaopen_bigzen_add_classckvV .W8`sXxYZ&[3@G\Tah]u^_sNz`/a6lb#ND*c4;^iu**N4c%._tN deN c#f0:g%;hBQ i  % F j y _  j  k   / < K lU c N j ct {    m   n  C T e  N c     # 3 *G s o}  p  N c  N c  N c  5 N m qw    N c  N c  AZs"-r}N|cN|cN|cN| cWl|NlcNlc #Nl*c4>GYiN\c$3N\:cDLcN\jctN\c CrMNLcNLcNL cWpsN<c$3N<:cDSN<ZcdntKSg|N,cN,cN,cN,cIbu_u,5KNRc\kNrc|*NcNc DTgNcNc$+VkNcNc&;^NcNc 1[Nbcl{NcvCwMa*NcxNc$3N:cDSNZcdn   * : B N ] {     !!!x!N|!c!!!!!!*"+"N$2"c<"K"N$R"c\"c"y"_""""*"#7#yJ#^#g######N#c#$z $(${2$C$NJ$cT$c$Nj$ct$$N$c$$$$$%'%3%N:%cD%P%%%%%%)&<&K&|U&c&Nj&ct&&N&c&&&&'7's'''}''N'c''N'c''N'c'(:(S(~((((())~)3)N:)cD)S)NZ)cd)s)Nz)c))N)c)))) **C*M*[*Nb*cl*{*N*c*****.+F+d+o+++++++,,*,,3,N:,cD,S,NZ,cd,l,,N,c,,,*,, -&-:-`-h-------.+.;.NB.cL.[.Nb.cl.{.N.c..... /P// 000h000N0c000 1N1c1(1N/1c91C1t1111223S3]3s3Nz3c33334?4I4S4{444N4c44N4c445!585H5S5c5r5555N5c55N5c55N6c 66D6W6g6r66Nl6c6666#7N\*7c47;7N77777p"6 (0(8@+H,P/X*`3hp7x(;&?)CH N U\0cjPq! y(@080@H PX `h px`%6 6,* ((08&@HPX`h0px4CH 33 ?)N U\0c j(P080@HPX `h px   6P1"`% P T U U* S8 Ty? TF T M TT T[ Tw b T6g T(x T TK T T T T+ T T T T T TM T T T % T 1 Te Tr T& T T T T] T Tr* Tn T{ T T TE T T TB TQ Ty T T<  TM  T T$ TH1 T> TK T$X Te T  T  T  T T T  TE TQ T r T  T@ T T& T T T- T.c Tw T  TR T* T T| T8 TT To T T2 TB T Tg T#  T/ T_L Td T | T To T+  T T Ta$ TA T^ T4z T T T T] T  T2 T6 TX T o T Tv T T T T"  T1 TH T _ T u TY TJ Tl T T\ Tp T T. TPE T\ Tt Tg T T T5 Tv T TN& T[B Tb T} To TB T Ti T0 @7 Q Q  T8# TB3 7H  ` 7 T| `% Q* Q" QT QJ T N Q|  Qx T Q Q, Q0 Q5%R%u%%%-&@&Y&8x&o*N4&Oo\Nf& T  Q Q Q Q  T NG X i ( CoPNZ h T r0 Q6 Q. Q^ QV T Np Q Q{ Q Q[p6N[voNpoNp8oNp B T! A QE QS QW Q\ T fNx Q'| Q9 R { x   o-N7 Ro_Niw T^ QZ QR Q Qz T NP Q Q Q Q $;QV`yoNPo(NP2MoZNPd"r T|0 Q Q  QA Q5 T N@ Qx Ql Q Q[t6Q[t (oN@Ho#N@-hHoUN@_rm T@w Q Q Q Q T N0 Q1 Q' Qa QU Q Q *GdOWkoN0)DoQN0[voN0oN0 T  Q Q  Q  Q T N . Q2 Q@ QAD Q5I R{y Qt} Ql8   o-N 8 Rh Ql Qq09o"N -MJfgc`oN oN  T &- Q1 Q? QC QH T RNd Qh Q v QMz QCh'w''&& ');'6'Qh['voN'oN(oN ( T(> QyB QqP QT QY T cNu Qy Q~ R Q  Q((() ) o- N8 RJ Q+N Q#S (q (~ ) o N >( W( !)! !H)'!o4!N>!h)Y!of!Np!)~! T! ! QP! QH! Qz! Qp! T !N! Q! Q! Q! Q! " 4" L"' d"K q" "H" "" "o"N" #o#N# :#oG#NQ# t# T~#)# Q# Q# Q# Q# T #N# QF# Q>#)#*$*+$*8$Q*S$]$p*x$o$N$*$o$N$*$ T5$$ Qk$ Qc % Q% Q% T %N0% Q4% QB% QF% QK% T f% Q j% Q o% T % T#% RU%v%%&&E9&^V&ws&&&&&&&'0'H'&e'1''o'N''o'N'(o(N(4(oA(NK("n( Tx(( QK ( QC ( Qu ( Qk ( T (N( Q ( Q ( Q ( Q ( Q ( Q ( R) Q ) Q #) Q# ') Q ,)D)\)Qw)h)()o)N))))e*,*D*Q*^*y*o*N***H*o*N*h+o+N+r'+ TT1+@Q+ QH U+ Q@ e+ Qn i+ Qh n+ T x+N8+b+m+++o+N8++ T,!(, Q ,, Q 1, T<, Q @, Q E, T O,N(c, Q g, Q l,!,!,!,",@",o,N(,`"-o -N(*-g"M- TW-Pw- Q {- Q - Q@ - Q6 - T -N`- Qp - Qd - Q - Q - Q - Q - R`- Q - Q . Q% . Q (. RpN.r...O.].m//#7/KR/u//////0,0D0Q0^0 k0(0o0N`0H0o0N`0P0x1o1N`141oA1N`K1Y1 T= c1*1 QF 1 Q> 1 Qp 1 Qf 1 T 1N1 Q 1 Q 1 Q 1 Q 1 R1 Q 1 Q 1 Q 1 Q "22+;2J+T2h+l2s+2+2+2+22,2,3,)3*F3*c3+{3+3+3,3,3!,3H,3o3N3h,4o!4N+4p,C4,^4ok4Nu4,4 T4,4 Q3 4 Q% 4 Qx 4 Qn 4 T 4N4 Q 4 Q 4 Q 4 Q 4 R5 Q5 Q%5 Q$)5 Q L5l-g5q5-5-5-5.5/.5-6*-6>-56-M6-Z6-g6P.6o6N6p.6o6N6.6o6N6. 7 T7057 Q>97 Q6G7 QfK7 Q^P7 T Z7Nl7 Qp7 Q7 Q7 Q7Z7o7778o'8N18L8oY8Nc8q8 T{88 Q8 Q8 Q8 Q8 T 8N8 Q8 Q8 Q&8 Q$8* 9?)9UM9be99o9N99o9N99 T9: Q6: Q.(: Q^,: QV1: T ;:NM: QQ: Q{a: Qe: Qj:::%:5:p:o;N;-;o:;ND;R; T(\;|; Q; Q; Q; Q; QX; QH; Q; Q; R ; Q; Q; Q; Q <g"<o:<zX<dq<<<<<<<<<<|==0=0:=H= TSR=3r= Qv= Q= Q= Q= T =N= Q0= Q&= Qb= QT=3=3>4>M4:>D>W4b>4}>>4>o>N>4>o>N>4> T? 6#? Q'? Q5? Q9? Q>? T H?NpZ? Q(^? Q"c?H6?[6?k6?v6?6?o@Np @6@ T}$@4D@ QFH@ Q>V@ QnZ@ Qf_@ T i@N{@ Q@ Q@ Q@ Q@ Q@ Q@ Q@ Q@ 5@%5@<5AL52AW5PAg5nAv5A5A5A5AoANA5BoBN&B6ABoNBNXB6fB TpB6B QB Q B Q=B Q5B T BN`B6B6B87Co!CN`+C?7NC TXCxC Q^|C QZC QyC QoC T CNC T-C TC QC QC Q&C QD QX D QND R'D. ED> hDF }D RD TD D D D !E!lK TwK.K QK QK QYK QIK QK QK Q;K Q#K T KNK RL.L/2L /JLT/gL=1~LoLNL RL0L0L#0Ll0M 1+Mo8MNCM~/aM QeM QkM.xM/M0M0MoMNM1M8MG1 N TANp"6N Q:N Q?N T INN\N Q`N Q|N QN QN Q7N Q-N QeN Q[N RN QN QN TN QN QN"N" O"O#.Oo;ONFO RXO Q\O QaON#yOb#Ok#O#O$OOX$OoONO"Pc)P"#LP#iP#P#P6$PPx$PoPNP$Qo$QN.Q$R QQBR QIGRiRRR4R#R7R;RDSX5SC?Se]Sy}SLSSSWSS TS@T Qy T QqT T-T QT Q"T:TRT_TlT)T TFTTUT TTT QT QTf U T-U QU QUp1U:KUUUoUyUU T U U QU QU QU Q U T UNUHUXVk)VDVoQVN[ViV T+rVV Q9V Q1V QaV QYV T VNVVV W(&Wo3WN=W/`W TjWW QW Q~W TWWWW TW W QW QW T X T X QX QX 3X @X [XeX rX XX X TnX$X QX Q X QHX Q@X T XNY QrY Qh Y$Y$1Y$>Y%KY+%XYH%tYoYNYT%Y T Yp Y QY QY QY QY QY QY Q1Y Q)Y T ZNZ R?#Z QT'Z QN,Z CZ`NZ RJ_Z QrcZ QjhZ Z3 Z@ Zx ZoZNZ [c[ =[G[ e[Y [[ [ T [[ Q[ Q[ Q[ Q[ T [N[[ R$ \ Q\ Q\ Q\ Q"\@\d\cn\\\`\N\\ TY \`\ Q\ Q] QC ] Q5] Q] Qx,] Q0] Q5]M]Z]q] ]] ]) ]J ]n ] TV] T] T^ T^ T O^ O" U.& UK* UR. Uu2 U6 U@ UE UJ UO UT UY U ^ Uc U h U/m U5r U?w UI| UP U] Ui Us U U U U U U d$@P@`p , X   D0P 0H  (0\P!p"$`%(&d()*,T.P13 4P  6| 6 @7.symtab.strtab.shstrtab.rela.text.rela.data.bss.rodata.str1.1.rodata.str1.8.rodata.rodata.cst4.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @7@A+ 8 &@(] 1;62;(E2>TD \0Fn8F^i@h zLc @ 0@0=&y@00E 00&  @8 X, 8(/294 0 0 0 644 24800 ` ELF>Y@@HdH%(HD$1H7HWHwHODG HD$dH+%(uHff.HHE1AdH%(HD$1fH9s!ty< t7< t3HA@H9rD DBHD$dH+%(u5HfDDDtH@AE1AHfUH5HSHH_HWdH%(HD$1H9HH w #> HpHHHH HHH$HE8HEHH$H](HPHEHU0XD< R< JHH9u@HE81'@^t|uNH](H]0HHM8H]HT$dH+%(H[]f.HH9뙐_ Ѐ:u ȃ߃A<wHu} EXHuPf.HuPHHcHcɈH4;у߃AvJЀ _ADuy*;E |Hu0HHE8H](HuHEP8HD;HE0HE8H](HuH@AWAVAUATUSHxdH%(H$h1H/HHIE11H$hdH+%(HxD[]A\A]A^A_DHHHL$`AILHHL-L5HHL$8HHtuHL|$PLLLLH5LHuADte|$H>fDH,tRH=t\HH511E1DfHD$HH511DH5Lt%H5LuZsaE1LH11H5E1fDty&H5Lt)H5LHHH511E1+L=H5LAoGH)AoO)JAoW$)R Ao_4)Z0AogD)b@AooT)jPAowd)r`AoGtƂ)BpH5Lu{HLH511E1PH511E18H51@1E1LH511E1%s: error parsing configuration: %sInvalid length of random seed: %u (must be %u)Invalid rngseed data prefix (must be hex:)%s: Invalid string in configuration: %cdebugverbosecolorrngseedprinthex:stbsysmuttInvalid print function: %sInvalid configuration: %sInvalid integer configurationUndefined config variablezen_conf_parse) :*vvv}}+},int-;< ,.=8=VVA>gl.VC luaD}E}F}HI . J .(K .0M8N .@O .HP .PR}XS`TVWX}Z [ \ ,][:?_7.v LW JE SYSv STB  "`hk eofl m n o r (s 0v 8w @x Hy PzX{%}vA     vRl NIL    R7A!Sl :"U "V  &3 x . t ($>/ .U uzu0XV 1ZZX 2X/#len\3lex^ z!_ {4 5#lenu 6j>UUT Q4(U0T (U0T R@>U| <UzT|R{X  TUs rUT} UT~ UT  Us( U0T Q /U0T  TUT  yUT (U0T Q R| UT  UT ( U0T  C UT (m U0T Q(U0T Q 7: : 8 L & p  9f$ nM R :B 6 *  % ]B 6 *  $@ ;q&P 4      % v B 6 *  UUsTPQ:& !  & D,   hz B 6 *  f f0 f< fKcurfX fiX xX"R R% HO H' H2 H?endHL'4 40 4C?I~ : ; 9 I8 I1BH} !I: ; 9 I$ >  :!;9 IB :!;9 I ( ( (H} :!;!I8 7I'II>! !I: ; 9 .:!;9! 'I !&I : ; 9! !I/ .?:! ; 9!'<.?: ; 9 'I<H}4:!;9 IB1RB UX!YW :!;9 I:!;!9!I : ; 9 I8 !4:!; 9 I"4:!; 9 I?#4:!; 9 IB$ %1RB UX!YW &1RB X!YW '.?:!;9!'@z(4:!;9!IB)% * : ; + ,$ > -&.</.?: ;9 'I<0.?: ; 9 'I@z1: ; 9 IB2: ; 9 IB34: ; 9 I44I45 U61RB UX Y W 7!I/8.?: ;9 'I@z9 : ;9 :1;4: ;9 I<: ;9 IB=.?: ; 9 'I 4>.?<n?6UVU V U VUVT\T \ T \T\PP PP   UVUVUUVUVSSu(S0UpRPUPU0S Vsu"1Pv0S VPPS VpQS V p8$8& r8$8&USu( r8$8&UPwUwUPTTPQQtwRRRrRr~tw1YYt0XX0DUDEUDTDETDQDEQDRDERDXDEX,d   u   =KKKK  >;d XK IKJyJ X=K vJ+< \JG K ~ .X Xqt JqJ3 ~t<X  @! L!|X  J |J RK *WJJ |XWJt'2<2I  ~ " }J}XKGKK }I -<.<= L"MHs K$h: wJ$?$9!<=uVu v<Y }KJ}XKK  XJ K }X}KKtXX>zJ/ << Y>X1. u urt= t X[X.6A slfY:gjh .F6A**< X#*gMK-J5A08Eif   fX K  0=+8   ; VX< (R tJX   1J>  /  ; gX x 4^X0 CLEX_eofdebuglevelsuffixessize_tlexerchar_offsetwherewhere_lastcharstringgp_offsetstring_lenstb__clex_token__src__func__stb__clex_eofzconflong long intsigned charlong intCLEX_intlitzconf_printfmemcpyset_colorinput_streamsprintfprintftypeline_offsetstderr_bufVERBOSEzenroom_tinput_stream_endunsigned intstdout_posstrlenrandom_generatoroverflow_arg_arealong unsigned intstderr_lenvsprintf_treal_numbershort unsigned intcurconfGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionconfigurationstrtolCLEX_first_unused_tokenstartstderr_fullrandom_externalvsnprintf_tuserdatazen_conf_parseparse_pointRNGSEEDCLEX_id__destlua_Statestrncasecmpstb__clex_iswhitezstd_czstd_dfloatvsnprintferrortokenwarningstdout_bufsingle_charsprintf_tunsigned charstb_c_lexer_get_locationshort intCOLORstb_c_lexer_get_tokentokenid__lenlexbufstb_lexerreg_save_area__stack_chk_failLIBCstdout_lenstring_storestore_lengthcharstrcasecmpint_numberrandom_seedstdout_fullvsprintfstring_storageMUTTsnprintfline_numbererrorlevelwhere_firstcharsnprintf_tfp_offsetstring_storage_lenstb__clex_parse_suffixesstb_lex_locationstderr_posstb_c_lexer_initCLEX_parse_errordoublePRINTF__va_list_tagzconf_rngseed/home/alby/dev/Zenroom/meson../src/zen_config.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include../lib/lua53/src/usr/include../src/zen_config.cstb_c_lexer.hzen_config.cstring_fortified.hstddef.hzenroom.hlua.hzen_config.hzen_error.hstrings.hstring.hstdlib.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx EH w A 8H i G (TLEKD0/ AAK HVFBB B(A0A8GP 8D0A(B BBBF ` `  +05:@FKPU'Z+`if"k/qOwX|(4EPLPV $.4<Izen_config.cCSWTCH.13curconf__func__.0.LC1.LC2.LC3.LC16.LC15.LC4.LC5.LC0.LC9.LC10.LC14.LC7.LC11.LC13.LC8.LC6.LC12stb_c_lexer_init__stack_chk_failstb_c_lexer_get_locationstb_c_lexer_get_tokenstrtolzen_conf_parsestrlen_GLOBAL_OFFSET_TABLE_zconf_rngseedstrcasecmpset_colorerrorwarningzconf_printfstrncasecmpA## &H#("**|%T+g+v~+|%, \- |2|BQZ.ks+~+|| \-++)*/;*/MV-_|p(0**+*/(1-:|JS-h z-#!-   * / = B \N RX b ql y A      O   - \  G N y * N v   ! " `/ j< I  V c p }   [ &   U   % . H U b o | < k  _ K \ N     % =, 3 : T Z ` f Um y  j* / q  ) T) e? YV  P    k [    } ` R! % .7 ]G K T X a e kt"WX~(=UXsk ` ^&0wKUpz ` '+Z i  : /D 5^ On {  4   $  X P  ' E I vR [ <p t }      G       * (    4# 2, E0 A9 W= UF aJ _S nW l` i u zy v        < <    # ' 1 : 1J N W [ d h q u { L  $    5  $ g $+ k7 P V Pm $x |  6   5 1 R F    *    , $" & + 6 : ? 0J N S 5^ b g Br v {E   w   *;  " 1& N* U. x2 6 @ E J O T Y  ^ c h %m 2r >w H| QP` <PXP.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.8.rodata.str1.1.rodata.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@p5&, 12@2O` o \ W@p;h{]v@U0 w 0@(V0  h!@XV0'x0-Z0p.&..  .@hX`/" 4UX/317 0 0 0 644 60632 ` ELF>@@HdH%(HD$1HD$dH+%(u1Hff.AUATUHSHdH%(HD$1HHL%HAT$AŅAD$HHpAT$HHDž~%1HcHsHc4HO@4AT$H9|HGHcAt$H769}HT$dH+%(H[]A\A]fDHD$dH+%(HHH51[]A\A]fHH5H1 HHAD$H~1fDAHKDH HcHV AD$HD9HVHAD$HDAWAVAUATUHSH(dH%(HD$1IHHIHHH111H5E1H5H1HT$HD$f*D$D,E94$t/HH511A$DHH51HILLLDP@x<HHD$dH+%(@H([]A\A]A^A_1H@HHHHHIHHHHHH5H1HH511D$ H5H1D$ HH5H1HH5H1HH5H1,ff.AVAUATUHH(dH%(HD$1IHHHIHOHH11E1H5H5H1E1HLLL@P0x7HHD$dH+%( H(]A\A]A^D1H@HHHHHIHHIHCHD$HH1H5LD$HH5H1HH5H1HH5H1\ff.ATUHHdH%(HD$1IHtPHLPu/HHD$dH+%(uzD Clua Dq Eq Fq H I z  J z( K z0 M8 N z@ O zH P zP RqX S` T V W Xq Z P [ v \  ] ) .? _  $ 8 V  #  &( '$0 (`8 )$@ *H +L ,P -` .p / xD8)V='[$[[) 050  len  val      "((big #q)ZJ)*Le  ? 5 -KK &Kf?R]K +?D?2?R?[$j?D?D? ??D ?,  ?!* * * H A A e.f ?DAq ?D-5 L?E }Z |/ U  ' U T}Q| - qE . 5 qZ . J .  /L"? 0oK .  L)? k in iv h out t2  UvT1 UvT2 UvT3 UvT4 Uv UvT@@ U|T}QR~XsRX Uv} UvT  UvT Q  UvT Q  UvT Q E UvT Q w UvT Q  UvT Q  - . L)? k in iv h out t UvT1UvT2UvT3UvT4Uv+UvT@f[U|T}QR~XsRsUvUvT UvT Q UvT Q .UvT Q `UvT Q UvT Q UvT Q  -|L|.?pk  m r s n resUvT1UvT2UvT3R UsT Q EUvT 2iUvT4QRU0T Q RUvT R~U~T}Q|RXsUvT1+UvT0jUUvT3Q jUvT3Q UvT UvT UvT Q RU0T Q CUvT uUvT Q UvT Q UvT Q  -  . `&L`'?pkc 6 md re sf orespUvT1UvT2 UvT3R;U~T Q `UvT U@T|Q}R~UvT1UvT0jUvT3Q jUvT3Q 2UvT PUvT UvT Q UvT Q UvT Q UvT Q  - 6 . &*L*,?sk+  m, 23 n4 Er> s@ 'UvT0Q2EUvT|pUvT Q UvT|UvT Q U|Q0R}XsY~UvT Q UvT Q kE rH sJ UvT4UvT0Q2UvT| UvT Q *UvT|UUvT Q U|T0Q~R}XsYUvT Q UvT Q UvT Q 6UvT1SUvT22wUvT3QRU0T Q RUvT R|UvT4UvR9U0T Q ^UvT UvT Q UvT Q  -  . m"L%?sk }" m  r s UvT0Q2UvT@UvT Q UvT@DUvT Q oU@Q0R|XsY}UvT Q UvT Q !k r s , UvT3N UvT0Q2l UvT@ UvT Q  UvT@ UvT Q !U@T0Q}R|XsY~C!UvT Q u!UvT Q UvT Q !UvT1!UvT2!UvT3-"UvT Q _"UvT Q  - }" . m"Ԇ#L#?pk $ resix 1fH#y Uve#UvT1y#Us#Uv2#UUT #UvT Q  - $ . #J'L$?f Z' s sk pk kdf ses $UvT1$UvT2 %U|%U}<%UvT Z%UvT@z%U}T|Q~%U T~Q0R X%UvTQ~%UvT2%U|&U0<&UvT Q~n&UvT Q &UvT Q &UvT Q~&U0&U}'UvTQ~)'U0<'U0 - Z' . J'`(L%?pk }" 'UvT1'U|(UvT1 (UvT0R(UvT Q  -)L#?sk $ tmp pk (UvT1)UvT|.)UvM)U0T|Q})UvT Q )UvT Q )UvT Q  -t+Lt#?pkw $ sky {*UvT0Q2*Uv*UvT Q *Uv+UvT Q +T|Q}M+UvT Q +UvT Q  -b4+Lb? -[A q,L[?n[!ud\qe^A f ^,UvT}Q F ,UvT}Q  -3_ - q 4 5_  j- q 67 P-Uv5--U| UvT Q -UvT Q  -8I~H}I : ; 9 I8 4:!;9 IB !IH}4:!; 9 IB : ; 9 I H} &I I !I/ 'I4I4.?: ; 9 'I<$ > .?: ; 9 '<:!; 9 IB : ; 9 I8 :!;9 IB.:!;9! 'I@zH} : ; 9! 4:!;9 I.:!; 9! 'I@z :!;!I8  U4:!;9!IB.?:!; 9 'I@z 1B!% " : ; # $$ > %<& : ; 9 ''(: ; 9 I)4: ; 9 I?<*4: ; 9 I?+.?: ;9 '<,.?: ;9 'I<-.?: ;9 'I@z..: ;9 'I /: ;9 I04: ;9 I1 2H}3.1@z44151RB UX YW 6 U741B8.?<n ..U./U!!U!#V##U#%V!!P!#\##P#%\!!P!#^#$P$%^""P"#]$$P$%]""P"#_$$_$%P%%_""P"#S$$S$$P$$S""P$$P$$Y$$%%U%'V''U')V%%P%'\'(P()\&&P&'^((P()^&&P&']((P()]&&P&'_()_))P))_&&P&'S((S()P))S''P((P((Y((UVUVP]]P]P\\P\0__0P_P_0SS0PS0SaaPP U V U V P \ \ P \ P ] ] P ] 0 ^ ^ 0 P ^ P ^ 0 X 0 P X  0 @ @ P PUVUVP]]P]PSSPSaaP^^P^P_P_P^^P^P__P_PPRUVUVP\\P\PSSPS@@P]]P]P^P^P]]P]P^^P^P_P_@jUjVUVUUVnwPwSSPS1120PpP0]QP]PUUPTUVU!VP]\PP] ] \ !]P\P\P \ P \ \ P !\00 0 !00]\P0] 0 ] \ 0!!0P__ P _P^P^ U V U V P \ \ P \))U)*V**U*+V)*P**\**P**\**P**\*+P++\**P**]++P++]UVUVP]P]P\P\3U34U--U--V--U-.V--T--]--T-.]--P--\--P-.\--\+,U,,V,,U,,U,-V,,U,,V,-V,,P,,\,-P--\,?,,,-?    & g&WX<   W= J=<J<< J   XLJfKY W/< J h < hJ  hJ.fXt(JX J<J!;XZJXK u1i1UX<  y5 xtD X XXg fv Q ..J~kf==.t Xq#...*C.i*UX<  xD  y < uQ...brf==x...(~.g(WX<YK.d.z/fg/WX<  ! IXY fZ ='t'X<s#t X#X)..c....(.g(WX<  !=!=% .o!=!=#t#<!..!.l..! ..&~.h&rYt$<<,Y='Y="t"f<g..,zX.'.'9. g'W X< <3 K<@ g Y.nt. 3 Y= . .v. g<<zXY Y X, h,V X<Ks<  J] %= vt  ..k... X%-..,B.h,VX<Ks<  J]% = vt  ..k... X%,..&}.g&WX<YYt$<<,[..y<..,.%.%s  t s X< Y ZXyu.t$|f g$s X=[t..U!/ < /jtXj<PztzZ=%curvestdout_poszenroom_tecdh_pubcheckgp_offsetlerrorecdh_dsa_verifybig_initunsigned intecdh_session__int32_tstderr_leno_argocteterrorfuncecdh_aead_encryptecdh_aead_decryptdoublesizestdout_fullECP__PUBLIC_KEY_VALIDATEstderr_bufuint32_tecdh_keygensprintf_tfloatzstd_czstd_dluaL_Regsnprintf_toverflow_arg_areaGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectiondebuglevellua_getfieldlua_Statelua_createtablesize_tecdh_classecdh_pubgenerrorlevelluaopen_ecdhstderr_posuserdatarandom_externalfieldsizevsprintfcharvsnprintf_tlua_CFunctionecdh_pub_xyordero_newvsprintf_tKDF2ECP__KEY_PAIR_GENERATEECDHpool_ptrECP__SP_DSA_NOHASHlong long intborrowecdh_argcsprngo_dupdvalecdh_dsa_verify_hashedlua_Numbersnprintfecdh_dsa_signecdh_addlua_setfieldBIG_384_29_fromBytesLenpoolluaL_argerrorsprintfAES_GCM_ENCRYPTECP__SVDP_DHAES_GCM_DECRYPTparitystderr_fullshort intecdh_methodslong inthash__stack_chk_failECP__VP_DSA__va_list_taglua_tointegerxfp_offsetnamestdout_lenecdhmax_sizelong unsigned intreg_save_areaint32_tluaL_checkudataecdh_initchunksizetypeunsigned char__uint32_tECP__ECIES_ENCRYPTstdout_bufECP__ECIES_DECRYPTzen_add_classorder_sizerandom_generatorecdh_orderrandom_seedecdh_destroylua_typeECP__SP_DSAsigned charlua_Integershort unsigned intecdh_dsa_sign_hashed__func__ECP__VP_DSA_NOHASHlua_pushbooleanbig_newrndptrvsnprintf/home/alby/dev/Zenroom/meson../src/zen_ecdh.c/home/alby/dev/Zenroom/meson../src/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits../lib/lua53/srcmilagro-crypto-c/include../lib/milagro-crypto-c/include../src/zen_ecdh.czen_ecdh.cstddef.htypes.hstdint-intn.hstdint-uintn.hlua.hlauxlib.hamcl.hzenroom.hzen_ecdh.hzen_big.hzen_octet.hbig_384_29.hpbc_support.hecdh_support.hzen_error.hlua_functions.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx 4H f A L8FGA D(D@ (A ABBG X (M ABBN HFGB B(A0D8D`' 8F0A(B BBBH 8FGB A(GP (F BBBF (FFG0O FBF d<FGB B(A0D8D`;hUpGhA`d 8F0A(B BBBK hIpDhA``FGB B(A0D8DPXO`QXAPX 8F0A(B BBBI mXg`DXAP8FIA D(D@ (F ABBE HDFGB B(A0D8DP 8A0A(B BBBA HFGB B(A0D8D` 8A0A(B BBBB HFGB B(A0D8D` 8A0A(B BBBB 8(FGA D(D@l (F ABBC 0dFAD D0d  AABI 0qFLA G0q  DBBE K A  @ $;GpWb`px{ `  ph P0) 4?    JPV\(bxhntPz$+H3Kcp4 )8HUertyqzen_ecdh.cecdh_pub_xy__func__.11ecdh_dsa_verify_hashed__func__.10ecdh_dsa_verify__func__.8ecdh_pubcheck__func__.6ecdh_dsa_sign_hashed__func__.9ecdh_dsa_sign__func__.7ecdh_keygen__func__.0ecdh_session__func__.5ecdh_aead_decrypt__func__.4ecdh_aead_encrypt__func__.3ecdh_pubgen__func__.1ecdh_order__func__.2.LC22.LC21.LC25.LC26.LC28.LC23.LC24.LC27.LC29.LC30.LC31.LC32.LC33.LC35.LC34.LC36.LC38.LC37.LC39.LC40.LC41.LC43.LC44ecdh_destroy__stack_chk_failo_arg_GLOBAL_OFFSET_TABLE_ECDHo_newlerrorlua_typelua_tointegerxlua_pushbooleanlua_getfieldlua_createtablelua_setfieldZKDF2AES_GCM_DECRYPTAES_GCM_ENCRYPTo_dupbig_newbig_initBIG_384_29_fromBytesLenecdh_argluaL_checkudataluaL_argerrorecdh_addluaopen_ecdhecdh_initzen_add_class0>g?z*AB6&SZ'dCwB> ?$?=DMZ(bEi)sCF(E*E*AG>GK+XH_,lHy??'C(E-C 'C#*'4CCJ'TC^>??D(E)C*A*G^Gk+xH,H??'C'C'$C3:'DCN>?*AGGt'C>+?D?bF(E*ED?IB+J B3,EJX*AzGIB+JB , J! *K: *AS Z (i Ep .z C  ' C  ' C  ' C  ' C# * '4 CC J 'T Cc j 't C~ > ? ? D ? I* B= +J JW Bj ,w J *A I B + J B( ,5 JF *K^ *As z ' C  ' C  ' C  ' C  ' C  '$ C3 : 'D CN > I *A B / J B 0 J *K#*'4CCJ'TC^>??*AdBBDLsdz'C?*A1Cd'Cd 'C#d*'7C>*AlCs*A>?2??&?@BYByM3E4CL'CL'CL'$C8LD'ICcLj'tCL'C>?5 ?$?F?`ByBN6E7C,'C,'$C3,:'DCX,d'iC,'C,'C>? O*A(Bc j'tC 'C 'C>*APQ&RSZ8dCsz'C>9T:U>=;Y*Ai*=sX<Y>CC`  (08@HPX`hpxp`` ` p!-;@ E(@0K8V $Q % %* #1 $6 $ZB $)L $wV $?` $m $Sv $/{ $: $ $ $ $ $m $ $ $ $ $  $  $m $ $  $J $+W $d $w $+ $& $ $4 $  $  $DE $Q $ w $4 $ $ $" $$/ $< $I $V $c $p $w} $p $  $S $o $ $ $X ${ $ $x $  $* $> $K $X $e $ r $' $ $N $ $ $ $8 $ $ $ $Hf $z $ $ $Q $ $A $K $6 $JQ $ g $ $ $ $ $* $3 $hS $k $ $ $ $3 $ $ $:0 $G $g $ $c  ! ! $A $" w A  ( ` $d} $  $  !* !" $ P !R !J !w !o& !* !8 !< !L !P !_ !c !h    * D ] }A Y t 3~   P   P (  P M/ < PF xa n Px   P  $  !D !< $ 0 !l  !d/ !3 !B !F !T !X !h ! l !z !7~ !/(Jd},\tK0(0H%0/mJW0a|00 $V !^ !V ! !~ $#5 !9 !G !K !Y !5] !%b ${ !w !q ! !(Af !w<(Fjx B,\LVpv}:PD_lv8Xb $:p' !+ !: !> !C $M_ !c !q !6u !& ! !q $ ! ! ! ! %2<W(a.b| 3Qly(HR< $Ff !j !y !} ! $ !@ !6 $ $ !j !d " ! ! ! !(Fgq C X  x .;F " X !\ !j ! n !| !9 !1 $+ILVp   /7HTfxx~ m #0:~ U_ z8   $  !` !X# !' !, $6H !L !Q $[ !_ !d "-v !z ! !) !!    9 ;Eg p( H  "" !P !F !~ !t ! !  - ! O . m N  [ {   ! -!:!D! _!l!v! !!! ! ! ! "$"." I"V"`"R " $"@" !" !" !" ! " $"" !;" !5" !f" !T# ! # !#p+# !/# !4#{I#kf#z##G##h### $ $`$p5$ !9$ !F$ ! J$ ! O$ $Y$hj$ !i n$ !S |$ ! $ ! $ ! $ ! $ !S $ !I $ ! $ !w $$$ %%=%[%1{%H%%%%&-&=&X&e&ho&&&h&;&&G&M&p'|*'='`' $i'`' ! ' ! ' ! ' ! ' $'x'''(!(<(I(xS(a( $Lj(( ! ( ! ( !" ( ! ( $(( !G ( !? ( !l ( !d ((),/)>N)xi)v))))))))) $)` * ! * ! ,* ! 0* ! 5* $?*Q* ! U* ! Z* |* * *$* * *++ +87+D+N+Xi+v++b+ ${++ ! + ! +4+ $;++ ! + ! , != , !5 , !e , !] +, ! /, ! 4,U,c_,,p,,, ! , ! ,, "8, ! , ! , "8, ! , ! , -.-*;-R-_- k-h-- -- $=- $= " %/& %L* %S. %|2 %6 %: %D %I %N %S %X %] %"b %0g %?l %Eq %Ov %V{ %` %k %u % % % % %@ <@p`@ ` Hp,h.symtab.strtab.shstrtab.rela.text.rela.data.bss.rodata.str1.1.rodata.str1.8.rodata.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@@+P &@H1` 62`OE2'Ta-\@= mKX{N [0@0 \CQ\C @0h"0n0}p&pp  p@Xhtp=  }/338 0 0 0 644 54480 ` ELF>@@UHSHdH%(HD$1HHtA;t)1HHD$dH+%(u9H[]HҐHH5H1UHSHdH%(HD$1HHtA; t,1HHD$dH+%(u O ? O @ O J O K O  L O@]OyOO M O ViO O O !###/!O| L||U T|Q|-%  .  .OR L)sk ctssyUvT1UvT2UvT yUvUvT0(UvT Q ZUvT Q UvT Q -%  .O L)pk ssctHUvT1]jUvT0Q2UvT @UvT Q UvT @UvT Q  "Uv?UvT0qUvT Q UvT Q UvT Q -%~O L~-ct X UvT1u UvT0 UvT1 UvT Q -% . uO Lu-ssv \ UvT1y UvT0 UvT1 UvT Q -%lO Ll.pkm K UvT1h UvT0 UvT1 UvT Q -% . aO La,skb pkca UvT1 UvT  UvT Q  UvT Q -%  . RO LR,T V] UvT0Q2 UvT @ UvT Q  UvT @6UvT Q uUvT Q UvT Q -%3ORo L3sk4 ct5ssANUvT1kUvT2UvT UvUvT0UvT Q /UvT Q aUvT Q -%  .oO Lpk ss"ct$UvT1]?UvT0Q2]UvT @UvT Q UvT @UvT Q UvUvT0FUvT Q xUvT Q UvT Q -%O L&ct -UvT1JUvT0gUvT1UvT Q -%  .O L&ss 1UvT1NUvT0kUvT1UvT Q -% OL'pk UvT1:UvT0WUvT1UvT Q -%  . OL%sk pk/UvT1NUvT UvT Q UvT Q -%  .  OL%   ]nUvT0Q2UvT `@UvT Q UvT @UvT Q tAUvT Q sUvT Q -% OoL*  UvT1UvT0/UvT1aUvT Q -%  .o OAL(]UUT t -% OJL!pk sigmOUvT1UvT2UvT3UvT UvT0 +Uv]UvT Q UvT Q UvT Q -%  .  OJL+pk smmsgOUvT1UvT2UvT UvT0Uv3T|8UvT0jUvT Q UvT Q UvT Q -%  . ORL)sk msigUvT1UvT2UvT}UvUvT09UvT Q kUvT Q UvT Q -% xORl!Lxsky|! mzsig? UvT1\ UvT2{ UvT t  T} Uv UvT0 UvT Q ,!UvT Q ^!UvT Q -% |! .l! oOm"Lo-pkp !UvT1"UvT0-"UvT1_"UvT Q -% cO#Lc+skd pke"UvT1#UvT N#UvT Q #UvT Q -% TO-%LT+V  X ]$UvT0Q29$UvT @d$UvT Q $UvT @$UvT Q u$UvT Q %UvT Q -%"I~H}IH}4I4&I4:!;9! IB4:!; 9! IB .?: ; 9 'I< I !I/ :!;9 IB .:!; 9! 'I@z:!; 9 IB.:!;9! 'I@z$ >  !I: ; 9 I4:!; 9 IB.?: ; 9 '< :!; 9 I8  :!; 9 I8 4:!;9!I4:!;9! IB% $ > <'I : ; 9  : ; 9 .?: ;9 '< !.?: ;9 'I@z".?<n ++U++U U V U V P S S P S P \ P \ \ P ] P ] U V UV P SSPS P ]P] P \P\&U&\V\]U]V*/P/[S]oSoPSUVUVPSSPSUVUVPSSPSUVUVP\P\PSPSUVUVPSPSP\P\UVUVPSSPSP\P\\P]P]UVUVPSSPSP]P]P\P\UVUVPSSPSUVUVPSSPSUVUVPSSPSUVUVP\P\PSPSUVUVPSPSP\P\UVUVPSSPSUUU V U !VP ] !]!!P!!]P S !S!!P!!S P \ !\!!P!!\ !PUVUVP]]P]PSSPSSP\P\0!"U"#V##U#$V""P"#S##S#$P$$S""P"#\##\$$P$$\""P"#]##]##P##]$$U$&V&&U&'V$%P%%S&&S&&P&'S%%P%&\&&\&'P''\%%P%%]&&]&&P&&]UVUVPSSPS''U'(V((U((V''P'(\((P((\''P'(S((P((S()U)*V**U**V))P)*S**P**S))P)*\**P**\, k  0 Y0WX<Y F.z0pfY0WX<Y[ p.z1pfY1WX<Y F.z)fY)WX<Y F.z)ofY)WX<Y[ p.z*ofY*WX<Y F.z,SfY,WX<Y F.z0fY0WX<Y F.z,fg,WX<gs3>#qQ  rt  .i..> . ,M.g,WX<gsk>=H> Q   zt >q.H.v./Bg/WX<YGZ h .x.G.{/hfg/sYL=KY>h .Luf.K. !T.g!WX<gs3'#qQ  rt  .i..' . !M.g!WX<gsk'=G> Q   zt 'q.G.v.(g(WX<YFZ h .x.F.{(ifg(sYK=JY>h .Kvf.J.*c.*WY.S.g.WX< Ju"ZxJ"x .x..$g$WX<   ..zt qt...,Ag,WX< gs3GJZ J .z Gw.x.."S.g"WX< gs3@Z J .zf @w.x...V.g.WX<YHZ h .x.H.{.hfg.sYM=LY>h .Muf.L. ./!X8c<Y%qp_sntrup_kem_ctcheckqp_verifysize_tqp_verified_messageqp_kem_keygen__uint8_tqp_sntrup_kem_keygenPQCLEAN_SNTRUP761_CLEAN_crypto_kem_keypairPQCLEAN_DILITHIUM2_CLEAN_crypto_signlong long intsigned charqp_signPQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signaturelua_pushintegersignlong intPQCLEAN_KYBER512_CLEAN_crypto_kem_decPQCLEAN_KYBER512_CLEAN_crypto_kem_enclua_CFunctionecdh_classPQCLEAN_DILITHIUM2_CLEAN_crypto_pub_genecdh_methodsprivateunsigned intlong unsigned intlua_createtableqp_kem_sschecknameshort unsigned intzen_add_classo_newGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionqp_signature_checkqp_sntrup_kem_sschecko_argqp_signature_keygenlua_setfieldPQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypairqp_sntrup_kem_decluaL_Regpubliclua_Stateqp_signed_messageqp_signature_pubcheckfloatlua_pushbooleanunsigned charshort intqp_encPQCLEAN_SNTRUP761_CLEAN_crypto_kem_decPQCLEAN_SNTRUP761_CLEAN_crypto_kem_enclerror__func__luaopen_qp__stack_chk_failqp_sntrup_kem_pubgenPQCLEAN_SNTRUP761_CLEAN_crypto_kem_pubgenPQCLEAN_KYBER512_CLEAN_crypto_kem_keypaircharfuncqp_decPQCLEAN_KYBER512_CLEAN_crypto_pub_genqp_kem_pubcheckqp_kem_pubgenqp_sntrup_kem_pubcheckoctetqp_signature_lenlua_Integeruint8_tPQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verifyqp_sntrup_kem_encqp_signature_pubgenqp_kem_ctcheckresultPQCLEAN_DILITHIUM2_CLEAN_crypto_sign_open/home/alby/dev/Zenroom/meson../src/zen_qp.c/home/alby/dev/Zenroom/meson../src/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits../lib/lua53/srcmilagro-crypto-c/include../src/zen_qp.czen_qp.cstddef.htypes.hstdint-uintn.hlua.hlauxlib.hamcl.hzen_octet.hzen_error.hlua_functions.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx (EID0C FAD (HEID0@ FAG (tEID0C FAD (EID0C FAD (EID0@ FAG (EID0C FAD ($EID0C FAD (PEID0C FAD 8|RFGA D(D@ (F ABBF 8FGA D(D@ (F ABBE 0FFD D0Z  FABI 0(FHD D0  FABF 8\RFGA D(D@ (F ABBF 8FGA D(D@ (F ABBE 0FFD D0Z  FABI 0FHD D0  FABF <AH s A 8XJFGA D(D@w (F ABBH 8JFGA D(D@ (F ABBG 8RFGA D(D@ (F ABBG 8 RFGA D(D@ (F ABBD 0HFFD D0Z  FABI 0|FHD D0  FABF |Kk A   ,BN epq@`@R 2>pSP_0t0@ R& 0  APJJx R/`:PRBXMa lp    0LSPZbi.>Kr9csEr|}zen_qp.cqp_sntrup_kem_ctcheck__func__.19qp_sntrup_kem_sscheck__func__.18qp_sntrup_kem_pubcheck__func__.17qp_kem_ctcheck__func__.12qp_kem_sscheck__func__.11qp_kem_pubcheck__func__.10qp_signature_check__func__.7qp_signature_pubcheck__func__.2qp_sntrup_kem_dec__func__.21qp_sntrup_kem_enc__func__.20qp_sntrup_kem_pubgen__func__.16qp_sntrup_kem_keygen__func__.15qp_dec__func__.14qp_enc__func__.13qp_kem_pubgen__func__.9qp_kem_keygen__func__.8qp_signature_lenqp_verified_message__func__.6qp_verify__func__.5qp_signed_message__func__.4qp_sign__func__.3qp_signature_pubgen__func__.1qp_signature_keygen__func__.0.LC24.LC25.LC27.LC26.LC28.LC29.LC30.LC31.LC32.LC33.LC34.LC36o_arglua_pushbooleanlerror__stack_chk_failo_newPQCLEAN_SNTRUP761_CLEAN_crypto_kem_declua_createtablelua_setfieldPQCLEAN_SNTRUP761_CLEAN_crypto_kem_encPQCLEAN_SNTRUP761_CLEAN_crypto_kem_pubgenPQCLEAN_SNTRUP761_CLEAN_crypto_kem_keypairPQCLEAN_KYBER512_CLEAN_crypto_kem_decPQCLEAN_KYBER512_CLEAN_crypto_kem_encPQCLEAN_KYBER512_CLEAN_crypto_pub_genPQCLEAN_KYBER512_CLEAN_crypto_kem_keypairlua_pushintegerPQCLEAN_DILITHIUM2_CLEAN_crypto_sign_openPQCLEAN_DILITHIUM2_CLEAN_crypto_sign_verifyPQCLEAN_DILITHIUM2_CLEAN_crypto_signPQCLEAN_DILITHIUM2_CLEAN_crypto_sign_signaturePQCLEAN_DILITHIUM2_CLEAN_crypto_pub_genPQCLEAN_DILITHIUM2_CLEAN_crypto_sign_keypairluaopen_qpzen_add_class#E=FiFs2z9GHEFF2 9GHCE]FF2l9GHEFF#2 *94G;HcEzFF29GHE F9FC2J9TG[HEFF29GHE-FYFc2<j9tG{HEE:IJ;3<=GGFs2z9G29G29GHE =5KBIU>bLoI?LM@GF 29G+229<GK2R9\GfHEIN2L9G2L9$G+HWKdIwALIBLO2,9 G 2, 9$ G. Hg E E : I P ; < G F3 2": 9D GS 2"Z 9d Gs 2"z 9 G H E = K I >" L/ IB ?O La Q @ G F 2 9 G 2 9 G 2 9 G& HU Ej I R 2 9 G 2 9 G H K$ I7 AD LQ I` Bm L{ S 2 9 G 2 9 G HT=HwEE=GFIU,F;2B9LG[2b9lG{29GHEEE= G*FmV}F2t9G2t9G2t9GHE0EI:]I~WCGF2\9G2\ 9G#2\*94G>HwEE:IXC&G0FC2TJ9TGc2Tj9tG2T9GHEIY32:9DGS2Z9dGkHKIALIBLZ32:9DGS2Z9dGnHD\Hp (08P@HPX`hPpx` 0 @ @ #00p =( 0L8@ZHPhX`rh 4 73 8 8* 61 78 7? 7D 7 ^ 7e 7 l 7q 7I 7 7 7b 7 7 7 7V 7s 7y 7 7$ 7y7 7j 7?v 7: 7 7 7  7j4 7^ 7 u 7 7 7M 7' 7h 7! 7A 7-^ 7z 7 7- 7 7> 7 7) 7N5U 5Y 5 ^ 7m 7| 7g  5* 5" 5T! 5J& 7E02B 5F 5xT 5X 5]zAK2)DQ2[v2 7 5 5 5 5 7E2 5) 5!# 5N' 5F, I9kFfLsS #@ [h2r@2`2j 7 5s 5k 5$ 5) 7E3 2< 'Y Av m   2  7  5 5$ 5( 5- 7E7 2@ ] z    2  7(   5 5  5; 51 7E& 2p/ GL ai    2p  7j p 5g 5_ 5 5 7E* 2P< 5@ 5E b     2P (  2P / 7S 0? 5C 5H 7R 5V 5[ 7Ee 20n 7x 5&| 5 [ h  Z  -b7D _l20v( 202  7@  5K 5C 5u 5k 7E2& 5 5) 5- 52k O l    H 2&h &2&0 KX2&b  7  5 5 5 5 7E2 5J 5B 5o 5g  @ ^& L3 S Se    0=2G bo2y 2*  7 5 5 5 5 7E2.Kh82? 7@ 5 5 5 5  7E 2g2~Ol2 7  5@ 58 5j 5` 7E2;=XXs2_ 70  5 5 5 5 7E2  5 5Y 0n O \ w2 2  7;  5 5 7 50" 5(' 7E12: 7D 5UH 5MM o( H ZU q b  +82B ]j2t  7` 5z 5r 7 5 5 7E20KX2b 7E 5 5"A 7  5 5 5! 5& 7E02xB 5>F 54R 5lV 5b[ 7e 5i 5n$0.q,GT2x^y2x2x 7'P  5 5 5" 5' 7E12B 5F 5T 5/X 5'] 7g 5Nk 5Lp{009PTa2kp22 7 5_ 5W+ 5/ 54 7E>2`N 5R 5` 5d 5i4a#02`:Ub2`l82`B 7P 5  5  5;  51  7E2X 5i 5_  5  5 # {@ ] |  * 4 X  2X x!#!2X-!H!U!2X_!! 7!! 5 ! 5 ! 5 ! 5 ! 7E!2@!!1"]."xI"V"2@`"n" 7w"" 5 " 5 " 5A " 59 " 7E"2 " 5f " 5^ ""##H8#E#2 O#hj#w#2 #o# 7#p# 5 # 5 # 7# 5 # 5 # 7E#2# 7# 5 # 5 #$:$[$Ze$$$b$$H$$2$h %%2 %r.% 7Y2% 7Y 3" 8-& 8J* 8Q. 8z2 86 8@ 8E 8J 8O 8T 8Y 8^ 8c 8h 8m 8#r 8/| Lx @(`Tp,0`@  0  @\PPLp.symtab.strtab.shstrtab.rela.text.rela.data.bss.rodata.str1.1.rodata.str1.8.rodata.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@hsx+@ &@P162|E2@{Ta7%\@05 m@#{C N0@0 AN @0X0^?0 `&1`8` X`@@ eE m/357 0 0 0 644 56736 ` ELF>@@HHdH%(HD$1HD$dH+%(u HATxUHHdH%(HD$1IHtPHpذHHH@HHD$dH+%(u*HL]A\DHH5H1UHSHdH%(HD$1HHt&H{HD$dH+%(u'H[]ÐHH5H1ATUHSHdH%(HD$1IHA$@tBH5H1H5H11HT$dH+%(usH[]A\DHHHtH{LDHH5H1fDHH5H1PfDUHSHdH%(HD$1HHt&H{HD$dH+%(u'H[]ÐHH5H1ATUHSHdH%(HD$1IHtwHHHtGH{LtHD$dH+%(udH[]A\ÐH5HHH5H1fDHH5H1lfDAUHAATUHHdH%(HD$1IHt!HD$dH+%(u%HL]A\A]@HDHff.@UHHdH%(HD$1HtHD$dH+%(u%H1]DHH5Hff.AUATUHHdH%(HD$1IHI|$ulAD$HpIHHLLLHHD$dH+%(H]A\A]f.HIHtkID$ID$@ID$@A$HH5H1)HH5H13HH5H1xff.AUIATUHdH%(HD$1HHtfLIHtqHIHLLHLHD$dH+%(uQH]A\A]DHH5L1fDHH5L1rfDATIUSHPdH%(HD$H1HHt_LHHHtgIH<LLH}LHD$HdH+%(uNHP[]A\HH5L1fDHH5L1|ff.ATIUSHPdH%(HD$H1HHt_LHHHtgIHLLH}LHD$HdH+%(uNHP[]A\HH5L1fDHH5L1|ff.ATIUSHPdH%(HD$H1HHt_LHHHtgIHLLH}LHD$HdH+%(uNHP[]A\HH5L1fDHH5L1|ff.ATIUSHPdH%(HD$H1HHt_LHHHtgIHLLH}LHD$HdH+%(uNHP[]A\HH5L1fDHH5L1|ff.ATIUSHPdH%(HD$H1HHt_LHHHtgIHsLLLH}LHD$HdH+%(uQHP[]A\fDHH5L1fDHH5L1|ff.ATIUSHPdH%(HD$H1HHt_LHHHtgIHsLLH}LHD$HdH+%(uQHP[]A\fDHH5L1fDHH5L1|ff.ATUHSHdH%(HD$1HHt?HIHtJHsLHD$dH+%(uHH[]A\HH5H1fDHH5H1UHSHdH%(HD$1HHt1H{HHD$dH+%(u(H[]fHH5H1AUIATUSHdH%(HD$1HHLHHLIHHI LkHLLLHLHD$dH+%(uwH[]A\A]f.HH5L1UHH5L1NHH5L1Gff.ATUHSHHdH%(HD$1IHt1HsI|$HD$dH+%(u-HL[]A\HH5H1AUATUHSHdH%(HD$1IHt]HIHthLHHHtuIt$H{HD$dH+%(utH[]A\A]HH5H1fDHH5H1{HH5H1nff.AUATIUSHdH%(HD$1IHt]LHHthLLHHtuHuH{HD$dH+%(uuH[]A\A]HH5L1fDHH5L1{HH5L1nff.AUATIUSHdH%(HD$1IHt]LHHthLLHHtuHuH{HD$dH+%(uuH[]A\A]HH5L1fDHH5L1{HH5L1nff.ATUHSHdH%(HD$1IHt?LHHHtLH{HD$dH+%(uMH[]A\DHH5H1fDHH5H1ATUHSHdH%(HD$1IHt?LHHHtLH{HD$dH+%(uMH[]A\DHH5H1fDHH5H1H(H HdH%(H$HH5HL$ H HT$PHH$HL$p,H$H$H$H5HHH=HDŽ$H$HHD$HHD$HSHD$HD$(HHD$0HFHD$8HHD$@HHD$HHD$XHHD$`HHD$hHD$xH$H$HDŽ$H$dH+%(u H(Error allocating new ecp2 in %soctet length is %u instead of 64 (need to use sha512)Invalid argument to ECP2.mapit(), not an hashOctet doesn't contains a valid ECP2zenroom.ecp2NULL variable in %secp2 class expectednewgeneratorGmapitinfinfinitypairloopmillerateecp2affinenegativeisinfisinfinityoctetxrxiyryizrziadd__addsub__subeq__eqmul__mul__gc__tostringlua_new_ecp2ecp2_generatorecp2_mapitecp2_get_infinityecp2_millerloopecp2_affineecp2_negativeecp2_isinfecp2_octetecp2_get_xrecp2_get_xiecp2_get_yrecp2_get_yiecp2_get_zrecp2_get_ziecp2_addecp2_subecp2_eqecp2_mulecp2_outputecp2_destroyecp2_dupecp2_newk)& ' .(int Q )Q  y 7) h *Q +  ! " 9.ilen Qmax Qval  9 :. < &g (uXES ) 8 * ix my o<z qx rx $a &b '< (h %Jx (y )xz * + %ua 'b (x )V$a&ub'u,c(u-) Q * EQval ecpx(2) E* Eval+J 10)lenQQval   "r( big>)lenQQval  Q   J i %  < $T oQ W  N  >     &Q  "     //  F/ Q ]// -Qss  &s Q     Q ^ Q   c  ^   *s6Q!MdQ X L Q !  R    .QQ A< Q.Q)Q QIQ Qe <E ~  /Q_%L5{J}U T{Q}e) 5. % J. :QR9 L#e9 N o 0 o dUvT3IUvT Q &= UvT1U U|dm UvM UvT ' U}T|6 UvT}I UvT Q I+ UvT Q e) 2N . > }Q L}#e~9 N fzzbs& U|T1x U|] UvF9 UTs4R Uk TI U|T Q I U|T Q e)uQg Lu#ev9 N fzwzaxs&s U|T1x U|] UvF UTs4 U TI' U|T Q IY U|T Q e)mQLm#en9 N fyoybps& U|T1xU|]-UvFMUTs4fUTIU|T Q IU|T Q e)eQ{Le#ef9 N fygyahs&U|T1xU|]UvFUTs4U TI;U|T Q ImU|T Q e)[QL[#e\9 N fx]xb^s&U|T1x)U|]AUvFaUTs4zUTIU|T Q IU|T Q e)RQLR#eS9 N fxTxaUs&U|T1xU|]UvFUTs4UTINU|T Q IU|T Q e)FQLF"oG  eL9 TUvT1<:UvT I_UvT &wUv%UsT|IUvT Q IUvT Q e). 7QL7 p89  b9sr:9 &UvT1UvT2>%UvT}UsI:UvT Q IlUvT Q IUvT Q e). /QL/"e09  o1 &HUvT1dfUvTU|TsIUvT Q IUvT Q e)QrLp9  q9 &}U}T1&U}T2UvU|UvT|U}I2U}T Q IdU}T Q e). r QL %in9  out9 &UvT1>%/UvT|GUsIyUvT Q IUvT Q e). QbL e9  q9 p9 &eU|T1&U|T2>%U|T}UsTvIU|T Q I"U|T Q ITU|T Q e)QL e9   q9 p9 &U|T1&U|T2>%1U|T}OUsTvIU|T Q IU|T Q IU|T Q e)QL" e9  &eUvT1}UsUvIUvT Q e)QoL) e9  &BUvoZUsIUvT Q e). Q L# in9 N  out9 &5 UvT1>%S UvT|k UsI UvT Q I UvT Q e)Q""L' f"  x9 yl!U}&!U}T1!U}T2!Uv!U|!U}TvQ|"U}ID"U}T Q Iv"U}T Q I"U}T Q e)". "Qo#L& e9 # &8#UvP#UsI#UvT Q e)#. #uQ$Lu$ o %  e9 T($UvT1&@$Uv^$UsT|I$UvT I$UvT Q I$UvT Q e)%. $]Q>% L]% !e_9 W9 &LWinW$9 eX9  &%Uv%U|TsI&UvT Q e)Q9 q&LQnQ!Q udR< eT9 &UvT}Q &UvT}Q e)F9 ' LF!eG9  @Q@'o@e@$9 'UUTT#e)"&(&#&$&F'(&%&IUvT Q eF(UvT x)t(UvT}Q  (UvT e)" %ee)%#5%$ %]:)%%5%IUvT Q &W)UvT1e)1I~H}I4:!;9 IBH} : ; 9 I8 4I4.?: ; 9 '< : ; 9 I .?: ; 9 'I< 4:!; 9 IB &I  !I:!; 9 IBI!I/ :!;9 IB : ; 9 I8 .:!;9! 'I@z$ > .:!; 9! 'I@z : ; 9! 4:!;9!I : ; 9! 1BH}.?:!; 9 'I@z: ;!#9!I4:!;9!I.?:!; 9 'I ! :!; 9 I!4:!; 9!I".1@z#41B$1RB X!Y W %41&% ' ($ > )<*'I+ : ; 9 , : ; 9 I8- : ; 9 I8..?: ;9 'I</.?: ;9 'I@z0 U1.?<no &'U')U U V U V P \ \ P \ P ] P ] P \ P \ U \U\ P SPS P VVU\U\PSPSPVVU\U\PSPSPVVU\U\PSPSPVVU\U\PSPSPVVU\U\PSPSPVVUVUVP\\P\PSPSUVUVP]P]P\P\PSPSUVUVPSPSP\P\ U ] U ] P V vp P V vp P \ |p P \ |p##U#$V$$U$$V#$P$$\$$P$$\$$P$$S$$P$$SU \ U !\ P ] P !] P V !P!!V P S!!P!!S!!U!"\""U"#\!"P""]""P"#]""P""V"#P##V""P""S##P##SUVUVPSPSUVUVPSPS%%U%%V%%U%&V%%P%%\%&P&&\%%P%%S&&P&&SU]U]UPS}hPSPVvpPVvpP\|tP\|tUVUVPSPSUVUVP\\P\PSSPSSUVUVTSTSP\P\UVUVT]T]P\P\\ U @U T tp @T@gUgVUVkP\P\VUVUVPPV,   ' ?'IYgWX=[ u Yt.vf.Y.,f X<Y +.w%f g%W X<JY 2X.c Y ..)~ X<` v.. t'Ef #f']X# X<Y YL .,r..$ g$s X=[t..U!/ C Z Vt YYfaX.& g&W X<O X< < wY X<$XK XJ  ... ". g"W X<Y ZKIL..xf..& g&W X<Y &Y! .zJ.&&q. g&W X<Y &Y! .zJ.&&q. g&W X<Y &Y! .zJ.&&q. g&W X<Y &Y! .zJ.&&o. g&W X<Y &Y .zt.&&p. g&W X<Y &Y .zt.&%V. g%W X<Y Y ...w%f Y%W X<Y/ 9.w*Pf X<  KKH׃ ..x...(.  X<Yt ..w#f g#W X<Y Y Y ..}...#B. g#W X<Y Y Y ..z...#g. g#W X<Y Y Y ..z...(. g(W X<YY .b..w&f g&W X<YY .b..w f Es XsX%[ [ Y%ecp2_eqecp2_get_zrecp2_methodsBIG_384_29ECP2_BLS381_isinfecp2_mapitlerrorbig_initFP_BLS381_copypush_octet_to_hex_stringunsigned intluaL_checkudataECP2_BLS381_addluaopen_ecp2__int32_tfp12ecp2_affineo_argocteterrorfuncdoublesizelua_new_ecp2FP_BLS381_redcECP2_BLS381_equalsfloatluaL_Regecp2_millerloopecp2_destroyECP2_BLS381_affineECP_BLS381PAIR_BLS381_fexpECP2_BLS381_fromOctetGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionECP2_BLS381lua_getfieldFP12_BLS381ECP2_BLS381_neglua_StatePAIR_BLS381_ateECP_BLS381_affinesize_tECP2_BLS381_copyECP2_BLS381_subecp2_isinffp12_newcharlua_CFunctionlua_settopFP_BLS381lua_setmetatableo_newlong long intecp2ecp2_muldvaltotlenecp2_argecp2_classecp_argFP_BLS381_reduceluaL_argerrorecp2_outputecp2_addbig_argshort intlong int__stack_chk_failECP2_BLS381_generatorlua_newuserdatanameECP2_BLS381_inflong unsigned intPAIR_BLS381_G2mulint32_tFP4_BLS381chunksizeecp2_octettypeecp2_get_infinityunsigned charzen_add_classecp2_get_xiecp2_get_xr_ecp2_to_octetecp2_newecp2_subECP2_BLS381_toOctetsigned charshort unsigned intecp2_get_yi__func__ecp2_get_yrFP2_BLS381ECP2_BLS381_mapithalflenecp2_dupecp2_negativelua_pushbooleanbig_newecp2_get_ziecp2_generator/home/alby/dev/Zenroom/meson../src/zen_ecp2.c/home/alby/dev/Zenroom/meson../src/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits../lib/lua53/srcmilagro-crypto-c/include../src/zen_ecp2.czen_ecp2.cstddef.htypes.hstdint-intn.hlua.hlauxlib.hamcl.hbig_384_29.hfp_BLS381.hecp_BLS381.hfp2_BLS381.hecp2_BLS381.hfp4_BLS381.hfp12_BLS381.hzen_ecp.hzen_big.hzen_fp12.hzen_error.hzen_octet.hpair_BLS381.hlua_functions.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx @H r A (8FFG0a DBF (doEDD0z FAB 0FFD D0b  AABF (oEDD0z FAB 0FFD D0Q  FABB 0$qFLA G0q  DBBE XeEL n CF 0|RFGA G0  FBBK 0FJA D0s  FBBF 0FIA Dpo  FABD 0FIA Dpo  FABD 0LFIA Dpo  FABD 0FIA Dpo  FABD 0FIA Dpl  FABG 0FIA Dpl  FABG 0FFD D0R  FABA (PEID0D FAC 8|"FEA A(D@ (F ABBK 0FAD G0  DABH 8FGA D(D@g (F ABBH 8(FGD A(D@f (F ABBI 8dFGD A(D@f (F ABBI 0FFD D0M  FABF 0FFD D0M  FABF _KN A  h o*05P@ K@oZer }H pR8    p P  0 ! - 9 D O Z e p "PX (   p`       X$*!0C6O<5BiH]NbTmZ9`EfKlXr@@Y "8qAQ_el~'/AQbPk|0_zen_ecp2.c__func__.22ecp2_get_infinity__func__.3ecp2_mapit__func__.2ecp2_generator__func__.1lua_new_ecp2__func__.0__func__.20ecp2_output__func__.19ecp2_eq__func__.17ecp2_get_zi__func__.14ecp2_get_zr__func__.13ecp2_get_yi__func__.12ecp2_get_yr__func__.11ecp2_get_xi__func__.10ecp2_get_xr__func__.9ecp2_octet__func__.8ecp2_isinf__func__.7ecp2_millerloop__func__.4__func__.21ecp2_mul__func__.18ecp2_sub__func__.16ecp2_add__func__.15ecp2_negative__func__.6ecp2_affine__func__.5.LC23.LC22.LC24.LC25.LC26.LC27.LC28.LC31.LC34.LC29.LC38.LC36.LC37.LC40.LC30.LC32.LC33.LC35_ecp2_to_octetECP2_BLS381_toOctet__stack_chk_failecp2_newlua_newuserdatalua_getfieldlua_setmetatablelerrorECP2_BLS381_info_argECP2_BLS381_mapitECP2_BLS381_generatorECP2_BLS381_fromOctetecp2_argluaL_checkudataluaL_argerrorecp2_destroyECP2_BLS381_isinfo_newlua_settoppush_octet_to_hex_stringECP2_BLS381_affineECP2_BLS381_equalslua_pushbooleanbig_newbig_initFP_BLS381_copyFP_BLS381_reduceFP_BLS381_redcfp12_newecp_argECP_BLS381_affinePAIR_BLS381_atePAIR_BLS381_fexpecp2_dupECP2_BLS381_copybig_argPAIR_BLS381_G2mulECP2_BLS381_subECP2_BLS381_addECP2_BLS381_negluaopen_ecp2zen_add_classL<MdO9PQ1d:RMNS31,:;DRKMuT<U=RNV1; R1";,R6M^NoW1 ;RMTNX#>+R;1B;LR[1b;lRvM9Z?[M"YK1DR;ZRaMY]^_K`)^c14j;tR14;R14;RMY Y#a+a6b@ck1r;|R1;RMYdefghC1J;TRc1j;tR~MYdefgh#1*;4RC1J;TR^MYdefgh 1 ; R# 1* ;4 R> Mu Y d e f g h 1 ; R 1 ; R MU Ye dp e f g h 1 ; R 1 ; R M5 YE dP ed fl gx h 1 ; R 1 ; R M Y* ^> Lc 1j ;t R 1 ; R M Y ] c 1| ; R MB i[ Yt j a k l m 1L ; R1L ;R#1L*;4R>MsNo1T;RMY pn5qc1$j;tR1$;R1$;RMY Yn4rc1 j;tR1 ;R1 ;RMY Yn4sc1j;tR1;R1;RMYntC1lJ;TRc1lj;tR{MYna1\;R1\;$R+M>@EA]BdCpD|EFGHI/JfvMry ( 08 @H PX `h0 pxP p (08\@Hp 3 7 8 8* 61 7 8 7A 7F 7` 7mg 7n 7u 7z 7 7 7. 7 7 7' 7 7- 7 7 7-% 7+j 7v 7! 7  7f 7K 7Ov 76 7V 7h 73 7L  73 7L3 79G 7a 7A{ 7G 7 7 7. 7 7 7& 7!= 7U 7p 7 7q 7 7 7g 7 7t 75 7oG 7Y^ 7Py 7b 7 7 7R 7 7S 7 77 7hN 7e 7% 7, 7{ 7 7 7 7* 7[J 7If 7 7 70 4 4  7\ 7jmP 7Zpz 4*~ 4" 4T 4J 718 4 4x 5  4 4-   18! > V n    x  18   " 18, T 7j^ ~ 4 4 4 4 7 1 4 4     : S l X  1 x  1  7  43 4+ 4[ 4S# 7- 1N 4~R 4xW t      8   1( XC  P 1Z bh 7r p 4 4 4 4 7 1 4 4  .Ng  18  1B  7 P  4  4. 4-2 4%7 7A1b 4Pf 4Jky       % 21< W d1n" | 70  4n 4f 4 4 71 4 4Y i *t B b {   1  1  7 0 44 4B 4F 4K 7U1v 4"z 49 I T h p |  8 E1O j w1  7>P 4@ 48 4j 4` 71  4 4y1 ;VX`x 1 0 1 : 7>'G 4K 4Y 4] 4b 7l1(~ 4 4 4- 4%#9 x$ 11(;V c1(m 1( 7K  4R 4J 4z 4r 71# 4' 4, I. gB x  1  1  7! 4% 43 47 4< 7F1 X 4+\ 4a~'/:D )1 3N [1 e 7D 4b 4Z 4 4 71p 4 4 0HXc p1pzx 1p 7 4 4  4  4 71. 4!2 4@ 4FD 4>If#8x 1  1#> K1Uc 7l 4k 4c 4 4 71 4 4 4 4#28Pxk x1 1 1 7  4  4- 4*1 4"6 7@1I f ~   1  7[ 4O 4G 4w 4o 7"10+C[Hv 10O 7 4 4 4 4 71` 4 4 6 T l   1` (  1` / 76  ! 4 ! 4! 4D! 4: ! 7*!1P;! 4v?! 4jL! 4P! 4U!F m!_ !x ! ! ! ! " ." ;"1PE"`" m"1Pw"8" "1P"B" 7v"@" 4" 4# 4 # 4 # 7#1!#b9#sQ#l# y#1## 7## 45 # 4- # 4_ # 4U # 7#1$ 4 $ 4 $)$A$_$/z$$P$ $1$p$ $1$z % 7F#% 7-%1H?% 7;I%Ph% 4 l% 4 z% 4 ~% 4 % 4 % 4 % 7%1X%w%%% &1X&& 7S'&F& 47 J& 4/ W& 4_ [& 4W i& 4 m& 4 z& 4 ~& 4 &&&&!&& 7' 7'1h' 7%'D' 4 H' 4 U' 4 Y' 4 ^'!'@'@' 4 ' 4 ' 4 ' 4 ''' 4& ' 4$ '((1h((hG(k(u(((( 46 ( 4. ( 4Z ( 4V (H(H( 4k ) 4i )^#) 0)1H;)&X)ef) 7j) 7 2" 8/& 8L* 8S. 8|2 86 8@ 8E 8J 8O 8T 8Y 8^ 8 c 8h 8m 8)r 85w 8B| 8O 8] 8j 8x 8 8 8 8 8 8 <@hP@(\pPpP 0   T  P,h 0.symtab.strtab.shstrtab.rela.text.rela.data.bss.rodata.str1.8.rodata.str1.1.rodata.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@wp+` &@P1@62@E2TqaAo)\@@9 mB{Es *Q0@00 ZQqQ @`0 [0`0_b&bb  b(@pg( K r/378 0 0 0 644 56376 ` ELF>8@@UHSHdH%(HD$1HHHt.H{H5HD$dH+%(u(H[]fHH5H1ATUHHdH%(HD$1IHt8LHЉHD$dH+%(u+H]A\@HH5H1fUHSHdH%(HD$1HHt6HH{H5HD$dH+%(u(H[]fHH5H1ATUHHdH%(HD$1IHtPH8ذHH@aHHD$dH+%(u+HL]A\fDHH5H1UHSHdH%(HD$1HHt&H{ HD$dH+%(u'H[]ÐHH5H1ATUHSHdH%(HD$1IHA$@tBH5H1H5H11HT$dH+%(H[]A\ÐHHHt0A$1H5HH{ LHH5H1fDHH5H18ff.UHSHdH%(HD$1HHt&H{ HD$dH+%(u'H[]ÐHH5H1AUHATUHSHdH%(HD$1HtqHHHHIHIt$1H{ AHD$dH+%(HD[]A\A]@HIHoHHH;A$;CLAŅRLH{ AągHH5H1JH5H1&f.HH5H1HH5H1IT$:4z*H{ A@HA$KHH51E1H5H1tfHH5H1HH5H1tHE1DH1H5H5H1AUHAATUHHdH%(HD$1IHt!HD$dH+%(u%HL]A\A]@HDHff.@UHHdH%(HD$1HtHD$dH+%(u%H1]DHH5Hff.AUIATUHdH%(HD$1HHtfLIHtqH I HLLHLHD$dH+%(uQH]A\A]DHH5L1fDHH5L1rfDUHSHdH%(HD$1HHt1H{ HHD$dH+%(u(H[]fHH5H1ATUHSHHdH%(HD$1IHt1Hs I|$ HD$dH+%(u-HL[]A\HH5H1ATUHSHdH%(HD$1IHt?LHHHtLH{ HD$dH+%(uMH[]A\DHH5H1fDHH5H1ATUHSHdH%(HD$1IHt?LHHHtLH{ HD$dH+%(uMH[]A\DHH5H1fDHH5H1ATUHSHdH%(HD$1IHt?LHHHtLH{ HD$dH+%(uMH[]A\DHH5H1fDHH5H1ATUHSHdH%(HD$1IHHHHtnf{(uOLHIHHsI|$ HT$dH+%(H[]A\H5H11HH5H1uHH5H1@HH5H1SfDAUATIUSHdH%(HD$1IHt]LHHthLLHHtuHu H{ HD$dH+%(uuH[]A\A]HH5L1fDHH5L1{HH5L1nff.AUATIUSHdH%(HD$1IHt]LHHthLLHHtuHu H{ HD$dH+%(uuH[]A\A]HH5L1fDHH5L1{HH5L1nff.HHdH%(HD$1HD$dH+%(u HUHSHdH%(HD$1HHtIH{ HHHHsHHHD$dH+%(u+H[]DHH5H1fATIUHdH%(HD$1HHtPH HLIHHLHD$dH+%(u0H]A\fHH5L1ATLf UHLHdH%(HD$1tBHEHE@HE@EHD$dH+%(u&H]A\LHfAUATUHHdH%(HD$1IHI|$ ulAD$HpIHHLLLHHD$dH+%(H]A\A]f.HIHtkID$ID$@ID$@A$HH5H1)HH5H13HH5H1xff.AUATIUHdH%(HD$1HHtFELpIHtPHLHD$dH+%(uOH]A\A]fDHH5L1fDHH5L1fUH HH5H dH%(H$HHL$ H H$HL$pH$&HDŽ$HDŽ$H$HHD$HHD$H:HD$HD$(HHD$0HHD$8HHD$@HeHD$HHHD$PHHD$XHHD$`HUHD$hHD$xHH$HH$HH$HH$HH$HYH$HH$H+H$HH$HH$HHH=1HHH5H$dH+%(uH ]NULL variable in %szenroom.ecpmapit on o->len %uzenroom.bigecp class expectednewinfinfinityisinfordermapitgeneratorGaddsubmulvalidateprimeecpBLS381ECP curve is %saffinenegativedoubleisinfinityoctetxy__add__sub__muleq__eq__gc__tostringError allocating new ecp in %soctet length is %u instead of 64 (need to use sha512)Invalid argument to ECP.mapit(), not an hashnew ECP value out of curve (points to infinity)Octet length %u instead of %u bytesInvalid octet length to parse an ECP pointECP point validation returns %iOctet is not a valid ECP (point is not on this curve)Octet doesn't contains a valid ECPcannot multiply ECP point with double BIG numbers, need modulolua_new_ecpecp_get_infinityecp_isinfecp_orderecp_mapitecp_generatorecp_addecp_subecp_mulecp_validateecp_primeecp_affineecp_negativeecp_doubleecp_octetecp_get_xecp_get_yecp_eqecp_outputecp_destroyecp_dupecp_new>') *.+int Q)Q  y 7,h -Q . ! " >.nlen Qmax Qval >:. < &g (zXES ) 8 * . & ix my o<z qx r D  E Qval  ecp 0  .len Q Qval      "r( big N  Q  n & QQ @<2Q D [ r #< $7  V  *Q  E Q. IQ ``  w -Q &Q Q !&Q AX/act %Y!uuu "  { Q     .QQ A<%QQAQ QaQ Q} <E0QX L h{ }}YU T{Q}AJUvT Q 8'h. X}. mQRl L"el  o !So &$UvT3aUvT Q #pUvT1U| &UvUvT  U}T|UvT}a, UvT Q a^ UvT Q 8' D . q Q[ L!pk  Uv UsIaM UvT Q 8'k . [ Q L!el k y# UvT1 Us ' Uv? Uv$"^ UvTsa UvT Q 8'Q L!el k x#% U|T1= UvU U|m U|$" U|Tva U|T Q 8'}Q L}!e~l k o #R U|T1&j U| U}Tva U|T Q a U|T Q 8'1oQ"o"e"l bQ Lbpcl  qd l #U}T1#U}T2UvU|UvT|'U}aYU}T Q aU}T Q 8'. OQe LOePl u bQoutUl #IUvT1fUvT2"UvT|U| aUvT aUvT Q a%UvT Q aWUvT Q 8'u. e@Q L@"inAl  outBl #UvT1""UvT|w:Us alUvT Q aUvT Q 8'4Q L4$in5l  out6l #6UvT1"TUvT|elUs aUvT Q aUvT Q 8'. &Q L&e' l u q( l p)l #U|T1#U|T2"U|T}Us Tv aU|T Q aIU|T Q a{U|T Q 8'Q Lel u ql pl #"U|T1#?U|T2"]U|T}{Us Tv aU|T Q aU|T Q aU|T Q 8'Q L!el k #UvT1Us UvaUvT Q 8'Q2 L"inl  outl #UvT1"UvT|Us aUvT Q a$UvT Q 8'Q' L$o  resQ.UvT1U|UvaUvT Q 8'Q L!o k el .UvT1UvT aUvT n$ Uvr1UvT [OUs T|aUvT Q aUvT Q 8'Q L!resk 0UvHUsDaUvT Q 8'QoZ L(el j n$Uv2Us aLUvT Q 8'j. ZQo4 L%el D n$UvUs a&UvT Q 8'D. 4gQ" Lg#txj<" o el resQ!el xn$Uv4UvT1QUs Q0vUvT aUvT Q aUvT Q  UvT1Q . UvT1n$6 UvN U|l Us T| UvT a UvT 2 Us  UvT  !UvT a/!UvT aa!UvT Q a!UvT Q !UvT !UvT Q}a"UvT 8'". "ZQ@" dstZ srcZ"TT8'#SQ"$LS" %eUl Ml # LM inM!l eN l u n$F#Uvd#U| Ts a#UvT Q 8'Gl qn$ LG nGQudH<eJl 5$UvT}Q `$UvT}Q 8'#<l $$L<%e=l u n$%}$&$'n$<<%}$($aUvT Q }Z%UvTA%UvT}Q %%UvT 8'"ey&"&"'"SN&"("aUvT Q #k&UvT18' 8' 2 o& 'U|z*'UvT|Q18'3I~H}IH}4:!;9 IB4I4.?: ; 9 '<4:!; 9 IB &I .?: ; 9 'I< :!;9 IB :!; 9 IB  !II!I/ .:!;9! 'I@z$ >  : ; 9 I8 : ; 9 I : ; 9 I8 1B.:!; 9! 'I@z : ; 9! H}.?:! ;9! '<.?:!; 9 'I@z.1@z4: ; 9!I?<: ;!#9!I.?: ;9 'I< 4:!;9!I! U":!;!9 I#.?:!; 9 'I !$:!; 9 I%4:!; 9!I&41B'1RB X!Y W (41)% * +$ > ,<-'I. : ; 9 /.?: ; 9 '<0.?: ;9 'I@z1.?: ;9 'I 21RB X YW 3.?<n %(U()V))U))V!!U!"V""U"$V!!P!"\"#\##P##\""P""]##P##]##P##\#$P$$\!U!]V]^U^V%,P,\S^SUVUVUPSPSPVVU\ U \ UPV vt P V vtP \ \$$U$%\%%U%%\$$P$%V%%P%%V$$P$%]%%P%%]U]U]PVvtPVvtP\|tP\|tUVUVP\\P\PSSPSSP\P\UVUVP\P\PSPSUVUVP\P\PSPSU\U\P]P]PVPVPSPSU\U\P]P]PVPVPSPSUVUVPSPSUVUVP\P\PSPSUVUVP\P\Pp UVUVP\\P\PSPSUVUVPSPSUVUVPSPSUVUVPSPSU V U VP P P \ \ \ \ P \ P S S P S S P ] P ]P S S P S P \ \ P \UUTTUVUVTSTSP\P\ U V UV T ]T] P \P\\UVUVP\P\VUVUVPPV U !V!!U!!V T !|t!!T |t V,  "##$  $  X<$Y $9'~f g'W X<Y X.T.x$V X<Y y<.{~fgWX=[ u uYt.vt.Y.(f X<^ x..|$'f g$W X<JY 3.* YK .. +W. X<Y +.w&ff&gYY < fl < J < h.. X+JfX 0:Y yt..  9Y= ^"f g"s X=[t..U!/C ZVt YYfaX.! g!W X<YZKIL..xf..$ Y$W X<Y/ 9.w%~f X<Yt ..w%f g%W X<Y Y .b..w'of g'W X<Y Y .b..w%Bf g%W X<Y Y .b..w"f g"W X< Yw  Y  q..."Ng"WX<YY Y ..z..."h. g"W X<Y Y Y ..z...#~.#IY$ Y$W X<Y  zf.z$j g$W X<YJ .z.z%^fg%IK%;JXI J<$JK JJt."%2 g%W X<O / wY X<$XK XJ  ... $I. g$W X<Y (Y..p.(.w4Zr<otv$$\Xqtq<v lua_pushbooleanecp_newecp_affineecp_primeecp_negativepush_octet_to_hex_stringlua_newuserdataECP_BLS381_generatorecp_mulshort intsize_tECP_BLS381_isinfFP_BLS381ecp_isinf_fp_to_bigECP_BLS381_equalsBIG_384_29ECP_BLS381_subGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionecp_destroyo_argModulus_BLS381ecp_methodsluaL_Reglua_setmetatabledvalluaL_testudatazen_add_classecp_orderECP_BLS381_setxo_newluaopen_ecp_ecp_to_octetfloatfunclong long intecp_doubleluaL_argerrorluaL_checkudatalong intbig_initunsigned charecp_get_infinityPAIR_BLS381_G1mulecp_outputFP_BLS381_redcecp_octetecp_generatorECP_BLS381_negBIG_384_29_copywarningsigned charunsigned intbig_argdoublesizeECP_BLS381_fromOctetecp_classecp_get_xecp_get_y__func__short unsigned intecp_sublua_CFunctionoctetcharecp_argint32_tecp_dup_BoolECP_BLS381_addlua_settopECP_BLS381_PUBLIC_KEY_VALIDATElong unsigned intECP_BLS381_toOctetECP_BLS381_mapitECP_BLS381_infecp_mapitchunksizeecp_eq__int32_tECP_BLS381namelua_new_ecpECP_BLS381_dblecp_adderrorecp_validatetotlenbig_newECP_BLS381_copy__stack_chk_failBIG_384_29_rcopylerrorCURVE_Order_BLS381lua_getfieldhalflenlua_StateECP_BLS381_affine/home/alby/dev/Zenroom/meson../src/zen_ecp.c/home/alby/dev/Zenroom/meson../src/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits../lib/lua53/srcmilagro-crypto-c/include../src/zen_ecp.czen_ecp.cstddef.htypes.hstdint-intn.hlua.hlauxlib.hamcl.hbig_384_29.hfp_BLS381.hecp_BLS381.hzen_ecp.hzen_big.hzen_error.hpair_BLS381.hecdh_BLS381.hzen_octet.hlua_functions.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx (EDD0I FAC (HFFG0H FBE (tEDD0I FAC (FFG0` DBG (oEDD0z FAB 0FFD D0f  AABB (,oEDD0z FAB 8XFNA D(D@} (D ABBE 0qFLA G0q  DBBE eEL n CF 0FJA D0s  FBBF ( EID0D FAC 0LFAD G0  DABH 0FFD D0M  FABF 0FFD D0M  FABF 0FFD D0M  FABF 0FFD D0  AABI 8PFGD A(D@f (F ABBI 8FGD A(D@f (F ABBI @H r A (EID0Y FAF (FID0[ FBJ (<FEJ0K FBH 0hRFGA G0  FBBK 0FGD D0R  FBBG (EX FA   !. 9C8 N0Z0ohXs}H o   ( (  0  + 6 B JxU ]ph ph{  R       X 3h 0"?(.Z4R:@VFcKiQoWu]bhntz 3CK[hy"q (0e4FXi q@0 )5Czen_ecp.cecp_prime__func__.10ecp_validate__func__.9ecp_order__func__.3__func__.21ecp_generator__func__.5ecp_mapit__func__.4ecp_get_infinity__func__.1lua_new_ecp__func__.0__func__.19ecp_eq__func__.17ecp_isinf__func__.2__func__.20ecp_double__func__.13ecp_negative__func__.12ecp_affine__func__.11ecp_mul__func__.8ecp_sub__func__.7ecp_add__func__.6ecp_get_y__func__.16ecp_get_x__func__.15ecp_output__func__.18ecp_octet__func__.14.LC19.LC21.LC20.LC22.LC23.LC24.LC25.LC31.LC26.LC27.LC28.LC29.LC30.LC32.LC33.LC36.LC34.LC40.LC35.LC3.LC37.LC38.LC39.LC6.LC10.LC12.LC41.LC42.LC44.LC45.LC46big_newbig_init_GLOBAL_OFFSET_TABLE_Modulus_BLS381BIG_384_29_rcopylerror__stack_chk_failo_argECP_BLS381_PUBLIC_KEY_VALIDATElua_pushbooleanCURVE_Order_BLS381BIG_384_29_copyecp_newlua_newuserdatalua_getfieldlua_setmetatableECP_BLS381_generatorfuncECP_BLS381_mapitECP_BLS381_influaL_testudatabig_argECP_BLS381_setxECP_BLS381_fromOctetlua_settopwarningecp_argluaL_checkudataluaL_argerrorecp_destroyECP_BLS381_affineECP_BLS381_equalsECP_BLS381_isinfecp_dupECP_BLS381_copyECP_BLS381_dblECP_BLS381_negPAIR_BLS381_G1mulECP_BLS381_subECP_BLS381_add_fp_to_bigFP_BLS381_redc_ecp_to_octetECP_BLS381_toOcteto_newpush_octet_to_hex_stringluaopen_ecpzen_add_classactV)W9*Y>Zc/j7t[{\]^_/|7[\.V>WI*`Nas/4z7[\c8de/,9$[+\Nb_f/T7[\]:g;[$b9<AhMic/Dj7t[/D7[\bj/ 7[\)=Nk[btlm]b^&n>oE>O[c?mp/7[/7[jo @gA%[3/:7D[S/Z7d[|oBgC[\8r Ds\Rq{/7[\qquuv_;/B7L[[/b7l[v\qw_/$7[\# b9 yc /$j 7t [{ \ q x z / 7 [ / 7$ [+ \U qh xy { / 7 [ / 7 [ \ q x) uS /Z 7d [s /z 7 [ \ q l x |3 E= [K /tR 7\ [k /tr 7| [ /t 7 [ \ q q x }C /lJ 7T [c /lj 7t [ /l 7 [ \ q q x~C/dJ7T[c/dj7t[/d7[\\q$u,V7WCk/r7|[\quVW/7$[+\Vw\qw)o4?y/7[/7[/7[\Fq\o/7[/7[\FGHfIJKLMNO$PBQ`RSTU\ 0 ( 0c8@HPX `h px     t 1 5 6 6* 41 58 51A 5F 5` 5g 5n 5%u 5z 5x 5 5 58 58 5G 5 5 5 5M 5* 5Ro 5{ 5 5 5 5  5 50* 5W 5q 5g 5 5F 5Q 5 5 53 5NE 5 \ 5=s 5M 5 5c 5 5 5 5> 5/ 5J 5f 5x 5 5 5 5 5 5B 5: 5' 5'Z 5{ 5* 5 5 5 5 5k 5y& 5B 5#b 5 ~ 5S 5- 2 2  5f 54AK 5 2< 24 2f 2\ 5/ 2 2 3 2 2}%<I/Tq-8C # /- H U /_  5#  2 2 2 2 5 / " - B x7 D /N q 5z{  2 2  2F 2> 5 / 2i 2c  ( 0( ;@ G_ z  /  5p  2 2 2 2 5 / 2 2 & > V n  (  / / 5   2 2  2: 22 5 /- 2_1 2W6 JS `k s   /   /  59 5q(H 2L 2|Z 2^ 2c 5m/ 2 2 (PCP/Zpu/z 5x  2" 2 2L 2B 5/x 2| 2p$ 2( 2- J g  A  ` /x /x& AN/xX { 5`  2 2 2 2 5/ 2! 2  # ; Vc/m( //  5-0  2F 2> 2n 2f 5/ 2 2Y 7l U} m / /  5  2" 20 24 29 5C/pU 2Y 2g 2*k 2"p    X /px 3@/pJ er/p|  5  2O 2G 2w 2o 5/h 2 2 2 2 # @^|X/hx/h/h  5*J 2N 2\ 2` 2e 5o/(x/( 5 - 231 2+? 2[C 2SH 5R/e 2i 2xn  - h / /% 3 5<[ 2_ 2l 2p 2u 5/ 2 2/( 5]1P 2T 2a 22e 2(j 5t/H 2^ 2V  X( E( 2QPxkx/H/H 5  2 2{ 2 2 5/821BIRVq~/8 5 2 2 2 2 5/6C/Mp 5y0 2 2 2E 2= 5/XRc/X'J 5S r 2jv 2b 2 2 5/ 2 2 2 2 2  2  3  2C  29  2q  2g _x5Rqm w//R3  7 O *m B S  h   ! !)&! 0!HK!X!/b!h}!!/!!! !! 0"%" 5/"P" 2 T" 2 c" 2 g" 2 l""" 5" 5"/" 5" " 2 " 2 # 2 # 2 # 2 # 2 # 5&#/(/#' G#= e#x ##/(# # 5## 2> # 26 # 2f # 2^ # 2 # 2 $ 2 $ 2 $,$6$W$?a$!o$ 5$ 5$/0$$ 2 $ 2 $ 2 $ 2 $$% 2 % 2 %(%% 2%/0=%[%%%%/%0% 2 % 2 % 28 % 24 %x%x& 2I & 2G &7&D&/O&Vl&~&0& 2Y & 2Q & 2 & 2y &^&^& 2 & 2 & 2 & 2 &Z'+'9' 5=' 5 0" 6.& 6K* 6R. 6{2 66 6@ 6E 6J 6O 6T 6Y 6^ 6c 6h 6m 6&r 62w 6?| 6I 6S 6_ 6m 6{ 6 Lx00\ 0$P  0   T  @0l .symtab.strtab.shstrtab.rela.text.rela.data.bss.rodata.str1.1.rodata.str1.8.rodata.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@y+ 0 &@`1P62P E2`T08ahB'\@X8 mAC{D P0@(0 P"P @XX0ZT0`0a&aa  b@pf V sG /398 0 0 0 644 20312 ` ELF>H@@ATH5UHHdH%(HD$1HHHH<$u*HHD$dH+%(u9H1]A\H5IH$Lff.@HdH%(HD$1=HD$dH+%(uHUHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$HHH~`LuiH-HH1OHAH$HH$HD$HD$ D$0HD$HD$dH+%(uNH]ÐHH-IHOHLHH1A@LIUHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$HHHtx~VLH-HH1OHAHH$H$D$0HD$HD$ HD$HD$dH+%(uH]LfUSHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1HHHHLHH-IHOHLHH1AH$HH$HD$HD$ D$0HD$HHt ǀHHD$dH+%(uLH[]fH-HH1OHAjDHtLfAUATIUHHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1H$I1HD$HD$ LLHD$1$D$0HLLHHHHT$dH+%(u H]A\A]UHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$HHHtx~VLH-HH1OHAHH$H$D$0HD$HD$ HD$HD$dH+%(uH]LfUSHHT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1HHH~rLu~H-HH1OHAH$HH$HD$HD$ D$0HD$HHt ǀHD$dH+%(uQH[]HH-IHOHLHH1AiL4ZEN_traceback[!] %s[*]%s %s [*] %s [D] %s %s[!]%s %s [!] %s . %s %s[W]%s %s [W] %s   1:(MVff: int!"cA7!#2.;MRg2<sx.2=2f>.2$C %luaDEFHI . J .(K .0M8N .@O .HP .PRXS`TVWXZ A[ g\ ]:?_ H2  I2  J2  K2  L2  M2  N2 &ZP':O pfxQ  W ( S 2'-zG.2g-<}--2>-)B-2-2 C-a L-(2 arg ~prg UvT OQ RTUvT~ UvT OQ YT *act L-$2 arg ~prg {UvT OQ RTUvT~  L-&2 arg ~prg 8UvT OQ YTWUvT~ UvT OQ RT Q L 2 arg ~prg $UvT OQ RTCUvT~ I= L-'2 arg ~prg UvT OQ RT UvT~ / UvT OQ YT X8y onX 9 L9"-+w;= .P,>2} UvT g UvG1 UvQPO UvT 'x U2T Q4' U2T| . L.- fmt.&2/ ~ U0T|Q~8 UvT1] UvT|Q~z UvT2 Uv - D __sD__nD.. D7/I~I :!; 9 I8 H}: ; 9 I !I$ >  :!; 9 IB H} H} 4:!; 9! I? 4:!; 9 I.?: ; 9 'I<.?:!; 9!'@z:!; 9 IB4:!; 9! IB :!;!I8 'II4:!; 9 I!I/ 7I.?: ; 9 '<.?: ;9!'I<.?:!; 9!'I@z:! ; 9!I% I : ;  $ > !&I"&#<$ : ; 9 % : ; 9 I8 &4: ; 9 I?<'!I/(4: ; 9 I?<).?: ;9 '<*.?: ; 9 '@z+4: ; 9 I,4: ; 9 IB-.?: ; 9 'I.: ; 9 I/.?<ni UUUUUU TRTTYTTTZZ U U U U T R T T T XU U U U U UTY T T R T T T[ [UUUUTRTTTXUUUUUUTRTTYTTTZZUU)U)jVjmUmV?FPmP\ U V U V T \ T \,1k  % 8i%q YKxfa<Y2< &f4 '[ "ut<=eYz< "d-[ "ut<=e&Y"z3w\. g"u<#eY<X y#t<< y"Z 0teWeY-Y t.<1f[ "ut<=e&Y"}5v\. "ut<=eY<Xy< "d stdout_fulllua_settopzen_write_err_vawritezencode_lineluaL_whereshort intsize_tuserdatacolorANSI_GREENlong long intrandom_seedssize_tGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionstderr_poslua_tolstringsprintf_tANSI_YELLOWnoticeEXITCODEva_listfloatfuncformatANSI_CYAN__ssize_tstderr_bufANSI_MAGENTArandom_generatorfp_offsetgp_offsetsnprintfsprintfunsigned charzenroom_twarningsigned charvsprintf_trandom_externallua_errorunsigned intzstd_dargplong unsigned intstdout_lenshort unsigned intreg_save_arealua_gettopzencode_line_lencharlong intsnprintf_tvsnprintf_tvsnprintfANSI_REDvsprintfzstd_cerrorlevel__fmt__va_list_tagdebugleveloverflow_arg_area__builtin_va_listlua_pushvfstringstdout_posset_colorlua_concat__gnuc_va_listANSI_BLUEerrorzencode_tracebackANSI_RESET__stack_chk_faillerrorstderr_lenstdout_bufstderr_fulllua_Statelua_getglobal/home/alby/dev/Zenroom/meson../src/zen_error.c/home/alby/dev/Zenroom/meson../src/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits/usr/include../lib/lua53/src../src/zen_error.czen_error.cstddef.hstdarg.htypes.hunistd.hlua.hzenroom.hlauxlib.hstdio2.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx (FHG0R CBD H8H j A dIEG AB EG AA ,EAG7 AAJ 0FBD J  ABBA EG AA ,4aEAG AAD   P   %'*//;4C9W>KCUcn|8I(@@@0 1<FJaR ^huzen_error.cpfx.LC0.LC1.LC3.LC2.LC4.LC5.LC6.LC7.LC9.LC8zencode_tracebacklua_getgloballua_gettoplua_tolstringlua_settopwrite__stack_chk_failset_colornotice_GLOBAL_OFFSET_TABLE_Zzen_write_err_vaANSI_RESETANSI_GREENsnprintffuncANSI_REDEXITCODElerrorluaL_wherelua_pushvfstringlua_concatlua_erroractwarningANSI_YELLOWANSI_CYANANSI_MAGENTAANSI_BLUE  &.;Ox\*!"*#*$+*%5*!"3*%:*!*#*(J"c*)*%y'+,-.<*![e"*%?*!bmw"*#*1#*%-_djp x(0    * / P= oB N Mg "s }  ;  V   % F    q   " ) B ch  1   c + 7 pC O [ g Js    < 0  W      (( f3$< mG1P [4d o3x 2 #  `   ( (H Uh ~  L  _ ; " & + 5 \9 LV Z _}WK1   # ' D H MvkC| @ &   j Z   (/9NXv; @       '%D>R yWv 4z (  x h   " 0 9> {C c g l z      .   *  2 ?2 SP j y     %  M E j } 9 ^ {       " 0& M* T. }2 6 @ E J O T Y ^ c h m r %| Lh@@8.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rela.data.rel.local.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @1@,&q, P 12E 8@@2ZH U@83f$tm^0@ E0 @PE0>0\#.0$&$$ $`@G0& (+G/420 0 0 0 644 29928 ` ELF>m@@ATUHHdH%(HD$1IH|HذHH83AD$HfAD$H H5ID$1A$BLS3HD$dH+%(u'HL]A\fHH5H1ATUHSHdH%(HD$1IHt?HHHt_H{LHD$dH+%(u]H[]A\DHH5H1HHHuHH5H1AUHAATUHHdH%(HD$1IHt9AL$uLAL$ ujHD$dH+%(|HL]A\A]ÐHDHAL$tAH1E1HH5DA H1E1HH5pff.fUHHdH%(HD$1HtHD$dH+%(u%H1]DHH5Hff.ATUHSHdH%(HD$1HHt?HIHtJHsLHD$dH+%(uHH[]A\HH5H1fDHH5H1ATIUSHdH%(HD$1HHtOLHHtZHuH{LHD$dH+%(uMH[]A\DHH5L1fDHH5L1ATSHH(dH%(HD$1Ht5HsHxIHD$dH+%(u/H(L[A\DHH5H|$H|$@AUATUHSHdH%(HD$1IHt]HIHthLHHHtuIt$H{HD$dH+%(utH[]A\A]HH5H1fDHH5H1{HH5H1nff.ATIUSHdH%(HD$1HHt?HLHHtLHsH}HD$dH+%(uIH[]A\ÐHH5L1fDHH5L1ATIUSHdH%(HD$1HHt?HLHHtLHsH}HD$dH+%(uIH[]A\ÐHH5L1fDHH5L1AUATIUSHdH%(HD$1IHt]LHHthLLHHtuHuH{HD$dH+%(uuH[]A\A]HH5L1fDHH5L1{HH5L1nff.H8H HdH%(H$(HH=H5aHL$H$H ]LHT$8LL H|$PLHt$XH$H$HHD$HD$HH$H=H$H5H$H H$HHD$(HD$xH$HH$H=H$HT$pL\$ LT$0LL$@LD$HHD$`HD$hL\$pL$L$L$H$H$HH$HH$H$HH$HDŽ$HDŽ$H$(dH+%(u H8Error allocating new fp12 in %s%s: fp12 size mismatch (%u != %u)%s: fp12 chunk size mismatch (%u != %u)zenroom.fp12new fp12 (%u bytes)NULL variable in %sfp12 class expectednewocteteqmulsqrinvpow__mul__eq__gc__powfp12fp12_from_octetfp12_eqfp12_mulfp12_sqrfp12_invfp12_to_octetfp12_powfp12_destroyfp12_dupfp12_argfp12_new\    .int Q    )Q   y7 h Q   ! "  C.slen Qmax Qval C :. < &g (XES ) 8 *x $a &b '< ( %a 'b (x ) $Xa &b '!c (" ) Q *03lenQQval   "r( #big#d 3lenQQvalX --2 X s2RQ iQ T Q-- -- v -- -- 2-2X  -*--Q  !NNN ' A j--.QQA<Q #<$QQQQQ<5EQL}~2U T}Q~K. . {QL{ s| . d}kU|T1U|TsUvTsU|T Q  U|T Q K .. uQdLu sv . dwU|T1U|TsUvTs$U|T Q VU|T Q KmQ Lm xn . bo-rpUvT1 UvT23 UvT}K Us} UvT Q  UvT Q  UvT Q KeQ Le xf . ygdh U|T1 U|T2 U|T} UsTv U|T Q @ U|T Q r U|T Q K]Q L]l^ r_res`Q U|T13 U|T2iQ UsTvRi U| U|T Q  U|T Q K . VQ"LV%fW 2 oX 2s UvT1 UvT  U|Ts UvT Q UvT Q K2. "OQzLO'oP 2  fQ7UvT1UvUsT|"UvT Q :UvlUvT Q K. z%GQ&LG  'cI. @|L@s@$ . nBSoU|TsUHT Q K2L2n2!Qud3<o5 . TUvT}Q jUvT}Q UvT Q X UvT Q X K$_L$c% . (_+zpUvT UvT}Q UvT UvT Q QUvT Q K)MMM*eK+,G -.UvT Q =UvT1K/0 BLS383I~H}I4:!; 9 IB : ; 9 I8 : ; 9 I:!; 9 IBH} &I 4I4 $ >   !I .?: ; 9 '<I!I/ .?: ; 9 'I< : ; 9 I8 .:!; 9! 'I@z : ; 9! .?:!; 9 'I@z1B7I : ; 9! 4:!; 9!I:!; 9!I%  $ > <'I  : ; 9 ! : ; 9 I8" : ; 9 I8#: ; 9 I$.?: ;9 'I<%.?: ; 9 'I &: ; 9 I'4: ; 9 I(1RB UX Y W ).?: ; 9 'I 4*.1@z+41B,1RB X Y W -41.H}/.?<n06VUU U \ U \ P S P S P V P V U \ U \ P S PS P VPV U V U V P ] P ] P \ P \ P S P SU\U\P]P]PVPVPSPSU\U\PSPSPVPVPUVUVPSPSP\P\UVUVP\P\PSPS U U U H U T S T S P \ P \UVUVT]T]P\P\\P\\\'U'VUV+GPG\P\U`U`\UVUVPPV, U`ci  #gWX==" ] !<_f V rZ !._Yt.w<.Y 6*fg*WX<Y <Y .b.Y .w$^f g$s X=YXX\Jw.!X ;/ v ;/ Z    Z Vt YZfzfX.(  g(W X<Y %Y ..%.w"h g"W X<Y Y  ;/Y .a..x']fY Y =Yt.btx#( g#W X<Y Y Y ..}...#6 g#W X<Y Y .*..w#uf g#W X<Y Y .*..w#kf g#W X<Y Y Y ..... .-z+zz<^ u< ut oX& zY%size_ttypefp12_to_octetFP12_BLS381_toOctet__srcfp12_destroydvallua_newuserdataFP12_BLS381_sqrFP_BLS381long long intsigned charFP12_BLS381FP12_BLS381_equalsluaopen_fp12long intlua_CFunctionluaL_argerrorfp12_eqfp12_classunsigned intchunksizelong unsigned intnamefp12_sqrshort unsigned intzen_add_classo_newGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectiono_argstrcpylua_setmetatablelua_getfieldfp12_from_octetluaL_RegFP12_BLS381_fromOctetFP2_BLS381__destFP12_BLS381_invFP12_BLS381_copyfp12lua_Statefloatfp12_duplua_pushbooleanfp12_methodsint32_tunsigned chardoublesizefp12_powshort intlerror__func__fp12_new__stack_chk_failFP12_BLS381_mulfp12_argPAIR_BLS381_GTpowcharfuncbig_arg__int32_tBIG_384_29luaL_checkudataoctetFP4_BLS381fp12_invfp12_mul/home/alby/dev/Zenroom/meson../src/zen_fp12.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include../lib/lua53/srcmilagro-crypto-c/include../src/zen_fp12.czen_fp12.cstring_fortified.hstddef.htypes.hstdint-intn.hlua.hlauxlib.hamcl.hbig_384_29.hfp_BLS381.hfp2_BLS381.hfp4_BLS381.hfp12_BLS381.hzen_big.hzen_fp12.hzen_octet.hzen_big_factory.hlua_functions.hzen_error.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx (FFG0 DBC 0HFFD D0M  FABF 0|FLA G0L  DBBB eEL n CF 0FFD D0R  FABA 0FIA D0]  FABF (<|FAG@~ DBF 8hFGA D(D@g (F ABBH 0FIA D0Q  FABB 0FIA D0Q  FABB 8 FGD A(D@f (F ABBI HK A   (3 >h IWHbjux X 8 ( @    !5 HMI^SVZfb l&|,q2v8AQ^ot{e `|"3;M]m}@zen_fp12.c__func__.10fp12_from_octet__func__.0__func__.9__func__.7fp12_to_octet__func__.5fp12_eq__func__.1__func__.8fp12_pow__func__.6fp12_inv__func__.4fp12_sqr__func__.3fp12_mul__func__.2.LC1.LC2.LC0.LC3.LC4.LC5.LC6.LC8.LC7.LC12.LC9.LC10.LC11.LC14.LC13.LC15.LC18.LC16.LC17fp12_newlua_newuserdatalua_getfieldlua_setmetatablefunclerror__stack_chk_failo_argFP12_BLS381_fromOctetfp12_argluaL_checkudataluaL_argerrorfp12_destroyo_newFP12_BLS381_toOctetFP12_BLS381_equalslua_pushbooleanfp12_dupFP12_BLS381_copybig_argPAIR_BLS381_GTpowFP12_BLS381_invFP12_BLS381_sqrFP12_BLS381_mulluaopen_fp12_GLOBAL_OFFSET_TABLE_zen_add_class$37D4Q5{ 6!7892:CJ"T7\2sz"78<#=18$=7Y`%e7o8;d"78;*?>@cDj"t7D"78;;AB# *"47C J"T7[82Dt"78;E/CEFsTz"7T"7T"78;C-GS4Z"d7s4z"78;CH$ "7#$*"47;8g;|;CI"7"7"$7.8N&m't()*+,- .> / 0 *> 1 L 8  L  * 1 8 A F ` g %n ~u z f T      >   Y >/ pt  p f ] J Y m   A      G8 S j  ) V o  F B ^3 8T k  { Y  !  F6 @@_ c  h v  |   * "" R& J+ 58F wJ oO l1h!8!8 4 =\ ` m q v (  !(%8@!M(W?e n   6 . X [ S  x   34 IL g !t X~  ! X  ! X   @  ) - 2 < M Q ^ b g k     !  * !7 A (\ !i s 2   < 4 d \        4 R j 8 !  X !  _    * . 3 = HN R W t . B x ! H  ! H8 .A` *d "q Ru Jz  w o X !#`;V!cm 4 h `     ! +x< @ ERp!x 9   F > p f   !*KUv5A iHs  ( , 9 = B LYUb  r v    (HU ;HR`  q h{ .   A = R P !h!>L P  T " /& L* S. v2 6 @ E J O T Y  ^ c h (m /r <w H| U b p z     L @`l@L@.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.8.rodata.str1.1.rodata.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @ @? &Y ,Y 12` p@2 O` \ `W@Kha {.#Zv@h (0@h0 ((@(i0-010P3&v3x3  3h@k 682 8=l/441 0 0 0 644 54536 ` ELF>@@HdH%(HD$G8ubHD$dH+%(;HvH(HD= = uVHD$dH+%(HvH8HHD$dH+%(HvHHf=HD$dH+%(HvHHHHD$dH+%(u}HvH@HHD$dH+%(uUHvH HHD$dH+%(u-HvH0HHD$dH+%(uHff.ATUHSHHdH%(HD$GPyuLE1~#HSIcH}(A4D9#HD$dH+%(fH[]A\uۋ~E1f.HSIcH}A4D9#멐= ty= u:DE1E~HSIcH}8A4D9#ffD=UHD$dH+%(HvHHH[]A\f>E1HSIcH}0A4D9#fD6E1HSIcH}@A4D9#fDE1HSIcH} A4D9#fAW1ҾAVAUATUHSH8dH%(H$(1IHE1ҾHIHJLL|$ LI1H|$0LHc1fMcHH|$(HHmnemonic)D$ HD$ LLLHHD$Dd$D$$Dc McLLLHHD$@H\$Dd$HT$HA@HI@@H|$H|$H$(dH+%(uSH8[]A\A]A^A_HHHHf.AUIATUHPH dH%(HD$1IHHذLLID$ID$ ID$(HHHH5HFH5HH5HH5HbH5H H5H  H5H.HLHID$ID$HHHIHtILLHD$dH+%(uHH1]A\A]fHH5H1fDHH5H1AUIATUSHdH%(HD$1HHtmLIHtxsLHHLHHH[CEHD$dH+%(urH[]A\A]DHH5L1vHH5L1kHH5L1bff.AWAVAUATUHSH(dH%(HD$1IHHIHdHHHHHA$HD$AŋHpIHIHcHsDHAIHA~L$ELLHD$dH+%(aH([]A\A]A^A_HHHHHHHHHHA$HD$A@HH5H1HH5H1HD$HH1H5LL$HH5H1HH5H1&HH5H1ff.ATUHSH dH%(HD$1HHt_HIHtjCHpIHtt{1LHD$dH+%(u|H []A\HH5H1fDHH5H1yHD$HH1H5LD$e@AUATUHSH(dH%(HD$1HH!HIH(HIH/CtuBAHIHA@LL@ DH5H11HT$dH+%(HH([]A\A]fD!HIH LL u H5H1H1HX@HH5H1HH5H1HH5H1@H5Hg@HD$HH1H5LD$fHD$HH1H5LD$@ATIUSHdH%(HD$1HHtGsLHHtTHHCEHD$dH+%(uMH[]A\DHH5L1fDHH5L1fAVL3L5SHHH=H5LL HhLH dH%(H$XHH\$H$HH$HH$H"H$HH$HDH$HyHD$HL\$Lt$pL5L$L}H$HHT$8H|$@HT$HHt$PHD$XHD$hLT$ LL$(LD$0HL$`Lt$xHDŽ$HDŽ$L$H$L$H$H$(HH$0HH$H$H=H$H$H$HH$8L$L$L$H$ HDŽ$@HDŽ$HH$XdH+%(uHh[A^string expectedzenroom.hashsha256sha384sha512sha3_256sha3_512keccak256ripemd160Hash algorithm not known: %sNULL variable in %snew hash type %shash class expectedsaltiterationslength%s: hmac (%u bytes) failed.newoctethmackdf2kdfpbkdf2pbkdfmnemonic_seedprocessfeedyelddo__gchashError allocating new hash generator in %sHMAC is only supported for hash SHA256 or SHA512lua_new_hashhash_to_octethash_hmachash_kdf2hash_pbkdf2hash_processhash_feedhash_yeldhash_destroyhash_new&* :+H&O,intw*A-:  -d%lG& I&hJ6wKF(&Lwh6:F:V:OM%Q ShTwUP&Vw:::OWb[!_ aSb c wlend w3::eO:!len wmax wval O7.\wh /w   .0    !" -!P * +? ,wlen -w .  /  0 ( 10 28 3@ 4H V   3 ! 6- #H 1w1wHw $` > www  K ww 7w ww * H V .www" HE.'wT".k w= ! w  w  w  w 'w> > V n       ~! H .w$w AHDw< V nw       . x w."ww ww w5 HP.1w.L} ~U T}Q~& :  :  kw Lk(lorwsw'w u }z}} &v &&&&wz &2&&&U}QsR &| &&&&T}Q~&/ &&&&T}Q}kQ UvT1Q0ks UvT2Q0T U}E U~T . U~. U} UvT@1 U@T}Q}R X@Ysu UvT1Q  UvT2Q & 3: FwLF#hG kH IwI wsJ ssJ out_ &] &&&&a UvT1 UvT2-UvT3 JUvT3nUvT4Q UvT5UvUvT}T|QRX}UvT3Q BUvT3Q lUvT3Q  UvT UvT Q UvT UvT Q 1UvT Q cUvT Q UvT Q UvT Q UvT Q & :   -wL-!h. in/ out1 aUvT1 UvT2UvT|Q0AUvT Q sUvT Q UvT Q &:  w,L!h k in out avUvT1 UvT2 UvT3UvTA`U@T|Q}R@UvT ;UvT!`eU T|Q}R H1UvT UvT0UvT Q UvT Q CUvT Q uUvT Q UvT Q &wL! h  res a:U|T1RU|pUsTvU|T Q U|T Q &wL! h  o aeUvT1 UvT2U|T}UvT Q UvT Q &wL$ h  o  res aU}T1 U}T2U}UsT|UsTvKU}T Q }U}T Q U}T Q &: wL% h  res aWU|T1oU|UsTvU|T Q U|T Q &: (ho#nV'>V&(sho# iw&wL$4 h  UvT1Q R0+)UvT|TUvT Q|UvT Q &#waL h aUvT1FUvT Q &#q+Ln"w udH h$UvT}Q UvT}Q &#KG&LK5K*W&  hM6htS?@\&U ~&t&j&&U@TvQ?\&|y ~&t&j&&U|TvQ?\&^ ~&t&j&&U|TvQ?\&XO!~&t&j&&U|TvQ?\&0V!~&t&j&\&j"~&t&j&&U|TvQ?\&dq"~&t&j&&U|TvQ?\&p"~&t&j&&U|TvQ?\&vG#~&t&j&&U|TvQ?5e#U}TP#U}T}Q #U}T #UvT Q6$UvT Q6/$UvT Q6Y$UvT Q7$UvT Q7$UvT Q9$UvT Q9$UDD%U :%U l_%UV%U n%U}T Q %UV&UV9&U}T Qv&W&:G&)\&\\\.)H&J.78 mnemonic$$$I~H}I1BH}: ; 9 II!I/  !I : ; 9 I8 4:!; 9 IB .?: ; 9 'I< .?: ;9 '<:!; 9 IB4:!;9 IB&I.?: ; 9 '<H}$ >  : ; 9 I8 4I41RB X!Y W H}4:!;9 IB:!; 9!I:!;9 IB4:!;9 I1RB UX!YW!.:!; 9! 'I@z7I .:!;9! 'I@z! : ; 9! ".?: ;9 'I<#.?:!; 9 'I@z$.?<n:!;!% :!; 9! & :!; 9! I8'.?:!;!9!I<(.:!; 9! '@z).?:!; 9!'I !4*% + ,$ > -&.</'I0 : ; 9 1.?: ;9 'I@z213!I/44: ; 9 IB5: ; 9 IB64: ; 9 I7.?<n86 ''U'+UU V U VP] P ]P^T P ^\} ^ ^S sx |t }t |t P S S8} s $ &}^]P ] } PUVUVP^^P^P\\P\\PPP]P]]PSPSSPSPSP_P__PPY s $ &QsU V U !V P S P !S P \ !P!!\ P!!P!!X!!H!!U!#V##U#$V$$U$%V!"P"#S#$S$$P$%S""P"#]#$]$$P$%]""P"#\#$\$$P$%\""P##P%%P%%X%%%%P%%X%%U\U\PSPSPVPVUVUVP\P\P]P]U]U]PSPSP\P\PVPV&&U&&\&&U&'\&&P&&S&'P''S&&P&&V''P''VJUJSUSUUUUUUUUUUUUUUFTFSTSTTTTTTTTTTTTTTUVUUVUVUVUUVUVUVTSTSTS0\|\0\|\0\|\0\|\0\|\0\|\UVUVP\\PPUVUVPSSPSUVUVT]T]P\P\\ U ]U] T VTV P \\P\ ? V @ ? V \ ? V \?V\? @?V\?V\?V\?V\,I   &  KtPzJ%tNFatRxJstLHW<MG<QyJ<OE& h .<&tF&t"J&J" wfYf&F&t"J&J"<<(G(t$J(J$X ,q.<(G(t$J(J$#.#<0P0t,J0J,#.<&F&t"J&J"+g+s /X=! }<XY= v}< >l z<}<>} }XX} X }f<Y} XYN+L:< }f <Y} XzK ]Y=! h ...[f<<"X4} 4VJ X== &0 x<   <   <   <   <   <   <`  W XY=^  W XY=$XJR z W XY=z 0 r   WYWY=vx  W XY=g.Y  l  WYWY=f  WYWY= = <Z'<g'Ղ Ye= #XYY.#GY0%j g%s X=[t..U!/ > Y W X<Y<Z Zf F.$ g$W X<Y Y g .yf. .y$h g$W X<Y Yf..7..x'hf g'W X<Y Y  g ..xf.. .&. g&W X<    " L X@.} J }< / e=!Y ....h ===  ! K X<u..![h...$H. g$W X<YZ&Y .z..&Z$Ng$WX<< ` Y J   1 ..lt JKYm....tU.xX( g(W X<Y Y g .a. .x h "J Hv +vK (v ONqtqq<@Y(strlenlerrorhashtypeSHA3_processhash384unsigned intHASH256_initstrnlenhash_yeldhash_processsha512o_argocteterrorfuncRMD160_processhlen__builtin_memcpymnemoniclenSHA3_hashmnemoniclua_tolstringmnemonic_to_seeduint32_tsha256rmd160floatluaL_Regmalloc__lenalgostrncpySHA3_initsha3_512GNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionHASH384_processluaopen_hashosalt__destlua_getfieldAMCL_HMACHASH256_processlua_Statesize_t__memcpy_chksha3_256free__uint64_tdwordlua_new_hashhash512hash_pbkdf2keylencharHASH512_hashratelua_CFunctionlua_settopluaL_optlstringlua_setmetatableo_newKDF2uint8_tRMD160_hashhash256sha3saltKECCAK_hashlong long intHASH512_init__builtin___memcpy_chkhash_argRMD160_init_feedomnemonicluaL_argerrorstrncasecmphash_kdf2hash_methodsshort intlong int__builtin_strncpyhashlengthhash_feed__stack_chk_failuint64_tHASH512_processlua_newuserdata__uint8_tnamehash_hmaczen_memory_alloclong unsigned intsha384okeyluaL_checkudatakeccak256PBKDF2unsigned char__uint32_t__srczen_add_classhash_newluaL_optintegerhash_destroyHASH384_hashiter_yeldlua_typepassphrasesigned charlua_Integerhash_to_octetshort unsigned intmemcpy__func__hash_classlua_pushbooleanHASH384_initpassphraselenzen_memory_freeHASH256_hash/home/alby/dev/Zenroom/meson../src/zen_hash.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/includemilagro-crypto-c/include../lib/lua53/src../lib/milagro-crypto-c/include/usr/include../src/zen_hash.czen_hash.cstring_fortified.hstddef.htypes.hstdint-uintn.hamcl.hlua.hlauxlib.hrmd160.hzen_hash.hzen_error.hecdh_support.hstdlib.hstring.hzen_octet.hlua_functions.hzen_memory.hstrings.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx DD J J r F i G k E \ L \ L \ L T A @dBAD G0r  AABD   AABG LFIB B(A0D8GV 8F0A(B BBBD 0FEA L@  DBBJ (,FOG0P FBD 0XqFLA G0q  DBBE (EID0~ CAD 0FIA D0U  FABF 0FGA G0Q  CBBC 8 FJA A(D@y (F ABBF H\FGB B(A0D8D` 8F0A(B BBBA 0FFD D@k  FABH 8,FGA D(DP (A ABBG 0FIA D0U  FABF ,L.FOq FBA Od  ( 5 @ K Up ` j` u0 P @ @ 0 ,   $+2; DNX%u+17=C0IOU[agmsy!&). *9IW^fszP(5<LQ qZj w.zen_hash.cmnemonic_to_seed__func__.9lua_new_hash__func__.0__func__.8hash_yeld__func__.7hash_feed__func__.6hash_process__func__.5hash_pbkdf2__func__.4hash_kdf2__func__.3hash_hmac__func__.2hash_to_octet__func__.1.LC0.LC2.LC3.LC4.LC5.LC6.LC7.LC8.LC9.LC1.LC10.LC12.LC11.LC13.LC14.LC15.LC16.LC18.LC17.LC26.LC20.LC23.LC24.LC21.LC22.LC25.LC19.LC27.LC28.LC29.LC30.LC31.LC32HASH512_hashSHA3_hashHASH256_hashRMD160_hashKECCAK_hashHASH384_hash__stack_chk_failHASH512_processHASH256_processSHA3_processRMD160_processHASH384_processlua_tolstringstrlenstrnlen__memcpy_chkmallocmemcpyo_newPBKDF2luaL_argerrorhash_newlua_newuserdatalua_getfieldlua_setmetatablestrncpystrncasecmpzen_memory_allocRMD160_initHASH384_initHASH256_initSHA3_initHASH512_initlerrorluaL_optlstringfunchash_argluaL_checkudatahash_destroyzen_memory_freeo_arglua_typeluaL_optintegerAMCL_HMAClua_settoplua_pushbooleanluaopen_hash_GLOBAL_OFFSET_TABLE_zen_add_class~IJDKLL,LdNsIOOPQ;RCSVTqSTUVWW "X+"8XBIyZ#[\]$^% ^&&^:'B^V(^^r)z^*^]_`]_aL]e_rb]_c]_"d3:+De\]u_c]_c,eI $- f; YJ -T g{  . e I # i / X IC h} k | . e k I h U; lB .L e[ lb .l es I h l \ . e \ .$ e+ IW hl l U L . e L . e L .$ e. Ik h l m l n n UT"UDVs0[1[2[lnn<. e<".,e@<L.Qec<j.te<.e<.eIh l U7oc,j.te,.e,.eIhl)lOUpp3eUp4qrs+2.<eKR.\ekr.|e4.e.eI%h8U{ .e .eI56789 :;(<<=K>i?@<AK*jbBvIOCDEF G5H]DM  9 ! !* / K= [D ,R Y ?` e 1s    m  4    W k    $  4  r A A  %   ; ~ " x6 ;C ] j mw e _ 0    ~  m2 I xa '    h / F FU l      1  l( ? (W o       % yE oW &o B } 9 J    6 !Q ]}    b .  5 *9 "> I RM JR ] ya of q u z    F #   t   &    # ! 2 0% :. = ?A =O QS OX ? U , ^ \ h f r p Z  7 | z     0 R t   G u  2 ? L l v <  F  @     Y @ $ ) 4 48 (= H qL gZ ^ m q     B @ < [ Y f d  o   . K o  &H9Ccmu@0u(@2UMuZ@dxu@u@u@" ,L wP o^ b g Yq0    $;x+u80B]uj0tu0 @   K  A Y * y. o= A Q U Zw-St0<fs@u `u -u: D_ul vu  N     H @ Yp m e ; S qP upp upw        % Y/`@ D I f   u`( u`/  X0 ; ? L ,P $U Y_Pp Qt I v n[ p     5uBPL gutP~( uP2  1      Y2 6 ;)X<pOuu 9 %= J N SS`mz9a { m M   Q  ! H%2?L0Yhfwt ~}       :  4  T  P  Y1  ? *X EU pu}    k  c      YG   0u=G T b fl              0  .    , 6PU @ Y 8 ^ i h m ` r Y|                  7  ;  D  H  Q  U  Z ~          @ @ !  !  ! " !  '! , +! * 0!PT!]!x! 6 |! 4 ! A ! ? ! T ! R !!! ` ! ^ ! k ! i ! u ! s ! ""/"  3" } <"  @"  I"  M"  R"v"P"P"  "  "  "  "  "  "`""#  #  #  #  #  ##  (#H#}f#######$$*!$+0$FK$2Z$bu$;$~$D$$N$$$ %"%i;%vH%`%m%%&%H%%%y%%&&*&X:&]& k& u& & & R& & & & & & R& O& R& & & * &H  " !/& !L* !S. !v2 !6 !: !> !H !M !R !W !&\ !/a !7f !Fk !Mp !Su !]z !f !q !} ! ! ! ! ! ! != hP0 \    $0 `@ P.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.str1.8.rodata.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@Xw&.,.12.3@2haO\i&W@؍:hQ?{B v@X0 O0@0 OM3P @0\0b0kd&dd  dx@h0h( C Xs/462 0 0 0 644 49744 ` ELF>P@@ HdH%(HD$1HD$dH+%(u1HAUATIUSHL-dH%(HD$1I]H{LHHHc;LHHKHcUAIEHuLcHxLH5E1Hc}u"HD$dH+%(uxH[]A\A]fHc}HHHH81LDHH5L1+HCDAUATIUSHL-dH%(HD$1I]H{LHHEL4@HHIEHMHcSHsHxLcELH5U1Hc;u%HD$dH+%(H[]A\A]ÐHc;HHHH81LfDHH5L1EHCf.HH5L1ff.AUAATIUHHdH%(HD$1DHE11ɺHLHIHt"HD$dH+%(u%HL]A\A]DH5H1AVIAUIATUSHHdH%(HD$1HHHx8HtnHxPHh@H+hHLLHxHHAąHA9uIcHPHEt)HD$dH+%( HD[]A\A]A^DHD$dH+%(HLLH8H[]A\A]A^fDH8H1DH5HHhHH@PgDHHHH8AąBHH8H51E1A8H5HHH81HAVIAUIATUSHHdH%(HD$1HHHxHtnHx0Hh H+h(LLHx(HAąHA9uIcHP(Et)HD$dH+%( HD[]A\A]A^DHD$dH+%(HLLH8H[]A\A]A^fDH8H1DH5HHh(H@0gDHHHH8AąBHH8H51E1A8H5HHH81HHHt$(HT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1H$H$HD$HD$ D$0HD$HT$dH+%(uHfDAWAVAUATUHSHHdH%(HD$1HHt@E1Hx8t HH@H9HHrLHD$dH+%(HD[]A\A]A^A_fDHH5HHIH5HL=AL5E*QfL1HA9|)LHD HƃL1A!AWAVAUATUHSHdH%(HD$1t*HD$dH+%(H1[]A\A]A^A_DHH$H5HAEIHLAoIEuEHA9|RLHEIǃ~ѺH5EtH$LE1Hc$H9A뚐H5AWAVAUATUHSHdH%(HD$1vt*HD$dH+%(H1[]A\A]A^A_DHH$H5HAH5EIHLA)IEuEHA9|TLHIǃ~ѺH5EtH$LE1Hc$H9AH5AWAVAUATUHSHdH%(HD$1&t*HD$dH+%(H1[]A\A]A^A_DHH$H5HAH5EIHLAIEuEHA9|TLHIǃ~ѺH5EtH$LE1Hc$H9AH5HHt$(HT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$dH%(HD$1H$H$HD$HD$ D$0HD$HT$dH+%(uHfDAWAVAUATAUHSHHdH%(HD$1HHt=E1Hxt HH H9H(rIHD$dH+%(HD[]A\A]A^A_HH5HHEIH5HL=AE%L@L1HA9|)LHDHƃH=1ÐA,U HSHdH%(HD$1A1EtHT$dH+%(uYH[]HHHtHcHs9HH5H1AW AVAUATUHSHdH%(HD$1t-HD$dH+%(H1[]A\A]A^A_HH$H5HAEIHLAIEuEHA9|ZLHIǃ~ѺH5EtH$LE1Hc$H9AfH5UH5HHdH%(HD$11H5HHH5H1H5HHD$dH+%(uHH]NULL variable in %soctet compressed: %u -> %uZSTD error: %s octet uncompressed: %u -> %utostring %s%c%s%c [W] . _Giowriteprintprinterrzen_fatalwarnactcompressdecompress'tostring' must return a string to 'print'Error buffer full, log message lostFatal error writing error buffer: %sError buffer too small, log truncated: %u bytes (max %u)Output buffer full, result data lostFatal error writing output buffer: %sOutput buffer too small, data truncated: %u bytes (max %u)lua_print_stdout_tobufzen_writelua_print_stderr_tobufzen_zstd_decompresszen_zstd_compress$<  : (M=Vff:>!!!!?@int    ,136 7 8 9 : (; 0< 8= @@ HA PB XD`FhHpItJ xMNOQY [\]^ _ .`b A+  :   : -) )   cA ;1 6KK -K <a f.K = K f > .K. C"lua D E F H I .  J .( K .0 M8 N .@ O .H P .P RX S` T V W X Z % [ U \  ]:? _ B W 79 b! h] bqq - m qE .."len "max "val  ,  K!Q " + <CZ3K )4 DxqK Kq/ qEv q0 z .  q $qc@q@  `qK ... 0#/ q ] P K. .#K .BB.. # nnq  .. qK nq#B ` P0 #%  $1 qKDBu *LBq1D 1S E UvT $ UvT Q0  UvT E UvT $H UvT Q0E g UUT $  :u   : 2/b *L/$q$src0 n$dst0n res1 . 3<l  T1Q =  U| U|T1S U|` U|T f U|T Q  U|T Q $ : 2;*L"q$dst n$srcn  3)  T1Q *  U| U|T1sSU|GQU|T U|T Q $:L!qBL q% len . n i w  sKL!q% len . n i w  sKL"q o n   res w: ZL$q% len . n i w  sKL"q% len . n i w  sK45Lq6 # inlen .sK#:45Lq6 # inlen .sKFKL0qposlensKUvT ,UvT}XUvT1Q1R0X0x|UvT Q|\UvT $&+fmtK6arg~len .T~$&fmtK6arg~len .T~$&bfmtb"Kvab/resc7maxj .8;TvQ}R~ fT Q|Rv T    T 9|:T1QURT'd T1Q}R~$&6fmt6"Kva6/res77maxE .8(TvQ}R~ ST Q|Rv rT    T 9\:T1QURT'?s T1Q}R~$;P1;ggg'( z!>6IJ]^gp{ UvE UvT !U 2!UvT V!UvTsQ~ U Q|!T Q $"J "a"UvT1x"U1 UvT Q ("UvT $Z@$is~Z $is~(?$#UvTsQ #UvT #UvTsQ~%$U1T Q1 U1TW$UvE|$UvT  U1T Q1($UvT:$KI~IH} : ; 9 I8 1BH}4141B  !I 4:!;9 I : ; 9 I H} .?: ; 9 'I<$ > I!I/ &I:!; 9 IB4:!; 9 I.1@z1RB X!YW : ; 9 I4:!; 9 IB<'I.:!;9! 'I !:!;9 I 41.?: ; 9 '< 4I4! :!;!I8 " : ; 9 I8 #.?: ; 9 'I<$4:!;9 IB%4:!;9!I&.?:!; 9!'I@z'1RB X!Y W ( 1U)4: ; 9 I?<*:!;9 IB+I~, : ; 9 -7I. : ; 9! /.?: ;9 '<0.?: ;9 'I<14:!;9!I2.?:!;9!'I@z31RB UX!YW!4.:!; 9! 'I !5:!; 9!.I64:!; 9! I7 U8H}91RB UX!Y W!:H};.?:!; 9!'I !4<% =I> : ; ? @$ > A: ; 9 B&C4: ; 9 I?<D.?: ;9 '@zEH}F.: ; 9 'I@zG1 H 1I UJ 1UK.?<nf  !U!!V!!U!!U!!VU\U\U\PVVPVPSSPSS pU\@wUw\U\U\PVVVPSSPSS pU\UVUVT]T]Q\QP\P\UU p $ & UU p $ & U ] U ] Q U ] U ] T ^ T ^ R T ^ T ^ 0 P \ \ 0 P \ P \ V V V ^ R T ] Q U p T R ^ U Q ] pU]U]QU ] U ]T^T^RT ^ T ^0P\ \ 0 P \ P \V V V^RT]QUp T R ^ U Q ] pU9UUVUUV:V1SsSP\PTPTUVUVV1]P\1SPP_UVUVV1]P\1SPP_UVUVV1]P\1SPP_UVUUVTTTT\Q\Q\UV1SsSP]PTPTUVUVVVPSPSs $p $.PUVU V V1 ]P \1 SP P _,         i   $ Y%#%rJ  X!J @ *2uN .T ||< tXX m t.X ''qJ  #J 1 91uN .F ||< tXX Z .X/. |.ZVYg/\t..cZ /3X X3wt< JY  \ ;]t\. b( Y֞ '.Ig=I m t<X<< ;Y `C Zd <  X3Z3r< JY  \ ;]t X. sf ؞ ,ng=I m  t<X<^< ;Y `D Zd <  X)_;Y  7 s p<tn/   @ ~[ wt=pYX[zBzXYV=[XX['JXJ l  ; Z =Y Yz<lZyCyX YYYY=&XIYX$ XJXJ k  ; Z =YY Yx<nZyCyX YYYY=%XIYX#JXJ k  ; Z =YY Yx<nZyCyX YYYY=%XIYX)}_;Y? =?s p<tnY t   ~[ yt=YX[zBzXY:=[X?%XY%WXX_X x YX<*.t%Jfg%WXJ l  ; Z =Y Yz<l ZyCyX Y Y YY=&XI$YXX Xstt YIXstdout_poszenroom_t_shortbuflua_fatal_IO_lock_tgp_offsetZSTD_createCCtxstderr_IO_buf_endlerrorvsprintf_tEXITCODEzen_write_IO_write_endunsigned intlua_gettop_freeres_list_flagsstrerror_markersstderr_lencustom_iowritezen_write_erro_argocteterrorfuncluaL_errorzen_write_outstdout_fulllua_tolstringstderr_bufstdoutsprintf_t_IO_save_endfloatzstd_czstd_d_IO_codecvtsnprintf_tzen_actoverflow_arg_areazen_warnGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection_IO_backup_base_offsetdebuglevelZSTD_compressCCtxfprintf_filenozen_print__gnuc_va_listlua_Statezen_add_iosize_tZSTD_maxCLevel_IO_read_baseerrorlevel__fmtstderr_posuserdatarandom_externalvsprintf__streamchar__fprintf_chkvsnprintf_t_modelua_CFunctionlua_settop_IO_marker__errno_location_IO_read_ptrZSTD_DCtxZSTD_isErroro_newssize_tZSTD_DCtx_sstatuszen_fatalva_list_IO_write_baselong long intwrite_IO_save_baselua_KContextlua_getglobalcustom_print__apluaL_Regsnprintf_freeres_buf__pad5vfprintf_vtable_offsetZSTD_compressBoundZSTD_createDCtxlua_callkintptr_tsprintfstderr_full_IO_read_endlua_print_stderr_tobufshort intlua_pushvaluelong intZSTD_getErrorName__stack_chk_failluaL_setfuncsnewlinelua_KFunction_IO_wide_dataZSTD_decompressDCtx__va_list_taglua_print_format__ssize_tfp_offsetname__vfprintf_chkstdout_len_wide_data_lockzen_write_err_valong unsigned intlua_print_stdout_tobuf_old_offset_IO_FILEreg_save_areaZSTD_CCtx_szen_printerrzen_zstd_decompressunsigned charstdout_buf_IO_write_ptrzen_write_out_vaZSTD_CCtxrandom_generator_codecvtrandom_seedzen_zstd_compress__off_tsigned charshort unsigned int__builtin_va_list__func___chainFILE_flags2_cur_column__off64_t_unused2_IO_buf_basevsnprintf/home/alby/dev/Zenroom/meson../src/zen_io.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits/types/usr/include../lib/lua53/srcmilagro-crypto-c/include../lib/zstd../src/zen_io.czen_io.cstdio2.hstddef.hstdarg.htypes.hstruct_FILE.hFILE.hstdio.hunistd.hzenroom.hstdint.hlua.hamcl.hlauxlib.hzstd.hzen_error.hzen_octet.hstring.herrno.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx 9H k A 88;FBD A(D@ (F ABBC 8tbFBD A(D@ (F ABBB 0BJD G0c  DBBF TFEE A(A0D@ 0D(A BBBF m 0A(A BBBK T<FEE A(A0D@ 0D(A BBBF m 0A(A BBBK K A H(BBB B(A0D8DPK 8D0A(B BBBG H0FBB B(A0D8DPq 8C0A(B BBBF HHHFBB B(A0D8DPq 8C0A(B BBBF HHFBB B(A0D8DPq 8C0A(B BBBF K A H BBB B(D0D8DPK 8D0A(B BBBD (HEID0s AAI Ht@FGB B(A0D8DPq 8C0A(B BBBI EN g IE  9pP*;(^0i0v H` Hp  0@    /?0 X \&k,e2r8p>tDyJ~PV`q@;+b?Scq{@! /p:zen_io.czen_fatal__func__.6__func__.5lua_print_formatlua_print_stderr_tobuf.constprop.0__func__.2zen_printerrzen_warnzen_actlua_print_stdout_tobuf__func__.0zen_write__func__.1zen_printcustom_print.4custom_iowrite.3.LC1.LC2.LC0.LC3.LC4.LC7.LC5.LC6.LC10.LC8.LC9.LC11.LC13.LC12.LC15.LC14.LC16.LC17.LC18.LC19lua_fatal__stack_chk_failzen_zstd_compress_GLOBAL_OFFSET_TABLE_Zo_argZSTD_compressBoundo_newZSTD_maxCLevelZSTD_compressCCtxfuncZSTD_isErrorZSTD_getErrorNamestderr__fprintf_chklerrorZSTD_createCCtxzen_zstd_decompressZSTD_decompressDCtxZSTD_createDCtxlua_pushvaluelua_callklua_tolstringluaL_errorzen_write_err_va__vfprintf_chk__errno_locationstrerrorEXITCODEzen_write_out_vastdoutzen_write_errlua_gettoplua_getgloballua_settopzen_write_outzen_add_ioluaL_setfuncs354T*789:;<=>? +*@5A=3KlR!\BiCw4*78:E "=#>T?[ j*@tA|3L!BFL!B4G#G:HJI{#J4*7W*@$M*@L%MNO&M%*P54Y*7*R>'CMc*RvL(MNO)M*P4K4*7#,*!/BLTS*]+g,lUSVS4D TK *V U V - W W . W 4t T{ * U / W V - W$ W@ .J WT 4 T * U 0 W+ VQ -[ Wt W . W 4I Qf 4 *7  ! BT*!,)U>XNVr+yX48W!$B+4T*UV-W6WX.bWl4x1UZV2UZ4vL&LV0 (08@H PX` `h5pxD    * / =  B N $g s 4}   H       $  _  Q  ? # 0 = J W d q r~ U % s a  ?  K 3 S    ' 4 A N [ rh u p i F )   t P N  & WV  h d t {  ( 5 +B EO \ i v   /    &  i ?     " . : A nF 3R vw f  `    `  , V1 = Q s] y 7     % PF @a    V -    H T t  a  >    2 : pZ ^  c No x    ~      : I h  o  I =  w   6 P g' 6 : C G L xb /q xz x        ? '( X5 P ] Pg t   P   @    L D u i$ 6. p; (D  S W ` d i 9 / 9 9   A    -HR_l`pm{   C \  | 6 b [ t   ^ 60) ? ^K 6U      ' ! H @'->YN}   i e } {M j , 5V Z x |  @      w e =  <GQg| M      * `)`D $H Q @U :^ Xb Vgz  s a   #  " k e )>Ti0s "X@ 2      z 1 5 > B K O Tt9  H  [  H    90K )O ^@g@ R P ] [@ m e    Pp\2Pt30  8 8 3 7 @ D V Z  c "g u X 8 2    r 5H MZ h\r p    V N h h / x3 v< @ R V _ c q r~      r( 1x I d\n tN p: X `    / 8 T X a  e  w !{  4 0  J D / A _ -r<x V n \ y p    p . j2 `; ? H Q l p y }      ) % @ 8  - \ B!R3!dW!}h!k{! !!!!! e ! ] !!"  "  ""  &"  /"  3"  <"  @"  E"b"y"(""""/"0"  "  #"#>#  B#  K#  O#  a# + e# ' n# > r# : # # T # N ####!$r&$:@$X$s$\}$f$p$_$p$ ?$ ?// " -& J* Q. t2 6 : > B L  Q V "[ +` 4e =j Ho Pt ^y e~ m v         Ijp <@x@@L `  p Lx0p.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.str1.8.rodata.rela.data.rel.ro.local.rela.data.rel.ro.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@m&=,=12=@2KOP\ W@|0t o@} $@~5 g9{=j @0LH0@H0|HGIm @x0S0=[0 ]&3]8] 6X]1@8a3 iH@/481 0 0 0 644 9328 ` ELF>0@@HdH%(HD$1HD$dH+%(u Hf.HdH%(HD$1HD$dH+%(u Hf.HdH%(HD$1HD$dH+%(u Hf.HdH%(HD$1HD$dH+%(u Hf.HdH%(HD$1HD$dH+%(u Hf.HdH%(HD$1HD$dH+%(u Hf.ATUHHdH%(HD$1Ht-HHt]HD$dH+%(uWHH]A\fDE1HtHIHt/HD$dH+%(uHL]A\DE1HH511Malloc out of memory, requested %u B , :int{ 7 $* ] &]]. ]./] ud ] ptr*]6.D.ret= ]UvU0T QvUTTR!ptr!] ]@ptr ] (.]Z.sptr]]ptr ],.]. 6UU s6dVUUTT Z6gUU $ > I~IH}H}:!; 9 I:!; 9 I1B .1@z : ; 9 I  !I .?:!;9!'I< :!;!/9 IB:!;!/9 IB.?:!; 9!'I.?:!; 9!'I !% $ >  &I<.?: ; 9 '<.?: ;9 '<.?: ; 9 'I@z U4: ; 9 IBH}H}.?: ; 9 '.?: ; 9 '  .?<nUUUUTUTTTTTQQQQQQRRRVRRVPP\0U01U15U56U@pUpqUquUuvU@pTpqTquTuvTUUUU,,CN % '.<.JXX2 4;O;JXX" $/$JXXK  X  EA 7j7Y0Q@@"!HHdH%(HD$1HtHxHtHD$dH+%(u1HAT1ҾUHHdH%(HD$1IHt^L~1HHD$dH+%(uJH]A\1HH5H1HHDUSHdH%(HD$1Ht>_HtnH HHQu.=wHr#1HT$dH+%(u0H[]f.Hc\u1ҨEǸff.AT1ҾUHHdH%(HD$1IHt^L~1HHD$dH+%(uJH]A\1HH5H1HHDATIUSHHdH%(HD$|HcHsHcHHHLHD$dH+%(uHH[]A\HdH%(HD$1Ht{E1t9H xLAIctHЀ<uH511E1HD$dH+%(u-DHH511E1E1ff.AT1ҾUHHdH%(HD$1IHt^Lt2HHD$dH+%(uKH]A\1HH5H1HHDUSHdH%(HD$1HtaHHt/H1f.HcH\t DYu1HT$dH+%(u2H[]1ҨE1HH511AT1ҾUHHdH%(HD$1IHt^Lt2HHD$dH+%(uKH]A\1HH5H1HHDATUSHdH%(HD$1Ht\HHE1t(C<vHDX t2AIcH\uHD$dH+%(u2HD[]A\DE1H11E1H5fAT1ҾUHHdH%(HD$1IHt^Lt2HHD$dH+%(uKH]A\1HH5H1HHDAUATUHHdH%(HD$1A>IHHذHHA|$HcIEHAEEeHD$dH+%(zHL]A\A]1H5H5H1E1fH5fH5H1DDH5HE1rfAV1ҾAUATUHSH@dH%(HD$81HLt$H\$IILl$H LHLtjt$HH|$1HH4@4HL$HH9wt$HHT$8dH+%(H@[]A\A]A^fMH LHLvHH5H1Hf1sfHH5H1fDAUATUHH dH%(HD$1HT$.ztVD,HDIHtnHDLHHpXHD$dH+%(ubH ]A\A]fDHH5H1D$ D$ f.HH5H1uff.AT1ҾUHHdH%(HD$1Hti HILHPHtHD$dH+%(uZH]A\ÐHHH51HfDHHH511Hff.@AT1ҾUHSHdH%(HD$1HH)HAą=@HpD$HEIc1E1IH3f.@1u D$D$D$D$HH9tIH3I Dq u~@1u D$D$t$HMIcHD$A1@4H9uIcHEDEHT$dH+%(udH[]A\ÐDH5H1H5H11HH1E1{AT1ҾUHSHdH%(HD$1HHIÅt[H51H>`HLHxHHD$dH+%(uzH[]A\DHH511HHH511HHHH511Hv@AUATIUSH8dH%(HD$(1HT$ HHHT$LDl$EfL*D,L$ DL$ HH1/ v(fHcfHM*4@4/wDmAHD$(dH+%(urH8D[]A\A]fH5L1DHLHH5L1L$ AU1ҾHSHdH%(HD$1HHH=>RH1Ʉt1Hx7Hc3uHT$dH+%(u]H[]DHH1H5H5H11fHHLfAW1ҾAVAUATUHHdH%(HD$1IHLAąLcLIcHLHL<$IAąt`4$HH$HxHL9v}L)I4LLAH$EHD$dH+%(uzHD]A\A]A^A_LH5H1f.H5H1DI)K4>f.HHfAU1ҾIATUHdH%(HD$1HHttHAątMLHHxIA$AHD$dH+%(uDHD]A\A]fDH5L1DHLsf.AT1ҾIUSHdH%(HD$1HHteHƅx?LHHxHxTHT$dH+%(uRH[]A\@H5L11HLfH5L11fDAU1ҾIATUHdH%(HD$1HHtdHAąt=4@LAHHHD$dH+%(u?HD]A\A]@H5L1DHLff.fATUHH(dH%(HD$1HT$ Dd$ Ef*/stH,HD$HHT$H|$HHHH@2HH@qH9uAHD$dH+%(uCH(D]A\D\H,HD$H|$?xfH5H1ATUHSHdH%(HD$1D,E~mDH5H1DHHHt^Ic1fHSHH9uD#HT$dH+%(uAH[]A\fDH5H11HH5H1AVAUAATUHHdH%(HD$1HHDHIIHt7>!HD$dH+%(-HL]A\A]A^fDLHLH=tLH=uvDH1HIH"H$HHBH=>-rHIHLLH(fDHHHHtVHIHrHDH5H1H1E1H5HDHIH@HpIHLLHZH1H5H5H10H1H5H5H1fHDHIHt.@HpIHLL@DHtDHup1HIHHH5H1qHH5H1HH5H1DH5H1DHE1HHH5HH1HH5H1ff.ATIUHdH%(HD$1HHt@Et)HLHD$dH+%(u8H]A\ÐLfDHH5L1AVAUATUHHdH%(HD$1IHtlHIHtwAuAH9LIHt{LLLLHD$dH+%(urH]A\A]A^@HH5H1wHH5H1lHH5H1hff.AVAUATL%ULHH8dH%(HD$(1HHIHLHHHIH0AuHIHLLLLHD$(dH+%(H8]A\A]A^Ð1ҾHIHLLl$I$ED1ҾHIHtaLLt$Ld$D$@@HH5H17HH5H1HHf.HH2fUHSHdH%(HD$1HHt)3HHD$dH+%(u)H[]HH5H1fATUHSHdH%(HD$1HH |HsHIuMH5HH11HLHT$dH+%(ukH[]A\DLH1H5H1H1볐H룐HH5H1(ff.AUATUHSH(dH%(HD$1HHYHT$HDd$AE,1ҾH1IH/ffA*/1/ $DA@&QA$OpH @BD$AD$@pIL$@VD$D9WD$b9|$c.JLl$L$ LHxIHKLcLL$ HI,kLHLAH5H1HD$dH+%(zH(D[]A\A]DfHL$ H5ZDL$ A@&DH5H1L$ L$ HA^D tu |$bLH5H11HAHH5H1HH5H1fDHH5H1HLADL1fDIL$ff.ATUHSHdH%(HD$1IHHHH;A$MD$LK9OHc11IUUUUUUUUH33333333IfDII3HHHL!H)HHH!H!HHHHL!HHHHHHHH H؃H9uHHD$dH+%(uWH[]A\DHH5H1HH5H11ATUHSHdH%(HD$1HHHIHMc$D9t%H5H1H5H1LcELKI|$11fDA 2tfDƒuHI9uHHD$dH+%(uLH[]A\HH5H1OHH5H11ff.AUATUHSHdH%(HD$1HHHxHHIHǀH1H)HHK~@HAD911HM1DfHI*AD$fH*HuLHD$dH+%(u-H[]A\A]HH5H1ff.AWAVAUIATUSH(dH%(HD$1HH1HxHHIHǀHHH)HHxHHIHǀHHH)H+HK~HA+9E11f@C7tPffT$ **^C Zf( $ $T$ YZXZIIuL$Lf$W*f~fLZfn $^ $L(fnLHD$dH+%(u1H([]A\A]A^A_HH5L1FfDUHSHdH%(HD$1HHt1sHHD$dH+%(u0H[]f.HH5H1AVAUATUHHdH%(HD$1IHtdAUHHAIHt^LLDLHD$dH+%(uRH]A\A]A^HH5H1fDHH5H1fATUHSHdH%(HD$1IHHHHtvIc$;u^~)MD$H{11A8EHH9uHHD$dH+%(uaH[]A\fD1H@HH5H1mHH5H18ff.ATUHSHdH%(HD$1HH<HcIċ1HSHcHL0H0H0H0H0H0H00H9vHLHALHD$dH+%(u>H[]A\HfDHH5H1fDAVAUATIUSHdH%(HD$1IHAEI}11LEuEtK1fHcfL*IEfL(*LD9uHT$dH+%(u`H[]A\A]A^fDLfHH5L1,H5L11fDATUHSHdH%(HD$1HHto;tYHcHHIHcHLAHcLHD$dH+%(u?H[]A\@HfDHH5H1tff.ATIUSHdH%(HD$1HHt_Hs1HcHsHHLHHHD$dH+%(u0H[]A\HH5L1AVAUATUHSHdH%(HD$1HHD#ELsMA~`C$HcHIcLHIHH$LHLHT$dH+%(uqH[]A\A]A^@H5H11H븐HH5H1<H5H11ATUHSHdH%(HD$1HHt;taH{HcHsIHLHLHT$dH+%(u]H[]A\HfHH5H1dH5H11fDAUATIUHdH%(HD$1HHUtsH}HcHiVUUUH )Ѝ<HcHIHLLLHT$dH+%(uUH]A\A]fDLѐHH5L1YH5L11fDATIUSHdH%(HD$1HHtgLHHtrE~(1ɐș;HCHc4HUHc@4E9ۉEHD$dH+%(uMH1[]A\DHH5L1|HH5L1qfDATIUSHdH%(HD$1HHtg3LHHtu~*1zfHKHc4HM)ƒHc@49݉UHD$dH+%(uOH[]A\@HH5L1|HH5L1nfDAWAVAUATUHSHdH%(HD$1HHfHD,EfHD,E9 D9DHD)DpDIHAGA9|3D)f.HKHc4IMHc@4A9}EuHT$dH+%(H[]A\A]A^A_DH5H11DH5H11HH5H1DDH5H11\fHH5H1ff.ATIUSHdH%(HD$1HHH{LD2f41IHuHL9uщþLHHtXHEEHD$dH+%(uUH[]A\LHH51H{\HH5L1AUIATUHHdH%(HD$1HtHELpIHtJHLHD$dH+%(uIHL]A\A]f.HH5HH5L1fATUHHdH%(HD$1IHt0LHHD$dH+%(u/H]A\HH5H1AVAUATUHSHdH%(HD$1HHfHD,D9ExiHHIH3HD)IHDLLHT$dH+%(H[]A\A]A^DDH5H11DH5H11HH5H1HH5H1RHH5H1ff.ATUHHdH%(HD$1IHt0LHHD$dH+%(u/H]A\HH5H1AUIATIUSHHdH%(HD$1HHtJHt11AtHM@4BHH9r]HD$dH+%(u.H[]A\A]fHH5L1HH5`dH%(H$1H$HHHH5>HH$H=H$dH+%(u Hzenroom.octetstring expectedinvalid base58 digithigh-bit set on invalid digitError in %sexecution aborted%s :: invalid argumentbctb%s :: not bech32 addressNULL variable in %soperation abortedhex sequence invalidO.new 2nd arg is not a number%s: invalid string size: %ubase58 string expectedurl64 string expectedbase45 string expectedbase45 invalid stringbase64 string expectedstringnumberinvalid string size: %uzenroom.bigzenroom.ecpzenroom.ecp2Error in argument #%uInvalid segwit version: %doctetnewzerocrcconcatxorchopsubis_base64is_url64is_base58is_hexis_binfrom_numberfrom_base64from_base45from_url64from_base58from_stringfrom_strfrom_rawlenfrom_hexfrom_binfrom_mnemonicbase64url64base58strhexbinto_hexto_base64to_url64to_base58to_stringto_strto_arrayto_octetto_binto_mnemonicrandomentropybytefreqhammingpopcount_hammingto_segwitfrom_segwitreversefillbase45arrayeqpadmaxsegwitmnemonic__len__concat__bxor__eq__gc__tostringstring is not a valid url64 sequencestring is not a valid base64 sequencestring is not a valid base58 sequencestring is not a valid hex sequencestring is not a valid binary sequenceCannot create octet, size less than zeroCannot create octet, size too big: %uError allocating new userdata for octetError allocating new octet of %u bytes%s :: words cannot be encoded with bip39 formatbinary string sequence expectedinvalid binary sequence size: %uhex string sequence length: %uhex sequence too long: %u bytesbase58 string contains invalid charactersError in conversion from base58 for string: %surl64 string contains invalid charactersbase45 string contains invalid charactersbase64 string contains invalid charactersO.from_number input is not a numberCannot create a zero length octetCreating a zero filled octet of %u bytesargument %u octet too long: %u bytesinvalid NULL string (zero size)failed implicit conversion from string to octet%s: cannot convert %s to zeroom.octetoctet or string expected in concat%s :: octet bigger than 32 bytes cannot be encoded to mnemonic%s :: cannot be encoded to mnemonicInvalid size for segwit address: %dInvalid human readable part: %s%s :: cannot be encoded to segwit formatCannot measure hamming distance of octets of different lengthsarray cannot encode an empty octetbase64 cannot encode an empty octetbase58 cannot encode octets smaller than 3 bytesurl64 cannot encode an empty stringbase64 cannot encode an empty stringinvalid octet:sub() position starts from 1 not %iinvalid octet:sub() to end position %i smaller than start position %iinvalid octet:sub() to end position %i on small octet of len %icannot chop octet of size %i to higher length %icannot chop octet with negative size %dHH5H1% newoctetzerofrom_stringfrom_rawlenfrom_hexfrom_mnemonicnew_randomfrom_segwit_addresscrc8chopsubreversefilloctetto_base64to_url64to_base58to_base45to_stringto_octetto_arrayto_bineqpadmaxentropyentropy_bytefreqbitshift_hamming_distancepopcount_hamming_distanceto_segwit_addressto_mnemonicsizeconcat_nxor_nto_hexpush_buffer_to_octeto_dupo_argis_binis_hex_zJAg: ;int<****=2 F 1 %? & )1 * -F      1>1   S 7p? X* \1 h%1d2@A   !  "  ;%12& <>C%1]& =in%1M >%1 Clua D E F H I J ( K 0 M8 N @ O H P P RX S` T1 V1 W1 X Z  [ 2 \ ] ]F? _F Kira K 1T GX 1\ [`G[FkF  ӧlen 1max 1val  w  :%F < &g (XES ) %8 *x$ a&b'< (0 len1 1val    "(%3big,ixmyo<zqx r4h%x( y) xz*  +/  1val 3ecp4x(j ) * val+ 19BZNC/ @++++ D E** 6 ..&1N'1d 11U 1111+1  1 ^ -.-1kuR1 R 1| |1 L ..1 4u1u / .#1"1 1*  V 1@ ,W %1w 1  x ., ) 1 .1 7 18 8 10 uL 11Q 1v 1v = 1 )1 1 1    .. .1! 1A 1 Aa 1  y ..!     = ..\ 1 . j[ 1 . /1.  ; 1  S . 1x 1 1 ,  @ 1 11 1,1! 11A 1\ 1x &$ &# &   FO#-1LyPuy U TyQuwgF/ F  1 :Lcrc 1j i 1o  .J   res .yTU|T1ZU|T1\ U|T Q \ ,U|T Q wgJF : 1%L1Gx1c1 .  .yTUvT1yT/UvT2x TUvT \ yUvT  Uv\ UvT Q \ UvT Q wgF  1iL11c11 .  .l r 8 5%0yTUUvT1yTrUvT2 Uv\ UvT Q \ UvT Q wgS"1<#x!Sm1_m2_m4_ 1&Lo .6 i1 ;p**num1f ;** ] !^ ^ ^ ] !^ ^ ^yTU}T1 U &U  Ba8 ZU rU|  U}a ** U}a* U}a*\ U}T Q wg6F &* 14 L(o .0 i1pc1 ]# !^ ^ ^yT@UvT1 XU0 zUvT0Q0 Uv Uv UvT  U}\ UvT Q wg0F  1~L"tn1Tn u o .2UvT1QTZUvT} U|Q}\ >UvT Q \ pUvT Q wgF ~.max1`Lo .p yTUvT1 Uv\ RUvT Q wgpF ` 1wBLo .J yTUvT1 Uv\ 4UvT Q wg.eqp1Lpxq . yr .iv1reswyTUvT1yT UvT2 #Uv @UvT0\ rUvT Q \ UvT Q wgF .subR1 LRiS1cS1srcT .dstT.U1endU1p yTUvT1UvT2a*UvT3a*Z UvT~\ 7UvT Q\ bUvT Q|\ UvT Q \ UvT Q|R\ UvT Q wg 91>!L9src: .6 < .i=1j=1yT U|T1Z U|\ U|T Q \ 0!U|T Q wg $1bi#L$src% .J len&1l/ .r0 .yT!UvT1"UvT2a*lS3"UvTsZK"Uvo"U}T~Q|\ "UvT Q|\ "UvT R|\ "UvT Q \ )#UvT Q \ [#UvT Q wg 1$Llen n .J i1$UvT1a*zJ :$UvT Q|ZX$UvT|\ }$UvT \ $UvT Q wg.pad1A&Lo .p len  n  .yTX%UvT1 u%UvT2Z%UvT~ %U|T} %U|T~\ &UvT Q \ 3&UvT Q wg 1Z'Lo .' si1ooisyT'UvT1  +'UvT| C'U| ['Uv\ 'UvT Q wg'F '-1(Lo .' yT&(U|T1\D(U|Tv \(U|\ (U|T Q wg 1)L!o .) syT#)UvT1  N)UsT|w l)UvT| )U| )Uv\ )UvT Q wg)F ) 1*L o .* yTf*UvT1lS*UvT|\ *UvT Q wg*F * 1*a,L o .* c1idx1yTt+U|T10 +U|T0Q0 +U| +U| +U|T  +U|\ .,U|T Q \ S,U|T wg 1-L#slen1o .! ,U|T1Q0N-UvZ-U|36-Tv\ [-U|T  -U|T1Q \ -U|T wg 1/L"o .) 1byTS.U|T1W j.U0 W .Uv .U|Tv .Uv\ .U|T Q wg d10Ld!oe .) q bvx @yT/UvT1@ /Us /U}T@Q~R| $ & 0UvT} -0U}\ R0UvT  j0Uv\ 0UvT Q \ 0UvT wg F1O2LF!oG .* L1bNyTj1UvT1 1U| 1UvT| 1U| 1Uv\ 2UvT Q \ A2UvT wg 713L7"o8 .) =1b? ]> 2 ]yT3U|T1 <3U}Tv Z3U|T} r3U} 3U|\ 3U|T Q \ 3U|T wgG 16L x .y .sxsyxsys ud* n .A 4UvT1Q|yT4UvT1A 5UvT2Q|yT85UvT2ZP5Uv n5U|T} 5U|T~! 5UvT1Q0 5U}! 5UvT2Q0 6U|\ 26UvT Q \ d6UvT Q  6UvT2Q  6UvT1Q wg\ UvT Q  1b8L%sr8 o .! 7UvT1Q0Z7UvT 7U|x 7UvT Q  8UvT0x 78UvT Q  T8UvT0wgr8F b8 1O:L#o ._: yT9UvT1 9U 09U|x b9UvT Q  9UvT0 9U| 9UvT|x 9UvT  9UvT0 :Uv\ A:UvT Q wg_:F O: 14=L)o .= tn1@ userr1hrp=Ei1yTV;UvT1{ y;UvT2Q@! ;UvT3Q0 ;UE L ;U|TEQ *1 <UvT| \ <<UvT x a<UvT x <UvT  <Uvx <UvT Q| <UvT0\ =UvT Q x J=UvT Q x |=UvT Q  =UvT0 wg=F ==F W1J?LW+sX? ]1^ ?_ hrp`reta1ok .il! >UvT1Q0R ?UTQR X|Z!?Uv 9?UvRp?U}TsQ~R X|x  ?UvT0wg?F ?1?F' +1AL+ s,len. o3 .S4p51i61d71j81b9BW! @UvT1Q0S\@UsZ@UvT|x 'AUvT Q|\ LAUvT  vAUvT1Q wg 1 CL s* len1o$ .! $BUvT1Q0\ .?: ;9 '<4:!;9 I.1@z : ; 9! (4:!; 9 IB4:!;9 I 1RB UX!YW !:!; 9 I".:!;9! 'I !#:!;9 I$:!; 9!I%'I&':!; 9 IB(4:!; 9 I)1RB X!YW! * :!;!I8 +( ,.?: ;9 'I<-.?:!;9 'I@z..:!;9! 'I@z/.?:!; 9!'I !0 U11RB X!Y W!27I3: ;!#9!I4 : ; 9! 5 U6 7.?:!; 9!'I@z8.:!; 9! 'I !9.?:!; 9!'I !4:% U;$ > < : ; = >5I?<@&A : ; 9 B4: ; 9 I?<C> I: ; 9 D!E4: ; 9 I?<F.?: ; 9 'I<G.: ;9 'IU@zH.?: ;9 '@zI4: ; 9 IBJ4: ; 9 IK: ; 9 IBL4I4M.?: ; 9 '@zNH}O1UX Y W P1Q.?<nR.?<n: ; ,8U8U(U(\U\, ,IPL]P 08r"9r"/8r00 P USPSUUP-V]pPp|V(U(VUV0@T0 pur"'Pp1%P07R7;r0 P SSPS P \P\\(U(VUV-0-T0-0-?Q0UU P \P\ P MSPSXXYYPS )q3$x"q3$y"'q3$x"q3$y"'1%{ -S-HPHHps"U UUUUUUUUU 33333333U .U.]U] P SPS0 P%~^~~PR__PR\\R rp" rp"1#p?*=c=YYucuSS?~2$|"YVVbRot!!0PR!_! !0PR!\*U*VUV P uSPS0PPR]]Rrp"rp"1)>\>j|j\\0 S AsAkSS  0PR ].U.VUV a[~a~LP:\iP\&U&UVUVUVVP*S,IPIUS&U&TVTUUUwVP)S+APAMS(U(VUV P }\~\P\P(SewSwPS0)P)-p12T.U.VUV,P,3p3AP 0 ,p#,3p38p# P SSPS P N]P]___z\\\(U(\U\PdShPSPSVwPV 0 #P#*p*0P q !up!(up#(.up,U,VUV P SSPSm\r\\ P 5]]P] P ^P^0U0VUVk\l\P,S`vPv}SP p+U+VUVP_]b|P|]PC^e^P7\]vPv\(U(VUV P SSPSP\ 0 $T$tTdQdgRP \+Pt3$ $ &|"'U'^\^_U_\P1V4?V?XPXdV(U(VUVP\S`nSnPSP#\'U'UVUXUXVP,\-HPHT\,U,\U\ P ]]P]^~s ~"K~sKPs ~"0SKsKPS*U*{\{|U|\PKVNgVg}P}V P&P?OPqPPS[rS(U(\U\PXS\wPwSPP6V[`V,U,VUV P ,SSPS8S P $](U(VUVPaSe{S{PSPP \)U)\U\ P xV}VPVq32$# #!v32$# #P ]Q5U5VUV!V P ]]P]]!] P ]^^^PP^!0'00P]0P][00P\0P\00!0P2GPPP P ?\P\\)U)lVloUoVP(\Eh\hPP(U(VUV P {SSPSP8\Qc\*U*VUV P SSPSp1*}1*p1*}1*}1*}1*}1* P \\\P\\ 0QQ1Q1Q101Q0G1101P%\%)U\U.U.VUVUV2P2~\\\P   PlPP5PP0(Q0*U*hVhUVU P XSSPSP\P\\ P VPSsSSH0HQ1Q0100XxX00BUBHuHU0U0*U*VUVPR\p\PPQ!SZkPkSPS(U(VUV P eSgSPSPTgPgnTnrR.P 0 Rr'R/U/VUVUVU P ]]P]P5\P\Q___PK^l^^P)V}PV_ ~q" ~@"UQ ~q"p+U+]U]PVV[tVtPV P \K]P]d\PP\+U+{]{|U|]PHVMdVd|P|VP=MPMT\p3P/U/\U\ P SSPS+p1*p1*PCVPV 0 P.p.3P,U,VUV$p1*p1*p1*=P00$qw@R Rr/RPQq(Q+U+VUVPl^mP^PU]yP]P7\}P\(U(\U\ 0 $R$(r(/RPdVgPVPNStPS'U'UVUXUXVP,\-HPHT\(U(XUP P-U-t\twUw\ T v]vwTw]-Q-qSqwQwSPAVFbPbnV 0 Q#P(U(e]efUfU](T(aVafTf~T~VP*\*-PLbPbn\)U){V{UV)T)_]_T]T]T]T]T PXlPp|P|^P^P^P^^^'0':P]jPj\P\P\P\\P\P\P\P\P\P\P^>^^^^PZ]P]]PP7^^P*^^@U@VUUVUV<T<\TT\TTT\TPP]P]&U&f\fkUkp\-T-cSckTkpSP,V,2U38V)U)fVfiUiVP;\<`\`vPv~\P/?P$V.U.]V]vUvVUU47PPpPry4)U)fVfiUiVP;\<`\`vPv~\P/?P$VVUVxUxUUUU0?X[rXUU)U)eVehUhVP:\;`\`vPv~\P.?P%V.U.YVYpUpyVyUU03PJQP0)U)eVehUhVP:\;`\`vPv~\P.?P%V/U/WVWsUs}V}UU0"\""|"/\KS\0/\KS\0)U)eVehUhVP:\;`\`vPv~\P.?P%V<9!@apw v:!$,,0z192s!%    YYJXX'$g'sX=Y \. vX <6} ]t KX J6w< Qtt3t (g(sX=Y \. vX <67~$!( J s=H> ,X^\ <<FJ tKJgu Br u y X(.g(sX=Y N. vX <6~ ZtKX;< Ks4dt  X R%Xg%sX=Y N. vX <6~ [t<Y<$J uH O<* 6%tg%sX=Y N. vX <6,~XX==! X K  LoY ;Y zJtYRY y ;Y ].g.sY   J  /  X J[ 0 Yn vY  m..%h%V+ .Ytf<.+X!.(|.g(sY ] Y s=XPEYy .Y  .#~<g#sX=2  zX=X ;.="f Y ;.K$ 'JYtu]f 'x< JZI,K$uX<  WKtd.Y < .#Hfg#sY f X/N .  s=  X/uY [= t..Y X'i'U=!XN8N . < h<! <J< J!JJJ Y K gt<yY o< .&7XY&sX= 0x   < . JJ<<   tK / YJ xftY z< X&Ytg&sX=  t= H>X<M   |J J=Y|< |J >dY uuX= xY  t|< |JX<X%Ztg%sX=Y M v:0  Y s=  XL gtJxtY p< X&g&sX=Y N  s=YN 0 YX.tXY p< JY O&|g&sX=Y M = > dY ;=YtJzXY p< .&I i&UX Y K uK J<JJJ Y g gtt,Y  .gW XY\= Xy<   JY = YX.wt w.y"yfJX=X=Y.?H< K <K / J J< KY < XOY Y; ! =<# bX i  =Y<<<#<JY.Y#qX.o.#= g;* #tX. gW X<Yu.+ '.x zf g W X<Y Y gY...yX...#.l#zXP#zt&#z >dZ HY8  Q"9J < Yl'<f X'!30X < Y eYQ. .Y)Y =eY i; U4h4VX< jY EX> *p.  a  lJf<= <J <<= t<= t= t= u = <- Z.tf.. R4j4TX<JY; J rY < X/ ., J_ .p ..  J+ g+W X< w=w < -K % J1Jf K u<sKY  ..n ." g"W X< wX. wX=w  < w=w  <-K X% J1JX  .J@- XLL=L JJgJ Xf Jz J 8YIIKXK;K ..J^ ." YW X<Y .w~f gW X<Y W= X<Y...z..x gW X< YJ OXd"ZX" J[.wt c.. !~. g!W X<.% t   .YJ<K r > /-=  J X X X X /; =;=-gv   .  = e.YY kf '.# g#W X< KWt<J= ^Yt.q '.  J$ g$W X<Y.K# < e=Z= eY xt '. %. g%W X<Y  e= .y.{$Yf g$W X<< Jm JA  > ;KZ YXn vt '. t$E g$W X<Y.K  Y  d> YJ t '.  J%c g%W X<<K  z%8zfF t ;= YJ.u '. R$| h$V X<Y Y Rf >- X< \XX%"f fY =J ..z.z!f!/<2<# =% .` from_base64bprobstdout_poszenroom_tOCT_joctetBIG_384_29to_base45lua_pushnumberfrom_hexgp_offsetstrlenpopcount64bto_mnemonicluaL_testudatastrncmplerror__ctype_b_locentmaxOCT_tobase64newlenOCT_choppush_octet_to_hex_stringunsigned intpopcount_hamming_distanceluaL_checkudata__int32_tto_base58mnemonic_check_and_bits_ecp_to_octetluaopen_octetlua_pushlstringsegwit_addr_decodestderr_lenb58enc_maxo_arg__chocteterrorfuncleft__builtin_memcpyU64decodeto_base64to_octetnew_randomdoublesizestdout_fullbfreqfilloctetoctet_classlua_tolstringfrom_url64b58digits_mapstderr_bufuint32_tint8_tb45encodeentropysprintf_tfloatzstd_czstd_dluaL_Regmalloc__lensnprintf_tlua_is_url64buf2hexbinlenresultoverflow_arg_areaECP_BLS381fillis_base45GNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionECP2_BLS381debuglevel__destlua_getfield_ISlowerhex2buflua_Statefrom_mnemoniclua_createtablesize_tchop_ISxdigitis_base58bitshift_hamming_distanceerrorlevelluaL_optnumberfree__uint64_tstderr_posuserdatarandom_externalsegwit_addr_encodeis_base64vsprintflua_typenameto_url64charvsnprintf_tlua_CFunctionlua_settopluaL_optlstringFP_BLS381lua_setmetatabledatawitvero_newvsprintf_tcrc8uint8_tbitsrightpool_ptrto_stringreverselong long intlua_tonumberxborrowmaxlenecp2csprngfrom_stringOCT_pad_IScntrlo_dupdval_ISdigitentropy_bytefreqmemsetlua_Numbermemcpysnprintf_ISspacelua_pushintegergetlen_base64totlenwitprog_lenpoollua_pushstringnlenOCT_toStr__int8_tOCT_frombase64luaL_argerrorOCT_xorxor_nsprintffrom_segwit_addressis_url64zen_memory_allocmnemonic_from_datato_arrayis_binU64encodestderr_full_ISpunct_ISprintshort intconcat_nlong intbinmaxzero__stack_chk_failOCT_jstringdistancelog2uint64_to_destroy__va_list_taglua_newuserdatab58lenlua_tointegerxfp_offset__uint8_tto_bin_ISgraphnamestartstdout_lenfreqis_hexnew_octet_from_biglong unsigned intfloorfreg_save_areaint32_t_ISalphalua_is_base58b45decodeoctet_methodschunksizelua_is_binpush_buffer_to_octettypeunsigned char__uint32_twitprogstdout_buf__srczen_add_classsizelua_is_base64B64decoded_lenOCT_rand_ISalnumrandom_generatorluaL_optintegerB64encoded_lenfrom_base58random_seedlua_settablelua_typefrom_bin_ISblanksigned charlua_Integershort unsigned intOCT_copy__func__from_numberfrom_base45FP2_BLS381doublelua_is_hexto_segwit_address_ISuppernewoctethalflenlua_pushnil_ecp2_to_octetlua_pushbooleandestfrom_rawlenb58tobinrndptrzen_memory_freevsnprintfto_hex/home/alby/dev/Zenroom/meson../src/zen_octet.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include../lib/lua53/srcmilagro-crypto-c/include/usr/include../src/zen_octet.czen_octet.cstring_fortified.hstddef.htypes.hstdint-intn.hstdint-uintn.hlua.hlauxlib.hzenroom.hamcl.hbig_384_29.hfp_BLS381.hfp2_BLS381.hzen_big.hecp_BLS381.hecp2_BLS381.hzen_ecp.hmathcalls.hencoding.hstdlib.hlua_functions.hstring.hzen_error.hzen_memory.hctype.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx XH J A (8FHG0K FBH (dEAD0i AAK (FHG0K FBH 0pFDA G0M  DABE H o I ( FHG0J FBI (8EAD0c AAA (dFHG0J FBI 0FAA D0_  DABF (FHG0J FBI 0'FBA G0  DBBD @$JFIB A(D0Dp 0A(A BBBC 0hFGA G@j  FBBG (FHG0Q FBB 0FHD D0  AABB 0 FHD D0{  FABF 80PFGD A(D` (D ABBJ (lEKD0| AAF @NFIB B(A0G@ 0D(B BBBA 0FLA D0j  DBBG 0FKA D0a  AABE 0DFLA D0\  DBBE (xFFG@ DBF 0FFD D0  AABG 8FBE A(G@b (D BBBG (FID0C FBB 8@FGB A(G@x (F BBBE 8|FGB H(J` (F BBBB !`(wEID0{ FAD 0FFD D0  AABF 844FGA D(DP (D ABBF 0piFFD D0  FABF 0%FFD D0  FABA 84FGA D(D@ (F ABBA HFGB E(A0A8D` 8F0A(B BBBA (`EID0| FAK 8FGB A(G@m (F BBBH 0FFD D0  FABG 0ZFFD D0  FABD @0*FGB D(A0D@ 0A(A BBBG 0tFFD D0n  FABE 0FIA D0j  FABI @FGB A(D0D@ 0A(A BBBE 0 FFD D0x  AABH 0T FGD D0  ABBG 0 FIA D0x  CABF 0 FIA D0v  FABE H FGB B(A0D8DP 8A0A(B BBBD 0< FIA D0  FABA 0p FEA G0J  DBBK ( FFG0| FBI @ bFGB A(D0D@ 0A(A BBBF ( FFG0| FBI 8@ FGD A(G@W (A ABBJ | K r A  `(6 BM Y0dJx ``  P P  @   0  P   N P  ,8= H T `f r{  !w 0  P4 !i p#% P(0$49 0Ep%M Yp'] 'i 6(u )Z @+*  p, @- - / 0  1  ,14 @2D ~P4 U t` @6l 6bx y08      (3PQx] H o"(p.4:@FLRX^Xd(jpv1|G^t  h@8`# *18?F@MT[bi0pXw~PXpp+<D,SiF@]w'}$3<CMWap@ .9L_o~ 5  8$ P92 zen_octet.clua_is_url64lua_is_base64lua_is_base58__func__.38lua_is_hex__func__.37lua_is_binfrom_segwit_address__func__.7new_random__func__.6from_mnemonic__func__.5from_binfrom_hex__func__.4from_rawlen__func__.3from_string__func__.2from_base58from_url64from_base45from_base64from_numberzero__func__.1__func__.36__func__.33xor_n__func__.32concat_n__func__.31concat_n.coldsize__func__.30to_mnemonic__func__.29to_segwit_address__func__.28popcount_hamming_distance__func__.27bitshift_hamming_distance__func__.26entropy_bytefreq__func__.25entropy__func__.24max__func__.23__func__.22__func__.21to_bin__func__.20to_array__func__.19to_string__func__.17to_base45__func__.16to_base58__func__.15to_url64__func__.14to_base64__func__.13filloctet__func__.12reverse__func__.11sub__func__.10crc8__func__.8__func__.35__func__.18__func__.9newoctet__func__.0__func__.34.LC84.LC130.LC65.LC67.LC66.LC68.LC69.LC70.LC71.LC72.LC73.LC74.LC77.LC76.LC75.LC78.LC79.LC81.LC82.LC83.LC80.LC85.LC86.LC88.LC89.LC87.LC91.LC90.LC92.LC93.LC94.LC97.LC96.LC95.LC99.LC98.LC101.LC100.LC102.LC104.LC103.LC106.LC105.LC107.LC109.LC108.LC26.LC111.LC115.LC110.LC116.LC112.LC113.LC114.LC117.LC118.LC119.LC120.LC123.LC122.LC124.LC125.LC126.LC127.LC128.LC129.LC131.LC133.LC132.LC134.LC135.LC136.LC138.LC137.LC140.LC139.LC51o_destroyluaL_testudatazen_memory_free__stack_chk_faillua_tolstringlua_pushbooleanfuncluaL_argerror__ctype_b_locpush_octet_to_hex_stringzen_memory_allocbuf2hexlua_pushstring_GLOBAL_OFFSET_TABLE_b58digits_mapo_newlua_newuserdatalua_getfieldlua_setmetatablelerrorsegwit_addr_decodelua_pushintegerlua_tonumberxZOCT_randmnemonic_check_and_bitshex2buflua_tointegerxstrlenB64decoded_lenb58tobinmemcpyU64decodeis_base45b45decodeOCT_frombase64luaL_optnumbero_arglua_typelua_typenamestrncmpluaL_optlstringOCT_jstringlua_settopnew_octet_from_big_ecp_to_octet_ecp2_to_octetto_hexlua_pushnilOCT_copyOCT_xorluaL_checkudataOCT_joctetmnemonic_from_datasegwit_addr_encodelua_createtablelua_pushnumberlua_settablelog2luaL_optintegerOCT_padOCT_toStrlua_pushlstringb45encodemallocb58encB64encoded_lenU64encodeOCT_tobase64o_dupOCT_choppush_buffer_to_octetluaopen_octetzen_add_class e%8Tfg;6=hGSg`g *0i9cjl~ k#g07k[l'V]mgsg[l#*Vfwng0e=JWopqrs;`tn~u [\ v  C [\J wV   \  *  [L x # [L* x4 > v    [< y   [< w   G [ |  V z` g {q  |     }  ' V ~] g y    [, w     6Q\g[x 5IZ[ {g,@R]u  3@JxGWet(@Ks}t[es[zxe5:MRf /{4CNh+?N]s[zx[x[x[ [x'1d~[x )<Gs[zx[x[xe(DZt3[:xDS[Zxds [x#Uz[#[*x4>w- 6 [ k      [ x ![ !w!+![2!:!D!R!!!!""[l"x""[l"x""%#>#Z#d#k#pu###[L#x#$[L $x$!$W$m$$$%%%E%[,L%xV%`%%%%&&&&]&'' 'K'[R'x\'f''''['x''(1(>(Q(\(([(x(([(x((()X)))[ )x))[ )x))***** ++["+x,+6+i+++++,3,[:,xD,S,],f,,,,,,--[-x$-.-e-z------[-x--.S.k.v.~.....[.x... /5/S/[/l/w////[/x////&0f0t00000[0x0000%1:11[1x11[1x1122{2[2x22[2x2223'3U333344[z4x$494C4S4[zZ4xd4n44 5G5[pN5xU5q5[px5x55556[ 6x66["6x,636d6w66[6x6667&7?7Y777777[u7x77[u7x78[u 8x88T8g88[8x88839[:9xD9K9^99999f% 08 (408@!HP%X6`*h2p.x8`AKR0Yeq }P (08 @H PX `hP pxP  0/- (p,0#8p,@*H@+P3X@6`<h)pCx0O` Vp%^0$g#o!P4%6 *(2081@H1PX`h0px/-@-p,@6p,@+)('p' V(p%0^80$@gH#PoX!`hPpx0(0[ x _ c d d a& b- c; c B c I c<N cZ c_d cn cx cU c c\ c4 c c c c cI c( c c  c cr& cc2 coH ciT ce c q c v c c  c  c c c c c  c3 c^ c_ c c c c c c c c^, c9 cF c+S c= ` cy m cz c cn c c c. c c  c c $ c1 c> cql c c c2 c2! c 5 cO ci cv c c c cC  c^C cC P c^k c c1  c ck c c@ c7 c@ c c  c c7 c4  cP cN c4 cO ce c c c  c  c c< c+ 3 cS c c cy c c! c^ c cA cX cyx cp c c cN c c  cG1 c$M c| c c cf c@ c' c" c7B cb cz c cK c cW cT c)% c< cT c"y c ci c c c  c<" cB c] cy c c c cv c c c cb)P9I `M ` R c+b cr99 cj4 `0 `( `^ `V' `+ `9 `= `K `O `T c ^[tg cMr `v ` ` `45Y5[t5#[t-5P cTZ#z `C~ `; c `o `i ` ` ` ` c ` ` c [P c| `* ` )#B#0h#K@Uy#p]z##[P$[P%$ c#!C `\G `TL cW `[ `i `m `r c} ` ` c ` ` c [p c| ` ` `= `9 `X `T0" a `{ `o  a ` `! `% `. `2 `9!V!s""[p"[p" cp= cGp%g ` k `y `N} `F c [  `y `q c ` ` c  ` ` ` ` c ` ` c `5 `- `\ `X& `u* `s/ cw: `> `C cN `R `[%d at `x ` ` ` ` `& a ` ` ` ` `- `'%%%'&C&[&s&''$'`'[ j'A cK0$k `No `F} `| `t c [0 ` ` c ` ` ` ` `6 `,$ a `` `^  `q `o ` `$[$Aq$Y${$%%"%Z% [0d%6 c@` ` `d ` ` ` c [P ` `    (5[P?8 Zg[PqB p' ` ` `G `? c [' '!'<I[S'v c  `m `e ` ` c [ +[5'L(l `p `~ ` ` c [ `  `  `J  `D  `j  `f () \)$)A)\i[s)[)2 `  `  `  `  `  ` * ` . ` > `D B `< G c R `l V `f f ` j ` o c y[~2 3+3Y3 3(X84Sc(4~[~G4h4[~r4 c 10 ` 4 ` D ` H ` M c W [` cv k ` o ` } `3 `+ `\ `T  2 2 2  [ 2!'![1!2?! c;I!6i! ` m! ` }! ` ! ` ! c ![y! ` ! ` ! ` ! ` ! `L ! `D !6! 7"*74"C7L"]7p"7"P"7""7""[y"7# #[y*#8E#R#[y\#"8j# clt## `v # `n # ` # ` # ` # ` # c #[ # ` # ` #$+$h;$ Y$it$@~$$$[ $$'$ ` $ ` $ `+ $ `# % c %[!% `P %% `J 3% `r 7% `j <%(Y%5(v%B(%U(%`(%(%%[&(&*&[4&(B& cL&)l& ` p& ` ~& ` & ` & c &[ & ` & ` & `& ` & `<& `8& `X& `P& *'.*'*,'*D'+\'0+w''[ ':+' c '@' `' `' `' `' c ([ (h'(E(](x(([(( c(p,( `( `( `( ` ( c ([( `?) `;),$),1),O),m),)-)(-))[)2-) c)@6* `[ * `S.* `2* `|7* c A*[J*h6g*{6*6**[*6* c*@++ `+ `+ `+ `+ c )+[;+ `?+ `O+ `LS+ `DX+m+u+++++++++ ,+H,,%,[/,a,J,T,j,b, c l, , `u, `m, `, `, `, `, `, `,K,[-i-x7-R-\-|-G--^-- c=-@-- `- ` - `@- `8- c .[. c. `a . `_.. `t2. `n7.i-T.~-k.-x.-.-.-.-..[.-/ c2/-0/ `4/ `B/ `F/ `K/ c U/[^/ ci/ `m/ `{/ `/ `/ c/./W./o./z.0..0.I0S0.k0.00[0/00 /0 c0/0 `0 ` 1 `M1 `C1 c 1[(1 c31 `u71 `sE1 `I1 `N19/k1W/x1_/1p/1{/1/1/1/22[2/82B2/P2 cZ20z2 `~2 `2 `2 `2 c 2[2 c2 `2 `2 `22 `.2H02 a2 `H2 `F2*03j03x0=30[30s303033[3030303 cS3 a4 `_4 `U"4 `&4 `44 `84 `G4 `lK4 `^Z4 `^4 `4 `4 `4 c 4[4 `I4 `?44,4H5^95xQ5o555556H6)6[36hN6[6[e66866866%66[6 c6P 7 `z#7 `r17 `57 `:7 c D7[@V7 `Z7 `_7z 7 7 7 7p7[@7 8 !8o.8[@88 U8 x8 c|808 `8 `8 ` 8 `8 c 8[8 c8 `88 `28Y9~919L9Y9[c99999`9 9:8+:8:[B:Be: c o:P: `Y: `Q: `: `: c :[: cR: `: `: `1: `#: `; `i; `!; `&; c1; `5; `:;{W;z;;;;; <<3<=<: X<b<o }<< < << < ==[=!4=oA=[K=>!f=s=[}=H!=V!=!= c=> `N> `B> `> `> c )>[`2> cRB> cR> cem> `q> `> `> `> `> `> `5> `/>?>r> ?"?:?a?q? ~? ?Z ? c ? ? `\? `R @ `@ `@ `"@ `0@ `4@ `B@ `F@ `T@ `LX@ `Bp@ `t@ `y@ `@ `@K @_ @ @ @d A(Au CAMA mAwA A cVA A `A `A `.A `&A c A[0A `YA `OA `A `}B %B =B XBhB B+ Ba BBk B B C *C ECoRC[0\C yC C cCC `C `C `C `C `C `C c C[C `D `D `2D `*D99DMQD^iDDD[DDDDDD cm E"E `a&E `S4E `8E `HE `LE `QE ce\E ``E `pE `+tE `#yE cE `TE `LEE a E `wE `uE `E `E `E `EEE a3 F `F `F `F `&F `*F `/F$GF0iFDFVFaFyFFG,GXkJ `6yJ `n}J `dJ `J `J `J `J c J[ J `J `J K0K:NKiKsKKKKK[ KK c KL ` L ` 'L `E +L `? FL `v JL `t XL ` \L ` jL ` nL ` |L ` L ` LLLLLL c(M c XM ctM cM c M cMN `!N ` $N `3!(N `+!-N c 7N[IN `\!MN `T![N `!_N `}!dNNN-N@NKN OO[$O?OLO[VOqO~O[OO c!O1O `!O `!O `!O `!O `"O `!P c P[P c  P `,"$P `$")P)1FP>1cP1~PP[P1PP[P1P c: P08P `U"Q `M"Q `~"Q `v"Q c $Q[7QX8TQk8rQ8QQ[Q8Q cQQ `"Q `"Q `"Q `"Q.R `" R `"%R<3R)TR^RXlR ctR8R `"R `"R `#R `"R `1#R `)#R `[#R `S#R c R[R `#R `y#R8SH93S@S[JSO9mS cxS5S `#S `#S `#S `#S c S[S `$S `#S5S5T6#T0T[:T06UTbT[lT76zT cTT `2$T `*$T `l$T `V$T `$T `$T `j%T `<%T cT `&T `&T c T[U aC(U `T&,U `J&1UjZUrUUUUUUUVV8VBVYVfV[qVV `&V `}&VV aqV `&V `&VlVVW1W>W[IW aZZW `&^W `&cW WW/W+WW[WXX=XGX _X>tXXVXXXX$X Y8$Y.YROYYYzYYCYRYaYYZ[Z*Z:ZXZpZZZ[Z5Z cYZZ `&Z `&Z c Z `+'Z `'Z `'[ `'[!#[AG[Q[No[[[[[[][[[\ \6\HF\T\ cl\ c v\[\ c"\ c \[\ cJ\ c \ c\p] `'] `'+] `'/] `'<] `(@] `(E]R]j]]]] c] cP] c^ c^ c^ c"^ c-^ c';^ cE^ cO^ c^^`y^ `.(}^ `&(^ `Z(^ `P(^ `(^ `}(^^^ `(^ `(^^ __8_P_m___ __ `(_ `(_ a _ a _ `(_ `(_?``5` `)9` ` )B` `?)F` `5)O` `f)S` `b)\`0e`0` `|)` `z)`:`K`(`` a )adIaSakeaa `)a `)a `)a `)a`a`a `)a `)apa3a=bb"b=b `*Ab `*Jb `<*Nb `2*Wb `c*[b `_*dbmbb `y*b `w*b bbPbbc1c4Qc[c;mc@c `*c `*c `*c `*ccc `*c `*ccQc[dod d;d `*?d `*Hd `'+Ld `+Ud `N+Yd `J+bdPkdPd `d+d `b+dZdkdxd de+/eOeYekee `}+e `q+e `+e `+e `+e `+e e e `,e `+e'eQf[ff.1f0Lf `,Pf `,Yf `B,]f `8,ff `i,jf `e,sf|ff `,f `},ffffZ gj#g{@g`gjgxg cq|g cqg c'g cP914_444445D#p|##|#,#+E#]!!!!!!>!Y!|0"0"0"0"!p%O%z+&%&+&j&6P&]P&vj&&&%%%&&.&O0$}^$$$$7$a$r$$`   p'H'n(( )K ")k ") 2 i3 i3 2E \3m 3 03 1  2 24 #2] %2 6 6 7 -7M F7w       ', (Q =(s E( )  * 1*1*=K*Y1*@kp,,@,\@6k6@+p++M+v N]s@-Al-b~-u-- .O.c./NL@@ATIUSHdH%(HD$1HHH1H1H9seHDBf% uH9vMf.tA4H9rIA$HT$dH+%(uH[]A\f1AUATUHSHdH%(HD$1HL$$IJ\ MKL%LH8DHDW u'uXHH)HH$H9uHHH)HHHD$dH+%(uqH[]A\A]fL $HMtL)IHI)LBDG uA'uJ HH$H9uHxHcAUATUHSHdH%(HD$1HL$$IHJ\ MKL%LHHH)HH$H9t}HDP uH<$HtqIHI)HH)H :HH $L9t H DH uH)HHHD$dH+%(u"H[]A\A]DHHHff.AUATIUHdH%(HD$1HH,$HIMD-I|-H0L@HH)HH$I9HHDN uۃ߀[H<$HPHt8Hu%Hjt+HH)H$H9t~H<[t<]u؃HjuL)LLHH$HLHPfDLHT$dH+%(uKH]A\A]fH5L111H5LLAWAVAUATUHH dH%(HD$1HT$IHQHT$HIHH|$H|$HD$HxIHD$HxHT$LLIHT$LLHD$HD$H;D$uLLtC1HLLHD$dH+%(H ]A\A]A^A_fH븐H5H15f.H5H1f.HH5H1HH5H1ff.AWAVAUATUSH(H|$HT$dH%(HD$1IH>Ll$MO1IHD{HI9HIADP uL9rFfH IHcISHI9HtlI$I,HcDh tHL98f Ȅu8AAH|$)HHcHfDfAuDH|$HD$dH+%(uOH([]A\A]A^A_ff 념H|$HH511E1_LUH5HHdH%(HD$11H5HHD$dH+%(uHH]JSON as malformed beginning or endJSON doesn't starts with '{', char found: %cstrcasecmp: arg #1 MAX_LINE limit hitstrcasecmp: arg #2 MAX_LINE limit hitNULL variable in %s_Gparse_prefixstrcasecmptrimtrimqjsontoklua_parse_prefixlua_strcasecmp  P5)n]intA /      @ H7h/4nCC s !#M"Mx Hlow#  Qi | t n Cn ~ n:C ZC #r| CO#< /CnH Cn cCn n C!` LC uUvT UvT Q0"UUT  sH n}K L,Cin Pnp~zU|T1QP:U|T}:U|TvrU|U|T Z%U|T r=U| n n Ln'Coendpq @UvT1Q@:Uv [ n L['C\end]^ @UvT1Q@:Uv D nZ LD&CaEbElaF lbF @taG~tbG ~j #endTUvT1QUvT2Q@o U}To U|T~4U}T|QUvT0iU}U|UvT1UvT UvT  UvT Q L UvT Q  j HZ ; $;~ src;. len;@c<5d=5 % n L%(C&'  c)5*5% 2 n& '__c2 n UT1Q:/ UT "rI U} UT Q   H (I~H}IH}4:!; 9 IB$ >  !I&I ( :!; 9 IB .?: ; 9 '< .?: ; 9 'I< .:!; 9 'I@z4:!; 9 IB: ; 9 I4:!; 9 I( I4:!; 9 I!I/  :!; 9 I8 .?:! ; 9 'I<4I4% $ >  > I: ; 9 <'I : ; 9  !I/!.?: ; 9 '@z"H}# : ; 9 $: ; 9 IB% U& '4: ; 9 I(.?<nUVUUVU\U\P]]01R00P]PpPQqvQPUVUVP]TtTTPSSQSRrRSUVUVP]TtTTSQqQS U V U V P _ _ P _ P ^ ^ P ^ ^ P ] ] ] P \ \ \.U.\U\U.T.VT.Q.SQ808CrQ[f0fP U  P ^^P^ 0 S _ S Q S QQ_Q0S 0 S _ S ___0S v2$p" v2$x",P   Tf  E :X. <&< <X gJ) X$<J< <<Y<< Y M*, j*T  I=YX V>"JtYgIK\'<z tX=I= JgKIK z *] j*T  I= =YX V>gIKXJx JKIKXJx'<z^/.k/S JX%XX;!%*f%J)Jtu<JJz=HGX=fKJ=HK$</ r%Xf qt. t)j)T"<"JX=YYXYuI'....!y<7z<"..+M. i+U [+U X'<   X W/ 1H v1 X  t<  < <.c<YJt;u w 9J < K'tJ'X.t<<z U <'tJ U"  X"wttYIX_ISgraphsize_t_ISspace_ISlower_ISalpha_ISdigitlong long intsigned charlua_unserialize_jsonlong int_ISalnumlua_CFunctionlua_trim_quotes_ISblanklinelua_trim_spaces_ISpunctlua_pushlstringzen_memory_allocunsigned intlong unsigned intnamelevelsizeshort unsigned intstrcasecmpGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection__ctype_tolower_locluaL_Regdestlua_Statefloat__reslua_strcasecmplua_pushbooleanlua_pushnilunsigned charshort intzen_add_parselerror__func__luaL_checklstring__stack_chk_failcharfunc_IScntrl_ISxdigitzen_memory_freelua_getglobal__int32_tlua_settopfspacefront__ctype_b_loc_ISuppercustom_parserlua_parse_prefixluaL_setfuncs_ISprinttrimto/home/alby/dev/Zenroom/meson../src/zen_parse.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits/usr/lib/gcc/x86_64-linux-gnu/11/include../lib/lua53/src/usr/include../src/zen_parse.czen_parse.ctypes.hstddef.hlua.hlauxlib.hzen_memory.hstrings.hzen_error.hctype.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx 0BDA D0  AABC 8PFGA D(D@ (F ABBJ 8FGA D(D@ (F ABBF 0}FGD D0  ABBJ @FGB B(A0GP 0F(B BBBC H@FGB B(A0A8D`G 8F0A(B BBBC $`EN z IE  $4}IpXc0tx`   (X M+;O`]kyzen_parse.ctrimtolua_trim_quoteslua_trim_spaceslua_unserialize_jsonlua_strcasecmp__func__.1lua_parse_prefixlow__func__.0custom_parser.2.LC0.LC1.LC4.LC3.LC2.LC5__ctype_b_loc__stack_chk_failluaL_checklstringlua_pushlstringlua_pushnillerrorfunczen_memory_alloclua_pushbooleanzen_memory_free__ctype_tolower_loczen_add_parselua_getgloballuaL_setfuncslua_settop+ !S" !'" !.""#3=$MU%]#i !!&&E'S([)c)($$$ $ b!*MX"v#$ ,%-L G. 0 $p  /(0 48@ :H  (  * 1 B8  D K R BY P^ x c    " +   <     l   4     $ uN [ g y     &   h; [ s 6  x  .   Z3 7  < HQl v)KP N  E = k! e& 4 > B O S X{2AY(&a>mL Vu y ~  J <  ~ W 1 5 : D H W 4[ *` n+ p b Z    < @ N R  W oaqWz 2I5WR_jgX    6  C M "p Ez   ; 1 h b  ~     /   01 5 : D H M \ of w  {    w      f  \% 0 zJ g  t ~    " 0& M* T. w2 6 @ E J O T Y ^ c  h m !w TpD0.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.8.rodata.str1.1.rodata.rela.data.rel.ro.local.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @P@/&, 12@2F BO '\ ` W@x5t o@h6 70@H09X@(I0#L0&)0(&,(0( P(@J*h h.hK)/548 0 0 0 644 17904 ` ELF>>@@AUATIUSHH-dH%(HD$1HEHxXAHEHxXHEHxX HED HxXL HD$dH+%(uH[]A\A]ATUHSHL%dH%(HD$1I$HxXI$HxXH HD$dH+%(uH[]A\fUHHdH%(HD$HHHxXHHD$dH+%(u H]AT11UHSHdH%(HD$1L%@fH*HBt#HHHuHD$dH+%(uH[]A\ff.fATSHHXdH%(HD$H1IHuzH{`<1ȉoC`oKpHLoo@)$)L$)T$ )\$0HD$HdH+%(u#HXL[A\DH;H51HH511ATH5UHSHdH%(HD$1H1H5HHL%HfI$HHxXCH9uHD$dH+%(u H[]A\Error allocating new random number generator in %sRandom seed is external, deterministic execution_Grandom_int8random_int16random_int32random8random16random32randomruntime_random256rng_alloc  jjjqqq. int&(*jx 7!X0\hOTccwm"# h!C x"x ;h<h=8h85>INlh8CluaDqEqFqHI  J (K 0M8N @O HP PRqXS`TVWXqZ [ \ ]=  .?_l  ira  T X \ `  .  . $Z8, A .%; 1 occ7c$c [ ccc(ch P E L[[ {q&act %ch chq' L c 0O i p tUvT UvT Q0UvT   . t Lt!c cv idxw[UvT0Q0sUvoUvWUvT  jU Lj!c resk oGU| bw Lb"c resc oUv \XP L\!c res] oB Uv (=q ZZ=,)  rng?T *L ` UsT<EU0- U(R U|T@Q{q T  U0T Q  . +q sr,II~ : ; 9 I8 : ; 9 I !IH}H}$ >  4:!; 9 IB I !I/ :!; 9 IB &I'I.?: ; 9 '< :!;!I8 .?: ; 9 'I<.:!; 9! 'I@z:!;!9!I7I : ; 9!  : ; 9 I8!.?: ;9 '<.?: ;9 'I<4:!; 9 I H}%  : ;  $ > !<"&# : ; 9 $4: ; 9 I?<%4: ; 9 I?&.?: ; 9 '<'.?: ; 9 '@z(.?: ; 9 'I@z)4I4*4: ; 9 IB+.?: ; 9 'I 4,.?<nUVU0 s SsSSUVUV  s0s0U0\U\lrpH$s!vzTUVUVp8$s!UVUVPUSUSP\P\P\P,c $ $rJJJ/I=/</I=/;< *3Y<%pX%rJJuJ/; V1<$ttJY $g$IY$WJYKY<   VJfOJu+f=t.mf.hX Y #? f#ut Y  *JJ< [JJsprintf_tstdout_fulllua_settopcsprngshort intsize_tmallocrandombytesruntime_random256long long int__uint32_trandom_seed__uint16_tstdout_bufGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectionstderr_posmemcpylua_Numbertime_tuint8_tluaL_Regrng_alloclua_settablesigned charluaL_setfuncsfloatfuncRAND_bytettmpstderr_buflong intrandom_generator__destfp_offset__uint8_tgp_offsetunsigned charsnprintfnamerng_uint8sprintfrng_int32borrow__srczenroom_tlua_pushintegervsprintf_trandom_externaluint32_tunsigned intzstd_dlua_createtablestdout_lentimepool_ptr__func__short unsigned intreg_save_arealua_CFunctioncharuint16_tsnprintf_tvsnprintf_tvsnprintfvsprintftseedzstd_cAMCL_RAND_seederrorleveluserdatalong unsigned int__va_list_tagdebuglevelrndptr__time_toverflow_arg_areastdout_posrng_uint16rng_rr256__lenpoolrng_base__stack_chk_faillua_Integerlerrorzen_add_randomlua_pushnumberstderr_lenstderr_fulllua_Statelua_getglobal/home/alby/dev/Zenroom/meson../src/zen_random.c/home/alby/dev/Zenroom/meson../src/usr/lib/gcc/x86_64-linux-gnu/11/include/usr/include/x86_64-linux-gnu/bits../lib/lua53/src/usr/include/x86_64-linux-gnu/bits/typesmilagro-crypto-c/include/usr/include../src/zen_random.czen_random.cstddef.htypes.hstdint-uintn.hlua.hlauxlib.hzenroom.htime_t.hamcl.htime.hrandombytes.hzen_error.hstdlib.hstring_fortified.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx 8FBD A(D@~ (F ABBA 0XwFAD D0Y  FABA XEG @ FA 0FED I0l  FABA (FALp DBF 0FHD D0w  AABA w# X-7 B    M8RW\rt~ (6Dzen_random.crng_int32rng_uint16rng_uint8rng_rr256__func__.1rng_base.0.LC1.LC0.LC2_GLOBAL_OFFSET_TABLE_ZRAND_bytelua_pushinteger__stack_chk_faillua_createtableruntime_random256lua_pushnumberlua_settablerng_allocmallocrandombytestimeAMCL_RAND_seedactlerrorzen_add_randomlua_getgloballuaL_setfuncslua_settop*1AShw*=*ITt*D h!o"#$ %7'C H(U)\*c*}     (0 )8 @ 1HP :X` Chp Jx    * 1 z6 B L V ` m {  2     (  l   t   T  T% b3 8  D y | 1  | ^    y> + P        = P H  w * 7 fD qQ @^ (k Ax 7 _ m  R   !B LOX p i .     ^) WF a @  9      Y( /, +9 U= KBP;k uL Y     " 1 5 :\t H    5 EW#l0{HV _~ , $ N L 6  e ]   M+ XC xQ \  |       J ^    l s H. S h 8r     [  Y   @\ " 1& N* U. ~2 6 : > H M R "W -\ 6a >f Mk Sp ]u gz p w ~    \  .symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.8.rodata.str1.1.rela.data.rel.ro.local.rodata.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@$&, 12i@2i\T O@`(gp tz o@)h r@H:0  0@x:0;g@:X0l00& @@=H 8#O=/571 0 0 0 644 90736 ` ELF>0[@@HHdH4%(Ht$q9Nօt8HH9LcH9tNfHƤHI9wHqL)Hq~/HA HT$dH+%(uHfDH1HdH%(HD$1VHT$dH+%(u HF HATL%H5ULHHdH%(HD$1L11H5HHHH1HHA1EtHT$dH+%(u1H]A\DH HHH5S1ҾHdH%(HD$1HHH1H;H;HD$dH+%(uH1[fDHdH%(HD$1@=HD$dH+%(uHAWAVIHAUATUHSHHxH4$LD$dH%(H$h1D$0\f<%-Mt1HH)J~ HT$0H4$AHHHHHuЉЁ%%%%%uG@MtHH))ȃhHHЉЁ%%%%%=t;HH)D$0Ma=~H4$HADH$hdH+%(,D$0Hx[]A\A]A^A_H1CHsP?wL IcL>fDHt$L$<*Ht$/ƒHVH\$2CHH\$A<.HMFHL$Ht$<*lP1 wHT$ HtHHЀ vHT$A<.mH\$C<*_ H\$/H\$HSHBHCH\$D*CHH\$Ht$HVHBHFYH\$L$ CHH\$ ADŽ$I|$`fAD$`GG G0H511L1H=LID$XI$HHA$I<$H5I<$H5I<$1H5I<$E1E111L#I<$1ҾI<$1ҾI<$1ҾI<$H51I<$It$`@I<$H5Mt%I<$H51I<$LH5Mt%I<$H51I<$LH5HD$dH+%(HL[]A\A]A^fHH51I$HI$HI$HI$1H5>H511HH51I$HI$HI$HI$1xL-t!L-tL-HLDI<$1ҾI<$LHIH51E1@H51E1fH H1E1H5fUHH5HH?dH%(HD$1H}1ҾH}H51H}XHt HEXH}Ht?H51H}1ҾH}1ҾH}HEH}Ht HEH}Ht HE1H51HHHHD$dH+%(uH]fDAUATUSHdH%(HD$1HIL'HM@IL?HHH1HH5LLHHH5L11ҾLH5LH1Hu2H5L1HT$dH+%(H[]A\A]H5L1DLE1E11ɺ1HN}@1HH51xHH51Rff.ATUHdH%(HD$1HH/HIHH5HLHt|H5H11ҾHH5HH1L%A$tgH5H1A$HT$dH+%(H]A\E1E111HeL%A$H5H11HH51sHH5Off.UHSHdH%(HD$1H ?HHHHt 1?HDHt 1>HDHt 1:HDHHHHtwH8tqHHuBH8H51H;HHT$dH+%(H[]DH8H51H;1H51f1H51fH51hUHSHdH%(HD$1H ?HHHHt 1?HDHt 1>HDHt 1:HDHHHHtwH8tqHHuBH8H51H;HHT$dH+%(H[]DH8H51H;1H51f1H51fH51hAWAVAUATIHHUHSH(dH%(HD$1HL$`L|$hM/A<$MLHt 1?HDHt 1>HDHt 1:HDHL$HL$HHL0MLhLHHX HH8Lx@uN1H5LHHHT$dH+%(H([]A\A]A^A_f1H5LH1H51f1H51zfDH51\AWAVAUATIHHUHSH(dH%(HD$1HL$`L|$hM/A<$MLHt 1?HDHt 1>HDHt 1:HDHL$HL$HHL0MLhLHHX HH8Lx@uN1H5LHHHT$dH+%(H([]A\A]A^A_f1H5LH1H51f1H51zfDH51\0123456789abcdefxp0123456789ABCDEFXP00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899,3.0.0-develVERSIONRelease version: %s%s: %snullNo floatFatal errorSTB print functions in useMUTT print functions in useLIBC print functions in useLua newstate creation failedDEBUG%s: %s %sMemory in use: %u KBRNGSEEDdeclaring global: DATADATAdeclaring global: KEYSKEYSZenroom teardown.Memory used: %u KBlua gc and close...finally free Zen context%s: Zenroom context is NULL.CODEERROR:%sScript successfully executedExecution abortedInitialisation failed.Zenroom operations completed.initialisation of lua scripts failedPANIC: unprotected error in call to Lua API (%s) Memory allocation error at initalizationRuntime error at initializationUnknown error at initalizationError handler fault at initalizationRNG seed converted from hex to %u bytesRNG seed not found in configuration%s: Zenroom context not initialised.local _res, _err _res, _err = pcall( function() ZEN:begin() end) if not _res then exitcode(1) ZEN.OK = false error('INIT: '.._err,2) end _res, _err = pcall( function() ZEN:parse([[ %s ]]) end) if not _res then exitcode(1) ZEN.OK = false error('PARSE: '.._err,2) end _res, _err = pcall( function() ZEN:run() end) if not _res then exitcode(1) ZEN.OK = false error('EXEC: '.._err,2) end NULL string as script for zencode_exec()Empty string as script for zencode_exec()Error detected. Execution aborted.NULL string as script for zenroom_exec()Empty string as script for zenroom_exec()zen_exec_scriptzen_exec_zencodezen_init_pmainzen_init8D =(:(MEV ff :F&&&&GHint/ ! 1 3 6  7  8  9  : ( ; 0 < 8 = @ @ H A P B X D` Fh Hp It J x M N O Q Y  [ \ ] ^  _ . ` b  I +   :  :/0cA W 7=!   tt k  k nci   k top _ l_G uci z   ( _ 0 _ 8 @ H )P X O` 8    nny    k  X \ b% h1 m / . {(-K.. X' +           ( , 0 4 5 6 7 W8 x =J+BKRRK g :;!H \ ] _ top ^ _  _ _u j1  k 8 l @ mBg; <1. ==B[ [f>lq. [(C luaDEFHI . J .(K .0M8N .@O .HP .PRXS`TVWXZ [ \ 1]`  :?_LMSTB33" N 4 (]   ]  m :49 O> "buf? @"tmpA P:B   QZ_  R`  ; :0c + 0d.#~ H !U V ttVk Vk  Sd gce pf bgfhiinjk !qS r tt_rs+ &l S T4 55 .56 '/ 0 "tt0k 0k 1 k 2 k 3 "u7q  8 '8  "ttk k  k  k   l    ( 0    U  "tt_ V= 6nk 6tvk S  ' u  S = J u ! L  M  N O   P ( a  b _  c  ( e1k f gctx hW `Ol d c i ngX8 $ ud  _  _  S  S (  0 S @ P k T k U k V k W X $` h p x      )     ) .  3Ymt CZ S = C : S : i :4 : [iOZ 7* . .  ") ] J `E vD \ J H 4V A .1 76  V1   7   S.. ,[[>Y #q  . [ . \act% $ L   1.+i + +, +8 +D , ,.)- )-.Z0  L1 r3c<k< d< "-uUvT|YU~T $!UvU~T $!UvU0T 7U0T [U0T  8  , 8 D  .) ).Z  L rck d "fUvT|YU~T $!Uv'U~T $!?UvcU0T U0T U0T  8Ms  & 2 >rck d "-TvYT  $!T  $!U0T AU0T eU0T  8M-  & 2 >rck d "f[TvYzT  $!T  $!U0T U0T U0T  8jbQZZj  j0 *a retrLs UvT Q|UvT|"UvT 6EUvT Q0jUvT UvT VUvT0Q R0X0Y0UvT U0T Q CT Q  8 a :QF!ZZF! F1 *! retN+OLP U @]HUvT ?Q R}sU|T QvU|Tv U|T 6U|T Q0 U|T 0 U|T U U|T V U|T0Q R0X0Y0 Uv U0T Q !U0T Q  8 ! :!^"ZZ x!_Z@ !T !T3Q0!T  Y!T "T2Q06"T2Q0   Y"U0T "Uv 8`  y'$! $-$98ZZ  *' 9>#8lena56#\6P6D6>#U|YU0T  T$9 6%$T1Q0T Q R}l$U$U|Tv$U0T ,$U|$T|  %T )%T M%T Q0Vx%T0Q1R0X0Y0%T2Q0%T2Q0%T3Q0%T  &T|Q@)&T YH&T m&T Q~Y&T &T Q}Y&U0T Y&U0T 'U0T B'U|T {'T Q R  8 ' :':l);Ll*()  (UvT Q|6(U0T Q|N(Uvf(Uv~(Uv(Uvv(UvT0`(Uv )UvT Q R  8 () :):fj);Lfbi6g)6x6)T1Q 6)UUT Q0 J 8C*buf;fmtL vaY[c-*U0T0QURTXQ 8>+buf; DfmtW + va ~>+0+R~ 8dg+,bufg@<gI,fmtg] ,vagj[ci lj=^9,buf^3 ^?len^Ica, 8 =D,bufD* D5lenD?cF, ,sMdMseM 84-buf4:fmt4K +6 va7 ~-z-U0T0QURTX~ 85 H5 Xbufdfmtu va[ hex5 >5 bf f +D kG   eld!N P5fw"pr"tz"fl#+/lenJ 2~UvTz /vRcRf num {>5{g5sh lncsn645dpsn  0v 0 d= Q 1 i64P 1 iP 61o 2iecf z1lgk01len|%UvTz 1lg22len%U|Tz62lg0v2len2|Tz82Q}82Qs82T0Qz82T Q8T Q} 3i 93lg 2s3len %U|Tz83Qv8T}Qs 4i 3lg h.len %T->4i-/4lg ?len -m4i-^4lg ?len 5i 4lg04len%UvTz85T Qz8T Qi5B 55 5len2~UvTz 8 5 : 5 :j 5,fl,<6k956$A$N 8@9i6999.@g6gg<.R6#__sR#__nR.RR[.D6#__sD#__nD.D.1.7#__s111[.$T7#__s$$l>+8P+\+h+t+A+{B+m>+Lg|8t+h+\+P+A+{B+,M8U0T{Q0-U T{R|Xv-8U T{Q{R|Xv 8nCCI~ : ; 9 I8 H}I4: ;9 IB !I: ; 9 I : ;9 I8 H} : ;9 IB U I !I/ : ;9 IB.?: ; 9 'I<4:!;9 I1B : ; 9 I8 $ > .?: ; 9 '<: ; 9 I.?: ;9 'I@z  :!;9 &I'I: ;9 I : ; 9 I<H} 4:!;9 I! : ; 9 " : ;9 I8 #:!; 9!I$: ; 9 IB%H}& :!;!I8 ' : ;9 ( : ; 9 ):!;9 I*4I4+4: ;9!IB,:!;9 I- ..?:!; 9!'I/7I04: ; 9 I?<1.?: ;9 'I<2H}3( 44:!; 9 I5 :!;9 I6 :!;9 I7.?: ;9 '<84:!; 9 IB94:!; 9 IB:.:!; 9! 'I@z;:!; 9!&IB<:!;9 I=.:!;9 'I@z>4:!;9 I? @.?: ; 9!'I !4A41B41BC.?<n:!;!D% EIF : ; G H$ > I: ; 9 J5IK'L> I: ; 9 M( N4: ; 9 IO : ;9 P!I/Q4: ; 9 I?R4: ; 9 I?S : ; 9 T : ;9 U : ;9 V : ;9 W : ; 9 X : ; 9 Y : ; 9 I8Z : ; 9 I8[.?: ; 9 I<\.?: ; 9 '<]H}^.?: ;9 '@z_4: ;9 I?<`.?: ; 9 'I@za1RBX Y W b1RBUX Y W cH}d.?: ;9 'I e : ;9 f Ug4: ;9 Ih i1RBUX YW j.: ;9 ' k.?: ; 9 '@zl.1@zm1RBX YW n.?<nm#MMUMO\OOUOP\MMTMNUNOTOPUPPTPPUPPTMMQMNTNOQOPTPPQPPTPPQMMRMNQNOROPQPPRPPQPPRMNXNO]OOXOO]OPXPPXPPXPPXMNYNOSOOYOOSOPYPPYPPYPPYMN0NNPNOVOOVOOPOOVOP0MN0NO^OO^OP0NNPOOPNNUNNTNNQJJUJL\LLULM\JJTJKUKLTLLULMTMMUMMTJJQJKTKLQLLTLMQMMTMMQJJRJKQKLRLLQLMRMMQMMRJKXKL]LLXLL]LLXLMXMMXMMXJKYKLSLLYLLSLLYLMYMMYMMYJK0KKPKLVLLVLLPLLVLM0JK0KL^LL^LM0KKPLLPKKUKKTKKQGHUHIVIIUIIVIIUIIVIJUJJVGHTHHUHITIITIITIJTJJTGHQHHTHIQIIQIIQIJQJJQGHRHIRIIRIIRIJRJJRHHPHHUHHTHHQEEUEFVFFUFGVGGUGGVGGUGGVEETEEUEGTGGTGGTGGTGGTEEQEETEGQGGQGGQGGQGGQEEREGRGGRGGRGGRGGRFFPEEUEETEEQBBUBDUDDUDDUDDUDDUBBTBBQBC\CCTCD\DDTDDTDDTDDTDDTBC1CD0BCVCDV>?U?@S@AUAASAAUABU>?T?@]@@T@A]AATAATAATABTAA0??P??U?@V@AVAAUAAVAAUAAV?@\@A\<<U<>V>>U>>V33U39V99U9<V34T49]99T9;];<T<<]<<T34Q49^99Q9<^44P49\9;\<<\<<\77P;;P66P66Q66@66066U;<]UVUVUU s33U33Q33U33U33U33T33R33T33T33T33Q33X33Q33Q33Q12U23U12T23T12Q23Q22PUUTTQQTT+U+7P7UTRT!Q!{QQ37P7DpDRT37U7DuDRU7RX./U//Z//U..T./[//T//PU^U^\^ \ -^--\-.UT.zQVPV V X P X VPVXVXV\P\V\VVXPXV\P\V\VX{ X "V""P"#V##P#-VR.RX.zQPVuuU uq"t"# uq"# PuUuq"UPPUPpPpPPPPUuU!!u!!U!!u"!!U""P##P--PRSs|SSssTzsS z T S T t T z Q q Q z z# s S z T S T S T S T S T S z z z# S zSTSzz#zz#Szz#SzS"z""s""z#"#S##Q##q##Q#+z++s++S++s++z#++S+,z,,s,,S,-z0{{ { ] {{]{]{{{{{"{"#{##]#-{0 T 0 T 0 T 0 T 0Ss0TT{T{TT0TT { T S s !S!!sp""S""sp"#T#$T$%T%&{&'T'(T(){))T)+{++T+,{,,T,-{--T--{--T--{  ]   ]   ]   ] 0 ]]0] ]]0]@]]PVV0 ]"" "#0##]#$]$$0$$]$&]&+]+-] 00 0 -0--00Rz R R R z R R z z z 0Rzzzzzz z !Pz z z#+z++ z !++z+,z,-z--z--zQQPP  \ || \ |p" |p"# |q"# \\\ \\|\|\\\ \#$\%%%%\%%Y%&\&&((()\))\))\)*|**\**P**\**P*+\++\+,|,,\,-\--\Z  Z##Z$&Z'' ((Z 18_0XxX1_ @Q Q _ "z$$_$$Q$$ @$&Q&&R&&Q()X))x))X))x)*0**X**x**0**X**0**X*+ |P++_+, |P,,1,,X,-X--X V VP0VRP Rp2%P_  ((R()P)*R**P**R 00{0{{ p P { R_____ _ "{$$0&&P&&{++--_Pq__P P$$P%%P%%P&&P&&0&&P'' p '( q ()_)*_**0**_--P--q--P-- p --_ 0000$$0%&0 {\QQ{ Q ##Q--qq|PqZ()Z)*Z**z**Z,-ZP]PVVSsS !S!!P!!p!!P!!}!!P""S""PY^ ^--^""PQ rPPVPQ z V v $p $-( sq $v $-(P PS__p|"_ S _--_P**{,,{--{--{**z,,z--z--zUUTT/0U00]00U00U00]00U01]/0T00S00T01S/0Q00\00Q00Q00\00Q01\/0R00V00R00R00V01R11V00P01R11V00Q01\01S00U01]11P,=(+.3L  -  "#++,,-    --   "--  !""))--'(**,,----())*****,,''''))--;;;<4   ?[u@ 8Y   J=Z=;=-=?L22LX  =) v f)w )w& ; Y5 ~4 LJ4t {{J Y ze z p { f     $yVZ<<X/gKV = z:r,W < ?!x !r*VtJ@JK<gk+/W;Kw z .XXX~  E ]'nf!--JK</k+Y%+d>Z?Kf?Xft<'n'JX z"P; 7"^uYIY""<    =  ^| f<{J  : p {t <=; {JX. wXV c[ hXp xjX XK=$X.YI=J w< & .<&J <-<t=; AXfN X< H N < J L.J 1YW fX { 8XX  [zXw V / z  XnJ n<   yXf  \z z< JXy< 1YeyfX{  tJ gJX j! mJ ge yufX#  vJJ"J  y ytX%=%=Xz==XJXX` W Y- Ye= Y ,/  -J ..irY JvX +K:LXw L:= Y types.hstruct_FILE.hFILE.hstdint.hlua.hlstate.hzenroom.hzen_config.hzstd.hstdio.hllimits.hlobject.hsig_atomic_t.hlauxlib.hstdlib.hzen_memory.hzen_error.hlualib.hencoding.hmutt_sprintf.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx H y G 89H k A (TFOJ0x ABF jEK Q CA 9H k A LFBH B(A0D8JY 8A0A(B BBBD K A @,FBE D(D0I@ 0A(A BBBJ pK A CH o G @yFEE A(I0D@ 0D(A BBBC EN  AA 8FBA A(D@ (A ABBA (LbFAD0 ABI (xMEDD0 AAF (MEDD0 AAF HFBB B(J0D8D` 8A0A(B BBBJ LFBB B(J0D8D` 8A0A(B BBBJ  !9=LWje r y@     ((4/d  I!`&,27==CI"O4UG[[apgmsyHtX(&39G]dry 9`Cy *27ATaqP p.47!bG"MT#Ma %t&zenroom.cstbsp__clamp_callbackstbsp__count_clamp_callbackzen_init_pmain__func__.2zen_lua_panicstbsp__commahexu.5stbsp__digitpairhex.4__func__.3__func__.1__func__.0.LC0.LC1.LC2.LC3.LC4.LC5.LC7.LC6.LC14.LC16.LC19.LC21.LC22.LC23.LC24.LC25.LC26.LC15.LC17.LC13.LC8.LC11.LC10.LC9.LC20.LC12.LC18.LC27.LC28.LC29.LC30.LC33.LC34.LC35.LC36.LC37.LC38.LC32.LC31.LC43.LC42.LC41.LC40.LC39.LC45.LC44__stack_chk_failzen_setenvactluaL_openlibszen_add_iozen_add_parsezen_add_randomzen_require_overridezen_lua_initerrorlua_tolstring_GLOBAL_OFFSET_TABLE_stderr__fprintf_chkfflushz_set_separatorsz_vsprintfcbmemsetmemcpyz_sprintfz_vsnprintfz_snprintfz_vsprintfzen_initmallocZzen_conf_parsezconf_printfmutt_snprintfmutt_vsnprintfzconf_rngseedhex2buffuncrng_alloczen_memory_managerlua_newstatelua_pushintegerlua_setgloballua_atpaniclua_pushcclosurelua_pcallklua_gcpush_buffer_to_octetzen_teardownnoticezen_memory_freelua_closeZSTD_freeCCtxZSTD_freeDCtxzen_exec_zencodeluaL_loadstringEXITCODEzen_exec_scriptzencode_execzenroom_execzencode_exec_tobufzenroom_exec_tobufHHI#J+K3L;MCNMOUP QHR*TUVH;UH }  HYYg P Z  < ! 4 c Z ZVZYYY<HXH^XXH_\|HH`*ab*c*d"*e*f*g J*hIiP#[jekl*lymn$opqrs ss&%/JBtM&Rob'ijw(|I)j*I*d+*u*e *vj*h/,8jK*[R-c*]r*^*\J./01R 2Q 3Q#4* 6;QEH[5wxs6Jy7jssz{|.85j=}D*afH`9:I} ; Q R <- Q4 *A =K xs >} Q r }   ? Q   @ Q!HI!:Q!I\!g!;q!Q!R!<!Q!*!>!Q!r"*"="x-" 4"?;"QS" Z"@_"Qn"H"_"*a#~#A#j##w*#*V#B]#Qe#wu#C|#Q#D#Q#E#Q#H3$_:$*aS$d$Ak$js$wz$*$B$Q$w$C$Q$F$Q%G %Q%H%_%~%A%j%w%*5&B=&QE&wU&C\&Qu&F|&Q&G&Q&H2'_j'w'A'j'w'*'B'Q'w'C'Q(F (Q#(G*(Q9(HX  ,0 8$<(@,0H48P<T@D\H`LdPhTlXp\t`xd|hlptx|     $(,048<@DH3L P TX\`"d h*l.p2t6x |F  FJ R Z^  +  * / =  B qN  g  s i}   D       x     ;  2( <5 B O \  i v    Y  ` n G  ; m  /    , @  , 9 ^ F  S ` m z    h  J       2   & 2 > K d ~    (          #  & 3 6@  M g  t   2     g  v  L Y g u         F 9 s       , )h u         V 2 ~a        !  % w ' ( 7 5 g B gO  \ i Mv      , I     % * 1  C b P n z @ G  G = ] T  a # < 2H  T  ` #l  z !    U U   C C, 9 T ` | t z       '    1 # > L Z h v v         {> {K Y ^g  v    '      P \ mj     g R    '         ,  9 , F S ` X m !z       ) Q  ^ @ k  ~  S  j m     u    a  * K a w i Z J      i   7 W     Z     @- ? _Z r # 9   g   &&= RI M  R U^ Bb 4g s w }| d         q a % w          1  // ;3 9B EF CK6'Xn'v'''X'' (.8.(R\=(j v % R U M U  u    d     ` P      % w3 7 F >J 6Y a] ]l rp p | z  %%%%A&X(I&@`&Zd&~&&  # R   U    1 # d( x, l; ? N R a e t x }7$W$o$w$$X$$$8B%\f%t 7 " R   U .    w i d         . 2 7"D#\#q{'#a#Xi###(# #. :!\ &` e Rq nu Zz       U!`!u!#!F!ak!!"?"H c"-t: Dr"g Vsp   R 6 &    z x     9pIdt  1   O ' 1  L V    H    t  !!%!  -!PO! S! X!Ay!{!"!!!4!!!G!"7"D" Q"!^"9x"["A"j"  "" U"  "  " " = " / " d"  # x #  #  #  "# +# 5#  9#  >#!]#  a#  j#2t#2#  #  #  #  #  #  #M#_## #  $  $  $&$7$D$ U$m$$$d$i$}$$% % %*%?%N%y%%%%3%%F &V &*&m?&I&^&n&&&&&&&<& &'I'9'=C'?X'(e' r'|'I' w'' ' '  '  ' '' (''(7(/O(7g(?(G(Q(Y(((( ) ).) s7)U) K Y) G b)l) |) _ ) ] ) r ) p ))()))) )!*  %* { 6*  :*  J*  N*  S*** I**  *  * * 1 * - * G * C * 0+ [ + Y +c1+?+ I]+ + E++ g + c + N + } + y +  +  ,  ,  ,,  ',J,  N,  S, N _,  c,  t,  x,  ,  ,  ,  , ' , ! , ; , 9 ,, ,- G - A - f !- ` '- 02-  6-  J-{--  -`- H -  -  - N -  -  - O -  - n- j . . !.*. |7. K. O. ^. b. g. ;r. v. {. D .. # .. 7..  .. @.. .. .d .. h/ / / / // 3/ C/ G/ sW/ [/ k/ @o/ t// ]/ [// B/ g/ e/ s/ o/ M/ 0  &0 *0 90 X=0 JL0 P0 _0 ?c0 s0 w0 0 0 0 0 0  0 0 b0 m0 e0 R0 1 1 $-1 11 71 J1 N1 ]1 e a1 ] f1 {11  1  1"1 1  1  1Z 1} 2 72EX2  \2  a2fw2T 2g 2223 m3  3  3 }03  43  :3[3t33Z3 {3  3  3 33 4!3 2!3n4 4 N!4  H M R W \ #a 6f ?k Hp Su [z i p y               o>` <X `0tPpP!|"# % &.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.str1.8.rela.rodata.rela.debug_info.debug_abbrev.rela.debug_loclists.rela.debug_aranges.debug_rnglists.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @=(@xx&(  ,)12)@2+T/O@ aq18\@Y mPjqq#{@S 0@(T0g8@XT0 0 0& h @`X` H Z/591 0 0 0 644 14128 ` ELF>0@@USHH8H5dH%(HD$(H HHGHHHHHGHHGHHGHHG HHG(HHG0HHG8HHG@HHH-HHkp11Cx H5HD$(dH+%(uH8[]f.AVAUATUHSH dH%(H$1IHHLSHIHLSA4$HIHHLL$HLLLH1HLH$dH+%(H []A\A]A^H$dH+%(H HH51[]A\A]A^fHH5H1HH5H1HH5H1ECDH curve is SECP256K1NULL variable in %sInvalid public key passed as argumentecdh_add<  int <)<*H k w7 .4 ira4<TX <\ D` D . T .Ӑ len < max < val `h #1 &c('0(8)@*<H+<L,P-`.p/ <x <Th < <<< <1< <c<6 <<h <<<0:  . , & g ( XES ) ( * & i\ x m y o, z qX r2 D (   \   < C < 6<act %Nyddd << << << <E< t <~< f<< Q < E < ? <*<q L*pk1+ pk2/p1\}p2\~!7 UvT1U|UvT2 U}%UvDU}T|cU~T}U}T~U~T}Q0"UUT UvT Q 1 UvT Q c UvT Q 6 . q # 1 $ 1 i UN UvT6# U0T 6 %II~ : ; 9 I8  !IH}$ > : ; 9 I.?: ; 9 'I< : ; 9 I8 'I &I I !I/  : ; 9! .?: ; 9! '<4: ; 9 I?<4:!; 9 I4:!; 9! IB4:!;!39 IH}H}% $ > <'.?: ;9 '<.?: ;9 'I<.?: ; 9 '<.?: ; 9 'I@z: ; 9 IB 4I4!4: ; 9 IB"H}#.?: ; 9 '@z$: ; 9 IB%.?<nUVUVUUVP\\P\P]P]P^P^USUS,v     tt  tt<L! ! KIuJ. gW/X<f&g%...s  f st .. sJz..&.typeECP__SP_DSAECP_SECP256K1_SP_DSA_NOHASHECP_SECP256K1_ECIES_ENCRYPTorderECP_SECP256K1_VP_DSA_NOHASHpool_ptrlong long intsigned charrndptrlong intecdh_addBIG_256_28__uint32_tECP__KEY_PAIR_GENERATEpk_sumECP_SECP256K1unsigned intECP_SECP256K1_VP_DSAECP_SECP256K1_SVDP_DHlong unsigned intECP__ECIES_ENCRYPTshort unsigned into_newGNU C99 11.2.0 -mtune=generic -march=x86-64 -g -O3 -O2 -std=c99 -fstack-protector-all -fno-strict-overflow -fPIC -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protectiono_argECP_SECP256K1_KEY_PAIR_GENERATEECP_SECP256K1_fromOctetECP__PUBLIC_KEY_VALIDATEorder_sizeORDERcsprnglua_StateECP_SECP256K1_ECIES_DECRYPTfloat_Boolint32_tunsigned charECP__SP_DSA_NOHASHshort intECP_SECP256K1_toOctetlerror__func__ECP_SECP256K1_SP_DSAECP__VP_DSA_NOHASH__stack_chk_failBIG_256_28_rcopyuint32_tECP__VP_DSAchar__int32_tFP_SECP256K1ecdhhashECP_SECP256K1_PUBLIC_KEY_VALIDATEECP__ECIES_DECRYPTECDHCURVE_Order_SECP256K1borrowoctetorder_copypoolecdh_initcurveECP_SECP256K1_addBIG_256_28_toBytesECP__SVDP_DHfieldsize/home/alby/dev/Zenroom/meson../src/zen_ecdh_factory.c/home/alby/dev/Zenroom/meson../src/usr/include/x86_64-linux-gnu/bits../lib/lua53/srcmilagro-crypto-c/include../src/zen_ecdh_factory.czen_ecdh_factory.ctypes.hstdint-intn.hstdint-uintn.hlua.hamcl.hzen_ecdh.hbig_256_28.hfp_SECP256K1.hecp_SECP256K1.hzen_octet.hzen_error.hecdh_SECP256K1.hGCC: (Ubuntu 11.2.0-7ubuntu2) 11.2.0GNUzRx (EAGP AAA XHFGB A(D0G 0F(A BBBI ^ 0M(A BBBN     %*/4>Tj$@\mzen_ecdh_factory.cORDER__func__.0.LC0.LC2.LC1ecdh_init_GLOBAL_OFFSET_TABLE_CURVE_Order_SECP256K1ECP_SECP256K1_KEY_PAIR_GENERATEECP_SECP256K1_PUBLIC_KEY_VALIDATEECP_SECP256K1_SVDP_DHECP_SECP256K1_ECIES_ENCRYPTECP_SECP256K1_ECIES_DECRYPTECP_SECP256K1_SP_DSAECP_SECP256K1_VP_DSAECP_SECP256K1_SP_DSA_NOHASHECP_SECP256K1_VP_DSA_NOHASHBIG_256_28_rcopyBIG_256_28_toBytesact__stack_chk_failecdh_addo_argECDHo_newECP_SECP256K1_fromOctetECP_SECP256K1_addECP_SECP256K1_toOctetlerror*6*@*K*V*a*l*w*** !#2*$M#s%&&'(3:D)SZd)sz)!#) _  * 1 !8 K R Y F` g l tx o  Z    t   k' U ~   T 7 3   c   % D' 4 A N I[ m   ~' ] i xu~     < Y  O $j I O   F  -    > B P \T RY cu y    #<Qcw&Ed'H h ( 2 M Z d         $ 7 8; 8 " 7& T* [. ~2 < A F K P U Z _ d i n .s >x J} V L.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.str1.8.rodata.rela.debug_info.debug_abbrev.debug_loclists.rela.debug_aranges.rela.debug_line.debug_str.debug_line_str.comment.note.GNU-stack.note.gnu.property.rela.eh_frame @@(`&, 12,@2&O8 \A@ W@" h 5v0@h-0 @-0N0g0T&z @x/0@ 0/