From bdcf630aa934edb910c6608adc62ab0062f45169 Mon Sep 17 00:00:00 2001 From: Daniil Polyakov Date: Fri, 29 May 2026 21:07:46 +0300 Subject: [PATCH 1/2] feat(sequencer): update to a new zone sdk --- .deny.toml | 1 + Cargo.lock | 272 ++++++++++++---------- Cargo.toml | 14 +- integration_tests/tests/bridge.rs | 6 +- lez/sequencer/core/src/block_publisher.rs | 7 +- 5 files changed, 161 insertions(+), 139 deletions(-) diff --git a/.deny.toml b/.deny.toml index 8de5ab88..11566484 100644 --- a/.deny.toml +++ b/.deny.toml @@ -56,6 +56,7 @@ unused-allowed-license = "deny" allow-git = [ "https://github.com/EspressoSystems/jellyfish.git", "https://github.com/logos-blockchain/logos-blockchain.git", + "https://github.com/logos-blockchain/logos-blockchain-circuits.git", ] unknown-git = "deny" unknown-registry = "deny" diff --git a/Cargo.lock b/Cargo.lock index 8df9808a..ec3f641e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2707,7 +2707,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -2805,6 +2805,17 @@ dependencies = [ "serde", ] +[[package]] +name = "fd-lock" +version = "4.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" +dependencies = [ + "cfg-if", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "ferroid" version = "2.0.0" @@ -5451,7 +5462,7 @@ checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f" [[package]] name = "logos-blockchain-blend-crypto" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "blake2", "logos-blockchain-groth16", @@ -5465,7 +5476,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-message" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "blake2", "derivative", @@ -5489,7 +5500,7 @@ dependencies = [ [[package]] name = "logos-blockchain-blend-proofs" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ed25519-dalek", "generic-array 1.4.3", @@ -5509,7 +5520,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-broadcast-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "derivative", @@ -5525,7 +5536,7 @@ dependencies = [ [[package]] name = "logos-blockchain-chain-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "bytes", @@ -5554,19 +5565,88 @@ dependencies = [ "tracing-futures", ] +[[package]] +name = "logos-blockchain-circuits-build" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "dirs", + "fd-lock", + "flate2", + "tar", + "ureq", +] + +[[package]] +name = "logos-blockchain-circuits-common" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-types", +] + +[[package]] +name = "logos-blockchain-circuits-poc-sys" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-build", + "logos-blockchain-circuits-common", + "logos-blockchain-circuits-types", +] + +[[package]] +name = "logos-blockchain-circuits-pol-sys" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-build", + "logos-blockchain-circuits-common", + "logos-blockchain-circuits-types", +] + +[[package]] +name = "logos-blockchain-circuits-poq-sys" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-build", + "logos-blockchain-circuits-common", + "logos-blockchain-circuits-types", +] + [[package]] name = "logos-blockchain-circuits-prover" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "logos-blockchain-circuits-utils", "tempfile", ] +[[package]] +name = "logos-blockchain-circuits-signature-sys" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "logos-blockchain-circuits-build", + "logos-blockchain-circuits-common", + "logos-blockchain-circuits-types", +] + +[[package]] +name = "logos-blockchain-circuits-types" +version = "0.5.0" +source = "git+https://github.com/logos-blockchain/logos-blockchain-circuits.git?rev=2e79ac30831d89e6a349720c08d5b8b9978970e0#2e79ac30831d89e6a349720c08d5b8b9978970e0" +dependencies = [ + "bytes", + "libc", +] + [[package]] name = "logos-blockchain-circuits-utils" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "dirs", ] @@ -5574,7 +5654,7 @@ dependencies = [ [[package]] name = "logos-blockchain-common-http-client" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "futures", "hex", @@ -5596,7 +5676,7 @@ dependencies = [ [[package]] name = "logos-blockchain-core" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-ff 0.4.2", "bincode", @@ -5629,7 +5709,7 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-engine" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "logos-blockchain-pol", "logos-blockchain-utils", @@ -5644,7 +5724,7 @@ dependencies = [ [[package]] name = "logos-blockchain-cryptarchia-sync" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "bytes", "futures", @@ -5663,7 +5743,7 @@ dependencies = [ [[package]] name = "logos-blockchain-groth16" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-bn254 0.4.0", "ark-ec 0.4.2", @@ -5681,7 +5761,7 @@ dependencies = [ [[package]] name = "logos-blockchain-http-api-common" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "axum 0.7.9", "logos-blockchain-core", @@ -5701,7 +5781,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-keys" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "bytes", @@ -5727,7 +5807,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-macros" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "proc-macro2", "quote", @@ -5737,7 +5817,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-operators" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "logos-blockchain-blend-proofs", @@ -5753,7 +5833,7 @@ dependencies = [ [[package]] name = "logos-blockchain-key-management-system-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "log", @@ -5770,7 +5850,7 @@ dependencies = [ [[package]] name = "logos-blockchain-ledger" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "derivative", "logos-blockchain-blend-crypto", @@ -5796,7 +5876,7 @@ dependencies = [ [[package]] name = "logos-blockchain-libp2p" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "backon", @@ -5825,7 +5905,7 @@ dependencies = [ [[package]] name = "logos-blockchain-log-targets" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "logos-blockchain-log-targets-macros", ] @@ -5833,7 +5913,7 @@ dependencies = [ [[package]] name = "logos-blockchain-log-targets-macros" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "proc-macro2", "quote", @@ -5843,7 +5923,7 @@ dependencies = [ [[package]] name = "logos-blockchain-mmr" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-ff 0.4.2", "logos-blockchain-groth16", @@ -5856,7 +5936,7 @@ dependencies = [ [[package]] name = "logos-blockchain-network-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "futures", @@ -5877,13 +5957,14 @@ dependencies = [ [[package]] name = "logos-blockchain-poc" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ + "logos-blockchain-circuits-poc-sys", "logos-blockchain-circuits-prover", + "logos-blockchain-circuits-types", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", "logos-blockchain-proofs-error", - "logos-blockchain-witness-generator", "num-bigint 0.4.6", "serde", "serde_json", @@ -5893,15 +5974,16 @@ dependencies = [ [[package]] name = "logos-blockchain-pol" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "astro-float", + "logos-blockchain-circuits-pol-sys", "logos-blockchain-circuits-prover", + "logos-blockchain-circuits-types", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", "logos-blockchain-proofs-error", "logos-blockchain-utils", - "logos-blockchain-witness-generator", "num-bigint 0.4.6", "num-traits", "serde", @@ -5912,14 +5994,15 @@ dependencies = [ [[package]] name = "logos-blockchain-poq" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ + "logos-blockchain-circuits-poq-sys", "logos-blockchain-circuits-prover", + "logos-blockchain-circuits-types", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", "logos-blockchain-pol", "logos-blockchain-proofs-error", - "logos-blockchain-witness-generator", "num-bigint 0.4.6", "serde", "serde_json", @@ -5930,7 +6013,7 @@ dependencies = [ [[package]] name = "logos-blockchain-poseidon2" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-bn254 0.4.0", "ark-ff 0.4.2", @@ -5941,8 +6024,9 @@ dependencies = [ [[package]] name = "logos-blockchain-proofs-error" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ + "logos-blockchain-circuits-types", "logos-blockchain-groth16", "serde_json", "thiserror 2.0.18", @@ -5951,7 +6035,7 @@ dependencies = [ [[package]] name = "logos-blockchain-services-utils" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "futures", @@ -5966,7 +6050,7 @@ dependencies = [ [[package]] name = "logos-blockchain-storage-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "bytes", @@ -5985,7 +6069,7 @@ dependencies = [ [[package]] name = "logos-blockchain-time-service" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "futures", @@ -6008,7 +6092,7 @@ dependencies = [ [[package]] name = "logos-blockchain-tracing" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "flate2", "logos-blockchain-log-targets", @@ -6034,7 +6118,7 @@ dependencies = [ [[package]] name = "logos-blockchain-utils" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "blake2", @@ -6053,7 +6137,7 @@ dependencies = [ [[package]] name = "logos-blockchain-utxotree" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "ark-ff 0.4.2", "logos-blockchain-groth16", @@ -6064,25 +6148,18 @@ dependencies = [ "thiserror 2.0.18", ] -[[package]] -name = "logos-blockchain-witness-generator" -version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" -dependencies = [ - "tempfile", -] - [[package]] name = "logos-blockchain-zksign" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "logos-blockchain-circuits-prover", + "logos-blockchain-circuits-signature-sys", + "logos-blockchain-circuits-types", "logos-blockchain-circuits-utils", "logos-blockchain-groth16", "logos-blockchain-poseidon2", "logos-blockchain-proofs-error", - "logos-blockchain-witness-generator", "num-bigint 0.4.6", "serde", "serde_json", @@ -6093,7 +6170,7 @@ dependencies = [ [[package]] name = "logos-blockchain-zone-sdk" version = "0.1.2" -source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=dd055cc1ef7c130f710a52a190edd97bc7b0f71b#dd055cc1ef7c130f710a52a190edd97bc7b0f71b" +source = "git+https://github.com/logos-blockchain/logos-blockchain.git?rev=db9a8d821c1b20f29b03d02072817150cf969b8e#db9a8d821c1b20f29b03d02072817150cf969b8e" dependencies = [ "async-trait", "futures", @@ -7776,7 +7853,7 @@ dependencies = [ "once_cell", "socket2 0.6.4", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.59.0", ] [[package]] @@ -8687,7 +8764,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -9677,6 +9754,17 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +[[package]] +name = "tar" +version = "0.4.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" +dependencies = [ + "filetime", + "libc", + "xattr", +] + [[package]] name = "target-lexicon" version = "0.13.5" @@ -9693,7 +9781,7 @@ dependencies = [ "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -10636,12 +10724,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0" dependencies = [ "base64", + "flate2", "log", "percent-encoding", "rustls", "rustls-pki-types", "ureq-proto", "utf8-zero", + "webpki-roots", ] [[package]] @@ -11115,7 +11205,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -11263,15 +11353,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.5", -] - [[package]] name = "windows-sys" version = "0.61.2" @@ -11305,30 +11386,13 @@ dependencies = [ "windows_aarch64_gnullvm 0.52.6", "windows_aarch64_msvc 0.52.6", "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", + "windows_i686_gnullvm", "windows_i686_msvc 0.52.6", "windows_x86_64_gnu 0.52.6", "windows_x86_64_gnullvm 0.52.6", "windows_x86_64_msvc 0.52.6", ] -[[package]] -name = "windows-targets" -version = "0.53.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" -dependencies = [ - "windows-link", - "windows_aarch64_gnullvm 0.53.1", - "windows_aarch64_msvc 0.53.1", - "windows_i686_gnu 0.53.1", - "windows_i686_gnullvm 0.53.1", - "windows_i686_msvc 0.53.1", - "windows_x86_64_gnu 0.53.1", - "windows_x86_64_gnullvm 0.53.1", - "windows_x86_64_msvc 0.53.1", -] - [[package]] name = "windows-threading" version = "0.2.1" @@ -11350,12 +11414,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -11368,12 +11426,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -11386,24 +11438,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" -[[package]] -name = "windows_i686_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" - [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -11416,12 +11456,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_i686_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -11434,12 +11468,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" - [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -11452,12 +11480,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -11470,12 +11492,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" - [[package]] name = "winnow" version = "0.7.15" diff --git a/Cargo.toml b/Cargo.toml index 2cfbe059..d3e38fcc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -139,13 +139,13 @@ schemars = "1.2" async-stream = "0.3.6" criterion = { version = "0.8", features = ["html_reports"] } -logos-blockchain-common-http-client = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-key-management-system-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-core = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-chain-broadcast-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-chain-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-zone-sdk = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } -logos-blockchain-http-api-common = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "dd055cc1ef7c130f710a52a190edd97bc7b0f71b" } +logos-blockchain-common-http-client = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-key-management-system-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-core = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-chain-broadcast-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-chain-service = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-zone-sdk = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } +logos-blockchain-http-api-common = { git = "https://github.com/logos-blockchain/logos-blockchain.git", rev = "db9a8d821c1b20f29b03d02072817150cf969b8e" } rocksdb = { version = "0.24.0", default-features = false, features = [ "snappy", diff --git a/integration_tests/tests/bridge.rs b/integration_tests/tests/bridge.rs index 72157952..e6c0cd0c 100644 --- a/integration_tests/tests/bridge.rs +++ b/integration_tests/tests/bridge.rs @@ -204,7 +204,9 @@ async fn submit_bedrock_deposit( // Encode deposit metadata let metadata = borsh::to_vec(&DepositMetadata { recipient_id }) - .context("Failed to encode deposit metadata")?; + .context("Failed to encode deposit metadata")? + .try_into() + .context("Encoded metadata is too big")?; let funding_key = "2e03b2eff5a45478e7e79668d2a146cf2c5c7925bce927f2b1c67f2ab4fc0d26"; @@ -307,7 +309,7 @@ async fn submit_bedrock_deposit( tip: None, deposit: DepositOp { channel_id, - inputs: Inputs::new(vec![selected_note_id]), + inputs: Inputs::new(selected_note_id), metadata, }, change_public_key: balance.address, diff --git a/lez/sequencer/core/src/block_publisher.rs b/lez/sequencer/core/src/block_publisher.rs index 62cd7259..f07a47c6 100644 --- a/lez/sequencer/core/src/block_publisher.rs +++ b/lez/sequencer/core/src/block_publisher.rs @@ -94,7 +94,7 @@ impl BlockPublisherTrait for ZoneSdkPublisher { continue; }; match event { - Event::Published { checkpoint, .. } => on_checkpoint(checkpoint), + Event::Checkpoint { checkpoint } => on_checkpoint(checkpoint), Event::TxsFinalized { items } => { for op in items.into_iter().flat_map(|item| item.ops) { match op { @@ -111,7 +111,10 @@ impl BlockPublisherTrait for ZoneSdkPublisher { } } } - Event::ChannelUpdate { .. } | Event::Ready => {} + Event::ChannelUpdate { .. } + | Event::Published { .. } + | Event::Readiness { .. } + | Event::TurnNotification { .. } => {} } } }); From 7f5590907ff9727a6cfc109ac41da980a03d3a3e Mon Sep 17 00:00:00 2001 From: Daniil Polyakov Date: Fri, 29 May 2026 22:44:48 +0300 Subject: [PATCH 2/2] feat(sequencer): make bridge deposits fault-tolerant --- .deny.toml | 2 +- Cargo.lock | 1 + artifacts/program_methods/bridge.bin | Bin 419624 -> 425196 bytes integration_tests/tests/bridge.rs | 2 + lez/sequencer/core/Cargo.toml | 1 + lez/sequencer/core/src/block_store.rs | 23 +- lez/sequencer/core/src/lib.rs | 292 +++++++++++++++++-- lez/storage/src/sequencer/mod.rs | 77 ++++- lez/storage/src/sequencer/sequencer_cells.rs | 65 ++++- program_methods/guest/src/bin/bridge.rs | 1 + programs/bridge/core/src/lib.rs | 3 + 11 files changed, 439 insertions(+), 28 deletions(-) diff --git a/.deny.toml b/.deny.toml index 11566484..21d40007 100644 --- a/.deny.toml +++ b/.deny.toml @@ -13,7 +13,7 @@ ignore = [ { id = "RUSTSEC-2025-0055", reason = "`tracing-subscriber` v0.2.25 pulled in by ark-relations v0.4.0 - will be addressed before mainnet" }, { id = "RUSTSEC-2025-0141", reason = "`bincode` is unmaintained but continuing to use it." }, { id = "RUSTSEC-2023-0089", reason = "atomic-polyfill is pulled transitively via risc0-zkvm; waiting on upstream fix (see https://github.com/risc0/risc0/issues/3453)" }, -{ id = "RUSTSEC-2026-0118", reason = "`hickory-proto` v0.25.0-alpha.5 is present transitively from logos crates, modification may break integration" }, + { id = "RUSTSEC-2026-0118", reason = "`hickory-proto` v0.25.0-alpha.5 is present transitively from logos crates, modification may break integration" }, { id = "RUSTSEC-2026-0119", reason = "`hickory-proto` v0.25.0-alpha.5 is present transitively from logos crates, modification may break integration" }, { id = "RUSTSEC-2024-0370", reason = "transitive dependency of `logos-blockchain-http-api-common`, can't do anything than wait for upstream fix" }, ] diff --git a/Cargo.lock b/Cargo.lock index ec3f641e..d5ce6321 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9042,6 +9042,7 @@ dependencies = [ "logos-blockchain-zone-sdk", "mempool", "rand 0.8.6", + "risc0-zkvm", "serde", "serde_json", "storage", diff --git a/artifacts/program_methods/bridge.bin b/artifacts/program_methods/bridge.bin index 4c224cb4f474777fa68e823a17cdb419457771ba..9810c6ac4805b30ad94ec5e3cbe1508f623d2cc7 100644 GIT binary patch delta 116723 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 Yj80af-?3?Q(7EfeRlnU8y8HV72b|L9^#A|> delta 111640 zcmb4s3tUyj_Wz#QXP?7Uz$1bPcsPf*fS>}t0~LIsX=zz$sc7lV2bu3Ipdenzh!< z-sf=fT8EuSJFE()MHf~_hWU&==uo;VigNgy)%_>s9(jl=;?jUo0u_azs9#8x`sGgj zvTRTk{c2TzJV;fJr@8cNEbyZVPifLp)CjxkxvxpnY|P=6ZCj-%-xd`uVpF|pZRPs? zINZB=TzBfv8Z!J?sBe_4$QsGAd?PxhyA(Am*u}I!#qNWv#G>$ez2SDYz_+iYt-6&R z@QtuF5Ol6wU}t-C9~^*L)Nv*sT(56}`vKWQ4P2{t;3JRlWY}^r{3eRgdY@Tcz{Ww`F=+)%x@# z&0;YB%xwc`` z1N$1f_hIEGUa_$Yf$0Xl%A$h|8l{O%4RX?~$Jj~~%3@X?wC7G;^43j|Hf6BOS&HIs z*9Iz5Bi2p2frvUwpu!!x1joA^Yn53I_g!xi+Eg8JX;_hLe|+dvZmA!#hQ!-w)xwH_odXEz!$v0!AgOFal8gL{9Z0$r_kPLOI_rIx?!1|YSxS{v z_TN&+Qd80kbw5@#8`k&Rf7EL?jL$%G^gn4*Tk%-5TFenvZ}~dX`|7NQPM7S2{NhRp z@^d8>`?(TV`?=zy{9UnW{;ue3f0uKV|Gh59M1NPxL%w#4rsS`*_OUOwDr|{{PK!0W zwaCzyqPk-MYt>qQsYcx~nxe+$C~8cJ;)>m)xZCs<*Za((KWzf*(pVR?B49L z&aT4PJwBlDaU~w}aV4F_b&0xCi0X0#X)fnBiz|AM#T8p^am63AxDwA=)RW-^c)p%lY$7h4~EJnP95eZS_sugz}%J^*Jirz-S4aHa#V^NHyxKb`D zg)RpMa|WsTe%>&{Vomq=x)~}TsyW4)G{b6*SuS}?Gc@h0Xp3FjhS(v@(8OhJR)eD~ z?qD#|zD#k2R4QulHq{*r2HT%i-R+6R)fRX=M9~hS2tJ-8++d=bGs@=9nP^jUAF{b~ zi*4$lAe(zoluaF+W^)hDwz>Nsv#JBmTHOOKS=AB5<{q)ys@}TI>b`Z4)jg!z$^!3h z7pM*$WpxjoXjO+jWOWZKwzBfBo&Bxu!BJLs|1>nu23cxnf6YDQtfmgVq`8L@D|2*< z3)0-TZqq8h8%orndw|7Ui&E1Hy#tks3$ug@p&%$G5lTwhhAT*w3c6%*IiVC?L1&?$ zYA9%%CBIG2U{@06nS#qftS%?PTC9fbAX}?KbXgVYYv!^VQ|;}6O|p`?N`Ba0FL!jY zrY2Nt?gU~jR1>qUYD_WgsT#hGsL-|wEn2~l6@yu!MNv;sPef=yJ+!(F1H)n*sCOR2 zz{NJE6+=l1<$55lT4>jnVBrhTYvMGIWfYhgLjnk&A$=1Lr>xf~XMVWd_#Rv$Q4 zAJ))4qEN2ha&z^{7*<7ugEUrNt2)H6K;7}>narPp9{{A#-6%mwv=frgtGHnO8;^QpS2@#F5=> zLPjRBvol|Wvhob?I6dRh{$=ocOlCZXJ~c8P%CkhqlQjxi&0Q@?T9LwhilnoZ-iNT! znYWNUwl?#x7AmB1z9N-_`_-wGi)>eq86i?am+YFa;hObyE{>)4>_}o*Ue9}wU+nDJ zn|#U6^^7B@nP0CCQgU^lK_v>aRwE~~Dv~oLPjX&&+HOVkF454ZRSEf;C=V#_&S$B= zuc`Q{R|i5g7Wi~F8`9@)Qo-s^bOO*0UOwNOYmo~It6+qcB@#m zdS-WuIX-=jz1*)$ob>)@4g3cx=-e^cruR4S%KK|>>74%0e8pn12X|NO?dB-myvwpO z*CK7S)SP0=m)Kmo_8~UmmJsqKU-cP@VC!y)H*%FdY~-wnLgv1-nGlvTI5kre&F_Kwq|Dz<1J2b6>Xu zk44;uuhQEWunhydAy6L~*g-Cxl3%3(mi}U>pU5@Iu@TF}98+J`h zahq4G;cpr}YrhynI`u-`t4FG_aKMI4q)$|~3L^X5U?snu7HM|cdfvvI5w0PZM98IO zzBdoJr)5Bl*LH7c^LWFc1g_{#xUhM^aIL*Nk@%>cvwh%jy>WEK%PEm5d?V$LEdd4@3yY!vp%laO9-~a*OeILtHu?#MXu!Kim&u?CDuUZ$A#%2 z9ugI%gCKm)%M}eB#X?8%)qxBm#;UaGNvS?+)<9RvKpXZ5UM^>}w=23$cW>;Ud|l4b zQ21nDHa0Q3&`wCOa46u!8=UyS7{MVzz7v+v$`D}<$jhJ%N3|tW4=lCUZdx6XNjX+W zu_{+bR(Fv)yZpqAx1m4cW31aFvYquq$VfvY2>0aRxFBygj1rl!X0pNphjeTa+20Sk zw9y#U+gOqb%o2muu^OU|!fexg|GwQJlUbvk5(_~zA{R!Ih!qxpOv(HN`L(ru?%g6N zWyS%p4VvoFL+>FQs~VC?Dp|qMVCFwGuw$+`F0f|&4W&0IGicQ=kmi%S+3}%+$V3)C ztQ)zVjU4tMxsx3jw)cN+yABhqfs_4VJ5KB|cnUDdy&e(L;1!lL_I-7hLf z*qISI%}jPkgwM>9p?|Be?W)IF)~yjXoyqswv&pyKLR_ru);KbS9l7;EvXG~CBk`d| z-@&@i6~0{h+}D_2PCVN>GVOLVY6tgHSnwjHV)^zgriu6=X!SMpK)#pebVVbV*PS6^ zt8aBXj}%U!YC#0JK`~b=dZjTtC z%eN%PZY!ot-Ku16hLYM`kN2QtPdycF52!Z+c1f(X{e5wn8$jc=%;iDJmc_@j`rEq< z^l>|?DGX5+D>CE-eS{Zfi#qIgvq*CiB)K|eFV&2mYePcb6`ZQ_v zD;jzQ5u5akV?^dvC_~(XLTc(uOT>}NHO!&b6&uvc6l;Tx0T29n{CQs5g?u(80RM)*s?;&g}* zS)7FWB-AGtf*=`NMQkoXV60vcbO%9q5Tv6%9rcKACGmO(>8MXfeFo|?FaTl< z>QhkfI3~84-B8~R_1)Ek?CxmaycK0yu{f}h8;Am>P$XyB?u6p5YGQR)#FlP|EofYv zp~hCDbCRiV0OH{X6RY9Hk9p-=Ubd>vADL7rU#r*$Gp*1eqTXb8=WL4_U5vm(IwJ7k=md$ER8yuq+5&i> z*bXHjM0iQOl96BJOYQ4=D{S2(N=3=`ERnJ3;X_|=RX>RHg8ZVg3Fy-gK~3*hw$17a zTofdcWG`&#FinjiQSO-RD1_iBcWiZ(8b_Qi$7d{At`=~EbKk7)_A9W^bO>Y)(cl&^v4;1ytXNvpC z4~qKXp9-swPbfV6gyKH@oZ^1x6-9mbO~u~nX@zYGAog}kh&_Cz!Z!L5d&HBZBL7R$ zZRTZCF>|BRZPq4qJ4{h)?or$|52DXU6t-cR!q!k?x4T7Kg{`%S_N3bdFH$k}cBNv{ zWw7U~xIgNsbep^p?K-1fZ^h2GJgs#5dRB9Tidh@k&v!cullCOJQqCs19Mvh1XNoI2 zDA@)3$7x3r_QFY0A;K)NjuhcBl@UU|P+U|i`Mr-cw7aJ}&g84wx!{dqLCB7Eg=bag zx6v|0IxFjx00wVpc;B}R;eIn1Dw$u9=+qCL8j36OQ)~SccWt<$)+H(Kx;~2C521hA z659*Q%B-&CmDU%Q*I3osJkX2-&2+`J;<)vN6{vdxbx+h-?IlaZM!l6WWFe7pDDLgh z*^Xhvz2k{OqQ3Y6LG~HuN?aZ0O4=5tZin<>?(o*~-hJR6M+%7qNdg$3=z zf`$c-a=DxnU9RYDPFL(DC+ZzYFdeR>v?y0fc9gU_Avw~KSxJ;!Usba*&6uPqlxb|u zIJ=0XtR&|aU7q^lQW{{i;+tgBeN>@W#`646((&< zMJAOBJ$6MN*j0_mMow3ZGY;f-IOlLhpG^gq*eZ}T%py&V%f<;;v8u*bt8ScfxuT=G zxnj3FRP^g3A)F4_RFta{ah$AJ|Je+I25P!|rG( z6949e9}T;sVRtmlfN^DrFzrer8LnuO1S3nrJ&X@m^qveX;tVh+e5R;RL46A9Q&2Db zqVx*ZY+u6&ao_@xN@3jNc2pPkQV|v0(b>J!1k%f$P~B5aEbi$}%0!PvGWS9~?BpClRe@U^ghhrTu@=U)7aX9NLV!74-5dCMsw%3Uv^S5thtkD3>u5Uje!M2vJYDx z)DH`W1kg`QA6b=p(u1YOi?GpT0J3i4MmDd88gK4Rtf z8F^yvD0bw&m;l|bOKy{6EFJaQgc2Gevzj~P_@!fv@$ahGIO%nxQoGk+ZoDCZ2P&pd zIZtFRIOOh%u@86?k&fD}byL~YsdvfyeRo$Jp8BZ8*4u?cq+!u4Z^lIVATK9}RnF*Z z(^K4`Iqd3;2%E72S@_IaqodjE!pw;>$F<%gj!h)*wR0p3haP5&&7+j<3+&=}q(VP1 ziuTC0JFf-jc1hfn`69QHbOW3cr!CfxNA$L8l*Gl%ZE5>%CyA?Fi1=l+bw^5E&Lb?e zAR+*}0z7COoB1LHU|U*LF|go05-?XNC+A1ccHv00=UMpdD4Tv?Qp^UBzd375f*=pmC?7#I7L2^D-z`_&hJp<~*<9 z{t4d~?0&^0^Ck4;y?k9o-Xm#Lc3ZMtc3WCzbo(M(`{+Zayes@3%O;&L1T?prPY}l= zS#>Z}c@}2i+4RCu1{-TCY6_>&0DU4kYh{mv80+!)YC(WUsn4?d$Ab&yq&LcX+jDkA zdb_nAhg^j4a($3|Lok~S8aym4z~tdgW&K2EwOFK-OQuVjrJKdtHtO#~y(;@C*=p2p z5gDzhXOrD?O$B7?d|98bxZo~PrAUHbF+}o=Y`>HyQFT-Fb&WM#`o37p-U`>Y%zcMr3ySZFJQa4eR+6-!pkAciO_ z+0`e`_tqsf<#pW#nZ5%V*}Tq6a`jZ#kko!Th;3iyPITtw*DQv8 zy~DEB%VjP@CQO~67@d44xmy37(aEnf@Q?y8E#h_yzod1WbmOhUiw5=UIv8{Qgf*;N*o-e&Z{W2P6|2^d5s&G<;WMyX9lc?q z(cp7-V8c2&v68PV#y;~oF=ly&^?B}d;n?inLk?9qHXbB$sph=N&TaZ|khG?A2z7*6 zw<@}$FRDtHY}cO8)D>N$*9&VzfPhaBC!<1CRb`Sc_#1Y0bFyIv-?OAGI#&?=MYeX! zU(IWC!`2Q|uFc$Ed6wuvS#{&u%>9+sKmU@!`HgxjdtvY2;VYJujWMTsV*|^Mziq(I z?MO2@V&N}7DLO@FbcL0_nASYNg%?{4#&2iOX8OFHnv&Y*e9Wl`e04k3g%Xn!QE{MrlNmX4*o4=H z43nM{$Gq74)az>gEK}#CBvRU!5@*1j3^-Q8&73+6ZlWqKzc$`bZ;pkHtu(}}C9uVn zF$44fWlMrj!0|=7lKCpEyv>+@ePz6`_Fy&ptD76GeEolD zbn(rWMyUs)45R61blSIK!T}^9W*$*+Fxim)p^CDDbBPU+ku863c!lHbG+jWfWN!`| zTQywrQJ2SdRSjuw-B{JqI<>l0>s{|e=>8kwGLO~2t9uZLB9~3CdC%|@hghFleP!Sg z&u})UcCUfYsYtDR)O04<6_tm^6Cp^f`jLiwZk1E9-Bl6)UI*P?V6YJtgFi^udXGBO z#EOew4!K0|Xej$hHHw(~4)Lf+&kMya#-m$b3HA$n;|1(W+8fXI*XzQVt;n6t72T#g-sHMwGsmehQu?{b){M+ANBAVW70;!Rv*0Zki~Y_A z%)LtvJAP)Oq1$vq zHeEiSJjeXbb&&V-wy~sh9XjjsYo>is1a0Ga+a~)`Z2HB{LT{T<#tP0w$+mTCSk*Z^ zY(D4R3XZbvhrGSKRiV|4q6be%qC_FJ2@BvcD7iSl%}iWq)^U zV3pr2bm@K6?h%g*4E-Nvn3vsV&T9u=FZ?!2jy1QEX%h@O<^4?buf~=pu$ABT4bjKi z5id?+Zy4{)w-L5X&_yo=PZzR9EO906h-Y~h(&b#h)3OU`;vR9}5UaYN%b%6jy~EC2 z2o7iue5rMjVXN;m%Xh>tEdUo;qgaFyoSfl;}7X8Dc0sj_lYeFjgcVu-uhL=g`cviTpwe;%7i4b zM>)@WTrwJ#d{a?yDVYSE*L_(Zb6>@F{W3+4qBXG4U(;+CF-^ZCeb~rflSR+q@)BF} z>xc5b?kXF5`B9thd=7oWPG24)+m>8nJ+4G_S_gV9=MAwCceC73Sx-n}PB(3#lELI{j!K&}%0?7GP$~X6Wc*3UGnVlTzZ8iB%(7ljxD zwqa}km}`2>ioidykJKfTYmm~|+QgmAuJP1Wt*a1TQigQ*Zt50%_S;`GH=+krcD zmQQ@GXcvW35*tYIpviFJ)A@c2Ip_-yW4Hb`O2wAKQ>2mY#P%kbeBy%`o@67NZq>Oj z?JPxshg5nZS~SfNXM$Zr5Wpqz%2WfN$h57h9q+Li^!H1AU9>0Ei=;Qt)-&3hTr&sk z<{9lvR%@nEJr@H>j@nxvzpg9OvhcIrIgk(eskK&W5uXtOAvEs8m-P@Dlw3G12wY3T2 z@If3C=dYNOkiTAwmV;XJ_|{O8ZYVI1pAID*%n9+vP*N;wVu$l39Z1hOeFCw=8KQ>% zG_GEMFSH_mpm%tF8*eId81YUyKi7d=5(B%Q+8&>8@v&s~1QR(!Fms$g`&9nn@_8wh zUk)RkNh)`ABt31l!f(_r1Z2)JyNy1jImyR2@QCoqDf zt8$8^BYB>KT$2GwyTe#M{iFrgj>i*lBZ$@B#T%R?oG*zY>kR5Kk~%BxZ>jq@$;6I` zJMP@vG;v({LcsAxm(RY`{Pk8Zmyb1-?{^a2!C|+p_Z=a+L7pnImg~kb&#TQ{H*9H? z_nI-R;>d*f(0C~?h$8LUx#BI?rFL6n$fvtVdLgvHmU}0vwaf9kaw-_HH0B4cixg^e z$K<5sUs$K8+cm6E@%m$yCh#JlBjlvIw`*zL?%%8AM_Q>Kcw?+x-7&d%-W05`j9@&c zI-yjE`W4nNmtzNx(D!u}bgtMPsd^c|FV#=nxMOn@)mUpHPl_fl1qd5)YKbm~mI$Ab z$j?QSo}EOqtveE3&+kiw!yvA*_mr=x_KPv=3A|4X(X&j^!m}}kl#oskn3||fwa@zl z4@a_;{Pz1G5b-X15p^f#O!Z{NkxvZ=rcLIKM3P`Q{YiXeGoVf6MTz7`Sp%{;oykiA zuxll=cwP#LFlq|;;3U|rt|YWsmh|7q#wD9%C6oBZfxNF{$!UkvJw zDR~Skd5p(*!^+k9%bCYFj3MCzJvvXd^YAhy-iy~0`4^=r)Xf%e=}BK-Wu)W42~T)N zEUBVmgKiP8=|(Qe1({RA4|FFBZE~S4@$^YI9EzG#f`@`vn%LYc0n9s9$^R-nL@vj= zQob`2o{ zJ)mTBh4<-6hBy0&RXs_EfSY^--`|rwYC0}YpI&4X=_FZLWxQ>UhtoBGxnr<2O#H6i zBu9*Z{BAA3+MB$7i!{#^9PcUl7wQyshgEU!$dzjWbsk)5Y+b5*hc&I+1D{|m*l4Cm zE@N$7-LZqZ@`gSnBn_tj@2&#vianI7m+}8j6;JlCtcZQ71y2YMq3+)hI+j|kC589s zOOnM(K<1R<(HY9!z~}TOa_6xlCxzF5LU4ynCdD07D!5Q8zNuC6ORZMHmCi++EzP~7 zF11_kA*G^rpHgui_3Jg`Shn^bJhdN*68SIYo5IKTgI;yFk@E~c*^dkf>4hk=VyI81 zUzA9ml06?lGEaQ4(bMA=a*#+(SfAyMSy0RSSQ9?)Z|38&$yq~3&wB>;Cnvmh6~vTu z;f_3#-34=U=W5AzTjigw=*mV{Yz-dEoofWwUUt04?14X0UmlX|@`_1zz3iRDSLKnY zI9)xtFX$$$2-D2+b`@EqBiat)WrBD}GCzqCqo~f;3NOt@enBaxU^A-!PU$=*zV(M~~kx1VD=`wx=QzC<2dcIStPbDIOm-za%5) zih%UDYqi~7BrRZ&n5OLk&x_z;sqJ|_`Ytj<3O45`KYSO7k-(Ub_~pAyzE2$IMR$`h z{?6T`lP>BU&4m+2KYWMbI;MZU`BYJ#P~E?|ZG@};z8zC#Zc=x2BJ*Zhu!P&dA|Q%GDY$QQAOWJ(gV^lo>uaOxgq0If$Vq_ zQoN*UboVXae;<~WoXvOZCy>v@!5so^Gw1x`1OzoH;PX6bA_TEcm{CqOA2*SV3K#}* zU*8N5d<0vu;yZp|BH3j2$0tl8JwxDv+_9x;;-M%~AjOj_(pT#uPx&O0Oat_uOTDEG z>U{Xc$z+}FJ#@C*`+Lu_DP)Mgc3`$wJSXobCA70_a7jP4koR~4nS!I{J#ukXuH%OT=?wmPTWa@={s-xx+VpgD>2IDnGvM(4zFQkswU@EA%KD|b+i|nV z7$FioT>72wpGB%=U$*O>q5@J)4XDX8_+jKK0b|4(E$P&(lGAfYOvjs$Eh@1oJbbRX z8ni2X@Lc2}x_(LspFWq22?2oQPc3L+iA&Pc<`g{x~<YCf53%w=h?$8Qn2OEnk?=hGjBmh}E} zVm)4u5lwd^m}WR{S45sPtN6|$88KLCMl@elOrnIGS!rx^zRz!dYHldvg_mM)U#fJw z{}V;dsC~3MuI3u*ebzrt+WXWElxS--Z!89Pdi&p8-0?Vx@YR8DT=|yYEP^;TR+Ge^ zxbo?5*iVkM<+nW)i|=IptYREPVlK~;$4M<6q)VVARDN?J>pH{od_lY1m?`n`lDag` zkZ)&kWM#KjHX1v;sS>}m17B4_q6($Z!o+qHM+rufrKA`{coRi@6~h-hbsxN$*QrtB z4@KBDKj3}zHmuaoOwJOGb|Kh?s0J-w&^Bm6C(bk_eo!=MXrV#WN$jJI`*88Hp%@s% zMBKgv4@q}qr<3=f^7e^YhKtCAUq-c#(-X? zb8&iVO360bNf&6&L@DT^15&`X<1?W>_{Ir*$#SFtQ^YFKiV(^E^xUC)h(Nn-V3TJM z>}9Df!!X`y{K#^1`=~w0{Z^P3QQF&+x`OOB5|_Fm{M-}fYM3{K`>iCk!X~k9hI&q} zB(D==jo!^SJVkm6Zw{X~MylL8T29V(7t`wTou$g_hRTl__}hd~bpNAk-F7<Y$m z35@cjK263OD@7Z}*RDa*j{aH6x^cXI4Sa=Hk%<3NJ3)Ydn#)z{#-Pe=vECw{2M?Z%>m1L$sXoHo&r_}42 z)yKvR9^#9iBNL@3`HyKo%r8GjUYFupHkXGt*+dFsti)7tR z;zf*c!nC~2ZU?&b1jPdy8oyc7EKnk|jz63vP0*hZJ z#{{4=Jo*)Kz8T2cMgEeHY;&M%g|yZ&AHAEbj@yW4etBw|dD$6=UFQhYjBCJJGTGO^#V`~Epk?mPaR?-^W9aLi~}0RLwl=|I4i-F*ul2}1h+cERBVCAHOP|NDqK&j8 zZMv{Vu_SdnYJ-Csz2hnKc-DSQRtL^w=KD!sxzx9h!&j@1xr}2vi+}nFkb$S=OZ_faL>tiNR+XvuFP9sgKV-{!Z*2vku^By zGCEve3wa{+u%(02c%NExT_N(#sU^qcd`kWy%{FVOn9tYLdRdACK6!GT>7dsw;=Ah1 z`M^Z#>sqO!u?|txltIlQ(=O1a;gHz|YHxR#^cVYzyA(!RH(WLng(Bqb+9P8T=9XoQCMS$muV$tlVswiww%*ef|X%o)FG7 zXSrwUzmS{zAkD!;)fLF#dDCRlo)14kHZ&j5Ts#5cN%|*v^e1F^Hvm{dt2}zM(x)^3 z4cNAnGi`!qx6ZjPj|8jk)E~;|8C2<0p0ZC!Un;tR@jt^icBfGu?@vh$>7*0nK5IOl zZqs~@XyPxPf;kumKc2~-A@Q-D2D>YhHuLGH5%3MbQ-2y+S%5yk_LpViR=Ue`_$*1+ zY+I$lJ`Cq#s(+dR&!Y#LWpnk+DmPSEm?T)X%)@C{$jjGZ>^Q{ zsXtaXYj^EPpXVgUVVq&`T|*Jg!|7f%i)Ltka;*0lG4VNGu_t;*=E z$Rg`X-Ztv0v3W7-s;E)-j=^wEOFO*!al%FG1Bx^B?EXD{)Gr2X-RrjWGf`RgQ3m20tNx2K-a zQC@|uG-teR($Va-SzL;)r?4CF8nmqAi$ZU}3++q#5XreI#@rLSI0{5xMLlI*$=ihn ztDop{)GMnpjY?CF|88lhWXQT^F@B+oQE!*kUDlam%>7&!qa3hnrfwj66I+-qCy2%3 z`)pOI1{0_3=6CPq418syo2*K9m~6B;ePf#{n}PrIMtqjl9JpCmdOyx0v!l<%GkJYk z=oLzm(a}j>7v_E%Z^ z>fhEL`c2eMlisH8cRn(ZK4c!}d2pP!jWk0AZE1%#wofto^7n{mm4mLPF5NGQ@8#o2 zL#e_`^ErCP>fTYSc%(NA@(gs*Ao72rTo6s~`aedjS;-};2p61@x#<%M2a6IiPYV_W`5?b{( zFo7Bob#5RpNT9m!*U1ipEKZ;N`9L8Uad`c8pmxr^eIT9%Tk!nL6b^=tPNaS1(CdQu z)I_>4Zks*`1t24c(${2IVi+gp!eDr{G z$mU7vLQhaLN_o7xQoL?q#4OLiZgdopQ!4QlF?qKHG#px{(}aK+-MVb%D@dMY>2w_x zDF;%A={&jzT_?Yik~`f~)q_SE>dFa(`rG73;zyBUhr$GW6!pbA#iPfteSzH4iw>8= zKq+H;nUY%<$d~k@=^bwp7P_(-(+uRtd(k0=fC71RZ~ADGPW?aIoY*1?u`^!W2gf95 zdea%Q59n%iAE_${If(D-L&r2T=GC{ge*4lVWt;6m{A6=YZ5vO!el$&$YtpN&Coh{0 zH~s2-&(?wTQ%$_$gE!7zQuBQ$+o?KGqALER7PbyHqi+z~$B=@mw)Ko1 zE{ySen9~ZMCp>FMP`qrUd*_lTJy|2^CDJS}Jvh~sw3_!@(k0iH%6VItW0zyFk0Vdn zi`%GMfuW7Msy7TdJ#{1dW{Oh!bZhqg@O0D&{?_~Xf!pX=sm`TqJY~1j6U2a4@uD#_ z*Z@}Zjblu&6SLWKd<@0oNPWS@ZuVTggYKasW3~GwZT6JkMPsP#0w6E1E&TL7a4!JZ zvd}F&d>ox3WC7>Cg)bXNhYZrEw0E6kzYe)JrsNQ&lhw`;#RjA9S*A4*Sy$B7sC&*3 z#b!_Fc#1d5e!!r<_muJSdua!|F5UafupzT%>J`Jv`00D$AoYs&Te#nSa40&kzKo~d zhY%qZQpUI5M^|^&S*taM$lby;hsoL(a`>FBa`@aAJmV(NCk>t7UB(+G-Z;ERH-@2Q zJbY5C;qxZ74DTtJL~&Saj=wP<9zh>JcniOnPdi9C)s~4}lI!`MimPltUUI{se8ZM+ zZj#0JR*Y_ub=nTeXz5O#HyIr08Yp>*FP==31MYy#thsg%#>SJVS3LWHv`CFzE$0`f z(w?pyU1J$`>%eQwy5yQC4)9W&&F*FS!=tNq@N0bVG&;UhGa-m#MSoTsvswPg)Q#cr zo4jTkz0%xu)j#O9TXJ=(3}&nOBQst%nOf#$`O`BA_{aM{U{}$T3-@l-W^ZHp!xdli zhbyt{4`a?Ae)U0kH(hMG2l?pf^pc!uUA4VLoLN(RD@T8r{(TFc;wb~NIEnw(=&6b? zoq?j~TR4IxbMG0>#i=uCoPKRc6q+m+^F)YdqAb3WYCPjjZH_medRA^f^0 zegX0uLm{!AWebrPnQ@tKU1Zwclq6oii2l`FbNmrHzGDnzU833S)+LS7cycX<{F8Xz zVnj4uIknS0WsAjH(Ie2IWM2O$J=l^GE@{lvE0)gVTOXt2B`2lxxuuZy4Y(pk$XTEH zn=pAR=OYVga;KJIubRW!ZI)|>b|2vz3+b3RgDBIgxAem*xSEMofDmYbfnSpbzU)yR zS_EcvYhPB#ys{L}YZ&tJ{u?|OifF=(dF}6_`JuI*Xg59Xjbl9=l;aA_=53y&|Db1< z^F>e6FzS`f*FQ;}?WeAADv^Q+A1_=MTvI>gN1voAbn6O!{Yly-t(#-Y^eHo@%$)PE zavbE{KvJLNP{t-ZlyF?BxV&&p$5n)DU^2h=DSAImeS+6LMW5o6pQdvPFF)ZFzc8#U zS?N^#P_9CWCy~m$iL<9ooH@raZRX@D3mmDAK7Ae29DN*V<){xuz4)~7<>3bWJcSq>dz z!V>`J%$_}KHedZ3P2=^es1GlEo(4u9LnlK(nnD#N=%!AxviOc?>2mJ7hUTQa`;=1| z0D_&+Lno9b{1)H{z~@@AzAA}7wuat8CqB(TSwnmIPkh>`B!UJGN4c99Z>P8O0!G`> zlTY(fM*I0pSmjg#P(N!GKgwwPz?IFgQ^A8Dg?q21UF^y(pt}H^hD)%pYZV{5md?y= z1b#f=6_~9Pr3pU?I2>?Rc8gT^4{#_W``;i{U8vpr>q4cUt>%xdqan#?G7?RN(z?%b z;IA}5OjhXuS&C1KZ23FuXh!fOYn+M=_{UNDqkI~r4?p%I9ZS~m``6Q6G?ek@*VB}? zdCaNAfg%hSp7besjDNMB{uHzpc!v(l`Xqjq({8aV@nd^Jd}gz*xEBK~$ZnZeV`tuL z1C4c>G=jb@uJ{D}!N+8FYaV}m1MO!ykmpdi|7O~Gn9_5dTs+Aj6LvIm^2FPxOqrZN zed4qkea1PI8eGe8ZNxPP*GXI#ah2mbeoreF?%}vKHyMx0uEf{K#lweS+ATT)iQqr58FuZrN=h#MH{J; z9$COQZ=~%*7f)~Lqt8t616cII+pMKd{?kUv?i~d&cim*$i$Io zGHK%Ui8J%3+)!UI$D#8f*1Ir+@;Q9cCOU#{n9g6@L}O{eGyK#hu(a}7-fJ@ri;SKx z=}k#rSm01b%o4rAgjVv|n`ug~@aLprZ`R7-g*Ubx87}O&MQfo8`6;w-AC0M*{$b}M z4kZh4;3Da$YM$ezTWCgMRZ$DgvbP*cYj`kVft#?=sT?SFC};3P>KjqkqpU$GKBk}A z3A)zsRKNna(P-OF+!wm7=L(BUM&0(TOPyNhzAL)nGK3s8;* zd=WqG6OVRg+t#qzw%sP#w(O?1l}|gA!|3a>xYjxx%7NABaE(J*xe5aTc>&iE2GT_#51-*l@~Vgd$-XH>b04#-$o$j@RSz$2DWxWJf>8^eHoO-(#y&@kS{==8Tk;eBTT3 z)N{7-Hf8kg$o-%hjrw$4!hNiSZp1I`3;N01#QI*!{qarSNq25@DieTYxO(FfpFCWG zupRaxX8jt#E?g$O1^1m=!O!D98JGDHi~cwUy>lC%x1G+T@z3+0w$m`@;2Jm_;Kgbb zV>E7a;BU)Bpqj)TG{dsC3X8w7Q0u@S-9hi8u`lp1cEAUPzr_F80nGtUd=W6_o%!w_!WMRV!oot_c9=wn3O9Nmq5c;Vp_4&~gx zk>B7d!nNTOhf;9Tp)}&E68KLYiUXws}S<|OXoavY_Vf`*?d0Tcl@6@C1w3&0JJTPUpV*)xUZ>iMl zMk8kuS_ZKW=TDtDdt&|^o%%FzA|WvA9-cFM+DwFwtGoEU<@6u1Tfv06h_XHh>W z;4v7s@G0nO#Xfo};XuWWv+IRAA$0Kxt&|GYOMdoE8qA;f(6+RDCEw?vx3yh@dNI7P zb&6|OC6C-shq|T$9}aj0Iub%HvP3n{c&Zwu^ze`3PkU(lsDfG39-cL`i-@^GR!MuE zy6brkZMx!0+RNYBk1VWUFTcK@_M>HcdB4}G^Uiai>xlZVF{mA7K}b}yM#grGQZ@uf zDOtd^#;1lyDI42@kDKs~pf7J1rJQLW#XG)9BkW`MN#;Y)v6$4HeNH~>4I0MD8}!cL zZK%Bi*kve%q?dsth-be}+xs>v90zDmy+Jd4`gmmS0Ql$|V1KcPw|SE$h8_T3h)0Yd zK4O%Uz)1s2-AnC58vqUf+RW7jndxyBr$#BeqFQFW)fJ^AIir-tz}+_H_R;tC&mJ&r z^ljM#V07Kr@-N<`UHzBfJ6}oYLrBY8H)~q8pU*sis_@sP&_6*{J6`Rfc3yRWMn_Hu zJ{Y)CTw;~=nLBgl#2Hg23!57GI;RI|Vput7gfYF2vJJ{ZD8+2vd!6SVr2X#w8L$XO z55N#oQT9k{VS91+D5X2z!JdQHx#!>&{|zYfGNY8O1EWAGKf(}?JED}!5l|jzdJKS4 zBcqf9xOO@CR|n~B{g%ApR7QZVb>AnuMJbcJN|Ch2CqYEwgT<|jGbxqNev2lyb>PdB zLYqBN3jTY)$zOeo=C&OTSS)oDKjBSoeH&@Vt~YtVw`s1=In;~5+u;Cz>TTLz>wdtg z^prBZ@HQRjvkq`3>K7c~8C7&g@*M}IOdmukUIAvz@ez041t&lLCYL&oRi-zkY&Fp<>KHdrQMJyUH6t;{1~>`^!kj7GThYAcW4`DIYKKD;QIlK#c0yc z!oAq(nQ#H_g%2~~*|-;TGhyN3!^BUQ_QFUe@-ZM=H>w02+p5uC+_&yz1z?e2nC+jy zy~w#*!(DWkKUGWH$C~)ZffLKxgqPqx23LxXpUrTl`{_ za(ri$asij+C0WM5EK7m=Z`Uf+iOb8lL_ZtReojS{G7#6QN~jx`D97%V<*Ld;^X9*o z(XU}?_pc$7vGy72=(^doFjP%iq2CVFqg3%tS<7VuH0Xl7Rvd;}a;XiRNG>vZB*TV~F6sgCAEjK^_o7iDrWUz>)z^?lIb*gkL`D)O)agB<;;&YzhR-tg@bV?EcITL zVy->@ic%*0FIU6$D5VOQNq3>uy@~rjmTAqM+}uEEY8k++tH(gR_+#3eulks3{J_W5 z(RN(DOgo=JA}_r8xO)E6$B394>v`C59ExsmV!Mfx_2Y@2Nyq8Ent$pi^8D;k5C`+9 zdfL&7y?tuxC;X>RVKXQrPoX`^p{I}^qFjNptJ&FiH~^N)|?hc7L3r zx!xvzH(z~C*vEs#u9nlID{UJCq<%T@ewl=S9mA>&G$4V z`?xV%1{$&Ncp0TosgDC^P4~|ciJ)TA3^bPR5ramj^^C#~lM_DnA|36#iYG!sM3LV) z6%pr#pcEolh6XEet^AfBy+{+=EBSvlc>ymz!uyC+CA9-@^COKVYkB&Qv>RE#r-`D0 zZ~BoA@NXA+y{SyFJ+KX)^QCF3gZuwPdy|oT$WJtm%;69HL^El;i@*F6?M15id4Oaq zkNBBpT6e}?Z)yjFxI`oQf}g1aT|e_PjiWsh_&Yz-t|X5~G*Fk;N5!^T+{Te{qUgl8 zUZNIlCD4=kj0SoOspq>Jz*0Fsi-O|G$g2%Bk!M}P@nbpM~FuR68Guz+$t{#S5S#aI7IJCW0T&##a~XgB^? z8?~#Jg-!hu9(5V0)O3FLWtylhNx$Ay!yjs(A$;p)8mhI+xZV`akNK)${JsFy-$zVA z9C}zX`A?T=tTr(7dQ%b44p;3w=?bK`k`KQE$xqjv@X|D-A8B0u&g?M%am^6P&hWmwE38o}vep3_JN z&;`S!0SLENA0YCEJ&nTZh6(;6y~WNX3A?wI-2X4Ay^<&Yg|7Va_}zbD4UOc*e?gEt z^R73A^3_dX_sCx`xvhX#@@y+qdGRl(@-p|ojz0ZHGz-B?^BZx!DTzll(2o9MjB>d9 zK%mO>S$hu_+yJ$f@3~HgLAZZihb?U6J)3kU?rMUpD*2NV+T8?c93Cxfe>mpPe}mr1 z#dX1I91S0{uAdq!iu={Bq-fnU!1cI;M>f#Nb!SvBlC|zTwF}w6I}mjkDd1Cx+KnE* zOSc^FJn(P^yUNqNny9yeD2RdxCPeX5+y#6&#czl2n9i9i$B|z1}oIEXMZyKAV~bPqf;mOW<>xnvcn4djZ$09nF|eITln9RI*)7@SCiuX+!wc==J(?#VLZ)hex!*yz_WY8_0JKe-wrF%>Ek|Z;+3$FFz;L@dp2?jT(uW_y=GL zM|d_0?ZBJOeri>K8mi_UxX#}WQ#*Jg#weo?2&bi6_L%_K%UJ$hfIh*Vfx6fy2CBoT zqmI8C2!*cH%h>fns)b&a_u5Ffxyd{&2pXv8<3*9hmj^)+jr?^{?C0MFp^Ma`JfkiC zci}i*(pJ4y>;9csQ26!p5Z=&MwP;B#aG)JHb{%jf{4Ze9p1qEwNv|BLw`XFRdg7~ zcehh}YvEU}H|^r1uEHT&gVjXnHZ54q*LMAWy-DF`Z6K=(R{IF^3RZ_{=l(PoH&&TN zTa}JG4`3*P)_s2b@V zkIAJbBSGRpVIYq7;r+tYM0K=J6aTr5+Ckfix&?fB82YQ^2g4w@1N?JQH1fZ~Fq=94 zO-+?@?)P`Z+|TgU9l>QKKhaU`ti=a5HErMvf1%+#DqQV|HPAO)%~Y#`ns}!M8lk(9 z1K8>u=9|L7|7HGTxO%6xCZ?(B9OX|%sZspF2sMIC=F210I5jXqHskdXSOTF5{8R+w za+pU%V$x@LP9&5T+L8p6F0}(fA(xeg|CBNdBY)Gabx#i{d!{&;j`!;98V=j~3mp2~p@+ zsM?ViMS+{7etbm~xT)kHivL}5gkOnLds|a;n~Yc)#z#8Ua59z8aKgo`9nyrnLl_-D z;sgT?{Dc$Y>M^VdeqV$(J+@>aLmkMYTo`;h&lbggK2a3Md9h1%X^nYJ<^nw6Qoa0? z;Z02<`&aVXWQqK&6aU$zMrn>)o0%uwrNz&Izv4rbkMXyljY9zV5akp6 z75_Tiqz6iA*VZ8_@ga%|xH8zGLjtw}K7#(e^jfN<0$#NO-}f*(xEqMnu$Bhn0WWLS zU@2fFvZY=;=kP*;ZFaa9uwY1jsInjM8NgG35EJ^!fX({zfCsNAY-w--h_M*ZB=`Za z`Nov!AQ&nTuvs4pSTJb99RXuT&9FGs*$Oxj7}0*P0h{#003RuA)nEh=<~vuS!2$y| z8$1G7%-Dn<13cY;@P4XN47lZUscF*JNG7};N&)bc5+&nXsZwD}0v>fiyoUghZbVis z5Dh>G9hV_57x2;Vq)xXQ@T~8pP8S>WK|e^9)f@E{fQ1Bgl~SrKX~mF5xzzML;Ehg) z!6Q+&Q;dJw)q>aw0`ZcU{QN(z?gvhbsr}>l+;>}w#Ud$IZ3(NwB3guvMF=4jA%w7q zLWnzrun1xKg%D2&AuN)x2qAoCkcDH2IgaZx-bMp zZ{u3>H3w8d6V@jWE&m@po&4gEU(T`dBh(vDaq-*WAr)4>kc+k>q5bxjkc;}_sW&7q zven>mxIdqrvmxZ~r$zJ0H|rho3U^5A@f7Fhu|5%*Z24#|)+Zz5tv~}Wk)V%AT0jG? zbABD`Ba)W?CZ6y7HeTqw5HEH905>^*giDyj+L-_O=o1pkLV~;m>tmD2mXE%~Q=RqJ z(@f`Yu+AEbUygN_n18_f1f}^WT*@J1qkS4|Btf$@+49jUtXXXS18a_$|H7J-=6|pz zp;^;kliJ({YYv&)Va=JOeLB#A1kF+lD8~Berg>f5o?~uaA9r@%5SKf5#+A;SV12yP z%JTzeQLU`~*9decL6a`o@=;H$NoL*>FUH4{phPfKNul)a9QyFxU|3|vmVxxptXNW2soxGS^JAZ1Eqf^E7`m- zgaxcgY2{zSTG?iY_>2Ea79z`^i!~{EWfC8brS{I}0%E1=!K$wIMTC@>k@ zC#aSGKDJLu%g3tbu;~Uv&+I1eR2EWlQ9=3rQeTG0IbYF^^RM&HX}}}`R=BnPNxa1Q z3whTx{=azaZmE}HeehXlm2OyiuaOwC<)UqH75T}=wWmPB2$#?o+o#f1pdTK3Qy5~Z zJOK}Mz7AJ9*W>mB(gvQ#CC+p4Aa=+u*M;RI^l=i&-F%!-Y8{qa2s`lxxb<)Rh1ey`L&E5Di{<-clxZ?wm@ z_)d5t598xWNW=i#-nj->V~VRmJ|)i~YsoJ#E0r)M4fqj{$5vtIHR+Jc-wV%k`Dfy# zc(c%e-lCWBoXNi;R ze-9GMm=wvDk2c4eB<6CgS#Iu)brzVn!8%LK+u>2peX+iGVEO&9zJJhi{ojQIeG$O| zcEeMhtMF`m2mzWzrw3d7nOKv~d^YZk`-J$Z!IpnF)}(B?{@+W2eJMc=yd7)>7Glj> z^9NY7-uw}s;{1u?nS_?V1Zz^8zr^~&M4=ZcYH&>!Z6#R1+E}yRT!J<0%^P6Na&srF zv%uU1Yu1}faZQkJNV;LR#wSl1XS6mv-MKldd22=~}TL)})M2LtKl?ZsPU7CEWNukz5?cSqFYdmd<$PqeBB$ zBulFn5_RxzF1NavObZ=o^G~vpYH3yed00#N)Zn>z1lEo#e;^mLssagRAz@5&a$Z}9 z4&lJ)JT_P7a`93hLvlElBKLIsCnxzNgbZcxLjK_c9BP6wn4s-eHz`1xD9f(JW4!jVY6v##M za7WIHJPA7M{#PJDUoxs9L07i})=q2%4#MRWST7V9hdaBA$-Q_K-YVoTz(ZaB?|6!H z8Sjy;9#oc8PkV*UNKlWGEgx-x)qr^`tPYs_VEZbR_TY$M%O8f-0rPOI4w{d{>QHbY zI)Q|mKn?jxINchXM>%VVuf>xNE(;;K=z8qS-{|7Cu1s-O`KNHvU@On-|9TQ?TM}~7 z^LXf?7Qh_~Ugi7}o--uPZ@@)Iq<$TjADQ}1JU!jx=xzM4S+D;WlHm8?1DtN`0iQWh zg|_k?%;$hqA$Ml+X*9Vc7k6-eE?HO_*3ZQq92mS?N1mh+AK!9u8g|<-7k9WP`30>+ zAGroKM1SBF!^%P*a?xM7&uw9$p~F2nU-gx?WXnZc;?>T*@GRRy;&;IMik!t);z88M z&9d%)^3jP3a1C6K^&L7Za5KJ!{Pjst{9LT>+FAZ9c%;k!3F~`!mj5e0k9@o9?aGp= z@8yN-PcGVwgn0zSOD7E+g!P5KWXnZ|;X_>mmtcLt&+;$FQ^}8)TFO6)_2oaye-h6o zpR+yQfiG}8Ldo?nAN`kv=$Nu3o{(j@JwF$%WbN^~EC37LkgkuHI&X;A;zKscmXA8) z(axLTNzPsIVq7>RG%zqESOo`Q9dq+RSck}b2-Yz)55XEC^O0DG#C#OiAuu0cQQkskR&?eC#SbJc;32TT;Ljz4%Lu?+oX)YeoQK7-lu|~8m#9z@h7mrXi z)+8*9aeJ&uF$K?Xhu}6m;j}WswdJBaaOLS`vE)1Pdu~Xl;nLgFA-)g$5q|CbJVNhfYFTm`%0l~iEyyW_#*7rb4Ww`bl@uzbj&T_8?0kyUXJaD0W@hh*eJ2(cfva6<}TPT zJf%3@8k@J_E_vnHLRmB-EIe(v9%~Qcmr^Vwdt)6_TWGGr+9UHP8*{nlv@N4nElh)0 z$~DCCq@#Qj3zvr2*7{w_a`7B8UnCa@=uQP%xn3Yahrk+W#u{?-RXs2Zi>>uPVl7nW zVVlt*Y-|7fSPPG>{Wo&MuXUy>bol(udHttZxOV8k?<8o_*$a!xEpqWBD+>7+Voj=e zC8WbQZ^^}o_{~H9BCI)K?&gMEOK}yp-+$1$u-8V+zgg#(QCwRt+9z|&_Hz~J4yGr! zT#DzS7Y}(SuEVOZmeTPdaPeyJ47^}mnJQIvySQOckL{Qq%O0wO z6(RputOjgO9NCK-3d&pliM^Ra&QG`oH6kD2iEal9ACWNKC47Q!r2(!v>~B75)0yi( z=Io2TH6CFdApb}_+WAtP{ya%8nuuqT&wt|bkMTeHeU5ksBcA`P4hiJPAmaByI4IozmNSf z{1B&GWAhOlG7V`Ni8_QsxPj3Ka8ZnX0B40pSam3Wu`6Fx;F$cGX<)Sr(5!EE)-mk5 zaqA9s$LYpd;;i_6an<;;5R!}b$73%}%>2(q2a?e9k~Cm2E}t4E8H0QwZeT=CqzcW6 z>A^{j`RG3(-uw{uBlZYRx5nlRx8|mo4)taIiHBsC3y5cFrh<=LzDDE|XT`6^<5ZN7zd98rEf~|ska3zOCuMO4V z1$d^5&v#91@on)O@^vv%eLDtQekE=ozo4}}-lLFU0X29&0p_#tXgbh`1a;sJy!g_x zB%72w@l2OLA1`}|pl3HSE-Op2X<$p--?pKET6q ze05}m{>6jboZ704H?MJVh#!J03k*rJv6PaapB#$Ub}G=$$(DZw)*&#fulkuGi+?iM z@}I^!B<5$aep$%km*IjEEZ{p5bd1dZ!}>WPE3jer#FpO~>yVlGRflM>b5}gdxjUZV z+_O9Lf3Zv0l7QvTy>P^kSp!?+_Rjn$LsaR!10Kr<3@m;ptV3kp8S9Xk`*$xS$IKG; zAV9~+yeHPWVBQ;RVKEQHT3E~nU@a`>gRs^SGhgLzwK5JVkdSUXli_o*TFJ(esEft1 zc>bkfUBEN2PCFeE<^O_pnrTwWyYtoLRnFI7O{D%Ie-YMMGBdca+xFZf5-=zvT!nR7 z%?MtJbqqUW-K1{612-VfW3f)N(INh2tkbM#KIu?_MP7$Eo3G0w)VWPf5)MiKS z%dX^OF?3XWFa+zEhk)p=J$U_31xJJqEXA55)}bC%+>{c(b;v)`ji{~-7s|C|{7YLd zx){$Sp8lZ%S1%GuUBE;5egcw>k5J-=ooC@W?xok0*uS)T8mj>-|16&6JO|f=T;_kf z=tUCJt+9C~d!!Ckkf;$^h1H>USchQ80X)ygx#07#I%K!$&)`-sM6gDHYfxNY)t=l% zQ(lLppbB4h9ng?{gZ0B&aRHh+lAV#0Ef*by^`l&>K-Ui5p^I(#dLMco4V06hYsCv# zKVfG1^RRy0i$k2e{$CjqEZ|qHU;DC)Q_sy3TmF`Kx~s4kUhKRzF21fT38xDcxWRb` zJoS3zbN;K3{9(vQKaiGexoBss-$gU`$NF6~^B!2gpJv_@7vGe6Z>--|v;2WrzpZ9I z01vsFi=Eon5S>Q?zslAUZ~>mIfRH~O>lfaVEf@U<>lfn84`Ka6ocR%~Uy?J=!a5|$ zmXDsq`dzko|8*3fCZR74TEMedKfDz0lg96g z=ehio@eg>dQ2s_d%jFm5kg$-1wL`#n_;Xia{c@IGS70~19JdMaqwwl`!u2~Dnn6R`b0qYBgp$MxYGunvLwCOpJ_@aPt7 zzu~CzF9uuu%UC0tYz3Zvlb}gt0rRmYnfWcONo0Npk9B?z&vIUb^#hR>|1mDUC-tYe z)U4~@=Opy81iTa<>HIaWcm5X7cm5tPc3y!sDXjxPV@*o)FIbaO8}pwJ9Fm|}nQT0{ z#O3%T5;TOH^-65{TVPE>^Hx}M#M}pKl9{)~nv~}4vF03`)_?A3NYJE9wtQ5HHOb7o zV$EXn?pSliJOFEwnX9oTnR#EV(>mFTqW!T>`*8hf8y!djSEI1Ciw5I#Yi$0Gn^GO) z_9SYh+-fJ5Qijx4&S+n~w;NVAE=Ciu7NVuZ>*7>Akkt;?hoyQCtV7;g`>zTwBSFX1 zDtr~|n3~(~$33C*0a$aw@~_8QsQR}{8r)!iE zVW19NOM?BZsr(MsBpea)pFb!UH8F&`oaXZUQLclz8Zv}Q2iiu5xe?Rae_m!pFL3#~ zR*X-q{pZaj67J3vxHnVaerLtc&&0pw^3}jQ&Wdlu1Me-1+hZ5_t^t$ue)szS4-!fr zOauPHEA9&)PK)?ZYHuDW;CPSmU_9K#ABO85Ny{IB=gdky3~xdCWXngx@q~g)IF5wL z&L`k$&L`mo&ZDq8WEGx{)nW6Q_;2U4@zK-M{IR&;UoM|d!YCJTAs**^F<#(20WWdB z9Q(8AN}O)I<+3ej(fwsnO`BvAmL0(JUkzE$knn#8a0|we_Ag2T&SsM7n2ieg4`Yo8 z>r*^wS742podsJD=8nkuOgzE4&mqiuo)1|3nTHg3^~xTs7b=`ZfcDS=e!-d(Rpjfm zIqT3|JcPv|{&B1kv-n@Jj`6UN-}f*+CyGY|pNBP~hXh|;a6_b7Iuq;Hb(1X@J%$%K zKY=?wo#sD<{nf7?ucU!w%SX@S=>F7mac}3sOC(Ho2@TjE!`D?o%huTZDhrJ|P?b+c zq@F!ehuagQ5$ZIAH=%G+<}+V9Wn8lsB)$>VWxI{8A9>Z@cJs64H$~B%C!OrCW2ob{*`7^@H5WmWz7e zrOumU{cyMCmt*}nx4AbSm6-N9CfkspU+%Vm?eGlezPKjjs>A(ox-~XW=*L4V;>$?X zB>VvnbRNP>EOpRc3toY>L+#`H9}3JSK@D03-FUG%%6Ssj9$5v?VvT^!`dwUyG-Ai# z`NSt1pMu8K90JAbkX?gk=@1t}!c!zHas}$~z!%Gs@)UUHD}I=>;tQGh%Ur(VufQ$stH8sV0*_`2JnpRck2CR~x_mY8xwGQiRJ7iK zb`@#+>{nxR@>4CzE~>z`nF8D6bmLpB&Wb-e6MwABSN+F3EB>kq_TLZbH7-B}u5(s_ zC$W!z+T|<$S!cz6nTh|(Bz&beH8k^U1R{Tzx_?=z88tCt=_+v8h zg%K`51x|EUfr*&{SGjz}U*oL!hcoeyx_rey?o524`Tb0R4_$x?EOu4{zh~nAboq*3 z?X39j+qWLko;ckKoQEz!1@_MrIMC&*fx*s-ACrkc&*dxr0%yff_3<4!@9%a2Dsb;@ z9ctQqP#F1gS?DK^^>*O3$t$VP!hRl}gVU|Cx&4v6+@pLwiCUe{b@}Q;U8em1xqNlu zt{vQ&sRA!$3N&O2yzZ>{|7GHTbopvvrL*F@ab@*8)T3|9%B1~jY~Ea#-ms~_p_u}Q zyL`nDbyoZpnfOUAU-8#EE55#vDe$}tP=UG5D)2)l{wJ5O_(o^Ncipk|9(Tv-#_HYE zC8)q5nF2#xz8W~vS@9Dy@mINg#b4vB_-9(j7oz7}fC{|etOEaQT_F0=;YJDR7tzPy))?X;%DNClnTWJ70!c!J!#s8X#|J~&){!eGccdcwaLfvt)#pgdCW@<@D z?warcDrUKgMO_dBb=n^qw1cDv|pm#_GR z&Wisn6W`?W75{f|+`bBw?c92ZHpA)G*t~_a;t$BgALR1Yz#-0xKQ9x1L6V>BzY2`c z6u2i-V7kj!{C}L)z=BNtyDnex?>j4gWgKtqGpm1f0V?pjvkG+FrS%AHgww6Dd1GhA zS7zdOb@{4)ciGxkf#Wg-PRJBE$yxDN;uY?4eKoFXC<}e!Q8Ct^YDzY~m5b-|YOI6= zy*zvt7e=}dvdkgD{y>rfz70+)$VcDf*Qp>ED%fDx#FpO)s{wNt>@T;aINi7$@7l8e z$!S+bK=rF-A%>6c;?>UkVEx6WWaHb`xaWUT55m5|gK@ewHuoFGcb%xOJ$s-VmYKtN zGN%UXiBiI!1gOGzh#@?)Xs`#ax<`?@`R0Q)_B5T{#X^R9GQ@wNkVvFg_gfOwBxygE>LTNSzn7vfsy z4{$XVu0;i!6aU~DE?=MdS@A|$=mWpVhs$Opf6`O&+u$MCCfzVxlDZI0Bq2%@qQ~&E z1!;v(;L3MWKZTb&*JE`s*?1O-2RqNjBb;Bt`U_pj#yfKjB&=*n$VabZbtu{R&I0yd zYJ3}O4=jHn)*hQbz}jQ;N3whC@Dto}2=&RFB_yOvkJV{Qb4=eE_%b|D}I5q;#X$ke|7na|J|(iRbZpt zTMyC3INi9bbyj>Ou6wsEgyf=K@e1eNu^;jQuDm)>9USk!Djbn1aAKyw$joowDK3;QDkD=H-!G`*m(2;-A{HNX!6RJ$6L`M!Q+R=MJs!y+I5A2N+1J64 zjr)nJ`%K5aJuoqTW6gWI}|bnc5(qaD|U8P zfg>{U!(6`NhdV3&f=v8)m#_GOI$)a$OwAOy+vTgkz0Qh%F%$o?%UArX&Wiu4b$lWE z#s#Rra%UB2yJzbmZI9E9XPM55FVDpHcKND*8|V1-{{fi-2e|+hIK){EoSBI~+vO{M zth3^8%*0P|`ON>u=G$C?3e3(Fc*fNG?E_3;c-^^L@Rhjs`T)yJ>Nu9j@A4S6G56hx5+SMoWW(6nR;LFcgf6ugI z$X^z0`QPEOGt;kstyj&`i`OJT*N*;pI^`{X58Q`*);}fjLV^VSG1g?`W1n~$0VO1; zf(umOqcr~#eB>kPQvD#-A7xFpT=Xd3mHc%{Q29@={(!6He}VguuU`g^13K)@!r}tf z!OL9-cEzkcKKtl{$i}fkHh;DUs#(I_3%CtCb)nZc!BG{ z2Y8;#UyR#Rfemq+eYl#r{PuW`E58G_KUJ$1D=~lSHXi@D3%ijJQK7wgIST7<-6mTu zIsHyPs>yp8!x-?(9gkB1okWAFr02&j-9nKUXqEwwBQ1?G){C@ zfd?`L9(4JNpXsdl1)2DFUB2SqcUFAi$4r5hE`M2XaX?`JE5fUumXI%DZ%SU&kF8i|%P+(LpY4Czziyx2m=cVgN zP=`JZw*1c(Prmj;`RgB$ILYVv&xRyyPJ{KcCh7-#X2PB^RW(r`9eJX+SC{0jmck6 z?W@8WA;AhfjCIV+k76A&^W(TCNVjmaak@1&uX75YNn{V>Il&{G!B~47A5z@*RDRU~ z7mlEmp7HEUf@Wng)k&R1`09{tQo?l}^HT2Q$Rv+d6Pqa8dy; zMse{nuK#vkKb<7BH1I6e-(a`%dZWRKt%8kl@wa6y@tfj_-=!|Y{gAuS_?z{TOQmI&0-5fBTW#lrUoBg3rJO?P0G_ z;87B^M`}P7{EW3n=Iu`6r$LA}pMy2z^`S#^vG&mNqm%hcIPu)<#`O)r8bR}AC-ccf z4G~Lz9MC|3-@|__x$oNhd(JB9U674k$h z9-^@>Kn>o67q|*0an4L zhcHQ8fq{4`wp*q#G7Tmh-{`~3oG-xYkmZlZ#gyki@jCNBu;mvXBtbp2gqgU(eed)! zJevG`sNmCJi~k&}!{((}J7oSEYX{8VVs}XRWo{DEt+9C*76c8^WLng$y$9mu{enG+@OTg_9Pbq_III&n!p_2qbuYv4-Ues`A&lAsFXW5%p4tKnOkG-xa14X#3U_+ea6yxjwS zgqOGuf0pqVxRiKXXWAdm9a9^A86mznFz6?SgrwIjtr?$=CsDxiN8=Gisn5j|oG%QX zsXeCtj@)SY{4R;L|JwKh1PN1J1>Ny%=PmFm=iaza+q44}xO(00$<>bfMrZQR&3GIh z-nNida4`u}dA6I2yVEv$5zk}D){o5x;PLx-o!||RWbU+2%WsUQICsmqXU1FNg#}lj z4++1y29Lx`@rI$n%WzSLw85)zwR0`*{8ak;v(Ml~#cBK;+@5?}7rw)V%C*yg6(q=m zXi&#&)X>C`jTb5zkH!;S`ExTKho`vwi*b|lWkWgt+pm*$;3@)2oNMuD=NmJ=HRIdy zL>GS-Zg9R2FLs_Wl=-*RB|JiaCQ-8Sb?=Oy$@n=u#Kpger#d&_na*$E+0O42NEpg7 zwqw$ShnJ)s_y>0;KNlZ>e6;1T#7PJ9Q7^3X+PpRHi&cYG(j$W{|0t~X%!Ok}7)65a z(^cTAU<tM_O7Hgq0e~)!m1@ro!1f5nE@H5tFm~3sM zU$D*s%l{4QEHO7>&1&=CSZ9IxU);wzcN7mITg?0aMI?-9NytZQ;L*-&;;GJS@y(pBw5NnUE{2Z(i(HO_S%<-=ZkkE?+-7-~O%x@0h%HUGB z2fFxFVn0cD%eYE==qB;rc=3Aaq~0G-T|c(g|6Fu12@5&q$8Mm5+Ug0mFgvhjHVoE(Dq`qL)*;atA*M}rjvc93s0Z}$q416`M7__bV%REvz*`0_~VQ}#q)?y+NZ%UNtm=@TH!KW=lp%fKV{sA zXS?{{@w859eShPn&e74aL;G}~ZITf0zeb=vF4-upVC{@caFxs7Fyqd6w9DT#<1$>k zk-PqHPQr9opckI!ye(es+!vR2PCK}B#=B=c09U&BeejfmOE`dpiY{q|gEKxna6SQ7Z=BY5O2##~-~-MgVT3C%7SD0M01w?Ht?-hJFVFZ&JkG^mi)T4cKAQQr z+9ljVfcG64--(M#(+=E=E1dt6@yv`L!^2(t?4y}~rJJS|K1;x4=efAVEi^CTa_0tI z<@`DxitTFJ7@W*%{^TGYOMY>DQs<+th2cqp1$4(c&&@sYBgm50N&XhGhI9m$9|F?mGLon zhMUAE;3dwd;8nrQe?DC366CWp9*c{+c4z;z<)RDlQ0GhVXy?l_o|N&mcw!Q-^`CEE zlQ6?oa0{N}dI?QT$YZ&<#?v^q>Qi2crsq(;%_m>?K1*(B$Uv@cv7(kuLP?*oLJFoSbLOgyyt`a z<1IbVSU_*AAv14-=ipKj6hAE3@`vNa zgLMea*I^c>WdC)WJeh=aYizz5`-SPUi+Li#Az2wt!|9hWZcZ+wLhkt10Y$jd73hG6IIn|eIB$S8RuP_E4wwVb~v{q0Y>Iertw=26qfc z;OZ^A)0{TmXv8(nr)7Lr#^>OPF8+KxsJwep9rcaJlM~ZE374h`v9HYdYCPRla6N8v zz8TMBgpw^E-HMB!O?^8qb)Jf=Vyk_Yg1brZljL5UZhRdN`#G{o7auw>N~JmG3kw`m z_PA#*aqkIyg@X}o2>G3_am{DXb#M99nvvv zz`nz;yL??s-o(DcZ@YYz{~l`uK1GkUVzJjKf_bEPCK*|Pa{7W(R{SliQIy@{1RLkOn}|f?LvZ_Z2U+Pu5qry6P@?M zGjC1f_rdC*mERAm1Li?^7PcKY|3v1W5-i|C0-nY87R&v?mOlf(PJW&Qjlc)Nmj4lc zgZx~`&y7rM`9)YGW?o|?^G}m5+1f^H65vm(wQ;&NHkV*Oi)*f8X{JIuuOGphbW13t zb>V+l$9y6^md8xuCX^8?B44NVQw0(<#PNGPB>axmp?D8?5V`x+{8%bZE=Fym4P1wG z)@+OYG3}diKiqMfbWZfgD`>BcI=~1PP9b5M3#h>hozGSQ=ksvS=h8`a5AL&V+Q0)D zKb-NScwib|h@K>2QJN6dt3X9s;R{$jPPTkB5C4qy@?3lHL$Kxlgw;WFBld@M6;3y< z|9_C+kLh17KttT=q}CnUB;&4lyzB608E=87yZqkX`uyKEB&^~XC%4UQqdo9a3Jj&2 zx^3=ta^j@dxoF#rx5q181O0H5bAQ}^yL3bc;GV(Ee?G%WLZu5hAh|8TZC@u7V0Y%Xvq<(s>tLvVFS8dt_YQ;`sWL zi}odJ;M(4JFRto|BUy*b(EhS z;-8D{uKzEF0P@-Rq#B;%8hjlW^-DXn01tA0FStDH@e!xD&ObWiWAV6xtKdWu23DpG zjKX7`&j>E3dzur=GWp+UyaG?9yp2##mO(k$a?w_};1l|gFwX^SmvLXb)aCDt`?A!k zLt2VQ;y%0ZTP z5*lnz1?td5T(xUj|J8Ve^Yv#i|9ryDnSfjIXjkC>aGmosywv&rj33JQ5nR$g?a&j2 zOu|#Rrwe!vFJX_8YePQz2Cu?)Pgim#cfGr%6>f;DoHx$6TgHVRBn);1w#4msPb=(` z@pc*a#hqRJ&bZEb_l);y?LxE<3A0>*18~vv=^mbkm%03laPb~#2Pb5FMaGkGm5aZw zl?%L%BVniuxCM8l1I1wy&BN7IX@jrg;m&Vn{BFkY<0;f-S7MaCyd)GQJk~qyd{FPvgqH!jn(Vi%z2x>nvmb=b}wqg4`AByiT@! z)E(!q07A1`(B z1Mq6+eKI~EhkmeX2C>#_L$d5w~%lHU9$5nVV9#4ZMadbYq689aL?!dKps>^>G zH#q+nuSnwy(YGNXp5^rDl=E5zL^Th`GnNT_3xB4A+F*yJlPdE3(s^O zi^sW()A{%o=L_)y=ZosV)j`Aw{|!2CAuSetqwzGW`o z|FhHN?>He1_!nzdTLrm`*duq0i?F}GuYuF8v3X7G?|6Ey#kb>_#FYf;2Isf)b5X|v zOKWXN*p%zPW@X$Vp8bA$A+PaSXlfZE6*%k?PEGRT(@f8XS-f<)9T>_N)#l=>qdKMd zs>ytFibNl+~7{*!bQx#IfK)MVj=-cov+UL`iyVH{t!&T>BcXsV1EeiaQWJS zc^7H^ACh+9RRuWD$Nin(&Uhgn`D&RX@H!uAT$L`}9V&~g% zldEuQ#&_egL(?6ap7DQhmCG;8Bw-q}+%7gB;W`)a8LoF;n(;RoFURv;{Ev9jVQGhc z!F8z%(I2f7qSYBUrKJz~pZAZc=*Tdm>*3oGL$K!#+Q=gpi=^3AiC%E`AcpUY| zcRcLyU3h8Ip5Fi9(`+OxJT7hE9lX+Y=uccZBF+CdWBrVd&u@nZx%jp4L}$J2UKgAH z(FknVl8|`gj5ozIT?JgXq9*4pGuB_+^!eN3_Q$6?px+(uBlF+513U9SLtMb_8Sj;Qr(n;TQj~LPo%!}BaJt|x`|nLXeHkG*-a8=aa!nVrhvxaI2*6RI&I8rI*ZJ|VSkg` zgbSK97VtL-nl$ErvF3z1cUdxN%tcsp#JmR9F*dJ>bulxqjdd|Imt02s{`$QE0qMqD zuh?I|uez0AG+^Z_=H;yJaQ3{7x7WF+izh8NEL~iAUElY>tC_SzsZ>k*J;6yEJR`b{ z`KJI&c#wdF^w4gzKfv>_ofZG!At$Es`O90oEgtLg*TkPwz6}lNkoCm_UrOscwm`xt zmvFTLPD&fN9uIZ-&*JEmG=FZ!uVnlh?(gE?!t<#wA39X{orIAur+2~KCq~g;&V%rt z&gbI+&iCRf=eO}5&P{lC=gqF*=VDVAqJv22pC&{X;H77$dw2<+k4e;zB-}Ktg>>LOyyJFLC||k8{pl#RCfGKDgR7cqCr!@-M>+ zoFBoXEMC|D#Uu=|1l(p44;G!b!KKc_a3AN1c-EM7#IDAgw8_TbHpQCM<{R*|un;l- z^U+NtXqH;QEqEzDi3H8s7lSSTWjyeuH2zhrNox7?@hIoFutw1G-@!VhY+C=h_>fTN z0v2H%qh#ZkOmMyPr+B{e=U78*@k_A|q4{g9LuURK>kx(OFTX@ef`;4zR$vXe`Dd&l zH~)e)Y0bZ3&1!QK)~q-GjdfO-|HV3M!u6lE>FVUPvVbD2)6TpG)@f;86Km3$*T$Md z<`S&a+PneQq%(KII%~r9m!*>gomLi5igg;9yJ5dn_rU4K$M>*bsvB?OXFOO5XSPX} z>T(yarTHMtq%B0%3SgRjlq7^YbJ1rRe}U(@S^hPyI4_;`%W=oo(sf{iYnTJCrf*K~ zj*DFWskr?GJpZqzNp;{;5+)N+hBfQkUP}*MfeO6JHMnE2-2qL=s8E<==1}^MA5Sc#eQF=WlR@bIJ9*$K$*!?l?Z} zKvl+jXFL!OcJT)mNSH^39YPPs;WuzD_&&UhNt$eYs2IQL@;|_{T!;R}4HMG%Ha8?5 zPKBD}`v+Tng@ZE*hvLPqf+O);uEERj>PyoGuEGmk2cE!Xm!OGg`Gx4$ z)(O$?xWZNNH*R>nNBmK1ot6V8bC%3ceGRU0@i*Y{&QpTthYozuDxcT?i(4hI@Zefk z!BV`^tpjV_$U7dFr+Zj}tDQFtwjn<(lRwm3uYZpwVW_KM1RgOlZQvw4&H1$8`mjec zGx?8aJR8q;<)6hRS0wc_|8vn?5{8BZ`ITTBvVSu9`I}nDx5Z;!`89FTmFW(wi_4rl z1`o`0{%cYU$^;ye@eo|$Dj0@4UX?a*tm2s?C5(vX$kjM>^seF9><1uSU z7#D`L*Uc6{0#$CC@%DH^TtSlG4^MOMk1Je*r{JY7zb1GP^DiEOM>7FWX8bf>T%wcS|iz`fA9*|K>ijkKG&uV zu7UeF7vl=&_3$9)PPo>2lh`b+*5hL`0Via95}xiVI1LY~O*?cJ9_2h%<()6UlbtWY zGYc-^auQZJPYRBI*^Hz5aVCFB#$V#{>(UM_!wYUm{XHH$IrUGtpoHI3>~EUxC7<4F{y7(aM7)4 zhfc#4&V{o=!U~2+3&|6ifM+s(4i9k^yoi@NH{jCS(gxoMUKHvtzP(j`AzH6>LevrW zcNKKO3!S^-mCl<5FAWWxoXI~u<1=x`I_n_o?-&xMv?TBj7+&anaqx^>GD7n*`LAX? zA2+%3Z{w;vtifFLJ|1V*_5b6L&?g+Tjqh*)@Mz{hvhm{v zSaZUBj5G5;7oFe|yI^(Pm# zBcUNq&>-caweX2<4|c*QW3El)=A+~BnXbZGe1`KgxHFgMWaEqLSeI+_OXj$Js(j57 z;)q=I1|I1Oyo0AZe}HE=FUE76KgY|RzmjL99rzA6_}Bl9B#i%08t^;5kUg>??S3aK zo2y_8e74);L-1sme*_-m@-M|>aXWTUBRCT;n&GbhkCRaJVA_GF@l@yM@pxC^xAez?-PKOW&c0M}C9?t*KuPCF}qcE;yn ze*ZTOxPXLN&X?eEv(o&_v2M|E^BpWvf1oV6& z4R{cbbbb`q)bq94T(T7Zis!ieCS37kTK*qg?VO*+By?V5T7d%3b&r~gk_rza;6a9v z`r}!82`+Lyz8u#(Pr^f=N*lZmcYZqcO?ag9ZFoBM+Y^w1T^ZklYtr~a^Z*H+pYPsM!NYi{^DMm3`6*m7Cyjp&4|IMJ_v9H-Z)(&+^F8k9 zo{DX7FNd_nJpbQ~gz^{D3irf%PM2)?Xm9)+-Y-;mR)-oBf(6XLdhBL?80)#7`BAK=VCKj1WB7Oyw8u+=E&ofbhgRmVupV-0WB&7{ z5)$;3E7|hVa;(Q><{$82=b!Lo=SDouc@>`J{0G)UF01b^tcP4|v`+{AAwf^Ik}c2A z6(qH^BuofziKs(W_!tVP z3Kcj#*eW~|7sy{P!FhQWW3D%QHfKr9@$ua4c0Ru^I2Fg*UjhPf?mB^!nq{q<+6Dk)@`); zBCOkJ^Ceif-R4WN?wZXLvF@79S7F^Ho3D9*^Ix~omT(;bdLdz+jP=69d^6Tfr}(8#gd;M(g|oGaiiRxblbNRl&^vTyzu(RrAt2pyPtavh-;WUd-e-Wc)fF>B=v_ zlV3{fdk@cc{s?Qt*plo2CnWeuv;?PHWAm5TALH9^&&7wNf*^ek=qnemL)MJdpdEts z9%|izPAyjZ>|qxY8e9*%;ziDz;U?$u;7WCX@)u?DCuDp%p2;4!ja$n{kKpAv`TZZN z_?U!>m(w9zlJS>#u*+YDXS+$a&cmFRucYNS!0q1%KT1jcyW=J`7&>q&9!Gw`5~h$a z*;R0RuuZZ*GWn}BZpO1*`J$QZp>qe^w;}D|I*AJ{KcR4DCSXj)=i#BQf{XCPSJMh7 z;2F+WU=4Y)<)cYhBWAu9FPP8ue-l!4-aZv4qyhC<$H)pik2QqmxmZJNehD9oZ5>z< zZ23Q94Y~OjTocc~IHg_m8wu&w*xZEutpD5PYnFF@r1c(ensFJPN`vjGR6DpoUg1XQ zU|jGChmz3#wRA|2#5K;t@l5CAGd?-vQ*ncfKNHu!p4LC+5zhaGE@2!2-WO*)0k3fJ zSKylYX@%F|Db6=!JSF4X9%20FxB^oNn8c9Tef?{}$zkDx%2-2cUVvxcocdin-Q~ZJ zYeKZHjvwN5YiwRzAi*Ew#yWl=h#~8lOIEf)taKWY21;qAdlPGx$15A&^bWp8OM~%g zoX{Qn*j`o5cX z-~n9mLF$Kbjq|LGpUSu%k9YAe;8o5qKe*b(=O1H|Ij?~iI2WhZ`j?B=OA}&u z#7kU(E_moiX$QOFQO=uXT%K`nJkG^e;EIn`U%dY6uaxnwR-B-@o{M(Lc#n+t#3Nn& zzPNO8+QC7%%J~pH+pP;j@IpCmpSAf&5|+AvqwrVG$6%cm$;Kaxkv4(3Dtg;QCWuq`~R zvGy>&no_>TbwKOF)!2{7^@)@H*O1>x!f-cax8lX@VYwQl*$?qDm;Wh_K1qlCOZlzz zYS(=h7c*QO%Abfk;*P=hk_-VIl| z_&xFL@6+=8%7q2#%61M3)1B|cZ_%OB(4p7ya$FMJh@0@H!J9n6i%nO4Z(NS8{8_l# z<=>7A#c%hBb_x|VC;(dnKjQ`p^b7eLKgs)cu7bVs5WIEBKMPNE`M2XK&adDJKcpit z|4HV*Pk1{Mun^C21wO>{eorg-6c2G7ZabUP(zybUbv_y|bG~vm^KX$$c$|Rg&P#BE z^BPaFN6y>h+0Mt{iO!SojHa~1*JXTDA(Lc!=}Qc%<_$c&zhpSZ9UR z*Mz4e*7~21{w86%3-}k$cFsMMoQ76G5nkl-*TBo1*Tk!w*OuQ&zkF619In6lXjc;2 zF{#u?9pjUOt-({VX0^EnYtov}!UJ(95>)<)5;Uu=z&mn~ zUO2pm)2*?25%$;f`f07d3H7my*X4H=ZsM$(&+~pguozgMI9z{o(Sac$X@ox*g**O} zp0|hN@vei%;!2l)A|By93eWpDEq?}H=zI=d{;zxg|9lcwx`6RGYECP-6i<&2kh++Q zuEg`4uf@KD*Jtu?&iGc`6mk7ewp{doaYE|5aCt8EeYky_)H86U^CKBQk?~V_tc!mR zPcO9Vk^E&7_9*u(OK(xyKs!9!c`dx6ZJJ+#r&Hc`V8e_z&UjPY;NpAWLh%}D1zVCZ z*tt)}+hyDrPjc})waFM*QM^wd_>pZ_7PhKa@e+Vydek|kJ89!4X zp~)4Plktmq=(=eG4H>_V$GiLmxKBwM{~jLf{87e*&oT*L;EArl*LcKwX@$%26z3l^ z{w3qz@In{=7hbY{OMQi?nS{<8v?N4D&$V`kjEnI=7r!1J=iCX;@0ixNNycTZ%cx&tTUx=j)@|8vplB-Api?Y{pOJl^?5Tw0n|(2(&P885(tUHp3)FT$gf zd|iKX(I+IVb_Kq`rJJS=ex331jDNs=UHnR1<@_5S<@^`!*j4q%*S}oUOhV5%fiyZ) z^n7b~$ha6+x%l;P)Gh6BCtT{hNycU7xP2PjjD$X}Ksg@jyfvi-)vNsPIPDA>C3vn(6T4 zE?<9wVRoj&&$xV*UxcR@=<#qhz>se|hXi*FyJg%1N8Qu-(}PK6WA8H_gNGBJZ2D=R z*1iZA>NzI%2EhX)OmhVu&iGM0%jG|bmpIqsk{)S;FW{-v-zDxIpDPMZI>b-6&td+l z1D5a;0e%iN;&kIK7W+Byhs)QHc6_0A2fAcjis#W@Zz|R0d!HAWf0eGs2N2+W5Uz9i zhh=;OUgYwR#$}t^4)GI=c)0UP8J||jB%FcAy8`FnInL+fk}c8(#%FwK#uIUsi@zF= za4uX=LV0;w;msM>W&D45kc*#&hdbYoXF5NG=Q}^v+J$I#>xAeTywVkzgDZQb9efFo zaDFZ0w=#YQk9F}M;7Kj!`oEZjMJ)-r=<|%f%J>_sNtA5NYV3bj;|ILL<^O~m+)CJp zi{1<6_4aPELR1~dQjQ85XfT)?_` zBj@#TXXg!Z7w67+W9LnBoJ^}kJY#67$RKm~cEhtIcT?GY<+>?K%x zVD5G=zm(?UPrw@T&LMs})(BaB-(l^LmG8y1Ks(HjJtYmCL4po}6?hD553N80*8=UK zdGLR@N5Ju?=jiZFSck~G2y}+veR)< z?;b>JW3A7446btdj{VZ|Gw^8YFOh^qysyJ^6%pE#c7BB!ZSYR`rj`EY(9^dVy?%7aT68V!{rNcxy!#F zS7OUwh)22nzwspJEnZ?NcRmD9sO0*eY`N%&I3e}X86S)1RHpeS;#usGy?=1M;&)B+ zZ^jdy>+oVX0wl9=IGBVPbjU_zNXEl59*!5g_~UW;C+RV+#S;gl_1%cuyZkw? zaQ=063EvS=yJuQp1uo;XNw$3SGp=AxY(s)Zpi4ty%P++`Ys}rSX1Tcs)+9G?-cU$p zxh0enpjmG2jWx^7+hEOd^LAL1)Z7w>c z5|sc-1cdGo`~Wd@r$6I+21g3L+p1QlJRv^HV`Zcn`lI zqM$~N5)>pXA}Gvb5EYd;sEh;V{ZIA1snazbyLnE1ApY)I?z!h~Rozw9S7|4c*yZl?gRVuNrUxS+oZz#%q(ix~fpjknnN4e%1Czk@Sf|G$fZDyC2k zE*M}{xC>mt_){Anu<;>q71RIH#(x9XN;$^ALwtpT)6C!$*gMb)pw7lW+xVa0sZ9Sj zaB{9?pYR^0A>(FX*@dWIG!e~FU>&%p6U_T?8!pW#ploM&w`_;)m{NMi5$3b&A~}iq zqdrdq^8ow}O!XrJAr#DE5%vV1#-M|L{B?>laA1(tqAB1U#?!$SjAwywhP_&fSA)yJ z>Jye~@Ir7$s-G(O5d|+Zh4$}bUNasD7K5z-Zm@BIjfa7~On(&kaGqs94xDo%yZ$ec z1*irGUc+tUDd2lx5I!7YI(SCD#k0T#hpZN^0T+Qgo8Fw_Bk+7C{|Ouz(s2EcHyDHq z8Y-x_vGW70gm7@Fba*Xz>JTe{bQ=f3TcEElZi~Q~$Y}U*;zo7qBHb#Ohyv;(rEm+F z`bhCqFm;jQ>ELaQZwFJCDfyjX8bgZj0oO793;2xA3TC6gg@~2GTyTJK1vrQCJn#U< z3%~;zF9Hu@yab%bcqv$?K2sGgM*;Pj;+0_PGsUaG)CG#yfS(7qL;(%rk0dMkE--b0 z;@x1rbnpFu&c7Ruy88W4;Pbxe^Y{n`gYI-fc%J8gX%?98jKW#-()IYEN@UOpA9UTY zA52|BRT3w^yVg09+DurWEpp+?v)R*x|7?V!|pFsuYJch&d zVCpjSBozD|n7T~K7rla4G(*3Wtnf25P#v@|{j8&)ijCrb+4whbEt4lyWB(tjQtA-R zz$Y1BV&j%Jz8rjx>FaG#5Ey1T>sW3#NiaJ!PLj$!ztQ;TZ7eJ(ND6H4*);6 zob=80$0>4AQ1yuA;0ACC9GL3@D!5Csa&Rx029e@&a1OXR3TP#KL9&vs2j@e6wUqCZ zEZ0B00}=&Yp0pf(4!#oxO{77SonclEF9OpbRh$TZ4ycYPrQ(@j8nlXMfx9!l8(hKoKJf4(mj3%MH*|D9qE3Ko26 zDLepv`KZMYf%)d~FxWck>KB6f-Z2;FgfxcKQaojY!<@Em^eKJfvITtIm)QRc;Dt7e zUr|5-q(FhV*Q>Y{8v%5cJR3|c93}O4fT@MMB|A6bjfZIA38|k0ra|qI@<&;~wD!LY z9UT;8;&6(O!4zQlz-vCi6rkeT8jL@RP!$}20!66!5SRi~ zd;~mI5?wbO1zSg5{r`gb7&yV?l=6gKSV@bOKkS~nF#dT#b12MU3N6T>)H1jnychwg zPsOsqqRf&Hu<>9U-v~}+`a^XTWKOgkj0DeOJQke8GB6%o%D9B|8JB@6!0_P|lff@B zz7@l9fCgO!kWVgB!X)$0#0% z0_&)&9|Y!IpkZO6jLbrcs0;F#K8@;Iz@@jS3h+&+jc0;qG5KBKniDBvJ}O1~onjXX z4kN-JPyz9kpP)rkEQcMy2N`z)lYaPcimSmp|88+tFjb)B-N6klMuU5R$(BD26Lo&r~_v*fEue$qPW{7|y8uL0{F&?ncRgi`hk3W$}$ zui!yo3;|Q#d2g7NybGB6RPi-n8s&=9z%>`&V4 zzh!c=|31PV??0(y3gn>uzQ~Mp1Y1X4eF~Uoq%)I~eSyt>7?V=~Be*^N{@G}zKn^Nw z4(2gAIat6Qzvll>N({Tob9_HQwJjQ<4jHd7!6r)&;>U~+QsBXdCZKQTGkyZ1+C zuoKui@Qf%}W{~Dzg6PT=$iZ-%gON;50gSO6nD*nCob2b@>>purvR~X_Z_fV&@fcGe z2it58wlg_7c&EVuwJSlq$K+&x+GhU`CMWx!l|6m?O%DFa6v#p9fyjB<)yBq2uPe13 zABIyy4s&Mbz#q;MjW#}4&{_Vqag)#0hyGpcb9K=9Oy3EY)=^jgF_=5t!{ijwIWV`c zXL4$j^I)XC237~zdk&muFTcSM18U@Zgl7IbEEa!_D%FpSA5fDtzP(M(SE6_NJ3 zn8y^z!2+9uMNCc(wnRD*Z!kI8zh$$3o5{)kRD`|WMEt-M$ia^`2R|`6IdC6}OkpRm zbzm(6^9*)naAi*5FgF*(_91FKomn$F|i zW(CAXb8D5FC}TA@KQ1@WLrumd~T(LVwwo%Nx6l|DW+v$K2r@Q zC;KOD_D?f8*;jv#rGz`!$rQ-J$2JFhn4BD(19SU&CMSF6;m8JPV0Dna_b`?c?!eC! z$U(^FAdAV#K`EHqPhxVipJKDWjmgP=g>G~36jLAvt8EURVRCX%W3&H+$;tjxoBci} zCwsRzf)ugUSF^FPCDWCv^HFf(O8mk*EK-q4T5gkIp$>A{3%r(j>}%s3@Mb0-1nzRT zwIAFBuDRFZVMlDEWCRqfqpp55m_2B}Xty zM&-FhHfn8&srCdEX1(b)@AxKu8hr3mi(dgB-{Tf%r2ZCg>Tb9BRTSyJ4ekXweKke= zA^0rhG*OB7g7d(b=O!P~QP95DQurQx6bi{w;TLczb11&RH811Kz%!sfL+W<`7lB(y z?g0+$b&Hdd2Y@%j-YZ$pN5Rpao`!Y?qpy|?*K3-dN z3ZGkiW~IFHJ1ER>n@|0b!{qNVChm8Ojnd(AaO!Ng7%l_eP>0Vsx_U$l$%}u)tt#-B zDD{K?2;X3h7sr?l{0@VMK8i9MOkXcP@e@*tN6flQgKvMq?ZRzRM5*MIvq*6_e7q=m zKbRiK!Uwme!`AiqYH6QaRN+f;3ivfJy{f86%1?pmekj%FOQAz=71{xRIvE_mUop-a zMDrYY(BfSy<;$=Z&;wCpWdKLO^n8=s6|S&Tf+HehH@I-7o0K9dWB`wY%RhIUx1v&g z!!^9RLZr~$Lb@4oU!3R7&v%P*S;2hpIZVriatyo=b``kI4@Aj9Vl%uneW+WklKP{- z3n8zO6)p$U$B`szXVy>;udF7znOs{D4^F0Buj4I z2A|3!fC4b4iO2?@{MZ_Vo09R})&QhX>Q}TyKy_~6mSbRLM~C@NoE1|3p2uOnkOgDi ztnca+1c3LW=&E2)D*C*A_~{%BY+KrhKr5&r_Fcibpm(=Af&xF%9w z1*Y2uYgG%oBLL>_K`=dbm@5O`2`*@lj~8pCLCb4lfO)C<=z1`HCOuWkuS;`?szq*b zQ1WarJxrq(mQ7%~-)WSTPws(1$hveLc-uGD(tLRUU7*jm`fM%E>gZ9>965^b!Ubb@ z%_AnuKHUJ$WMiO51_ssJZn0TbIJY0<2?$u~Zv~(F#BKhbId$Q+{V~YF!=?UHV7=DY z$($BRSmBSLVB1DSC{y$RBB7UKBuj&8Fuf*7O}j1w(1I_lm2N$lXUI1Y8T!&Kw#jwk zA#f4&)k<1881v8dfi-QO8jOhFwIWQ)!?eO@-fG@DZ^XRE!?b5*KuI^@<_t``bCO>z zh@6Jo3y~qD9AnTN^^-=x{!KRsD=acHZ3NbTfyF@;%z?r(OgjW@PP=!(UGR(UVYw!% z!7G@&a3sF@!AjU23Y6l_V0tc+ToRuL)7?XBtL7t8_Ei0HdD%<0-yGHL@&wu9u&}n zl`5rL5vB>|vD&TrfNR~JhEcs5yzn!(aLX1Y6k~7jq%@p>l!9MAWbK}pmLTO=`&Aci z1+(2&7mrUu%A4T_QRE=;O>u<3t3m}y!YSs0`R;h%Js9Oh*xh6cHiA!H>uH!ZZ`_ZS zkaf}b;6!wx>QeV?49W)9HSrk6z}YSyF-JPQcy8oEGX=~SqQt*qTK4eJm6_ScC%|V| zh4(&yr90Ilj!Su{0$<4968?gg`g|Uk?iQ*dIqm<8A4Z=Qd&CTB@GY3W8d96b3kxCx zy6BO}fNllv$n=P*(tZs%`+ARPFL@t$&H#_7kPYm=5CPznj~Z<5|2hiJ4YcO@d*Bwm za84*4t5qJyusFW`S z)6a>Im3;AX*blSLs(XT~!Skj3QUmM82s8*|&kW$ND4?H=SM%~yF#V!C-B?L2O2B-i zTTg0ai+h9V4lcEB+y|z+{t9FTTfubOVUA4seRw+l*J9mZ zJo|ZMC9IJ+@*%B`~(CAF5t={Q8+fzc7Q) z1y+y|OJ9%7q2CwFAW}a)c!By^Hhn!tr~1ti9GX@g3ei>D|H|Rxryn%o}!{^IP z2N;7x+C1Z`46VLj>>iVTqV@UsF*k)WjK1St$;P9FTGPt=GqnMZIEGO$99lG&aSo$E z;~oaZ=|Ya3XhEP|KA&&A(PF5pjZt{JE6Mop>$EAoV&=-VN7}B4K7oz=URp)Ve~--=@~xI-bm*;>$8Nu`@d%AIGckNm_0}GWR!9A- zu3pBDK3Z}#;Y%f2j*)hKbm8pvT4&?_>$Ml6S$bw@ZHybUwFjdKcTCnwTSdvGk-bDq zG4Aghy}qmN)%?bxzFM2u*+{2sM^AR;wf(eAN3^KSkoCK@R>m{^wFhHY;%|I<8b1t0 z%C`^I5{-%+ZEYO$ve9_sT;2Vl-|=AX{;{XfA6^^$jSRvB>{8*B^c<+Q(nEnP-$YzZ zPt5T8OUry^1LADsAKn7P4b=a@Ci;6>rcu%60;yAyOebcy~r}L22m<{s%PCVhX#&nVX zA2`WUD?`-g+Hq@z`M+qZCtX<no%UkDB}Ru;di|!gXyORE#QU2nhyJEL HIs5+rnk^+& diff --git a/integration_tests/tests/bridge.rs b/integration_tests/tests/bridge.rs index e6c0cd0c..81f62f2b 100644 --- a/integration_tests/tests/bridge.rs +++ b/integration_tests/tests/bridge.rs @@ -43,6 +43,7 @@ async fn public_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> { vec![bridge_account_id, recipient_vault_id], vec![], bridge_core::Instruction::Deposit { + l1_deposit_op_id: [0_u8; 32], vault_program_id, recipient_id, amount: 1, @@ -129,6 +130,7 @@ async fn private_bridge_deposit_invocation_is_dropped() -> anyhow::Result<()> { // Serialize the bridge deposit instruction let instruction = Program::serialize_instruction(bridge_core::Instruction::Deposit { + l1_deposit_op_id: [0_u8; 32], vault_program_id, recipient_id, amount: 1, diff --git a/lez/sequencer/core/Cargo.toml b/lez/sequencer/core/Cargo.toml index ea08c6f1..f7296f42 100644 --- a/lez/sequencer/core/Cargo.toml +++ b/lez/sequencer/core/Cargo.toml @@ -34,6 +34,7 @@ borsh.workspace = true bytesize.workspace = true hex.workspace = true url.workspace = true +risc0-zkvm.workspace = true [features] default = [] diff --git a/lez/sequencer/core/src/block_store.rs b/lez/sequencer/core/src/block_store.rs index 2e934d2c..97a23848 100644 --- a/lez/sequencer/core/src/block_store.rs +++ b/lez/sequencer/core/src/block_store.rs @@ -10,7 +10,7 @@ use lee::V03State; use log::info; use logos_blockchain_zone_sdk::sequencer::SequencerCheckpoint; pub use storage::DbResult; -use storage::sequencer::RocksDBIO; +use storage::sequencer::{RocksDBIO, sequencer_cells::PendingDepositEventRecord}; pub struct SequencerStore { dbio: Arc, @@ -165,6 +165,27 @@ impl SequencerStore { self.dbio.put_zone_sdk_checkpoint_bytes(&bytes)?; Ok(()) } + + pub fn get_unfulfilled_deposit_events(&self) -> DbResult> { + self.dbio.get_pending_deposit_events() + } + + pub fn mark_unfulfilled_deposit_events_submitted( + &self, + deposit_op_ids: &[HashType], + submitted_block_id: u64, + ) -> DbResult { + self.dbio + .mark_pending_deposit_events_submitted(deposit_op_ids, submitted_block_id) + } + + pub fn remove_fulfilled_unfulfilled_deposit_events_up_to_block( + &self, + finalized_block_id: u64, + ) -> DbResult { + self.dbio + .remove_fulfilled_pending_deposit_events_up_to_block(finalized_block_id) + } } pub(crate) fn block_to_transactions_map(block: &Block) -> HashMap { diff --git a/lez/sequencer/core/src/lib.rs b/lez/sequencer/core/src/lib.rs index f4084c6d..0f836c00 100644 --- a/lez/sequencer/core/src/lib.rs +++ b/lez/sequencer/core/src/lib.rs @@ -1,4 +1,4 @@ -use std::{path::Path, time::Instant}; +use std::{path::Path, sync::Arc, time::Instant}; use anyhow::{Context as _, Result, anyhow}; use borsh::BorshDeserialize; @@ -16,6 +16,7 @@ use mempool::{MemPool, MemPoolHandle}; #[cfg(feature = "mock")] pub use mock::SequencerCoreWithMockClients; pub use storage::error::DbError; +use storage::sequencer::sequencer_cells::PendingDepositEventRecord; use crate::{ block_publisher::{BlockPublisherTrait, ZoneSdkPublisher}, @@ -147,26 +148,72 @@ impl SequencerCore { let dbio_for_finalized = store.dbio(); let on_finalized_block: block_publisher::FinalizedBlockSink = Box::new(move |block_id| { + // NOTE: Theoretically Zone SDK may report finalization happening multiple times for the + // same block. In practice this is very unlikely to happen. For that to + // happen Sequencer should crash between receiving Finalized and Checkpoint events while + // these events happen very fast (because Checkpoints are generated by Zone SDK + // locally). + if let Err(err) = dbio_for_finalized.clean_pending_blocks_up_to(block_id) { error!("Failed to mark pending blocks finalized up to {block_id}: {err:#}"); } + + match dbio_for_finalized.remove_fulfilled_pending_deposit_events_up_to_block(block_id) { + Ok(0) => {} + Ok(removed) => { + info!( + "Removed {removed} fulfilled pending deposit events up to finalized block {block_id}" + ); + } + Err(err) => { + error!( + "Failed to remove fulfilled pending deposit events up to block {block_id}: {err:#}" + ); + } + } }); let (mempool, mempool_handle) = MemPool::new(config.mempool_max_size); + replay_unfulfilled_deposit_events(&store, mempool_handle.clone()); + let mempool_handle_for_deposit = mempool_handle.clone(); + let dbio_for_deposit = store.dbio(); let on_deposit_event: block_publisher::OnDepositEventSink = Box::new(move |deposit| { + // NOTE: Theoretically Zone SDK may report multiple identical deposits. In practice this + // is very unlikely to happen. For that to happen Sequencer should crash + // between receiving Deposit and Checkpoint events while these events happen + // very fast (because Checkpoints are generated by Zone SDK locally). + + let dbio_for_deposit = Arc::clone(&dbio_for_deposit); let mempool_handle_for_deposit = mempool_handle_for_deposit.clone(); Box::pin(async move { - info!( - "Observed Bedrock Deposit event with id: {:?}", - hex::encode(deposit.op_id) - ); - let tx = match build_bridge_deposit_tx(&deposit) { + let id_hex = hex::encode(deposit.op_id); + info!("Observed Bedrock Deposit event with id: {id_hex}"); + + let event_record = pending_deposit_event_record(&deposit); + + match dbio_for_deposit.add_pending_deposit_event(event_record.clone()) { + Ok(true) => {} + Ok(false) => { + info!( + "Deposit event {id_hex} already persisted as unfulfilled, skipping duplicate enqueue", + ); + return; + } + Err(err) => { + error!( + "Failed to persist unfulfilled deposit event {id_hex} before enqueue: {err:#}. Deposit will be lost.", + ); + return; + } + } + + let tx = match build_bridge_deposit_tx_from_event(&event_record) { Ok(tx) => tx, Err(err) => { - warn!( - "Skipping finalized Bedrock deposit event due to tx build failure: {err:#}" + error!( + "Failed to build transaction from Bedrock deposit event {id_hex}: {err:#}. Deposit will be lost.", ); return; } @@ -177,7 +224,7 @@ impl SequencerCore { .await { error!( - "Failed to queue sequencer transaction built from finalized Bedrock event: {err:#}" + "Failed to queue sequencer transaction built from finalized Bedrock event: {err:#}. Deposit will be lost." ); } }) @@ -199,8 +246,11 @@ impl SequencerCore { // genesis block so the indexer can find the channel start. After the // first publish, zone-sdk's checkpoint persistence covers further // restarts. - if is_fresh_start && let Err(err) = block_publisher.publish_block(&genesis_block).await { - error!("Failed to publish genesis block: {err:#}"); + if is_fresh_start { + block_publisher + .publish_block(&genesis_block) + .await + .expect("Failed to publish genesis block"); } let sequencer_core = Self { @@ -217,30 +267,47 @@ impl SequencerCore { /// Produces a new block from mempool transactions and publishes it via zone-sdk. pub async fn produce_new_block(&mut self) -> Result { - let block = self + let block_with_meta = self .build_block_from_mempool() .context("Failed to build block from mempool transactions")?; + let BlockWithMeta { + block, + deposit_event_ids, + } = block_with_meta; // TODO: Remove msg_id from store.update — it is no longer needed now that // zone-sdk manages L1 settlement state via its own checkpoint. let placeholder_msg_id = [0_u8; 32]; - if let Err(err) = self.block_publisher.publish_block(&block).await { - error!("Failed to publish block to Bedrock with error: {err:#}"); - } + self.block_publisher + .publish_block(&block) + .await + .context("Failed to publish block to Bedrock")?; + self.store.update(&block, placeholder_msg_id, &self.state)?; + let updated_deposits = self + .store + .mark_unfulfilled_deposit_events_submitted(&deposit_event_ids, block.header.block_id)?; + if updated_deposits > 0 { + info!( + "Marked {updated_deposits} pending deposit events as submitted in block {}", + block.header.block_id + ); + } + Ok(self.chain_height) } /// Builds a new block from transactions in the mempool. /// Does NOT publish or store the block — the caller is responsible for that. - pub fn build_block_from_mempool(&mut self) -> Result { + fn build_block_from_mempool(&mut self) -> Result { let now = Instant::now(); let new_block_height = self.next_block_id(); - let mut valid_transactions = vec![]; + let mut valid_transactions = Vec::new(); + let mut deposit_event_ids = Vec::new(); let max_block_size = usize::try_from(self.sequencer_config.max_block_size.as_u64()) .expect("`max_block_size` should fit into usize"); @@ -311,6 +378,20 @@ impl SequencerCore { let LeeTransaction::Public(public_tx) = &tx else { panic!("Sequencer may only generate Public transactions, found {tx:#?}"); }; + + if public_tx.message.program_id == Program::bridge().id() { + let instruction: bridge_core::Instruction = + risc0_zkvm::serde::from_slice(&public_tx.message.instruction_data) + .context("Failed to deserialize bridge instruction")?; + match instruction { + bridge_core::Instruction::Deposit { + l1_deposit_op_id, .. + } => { + deposit_event_ids.push(HashType(l1_deposit_op_id)); + } + } + } + self.state .transition_from_public_transaction( public_tx, @@ -355,7 +436,11 @@ impl SequencerCore { hashable_data.transactions.len(), now.elapsed().as_secs() ); - Ok(block) + + Ok(BlockWithMeta { + block, + deposit_event_ids, + }) } pub const fn state(&self) -> &lee::V03State { @@ -411,6 +496,60 @@ impl SequencerCore { } } +struct BlockWithMeta { + block: Block, + deposit_event_ids: Vec, +} + +/// Checks the database for any pending deposit events that have not yet been marked as submitted in +/// a block, and re-queues them in the mempool in a separate async task for inclusion in the next +/// block. +fn replay_unfulfilled_deposit_events( + store: &SequencerStore, + mempool_handle: MemPoolHandle<(TransactionOrigin, LeeTransaction)>, +) { + let replay_records: Vec = store + .get_unfulfilled_deposit_events() + .expect("Failed to load unfulfilled deposit events") + .into_iter() + .filter(|record| record.submitted_in_block_id.is_none()) + .collect(); + + if replay_records.is_empty() { + return; + } + + info!( + "Found {} unfulfilled deposit events in DB, re-queueing", + replay_records.len() + ); + tokio::spawn(async move { + for record in replay_records { + let tx = match build_bridge_deposit_tx_from_event(&record) { + Ok(tx) => tx, + Err(err) => { + warn!( + "Skipping replay of pending deposit event {} due to tx build failure: {err:#}", + hex::encode(record.deposit_op_id) + ); + continue; + } + }; + + if let Err(err) = mempool_handle + .push((TransactionOrigin::Sequencer, tx)) + .await + { + error!( + "Failed to re-queue unfulfilled deposit event {} from DB: {err:#}", + hex::encode(record.deposit_op_id) + ); + break; + } + } + }); +} + /// Builds the initial genesis state from `testnet_initial_state` plus configured genesis /// transactions. Returns the final state and the list of [`LeeTransaction`]s that should be /// committed to the genesis block so external observers can replay them. @@ -485,10 +624,20 @@ fn build_supply_bridge_account_genesis_transaction(balance: u128) -> PublicTrans PublicTransaction::new(message, witness_set) } -fn build_bridge_deposit_tx( +fn pending_deposit_event_record( deposit: &logos_blockchain_zone_sdk::state::DepositInfo, -) -> Result { - let metadata = DepositMetadata::decode(&deposit.metadata) +) -> PendingDepositEventRecord { + PendingDepositEventRecord { + deposit_op_id: HashType(deposit.op_id), + source_tx_hash: HashType(deposit.tx_hash.0), + amount: deposit.amount, + metadata: deposit.metadata.clone().into(), + submitted_in_block_id: None, + } +} + +fn build_bridge_deposit_tx_from_event(event: &PendingDepositEventRecord) -> Result { + let metadata = DepositMetadata::decode(&event.metadata) .context("Failed to decode finalized Bedrock deposit metadata")?; let bridge_program_id = Program::bridge().id(); @@ -501,9 +650,10 @@ fn build_bridge_deposit_tx( vec![lee::system_bridge_account_id(), recipient_vault_id], vec![], bridge_core::Instruction::Deposit { + l1_deposit_op_id: event.deposit_op_id.0, vault_program_id, recipient_id: metadata.recipient_id, - amount: u128::from(deposit.amount), + amount: u128::from(event.amount), }, ) .context("Failed to build bridge deposit message")?; @@ -552,6 +702,7 @@ mod tests { }; use logos_blockchain_core::mantle::ops::channel::ChannelId; use mempool::MemPoolHandle; + use storage::sequencer::sequencer_cells::PendingDepositEventRecord; use tempfile::tempdir; use testnet_initial_state::{initial_accounts, initial_pub_accounts_private_keys}; @@ -563,6 +714,11 @@ mod tests { mock::SequencerCoreWithMockClients, }; + #[derive(borsh::BorshSerialize)] + struct DepositMetadataForEncoding { + recipient_id: lee::AccountId, + } + fn setup_sequencer_config() -> SequencerConfig { let tempdir = tempfile::tempdir().unwrap(); let home = tempdir.path().to_path_buf(); @@ -620,6 +776,35 @@ mod tests { (sequencer, mempool_handle) } + fn tx_is_bridge_deposit( + tx: &LeeTransaction, + deposit_op_id: [u8; 32], + expected_amount: u64, + ) -> bool { + let LeeTransaction::Public(public_tx) = tx else { + return false; + }; + + if public_tx.message.program_id != lee::program::Program::bridge().id() { + return false; + } + + let instruction: bridge_core::Instruction = + match risc0_zkvm::serde::from_slice(&public_tx.message.instruction_data) { + Ok(instruction) => instruction, + Err(_err) => return false, + }; + + matches!( + instruction, + bridge_core::Instruction::Deposit { + l1_deposit_op_id, + amount, + .. + } if l1_deposit_op_id == deposit_op_id && amount == u128::from(expected_amount) + ) + } + #[tokio::test] async fn start_from_config() { let config = setup_sequencer_config(); @@ -690,6 +875,69 @@ mod tests { let _ = SequencerCoreWithMockClients::start_from_config(config).await; } + #[tokio::test] + async fn start_from_config_replays_unfulfilled_deposit_events_from_db() { + let config = setup_sequencer_config(); + let deposit_op_id = [13_u8; 32]; + let expected_amount = 1_u64; + let recipient_id = initial_accounts()[0].account_id; + + { + let (_sequencer, _mempool_handle) = + SequencerCoreWithMockClients::start_from_config(config.clone()).await; + } + + let pending_event = PendingDepositEventRecord { + deposit_op_id: HashType(deposit_op_id), + source_tx_hash: HashType([7_u8; 32]), + amount: expected_amount, + metadata: borsh::to_vec(&DepositMetadataForEncoding { recipient_id }).unwrap(), + submitted_in_block_id: None, + }; + + { + let signing_key = lee::PrivateKey::try_new(config.signing_key).unwrap(); + let store = SequencerStore::open_db(&config.home.join("rocksdb"), signing_key).unwrap(); + + let inserted = store + .dbio() + .add_pending_deposit_event(pending_event) + .unwrap(); + assert!(inserted); + } + + let (mut sequencer, _mempool_handle) = + SequencerCoreWithMockClients::start_from_config(config).await; + + let (origin, tx) = tokio::time::timeout(Duration::from_secs(5), async { + loop { + if let Some((origin, tx)) = sequencer.mempool.pop() { + return (origin, tx); + } + + tokio::time::sleep(Duration::from_millis(100)).await; + } + }) + .await + .expect("Timed out waiting for pending deposit event to be replayed into mempool"); + + match origin { + TransactionOrigin::Sequencer => {} + TransactionOrigin::User => { + panic!("Unexpected user transaction in empty mempool replay test") + } + } + + assert!(tx_is_bridge_deposit(&tx, deposit_op_id, expected_amount)); + + let pending_events = sequencer.store.get_unfulfilled_deposit_events().unwrap(); + let replayed_event = pending_events + .into_iter() + .find(|event| event.deposit_op_id == HashType(deposit_op_id)) + .expect("Pending deposit event should remain in DB until included in a block"); + assert!(replayed_event.submitted_in_block_id.is_none()); + } + #[test] fn transaction_pre_check_pass() { let tx = common::test_utils::produce_dummy_empty_transaction(); diff --git a/lez/storage/src/sequencer/mod.rs b/lez/storage/src/sequencer/mod.rs index 01c1343d..851dc4ff 100644 --- a/lez/storage/src/sequencer/mod.rs +++ b/lez/storage/src/sequencer/mod.rs @@ -1,6 +1,9 @@ use std::{path::Path, sync::Arc}; -use common::block::{BedrockStatus, Block, BlockMeta, MantleMsgId}; +use common::{ + HashType, + block::{BedrockStatus, Block, BlockMeta, MantleMsgId}, +}; use lee::V03State; use rocksdb::{ BoundColumnFamily, ColumnFamilyDescriptor, DBWithThreadMode, MultiThreaded, Options, WriteBatch, @@ -12,7 +15,8 @@ use crate::{ error::DbError, sequencer::sequencer_cells::{ LEEStateCellOwned, LEEStateCellRef, LastFinalizedBlockIdCell, LatestBlockMetaCellOwned, - LatestBlockMetaCellRef, ZoneSdkCheckpointCellOwned, ZoneSdkCheckpointCellRef, + LatestBlockMetaCellRef, PendingDepositEventRecord, PendingDepositEventsCellOwned, + PendingDepositEventsCellRef, ZoneSdkCheckpointCellOwned, ZoneSdkCheckpointCellRef, }, }; @@ -24,6 +28,9 @@ pub const DB_META_LAST_FINALIZED_BLOCK_ID: &str = "last_finalized_block_id"; pub const DB_META_LATEST_BLOCK_META_KEY: &str = "latest_block_meta"; /// Key base for storing the zone-sdk sequencer checkpoint (opaque bytes). pub const DB_META_ZONE_SDK_CHECKPOINT_KEY: &str = "zone_sdk_checkpoint"; +/// Key base for storing queued deposit events that were not yet +/// fulfilled on L2. +pub const DB_META_PENDING_DEPOSIT_EVENTS_KEY: &str = "pending_deposit_events"; /// Key base for storing the LEE state. pub const DB_LEE_STATE_KEY: &str = "lee_state"; @@ -239,6 +246,72 @@ impl RocksDBIO { self.put(&ZoneSdkCheckpointCellRef(bytes), ()) } + pub fn get_pending_deposit_events(&self) -> DbResult> { + Ok(self + .get_opt::(())? + .map_or_else(Vec::new, |cell| cell.0)) + } + + fn put_pending_deposit_events(&self, records: &[PendingDepositEventRecord]) -> DbResult<()> { + self.put(&PendingDepositEventsCellRef(records), ()) + } + + pub fn add_pending_deposit_event(&self, event: PendingDepositEventRecord) -> DbResult { + let mut records = self.get_pending_deposit_events()?; + if records + .iter() + .any(|record| record.deposit_op_id == event.deposit_op_id) + { + return Ok(false); + } + records.push(event); + self.put_pending_deposit_events(&records)?; + Ok(true) + } + + pub fn mark_pending_deposit_events_submitted( + &self, + deposit_op_ids: &[HashType], + submitted_block_id: u64, + ) -> DbResult { + let mut records = self.get_pending_deposit_events()?; + let mut updated: usize = 0; + + for record in records + .iter_mut() + .filter(|record| deposit_op_ids.contains(&record.deposit_op_id)) + { + record.submitted_in_block_id = Some(submitted_block_id); + updated = updated.saturating_add(1); + } + + if updated > 0 { + self.put_pending_deposit_events(&records)?; + } + + Ok(updated) + } + + pub fn remove_fulfilled_pending_deposit_events_up_to_block( + &self, + finalized_block_id: u64, + ) -> DbResult { + let mut records = self.get_pending_deposit_events()?; + let before = records.len(); + records.retain(|record| { + record + .submitted_in_block_id + .is_none_or(|submitted_id| submitted_id > finalized_block_id) + }); + + let removed = before.saturating_sub(records.len()); + if removed > 0 { + self.put_pending_deposit_events(&records)?; + } + + Ok(removed) + } + pub fn put_block( &self, block: &Block, diff --git a/lez/storage/src/sequencer/sequencer_cells.rs b/lez/storage/src/sequencer/sequencer_cells.rs index 9a6a607b..39b6a406 100644 --- a/lez/storage/src/sequencer/sequencer_cells.rs +++ b/lez/storage/src/sequencer/sequencer_cells.rs @@ -1,5 +1,5 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use common::block::BlockMeta; +use common::{HashType, block::BlockMeta}; use lee::V03State; use crate::{ @@ -8,7 +8,8 @@ use crate::{ error::DbError, sequencer::{ CF_LEE_STATE_NAME, DB_LEE_STATE_KEY, DB_META_LAST_FINALIZED_BLOCK_ID, - DB_META_LATEST_BLOCK_META_KEY, DB_META_ZONE_SDK_CHECKPOINT_KEY, + DB_META_LATEST_BLOCK_META_KEY, DB_META_PENDING_DEPOSIT_EVENTS_KEY, + DB_META_ZONE_SDK_CHECKPOINT_KEY, }, }; @@ -131,12 +132,56 @@ impl SimpleWritableCell for ZoneSdkCheckpointCellRef<'_> { } } +#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] +pub struct PendingDepositEventRecord { + pub deposit_op_id: HashType, + pub source_tx_hash: HashType, + pub amount: u64, + pub metadata: Vec, + /// Set when block containing the deposit event is submitted, but not necessarily finalized. + pub submitted_in_block_id: Option, +} + +#[derive(BorshDeserialize)] +pub struct PendingDepositEventsCellOwned(pub Vec); + +impl SimpleStorableCell for PendingDepositEventsCellOwned { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_PENDING_DEPOSIT_EVENTS_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleReadableCell for PendingDepositEventsCellOwned {} + +#[derive(BorshSerialize)] +pub struct PendingDepositEventsCellRef<'records>(pub &'records [PendingDepositEventRecord]); + +impl SimpleStorableCell for PendingDepositEventsCellRef<'_> { + type KeyParams = (); + + const CELL_NAME: &'static str = DB_META_PENDING_DEPOSIT_EVENTS_KEY; + const CF_NAME: &'static str = CF_META_NAME; +} + +impl SimpleWritableCell for PendingDepositEventsCellRef<'_> { + fn value_constructor(&self) -> DbResult> { + borsh::to_vec(&self).map_err(|err| { + DbError::borsh_cast_message( + err, + Some("Failed to serialize pending deposit events cell".to_owned()), + ) + }) + } +} + #[cfg(test)] mod uniform_tests { use crate::{ cells::SimpleStorableCell as _, sequencer::sequencer_cells::{ LEEStateCellOwned, LEEStateCellRef, LatestBlockMetaCellOwned, LatestBlockMetaCellRef, + PendingDepositEventsCellOwned, PendingDepositEventsCellRef, }, }; @@ -165,4 +210,20 @@ mod uniform_tests { LatestBlockMetaCellOwned::key_constructor(()).unwrap() ); } + + #[test] + fn pending_deposit_events_ref_and_owned_is_aligned() { + assert_eq!( + PendingDepositEventsCellRef::CELL_NAME, + PendingDepositEventsCellOwned::CELL_NAME + ); + assert_eq!( + PendingDepositEventsCellRef::CF_NAME, + PendingDepositEventsCellOwned::CF_NAME + ); + assert_eq!( + PendingDepositEventsCellRef::key_constructor(()).unwrap(), + PendingDepositEventsCellOwned::key_constructor(()).unwrap() + ); + } } diff --git a/program_methods/guest/src/bin/bridge.rs b/program_methods/guest/src/bin/bridge.rs index 4d983439..eb082c7c 100644 --- a/program_methods/guest/src/bin/bridge.rs +++ b/program_methods/guest/src/bin/bridge.rs @@ -33,6 +33,7 @@ fn main() { let chained_calls = match instruction { Instruction::Deposit { + l1_deposit_op_id: _, vault_program_id, recipient_id, amount, diff --git a/programs/bridge/core/src/lib.rs b/programs/bridge/core/src/lib.rs index 4a4e9fd8..1e1bff4f 100644 --- a/programs/bridge/core/src/lib.rs +++ b/programs/bridge/core/src/lib.rs @@ -12,6 +12,9 @@ pub enum Instruction { /// - Bridge PDA account /// - Recipient vault PDA account Deposit { + /// Deposit OP ID from L1, stored here to pin each [`Deposit`](Instruction::Deposit) to a + /// Deposit Event on L1. + l1_deposit_op_id: [u8; 32], vault_program_id: ProgramId, recipient_id: AccountId, amount: u128,