Files
node/test/committee/elsewhere.txt
zeekayandHanzo Dev b98e8d9d61 The name is the node; the chain is in the proof
LP-10603 said the chain was in the NAME and I implemented that. The document
now says otherwise, and it is right: Go derives a node's own identity with
ids.Empty (node.go's MyNodeID = DeriveNodeID(ids.Empty)) and re-derives with
ids.Empty to check a peer, so a node answers to one name on every chain it
serves. Putting the chain in the name gave it as many names as it had chains,
and it broke agreement with Rust, which was right all along.

What the chain scopes is the ENTITLEMENT, and that belongs one layer down. The
possession proof is now signed and checked over chain | node | key rather than
node | key alone, so a line published for one network authorises nothing on
another while the name stays the same everywhere. Committee::claim is the one
statement of those 100 bytes; Signer::publish signs them and the door checks
them. The link goes back to binding a peer at chain zero, which is what Go
does and what a name is.

The door is this file's own now, and that is a consequence worth naming.
consensus::admit holds the REGISTRATION proof, whose message is fixed at
node | key and pinned across three languages by a frozen corpus; a committee
proof is a different message, so it cannot go through that door. The clauses
are the same clauses in the same order — encoding, possession, one key per
node — and the pairing is under the tag lux::consensus::bls publishes. That
surface exposes a general pop_sign and only a node-bound pop_verify; the
general verify would belong there.

Measured, three ways, on test/committee/four.txt:

  C++  Committee::read(...).root()   de34e8d1948f90d09610c8737c6487d494e093ba01680f1a54095a1cdfa696e7
  Rust lux_node::engine::Committee   de34e8d1948f90d09610c8737c6487d494e093ba01680f1a54095a1cdfa696e7
  Go   luxfi/validators SetRoot      de34e8d1948f90d09610c8737c6487d494e093ba01680f1a54095a1cdfa696e7

with the four names agreeing one for one in all three — the divergence from
Rust is gone. Go checks every proof over chain | node | key with its own
bls.VerifyProofOfPossession and answers for all four; read as a committee of
another network the same file names the same validators and admits none of
them. test/committee/elsewhere.txt is the mirror: the same four publishing
somewhere else, refused here. Rust computes the same root and then says
PopInvalid, because it still checks the node-bound proof — the remaining half
of the port, not a disagreement.

TWO THINGS CARRIED, both in this commit because they are what the link needed.

Signing is deterministic now. LP-10602 mandates it and Go signs that way, but
the C ABI offered only SignCtx(rand.Reader, ...), so a published handshake
could be checked and never reproduced. mldsa65_sign_ctx_det now exists in
luxfi/crypto's cabi — SignCtxDeterministic was already there, it was simply
not exported — and the link signs through it. The vector carries both secrets,
and pq_vector_test re-makes both signatures and compares them byte for byte:
signing prefix_resp here gives back the bytes GO put on the wire, which says
the two implementations agree on the signature rather than merely accepting
each other's.

And the nine-line ZAP pairing is gone from plugin.cpp. zap-cpp-core wrote and
read an error response's body length-prefixed where Go writes it raw, so every
error from a Go plugin arrived as "truncated error response" — fixed in both
halves on lux-cpp/zap-cpp-core branch net/error-body-is-raw, with a
conformance case that pins the bytes rather than a round trip. Verified live:
the plugin's real complaint now reaches the caller through ZapClient.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 01:15:09 -07:00

6 lines
16 KiB
Plaintext

# SPDX-License-Identifier: BSD-3-Clause-Eco
fc00695525bfe7685a3e3b8a6a96b7d6d6cbce4855dba8bd56ef3cce6b615b33ae1be3bee41dd225ed19998386c14bbd0274767602120d93730a29a942d475bb588d99e214dc40893870dc32dc1d831b3a63db27f7684eb9c68f42ee3fc4cc749a1b124d7a3685d77db42995f39094c17317b8b1af5f053f7272331a6947fc246cab0820c36ba62024ef470a416e5ade69607957812c30322399250782f832a422c58cd1b2f23112fa5dddcd6035a71c9c361f741ea155a5c3dbb3280c53d149a50bb91fbf9bc68a1e766d3f50002f0c391705ffbf0bde8fea91aa2502127efaaa087039cd2dad18654002e7c016b307476474695ce586a876f0f2ce3bc92f7bc19da8716d5e1692c5f39d49c1b24fcbf7446fbe2b8da0b5fd9d82e2bf3b64bd710cb6338ae2b83d0a6037a9dafa269b464b0b39de2ed777452a1bf929573a1f0681a4bc313ea5b3dd4a504c8cf4c9668e0e0e5de6aa62176bbe54f4d5ea74baa1427c784341b25090ab827e5cdfadfd53d506026dc74f0cd8c7fd2b17e2a0f74ea556273b552f031b36770e9f3ea33b6b58a1250932d7bc0199fbd04e9e9134b322cd75af25a6354bf186ec8c0ee2db7cebb90aee6bae82939267661de060f7be432fcf32363ea06343ed2bc02910539a0548cd248c51872b912e0cd7b62295e5a268531b3a32dff460525f2a30873d8d4cad791dd186ebd0490bfbbcf0e9b8eae8c210c665d4bfd45bdb78a1629109f446046158b7a6c89cf2587509e3a4994ce1fabc4e96a82b973306f92e5d84de3cff540fa7aec1d4b8ebf5547ce29c41b67e1fea31008a237a604d279d5efd0ba912bf1586b2ae871f17c54f80f95c935096529b5e81f77592c76f2deb6d80098c42f672cb09d47ffe64c5fed73126cca63cbbdde1b39be92576c2806547943ef31ee2b9467ce8063a5798e4460ea55361486c5ade8c4105ae3f40a8f6e13496a00b59046df56b2163aa72bdd0c0937f0827d397f7da5aa6aa264f9bd125999bf2d3ef1930a35bdca9efba3eaf3c22641a361c842d1a9df979f1c079e11cecf6d210f7dc0a8043f02c87775cd19d18bd9019ea0ca190626e2b680ef9907063b09bdded123c8329f571307d680ed92743dd03c0bba30757a121178baed8c05aec09b93641e190c8524e377f2f755cc48db26180fc108cd3ab139de5344aa49df18621d404c5a526147a4490c9b815ee059161c9fa845c4db5aff31b0c36b5ed23b5f0741188d5f09a64a86ed13fcdca23675e30dab4cafc7ddb7ab0fb819b74483c3e96e0ead72c6a9e756520427edcea0e9d3e03151322049da2d382a4abd147aa802174dc540b0d964d42e673de61f18d4cdb610aa8e187b09fe7ac0d5eeb881e6cbe9d15b1ef742a0c2f1cedbc1b696ec8f212e37acbe144cb4bbc0ece44ef2dc6d47b19bdd1a14d7a646f4ae954c51c80e8c6b874f29b8dc8a35475087c39828cf4fbf6d3f149cb18696306cc27187eb68badea8311a9e258e2985bfb7490cc3bd72b1e7b9eb67e5af120327f892b482c37b1dffcc31c0765eff0d88c61af6255f4c6f1bf56711f151460b8a233257ec680e2d7e47845c5f34a18ae71be61d78c5fd52716e956d0747351ecee78a216380adab4bd101f15de114620f61fd3c385bd979d568b3adce7ad487f125e5fbc9664c93766b15a878eb18ca3ff2b27340689b9832068044ebc85b0bf7522b111308f9efbf774cc6c1df1b615d0e397e3aa8d5d8e08a43d1d2e461a5ec49b5a1f33eb5cb1742d7caa159339b7d5825b4b1645ca39d9e163f21a01ab31ec952596c645a513716c89aea19a2208056ccf1f59925b6c8b683826c48a167a677f7d533fd39f06a9435c1d0a0092e1c684b0deaf122603d7084750c4c53030771912fd4772007a924de469a1c24c928c7860f5c7752cedb2061d4237e8b3545103dfe60e33666144437918ab2e7e53f0f8029ebc304127d729ae5ccd6afc0317691bc11e0d94968b703d1bd2d87f5bc502d79172dbe60cd989ec2618c96f6ebbd514163cfa03ec80fa0a6dbea993400b5d96570b3b6ecd2b5909f4afac12b8ff98c52f254fad37349d1758ee00194bb597880d9c1241f6dd1fc0689262876b4620abbdeb00b2c8d12598c64baa50e8cd814533f5061e8fe2ef6c1a754dd8e3404fd1717e7012666d341353f9b246158fab7b729104ac7314ec3208b5b92054a58b7523175cacbb6f4b2a9b0650d640521c6a936894961329b939a742084c5722af0bd1438ae68bd1d2b9dbecb0081c77c079b281aecc8672a1852bbec32bab71d125268a486619c20c9a6caf16ad393b164c3937530993ddc85d2e4f2a4bd5ca8bd2bda41a39ce47fe2024a7015a95f69f4b4dc68d775f47d41c430e160521ce814de58c97875fcac964853861f21a6ad9cb45ee211450fc71cbbff50a8f0cbadcef00ed4e76fae6946e3979c793b2f4aade076d8925331608a23f22460749716e948bfd59cc14bde830234fad883e33f1b714336888d2df38ca9a55f0f4682f10c26d0710e4287328b475d9674c558ce88d3f5d1d4ad0e2291e16ee4aa8d1768a2c1858c96501a633e338905aa714cae9fd1c8234854489d79be5922dac8dc04f7f1dfaad50743c9045624245d1285e6f16ae0d70f8098e96061a675ca3f03b191afdb35ae46d605e88a74918835ada056bf6c6855d0c00cedbdd9f70a4b85fd6759902dfb369a960e4b78dd89d94f7f70168d9b860a912530969603e58d22b1e7b b9445f4601a08d207c50dc194e73efc49a73ebed4734a7abbfb2217e231bb5f8591b4095bc90d1025aaa875add716ba9 85df6fd950a1946014556e610ca82bfe395e4b68e19c17c864b49226afb73bfeef4d83f51940e3d0de5069b5e1ba9a7c0b93a6a19fe43df603a2ad66f2bb9bd8cb5c3f4e7e1f989a07f5e088c5babb9161a79e8cece447b6dff0ac68e41372a4
03841301a387b95aa112348f7820e71b527f72e47a99aa89b8d54bcafd108058e43fa8ec40884ad4ab5f73ee0b3d922fbaf47a27b95e3a90b4ce015c5ec02353e63b918f74bd61a3ae59223307ae22e55c88d6fbe38a24c1c792d830e00f985f06a06e0768a509087deecc6cc19d67fc7fb9e386532e20d4fc10a3c98e7beb39136a5178cea3a12321963297cd55262455e28692fb6c2dbe372204390a30a52b3ff2655a9bd611ab08362a9fba11c6b305b41ed69221e289e33b962cdeffaef3f10d4eb981a561a83220c09021ec45e4cde654618133d183f83fda6240396aea6017ab20778f2eb0861fad1f32b1980e97b5e9a70e94afe0f5add967268d8cc4c8fcac0412214f6cf9bd88e5d9d6864701cf5f36be75d7b67b6fc06373de68e16c4ce4a6abebefbfde5766a174846de569ea048959dc26d5788495cef9b99b5810711e4e720fa3f964f50ac9f4cbee2541c8054ba9a5ca41fce94ff329866676ee117e8265f44fe84b68090df7bbc934809d3709e9777db50f15366c2060c52aff8c4e9c8557b0124ba9f5f5fac521cb8840f9ab1d8bc4fd3cbf87efe8b96ed9e453852aa6c3033b956f229586bfb908d5cab5932ce1dfb7a177b731af0ea4c86a6bd7e4fee5e44a4e8d6a32fea7e562c02f5eef58ab5eac33f537dd8f7f09bd810b7a89a224c8912456c9e748664de7657f2d61d11df9bf5dcb12484ccdac7718aca6a480ffa5f4b58db0743a6d2c7f34eef23e81cfac351315efffe7acd3bc04c3366b68fb208aa167d1234bf080fd8d371b73ccf3e978001645bb074928a352317572b5a00ca8d4c96c356392835794a8887cacca3646098cc89a763c1bda2e73c923936f0dc0eaeabbf2a03e91a2dce99be46290dd80b25c1ab64cd1bbfe76fc3f02440e90fa8a059898963088f0fdb204931fdd1ebd73f433f7a50e69bc4c0ad3c79e93c96bcb7ee9a2267018d8da8bbe70011c8acb14c793faa2c9ce28b1a0e2ace21148729e18638d6a495eff92bb0aa07a156f0ff558d7d7473a4845b3762cb26e2d6482e6613490262672422166ac48547c0f99d5b55f41659c5ac590fdbac3e3b257b10c5f70dfa61b96c7dacb1c3d82f73528a351872a9069de6cd708a8d4f9ae7669b1cc62c22234f4171afb6fc736344db1facf5b787fa704f6847db68b1a71ccf1f8ea4f410784178142c580107de11beb564256f987b39d8750391e4621698870b0b00dbb66c97fecac9abfb11fe20874fcc50a473114db60bbf12d9c2d754b0b9b3b96fab7da8cc92d94cd7c23809f86c96ddb019ac9825a636dce6cabb40a3239ad273736c9d6d49106457b13a0ba591694df87a18f8869af7cf40f1aaac36c9534625e676b9970021ffe035885c36868f3bc1978e9626b147ca042a81b00f4b3ad2ebbc2ed16a53b7e5668e60b936d4821353fe9385d8a90d362144a0a148cd2d5a2b345cb67c041818701b47b637b4775c50762f73d289db4b41de9d669d004e1062994531be56700e9e3a74c18725cd3cc335d8e5b7fe122a1c7f9b51b6c88d341caf940f4e9649f4bc1bf071d37de2c3bb2712ded21dfdb777f72f2f993275343305c1a1fe49f730ea05d74cfb84c64469bd288bcaf594cc49aa09afa8e3b5d19b6fdce8975b64350475e8e2ab36077abe461df6375860e5df21964e01d4d193b4711154458a0aedda5ffe26d99a052e92ff9b11e27a1eeba4517152038390653090736207f0c68774ecd562d1f944699f3f8e112c70a4b5ef44ac25bc1107d349f5659ab24d85e93429278444151eb5424031c6c44018c2422091b859f209b96b41d94ebfcf7b968ed9613350c333f7ec338842bf52e6f5375b60af7f6103fab60bbe53fd5f18bc67cd12979406558223ba4aae86ab353caa268f671d7aa8b6b7faf9aec3e2703cd474005a61e1ba4b9a61c3986948ab73bbf486f8cada5634f93f06848191d03651a19b28a2cce0c4bd0f0f5d0370f900ccc34832339c706f9a59665075284ef74aaa15a1f561543e36448551ec44fe79b2cce785cfea61227466c1eb84d097616b080c0828f272aee41e535440376cb0a2c985a831da7970de93872aabb15806adfc9c69f61af6336fdf28e0813a20a2b16e8dd0f9dc7acc44fcac68f62dbd96587b28a1a52f4c95eb260d97eb2b40938108098280f2d0626fae48efd804ecc679179013679f6bb1d80648987e20db275cbf4f7c01dfc7a9f3d799c01217cd18712b33d0cea3d8548b52864d406891695957635c98ed918ca5a476c0a63d9d8bdced483d9d725a40ac75032a90423a4930cffa63b7ac74d4eff4b2233952d8ff483153a54e586bb501e205ab60205b0bc514a8aaf4e059961e6e5d86c72d1ac2b8b61b99a98bad7046200bd1bd9d70ad3284f2bf266dc180e7bee323950302190a4295b6e400a861637318094d59fb7d0dc0e5440912da474d4562970d5d510be9c5419cfabc86a1524ee381b7787729f3a2dbff776f3df10a7c3dd86d9d1cd11cc03978ff575716896a2eb584f32ae6ee76a19a53de675874f69f810625f03ff93cef0d48c27601696bd2874f179c053e94c8455553f0e6eed8fea4c0fe9f8e1b6ed7132a7383b114985816f70f665a7e427fe68e7e4811a074f32cf6062731b3c28ba51edad6b3c47c6f4d5011585d018bf6343f714b4cacc9e1cbc3f1617c4875141125ac59e22f9b44e46ea407beec1c32428ab100966baf7a3e0ec948e10b410d6297ff5e93a9730bbfadf b37afa0bf15dd8095ef4d560785c1bec0699e9ee003a5d2981e1827423402de00f26deb79a37b008197b52d1a011357b 8b13a494f264a10f37886eab6772b4892b6a065a2a16c7660ff35eb22b8ad225f906064cb6a4aa8bffb2d3d2f10aaa5f07d3cdc477b056de3a7dc086d5e5984cc846be7fa9ceeca5be4387851b2164739e132b0bb0f96033947a719766e26261
b3ef3868b20008824902316dd0c27d3208cbae7fa60c26937d563a72a5e5b8cc432efbbc820ac890d9d3a75816a835e0cd8934d15f963aa3f40015451950b60ff41f9535278f9a7d184423b22e2a7dc7a9dc5fa5323a30f3742bffd27fab688e76fb5c9ca2b6a9c0e2efd928a46b5e207951304be004c84f3b8632b4edf2792021aa8c60d959d116b3d4d1bc238572284160b8f64cc0fad2df28d1a99645380e63ffd9243efe791b1ae63fa425805c3907bce6a0eb6f9c4c400eb69f3920f978377636b9df4c9ddfbe1992f4a9142466a1625476f0b403c2503882b9ec8d9e212e7dae1d3fe1365bdfa0981f9445c0e21efd9f403f9b9ce9fbb4bb1c1f4713e7cd02cd99ca938ccc111c0ebcb3292303c3add2ed60ff78032c134ea6b6714e803e5183b8c33955bfaafe6655f962f014a273edb8fc357aa44f5d91e14b15d2bb49f3415d404ab4e2cb6b50d152d523279c9cb5d5214d31d78a90d914e2beac7d01752f170c1ab8142a21acec7d2c543c7182db3f6570aaa03b7bbc5df85debb01b20be4dd4de6a1672b5b7dacb726c0a1e78e55121c58c6709dcd1287203ccaedf4e3c24ab55fe75433e31639730a51819d6fa04954f7d7f9e99f3f0ac68f00e295116dda9205714a8caaac3214b255ebef7e8fd2fdb7fb71e52fbd2f890c46629a73409bfe4ca10433cd38853cd25f15fa20860b4ce6bff08517ccf5d25acd892ca5657bdcb2dc922288d6cab1b1ae15cbd32039238ecf136d91d3fa660fd8cacc491964ed14d84532d09d616d6f46df44c2e32646080f602f8c9ba4a2b546e5e1dabe9c3195b0dce1bfcbdc8768a1257d23a76d55056ea149ed35f88df019597b3af4eb5ab762d61ac326128ffde771f00fab00455a413342ff1cbdd631d949d6c69112ca24b1d69f73ea63acc375e02f5b6e47d141c8f63b9942bcd50620940339ce63f57bbb6f4eced148599bc11bb960106746d32a6cb4bc0084dda6dc87e19a4b9b8e6334ef963c14506243dfca1e74bc45d52bca7a6fb67f61a8a59afbfbcc68b1d9766dcaf071d37afd943664300266ec97dff8e0a807bec5db5bfaf6663aebe743c433313e6abf001e442be7849d8f6d8708d9a1198b9a9bbff122206996585c5efaac7753fe386c47e53c13cda746636084357ba71fcfd9d34d2777455cbc0c6174cc19b73f9741622105f10a1781ded7809bba97688a631f0532ec209901fe55370651baf40a7b768e1df429c98e62d9c6df70ea9011cd57ba18a43e408d83efe59c8f978f3b7ff1dd0140e05abe5422da21afb6ccdbba6410db74a9d9e6d2275f60a67d2ada0525e5674fc96c5149fed0f568195eb2dace244b7d3f63e0fea05ac35aca6b408d32cabac007636fae122f145ee5bf45433e7a1e46f922122cada056e71e36974b294a6c41ae9f3e4ec7296e65af53a254e40780a5b9ef87e780dfd7d045bb73a1f4bd0fe83eb3e2c44cdc14b2527e7fe1ae6bcf5557e7572a0f8047999c9b4a6191bda351c9e57dfebb30c5600971af97c5dc442a36fc2e63367a4025ad0c2d348014e7cd6672fca3889d4533f7994bdac6f82a246d20d5a70e18dcccdcdb713d57ad812af0a8e680fdb37c4801548b3070a09974d1c9ca0e917f2a964a7195309acc0af653784259da286839f5108d21e8dbbcfbbf3c253cce771778352b0a38bf4ba59a0df8f9905627c5b00f213d99606b2d8dd267796edfb18460c6365dd89a7c6f9fe47e6e118a4526c2b99d426b65cdf8e96a520be73191ec01b1f05950879f8cddb39b387dc7994d3d1deccb94cc4b83f1427bc81e39e7825bcf045bd657d73825699eeb41b5468690932d6f8800a2c02f64087733a4ad3ff8c92d2e6c307786758d382f87d2674e66c8597acf436024b8f3db40b46691b689422e96fefed17d665c2b4ff2ceeaffb89ba06cfb9498b0c789e3b6239a714735043eb239abf5f258c9605c9c899e6edfadd60b7a7eaae11e80cf531f72b9655ce76e3f841a2fcd80db2f5183e9fcb855e490582966fabb46bf24bb54d63587dd9ad1e3a5a211e065e38966b2da9ae0c2c9651d2488497720cbf2bf4f3ec627e109c6155f98b85e456cb4c79cdc3c38a851593d2885add4f5979a3af339cc60f481e53c7318968952eee2604dcd588de18cada3d576610005e2f026f05e4959a5110de4e850f5410eeb712dde4df02f84b5c6304a9687702acc94979c59c4cd379a7e57241009c15f3d47a3f331a7d97f518424b5c738b50b855c2692724e1819acdbda6132c68e341a9b2322bc9e4c0a12f38172ef466d1cb0c94be18123d22c7cf585361d83da8162bf5b6c86338cf7bd3e3f4c47590ef984f3034ba105c99216c4ab09b3a299b5b1c873cbc17839bf506a4586b21b068e0636aa4568af9f5c9e2673bbda477e400d4db841ec77b309083fbdc129380ee9bbf173fdee707b5555e714d213f164613011683fa99ef2dbc63a858f19225cb7dcd03af71ab9e9175c504dea2e67de2e649799fb636e407fd4bad13c647577e8daaaa3ee77f08e1e81a950c9f885d7642d0b0221fe8b4195ec6cee5dc6ea8060d53e6dd82c938d5e408d4ad72935215e74b3263b48ed01d773405222bd53a9aa2ee7151f53e2152cf75e4ce23668f5a56b3e5f2481a6cf4d79c1555734ad31a72d8a9384f33fd40dfc1496eccf072e2d4b00d88aef0f8f0581597867e4f868e73198b8c9593d09e213031b25b7d9e347b8d6e7f5eb053537c0c812b273ceaf8 ae25786d0f109bfa68ce17dd6ed17c72ae88c87f367a2e0dae6fb879298d2576981984d368e99a8683fceecd4ce78040 89f52f4ef5296efd834e9f6da5db955c3e61c4d4a4cf6145ef16cd9275e6920689c91b3234c14dbbadfc94cc8dcf8f010157fb532fc7b10116ec5f06719611596e475bbc522c01db6a1adfcd0d7745134d355c9e7b92f9596517b4649cf977b3
64876c7213f3c333ceea0f0e2c9e03441e7cf648a691a23e6f05cd359c36e90feedf6bce0fe7490ae31b2a28e0e1b56a48b079416b8c5ad4c3f242897c5af4eb08305ae7e824c78365ba039e134cfda67de41cb3b06f6d3d077670075099898bc9cd616331033bba6c61f7d2599f04cdb6ed55451af740c68f1b0d53dc4365d5546e7d77e67ba00d81e64b87cd4b414240006821e318fb6bb8c4a4c31da27ba6d3389d42dd949b0db55a94f6e234c6f56e6b8e73d524a8e1227a948af9dc2aa10df42f6a627e7cad1cb761e185b30d8e37fb40365fab7bdbecfca6ab05fa51c2d72a58aba3d7ec28a144ec9df7f5011b8ada3cc166a7f37ea21d29236e84fcaa84eb7e7abd2c414062c71c64dfc01571381d092559fe8041ce6b32e7247186ef24d6c372f6a0aae2dc83c97ba2f1905e444276eacd356e3ee8544ca8fde2a89c2e7e90a70db369565bca40aca658cf0f7a91040adfa5bd95e9df3e3c77b6cc2e927de8337ae761824b1f53d578d12a17b7a79adef6dc987e43d33742f659141b67e5b6dec1d549c163815b5e60359c215e1be3969b9a5c1d9cdef30df6b97a755748486c5aac7923b207d86e1eeabeac546628be164eee7a9d0da54740ad0e9ec19a191eebae81a40ca825a654f16a4d770abfd395926d7bca83dfc68b5da4916fe1f8951834ca0602af2a5b297adc58acb682b1eec91b94b9ddaba6664c91fcae13f8eba7e967e1723260ecead06293a8b07427e21453a70c5dcd0ad6db52f3c3f74bd8e567d8e2f97135f1494e465d89a941502c78b5126703919b425ea7ab23751ffb91cfda7fb5fb315a35b64491f3bb4a93c2d00b35473358dec1635e7e50456e05eae16f30f9d0dbb58b68d3b418ab293837469de957eb5664b48418243ec23aef3e212439b02af0cb02c190d5e6135a45fab09b241798778a0ada002783744eaecab644dc3d1f823281a3cba5c03d457b05ce7743ee4ffbfb8b476c62bde5990b3eb359cc71609b1b211db283c6279a3610e8e6e24d7453d605757d4bb8df06cc486d3049930b5e7c951ac462e5bad8cc2906ee7308113c04c97245ed66c6390707f29a38e827adfcfd917684febe0c68f55eca08297d9f83cc57c8280107236943770ffd2563598b4bf421c0b834147a0495b2351db92aa996324f79e0c329ddd83d7623857bd56bb8a78844ca018c7fb8df81fca5b8b27a20279fbde01666a084ca6c9d2b36f2cb70b95380dbe6f711869d7c42cc7c9c427c8ce9affc38f8c6adb6f71ad07d7fad61a047d74b6fd3bcc2816aeb7f4deb18f52f5c4b85ce1bc5a38468e946c8db0013993ba06402aac4f216c2fdb05b5cc737d1f474498968e806d7a06f339f7402d5185f659dca2f00b52823b5f864fa819330feaa845a57193807094d7b460d710a0903f80bcaf2bf55d512e9d85b89ed94e5bd74d3c425dd32841bd6a8ab90a53f0eda98243b929403521b612ae5ebad21f59301815c947ca2d7425d43ddd9c7272e370187023a59af2a95420ca38aa9e3b96c744320f522fe20934ddf0234c38fb32a316a524068805df7500ca6b1ecf2e3682d0acb9f0399ffb4779efc182d49a761e441c3557d2738925b76612cf48df7178b2f8e736293d8f760f80d648157b5e9137b35deca64210ef6eb9800ba01920f463771e29af4e21fd652ac86f9b1da5ff3e45a8a8d2508c7155cdd37584ab7495126fe7f4c8b4ba9e31b423bfa9d53a8329b74b7f763e211546d86694ee54c6ac0e16ea0dcfaea4393925fb40e2eda70242fb976f8809d9255b90ace40df6b2dbc6ca8bbdaeca4028b503fc29219d5d0dd0cb1ab61335b5a80f699cbce51b938644fb77464b4339f9ee0bc3435d7f43d7456f0073937a42419db24c12865f512522111b329bce1afc57302c8bdf69a7850c7adfbe3550007be32daee2b4df5745361b247ef3ce34acda913001a8e1bbd7c79eda6bae3fa559a21dbbc8675beb3cbf20c0fff3d60ded6a7d7204cafce1af4826ca9dd9258fa596e47dd38ad3319638c5266b2e4a0ee1d969884230856bb08ab1ddfa93bdea76761012c69f088d840c19ff853a1522d9bfd179189b85ba9c4923694468d3ab95f761710cd41d7315ec9573d766e1feddfc25099647199ce1aa6e9397e4c3e20c41956a1f77fdf18c5547e963b74066d732e08e72d24894e9c09cfa228e8b4bde5b26fd90658f6f7792a86818d6d802b741a2d15af9ef2f4eff4286c0253678c8996a3f0f01bda795e3f157e7b40d4b92f9fc8f30f713db2a30c48f531c98efedfab3fcbde9c3a5bffd35b8b24dc4bb7009eeceff4a5c48c3f392add07fbb258a38348060940616775025f7abac1f464ef33f50a4da4685d4247a77e34932093ad7a03824e9329c974ead42b8d824378107f8683f507bb74444d1b6e9f65d6dbfcb1bfacf2c4e3802e1f6e0fda2c7f2d73d8b51aad19d5202587c35a36dcf4c43d41156971daa61d033b59e720b4c6a6663f2928df12d6d347955f93723e211e38d8b8feefc723b21fb4c3566d88b64aab1cfd484580b96ac31677bc2489768803602c014bb3bcd943aecac32b4fdbd1f2cf13b9a7782bb273e5d3ddb221f3de6e66697621fdee3606c819364547030537c073aa3d48accf6e002bee3955e9a5c52440e6c6e922de90a6bdbd73bf81c2382d211fdd6af2a5a33123b1eab7131026fe90e3dd4c3a8a662a6619549dad020b75d5a748e9900c294f39e71feee44cdf9a608bcc673f16de 8177eb8d3a6753a9e997e267cb290f7d2ba9d67aec074bfae93429c89c227c3c234bf9734ae427a1d1da49dfb05727ff a5e590c3bc2a5d2ee230e662db4f5e51a8a3fa590d6dffb7da5ac3945a3555b3f959204b7569937743ee7691c24140690df96079b145ef578bb450434a845b1c98fb77e4aa0e0a9b812284fe7d71dc36c6c2b019d9087f5b4980fef773ca46e2