From 314f1d696c8dfe848867bc0859e1def6a2bb4441 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Mon, 22 Jun 2026 21:50:58 +0530 Subject: [PATCH 1/8] feat: Schedule undelegation from observed DLP requests --- .agents/context/crates/magicblock-accounts.md | 5 + .../crates/magicblock-committor-service.md | 10 +- .agents/rules/testing-and-validation.md | 13 + .agents/specs/validator-specification.md | 17 + Cargo.lock | 143 +++- Cargo.toml | 2 +- magicblock-accounts/Cargo.toml | 13 + magicblock-accounts/src/errors.rs | 2 + magicblock-accounts/src/lib.rs | 1 + .../src/scheduled_commits_processor.rs | 417 ++++++++++++ magicblock-api/src/magic_validator.rs | 36 + .../src/chainlink/fetch_cloner/mod.rs | 78 ++- magicblock-chainlink/src/chainlink/mod.rs | 78 ++- magicblock-committor-service/Cargo.toml | 3 + .../intent_executor/single_stage_executor.rs | 61 +- .../src/intent_executor/task_info_fetcher.rs | 225 ++++++- .../src/intent_executor/two_stage_executor.rs | 63 +- .../src/tasks/commit_finalize_task.rs | 15 +- magicblock-committor-service/src/tasks/mod.rs | 75 ++- .../src/tasks/task_builder.rs | 222 ++++-- .../src/tasks/task_strategist.rs | 62 ++ .../src/transactions.rs | 635 ++++++++++++++++++ test-integration/Cargo.lock | 81 ++- test-integration/Cargo.toml | 2 +- .../programs/schedulecommit/src/api.rs | 40 +- .../programs/schedulecommit/src/lib.rs | 77 +++ test-integration/schedulecommit/elfs/dlp.so | Bin 453720 -> 473048 bytes .../tests/02_commit_and_undelegate.rs | 171 ++++- .../test-chainlink/src/ixtest_context.rs | 2 + .../test-committor-service/tests/common.rs | 32 + .../tests/test_ix_commit_local.rs | 42 +- .../tests/test_transaction_preparator.rs | 11 + .../tests/utils/transactions.rs | 21 +- 33 files changed, 2437 insertions(+), 218 deletions(-) create mode 100644 magicblock-accounts/src/scheduled_commits_processor.rs diff --git a/.agents/context/crates/magicblock-accounts.md b/.agents/context/crates/magicblock-accounts.md index ac6379fbb..b2bf14c03 100644 --- a/.agents/context/crates/magicblock-accounts.md +++ b/.agents/context/crates/magicblock-accounts.md @@ -231,6 +231,10 @@ Do not replace this with an ordinary per-instance queue unless the Magic Program The code uses `expect(POISONED_MUTEX_MSG)` in the normal processing paths. One recovery cleanup path handles poisoning by logging and taking the inner map. Treat mutex poisoning as a serious invariant violation. +### Owner-program undelegation requests + +`magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. The committor then relies on DLP finalize/commit-finalize auto-undelegation accounts derived from `DelegationMetadata`; it does not need a separate request-PDA fetch to find the request rent payer. + ### Undelegation notifications are best-effort Before scheduling an intent bundle, the processor calls `chainlink.undelegation_requested` for accounts from commit-and-undelegate intents. Errors are aggregated and logged but do not fail scheduling. This favors settlement progress over local watcher correctness; if you change it, document how accounts that are already locally immutable/undelegating recover from missed base-layer subscriptions. @@ -296,6 +300,7 @@ Risks: Inspect first: - `prepare_intent_bundles_for_scheduling` and `process_undelegation_requests`; +- `magicblock-api/src/magic_validator.rs` startup wiring, especially whether the observed `UndelegationRequest` processor is spawned; - `ScheduledIntentBundle::get_undelegate_intent_pubkeys` / `has_undelegate_intent`; - `magicblock-chainlink::undelegation_requested`; - Magic Program code that marks accounts undelegating/immutable when scheduling commit-and-undelegate. diff --git a/.agents/context/crates/magicblock-committor-service.md b/.agents/context/crates/magicblock-committor-service.md index 9e5ce5c20..9ba6b918a 100644 --- a/.agents/context/crates/magicblock-committor-service.md +++ b/.agents/context/crates/magicblock-committor-service.md @@ -8,7 +8,7 @@ High-level responsibilities: - expose `CommittorService` / `BaseIntentCommittor` as the async service boundary used by `magicblock-api`, `magicblock-accounts`, and account cloning; - schedule intent bundles without executing mutually conflicting committed accounts in parallel; -- fetch Delegation Program metadata, commit nonces, rent reimbursements, and base accounts needed for task construction; +- fetch Delegation Program metadata, including commit nonces and rent payer data, plus base accounts needed for task construction; - choose commit delivery strategies: state args, diff args, state buffers, diff buffers, and optional ALTs; - prepare and clean up committor-program buffer accounts and TableMania lookup-table reservations; - execute single-stage or two-stage base-layer transaction flows and schedule action callbacks; @@ -189,7 +189,7 @@ The scheduler blocks on the union of `ScheduledIntentBundle::get_all_committed_p IntentExecutorImpl::execute -> mark persisted rows Pending -> TaskBuilderImpl::commit_tasks + finalize_tasks - -> fetch next commit nonces and diffable base accounts using max(remote_slot) + -> fetch next commit nonces, delegation metadata, and diffable base accounts using max(remote_slot) -> persist commit_id for each committed account -> create commit, commit-finalize, undelegate, finalize, and action tasks -> TaskStrategist::build_execution_strategy @@ -203,6 +203,10 @@ IntentExecutorImpl::execute -> reset nonce cache for all committed pubkeys on errors, or only undelegated pubkeys on successful undelegation ``` +Task building fetches `DelegationMetadata` for accounts whose base-layer flow may finalize. `FinalizeTask` and `CommitFinalizeTask` include the delegated account owner and `DelegationMetadata.rent_payer` so the Delegation Program can auto-undelegate owner-program requests during finalize, commit-finalize, and commit-finalize-from-buffer. The active task-building path derives the request PDA through the DLP instruction builders and does not fetch or decode `UndelegationRequest`; explicit undelegate tasks still pass `request_rent_payer = None` unless a future path deliberately restores request-account decoding. + +Transaction fit is not only packet size. `TaskStrategist` currently checks whether a single-stage transaction or each two-stage transaction fits the wire size, optionally after switching commits to buffers and adding ALTs, but it does not split a transaction stage by compute units. Each commit, finalize, commit-finalize, and undelegate task currently advertises `120_000` CU, while Agave caps a transaction at `1_400_000` CU. Keep task bundles below that transaction-level cap unless the strategist and executor/output/persistence model are extended to split, record, and confirm multiple transactions for the affected stage. + For committed accounts with `data.len() > COMMIT_STATE_SIZE_THRESHOLD` (`256`), the task builder fetches the base account and may use diff-in-args delivery. If the base-account fetch fails, it falls back to full state args and logs a warning. This can increase transaction size and trigger buffer/ALT strategy later. ### Delivery preparation and cleanup flow @@ -229,7 +233,7 @@ Do not remove sorted lock acquisition or the retiring map without replacing the ### `min_context_slot` and freshness -Task-info RPC reads use the maximum `remote_slot` across committed accounts as `min_context_slot` when fetching delegation metadata and diffable base accounts. This helps avoid building commits against base-layer state older than the ER account snapshot. The fetcher retries `Minimum context slot not reached` up to five times with short sleeps. Preserve this freshness check unless the broader account-sync/settlement contract changes. +Task-info RPC reads use the maximum `remote_slot` across committed accounts as `min_context_slot` when fetching delegation metadata and diffable base accounts. This helps avoid building commits against base-layer state older than the ER account snapshot, including stale rent-payer or owner-program undelegation-requester metadata used by auto-undelegation account metas. The fetcher retries `Minimum context slot not reached` up to five times with short sleeps. Preserve this freshness check unless the broader account-sync/settlement contract changes. ### Persistence is both status API and recovery state diff --git a/.agents/rules/testing-and-validation.md b/.agents/rules/testing-and-validation.md index a0b57cc9a..24f47b6ec 100644 --- a/.agents/rules/testing-and-validation.md +++ b/.agents/rules/testing-and-validation.md @@ -98,6 +98,19 @@ RUN_TESTS=committor_intent_executor make test The integration runner builds required SBF programs via `make programs` as dependencies of `make test`. +When updating `magicblock-delegation-program-api` to a new Delegation Program +commit, also update the DLP program binary used by integration validators: +`test-integration/schedulecommit/elfs/dlp.so`. A mismatched API/ELF can compile +but fail at runtime when instruction account layouts change, for example DLP +`TooManyAccountKeys` on `CommitFinalize`. + +Avoid using DLP transaction log strings as the primary success oracle in +committor integration tests. Local validator transaction history/log retrieval +can be inconsistent across DLP or validator revisions, and DLP may change opcode +logging without changing validator behavior. Prefer persisted committor status, +strategy, signatures, and final account owner/data checks; keep log fetches for +diagnostics on failure. + ## Isolating one integration test For fast debugging, start only the validators needed by a suite in one terminal, then run the desired Rust test directly in another terminal. diff --git a/.agents/specs/validator-specification.md b/.agents/specs/validator-specification.md index 71c4ff794..1fd61517e 100644 --- a/.agents/specs/validator-specification.md +++ b/.agents/specs/validator-specification.md @@ -257,6 +257,23 @@ When `ScheduleIntentBundle` includes undelegation, the Magic Program marks each This is a critical lifecycle invariant. Do not allow normal ER transactions to keep mutating an account after commit-and-undelegate has been scheduled. +Owner-program requested undelegation is recorded by the Delegation Program in +`DelegationMetadata.undelegation_requester = OwnerProgram` and an +`UndelegationRequest` PDA. This marker is not a validator-side completion +signal: the validator must still commit/finalize the latest ER state. For +commit/finalize, commit-finalize, and commit-finalize-from-buffer paths, the +committor supplies the DLP auto-undelegation accounts using the delegated +account's owner program and `DelegationMetadata.rent_payer`; it derives the +request PDA for those instruction metas and does not need to fetch or decode +`UndelegationRequest` during task construction. + +If DLP sees `OwnerProgram` requester during a successful finalize path, it +finalizes the committed state and undelegates/closes the delegation/request PDAs +in the same instruction flow. An explicit undelegate instruction later in the +same transaction may no-op once ownership has already returned to the owner +program. `AlreadyUndelegated` remains a conflict for validator-requested +undelegation state, not a reason to drop an owner-program request. + ### Callback discriminator The public docs specify an undelegation callback discriminator: diff --git a/Cargo.lock b/Cargo.lock index e4c21d437..d839bb02a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -280,7 +280,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -291,7 +291,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -900,17 +900,40 @@ dependencies = [ "subtle", ] +[[package]] +name = "borsh" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115e54d64eb62cdebad391c19efc9dce4981c690c85a33a12199d99bb9546fee" +dependencies = [ + "borsh-derive 0.10.4", + "hashbrown 0.13.2", +] + [[package]] name = "borsh" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ - "borsh-derive", + "borsh-derive 1.6.1", "bytes", "cfg_aliases", ] +[[package]] +name = "borsh-derive" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "831213f80d9423998dd696e2c5345aba6be7a0bd8cd19e31c5243e13df1cef89" +dependencies = [ + "borsh-derive-internal", + "borsh-schema-derive-internal", + "proc-macro-crate 0.1.5", + "proc-macro2", + "syn 1.0.109", +] + [[package]] name = "borsh-derive" version = "1.6.1" @@ -918,12 +941,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", - "proc-macro-crate", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.118", ] +[[package]] +name = "borsh-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65d6ba50644c98714aa2a70d13d7df3cd75cd2b523a2b452bf010443800976b3" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "borsh-schema-derive-internal" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "276691d96f063427be83e6692b86148e488ebba9f48f77788724ca027ba3b6d4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "brotli" version = "8.0.4" @@ -2021,7 +2066,7 @@ dependencies = [ "atomic", "pear", "serde", - "toml", + "toml 0.8.23", "uncased", "version_check", ] @@ -3422,7 +3467,7 @@ name = "magic-domain-program" version = "0.3.0" source = "git+https://github.com/magicblock-labs/magic-domain-program.git?rev=6cb903d#6cb903da837ebafeecb59a3861a457b7a2092e55" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck_derive", "solana-program 3.0.0", "solana-system-interface 3.1.0", @@ -3460,11 +3505,24 @@ name = "magicblock-accounts" version = "0.13.3" dependencies = [ "async-trait", + "magicblock-account-cloner", + "magicblock-chainlink", "magicblock-committor-service", + "magicblock-core", + "magicblock-delegation-program-api", + "magicblock-metrics", + "magicblock-program", + "solana-hash 4.2.0", + "solana-instruction 3.3.0", + "solana-keypair", "solana-pubkey 4.1.0", + "solana-signer", + "solana-transaction", "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", + "tokio-util", + "tracing", "url", ] @@ -3565,7 +3623,7 @@ version = "0.13.3" dependencies = [ "agave-feature-set", "anyhow", - "borsh", + "borsh 1.6.1", "fd-lock", "magic-domain-program", "magicblock-account-cloner", @@ -3631,7 +3689,7 @@ dependencies = [ "assert_matches", "async-trait", "bincode", - "borsh", + "borsh 1.6.1", "futures-util", "helius-laserstream", "lru 0.16.4", @@ -3684,7 +3742,7 @@ dependencies = [ name = "magicblock-committor-program" version = "0.13.3" dependencies = [ - "borsh", + "borsh 1.6.1", "paste", "solana-account 3.4.0", "solana-account-info 3.1.1", @@ -3701,7 +3759,7 @@ version = "0.13.3" dependencies = [ "async-trait", "bincode", - "borsh", + "borsh 1.6.1", "futures-util", "lru 0.16.4", "magicblock-account-cloner", @@ -3718,6 +3776,7 @@ dependencies = [ "rusqlite", "solana-account 3.4.0", "solana-account-decoder", + "solana-address-lookup-table-interface 3.0.1", "solana-commitment-config", "solana-compute-budget-interface", "solana-hash 4.2.0", @@ -3729,11 +3788,13 @@ dependencies = [ "solana-pubkey 4.1.0", "solana-rpc-client", "solana-rpc-client-api", + "solana-sdk-ids 3.1.0", "solana-signature 3.3.0", "solana-signer", "solana-transaction", "solana-transaction-error 3.1.0", "solana-transaction-status-client-types", + "static_assertions", "tempfile", "test-kit", "thiserror 2.0.18", @@ -3758,7 +3819,7 @@ dependencies = [ "solana-pubkey 4.1.0", "solana-signer", "tempfile", - "toml", + "toml 0.8.23", "url", ] @@ -3794,11 +3855,12 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" -version = "0.3.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" +version = "3.0.0" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7#72af1c7542ee00a383f0945184fee4a0d9cec6e0" dependencies = [ "bincode", - "borsh", + "borsh 0.10.4", + "borsh 1.6.1", "bytemuck", "const-crypto", "libsodium-rs", @@ -3813,6 +3875,7 @@ dependencies = [ "solana-instruction 3.3.0", "solana-loader-v3-interface 6.1.1", "solana-program 3.0.0", + "solana-pubkey 2.4.0", "solana-sdk", "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", @@ -4402,7 +4465,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4553,7 +4616,7 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.118", @@ -4907,6 +4970,15 @@ dependencies = [ "syn 2.0.118", ] +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml 0.5.11", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" @@ -4970,7 +5042,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03da047801ff44bb6a4d407d4860c05fd70bb81714e6b2f3812603d5b145b042" dependencies = [ "heck", - "itertools 0.13.0", + "itertools 0.14.0", "log", "multimap", "petgraph", @@ -4991,7 +5063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b570b25f7617e43d59005d0990ccb79e950a423952cea19671b7a876da390adf" dependencies = [ "anyhow", - "itertools 0.13.0", + "itertools 0.14.0", "proc-macro2", "quote", "syn 2.0.118", @@ -6247,7 +6319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -6388,7 +6460,7 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f08236dacd0e6dc8234becef58e27c8567856644ef509d7e97957d55a91dc72" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", @@ -6568,7 +6640,7 @@ version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c04abbae16f57178a163125805637b8a076175bb5c0002fb04f4792bea901cf7" dependencies = [ - "borsh", + "borsh 1.6.1", ] [[package]] @@ -6700,7 +6772,7 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8292c436b269ad23cecc8b24f7da3ab07ca111661e25e00ce0e1d22771951ab9" dependencies = [ - "borsh", + "borsh 1.6.1", "solana-instruction 3.3.0", "solana-sdk-ids 3.1.0", ] @@ -7116,7 +7188,7 @@ version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8064ea1d591ec791be95245058ca40f4f5345d390c200069d0f79bbf55bfae55" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "five8 1.0.0", @@ -7162,7 +7234,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97881335fc698deb46c6571945969aae6d93a14e2fff792a368b4fac872f116" dependencies = [ "bincode", - "borsh", + "borsh 1.6.1", "serde", "serde_derive", "solana-define-syscall 5.1.0", @@ -7790,7 +7862,7 @@ version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f04fa578707b3612b095f0c8e19b66a1233f7c42ca8082fcb3b745afcc0add6" dependencies = [ - "borsh", + "borsh 1.6.1", "serde", "serde_derive", ] @@ -7894,6 +7966,8 @@ version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b62adb9c3261a052ca1f999398c388f1daf558a1b492f60a6d9e64857db4ff1" dependencies = [ + "borsh 0.10.4", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "curve25519-dalek 4.1.3", @@ -8904,7 +8978,7 @@ dependencies = [ "agave-reserved-account-keys", "base64 0.22.1", "bincode", - "borsh", + "borsh 1.6.1", "bs58", "log", "serde", @@ -9065,7 +9139,7 @@ version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ea15126ebdc7e270c50d43884369af9f51d2308156d46a18e351522a164844d" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", ] @@ -9222,7 +9296,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6433917b60441d68d99a17e121d9db0ea15a9a69c0e5afa34649cf5ba12612f" dependencies = [ - "borsh", + "borsh 1.6.1", "solana-instruction 3.3.0", "solana-pubkey 3.0.0", ] @@ -9289,7 +9363,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f9c6e142cdf1e7e77f480053ec9f0ce989890768ddf91f619b50f39d1b456f5" dependencies = [ - "borsh", + "borsh 1.6.1", "bytemuck", "bytemuck_derive", "num-derive", @@ -9407,7 +9481,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c467c7c3bd056f8fe60119e7ec34ddd6f23052c2fa8f1f51999098063b72676" dependencies = [ - "borsh", + "borsh 1.6.1", "num-derive", "num-traits", "solana-borsh", @@ -9852,6 +9926,15 @@ dependencies = [ "webpki-roots 0.26.11", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.23" diff --git a/Cargo.toml b/Cargo.toml index 451715d7d..ce5ff6a14 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "72af1c7" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/magicblock-accounts/Cargo.toml b/magicblock-accounts/Cargo.toml index 5b48785a5..acd1da290 100644 --- a/magicblock-accounts/Cargo.toml +++ b/magicblock-accounts/Cargo.toml @@ -9,10 +9,23 @@ edition.workspace = true [dependencies] async-trait = { workspace = true } +tracing = { workspace = true } +magicblock-account-cloner = { workspace = true } +magicblock-chainlink = { workspace = true } magicblock-committor-service = { workspace = true } +magicblock-core = { workspace = true } +magicblock-delegation-program-api = { workspace = true } +magicblock-metrics = { workspace = true } +magicblock-program = { workspace = true } +solana-hash = { workspace = true } +solana-instruction = { workspace = true } +solana-keypair = { workspace = true } solana-pubkey = { workspace = true } +solana-signer = { workspace = true } +solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } tokio = { workspace = true } +tokio-util = { workspace = true } thiserror = { workspace = true } url = { workspace = true } diff --git a/magicblock-accounts/src/errors.rs b/magicblock-accounts/src/errors.rs index d4a7b5980..148921dfe 100644 --- a/magicblock-accounts/src/errors.rs +++ b/magicblock-accounts/src/errors.rs @@ -55,6 +55,8 @@ pub enum ScheduledCommitsProcessorError { RecvError(#[from] RecvError), #[error("CommittorSerivceError: {0}")] CommittorSerivceError(Box), + #[error("PoisonedMutex: {0}")] + PoisonedMutex(&'static str), } impl From for ScheduledCommitsProcessorError { diff --git a/magicblock-accounts/src/lib.rs b/magicblock-accounts/src/lib.rs index c7eac2118..d11a013b2 100644 --- a/magicblock-accounts/src/lib.rs +++ b/magicblock-accounts/src/lib.rs @@ -1,5 +1,6 @@ mod config; pub mod errors; +pub mod scheduled_commits_processor; mod traits; pub use config::*; diff --git a/magicblock-accounts/src/scheduled_commits_processor.rs b/magicblock-accounts/src/scheduled_commits_processor.rs new file mode 100644 index 000000000..8b1ef1ef5 --- /dev/null +++ b/magicblock-accounts/src/scheduled_commits_processor.rs @@ -0,0 +1,417 @@ +use std::{ + collections::HashMap, + fmt, + sync::{Arc, Mutex, MutexGuard}, + time::Duration, +}; + +use dlp_api::pda::undelegation_request_pda_from_delegated_account; +use magicblock_account_cloner::ChainlinkCloner; +use magicblock_chainlink::{ + ObservedUndelegationRequest, ProdChainlink, ProdInnerChainlink, +}; +use magicblock_core::{ + link::transactions::TransactionSchedulerHandle, traits::LatestBlockProvider, +}; +use magicblock_metrics::metrics::AccountFetchOrigin; +use magicblock_program::{ + instruction::MagicBlockInstruction, MAGIC_CONTEXT_PUBKEY, +}; +use solana_hash::Hash; +use solana_instruction::{AccountMeta, Instruction}; +use solana_keypair::Keypair; +use solana_pubkey::Pubkey; +use solana_signer::Signer; +use solana_transaction::Transaction; +use solana_transaction_error::TransactionError; +use tokio::sync::broadcast; +use tokio_util::sync::CancellationToken; +use tracing::{debug, error, info, warn}; + +const POISONED_MUTEX_MSG: &str = + "Mutex of ScheduledCommitsProcessorImpl internal state is poisoned"; +const UNDELEGATION_REQUEST_MAX_ATTEMPTS: usize = 3; +const UNDELEGATION_REQUEST_RETRY_BASE_DELAY: Duration = + Duration::from_millis(100); + +pub type InnerChainlinkImpl = ProdInnerChainlink; +pub type ChainlinkImpl = ProdChainlink; + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +struct ObservedUndelegationRequestIdentity { + created_slot: u64, + expires_at_slot: u64, + last_commit_id_at_request: u64, + rent_payer: Pubkey, +} + +impl From<&ObservedUndelegationRequest> + for ObservedUndelegationRequestIdentity +{ + fn from(request: &ObservedUndelegationRequest) -> Self { + Self { + created_slot: request.created_slot, + expires_at_slot: request.expires_at_slot, + last_commit_id_at_request: request.last_commit_id_at_request, + rent_payer: request.rent_payer, + } + } +} + +type ObservedUndelegationRequests = + HashMap; + +#[derive(Debug)] +enum ObservedUndelegationRequestError { + Transient(&'static str), + Schedule(TransactionError), + PoisonedMutex(&'static str), +} + +impl ObservedUndelegationRequestError { + fn retryable(&self) -> bool { + matches!(self, Self::Transient(_) | Self::Schedule(_)) + } +} + +impl fmt::Display for ObservedUndelegationRequestError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Transient(reason) => write!(f, "{reason}"), + Self::Schedule(err) => { + write!(f, "failed to schedule request: {err}") + } + Self::PoisonedMutex(msg) => write!(f, "{msg}"), + } + } +} + +pub struct ScheduledCommitsProcessorImpl { + chainlink: Arc, + cancellation_token: CancellationToken, + internal_transaction_scheduler: TransactionSchedulerHandle, + validator_authority: Arc, + latest_block_reader: Arc, + observed_undelegation_requests: Arc>, +} + +trait LatestBlockReader: Send + Sync { + fn blockhash(&self) -> Hash; +} + +impl LatestBlockReader for T +where + T: LatestBlockProvider, +{ + fn blockhash(&self) -> Hash { + LatestBlockProvider::blockhash(self) + } +} + +impl ScheduledCommitsProcessorImpl { + pub fn new( + chainlink: Arc, + internal_transaction_scheduler: TransactionSchedulerHandle, + validator_authority: Keypair, + latest_block: impl LatestBlockProvider, + ) -> Self { + Self { + chainlink, + cancellation_token: CancellationToken::new(), + internal_transaction_scheduler, + validator_authority: Arc::new(validator_authority), + latest_block_reader: Arc::new(latest_block.clone()), + observed_undelegation_requests: Arc::new(Mutex::default()), + } + } + + async fn undelegation_request_processor( + mut requests: broadcast::Receiver, + cancellation_token: CancellationToken, + chainlink: Arc, + internal_transaction_scheduler: TransactionSchedulerHandle, + validator_authority: Arc, + latest_block: Arc, + observed_requests: Arc>, + ) { + loop { + let request = tokio::select! { + biased; + _ = cancellation_token.cancelled() => { + info!("Shutting down undelegation request processor"); + return; + } + request = requests.recv() => { + match request { + Ok(request) => request, + Err(broadcast::error::RecvError::Closed) => { + info!("Undelegation request subscription closed"); + return; + } + Err(broadcast::error::RecvError::Lagged(skipped)) => { + error!( + skipped_count = skipped, + "Lagged behind undelegation request updates" + ); + continue; + } + } + } + }; + + Self::process_observed_undelegation_request_with_retries( + request, + &chainlink, + &internal_transaction_scheduler, + validator_authority.as_ref(), + latest_block.as_ref(), + &observed_requests, + &cancellation_token, + ) + .await; + } + } + + async fn process_observed_undelegation_request_with_retries( + request: ObservedUndelegationRequest, + chainlink: &ChainlinkImpl, + internal_transaction_scheduler: &TransactionSchedulerHandle, + validator_authority: &Keypair, + latest_block: &dyn LatestBlockReader, + observed_requests: &Arc>, + cancellation_token: &CancellationToken, + ) { + let mut attempt = 1; + loop { + let result = Self::process_observed_undelegation_request( + request.clone(), + chainlink, + internal_transaction_scheduler, + validator_authority, + latest_block, + observed_requests, + ) + .await; + match result { + Ok(()) => return, + Err(err) + if err.retryable() + && attempt < UNDELEGATION_REQUEST_MAX_ATTEMPTS => + { + let delay = UNDELEGATION_REQUEST_RETRY_BASE_DELAY + * 2_u32.pow((attempt - 1) as u32); + warn!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + attempt, + max_attempts = UNDELEGATION_REQUEST_MAX_ATTEMPTS, + retry_delay_ms = delay.as_millis(), + error = %err, + "Retrying observed undelegation request after transient failure" + ); + tokio::select! { + biased; + _ = cancellation_token.cancelled() => { + info!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + "Stopping undelegation request retry because processor is shutting down" + ); + return; + } + _ = tokio::time::sleep(delay) => {} + } + attempt += 1; + } + Err(err) => { + error!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + attempt, + max_attempts = UNDELEGATION_REQUEST_MAX_ATTEMPTS, + error = %err, + "Failed to process observed undelegation request" + ); + return; + } + } + } + } + + async fn process_observed_undelegation_request( + request: ObservedUndelegationRequest, + chainlink: &ChainlinkImpl, + internal_transaction_scheduler: &TransactionSchedulerHandle, + validator_authority: &Keypair, + latest_block: &dyn LatestBlockReader, + observed_requests: &Arc>, + ) -> Result<(), ObservedUndelegationRequestError> { + if request.observed_slot >= request.expires_at_slot { + warn!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + observed_slot = request.observed_slot, + expires_at_slot = request.expires_at_slot, + "Observed expired undelegation request; scheduling normal undelegation anyway to avoid timeout carry-over rollback when possible" + ); + } + + let expected_request_pda = + undelegation_request_pda_from_delegated_account( + &request.delegated_account, + ); + if expected_request_pda != request.request_pda { + error!( + request_pda = %request.request_pda, + expected_request_pda = %expected_request_pda, + delegated_account = %request.delegated_account, + "Skipping undelegation request with invalid PDA" + ); + return Ok(()); + } + + let request_identity = + ObservedUndelegationRequestIdentity::from(&request); + { + let mut observed = Self::lock_observed_requests(observed_requests)?; + if observed.get(&request.request_pda) == Some(&request_identity) { + debug!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + "Skipping already observed undelegation request" + ); + return Ok(()); + } + observed.insert(request.request_pda, request_identity); + } + + let delegated = match chainlink + .accounts_delegated_on_base_and_er( + &[request.delegated_account], + AccountFetchOrigin::GetAccount, + ) + .await + { + Ok(value) => value.into_iter().next().unwrap_or(false), + Err(err) => { + Self::remove_observed_request( + observed_requests, + &request.request_pda, + )?; + error!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + error = ?err, + "Failed to verify requested undelegation account" + ); + return Err(ObservedUndelegationRequestError::Transient( + "failed to verify requested undelegation account", + )); + } + }; + if !delegated { + Self::remove_observed_request( + observed_requests, + &request.request_pda, + )?; + debug!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + "Skipping request because account is not delegated on base and ER" + ); + return Ok(()); + } + + if let Err(err) = chainlink + .undelegation_requested(request.delegated_account) + .await + { + error!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + error = ?err, + "Failed to start undelegation tracking" + ); + } + + let ix = Self::schedule_commit_and_undelegate_instruction( + &validator_authority.pubkey(), + request.delegated_account, + ); + let tx = Transaction::new_signed_with_payer( + &[ix], + Some(&validator_authority.pubkey()), + &[validator_authority], + latest_block.blockhash(), + ); + + if let Err(err) = internal_transaction_scheduler.execute(tx).await { + Self::remove_observed_request( + observed_requests, + &request.request_pda, + )?; + return Err(ObservedUndelegationRequestError::Schedule(err)); + } + + info!( + request_pda = %request.request_pda, + delegated_account = %request.delegated_account, + "Scheduled requested undelegation via ScheduleCommitAndUndelegate" + ); + Ok(()) + } + + fn lock_observed_requests<'a>( + observed_requests: &'a Arc>, + ) -> Result< + MutexGuard<'a, ObservedUndelegationRequests>, + ObservedUndelegationRequestError, + > { + observed_requests.lock().map_err(|_| { + ObservedUndelegationRequestError::PoisonedMutex(POISONED_MUTEX_MSG) + }) + } + + fn remove_observed_request( + observed_requests: &Arc>, + request_pda: &Pubkey, + ) -> Result<(), ObservedUndelegationRequestError> { + Self::lock_observed_requests(observed_requests)?.remove(request_pda); + Ok(()) + } + + fn schedule_commit_and_undelegate_instruction( + payer: &Pubkey, + delegated_account: Pubkey, + ) -> Instruction { + Instruction::new_with_bincode( + magicblock_program::id(), + &MagicBlockInstruction::ScheduleCommitAndUndelegate, + vec![ + AccountMeta::new(*payer, true), + AccountMeta::new(MAGIC_CONTEXT_PUBKEY, false), + AccountMeta::new(delegated_account, false), + ], + ) + } + + pub fn spawn_undelegation_request_processor(self: &Arc) { + let Some(requests) = self.chainlink.subscribe_undelegation_requests() + else { + return; + }; + tokio::spawn(Self::undelegation_request_processor( + requests, + self.cancellation_token.clone(), + self.chainlink.clone(), + self.internal_transaction_scheduler.clone(), + self.validator_authority.clone(), + self.latest_block_reader.clone(), + self.observed_undelegation_requests.clone(), + )); + } + + pub fn stop(&self) { + self.cancellation_token.cancel(); + } +} diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index b4d569ab8..0dc4f40cb 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -9,6 +9,7 @@ use std::{ }; use magicblock_account_cloner::ChainlinkCloner; +use magicblock_accounts::scheduled_commits_processor::ScheduledCommitsProcessorImpl; use magicblock_accounts_db::{traits::AccountsBank, AccountsDb}; use magicblock_aperture::{ initialize_aperture, @@ -113,6 +114,7 @@ pub struct MagicValidator { ledger_truncator: LedgerTruncator, intent_execution_service: IntentExecutionServiceImpl, replication_service: Option, + scheduled_commits_processor: Option>, rpc_handle: thread::JoinHandle<()>, identity: Pubkey, transaction_scheduler: TransactionSchedulerHandle, @@ -323,6 +325,19 @@ impl MagicValidator { ); log_timing("startup", "system_metrics_ticker_start", step_start); + let scheduled_commits_processor = (!matches!( + config.validator.replication_mode, + ReplicationMode::Replica { .. } + )) + .then(|| { + Arc::new(ScheduledCommitsProcessorImpl::new( + chainlink.clone(), + dispatch.transaction_scheduler.clone(), + identity_keypair.insecure_clone(), + ledger.latest_block().clone(), + )) + }); + let step_start = Instant::now(); load_upgradeable_programs( &accountsdb, @@ -444,6 +459,7 @@ impl MagicValidator { _metrics: (metrics_service, system_metrics_ticker), intent_execution_service, replication_service, + scheduled_commits_processor, token, ledger, ledger_truncator, @@ -1037,6 +1053,15 @@ impl MagicValidator { } } + if !matches!( + self.config.validator.replication_mode, + ReplicationMode::Replica { .. } + ) { + if let Some(processor) = self.scheduled_commits_processor.as_ref() { + processor.spawn_undelegation_request_processor(); + } + } + // Now we are ready to start all services and are ready to accept transactions if let Some(frequency) = self .config @@ -1125,6 +1150,17 @@ impl MagicValidator { // Ordering is important here // Commitor service shall be stopped last self.token.cancel(); + if let Some(ref scheduled_commits_processor) = + self.scheduled_commits_processor + { + let step_start = Instant::now(); + scheduled_commits_processor.stop(); + log_timing( + "shutdown", + "scheduled_commits_processor_stop", + step_start, + ); + } let step_start = Instant::now(); if let Err(err) = self.intent_execution_service.stop().await { diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index 2546c98b2..d45f906bc 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -9,7 +9,8 @@ use std::{ }; use dlp_api::{ - pda::delegation_record_pda_from_delegated_account, state::DelegationRecord, + pda::delegation_record_pda_from_delegated_account, + state::{DelegationRecord, UndelegationRequest}, }; use lru::LruCache; use magicblock_accounts_db::traits::AccountsBank; @@ -35,7 +36,7 @@ use solana_sdk_ids::system_program; use solana_signature::Signature; use solana_signer::Signer; use tokio::{ - sync::{mpsc, oneshot, Semaphore}, + sync::{broadcast, mpsc, oneshot, Semaphore}, task, task::JoinSet, }; @@ -76,6 +77,7 @@ use crate::{ blacklisted_accounts::{ blacklisted_accounts, programs_not_to_subscribe, }, + ObservedUndelegationRequest, }, cloner::{ errors::{ClonerError, ClonerResult}, @@ -145,6 +147,8 @@ where /// Risk checker for post-delegation action addresses. risk_service: Option>, + + undelegation_request_sender: broadcast::Sender, } struct PendingUndelegationGuard { @@ -209,6 +213,9 @@ where .pending_operation_timeout_ms .clone(), risk_service: self.risk_service.clone(), + undelegation_request_sender: self + .undelegation_request_sender + .clone(), } } } @@ -230,6 +237,33 @@ where subscription_updates_rx: mpsc::Receiver, allowed_programs: Option>, risk_service: Option>, + ) -> Arc { + let (undelegation_request_sender, _) = broadcast::channel(1024); + Self::new_with_undelegation_request_sender( + remote_account_provider, + accounts_bank, + cloner, + validator_keypair, + subscription_updates_rx, + allowed_programs, + risk_service, + undelegation_request_sender, + ) + } + + /// Create FetchCloner with subscription updates and request notifications connected. + #[allow(clippy::too_many_arguments)] + pub fn new_with_undelegation_request_sender( + remote_account_provider: &Arc>, + accounts_bank: &Arc, + cloner: &Arc, + validator_keypair: Keypair, + subscription_updates_rx: mpsc::Receiver, + allowed_programs: Option>, + risk_service: Option>, + undelegation_request_sender: broadcast::Sender< + ObservedUndelegationRequest, + >, ) -> Arc { let validator_pubkey = validator_keypair.pubkey(); let blacklisted_accounts = blacklisted_accounts(&validator_pubkey); @@ -258,6 +292,7 @@ where FETCH_CLONE_OPERATION_TIMEOUT.as_millis() as u64, )), risk_service, + undelegation_request_sender, }); let accounts_bank_for_eviction = accounts_bank.clone(); @@ -2147,6 +2182,45 @@ where // use, etc. (None, None, DelegationActions::default()) } + } else if let Ok(request) = + UndelegationRequest::try_from_bytes_with_discriminator( + account.data(), + ) + { + let observed = ObservedUndelegationRequest { + request_pda: pubkey, + delegated_account: request.delegated_account, + owner_program: request.owner_program, + rent_payer: request.rent_payer, + created_slot: request.created_slot, + expires_at_slot: request.expires_at_slot, + last_commit_id_at_request: request + .last_commit_id_at_request, + observed_slot: account.remote_slot(), + }; + trace!( + request_pda = %observed.request_pda, + delegated_account = %observed.delegated_account, + owner_program = %observed.owner_program, + rent_payer = %observed.rent_payer, + expires_at_slot = observed.expires_at_slot, + "Observed DLP undelegation request" + ); + if let Err(broadcast::error::SendError(observed)) = + self.undelegation_request_sender.send(observed) + { + warn!( + request_pda = %observed.request_pda, + delegated_account = %observed.delegated_account, + owner_program = %observed.owner_program, + "Dropped observed DLP undelegation request because no subscribers are active" + ); + } + ( + Some(account.into_account_shared_data()), + None, + DelegationActions::default(), + ) } else if is_internal_dlp_account_data(account.data()) { ( Some(account.into_account_shared_data()), diff --git a/magicblock-chainlink/src/chainlink/mod.rs b/magicblock-chainlink/src/chainlink/mod.rs index 2f4a844c3..70dd82b2a 100644 --- a/magicblock-chainlink/src/chainlink/mod.rs +++ b/magicblock-chainlink/src/chainlink/mod.rs @@ -15,7 +15,10 @@ use solana_commitment_config::CommitmentConfig; use solana_keypair::Keypair; use solana_pubkey::Pubkey; use solana_transaction::sanitized::SanitizedTransaction; -use tokio::{sync::mpsc, task}; +use tokio::{ + sync::{broadcast, mpsc}, + task, +}; use tracing::*; use crate::{ @@ -56,6 +59,18 @@ pub type ProdChainlink = ReplicationModeAwareChainlink< C, >; +#[derive(Clone, Debug, PartialEq, Eq)] +pub struct ObservedUndelegationRequest { + pub request_pda: Pubkey, + pub delegated_account: Pubkey, + pub owner_program: Pubkey, + pub rent_payer: Pubkey, + pub created_slot: u64, + pub expires_at_slot: u64, + pub last_commit_id_at_request: u64, + pub observed_slot: u64, +} + // ----------------- // Chainlink // ----------------- @@ -67,6 +82,7 @@ pub struct InnerChainlink< > { accounts_bank: Arc, fetch_cloner: Option>>, + undelegation_request_sender: broadcast::Sender, /// The subscription to events for each account that is removed from /// the accounts tracked by the provider. /// In that case we also remove it from the bank since it is no longer @@ -188,6 +204,17 @@ impl Self::Disabled => false, } } + + pub fn subscribe_undelegation_requests( + &self, + ) -> Option> { + match self { + Self::Enabled(chainlink) => { + Some(chainlink.subscribe_undelegation_requests()) + } + Self::Disabled => None, + } + } } impl @@ -196,6 +223,21 @@ impl pub fn try_new( accounts_bank: &Arc, fetch_cloner: Option>>, + ) -> ChainlinkResult { + let (undelegation_request_sender, _) = broadcast::channel(1024); + Self::try_new_with_undelegation_request_sender( + accounts_bank, + fetch_cloner, + undelegation_request_sender, + ) + } + + pub fn try_new_with_undelegation_request_sender( + accounts_bank: &Arc, + fetch_cloner: Option>>, + undelegation_request_sender: broadcast::Sender< + ObservedUndelegationRequest, + >, ) -> ChainlinkResult { let removed_accounts_sub = if let Some(fetch_cloner) = &fetch_cloner { let removed_accounts_rx = @@ -213,6 +255,7 @@ impl Ok(Self { accounts_bank: accounts_bank.clone(), fetch_cloner, + undelegation_request_sender, removed_accounts_sub, }) } @@ -254,6 +297,7 @@ impl Some(chain_slot), ) .await?; + let (undelegation_request_sender, _) = broadcast::channel(1024); let fetch_cloner = if let Some(provider) = account_provider { let provider = Arc::new(provider); let risk_service = RiskService::try_from_config( @@ -261,21 +305,27 @@ impl ledger_path, )? .map(Arc::new); - let fetch_cloner = FetchCloner::new( - &provider, - accounts_bank, - cloner, - validator_keypair, - rx, - chainlink_config.allowed_programs.clone(), - risk_service, - ); + let fetch_cloner = + FetchCloner::new_with_undelegation_request_sender( + &provider, + accounts_bank, + cloner, + validator_keypair, + rx, + chainlink_config.allowed_programs.clone(), + risk_service, + undelegation_request_sender.clone(), + ); Some(fetch_cloner) } else { None }; - InnerChainlink::try_new(accounts_bank, fetch_cloner) + InnerChainlink::try_new_with_undelegation_request_sender( + accounts_bank, + fetch_cloner, + undelegation_request_sender, + ) } fn subscribe_account_removals( @@ -594,6 +644,12 @@ impl .map(|provider| provider.is_watching(pubkey)) .unwrap_or(false) } + + pub fn subscribe_undelegation_requests( + &self, + ) -> broadcast::Receiver { + self.undelegation_request_sender.subscribe() + } } // ----------------- diff --git a/magicblock-committor-service/Cargo.toml b/magicblock-committor-service/Cargo.toml index d9728d739..f1be595d0 100644 --- a/magicblock-committor-service/Cargo.toml +++ b/magicblock-committor-service/Cargo.toml @@ -51,11 +51,14 @@ solana-signer = { workspace = true } solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } solana-transaction-status-client-types = { workspace = true } +static_assertions = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } tokio-util = { workspace = true } [dev-dependencies] +solana-address-lookup-table-interface = { workspace = true } +solana-sdk-ids = { workspace = true } solana-signature = { workspace = true, features = ["rand"] } rand = { workspace = true } tempfile = { workspace = true } diff --git a/magicblock-committor-service/src/intent_executor/single_stage_executor.rs b/magicblock-committor-service/src/intent_executor/single_stage_executor.rs index 3b9dddfce..d153b0633 100644 --- a/magicblock-committor-service/src/intent_executor/single_stage_executor.rs +++ b/magicblock-committor-service/src/intent_executor/single_stage_executor.rs @@ -22,7 +22,10 @@ use crate::{ IntentExecutionReport, }, persist::{IntentPersister, IntentPersisterImpl}, - tasks::{task_strategist::TransactionStrategy, BaseTaskImpl, FinalizeTask}, + tasks::{ + task_builder::TaskBuilderError, task_strategist::TransactionStrategy, + BaseTaskImpl, FinalizeTask, + }, transaction_preparator::TransactionPreparator, }; @@ -215,22 +218,36 @@ where ) => { let optimized_tasks = self.transaction_strategy.optimized_tasks.as_slice(); - if let Some(delegated_account) = err + if let Some(( + delegated_account, + owner_program, + min_context_slot, + rent_reimbursement, + )) = err .task_index() .and_then(|index| optimized_tasks.get(index as usize)) .and_then(|task| match task { - BaseTaskImpl::Commit(task) => { - Some(task.committed_account.pubkey) - } - BaseTaskImpl::CommitFinalize(task) => { - Some(task.committed_account.pubkey) - } + BaseTaskImpl::Commit(task) => Some(( + task.committed_account.pubkey, + task.committed_account.account.owner, + task.committed_account.remote_slot, + None, + )), + BaseTaskImpl::CommitFinalize(task) => Some(( + task.committed_account.pubkey, + task.committed_account.account.owner, + task.committed_account.remote_slot, + Some(task.rent_reimbursement), + )), _ => None, }) { self.handle_unfinalized_account_error( signature, delegated_account, + owner_program, + min_context_slot, + rent_reimbursement, transaction_preparator, ) .await @@ -273,10 +290,34 @@ where &self, failed_signature: &Option, delegated_account: Pubkey, + owner_program: Pubkey, + min_context_slot: u64, + rent_reimbursement: Option, transaction_preparator: &T, ) -> IntentExecutorResult> { - let finalize_task: BaseTaskImpl = - FinalizeTask { delegated_account }.into(); + let rent_reimbursement = + if let Some(rent_reimbursement) = rent_reimbursement { + rent_reimbursement + } else { + self.task_info_fetcher + .fetch_delegation_metadata( + &[delegated_account], + min_context_slot, + ) + .await + .map_err(TaskBuilderError::FinalizedTasksBuildError)? + .get(&delegated_account) + .map(|metadata| metadata.rent_payer) + .ok_or(TaskBuilderError::MissingDelegationMetadata( + delegated_account, + ))? + }; + let finalize_task: BaseTaskImpl = FinalizeTask { + delegated_account, + owner_program, + rent_reimbursement, + } + .into(); prepare_and_execute_strategy( &self.intent_client, &self.authority, diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index b4f26fe1d..e824d5ba2 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -8,7 +8,9 @@ use std::{ use async_trait::async_trait; use dlp_api::{ - delegation_metadata_seeds_from_delegated_account, state::DelegationMetadata, + delegation_metadata_seeds_from_delegated_account, + pda::undelegation_request_pda_from_delegated_account, + state::{DelegationMetadata, UndelegationRequest}, }; use lru::LruCache; use magicblock_metrics::metrics; @@ -53,6 +55,20 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { min_context_slot: u64, ) -> TaskInfoFetcherResult>; + /// Fetches delegation metadata keyed by delegated account pubkey. + async fn fetch_delegation_metadata( + &self, + pubkeys: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult>; + + /// Fetches request-undelegation accounts keyed by delegated account pubkey. + async fn fetch_undelegation_requests( + &self, + delegated_accounts: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult>; + async fn get_base_accounts( &self, pubkeys: &[Pubkey], @@ -172,6 +188,57 @@ impl RpcTaskInfoFetcher { } } + pub async fn fetch_optional_accounts_with_retries( + rpc_client: &MagicblockRpcClient, + pubkeys: &[Pubkey], + min_context_slot: u64, + max_retries: NonZeroUsize, + ) -> TaskInfoFetcherResult>> { + if pubkeys.is_empty() { + return Ok(Vec::new()); + } + + let mut i = 0; + loop { + i += 1; + let err = match Self::fetch_optional_accounts( + rpc_client, + pubkeys, + min_context_slot, + ) + .await + { + Ok(value) => break Ok(value), + Err(err) => err, + }; + + match err { + TaskInfoFetcherError::MinContextSlotNotReachedError(_, _) => { + info!( + min_context_slot, + attempt = i, + "Min context slot not reached" + ); + tokio::time::sleep(Duration::from_millis(100)).await; + } + TaskInfoFetcherError::MagicBlockRpcClientError(ref err) => { + warn!(error = ?err, attempt = i, "Fetch optional account error"); + } + TaskInfoFetcherError::AccountNotFoundError(_) + | TaskInfoFetcherError::InvalidAccountDataError(_) => { + error!(error = ?err, "Unexpected error"); + break Err(err); + } + } + + if i >= max_retries.get() { + break Err(err); + } + + tokio::time::sleep(Duration::from_millis(50)).await; + } + } + /// Fetches specified list of accounts pub async fn fetch_accounts( rpc_client: &MagicblockRpcClient, @@ -221,6 +288,34 @@ impl RpcTaskInfoFetcher { Ok(accounts) } + + pub async fn fetch_optional_accounts( + rpc_client: &MagicblockRpcClient, + pubkeys: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult>> { + if pubkeys.is_empty() { + return Ok(Vec::new()); + } + + metrics::inc_task_info_fetcher_a_count(); + let commitment = rpc_client.commitment(); + rpc_client + .get_multiple_accounts_with_config( + pubkeys, + RpcAccountInfoConfig { + encoding: Some(UiAccountEncoding::Base64Zstd), + commitment: Some(commitment), + data_slice: None, + min_context_slot: Some(min_context_slot), + }, + None, + ) + .await + .map_err(|err| { + TaskInfoFetcherError::map_client_error(min_context_slot, err) + }) + } } #[async_trait] @@ -241,7 +336,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { ) .await? .into_iter() - .map(|m| m.last_update_nonce + 1); + .map(|m| m.last_commit_id + 1); Ok(pubkeys.iter().copied().zip(nonces).collect()) } @@ -261,7 +356,7 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { ) .await? .into_iter() - .map(|m| m.last_update_nonce); + .map(|m| m.last_commit_id); Ok(pubkeys.iter().copied().zip(nonces).collect()) } @@ -282,6 +377,78 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .collect()) } + async fn fetch_delegation_metadata( + &self, + pubkeys: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult> { + Ok(pubkeys + .iter() + .copied() + .zip( + Self::fetch_metadata_with_retries( + &self.rpc_client, + pubkeys, + min_context_slot, + NUM_FETCH_RETRIES, + ) + .await?, + ) + .collect()) + } + + async fn fetch_undelegation_requests( + &self, + delegated_accounts: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult> { + if delegated_accounts.is_empty() { + return Ok(HashMap::new()); + } + + let request_pdas = delegated_accounts + .iter() + .map(undelegation_request_pda_from_delegated_account) + .collect::>(); + + let accounts = Self::fetch_optional_accounts_with_retries( + &self.rpc_client, + &request_pdas, + min_context_slot, + NUM_FETCH_RETRIES, + ) + .await?; + + let mut requests = HashMap::new(); + for ((delegated_account, request_pda), account) in delegated_accounts + .iter() + .copied() + .zip(request_pdas) + .zip(accounts.into_iter()) + { + let Some(account) = account else { + continue; + }; + let request = + *UndelegationRequest::try_from_bytes_with_discriminator( + &account.data, + ) + .map_err(|_| { + TaskInfoFetcherError::InvalidAccountDataError(request_pda) + })?; + + if request.delegated_account != delegated_account { + return Err(TaskInfoFetcherError::InvalidAccountDataError( + request_pda, + )); + } + + requests.insert(delegated_account, request); + } + + Ok(requests) + } + async fn get_base_accounts( &self, pubkeys: &[Pubkey], @@ -623,6 +790,26 @@ impl TaskInfoFetcher for CacheTaskInfoFetcher { .await } + async fn fetch_delegation_metadata( + &self, + pubkeys: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult> { + self.inner + .fetch_delegation_metadata(pubkeys, min_context_slot) + .await + } + + async fn fetch_undelegation_requests( + &self, + delegated_accounts: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult> { + self.inner + .fetch_undelegation_requests(delegated_accounts, min_context_slot) + .await + } + async fn get_base_accounts( &self, pubkeys: &[Pubkey], @@ -1015,6 +1202,38 @@ mod tests { unimplemented!() } + async fn fetch_delegation_metadata( + &self, + pubkeys: &[Pubkey], + _: u64, + ) -> TaskInfoFetcherResult> + { + Ok(pubkeys + .iter() + .map(|pubkey| { + ( + *pubkey, + DelegationMetadata { + last_commit_id: 0, + undelegation_requester: + dlp_api::state::UndelegationRequester::None, + seeds: vec![], + rent_payer: *pubkey, + }, + ) + }) + .collect()) + } + + async fn fetch_undelegation_requests( + &self, + _delegated_accounts: &[Pubkey], + _: u64, + ) -> TaskInfoFetcherResult> + { + Ok(HashMap::new()) + } + async fn get_base_accounts( &self, _: &[Pubkey], diff --git a/magicblock-committor-service/src/intent_executor/two_stage_executor.rs b/magicblock-committor-service/src/intent_executor/two_stage_executor.rs index 196ae72be..313065f9f 100644 --- a/magicblock-committor-service/src/intent_executor/two_stage_executor.rs +++ b/magicblock-committor-service/src/intent_executor/two_stage_executor.rs @@ -23,7 +23,10 @@ use crate::{ IntentExecutionReport, }, persist::{IntentPersister, IntentPersisterImpl}, - tasks::{task_strategist::TransactionStrategy, BaseTaskImpl, FinalizeTask}, + tasks::{ + task_builder::TaskBuilderError, task_strategist::TransactionStrategy, + BaseTaskImpl, FinalizeTask, + }, transaction_preparator::TransactionPreparator, }; @@ -204,21 +207,55 @@ where let optimized_tasks = self.state.commit_strategy.optimized_tasks.as_slice(); let task_index = err.task_index(); - if let Some(delegated_account) = task_index + if let Some(( + delegated_account, + owner_program, + min_context_slot, + rent_reimbursement, + )) = task_index .and_then(|index| optimized_tasks.get(index as usize)) .and_then(|task| match task { - BaseTaskImpl::Commit(task) => { - Some(task.committed_account.pubkey) - } - BaseTaskImpl::CommitFinalize(task) => { - Some(task.committed_account.pubkey) - } + BaseTaskImpl::Commit(task) => Some(( + task.committed_account.pubkey, + task.committed_account.account.owner, + task.committed_account.remote_slot, + None, + )), + BaseTaskImpl::CommitFinalize(task) => Some(( + task.committed_account.pubkey, + task.committed_account.account.owner, + task.committed_account.remote_slot, + Some(task.rent_reimbursement), + )), _ => None, }) { + let rent_reimbursement = + if let Some(rent_reimbursement) = rent_reimbursement { + rent_reimbursement + } else { + task_info_fetcher + .fetch_delegation_metadata( + &[delegated_account], + min_context_slot, + ) + .await + .map_err( + TaskBuilderError::FinalizedTasksBuildError, + )? + .get(&delegated_account) + .map(|metadata| metadata.rent_payer) + .ok_or( + TaskBuilderError::MissingDelegationMetadata( + delegated_account, + ), + )? + }; self.handle_unfinalized_account_error( signature, delegated_account, + owner_program, + rent_reimbursement, transaction_preparator, ) .await @@ -274,10 +311,16 @@ where &self, failed_signature: &Option, delegated_account: Pubkey, + owner_program: Pubkey, + rent_reimbursement: Pubkey, transaction_preparator: &T, ) -> IntentExecutorResult> { - let finalize_task: BaseTaskImpl = - FinalizeTask { delegated_account }.into(); + let finalize_task: BaseTaskImpl = FinalizeTask { + delegated_account, + owner_program, + rent_reimbursement, + } + .into(); prepare_and_execute_strategy( &self.intent_client, &self.authority, diff --git a/magicblock-committor-service/src/tasks/commit_finalize_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_task.rs index 6a174f582..33d6abe5c 100644 --- a/magicblock-committor-service/src/tasks/commit_finalize_task.rs +++ b/magicblock-committor-service/src/tasks/commit_finalize_task.rs @@ -1,7 +1,9 @@ use dlp_api::{ args::CommitFinalizeArgs, diff::compute_diff, - instruction_builder::{commit_diff_size_budget, commit_size_budget}, + instruction_builder::{ + commit_finalize_from_buffer_size_budget, commit_finalize_size_budget, + }, AccountSizeClass, }; use magicblock_committor_program::Chunks; @@ -29,6 +31,7 @@ pub struct CommitFinalizeTask { pub allow_undelegation: bool, pub committed_account: CommittedAccount, pub delivery: CommitDelivery, + pub rent_reimbursement: Pubkey, } impl CommitFinalizeTask { @@ -63,6 +66,8 @@ impl CommitFinalizeTask { dlp_api::instruction_builder::commit_finalize( *validator, self.committed_account.pubkey, + self.committed_account.account.owner, + self.rent_reimbursement, &mut args, &data, ) @@ -95,6 +100,8 @@ impl CommitFinalizeTask { *validator, self.committed_account.pubkey, data_buffer_pubkey, + self.committed_account.account.owner, + self.rent_reimbursement, &mut args, ) .0 @@ -241,16 +248,16 @@ impl BaseTask for CommitFinalizeTask { fn accounts_size_budget(&self) -> u32 { match &self.delivery { CommitDelivery::StateInArgs => { - commit_size_budget(AccountSizeClass::Dynamic( + commit_finalize_size_budget(AccountSizeClass::Dynamic( self.committed_account.account.data.len() as u32, )) } CommitDelivery::StateInBuffer { .. } | CommitDelivery::DiffInBuffer { .. } => { - commit_size_budget(AccountSizeClass::Huge) + commit_finalize_from_buffer_size_budget(AccountSizeClass::Huge) } CommitDelivery::DiffInArgs { .. } => { - commit_diff_size_budget(AccountSizeClass::Dynamic( + commit_finalize_size_budget(AccountSizeClass::Dynamic( self.committed_account.account.data.len() as u32, )) } diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index 7640ff74e..fefc73c92 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -95,10 +95,16 @@ impl BaseTask for BaseTaskImpl { AccountSizeClass::Huge, ) } - Self::Undelegate(_) => { - dlp_api::instruction_builder::undelegate_size_budget( - AccountSizeClass::Huge, - ) + Self::Undelegate(value) => { + if value.request_rent_payer.is_some() { + dlp_api::instruction_builder::undelegate_with_request_size_budget( + AccountSizeClass::Huge, + ) + } else { + dlp_api::instruction_builder::undelegate_size_budget( + AccountSizeClass::Huge, + ) + } } } } @@ -177,16 +183,27 @@ pub struct UndelegateTask { pub delegated_account: Pubkey, pub owner_program: Pubkey, pub rent_reimbursement: Pubkey, + pub request_rent_payer: Option, } impl UndelegateTask { pub fn instruction(&self, validator: &Pubkey) -> Instruction { - dlp_api::instruction_builder::undelegate( - *validator, - self.delegated_account, - self.owner_program, - self.rent_reimbursement, - ) + if let Some(request_rent_payer) = self.request_rent_payer { + dlp_api::instruction_builder::undelegate_with_request( + *validator, + self.delegated_account, + self.owner_program, + self.rent_reimbursement, + request_rent_payer, + ) + } else { + dlp_api::instruction_builder::undelegate( + *validator, + self.delegated_account, + self.owner_program, + self.rent_reimbursement, + ) + } } } @@ -199,6 +216,8 @@ impl From for BaseTaskImpl { #[derive(Clone, Debug)] pub struct FinalizeTask { pub delegated_account: Pubkey, + pub owner_program: Pubkey, + pub rent_reimbursement: Pubkey, } impl FinalizeTask { @@ -206,6 +225,8 @@ impl FinalizeTask { dlp_api::instruction_builder::finalize( *validator, self.delegated_account, + self.owner_program, + self.rent_reimbursement, ) } } @@ -548,6 +569,10 @@ impl CleanupTask { #[cfg(test)] mod serialization_safety_test { + use dlp_api::{ + discriminator::DlpDiscriminator, + pda::undelegation_request_pda_from_delegated_account, + }; use magicblock_core::intent::CommittedAccount; use magicblock_program::{ args::ShortAccountMeta, magic_scheduled_base_intent::ProgramArgs, @@ -603,6 +628,8 @@ mod serialization_safety_test { // Test Finalize variant let finalize_task: BaseTaskImpl = FinalizeTask { delegated_account: Pubkey::new_unique(), + owner_program: Pubkey::new_unique(), + rent_reimbursement: Pubkey::new_unique(), } .into(); assert_serializable(&finalize_task.instruction(&validator)); @@ -612,6 +639,7 @@ mod serialization_safety_test { delegated_account: Pubkey::new_unique(), owner_program: Pubkey::new_unique(), rent_reimbursement: Pubkey::new_unique(), + request_rent_payer: None, } .into(); assert_serializable(&undelegate_task.instruction(&validator)); @@ -661,6 +689,33 @@ mod serialization_safety_test { assert_serializable(&base_action_v2.instruction(&validator)); } + #[test] + fn test_undelegate_task_uses_request_accounts_when_rent_payer_is_present() { + let delegated_account = Pubkey::new_unique(); + let request_rent_payer = Pubkey::new_unique(); + + let ix = UndelegateTask { + delegated_account, + owner_program: Pubkey::new_unique(), + rent_reimbursement: Pubkey::new_unique(), + request_rent_payer: Some(request_rent_payer), + } + .instruction(&Pubkey::new_unique()); + + assert_eq!(ix.program_id, dlp_api::id()); + assert_eq!(ix.data, DlpDiscriminator::Undelegate.to_vec()); + assert_eq!(ix.accounts.len(), 14); + assert_eq!( + ix.accounts[12].pubkey, + undelegation_request_pda_from_delegated_account(&delegated_account) + ); + assert!(ix.accounts[12].is_writable); + assert!(!ix.accounts[12].is_signer); + assert_eq!(ix.accounts[13].pubkey, request_rent_payer); + assert!(ix.accounts[13].is_writable); + assert!(!ix.accounts[13].is_signer); + } + fn make_buffer_commit_task( commit_id: u64, allow_undelegation: bool, diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 515e925f5..2989f0f6e 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, sync::Arc}; use async_trait::async_trait; -use futures_util::future::try_join_all; +use dlp_api::state::DelegationMetadata; use magicblock_core::intent::CommittedAccount; use magicblock_program::magic_scheduled_base_intent::{ BaseAction, CommitAndUndelegate, CommitType, ScheduledIntentBundle, @@ -46,6 +46,8 @@ pub struct CommitStageTaskInfo { commit_nonces: HashMap, /// Base account state for diff calculation base_accounts: HashMap, + /// Delegation metadata needed by commit-finalize account metas. + delegation_metadata: HashMap, } /// Task builder @@ -137,6 +139,49 @@ impl TaskBuilderImpl { .await } + async fn fetch_delegation_metadata( + task_info_fetcher: &Arc, + pubkeys: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult> { + task_info_fetcher + .fetch_delegation_metadata(pubkeys, min_context_slot) + .await + } + + fn get_commit_finalize_pubkeys( + intent_bundle: &ScheduledIntentBundle, + ) -> Vec { + [ + intent_bundle + .intent_bundle + .get_commit_finalize_intent_pubkeys(), + intent_bundle + .intent_bundle + .get_commit_finalize_and_undelegate_intent_pubkeys(), + ] + .into_iter() + .flatten() + .flatten() + .collect() + } + + fn get_finalize_stage_metadata_pubkeys( + intent_bundle: &ScheduledIntentBundle, + ) -> Vec { + [ + intent_bundle.get_commit_intent_pubkeys(), + intent_bundle.get_undelegate_intent_pubkeys(), + intent_bundle + .intent_bundle + .get_commit_finalize_and_undelegate_intent_pubkeys(), + ] + .into_iter() + .flatten() + .flatten() + .collect() + } + async fn fetch_commit_stage_info( intent_bundle: &ScheduledIntentBundle, task_info_fetcher: &Arc, @@ -150,7 +195,9 @@ impl TaskBuilderImpl { .map(|account| account.remote_slot) .max() .unwrap_or(0); - let (commit_ids, base_accounts) = tokio::join!( + let commit_finalize_pubkeys = + Self::get_commit_finalize_pubkeys(intent_bundle); + let (commit_ids, base_accounts, delegation_metadata) = tokio::join!( Self::fetch_commit_nonces( task_info_fetcher, &all_committed_accounts, @@ -160,10 +207,17 @@ impl TaskBuilderImpl { task_info_fetcher, &all_committed_accounts, min_context_slot + ), + Self::fetch_delegation_metadata( + task_info_fetcher, + &commit_finalize_pubkeys, + min_context_slot ) ); let commit_nonces = commit_ids.map_err(TaskBuilderError::CommitTasksBuildError)?; + let delegation_metadata = delegation_metadata + .map_err(TaskBuilderError::CommitTasksBuildError)?; let base_accounts = base_accounts.unwrap_or_else(|err| { tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch base accounts, falling back to CommitState"); Default::default() @@ -181,6 +235,7 @@ impl TaskBuilderImpl { Ok(CommitStageTaskInfo { commit_nonces, base_accounts, + delegation_metadata, }) } @@ -189,6 +244,7 @@ impl TaskBuilderImpl { allow_undelegation: bool, account: CommittedAccount, base_account: Option, + rent_reimbursement: Pubkey, ) -> CommitFinalizeTask { let base_account = if account.account.data.len() > COMMIT_STATE_SIZE_THRESHOLD { @@ -208,6 +264,7 @@ impl TaskBuilderImpl { allow_undelegation, committed_account: account, delivery: delivery_details, + rent_reimbursement, } } } @@ -230,6 +287,7 @@ impl TasksBuilder for TaskBuilderImpl { let CommitStageTaskInfo { mut commit_nonces, mut base_accounts, + mut delegation_metadata, } = Self::fetch_commit_stage_info( intent_bundle, task_info_fetcher, @@ -252,8 +310,9 @@ impl TasksBuilder for TaskBuilderImpl { CommitFinalizeBuilder { commit_nonces: &mut commit_nonces, base_accounts: &mut base_accounts, + delegation_metadata: &mut delegation_metadata, } - .build(value), + .build(value)?, ); } if let Some(ref value) = @@ -274,8 +333,9 @@ impl TasksBuilder for TaskBuilderImpl { CommitFinalizeAndUndelegateBuilder { commit_nonces: &mut commit_nonces, base_accounts: &mut base_accounts, + delegation_metadata: &mut delegation_metadata, } - .build(&value.commit_action), + .build(&value.commit_action)?, ); } @@ -288,9 +348,14 @@ impl TasksBuilder for TaskBuilderImpl { intent_bundle: &ScheduledIntentBundle, ) -> TaskBuilderResult> { // Helper to create a finalize task - fn finalize_task(account: &CommittedAccount) -> BaseTaskImpl { + fn finalize_task( + account: &CommittedAccount, + rent_reimbursement: Pubkey, + ) -> BaseTaskImpl { FinalizeTask { delegated_account: account.pubkey, + owner_program: account.account.owner, + rent_reimbursement, } .into() } @@ -299,64 +364,75 @@ impl TasksBuilder for TaskBuilderImpl { fn undelegate_task( account: &CommittedAccount, rent_reimbursement: &Pubkey, + request_rent_payer: Option, ) -> BaseTaskImpl { UndelegateTask { delegated_account: account.pubkey, owner_program: account.account.owner, rent_reimbursement: *rent_reimbursement, + request_rent_payer, } .into() } // Helper to process commit types - fn create_finalize_tasks(commit: &CommitType) -> Vec { + fn create_finalize_tasks( + commit: &CommitType, + delegation_metadata: &HashMap, + ) -> TaskBuilderResult> { match commit { - CommitType::Standalone(accounts) => { - accounts.iter().map(finalize_task).collect() - } + CommitType::Standalone(accounts) => accounts + .iter() + .map(|account| { + Ok(finalize_task( + account, + rent_reimbursement( + delegation_metadata, + account.pubkey, + )?, + )) + }) + .collect(), CommitType::WithBaseActions { committed_accounts, base_actions, } => { let mut tasks = committed_accounts .iter() - .map(finalize_task) - .collect::>(); + .map(|account| { + Ok(finalize_task( + account, + rent_reimbursement( + delegation_metadata, + account.pubkey, + )?, + )) + }) + .collect::>>()?; tasks.extend(TaskBuilderImpl::create_action_tasks( base_actions, )); - tasks + Ok(tasks) } } } - async fn create_undelegate_tasks( + fn create_undelegate_tasks( commit_and_undelegate: &CommitAndUndelegate, - info_fetcher: &Arc, + delegation_metadata: &HashMap, ) -> TaskBuilderResult> { - // Get rent reimbursments for undelegated accounts let accounts = commit_and_undelegate.get_committed_accounts(); - let mut min_context_slot = 0; - let pubkeys = accounts - .iter() - .map(|account| { - min_context_slot = - std::cmp::max(min_context_slot, account.remote_slot); - account.pubkey - }) - .collect::>(); - let rent_reimbursements = info_fetcher - .fetch_rent_reimbursements(&pubkeys, min_context_slot) - .await - .map_err(TaskBuilderError::FinalizedTasksBuildError)?; let mut tasks = accounts .iter() - .zip(rent_reimbursements) - .map(|(account, rent_reimbursement)| { - undelegate_task(account, &rent_reimbursement) + .map(|account| { + let rent_reimbursement = rent_reimbursement( + delegation_metadata, + account.pubkey, + )?; + Ok(undelegate_task(account, &rent_reimbursement, None)) }) - .collect::>(); + .collect::>>()?; if let UndelegateType::WithBaseActions(actions) = &commit_and_undelegate.undelegate_action @@ -367,27 +443,42 @@ impl TasksBuilder for TaskBuilderImpl { } let mut tasks = Vec::new(); - let mut futures = Vec::with_capacity(2); + let finalize_metadata_pubkeys = + Self::get_finalize_stage_metadata_pubkeys(intent_bundle); + let min_context_slot = intent_bundle + .get_all_committed_accounts() + .iter() + .map(|account| account.remote_slot) + .max() + .unwrap_or(0); + let delegation_metadata = Self::fetch_delegation_metadata( + info_fetcher, + &finalize_metadata_pubkeys, + min_context_slot, + ) + .await + .map_err(TaskBuilderError::FinalizedTasksBuildError)?; if let Some(ref value) = intent_bundle.intent_bundle.commit { - tasks.extend(create_finalize_tasks(value)); + tasks.extend(create_finalize_tasks(value, &delegation_metadata)?); } if let Some(ref value) = intent_bundle.intent_bundle.commit_and_undelegate { - tasks.extend(create_finalize_tasks(&value.commit_action)); - futures.push(create_undelegate_tasks(value, info_fetcher)); + tasks.extend(create_finalize_tasks( + &value.commit_action, + &delegation_metadata, + )?); + tasks.extend(create_undelegate_tasks(value, &delegation_metadata)?); } if let Some(ref value) = intent_bundle.intent_bundle.commit_finalize_and_undelegate { - futures.push(create_undelegate_tasks(value, info_fetcher)); + tasks.extend(create_undelegate_tasks(value, &delegation_metadata)?); } - tasks.extend(try_join_all(futures).await?.into_iter().flatten()); - Ok(tasks) } } @@ -447,66 +538,82 @@ impl<'a> CommitAndUndelegateBuilder<'a> { struct CommitFinalizeBuilder<'a> { commit_nonces: &'a mut HashMap, base_accounts: &'a mut HashMap, + delegation_metadata: &'a mut HashMap, } impl<'a> CommitFinalizeBuilder<'a> { - fn build(&mut self, commit_type: &CommitType) -> Vec { + fn build( + &mut self, + commit_type: &CommitType, + ) -> TaskBuilderResult> { let mut tasks: Vec = commit_type .get_committed_accounts() .iter() - .map(|account| { + .map(|account| -> TaskBuilderResult { let nonce = take_commit_nonce(self.commit_nonces, account.pubkey); let base = self.base_accounts.remove(&account.pubkey); - TaskBuilderImpl::create_commit_finalize_task( + Ok(TaskBuilderImpl::create_commit_finalize_task( nonce, false, account.clone(), base, + rent_reimbursement( + self.delegation_metadata, + account.pubkey, + )?, ) - .into() + .into()) }) - .collect(); + .collect::>>()?; if let CommitType::WithBaseActions { ref base_actions, .. } = commit_type { tasks.extend(TaskBuilderImpl::create_action_tasks(base_actions)); } - tasks + Ok(tasks) } } struct CommitFinalizeAndUndelegateBuilder<'a> { commit_nonces: &'a mut HashMap, base_accounts: &'a mut HashMap, + delegation_metadata: &'a mut HashMap, } impl<'a> CommitFinalizeAndUndelegateBuilder<'a> { - fn build(&mut self, commit_type: &CommitType) -> Vec { + fn build( + &mut self, + commit_type: &CommitType, + ) -> TaskBuilderResult> { let mut tasks: Vec = commit_type .get_committed_accounts() .iter() - .map(|account| { + .map(|account| -> TaskBuilderResult { let nonce = take_commit_nonce(self.commit_nonces, account.pubkey); let base = self.base_accounts.remove(&account.pubkey); - TaskBuilderImpl::create_commit_finalize_task( + Ok(TaskBuilderImpl::create_commit_finalize_task( nonce, true, account.clone(), base, + rent_reimbursement( + self.delegation_metadata, + account.pubkey, + )?, ) - .into() + .into()) }) - .collect(); + .collect::>>()?; if let CommitType::WithBaseActions { ref base_actions, .. } = commit_type { tasks.extend(TaskBuilderImpl::create_action_tasks(base_actions)); } - tasks + Ok(tasks) } } @@ -523,12 +630,24 @@ fn take_commit_nonce( }) } +fn rent_reimbursement( + delegation_metadata: &HashMap, + pubkey: Pubkey, +) -> TaskBuilderResult { + delegation_metadata + .get(&pubkey) + .map(|metadata| metadata.rent_payer) + .ok_or(TaskBuilderError::MissingDelegationMetadata(pubkey)) +} + #[derive(thiserror::Error, Debug)] pub enum TaskBuilderError { #[error("CommitIdFetchError: {0}")] CommitTasksBuildError(#[source] TaskInfoFetcherError), #[error("FinalizedTasksBuildError: {0}")] FinalizedTasksBuildError(#[source] TaskInfoFetcherError), + #[error("Missing delegation metadata for {0}")] + MissingDelegationMetadata(Pubkey), } impl TaskBuilderError { @@ -536,6 +655,7 @@ impl TaskBuilderError { match self { Self::CommitTasksBuildError(err) => err.signature(), Self::FinalizedTasksBuildError(err) => err.signature(), + Self::MissingDelegationMetadata(_) => None, } } } diff --git a/magicblock-committor-service/src/tasks/task_strategist.rs b/magicblock-committor-service/src/tasks/task_strategist.rs index b55cbd7dc..8203699ea 100644 --- a/magicblock-committor-service/src/tasks/task_strategist.rs +++ b/magicblock-committor-service/src/tasks/task_strategist.rs @@ -472,6 +472,9 @@ pub type TaskStrategistResult = Result; mod tests { use std::{collections::HashMap, sync::Arc}; + use dlp_api::state::{ + DelegationMetadata, UndelegationRequest, UndelegationRequester, + }; use magicblock_core::intent::CommittedAccount; use magicblock_program::magic_scheduled_base_intent::{ BaseAction, ProgramArgs, @@ -497,6 +500,7 @@ mod tests { test_utils, }; + #[derive(Default)] struct MockInfoFetcher; #[async_trait::async_trait] @@ -525,6 +529,37 @@ mod tests { Ok(pubkeys.iter().map(|_| Pubkey::new_unique()).collect()) } + async fn fetch_delegation_metadata( + &self, + pubkeys: &[Pubkey], + _: u64, + ) -> TaskInfoFetcherResult> + { + Ok(pubkeys + .iter() + .map(|pubkey| { + ( + *pubkey, + DelegationMetadata { + last_commit_id: 0, + undelegation_requester: UndelegationRequester::None, + seeds: vec![], + rent_payer: *pubkey, + }, + ) + }) + .collect()) + } + + async fn fetch_undelegation_requests( + &self, + _delegated_accounts: &[Pubkey], + _: u64, + ) -> TaskInfoFetcherResult> + { + Ok(HashMap::new()) + } + async fn get_base_accounts( &self, _pubkeys: &[Pubkey], @@ -598,6 +633,8 @@ mod tests { fn create_test_finalize_task() -> FinalizeTask { FinalizeTask { delegated_account: Pubkey::new_unique(), + owner_program: Pubkey::new_unique(), + rent_reimbursement: Pubkey::new_unique(), } } @@ -607,6 +644,7 @@ mod tests { delegated_account: Pubkey::new_unique(), owner_program: Pubkey::default(), rent_reimbursement: Pubkey::new_unique(), + request_rent_payer: None, } } @@ -862,6 +900,30 @@ mod tests { assert!(!strategy.lookup_tables_keys.is_empty()); } + #[tokio::test] + async fn test_finalize_tasks_uses_metadata_rent_payer_for_undelegate() { + let delegated_account = Pubkey::new_unique(); + let intent = create_test_intent(0, &[delegated_account], true); + let info_fetcher = Arc::new(MockInfoFetcher); + + let tasks = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) + .await + .unwrap(); + + assert_eq!(tasks.len(), 2); + let BaseTaskImpl::Finalize(task) = &tasks[0] else { + panic!("expected finalize task"); + }; + assert_eq!(task.delegated_account, delegated_account); + assert_eq!(task.rent_reimbursement, delegated_account); + let BaseTaskImpl::Undelegate(task) = &tasks[1] else { + panic!("expected undelegate task"); + }; + assert_eq!(task.delegated_account, delegated_account); + assert_eq!(task.rent_reimbursement, delegated_account); + assert_eq!(task.request_rent_payer, None); + } + #[tokio::test] async fn test_build_single_stage_mode() { let pubkey = [Pubkey::new_unique()]; diff --git a/magicblock-committor-service/src/transactions.rs b/magicblock-committor-service/src/transactions.rs index 2c25c7d42..40e61998c 100644 --- a/magicblock-committor-service/src/transactions.rs +++ b/magicblock-committor-service/src/transactions.rs @@ -1,12 +1,647 @@ use solana_packet::PACKET_DATA_SIZE; use solana_rpc_client::rpc_client::SerializableTransaction; +use static_assertions::const_assert; /// Maximum serialized transaction size that can be sent over the wire. pub(crate) const MAX_TRANSACTION_WIRE_SIZE: usize = PACKET_DATA_SIZE; +/// How many process and commit buffer instructions fit into a single transaction +#[allow(unused)] // serves as documentation as well +pub const MAX_PROCESS_PER_TX: u8 = 3; + +/// How many process and commit buffer instructions fit into a single transaction +/// when using address lookup tables but not including the buffer account in the +/// lookup table +#[allow(unused)] // serves as documentation as well +pub const MAX_PROCESS_PER_TX_USING_LOOKUP: u8 = 12; + +/// How many close buffer instructions fit into a single transaction +#[allow(unused)] // serves as documentation as well +pub const MAX_CLOSE_PER_TX: u8 = 8; + +/// How many close buffer instructions fit into a single transaction +/// when using address lookup tables but not including the buffer account +/// nor chunk account in the lookup table +#[allow(unused)] // serves as documentation as well +pub const MAX_CLOSE_PER_TX_USING_LOOKUP: u8 = 8; + +/// How many process and commit buffer instructions combined with close buffer instructions +/// fit into a single transaction +#[allow(unused)] // serves as documentation as well +pub const MAX_PROCESS_AND_CLOSE_PER_TX: u8 = 2; + +/// How many process and commit buffer instructions combined with +/// close buffer instructions fit into a single transaction when +/// using lookup tables but not including the buffer account +#[allow(unused)] // serves as documentation as well +pub const MAX_PROCESS_AND_CLOSE_PER_TX_USING_LOOKUP: u8 = 4; + +/// How many finalize instructions fit into a single transaction +#[allow(unused)] // serves as documentation as well +pub const MAX_FINALIZE_PER_TX: u8 = 2; + +/// How many finalize instructions fit into a single transaction +/// when using address lookup tables +#[allow(unused)] // serves as documentation as well +pub const MAX_FINALIZE_PER_TX_USING_LOOKUP: u8 = 40; + +/// How many undelegate instructions fit into a single transaction +/// NOTE: that we assume the rent reimbursement account to be the delegated account +#[allow(unused)] // serves as documentation as well +pub const MAX_UNDELEGATE_PER_TX: u8 = 3; + +/// How many undelegate instructions fit into a single transaction +/// when using address lookup tables +/// NOTE: that we assume the rent reimbursement account to be the delegated account +#[allow(unused)] // serves as documentation as well +pub const MAX_UNDELEGATE_PER_TX_USING_LOOKUP: u8 = 15; + +// Allows us to run undelegate instructions without rechunking them since we know +// that we didn't process more than we also can undelegate +const_assert!(MAX_PROCESS_PER_TX <= MAX_UNDELEGATE_PER_TX,); + +// Allows us to run undelegate instructions using lookup tables without rechunking +// them since we know that we didn't process more than we also can undelegate +const_assert!( + MAX_PROCESS_PER_TX_USING_LOOKUP <= MAX_UNDELEGATE_PER_TX_USING_LOOKUP +); + pub fn serialized_transaction_size( transaction: &impl SerializableTransaction, ) -> usize { // SAFETY: runs on transactions we already serialize before sending. usize::try_from(bincode::serialized_size(transaction).unwrap()).unwrap() } + +#[cfg(test)] +mod test { + use std::collections::HashSet; + + use dlp_api::{ + args::{CommitStateArgs, CommitStateFromBufferArgs}, + pda, + }; + use magicblock_committor_program::{ + id as committor_program_id, + instruction_builder::close_buffer::{ + create_close_ix, CreateCloseIxArgs, + }, + }; + use solana_address_lookup_table_interface::state::LOOKUP_TABLE_MAX_ADDRESSES; + use solana_compute_budget_interface::ComputeBudgetInstruction; + use solana_hash::Hash; + use solana_instruction::Instruction; + use solana_keypair::Keypair; + use solana_message::{ + v0::Message, AddressLookupTableAccount, VersionedMessage, + }; + use solana_pubkey::Pubkey; + use solana_sdk_ids::system_program; + use solana_signer::Signer; + use solana_transaction::versioned::VersionedTransaction; + use tracing::info; + + use super::*; + use crate::test_utils; + + type TransactionSizeError = Box; + type TransactionSizeResult = Result; + + fn get_lookup_tables( + ixs: &[Instruction], + ) -> Vec { + let pubkeys = ixs + .iter() + .flat_map(|ix| ix.accounts.iter().map(|acc| acc.pubkey)) + .collect::>(); + + let lookup_table = AddressLookupTableAccount { + key: Pubkey::default(), + addresses: pubkeys.into_iter().collect(), + }; + vec![lookup_table] + } + + // ----------------- + // Helpers + // ----------------- + #[allow(clippy::enum_variant_names)] + enum TransactionOpts { + NoLookupTable, + UseLookupTable, + } + fn transaction_wire_size( + auth: &Keypair, + ixs: &[Instruction], + opts: &TransactionOpts, + ) -> TransactionSizeResult { + use TransactionOpts::*; + let lookup_tables = match opts { + NoLookupTable => vec![], + UseLookupTable => get_lookup_tables(ixs), + }; + + let versioned_msg = Message::try_compile( + &auth.pubkey(), + ixs, + &lookup_tables, + Hash::default(), + ) + .map_err(|err| -> TransactionSizeError { Box::new(err) })?; + let versioned_tx = VersionedTransaction::try_new( + VersionedMessage::V0(versioned_msg), + &[&auth], + ) + .map_err(|err| -> TransactionSizeError { Box::new(err) })?; + + Ok(serialized_transaction_size(&versioned_tx)) + } + + fn compute_budget_ixs() -> Vec { + vec![ + ComputeBudgetInstruction::set_compute_unit_limit(125_000), + ComputeBudgetInstruction::set_compute_unit_price(1_000_000), + ] + } + + // ----------------- + // Process Commitables and Close Buffers + // ----------------- + pub(crate) fn process_commits_ix( + validator_auth: Pubkey, + pubkey: &Pubkey, + delegated_account_owner: &Pubkey, + buffer_pda: &Pubkey, + commit_args: CommitStateFromBufferArgs, + ) -> Instruction { + dlp_api::instruction_builder::commit_state_from_buffer( + validator_auth, + *pubkey, + *delegated_account_owner, + *buffer_pda, + commit_args, + ) + } + + pub(crate) fn close_buffers_ix( + validator_auth: Pubkey, + pubkey: &Pubkey, + commit_id: u64, + ) -> Instruction { + create_close_ix(CreateCloseIxArgs { + authority: validator_auth, + pubkey: *pubkey, + commit_id, + }) + } + + pub(crate) fn process_and_close_ixs( + validator_auth: Pubkey, + pubkey: &Pubkey, + delegated_account_owner: &Pubkey, + buffer_pda: &Pubkey, + commit_id: u64, + commit_args: CommitStateFromBufferArgs, + ) -> Vec { + let process_ix = process_commits_ix( + validator_auth, + pubkey, + delegated_account_owner, + buffer_pda, + commit_args, + ); + let close_ix = close_buffers_ix(validator_auth, pubkey, commit_id); + + vec![process_ix, close_ix] + } + + // ----------------- + // Finalize + // ----------------- + pub(crate) fn finalize_ix( + validator_auth: Pubkey, + pubkey: &Pubkey, + ) -> Instruction { + dlp_api::instruction_builder::finalize( + validator_auth, + *pubkey, + Pubkey::new_unique(), + Pubkey::new_unique(), + ) + } + + // These tests statically determine the optimal ix count to fit into a single + // transaction and assert that the const we export in prod match those numbers. + // Thus when an instruction changes and one of those numbers with it a failing + // test alerts us. + // This is less overhead than running those static functions each time at + // startup. + + #[test] + fn test_max_process_per_tx() { + test_utils::init_test_logger(); + assert_eq!(super::MAX_PROCESS_PER_TX, max_process_per_tx()); + assert_eq!( + super::MAX_PROCESS_PER_TX_USING_LOOKUP, + max_process_per_tx_using_lookup() + ); + } + + #[test] + fn test_max_close_per_tx() { + test_utils::init_test_logger(); + assert_eq!(super::MAX_CLOSE_PER_TX, max_close_per_tx()); + assert_eq!( + super::MAX_CLOSE_PER_TX_USING_LOOKUP, + max_close_per_tx_using_lookup() + ); + } + + #[test] + fn test_max_process_and_closes_per_tx() { + test_utils::init_test_logger(); + assert_eq!( + super::MAX_PROCESS_AND_CLOSE_PER_TX, + max_process_and_close_per_tx() + ); + assert_eq!( + super::MAX_PROCESS_AND_CLOSE_PER_TX_USING_LOOKUP, + max_process_and_close_per_tx_using_lookup() + ); + } + + #[test] + fn test_max_finalize_per_tx() { + test_utils::init_test_logger(); + assert_eq!(super::MAX_FINALIZE_PER_TX, max_finalize_per_tx()); + assert_eq!( + super::MAX_FINALIZE_PER_TX_USING_LOOKUP, + max_finalize_per_tx_using_lookup() + ); + } + + #[test] + fn test_max_undelegate_per_tx() { + test_utils::init_test_logger(); + assert_eq!(super::MAX_UNDELEGATE_PER_TX, max_undelegate_per_tx()); + assert_eq!( + super::MAX_UNDELEGATE_PER_TX_USING_LOOKUP, + max_undelegate_per_tx_using_lookup() + ); + } + + // ----------------- + // Process Commitables using Args + // ----------------- + #[test] + fn test_log_commit_args_ix_sizes() { + test_utils::init_test_logger(); + // This test is used to investigate the size of the transaction related to + // the amount of committed accounts and their data size. + fn run(auth: &Keypair, ixs: usize) { + let mut tx_lines = vec![]; + use TransactionOpts::*; + for tx_opts in [NoLookupTable, UseLookupTable] { + let mut tx_sizes = vec![]; + for size in [0, 10, 20, 50, 100, 200, 500, 1024] { + let ixs = (0..ixs) + .map(|_| make_ix(auth, size)) + .collect::>(); + + let tx_size = + transaction_wire_size(auth, &ixs, &tx_opts).unwrap(); + tx_sizes.push((size, tx_size)); + } + tx_lines.push(tx_sizes); + } + let sizes = tx_lines + .into_iter() + .map(|line| { + line.into_iter() + .map(|(size, len)| format!("{:4}:{:5}", size, len)) + .collect::>() + .join("|") + }) + .collect::>() + .join("\n"); + info!(instruction_count = ixs, sizes = %sizes, "Transaction size report"); + } + fn make_ix(auth: &Keypair, data_size: usize) -> Instruction { + let data = vec![1; data_size]; + let args = CommitStateArgs { + data, + ..CommitStateArgs::default() + }; + dlp_api::instruction_builder::commit_state( + auth.pubkey(), + Pubkey::new_unique(), + Pubkey::new_unique(), + args, + ) + } + + let auth = &Keypair::new(); + run(auth, 0); + run(auth, 1); + run(auth, 2); + run(auth, 5); + run(auth, 8); + run(auth, 10); + run(auth, 15); + run(auth, 20); + // This logs raw wire sizes. The sendability limit is + // MAX_TRANSACTION_WIRE_SIZE. + } + + // ----------------- + // Process Commitables and Close Buffers + // ----------------- + fn max_process_per_tx() -> u8 { + max_chunks_per_transaction("Max process per tx", |auth_pubkey| { + let pubkey = Pubkey::new_unique(); + let delegated_account_owner = Pubkey::new_unique(); + let buffer_pda = Pubkey::new_unique(); + let commit_args = CommitStateFromBufferArgs::default(); + vec![process_commits_ix( + auth_pubkey, + &pubkey, + &delegated_account_owner, + &buffer_pda, + commit_args, + )] + }) + } + + fn max_process_per_tx_using_lookup() -> u8 { + max_chunks_per_transaction_using_lookup_table( + "Max process per tx using lookup", + |auth_pubkey, committee, delegated_account_owner| { + let buffer_pda = Pubkey::new_unique(); + let commit_args = CommitStateFromBufferArgs::default(); + vec![process_commits_ix( + auth_pubkey, + &committee, + &delegated_account_owner, + &buffer_pda, + commit_args, + )] + }, + None, + ) + } + + fn max_close_per_tx() -> u8 { + let commit_id = 0; + max_chunks_per_transaction("Max close per tx", |auth_pubkey| { + let pubkey = Pubkey::new_unique(); + vec![close_buffers_ix(auth_pubkey, &pubkey, commit_id)] + }) + } + + fn max_close_per_tx_using_lookup() -> u8 { + let commit_id = 0; + max_chunks_per_transaction_using_lookup_table( + "Max close per tx using lookup", + |auth_pubkey, committee, _| { + vec![close_buffers_ix(auth_pubkey, &committee, commit_id)] + }, + None, + ) + } + + fn max_process_and_close_per_tx() -> u8 { + let commit_id = 0; + max_chunks_per_transaction( + "Max process and close per tx", + |auth_pubkey| { + let pubkey = Pubkey::new_unique(); + let delegated_account_owner = Pubkey::new_unique(); + let buffer_pda = Pubkey::new_unique(); + let commit_args = CommitStateFromBufferArgs::default(); + process_and_close_ixs( + auth_pubkey, + &pubkey, + &delegated_account_owner, + &buffer_pda, + commit_id, + commit_args, + ) + }, + ) + } + + fn max_process_and_close_per_tx_using_lookup() -> u8 { + let commit_id = 0; + max_chunks_per_transaction_using_lookup_table( + "Max process and close per tx using lookup", + |auth_pubkey, committee, delegated_account_owner| { + let commit_args = CommitStateFromBufferArgs::default(); + let buffer_pda = Pubkey::new_unique(); + process_and_close_ixs( + auth_pubkey, + &committee, + &delegated_account_owner, + &buffer_pda, + commit_id, + commit_args, + ) + }, + None, + ) + } + + // ----------------- + // Finalize + // ----------------- + fn max_finalize_per_tx() -> u8 { + max_chunks_per_transaction("Max finalize per tx", |auth_pubkey| { + let pubkey = Pubkey::new_unique(); + vec![finalize_ix(auth_pubkey, &pubkey)] + }) + } + + fn max_finalize_per_tx_using_lookup() -> u8 { + max_chunks_per_transaction_using_lookup_table( + "Max finalize per tx using lookup", + |auth_pubkey, committee, _| { + vec![finalize_ix(auth_pubkey, &committee)] + }, + Some(40), + ) + } + + // ----------------- + // Undelegate + // ----------------- + fn max_undelegate_per_tx() -> u8 { + max_chunks_per_transaction("Max undelegate per tx", |auth_pubkey| { + let pubkey = Pubkey::new_unique(); + let owner_program = Pubkey::new_unique(); + vec![dlp_api::instruction_builder::undelegate( + auth_pubkey, + pubkey, + owner_program, + auth_pubkey, + )] + }) + } + + fn max_undelegate_per_tx_using_lookup() -> u8 { + max_chunks_per_transaction_using_lookup_table( + "Max undelegate per tx using lookup", + |auth_pubkey, committee, owner_program| { + vec![dlp_api::instruction_builder::undelegate( + auth_pubkey, + committee, + owner_program, + auth_pubkey, + )] + }, + None, + ) + } + + // ----------------- + // Max Chunks Per Transaction + // ----------------- + + fn max_chunks_per_transaction Vec>( + label: &str, + create_ixs: F, + ) -> u8 { + info!(test_label = label, "Starting transaction chunking test"); + + let auth = Keypair::new(); + let auth_pubkey = auth.pubkey(); + // NOTE: the size of the budget instructions is always the same, no matter + // which budget we provide + let mut ixs = compute_budget_ixs(); + let mut chunks = 0_u8; + loop { + ixs.extend(create_ixs(auth_pubkey)); + chunks += 1; + + // SAFETY: runs statically + let versioned_msg = + Message::try_compile(&auth_pubkey, &ixs, &[], Hash::default()) + .unwrap(); + // SAFETY: runs statically + let versioned_tx = VersionedTransaction::try_new( + VersionedMessage::V0(versioned_msg), + &[&auth], + ) + .unwrap(); + let tx_size = serialized_transaction_size(&versioned_tx); + info!( + chunks = chunks, + size_bytes = tx_size, + "Transaction size measured" + ); + if tx_size > MAX_TRANSACTION_WIRE_SIZE { + return chunks - 1; + } + } + } + + fn extend_lookup_table( + lookup_table: &mut AddressLookupTableAccount, + auth_pubkey: Pubkey, + committee: Pubkey, + owner: Option<&Pubkey>, + ) { + let mut keys = HashSet::from([ + committee, + pda::delegation_record_pda_from_delegated_account(&committee), + pda::delegation_metadata_pda_from_delegated_account(&committee), + pda::commit_state_pda_from_delegated_account(&committee), + pda::commit_record_pda_from_delegated_account(&committee), + pda::undelegate_buffer_pda_from_delegated_account(&committee), + auth_pubkey, + system_program::id(), + dlp_api::id(), + pda::fees_vault_pda(), + pda::validator_fees_vault_pda_from_validator(&auth_pubkey), + committor_program_id(), + ]); + if let Some(owner) = owner { + keys.insert(pda::program_config_from_program_id(owner)); + } + keys.extend(lookup_table.addresses.iter().cloned()); + lookup_table.addresses = keys.into_iter().collect(); + assert!( + lookup_table.addresses.len() <= LOOKUP_TABLE_MAX_ADDRESSES, + "Lookup table has too many ({}) addresses", + lookup_table.addresses.len() + ); + } + + fn max_chunks_per_transaction_using_lookup_table< + FI: Fn(Pubkey, Pubkey, Pubkey) -> Vec, + >( + label: &str, + create_ixs: FI, + start_at: Option, + ) -> u8 { + info!(test_label = label, start_at = ?start_at, "Starting lookup table transaction test"); + let auth = Keypair::new(); + let auth_pubkey = auth.pubkey(); + let mut ixs = compute_budget_ixs(); + let mut chunks = start_at.unwrap_or_default(); + let mut lookup_table = AddressLookupTableAccount { + key: Pubkey::default(), + addresses: vec![], + }; + // If we start at specific chunk size let's prep the ixs and assume + // we are using the same addresses to avoid blowing out the lookup table + if chunks > 0 { + let committee = Pubkey::new_unique(); + let owner_program = Pubkey::new_unique(); + extend_lookup_table( + &mut lookup_table, + auth_pubkey, + committee, + Some(&owner_program), + ); + for _ in 0..chunks { + ixs.extend(create_ixs(auth_pubkey, committee, owner_program)); + } + } + loop { + let committee = Pubkey::new_unique(); + let owner_program = Pubkey::new_unique(); + ixs.extend(create_ixs(auth_pubkey, committee, owner_program)); + + chunks += 1; + extend_lookup_table( + &mut lookup_table, + auth_pubkey, + committee, + Some(&owner_program), + ); + + // SAFETY: runs statically + let versioned_msg = Message::try_compile( + &auth_pubkey, + &ixs, + &[lookup_table.clone()], + Hash::default(), + ) + .unwrap(); + // SAFETY: runs statically + let versioned_tx = VersionedTransaction::try_new( + VersionedMessage::V0(versioned_msg), + &[&auth], + ) + .unwrap(); + let tx_size = serialized_transaction_size(&versioned_tx); + info!( + chunks = chunks, + size_bytes = tx_size, + "Transaction size measured with lookup table" + ); + if tx_size > MAX_TRANSACTION_WIRE_SIZE { + return chunks - 1; + } + } + } +} diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 04305a12b..6dee47c77 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -1955,7 +1955,7 @@ dependencies = [ "ephemeral-rollups-sdk-attribute-ephemeral-accounts", "five8 0.2.1", "getrandom 0.2.17", - "magicblock-delegation-program-api 3.0.0", + "magicblock-delegation-program-api 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "magicblock-magic-program-api 0.10.1", "solana-account 3.4.0", "solana-account-info 2.3.0", @@ -2041,7 +2041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -2102,7 +2102,7 @@ checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -3050,7 +3050,7 @@ dependencies = [ "borsh 1.7.0", "color-backtrace", "magicblock-config", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "rand 0.8.6", "rayon", "serde", @@ -3527,11 +3527,24 @@ name = "magicblock-accounts" version = "0.13.3" dependencies = [ "async-trait", + "magicblock-account-cloner", + "magicblock-chainlink", "magicblock-committor-service", + "magicblock-core", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-metrics", + "magicblock-program", + "solana-hash 4.2.0", + "solana-instruction 3.3.0", + "solana-keypair", "solana-pubkey 4.1.0", + "solana-signer", + "solana-transaction", "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", + "tokio-util", + "tracing", "url", ] @@ -3634,7 +3647,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-ledger", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", @@ -3696,7 +3709,7 @@ dependencies = [ "magicblock-aml", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", "parking_lot", @@ -3765,7 +3778,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-committor-program", "magicblock-core", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3789,6 +3802,7 @@ dependencies = [ "solana-transaction", "solana-transaction-error 3.1.0", "solana-transaction-status-client-types", + "static_assertions", "thiserror 2.0.18", "tokio", "tokio-util", @@ -3844,10 +3858,12 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" -version = "0.3.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=25386a7c1d406d06b8d07a4d5b0fd37d5e74213b#25386a7c1d406d06b8d07a4d5b0fd37d5e74213b" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "288904a9950bd20f27f0ef934f320ab1410bd35a6d5c9cf138eca276442b6b2e" dependencies = [ "bincode", + "borsh 0.10.4", "borsh 1.7.0", "bytemuck", "const-crypto", @@ -3863,6 +3879,7 @@ dependencies = [ "solana-instruction 3.3.0", "solana-loader-v3-interface 6.1.1", "solana-program 3.0.0", + "solana-pubkey 2.4.0", "solana-sdk", "solana-sdk-ids 3.1.0", "solana-sha256-hasher 3.1.0", @@ -3875,8 +3892,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "288904a9950bd20f27f0ef934f320ab1410bd35a6d5c9cf138eca276442b6b2e" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7#72af1c7542ee00a383f0945184fee4a0d9cec6e0" dependencies = [ "bincode", "borsh 0.10.4", @@ -4035,7 +4051,7 @@ dependencies = [ "bincode", "lazy_static", "magicblock-core", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-magic-program-api 0.13.3", "num-derive", "num-traits", @@ -4193,7 +4209,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.13.3" dependencies = [ - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -4451,7 +4467,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -5042,7 +5058,7 @@ version = "0.0.0" dependencies = [ "borsh 1.7.0", "ephemeral-rollups-sdk", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-magic-program-api 0.13.3", "rkyv 0.7.46", "solana-program 3.0.0", @@ -5801,7 +5817,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -5930,7 +5946,7 @@ dependencies = [ "anyhow", "borsh 1.7.0", "integration-test-tools", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "program-schedulecommit", "solana-commitment-config", "solana-compute-budget-interface", @@ -5952,7 +5968,7 @@ dependencies = [ "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -5980,7 +5996,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-magic-program-api 0.13.3", "magicblock-program", "program-schedulecommit", @@ -6001,7 +6017,7 @@ name = "schedulecommit-test-security" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-magic-program-api 0.13.3", "program-schedulecommit", "program-schedulecommit-security", @@ -9759,7 +9775,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -9780,7 +9796,7 @@ dependencies = [ "integration-test-tools", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9807,7 +9823,7 @@ dependencies = [ "magicblock-aml", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "program-flexi-counter", "program-mini", "solana-account 3.4.0", @@ -9833,7 +9849,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9903,7 +9919,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "program-flexi-counter", "solana-commitment-config", "solana-rpc-client", @@ -9926,7 +9942,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-program", "magicblock-validator-admin", "solana-commitment-config", @@ -9972,7 +9988,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "log", - "magicblock-delegation-program-api 0.3.0", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", "magicblock-magic-program-api 0.13.3", "program-flexi-counter", "solana-rpc-client-api", @@ -10944,7 +10960,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -11099,15 +11115,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.60.2" diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 05da5a293..7173bafba 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -63,7 +63,7 @@ magicblock-committor-program = { path = "../magicblock-committor-program", featu magicblock-committor-service = { path = "../magicblock-committor-service" } magicblock-config = { path = "../magicblock-config" } magicblock-core = { path = "../magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "25386a7c1d406d06b8d07a4d5b0fd37d5e74213b", default-features = false } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "72af1c7", default-features = false } magicblock-magic-program-api = { path = "../magicblock-magic-program-api" } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } diff --git a/test-integration/programs/schedulecommit/src/api.rs b/test-integration/programs/schedulecommit/src/api.rs index 0dfe0931b..ed50202f6 100644 --- a/test-integration/programs/schedulecommit/src/api.rs +++ b/test-integration/programs/schedulecommit/src/api.rs @@ -1,4 +1,11 @@ -use dlp_api::args::{DelegateArgs, DelegateEphemeralBalanceArgs}; +use dlp_api::{ + args::{DelegateArgs, DelegateEphemeralBalanceArgs}, + pda::{ + delegation_metadata_pda_from_delegated_account, + delegation_record_pda_from_delegated_account, + undelegation_request_pda_from_delegated_account, + }, +}; use ephemeral_rollups_sdk::delegate_args::{ DelegateAccountMetas, DelegateAccounts, }; @@ -164,6 +171,37 @@ pub fn delegate_account_cpi_instruction( ) } +pub fn request_undelegation_cpi_instruction( + payer: Pubkey, + player: Pubkey, + committee: Pubkey, +) -> Instruction { + let program_id = crate::id(); + let request_pda = + undelegation_request_pda_from_delegated_account(&committee); + let delegation_record = + delegation_record_pda_from_delegated_account(&committee); + let delegation_metadata = + delegation_metadata_pda_from_delegated_account(&committee); + + let account_metas = vec![ + AccountMeta::new(payer, true), + AccountMeta::new_readonly(committee, false), + AccountMeta::new_readonly(program_id, false), + AccountMeta::new(request_pda, false), + AccountMeta::new_readonly(delegation_record, false), + AccountMeta::new(delegation_metadata, false), + AccountMeta::new_readonly(system_program::id(), false), + AccountMeta::new_readonly(dlp_api::id(), false), + ]; + + Instruction::new_with_borsh( + program_id, + &ScheduleCommitInstruction::RequestUndelegationCpi(player), + account_metas, + ) +} + /// Creates an instruction that calls the _legit_ program which owns /// the PDAs to be commited via CPI into the MagicBlock program. /// It provides the following account metas to the invoked program: diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index 414219861..a9361dcae 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -198,6 +198,20 @@ pub enum ScheduleCommitInstruction { ScheduleCommitWithVaultAndOrderBookCpi(ScheduleCommitWithOrderBookArgs), ScheduleCommitForOrderBook(ScheduleCommitType), + + /// CPI into the delegation program to request undelegation for a + /// schedulecommit-owned PDA. + /// + /// # Account references + /// - **0.** `[WRITE, SIGNER]` Payer funding the request PDA + /// - **1.** `[]` Delegated schedulecommit PDA + /// - **2.** `[]` Schedulecommit owner program + /// - **3.** `[WRITE]` Undelegation request PDA + /// - **4.** `[]` Delegation record PDA + /// - **5.** `[]` Delegation metadata PDA + /// - **6.** `[]` System program + /// - **7.** `[]` Delegation program + RequestUndelegationCpi(Pubkey), } /// @@ -348,6 +362,9 @@ pub fn process_instruction<'a>( ScheduleCommitForOrderBook(commit_type) => { process_schedulecommit_for_orderbook(accounts, commit_type) } + RequestUndelegationCpi(player) => { + process_request_undelegation_cpi(program_id, accounts, player) + } ScheduleCommitWithVaultAndOrderBookCpi(args) => { process_schedulecommit_with_vault_and_order_book_cpi( accounts, &args, @@ -646,6 +663,66 @@ pub fn process_delegate_cpi( Ok(()) } +fn process_request_undelegation_cpi( + program_id: &Pubkey, + accounts: &[AccountInfo], + player: Pubkey, +) -> Result<(), ProgramError> { + msg!("Processing request_undelegation_cpi instruction"); + + let [payer, delegated_account, owner_program, undelegation_request, delegation_record, delegation_metadata, system_program, dlp_program] = + accounts + else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + + assert_is_signer(payer, "payer")?; + assert_keys_equal(owner_program.key, program_id, || { + format!( + "Owner program '{}' does not match schedulecommit program '{}'", + owner_program.key, program_id + ) + })?; + assert_keys_equal(dlp_program.key, &dlp_api::id(), || { + format!( + "DLP program '{}' does not match expected program '{}'", + dlp_program.key, + dlp_api::id() + ) + })?; + + let (expected_pda, bump) = pda_and_bump(&player); + assert_keys_equal(delegated_account.key, &expected_pda, || { + format!( + "Delegated account '{}' does not match PDA '{}' for player '{}'", + delegated_account.key, expected_pda, player + ) + })?; + + let ix = dlp_api::instruction_builder::request_undelegation( + *payer.key, + *delegated_account.key, + *owner_program.key, + ); + let bump_arr = [bump]; + let signer_seeds = pda_seeds_with_bump(&player, &bump_arr); + + invoke_signed( + &ix, + &[ + payer.clone(), + delegated_account.clone(), + owner_program.clone(), + undelegation_request.clone(), + delegation_record.clone(), + delegation_metadata.clone(), + system_program.clone(), + dlp_program.clone(), + ], + &[&signer_seeds], + ) +} + pub struct ProcessSchedulecommitCpiArgs { pub modify_accounts: bool, pub commit_payer: bool, diff --git a/test-integration/schedulecommit/elfs/dlp.so b/test-integration/schedulecommit/elfs/dlp.so index 248510aaa65c31c46d6cd116e7b95278962204eb..1cd487be083a613c790674a451134f5c3c4c3129 100755 GIT binary patch literal 473048 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%0A0xaHzk8KFyOD^8`}qgh&z{~2z7tRQMJv)5 zN&4c7bmg!52g3KhH?X|jLlV+K>Dw-F@P3qB9NOQo(L&wN=x^w@_;L%ERi-%u{w}ZJugX`gek_u9nn1iV{-)oJUV2RV+bMX3{bKtee}&&Wjo#p|tQWvq zvXaj_4tuaJ;doxzu-N4Natohp;rSMxBO%Y_5N?RiKG27HDSO`L!VbvA&iz84cxa!5 zVZC#~H|oO{z@xu+$L$andx-B}VP4A0)#H&P9ru;=SH75^=}DBEks5OI8Szt&nB3$m zeSyi@`%NcNmv+pzs3I` zq0iUcw`KeE7x9Pt$DiFQU@`x$Vs_@7GUwmFlzF^z{{4l*xBG67H~)TeCFHTn{JXb+ zbQ39`U&Hygh4Xfm`S)$8_ju;t+fcst{Oj|r`T;8ETOWsQG7d}Qak-7Vr55`5)OAmP z!y-#>w@}y9;rQB4`3uhZQLg;FBn0+9zSZb-o=id3@sb zR5$rCX#Igc;rzz=;7>pYoF5Xpbxo_KH%FxX5HIb=iR~%!d!qJK=&$qn7N}Otx4CG! z;EV4sN{Dmh5>8xiJ_3$HPX+eWKG1{rDbemq*Tum&CqG>uQVwgai+{GWyj-pKv5sWQ z)mj(-AXDytW!BkqfiL;^Z<%tn*2Ujsxj?QDab0YBgK%>5F`fnw+q(Er`MS73s%d+z z7kX5(ys`8c!ri|u_B^x?STxqg2SF&BME_7ONfN)P-#LuwbznYUKpmFL56l;%IG za%Sfud_OX4U$Xsvj4}83hJKhkx*_KrE$p7-3U^$7n(-GtvQ z^8PuwU7Y1q{v8hc!Ewe~?w>gu_1G@ceINK0vKl8mt?%jKcx;jKn(zI6xX?+^sJBM& zDEV=8pUT(oUVbk6!l%N2(|oJwyR{9gBO2}%F|8NW@59+mcm&f|Z)eQ`K* zZqMzDM)>P-&$h^$-_IKIL+@{?v@dkMc4GTN*YhXKU*r5&yT9bGS!!}|e1A>S-!1$O z`*%R>I``A{R`@|krzh;M3Fgf;gwvzz*sy)2udXlt7=O*741YOKbNv1@{OpB2hm5~3 ztyp)fd{wTymA~e%!8k7S*VsLr{S8mtUvrrIyI2PSbcOv`8t1-F{Nw#K2S6X{sjR=| zF`T1`cOF!IJ9I$8kUuB#*Ia|~<8p;_b|#0%m!r~nucW*3!~8T)qP&dNke9cLyo{N= z%&w3Zm5W+a-Qu6M_)H1oVbv2S!ydVH z2=Z(5erV^`dXM|%C?A%qWtY5^<%-fhc^`Ls#x8jS2nhd#*(KX++9gHEbuRju=(}<| zBeX+wpT9gmv_pO({;+rgcF1kroS)Uc3GI-V-2yx06zxxi9b)rzXooxkIBvH%y{N~Y z2RNUbMr{$;A6CDb{gFrciP|3}edGQrw<}!#oP0mkK90X&e&DzoT`Ap@?;yezb6h{w z2*xSS1F2jW_i1S7;U?lA%KEE5klByjLHq)IPUNq8r{FVU`0OxzY+il>{;CHu_zYz5 zIg!8W^~7iQcEw}QfP~?=+6Z{n=7URRKGc>uURcnqFyt={!;Cr|K1ZrP7X6JL8YHBR7x_gDR(7m$)7I`CYU#HVD1` zC;6#--TC9-_HxMy>swhUg`WWM*;P&*$d5`Vt>Sbet3^$N4$@V zaD2T+IKOW%_k)Q3*{0>0FLppt?d-0)2I+5Mq+R5;u;*L}bJ0(wLSf|Xf`2ahCtd%K zyv5=NEnfcqMK1cXq{n*{Ug2*Z;)}iw9{@vMamOt}7nS93w z1jVyr=DRZaEgIjZHSkXCBJ{F_Pc+o(x-oF zo1};G-VJ&6bIr8R`A{ByJScu>lhY52oW?tiKK>rnkm~#Rf($-q86J~8>=d~DlMSEA zhR@_me3lD7Hf{oZ4hcTX4WGe^anl)$yRaW$m3p04??LN_`5P`5w4(TmdifDwseFsC zGCuCwsP_E}HJ)6g`N`Q@KFM4CUAj(rvKUp(=Znx5Vxc#+1R$o+6_+sE`xR zU%BXAqW7sMTfm=*_$h1cFMO{EJzF4`v9EvO2~9fA7%4L{$kEMYA5HSHUSt9t3G%< z>#JIH+@I;s?=y6qZFKxdrd%yLejrnBrriZW#5sPRVes~3%GILdPL>PkxF$o#gF?q% zqvM*Ibo}W>n1=&@@{bV@_i4C47oT80$VER8`vv=L(oQb=p2csr_;)RSmBqhf@k=fK zuNJ@1;@`CRxfcJ1#7D0swSX^t{e0pZ^nTfkCQs7yRrPw_3ipHZ*ngBPJS^iXX+9!h z{Nl>@0QX`1(H=ro*$3YLT3ak4PPsc9c4b`LFZM>h?yE>ayTb=09`7F0(7qem$ISvf zAzye;7U5j=Y|z#4>$Cf@{QItbBh$oR@9(ExgL2J;bC-aN)dhLexT2ha19KN<1JMSgPs6!tSed5?UFHb439DI`>Wa?hlvAdHJj zr~Kq!Oy+tkKlvMzo+jbnMU4_(Gl>>oe)5OvI0MDQO5d)@k4!oP@vdoiOo0k3>wm=e zD%K(q5AO&1t8+^9CEbZ9>2u-7NoQ@pFk<&P)pu(D?v(0suB{zEL;4;KAimzhuDVvm$Ht?azd>Hod`RRsyIy2_&&sq%5oCM+G@lhSy=>6%Ur+bfH`mNPkN}kEEx?#;2a&F74YK7QFF2C*y0| zW0Y^6hk9h?>%_RacjNH$eLc+d{TH3`6XNieADyv1X;!(A@~51MT*&W|f4nbgRykq% z#~zBl$Mjz=>ljO#Rc@I6mmz-5s=xXhrjN7z{)T9rz(Vd@MQ4SB1-or|7AJ639e9%4ViHy#N zjIK=yoUM050iJ| z^LyMc;qS@CHZO3T2G7P7=YO5swPkR|Kws7`z^*Cm{;bfgFft}#*dFm=xo5ynn~Qc+ zy_CTT@$vWBS$<83*RaZC*VJ!f<}9zzdtF$5De)M(L+0JW$QlWA(H5%HiuQ0GMCIjP z=3<@$pQzXAr&`=w&aXemzPHb(U3CYiuw1-H@rjG7cavs?7mw&T3;SQIfA0?aSCj6F zObG8N&J(b|7f65g`#Ob@qv9XPMLp7A&fA=mHbuB0}}5W{E)<#VK5MWeo|iS$J+)!Ea|rm={+~McTCsvL-$Fzu4ATzcn@5{ zq~kP;D;`P5pIBV+NIF_Au5gkLo1cc7tiJlY;-MCcw@dqdL#mh7bu5y2VQ8!5_wCg9 zx+Nc!^mwP1PnHZ@T;U~4-eYlXFIjS*#8-9PE8)84Z4%yY_ld*>m*dXQ_o&_Gc1<`x-+}R(+Jkoq*(&V( z%5n6a`sS+r?-h9<-sN`6nl$~9GCRfOvtQ*l-8Tce!l+NuXe|3QVr|6`nO4Y$D612W!kB=4qIQ=&OT|UtNt#9AIw){X!psOubz!{ zU^?zLv3F6G`Knj(InI1F67)A*7u}8dsxUHQ{kmP@1bUJhGJd5rTgIpD0X)jzC!eEw zu53M%>d74fzoaL(TU_;jKi(HQsq2~J=*jZ+Oi53&{ga_5zW{kj`88oZxk%_)$6XGE7xo9 zrdllc2I$nQ%>S(;ox&l>9M8wu*TWOyYM|l7(uYupj3^ZbSZZ z-h|zi+7Hhxv)592mUeOeRmx$X)Z!}7>+X+ap2T}ovc9GrK*CgxOI`O>+Am{LU&@!+ zFUl{bm)UQDpJj6yz9qdh1MP=$F8+s|q)MfKCG@M1Z=}=bLHEb6k9I3xo-56i(V62Y z9H%T%%kRkddKV)<#9!>sg2E+!KgR)&d~}t_AL+9p7)RCYspX<4N^~BF-Qf@Jl@z`v zJ!&WRHykv6`uF41{tEp$f=|ZY^8F~{_oui=Dz<%noFfo;OqczgpdXX4zrl6)EFhDM zUYGXg0~d4T>qEaxCw_W;A8)znF&T%I>-I+<&Duxfe4k(f>-O%l@iuPb?U#?rcstJe z{RrW&RD3y}Ypvg3QU?Es!T)!Ke;hl6@>6Zy{4%UBO6%qw^1Xo4x_Ln89;fT(?H2cS z^SdQpS~u&x1BIfmn|md{a^3tau}4em=GREM+dEW#`i9m^d|k&)sxO8VkEG*e7FRry zj#U;{Jd%#vEUs`$>t>VB4qrFxdI#sv6u%*z?@Q}uy)U7(Zhp4HP1nr}Ebi;(xfa*; zMzUnK#8=rme_gY#|8HMt`q1Pz9G}!Ll+Qaa;JW#HBFCW}JqFQ8{pRimFRHvyPalH( zuzrmC9M9F)&4*3zE|Px7#X}ZXI?x_Gsq1FoQA_WZubWH$ZLXUiuYcS1Mz~(PI@k^E#mVD=;=mV7r^f+{PKI9u&<%~+azG4xK%^S1KUkz zTKcvF@}pY2`>ox9OuO$xyRf4&?TtyipTP0dYR~yWeG{I?XMYZnjzz6cJog29kNo4q za_>jE!pJ^pFJJ$eQ>Z@+Lm!nm?&}vKbxnJ!*hwM0=~x#(9{cFMALcr2x~!XhUg)a- zxU@HF_80x4-Dv;GSZA)Bkem)FJ_R6whjeR4NcxuTLoGD>2pCLQf1%va9&!H?;e>csvxn5~Rec|>o7g|0l*LSJ?G<4 zUp*`HT{Px%9Q^)S;ks$fDTG_;UpgNW%5}r0h(joBcLd`rw*3g#TgS667Gpg4IDmgb z##>kYOH}@jW54VO#xe2MeTE%Y|1(p>{&@oS$u$@sCHv$p@@C(YZ=W>F{QG~cebPs1 zf*cKMDD#HdCo7?s^U)z0)Ep2Q!pMk$dPBPNkHSpT8?u zClwSL(|I&@@5bGd;PVO7--dLbpXc7K<-`0pGvDUvy&FCvcxKyoJDc!6hVs6i&)2<4 z#?f4#Z|xpapKp^*+FsnMVZ}UK)Ont8`-z9CzD652KEI{*f{f;py})${&xl%DdK*nJ$I)wYbpTT_~rSVozG;pp<=ZUcX z7V|$3fYF5!eGegD|K*&{({GXaG#5Qm6@RCH*zR=RCuDx}*!G<>^0jfr>=}Yjh{xiL z-g%wivsn6@um7asqu*!BMV}CSx~82{M?L9&jSwE+x2R@6)bdjgeu(zNM(J-?{RgDI z&~5;G%H&_(OV~!Ls{9W_zZFL8eT4eCswY=zezkKpy}&P}-^E&veq|Dd^6)8v*K7D} z6?`&ud_v>2KNzP;kDc!*X!~sU>FDS(Xiee~?^b_N7ZnGdxf>-&$3tS@sZY;|n7$#L z(*VcIU)DWC$8V6|8004ny3S+&MgsfQ{Ujk@Ic|J^Fiani^n+p#2%KMthzP)$W-V^~i27fW(e?)Tg${Pz1jTz=wWyU@$+%>IT$ z>AoZl4$5D-UArii%W}I`*XvTg%-^a02&R|W^R^$v^ojaAg%5$hQ{-`%(j~b^&)qrQ zIj>QkDUS;v7b#!v((>!cNBs2im3*42dK2%o@rk$U1pIi{TWtT&!LNLDs#pO14eHnF zZ%}^^?h_O~_M6@a`I)_UWGUc;`2*trY?u0^V>!RguTyL@{<@#L#p1dS=_{%nt+Vqa zS%3Gs{=*e=7OqP|e5fy~txIa{=a4_u)+N0hZ-L$+-@|puyE6BKF`sl^b6&VExuwRs z{ya3Hx!R#(dj!t{G3joAVn1vE7gE<9vBU<~Lubbk&c^yh(jChH@c% z;+yq*j;=x>JcRd2=n=Pfy6P^H{r19;>hIG2{YQWS@PJft-HUruBp$ZY0)B*a95XsD zvUdLSMxK9E{q5_}u4zq^DX1Zw4b;O`)@!x)z_ZKg{x%t}8*1o}<&uu~yG>uH-inLe7FYe%S6nLP z)-}IPLfn^X`(@oV_REf@?Um0T<7s-CKdAXgnqEGCs9svz04bIb1ovU1Q$h z_Y$Z_xgSG)L^{!aaery)yT3Z`CCy*7c~s}Sr1|eGZhrUXzqPpfVUlLmFMY)U>BqX} zuS&kJx7OLdU&t?+*E0H#c%Abej6=J>8u#xBJj~w$FKOOkamQo3#T^fAzi(LWzIZb_ zizjSX=9A!j`+CSrKKi~Wy|5hhSGaGMrS}%n-{i2`x#tJ}2Khy8pW}q{2K)Dk2iZTh z2VpN8{${r}H(6Zm7~Bgj@pb(VNf^Ql=clAc%ZK?7p*^?9Lq8e$Uu{03T@~ul?0ob^ z*ui4=l%4B4xpE%TTjXQN=m(@lz6%S6FXx!>%nV0}1~>*C@8p*!@O@ny{72P^n-Q0QIq(}Lw?a<`oN-|RS-8()W0|6^!M zf40l}-ZzW>DU2+a(Dg0*yB_l6b~@uXBHmR$Ab!FV&I^G&MwIV>zNA~c+w66dYr?;* zwY(p_tQX{evZXwKAd~;=Og{M-p4acrK@2>h|7(iLpXSKljq#w${hXQ2a^5xd zAKa#;{9Luui{o$%S@4&sT&%Hjm{$hy)BRCCZsH*ur?y||{+MK;>Ys4Dv0u~!W5Iqt z>31Ps+zQK4u9@BpzA-HF9*TnE5f3T-OW!*^pn5j_-l^hK`u?cu4emYiNfs(S;+Yzc zPotHCew~hn7|v*tFqv*)r=}iOxfv-ot2t6_!jwpsiyEkCmOD-F&Y z#SwzdNUhspkp}44a zMd^H^+8;@Cr{#~Eo?9&Oeth46>*W51771(V+jy{aUa1G;HI#em*-&r1GLt_Y_DDRa z`kLcnWhTE9`Jog%{>{hKoR*j7E}{uSomn8`mV^>rR#{)>@+GWGvb>i^xs zX7M{w4;*hkAiasl*D=%zdtPGm!P1KP;0q4`j_D7Ue>>t`^4E$kZgtHZY z@Nga&K#1>a$UNZsGHho$+9AE3kA1)}UF^pbp1W%jJWA*8rdwR?y}qK-vz9-i(#}#o zFui=dj|qP&^~3%&y?i~fFHOIo#`(Ke&?U43X}8weZ+5v0{ZL;AKT|){-J~{b76@|- z!rFeQy~6j$W53i>4l?$O>le<$Hw69T_Z~Q7k)M4cZ}lc8@0NDsA>BV(VDjdAY?Q>n z(|Epyc<)We!@@%v_KaJ2P(pm~PUOk`j>-K;B%S_OjEkeJm?H5oE-7X8qBkiuF zITHBv?~|@2e}BE62MF}8*rx%Vh3*CErszTPiFAJ^?rn^Rj9xpPjyt5C(tWbqE#4ww zh!^1kuW>@=dr4V-N0i@TZI|cE#P0R=!CFlx9=d-oFNqKBlw$DDKtr;p0K`grtoC*|M?=;=@4y|2PZr^(5G>U^G=zvG>zx1sOb zAt&*W?StuZBx<|@iFjOJB^`%#y!NPm!@ils-JgJa4{SW^e4E^_dXM@WQv=5Fe#z(g zitKo|JErZ~`Re~)f2&{T$?xeyPZDVPuhn zZZ}bH4fA`L=C5M>>F+|kC}JyiYOmP=H!$7o;#~A*ieI`f5|-yYNjT@ByzkSL>fIyt z3PU?(9g&Ofwz%JK_y&y+pCx$aqJE3tZ1D{ef8yuBekk@q>74puiC3OeFLD}=O6S0S zB;`uy)c-@`|L4xBe^2pF-|s%j=hXe&vdxPX_IQERQ9I>5=hA_@u&2mi(ISij`IIAn3vv$X$CLB6bu%KX);*O`8@)=>+}@GIGSe4#Gno6HY8i8a=r zn6E;6FS*D3uA4MJ+y_3F??0>AUGu)FO8TFw^W`Fihx;9bW;0X=vwBFQahjNrOc_tnVfb@vQN zey9i4{?_?6OxJb9KADHZbhQ`Njt}=sIIybimryT<{3Sm_z764CvJgJ=N%vmP2lk$M zzV0hW$(WKpeY@EQeqY7|5-$`Vk#JS>PK&D@g8MP7yvh&Z--P{xd~^-TQf?0uKhYAZ zH$M2zl3b;J{{m}i{`G(pn;-q*`gxK**X1x+Pl;Sxy?D^ZyUkOhua|1Fp4u}F_>5?r z`?w zRsSq_hJ>+dh;C;QF%^O;_Q9`65g{~F7G^tf~=@$oa6ekdJE{roiY}^bU*3j>(7!F(TIZAxPCvH0h;$3+Eb>#(dZB#0>jZSW?WOhWmPRgl_wc zZi6-H_IvCb=b}kEegnJkyYK_}Jdm%yP8x{qUJ17+>DTN=j<1*3-QO$n5Xu4R?dRaa z^jdncSISrFMX;)>UKIWf3VK!V^N2|QmF-d>Y+vzG{gJNY0{ziS{_iok_$~am^`O6B zK{Y;BgpdQ*Nc6nF*RXTqct-k=u{u2MO%((*6jp^^mq>~T1=uWZ;?{B?Ym=V#cO^WY3G(fxWw{^qsczh+8=WaHA<@4OF z5--hjcUau#Ikh9=VO!q^O0UsM(~8|tyiOdZ2k7} zlys;(JY0X4l=pcrUMbPCc0#!g=esYVtx(U2yc&H%dCXQFDUoa-aM2bS}n z^Wkg9qf6lT{C=iiLYHldC*_sjOT>2+Y`)WZFD~kMO`0q9UN7)Eu0J-^$m!+ePX7Kj}WpCaoX0mf*0x zWTvH$sNQn@&3+tWKg62AS)MyTEYA(85@Wp*rrmwG(IM;Jqg7YlZ&OK9Z z-JW3i^7|GG^Y8=sdFg!JO}|5zgZWhTUFp6E*N1*z#OtKLrTZeLSlsW6h$LR=hiex^ zN`APUl)JrSK+6wJm2h2$-cJ}0DISU4Tj>7Rq~l#uE*?@ml8&Oq6;5LJPsBr}zdO|4 ziib?UcPM@PhDNMC^-mOr>LlK`Q{(HFyg=dZH2ZDIB^EdPZOOAOZu^i+7D#+m$2Tr?F&^-!u5SPuaU3q9Ixi5>%!?;5{hzosO){HeF87!=Y+<~{q0gO7wwdB$ni?K zaXHFG2PMC-`}KMrq>8*Gkh^TV#CvHbUG2nQp#}8E))Vn+<$Jt_spayRwX1f&y}TVA zXMV3lG)~da;^FI)biUXu%|xmFX+xR#UJhL!&XZzCnZEaVkmbIe`7YXF=q2CBXa1o~ ze%6lq8uCx(d^jG=hdzIM|3Z80runq{$8A3Bs%iIMp5Ytii2a(CNgqIZF8U4CgUI7a z(X*z%C!%NBzWZsz`-mvN^s6xp^{m)AgTz+PdkTLG8fX8WD|)s`*9-RkT`qdDjEg_o zZ?@a~RY7~dY~y<3xkA5CZrQKUe|8P!-t>AnFZ>ww<5i0P!}VY;o^<`-etolJL%A0H zVsf2y*tzA`D;&~6#=(fjv;MQtjz}_c&T$Zqll7VW?D}_ICcla6SGVWx()L67{q@P+`M~(-!`%R(abfe>f znsj`q1|8qQ^kMBM&y$e8;l8`rGp;vH{@Cu9VH<|yF&uxsj%2y^6VUD4lT5ezYIL)4 z6|N^fEOe_ky3MRfw*k;67yUvA^hfKBDt?IDG4AtGV@>JOivO`bzJB)@U4O2<#2H$FlBjtCgpe-r+0(s-yBeueuRLwFn)F0aII zJd>ZDKYyCZ--!Kjm!Hs&Ohbe4UL}0nDC>=``mfhq2d=Ck@0TF`kMTqN{qg8x`i^+= zdteoG3C9oePo}=uz;gw=%J~!0&-KL(Lca}0zoDA+JHH0~8ks&peG%$M?kv^T7p47) z_nv@myH7IRdPBPTd{sqXoGWzeHM(uDNw)^jCl`HD7$J83<5&kLfxT39J>1-;^GW~2 z*P|!0lTOD0cf3DQW+zd8v+L0>Vc(DI2#&*Cbd8jE`C5;}7D>NK(pipvja>8*(XWNw zQ_PQiDpE1;@BWqOn;c5;3CGEP^DF-;=7n7JKC6GK`pt?`ylj2@BjA;j+Y$)(QPpEr z%6)_TmO(o89{c&ROgil~+)K%BM)7^!(qL@o5W@N_7ut2FQa=aqId3NEcVN`dALgsx zHM_;f?Ph7N>Uw4vqzcEK=;JE$@)gy_kLi8(_xYLptR2^JlE+sR%*V04r%`P^GjP~S zYCIRU|BAm#>-Pc4sJ4E0dB@O}dH4g{0OvUJ&T?VC%Ded)Cm`?F9*^FEJpVBBy*#CN zX+Ale$VjRP=G< zEUo8$sMH^xxlhae;IVyo$o=D8b#c}HupiGU>&G*sA%EX8^?#oL|6Fv3z%LBx_h$+t z`(>WZMX#vZuJe`cx0kig(_0)*T0eb{a;7AgjR*3B_1DeA_)Whb@kO~WFMFRwZ1~gv z&v`j9dgh`VYv6r@q?gt!ua^Fl{JgJ~cxm7C^%hsWSJ^(8^N)CbeLmMI3E5uO56WG* zU;0ey1rB~ZvE3^b>YpzIj`zp?c@_Jm+4ah>!b{hurr*+i#9-Yrk9uRo$^#FP`%M~m zJ<9&9$moTv-gs#yKdU#oGWqS)({4ZBrR{}!`Vjd%(k}YBtNz6`=eI9$zqx4mgW5jc zcQCyc9qhe!ju(=i{d?AN=n(ohFU|CWbO`-Ii;y1|r;B`)&I_r31MfAd9T?zyqVqy+ z;eKfqdQCF?KP~iXGkUG9sUIJxL9hO5^cpg{f=;1dBOK2ko&x#VZRN0L5&0=-JfvIx z1azBmlIhk`jc%(Huh6e?pU|zv==QXla`qa~Cl_4=3B!0C(f1)n->C3-4^0bl+`i{N z(>Su+zYwO6N%}s~^Rd6@Y44j=z6W$q)!teJhos#tZex+mS{eGo$lD^-sd`Rs5ey)ql&ihWk zirv%uk;C)BEick^@W1Tbb-UgJ!1p!F-dFFuS<3sp0X?$Y54!DA{v}IaC;9O%yS^8ds^A7@NqW1$N%}cdE3zuuy(XHW3sZl(eI`A`*&D;vDC}H-yawE%lKPYy&Rn-wngPgf>i*KxX@Xa4n> z{7%?yxOYV8!~8$XX_z0tpVZ%I?S|`|sVGW3KX)eVp52eAojP(r!q9*HaqNfTzJ!!6 zr*dB1TI$Cp7AM$gNeormzkLTZud_UK+8ueNLV!eg=x}W{7 z8F8FrK??CaUHlKZXa=K*zgFZEalFz_D-z{@2}Xepg#G*c3zfA=Qv{e_b4x`w7p#Pk76GbcE8&CM~w{q z=63h$F)3Kh4?uXKy}x&$9FMHui!)LdPq+J1`LS{3@-qs(&WCs}2B|~4m-KY`3GMkG zyr&!wj@Qs$`)($m<24*F|BC#RY3DWt_L|$5-oJ2NP~i9&X)=55%N26&^0PR@SLgSf zOnQWV=c30%PnXtzdTyt*{ySClcWM21y2W+gS!M6V#|7m><+}4S$tdhTSMbh7pOJVf zKWoM%9`b#_nl$nH!N3E-0ZJgI*~eNd0#+jSn+Sew$T4`h97k+zqh*gIZp$ zQ73qgi9~*6m~yd>gPln8NaY5ybV%M=}_4HDXV98((nTohf)%_XVrxB${KiGl}TrR zbFzy_yxwo{zp3-o?$28M8y5d)&GwdO;5r>H&ZN8k`xNBb-%lyoOYb#$XZ^!EpbNuq zm-ZhIAO9PqOWU!1om}*wv_t*zf)xkB6f# zB-W^hu_mF7t7`Rs3%;cF?3{hIaz75snLj*Usqo`g_1m~#B|ljuylb*5{;oQeW8a5x zI{Q9ySDo@TZZ&u|fBC${ejdXUue9-SmMZLm`E}BIXKFt60n2+mhU;+-*!$_>=pt=z zbb*D|FP6tPYO3$u?#Qa*nUh zFL#?f-ePU95v{0^Rt zb8Q}t_l!&Z^UhE{=BMG3OgxUK&&%DqsBkLH{Y`@{p5L z4k&l0mJjo#zR}I;o4nKD-sy0Et#qCz%|+=wap!BCcwLD;di_zG@7-U@eBQXBw>1Uj zuGab~|7Kgfs3Gn2!|1P{b0nM>BP~l$?5_!ab7tnHVq8?ZCbQctuJlW0w^&@uC$nu_ zZPGBAy;$=%S^sBuT3qRn%vOPR|790_))xWNkPQ7;MuS#*!X)*PtPG_PA$20kxfpUt6m2*8v|2Q#EIutMJ z>mxyX_-^Gmdz{5L>1dO5mcOf`giq4Zl%^jjgEL*yOXo^j#yJxB{Y6T6x}I)jYwAyZ zRREXcl;x@CHw5YI|A#v(``2gsw`=mLGJYvv_=opojQ%?j!NYqgNPm}K-rv7uUa3E9 zml~CHUla6)?fyq6?HN@VVf~w`)MxoOqkNVRO#ipG>gmMS%e#Iay%33bmJunuBGENP ze=Gx@c&2ns);Qs=xt9282IF6ZE)DhUPY`$bqk+DDDewvRJzp8(XXV^pAiaWT;|Gm@ zyRaKfxuTwAIBNRW_47rOa`K%9Z-?^Ekx6>9Jn?M=UmU-#Ivc;MnG1NPSE+y5!w^2q zgk!rV{puJ|%h&xc8F%r9V;aU&Ssm{kNf6~HX$RcT_Esb_h5NMtb1dGb?d9d`kEnMq z5X0l;iRbTVFB?A9`tfVA2fr`vdw*H)tAL-2zN>f{eK?+iXX6Ji(AX}#f5&ragwG=R zNmFEIAYL37>_>xz%*Xrm_=|oR{n_5%qdlkR=-HATHD09Q=nWdO+>ho5a^pXH=AH&y;JHa%V`n$AjmO!ubyUCFzOh z;xar{P$$yw+cJ1jixb{R89X>q@Pz$-N~Rw1pj`aR3)p`Z{KwO;qc!>!&L93>=;ML= zgA81baQ3e)=pXSuy|Xla*DX}N7q0IyoMb$4ys-RHjN7cewrb&{s;>r72oLo(wo#-W z<(c(a!#V?}|!}Y{L!W&X}w5t%6b<@uf!tbi|ELuL= z8bdnif}i4FV@Q71|8>d!U_WnS{o(;%;(HnvSNpcVLHilvBlh%KZI5uiCUDFi zHu|J?srA?OYBCEI@OZy{zdp8gq3cV+CEi|c^kS(NrRzYQw$u0bS^ks2!{<+*KSF)H zyNY~_UTtt~e(>{n`TD6*3$lDZYTTsd`fNV+d716L8}0HvGUD4+|J!4%S0O()YW>kG zEVTAm|3T8Ppmwa|&Geh9;d>l7aBEkEb7M6)%M6dj7CzU)`5Gq88$=FhXI+IP+6U|( z@v4`0lmY(zgLHi|9R={D>zC;&?{3#6nqB%X!d8c)^G3W?3#8{Hwrc(K9K}`vANe^8 zKi7~nY!Q6%Jt48r`Wpr$jQe!|7Vq<@T;HSe9rx*bwZ0Bb7VePzl3#wr;)c({eH!=g zJ~Z!_cy=9`G;f#m(cOwC&kbz{y~2CHH(R5L3| z{YwziLWId3dQZMU)JmQ3uN4~7#Y45H-cJ{Uhs;*IzV zyA5%^x#as1jI;fm`4y|ddx_*@Amgc)&y#KLSBPimI12H(8TrWtN{@#K1W&3DZQk;A z9`wFE$MYk|x)<^Q)UlpdMUbzXtMsjlmA-Y$Eq|8Mx9(NIk>#JE^sW0drEgtc>08&T z^sRfA(zkAdP{j2V^)l&AJ@jtKMbdLr=L^G^c6$r*!*%UTDNkl^(OxD6LVJvMFyVb2 z@Te!-kdJfl_*=4H*sk(tO+`B4<)Rf8=|DyBd=ucN>qWq4d3^tIoE1|4T7faOH!7|&B$jv%AcnbtoV;kM1NF~_CFzXd8X70@uR#Gzdx@* z7tUxQo=+p5MFAszAIh7{BjMbg>F1(M{klv)J2Uxzzygr{T+DPE2VwhpTRbHQZkMQTCeuW-tm*UYJUb2X1uB{iy zUsQ=MLF1&a`-Au`a6ZguI(f%&>i*2GNqXO3s^`qk^LZg|B~;u;b(+o(zK$h4{KNZ5 zloqsirUYer@!xwEMaj6dg% zz&jpR`OZ((edBmU$6wdfnIh*U|IQH^f5|;MZt?vaiLZv(O8++i7@p)F9mk=ck9x!B z6UyVCfVI9~)o=UBt{<{^v;0=5DwmUs@Il=?+R6HD+<(RL9gzK8r1)n2VA*;s{|PB? z`y%tD8&PT(7EE4kzb?K_^}<|rGe@J_wfuVN6Y%o+XtSmh{^wy>#B1>bkIM`E2@-E? zl_1?O2+v_{x(4-ZUF`m(WVXU7`3DuBkiHuNdZqp^8*ih=C;Fe*bYEYKAh337i`cJS zb-GT7*C~GST7^Gnp4m&L-#A~eW-{B#U8v=fC2F6>7b>2~5|xMeLM@jpQNF|q4t`OU zr<|+~(BI7l$NabPW`ncP;A}QH3k{CZIa#Q1mH{vPgS|aR`sH-?e#AqHAMTwL`HhDZ zF5b(sxXF3P0gIcwcZ^AVPOHuv;Xa?x!S;DbN4D>NqMGjsHCaCwTmKeWzuE-tvU!)| zH~jwMQZ(2VDSp2GS$m4sbALYZ;Dh&11@B~*3M|f7T6~7(E1YDO&Nu0JpT%B85#jQe zk3ZKh@mY$0e752pFOcHVoMpOCGnb1uJfqiYxE|oCC*n5kuaCp^08aRqouT_7{SAsQ z?k^KR5#C!-KC~LWd>on`lQf%L`26dB=~itQ?^jCwP_G;yJqIHcpUPcFCKU+>>~7-j6Q>$y}f`22gNw$FC!G0sQdZunlU?Iv~(CV8W#r}TIK zh_xTDIv@q|lba&`!uOUc`YZGGN`=GrP6NT?5giAkv8M06n_K`MZ_;>vn#+TY52K^+ zbB1~fWIOio-B6-<+^%cfs&Lj~leUxT1;x|TlUW+yRX0g)dg(vqfZ)IOlrKaqKiZ8y zc+!4X^mn?H5BZwy=dV%U^<>`9quDu~wdig;@@WsU=YAf+?ZbGb;cNDIGT-pU{`MD9 z{)G6pp%9*Qyrg_;ufSX8$ACZIMLpcNA$-hFYZW*ym-%{)KZJRgPrlyl_`5WI3E04O zte;<60QqKouH!SPgLB-D~QV9_u!rCIz_8Az$6k*;TLS7s7E9)+an_#=8wK zpBMMWq%QE;AOZH%RR8$-X38VmdH6mcfXBz1&v!0Aey-5>Tl`!>%12aZOR1b~5^y*N zd_aCYUODr9$I|$ES_R*D9w1zIj<9{3PttKxR6ICea^I5uy#qQm#gjH)UD8Vk~NTrJS{T~4#(iS|7;FY7%7mEh~N{3Kl`yM2<_`wBkart8Q) zg`e0sayy0gX!~Xm!XCo^YuNsd7snwbB5eO#XG4xI)C!Joyh`KoYL>=4at&A8C>PLO z^uk(6jz(XtA@?`8WbENrVSUcN?g-N3VbzoIh|<&jmvgT%c#AY_T&!W&l*uB8edlX@ zo%K7N2U@M(6&ezc-k?3wfkVap1hwXYCvpyp8*^?iu$|4o!Sx>FyAXH!`~ElS-$Hya zpD|>)SAcEH@OvZvug8B5`Lv$tX_osa6p!@Zwml;;?;IOYmF+hc(Wvz&S#lCzZJKHeV>xgXH^yc@Wc5dH1n|7M!|d6>Rn_&aZAddDZu zeKcw1uTp*Yr>y7%f_QvB4*f2ldtp%C+OOs(n*Ds#zgECRwaztgpNf7~mO?Ps&vD;k z`X@i>OaVYUd@_C|{bncLC&>}l@sxO9XSiLE^w>P|PA#_pa&VaC?$UVUDh=J9Pwm*7 zRBw{+GEb^{#{6#W8eZOxp94L9dJf%>Phil ztNkFp-OLA__@wzOHO~B-k-uV^Ht6F!v;&qS|ASV)Ynn3FzgIE3M&XQZ)X?Q@^dd_) zy|ru7JemLe91+(OL!XZv4}ZUx_!LopZnu`>JcA*g zj!)(z`&jlo!>GZh{d$=Bo3wt|kF$`T7w-r3z3->{x^fc$<4M<*n^bVq^G*gYT~~6l z#*@NnT4Zs9)6{NpgVWSzaS5WNsYQOwvH7L~|Du+oK9>Fj^nD8Y(G~q%#=Ng{67wtg zI7ylm4Fh%0piykl;e7!6LFU3 zxnqC7)A>R9BtIQ)qv->;TRA^=BfpD)@i5+r(A#srne)NzQnq&l?Im{3j&>yLrEm<- zVUU54X*LQTrUx5Mej2U+-d-p_-zI$5pX&ewPdu#aHTQG-`#CPp4yQ|6ML*0w^n6eE z_ihsNgSg#U0awMWw4U0mc(DHmfS=1l7Y`E(eyYdu-lnb#TD82l>wHP$DyFda4@r6N zPjbKNZ}+Dq^HqS{znRPj0&H)s%2_gB!`S3DG5JcrcR%08i@)zYzg_FwK2$Pa5lPoK zvsyHNlLS~dbz0ooo3+^DibpbQsl^q~WY%(x+j;HS=#b3n)^ztH&01q|htq3uhqFQA z>A1OAq80Dwh5DFs=HuAsRlnEI?S)2dE=ratpQ!iA!7Lp2>$=`g`gNXky_cVIi6E3L zQT`?U<_Cjby?d!R`yB_lKRnkLB zpRAtnb$z3ax79$0e4T4_Z5%NCb}HTZUJul?*w578u9qnXEhy^q468H0Yswd8ypfO0 zcYg@iFZc()w$ZN@5j=b80KwzqJvRErJ9WG#=9iC8Gk%y~-u=>v`Q_8`b-I9){X9aZ z{$%LwFwW;PYnSU6KC2Ou4)IQ~{<6*?H#`rmuWlQ65Jw zh5Y;YTA*-8l?&vPhXF8`~%;|gwIZwQM0d8eXv}r zMQ*nxH*JyfNymVMAH#dNq}}NCTF&QD;yIOgZnAXiC)1}OJ>I2oIG>UOeqJlSUJ06< zp<#SIu?L=KXc%8_@0n2ZusDsBm1)eSX2c%?9U?gn9VA`NV_TpJbt?dw=5HhQF-` z;$g+#^}YL7T|VMH2L-PCi7z`t&)ucxY@IKD&er*2`;h7Rhdx28bbmq>IpR4PA1AJ- zreeKA{^i^r9XcTR@SLCUb&t}~?T@a>->`GnhxOcbQRzlGAZ5rWhLqd+*cwXbi9wZz zcu3`#`O_iSp}s&g^;?hH{NVe!yKrCbz`@C4PcroL)9VdSUmwjqU+Hk(Ok$7rZN9l^ z(o>_$5l`;X^AWBe376@vACqP~H!;N87?Xg{1$uh^&FJjwM*1;2QH1^ZE<)YqM!S0u z!9)5={jCy}axG8*@lgFyro=lV4U5wyOz{H|*@F~65*1IfQ1P2<`rhTv$4@OhiQkt{ z-}%A#gTT${pRUJ{&L_T6&;3Dvj5F?f5BkI6DkpoJu4Hy}5$-7?iX}SgxbS_cT!hI0 zPtv2~Bk8d5xkTj$-*XqabNgi~)Kv@0r~1(P@9Tf!zY^!o@^)VtecUYKeBnBV_2UtP z+l>ew=X=tu_|4g_iqPS@edgoC?HIQA5^0Zbt0`Z}AGdpQk?yl(`=9if{xbYrKe&A` zhleBx=WYq)++PdhE@zuHo$X(R_PZiGmkW5({szs@MgOhzdy~fFol4huNa^hNw59a0 za%p;|{AjnqF@5IyI9@*sKi;AJ^mAC3ouT{5J}>0!W(&YkHE&^GD1I&uOWMzs-8O~%(%xG=))y>z|Yqw>t}c(WYe8)uk~7hew=9Z2u3 zkfB_3Hj80?b9pD#QLjk?S%)$u7tNCd*W)}l%qQ%J>}QxAUacSPnSMMI{dmZ_=5|)t zF72aucwG42Xma5DbnAf>@p3umcp@Dgzc~f9w_FZ))jd_mPe$&j&uMRv9?Q{ZhvVae z^NIHVSAxfClgn!?^!YC9HycJh(f0)a$K&f&IWM1~!$aqTj`OwLdTYy~cDaBj`;8#R2_BaQv@bc$yq9t0BJV&$1$ zhllA5pKa;vKZoWrgpVPY-`sc|;>k@qPJG<>c%eL;2ZYl3;~GLl`3}AJ)%le)FP3}Z zcAfGA;Y(>g>6G-+d@^0)^oNsJ_UVg5xGZ*Uj zU3THVfKI@qerA|7Yr5}8vp?U#t2s%7rpHBX=LH26mhu|se9wpXyZ}^sJ~ipL`)_;N z1V6UJ{G_>Em)&}U#C@MW)DzpG=Y2mR9#Z;^-YUhT(U)pSIopsKC*Q|D zR6Mvt;K#-78V+?zm~_~DKBRO`I#dtFL)zc;yyz~4kMEL7J>PdFeSXh%y)iuAsr~SC zsp}yN?C+?W1G27^{x@j<-T&--YQ&i4Ggs9n#=p|{*{z!XY)k*3mCM&XQ!?D1^Y*T@ z@?knqiK?Z`_^(o4#(kA^bh#>=mLPq&&h(hco8v`27V3dpES#aDYeIcn{Lc#=E6cUo66Z-$#B3zdP~Y_lJDlz8ZQ7U6K7# z?o%ZVOGPerO}&}ayL=uTfqXX>Bssk|!RIxe$3$163b`_S zrSTlCcb?tD;e5aD#hShhL}UFfyKlqiBbQs;`z{3&`(Ezcw`;xCASQ+s=2IPSji%3* z0hqv}lED-9cMHeqW=Sr6x5(fnH!Tu6ahxvBj8lFuAs!r%{J6M9LmO|geTO&RrQ??4 zt_5_BcPTvTXTc|@=YB(cHXH{Z;?bSK<7UBQqv5gPgm~~imE@j`-Q@PdHl>5>jd*yC zzzg-qt5C%Gk=h3teG(6KD;_&k&baWLb5)5i7%+I^qRNraM@|=~N66nF zLa(Ot=+)Yu-={Qc@=iPJF!~?cxn1`^#Wx+o@GluSmb#k2w3^g`VzjP2A66ekrGu z-^<|ZHP;`p>50^D<^HHQ>i8ucThOlC({t?ns<$_1wyg&xGoJ%K(?x_`p+ z)AJhh6o1zLJi++wL-7ht{cRt6%N`LojPMxN5f7zYt`1JARm*dCAi;o{4 zcRr6gp1w~U+qgH5|rouqf3#j;HH^y?6dt`D5?X z_U&SmBz!(8b9H9I4bm-_;^r%%E=oK zdBM}ytIikp?;mJ?nI7=*;QXsCR{{?5t>NPx4?h1^j)R|^U>qnN|L2T@uS{?pDBj^X z_;Tm*#(~L;(f5DMI9M_u{Y^TyXulVj9N0ZH*!LS}O47Vh`I!3cH)wph&LgxBIj(k1 zT^_NEZVytgw;;~-IYX{XSq?wtnbW#l!g%*~ZNH%DKEK36+AigK4)r|7IUkp2pErD; zG`9NjD$^IYq9UI76{a_D()l!5GA8XM9s4!(duHrjoznXu+Rt#lc{#>cKAJ0Vll!&* zSw9y1B-)>~QVjbtO5b>=(wqHx73ko8y!7c>#O77^)TQ&KSvGzuBmf`ues>6(ytPJY9EE`qJx5;$xT2Xpq~20 zYxBF3PCUOA!rwuG@8tFx{gvH+jY-%Z_rI6+qYoV;eC|uLNPolOW0d%i zPUHi}+dzgMpTi6BeP*Y1O@4~lF@5t|2_{;1ev5?hJY5hZ=i9tIZ-%5N=i7LirvuU7 zLyylSHnfi#{w)n8TWnS(IJ+CJ%aRKgAa}OYWy0Y z*N&g-PSb`sUm`ob=QkJqLiicJS0(kgY5l3z?%j^(22J04pY}W57b$4E``t(%w)3$0 zw;JE5`D;(n_wjrm&g~QTU-NxW;>&clkhQ10|8Cc>ZBX4F;?H*Zewx%jU)$yW597q^ zZoGit>r%$~enDQmfRHEn;raNv;65AzW_+E!kLvHet-F({0l(*I-0@o3Q2pLWU(bd6 zQLoA1^AW)Z2;*^ls85K$<5egs{8h7bo#*;yl`dOKa(Iz|N%x&xf9<`R&_LfSHGl5a z8oIxdbot5))Zfvz>^ygBNLVbAv z@Yqj&!PD)Ju2X&_@SGmhXY-zC#5K6ol=REjZz`n|&NHB&QvZm_LD=4awRb)0$3?XZ z{64$>2A!Y!8}>>2>A4+yUow5q&h8~l-?OuGWPX2@pJQ5!^TX(JS$}t+{cxP_XM6~S z@KA5j&R{*%_+!aTP51L# zZ11H&G#{BCx**jepYNH!NO-AmLVCJCWexIuy`ASrtMF7S$4@=@Jrj;E`P-7=P^Pk?Nc=0_fKg)QSSVn&_)xHxZUj0Q*3^1N5}B^_Y~rG z)qAdQ()$rEmSVV%$MP@Nc;e^tY~3IB=g^#zTyh+=pbF)6QKp{<&`;+V>HG-FC05nH z*Whq{AIIf8)^0?xod>*Zwc&Taj>qI4AD>4>o~!ZWqiB!ocd#JZyIRY6dw$=M>jn2$ z_qm^-P1}p-qcR>}A1nhf!s9&_e9n8L%9ZPh^c;uX6X5!!8h$%a-}UI;Hxer15JSP& zdI?LqC?h}a5GX7j`bURb)xu4$08|@#CAm5ir?;E<%^t8QKk=$f_Hab?L z-v+>OesY{$n$e@}$fsN`&B*0zAeSs(OODrM%D;+oY~#e`)BX6A>(`*2q*w9hJVKU* z_>O}g-hZE;S&!qmqvBYu8BJ&kJzf#{{>dM;A*mnLkOf zJnot2Lp^d3Km9!f+6lyfbo$9JfzLbf1CM_fCb?6hCA`koxZBw)UP$V~zCplWZkL7k z{}-QM>KEnVj*R@Yp&sRDV@4j%gFLLbLh*LGJf8YzQ=X24uZ$0~YeRhB`~>lxjrQVs zqz2kG`-tqi16@ciCzX+ZrqY+=lk}=}-<03;#`zp#ax7i18T=3q`{8in3v7J1vb7T3 zonNkJ;{}RGD5o4hlmmu7UT*JGIZFyEf6fP%dl>!diBzBUN0s>>IZl2$zE4*?^Hcv) ze#DC@4Uq4$aFhNq$#=hZ zdYjaeeLvsligz58cH&8>fG5R=LW8FyH%d>x zZ@=`Nc%2_&+o$yRi{cBkzTem6_h-kaYddjX;rYCn`2Ob&*3Ok$F0uEF(*3th3b)bt z?(g&X{*C*~)BPQL|0~`9v3m=XR)rJSwabrqQj3K7Npm%<(+>Fipne}3^(aSBJgofj z^#tigl4a#1-hDv%==0Gk0Uym>r(wEoGWj9jCPQvwd%qxsyH(4(d~p5s|FZWsV0Km2 z-T1jPxk-rC34s$rB+i|D4yh?aU?4^#6FwuN1o1L~Iwm&*Bm`SBj4(NKq)a06)wh}e zLSEil=T5$@Y4fjA(7)-VS~ZU!ebZKL`qmF>wZ+=nXzkyqX#T(7`Z#ybnLCpJ+P8h4 z?kAaj_daW{z4lsbuf6ui*@tv^{k|R$>c!2}i>j6*{If{YzB7d5-=AU~&c}svK?ULc znD+FsoIU1@koI_c&K{?)*75ugbMO}!{DB<&T?YTn9Q*= zn}fd%@Y(v1nvLwfE}Yv}y*~p2MF{z{0(_zzRwF;zw^HEJCp#2=_XHZdIxfdTQBU;=sjpnPQtU|f9*)l& z?Yx8AvD$eC)zf4%Yr{BW@4wtuQ9IX;dpY@LcSr~QkI)}k!t}ePxU}a+(H9*UlUvoU z#}n1>;JO!7CUX4q3O_x;^|S2$=RL;v?A|%W8`j^7`pCCWq8^;PQNHhMQ@%f;@=Dif zIo#VKd`vf(|MldvqvSHf@T~?uKac6_b2!f^@O}?gNXKNh+w7RH-;l091fE*?$x7eO zsS=k@`_ZWS^Zwm4Mo+@_`FR98pAgnhIj}y?Y+dJYBa)VIx5{owZ?88{ySc+_;MBxM}|Xig-v)t@LvKUR8{0}(>n zqHz5Mm6zKS_kR+bx6uC~y*}^tb=a)F%M=g&9I?CRH@Q4Ke-i8f=_xn-)aV#le}6&g z@^!t`=~Ok2M$tJ<%lkQ;dUAOm<(GXAN)4;u3+4Rqc4vON&ueMq5E7eb_ogPY&h{jAm>Nj>P-s7B`;^ABx3Bc7ldS4Pa>-yP)m&!WDb?e8bW zjmik>arZgo8wf*4W=oWPKf%+4`zsW2x##a`3H6xsAJ!-J0xe^f-%R{f?O&N+np;2h zdvLRQ<`_M8Uedn<(L7i47xCk#2oBHjOX>w1O2}uuufQv2t{3_K$LD8%zt*qGFG`O2 z|BQyDlaN42ZC%gn;dA;0vD6mSkIGq|c#hyV;pT$BjF~?kJT-!FuL3;R+r0b_P|oXR zzQg@%kni?$JUNsA&wb(tbN9`?8Tl_*F7r_c!TYI?TRaa?LO$OI1F0kYChCR1@8WV| zd#}Ytg4aI-d}BEa16?he^7gylg#P&t;c#bi^>NAchV-zfkRI|s&!2kqEPILceDfsq ztbBp={OU`j=g3LuX?=n8oc$8%`4iG}11d$xzUS?Ji;YL2oH*{f{i43y7}Q_$FJAoj zCO=GiY+Os1u2*}!aE-(v9UPxSzkdzVq-P(N*nPg6?0rVcaa;_-Ko=*32)<9`_Zb!= zbasTWo`GCFhpqif0LS{8Uk5z>o0QInH%gpTmF^ht9Wu~P#E99SPJ3N29|RffBE-`O zyXgBYd3v4Bkgko^-f5U`W#@K>SevfP^11s*;r#A2(ChuT#%J?iY@H{p=h4JThwDEOH6tbOe4e z>3TJqn(R?MO7^NA<@Ml&=J5;|V z_-~)7-zBNox#(_te?O_}zFl@d!H|A`-p?W2w&Uko-tURusqdHEeo-^Yj?(#Rz|-lv z@95u0>9%t#w^g;?+o!9anqH|67U^W@&CM?opTF373%j;WfuUM47l09xie}B)jLwGO z@+4pSz$afP=DrvGf$}7skGp*G^$?C*dSZOXfg!|~ zr+1~`(|OGc!Luqym$rK(9@ocEkB^!j??c>U>*8gcC!mOYKH>9ApSM*^u6_=vQvDmz z6PLS>)9FIB`@Rm~_s8_ueM!Cc{)*%8y|RQ_p;s4?dg>PhiaIL{9a!%x1)Htl&HS+y=@0T@y?1<{~hQk`$`7PEH1kC?*;B-Bf z{)9G*{1E5cOE-HkH^2QSzQ=3&!+udh1$`FRyH|wv&-abU-%sM)d(93iJw1EWz9qYL zTyQ>h*|;`}F6wEHt`7wB7~gN~?a|iz`3ygoldY%kQ9Dq?Ez*Sa`$lT_n;Ji}`%TTy zHhB~yea|CX@5}B*Re9I$MSV`?V&(GkO@JQ-#nccnzaK-2;eLjYLPZuhmi1!1K-;1~NR|~tgZ9%r zUwr?_?IG{s`4CD_Um1t(*^Bnj?$RQ1J%p^LeaY+ZO!|}611gWqPupv0?MHsEji0Xx z$AJ>?*7SWgQX}c0ok)gi{F=e^KGg?bKhL*w)>*BBCw+KO=1K>kmhO zU+i|SKYW(`v?6Gu1?ZpThtH3)`%3&fNPf@eoeH1qRXVtT2=wxPJ5XTW^);a*>@a#-Q32}JYRfYde$@u79o_k&tn%te=~dN=U=yxDzrJ@ zUyL6i9`cWR-6H+v8EIcvZJ|~~~{LjXC-fGVe<(`wj z;e6y1!E--;A0YTTK4_^J~zKyYT}decak}za+Ev z_<7E_QTMU@z0c%ygSYQE`Fk(^ezp6_^an_<&lCHns2%qA7WkY&#z(|{9wj?ZZu{Gz zKDl19XvR;-k|Bhno$&KIY;U)`Z>i%%xiIpc(0cseXma}w`MPJL=xcsH*Y$w%!N2p4 zd#y*UXZU=6C*+?Rf7il~fy$%5Hw)d#-c5o(r2k~=6Cb7g9=7#~{?YXwUHNs?hIP$wFT*mmYy%j0E*Y)@tBwn`uJc(aQyWW|rznZIm zHfkW9cf7!M-Il}qsT^K*IpV!J2lqq{j+TRPs{^>OUv3NXDZe+*sSPT$doX!YzB7Px ze}#A-LcaUyE-&UoEs(GJ)IE(@U;}LY&GgRnhVZB3d3N8u`L%ifyNvfDq`w5^xN>{) zat%_Bdd2cZe8me<_8z|bJH_ZblHW5;^`qx>)qg)H=JVlB@QHxr5Ak*R_&tYMalQlj zCB#?RbFK$cU+K3op4U)_IuQH0)h@p;m6-_6pPIc_z4iBlI)Rtx-X!e4Hrcc%HO`_*(07 z!)uU0$n(?J1^9j;=^>s1{`d5#emcMQPcuES{=<5A(>@azVRU~g2|o9uT@EgvPLv^? z%eX0lzczoe%}`$^J^iV*yKm(%0=iOy)aXJym_bHG6-P4-xX~-QEw9wHzD z(2sHdmrHt;A$|X{V)tJ7xg*w3Idsp50bp$HaXn10-lTpNd=LiAmo=^3G4gvQlj%ms zZC5MYlUoHYeR#dZ$y@XufOO$TO;1~5_(UCWp7NOF`}`FBTGC;ACR3k>q?q_s^wY@a zH-Or1UPD zzfsb(69?XHofbLcts@?wAGk}3W$)*uO9!-F-I|~5RDNPTSn~}v+qIVM+M)dS?=vMk z6|VVaE5BRQm`_T1%>O0kJmqjeC-FVX@p^~WkM}7BZXJwQ38=1pNb#|K&j#hjYu{kl zzO`E3-|O*qW%3!?YxE6D?DHZ2{uSvx9@NWn_kiAFG%WJS?ED_BhubY;=gr=c?&7kV zTsS_v|9J`RcK~;K4(@cIWPM9>aAWzM?K!yFIef9wJLoxatiQPW=Ih{>3mL z2z<`4$kUn~H80nE+G`3jF5D;?<-*0%PeVGW(#g! z-D3S`j-v;BKa)GK^e-52K1BH6y-nwj-JA76zsa*0seMnXY8MZlftRrmmQ8z=#FXdc zpdb4^EZIG`RRNQ8l}7^mfqNRIUbh>5FFxu2(|?5??>?%}_Z*Qp92X7|&lbh&_A=S2 z_-I#30X@Wbl=yZYR(v}SDL(5T&Ucnuk}LOJ;iJ)M{lNKkaPjP{{Uh%sX*2t^(&8m2 z$jbgHD=ghH>RysI_D{%pd#?V)^Wg^t{NsE+*`ebH?#+>QknWYaa({;Q4&P$@8B)0Y zZ{h5i{p~sBL-kqXhmAMa8@%E5?{yRZKo0+5^2P0f%|o0oe(#>I+c~}dK2&GwXBp{4J*J{+$xnk96js@G)6#{)D~9;rAE$_s~PW9nJX>zF*Kmy~y^lXPO_O z^Tmpt5BGKJc;Z|4a@S8$IV*Y<}TW zlP-{VtbM*uKitZ{r{0LOAyA$=<2H$X8yzFG*%_`X-^ z<32|l^=q@HX;-e!wcq_DEGdtGyCDbX>q&7AZY;h}&B3k7;rlg^#CEC zC|4e4PU?RQa9O*Ij$*W3#~J7m`yKlkRoeADy|N7{^rO35HGaILaqiq!dcTe5_fs3$ z?<9hq+a~yZ{nXbveLbWd-;-y(-al*mJ+xjU{U>yLd5@Ry>>sOg{o_&g4;$BgocHxI z^8b}6@BQEFPv$AT%dS`d+3&>})@I9n-0bpxFGQ2|_lm8j@I57FExR5QTm-Hs6W+fM zSh-5F!3R>!c4~dJFASJ3OPnlFg#O(~_apk?@0S3vZ2JO*v-g9RJ$kLAGkqMVUx)K6 zzZWB%Z(m3KF+HdLocsEb_Lxi0Y_o}hofA_wRFt2GBV7JugC;9i--$CK*h&#Q89WAW$g z04}sETY`M@XMV08>M83vJ%9`CNP+l!lppOrIIpOcn0Ngq7_B8k%tx-RGIO3n96 zcGPsY#=ef;2Nf$JYgwft560AE>t~^UhWZ@p@p1J35bj;M_M$6Ed;cv5H!67`2W!W zF0>>65af^7Pd*&Lh5hX7$j|!8N%)@z_bGA+$gkfgEnpCW@5iQVOOhU*FHv@0y7?hX z+r317-qiiwVswGXwG(pSk948Qc}UCA&*gpt<;M|;a(M*jrhR;@%vLz}i#fmFer0W3 z@b!S~9ydGZL%5aisRL*03~7tv^?H094*lXapo{c8i3K^%&p#6Ak>6{J^$KZUn%#4} z#?m@(@1HVwf_@jve_`!!i8envu;=xD{)YL_v`_plsret@K6|_0A0hA)XX9xUU3m5X ze!}0EVE$82M}NosA9OA~>EDj5@ZP~^nBK{f`krtf)3$!V*94FhzXl=^ zIY?S4z`Q};M&&x+`>cKX-bPY=z|#6&M^e4l(*9kLK1+XH;_RML96BT&KELUmspsfI z`h~tgPre3%D33F69y+7LzqjgiOgFuCI&8lzsTv*T51xwLf8FH%$rmYidXE1s_g|dc zza-}oP5*w0azDr9{)HDQci!Oh-*W%O$^HGmNV)s^q}hSc-VB(1`6?V~%J2CR@_$C` zRZ@M>?AZ}Z4_NxJ#5^y_QKz0g&f8zPZ)gnr>-(IvclGV?A6mU`hxb_8?eGUJ?RHr2 zFG^>=aJl5~MRGg5R^(!IWc|_T$n3Duk=bFR;|18^51BlE<&xTX{zArI&Y%9fKfZ9e zk2U_z`9=1}I{nc7uG>xSGhU?JsV)C4_g|dczs2|L-2cn^yZL`ve>eXx>+kjbuBRaz z2ETtWv2$qU23>DUrnSlQvfZnb*twr_gW7;(T8BNi`TyxFB~83^S!0|(Wbk@A@tZlB z-^UCDzlYWR|2wCgcY=m9^pl%lfI~kS5ZQMH{QO#YKO5~e?h!vm{C>VXN%Xxz+!JQ` zx-aeb@z>VjxavYbdx6>SH%OdRn=QTE(q~!vHI{C&^!XC^RL_&Rcjk2x*ZgeVR}RNL z`3^|nXLB8yRsDm z`ExWsyBC179h{4-XdD-CnFIpQlacZsJ0G?V%2PtRC~pk~>lM3^iNN>iWc|IOY0ls8 z4D1%?w={L+>qq|?`eSfD|4(-4K02Qt2%ZzqgE>5KPX*8K11_8I8@|k606km}^z|I( z4`U#7J-gQJ?iv6gc)wsf$nk7FrYeu++y&c*_dG;?r0Z2Vy2vlqvz>Gqf9tjHF+Sg? zc*6C}B{_Tr!}s2>owokz?F`$u1MPFZ@_Ci*MSIxP;Rm!G+51|)-n3iu>&fr&96j@l zo_B#Bucu!7HU-bgr~fyH$JbSR!*(?4bEG0s2S zUirCK(y=kvr=UKPzkDD2_$)BV0{Qkf$hq6H`jB73|8Bcq()A?0TGu!Hy(p(I(e4-} z+gOVBPuF{rZQ2jB`{cHvB6|vQQo*o3$Rl=cKD;f#sWB7*apJt7Wd`moy$aDs*(Uv`Cuo$I{}3cJlz~dPE+J z-j|_ol+Q>%RojzPb^eg?BYWTSnAF32$x&R&zoMfi50`KL90=u1OPS|OCU;x^qnsi7 zx^iwN{h*h@?OPwxC8W!RSnS`^_|1M@lw0y(=fDK=f$jX8Ko7ZJ_iE&4{j!P#0{4X} zKjxoj{3!z(4R&KKtlk~ZOcY8%T82tVR*H70+Z->)gjP!l6Oh0MV5Hda8?D|+z z{WCqmcjhh4R#JbbT3V7wPnLA32XdZuNT18Ty|s5I_478(AAa1PL$t)~`koBwxz?^} z*9kyk{Q~y{=r}p;&6;oLbCXAu?yiI{?qVCstc;{E_fG zo!O#tsQ#;^&$jeGTKaTLf5XzJNnBfRJXg}xC;W?g>&TJk;==yKbK~UKdwBl2B5Z|U zqvLc}3$>kcbo-*`;ksJX0J^=a`9bpyzNB&H2hEXmOvORy*`{$^SSo2hccoI7ETKQy zrV3pyoGqEjwl;~&1@o)6EwOZL&pRY$KVtjKIsbSa@=Eyc_pMMrX6O1TTTrimQ~#O& z5e#fBH*Wu~0Eyw*4|wm_Y$wCD8#VTR-9JU`^Y9+c7ypxbW%iBZ+G|2P1ikY8um`?7 z5^hD<9>BRDwIv7l#vDFMgzdWraEXlQXV%@91XppNo~hnSGpX{6^zxuR?or#QH^_$$RAbxQ}-_e%8i2m7|aU z9PfO6{Dwd-KHm9v6*x^TXGT*PVnP;@`alew6-$_;G>p;~OK^QBR#8t{?p;;RlAZm!uy*$NS>{ z5&Chu@#8x$k{_-g_n(9xVuxOWeth+X@WcCu*^i`$)&k=IoVu5n-t-0j{^63{AMV;l zsxV&mz>p%)ZeQB-`2XSWjSGMCsje1!fqbqb9iOlLy{~_gd0V>v@MgaUh~qc?(d5n& zAIWzR{$#^xSMc}mu3WQX*5Wq)lm0#TIk@L?`22j{fgIde=LmiuaM}Fd==AZ3<8a8Abmj{2f0!Tg zHJ#a!<%jY}XD*Ta^vO1fL;Fwuv7V>ULEZi`{Sl-oA9^JD^8_5{SK+^p>)ANdicExL z^Gb=I!u_Hb;#a-;j>GY+482b1sZ^D|WQWohH(ns+lbzb0)V{~%_Zj%T2kAuuhVidW zeq{O)_!pudfqya9x#yH}3gCW}lc)P3_+(?E;KtIA zb%0B@C|{jUmj9o*@?)KQULC-3p4M*lZzJBJOLLKm2n3|{VuErvwu2#&s0>5unV(X)caNd_dCNgZ z#qK347xWEaf8T}nGYA8zPIEvD20Mhx-Y==1R27Qr0mK`g?|T&Y{W?DPuPK)x40J8l z4DY{wzR25&^;4-QyI*CBCmuj^;&%)OHK?{NG3z2-pBR5=kEJ;{I2ZSF6Fx~(tUy3c4#|qzo-u~Vt4hr0cy=VXSIN&+h4L7LzWKT$;g5aS zTgmku{I&aY^*gVew*W;H&PQcme~8q;??8VL`3H9KE7(V&y@~NW)ca+y zqogMY**!dd?{i4kD$qr{@CPVY#BGx-H(vieVDRrooa}o>;FG-vGQNfNj=G2Wag}p1 z(sj|0jsf5c=VOPE=J?bGgrx5Y{79eNB=w|re|T7)bcKANzmV)P`u2@M-`P4A`gwl8 z-#o;-5qMeu!@?i+H+`L+c4sB|70Aiy?l8IsKzI0@_`E#Z=Wr?8clQdELi{*$YxZ_n zmwzI^f1@6K_Z_1>P<@Z_{U@qG&+ZdWbEV)qE7bb1idwXQ$MOb>KDGu?1N))6ba->L20 ztMFV`7QG7E-vj>RJfyBiKB?=E@kDX;rQd5w`8(i#teg6`mzqliI?`3actkS3+c$q z_W_)%aJ?uO-hfiH%i8`*3kXK&o;gSAt+YrI>5`;lF85-p~wB1N>%CYw)>7MRi(Gv_2dzH zIJEbNq+B|UvmmAqTly?X`}o;Aty$9CuLD_f?>4H&{l(UfeX1vZ52?$C`+$Vwd+Q8E z@sd!_ZlyQbr|r-C9Z9uA=$Li>Xufoye%hOV!uXyqH|sV3OX=^Qq49>P8b3K%;*h`8 zgT&uYzfzhyd3;&_G<(K-c5ekF`zPa&E}lnV|6~i;KU)#k>!0tI z{&~#$qsg(V>+tDJl_%xSkoC`PnjYOh+vPz>hxE@t9=+gE&mObelUB;UTKc5zn~dtG zuT{RZXnox_pFUYX_5DisV-oMDyL0`t&ON|m_0wzEPb*5t0$t8_pzmRFKVs7LQ#n?>#yqnCD}cuC4Ih6`NVxx>9^J&(+$=x)Bj@hdEuMOjr~{j zfPWCOdw}Pt7YY24qc@xvvF!*XNw z(+}Xi7auRV9|IQSdx59ePmP~pJtea%mw~=8-}j^5CjG7`^tn9<;k;kJ7UlE(u-32j zTvk}l`Enu36{B9kU)gK@dUA)bHjgjs*IShHypNbGG3?ijL;SqoGVIqY@w{HYo-F-Z z_u0~H+&wyS+_iok;vWFt++WE0`(~wUbbntc55n^K{(d7MT#kwL`+WOnou%V+i02UP zx!HrzZ@ln4;Cl)E_)oD9>Hf_E@R$5cs@f0yUcc1OQP})r5|oiWH1umpUr1LA=%W9H z?Cf6S(f#r(q7T`4ivA}3(&Ui!%YD`__gKHQek;s|E0*=k&13h=@8KfASr2Si{jScC zIL+p-Hjd8J{^j>~)#k(6Z_{kvZ2fuWR>Nog+~(OKU!;HURe#sleaWXb5YO@W`ClWy z)sO9+p>oH48lsoIGge3w)Ab!1Z|AHUe#s`5=KZaQr2g(1S4;Y~s@`jU`wZRRFGjyD zctSn$e*6XSBd>S0eysg8EY|@!lHO0FTrs*s>h*h1eBCvKA2j&y24T@2}Wc2K*YJF9GPW>bP@I5u&A5gJ+(haIFW!x7CP^>#>eZ}Z@K~UMZ zQ}FpbGVNEriceGi=K12|rk~59pYb7JqCH|9wtExk3hfa`u6p+9Ztnlv`h)LZX6q9( zpA-6gyz=|>{ao8nwac2w`};<|H<69{s%l z^{>PFpcbS2d0#i9-ppouZT%ua^GG)osYt_9;R*%8hVW;74BXeciO)z3}7%%e@}u{NA6@<+UGX^LLY{uNx#g z4r_aN8r+2)LT9q$kmRQqYJW_2JY(rLdw#&ut(G=^UkHK_aQ~A%SN%zLDF0Jk_QP}S z@4XkAeLb@z<c$Va!Ygn#DqI)<|ae$FF= z|DeDtziao&AC~pg{wYUCt)uP*d^jGnUCux1?;@>ojw-Dgpg-x14-Ijcwin|4q_<-)XYrh@^Y(7PL`i*Px`kZvZ0@D!UYa z_YJByqrNL;??rWNn}>NxO>bX)%6i)kjHjx%CvWc}q3@TW&wGBs`utZA za6Nrq3VkO1BjjpwaXt6*xOu;<$MoCxU6Y-vw|)z1_O zz4o2G?u&F_X898GZ@);_*H1-{ecZZH{3z99yf>oytK9(@B@A?JK?Mlu{SpQKrM+Kb z_v)lewclpnomgn?tZF&hQ`Q^qGmwS;{WY(@Yl{+)=cDt(`%$RxM}U|1XcOd=&3lZl z#O#UlH`%FnCB0JXae1UyTKg_)l^^N!lE(9OT+8@sau4fwex6s4pUOT(4*zJ@Vvc4U zXVqS$wx5@8pV!xG-$U+1F$#!&8CWUz&vVCY<0U$zmuAWei)9^fP5wL8W z4xe*`81FeP-FVOAlRT&B#w*X2?eU&d6UKW^4|BZd+({kpIW6UQ&oSK{_c@jg#(mE7 z7USWkK8^SMoRd7KMHsLAt4{K~`6SOvCwWfQ8n6D@CwV^SB+uub=Rsz_?YovdKXnV>!+S=K!#>hJ z(Bg4EoyT(;?54j*lC86#)2}3+Ui?8|d8X@?FQ7czL;dn|W^3_&5oL(vG$8 zx0&zX!AZz;gmU9V`NAgm>q)1d_o4mb6f8AY+$M-Y-p*9cTbGC5Q_YZRZHs>J#8?iomlzu}Gb9KChFZ(7cgZ0 zzMr@1*{9!)4EuK;|FBN z$7$cs;P=+rcbdq_=^3kiUVqpw&KJqAYakc@K2PmC!P?Pl-w7^Bd;B|^KEHK)=HH+0 zF+Zs{`~I}@z4xL^q$USD>6NO8shyW9 zMqg6C*}8|@Bk#}c6DF!X9YfDT{Zo6#(GT>Qf5i8KZbdrJKdy_qoj#hg_e*K-cW8T( zq0w@E#`ym&^vAG%RD=CvZFiUL=ZA8oJ@t98^DU&y=aWDDHsuNfh>*wc<-&Y&)b+&m zG+a+0y}q8wac%|RsXqlcO2z2M%Ks&-4SdSk3Ad9RKiBYipx-jj*uqk3FV-OD_<1bH zPrL$Dcl^8=@Z*i2c|0x9_j=B99w2kH8AyysOrm#g2gPWBv?=RW=wqjvyn?Hq1AS@*5NeuKw2KQ*ZO zZ+gsq+yOiwKNyE}Yy=(T59y_!Rzh5F-{e}@h1x#JA;F)W^R(|o`gxq;-9UoCb3M;e z9#u=DlD}ZPZ67$hmw&T9Ux()<{Oq$hE~vo^%ad>TK1jy5MG&~3Cn^`N5k!6-qIS+o zzhhr%(R#Z5J@$&Gv;D{lttae`?Kk#RAQ*&R-)}T|B>N6q`^_$%t$GsDN&7@QnLlU6 zdmY35B$o8`UEhbPRF&S^IV;uI?3~q|)K2Q{fY4DpXZ4_^IUD6U+pUt$&RL;(AnOFr zZGgo%*QxC&M*myjTz=da=5yZ%bAKe+V{+fE?aqIXGqHWZS#|b<2T?Ee{Pni(OZ>C$ z=d2!dYOJo(CV!fq5HOqzdrqE*e0~sk!*PN7!Ft}qe!fTfkyN)!xnyXS z;-6-A#`xpk@AYw^250r&se0k#koU`w4j(^fqkZ}Q==(~urrke^e&@?8QLY%-`K&Sh zh6WkmYxYv*T=NUgly@XTy2uZ=gY4I(z>bnn7n4uEUOuG!56iRv5>D@fRXN3WuMg=6 z?Oj-o<7nKV>xwM@LyVXH-C4Jrc{}NLInC}PI;Qe6e=GC%%pa@SV|}lj^_(qy{CDN^ z5|!V0(&hdXqj&Bk9R%iaap7?fXy}ZZ!IQftAlZglX&*N!*f}@@J#`sf_<@$9UsE>HcMp|J-+ANVpisc%H`TbrxT$vD3l%6ibkgVB?8$ z<8hH|)(>YZe9t^u6CJaN(xx^e8`O#WYoJ{HZ59ZY+g)0(w?S1pS(`#aephh&hG=; zE9H^}D(7_J0Zkj97l7W`!0+oFKJKRr)xP@tdDdAM0Sa)5L~{Ou<$T>C*{$|Eo^111 zyGP5{JIIF~&`kS6y5(LZl#gwG)YGGi7Z-FK4*7YE{9LQ`63>?*JNJ{_FLQgHXmQbJ zG%eGU@$fx20w29-=ot#Ld{N%c8!6vBJs%lSzFErGqX*46;rcWlJ)aqYFBW{HhvgH~ zA75{5;${Pap92{-|D+hHKjnUq&r`B>g_)!0D>C2QrTCH|(-S*)k?cGqdPDwy4zyIN z_8ltQZ}Wbd*KMbAJ2z7M8yUzF>APL(O3}j~u>CF%j-I)Z_Ll zsUQO(>DGSe-wSE7@rUC81MkZwJX=SY%$YQKDb<9?L;F)a7xb6HO9md`7~ z`lUbIsdVP+_i>wez8>h4@BjLIJ=v%BKD}Gpmp*QG*!EwYUzwggs`U|X8};l4P5bwX zU2p2W2S$2HCj-lWz7Ab+gY5^H9Z7v$Q1?AsC&=jOuHkzX=`p%<^NJ2Xzj!D1Z5E>l z-)Gzompji-(giZHzO96Ee}$Z>*;}7a8sARQ|7Ljx-?wqTy1&!JN)U*h^*?}q&#<~A zQPgbDvvN8NWbIAXD?n0Fcz>_a*Zur`YqoC+KwRGzpq@6Q{a#D&f1zIUIm@NcM~;td zN_sys5Hfn^OEUZJbZGxrzMdZ<l1b zyZSgv=IW31dW~b;o=CW4p0+btsri%-^EuxaJn~o5gh=vT2MUcbxKd>k1m(unH*eyeLV8}ERyvK7wS9x z9DmQm^}+k6&%TDg&}Ry)Ty+0h~G zZR%wTdTRa1$C>xDW`KzcrVC6UJgMKYXPk8g94P z#_5n>;kfU5M}7S~Y>WH3?w7oz@gMa1xwxd2tq1=3%D0f7aDGI6o((wJx5~8>%W$$@ zL_Fz+Bf_Tz;49&M9oGGjbm4RIJlS zE-$h1HF-eg)${Ha0qD7}Byn$t#ci6OZnW`XjkY%}Y5UWy0xt7@(oMaS7`zw#E9yMS z{ZqH=?k~Gs{G5lM4^Fk(Ob=WiIG-q>9_K6NJQsEO^K2evcF6CA@pIHEJ}OI!ou8rH zs7J(y*W|MAB)wpKyNO-<2l2VxC*HpXoniW00o}uVDGnjMdZo~poj00q`L=JBR8}Zl zwr|p5X>C_hSz>9^mr9$ZwI7D}YaAebX75PfPNdndDd~_ehY7b<&`5thn$zQ}pyS~_ z)0&{&?&lHzJfKJ((|LFDeqFC|ez<>-?9lcT9%xPs!>%#JlaPTB`rY!}?3&vj$JYlX zDFJ>R+QZoIG7O4$w-$T*M2`&<(kavko=^idXUU-)wF$I zGHESo`dsCg`^m{{bWDV_MWQJ4@3tvi>i72clmsBHDBiT7^`zHzX#R4e!{<*eN@qs5 z`MF#lM>B7{}W^e9~%XZg$Nb9{cziu`;-3_Y8#<$V4}|DuE} z-&Y~rY~oo%Ek?W%83_Hr&U*XtpK*rY#x3Gui$gp-2bwRJRFH{~+Wk;IuSutBeZJ0- zPAv(X*ORTwp&n_c_1_d9nI>SUCmcW64qEn?Ql3ro^7(xi;y?eZ&`)bm*iR=QKNc

GOV{n14qFZCNH*;SnSzz_r1$5;?GubQqY823pS7U!L*_tyMHu2U&pib z;u4ER=~>#p4qgVuLugtqQPg~y#{mj+wUgs1DPcWqXL^?Mq5B3x^E{B^%lg6T z){p0CoSyG#EtmCooA>zmn9Npud3_sRW%;%*<=;#7eIu7svPJzJmjm0e01a`!2KSO2 zBPRDxaleqIbzI;&BA9I4lm5bF!4uX8v?IQMbOhzrPFW-J?VqyBV)cLfr>wAahs8Qik8!@9^!fWfzQ56P zIkBT3PEf|U{Vq5DPZ==0n=IaF@p_5l2~AqhE-5DaGV4Ka(-oTb ze%{of=^h&bdvEcyjJx!q z?&~L9Z`}%d{M;J956F7@r#xfv0gLxqJZSNDi?>?*pu};*bkSFD*E--L3E{j(+HdW2 zyH~lDwF0hF;~1;oC8k$sx=GbIsywLa^VVye*gkU8c1@=bXw1==eDHO)a`gWRKggdF z^Fb6jT5kBK6GWZaVLWF#JbyI+{&a#*0$-$+#5@Y;Y#Dq%WgVVV0>gvM1%CX0kaAur z$;{twGP|0Xd=mm93~$o-VpKlZ-n^jcJ(^Apeu3pTTl>^F-81=|$@^K0k6L`h5RX{Nzo#tLw%t= zYI+MY5qf58Ty8LYCZ}@o$0wwm!8Mz|Fg&R6Y{nAci5p%a_~$jeO72$<mP6Ch1j8r;nq_jYLP{ebn6gXM-F2wlzB+jA&2>1=PDFshxTk9PZ$ z*f@3j?DI_O6OOIRJYjv#KY!P&z^~kDKxbZ&e=W*jZ#lFOicZhz( zjnm~#fVlA<>HB<6JHmWy86dt@_VeP#bHv}|b9i*f@09Oy#Eriy-}{L1{(6(-zfI;3 zapOEWITAOPf-U zmMcbg<1hG$=jXn;_PiLW;F*D<9u}Ln`-dk{k#K#{`q@4p`UaN`sU{ci08R45VHpNPeb@;1pb)WQN6#H z<1vb29M*d%lDVX|HqQvpV;(~J;Y;PQ_+dA}Q7lHUl??K8K~DZLo)n{tvgfbMJ?DF? z#Yhbj%Xb8PpqyVP&-wPP^7W&EocWw5w~CSa(JcQ+AP+vDC(q}zxaiTW-1BMje0KKy z^c?;+c@86jK>Xj$(Z?Q~y)TI8U&uXgmgm!1T*}{@({q~SqVzU{rTmRS zd7saduHCtM+2W#D2QBxm+;eiw*GF0YH*#{}`^L0eXNLB60WuMMKH%%nolqXII@{-` zoyYZdCw4WQu6C>dL?KkHyls`-I`7S)?d1rFc?Q?eCN7XaR?ggV!Lx^!cn}Ov&N&FQ_X6Gd0 z(@3R0uj09{FBAR|!fWv;U8g_XU(D*iO7W#j4@-Z{>Q{BCoo}R)Ads)*hx7dbc3Onh zRAPj%pVKa|{gQv5#_mUuzPlhx&i9DI_p8bcijesXlq-MoJt79$mmmx@+xlX%PwmN~ zvsF*y(@+6|-(wP6`H(*P6TW^q{HS6L_W{3v=YGz~&sX|6uk?Q9r>{Tto1DBouGfBk zDSXbFe7>B?p{n)ME*znw$#eRt=F-&;ob@6LrhZC^Ayr*^l>GoyEorhT0|^vhlw+Bbuv zJ=~k4>mDe;D13Bo5FD@jnWU>Pga?fbJ=Ra-hIdFhZqR#-fXj+tuG|n5X_;!%Fq{8ZHrkuiUUo z*SD7o88WU+dP~j!!2OHzAhGpqf1jEC|9HTcQ}IXkexEJSP?Wc8z%Ro~KF@f#R&Tmc z*8{@&4fQ9r`)mlm{;Q_6K$$L7Jq_Ux2)yc#)9wD6%ZGR#3dXx)v|b1dpMPV-b5(ek zb8UZG{Wm|KPX4S4+cVSJQ`Ppm=wIW_$yzbQ@sPDJH& zm2J0ucZBsXd4c+I>|?e1>-qCz=?7Fi^XJ3vf3B|*p7Vyw|lYn(jnCANAS`!^vjN&-~|ZO%wmygZ|_1gYz=r1+QJUPFc&Hr+KlP=DnlZWtw@n)^3X`3Xoc~1Dg%7HmpN4!m+ zr`xrh%Q>WnYl)uk`_TT}_w#)`BON~r_*1d{b$>shlg0z8R-T|gI+ZUI%2fJcii({fI~`^CP#PW;~jXfe|F*E%KyozP)`KtG?R>KP)mmyiM1>*v(Khl?iaD*81e+Ivg!u|HJ zKYRrB#u1o^;PmRMBipU>&ai*U{A`PWN1?tPMV7zcoDAxIL0P-?*(C+qUL?*1^i%|CESnqb=jm-&jIA|x!rAgMC!*SACAlbyPcOL#2( zW$QWFcN2GLKTUQYHNB@bNBdRn&~Huus`@;C4=VSaRMJvx!1mRs?sk3{y2s%Da@Q3$kF)vDux`W2xcA=KpxYX~4si+P`YdL7K8kba7CSB9 z>!bfmIJc{$dp`K;&$D)}2M|Ih$fs$GCo5g?WWCoro;*+de)kKUj$H-a@nL^jh;r_a z^;C3z?tYEmKhz008kln7m9ihiaxv1B?^(Hd1}!P+{Y{W|Hs2J9BtaUywC<>va4*!Ls6KGN|t;Jp3y_B9@c{&;)+oWk%%AuH2^ zMBS+D{=4J?tv9(qCrF$(lmD4~=4g3eS8;!u^t>NM9PY*V&%aix$&2_thmP*_GyOfJ z9ly`pvwa_1Hw^V^L(qRt1^(s$z8~^r@cKNaUUaC1HQ4H9bvhPi3R#*{g?X5a2F4RAo#dSJ99i|XSM(~o@D-Q ztALCCz60%af5iJE>%9c|#Lp@+|5w!^Do>_XQy%)Aho_M*aGNDNo6i!@^DWv>RvSKQ z66+xLpkgr3XCpyw>1rziz_2do_%tzByr&#BaZE$UB9 z-rm1Ek;i^`OW_=$zg+lrK^VUOLx0WXN`1IIv|mscQpWampN00_Z1f!qxXHF z_s%K*c%l`kLVUPpIa`M#zEkDjd)R(sDe3(2m$mnQA(UqF8B=T@Kxzgg>MI zzNOdon|go8##_Y8uDtWMJN*3ZT1dC|*1O)3PEo&w_fQi*&ml7o+adbn{2W7`l;g@A zU*3_E*Lz?YCLKw{g_p+s)INw?}RVeZ7J8cCa41=O)G?4e9pxB+^YtAf&b) z?)>-nsU0qCM;G9SODqNbY}451RleT3zr7w})-!*sr;R0;&Y*Vp+!UON{7K9i4q z2WC9@1%UVUJJ(`&nrWUgezLi??*ED`Do(3)9i!fE1R${*qsRH{^duKryC!J4Tl_qq z@yG4d)263);k-XXHZOqPS(UR-e@y=E5U}hXQI1!i3CB0!zX2fhhc*V~<$PC=ro7+6 z@#!MPH*D?jbB}SuUx|DO_Zak$bdulRPux!N`K|0fTNF<@`g7C&e~>uC4;^GkHW@#A zG~K*e<3;{mf*$2>ljVo-*Q>42Z;bVaGvEYdpMFB@H7Nj1C2;(>YAT)Pt?DMxp z7n>h%PRB`Ydk8`#u9m_s+o|gksbxaXa^sNY`9RMxB7a1V67rJb<{@ z_C5R12zp6ZAwIzsi=|n7iK|DY_b0{b1+d7G&)ZUvNrEfM)W%{;O z;Y0uFn^>rHee?d4oT>U-j6NlLmmgQ#CpD`*tqcmn_ChtHO2@ViLH`k?%DU+}YuG{! zes5C6vf^7&u|cp1*SSmUNnjk`B$%*SAPG<=t)`{0+A@N*I} zpGUtcPtg0TIgjx`PVT>0GvdPk5Y6m#0Z)aFu`eR|s?O3+ z-*#iIpK@M7(Qy3yC^kBL{l)d3`F!Qn`(-x11^9j?hmU&Cavx$j8(*m>CFIA2Z>yaN z%Ac7lPYq=Gp$`45Sza3Tog}L$^Nm%}oTzT@dT=Gp&!+_{#EkoP}{5W%&H*ap0bMImX`-fDq#7r)+-Y_mahvPiT4p5F*5r z^x#pt^ueDnJ*?u5n#>MTo~Sa~@Apoq3)1qe(r_WK`Jzd@h(0WaIJ`Z7&7y+&hyKZVcP9?z#9 zG$9a*@oIx-egT2`jL)h9oqplK0f z5q%(&c)Mr5L+gKdy~Kpazi9t@{?+m@CXF9BR<4^0?`!UvwLV|}2j0j8p`7l^ExFM%6n514g~}ehBr3^nD@+_q(W%eAxxKWJu-V^A^6|)rRMv zwb;+OH9tx!v1bUrUizk~Z{oaZVC5N?Gmm!I*GZ{YC8X1(t3*DySK?=E`PwPZJkR*k zlXby0r0)>qMtZKr94gFT55D^RgU{cXdp;HI^5=ekG{0NZfqKT$%Vlf!n;q2n0cC$g zF-W^D4(WIX^|1ceqW)x`+8NxlsruJ~$`B}CDR1$YVXkO*I)U%Ry(8O2e3_p9`B{sY0`!dU7&SG#cK83*8>|hi0fx++Pr{7;fy3bkOy;o9y5HmK3IqR5`Oks+;#VNM6ZaCp&0$6q&xAOw{C<_SXf*M-zvu5yBs*694B64a^L0S=_Xyp-bPb{eCe2Jp=LezLJ zeo}u~zn_;1-!RJMD#U zG>{KryV(z7_h)nSz^2Qj_=tN;q~E9*q6+kaVF6Ie(&_ zm5Vk{GJdnH@TXG=j0;~>{uuvU{=-Hm&eM$=PidEU4-Z4Q4khie{^I+oq=WEJ8~$+K zC++DFG|@|+_gQ-yKBDbeu6QSbD7M$>OqZHnrqM>21Ut0mXRzzLEe(FMAG_b<;|b-- zBDC}WYZmZrR(SVYnEy7oZo>iI$s9int{$F8a(Ku;;<-MD=fFwuJe0#jP7u%4z?1AW zeH~gU`t19a_>Q9V_eGbIJD_{HMEE{(xA4#HGsbVRo9V)51U?yxeon}A;YLgEwe%)Q z`?;=pg_{JA?|0H~VEf{RHmN9YKYX7p)El_=Z90w(K9v`g8zdb8$VyR!D2Dx8h0u2&g5*NgT-N$s4v58?+>p6SB}MDB5e`Z2?Uq*m=V`Po#GWOlxS_JI9jOu52p zvBWHs>;9GV1VLQT4w}gmxgyU%e$wA|3An5ujgaSEn(tR_kPeY2{z&ZdT%&NyroCT& zRIb$Yo{1(;#3f|8KT}zy&wamO_yJ9ik_XC(JRdN5BF*4_Po@u>G@tW}5`Oksoaw_R zlc$1V-2ayFD{ioLkLCIx*{S{0?`>Ihrq=8IvAyBhf{f#H6`t$u(myARA;%7d3;QSS zrr$H?>#|w@97~Q3I&k@T>g@{sC9%gZR*q;UTROZ(>0Q=xi~RU6BgY9QN9$*Jzd`z! z?}IODF*(lH_O(y^u*$Kb>2-K4a;J7Q}=uS&Rzee=OcWVA9`-*Y^&HOZ9|5{dQmjacNMA05Zb?xg4eeU=9 zjoBXoMtZxvKWee;{D<#H_`P|f`lGeC%ljkJ3|W6Hm>f+`NmbYLy0*_TxE-uM>;G}2 z3n=)WiLR@_KBMbLzHgAX&j&BP#{5%_eg2i~HG4eq?SkL&T?KsP>u9_1TZZRd5|74H zRy+%pE{=cHuhDw>2ZraviU%+(n9&nmqj)yd@W^xH%dG92<+<<2vL1R0z2;9QL*|FJ zAQNHHS^>}2v)c>TNIysyZrA>@Md954OBe2y{96CeiBsqgNdK_;R5;J4Kknz)CZSsK zLuQ*Fa)FIkbIcC`lSx@Nf3y8P?tiIf2+{t-#HHXbxP|K_X(Ql z+Kn1>oM6*4Kg#Wftv`%fpSV=Z@!cARaQ&@>bT&T1pAxlQ)|DS_O5Y|GkNeA_avCl(Y zKeBnKtv4QQQ9|4=&DPbdpC@}%KKXJ!PIy0UFFYsvbv6Ch0VdRQ83%0K8AZSKi%kD7 zH2t4v`v1#bzZlZ>i)5$i|8jCu*JG9-{w$cu_=_#w%+A(r*xr%PSL^c~5{VwN-#h<( zo*GY_p>UfN&d*D@pLEi74bz`&-cCmk;RWw+o8Gf5^=1D8C=fzC@hiH&>FXNsC;8mz z^l=aSJu;qz@}xb(cd4XbXY=?LL7S~_W$Rdjn$PCQx`d5$FM8buMACki3$`vnqAl>} z{^{1fhL4YIANauMK0m3qzaZ-plU^y<{9MF3pd$;Ld|hHt9?QCttV_Jq_5i=M$M>Ui z@=EsVxU+x0wQJG`wO!X49bhcmmG-M$PKI<|?(JN3>2#T2XLiE$%JGg}u1U)IyuKK{ zT+-x+^aqRYne#d!gnBLc7T+^>rsRj?jPw(e1J@T`k0qdFNc9Wrhq6xKcE{;&FWe}0 zC$ux4Kz|GM@uOg1%`WM>oxi`>+QEUdq({9U$9 z9rZhbhIBez?yqrOj_p3UUC+fj|NMLt_gh!KS7`v4wDTT}QQU9)`1)Et>7gdq+rNJb zK7s2g;pq3&gS!)W{XD{WaKB;o?+woz059Ax!FwooE^-&@C%u1`gU527z#q-Qf6(Cn zE(h=UkLBS1r@>cl8p)4~4F5ome~%jc!W{g?2ERTB|2qc%vm8D29LdMYIrs+v&vBM~ z9*>Xj1DxOg7s|Vo!}l=Z9sx20*0&`0{C+%7Z`%4ipATQfzlhlx5t5Qb*l+4bNx;n< z5IFx{DDGL7{A8~7hj_wfN&9@%*FESjQ17$z7)Ud8T7G%LfRx+c_8u)Sf7Sn`oroLX zBJkn43gWAG9)kU$UOua=mya$~H=ix42VV;E-JZPU^A=P#gwJM@R2pXfuf zg#2#o%kw$*>t&qlUib;st15HVpFf0gjC#$$`nMyd{rdn6P&kg>jCHdR?spAtJK;97 z^yqzZA7`4^>T^He&V4gEXMlP~oHLlOaK287_uPKYmg74Xa?aq>1#}LCkS_ZF+4%tA z?ZES~__(a&uWi1s@dH#g1g?|No`2Tj5WlSJZ4ofx%S9O5-L9?!aV+QiB%ihPc;^F% z&*#ezp#2P;i1X(H*e=RpkbXy1;W%F9=gq{&_U;7;;onYq3>iG|z7_q|{mNaFrptbu zr~N!2$A7+m_Eh6ExjE186KXGt%y-}lR|H9a2gKqdlh za`d?;U+ep33oPAiaBLr%4L{rO7t(Qb9q40y9Ct>XTjijRP{A0+KsbPmm`9b6?n5SH z?yDlgI*^`sXfOO!_6KFdewSPbPpu}+ltqA)2hCxX`jsCz8>Q8=slloNKXHiFe%<~x_gQDU- z1S!hSXUtQ=D$qZM${RHP&vHH^*{%GDqbr55WS{aY*`xf68+1R}{i;mAcWOK6-^zN3 zt$StXHK0x8gTG&xRCS-x*FO)oyi5>e_DRKvbuG2WF5iP^{F&J$jor?Ug*Th8%vJi@ zC-jOQv;R@S;|Vyti4d-%3;kC}_6Ykx`{C!^*-rMqimwy;I{G|aC)_^|9RY#+_iT!P zM+8^%7<0Go4PacX&{rQ~OxX_3=f|*R37dd3&Tikna6gYCGb_ z_v*g8x-+t_!so;HD|As-vtciC`ZAVW4z_&JpV*KMBYEW{|;}}id`P~KDMk6EIME3-!8A_ zD->@3UCZQ$zmHKaE|+vM`kKhe*UxHrq}pu!XfIr>{R-LAuL^45hE1;7dedC3Z_Igq zyFT}MzWXPvpEdrX&P#QIE;cM~{C#Oix$*DiMAf2AuO|7?@Z7% zIk#U;_bEKbWtfE%^b-isbGhCl6i@iEtP}Wpgx?$P^WokWE${0P&5I46>Ho4VP;><1 z75qR>{OljpcltBe@LcAQ&2!9-yT5sG)8_~dJM?jhy}x*Way`iRpSbt|kw5lVbo`uR z`wM%B4fMbe$-ew{t{u=0IKPN#B@BN+6zsGrbP>-DF z=+S!ecnLoj_(D7sB=f(W!y|s-ICx%}!voR<&sTwm@82=_xa8v))|I4xr3+W6owD;d z>B5zk_V>D1NxHr9i0)@Stai=)DL?P-b_MIWTHfV3DAmjQChh;MEA+r%Q-|e4O{ggq zO=AB0W07C7OY0qet3FtS1CI>WlmB@3@ z(uhcx@27MRX#Tb9YR}1^NuW<+;1zs#>+@xoVbX$7vGx2tXaM_L{=7$p%t7$?)_U)L5p7h?SOedtc$w3S4MeH0QGr8Zw6!>WV)R=OAOMSV=MLpN$ z{WsaAcE|7i^K-;5|Mtd9Rh~A!z8HDRxvm#0&&E5Xy>91RuS5S##*r5*PY9Kqc7Jr) zg>RGk{>#bpG9f!V7m}S*xBZd!34g2mEmtU9O^&=B2jkLi9iRRDU^2K@`jdZ0vepl^ zyni=y)ljQ1~AZf<|GeyH~4znt7mKKmE62xE)UzewB(BTT(?KRj=T zo67Jn1kE8Ypn^m88X`1>;JMQ`xPdH2QSij&p6X|X;JC^rH zo>nv?=38gszc%PnkMs$n|rn1aDH(JqVV!~-$d}crP0JOdOXP>o8*#o( z;Nu3fQ#Ma2>Pjc<)}THwY*xNHKfny~!`nCZy!Je4Uol#wd;%ZOXSu4@TekJ^J28J} zKK*#=q2EjE?dSYW`2TJ^MDY1m$cGOKACz8yf5^)vLtCXC9M6gWvldftC2jE+=bR(> zv-#SN?NV;p5^6X4hxw!4pZt7i#)r)U79HHA=au|@Z|(I&l5^!Bx=03r4Js~(YL?Vh0Nn$Fs3>xho$ z;3ge+{2Z2_XCS{@QIze;znA?9w1?~4W9`Fk&+QZb5H@AJeb@sz`0p9~So^StbMVg@ z{8;<28*}pbrooT354$P{|5bzkes15JCt>RG=PQ8s_1W?G_$c+lh19yU+)DR?FaQ>Jo-M(`g&B)gde&3{*=$}tUZ4=SIcv>fd;3y!^SEW=o|zpW_cpPD?S zfj!CJ6A1S;kzHDL)vpNLZRgIA3gSsRPxf~8;VJ7Iey2Q+uAQr~zaPNoL{KlErnX)_ zTU;-nbk@r+1^Ih`l=COv?=a$h{wn~4z@OQW=8xE4wtVu5J41f1hf+#+C+&&TfV)^vLHGooMqebBDUhD5(Id?X&>j+-_1`CC@rzAKvAccHo( zpOo_H)f*M>O`9~H*(!0f%~RQr1|g5;ZHjjt(rx(pS&J7SUWqivhXdE+UMaNu%}@Z2 zAG{xY9iEl&-|r1(Ii~yYpK*Ki>B4o0?;s$;Iy`4nTpwp(yxkt0J88lg%8=MN7w)_5 z1)bsg9^rhSgY+B)Jt6$|I`GL(FT|5>vk~0bEkuDrwwztIw<3B_{v)Je|2j^N03IO#Neivgd%L)BcjgO$(5T zz%w=sJnu|6$`${jJ4~+W%vAzUIih*Ee|Np6!GFS~{VOD$KB@e<_X%Voxc#KuN=Wxv zjP*-_Z!f$onhF})3voo%91EU)JL{Q;)pU~Te*Dw;O^)$2wdCVB;fm3G{3YHqqmE0P z#>Gp0+6BCW_d`EX4_GYkr<1N-g;|=9JU%Z*c23mBg?zhM9;_C8&*3-I_$T<-zFqhp zfaK#hIyz zYt$=-PS8Psbm2MGwhl~?e2Xu610EvycWch0QXn*6rE#)zK?_J>IF0Om=->$Tl?U2Yk7K4MMpYhwlmThb> z3JMl}U=u*b_98-XS1V~PuaUHpRGLTo>&;LIl&(6%5nKNh3oH=vm@e3Yy z{owkKd_z2r;GJqZhUtRC$`8T8)!J_uGjygu)P(({?czF=^25>_2b6$ECfzOhfrN)D_Or)fX1!EnK$rDfsTTP%K);$v_R`wG{t>BR<3FE%Lu1`jL#!66OT zg>Ww2;iTpv=77@ju& zTYX37YQ^C`s9RSD4?DbWm14Xj7j(*x8t^OW9vo777L?q;+u`frC+g?Mxvf%;>5+8~ zPqXtkPSSHi3GaOZ$8|6{#rQXP#Py>ae|F!Xan=_EzOvuvqj|#5n&f?kc!oQ9_g}Cm2n;u*1@TPvn z{TI>^Rzc$|HOZle9+WCaW*?NyFA*ZiPa?ZwIa8Uc}*k&C7oX1#Sitnq! znORkupELM z&g>(wn@M~TvYpQKluACeelhw454rXXKtRBmd>GTNf+TzP-og<#U)8PA___i08&{BP z*dFCydq0DGb_U}g(snE^D1pe2&!N5c9`iBBAA8(9XXhh>1DbCSi4Et}4bqjyU*<&hI~70e{%RPh>ZGrUL$egP+K5w7Wtdc+kO5WH)N9fd7btpXmJl_bTxD zu!Dajtz(3gC0{OvPrHg&QT_)JXLcs0FRe(wi{;^OLq$C6VYyr{GW`P;c>EsX?E3?O z4olc+ec>p<1Nofu8&|2|NLK5G(BgGZ>G*QrX)j)WLiyt`p_39en4m%)a2(F+rPv zmDvkkq?`c#=on;@o;)<<$0Esc<)Kp_wkvszPJ5(epiGu4#RXDw`|$mn#CHAFh~Nq{Z1x( zbE~FGx~&t55B`__DLaooPr$uQo1O=;`+1$H$4AnT^N+QCNAL~~92ei_m4v6~LssIw zd#<)Yc+xZY;IC!PO|4XSvVTr@dzWSJ@|cFrW> zzOxay@4yx>_g^F)#Xau3oVR-tz7WkKpA={4_n9jBGB}`onRj|nanV_l&(4uqe+LJ@ zC;fhuoeP)n+`iS#8a92VvOTyLFZo)42Q^Up{_jzQ=~_T<0u(P-J);KYWB88FJUuJv z_KtexI5GWsj9ns-Y~lNg_474c=f-nzSleOpgzG%gzu@HN%rp3Ud}&$CY~_Fai| z%FBuLL8<3j$FG}|p2zknquIThx?8otW4Ee63Er#p4z6*0z4K-1pWqsmPuA~sjj&*#%oi#Ti05wsPm?Q#r^&OxeGe<#M+9EPkNOSE<@&VbFkfGzp(kB> z;|k@gU|9K<{KkAwI{zEjpuunjrw4QXBHb6SKt*ujxtu2Dzv3*3#{Btd?UyDENBPdL z;JXil@5bZLRTXfz11?#m1@`$`?ql9M!8h2XSM<4BfxmRM_&b3m z%iV)h1~K?My|W}tK4q65TRB_c>Q;&e`kf;`tQ_ud-x{so;cMla{q#2AO;=p)i*NO^ zKDs^LG^y9xS*jmQ250pjTX(92YqR13AI?T>kG9YDr%Ux{`N@Rx1@SGTm!roXZ?$W` z(xbR(la#yD+aNyiVG}}rMi~El_8sLSi3ex$jq}b#^T>`0{@Dju!mo|ck@eM~JkA&U zD&Q$g3Ey4;f3AbSzXE;$u(nS>GM!lJzIF>pX6vw&yWbFGG(Bijz6<6k{YbZ?(fWWF z+yDFcBVAIU3?1bnbK3r>?PF73Y{cJ)7VFvi&gd1|QBdgpGfVu;b*hi@nEy`@Js$l3 zs=$jF6aJ5*@H#CD-Mm?)@=Y%uIe<)X)NARQKJ9kI?_Ed;^#%gHNxWA7n((3}$-ev4iO%(b8tpLjpT&2usHtah zZ*(5~Wc8iGIjQQ?Wkza2f1!E!KG)qyjbYv=mq4zd%(07p9-`HJfsDHr8O%QZcY z?JkS&knCb#DT}|?#iP8k_z!A)3y8^jYJCm&k+^V$Mf#pVpIiSF7X6F#W#3(v{*s2< zEUf21`!2Px(zvhR!n!V^{PgfHu*QO(&Yqc`qcNmE=@RmT;Pcu^;n_b1Pun}#VbscP zL3yZdlzdHoBmdLBYV)J57fA=&QCUB$WIl#XZ!kV(IY{zsf3AP3?n~~Rs{5(^Q~!1J zcbFfA(2hDEKJBJM@bSz<_+7Z@{>2X?_}0z=5L`bhDZ;NoKH_itI6G1Q^%!EgL)t$# zEF-m`e;%^^+?ym^HvZ8ExF;a-Y(EK+vhnZiqsG@Z&N;r{3r0*zZ=j#t_-^l$V&pu* zjre&K`0azAfaXG1R__4gojgFDW%9uBh0!&w>W#=BfQI`CW;driDU%DT?uYhp>$m16 zK|}O~GPy7gJV@+?@C>+bHu6`9*BXXYF0u$)Uk%~6$OZTuKV#$psffsq;;17eDFnmT0j{Gn30P*BA+66@( zxN>YA6v_j@gT+N|h&*uZv2ikl{A3-oC-qO&b=uCUKNTGNr;ffcd2m2m#M%3&5qxdj z_XCeIc`!@iMV}CPpfs^@T9ONjN72#aD9WM6Vejdbjo0}Y&#t{3*K~ztdd{gZOYM>$ z(ddxw)C>PAs&^vaI{`!aLG9AMQ(c^)df`sc2U*JWKr|UP?^COnK=n=_ZoUvbgw&SVDdZ9SuQHhV1 zLwQnk`-#!`{SvS99m{#-pGCeKUn*t`5uvc){bXfdmg9SCGDagg?|+A(RSc7 zxueAfSNR-NE{9v<|kNfWu?gTwhgp9M7q011TYj>8`9X4))bER1D%e9h^a3><);S1qrIk*{{ zw7zSceQ&d~C%E)fjI*t-4=3MMs;@Xh=^Ul&9i-z7?T2XmYKebT@j*L|>b}8W4 zKh>vdyI1{E?LIz1yPuMHYk#yI+U^p)dhd$1+l{w9zdT(iZ%G&W(fXeuJ=zcnM>_P9 zu8Wl3#TiQ9;^hvHh7umT%jl%|N6U?ldyemNK6rUde^$za^8Wwc82CG+|4&G~op;%T zbNv_s6U%|k(oAXR7Up;MNt3tK8xf86YkviHFKf|rQcrN2<}WUKM#HD-z&1I>{Y*OA zQN>p^6MU%iKydIy$!B_Sozp`&pW=V$quNf|aOr{ruHG}$juITudhK1clKq6*Gvo#8 zV>zkGx}jElKeD{E z4~`-FX_vk&N9m@tA_tOh=^xvy{4;Zo?qk?_M$?C0pKevNzi@tPge-d`~O zGJVnNi}ovt)L5nWqbvE#;O+ioDt1KnVQF8a8*%Nn{;>D@?VXaaej9&o92i`}3I?=e}{Q6t7T_u3${K27N$z~B$_uw& zZ1;ri9V5aKG#M{yyIsD7r~9zvPdcMJ!vrzCGMKJ}3f#IhI7{VH-;K=0b}2r=fXWdY z|MtD~*K3#ELmzQ?S^cS)+Tm>7*9m&~sBg&mVY{kg!dFI*f}-IC1wxnP59vtGwsx5v z?I`+`GW(P+EfU;^{ix&8FU9K~ z7rzCSu%47RS0ISyWtmccr<^^K@oOXTMn`-YvCZj@rZ;3n5!&OUDM zsTv=p+;@v6guly`b4cqe<pq;gsj_JD~l* z^(WybqA&BkB>6re^#tyGjnOyyt{&HQMsK5Y$~)-tDV{;752*ZNy;nr&TG_9*51;Tp zD&_P!y{7MU9Uo?&Nmglp+4$yq9!?zWpkumhJPg=1&5qmIH>tjvdaj&>#uoSM%URg9xqqE zH#GM_MD1N}JXF?Kh$)>+&oQ}FIi8C%HvF6|;eHXi zS!5cl{h^&Xy-C{{-H+l-CFd3)qHG_T=Raj!PQn0&D?e8i*mT>R!Rpy)7;`FFnq?qtKYbi1oT+*G_;ri$=`TblVO}r1I{q#pZ zNGSNN;-MbZ|EcejMZ$YB0A^T6i^6i{FmtlX2`iWDoswJaZJX@$Sw#K?>gRp*l0*L8 z!~*&*{+{Odz*-q9;b-p>SC%_-vc6wu_;v?3~31 zP6$sFuG94k?HxDI548v;=; z0i5;g%EW1+&msf6B#+BvmV>=oQMV|=puGNOg=hVB#mDVNL6$1K_* z@d=!?p{vB}iTIBs-PTLVD&5~2PW)KxVWb!NFqQa`(1YdwexzOa?yclEc@Wi0T0yrx zQ+uTx!#m+^S3FS8?cD)l%&i={oP85O(E zKFlWv6ps2H=@D(;35Fx{PbI!$kd3kMn~AtwQ&3opzvC!e)03 z4rsrGdaQ#tyE?vKBo(kf?--{a@UD}jNAW-Y3*sOA3-r^&+AleG&X(sqq&?0L4k%r} z(V^%4gF{bAdjh97MDZXUE6-2w!FgYf>nPkN(sQ^($FmW}JF?P$xc@1>ov%0kr2Z!3 z%B@qwafSG@apm55FnuT5uf%WX)ZKzV`4uFFJXJ=cU9*hdk#dk!{{A`2VSdI32Xy`_ zHn??)vnLk!D4mM-KFUFDFYP<*FY?cE{5HLo_1_uk@1sbYi!9uKcr>zq!F>N48_C7X zmr6Uv%$xJHp7b^9+q^r3pv;@_N73YwPEGH`Z?+>T(iin{@P!WZrh{va%!@!@>V~)1 z_HWaXc{R-LVcxtJ4S_Rx70#Or6w30=yw=T|gBsrgJcw6nG6W1C|~9?CwCM8`6+PVC=X@c zba)tk;k;QPZ_x9JDH&u>=^CECBpEp&r;QY;& zQBNqJH>V>O{o~e|;k@biZ)M_4H*ZeYeoQP9y4!dT4l4grt&(vaZ;i2&|^C~7UIJWBz&8v>DOrM!}UOivR z9no&WyPA%k;2Y92DsL(GqH^#A!;$%|8R4Vgd#+3Z1yH`$J!AEO;^p0at%=DBFOtT&vu9?<>U@#d{ntUoeuVe13) z)@tFO@c#IX(roMxSIh@H-F&d;xWGr-&32LQuVJ9sd|-B1(l2V?A{=F429=}CDl4sw@` zgiFPB#cB2!ie<1i?kA``w0-p4ETvcOCLRCD_*9WkTo<#b;HDR){!Y+e^1FMcw!e{E zuKCU0mAg^bCstl6{!`H}IFHlWIyiUJKWV$(ulX}KE1hmwq~}*|n4#y0+Ar7k(GD;5 zyZc48%d|YR9|USnDAP}9FCo2^mfHM=bkK1xqqE zN5dB=o<>i*hgs|7kMTipk$_9NY+-P>h9~UjyC&*qr*F0^oq~*(6CF3@?Nqq1ooJV| z&$V;gt$I!|aQD~(*Z+;vwE;Fi+kBVs)X);PYfL^RyqzPO7*6#H>RHl{v$P$yZxr_9 zX&OIf98~cC2$>Vk@C^4QG&&sTBidb_-TMmnTZJD_^)izc!0x$HzosNe#Z&>bb*J$+ z`Is7maWnXh__)fY^5{6V1zXXio8j#|2hq~kdl)_N%y9{{}RKPgAK;AZ6qE64c7_Ag8h z*?qf&_XkpMu|dmUSv?I@M7a(hyO(ACYI525#@?mjI+S$d`T)amH0kVseQLh&xGr0T z^e3Hf^JljD-$q9O&oEuWbNZx{6INdl=fs%KcK;k@nEn&&*ZA7|n2K|?j?RtqzcNn0 zd9mV7oxg0q(C+ycZ`W~b{4|8d&~nB8CTiK(Txp-}11Dn(SY3Gj)84-e&to{b&iM(` z)5rNQoxLNFcH`wT&}%6ex7}BM4g?->uD!t&N_??d>J1)wM(APZ z0<3?{4rKho_EP_9ys=61-R-OIz8}Z&0(@n^gLE-@mBiQd2$=BJ(hKR5idD(HWa})} z$C+XXKARfS%ayP7*M;Zq#NGk8fP$Ys#wVTili_RUhFXOGfWO;U3ioyI)O_~dgUv6T zM~Fw#@tx7l-a)W;Hte3n$>_cS4cGj5^aT89JmuGL z%@0Ojtcb_-0_=63wf$O?k2WuJ9$LhCC<9=)-03>e9dY+J6LJe4{YLhLv;M2|B^ZI% z@s)7vf>fNXEWw+-KIA*c2f<;bdu4fzOD~oDb!;4*)obe}~=PsOZd|ceA{Tg(fRZ))PW5?e%-ia^E3m#Uvo${0~ z4c|H)CSgBQu8IBPMk!wO2ZpVjBN>*aVfu|3u#q<8J^@1xR}j@rpFomY`!qMrQ-7>L&94vejxJ&`cumh zee!msl=NXGgsl$^&gc;4cju*ohaEq;^?Budk&>6N^t>|>;JpV{ZRcmTJtsbX86qLl zeWS0vBh@|)f(9<+D<>aKFRp8o+o_JY63%o$`A)@xxKR7sW894*aRz!urSb z36n3ysj81P&Qb-l&e^3*&l*BGeF@({B&P3m>jlwk#dv$Q(70OK4I(d%Jy4+(oWQJ=&AtH}mxkqkfso)cY>4Jk=UgM2lQn@)nd&joZk4+VE={l;(M`~&7EhAD5W0379DfD7)_0+aGuKjz(?Zamzp z@?t(R5yI9*W;e8VQF0k6COnTz`vvRCWwe6+scOe-bLSaW#@?>u6P-)A;n+EPjuv4V zpSZ6h;}c=_e?n>po;hvr@RY?~6XI>&44mD{+DkieU7PC!z)^0khEFOuR@$G`ZE z;dvb6X6}@iM^_`9uyvMu*DpMe*sgT2_aCetqifQe!{U&Cf%vRX$AFz7}PR@IUB)JgnLA#MWYWx1Fxbjg*C!41a zYPp1$`v^B`xYQogBh~JhbasO=<+yy6^sclIh3{aXOUOqyzivBI$C>eAR4*l8jQEO| z=?8(T174_iB$aQiy~Lk%Hu!M7OxJRPjPg(5@`ZNP<(h8q5nDM0XD29jYI;8z1}-fB z8jTOvmx>O~L%Vt$z0Lk^^ewn?P`q8oS^reM|B8Kp7g=J^;qI?x^*-CkBU%s9;r$Nd zKa;DJbC~)@gEoB!D`@v!ISbU!E*0PM5xySqeQy2TcTnp$dN(7Tj^|_950rECQ!$-~ z?Y>XOt;3n_dHepu&dJh7MHIq**+6{2KbW({cY1Z;zSj|sYbVFUaru6Qw|+Y6+MS#% z4Gi_7!Xzb7(Vf#ToT>Bm9w%}P4?BNv=kaa*XXkY7TyAiir#BRDe@5h2@d2GL!*jQ;ot683wl0kBe>{b8Ve?VAKB#D46rOse zwb$C26s$|_H9e_P?wR}|UMD-BUg|exz~I26(oVZqFt#66zL;FH`6l|_(8TA6X*FJNxxD3@Z8hAF5cNGiVrB?+d9a;Phxt2y%S^a z7$zq@Cj}I*({-Y?!@h4Dey4>(1J2$tt{u>D-)i;kokQBeZp1j?`63c%IFaxUz^A@U zx+F3BuZM5?_qIOWPf2(mLM-fOtHtwb(0L?5C;nF9?@8xBi*iu>XsEw}-gG59)O-!! zBA#dM?Q7C7<=Z8Mclo$}sAE{wSE-jtkKvV`Z=oLBKkGz3a#!D4`~ycli{;q+9&9(e z(C~T;Hs2SJKg_q8xsVTqOTJke4&1uD6Y-o0neM^H-t5wAcPkv{Y4WqZV`cBLS$)h; z{F-$-jnD&#!A0w#MaIgv@@$wMa{Q>lupa|EZ*oA(Tm0Vl3w&~l z%DKjc%BbP}%DW}m>r?ey-k}nHLTAy>R>i#$wA0>~*|spy@)BydYMiTbFD!43mRDPN zy>hEvxp@H$-2F5Ao@^@7CGkf8+Pkzo(--R;-d0a|&+_cEv^=+eK{>;gr`&tReTTF^ zhH>uWM#N{_J?e13(}VKMn16hnb{qzyi)yFN`BJ|ChG5DoFCZ- zNSn`xVb7)EhGF~HPYdNi8LzIIs%Sm{@ zMYat2%H-nWHBF2T^{~==ze=ZMmFh*ou(Q8xQNA!aZRbV$l2VMk*DCylVMpJ-Pnk{B zIDSw@Bwlo!AL#5{zn#mqeA~7xmh@z`>SKZ1mup<%^fTj=H3D`LKA$4>8y_3~HlBDc z^+e>JALqlb12@Cd)=}G5=sj?I&)@F3hx}>lr;Orb_I%@O@(Zd8^*`H>vw7zzI`dql z6OJR<&SO;S4K}YP@ahx5Je!Y>t@(n4&7NcNCWqM0rz+a{IkfZ5(B*N$&ta|bP2M_v z#o9^w-HCI=p*~^j#d(@9Sm^Yr`+bRswx2T?+fN8nxz*h$KzwX{_45bC4k zVZA5d7u-2EtG5O9Ucz+v`9 zi5Kxb8D6Aw^u8kBZ!W zQ#*ayzUM{xMQ3m!-9Zn!iRn%*(LN@zj;z*ttX_MU#l8c;c)}I0Ryq}DF?VVGXmXzX zNjQ_=&C3NWe3y^uY}$D7#Av*D);L}~={8=xABjJV%D^sTzt1xVKyX8-l=#~FrY(Ty z{k*zMC0XuO^Zhu6=-c_`^cqbc0zCfr(hlCvUzpruI@@LOv_q7Ar)Rd7!+7#5L-gxi zJn2P!hxA_!zs}K<q0w!IRtVNWuqhS8%6oj&KKLhTJ61=G+E=bgyWso2N|SZy9O2NuHxB{0qkyApK|0}iFM>YhaCBS+ zt%!s(dmqQ4&=+yizwo7hot#K(cZTmj6Mv%2^BN*QT)n9(-G^s=(Q#&Wx-^whxFP&8 ze`UFXXLP)|dI`T2f3>Ue51h>}l>2nJ*DQ1^HY^o?IDR(T3wkgSe&3l|XeaO%`Q-fU zq_;?a5sn%A&Xnx(-Hmd%Ng>>80>^(r-!bK3EdTf>YT?-lq*C4SG;{m%b@+*jN)^?vcA^(%~to=k?y%jM4)l6nfVEW8THAq{mx9k7Sh!rpDRINM^sW z`MOWIWvqQai{Umx`mRub;^nP^r|Gkeb5!9lKBFALwvCJ%<}iLfwq~{zkeoC}{3tv* z|45Zi@ZmUHFJPXXOSSVaEFZ;>_H}4FE+pP<=IbN-6uk9~XmY=QGbI@iV4DF6ij&-6gkvqXW3+fCH^&QyRF1PI^k=s%28EH6gkPE|Ua9irLMlk*;@ z49v4DHuw4vP-$*9fzu(0+|Dnu2?( zy+RM`ui}i|5~e(BjnMDS%f%PNa?0hz%Mx$rRipA?HRxvNR$2f4?UeZH#*-^57geqh z{_)47@G3u|<#$Q>Z(Q!S3jCvjZ&c2(7Rnj=(en2JJ}P(jVH_1N*Y;9h0gB=I47>Lw z^El#zEqd-H{NC>tJr85&$HVWnIlBkXg?qqk2tFlQpMLf?)O%`gK_ufHztn&k$Pe4@ zAs0cuBy>P6&g#Gp*HdH)xTL#R$9+9CYt-ap3(`oCzBPn`o&v7V9<#D{w;uqcbWPINiEsyjRdE)#h+&yC3N3L`0 z5$T;{u|qm(aN&p*0)o&jXEo>SXP@T})NS5GbyPx|~G z_bq{;OZ()(Q&A3lAL(3| z(C0c>@+D&4L5yWv7u&qg`TPqTkPp7(b3X0Nl5bK><_m`DqWOMn+1Px;fG0(5J!SBm z$4-pa;hmLlj-GfJd(LM{abjP7P2#^k`i{rrGCt5`SucX5UbE8+$WO$ld9LPbUZ;Kw z@FG1@iLc1`H-4f#`gQ{N!S|6~;=?bEej9nBaF6})m2u#{sPfmXyI9_)=f{Kl{OG1{ zOqK6rOFcl6e#qysmhjCkJjH93@CRJD#@i?154mu{+b`ie zT)4_RF5!DzIOd&@@cj}FPTw!S?YAW5)d29fc9-Z82=e_eJ7?ziuG+83%RxOtDte&u3HxBK4V(p#f`D;)=*vGSbl^kCTH(u~o z0UWtd;VZ|rjlYbN-ODQ)UMA4}-n|^uaJHY-exHUdpUHzG7wCO(&KE)lC+FD|=5h&B-xGQb zO3k{Exz@0ai=fg5ob>|JEpA*Id4fl2eh6V)JuG8XKC2r zY`nT4^M|8P{YtGbvr+xoI(b1d)3MQV@0yMvm~y{}~J)0MG4!Qc8XdLK&Y zf4Y{|K3o0ZfcB%k&t&}*3@besb0ENl=V(8n^h&sQ$~(~y($62!^6Y!F$=H>eFQR|2 zq~ani*Z8IA`oZumIy)uT?R3Q%N{5m6YnbZ~sqdhMsnB=LR@DcDOew2HHx8qCdTR!7~ukg_n<0It@(+>mJUt{>_LS%$9 z{Ox?;%J>51AJmKgy)pdb_@>>hGlPTLpS5jL9QauKYw;{%&HmPK$k)S4&xH4c@~`9b z=y^rew#4A8q4&=6iMjh5b!TGIvWhp%>|x!nskpZSU3Z z(AoZr*(q(FS-eWq?HotK({()SVgHUhAD}~`a%UpA!b^a29+SXsJ=Wf`E?VR33`Epxz zp=9})Zy4+Cu-{zyb}t}27d&5*}CB}04+uOaN?ikJ}}pz9Fmr9_kN9Tw+Y=SmvkK;osR`iH{L1#_o1BP z486Z)>+UFDuqg6RD*8S-@F8cCPM^fmdgP7^eN|`|2X=*gn82BxSb=ldEf5) z*||nHAIDQwsu<`z?Nz5@vqk?iSzd!ei#8 zj1(_+Ph<=A0G3B*-#mT9!s&ka@wOOHE zq6LXE9xl~#E(5&G&()6akuLMIOE4#aa9Pk~A8Y8DE_vb|DZ}UyY$rn2>OS`O({I<@15`|rY@TVPIoxvYK zBplmyf^z(j3!@R3_GP|dKeAr#n+5J2=HTG>NVZVkSv#I|^>SRJNH2?mIZkbyn;vC$ zNb4t?hgc6jr4!Dl;rUq=TXKKTN4aJnvG@Lm6YJ!C8Pkv0Z#;i*`{DMk*T`+i3}^Hi zGCK8YJjWQ{Z?W$v%!e6;;W{F_*>f(0H>K+df<0%`64{zuxix%?ejoul(P4kEN^M=j>mF^$N#z675R% z{iwM$&yViC_x|u5DdOn^bjbOSP4eYNj_vo2X@9$xYva0ZsfIh@5d+TY#B9uXMnBP+ zoUYxf;l8B~|7vX?@s<8`<1&OhU*QWY)b9k}`S>~H{NSM%g-=uNJz=~5VtitD#E?(W zUb@Qm&z*E)6kS%L&jj@(@xCFQ+1)Df;XCVe#s{S1I}qmnep$b_37FVNIDSlShVqYx z3g8N}6|TV?r@2ijt_HI+%W=${7LWjcDQXs<>`_wnNV0v!py_d5D zz~trcBg7Vk@TY2i`wj!;LmdRQrQ1F1%6I-vFC_el=y+N5h>U~cjQ!%%Zoa9^ZvLpm zN7pUXTkQK`(fCIsUgbZ_DL-ef{XE_|%>9z@gw(TV>NC!Nd=w(g+kJRRxlO9LWfAo*6=D!-IKhwg1qqFk` zwjXHx(g}Vh9^pA@gkL~J#z!O^`#*`lxrr*zho6~Eu0lNE7@th&yTqAu^&CI@Lf-{iZ}a`?+q+0i7y6D9PkhFM7y6C^FZ3NJ-j9@X7@0}mX#GM@E)L+# z{xY&pf?nFmt0CkQ`dzE>wJtq+UzYgRI{0*}!qxYxPdT#+e|FCBD1NWTUmY{S*}9JB z5H4YOsYH8uS02wr5l@qgN1Xm|^1|j(n?G$`Us-P6;a^#P9UBMNxEz8H&c@5gEfNIY zdVV;3r|(vcw{(L~cq;#D&@Q3#I)$@#nLN)sJ|ta)Kiv4Nt8wLK)qfTRv7BcyanWyf z_%vP!28By_dJo0ukgdT-ap4RfgFkZN83JE}Y?9tDL40qT+5pq&hF%rhc<0 zPyC%(T7Z53m+@@By-R6u-Lr^o$!;^#o%>=sS&j2DA-KMJ`J58cW*-lxF?VTR;dr5= z-dS=lUUI~JXQ(26P2()rudbXy| z?Csh4YTBRJo)-9{_%nMg<(R}%4l@2mEuVILd?I0VIJU%#!#Dd`DgK=jZ{IQDIHu#c z5V}_2-R$tI{9bVLJ(@4N4(7d2;~N{tq}yziS$mtp*LJEOzBADWA7%QJde zzc#mOJo87~zGKTTkRY;4`Sw0C=~Su*%fui5dty>rI) z#Ut%|w&pvdY+rf47xy+hJ~MqTA*aJZzom+O`VRGvO;g0m^P^tZ9|oWBv>&!5&ykEN z&%RTj;iHg?>>u_!{knpdKey_IQT7w@rr!zQhac{@%tZh$Kd62R_rK^^9^KyM>f3o4 zgEKj6_k;Jketfc$!2rQgPhmwp>3-bejb{$YndwRWy~uRy ze|z5`Jm)Y=bF+RQKUqF~``*Zyd2}8U;kfSi;oEl>>m5JUcQO_6tHlfLq;|fcUYA|r zyY}{7W?QEoxf2M$F-&LQ$K-yY&+vteMf>klpK_Nuj$G*SAxvlco5g~LtzA4H;UlWq zO|&+C>d#QP`nl@Yu5;m57vALjea^o_{i1u<#^`$#{f__tKfB&)&v$p{2K@ePd%nM; zBiohj%nao6JuYIf$39km<+_WHLQ|roTTE`1$R=%X$9tuvSH+Z!lXJDD=12 zcjela^cOt-%=Huo`Ul&IYN0+;DC9bOm{gxCWcv&C{ewL{+5Y;WeE$vgy+{+bM5Kv*=%}O zX0S^jqkW~l5#=rrTeyp5RusBD1FmpA$4(~5SbV^Rxt>l#sVm>vneDewN4CB{o9STi zm+wgo&#W+9p)1#(t?$lDxnmLP&kUt^W!nv)oKVuHT+cwZzbDgWjoY3>Ah#!*wuD~` z!szUQdUQZrSGK;RKev6HZfwWcOYg|^baZ9=)4P`c+R^A6%(dS@yjYV_GNg0QV0ZoY zu7TwpASQYl+}jz{clPHBg9IOku8vnia&GU>cc)cqPLLyH{vpVYbVg;(1hCdQ^&$KI zsynPC`NrWP@UmmMU!Ii<10BN2xqN-DySJ+_L5oWbCBWEm91)o|n-FkJM-KMn+99|h zbU;J$pVe0g3S>E{|Ceu7iF`6bt&)On+ygejw=0PDCWfbRyZ9 zc}(lc#%-7#2W4&=lMK$bjva@kjX_!RFHfOxXyqV)>M^8p1BH72&J5&3p^5psen+;e z7t{EJ?HMyHJNh%7c~JnyG!PTUNg7z$52fB39LP~y=*SQYk|x_jF0xRW{?QIGKaj-$ z7A@!3NGzw47!oCHqoR|kW5}Shh6>>wnf@$BU^jW+Nk2BQtVzPnkr}%z5nb0)fHKIM zqTDLFP{^&(6rFj2Z)bm|JKdh|*`5n0%~C65gp`K8!u4c3qLdxevZ$P{m=!~YBTPpw zNN?}TXGGekdMF6|fxHh6=j3rofkIfmO? z{VSjT$*PAxb!p$dU+Z1e^H|&e^UXiIY1^keKDTqqx{qyY-M}?6ovuQ34aDCXJ36|q zzdzsK;5R7`HFZ&Q2sZZQ268evcL2@oZXfC@HRU#F(;bBde_%(JTC<-k_>&GlJN@kQ zuD^QLhrW14US0e5U;o?Nt3WV^cjjMnUT4^mbJs0xS; zWjk2@Sx*jpaltk1_vdE*)@Oe2w;n(A;Cs5SFQnc#i{(NG&-Tm8VS6UmmF;Noa~-?= zi~TiCo0`^a-1^?fj(UIhQcJ_}rzf2oTXFf9?|XdZq#u0fAI`r2>9*fJ>+XGr-|gC; z>bapOKh)zw8+EnO)ZaPS4OO)~c4KJ?uof$c@UnjyVjaEfBAnfx-T)OHTFVO8w@lbxBv{2iEoE z2RnDT==Wp;tIfq+D)e42G_>k6ySIP^uaJe+y4~&goi$V(g_v#yp@hPYjd{uJN^oVP z_RS>Y?re9j5i`|O80_tZ7(hFM!mdoe%d!!RpUzBI^AHwNB|Ka~1=6*NDUKcV+uA@Q0N9OMKeemEAtzFZ73YU<6S?+mp+7%xkAA+R#8*+0d|YZ4)FF`n72nI7UQRf39=KK&x+~ zP(&VE)|-ct;kN=dWs7>kFI~3${1q!NxNy})nYQ+h>~?DpW;@~iCTl2IBbPx5+N`Di z#f^Rr<9mg!!$B=gPW3{>cVt=g6?y#V-$DyOLxby2GLBDm*I(|#*uYU;cylFa?qy+a zF$27A^_PnEq9U(pU4B-DFObP%Jo|$^kiP9Zgq)o8yJ7HnHwCQ{Ri_Qe%Ap;3Od_h{ zmy*aS*|Idw&M3BZbG87MYG@ej8S2mUE?C&=!_Wc?NGpimswS0GPiRm5|9HGX;du8uSZF#hTB-wAUQ>`SDE%{OBUV-6V{k_7~kJY(UyGXw2AK-En94QXPX z=0sMUO3Ge=3Y+^kvy}}E3@kv}Lcj6dI@vY)QLN4zn?-U~<_U2+Z|d)i#il1aRBC6W zeHh1>tGoQRU?5vS_hve*zngoV0k6Erm-t(uEo{&A7X~B~W_bR}`b+(MzrU%!#{X;C#Om zFI)4ysor&FO1e}nNrqx&{F<(OAzK+~Xob~98n7NKdKDy+HAF2$b`5%DgBmb2+gcco zO210^OQgWu1{E~h;pk@jt|c19%R{9)%8F9k0!b_r955D|8%$Xw z^%_`QLmV;pguk;yY%?sQZ5SR++aVLkAW%zf9_!4`S|IXj2?pkZh3EMjz!2H~hK4QB z1J^AK=OyD-D%S-c23kK3JXTSFphKxcnPrT~sC zDY*XjL0QK_kIa~!*}ItL0c)h13c}WeP;3Smol}>A4yxu^Dyc+`s~}K(8-|5ad>7aF zz{?S*;Dp$$1*EMCFltg;HeRrUUuidzQeY$D$Wn0oM8@Fy~PHBwEwIwZ0 zo3CoXFwFP9%PCGYia_0gc4D=Z>hFe8-(O(74?Bbkt`bRIL}VD4sWV)tlcpH?Afyg@ zjuo~85*%VTGBn&mhBku;Xh_i|CD4X(0mdn7$fjbD7m|iWTW@H`HTYurSxh3dizcvG zBg*z0k=r#?I7E7-E7Q$YX#s_zbrnc!ZdBQk!wM9}(K3XUhz(BlfNCa-xSXwM&I69w zUAg>V!8R!Y0pcw2H)nTp!w-uk#Z@(X>mH}*muOe|wb*(kWK_$9akjQenYFlW%X| zk;|ubM&Vldb&HY;mqdyQTa{g`%z(BC2?||#QF$=RmSlJLqB9HW%s`saQMyTiWn?$< zl^Qij0$~tnk0l+^>wMztb{m(`7TAOVP1d zo;0s4ZHXJ)6|uPvpacs_2%GC}8|*KLO`z0J;>DrDc6Ok9-GCWG8W~2R;9S@cPG71g zI3}{vB6?aH3RQWbCEhYlocBHeH8iYUcg4EPnzn9izAC+W-J0gjYtvhsE`xd(F%6eG zuhfJknF7ea9m??3dG8Zo61mKptVG;)o?l_zDP^S`NnhEt`9144Z(9hBR0jnlh|{R& z`Ew+%-_U>cOHTel^BO;hTMtr28H9(er@2tgy2yeTXl>*hK*qrgr8L&UOj z^h-!gz$G@%Ein04;=U!8R#9Z6M;9#Ij6u}U(3u@ru<#Op2~KmQp^fLd2eI|6t6!a9 z#*7!4EocdWu)L&l+EN_?7C^V$akEc2gJG=}W}#s5Wikk%+<3R+?WrFlJ>?yM(E@=Iw-@z<6#J2Zz|XdY^(u96g#2()5aW2 zb_aVrXkY`-D+*q=8*Odq$nIJlf#~c!Zvb{!>WGnOuQv}vcn}uZiPipK+Y<13r1ZsD zs21u={kIs%5UG09-3B-+p7mF3T(j<~E$fzacL3KcHVa``P2*rs=U}EY3!HkqLVmEn zJ&R4gj_fa1pXcbc?y9vDQBu!Nlk$2?s1(-MG_+6nZ_@pA*CX85*7@Zzb(U`D{VjZI zMf!9Xw)(6dcU;lkV$<`61m#;ZbbLFD&dPVkGv$sx(hh1>4Cgh`ziWL>t5*4Z)6uZG=fVJFpd8b8wL|w`o|i9Y2$vw zR`rt^)UnU+mbI|KcR+WQ31Do6uVZ)*P1bMR@*dji&G7!KHej1-*98OQz>ZvD3B)~i zq#0^QbTTc7Yvn?AU`aa`zMT}BoTH(C_hUZFb#eh%R$-bJ zSLV@Ju~js$Pp{d~bk$|+)~2smcNIFxVy{YFnQmUce#^S8=}k==H*YCqJ7o(FQkeTE zTn6XV+z4Y;KjuQ%E*ObDrXH@eJCt%|xfU#3D%C^F?H#}l=MteNtL));%cMZ&1;ObAeWzjGTaPySp6V%cSS+F_>ntJ4{PbC)5DUTWW47CyUIQC7WVt;w$|M4FD%KcetIxk|8u=6jigA z8P&`jBCETJEZDDSPj&`#D^u;53!If1yoe6AdYYWYJZjdoRl^eBWr-NFG2{Q@_P|h$ zj9QdR23f<`X%(==@U&35NwJ~A&Q$6NsB_d?BN3)usM;k*I=w;1m^qQzFS3dd6~L?1(FUesPSCNxT3;6zD=rHt`Qz^r=n73>dbav&l_8o zg9FXmoBOdNfP+0(W_kiS4P(uN2#fq|qHLnbyE5C~nO%!S*~MH_+NE^BQpVV5*ZOAe zEJaesp4W;bZnU!@8n;;(bZj+c@nh@Jt$%{FXzi6CW9zPj2y1pVt;Nu|LJn_OM0AW> zT)3vwu45+0z789n4J%P|YaYk5u=(Z&1hl6noWH`sybv21L1OnGx5ZLl$h z0aZ4A9Aq}@UPLsdxn~Vc!VZCGiUW3g$~>osQ&wd=(GCLbhXn$LL1XPrGOc$;hMnzF zYt+ULoZ6G49UF0srwhkOyRtI$-5QE_9qG*1Tlb!)U-|a%s-!wwhv{okrSv+NuD7`L zTXBp!&Bg009HsTAm2c}rTOZmw(CXvcuXOzO9G$`0I??JiIK$7@t+O?oXX{0GoloAB zWsUaQyWX?VKph+(}}kI`8UlL9Zp*V=7(Tf1Ge{(tW` zL;>U9-%xeG@oIQ3^S|QXZ<0_?{!NYdfvpcz@9BQ)jDMf>ol_U(&YZLUhkt&`!TCLt zk3aV@F`a#CdCWVq;g)$rUwB*13)=<~wci~&Wp3Zc&pPq`h3=-W=Y0cDCVc;tpPlo* z$rpKFTX^fKe|py!-qyOP!9j>^;=)wHKFLh)o5?^=hlv!-wI>p;ZfP9OV?l(aM^~- z-*d&4S8cj_^OmitYg(>-?{#{FwsS{r=MCLG`QAR9wHw?u1Y@ikqrydtGas>RTqiGc zm0?Tty?rP6n}_(YA0X%93oLLK_R%_M$IgVsM-1Km5Dxsi1C3)C;tS@}pkxCmEdNl+6F81{-RzkuCMl&dsSg{+{?iz>cr94zja?>Or z<{fldSDt4HXcN$-nctbk8b|C>&^eXM)P&HH7kXmLn+N1^?gQ6nxb(A}rGEE2@;KlX z_FPu3KERw{M?2&U4>ySx;|LTe7`cqVvu0T9hE=O2#GPRQb5Zqm3Z&y>M#3-ziWNXa zy(J;7?9S}wh8T~_GMA4o;_=>|f}Xl?rRZRQ6(}qwIv_Td#*G{emU}lmp8aNOa#tIS zX$!iSM7sipvkU}WZ@}&s?l(9UKJ0mEK8V467L0#v%XIT@gP(Vo8$x1;3D1^+8|}M@~y43Z{q^9-wN9!&Og&0){31kZk`b5$>30|jh;=+q zzZsj3%{^Vgdfb)L11hCoSK#y*j4>giOwm)tjw?3uK7g$wG0a%$oi@j`?E=x(gT1 z3&=y$$`!eu8;m&#$gRpIHyvF860m3pl8xLL=^yL`DI;UL)XD4e+r?^gWfn)^aLr9P z8=cz>snnkmQ!`&wfLTlWx&d3n1e77HW858kfSFpa#3?{&eP!zoQz}e&0h}7vnXkIR1-mc+1k{v{<$#J}DlLRnLyS z`09A9W^ye4mMO8tC~q)+ZfsXo zb$m)}Qq|Xi0I;oLiSfykrp9AS>y}k7omyQrZ^|igzdAl?6%vpsv1)QWet%W$t+5(b zRu%ukYA^PGW_eY=A8Yl!Nx8UJ9h>UMH^n`)vO0ElJQ2GuKI62v#^y~v`z^89c~wi% zGN2fn6I%ny$K$7;?u8LQKEV2I< ztD2k?+G;<%t)?omCI%9b9jdC)xVObqliA4Wq_oC^SAGDDC&7O^QvtkFXq4r@)v<&( zB^LkJ*wpIk*d3_9I_6JZFiHAuQoL#jx&WWHLP?v?1ZpT_&mu zO-E}d)q1B?Re6bb)p)T>s;>q&q3uiJ)4fF1q{)-xHSegtr^>sqdimto+hS)XVznsw zR4Fyl5!;VEjn!WDYpAcg#%ta8qUZf-{-s-KC%N&3Pu=pqrtZZ*uErX)Zs$nHk5={k z=)S{W`^nEP`F<51K8n5jBTJ@y^jlT0u1eO{e`jF!5C8ScUzz-T_2<9#=wE*J?7ind zTs5!m`&VJ%5c};V_rLG9uY9im6&)c!2 zoA>|5-G@e6t_KHdCrIq=nkWrhV!Ch1bJkZjU7Oyr@iLsTzHH;xEn|136$5OHX4`Mz zzV2Y#0$1@uxnhY6aSIl{ZZ_z*$VQYRxx8b* zj)b3VxM}WR+%oY0das@*;h)?$a^GKm`PTh!e|3d~|KU@Mrr$qx#S1H6y;#D3@IO~B z`g!N7|GDYawGw{UC13dKZ+-Qtn{Rma3JL$oUw&oA{I%bB;+9vpO8DL{&i&tC`uGiZ z?|=1r3Ew>2_B(UBKK1oKd9_2rKmA(zt=De<nJ;|% zl8>G-`m}^6z3ZKeK0odH?<^Vps)WCCS0VS&IdlGSlx zFyqv_Iwt?aXMcC}hZ27J1Doz)f9y-6 z81&9f8~*C|zBg(!c-yC*_`&WYRnFpj^OSpD-hI&}H@?H2Ncy8>%@>Pby6^ZZXSwaY z{-26pTK>Bq-s0Zx-m&ldpL}T5Uq9O|uiAOux^o|xK5u^W$3Ng*EVa%5`RBj7>|pzk z4ti@P{K%1~KC~+P%}0-US4jBl*-y^+gUL_6|2c1~gddpMcj?b&Zu|U8-t`i`_PcL? z_`KYecfB>%A>n`e{oWZJKaPEEeymHvmk+)0z()^tAG|a+AmLkX_?mLurZkF($J@MfC?z;7Tx84=|kc1nz-TTxNTUI{xsn|Ud{-gc({rmNQ zyyzoO#y%$DzfbS~=&_Hl|K{Jt9+L3f4_);26@T{N@GG%TN%;DY-+!q8fiL{@%=jNm z_)DMr{?;uc&mUbD|Ez?+-E{6t)Boj_4_p!dyo85$U;mW{zvMr?J^r+WzqMsn@n5bx z^Zpy-UzKpf(z^See{BD^AB;aQ;d}q+@2}tTSAYA+XX4+H@WpEnKlHc1{ov1^iT_Z- z)7Cz8_=+ob{qG;deQd>a8nIS`tqW>ZVr}J9tzzA% z(dPR+@H{#5eiv%5>vLVdzkYKWA71x;&oc|mFwB9Ov5ovE^G|uz>$@jrpH%k`Hs5j1 z$%ig9FSAdpd#^X{u?OCn`owManRRd6w(#WHH+<`gyuGjP{c;;_xN-cP7hkh4sQb=| zfBwZ)ukUozr}l+)zk2ptkF0v)n)gOI4y(J>ZdCj^y0P;VU(xXOco!`24)iqH=T4P7 z_MzV*wCv5&N#p#hJPuth{>giu$@`Y2FK)91_8(<4#k~h@TR!cu{qDN?|K6LJ+6n%X z#M{p)yZd+l_q6zC=h`(x?=yX~{Im9&v3Tj?(^j3@V*ph?5z6?>%+z`X8m_Z+NXg+!wzc zmfx6~=k0F913iO1M$g<{e{WB3Z||JmzTW=cf!@Jhqj&Bc|D2vVz2YLheRKNf z49ppvW6YV`=kM$3>+PG<*VotIH_$iOXY|eO_xJbo_x8`}@9XdHALt+KH~Qxe_y>9h zdI#nV^bPb63=9ko7z1+${ewM&y@PWG`v&_52L=ZRjlsEw-{>)VjX6f2(QgbGgN9+u zohxQ>u9*B>(e+$0+FTj>KMwU@$%|6}XUZ?7Hcnc}6O7`d!y56sDDiW%`e}lp^HS<6 z2jW5}+dsdE(^>UzZHX^HiO(q~%$hapr25yB|mwM$X zlg5Qv#AO7<*Y3q9qWX{B#OYb_dqHu+Eg}Qz(`w@aF7>EQ9DIrc@%E0+&UTlptG&Bp zSo=taTO2u#>DXb?*tQ+p$G7h^Vp7Ls*A#I`zS41e`~CI@+8=A*-2OuQi^E^)db$0T z_Sf3V9b4MpbyV6v@KznQ_AeY;+lKExf1kyNZ@lTIo6o)M>T7=b;3F45;Oy)g*n6L2 zJ}$oC80#4rJm%O7?z->($NS4;F8SdVH#tU(96e@_p1yepE;{&-#fL9nap{K3H$MEE z-#)qN*_Tgz_?HtWb-KETjU7KQcV6bs(yLvA$tyFR-ShW3^|Xywjb6Rvi4Q(J{*+I? z+;-$q*Ihqr_U^u;Z%p6vvs>@T-22F5PdbMU-*NK1eGfe1_B($6T)K0o3A;?+XWw_< z|8Uz=n;hOY>nGcLMon@|>)N?vM#n?URpg8`V4F!s|~xYnb`urH3sW zagpCWu6yJ49qSLe?pO0J-n4#h=bnxeox61}>h^W)ur52#+;qZ>TNEt=sTJ$LSp->|LGijS=$;=el1Uc2L*a1?FenYh1A%7o9V9 z_}JmccI{+dvhE=J5B49m<3*tTJ?{vC4 zyGD0U8n)B$2_xJihmUf&?PJF5&^4}Yyu;JBlYK(x#I{N8Q^tAiGwgc}o7Lub^tAW3 z-Ql>i{VvDdt}oiRc6`qZM`OWYA#kPI( zm@l`Flb5f!=*sJFeCGMhBS!BrZ~lP?AA7=yCofsP;_@r+6r()#%vpIL~Uh2I2*5TtFJ-0a4y|!ED@Qx1i zcK5nZJKMZ_Iz{$!hxu#!MEj@_|9)7pYIWlv;NLUL#TRwOU)03qahe=otd=J^>mQYe z{%*AVH2G#Fe@b$WIFH-7h*14Izv@^)zi~7&^3OE&E4s;d5Ou!1;l{gCeN6EuEAfq9 z`PVP;u2sjf)iH4mGrx_&N0UzuMFfO~h|&w|_&KO67s8I8M9J z;k8}a5wV@LL)tcGym!iQZ)D1cGrcqR^rvU6zCALtJyV{!^VafSwtsmCZrTD<|#Epz>owjA>D&RZ4-`fmB=&P%r(SzWpGsKZxpIqJs8mL6@} zy!4nAFWhpB?X{`L+RC?t?|Xad@$bL0<%D8o>4{$32PanBE;vd5-Bh>Y&&S(`Cq_GM z`h2JiJ}<1#drH6hHF;U1hx);>f@`4h;MK9t?Z4kxB|`hE{KevaH$CdHY%UQu?a}9z z$BB--D)-w7PTQ{PaagqayDl7`+NA!t7WFc|OOyKJThzm~evyKaljgXK*aTHs3iKI zq^7ICx5fR}M7=&o|5x#RpQ7q-ZEt+;k^I$8PTMjSe^0!C^|D0KP?tnZ!6aLvn}G? zqW@`4`u{@gx0>}oOMDrmS$sgm_1{FS(;aLPm-lNN*JQfSi1}&O|MxBNYsLCqsm7JJ zd7P~tTjRHgm|m_);`OBe&Ldy*db-z&{ms#8+}A}v`a5>k_!}ZVR@J;K_G5ZK`3({4 zZ4zHBVtPGTUoSU{*TK%J-Wr#$554^yKi#?gxt68hBkv+!|9T$fGS5`~S?BjRqCfqe zz@XUg=xNRuwfb*jBgQ$m@3Z9oLdUP(!?}ImEW3V1SZ@>39|-H`M!HR`4?Pd32?u0Q z3>=r|EaZ^(4(;Ei1AF4~E)xCeZDOg&>+#MLb^5U!??m6wdXTLX>MLTsTlXVe|0B`Aehta~T%v!y4*#3}?-JwxU*;!E>yi8Wy7_;Kre7xi zLoAQpcgyA3D)Rbyx2{*2lY?W%(EeT8E3Dt6rFs4F^D|e}>upumpCoL3zQ0BNnZkOT zl=VLn-bFr8!!yD&G(^j<+v~*sK(GI^L|#wJ8eb#g`aR1U|E`GZ{qZMaI@aT;t-^Zy z6lJy@XFBWm&XAAg&@XIVFN=kDZ=~w~zh1ol^>Q2_BKp1QeX*a~P1VWmUOyL4i|ttN zg94WL0Vv;OaF5x=WNT)yu&>*t;p@%vlEvn}Eew1_|0BL4Fh@n5uv z|FT6q*CPI_7V$?~#2;-Df2>9P@fPuXi}-I^#Q{I@OQPqv6Z)gr#BMf~X&@zG+t z)BBizitSXtPs(FKz5QC_KM`@C_$LQz{5s)Q@%`%6Sbu|vO>Yvvu|-_&2b$I2(jqRm z(`NN@J8c%1+iA1-9WCN=J8f1kx6@{Ext%tP%k8vT{Js`(xt%tvm)mKxxZF;g#pQO| zEH1axX7Ptx#N~F{tX^)X&Ej%9Z5Ef?X|uT8PMgK$cG@idM2mR7MO<#D&H9nsX|uT8 zPMgK$cG@idRExOWPMg)&MBFR>$-%mPeJQMu-K_D+ZA07dx#D<1zgHe4>h<<(jm!0^ zYsQQB>#4$WI7a-_^&`dk4*h<8k%;T#j@3IlZH6os!z%G_ulgf#k3~ydzMl25!gTSu zb&jeTA?8!}V~yV`;vQ9Fjo&8X`ncj4@uAInykdyYox{{P@^g{iXIbONiugQL6BFa> zX~>YZ&iejljmzz34>i6`d^lVs=0^`jaojD3s%lHB-Ktt$*RflpZh~t4s@-3;C#!ai zYA;i5TD1?Tc9Uw~P;EuE|4^-S_r`RlsCH1b3sw6~)vi?Sd8)lawLeqs!>YBehs|PP z^z&>zZ(=&CyWF@IykaiBiu=gV51&-zS!4hYK*#ZVQiVn*Yk?GCX&I8{B~CR+Vj!W#dF zi0l2CHU7MaPgCPs<1e&`2Sj`qRXNH(xM+3Z`RMrBCg*bt^H3Bas8fXjZYMDyDRM0ex8Wy*F*n)cpUJy zc;0qZean8ttknnW_}5$F9pZeh-iGBm)%Di6e6Q5;zlr73`!f0Z(D9h%{NVyiJTK0d z$-xwVKas;X#Qe(PIMuFE?WL-{S+$R-_C?ixtlBC2H^yI}+Qq6(tK*cDluuLbTGb|0 zdyQ)ERqeB?t*G`()s8)&F`YT8Jwmmos&>6U-V`UpJkyg^t@cKdMS*W_bjd(+dCBk}mRi}Cg6w`TbVL|z=u zY#+knbL0t1v&8YnX!Y3lzGM4yZ(S~ZywNJp#~b3CBlR8=qCYvLb*qjybUdZv|7krp zdT89Ez22GlU*SC+9eNM2uFu@ZjeNMp@|4tcWq*3TT9-F%>0ifnE60hcd}exMIsIyX zc+@u=UZL8xs=ZLPKUVGSs(nzkAvOM^%9~VMRBexH-%#z}RQs7~JCAHkcPG{EuG+m- zd$4M=YJQJWK1sDv)vi&ksoD*yO{uo5#=lEBr`jh~`$yIORka_f_Dj`v9o3l6v8vr! zwY#b|^GWm9U*yZi^XdMo(VC)84i6pe-2U2?UMxN*O_dMCV0~RbK6dEuR2A_;(Vtfu zm5u*fUq2<)|6XD|z3;hHY$tjjvs|3d(Z^7;#OV5XXtvl7>0|frin#v#V2z*MA})`& zn$@4%BK|)j-fX&CMO+`ZS*P1B7Em9DTI1)m=>K~y;=@Eg&E`{nJHJ_6o~LRSKU2h~ ziD}5eIzRIM_WHQq8ox-yo6Y~JBHnCy<+t_qb7bvD{Hn0&{EW23Q{r>4o(Flnt3R(= z<9CX{Jz83NOTg1D?eCqwRb-Hpr>(_%d9%vE2w?+T=w21$y#rk=p zMf}Yc@i}5UYBv7^BHnENzuhAKXA$2`%&Q!%%ll!A`0p+8fY^TZYwuApzJ9)}ad|$x zS^V)9@$*Ih`gLebcG|q6P7hy3@OuI>uHR2|D`QphGY&bJ^mqQ9mg4s@{K9%&HLH(^ z_Y?iTCi8Qt-a5W`n*MFrU(}1mfk7V=TIV-@c4K}6@=H2m2wv4_mx%qK{>*-lI7zLa zCu{s65!atpm!INPzpiRb@>KCTPwz)h6z3lry^8(4sMGskS-E&ur>*f$&=@aC>+QFq z-nx8G3R{npHVf-{lRf0c`qVYF(dQAC zTK>*2*NHxUwZ_Hj+I~K8iRJI)^0-+qXf1Ied zF3)OV{Ti2Dd|%kQ{(dSvLw7FPhauF zk8cr|$0g0Cds&P4buHqzwTR2*Zr1;kE#j}Yh`-w+{#lE-T|6<(rfbvp7+50iF<@I( zzi5iMfzPVbmWgZdi`zxiZwo7~#sBRk;tCqe#P`E(OXVd{>XC1+{??NEgT@_v>KFMD z7dKimG>*LAguHgTzI)ITb@8D3Sf{P}uDD7{>VCq~GUE13} zP=8pTr^e)DQT^5tmP+jGOtBpGvBXS^3%oQ&le62n@tjVbAuf;8$jOB}Beuk5E34O^ z-v9ZAixnycZ9}a@?I<~*HdLJtlTC7#TqcLqhkMY!fNXVl3A?buXYo&-5M z9rHPIbOz=V`j3!$dfvTo`2yq!IZjTIbL0}a zM)t@LQex2aV~|7S7`ZS9$1jnMKFp`dfqu+~$r-X|5bG=R(3$z@Z~&c=J7_WJQY14w8-2u|7nO*N-xWp06Z1vj)e{lg%GszH~7I8)W|rn2(T6a_SFQUnJMa)jwjr_eFGoTqS#7qIz=Z z70jFDObPQPa_&{kSIDl{Fkd9w%C^!DZ@=ik75?M<}rEpizhCdbLax3NA>_Pm4n z2-*J^%ooYAzhXX3&XX&D!}`d3=ma@S4!n=`DRQ1%A?N;%2bix^(Z)yU7&-7U z<`bWwi=U%IHFWWx=o;Dk1?B@=(NS`e?EMPs(`4^9%m>Laa#Ec&(Xa0uxlGQ=6X;^l z^(Fbi(&CB(EiPXH`GWkzq@~`FC!8%Vs1p#n|0>zz#(JClqPb;!A2~!e#$bJfoFK<` z!1@$9PY%f+?po$2DJ~3Wb;5(r?}SdtFVKiVFMo*~mS32$M(&{4m)hyA7;2$Puz@F4p_WVRDV^ormKG$@%%14>T?} zwSE1$_rbhDjz`Q|@kYfj6y}1w_J`f#Tg!Tr}#Y525L(zrB=*;2hs{DeV z<@FN$COSzjk-bM^eUw}vyN|;9FgZ=Gko`yF_;GTH>^%nSqvR~PMh+Z{o zd(XuB2suSAlD%tj{MdKVxwFy9IJ)>fbm|;*iR}75=ELWsGvo@{xB%0${`@zh z!(@{jy$S1+)9y*R!}E|Y!tVSS98BiruB`Up8gu9A%` zj&G6+WZwf=A0y|;wg<63NKTSVXyXZVA&<5_g$`~) z2cAYJ3h2l)=rq~(9Oi@M1i3`^Jdfjt$O&?BGuDTT=rlR@2h3;xh|au-uDpcKzl^rM zf{wn1&XTL-!0T9Vl5^xLIq(LKA1tFI{kvtgn*&f5CjHf;Pz+a*q(A#&_1%%{kCa)s>v7mn|4Ysb&~?dV_!I!i8*ZBDB1M2EZ3COJbcl56BZ zH})4NmqudVGYTCgSH@u8y#v}H7s%!DSReMFa}&_UM09Qvx=eOW#=K`|bdp>lXQyC& ziEQ&?-bW6R-BYpNAVZG7BqzwGyilxVedNimDCQI70@-~U)`w3=d*lyoEYmBI!)IXLzY1MljZU43 zE|L9fFrQtEu9A(jFkd9s$lmW_eTrNrd(WnNa*6DXV}0x#bc&oO2hYX&7&%4ue;@0^ zWRq;1hxHM1f*ig8>x(8jav{1*j{E@g338U~zXa>UWRsjB7sR6v^<^CtoM;aggcPY#n!a)z9J82j`65}hU&$W^i@hvNsx zWpeIOtS^&Yk6}LcI6D4obmx}Q)JgmSnnr? z$=;W-K1hy{i?3jPsf6~ug)VJD+ula|$oY3MAE=;H|BLqg4PAT>T_bzn$9#|+BWKCs zzvK8OIYTazYh?dFus`=F=n~oUDdtl(beZh^C+1`1EV)AVeu3kgThXyE(J6ACTp_!^ z!tqOF+rKdHBfGX?-cJsbed-GA`un6Ia-3WiH!!xozvVm72`9Qhu6ANR=R#M=?k>y+ zhM|+>BH23}>m%e8xk&bn#PN$`(KWJnN6ZJwF|ubI)(6N@a*~`Q`#jiRVkdNk9G!sq z0=Y!4OvL)cBy?diIz9y*^P&snz*Nj<$jMzX@1KSaPDi_TN5{xja?XeK;XTl?J<-`2 z=-fh0=Yzv2C+VW2)eKs zT|N?>I|>~;8XY$H+-?j%>Rd`}2@Pl=+2H9rEe34usN1a%2l2ha?Ipf0d^W+NI)`j(9a*S+@#QG39N;b(Ua+X{m zm&wMCIQ@zTU7CdU?2JxMK_{l6UDMG)a*piV4eQh7!tR)l_|SkV>*oF?ZM;rPCT&>?c1oF*5@t|0aoBWKA~a_L|k-*zb4PY#n!a)w+X`wqkYL*zI) zO)ijK-@yKgyxLV-QPlIqv#4bd>ZCW za)#_%iS;3JiR?KY>!aif+4pU%kCSU;;|#1%kX@@VA0(&PtFb;$u8`d^tT)KH?_j=6 zcAbfNKRHZJvDe`E6>|7&%qPg{b1|R)K00s#I%=Xl7ozTs1G-3#ZNz+< z?7tfG*=x`>vT-fuGbwb5oW23`)f>^qP3Sl|b~EP7X|(UB=-jR7>TPJ_c66K^ehBmB zhtZi|qVwcT4)d``(ZR>iW*(g*m!HOb@mX~E_h^%xA(x)R`Wo5&Jm&r65IIUtkTc{0 zxlDF%#_9XWVRDIFBYTS2pFs|j$tiM@P-6kn`jcIq?zpmnM7vf%y9Jxj|99SPG=gAdvXc~?mC7a|7xk#>%ZPT%T57|!+k|X3eIZ4it^W+k_ zO7`rA^BW*X$jKR4pV$u_-X9$!C&+1Xj$9;H$hHG;dLFW$93)4`adMhmAeYHCvS%UA zUw|AXC&(GHH%R?`1D!kyogwGRC32PQIvV@)k_~c*93`9N6gf*SkjrG-F*tu7vOzY( zSnoX^ojeI0U4k~rDRP!vAeYIm2=?zI2iZ%pKEDiIA;*_vzDCZhz`XlZw2vGhhsiN= zf?OsCzlGC_lQZNJIS|G1W8~UO%)3rUhsaT~NluYntFb>1IYN$;ljID!`W@^)cP84l z2Aw1q$=@swYY;3@Mh@86u^Cfa%Bj%IjBH5F~diRy+kh)ipe!avqn6KQ4cHe^zlH>PczCsS( zhxsx&bU)@(WKS0J0dn}4l+U4Kb8m7M)2*5}E=FEF1ad$wZUB$wDeS~$Z2wpTqIY>wliq{$$oN> z93n@_COJjUlJn#exk|RJqWLHL$w6|2949Bq8FHRnB3H?-)i}RivOx}!qhynuB4^13 za+zEsyJ9%M9F0Y&HCHu(%a)=xu$H*o*NzRh<Tq0MVUkdB}cpkQ^b$ z$w_jCoF|vaRkG`QIKN)9K@O3lWRsjCXUPR}nOq~g&%ycikptu~IYv&9)8rhvNUo4= z=i>Z%$bNE=93jWaNpgmqCzr@ovP<1ZSDzp9k_~c*93{ueNpgmqBNxf~KEHbYYLvH~ zhwIx#c9XqiAK6bf$N_SY93qFw5pt9qBge@mIYCa6Q{*%`L(Y+D%o{D zK7U?vfE*#4Wpb75x)9fgmu!$j&ByCFjW{a+U1* z0nV?NY>-3bFgZewl4ImJ*(4{(NpgyuCTGZ5a*muQ7sy3&iCiXE$W?NUY`Ykr4;R@@ z_K>|~AK6bf$N_SY93qFw5pt9qBge@mIYCa6Q{*%`L(Y+GPy#ol56Bx z0-yglIZ4it^W+k_N_PDar{^Ub93+RyQF4NuCFjU_a)DeX*T}A`ae2LDKRG}Skt5_7 z*(4{)X>yjFCl|?Oa*gc%5iYNf93Y3t5ps-dl9S{#IZMuyi{vu7Lavex_4}Z1@hu;D zCCl{A^{@Nbq~$Mja$a@_g*v9pUmX`FjOz? zdmUYT6J7oUUHKdx`+4K{Msj+xzkp@=rGsS8Peo7+vR=M2JkLrEIrMvU@_BTAGurhB zwE0JL;YIRG=-Mmj(5vX=Yv|1D=Iqm93#6Ca>$AE86!1UdEv z)|a=U^V`t=w#NO3^z&8jLPy=`^k{Tx4B9;w?e9mY2hhbqbk;y;=Au*c(Aj;^rG3%a z0NT3*9VV9|m=7#N=a!>m>i*4o{Z-Wcd$j{U#QN-|=-OrI(gt+#a&-O*bowfE^=fqC zM`+LW=;DoN*Ujia8XZ^nTh+@Ke+ctga!}o`PuF|Y{qnS3>i&1yA$31H?Si^LopwOo z4^BI&?(e4UQukBSPN@5%Y3J1a&a@46zcKBqx}TVKUfu6YJEHE_r5$oMu4k;BAC6A! zfUb>4$2{opWVC;0bcSr3g88%;ot=vI%tD7|qdkk!p~KP1W6_x~x^M!zr0$2K*N;Dj z`B)rXITv00K00;*x?-Yj7o)uibm%g)cLO?jIoiJw?MkAHSCiHKIP~(Se}eh+jp&TJ zUxlvs+==SoDE=oL0$h<*N4|(KAuLG)b%oTy?4&g@tB-n z{{T9_09{bmhtuPm3o&0&*EiGo+G5PdL+EG(9a7hW(&PKo^`5jV>iSLEUUmH@?Si@< zleSG=Z%MmEHr4f&bUqrx`6-`?_F0Zk<@zc-Gj#mZDIQiW$D{H)AkpGbUON0Ty7VV> zq=wFZg)aGr-XCRugG8)3Bnc(m_Cbmb(pS6%;0 z&rjtOF;Ou{cZq-1@k8rJ+BX56nu_*MM@M%@mu8_uN1&@K(VjEViM41?9BrI~&a6YH zo`T&AA0@B^%t3g&h?{1d!zmPqg@B1lj{B&dj8|; zej3^pbw3O3fMe+OR)0R#{Ty^YITG_V`_S^p8m|+bUWg6^(eA_0`P1FM@7I{GmC&9oL-R9C_V;IWM%~X__9gRK%lpxA z>Fm(QNlIL`3h-s(@@?mT(smz3;X^h&nh&QWsH0x5yp7eiy^XnbrjeKXI_nS+kfZdfU~+V$Ubp42N~ng%m+MZB-*`3KZ2EU( zx=rl)pU2-zq~#R#_%(H2OSf4yx?T!Befb>8VY>JyUk{B}lh}{{xKXKFwVSC=L(Zoj z-yn34B~vb@v-N<3%iv6_2f`7>~RvDk+Mw9mOP6Nr+=y3Wj82Cq;?IBFM6#cr1u@ z^;l$wCXP$NS!#rvf@b7JqNEiRzNqb&%52576kN8dEJf_5P%u!4*`n|K&+_KZn;Bb9 z0)^lAeu=N{yZ4@Z_IvK~?!5837p|{KBm#S81hY7I;er}|)usjY|25O91Z_cUZ~^^0 zCzu_eWs?3+D~Pi6pHWKXng$ngHb8YiZ2K1}kEdtul6scK%F=_ze;pIm2h!+#s6aI&*%;>R{Zip zf2jSUKh&HxNAQ_N{Sw=zGBbZ5c;^NGQ1LeU-TV!VkW0038gA5n*9o7)X6@$|X+K`z zYQZdG^Q6k<2lT24PvE#z>*I#^4C1N58(%5?RniOVe@-p&Ygq7fO6O*RLH`A*gy=(f zm%vE|b^M3V_mf1&_%11jo=p)C-N=OU?IfpV@KoQEEaf2Z;hm1bn??BLRBtnhB;ysy zSM~j2LKc|zED(7c{kgozFFYu6FVgWd#>@E9v+kJSN%nw0QZvL?WM+`j(BtEGT;=u| z>N}S|&h0XZXDMDMIA4h_Yxk$r-sPp9D@gme9k#C$!>T8uAP0T=<93(~F6E+ns?@fO zlvbaxLE!p$gRfzO$OHBJud&)e5H^(C(=o0udfZn#$#nJAo|pnYeYF#ujvo^ku%BV7 z@9Q_{9nVQQ^kRbkhn!OM%GZ}U+sWqWJ>croAF5o#nIgBOI!5rrd-`+v4=BIIk-5V{ z-}psRYd5_HgmAs+MUVO~X{kB<3D$rt0W7QzLwFy&@Oz z4edIofj9g(@LWN7rx;q1pW%Mdvz6+9Q*)M3ZK?lHOqbZJ8j`W+rpKX}jMr>~af@^$9*ECK_b8hxe*i>ZGZu+12<~frIu7N#`@cXSv?P@|t3uPjfyl*JPk}64PVA`2&U{z65rS zww3x@&-F+F=&}CH@5bYTTrXD(diIMB`hEg>X?%fw03z`C8KIDwJ&W@e4^+Zq%~|k3 zJHV^d?orZ(RPa;fucUFjU2h8`o|;XA5IxSda=K_h^keZooDD7~d7-A!F}_#cgN{0? z3OztM^jt{xC=Ea}8$j^*1-Y!QS&=WR{YF_XP8-_XW z`{yz0H|!I+!+*ohU6z|ud(lIewf1TUS%a^3mxVSI{hS-te)b3)_z}RJD{d(mKPvAL zPfb$)Zba~0bdTtl+a=}3H}LDbBr}sY_y+m4-y{60reCgC_*Rrt3j;nMIeiKJQh#V! zT~13>PHBc;l#}trGteqSyaCw;lVb3JjnXg|}Ii{N=Sx%}NUp<1dx> z<6ikARKC1sM(`9W3LBO0T0ai|VPZDwA^tkCQgjj!(a-xHC!En3oWBCTD*=^Kjcfe4 z%;slbAb(`@lxTh?=u2Y?+1mFCp%%y5d@LC(;yTg1ZJpS2*f7CNj;h=?*Ji8jrcdir;$a$Ktne zz2F(HZQ?(|1!+lFh@C}pJPThD?*fl&2y}7&aDmvb%?~vm+(o#;?vgy)r20cLZ!o{) z^JxyrFzSB=qZP%0;Oho@g?=v~m^SX<{R`;5KVC1V^2ZyemB%q_8Ikh1?0-b=1;G>Z z&i^647+n}|EiQX1;nPKCiWQF39I;=Ur~7zcNO}tY2!9TLnMVC+92J2$CvrRA__Lg@ z-(kdEFM6SPocM^p&L`gd0THy4@C8O^qwCwG|DbC^>EikkT~DRfB(L5!POH+@1T7*t z@8P6s+?gW(ga_Ize}RWZy>h!-QS8zCi!wR>qKX_p4SGo~o2Y$?;wL<&hrS$dB~&55 zQP4}(xPCyp8DrTTI6f0*Hf+ebOg9(|3_J1q6V=YG)Z(VwF{#ShZ%&`C~HGq2+Y zm=AkTf7s9_@V3g^BQq00KmCdE3#kwH4C%4O(GQbxr>VT2bYcS>l0M*fNK;*x4;XIP z(7`FKs|Y>~TR8tP@d{60?KbH@EBP+MFHL`%J*Er2zq=x zw~!p5UmY?2Tu1ydy8*pu=?cQ9xvB@*yx`keC-`Ucf^Vnk$$i2=r|U#vovbg|`cGIV zfpRV{<8x2lV#d$bA8q~;_9-1Bq9@7V6U-Nr&%-2ILNR!l{1={Np#JKp%5_BOkFPVi zd>g}AbXhrH+K4aElaEtTyxpQJ{({?uef5%VzfjUcvpMzo3q5eh1aE&F?egp}lemcS zcgI9-as4l|zg=d3yP00ITfbk(75Kjo_=7pchwNGDuG?FNuhIPwwMzzX;PUK<*mG*m z28I%c7un~1(#erIiQpCVC+rickJl-+Pf!5+Y@)Q1ea>S0JgxSqa?GD9wNEwa$Ug5S zVDyyR=Nf+R%^}V?N#DWr}i4wrKSFe@Coq)sofOp7d?dAl`hr)WbiKx7xsz=_RD%8 z-IBg(ynIaMJ-mhM*Q;GitDrx!+k3_D_;NM^5d?9A0GCdxi5yW+#H@(4Vktq&{8~F}vPG<(2IE&7`li z&l0oiiHdgZ!|x~lSiBI~`yRoo+}@kHz;7S7_g+%a$o|yslIyeDAC*TIgr3Oy@{zu=$Ciyh2ul=tDiVkluw^0SBrSg60A2>g7!mJwcv zzv%T@?DBK057Br^_QrOpb{g5`h}z{bwM(^I!N#-8J=N{ zbsTNz)x3+wrTppR=v6Kp#;5YLaDfzph67*x(6npA0TxJZ(Rzr$P1uQwgjN zVSey5uJ7YnU+eYa zQ5#SF{!df?Hjct>XCE=B1lRUs@(hknNd!T){X8WSQv5oVP)0G5woZ8_@&0Nf>PdDUgeggIXi$Yy@>^RFY zHB0t$-0(@xN8@(GY0iiH&q&&LiqkT<1@4ab?QC5xMfgPHz4Dd(pTKDrxNb=L57!CY zQ1_w372+U5S)K{HC<`ggy<7T`-E4^i@Me6cyf=P9u47Hg3@QS>XWl9LF&KOQV|sr! zI~XOtp?zH)(K9l}_`BgzPUC*RT?2m8OWQwB2Fn;hpKtw;hsQU_$M-9*A-@tH>g9gI z{X04J+XF9Oe}42!%oh|t-7hG^?_%Legx?*)XCLlPrS}T<6S9A6aU$$t6Zl;L?>6Og zJK^n@1D>__$CoXj?+*2k2hqBy?_H$dY0B@`6#U;rKG)>?&@!>v#lqGgyjtj(yA)6e zZk2WG@oS`f{02z@_e&$R?*1gg`!vBT-w%`i%#X$6()IyjEIla4)6+2h{l3=`U)l$R zAGZHv^KakY-$3-_pD(!(Ny05Huow$LWC{Kyu(;55ax1)?=%!?RcM81m*A(F%#&{8}|5Hcw*uIDDXE-|_ru3M-p3T3Wrhb9`w!hepPGvBY2xY?_mu_}pCydXAoHoXt~$*5vUSxJ0?+u64Ep#* z?pVHz&w%gmb6-mRWb@KbxV=OB(>QBL`b!2o7+!YdFqhkS5cX~1d}@v;RNUWNoMUpu z`pUZq66Rq@eZSvJc*XUq(md=7tOxyqN2Fi9niu`Dd3v~A^{ndp%5tX5$0N?4F~Z9! zAKWqF6X^8yVbQ|p3Y-B>Xq=Yu*&UVsO)uLQkm1tf_XoX?uVaSmwlO`>%h!V5A<5e~ zwvsxB-MNCqF}AK5-Y0euu7Y*aIJAqCVEi6Qz!Z;>3x58;W{C5NOx zJMU62gLzzWT;o8$ z9^{64U!!_)y?2F^jL#xnU-sL94`}yA(BCO|l(!cWFob1{`~;r2bNH}H#aep=FH z&_?j$Onhy9q%x6U=L_;~dzy&q;f5l4_aCg(bR zd{NK*7VvIUyiXC{J$E2ijH~UO1?HFi^xkDr8U)X7loa%SisE)V?=(*J@ZkN2-$VAK zQ?7?ajM4fs#v7}*me!TV)o&SIXn%y-e*}RgJ>#+V;0uw#yq%i*{fuPf&K!{*7MR^(VL>)3Ie9DJ@L5ba_MipNmDIfe7EMEq`S$_ z6B>by)4=O~T0(JK=?{7^A40kD-PZLiju`LZYAlC`Mo~}N&AnIN+q^omBaK(0bGX}t z;jUZ!h@H>#@!3l_yIlg;<)nTY9`_gVco2B#IlBmth0;E}OZxHU|0oqj_{I3;I!`d* z)Qpw@fBAMWL2~rxIoFYh+{h&BN@`9cx3l;+HCytwUYVM$^V>TG@5`xeE#T|;w37Ia z{9?nWAoXA$-=%)%>iB;BZ1D#@doSV&m>*DaG~Q-r|495omG*!)pIY8+b}=CRJmf^b z#(O0n#dC@;^aTAp@-{+%9vlDX?veVt5>r!c^r!h-v&$r}E(O6Z0^dUAc#oc3_5}S) z>nz$nTp;-)^gYAJ=zZVJ6U_fzGd~)%QGUFG{-Gz5+e*osA1TUhO_|&#!Jn;CA9Oq& zayxuV>R_MMcD^Cs(NRp*-OI9P1%N69R8W8r35H*nY41YuUbXg+H}vXmX&zWy7Os!JH04Qj7?U~!t+tI6HQjYlqqcPOrp?V4qB7dR&OCoEs{XX?j_@~vn2+IKs?yx?bj zIsY5c?uO3@f7Jgybhpxb50gRjb74$0zqE6XExidFZk4aLnJB{zr62 z{_y0eef9FHvh!AJaE*$JKCW$4+h<>SjFk5~*RzDScV&y1Fvi3>&#Ai$Sl;(1AWPtzOSbK0P$=sCo zuaA{4=5j;_Qhu>l?$h;)7(cO7n$%OV=y&k*rFg+3NBe5(cg>Gx^AfLgHt2eK9=*%B z#Bo|d^Ta=#pT#)z?4303=y+`7PcqOrSK(LEyZ2LDTPH{*C_|4cNIa0z^Q$SE7gJZX z|NC^N$mR){zv4am|04Zw>tcR6k?*P0?1+Gm7c4v7dqzl z$a~nxX%D`|zoyrVua|lj*UlC9MdR!Y?l*Utl=tX(Z+seW)OOcMT2I|hc>REmVM6?2 zDUQ}JL*2);{o+VoM%Pk>t9t3WB=2 zd;6X@;_E7b>)QdoYp{MS?)2e({tZQVmC8YpwMYM-q58+@o&P?&lnUq>S9u`rqNgTv zf&8%<#zLl+nIU<=+4%0Fy&(VbcNOgg`R`NS`i=CqQTnmC+-aO0+CD`i_e1AAB);|i zldUH|8j}2Aoca)Zrfi)lTJKQ3-A(nGBCdcNZ93u(_%}M z4Q#(U+k#w?KJx>eGld_WF@J6Jf)8(eCH0e)_Q=1V@^QZ4{avwo@2*mBAXe|4UOm$b zqiZt}1<_f2J&Q7QoNwyLjG0U?{30G#hbWQKC7h7I1UD!@PuBGQjQ+-(N_fvEJ@@IG z<>|f8hb^x!t@lTi$9YoNqTk-vcWZC!YEI>f`8nhssys9L-HE|Ld=1YCzFxMQ=*ZF^ z^qi|b@Ig(3W9^M@YY#n<2!z4*|LZF1kRH_kBH?BA4S&4f9FyBCJ-PYyZiv;}QK6ps z^VBSfoDJW(IYxu=z?~C+F z##87Q{xbctcJ_TH;9Y!(@La)QqVI-WujJi5RDm8lH{P!6KXyJ5{;NMWUi7_=;N2_j zR}wu-(0;GrWBZrg*)&(!Q75Uh@0RO8eNoS&^W9l#AFW$txmsZRW>^oSu7Yqt@!c); zU9aXReYR^%OZh=gg1PFSO;!XlE3QWl?=%6f?k3iSI~XMI>Fm*m3Z3p!~8bt10MMCW%7?H zy+_0CWw1dmD`_U7`*)4{exAMm9bT8QIM&6=F+ax>ZkPS7@w=p5w2nCuR&((|Lg8FHbrymdUy0ym3`D^o8n@8F{bEHRUfoJ`Ox5)SZeYL@9gve!h9MSqQ ze8z?CYzL1%dj9>lx2fC=u9yYGTSokf@D(-(mCjF&9VR(kD}u50(C{+RQ#+Sw zu7yaMdyUW&svop|Fg-fq&G&4-tFKo0YWFAg(L5LsaK93I_W8wn|5AYuxqP0+(TA=T zMLidOzfQb9N_YXkAKzU*U&<{N{4+D2!u~zCw2@!*T$bk4E!FjP<+EEV4kNsb0Mg@@ zl0&4&?u&3sM1Up-pWoX&J$}6W#(3T9!2w-=h4@9sMH?sLac%o$;wXxKS>h#Mo@dDa z0N%Ca=duM^pUUbv#Lg9>zt!eP)%%rp(fm;FGq8DAv~HAVHnKl8JXQe@?cea}Tp{}3 zxj^6o4mf^Jywrb6FLX~uPS*V_KCHxtB^CRpAeQ?RJVF{v@z^+R{v6}x26_*E4!^r- z-*#Ue-Vg5c#zTfutQW~s_0uhr{!$v}8vk;aOG69`B)%!k3&9WDhlZV3T0eq+#S>nm zbf{kfUf&@&DUPbBylfpy^r+_!^djRr(z5dyinr0RwYJLn;mgok;zyu_{{MpZlWiRU z`Tsa8K147**}TB_^#bq9^dg2=bUwF$+7!nSdC)(bA3%=a5b)R+!wd7E6wjvp_@-!Q zfaeA!J~Td-jZbQ~zWyC2xae=3(&G0(vYu!A(6;}W^zp-ZZT<`T^?1MQLH{<+`1cKQT;$0E{P5$juMv8{J4Nj+ z{s6z`ca-aETrVNdG_^zhYsfCU=x^jds;T)C#8trWBm6J*Ct?k5w>%2zS==b;IKjhX z{@(PyyJ*k{XaZ@|2!|)#jkn2-s1c^;)}&s-SY&0SD57fyO&7b=CQCB zz+Y4I4BmJ2;ctW76h7$uG4bBzw<$e4IkkOrzg;!FrvB>j;5D}luihA5UuC>{6|a6y z<9xRL59k3bYVls-TO4oDnI?F)&OV*`{iK9_>SrNOJdqwPmAtJ3`u&|!{dq5?ZcyU1 z3~L$jNzY41>wkKVAQ?Q$^c^FxkXzJ`t>3TI{w$tQ`K4;)h3k>=!pFn>)yIf2=1=V2 z&`izK7@(aCi`Iwj`*d9&j{KUQKMDK9Z`ycj^KXCtG^zB{GCcPSdd%L7eop9#=v*dw zTmMVZJ`x^xQ8`@(|1F?PnvwpB9bn$h?Ue7cDDz4}!1}fNQNJ)QddlXt5r1_aTYQ!WGhSH1A!}BIP#kUC<=?J)8vQSEBn%^gF@m zUW5fQ-*9^*jqbgQ;vn%e@$&Na!f!h-Y3nD}zr|I3GX+136N_{y9yXs>zi8_(ML20D z?0oDh(r55h*FjP<$*Ae^`EK>DqxXKii~wAmXHWCIw5Wjf- z8lw+%efxI8a}WJNkNKUjUh=j+X#UN_XGQVZEOIIO<6)J9*_-l(_($Mr z-$wGeg5ZPw8`weIzXFe!;eGzN$k+UcuD3>hAg_9%^F-5^c-)M*bBh^#C2~X zypB;{z{B{5@-}*J^9r-qjGkjJ^VczcJJ$hlbYAiqNTPK!i+{R%w{dy6PWY9YEq*vu zJq{0vUSr*q`Lmv5qeapc@CFnQ zFGx$O=fItP|7PER9~3<`|7i1oNRM^DALS%+8s8)i=)PCtz!WZTrYBA(){DRppT1G> zU(hN!uWR&O%k-)K6+|y>{0bKcT}6FR`tC@hd)n701|f~;5q$;Tz8*ktc6xea{^oqw zy?Ecmg9G{Wk^b2@o2r2YQ(lI{z&&Rt>j(6OQqPLo`n^eSKu9tYdT$Tml*02N>U9y{z%|>KvU!SY6h=hjqV^NTqb3iFN5O1*DvgUgZfM*FI$!)_ z#9yMX#^1%VjlkcNFg{s1)KylWhdJ7kuKCw=>Yf3Wf1&Z(pRTJ(ST zg!pN_=fRJg8IFhV!x-Px@9tP2e6w>i#r-Yem(2sCeMtN6SmUl}T+wkYlB>$kgajg3aeKzNU#aCNH0^|4Z~b<(u0|4525~{lsvk<`?qopl_DoTdjZhazX&@_4hAa zx3udX5c-Y(e*eEDoi%^G;~wQxR{D+h9agpo+=We&zAepZgon+mV*GHOiqE<;BDWYm z=$BX%?IYWMEcp0w!mBzy3U{IMN9`lR=XypjS}*qXYZLJs@LxeyTz(Vdl}d<13H#E5 zr+$wbHp}?s3cdW^zDIC{e$AiO`uj95bo%QPJ0ah~pq4jj{R5hB)%<|wTO>c+A?e6A zE#D&PMdCkGGgdNz-Sc!jw*6i5bKs}#``I{cdT;j-NBVB}G@8EKedjv=vp6cwKY!dt z-0R2BY`;2>8&`pV-=8Ys_p=y(yLUX|^DdRA{$7iHA7GPlYTVOPK9T)m+_H5?}!SDaWcs2=Ko8RU|zii&<^d7!Sac5g> z{B0l`i^g3EkLcWi;L&}N_>DC)p33{(KE4NlUysxSUVW6WF0V~oFIxIWZ=H`s^X|3M&c0s^*QWV}8&bcqwn_7+rTy9#&8r^Ryh-nEw|Qv9|Esw= zum2-rM*KY)v;Pkbl04T5eEZ%hiZd4y;q*9J-lI9H^7}4+&F5!`O~rA3tGxI5@QK}I z9~AGR9_+2gs}H_2pJV)UhXo(-{dFYg9U4cQzpbPXN#b`zx5WvqijU%N`?z-A8FD7| znrdJ3T(0PrO8xHD>h~^~DSod};l%I+eiPKbkL({$GLQ)o_9yATz}bF>-j8u)rus9& z6;F!J?ZR(mX3i6T24_N#t-ITIc;QCz1EJnK80x(n<7A6?;D30$E@+;Z%zo`&$pg=~ z5T16=3f(&>`ef&wbzRH+C;DfDOazbf#3gy7k} zli8{7r~YlYs1KNrzCSh}T|=yaJ)DWz!#fX>KCckIjZ0WUa(W%VaC_xN_e!;cPN`?# zJFJ=Udht7Z#BRIiOTC9)-p>`ob^T1|j#b+J8fm|HtE6Fbuaq}xdAGcWe2LuX-X+X? zp*QBgis#0JkI_1_ofouq=H_9BAFVSth+g^pX1!5j`Us`K=nD6rGa z;kVgO@8Rx>^Ii30(2tK3-d*G`0LS8nxvJOhsOYuP(M6R|5AX?ew0;9Pw+<71Lt-Z= zCw5g`M?n4codk#ajn~7t3_pg)`bGUVs&D&TxECFdjT`V2{}uBSSP6xnxG;7fWCQsL z)K7j18YmC?TSb4Oep9Uee64?ZtUe@!`faiLPuKcy{z55ytG^{ye>VKqdcniiEo|MW zyI%asX6grgO3`^SJgyPYXzf||$uC_XhU)tR#9!dsTdCgMySO^}0rAteZ)g0s?+!1$ ziyRg`KAh7E2Ow-5ce>9Tc2NiPgc>i#e|G|WzAeVLw@`iXZD))R-y&f;h2xga7P#v~ z-|csx+)|<2?7_x+w_N@E&FX)Nr+AFM@ea?h$Sh z`nr1ruFc=W+5v{MBdPu61s?oFN!>?Jn;my;41lN%#hc!vp7}rU8~zP`zn9WV@#Vi9E7fQCmuTHj=cka%`^e{6 z+}~X%a>cqT@Ytc_y3GfU)HHBBY;lau=Zqhr{?3#;TF!T-)5f7=qDQu_ZR7M}n-@`K z&}aKsMsIxG7x-V)DSV*nCHBkuNVMVc_6Nn_}V_eni;Q9dltUC#x$Cd zeTyEsm1@rqs6B5K{##tWV@(x%w(#u0n!q>>I^=*USADW&cerCHi{`W|I^t-8&T`PX>nEFxG8`N)wzU#ccs(t4tSbj$m z^=jXuH)h{q-z1m2VfB|WI?cW!{*S1ie?agye^GAVA}6EU;%eL10se0z{J{_AZ(iV` zKHIm_?cbZz!1Sse#Nu-Moq)$<*FPj$!gU)&&ld&L@LsGoj{pyO&D;wlCbhQ1Wvx7k;?Iq95i@$B)Q+`rMM|_cl-2 zOs^r&l-`56X4Vxl58Xrzq$i}`BSlKTABlwWCncZZY+!MP?Jq^^i+10-o@?{@vlHWA zLE1yVPEa26Z#=ecv1ZnD|JU$f{r3FJgS3w1hE-0{?^lUjT&@Gv>6|GAB=lI^;oHqO z>ARf_OB?pTf%%7f(a_M&g@)0&kPa@l^*H-|tm69oCN1agX#c;3{|FB@NqR?`Q?o1g zE0iP4jpPS9U~iLjPQ0kkrv%UF_cA6qpA3$0`s>8&Ia|qZ>9|nD?@SE8(~94{oL1Y{ zusFgkQTx#E>%w)T3QzolukYJp`aZ1w=>o#b?zuHRNY%*s1lvCe*NOj$_V4WXgYztA zKBu*%3j8x!z!!ZoJ<8O`JuEi>PrvyNA*5shm`P4{%yM*EJ~e^Y|0T?*QQg zeLYC@+Iaw@yNmn~X3e&5V(Z#-SA#qBUgJ}Doy_;bn!f{n zlces5*h6@u<<(wp)cQw6AHy3J-VxQ;8?|5E-;MN6*XJ;=NfSt49!x*!0v^!4pVG)b zELZr;xH#JXvU5D)E!wZ%KNoHkJbn15l%H>>)aLQwElS@;krTdmKo5R9%!7c>OiB%( z=w6go!N<-G+dj43UtRpY5aE-rj~tH_q&@WbG{LvH#J>MQzvv>q9x{&TF+=wJg9nV{zT_}Ht*=7P9RC!hnlPVI^lky zql@H)^2K6ayuLu>OyPbB;AecW^(PzWp+^tUMu)8@Krf(wh?CRQ4)GNTP0{xUfRo`_ z2GL7!@z{EzJ1TfY=P>lVO*~F^%S3QO!?Evm zfERkU@zXtD8X6qnPhyw?A3$F+F#HW~;ZI+U<_R7i$PaJg-<`Ro(!c+`DDb!YQS9C) zth3|2#XUA&rDjM6u;-853491KdfXCDqV*%oquzVTVHn@W*GN74{>|58j6dj)`&GH4 zJzZl({#X2IbgoX%B^C7zT=e=`%h}@hH0rNxJ#q0aDc?=xfCBUb&9d)WoQ*$fC-7J3 z!Tg~4dH?(t?8DYOtslVc`JOj!FO`06KhMpV{NiPjUV1I4FVcZ=7;=1=cnA^z?}Nk; z(*wKj>G8k=J%Bgn!9)IeH*$Ah2E!FIv##hkL5-6P#^VPO?naS@2Z`c zUH8?_J`Fl>zXI!Lo-*`6Upf9bB6-jaxPW&7;b-#4xoW)Er@y^Xa;9IVAO3#S&F8?U ziGZCCK0l=UTAm0#*PjEQP3MWv-vK z-`|@*Gucc(21nzN-rEq_$AIe1fik^03BGvr z98h}jd&agdVZRrIeJbyv-z}0CcCV=6VfP2SA>oJZ+qfaIFWY}|$_HB~ip~SZ)}!nk zmecj`)OqO9!TuuOrlUuLO8=+n`;1C@gmPbxT8JUgqa_vfXhQjZvW)L>zXUk|&IA8V zdZhl*`~>_H>ro_MiMO*uKV`U`x?h?d()%>l$$jZ=NcvCBn7;qo$@~&2!%oq!`6tsi zlVkR<^wYUs0;a6qbKkjs9s>y1ihdXM@+ZQFNH5Rd&YH=e+5N~xzb$%J^xJA*=i#?s z!gLqy5iZicOEAe-#)=J+Q$*R&&R%+J-)^9t>mZsmEL=+*cZxu`)VWB!7ly} z;cIdz`sp#{^Jp2LCu8)FYQLAWUlaYXb3D`cYl~QrMZY$|{hB?5>%`9OoOg7eovs(3 z4_~L=cz%8hdIdgR$$S+(Hve7RpHcjx?bTC#f*sG&uN0|_XB-_UiVW?^p|73KE?Qj`zJXiK5%OH zsZS^V_~d!=e^TkicYQv-X_d>CD*BFgzP=w&I=1-wzLMDx#k>A@96XNfk#funF>!`I zpNyR+nSp-v{HUE@0Kaz8JUGR(S!xHTSA6=-el4E$=|aC~|2?`e*w!H|{wePNosQ|3 z*qyYk;M-3+u%3#jnf(48^nxDfB|go@{DRoa zyubk%{ zZzSxD)Qj!xCB&DNv|J04?DsZPGsQoGzR!1nzGqM=m22GRE+^D|~2b{+-vJcr7$P7b}#%#{9ZJu%Yb z%LQ)qy}ZUbsadkVi}^Sn<7c!UsQZm}|AKw5jdF0z)*Ed-GBZQs4O@R_y9eAnpv$@q z=DCm;ID~!y2lsNGiur{k`30NjM&DKIIUYN=(?!!^pl<8YsabkI&>rDG>Q7e7x>558DB!o)Cc^1jOI@`*FnPt|E@If&CHVD%Xr*=MfZa%-S3|!_~`e`6i-I- zn@0T~QvEWyFBL*8E-^k8?Gx4& zp(k8`UnRo*eFC?00Vx1I-TJ#(JM?$6!u2Fjdf?aa#N%ma-&tw=f&0|)n4bgP&xYL* z7-Ca&uQ={gN4-dHIxn*CR?u!^2mFuh*Es$DysCelrr)XVU)3J=i9MXt|73wZ@x}9} z#~^QgU&;RrRnWWWJjWV=2lj#0&`+ePB>t5=QoDCOya73kiwn4(TTTq4$8F+-SHBnz znJB~Ie+iD7Y^Y0LshLlg_GuZ|+=?^<$gOOWwCNH_m*A8u$-hz4J@URs??no;X%q(` zog3uzC4!Ib*M(Q}>qy>^FZ99o*Uj$m{wW=xOAtI)Jd+G$po#k@JO2iFe@S+ijn)b6 zch@DZ!8q+b{Wi}nu7ljp#o3YXvc9I~WH=w4bG=_$<9Em5p`i~*u0=@_}4eU{n+{Vs|NmnJ8*|(d~e?%>jpOdz;B~x+Yf%|V&o{V`vYZoFn%vU>SOKy_WLvrIRR+jn?~nb?vVEnEmZt;Ty=*>ncfWD z^M#U}j_W<*4oM5{l4fnWuxy1SwGhniHg2MT7p_6&*w-wezl~)_p*aUeC&4w zqVY}Tf_m>F*&`jH)cm;Vp})UMDjbcMHa^-qysb<5d^-t!E(kt2|6qJ<{vq^Q>=5g% z9OoA#?o0BoRZ<*S_zd&e?ivczr@RSubIV< zq3)BJzp(qLjL!GZzKDPK(x)W`v znfQaqHdAvs19XKAT+a=)aT?u2YwO=SUL}LoT;Jvg{=GVkpV~F_XV+v=ub{UWxgqx- zohCZGdT)r;!%P$Pz89-^Pplqw!S%i!tM{j|dWdWR@9VL81F?FwTJOtVJsa=QzT0~b z`u;iA9(sj(|L)a;T|!QHpT+w;W$3}YI34r9*WLy_YZ5u+)10CmRhzPLYb%Xopxe$p zbuN&22=Ae(Rxi>k5pNKm&+n?8n!-@-Dv>bAIS~!gg-+4xny5< z|8Lx$QT_-amSU@;{<74Fo^cRC56W9#U9@xfUzzc6akPFHol7|jJ+Gi9mFPKop7i{f z=J98vXXw8$kA<`=)AP*ppvTQ82GDcWH3ARQIOvPJP{y^nX_OZE6RiVWBk#e#KYI(| zu|o0|hh_Et)oSZvCI`sT^!EEiH{gZ0V&19WyEwrQ@ma-ny-P%p@wmhHGt~4f>v~HV zan~#KTD%hdPH92tf$x_Mvwc{=`{utE{i0w0 zp9tQ=+^Z*V^}D`apCtUlX7SUI*H4q59s_?+VgysPnaOujqmKuk486 zlbW-Jo5ka^(C)#wPoN@hei!`-zl+r8+XlkZ{FXm{#^dPl=NLaXF+ZYpCjD;6?t_fh z5j3uk>%Zx7Dk1vq;}PfA6zPfa#~nM#{l@8BwD9+s!0?ca=Wb+@>$#&RB-Q=7N^v>P z)j$v8arvF?#GkD2Z6(Qt{f@@F7Vm}kiT#^g!d+6|jR+nVuVY;qqD=;0VtkB0nD;}X zcHdVt@3QmgBV$6ZsFeT@f_|HqF3OREqQ~doAko8mPxi9NNqih`-^Osl{T-4X+QO;d zF3$I@q^HHW@M)r_gA?2?$-k~%+AsKsem_P1#^vJ*gWPUW-B4M-hVQ>nyJYZAF3%m6 z__Ala|TI}8piQGa7GlQO&+x|-vx9eODEu~m$Xh8F_U(-D#bnjT*$mKorf0xs6 z*-}oUd(P%ROY^;g$9(B1mlt|^=3mL>N%~bZ`~f-ldhxa0+w02*^0n`zP`~tdNroAY zU;mw4U-YH8zCJNUCQADg`uoqv7!AJH0D9-gVbEh6Z=jEx==(;D&naqR^C-OELu;hv zdaC?4f2-%aef+i%e6)Wp>+6ezPqx37SG=gdGg@ze*1gPM+jo0*e~`^*eE6q!q0mJ4?Ab%?{nSrPKsf4Kho}H4)2os5uO#s zRp5pGzRdGQ=`Z@7L_HU0>!RQ{@U=L++PNB=??wHt6g(>N#n!Pt$^D;VI`KO?=*QMi zs*UGKzU_?s!m#)QpWlFM{04oOVZ4dXy-PpSKR+TCZRbaN^nP!f-x_}`&X^9}6Uz55 z5Z!KgQsk`rGMkmpDg8a6xIWuHy#2m*GLUi7r~gEZ{!gHvk(1ib2~MZo&q481Nxl`k zbbN^O`O}X}jxwLiGb~jo;w(9 zkUb*tP^aow_K3jmyh+wYde*18VyNq`c0Q|Y9aYEmB7cN0eR^*O;wu2M^-IKGpw#Ev zN$_ciyW?{!>~9+-?~kKjBmFRaxA(A<7OD#V_P(Qh9{=mW>+|Qp>vkWncs!#15BUEn z{hbMxG2vTl%+(wEknG@__%6*Ob}|YFgZr%YTgZExbeUvv@FC&s2Sl-y`7T%lcSA z@3d}Ac*CyI?;z3Tj>&jp_(tdKwLgms;V(f~Dj@=&4*Y*3_%_c>MZY_yUvOHScaCY^#zz_dx-~A{q4(bBbRLV}or1`0AEsNs6WF19 zRM{aJ|2o%-VBL_wx46{l?^Brn=pGWkzGH2gpkltzB*=YmZ0n@9^Xj%};dQ!uQ)E7g`}X8 zDG1WX?g{n%C&oLA?@)jASu$3jiN$eYpTun_Z<*nji~sZC?PGW{4i@8|V5XAT}io7?DKlKdaSc$Lf+)u<;uin#W9S8U+>i{s?e~b8QeBG#g)!%7A zJD-2KrQ%OBGt!J0%1=HSeAIK_{~LV#+N0Cs$LTzT>fp$_nrk37l2Q`o+pEJ#J}LT zoPT#ulYje^f3gxU{Ihkq$WOHK`$)gThE~zvn^nILZIJv;s^8n&s_OUVbLjViD*D|V z)9;QF`AB?U&F@0arG8xer=3q_dnxhb;tzdzZLHt>m@a>vU;Ox~GC$7iQ=T8^xZm^7 zH?Vw;3!ij+uH?sWtf=3wV}XQ+`ni3$y;tDqcvzelPb$6>nkt`Sc%k3NC=N;mm<7@J zt$1R71-(E#cG~B+-ec#FQ=l(w9uR!=-l%fEpV4v|C++^#a{ddxKL2}}|AK#C?Xc2w zK*!NRPW^E-&VP)^w!}kGC*;Jb&CP`gM=S6Gx>S`}lW5@3UIp z;)!cD|A3^BOV=(huGm_9AF^MNeOuPE61^1v<=g3L&rZwrQte;k=i>TVY~9ntAL}E& zpE>T)1H9kG{2f*M8sjw5Go>5(zf%7Cae^BXzS-~9x<9Eu4a(h{WL$H1$#~||$Ndwp z@Yp$fz~9c_tqDKiFMYdiZ={1t^rU7|0X;?kAlT&c^1H`|PmkUc2LAbQ?A(znh#gq{ zQ16E`I}7c8c3I|)=2L)o;8!F+P!_FQpNIT*O;dh773?D!e3a#V?s+1!J^H<6$Sciy z-N*&tOWU)^SoHaAoEN@;`6zz>Z1cj6%EuzL0r}fy5g&Yg%k66B_nDe>RG$6~;gjgw z`Olx1O_NW{l}|eL0{!LlzRQ^{W#@6j{TGT}=A|5QR6u?UdiN;BRxUrA%fp5?PF+6G zd@HBW$KyBjQEgf$@5lUcXY@Y!;NM+EuY(02SoSHKSEBw`FHAiT?;q{_>)*Be*zvw* z_$T+`{fqYHN9|trGJjS;4Ox$Fg?~M)d0N`oLV4RS1pWoae?swX;ndcv?VO?QvxN<5 zEkCaH>p8XgEwA%^PS&*0BjE3)@3vC<`;ox^Y3V=wILiK~_2|391>!&P{+isu&*S~h z=0ARaxS)8xbL%_)^MiQ5xBYKk9_sJtp#DE@pK~4FKe(x5L%2Y+eAmnbuRj&nfp13@ z+8^emWS^m4<@d*o-#V^P#z$=jI$lHTWASqdwl0VDOyADhSG|< z&^})-zlHgjNxX#jQQWZ(&V$a;68jXs`*5Z+KKu1Aq<-x??5gASu<#4(7Zu0rJyH(* z-$&mix%?>OYwMPHPu)c89>~9+_Q|0i-qUaE9)Hs)Z;#NrA>u~J52>9~#=05ct*P0@ z>o(v^sU4%X><3U$kPL3)JnHQ{2mc@kf1kH>UMY4O_HB#g5&W^gJ}7eX`3t==yY%@B z(lMSQ_2)IMRKF}9()k+rwvYMSru^N&X~bWz-aX)N6~5RxsPLdfqw)P&+b6O8FN;gF zg_m)Eoz1$RT)0{DgNl#v#qL43``W|i16tn8=?f*%LYA%F0{y8MOjzI?@gTDjj! z@`e8S@`Zk#O};N=`3gT=LHJoozJEyawR0?SIrpq!@&nrsbv#1IcP!NXRH*kkCj&Vj zfPE1>`0kzU%+sUiP(R7wex}c#Uth)Vh5xoc13W&y^$o04_xB%ro~@_j{n(nB-$5U5 z{>H@v=5M(E%q3t^uzKSs-)84;@c#V|2VcSaA8uZE+&{1Rx~~_QC2RB*C)7M zaUWC8^@eL@e$b=)WAXL3aHGgOevZa|kIBD(rx$qdVYH*~sDbBvI=2;#Yg&%?4{XPH zE8mCs^lt;4`veZ^P41L^l}Enn^LLWziO%Edxl+4d(d3BrD4c{Vm;b2njhI;~|KaHU z$4lft7`-o*zt}b4f2;&QoyV#F2ph`ha|1Dbz!4^&53C16!Ux=Y0{t<)h|Y-mDKxtI-dc0y(fyR@!cC9 zyEpHN+D-gBId`|fw>ZMpHF1BiZ(pCXh<% zZBkDB^8H?W<84xY4<~{7-`qT5Oe(RL3&KN_Kf@pH&NSzJ`3>WKDUCP7brW0+&X?MAd7xo6;K-vy!m zSVyU!7=)gC{_+fsf7#)8vptX;)GmttOCa;V{fp|}%zyZJo+7;HyJ+E)hwmu$gZUUV z4|p7TJDrc+|8>T<^U$Q=pO<#@J0D7q@Y^-*<9_J8IKRid6mo8_C*tYJYb^=w<}`xCMQezOI!>~5v&{Gyp8@y5So_Vf_I296Hpb6h=%M;| zz;VpaeunSzy__09eLF*(03p>{Fqed3S>G!o&KXn{wkos;&#+x$yJ^XIyDCKk9 z|1SrAdQK;!=i0NwG7e-%4m01A!E>3w?C{H(jwGFC#f$j3mkd6_@13@%bC-hmJZ>J{ zb7$*E?W-1YLG*hMcf!iZ&o7k&`u4jO_B$i(s|1k!e!IIUE%jIFIkdeSIPZEmq5DE4 zf0dpKfm`#CXqYkhbz`hB>g1Q+=HeylzG zYJ|_8ddgv4wV%g3w}%vj^P&g#`yRCJs^wgab3B}n>lxtYL65LGqKo2SmQ$`#+5=De zFX(~M(~}JLi(H3ve11+pzxUT)Cn)Zq-??Tu{(Fw!H;(dqy1$&$N0$Bpw>N$`gL{S0 z=kDiXqGJp9i}?&t4%clHJTz`ttoUxP-O1k}Y_IK@!V$f#wQXFlul5Q~ch$D?JfRX_ zu0%XEB>kZu*dyWx^oRHmDbAB`^3EB8k6USeK;K0R-&M|GLyP8x4>oU!%fWuvjMf*0 zFZSI~UhyCrwh&&G_IKLA=L)|E*uw9{pW!V zdXJJ{&W>zRKlX=Zeyo-8mHC-Zuh1d>1p40U#S@`^zX3cj9z^pwj}PpxJb%pcAvu9Q zlMjAR22W%+dDYW-h(5`m?v*rbRy*3;!tcXowWGaFnpZp8o7TMAQLKNvPYm%b9`yS% z3iZb+{>EeR_imy$jl7NrU4%69yEV^mPI^Lr@?*chc-vCR-zM%Zc(I6!{LU-6 zZg%)(I__-OeCd2E8FcY`mzVcpgN$1)|2pN1&TsN>;(TYr`vgv2&L;AB*MT z<|#g=2fG*@j)#Dm4}SyMIr{%fhm1q_c;k@yUAm8g`EL7q^gFhi7eCxb{uVo0@ULK~ z4We=Q;T2meHf1`Iu276hG*-kx9K7n^6z`367dyMsr<{O;iz4%k*`&se9_ z>&u)Pe!mWX`o0(+tMU79V)d%|(|5)AeImy1i<#dimER{S^SgpS{p%P%k5}R6N5IdK z)IF))>TLq z`CJUruz3^Lx8J2leAYtm>AWbvhu>}EdK)-z_l3DedWrW9{ruk7%WcF*#5aC?i?{`G zE9@Xkd^f*N^CIRa{oXvop>;#e?~D46`~58hA8>jBXQ+egyTTSueLOa3y&Gb3?&5j- zCXH96ANp=Z^MZ%1EBNqazMs~5n-tFtn%|)LHqQ6#@8YztcFSYLQi@NS9>b96+biaW zn4i~s^K+ZOVV({7nBVa6m>@?IHVEGS`)&MwXPG<(_`T5O*WbYJd&}x$9zo{>%id!? zLGvtrp9;nZJKP(f=j2GQKxei1A(P1evVqD$&*yF-y{RqNn-g>&AN0l_$H5Pb&uG`+ z>&@_qpVMocqvNzvd@x4v(C#^`CJVT@Cs55rpT>1WXsTXzcgx3FCO_N96;%J9Pm z(~Duvi(b%u>de2MhUw{t+3R%mBo!3Emh+IyAG2JZ?0LAY>$+$@KPYw*&F2R+4=slu zIv{zS&(nEG=2O@_D(`jwH*6l}Jn28Dz8s*RbUz=rgWSJyEBTuEKC7;~rxGug_`4wU z!LWJ56!7TW|9nXgwQ*|Sv-$lrk-qqLjCnQsyY@!X$HOh6XG2Y*XWo1S`1$R4ok{0; zXy5urrQ>@V{oDtvME~bvJ!mA&a5HoMoc+6xm(V{P(f^UN(*G8Q>mvF^KRfqd$$ah9 zbyo9(v@XGLQwbrcyx$F64ts4=d_Vi=rS!nB`1@8vgr7Sm>&>ZI9};}>5|`6DF2i%f z9V`dGzYAmhx47pb@PDXY_+PkC_@8I69H)u@((e%Wm;asu)TbZ?NNxH&4NO%xbEMeuzCZ-&VRS#47{DFP{&f2km}& z1C8h8fAL_RhH>^>>sQI(`!a6ox+JYX3BPrHj?SNJUi8WK@yQ=EnM#M{an60aV5!dkoRBK|D@^TD8xTBZgcrnb*s>f%aQ8S<_dzxqPiFIEAX%Q zoc?_)Z`bzLAL88ygFBgTC_7iygU&`=G%YFV! zd+V>r|Ha%cJG@NnQt#I-?lZqb_0ag$Tm?_#*8q8#v+?VybKoiM%lW12fvT@q|A4B2 z4*X$y`fQE+!)C!Z8L(MLe4c*0p8|4m-DBY@1B?SnIZw6D*p{hq`5!`sFB6Nl&Yd|EYs z?((JlN(M(64_7C0OVx;fn$9}KTVm^wIOz%g{p;6heAIXVad5SD$P=-8V=;I*PX%}% zLcKh=DSA9Rwhp<9_2)u~gYvUEMLQXXO8q|UfQA-^`_cB&aVV&=4*5B9UD^Bv3^zL> zhLQ}PFa14P?WzI|8uc1rp76HbeK8+^ii+Y;kP zHGR7wR<9c0UKHb7e~fRBFyHnu9W=gjIvss`X^d~ZRrvN==G*HSZg!-XQ}Vmar)uN< zqPkCUyi{85#|w{fd-Km0msnh6ejapOeUS7bFLBqns5kqW=V1Pzajp49#LIZl?kKej zYh@g^a=cGbJL~5odViGtu7TBqe}$g|tf{H*UyF9%dqCF3@ZRFY+j*3te)da02A6)% zfaAMI8eaquq}Q#S2c7VfbiXm@-5xHc`K`=r%pVl@dljz2tA4&_fN|}sy_eHnwFmfI zNu_=72MGVibH3&$JbsHE+V`j7e%ZgJePE`C=4IT!KdxXNd%ovu==_Aj8!m%~`E>D| z%Huy*(-zZrn=d_==**6^v7Tq<6w2n&2e|*SGQ2Q9v~xhv`(Mwwno_?Q%|r64Z#piU zKAr767VD+Px0Uqf%4zCNYwTPW*70qhnAUNbZ!W*jaIxDtKYZ}{$e?5X4;`f7U_FP|=6A1a9dfL{UM{PP`YvOBD|kO~AikA)O| zjH=PS=c+dvPZs@-*z$r z@+U7N|97~B`Q?V1IQ8jz8Q}*%o+eP3pQK~@bUW#j{VwSA^~n55xg113zdk)mSJ9() zvmT{Yk5XlNB>G+re_fyO^ky0H?}_RS&0|=g+2Jc0FZ#ZU$L;L!^EIE;{4&kYI7eJC zRiWIE3x3XUrV|%DkH_)yxS)l`>9fTJL)5NPTu?{tZ2Uf-xZpeYPa`fk=lC!4>vB8X z#CBM;$9-yd{hFG6?$o@*5jY11!O{K_r@nn%2>lyjvGTbb=#|Z1;4f%viO+Gu@9_G7 zcYitj$2Uk%U7=p&l)q5Yp)KNn*NNXMi!TT$#uvaFj=}p5!SnG8fS=B%fDiD%e%E|$ ze>~Ry(~Qq-#V1gF`lpT0L=4`4#PB)ot+N9k-~oJAD?X=V?LPo~@@IIx#r8kl$Z1)B z@%-Z?!L8&Uzw$@$kEgi48=91M>Zi>vz{lA!zxYA!*W$AQmV3D0#@jI+AI}w^b!fe@ zGQAN$Im+*8Usmgt$7eF$4syLGa_)H|wytII*({;2eJP9?|pIx~}aX`tzr^KLEd0 z?kE40{MOn0tQ}xE+q?+&|0-%{{hW`VTwmfR1#WTvBzc4TWl(;M^WzkTzkftbG7{OJ!_Uj|fP zep}{GsyDyF`P05C@xhmFL40t4`Q?W8aq7oUFFVKl=@H`hZ}a@Azlt7Rzeg z_}`j8J;-<^gZnt8?~yexa?B3DN%L>vw0d0d$_jCVKYzN5+gqGiTvr`nzvRaS2YDQC zOP9S&lVT_oZ5x8G7kB1!FFnA-_M;-TyQP5!?{9ITUz%KJj>#O-=O)^PUzng zm_J=bdP?_Ch@A2}B^?sF>3d39=ZcRLXPG};OYnUA?*M-1F@O49#%G)2)1mlmk#TGq z_{8T=m&Nee6vJmejelpGKV1xb@>>`W`reZ9a3h;I@6*{va4XH9uDAvMaf8y)Chem6 zlfbJqe`?@>z+Tgg6{2Ui7P^1O781v{1m@;xt6HBXX7z;wCj z_Z}|Pyqrg)dohLXJ=~nnpWuraTlcr~bGFaq+Y9zZ!{#P#k9pi@XkQQGOt*Kh1pTfx z&pYX!7anKmzBt-{2`##+7e+=gU4s-Qj z7Wp%L?`Zd7;rm0JKft;#=Fj1}`Up>q3m6~p6u&#{U_6T79m;pm#qSR7J4yTQ(7uzj z?+)cW!xQ=L@C4bB(|JPlyNXw1m5cbI_X~y_TbPda#*fMStA$^5{*L`iq#sv9ifAYE zxAw*lY5laM`a3=CjmJ5kyBb`A9t|^R>|PtJAExO&-H-QEl>7WYLGq{X_#(bOpz?o1 ziTs66bWTU*FMOu&1T-&v?yKGOOPnJ#x%>UFTs=9%?^KgBzFUaz4^)=7_|u}ig-=C! z3qPxWXIfd_;r>(1r=Iip-t-=pyYSat1TGVwFO#&metVkXy31nvux^syw>N&68@S8j z`tSjLAJ>O})c0vgBYpS>eJ}nEzgvgL<)t4tuZ8oOgq-mzz88O%Nss_a>bG$|m3S># zWDySNLJzc$%lJpDjS*)xNiC zM!me^L3j?5p8NOkyq&h-$=+ChX&%if;6u;I&oMp7x7-YRg+AnekMcfTKIc==euzH! zGt|2|gL6y|GTiL&0H@Y}re=iqad7^%ftuR+gyQ$9av_tQ%eDKo$9uIOYS%=6M*Q~T zPUg49HQ;x(d#`4KKVH3R_g*Dp^{U-_^@}f;^7{<VZ#{?ztM@Am!+P z67+fXul4SQ#QHxB1NFWTt5@y&w9m!()fT(&>N@7v2KLLgPRo3lnwo-L(SH$tlEFGg zbUJi?VvjUpP#rwlCykG74f7HV-!J+^0SiNfW{e6tS3FyNv?v~+P!t_nD9*}*N z=mX@5?<-wi#!2&^=>H!fZxJ)``~y5*MsyDg{7QbOl6(R02=Mg$PBl9ijMb|~_g}>5 z-UPYsEz(`fbjv)-zK@9HN|%+fTvgBTeo*zBiilphuXsB2R{L)K?id}_{OsOXy=wHn zK1T0Y%+G%J58-EztDMJ5~zH=PoKwQ~7R9O`o3Z?*&%%&rg69I8`1Z6n%}~Fpz}N$hj02NLXh9~IP84lubaP0^O*g|h0k{q z@${6(UowuD$6qJ7U3(*4LPt+|{6$K~@9QOv;_;X0`?S87c(mQl_gw}l)BGfgzoeh? z_{-k6YJGCJ^iX^)^vrAHd@6Atdp>(#jK9XX-gNvzwfO6Tn7#i+EdGK%v7h?SQh!-3 z{`wi}Gy`FJq}hI7d{-5Yc=_g$LduZ7ydp**M^wl^aev^GI+b3r_}q9{rdG-hbb^vUMK8*jM|Y~YN1zvGx!!7 z*AB^dAmM(QN4vbNOJx!ZxnVB9jK`x?BE@-^zl!s;p2Yg<@@q6N^LCfNRP!=#clqU- zw|!~Zr@{F(0PL$3di!e2_fm&N>9r(@&-_d{{c#^?A?08+ixE}Jo z)A$|3=W{vQ-$Hs8*6Mnj=ig50y0gD-0)AmV1npixdQ9U#uTxe!_k(jSCF4Kp>p36# zu8Q0F@;O2E0rz<^`xqp-**(qSq2t28{jz@Nw};)(`k>0;B*QPR>z&a232sm8KCGub z4TGGg-<|j+g(k%RHu;@IPfx&S@RLyE_@(}F-BTcXM7yRtrx8k~sy_dM6xb9-_(+oG2=uy2C__p5b^xmt~oHy4%g;R4bb1s>|{K(TwdU(D?`eEx5SdSZyeGm9b zx)0AKAZ5~1?w#zSS?tj6Ii-7-;bzD$iM`PIZI%a}6Jz_OeH_i3-x|=oty674b6Q`L zy#Kv2@J%Hk8Ne5~%M-ZQc98Y1^m}3H=c>A=aQqbWpKY!n{VuAjV?LLb z5PEDMH5oje+xhypocQO4R3BD}eC=L&w@UaHHmiNDg7m;Yu~)Z>vy>ORwcl?Fo5c@0 zy~mF3H4yua?l)9FI#2skKbsv+v)#u1A?WO_VxLWf0{jb^5&1uvaGPDn?I;<1Rpl&l zb-P4vPVdJH*L8>=(R=j5buv$Jdf#5SPS)j}-pd!R(|OL2&`~@<^z&8?Bmpz6Z{o@U&eX|dXL;ham0w;TRALxY5JN#bUsqA>y-(Xi(ulSc4oxG4gi;7qAmt&kf(DBixcC{6BLRu_v_M0A zB`uHa9Q3ADAk+&01^LV`ld3Z8`0yzo4H+($_Zqp{LQ`e0l}c-zoc;{($UH z+WW}t4`f9iAaA^mzFqQYKS_SBJs#|T+UsuLA$w1L5$p40`RC?Auld8C_>UQo5-WTt6au&sqn$ywOI4Q2Y*+k=9LfU?UnqR2}xH?N?J9=>86TlPU*Y# zoZ5IBKkkYPVP9q5*w5=|Tv(^G<6+oW6PL6Q-zbhyyCw6}&((9@hEq*&Y&&}`+UdO; zG_MQlFQ)pS^95AThGX9cMDII^AC=d0b)2{Bhwpo-R6HBC-D1r*XnvICvE=(+h+W_u z=5s0b7WXcK!|5F&2R5E^zmL!_;SI68yYoHTZa&WPWy6#CHJ+beFQ0LKslCY0FQLbV z9eTfr(%IZEV)xUFxXGF)=DpaD(iPU`{HS>k%g?_TB>Hrw`3AYP&*!mUY0bY5x|iL? zqX&4X{|>o%3(vnEo^Q$WahZRaNu~$eS@5As?S!s(`iC@8DePMw=j9wUx6dAS=1QuTkK%| zUV@HBu1J0zr+!D1=FgG5`up^Lo7mHg%!}atIQQQ2KCb7!SIKcm-wQ)}Vy^F1K1Aa) z{-k-Y(pR|&{C4pZ_x*mQ_`xRbviTA|A1w3U%oDrbfjS@D9w7&dXuPRhyUvqG3iQZ7 z*ZY;CmyCSbbTW2q`_I5X@efQr_)k?NadGd{y6$28)_0KJpUH3iQW3ut=lhJ`ItlS- z{m%l;|JZ)3v@i5qf6eXe@8;mVh0*V}|KE3Fc>X;>_v-sG8W8>HyLiku6A#dL(Kv6z zK}U!qMjSZ53c=BMK;sG%zu9o0&;Vz*1LwyfI6~I|AEA>C2LuJ22?x%1LvVUoPX};% zIB&y&XAC&g4xHT#hZGh4g7_%M_MP-Br*ZEkCDXtEq%i&O4dGcj{YM=*pAW$)o&I|q zIG+x|DV_e44xCH~PU-ab>caHt3&H7j_}E#%N5seAW2FPKr&X zG8|VPcB?$>QF-_U#KkLRJ}!3X))m6Dba|+C;B2O>j!*`57MVJ7`||qw~a?7yC-z-PF8{i{co~iyb%q6y0;A@WjuedmuC~ z^OoX%&C7hIbpg$boSSuIb5AVYPomGewZ9R~cWU0mU+tO~`7U-(3gT$ohk?Lxrt{8- z$ISYHz5hqWGn{w+vc|2=y59C#%{OU&So4jV&v3p&?{Lb2;Aw9=F#fvDl;Uca=yKg^6{oO_n>1Wwj*%82A1v zeAE4gjf6M&gLPp1LG@W4&HGzsKPB$Thkt`}y-nzj){}frOF1VJb>HCFkAwIS># zhLg&5a~k*FFY)WF>HJ%;gXP3Nmm2rpr})Y`9euZ)@ihAg<{W;oUq7MGcT1YTCs*=? z`(9Tv!OZ!&m9f{+JnCmW!uwv+4DZY(Z-B%&>jPLnkbajhxs~BT-h&_359E1^wx|0& zm`;$tZmJmfKE&0{d8A<7as!v|kDP6CT}^wa8KcB%%4)|9(BLtT8Exd^ZS)fy(qfB+@X8BL-!ohy;JGl?$AA$->-7$-WoB# zH!|?&XoEaWHU!;BEd^s&NUjn|J$a1kid^_0T zN7Q^NbLvI$ZJxt7zJF({$T{W#mel=hx$@0(_!i8Ua))oz*q(ovL-9s$F1Y}Vb)_wf2n;Hy;eH>hgd!cKEsQ9H!_?;dFW%k zv3$wjcpTy9_WJE-beyvOZuF~b-$D0Zz7KX^;M(tJKeCPNpSVr=a~WEAd5-cgQhQ(bFK6?f_6MmQ{6_du#{UT3(-!~4jKkQI`)X*@hknL>nRCm&?z;s0 zV&bp5?T@MvIi!0F`5aOky>}+}($%vc-c_-h(@hn1&w^3K{P9!CAGi1Q;Gcs|#>52^{M^>-=*Qf987e3Lu-N_#{BEMF_OnO( zk$pV7z3k(N-@ZThD~&tz)A;#6`3d%C##v62<^8;mVfQcl+j6eYE*Ja-U&w#Gb>776 zLmv3=%8K1E=j8+W5Po%41osny&q3VR%5r1le;ML~0jfm5+1$_ahLD`pF^NG*UKh=aM^p1PK<-+}tCv$$&toz#i z3SUHyo=>^ykC2-tmYaT+o23PMMdZ9tZUpar%gr%F&$--pY0FLizRTfz8PB*k%630B z{D9`aqU_Te{gW-Nj%)?&i9>*S%SK4=HzSDZ5qyysT z%;lbz4-!0kK6V2?3m@PCd=685+!h8Yvoi1P@Hrsoe#m-{Y_-Xv5D>@BTJs-C=z@s4|oBJ`wLm-;Nv-$FfUp8uEX$?&?A zkq28(zJm3nw6o);6G&f`5;uK{+UL)uTIc^>MD5Kvt=Ys)kM|ILNVk!DLVlmfZxA<0 z-i*V~$~xeEHRnPMsK31$2ZZ&f@nhU}LA+GjIksZ)(p=B6JxOxvXT}xZ1}9#s*ZhH< zpT=%IpXb=hBj)AHcwUz4y!=#wKl9IZj?KuCvA65=es|$hSH;VjKlskI#7TL(T@b&V zL2^8oIO#JX`RG-7F#BjT$4RC7wYI(Q!+a|e9|>PfyfOFh0eFsFnE2>VKZ3sYR4xkR zBk0X&|9szmF8qYK__;HF4tU!voq10^?;L>Jr68@aiIy7Lm~Q6WH?3zK@caMwLjH!~T}WI6xw7LB za`|VBi+)3LO6$9fC;2Cm4hTQy5*PiB;MwzkH}IQ9T=ad$XOH5uTk%o*HHWz9M-D!t z4nF&ei|z+LxpBc`Sk@2h@#P3!vAF1$v@b&IMv8xqQ?qVAQ(W{l^q2R$`c#h0I<>L0 zrTJYpo}zC?8J=A(`lc{Gl6B3(_(=5T{>MlC;6su4C{E)~<@%Xk#p0ux$MO8dN5agVTPQ)=OLU%zQ=rIF;W;z$&PojmISp z96U$;O@Nc34E?Y!)b}^aua`WY|Ke<#7ukLux7iOvIjODZ$i8qz|8#h*RIj6!Q{WxG z=kwe8ye|Jde9z~%^m%>$`Do~#&#&wAhWzt~L-%}sRh}c5reAQ+=i`#k-}8ASjgaij zdCfc?``#LybRxe{$~SQ{UI)O)Z2I85OL|p1*GsSI;S}_^l=KJeZ1_G;v#%!SX@Yx% zX11 zJP6Nv@J;n1Nqw1C+F?r^&Z%{DryS-h9BMQ$@S>|KF*I_%ZUfO3_9oOo73|0!h2Jr z?(zHp=&?oGfxc1q7xp;yqVDm0k3-*H(08lA$M~OIOLWWj@px$egHx1a9v8dEvj=od z1?_L7JnWIH2i`;Fpxfb8)tuAba2BEtdPi90=fj+{=rt$>#r&IM_dSliR_X)aD=|*R z3v`RR&okxJi@NXXGKX$C$6tAf={6#ILeG`Qz0(sTVbl zwaz&Byx#hNZlB|E6hE&A{^9(ypXuarn*BV``?cV&u#?|#;7{HtF+N^wiqVxjY98a(~%_=ij(`60FPJh(TV zFT-ea+>LwYjDG{Y`{b)>9N9fAw{-5GQC(mX8gU#(%pOR+0a z_jYc;_){`|_ytk+^vy1v9DDKaLMM@1y~owi33dSzS#WRXkkXx=mueSY=kPU(|BX() zD7&!M8P|lv|IhKbCYApak^Dc`;WzF#wBu^S?{4sWXfMM_WgZiLFA+LiO!S9fT}-nF z2DIQl=l^!QaEIR8IXw*wZFy#Xtw$-9zeiH=`wJ5^F9u~_5q81)b+;T&jHX}k9+0eu z+Hm`6{D8BE>^0;DB#C<;mpFJx_IK?1BTgJ^?(OWRc7SvIdr6;mY5d$KakGJI!&aA)Ba8!;B~Y$}J7_Ze+Ygn$uNHO-2+_@YGD4tKLq9c?4-!)Dk(Q| znqH-Hpzj3(zdEXK3L4%HBkoWl)q8r%uiJ#OZ8=+*-wG1$jkn+pP~VBUgou*l6J+;<3Qi|S-}f*`3=2i z1OIdy@^Jbf z#;F%2SM82mb;F)ma`p4G!1o@tOWmBty)Wd)h4o86C*zNMpW||~-W9yJcrM5ktj7#- zw&;3S)cdh-0-kD@W?Juhqf;;HJ**3yaaTKW+BlE9mgU{gRC5ZtVm{e%+QsLG?G?ZO znAP#k3*xjJ8{vN)!EjPTm7LPLmFoX$nGgB<>DDoTy#AR3y-suJ5aqwrIrXCG^%93( zBaZ*FgXuM@ax%hcK(AUJAM&dmdf{AuG5@8V>2(LgNe$&x?uJz_$$Dz=p5OIM$5QAO z^?v3ehYnHe02NNXD0;;mdX+o!bv4s#G0Oqz!$|phfkQ73aEi#+E16ykRK7fwuZx*3 z9hrMMpNzeN?Vz9e0q28w`QJ4!@v@(JQ1h~1>u2uMyxCV4J-a{mg|8vKn(&TiImi3` ztLQK2N&Mp8@v28;UIcu8EAxMU`24-^h4o0(y!dygUKF2qqh3bvhTZCO=EdpE=YE|R zeUbCx+vE_~aC#%=1zurKWp2}X(W~>~9Gw^K`FZwg`i^yizb+JpEB4LH*GvB#`b_<3 z(pT26yQKzPA^l#${r4LwzA^r8-20>A)2ez+pa%OY>$IE{0{wz}yG^;+?_giWlvi{8 zMC_C70TSK}hxSrAIC2}hCx6?xjHgTX4ekE0e`(HLkv(Pj!9Dp6n%^z- z$;f(P$@kmyB2CpT-UD`WpbdbywJYTt)(=HY3s=fvR+%a^^h zNcq&OT9!$DgD>=EH}y+;pX=LnypQIcKcIT#fBL@n!BMt@w*7@Z#ke~oq$g$B&CSJGUpg-ud zy$+l=h2V%B2XHhl+fI$?2Yg^U_`WI!&V?a38Yiiqr1{SAl8p}p0C37r4Ug;G5S-l- zZ{^{P7r=p@XFct}X$Zj?b>NH?z(L##IQ0&k(?f7_4xIi1I2aA!G&yii1e}9}Uw#>+ zg7m#bSC}NUYjxTk$NfwFz~1Z?yHYhFY1bY}+jetG?_)Dw!M$ICH~E45Jnk)E`7A~5 z>K*%+*vB}GoHaS^UQ~1(Y9BS8Pj{((Y!iDL_xQ6KUMYCCI{kUv-|Xi{w*%*|6EpM8 z%!fXw-4xmt_z6A2r>b5_yTrdvw+S8M-Y-NhhB@JNlqh{L;`H}R?r-+v-R;2nQ3y`y z`e4F=vu7W4BT;90pLW`PvnbvAly3b>H>F>j&@=9Rsbsn>J~^y!?g@>zLHx_SzEMBG znx{s-YaKYB3&AO!ZVe8c;SikC^=PvLryp=;&^JbJwma=U#{IkcCa3ftQTi(%+JrB0 zZ)?f)?{WHjUue9g)4$(=vo!>#bo!4vaQqOQ(&@j)fzuv>Q@S0Sbl_|RoEi9N?3U-) z<8|D>%g0gW960BO;FQkCMh8wq2u|sIT<5?! zJp`w8K6W~AP7J{*-5=?7;H(6k8RWtEA33Mpk=(y454%+!_NY9lT(pUt(0vK&M~Ixz zcO*40@tVOAmVEx+(9dwc zh?i!2Z)h8BA)wvN_l5@RUzbyT#IY|V3=r48h|;+CNsiyldY7NoaUR_$c>Yg+SF5d0 z__xpRYBe!`AfIb!oT;3CS4;P;&G-_rqgir;^`;SqzhRqxSF0;0{pt4y0q=NH^=7@v zj>E^@_kr}>?nhop^j#=%t685i>kssP{nH?9%aWChhYfEe0^a)x9_bTqNAsD-d1q=N z+(Md{^1haRk3XLe$l@vO)6LU+N47}byhky1x#Tgvx4$;Lu7~%->~pvm(Y&Jl2JSyu zwk(GIG_y_-j7#u3YQ4bqcQ!B`{egN;ai2z?6R$l(>%{(Wv&^gQ)!Z=p`(Sc@Af5j{ zn4T-RROk7w5tifhr83Xc2jKf)c<(1&A>*?7)JOEex}tsV4(n(*PX~Jbh^CG|*vItp zhvdC5yL}I}x7QW_g!%)$Qa{_nsa?O5>I3e#sh(XP`Yu>kJ==wJTOFr%J-HvGn#=u6 zH^Zm<$~51p`3B8Tvz;mVdtjtb2(^;e6@%}A3Eyoz<$GXaXA<7`SsvW=AhX}Ok!DXd z)woX6WNfnF{sURpU!2zqcM<)f^}+=A7w83{$A)cZFkLnn`c@UvcN*uhtoa6dgI|eP zVxD+PU$bvC&G?venq!09EuRZ<=PlNQ?RyUTu`ZjE`hfq3pHV)e?THRk&bhFk()>yd zO>uw8viq4n=Dc*U4}B~Hu;B>ZCRq;9Pw$L$llMeOfAap+hAtVW8J|Dg$@EL_D12X2 z`svQ|=NildU6)N9w43qrhorr)-$%6ZoN(w4`T*bGo=I@BlML6~OFgzh=w!}wKp%}b z`lyZQ)uHRpSbwGeyv<9c9r<@WK69UE;13Ye^h?Ib=+G}HZ{mD1c8->}E8kmnA5Y}p z+@r$xPf^X_{waBn_WAto*ZI)D8R2vA-LD?SvtIG6)cgeJZTf?M=6*?YZp!SR+V$l9 zSF?{Q^ZWU{FJ*6pT=aey^IKi-*ddj|7D)*G&SHivE4-)?& zANaZQ7WYiNXYhYP1pZ$lkICh`NBGOR$3pz2ej)xQ9uxXU^Jx!L%C+~KXdF;vaZmJ_ zfgcU$D~xw4_ZZVF?)`}Mpo{PFWj!o+;c|@cijX`SJ{UQ)?fDnFgMAMB-mt-c4dM?o z4@^6=?}d3?xrOSfe3|DczlqvEST2Gyrt`==haXF3lgISjbAMQi`YEb^*FjQl?g=yR z5t@C{`wl-3>?C;*xi;@{oA0b(oIu6gi)-2)rSp&MTxs_y>;8tVm*#q(@;g{xik#9u zFpt^Kf48Ms^QGB48=qFvv&HNl&YcJMDVMYS6tjC`AN#rg{kc!M-Z>v*{Grd%{7ntj zv))dYeX_vrNqjKM{oCUb{KcPxT-RIsxyHXc@b@Vjd6IRRecz{S{E1ffGj04YgTFk$ zVmhn)l#dU|iTL}$dYY`~+5LddM2~|0o0!+d``%SWBcM{|LEhpo>8Co*pXzqytDp}E|rTutFxH-pd_bYtS`09C-o5~2e zIhN(7QspMJxI7xywe;ZwO&8Lzl^4X3Hx8Jgd$ z`6D#n!D-lTPrYjSvd{25441>6zm@A7KXE2|e)qo?x94}fyEJ=#WOs3U{sC$~8+*Qy z>POpiGmpY?X<)z2{G$6jiNL`;>(qJHuBn-Kvc6u*{m6W;Wsce9;XMNAMYHY*elDO# zIF|;Guh{*_mt$UK7b`!?IZYdX!PWZ&2mT1)EN@k`@hZtK7&(&M{bf+dwhEdUNJqlp7q>> z;=fngZJ|NaZ*0A!7=O8QFY;RSm)CFgJZ}QO%ILe&{Hjvd5$y3i-}fT#0sXTwe*0eJ z8@~g;Y7f&XSr(=L3jHe4fBW{UaFx@6zZd!YjBhIU2&ZxHyPQJL?Y8)8_6@r#dYGSG z746Sb6~agKIrKE~EWR$*cpKcq)jK zO1wwe=)DYg!|NTlmFWMv-<|m;$+e$Zto}-a;@PA5dd(l$`E2ZIvG@q~J%~4^pCb_? zIh@jTlJV)P*rWN~nvQe1EuZZX^Z124kK1(~f1<$u?dAUGK96BPN}b2BHy9u64MY>) z5y6lBP{JdSA7hvIb&s;~JH;Qj>2XGh@=kW*NIrU19vV!1%k$dq$BvIm^=Iw4 zs1Nin;@=8iOq?WFCh`+HuRZV!pZ*adebH;wjk%{{Y=`VbVj*AYI+%!eV z&3jmGnpAEI{eou5v!3I%=_Pm{xVXrclOQg78{-xC-pK2cv_7i&i!^_c<}c)Y*gnH< zZeVzRSU<+QDaE@zAG$&tR?Kk*ns^9^YbuS1cYHKO6e3Qt@9b?Y0OV zW{QV0=r8X-^{M@P*z9ttaYt!m-{w*SN^&L#Q0rZqobv9KWY>2Q%LE-ahBY z-l+V3t)z7S0_(r@DmiE5*Gjn$r0D0rx>3?ClBQS5`J_cPTo_&%m%0|za^B|OG}e{Z$oa*wlld{<2ZFz#N3#!+{9Uzp3i(uan(i994aizYb7I|7IjbeCAQyXYOBye!$3p$5m;nH>mY!KWQBG zQj*X61yq09i5Hhz_c~)<-t;qdf~hIsms5&sO%|UGGfp73Z`OEhby|&3d zd4f+X;ar!uU^KP>c#dzUZ?a53u=Z%am*G%6$a#Nox0JUvacb_{F#Y?t2wZ=s@^h`^)7!)^qI1Ly zFIdl8CvcRG={3EQCpv?!bgwh#+ba4r?Ri$#{W>*m<#mAcd87QC&M_;#Bb-m~$Z5IA zXR&<|(MuBr@fqlB&Xd^m@8|MDy|<3b3-zABDb#xcC(wH&LL5g*I?4DTj+FdvO~(uH zoWeR~R_JW62b~SQmz!dGB+HlZd^7iy(mkU}CxMr4iyDvMo$fMtjxZh}dcZHR`p0-N zFMzkdQ|57@e#1m1eK7bG<6*;Vr1p^0Pdak%Y59XFe-AhJlJj3AdPL8i_)9U{Y2LZ` z=+uNBueA0JfhT_M`^E{rfk@^zp%T0YO7(#`o#SG>H>5C1x~FwDC!V>db*xYFfG_n$ z?)_y={9xt6zY-t&369J=f2YhV=$FuYyL#Rm<<_rZ`7xq{!sT?%;utxPfOC!A)F95$ zyXWD4AK-y<{BhDUO6eE(syTJxEI$VL5v>aPo#1i<-@wW1nR6H%>)SiXpUvw(g~NP> z9#(#sbNlAJyQy!VBUtn&BXPyJjy9v&N3o$C_PtkwoIq)X2WL(WTf@Z3Zb0a7> z=Ln46GWYB)QvH>e3j&WG?!nH&@t|PjOl}N z==HewQO>6ZALj9;24q}u@3x}l`|3CDeSq81d}4Z=e(&7AP0MBe1$Jk#+JzCWAC!Aq zE^v<0xUj9FlI=`eMLFA@^%Y`Qx+*eUe^W)jes5doZS!R(_%fjMB7MO6k>nF}Fzaeq zk8syLR}mkG|BRnm{|@ZiI_}r*r;g;B{6QYCU5@^W*|BOaFVy=UmlxWxb}lcpW9zuw z*oV2VhfYS=vA2@GPYp~m9g-x+RYW&?eEl-phqA7t=%frO(^VdGebjT{SMx^*oZlN&IDVe;(u$dMkhbgX(kihxvIz z4gL-0o6(<1c@5h$_YK>0!~J?@o?txvH^xHiyQh-=ru{F*D+#9y@Kp~(53>GKJdz7f z;^+P~;=lV>i{DP?dAYscFXQvo4)`m?PLuwV=SOpM&p%qq7ik=UaZlX3z`Jva^l!$I zUNtTB%1ArZn`Zgf_~BCN-yZJ-Js(s0o9{H3^&Wp%_%U{?z)PPe_(C7z$aN|=A#^BT zR3Lw$e!B|$C3ipnT?jK?(~rM1=m+<}q;h+;p9S0x_$~58jK=fKulaeLxsLo}oZoP` z`XM)RwZIQC@>C<`{$inTf^VBA{x&PWZkFeXg@^JV{>3^D4R!A9Rr;%gbCiS`URwPe zb06e!gfGT%I;EFW>Ypue{d1+?McPmLHpw5=B+rk!LF-+u>1(zAHIh$XBzgZ7eSWGw zmtlM9wUY0OnY4i`cEvP~jn!$smQ!0Uz&|q&!0(5@N%|)94AYh3RiW>(+{`m{&ii=+ zj?NXzc}xE$0zf~1lhpTXqyp}T2z`HNwMLEM0vHeGQ33-suCHH~MuUhLvv zgQQyo9<3X5`;J2-zgf>Q+Hh(K4*W6q9MhEq7kc@7|Di%gAn3l40=u@3=k*Aer}cg3 z^p1YcqrH8f5`7O!@XORm{VMS*XrD^+VxPMz_C5=bsHv{Dh5%P5M1p;?Tggl-6I(^>2{T0a5$>;KO`hKYLn+QR_ zMC@bIPUXFr9ASM3^r|I(`-9VL5B*_J`DEmW!Fa{w2Yx{@`8jef@}uhk>9##pDN?bMEp}4RU&g^3x#nEs&oxwcM4THCpb<&*@SgDL=RB^CNc=(mFw3DoD1JJ< zM;MaJVsey=kfR?E+_~x@+F#;+&AJlc-1kdcpBa55aYi6d5^v2UPw-3UEKgfRPZ<5| zt9}mjk}vcxkgIF8+?A`%TJFkKyOc-D)kFF`O0K@4&!gn(Yx+D&uEzLzAXmTUd;#5V zVXx#4<#(DZ)0aqlwF7{%T&|$+4eV?#R^f>Wb^?oPUxBG*g zu-ALnQ-5Z?1NT`2!SoK1o0hBiwF9qXYj;sN(3@|j_6hGLtZ?ZZBlkNt#MSwJUba&m zl82s*y6<`;UF>Y)eblS?eITdse_lZ#(BFEeUevwBEvT1KJZMmRaQ~Uw0l<0qWi(&2 zdu5(x_Hc@F*iFO{xTzuT9ULB4PT`UH`q`2FBTu_P}J?_vCONPMb zNQ}dhH}5~g<2_RAEpzHc(fKf^-jNQx4=KDwPQ5626;8b`Is64hFpjuW?@p&*?Bk*y zE=0HaRtdgYa{f-{Teb47GR(K_)SiAe-{Qm{vwj%&zQyyo6n=OS^7q6y!u+`3;T!JN zz&IXv>V3zlM^lRH{Sx&uz*_L`b>{U2Jl;N?*S(>6?W>&G<9)nA#*6j9xF>qFl<`K* z_isDnh?2i=I`yLDP6A(lTN*9hfY{R0lben^`hY2=G2RtuOD*iMa|c3 zsAtiAFV+>U`TDohV3%b7#_UJNy_@%&&S?j~D7n1WsTW0;4yRs}UVNKVFACm9r(P7D z*E{tdb@*GO{B1!!i_U!Cp+)D1na(-Y6a8U5k&!sk_@%bKNHvJQsHA@4-mxX~B}!j3 zI^&6w|FurNC_289>di)9)H`sa^u;NtXVG)FBez+mr|buqeSo;IzA11diWr(P7i#ZJ8_xqX3CFG@cggnAa8`y4u7!*uSKb&5xC>vO7`o`3I+76uth_sTZZ6f8*4Pf;ZvRi=zKeoO)4u z57nEEUihK|H%c#z zpq@pq9!Fk}VtVzey!PxvUaw<6qZI!uN?&}^!8?j>A9LzO(d{;;UX;H0kW()T-ZrOR zl)T>H)QghWZq&2rKkoR$f1tB=bdQ?K>v&jRbzLg%9X+F-Ks?OrJ(eC={X|#~<2m%u zI~=^vbm|#@|0<_m6umBY>ivrY4{z>o_&%>Fj=5F`lg8g>}$o>KEhwB*wL~UB)%g%BkJ1 znc87r0_y@eN6_G$L!AEr;XmB0bXmtK?t#KempQM3b1aC@lCianK>i$`S)Vw=_zs^6wui`7>9v zad}=}P7M8e$=z**68S)I;LBb&Z|aF0iXTE?JDPH9_ak=ZzCk= zmp)I{o6~D#{W-l#*PE+ytRL)tA?JYml~>Zdapt2PH{DIo^XD^EztR2#!!vp>?#Xw! z{P)x`9?%;E+Dor#X1*u%ya>us!<@4$qs1ZQ(`%Zz-l7%U+{^FB>vz%U9vgmc zjov@c%h%6|zNx_m(MJdM@Hq#6yXt}WwsQx-1M-ITUZm;sL=WG27;;jMl=LIRJ;9Vy zJN%A1S<;Is4+ET-*Te~Mdx$Cu&tt%?LCHL_npCi z&;k9Kb4SI_i(O9ZlsD||& ze{bH8c`@T>{F=NUruJ-QY$-kOr*Vs(_6O8nuMxX}a}J^N`X_JZeo$`x8vLD7fBC8K z4hiqj^Ql*v=Pjp7d)W1Esuwrs^loaP9MQk0o>QAoUc`J`%KR!`1c{ zFMOQzs5`%0KLYfUbBUXHerzOsA^E@?f1FgqXcFCI{+zkw%CNlW6SV!gIS^6<~2 z{P+(+KCOCDe*8A4UX;IhgH!K8Xa2l~P=b7SJN2Uc#WdB+%TEzMet`og%8%cKdRe6p z(F69)_UmRN_en2PT)vkyaR)2s-9!E%$#-j@!2VJ>d{c^4!mRowy`g9T?`i0Bs zJ(Sa>KK!R{dY*p|h4LgGeBO}dME#{GdjtCa^lM?gH07+n;GIK1J1u%zztf)AOQbJe z!u@}O{a_bQGw+t4x}C=#e(qWG_9NWh%u6HR=;!s^c`wGi zClMYey+?n#>_dmk!CzS~G<-bC@T&$r3jQY%{>Bd3C*Cl}nx{$7XDCpqt(F?2}hSp}ZXHyh4I3ywMe zM&D_lLdOQbbXDPb^6|gWd>CN#_#VmK$nTOo==KG|F*P*K{U*xJVLhEJYxG`BRcyO~ z_ZjT$to_ObAQ|)(Np^s|Bv{kdC^;Ro{sZ?*KXN0bI#5l{}kb4&KskC z({ggw^p~!hW;k~Jajrkbr}q2BeC|Ih05N}<-YLn0PuKH%`4fVF zc9K(+Q#bkdl99*y54{J(&keq`|EKxgLjR16yVy9^4Wgk3gO+ zx{WIS<*=^)3^Q(ECEHVEunQ!x#GCh;?Yk0nO zXxx~bf1C16LKOPbU80d7bx^X)#Y?NlyHZub#wC-CE58RHw^lMdlS-#c}ln|^1D zujyCtjeFCqUxR)>7V6h8c|1GjNQaMy=umopw`)6*o4EIL9*3=;FjwN`?bqnF@6Hlmx8KWW z+1{nshFP{3dIjT__2$y)X7u3axZklxfj1`0B%c2UiTh5QKTq~~XcEbMhZl!9a`7}$ z|H8s}5byn)eFm)Obz5-{{M%P?{7}#RCSq6diiAJZ$a#OTLDEberzU>2$>IA0fS?oS%0Lf0x%O zH}80qQ^aK>)_BrYf~SpN55))Odr_!geTTrtzvg{DyZ)mz9(rGw=XqB}6OX&AqMrSb zu8KxZ?fQEVCuapF{6Wwg<9mSaC7`&B;n2RBtg~h%E=;eQlze8dKA+&cp^FWFuhMrM z@r%+W5!=Ily+15;NyOeFaY=06JkT={TN#6XO2iJ8cp~y${Rv(`_UAT;-*$oAdNN zT}fAoo~7?)O8&fNNiP-oO_SWBzw{27&*?6qTY8(&jqc0l=l+n$r%ks8=X(l9zVCmu z@cVPA!L$F4ep15?oW{NHGktA2g1=+KUx)pPU1&w+%D-ZAL{}`399_=yBsDDOl;WO@ z--Z_@KP`M;ii{WQ4c4!_rG}ShNG_BvI$v$Ln1}Q}8aGRpe`bEEa{DgGZBFQ(EFUHf z4*3&2%zBO8kCD^UXud-~ivRW|<`33wK|icxBHcybNrL}n)=O8KJRZ`|>}%ru762q- zGV)~X`gy2=@Asgdy}r)$>p&^VGWGL{-;j{&5Bs{vVIHOKC%$Pt^bb5xezaAN_Tx@_ zSS-}L#HweXH~Q6h02l2qaoU6KXnz6PXDCBI*xhc((I&~``8ZuU;%9qQ&vtVf_b$b- zdHoxI*mOj^VbhWGT)P+@4=2oU9&Yn~)3M&71Nuk5!2fR!9ir%1XSKKKc(>C&ijK7o z9Y-BHew67ru5=t#I<98Q*!15`?fk6RBX|CeT?1;#xNiPW%;Sd{PHK3!!h4SGV6uGe zeCR{JkE?qfTZ93L*k@qQ^7;XKn)Px<>Vf~wz+3e;==Tot#m7D(&r^E7F}ZMhKH`A9 zeqOKb2_E-*yyWwGn+j{G$ls2CWgjbiPsbGFEv(=7a$z_a)PJ(BL)EBILR^4sLo(m4UvJBfLpgW4c{ zsCKDpg6sPOqKBjO62{X+B(?EnKg{aqXj%_Wshv;8J{^Z7r3S@*riLG3d87Co)6Gkk zKQ#}U-B)?(NTD|LWt!=4>=NXTM8Y%osG9v|$RFrO`x?_|=WmIUmqCJn=TY*K)#p+2 z@=1N(05H6-8kUzG{5;*Ja_~{E#`1z5ZF<$huEQBec@cSeH}TiZr_``~Pb#^vlKGtX zi!6TQdsOK*krU&;rPqku+H&(@mK*slRdV6~VR-2-<-6(+(76$KS@7{)r}Qe3Cv)Bp za`5I;AlLd`r-kP+yu2P-!NX%euE~M781UBYDUjKnC%N!!k?XArhwuXbZM;0j zYd6CIJ|80aMx1f;Zv(q&;tBem0Q*JeJ_tV}-{DDD^|3s5RrK;bGn*<}pTz{R`#~Ht zwo~ySuL}N%@td&zKrQ$jAOryWwC;P~G##IV|A1eTcO6I$GgGV&(pBg3e5CuhG=G-n zB`!%<$^B%$-p`t@TFuWp^!(`NstY)8{FBW^;;^VV=?3z1h%Pd3mQ^!;W0u^4-u`y{ zOKDd8_LiER>{t5RiQrr=^SY%bqve%aF8*vw%_p_ITFYfWvZdzZT3*ZL$r!66>aR}o z{Fw4GACoaq7x*-AnutBhh{3-HguFjB$dCCu+3ZiHBoBY);$H-E0XaUJ9zkwShrPDy z-Skkn-eFqrWT&3*z)NVo6HqTB{X#$CJ4$9=qQBcu1U>cpNtwM*qbABBC&sTs{uGjD z6L%tyqaHTgJ2Oz&tr_P9QmdBghXw1a*JsPF&Hvc8tpztZOo+!3CK?by%xdESoQ%GFqpSJR(1 zeRg9VLhXKfjo4q?-r$^Q;0NxW2BhS|v)B)u$^RKAxaltSyYlc0{h)i;UW_Z;YYX7k zIrxqO-}S(P{Dn1Q_iTJWax(1MsKVPM@UD{j&@+|vC+>+Mkqpscgy8x^4!&*bk8hCn zc0XSS-h*G@eo~ncPHCNr?U+s9oK4>yVlRzfV8io~a_cTt_OPKc&GSV-e-%ZaGp3ia(JA0h{{s>9)OR1ebA4Jb= z=K6s9VtO9;IymoV)$d#-c7nb~!FG(+=hz<8d1lQ|X}($W)0)@yf>mOFOgx_~AL13z zj*QgXtmjV1zH&SB{av!Znjc}f=DZA@Z`Hhk+sS#OKcUa-X&mOeTy{C+&3rG|E{A|&g#4}{w(0X0_SLk1<%C7H1$k+a7g&> z=LFx5?T4V4{QZCB=LK-L^5eXp47fEM7c1O(%h*`c_s~Q>^qxZc&Y=B3VDg~r zlJveT)7z~38~P^ZUB&&SSBd_Qd(wZN&U5gCegpb-2)*E!!7~PZ2CZ`NslnmXGOhPh ztDa5wjZ_Xj%Gq8ULd4|16uaR{Ny3d-+)0d7)S~0>Y=n8%4_eT{8!bk&IF_v-T;=hG$bmyy4w?S$UspJ`s~UAjx`zb)_0h}W`A{*a&Z zrbpoCT*mPltw(c8-`8Ndgg(Fz=V~vfH0~|u^8L|YCs_Ii{6-hx=YQQt_*r^4N`J4k z+S~f;->Cg;^w$xN{%UmM+4qsdPJTAigX|@zM(*O?Gn_Al4o5rdAn^ME=U{6b(ASSU z_UaI=SLW0^!+}Rro8irK##85vr-R2+uj8o;jmLZs$@nY4uk3Uhe@5h)&IzKM(Ec#= zPk#KvcuH-EnXCu5OCIBj8vhgEw^c7{{Es{JqQ?JA)XPY}(06;_*IRz!1w8(}?8nnS zJEw-9#m4{m%V@kRk8$r;3^)Y;S&0++#{#*FdtVm%4$3_Ahh!cyT?m5Rp6O)a_Z8|d z*nh~9#wR_f`|{~F;X^(?F#8bJcmWUN$&lSGus6D|n}|Kh<1q2GSw|>le;TN!vA6kk z^{csgaNa=o&;I%CkJy1|`y=)uus>>d&QrT{so0rxMUM5XksH5X^8PM)?(bAPG@y1U zD{x)=L+jP5ub&?~w0YaOV{eT85jhI%kI=<@FZ%hkKiv`b=Y8Kt+%m=VaKF!!8hkI$ zr_^var*Us7>!G~fnIV2CbM)kkNp!)t7U&6`*U(RW*1gyEIf7=V-o%8&xR?Q`M@<>t z8yvmUyx&+3(g7h`~4fxt|?`hsgAU{guoN3ONBBxRIvD_I~lzp7<)Qhr@&)yrhkB$GJ zyv7?C&)a$YO&YH?a+;S@8Yhom?KR5h!#-}I!P5`<80E44W0OZzRL)8SMv?)^aN z^cb%%riLYMhCrA&-pRQr@O>%rMF3Z=MSk}=~^doOq=*U{@@;2M{esBd!*+a(t1wNAJq7&P2;UW zU59S#6*xOIE;9GlXQtI|_Q~^A&62KZlJvYrNiQ{Vkgt z*MDF9C&Wc^?@(&EQ|I-&m>*-;O8vN(7XE;!^fT*Uai(?=KP)TwyLK+_ox$x>gD+LN zX=k`}9!d4-J2+qZ`l{GdZLf0DrE)T)a?+)8 z;(p&CBjcy@3nC8(Ku-E2!hb2w*VN!nmYdXYKc|~PMEa4PSN@uNUryHiG0Ois z%|D?0KT-4Mev+4J{s^tVO7r(>efdszYVa_9ek?yvE{O5_%K7s(uNHj9j+Zn^rv|I& z&oL~P(l5E-sHc%n#*XCFo;Qd$=>2J)kI?_8^1iyW&Xtcl4(I;;{JvHL>xB(%XGprE zUi3s&9jA6beeV8@#$C6pqWLz^&*P=l?zwYHr-^uZr4R6wsj|svPequc}1pKDtSA8;;Ob z^eNgcoRO|?Vmt!6_9V=ocFg@N_ovOS`Kbg{jJrU zw$#*cIr^plXgx*rgnx+XkE;>fBcy%)x#?HxwJebvF8mHHSAF9jZTde<`10JOQ^8O|A8IoTc&Sb>-qg);N1;djJC%LdShH=^La@3CQ z<<0BWK7xyRc5Bgddm{`dUDeO?+t1`QFM0sy_6{ZZ|C`S3eef$pzx=s9nYRV!hzic_ z@v=7gxx`5N(f5Cto-H+hlf1bXQ{R(nsrieRS4*n*h_uxFNz0|**`M2c9nUzd7Xm_l zo(wYBS)JQ!fLy1f9p*{1b8hd2^ayhM3a4JwxxJS;^Q0T{ytXrxGu@mP zn5P~+Nz9wU>lrTjm+QAI zqW%NB!(gp*-!czNIrsgtlf(0v{fkWjeXb?BEZx7r$%in!efby1yfxatp!IInC+7bD zWNd;F3(CtmpN##~DVO<>jQ!Xt7dw-TJ*wprX9fF=y8d|xKla9!N^0IKGy8JJJ_YwP z^J^=fZ|-LvP`po(`P8z4*-HG<@}o&8=$HQvrMS`7bG65ZRCB$SB|2|4KJfLvyhN;l zEt}CB7zaj3=ca^ix;}|G3Y4 zrZ1gO6Mh)~DSz&omt$$(n&%?7fgXQ`=Tq?9_(?L}mYQkjc{LN3{3NvlPdU#;9+Ub$ zaR683F|YUY_=p@P`R!Md*L-;c_mhadm;EJwNbtuzK@WNTpW|wLe>n7)S$Bh8k2<&A zeRsItwT}LWoIzgGPQ57oe=X`|6c3_?dms022w|cZ8&cYj=G5qaKO_7@{(71pW?c^X zF61q^d!M0xvf2-guTJBV2XT%f^BBXWbwf^#pO&2WOZKDS*TW8A9|ykO%10!|V7 zT?P6L_cEO1!WT=NZ_!=s;zVALy_Dbvc99rGzue88k1Osi)ckFlFVlQ@T_Wzi6U~D86@fqa9CZ); zVc=f}gW>m4qwaxU(& zQ90sd{7igK_v~<<){$8*v0hzGCHZ-rnNoqADx z`@U0es{?PT!uz&UFN$y9M7@lTi|AAdzHOB}=v2>qt5&{MhWVCq_@(Q$d48oFex(HN zO#J#f5yZ$j`hNg?B0YOJHMQ}?dtZ2-qd39DukJdxS^uQ>dzhbeKaq|j>_7TupCE7V z1i#dN#6L68;Dr+YgsYQslUEX(){;5?$h#mNe`*!v}MWNoZ90P{Wz7^ zk3B?(KtCQ!l4R>gv3L2nA;R8(UjIfY+5ND7yoI}GIs60dI~BwY>i1wCS-)=Mhb~_t z=WcDd`-&fKzp5~Pp!EbEuem3rBU8!#P$G7+jyK?210h1^2)Mql>&N+hqwF;EnZBDM z?ecN9C;ruvQw==M`?rW3x74iG^2J(S&BJY}IZ?}}7%r{zOTSsMOVM&Ce2IL%rHSDu zVml(@0a=%|>Du&kAn)MkdXfw9rMUm!%yud8|C==bzt{h7Ci(XDoSBJF3;q9ImBW7F zbAkWguJT}>6C>ys`2TNno{M~u9uoPhX?31gYkTAWU+z2?y%PBUreB)O^b7odQ!e@? z@c&JD1J_T)D%kS*LsDMg|3~PLnf!kbcEs{mqx}EBkA~|-`Tu`Gy$qwv?_JcA+}r-@ z700nYWO*ikf>X=~tdr7r%9(G-KLdYI{U+p}M&5#34Y*nDhp2A+|JTra45`d93^z4g z&8g`>Iq$-GRn#Qf|8HXc8UF$E^9@#fj(FjCYM;mVd9b5DrE#L)>z#h_zJcl2rpu#L z-`H7S^;+Dkm$=8GSGTi|WBjZ)kpD;Lr=~$kIzPoJ-P?yO-!sA~Q-$y%ZP#brR|S0T zeIxv8*Kd9Sx3~G#8PWe*?*Dr2zmrq*eoCbN&4?Z}-~F-sG5*Ev1ef9vp0}o6+}p+r zJ9)ow27f+kUttI2Tjdh-Dr&xb*r^v4-}R!N#iwb+wVRlH!tY}-Up)1HTgVpT_j(#De%Go0o{Ww1d)Bm{qWZjv zpBHN;oJ|!QJU}6yvQ+qPlYdf z>Z+)H7LG?q{}G*`2M8tBAEkXa)x)@F_RV=NRmE zg5Pu=zr&fYb$s3k{RbiB4^8s8{M=N*`1VqJTW*)~_$H)&c5gxb-BcfR zdy?SVc!(TM3H`SzAG-E%-mV9_2kX>(7(Tr(Bz(>6*1Y&j9T}Mybe{%4C%vok+biR*e$(BnqWVjedVJ%RVZtrS1BRZfA<>8{0`+W6soLb^)s`!nmsbS|Kv-Z;_0+&^OO zTk!`(PJDeo2>reN39^sF<2)|9KZe&2OeU#pf*Phx}pDw<{Se z-QOwY`R^Q^s`$iB+8}tu6|cDB6|XJ8YlQH!@p<|#;4`B5{F&{CUx3f#^M+5(!Do{3 z$uT~Og^Q-)FQx|X;C$TM`ezI%{~er73zn3JH7iHeC}p^`V^m!GCsyXk9(u+_qg^X?qx;aY;R(ECt{Cr`@CN_ zLmc!$=e!6V+hD!&7Q(~WJ?P`8^CFiz^+p|d@O&}PlBkzq^w=JZBVM^h@_7CL%`IC0 z;`oHVOTsD2$&Baq9`bLh3+w4oz_Iis^fv0X(R)j&!Fw4F&2LWQ-tjzd=zO8d?+2Nl zh%at*;)}BsZ}cDdTLJ!%VDxh?;RF8QcUPI72O_%(dq?+?ak>4SjA_#2IH!R2==U2= zzeiBH8MpsD#8ambzWa=))NTWh6YTNPxG+>RPMe=5&R9h8bE53Ir!a6oJHqsi())4m zUqo*8eJ^u=L$J@+2r#rhCh@)TtBqflh|wWG`WgPLjD3sX_4D{b-)URgMG`FIMykJt z<&|gipP)zZqwiT&N__(t{!2Gih-x{zeMt@^u|1kI&boOr(V=N zn?${gj0SkOI`iyeo@ebk&srnr*?-Z#mknoK#5{W;&$G*Qo~_e)_IaLPslnTIp4Di) zCUMKk*oPzdbQ0Wn=AVp!|0O^IzlK*e5WJ z$v(|K?rtD@+x~`$yN8YeUmJx_xrPEh34Y?Y1Ha>#uO{xkN$|1a?q=XuLfk!ZDj8+{ z0dCEg=N5O@(YR)cyI%x+hw5~E^#$XrruMen*7EpjrGB=$p#Ea24}9lSy$~NcUY%{+ zUCHo+xO=hYpTD?!`IWPYyG1UG#ogsZhr+m9<2#LmL8o`)p5@_k9#?YV`J#tRe4dY+ zb${dl#?2n{Rq(gt)Rkl>Qp29&^Gd-dBm0T;{fa4wWU$^~)*mE}E=GsxX`2octXKU3 z@fZA^InIL)KlmN`ot_5##KJTGQblQM@EOj>y^%km{LUJ3#OY`5mCUba)N(P+dx4u? zrTuIbKl98b%eeylOq}zj_tC^}QTysg#JBz~xy!+y7U&mdhZ<2UO#{?XFjeE&MX&SAcj-O<1m zXx*9VW6$4K;F*>7_B#7~=*LVu<3s!6;`e7-HLvSxgW8Vh4}EFF;q|WpeNJ8?^sYIl z4Y~L!zN4Gb=cG;70gv^P$Mc6qAvf!k9vdXi?=a(*`Ia`{@wMQH-j?-Hz-h;RnzO$X z+!OXKjt4dp{?*j=>pvp>`+5(YjbAh2XXMb_TM77ge-U^#E1n-@JneRZkH|0Tzm50z z!uw6Z`HHVH0{(#7xiz8>H&i+6%c~04H5(m18awx`6~xDE6XQqsyKw5>50CZW-Hu)Q zKSck1?PEo~&+G4+7JYDm;g|5kCz-;}Un}K#IXzACb6F>BpmE!Ju7~;2p#1oh$jwg0 zC%-x1Na_XBU`^*s76 z2g8qh?JUo!!KXAIlX+VZudCfTMChKb>SlTr#_O`-g$8cOu z-zToTj_DgNM;s{i4cs7Jznbd@>j_PqPsC2)w3N6jYJKeQUm*QbLfrKir(RUt{zufa z^v-T)-*X+$yFJVgKeL-t%zs&*8ew`O|5w`2wBd{cP7!^44lVShG7kuUhsQaMd)G@G zHh7ux`xQz*!>?G$>UDFD1P1J@N2~3*DB`MsPbzhl3({b{K`e}>oDfm9m=nq^6MPsm!tn3 zePH~7xOcPIYgtb5qV#Rt`y;Poqy`UW|1R#`@FW;R-vd&)V0Ke}fj-}&&(GlJh3hQ8 zV|a$&(d#HrljVk=Ao3Pn@8?DI1AW)LQpOjSH|UMmDj&pd8vSt6QuIdiMdvZ(nuQK&<{slj@n?}2G$(!dW-$?Cd^Ih|^s6P0Gd3^=1HWA#73U^Ra zoX6=T|HsdW-o0<>S^U79e=y%4Fz3TCUZ582Q%bv|bo^}<{k#v^M(;i1!u53517bfa zpr2_iz2bh&k3Wkc2Y!7!mz(#0=>B5P+xn-U#zFor?=Rcs@MCCSvY~2Qg7M)!WAOE^ zIG$Sj2KwHJ;kV(dStm_by-oS~R!-Y0uF`z#vw#=ycU<^6#Nhef{c`Y4@27C_%->&~ z(fTyrKBkMDgSYDoUBoXP%V~Y;d^hTE({lzE9HFnQm*D&31e*BUt!bz7cb(>&HEk-8 zuU3b@kVDMV%b35dtS6ESn+y0W@)b1>!MBjV2H&RVgue}pmrV!sZ`)_)_fDk;@wb}j z0e)k=;4@O-OU-Ehi`_T#uC1b-=kNN89P_QKBBSZYG~KT0&75wk=;3*9#ASWW%QF!lLP7u;`RqUUf(0(veJ~j9@#xw41RC|84=C9EFMVjBh z`LNxDJ$;0qhs$A4ThyNK+nx@SJu7BUKYsbl_Vh&&_ViuUZZ`JxVyYiyPlNf>$@8Jm zUWz?ytLWx=70jo`mIv&Uo7pmP$%>=`(L16xue%kL4W!lZn|nW^EvQ`)P80J4*am$`a_~mCJW?8 z^q}}d_V{2w%=(&LF7|Ve%H!PqqjK;=)C>C~#y`56*CooCZpnp-2)!6Jj(z(_;CEL= zY5tM@T`glj$ut$%&$#!1#!m+`-f{1%oHu@T@Sgh$W?(7tXViMZpFc-*D`CB0%BdF> zfBp{jEV)|j?9*OaL-smbspDD9Y2Y{X=GP1UNc*ogobrf$+J;)J7aT0~8ZPHF?)`=1 zKSQq|UjH+fmqM?oc>OyL9irm(Z#ng%==GpOuW9VNSo_+iGQB*d*EHi_j9w2p^qK-3 zYd+M`{6o7VnO;vZ99oCxlq5PZc)gfj7CpZIdU@25L!+1Pr*$ei|Hg9n&mXsnUMh@RWj$!$ zajW6C+TB4GH@^Rexjc&6Sv;L{2fvL z&M|JK`5#)B$bU!t`HEW&pJg5fesxa$liA0u{Y0N)e%(^i*R+4k^r3qXIkow-uekNE zL|+pZq^m@((zB2wnfFogpvJM!qulgG$jvKRZu(SiqWrZeyd{nezBk|W+%YuO4qV*& z1;#7x{j0{Q_iFxKn!jE1>4>;h-s38?r`KrQD*9w5d-^@t%`Kuo#^5~C4|ef^^)uVk z(_x2;*waC3HyeA}P4%PgshK|}ZguUanO6rsZta0Q<%Ax%haL9Lju$C3n=x*E7v@v8 zm-$EQ{G84uZhbGovFC9o@Y*VPl@hnUjq&JKJUS&EP&+e+xOJ0*PpgB^zT(zPfzMF8 z;E`+P)E-|m!7HZU(zGu`>vD>Jv$QjEtNv}Vxb-shr|*ydZ-`r)z>loT?L0X@g8BT3 z&%-}zV!HkR6SqDlaoFHRjCb7oG3Un`Wqe~NOX|Nt&Rv~0e*y0kKz`^y^XpDi%!40& zKa)Q&m0s1u`jNidBzp3~!uP~RXujL)N#o9Ye3 z^CBLn-5WV4tdqc-2)QeDA6dzIRm!f4V9JKYN^5r?J-w!I$)^ zZn5vw?{Dq#(qKVf;Bnl87;iPpQ_EG~qn%TtpM^&^;bHe9a61JqjnCfasHA?La{7UY zqMs`6NAPaB>M|McX7on;as+1`rEWilj+ig_0nXdMZt;h33-M>!1q>JWSoBhTe=9fh z?EASV@E+)PDNnCz=Wzh;<26+OTCK0o?elNX){*>qPe44qu~w~@kraLq-WT_?0lafh zC;237R{l!n7HX#3gwC|y!}F284u~F=01Yq>Aao_^Yu9#C-u^+)(M=9 zzy;lVK=)yxyZt`gGNM0yze?%btMskZe2?ZAbDqY-^tQiy!{f^FeTMMT`+L(>C&)Qiy?-cOwNmq{U#pgDUiwQ{B{;vS;;?^!&g(1W9IZ|7 zPLgB${6u?Am>-y@hTg#E)cYWxA`ixX*!Lz-H{C6(9|e0ud>y5J(Ei~Q!{z87<%>w~ z`@`~HW!$^_5Vt+!aSKYRz0P;E`_nz#PWUk>@|ZlRY(7YBkF$aLvH5xr;X(T~Odr_e zket-~k(m(p9v3}k$qDeFdxAxN-oxmypN-iG|8Dp3Vg9WmzlP4eF@DL|2V$t_=LAnW zKgQ*>&cg8gLDA1P-cjSe`Ci~LGar_(?gHCMeno%#1KQu3W|5Nt=`X#eiSy}I^4*+t zmC&UCkF9`4<0L&BWsm;-s~E591tNt_SAR(SftJ*#nMmfmD)e?8!Hwz<^Be;KzrO_i zukc$^8G&;Xup)gy+#08J>}KRBPe!trQs2mp#m7dP?|}CSItpp`3pq_!Rf=3tr+>80 zvC(&*dA|D@*>|S%G(yKrqv`><54R&D^xa$~@=WJnc>dA3mw!N@{yX&XbO>+pKkacs zt^$3$c&di*vY)$t0P8W;!$u!~FT^_L%U#6xj)7X4hZ(U?EvW~YKj}4M=l9nSG5x|n zSmyW#6n-%t7qI-9{wv@n(R*7mzwq?~$eEv&`7nk-({IsgNz+vmG9S%%=ewpPulG%) zcj)}tHp%7ir=VwSe~Lt=kd9e_4}T1FhupoMzq`(#Rq&GK-8t&;Y&=Wg-U#S4-)In1lG4sXAuuoKt3bmp(lvb#HRxg5B&q*(bj%iuKI<*wc?O* z>SurDvy^z~29C>A4_&p2>1h0x*~BS(Ngjjoe1peR5SLi;(Fy-qw|ZVh>2 z$0Os0DR!_6?Y7u?l!xOe@u#?cD2`J9s;$t!Y6ag^&x3ED}+IL|Hz{Y*S(my16na*TOHLuGph1q1m&-mcH_O_mDjXY3u;fl(jh zir-7)%czx8{q-+JzrxgwAKd(Cu>Do?vZvJ&4xkma8%3nOMRg;cJk}vjbOidq)I z<9rGSPMzwWux2b+n)Gkek~Q>v4E@5jwAVIn<2+p45B1#t3hn=FK85~8C#no)&*OS0 zP<}g9&q7)7c zK0fq$s@Si85%|-;*Zlh3)}P&fNnO9h_4aiAEBmj-#4oZFf}hQUkbj3B!u>VLPO72w zUne6ytY@b?V#B+wQKRbjo=gENBYM5a(>Kn zlx3sKkoK3voBP4zd_O@uIDcnHeTdG+LNZp6Bc2a`Ur5P#`R>Cayd4hHWBtT>oy-%Y zlbM@7`7NC8#`xj8GOrNxoA`#uFn;**A-2c*W8hn*hb2APFmfkr({VQSFkheducM70 zJ`>f`Q+l5?{_*(fd)aSie)C?IF5U}+GVr5PPfzPTZ~WM4v1WD7PgK$-g>r- zFHQgZ_6Z)GU!fdOPM?(dWyoD4|M2&#=9f?JAF|)8Y4|X4@eIDb?7$3?H?bXq_XW+m2x}%MA-QILJePtZ+srYaIp7YD&<{2^Yj{R{^6-r zcJ0}Z$*$$?l+Q1Ro$5FDo8MeWI1^T_A7TegAAFq3cHR1s*v`)5vBbLb3OFdf5 z!5~Zg&SIcy^W8MXll|lH2+OOsD#&>13zOrPK@ha`3 zpBE*Zz@Tkq2zoVcLoUSgT=i0pLU ze|}KzmC*hK_wI;2C7tvB=?<(f5}!&d=$~#CeskX&^-_n$MSJ9?xCnzZx#KiW3L*A`^(tNj#}f5~6vr>H-~_$q(R^oa4N8?RDc zM;ou^=kq8pem@uNfXb8gSMhlDb&!+(-6r=9=kq=;;vP1s!91;;M0!R%$gfZ0oLVtC zU&dd!|6ceuI8o>Q1}Exx6M9_3Pu`0j^ZlvddlkQB9&W0XBOR;x?el-fjK4nrchthF z=lx}sqXAog$j?^{tl3e6m-0j9CB~=Gyx@)oekB#)@yrWuhMy7F>vVqG9QuWdm)mLg zYtk0;%WLKX-@v63l+$$h%hKLp>yqfVBwR?oE8TqFjun!xvv`f&dl<1SP)NQedOp?c zBlF^c-TaYsD!doBzTG^ja4lVnCD?EF`m?E*{d+zjdYGp}*lpv-m0E)1$FF^}VzDXz z04e?JS3efnNz_(lC#Ri+Wz==LLwM)wsqssDnOot0l;famynWeNHsrC7x7SMhp!f2w zjJG#PxVL43#_zLrvGb*RoOe_H_wUty68l4>M~d<1cWmQv%OU6~$1MvC|EaG=KR>8; z!N*s5zIRXf>oEiz!%^yPnmzs~kgVRsiK}e_qs{ld!Y2(TKtqbKw!ZwHPMADfqt_ocoD{!hFgR^)K2!b$I0rT*Dw4U^ta&-L%e z(5|r8#syJ6-dhj43ts-+MtsN7!bcR}h@a{o>;Cw9`$@Te>3*Zj$;f?*7wstpk@)@5 zEa-*pKO|kN?Dn*4*}YcT5w@4*=0c8Qev^KT|0Tw`kH!8bC>QU0CH%14{M?m_FX4Xq znbml#Ww|JQV=jG5E`3)no%D(Ke|F~5iAOAtu0KD<_>y#ro{eEh<$wC*DWdL~-?CbB zalZHje)|4?_B)3VPFq%}yp${-;+B(?ZTpH zewTDSlIs_oZyy8SnEoj4Q3!@l7*;-ni>3;KX~$u$_abB@o*imO!bLhzPCL|o2GpVH zN|!KM!~VV3@N_L7&M~-??7hg~b{f1kEw?6VOE>|S(PPpKNyzNhqz((4U7Mr`WcGei zm!uCSSIK)#a)rPfOkQU3ueA58E&XPB2m5YnI_ZrTo+Ry0C+Wg0?%A;L8!SDs@aqiD z9Wt?lduJ{FF3Y#U!doo7(Zbs-e3ylHNO(=M*Wm26_)l2A9Txtmg|}JwgBIRm;rAGv z&kCG1$@e5Yn0(XTU$OU>?EN`;Q_idH=2C&j_-Z@5Jd3Zk%PX?@xPSBeqEhUmU`61g z*|`N4K4jrV7Cvm@#S$Kz*!dfd8!*0;cic~k-ez{YvM%0>{v*~8+TqxK+>}e7gbAZC zr1qS8@rSweMUt+1%JgNq^tF<%`pxtka_Kve?(@D(zb==4gz1}w4PvKXiu5P5e~|ud zNa538r5(un3)^STeu8u+e(#ydenR`r+J54z9QM`iCvN4uXW8n3+_=4&pNnVz&w9>9 zKUhdUDex+Oit<0x_iS8i@!9$?0N_D6k(WZUljtL?<0`BZ{mRlsj?$KgCG7hTeVuv0 z?%7W7Wp0+&a_MC04iVOJg=Ct}r6ZavHzEgSAbkaRys!|ygS zei^XkMF4%4@45{L;K|QRPoMW=lmMKequL%jZ`M1Lr@Vmgkm8Zfe2RpZ0d0Y6^;~EE zO7FR>mE-!K3p}SczJI3psX0mWxOKag-CISxrhfAm}2@Bf9r7JU>t<!p8i`h7twl-}8X|K%2*Ao}(H$Nl~v0pDx)`+r&(@!Q<*e}l+ho5){J=_!yb@OP7- zA?r0;@H6bx`Lnr@E3hBu0c_l%?orZwh2~E?jtiXB?q^R2PilDZsJ^!!(YMXBr}vzY zFwX(7;>U9i;Dy}xSMD^phvZ$Ew^aKRvU$q`mahFj#^)AR{{Z823onqj?`sL0R!9TG zL()9ihbsNL`9tw|`mcCz+_2GY zr_*zX;GfMe+db|+{~Y5*xRrH`+VhMF{fWJX2goaSZkL8*zvjUikXyq~`hWUCCdUkS zzPH+cSPQs}Ux)ZYqTlHYLx&Xaj!8=YY+N+K+LOpT#($Cd8?AtYdk7>w-;Ygim+5r$ zrwTWnt8#;NMTI+8o@tc^W}x);*(mx(V^v-)ql|1uYN+@ejm@CFYUMdHGY(qD{bW^{yVn^Mdbv$?F@H}jIdHVg5zIs^C`Sh3de9!8k4@&$k z9jX`oLm!gxK*tz`H)Q91I<`o-G-T&|I<`qTzi#gHELFO*P~Hwh`*)d zEQ$B;(bk(kntndlPd}r4^nC#45BoVz?w{HMc=hJ@7nncC@3?Us_DHl&;&wW_k2O0V zzd-Qxeuw=BM+P#EU-?Gq9Pit>=f%E%gYnhlc(p5%ziNI}?F-|p=Lrs|93cKPRru9@ zADaC_r5~Akf+LuE^O>~Q@jRjQYu=x%Lm@ozyym^)A8Egwx9dIaC&m88{mh4Ep&wFn zUezCcfbo!9fsgj!U*i2&vyBh;Z)Pm&*B9>DxL40**!pEysRJdBvuVL&J3J5kejicrebQm&VM(Z0?^LUIQnVk4 z^}Yl3V%{rPUz>ynt$mH^^M0K4j_-3L+-JkPkMzhCBdsTS?NOW;=e1MNq> z|0^WF0tBpI59RFru-W@AwTu13X79W16*{?I(SGyE+xPxqv*+L=MWlFElhD5pwY4Ff z+4FV;@HDdLeoo)_ZI*VKUEiU23`{h;zC-c6Wun@3x7TTxeor-BqISOb#>Z*DU2jW@ zZ#_GH^E}$|3x%HKbM!o}{ecVjz`mIYa6O_Pv_lU_cQSVWiZAPWLF6w_N4n2@)GI#? z>BLVZQ?T6V`=vu!$AhhQNF$x7;r%NDwin^qYSLyHqpo-lXZi4op3{9P4~B{>O;V$_ku?xpZ9*QF^ib3%E{L-XZ-% zW&UNGg;joH_-lnejn}KizuTqt`?`zIo3j5w*COqEXB+sw+x$B4vC5uIQ4cJxmvkk* zH|FdX>B#t5xp?vg`{Bi0j%-nU8teTL(esMl|6NY+cSyLD>HS^_`#6aEjQO0tKkbL5 zLO+VXZG5BMop@i@jz4%B^{2J^ulNnzsQu~cU5fuLH*OKW^>)2m-nge$@JzdgBwQL+ zynDOeBjHq-Z67a%smiFB?|Zr5bhFZj@J4V>nEhb=@zMc-Te(kcuZ24W-zR;%g#M{&ykzH( ziC^`2>GbEl=rP9arhRHOPV#=l?ST7rq)!*lH}&sJRDSoUUqyVX^y|D^#O^Y_dOdf! zlw*ALxN&I~U%g(uSmmqEeE{2Xe7mbI-xNRCALG*`#k;)C!V@IS`vB-c4{RTO|5BcQ z?jObR56V1jo5@3EKNAI%@`0vT@qzQaquKYfVBcf-Zl|8sPXEd8Q_=b=`$cu$#?N17 z=Yz8SsUMefQzhH~+ncSEDxAvx-*<6XgL;%s{vF*=Zc@Iqd`I2`YmUpiknEN>#+}ms z$~=|glXgtdc-!CVuW zPo6iI;#$={m%l&WTP>H~PhN)j%-`6p?dQD&O!s|Fe(x*&80W|5N25>Fe%{*}>x0l| zbA`^&MmokTCTA*dxVNQB?&9(Z@T$x!)viy({)Y1@rXxg3O_In~9XGq6!r=jDR|0X)F9F>lrYe>fy&}_twwL!5h}(7Tlp9D2z0#7 zE_9F4_!09zeEdxQJZA>rX>!tBlHyXHQTyfeXa(LftEV{T?kq`QnGo&stJi-~Pvi5`)#vaQs2&X}9R;5^NLMdt`Fdb1=QHRy z;{Bx1VaXn%j^=UQIFW}%J`o0PI+0C zi{E1L*T4>9|B=wm{ee*G6aYRi5c(8e44368f8M`+YG-x5su$|F!~c{EwBqurhc<4v z@vi&h!S>sZnCcP#<#Vd_i2QTC@qUZ>uEl+;aXrVFFX~^f%%$i3i_7G`*8iIR)%&ry ze}#xj|N7vwM)Om2!Y^)@%kPRDU!C6_x%jo9Lm~MAtBd68nEJEXz7D;2p?_av`FaW9 z7KH0h98TOG$NStmc$2R`1Yc;^;&IsY^L}jlp?LfLf>73W!Om;C@1wg{JIr*Q$}{F? zCB3qbPS*)i+ZTiHo`^n<_`L9-$!nxv~PWN+|?-#?6Q>#DLhp(c1xLx5rGJc-?$i}fg&%RRA<8w>2 zJMRCcT{@o}k88h+A#v=#iJq8T#Qn~O+;FjsBKVbUWTsryd{Z_sH z;!D%f-hJwKQ2wgy%CxJ+&c}2l-mHiGi{sty-i&zXOBgmf>{I-CZYQSG$n%Yk7wMbh zTt0+==uW2=jk{sXUz8>;C|5?i)!5&wRe;bbi+we&6K`{H|NjF7A_%4oJmfVFZ(s4 z@Esz-zclnp3H$!8{^6HOnEOg0LfH4D^9$FR-eu#x+&-{Ea=G~7J|E)u-mlK~NvYmc z)_uPr^@MD{hx#X#b>D4*U+w;mh0>xv$~k^DzgNFx=hl3kclFQ_ZD-BC4y}LS z#u<{ndY9sN%ZkaQ)TAr=>hcy3qHJO%alV>5BTS#ntDD)JfaJM?i|UhhvgU+Lp0-`7gG z$!~ey@*I)l)6ZK@h8%O;0Mcah*S>#c8SEoBs`Nq5*$-TIH~!$spDXKGy-DKp_uC4+ z0h{9=W_bMHJ5#@c=f)d-f8uW5uadk*(pUvs-^?JDwG;D4|i_u?flFxSteXoPw z6_cfsUQ4IPw{A~3Rr?p}d^hP}j?aHym(RYAf5`ak>-YyPJVER#*YU~cdiTVUj&3LN z^sZ-D^xh2b$4TCBY7E5JR8+W%(jQl9Sn2Q~@Zfi(&r^RF~-Rr)|W#eQ0W z>w~*hKmD9{uzNMQKfY=_deH&FFuPB}`l)(+_#p~9yoz1XdVF20!WV6?&s%mkos@Nv zMs)CVM-~3)_&k)9fb?IvewErhY9V={EEuO9wyx2&Sm;zpt}uFzReogO&v}Z3{XA0t zke)B0p8(Tvoh6cd<0~YK@;G@5efy<@*NX zap)GKzsM7Uq-uHCFkeqxu|+_ zy(qWtL_5g(Co+DwkWIcz#rSN0#%7I==dIp33SDCTd=&GfF&;{nO1pn9^Qe4Z{BKIOh0rIRrKroa*Z6ieQs_*zi)7UWS`ORZ1ZD>EetzU zHE(6~B;B8JhIIV9)6ns6|10Te_Prh*pBvG!r|+SLbUP0E;9d<$PuHm3cRPst?aYq6 z`zNFr?5c!uj`~*`Ry%|Htt1@FgY)Gp0{=#VpRLRGtzhvatd`fPcID}`D`m|``%8ZL zcSE=y%ak~s`hojsq+iVLKgrQ4UXR^9HJL>Q`p2ymnOV8Vpw^hl3_M??~nnFUvSBYH!L-2&M?jQAg8L#*r{?*9D7pzuiIB>`eu1m`7Nw3o>%!}%4gJH z5zkDntvu!UtepH&KI8uV6y`BvdgblWqq%e$&#p84Y+r4>|MVu2D;?j}wqG5;xIU-v z>>M4PzCReEz4%hjpFLrElE~Z7-PeQL(g5x^1@1(Ht8!4;53O=gND7wz_~mY5gZjUO z`eS@uZa!E?Zl+KBkl~?n?)O(=-+;AW?*qVo?Vph|z1!9Qs`&3u5k0Bw4}ZGq&0r$$ zct7Lh>Gb38978yH{9^k%hxXU}_^?~$*!@k)-PwQ>RuRgR>(5W2-0xAiJO?6jUuS)K zXHITa?kjee-vNl*mzVp$%%!iTe&zgwSnlb7hCMnys*(HihHL2Qa{sBE9Jt(XVf-2R z^X%tH@77W167Sd9lxvsLrQ*;3Po(31eUqz=^2YsJ7JlshhtSRY-IdC>*#975i2qlo zMf9uj=hro)-#Z%6Zx!Ps`$)RR=VKcA^X2x&@)gr@`Dy6*%Ku6_){#S}G~p`d~dp(%lb>_mOf&(bt3H_!Hn)+O=H$=3eC|?>9Rn@k=E>*g8cvKL?ufseE_( zu-YFxckB0u#`?(p4f**u&IfIX*0(4(fA^q{e|veKO-btso2SZ;wBs(dZ<~=35AOH2 zFtvu^4HlLl!ZyFL@{mM?nFgn8ujaFRc+xKQJA$9X?^3@b%y2k5t`93oEy#5SXSwQA z21nA-N&kYNbNpW+Q+JSkQrjr~FHoe$>LszjWybEv)=Ym%hi~d{*!| z)B9Z0mZie~v}3uxyH@CX$trzgJ%xZP{=@jxG~IDa2&D6bIxAF%I% z$NH?}Gi_%apTI8Ho3Gy?;~b@Te6AWIf_1LNdjDBj$RYbIx6r;1Ss0nvzsB?RPv^bW z4g7|9AJ)5a_gk}n^z|9qn|J2Y)o;*w1g5_um%d2$y{TPf`qo_fT1i)X%JjG8(&1)R z`RjM*(vL`b#jklY(ktVl4aT=^^7i}jV*0axKJ9s_h_2F)dVg;BHP8>DD@gpm36mN2 zDc@@RplOrDj>YwpPb~NT-24ss$@rzYewOt!{`I;19G5Wu&k$coUjB1RLS_Em#|tXw zK3=H!$H&ypmP~$tCCD1h->V&{_(eXi<$h7)d9C|$csl;C%*9jQiT_1tZy|Y!`0?H^ zhtdf_%;&2@pW+$Qk$jBj*+2Mh$Zez_s(+R934~DNA30xrpVB(5C)*zhKJy`-SG6_v zlVW|jI47^7Pn!jdz-?fR``IzRH>-bUVY6P#hP>vhU z&ud2-*XwfpvK(KX-&1n&iOKO#(7r;Venv%aef`h%R@eXP)i)n-3!;6L_Z>#3GcW)A z9A1uZl8bkIzXp73^!mJ_Fm!OD>e=8#(^JgoLA zyQfq8i^@Hn2Q~d1DTaGIv|o(ra;%QuNO^rB=KTwae7*{FQu?IX`lix1o6jE9aZVxm zzdvM68NQPh-+X<9|B2i-=`kife+^H{XT|#VV~mf<7&d&pUaoG2m5mARr67|D<1K<{HfIA-6wy= z6n?)7!*qW(_S`l{e#iWDJ^p*nZ*%80T$m!1ZECFA_Zk5xX+h*3S zFP@K^FZoUG?cPjZ5ARvGRLW=HRXE4|ecz|o(I#>g<1P3NSvw#Hq94N+hOu*f|E}0s z!?XXrk|D3>h2(u&f42U=*X(g(e&G&z=j$gO_T}j2^$s8&_oy0NZFkz@a8*xI^Cxj1 zh}Ea{xV~1tm!ke@T)*q#@8Mu=Az5PjY<_ynVS~5W@ITZL|Lr;aw?KZ`t`~uBaedyd z<+=Rsp9~^CPuHGlvt`|^kX$PLehkm$aa9f;ZV)mq-zmfod+966X>G+rL zs;1*2*w1+Vj`?CcLpo>ccAHoW(%0GB=B4BHyXRt`NhAM1wo}t{_T`w+x#C|>%cbY- zQxWMEKXIeU*Kw0CmEV}Zr#r{7Hg4x;YhUDdLxqKYe~hzZjprZFm4b1-E?3Xb$(74* zl8bje`Wo6-Fe@6$e;%5UCw%jLIF;{}sK3DZiUi{XDU3h9{&JJ)P3^v%kN=o? zgPoVe{FKT^c5k)HOSZmMQpoIo@Gq(CC+d|t{XClY=bRrqI)9uN!e7$)7cW%*<5=#V z(ang@?~jV-M@dK0=_mhE$l$RaeBLbKKG6enD)sRC%XztZxxN>H9x8U?|D61O1rG6= zj&%;-Z|3ijtF@|;S@u>pyKecNke{sFDD}J}%7=bL=*D)P_@@d!n5UHZSdLC`{MVxP zjQNjUo{<55=gFG^xTJNEK5s?_>_-zg zxF1~Jj7PSre0Mxpp##(32?jY`{5{gCaHqG!kmG4Jx>BxCB)JrP#%X%*#L^A($#rJ^vT{7E|wOSv$ld`vr( z&!wU7NqlMexV(GksAJswd~HuU#qcg``E-hp+q8T-rA_J~9^|{zhw^jBk1O&yBhDtg3rKOK5`!4bs)ad8%M%pDg8M(sVH|U$?JE22isgCpa&(wiJ=+^x& z7u;a{pQ-uN3l)B|>05fa#@Ezyk=3JUiCvk6dYrE#uc%FLWqO;%n|!286tA?ac0UgF z&HHn=XPmzyhH*dsP2@xWTFt*XMklMs@!vm7Y2KQ(&)S={U-9$&qtSIN+OvO_@+uFn z5By|J&5r}_FRmioClAjbJjw9B1$cfRK&+>#;UDJV^nH)&X?l<9dmqGB=($0PC;0A&|(*<9$WXd?x6+PTT477y3=U%|5t&^Y1?r zuj22cT)&oU-lX;Tcbf3sSLKJrLQ+)Fp? zFH|H61Bzc*r|q3S^J2;8c0|V6h)K`0e3xjxbcx~>E>XPGC8qzEXufob@+BxZtWT;u z6%yV8hguigwGbAJZFaE%N zRpyTwAKHyxu7~EgxE~k1|1~=m+65f^KjmL+R}Pb&Lz+(h9YdJGK z3%W7f>i9(T{2u7oZ1(lq3HCjX&FZjn9}tpHjVw^O-4lK+_{98(%acFUxI0mfkK5b* zfl`C;26=(cD%XClfbC^Hk30Yb@Hijcj;?Dub!rjfeLm}9&4w^4#Ip|IJMm^bYYL^q zj843KIz_{~n#LrbLHyvj!$SXc<361%LU?2a{@}^@cBzKl4u_0yQ>7ff@1=AoYd+dn z@v~NHnC;n#pJA`suaThf`|l)nsPAqK7te;G;c>sqF?4Kk$zW$)ILrrj#zNuChzC{{FdLRoEm=KZ___J@d7jA z2LHYDD)PhjO+b8H|GEzF{Ss}b;~RQ49Qv3WcJ*5ASM%-2=HG7B{G1n9kn<1U#(4!K zFOA~E9_35etNbX~*V9|CRXDEK&5JeMJ@zc&P`{0f2CUtgU2L~niAJbrn6`Ca4>mwzR;hbhQ$3n$Z~4e zm~+HZ6q^75Pw3ORrLc<75#B7XqzJj=JW0BB0>2pUzs7jZ67=higT&5UWa(Gx zn{sj(KPh)do?oqhF9W09j=F!I&QZPc`8{vXppq?XpT~3FanTEJcr|PL$p88I**;Ie z__=$&`WD7_ee^lMO56D>qEDLylb%ID5Rdn}Bj6Vw(qrpOqx@EXy?KV&Xsi2S+5Jdv z=cwR#IPY;1bmVWmT78}GCezpAm>En;=*JO-bkO>f2P8V-IFOR>eyaEX=^C{Y@%^sH znD2Hi*W9ab_XjgS=ti|OZ0B(xr} zHk$_>4bGQ|kBLf#_d0C{@qGi+K_@<0`brHmeGSrk&ejTD&*OEC*CG8OE8i_&IRTv8 zw7lP2GqO>`E@vb2E#2(bt}!!pKF0Kc{wVo2a=GT43w|GCxKG1=pPi@oA)Od{ea$8( zu6Ofc{}wTQvzBMOu8Z4U(s=J@nEq0x11=x;k9wwQznRe~qT|)|=y0c%U#o8)|2Q7L zUzzn`Tg0i>6`GHBpPsnWi|I%{H8M}r-M+=&?>)x!O_m^3 z4DI}iC?Ea)MF=zhSmviN;&FaZKFLpqoB4YkYH#QVtU!7<0pnqK5#GM;)7;Kj@=5(( z_v2XK&tUh{iE20KcP&D`3=YC85Z(j)37Kw|;9+*K+2pg?+VAzndhlJscl$X2Ab7$a z$3yGQ_Ip^m!|9e<(GK&cT;4rC*nD_u<7oHOy#LDJs+d*AO`8=Dw*Sl0?-?F;FLv0Y zbPYpC)czX%yk6%^7FIEZe|%K(d%fv)wckD;lg?2A^7*lJ4iF$c)~SGae;Z70Q(7IrurB%JBZ^Cg(%*VAHqOgW=CQ;)r0ZFYaPP0KfHbxFEJ`9!-< zInBfIc|o`P_@1=ziQ{v^FOI!b0H#Znf9asgr|V(Zr}vy+abAovX z-b>!gV|3`c<(*N}s%)@Nsyv>02Mbkgu&~-LdpdvM zaX+JZr3AD7$ombBPuh^w(^tLj%5=gXd4ZKH>U-CiwaFO#95Fp`yH0#a@%>N#ACl4I z*CQVP!1qJKXQzw%*O@(7F2xe}+tM5FlKg4c7I}a8th0r7BiCy_??;K}c;dOq;;o&G zXFnWvDIE5v2-%O+TjTJ6uoff#)=RhwDwhrs+Fay{Yw+ng8SKwC+buvGSRH zw(^FbkHd%$>5|P~`#kZmwzpNMAFhclx9TB)bAG~myt;6>lU!5;LzvXzBq4^bFCEckHUPWZY{>FEAP_gVia^yU5yQUd#9BtPYV zVe*M@%I*7FpxG*Cg2}`l^-tFD{4q~WF2~RG9$jB|`$)Kqcl+q)JmP&m9H9HUyZ388Zsa`1 zB9v!)zK*x9lA_*y2;d=orM%IB`3}QYh2aS&nI3i~`YunBcZMH`$QESyk*Ijm4&4{f zYWCjc&h@7eo~-w8P~Q2$@Q330t9b%G89_Xs@CW)mYS@nx47=Tf{jjjg$^NNVGC7$) zVXX3B$&UQ07d}5;NM0oQ(lx3dX_x8e5|y9y9@PW)U&h1Sw4p>M$JTxy{}cbUz`tmA z(7zk#eBn5T<-=Zsy8;0`&UeRe`ZhI$4%huN*AM46>su-H>8zdWjr%=?MAuU)a-{7~ z*O>i+9Iy#)AKX8fzSY)y?iBQre7)Z9vHn+}{_aHWLstI=Emuf>D*EO0#{O2*H>GnS z(S9_e$K77e;&b^&R%p88>+3aMJ`X?a(01Zp8>x5UG+mGMexcZ;iaet3E&L0`&+**_ zf3*!&l8=1HcAox~_me&kH}WQA!o&H)!?}6uKf(Qa?(b#eFP`o2`1D4VhY=DH&w9MkwB)*_5=`QFG`((oTNJ+szu6wjV>ccI z^!Own}_bjR5|8SgW_7!T9<_WEynEn{^3gzdU%1w&X5HM~a*-}Q)N`#hfF z*^CD-dEaFD8Q+A5@q9ne;@N(x<}$p0gVa5EzY*c|Mz!~@H{QQc9xebv-hYo=ONhwd zwO01)I=|8uJvXpx+`p;)%leZ=lCRRAOp-9wi*zI`ye@Nl?tWR?(WdZA%z=Jq+=QeF zxVXG~{#NVv(~hZ@Q9fs4vRg#{rnWy=X$aLJts$pirlP*~<;e|KfAYos(i|xcV*m+-12*XOhk((uZ zGV&^YQ_kisfY8`O{3nUs+ad5nd7Hk67s)&Avi^Kn>6~_{9Spl+@h|)SZ=7HB-{8mbqW5*;LDIT#+M@V9Xe8w|hKDHGw;J1l zn=V2mo>s4i!0~WBD%Sg(+9X=!neDjA@;6)ln2w_F4hNN1>3bAkrSBF`d$9ojvvqv@ zUWEU?KIG%}K8P4hvaFkOohqHURODjUS=R}jW4Zkp(w(pU=co?vZ(4%VfLoTA%%kmv zeEW9*eg4Axwe?^Inv&GWmH8{p=PR5G0tPV5XMDfz6&k+`L}U4GTi5me$mJIIeoDr) zYlXC<_3c`&55$B@p+8l9Yc_kf48Q~)jSQZ+9d}VrH%oNpKUCJy76^Rm>B(Gww(6Jk zPqs*UDBq=T)3>m5m4@ve1?qJh=o)q@Jlbc$r=a^rV|;i{rV&2GV^Ypu+#`5wG(0w( z7LR7~{~qlRydTK?g?p6_Za2anZAWZB{s>u|ADMrUvnOF#`4V=hoN*kAYGvF?`I~>% z2V~qCw>y@*0TKsKoF2M@|=~M~L|QP1x0}AH7E5r(Gun?uf}d{j6hXe>hL^_4&tO>qPX& znC|{r#ut-M%F$cfACVA8DUC)2mls;FI& zcGGouMFQ?6`zIM*sE6C5AK6ty>G=k z+doy-{Nq6uriUSIpZh<|kL#8y<51i0ocTK@@62~C+T(n3z286UHBv!XrhHmB_thG{ z!RBLZ|F+L>_CfC09$z2we$wYBJU!d5Vg8ltk?+Iw@uIKGXX~XV_s-|AN9Q+uUUU4} zD)$R-D+-=I9~ZChcF{kzcGu{S*(t}<*NKDaRoX6K@!eL_Yg_LND?va!X}i9|O4Xm# z_AR@;ar|8W_uuv(DmQix!`IoT_p9PMp25yh`8ul0yZ5uT_*U0ni(ejpZCBPlJCEh_ z!;Wtu`CGMjrjLE5S7D#>!SV9-uvlLny#{u7wbtYIE90Y`?{a!mo@u|PZ_xdV*?RB! z+OFX1bLShqeZBX5vuoy$rD`6sbyL#64Jfdm0{Bxs8+5)PKQBOiV7klY{#iE(;uSsU z(eP>YK>LR?*8}ZupFBO#1pt>L_XF6ze}doT{Bk|;{-?2ANwc%_=8shm_MkXeoAtl7 z`taS;=!4SpcSj#Se}?*CenPL(kMw`%sQO@XWA^5EMjw`Jk@lutcWJxlnmn{@Q@&lV z<9poqU}5VgS~h5Sx%MOU52;_f#xGCUME3`2584ps_?&N!OPLQp<(b~TT;5@~*5~%! z`!7~zkpan9 z)^=6)scSgav)4nQjFYsOdWv|O-tvly>O0N?pJV(@p3pDujG zy*x%I$M1-?Gs5qP;Ae6Z(WePj`uMIfzia9A64EJxzk^}O5g+f5eEh@l=Id}_c!8p9FO*4KaqBvjNnjzK8kkux;ew&L=)n9 zCnD^4Wcx8}{d^rZEiyemrv!4z_lDUL_w%_<4rPm~?6Qd!~m zPSNp*>qW28C8O7T0h6tdxSs95MhW2KkyiA1e0*MwczyC}9hbK;-st7_-}&`vq)9sb zO+F9fKeIZ%pTzn(AII;t9+p_lccLCXjxYJdhxLE)=M_Ej`G;Wl2NcKYxy04&Yovl= zldZcV1oEBoaSZn_5o9)wyF|bz;o1#SE?mh|%%HQ6muy|y?>9)-s9mI=O}Ocrlfu_@ zjp}PUctXOf`xTG*xMzXmtcPLO_--|Sm-CL4q*$+c-jVH`3kv~{kZvu zgrpDQQlq&Jb~tAbmO+oQalFYvT;CR}?|PIEW$nNGK99kPYDWk0Q7+aLe1D0Z-}Cd% zY0F_tS3Swr{cZf``)$@?pDRs!T))`+Awq|rkHmw(C*DVK!0@{pZ4PC%=V3_k3d4$5 z>i0-AIPc-(($Kz0>M1srDeqQx!LqGbei8Z&ia8)Gz?E_=lnyb@zd;Ib`Jdck}U}{Ed6o~r@oKO#@TUu zwtcx;UfWQF@_I7Y&L+yM$tmglG2}}P-$BE};rhKQuBSfF+3(}bd5T|{qxiXBxeP=i zop^qp&joiVpIvXW^?y4D;QC#U&pS}w?b`l32o+(77k_18jZWN;EhPV0rO&=@;(8jC z9Z9hLcMJQB&fC?lr1!X;QM*$QFP>fFxLNS%(|j4-iVDx=gK|SX=ovd5zaVGo4kW9e zZgMuZP33HnBqy1iHEFu9gE-%sP0oUyJ5R4M`I=?&W#^{DENj;_#-|wy-}m{tzR~X$ zdu{WB*}W>4n4Px$|LKiJALCm+x~xGJP6yi2|CzI+ok*u#PRgC{d_VM$`5Vdcyj=dh z$e-t{uUAp7sgvni#h?8M`4rV+a#Fr zzvl{t<9L$4`*ZRz4@D>si*o#ZJ^4FZ;raY{&(&(<`tTBYz0lHc&^Phga#gkbooRiq zq5Yp}@XTK!`Cbp4)62DeVTQKX$BB*Z&GGxBe4Q-w^9_CshwX4U;Ud$wcE!W#=IwVo z8|Eq=vD{Fe*?zuVesAelzNaOX2ZzUe??$`UBx+v7+N;%fYrg%#_I2N{`C3hmZds-2x0t_~`G>xbaX|C? zdIj5c?YWSfl^Rd|K{Jxp^DSS;LD5I&pU<;oChtLIA1m-=~=z1rSvJ;us4o4=XaMVrs}^@MD`-_8U1 z`Cgx&Oxv~I(9|hE!k9LB7ss^fyGa|8zh8;=ikcDjD1Y2(Y+uH$6*#NG|5z`NAom`%?lb?nSWd0Mm{1;pPwYmHsxBN4Iq_&iJ5x=>X|E^sA z|84pI^+a`kYC7@Rk<0&K3tF!YEt4nIn<~NO3f3Ixyf`9DiV>}ixe7mNz zJ+Bve0det!*QvcOj??~~>jnUkIQ-d7kDlUA((K;wJx2HJ9xFnrro%kc$9nz&^nR5IUx7)J~+^kJa#Hs=-?ac)mZ6cp~}~_P0rXzn>-M#{{Hj z=lj7!KE&%2fKw?yLGjx;N#5OO|GcLDydQPY@OdlS=j+pU9y6|=d|-VXv4njm1a3tR zk89ZE(C;syT_F8a+h0*g{;CF_#Rm7!Cj)L-`N4YrKAN{&Jxk@Ic$WD&U@t^EX}$t~ z@VGw_W~iS~NPeOCTn<2Z(sp?zgH6gWwbw!Rdq&}lN>l3?c z{*cdGdHi_T4Kxe)YCdXsRM$V)q$HPeY{E|NBHK?yI;P4n(n*K*O#~R-DyZ)ZFK6$^Uqq@tHPF;meS ztuJlYa()jr@dSHMg^SfLbdUYD@-?St6@4W3z+Ye4crAZ#Ml44hSNMEB?Kz85UT?tL z#~YbnILGju!df{0rt;$S$jd9?H2t)q2lPh>f$@L)6X?Tu0fYWW;W`|q^Tv##U{e|Q zalVK-3FioYGv9OD_09Ov@{@whKM(l{$IF*d&g*5o=X-Y)@AhUiy0sxc*Vz_#DQ^*! z`a1A_+;nuiIg`*pZ=9!Tleev-5qUh6Pnq}FrQw*5``}=D{ap7#R)043v}?%Q?|hE^ z+26E5?&oL`*E8>Thz~6o*Y!yMJbip!GsfqECy3AYh|eDwK3Ch@`!TamF&?zT@jA!^ z2$s{M(%*~~x_JBjo=fldN2AX_6Ccxuv}={>XU7V8$9T|Q$Nj?!gei}ln)UHd*n3dQ z(N0Fs#vVH4c-)@){a}UUnGzq@voTlCVQc>aF4V= z*1r~;XtmCae(#Ft=k>X zzGiP?JZM*l$5nWT9qR97`OPjlUk0=JPtE7^pj?M12C@7LpR6AvzuS<`dd5ILe0`MR zIauiR^<>H={$>1GUH+!Py`|+t@-EqazTRx#$`6cBs#l?`;|X79%hscfkNss`Ul_1? zs8H7Z(Y`((c6?Fb_1pf_fjPvQa$@r6_q+^geSXhNY3P8I>zzaFF`gSzd~cb94g=4? z6zvGvK0dBj17=s8-ogDdTesyri1d4$*uv9aQhD|DWY;IsaT@6A^It4C5Ba;t>o}tk ze7gooVB^omqSX^h8Z~_r3$h_00gb~eSSHcSDt}PcwB!S zk1+GF#$U+V>ZI$m6XyGM{Nwvb!#S3}MfKC=+V^SueGRT>uD62|RlfcFp35oeA@$pQ zrtfF=b?exUxE&__yd7>g;(Ri0TB&eJpXWjU-EMa`Ro^$_<-_HjQlRHT2sWM=-bu4x z(@=3~NcVY^Y+tmGyVxE!rFRY-V7_yDmoBmI#=Jn1aWB9&nJ4jeAwRbtrWhWpmq^BR z`xeQU-m^;H;T5_sF8i+U0^uaOnnp5pkj{0PJIG<|oQydN2-{sq1VCU{*iXRYL; zU$FFrh9qLr4&VQ%?ThKp@A|kO=<9N6*G7ToerDLI^u%|ZG~Ph7T?g5&VWq#{R~U9` zzSf%+e|+Cb%3+>Y-{k}Hra!(a!jtemfbj_SPg*{uLmzyDHh{YBZiUD8ZH&r|*1jEa z`%G?q{nFdTdLLvvhW1*$JLK)>;QbsM@!b~H%W{7Kd<)5l@WcDp_`6Y^l!yKb-mlL2 zYn%ZhoX=sr73W)(%Xg0D`*bc}$mOG+5Z)(p`O;jzqUC!emv2ihA1xH&9gOn%`U~UV z7{!w>pE{;}1d55BrN%PffheD^6EXfa#JeBo?Pom5Cf^ex96oHn-}^VHW)gnJ+a%5H zp^sz2u<4KSd%xW$%XB^$co=qtPwVCSUWPCkS!{ZhM07V@Dta3G&lKq}v`XZ|?^E{q zghG-^xigW2?KwKT9K0o>6Y04-mygsXeeTHRYa|Doa{1nygU1;g!uyk4zD9DeKFSyK zabXlsyg%4L4*n?0=XQ(r&qsVCIpDq%?r8Dz2pA6u{d>3S{AsVv{|_2J@!dY*1HN}D z`5rm<0tqji{49BspL?Tu0N^`dLdydFE zwzG!_XS2d}dl_~rJld5*5k7?XT*BLVSm6!pcMe@YobD`lG*|9y+E42bTo0UHk6bh( zYk&1V-A=P#OYObj6iJEiW?Ohs%|2b)HS&2u&K|zzxz+vqF|<1jYyW}$+R`54eIkeV zY_xaewML&I&A0y*I^e-PfYPCS%;;hL4JX0yI9&h!0pYjh@cK68%k9ENR?g(e&!J_0 zo#E^2!ZqJhx?an3*gqjx&v>{DY1dw%o6CpqI}DebKVj=wzMmi8E7$yy+#O}VF{Jfy z-t-W{l#6XYLOaSwC4V>efs#+9efAwHn;#Fmk4buQoKCp-xHt^!_=EC)Ai~?_Ka>^k z?B1scp992am*V61%@Ci1z$fdUgQlaOm-<8bfVQjG%Dr9R)#e!}@6_)|!}F8Tet zdcH5RcdHuiUh79Q|5V9Yvk&yc6E2p$T&^$lgS{Wxhz_kNx4Bckl^*eWrS#XE3{RA6 z)L(y@@*3rPas0h5$OSD9+x5je?RUK0 z-y@!H&cSWek3SscW4SLOoY`%o2jd|wRsA=j&|g1C2%FJ;j|62uU*1ppNUopq{&7## zF4~_@=JL6}GL*~Li0<#o<@-Vo9?Y50eOoSHBf8%g<#T&adb}!%C*GfJ&_BK<%16G@ z)nWPT5uef7_*#$7>?h;-GE&&}r4&?;+<)`^7PK#{C-b8qzm&KA^Y~Z&IKD6Nutq1X z7cv(1$M#`V{3qRi+TGM8aN>Tjjdo-}%cV=Es(pBqhG`d$4t&Jn?R%$1jfZvD_ab+(^DC7v!kV3$y?Db*v|-hd0u=JTm{y2=`7=|7@krLl=_$ zYTuDgNu+$^XXW0YYdR5v{N6E7-?z2t`}tG#JqL*5N$} zJ)8fZkMDr6-a#9`5-*^DcF}57`z1s-cHlo*InO_W_VO87rtdyXU$)`rdV4Rtb)h8m;jhHo`-1UZ5?`7` zDg*9Z<)`;UeWekJO)Aa(Yk7Q_jDf%hyQnznIH+YYv{T*L*IQuaVw= zI?5O8{oA5=;@xQcH4^3XeHLubn-QPs|0W?@rqA*CSNj*`FXagTYUbm7pKW@7n*d7f z9EOjxeP4p_ukriU@x6G}U-QrDUr%~bWgd%oZht=HVUFTgZ{LOMEj5kvyu{Dv1*pec za^sFQn7>?xDp+x4-BJC*bfwmlUvC^7KS}ya*YDB{&FB3o@m~H*Qz9h!I3hb|V)Mex zcQ|Tame1Oswkuq($L&bmpWX#KL%OUg>N?+{NWOd>C1mHHjtYHo&yu`-ewpJB@|Ar4 z+{!nK5xH;Uo)`Q5A&fsbf82i%o40;z+BV;(BKgPZA<9dZeBlA#ufq5bKb-t4^Z#gB z*CGGDL5%lxCA#rhWStKT8*{72Ix^)EvC z3l?_0`?Q5!?{q%g{jztc`qgcp+pi&EV@M^~(aDSC-95(q z-E)>om~f%0SV!Pr_#g6D@4016rVqUjSK^Jn|l%X3w)TV7&%*lOX+EqtDZ zUtr;83tuSj{_^wWJ{N--RF87kkIH#mxjsyNQvIF#|XgWyO7i0YD<5eF=V1K^Qh3Q>U zI^nz{2glcq=5riu`>-6I%OCOQjx`_uF@6K$eEfNx+p!gjuj_^Hf62yiWlbLsp>MP+*joZ0Z@$q)X?Rz!a7t`TJ zwio}|RR1noA^EE4L)O0C3Xkp1^KUqZ&uqhI9Psga>a}l7l+Jb?&cWeMIO6~76QlEw zl3Pf$e|P)D{^9Qt}-#C!L`G=Jv|%6!BOTjdy%}HWlXcV04b2c)c2Y?gc&g ztjGU0{O`4MH!dgX5?g1v6p45ozo6=vgsp87pZP^wRS$jq61JiuJU(s-Th*SpUlrS@ zL%=7tPxP0F=eM}NwL!q(JA7`B)Nko&?~nxlj-K!L>uH~B@n#q7duBcDvn;+%-*!%> zr@dXmJcq*?V!RFzuX`m~`1v%@jQpwgqmGHZh4MjpXY{c38K(#RME9ef@zdDPw0UBX*59oXj>A-e=JCZ}r z*U>^}dRayQ5A6o|$N1xD7RybJ+Q)J}uY+va{15Yg1Nq%v5f46o4~@&G%cHl$@h>F0 zA1Z$?FO$AL~DGAG?KJ9w%8?>xaHcIF*CXrfJGCCpBYd6wG4LV4?IPz-|+GESmnAz3I1X0JPC9+O_O)n+G*kQEWE(NMGG&IH}#0^@6P$h zKA-I8hp4B|%jqdwP*1-p|BNr7<2kK<8y%Vdb<}UcO54ew*R9nE*XzNFM}%+jzAo~` z?Hl{GYhpVDKg;KJ&q4nh=j)E!gM98sJtdcKc@7>qLVU+de{J~KdYIFLd=h^vYTuHm zeFc2Ink_q%_S~4Of40^C^BmRD%!~WmxinnjH ze(nnDHSpx){X@fkM9pXAJh%DD;SA{UG^0oLyxW=6!{^;@Jq zC?DUenuk1ddboVtc^Z1qZ+ar~@f&`x;I|+jpEY{?>~Ye=<>S87&_nFd6OfOuJQjMm zewh6T{q%0YcQ|!VZTtPt@%K*_?0#R5eP7J)ccb0DqW}JXX8PKWH+;CKon9dNd%F*g z=_}v;wNEf^bI(IJ_q0Q~@UZ`;KN{AxF(`h-$JU&EHGlu*(iMxRU)0H;vaf}hWaGTO z5?yyaaz{i@+7a3t+RK;F-fq%z#ODLKd{Wv)fzN-u50QAnrls=!FwWUsf?xIOy8-Y^LoX71N@c|_3@d)cvo4nM zVW+kywfn$&=g>M3AC=4W`4U9`*C{_T`PifJoZn*myj|q`N8U>jj@SbD!{w$ZTk$n6R`NC$UtK&($AI_C;v>)m_ zQ9h2-=3D&_5w6cW<@}&{e+NhaI`c2+pW}n)b9u<-fhQTC+V!1J@1KMQ;2CJwcb0DF z;=?%_KNoUHKgZ{1{kvU$FDmKqr`WFxc1yb)4&`(O{(CrBeSL@{cdx~N^54_@wYn@k zVCROHfnF3;$^lTp-HuJ77Yy^^x;Tse=`0B**IlXaWtM;7LJfO84#&^$bH7R(vaGlF z?6C#e_rrKpEp~C^uPgG{Z178}CP{BQGUDmY)k8V0}qowmC>}cscAv9V#XUs=Sf7WTzTTheTcA9jucC`9u zoF;wdY0_t%CVh6Dbic1JyKl|>i|(<{kp5$&j6!%guXLPtdb5V9AM9T^&$Tp~=cJy` z`abQ|3F$Zdyd3TRYmq;`7nbMYsF$=n+^>>{^HkVz?q_1U`vtU%OBo)(A3QA2aJ};E zFWCQ5uI$<9_L2MHIKF0j^lZ$p}J*`^LUa#lZf*|GSU~~_z-(w%skMpu=%Ux0*^H10Xp|{8H_looH zmHdY!|KP-J_TG4k?HruAMcyO36#&;$^5-aoUL{Q@efPsa(_dsi;OA->-wZy~=mCvA zo|FoR$N62_^CyBwy1h-`YjoYQIQ|=wuLh3M-S^+^0wdppoYZ5!|qPm3=oc-!7*U>%A*i?^jT-*Msw_HFQ}3 z{Jmcwzjoxx-}$|Y{s)~tP5hqcP+p|)Zj-WPr{No`Q@X zK`+p4)uk0V8SR|xJmR}c%R9aO{4eSJLg0(<0!qE1JWuhvPxFu5tZ%k+V^kl@T?##F zrQ?bxlubWueD2?2N)7)Jql2$&HgD2$**We#%IEHJpOE?sNsnZpoRE{8|K!8-f_%cT z%4;DpxiI?__HB^z)Jv5B$-dF^PoMUOTHf|a`n@{7PMF?vOvVR|@|JJO%$b^7i8ukNNdD_%hn z?cei5!9VO)eFugd+B_%`&k9Mmp<$6e0nTB#5BG3a}6g}h^Y*^Xf6eOUiY^m`S5 zXQIfP%VSc$=6%F+`_N6@Kq9qUdp;)*n3jqWBRxpU0Ij! z+V1I-YwzKtJ{FRP1YX#CSl@Q9Fz0EbXQS_5oxZiP+_CJm|2pGux-O%Qzw>aWL+%(2O_vz5i#eOvHfy*W3{O`U?IXtHJ&(86mjvw7)Ch5GB z^{30gcc>cfTjeU7%0VnoDUB8$w`X~MAs$;q-?!->luL3!LiBkd#I&O(3DpV94Q0?7N9lKI8GEqaeysa@;o z^?Qd)8qU6xY5S>tKBm8f3h)fHs2}6}2>Y!6w*7=X(`v^H?0@R{%gaGWpZ8*WSu)uD zeC{8Y%8GBV`JH|rSg-q&>nQ#7Yc>iUQtSUR|7$V^C3yPn+}pt9RteK?11-7F991Xj zc5O!?`GUZ4{?Q+0y8Efwet7d&!tR5TKY#yTD68B}-voie6Z35c>LtJCLhoFjr{AFs z^6%B8gDU_29UI=OLHab?xGDSobXmZQJlzGjaeqtsU_F0MJLBW1@;1RY45=Qb_FeU0 z^hxbI#>9(HC7*`Vb+lrY`7W1(xP9a|>-{~nFRzc-UnuoYpL~bB<8n@yv0{%lYkEV! zO>bV#!*@GZ@z-Vxz7>D1RlZ9U*Lwi?#{SxY$iA~3FDCtlmCwQMhm6Y~vi6oB&o%hi zcba@YoA>mQv@YkxFLO{LTD1(u?+e5ayluW&T$rU-Ykn?L$tp`!h{W=NO)L-=?4AB|JXF(eDZMAm$cMvX^rURtn+1g)cbh%fGW1dUpgmm}^;8(PLtNy(^|4x+4LwpYa@pS() zy$t~H#OVy@*MG9_Pu-?+Sx9~+{0uXg8+La#p=y81U*5lV7cAcB*Waf6B>kA;-~V=c z_P1%qEFS$cpU}2c-hK|8^Ct5Ula|_Q;^~K{cJ3!_()NvLHu0erGac(ye0<$0ZI@s& zaQQ{@W8ix2hX*d~l<;5^Ypdvs-y7xSTn;mO%#`fOhtC=>?eu%@2NXQMf2HlIz)?Jj z5ApYVJ-Mz%383BLbGrI?uRa-*FXwWw&fuJ`{(L=@GwO@C)6@C=i#F8f@&4Ta`aPtu z@5A)(DUFm7iHGUbE5fCuKaujJPgedMLgzl_@q%xdT;VhE_w_v9GtGx|ZQ~n3<|IBp zf&qLY@F*!UyyFo(-p`I?tXtXr?7JA!dO?z`9lj3c_l3=c9&{o-U2;_W1N$C0<%<1( z+NJi{zqgTg98mpiM}zRp1@IYo`?%TtuIxKj*ZX~;+HZ&J{k-5_g=78D^r>9}&%d|D z^C^TIb}L?CkK$1rcd_IP>xeb#-6SueFO`t`OT1;@6OxMdeU<)A?UJ$BqzfCdys%$# zJ5E0R7`*d!^{IdtkB53nTCexFnOvd_>Fn}58vF^Mt;6pr%@MrZ&KDBx&qpi&`BCxX zE)Bw0e;~#W&4ipva#eqyZ~r$U_&p`^4; z`MB&}IFnQVj*0t6nZLC2kjM%7G7Wh7{WID8%doX`r~2RNCCG>;_3vgXyEFOs`8(HN z-={_RtrtXkV)yQ)9ghDt!Gr$UiOV1q_M~?Ic+9V3q;ren&HM|-T4zJNY`hfb-y!)= zWbl{2*PH;!ul;eHf1Bh#Ci#8;{ourdr$8R)|6zH@`41pJ+efV3{)|S4|3uy_pRzv* z?Nd=2a%JC_eEWY*sivKg)7sASc1*O?-SG*B{&0eEqS!UPXDe z^;Mj|68-KTqx5%qb-y~z-B;%H%H-}o#gq7537$TY@2Ff@2d^UTDInjyzWlvLHTd*a z@VSuq*t$q=yt~NH)A0Mc>{57+bQ|P9PfxZBVw0^0xL;UI)DFe>QGNg-SLt8jB;d*L zHb2Ju6Zhks{%N~pm-76TAHTT&-wb^C5IXU?lg1d&O>Oc@S}on_;_K8-hp z@4)zahwuAkyLpbp{jIsErxW2&QhVUvxpaF*d1E@u?V1n#kd1sx??42e3?Fqvvi&RG zztgW|`OL2@OR>z)&gQ4h{<5BJ7>c?abKZ{i*>gtUA^JXi3h!qEaOUIo>|y*SyrPf) zn20CL(sz1;zKb{|&wOFFwlgf%c=CtwoR1SY@>j#mk*c~S#c@y5@@>}d&1qwD(m!{e zzUQ5pXZ!IAkn_J{k{7Kv(Mgp?X}lld+oK?{&@Blf5^Vi9@?hyLxT#J_Ln3* zEhwJs{dc>!D_ttdSv!z_BG;N7_QG`01Ihgg7xn{=pB!(|q}h41a6Du@^-C9g;yo%1B~>|$wasU{v-5Py-x`?;|qe$%MJ8$Vm#A<=kGMg17> z-4h@gS9|Zs1$RioTp%SMeIMTEITKH4KF(Lz9zITx-}@OJvvlNtfZ>NVOnYE;U=I|d zYa}5VQ@Z_~-a(spX5)tSr|f%IG6BxdL)GN7ewo3u5#iF6n}rW)=T`Ck99BMmmXD3V ze2e=Oe!NHg79UqpKRVWXGJdDiHW*%&7ss27uc*rB>l*9ZH9zNXtMSv{B~8Y<6yDac zeE%nTVv)w%`6Hiiw#+p==of1tXua^CCEvZhw`#iE&0+hvJ^FQk_VtOXJb`kv zIglIj`%1(okB>@z@()3o|FS=oCyz;di`CofxQ#{xufF5lTZ(&G;(eX}JQ=Ul*4 zIN!HU?=4BVMb%rB-m5=+T=D%$(mgLncNg?L<9l-PAHNv-OuIvry=T~99uVp~iXi#% zieUWlas0*DE3W{Z{@#tRgCw?I9k$mg@ZHy!Nf)Xi=LdG@>i4&Rqdh|B=Vj-j-3agV zjm$pjJSqH7_MOspxK-sVF2aa{bN?6GK(d|y+ zr-`4uPuKgBM|2%9gWIn7lRa90!UGNV8+3qjy%^f@iy#X{OXs{HT$ju5GlumceZ>DX z=?vOstHmFJ@9mPz?h?Y%#m{QLo1^?qI(j5NDQSBom(0`fT{As`9O$*lUH}nXibg9u{-zlc;N@qs*94(LM4Nx7S9o{`lZbk#c z@%|F9EK0AIAl50T%8&d$h2!({`{dg#CA7EA*QmEhA>*lWMqqss?+E_WPx|o(F17Cr zeO{7IH$L?vqokL_&&o5o_wQU-4k1_$suZPtnm^sF`Saywc#KZwy9^!9<&AoTHD>&e z{*H1+YAbq#nzG-z`qM1PpxFc&C?g zd^p#?C`w))+lM(qx#c)RI-bepn?StJyE3{>UXp-5((miF*?cN@e@aFl%HckUxlw=D z*xwbo}UySTn{8AEpI}_U&a^4Bn6F+3+%OMSK9}soQHDc>nQ#m8PC6j z?LGpjXL}{ZlHi$jlb%mY+9eqEpZ_BrHy3KSP0gQdoyNc8$lm8tv53kzzeShbBZqi1 z9T+|O6wZrL!KL>z2)$o^zS^SUyqzAdd+vjs<>wPB>-6VIy?vc4J3qcn@rCQJD=)9e znV(Nc->-09KewlSeoj4eGN(U(^Zbh5@_jR&{|(&eM{WGvhwtAhuWV14Ls8uHCIO3^ zeo^R-n|@2agN&O#AnO-#)4RlSiJR_`@hond8F6Heo8BX9hH=yVGXBI(7s?VCgu7#9XHL8cQxXsO)_4@P4nc-t+;8njMH(`dXe+E z>E#idIBt5S?6|~DZx%Z(Zn`1j6sz3yZqdhFxBDN>YCEuEY(M5JM!(8n0voZfTtL#0nPl+95Vz z<7Xs&C`fh${mv|XFi0=j_p^R}p8a?F(n|e&-k%?@eLsQlD|S|d%I*3P{xI}{ zuY>!$tVL->jHAfUo*9P$AL$!&?Ghut81*n&(tkOZ&M&}=(a%Y`<0YQ0LH#K|gz)!!Lb!hj zBH)hu-{e~C(3f!oFSNTzG&Zt&DUn$^mQ;+HA zKGV-{HT`_O>E}0sHtNS%Y9BY1O+UZc^mAl|6-)$&P72ye-@)R5F`rYxo_m_ z%warOjre5*uY$+0jQAc#SH){TT~ZUzCMt^du7;<5<^3@%SNqQuHF&Vy2zV8s{sEPz z@)Y*gYP?i&{ykNQm*bd!e-XyhLMld-(rP>qLB!9liRZXpj7l}}Iu24BRpVg~Dw-7= zmP@<0D6Lox&rzc&tzI2Z`OCh$4%(G7EB~%F#81oE_npIda!yYz8#-mv%h``1cu=+GQ1g?;T};>)!MBg7)KP>&MNn*M5w6vNCSILHlv@YqcLYU!eWC z`De8sH(#jzxcM6G$IY$Uj}cF~jGN!2{kZv++K-#B(|+9iYVF6(S8G3RUZnjP_mr?- z#LXQd0de!Iq#u`?FO~jFzOo;i8!bj}mYI2rH_A`OvtOD+{0jNWc+zJM@yq2W z<4tukjQFdw_%G!2F8RZDyblxlqKrn`?m99^Hsq&urt$25<`93C{A79f=MM4KzY(c3 z6iGt7_HV+6^TKevWj{6tcv@{*F7=5y#LttTwC4ji>gxvUZJnza%~3d%$9`lE`AhPX zbX2T3^2z!);;HY=;SP9| zON6K1G>3T2&G?G-M*5XH#s?|{@rZz9e895N{Ctqf){+G`0qfR?@e~a*^zFOf( z+Idvx=i`cn_8`}-(#~fjp78U=Dio)kI-d@|KM^~)Q`foO4(9nb%H7Dc`t~N}_ebam z{#}jhqh4fUecetVJzTfi*L1$>4_miL26Qbe*`QoYwk!Q{6EZOWpoZTKk1@XA=KCwL zo&Qbl)z))((zWGps@EggA87ZHqfGxLq`RK<^XN{muix=J#>If=c?|L)oHxk+(>_GP z`S~W|y&a0g*9FOU<}-Iz=P^D_ewq^Sbx9BVJmE~|u=`P%*UR&fu6d}q$7lO}iEQ|g@0+4-0I6c48~lDy^LXh@WPr=oyJu=YaeFntelyXb_$IDa-|Nw0@yU&fKlO8$ zH!6N#KTd8`{Jw6Q+^BfGA2+I(pZ6mlOUUByC9=L9sBhLDPM;~8HOt8b@BJv_w_&uoRul7&ymc#-ut z-!GfFLesZ_V7PQMmkd!iJx~!XLf0Nzj)btYHfdYeCm7sGrIiz_8!H<{T}k4 z_549j-f6LL{cuAd@7yn06okp|^D&`!y-4^~x%3S|`#T)-O^2b8(RaSm!+2UQ`S=Ml znn*9u;T(^Sx9pEAuCDaQbaB@yV#?oRkS?Al@r3^@?!0i9F1{#>pI3#)-;2_H-;rsh zQ?$D{ZqbtQbAv8-9G5;8;N`eTc=F>@K|JescSogu{j(84e5N;g0T0(ywlnv=zymj_ z+^h-AKj|{|OHE+-#`z4R0pS?F3t{J8ovMyI=R-j|k#mqUHQks!1aHh#U*&&#$Sk=Q)h$HB(-&cDd_0de7< zrC%jm&E84O-g#K*%eXWv(u>j8 zg$}PT^YOd(B2I-9pX)EmUEoH;bslsBS%)VG&-qZkNEhXY_24{;KGWU)^>tL1_xmW% z+cAGGm+7~&9{tD+7oKmp9P#;mWUp_ykNhZ1`WJKldK)U@deYC$yqNP$+dz-&5kEIm zv(K?i>$|VnW#h}9(F0}*^_}D^?7TU?^kpAC@;kb#t2*p zw${8{FB{`@=bW)XKy+HPFM^I&r}F>vH)>2j%?m z9M($}*}2qfaUFc5<5*R_bT#8#@OI?zLS&?V4+MBg_xC}!_g~6U$?EfE==q5P0&oNH zOYn!yr+veuxWT!Hp-$C{;d~Tgm)-Bda?fKJIOx3m^_{jaJ+AT8>v$Gg@^J)WzNR|) z>dk*C=b_&JAttQ(^1NKP_cFN&%9s9Pb}!3+2`Zk)liAHSj`_K{>^}JbpUg9tYW;}s zVc_%c4gLNE|875{Z?3}ocpBP`&!C>6y@8oo9X^Zc4~YXE@D<_&hgzuSGOCP$mVU8)v; zH!Gd4>!$u5S~`89;(3qCPddHR!s6ll+{N-^6V_{qC!O|y$mz(mQL*26KQUAb-WT!j zsZGuw(sj3FQ0;EFpZq&kKi83V9x(e#3C_OjwsR%n{<2aee@D~SUD{tB*I2H9?V?=n zwJ?<2DBH>IH{v+ID0q)Cl-F+X+2xOX|2>4W{&1Dz%jTQb@7P}COxRwZV|#5=c;|mM z5A^o&d7__7^m(MUueVpoXB36`irxe5@3=T${M{G-{ulff0#ZNMKWOyW{ZX7B5}&yW zANOkvzgMrvN9RusABQv_`Sw%fqm{?-2SPqxt8m%*;!7lmDz8EAmgqh3!JQcljq@88(;kH67Wla{6Q7 z?+Lyi6!7=$A%D+7PVXXLv-&B;KW;fCKa`__|0lwa|C!^*8$*7Wes%rt=h)6PAC~zW z=$83IK?OE0=soapA+h!O)s{X(=NE-LVXM-9dzJ3*6|U3$J-qYD`p1QKo&ObnR_1@@ z!d96VdViw+;5?E2h594iWcv@+&a_iYNDt?6kFefm7tpR_IicM^JB#=V@Y$c|A-x#s zfEJbu6^Zx__*)r&Ne}V)J=7sQND(?e0Xnn!5%3cp_v@d6S6NT#XGrZLsAk}U5eygN z<2;9Se&{Ugot|aAzb^D$UQ-?|f0p+fXIb9c&$7HP10VU^1N^?#c!2GrcR9ehboBjy>+nluK?^=jRR(@!x>_d3)5)vDT~`**f9ANd?)b<@|w|{hVw( ziP{MIW0HRV8&7Ic{WGam^$)`AzwxA>g3QrBPxTMZowL0erkpUH{fzl3|2&UP4kTt@ z`MoJzk0nWd-h<&e62_(*9K(7JN9kf%^@sAa9=@9;KdGr--kT&Hh$I~hgbV3;E5a!k zJK^$tO>_66P_K^$^Deg|!+A63Q@$Te_*2)h2I}g~dv^=G&dUhD`Th|8q>Ss8`J3)1 zpUwRz|AZplzRcId?OKkXyTkgN#r-Z-_3{0Ipr1;8TCG07|C74kdmt`Z)bn` zZNOFT@wa;%vik$A-9ab*K`vEJ2FLV%|DhR-gV)`@GtCUyj1wyjib?~!$WbEFUWUtC$vPahi!u-dXA9Bn5vL3gLBe6Q-dozBf zk18GM4vqKkB*XO+ve@4d^7WMLTn7@hW%QgX@!o@o6z?w45gsI*fnU0RUc)c&oGz@7 z%gs}$m&;9D&^qPUeJB@7x2A95$KY_aazyHICIab%Xe3WA$CY+Id%D>UHQD@#(I--qezN9i>cx(JZT{cHixzR&P=eAbh9K{y=4??wGRJW zM3tU(J+6Av&-d{D7h>Z1A7T#WlIw;to&66WXkDb!bVzK+QJ zH=*r)J@3b{-*OX%>TF%l^wySXw!dZiC~l60jx*^aN*d{7z0XA-{Wa?eS!Vuv`sg!A z&+DVXF{LlB@6V)vzKb$k|F|Bg86TvUft+b~`-$8y=HFc}2LJtDy~O15O!tdXZ@As- z>&)CAE9La~?*J}&!p4;YHV$ml3i>=TTiKGt-Au&eO+KzVmX)cK!_b>HWp^ zAlBvojU}X=C&dr*Jxlw3T+8SD^d!Q>(*rsO$DS4V>>anU=-&xhjJ`y%fPQ?=(jO8z z8QlMa8vIi^zo>)%3c){B@Wllb43~^eH~hb6_|KDYx$x_X|G+c}hxA|60RKF}e^Cy9 z$?*TK;eWZ|f1l!iqO}J9yaxDRDfs8*@OK&h4;lVT4gUue|5&GlVTac6X;Fi6TBMvs zxpI1}oDW(#ud#AIXyq)na*o%Ov!X#c++P|TTahbgm6fy8%6Ws8GiK$iv~r%QDQ9(q za=wT7!Lil3a{8>Cd##+eSULNwoLjA&V>RV$Xi&~cDQ82joXu9wJFJ|IR?ZVv&L%78 zXiYg=8NKBUaAgnsOd!P|la6oCk8{?6h*;YUMm=<$TP_ zdC1CnvZkC}4a)gnQqHbiIlHZ#>#dv*SUFEwIgeR62WrYW(4ZWyOAU@4uyWMyOU9nG za;}zgLcIa;%-ssp_L&xz3bZiqkj_2q&VRW=K zq=P0=G5U3*b)VC4_d0l=$DO-zZbxA z!R7Q@62^NIHFP}NfR437$Fq{JG7pHvzAQ%HL20nlg7MAi;5tt+db`o_T#k+(7#&+{ z=$HxwAwK8Fn}v?4Qf`Hg=|;z2Hl%|+s~EX{I8Wd!{Fo-;v~_b09TzpAV~NmlQI3w1 z(eZ_bbkOq0_bA2>eTS_=N2}4Xp@t5Q_crp<{IeI-Z05i19r~N1xH53m0K~0*&Z(u1sRx z!uatPqvNlPj$4h66*Y8hXg~-1&7j?zR_QOBjgEIT^3@dVW6ITaAms~{l3xh z0i)wX#*fF0j(Ih79B4qtUZLYaj*cgdj)hWAJvuNo0v#VWI-W2(-0uF6(NU_Q<8T8y z-Yaw*&e3ty=xA?9$N56Xn9=b`qhqJ><5Nb*MKyFBYe2_#q2pMNj%SPx*1EoYa4KGm zc1rr-*yoIndyS6I8y(YY=s4bhjzOX0xY42OLX~%CH0r_UB4i7oiw`4Ufq34!o^4rR@9T1mkAxeXmtF&(J^3jd`rSZGfI-4 zj43@sGukYyd>fkaDhq3S4$YWlVU@F?8M?oS`#7aOLo;+;8~0#Z7>iqQ$(ZVkp&5D( zH5pSqHk7^pv%=tK8vH5?>jD(+SF^CKJB{^On6)JS4HhQ%8QyGRU9iFV9t%@?nLcV^ zm9J#%0SoIs7T$-lFtrfjcUf5Xwea4Rg>`)w?*v$wqY2@kv@l0Gh7Vhqqc6ipE$ni3 z%)+`(iTk-N?DLc37N&K_{3k4|>!U;O*M-5M`*l5INT-=tuNH8~qw0%#azc(4#fsYC=vd>dA;t4BH`CZ|M>Wdecm7(X^Uum@OL^wZ3S9{JBfRe7h(@FUW9OOsG zH@`SKC^J=iI+ndvk!7^&^0=zo~*p zBZcaB%)Gy^v-`kDrX7&>8kwf^Ccm$q=UZ9eh@JcP_jmmJj-*}N+xxfgkEi~fgO#6+ zANz%TIk%RdznlQwe(s9(IF1U2`eG~7_gH?&`2!4Z(J=Q-v8^Tj_iM=K=e~RK8~^a` zvDtfjMx{R8%`+lwGgsly(?k5E;~z@IcUbcA-7exw_8gP2zkliH$p~Kx`&mFQ@l)R8 zpkGoC{|xZ4zpf7Cm;0k9f-v!Zkn+3$z;MjR`qDmmHV5}iiS#OcSv%yuHwpPjzMqM% zMFD=&HU0G!y-B(rB3){pXWy%NzhL^uf#2oPzYp^9Ec>qgd>xMo|LKr_vsqiz$KG@G z^K@tP{X5%<_@038-@j+?_*_Y>pc`X{_^1P2Z0A;(ZxO~%Z&$zfAwEwBIHsSE^l+SM zBD_{3O6@yXKUb60zd^Z)omYqpW(Qr30!R<;1))opiWg1XYyR8RCmqlIImh`niEw($ zcAIEsUyms~SHq;AZ8tpYD|kMLpMHKM*{%AhY`6au%@6w{&*L~>e1Dn!kdAcyG1C29 zPGa*~|4!BQkLxjyXPC~z89#R@WBvY$bU^vzd_APu@ZP4r%UU$wzsGjD^ZOXWdbk}z zsrL7GvhRt_o^!siUQ{{xa(UkZDU9vj-vl-XT|8O)ihpV}90XqEEwq zUu$ao@bV^BXnOJ%{jMfH?`nyd=(2pH>iav-exBrDmm>1^i6{M>=&=?W?{JCrvw>#S zm-81XynnAjyF%)Bp1xzwFq?Ycc{n$P9}F{xpS#SyPwCa~g7WxWZ?`Hi&8@3lHjsM6C%0mt&_{Qea3kB;s0`OXSGiM`{Sy;p1bdW~M!>t)=pMVGf<+iZME z?ESy_b97xKFF)D$Hjh6kVUv~&xZQFw37 zn?bt6&A(dfk=nUZzemi|eI8TqT--Al3L4dq^!&>?)XT@|K^x!8&H8R3<(2hxJ214D zp9OxWkL~)~C#-WCUnl~!BTnYp@p>%S__?ky|NpF$pY`}>bj6GxZ%}?__ukIYu)i0` zGl_Ib{vFuWCa)cup4z*!nI2oI{cqNCRg|f{dop;7!sq43`|reiE&V?AS>N5c`hG#$ z;aRgIwIA?ZNV>t zazV$(WS`oH{+?MpS=T>jZM{JdF4<8Q-|dO3kXgzzeLNTVq`XT6Eb{lH{2ivDbsEp_ zDOj${V|lXO_pwLq>115>rR%vh%l}09;r7O0yW%MqbY3)T>k^4rvg3O3yM~u_2g`Ij^1BJ{d~Mk_C90srt`~*lF`$n zzTfvYY~w<@N#$e*!gTCL^{$zcqKYV`9dlX6tC#LU0{UvfWu81jz(l7Q}812JxoO+j2CAUM8 zah0P+nqPUPG@w?CRb1o=l5CK zFDwtwww!f&G47#}a&$W@<9n)VHhTw${3fKgm+P%^vyKm0d)qkYh8yZzg4@9Ej{lm2XrY<+* z7knf?KSa7*&d1m)I&O>HQaQpAj$29RY?t_a-}g`EX*-4O%yQiBbo#HE`glc`<&VP?(figW&MA)hW#ENUngMx--k-g!;#;Ma5 zb(n|q^?k=Xu~f?;-qSEVGx#|g@ApLUy(7A~=|X8&z9U4H&i94Tgz&e@xD_`oKp$gx zo_;Uiv{U9Zann*A=bGMY_cgvnR=oM%5l>*mO?TM48XbBcf72>^SL1bZ-+j4hwXWY9 zy{zw-ZS5D?QRc7E!*}=E-~7HF>ZJz)zGUkcIk^ho?FqlzE=B`Ycv%#)BGzgOGo#`$k4*V~8X-cnWH4K?W>sY=%lRmy7>U;+;^|9~ZEBn8CpS!<564vY21G?GYIO8owI{Zl6@>7F*}=pRaAZJ}Cd#IhOzA+bj69 z^~*6WpYyLq@eR!=4us^0N?*c=b(T^Yb9bD)&reEt00_)U&ydKY5@o#Wy7i0aCi5AU9} z3pJhb6?f{MFD{HFNIh|`?=y_<3fjxwXK?#D-+vpnPrp*b`Yr^a{#`lu4bkMdr>TU$ zVzMtmn-lTsX_5r-y%KmNjeGY@$RsOGU*K&P+FvJHx;gW3{ z@ADSl&nEtF;6PNyk2wm*d;3fHIc&b$VKMIWA)O4<4Zh6EU8doo1y@qZY^zmRi*zjiU@NgIOnPj6?K zwO6^n9AT%&=NB*LoC(iQypVGy-~I~vdB2cVcb)DJkRHhQim_B^3*Nw>i5IY?AuWR`7S# z{l0I`kMLRW>3vuiMOM(O>zm02odYBrZN2$nBr@IKE8C`F&L@~Jd#~)hI*@rgBo8aS zULN`Sd6ehlBke$%pzPPo$@JrYS{WZFbUCEvy+?mvB3Xb;aLMIbZgROAw4{st&)R!7 zp#bOiw*~gvKxhx10q*ud-d>3P^2zo}yRx2Fm#XcT+YxqpeLj|*TQs?M{m1;j13sM# z{J{Wz1no}e`Q4}d^!&G*WHIQIzyJO7!hP$x`@bfOUW-5V>K~=3OPK#m{q(=pB`=Pw|>TcLU;ER?XYg=bDsLZHL4q#PCWkz*mw$O-H`uz;z|7P zf*-!`PdOw?!rzN{;%C^`W!*k2PX!=cG17YrdGEczZIkG1K0`d)Axre1Fnl8C$nJ9f z4wkR#0s9o%&(jB0j?)Ag;nGC$63^}ic;1fqSXMo;j?<_4xQ^2m@FBJR`E;k^W3MLN z&R^D-C3}Bld0#+W#&?XpbQ3mTWcsf)py%g>9-ZS4jVe9qW~*19pb=`Hul!E~z~4V| zeL=m4CXQ|^yi({d7k*w4PV6_lsF>`t4QiP3@c4NZdEmM_DI@(qgSz;fL7oeaiZNFf1QLQ(}qtrL6B>$tLgJ{85+>K;sSS zyE|9kUeLE?+BZ+n1F8_;H;Ipp3U@C2yN>lYmXOY6CRaRS5%$aJB3Exx{3z#_N<()u zuzvk*LoVNx`#U$^wuSNicWu1Wzjs@Q)*ZV2?q5vpT@Id`A%5NiNI$HH$WK2pXg%t+ zC)@EvjxSfR9#((WeKo{~@|?En_i7x^sgcr6dQO4wtWk9N z&Kmncy?53=9N=gD*rfapChSM#%dwf1Z!iaLAMWWCy9dDZhc-P^Bi~i+0lbfgati#U zhj>o`Z@9je?-yY`3BM!PUVn;ks1Ly!kw3~uy>VqW0Q`KN+avxxPeo6u-B&KW23Q~u zcK@;4E#dmgtr#bZk?ONy)UyQma$%A7`^E1QzL4&}hMZ7eldiCTd<5}vbTeW>FVbIF z|JW_%@cS|1=XYaLf8gt>k~eFoF)1!v-}LXoL_YUZV$`LrcCH|R=ebMYA0zzg$Jmk% zuj{m-eZEWJbse|z-QV%kV3qV^>bYc{jx$NW;t9WtqCAj)n^B=;e3#TSZkjKE$(Yu= zUcbD*s$b4k_yuMkFQj${zS$-5eSOXC&tlXr@qF)03#Iwii!)(8s^*yMRHn-?>gI^~9gjOM`ma`CE=dM^^;#s&=w-g30ATO1w+eXE_%` zk2swSgRPmJ?cuyn{{3daXZA~KaKe4xPsj5obiV)P``hW_lhRMJ{%dxszc&{46B!rw z3L3G4IKH?Z_5BFeqle{;sh*2*IF6)c>n&R~e`@;;&VPT0*5Sf>tU;FSe0G=Sr#(u? zbw=VpSW*V~_fNeRUoOrOxR%-CMMqu_GZo_v$f5iYM!EewezYj-yFwQ1?|jw zu0%eU$ByRbPD{H0j{axuyej!a7Z;8HHjhqkwRI7@7a-%K&C~px!CCYFDlLa};a|Z2 zsnz_aP{8?jPtN}{)svb&YoEQxMPAMXPfhRN%enmeIibq;o!Ssd_I;-+o@6PhL;fN2 z?^B=kI`StRr#Y%3eVfK--$%OK+Ib!J2exZ0TCUPR%3>9;Piw%Bjwn7=SS?NmF#^>x_aPJr+EaVFGDZ$?}A_r*RxNncLt z+5Zgx%dH*!ejB65`Rnu~S6IC!X};T#KYLCWC>;`61p^$5WE`pEpNw4?d>-m=Wn=cu3Gr|+KBB=ii;)^tBd z)y?m=Ntfm8MWL?)$hGiC;SVh%J-Wxh5%XG9<|zCMo;HLk`D@FahSb6t@RK{0{5)5{ zb7n061pFbZ*D%0Xeo;;zR^V&tZ3a{&o%m>45#K5Jj?e4MbmFbWqja%c($foH_yT{F zcsQwrYZ(wPN(URrn|AXklecvW@8cc&2jA^-dGr30yiD=oo<@Ptx!DXkWP_Cl6kw5pm&Hqj?Cgzfn`Up2PHX z#%_ryM*ZUZILvlonQ>D|;**RY_ZUBZPT{S-?5DyP&{M@18@KwG33zmm!JjjK(3j{g zTcm!=YW3HTs-N-aT^c@X{wxCFaB*S78TsS-jq55TB`(a7d={kwF0iwkek z`dzJfz5V@sl+SxA@}Tv|$LIM_F8sChBew(31kavVE~sH1;$c0wk4P8B_aIy@l<>DY zeiY$yp@Y#?@D%76`- zUyYA)&wL+aJ{w;tCndzkg}+lh6XgGLE-uqfX@Vv&PInmdigX z`TwG({C~;i=Saf*AIRk=Kg)%$So`XIq=!&G^$7LMh8rq;VE!+_)?oWH{Y-G@LnM@R zZsu2I(1W9s#eZtjOC}L>+PX^cr7QasujOkQBDD4^sMXVP^M9AH-}}OTN4(cBljtan zrySIaXTkO2S>t-~q_19lDTv<>dPyJc%`zO4#GmNqFW42}6X{<!K;CP3jZ=ayW+Q zPrOFs*S{2qEZx6LVmj;N@sxuWIOe9m*5DamfMY!U%Pf8v`;AoL!O$sm zvfT)Luurl`JCcr#?HA!M+v~8j(_nk6g-5mh7We&-5$mTNl`!Rw?qHw(7{>1s{!du^ z`p!QPxNv@Q3=3kOk96z;JmvZ8Z7Rsx_PA13dp~ ze&$SDr~ZiHu-wf*tY7Y*uv}ykJX~OeW0-h|pY9+hGH|YMD)hWe%2_`$U3{FIswwv( z3>fw5`v)jDr0+91xZgl|9aejVpc zqpL1_J>xFKe}A8ma#cb&UA$V_XJp#ye`8hGO*{M}`k$Su3$7u3N6~Ji=a$xLx;KEY zKL23)jk)ycsF$bveXoZgmpv$_kz6k6J9rw&u#?r_q3n;?3{r3NL;4P*9F~7I%1@q9 zJ(G-U{e0bl%`5rM|5Kn?M)>6S;|-u*5S6O^WAerCsac0g6OY?_ z{(VZaXZ61!Iy$mI2UP!l)b&dqZoWP%2c%lWsW2j_bje4uNiQi1dHYm`TzKV8GN?sOOax`})U>&<@P?{?5?-)J*L{g4Z~x$tS1wQx}hZhasBq8;&{6#BfO;XFsH!7R$RYlw~Q^ndWBBJkZL z!Avf)d%aA~^6h_Q!BJ_SVx)dWPLvP07hd{zcj1WgW3S-{9n>>y2RiSsvCjiyjUPb$ zDMu|gYdAb#BKb8s>L1V_bHNDV4;cct-ul-R@J;x$S>uP{mGGbQC(2p5X!9iFH=#tX zdX>Pq@I~d1@z2|T!sx`kWHsX{^-|nq^P1Vjh<*WdQlAAH_VWs)gYbt8e>m@x`t&IL zi=X#deVTqp>$6nxP61J@udkQkz6Pxil{VZI=%GHmBM|bR{n+guA5TI({}h&xJ>BgV z>i_jGM|^;HD#wp)T24JYAIae%|A>d@5<)yrJ`bKfIXvV9@!SAB$zGG!@l_(vJ`Sgy z8-75_=IgUw*?w$CVZHFr^)tqA(VJ=KVS!J^qkm_9-@ zowOTRzqqN3*=zKN@3Vz+!+N)L2)NvDNO|rro8Ig)y}7EQHwk%g)g_W4E__A&%L{&q)p1 zu}8qF+L3y*Wx2-tx@^`z8?|GT4qQH-dc8t>N%ZjxZAVm-HJ#{Fx|X!xCO`huwBsae zN9$+!u15No?}N{`dp-TUNB889Xgl_6eFso^X-At^g!)waqmAn!zr}8CWS^S8b^G+- z@(w8|o_vk?SvwYu@8e1b$6Xmm_gWb8Rn;GT-jdg^$Oq8OPV@DzCH>uksJ|p$v>#qw z{klTaThMRl8umw|QBKx)eW?RbgCCu6#vw`SLD zgWJR6v;H4Px`2|l>Ud54%qqA&o!8Gtu6~pB_hO{J&%crbrjIB8g5Y<2*V?#Ms~3LR z@cei2Yw?s7Pp8tw@sILVE0_A-K{5J>;sFdZX7ogFQaqa~cqHBUGHcg1N%#F&mP1Qn z$n42v-0aYHM8eHqC*aw7c6Z@T(ht(kUD{u^E1cVZY3Binuk;U{IOXRt+5Bz1lArc? zi}lATC|2x{i_H$X+{UZfW`{s{Nm(|3v;95qC-Xf_A%|2PVM!iDP^&$lkIb{5*f*CqCw{cG#?^RF^K8lO7~vkUW3PF&D)n(4?+p^NK9bRoaa zYJK89&3FA~^*K(k>X{wodc*M7tWR96`C6?0;rd$%N!j=adrJ6@IQnbmX}vhU(Ded8 zV_J4eF#FDgc4-Mw!{)EqZtD|fpVh8U$kK1Nz7-cbgkL_cx}6*HN#_5vwcK@(YtlhE zqVMximyc{7YU_*vXSZJ&HTA1Az@b{9^{eqBZWRiMN5EExw(&THtm zb%sp-uQ2)VF!}#UuV0Mo`bDzW1#E8kLITwa$Iu$ z`#d$Ce38PL{`d0|ZYMqOx`xS5HgC7_la95DXVj{)+Bz`nrbMmrkdT zd)V)hb^5S9sn2j8Tl#f2k8c;W+4@$d2X|{ct0U_YHqO1^bsJQI`m(jvOMQGlI@eyw z0UdV^USjo{@>^Q38;lMxmi0Ug zgp+-0hfNs&-QMtf`*6Rb^otg=+kBqv`zI|6wVb%=RWd%i-uHOw6OP-17dzaur@0mA z>p+oTk-`7(c-8nk)39p8Q{*WqbD(0*b&4ZITVWcBv_ z7?+>uziaT{%HhAt;J4=B|K8w_^F@d zC*WE~1c+E1_25fEyz7$}ecpn?2DkPa^@mY^)+0M_ zVd;Kumg%fdi^a2DtIk^l@m1$7ES~Ff9LK1)$w$)fPTHx5e>I(SY@BzIh8ci6*rPxE z{KPPVCB(1CzC6>hUoY$7>pMTAay7JH z`#9mYF*kHJ$n1juwD~^Hw5^lm?0X;Xo5?u?lv{Pq;1Y!+KT7zC?@0e0sBpfZPtF;9 zwt&t77t%%hKRX|Qd_72S#K$E)e1Ws7)D1p zfMomMq_c$Zu=(6qMG)&idfuVC@I%=j;JHh>eEo>8g!p0e&$Yg>i^$zJ|lTt`4LCg2w}++%CBU<@-J@E{baYR zGWp)C^`Lz#>mj!8m7UjsG?5SfePJ@D`;5N+d8D1U2y?weeV?!A+xN(Ye_(n^eb=*% z@MiOsIf6dwo-`zK%>G9Kk0-rU62f(Kp?|r;hx&o~!_T|3p6q}9zE0@t=pDLFc(4N< z0gn6ktanjv6=He+CiI7RDQ9tWo4`+O5HCB2>2!Lz6T3B?(#L!*k1u$>ZuQ8{+av6b zbRWD%>k&8qn(n)+IV0mTbWv8bp)Yds(x_dIw13gsQGM!VIv;<1f12&9aliDyi_mfV#VU-4@*VL&3_{&s^)KfHOY@A-p{{iCzEfN zPoKBUTJ$@T&-GW!eG1QU8EWA)?F0f0zFzM&h$lTK>jb_Y;rFupe0Zo`^ZPnP+d{)< z^1oy|1Raie1wW7zKl=yeo%Rgx(@Mr|o@094?ad=wKTmM9`=`YB{^I?~zma7vzF_D zLI1vn;}RvMU%@c{eNNgh*{9`B+^h-nao~~8=cV0~cIrNJk3`F@`Q%?ZvO&s^d z2kp%ATP7=f&G<=Q7tucSS9TNobc^8J+cqZ)txKqa00nF9L62VTMV4ozROES4Yrww}Kq6<~kMpZDk| zbKv|tx#!!r%J!?s5IEn5&CZo<*LdzPmGE=eeA=a?Z_Rc)7h?SOedu1`V|qO0SLj9Q zN}a!we`M{%GR9Ibm>lib_DuGvTsD@6H>*6@_~7yw7rO*sjU3z}(N*U_<$TvFjVHfF z4)B*T{VoTS&0d;(i2$Y#^{Ko~`k;hs+I_b~i(H95*l%I*p{m`j{jT3oNtgCUu&Ukf z*YqXJ9+Ds4uKU4%Y4==v^d}16a;f?gws1=Rln^y+zU#F$k4UqKo@0)z-EU(E?PK;- z!*;*1e!Is-J=f*^H`%9p$M3)PbHv{M-OX2Pd)oN=LfTW#b-mE`Y`#w3=RdSbUk zOMA*V@{Wcza&)Rzduqu05^4x?Pc-Q@=v_)II4hbiZY}hAZv(vl5X!uH&hA%&GoOh+cMQJ|LNMz+UMZhc425S z`i}U$P{Nc;x5M*#IG*}tfpfi`98mptE%H%M)%NTAMSm8f`^0~K{Kpi(t!p}d-+!sd z*(VI|$IlY)k-BsfFYCKx?iVH9*YACtWI9`TXuBk1KE6%md7p+kPEe1#yv37dDjw?> zTxWtxj!Zzir^8?HvKfHd8=e3tf{fg0iw_sVE@wDS9hklQ=*Prt@;s3ozg!B1U$cIk~A9hQ9{2YqsOU8FfJjZk5 zf7*P?t%S}0;_O!n{%pRsXP4w#vWU`+{$cj0_a{Fen(<+qfJH~P>Ukyq-kbX=r8jAt z5`y!eh4}CDK%bv38C)X>{5x2mpZj~vy~c-fVV25`wU^_Wzg6$+y<;7a!}&Xj>BADN zd}lsG!&yCT9ntX|*{b7?pTqL=4CMDbWMzHw-(_EfBDucZXdm`KZl7=!*g^P4`>;oI z@Z6Rqe4~BX<2iUfYfSh?`>>c0p3Uc3-l80y zSxn!e{tODBM`llzh`3p{*Mjf)3({e;edD_|AN4dd zHr_XuVJte>Rh0ZsO`X=np5)_HxUY%m(voX`O5iqL3grVAPtkd@*J~K5EN|j2Nsg|c zqrQJ1z;q(07f)4NFP=577f(9t#g~Hk{Xok36YqDZ`kvqHR?d@1@7fOhfor>2ecmrs z^*#U98o$=&NyEU)daO10Y+c;y%XIvUJf3{4+Fv$&jIY{Xws`Vs5%T-FBFbG4!hTOl z+Z71F-SL=yH|Xc|Ij`f0H(~X=^ELsCd_H#1dJU&54~u-I_Acz2W#b}W89ovZcjw#G z_xW3v-}0sQ?$(;-$0UEcaD}=xM9MCwq4bzi|#re9HIh0GEvIlrZj-*7UJm;*)<&Pg@shyuCY2`D1*t z|4E5YM@r(i%ta*J4%jbrJnu|6wk!TccUrrqt*Zr|?TG5({@M*12LB0{j;xSy`k3

~zceLv(A<$%R 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 ECu7rtGynhq diff --git a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs index dbf3e8515..c54a4a594 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs @@ -1,3 +1,12 @@ +use std::{ + thread::sleep, + time::{Duration, Instant}, +}; + +use dlp_api::{ + pda::undelegation_request_pda_from_delegated_account, + state::UndelegationRequest, +}; use integration_test_tools::{ conversions::stringify_simulation_result, run_test, scheduled_commits::extract_scheduled_commit_sent_signature_from_logs, @@ -5,14 +14,15 @@ use integration_test_tools::{ }; use program_schedulecommit::{ api::{ - increase_count_instruction, + increase_count_instruction, request_undelegation_cpi_instruction, schedule_commit_and_undelegate_cpi_instruction, schedule_commit_and_undelegate_cpi_twice, schedule_commit_and_undelegate_cpi_with_mod_after_instruction, schedule_commit_instruction_for_order_book, set_count_instruction, update_order_book_instruction, UserSeeds, }, - BookUpdate, OrderLevel, ScheduleCommitType, FAIL_UNDELEGATION_COUNT, + BookUpdate, MainAccount, OrderLevel, ScheduleCommitType, + FAIL_UNDELEGATION_COUNT, }; use rand::{RngCore, SeedableRng}; use schedulecommit_client::{ @@ -49,6 +59,9 @@ use crate::utils::{ mod utils; +const REQUESTED_UNDELEGATION_MAX_WAIT: Duration = Duration::from_secs(30); +const REQUESTED_UNDELEGATION_RETRY_DELAY: Duration = Duration::from_millis(250); + fn commit_and_undelegate_one_account( modify_after: bool, ) -> ( @@ -285,6 +298,81 @@ fn commit_and_undelegate_two_accounts_twice() -> ( (ctx, *sig, tx_res) } +fn assert_undelegation_request( + request_data: &[u8], + delegated_account: Pubkey, + rent_payer: Pubkey, +) { + let request = + UndelegationRequest::try_from_bytes_with_discriminator(request_data) + .unwrap(); + assert_eq!( + request.delegated_account.to_bytes(), + delegated_account.to_bytes(), + "request should target delegated account" + ); + assert_eq!( + request.owner_program.to_bytes(), + program_schedulecommit::id().to_bytes(), + "request should target schedulecommit owner program" + ); + assert_eq!( + request.rent_payer.to_bytes(), + rent_payer.to_bytes(), + "request rent payer should match chain payer" + ); + assert!( + request.expires_at_slot > request.created_slot, + "request should use a future timeout slot" + ); +} + +fn wait_for_requested_undelegation_on_chain( + ctx: &ScheduleCommitTestContext, + pda: Pubkey, + request_pda: Pubkey, + expected_count: u64, +) { + let start = Instant::now(); + let mut last_state = String::new(); + + while start.elapsed() < REQUESTED_UNDELEGATION_MAX_WAIT { + let owner_result = ctx.fetch_chain_account_owner(pda); + let owner_restored = matches!( + &owner_result, + Ok(owner) if *owner == program_schedulecommit::id() + ); + let owner_state = owner_result + .map(|owner| owner.to_string()) + .unwrap_or_else(|err| format!("error: {err:?}")); + + let request_exists = ctx.fetch_chain_account(request_pda).is_ok(); + let count_result = ctx + .fetch_chain_account_data(pda) + .map_err(|err| err.to_string()) + .and_then(|data| { + MainAccount::try_decode(&data) + .map(|account| account.count) + .map_err(|err| err.to_string()) + }); + let count_matches = + matches!(&count_result, Ok(count) if *count == expected_count); + + if owner_restored && !request_exists && count_matches { + return; + } + + last_state = format!( + "owner={owner_state}, request_exists={request_exists}, count={count_result:?}" + ); + sleep(REQUESTED_UNDELEGATION_RETRY_DELAY); + } + + panic!( + "timed out waiting for requested undelegation of {pda}; last state: {last_state}" + ); +} + #[test] fn test_committing_and_undelegating_one_account() { run_test!({ @@ -300,6 +388,85 @@ fn test_committing_and_undelegating_one_account() { }); } +#[test] +fn test_request_undelegation_commits_and_undelegates_one_account() { + run_test!({ + let ctx = get_context_with_delegated_committees( + 1, + UserSeeds::MagicScheduleCommit, + ); + let ScheduleCommitTestContextFields { + payer_ephem, + payer_chain, + committees, + commitment, + ephem_client, + .. + } = ctx.fields(); + let (player, committee_pda) = &committees[0]; + let request_pda = + undelegation_request_pda_from_delegated_account(committee_pda); + + assert!( + ctx.fetch_chain_account(request_pda).is_err(), + "request PDA should not exist before request" + ); + + assert_can_increase_committee_count( + *committee_pda, + payer_ephem, + ephem_client, + commitment, + ); + + let ix = request_undelegation_cpi_instruction( + payer_chain.pubkey(), + player.pubkey(), + *committee_pda, + ); + let request_tx = Transaction::new_signed_with_payer( + &[ix], + Some(&payer_chain.pubkey()), + &[payer_chain], + ctx.try_chain_blockhash().unwrap(), + ); + let request_sig = *request_tx.get_signature(); + let request_res = ctx + .try_chain_client() + .unwrap() + .send_and_confirm_transaction_with_spinner_and_config( + &request_tx, + *commitment, + RpcSendTransactionConfig { + skip_preflight: true, + ..Default::default() + }, + ); + ctx.dump_chain_logs(request_sig); + assert!( + request_res.is_ok(), + "request undelegation transaction failed: {request_res:?}" + ); + + if let Ok(request_data) = ctx.fetch_chain_account_data(request_pda) { + assert_undelegation_request( + &request_data, + *committee_pda, + payer_chain.pubkey(), + ); + } else { + debug!("Undelegation request was already consumed"); + } + + wait_for_requested_undelegation_on_chain( + &ctx, + *committee_pda, + request_pda, + 1, + ); + }); +} + #[test] fn test_commit_huge_order_book_account() { run_test_for_commit_huge_order_book_account(ScheduleCommitType::Commit); diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index 8fff08e53..8e0d2e301 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -316,6 +316,8 @@ impl IxtestContext { let finalize_ix = dlp_api::instruction_builder::finalize( self.validator_kp.pubkey(), counter_pda, + program_flexi_counter::id(), + counter_auth.pubkey(), ); let undelegate_ix = dlp_api::instruction_builder::undelegate( self.validator_kp.pubkey(), diff --git a/test-integration/test-committor-service/tests/common.rs b/test-integration/test-committor-service/tests/common.rs index 66f896211..2b8add52f 100644 --- a/test-integration/test-committor-service/tests/common.rs +++ b/test-integration/test-committor-service/tests/common.rs @@ -7,6 +7,9 @@ use std::{ }; use async_trait::async_trait; +use dlp_api::state::{ + DelegationMetadata, UndelegationRequest, UndelegationRequester, +}; use magicblock_committor_service::{ intent_executor::{ task_info_fetcher::{ @@ -192,6 +195,35 @@ impl TaskInfoFetcher for MockTaskInfoFetcher { Ok(pubkeys.to_vec()) } + async fn fetch_delegation_metadata( + &self, + pubkeys: &[Pubkey], + _: u64, + ) -> TaskInfoFetcherResult> { + Ok(pubkeys + .iter() + .map(|pubkey| { + ( + *pubkey, + DelegationMetadata { + last_commit_id: 0, + undelegation_requester: UndelegationRequester::None, + seeds: vec![], + rent_payer: *pubkey, + }, + ) + }) + .collect()) + } + + async fn fetch_undelegation_requests( + &self, + _delegated_accounts: &[Pubkey], + _: u64, + ) -> TaskInfoFetcherResult> { + Ok(HashMap::new()) + } + async fn get_base_accounts( &self, pubkeys: &[Pubkey], diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index 72ae07121..f28eaf88c 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -24,7 +24,7 @@ use solana_sdk::{ use test_kit::init_logger; use tokio::task::JoinSet; use tracing::*; -use utils::transactions::{print_tx_logs, tx_logs_contain}; +use utils::transactions::print_tx_logs; use self::utils::transactions::init_and_delegate_order_book_on_chain; use crate::utils::{ @@ -189,7 +189,7 @@ async fn test_ix_commit_order_book_change_100_bytes() { async fn test_ix_commit_order_book_change_671_bytes() { commit_book_order_account( 671, - CommitStrategy::DiffArgs, + CommitStrategy::DiffBuffer, CommitIntentKind::Commit, ) .await; @@ -564,9 +564,9 @@ async fn test_commit_20_accounts_1kb_bundle_size_6() { } #[tokio::test] -async fn test_commit_20_accounts_1kb_bundle_size_20() { +async fn test_commit_20_accounts_1kb_bundle_size_5() { commit_20_accounts_1kb( - 20, + 5, expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 20)]), CommitIntentKind::Commit, ) @@ -694,7 +694,7 @@ async fn test_ix_execute_intent_bundle_commit_and_commit_finalize_mixed() { &[1024, 2048], &[1024, 2048], &[], - expect_strategies(&[(CommitStrategy::DiffArgs, 4)]), + expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 4)]), ) .await; } @@ -1014,39 +1014,7 @@ async fn ix_commit_local( let commit_finalized_and_undelegated_accounts = base_intent.get_commit_finalize_and_undelegate_intent_accounts(); - let has_commit_flow = - committed_accounts.is_some() || undelegated_accounts.is_some(); - let has_commit_finalize_flow = committed_finalize_accounts.is_some() - || commit_finalized_and_undelegated_accounts.is_some(); - if has_commit_flow { - assert!( - tx_logs_contain(&rpc_client, &commit_signature, "CommitState") - .await - ); - assert!( - tx_logs_contain(&rpc_client, &finalize_signature, "Finalize") - .await - ); - } - if has_commit_finalize_flow { - assert!( - tx_logs_contain( - &rpc_client, - &commit_signature, - "CommitFinalize" - ) - .await - ); - } - let has_undelegate = base_intent.has_undelegate_intent(); - if has_undelegate { - // Undelegate is part of atomic Finalization Stage - assert!( - tx_logs_contain(&rpc_client, &finalize_signature, "Undelegate") - .await - ); - } let mut committed_accounts: HashMap = [ (false, committed_accounts), diff --git a/test-integration/test-committor-service/tests/test_transaction_preparator.rs b/test-integration/test-committor-service/tests/test_transaction_preparator.rs index 207f3fc48..63da47352 100644 --- a/test-integration/test-committor-service/tests/test_transaction_preparator.rs +++ b/test-integration/test-committor-service/tests/test_transaction_preparator.rs @@ -45,6 +45,8 @@ async fn test_prepare_commit_tx_with_single_account() { .into(), FinalizeTask { delegated_account: committed_account.pubkey, + owner_program: committed_account.account.owner, + rent_reimbursement: Pubkey::new_unique(), } .into(), ]; @@ -111,11 +113,15 @@ async fn test_prepare_commit_tx_with_multiple_accounts() { // finalize account 1 FinalizeTask { delegated_account: committed_account1.pubkey, + owner_program: committed_account1.account.owner, + rent_reimbursement: Pubkey::new_unique(), } .into(), // finalize account 2 FinalizeTask { delegated_account: committed_account2.pubkey, + owner_program: committed_account2.account.owner, + rent_reimbursement: Pubkey::new_unique(), } .into(), ]; @@ -204,6 +210,8 @@ async fn test_prepare_commit_tx_with_base_actions() { // finalize account FinalizeTask { delegated_account: committed_account.pubkey, + owner_program: committed_account.account.owner, + rent_reimbursement: Pubkey::new_unique(), } .into(), // BaseAction @@ -280,6 +288,8 @@ async fn test_prepare_finalize_tx_with_undelegate_with_atls() { // finalize account FinalizeTask { delegated_account: committed_account.pubkey, + owner_program: committed_account.account.owner, + rent_reimbursement: Pubkey::new_unique(), } .into(), // Undelegate @@ -287,6 +297,7 @@ async fn test_prepare_finalize_tx_with_undelegate_with_atls() { delegated_account: committed_account.pubkey, owner_program: Pubkey::new_unique(), rent_reimbursement: Pubkey::new_unique(), + request_rent_payer: None, } .into(), ]; diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index 5e01d0005..073caefca 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -74,6 +74,14 @@ pub async fn fetch_tx_logs( rpc_client: &RpcClient, signature: &Signature, ) -> Vec { + try_fetch_tx_logs(rpc_client, signature).await.unwrap() +} + +#[allow(dead_code)] +pub async fn try_fetch_tx_logs( + rpc_client: &RpcClient, + signature: &Signature, +) -> Result, String> { // NOTE: we encountered the following error a few times which makes tests fail for the // wrong reason: // Error { @@ -103,10 +111,10 @@ pub async fn fetch_tx_logs( tracing::error!("Failed to get transaction: {}", err); retries -= 1; if retries == 0 { - panic!( + return Err(format!( "Failed to get transaction after {} retries", MAX_RETRIES - ); + )); } tokio::time::sleep(tokio::time::Duration::from_millis(100)) .await; @@ -116,15 +124,18 @@ pub async fn fetch_tx_logs( tx.transaction .meta .as_ref() - .unwrap() + .ok_or_else(|| "Transaction metadata is missing".to_string())? .log_messages .clone() - .unwrap_or_else(Vec::new) + .ok_or_else(|| "Transaction log messages are missing".to_string()) } #[allow(dead_code)] pub async fn print_tx_logs(rpc_client: &RpcClient, signature: &Signature) { - println!("logs: {:#?}", fetch_tx_logs(rpc_client, signature).await); + match try_fetch_tx_logs(rpc_client, signature).await { + Ok(logs) => println!("logs: {logs:#?}"), + Err(err) => println!("Unable to fetch logs for {signature}: {err}"), + } } async fn airdrop_and_confirm( From 0a13b0765458945de5c8f7d9c468de7bbfe19b6e Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Tue, 7 Jul 2026 04:06:45 +0530 Subject: [PATCH 2/8] use standalone DLP undelegate --- .agents/context/crates/magicblock-accounts.md | 2 +- .../crates/magicblock-committor-service.md | 4 +- .agents/specs/validator-specification.md | 27 +-- Cargo.lock | 12 +- Cargo.toml | 2 +- .../intent_executor/single_stage_executor.rs | 61 +----- .../src/intent_executor/two_stage_executor.rs | 63 +----- .../src/tasks/commit_finalize_task.rs | 5 - magicblock-committor-service/src/tasks/mod.rs | 6 - .../src/tasks/task_builder.rs | 196 +++++++++++------- .../src/tasks/task_strategist.rs | 155 ++++++++++++-- .../src/transactions.rs | 11 +- test-integration/Cargo.lock | 40 ++-- test-integration/Cargo.toml | 2 +- test-integration/schedulecommit/elfs/dlp.so | Bin 473048 -> 468552 bytes .../tests/test_transaction_preparator.rs | 10 - 16 files changed, 321 insertions(+), 275 deletions(-) diff --git a/.agents/context/crates/magicblock-accounts.md b/.agents/context/crates/magicblock-accounts.md index b2bf14c03..bf322c520 100644 --- a/.agents/context/crates/magicblock-accounts.md +++ b/.agents/context/crates/magicblock-accounts.md @@ -233,7 +233,7 @@ The code uses `expect(POISONED_MUTEX_MSG)` in the normal processing paths. One r ### Owner-program undelegation requests -`magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. The committor then relies on DLP finalize/commit-finalize auto-undelegation accounts derived from `DelegationMetadata`; it does not need a separate request-PDA fetch to find the request rent payer. +`magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. Current DLP finalize instructions do not undelegate; the committor finalizes state and then sends standalone DLP `Undelegate`. When `DelegationMetadata.undelegation_requester = OwnerProgram`, the committor fetches the matching request PDA and passes the request rent payer to `Undelegate` so DLP can close the request account. ### Undelegation notifications are best-effort diff --git a/.agents/context/crates/magicblock-committor-service.md b/.agents/context/crates/magicblock-committor-service.md index 9ba6b918a..4daed77d9 100644 --- a/.agents/context/crates/magicblock-committor-service.md +++ b/.agents/context/crates/magicblock-committor-service.md @@ -203,7 +203,7 @@ IntentExecutorImpl::execute -> reset nonce cache for all committed pubkeys on errors, or only undelegated pubkeys on successful undelegation ``` -Task building fetches `DelegationMetadata` for accounts whose base-layer flow may finalize. `FinalizeTask` and `CommitFinalizeTask` include the delegated account owner and `DelegationMetadata.rent_payer` so the Delegation Program can auto-undelegate owner-program requests during finalize, commit-finalize, and commit-finalize-from-buffer. The active task-building path derives the request PDA through the DLP instruction builders and does not fetch or decode `UndelegationRequest`; explicit undelegate tasks still pass `request_rent_payer = None` unless a future path deliberately restores request-account decoding. +Current DLP finalize instructions do not undelegate and require only the validator plus delegated account, so `FinalizeTask` and `CommitFinalizeTask` no longer fetch or carry owner/rent metadata. Finalize-stage `UndelegateTask`s complete ownership return through standalone DLP `Undelegate`. For owner-program requests, task building detects `DelegationMetadata.undelegation_requester = OwnerProgram`, fetches the matching `UndelegationRequest` with the same `min_context_slot`, validates the request owner against the committed account owner, and passes `request.rent_payer` so DLP can close the request PDA. For validator-requested undelegation, or metadata still showing `None` because commit and finalize task lists are built before the commit-stage transaction records the validator requester on base, `request_rent_payer` remains `None`. Transaction fit is not only packet size. `TaskStrategist` currently checks whether a single-stage transaction or each two-stage transaction fits the wire size, optionally after switching commits to buffers and adding ALTs, but it does not split a transaction stage by compute units. Each commit, finalize, commit-finalize, and undelegate task currently advertises `120_000` CU, while Agave caps a transaction at `1_400_000` CU. Keep task bundles below that transaction-level cap unless the strategist and executor/output/persistence model are extended to split, record, and confirm multiple transactions for the affected stage. @@ -233,7 +233,7 @@ Do not remove sorted lock acquisition or the retiring map without replacing the ### `min_context_slot` and freshness -Task-info RPC reads use the maximum `remote_slot` across committed accounts as `min_context_slot` when fetching delegation metadata and diffable base accounts. This helps avoid building commits against base-layer state older than the ER account snapshot, including stale rent-payer or owner-program undelegation-requester metadata used by auto-undelegation account metas. The fetcher retries `Minimum context slot not reached` up to five times with short sleeps. Preserve this freshness check unless the broader account-sync/settlement contract changes. +Task-info RPC reads use the maximum `remote_slot` across committed accounts as `min_context_slot` when fetching delegation metadata, undelegation requests, and diffable base accounts. This helps avoid building commits or standalone undelegate tasks against base-layer state older than the ER account snapshot, including stale rent-payer or owner-program requester metadata. The fetcher retries `Minimum context slot not reached` up to five times with short sleeps. Preserve this freshness check unless the broader account-sync/settlement contract changes. ### Persistence is both status API and recovery state diff --git a/.agents/specs/validator-specification.md b/.agents/specs/validator-specification.md index 1fd61517e..9570042d9 100644 --- a/.agents/specs/validator-specification.md +++ b/.agents/specs/validator-specification.md @@ -260,19 +260,20 @@ This is a critical lifecycle invariant. Do not allow normal ER transactions to k Owner-program requested undelegation is recorded by the Delegation Program in `DelegationMetadata.undelegation_requester = OwnerProgram` and an `UndelegationRequest` PDA. This marker is not a validator-side completion -signal: the validator must still commit/finalize the latest ER state. For -commit/finalize, commit-finalize, and commit-finalize-from-buffer paths, the -committor supplies the DLP auto-undelegation accounts using the delegated -account's owner program and `DelegationMetadata.rent_payer`; it derives the -request PDA for those instruction metas and does not need to fetch or decode -`UndelegationRequest` during task construction. - -If DLP sees `OwnerProgram` requester during a successful finalize path, it -finalizes the committed state and undelegates/closes the delegation/request PDAs -in the same instruction flow. An explicit undelegate instruction later in the -same transaction may no-op once ownership has already returned to the owner -program. `AlreadyUndelegated` remains a conflict for validator-requested -undelegation state, not a reason to drop an owner-program request. +signal: the validator must still schedule commit-and-undelegate so the latest +ER state is committed/finalized before ownership returns to the owner program. + +The current Delegation Program does not undelegate from finalize instructions. +Commit/finalize-style instructions only commit/finalize state and record or +preserve `DelegationMetadata.undelegation_requester`. The validator-side +committor completes undelegation by sending a standalone DLP `Undelegate` +instruction in the finalize stage. When metadata says the requester is +`OwnerProgram`, the committor must also pass the undelegation request PDA and +the request account's rent payer to `Undelegate`; when metadata says +`Validator` or is still `None` at task-build time, no request accounts are +passed. `None` can be valid for validator-requested undelegation because commit +and finalize task lists are built before the commit-stage transaction records +the validator requester on base. ### Callback discriminator diff --git a/Cargo.lock b/Cargo.lock index d839bb02a..55ffae875 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1970,7 +1970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -3856,7 +3856,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "3.0.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7#72af1c7542ee00a383f0945184fee4a0d9cec6e0" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40#212d3445ed6384caf3661fbc34e35df4ba9fcd40" dependencies = [ "bincode", "borsh 0.10.4", @@ -5289,7 +5289,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -5765,7 +5765,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -9668,7 +9668,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix 1.1.4", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -10626,7 +10626,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index ce5ff6a14..951d80cf3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "72af1c7" } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "212d3445ed6384caf3661fbc34e35df4ba9fcd40" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/magicblock-committor-service/src/intent_executor/single_stage_executor.rs b/magicblock-committor-service/src/intent_executor/single_stage_executor.rs index d153b0633..3b9dddfce 100644 --- a/magicblock-committor-service/src/intent_executor/single_stage_executor.rs +++ b/magicblock-committor-service/src/intent_executor/single_stage_executor.rs @@ -22,10 +22,7 @@ use crate::{ IntentExecutionReport, }, persist::{IntentPersister, IntentPersisterImpl}, - tasks::{ - task_builder::TaskBuilderError, task_strategist::TransactionStrategy, - BaseTaskImpl, FinalizeTask, - }, + tasks::{task_strategist::TransactionStrategy, BaseTaskImpl, FinalizeTask}, transaction_preparator::TransactionPreparator, }; @@ -218,36 +215,22 @@ where ) => { let optimized_tasks = self.transaction_strategy.optimized_tasks.as_slice(); - if let Some(( - delegated_account, - owner_program, - min_context_slot, - rent_reimbursement, - )) = err + if let Some(delegated_account) = err .task_index() .and_then(|index| optimized_tasks.get(index as usize)) .and_then(|task| match task { - BaseTaskImpl::Commit(task) => Some(( - task.committed_account.pubkey, - task.committed_account.account.owner, - task.committed_account.remote_slot, - None, - )), - BaseTaskImpl::CommitFinalize(task) => Some(( - task.committed_account.pubkey, - task.committed_account.account.owner, - task.committed_account.remote_slot, - Some(task.rent_reimbursement), - )), + BaseTaskImpl::Commit(task) => { + Some(task.committed_account.pubkey) + } + BaseTaskImpl::CommitFinalize(task) => { + Some(task.committed_account.pubkey) + } _ => None, }) { self.handle_unfinalized_account_error( signature, delegated_account, - owner_program, - min_context_slot, - rent_reimbursement, transaction_preparator, ) .await @@ -290,34 +273,10 @@ where &self, failed_signature: &Option, delegated_account: Pubkey, - owner_program: Pubkey, - min_context_slot: u64, - rent_reimbursement: Option, transaction_preparator: &T, ) -> IntentExecutorResult> { - let rent_reimbursement = - if let Some(rent_reimbursement) = rent_reimbursement { - rent_reimbursement - } else { - self.task_info_fetcher - .fetch_delegation_metadata( - &[delegated_account], - min_context_slot, - ) - .await - .map_err(TaskBuilderError::FinalizedTasksBuildError)? - .get(&delegated_account) - .map(|metadata| metadata.rent_payer) - .ok_or(TaskBuilderError::MissingDelegationMetadata( - delegated_account, - ))? - }; - let finalize_task: BaseTaskImpl = FinalizeTask { - delegated_account, - owner_program, - rent_reimbursement, - } - .into(); + let finalize_task: BaseTaskImpl = + FinalizeTask { delegated_account }.into(); prepare_and_execute_strategy( &self.intent_client, &self.authority, diff --git a/magicblock-committor-service/src/intent_executor/two_stage_executor.rs b/magicblock-committor-service/src/intent_executor/two_stage_executor.rs index 313065f9f..196ae72be 100644 --- a/magicblock-committor-service/src/intent_executor/two_stage_executor.rs +++ b/magicblock-committor-service/src/intent_executor/two_stage_executor.rs @@ -23,10 +23,7 @@ use crate::{ IntentExecutionReport, }, persist::{IntentPersister, IntentPersisterImpl}, - tasks::{ - task_builder::TaskBuilderError, task_strategist::TransactionStrategy, - BaseTaskImpl, FinalizeTask, - }, + tasks::{task_strategist::TransactionStrategy, BaseTaskImpl, FinalizeTask}, transaction_preparator::TransactionPreparator, }; @@ -207,55 +204,21 @@ where let optimized_tasks = self.state.commit_strategy.optimized_tasks.as_slice(); let task_index = err.task_index(); - if let Some(( - delegated_account, - owner_program, - min_context_slot, - rent_reimbursement, - )) = task_index + if let Some(delegated_account) = task_index .and_then(|index| optimized_tasks.get(index as usize)) .and_then(|task| match task { - BaseTaskImpl::Commit(task) => Some(( - task.committed_account.pubkey, - task.committed_account.account.owner, - task.committed_account.remote_slot, - None, - )), - BaseTaskImpl::CommitFinalize(task) => Some(( - task.committed_account.pubkey, - task.committed_account.account.owner, - task.committed_account.remote_slot, - Some(task.rent_reimbursement), - )), + BaseTaskImpl::Commit(task) => { + Some(task.committed_account.pubkey) + } + BaseTaskImpl::CommitFinalize(task) => { + Some(task.committed_account.pubkey) + } _ => None, }) { - let rent_reimbursement = - if let Some(rent_reimbursement) = rent_reimbursement { - rent_reimbursement - } else { - task_info_fetcher - .fetch_delegation_metadata( - &[delegated_account], - min_context_slot, - ) - .await - .map_err( - TaskBuilderError::FinalizedTasksBuildError, - )? - .get(&delegated_account) - .map(|metadata| metadata.rent_payer) - .ok_or( - TaskBuilderError::MissingDelegationMetadata( - delegated_account, - ), - )? - }; self.handle_unfinalized_account_error( signature, delegated_account, - owner_program, - rent_reimbursement, transaction_preparator, ) .await @@ -311,16 +274,10 @@ where &self, failed_signature: &Option, delegated_account: Pubkey, - owner_program: Pubkey, - rent_reimbursement: Pubkey, transaction_preparator: &T, ) -> IntentExecutorResult> { - let finalize_task: BaseTaskImpl = FinalizeTask { - delegated_account, - owner_program, - rent_reimbursement, - } - .into(); + let finalize_task: BaseTaskImpl = + FinalizeTask { delegated_account }.into(); prepare_and_execute_strategy( &self.intent_client, &self.authority, diff --git a/magicblock-committor-service/src/tasks/commit_finalize_task.rs b/magicblock-committor-service/src/tasks/commit_finalize_task.rs index 33d6abe5c..33f48c0f6 100644 --- a/magicblock-committor-service/src/tasks/commit_finalize_task.rs +++ b/magicblock-committor-service/src/tasks/commit_finalize_task.rs @@ -31,7 +31,6 @@ pub struct CommitFinalizeTask { pub allow_undelegation: bool, pub committed_account: CommittedAccount, pub delivery: CommitDelivery, - pub rent_reimbursement: Pubkey, } impl CommitFinalizeTask { @@ -66,8 +65,6 @@ impl CommitFinalizeTask { dlp_api::instruction_builder::commit_finalize( *validator, self.committed_account.pubkey, - self.committed_account.account.owner, - self.rent_reimbursement, &mut args, &data, ) @@ -100,8 +97,6 @@ impl CommitFinalizeTask { *validator, self.committed_account.pubkey, data_buffer_pubkey, - self.committed_account.account.owner, - self.rent_reimbursement, &mut args, ) .0 diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index fefc73c92..714dc0dbc 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -216,8 +216,6 @@ impl From for BaseTaskImpl { #[derive(Clone, Debug)] pub struct FinalizeTask { pub delegated_account: Pubkey, - pub owner_program: Pubkey, - pub rent_reimbursement: Pubkey, } impl FinalizeTask { @@ -225,8 +223,6 @@ impl FinalizeTask { dlp_api::instruction_builder::finalize( *validator, self.delegated_account, - self.owner_program, - self.rent_reimbursement, ) } } @@ -628,8 +624,6 @@ mod serialization_safety_test { // Test Finalize variant let finalize_task: BaseTaskImpl = FinalizeTask { delegated_account: Pubkey::new_unique(), - owner_program: Pubkey::new_unique(), - rent_reimbursement: Pubkey::new_unique(), } .into(); assert_serializable(&finalize_task.instruction(&validator)); diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 2989f0f6e..3f6b9c7ed 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -1,7 +1,9 @@ use std::{collections::HashMap, sync::Arc}; use async_trait::async_trait; -use dlp_api::state::DelegationMetadata; +use dlp_api::state::{ + DelegationMetadata, UndelegationRequest, UndelegationRequester, +}; use magicblock_core::intent::CommittedAccount; use magicblock_program::magic_scheduled_base_intent::{ BaseAction, CommitAndUndelegate, CommitType, ScheduledIntentBundle, @@ -46,8 +48,6 @@ pub struct CommitStageTaskInfo { commit_nonces: HashMap, /// Base account state for diff calculation base_accounts: HashMap, - /// Delegation metadata needed by commit-finalize account metas. - delegation_metadata: HashMap, } /// Task builder @@ -149,28 +149,20 @@ impl TaskBuilderImpl { .await } - fn get_commit_finalize_pubkeys( - intent_bundle: &ScheduledIntentBundle, - ) -> Vec { - [ - intent_bundle - .intent_bundle - .get_commit_finalize_intent_pubkeys(), - intent_bundle - .intent_bundle - .get_commit_finalize_and_undelegate_intent_pubkeys(), - ] - .into_iter() - .flatten() - .flatten() - .collect() + async fn fetch_undelegation_requests( + task_info_fetcher: &Arc, + pubkeys: &[Pubkey], + min_context_slot: u64, + ) -> TaskInfoFetcherResult> { + task_info_fetcher + .fetch_undelegation_requests(pubkeys, min_context_slot) + .await } fn get_finalize_stage_metadata_pubkeys( intent_bundle: &ScheduledIntentBundle, ) -> Vec { [ - intent_bundle.get_commit_intent_pubkeys(), intent_bundle.get_undelegate_intent_pubkeys(), intent_bundle .intent_bundle @@ -195,9 +187,7 @@ impl TaskBuilderImpl { .map(|account| account.remote_slot) .max() .unwrap_or(0); - let commit_finalize_pubkeys = - Self::get_commit_finalize_pubkeys(intent_bundle); - let (commit_ids, base_accounts, delegation_metadata) = tokio::join!( + let (commit_ids, base_accounts) = tokio::join!( Self::fetch_commit_nonces( task_info_fetcher, &all_committed_accounts, @@ -207,17 +197,10 @@ impl TaskBuilderImpl { task_info_fetcher, &all_committed_accounts, min_context_slot - ), - Self::fetch_delegation_metadata( - task_info_fetcher, - &commit_finalize_pubkeys, - min_context_slot ) ); let commit_nonces = commit_ids.map_err(TaskBuilderError::CommitTasksBuildError)?; - let delegation_metadata = delegation_metadata - .map_err(TaskBuilderError::CommitTasksBuildError)?; let base_accounts = base_accounts.unwrap_or_else(|err| { tracing::warn!(intent_id = intent_bundle.id, error = ?err, "Failed to fetch base accounts, falling back to CommitState"); Default::default() @@ -235,7 +218,6 @@ impl TaskBuilderImpl { Ok(CommitStageTaskInfo { commit_nonces, base_accounts, - delegation_metadata, }) } @@ -244,7 +226,6 @@ impl TaskBuilderImpl { allow_undelegation: bool, account: CommittedAccount, base_account: Option, - rent_reimbursement: Pubkey, ) -> CommitFinalizeTask { let base_account = if account.account.data.len() > COMMIT_STATE_SIZE_THRESHOLD { @@ -264,7 +245,6 @@ impl TaskBuilderImpl { allow_undelegation, committed_account: account, delivery: delivery_details, - rent_reimbursement, } } } @@ -287,7 +267,6 @@ impl TasksBuilder for TaskBuilderImpl { let CommitStageTaskInfo { mut commit_nonces, mut base_accounts, - mut delegation_metadata, } = Self::fetch_commit_stage_info( intent_bundle, task_info_fetcher, @@ -310,7 +289,6 @@ impl TasksBuilder for TaskBuilderImpl { CommitFinalizeBuilder { commit_nonces: &mut commit_nonces, base_accounts: &mut base_accounts, - delegation_metadata: &mut delegation_metadata, } .build(value)?, ); @@ -333,7 +311,6 @@ impl TasksBuilder for TaskBuilderImpl { CommitFinalizeAndUndelegateBuilder { commit_nonces: &mut commit_nonces, base_accounts: &mut base_accounts, - delegation_metadata: &mut delegation_metadata, } .build(&value.commit_action)?, ); @@ -348,14 +325,9 @@ impl TasksBuilder for TaskBuilderImpl { intent_bundle: &ScheduledIntentBundle, ) -> TaskBuilderResult> { // Helper to create a finalize task - fn finalize_task( - account: &CommittedAccount, - rent_reimbursement: Pubkey, - ) -> BaseTaskImpl { + fn finalize_task(account: &CommittedAccount) -> BaseTaskImpl { FinalizeTask { delegated_account: account.pubkey, - owner_program: account.account.owner, - rent_reimbursement, } .into() } @@ -378,20 +350,11 @@ impl TasksBuilder for TaskBuilderImpl { // Helper to process commit types fn create_finalize_tasks( commit: &CommitType, - delegation_metadata: &HashMap, ) -> TaskBuilderResult> { match commit { CommitType::Standalone(accounts) => accounts .iter() - .map(|account| { - Ok(finalize_task( - account, - rent_reimbursement( - delegation_metadata, - account.pubkey, - )?, - )) - }) + .map(|account| Ok(finalize_task(account))) .collect(), CommitType::WithBaseActions { committed_accounts, @@ -399,15 +362,7 @@ impl TasksBuilder for TaskBuilderImpl { } => { let mut tasks = committed_accounts .iter() - .map(|account| { - Ok(finalize_task( - account, - rent_reimbursement( - delegation_metadata, - account.pubkey, - )?, - )) - }) + .map(|account| Ok(finalize_task(account))) .collect::>>()?; tasks.extend(TaskBuilderImpl::create_action_tasks( base_actions, @@ -420,6 +375,7 @@ impl TasksBuilder for TaskBuilderImpl { fn create_undelegate_tasks( commit_and_undelegate: &CommitAndUndelegate, delegation_metadata: &HashMap, + undelegation_requests: &HashMap, ) -> TaskBuilderResult> { let accounts = commit_and_undelegate.get_committed_accounts(); @@ -430,7 +386,16 @@ impl TasksBuilder for TaskBuilderImpl { delegation_metadata, account.pubkey, )?; - Ok(undelegate_task(account, &rent_reimbursement, None)) + let request_rent_payer = request_rent_payer( + delegation_metadata, + undelegation_requests, + account, + )?; + Ok(undelegate_task( + account, + &rent_reimbursement, + request_rent_payer, + )) }) .collect::>>()?; @@ -458,25 +423,42 @@ impl TasksBuilder for TaskBuilderImpl { ) .await .map_err(TaskBuilderError::FinalizedTasksBuildError)?; + let request_pubkeys = owner_program_request_pubkeys( + intent_bundle.get_undelegate_intent_accounts(), + intent_bundle.get_commit_finalize_and_undelegate_intent_accounts(), + &delegation_metadata, + )?; + let undelegation_requests = Self::fetch_undelegation_requests( + info_fetcher, + &request_pubkeys, + min_context_slot, + ) + .await + .map_err(TaskBuilderError::FinalizedTasksBuildError)?; if let Some(ref value) = intent_bundle.intent_bundle.commit { - tasks.extend(create_finalize_tasks(value, &delegation_metadata)?); + tasks.extend(create_finalize_tasks(value)?); } if let Some(ref value) = intent_bundle.intent_bundle.commit_and_undelegate { - tasks.extend(create_finalize_tasks( - &value.commit_action, + tasks.extend(create_finalize_tasks(&value.commit_action)?); + tasks.extend(create_undelegate_tasks( + value, &delegation_metadata, + &undelegation_requests, )?); - tasks.extend(create_undelegate_tasks(value, &delegation_metadata)?); } if let Some(ref value) = intent_bundle.intent_bundle.commit_finalize_and_undelegate { - tasks.extend(create_undelegate_tasks(value, &delegation_metadata)?); + tasks.extend(create_undelegate_tasks( + value, + &delegation_metadata, + &undelegation_requests, + )?); } Ok(tasks) @@ -538,7 +520,6 @@ impl<'a> CommitAndUndelegateBuilder<'a> { struct CommitFinalizeBuilder<'a> { commit_nonces: &'a mut HashMap, base_accounts: &'a mut HashMap, - delegation_metadata: &'a mut HashMap, } impl<'a> CommitFinalizeBuilder<'a> { @@ -558,10 +539,6 @@ impl<'a> CommitFinalizeBuilder<'a> { false, account.clone(), base, - rent_reimbursement( - self.delegation_metadata, - account.pubkey, - )?, ) .into()) }) @@ -579,7 +556,6 @@ impl<'a> CommitFinalizeBuilder<'a> { struct CommitFinalizeAndUndelegateBuilder<'a> { commit_nonces: &'a mut HashMap, base_accounts: &'a mut HashMap, - delegation_metadata: &'a mut HashMap, } impl<'a> CommitFinalizeAndUndelegateBuilder<'a> { @@ -599,10 +575,6 @@ impl<'a> CommitFinalizeAndUndelegateBuilder<'a> { true, account.clone(), base, - rent_reimbursement( - self.delegation_metadata, - account.pubkey, - )?, ) .into()) }) @@ -640,6 +612,64 @@ fn rent_reimbursement( .ok_or(TaskBuilderError::MissingDelegationMetadata(pubkey)) } +fn owner_program_request_pubkeys( + commit_and_undelegate_accounts: Option<&Vec>, + commit_finalize_and_undelegate_accounts: Option<&Vec>, + delegation_metadata: &HashMap, +) -> TaskBuilderResult> { + [ + commit_and_undelegate_accounts, + commit_finalize_and_undelegate_accounts, + ] + .into_iter() + .flatten() + .flat_map(|accounts| accounts.iter()) + .filter_map(|account| { + let metadata = match delegation_metadata.get(&account.pubkey) { + Some(metadata) => metadata, + None => { + return Some(Err(TaskBuilderError::MissingDelegationMetadata( + account.pubkey, + ))); + } + }; + if metadata.undelegation_requester + == UndelegationRequester::OwnerProgram + { + Some(Ok(account.pubkey)) + } else { + None + } + }) + .collect() +} + +fn request_rent_payer( + delegation_metadata: &HashMap, + undelegation_requests: &HashMap, + account: &CommittedAccount, +) -> TaskBuilderResult> { + let metadata = delegation_metadata + .get(&account.pubkey) + .ok_or(TaskBuilderError::MissingDelegationMetadata(account.pubkey))?; + if metadata.undelegation_requester != UndelegationRequester::OwnerProgram { + return Ok(None); + } + + let request = undelegation_requests + .get(&account.pubkey) + .ok_or(TaskBuilderError::MissingUndelegationRequest(account.pubkey))?; + if request.owner_program != account.account.owner { + return Err(TaskBuilderError::InvalidUndelegationRequestOwner { + delegated_account: account.pubkey, + request_owner: request.owner_program, + account_owner: account.account.owner, + }); + } + + Ok(Some(request.rent_payer)) +} + #[derive(thiserror::Error, Debug)] pub enum TaskBuilderError { #[error("CommitIdFetchError: {0}")] @@ -648,6 +678,16 @@ pub enum TaskBuilderError { FinalizedTasksBuildError(#[source] TaskInfoFetcherError), #[error("Missing delegation metadata for {0}")] MissingDelegationMetadata(Pubkey), + #[error("Missing undelegation request for owner-program request {0}")] + MissingUndelegationRequest(Pubkey), + #[error( + "Undelegation request for {delegated_account} has owner {request_owner}, expected {account_owner}" + )] + InvalidUndelegationRequestOwner { + delegated_account: Pubkey, + request_owner: Pubkey, + account_owner: Pubkey, + }, } impl TaskBuilderError { @@ -655,7 +695,9 @@ impl TaskBuilderError { match self { Self::CommitTasksBuildError(err) => err.signature(), Self::FinalizedTasksBuildError(err) => err.signature(), - Self::MissingDelegationMetadata(_) => None, + Self::MissingDelegationMetadata(_) + | Self::MissingUndelegationRequest(_) + | Self::InvalidUndelegationRequestOwner { .. } => None, } } } diff --git a/magicblock-committor-service/src/tasks/task_strategist.rs b/magicblock-committor-service/src/tasks/task_strategist.rs index 8203699ea..c8d5ea2b0 100644 --- a/magicblock-committor-service/src/tasks/task_strategist.rs +++ b/magicblock-committor-service/src/tasks/task_strategist.rs @@ -501,7 +501,10 @@ mod tests { }; #[derive(Default)] - struct MockInfoFetcher; + struct MockInfoFetcher { + delegation_metadata: HashMap, + undelegation_requests: HashMap, + } #[async_trait::async_trait] impl TaskInfoFetcher for MockInfoFetcher { @@ -538,13 +541,18 @@ mod tests { Ok(pubkeys .iter() .map(|pubkey| { + let (undelegation_requester, rent_payer) = self + .delegation_metadata + .get(pubkey) + .copied() + .unwrap_or((UndelegationRequester::None, *pubkey)); ( *pubkey, DelegationMetadata { last_commit_id: 0, - undelegation_requester: UndelegationRequester::None, + undelegation_requester, seeds: vec![], - rent_payer: *pubkey, + rent_payer, }, ) }) @@ -553,11 +561,18 @@ mod tests { async fn fetch_undelegation_requests( &self, - _delegated_accounts: &[Pubkey], + delegated_accounts: &[Pubkey], _: u64, ) -> TaskInfoFetcherResult> { - Ok(HashMap::new()) + Ok(delegated_accounts + .iter() + .filter_map(|pubkey| { + self.undelegation_requests + .get(pubkey) + .map(|request| (*pubkey, *request)) + }) + .collect()) } async fn get_base_accounts( @@ -633,8 +648,6 @@ mod tests { fn create_test_finalize_task() -> FinalizeTask { FinalizeTask { delegated_account: Pubkey::new_unique(), - owner_program: Pubkey::new_unique(), - rent_reimbursement: Pubkey::new_unique(), } } @@ -904,7 +917,7 @@ mod tests { async fn test_finalize_tasks_uses_metadata_rent_payer_for_undelegate() { let delegated_account = Pubkey::new_unique(); let intent = create_test_intent(0, &[delegated_account], true); - let info_fetcher = Arc::new(MockInfoFetcher); + let info_fetcher = Arc::new(MockInfoFetcher::default()); let tasks = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) .await @@ -915,7 +928,6 @@ mod tests { panic!("expected finalize task"); }; assert_eq!(task.delegated_account, delegated_account); - assert_eq!(task.rent_reimbursement, delegated_account); let BaseTaskImpl::Undelegate(task) = &tasks[1] else { panic!("expected undelegate task"); }; @@ -924,12 +936,118 @@ mod tests { assert_eq!(task.request_rent_payer, None); } + #[tokio::test] + async fn test_finalize_tasks_use_request_rent_payer_for_owner_program_undelegate( + ) { + let delegated_account = Pubkey::new_unique(); + let request_rent_payer = Pubkey::new_unique(); + let intent = create_test_intent(0, &[delegated_account], true); + let owner_program = intent + .get_undelegate_intent_accounts() + .unwrap() + .first() + .unwrap() + .account + .owner; + let info_fetcher = Arc::new(MockInfoFetcher { + delegation_metadata: HashMap::from([( + delegated_account, + (UndelegationRequester::OwnerProgram, delegated_account), + )]), + undelegation_requests: HashMap::from([( + delegated_account, + UndelegationRequest { + delegated_account, + owner_program, + rent_payer: request_rent_payer, + created_slot: 0, + expires_at_slot: 10, + last_commit_id_at_request: 0, + bump: 255, + _padding: [0; 7], + }, + )]), + }); + + let tasks = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) + .await + .unwrap(); + + let BaseTaskImpl::Undelegate(task) = &tasks[1] else { + panic!("expected undelegate task"); + }; + assert_eq!(task.delegated_account, delegated_account); + assert_eq!(task.rent_reimbursement, delegated_account); + assert_eq!(task.request_rent_payer, Some(request_rent_payer)); + } + + #[tokio::test] + async fn test_finalize_tasks_fail_when_owner_program_request_missing() { + let delegated_account = Pubkey::new_unique(); + let intent = create_test_intent(0, &[delegated_account], true); + let info_fetcher = Arc::new(MockInfoFetcher { + delegation_metadata: HashMap::from([( + delegated_account, + (UndelegationRequester::OwnerProgram, delegated_account), + )]), + undelegation_requests: HashMap::new(), + }); + + let err = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) + .await + .unwrap_err(); + + assert!(matches!( + err, + crate::tasks::task_builder::TaskBuilderError::MissingUndelegationRequest(pubkey) + if pubkey == delegated_account + )); + } + + #[tokio::test] + async fn test_finalize_tasks_fail_when_owner_program_request_owner_mismatches( + ) { + let delegated_account = Pubkey::new_unique(); + let intent = create_test_intent(0, &[delegated_account], true); + let info_fetcher = Arc::new(MockInfoFetcher { + delegation_metadata: HashMap::from([( + delegated_account, + (UndelegationRequester::OwnerProgram, delegated_account), + )]), + undelegation_requests: HashMap::from([( + delegated_account, + UndelegationRequest { + delegated_account, + owner_program: Pubkey::new_unique(), + rent_payer: Pubkey::new_unique(), + created_slot: 0, + expires_at_slot: 10, + last_commit_id_at_request: 0, + bump: 255, + _padding: [0; 7], + }, + )]), + }); + + let err = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) + .await + .unwrap_err(); + + assert!(matches!( + err, + crate::tasks::task_builder::TaskBuilderError::InvalidUndelegationRequestOwner { + delegated_account: pubkey, + .. + } if pubkey == delegated_account + )); + } + #[tokio::test] async fn test_build_single_stage_mode() { let pubkey = [Pubkey::new_unique()]; let intent = create_test_intent(0, &pubkey, false); - let info_fetcher = Arc::new(MockInfoFetcher); + let info_fetcher = Arc::new(MockInfoFetcher::default()); let commit_task = TaskBuilderImpl::commit_tasks( &info_fetcher, &intent, @@ -957,11 +1075,12 @@ mod tests { } #[tokio::test] - async fn test_build_two_stage_mode_no_alts() { - let pubkeys: [_; 3] = std::array::from_fn(|_| Pubkey::new_unique()); + async fn test_build_two_stage_mode_when_task_count_exceeds_single_stage_limit( + ) { + let pubkeys: [_; 8] = std::array::from_fn(|_| Pubkey::new_unique()); let intent = create_test_intent(0, &pubkeys, true); - let info_fetcher = Arc::new(MockInfoFetcher); + let info_fetcher = Arc::new(MockInfoFetcher::default()); let commit_task = TaskBuilderImpl::commit_tasks( &info_fetcher, &intent, @@ -982,15 +1101,9 @@ mod tests { ) .expect("Execution mode created"); - let StrategyExecutionMode::TwoStage { - commit_stage, - finalize_stage, - } = execution_mode - else { + let StrategyExecutionMode::TwoStage { .. } = execution_mode else { panic!("Unexpected execution mode"); }; - assert!(!commit_stage.uses_alts()); - assert!(!finalize_stage.uses_alts()); } #[tokio::test] @@ -998,7 +1111,7 @@ mod tests { let pubkeys: [_; 8] = std::array::from_fn(|_| Pubkey::new_unique()); let intent = create_test_intent(0, &pubkeys, false); - let info_fetcher = Arc::new(MockInfoFetcher); + let info_fetcher = Arc::new(MockInfoFetcher::default()); let commit_task = TaskBuilderImpl::commit_tasks( &info_fetcher, &intent, diff --git a/magicblock-committor-service/src/transactions.rs b/magicblock-committor-service/src/transactions.rs index 40e61998c..d22c518c1 100644 --- a/magicblock-committor-service/src/transactions.rs +++ b/magicblock-committor-service/src/transactions.rs @@ -38,12 +38,12 @@ pub const MAX_PROCESS_AND_CLOSE_PER_TX_USING_LOOKUP: u8 = 4; /// How many finalize instructions fit into a single transaction #[allow(unused)] // serves as documentation as well -pub const MAX_FINALIZE_PER_TX: u8 = 2; +pub const MAX_FINALIZE_PER_TX: u8 = 5; /// How many finalize instructions fit into a single transaction /// when using address lookup tables #[allow(unused)] // serves as documentation as well -pub const MAX_FINALIZE_PER_TX_USING_LOOKUP: u8 = 40; +pub const MAX_FINALIZE_PER_TX_USING_LOOKUP: u8 = 48; /// How many undelegate instructions fit into a single transaction /// NOTE: that we assume the rent reimbursement account to be the delegated account @@ -222,12 +222,7 @@ mod test { validator_auth: Pubkey, pubkey: &Pubkey, ) -> Instruction { - dlp_api::instruction_builder::finalize( - validator_auth, - *pubkey, - Pubkey::new_unique(), - Pubkey::new_unique(), - ) + dlp_api::instruction_builder::finalize(validator_auth, *pubkey) } // These tests statically determine the optimal ix count to fit into a single diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 6dee47c77..5dbb77910 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -3050,7 +3050,7 @@ dependencies = [ "borsh 1.7.0", "color-backtrace", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "rand 0.8.6", "rayon", "serde", @@ -3531,7 +3531,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-metrics", "magicblock-program", "solana-hash 4.2.0", @@ -3647,7 +3647,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-ledger", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", @@ -3709,7 +3709,7 @@ dependencies = [ "magicblock-aml", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", "parking_lot", @@ -3778,7 +3778,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-committor-program", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3892,7 +3892,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "3.0.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7#72af1c7542ee00a383f0945184fee4a0d9cec6e0" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40#212d3445ed6384caf3661fbc34e35df4ba9fcd40" dependencies = [ "bincode", "borsh 0.10.4", @@ -3918,7 +3918,7 @@ dependencies = [ "solana-system-interface 2.0.0", "static_assertions", "strum", - "thiserror 2.0.18", + "thiserror 1.0.69", ] [[package]] @@ -4051,7 +4051,7 @@ dependencies = [ "bincode", "lazy_static", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-magic-program-api 0.13.3", "num-derive", "num-traits", @@ -4209,7 +4209,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.13.3" dependencies = [ - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -5058,7 +5058,7 @@ version = "0.0.0" dependencies = [ "borsh 1.7.0", "ephemeral-rollups-sdk", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-magic-program-api 0.13.3", "rkyv 0.7.46", "solana-program 3.0.0", @@ -5946,7 +5946,7 @@ dependencies = [ "anyhow", "borsh 1.7.0", "integration-test-tools", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "program-schedulecommit", "solana-commitment-config", "solana-compute-budget-interface", @@ -5968,7 +5968,7 @@ dependencies = [ "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -5996,7 +5996,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-magic-program-api 0.13.3", "magicblock-program", "program-schedulecommit", @@ -6017,7 +6017,7 @@ name = "schedulecommit-test-security" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-magic-program-api 0.13.3", "program-schedulecommit", "program-schedulecommit-security", @@ -9796,7 +9796,7 @@ dependencies = [ "integration-test-tools", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9823,7 +9823,7 @@ dependencies = [ "magicblock-aml", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "program-flexi-counter", "program-mini", "solana-account 3.4.0", @@ -9849,7 +9849,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9919,7 +9919,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "program-flexi-counter", "solana-commitment-config", "solana-rpc-client", @@ -9942,7 +9942,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-program", "magicblock-validator-admin", "solana-commitment-config", @@ -9988,7 +9988,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "log", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=72af1c7)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", "magicblock-magic-program-api 0.13.3", "program-flexi-counter", "solana-rpc-client-api", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 7173bafba..c9ea7d4ca 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -63,7 +63,7 @@ magicblock-committor-program = { path = "../magicblock-committor-program", featu magicblock-committor-service = { path = "../magicblock-committor-service" } magicblock-config = { path = "../magicblock-config" } magicblock-core = { path = "../magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "72af1c7", default-features = false } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "212d3445ed6384caf3661fbc34e35df4ba9fcd40", default-features = false } magicblock-magic-program-api = { path = "../magicblock-magic-program-api" } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } diff --git a/test-integration/schedulecommit/elfs/dlp.so b/test-integration/schedulecommit/elfs/dlp.so index 1cd487be083a613c790674a451134f5c3c4c3129..7f5151d5ba637281106fb2bd22821d5802b4f0f1 100755 GIT binary patch delta 137354 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 delta 139371 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 Date: Tue, 7 Jul 2026 13:00:49 +0530 Subject: [PATCH 3/8] drop undelegation request account fetch and simplify --- .agents/context/crates/magicblock-accounts.md | 2 +- .../crates/magicblock-committor-service.md | 2 +- .agents/specs/validator-specification.md | 13 +- Cargo.lock | 12 +- Cargo.toml | 2 +- .../src/intent_executor/task_info_fetcher.rs | 203 +----------------- magicblock-committor-service/src/tasks/mod.rs | 19 +- .../src/tasks/task_builder.rs | 129 ++--------- .../src/tasks/task_strategist.rs | 121 +---------- test-integration/Cargo.lock | 58 ++--- test-integration/Cargo.toml | 2 +- test-integration/schedulecommit/elfs/dlp.so | Bin 468552 -> 468440 bytes .../test-committor-service/tests/common.rs | 22 +- .../tests/test_transaction_preparator.rs | 2 +- 14 files changed, 81 insertions(+), 506 deletions(-) diff --git a/.agents/context/crates/magicblock-accounts.md b/.agents/context/crates/magicblock-accounts.md index bf322c520..da27d946e 100644 --- a/.agents/context/crates/magicblock-accounts.md +++ b/.agents/context/crates/magicblock-accounts.md @@ -233,7 +233,7 @@ The code uses `expect(POISONED_MUTEX_MSG)` in the normal processing paths. One r ### Owner-program undelegation requests -`magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. Current DLP finalize instructions do not undelegate; the committor finalizes state and then sends standalone DLP `Undelegate`. When `DelegationMetadata.undelegation_requester = OwnerProgram`, the committor fetches the matching request PDA and passes the request rent payer to `Undelegate` so DLP can close the request account. +`magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. Current DLP finalize instructions do not undelegate; the committor finalizes state and then sends standalone DLP `Undelegate`. When `DelegationMetadata.undelegation_requester = OwnerProgram`, the committor includes the derived request PDA in `Undelegate`; DLP validates it and uses the delegation metadata rent payer to close both delegation and request accounts. ### Undelegation notifications are best-effort diff --git a/.agents/context/crates/magicblock-committor-service.md b/.agents/context/crates/magicblock-committor-service.md index 4daed77d9..3c8b492b0 100644 --- a/.agents/context/crates/magicblock-committor-service.md +++ b/.agents/context/crates/magicblock-committor-service.md @@ -203,7 +203,7 @@ IntentExecutorImpl::execute -> reset nonce cache for all committed pubkeys on errors, or only undelegated pubkeys on successful undelegation ``` -Current DLP finalize instructions do not undelegate and require only the validator plus delegated account, so `FinalizeTask` and `CommitFinalizeTask` no longer fetch or carry owner/rent metadata. Finalize-stage `UndelegateTask`s complete ownership return through standalone DLP `Undelegate`. For owner-program requests, task building detects `DelegationMetadata.undelegation_requester = OwnerProgram`, fetches the matching `UndelegationRequest` with the same `min_context_slot`, validates the request owner against the committed account owner, and passes `request.rent_payer` so DLP can close the request PDA. For validator-requested undelegation, or metadata still showing `None` because commit and finalize task lists are built before the commit-stage transaction records the validator requester on base, `request_rent_payer` remains `None`. +Current DLP finalize instructions do not undelegate and require only the validator plus delegated account, so `FinalizeTask` and `CommitFinalizeTask` no longer fetch or carry owner/rent metadata. Finalize-stage `UndelegateTask`s complete ownership return through standalone DLP `Undelegate`. For owner-program requests, task building detects `DelegationMetadata.undelegation_requester = OwnerProgram` and includes the derived request PDA; DLP validates that request account and uses `DelegationMetadata.rent_payer` to close both delegation and request accounts. For validator-requested undelegation, or metadata still showing `None` because commit and finalize task lists are built before the commit-stage transaction records the validator requester on base, no request account is included. Transaction fit is not only packet size. `TaskStrategist` currently checks whether a single-stage transaction or each two-stage transaction fits the wire size, optionally after switching commits to buffers and adding ALTs, but it does not split a transaction stage by compute units. Each commit, finalize, commit-finalize, and undelegate task currently advertises `120_000` CU, while Agave caps a transaction at `1_400_000` CU. Keep task bundles below that transaction-level cap unless the strategist and executor/output/persistence model are extended to split, record, and confirm multiple transactions for the affected stage. diff --git a/.agents/specs/validator-specification.md b/.agents/specs/validator-specification.md index 9570042d9..343cd747e 100644 --- a/.agents/specs/validator-specification.md +++ b/.agents/specs/validator-specification.md @@ -268,12 +268,13 @@ Commit/finalize-style instructions only commit/finalize state and record or preserve `DelegationMetadata.undelegation_requester`. The validator-side committor completes undelegation by sending a standalone DLP `Undelegate` instruction in the finalize stage. When metadata says the requester is -`OwnerProgram`, the committor must also pass the undelegation request PDA and -the request account's rent payer to `Undelegate`; when metadata says -`Validator` or is still `None` at task-build time, no request accounts are -passed. `None` can be valid for validator-requested undelegation because commit -and finalize task lists are built before the commit-stage transaction records -the validator requester on base. +`OwnerProgram`, the committor must also include the undelegation request PDA in +`Undelegate`; the delegation metadata rent payer is used for both delegation +and request account cleanup. When metadata says `Validator` or is still `None` +at task-build time, no request account is passed. `None` can be valid for +validator-requested undelegation because commit and finalize task lists are +built before the commit-stage transaction records the validator requester on +base. ### Callback discriminator diff --git a/Cargo.lock b/Cargo.lock index 55ffae875..dbfdab51c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1970,7 +1970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -3856,7 +3856,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "3.0.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40#212d3445ed6384caf3661fbc34e35df4ba9fcd40" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d#074a1a4175faea2e47b745e15dcabecb046e815d" dependencies = [ "bincode", "borsh 0.10.4", @@ -5289,7 +5289,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -5765,7 +5765,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys 0.12.1", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -9668,7 +9668,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix 1.1.4", - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] @@ -10626,7 +10626,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.60.2", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 951d80cf3..818d0aa0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "212d3445ed6384caf3661fbc34e35df4ba9fcd40" } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "074a1a4175faea2e47b745e15dcabecb046e815d" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs index e824d5ba2..ba138ed16 100644 --- a/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs +++ b/magicblock-committor-service/src/intent_executor/task_info_fetcher.rs @@ -8,9 +8,7 @@ use std::{ use async_trait::async_trait; use dlp_api::{ - delegation_metadata_seeds_from_delegated_account, - pda::undelegation_request_pda_from_delegated_account, - state::{DelegationMetadata, UndelegationRequest}, + delegation_metadata_seeds_from_delegated_account, state::DelegationMetadata, }; use lru::LruCache; use magicblock_metrics::metrics; @@ -48,13 +46,6 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { min_context_slot: u64, ) -> TaskInfoFetcherResult>; - /// Fetches rent reimbursement address for pubkeys - async fn fetch_rent_reimbursements( - &self, - pubkeys: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult>; - /// Fetches delegation metadata keyed by delegated account pubkey. async fn fetch_delegation_metadata( &self, @@ -62,13 +53,6 @@ pub trait TaskInfoFetcher: Send + Sync + 'static { min_context_slot: u64, ) -> TaskInfoFetcherResult>; - /// Fetches request-undelegation accounts keyed by delegated account pubkey. - async fn fetch_undelegation_requests( - &self, - delegated_accounts: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult>; - async fn get_base_accounts( &self, pubkeys: &[Pubkey], @@ -188,57 +172,6 @@ impl RpcTaskInfoFetcher { } } - pub async fn fetch_optional_accounts_with_retries( - rpc_client: &MagicblockRpcClient, - pubkeys: &[Pubkey], - min_context_slot: u64, - max_retries: NonZeroUsize, - ) -> TaskInfoFetcherResult>> { - if pubkeys.is_empty() { - return Ok(Vec::new()); - } - - let mut i = 0; - loop { - i += 1; - let err = match Self::fetch_optional_accounts( - rpc_client, - pubkeys, - min_context_slot, - ) - .await - { - Ok(value) => break Ok(value), - Err(err) => err, - }; - - match err { - TaskInfoFetcherError::MinContextSlotNotReachedError(_, _) => { - info!( - min_context_slot, - attempt = i, - "Min context slot not reached" - ); - tokio::time::sleep(Duration::from_millis(100)).await; - } - TaskInfoFetcherError::MagicBlockRpcClientError(ref err) => { - warn!(error = ?err, attempt = i, "Fetch optional account error"); - } - TaskInfoFetcherError::AccountNotFoundError(_) - | TaskInfoFetcherError::InvalidAccountDataError(_) => { - error!(error = ?err, "Unexpected error"); - break Err(err); - } - } - - if i >= max_retries.get() { - break Err(err); - } - - tokio::time::sleep(Duration::from_millis(50)).await; - } - } - /// Fetches specified list of accounts pub async fn fetch_accounts( rpc_client: &MagicblockRpcClient, @@ -288,34 +221,6 @@ impl RpcTaskInfoFetcher { Ok(accounts) } - - pub async fn fetch_optional_accounts( - rpc_client: &MagicblockRpcClient, - pubkeys: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult>> { - if pubkeys.is_empty() { - return Ok(Vec::new()); - } - - metrics::inc_task_info_fetcher_a_count(); - let commitment = rpc_client.commitment(); - rpc_client - .get_multiple_accounts_with_config( - pubkeys, - RpcAccountInfoConfig { - encoding: Some(UiAccountEncoding::Base64Zstd), - commitment: Some(commitment), - data_slice: None, - min_context_slot: Some(min_context_slot), - }, - None, - ) - .await - .map_err(|err| { - TaskInfoFetcherError::map_client_error(min_context_slot, err) - }) - } } #[async_trait] @@ -360,23 +265,6 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { Ok(pubkeys.iter().copied().zip(nonces).collect()) } - async fn fetch_rent_reimbursements( - &self, - pubkeys: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult> { - Ok(Self::fetch_metadata_with_retries( - &self.rpc_client, - pubkeys, - min_context_slot, - NUM_FETCH_RETRIES, - ) - .await? - .into_iter() - .map(|m| m.rent_payer) - .collect()) - } - async fn fetch_delegation_metadata( &self, pubkeys: &[Pubkey], @@ -397,58 +285,6 @@ impl TaskInfoFetcher for RpcTaskInfoFetcher { .collect()) } - async fn fetch_undelegation_requests( - &self, - delegated_accounts: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult> { - if delegated_accounts.is_empty() { - return Ok(HashMap::new()); - } - - let request_pdas = delegated_accounts - .iter() - .map(undelegation_request_pda_from_delegated_account) - .collect::>(); - - let accounts = Self::fetch_optional_accounts_with_retries( - &self.rpc_client, - &request_pdas, - min_context_slot, - NUM_FETCH_RETRIES, - ) - .await?; - - let mut requests = HashMap::new(); - for ((delegated_account, request_pda), account) in delegated_accounts - .iter() - .copied() - .zip(request_pdas) - .zip(accounts.into_iter()) - { - let Some(account) = account else { - continue; - }; - let request = - *UndelegationRequest::try_from_bytes_with_discriminator( - &account.data, - ) - .map_err(|_| { - TaskInfoFetcherError::InvalidAccountDataError(request_pda) - })?; - - if request.delegated_account != delegated_account { - return Err(TaskInfoFetcherError::InvalidAccountDataError( - request_pda, - )); - } - - requests.insert(delegated_account, request); - } - - Ok(requests) - } - async fn get_base_accounts( &self, pubkeys: &[Pubkey], @@ -780,16 +616,6 @@ impl TaskInfoFetcher for CacheTaskInfoFetcher { Ok(result) } - async fn fetch_rent_reimbursements( - &self, - pubkeys: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult> { - self.inner - .fetch_rent_reimbursements(pubkeys, min_context_slot) - .await - } - async fn fetch_delegation_metadata( &self, pubkeys: &[Pubkey], @@ -800,16 +626,6 @@ impl TaskInfoFetcher for CacheTaskInfoFetcher { .await } - async fn fetch_undelegation_requests( - &self, - delegated_accounts: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult> { - self.inner - .fetch_undelegation_requests(delegated_accounts, min_context_slot) - .await - } - async fn get_base_accounts( &self, pubkeys: &[Pubkey], @@ -1194,14 +1010,6 @@ mod tests { .collect()) } - async fn fetch_rent_reimbursements( - &self, - _: &[Pubkey], - _: u64, - ) -> TaskInfoFetcherResult> { - unimplemented!() - } - async fn fetch_delegation_metadata( &self, pubkeys: &[Pubkey], @@ -1225,15 +1033,6 @@ mod tests { .collect()) } - async fn fetch_undelegation_requests( - &self, - _delegated_accounts: &[Pubkey], - _: u64, - ) -> TaskInfoFetcherResult> - { - Ok(HashMap::new()) - } - async fn get_base_accounts( &self, _: &[Pubkey], diff --git a/magicblock-committor-service/src/tasks/mod.rs b/magicblock-committor-service/src/tasks/mod.rs index 714dc0dbc..845b11680 100644 --- a/magicblock-committor-service/src/tasks/mod.rs +++ b/magicblock-committor-service/src/tasks/mod.rs @@ -96,7 +96,7 @@ impl BaseTask for BaseTaskImpl { ) } Self::Undelegate(value) => { - if value.request_rent_payer.is_some() { + if value.include_undelegation_request { dlp_api::instruction_builder::undelegate_with_request_size_budget( AccountSizeClass::Huge, ) @@ -183,18 +183,17 @@ pub struct UndelegateTask { pub delegated_account: Pubkey, pub owner_program: Pubkey, pub rent_reimbursement: Pubkey, - pub request_rent_payer: Option, + pub include_undelegation_request: bool, } impl UndelegateTask { pub fn instruction(&self, validator: &Pubkey) -> Instruction { - if let Some(request_rent_payer) = self.request_rent_payer { + if self.include_undelegation_request { dlp_api::instruction_builder::undelegate_with_request( *validator, self.delegated_account, self.owner_program, self.rent_reimbursement, - request_rent_payer, ) } else { dlp_api::instruction_builder::undelegate( @@ -633,7 +632,7 @@ mod serialization_safety_test { delegated_account: Pubkey::new_unique(), owner_program: Pubkey::new_unique(), rent_reimbursement: Pubkey::new_unique(), - request_rent_payer: None, + include_undelegation_request: false, } .into(); assert_serializable(&undelegate_task.instruction(&validator)); @@ -684,30 +683,26 @@ mod serialization_safety_test { } #[test] - fn test_undelegate_task_uses_request_accounts_when_rent_payer_is_present() { + fn test_undelegate_task_uses_request_account_when_included() { let delegated_account = Pubkey::new_unique(); - let request_rent_payer = Pubkey::new_unique(); let ix = UndelegateTask { delegated_account, owner_program: Pubkey::new_unique(), rent_reimbursement: Pubkey::new_unique(), - request_rent_payer: Some(request_rent_payer), + include_undelegation_request: true, } .instruction(&Pubkey::new_unique()); assert_eq!(ix.program_id, dlp_api::id()); assert_eq!(ix.data, DlpDiscriminator::Undelegate.to_vec()); - assert_eq!(ix.accounts.len(), 14); + assert_eq!(ix.accounts.len(), 13); assert_eq!( ix.accounts[12].pubkey, undelegation_request_pda_from_delegated_account(&delegated_account) ); assert!(ix.accounts[12].is_writable); assert!(!ix.accounts[12].is_signer); - assert_eq!(ix.accounts[13].pubkey, request_rent_payer); - assert!(ix.accounts[13].is_writable); - assert!(!ix.accounts[13].is_signer); } fn make_buffer_commit_task( diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index 3f6b9c7ed..f8b28044e 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -1,9 +1,7 @@ use std::{collections::HashMap, sync::Arc}; use async_trait::async_trait; -use dlp_api::state::{ - DelegationMetadata, UndelegationRequest, UndelegationRequester, -}; +use dlp_api::state::{DelegationMetadata, UndelegationRequester}; use magicblock_core::intent::CommittedAccount; use magicblock_program::magic_scheduled_base_intent::{ BaseAction, CommitAndUndelegate, CommitType, ScheduledIntentBundle, @@ -149,16 +147,6 @@ impl TaskBuilderImpl { .await } - async fn fetch_undelegation_requests( - task_info_fetcher: &Arc, - pubkeys: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult> { - task_info_fetcher - .fetch_undelegation_requests(pubkeys, min_context_slot) - .await - } - fn get_finalize_stage_metadata_pubkeys( intent_bundle: &ScheduledIntentBundle, ) -> Vec { @@ -336,13 +324,13 @@ impl TasksBuilder for TaskBuilderImpl { fn undelegate_task( account: &CommittedAccount, rent_reimbursement: &Pubkey, - request_rent_payer: Option, + include_undelegation_request: bool, ) -> BaseTaskImpl { UndelegateTask { delegated_account: account.pubkey, owner_program: account.account.owner, rent_reimbursement: *rent_reimbursement, - request_rent_payer, + include_undelegation_request, } .into() } @@ -375,7 +363,6 @@ impl TasksBuilder for TaskBuilderImpl { fn create_undelegate_tasks( commit_and_undelegate: &CommitAndUndelegate, delegation_metadata: &HashMap, - undelegation_requests: &HashMap, ) -> TaskBuilderResult> { let accounts = commit_and_undelegate.get_committed_accounts(); @@ -386,15 +373,15 @@ impl TasksBuilder for TaskBuilderImpl { delegation_metadata, account.pubkey, )?; - let request_rent_payer = request_rent_payer( - delegation_metadata, - undelegation_requests, - account, - )?; + let include_undelegation_request = + should_include_undelegation_request( + delegation_metadata, + account.pubkey, + )?; Ok(undelegate_task( account, &rent_reimbursement, - request_rent_payer, + include_undelegation_request, )) }) .collect::>>()?; @@ -423,18 +410,6 @@ impl TasksBuilder for TaskBuilderImpl { ) .await .map_err(TaskBuilderError::FinalizedTasksBuildError)?; - let request_pubkeys = owner_program_request_pubkeys( - intent_bundle.get_undelegate_intent_accounts(), - intent_bundle.get_commit_finalize_and_undelegate_intent_accounts(), - &delegation_metadata, - )?; - let undelegation_requests = Self::fetch_undelegation_requests( - info_fetcher, - &request_pubkeys, - min_context_slot, - ) - .await - .map_err(TaskBuilderError::FinalizedTasksBuildError)?; if let Some(ref value) = intent_bundle.intent_bundle.commit { tasks.extend(create_finalize_tasks(value)?); @@ -444,21 +419,13 @@ impl TasksBuilder for TaskBuilderImpl { intent_bundle.intent_bundle.commit_and_undelegate { tasks.extend(create_finalize_tasks(&value.commit_action)?); - tasks.extend(create_undelegate_tasks( - value, - &delegation_metadata, - &undelegation_requests, - )?); + tasks.extend(create_undelegate_tasks(value, &delegation_metadata)?); } if let Some(ref value) = intent_bundle.intent_bundle.commit_finalize_and_undelegate { - tasks.extend(create_undelegate_tasks( - value, - &delegation_metadata, - &undelegation_requests, - )?); + tasks.extend(create_undelegate_tasks(value, &delegation_metadata)?); } Ok(tasks) @@ -612,62 +579,14 @@ fn rent_reimbursement( .ok_or(TaskBuilderError::MissingDelegationMetadata(pubkey)) } -fn owner_program_request_pubkeys( - commit_and_undelegate_accounts: Option<&Vec>, - commit_finalize_and_undelegate_accounts: Option<&Vec>, +fn should_include_undelegation_request( delegation_metadata: &HashMap, -) -> TaskBuilderResult> { - [ - commit_and_undelegate_accounts, - commit_finalize_and_undelegate_accounts, - ] - .into_iter() - .flatten() - .flat_map(|accounts| accounts.iter()) - .filter_map(|account| { - let metadata = match delegation_metadata.get(&account.pubkey) { - Some(metadata) => metadata, - None => { - return Some(Err(TaskBuilderError::MissingDelegationMetadata( - account.pubkey, - ))); - } - }; - if metadata.undelegation_requester - == UndelegationRequester::OwnerProgram - { - Some(Ok(account.pubkey)) - } else { - None - } - }) - .collect() -} - -fn request_rent_payer( - delegation_metadata: &HashMap, - undelegation_requests: &HashMap, - account: &CommittedAccount, -) -> TaskBuilderResult> { + pubkey: Pubkey, +) -> TaskBuilderResult { let metadata = delegation_metadata - .get(&account.pubkey) - .ok_or(TaskBuilderError::MissingDelegationMetadata(account.pubkey))?; - if metadata.undelegation_requester != UndelegationRequester::OwnerProgram { - return Ok(None); - } - - let request = undelegation_requests - .get(&account.pubkey) - .ok_or(TaskBuilderError::MissingUndelegationRequest(account.pubkey))?; - if request.owner_program != account.account.owner { - return Err(TaskBuilderError::InvalidUndelegationRequestOwner { - delegated_account: account.pubkey, - request_owner: request.owner_program, - account_owner: account.account.owner, - }); - } - - Ok(Some(request.rent_payer)) + .get(&pubkey) + .ok_or(TaskBuilderError::MissingDelegationMetadata(pubkey))?; + Ok(metadata.undelegation_requester == UndelegationRequester::OwnerProgram) } #[derive(thiserror::Error, Debug)] @@ -678,16 +597,6 @@ pub enum TaskBuilderError { FinalizedTasksBuildError(#[source] TaskInfoFetcherError), #[error("Missing delegation metadata for {0}")] MissingDelegationMetadata(Pubkey), - #[error("Missing undelegation request for owner-program request {0}")] - MissingUndelegationRequest(Pubkey), - #[error( - "Undelegation request for {delegated_account} has owner {request_owner}, expected {account_owner}" - )] - InvalidUndelegationRequestOwner { - delegated_account: Pubkey, - request_owner: Pubkey, - account_owner: Pubkey, - }, } impl TaskBuilderError { @@ -695,9 +604,7 @@ impl TaskBuilderError { match self { Self::CommitTasksBuildError(err) => err.signature(), Self::FinalizedTasksBuildError(err) => err.signature(), - Self::MissingDelegationMetadata(_) - | Self::MissingUndelegationRequest(_) - | Self::InvalidUndelegationRequestOwner { .. } => None, + Self::MissingDelegationMetadata(_) => None, } } } diff --git a/magicblock-committor-service/src/tasks/task_strategist.rs b/magicblock-committor-service/src/tasks/task_strategist.rs index c8d5ea2b0..d0fa5b9e3 100644 --- a/magicblock-committor-service/src/tasks/task_strategist.rs +++ b/magicblock-committor-service/src/tasks/task_strategist.rs @@ -472,9 +472,7 @@ pub type TaskStrategistResult = Result; mod tests { use std::{collections::HashMap, sync::Arc}; - use dlp_api::state::{ - DelegationMetadata, UndelegationRequest, UndelegationRequester, - }; + use dlp_api::state::{DelegationMetadata, UndelegationRequester}; use magicblock_core::intent::CommittedAccount; use magicblock_program::magic_scheduled_base_intent::{ BaseAction, ProgramArgs, @@ -503,7 +501,6 @@ mod tests { #[derive(Default)] struct MockInfoFetcher { delegation_metadata: HashMap, - undelegation_requests: HashMap, } #[async_trait::async_trait] @@ -524,14 +521,6 @@ mod tests { Ok(pubkeys.iter().map(|pubkey| (*pubkey, 0)).collect()) } - async fn fetch_rent_reimbursements( - &self, - pubkeys: &[Pubkey], - _: u64, - ) -> TaskInfoFetcherResult> { - Ok(pubkeys.iter().map(|_| Pubkey::new_unique()).collect()) - } - async fn fetch_delegation_metadata( &self, pubkeys: &[Pubkey], @@ -559,22 +548,6 @@ mod tests { .collect()) } - async fn fetch_undelegation_requests( - &self, - delegated_accounts: &[Pubkey], - _: u64, - ) -> TaskInfoFetcherResult> - { - Ok(delegated_accounts - .iter() - .filter_map(|pubkey| { - self.undelegation_requests - .get(pubkey) - .map(|request| (*pubkey, *request)) - }) - .collect()) - } - async fn get_base_accounts( &self, _pubkeys: &[Pubkey], @@ -657,7 +630,7 @@ mod tests { delegated_account: Pubkey::new_unique(), owner_program: Pubkey::default(), rent_reimbursement: Pubkey::new_unique(), - request_rent_payer: None, + include_undelegation_request: false, } } @@ -933,40 +906,19 @@ mod tests { }; assert_eq!(task.delegated_account, delegated_account); assert_eq!(task.rent_reimbursement, delegated_account); - assert_eq!(task.request_rent_payer, None); + assert!(!task.include_undelegation_request); } #[tokio::test] - async fn test_finalize_tasks_use_request_rent_payer_for_owner_program_undelegate( - ) { + async fn test_finalize_tasks_include_request_for_owner_program_undelegate() + { let delegated_account = Pubkey::new_unique(); - let request_rent_payer = Pubkey::new_unique(); let intent = create_test_intent(0, &[delegated_account], true); - let owner_program = intent - .get_undelegate_intent_accounts() - .unwrap() - .first() - .unwrap() - .account - .owner; let info_fetcher = Arc::new(MockInfoFetcher { delegation_metadata: HashMap::from([( delegated_account, (UndelegationRequester::OwnerProgram, delegated_account), )]), - undelegation_requests: HashMap::from([( - delegated_account, - UndelegationRequest { - delegated_account, - owner_program, - rent_payer: request_rent_payer, - created_slot: 0, - expires_at_slot: 10, - last_commit_id_at_request: 0, - bump: 255, - _padding: [0; 7], - }, - )]), }); let tasks = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) @@ -978,68 +930,7 @@ mod tests { }; assert_eq!(task.delegated_account, delegated_account); assert_eq!(task.rent_reimbursement, delegated_account); - assert_eq!(task.request_rent_payer, Some(request_rent_payer)); - } - - #[tokio::test] - async fn test_finalize_tasks_fail_when_owner_program_request_missing() { - let delegated_account = Pubkey::new_unique(); - let intent = create_test_intent(0, &[delegated_account], true); - let info_fetcher = Arc::new(MockInfoFetcher { - delegation_metadata: HashMap::from([( - delegated_account, - (UndelegationRequester::OwnerProgram, delegated_account), - )]), - undelegation_requests: HashMap::new(), - }); - - let err = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) - .await - .unwrap_err(); - - assert!(matches!( - err, - crate::tasks::task_builder::TaskBuilderError::MissingUndelegationRequest(pubkey) - if pubkey == delegated_account - )); - } - - #[tokio::test] - async fn test_finalize_tasks_fail_when_owner_program_request_owner_mismatches( - ) { - let delegated_account = Pubkey::new_unique(); - let intent = create_test_intent(0, &[delegated_account], true); - let info_fetcher = Arc::new(MockInfoFetcher { - delegation_metadata: HashMap::from([( - delegated_account, - (UndelegationRequester::OwnerProgram, delegated_account), - )]), - undelegation_requests: HashMap::from([( - delegated_account, - UndelegationRequest { - delegated_account, - owner_program: Pubkey::new_unique(), - rent_payer: Pubkey::new_unique(), - created_slot: 0, - expires_at_slot: 10, - last_commit_id_at_request: 0, - bump: 255, - _padding: [0; 7], - }, - )]), - }); - - let err = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) - .await - .unwrap_err(); - - assert!(matches!( - err, - crate::tasks::task_builder::TaskBuilderError::InvalidUndelegationRequestOwner { - delegated_account: pubkey, - .. - } if pubkey == delegated_account - )); + assert!(task.include_undelegation_request); } #[tokio::test] diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 5dbb77910..36289e04e 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -289,7 +289,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -300,7 +300,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2041,7 +2041,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -3050,7 +3050,7 @@ dependencies = [ "borsh 1.7.0", "color-backtrace", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "rand 0.8.6", "rayon", "serde", @@ -3531,7 +3531,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-metrics", "magicblock-program", "solana-hash 4.2.0", @@ -3647,7 +3647,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-ledger", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", @@ -3709,7 +3709,7 @@ dependencies = [ "magicblock-aml", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", "parking_lot", @@ -3778,7 +3778,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-committor-program", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3892,7 +3892,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "3.0.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40#212d3445ed6384caf3661fbc34e35df4ba9fcd40" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d#074a1a4175faea2e47b745e15dcabecb046e815d" dependencies = [ "bincode", "borsh 0.10.4", @@ -3918,7 +3918,7 @@ dependencies = [ "solana-system-interface 2.0.0", "static_assertions", "strum", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] @@ -4051,7 +4051,7 @@ dependencies = [ "bincode", "lazy_static", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-magic-program-api 0.13.3", "num-derive", "num-traits", @@ -4209,7 +4209,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.13.3" dependencies = [ - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -4467,7 +4467,7 @@ version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -5058,7 +5058,7 @@ version = "0.0.0" dependencies = [ "borsh 1.7.0", "ephemeral-rollups-sdk", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-magic-program-api 0.13.3", "rkyv 0.7.46", "solana-program 3.0.0", @@ -5355,7 +5355,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -5817,7 +5817,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -5946,7 +5946,7 @@ dependencies = [ "anyhow", "borsh 1.7.0", "integration-test-tools", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "program-schedulecommit", "solana-commitment-config", "solana-compute-budget-interface", @@ -5968,7 +5968,7 @@ dependencies = [ "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -5996,7 +5996,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-magic-program-api 0.13.3", "magicblock-program", "program-schedulecommit", @@ -6017,7 +6017,7 @@ name = "schedulecommit-test-security" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-magic-program-api 0.13.3", "program-schedulecommit", "program-schedulecommit-security", @@ -6439,7 +6439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -9775,7 +9775,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] @@ -9796,7 +9796,7 @@ dependencies = [ "integration-test-tools", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9823,7 +9823,7 @@ dependencies = [ "magicblock-aml", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "program-flexi-counter", "program-mini", "solana-account 3.4.0", @@ -9849,7 +9849,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9919,7 +9919,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "program-flexi-counter", "solana-commitment-config", "solana-rpc-client", @@ -9942,7 +9942,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-program", "magicblock-validator-admin", "solana-commitment-config", @@ -9988,7 +9988,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "log", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=212d3445ed6384caf3661fbc34e35df4ba9fcd40)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", "magicblock-magic-program-api 0.13.3", "program-flexi-counter", "solana-rpc-client-api", @@ -10960,7 +10960,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.52.0", ] [[package]] diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index c9ea7d4ca..43dbf1099 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -63,7 +63,7 @@ magicblock-committor-program = { path = "../magicblock-committor-program", featu magicblock-committor-service = { path = "../magicblock-committor-service" } magicblock-config = { path = "../magicblock-config" } magicblock-core = { path = "../magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "212d3445ed6384caf3661fbc34e35df4ba9fcd40", default-features = false } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "074a1a4175faea2e47b745e15dcabecb046e815d", default-features = false } magicblock-magic-program-api = { path = "../magicblock-magic-program-api" } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } diff --git a/test-integration/schedulecommit/elfs/dlp.so b/test-integration/schedulecommit/elfs/dlp.so index 7f5151d5ba637281106fb2bd22821d5802b4f0f1..46e74a064f5b681d5fdf7c8ebb32c4ef2c992159 100755 GIT binary patch delta 129077 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 delta 132448 zcmd44d0bV+`#64P-~u8lT-m&`x&V>_nhTmDZfI&o3oa?j6&G?L)b#E3s;Ie_WQ{sz zN?vdQQ?kgVMX`EUR%TjhR%*U0%Sz4C%-!Gf%*^4Qd%)`R`F=jX*XRDhFwe|9^KA3X zGs`*W*hdlj4@4|)6l9|s{?f%?P4jE^Ok(@OG9Mq2*HbM}786LYWWTR0H>cZY%X)fh zZ08L{35#SqbGmx1Y^Tzun%)qJ!zR-g%7*TgQSu7ml{?60N`7P6-d~WTmF+ASEo^(; zwpPt9t0UG0Kzr^ER#CUT^-PW@_>mnvYMa+svV#@XjiUGNU}*sv5D)j-jr{j$n#1mglF_Q9?uCeMuvU%ZY5pEQ;7bxpPOyoM zlj*KESaIW%%K-8ritnM6KkT_Tf7C>9ov)rbblc07JFBdgkEZ;vm@;!ZIKk62j7wLh1X#Y&PVE1+!vEx(Bnp zknFdzlaSm9X15?&7R;iOqG*d?(I6n04TM}l7@L+foP1b$Bk zH`$3c(ez9McB{=n>-ynt%ECcq+lRB0cZ1E2U} zz%1=T9KtMpRuLw{GrP@uF3S-ovf&98kx>M?%I{k*vaar51@;) z+3@rtGK8H=zn?z5lcjZwqnj$&t!@LTHiA_^vVQ|B?p~dHbpspIEkl+0yEaIt_Y`9p zJ!X^j?B>J0t=qFb6}Dgli|VDq z%2qu*hF$tRm<49FweB`m9$vx*W(}Y#8}a=6Euq#!rsAv;ws7DoT3N}W1`TD0vlv}j z$;J$9${d5< zo2G=hTiEQ8!^v=VVq{lvc#*mBFx~XZZ9qF6ep%C2N|O|m$xegA+y(x!9hBk7Ofg~1 zUSC->+J}%YDp!t4Mj!m{*segfC9f;}*UKy;ub4hMnf;KLMu)!4;vP)`$C~wMviA>Q z{e0g|uL$}}BYyIxS7_fpCcH;pkdE8O=C&cEqm7~?$5j6lRX^3n2VC(AwM{pbf1t{T zg^P0Qa#Q&`FR{GYBHyxQ6T6Z#?Bj_e=Xy6GbbtGqcqjFJ~BL!6IMN((9%&iaeYLm^ zxyb4*c}a(N!kpQ+D9P{kRyk7G*(c{HMC2G-@YK^JorNrWTF3qJQnq*5 zUg|fJ%`S=~ud$6qyD&5S>AloZz@nC)q}c_Px0bIWG-f1Q_3T2LIte7X!%p7)*=hJkUJXdFc$62sCo;BMX z$lhF?M}H0Hw>pwg+HFZ?+H>^@oimaRShLEy+7!+NFRi@1W&rU|QTi-d#0IPl_1D#1 zyojA#yVHMKj@0(l99Fz;TCh1%D!z34Hk;GDC40CyutvZ%l1(k{P2YS1Ja~q6+>P6} zjT3O$6D;(F3^I{rzwk}aAroyw*nR64(Y(fdz;h(jnt1`5!mz+!IQWOh8?#&ML#_Qx z;KIi2{Mk@zh6y~kF&p3twRSUsiyE`N=R#@c3#_Op)Vlar&o0_G;%RG082i{2M&_{7 zu4r~#W&3M(#_kqLty;j&!SR{A3ycS%H#&yxG5P%!I4e(2c0nq^JUgEV!L|>zLMm9~wrKE=UAFy;Y{dWRCuOW6+{P|!>s%v}hIqZAW+Xj=EvrZ-AF(|Z zUFoZH*{zCc?IXy|%B+`@Ny4cbp`v?&z)_lc_V#UycI-B5`%*f@ol{>5Be946 zrcDgnw!JsaJYVVaUMPvb@He$D{DM7v&0c(^8+nSIdu0Sz!F`n@Z~*~-^H{xC$C9CJ zD*PS5PQc%8tk;gQq%GS9f8$xm&au>Xp3UAlhSodJet<+f&j##TNPcBUb}b?&S@!Nl zF+m^xKu`J}xMPwjb2Y-99=6e=l7x1?! zYqxh1wVq>p_b#O59LuO$2=@1J)gtl@%i6aHW`q;)cMlu=7AIROZ@#tJD<;nrs1^Nm z`?k|ZuGcKu^xJG^Spv)t6W<>J%d3yy{}-J%n`P`@MdnwY*ndBv181|O4@2p(Tv$~0 zU`sx%ORto$gCFHX%+=*UJVXPnKDwX!je^nvddWMYWJcxa0}wR4$Lbvpv$i;gRvaU& z7_B#N6x;i;Xi)!PK5?>H2jfW_w(($Zn(9%Kg(WoL96NcWY30>V8WJ){;Cmem!H945 zD1K{!7i)|W)n{O(Qln>+R3;EgJ7}ZaP1S5ehA5AFP?1OwFXUPn%hvOIt>=BM`geN5JLBlW&^%0CO6r+Z{tC`A>TdZjWIHt@Lf#w zY9PR(EfpQ;6A=2J5&>VtUi@wnEsADQ-)GSMxjfCAhC+NW>-)!OlZov7_o1||llh#E z^A7?cqF@$9vi7HoDT`!BPmiH~w^-T_?dg@#?h*AijHoE~{STS+@rx|&KpeTNGW$mh z={DyY67P5-1{1ByB@)dSP%egPp=z?sJ3CDm^>#@~h#>9jd=ORnVpe)4mTzrC0~$L! z6;xM(_M*}yQE3kQ{@kjO7c%W3!u`Op zGckwd{v12*UJz~W(toSY_sK3?If6^4ZMWW~$U71ii#{B#LjsQKK;+rsLj-)1>xzJf z5QoTTkr|>KEy1q|JO6V8DPVPfY1BP)2AD0-jlW%ByLBP8Xy1zb4F7a#ePtpmRtAE< zxiXL8(AmZ!-m}*K5%@O1e~Dp5zl2)rn7}>}!cvpH5$;lGfu`kXO7mnM#rE+S)XZun zgXQe{FD=@n0I3+0BtSLefM^A9xYn7j=@?VO4wO0OuqaIB}eEH4~BED>3V&T3f?AE!^#5Vx! zD3SJ~^NpnYnyOE3B34qBKk)N)X%w9~hSv|Ewq{1F2@w2D6(XJ#yIiDGY*%jb&cjJ8 zUw1F@Z8Hu9;>r}PIBoh^?4$B>Od186ev`Mqk3=DbR{nl*wa>0vZE=U7@PMdU$j=A6#L|!RvuE;`pO{M9|DgeajP4K7N3E#KGE13Q` zniuyaq0v8`0r9)G3+g8W3CNa3>nyl)l;*L1zc(s819Eisl@73KgFvSF!u+xr*2~Vm zgT>g==bb%G`-uwZ2(e?pA;(@v$&CXx0P*Lv<%vFgVP402&|dcGlBN(HE2?SZ{O9z& z4Y=T+g4+cC8R?%XD$ek~SEQ5u``iZqSF0HM1A$eg5)pPZowd3cma^Co_M^ppfbnk`|NmTcmtHE({@bJIG8%@F?DmP;zN$my8NkN8d!)TL;O=mqnU*Z89Pb>MQW5W(u4J$e;nvgQAZZ> zmjk*~3dmkEQ|RB=ZZ%9L*e>J@=&)?95RkomwMZ>mVIf)_FxE_TXwgP1+mK<7(Y{9oqIBuDrV!gQukm3QNX$r0 zx%QW)OLw&_);-bd3UavoggjtsQS#7KUMhA53}b&F4~H#Q@T7tlwINYfD7lTHJ_;DO zqW3rCd)ttf4?UxX=yrkGX>U;{4~OuW1^ zidUSVk{1YcQ{zlboVf!Ndy$FqGm;6{*&D3$jbhunTj+e;7OKXAt&g(M<$w$YXi*l* zYqikT0;$_Vm#e(nLUEn=f6hW*20!F*^$`}@71XV1{}l^eY*OETU$G zR`X0+?L7+AP*NZS2kHVorxDjy#`ju zz|RpYQ;1naJ>zJM0jkg+EsMp4NW!uyP+hH#9IhBal+%_fnmJqvDxY$VZT&MmClK1A zPBVa0m|sO9%&#If_MxeIg@D`$9|7*jY3rk$a*F80Y18AZ)NA~}qcr>xbXrbZxT@u+ zNJv+CP32QXe#+7jBAwx%c?)GU!$0O0Ml41rh_gKgP<{>hNiWj2Q1)x2YdY8{^jJey zd4dut3}gMlqJB)x`U37(170BT1PXWv)!ycJ`Hu=hCQk3T-5Lh|=YwBvwb*U>J z%g=k0(C`eSvdZRMM=d+b7hgx^G%A3~h>Qs3OqYcv1=ltH@dgrB*y%5Hp~t$;r834f z^6IILJb~6})3uSK@=_ZPmo(!kwi;S#TB}-c1p*|Cr4Fd4{&%Dq*(#({I8jLFp9eqx zAof9N!Pvu}JBZpY?W#J6DwFvR)j`yH2~a_lzA$wr?vrq}spU-EE%LnJFb&RJk4~?o zk5D-3BnX6WFH`Yexr|O6Y9$#$28ejbQKF)l!~%gScj*L~uF1Q_5Bx~N`BoG?IQzA9$?btOw+>eG9mK8wPrN>3Nz2sPpdWTd@y9xGvAT$u=S#@5h zu`ZD;Wr}j_|2J?NcV=m|lyb@Tp)xW{94yk@r4P$=ja;&UGZ1-)OF24HDH<9XksV71 zhpUlvsDT7bUB_1SjY|7O&>`0b_Hwy40QV`-hLEF*4mpuK6Q!NzE^Vts%RhXS+W5>} zBrp(TOvKv&1-p6wHNJHh3GciecaKU07O^(cBPu^3{_R2>4%coeRzp3cns0C69U<0) zJZFJdINKiK-M0WIl4|l^5r~c4>iEAMiL35sCHZA?SXs0`g!4mZHYAoGtV1H;{0XKW zI&>Pp)s2J}1^`w1svcMQ7*`vy=P4dP5!k;M*z|2zr%hAb%n`zI+Rlhc1wu{<50X-F z+D=J$P#*z+HL%D-f4tP6gmssGtT|}|I#@4;cE;s|16UXTI7(zUU97FpVT*E1)i2#q za^@<(;Sc*uviodR4<;i)21dtopt41i-Rp2S`O_8oQfS~oOzg;EsV}GQ$WEbLH3@kl zr6D9v(CBbU2AY$MJ1{6a?qc0Zu>oq!@DmJTKGHf^fIZ7EbVUJR!KiG705+&3=YVbw z6j-!}u^h}umo&WtA-bf+x~Wz|_{;!UF=a@)U}Ek- zk1iMn!`L90LV;d0NT#EJ+(|OoR*9gdVA_dxIs;=t@+f>{1pm=ZFWD-pLD(b-?qSic z{I?ofv`dH@2Q>e>9*O0nZqmR(x+576gUnG)bFPhN- zjlkVsmvorAj2*55KJ)?7h#y$uX>k-00 zqeNk-xjH!(>A>9qsU3?p6>9+Hf7?##&E0U4P^-Pn(-|B6kM7-)P&6hME!vA=Y2g|CrXAr1mz^q!uXMO<+lClP(B$ zNi1m3nYg%+(}S1|eMa(%A`&S$cyucNp~%2NBf&v`#X%p%!P|m^NkKx}S{9MpWp|dg zn}cN_y>p?~7!##R){RYICF{^{S<&q%`i-4c+}1_ied3m+${a>K->VG_KLJ9hk39JPDD}oJzPBjU7x1A>~QG#v^rqT%fr*77t2nO0J22vCQ zj|+nDw!~1mm}XtN^PbS$VYZ9ng5G%fN&Hg+gt{MJzkxur{xrG*7 z+nL8G2$lbSv)?Y9sEl!(HWimH)#K7TZ}tabFy*w#pxxn$xyB|;4<~*2xlq!ZuNXrD z`PsdsPE*)eu$NyEt~jesNsX`?!}))--G7H5%%$XQlILHYjR?J{*r7JD)i@&o5_hrI z7aL|4n9fOT9-_+;3URnngvQ}qT;z>o34>ygn5q{JTXX?5yn&RXTEDqc`Pbp3QD2mc zPTUOtLuzrqU!`*GHN(G5<=3lpb&W1BTo=orX2XRZE+{=bQbP|oY4e-_8r)ivBZJ0p zkX3@=@Y=al2A4DZSKq?fXNLdcTZEn45zRYCkU$!Ki=W(28W)x;Wj!N}-fisCs>Z>A zl{~mwEM~kJ{&Q98Q0XLI5~;D_1Yi`m z(qn)&j6MdNbb1H`-<1t60X))pt)Gtqtu*HQ_X-TPfZnuqfJA&0>cI(rA_b`SF@Ldv@9AG9@k!WL*?ax zg}v;!%HI;6-P2>c1NTU)w=hG`a-&DT+(RJHLo9TbbASNdsp=sadgd>|8Q12~KYCtz z^fd7JwR!Yy&$~VP#D$RgTaW&?o?AwwHH|q(7<08z^TWHm!}x_r5))~(yZvCW#_KqF zyh{{`F5GXrf0zlng{u!j&<@vrnU>1Q0ZxSF_%20tL0k_C#LYdtkc3VR&H0oG-$1}; zBx5&{q2eYm0RD9p2`ao|YJ|JNj*@+fh~0_^84v#xA_7fgs;7yFG7}Nwqk)J7Q=^th zgloI#T;Irbl$VLTk)zdj@B~|Mvv9+DMf_^nPI)BV@=#*wvfma$q-b)jM92DsD5qQJ zQr#oS2{9Pu?mqqY6T_cxf0TsqbJIvXA9e<2!mTbM&b<8!zQajyxg4-G?>4V^l!OHd z|4=4891az6z8%W@$C88~#BRJ-5YFozr;&w2#jvrLtq{yuv>|^p4&}z$oyXz)I}F2g z!H#hlw#8u>QcGkNr^exPP{HXh8yX`kzvporrpw6cKWmKRP*!$FRx+=z%l_vgD~0#} z|H$e!P`ks`M@349X znl>r1x!nZaB(55jY7MUDBN47Z(YezmHS8$& z6L}*?SK#;uPs`2AEDAosu|ZSBU-7UIM~TE&YjCwdbga*b{|~{{je07$+7BC6_VNpG zcn+(f|9)^4^n+jm7C|DlXy5aT@C0^Ob=dQO-vyk{oHlt7=XgLYyqk=DWS=Y!N)g3bL~h~3GcgLDs^G9h zfu9?mF7hE{E=1mLICh%=dDt|$$~ym&K=oT>M^3;9n=9IgeeNT^eE2emolRhQM~8gG zZ?+}TbVW9gYDXd(OBPVxR|~MO-GVmE|H-r3k$C#fI6k`_SxEIq1vVpEHN&FSt49S& zOknk>09nT;wukPl-Bq{Mj=tQR#JJ}C;RI+*Oyj#G3XiqZe;l@0v16=N#i|9db z_`_c7Me^YtU@w2B2`;afCI1V-E?FJr7K10WFdXrR-KJ-wx)Ox>Ib1RPqYmU=y1Fsm zl(&vHpWYi@JtU%)FmkvJMWjvwtrUhTYH8g-c*Mfeyx z8mp1^!KQK8Qt7_534iaN>Tx)O9lFx8>#RG)*OG*SZj{IGJaPV7=LAI zoTZ5N?(wI?&Erppr;GX_q!{)La7;+Jd;G2T9Df^+dup_;pSX!*U2lS`0r)(hl?Dbg zY8Wq0BM}kq0rvqM!8ly2s|VowkMW~vAmP$S`K>fEhHiytm*GgoiD(T&LD?srb{rnL zpivFF3I)p916P%wbtT=ZO=7f(CY{zC6Wndw>1fpHC;R z-X*CvYC8{?=V}whp*CmGj-KHkcO$*Yt30GT=^cL0DsX6P`7wCcHXZi=}6Umu%rt@D<1rbtqE!M zM))z{n+LWb!M^gw*kbP0i*z6l^Lu)c*up%k`yAJzbr+QC7hCjIW)=Zf;im_kjv!zK zer^LkqYN8oQH1Lghz^et@DNg{By>g8hjSXW=Ugt&@j~jXrZ{zl)agROr$RcNVvCSE znG{Vwq|Vdu1Pi7bMY2Qc>>>Eyf86=ipDkXvB-#j~mG=KCL#00dfV9hp1 z(&|!SjBUBf%liSaeXsKRq}T_W!z3s3#)~T8$KirSE+&9~4*w+s*5?vk7i$O-T+8(Z zi9XUAB}7qk!63`CReSyPUtbScG@EE=RB-c~;0Q~lNF97hZ}L1{EN%^k^3Huo5;@Pu z_aRj+jtRcd3J<`es`m27#kQoqO!5u40YpB89Oe(*OCBJ%_{Mul2iosZe)3)t7iRwk z0=BYL5j$r2?WH#4x%?Dw+?PD(cRd%)`pQ-QW?zWrz`hwYlaOc^&NZh56Grak{<&0c zh*n8?KrfQi?V=#iSPzFk1Vq(B$oWel{K6~ylLzRtk8q#+$Uw4>XWvKS3x7L_LYOXw zcb4A)DFoMkfm5Ghoi?Qjmz;SWL78X>U?^=xT9YPO9~IO7FKMc3B`i62%_y<`n7cGb zq_7eYsryQl?3iaBflGaoZ5h{M7q-9bB2pL^To)9!0MD?>p4P}qfVoS{ZnFtv!ueAJ zNMIq}Cq;~pJc5=`AcO)|B+}aMr4GhOp-jj?Jo<^}YR1Un0mQQ*N8%}!s}YE$MPB#Y zVs$c3c&r$K2?^*0TG0a-%-@ZO;Bw3L0VFv{dR6y{?J0iG{bW)H^TSh#fJ1kCa5qE= zRB9G(7OVUjUUv#apo_2at)V0iEcW^|VyBtcSkk4?zzGn=*vq6t%kuk_@?l{ll_oUg zX;ow)`H|0hfJ7D+t1xDcu$ks$BnW!F@DiTa&2%sFYAs#@w+*I?_L0^z!uj0Ui^%rX zUW7M#klf9`-$nwXQ{lNl2fH>hLbxNdxktftLB(p+-qH zEp_4FSY&A~_HI6U5$#xQ`KWe}r`Xi4Wfj%=LW)m|I&0*zW!(*uICF zG|`ByWjRn4YasJ+1cV!;`z8V!R7)3(YzqK<44Uo_fVi7yjM_~%8Fi}2SIy<~wvZw7ST&fV%B646?-}SpnbW3EF=)P{1tViO_TGY{Ki0AW8le<7K?^c@ti|1A=RJKw37Q=Z_$94Vrxo zo_2+B5pV!~f|rgU@g3#VI~L|9^hFq`;6DzRBvaqG1oi|Q7OjDBS+Kdly>eiV*Dt|6 ze9Y~|aY3!thWDGm^1>78%Qxo0+OXkZ=&3|L_~dZOCtYv~fT_h}Z8&{AKc7S53j2)4 z%UbdT&0aP~h`^%Fk#ml^jtP8StPhC5A)E}6s#AYq8j&4GTA2XVoJM4M zwnE@2ksP^$(Wez5WqkZdgD!ndO4Ap0)C5~4O+>*tav@*Z!MOCk-6y1T~nfw>TT z))i_C7GkxR$wzlAS}td~q;*R1SEy_Aqu>8hQ?}&5eG#w4HL+EtZUY|sqE@5(%mh|O zcaSd_MWS2qL1=XHQ7F)%psF^bgBL!Gf}rsbtoiJ&35xhUk;0o_q|K@Qi{|8Ofd7>W ze^x5IlLkB7NrN4Q4P;v-f|@G4TUVi|=N43x>qbGjOcK#Gy4D0&lH$C}7+9v~4C2Gb zcr4T39mf}rfq_^qgd(r1*vqbnHG)OEsRp7nvzh}@+OylG$h<{6s$7Z;eD&+c7VQ~n z1j=j;_zIPex)Z{WgtYDD4-0}U@QMJGQqA!(T?j4G`m12Tv)mY_Z4l+vVHky_z#Kqm zc9LjCQ(!DYC@&BjZ$plLmY*L>;-bHR^4jjsWWd%2EOOp zBapinF%Wq^N(RAp$CK|8J8wIVgp*GEzHzY8F78^4B8T|(aU_|{;dhNE-Qvx+`(E|v zBt=b`7x?)1$w2r?Y+UXAU0SZZ0B|J$#di-zA?YL!wH2I!lvxy|5ir7Rpq6PShOu7?`cbTlBnBS zrtl!1oB+??te317m-#CdR$D8j#eIalxRygJ; z9CIWN^EuoJ-fl9i63y3`-sMv#lX$E75TNIyykatm>!5BQ33Ep|zK>nHbjwavMyFf0 zZiLmVN4ECja{lirVA+2B#1!4KVYlXSGO*BBnS*}NY`KFu=u>y47^F4LK`;ManZp%1 zh{3VV0lIZ+bzh2H96+^(sKX$m>)E?pxSp64VGk0Ke&T`+Us#R^Vf&|lBuOcp4mr0$ zNTIlWkId`c!;>b0tUa;!3SsKUJqANDxd+u=wR8I%c&iFvK;Lscgbb0lVQOJ;CgN8hG@yT!kU9fvjA@_0LHhuj2qm^dMj6 zsP+q?{Hy~U(QZIL@hB|L`X3~IHSI5tSIi(uHQdm95LY=|I(OziHGY>9+)!Qqu2Xhb ze2_uN8@oF#+MDAIUGd4y4Q}XTVLuYF z(eA3AmUh<~3=_8((L{`Pw;saJYP;*;fZX5P9S9hH?ngLJ@sDPaXKFa243wyP@DwIQ zIfhD))$WM;^F6a`aYStej{UN&YoEe#sCGvLb6jC9j;IM=R#=N8a*gHh71rX2nt2$) zYGr)7Bhn2+OtGzbKrGx%o;-&vC8PMwIl6_5%Zvl>=_}-9FJCLjhUXTg^kKb)zpCCU zZ7)-J356(c?h~u|@N*qtlkC12aUcpufvx6|Fl+H=5NS`6wQ+)dFoqwzLPEV8eh!Zk zr27WjMnDBz>G&ghL&fni_{e{Dq0$V82Bb&wiyLqHz&|tY$ zC~9G)RtMj|AyxtNBw*4N$XM7?^D(|<1#L{tNc>WT2 zbMn|ReBlz=dKPW$Jf~&K{1AOCCz|up&t9j1IQSl_7wu-cb%ipD|;1w6)%D7}28MZ_SX42$7B89ub zq8vrt{Xu?f6*z!Eeh(-2w@eoW&NZ1L#o!u$gFvEPAvHF(+sBP0Qqa*LjT1 zFLQZuWAJPND~TU1hZ{`AWI%Nv%Mn>E2K=N6t~y!Bj}${E_h<4VZm?kbN-j@&0fyAG z*?iy&fL?7~J!&FVd6!WputGk9*IN(B6EbLzeOrC8T$Q#o&o7+AX!PD&TjQ!i|j`+*wK-)&kQcZ#l(>XTYgM;s(;D z&ASk=RN)l?_`%k`h*@EAAqJ>1oWS?cpzD)&GJJcC!0IXd#SNq*xyes&02k68T-rvm zO22{8QUwVvi5!E3Jm3=!4{IPl2Cq}x2nXWRMY(hK)Z*_o<>!{l13N7O3*lWjSqrBEQQ=;=!32y-5gZC(nEFuyhlNwlA;s zv@tTgTP^SlU9-bwec0F*=urf70Ifw!6ZMVq-E#xu=>qQDOv>H26Uy*}!i%5XLK2b# zCo1Xy1KLc%H_)Q`picJSKA+6tAC-|t$qA-LV?7!vKT>_Dna+n+kVe*YQ={SE@Pid_ z=s2OA_yr9%6=v~|%i%EbMg^1=n9BO|kS$n-?G~HLdhl#0>wrAryZ_dkiaU7_dh7~R z)7;!0;?6BV=x$S^*58N|tDr-oy8FcH82@?;>6pCOG!SAv`lwxkLF-M8!uiA($^FT@ zP2hlkfGhcssgajQqdREhjH%JJlX$2&AXyvlX%FY|g#PdBA>7pHv`3@bDF{k2H9F2e zt^l(S^A#4R^9+TkY7T4pNSdXgV32SY|< zweB+&mY(FZ9|E`7=_Qhwe9TnHJxHlZ|In9-Ey>iT$fM02$oHGzsl^47{2MQmIzgtQ znMUeUO@&iV^3W}K!Qd5AC(u+jj-S{LI>|GEhkMXhlPBRo=9n5~c{I8MQ>#sl`Wtkz z-Bi}Y$kl#RVJF2EdJyX=Q(z8I{+Mr!T1d zb~SlkQF;A%S`)q--b$~^{Zw8ZPrCwDez_`_(^vKB^xf6x<@)io6q@^ZTF#U1993w~gj#nWLPvO^JC67}5Ao_HUT*0V=XefTZ1a4&<*+H6P)g7dYfAu=?j}FX+ zleJCi9$R^VB2dnaA*40`ZYOC?^9QoD=R$c)crO-BzmI3^f~#h2`S@L=MOgd$aF&-F zG(ewVbelbzzqku7s1^?8=Xb$*%Ss4k?d99WHb_>T1Y!eE-5?MBH8h49?e5)x>5R!! z%lLONpR${{{F)Dh7{pK0_}W7E?Kt0xVKT&c=rve@*KGS|J$qme0t{vkS(0qNoHh_}KpoMMemM>HjMVO4ro5CEE-$6g0@!Ju zMsn!>t9UD|!E>LW`R*5Ov+6A1L&Lz_^h;^M{M{-z=eckY@%IsRkj6I924h4tb$D+V zue*=Lb~po-vV0e*-D3H;n;!W!C$HS7?fAM&*ifFkk0jR_is2^m&7a>#T8A08i!9o` z&{h^Uev3pm8iP5o*jLrgW4y>?TP$udLZE`rbx67Ep>XwG3Ka^w68IYs(hdm})oMn* zjdZM{yg6wI(p+ETB3_rUuu5vt{nGz8+@{)tvR^{ z7Fioo`C{f;kP2cVtpS2K&vM***L#!g@sWl(P}3sr#%kJF$RoAB{HM1`P|y)U`D9r9 zprOD=IC$fCNPM>gq7RF9T$qo!kI3*TLK~iNEj==PK(&^hc!$K=eq97kZ7v{&pK;Ir zKMPq><2d@zV)2b!`u0MW-#Ce`UC5LEO(J6bMCW_L^!M&a?cjY9pdAL|U_Soeu#@4( z*}uu88sp$!V3!V;6oP($>>Q`xeuZ5DJUC9rgJTDIja%N+x3ov$Zdza+*_p!?$Uk}y z23ub32gu1DounwAl7k1xUy@0@*M511Qna5;;Ex=IOKR2+$b&UbYV5=Lv=2y9jQPO$ zI~YaIrPWx~sZcuq5BwY@F=8AV$KBV5#SWs^r?rf`4?f0mmmu2w)A@%#{282Y2k?oX>4F6m7H_cR&PzRMCrt|FbXH zE1aMDiUilVE>RA}j*@i27Z{dI?=%Kq;#ptUG6p$c`E@O0FmxC{_;oE~@Hy`!yG=*be9Z* z?ct&vZnFx^@R4|xUo7)uOBpY{&?Uz8r;Aek9B6u5q*Vd_4xDOkXZ5)-}4O# zOTPFaL~{@Y)CYtX?Gb_2zUhXjt8Y(Z)K~8#++%%|H$DZ2JMbp=QzY_k=h6aE4?_(x zLxT^)pJRjKzlY2_m+GrOxVLqRjEGtC783RJ%mAX&Z* zB$6fk=Wj_=eG~z3DMCD0QQ=#=)ys0TAZo%`32R_lHAOO2CGS*%yOm~?YxfofxoSHW zKdpy9{gqt$B~<;1pXTIG5mf3zbZposqlwM?rL!-DxX1X|N0(;x1VY@1HvH1zeT0I! z$aqUF<**SOFWb2{U?qaFzzs5laQr8^o5X6-qQyT0JUasaRo&5L86BDkiHw)u6w^D> z5u*8g_5|O1w|6LgcOEbL9(2^6-}fa6^Vv90)86&vUwuy!3k%_Y{f35qBM5H%NZqT` zGW}}+s0{q+!rk^PG9mLKg=H3UJqUJ2uq4ZCk080KA(p}t9j-~@5AMwg{Ml{V6EXA( z_uWE=Ck+t^Z!`$Td&vQz61!53qg1LY#4A~1*>FgdJNpKTG&fOwsB4Cwgm=~O;|*FYDyBnN@a(L!)SJZFVAZ7@E@Aq1I2=Qpph7Z0-g6X2j zUHKPDF`>-{@cMtiasAK%eD)u3C^L8f9&9(^IZqRBe*6!zo=%P7voFKx@x*t*WRwF$ z_Yu;953dVf4$3pZD`b6=%THg1gU6P=xX+(tARQHluQaed0JZh|A^Iv3u}zEPMR-Qt z53$XaW`uD4bJ!+uV3<78?q-5FjglWQ?aU*uK91fL#{-(DgX ze&i}l$Ori!S4lE$GnmI+0|lK@hxxz#+mqC%;`rWH-l2TO4S2?CO&qVd23LT7{5OB^ z8XT{0=clg$j^M#O^g7^>y0Cs`LZNee&;*y{(+~d5Z+X#B`c%AB)jOtYy6pGzdN+XX zMZDDwa=$LxkZq>gi}CSu*81Lt)-qFx?5<;2r4$!Q^J1E1lEPU z!UR{sewr`12?jH`C*O1vMwM<5b4;~$5jjn8)#)@7ST~4CCb+6T!35T69BYD?#Pj+f zc`}lpy9Gqv)sxr14QebJ#4|9J>I}Kh)XFX4KBf}cJ?&vqXctp8U7@KfyU=J#dafK! z-I8fxsyr}33?cqGg}YI*gHF+=I*%oIs&JW7q0LlJi6_Ja*2NQOf-4o)qGNHQ*9+(>$@hn>=d3-zv)H8sz>JQrdmpo-a7!!3eJS{0&nU~X7j1uZb4Z~O^x&} zi%oDPrsquHJLz_Xsh$$k(NLev{YHZDg4TQ! zys$ApAL|_!WCHuQz!&RVN14Dyjd@xV@30mIu%pENjNyxKdzuv7eVPr`$veDwvR5c6 z<=MVKYGe;S+ZRY}(w`sorAhSt2XUs2;7$DKgXAio>PM4<%1rCJ34Dhi{gLK178kjE z>L3Ag`IhIrY&^n?`dPgNKsrIg?06dqGEAEDTgVULT{FSu6)yV6+kBuujk2bjirdTi zh@O3$7yE;|N##5Ifst3bix1%O3;whx?cP+pxaX)z1cRE%VBoL`uC#r?1n$>@S77Y$ zz6q`feEV(jg<$d|uNOcc!zbtiU|@g8*9Fkcd~$w$Q;_G@RjxHZMc5BvH`_M zhWN<_bQ9h6fRuVkARR|L&E)liXdL+uZx=+9Y4;wx#spCxQXS&_`j)3+i(BvkD}ch`6qgEKZ75on?<#1fLtEeH!jZEPigK2!wK9hFG@)N;yvu*7x4ER@zeI(;X zUJ+0SZ@s55F!zSQJXAe6Cr30$1ViHngw2BD=V77`*V@=@KTX=fkUdsE9 zG}Ti|$bL&&N!dP6<5E@vuaU_Pqw(sDvI#E>qc>>kEV&d+oXPiw(JKM{lU&oqiXsG79B*9kYE&2ponavyVZvSW1kri!e6=s3p3K(wB__EXs__KU7~1Le zLkJg3<`5Dl-m+u-+Q4q;JcL{nFYpP07oXtDFN9nXJ0~F|I8}oUEC8(2tRnpnX(-Ys zNr*_}NvKF0lQ5COwGl|O$YZ=;JdGWdauGzn5g_n`O=v-VRj$le&6g>1_suCcclNTj zqMp4xMWhz(q!3n?&j>1>6>!ORxF$>isj&4C!R^+;0&mhLDcumCbRu-PSwAtA(uQ}G z2!uKzzI@VE?}j{L9Q8{-3KKheEnN$%O%@|kPl?OMB<0lxDa#h(hV|Qv;HP) zxjQ@|^H1QmL{SG6tX7H*>I&SK4*nBM93`25@_=zPys)ap;e{6jVOa!s8RaT#SB%@yI1|r^a(stBnxeDQDalCRV={f@ zkWBsei?rIr*UP+Pqb!GA3{mbVmF*oR5^rw9r89+6a@R~(%DVD94^E`nca7Vp08-oV zvO<-YB6NQX4GLdbuF7tn88ygt6t<8J zs#eL=7qp5tc2fFGlzPV3>tmnDXH&svpR0%=tIkeelqh?dA@#4z z&4{;?z?)vE5Wgf48xf(R;e1mV5E9b(FWm}WK|qh7yOrh2tvsdN%3_hiqgEny_mc>Y z4>enY&7~8Vqg>6og{J^(G%lGFklW0a=t1!?k(%g%%ZR_0+cunSel4zLqk3B$wVbkPO^?=v7z48Gs z>rPVz`CwP!NGNyn0!E8obF$z>DDN(0p(I^;OINBIR8^vavE3=5wA$ws-QS@OTK;UD zTfPqx%Cnct>pvFl{aZYuEpYpg;&zB9w=``pPnrjtJ8zk|(b;XUvpdgJL9+XBl8Ie$ z$;iO&pIwmMV}dIENqmd;q+mD8CmO!@?rE#KFKLhs8#nm@248`Ys{ZB|Ag+ly}op^LvCSAjbTB;R->_a-|n|16XidI-u@$MNKOcHLvWER?^PY znNH0Xotn#ULbrxdBdNK+#6*qw_J+Yq#tUk;%L@~(GLfQjV_1m##vi^E5q-BstIwV7 zXzT-d=p;6ZGBB~)M+zeG`o=gyCa3`-?=-<@W`q$n_o>qA8r?vm(caO7Fw#YA7Ly1b zRDNNG5`pbK5CPI$`-7h&CYeN$aLLn3ItfvvTtdF!P+6oF?VFpJ&+-{50w+hAj(Hz2< znv>1zJ#kVE6m(?OY3L&+)hFOQzX1 z%c9X48g@QU?_ADc#%5c4VCR}@mL@vKaf~ghI?8swb@=P4)RuDvf^o-YGbysJ5$ACv zrR;{l0q5c(g%`&CE^rz~%mobYb(Yqg`JHcl$2+|661Fb6q*`APsiRc2ZYwFu@=EZ* zbwgD{Js&6X4ws|`&FJ&)V9{VDVtt{>sSsX$C8)siLr|`JvJh>7P(R$J$<%zCLcpSa zXqPSFe{6t5MQ?zJQBM|alxV1%qeUB8oyV}%qQUD0I?@rOj1TQZvkI$6QLO9$y%K>B z5}`qFsTW1`8rb^?Mz5Wvrpf_2tThc!7+r<80`LV>fL)op(ND?{2WE-`_rM}1#kBe@ zh51Kc{brH(C^`kWX)0)NY?d_YlQS+xkO$p{blP<#g^(q+#i2E`yDZL@d$>PTw!rD)S6R0^fF*^tmov#(M5|1)RCe zk9VfwbeJD6?nyhv>6>kM4uKSfd)It#_}K1vlGdzngtu@6^AMwq(ZD@xj;123O=^wp z(IKVC*tU}#+s?$A;|wM4Tq=V~-4~!iYp`E%$2Ds#$q_dD(8tu@L?T1juB`rOK zv{#=}l&)B}HaHrVzDBLu#R`_s>Ovdyz^*hPVNKUsq@^q}#COjP)P`dd*mcjYbc{_} zntmq-hdF8wm*f8@R=;(sSHFBqI?ZV#MKQ&;PZ_elr2U(vuT>4G>i3@ld*3I*f+0pO zaEDC%99={+wZM&0vG_P4tSq0?;&wom?=p%$N*^49Kv=NGf?>N<*toucH4gI_UT+)? zE6fG+vb#*XE+uj_hR`4wU1*fb!@<2R%;(zNyDpe_Cd#V>ljh=16^^J3(avbL`%J4P zwJ{T_$>G4uXd-s+9~_1-bGS-d~Umw&o5+&7gkFz zvnz(D^`XrYr8+EHvY;%>r$WR&j#RWM2u`Y3^cFAvcn_LX7$yZb7pD-w1UZidb!DaoWT=%0@?L{>W7y3exxhiVXFM%0F*#|s8ZO-T@taR}* zYweCTQ%)x~H4(V_+%!5?aIqKp@t!oi#*NNF-Ndy7Hs^-8l@M8HwIp>!0;iYZReMqZ z+P^@MF;J34&R!Q@*QGcDg5-Q92MBu2vwi={=GKTA=bzeKTcc!B(KnW;jzPf6$h4Ni z#?plZ;Ce4yKI}zf`aBP07+WXY@|>t9(GQ%Q655arAA=gBo~Md4uNpZBJDR1Gz?DP+;)OW=`5{Nd7Q6r>hyo*+`sXZiFO?~@PleVp>M z57LC{Ga(H{U>A+W0KB`Y{07H$6s-ZS&V>40Mz~AX$LRvUcW4Yesyd;_){EZZ6iB4z zsMMnMz3!pU)33`_W!@e1c>>_#T{Z=Gg$V7bAQY{#e_gR9ReM%;~MQYLDJ(Nb9-uSv) z=O>u@&~191BEt65Ykwt!)D$li1-VuzGDz$`BKq z;f4hy%Djo_G)62K9j@?8{H&cucw4lCnh5`Uoi;4aEt-0VRrOS-hg@<5S5JKqHX(t! zy&Dcz3SYmsmawaO6u)xKqaFBzbO6AuK2LlAM^EoeltFTJKLAeqTP&oZ*~_@-)E+2iXApSdIEPM>`V_3HaXx)4W+B4J=#^o*cd+B{)Edf8P<_ z@i{|}%w&-2K9rCWbstLT5t$4o;ALl`WBuVL_%Mme4_1+$ToCJD1cz65j#m}*saA5N zuM=U1QI*T}p>v#6B|MBHyf|z&E5w@0PZ#;x){$2(i*;n`d($6Nie0dT*{Tkmp4NjUXI`Wg#sEzM_ zhz18*?~@&2^l8!V_w3-X3DGMN@_yq16I^zX@;-tMzAGI!JCuE)R+ocT9VLC#k|X^h zU)!EUG_z=@iIH84)<#&ky=;^k-pSX5chg_W^)hy2n5ot1-f9BtqkFT7s?4j%*E-D5JqH=uqd(qVR8dU<6AUYU7kXJm2ZYtFF;P#T_$Pp9+^a6)gbkUHO%7d-!Hebph z-U{6bxIEy>ZgW(@aSFitaz`Y)&1VW8qu^zt_v|)@6g)w|v#1YqUWFUEb)@5pjo|rH zAlUw5x91>=@xyDp)=y1f`7X8IA0ybH)B=!;(Q;S8LDld8#UgdDC1F;tFlk!#9E2>tDZ1v*JqWMd|rJ@PP zSXu7gyMIdnaG8o4cjT$^>g985G+@m!SLzELn#VbHVeF@(h2xIv>Vv8rbO1j@;JL2; zP?e{PRIJO5=hU(93Anzl)^|_!WpqUKx_PdsC&pT5cs4OaYpQfmed*pL?Nv>A{xGn$ zJQG~`!^~Wh8p5x6T2)J7RWV{Nf~ZfVx>ey?s5KCzuazv?Cs(9J=#$g~re2jv^f!Uk zG?CuhM9hAZi3bW|4k;7gZ!&Rk82y)!7&=)RcgM%TxY1#l@9<9mIFcL+q+7J|D=1QA zML0dYD8;kal8EXJgK$1?Er}l{O~YVwYh^=WIXDNX2zR53Xdgth?ufGLA(aQu5Dx!V zJ*@Juu@lJu7*4ZsE92o2bPNr=$ln|R_t}7-vm;`~cSgePzhSgAUzobRe2z%r zDLf@|H3)y%<>^!OVC4rBT#mxl|3R=zkpirwV$g4x4!6MU1F@?L`cp4y?B<2&^!gw{ zeXkuQDZ{4LLLmPiWp4skRkb~i-?Ps-3Zw{EhARSsD55C>Dv~MTj15TXRh|ifQ>KP! zYF<%5Gow4SIdAM0>BnCbL(T4H~7Hl^Qu`ivP9t-scVn{r=wne#*^W zds=(#wbovH?cwaD-r*15f#q?tpBZO#Z;U@MVP?GU`EL_kV4Swcgz@FSyfI$EF}6sC zy)3D8fjd$5u0Zepz(-hu%Z}MjwY9XOwwl0(6;)+wyp)udhZQxGH!dF|uPnuHOydVY z@4F%z_aJjUAzdX1MQaYj<8wcjHy)tC>uwx*7iU%0%Xq-KaxF8en6uG5SqZTb{^_|x zf-G&>YdGX^h^!c&^Q4&CocK3!uHBdZ#YXwRII2%lDGW;m07ae~s`%!OwC;^%$nAU9{1Gd!hZm>`R<>1* z=lD(_dkZfgjng9iL(ngpS1a}q^R~gFWjM86@PqZsSVHl41-L!qaVVDRE?gwGXIgeh zs3dAJjd$o~{rQp3iO}>VR8o&99!`ELT!iav0v;9seNMB$xPzu{1)$+fjm+iUIxM?& z5W9tkaNC_5hP0HVvnvkhGlNCPWnvXn#EPrTyxOt6NZz(g9_p6&1wJ(i&9Ha|iz|K& zdyQ|*h>8OVSHf1VMXXpq#phsk6jsT#h;^`t&oRVFu0^b=5*{VOD!CT1-Y(+ufP|qR z@Hhb6K9jX87TjSt$Q&pn^mA0z^FhzH{*42Sap_JnzUS(w+AY&BnbHlk_Q~{frt~PP z4(s19(u=Ks$P7_lbTE#MI06lX4$2DA<--Au{fqpM`MB}2G%ASHqOFJ3#IN)srq-mh2u># z84aM_^4>+Ph})eM>X!dp6f>K=A2WQH_slk;tGJPqW`fK6F}It*xn21Ox|2;{aWkWL zB7rNhS^Uu!L!8O|a-|=QNP?JgD&z25G%UI}XB1IMa3}HfM2s8L6LpJz_*4`pT3+qj zQkkvgA?{OfxG{>JjhmIy8ot(SA;aA{wSyIYTmrE(g!pDkDavG08A|C(>RWXjSH?Ii zi*v1bb!5YQ*2(`K^m&_g(lJHoBr8hi&2*BR`ve{A__PfD<%SEcwJQ&q;6j@1$}|&P zaH-w(iQuSWE)FzWRHQIWcx{X)^^Dg>=u9#-<){+wU5A`)U1mX2nP|u`3*>n!N1r&t z*ODFclt_1#PvCGz`$+<$?4%W@3@IW*U=$Ctt;;Wqjgh; zC|QBj$*owgFGz<=h|7HsE3m+#k<2;MO!=AXr(<1=LZ~cvh@; z442cqou~;s);lL!^F5*2Ca`ch&6q*pN?s+`8~bsrJeNCtxZV(N3_B|KU#6TihQj3} z9DNk8z%ezlT;7cNpwJuese0t zOogAJ5fh2L^+1vlh3TH{l;Cm=Ru5EzD1l@8)8P5HOH4czz$OocGv}4atPx~*xX$Unr=Zj!ERkS0%$m6K-Wtena`kBCD88$;VaZ%|-EImn-CT=)DJ*rwQ zCyr7cy1B^PWlL(r2a8gAqKS)2g!9t&;b1pQBogLw3@33Aai3CSiFbZIkdQ z376_3sYb#@JBB;Cmo7%dknL@6dXLKf*5w(MA=b?%uyiNCMBqwZF_&$dX;h~3QHheH zV!QFEgv4=o@<$_uJNbi=-trb8MkM7C8j;!{UI!j{=Ap52wky}piE zTg>EMmKM@tQ$LIw#E+Wb(n6YR0)zA+RZB{6}8g_Jg(z#h~HAZx;dM-w?UY{H6= z4;{OB6z5L(q>yE$ti=8kPsO!&&s~)3NraQ>L_fFb)Q86%wOD%MV)RLgehwIJ!m!F? zBBZ^RBrHairkU~?mZ1qeGX@$;&;gumf*YnGfjv5IF?IY3Vu^FL?6?IUS;F!{#?d&- zS%gp-Oa1eO-d8Mz>8EN7-@v3)`V^vd}BpF6@ZL5=2A zyE2noy;OUbE)e+?3uhu~ikX6tbo^4+t^Pl;z8C$GEA2N2g~JoId6-#KoU z2OPyI$5FlioTvz){A%dbG=4QSF~LI>*_CA8jg}^7Z;l4-z((=AU~*D#e%+g?$Ha(t zKK?SnB~za_feohq!vq&ho$wohJ(xO+Y-$gteuFwzmCJ|MQJM93`N{*fJ8Yc21)CD* zhhUsWGX%TuSsCdd^b+&Jd9^*I;Esk@R}CJC2XSV~ZK^l1(!T|$2tE*qEQO!hb1dQy}(9FCKv zh&twCN&ID7kIM!mLh?4Uqq7jb?C3_BE=AFm9wo|0e=pOe$l|qVxcUUk7u>y=N0kE3|zQhrWAsk*ScE} zCr>sxEY`LGtL`AP;xI3lSNZ+r@_|=3_U+$HrmuS;k;&V0J)z*ix+RDXb)tP2TCh)g zXD}A4DdDv_wwChHv(*C3?x=EmRhA%Dj_QRXe^o(?{JEH)db11bedMWbxE_J{x9|eY zJF8f9bfZx5mD71K#7;V2a%J2C#=xi@G{y;RgfU93!mGw-lSzkOJ{n@uKUV^174`()4e zx9E92X7^;14xCMPi~LpfE%I-|{M6iigJIliHmtMQyete83su~-jAc58;W zSF=o?#+ir*dI<4LZLGI)w*2l2TW$prVvFd4K}|=s7zM{>w*?vcD_U{eDtOK4q7jGP zDusoO3v@Y08!sM+!>RZo(Q7cVibcg`6FDn|UFpufkn@f4PzRotYUa6ZV=1?>uSos{ z{5dwG6Yco3EHiC2rjfDF7AhH`R zIe8q}&&P8%&VCJtWDd{E{W{Nfg)OBF1ede%C<0fC+WG3s zWMW#0_*DT?+4x+e*|^=K!w`ST=(@!Q$JVfs)|-)bp@}%ZVvBj(78<0LCw$DMC25Nb zOr^i(r3+-~FyVDXB`3TU=dV&v&|4u%eU`_K%U=%H3qpo#R27R(A8WodBgF+=TMQ~sFw&|f(3QUDxN>D zcAo4&k8gPo2s3)h$?#Yj4*RZ3Q1jQ{U%x)rui_dE`+!A3o0nLCl}@gZE0!vw=U4E& zB|74#FwAsn4ohP{ya^4pEWB8d!Fb%qz0GL2-0#Ek)Tpt|fnr5*W7jhpFNsmym2MO9 zD(O0l#!FFN=}{tX?1C0Yj}QP?1#vv?cDWl3CrCKAWjq>8k#HgRZbZ^JJXkr%3*a;( zL$248hm@@~Sf$8W-~{lrD)mJBNj7!|u2Hc4KzGQ7}piCnU89#nkT1Qzz)ozn?i zDJVg8rVvFZxha##DVioJnsQT$t{n=k;w1$GGKhlP5(EV+`~FQvUC(LPNJ9|yZ@Uc* z1HZ$ZBRtzaj0cej<7F{);J5e-B^;qO9T-bustNND$$=I05j?NQM($9N`)8rE%Vn+ZVoD#)T2~$Wy{R zT;zveL@8sDH!uU+zmD{#wXS?TpVqptszQkKe+>6T}OTn1)RGR~H})@y zk=keii*FFmc!9u`yehu;k!A8DPa-l@OdN^ zvAiBU4kTR#pNV+wdN~2lH1)CkZ?T>=`nbr{8R;vZZvx9c7MS{IG4=5_-bWvfgQL>I z!u@8uz*n`k;$4o1vScN! zShx7{eU7}^HF8L*{vakX4nGBpZF|nH1SeA|8AILj8bvXmU=1Qy8paJ{&*gx3-8b3I zjoj>*)l|%IdQL^9zE38s5(!oNdEDXh#6KnB2L(JZipR69PYC$`yexVrp3watmqjVN zd2Xpxt-L9VBRZ4+5v&YEwd>t^8^-C_a{2a4wv_$oyC*95LB^rU{>BG84swQZPcr*2 zcpdC${R6IZ@Gvrb_Y&)LC%sGNA{$bzf@|^Yq&Fp;+Q)R)HJ#TaJW9gFay2`tPAQ-D zS1S9twGcGJJllobVW@hVrlsTPH4|8vXKC9BT*+(Z%48GmRZJ3b>i2viURABwqo~}( zL(X+H)8X-IacSY}!D0*b%fa3%q(X?-o%?R5d2l^1jjLfEx^1;hT(cT#w56@KkrRNZ ze<=q1t5`>soO85i>F2}-DZy~9?dRJS{;wjK>Z7022R^D|o#T4of+)DvFJ}m*TgD5m zFKCT%afo|(SViu1T_Lp6R{_Ago zl{WrCN%hGqB-wYu`MvJmUM9o}uo_m{OOEJSzyi)T@WO3^XW zRfkP(@e{bk;;3pA(^2JN9vU3$<_VN&-t8y(xbBGNX1=9Uw5ZqR(TO$ULO0?;(^N6A zlf-}yvX0?7jCH4O5$ghn+)3KoUQ|H$8l&*fy-;~p>6p@Vm5z;x#g_3ztmmD=+5J#n zwl(o3t=;!0ZeBQygFVG3v9v=z2z#R&iBIs-CuQkdxkty7V!}#wFSDi(q6z+HyTiGH z^IhIc%dK2r{V!WEhp&n)m|7Z=>PC(ba^6+38yq@N>;_*UPlfB$&pbRSPUr}&=sxvR z!TIy%g0l_#6%T4GF7jh^U_woUauy*DRcng-N;D`!Z3Qi<1hkGboqd4$u zJ7gb*hvPk44(VhSEKo>icJRlI?Y^(Dw1oO|$jMbA)$=6!Tq0NHZec=)89u>!Jl53} zALXh&2Mw>V*z`?%kZjf4d9J*wS{{0i@+PdE`2KV52-?Kc?Y@fzFU>JL%&_ZN(Wukl3ADF8^GN z5hvZh*YFOFV~aeHf3GpXQHaS7blm15-ky%zYp6!?O=L;quf*bJvn=g$`{L_{-0hoX zD*Zbzoh3`Rm2Pc8SYzGesEop`<~kOY@-XsQOu_Wo6c`f)J3m>MuTH%}2 zEoG;@cf4ecTj5VdJ4O zO^{(jTXZZb4RYQzj@EjiEpqD zt_`p>Ud+7#mLlUf-vC=IH^7>1GKJXq$Pv{Nu;H6eAt$lBMD3d@4ZZ=k`@FY0G_=Mf z8mY>C{E(7CP)E&f9`_`I&2raT``v+VmMlcFaKLUc!Ml)cp)KhBz!|lK zY%O&QcP4yVZiI~@q&L@#lU3EV0$GDQq%lS>|D~H0#Grbtcd4kC2zzT!+8XQRi_N*2 zCh8Zorybjb0(3lw&EpRbP>I%RH=QTuNh-xMR7EBFTpZP_MPgN{K&4VNL6Wgh=KJ<` zII$DA#Y%V%_qNzV85e|bZ;MTzhV@qNK1Dj{Jg~=qF$Syxt^4bEEM7{?-SXTsaHiK!iDEr zDhC_d7d>nfceAYYENsma^$$7fS-jR@-}|nHVKsTR6M0;>EIcJ@6(*XYOoEk3__!{e zDK&g5mtH|)OQ!PBh-Xb;;ZvD#n!q08UT-=hukytNKyd(0H zXFavzj6l{c=r7Kz+|JA4omd{~7I7vF7gBuqJj)sK{WP}g32#D2FSS!j_!x6YZYkOX zE$5J-f>Lrd^B~GJGBn>lr#~F>)t}zc)F)cyMDar!d9|nbxapSLC8co}ZOUGj(fNO4 zp5n~^k$GM^j>FCuY`E4#ga|owp-E;ES0W9Q*0?%4TH1@_WoLpJH)oJN#!B{xAH`=* z$N$`G`Jn=NVPj4pSABTgZA2ie`s&In*teIY}Jy zSx~owLr#;GHgVOjQmi&hCYUICTK0+Wcv6lw9tvB_O>wAS#=?DiOvOIo(Ip6aj}3#Yj!K(igT6a&Kwr{xuOr;O7!m8< z!Wpai8o{%*O?3D{I*Mp6LHXdTrS{aM`LuLZ0WY6z{cka5qYRhjxL}JEuUaTG91w9= zx=p5+$n=j)=}|JhRHnZ#)8!l=n84%47knIn^5fGE*PUEx4Z0dM5ZWy(JkH0(jj(~x zKAGNVN;eSNFVnx5=>nnF#W>(ZD#J(TNzw}LNpas2ZJjDO&HI%m<7Dk7&LHlSwc?v* zg<(-#*y&`gAGR~s4^P2kXtV>FAFwV~IvH*QsXSPy1Lzb)Ygy@Za*j{c{FN6C891f8OH3AprB zpe+iB1b;+)bzU*p8V_trfWM1J?O}qtrr9 zDWN*tsz+FDuCt>qiUC(4c*oBq0tV&EP3dL|K4VIc`iF^>Psv&^h^iy57FS(vTq1?PDNCVXeA6hW5emrm%RH29aOwm| zU$~E#FPv6FggE89HV~S9jDt0Ma91#|QsbHN8yh^-@ykn;8RvhlJq$07Vcg=oNFsmj zJi|!k)Wv7mWW1-O_DSBT+Xn5%>oraq;aLXw`##ozNt5&yQy*p5YfNC#^*bvGTuFH1 z8UTsgLXi8yt01}Dd5?v}-S);uJ*SmC(I@fniiPwDm_WophFZo%_yQ~5p;Zm+;C$5}LcZYuwBWUJ*$L3z+yBdAeVb%@E`0Z2 zHZ8E0canQprqi*Wr(oG1*i`0aev+e|u46CkSG>cc}% zj4tDu+8c4s!rO^+EE1K=;*@(_nyL1`sdm@H#nU|-oWrt%YeRLYPzVN!b1)56a;iq;Gd z*PgsIP8nlT$7MGsnz5hno(?J`{GizP?3BmL;XF`(4ROJ6(=|RHge~V8=lVUy!x?@{ zWxPaulxUIIv?7M48t4WdTs_G8YW!5l)iA{t#FxkNHibb3DEOQOG0c1BXEuV>U*ST~ z)9Pt$Mzx zC)59w@uq8hl3Y~65=wd=CA_z^*Y7njE zHXg#R)r!N0KH0o$7`uDFVxx{zJ+dESzfbl9=d28v_$8h_F*+meG|uq5%tvIB-)@fN zBEQ#UxJ`zYGJJuDbi|!T(z7!aXb9a%k&PaJthRX*r@N!Nf`@x=uay15TGq>DYZQWL zyTUv>evZ8>l+@$84XM?|$2HhdU$CIo1xdahIhVDatDr*kML&}upM zp)JN9&*F2EiE6w^hI1+>S({<_cq>O5{m;B2e6CDPrIl~WxOlG)9f~skZ!s0h=lFuz zCnlr&vl`S|d4du|I_V7k$OIOaXWDxN_Mls-X}7T~771OoTB_|*9+HL-mZ#WlwElUU z_o$VK(^JJi_926OxtIgCmGDrvg!Ad==34Re4bnZeV!0qdORZ>DiiwujxgHbh)>A8P zM*8fPGrwCaVs8d^w6WmH&~RJ{30RJq-jfe?7W!f0;*L?pIS9PD?h{)*hE8e== z#m1Lgrx}9c!%bPYz=-pQi~Pj7#6>Ovs=r-Ij8Kw`Q0LJ=FG9(o&~qS5XbIsV=*W#3 z-zt&uW{amgaDZhl5y%wfo+UaV zrI0b`N2H>xtPxq_-~ueL*0_W zjTf3@#AUaNj?mCn3k@VpJWRO5@@(-}Cb+milJL0+@lumbwvHpd`YH{kqq6iW-CoPR zo+7NVwg@!*_qyd%zR>qxTe#gF5!Px>c<*#icS&1rt#RA6&2bhL`yQ$S+D4|PJ(Y_y z*F(AZ(h@nWJF=VMR5Nrlk+&ijijLzR^xRyiJI=y8*Ye8tgp8y*ap$C-$LS0n&G!89 zwo}Jh>|l}a|L2m}V?}I(F+Z~(S;7Ue@LgL=oSMJ~&hERxYvC)uDCzc93Y;935;w(r zx$a&V3{mak)UeYOn_H zmUu>LA0~T(rC7X0U=MkoPGTW-8Zp-LF2pVcQY@xlEx-E{TjsC*X;Jc<%Le5g;Qx4v z!TbLYG5AX?N@!`%#o)DEZ0ZJLQ2js)F$hM9xsezwe}IdDk^@K1vk0r?EGD@gkBdN? z3v3~?T!6YOEIz8m6o#XOvcc)>sKi|753{(==1D67b9s`i={!VUWRWfAFB`AzGIvzq zDp-VaNhas7&gS_m(o}cjd8os>Tddn#QQb8sMV+;cJoLorAa4HNh^HUNk;B{R5|@ML z;p&^r*3C3=S$wE=*URBz-HtpCPk+nifOd`L!n{{l0NlNU`S_&cS~qXo{`3FW>b*FJ z4|QJcC%j?ZGLgqU5zgiND{@IEtp?BYz;EFOFdo+9d}#OW-oi%C@+vP3HCK6h`uY&B zAWK#d)1m^goh=FyP#V5Rq0pxTg%0_B_dyYNFz=0p4Ub-9GJXHVeHxQ`*o-@5lOKQ&D$oHc)A5R za_A%DwdaGbvJ=P;fy zel9`6lO;S#gwLS@#b34+Nr^v)Tqrwi=^`#oD919IlQ3U&@i>vN6zPvY<6Kv^JYw!x zYLjr0o-LOyj-^o&F4D87rI~9PZgb6lcJLe4h0@=kzct*t~5~ob+~IC+9mC0@eF@en*mM&(DQP94y++ z2Ha-jl}c{L$(w$}oD-?i+HhWJ-ZmQ#b-bWSzt%VhM8WC%SU2P4sa4g;MW`|9M@peX ztay2<)C8B#uE$JZ`8IKp2`ukyIjX_`N!%J65(Dv1Dq&qcy+2!#Aq@7?E!{W*+!g1A z-c(b?y<^3Tcey6GMDKnRctkAtH{%twaVEIHulQa9dx%sVlGJm83nPZ8O5h|!M=cMD z#I!E;>`O8B#nVx@1mm8Ly1v*uuXfP7$9h!D`Of8K7s7`O=O5ki%wh3RS)Ls8H)4#t zP8<`v??}NhcyJH~GBuXr95#iiU5ht23Dz+VDsPoW&0J1p{M@u)sdnu}ys)oiX=a3J zJYf-&tj#2Avp5d-MD()9{SpJwo6@zN({={A-yzOgy}Wi<13%N^&a6ZrjNDH)e8i?}A^ z7i9b@FRok8$@qC0|5L_K$@m{IxwYC`nG5Bu)!RDROpil-iYq8IT(~(Dtb7E&V2<$hYhrTkCnMy>*lZ zZ~LpZ&|@g0dDXKx#(A}3;g8EV_}yPkjIvCYej6kMv14nGQM4-|It*;5rn4D%CDmW; zqU?lM+Nm9SzsGA7Y=aZ8WRF+LOV0<12FtNk(9rJt8k}pVMl(sscEL!VwJz=NEx$2c>lrs-|Ge`*6;x-sX1>BeXJoA_9`zs~cH)1T@>!5IEHyJKMu4 z#-_6`%nDK$`n~PWd?rXepp1Y$!D?vSx5&-zA==aitFyEmqCV~T5VdpggDP@plxLt% zh#Gz0xqdV<=jF&W@zBt&!Ahe~7*?rU8c7zAS9|eq26(EZ-CTFJ;MJ(1yNJZQxtJR~ zYxntz*GIexr$W>?h96ZbBhK!Rxs69cI zK2)`}OQsi_YiniM*Px>fsXST|?hpKyr46av%&DBCtbpteYCok2W(KKwaK3|T^Rv0L zhJ>jHSXG^ngJdrvKj?R3B5&}AQz!@cT@TeK+GgVDrD!D>ddaS=R$IZKcIrrWdUquJ?UG) zrN!KnvgGy%HH|&Kle4693SuJFhpcZ`(MQvs z;)jKZjT0ur#z?gc_YHe>QoF@{hRLKWL$G7IUDen-N01(_t>8qceK zQ);}noV0e|35-;qr({}i$#R2PB&y&|k`s&cg^Jn4?xXU04au~@VqZ1DC7x5Th{0~C zY^8`@YDK6xxOndI^$^dFf>7*OE4UlQ)9aJ+G@ms@KoL$*tgXyZ7 zv#mk9MNMH(;Ag*YQ6qgGKsp3l@_b>+EozkCRE*h>yeQaZw+O+GZ=+6Q69t>H@>cLk z8)TZ~Bxr7<=35Uw;5`O0E5l6^xKFz=r#2v8yE*k~#gkKQ&R4qA z6jF!EDA@89eB47F)nVQSw2ZkfK#cPUZ!v)$gvEbU760OSlyEEHPz~t z2mj`?41Q>GOHZ|T)c2fg#U@0s&&Rsp+Lc!bN8R!f-sVPasl-A=FSTo{0Me-zNdJk2 zcjIP9ZMtOlf69V)OLpHaRhnRkVc311(Zk@=9;k}1uZM4kn-T$V^>FaQbR|Yb#))qGlm4%mA)!R zquOk8zOK=*7_*6PsfUmIsfnS<}GApN;7jX-}F+&Z)qj#$Ys7`G(?q5M}ikb_x zx8wZsCLFn4?aemeVc3DV60LX{k_V~_l%HY8Kot0E8&NIf5sid8_iS@%C>lA#)Lrb~;m~lWI!+l44-Z$LV8_B?<6SuS{D#Yk5o(=st8>o?^-+brUJJ?T z>Ix*so^*A#Q90Z3DvTI~0=@5bC>w>ff8EPfd#gL$wX=1vLjG{IFWh;TdY{pT(hqjt zrGCIxyy9#afy2YDY=w*WU>n5 zgrb~=Bbn-WmnxW74;lBW)BKL~6n4sAouJ`foC2?Rf}H!%PT7Kn>wVbc8VDYvKH;~? zovmgJ+O<8la+z<}(A_Qb!AdE-I99z^sfE*H)ow~M1ly4}UV?shB+d-jL9uD@DFu_@ zv>lh=+aY3{+D$u5tXh(ar%iUe2sz`h*->zMJZ2jXZL`$T&}BTT`RCxC@oG1iHvkV> ztV~sX*b^^8*?45h&LVFl<$Y9{36E!?Qd{;S)Meoi^|}?_&r;uKPt-u!Kd@gv)d;pa zS_A$QaD>0Df%pmP0@f`KY9^?$+DHQxTR8sZX$obbDWqG96u3G8v1tcg?^m7Z9yoG8 zb|4E#)@&?D`8PyNREycl8rV1yt1qpA1`3zgz|o0ne9!@Oo8{H|$T_BrU-5)}!D^6p zWt~BT&(=XkHd-MM)j(=KPA600P`3JL`0Ko=g%{nsK#aKEC)=Zn{jMr%)-y|^?+K$?&tx@xu{t3U`sBtOl%Km&Q*J~ zBFRp}b$_0EcR0BzuqV~V-S*qKC*7T6D14Kr-oh^b8!{e5JhVw_rt&b@Cm~yOfhCjF zk?qQGA!(@TVC8=27n9VbN?1`3G!wST6}M%zYffA}4f3a`D>UZn;@2;L|5P^$S z)hF;PfVk}aXq@WD9@xT3uG|k@r(t(%V~OHTvb*E>y8wdX`(Kb0*EY~!xrr>u+6~q?EEn@a475f-nEt4Dk;k!wlu<+vG$to?q7$=+8FL zSBAlchfsN?w}$3fsL79PhB`a)+&5Uo40S}nfWGh5AsH)pDG0oS{7mX*Z=RR}M@5%rs;PEdBk)LF>=Be0`_`|DxLEOor{ zPq>C~wrH~uf(4t!h|Gnl539X{-sTmSNDKXtn*p_x6^0D#sUR6hW&dtPG>TQm!=QZB z2V)>RUwt%S6R%;Rtf7j*#HZB`s;ltx6~z6?=-{|#HZoiSFUxvza%8~q*=k&ngV#_X zYXCP6Jyv5iy5&R8-+Le9f#p%OHlpxP-SU8&Be^8>fPw;b9)n75qIJr^!emome#|_S zXQnvq;^N0@Vdxz7wxC0}kk>6QbAsm8wBZ8HhZJ?!mN`hzY@;Wkx8q-)I*6X9)-6lm z?>T4?Jhuko=c4|rfmL&n+WV^o2fd3fe9~_y)N z*o#+j`x-rea@2Nu$ns~TfN2J?ZKhT#MJsfos(_QM6+V5vK#fw?!I1^XpbtR5N7dQN zQrPmST8s{yt_#&W&~Y(!p}LiI=?4A|#N_pINOmA59lOCe2O1W~s|03^RRXi`s~~a_ z&akogXw)K{Iqox1P`bgYMW{FbQ^oZ++l%319Eh=n=&Wkf1&RtWcZ@5y0(%OP0PAJ$ z3Z9$nu$_x>RIjduql?wL4)rFhX;Qf`mqt3bEKz%FS`jWNA#*T#6&ov|c`4%keWfs* z4kK@p0rh1ixmXzFnKJa8y04hDt z%@ZF?xBF=5q(72@mRlr7@m$gs3y*4H7=?l`Eew8oOr4>G!ad7T2(2(515Kku8YlR^ zRJAFy;M3(uslLxaLrL)5s{TIzz_OIP^(Ib4qJi^)!xg_pY#uGK6%66Hnv3+Y9U~kstfO^D7ZM zUn4s^x(2>lsV1}QYrub%Izl_WM$&?Pyaw`DspGUCT#!9$cu$m(aA6gCkFP*>ncBO1 zf@!bgKLdpIXES+|YGG#?BKEEgj+Ut*gHL++J?Lm$u8A2FZ%6Mydm(c)Yv%Ugi(L*N z25JTUo^6z=9D?G;Td(W@*ZTbR)0~hJBL4u<}^$1$}pKg#^f#z#YkMfM=sq8|x z^0MU_EWHQBzkp1BtS9Vx0T&o`J)!vpY}BU!Le?P%e%lk0*P$xg*AsHqVfy@@Q1l|E z@1G3~>(u11zf8m+643a@6@dSXSpG$PtOZ}3Zyl3H$cDhjFW|IODl0iT8`i$4rgneC zR0-{DQ6;q|icNA}dlAQ!l@>S~HmGY=x)xH@PYrR-s#Fscj5#+};cP~KG*_$s{15*v z>iexwF&}zGeTD@m!nEz`E?izj?7*el`n2-0TOt*JEj!fDl*RB~9V+%Y5b>%yT6s_e z+3@hIxLBP&2g+W>g3rP5di9d>84P+&?a!99Ew8h6bUyo<`X5Ev=(N9qwJ77D>rS;N zytZ4t9gTT7vm2>*xK;Uy=%Fxbm)eI}6e!w-OSWGvZ|sUFRG|AvtsUg<#2v8LEUjC@zsZI>6f5e-!K80TYLZsqiA>&`jU_NtT+<22HQagjnED%I9S1uxwn7bzo9o?t3C#aZb+X2S^5(H4tO2If_Pxu;4b5k} zd1~~26H%_JN;Cr#Vyqz*T(rH$3zX-KXzB(t~QE)YQx@=jkR~ zZ(28*;BoP=>#W*PK5!#Sa+K;gv7(fb7~JrIj=5P>R``#btvpVr;b%#goyLl zdF6t7i^4wX1^yS+kg$WM(*Hr99%=O2_K=F{)|006J-u*v!=U7%`lV6^_Dkw#@a1LI zX8j`-9}DNb7Ui$@f{e>p-eMAl!d}qovYKrD@y7XknDal3_+*QR)oxUOpgI3k==vAx zPbUOl!R5n0q2Cqt2c-gn|He7-C0Oz|PULzMZ>or=~?4P0o-_oMT)roE~tufc{^S~t9fSDv#h6|~mcLfp7t(pnp@_=E1F zb@QDYF8EJ}L#?%LXm|DU(H>wv^PtQ}D^oT=gs*l78xjs@e68}xxypq0`Aj#i+??O5LYc&c^@k1Ld?t(e6g9#~$tBA&evPls9Ay_eRSSUnK&_{e4@UwK zuqhA$xmGPmDTH2Dtq-IJYJFjzRSQx6f~T$83HWBI777I&G+g|)*HYnM9kjWDQS-cY z!PhV-Oq;ExAZtT?m^Q_lV#=_#8DcwXCzM~HZMZhlcJw@%(!05LBs=dc57Ab>4zt>8 zampoF(m@*p|81{Lu%?+Lt4CmYB;;GOOyKr`zf3)c76Xn_K?qCmGDc`tmM4-8s zrOsfR)=p76LDvpiw{~IJOWm@Q_s$U*03UbOBg!+^2f^ZS&4&esmS?QTv82D-hQj;d zS|sxou(t`OhvH7Lmd^^$m48)}VJ$FGwB}lQ^456PZvdQ#(9S41a41siulx(zc0#6j z3GAJ;(aJU0(n*`G`~ksH7<&n(Mrq^OukqqF-&1GZ%NIH@cY$P93Be({7NvzURN!Y$ zg;;+y5v|8dw@NU zu`Tm}6Uvd&s(kY-#HS#~E^_YZtZilNq25q*5l_qggYxGIeM|Z0_U1!u9czNG6#3cc zv(ARDnm<$Ca(>!Pdr(0aQorsfjS2ISe`4X2?pm6X4Q+d9cLb)-_m+S%$nJrHmrFUj z!4CWz3m?KDaG@#ZLTG!d)|)-wTMWbcKM_aisU{pNd-IQ-g9$8$<2e)f_1^r0!K+MQ zK}S~lCv2Rnh6b8ajhE(25KeC`lSinhcF8rS_nY#6&>M34)8RuCT;g=E3H(WKXy~Pd zSnoE$1yb5b1XHWlwx)DrH1GHmQsZ$nb;7D66vS&|S?N4Db1$x)8{@UU%G(g!8;4+% zNg}?0slAcjyG`H|umQnnrvToI2!Zc=YYBli)0h-OL;@B)Xe#<8*b}tTffiHl|G>@! zZM^lQDR-9yh)mRSl-prRqBfGPo(~7cXq}<)MO2;V6H#L$>m+IY18YsyJp=Y6?Lp@2 z4-HAE@+D&osA=+MjHwB3j-w?SPWk*uSEVVR9F_GZ@RS68G|dVoc(>jVd0q>(5%^gl zDr9is+K<=%E9~i`g<9>VQj&!NpYVXw`Y;9B_C+1@tz_;;DS4?|08eoFw$3$yCCU$* zz)h%2CgLsH=_a^jq{#?=t~$ut-IOe!5@+`}K~6v9qiC4lPx~cspNZ^e;o)SQ>t0iaAqn(xb>&akk)nMTc-TaMGUuw>v`~e_ zzGi?HX{|G1_s;}q_!mCsV**PGY&L;EO%N*mB@<;|Nytc519z(H96y;6{ud51ij*p+}6Wt0#tA4_pM zD!y=Jpaw2|Xs7BtSffp%m|ikXaEa7iCh(O6vi7VaOkl~ygAvTtVQW*mp$>2RgLsEs zKLZ&(wOH7ms-+RN&ZOdybv2bahC@c*QI9ggC1xE>V1XG7OVt9H9H&4zPG6t#?z1Ek z^A*^9Cb8+6rtM>y_(EZt7RwGUfRMr32)|=^N|#ngLlYrqsFv(pKUm9D(BwWnM0?P0 zvrN1%(TRyG6!zJ9I5R|><~LO)Oq8Wo4yRJ9;m8PWwqIA7xH8c>Zlo5epe~)Cj>BDwKmat^iFE)hjY}{ozD8ZwatoB>9l8PcPNY{an@ylr=e~% zQnl@A?7N5AV8f$lIH570(}3ndM+nT++B2WF5SyuGu)0KUQ{cDHS7mCQNY*mZdfK1J zwXO0yZZG4+atb#FjT%Y7e}mwAQNUx9=s`~98`v>g>tsE2%DdUSFm+Q1J9tX8`uV+D zM>Z~r=E3B!CJ$Mr$pA^f{dN1>J5%q&WrW{GY*7-XYz)fR#w41J#wle{HikSP~uPyM~DASR@%I?SX zOGuIXMSA2!OkXV1XUp<_eQcGUQCN0{OzS_kz4aRG_S zU*2Zrdh5sEUa({*#!yx)AH~BU%5drM@4G2>@RMpKJF$}m_kWqKcqTgK9b4tCuGT|& zcDmJp1@L;7c;&))@pFq}<(9=9sqgFxUGK11=FCBcz@J_5=gj6<&ZF2o${79}Lqs>T zqtWwB@xh{7j=90P9FT48&qK#xn+WGdNI0Gi#vdURhM{9{6#k3h+^#&#wkGg!P9hI1 zw0T9`{)lv}0e71&G;A*0Ie05X3uPPbg)OGSDE zjELGAvlCGZ?-b85xgJlewZN?eLEdp0)i8`|qd}coQnSDP9$a z9}1{qk?hm!us&BySN?{dbJ2HUSc}h51Cod|bnE+Y1+vNn79%&H)C8{cpaxN)r=-GT zrhH-~dlVtqu`Clad5_#MQ+8=hc39v6Cj%Kzk8>gqgoh_-lVSHHZ8@_nfYiyT5^M{g zY%*%$UT|o#_5?eJhUgS6hm~G{hAF5^-)(}_skl(M*STS;_JG1N=Rxx{wEW|Kg7^ou ze2u=7QQjC3r2X+L{!w4n6WYwxe3V@0=?8I!Q3gWWhqRaQ9MO)4aK+ynetrm-s{P=e z8QP^5?uu<-pNSrT+u*&K+Dk3`6@#4fXKAe!baX9w7_Ihq|A4O^)}|?s&-&bgS-JMkxEEY!YI0-&oy zdx>5B1>Sd{iF4@}IO9M^T+=TQyGU!+TBDg%p3or*(hIfaN(y{hi2R(epgc7oUM<M7v=vELn-RM-3cWsqM8E zm~y>-3~E+s$t~bt{0wJSVTa85KmHlw%d``$bb)XkBs_y&&l!;Yj0R}HTzE!%rUg$Z z@ce4D`+xWY;-A$vw%|6jMW5BKvp<{Q=yND0{b6`Hj`pD@XedXPIM4(a%e86NO(wj5 z{Ry{Pk#$a=fwgP2RO;RuT<#x4CGfm9&br%_{q>)q=6UR<8UDp_IP*Mq(+vOkxHEpO zcEF#-Epj$*CL=d(5v-`u-e;E`kg-(@f%8A1i+A2u?Jz4?4qXHLCVrzsK8 zb|>1oP2W0WccN-z^HQBFoZ1!LX5sL!g1eK-@jshv?*_!9|Mq zO@okkFzh;ve|H@2en+ci_kRQVfQLB7L-4;r6}0<(R9)5xa(!qE@35p3`~eSG24e&OxCvWB&_%lOH~hpnh!C#OC%il5VL2A z(kV5N@ewA+c7Xhku+(k=j;n_QA88BN8f@!hELAWJ@+n*~j4z#F`^VZQb}&RDcnFF< zK^F0j_ko8#)$V7X4ub>Nl~CuAPpRu0zlL%D)*=I!eCB3pt|^B>{I^;IPL-#>)vjydU(w3`JCy$ri1=RH%N8z%qu*<>S|lYj z#^^!p&qEM-1iKmd75MMO;X8f^Rvf|p`N;Tphv2{wghwrg6GxEYFCG&4K0E|DM^S-a z9R_EPB9TMH!3b8r7*c;gI$anBITSW6hN2&^+__JXZ(^A81Bi;2HcdSVi6P7^PF>M+< zIRY*o!*V4>5Puw1TN`-zI4Xtd>D*ro>yK+TR$l}S2lNrntH-rX3for%8&9B8#&E?i zNL~zg{erp_AmXIvxB)MIJ zOA{jh-21^lNDrX`u|YZ&fD8=7Y9IH`|FF!TdpDF}e&{k>5AfT9s|TuN@!ils!1Kcp z_>u&^fT)hvWBp!`@ecPuWH4r$G6pl1OW;p;Lk0rFPMXkLCDV7_4MkLF>}WjzHV5nY z&AG?%__`ho%L#HmSPx*ki=C}P^mv`9l-yCj7!2nNF>PR?zK?P@Ct~*`+RRo0@ktn$ z7_)>D$e}nQOWk7WB~V6ji7aa>L6-u?C7$eX37nz$w)^?!GSwg1N04oV4DOE3BWV-BPSc)lqt4x<&4$Cy9SITrrg0Rb`^cQ8iF?5Zl^yg)|9J;XS zru1iIdhUIEXj#cpSTS6W468Tgdyewq|NECh1Ew>drOu5xEMS>8P3$OpM6#}U~JPem^KD8?p_9EWArjMXbeP-)r(l_7}z*gucLT| zU7yB`icexic0}OneQpFvF?1rufSt8G2F;Y-ag29*XPIt$4C2S>)n%V}Vkn-c)^Hn|hbQb@_KFnxZGO^iyzPs-6s|rs!#GH_tYLVdBxv&Fur(DZTu&k0apjsd^h{<1~Gi#^O6b#!USy z8HPdHEd46GJ_b@BMi#p|2F5+C?_yW@NER_=ER^NzE0}FLgv`bfMtJ^gWHD_ljda-B z0(~WGjd=oLwJ z7wVH0mOjRL#-Yb5ls%^qHFeKIWUh1`DPp6>z)=LUgvXp03y~A4k(?sYNKp|2uoPAr z0#}Rl6lyuS*wxa&Hh8dzcn`%xw0V*0#q9CU<0X24f~0a@T&l;0u&>8DBP;ZLh5jge z0madSQqD6k>S)m;l_EFj`9z(v4SEid`OF4=t&2LFHtJ)EI+!~Q0$$R4O6nA`&S-eN zgms46xy7*c>PvcSmb)C9YxEN=eL0-iilUag+!<1WBJS#A79htcEp2srQ5Gufu)BAXZ%}ws=^w1-Vwx;Tn@f}8)w7A6XDF;h*47=MDD>5i)HM=j7v4-EbH z;g~GM8Gj#AWYh#`#yD)>r`y85&T=aSvcm98D;NH5|G*Ukj@zH(D04jf&<^qMU?tJx zoFm?$ey+Tqn*cN+PTP;IU|1$X=dS&FgHC`22Smcg16b3($DL?%T~t`xv1DzAI6pZ^ zW7>AC^XTU^VEBjs7xItPFZDKj>&t;U7mEkt|{D#=3jlu7Y!%h140AC_9GYgki>Uy@o<8 zfEz16>&MtZG(t|eG*A(1@`_J`S-+sA60pLR>A)|DWr917!dLiOE?TtsgCG9jiDPG;blQ?- zi8D?+@r%Z#+8x4`%FiCgMN_?|lOus39?Q$2}~O+LR*$pAD8-Xm;P{}@kxol-B6-0W&Qu8>2}|XejDp=%E{Lgzm@eP$HB!G@qH;PN^ql{q#p+ zI$bi&*{t>1lZVH{sbZHYAo^+cWak;Jd$<3cvU6t{UG~qkWxl-^&3l)xKM*!%brSKz zQopTpfjH?;Pjr&{mrDH1zsvDt%aotBs2P1#sSi$ZZWI0F1NZl-E1exmesyTz{*f4dT*Zx#KLhol^P_0+{ZBJAyBFAK{lW{{?au%UB>4;iQu zFMZjz^8;eH=h?qblaCX1d!`Tj{zlR5ad6^vXBF#rims1eokZWrdRgoqeLL%47k#k4 z)19|j*XMqZK7R$ZuY&qg*8d0f+gSe&>RUyh*k6BV)1`8)l~vlwA@^g*td-QH@1wqi z^&0BySpN~~n_2$}>d&xVM}69b)V`mgejMw+Kz$YK52C)2^-(#$+3x(#6lc5E-izxmM(cJH9^!25zZ$kYx*1v)JR@T3b`cBsGMtxSA z+NXyjp7t$a{ky2IWBoqVH?#gd)SqE}3+mG@ruO|1_2XFoG3u*We*pE3tZzeoJL^A3 z{cYBNiTeCYsQo?BL-MDS^q-}y?>}zX|H5*L6+QQ&3@7KfA^l;U9U6G;drF)=-+S%f z6}!HR)5&YEirt<%e=NguJ49M9ezu%%%P=Y`KT z8Dm~5E1mJ&qns`Ni~5mr&)|19iayV)>rV4-t4n#Sq;WQh|JKWVd%w#&VD}El^Ix6d zEIZG)*M#I96Pzoq@$EmM@fGt=tmOVPKKq!n>Kfmy32mc{FB(J77$$|j;$DLunC9%f zT!#1d&S^jSY2AOgbDDRR*zIo6E%mm}d;1}`8>{qf$GZ3a$J-El8!>afZ0e+0<*qcv zUU{FDJ2;7-`K;)6M88Y??4U^W`B#v>Lv%Z07JaGKFO*Z*C8qo(lH04|g)$=5x_3mZ zuUd9AYVKG-*QW@3$D&94I^H{C*QZ$9JM@S@Bf9sFuV43>qed9M4$JCg*Zl?EVotGCoBGTCr_T{tkeEa$d}e^8};^^DYuCS>VG8Z zIB8-(iT_qz|FNRmj;L?ZtbVNAR%_jn_SpkPZ)dAlCONa#%6YdaHv>8)%m);^%$Mfg zHhJ)HS6^WA#U@{7@~cf=GWjn|{+!8QGx>XDtgqAfBiwwNo9EQN#_(Q~A7k<}OrA0M zttQ`O@*kSKW%7TRe6qe-mvo59Pd52wCjYd_ztPWg@{yM@ykzo`quc@xH2H^2o;LY< zlYhbFcbR;f$saMfJe=z{&`A8 zQ}@&P0r{jr;?I}+BzwWtQ&`)MF7Zo5pRxIPy!Dln!82F;WHy|vZ_ixuQTNPK{=GQ^ zJ>=%6EXK>wnZi=`Af5GJ^w>W5;DFr=abb>oWtN_7ftz71OO}@?K51ITilRs(l_KSK~>#hFY(k^!+$6s^vnn*fb9`_9% z$ZEbxMl*Aq)326$)W1)XiH&^o4-WjzbzLd9_x3r(EizEBhs>xv!al&+aiMRInNP_b zenb}|=@as2#|lqPceY+DN19jHml2P?lXZPNxx4)7B=NJZqxkW1G}*D1=u23?TH-wA zuVY=$gznKdv##G6eo(*me*Mp|ek0aDZ5_4m!=fKBj6aU`X`cFw2tb+b{Zd*7fb6M}M33sZzh)z7jt_NA=%}@k?2M3fq4h>(8LRmGvV%V@;`l zC+jbWK3CeHljyVZ)V_y2`pcuv60N`N88+z08Fu|eUnlxJuf9&=?J%YzT{xsGGU@yB z`E}km_mc2SZV3swD0-jb?)V5k748VzZK;c3{|KGTUnT#J)F+P``yc49_syMIz1*!g zyT;A)1vj4(a5k@(^_U`8EIXw9U%4l=L%IFV@|ka%x+}8BsIyc2bC-+V9$qV@Zf_{;7aq-%xcVlzlL3)_98jUSdXnfKxGy`sD4$bQJV>c18EJqfUvbsfU~ zhsue?uCN}z+sFEc%cb~w+3|2ClAf9 z2p^#TF{w%$g!NJRB-Y#BLxgQ-(nTCDY}+H4Q|E}mHcC6Jk{;mQ!Ve1T)G+yPB)2yh zc2AA=J!El<>uXn_uAh8Kvf~=tQ{@#QS7`e!esfNC!{jO1&F+78m)eoL+sWi@)dlB_ z8+{)=ENqG^ob6z(ED?Laq|m^x0XGT><}Q&b4zw-YdIz)++#PQ#vf0npJoZXK8 z6%XtBRl{S@TyN^-aE-gf0sZjCqlbTooFXm|=N}pP_v=^Hp`oudiSv&R0{Z_{iJQdj z$Iw6UIC8XQ*{xrt2L@M&|G_%Ad6u|DoO%NNi^Nsp_S44S)UN{1U;%+=kz>Ru;^cGa zUmy;@fO^L8(Y9B|{)i53;{2abuR06A;G3Q6{T0ob7m-WEb>hU|(7!_5B<>;SRO2Nq z!2dFGoH*J=y+B+iF6=`8=4)P--IsX7YmfmNapIq-XNk+i^*7PqeLcYNV05Q9HZ1k4 z@>>|-&ec2&D8G$*gSbl^Fjr&SGor*P59|6>MBjf%vH{8dn+S%S-VOEqMC7u0$GDC6 z>-zyud70_Rr6Kq0SM{NxA6RkUkTGablekCR)}N<&D)i4ljt~d;u)15niVY0?a#WhQ zx0elY_2@px5&dmzNp=gQ_eGBB2cI52Z`sr@!&r1k5EqHt#G%<3pCT?1w?eLe&bByu zAQq542sv{wa%C=Z{t)CkaqLjki!SE|o2*F=q4!`winvVNA`Z^S`1S(gg_>pi+bxhf z3>~6}Bd3T9#FZn^ze(I9&K@cL&Yv9LyK?F%3=I?4h}*>eD8^TbTg2*U@Xx6-8dQV0 zOPoFi3Q!&5+Oep&iT%fUb-fdg_ZsAsL|h|o6Z>NrAN&Avcrmj2pojHA*!3EO8z*`k zgtPji4N11QlukizEkUlHhTPL1t$5-SXAHT25-52L+ObU>{>U&u>lxxEaqvv^PZ3v! z+^=7ChX!4~ik^i9BkD-6T zvb+9r<+q0Z`pYL(=U_mVxK8Xp7yT2&CE~W>!AUrL9u|-x4lF}GP8>_2o+d65XO{Q< zhbQ66`B*@cxJMjXf&Ovg3~_5E`l|~y%l5a2Rk&{$a`a*hDCkcBC0YN}rO1`bkTaJf zSBcxJMA!S@78qTP0R`d)ac~X#Cy9&14dUS1ac=*&4M=|i3#@(;xsXL}T#a132DwSB zu0=huZk*fyZ3D{d(4kEn$)TPht`N70qw6u=e?2+GuSbU>ao`5j%QqqyZ$b{-j9e-p z*K=g(5c_YzfCzDtxI-NOEXHSvb7e9_K8FEG;yiKqR`gF0XNiNifxkS%L4!&Y_dX8+ zDqBSEZ9oov0Xa^b`Jz{s{#OEnQlT$-9h8a_XNY58LH{&yk+|k%-T&KOgK*@lSYY@L zr_xC=R0 zK`s)vh(mXyf10>DV7GpmN(%#G|ASm0_TPhgg1AcDBaVH?#GCq6*&6!muT+OPaxYex zC2kRiHlu%4xIwJ+hq9jS5+yD?je7oBFUu}1gF)syBTl~H4G{khvU(9Y z{|a)6xaDQtrRuL@K#MrI3w8hN$RXl1arO=LFMC+muNoeM=41~83dB|77P0y##%G8d zL+;nFxLiPb#R6AO@w#7*LE1pOlmy(~Q{0|x0~hj|@j zRpsSV-ZhR9`wvGwPFx^P9O3cT7nY*eAlziu-^Y?^}wd2ytz|XY2Ko zH5?dRj(r#ls1d7EQI8SVoH_T)!4+GAZZ+Z_aqKkoZxDBhg9-Fce*`$EifB+Z;^dhS zpz_2O;^bN6Ph0_(og4co2Be9L#F4YnKS`V?4xfYm6))?~6+RCg62w{J{KwJ1LfjLn}`IYEjA#M`K)99ZW zuv@<>4GiwV70+NmjkrzhUyc3|;v{ivt?@VYtK?N!KN z4?=?1VgaS=kn6-9VwFSxFmZx7>+;OOC8JCZNoRD6+!*-RW4RIHByr(-^sf@Ph%+~# zf8b`|oQk4BrHBi}RpL$o3RJ1jAa`#;4u00l(m!HgP%2GaB#wX1TY!AddMk4JHsltu z`n*Ti{WI(}2p5YU2jS8N*3 zH~&-=TkuI89s>?)N|2fEqajAEg3`)5L|}qkomSMI8CV zc(?!C1_bn^M4m0uA`U)^S25~n> zhTtEufZ|_}Gk-;nzKEP9F8>Yn^h?OOA{lDL(N{2_K-?e>cF{jcTtt>{%c4Prc3}Z6 zV)Yv8VPgO5s7HvCz|#LJZ(u;>pUC+)k?X{rf1zG|3%O0~|F=ii{XhDS#~_?1t`ocO z${C(F5@sGCdlVIj>%_tF?hiz?fB*Q)`i2IvsWNecxJw)y!T1_+o7nFk_`An{WN6U! zt0ZxF${?Vx7pEczry)0q1JhA&4A`w-1xL{#FatSF+$N6if&P)bkekGvy^U__SLOcP z!NYy3_Qe7U#EF@xcZvP`p&s9#c$Uk9>wn7_2Aya&1{6ccb>iY2)Vsv-15l3~)aT*# zzv&tVSHsT17?7HaTqBMif_jNK6h=MYXW9OCjf><^em4fh<{{?~MXtXGIr(1X?n30^ z`-JuWw+(1%gNFl$BX@|?N1z@!61hgKqNpd2o`Bc?su;WtNH0RJ6Gx9hy+m9gj=mrL zi^olH`@h`+r4!Jhaw2j*jvPG+Ie0R1;#B1D66E%h92)AUAt%p5ZWHG}ihAR0>Dsjuf26Ty43H1sOJxkqcGi z>i3XiTaoL;E#mkC*59pP70rx9w%0Zvvkv|CsM6!eLp_T{;21L`~A;0pfU>`VzZIEbCCT9BS(l+#0BE^!MnNr z-!{NM7YmFMr-%#04dU{%L-)PNrTNHB;<&S8yL`x3U4U*aViiF>Oq?bz zE=2ztaU1ynDv$en=2iwsY5GGC#7l|v2Fg|z;a?H!Rv!}fV;UaO3xJR6NKUPpC zZWA|-9s2hVw(fC5gVe7=bO^+WGsGq07I83!<;RBX9_;C%LD#Q}#5Lj`aeWLc=nw}^ zKs`EOw|K3^)hjXIQmia&$xW@;8Is0ht}B`5KJOxi0jUCkN9TK$)AI6 z>RjZqv*}Se?ZrQi<_vL(IJgx3W5f+&|1$JXB0ICd3v`5bcOR^$wE+ZlUY4x82&&@KEWP94Af@7l{K8VtJ7v_v=@Qp`l-YhPX&vC2kUT zi37i)1`K$getjx2Fu0s?HasEc;RcywW@b@)E7Kxw{1)r!5{I^<9wW{m=Tr?1szn@l zmFesHGt`fJ2)edig^3aDkMcndozjOQ!3kVapi35+Ie~Gw3 zoO~4h{m%}$Uw^$lH0aKec>y{5N96pUkZZ(E;x2LE&x3gP;K&RO{mxk-t`ql&1AiG5 z*pIIhw}_J+>+jaD3IjtwUVd?89bE1ZtG}Y2ATAI$i2Y__RKKZTg{;A?PZfyk#6dG% zsy$5O#F3Y=fx(@~al?b5bofVY?q%m3{2@VQynH4KKciN;AaRs9L7XA3E%BBo{V$pD8srCdA3-jkgwaV_ffJ$f0wPtHhCWQEwB+&qFRX=qS^OR<1Bah=$I8T!lnqh)IhuUskO4zTRWpqXmg zp6KJm?bTRd%}hyc{hL>!-XSipMLl$thxIk4;x*`|f5PJ+m?aK<67?i;o47|@%MRmp z{VI0#(4e_NT)77I;HQvl*CDrv6YEgV47p#wstyghe$^w+=dpmwdgLx~=6ci%#N8XM z?$)mYpSFg6{VGe`Aokyc{t4pv&8Qd5^yRkCR5u#k)UQHi42XXnIZs^u2I`@2BIk*N z-$K1$creCpl0)Jy49F4}?G;xbK^Z@#2i0j+5 zF5BPk6ZLZph!f|DtHf>M?1NZdnYgA|?|<8X@UJi+Nt_`r64!}a#O>`^eowgH|7-(7 z52Hhz*#CRfBg6^f_~YoGX(5;YKx6FY6X?)=5;^cRa{gIl^*nNcxJ#V+6OFO6f5HNi ze@4#y1=;^1a)`K1T=*OM7jiG5p-G&08TArza3|_1;x=*k74*+_$j~FscQK$toOl)W z8gXD3>VemQPf(FJ!Jx|WK5?CFrwo4_IZ7ONMql;K9+!6(zABFltE4uF+r&NMz*4L& zOdKOlBA=l$Xix>>GI4{rN!)hk?2=F6)G};WfH>?d-{o62uIB96ykyBg*r<)%XKC$I;%VP>8$HKr?ZeV`gh3^&X{Bi^XFp= zO2k#-y0bw?cbsjK%?VzB(GlX9GwvT!Ns7!_;v#X`8T*HC!Dx%j9cQ(aHtJu2l?I&+ z+8iZw+__Ji(`3#%JG8k(=8E&GHaE!Jaz@_}bC1k^XQ4KSS7J+|&go(vmv&ZbwLogg z*`UoeGB=$2w7Em(p0h*DW5EltiU@I>I7OUs=JcfWBALru#(KU56UI`PV)0qxB5{Sd z?ri&)Z}#nP`2x~A$KLYIcJlJSQ`L*MUIhLvid_4dw ztPwYfTf}YR4sn;b2doFtpTq|Ei37wz;t+9|I6@rt@?KJZ%xe&if6_U@H!^=TMfS9_ z+$TLGOXj?@TAPbxE;;M9xkBcuvq78dWNtW{w7Es*wsW60cgfsywrR6Ji(4+>?9k>A znZwR=+8iZw%z0It6J$<0<3>jG^>tLTu`H>1;_lVhgdTCg+2$XaJtuYzx+RG-&bZy> zD2wf`j}*Nq>qS!*w@;FPLVA&(G!k=~`oFGT1SZQOq8ACh$mm5;FRHSTvD1#pvKI1g z;3*>u#$wlE^>N|^agsRY%#mW|WXW71ZaAyOZPb4q))sc|o1(WrnPbj2ZBCFm>Fm(v zG?_EbbK0CIvs{F=xkTo&Gj6Jwt7NV@quSgcvs|*ZxlQJdvrx=qJu<6xxO#r#0I|%E zsY?%&IpQqW<`|jd&T4H=k~!t9*X9hFv(AR8vc=0}t~mFJ_W^Y>w}}0@ExV?U%pW(W zp2t;c5qF)_r%P`NIqP+na5m{I?`)Io^y+$yZ4kGKd&Gh3FGM9)e#B!@7VYwEWJH-AQu@MpCC~=H9PMkuP zPcqP;3dCjNDsi2-N!%vx0_#iHr*RDf#3AAcaf~=YoFdM8S=V3m8iXsvb>b#*o48A? zZlV?Ru&!T)JO<4X;uvv)I7OT$&M=!VOiYqDxlEoha&RtlfUZ_4F)01b0RKsvhTQwH z`#T-02Y-rOeigZ69s( z6R$f#;c<^a{%xCA!`Xn4d6k>x=#%JQGH-ITdgocx1J5HT|2*WJUZcQ^LqngTn*wcC(OUqJ4-?@!3} zPds`H)W3udfv+Jq?m$*|B1g-}8S^>;+rW&O$=!0r&g58<3oZ z4wbpcv3bZLGi|AjuPj2nH%7b|Idig^AjlSwKLs7q31t77$UWw>P;Z;LCvEwS^H2{h z&7mQfLhccV%}k26z|e*0Us;XZHuDTxfB&aYkLL87uswaCOAV^5M?HK4a^WUqnRXh= zYkwBmZ)U5r4a()oko`Ocbj)ONHXyPQ_3oX>>AR4tX6iK?pEpyb8I~_PnW@gKLuoS> z5d1E3{C;HhW8}uqk-HBfx6HI!Zhdn6`5!@t+M~$f$B@%z4kz1S|I4Un&5T7>ue^?W z(o7K4*Y)wAHuL8U0{p`fjy^L+&0H&1FPMo!EEmlr5|(3EVSMaM$Yt|$d+qOD{|^}s zp>&0zdC1iWa_unWjQQ22Z9vQXiqdlD1oTfY9hhB2jm)~d5&6qM zBnwHJ^#k;t9YgBi3{S$jrZI8_+ZJ?OBc; zJM7guzWkx#F40_yBNtCb4u4p)Y=2u|XbCz56UeR8kpt$}h&Dd*x|AnL^X~Fj+Gn_h zG&lD}j?EF)``-q%4nl{(A;|gp$jQ@@JC`5_E=SIOwGGH&Gk2@4AoWw!6Ww8h zCQF4y^9~v9FPu~D*U=&CxmryTr_No&!)~f@;Qk>`6At}o$kT-*ue)FB&=qK|{bZ;I zg#8|UR6p`az3!ZF;K&cgSA5Q!2ae32(J TaskInfoFetcherResult> { - Ok(pubkeys.to_vec()) - } - async fn fetch_delegation_metadata( &self, pubkeys: &[Pubkey], @@ -212,18 +202,10 @@ impl TaskInfoFetcher for MockTaskInfoFetcher { rent_payer: *pubkey, }, ) - }) + }) .collect()) } - async fn fetch_undelegation_requests( - &self, - _delegated_accounts: &[Pubkey], - _: u64, - ) -> TaskInfoFetcherResult> { - Ok(HashMap::new()) - } - async fn get_base_accounts( &self, pubkeys: &[Pubkey], diff --git a/test-integration/test-committor-service/tests/test_transaction_preparator.rs b/test-integration/test-committor-service/tests/test_transaction_preparator.rs index 2aca5c364..e5cfb01b0 100644 --- a/test-integration/test-committor-service/tests/test_transaction_preparator.rs +++ b/test-integration/test-committor-service/tests/test_transaction_preparator.rs @@ -287,7 +287,7 @@ async fn test_prepare_finalize_tx_with_undelegate_with_atls() { delegated_account: committed_account.pubkey, owner_program: Pubkey::new_unique(), rent_reimbursement: Pubkey::new_unique(), - request_rent_payer: None, + include_undelegation_request: false, } .into(), ]; From 449884120b651ce1641fd68e9fbcf7d368061114 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Tue, 7 Jul 2026 13:23:01 +0530 Subject: [PATCH 4/8] cleanup unecessary stuff --- .agents/context/crates/magicblock-accounts.md | 2 +- .../crates/magicblock-committor-service.md | 2 +- .agents/specs/validator-specification.md | 4 + Cargo.lock | 5 +- Cargo.toml | 2 +- magicblock-accounts/src/errors.rs | 2 - .../src/scheduled_commits_processor.rs | 11 +- .../src/chainlink/fetch_cloner/mod.rs | 8 - magicblock-chainlink/src/chainlink/mod.rs | 4 - magicblock-committor-service/Cargo.toml | 3 - .../src/tasks/task_builder.rs | 79 +-- .../src/tasks/task_strategist.rs | 23 - .../src/transactions.rs | 630 ------------------ test-integration/Cargo.lock | 39 +- test-integration/Cargo.toml | 2 +- .../programs/schedulecommit/src/lib.rs | 13 +- test-integration/schedulecommit/elfs/dlp.so | Bin 468440 -> 464792 bytes .../tests/02_commit_and_undelegate.rs | 44 +- .../test-chainlink/src/ixtest_context.rs | 2 - .../test-committor-service/tests/common.rs | 2 +- .../tests/utils/transactions.rs | 21 +- 21 files changed, 67 insertions(+), 831 deletions(-) diff --git a/.agents/context/crates/magicblock-accounts.md b/.agents/context/crates/magicblock-accounts.md index da27d946e..78182765a 100644 --- a/.agents/context/crates/magicblock-accounts.md +++ b/.agents/context/crates/magicblock-accounts.md @@ -233,7 +233,7 @@ The code uses `expect(POISONED_MUTEX_MSG)` in the normal processing paths. One r ### Owner-program undelegation requests -`magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. Current DLP finalize instructions do not undelegate; the committor finalizes state and then sends standalone DLP `Undelegate`. When `DelegationMetadata.undelegation_requester = OwnerProgram`, the committor includes the derived request PDA in `Undelegate`; DLP validates it and uses the delegation metadata rent payer to close both delegation and request accounts. +`magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. The request account carries the delegated account and expiry slot only, so validator logic must verify the request PDA against the delegated account and must not depend on request-local owner, rent payer, or commit nonce fields. Current DLP finalize instructions do not undelegate; the committor finalizes state and then sends standalone DLP `Undelegate`. When `DelegationMetadata.undelegation_requester = OwnerProgram`, the committor includes the derived request PDA in `Undelegate`; DLP validates it and uses the delegation metadata rent payer to close both delegation and request accounts. ### Undelegation notifications are best-effort diff --git a/.agents/context/crates/magicblock-committor-service.md b/.agents/context/crates/magicblock-committor-service.md index 3c8b492b0..70b4e7737 100644 --- a/.agents/context/crates/magicblock-committor-service.md +++ b/.agents/context/crates/magicblock-committor-service.md @@ -233,7 +233,7 @@ Do not remove sorted lock acquisition or the retiring map without replacing the ### `min_context_slot` and freshness -Task-info RPC reads use the maximum `remote_slot` across committed accounts as `min_context_slot` when fetching delegation metadata, undelegation requests, and diffable base accounts. This helps avoid building commits or standalone undelegate tasks against base-layer state older than the ER account snapshot, including stale rent-payer or owner-program requester metadata. The fetcher retries `Minimum context slot not reached` up to five times with short sleeps. Preserve this freshness check unless the broader account-sync/settlement contract changes. +Task-info RPC reads use the maximum `remote_slot` across committed accounts as `min_context_slot` when fetching delegation metadata and diffable base accounts. This helps avoid building commits or standalone undelegate tasks against base-layer state older than the ER account snapshot, including stale rent-payer or owner-program requester metadata. The fetcher retries `Minimum context slot not reached` up to five times with short sleeps. Preserve this freshness check unless the broader account-sync/settlement contract changes. ### Persistence is both status API and recovery state diff --git a/.agents/specs/validator-specification.md b/.agents/specs/validator-specification.md index 343cd747e..32775b816 100644 --- a/.agents/specs/validator-specification.md +++ b/.agents/specs/validator-specification.md @@ -262,6 +262,10 @@ Owner-program requested undelegation is recorded by the Delegation Program in `UndelegationRequest` PDA. This marker is not a validator-side completion signal: the validator must still schedule commit-and-undelegate so the latest ER state is committed/finalized before ownership returns to the owner program. +The request account data carries the delegated account and expiry slot only; +owner, rent payer, and commit nonce information must come from the delegation +record/metadata. Validators must still verify that the request PDA matches the +delegated account before scheduling. The current Delegation Program does not undelegate from finalize instructions. Commit/finalize-style instructions only commit/finalize state and record or diff --git a/Cargo.lock b/Cargo.lock index dbfdab51c..9f17f4eca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3776,7 +3776,6 @@ dependencies = [ "rusqlite", "solana-account 3.4.0", "solana-account-decoder", - "solana-address-lookup-table-interface 3.0.1", "solana-commitment-config", "solana-compute-budget-interface", "solana-hash 4.2.0", @@ -3788,13 +3787,11 @@ dependencies = [ "solana-pubkey 4.1.0", "solana-rpc-client", "solana-rpc-client-api", - "solana-sdk-ids 3.1.0", "solana-signature 3.3.0", "solana-signer", "solana-transaction", "solana-transaction-error 3.1.0", "solana-transaction-status-client-types", - "static_assertions", "tempfile", "test-kit", "thiserror 2.0.18", @@ -3856,7 +3853,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "3.0.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d#074a1a4175faea2e47b745e15dcabecb046e815d" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71#26d01c4b5c0c29acbebd41d14b303e1608bbaa71" dependencies = [ "bincode", "borsh 0.10.4", diff --git a/Cargo.toml b/Cargo.toml index 818d0aa0a..822000adb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "074a1a4175faea2e47b745e15dcabecb046e815d" } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "26d01c4b5c0c29acbebd41d14b303e1608bbaa71" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/magicblock-accounts/src/errors.rs b/magicblock-accounts/src/errors.rs index 148921dfe..d4a7b5980 100644 --- a/magicblock-accounts/src/errors.rs +++ b/magicblock-accounts/src/errors.rs @@ -55,8 +55,6 @@ pub enum ScheduledCommitsProcessorError { RecvError(#[from] RecvError), #[error("CommittorSerivceError: {0}")] CommittorSerivceError(Box), - #[error("PoisonedMutex: {0}")] - PoisonedMutex(&'static str), } impl From for ScheduledCommitsProcessorError { diff --git a/magicblock-accounts/src/scheduled_commits_processor.rs b/magicblock-accounts/src/scheduled_commits_processor.rs index 8b1ef1ef5..7821c173c 100644 --- a/magicblock-accounts/src/scheduled_commits_processor.rs +++ b/magicblock-accounts/src/scheduled_commits_processor.rs @@ -7,9 +7,7 @@ use std::{ use dlp_api::pda::undelegation_request_pda_from_delegated_account; use magicblock_account_cloner::ChainlinkCloner; -use magicblock_chainlink::{ - ObservedUndelegationRequest, ProdChainlink, ProdInnerChainlink, -}; +use magicblock_chainlink::{ObservedUndelegationRequest, ProdChainlink}; use magicblock_core::{ link::transactions::TransactionSchedulerHandle, traits::LatestBlockProvider, }; @@ -34,15 +32,11 @@ const UNDELEGATION_REQUEST_MAX_ATTEMPTS: usize = 3; const UNDELEGATION_REQUEST_RETRY_BASE_DELAY: Duration = Duration::from_millis(100); -pub type InnerChainlinkImpl = ProdInnerChainlink; pub type ChainlinkImpl = ProdChainlink; #[derive(Clone, Copy, Debug, PartialEq, Eq)] struct ObservedUndelegationRequestIdentity { - created_slot: u64, expires_at_slot: u64, - last_commit_id_at_request: u64, - rent_payer: Pubkey, } impl From<&ObservedUndelegationRequest> @@ -50,10 +44,7 @@ impl From<&ObservedUndelegationRequest> { fn from(request: &ObservedUndelegationRequest) -> Self { Self { - created_slot: request.created_slot, expires_at_slot: request.expires_at_slot, - last_commit_id_at_request: request.last_commit_id_at_request, - rent_payer: request.rent_payer, } } } diff --git a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs index d45f906bc..f2e330763 100644 --- a/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs +++ b/magicblock-chainlink/src/chainlink/fetch_cloner/mod.rs @@ -2190,19 +2190,12 @@ where let observed = ObservedUndelegationRequest { request_pda: pubkey, delegated_account: request.delegated_account, - owner_program: request.owner_program, - rent_payer: request.rent_payer, - created_slot: request.created_slot, expires_at_slot: request.expires_at_slot, - last_commit_id_at_request: request - .last_commit_id_at_request, observed_slot: account.remote_slot(), }; trace!( request_pda = %observed.request_pda, delegated_account = %observed.delegated_account, - owner_program = %observed.owner_program, - rent_payer = %observed.rent_payer, expires_at_slot = observed.expires_at_slot, "Observed DLP undelegation request" ); @@ -2212,7 +2205,6 @@ where warn!( request_pda = %observed.request_pda, delegated_account = %observed.delegated_account, - owner_program = %observed.owner_program, "Dropped observed DLP undelegation request because no subscribers are active" ); } diff --git a/magicblock-chainlink/src/chainlink/mod.rs b/magicblock-chainlink/src/chainlink/mod.rs index 70dd82b2a..991800c84 100644 --- a/magicblock-chainlink/src/chainlink/mod.rs +++ b/magicblock-chainlink/src/chainlink/mod.rs @@ -63,11 +63,7 @@ pub type ProdChainlink = ReplicationModeAwareChainlink< pub struct ObservedUndelegationRequest { pub request_pda: Pubkey, pub delegated_account: Pubkey, - pub owner_program: Pubkey, - pub rent_payer: Pubkey, - pub created_slot: u64, pub expires_at_slot: u64, - pub last_commit_id_at_request: u64, pub observed_slot: u64, } diff --git a/magicblock-committor-service/Cargo.toml b/magicblock-committor-service/Cargo.toml index f1be595d0..d9728d739 100644 --- a/magicblock-committor-service/Cargo.toml +++ b/magicblock-committor-service/Cargo.toml @@ -51,14 +51,11 @@ solana-signer = { workspace = true } solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } solana-transaction-status-client-types = { workspace = true } -static_assertions = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } tokio-util = { workspace = true } [dev-dependencies] -solana-address-lookup-table-interface = { workspace = true } -solana-sdk-ids = { workspace = true } solana-signature = { workspace = true, features = ["rand"] } rand = { workspace = true } tempfile = { workspace = true } diff --git a/magicblock-committor-service/src/tasks/task_builder.rs b/magicblock-committor-service/src/tasks/task_builder.rs index f8b28044e..5efbeb24b 100644 --- a/magicblock-committor-service/src/tasks/task_builder.rs +++ b/magicblock-committor-service/src/tasks/task_builder.rs @@ -137,16 +137,6 @@ impl TaskBuilderImpl { .await } - async fn fetch_delegation_metadata( - task_info_fetcher: &Arc, - pubkeys: &[Pubkey], - min_context_slot: u64, - ) -> TaskInfoFetcherResult> { - task_info_fetcher - .fetch_delegation_metadata(pubkeys, min_context_slot) - .await - } - fn get_finalize_stage_metadata_pubkeys( intent_bundle: &ScheduledIntentBundle, ) -> Vec { @@ -278,7 +268,7 @@ impl TasksBuilder for TaskBuilderImpl { commit_nonces: &mut commit_nonces, base_accounts: &mut base_accounts, } - .build(value)?, + .build(value), ); } if let Some(ref value) = @@ -300,7 +290,7 @@ impl TasksBuilder for TaskBuilderImpl { commit_nonces: &mut commit_nonces, base_accounts: &mut base_accounts, } - .build(&value.commit_action)?, + .build(&value.commit_action), ); } @@ -336,26 +326,23 @@ impl TasksBuilder for TaskBuilderImpl { } // Helper to process commit types - fn create_finalize_tasks( - commit: &CommitType, - ) -> TaskBuilderResult> { + fn create_finalize_tasks(commit: &CommitType) -> Vec { match commit { - CommitType::Standalone(accounts) => accounts - .iter() - .map(|account| Ok(finalize_task(account))) - .collect(), + CommitType::Standalone(accounts) => { + accounts.iter().map(finalize_task).collect() + } CommitType::WithBaseActions { committed_accounts, base_actions, } => { let mut tasks = committed_accounts .iter() - .map(|account| Ok(finalize_task(account))) - .collect::>>()?; + .map(finalize_task) + .collect::>(); tasks.extend(TaskBuilderImpl::create_action_tasks( base_actions, )); - Ok(tasks) + tasks } } } @@ -403,22 +390,22 @@ impl TasksBuilder for TaskBuilderImpl { .map(|account| account.remote_slot) .max() .unwrap_or(0); - let delegation_metadata = Self::fetch_delegation_metadata( - info_fetcher, - &finalize_metadata_pubkeys, - min_context_slot, - ) - .await - .map_err(TaskBuilderError::FinalizedTasksBuildError)?; + let delegation_metadata = info_fetcher + .fetch_delegation_metadata( + &finalize_metadata_pubkeys, + min_context_slot, + ) + .await + .map_err(TaskBuilderError::FinalizedTasksBuildError)?; if let Some(ref value) = intent_bundle.intent_bundle.commit { - tasks.extend(create_finalize_tasks(value)?); + tasks.extend(create_finalize_tasks(value)); } if let Some(ref value) = intent_bundle.intent_bundle.commit_and_undelegate { - tasks.extend(create_finalize_tasks(&value.commit_action)?); + tasks.extend(create_finalize_tasks(&value.commit_action)); tasks.extend(create_undelegate_tasks(value, &delegation_metadata)?); } @@ -490,33 +477,30 @@ struct CommitFinalizeBuilder<'a> { } impl<'a> CommitFinalizeBuilder<'a> { - fn build( - &mut self, - commit_type: &CommitType, - ) -> TaskBuilderResult> { + fn build(&mut self, commit_type: &CommitType) -> Vec { let mut tasks: Vec = commit_type .get_committed_accounts() .iter() - .map(|account| -> TaskBuilderResult { + .map(|account| { let nonce = take_commit_nonce(self.commit_nonces, account.pubkey); let base = self.base_accounts.remove(&account.pubkey); - Ok(TaskBuilderImpl::create_commit_finalize_task( + TaskBuilderImpl::create_commit_finalize_task( nonce, false, account.clone(), base, ) - .into()) + .into() }) - .collect::>>()?; + .collect(); if let CommitType::WithBaseActions { ref base_actions, .. } = commit_type { tasks.extend(TaskBuilderImpl::create_action_tasks(base_actions)); } - Ok(tasks) + tasks } } @@ -526,33 +510,30 @@ struct CommitFinalizeAndUndelegateBuilder<'a> { } impl<'a> CommitFinalizeAndUndelegateBuilder<'a> { - fn build( - &mut self, - commit_type: &CommitType, - ) -> TaskBuilderResult> { + fn build(&mut self, commit_type: &CommitType) -> Vec { let mut tasks: Vec = commit_type .get_committed_accounts() .iter() - .map(|account| -> TaskBuilderResult { + .map(|account| { let nonce = take_commit_nonce(self.commit_nonces, account.pubkey); let base = self.base_accounts.remove(&account.pubkey); - Ok(TaskBuilderImpl::create_commit_finalize_task( + TaskBuilderImpl::create_commit_finalize_task( nonce, true, account.clone(), base, ) - .into()) + .into() }) - .collect::>>()?; + .collect(); if let CommitType::WithBaseActions { ref base_actions, .. } = commit_type { tasks.extend(TaskBuilderImpl::create_action_tasks(base_actions)); } - Ok(tasks) + tasks } } diff --git a/magicblock-committor-service/src/tasks/task_strategist.rs b/magicblock-committor-service/src/tasks/task_strategist.rs index d0fa5b9e3..b142addb4 100644 --- a/magicblock-committor-service/src/tasks/task_strategist.rs +++ b/magicblock-committor-service/src/tasks/task_strategist.rs @@ -886,29 +886,6 @@ mod tests { assert!(!strategy.lookup_tables_keys.is_empty()); } - #[tokio::test] - async fn test_finalize_tasks_uses_metadata_rent_payer_for_undelegate() { - let delegated_account = Pubkey::new_unique(); - let intent = create_test_intent(0, &[delegated_account], true); - let info_fetcher = Arc::new(MockInfoFetcher::default()); - - let tasks = TaskBuilderImpl::finalize_tasks(&info_fetcher, &intent) - .await - .unwrap(); - - assert_eq!(tasks.len(), 2); - let BaseTaskImpl::Finalize(task) = &tasks[0] else { - panic!("expected finalize task"); - }; - assert_eq!(task.delegated_account, delegated_account); - let BaseTaskImpl::Undelegate(task) = &tasks[1] else { - panic!("expected undelegate task"); - }; - assert_eq!(task.delegated_account, delegated_account); - assert_eq!(task.rent_reimbursement, delegated_account); - assert!(!task.include_undelegation_request); - } - #[tokio::test] async fn test_finalize_tasks_include_request_for_owner_program_undelegate() { diff --git a/magicblock-committor-service/src/transactions.rs b/magicblock-committor-service/src/transactions.rs index d22c518c1..2c25c7d42 100644 --- a/magicblock-committor-service/src/transactions.rs +++ b/magicblock-committor-service/src/transactions.rs @@ -1,642 +1,12 @@ use solana_packet::PACKET_DATA_SIZE; use solana_rpc_client::rpc_client::SerializableTransaction; -use static_assertions::const_assert; /// Maximum serialized transaction size that can be sent over the wire. pub(crate) const MAX_TRANSACTION_WIRE_SIZE: usize = PACKET_DATA_SIZE; -/// How many process and commit buffer instructions fit into a single transaction -#[allow(unused)] // serves as documentation as well -pub const MAX_PROCESS_PER_TX: u8 = 3; - -/// How many process and commit buffer instructions fit into a single transaction -/// when using address lookup tables but not including the buffer account in the -/// lookup table -#[allow(unused)] // serves as documentation as well -pub const MAX_PROCESS_PER_TX_USING_LOOKUP: u8 = 12; - -/// How many close buffer instructions fit into a single transaction -#[allow(unused)] // serves as documentation as well -pub const MAX_CLOSE_PER_TX: u8 = 8; - -/// How many close buffer instructions fit into a single transaction -/// when using address lookup tables but not including the buffer account -/// nor chunk account in the lookup table -#[allow(unused)] // serves as documentation as well -pub const MAX_CLOSE_PER_TX_USING_LOOKUP: u8 = 8; - -/// How many process and commit buffer instructions combined with close buffer instructions -/// fit into a single transaction -#[allow(unused)] // serves as documentation as well -pub const MAX_PROCESS_AND_CLOSE_PER_TX: u8 = 2; - -/// How many process and commit buffer instructions combined with -/// close buffer instructions fit into a single transaction when -/// using lookup tables but not including the buffer account -#[allow(unused)] // serves as documentation as well -pub const MAX_PROCESS_AND_CLOSE_PER_TX_USING_LOOKUP: u8 = 4; - -/// How many finalize instructions fit into a single transaction -#[allow(unused)] // serves as documentation as well -pub const MAX_FINALIZE_PER_TX: u8 = 5; - -/// How many finalize instructions fit into a single transaction -/// when using address lookup tables -#[allow(unused)] // serves as documentation as well -pub const MAX_FINALIZE_PER_TX_USING_LOOKUP: u8 = 48; - -/// How many undelegate instructions fit into a single transaction -/// NOTE: that we assume the rent reimbursement account to be the delegated account -#[allow(unused)] // serves as documentation as well -pub const MAX_UNDELEGATE_PER_TX: u8 = 3; - -/// How many undelegate instructions fit into a single transaction -/// when using address lookup tables -/// NOTE: that we assume the rent reimbursement account to be the delegated account -#[allow(unused)] // serves as documentation as well -pub const MAX_UNDELEGATE_PER_TX_USING_LOOKUP: u8 = 15; - -// Allows us to run undelegate instructions without rechunking them since we know -// that we didn't process more than we also can undelegate -const_assert!(MAX_PROCESS_PER_TX <= MAX_UNDELEGATE_PER_TX,); - -// Allows us to run undelegate instructions using lookup tables without rechunking -// them since we know that we didn't process more than we also can undelegate -const_assert!( - MAX_PROCESS_PER_TX_USING_LOOKUP <= MAX_UNDELEGATE_PER_TX_USING_LOOKUP -); - pub fn serialized_transaction_size( transaction: &impl SerializableTransaction, ) -> usize { // SAFETY: runs on transactions we already serialize before sending. usize::try_from(bincode::serialized_size(transaction).unwrap()).unwrap() } - -#[cfg(test)] -mod test { - use std::collections::HashSet; - - use dlp_api::{ - args::{CommitStateArgs, CommitStateFromBufferArgs}, - pda, - }; - use magicblock_committor_program::{ - id as committor_program_id, - instruction_builder::close_buffer::{ - create_close_ix, CreateCloseIxArgs, - }, - }; - use solana_address_lookup_table_interface::state::LOOKUP_TABLE_MAX_ADDRESSES; - use solana_compute_budget_interface::ComputeBudgetInstruction; - use solana_hash::Hash; - use solana_instruction::Instruction; - use solana_keypair::Keypair; - use solana_message::{ - v0::Message, AddressLookupTableAccount, VersionedMessage, - }; - use solana_pubkey::Pubkey; - use solana_sdk_ids::system_program; - use solana_signer::Signer; - use solana_transaction::versioned::VersionedTransaction; - use tracing::info; - - use super::*; - use crate::test_utils; - - type TransactionSizeError = Box; - type TransactionSizeResult = Result; - - fn get_lookup_tables( - ixs: &[Instruction], - ) -> Vec { - let pubkeys = ixs - .iter() - .flat_map(|ix| ix.accounts.iter().map(|acc| acc.pubkey)) - .collect::>(); - - let lookup_table = AddressLookupTableAccount { - key: Pubkey::default(), - addresses: pubkeys.into_iter().collect(), - }; - vec![lookup_table] - } - - // ----------------- - // Helpers - // ----------------- - #[allow(clippy::enum_variant_names)] - enum TransactionOpts { - NoLookupTable, - UseLookupTable, - } - fn transaction_wire_size( - auth: &Keypair, - ixs: &[Instruction], - opts: &TransactionOpts, - ) -> TransactionSizeResult { - use TransactionOpts::*; - let lookup_tables = match opts { - NoLookupTable => vec![], - UseLookupTable => get_lookup_tables(ixs), - }; - - let versioned_msg = Message::try_compile( - &auth.pubkey(), - ixs, - &lookup_tables, - Hash::default(), - ) - .map_err(|err| -> TransactionSizeError { Box::new(err) })?; - let versioned_tx = VersionedTransaction::try_new( - VersionedMessage::V0(versioned_msg), - &[&auth], - ) - .map_err(|err| -> TransactionSizeError { Box::new(err) })?; - - Ok(serialized_transaction_size(&versioned_tx)) - } - - fn compute_budget_ixs() -> Vec { - vec![ - ComputeBudgetInstruction::set_compute_unit_limit(125_000), - ComputeBudgetInstruction::set_compute_unit_price(1_000_000), - ] - } - - // ----------------- - // Process Commitables and Close Buffers - // ----------------- - pub(crate) fn process_commits_ix( - validator_auth: Pubkey, - pubkey: &Pubkey, - delegated_account_owner: &Pubkey, - buffer_pda: &Pubkey, - commit_args: CommitStateFromBufferArgs, - ) -> Instruction { - dlp_api::instruction_builder::commit_state_from_buffer( - validator_auth, - *pubkey, - *delegated_account_owner, - *buffer_pda, - commit_args, - ) - } - - pub(crate) fn close_buffers_ix( - validator_auth: Pubkey, - pubkey: &Pubkey, - commit_id: u64, - ) -> Instruction { - create_close_ix(CreateCloseIxArgs { - authority: validator_auth, - pubkey: *pubkey, - commit_id, - }) - } - - pub(crate) fn process_and_close_ixs( - validator_auth: Pubkey, - pubkey: &Pubkey, - delegated_account_owner: &Pubkey, - buffer_pda: &Pubkey, - commit_id: u64, - commit_args: CommitStateFromBufferArgs, - ) -> Vec { - let process_ix = process_commits_ix( - validator_auth, - pubkey, - delegated_account_owner, - buffer_pda, - commit_args, - ); - let close_ix = close_buffers_ix(validator_auth, pubkey, commit_id); - - vec![process_ix, close_ix] - } - - // ----------------- - // Finalize - // ----------------- - pub(crate) fn finalize_ix( - validator_auth: Pubkey, - pubkey: &Pubkey, - ) -> Instruction { - dlp_api::instruction_builder::finalize(validator_auth, *pubkey) - } - - // These tests statically determine the optimal ix count to fit into a single - // transaction and assert that the const we export in prod match those numbers. - // Thus when an instruction changes and one of those numbers with it a failing - // test alerts us. - // This is less overhead than running those static functions each time at - // startup. - - #[test] - fn test_max_process_per_tx() { - test_utils::init_test_logger(); - assert_eq!(super::MAX_PROCESS_PER_TX, max_process_per_tx()); - assert_eq!( - super::MAX_PROCESS_PER_TX_USING_LOOKUP, - max_process_per_tx_using_lookup() - ); - } - - #[test] - fn test_max_close_per_tx() { - test_utils::init_test_logger(); - assert_eq!(super::MAX_CLOSE_PER_TX, max_close_per_tx()); - assert_eq!( - super::MAX_CLOSE_PER_TX_USING_LOOKUP, - max_close_per_tx_using_lookup() - ); - } - - #[test] - fn test_max_process_and_closes_per_tx() { - test_utils::init_test_logger(); - assert_eq!( - super::MAX_PROCESS_AND_CLOSE_PER_TX, - max_process_and_close_per_tx() - ); - assert_eq!( - super::MAX_PROCESS_AND_CLOSE_PER_TX_USING_LOOKUP, - max_process_and_close_per_tx_using_lookup() - ); - } - - #[test] - fn test_max_finalize_per_tx() { - test_utils::init_test_logger(); - assert_eq!(super::MAX_FINALIZE_PER_TX, max_finalize_per_tx()); - assert_eq!( - super::MAX_FINALIZE_PER_TX_USING_LOOKUP, - max_finalize_per_tx_using_lookup() - ); - } - - #[test] - fn test_max_undelegate_per_tx() { - test_utils::init_test_logger(); - assert_eq!(super::MAX_UNDELEGATE_PER_TX, max_undelegate_per_tx()); - assert_eq!( - super::MAX_UNDELEGATE_PER_TX_USING_LOOKUP, - max_undelegate_per_tx_using_lookup() - ); - } - - // ----------------- - // Process Commitables using Args - // ----------------- - #[test] - fn test_log_commit_args_ix_sizes() { - test_utils::init_test_logger(); - // This test is used to investigate the size of the transaction related to - // the amount of committed accounts and their data size. - fn run(auth: &Keypair, ixs: usize) { - let mut tx_lines = vec![]; - use TransactionOpts::*; - for tx_opts in [NoLookupTable, UseLookupTable] { - let mut tx_sizes = vec![]; - for size in [0, 10, 20, 50, 100, 200, 500, 1024] { - let ixs = (0..ixs) - .map(|_| make_ix(auth, size)) - .collect::>(); - - let tx_size = - transaction_wire_size(auth, &ixs, &tx_opts).unwrap(); - tx_sizes.push((size, tx_size)); - } - tx_lines.push(tx_sizes); - } - let sizes = tx_lines - .into_iter() - .map(|line| { - line.into_iter() - .map(|(size, len)| format!("{:4}:{:5}", size, len)) - .collect::>() - .join("|") - }) - .collect::>() - .join("\n"); - info!(instruction_count = ixs, sizes = %sizes, "Transaction size report"); - } - fn make_ix(auth: &Keypair, data_size: usize) -> Instruction { - let data = vec![1; data_size]; - let args = CommitStateArgs { - data, - ..CommitStateArgs::default() - }; - dlp_api::instruction_builder::commit_state( - auth.pubkey(), - Pubkey::new_unique(), - Pubkey::new_unique(), - args, - ) - } - - let auth = &Keypair::new(); - run(auth, 0); - run(auth, 1); - run(auth, 2); - run(auth, 5); - run(auth, 8); - run(auth, 10); - run(auth, 15); - run(auth, 20); - // This logs raw wire sizes. The sendability limit is - // MAX_TRANSACTION_WIRE_SIZE. - } - - // ----------------- - // Process Commitables and Close Buffers - // ----------------- - fn max_process_per_tx() -> u8 { - max_chunks_per_transaction("Max process per tx", |auth_pubkey| { - let pubkey = Pubkey::new_unique(); - let delegated_account_owner = Pubkey::new_unique(); - let buffer_pda = Pubkey::new_unique(); - let commit_args = CommitStateFromBufferArgs::default(); - vec![process_commits_ix( - auth_pubkey, - &pubkey, - &delegated_account_owner, - &buffer_pda, - commit_args, - )] - }) - } - - fn max_process_per_tx_using_lookup() -> u8 { - max_chunks_per_transaction_using_lookup_table( - "Max process per tx using lookup", - |auth_pubkey, committee, delegated_account_owner| { - let buffer_pda = Pubkey::new_unique(); - let commit_args = CommitStateFromBufferArgs::default(); - vec![process_commits_ix( - auth_pubkey, - &committee, - &delegated_account_owner, - &buffer_pda, - commit_args, - )] - }, - None, - ) - } - - fn max_close_per_tx() -> u8 { - let commit_id = 0; - max_chunks_per_transaction("Max close per tx", |auth_pubkey| { - let pubkey = Pubkey::new_unique(); - vec![close_buffers_ix(auth_pubkey, &pubkey, commit_id)] - }) - } - - fn max_close_per_tx_using_lookup() -> u8 { - let commit_id = 0; - max_chunks_per_transaction_using_lookup_table( - "Max close per tx using lookup", - |auth_pubkey, committee, _| { - vec![close_buffers_ix(auth_pubkey, &committee, commit_id)] - }, - None, - ) - } - - fn max_process_and_close_per_tx() -> u8 { - let commit_id = 0; - max_chunks_per_transaction( - "Max process and close per tx", - |auth_pubkey| { - let pubkey = Pubkey::new_unique(); - let delegated_account_owner = Pubkey::new_unique(); - let buffer_pda = Pubkey::new_unique(); - let commit_args = CommitStateFromBufferArgs::default(); - process_and_close_ixs( - auth_pubkey, - &pubkey, - &delegated_account_owner, - &buffer_pda, - commit_id, - commit_args, - ) - }, - ) - } - - fn max_process_and_close_per_tx_using_lookup() -> u8 { - let commit_id = 0; - max_chunks_per_transaction_using_lookup_table( - "Max process and close per tx using lookup", - |auth_pubkey, committee, delegated_account_owner| { - let commit_args = CommitStateFromBufferArgs::default(); - let buffer_pda = Pubkey::new_unique(); - process_and_close_ixs( - auth_pubkey, - &committee, - &delegated_account_owner, - &buffer_pda, - commit_id, - commit_args, - ) - }, - None, - ) - } - - // ----------------- - // Finalize - // ----------------- - fn max_finalize_per_tx() -> u8 { - max_chunks_per_transaction("Max finalize per tx", |auth_pubkey| { - let pubkey = Pubkey::new_unique(); - vec![finalize_ix(auth_pubkey, &pubkey)] - }) - } - - fn max_finalize_per_tx_using_lookup() -> u8 { - max_chunks_per_transaction_using_lookup_table( - "Max finalize per tx using lookup", - |auth_pubkey, committee, _| { - vec![finalize_ix(auth_pubkey, &committee)] - }, - Some(40), - ) - } - - // ----------------- - // Undelegate - // ----------------- - fn max_undelegate_per_tx() -> u8 { - max_chunks_per_transaction("Max undelegate per tx", |auth_pubkey| { - let pubkey = Pubkey::new_unique(); - let owner_program = Pubkey::new_unique(); - vec![dlp_api::instruction_builder::undelegate( - auth_pubkey, - pubkey, - owner_program, - auth_pubkey, - )] - }) - } - - fn max_undelegate_per_tx_using_lookup() -> u8 { - max_chunks_per_transaction_using_lookup_table( - "Max undelegate per tx using lookup", - |auth_pubkey, committee, owner_program| { - vec![dlp_api::instruction_builder::undelegate( - auth_pubkey, - committee, - owner_program, - auth_pubkey, - )] - }, - None, - ) - } - - // ----------------- - // Max Chunks Per Transaction - // ----------------- - - fn max_chunks_per_transaction Vec>( - label: &str, - create_ixs: F, - ) -> u8 { - info!(test_label = label, "Starting transaction chunking test"); - - let auth = Keypair::new(); - let auth_pubkey = auth.pubkey(); - // NOTE: the size of the budget instructions is always the same, no matter - // which budget we provide - let mut ixs = compute_budget_ixs(); - let mut chunks = 0_u8; - loop { - ixs.extend(create_ixs(auth_pubkey)); - chunks += 1; - - // SAFETY: runs statically - let versioned_msg = - Message::try_compile(&auth_pubkey, &ixs, &[], Hash::default()) - .unwrap(); - // SAFETY: runs statically - let versioned_tx = VersionedTransaction::try_new( - VersionedMessage::V0(versioned_msg), - &[&auth], - ) - .unwrap(); - let tx_size = serialized_transaction_size(&versioned_tx); - info!( - chunks = chunks, - size_bytes = tx_size, - "Transaction size measured" - ); - if tx_size > MAX_TRANSACTION_WIRE_SIZE { - return chunks - 1; - } - } - } - - fn extend_lookup_table( - lookup_table: &mut AddressLookupTableAccount, - auth_pubkey: Pubkey, - committee: Pubkey, - owner: Option<&Pubkey>, - ) { - let mut keys = HashSet::from([ - committee, - pda::delegation_record_pda_from_delegated_account(&committee), - pda::delegation_metadata_pda_from_delegated_account(&committee), - pda::commit_state_pda_from_delegated_account(&committee), - pda::commit_record_pda_from_delegated_account(&committee), - pda::undelegate_buffer_pda_from_delegated_account(&committee), - auth_pubkey, - system_program::id(), - dlp_api::id(), - pda::fees_vault_pda(), - pda::validator_fees_vault_pda_from_validator(&auth_pubkey), - committor_program_id(), - ]); - if let Some(owner) = owner { - keys.insert(pda::program_config_from_program_id(owner)); - } - keys.extend(lookup_table.addresses.iter().cloned()); - lookup_table.addresses = keys.into_iter().collect(); - assert!( - lookup_table.addresses.len() <= LOOKUP_TABLE_MAX_ADDRESSES, - "Lookup table has too many ({}) addresses", - lookup_table.addresses.len() - ); - } - - fn max_chunks_per_transaction_using_lookup_table< - FI: Fn(Pubkey, Pubkey, Pubkey) -> Vec, - >( - label: &str, - create_ixs: FI, - start_at: Option, - ) -> u8 { - info!(test_label = label, start_at = ?start_at, "Starting lookup table transaction test"); - let auth = Keypair::new(); - let auth_pubkey = auth.pubkey(); - let mut ixs = compute_budget_ixs(); - let mut chunks = start_at.unwrap_or_default(); - let mut lookup_table = AddressLookupTableAccount { - key: Pubkey::default(), - addresses: vec![], - }; - // If we start at specific chunk size let's prep the ixs and assume - // we are using the same addresses to avoid blowing out the lookup table - if chunks > 0 { - let committee = Pubkey::new_unique(); - let owner_program = Pubkey::new_unique(); - extend_lookup_table( - &mut lookup_table, - auth_pubkey, - committee, - Some(&owner_program), - ); - for _ in 0..chunks { - ixs.extend(create_ixs(auth_pubkey, committee, owner_program)); - } - } - loop { - let committee = Pubkey::new_unique(); - let owner_program = Pubkey::new_unique(); - ixs.extend(create_ixs(auth_pubkey, committee, owner_program)); - - chunks += 1; - extend_lookup_table( - &mut lookup_table, - auth_pubkey, - committee, - Some(&owner_program), - ); - - // SAFETY: runs statically - let versioned_msg = Message::try_compile( - &auth_pubkey, - &ixs, - &[lookup_table.clone()], - Hash::default(), - ) - .unwrap(); - // SAFETY: runs statically - let versioned_tx = VersionedTransaction::try_new( - VersionedMessage::V0(versioned_msg), - &[&auth], - ) - .unwrap(); - let tx_size = serialized_transaction_size(&versioned_tx); - info!( - chunks = chunks, - size_bytes = tx_size, - "Transaction size measured with lookup table" - ); - if tx_size > MAX_TRANSACTION_WIRE_SIZE { - return chunks - 1; - } - } - } -} diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index 36289e04e..d0bdcbedf 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -3050,7 +3050,7 @@ dependencies = [ "borsh 1.7.0", "color-backtrace", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "rand 0.8.6", "rayon", "serde", @@ -3531,7 +3531,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-metrics", "magicblock-program", "solana-hash 4.2.0", @@ -3647,7 +3647,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-ledger", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", @@ -3709,7 +3709,7 @@ dependencies = [ "magicblock-aml", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", "parking_lot", @@ -3778,7 +3778,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-committor-program", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3802,7 +3802,6 @@ dependencies = [ "solana-transaction", "solana-transaction-error 3.1.0", "solana-transaction-status-client-types", - "static_assertions", "thiserror 2.0.18", "tokio", "tokio-util", @@ -3892,7 +3891,7 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" version = "3.0.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d#074a1a4175faea2e47b745e15dcabecb046e815d" +source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71#26d01c4b5c0c29acbebd41d14b303e1608bbaa71" dependencies = [ "bincode", "borsh 0.10.4", @@ -4051,7 +4050,7 @@ dependencies = [ "bincode", "lazy_static", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-magic-program-api 0.13.3", "num-derive", "num-traits", @@ -4209,7 +4208,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.13.3" dependencies = [ - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -5058,7 +5057,7 @@ version = "0.0.0" dependencies = [ "borsh 1.7.0", "ephemeral-rollups-sdk", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-magic-program-api 0.13.3", "rkyv 0.7.46", "solana-program 3.0.0", @@ -5946,7 +5945,7 @@ dependencies = [ "anyhow", "borsh 1.7.0", "integration-test-tools", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "program-schedulecommit", "solana-commitment-config", "solana-compute-budget-interface", @@ -5968,7 +5967,7 @@ dependencies = [ "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -5996,7 +5995,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-magic-program-api 0.13.3", "magicblock-program", "program-schedulecommit", @@ -6017,7 +6016,7 @@ name = "schedulecommit-test-security" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-magic-program-api 0.13.3", "program-schedulecommit", "program-schedulecommit-security", @@ -9796,7 +9795,7 @@ dependencies = [ "integration-test-tools", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9823,7 +9822,7 @@ dependencies = [ "magicblock-aml", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "program-flexi-counter", "program-mini", "solana-account 3.4.0", @@ -9849,7 +9848,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9919,7 +9918,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "program-flexi-counter", "solana-commitment-config", "solana-rpc-client", @@ -9942,7 +9941,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-program", "magicblock-validator-admin", "solana-commitment-config", @@ -9988,7 +9987,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "log", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=074a1a4175faea2e47b745e15dcabecb046e815d)", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-magic-program-api 0.13.3", "program-flexi-counter", "solana-rpc-client-api", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index 43dbf1099..c4fd48dd2 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -63,7 +63,7 @@ magicblock-committor-program = { path = "../magicblock-committor-program", featu magicblock-committor-service = { path = "../magicblock-committor-service" } magicblock-config = { path = "../magicblock-config" } magicblock-core = { path = "../magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "074a1a4175faea2e47b745e15dcabecb046e815d", default-features = false } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "26d01c4b5c0c29acbebd41d14b303e1608bbaa71", default-features = false } magicblock-magic-program-api = { path = "../magicblock-magic-program-api" } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" } diff --git a/test-integration/programs/schedulecommit/src/lib.rs b/test-integration/programs/schedulecommit/src/lib.rs index a9361dcae..6caa9b031 100644 --- a/test-integration/programs/schedulecommit/src/lib.rs +++ b/test-integration/programs/schedulecommit/src/lib.rs @@ -199,18 +199,7 @@ pub enum ScheduleCommitInstruction { ScheduleCommitForOrderBook(ScheduleCommitType), - /// CPI into the delegation program to request undelegation for a - /// schedulecommit-owned PDA. - /// - /// # Account references - /// - **0.** `[WRITE, SIGNER]` Payer funding the request PDA - /// - **1.** `[]` Delegated schedulecommit PDA - /// - **2.** `[]` Schedulecommit owner program - /// - **3.** `[WRITE]` Undelegation request PDA - /// - **4.** `[]` Delegation record PDA - /// - **5.** `[]` Delegation metadata PDA - /// - **6.** `[]` System program - /// - **7.** `[]` Delegation program + /// CPI into DLP to request undelegation for a schedulecommit-owned PDA. RequestUndelegationCpi(Pubkey), } diff --git a/test-integration/schedulecommit/elfs/dlp.so b/test-integration/schedulecommit/elfs/dlp.so index 46e74a064f5b681d5fdf7c8ebb32c4ef2c992159..b8fa734fec45d3b4b2f52ad8989ebcbd9070e719 100755 GIT binary patch delta 95056 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 E0L1x(DgXcg diff --git a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs index c54a4a594..aa7419525 100644 --- a/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs +++ b/test-integration/schedulecommit/test-scenarios/tests/02_commit_and_undelegate.rs @@ -3,10 +3,7 @@ use std::{ time::{Duration, Instant}, }; -use dlp_api::{ - pda::undelegation_request_pda_from_delegated_account, - state::UndelegationRequest, -}; +use dlp_api::pda::undelegation_request_pda_from_delegated_account; use integration_test_tools::{ conversions::stringify_simulation_result, run_test, scheduled_commits::extract_scheduled_commit_sent_signature_from_logs, @@ -298,35 +295,6 @@ fn commit_and_undelegate_two_accounts_twice() -> ( (ctx, *sig, tx_res) } -fn assert_undelegation_request( - request_data: &[u8], - delegated_account: Pubkey, - rent_payer: Pubkey, -) { - let request = - UndelegationRequest::try_from_bytes_with_discriminator(request_data) - .unwrap(); - assert_eq!( - request.delegated_account.to_bytes(), - delegated_account.to_bytes(), - "request should target delegated account" - ); - assert_eq!( - request.owner_program.to_bytes(), - program_schedulecommit::id().to_bytes(), - "request should target schedulecommit owner program" - ); - assert_eq!( - request.rent_payer.to_bytes(), - rent_payer.to_bytes(), - "request rent payer should match chain payer" - ); - assert!( - request.expires_at_slot > request.created_slot, - "request should use a future timeout slot" - ); -} - fn wait_for_requested_undelegation_on_chain( ctx: &ScheduleCommitTestContext, pda: Pubkey, @@ -448,16 +416,6 @@ fn test_request_undelegation_commits_and_undelegates_one_account() { "request undelegation transaction failed: {request_res:?}" ); - if let Ok(request_data) = ctx.fetch_chain_account_data(request_pda) { - assert_undelegation_request( - &request_data, - *committee_pda, - payer_chain.pubkey(), - ); - } else { - debug!("Undelegation request was already consumed"); - } - wait_for_requested_undelegation_on_chain( &ctx, *committee_pda, diff --git a/test-integration/test-chainlink/src/ixtest_context.rs b/test-integration/test-chainlink/src/ixtest_context.rs index 8e0d2e301..8fff08e53 100644 --- a/test-integration/test-chainlink/src/ixtest_context.rs +++ b/test-integration/test-chainlink/src/ixtest_context.rs @@ -316,8 +316,6 @@ impl IxtestContext { let finalize_ix = dlp_api::instruction_builder::finalize( self.validator_kp.pubkey(), counter_pda, - program_flexi_counter::id(), - counter_auth.pubkey(), ); let undelegate_ix = dlp_api::instruction_builder::undelegate( self.validator_kp.pubkey(), diff --git a/test-integration/test-committor-service/tests/common.rs b/test-integration/test-committor-service/tests/common.rs index f5fe0af08..bbf90d47e 100644 --- a/test-integration/test-committor-service/tests/common.rs +++ b/test-integration/test-committor-service/tests/common.rs @@ -202,7 +202,7 @@ impl TaskInfoFetcher for MockTaskInfoFetcher { rent_payer: *pubkey, }, ) - }) + }) .collect()) } diff --git a/test-integration/test-committor-service/tests/utils/transactions.rs b/test-integration/test-committor-service/tests/utils/transactions.rs index 073caefca..5e01d0005 100644 --- a/test-integration/test-committor-service/tests/utils/transactions.rs +++ b/test-integration/test-committor-service/tests/utils/transactions.rs @@ -74,14 +74,6 @@ pub async fn fetch_tx_logs( rpc_client: &RpcClient, signature: &Signature, ) -> Vec { - try_fetch_tx_logs(rpc_client, signature).await.unwrap() -} - -#[allow(dead_code)] -pub async fn try_fetch_tx_logs( - rpc_client: &RpcClient, - signature: &Signature, -) -> Result, String> { // NOTE: we encountered the following error a few times which makes tests fail for the // wrong reason: // Error { @@ -111,10 +103,10 @@ pub async fn try_fetch_tx_logs( tracing::error!("Failed to get transaction: {}", err); retries -= 1; if retries == 0 { - return Err(format!( + panic!( "Failed to get transaction after {} retries", MAX_RETRIES - )); + ); } tokio::time::sleep(tokio::time::Duration::from_millis(100)) .await; @@ -124,18 +116,15 @@ pub async fn try_fetch_tx_logs( tx.transaction .meta .as_ref() - .ok_or_else(|| "Transaction metadata is missing".to_string())? + .unwrap() .log_messages .clone() - .ok_or_else(|| "Transaction log messages are missing".to_string()) + .unwrap_or_else(Vec::new) } #[allow(dead_code)] pub async fn print_tx_logs(rpc_client: &RpcClient, signature: &Signature) { - match try_fetch_tx_logs(rpc_client, signature).await { - Ok(logs) => println!("logs: {logs:#?}"), - Err(err) => println!("Unable to fetch logs for {signature}: {err}"), - } + println!("logs: {:#?}", fetch_tx_logs(rpc_client, signature).await); } async fn airdrop_and_confirm( From 8301499e468a66c2f45ccc52d58cf1d432472e02 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Tue, 7 Jul 2026 17:09:15 +0530 Subject: [PATCH 5/8] fix ci --- .../test-committor-service/tests/test_ix_commit_local.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test-integration/test-committor-service/tests/test_ix_commit_local.rs b/test-integration/test-committor-service/tests/test_ix_commit_local.rs index f28eaf88c..f7e5df7a8 100644 --- a/test-integration/test-committor-service/tests/test_ix_commit_local.rs +++ b/test-integration/test-committor-service/tests/test_ix_commit_local.rs @@ -189,7 +189,7 @@ async fn test_ix_commit_order_book_change_100_bytes() { async fn test_ix_commit_order_book_change_671_bytes() { commit_book_order_account( 671, - CommitStrategy::DiffBuffer, + CommitStrategy::DiffArgs, CommitIntentKind::Commit, ) .await; @@ -694,7 +694,7 @@ async fn test_ix_execute_intent_bundle_commit_and_commit_finalize_mixed() { &[1024, 2048], &[1024, 2048], &[], - expect_strategies(&[(CommitStrategy::DiffBufferWithLookupTable, 4)]), + expect_strategies(&[(CommitStrategy::DiffArgs, 4)]), ) .await; } From 8f9aebb1495ea4349fda1eda401b213f3875d3db Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Tue, 7 Jul 2026 19:46:45 +0530 Subject: [PATCH 6/8] Remove ObservedUndelegationRequestIdentity --- .agents/context/crates/magicblock-accounts.md | 2 - .../src/scheduled_commits_processor.rs | 83 +------------------ 2 files changed, 1 insertion(+), 84 deletions(-) diff --git a/.agents/context/crates/magicblock-accounts.md b/.agents/context/crates/magicblock-accounts.md index 78182765a..00952ddea 100644 --- a/.agents/context/crates/magicblock-accounts.md +++ b/.agents/context/crates/magicblock-accounts.md @@ -229,8 +229,6 @@ Do not replace this with an ordinary per-instance queue unless the Magic Program `intents_meta_map` is protected by a standard `Mutex`. Current critical sections are intentionally small: insert metadata and remove metadata by intent ID. Avoid holding this lock across `.await`, committor calls, Chainlink calls, scheduler execution, or expensive logging/formatting. -The code uses `expect(POISONED_MUTEX_MSG)` in the normal processing paths. One recovery cleanup path handles poisoning by logging and taking the inner map. Treat mutex poisoning as a serious invariant violation. - ### Owner-program undelegation requests `magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. The request account carries the delegated account and expiry slot only, so validator logic must verify the request PDA against the delegated account and must not depend on request-local owner, rent payer, or commit nonce fields. Current DLP finalize instructions do not undelegate; the committor finalizes state and then sends standalone DLP `Undelegate`. When `DelegationMetadata.undelegation_requester = OwnerProgram`, the committor includes the derived request PDA in `Undelegate`; DLP validates it and uses the delegation metadata rent payer to close both delegation and request accounts. diff --git a/magicblock-accounts/src/scheduled_commits_processor.rs b/magicblock-accounts/src/scheduled_commits_processor.rs index 7821c173c..7e42eb5dd 100644 --- a/magicblock-accounts/src/scheduled_commits_processor.rs +++ b/magicblock-accounts/src/scheduled_commits_processor.rs @@ -1,9 +1,4 @@ -use std::{ - collections::HashMap, - fmt, - sync::{Arc, Mutex, MutexGuard}, - time::Duration, -}; +use std::{fmt, sync::Arc, time::Duration}; use dlp_api::pda::undelegation_request_pda_from_delegated_account; use magicblock_account_cloner::ChainlinkCloner; @@ -26,37 +21,16 @@ use tokio::sync::broadcast; use tokio_util::sync::CancellationToken; use tracing::{debug, error, info, warn}; -const POISONED_MUTEX_MSG: &str = - "Mutex of ScheduledCommitsProcessorImpl internal state is poisoned"; const UNDELEGATION_REQUEST_MAX_ATTEMPTS: usize = 3; const UNDELEGATION_REQUEST_RETRY_BASE_DELAY: Duration = Duration::from_millis(100); pub type ChainlinkImpl = ProdChainlink; -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -struct ObservedUndelegationRequestIdentity { - expires_at_slot: u64, -} - -impl From<&ObservedUndelegationRequest> - for ObservedUndelegationRequestIdentity -{ - fn from(request: &ObservedUndelegationRequest) -> Self { - Self { - expires_at_slot: request.expires_at_slot, - } - } -} - -type ObservedUndelegationRequests = - HashMap; - #[derive(Debug)] enum ObservedUndelegationRequestError { Transient(&'static str), Schedule(TransactionError), - PoisonedMutex(&'static str), } impl ObservedUndelegationRequestError { @@ -72,7 +46,6 @@ impl fmt::Display for ObservedUndelegationRequestError { Self::Schedule(err) => { write!(f, "failed to schedule request: {err}") } - Self::PoisonedMutex(msg) => write!(f, "{msg}"), } } } @@ -83,7 +56,6 @@ pub struct ScheduledCommitsProcessorImpl { internal_transaction_scheduler: TransactionSchedulerHandle, validator_authority: Arc, latest_block_reader: Arc, - observed_undelegation_requests: Arc>, } trait LatestBlockReader: Send + Sync { @@ -112,7 +84,6 @@ impl ScheduledCommitsProcessorImpl { internal_transaction_scheduler, validator_authority: Arc::new(validator_authority), latest_block_reader: Arc::new(latest_block.clone()), - observed_undelegation_requests: Arc::new(Mutex::default()), } } @@ -123,7 +94,6 @@ impl ScheduledCommitsProcessorImpl { internal_transaction_scheduler: TransactionSchedulerHandle, validator_authority: Arc, latest_block: Arc, - observed_requests: Arc>, ) { loop { let request = tokio::select! { @@ -156,7 +126,6 @@ impl ScheduledCommitsProcessorImpl { &internal_transaction_scheduler, validator_authority.as_ref(), latest_block.as_ref(), - &observed_requests, &cancellation_token, ) .await; @@ -169,7 +138,6 @@ impl ScheduledCommitsProcessorImpl { internal_transaction_scheduler: &TransactionSchedulerHandle, validator_authority: &Keypair, latest_block: &dyn LatestBlockReader, - observed_requests: &Arc>, cancellation_token: &CancellationToken, ) { let mut attempt = 1; @@ -180,7 +148,6 @@ impl ScheduledCommitsProcessorImpl { internal_transaction_scheduler, validator_authority, latest_block, - observed_requests, ) .await; match result { @@ -235,7 +202,6 @@ impl ScheduledCommitsProcessorImpl { internal_transaction_scheduler: &TransactionSchedulerHandle, validator_authority: &Keypair, latest_block: &dyn LatestBlockReader, - observed_requests: &Arc>, ) -> Result<(), ObservedUndelegationRequestError> { if request.observed_slot >= request.expires_at_slot { warn!( @@ -261,21 +227,6 @@ impl ScheduledCommitsProcessorImpl { return Ok(()); } - let request_identity = - ObservedUndelegationRequestIdentity::from(&request); - { - let mut observed = Self::lock_observed_requests(observed_requests)?; - if observed.get(&request.request_pda) == Some(&request_identity) { - debug!( - request_pda = %request.request_pda, - delegated_account = %request.delegated_account, - "Skipping already observed undelegation request" - ); - return Ok(()); - } - observed.insert(request.request_pda, request_identity); - } - let delegated = match chainlink .accounts_delegated_on_base_and_er( &[request.delegated_account], @@ -285,10 +236,6 @@ impl ScheduledCommitsProcessorImpl { { Ok(value) => value.into_iter().next().unwrap_or(false), Err(err) => { - Self::remove_observed_request( - observed_requests, - &request.request_pda, - )?; error!( request_pda = %request.request_pda, delegated_account = %request.delegated_account, @@ -301,10 +248,6 @@ impl ScheduledCommitsProcessorImpl { } }; if !delegated { - Self::remove_observed_request( - observed_requests, - &request.request_pda, - )?; debug!( request_pda = %request.request_pda, delegated_account = %request.delegated_account, @@ -337,10 +280,6 @@ impl ScheduledCommitsProcessorImpl { ); if let Err(err) = internal_transaction_scheduler.execute(tx).await { - Self::remove_observed_request( - observed_requests, - &request.request_pda, - )?; return Err(ObservedUndelegationRequestError::Schedule(err)); } @@ -352,25 +291,6 @@ impl ScheduledCommitsProcessorImpl { Ok(()) } - fn lock_observed_requests<'a>( - observed_requests: &'a Arc>, - ) -> Result< - MutexGuard<'a, ObservedUndelegationRequests>, - ObservedUndelegationRequestError, - > { - observed_requests.lock().map_err(|_| { - ObservedUndelegationRequestError::PoisonedMutex(POISONED_MUTEX_MSG) - }) - } - - fn remove_observed_request( - observed_requests: &Arc>, - request_pda: &Pubkey, - ) -> Result<(), ObservedUndelegationRequestError> { - Self::lock_observed_requests(observed_requests)?.remove(request_pda); - Ok(()) - } - fn schedule_commit_and_undelegate_instruction( payer: &Pubkey, delegated_account: Pubkey, @@ -398,7 +318,6 @@ impl ScheduledCommitsProcessorImpl { self.internal_transaction_scheduler.clone(), self.validator_authority.clone(), self.latest_block_reader.clone(), - self.observed_undelegation_requests.clone(), )); } From dd1e1806d7f742908e8bc83030220b8da83b6046 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Wed, 8 Jul 2026 02:17:14 +0530 Subject: [PATCH 7/8] =?UTF-8?q?Move=20magicblock-accounts/src/scheduled=5F?= =?UTF-8?q?commits=5Fprocessor.rs=20=E2=9F=B6=20=20=20magicblock-services/?= =?UTF-8?q?src/undelegation=5Frequest=5Fservice.rs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agents/context/crate-map.md | 14 +- .agents/context/crates/magicblock-accounts.md | 414 +++++------------- .agents/context/crates/magicblock-api.md | 49 ++- .../crates/magicblock-committor-service.md | 23 +- .agents/context/crates/magicblock-core.md | 8 +- .agents/context/crates/magicblock-services.md | 111 ++++- .../crates/magicblock-validator-admin.md | 4 +- .agents/specs/validator-specification.md | 2 +- Cargo.lock | 22 +- docs/architecture.md | 6 +- magicblock-accounts/Cargo.toml | 13 - magicblock-accounts/src/lib.rs | 1 - magicblock-api/Cargo.toml | 1 - magicblock-api/src/errors.rs | 9 - magicblock-api/src/magic_validator.rs | 30 +- magicblock-services/Cargo.toml | 8 + magicblock-services/src/lib.rs | 1 + .../src/undelegation_request_service.rs | 6 +- test-integration/Cargo.lock | 35 +- 19 files changed, 313 insertions(+), 444 deletions(-) rename magicblock-accounts/src/scheduled_commits_processor.rs => magicblock-services/src/undelegation_request_service.rs (98%) diff --git a/.agents/context/crate-map.md b/.agents/context/crate-map.md index 1904ca0cd..39a0af0a7 100644 --- a/.agents/context/crate-map.md +++ b/.agents/context/crate-map.md @@ -36,16 +36,16 @@ The validator is performance-sensitive. When changing any crate on RPC, account | Crate | Purpose | Depends on | Used by | Notes | |---|---|---|---|---| -| `magicblock-chainlink` | Base-chain account/delegation coordination. | accounts-db, AML, config, core, magic-program API, metrics | account-cloner, accounts, aperture, API, magic program | Checks/clones remote accounts, tracks delegation state, coordinates base-layer reads. See `.agents/context/crates/magicblock-chainlink.md` before changing this crate. | -| `magicblock-account-cloner` | Fetches and injects base-layer accounts/programs into local validator state. | accounts-db, chainlink, committor-service, config, core, ledger, magic-program API, magic program, rpc-client | accounts, aperture, API | Distinguishes fee payer, delegated, and undelegated accounts; handles large/program clone paths. See `.agents/context/crates/magicblock-account-cloner.md` before changing this crate. | -| `magicblock-accounts` | Account manager and scheduled commit processing glue. | account-cloner, accounts-db, chainlink, committor-service, core, metrics, magic program | `magicblock-api` | Current active role is scheduled commit processing and pending intent recovery; see `.agents/context/crates/magicblock-accounts.md` before changing this crate. | +| `magicblock-chainlink` | Base-chain account/delegation coordination. | accounts-db, AML, config, core, magic-program API, metrics | account-cloner, aperture, API, magic program, services | Checks/clones remote accounts, tracks delegation state, coordinates base-layer reads and observed undelegation requests. See `.agents/context/crates/magicblock-chainlink.md` before changing this crate. | +| `magicblock-account-cloner` | Fetches and injects base-layer accounts/programs into local validator state. | accounts-db, chainlink, committor-service, config, core, ledger, magic-program API, magic program, rpc-client | aperture, API, services | Distinguishes fee payer, delegated, and undelegated accounts; handles large/program clone paths. See `.agents/context/crates/magicblock-account-cloner.md` before changing this crate. | +| `magicblock-accounts` | Legacy account config/error/trait compatibility crate. | committor-service | no active runtime consumer | Do not add new services here; current account lifecycle and scheduled-intent behavior live in chainlink/cloner, services, and committor-service. See `.agents/context/crates/magicblock-accounts.md` before changing this crate. | | `magicblock-aml` | External/cached risk-scoring integration. | `magicblock-config` (dev: `magicblock-core`) | `magicblock-chainlink` | Optional Range risk checks for post-delegation action signers; see `.agents/context/crates/magicblock-aml.md` before changing this crate. | ## Commit and base-layer settlement crates | Crate | Purpose | Depends on | Used by | Notes | |---|---|---|---|---| -| `magicblock-committor-service` | Executes scheduled base-layer intents: commit, undelegate, finalize, action. | committor program, core, metrics, magic program, rpc-client, table-mania | account-cloner, accounts, API | Durable commit pipeline; handles scheduling, transaction prep, buffers, ALTs, confirmations. See `.agents/context/crates/magicblock-committor-service.md` before changing this crate. | +| `magicblock-committor-service` | Executes scheduled base-layer intents: commit, undelegate, finalize, action. | committor program, core, metrics, magic program, rpc-client, table-mania | account-cloner, API | Durable commit pipeline; accepts scheduled intents, handles recovery, transaction prep, buffers, ALTs, confirmations. See `.agents/context/crates/magicblock-committor-service.md` before changing this crate. | | `magicblock-committor-program` | On-chain committor program. | none | `magicblock-committor-service` | Base-layer program side for changeset buffers/commit application; see `.agents/context/crates/magicblock-committor-program.md` before changing this crate. | | `magicblock-table-mania` | Address lookup table management. | metrics, rpc-client | `magicblock-committor-service` | Creates/extends/deactivates/closes ALTs needed by commit transactions. See `.agents/context/crates/magicblock-table-mania.md` before changing this crate. | @@ -63,7 +63,7 @@ The validator is performance-sensitive. When changing any crate on RPC, account |---|---|---|---|---| | `magicblock-task-scheduler` | Program-scheduled task/crank service. | config, core, ledger, magic program | `magicblock-api` | SQLite-backed delay queue, retries/backoff, scheduled transaction submission. See `.agents/context/crates/magicblock-task-scheduler.md` before changing this crate. | | `magicblock-replicator` | Primary/replica event replication over NATS JetStream. | accounts-db, config, core, ledger | `magicblock-api` | Preserves HA/replica replay behavior; primary and replica modes differ intentionally. | -| `magicblock-services` | Shared service utilities/adapters. | core, magic-program API | `magicblock-api` | Common service abstractions; keep generic. See `.agents/context/crates/magicblock-services.md` before changing this crate. | +| `magicblock-services` | Shared validator services/adapters. | account-cloner, chainlink, core, magic-program API, metrics, magic program | `magicblock-api` | Callback adapter and owner-program undelegation request observer. See `.agents/context/crates/magicblock-services.md` before changing this crate. | | `magicblock-metrics` | Metrics helpers and instrumentation. | none | RPC, ledger, processor, chainlink, committor, table-mania, API | Prefer adding observability here rather than ad-hoc metrics code. See `.agents/context/crates/magicblock-metrics.md` before changing this crate. | ## Tools and test support @@ -78,8 +78,8 @@ The validator is performance-sensitive. When changing any crate on RPC, account ## How to use this map - For transaction correctness, start with `magicblock-processor`, then inspect `magicblock-accounts-db`, `magicblock-ledger`, and `magicblock-program` interactions. -- For delegation or account cloning bugs, start with `magicblock-chainlink`, `magicblock-account-cloner`, and `magicblock-accounts`. -- For commit or undelegation bugs, start with `magicblock-program`, `magicblock-accounts`, and `magicblock-committor-service`. +- For delegation or account cloning bugs, start with `magicblock-chainlink` and `magicblock-account-cloner`; include `magicblock-services` when observed undelegation requests are involved. +- For commit or undelegation bugs, start with `magicblock-program`, `magicblock-committor-service`, and `magicblock-services` for request-triggered scheduling. - For RPC behavior, start with `magicblock-aperture`; check `magicblock-chainlink` if reads trigger cloning. - For validator lifecycle/startup/shutdown, start with `magicblock-api` and `magicblock-validator`. - When adding, removing, renaming, or repurposing a crate, update this file and `AGENTS.md` in the same change. diff --git a/.agents/context/crates/magicblock-accounts.md b/.agents/context/crates/magicblock-accounts.md index 00952ddea..7edc614ff 100644 --- a/.agents/context/crates/magicblock-accounts.md +++ b/.agents/context/crates/magicblock-accounts.md @@ -2,357 +2,169 @@ ## Purpose -`magicblock-accounts` is the validator-side glue between Magic Program scheduled intents, Chainlink account lifecycle tracking, and the committor service. In the current implementation it does **not** own the account-cloning manager described by its historical README; account fetching/cloning is owned by `magicblock-chainlink` and `magicblock-account-cloner`. This crate's active runtime responsibility is scheduled commit processing. +`magicblock-accounts` is currently a legacy compatibility crate. It remains in +the workspace because older account/scheduled-commit types are still exported, +but no production validator service is wired through this crate. -At a high level it: +Current source exports: -- exposes the `ScheduledCommitsProcessor` trait used by `magicblock-api`'s slot ticker; -- implements `ScheduledCommitsProcessorImpl`, which drains accepted `ScheduledIntentBundle`s from the Magic Program global transaction scheduler; -- forwards scheduled and recovered intent bundles to `magicblock-committor-service`; -- tracks per-intent metadata needed to signal `ScheduledCommitSent` back into local validator execution after base-layer intent execution finishes; -- notifies Chainlink when accounts are about to be undelegated so base-layer undelegation completion can be watched; -- starts a one-shot recovery pass for persisted pending intent bundles after ledger replay and account-bank reset. +- `config::*`, including the local historical `LifecycleMode`; +- `errors`, including legacy account and scheduled-commit error types; +- `traits::*`, including the legacy `ScheduledCommitsProcessor` trait. -This crate sits on the commit/undelegation settlement path and interacts with the transaction scheduler. It is not part of ordinary SVM transaction execution, but its ticker-triggered work can affect slot progression, local commit lifecycle state, Chainlink subscription state, and committor throughput. Avoid adding blocking work, unbounded locks, duplicate intent scheduling, or heavy per-intent processing without an explicit performance tradeoff. +This crate does **not** own active account fetching/cloning, scheduled intent +execution, owner-program undelegation request handling, or committor delivery. -## Update requirement +Current owners: -Update this document in the same change whenever behavior in `magicblock-accounts` changes, or when another crate changes the flows/contracts consumed here. Update it for changes to: +- account fetching/cloning: `magicblock-chainlink` and + `magicblock-account-cloner`; +- scheduled intent acceptance, result handling, and pending-intent recovery: + `magicblock-committor-service/src/service.rs` and + `magicblock-committor-service/src/service/intent_client.rs`; +- owner-program `UndelegationRequest` observation and local + `ScheduleCommitAndUndelegate` submission: + `magicblock-services/src/undelegation_request_service.rs`; +- validator startup/shutdown wiring: `magicblock-api/src/magic_validator.rs`. -- `ScheduledCommitsProcessor` trait methods or `ScheduledCommitsProcessorImpl::new` wiring; -- scheduled intent draining, metadata tracking, result processing, or `SentCommit` construction; -- pending intent recovery timing, delegation checks, or recovered scheduling behavior; -- Chainlink undelegation notification behavior; -- Magic Program scheduled intent types, `TransactionScheduler` global state, `ScheduledCommitSent`, or `SentCommit` fields; -- committor result subscription, broadcast error handling, patched-error/callback-report handling, or execution-output variants; -- startup/shutdown ordering in `magicblock-api` that affects this processor; -- validation commands or integration suites relevant to schedule intents, commits, or undelegation; -- performance characteristics of scheduled commit processing, result handling, or recovery. +Do not add new runtime services here just because the crate name says +`accounts`. Prefer the current owner crate for the behavior being changed. -For the general documentation-update rule, see `.agents/memory/agent-memory-and-docs.md`. +## Update Requirement -## Where it sits in the repository +Update this document in the same change when: -Primary files and nearby contracts: +- this crate gains or loses exports; +- the legacy `ScheduledCommitsProcessor` trait or account error surface changes; +- production wiring starts or stops depending on this crate; +- historical account-manager remnants are removed or intentionally revived. + +For the general documentation-update rule, see +`.agents/memory/agent-memory-and-docs.md`. + +## Where It Sits | Path | Role | |---|---| -| `magicblock-accounts/Cargo.toml` | Crate dependencies. Pulls in Chainlink/cloner aliases, committor service, core scheduler types, metrics, and Magic Program scheduled intent types. | -| `magicblock-accounts/README.md` | Historical notes about an `AccountsManager`/`ensure_accounts` design. Treat source and this guide as canonical for current behavior. | -| `magicblock-accounts/src/lib.rs` | Public exports: `config::*`, `traits::*`, `errors`, and `scheduled_commits_processor`. | -| `magicblock-accounts/src/config.rs` | Defines a local `LifecycleMode` enum and `requires_ephemeral_validation`; currently no tracked consumer uses this type. Do not confuse it with `magicblock-config::config::LifecycleMode`, which is the validator config type in use. | -| `magicblock-accounts/src/traits.rs` | Defines the `ScheduledCommitsProcessor` async trait consumed by the API slot ticker. | -| `magicblock-accounts/src/scheduled_commits_processor.rs` | Main implementation: scheduled intent draining, committor scheduling, pending recovery, Chainlink undelegation notifications, result subscription loop, and `SentCommit` signaling. | -| `magicblock-accounts/src/errors.rs` | Error enums and result aliases for scheduled commit processing plus older account/committor error variants. | -| `magicblock-api/src/magic_validator.rs` | Production wiring. Constructs `ScheduledCommitsProcessorImpl`, starts recovery after replay/reset, passes it to the slot ticker, and stops it before stopping the committor service. | -| `magicblock-api/src/tickers.rs` | Slot ticker checks `MagicContext::has_scheduled_commits`, executes `AcceptScheduleCommits`, then calls `ScheduledCommitsProcessor::process`. | -| `programs/magicblock/src/magic_context.rs` | `MagicContext` storage and `has_scheduled_commits` fast check used by the slot ticker. | -| `programs/magicblock/src/schedule_transactions/process_accept_scheduled_commits.rs` | Magic Program instruction that moves scheduled intents from `MagicContext` into global `TransactionScheduler` state. | -| `programs/magicblock/src/magic_scheduled_base_intent.rs` | Defines `ScheduledIntentBundle`, `MagicIntentBundle`, and helpers such as `get_all_committed_pubkeys` / `has_undelegate_intent`. | -| `magicblock-committor-service/src/service.rs` | `BaseIntentCommittor` trait and `CommittorService` oneshot APIs used by this crate. | -| `magicblock-committor-service/src/committor_processor.rs` | Persists and schedules normal intents; loads pending intent bundles for recovery; schedules recovered bundles without re-persisting. | -| `test-integration/test-schedule-intent/` and `test-integration/schedulecommit/` | Integration coverage for schedule intent, commit, and commit-and-undelegate behavior. | - -Main consumers: - -- `magicblock-api` is the only production consumer of `ScheduledCommitsProcessorImpl`. -- `magicblock-api::tickers` depends on the `ScheduledCommitsProcessor` trait rather than the concrete implementation. -- The committor service is the downstream executor for base-layer intents. -- Chainlink is notified when accounts are entering undelegation so it can watch/update base-layer state. -- The Magic Program is both upstream (schedules/accepts intents) and downstream (receives local `ScheduledCommitSent` signals). - -Important boundaries: - -- This crate does not fetch or clone transaction accounts for ordinary execution; use `magicblock-chainlink` / `magicblock-account-cloner` for account availability changes. -- This crate does not build base-layer commit transactions; that belongs to `magicblock-committor-service`. -- This crate does not enforce final SVM writable-account access rules; that belongs to the processor/SVM path. - -## Public API shape / Main public types and APIs +| `magicblock-accounts/Cargo.toml` | Minimal dependencies for the legacy config, traits, and errors. | +| `magicblock-accounts/src/lib.rs` | Public surface: `config::*`, `errors`, and `traits::*`. | +| `magicblock-accounts/src/config.rs` | Historical `LifecycleMode` and `requires_ephemeral_validation` helper. Current validator lifecycle config comes from `magicblock-config`, not this local enum. | +| `magicblock-accounts/src/traits.rs` | Legacy `ScheduledCommitsProcessor` trait. There is no current production implementation in this crate. | +| `magicblock-accounts/src/errors.rs` | Legacy account and scheduled-commit error types. Check for real consumers before adding variants. | +| `magicblock-accounts/README.md` | Historical account-manager notes. Treat it as stale unless source confirms the described API still exists. | + +The crate is still a workspace member and workspace dependency alias, but there +is no active production Rust consumer at the time of writing. + +## Public API Shape `magicblock-accounts/src/lib.rs` exports: ```rust mod config; pub mod errors; -pub mod scheduled_commits_processor; mod traits; pub use config::*; pub use traits::*; ``` -### `ScheduledCommitsProcessor` trait - -Defined in `src/traits.rs`: - -- `async fn process(&self) -> ScheduledCommitsProcessorResult<()>` drains accepted scheduled intents and hands them to the committor; -- `fn scheduled_commits_len(&self) -> usize` returns the count of accepted intents in Magic Program global scheduler state; -- `fn clear_scheduled_commits(&self)` clears that global scheduler state; -- `fn stop(&self)` cancels processor background work. - -The trait is `Send + Sync + 'static` and is used by `magicblock-api/src/tickers.rs` to keep slot ticker code generic. - -### `ScheduledCommitsProcessorImpl` - -Defined in `src/scheduled_commits_processor.rs` and constructed with: - -```rust -pub fn new( - committor: Arc, - chainlink: Arc, - internal_transaction_scheduler: TransactionSchedulerHandle, - latest_block: impl LatestBlockProvider, -) -> Self -``` - -Stored state: - -- `committor: Arc` schedules intent bundles and provides result broadcasts / pending persisted intents; -- `chainlink: Arc` receives `undelegation_requested(pubkey)` calls before commit-and-undelegate execution; -- `cancellation_token: CancellationToken` stops the result-processing loop; -- `intents_meta_map: Arc>>` maps intent IDs to local metadata needed when committor results return; -- `transaction_scheduler: magicblock_program::TransactionScheduler` accesses the Magic Program's global scheduled action store. - -Important public method outside the trait: - -- `spawn_pending_intents_recovery(self: &Arc)` starts a one-shot task that loads persisted pending intent bundles from committor storage, filters them through Chainlink delegation checks, and schedules recoverable bundles. It must run only after ledger replay and account-bank reset. - -### Type aliases - -- `InnerChainlinkImpl = ProdInnerChainlink` -- `ChainlinkImpl = ProdChainlink` - -These encode the current production Chainlink/cloner stack. If Chainlink generic wiring changes, update these aliases and this guide together. - -### Errors - -`ScheduledCommitsProcessorError` wraps: - -- `tokio::sync::oneshot::error::RecvError` when committor oneshot requests fail; -- boxed `CommittorServiceError` from scheduling, recovery, or result-subscription operations. - -`AccountsError` still contains broader account/committor/cloner variants from older APIs. Check whether a variant is actually consumed before relying on it for new behavior. - -## Runtime flows - -### Normal scheduled commit flow - -```text -program invokes Magic Program schedule instruction - -> MagicContext stores ScheduledIntentBundle(s) - -> slot ticker sees MagicContext::has_scheduled_commits - -> validator-signed AcceptScheduleCommits transaction runs locally - -> Magic Program moves bundles into global TransactionScheduler state - -> ScheduledCommitsProcessorImpl::process drains them - -> committor service persists/schedules base-layer intent execution - -> committor broadcasts result - -> processor registers SentCommit and schedules local ScheduledCommitSent transaction -``` - -Ordered details: - -1. User/program code schedules commit, commit-and-undelegate, commit-finalize, and/or action intent bundles through the Magic Program. -2. `magicblock-api::init_slot_ticker` periodically reads `MAGIC_CONTEXT_PUBKEY` from `AccountsDb` and calls `MagicContext::has_scheduled_commits`. -3. If there are pending scheduled commits, `handle_scheduled_commits` builds `InstructionUtils::accept_scheduled_commits(latest_block.blockhash)` and submits it through the internal `TransactionSchedulerHandle`. -4. `process_accept_scheduled_commits` validates the validator authority signer, drains `MagicContext::scheduled_base_intents`, and calls `TransactionScheduler::default().accept_scheduled_base_intent(...)`. -5. `ScheduledCommitsProcessorImpl::process` calls `take_scheduled_intent_bundles()` on its `magicblock_program::TransactionScheduler` handle. Empty drains are no-ops. -6. For non-empty drains it increments `magicblock_metrics::metrics::inc_committor_intents_count_by` and calls `process_intent_bundles`. -7. `prepare_intent_bundles_for_scheduling` stores `ScheduledBaseIntentMeta` for every intent ID and gathers pubkeys from undelegation intents. -8. `process_undelegation_requests` concurrently calls `chainlink.undelegation_requested(pubkey)` for gathered pubkeys; failures are logged but do not abort the commit. -9. The committor receives the bundles via `CommittorService::schedule_intent_bundles` and returns through a oneshot when scheduling is accepted. -10. The background `result_processor` receives `BroadcastedIntentExecutionResult`s from the committor broadcast channel. -11. `process_intent_result` removes the intent metadata, builds/registers a `SentCommit`, creates or reuses the `ScheduledCommitSent` transaction, encodes it with `with_encoded`, and submits it to the internal scheduler. - -Caveats: - -- The slot ticker has a TODO about possible delay between accepting and processing scheduled commits. Do not add extra sleeps or slow work to this path. -- `process_undelegation_requests` logs subscription failures and continues. That can leave undelegating accounts in a problematic local state; changing this policy is a lifecycle decision, not a local cleanup. -- `intents_meta_map` is keyed by intent ID. Duplicate IDs or unexpected duplicate results can cause missing metadata and are logged as errors. - -### Pending intent recovery flow - -```text -validator start/restart - -> ledger replay - -> account-bank reset/cleanup - -> spawn_pending_intents_recovery - -> committor loads persisted pending bundles - -> Chainlink verifies accounts delegated on base and ER - -> recoverable bundles schedule through committor without re-persisting -``` - -Ordered details: - -1. `magicblock-api::MagicValidator::start` processes ledger replay and clears Magic Program global scheduled actions before starting the normal slot ticker. -2. After account-bank reset, and only in the branch where replay/reset is performed, the API calls `processor.spawn_pending_intents_recovery()`. -3. `recover_pending_intents` asks the committor for `get_pending_intent_bundles().await??`. -4. `recoverable_intent_bundles` checks every bundle's committed pubkeys with `chainlink.accounts_delegated_on_base_and_er(&pubkeys, AccountFetchOrigin::GetAccount)`. -5. Bundles with any non-delegated account, or bundles whose checks error, are skipped and logged. -6. Recoverable bundles go through `process_intent_bundles` with `CommittorService::schedule_recovered_intent_bundles`, which schedules without re-persisting rows. -7. If scheduling recovered bundles fails, metadata for those intent IDs is removed to avoid stale entries. - -Caveats: - -- Recovery must happen after replay/reset because Chainlink delegation checks read local bank state. -- Recovery currently only runs when `MagicValidator::start` enters the replay/reset path. Changing startup branches can affect pending intent durability. -- Filtering requires all committed accounts in a bundle to be delegated on both base and ER; this protects against re-sending stale or already-undelegated work. +### Legacy `ScheduledCommitsProcessor` -### Result-to-local-signal flow +`src/traits.rs` defines: -When the committor completes an intent: +- `process`; +- `scheduled_commits_len`; +- `clear_scheduled_commits`; +- `stop`. -1. `BroadcastedIntentExecutionResult` includes the intent ID, success/error output, patched errors, and callback scheduling report. -2. `ScheduledBaseIntentMeta` supplies the original slot, blockhash, payer, committed pubkeys, optional prebuilt `sent_transaction`, and undelegation flag. -3. `build_sent_commit` converts execution output into chain signatures: - - `ExecutionOutput::SingleStage(signature)` becomes one signature; - - `ExecutionOutput::TwoStage { commit_signature, finalize_signature }` becomes two signatures; - - errors try to expose any available commit/finalize signatures through `err.signatures()`. -4. Patched errors and callback scheduling results are stringified into `SentCommit` fields. -5. `register_scheduled_commit_sent(sent_commit)` stores the result for the Magic Program's local `ScheduledCommitSent` processor. -6. The internal transaction scheduler executes the validator-signed `ScheduledCommitSent` transaction so local execution can observe the sent-commit result. +The active scheduled-intent service no longer consumes this trait. It lives in +`magicblock-committor-service` and accepts scheduled intents directly through an +internal ER intent client. -If the original intent did not carry a signed `sent_transaction`, the processor builds a new one with the current latest blockhash. This fallback is important for recovered intents reconstructed from persistence. +### Legacy Errors -### Shutdown flow +`src/errors.rs` still exposes `AccountsError`, +`ScheduledCommitsProcessorError`, and result aliases. Several variants refer to +historical account-manager or scheduled-commit flows. Before reusing one for new +behavior, confirm there is an active caller that will receive and handle it. -`MagicValidator::stop` cancels the validator token, then calls `scheduled_commits_processor.stop()` before `committor_service.stop()`. Preserve this ordering: the result processor must be told to stop while the committor is still available enough to shut down cleanly, and the committor is intentionally stopped last among these services. +## Important Caveats -## Important internals and caveats +### Do Not Revive Runtime Ownership Accidentally -### Magic Program global scheduler state +This crate was previously used for account/scheduled-commit glue, but that +responsibility has moved. New services should be placed where the active runtime +boundary is: -`magicblock_program::TransactionScheduler::default()` is used as a handle to global scheduled action state. The `AcceptScheduleCommits` instruction writes into that state, and `ScheduledCommitsProcessorImpl::process` drains it. During ledger replay, `magicblock-api` clears this state to avoid re-committing accepted intents replayed from the ledger. +- `magicblock-services` for small validator background services and adapters; +- `magicblock-committor-service` for base-layer intent execution and recovery; +- `magicblock-chainlink` / `magicblock-account-cloner` for account lifecycle and + cloning; +- `magicblock-api` for startup/shutdown orchestration. -Do not replace this with an ordinary per-instance queue unless the Magic Program and replay semantics are updated together. +### Historical README/API Drift -### Metadata map and locking +The README describes older names such as `AccountsManager`, +`ExternalAccountsManager`, `BankAccountProvider`, `RemoteAccountCloner`, +`Transwise`, and `ensure_accounts`. These are not present in the current crate +source. Do not implement new features against those names without first checking +current Chainlink/cloner/API ownership and updating or removing stale docs. -`intents_meta_map` is protected by a standard `Mutex`. Current critical sections are intentionally small: insert metadata and remove metadata by intent ID. Avoid holding this lock across `.await`, committor calls, Chainlink calls, scheduler execution, or expensive logging/formatting. +### Local `LifecycleMode` Drift -### Owner-program undelegation requests +`magicblock-accounts/src/config.rs` defines a `LifecycleMode` separate from +`magicblock-config::config::LifecycleMode`. Current repository usages of +validator lifecycle mode use `magicblock-config`, not this local type. Avoid +adding new configuration wiring through the local enum unless that duplication +is intentional and documented. -`magicblock-api` starts `ScheduledCommitsProcessorImpl::spawn_undelegation_request_processor` for non-replica validators. That observer consumes Chainlink's observed Delegation Program `UndelegationRequest` updates and synthesizes the commit/finalize opportunity for owner-program requested undelegation. The request account carries the delegated account and expiry slot only, so validator logic must verify the request PDA against the delegated account and must not depend on request-local owner, rent payer, or commit nonce fields. Current DLP finalize instructions do not undelegate; the committor finalizes state and then sends standalone DLP `Undelegate`. When `DelegationMetadata.undelegation_requester = OwnerProgram`, the committor includes the derived request PDA in `Undelegate`; DLP validates it and uses the delegation metadata rent payer to close both delegation and request accounts. +## Change Guidance -### Undelegation notifications are best-effort - -Before scheduling an intent bundle, the processor calls `chainlink.undelegation_requested` for accounts from commit-and-undelegate intents. Errors are aggregated and logged but do not fail scheduling. This favors settlement progress over local watcher correctness; if you change it, document how accounts that are already locally immutable/undelegating recover from missed base-layer subscriptions. - -### Historical README/API drift - -The README describes `AccountsManager`, `ExternalAccountsManager`, `BankAccountProvider`, `RemoteAccountCloner`, `Transwise`, and `ensure_accounts`. These are not present in the current crate source. Do not implement new features against those names without first checking current Chainlink/cloner/API ownership and updating/removing stale docs. - -### Local `LifecycleMode` drift - -`magicblock-accounts/src/config.rs` defines a `LifecycleMode` separate from `magicblock-config::config::LifecycleMode`. Current repository usages of validator lifecycle mode use `magicblock-config`, not this local type. Avoid adding new configuration wiring through the local enum unless that duplication is intentional and documented. - -## Important invariants - -1. `process()` must drain only accepted scheduled intent bundles from Magic Program global scheduler state; it must not re-read `MagicContext` directly. -2. `AcceptScheduleCommits` must be executed before `process()` so MagicContext intents are moved and cleared atomically by the Magic Program. -3. Intent metadata must be inserted before committor scheduling so result processing can build a correct `SentCommit`. -4. Intent metadata must be removed on result handling and on failed recovered scheduling; stale entries can make later duplicate IDs or results misleading. -5. Recovery must run only after ledger replay and local account-bank reset, because delegation checks depend on current local account state. -6. Recovered bundles must be filtered so all committed accounts are delegated on base and ER before scheduling. -7. Recovered bundles must use the committor recovered scheduling path, not the normal persistence path, to avoid duplicating persisted rows. -8. Commit-and-undelegate intents must notify Chainlink before scheduling whenever possible so base-layer undelegation completion can be tracked. -9. The result processor must not block indefinitely on slow local scheduler work without observing cancellation between results. -10. Broadcast lag from committor results is unexpected and requires investigation; silently dropping lagged results would leave local sent-commit state incomplete. -11. `SentCommit` fields must stay aligned with Magic Program `ScheduledCommitSent` expectations, including chain signatures, patched errors, callback reports, included pubkeys, payer, slot, blockhash, and undelegation flag. -12. Documentation and code must not describe this crate as the active account ensure/cloning owner unless that behavior is restored in source. - -## Common change areas and what to inspect - -### Changing scheduled commit acceptance or slot ticker behavior +### Removing Legacy Surface Inspect first: -- `magicblock-api/src/tickers.rs` (`init_slot_ticker`, `handle_scheduled_commits`); -- `programs/magicblock/src/magic_context.rs` (`has_scheduled_commits`, `take_scheduled_commits`); -- `programs/magicblock/src/schedule_transactions/process_accept_scheduled_commits.rs`; -- `magicblock-accounts/src/scheduled_commits_processor.rs::process`. +- workspace and integration `Cargo.toml` files; +- `rg "magicblock_accounts|magicblock-accounts"`; +- `magicblock-api/src/errors.rs`; +- public downstream crates or examples if this crate is published. Risks: -- accepting without processing can leave intents stranded in global scheduler state; -- processing without accepting misses MagicContext-staged intents; -- replay can re-populate global scheduled actions unless startup clear semantics are preserved. +- deleting exported symbols can still be a public API break even when no + current workspace consumer uses them; +- tests or external users may still compile against the legacy traits/errors. -### Changing committor scheduling or result handling +### Adding New Account Lifecycle Behavior -Inspect first: - -- `ScheduledCommitsProcessorImpl::process_intent_bundles`; -- `prepare_intent_bundles_for_scheduling`; -- `result_processor`, `process_intent_result`, and `build_sent_commit`; -- `magicblock-committor-service/src/service.rs` `BaseIntentCommittor` methods; -- `magicblock-committor-service/src/intent_execution_manager/intent_execution_engine.rs` result fields. - -Risks: - -- missing result subscriptions can prevent local `ScheduledCommitSent` signaling; -- new `ExecutionOutput` variants must be converted into `SentCommit.chain_signatures` deliberately; -- callback or patched-error fields are user/operator-visible through Magic Program result state. - -### Changing undelegation lifecycle behavior - -Inspect first: +Start with: -- `prepare_intent_bundles_for_scheduling` and `process_undelegation_requests`; -- `magicblock-api/src/magic_validator.rs` startup wiring, especially whether the observed `UndelegationRequest` processor is spawned; -- `ScheduledIntentBundle::get_undelegate_intent_pubkeys` / `has_undelegate_intent`; -- `magicblock-chainlink::undelegation_requested`; -- Magic Program code that marks accounts undelegating/immutable when scheduling commit-and-undelegate. - -Risks: - -- missing Chainlink notification can leave local state out of sync with base-layer undelegation; -- failing the whole commit on notification errors may affect settlement availability; -- ordinary ER execution must not continue mutating accounts after commit-and-undelegate has been scheduled. - -### Changing pending intent recovery - -Inspect first: - -- `spawn_pending_intents_recovery`, `recover_pending_intents`, `recoverable_intent_bundles`, and `process_recovered_intent_bundles`; -- `magicblock-api/src/magic_validator.rs` startup ordering around replay/reset; -- `magicblock-committor-service/src/committor_processor.rs::pending_intent_bundles`; -- Chainlink `accounts_delegated_on_base_and_er` behavior. - -Risks: - -- running recovery before local bank repair can schedule invalid or stale commits; -- skipping delegation checks can re-send intents for accounts no longer delegated to this ER; -- normal scheduling can duplicate persistence rows for recovered work. - -### Cleaning up stale account-manager remnants - -Inspect first: - -- `magicblock-accounts/README.md`; -- `src/config.rs` and `src/errors.rs` for unused historical APIs; -- `.agents/context/crate-map.md` and this guide; -- current owners in `magicblock-chainlink`, `magicblock-account-cloner`, and `magicblock-api`. - -Risks: +- `magicblock-chainlink`; +- `magicblock-account-cloner`; +- `magicblock-services`; +- `magicblock-api/src/magic_validator.rs`. -- deleting exported symbols can be a public API break even if no current workspace consumer uses them; -- account availability behavior belongs outside this crate in the current architecture. +Do not put new account synchronization, DLP request scanning, or commit +scheduling loops in this crate without an explicit ownership decision. -## Tests and validation +## Tests And Validation -- Markdown-only guide changes: run `git diff --check` for this file; no Rust checks are needed. -- Rust changes in this crate: use `.agents/rules/testing-and-validation.md` or `mbv-check`; include focused package checks for `magicblock-accounts`. -- Related package checks by change area: `magicblock-api`, `magicblock-program`, and `magicblock-committor-service` for scheduled commits, pending recovery, or undelegation behavior. -- Relevant integration suites: `test-schedule-intents`, `test-committor`, and `test-task-scheduler`; use `.agents/rules/testing-and-validation.md` for exact setup/test commands. -- Performance validation intent: changes to slot-ticker commit processing, intent metadata handling, Chainlink undelegation notification, or result handling should report whether they add work to periodic slot processing, committor scheduling, or transaction-scheduler submission. +- Markdown-only guide changes: run `git diff --check`. +- Rust changes in this crate: run `cargo check -p magicblock-accounts`. +- If removing exports, also run the smallest affected consumer package checks + found by `rg`. +- If moving behavior out of or into this crate, also run checks for the new + owner crate and `magicblock-api`. -## Adjacent implementation references +## Adjacent References -- `.agents/context/crates/magicblock-account-cloner.md` — current account-cloner guide; useful because this crate aliases the production cloner stack through Chainlink. -- `.agents/context/crates/magicblock-chainlink.md` — Chainlink lifecycle/delegation guide, especially `undelegation_requested` and delegation checks. -- `magicblock-accounts/README.md` — historical summary; verify against source before using. -- `magicblock-api/src/tickers.rs` — slot ticker that invokes this crate. -- `magicblock-api/src/magic_validator.rs` — startup/shutdown and recovery wiring. -- `programs/magicblock/src/schedule_transactions/` — Magic Program scheduling and acceptance processors. -- `magicblock-committor-service/` — base-layer intent execution, persistence, and recovery source. -- `test-integration/test-schedule-intent/` and `test-integration/schedulecommit/` — integration coverage for schedule intent, commit, and commit-and-undelegate behavior. +- `.agents/context/crates/magicblock-services.md` - background service adapters, + including owner-program undelegation request observation. +- `.agents/context/crates/magicblock-committor-service.md` - scheduled intent + acceptance, execution, result notification, and recovery. +- `.agents/context/crates/magicblock-chainlink.md` - delegation/account lifecycle + coordination. +- `.agents/context/crates/magicblock-account-cloner.md` - base account/program + cloning. +- `.agents/context/crates/magicblock-api.md` - validator startup/shutdown wiring. diff --git a/.agents/context/crates/magicblock-api.md b/.agents/context/crates/magicblock-api.md index 29ba84ae7..63c650573 100644 --- a/.agents/context/crates/magicblock-api.md +++ b/.agents/context/crates/magicblock-api.md @@ -9,7 +9,7 @@ High-level responsibilities: - initialize persistent ledger and AccountsDb state; - sync and verify the validator keypair stored beside the ledger; - build genesis/sys accounts required by the local runtime; -- create Chainlink/account-cloning, committor, scheduled-commit, replication, metrics, task-scheduler, and Aperture RPC services; +- create Chainlink/account-cloning, committor/intent-execution, undelegation-request, replication, metrics, task-scheduler, and Aperture RPC services; - spawn transaction execution, RPC runtime, slot/system tickers, ledger truncation, and optional replication service threads/tasks; - transition the scheduler out of `StartingUp` after replay/reset/recovery; - register/unregister the validator in the Magic Domain Program and manage validator fee-vault setup in standalone ephemeral mode; @@ -24,7 +24,7 @@ Update this document in the same change whenever `magicblock-api` behavior or co - `MagicValidator::try_from_config`, `start`, `stop`, `prepare_ledger_for_shutdown`, or validator registration/unregistration behavior; - startup/shutdown ordering, service ownership, cancellation semantics, or thread/runtime spawning; - ledger, AccountsDb, keypair, genesis, MagicContext, ephemeral vault, or native mint initialization; -- Chainlink, committor, scheduled commit recovery, replication, task scheduler, RPC/Aperture, metrics, or ledger truncator wiring; +- Chainlink, committor/intent-execution, undelegation request service, replication, task scheduler, RPC/Aperture, metrics, or ledger truncator wiring; - scheduler mode transitions for standalone, primary, or replica roles; - MagicSys/commit nonce lookup behavior; - domain registry, fee vault, claim-fees, or other base-layer operator flows; @@ -43,7 +43,7 @@ For the general documentation-update rule, see `.agents/memory/agent-memory-and- | `magicblock-api/src/fund_account.rs` | Local genesis/runtime account seeding for validator identity, `MagicContext`, and ephemeral vault. | | `magicblock-api/src/genesis_utils.rs` | Local genesis account construction, native mint setup, and feature activation helpers. | | `magicblock-api/src/magic_sys_adapter.rs` | Adapter from Magic Program `MagicSys` trait calls to `CommittorService` commit-nonce lookups. | -| `magicblock-api/src/tickers.rs` | Slot ticker for accepting scheduled commits and system metrics ticker for storage/account gauges. | +| `magicblock-api/src/tickers.rs` | System metrics ticker for storage/account gauges. | | `magicblock-api/src/errors.rs` | `ApiError` and `ApiResult`, including boxed conversions from downstream service errors. | | `magicblock-api/README.md` | Short public usage example for constructing and starting `MagicValidator`. | | `magicblock-validator/src/main.rs` | Primary consumer: parses config, creates `MagicValidator`, takes the ledger lock, starts/stops the validator, and drives TUI/headless lifecycle. | @@ -56,7 +56,7 @@ Main consumers: - `test-integration/test-magicblock-api` directly uses `DomainRegistryManager` and exercises runtime behavior through integration contexts. - Other crates are mostly downstream services wired by this crate rather than consumers of it. -Important downstream dependencies include `magicblock-accounts-db`, `magicblock-ledger`, `magicblock-processor`, `magicblock-aperture`, `magicblock-chainlink`, `magicblock-account-cloner`, `magicblock-accounts`, `magicblock-committor-service`, `magicblock-replicator`, `magicblock-task-scheduler`, `magicblock-metrics`, `magicblock-services`, `magicblock-program`, and `magicblock-validator-admin`. +Important downstream dependencies include `magicblock-accounts-db`, `magicblock-ledger`, `magicblock-processor`, `magicblock-aperture`, `magicblock-chainlink`, `magicblock-account-cloner`, `magicblock-committor-service`, `magicblock-replicator`, `magicblock-task-scheduler`, `magicblock-metrics`, `magicblock-services`, `magicblock-program`, and `magicblock-validator-admin`. ## Public API shape / Main public types and APIs @@ -82,7 +82,6 @@ The exported public API is intentionally small for production use: Private but important internal APIs: - `MagicSysAdapter` implements `magicblock_core::traits::MagicSys` so Magic Program execution can synchronously ask the committor service for current commit nonces. -- `init_slot_ticker` periodically accepts scheduled commits through the transaction scheduler and then asks `ScheduledCommitsProcessor` to process them. - `init_system_metrics_ticker` periodically updates storage/account gauges. ## Runtime flows @@ -97,7 +96,7 @@ ValidatorParams -> chainlink/account cloner -> replication service (optional) -> metrics + system metrics ticker - -> scheduled commit processor + -> undelegation request service -> program loading + validator authority init -> transaction scheduler/execution thread -> Aperture RPC runtime thread @@ -116,7 +115,7 @@ Current order matters: 8. Create replication service if a broker was configured. 9. Insert missing genesis accounts, initialize validator identity, MagicContext, and ephemeral vault accounts. 10. Start metrics service and system metrics ticker. -11. Create the scheduled-commit processor if a committor service exists. +11. Create the undelegation request service for non-replica validators. 12. Load configured upgradeable programs and initialize Magic Program validator authority/override. 13. Build the SVM environment, transaction scheduler state, and executor count; spawn the transaction execution thread. 14. Build Aperture shared state and start the RPC server on its own Tokio runtime thread. @@ -135,28 +134,40 @@ Caveats: 3. After replay, Magic Program scheduled actions are cleared so replayed accept-commit transactions do not re-commit. 4. Optional AccountsDb defragmentation runs before normal work starts; this is explicitly marked safe only before cleanup, scheduler mode changes, replication, slot ticks, or task recovery. 5. Standalone/primary nodes reset the bank and, for primaries, send a replication `Message::Reset`. -6. Pending commit intent recovery runs only after replay and reset. +6. The intent execution service starts only after replay/reset and handles pending commit intent recovery before its normal accept loop. 7. Standalone nodes switch the scheduler to `SchedulerMode::Primary`; primary/replica modes spawn the replication service instead. 8. Standalone ephemeral nodes start background base-layer setup: funding check, magic fee vault init/delegation, optional startup fee claim, and optional domain registration. -9. Claim-fees periodic task, slot ticker, ledger truncator, and primary-only task scheduler are started. +9. The undelegation request service, claim-fees periodic task, intent execution service, ledger truncator, and primary-only task scheduler are started. -### Scheduled commit tick flow +### Scheduled intent service flow ```text -slot ticker sleep +intent execution service interval -> read MagicContext from AccountsDb -> if scheduled commits exist, execute AcceptScheduleCommits tx through scheduler - -> ScheduledCommitsProcessor::process() - -> committor service schedules base-layer work + -> take accepted ScheduledIntentBundle(s) + -> committor processor schedules base-layer work + -> result processor submits ScheduledCommitSent locally ``` -The ticker uses the same transaction scheduler path as normal execution for the validator-signed accept transaction. It currently has a known TODO about possible delay between accept and processing; do not hide or worsen that behavior without an explicit fix. +The accept transaction uses the same transaction scheduler path as normal execution. The scheduling/result loop lives in `magicblock-committor-service::service`, while this crate owns construction, start, and stop ordering. + +### Undelegation request service flow + +```text +Chainlink observes DLP UndelegationRequest + -> magicblock-services::UndelegationRequestService validates request/delegation + -> submit local ScheduleCommitAndUndelegate transaction + -> scheduled intent service accepts and executes the resulting intent +``` + +This service is started only for non-replica validators. ### Shutdown flow: `MagicValidator::stop` 1. Send unregister transaction in the background when standalone ephemeral on-chain coordination is enabled. 2. Set the local `exit` flag and cancel the shared cancellation token. -3. Stop scheduled commit processor, then committor service. The code comment says the committor service should be stopped last, but the current implementation stops it early after scheduled-commit processing; treat this ordering as compatibility-sensitive and inspect in-flight intent behavior before changing it. +3. Stop the undelegation request service, then the intent execution service. 4. Stop claim-fees task. 5. Join RPC thread, slot ticker, ledger truncator, replication thread, and transaction execution thread. 6. Flush AccountsDb. @@ -203,7 +214,7 @@ The ledger stores a validator keypair file beside the blockstore parent. With `v 1. Ledger replay, optional defragmentation, bank reset, pending intent recovery, and scheduler mode transition must remain ordered so execution does not race recovery or cleanup. 2. Replicas must not use enabled Chainlink or local cleanup in ways that diverge from primary-replicated state. -3. Scheduled commit recovery must run only after replay and reset, because it reads local account state for delegation checks. +3. Pending intent recovery must run only after replay and reset, because it reads local account state for delegation checks. 4. `MagicContext` must exist before the slot ticker can run, and it must remain Magic Program-owned and delegated locally. 5. Ephemeral vault initialization must preserve the ephemeral flag and Magic Program owner. 6. Validator identity must remain privileged in local AccountsDb. @@ -235,7 +246,7 @@ Inspect first: - `MagicValidator::stop`; - `prepare_ledger_for_shutdown` and `magicblock-validator/src/main.rs` shutdown sequence; -- downstream service `stop`/`join` semantics for scheduled commits, committor, ledger truncator, replication, transaction scheduler, task scheduler, and RPC. +- downstream service `stop`/`join` semantics for undelegation requests, intent execution, ledger truncator, replication, transaction scheduler, task scheduler, and RPC. Risks: @@ -270,7 +281,7 @@ Inspect first: Risks: -- missing local sys accounts causing startup or scheduled-commit ticker panics; +- missing local sys accounts causing startup or scheduled-intent accept loop panics; - changing account flags that SVM access validation relies on; - primary/replica genesis state divergence. @@ -298,7 +309,7 @@ Risks: ## Adjacent implementation references - `.agents/context/crates/magicblock-aperture.md` — RPC/pubsub service details wired by this crate. -- `.agents/context/crates/magicblock-account-cloner.md`, `.agents/context/crates/magicblock-accounts.md`, and `.agents/context/crates/magicblock-chainlink.md` — account sync and scheduled-commit dependencies wired by this crate. +- `.agents/context/crates/magicblock-account-cloner.md`, `.agents/context/crates/magicblock-chainlink.md`, `.agents/context/crates/magicblock-committor-service.md`, and `.agents/context/crates/magicblock-services.md` — account sync, scheduled-intent, and request-observer dependencies wired by this crate. - `magicblock-api/README.md` — short usage example for `MagicValidator`. - `magicblock-validator/src/main.rs` — production binary lifecycle around `MagicValidator`. - `test-integration/test-magicblock-api/` — integration tests for API-owned flows. diff --git a/.agents/context/crates/magicblock-committor-service.md b/.agents/context/crates/magicblock-committor-service.md index 70b4e7737..5023b3670 100644 --- a/.agents/context/crates/magicblock-committor-service.md +++ b/.agents/context/crates/magicblock-committor-service.md @@ -6,7 +6,7 @@ High-level responsibilities: -- expose `CommittorService` / `BaseIntentCommittor` as the async service boundary used by `magicblock-api`, `magicblock-accounts`, and account cloning; +- expose `CommittorService` / `BaseIntentCommittor` as the async service boundary used by `magicblock-api` and account cloning; - schedule intent bundles without executing mutually conflicting committed accounts in parallel; - fetch Delegation Program metadata, including commit nonces and rent payer data, plus base accounts needed for task construction; - choose commit delivery strategies: state args, diff args, state buffers, diff buffers, and optional ALTs; @@ -55,7 +55,7 @@ For the general documentation-update rule, see .agents/memory/agent-memory-and-d | `src/persist/` | SQLite persistence for commit rows, bundle signatures, status/strategy enums, and conversion utilities. | | `src/stubs/` | Feature-gated dev/test stub committor behind `dev-context-only-utils`. | | `magicblock-api/src/magic_validator.rs` | Starts the service at validator initialization with `committor_service.sqlite`, validator keypair, RPC URL, websocket URL, compute-unit price, and action callback scheduler. | -| `magicblock-accounts/src/scheduled_commits_processor.rs` | Main runtime producer/consumer: takes scheduled intent bundles from the transaction scheduler, schedules them with the committor, consumes result broadcasts, and performs pending-intent recovery after ledger replay. | +| `src/service.rs` and `src/service/intent_client.rs` | Runtime producer/consumer: accepts scheduled intent bundles from `MagicContext`, schedules them with the committor, consumes result broadcasts, submits `ScheduledCommitSent`, and performs pending-intent recovery after ledger replay. | | `magicblock-account-cloner/src/account_cloner.rs` | Uses `BaseIntentCommittor` for lookup-table reservation around account cloning and diagnostic mapping of committor errors. | | `magicblock-api/src/magic_sys_adapter.rs` | Fetches current commit nonces through the committor service for Magic syscalls. | | `test-integration/test-committor-service/` | Integration coverage for delivery preparators, transaction preparators, intent executor flows, and local commit execution. | @@ -136,14 +136,15 @@ magicblock-api::MagicValidator::init_committor_service -> actor run loop spawned on Tokio ``` -The service is initialized before the account manager starts pending-intent recovery. Pending recovery must run after ledger replay so local accounts reflect delegated state before recovered intents are checked. +The intent execution service is started after ledger replay/reset so pending recovery sees local accounts that reflect current delegated state before recovered intents are checked. ### Fresh scheduled intent flow ```text Magic Program schedules intent in ER - -> transaction scheduler exposes ScheduledIntentBundle(s) - -> magicblock-accounts::ScheduledCommitsProcessor::process + -> MagicContext stores ScheduledIntentBundle(s) + -> InternalIntentRpcClient executes AcceptScheduleCommits locally + -> TransactionScheduler exposes accepted ScheduledIntentBundle(s) -> CommittorService::schedule_intent_bundles -> CommittorProcessor::schedule_intent_bundle -> IntentPersisterImpl::start_base_intents @@ -152,19 +153,19 @@ Magic Program schedules intent in ER -> IntentScheduler blocks conflicts by committed pubkeys -> IntentExecutorImpl executes selected intent -> broadcast result - -> ScheduledCommitsProcessor consumes result and updates local/metadata state + -> IntentExecutionService consumes result and submits ScheduledCommitSent locally ``` `CommittorProcessor::schedule_intent_bundle` logs persistence failures but still tries to execute. This is intentionally loud because losing persistence weakens restart recovery; do not hide or downgrade that error path. ### Recovery flow for pending intents -1. `magicblock-accounts` calls `get_pending_intent_bundles()` after replay. +1. `IntentExecutionService` calls `pending_intent_bundles()` after replay/reset when it starts. 2. `CommittorProcessor::pending_intent_bundles` loads SQLite rows with `CommitStatus::Pending` and `created_at` inside the 14-day recovery window. 3. It fetches the current base-layer slot and reconstructs `ScheduledIntentBundle`s grouped by `message_id`. 4. Rows for a message must agree on ER slot and ER blockhash; otherwise that message is skipped. 5. Data-account rows without stored data are skipped because they cannot reconstruct a `CommittedAccount` safely. -6. `magicblock-accounts` filters recovered bundles against current delegated state, then calls `schedule_recovered_intent_bundles` so rows are not inserted again. +6. `IntentExecutionService` filters recovered bundles against current delegated state, then calls `schedule_recovered_intent_bundles` so rows are not inserted again. Preserve the no-repersist path for recovered intents. Re-inserting rows can violate primary keys or duplicate status history. @@ -272,7 +273,7 @@ The public service API uses nonblocking `try_send`. If the service channel is fu ### Changing service API, startup, or shutdown -Start with `src/service.rs`, `src/committor_processor.rs`, and `magicblock-api/src/magic_validator.rs`. Then inspect `magicblock-accounts/src/scheduled_commits_processor.rs`, `magicblock-account-cloner/src/account_cloner.rs`, and `magicblock-api/src/magic_sys_adapter.rs`. Check oneshot behavior, channel capacity/backpressure, cancellation, and whether consumers need errors instead of logged-only failures. +Start with `src/service.rs`, `src/service/intent_client.rs`, `src/committor_processor.rs`, and `magicblock-api/src/magic_validator.rs`. Then inspect `magicblock-account-cloner/src/account_cloner.rs` and `magicblock-api/src/magic_sys_adapter.rs`. Check oneshot behavior, channel capacity/backpressure, cancellation, and whether consumers need errors instead of logged-only failures. ### Changing scheduling or concurrency @@ -292,7 +293,7 @@ Start with `src/transaction_preparator/mod.rs` and `delivery_preparator.rs`, the ### Changing persistence or recovery -Start with `src/persist/db.rs`, `src/persist/commit_persister.rs`, `src/persist/types/`, and `src/committor_processor.rs` recovery helpers. Then inspect `magicblock-accounts/src/scheduled_commits_processor.rs`. Preserve schema compatibility, enum string values, `u64`/`i64` conversions, row grouping by `message_id`, 14-day recovery window, and no-repersist recovery scheduling. +Start with `src/persist/db.rs`, `src/persist/commit_persister.rs`, `src/persist/types/`, `src/committor_processor.rs` recovery helpers, and `src/service.rs` recovery filtering. Preserve schema compatibility, enum string values, `u64`/`i64` conversions, row grouping by `message_id`, 14-day recovery window, and no-repersist recovery scheduling. ### Changing metrics or observability @@ -312,6 +313,6 @@ Start with metric calls in `intent_execution_engine.rs`, `delivery_preparator.rs - `.agents/context/crates/magicblock-committor-program.md` — buffer/chunks on-chain helper contracts. - `.agents/context/crates/magicblock-rpc-client.md` — base-layer send/confirm and RPC helper behavior. - `.agents/context/crates/magicblock-table-mania.md` — ALT lifecycle and finalized-read semantics. -- `.agents/context/crates/magicblock-accounts.md` — scheduled commit processing and pending-intent recovery call sites. +- `.agents/context/crates/magicblock-services.md` — request-driven local scheduling that can create commit-and-undelegate intents. - `magicblock-committor-service/README.md` — high-level implementation notes. - `test-integration/test-committor-service/` — integration coverage of delivery and intent execution. diff --git a/.agents/context/crates/magicblock-core.md b/.agents/context/crates/magicblock-core.md index 06f23deae..3c34739df 100644 --- a/.agents/context/crates/magicblock-core.md +++ b/.agents/context/crates/magicblock-core.md @@ -55,7 +55,7 @@ Main consumers include: - `magicblock-processor`, which consumes `ValidatorChannelEndpoints`, executes `SchedulerCommand`s, drains `ExecutionTlsStash`, and emits account/status/replication messages; - `magicblock-replicator`, which consumes and publishes `link::replication::Message` and uses `wait_for_idle()` during checksum/reset operations; - `magicblock-ledger`, which replays persisted transactions through `TransactionSchedulerHandle::replay`; -- `magicblock-accounts`, `magicblock-account-cloner`, and `magicblock-task-scheduler`, which submit validator-internal transactions or consume scheduled tasks; +- `magicblock-committor-service`, `magicblock-services`, `magicblock-account-cloner`, and `magicblock-task-scheduler`, which submit validator-internal transactions, consume scheduled intents, or consume scheduled tasks; - `programs/magicblock`, which uses `MagicSys`, `CommittedAccount`, `BaseActionCallback`, coordination mode, and `ExecutionTlsStash`; - `magicblock-committor-service`, which consumes committed-account/action types and callback scheduling traits; - `magicblock-chainlink`, which uses token/eATA helpers and consolidated logging helpers. @@ -346,7 +346,8 @@ Start with: - `magicblock-core/src/traits.rs` - `programs/magicblock/src/magic_sys.rs` - `programs/magicblock/src/magic_scheduled_base_intent.rs` -- `magicblock-accounts/src/scheduled_commits_processor.rs` +- `magicblock-committor-service/src/service/intent_client.rs` +- `magicblock-services/src/undelegation_request_service.rs` - `magicblock-committor-service/src/` Check serialization, persistence, commit nonce behavior, callback error mapping, and base-layer settlement compatibility. @@ -389,6 +390,7 @@ Avoid adding high-cardinality or noisy logs to hot loops. Keep test logging idem - `.agents/context/crates/magicblock-api.md` — service wiring consumer of core endpoints. - `.agents/context/crates/magicblock-aperture.md` — RPC/account/status event consumer. - `.agents/context/crates/magicblock-account-cloner.md` — internal transaction submission consumer. -- `.agents/context/crates/magicblock-accounts.md` — scheduled commit consumer of core payloads. +- `.agents/context/crates/magicblock-committor-service.md` — scheduled intent consumer of core payloads. +- `.agents/context/crates/magicblock-services.md` — service adapters that submit validator-internal transactions. - `.agents/context/crates/magicblock-chainlink.md` — token/eATA helper and logging consumer. - `.agents/context/crates/magicblock-config.md` — config types that drive startup mode and service wiring. diff --git a/.agents/context/crates/magicblock-services.md b/.agents/context/crates/magicblock-services.md index 97c33d568..f0496e524 100644 --- a/.agents/context/crates/magicblock-services.md +++ b/.agents/context/crates/magicblock-services.md @@ -2,29 +2,32 @@ ## Purpose -`magicblock-services` contains small reusable service adapters that run alongside the validator and communicate through existing validator/RPC contracts. Its current responsibility is the action-callback adapter used by the committor pipeline to notify user callback programs about Magic Action results. +`magicblock-services` contains small reusable services and adapters that run alongside the validator and communicate through existing validator/RPC contracts. It currently owns the action-callback adapter used by the committor pipeline and the owner-program undelegation request service that turns observed Delegation Program requests into local `ScheduleCommitAndUndelegate` transactions. High-level responsibilities: - implement `magicblock_core::traits::ActionsCallbackScheduler` for validator-runtime use; - turn `BaseActionCallback` payloads from committed Magic Actions into local callback transactions; - wrap callback results in the `magicblock-magic-program-api` `MagicResponse::V1` wire shape; -- submit callback transactions asynchronously through Solana's nonblocking `RpcClient`. +- submit callback transactions asynchronously through Solana's nonblocking `RpcClient`; +- subscribe to Chainlink-observed Delegation Program `UndelegationRequest` accounts; +- validate request PDAs and delegated-account state before scheduling local validator-signed `ScheduleCommitAndUndelegate` transactions. -This crate is settlement-adjacent and can affect Magic Action user experience. It is not the committor itself, does not own intent execution or persistence, and must stay generic enough to be used as a service adapter rather than a protocol owner. +This crate is settlement-adjacent and can affect Magic Action user experience and undelegation liveness. It is not the committor itself, does not own base-layer intent execution or persistence, and should stay limited to service/adaptor boundaries rather than becoming a protocol owner. -End-to-end commit/undelegation semantics live in .agents/specs/validator-specification.md; this crate owns fire-and-forget local Magic Action callback transaction construction and scheduling. +End-to-end commit/undelegation semantics live in .agents/specs/validator-specification.md; this crate owns callback transaction construction/scheduling and request-observer submission of local schedule transactions. ## Update requirement Update this guide in the same change whenever behavior or contracts in `magicblock-services` change. In particular, update it for changes to: -- exported modules or public constructors in `magicblock-services/src/lib.rs` or `actions_callback_service.rs`; +- exported modules or public constructors in `magicblock-services/src/lib.rs`, `actions_callback_service.rs`, or `undelegation_request_service.rs`; - the `ActionsCallbackService` transaction layout, signer handling, blockhash source, or callback response encoding; +- the `UndelegationRequestService` request validation, retry policy, Chainlink checks, transaction layout, signer handling, blockhash source, or subscription/polling behavior; - how callback signatures, errors, receipts, discriminators, payloads, or account metas are propagated; - asynchronous send behavior, logging, retry/confirmation semantics, or Tokio runtime assumptions; -- call-site wiring in `magicblock-api` or committor expectations around `ActionsCallbackScheduler`; -- validation commands or integration suites relevant to action callbacks. +- call-site wiring in `magicblock-api`, committor expectations around `ActionsCallbackScheduler`, or Chainlink observer contracts consumed by the undelegation request service; +- validation commands or integration suites relevant to action callbacks or owner-program undelegation requests. Because callbacks are a cross-crate contract between Magic Program scheduling, committor execution, and user callback programs, also update this file when another crate changes `BaseActionCallback`, `MagicResponse`, `CallbackInstruction`, or `ActionsCallbackScheduler` semantics. @@ -34,19 +37,23 @@ For the general documentation-update rule, see .agents/memory/agent-memory-and-d | Path | Role | |---|---| -| `magicblock-services/Cargo.toml` | Package metadata and dependencies. Depends on `magicblock-core`, `magicblock-magic-program-api`, Solana transaction/RPC crates, Tokio, and tracing. | -| `magicblock-services/src/lib.rs` | Public module surface. Currently exports only `actions_callback_service`. | +| `magicblock-services/Cargo.toml` | Package metadata and dependencies. Depends on shared core/Magic Program types, Chainlink/cloner wiring, Solana transaction/RPC crates, Tokio, and tracing. | +| `magicblock-services/src/lib.rs` | Public module surface. Exports `actions_callback_service` and `undelegation_request_service`. | | `magicblock-services/src/actions_callback_service.rs` | Implements `ActionsCallbackService` and `ActionsCallbackScheduler`. Builds and sends callback transactions. | -| `magicblock-api/src/magic_validator.rs` | Runtime wiring. `init_committor_service` creates `ActionsCallbackService` with the validator keypair, local latest-block provider, and an RPC client pointed at the validator aperture HTTP endpoint. | +| `magicblock-services/src/undelegation_request_service.rs` | Implements `UndelegationRequestService`. Consumes observed DLP request accounts and schedules local `ScheduleCommitAndUndelegate` transactions. | +| `magicblock-api/src/magic_validator.rs` | Runtime wiring. `init_committor_processor` creates `ActionsCallbackService`; validator startup creates and starts `UndelegationRequestService` for non-replica validators. | | `magicblock-core/src/traits.rs` | Defines `ActionsCallbackScheduler`, `ActionResult`, `ActionError`, and `CallbackScheduleError`. | | `magicblock-core/src/intent.rs` | Defines `BaseActionCallback`, the callback payload this crate consumes. | +| `magicblock-chainlink` | Supplies `subscribe_undelegation_requests`, delegation-state checks, and `undelegation_requested` lifecycle notification. | | `magicblock-committor-service/src/intent_executor/utils.rs` | Extracts callbacks from action tasks and invokes the scheduler after success, action failure, or timeout. | | `programs/magicblock/src/schedule_transactions/process_add_action_callback.rs` | Magic Program path that attaches callbacks to scheduled base actions. | +| `programs/magicblock/src/schedule_transactions/process_schedule_commit.rs` | Magic Program path reached by the local `ScheduleCommitAndUndelegate` transaction. | Main consumers: -- `magicblock-api`, which constructs the concrete callback service for the validator; +- `magicblock-api`, which constructs the concrete callback service and undelegation request service for the validator; - `magicblock-committor-service`, which is generic over `ActionsCallbackScheduler` and calls it from intent execution; +- Chainlink, which publishes observed undelegation request updates consumed by this crate; - callback-capable Magic Action flows scheduled through `programs/magicblock`. There are no crate-local tests or README files for `magicblock-services` at the time of writing. Use the committor integration tests when callback behavior changes. @@ -58,8 +65,9 @@ There are no crate-local tests or README files for `magicblock-services` at the `src/lib.rs` exposes: - `pub mod actions_callback_service`. +- `pub mod undelegation_request_service`. -Keep this surface small. New shared services should be added only when they are truly generic validator service adapters and not better owned by API orchestration, committor, RPC-client, or Magic Program crates. +Keep this surface small. New shared services should be added only when they are truly validator background services/adapters and not better owned by API orchestration, committor, RPC-client, Chainlink, or Magic Program crates. ### `ActionsCallbackService` @@ -87,6 +95,35 @@ The service implements `Clone` when `L: Clone`. Cloning uses `authority.insecure The return value reports scheduling/build success, not confirmed on-chain callback execution. The spawned task logs send failures but does not retry or update the returned result after the fact. +### `UndelegationRequestService` + +`UndelegationRequestService` stores: + +- `Arc>` for observed request subscription, delegation checks, and undelegation tracking notification; +- `TransactionSchedulerHandle` for submitting local validator transactions; +- validator `Keypair` authority used as payer and signer; +- a `LatestBlockProvider` wrapper used to sign each local transaction with a fresh ER blockhash; +- a `CancellationToken` used by `stop`. + +Public API: + +```rust +UndelegationRequestService::new(chainlink, scheduler, authority, latest_block) +service.start() +service.stop() +``` + +`start` subscribes to Chainlink observed undelegation requests and spawns one background task. The service does not own request discovery itself; Chainlink owns base-layer subscription/scanning and emits `ObservedUndelegationRequest` values. + +For each observed request, the service: + +1. verifies the request PDA matches the delegated account; +2. checks the delegated account is delegated on base and ER; +3. best-effort notifies Chainlink with `undelegation_requested`; +4. submits a local validator-signed `ScheduleCommitAndUndelegate` transaction with payer, `MAGIC_CONTEXT_PUBKEY`, and delegated account. + +Transient delegation-check and local-scheduling failures are retried three times with short exponential backoff. Invalid request PDAs and non-delegated accounts are skipped. + ## Runtime flows ### Validator startup wiring @@ -98,6 +135,20 @@ The return value reports scheduling/build success, not confirmed on-chain callba Preserve this separation. `magicblock-services` should not reach back into validator orchestration or committor internals. +### Undelegation Request Service Startup + +```text +magicblock-api::MagicValidator::try_from_config + -> create UndelegationRequestService for non-replica validators +magicblock-api::MagicValidator::start + -> service.start() + -> Chainlink observed request subscription + -> local ScheduleCommitAndUndelegate transaction + -> committor scheduled-intent service handles the resulting Magic Program intent +``` + +Replica validators do not start this service because replica Chainlink is disabled and ownership/lifecycle decisions should come from primary state replication. + ### Callback scheduling and transaction construction ```text @@ -159,6 +210,14 @@ The callback instruction data combines a program-specific discriminator with a b `CallbackScheduleError` only covers local serialization/signing failures. RPC send failures are logged asynchronously with the callback transaction signature and do not flow back into `IntentExecutionReport` after `schedule` returns. +### Undelegation request observer boundary + +The undelegation request service is a trigger: it only schedules the local Magic Program intent. It does not build or send base-layer commit/undelegate transactions, persist intent rows, or decide committor task strategy. After local scheduling, the normal committor intent service accepts and executes the resulting scheduled intent. + +The service validates the request PDA from delegated account before scheduling. It must not trust request-local owner, rent payer, or commit nonce fields; current request data carries the delegated account and expiry slot only. + +The service logs expired requests but still schedules normal undelegation when the delegated account is still valid. This preserves the best chance of committing ER state and clearing lifecycle state instead of leaving timeout/rollback handling to a stale request. + ## Important invariants 1. `schedule` must return exactly one `Result` for each input callback, preserving input order. @@ -168,7 +227,13 @@ The callback instruction data combines a program-specific discriminator with a b 5. Inner account meta writability must be propagated from `BaseActionCallback`; this crate should not reinterpret callback account authorization. 6. The `Noop(counter)` uniqueness instruction must keep otherwise duplicate callback transactions from producing identical signatures. 7. Do not add blocking RPC confirmation or retry loops to the committor hot path without an explicit architecture decision and performance review. -8. Keep the crate dependency-light. Generic service adapters should not pull in validator orchestration, persistence, or large protocol owners. +8. Keep service dependencies scoped to the adapter. Do not pull validator orchestration or persistence into this crate. +9. `UndelegationRequestService` must verify the request PDA before scheduling. +10. `UndelegationRequestService` must schedule only when the delegated account is delegated on both base and ER. +11. `UndelegationRequestService` must use the validator authority as local transaction payer and signer. +12. Request observation must remain non-replica-only unless replica lifecycle semantics are redesigned. +13. The request service must not bypass the Magic Program scheduled-intent path or call the committor directly for owner-program requests. +14. Missing Chainlink `undelegation_requested` notification should be logged but must not prevent local scheduling under the current best-effort policy. ## Common change areas and what to inspect @@ -199,11 +264,24 @@ Do not make `schedule` block on network confirmation unless the committor timeou Start with: - `magicblock-api/src/magic_validator.rs::init_committor_service`; +- `magicblock-api/src/magic_validator.rs` construction/start/stop of `UndelegationRequestService`; - `magicblock-config` endpoint settings used by `config.aperture.listen.http()` and `config.rpc_url()`; - `magicblock-committor-service::CommittorService::try_start` generic bounds. Be explicit about whether callbacks should be sent to local aperture or base-layer RPC. +### Changing owner-program undelegation request handling + +Start with: + +- `magicblock-services/src/undelegation_request_service.rs`; +- `magicblock-chainlink` observed undelegation request subscription and delegation checks; +- `programs/magicblock/src/schedule_transactions/process_schedule_commit.rs`; +- `magicblock-committor-service/src/service.rs` and task building for accepted commit-and-undelegate intents; +- DLP request PDA and metadata semantics in `magicblock-delegation-program-api`. + +Check PDA validation, replica gating, retry behavior, local transaction accounts, blockhash freshness, and whether failures should be skipped, retried, or surfaced. + ### Adding another shared service adapter Start with `magicblock-services/src/lib.rs` and ask whether the new adapter belongs here. Prefer this crate only for small generic services that implement shared traits. Put orchestration in `magicblock-api`, settlement logic in `magicblock-committor-service`, RPC policy in `magicblock-rpc-client`, and protocol wire types in `magicblock-magic-program-api`. @@ -212,8 +290,8 @@ Start with `magicblock-services/src/lib.rs` and ask whether the new adapter belo - Markdown-only guide changes: run `git diff --check` for this file; no Rust checks are needed. - Rust changes in this crate: use `.agents/rules/testing-and-validation.md` or `mbv-check`; include focused package checks for `magicblock-services`. -- Consumer validation intent: because this crate has no crate-local tests, include relevant `magicblock-committor-service` checks for callback behavior changes. -- Relevant integration suites: committor suites that exercise action callbacks and timeouts; use `.agents/rules/testing-and-validation.md` for exact setup/test commands. +- Consumer validation intent: because this crate has limited crate-local coverage, include relevant `magicblock-committor-service` checks for callback behavior changes and request-driven undelegation integration checks for undelegation request changes. +- Relevant integration suites: committor suites that exercise action callbacks/timeouts, plus schedule-commit or undelegation request suites when `UndelegationRequestService` changes; use `.agents/rules/testing-and-validation.md` for exact setup/test commands. - Performance-risk validation intent: report any added synchronous RPC work, retries, confirmation, persistence, extra serialization, or unbounded spawning/logging and its effect on committor throughput and callback latency. @@ -221,7 +299,10 @@ Start with `magicblock-services/src/lib.rs` and ask whether the new adapter belo - `.agents/context/crates/magicblock-core.md` — `ActionsCallbackScheduler`, `BaseActionCallback`, and related shared trait/type contracts. - `.agents/context/crates/magicblock-api.md` — validator startup and service wiring. +- `.agents/context/crates/magicblock-chainlink.md` — observed undelegation request subscription and delegation lifecycle checks. +- `.agents/context/crates/magicblock-committor-service.md` — scheduled intent acceptance/execution after request service submits the local schedule transaction. - `.agents/context/crates/magicblock-magic-program-api.md` — callback instruction and response wire types. - `.agents/context/crates/magicblock-rpc-client.md` — relevant if callback delivery begins using shared send/confirm helpers. - `magicblock-committor-service/src/intent_executor/utils.rs` — committor callback scheduling call site. - `programs/magicblock/src/schedule_transactions/process_add_action_callback.rs` — Magic Program callback attachment path. +- `programs/magicblock/src/schedule_transactions/process_schedule_commit.rs` — Magic Program schedule path used by owner-program undelegation requests. diff --git a/.agents/context/crates/magicblock-validator-admin.md b/.agents/context/crates/magicblock-validator-admin.md index 08e3ec73e..9dad839b8 100644 --- a/.agents/context/crates/magicblock-validator-admin.md +++ b/.agents/context/crates/magicblock-validator-admin.md @@ -129,8 +129,8 @@ The periodic task uses the validator's configured RPC URL. Do not move it onto t ```text MagicValidator::stop - -> stop scheduled-commit processor - -> stop committor service + -> stop undelegation request service + -> stop intent execution service -> claim_fees_task.stop().await -> join RPC thread and remaining validator services ``` diff --git a/.agents/specs/validator-specification.md b/.agents/specs/validator-specification.md index 32775b816..41dd98eda 100644 --- a/.agents/specs/validator-specification.md +++ b/.agents/specs/validator-specification.md @@ -301,7 +301,7 @@ The committor service realizes scheduled base-layer intents. Its inputs are sche The documented commit pipeline is: 1. Magic Program schedules intents in MagicContext. -2. `magicblock-accounts` / scheduled commit processing picks up intents each slot. +2. `magicblock-committor-service` intent execution service accepts scheduled intents from `MagicContext` on its interval. 3. `magicblock-committor-service` schedules and executes intents. 4. Task building creates atomic base-layer tasks such as commit, undelegate, finalize, and action. 5. Task strategy packs tasks into valid transactions. diff --git a/Cargo.lock b/Cargo.lock index 9f17f4eca..3d33cd1a8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3505,24 +3505,11 @@ name = "magicblock-accounts" version = "0.13.3" dependencies = [ "async-trait", - "magicblock-account-cloner", - "magicblock-chainlink", "magicblock-committor-service", - "magicblock-core", - "magicblock-delegation-program-api", - "magicblock-metrics", - "magicblock-program", - "solana-hash 4.2.0", - "solana-instruction 3.3.0", - "solana-keypair", "solana-pubkey 4.1.0", - "solana-signer", - "solana-transaction", "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", - "tokio-util", - "tracing", "url", ] @@ -3627,7 +3614,6 @@ dependencies = [ "fd-lock", "magic-domain-program", "magicblock-account-cloner", - "magicblock-accounts", "magicblock-accounts-db", "magicblock-aperture", "magicblock-chainlink", @@ -4105,8 +4091,14 @@ version = "0.13.3" dependencies = [ "bincode", "futures-util", + "magicblock-account-cloner", + "magicblock-chainlink", "magicblock-core", + "magicblock-delegation-program-api", "magicblock-magic-program-api", + "magicblock-metrics", + "magicblock-program", + "solana-hash 4.2.0", "solana-instruction 3.3.0", "solana-keypair", "solana-message 3.1.0", @@ -4115,8 +4107,10 @@ dependencies = [ "solana-signature 3.3.0", "solana-signer", "solana-transaction", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", + "tokio-util", "tracing", ] diff --git a/docs/architecture.md b/docs/architecture.md index 0e77bbd3d..a0f51479d 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -179,9 +179,9 @@ loader-specific paths (V1→V3 conversion, V4 buffer + deploy). in the 5 MB `MagicContext` account. A second validator-signed instruction (`AcceptScheduleCommits`) moves staged intents to a global map — a deliberate two-stage flow across slot boundaries. -2. [`magicblock-accounts`](../magicblock-accounts) - (`ScheduledCommitsProcessorImpl`) picks intents up each slot (driven by the slot - ticker) and feeds [`magicblock-committor-service`](../magicblock-committor-service). +2. [`magicblock-committor-service`](../magicblock-committor-service) runs the + intent execution service, which periodically accepts staged intents from + `MagicContext`, schedules them, and reports `ScheduledCommitSent` locally. 3. The committor service builds base-chain transactions: [`tasks/task_strategist.rs`](../magicblock-committor-service/src/tasks/task_strategist.rs) packs commit tasks under CPI-depth limits (falling back to a two-stage diff --git a/magicblock-accounts/Cargo.toml b/magicblock-accounts/Cargo.toml index acd1da290..5b48785a5 100644 --- a/magicblock-accounts/Cargo.toml +++ b/magicblock-accounts/Cargo.toml @@ -9,23 +9,10 @@ edition.workspace = true [dependencies] async-trait = { workspace = true } -tracing = { workspace = true } -magicblock-account-cloner = { workspace = true } -magicblock-chainlink = { workspace = true } magicblock-committor-service = { workspace = true } -magicblock-core = { workspace = true } -magicblock-delegation-program-api = { workspace = true } -magicblock-metrics = { workspace = true } -magicblock-program = { workspace = true } -solana-hash = { workspace = true } -solana-instruction = { workspace = true } -solana-keypair = { workspace = true } solana-pubkey = { workspace = true } -solana-signer = { workspace = true } -solana-transaction = { workspace = true } solana-transaction-error = { workspace = true } tokio = { workspace = true } -tokio-util = { workspace = true } thiserror = { workspace = true } url = { workspace = true } diff --git a/magicblock-accounts/src/lib.rs b/magicblock-accounts/src/lib.rs index d11a013b2..c7eac2118 100644 --- a/magicblock-accounts/src/lib.rs +++ b/magicblock-accounts/src/lib.rs @@ -1,6 +1,5 @@ mod config; pub mod errors; -pub mod scheduled_commits_processor; mod traits; pub use config::*; diff --git a/magicblock-api/Cargo.toml b/magicblock-api/Cargo.toml index 1ddbc66de..76828a769 100644 --- a/magicblock-api/Cargo.toml +++ b/magicblock-api/Cargo.toml @@ -16,7 +16,6 @@ tracing = { workspace = true } magicblock-delegation-program-api = { workspace = true } magic-domain-program = { workspace = true } magicblock-account-cloner = { workspace = true } -magicblock-accounts = { workspace = true } magicblock-accounts-db = { workspace = true } magicblock-aperture = { workspace = true } magicblock-chainlink = { workspace = true } diff --git a/magicblock-api/src/errors.rs b/magicblock-api/src/errors.rs index 4f80a6b72..f04f30d8c 100644 --- a/magicblock-api/src/errors.rs +++ b/magicblock-api/src/errors.rs @@ -13,9 +13,6 @@ pub enum ApiError { #[error("Aperture service error: {0}")] Aperture(#[from] magicblock_aperture::error::ApertureError), - #[error("Accounts error: {0}")] - AccountsError(Box), - #[error("Ledger error: {0}")] LedgerError(Box), @@ -113,12 +110,6 @@ pub enum ApiError { Replication(#[from] magicblock_replicator::Error), } -impl From for ApiError { - fn from(e: magicblock_accounts::errors::AccountsError) -> Self { - Self::AccountsError(Box::new(e)) - } -} - impl From for ApiError { fn from(e: magicblock_ledger::errors::LedgerError) -> Self { Self::LedgerError(Box::new(e)) diff --git a/magicblock-api/src/magic_validator.rs b/magicblock-api/src/magic_validator.rs index 0dc4f40cb..e23f806f8 100644 --- a/magicblock-api/src/magic_validator.rs +++ b/magicblock-api/src/magic_validator.rs @@ -9,7 +9,6 @@ use std::{ }; use magicblock_account_cloner::ChainlinkCloner; -use magicblock_accounts::scheduled_commits_processor::ScheduledCommitsProcessorImpl; use magicblock_accounts_db::{traits::AccountsBank, AccountsDb}; use magicblock_aperture::{ initialize_aperture, @@ -58,7 +57,10 @@ use magicblock_program::{ TransactionScheduler as ActionTransactionScheduler, }; use magicblock_replicator::{nats::Broker, BrokerSource, ReplicationService}; -use magicblock_services::actions_callback_service::ActionsCallbackService; +use magicblock_services::{ + actions_callback_service::ActionsCallbackService, + undelegation_request_service::UndelegationRequestService, +}; use magicblock_task_scheduler::{SchedulerDatabase, TaskSchedulerService}; use magicblock_validator_admin::claim_fees::{claim_fees, ClaimFeesTask}; use mdp::state::{ @@ -114,7 +116,7 @@ pub struct MagicValidator { ledger_truncator: LedgerTruncator, intent_execution_service: IntentExecutionServiceImpl, replication_service: Option, - scheduled_commits_processor: Option>, + undelegation_request_service: Option>, rpc_handle: thread::JoinHandle<()>, identity: Pubkey, transaction_scheduler: TransactionSchedulerHandle, @@ -325,12 +327,12 @@ impl MagicValidator { ); log_timing("startup", "system_metrics_ticker_start", step_start); - let scheduled_commits_processor = (!matches!( + let undelegation_request_service = (!matches!( config.validator.replication_mode, ReplicationMode::Replica { .. } )) .then(|| { - Arc::new(ScheduledCommitsProcessorImpl::new( + Arc::new(UndelegationRequestService::new( chainlink.clone(), dispatch.transaction_scheduler.clone(), identity_keypair.insecure_clone(), @@ -459,7 +461,7 @@ impl MagicValidator { _metrics: (metrics_service, system_metrics_ticker), intent_execution_service, replication_service, - scheduled_commits_processor, + undelegation_request_service, token, ledger, ledger_truncator, @@ -1057,8 +1059,8 @@ impl MagicValidator { self.config.validator.replication_mode, ReplicationMode::Replica { .. } ) { - if let Some(processor) = self.scheduled_commits_processor.as_ref() { - processor.spawn_undelegation_request_processor(); + if let Some(service) = self.undelegation_request_service.as_ref() { + service.start(); } } @@ -1147,17 +1149,17 @@ impl MagicValidator { self.start_unregister_validator_on_chain().await; self.exit.store(true, Ordering::Relaxed); - // Ordering is important here - // Commitor service shall be stopped last + // Stop request ingress before stopping intent execution so shutdown + // does not admit new local undelegation scheduling work. self.token.cancel(); - if let Some(ref scheduled_commits_processor) = - self.scheduled_commits_processor + if let Some(ref undelegation_request_service) = + self.undelegation_request_service { let step_start = Instant::now(); - scheduled_commits_processor.stop(); + undelegation_request_service.stop(); log_timing( "shutdown", - "scheduled_commits_processor_stop", + "undelegation_request_service_stop", step_start, ); } diff --git a/magicblock-services/Cargo.toml b/magicblock-services/Cargo.toml index 2c4134370..da9fe6a0b 100644 --- a/magicblock-services/Cargo.toml +++ b/magicblock-services/Cargo.toml @@ -11,9 +11,15 @@ description = "Services that run on top of the MagicBlock validator and communic [dependencies] bincode = { workspace = true } futures-util = { workspace = true } +magicblock-account-cloner = { workspace = true } +magicblock-chainlink = { workspace = true } magicblock-core = { workspace = true } +magicblock-delegation-program-api = { workspace = true } magicblock-magic-program-api = { workspace = true } +magicblock-metrics = { workspace = true } +magicblock-program = { workspace = true } thiserror = { workspace = true } +solana-hash = { workspace = true } solana-instruction = { workspace = true } solana-keypair = { workspace = true } solana-message = { workspace = true } @@ -22,5 +28,7 @@ solana-rpc-client = { workspace = true } solana-signature = { workspace = true } solana-signer = { workspace = true } solana-transaction = { workspace = true } +solana-transaction-error = { workspace = true } tokio = { workspace = true } +tokio-util = { workspace = true } tracing = { workspace = true } diff --git a/magicblock-services/src/lib.rs b/magicblock-services/src/lib.rs index a3b1ee7f5..ae39af350 100644 --- a/magicblock-services/src/lib.rs +++ b/magicblock-services/src/lib.rs @@ -1 +1,2 @@ pub mod actions_callback_service; +pub mod undelegation_request_service; diff --git a/magicblock-accounts/src/scheduled_commits_processor.rs b/magicblock-services/src/undelegation_request_service.rs similarity index 98% rename from magicblock-accounts/src/scheduled_commits_processor.rs rename to magicblock-services/src/undelegation_request_service.rs index 7e42eb5dd..2f1196174 100644 --- a/magicblock-accounts/src/scheduled_commits_processor.rs +++ b/magicblock-services/src/undelegation_request_service.rs @@ -50,7 +50,7 @@ impl fmt::Display for ObservedUndelegationRequestError { } } -pub struct ScheduledCommitsProcessorImpl { +pub struct UndelegationRequestService { chainlink: Arc, cancellation_token: CancellationToken, internal_transaction_scheduler: TransactionSchedulerHandle, @@ -71,7 +71,7 @@ where } } -impl ScheduledCommitsProcessorImpl { +impl UndelegationRequestService { pub fn new( chainlink: Arc, internal_transaction_scheduler: TransactionSchedulerHandle, @@ -306,7 +306,7 @@ impl ScheduledCommitsProcessorImpl { ) } - pub fn spawn_undelegation_request_processor(self: &Arc) { + pub fn start(self: &Arc) { let Some(requests) = self.chainlink.subscribe_undelegation_requests() else { return; diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index d0bdcbedf..b1aa602a7 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -3522,32 +3522,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "magicblock-accounts" -version = "0.13.3" -dependencies = [ - "async-trait", - "magicblock-account-cloner", - "magicblock-chainlink", - "magicblock-committor-service", - "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", - "magicblock-metrics", - "magicblock-program", - "solana-hash 4.2.0", - "solana-instruction 3.3.0", - "solana-keypair", - "solana-pubkey 4.1.0", - "solana-signer", - "solana-transaction", - "solana-transaction-error 3.1.0", - "thiserror 2.0.18", - "tokio", - "tokio-util", - "tracing", - "url", -] - [[package]] name = "magicblock-accounts-db" version = "0.13.3" @@ -3640,7 +3614,6 @@ dependencies = [ "fd-lock", "magic-domain-program", "magicblock-account-cloner", - "magicblock-accounts", "magicblock-accounts-db", "magicblock-aperture", "magicblock-chainlink", @@ -4136,8 +4109,14 @@ version = "0.13.3" dependencies = [ "bincode", "futures-util", + "magicblock-account-cloner", + "magicblock-chainlink", "magicblock-core", + "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", "magicblock-magic-program-api 0.13.3", + "magicblock-metrics", + "magicblock-program", + "solana-hash 4.2.0", "solana-instruction 3.3.0", "solana-keypair", "solana-message 3.1.0", @@ -4146,8 +4125,10 @@ dependencies = [ "solana-signature", "solana-signer", "solana-transaction", + "solana-transaction-error 3.1.0", "thiserror 2.0.18", "tokio", + "tokio-util", "tracing", ] From cb771a0156ff49b9b7175b8972f4290a781ef367 Mon Sep 17 00:00:00 2001 From: Sarfaraz Nawaz Date: Thu, 9 Jul 2026 02:32:40 +0530 Subject: [PATCH 8/8] update dlp to 3.1.0 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- test-integration/Cargo.lock | 42 ++++++++++++++++++------------------- test-integration/Cargo.toml | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3d33cd1a8..630f30984 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3838,8 +3838,8 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" -version = "3.0.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71#26d01c4b5c0c29acbebd41d14b303e1608bbaa71" +version = "3.1.0" +source = "git+https://github.com/magicblock-labs/delegation-program.git?tag=v3.1.0#27f7fd8178630b88e2be45d92b174b8f2ef4661e" dependencies = [ "bincode", "borsh 0.10.4", diff --git a/Cargo.toml b/Cargo.toml index 822000adb..1e59bfe95 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ magicblock-committor-program = { path = "./magicblock-committor-program", featur magicblock-committor-service = { path = "./magicblock-committor-service" } magicblock-config = { path = "./magicblock-config" } magicblock-core = { path = "./magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "26d01c4b5c0c29acbebd41d14b303e1608bbaa71" } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", tag = "v3.1.0" } magicblock-ledger = { path = "./magicblock-ledger" } magicblock-magic-program-api = { path = "./magicblock-magic-program-api" } magicblock-metrics = { path = "./magicblock-metrics" } diff --git a/test-integration/Cargo.lock b/test-integration/Cargo.lock index b1aa602a7..16d623cfd 100644 --- a/test-integration/Cargo.lock +++ b/test-integration/Cargo.lock @@ -1955,7 +1955,7 @@ dependencies = [ "ephemeral-rollups-sdk-attribute-ephemeral-accounts", "five8 0.2.1", "getrandom 0.2.17", - "magicblock-delegation-program-api 3.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "magicblock-delegation-program-api 3.0.0", "magicblock-magic-program-api 0.10.1", "solana-account 3.4.0", "solana-account-info 2.3.0", @@ -3050,7 +3050,7 @@ dependencies = [ "borsh 1.7.0", "color-backtrace", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "rand 0.8.6", "rayon", "serde", @@ -3620,7 +3620,7 @@ dependencies = [ "magicblock-committor-service", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-ledger", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", @@ -3682,7 +3682,7 @@ dependencies = [ "magicblock-aml", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", "parking_lot", @@ -3751,7 +3751,7 @@ dependencies = [ "magicblock-chainlink", "magicblock-committor-program", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-metrics", "magicblock-program", "magicblock-rpc-client", @@ -3863,8 +3863,8 @@ dependencies = [ [[package]] name = "magicblock-delegation-program-api" -version = "3.0.0" -source = "git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71#26d01c4b5c0c29acbebd41d14b303e1608bbaa71" +version = "3.1.0" +source = "git+https://github.com/magicblock-labs/delegation-program.git?tag=v3.1.0#27f7fd8178630b88e2be45d92b174b8f2ef4661e" dependencies = [ "bincode", "borsh 0.10.4", @@ -4023,7 +4023,7 @@ dependencies = [ "bincode", "lazy_static", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-magic-program-api 0.13.3", "num-derive", "num-traits", @@ -4112,7 +4112,7 @@ dependencies = [ "magicblock-account-cloner", "magicblock-chainlink", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-magic-program-api 0.13.3", "magicblock-metrics", "magicblock-program", @@ -4189,7 +4189,7 @@ dependencies = [ name = "magicblock-validator-admin" version = "0.13.3" dependencies = [ - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-program", "magicblock-rpc-client", "solana-commitment-config", @@ -5038,7 +5038,7 @@ version = "0.0.0" dependencies = [ "borsh 1.7.0", "ephemeral-rollups-sdk", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-magic-program-api 0.13.3", "rkyv 0.7.46", "solana-program 3.0.0", @@ -5926,7 +5926,7 @@ dependencies = [ "anyhow", "borsh 1.7.0", "integration-test-tools", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "program-schedulecommit", "solana-commitment-config", "solana-compute-budget-interface", @@ -5948,7 +5948,7 @@ dependencies = [ "magicblock-committor-program", "magicblock-committor-service", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-program", "magicblock-rpc-client", "magicblock-table-mania", @@ -5976,7 +5976,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-magic-program-api 0.13.3", "magicblock-program", "program-schedulecommit", @@ -5997,7 +5997,7 @@ name = "schedulecommit-test-security" version = "0.0.0" dependencies = [ "integration-test-tools", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-magic-program-api 0.13.3", "program-schedulecommit", "program-schedulecommit-security", @@ -9776,7 +9776,7 @@ dependencies = [ "integration-test-tools", "magicblock-config", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9803,7 +9803,7 @@ dependencies = [ "magicblock-aml", "magicblock-chainlink", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "program-flexi-counter", "program-mini", "solana-account 3.4.0", @@ -9829,7 +9829,7 @@ version = "0.0.0" dependencies = [ "integration-test-tools", "magicblock-core", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "program-flexi-counter", "program-mini", "solana-loader-v4-interface 3.1.0", @@ -9899,7 +9899,7 @@ dependencies = [ "integration-test-tools", "magicblock-accounts-db", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "program-flexi-counter", "solana-commitment-config", "solana-rpc-client", @@ -9922,7 +9922,7 @@ dependencies = [ "magic-domain-program", "magicblock-api", "magicblock-config", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-program", "magicblock-validator-admin", "solana-commitment-config", @@ -9968,7 +9968,7 @@ dependencies = [ "ephemeral-rollups-sdk", "integration-test-tools", "log", - "magicblock-delegation-program-api 3.0.0 (git+https://github.com/magicblock-labs/delegation-program.git?rev=26d01c4b5c0c29acbebd41d14b303e1608bbaa71)", + "magicblock-delegation-program-api 3.1.0", "magicblock-magic-program-api 0.13.3", "program-flexi-counter", "solana-rpc-client-api", diff --git a/test-integration/Cargo.toml b/test-integration/Cargo.toml index c4fd48dd2..c98198e31 100644 --- a/test-integration/Cargo.toml +++ b/test-integration/Cargo.toml @@ -63,7 +63,7 @@ magicblock-committor-program = { path = "../magicblock-committor-program", featu magicblock-committor-service = { path = "../magicblock-committor-service" } magicblock-config = { path = "../magicblock-config" } magicblock-core = { path = "../magicblock-core" } -magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", rev = "26d01c4b5c0c29acbebd41d14b303e1608bbaa71", default-features = false } +magicblock-delegation-program-api = { git = "https://github.com/magicblock-labs/delegation-program.git", tag = "v3.1.0", default-features = false } magicblock-magic-program-api = { path = "../magicblock-magic-program-api" } magicblock-program = { path = "../programs/magicblock" } magicblock-rpc-client = { path = "../magicblock-rpc-client" }