From 383e5de34f54d1c463d226126f362333ff8b4ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marin=20Ver=C5=A1i=C4=87?= Date: Tue, 18 Jun 2024 11:54:08 +0200 Subject: [PATCH] refactor!: fix naming convention for assets and permissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marin Veršić --- Cargo.lock | 2 +- client/examples/million_accounts_genesis.rs | 2 +- client/tests/integration/asset.rs | 8 +- client/tests/integration/events/data.rs | 8 +- client/tests/integration/queries/account.rs | 8 +- client/tests/integration/queries/asset.rs | 6 +- .../src/lib.rs | 4 +- .../src/lib.rs | 4 +- client/tests/integration/upgrade.rs | 4 +- client_cli/README.md | 8 +- client_cli/pytests/common/consts.py | 2 +- client_cli/pytests/models/asset.py | 6 +- .../pytests/src/client_cli/client_cli.py | 18 ++-- client_cli/pytests/src/client_cli/iroha.py | 6 +- client_cli/pytests/test/__init__.py | 8 +- client_cli/pytests/test/assets/conftest.py | 8 +- .../pytests/test/assets/test_burn_assets.py | 2 +- .../pytests/test/assets/test_mint_assets.py | 16 +-- .../assets/test_register_asset_definitions.py | 54 +++++----- client_cli/pytests/test/conftest.py | 54 +++++----- client_cli/src/main.rs | 6 +- configs/swarm/docker-compose.local.yml | 12 +-- configs/swarm/docker-compose.single.yml | 4 +- configs/swarm/docker-compose.yml | 12 +-- configs/swarm/executor.wasm | Bin 509796 -> 509673 bytes configs/swarm/genesis.json | 10 +- core/benches/validation.rs | 4 +- core/src/block.rs | 4 +- core/src/query/store.rs | 10 +- core/src/smartcontracts/isi/account.rs | 52 +++++----- core/src/smartcontracts/isi/asset.rs | 34 +++---- core/src/smartcontracts/isi/domain.rs | 4 +- core/src/smartcontracts/isi/triggers/mod.rs | 10 +- core/src/smartcontracts/isi/tx.rs | 2 +- core/src/smartcontracts/isi/world.rs | 39 ++++---- core/src/smartcontracts/wasm.rs | 6 +- core/src/state.rs | 6 +- data_model/src/account.rs | 2 +- data_model/src/asset.rs | 40 ++++---- data_model/src/block.rs | 10 +- data_model/src/events/data/events.rs | 10 +- data_model/src/events/pipeline.rs | 2 +- data_model/src/executor.rs | 6 +- data_model/src/isi.rs | 12 +-- data_model/src/lib.rs | 4 +- data_model/src/permission.rs | 39 +------- data_model/src/query/cursor.rs | 24 ++--- data_model/src/query/mod.rs | 65 +++++-------- data_model/src/query/pagination.rs | 22 ----- data_model/src/query/predicate.rs | 4 +- data_model/src/query/sorting.rs | 13 --- docs/source/references/schema.json | 92 ++++++++---------- genesis/src/lib.rs | 4 +- schema/gen/src/lib.rs | 7 +- .../executor/derive/src/permission.rs | 12 +-- .../executor/src/default/permissions.rs | 4 +- smart_contract/executor/src/lib.rs | 13 +-- smart_contract/executor/src/permission.rs | 10 +- tools/kagami/src/genesis/generate.rs | 9 +- tools/swarm/src/lib.rs | 24 ++--- tools/swarm/src/schema.rs | 12 +-- 61 files changed, 395 insertions(+), 488 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b07611b7a51..2c10bd07b81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3348,7 +3348,7 @@ version = "2.0.0-pre-rc.21" dependencies = [ "clap", "color-eyre", - "displaydoc 0.2.4 (git+https://github.com/akonradi-signal/displaydoc.git?branch=anonymous-const)", + "displaydoc", "expect-test", "inquire", "iroha_config", diff --git a/client/examples/million_accounts_genesis.rs b/client/examples/million_accounts_genesis.rs index d547aff6781..d8033ec6392 100644 --- a/client/examples/million_accounts_genesis.rs +++ b/client/examples/million_accounts_genesis.rs @@ -29,7 +29,7 @@ fn generate_genesis( .account(signatory_alice.clone()) .asset( format!("xor-{i}").parse().expect("Valid"), - AssetValueType::Numeric(NumericSpec::default()), + AssetType::Numeric(NumericSpec::default()), ) .finish_domain(); } diff --git a/client/tests/integration/asset.rs b/client/tests/integration/asset.rs index f0fe33e8fd9..85aecc3e6df 100644 --- a/client/tests/integration/asset.rs +++ b/client/tests/integration/asset.rs @@ -5,7 +5,7 @@ use iroha::{ client::{self, QueryResult}, crypto::KeyPair, data_model::{ - asset::{AssetId, AssetValue, AssetValueType}, + asset::{AssetId, AssetType, AssetValue}, isi::error::{InstructionEvaluationError, InstructionExecutionError, Mismatch, TypeError}, prelude::*, transaction::error::TransactionRejectionReason, @@ -402,7 +402,7 @@ fn fail_if_dont_satisfy_spec() { // Create asset definition which accepts only integers let asset_definition = AssetDefinition::new( asset_definition_id.clone(), - AssetValueType::Numeric(NumericSpec::integer()), + AssetType::Numeric(NumericSpec::integer()), ); test_client @@ -435,8 +435,8 @@ fn fail_if_dont_satisfy_spec() { &TransactionRejectionReason::Validation(ValidationFail::InstructionFailed( InstructionExecutionError::Evaluate(InstructionEvaluationError::Type( TypeError::from(Mismatch { - expected: AssetValueType::Numeric(NumericSpec::integer()), - actual: AssetValueType::Numeric(NumericSpec::fractional(2)) + expected: AssetType::Numeric(NumericSpec::integer()), + actual: AssetType::Numeric(NumericSpec::fractional(2)) }) )) )) diff --git a/client/tests/integration/events/data.rs b/client/tests/integration/events/data.rs index 1e35a9819ed..8fea7736954 100644 --- a/client/tests/integration/events/data.rs +++ b/client/tests/integration/events/data.rs @@ -240,13 +240,13 @@ fn produce_multiple_events() -> Result<()> { DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( AccountPermissionChanged { account: bob_id.clone(), - permission: token_1.id.clone(), + permission: token_1.clone(), }, ))), DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionAdded( AccountPermissionChanged { account: bob_id.clone(), - permission: token_2.id.clone(), + permission: token_2.clone(), }, ))), DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleGranted( @@ -258,13 +258,13 @@ fn produce_multiple_events() -> Result<()> { DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( AccountPermissionChanged { account: bob_id.clone(), - permission: token_1.id, + permission: token_1, }, ))), DataEvent::Domain(DomainEvent::Account(AccountEvent::PermissionRemoved( AccountPermissionChanged { account: bob_id.clone(), - permission: token_2.id, + permission: token_2, }, ))), DataEvent::Domain(DomainEvent::Account(AccountEvent::RoleRevoked( diff --git a/client/tests/integration/queries/account.rs b/client/tests/integration/queries/account.rs index d89d74b8ac0..1f6addaf7f9 100644 --- a/client/tests/integration/queries/account.rs +++ b/client/tests/integration/queries/account.rs @@ -24,8 +24,8 @@ fn find_accounts_with_asset() -> Result<()> { assert_eq!(received_asset_definition.id(), asset_definition.id()); assert!(matches!( - received_asset_definition.value_type(), - AssetValueType::Numeric(_) + received_asset_definition.type_(), + AssetType::Numeric(_) )); let accounts: [AccountId; 5] = [ @@ -61,8 +61,8 @@ fn find_accounts_with_asset() -> Result<()> { assert_eq!(received_asset_definition.id(), asset_definition.id()); assert_eq!( - received_asset_definition.value_type(), - AssetValueType::Numeric(NumericSpec::default()), + received_asset_definition.type_(), + AssetType::Numeric(NumericSpec::default()), ); let found_accounts = test_client diff --git a/client/tests/integration/queries/asset.rs b/client/tests/integration/queries/asset.rs index d306f5b9540..8229cc2e7d4 100644 --- a/client/tests/integration/queries/asset.rs +++ b/client/tests/integration/queries/asset.rs @@ -44,7 +44,7 @@ fn find_asset_total_quantity() -> Result<()> { &test_client, &accounts, "quantity#wonderland", - AssetValueType::Numeric(NumericSpec::default()), + AssetType::Numeric(NumericSpec::default()), numeric!(1), numeric!(10), numeric!(5), @@ -56,7 +56,7 @@ fn find_asset_total_quantity() -> Result<()> { &test_client, &accounts, "fixed#wonderland", - AssetValueType::Numeric(NumericSpec::default()), + AssetType::Numeric(NumericSpec::default()), numeric!(1.0), numeric!(10.0), numeric!(5.0), @@ -131,7 +131,7 @@ fn test_total_quantity( test_client: &Client, accounts: &[AccountId; 5], definition: &str, - asset_value_type: AssetValueType, + asset_value_type: AssetType, initial_value: T, to_mint: T, to_burn: T, diff --git a/client/tests/integration/smartcontracts/executor_with_custom_permission/src/lib.rs b/client/tests/integration/smartcontracts/executor_with_custom_permission/src/lib.rs index 4a4ddb6df86..df79e867615 100644 --- a/client/tests/integration/smartcontracts/executor_with_custom_permission/src/lib.rs +++ b/client/tests/integration/smartcontracts/executor_with_custom_permission/src/lib.rs @@ -110,9 +110,9 @@ impl Executor { fn replace_token(accounts: &[(Account, DomainId)]) -> MigrationResult { let can_unregister_domain_definition_id = - iroha_executor::default::permissions::domain::CanUnregisterDomain::id(); + iroha_executor::default::permissions::domain::CanUnregisterDomain::name(); - let can_control_domain_lives_definition_id = token::CanControlDomainLives::id(); + let can_control_domain_lives_definition_id = token::CanControlDomainLives::name(); accounts .iter() diff --git a/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/src/lib.rs b/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/src/lib.rs index 420ff477e67..0e45690ca93 100644 --- a/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/src/lib.rs +++ b/client/tests/integration/smartcontracts/smart_contract_can_filter_queries/src/lib.rs @@ -35,14 +35,14 @@ fn main(_owner: AccountId) { Register::asset_definition(AssetDefinition::new( time_id.clone(), - AssetValueType::Numeric(NumericSpec::default()), + AssetType::Numeric(NumericSpec::default()), )) .execute() .dbg_unwrap(); Register::asset_definition(AssetDefinition::new( space_id.clone(), - AssetValueType::Numeric(NumericSpec::default()), + AssetType::Numeric(NumericSpec::default()), )) .execute() .dbg_unwrap(); diff --git a/client/tests/integration/upgrade.rs b/client/tests/integration/upgrade.rs index 2d06f4a8a75..914dd7aa3e4 100644 --- a/client/tests/integration/upgrade.rs +++ b/client/tests/integration/upgrade.rs @@ -146,7 +146,7 @@ fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { assert!(client .request(FindExecutorDataModel)? .permissions() - .contains(&can_unregister_domain_token.id)); + .contains(can_unregister_domain_token.name())); // Check that `TEST_ROLE` has permission assert!(client @@ -174,7 +174,7 @@ fn executor_upgrade_should_revoke_removed_permissions() -> Result<()> { assert!(!client .request(FindExecutorDataModel)? .permissions() - .contains(&can_unregister_domain_token.id)); + .contains(can_unregister_domain_token.name())); // Check that `TEST_ROLE` doesn't have permission assert!(!client diff --git a/client_cli/README.md b/client_cli/README.md index 869fe9b3763..08c4494f3d2 100644 --- a/client_cli/README.md +++ b/client_cli/README.md @@ -61,7 +61,7 @@ Check the [Bash guide in Iroha Tutorial](https://hyperledger.github.io/iroha-2-d ```bash ./iroha domain register --id="Soramitsu" ./iroha account register --id="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" -./iroha asset register --id="XOR#Soramitsu" --value-type=Numeric +./iroha asset register --id="XOR#Soramitsu" --type=Numeric ./iroha asset mint --account="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" --asset="XOR#Soramitsu" --quantity=1010 ./iroha asset get --account="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" --asset="XOR#Soramitsu" ``` @@ -111,7 +111,7 @@ To do so, you must first register an Asset Definition and only then add some Ass Every asset has its own value spec. In this example, it is defined as `Numeric`, a 96-bit unsigned decimal. We also support `Store` for key-value structured data. ```bash -./iroha asset register --id="XOR#Soramitsu" --value-type=Numeric +./iroha asset register --id="XOR#Soramitsu" --type=Numeric ./iroha asset mint --account="ed01204A3C5A6B77BBE439969F95F0AA4E01AE31EC45A0D68C131B2C622751FCC5E3B6@Soramitsu" --asset="XOR#Soramitsu" --quantity=1010 ``` @@ -186,8 +186,8 @@ To test transactions in the JSON format (used in the genesis block and by other cat /path/to/file.json | ./iroha json transaction ``` -### Request arbitrary query +### Request arbitrary query -```bash +```bash echo '{ "FindAllParameters": null }' | ./iroha --config client.toml json query ``` diff --git a/client_cli/pytests/common/consts.py b/client_cli/pytests/common/consts.py index c46337ff847..837c9eb388e 100644 --- a/client_cli/pytests/common/consts.py +++ b/client_cli/pytests/common/consts.py @@ -20,7 +20,7 @@ class Stderr(Enum): TOO_LONG = "Name length violation" FAILED_TO_FIND_DOMAIN = "Failed to find domain" INVALID_CHARACTER = "Failed to parse" - INVALID_VALUE_TYPE = "should be either `Store` or `Numeric`" + INVALID_TYPE = "should be either `Store` or `Numeric`" RESERVED_CHARACTER = ( "The `@` character is reserved for `account@domain` constructs, " "and `#` — for `asset#domain`." diff --git a/client_cli/pytests/models/asset.py b/client_cli/pytests/models/asset.py index c3decd39da4..ae4d55f2c07 100644 --- a/client_cli/pytests/models/asset.py +++ b/client_cli/pytests/models/asset.py @@ -14,13 +14,13 @@ class AssetDefinition: :type name: str :param domain: The domain of the asset definition. :type domain: str - :param value_type: The value type of the asset definition. - :type value_type: str + :param type_: The value type of the asset definition. + :type type_: str """ name: str domain: str - value_type: str + type_: str def __repr__(self): return f"{self.name}#{self.domain}" diff --git a/client_cli/pytests/src/client_cli/client_cli.py b/client_cli/pytests/src/client_cli/client_cli.py index 6ebcdadafba..4ecde368a26 100644 --- a/client_cli/pytests/src/client_cli/client_cli.py +++ b/client_cli/pytests/src/client_cli/client_cli.py @@ -150,7 +150,7 @@ def account(self, signatory: str, domain: str): self.execute() return self - def asset(self, asset_definition=None, account=None, value_of_value_type=None): + def asset(self, asset_definition=None, account=None, value_of_type=None): """ Executes the 'asset' command with the given asset definition, account, and value. @@ -158,13 +158,13 @@ def asset(self, asset_definition=None, account=None, value_of_value_type=None): :type asset_definition: AssetDefinition :param account: The account to be queried, defaults to None. :type account: Account - :param value_of_value_type: The value of the value type, defaults to None. - :type value_of_value_type: str, optional + :param value_of_type: The value of the asset type, defaults to None. + :type value_of_type: str, optional :return: The current ClientCli object. :rtype: ClientCli """ self.command.insert(2, "asset") - if asset_definition and account and value_of_value_type: + if asset_definition and account and value_of_type: self.command.append( "--asset-id=" + asset_definition.name @@ -175,7 +175,7 @@ def asset(self, asset_definition=None, account=None, value_of_value_type=None): + "@" + account.domain ) - self.command.append("--quantity=" + value_of_value_type) + self.command.append("--quantity=" + value_of_type) self.execute() return self @@ -239,7 +239,7 @@ def burn(self, account, asset, quantity: str): self.execute() return self - def definition(self, asset: str, domain: str, value_type: str): + def definition(self, asset: str, domain: str, type_: str): """ Executes the 'definition' command for the given asset, domain, and value type. @@ -247,13 +247,13 @@ def definition(self, asset: str, domain: str, value_type: str): :type asset: str :param domain: The domain of the asset. :type domain: str - :param value_type: The value type of the asset. - :type value_type: str + :param type_: The value type of the asset. + :type type_: str :return: The current ClientCli object. :rtype: ClientCli """ self.command.append("--definition-id=" + asset + "#" + domain) - self.command.append("--value-type=" + value_type) + self.command.append("--type=" + type_) self.execute() return self diff --git a/client_cli/pytests/src/client_cli/iroha.py b/client_cli/pytests/src/client_cli/iroha.py index 7bfa0ba3af6..d186a5099e7 100644 --- a/client_cli/pytests/src/client_cli/iroha.py +++ b/client_cli/pytests/src/client_cli/iroha.py @@ -113,9 +113,9 @@ def asset_definitions(self) -> Dict[str, str]: for domain in domains: asset_defs = domain.get("asset_definitions") for asset_def in asset_defs.values(): - value_type = asset_def.get("value_type") - if value_type: - asset_definitions[asset_def["id"]] = value_type + type_ = asset_def.get("type") + if type_: + asset_definitions[asset_def["id"]] = type_ return asset_definitions else: return {} diff --git a/client_cli/pytests/test/__init__.py b/client_cli/pytests/test/__init__.py index 1ca1a357dae..567088bd974 100644 --- a/client_cli/pytests/test/__init__.py +++ b/client_cli/pytests/test/__init__.py @@ -15,14 +15,14 @@ GIVEN_public_key, GIVEN_numeric_asset_for_account, GIVEN_numeric_value, - GIVEN_numeric_value_type, + GIVEN_numeric_type, GIVEN_random_character, GIVEN_registered_account, - GIVEN_registered_asset_definition_with_numeric_value_type, - GIVEN_registered_asset_definition_with_store_value_type, + GIVEN_registered_asset_definition_with_numeric_type, + GIVEN_registered_asset_definition_with_store_type, GIVEN_registered_domain, GIVEN_registered_domain_with_uppercase_letter, - GIVEN_store_value_type, + GIVEN_store_type, GIVEN_string_with_reserved_character, GIVEN_string_with_whitespaces, before_all, diff --git a/client_cli/pytests/test/assets/conftest.py b/client_cli/pytests/test/assets/conftest.py index aa67951891e..5bc69f5b2fc 100644 --- a/client_cli/pytests/test/assets/conftest.py +++ b/client_cli/pytests/test/assets/conftest.py @@ -9,12 +9,12 @@ GIVEN_public_key, GIVEN_numeric_asset_for_account, GIVEN_numeric_value, - GIVEN_numeric_value_type, + GIVEN_numeric_type, GIVEN_registered_account, - GIVEN_registered_asset_definition_with_numeric_value_type, - GIVEN_registered_asset_definition_with_store_value_type, + GIVEN_registered_asset_definition_with_numeric_type, + GIVEN_registered_asset_definition_with_store_type, GIVEN_registered_domain, - GIVEN_store_value_type, + GIVEN_store_type, before_all, before_each, ) diff --git a/client_cli/pytests/test/assets/test_burn_assets.py b/client_cli/pytests/test/assets/test_burn_assets.py index b7d22f3ab3b..97b832e693b 100644 --- a/client_cli/pytests/test/assets/test_burn_assets.py +++ b/client_cli/pytests/test/assets/test_burn_assets.py @@ -41,7 +41,7 @@ def test_burn_asset_for_account_in_same_domain( @allure.label("permission", "can_burn_assets_with_definition") @pytest.mark.xfail(reason="TO DO") def test_burn_other_user_asset( - GIVEN_registered_asset_definition_with_numeric_value_type, + GIVEN_registered_asset_definition_with_numeric_type, GIVEN_registered_account, GIVEN_numeric_value, ): diff --git a/client_cli/pytests/test/assets/test_mint_assets.py b/client_cli/pytests/test/assets/test_mint_assets.py index ef83e794df0..5cfdf0f1e60 100644 --- a/client_cli/pytests/test/assets/test_mint_assets.py +++ b/client_cli/pytests/test/assets/test_mint_assets.py @@ -11,34 +11,34 @@ def story_account_mint_asset(): @allure.label("sdk_test_id", "mint_asset_for_account_in_same_domain") def test_mint_asset_for_account_in_same_domain( - GIVEN_registered_asset_definition_with_numeric_value_type, + GIVEN_registered_asset_definition_with_numeric_type, GIVEN_registered_account, GIVEN_numeric_value, ): with allure.step( f'WHEN client_cli mint "{GIVEN_numeric_value}" of ' - f'"{GIVEN_registered_asset_definition_with_numeric_value_type}" ' + f'"{GIVEN_registered_asset_definition_with_numeric_type}" ' f'for the "{GIVEN_registered_account}"' ): client_cli.mint().asset( account=GIVEN_registered_account, - asset_definition=GIVEN_registered_asset_definition_with_numeric_value_type, - value_of_value_type=GIVEN_numeric_value, + asset_definition=GIVEN_registered_asset_definition_with_numeric_type, + value_of_type=GIVEN_numeric_value, ) with allure.step( f'THEN "{GIVEN_registered_account}" ' f'should have the "{GIVEN_numeric_value}" of ' - f'"{GIVEN_registered_asset_definition_with_numeric_value_type}"' + f'"{GIVEN_registered_asset_definition_with_numeric_type}"' ): iroha.should( have.asset( - f"{GIVEN_registered_asset_definition_with_numeric_value_type.name}##" + f"{GIVEN_registered_asset_definition_with_numeric_type.name}##" f"{GIVEN_registered_account}" ) ) iroha.should( have.asset_has_quantity( - f"{GIVEN_registered_asset_definition_with_numeric_value_type.name}##" + f"{GIVEN_registered_asset_definition_with_numeric_type.name}##" f"{GIVEN_registered_account}", GIVEN_numeric_value, ) @@ -55,7 +55,7 @@ def test_mint_asset_quantity_after_minting(GIVEN_minted_asset_quantity): client_cli.mint().asset( account=GIVEN_minted_asset_quantity.account, asset_definition=GIVEN_minted_asset_quantity.definition, - value_of_value_type="1", + value_of_type="1", ) expected_quantity = int(GIVEN_minted_asset_quantity.value) + 1 with allure.step( diff --git a/client_cli/pytests/test/assets/test_register_asset_definitions.py b/client_cli/pytests/test/assets/test_register_asset_definitions.py index 03233ccc373..cb6308378dd 100644 --- a/client_cli/pytests/test/assets/test_register_asset_definitions.py +++ b/client_cli/pytests/test/assets/test_register_asset_definitions.py @@ -11,19 +11,19 @@ def story_account_registers_asset_definitions(): allure.dynamic.label("permission", "no_permission_required") -@allure.label("sdk_test_id", "register_asset_definition_with_numeric_value_type") -def test_register_asset_definition_with_numeric_value_type( - GIVEN_fake_asset_name, GIVEN_registered_domain, GIVEN_numeric_value_type +@allure.label("sdk_test_id", "register_asset_definition_with_numeric_type") +def test_register_asset_definition_with_numeric_type( + GIVEN_fake_asset_name, GIVEN_registered_domain, GIVEN_numeric_type ): with allure.step( f'WHEN client_cli registers the asset_definition "{GIVEN_fake_asset_name}" ' - f'with "{GIVEN_numeric_value_type}" value type' + f'with "{GIVEN_numeric_type}" value type' f'in the "{GIVEN_registered_domain.name}" domain' ): client_cli.register().asset().definition( asset=GIVEN_fake_asset_name, domain=GIVEN_registered_domain.name, - value_type=GIVEN_numeric_value_type, + type_=GIVEN_numeric_type, ) with allure.step(f'THEN Iroha should have the asset "{GIVEN_fake_asset_name}"'): iroha.should( @@ -35,35 +35,35 @@ def test_register_asset_definition_with_numeric_value_type( @allure.label("sdk_test_id", "register_asset_definition_with_too_long_name") def test_register_asset_definition_with_too_long_name( - GIVEN_129_length_name, GIVEN_registered_domain, GIVEN_numeric_value_type + GIVEN_129_length_name, GIVEN_registered_domain, GIVEN_numeric_type ): with allure.step( f'WHEN client_cli registers the asset_definition "{GIVEN_129_length_name}" ' - f'with "{GIVEN_numeric_value_type}" value type' + f'with "{GIVEN_numeric_type}" value type' f'in the "{GIVEN_registered_domain.name}" domain' ): client_cli.register().asset().definition( asset=GIVEN_129_length_name, domain=GIVEN_registered_domain.name, - value_type=GIVEN_numeric_value_type, + type_=GIVEN_numeric_type, ) with allure.step(f'THEN Iroha should have the asset "{GIVEN_129_length_name}"'): client_cli.should(have.error(Stderr.TOO_LONG.value)) -@allure.label("sdk_test_id", "register_asset_definition_with_store_value_type") -def test_register_asset_definition_with_store_value_type( - GIVEN_fake_asset_name, GIVEN_registered_domain, GIVEN_store_value_type +@allure.label("sdk_test_id", "register_asset_definition_with_store_type") +def test_register_asset_definition_with_store_type( + GIVEN_fake_asset_name, GIVEN_registered_domain, GIVEN_store_type ): with allure.step( f'WHEN client_cli registers the asset_definition "{GIVEN_fake_asset_name}" ' - f'with "{GIVEN_store_value_type}" value type' + f'with "{GIVEN_store_type}" value type' f'in the "{GIVEN_registered_domain.name}" domain' ): client_cli.register().asset().definition( asset=GIVEN_fake_asset_name, domain=GIVEN_registered_domain.name, - value_type=GIVEN_store_value_type, + type_=GIVEN_store_type, ) with allure.step(f'THEN Iroha should have the asset "{GIVEN_fake_asset_name}"'): iroha.should( @@ -91,21 +91,21 @@ def test_register_fixed_asset_definition( @allure.label("sdk_test_id", "register_asset_with_existing_name") def test_register_asset_with_existing_name( - GIVEN_registered_asset_definition_with_numeric_value_type, + GIVEN_registered_asset_definition_with_numeric_type, ): with allure.step( f"WHEN account tries to register an asset definition " - f'with the same name "{GIVEN_registered_asset_definition_with_numeric_value_type.name}"' - f'in the "{GIVEN_registered_asset_definition_with_numeric_value_type.domain}" domain' + f'with the same name "{GIVEN_registered_asset_definition_with_numeric_type.name}"' + f'in the "{GIVEN_registered_asset_definition_with_numeric_type.domain}" domain' ): client_cli.register().asset().definition( - asset=GIVEN_registered_asset_definition_with_numeric_value_type.name, - domain=GIVEN_registered_asset_definition_with_numeric_value_type.domain, - value_type=GIVEN_registered_asset_definition_with_numeric_value_type.value_type, + asset=GIVEN_registered_asset_definition_with_numeric_type.name, + domain=GIVEN_registered_asset_definition_with_numeric_type.domain, + type_=GIVEN_registered_asset_definition_with_numeric_type.type_, ) with allure.step( f'THEN client_cli should have the asset definition error: "' - f'{GIVEN_registered_asset_definition_with_numeric_value_type.__repr__()}"' + f'{GIVEN_registered_asset_definition_with_numeric_type.__repr__()}"' ): client_cli.should(have.error(Stderr.REPETITION.value)) @@ -117,7 +117,7 @@ def test_register_asset_with_empty_name(GIVEN_registered_domain): f'in the "{GIVEN_registered_domain.name}" domain' ): client_cli.register().asset().definition( - asset="", domain=GIVEN_registered_domain.name, value_type="Numeric" + asset="", domain=GIVEN_registered_domain.name, type_="Numeric" ) with allure.step(f'THEN сlient_cli should have the asset error: "{Stderr.EMPTY}"'): client_cli.should(have.error(Stderr.EMPTY.value)) @@ -125,7 +125,7 @@ def test_register_asset_with_empty_name(GIVEN_registered_domain): @allure.label("sdk_test_id", "register_asset_with_not_existing_domain") def test_register_asset_with_not_existing_domain( - GIVEN_not_existing_name, GIVEN_numeric_value_type, GIVEN_fake_asset_name + GIVEN_not_existing_name, GIVEN_numeric_type, GIVEN_fake_asset_name ): with allure.step( "WHEN client_cli tries to register an asset definition with not existing domain" @@ -133,14 +133,14 @@ def test_register_asset_with_not_existing_domain( client_cli.register().asset().definition( asset=GIVEN_fake_asset_name, domain=GIVEN_not_existing_name, - value_type=GIVEN_numeric_value_type, + type_=GIVEN_numeric_type, ) with allure.step("THEN client_cli should have the error"): client_cli.should(have.error(Stderr.FAILED_TO_FIND_DOMAIN.value)) -@allure.label("sdk_test_id", "register_asset_with_too_long_value_type") -def test_register_asset_with_too_long_value_type( +@allure.label("sdk_test_id", "register_asset_with_too_long_type") +def test_register_asset_with_too_long_type( GIVEN_fake_asset_name, GIVEN_registered_domain ): with allure.step( @@ -149,7 +149,7 @@ def test_register_asset_with_too_long_value_type( client_cli.register().asset().definition( asset=GIVEN_fake_asset_name, domain=GIVEN_registered_domain.name, - value_type="coin", + type_="coin", ) with allure.step("THEN client_cli should have the error"): - client_cli.should(have.error(Stderr.INVALID_VALUE_TYPE.value)) + client_cli.should(have.error(Stderr.INVALID_TYPE.value)) diff --git a/client_cli/pytests/test/conftest.py b/client_cli/pytests/test/conftest.py index 364456252ff..4a4dfaacde9 100644 --- a/client_cli/pytests/test/conftest.py +++ b/client_cli/pytests/test/conftest.py @@ -93,13 +93,13 @@ def GIVEN_currently_authorized_account(): @pytest.fixture() def GIVEN_currently_account_quantity_with_two_quantity_of_asset( - GIVEN_currently_authorized_account, GIVEN_numeric_value_type, GIVEN_fake_asset_name + GIVEN_currently_authorized_account, GIVEN_numeric_type, GIVEN_fake_asset_name ): """Fixture to get the currently authorized account asset""" asset_def = AssetDefinition( name=GIVEN_fake_asset_name, domain=GIVEN_currently_authorized_account.domain, - value_type=GIVEN_numeric_value_type, + type_=GIVEN_numeric_type, ) asset = Asset( definition=asset_def, value="2", account=GIVEN_currently_authorized_account @@ -112,26 +112,26 @@ def GIVEN_currently_account_quantity_with_two_quantity_of_asset( client_cli.register().asset().definition( asset=asset.definition.name, domain=asset.definition.domain, - value_type=asset.definition.value_type, + type_=asset.definition.type_, ) client_cli.mint().asset( account=GIVEN_currently_authorized_account, asset_definition=asset.definition, - value_of_value_type=asset.value, + value_of_type=asset.value, ) return asset @pytest.fixture() def GIVEN_numeric_asset_for_account( - request, GIVEN_numeric_value_type, GIVEN_fake_asset_name, GIVEN_numeric_value + request, GIVEN_numeric_type, GIVEN_fake_asset_name, GIVEN_numeric_value ): """Fixture to get an asset for a given account and domain with specified quantity.""" account, domain = request.param.split("@") account = Account(signatory=account, domain=domain) asset_def = AssetDefinition( - name=GIVEN_fake_asset_name, domain=domain, value_type=GIVEN_numeric_value_type + name=GIVEN_fake_asset_name, domain=domain, type_=GIVEN_numeric_type ) asset = Asset( definition=asset_def, value=GIVEN_numeric_value, account=account.signatory @@ -143,26 +143,26 @@ def GIVEN_numeric_asset_for_account( client_cli.register().asset().definition( asset=asset.definition.name, domain=asset.definition.domain, - value_type=asset.definition.value_type, + type_=asset.definition.type_, ) client_cli.mint().asset( account=account, asset_definition=asset.definition, - value_of_value_type=asset.value, + value_of_type=asset.value, ) return asset @pytest.fixture() -def GIVEN_registered_asset_definition_with_numeric_value_type( - GIVEN_registered_domain, GIVEN_numeric_value_type, GIVEN_fake_asset_name +def GIVEN_registered_asset_definition_with_numeric_type( + GIVEN_registered_domain, GIVEN_numeric_type, GIVEN_fake_asset_name ): """Fixture to create and register an asset definition with numeric value type.""" asset_def = AssetDefinition( name=GIVEN_fake_asset_name, domain=GIVEN_registered_domain.name, - value_type=GIVEN_numeric_value_type, + type_=GIVEN_numeric_type, ) with allure.step( f'GIVEN the asset_definition "{GIVEN_fake_asset_name}" ' @@ -171,14 +171,14 @@ def GIVEN_registered_asset_definition_with_numeric_value_type( client_cli.register().asset().definition( asset=asset_def.name, domain=asset_def.domain, - value_type=asset_def.value_type, + type_=asset_def.type_, ) return asset_def @pytest.fixture() def GIVEN_minted_asset_quantity( - GIVEN_registered_asset_definition_with_numeric_value_type, + GIVEN_registered_asset_definition_with_numeric_type, GIVEN_registered_account, GIVEN_numeric_value, ): @@ -187,26 +187,26 @@ def GIVEN_minted_asset_quantity( """ asset = Asset( account=GIVEN_registered_account, - definition=GIVEN_registered_asset_definition_with_numeric_value_type, + definition=GIVEN_registered_asset_definition_with_numeric_type, value=GIVEN_numeric_value, ) client_cli.mint().asset( account=asset.account, asset_definition=asset.definition, - value_of_value_type=asset.value, + value_of_type=asset.value, ) return asset @pytest.fixture() -def GIVEN_registered_asset_definition_with_store_value_type( - GIVEN_registered_domain, GIVEN_store_value_type, GIVEN_fake_asset_name +def GIVEN_registered_asset_definition_with_store_type( + GIVEN_registered_domain, GIVEN_store_type, GIVEN_fake_asset_name ): """Fixture to create and register an asset definition with store value type.""" asset_def = AssetDefinition( name=GIVEN_fake_asset_name, domain=GIVEN_registered_domain.name, - value_type=GIVEN_store_value_type, + type_=GIVEN_store_type, ) with allure.step( f'GIVEN the asset_definition "{GIVEN_fake_asset_name}" ' @@ -215,7 +215,7 @@ def GIVEN_registered_asset_definition_with_store_value_type( client_cli.register().asset().definition( asset=asset_def.name, domain=asset_def.domain, - value_type=asset_def.value_type, + type=asset_def.type, ) return asset_def @@ -290,19 +290,19 @@ def GIVEN_key_with_invalid_character_in_key( @pytest.fixture() -def GIVEN_numeric_value_type(): +def GIVEN_numeric_type(): """Fixture to provide a numeric value type.""" - value_type = ValueTypes.NUMERIC.value - with allure.step(f'GIVEN a "{value_type}" value type'): - return value_type + type_ = ValueTypes.NUMERIC.value + with allure.step(f'GIVEN a "{type_}" value type'): + return type_ @pytest.fixture() -def GIVEN_store_value_type(): +def GIVEN_store_type(): """Fixture to provide a store value type.""" - value_type = ValueTypes.STORE.value - with allure.step(f'GIVEN a "{value_type}" value type'): - return value_type + type_ = ValueTypes.STORE.value + with allure.step(f'GIVEN a "{type_}" value type'): + return type_ @pytest.fixture() diff --git a/client_cli/src/main.rs b/client_cli/src/main.rs index 3a2ea0caa3e..18dfa49bdc7 100644 --- a/client_cli/src/main.rs +++ b/client_cli/src/main.rs @@ -712,7 +712,7 @@ mod asset { pub unmintable: bool, /// Value type stored in asset #[arg(short, long)] - pub value_type: AssetValueType, + pub r#type: AssetType, #[command(flatten)] pub metadata: MetadataArgs, } @@ -721,11 +721,11 @@ mod asset { fn run(self, context: &mut dyn RunContext) -> Result<()> { let Self { definition_id, - value_type, + r#type, unmintable, metadata, } = self; - let mut asset_definition = AssetDefinition::new(definition_id, value_type); + let mut asset_definition = AssetDefinition::new(definition_id, r#type); if unmintable { asset_definition = asset_definition.mintable_once(); } diff --git a/configs/swarm/docker-compose.local.yml b/configs/swarm/docker-compose.local.yml index 16142fa6b39..bbc6d9bdebc 100644 --- a/configs/swarm/docker-compose.local.yml +++ b/configs/swarm/docker-compose.local.yml @@ -20,9 +20,9 @@ services: P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' + TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' GENESIS_PRIVATE_KEY: 80264082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD4164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - GENESIS_SIGNED_FILE: /tmp/genesis.signed.scale + GENESIS: /tmp/genesis.signed.scale TOPOLOGY: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' ports: - 1337:1337 @@ -48,7 +48,7 @@ services: kagami genesis sign /tmp/genesis.json \\ --public-key $$GENESIS_PUBLIC_KEY \\ --private-key $$GENESIS_PRIVATE_KEY \\ - --out-file $$GENESIS_SIGNED_FILE \\ + --out-file $$GENESIS \\ && \\ irohad --submit-genesis " @@ -64,7 +64,7 @@ services: P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' + TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' ports: - 1338:1338 - 8081:8081 @@ -89,7 +89,7 @@ services: P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' + TRUSTED_PEERS: '[{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' ports: - 1339:1339 - 8082:8082 @@ -114,7 +114,7 @@ services: P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"}]' + TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"}]' ports: - 1340:1340 - 8083:8083 diff --git a/configs/swarm/docker-compose.single.yml b/configs/swarm/docker-compose.single.yml index 49dbec866de..f9412f29c5a 100644 --- a/configs/swarm/docker-compose.single.yml +++ b/configs/swarm/docker-compose.single.yml @@ -21,7 +21,7 @@ services: API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 GENESIS_PRIVATE_KEY: 80264082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD4164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - GENESIS_SIGNED_FILE: /tmp/genesis.signed.scale + GENESIS: /tmp/genesis.signed.scale TOPOLOGY: '[{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"}]' ports: - 1337:1337 @@ -47,7 +47,7 @@ services: kagami genesis sign /tmp/genesis.json \\ --public-key $$GENESIS_PUBLIC_KEY \\ --private-key $$GENESIS_PRIVATE_KEY \\ - --out-file $$GENESIS_SIGNED_FILE \\ + --out-file $$GENESIS \\ && \\ irohad --submit-genesis " diff --git a/configs/swarm/docker-compose.yml b/configs/swarm/docker-compose.yml index e96c7f31aef..d635c5d656f 100644 --- a/configs/swarm/docker-compose.yml +++ b/configs/swarm/docker-compose.yml @@ -12,9 +12,9 @@ services: P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' + TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' GENESIS_PRIVATE_KEY: 80264082B3BDE54AEBECA4146257DA0DE8D59D8E46D5FE34887DCD8072866792FCB3AD4164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - GENESIS_SIGNED_FILE: /tmp/genesis.signed.scale + GENESIS: /tmp/genesis.signed.scale TOPOLOGY: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' ports: - 1337:1337 @@ -40,7 +40,7 @@ services: kagami genesis sign /tmp/genesis.json \\ --public-key $$GENESIS_PUBLIC_KEY \\ --private-key $$GENESIS_PRIVATE_KEY \\ - --out-file $$GENESIS_SIGNED_FILE \\ + --out-file $$GENESIS \\ && \\ irohad --submit-genesis " @@ -53,7 +53,7 @@ services: P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' + TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' ports: - 1338:1338 - 8081:8081 @@ -75,7 +75,7 @@ services: P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' + TRUSTED_PEERS: '[{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"},{"address":"irohad3:1340","public_key":"ed0120CACF3A84B8DC8710CE9D6B968EE95EC7EE4C93C85858F026F3B4417F569592CE"}]' ports: - 1339:1339 - 8082:8082 @@ -97,7 +97,7 @@ services: P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed01204164BF554923ECE1FD412D241036D863A6AE430476C898248B8237D77534CFC4 - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"}]' + TRUSTED_PEERS: '[{"address":"irohad2:1339","public_key":"ed01204EE2FCD53E1730AF142D1E23951198678295047F9314B4006B0CB61850B1DB10"},{"address":"irohad1:1338","public_key":"ed01209897952D14BDFAEA780087C38FF3EB800CB20B882748FC95A575ADB9CD2CB21D"},{"address":"irohad0:1337","public_key":"ed0120A98BAFB0663CE08D75EBD506FEC38A84E576A7C9B0897693ED4B04FD9EF2D18D"}]' ports: - 1340:1340 - 8083:8083 diff --git a/configs/swarm/executor.wasm b/configs/swarm/executor.wasm index dcef63c24dd091c614deddf813efdffe050f85c1..a0ce85090948758609a066958a0f91074c736d3b 100644 GIT binary patch delta 129073 zcmeFa2Ygk<_Ah>B_Nh53JCGg{b{d2diu5KqQJRW^?b<0SYD7`gtKO?5C_?CgEe<6@ zC<;;o0YfJsXrv`kq?e#nK?q2%@4IH7b8-UVUhlj9Kkq$%|0rkgnOU=D&6>5=%&aN< z(5RZnN7l@9@uW?D-}{*?CNnqT&thUG#yH2rWa5m`gMRcrd}K|8Wiq1ajWM&yjDMzT zCcJQ`9;wvyvzi%qa7E!}{cc4IvzSbFiIXdq2+p|G2IPwVcO|Job#CI^%(=ya;*cLf zJj}ocZ1e+a%qF`mo}2U{C6<}=Bg(=i9DgQeR_KX82mTR3X8LjedEW_7peazFYL3q^ zaE21S7C-J!#eh8eV<^{Z1Lag*pthNV)Bqcpfj^7MD#>BdCR+_Fvk_fpW(B(}9F(I# zGc$2BA}nT=$~A*;X5t^wVhRYd%2yyFJ~F+ZB{6{TdjIq>mN0HH=~FG$_2rg;E`EL% z`iqgj^2gs|p|~*l0Mm^6G8WE5WHV4f?xvyk0h<90W<^=!^`_QfeT+3+pJG)JGt^o` zA8n09$l?BHMc7u$WO6EID`=;>#8L^I*R;#s z@3Ti~$60ibSNivRxmS<3UhCEW?Hkp%1ca89N<*J$k&* z>+N1WUVQxpg*kilc=^R%Z}jNh>#Y|R?#M%XxtLS1h{&2hIPUGV$5z0O+79z|N|CZw z8D!2fe`C()>-j8xiItfTnGc(fm=BtdnU9-qSa$J4e6HUi+YWxtcHXv~Z{e$KKbuP( zJNbTI#`o}f{JQN}hV6)LA-~41vny;KpU?C8BEE#r#yb&wh4aA zZ6oYM?bq1}+d+QVcG-5tcGY&xcGh;rR&G0KyKMg5_N#4=`8V5X+XdT4_JQ_c_La6% zw%z7T`z6~&+YtL;`*8br_AT~djwAMO?ECDa94qa;$2gAL2RTmKOYB$em+af^U)s;w z7uW|n7TI^%m)OtSzp~%3PqYjBbo*TU=k{Ohh4vwiT>D1*GJBc*wEai>FSg^hEc+++ zLH3XBH*Gg;xqg27sv6(>{gbl{HXy;|(sZkz_Mj^wU1Ki)bk(VGm!00t>B-!Lr=6av zzsBn*5pjxUqEzluDYiKPOq5`6A>Wi1+@JDm`LFx+U~Hql)!B{TWV+@bpOMd*HA6{t zl|V}5Pm0MDZ+0=w9NpSv(#+;mcOv2gOiq91bh_*sBLcccyV$GoBxoPJi63*ii|Bgq zO;8fgqvI_u_3v?30D~9;jwGwK&+-b*~y%WWFRI0)Q+GH7CH@{n1~HZ5DImvZ)+Ac(BI@VIm;MRGN@iY ztngGlJx)PA_3VJ}Y;LaV&jp6X(t8CHQ7BUbD~iwqYkkOq^GDPQWOa-EqO@w7pDS6V zw_q*ERmkKk*Fsw;nHG@CU7412HB?_;dw@nj4shN82S?-^WWuaD=vD8X{EmMZ)y--k z&Hp7CJxN)qex%MdXAE%7;^~^A#_GS-trJbyxN8tkcPWxr^jHkWxd7j|US4A(J&&cU z8cG_NnVI<>Snfn^;y{B8H|KV0Bj&nfN>_vRYW17jC|7_QuRm1(K~}6!u0Mpu=(SQh zvUvTqlqdDD&^P>lW16Xsf|gQ;S@f}?W7;jV#4-O!l3R1SI>m-S1Oj!qSzSRX;YI+- z{^@m~2~!Co%nd$W?->@7A)`WkGgU``aV4fhC%L+i$@-#!XIlJ|ya|d=!b#?z=uI&DBuujC>mwRR z=UDtTZ@Rs5x*8e&BJ#(2)BSwXK}w7_!ReDQ$>Lwbo8a%0094W5gaDs}W%`K72%-cc z<*r+hPckT76B!=$m4yV$ogVCyK1(l;Oo|3}$dfxc#3vcq8%5pC7U}(>lA=I0M8FLd zZ9p;DZgr79KPrL`vFJrnjhg}&)Wi*?Rl?x_i z$d(@O(5$XR!<4ylt?BVr&F+EYu4|Tb7%WfnQgb?h$?)k%W7@-L)Q*h}F-j?ex#BJW z7|Bn@rqNg*jc>PzXo7xkG^L zS6nsHiFEy=2KO;t-_qbic22*)VKdM@uwfJ%rROw^tG3uv>O?^p`f1n^b+NuDp|f9+#0PQzUQbEXs%7S{ z!-z!HSQ=}=Yk(rN-Xk%E{iu&jjMj%Y()doZKCe-mI%o=Msz@SfnB&@JB1w@QIZ8vE zJ)M|dtOqx)9)%RiLh7RwKpW)EpfR-WZ3^(vl)l#wNZr02S;jpO7L|A)Pw>gOoca4V}db(ZiDn!WQ zm1fP}LKfoM3#sO=Y@V*}(x>0m7XqO+2_tcC@>I`3@+x1!<^0rjA66`)}Ti)x_nB(;8b133<-c}A|g3mT>;si;^b-ur%`O4 zO`j6jjV0>kfji~6hDI~SKtsArEZlWWNmrBfvq2xqagEK(U>Gc8Tw_M_ z*yOlowA#VH7HPP{K&qFiyJ=XnGPpOZt=Fs;igKG(o57Ox-PK+K%hRfNVs-Rk)t_N? z^`q5)!|zWaF8!05!{Wxe6+M*{U8zuX(o|Q8Nu8-T(lXdsJx}`w^txW$>(JiwHu1Bv~brQ>&Z zvrZV7DX#I5YX`<<^_xGTr3 z;2@DH`V%R)*Op}*0;hCZ!z(@NzWY%TM>@w7g^O(L70zp70fL#6|5?^2LSU(mK8 zE6%^S-9AL-$G7JS9!Y6^31sX&{Se^yZs%4)AL`Uuuj=}lj$a{dQYWoaDc^Q7sEgH8 zJ3j-;KJWYkpx)@xSW;F^pVFyDCHO5}D&Sk_1MZ{R%((9dNz#K|BlI!%hs&J7lrz+a zZ<0=jL_q|MdGb(w}&vCUG@0P{3hMQIU??VICNhr!YiJ@cb~}W4gqXiTne5J_kmX^_+qHpY$@?J+(`iUeYU4GPyc%h3l5ybt)0ks<&(+2u^u# z5}eTIrQo!9fyj8HON9Q>3&g0L7w)Z;?ZgYR+^+h9oIriri=aQh=*9b~)*&xZ&dskx z>DT%=^}a9pOR)-e>Zd<;RfU2YssYHK@-kI_!Yf8@YS|mF)JKKtrGHu}o4dxy_NvVG zs?656qP~av62Uk6cDWPJo_$Ty{%_MSuYZAD?fW&sFI9VZzbLm*_e)RE zxAaS?Qal57HAjl)8yVoh!8a0!1D5`Tgg9{WO@F;de}9Df_J6ceE!PopUyiK_WKs(ajiNf2n?>t^rPD8$5`#aS@|NB({j(*pZanHMy@xr@cUw*=ScEVc! zeM;>4K5=)-)HeFo_o=$sAB5?{{t<(>zF$V^>;3`d$lvpiNXl^jp9Grx0kVzF4%7R8 zKv3BqATs}(4c1bQj~zf-HfO*rFX4VLh0kR?WzjUdX4VHj z8>R2a=mpAKWiGT~8Y@lZnarn1abxxLfk?{VJg_s-5&AKe()nX5Y?O+37Nc!U%iXO+Y)816&db0dhjK_iH`%#j`h zTSpS_j*jeIsaB7ULPkAr)IX4;-so-ACI%CN^zv~L`a{{tRf?ydKEDUV(_;-AkD(I( zHs&T%b-&4tSc2YWat(dP*hk#_QPFR_K}9v4s0g0m zrlJtp224tbs+t1yR{@d%KTb-n#4l?O@v9fC+NvC~YCq@HWNRcl6f@H@0B{ex| z;DcWp8c4BIzKryiMB-fYE2H5b)8C#+B}|-&#@GAJBG_rO99GfXmxg7|P|rbDw@+&tQG~SA^@@SJWua%&usZ@v|#8$|G|gm7)DJYDF2-y=71` zvbl?KhYaNAcyoZCQ3~J<2#Rx;JYBcv*Ngp%>cBHJGYw`XMYC-*N|vv4^zQk|@iT1x zaB#_pFKqsBZ^_p$Z5~=N;GLA8*l>!?AI>qEmRpfynm31s1%@+is(vazHt6#Tz{vpA z&*WFv8!WbmBi@4x@t)G>>6u@L>CZ22X8she9=%sVXv{dbYX=R;4fhif0H4KY7XN5{ z&C<|lVezNQA227jEjJN1F7KbNIu#l_Joo*%9h&z3v^zO*|7zKA*A`6bDg5g)0 zvLwO`=S?J)5(5`g1s2~@;6n-@yCgIj9vJu=t0)Eup$6Ni@#e}ZrhXk^{@mgpLL~)F zw)n#nNpyGs8t~68dfwOJ{z&rhW|qu&{Ojg?ibanr2&qXpK8&26omUv^GX(4 zi?}$xpdp_wA!BA(s8QXdNf(}*179E$)$Xn@EhOkw@Nl|xUJ>}MtxIJ*wX~rbj0vJ@ zM8O|efy1|yS^CPQ5lQf+L2Ifg0tno~t>#F|gO=4X&qgF+O`2mNO{#+SxfXvoM`i07 z*+v-I9J2N1=*7z-8UjZ8&PX%})Ev(Y1#-b*y@31x4k-^1C$y4P@3K5PbfV3hD1DEB zQs?O%m&ZoW1FZ7B zyCMty>`JoDu`82;V0>uujb(`Xc;x60uk3@AWh>{mfX6~{9jowIz=UCm!)ACaFp=4b zC68oY=Jr_NHJcnrCHmx55v)`%Sk;Og6gG94eqmL!&|<$hLbp?qjxXkRl%=k|7jBnN zRwqagoC22>oONbbefUh4u1+PF3J~%7V*8(r35> zW+LZ}$JbJ6iNhiX5lh$h2OsOLOAbZ`GIl0c6uE|& zx?6u?U4L0Ov+JZO-DRU_Gp%YofCsz<iW$T|p)>WNYB7DR>H{1gRu8&y)S}u5VTLh-Q!fN8N_7xV2$Ewb(7Ap`7 z8?mVHvL$feSk+CuLx5E?2gt=A^=GSC`vMDL%k(pw>$5fD&2-i#%ng}og$vQ*BsV3f zM>oIaQFed`2^WPgvV_oFtKm|MXwH){Xhtiht0)-_#LC2L_p#Oii>z2b0}r7=>QXWA zE;v)3EUHP>_(xIwguT+q>W}p^=_?~3M9Gl+F{_*O?~5Mx-)(b-!I>nTM0)M--%$6G zGv^O5b@Pl{nOd^!ugFx|32_41Ko>a2#C7oanCX^(Q z&LCkuR$V>zU`xq8(5K+iP~=6LW+88*LT*^AGze`g0h8U@M)JB(lul+np(_LXlbY!zKO|dEPA7p7 z1E;VD_&%#Bp2Aw#wyiZpA|RIyCN0`lo3yBuwa4RNDb%b~#7$-G5b80N5Q)sGEDVoR zkFwfOtu<4jTDhyCTB=kn)DSBjM8E;7D4)uj@|$My;bZJ&RwzbKV`*V-SgBlAuX2gI zA7@WOyIj**I`l)#o6h11AW=fiEN~J zroU2K|L3lnXp%|0V%au*`K~(VHO%>-SQ~Dw-Xz}b623GJH2b+$j>ZF82YqrC<=}lM z{n)@%M3muOox}B%-7N!4QF$6ZQPoZ{{UN_l(eE5KjEveH&-UsIcYlyEW*%~e5En39 zgb2C5por>-2!NqQcqxU$D2&br;jI*oq%e7G71vP;M^TtoLKN4)`3T2T7~+iZbP7`e zWWW$Epl~R{vcL?)Z1%(i)R7PeDV#t#l4W?%0))dU44nY{BnrzC{bYCvg=Y3__Sk5gJ7VNq`ax%POlfe1yWXz+f59T<8f`li`UJ zCP@mYF2l3E;Sd>KPGMPKs0{C8I7*L};mP?3OAgeK;X(>af-^AL0|6xzAt{QL;X@Rb9H=S7 zS13%47NE)S=*0*}P&iJ8XHvKth2v#-nKzsu!<#59n=ny^f2J^TG$st+{#NUMhz9 zH`C8tO+s|PvJQw|QdSGUd&{End#S7uE6_`?RoB}d^b0RTzvQx^5*?rlic}A~y4|Wj zdoZ4D&@&Gx@Kts_`*;_9--#z}U(>>Axk+DpIx_$9 zlV=&W%hCJE({v z6tPI(bT+|pZ3-DrtGZObcs4e;2qBlEF1E%qXtzZz(`)^nX`kf5GynHzCA(|*AZdKA zo^`I|xSn#Qo5ARIwvv^;Og?a>A!hSIS20IH?azBzDl)pVFn!h424G#>g}PprK6|Z} z!D)wnuncBd&%I{wHRg7nQlAK(w!TO_efHwrY_*LsodMrDj zAGlImUwzZgw9hVLS00VTZbqQIemCj{mf7O5y$Q@(N}E~6HD)1t`K89eQqXAhL+wN( zApQD{rqyYq2Svo2)zW{*t(C?A#)n&bD~aS^hg+d~$&DISa_k;|%~;JPNnEWzaPvMi zhPVkasoW5kZ&uL|9jZjxWZZH#n{5(tHCROWGKYV%9HC+}OAFdIw6JKvwXv`o ze6LN631UfBtrFl?i-9xIgR_B^)n~sNIFm7YRA-2(PS(XgA7rMO#+#wwn%HY)Er|gM zGM7VE0YiRGw6bBCG~3AC@=m!A*o@rqKDk>`?zVOY6Df1sF#You9_(AV%i1v@UL3Tt zCa7SHgGE=D#nW_A^N%By!pu&%Y%E0da4_wO;4Q~`m^X@NdfJ3(`XwL zq)EIH#KN3eH0349`otky)0PGEflf!Z5oGJEztNmAk`6Te!vU-z+h!C$zB26P00Xv$ z2lmN8!0tELwIC4e@}T`J$bgLYK=up*~{&S$B59z`7H#iaJdcM={cw7S#;c2oJ2N2CVNz0_&y9SnsZGK!$rDCszmL zg%Chy(RPgrUUdjDAj3S6Uxc9iA~&x9>r?*gp$2TI2X<>HV1IXWpfaooGhjnJuouHX zK~^9r*jbr^$>9cMbr0l?a9}Mku#(@#hl1}S4A^QO*xHe-yLeM!wZ)W3w3U}t<&g$p zum`YP6p(H;kiuKyi!?IYfK?@Is1!PKsJu_EKJLncpzV>iF#x(DyDN%1Ed*qZn%JSA>a% z6#8*SC5ljqs_jyP7()&1vObz&7*HQgV$|TbgJIw4L6>KsgGUSIc{-VQ61B)!gC{l* z|K5*R>bDDB37T`%VhDi&C*?bxu^J}M)Bp9ix1O`;w_%y|E{rEcFlmr zLW(b`{&CXEcZ-u&zHb}=^9?}koc0Ce@di@GhcJMk&yiby48Fi4V6gcn;i%8N9J%Dq z&1G&wO0r~b+W9HlZn2Z``k%@DbX ztiC($Nf@iiftFa&F$t|PLu4nh)~rNqNa+g!;5Xr^*gj}UvptMars8Tu&KH>I=$XWt+e6-*hPf{__}oPCqAj^z!ma?lQE-yjyTe1llJ@(p6Yvu_aVR^H%B z2QBG&f*C4MW9`ZlrXYGIZxGP5!_-41g6O2YK>(wJ@&=KL&dE23j>$LZ=X6D4jROOJ zb-BZgx?_vE;`)6iMDLVIEfQziu!h)qL2D$j;^lkLt7>BTJ?yp6`Q%Tpt2P1jISlb& zN7dmD(e_@}&hgz>NIFWnUF}%o*T6@tC3y>7tGQ*;Yh#SVD#g%sK)Blh6uDX|A?zDGRJlCFuvmeCY+p~A!0hW7J zg(a1}4gUQj6@8Z`K1*f)#G|wo6aT-=|DTun!6fs){VSOdsY2%0i#GSNyB!B-A@h;{ zlOo@y0~@FQ_6K{fxwkD1T`KsKd$0c+*4vtk0mGPGoV^bV1~c5O!KP=7nYv$Qy)kAw zb5<@F2LI0LST|3lF_TFBoppwDPV{<>wX$VnWrJ2Br@qD_FiZS=BTEolzhgF1+bhx! zCQg6H9t5Vli!fMQM1Hzd>7xq~<>y#6By1{@Ybnm}8LenE_#TJ=cAnM4oM-fdv@lt< z^HUT)2--G?vIkkCNMHA-*GUKeNwEmn$Wond7ZLmkt3~z&b}v>^Kx$pDk4PNcDAz+9 zUSzcbyzV;byr{d0wNWcvbu^U1TIHB-?2}gpD{-8xuh|8!05%zuJC zicypDBzrtytCuNOb>C<2v*#gd8=u5vXp!jEz*^rr!jR_Zr`Y{`w^fuiu-b1a)y z_D(;?>Y$u4O;8*b`{%Gx6k9k4i-KhWXQPIZh|(bfnO}-%_e|DOobHKynm%=Fgu$U^ zy;vvp<{vbI*CdPNrUUm7{#=Q{pg(QX!T;$YyxepkhV)_2t5g3VS4J316h2!q#{Y%8 z2LHb7fqOF=DRRe!$jyXJ+WaQ#6tK<9z}qae+<36kFh&D? zHy)f@^H;LaF9&=?N5`=%N71S>$SD@-KoOPfabD41%N|cu^Z%fcnR}b}B>OLGdczGx znbwCj75!*(+H)|QE`QtB$Pe+ZlD3q3lEJ%Zuq zFInu}YCh1}SYtJ-Ul;TpijFm){9h_$9ZMDZn6>^dqK};ee)rbCDpjm+U1^x}O1iky zUH!kr*l6u|_L+L^59;FH+jMbpu^|e7v0+dLY!ejkPiFTAT=ojcZT%I^C{oxho8(q* z_{-=V{bGKC__um2_jow|}923cB%-Q08HtaP*HVi0rz3=Luz7|B?#w*do>^ zV3V6GcU)WA`$rdWo>LG0K@P9HZO$?G>pz*p|2Md!YKv~m*mJZ?naMj9;4qCmdQRWwbD}*b0x23patNp(1BF>&eg06*rc%G@SnzX)9P~ zzltsW;?ouEF-kwNf(=&V;HZHIDIO2nvJo!^u4K=V&z-rJVxi4jH(Jt%8^~R^Stv7^ z=T+1VM0o0kJ=2uvZ`6$Li>SYvf8NFo2ywT--@kU&DMt2HY!vXkIkr1UFXCAZWjCDGGi+W)~sRu8BU>xiM4Ct z3(-WcwX6Xi*~ViH9!RYwQ}Gfky6<3GLHl*AFXgg(a+PmkO$&n7v(`M|SFa(y!=&?? zF=MFYkDR;QP>cV8{>T(DZ4+FYD+HS2WzlRidl-xjB*w;wo11Yvlja{#5kk|HZD#cl z>8yxE$gffe`-#@GyF}hrR=r@(7M4YA#Va6yq-Qa1O8dk+wYzP&fa&dRqlK)$&dfG$ zyO-q!i?_3flz<&xvAvBKhBMX}TUVOuuU}_K?f>)6*vpH5cCB}ey%aFotrd41C~TGn3_GUpu+yUen^2+{b%)qzjZ3U>-i5kD?z$vzw31y0 zt{7Tsr2|rhR-~dk#A`Xd8dnT0wrOxFqdUYFWO}Z&q1V{-E0c%#thi;!?*wbaibb0f zEC#1@u+Yt2dFU^U3$es2Cs;@JqsTkKq629ch+KM**W-v?Cs?e!Xa^^|>L_{E7D_Ii z3c-#`^eyg_b_kc@lywpIp@_JXES63s0tYszFu6HJJa`g&RZGRICs{(^H&|p(=56UG zRb4M~PGTWQ6H89A6vr|oxk707*ol*Hzi%w@R7d6V!5o%&|IeIotTq|ey;nC>~n}Gv9C(od|8-(L5 zy2fSVR4r>G@$y*~88FYQGKP zreKRC!nhU=_XuEb3R7_@05+vCb)Jpx5py4XrnOMdEA2wTP?fN#>LlY@0C_-Kq%!_U zpuAa=)-nm{3Ne-O`>=j?lJNv~L#Uj0VrRt@oc9mFu`+I4A@+rxiPFJ5N}S<*I)KM1 z{2u2*3oHZO*@lJbUliUtWU+;AK`;*MV-*$ptQLsIX72ji5FPwZ*(f&gx;-Z5O3npB;~4Z6*)mXrco{TMQ=DaZwLx|)fMu(dI6QCQ-s6-bvbi7 zzy{nJs|JZTx0$o}RkL`oI&UMI|73of0ynGk6tU|kbExR0@+iKViI|<{#?_5W3Z)PO zncBeV{7~RzK&V)=!|YehVYXPT4u{Q7S91Uedjj_CFh@6%7Z%d$YfGo6M#hbW6xZAn zC2ud3P~w3Qp1{wV#hW3#0oRp3XzLR#`z}hJD%K#GPqK*J zkvvHhMDt*wMsdeIxQC*7l^Jd=*|>2PCFA0Sran1P@-tCJ$#;38Ny6nFB`A5B7)8mb zRwGX`2=XDU5Xmipw1H1Dt}ZdIQ!wICapQVcQV!-{-vbHx3y$WI=4Cejx?+AbkLnUg z>PP%Ry>PV0U}L57ZmpMbf2&ciTAmy@hcE_+JK*+-L~mT~tyzt$U6FN`g*I(cVK}`A zLlWo7W3qc=GmdIRgDrwAWx)zY{|>p2T#qK;zgWEV{H-x{8KzxUBzE zac>;&#zu*8ar|$#ueds!YZj3a5A7}%Q{#CI+alJ)^Ki$xAF+*OE5{zu1Mz$?+b#Me z@CGS+BrPU7&`g~|oS&p-FJkK`B|P4dR^#CS>UwFQtBJJ<99OG}y$QTN9*#ubHdaF# z4#=zfSXzxZV|OTd*I?C;(J1}-MD)NpVn`xJ^*?8euM&Am1RPwz+Z}hLTPZW#RW<|o zR3dtr10pPm#% zol+3`M(8QL0n*l`@JTpj@LU5PfwXrU@HrJ}4>y!)ry9yMTO&RnsK0K+Qvi9o87j3C zGcyRyZb(Kl&$I-P;Nh$iIug8)hfNc)jrr@yHL@{s9T6)U^M(kWXbh>>gyk+&>!_G< z7w?WjFWe>5YBk~CAoABHh+Hq)HU*Wt3tnx?`>@!2f$}GAkpYZf<$@hW@?OX90MluR6_@EU(#}NBw8yP#Q4Y2MO zE86gsYKPpElRUT?bEOS`3>@j!R+jx?TNvh}VscwqUU^&Ir=qsFT9#x8we@SEz=dg* zwSBuCe*i+bwjJ+)Qm(Y;FQVw4sVI84_%IdCe?TluMcQF;F_ou_*W2U$kAe?GuJ>KM z5&y_0=D7G5?&qiCNE#33AKS##dw3lYe-Gq;wRqwlj9SY??mfH>LU`0Iu-*$1YnpAB zV+Tw|&zU`M=e=(iyl)r1ZL&GlOP!dM8FhOyhc~9{3qt3ihgIi4yUHQP&gVHdSGa7$%GE7hzopu&wonh08 z#f{D|gvFw97v9Q(gZ=8yqF)y@PL7z~g~#!0qs6yfcq43WyVwQNe?Zi}j}LJg-U2M# z1I@Dg_(SZpaNG}Ut3~bmF<;m%`rpr+MC>6eV@u}AFi^HSN~5?iDH-R)s{5fc=f%nU z(IDGI@&i03X@i9zw<$PA@6>E`Es**fhU7N#d8jxwVZmJh2SoY<{9Sfn=Fbms7P-_y zw>eP_KS5sCHk`Ghq4*$+xZ0J!fEx9DkWY&zO5yv!`Kmxz(n90h4R;l;g*OD350hn0 ze2C+MCNb|JNXhYn^AGXiwi-tu>~Pf_gH(-I>7og+JDS>YRkrwqM=&t%v z!Gb6FQ>?`xMfx~gJ2#?mI;KB}N-1wj=K*Db$C{;U;Vn$)BDJsM?1bXz~C$$U@2*<0d`SrcxqsV4VYiTZDL) z_s#&9aCE*9oHaHbK)Duu@r<(g$g;UtDTiVkd?pvTq72OTp21^FOd;jkwk%=d(dZ- z?<)>2IalrmpD1DJ!Rw)aYTSdTvP+_W4_-IohTP8UW`rMd5HFqTC9${%dZ-Ixdk^jc zY(&q01^ZM_9#`uE`h2hfG#FSQ#%IVtI?$weLCaE%nA(#kWgra6Bx$4T1sJ8HWC{~| zf2UCPcR)n@v}7828|ilQvy?=#L9OHV@JWfJ7SFYL7)zICS=4g`ObUS_AaFp0n{NoC zO5~tqilPF46OZ-cU1P3um+kGhTAPM2mm=@3055?iMUmklFz(5~j9EJzHD@JPBmhN)wvKXkn- z4oBFrg6P6{oT_ac8ndVq~Oqc+zR5z>dJ1Y9R@YH%|}J=h1MwW}ht z507z!8xm+$M~k_AAU?%nOCQ-XH~R2sd3!s9JdH+!qDgG=cJx3PU{Dj3k>zdm5^v=8 zRNGsdmfnx1a;g)k#muUZBN>mhkl%ca&|l)Ms(oq z!e(k=X6!;=2hCU{HY}s7{4zK`!5GcqSh5r>!a%A=3QLmf%7kII$QFiVn89IpcBl+Kf8m!V zzsLkI1Vq*=JS=u7@puq|c6B%*wPRQMNaMw{MjMTiYTf;H4^3m`dns`-vmB+V-hIYBXUI99eW&_?D z&}lrhI1Ev4QSG;0m2;M_UWICBo&vu=5u0E2RqdsbQb|ROX{-O z2#k}uZ1iMc3EH-TKZY)YU4}9n`J_yGwAsjQNH_SIl%7V#RrHPOAVZspLRXQeJD&kt z?ZW6DoiaUgz)`woa5ISo6#a|7yroysFZ~XRx817f3KZSyRdigeM!LV0Y{D!Biawq) zfm|9S8H!GQL6K6ag>_+s_X`UPYWWeklGLZ=T*_SA2*hfJVwx} z4iyvnNvp8DpR@`m`tca|_f{w|_zfOrHz?V>UaalMBSfb+craOUbRn<^MfZZ`fuwO{ z5k57BDPHNKP8H7Qdkrqsl zr*7&*ip2NK1|?}cjXvX%33DX%IBQ9vsX4!tsHD~f2!^xjI4PWR+F;BIt?A&C#&Fd# zAYk*0JL3PfeYb?NCEnSsi!z?P8k4=7uKY=;n z#dr7v>Qu>A4^QE(hz=hQSp9w7$^a=WR0#u3>slu25_cXsZ6q)tQo&Qt3#| zW`W3Le#wd?qLv2zh$A5;Rm7&Uy;v~)idtw8O28XB5GPHLWVXaxFp_E;7-yMPKZ$Y{ z20pXI6aV0E^_)!%LD(oroo$w1Ba-@MSOp0H8VoQ3kbM!dz*5{!2^Ll4eKJ`nVyao4 zDeC=`*G!s2rIbtab_{L7R2gB+p_lH)RE@?=qTfGxXal3Qi^#i+>o43Rm@;{dsXNHj zxrA;h&T7sTi~fnrQ;Nk;|HS&(md`%m-7?1S0#D`&H@xLXk}KckT2h%kIGs z$(P*8QqAM(+d_Woe1dkm#)G&DVzK86v?Iw((nDWy!a;r#7>oeSSo}oS!$t82e0D}2 z=AY^UvsN9(IN2kw)ewNk*DJlbcO!>7-5eJPOhpI;Q6Lxv2dH_HV~7jY(4WD)FQlX4Ntr$N|x3$dPY`JH?*>{6M}FS&*Qhib#;s zg>hwOP+#JAp$+`TFLgBXo!kSVD!v7&fF$`zNV3Yvu+Ahi#1VWPfzw-*i{a8)yNkUk z-W|Y$9HfOt%Z?tvpUx%B1p%1T_qAkQCE0Dd=f7q5w}E8Vg|LoJQIv=5{&hS)nNt-;(av)-5ARe z#C#paf*^OXz-g3DymtU2$g4;)a+2LgK`?RfHUWqc*;0#8<=_l7g2d;qRWoWTn+pORqC=`Pu9ZW<-qQcNawiKH5Bf<+(oYe|U|3X40@jOI@#%MQ7rA)*8m z*E4yeyS!Oxpf9sx(gJz15>h7fQ8!Qd%$WE9M)Vkn(f%q=OTwjxSji^{k}Bh=5i#A8 z@zN)ONhWTzlxftGXh#$v^H@Cb)TEW-xdCsqExIEE-r;gmd#u=4AK-yn?ZGDW>X zn5gU*uMFa8SVEaQh>v$3z{YO6m|8t)77u;GTPBla!evdPG@Fa=%|juswz31T(Kcr} z>_S*9_yj(=Vo~}D?+^tnSPE3>Cq$(HZS>YOld6kGgLzkYrUwkhRAi4>Fqlt4=%FFJ zH6Fu;UP}VLjY>xDxvi%dCd++Uj`aqZN!5AB^F3Ou~^nx zDH@IC@zv=9G};dY`B&*D1cw)29E;VjLt@2Peh=z)bF5r3tD*Cr;O~bz)(UrvIXYj! zPKl>K#d6+vqU=-d(y#>Mz`m-uc+COt3GS6Z2>u)*_Fg=4glim}P=iFTalCHh{cNU& zjZ|oTs0oA>S!&RarZ%8YV{7rVeaFV|eXCvDou zE7yiDJ-PtCT4ROCW!#y#S=_gV*J)Y>APQQKyW-WQSmiglp>b@67N1~OEEu)-oXKAZ z8@%lB=5y0O+1xyB{nGPiKQ0)vaYhFG!KD*;QVaKS6!_UpX&blae0}-M<-)xfBjbCT zrnIs>zwY@tZ+z|%L}Vd?gcn_u1+?GHk$auajOX>6RfWHTG|1#ex^~G;ACBS}q^(`e zUkxkWb?W-3SI$iwkXBeW_WaS`1|H4+b4Z&eh_u#K;lCqkQ*UEk_>Da~_FkX;eL;yS z?fjlmtLKhhJ890JLZJA4F;8h;CHgzkhf8%TSQmQw^IxWoS+((SK-$ucUmpB@>BT({ z{wa+*L2|BD73l9s7{0D?i_C@Qe!YF^uu+SLzm+!d#?XlqXRO{_|4*UrpisZ%$s%(i zH#e=Kj60HuZ&g(AF05>PY2mShzvx3U(!Tnw{7~-HYm>XU$!qSu;znx3PZv&qt=~+DSa6RTbDP5%#^0KH&JxExZd`@byqJZ~m-BWu~;8 z-=+>3x9i%H=l=}q=E#<9Ru%d?k~iB|=E4TuJU--?37O0Hn9}yIzOemh>6dGt{WB>0 z!O+&K(BF|V+}eE$<3dM%G518~Y7%8{f@-R3)sm3 zODlJCZO-sD`}3C!Nc(Zc_b1McIzMum$B6t_;x@}*TUF@qNEz-Jxs`1T4jvx!+oyWR zw8NjRzPxI~?92&&3Uyx?Y^wtM9f`x;SQT0tDz=v7?f&`tuQ6#;PJW!b_0WWE@3@<@ zMXvFs52>W*e%SomxEn)PtFWuM=vAE>(95{uSjHwjsgR#lWxiMGu?ii*Qm zw=!<$&=K>$5@T-mOUplU{QDzomdx>3k^hQ7Y^mo2=y} zV-~OT4BS>^uh{v+)&*y8-a!K{OyMa_t3Y0flr28OkK<-O;`Q;co6{$LJR`GZ+POVb zXPrNIEU&GHtpAEfs|wJ0R)M?{S-v`n>qTxAt}o`!Sut+d@VuR-w0X;yuUb6j(vpt< zHE|31-P3(VuuQTh2_p!JL1a`Io~{%wr9_nc?+_3to+d{@c&IavhSt9x2_6* zCDMGG5*IJr!n5#cLoVf<{A|!n42Q;F{&K?cUrt~6+S3KJ_^${&Ckbp`WdV1j5Z9(u zFfVlY!kizMjrnENdugN3%%1;w?&6#OeS2c^BG!KeVXFdpC9-^lZS`%83q3OO%%R^) z^5@2-EgAXI?5pR$UH+&?*8Ur|iSqH#&nl2tqRqEa3o5bf_pF_}SM4}3=bf~l56;|P zFzlyQkN+uT{cR#xRt54qlJ(JTeP;Nc{TFgR`gr@W?WVMK+a_LH^3{~W?W7Eom-57> z{~6O#Uq!*V8F&K^b)>d1;WK^~IFQgoC5xKtxL@-si@GDNxX93uy7nvht1*Z6eRt^6 zn9rB@N&9xePn$MhoVMUe_q5!i?xhKNQcG-DNUH+OD1cX*l<&D!bP|MfHFw3%8oYnT zprPlBK1};9`=fnd9UZmkd+qG2c1A-44NlB3r?E?oGt zDec?uXMekY!mP#NUhL~6_EvZsu>-HdoZ* z+lpFL1y@x$8+=30YN9Sy;Y7yfG1o z{p{DmfeT6|=D(9RbNIS-IfGX2tLH_ZEzu`8tpdhCT-ncqQ_r`U@!0D#xBNQj+K`)d z(>@(~yx?@^?wOt4*s-Y$r=d3R>Y{xiw>SOIrns~u^_%makq!K(737^-%k8){$ZG;xS5-_U3cvFi#GN4f0B_l>WBOrhkwo=O@54h>pt17AzmA?GM zy+*h2Gki+%$c3Z6J2wc*oSAoR-kwQwc5ET*KYqi1N-Nzn=N8LYF}{#DXD{KZsngC~pYrXdea%4DrEmXJvU1&Ib^ngXvc*1}tEz-M5{K&x zZ{b|bnH6J}uUfEwZAjXL?5lapK3j7<#jD&!B6kB1X;%m*t_%0TyZ$2uDy(2+sI$=1 z=$Q@?{4H?yC~QfqU&b<3qBvzcncrp|D_|2mckRXc+ zbRHXfr#s;rm{{SiqeRe;rXq`}au&it2iWLGF2Z3sf=`){dv zrj$q3`%joTwG=BlMdD&9AB*N6_5=S69}0{65i5VQMAskrOgzs2$X^Smg-0u0g;8A# zaQS0jgB`yZCceK7ivzM1y$Pkf*RRR}Z&he-(3Y=Hjy6MsgY%ch$tuyXIO z&JmAp$1&o$V*7Uf9qR$TgC2$7p#F@moqRCF|ecdEp*~u5;3r5kq_>1zp zypot|T6Nlmjr*r}@s@19*tm=LV+%y<-Mp9kl zt#hGhvWKUHEO5m8Y1r@AQ^Tq>mYA@_m?z%e!?UW-cTg*0Cn5Ib*fsdT)rAE?dvOeo zO%(I@@gD-ebkHGqLs->GV$^R}(oxY0lWoH#2(r(Wqc6FgO!4eNQJ2j5asCy2cV zfInX(mfUaUEUdghBmWjryc60x5-#Db%|W)QF~ zRnlEQ6VVnB-Ql2z=;x_+{!}~s*wxR(je|U)(dTp;6Er0APtDL>c_EpagB3KpmM{}% z*tPhXP#K9-oq*4_h%x(lqWvhLHv|2LKYP%Ji@iVdVUHJ5WoheM4Ov-^HA+uqu^33( zh!WFjYsF+RjUqhUacW6gBJ|UT|HPmG6I#q4m$M${3H9UsUH=MwlrMVWJcKpme9`p~ z7B@c^>4*43xA5@FA>Pn_f-0h*B8?C82cnCKct3TLJfX^5v+zZtT@+=5EQ~*lwb}_{ z-C>BtDaz%CTxSmRo{e*i_Jw&MONk#?%G>G@2u;f+z(8dC=m>wqL(Qcl5cz!3_^8py z9F5%XD3+e{#g|8UWBVmfLmoKFU+(A@rGHrziK5LlfyzQVz%;8dUd?*kdq3 z1pmtG*fS*os4NIi6n%c>_dc~vB7ph)7mPBf-yv&lKt>QabuG7u#%(onVu6?h7`yTE z#RDfQS1SzF!UuUORSTaABEd?G`kj!!n6+U3S=7tgzf9H4gcIU@=LX$MDHuP+; zqlRS#v2>G-Vet(Sf}M3@gBVl|8-xtY>&`%DxRC)x)82oHLq>@P=On)#ILF6eRK5Qk zUx&xk^XOTZh(|8)JUq-7xj;Xga}g)0e-(`{@eFoCEWE^TXeW&uLCESm=~9$;w6lE5KJS60V{>&WN5@u}S2VSbLS{;%l$HuOV`qm~xGG zN&d+uc|`pSIul%fg36;(P{!>xig8Ep5bAYYRiax&tLr=_*!Vo392nAe)4>+;(skY} z@)W3}ts}IBXRyT?PrW9N5braKCD-}bCire4y6I$OIHS<<;$)nL$7mm0Ow_Y7DFjKs zyOTm>y6AQTQxK=vx))pjeizGc@KLzrq{~g*%k zbPC};91Al!#oSp+1i#G0-`Xmj*;0|)R_TX3&eV3e^Y$mPx}EY^^$^q-e2PL{=YCp< zfO>UFr1A!1tHdw{s#l3QOc{xb%UW^eZ5-;H&lNqel!}H5CYoF(=OnSJ)EXl~!g!;Q z3)pLgb|BK|m;%EF!}H>aFy1D^%h`?0`4MNfj0BS_)B0*WPXwFQfjl12^su}cr=Z%{ z@J9Q1Xu}I8NBEQ@4h!Mr6*j41N1Tkp@m`9eR2!hmjLq&eyuv{f?5M+;9Bg&;#Al$j zkpTU`H-E6BZjj_FcV%KHJ{pfOdq7bPB5?zRCxSK;$-^u13=4|H7C;Sz(n1iHFQegtZ7<#`|k#CCb0pFCNFSj7&l|D{(mafz4GIcbf1MkAbk< zW~HcuJyoR5bV;G{g6*Cg9q5d=*?iT53E&(5I(9q_MUo^aWFjA2byO0 z@Us!DhZ&-~MG48s;`lZk5lF!4Y8J=g0;lsc&aBj^<=70Xpi!~G8BK#N=9ddSBtz9W zPjxL_UPye&;?(UbIFLx3^TJ5X@%Vrooz5_52No0tzDRClPzZZ7>2xUoD0>B0Fwvu< zsj_h(DrR>ca!Vr`=Y(a1I!ZQ;k!T33QNB@MOYB1o2YH_Gz16IOsaE9!ma&;83DP4)+v;clZ&zhpCiwy=#V3xM z!a{wGPh75y1GGBXaD@^%rGsOnfBt-H5??2BmT}xGT>9Q{yrJ zG{ES>N9C59L8A@0i1=uN69ZKxw2j1CVkBtsH9QDPz+&Z=3PXVnxa9a4iJ(+fLaG}G z=$Hi&YSBV~`I4%<_=rp>M-Gb?X;763DD$nv7ve~WMFRt=!sVdbd>h@_*fwm@qJcOs zSP6YXLYB$68b-DfnXPj3fGwE8TC^Agq)>wRv=hKO$S!40g+Li&&w)sD+>At_5zS)*Ml{F})Dg@S|#o zUe!JPE;k5|z-b5KcUE=fj6rxd$O`fhj?UqBe&hO1K)4CdmJqiRo(HOeJcMUTkjnZ1 z27#y`585QT&_9x|Ya9H{;7F(N|F#%e=Nc}U z$3ZdlbViWL0<{?CyyeLb#z5I2T9HslgBoKffsO~e@yWMAy*KsdWyVN{?opQ`9RjAU{_c49$b&Y$e~jK1 zeG{%a;pk~41?Ze`&{_`PXoN)Dv^_(g3{Z*APSrhQ13E|IMhYkl7SJDiMk{2+)ohOc z<7m`FLn1m$=>}JD02R39*azw^Z(Wi@H7|fc4G!p|G(vW3w7)sDAd-dBAOOe z#9c1nnuh}zg25Mr-WK&6E8__l4GZwF6G{vpU8K}LXL?B;yy#J$17hMS4cAjy-0v7B z%CVe74hpx3i}6Z)Q|h^hUnFOk0UEsbt5k0}?C@j-z2ijJ1SMP^=k?MZrP1BNU_N26 zfzBwJ!kBOnIEqFhUbuLpy}ab%%rSAncRYo|Zgx7!OlMG~(0F)*P5o9^ray)sBySls z+M-d4A*&F$5!|`S!u)8smTQ;8H4+pIzi}d-#;5X!#>jGjMgm5YG;kkR*hs07v_Ujw z6pbT&WQAk|r_{i88E1dLxSN1@Qi)ewiar5KHb_=_MTLf-l727K-7zpDpiPzoZI=Vz z+na&rNi_5}>f$Df#P5zj%A|@G6QdZ2Wdt_04h<(m=wJ1h@%X*cVv> zD9};CUEDWB9d&fjaolEcKF34{5fua!C=}FyD4?ip8r*}5B8mic1Qjs|Dhev@xbl17 zQ{DI8fHU9oe1H7JCw;rR>eQ)Ir%s)7>Qt5OGsvb4a#;z+UIHlQ0)Iw5N}Mr_a91=* zO?@4x3cIi$Sb-&}9r{U*7Q|(XC0XDhzx7 zW;dT570ljSAERbY_cva}fRItfcQG!^FbqP(Q52FgHfd)tn~YPKVHq}z7+TSo zi`o>9RT=&fdF+6UWDjA16)+&LbX<6#9_TTszSBv8J$nC1pJvgpI`w+ygi?w)>R{IJN>!ljtW)Q7AF#DxH-W9Gswdf zNu&c7O4e7X$*rt10yV3Nwr&2>O%?T$Z&YU00kbm|*rs~3S=LPzLaTqNn>x0ql&nXd z15^XrwN2FlGorgHs*n=YMP#1OoaUR(?B?3;>dGpM_3y!_65ABM=wXtYsVbSiJyelx zeWRe1p*@(hdZ?Lb%2z#9q1D16CX?|46klqU@dHRxBdPl<>C_$LnJS7oyQf+e5(?kE z{S|NOgkF;>P0&jf*%DO!yaP1o8cEG;$PK;JyQc`T8bI3k{&hfiJFr#IfDUXFRJ3@L z`pmN4s-^Q<-J0I&dDqPEr%JcEKFHZ4)kX^P76vWdDeTf6j`w}9_Hh5P6Hqqcwmz)sUgdez=+(BQE&=8FDshuvMbufKX+!yEbdVATbCCEp*cDq6{<0x<|1xDCW#K(Ra7lvJvN zoCnPDmFn=;krOY-4zm4x3@`by$vjl4hB*t&CzYz7GtIOeq7E88<1UayPE8e2M28~I zm>%TPt@hJhTssIFkR_ml0%`!W2XFBY-4i&PW(&(d82q3^W0?NUl4kDcRt=mT zvHuPeWrOR#hLr}o0nNB!s$c$u2JBjZ6hjYVS2vA5{-V=?FJj(}~ zBD@gT)6b8f5#hVRO7rC~I1e|!VcH(74sQ9QLya4g9=*8ulkKlG9fzw6;KrOZT(!gF zf#GUi;S+Ef9t&xOJb>$667XVzvqq@lI9vCw5$Y(@d8F#$tgky^q&lWetEV~TgFz^F zuf2k-q^|Ivu3K@s3LNL@y6?_V^KnAPT#x{BQcwe(^Ai6#v+ykSC!9y!e5~q@LrV`H zi>`XX{9~*-vG4`x(ont8yclSLbG@oJGvOTdt@Dz(=3G^Z4VAObRfl4|{@ruc-^(|%ksumSfv|@P8l%G> z4l+*U8taU&n5)iH7oyZV=c#Hu&iI3xj-~Wne}HPR&g7l1IsjD9^VQez4R^ReRh4X- zB}-3eU&uLRTf7wp)6KOPs0jxm>0hV@R{y#dTm!%M&=?MBK!@nR1qD|G=~Nztit~o| zOU0TlQuFpp6^D4>@0SXBj=Y8YrBcOouDr;+c%dq8v2AgEtWPX9EXHAu=$-A0&7KR@ zlq?xGTjrVxe^djVS?0+`Sc<+FuNYaMt}Znx?HSIJ!yk07YzhoL*a3`G7}5Fke|3_AQo(qpE#*g zM4DW>4zX9GIiqoV$=3d>gbXkXbs0&u*oa)+>vNf zaujmn^o_-)`cLX0w{fvq`6qR-yYoTw^`F!r=XKL;vTI9NT~>B+>b{sM(jd7A9j&JmPOG-N~ajc&CnQ^p&(o7j`0P2N!_?h z)Ll-$)o!90us+BUG2`PEW5)@mtN{Hc;SVo_kCn$t0vxTFjFn*2cl)y%mUz<@Jq0T} z|1p30v+8I1m%F3#tPHY4$K3m8HPA;a5)@HNA^g!Oz2nd7v}Th+Cc|734i1l(?mH(G2r#KIG$0V9Q*>}Wu7h$oZoo*v z0eNu3D)Lj~%SD^uA;4idi6R`d4du^=?w16|BXFWutiV)WsX97S%-Aa-h2AvxT&db) zee0PkRh9GhtgF;R1NIk4Qos7$`qM(|gR3AO)*I()Fvc&-&Cyq@5qwU*8d7OP-D6j) zi?guty8X4P-GxAGD74Z5%TPk(mTz`O?WmE_Z$ZmP)C2dR{a$-<>miUcNTt51r!^}0o~_sNWsrcyX(|V z&KGs}U#E5|WW4PLH4>O^xIqndkeoX~)hnz5zIu~tU;Pcs!#Rr?-L>aP;uf3Iv&FkBtlxQjtcGk%)7^h{~2tlE)hrLCK7 zl|(z(!9$aQ7u_-G-VvUa{$R~Q>{NfHYR5Sisyr7*A%iCY`bRT%x+=+oOo3#zQrG-@ zy6W~nnKZ?fDL%Dq_x}%*%795TDM;0{1JWcX8PY@{2`rONyj^v4e|F77x2s|~e+WJ^ z$Y>sTO+}$T&x$QlmVLD|&$4nzOgEU8-;}(ttMWzu_&<;V&R1e&0VK1S^3~bETSE$kEwk@i)a{S-SZzELKqZt_> zCurj=68T*t2d#=8%y}H{FqK$X;l`^=ILXj);z3d7Ob1sUY(4avg|NZAdxyFkw~qZ| zhU$sO{q}LsOx4QloS}-4^xF(|I39=1lnhtc2Qo1Gt25?$NRG+d#;hkV554JuYr!)O;zxKWh~y%G(})$LDEOWYiY6&M}@s)CK$}eFPR67 z>H`>WqZA(QY8vj_k1?{qxiKg zRS(=gXWNYn*G}mzh2{vJQnt%nID6KZVRHqEv2z9IYvu~hK!WsVy#>jtyXL=AKj+=` z_xu(UWLRAe}sJ&Z2*3MUjX4~E1 zTWLZoQ*e*4LFaoSNbQr&&_%7Va>Sm)La{*d0qOjEq+xg5BV7dK3eB7MM39P&cdu#= zsIBjn236iGR6X-vDf6#+s=ZlsugbTrDm2f|Q@PDrR^7SjsbAKAdiR2^AxYcMs+By= zYK5YMYlWhx)uw~ug5}?T4)7@Ro}cc^{F3TS^oNa_Dij_xY<0x zr_Veg@Ge1&$D8QH~ z=^hOB#jZeP5(?3T(L-Ym;OY%Ji_n}~%#VxIT!enTewNqEys#K}Pd3{Z ztJ|Zb`yNzna8b_Fcnr28b18(Hi<5yvXOv>td+5%m%RlK2js1hQ`cu(D)HKZ`9#Tg% z$7JYPqXaH>eBEF!cu0+OZ&BuvcjLJH_#yZ%CY!7!;A<;W$f&yktciWk}@ zWLvLUBc1a+Qx?s<7!rMtC^~YUqko$MBJk4_5#VE1F9Df1n6HqOn>)ZVGVb!}^cv7w#$noadp9QL0pR}>F8a0J!bjQ8+Fo-$V z?0#5{te%S#ojG4Y;mZcyxX$D9x(oW%F70B2C+rX;944 zzCq>Rqsr)318YESib;XUDVfEOTsx{3iyf6x*Ti}o!_OjDB2`xU98n#vD&X=jl{-9K zh6$DDq67p9R9?xK6PAl}otgOo4f?M|4b2OiLxA|g=q%P#9U+oSSkxjJvIIg|B+xx{ za4N#YQI(R489R%)H0sAUkKfXNIGx|>iuZB6zGE5LuqR31^u zV+lATs+@39%l4DQvcg(i-(@qIkCc#pYl6JACUW4iHAs-w(8K_ca7imFnh6+f!$nu& zA3SWGRE}5;xH?2aGZV)RFo_V1T3~xUbQ4QP8dyZ$5<^vD7=rLL7l9d9dHIph1yf7@ zG*CR0%Ih z$>XM#+Qa)GsxV#ExlT4+OAYYB*qB;~Lx>z){in*at|-fPM?#WhMM1S9@vJ-%L1>p7 zLkYufMoU7nD99h_VG2KVcPcsJMvPXQfszc|Z!-kdxKab`p($}8m+2TxwF59yU}V_^ zeTTwP-&_7naX5v&?IIZh6n}Oyih2%0HH87X6Zj)bG4q5Y1;Z>XL_V5iR;^SO_>SQP z7N)eZ5J`8LReoBj%KO5&K)fax1$cwPyd)0V9X6ECn8<%2XAfoYZ)73>(C5cUg?r;RI zq-HL~&Z@I3v7jpSFt^DfX^%Sf2U|tGd}|WeijINX#%;1lDxE`RtI4{o*?>A)5LJB0 zTp<0vPR;$ZZNl%thY#>~;A6_(4?b&!p9-l>*L~3>NzJTs-zv4qvei=gwqKLL?Y~py zG)c{*8mp|4)cvc(xCMlaDw(wbiHJnR3SIMLZql6cr1~+WtK{AfiKUXbf7jJYY9A)yT(;TI-&AN{w*1#4f%bpp;RG@t;wJBjg)IV$;rIf#mPe(%-LLb>}~$Ue|FO zWn4G-d8Hj(yMx2uG3$pi*Btc%Y=wE|q8HSt>M*J#vCwg`I6&`1BYdP3uLnwWxbv|n zRW%WtFKYS@cBvfg{DC(>#OPCx?tZ}P5-;pwaYzkp?8tXSFR-o}3s&YD<~Ri9WJcr* z=WkatjyxN!vI46LzE}^J6cQgu^w4UNnFd1cPcN#@9j8$NFYzB`1F`DLyK+RKOJapL z1~00D4!!I})#cn`5P;GULd^y|;#Z?+{fYio^0Dm-ZHIbbzmz*b5D`8koy{sgh(~L2 z1maewaH{}rkS$%KI*yqyN{)**U@CF^2Pu0I0H7rDJCwq1l`~k?l7Kh^A5NG8l&yZuHur0DoHd#hi z^!$g-Z!d+xXtq(<5%y$#Y(Hcza<)IB289}EQv+grXURKEx+m`^cUon(2pS-Mkwi6=`dJH?5zrh*k zXO0SBTi16j!UbCIr;V*eWEj7i3tmxwJP1S4WA`xz#STS`0;nSb0LSjf%J@x~7i)dk z{o*e$zrLcnUK;Wp!YQ zR$ypjpgn4)tyAren&g&*g=tH13FG0w@hm zOmsyRC~^meYfy}=VF7th=f1-{{kr14NSG;VAu|Zu3Ra1V#;helt3p;9-l^UeBw$RZ z5-jOulc3$9#%t+PUt>c1FuWI|*dkk=XQ5ZuLTGdNr1EC~#?E}m9WhBcp`@~8#Ng)H zER3V|(pe}o872!e3$4ZuX+E%K3R$0@?sw9sIt4V_LV|gK4$i2Itqb`aher?$DkIxL zFoj=I)k)}bSgVbs=6n?9;sF=7J>YQKbWA6ITKZ?ylWx@iswabk5ru6*bMSG-46Af( z%Q60<6fB~E|I_WLZqg7g0fj{wh8F$=VNoV}qiKa^;82_>C07_MV6wYPx*rDTO_s{PC&sJy_~_GfOKHFES#Yc59OJQX`fDEczB1f)9dG)?iFQ z+Mv1Q0}-fMd@!gW%Qo3|gvcA|r;N=l=qVvzIR1e>ilx{fhwwoz=~eD0gjj%rgn7Q2 z+5~oGJ`#FK>UE^bhL9jv*lofB88bqrT*0EAB{+IEbJW>xLj>4#@J}X)tW?MKX2%PR z5RX`zKQg8}9F!+8&Dn3Ma!OkYR!j`!#b}~K&9*O?*zQFE%Nv+vQZ(hPZF z*O4pmLfIa_9G@=*r%ijh9z#DgWg6=3OJcIJTbk>0L!&Qh6$WP`whpCGi|9kSL;6@W zt3eF(6so&{o>mTS(k0cycGHMV+Oma7fPzHQPbex=bt*qeOY}vcWzYh3!zmNiVMS_) zKsB`q;U7STkl@sgEf)ZTIl*q9k4Or|={^a?CBo=W5fqSYn5jax=1@ZdRWg1BT0jrI z7Bz?L2t@2Ri+XiL2w@apU_W9mYFaRE=RKK^;IE4y#(-(aE2ub^lDZ<)G33ThG6Be) z`VHdXcNtV7C-I)+=xTcF7?S38in$}vc6%$S*q-EEDEOZBfZD|@F&*fv7Zb4((Jg=VF7Inoa&Kea zAa^YAK$z!Yq=i}XuIkoi?|1d=s*#uYM6$v?mwzrm{P5@RA~?9lG`@$Z;}=Y)Evj?w zI--C%9}A-=ZBZw?AK}Ck*X?39Y{4qt$L7l|h;07BbbBB3!N+-Mry29U8tMFIroXSc zT)Y#i8V}vTm5nh(UZTzofuOoVih9Qg3iwTKINVr$brCU|M_7s9d(*|Qn3AkDOT};{>oAse;RXrvtRG;7gYX<+Kh{$&f zw3+KFa4<|}%tk3_=#dLDdSomQsU!AbW%zu0`m-7XgALKM+TWdnsT7?B)T{Jhg^sCm z+`-EH>jTxVI#rrA!P|>=eJ;noxZ;XuupZoJS^gKqojgi%NAHL|f+CDO748DZl4cPi zIhmECfXrIMSrUzx>cuyMEf3KS05@rRHL4OEo_%Da>M`z1Is3{|O{(|z;4m=Ishj(c z!9ZNpL#IxI70uu@ahsrm1ZBt!_tp^JR2&J?q_23>kT-65b#Vk$(NRo^QJOxe3V))YuT=w%e)hic8 zu+ad$>zV!^s?mt@{pW|OKaSdY_(Ke}_2#P&)xd$mw%Oool+RtQH@Im?@bWL6c43RsjJGAa29P5;WVB zD+VvjEpn;o9AK$*Cfj$BZNiHQ-`_gMNaljJ-7$0>Ppq#A}c; zZ%}Wh`bG;W#0m8y+A-2Wgym5-Avmu$i$7Hr)eA%VV>HMo4APmA(-3>EDGj3%;_FQJ zZkFvPZu&+Z5F1?)t~94Ne_NGDybQ8|yPIW0I^P}oW6YS(RBl|>CMTG4KT};odta`J zM%~ySG3ztcv%R<#fg7&ZMyE&Z10#dC;P!0%OkIrObL1{{2_BE_g8X>b?A)bzqjK}z z*nzOY^xdtVLgMb->U!*ixa@OP)^aPv1SUhS=VHQ;qp!^T&(+gTqdDgbRn}<-F76#a z(2f18DmiH(!Z>&omz-3U2pn_+-Ay0XE%-v+>Ja`O)k==k#2KG-U_1VY=Hxx9XY&u? za0K%M>yg-_#TAO_dsOf0PZT!K%9tDpCghm(Z$MwrjhF z3VK?5;$zyKP$=Ph$FF48V3a49eryi=TD{#Cn19;c=}ci!gYeZZz`YA=TVHq3H`smy z?WobwNps7$>Nxy9-o@`9?Qf)yH4DB|Ei%#%HZ8xG1o?P_{T&rLxMgW@!`vHx%(?^( z`1Z*kXW}++0Y9$!+bhbC^ZysNb7LVBBwNEV7UJQC(*79&1W|N`F4?C;9x)PwCHp`#Jr2@z3)43P+DK z7yP1p3u2uA$r}siLB}WxHomlY5HUu3uC-XDs_F4t8crIEai;CQ2+mkDabG%58kKP~ zuhwBzV_UWg-rw^2iy%bnVA`h}KgSNgkPvCy!YcVl<1x;3S1BmQD4pt)5Sgx8r*QpR zr#}OaN^`cSJE1){c#`KU`#3i)jRZA{%-3;!2I@N|OENr_r9UgQ3kkT&l~aM0QTLlC zvUM-qvhzu{Ziid7y&T<11b~%cPz!b3aGgpQ!*uPnO6I5>jCv2%40$t(O6i|7ZP=JH3-_6xMhuD=Gn>kGu zqB5y~lSaLbcb7_RB5f5$DUL|!XuI=H7~fD5Q6pw(dK9hv4pt!up9ggDH9#x;S_H{d z)m-=QvfRKf*)j_=fc8~Ty#glzkt#DP{^A=#;iY&Ph{8>^v!OL4aVzO&(qwkRyqnN@ z1Lkn*Axkk4Sfmf;pap=A@Gwc;LtVo2@8nvD@@q_So*r|qZ9Q~>6q**2FNY^MREfK( zngYhaOJjs8P~5}z%@!Ir7DO~=^^8Uc>LI8}1+y+smkdoU({T-L5tM}}j+693W_VTi z1Bp#qwtR&o^`hhfio0DZ1fk?*vJ9wN z=mzMK0J%d404P9zO4vjd7LwF3jaAsvk`tu?g)6M)v1Yn_yzLThG{bNXfyV82cj5%k z9>)QrqwoOSI4_fCm)eme!$Q8N5W>c?2ojh5z+V;aw{Z-Bpg))KDa@7D zpSUKuhk6_k#tbAKJH0@cgmP%JbU7iwH5DynVkpB+#$98X%->R&zc6BcWMKx&{Dl$o z!=r+_@C{^?;=Jme%)bZ?PPQDZ)&e=?Slfy^teklPJ!6Inpo)OQXPdy+MO~UOU2RrI ztX>(m9|t&liv3}(^>qoBDrfup)ao!oSx504U?Ri|LgkUOGZdok=wz_CNlY0c`-BaM ztHx)V2LaCBLNA4GsCvA_;cW+N!HmWWeg4)jL}$PFm};T%=AehFZF&y0dP#2(Z(M$u z9pSx9rsrM0Vh0Z(HxIv3^+$4C%0jeaJHHJRW&TOw=}=3h2>1;`(bmOIB~}T>VIsbv z5jjvIs**7@I*L}E2EhWKLijC4QN5g48LSe$c209!yITb z3&YNl1pl6DL>2>oan*5Xz$j;wC}#=4puY-_{A3Hs4wt3C8?YqAm)DX$2WU zqa3eUNjPX2C7KS%;Cjduw@ktyb9JX_a4Hyps%hm^RCIbhX z8KV?3>SoT|lV(9?2z7`fXULsaZqlZnZN|66T(QC2+EV1tvX=U=W(+l@A0!M|RE7HF z){7ATPE4$$lMWA#zxC#_Lfxa%;)S&rSjmH23=7J8ScIP3D9p~{SOxM7B!qQ^qw4MG z-B_sGG6aLIr1@a8(cKcW;JqRpw3;8*Z37~tZVs8TMcT&VP=m2mUo17Fv2w~~CYzvQ zbSNvf6oW{+L|h}RI0Tu2h-9*O$Rq)yA*hvL*!Ix>lTOv^cfGjqo0q>D{`42Isukbf zw`%R8$!l|P`9;E)?+_3QC+73^Yc2tzz?+{;U9$GwuQ#`>`uEHCJ^tHkKi|kZ8-rH* znE&U~f6dlbaG$I*$=156<+_}N93uzO;DCDiYJZ*iD?Z@+s@72dHkcM|^eK2;+(uWN z@Dc1M&>N#=`Tn7%mkk1&s__74*ig~)N?(AN#%=Wf=Xf*&q@}WuF5DN#3pG!jXF(h18fdB=> zc|bx-u3W4LOTBPJVgn)z0;G>+aXbpko7oaKW9{aE5*!(VDNfs97&6WeDa(Rf&}MG2 z&V{FZVX^M()+qB%vA)RJW`Yvkvn`r{j0>D(4Bl=U>mN9fAca+ne)B(GQ=PZ6oy&#w*u{VjIxN<$9Ev zTCTIv`=_+i-Ox?d?eqj-s@sEsHkeWE^)9^i@1O_cvW@W_bjMD$n8wN|Waus8{BQLc zJIAiFV#X}%p#Oma-EndOVjZbfH6S+~O|#8{r0#eo5(5CCz6l9F$gM@^;4*nMqo-Bf zs%qdgUd8E(+Ly%RNsJ3mll5mqSa(wm?wEW^?UA${Q9rawj80Qlrdyp&v4)<*JmOr^ zF9zcrpty0^A`4_t1duQ(rePtHI5m5~*LewP42&mRKZ|%+pvbX`8D+X-^I8S(DIF!C zG8XhAGB=LYN1A6#_2ChHk7|d$-(Y5!>y9mdgM0>805g|m;3C{$UN6^Ocxg#FY_&z^ z;f}haIi#a*)#9g&ynSuf3p+v<&o{SrME}oc)@( zV+R4Mp7SFyxI3VPyp}S2eO1LcsRWGaP35 zMJL@UJ5rELac4aX?OoPc|H=8cDe0mIfu1LJ(S57`&1Ujc1Lz4DbeP2O@QJx)mdY@| zl8s|Lh86LWxsz>eMU=T9R20BRn5M#<7>eNxDNbNpJeG<$=*sGPVzB-!luJUu*k6UX zE5`of{*IqbMOU4qGK!&td&j`7)Ez_ABQ>B!27T*MT~06{v|?aCl($T2QX$dH(`rh3 z$uHbAu?XM`Q{Y04=3I=!oMcPe9w1<=4;xB-z_u=tEDV2XEG~#gUOE~0hPo7qNo~RA z7iPexUzF)ufu8xwq_EfXf||HwiPX26o4707z2VZyFX#bC#AqDk zmSHU=m}JdUGqJnA7xJP@4}FO<(cInx5*pTQ4-ATlq{>bx&47+&7}|d#b8Leth`D}3 zwBU-ta}Q`EL!#7{NLt#&lLb`OT<%=Ll$_7ZWc~Wk;efRvaQ;m)bfZ!5fXb_uK}55FwTCp|xPo;6BX-r-03v1sxKwz8 z76E-Kr~+!1V80VdU>y6hmO&a^hqKuiHKPz0FxgD;sP$MR8+_DIjg&Y)Xp3-GSj^g+ zQPxQ?$HBg3Zfnq@@}+eB4&VWbmwZK6` zb3%Q7lQ4)0NY8e#+a|-(!XH`T4c5Zv6!Co;6K0~(>pgbkMkrh3uKA_C@ydD8FzF3Ly4o3ehrX+A&~L;dPG01|xBR}df3 z#J?A0-JF>~dXtsKnY0%o0!{`nMp%HnA?}7nn1a#@2gM!=@FAWRYVu9KM#Ui)tLxovJ$2C+Yn} zZ6P2yeL24)2PK#6x5wxZtyHmTX|sZ&TS!3n5n~`DQgSRoW#vb9HV6S>6nlw_@!OKdhR*H){;u*`yjU zYvdb=LyiL#k-ZOR$X*;}m+odd^g?tggh0s@F0xMt!+_AKS#XwtM=;$US*FOuH;iH9 z7$T_B2v%wv(kg%mNoBSU(yfkypE|68LXS1D>(Gj@77C+u4U|w3vKd@QyKjmaK3JEO zS)n~mrlyFh(kj3K8~Bfye;?<><0MdFv!w| zN)03nrDw*D@Tf-#Stv-!%PGTl9&+1cO6Rm$7)y?}ObY=D+m#Sk@e$ zfHXc?D+S(=)V$%+H7T#-%UfB(=MR(Rgl@z1D4bw&`7m9C$HZZ}L&(ATRt?5>Zm3`> z%Lu9#;QYOANA~yM?qMdEJkMFL46f;Y?f9HHOwGDQh$4#g*Tw+GhpLBdWo3%3E*+v~0nF-Dk;F))rs7V}>2)Stph%_e6a9LX} zpTA26iF6ZwY>E#sO;?$)NP{DrW{MypIy1$S0+5SAsg&x1^zW9bLDUoyNKE2W@S^wf zB2|xO;_vjGY#?ivt^-C{R7I2@3>+mPo-fbxSpy6d$q;>_ghhXV?W2^aJO*f#q>@Gd zrPIRUQj{Jjp=*H$a-`cYA$J&o`_~@T)nsV4_%C&Zj9r-S-l#YvT2vW$mF(F%?HK@* z;z|f}_egkA-ZlRjsqYNEw~1Q!QcBQThOgBlz}cB;;I%s5`P!UVrB6qk=|fezZwsCr zO%IkXmq)fgqwe!6eXi5z9V^KZ=DIT{aB1K<{(G=N%HnVZiq{r9Pg+o0g}&%-G1nfZ z2NvQytvL7SW3&aZi4ok3%GVsGFL2&5-490y&K7gT;reo*_{8CGQsC69!*$2w-ov~j zz_7JsHrG-j(grmx$BQOU5fz$0(ja-KE`-)`@(?7@_4Pc$>-voNezZO|K_Q)wqxBqr zm3e-&J}gXtsfC2*N9chqn8We!v`p&Iw?|L?{Rln0N>0EhP^#P(dlZ0MQL^Sj zYeIb`Ru5#;@R3H!Q<%@dCeqj+0Iuhop`yWs4Y<0{EX?^4p#UFyf|JxKg%^S&bq`FL z*y0MjWVUwvH?5ljVV;=PSQ0)*|5;9(HJvyeI^jzT!iSbbcSh7p@N3wgkg-(n5D^Ns zJM6-2?wEsej)q7|8HNXhtPwAHkf-ueU&`5A0)wf> zMGO*&+uC;H;T=uMB%qCc&d4Ugyhv>y&dSx%44Y~NCmxa9jmVRsKcGDwI92ALAyKsn z2s4=?Ym>~IoAD_J^P>njnfU-TD#K%e1b$5!$Wxt(Ya>!})8aT6OeZqSZYfQJ04n8F z164+S2edR4<@L~FGE@dyHlp3YD@^OHI*nFVXyDhhum>{Kc4Qr}KU$=u4z0kD;@ocw zkWJ50#37$#WCj8YsrfbGX@IK$uIN6CW-uIK}0@Eq*J3iB!c zpm?FTaIP3*Koum1WQ*#N!A-Rgwef*$>i5#HJr&mk}U z3!%ZyZs}Z73?rV*6IwNC&J{^u2NJ$Pz2@wm9wpeGY44H(R%EHv6wJN_4^fg~sAT9q z0)@g4LAYr+;lwC@DijeF&WgB<0Um>h2Lgmkp&7NNn$1aNv#ql`0>M^d__4ASQKa=L zJbxb@n<^3YfM=t&GF5L$v}45atIVQTH6%Z38`Oz`9p|&Wy1GuIEgnfkW z6GA!`n*APjVVIkH8l_P({DA|?;H1L?8=V^9|EtmAR>lJwEfDQm5RXyJXmhj$|M#J? z9QQd&0dAF`R~!9{um*6Gd`nc~cLkt0b~Flak|t75L z(rhUl^_zu-!jf5JJ*H#nFwDUi_)O=;ToJfhn0EpJ?zgaCq1+Nb${ddxoxtR#PfUxGg%#%5%w!=>d(V95owH)_u9t!rtP6(EeD@SPW`| z5)%v6`*Tc(Q=lI`Wrm-kCqhkJbBccCFwvqQl|<%>I7Dp)bh!7jw}YiNcTz{hQ1Yj9 zn_wy`%!R+&+tnd7;1$#7G~Fuqm0S^9NxUC_n(p6`2*Ni9^NAk&&>a35J7cU1X)%K(7M!N79Ltc9a%Iv*r|U6LjaQwnFY34s<{rIKfKCDHzYIkI`5Ye~FqwcU zH<+q3^!e^DznX<-=tHpi^P@8mA+^y|oT>j__98Zz_|NOaMXAkME;dteAsXD391o7E zKU1HJU8iMd=^oC9b;q8i?^kZ4GQ-c)6{hqYY#ZG1wi$Jf?w7UQ^%rV?tGVtReRNI; z*I#JfI7c7lY&Y%B)vq~^n9t7DyP@iDI!_9ooMbXBbEC z)Ybh#KcAibJ`Z%z{`+;;U!q%NqwtKY^l2>o`Bl2I<#sY(hri+C4Ag!lA6rf3)%wip z+ReB=hvr2tBp&ux2I&OKJS=1Em$H-ALaGq+U})}_vRUt+(g545X{ogk8nv5SM73kt z0if!$&<`E|syj793n_cY;}|%$@sz*n7s56w|9z9ZP7mzDEDZIcdXFXJ37gPIkB~9p ztpF_B+GXbdT&Le99Zsv(XM-${RqJE;s%mss=iRyF&d}a|4vDR~7^bvf%E+>=!HzHiMs$UHSXo7|Gfa@Mnj^}( z1-rw9BIY=ztb4F0OlSpmhAg`z_;yp>nbY-Oog9$cWo*btb(?S3J>9$y-9%e-5Xgjk z>HL{`P|iaeo{t3u{x6O>ekP>kOXl{OkeOebhMBsR+t6Tk&eRu-_!_1%TEx|t3b(SH zD5RpEA}WCZrlJX*DsqTv-L?OFKfm=f?l}i<79|Y zh6rK`g!c5ZDZW#m+I+3958SJRJq`9!Iz-xDf2VHS8Zn+=dqj3}%Eqh<;n&wkZ0a)j z4se^=Yj^6>3Q|VdZ4?N&f!>ByQSnAX?WakA7pC1}{JV6oKFsYP$`1RB+~75t zpAg9g0zuKd!#p!bpV2`|ftqNt|@s#0P32a<3A*T2i?-LN|}3>R>k% z7haYpw?gq+!)mBH428iBHe3w-nh0PW2-?3F%2)b(UEbY@sZjT(qL9FQP57tMbY?? zuUY=DuKx=e4A%xiuw$wTR$wyB5=`X}=R2%RCUfNtwdnwQM5--1K$I59DKiIyehwdt zc_qhxQIk(3FB<6figgIGM9)EOpa*qHJQ?8?HhmSyO24X|g3zc`?ew&==a^uwuNBAY zlePM^B-qO`J?IDyY{A1N;93~u{=#-_`OWm3r`sZ`@924maNlZb=IMVXCv6O`rBtKy z;hP9pE%Z)U;TWUbTwFXK3daU>#(dqb3kQJi72At*Li}}_{!xD|Lja}Ua9<#&a!ACv z^L5!^=x(p-JZwc2n4qX@Z+T-Xgn{%ec;+=$3ZB8=JHh|2)qOi(|I?{{l*!~bx)L29 znhwcBzI9MYz7kQ2R{LgG=%CqPy6~SQ`e7fS7*;;xA@#(I!tcs|Rwwg$?Of93U!o2g zH(0CPe7-;raXvM_-mg3B$<*h^+^-8eN&AD9U?SwPx}Iy0du?>CR4qtdPBuPy!fas(FwIVpHiFC2wUyhaJVl5c&eT_QyT& zd(gWVN(+S40o9J+Ei}Zedq8)ps>fOYj$>qxp`AhXRkk0Ja_3$cmd20@vLG0+1&{R}^G5gVpM*td`lVLHP|z->`_9Fet> zpUxe)IU!xh85pf$`r0tPI`zS|1-RIWF@bR@1w2Ha3!vFDp@DlMK&@!sq&B z*nZMrW-Zf;?b_OL5Pwsb>%ZXI$$iW9Fy}vJ*b04w^R}6=LeFtFndC}+Bp%~e>I;#x zVI?-hVAL|U0)qY$x%89b4~ir-SlQx)vYm2#4Fm`i683ai# zy&j_MKc>$+x_#jmDlLVB5XmgGV{CejIqw}kEawI4M{I$){&{`0`>kt6G4EJ5N(rb$A&3FXMU-j&Y2$wY z5N+b+@EyGWp03QO^`I@fqqkin_`@vQ0?Ms4mv7MrW3T?hTXY*N0KT+EkH~!iYikzE zJEpB|)rqa4y#sxo0pFN!eI&`7{L%g=+8p`59tvm!+r&oz+Kcal@+)U;)qEMbRTHBG z#1?RriE6DI;dkp+%!nwk6`_)A%%@xRY1qvbe4qzhgxgOu>qsB6gKn`cK7!3YhC7>L z{%)PRetnnv^?mBs52;^!wP|e7y|N|0 z<0s9Nhr6Yw-$q?_Xi{Kdz+DsJhbPPgrXwd_I*s=$@o2MOT2(5|9Dj4XJU=()xVgj& zUZbRWaii|z?$PGEjk<%AG(~UddcJOYLw9Lzs{}lP#rEr@Y4)Zr9xD{0!GTKspGdAP zcmcf%Kob8)B#@@hI*C?zXE_x2p8(CU8Hm|<3$7rHPk5DFs04WWPnZdB>Obd1nb(+~ zP@(&aHm%;$T?YJW>4aiy9H9n&{gz7Gm-_VtP+5Q{lMZt1C;w}0uG$2~`%saorz}!yboss?N-R99}8t7mw@G&>Ol$v}Byy z25*Y^DiD;3eS*;1Xg}uELF2r^46oD2qV(iCJ+&Vd8%(LpPaQfrn!Bx_7Q;i0F&%X9 z8*-tHI9Cphb--&9+YFCcrQ2UP5ufSfa{Qa{3#j7PBq`$GED1>@+=5>)>G2ERTn<$H zy46dx!05-XU6dH8!-oJ6z7kDkcQ{@V-|m?WtH9_R&6lgNL1>rh@PsaMr+8-26WDq9 zg*o>L-J#_q4_Es-SlN|g*;rZIWo~~$?`;VI?h&)of_E-7umWJJY3 z<}bq&omwu!2rd}^3-i{K`swN!!f#Bc8_WdXxRiYVukTErCw@&GpPxPwPut+?!FJ>9wBu z>SNy>^9dwi`_(z*sslqFhrLF#}Dae_K?k%+0Z2x3QR{FlP142Q8Sl8-2%%^eNG=+^o96e9O!hy z36?+2SI_A-WATZD-u4D396+1qQMYn%FLOHkbdUC?1EtXtAscqGrA9f<-6MY$URoAY zBa^t`9{dU@;L{81b#LG>qh7DU%EFne_1W(2o_S(5)&*|!%=Xp#ie7iXF60I{Vc}BC z!ng$x0ObtKOjYVu&%FA)jH6x8>mhw^XPa@HKK@h3VzzYYfO27D__tYNS&kO914-tj z7Z7>7(Oma}F0Lm0pv8DDXYEH7e#jf2=;Lre-!9`GzC?^+*|l!_j6)k~uQP8U2{zqJ zga;r~h}cX>>&K}G9y-ULlS*C&Lo(SFx2_KmLPlUj0-?w-ZmSKUVq6S=QI{Mv%{E6k zh}?#3GeS3b>Ut#dAOMpwVN35alV8*qcVEglt4L9TMdjkm`0D_jLFG~)6lFJiru`b- zvDs~~u0tO`q@g)}4Fa#0o0V&@3bVqzw?@yPGWHVI*S;`QU(%i0Orh`c+ZYde#1FXK zEv<2DI5HJSoMky5m!VL+a@ede>SbMc5-nk8lH$@^C1n1ItTz zPzJ$c(jAo0_?peH+RTH)!1P_Ky~4Q`UWNS(Cnp$~pS$#!W4}<6qaZwy5gXf{Vn0Te zn!DEOUWHBZknxc%pvszlkx`NpjtB}~G^G3$JuvHW!PGbXUeQT&-77j?{kX)urP?E- zHqAhf3FWPPPcsww42m4!qFOST#h1*4w3{r`1*Oa|&8C3{%ts}d$VfhvZ5OllfpDiV zq<|Kp0*pP6K_Xj3B`*8L{R5 zUuF1o`fpzaGe)CJ9k%TL!;$qzV^pBYG?Gpe7(&T(+ETV8#4dyUA^IWtQC&J8%1(sf z2nYRc#~o?^;T*x5S9R&hR4nWmn3OT5(Op(61FT1Fx)sz+x7`?ZsLbc#kO)P!+4HI{ z?)`;hkJ-SsEeaSu5+x~)A<7w*d|@hI(+9N*#U#gPB7q(O-n@VH`qy-O59-K7m#Sw6 zs-B*Cbd#53E-i>B%$C=5vx>Qy=-Wvnocc1S7|4(o>-7+-0LQM!eg{+_NH6sY%%$sf zaofoR6DGl>|2lN=LysMbqKI0%_*S@HvKW8(!C^m3-&mv_ZLPDjDgqg$#T{yrNmQ z1IpQR=Di(yxtadGgm^Cb9?L29=8f<5csvgILAS=^lpmnF)|-F*09WW-V}8&b@_)N^ zHP;G)o>(&3VqW+Gv9+ts&p+rtyC2W38^0H)K0w!<_mlpj^^=a{(aV*pUPk+yX7_ix z2hZ?m`#t8n4Q9yq`gC)%&%>?ZYbe=a)YHtJF54U*UJ2V?FjC%{=c*xK4=y*7lkGIUdS>7c0;VQDd zAF&u&o`ZsKn$vTlw@pT7(4kagyjUAnXwS#x=!G>$BRPOq*OuO@!NSG;c*EQ43g zfZg!6Y%p7Q>smajKgX8w4W`2vV1x$K{CTgXIpYgm)N!4c@L%)FFkW~JHqb0MuOF6*)xX2Cc56&y!=*|#9un`XwhaKHk=eE9X=Fz z&ofhhhL>rF+59v1r9WTy^Uvr~r=hOpuX?4+-g;%9zT}{ny+n8yv%ei4zpJd>Oj8^d z>K>iw5QB>6K-+>@!9~EB-!St`?@*MVc`vN1w`Okh78#T0O$1l9&-Yg2(U|XDNcf|h zd8dNO?rG-z0YM#3fj1O=ad3e*1&?(FUSIcJ&y1_|lBU%6a@%Z1L^*sQv~+{mFlQVe zJb2r@p6j*8X)d4VdN+aR|C;bdf#;u2cq`Dsm*;t1&G7GV7{hAwR}3Mr&AjjQfJ)pb zhh;soY^X4~@LR~b{0_)y(y$Z#Ei_qiP67_^#`X>nyV2~)!H9U)9CM|2nwkCq81ZAX zJ6#O7^!GfrGy_92G&7PIj~$d8ZAt`DJJeQa{K>mH>aODDG}cNh{697`E= zMf*qLq|+0&>(*y}4M79V{S$i2C<%k_QwiLH3xC|vc6pKCerobf_R#?x_GZY65W3Z+ zt|94w|NM5a(I+@sT8}nUJ_1tf>Xv+@6As4ns*mBHTx;A<^gR%e^FD!Ez0SP$i7qjJ z@V)=E{=%bcdysps1qj&;q3&-s$2Iqckq>Td?$u+h`j{48DPHTww}6-dTh_Mp20P!^ zZEgw4=Kk!NFAKd1eEzk_dk$**z*gS1&Ie|BEAKIAp%=IIDx5uLdTX!J-3POvwb#G@ zI)$!;ZxOb$kb_fq%zs5rTypq=!OeMLohbeA3QaM6+ITQfCzx~Ec)bYcHax+NMLI)Ryw+0#cb`>fRVP$F+2anZF<8 zUCkFbN_&~&0bWZSR?&NacT_uSTXdVDxOGqsphpU6^r4yahIk!GrHMnlDj81g%_l>= zp{93lucH~A^xBu)5_dc*IOi((7An*#X~qpbZ|S<@s__DSV*o zlHOVEURT)1s(Qt;Q5KJ!GAvcWFNb-Lp6#kK@1GEN&y;!Hi#O1Li|u!WGKt-Y$rqQa zl=xp8r`&rbxfe?~gWO~i=Qj>^E07o4fUTFF0C6eeXXRcGbXTj6-iU-a<-_!IJ9;Ct z=P=@-4`lYDj@~)xw}MWXjMkacJ9*XF+x8(#8)W&Qlh+gDD6g|OK6@R@6(RAu&S06Z z&EuWDQ?tLr$tpn?Bo=n@&P{IqzaciGi}xqzG4op&Z$Rnf8&{(hbSdHyV|YZ$pFP7I z*VU`U+U8ANy+PSKSVwczv8Jnc8e~hm3a=xO3M#yd@K{{o-3Y?<>4pjAR&zo(uWQ8{ z6Eh)0qC6|yNF%N{s{0D{vER0t+HPKP$wS&{9V!DJ!t6XMOEj`wM5Mgf&U?kdpu4Su zcSM_U2Pj37>o)U7H*d80wv9L1nQabk>mBDzF}Jq$`a!%r)7EQ^$A8*-RV^lQ&kk2? z_ybFi{;Q^2vDY{EeV0q+a67zj&M!tICe__o?6q?c3w~b-g!N5kYl%0~dDwI)^?D>9 z#yP2wM;K9^g6tzPZBGZV0A>dwgo12<9AD~{AoIjhZ$Qx_xtK3TLWkpLiSL2?+iWQH z+WGh-sZufzslSwZ6P!oQ_3gZhqVt+IR9g9r+10^o3(@2yy@QN9#On#qo~(|z&;&rS z!LDiD-D_XWaYDw;jz-A>SBbCa4&n8X`4sS+_f4XQS6uqUO;Mjim5`%k;W4*0?=wLUuT|N8 z^5pjY$MhNC6`7g=-T?E5AzlY>ujfN> zTr@N#IMxpJhBk-e+X<#(=?A^C(oOsjuIF6W(~FyAPp{0K9oB=CtN9}Jl=bp1rx?1U zR|?vy6p>Av3)XKEp$<`g;BIzm$+7(GcL~uIlUc%umu|#uUaGn``=d71i)A zCn&hsDb2JKa~$}ST>qLppO3vdPrNx0%hzDufF4ze)IB<{8NWW|_wTiH4-%$`#yGasU_$kERzdKGZ zge2l8Tn@^=CoU2K^}&&#a9r(O{k(2CBKpOCUY|08W4(i9FEpW6(rre=T^1ygCcnSe z`;4L(lERuX6F|M9ZqqJ zu=Rb|-|tmaelA*wz03lu!PuPVe@Xu!G&7uM1^M9uNo=i0ZIYGV!RFphPPVxKznrONUZrS(TPiW>?eWa1J!Jl!(8C*43c&-X1 z#UtB)0CcbpriJFuy}dTj1}66QDop;z-gPi9+O>8E_dB4_gQ-Ffp}S)HE3Zq;pZjBJ*(^e&-Kn`$__3(;&q6Qg9gSybg+e$I+qk%B?Fk9%8MaujWW>8ZF*;zC2h zujc%f&0iFk@POc#2+UmmqL2*o`HNyQ$l)(YH)Z{WE6v{z#duy}9zGP-%wuNIVP0<^ zRSLhs-+|>d|1op*VP3ap=~SexG!Gr-U5;|4hokWu%^`<-f5h8@!@cwH79RywVn@6T z(~JMCh+ZE-14;A7Xs@d1W5Dc?E#+ z<0$AS8_dwr-T*xQGTP(WMl(ixy+yvM5Y#l+^gYT8IJ;eSly_=^G-#Il}ttaoDBq_~)a zxZW4)0z=K}8T^F9?HFyw-)7yhUKhal>R1>A8;o}x-Zq$?$9V^r{F_4IEkw>!X$Vo$ z!GbJK>i<3tb=+X~9Os?Xu}K{syI4grR;)z=tp0es*B!M?KVE9N|9EKO8_dSzp+h&A z-;Vb>mu2I6)z`vh+hpamz2-|Dmzy(M_lCwZ6P+vO(#y&Y!m zNl^UWG-W4)EjF5yPsSv*+&p`-cO(+CPr+QZ+#G)jw2zJEvQxl7%gt@4c*z1*4^NN; zN7JttetZ8EuWxHe)i6-FxfKp!(>k5%4FZ^CF3K)9*PZJ1!Q+ury;lpt|D3L6K|{tf zb}5-Dr^)Df;WWsS<>u4Vyt6n?#P<&kJ%({|;_2SWZKo@{H6illQP+)OF=nIb9mKn! zh@eo*+zLGdfx_u}TGLGg?5>Da+Q^7X;-wm@>{U_r8=GCm-_Dn-n8 z2`+wE`B-PJsEl`aZZUH!H?L;=`#v6BfGHEBhWKnT z#Y5r;IdE+ZiI42F6?0fH0QwNTfegv5aL4%5rOsc(iK$n^`D&nPR-`^^tPAD}`*x%@hfpN+OP^P3C zD6=(gZtE65!FETnIj?)X4NCsAyRcbpcl7)%xU799 zf?E&hRx>n95d804vMrNKip?KK#ajWbko$!t_omQ_Sn}5Y!jk(Ak7qUEvuy_;lsFl5 zg%1#m3D#>Z5+2I*N9MWHy;Bp9hZ={1#<99ZR!?)x8QwZd_>tGd+nIr9dUv|J;=DAi z*nD;-W}@9@;91^msGhH%1!Z=ZNsRSQfqXr0EN06M=7zEOw%U}O?Y)ovh(Dg~jWF}3 zdZjr1`q`;oF*3X}6$;WfCVQIKzLmuHVS=}D{D@?gh)8qrG_TD-2DZfD6DPmgaAJ{B zRpq>R38DN@BX`MRu`x-a0#K{W)PKN5@xA%vA6`4zVL=-P06KA2tt!O~Q&pA#0J|>( z+ugu#&zj@@>2)`!UgP!aZYz}{;vTGOpDw}yz#VepK;2@NUE>wY{a4WZ{AXoa-s1$k z&+;Fm!1$V>OrKuk4e3dkURCJ{m~@~)+H0ev2D>SX5>?B%P9WO9*&aLg`O!hMI^ zY`8^1Jn;qrIl`fUJ|5r(i5L_xk)u#SgQB3^iU#D6BT7(^ps2{9pdfgIpnxKN|LU3D zY(kLdd4FGYnd#~7>h9|5>gww1YD}&N$7@fcKZZ}xh5*64CTO))n9uz(L2IQ>(Q&{| z8%K)^fb|3Pd4bkQeL0F2JObSfbP11QO8<`bJgQBC(zf43?4TT@O%svyC_hq2o1|5P zv2~3}+Dz;55Y>4MbJ`<5sL0YX98M0R97ztv<%ufMjH)oQ^)AB$r>`M5R|Ns^`@ z$uY{rBLK_+Yjth9Vud(wRWrj4!eR;-SXA(3W#!un za&!GG^}h={AjfFmU0?-A>HJ+-)|OC%yP?8fM~m*(veEG4cSGtap@e~u$xWI+5VZCk zeKZgn&2Pv#NUONHz^)$@ENij{Az2CCKM1lJcDDwhv)9odgR~per*-Ock1X_)dmyKr zp>y|Ww|VzU!&ts$1k$Z^u{<3&kaMrV0v!A)A*`*|X~qyOOP#9IZadt4 zsMbM!Qm4s7wN2=ltb4WGcnc_8jRH)*YozhFi$1v*1LqiBH%x05XGISTMX#fRVQ|@> zuhYBb(f5U-VQx7L8$-vb|8VWG1S|7H-95M$Lju3(qHl(4Eh4{@y;A1#xM}Qgi2NN# zXszwk`Me)xrT)i7kB`7;pQcms2(6`E)p_L!*3n-hw7XE%+eT{5?C7HK=odyx>inTR zdR2IIqZ}xE_R>u`T3_`konFn+uI1;M9PELi(DtLWrt$fxd%9ZY3e{>IJv>S~+@M5~ za2XC{vpj?r4m>-E?-eHV%)GW3(G+<$ahkj?strX?;=; zNKB-#(3{~jVcy8|2Kw>I}xDRrKzwbuU9uzaDFQ&Hi9sn9WE z&uGC^jB7kUpNd7q4$68`8=Cniq5?QL7Q?*D?Tt1gm_hRfG%f}K{Ak`#j)rICh~S1Y zUZLwh_#{@7A5mPs#v97(^Fhjhd@LW+>u%~i4fX^G4w{BFF-`?c!*Z^Sewc>csXr;< zDbUK<;?7TLFDlA8I{38KQpI8twq(@-u+enwrpS%V$4+7fKSxhZ*XAOxcLs2>oBGYr zUh!HRzV?>*!n13k)>)ZLlMA6s`;?w9gpTA4eOsv2<+;}VtadGe zw>*nJJVReSs}12!NPuylKe$2Pe-?K_@qcD%PbrzFC3*ILK?%23!A4+R=O&@;~ioj=pt z&ujiPv?CU-l1^}=n>cQ<`jRERLoSMY0XtGN>FO6Se;lRv|8pnpVVFH6FIEMvdK(s2r%yqByi~q&FE} zR`@jdZuLLAc?jS6`EQwf(PY zX6lD>Vask`(p4Na+<_ni1E_?>+5(iadNDe;jCL-@76LS2v2vWPL2+=Rifw~YBf)3! zfYWHiCLuQ;eM>{CXc>!t(AdUHw0k{>$2PW^W_@~TiQEX@xdaL>%#lkppKT}O23#J; zi*VpR3VEBpuCeLQ?$@<82~Wz}HulPiIo%tod4Me*<&ePWt){sHvVLeW}(h z4Q;~)7TP2S-&>aXg&%b{^61{B+I676;-%U()z?X=rMw64cX?x2Pas(%xM$5}Fl$*y zOP9&5iH6Iy87f4Rb<4Hd_Ec8RMUO8>&zDlt3LrP1u3n)vw7uggpk$JTSaFarX^!&o(NlpPch!!HJEfpucrH<9nX;#=O-K2Tu$ zR%?ycBLQRrZMuYSNH$(P zvKaH1O&Y?Ck)#11ELBgKi|`&tsUlWnC(exHJgROa1Er@e6u92p_?UX#cq+L)nSX4 zjtlJkStElS3^Y3uJTM;A$+m5iwv=-)ww{t4OzOtp+JY+WrXRLQ4hA#5bgdNh_C9sl z3J&%`@ts?>80KK3wrPWc9IODH?tvGI1KZ?oLQDzN)i%d^mKv9!19#KF60LS>i9{>g z_(3+uZUoa8G9&A}5^aIB*V82l!D}Zj4+9f{+=WZT%3uetrMCu^MdDM0odowJA&G&1 zeMXRj@gd+iq`?7k9M)lv)l1*khTzHvh}P_>hrgtKfca%N_51*Ru$%7xAjH0yfSG-j z;5-#~bdl@PEYzOJS%W&YWYLmeIv}Xr8=@|XJ zL%RV>^Zp+K#rrAuL#?GfqB{jgbQaeR8>En>w$iQ-H5^r-z(=6ozx+W$c_UQVV@he za4+cA?mG65GjJ$(9nOApS_NtA+i5u&04b(p0PxT0Tvev41TzDtG1pfCE(`|4l+bC~ z0j)-0p{z@WYE;OVhJ6cevuuoP6H6s9@kUc?*;O=Nv9s2wkTuv^l)(ih8deEmH7IXw zJB4=a*WzwmCtI4Kni3Kg#Ees}sBub!r{+p=wE&j?sbRy;Q0rcrk(wURQUk#{Hor7M z801#6xi(~^v~Xm#>vFZp3groFnw2pnR9Kwd4tYk5k-U!ff2q|<4>mZ3n_;3EOi7_u zhov_6Yl#i4M(`bZGIcn;bPd%4wja0ehbCg3Mw7qP5@NX(OocXFO4+S7?kzupVcH+D zE$+p75g6rTynC?1Eyp&W0pRkO4!w$n_fSh$(xiP_qxyW_gXJ(jh{uEvcu_4v)E*>T zoQcO?-$MFfA6C9ADg8@K53kT2Uuw;0{Q=DlJ-xRKm0eHW%CN*-N5jjs<=8NXq4)E> zmg}t8lsm#Jbk=Oj*HyZ8d=C4>t95Hn5U+3Q%!(A4FCbM4Gd1HadASmAs-N4VwGLR& zAQUiROK6O0zE%{56c}F;DibbSu5zk{61oafXVAfna{Vb`KxP{WI{;t`+m3A6DXWLn zNTM+AmgzEyM<$`ApJ-9h;jy&!6D_^o5(~QVI_Co{@N@_BbmI*R5U*aBQtYQ%*CvbY zmSg{9k==5pnpz+ zt;X!tV!iWi=m5E(9Qun^%OWbIz2;xj^64=24&$CXm3fx}0Pe4=%GwY@NA zocS3*sV}rH;2zk@W~(%?Uu!HZpa2h#O*aD?IfQG`h2UbX&5%gOggH961;CC4-{KOimWt!a5Y zujElA#wZ3Xu!e!grf9*zhsgu1<>7-`hwIcz zcXIq^N)#ukHMhMpvH>c@zA6;|@p(wb+GZpxfwv4KlVb+`;m>`Jb{xXVguhGauR~gs z#5oKOwge^~(1EbK@?7fl7370$l=GEVJ>u{>24+mA8DDA1fx~YjB#g<}LPb+7r3vd! zT-MB0vFI zR69@e`$6k5Ekh6qxj%nRGoRq4- zES4vna-|Gsh(4ee-UW=`WL#s!opwql&$o3Vrnzwj`%|>>m{y%-daPRLz3;RsP>*#z zuJywD7asAj=x8UEm(a!W8xgk;q@2S5MYrEB?8i5`4WSFk#xlg z>=W#!4^E(EC3OA-*a#LX-$QlrK0W`vG^sl9y_OEwd+^%N`B}%s`6Fb0Rv4JE9hDc^ z7g{c+bgaQ;6{Fe=%@|^XLzlfUz+8LF=z_oIhy!*IF%56ze9-|!4*&}D!ImGZ%q=^Tz=i1ag^1Hn{y8;~{1F#jo~+}|-o zme5!njKN50epXBORaFd>Cm1TK94auDJNS!6SkU99>MUBn)M-%3uUeP(zq*wOwqaO> zqjySO9xObpw8j*46-HJ zj1NDb|IYbS=Qkh3wST$XuEPg@IPlG?c}3sh!$Zi3Jzgwt*jN?rJxclJwsY)K2%05M z{o1sbFBTOZ`*EzDd)9kpYo6V+tMC(<8;938i{h`tMusd)FdLySPQohfB>i|2GS*iV zdrE73M^#lvX5a(X#$X-Bhq`R2HBn+KD!aU-@=65x2Rz^zzkrp1W8sAeM#vGU;>dpM%qwe4mrO5(qhOn)DDSl9jbQeQPao0p(^|cNO>9xD zMtaEw+ehn&hJPQQxv|h9yB$6T=Ucb~@6DdF{grnv?)>YCQM?(TW`|m1O%>@Q%L|uZ zvdgQ*%YPJ-;mpc}8vvEAKLaJ(DthV+H2PoB;xk(P##MDHx)3#Wf(%&N0QeNk|{ zCYO_Ib~!2ke;KeF!Ut@ZD$5C>mnn1`%anfX4xxVRY{1ZQAn~pv+wA<=C>qC4-WgOL^fz?t&9`A^yT+^1tOwIE)u$ zNGHPE*SgBORcIfNzzU5#Vzp|0!TNole7y3ve;nDXzu%VsZdu`)t#D{1TQ%w+^9t;C z@bD;av&AyYi@aQ`Y-vj7E@x?0?hwb|%wf&i8{VvzRaUM-vvzW`c9i!Wt&LS1sUPcf zELLp@<4VI&8`8Cjst=ZF(dV^3x0Ojw1pNtwWaATET3TYYGsQZ}j<-+cH)EM)e})fj zgK2QaL%y=w@m03=MdYebvR`TSd2Q%`fA`hZBM7V9xz~#!2|gdwuR*W8%o4NYWlb4rHg-I)B5rW_F>tq zU(}jZTOTP`s`eaYV`T$feGvpYgL3%sE=|9vHB5bG2TBG9!A2-B7w2?f0}2y73=Vc* z)as?Z8??NQW=;fn_}|B;vit=Ui?f)@#^UDxXeElWanA2Betm{g6yeL<5E)8~42k|{ ztwQh~EQCwY{czN3?WQqgV?Eukh-cMTBdwE~S*n=80eSH0TNQ%JB0k)PJ$9I4V+({9 zCaQIC6?Pk^*wT1L1m;{8*KA897Zm!&Oc)V(v1x2wY{l05P`erF`#1YG|Fc)AW9|~jRUAk8jccY~rXyQNdw#P86-z-mF z*pKTcgdaxXg+jD#{=;)T&;S~%m@|0CDh2_z$dAennI%JD0NcR%h$A}ryNN_Mj<#Wv zG``WPmJSogEfLZHb6*6i`zHMrAsXS)z>TeK*!sFfQ#PoUN>;^R%`&K#(B7o^ZqdBy zrbv6;6ybF+D>P9!yb(T+gI@NjMyvd2wwVrDUw4fZ87O6Rq_jny6$xY5J+$5m9YLJB zZym*T6tyr#G>SsKR#4w4Xvz=op~5K9CH*Ui_eL6itFavu^w#~;S|B5XDZ{3MsCKkk zh-w|?&t@$7U*iYs|ADM!c*n{yh^%NSO94&BIYl0XXUbNL<22SIdJN3twIVNnka5*a zYpuu{4HL^RUP~5mJl{)+_(gcyh(uEk9 zO3$Tgv0`*!{Q{)3m(}ym!8DxY$gJ`t%Oqx~eVnKpAO8I(q=CcFv2miMXH{^&!0F$- zhgQUiRtfK0!~|fa5c!PPq2;49aiZC+vr!}zES6AV)j}e_e3%Ff6L=f6eVqQPM~#F| zC(I5KvFwwxN)Mv~Zb4OlbMnWFTGbCTHbhlLQRjH!t6swK?keNUyrOpVM4JkhS#a`! z33QPIlLlUj_#b;XNE|Iy$(115E6b=$g6N&F&01#T{G#7$Z91K!=Mm8v5jMJ`0iSh) zI~i1re?LF?0GkVAkl#;QALO7sgLeZ(n2GQ(x`qZOiW{&JU6UxfD7kbxQ8a_wTDh)g z0iLn5j9Mmvx#rV7Nun=2zOGIZ0~+nJF4^%x zB++((86`&US2ct${RtW2f0`cXe5D~V@7fW2& zL^(A@-!^&NdEg!)ImF&t^_D3HCP8@%&BgOqDb;J&3Hl3{_x>WxN{Dcn|$*m)~)g%{{4mh#uS66gR zz3lRv_Dm7=sI0E2AF!9u*sHYNUE|Gmca1k|35^$f35_><35_><35_><35_>v3C)Z3 zf(W_%#y1NHn|ytPDLLCK4>cKuGCsgbLyP`rBjln#U7fA?uvke~=iv?-aG`XyKmprW zEMG@iQTG{^bAjQASSceOvLYrLmLr1+h*&Bk@@#1Na4sr8u=duN&+GmM=(dr@uL`bk z4)gfQUMASZ_$=mW(vdcGnkt%vxxMaRU({0zBWU?4rAxar((izDTmh3ej86IbzO{1* zjsPFny!wz||B=4+? z=!XWPw)RX!R8%$%ZzIyf)~H55k*@CDDVKxou<%pl5;L^w%jNyDnoMyvW2|cB`y6@G zMN$~hRsFI4#C6M9Vpah&e=T5ouK;s?Wtd!1oCuR0UIAv+;5jJ-h)x zYh9uBOREGref{NtZg>|!Yg_^7iYkC+zzfu6=xM_)z=Z$tf2GmYRlrPF*X+6+&~KUW zuT;@BRRWy{Z-}7$luJib$!Q<-3}9aU_r8Y3QAK_vncSj1 zm+O{1-c+bX18)!}rCpD?{1EMVQ5gtiP96u2_~xv#PtwKCS7d)oeo47TJtS!NOG>7G z?gOhoJVnY>WzVd*z1$rO_b6B4ab%BD7ZAJ)mCgv=y^sOnHYcST9>3g(t}3SY7NR?B zg9WQQG;{|R^2XPKPA*hhvwi!do0Q=&2Y=>eCA*rPw!Awy?QZIFGtm4s`Cm~+GS-*B zqOhv5>=mUt`l4*FGMvB0-HLVLVVb!}8Sg<~*o$%Qh?rNErs#+HKMwwLTct(sS8*QJ{ZUsnnAr*>W*Z<>6qu>^?UzD0d|3$dN&ulE z528~QAk4i1BKx+>)!<9Ei>tT{py%$mqy{h*GCGRdRUqL6SD;c8{C8dgK;3{#Y#=*T z0paAOy-VL$0pWrreN_RWsO-`@6y9}d9oCj!t`3J;`l!^E?eD%6LcwL3*{V%|P?5#b zkt!gR;c#@-GUS?%0HKD(%%=0Y9x~)*=gnpR4KqusV&0tLuC$pc>BFj2`%9&P3p{T& zy~5Bds0@=Nhdg)LrtagWnzVC}xVZuBcqwn;{UNo~N{-;s)&nchqcy#t(&71pAh3O(!p4hEbg} z3s!*B)sbFo!#7i&b;5OB^eC_H4|p{-3z0f3dd&z3!q6y1!5Z3&V_ck{eU?K#qv0TT zbdFayqfh}a&cVVOnjM<+33|5~-6zf16A9Pn2VW%C zX_DC%j)UPtfbWlkT_M%JSEMDyz)z9}IUWjzNYny{Xmh-g)bCy~IeQ2QQZM?=O zvT$`EP71`pk^ufdM#1(Fst@3vZI58Lgs50pDN3Vy{uF69m351O@#vP0XgG?EkXc}7 z0(WZtV0Osy$QzMkYCRE@c)|se(1dnG89MB%y(y*+T`$@n$w)+#8GYOn(J-k*H=`(g zLY43dejsrOEP|dICR(+G7rHVB#3?7-}V=_bzB;oxRkTNO3ngMK)rh$n0aoyKCE zlBZvXiK{d9wrVb?b!Di_aL@5{1?OE|hG2d$&g(%bI^8#1 z)bntc`J&sZH-chxdU?2L<~pzR|>!`55^YL4rC z?&sn(KW@)tNb+3Ve7y5PeTiIo$0@uu;KrtUBVjmzb8;g^YCwk;lMh?8Rr6r^=Wp&$ zH_JcesyI?FaRYPJNaGFAPC5_{YZF{$%a)ojhqXM}sJ3Yb&eI~v1qGdq=Q)MREnPjM zfcEh`sd(87FgDZBEgsaeZa1zQw5!|&IR9!DW?y#+fyCj%G8R^RJcyjel1OF>ZPj_~ zvyacZ0Rps%uTz5@tYCHOog=1aL^9T3fZS0jaN>#N`6`b`zA)2Evb3~H;r&J)U#O%r7N?`1hb1C!e4lhkr($Xr7_x1+Zv#wv6znyZx<4vf z#vBDkkRP4rbHT*-iAP0WPZ->j4mvbm)C`^?xLmuBR&4k238HfY*suq$OR%p0+=?rv z9MyTR+VDjA_{7CpD4VIz1EO>6J3u*mn1ydru$W?^2e2J0wCE<&X*XdKVQvAX4FC9u+9y3LwKR z7W{hD=pm6+3I03u$U{N+)##&##CYZ9;;SBpz=twNJc8~lqs5Pi`iXqe9!T37syr3K zqMrVK6prnFplTCEHyt7%>RXEjO~jBe>CK5^bm9tL9W*prVG_o*ReX*R9*|m15;Gz` zdjm0zU>nu)r_sUTOdk2ZI%@KLwNM6HP2rAW}W>IC0$f_FGUjY|^T8xUFUPdIL~ zBPE|<-{8Eu;s^^&EGyyFjC;R+Pb?E zF{Txsh0P4U74-uPQftdScXlu<98OzVktCG0e1qm=tMW)KH)xo_GnwpEj1TEho~Rk% zQh3)!?t-kv3)h2%HG2nVcc}GMZQwAh@a-D}aYeVig~O5M8#oAz3hv=>jJ1Q)DqWqx zp@%}dI2;P!!$A<2UdnwO2$a&{%d#g#tvGAnOA@^cW~bq|cV4SQnEIF7J7uRRM)3B| zxBm~jLc85^R|v|zpH3+?a4y9C8x(Qtc(bQD-T0(v8MQTJds@b1^F;fP-O-7>KLkSB ztgusK`TDzyof^y6KV0n9SiYWhv0G#Ldd@}t@5Ha`HgM0oe;N#ZOp5BM`l#(wqG!A*&&DCG+zG=D7Ulx$ zJNBkSj@RY)6HkelYBX)S zs4d>lQCkP<(u(O~a#CAq1MgoO2RX)H8Y?~Ow4-h_gxR1=rgKRgiZw@?G8I?AY{%*4 zp|?)*&Fn%?&%lQ1-}L@`zd)8rpWT-aPq%FxYq&f^9G-%eYofcC`YhkkQD>yYQS9%QVH9ZKvjgIKi}1 zLdy0aDR0P!k{-d_5Cn|ZihyH~ns?{@?jYntbod#O%qN$!V-d+)^LB+N>l9reYTB2; z&Vw%()t_gKv?Mdjc*<%S{M}tsAbP2f>om7O47rhIZq=WUqtv`nj*PZ2=P)zN-4;m~ zGDs->ECXj&YwAE|%Wf>aVX}#0s8J`VZ=vYei!F3E10~TJaIuK~;bU-)wXw4Q7)`$c zI}mGQeQmRSyy8>+d|5jj-a`nK(yHn|45tnew5L$CXlQpfBtFG|LdMHuo!N~6I=tt; z)+n$=RHN)?g*V2cBR+nIV%pLD&x*td3y|54W;~0jYAY>y7JI2xB&-um2sC8ZFK;Rv zWY|dGM&4PXmPLo$I&}j|vFQ`uo`L}A?pbi?`W#K1CDLLU-#lQ^jKl1z=e1dwn?I$a zvqarCZaxee;f;Yz$4+V>x8sh^tNM5ZjA5j^8aOh6*ClE45z`i>0jF;2JR4TN2k4I3 zqDIEA7Ktl9I8g#d)71?M7M_yCOecF4l~p%zfN|k$OnYwHiCoI7^!;qn8a1pnN2Ij0 zD1xU*#rPCNft%?Sj{|jbLP}#P+@CVWI+nBsFb71U@qFL6o$n7jD z)Jy^P6X@U^F-1wCfpf)G5m*JXJ@pw{JXc(=B+#F8Mca5cFITzYjN#l^oVcZIf@k4R z=>dW>WQf4&Si(X4$8Hv!3%Jo7w}0QPKU{r0jGr@eYX2gdf%SmNLj!ApO)nZT_{)0xBwr#Hf8JKl9-X+bmy$qNr|(H zR=eoe7jYM!nx#I5?qQr@6wAJ2Z*EN-^At}UBJKb9%X3PMCMUjXjAw|mI9xB2Huof1 z={QvjRyCxQ)A|XS{tbv&Zb~z1qz1rkM@BHKG%#`h0OaToyh! z9}?+VT0LJhk8fu>muH((&CEP+2fyysqm$|MeDQJsr?_S1e9|YGk86H7*4vdo9*l)Y zA%uadwj4$aF~l=epbGb|q;m_wwn$H^-4y|G(&Hr;HRaCM;c_jgsUV2fa1^)YHIsu`6IfQwVxF9CzJv_Cz znLov%1$dr_MQi?BT;dLg3dpoj=f#a*D6MW-X*B31kr4Rb3%DG74e;xf!w(80+-W#@ zewm)<+EwU!0Vv#Bn~m?MxFXcDeYTG8wZp!Lkp$!jn{FbIs8-d9QbUPY;=AKo`5&l|Wh$wpoYD!5lAs8e`bMM!XJd}$#KaV6AKv2c zY}(}+DU^)oul5`U3xoSu*iZ!LKt9fGgz_+(&j&FiU}A@x8B4xRkZ-xMn91QHIyf}g z%`Q@7QV77yUoz;x8YWyyuFY=qZ1y`H?AY&w-_xtSoy=r!yxHB`Hae-CbVB8WZZ1=2 zC`qH`%x)3OtT1A6gId}Ek>*v@Vv$I^;WEqski&TamxPH<^J{=CFWI>iGAJetaNvIg z%%&>x${ql&h-S9E|93QRv*)@Xj)CF?Y<5_qs(WZq%0Z4+NeV{a%0UY3BX@=h?8`m} z_9HNlhOlql9%QvPdi|z(kQCdf`(n*5 z6>;!i)xw2ZNN?v>ErM_vEQGr&f^CS_SJ^rZaHVw59j#%I9HXmW6MWz6_}4_e1|9sO zV&i-faAAt_HplXao|@-t@9i92joy1rWWvwfS>(Z^=3-GVt-xl zpgR|f)ba!|mnJAgfEr<6_xfUUp@5-qV-I4A2v7Qkwu6 zsd;UPR)Q32^19Eg7p`gu(IiNL>$L$`%8T{GF}iszuu(5u+whECcyLa?JYoa#AeqE~ zlm!{H%zqgxWw9agA2d@L=D%Szh}3eB%v>eNC?1Wb6WdVS*Unn`vEI)70;bTxAIW=H z-g>49`fKOC7UFl{b9>vz*n-0``t5bmPVeB4 z!azu%7H{C>*9^Mp4N-YvS=j)B+{R20l{|7auQ+`P^JD4}|O9wO4ypdlrv0K=JUp%JYyn$c**g1z6 z$uz7uv(5hel3j5g3H1k%BU{}aLV{G#RG6Wi)(nmHAg-O{F=n$`9n1QTC>Ja@d@8^t z2+OcHvI%aA#f@1V%$vDnu4YGm$&@$E!S2`t?|m$}KGeg*^MJb6!%Hsz<|s?mwic&@ zqz34!<>H!nOX;!%USs%zS$P}4g5{!Cea!RzA~)+Pt;=2zTocL5$D;DFYqq5$%SErj zpcYoRdE;4sgrDLpU-!e8R1cq!?PO|jo1D~G7gN)ca^ zD~gee{OC8>1MoXqvN@L3Aawmo(I5qKA1FW4nx8?aPUD~k+X^=ot^_I8fxB0B!{#$` zOjl1&9TcXZscZ%zY0V8cwFmZ%z5TLf+hMu#b2f3On)ljAv1$}#9k z>@c@A4ghIzFpb_|!x5;M2KW>fRZImimY{;DP198njq8~TBin#4e0j}9X(T(v6~?vP zhElr?Wsxic%Qi(AU%&^hl_?b@!)6&#Tszp6^z+m+`5W4nnghqz2;%xtyKN>inW?g6 zQFhC)Ur^5!GBej9$%0^*BFAT#NdRNp7Sy9(R-yYXT7`lW8|ubBDSsIjjuW|i&14HZ z*m#G9Mi4u2Ss??!P8^1c$M_Pvs2Iu$NB|QjhKoU zH9E*2q=H)E!qsP1!?d`Lg$0*Cs-LG0ZC)+9HDbhDa~5}mRh*oc7|KqJa3=mze!8jI zo1#WKC}%B?AB;-SDdV^xQm%h_xJvnMb|m(mPtf=`g)izS;h)SSyQjxTMQ@7kfe4U3 zn<~KY-N(l&cVb&R-hjJoATZiA`lNAnR{{fY1rBGoaO;_a)G`Y$%b2Rc$#aD91j_ZV zl6xK)#=dBzkdvZh9+uu51jFQRND(#V|TC9We_Ro~G zMl^J@Ei4Lx8ok#V(ad#Rpbd|%5oSUJ=ura0ztBa&F5r7wu?F264Z4E`j=UMk=|JpS zaHV8?f;o__$@j0qrzB~N68r>PAdX~`wkMPCfwm@4_)Bf@z9_h7w#`;hX@rtPp;Cl` zCM~K-``;C@pmJuE#t*FPh5+F4#o+D%m;#M`Thw$%gK~6KKZ54GEgCk9_B61#9hz$L zmbPNT8>@kReCWC`#!U<*4s~!i5R9W=-o{~y>eS*L(VUIDnmCTb@C>XGc*4C1&gzyj z2m_E2mj?cZub51^LJS&jASzCrW*SB=#0g&8@uoPYTdTTJzG%1^;|}L}<~Km#NaP0( zm9J?7o7#RPZV2RJf zP5_+NHF4DTMbM^Vk(KZr5Y7Z_#`|l-iVRnpMo`>Z(Mz<=j=33=#NBJr?(gX3wW32! z9>byO3F~aR0~7(~k;~5d&aV|2e%$mTLsEr_3+myY4u)(Yl60Pf+e54Muzh0Z-<(w@ zKF3B=D17ibctY7t&#V);HqgqNoe^zP@jB51)Ov9pHei0H)OST4y%wf_#jHhL--W?{ zG~N5IxY`>Rq7cvv09K$F5NQ(ac~_)%vT4Pa1Zn|{R6AF+S>1k%GiwGRVJJCEBQu?w zqs(Lz8L0kx(TF!{Do!OlPe^twc}h*Xe?2w<-IgaD^nRptLnJ3=_#xu;`2YyMtuRB} z8pU&bxl~y}sB}Z{Y3CgPcGt>m>%G;i>y74BRy%J`d@}H<3wjI!Cogiaq1GGg%j)2( zwZXXjZf_uxmla`pflz`vDEJywpmr2E7Q{8p64yHT*#avJx&+=1+7g$yjv3{xjZsvc z3p0B_^U~Ja-HgZV(#d-j?`GBq%p`zIMFqNHmFdDs|JG2XRQhiA^0s3>YbRwE+t%9$ zz-t0{Ei=yRW63?J1?DJx;!1|p)@%w`xsDOu)~I8BfJp+FRDkSew(IWgB`X^Ttw>jI zCk!-Okq&-nDbk^!hy<)`g^W$2VPuNg2HaO}Uv=9gZoUmu zTqg`#NHtK%n^~DEdp3uopT>CjGhv?z6FK&M>NK-6)f7B%g>oVunVC2g?KC^!qBJ~U zrwDO^T^#Xfv^EFm%qG!daD{!bH6FhGnp?jFZ?DU@`FL9{-!@3n4DQNe^BC5&yg`aC z!ftACOV6P`mfe^+(qYBpsE!>+H|4)4+SJ{LQ`q2>)qy}AduYP&@IIozjDiUNw8EEN65SCrX*19r0jBM;(7k%I=$yfP6P3XX7{z%^H_Oa&uT>fZ$~ny{ zHF*mZ1Usqo7LkQz)?-_+Bg_oS-hRa|!9y{= zpk~`d&G_vyCYnF7(XIn7aPQhCS{XZ#3db(6^NmLh<5OC=O*CLfO&@L(Hz^+$nAkm__k^F3-;}klI~*<^%Dml6U~fF^<4&44>1PkQC!!@qtqD zniBX{jhd$^F>G|VSnb3;hJ9La-2ABUNOb~buaC0oC zMA(|j{H6HL?n`mIC>L`QxjZI2MMW%xYq+hI>2U!Lzl5cnhiM5Cxfv@{LOu&7RWC`p z8A(+nH8`oukNZy08*mKG6~Xa2E{I=bWC3PE7(5&6Wh4-c=DPfA<^0J07GO<|%7aTAiU z_05C&17YARRu>0YVzet;hJ^4CitMtoOAw4kHv$%4>t*LdZ!-W3p)%b$qyv_$bhx6) zf)69!O6iKwV_0u+ItWRAz6aIkNVe!vUWy9Zm)ipzMG3n^gQ!KE)LP?G_g&(YQdFGz zu{h{V`~&F1#yZa;PCqwNF@C23)l@I_`b4}A+gaQp+k|R=DiTsYaPj~GAf(5lRmIYc z$$K|l{VB|hesi-`t{9Ay{mNrxWV@1UZ-$Z(Ltwd=m%7gDEF}O=t~wVRr`_2OT9NHa zr@ucHQMiQ8y;t0ZYhj1%6|1oOn)Df5sG(}$01-Y1ujiys7}LR~t$(=G_<&~LZi!(= zlRg9gIZvBD6OBAbt93WAeC{#Mqte;WAPD_IT|O5#SLeoo`M~fWRrld~`6TW-^zEOt z;&U-C{x3IfSYrzbF!~rX?plwF27Cdw;zW@SC{>wYPqRhuS$IB&b-`I$_JwE<=PGpc z3(+a&g0v{%83u+~C#mT^F1=YdbykC9D!o(9$nqSMneF z=u43n4VD&xxrEgjo9V)rqG_Eo(%=uJ@=$ddzlR0E7L7A*_#sdxibUgmoInPexG$s` zI^Dk?OU>_S`F_zW;sh4>XyQfsd%wg{mjj}<@(K{r~29&ER69H2( z`ivocPEQ{crRp&^{d1MGK0SH}<|Tj9KZnHc#z`1c@P<4yU{r29xxN-{B2W|9bQph= z|7%eV%cKEci^e-I*>OoPUeOQ2+hjC5x2h{Vh_$JlDAzy}$ zw!l8`q#Ng@;jnNAWgii@1sIfynF8LMP9&>Q)-5TA)f}Iw>rk`!Ka(|0SgTkkbAcyF z@Zgvec!$bb(eQz7J|Mxwh>0-=G1d~mgc-z0=%IL(3?|tdO~XTKU-$vq=gGPAH=+?1 zqpVlK91gO^6-56tKycL@EL0p8CF&!+JX7ESaRMxde|^#*X-V~|srB~hX6E0P18QcuHvoVOpE;`C2e`H8a~$d4P{U_peH4cG}N9JV|zBNrAl_|KJtNr1ni z3~+C-Kdm?R90bM}coZMj;BoEdJa&w98;%$UqoIEi2+ni^pR zVIs@otr;CK9_MJBEWxCRtJ|!gH5W4Dox-tfW5t(cS^?CD`E|6B$8jYHqAAEJgPQ?} zQLYqmGF`44uo%S&itUFD(m@L7Olmg5MJSiiu+n6TNk0#^?7Bdu$C;&=&30a>1faXV@2SNRsIOcOncwSI&2ubOQ)A6twS@D2UQ#!`4-iOz^H&ZCOZxS}f1XhS_`s@dpEAE<|s?=rD`j0MntaMzu27Ch3F z5JA?Aa)g-ZBmkZk83Zn;`ip)&CcFWQ?SlUSF5hnV_a#L!<%B>(Aglz*VK4}uT6NQU zw>noruVAu8-s!*i4NuC+$^n&di6&f$60mZz@D^p95!%LsqZgr3Azv&v-5O z#%Dtvgv#m6S)qfBXrnqNf@S`E9L7ShuH+nCH7^Srz>XQ$g|l--Rqm=BAPUvP1o9Ua zMUE(5x}yXfZ-Uf^c{xUPtC%%-2HxRB3Gj{#x`y#22pX@v?+Ios9Zm65W}b~UaGJn8 zRSs9(_yIPbe9RA>#&y7=a3^{Q_eg*q@WgRH)XC~Gj2_7)WS`8&SJ>FA#xu-~z(+9_ z+0@u+K#vKUU`X8842j1HLqg4LNPNGq+bHBQ%RPW0!`Z>_C5>; zj4}5~*Nj)HDZmG7YdjlPLvE!1Q*bLh{>D&->@%{7rK!VIfx2@+R_&|812!lej*gB! zsEce#s0{ENW?~A+4QvR1xIUF@&dJyTYN?8$0)(wqcvA8Q7NOM|=5ocb=6K=fFA^I( z%Uf??5)2M8%;+qx7wihn;;$CZlZ8l*&s_q_M@h3)u1hv+{}c4MVw9ta4iWC z2F!RuiYy<_a;$*sMV8Z_Q+5qggKQ!*Wab%6H&qqOSdlXcBL=xJqobesgl53`U(gbZ zb`th7?j+FY61&$I;VEJB?n-1iiP{v7j>ja$L>L5cN#z3N5W>bwaIOd+FSam;QCmLU z`EYDhTK80#@Z_jQr>?;buACevlYLI;7@===a+iXE`_}?>anQX$62Ydjim1>aLJ$ei z%lOPQj+sten-zp!hqDF@`jidpBvzSWFEo~ z`Gcv%Z+KbzAK{-Ui41!kNXsNDTLY^k8O#d?ag7vW&q%(8msQpb7Yr83;35t(g@6e^ z=ymZ_#3Kx(fUzyNDt*o-j%djzRi2N)_f6L*pNn_9chzXVpW@%aKXaOFgjmm=fM5Srai?*{a3)@&&S!$2pc#VL~AuJDAcn)xxhAWG% z{zX)8?U#!U2lr)Y-6Ks(EtEdhRXz(nNePihspv)Te3puc99g`qe%ud?U-NC|SM6GX+l_*hRp=wX0>r zzEZU?98n|WtXw0AX~xsE;v`BhAma~_Nc&F;Z@n4vZchsh=wRa%6m86pn6Wyo%Krn0 zz^C94cn1wUCGLuxV<8k16C<=5eRT@==Kg?VRibr^xg3Y($dwRiY3wi?Q}5qJ6Q9hc zp{2k(6B@)5Uh<)>c9))^SAG-St;Mg?Ui@DCO*F@WqGqQ>n>H8S+$Fry;S~jczCqug7Fn9)Wz4wgqhCZ6U2{gb zT|5uY>Kj>&#-4%U!4I_gj7W|z$4IdM==(FG@&AYoUgI)08dil3s~t8r7CS9!YEGw4 zizc+|chNBQX*3DL8i&C_!OWr1cDW^YO=B#VVp7L3g2k|8YA=sU00JT3WI*H?~7(Gjmo)w$w{wh@= zkWG1NSF^Avha4(ZIkq7PE|Q`<&xzVeQqp7b6`B=R6EJ~Kqr!7I<9~wQJBJfAuhI|a z#G%&bY_UxaZ#XVskrgA!0F%-9)<^tfqPv-=LC&ZP{QvQ&83QH|XdNwwnuk_j5OoEr=m4q?TmYfZqv*dy&!l`W)&&XlNsuw7D z`GXzDbNe&oy(sEL;tSN92p3Y{i(;%3S!mE7xN_mpMeI(ntZQ9R24S22yeMj@g^~1d zXRSsmk3t;ab>dJr%2OCTPcgWV;M#x0)TUK?A6BC}F&}Yct5bdWCy#Rh$_sN8y;_?W zux)6;lHVeu28CR=OI<|1n55_fY8B!-l95vO zm8&J$ul}QsQ90OL@fXr*MQ@KBO;o)x9=ECbt$3_a^;USCQ1t@kFM8Oi->2^Tgno4D zOVzS`n&;B%sQdD1qf4&~Cn(>z^r4=U=vy|2LC>B$L^o=BJ;Xes>7857k6b><>%j`a z&wJZ$V}7JZtqXo*V`637k3MF1*@Y)ut z1_)4cF|Qd5Xm5nxLV1ydTfZS`0W&uT{*wurf^ml>jdAP4;ummMxe0-(81g%=oIdW> zyEOPrw>`&Ny5MqW4VD`Q`|B5UO{CsSd6_&>dK#^Y)aynU+e=*Z`BFL@3FOJxm#qlv zApcTYAEny|`KwWMwEhV6r%y)f@2I7#=_-$&nf6koG#2BXqX@p`7=&jzj6b@X3he}J zpIK#sZ;_xnAn^8*RA;xvZej>RF13!)+bJ*6=omc(gL5iESxAkoe#~Bp{C+p8B_EoVqlq49>aP>&a;dz#^|YS-{l0*(v~Lx$CC-Ratwxlc?@i{WX$_-(zUUA zN{t1`x{Q_dXPka5Y=(QqgUX9(biCf1qp@)r0qd}pv?X4D19%;kfUTRgG$R2cW-V<= zz-TI_zY_EwIJ%vksJE*C@`*&fUxg1}C+bDYOv+8tYpbZ(!X&++`coYU0vVApD{%-YYl#mOVh^y zwYh0v6G!Q_H2o^|sGwD8dLsRm2A;E(rq|HR5OrrwJzqV%hK|?NuTqW{H>jn*sw%r^ zm#L>lZRbfGTexh6a>~?ittTx?m{~|Y1ExOavMy<8!t)~peFYb@jrHnns(pkx$mxGw z=?C4o6p+Cz0OnmUhWU1K`p}uXDbuIdOg_pwK&+}z&PZ8Sq*Y>$Pk#V4I^xs6(V~y8 zSNl1jJlO1r+ETnb9hKB>Tx2*DI+CF$7SCv;7YoHj-COFdXh};wuT~2OrfvLO__f5Z z6@IN9{v~q&09Q}mH$ZPrkF?V7QBTaJuUhHb)qV45achv{0Q$YP-V8S#)@!5JxpiN( z;i!SEy_@wjhmIRJc3cP3aRJ|=@U72?F+hc?uf6Q@as&kx7BB%?9Q2b2le=i#Sdrdliav^?`)R-EO_u!eto_>vAW@i zN8+33qH)=Jof-uQd5~rSo=!ZA@YL{xJhOyWXX}~bL@^N2 zobk{SS9f^3>chmm^`TGdx%ITQtKL^BqPT8|I=l%{11+qr=!PssbOhfqRC;&UGqISM zjE6Y6RRUGH;%r1_pMoKTedGXHP`Ztm4$!}@Zjrw+geCQ^<6y9n4 zH={}g^!m**H0~A|+JB2)s^|WK+-qGl?N)sYMc%3pu2Gt4IGO?@f8Z(byntr|Jo%4a zAD|DX?A!GMx5IzpH)Q=ThOWO&KS`h5t`{YR_c4=J7yMcmKY54#p5iX;WJr?hP5th| zME1#DdMS;(OCMe@Jp2o*fN`il^5Oj~H|Bh%qB3Jlv`Hy}R{f#oh2K!;y~o z>*?!(!0sqY9;7!)4KMa8#10xYZ0xuZ6NZnbdj>&TIDZx857HY3j`TJhZbWC{$A4U) zAHOX8`0xK39{0e|L8HbG9b}H5FmA+{VHGHyv5<{lYlkDiHY*YZJo5Ob2LGH+MNu67 z!;`l-q71GE|EY`!JRJU)9>;fx?Ed%V3#SaeY@ULs$8Q)tV*Gd%ZQeU#=%^v)K*wgk z;fO_M$q4WqG3LQR?MICmVvZU*X4r(`rsJ@kpaD1qkJup(+&5~(;6W3HhCtwBw&93l zAoScldL5-JZM;WMj_QUl{=tLCJ}_nid57pJ#rk0Vdqugm_|y=+tJIg^Iz4U``A>M*@d5+mrwhwmF2o~b7t8m7-m z3GZ)4a4-CTVC;mC&>Pc3BS2n#N9widnh_w@<0JGeS~CLN5C7D+Vs{VMYf^)e`kmh1 z$QEA0)s@2C=v6>U?Ss$V#*Q8|VodKL;mNO|LnFayuBG!MfuX)sGe=KO?T5tI4IMhJ z_mGOPucK>o^t3kp5qOvS8%79eZj1|;F386=VBeXL!SBM>*i{x)dHka0uDk9XXNZ;ALZ{%^wXz6b6BW!#-J z^kD~Oj?z87Z^p-P9NdEN4PyuA44vQyh+bpIPZ*A$!!ZEgxz`!ct@zzHcHD&Ue7Dhz zQTn|d`aUpv=(rJsE5c;zxM9NBaYL^eF?z&=@q-85H)t@}K!tK|r?}C;{c3758o0lM z`j6IMp|~;nphPAc00=MaPMS6bbJtz8Zj4^*>I!wco9i~{;Zb7;4XKc2Aij4WecyzK zuNyRBc=s_A#yx!F*s<9ohJ}M2MCZqVm)=8z#_DMqXoT$e8^?_pHf-oP?&RwRjl)2g zFmzlU#D%(zmXFoF7@y&Dld((hySu7P`z{DD!UD)6RZ_?Cqq|1qfH_+{b8 ze;gixUlxA+$KjFqW#Pwv9L~Wn3qStj@F@JU@Z&!YkH#+xKl}yc2M}TKgA9+Y6uz%g z`2I@aah1a3D}_NM72rP*3J0tjJsA36h5u72{7|Lv!OerUf{ z;A41Z;m3cBBL1F*AOCSU7r!k0_>aSr@yo)G|2X_Oep&eOABU&lmxUkyaX1gZEd2P7 z!%yIsg&&tAKTO3liv#%M1W)3Zg&+TMI3K?({P>T<)9}l}kN-IQ6nyJW6Up`*14cAP&#_MTG zvykvwjGXX7%2o=mq+(mT56Ad=-zg%(WGZ*Z%38jgkt)}iy0^nUIE2sT16 zllnh~;3_+K4ZZ%Dp5v}|7vxpM4x*X?{RYot2y%1tZZRCmRy8{Y^f<0&hWijAxe_nX zp@2TtbHm++l)m3a+8W%{G>V?A$I#=sdRxyXL^5yKgUH$zps2}c&8b|yqo>J0tHLJ{ z>9bnXcd~x9djY<;MkXAzo2(CWM-4I@EO$4jxX1Nd+z%qiD7=pDe_X%a^BIC%n|lW^ zN?POtU%x!AH#M5wV>s&L`y2Rf;7Qj`(Y>^LvK~pdOhGHAA)fQ)(zGdhPxrTW^5^Nx zDLM>*2U}Hmm%8Wa{UTpMka4+h0KJ%}-yG=}Vs+9_1L$I&ewTYN!aRR#H1r8bb6#5T zgx*oMqQ}s-3(yfNWOADXS>r(nuJr<(={Zqm2H`AP{dIPoWR@yXGzdo|& zy;kdv-b&S<)NeKd2y?gniQGwe(!!}&-hIwwv2-fha(b#>(|rJmcs7ltFQ3%=xZ4b~ zWXlHBBp<1}-WoWtj61YIMToKLlY5T!k(J5}}Q=M*_zZ;*WE3rKYu1JfP; z(tRxbLFk)Dy{2PKXu9^=21%7pzcNfJw{L`P}_Y)8HLX!DU1vv2X?CMCglq0mP zWAmFM)p{8ys8zC|n#2E*479HQdrl39e?JFA?%~Xbx5YX9Kgdwgz9(*Jjf8*7P-)*` zqqn4CRrfTf>|8kT=m4aAjzfCZ^tT_Xxe`mh*Jbd!$p5$ZkFGtD0xI6wz5VeLb`jyg zy)z(|mOA5bBzd7TDqU6gnk9OMtiqh^GSa z5+L3R#0P=+6cFD6;wM1-5r}^SF*_eHp#rfK5Gw<*9uON(zk8HDop%YaZ?zhTw*c|J z>4C@CgPmD?fe96e#ei4}h~8+p`II0%;^6?1lt3Kq%4?G#jNUD%cwWb^|I{u6nPU&_fSAz(ncN zduS%~P?P`xLJ<%t30-MHKsx-tXP({7ZU}nsN8kVN{rKJ}`#dvq=FFKh=bY*1`FUv7 zW5cRuyLiIpfcyZRQD@*f{26sj#~A1I(9!?&k29ve$%j4~i5E)n{^8Z2GZ>i3pwm^< z;g#EXB`fDU88?|3w{pEs?Ws=) z;5yC?oEwc6b&@_N0VV4YrDymLrRj_YlgVhLC}05|`ZcLX^$XQJLoM|eLxnV=(%>c4 zH^AwS8T9hWQ6%asahOmCa6)Gwq6`L;8TpBR`Ns@qL$DHLMvQ?)>&!7GW+qCg`XGWE zfyRhe12Tdwb`C%)-kqCX!75!)utHp9I`v&+ygJDkYS936Ms>9@@+qoE6=OiSQT_#L z56^EvfH8oGCS3T7;Gy2uknKW0;3MHMqFe&SpIX%v7wK&^YEd*Vpol)5I^0y*3JN5( zI(4BbTz%gZppG|HRL7VSD(G}JJ*p!q=dtQRQv~DcCDTO5SL`ch)H7X(sj@zexzf|~ zbhb2|Yu2uH@|nF$U1E-BhgD{Y4tnRk4?p_g(Q{Vo%#^4d~qY^{yXv?fk}juj`qubLY3;=-Q+6t6e{QL(i>?K%|S=vRGv0 z9o8BTw<$2^vY*Vq@bC0n^c(a841*2d8*=z2K9>*H=NOk8R~T0szcsElt}*s89pXRp zIRX332l#RG3G+{UCtqOBH5OVA@+15hKg_dviTOa9dB6FT`6rfbTx49r(|Ip`n`QHb zJclpk%lHDmneX9y`8NGho@bnA&I*`ozGJ>=?!^zAkMkeRXUu2K=gjBLN6kmf#pZ>^ zBJ(%KW9CEVpUo%Dm(7>Vx6Jd+7tN>5znHI^ubFR~v-x1tWy?&<9?LY#e9HmLAZywP z%Qu!ymZ6rNmaCRL%a4{U%N$ED>vqd&OJ8e&Wq|d(CDVGuGSoW3a>MeyWxZvrj*=2Yk#~8vC-E&ZTsVFJ*~<~r3LU`(4RM)3H<8-b&cl4=oBy*qlbeNE) z{KH{(O+^U~rcdVdUm8dK;`Gimt^;6N8`P3Hxxvm-Nd&VKIoffnk zQsZ=w27xpO>Ke#xc5||pJ4o-+ISdqo1h5GY%H9|V^>&?%0AFklu*zEso6dHSF?||UzD%uoszVPrbwbd_`~8^7!Avfh z$;)9TQH%m)4k}ljl-P-dsJ9dM)!Y^kWe>3jyPOKWDfSAkJSJbcy;2kXDLv}IU8nS^ zO4!I+U)Tx842m^qFiE~Shy!MNRmazA6&Oy{wQ4xkbG7#K%$@4y+OI}bLB?L1j9DZT zT?M*SB}9EFX)23VPbIy@wy7QJv|&}%tU50r$T&?-6*3*>#XbJ6DPg z>hACn(Ibow7Fd~N&XB5nV@4p7#FZNqRZWiwO&d;8;qLTd6bRGOks~lQ5h5%hLOq!X zT_praLO6t+AY>U8%gYwxn~n5@sK}&J(4-W2K#^ruC@*u68-6Om2f71OC}7jTQH73? zq2ZE1E28{pQvVeh{g$N6W(2W!JDA>Nw}zYKm< zW4#FhJ_(?tiZ{XLlYpYeM@2+kWP#D%^dO(~q3X7%$Y@XkfpJ$P*e4m;S#(5HFJoYY zH$B8BJzc#oIw2a^AuaCgp+3pT{z3EuY>>JzIw1-)qJ7;^(HayZZVggPq9gesgBlQ1 zpIua2#6(74Gz6Nxunr%LfOxa(CEeP&L z(8-(P?FXo-lSd+dU@E=E!1%!o>Xbd|Lsb?#c3H{BJ5y?R4B}|l5-WgQC7KP;+l@*u zH6peiyREj3?ZP&zvtkooA|t?E8J5&I6y%x|km@lR0UjjB%&Bo!yU7)=SrXSIQ)-;a zZt=iz*G*%p-Re!wg)o_9qMBIsL0Exzs>X(Dr4;d0lmP%Od2H3>mYYGalh1^bI{93K z@}}gCvfV0$*X1Pg(>WE4h?FEp07Tlw8}lVpy8<=RUX2}4TiDxKsQ_j-E1T3|_N0o- zz%N&FH)T2co+UO1EK*v80?CYtDcT; z8?Z&g-3B{Q{|6gB6p)8PP@vMgtLVGp z)TyD3&6F!hsi_u+J`UNf7dC(;sJUUSSxxm$*bC}L`=I+qx`ii(gvU@SJbDtIOr}h; z#u-`#8Dw7@lS+D__HjJIMylH!Ux1tK;~K?KAx2nWhY>w3OLdr$l_VP?+e;lE=cu%j zxzl9=7^JLHcf^tC)vwmDI#L1t)=8zJ{sPU4I7=$gPH@z1c;hBX<%7MlOD5~7tB_(i6$xs$>R&Y3L83T`qc;JS zWV~F32pAE75rZ+xgsM7u7RFCx#_*a?uRo|&YlLBj(5OZu6SUQ+ELVHfsM(kp!(CZu zWzVpLyYdh+mI{`oiA3o-0IP$x=BdhNwXjC_NXn{9(KXTQs0J8qxpAmZJ74T_Q$T?N z0S^T_HBu^2AoZp+)C)ve8CggV(bBKF)2U;XTC9Q0B@ki_P-JL2NX81rH`JA{R!Fp0 z+({5YzJ;jCiIpSPF-tm(eH{zZV;|f!ym| zSzx;ra^I@)OU$WGZu}`bq((Kl28ht6_u;oqQ-8Rxnrd)QscoAj0QS9R1p9V#f*srZ zX+NCTn-lE(S6@;W-XG5nE#7m#g8}Sn3j(gyvOe3kxKm4vVYe;5|3OUFw=I4kr8@!4 zdFXuvq95MFO(Zs9HnroRN@_rxSw;$0QrEPL@hj(W8;zz|waX(-)XcU-*SBqV>H)2G zc{Ea;(k=p6SG2SHG}p_>vFeeXfXaNdzAPo=u2RlES_ba(YPhUjLkI#IG-{+sLL8&i?s-vEDv4q8Y zo?T6uM!!Irj=V64ITyeC;y7Yxz{>V2)tRAimdmC)?ys`0gwdj91IHTKm+ zKO&xdm2k{|H4Rcy=QSxM9bUiB-GJfh*w-t|MyV(>7rvet=0kv8pQz6=bZ8Y+K`s8c zqnF)v)p>6;0J`Eg9winey+u@Xd8@vKWGKYOlhu-!!&Q6Ve+QS=bR*xUs^z|YP12%Q z>%SGQ7Q7QF(MG9v-k~OpNUaSD9!?$QS3O@Axp8%qxVjOa7j@Sd1RUKZj(6MH%jdPX zs=B{{J8@&Hcv>peT7FN?rE}DcONfh+n~V$6cAOrr zuK7F$AO}9L%w$DP>iM4Gs`4c@Z{n8(+DZP7_>wYj_;RL~^Z;1TPtsmQv-cbTJx}Wj zlAlapXvU~QTGoJGl;)WFqPnIRsA;>&P#PM<1x+azOe_VG6( zb23U*Oyi8cA8{tJA8{t3KjC~pVlPp?7)etqsILwr z;xY!xR@*a(kXZ*4;lVBkL)Wo-A+4RmM`uVywGlRH$&Qe}$@!qY6>)xMv*c+>LQH zm>abwD0X zI$NlxzM%?Lm{KaC-%rsbl&tUMsckg{u&6z{hO36@)bLfNQ&V=7za$P5r$@@3*=AGo z+JyQw(}C%pW};>tI)lnuJcF7wVWl_~MOwA~QmX1^-tprgh4kK8aY#7{2N*?TS zSa+d#ZK-K^X;H(xMY$2d^829GN;Sk8f&#SS0k1&>Qly)vVX9+st=O?t7oKJ}(9A>9 zI*w)z+Us~Vb+I#Hq8YuW7BR^jh@~tEHrebUUzq?LYR|=$)xyP=h;Ph+SPzpRQ%W;V zRnISuV8d1OlGwoMrO`9g`b%OX5aG!(qcm-ZI(%8U`uUPZRnE8V@2}=o0tJj)XA!;J9E=>n)84{MA4!JCbaz z;CGfb;%5x%q@@uCEU!e#Vz6=}mxt~u2Fo;&R7?~WkmLfD8Nf1{I+bAwGI$#6Yl)ucG>*O^Bg=ul zYEYlbsg`ifK+RfC`gKETBTH-xbLv*PaW8B)fkyJ_mdxhH=i3~&4UiP@sWNc5<**tGx?@mRIft42$Bq9l7HL4bh0Z!T|QxQuDIOn7bu zC3Igg7pAB3N*X6LS(y+FGfJ~YELzpZqd@Jp@=c`dTsgl3X3l!osnVG5nt z443zDTHz~l&z$j^Necnm3gA>D)<_UF(}?X3Jm(s*0$8}J8BM0mm`n$+ZWOjHz(FPK z)5}#f=3aGsVfDjogF0b#HMyLpcg4`kpTSid)A=2%lcUJ$n=u>J)3!(lWZ$i$)jdkC zwWbA|qQ1R`76RQ%K4kG|r(oQg7`9Gbw&oz)q>8+{0iXhlHRv>!tA%+^_q0Aw5~A%k z$ZZG|o99_CGBwfX(rOX-f!|zY-K^GG`$cu4hr5b&w4}h?rDCN)zF{lNfTaNIYW>^TL6fnRUxKqQNLJ6X(j6-XeG(IzGc91%(<0l{9B@SSRWCz7aKE})uRBc zX^4c12ox83vv{EB@hy7@j|bbbYHXKU{9OwKCbeZ%@yKh-!tl7zhgE0G z#I3e0s&?kLSVS->g}hae$!@?l7MP;sz<@fr6B}9RWokQUrM4;YcJ24I*+S8y9lJl= zov)t>t3pO>xY0JBvO}zG$DU?8iM-}vXNop?;8G6;)Ez{MyximaDXZ*h&L2paDRLk|FtHPzu!}`A-IJG26ni zsOXAJRr1v2O+A7R{yu|i7^mLN-}L4GC-^JgTf`#No!d6hI+|SPkxOS-N7K9VVJ@v+ zYmg!JJQM4Rw2lUq&!g8L)UDeiv5t0PyIe=JLMR-C4N3JOIj#(>k?CF8SRy4oQ&S7u zK=l_DRwE@r!UpV}dUXFp;X}13)`Zy*v>&VBw8|eqiche1BdvnzX~2r*nDIu^1d zwpd(vlC|dpE#kqaSQB&Kb($!A@f7P1$n>_R8h{)=gN2L29V`*=-Jgc0?GhuNW-Srg z{Ne_BLB2?mWX% z!rib^p-f(d8Z(8x0DW5cEK4O#uksv=LmA1>u_!F<_S*Y4MY`IXnu40!&#@27Xw;X_ zvpVX|eP6SK>bpO-w(kR-E<-nIr485&hU!80UY8qHs8c(Gwwjo5GbTOy*bb67vy` zqA;y_>s<>e97ka+0wcVO!c+hmG=xu5I1FJ~U>ag>dSZeSCB%pYfT%_}uyT*|B@~XJ zFw_CzEfkg|2FUPn3dc~oO@@1ABV3ijfigUa!jhsO8D2->SW2&8Pa}jy6k(@`UUnndK43puEMF>llgkv-h0>)8< zo+)43|(? z5}Z~=Mx-x6grq1|hDT9Ya-gaV&!#XnT993a*HAc;!VVeUOW}$Xj+5b^z2Ryye1pQW z3FBpW)RJp4R_grn zF>YI;zI&*aX{GF%)d`0>@P!t&Zgs3Di5p^_aA*TvK@{cwZ= z^l&ru!{-k>*%CFf=wbYJDyoT?dN*6)eOpoWD(D7TV14Q;!y5B^8p@Pl&(~9INO8SJ z%S@!F1q`Z-XFfL4TL;y}Qa%EO%$140%VkF8T0uqhQf(~CVvG8Z;y8?tzAA1Q<%W>P zCCP@~n)aI%Ge#W9!IN479?eq(56LFy zaSS?c1Y;k(m>#^qo!^YE!=N-By@Q9T^RKzUnUZT5$Ec57s%07?dusJxm)z`jsOK)l znA2DJvOMWBvAome2pTuIZam{WCSCGaA3=eyhipsa3C3iMWe> zL=V^(dyClTy7d5{({I)CW1<}Lc$uhPzv2Q7BksgvlQZdZ4fV0x7UmSin{mDlM7@7I z5-3((tyy80InDsHhXE&e?^N?{C#td6VnQGQ200Fr4Ue(V=t-=B`sKC2;G%zrNmGc~ zWtlW&<==)$t?t2~c6XFOr?$_iY3Lhw9zg?S-+@5*Gkkf5HtTrZAn-7yUO)xnzUr{ED zwSlZ%$U@*w(q&;Tq&Qus)X3U%Ur8w<0xbyuTER>Pc6lQlPOfxfhfTNc)on#3Wi z6d)-BwBi&mSy=*GK>2I4d(_GyNulg^pX~c&_O1cQepD;|luz+@vBvI2Qq>0uvVexS zY(R2CLxKYV_ozc~pjL-ipZs)uz$xAh#58WJmOleSYoqdwY##`iEeLbKT=7H@i-sU} z3u1NI&l+HsKVZcQTBFBE?125C0$^8burvK(D+g<^(H_{(f&sf$!iw#|%*4Fq+Z7Eo z$^)9N0CaMwz3CyKnUx|W)Wpp;v$gle$i9@y2PtfM$liPbRUXh57^@lr4#OoI&b zK%NW(t#>3=(K#F}@PcNCYoMVXP$dEcoR!rw`Iny)p@CNNfJQ_DtEyog9_fpY_J_&MZo(=`sp( zJU#|XcoA!bDev~jO&HLL?9Nz4Sm_yZimFeTqRWgq^~x?${Isdl zm?bP&Jdntq3flii_zM1Qd<8Xu@8TcfyNN-t91{N_eJ|E#SU?n8YqOXN+QNzFY>~K9 zn>`)U$3p9BIQi}>(WTOQhj=*&BaLmMZkj1d%c1mvz|%^M*wG3)yU|VDJy#ru_^dc? zH)|`72e!%q|OZ=an{*4h>a?5aD|ojr#!(l1*owt zXgag%p%OuKKi(jK(e-$PNJY2f8$_4m8w{|yDq|9jalEq3YCzqMw8}VT zCPea_PT3+JeTdb?aR{t5Db+=7l;8A!!ixlYLw zbz89nQRx9T>i^kk$bH_^kbA}O2iYh0JPs*hli5dAoHlAhQkkZAy*R~!WcDxcxt5EG z|7yekdu{l31_b)-f2s`=HEkF{+Hm6kZ*5o})SC`^|K6tB%5SLu_1{#RnfpJ}#r^Nv zR9hHy!rlMlq7_C9?|;u;#o(#9yWA6G@3KVG8Er?*v5~dKx~Ay1ku|gCVetcn^?WdzKfUMbvFyv zE`{S3OSZXJfUr!kMD*Ou9;WS*TcAN(0*b^sEbTDTE+j6r&@pYfnYlzLTUhlV?}8jH zScuLY*!@cBVjK;-urE1m3riAvJFw^3KvAzF3r|~vjRzpYRT%7AlTlkm-N9M|ZtvkT zpR0B%4x&hydYGz6nA#G?2pBu>shq@4N|NqrJHwB1PDZ%yu%0em8wZy|JMAzzsyIQ9 z7&7|am_FPgzU#=|7ul^%ff)1MwVmZO6=;Jwzdfz2wVI^=E%vm=qxXw>fjt|v!YkJ% z$aUHa>@~<@(KJkEmWVskSZ&i>O|I)tXOHqx7J)ODkDBv0X{;!m&c*;d^(D+L<@R0* z9wA2&+9htigvrSg@xaRrE83#-OboA=h|gcfaBZ1jE>l!Q-}NwaMxP~jBla;zTg3jC zp+Pf^!ZC~WX4%5^1?y1R4O_aihhaEL%?_cw!rp+mDqpfp+Q{qjkcoB|>&}r|{Ovol zVHA6yGqwPCiNZ8Ch-A|(&hiS~a#7fYb%mtw=!o^h$GfsNLF4{ts6SV(7Hf9UGt{5D z^@FD)BO+TsvJKCoud> zbW#4_%S1O7Q$JuyqFZ9d|_7r-=n;GnriayYp*iknqBXjxiNu!^7W_3x*>DRTLam&r$ViMw3ple=6+(Us@ zYK-txpq1bM4Hf8>pniX}26LdCt}XNbj_$lEs@B5c{c^Xj4*Z+jO|JwE{v$4r^O@m! zj*lO}G4KBa$H&Dx%h)TlD9&8uA^__#08C$xXb>Y+I ziHH>}1t{2eg|2|DDKUBKsU$F3^H+ zi^mJFBkvTG3(%-eu@w)nKakiD_dkI)`GSOwTV;ZkTB23XhOI1vnu&XoKidvZXGKwTHFS2W|Kx))bU8s=Bo9Z^arpEt%zI zM7g7?B%?Mx^BYv{UjKI+R6Tr(y%jXw&5C;-d>QiZj2y(?pV=z90f|fwJCs!Ub&%;eWx9^-1dc_SuoXuEbwqxDe$#ZdpnVu`n${um-7bdR&;-t5z zcAC|zOI;-rFLAmL=Hw+@o;1%upQGK(p#$u$Yy>rzU847C)*9ymH=SnDNt9P^bm-lk zl`aLnlTO>d$wmK!15G#yg`ODBgha?0R#|pwbhE6;lPEFpY*fU zRGw16#22+X*56bI#C7}?#=6j}i1%0uo~vo1Uk|!+o7BYr_Mmbp_~I3^^*OOuu@xG0 z^N;v>pq!=kn+5;nXX#Gtx3}3!Ha6$OJFGE_o^8ekDLDj%Fk?>*0g`OmT^lue18>?1 zjuf<1TpUfrot_a!34qh^2*Z&c94Fv-4uiW*I+w$gA!a&|gCmsE2Lle{cwTW3$MXu~ zpuLJ$7=NmQ>h^sp@u^}B=)aSGF&`i;I58`G}o`vnR zDHpY{yiHHxOIldViSQXMOs);2j|N=$#hb)#rnd??Ck^~%7JFIx@dGP~pYY$OXc4p! zOH_3=@wSE`xR)*_Z8e0k%VNEW*GRgkc^|~Z1!U4uPI#_W2B0=zINlCZ;dFBl?-xac znY-9Q@q(G>fjv}9LR#AdpH)v&x-x`>sv?s zz~PJ50#CC6$`81>%FYKmyN$O0ej*&QQP726v+XC7_i$Hrofnk%#%%@T~@8M1?@Od9)aeMw7*2F~f^8 z@gLoqeVrk?hV=YM%Fxt%{z`NGDC18$ZH(&$`A2 z(RT6;Sg(7kD;sx~CL3{ijNzY-Tn$sk44!2aYwH;A7pp6BlW(sZw>c}&6tBJ zU-@OR)f0K4CI=sD6iF3%9qzP=)uEXsy>j9(q&WMz&Dbh+}%-HB)YgRXa@%u}QCw63xT-Kpa;2teLTi*maXX$8LyP zw|Gp*K}JIo%7r}WZf}a`Z*f=7jWD2RBSe)5Ub!iJcqD5+AOP@<+g*be;dNdMDTe3T z2RvYjI#>$v9&%TP1CJIy(XvOTCV zz=l3KP;ARct=RiK(OzFMD0YN+pOR6hdY)uZ<3rVCB!>Vg#y8~l0(bpoUA7?lE!3s9 zCmNoKHOCcN1UR8N#|244&4D$&V8hCSRUpfS#Rb?SxQ8hI0xTph;f$_hRoqp3iwk9>yzzpI8NtXm7U^N3~vk-vMC5c3^3`SL%PKVTP)0BE8*H`h;SS?*lIEc z-{wfU1_0Q@IGnhG#e;!I+&0m-3LjK)omrYT>1SPz!8ZtdEc%TrA~hBYcvNJ@^80XU zW_>L0%8rSIs=NbkBK)H&f3CtjuFU7Kce0yqDqe{+g*!?{)V*MZp18hSLKceTzL2)o@@~wcTB+T}L4$k!L-Qsld zWbs2&T~l|Xh;1B4i5uE^e^xA3*m<3ZBgl-#rR(d|r8)wDgDXeJICxl$)0PtB(9Q+B zPT>X=KwbObe?d->>N|LCn9f%myhW@N2{eZ}#!555aVpHG1kH88_7;c(IKswrM~K@F zo)meU*{vxt9fNeZ=Znl(i8O1#55=LMJ|XZGfJQ(+86oM$R*#v<_Ba%IM%;|!QEW?2 zL^a-wvE!m+JbxA$X2$c6*hx_(0lobx(KCVXL|Z&uosZ)`o5Ydoyfy#DBx=^+6M%J7 z4c-Zl8czN>9#fs1u0%v6@<-9#zm~{TP{{N|nC@bcpU4~FUe(P+UZ0&4b!r0SjQD3w zq@5AtC{!d))#P=M7Ez0jjoK?`uaV^21n#V;s;9UgV)=8(wDQNF~8(fmr~dOxlE14Xw>CsQ&3PWlx94s;%Rrap&M=v zizk}#XTZ*B&3NtFp5#{W%%G*G(6G0(KIh!|;U`o)(FkMp)1p;#@biqA+nmQBw5d67 zkHV}ic`H1gXvyCwtqLmQu8KyUYpDXO}72-}u}_m5e_J{D;bvG_2a zW)-x|qD=6%}1=KZ(`nn+GMw(2=r zR@!-K|4?3mwmbvDMtmS_P%7YS)!Q9kL%Vr9OQAV7QJ|Wh$ zi zMBZ9B+`@-DhykCq=NSO!k3ovgpl>vHcF&NU#D4cfX22d#_4e9=BfAO#9U@ixU(a-T|)wBxHeQZLl z)eut^H@HNf)9HEs9B*2ZjnuQ!IMTcjg_5b3)q^J?knWcV95l~}R|>?L7x}AcUE(EzURJcJRBOam|D3Eag0}9&t!$)r5 zHT^rEDDmRUycRCi_J5ftvs>cbPQ0=xdYOkr_HpxDaw7oQh@m#+mauk$_Fy*EiMzB6 zHSZ0(0I=0>V9^A;03jL{2<~qj&2B{_;stF7w;EXow1g@nNFl20uZF9W=3bWoV&& zI)}w|^`fLd2x}sg2{j?ZC`o{%Sa6MlW;76w^!dRcbF&dK<($ukoayUNj1#mNrn-l-GFuq&vU>Upo(@ygGI( zEt_k4VZvNNvKe7bB2CIj!Cr?rZ4+^?^Lj0033f|!U3M!pKWmMwGE=HMAA``1M1g2b zbDYJ+>5~}LctvE8hXI59>IEkZxsRfeZOV8ggS4?Ql7Mr|8Ew>z5~p70%_?Te1Z5P7 z8GKC$SOnQSq|FM8BsRfe~nbXegv&GI2~AXpAOF!QhUg=bJn{nQD*E9o#^}jnl@WKN0ni zRLVg{oRpnZ!Ij>K4kplS1bGZ-q^m^v#y5HG*r7yBUwjwFq70|(ShrI~XfFn=bA-Ib zyQYmL{n9Jrfhtjd)zpDpApu_=JQPV9@>iht#0;&)VHol-mXLv>U7DG}nGtt#`W{pq zAx-M>X$e{LtkzWXajlhuGWa%yy1N77!dndRPx{I}&i>-O8Q0+}V?WQK6O<7)+St3&0$4y7L% zFM64cyWgbtbEMiEw7?jt_F5+g0?1K6^0Ph0)z%_V0+b-Fd9rjCc&d5OJ=% zGyuWxO8cGsF0Ud#Mnk$j1W1x}xfWktha_$jUjUdaJ0=y-_56py+X|#Kr0YT(s(9s- z`czcGtwyp*;aJfFJ%M_G+6Rw^W;`Num*(N9)75x=avDM~e#%!;KrxJ!=2)6`@X5~bDFr~lY$^L_lq9<$ zx2@DP$jcWh9kxxcu^&Q%<}x7{7^$_5vY!l?)-qCGs45+Z>B>kh`&v&du^u%d8T3>J z`KZwe2e6bzm)cdtN~yZ`K7an6mcOZOv1lgd8R6pvJUg*i4P|w~yVaZ{>HA`+(VAQn{ z;27=2q>K>-J^5RATXGUdxbFQoEcvAEQX0J+0eL$hLSUP}CEq9eumg?U#yi_cws(n9 z2F0Qec(vHCsm>YXcm>t6rz$e6DY#xaA})TwpT|_M{fE50GFA4SaJ#3;&Qvk;L!OBW zH~WaUX-*<(#XV2h4mr9*=jF01$A}H!98IQhGC}L2lv6Yq1&h%$FiftNf5ab3n@0Jj z%Mvh3!XT9PDdp$`dgdP6O8JBZ14`e>eDrbN2>=aqXv%`}3iqwm!4jP0$_%PxK2Bpm z)iAlF&!Um|;}^cgOv)^SU3~sA)<~y`Lm%^bo#yUci%m}YEu^U zNFsV^9)LI+zmR%j=!r>>GMCzI2}-~lX(~;eWVZM+7)jkVj57^NfJ8YHb2x|o?^9v1YT>0K4s*~Oxh$=1==6~{yX+=LF*CKr~rEM5eTM02yh1}izV+67iLFq2jh=#vgy%7%lIs)Sdcv! z5g`H z4HG~|i6GPRofZ(nlpKN&qKDgF8eQvjGJ}KQ9RyBqQ7#6jmlhZ6DGL6@gRP{I+Hm*S zzxYdO%PIf97R1B=MFwb~O!|Gb0g-JXhH+PV%hWjVKv_Y7nFv@hIao<`v1)PD4rE)c z@`AdnP=e@{)m{*v#H&bzD-=phqXw2Y*wKlCv4OBkOhZAuuZW-K9ND>=hQD0K|xF)DFS{wx^*HB)&jdWD_h`pUh!kKd5|q$@2zlYd$D=(4d@PZ?Z(9X{oQO9Tny8F0vj59k4{fT5l8hzM$1toZ>>at@-U#Z$9tYaNRWatQ-N zP`F~vgBxP4anZCWQ)V(!0>x7+`^9rDUTbdjU>dyDWz*uRr3v2Z!4s~n{t)Sf7S=htcq43BZV7OOlO+l@L#h+B|tYcBV9on_7}`h>)iiR=E9@g^)B+)!l`g zu>2$ANtcW*k>KW4X|)X+B5(EF)s`b4H@F@y9ALFur1Kqi)QLLcNe~fF&6RbMud*H2 ziKJdUGHN~CWP-L0qyd3`64xFNS__d@mW1l zJeV(r7hp%_`$XPYLx9*Zgf|FwN~c;hY{oVN_6RBs#Tg~1cz-CLgETsuR+^SL3|pA+ zO*)Jx)^tMKk!DYI1F#QV4^nf}ltb5slJJF(?syc4`NL?QJzVS<#%nr`(;NkZ3@sae z?erBGnN`Z+2@x|K3u8|4{BZ1|eJ}bA=W&(DgCFg;U|6NlPbk(Nmk-A_+G&9$#fPxt zr461!X%P{Fu0$Rg2XDCA=E`Z&Gn02g8|}=*u43_+5qtp{mpuYIjcY`sk!aH+;**g) z79)!>Be4tlwfJ@8%Ke_kn`DsdtT+-0FG#{P=t>O!nI~$b;3cNXHXn78n2R-l^R=m>S7Kv~% zx|F{jes;ys{fkZxzu7fq=Fwp@&SmadwnwLwhzm1#LKC-p1}vHBQid-5X6(@uS-q#F z$uENHQWjobRP@uTk$YAn0&-3`E1;A%NZTrTW>KpU zZg*+4_1uWH%r)crQxO-g|F9x`aQe0Lx|G}_*$ajiPrY>HFQHH@S4W!- zG7Joxm@#%%!HMa)i_=mje0THOj^dT?{001bu3B4_B?X-D^eotBa} z>ZJH??A(G4e+}D;XYr(J<)ZhePt>2yBgm62#4KXS<>j~fues89QCiB6$Ikc48?ceD4=Uyn}9xa48qpCM1Qox_tFm52PE#L2G(kooYcX!zlbvzfo_+p{+} zEoJijqs6^Xj2RaG7w`^tl$y4AdFby+UeR3|8gX&hwqJ)I9eMqLE@k@qA5RRJIsM#n zSW;=@{tWZr;Yf;Jx%lr%pmhB2$G@P|}P8kL9sp5(!kn~&NKpU+cNp$ny-Hu_kf$aM(%IQNVOd?f8X)lS1zw^=2qMJ8_zHJ<-pD% zFO=JPVF)QDZ&Eqf{fNu+(OTT>E6cl^n+kqXht1CHlrsC$^;VDB! zS046zQU`B5KCGjjHEhD6-uWX3E;{gV%Bc~VclQ0fa{j}Ao^|4hMLfw-4r+hO#P~&} zokLN-Rr@A=b$sGsUCN<5rNV?2eraF63e47otUUC7jSYuv!*!`&URZzISDZ{+56X$+8 zmwsu~SbNIIf<0ditC&9ZtML(O3{!5-=AB4SncU%+@BFT zp016S8kU3pp47pKPZ`#QP5vrt^RzoirIoEH7f_TA7#D* zclK_+rH@%Mf6n%c8(OBU-m~E3%(L_FwEqkECN8hyiDJ@BZfICe0eJ)A+>>bCO6S7p_QnWq@qp{yP5|yF1I9q%6x1b zyl!gZ_VRMxt?DFk`lr29d*{r+(051XjYEUZ4cG=M}8usI+j78(J zBD~lqYh;%PQy%(BzGPSZY3hx01vBRs{j5vbK4j2O2Trd(G7KG_o8y@p$IAsO5BKo9 zNUxGRaqjr9#vCl_mNIbG!kuew^_kG!i~f>CU$-2P@{r@J2xTl&?DlQ*=HD4GvH!HR zlz~Sk4p=zyyE#vLvCkmv3C*y>l~Nv@R)qhG4(`YMvYw{eqi3$%Hz)h%zM*L;d-8S- zpZWdtjp;NZNMFU{8~$fgS!|ekG)J6W#Vt7aSgJPVmQzY2R(5>nw7B|Ph8JN6`yc!1 zz|fT|TBZD!Km7LQwbu?j1~Lz>2AOWpd~)D&^s>CX{lnQ2tM)GV?){X(2XDJ~KWxJ)-jCbo?KxgN zGM@$vzpeXE3B*}*FM+m9=5FoXW?F2lAxUjiURn2~6&~-(@G|`CUrr93y0mERPF+gY z?U8v?^Un5ng4X9Y{HL@|@}V_gl84qUrS0ClyrS+&Dtu>_VQbi_Sw%nhn>BgY^C<)K zX6#%x;>Q9TC|&a1e@bbdFQs`NO2?N{+OV9G?nx-TFl#(T7uki}P^Db`wf~gC>-+7< z!YtsotnG)6+?x2B*X+$Bvsa_34(G?q1=Py%?zfJJcYFl zj%)rK7~{9fZ(K@9CzV}~%65|*N#ueUNiJ%0dMl6my|M$e&r{pl1kujyAJ#^e?S}mQ zvWZplP9E+Gw!sd^zkwX&-rj}{m#yOI?R+Gf^5k|t2Ip?REX3a1bTPY-&%oo!9oP)p zCi3v9Og#4Nz`o%O5xSFq&1Q-PJ9#fe*54)5+U(*l%ggWNG6Xy1fmp6wxC;=oMT6b^ z)5w`tZ0qCDTQ2syaEB4+9k7+03ZV77`E(#n{Q(yxXN$}qaP)M$`2GjJkj)XF?%{99 zPdS@haIR9(UWrafZxiSC@TT}ARE@p-eKt>sy}YaYd(QxhuvgK5to!%_Zi2AUM5ij| zi)Z%n=J*I-=02VjI?oyxKm>Kc{#$@X%zUw9AJ3>X*Glb#^L;oOW5K0;ld>SE`;WLC zhp)NWe&RbTOtq5d0r&OzuQ43uH7vV_Vcu`T;j^d%ybYEqUp>G-d&PT$Gn71~K#(J) z#}pO$X=5wM9!+P5kwBgzmYES7R0~HThH4i-b-2Ak+34;Ro{G$dy*7|WU*F0S%?_fd zg`(F%Ud=R)+TSLM&tlIr?;tlA###fbibKV`sc8)Q21SUNBdGjB;X1_QL;Pwm+8S6% z^gPL{1OqcZOz+xHbupqY-yD*4`Q;FQjVc{TmBx=n87*Eq%&XPY3bn&U+$aMSQaY(q z#$t4Bu~(Y`#{u@Z8PFApRLR1pg2cI>c)aB>p*H~i{=*V|ToIp)Z>}X5^YBJgM+h)o zo{LXS!ik6R?g$T4Z1x0uJao{f1ym7SjBQ{IL!`tIRTe{(O{^{9b;bB%+{j-jW*6hG z-8iwam_Jd5J1o~7>*s`0@n_TGAmz;%SW(HoF%Fr zg$SIWTmi`S_)*@a{wS>xVZO+&;Rkljk7}w|1#GHk5nu&mJA9P)@KE#2F^Kp=F$@oi z;%L8uW4tlGHc9?8h^<nBuJkfI11C2Vo{bGR(!HE41=QQ%S%erfjkpxaXgRf+iQzg=vS*QFf zQVA8Qpt03k5mEnVUZchhD#7%Jw2*K$h<5WyeiF*9qgJi0!b!iXTY3?@$wBX4h;2B%ATV8Qe+C7PHRqH}GkRVA!MT9(z~GwNFEb8;QER(Ev477RpXDIIPlHWDI14=HE43-sNy&M#pP@9%y}GDSSUuE=TCY{`}w>y zoAD*w>50lK;f;e(nx~h5DIQ(I6MU0_A_~T@mS5!SJhM)m5CjxGZ9?@kyActht8B@5Ie(yq)uVv*ZPJ59kYUV~Ng^$Pd+Q zgm-IibiR1^Iph0Z7&Kp&}45I1m2A!5U zXt2dmzldwSi;be<4L;I(QBP-UoOUMm-r%vd=*lsUmC#S5az(ENBXOh=5i!bD2^CTo9pQONh?S;EpoVK?pgAbIOvKqx1k^vH75^q2S()~pxjv+qVK`t*3s#5J^F(tJO<+q z3{G&A&53@V7=|Z&=}ckzp>VHSpX)!u{C_&vt7&_{Q7*aW0&)){wlZ69&dkKbbQ9bo zkY5L-FONez(8Ji%LD!jaAdJqv(1{VuI`CCa+@paDI~?M|aWxr*8?Y2bsb)YGX{Uc_ z=!26|IB~|)VA19;qpIN?a704iFF8?nCQ+s0RH}nA?YT#!?5egiHEG5>neDy3=o4H`l!Hd z0dcsyq@fW`quznrE;yTnQKAk%ILoMA{?ID}J(VXfN}d}bCFuD)AUN+RU03+zBCcr1 z={*@VhJxA3Ai_u7zzIz+KHR2GK}9{#G^@t#DT4K3kK`8|cExI5M;LB5;-i5?E@j1c zz(s&bADfncEzd(J{A6*S>^ikPkJvMqQ_rZEx6L8!?$YENj%6vsi1Qi^IOz?f;D$WY zM*$qEgzq34uYop@?#T^xrF)*TjUX`wSG_bX4{A#HKhd~^L>VDlNJB^lfJA{3w30m7 zWJwaan;@+?x`&{VLJ|Th=*9qHC$yw%nJ|U;04byPR&=&$obfMFKo)MJK=y{dTk>4Uqht<&G;AQaValv97k%_alMtihYQ<@SQ?y5nN1c}i=3MGhttAc43 z!cs*8$pc7LLs`0uG`f|z07>_viuyTENxEU<>;XhKHBu(>TFW*`p@eW(19k@x{sPG9 zVmgqZ8X~)rKJ0moAu`TQcM%%LdKb_0KzD$LZnA;avSgQNWJltf0I|DDsQ!XRb|#1l z_K*!*3C8(p3K~>GxXI3x5M{~E28qFv?5<%RveQ9Ru-#2I3<40BWp|+jakINff|QYx zbO-~a#E#nqAUkJUn7)bBX>bZuRrJtJ%3nsqAt(~UO*fg0vic6;2i+AtQj;k`{Iwq~ z2^uSUssWROso-7pD3UPldXQl&V;z7+tA{f#Qr6?U2-v~8TS!u}L1m<;9xzmQu|FL& zMw0N09+mZ>ugOe>GR`gSFj{vD`y`MQ=^+~y>~7|lNC=H+B>ONv=VWF5V@4RCMpgCk z4A$#KyZ(CPfiU*ex6#uULL(UJNhpS%wn*yQVN@AzufQ#!Yv1TRTnWsST|7MR#$jPZ z>*8Sq<=6w=XSg(ivK!H|0@-j;=+IYxyRYmaO#scK(T+C8K-ZXo5e2wLojAs0o}mZ1 z!k0rJ0;V(aMee(E=$#NxhxGfS`$caBHz6EducQFo)d2BIoIYG$uSI94!1up4BA`1K zZX75~FYn8E#wcXPQ5pR2pwSNvjp!bt8(fcTnsQ(#>4C9Eq8ze$0kpz#XI*}209f>N zy%gqydUg*KDyP*54T&1T?FpFdsW66O24xJ@%czW&@q~-U1$bD9Fj~bTz4f^bOS0}o zkMgV#3U_HVVm7+pFD4#%)`SEPw{*lPulh^zk|l`M|gw7tCpx zil4MR3|8GkHj*%!grPn3a%@S1BoariMZvD4y*!*nD?(x+o>GXIMp&G8m@QMyNJZly zm$!L%73eb40SqIq$8YTZ9 zZSNgsMUnLZ-|niqlc9lu85qL71HzDV6oDQUvtn9ZBkr!N3%V<=@2+W`F(E1{Do_}J zK~YgrQP4q51A+n~U;<1y7*WARMaBI6ey6(cy@S5*_k4eR@H}(7t1Fy3b?T%#RR!aP^*s1hsd%uJJ00z05nl zi~V7@byGc0pY5X-MYbukm1D{7QF%I}(uC3~> z(rvMaU&|(8Y^X=i$a&Z~EMokryP8`4lIY#Pr)9(A`a3#xt)%8^61HCt)w+$;16psY z4cn7@s3ZO+-x~1kHwpmtx!)?hjZj5?EB2{;{6^FxB}cm37CqJZyZxY95{vLHxwlG5Ju}%v`L&Psirc7_k9)U44KmrJA7AxS zOC3tVlT#+Q4cpLLwT^~OzU7XE=;xBUcN?{mnv1KlKI*M8f~$?d>~H!3eXVIXST~fQ zWE11V_V24oTT3m_#F})X{-nNYh2O3nBpnqiTHT^x#Z#x9tr(y>xZ^)?vmvI&l$mbM zVka@CLH2DU)gf)MV>Og^&7bd|ChN&&NnS24k$e|kbV70*Gv zXG=z?gOlHViw_&^$s^QI|CZTy`UusBhro_dXW!0{&K4?B z;_;wXcrL?N?DBn8TRUu|>Ra;qMr`Y)i!c#R-Docusk-WyJ=`rnXQXOhvKS&P<&8*i zFg~;|j#O3b;+G@UNdF1nR{!E3>^)j}M?}166d+;!l2n z<+J_NUphSlh6NXCSX;X?fpuzVO*p@r3${AM;RDau=l4_dN}q*m@dzwpqbP>YObipj zbN0efY822|KS~{HpL#dh7DIB`EvlRKMysCQy87Ou)#2rBmdh|Ym*1t6NJwf@u)O}J z6R;ZWEw6v&M0J-JOrH(BK{~;0lTs6dmG;V$)Ze^k?aq@_4{x0m5RT9{2?@i=3a=Ywg)en$-ezK~(zeTq5(n_V`X zqPpSdyHnI~Tnf_vRQznS6Hiq<=JkeC)%m{#rTJ-U9LkSBP3`XZ5{MT=MJ){b7)da( zI~N+xIvmrc_Q(4A6Q`?x`%`AyzT*|oj6Z6;Iukn+A0Mx3@H6-fbu*mKFP;Ixzrk)l z16f|S`F~PhA@RpQscIyS`m<^aa8CTQy6U&!?D(@9T=O!hh>N8o5;(2^DAoT8n@0YMQ~jaGT4=;jC_m<8@B?|{ zNm}hebet7FSAadFG z=pkoexY?wQ54|N!jip;Xob`Y``D``NpN9B_voY;vJ!sdTt%l$Z^-dF1g-!iU-8+2d z+=fKhEBt~#E4}csdH7wSf;U0GvUU>go{yBOaOFMtsl!aZ55HhUZ`xn~2BLVa9#uW= zb$G!qY6jp2dcrmWyn^t(@ZH5g-4^@hMAZuG;N~2)Z_yT~i(ujQEqmBGs=wWEjv5qf zz&LVc1z=<5W74-eSDnyo%W6kJ;PW^I%U*b{THI_~oCbz~wBdgTy}nTYyqR zq4vWz+fL`HyHAg%D>x%K0;a1VSBID5HW!Z@gFz(WZ}Q++QF>)zIu#Px9uD{Pi&|&a zgTR?aBoL3#JJH;BxJ4agD<`Q+@7-I^eY2ZAXOe0MUUtnS)zN#?-a84iV=E#pns~-1q&Cup`K{Nf2vYD?VqXyC)>{Xr#d?i zTa@!If#d|Zw|btUb%ztRx$;5*fYHD^_!@eRLwvSF?18se3c5=x)kMfyAG0-*!96E{TR05~MF1%D-<9%H}=s#+^ zLdFi4t1;;BX_u=J9+GdnLNzFy(|*!qEIsUDdH8H0$$fWBW)=MlN%st8rV_Fe7Ra~E z2k$z*0dDtNCr%XOvaZGpPp68G-h>*4k_v0ca%Sc%=n51ta%Lvn9C!tb3=3=AXI@i? zk8xqBmaHo*bzc#QK$RtK7K$;x<{>sis>V?`xn&ncZk7S=>lVBM>v38538i89?4|IK z1xR4s0(KI$M&?)Ck7}&T791>>JT_d?gQo0GeD!hF-%D~{O~ZVV ziG{ui*`Xp}1Z}!k5Cz^ra={PwuItsP8bK^+&XFL1g0Y1TTzn`jp#l*DV->A+xNjf2`cO**b!xmRL!3n4Hv|d0! zCroxcgeYYM*oGi6GeVhm>~lA%%0iqc45CBTzu3=jQWeEu8eq$gW!sk1RQLar3NvJv zA;kY5sgNTUW~mUEX^Pn_F4^lW4%p)e>$dD>mG*0u9dWa2Cuj1&GnV1AU_`j8J9l1g z=QTsN?x718YJYuHgyol%Vt+KbzgdARFpPs4u zBIgeGt=vkM1KiJfR&w5Kp~|na4_nE()kG!fZL=)C*LN`U3!}UHs>~JuHg>V(eAhn z3c*U-PzU9p+3gs~l@D8aW%>2W!3L}vT4VYcU^hsYx3o2oWIL1C9!H$kZPT3kFKFFiORGD zXH^!UOE=viT>^|mdJJBnExJ=R%YiXzhq;7_1hIG(-j$}V_jv(>8Ig-83eM9z+ z_Om&H5@c`JvIWABI#w^ZdFRxvGauP9hzRL2S8#d6T*2kJbK~+I?Nf85Q&P!x_smLK zv68atyT4rf_%pxUVYdtNy42+&FUTS<<&f6~$oo^BAP=y0Y@Vua-1^R}-8;9ux<|^R z5n`0}+q`+IC7#>OlaB2>Pw;T!JSqI2yU?Ti<_Ta=%!|vkvER=V+%>;T%JjQS${cZ* zbOvRJsQcZ|8}7%uTctV+0hgsp9gH0?@NM{*!Vz;q#pQtdfV-uV3+|Rm>fFyd_p|42 z!CiX3;4YjmIVa7RoU`4}n)w3cxASBCv`IBXJ6MBe6O1;%Pkv=Hv^3}*>EfC9NQqnA z&vWi)$35ytIA3s zj2@BL=oPgEM*Rv>~d0_3X0?fXf^0H}|PKVJuI1E!o>X zw*VcTX5U+&Zi$oT-VXtM3tH`+IFE)pc^=dsA1;l^$%K=O!3KRCx0^{o1bgJdhpQW= z=!nFH1TnZ3Eu!)1Htzv-aElqL(l`qT_2TP#JN^Oa%{SV452!N$27cPuwhyYHJrP4m zU#)t#DMh6LWU(eI?Ni~ss40hpT$SW0nD zL+YQ1A3|$U0(3y=baXeOIa~(7C@89R`0*J~R0*CMV7kGqk$eSFxg^)0nV&IHP>2Os zbT8@-E0j1T=f13o0V!l%)E`klh9s&C!$aSuVx2heQBon|^O#GceS9r7b8T92u4sr!A(Wbd&jr2^qI0 zz)Npp-z|HC1nCWRE>uzzFWtDJxfRo=%f87U{J1vhY++tdbp!;CR_Aongd_$q9%nb| zk%w3^(#9h24jBqp?Go`CKmjtY{_-Ph7f2oYv)Gja%`GYPw!u8;|VqUIv%XJ8xh0}b03}&Ta^d25CK4>2I6v)yRiJOC$ndY$Q zgBrl>#xqMYjyQ?xyJ9Q|!X4IysG%@Mt&5ADqb`s+LKX<4@6iO4VH3i32b>($WZ{) z^cvKNNJ!ddE+3+%jA>|^Bc*W9Pg}^Bq6Jw| z7+ffI3fu^%T&v2wN$Grl446z_9H1-A(6Jifk#3zbVm{5?HvQsR3pTmQ9CJh89t0rm!r=2#PSSaqT454DnMAxJG4mWaL(6 z6v1y@Zm?M-0)FIg$JxU6Q4jsRt_IT7^*A6-RpC2k9#)JvK=DT|&O+dPyBN5G?Shz3 z+i{8NgzJ#-?B<6(c!}!AxIUP(^u!^=8rZ^FEKF&1DL6(jP9Ysi*db+sf#hw#3q4@2IlO@5@C6YSj58z~a&;nBhDN`{W3M$>nRY62bn!g>v?}c(1yaA) z1l9$cws88>YQ0Xnh~xT!%a!&Rq9+m}W|0iE=ttJv8hWt1kLL)90P%u*?4MVtu}K$H zVjo$d+UCbR*lt{*%4=pJu4IUxP-8F$A}tk*P1tZjPB8&|0Q)scJn+_ORGhe$C5)U* zL|8hCiBw}MazQ*ZhCCm=aEzwf!&EEcdGkIQeq_gpU_s_0d)D)+bLR$X)fK^G^e$-_ zM??LDXlb-n67ZHP@TrHMS6%Ije!5Lxb|1~k`Zbxk(-orH%OuPnR}4i#{=vO=;7ZlG z#@(Le12XzogNMiou}H5ZmOJ8!eziAL)lrkc+3#>att*61$c&iVI7|OwvW7>f@T%Yr z;GsM6jstGQYRK?yS?mXQxeo=qt6APSjzqP6W2I^r#Rjmptcpf$M6@%^GqBRERB*~n@h&Bp*@(xKb-@2gZ{ffz<8gKe&>R9OU*Ydn@5 zS>=MgN5nuRasXjgDsqLw2}`hoY)RP*1JQ$SA$&6;hB(xU)R0eVkQF-iqnlhG<>(Dj z66j_uYh8bEW<7)LAGM=iP!)0m3-wQF7yL5^97>`4>_soAj%SJPh%t5Hg`mZlN~*oM zZC}`$M>K&lyQ^txoW86&L7RwJ6nIE>fe5!-An z9JDw1!l!=qIP%o<7n9Ne2>vn~%rq&2o(SJ?-=mh@cOiLz$0>z zI0hNvyg&>kmDVT^DQ_v+lFuI?(|rh@RE!q|{O%oI17NE%2PhZP2Qw3e+^)6gBO$^R z$U;O9z%r>DKV;1ef0pJ^D=-$nQ4$e>t_Nt0z(Zsg5MWF#hh(A@wSm_Y;2Iy0N*B0- zjSyrw)DuNrA>0_AEkMh4Is&0QQSP~_iiUvQgJzle8qvMQI>2`lMw~*ja;34!jbu~Q z4NaiPEC`&ih9vF^$a^;TEWhXz?G@A7sV#_?6WIWTAFztq5WUgWgja?QNzAEWnig}0 z00b_$aWV;RG_W181}sDT4%n2Q{hW}bC|(zH+I66^*i~N#eol^`sV%4C!YGhc#7Rz; zoDkY#mxW=l2KbMwAq!=gE36=30(+GC1OFasD#_9Uah7e@)dZ~`W1gufhu#@`JX3lI zomr3+7mi!2fg&x<~x z4j@Z}2*czh`AV=c$-q6uM2l+VdqlJHnx)y9e$nH~g~(@VR%p#N47zpnjv_7v?Sp-e z*JHpP^j{Yf!;6{L%>O$OA+q$;=FQD8=FO!VNN1jP6I% zL&nnKg8awL9s@64gh;9xB&s4}Ev6LsE=VZkPCV>{tO4{W zmZ6w}paU9+380nZOHgkhuECYCDd&h+Ra+=&(YVRT$9rsmw_JYX_7D>>kv}Zzts5g; zNgQ{d%$s?H{C|tw%0i4SI*$>+m?lAIV3E=*7R)?KY0@=V232AV4IQ{rkSqhs4RL0$ z2A2+E$*m%fsTlyI3hsMAO^GZiKrjYzMK~f}9_*|ibPUkpdI!ZU>g~LM0gcmZ=FibBY6JP-|KB8hy zBP38+<5z$M@S03u46wny+x!O5YoLJS$Q0yHMjt7+n-ok6mvQ34WD8Npjz|Ly7m{CB zMcM~1>68dZjAiB-$iZ_O%92;~wr4-wq*@MimvV{~ir!PtH_kKZ)}O?JpnW3-;V=kH z7(U%MtBTW|(dJ`G4XAO}56FgKJ9i${%J?bDun~j9adF8KvyKjkD&&$xop(5~cW*}Y z;TF4Xvl`v$1rDwF6XqtJB-w>vDxdLqm_l`S^cF-OY_gNLsKEnXL|&YAaiCnCM@lw) zKR8(J)VrL|(T6p5=N5H)U!2Ea+h;CVmTTT2)9J5 zsR`jUoQJx-0OnUJWzIrK^uI1}m#|^3f|sWff1iM~N_|L4q6nT8P3`;;7&h3bV(?l2 zJq7#G`&Sy{m8NH-DD-UicU7mpntm57$~v?~QH@=|b5-zZf%D|hKth%jxYRoP?{`)I zaRL_7DV>n=@yy#=%+(b*O{SdlofYR>%g+tLN+)IWph)ox2Wv3WM z?MRnygtLdLapJjRz8F{B?T~|x%3{_eWut;P19TimWmvVd`%yNoG+d2dBqev8#CFCF zRsApLyV;${Ch66x8y&KWh&+H+MYEmO+WZQgCA=02F4+So%6}V`01ZRrjH&cVe2%3$vqudGP2TlFpN?1*H8v zuoh&;5_s=KB3%d-8Vu52{J!d0NX=m-wGM3`c^~l~YwWuB)fouz@AHA02cR~7poW1_ z74WLgpFP|BAIY}%fDaKm@tke=5Rn_t*yNDYS@iFeHc z&yE=$Af83YtOjC^`UXS`UnpUUMNo$gs~Rv~Vgn{ZCu{umO9~*FRD2T*Ek8CQQ;yxfzE_H=AkwxTePYC$rf#j zEZiL}tVKk!YdwaDvyec_-dDgSalIK`Nw#NVDg(LO>FV`W2#8fA+F=5_YG?W*d}4@CF}y~`)GpV@?s?azQNQ$n1X z+0o5|evH0w12#K~%?OjD<=mW&*i=*OkK0vOx3G7O?e?kaDjGbIgu|Iof3U@#`l;&G zk@Yimo(yb^GOC$U%YC1!vmqLT&(uWxT>2R%{k!&&&lIl%-trmt3#_-_eWsp5;^NQM z<=9m-c!x^2+6I#bVMbJnz|VO=)c5vpJJi$O2e#`@M1xM>Y!AV&_i_Eio$7jTp9lyB z-@`wHp~F;!z+m1`FuUyM|3$~Q+tOWX zL)E9E!lJ)r__ZPIb z@q0-}=?tXj{UD!T{vliMtRLZ9jXJXSNBN9qPqSD56qi25e)ZE{ZJ%Zvf0oYxAX9m^ zZ6-;FANVy3TDI-eX3W$?lJrY?n)s1!=d|Bq%9eM(6!l@|6}P?&E@*JWi&r!ZzQo*Qhu&T>d#7@GamPUk_|hicE7F7 z)4g#x?8AAw1CE1Tm#4c#rZxEoq%2(hGxIeM*5bU>L;OZ?w3Hd*FCu6AkPF$kPgA~z zvm~fl4xGS+xH#kiydP8I0mQw12ikJhM$)~&F@*A~VeF6{BXc~}vC_e6_)37aE4B|Z zAw5ndhj%r&Hl?Oup6uHK?cv^y9H5&`|B)3UrHZ4kLStsJNkQ1dNL8>xo928`J=D5x6)t5`z|?gGz-xWY~Ec}Tp{ZY$K|Bn$*X0Yo0R>uL&S+rx@< zrwB(FK_oXek8#9SxTYR9fGdIu*4vwlbVcroXuv2$ZXAKgen~4?6u2s}(Ie_T!*_5M zC(pMIn3?^I@FkaJA_+xeR3$>}B0&6;*9mxcID!O2Y&R^S(E@H9VnSg7ctvqUq%x0oahUf&p`_HuiXDH%qMjn^ zMPx^ZwVXk2)fnD6zT6};s7`hjfKWgJ&W?7q(azYQ5u>kjf%5jjw`Cca^=M( zx{I6XJnK~yeOG7F?e8W?^nYRIFz^RIs5UtP+6YHIvxvq!W$`@&4|Y_6h@~bjqd{0! z`MZgM%*;vTya=DR;GbWx2tz;^c#!~@Vm|>lLs+mlMH=F5>XY&vU4B;#l zV$F!;4ppuK=ZyQ|{r&_vfnnug7&6PNY^p9VCn1fn?hq$1$vC79UZBxWg`>2Z=StQh z(BLX=@?L6BZ?6AP6U9I1IQ{{3BS5hr%++c zBEL=pUXt)egU$deUg#5dLriD5&|Mug&;pECjY}_pawq8<#iLacWk-lBlj)e2uh{m2 znp;F)sfr^RVQ=^WW6g)7`g$MWGJhN=xk!otMPQE+nMF_)G3t;DLCAp;ag&T5)p5k; zG;kuA=h3%35-3SifN8)tA`(DF-}%N4v}DbUIb=)7g$vH39OyC&t0>$vxT^-ywSZrI zUz{cyeL!d=Wd!QrJ>>W)Nwt*naQjJ}oFO>THL5enU>Aj>wB`_)uD3Gl&<9xb42{f2 zIdHvTnqLDPqD~jrAbMyNBAGi~gcU`DkE|+~O9&wjv78dO;${){{lzIfOkfK#hf8OI zj|j#HH)ZB_Cq>{S3UEYk|CSIT>+LZu^*;Eyu%$kr8DlHyXNbb}*0$8gl|887XhPdg zz#IBjz_+pYy_N2Xa%Z&Cr6<5hFd=<_95a07++{=^9HKaaJx-z6m%G#DAeFc#pWIxm0%>%!a7%U<7f$@!6nB;jeO7WG(>#77R6E z0p4s)sg_ujxLv`eYgYKGtPM+OX-DYqDX)6>{mbS&b;GmE+E?4%lONl*^^?1v<_$V> zZYen)T75E)_bf;GU%hL}jLYrMS9hu2{rMXUCokVLoi{P5qC33EiCg8{($;$PUgzEp z`2TS3ZBaj(7RC0zt#zec-&&W!Bk^%-UEOL;L6IE8hWY3rhrS?KWA|;NtMUD^Hu{ek zvMp`&@%ZUermOzC9ZU|Ght;8iPw-5hbvAk|rVK9w$Tekn^nb1?k;Rm5jTDxA`%VuJS0hY7bcU>=Dl!{lL?Xwr+GSl~c=KR%^9 z$~pp4`o#(M=XSc(|J<9=B6*N~5#k5VtT`2WY!S+k6L3=6ofWz}jX?*0q@%tN1y*#_6Pt4a zgLxx2T}gM?k)3qs(MXI1w^$|ANN^oGdKVcZ)wTXmg}W%6W+=gPBpe7=m|Az(Ih}O7 za#W%)1uzX9G!)42=})s8JL$3m9b9PF6@o-{QFa^saZu>8VhO4qxABu@-sB>t#9bnh z(CclllRo+fT71xBR~;;0tYgw zVOSJP$nG*4!pTg@+{N|3D$d+I(k(!Ua0W#=F$E(53Ob2{+!9a#oS^E)=6Ye0{wlak zfrYxKQrw^7p12R#|5DtpWJ6I)^tul&Mgx|`n7L#3g zi#87|fHqi~sV-OHY2`rQ0&Q53xL!+XuRV>AhfAchfyjb_A>) z0Z;n?1gV27If%ue&yVp6>yob!JBzkwzjndv=h;_s3&D8csFx?f@3co&>GETD5@iTx z$ng(M(>XdinGO7y=#XOoyYcJ?n5j@F&0hJiVSxGUlU2GyIkcacdL7e1c2F;TI8{1T zBGijI&{i|xTW97(8p{&l6tQyF*~7c*xtRDny6cJFwf4jw;GFC2v>v)2-j?^! z<*lRx>>!sO*p=V`y8|B%#)o98Io+{7_g&$o1ilw&C;8$)AREQn9EkBcnFZw_M)y<< zVsuY*IbUZF@2M-%=s$YuilKxXyG0{m{Q?~PJ@G@3B{4*=;)o=u{_%4J$37S z(K;?+%6@C*fSUqg2S(!5L^iy!r=?g{xpw?w5i2y`7uU!-1Ql|&9`#e^5$Pk`@+B$}g&hkL01T7> zl+wF{CZNJNAd!UOb}y?LcEE)vmwiDq%2BB%pD9>q12h8U#sDqAj(`e;5845o7Zr2X zUz~Lcj3a3rctThU@{mnK$D(o%V7B8s;%Sg@qlRgc3^uFmf^dXb*9tJQ5H)pI3!07N zI=o%eM+g1fFe6YaYF(^1u9yL^JU83f5rTlG;L0oLtJ}-I+6bzglB6;aeTW>9w}OW> zPp&+!bsSEjhCPj3 zrD%a#8(JVnb~R@}soS0GiV_|cZ4eJ1EDo;9VIp1MPxtbs*rok+s%5lS0Y(>W7U_rm zte@`UxDz`8E9iM!(O-9@a)jvsBH^+k<{^oIxUfg}*Ijzb8KE9yy@#QqF%we^5Cb(+ z3}D4otb+vT1gHDky8gPN#m#hD@aQ|)1H`zEb^Ues9k{aB@+&JqeQTQ?x;wnrY&UXaZNx`9%(oMK=Yu( z?i}Pi3ZOpv#)OAr!%1ep30Qb`Q0XR%fkRsu^h{gvR-Qe1!d*pLz|WQiU)=w>&_w}Q z=qI*N=hT(iF@xm;P*?^rZuErE*iW$3`|MMLb;Sf>2~E0Ah7`k@LteCnBpE}O21a-V z5(XO0WJ%Bur-{gkn-$2A3seAXjTxdV{_NUwcaVg$Bw#zje{d`GQM7%lh+1Hs}x8T{8K1)`m(% z)C(5NAmgY7;jQCo4Uz|Q+%wfM z4%gMkWi-5W3*-QVsNAXg5MvoJ;)m$4yiTZW_4Qoz1049xE@uso?n!lHp4d~cqG0$Urh zRWx@E(P!Q&n+5AEE)KsWo3llf6AMukArVNZ-Klu4FVkw8QF}uF;taWc!Ix>!T%w{} zt&k93E)WD+=P+IKafjg{mn;}yF>W)ha#^4lHV!aI9~pk=dXEEsrJcRuXdbmD>xemU zP&)-4n_*r@)$3F%HyU{kj}kC0qtUbnED7*3yHwJxxtf8h_ij3111(~#!MUhlipdbk z_7Rw9uIY4Je945Jmr($c3(j!Dl>_i)&vw2`IPz?y<+iD$^43&XhOcS_o-R74cJ|A6LEeJ zaGX@bkrk5N2wO!m#GfcFF&-fMI3+HR2^uGF&oN-TcW9Z2jU;kN5h%;|x^QJAp`O ze=N<0U@HukbQ1n$ae!iDL`(WApfd*V+3NlE;8L9El;q+mCRzxK7a_|ukoMPq@!qk! z_J*n2y7Q4+A%vtdEbFhveF$+!u@K)%>@A9q*j9pHJL1XI z!SLcf0tk$H0}qkvexTm}z}$M8IopAC5MmeVhANw9i^Cwf6F$L=*qKfT;ZpnPf%?R5 zZk-sb#F5x3j(5%%0xw*OXRW~!+i$Es0>^2z17B(dWIbi4jMWE32{6o%uz9Q=3>y*K zCWAZONn8%%jtA+E7`Xio(xa;70CrYNRowLm1>jPZtUR3^?NvDCg5AYOS})H+yn$*2 z0nf0yP4=CG;LYN9)Q0`7DH^aup3OU0_k_H}c1=Lx(+z>e3g?DEkRu!+5*J%p5-g|8 ztnETs=tVCrsboRBqPrp)pl0BCLMtK^MCr5cee>zc47N8?>vqj)!!ffhN%v+fAsQ|)JxSNPQE;?sGEpW5G zHVyRTM7^R`q!eZ$DFiDMhUK9$I}7z}yiEFmkYs_C=)CbGm=ACB8~iAF5L*?0Kp?US=C~<@Nu!uf-a<#c7S7Plj_nCc)} z;}5c_-%G=4B$|veazR4!Yvw1%mmd}GA61Kh6lOjH7LOy7^Fk<3?skjv%49?nd(NFXAa)`C;r5}*pu zc3h(Z$oLBHF6b~0U@Am!+ORvBY_50MzGfdiLbnogAxerX`h5soszi??KctK##AVn4 zB)WOxE-w-+B2x}>e$y?ei&717;BhQm-yA?30dU!D4biY*!~}PqtImCoMs2U$GS|@p ziZDhF6*R3aS(AOo;JGY0Xcyo>XYmLk1G2?sq)OLmJi0y*Mr8WGI?ZCJMe<{=i-{&f z3JidN7$gJqIOOtJ-99x(^R_o^5umRIEki4D%|M?#v?6%c>f`ieD2CS` zryrJsP|2l)BMJ{hd(G{Cj@Rv*O_M_|f*EAV8$Ejz(%Mg#v^cuTr>g~yVcuzsn2Se` z*XjLVEJSvUB6{Iq#uDcce*4|;Bw4`g4}u0lA{@CjT{2Li+b&SNk{z_H%; zK0%KIhAulnpVfH{tU7L?aBZ951*inb=LPrx5deZ*Z}U&ofA$ytV$VHM?}u^^o`|TT zP4+L6#?V<;71w}fou&`{8Q-9C|-7+8LPC8$oz;cVv*TY)L zeG8rbg?kqO#rgbs*Zy+8KB;EomgTtFkMje(4LkF~Yy!_4!P3QEDcdo{n&#m&ZJM%0 z@13#{236BMSZYN|%eZwpDHp60SpW2&x=SRU9uS?@+e6YE(n0`db`Ai|Iu#|4;?PkrvfdPT&54_>zd1SH}B2*FE7*Y z8@|7Bl^zAFp!8}zzVCCOcFKKLhFCEoC&7?0U!DP~?D5PTLvQcCS|8GU8=|pf*C-sP zz^DE3YTdEI(J%1I>kuRikd~F}=b*{DvY0v#+_RV}!FKzn$@*K+*&naboeDD8vX@_@ zd+hrOcS$MM4@L)_47v|s^n&+s2B@UV+=y;fhRqLRAPs-v2k+aDuhD&r0A8H2J~c%* zs=}=<1>LiSQ}zAsU9*e!nW;Km_*VA&_Nn@X0koA6VdTr2Ruv#d^UI)Gp!qmL8L>m? zC)5##HrsfE?u-kZ^o{x|4HES1@~OH*&3l=OX)dAjmpYe~J=Hn9wU-8P;M#5%y+G z=$GysUKJ(adKknPrMrYRQ=$}@nN|L<^giL#D4_)tMy9)l)1riyOc;~y7EX^6VCq)+ z2c)aQSy6%;d~_YP9!SpyH3;p@Cq;r#C@>6 ze$LIhmtXv`&-1KNxHQ~uH{Gg-6#uwkMIvk-)MCUFcJ3p(!Va8{IIcDJ#OZp!w%^0T zMN2eLtNd}52%OIg)dgYQEB4{(`Y&bf^B}tA(aB0^3#1qL3m{7JZ=w*umAm%n86Y%- zFCq=9`6hem487mJjpX6*?5N;2k~u=s0!b2UM3PWtKG-^b5Zi%k0)j`#18^6M-91Ae zUO1CG+WBtnp)(O$_LDttCRq1JcJWMoQ@@wJ;yj8)MwQ_9sR_YK3O9tZ;H{T?>z#On zOEP|lb?LSCe5;SGSgRT72TbBNiQ~XP86^ji2n}hiZL|n*e@Qol{sm#fEAH|$Mr(3{ zF7_}(0B8a>fxxTy1>hp$k(lYMBQ-+H2EBt_1Q57B_F|9) zVD$&-1Z^7B@_4yP1=pr2;n5{%cE;^xK##aW#TTaCU^mUuy`3tK&>rmV@xygaql??# z=neI^unn~BT88*X%XRLQWmd?q4Y>wEgh%JXv9{Z_^cR`GJ@xl@NGW2=N~FncH-KfmQIsT(Y!5eu|ZJ1~MZ_R=vPMqgP0shFINL zBuFK9jVpkX1vH}q7KJ>Lu24h1hd@9l#$S|juMd$n+640>`0xp#VL(Y^0yK5y?fQ?M zq!jRn&PXm&lT?6Q{gCO$+cj=XtH0z9{k6xNUUbxEA+L794TQiHjln7JKx%zMH?0@G z^H_u2eFD)gCZus+aW4o_CdIHF3WLwrZ=GvbQlniFE>(v+piCibA488!+zVfWxx!!< zDU%GoW9lLdA|;k%-E{Z*yfO&F3#fqy02Cvo8^l;(K)jUBBOG9|?lYNu^e+nK#*Ru7N&NJf_%Mgtb^jQ-gcS?$w>0ny%T#3 z)Pa{Zy`8~J-0Ux-g3IgBS4p9Hk_?lR;3h@a+(Mnf{f9&*Ociu-z2;6N1W5r;oQ85^ z8B=-cM2JBJv21`tgv5fsw}J3C==!JT>5IIY$Cyq^qZ<)76p{%$iuF)Rz5-FAWVkod zAN@ZIAYp=M*tH1zD27GQWQ0a>qwu>5mLrIecc`U&{$;mNe512x?c%%jaBqj*dAF__ zE*MEkaHZVq=!a9C8KA=@pbAnqBBkR!BN8?3htnx&j-0R4B^!0B*?p;I)u}1>1@rBt z^YvITTe<}Du^5uqcDffP z%PaQ0d$E(@CA;=s_?kD^Pw&-pIZ6nf0rA3+frHe&LOt{_FXDlq{J=2^%*j=1SPjtt zV!B7^3=jc<#py|eq)L8zec-u-^~wRq^o!D0N9i@0556k^o)4M;@UDPCWVTc^OJov= zBCe>7OK(6r^XJ9+d%5)ONQc)h&Y#bXYf=&A1c*14F9m84iW!wyiVsanM4&bzoh?L= zny`!&5nWN6g<;ZFy$EO|5(IWErr;H>aBxKA*H}9%W|JuBW&`$|rMx^6axz$Mi|^Mj zrB^Ut(tU&5~Y zgL59zTL#U?jjclv;_X-Kp%P{s9o7>}2&SqME$i}*f-%L1-~tjZ-#_rM?pc(R(KbG; z%WTg_bc_9SQYFAw9<&)iJUVRODysF#ZXIsS^;;*WGY37RZL>(C;hx` z<2_}EJ+B`{*3X{T1Mt&fB@Do)?IkO9w=qr)NU0HtcgP*7??_=dEF2T^!-XPraM%y* z9x);q9ovVj5W1RueGGNlgu&Syr4V5g|Yet-M1Y16Y$-f zlTN^@ONb{5nLgCE`HR^6@{Jw-qVCk{JzaE{k1)TK)RGS`_E&b|i+azYs1|%JEInre zE-Pg_A5%g0C9HmQX0RnJkb@0Mp(Y6n9lzAx0W&N&l>5d$v|2x1vqNJu7`YWPxIKBn zPM758Bz@tM5CxOT^Beq1CV4d(>R<1iO8W?lU9@h~icR zN7^QGx4QgnxVR<1NPGOUTie6e>T_Ctms2Ct_h`FzEdt}e&ql7?T>5q(N#aW zPf-V9@!+bpY&$U;e$n=Vm-M0OUvqM^fm$ON6I}59a{Jy(&@gcE8X1WQ(cieF3^I`YTP8sU5vCu1TjC1Wc5aC)T~cmmt}^YV7V03u)%*@h zEao3>TKUEv^fJg|lRf)oeZ&dhh&2>pJVUxvVsPoQj2fuMl}AyrU!p;XGJhi6(8GpQ~l4hy=4O~^8HBLr#I+H zy+4O(f_+0NA=~zjY*UzGAnHDt(c-))z+6U!@8hVXCHgRX@#fB6+%G4K=D9ia%)8?sIJ+=a6U@FO1}Gyn?lVEm!req}3O)o1sZ!te&-NKpAu zfsaFnFGKB!FmweXM%SqAL$B)2%|3z#8#&-GEA7@-^s(EHH^nMw&Ux%OZkViGAt=52VGDUe_Jl#dPK98i(bR6_Zx4 zx3|2m>q>U8ZFqu^g0UL?hVDJ!Ym5$($ge-r#W>I`CRc~x8{iDfe9afeVf$^;Y5Uw8 z+LY{e^;Nn0UO|05zjjF}S05Y%9+VWJXqk%~hqyl5eUt88+7tkkhRc9WbWJz?g0K%S zEQn?j883S9=q5cl??wSJunn8A@CbvM(5 zT-lau_4mGR-|H)`<&wD~oe^01gyueurj~q_`ICytbMLP*jk^4AUj;HohKgWzWwX-~ z?Mpu+6fzef3|#(r{z@GYbaC1gjG}`*Ms-wCF8WblHXquU3 zaCHA(&aB2jA>EDEHMz{5>23hyp#;y%5RWk8PqeLhQ@88$jpz1|`y6kuRQwcGWN8Js z&S~Tu`{J8=V4H|ha!wZE-caNT!GLY>mhNbvp5XAgbc5H)-t@9AuqPw2YIiQskrL#R zBH<(;fp^S%OAq&VX#37vy2EHXkvteJ5b(lqi=(N+zJ0*r8KET4;`ssJNecxh4z%Hm zy39wVC%vsZbp!^v8iP*48UV|Yow4-XL;eAF`!?jx&Gv=2v7~d0-TAgYKmS&P&$#v7 zp7oAC;jmJv^3A}+dw%=3W zh;KcmOT5+gn5Xn<{_Vy-_LQz_xfbkH}h1Nd75YJ+^2Q#e97+xRkr#5etWy?X)Fp>3Ep72Togl#UpQQuj+}Vu zG9eg-pYpxZsxxVJ)V0aVlEQ@N7jisO$Y`&8M)$3}%>hu1(_2W!K6(#YY^IBl6~cvp zy#9=C@NYAA=CitM3kM4tVtY6(rpmtjtZsLTAd)^^V)brf6Hmc8ZOdBtt!@7X1SmdWFK^Io{n^Ie*#IBIgZA47eMakrnQ9+&PauJZ>^aMI zSl~VdcNqJ`a`?f{=j?06*=Nd{6??wQ*Ty9C^Yint_AHdO!lqW}iq;P0aJLV0aN-G# z{&9ug{~XswJoAG-MMc$4!_b-WjK?&A{prm#MpaSLMYK~b6m*gNjR%&Rn9ql}*0^uDn8M0@xBa>vA})-U2TQ13NXH?AUhK416pOm)wLOY75A- z@+#zc#|~ejJC=URw9+9^0>otIrr(Wr;u5`YQTA-#-S*Mu{^|Cl$8}eKNi+!0Jg(2@ z3-EtEE5Z2-tOOo5I-ua7u^XSzg9}iJ5>?1P{UjDQHrlcEdRWJ7)s8cuS7J9p6$lyg-#>@C&h*lXHusUD5Dla}gEUDzA0poux= zgg=txP5$6yc4KER)gy32XtQp~(Mbo1owroCwgaBThW%-F8q%w>5CZW{!7IWtJ5tC6 zaWuwLPhw4QqkZp55YG#?d>K}hR@?oS!I%28ov}<0YPW$_EP#sIhc$~n1TdUKTaz^H zy`A>Xq#21r=-y14Uag)th<@b0BZc$IV4Zuogtt7;^u?XO2j`h89GW;O&)fj*{?|M+ zSTDmqIQ!F;xUT2Kd_zye>U^^WV9YBpoxD%&@&eP=d(pmKU^)V*9|}y*_N(Ei1(qv4 zM%v=3J!3m4kQHJS!a`Ga(r4F`P=F_*pU&tnG6~%ChXFp!tyu8eS53ajJ{nYqXm9a3 zt1)IQ$y)ow=lUr7>^rgp7MMIJnbhZdVdaDc`1VlxLh29}r}css4cRJ41eo!_=b^M>ul_?AI1Qs8Zq?X&|7 z;T8Lj9bgC#8++XjEMdH23wP>&W5BN1si*gN6^{J_f#>|NHO_Cw^vK8IvSIskD$6m+ zDq9>_0-tGE%Nb|Ke1Vm>*XsZJ1waMSUH)Hv=Fm5wr*j8ybGogI((sT#)}j`}V_Q%` zAs4!huO*<_E|1&7gk`_nF6ho9MBVsH6+yWdw3q8sdAzS30& z^#_~n&0it*c}x8xU*P}+xR2WI*2fiKa)1iG;4S+(QX5r@JTX$oD5M!2ZwBZC_N|GV5fegt2)3R)C@@`%2F&@^6KMSGpKBt=NayvO2vCGMM>Xe*S@cN^0b%l-iN1Wy)FAd zpJ*R{7h_OsH@=JdH`;IC)f2o0_KdBdrv>(+t%!rzXyDl9uB(C?fmb-sotx9@q5(hy;c9- z4|<7D0-Eu&p4jzOQ{?0#MJ>e0ZKkMG0)*~ywz$(qz<=$)U-bSgbKx)WvTn7n^fn#s zmS6OB_8%YUd1$Z2hx(sr>go@5Z$N{$(`<{6bZf8CcKZlqy2{@75e|pkWZQhKk6}F% zKGuT~0AKg9-hl3%_lbU!de33o^?ktf*W1OhIPz2cY_?Z_s;6LfH2X|{@4avHKS#k$ zcGTy3{IL5xu3K`hL^iAs9R;gnUa-USF;`&<3eV-jZB?Zn3b!3UzHjFlGX+5RNSYID zkpk2D!d5AB4WM15%veDCoidA&;X!S>*+2cNCu4o+(_i&+@1q$HnllOi<;_jG?cteG zKt{Na*U?_%nFGM0)_Gv)7tZElQ!AXT*cq1EzNVl|KY97rC`NtTA9aj0#HpU81ojp zpwtY*TA6*n)C?H#vI0UO)Zk(iK1y2#yWk>a951j-sXV`oUU*curr5EqO&|ZKEA78p zo8C#RxnUC9!&;l}{?evtJG+>}K>ow`F-KzS_>_H2|F(@%+ej>}q0(Vkz?7|jh%>OS z?qjN3Zdtv8J6)3@AF#@VYr(sAHT?>=`CJ->lX9CK-xZkIQh!BP)4@Yu>bhZAHruzm znK9l%+rG;59JvrDQ9@Xtfi7YGA>fSLP+16D7qKM>b=!#Tl5|;f%~8(e=IK*7?SKol z3+D*g3IP{xB>;HhGNa!Afn8T+It2J6sZw1rQopY{gMe(jvxgJHw7b@0=^vP4c=h2HQ#ZOzFLAg{DF72d0M zXIpbI-p+1kdbE3$S`H3>VSy=-kc|GTN$Cnia4c+R*7yq^x9Lu%m0QJ7RP?9X85Q7u zAKK*=W^|MEqV{G?{!2eMB*MOkC^@#hIX(Nfti3rHomCx7P5vzQq8wSS>tK2Tp85`E zLjDgd*BXi4JA#0}w`X)Tf5^XwiCvNSTt_qBpYl7fjP7Lq<~?NZ?_>sfSJ|zdOgnF- z{l1eKhIu>y2g>G8XB90_#d#@n0vOinlyvn{e}D>9OSC`d9uBLG1O!YG@)U|xh5WM`bn5iFZby?`}dxvjU6!z zSMaWFmC8$7U5@7Uo(entwldm9m|CC`L^4K_XuAs!w66{`RUPO<3L9bC&EnbaJMeHDAK(rQZco|= z`XgcRDx`K5j1@csVnk!4u}>7XHGb(PaJRCeuLQ`s52#@D=J-a| zJ-Txb2e%gvX27pA*M~)Qps8#fR8ZQxwo%75N=~=1XSVeJXm4l(y1bWkInsXF#$14B z5a&R9TbXI*&r8~LZ`0a7TV@8?KE2Jz3UO)GBI12I#vM1VRHu*O>dZomkb6!`PzOo7|H>TSsP-in=$f%Cqv1s`@~*41heiz``8duHS8H*4Se-`vOt9MkixTa<5(0}xAkRxm3Jc*vAsxOC+LlAj@RDz(G&lm5wZF6{4mBhF zg-QFO52NUbp{5ez>&>B}W0Vdvo&9f&JkmKX}|8y{~CCV$WQ#dt5J>tkfk8>d9-GiG}IMhII5MaOE3o zp%f4(VdtRw_EJ5a@i{rZW)6)Uuk35u^pYI1r9ZAip_W8YkLEb&ii7Ti>QdWkr0L^5 zX{$$?LHkKTFhm7BRgwqbl1nKQxH5De;=W0O$XpPu?g=^x{78#OBDP{F><6q*q;>GH z{dJ@{$G>WgJ$FAdiu%+;`TjY9rs3poc>Si-0SiUf@065D6AnczKZZyRmark59TzH))cXGlcwoRrAE zH`uGjnC0H%c5G<=-eOUq#37}U6M82SmH7xQT@{)`yCIn|n5c%~M=3LrD{8clITnaq zqxJ`fuN_it&O80F!s3AZsS*cWa#_}g<;6#=!}^fp-~e=flYQv`^H;nLIMAGdx9JB$joh4sF75@-2zR9iBV`Xh*c_VP>G@-PF&~zS zSoXuGaYGCc%79ET$mMqN!5G5z_LGC5POi6Ahd|9(Z%;kMbivORhX6ow2UR4YAqbl;UEWp(%730H79zv+U+2Vdf?5WjOtCQ^razJlvdvjS?RnZjMRcniRhcuBnBZ!BDdXhF+vG`k(_o+Y^s4 zU0XNFMz@)Kx)q-Q{<0&$Z65|(NAOfET?IZJ&d($BXmKPOe8^sQq&c>8lbQ@iANH*a z_h6F}wYB?5)8n^I%BO)xLH}HDPd`eu$Ein|ebTSN=;)m&<|dxri4uqOXr_rcU1DE7 z3hghkqsN&x`5FFl>NwLjKf_Bd!&~rrk{%`_0u~WY-`o4fnWOS!9%g?ThY7pMc0JlG zKy4e2hLyG1esr{1h__pgF%$9amtz3lX4~Uf*a2_YM~=lPzh>V*7II~YJ^VO$gWj++ zkArwwV&6RuuAfqB??f;q13aiA{P+b~Hac0^QJ>L^?6{Iks;iXM;no&w*yzGYr7+y8H7Eh%fv z#mNq~-2`)+zZHV#9|%#}FaZ+wJ=<=gnFR}U%4^BqwsE3q4n=a;L~}e8&#~uV;;y%6 zor4VPW}a)_1-))P*NnFPYoU;RZV#1Qo2>&a%{;x65qCdl@nA(<`#o^0~)3HGqKKT2LeQApM5Bhn? zwWe!e+r{d`{L^BVj0wdN1-ZX9}@xvZ5dd?Bw2aFs7G_U-FT zf8eC#dUJC0eF{B4?)&}5UUIz|=$N8!R*gQ2i$1-wEP;AxXRzCGf*wF z=ig`=yR8yEX(M)t(M(6UB36VbKNzQ8#fLgP%ry3*o6NsJM!Rk@=i}$k)6B7U?nUNY zu-cM~&8hgAcrkngFW74@h9Bqyd+)`_{*vu*i8;I5T~eXjKX;|_RpghAZv+h2L6?KC z$-XiT9*p;Ghnr#by>AEKYXfm?)eG~5Dv70!xVOn=*A5?oB1?6^thU{0gkCqeLhVAoHAfxq5vpJcAb+_~U< z^B26mdA{l7V?ptU^D$&QleX_a&H1+Ltsv(2?eVvo3!B4(>#!)k$ZzdCx0;T!yATqd z_oy>k7ji#VfUb5Nlm|=$5f`6D}p(mgE57VKF(vB7d z3U{ICt8Nd)s5&hd&dVMO>{COZ*V~onnI3lCKTLm-Vo?#sY!{tpDu#am5!+qu@~Yb( zO_mKuHPtU{nu>)0s*pk7h25d}ci~vj1Wrme_Vn}2aA4pz)WY`3wlGh#jUM4YTxfs( zCye_q?3oupbn|(+=}?r=dpmCiW1HOL?0k3C@3fx5QHG0;m#986p%wyo}z#! zD(L@LJ+sLs1n~cTpSYRn>F(;Qy1J^mx_Y7dV-)@Jgq&CHpVR`;C(&)J>GbQgT7&Xo z+LPczzNa^z#A@;b{qm$1Le(FBN*j#o9(f8Xjk9zak1A*Fe7wUc6{Oi}l%>P-E~_;l ztVztC76Q)-T;3VN963ebgtQx}>O7$5S!z2E1Q*6x^R!OtctP*Z1If#zL-Vwm92`nO zmC7`ov?m$w;v=^nQs#qJ9-ub!wID&Hftz9osT8* zAXy8v!P$Sy{Rxj5%li{v+=1cYzU5sGdw(K^_a|alNf+Lqz$=!^V++8b9isS!8t+eR zS_p~>$X_pn>SrIdc>!Dd2;TDoI76W53*cP#(|0dG2l_W9E&_qNl;36%_Gz#IcI-v1 zkqRcN!b|9aBC7L}c6)RIGlsk-T&8DV(&iy=@IUC8ebnPW+RFiZtAP(%sMu;a4V3gt z<`6Q3<$~$ZUzE5Qs^&{nxL6yU{)dLskveboGsn_N?rHHgh{iIFIxo@sP^D2IQfH{; zD3lL#+))s~e+7N4>0Yb`qjCehU5yj7CE$Gp zd7RYvf{BOf+36&!kQ?NrGCK$ZV~9(BLN#&N*-bEy$fP9?Nm5hvkXDEzT zy!^V>D8<%8WB>r@LrOqWV#tfX()X`xO=5p$C~U=t0*!N2{|)r#k97MRnw5@r#KGUm z_uT5bu3k180(FdcG+Ofpw5a3h+c&^jouY~>HB#~Qt(D-T_ff_wtwr|Z*p!j_&f>i< zIjc)HWfCPP&NL^5H)U9&;8pa&Jhem0ldvx=n_0$Q3aTj@t6M*%?r&=M3f|#?LDYk* zw4{K&t@EAi_c}ZU7l65rHL7y=xJgO*7Ym3hkqfYvrszv{nly+QJe}7~&$ZU|PCe@0fLR8SJ=DV(!RwT9#HM zeAv`qxDF!4zWfdAvJ_u1Cf9)4KH% z`@dL^?#DLqdby${ZP4z6OJERlx0!BjXSs6f28eL`Xx#?visJy*1}*69*m~gvhbPN2 z99Q)r;ml8=)~oX#m>@XMdQWSb@RqDeod6hIKL6`M+vjbB_yE>mBZ$*JD%=P`?JYXL zQEQ)$YWtyM+s*T$uInA!g1}mfioZhLH)%b9B8xX^-Ee;3`%SiZEZ)bi-X@y!zV;MG zG-0#$T!R&wX<&Xpt~act?ol})IxrR*Yn^~avHoB%nYYcc_?6JDqRkl61N7Hstw~IY z#EUgBv_%8sf}S?z$u2|UQ3j3Mg4KLBy|P7n5Xh8VfMt9;Jz1b-)Bt3-kia$=FL_}s z!mDwBj|(beeefYEOdrjBM@ygs1zI8+bf!S!)vT@P+S&B}R_#%AO0y5ZiO!~8AAlp; zN1uEkvFFkUTBf!g*i%52w;_IOe$F=SL%yt0-=TF(0E$5UWGjd5(f)u2?9e_*m?eiG z#vTGsAesSm{t&y2Tgmeg;LM_$A8DDXTV%4I<&-@O??Yjn0hEul#fg$Q$}3qsCR|}- z$pC6ToBe>e9uqE=KsNJx7Gl8wiY?ixC7=!Kc51`YQA7pg+iZ{TT4#K5 z4hmN~wA=+5a666J1*G3WukOOUJ(+)a7r4C2utDMVO-g$_K~_Tw%agPd%OX%CW)Jps zzo#4aAkTL+dJj19<1}p#v?}}P)E=#udQzd8BVcoN^Io9wA$okT)~Vk6vbn2OI7wq1 z3HYFPV?N2*X9;P?xPfIlmX;>-*GrAI7JMR_>E@=&OBTsaBI`zm|CgOVxBg zD8vEkzaKLHY?`+pRh&&9?bq7j;VY7;^JEb?s9hq$!o!b+vW$fX7D||qNb?DYEWwfj zWGVH(a-qEWzY={e{#T+;m5=3o?)I@1M(+E#ge;{Y4-oQgkd2@+n+eBEku0sXP`@k)bTUS^0#UDXP`@HfdTTi!^Ydk z?bY`ZR^J^8?fMLQqaAelGY}*MD}Js$*ciRT7>ikmG-1gXJ{wlT3a@N{W(r1vVc1?%YIRJJ}?j|N02f;eCs~$*3UDD-Voejsa1c!ls zZPtJybxl6ZQWKlwKMAbA?YquxSEspUz^omrJIt z-)K!jHZ-t8+&T%3kN5DcS=jzSFG#4|No=sesb)y%s`0!89nQ$OWy8Q>+F?-Fv%@Ih zF_=wRC#2?50mxXO%Orl8B>5_7=-D$`R<(t88O95o8xS!wT!08Sj5avl*?5r-pV8XY zeaUG*)Qtae+K<=8cKcbay~N3auP;&O|7k7ipe5)s)mZAZ=w+w0WyN(ZX*8`uj^tMy zaDee@3AoqjG9tTOCDLv!c1m~@xQ}`8&}zUo?LM{#vD7D;@U3Ax8BplIRn%0<+Z*MfC%)H`LeJ|^9`n{P<^}(W0S@2` z?+{DdBu4d_P#N%c3#UON5kQMe0%$XD-y738BP52B7~Y*L&I8>?Nr2VQ9MepK1NLxf znAw=-=sRVYuQR44Cy9{-T5^iAzFOv5L7PD(;u|_Ms`&d%iu(#$?itkfEA0ljeR}dM zEDO)m8hlJniJ0fu*bmbd%K1`D@ceEo_Ah(q%zOb?_WYYI8&pdQ(B_Q#3@WzGVm6zRyxJwZ#C7b0Nl8IT z7<9;s78~UAj@C@x%#~z6{FUiln;*26jpr~1+Q<}xAudLybO%vvnhYKb!_V|z?UGJ2 z0wO(a`b6v-`z+!IOT{oLUxat#s6v1LfLXedYMs-}#MK4|e% zLgtBuh-TF~qBp^U9nq37Voq8Y7t*S8S_5_OPC9;0tD88V!C=3}!~>=|uihucdh=ZsWS(_NE8VYssFxcM*cWL(1b&(Po6;&D#!5-^;~1q4d1>><~7EFfFC6 z5_%2hfxh$eE@+i1u9#aicjk|8e0Iu}`_~_rcWwT>;FJ&giAEQ+YU;Z>^}e75)22+w z`|N{>&#qe>V&PoLoqF=?t&28pn0LfQb1q>1ucUX845n0{UC^>Z%mo6{X(=1`i9nv0ev@SN!6$&i+@nd^eZ}E2^by0Aw9k?)cO1zxd_X zN0;7~`_Xf47d*41XwJ#|N*4)AB1;Z{1_4^B98LyYk;!{{d_E$b4*#fiQ|3~&pR}Fq zw;9&R(b&HQ!^RE@SaYrZ49072e$$^doPeB5ZGY7kc$~WJr4zqux2Bf#Qbf~`H=l0& zO>2MmPf}>k!Lvc z8A2v({|BVw?X>L=xi=p5r@;X(+|D?F#U{mbE5em=uV0$-)~kQHoa~$S%zSsuIKT2IdOmD_ZIn)$cCv z^54iV0HKAv%ByQY^#KsK?LxSb@`aHKo+37Lzhefs#sgd1?eVxoRii{bbau}u(W+8; z*9I4(7Hs21z{8XqpElFMC{ZosAf1nu7)zsIf?}ITTT@FqOQK1XHIu*S+!JcV9mc%e zs3o@>+j|aK!y;}imY;HqE5-_5lv2~3lZ|uW^oS;!V|Qe=CNj{5y_%?Av%KL)hoGi7 z;SK_dJ9XvF%CE>-n_Pn1xg~i2|7O~*jhwb^$}On4bLG5cxq`P3AjMe9di3ZY(A ze8=b(U8Gjr{?(V8w`@EAZMWR>3to8c`@9*iEOkgswP6Q&3P#(gHuKHHUmg7Im(49~ z3iIYi=id7E=*QE0hY3s&YPm3p;pyw}5ON9>lLk9)$^7HY@G%u8N-&`=Axe$Qt68bW z6=0egn<83hHz}#OZn?#kwtK(Yh^x^gCYmL^d9^m##|7>FC}w=hqqq@mIuY5XM&(qk zRFjzU80#XM)PM>S!G?W68=^(mK3gSW0&C2tB(~|y&9dmas`&iocKOX%F2YgG!Y{CP zm9MPEnj`FdRGjQr>gN-K@4WW8-;QBeB?pCHE{3p4^43z2F8;Pe*2`F=QF@HHQ5<^* zXCn^N@EGwN^f@=iqFpd=i4|S&csEv5#p4J*(i?v9(lrtsR+iG*I8nFad(l$)AVmNv zFmSJIq~GF%i6d4i1|A!zg&}IC9><*=7RUs4u#l#L+l5^V#9|45!VuNcH-v4OVwl_j z9{vx)Boh~V(k2G8DgT%uwkuHEFOA2ld7O6Ok-agxI5Bc0TBqz%@E$IOi_rNFZhPmA zLBr}NGeOLPW%QZ^v07agZ6DUnOGGg*)0#xl0FP6NVr!jo9wxkC?Mmzv;5851)B)`6 zg>Ov85jGgBX43v7F%Rco?yHFERi%uHv^52mUA_C_ z49Nj{xGyw=YiUtmEfP9#jwM^xWNAb{bo&0fVI}6=1Mnf=Zao!yZGu zko=bv^ut<8Nfov6XrGF$%>y(xRn%ikH+hBu-t28lH(9r}v>{bAX#GChSxD_m0Cv`_ zfI;P5(i##&`LPJfb4w`FIAl*gl#K)?Y7#|%r^=!oTe+5Lq9%$SlqRa-@l2Yiff~GR zhYll7J-eSyWQ$C!F~M|H_6zEej!w?|n5L$SHZfnJfkrxhYtcIm?t(hu0DaLL{OVd7 zb(hvqoPp&t%<0w)!KV$h`z}aS&(QaGX`OsigpbcUVOZazwtcm<*s#af#rrW@sdO@3 zRB1V94v(Dm52JPaR1-~fnh`U_lWZDojGgm)HWS<=9$MZx-)ldR+i86?|v@34Q_d@Xo;P!i#|~<|GbghU>=*H3NU0IO@pEugoJ-&{6%o~+!%6reRaE~HcO8=Od5ef7FLM${ zmOtzyVKd=~B(HN4X8<-iNxVMH(TFswIgQg%Ytipq5;SR?ge|GLFE?@$r@jSv=OkD} zB9jzFKso9p;mv`Fg3fXh?$;37w9;udZ{J6xInQaFHWfNa%JltjVK9Jl!bwtQ?EmB> z&hT7vlCa3?6x4#-H0dRzVgJPdGk>1lCQQz78cy=r?2;tQWX}+GP^!j9em{*gIC|Q~ z6pj4jKDPb#ViySW>`7BJPAIhT2*57>UEnfSVK0rg!4e{KI*NokC(=WJ?0kEMNG}4J zhf#G)Tr*ADCQjomFU`E5sFAhI1~HE369}R;m0#xbAE$d{yYk_cKPXz@&ZlWX(Io-b zl5=md7l43cPD)=P;s)owa=?j^Huj3Ook7J~AM*nYJthcNV7#BPKgcVhHc zogh>VOXWdYT}@QR`MRQNqKPj36XXo1an(TYWmIxB`&Mj?`s|%W|E(q(qhWc~MU}L* zm~57(ykVie)kTiu2?42Zt|2VP{{ccpHAF3R%AYkLBYa3rvc#a!_*WScN&uct$2-rx zGP8UUCvm1{nAAZ#9*N535iDnthY4me*+W5LvZvd$!lnXCxEKd*Rys8)GsQP?5*{AF zD0GsPnc;^y36C<89Cea7Gu-2lo3ot6X>#aiCrz0tev}oN4wx_nj+o*+eJ8$#Bz%)R zN}7Xr?zu8Ed>JQ+x05(fxb|{|ny4_+P*N??Ab6Z9_?4wedjF+d3#h0P2>$mt5(!-0 zM!RbXGqh(Bayh+m81GyGry1dWF&jmwCiIyhb|gtFsf8XicJ3bwq0VycduF z16Ps&cpxSh|B_*@-Dez3h6hs4 zx}tUM#TsWQJ6p2{V~Db{+9cP8H^34)Xc;^sb|@kle)1N0fZ z^YkhM`XVQ(WP_gX%s?A-F)O#6r&l_XV3?gGJ}jM;8}JgxWMncQ0`yqV%LnjdKEFgx z9GMHqaj}7@Q)+|d3^3jyIuh;d4VDz@(@;dKf9P~yLvc5*_Xxt)z?ECawu{9M>pvjTNbFRmP*EeSn7b&hu}IOj>An?icD0pEUqlO?Zfq<9savlmzT^H6 zKFsno1gjN|MfH#)hhz8J@xO&P$Nv`IY&o2_wr#l|Z;l*}H%AV~+Y(z2=eJ`0z|$Tn z!{eI`gsqYOheesKez6=G6J>me#rR^)!6c8=9Av3;lpv&%EOkEam;!~$Qu7p$lzH-X zgdO#O@q!HAkBCL`?NK}83Bx{HJr)tz7C`2S4z#I?VIQmpbD$WDxzaT-o-i?0e2dix zPm$7(7Y_AKW_kw$cpM(CJz3QCzK2S|_5j8?11Ce+nn*pGinh&P)Z`8`um-1rnUXP2 z1ov8UcbQ+8OVb7Ubp;=+wG+HYxBRFypx>H`y79L7%T?KJt5r@@vu5Ik*j=(0q3iXE(AJMZl?#nuHwPvNF1_{2v6|%$`g>EC8H&@yyeKpk}5)?s|R$K zV(#L5V8VTX-oGa-Drd~QSH41AZYucH8| zj2;^VVf1q2hkb3NZj0$w~4!zZlnx^x}Q6;Tt!1(3z4NB-7Omx zstKyxHbGF)tI9kiA9j~g1IcH+rm$9{!j}jgpv!kDIS94st5m_G|8gZ2 zk0<&nbY3II%y|CIRboV z6_LrL*Z40P{glD*NMSss-t#Oxf3u|lDu={j?GW%)OJ&png+{t~w$-FzYO7v7e z&5OoQ?I+be+xkJ>Lmq0@A9l|;TGrQ&WNUA9Hg3nEG`U_zvCXut&uM&**12AI_N@O1xSC#qtK}-) z7G7s6{JcZ#kf zuU~_Xm<2W=D5v#5??UzJUZ?fTt`42)3^uR>H;c;UK+j|74X*?Jwd+7%PF8lg(5LPJ zbn`mUU%xhV_2{;%A;vVO+Lf*Ye${orAG8spoW5DhJ5-t10l)e>;HSPXYhR@V?`Ap_ zDSV!U3xJZ}rbv}4BtjoW#yE#ah~^KFG4Zn4r`EMIX`!3*&T})(3VkQ)p!$XuIE|!amxKEhAUrx38dT#jDez zP3W3hrMiX&b`V*a*Cxr-vo8w1mSTN_M=I9Qk}DX44Od|dit=R-dy9LxJS}yh-Tp`| z^>gKGsf(%FCALz!9(HZI&hQuQl$EPiT)E;dJdah`s#3ZOYu+TXuEs3Xghd9c>B|AN zwg8}NmIn3FH9%#l(?5`~%0c?&TLG(DDOgu-pzOGMtIyvGVs=&Nb3Op{8rOkdcy;KK zX*vxPC3HkNm7mSVV;R>0zx&$YVZN^1T`o2InYS&jM-TR08@gJsYNQ%>$Uak0qc6q!IA6q+S#iuk9&A|#FZ*xF1%dM=8J1XSEs&rwaPEr z0Pv+J?v+D+@;cz>Y`Plw?Hd99dehTi*Ksf4%we&2_*RZoXRW&ocPy zjqJDA0l%_9f-h%66m9|d>Xg?J=jOgI7OVJrA?sFU02ZkRxIq}}&@DwumN>gqid7eG zRl2FuJk++QlC3WX*UMtnlRcHmNItGJG%!-Esz^ouRd~yF#BEAd#LT=+xdEa5w@G;C zZ&NBFw0a5Tt_@WGb|o#@v4FK@D-E(0H~`}r4-L3oX`;ewMcbvy{WwnZ_w7nh)3{@X*k$#SOio)6KJrI!qv+51|s&e(EMIk570RV>XhQvE*HfCWsr;?PD^@}Tdhkh%_Ns1Ddg>Y4N&St zd%Y{CiL05vF3qCQYuAL8XG>Y-z$)B+WxYDweT{lS+CN@?&mYbQs4|22<+VVm^KBD^ za;mjwA7G`H?ym9uu2C&@>br6jTU@yYZeDjqy{;s;)4f+W4w3A~&sT*%k2ywIC|`56 zm~lP$r|spU9Fj$hh3PbFptz$3l)-GW!pdOiuq?hnkF_kU3}z!~YpRMnDsj3z?jA7; zJpNPnh&y3gTq@6MB(ZbQxqD#yw4GYqD+YjhTX?T{0(p`LiF#s=H>mnuRN(=UNka#T z%)ne&k=J!)S%RGtu%k)n_%y!rL^b9i3YU>C9|S_PfKCn)J+*~i->-4hVlY(6Q0=oZ zr`)!Q3V7T&+;2@+hrucxd!)16LEVZO5s0=z0Zq+8WHf6Y*i`@&^?XfDn_QMJyij8uz@X)f^|2>>*@F@jp zL7l-{zwCFV8Q*osJ5e!EYeGI@?Fk{ys?!D-?M82dsu%LYVlSo>SJyfqjH-wg6#8h?T*fNUY}^n@P5K(#`9Q3+jUDdej^ zW4gm_Ajc!GKHS9hn!@g$pxhN~g)+Q2Vg%m+=mZz~%)@<$7IUxh0L0i9=qL)GP$hgy z;ZFgLMhy{-8$~z6`B5l~&=5XHu?J@K7(E=ePH(2727Gwec0CRYZMX3%`jrk05jQGc z%Di7x#1UE;Qev>AK_$AMuY`xn9(MA9SU}b2w);gjKO6zzF2iQ(Z2%ojlkXRe-O;_05>^ish1R>GoBX}My)LMXN89;OFgdy*bOdh9mXj@ZMRjmJ=YCe z(`>c?p9FScwl{w!J1&@o!TST=V47#V7R^TJ&D8n8HEy@OU=`a9pjsOKxL4m#)E$ZM9s_y~OKM9|r z4Dtd=Wvg3==uuvFhugbm_KkM- za9zK7Slmzphk^K*8LVDh_C+KgxazuGY1kWe8Gc`oPmrxwaQeUNzr+o3Yk4xma}ARN zHyoPMzhGJ-^ke3deLKb`%EU=Q&HKD{EHeni}^zT#zX@`=>_ zQBgg)G-wW)Ab$O5@xMfBbbzY?7x3X6+a49{c-dnA^Hm=coywH8mj3-%Nm;ue6Avj% z^4tC!>IRfQ^l@ds?<&VcjdmTJ5`lLE_ zcmgvbi{?EcMkap2JVz~~F_vUp1joKcpt(zaQatCG^af&T!)f>Vr?6WK`VtcC1?l^c z2vXKlBGa>)6ErJ7!7fhlH7CfpBEgLzk>j1P5^)8tDyP#T0CA%;uQ9wD4bXV78O#{339L= zm>}{nFv`=SV|=k!Up_SDmS>}SKP`Irc6-D2+=UjZq4QGXmV>>I76lX2j z$lhyLKD?2g#j7dMWRHSv;H?uyr4X0GyW4WNcs*XY9$13HJKg(=TVLKrH^YkD=0*?~ zPCHxO99go_jlhWTUN^_sJKc@5)Uh0Tw0O6hLy>#k2;$;dx!(=8UAjfenOL>s(p0p` z+-e`&h7ElOa7r-8VSnDmd+T(1GS2-tJLv7Eh(^Bc_Sj+veLthvq!xRjxT@( zKfm(zC5`?3%GdvB?C4j%F4ox7uY6sC3oNFJ`d;KgEZ_9?uc=~g6&_=3wy{s|6#EKI zc`+A0F)F1D^C4lqX<`tl!t80HDem&!ISp2nSu~)%8l-B^h)(fY@=!X`N+>W3$fBq0 z@306e_Af5KfBK9lO4w$%2-~W5+l)P4x|}R>)NM+!b$kMxVpN&Vi<(NeP8U_xV^Q?z zbWvHnG)!#@i?tW0i}8J%%Tq|!`U)%!6vnaZgdon=Fi~7BzZKZuTFYX^26tWzJ zI7d2jy@6~#t&e-9;U-5h{s&K;&x_8mO#l6PadX-vuruMDZ1rU4lunig&Jc-pra1A8 z65&|MZ{_*{mkpyBZV)m7oE|TkAyU{~WNs|tc)zqb?n~M~LnQNI)7&`3u|1SipKk^I zIYU&c!XlPx&4=G6)tYDwvza<+QRF0qC)HMYqO*Ed(4;&usJWeCs^G$9Mmvk?GPC)V znCvr{$U3g<;D(C31XZWNOpy-HBR9+xt-NgIj^Q(L_>0`gGtP-BRyrZ9h=h|C&-vBGHpbW&dfH&F@{M50de6zhf~ybj>w2UW#ga{^w5KIL?u2eo;L?8nuj(b z8m!~tIid-w;-4#08rg%#s~=8VVEl07y5e_%p>%__U|!ow8D$^$Tnm6$AU)J;E+!p3 z|4p8YgC6ig1irxOi|d^Nm-Cp!Z2M%_v5n?A#z51KATsm&il0^F`$>4+|7hq{As4u#W8J4IYK!@UKFb zbcncdR@6=DXvppJq5AaDlk-Jp8kD9uuM`6T1`i%62o*S$2^oXd%@@rpdKlvo;-QsA z+6B57KqOf})fUL+-MK(i)7X)ohbAn*Sr_!=s|!TU_SKMOQ`|7P%#!`V(kEL-ZjT)n zsO~Oal5mNV{m#$uJAc7DAXZo?5<~G$5`5-kNDGu$4GIHyR5D{Ncwu;9S2&`9zoMOz z0}WZLkXnM*=VX#k<2v}EK&a_1iVFZ3mj1XvMSd2>L0N(C1#tn(o~nUdKnKZG>KNzc z>@|a}aE-8?Ju8rnSddZ0xFFFp1*3zWO3 zZOIJ#a9rSKF7seqpawrtmn{B{I>HvURwT3uq>&>4h_n4DfGK=29x9BCjIGi*(LSkSGcx8>31v0Z8;GaXvZIq#sy$g znx&!-F}r1(aV1Gj9={g+9c_kKSrc?5&@$JB6`^Jc3j6>Ru)%il2do3()-PLoRGgKODyz#xNZ}88PtC2|3uIqnuKSq$eoG zx(0h@8-@gG(-hcgwh!Y^Id~e4?CCx;6s~V%eoWBo z=Jz4L^r&fbVv*TF+^(BF2HBZXLeC&Mxybx*PIuk>%&?`Dw0>FyGQwg%JZG;xaGWkA zhaW5+2QY$HfhlK+O$V+IQ-XBJA3(|_gOz3BHKT_=UVTcnmmq4tR3wEWI&!N+hnV}7 zgZ*<{pfgwQd|V(r&Co$L)zfi-4*VTd3gazXEYpL+cj0)fGTrcG2C&s@plTk5*DBYX z`Wl;C%GHOd7Oy^`mXSmGy@R=oM#afgBx}iG5IHz^#_nKvonvnpMsXgd?Nc$Laag}0 zDA*!FoO~M>hXos#)rBX9b3rUtf)E^Qa>v`~&!voWNa{q8Sj){WeVeM&t zBg+mis*)I&sxP#i_AuDUHaP-Y7}-MTM6*K}b^wR4WOw2;&p#vjoDPGoSsKcL)EJ&q zk>vm@n_jILCW43m!QxU}4)4y&t7lkTDb@c#)a&&B2?xO>OUF!OZcK>lEIVJWXXt#S zsi~s#<&aOuU|^}lAn^L`110Q$K1vD1o1Ft~%_LC!R4iSYku8su#K3{oRDs29x%$9j zlqJcxTqJ# zJd-C+47Lp15R**5yehIG$=7`iDsx;;fk)_RREUw%4_@4q^A9X`1!k&wX4?99IgR-M zpwo!rJh9ivgUJ{vfk!snk8EiA`nYTr9DD`3Wx1$mNlwbB@v!O;NKQYL)Emx!rUyME&M;n2%F%vBN zK#CQ!XML|gT5L8IRgDc(9x$JM30Hy~-$E5V?@W$zcof!7~5=ewi0 z1RJXHRc0OLxF-f~;e41~^|=5Hz^xqK9v5i9Ptfaz{2lYXr&%}9$m|}t&Fm4l-NX*1 zSufDoXL&7l(q+R9y3-*+>Sklp9ZE+nbIe;!e9AE^n(*G54*4pb)y(OEbTiGY&o60a zws||hWSecw+xVpoHZ2?RiywPu4f!S3w9KCTVwt(-E&P&On#>mC2F4$i#bOw26)hDN za%F>Gcu2S`Rz#!U+L$0a_O)ORVWMwVLh-+kny(VKAw0`X8;c<@u)HgCeRuWouf!tXXO7Q9ow8Z+F) zR`E)HVrvj88r+rzcc4KiY1UWZ>$u(6oAH@3;0+Qk;ROX6R-rwGiCo7iL^Hajao;SavQ3Y{mxCajN zMU50p1`vs8mS`ldx(zrj^&>WOwW!#-DqI({1J9r_+>GkvuL@m;f>!fZKL!@bOoM|M z1?gTIt0WR&e+%Wr&;x+b6#MbK!Ol&=AVM@~ZhVXWf}?W`L^OA0mU?GU3HSeUG!lhx zTrDy})lG%F*}z2z>}A+0j2;$D!nvQDxT=Ltm5ZWnGKnU{7+-6=$Z)0vAPZX>__#9I zIPdPSZt^!YC1JSf>x3Zgadeu3nWUHrvLQaFAy93HOd&HfIJq%j9i1VD2MzSSG7K6w z_k#=u=T4aQ1u!0v(|E@njrJD0%9>#885`e7mc+0-SzbnNx?zrhPQir{QPKoq4+q#C zi?m0GHj~Uw=wRav_9QWX72X#Quz)HDn#p<)`{OS5cnG5o-tHFMdQ`iaIsknoyPBJ8 zd_x&;<4{*syI-O#Uw401y6J7vzBZ49y)f{|*riDwE(6)a_=Jg2$WIS#dRt^<0d>{` zUo6Z}ASjPQUNmz%a_UM1niGvZ#3S?G5kcQ^VU5Quf3%ao3e|l_bO^-&<#~%9`zJx{ zD&w}L;lX$#4^Bu8Y_J>BFSPL%Iso@Gu2GO6YB*BMEU-d27G=icag^1^#aj6w+k&ue zO%f}t%dAr68bYmO9O1i$piRQoCiM4iy6_G($zFo#-$TmhG=42Q`vfgrD{4WntXL=r zDErA;Q9tT)VH_dPIxMy^z)uMbf1$v^R`pR4R;V#Qw7df2tyKW(J&L|$W~;hXn;!Pzo@z`udq<)OA*L*L zs1PBIcCHhZjbp6sh2F~_jJ1@11!CypI#J1sO-Xs%bqr;`D{9sE`m=2MhZdW>gR7Wu zd~MWqx!^IKZ=l2!<4{YN3&A9M~6d{Iw55=EcnivjVU36@1o zD8%6~v#zUhFors<7dZ)^p_>_(&3LP_Q522aDr0c9h3G7r=f>WFwd2fsH2yQHy+O3B z#LH0es%0V{Z)HH!0fiiN^Ak3Rn(HQ6&QoOh1>qU?sB%`w%;0$RW zrMxF9`5Y9^tr-)bocBb>4A~0@W9?omj14NdVgLmK|8TkF()UCay|N@&m1)m=ICANw zbMJ{8Lt&d9U^~`PubB{uBf!m+aF}_J<(_PJ0Z&}0A-Nnmfi<8IFd)@Q=ruE(w=7HXzfKALG_&|&li%Af4@VOJL;~+G!pnx?n zEU;yQkRfk0`~L_Fb6o&89M1w>H0|5gEr`a4_wx!7OIx=80Dii=|0`L}rZYVqz zb1BL6K}&(c%(l>4G>0Z49@>f4few7c`6d)l#RtfhLFudFQV8s-HHEY%zn6SA+Xq@O z-4%fhK&xa%@fJ>4F&gCy)CAnFWl*ts;Fvv zS-k{Euk8Y@ok7MBgCyFzW(e`oNS2GN7P7{gF<4-305{hb%4Q$DA4mR&=u2 z40Kp-?R>sj+>w*UPGE31Of$7P9y!@6-$nojV0G|-(mM+eD_b@3$jydbB232EIhfmQ zlMNRGZZn%6*aH6+`{OMNO= z^7SXMb(MzAGjKQsqUn9h57?GL=n2@yfxGYrna5)QSXq{1GBU@sjGsE3&f+OqNv~x0 z;8z&3xI?uMAkNv2tW&a|ofE4ppYSv{l?tQ&Pv}Uar+n{5s+?pooz+lUTyb*$Wy-pq5MEpY5onm3FUw;e-i~05v;(x5W`f%BR6P4 z1Q7L!m%pUoi}Z=lU#P)0k>&q|_v1mYInhBHybU&mhv=DYqDH&t53&zb7qVb44gj&h zf1v<8o1(?};A|)d4!mJx1ha6yV%KH;c7QX)a7s2>g^vOHd7Ef#>_KMO7GsYWj|}5u z%HA$&u%osC+r{n5&ir?`i#HVINd7$^iV8|HSV9#GhZ|NvOhR2ebl6GFf94}`KuP=@ z!)2WCV(n02`+`4;aU}o2o#Is`?HkoMUsGb)4N`$VJQ#(lMVUxvyiE;vLm+$`MvKy3 zin(F7n__I?XN)1EurCg(3iDRueNM@qblG@OHMa1@BiJ6bzc0pW0F`0*J9uaNJ73{s zgulc4E>;?5P`w-rVr_<^opgv`C&+HQ)bq&3Hw49UEH9=$J3}uSHQmmenh&(7%{#+9spr%ZQ-WO=pb8OF$zk?L3+~wQt=&{EB1;SzSlUV zE#uOWy|5)M%HO+B9CasNLU&<*nU@YXhzgFt8-LRKAB$Zu>%--{IVn5cJV}rpsUWIC zIFTrf3%Cxz4(5WF>L;o}Wf+~jUrT6Zt^Q&w65719wHyIw#aC7ZSl)H_uq9;oYsQb> zTx|SHIRrBbeDy7F!L!PggTlZ)m-7#bKFTlj(?PLX`IVM^BHGkKML`riL6_uW0VsH@-N@N=BjXwcR16ycF!5rL*{D(*n zS_4e{l@bnP_x)FDdRVle2M>!@v42V*;x6vnVQ?k=-eGY+j2x?c2E+dS)b}$n5jH6& zKLh)xlR{Z716XgV+b89uKL3PjDeU);LBn$3&re z+DoBX?&@^u7|b<(r*U71UyO5JB*S($lXKK}7fm`YnpQ@2U?X8%!W3Y+J_?fw)D9J7 z^fSJu&yI`nF+V~p3I?7#b{E}uLe%r`0v+Hk!dx--(2^7IG_sQlPl!{g_Au~ia5NB> zYUjK@3j!okZ96IYq%$ZL>ku57e3zp7?Awt}sKbLWhYl1dm4Pa)Pl=2hxq(4Pf9eQ5(3?1*&B{Sh|262H)H0f*}0TDN#FQ!vn{FsqudT z4+@askaqwN9TU`t1$cqM1ND7kO13 z3`M|GbU}OE)_4`)Kyx@Ju1y^k^s>%_$z2qf4bAu)1IIvzV{AY+OdWPJaF!3c*ToO@ z2830RJU)rQ1jEP41v(fD5cnVY4RkX!oWFZa?@cmG171y_$FM)5+PF+y)}2d4xuA_U z?403PppejpW5c$WPqa>c#2`u7f|V+A<ed1P$X4%J^CYLiRdF@NG^jxFyo|~_PdQ8&9*Mr42abz#l^h<1{=jOJM@=V%84wA zpjCFq;#St09oWA#(Jd z2X=T!rg!Jf489`Q9!VfNVF;GMx?`< z1E`0z{NN>;orhOw!`Zo_ZuF{WxLrN0Lw|ra!+kOk93|jv5g0x;)K+oj3okZ`v4`(z zbnycTZ~>~0SJomRpWF`Pr_4MDZQwMa`Km-|-T0r^R@!6GxDJpF3(yc&>u%yFH1VjD zJz{_^$&8$ib7XVp<5D&d6ZD81b6HyE8Z)8;z%PcxW6h9wo-icT%z+d_k9dqcp7cBd zAT^vF%Z8*G)_i8%Y@-Cw#BgA}%2?&*w&Cr1b!Ect)Yq69QAcj375WIJ3hOc^GnTGl zb!|-{6WSTkEnVBWzE|l9Y?-)Rtz0{}223D|%K+KJMA)QYeFY_Bjj`Qz2!U>McVe=j z>(?v52T=Zl$g6<~0KY4FH2aIJF|!9@xWEM&!=%zCoZ-QcBwQ9IYk@-SMFXUlJnUqRj2zf+@%l+-N}f=2Pl`Rtu%CCj57O{VF|FSlDO=4VPGV_LIH&* zxL{@>P!|wMjHD!z(Ix2WmgC6CBm09F09HjYnw3{Bceh-*xEGNNZhC+eSl3YgKSDjs zQ5*VEZUvC~u!AHA@s!ZPr$AyV#%X6t08dzE1kQ#5l&)ULnP6N$?sBf1(`>uZkrT{e z8aW+C8Gl)>4QtVPiIt}#d9WlIkew%~f;ANhA>@D}p}!-iSIFYi!xdN!kL=@AB#0RI zaok8m%9&f-*+_vE98B1hXq$^=PQV>TsqjiK^E$|1$Z#+;a%KU(iU}e6L4Q?ScX)Ud#xuViZNbtljf+hF|az4!HMDEdATC}Ea@O4iVUs|2N%oWG7d6|fN1}V zH!kJk1xmoJ@-mwe#I^wTY(Q64UcZ=Ijv5hk^PZivLddm)R~0a{5C(WL!l0HURIip0 z3o;kXJi62w13Y*smHGXsi4e6Y^Q^n#$O}9>J;PWGLH$@DGBCkh7N%4TL&l|txY$4n zU`S{o8m6O!TBEQenIq$o@4i7 z6nZiL0&F+_M@KG*CQat@XJE`f=taq~@aj!DKZ?3RnG-5A&dG=dBxT96WEB6R89#~+ z6-x``?yx|9;zyX6T&4;?iKb02dwGN;MMYh72}agyrQbSGEbK)GCls2 zXq|kS8xFpj8;+UD4PWI}qNu_JaYGc-H74T}{8=QS>ze;8hSnM-7V`mr3AZC;SYNJ8<%zsRb4pTEkSA}2(b;hT^i>z+A zIE<-HSc}FwIJjtt(ETt{!lHm7G5{MQ%nIOdTNV)s(fUKYuKb>V_7CWqs{J7w#W%&U zIP!-VlN|VA3sE?W#iEumj~ZVRHDmtp`alG+JBoHvi_dYU^yy2YssL!*N=U0N0mX4l z{F3ODM8H{qVZjcn2nNSMT3!}G&tkBUfbbj*x-9i$lP`-7SICOdswdp8%Vc;8%|GBHT%&?;V4?H=oxst zujnoC_)XF4;89i8d*ktxsyD{tZB@@x{-$j2*hzo1M_uZEcRntns07ot}^8Sq1PuvozL8ZSiq)ihqNq)C9= z8u#`GF3GZEG{EXx6W*qGG(D)ikbg)+d6ixS+OYVK2_KC-(0O1HlVZMRETWe@dPC(! zD)Q((lNK@6a^as$$ap#oDVlrrA@PeitK2PN(G!$oKdtfVZQwECyjM?&{RonHSci=h z)fJ=l&dL(%AFa2IStpOuGj18L)9cabB^i-UKSt|Q>{$DR{_8Z!r#mO~`5^W!G5Wje z{I|*L*Rz$E$nxtc>e{#IE(FtGiso~!7(Q%y@ipl{Jp0NDBv^$6X-L4ET(VZpuya|Q zposqR>&-cyO>Y4}jpCh6po0zI4E2cBn^#9XHm|X2BwA0Se=Rh>*jEnAsWRp~y&0>g zHoL?LVj~lP3y=w(;oG~Q^exE>QYK?&y+fB{^^}acoC1qSNeV~@GR1;-s9~I*((DyZ z0R?AC3LFoWDb{ifOpZ!oFvK!u>pK*R(+AM@1z_dTi!7tA+O&_&l!3n+=W?S=&eD5FB_O4ODL;? zKGU}jn1%rfMBzf1?G^N!l*1Gs4-|iwvg7qG91RW~7I=t$HeP=nHwHFKzy?!3^-92W z$){%%FqPh=9SM3zWj)0t>NtiS0kV6d-o4a^6^Z&{xM8?4Nw2J;V#Aa4TI!~qL`ix( zRPacWUYCQ>74<9>)wm*1?=2coQGZ{3epYW1oJ&B*|lTqxJopd@GGwCE%OwpfKw$Q>9lv+UBQuG7x zZ$_zzTT44r^+px8+Po&_6R%U6Q9vUFfH5=Z7=sHDH5R@)Pu=4*iM4baKeaNVq67eZbZsu~~i zqKsi?Q<#mW-n*K#fno9>H4a!cnVd$+9WGw?z{D$9EL#NhrWJPqsomBJrMuKxGcmx7 z-bWJynCc(W-T+1rM|FdGrQ|PJAqd?y${8lhindE^8q^>5c0)bh%s}{G#w{gdZeu`Oe|SWx`FUZ6ke3N>hA} zagyOaQ&%>A&H4VkFB<9d)%iq^Hr78QHJbX=ZS?^Iyu3jah03kop?8VcKXAzzno?vVaQ`cNQTb;k2 zy5;K4FuykD>O<7RjWVb%-$Z@e={I9f@{M--5Rtb9^%_7ua`gt(xjp845k1}>-%o7C z_Xc#iGd>kidIvpQEZ!zRozK-9iE-QI`-ygXW6geD&{1!s7VNMKS&Zv{I_d;#zC9f= z9*cLbs)vSuh^N4F51uvfm8HaN5Yo1@Tuf9d`UTkeh6nu;>+^wh6!G0(%rk`F|Een=` zJ=z!&K^|#kxKw1i#R(4`b>GlYL&rWgB7b0iJz4SgX=}K$5I=#&55UT{2p-b)+Gb?2 z?GQU~#E{WrhK{{|v|Ai6w2ui|z!$f4jsy_WV_7sKVHB?I+@7Lhr*!tL>E zj$h<_VO&td|GC|YqPVO=`hK9E+-k~%tu7yUXKR&w;fV0d@~08CtLMm}4?Q$=)DZK& zp@T;ZG6%SpTZStR0GCnQd-P;)p%Z+B`ro6cd(R+PLB>9Pk6xu_2fW@qdeq>aqel*o ztWigNj|?}--*S)cQ6MSQe5SgzN!qf3x$8*qN z+0#Quk8-*0$2YD!68FPxk3CSTCS53hh(7y@ala8sn^XV$^&9EP zG(90Icl4ue=*6LWCt7j8K80Q$s#n)<8aiamz_Ekr&!Ku<>NQkPC1sd?cc3e>M%J-g znQ%u64bv+tH_?BF>B*IDMyz%3y`vu^0OmqC$nw{zUUG3fcR5@KZB z9f;$J#iWq`%j#-`WB@Ovo{yWR`6Lo_!*`wzH#_m&o$%ctqQ{omc}6(j1`ZlDX7ED~ zxq2aeB7RKj@5Jwchwm9N^xpo%2R~N25xo&tmnk$S*V+PZ=BlUsFcMKfy@L)!~Qi=Le|4~?g`qPY2 zdS!BkDf<_&-iQ1i$~=@WUfU zl!9@88JI&$!ZunTeA(iEhd(&s$IFDDC==#s7dcE%l?gN4$oO$(!sDGV zr;`gR6Mnu-ct)9U z9>N{L}N=tFq5`CrT2_}6G3j^+Fmqn zs&3NVAzi0-A-%EJ-`_5DH-$p_X#dj)GH?D>FEG#a*5i5_wHl|#QL71hG}RlY*YW>= z6wIM0cN(tB+`deDa~zr=Q@l7%Z|J{!fL(7BDT3U{G)fzf6z3R*f4pATzZWT*07foS zWK!iRdNTDJuXjsoHPC=34wq{HzMFUsX?V6+;$|^d-iS|*#WUM^rDSNVBLv{6`0h9Gxqi?#; zZfIg3+B6v@y@fCjcC9{?F-5<_>lUQEBuU9EK7Zj z^_|!LWz-9wy;(yIDV{aSe|8!~c6H9DwDMWKM)I=5;4?Lbp}VY$9I*M*Z=Z$0GWByf z2GiF=XgE4uZvZjC|D66ccbl9^{N#*aTUSD{;Y;G_#s7ipu8ZHz1HoP)a{m|kp6B&D zlR|Gz`vBk#m$gN{BqB<_q`Isx_(jdB?6Q84Z&MRo)?e~%Sc=Pf?is|o$4$(1Sue`h zqIkrwlCKj#O?FxD%h$nsE4i#a{2FEUUmWkUj>`8l|LTk+XP*gi#L_uwNc1O1XgOak zYJgPFKFfi;%hx~vyuph@*#hG)2}*Et}@oydM{TLs8@GPL;cq+U&saF+}f-aKUF z)^wNkxeVPfbHM34k@9~W(sQP-d$iJ95D%G=m)&s zp@0>OgpbhoA3!9SgCI|+WmI9C-ZyUhF4RoviwkvkY^Ix#CooFe_izke&g8$b zO&_ClSOfuj8GdW=+kxLf{Jz5P0)Bts7aeQ367dV*R~x@<{BrTT5x<`J^~3L8x@U(z z#D5TC*Ae_qi9LmF9*MF`1Qo^ S4*dG!XDvHGBR State { let state = State::new( { let (account_id, _account_keypair) = gen_account_in(&*STARTER_DOMAIN); - let mut domain = Domain::new(STARTER_DOMAIN.clone()).build(&account_id); + let domain = Domain::new(STARTER_DOMAIN.clone()).build(&account_id); let account = Account::new(account_id.clone()).build(&account_id); - World::with([domain], UniqueVec::new()) + World::with([domain], [account], UniqueVec::new()) }, kura, query_handle, diff --git a/core/src/block.rs b/core/src/block.rs index f0aadb019a7..2f66278d414 100644 --- a/core/src/block.rs +++ b/core/src/block.rs @@ -168,7 +168,7 @@ mod pending { .collect::>() .hash() .expect("INTERNAL BUG: Empty block created"), - timestamp_ms: SystemTime::now() + creation_time_ms: SystemTime::now() .duration_since(SystemTime::UNIX_EPOCH) .expect("INTERNAL BUG: Failed to get the current system time") .as_millis() @@ -645,7 +645,7 @@ mod valid { transactions_hash: HashOf::from_untyped_unchecked(Hash::prehashed( [1; Hash::LENGTH], )), - timestamp_ms: 0, + creation_time_ms: 0, view_change_index: 0, consensus_estimation_ms: 4_000, }, diff --git a/core/src/query/store.rs b/core/src/query/store.rs index be9da50dbd3..b6da9cb698f 100644 --- a/core/src/query/store.rs +++ b/core/src/query/store.rs @@ -8,7 +8,11 @@ use std::{ use indexmap::IndexMap; use iroha_config::parameters::actual::LiveQueryStore as Config; use iroha_data_model::{ - query::{cursor::ForwardCursor, error::QueryExecutionFail, QueryId, QueryOutputBox}, + query::{ + cursor::{ForwardCursor, QueryId}, + error::QueryExecutionFail, + QueryOutputBox, + }, BatchedResponse, BatchedResponseV1, ValidationFail, }; use iroha_logger::trace; @@ -184,7 +188,7 @@ impl LiveQueryStoreHandle { &self, cursor: ForwardCursor, ) -> Result> { - let query_id = cursor.query_id.ok_or(UnknownCursor)?; + let query_id = cursor.query.ok_or(UnknownCursor)?; let live_query = self.remove(query_id.clone())?.ok_or(UnknownCursor)?; self.construct_query_response(query_id, cursor.cursor.map(NonZeroU64::get), live_query) @@ -235,7 +239,7 @@ impl LiveQueryStoreHandle { let query_response = BatchedResponseV1 { batch: QueryOutputBox::Vec(batch), cursor: ForwardCursor { - query_id: Some(query_id), + query: Some(query_id), cursor: next_cursor, }, }; diff --git a/core/src/smartcontracts/isi/account.rs b/core/src/smartcontracts/isi/account.rs index bea9b9c375f..d69174df845 100644 --- a/core/src/smartcontracts/isi/account.rs +++ b/core/src/smartcontracts/isi/account.rs @@ -25,7 +25,7 @@ impl Registrable for iroha_data_model::account::NewAccount { /// - Revoke permissions or roles pub mod isi { use iroha_data_model::{ - asset::{AssetValue, AssetValueType}, + asset::{AssetType, AssetValue}, isi::{ error::{MintabilityError, RepetitionError}, InstructionType, @@ -78,7 +78,7 @@ pub mod isi { _ => Err(err.into()), }, Ok(_) => Err(RepetitionError { - instruction_type: InstructionType::Register, + instruction: InstructionType::Register, id: IdBox::AssetId(asset_id.clone()), } .into()), @@ -243,7 +243,7 @@ pub mod isi { ) -> Result<(), Error> { let account_id = self.destination; let permission = self.object; - let permission_id = permission.id.clone(); + let permission_name = permission.name.clone(); // Check if account exists state_transaction.world.account_mut(&account_id)?; @@ -252,9 +252,9 @@ pub mod isi { .world .executor_data_model .permissions - .contains(&permission_id) + .contains(&permission_name) { - return Err(FindError::Permission(permission_id).into()); + return Err(FindError::Permission(permission).into()); } if state_transaction @@ -262,22 +262,22 @@ pub mod isi { .account_contains_inherent_permission(&account_id, &permission) { return Err(RepetitionError { - instruction_type: InstructionType::Grant, - id: permission.id.into(), + instruction: InstructionType::Grant, + id: permission.into(), } .into()); } state_transaction .world - .add_account_permission(&account_id, permission); + .add_account_permission(&account_id, permission.clone()); state_transaction .world .emit_events(Some(AccountEvent::PermissionAdded( AccountPermissionChanged { account: account_id, - permission: permission_id, + permission, }, ))); @@ -302,7 +302,7 @@ pub mod isi { .world .remove_account_permission(&account_id, &permission) { - return Err(FindError::Permission(permission.id).into()); + return Err(FindError::Permission(permission).into()); } state_transaction @@ -310,7 +310,7 @@ pub mod isi { .emit_events(Some(AccountEvent::PermissionRemoved( AccountPermissionChanged { account: account_id, - permission: permission.id, + permission, }, ))); @@ -333,10 +333,8 @@ pub mod isi { .roles .get(&role_id) .ok_or_else(|| FindError::Role(role_id.clone()))? - .clone() .permissions - .into_iter() - .map(|token| token.id); + .clone(); state_transaction.world.account(&account_id)?; @@ -350,7 +348,7 @@ pub mod isi { .is_some() { return Err(RepetitionError { - instruction_type: InstructionType::Grant, + instruction: InstructionType::Grant, id: IdBox::RoleId(role_id), } .into()); @@ -359,10 +357,11 @@ pub mod isi { state_transaction.world.emit_events({ let account_id_clone = account_id.clone(); permissions + .into_iter() .zip(core::iter::repeat_with(move || account_id.clone())) - .map(|(permission_id, account_id)| AccountPermissionChanged { + .map(|(permission, account_id)| AccountPermissionChanged { account: account_id, - permission: permission_id, + permission, }) .map(AccountEvent::PermissionAdded) .chain(std::iter::once(AccountEvent::RoleGranted( @@ -392,10 +391,8 @@ pub mod isi { .roles .get(&role_id) .ok_or_else(|| FindError::Role(role_id.clone()))? - .clone() .permissions - .into_iter() - .map(|token| token.id); + .clone(); if state_transaction .world @@ -412,10 +409,11 @@ pub mod isi { state_transaction.world.emit_events({ let account_id_clone = account_id.clone(); permissions + .into_iter() .zip(core::iter::repeat_with(move || account_id.clone())) - .map(|(permission_id, account_id)| AccountPermissionChanged { + .map(|(permission, account_id)| AccountPermissionChanged { account: account_id, - permission: permission_id, + permission, }) .map(AccountEvent::PermissionRemoved) .chain(std::iter::once(AccountEvent::RoleRevoked( @@ -436,9 +434,9 @@ pub mod isi { state_transaction: &mut StateTransaction<'_, '_>, value: &AssetValue, ) -> Result<(), Error> { - let expected_asset_value_type = match value.value_type() { - AssetValueType::Numeric(_) => asset::isi::expected_asset_value_type_numeric, - AssetValueType::Store => asset::isi::expected_asset_value_type_store, + let expected_asset_value_type = match value.type_() { + AssetType::Numeric(_) => asset::isi::expected_asset_value_type_numeric, + AssetType::Store => asset::isi::expected_asset_value_type_store, }; let definition = asset::isi::assert_asset_type( definition_id, @@ -572,7 +570,7 @@ pub mod query { &self, state_ro: &'state impl StateReadOnly, ) -> Result + 'state>, Error> { - let id = &self.domain_id; + let id = &self.domain; iroha_logger::trace!(%id); Ok(Box::new( @@ -601,7 +599,7 @@ pub mod query { &self, state_ro: &'state impl StateReadOnly, ) -> Result + 'state>, Error> { - let asset_definition_id = self.asset_definition_id.clone(); + let asset_definition_id = self.asset_definition.clone(); iroha_logger::trace!(%asset_definition_id); Ok(Box::new( diff --git a/core/src/smartcontracts/isi/asset.rs b/core/src/smartcontracts/isi/asset.rs index 38621f4ec5d..8eb0904b12d 100644 --- a/core/src/smartcontracts/isi/asset.rs +++ b/core/src/smartcontracts/isi/asset.rs @@ -18,7 +18,7 @@ impl Registrable for NewAssetDefinition { fn build(self, authority: &AccountId) -> Self::Target { Self::Target { id: self.id, - value_type: self.value_type, + type_: self.type_, mintable: self.mintable, logo: self.logo, metadata: self.metadata, @@ -32,7 +32,7 @@ impl Registrable for NewAssetDefinition { /// - update metadata /// - transfer, etc. pub mod isi { - use iroha_data_model::{asset::AssetValueType, isi::error::MintabilityError}; + use iroha_data_model::{asset::AssetType, isi::error::MintabilityError}; use super::*; use crate::smartcontracts::account::isi::forbid_minting; @@ -348,9 +348,9 @@ pub mod isi { asset_definition: &AssetDefinition, ) -> Result { let object_spec = NumericSpec::fractional(object.scale()); - let object_asset_value_type = AssetValueType::Numeric(object_spec); - let asset_definition_spec = match asset_definition.value_type { - AssetValueType::Numeric(spec) => spec, + let object_asset_value_type = AssetType::Numeric(object_spec); + let asset_definition_spec = match asset_definition.type_ { + AssetType::Numeric(spec) => spec, other => { return Err(TypeError::from(Mismatch { expected: other, @@ -361,7 +361,7 @@ pub mod isi { }; asset_definition_spec.check(object).map_err(|_| { TypeError::from(Mismatch { - expected: AssetValueType::Numeric(asset_definition_spec), + expected: AssetType::Numeric(asset_definition_spec), actual: object_asset_value_type, }) })?; @@ -372,10 +372,10 @@ pub mod isi { pub(crate) fn assert_asset_type( definition_id: &AssetDefinitionId, state_transaction: &StateTransaction<'_, '_>, - expected_value_type: impl Fn(&AssetValueType) -> Result<(), TypeError>, + expected_value_type: impl Fn(&AssetType) -> Result<(), TypeError>, ) -> Result { let asset_definition = state_transaction.world.asset_definition(definition_id)?; - expected_value_type(&asset_definition.value_type) + expected_value_type(&asset_definition.type_) .map(|()| asset_definition) .map_err(Into::into) } @@ -403,19 +403,19 @@ pub mod isi { } pub(crate) fn expected_asset_value_type_numeric( - asset_value_type: &AssetValueType, + asset_value_type: &AssetType, ) -> Result<(), TypeError> { match asset_value_type { - AssetValueType::Numeric(_) => Ok(()), + AssetType::Numeric(_) => Ok(()), other => Err(TypeError::NumericAssetValueTypeExpected(*other)), } } pub(crate) fn expected_asset_value_type_store( - asset_value_type: &AssetValueType, + asset_value_type: &AssetType, ) -> Result<(), TypeError> { match asset_value_type { - AssetValueType::Store => Ok(()), + AssetType::Store => Ok(()), other => Err(TypeError::NumericAssetValueTypeExpected(*other)), } } @@ -522,7 +522,7 @@ pub mod query { &self, state_ro: &'state impl StateReadOnly, ) -> Result + 'state>, Error> { - let id = &self.account_id; + let id = &self.account; iroha_logger::trace!(%id); Ok(Box::new(state_ro.world().account_assets(id)?.cloned())) } @@ -534,7 +534,7 @@ pub mod query { &self, state_ro: &'state impl StateReadOnly, ) -> Result + 'state>, Error> { - let id = self.asset_definition_id.clone(); + let id = self.asset_definition.clone(); iroha_logger::trace!(%id); Ok(Box::new( state_ro @@ -559,7 +559,7 @@ pub mod query { &self, state_ro: &'state impl StateReadOnly, ) -> Result + 'state>, Error> { - let id = &self.domain_id; + let id = &self.domain; iroha_logger::trace!(%id); Ok(Box::new( state_ro @@ -577,8 +577,8 @@ pub mod query { &self, state_ro: &'state impl StateReadOnly, ) -> Result + 'state>, Error> { - let domain_id = self.domain_id.clone(); - let asset_definition_id = self.asset_definition_id.clone(); + let domain_id = self.domain.clone(); + let asset_definition_id = self.asset_definition.clone(); let domain = state_ro.world().domain(&domain_id)?; let _definition = domain .asset_definitions diff --git a/core/src/smartcontracts/isi/domain.rs b/core/src/smartcontracts/isi/domain.rs index 5dcad8e7b58..cb964a2f30f 100644 --- a/core/src/smartcontracts/isi/domain.rs +++ b/core/src/smartcontracts/isi/domain.rs @@ -57,7 +57,7 @@ pub mod isi { let _domain = state_transaction.world.domain_mut(&account_id.domain)?; if state_transaction.world.account(&account_id).is_ok() { return Err(RepetitionError { - instruction_type: InstructionType::Register, + instruction: InstructionType::Register, id: IdBox::AccountId(account_id), } .into()); @@ -139,7 +139,7 @@ pub mod isi { .domain_mut(&asset_definition_id.domain)?; if domain.asset_definitions.contains_key(&asset_definition_id) { return Err(RepetitionError { - instruction_type: InstructionType::Register, + instruction: InstructionType::Register, id: IdBox::AssetDefinitionId(asset_definition_id), } .into()); diff --git a/core/src/smartcontracts/isi/triggers/mod.rs b/core/src/smartcontracts/isi/triggers/mod.rs index aeb80783ea6..7f3d8db3645 100644 --- a/core/src/smartcontracts/isi/triggers/mod.rs +++ b/core/src/smartcontracts/isi/triggers/mod.rs @@ -42,7 +42,7 @@ pub mod isi { } let last_block_estimation = state_transaction.latest_block().map(|block| { - block.header().timestamp() + block.header().creation_time() + Duration::from_millis(block.header().consensus_estimation_ms) }); @@ -99,7 +99,7 @@ pub mod isi { if !success { return Err(RepetitionError { - instruction_type: InstructionType::Register, + instruction: InstructionType::Register, id: trigger_id.into(), } .into()); @@ -130,7 +130,7 @@ pub mod isi { Ok(()) } else { Err(RepetitionError { - instruction_type: InstructionType::Unregister, + instruction: InstructionType::Unregister, id: trigger_id.into(), } .into()) @@ -389,7 +389,7 @@ pub mod query { &self, state_ro: &'state impl StateReadOnly, ) -> eyre::Result + 'state>, Error> { - let account_id = self.account_id.clone(); + let account_id = self.account.clone(); Ok(Box::new( state_ro @@ -417,7 +417,7 @@ pub mod query { &self, state_ro: &'state impl StateReadOnly, ) -> eyre::Result + 'state>, Error> { - let domain_id = self.domain_id.clone(); + let domain_id = self.domain.clone(); Ok(Box::new( state_ro diff --git a/core/src/smartcontracts/isi/tx.rs b/core/src/smartcontracts/isi/tx.rs index e10d8b0f594..886c5a507a6 100644 --- a/core/src/smartcontracts/isi/tx.rs +++ b/core/src/smartcontracts/isi/tx.rs @@ -87,7 +87,7 @@ impl ValidQuery for FindTransactionsByAccountId { &self, state_ro: &'state impl StateReadOnly, ) -> Result + 'state>, QueryExecutionFail> { - let account_id = self.account_id.clone(); + let account_id = self.account.clone(); Ok(Box::new( state_ro diff --git a/core/src/smartcontracts/isi/world.rs b/core/src/smartcontracts/isi/world.rs index 72b65dc194b..f459c965687 100644 --- a/core/src/smartcontracts/isi/world.rs +++ b/core/src/smartcontracts/isi/world.rs @@ -43,7 +43,7 @@ pub mod isi { if let PushResult::Duplicate(duplicate) = world.trusted_peers_ids.push(peer_id.clone()) { return Err(RepetitionError { - instruction_type: InstructionType::Register, + instruction: InstructionType::Register, id: IdBox::PeerId(duplicate), } .into()); @@ -100,7 +100,7 @@ pub mod isi { let world = &mut state_transaction.world; if world.domains.get(&domain_id).is_some() { return Err(RepetitionError { - instruction_type: InstructionType::Register, + instruction: InstructionType::Register, id: IdBox::DomainId(domain_id), } .into()); @@ -178,7 +178,7 @@ pub mod isi { if state_transaction.world.roles.get(role.id()).is_some() { return Err(RepetitionError { - instruction_type: InstructionType::Register, + instruction: InstructionType::Register, id: IdBox::RoleId(role.id), } .into()); @@ -189,9 +189,9 @@ pub mod isi { .world .executor_data_model .permissions - .contains(&permission.id) + .contains(&permission.name) { - return Err(FindError::Permission(permission.id.clone()).into()); + return Err(FindError::Permission(permission.clone()).into()); } } @@ -252,15 +252,15 @@ pub mod isi { ) -> Result<(), Error> { let role_id = self.destination; let permission = self.object; - let permission_id = permission.id.clone(); + let permission_name = permission.name.clone(); if !state_transaction .world .executor_data_model .permissions - .contains(&permission_id) + .contains(&permission_name) { - return Err(FindError::Permission(permission_id).into()); + return Err(FindError::Permission(permission).into()); } let Some(role) = state_transaction.world.roles.get_mut(&role_id) else { @@ -269,8 +269,8 @@ pub mod isi { if !role.permissions.insert(permission.clone()) { return Err(RepetitionError { - instruction_type: InstructionType::Grant, - id: permission.id.into(), + instruction: InstructionType::Grant, + id: permission.into(), } .into()); } @@ -279,7 +279,7 @@ pub mod isi { .world .emit_events(Some(RoleEvent::PermissionAdded(RolePermissionChanged { role: role_id, - permission: permission_id, + permission, }))); Ok(()) @@ -295,21 +295,20 @@ pub mod isi { ) -> Result<(), Error> { let role_id = self.destination; let permission = self.object; - let permission_id = permission.id.clone(); let Some(role) = state_transaction.world.roles.get_mut(&role_id) else { return Err(FindError::Role(role_id).into()); }; if !role.permissions.remove(&permission) { - return Err(FindError::Permission(permission_id).into()); + return Err(FindError::Permission(permission).into()); } state_transaction .world .emit_events(Some(RoleEvent::PermissionRemoved(RolePermissionChanged { role: role_id, - permission: permission_id, + permission, }))); Ok(()) @@ -351,7 +350,7 @@ pub mod isi { if !state_transaction.world.parameters.insert(parameter.clone()) { return Err(RepetitionError { - instruction_type: InstructionType::NewParameter, + instruction: InstructionType::NewParameter, id: IdBox::ParameterId(parameter_id), } .into()); @@ -409,7 +408,7 @@ pub mod isi { fn revoke_removed_permissions( authority: &AccountId, state_transaction: &mut StateTransaction, - permissions_before: BTreeSet, + permissions_before: BTreeSet, ) -> Result<(), Error> { let world = state_transaction.world(); let permissions_after = world.executor_data_model().permissions(); @@ -437,7 +436,7 @@ pub mod isi { fn find_related_accounts( world: &impl WorldReadOnly, - permissions: &BTreeSet, + permissions: &BTreeSet, ) -> Vec<(AccountId, Permission)> { world .account_permissions() @@ -445,7 +444,7 @@ pub mod isi { .flat_map(|(account_id, account_permissions)| { account_permissions .iter() - .filter(|permission| permissions.contains(&permission.id)) + .filter(|permission| permissions.contains(&permission.name)) .map(|permission| (account_id.clone(), permission.clone())) }) .collect() @@ -453,7 +452,7 @@ pub mod isi { fn find_related_roles( world: &impl WorldReadOnly, - permissions: &BTreeSet, + permissions: &BTreeSet, ) -> Vec<(RoleId, Permission)> { world .roles() @@ -461,7 +460,7 @@ pub mod isi { .flat_map(|(role_id, role)| { role.permissions .iter() - .filter(|permission| permissions.contains(&permission.id)) + .filter(|permission| permissions.contains(&permission.name)) .map(|permission| (role_id.clone(), permission.clone())) }) .collect() diff --git a/core/src/smartcontracts/wasm.rs b/core/src/smartcontracts/wasm.rs index 9ab00dcbcf3..64f385c038f 100644 --- a/core/src/smartcontracts/wasm.rs +++ b/core/src/smartcontracts/wasm.rs @@ -12,7 +12,7 @@ use iroha_data_model::{ executor::{self, ExecutorDataModel, MigrationResult}, isi::InstructionBox, prelude::*, - query::{QueryBox, QueryId, QueryOutputBox, QueryRequest, SmartContractQuery}, + query::{cursor::QueryId, QueryBox, QueryOutputBox, QueryRequest, SmartContractQuery}, smart_contract::payloads::{self, Validate}, BatchedResponse, Level as LogLevel, ValidationFail, }; @@ -812,7 +812,7 @@ where }?; match &batched { BatchedResponse::V1(batched) => { - if let Some(query_id) = &batched.cursor.query_id { + if let Some(query_id) = &batched.cursor.query { state.executed_queries.insert(query_id.clone()); } } @@ -822,7 +822,7 @@ where QueryRequest::Cursor(cursor) => { // In a normal situation we already have this `query_id` stored, // so that's a protection from malicious smart contract - if let Some(query_id) = &cursor.query_id { + if let Some(query_id) = &cursor.query { state.executed_queries.insert(query_id.clone()); } state diff --git a/core/src/state.rs b/core/src/state.rs index 0c00cb5467b..54ac916d4f2 100644 --- a/core/src/state.rs +++ b/core/src/state.rs @@ -1122,7 +1122,7 @@ pub trait StateReadOnly { let opt = self .kura() .get_block_by_height(nonzero_ext::nonzero!(1_usize)) - .map(|genesis_block| genesis_block.header().timestamp()); + .map(|genesis_block| genesis_block.header().creation_time()); if opt.is_none() { error!("Failed to get genesis block from Kura."); @@ -1303,13 +1303,13 @@ impl<'state> StateBlock<'state> { let header = &latest_block.as_ref().header(); TimeInterval { - since: header.timestamp(), + since: header.creation_time(), length: header.consensus_estimation(), } }); let interval = TimeInterval { - since: block.as_ref().header().timestamp(), + since: block.as_ref().header().creation_time(), length: block.as_ref().header().consensus_estimation(), }; diff --git a/data_model/src/account.rs b/data_model/src/account.rs index 0e99bf6d495..6d75fc54358 100644 --- a/data_model/src/account.rs +++ b/data_model/src/account.rs @@ -234,10 +234,10 @@ pub mod prelude { } #[cfg(test)] +#[cfg(feature = "transparent_api")] mod tests { use super::*; - #[cfg(feature = "transparent_api")] #[test] fn parse_account_id() { const SIGNATORY: &str = diff --git a/data_model/src/asset.rs b/data_model/src/asset.rs index 6b3972c1e49..71d8a4cca62 100644 --- a/data_model/src/asset.rs +++ b/data_model/src/asset.rs @@ -114,7 +114,7 @@ mod model { Serialize, IntoSchema, )] - #[display(fmt = "{id} {value_type}{mintable}")] + #[display(fmt = "{id} {type_}{mintable}")] #[allow(clippy::multiple_inherent_impl)] #[ffi_type] pub struct AssetDefinition { @@ -122,7 +122,8 @@ mod model { pub id: AssetDefinitionId, /// Type of [`AssetValue`] #[getset(get_copy = "pub")] - pub value_type: AssetValueType, + #[serde(rename = "type")] + pub type_: AssetType, /// Is the asset mintable #[getset(get_copy = "pub")] pub mintable: Mintable, @@ -164,13 +165,14 @@ mod model { #[derive( Debug, Display, Clone, IdEqOrdHash, Decode, Encode, Deserialize, Serialize, IntoSchema, )] - #[display(fmt = "{id} {mintable}{value_type}")] + #[display(fmt = "{id} {mintable}{type_}")] #[ffi_type] pub struct NewAssetDefinition { /// The identification associated with the asset definition builder. pub id: AssetDefinitionId, /// The type value associated with the asset definition builder. - pub value_type: AssetValueType, + #[serde(rename = "type")] + pub type_: AssetType, /// The mintablility associated with the asset definition builder. pub mintable: Mintable, /// IPFS link to the [`AssetDefinition`] logo @@ -196,7 +198,7 @@ mod model { )] #[ffi_type] #[repr(u8)] - pub enum AssetValueType { + pub enum AssetType { /// Asset's qualitative value. #[display(fmt = "{_0}")] Numeric(NumericSpec), @@ -268,12 +270,12 @@ mod model { } } -/// Error occurred while parsing `AssetValueType` +/// Error occurred while parsing `AssetType` #[derive(Debug, displaydoc::Display, Clone)] #[cfg_attr(feature = "std", derive(thiserror::Error))] #[repr(u8)] pub enum AssetValueTypeParseError { - /// `AssetValueType` should be either `Store` or `Numeric` + /// `AssetType` should be either `Store` or `Numeric` WrongVariant, /// Error occurred while parsing `Numeric` variant: {_0} Numeric(#[cfg_attr(feature = "std", source)] NumericSpecParseError), @@ -283,22 +285,22 @@ impl AssetDefinition { /// Construct builder for [`AssetDefinition`] identifiable by [`Id`]. #[must_use] #[inline] - pub fn new(id: AssetDefinitionId, value_type: AssetValueType) -> ::With { - ::With::new(id, value_type) + pub fn new(id: AssetDefinitionId, type_: AssetType) -> ::With { + ::With::new(id, type_) } /// Construct builder for [`AssetDefinition`] identifiable by [`Id`]. #[must_use] #[inline] pub fn numeric(id: AssetDefinitionId) -> ::With { - ::With::new(id, AssetValueType::Numeric(NumericSpec::default())) + ::With::new(id, AssetType::Numeric(NumericSpec::default())) } /// Construct builder for [`AssetDefinition`] identifiable by [`Id`]. #[must_use] #[inline] pub fn store(id: AssetDefinitionId) -> ::With { - ::With::new(id, AssetValueType::Store) + ::With::new(id, AssetType::Store) } } @@ -314,10 +316,10 @@ impl Asset { impl NewAssetDefinition { /// Create a [`NewAssetDefinition`], reserved for internal use. - fn new(id: AssetDefinitionId, value_type: AssetValueType) -> Self { + fn new(id: AssetDefinitionId, type_: AssetType) -> Self { Self { id, - value_type, + type_, mintable: Mintable::Infinitely, logo: None, metadata: Metadata::default(), @@ -356,12 +358,10 @@ impl HasMetadata for AssetDefinition { impl AssetValue { /// Returns the asset type as a string. - pub const fn value_type(&self) -> AssetValueType { + pub const fn type_(&self) -> AssetType { match *self { - Self::Numeric(numeric) => { - AssetValueType::Numeric(NumericSpec::fractional(numeric.scale())) - } - Self::Store(_) => AssetValueType::Store, + Self::Numeric(numeric) => AssetType::Numeric(NumericSpec::fractional(numeric.scale())), + Self::Store(_) => AssetType::Store, } } /// Returns true if this value is zero, false if it contains [`Metadata`] or positive value @@ -446,7 +446,7 @@ impl FromStr for AssetId { } } -impl FromStr for AssetValueType { +impl FromStr for AssetType { type Err = AssetValueTypeParseError; fn from_str(s: &str) -> Result { @@ -478,7 +478,7 @@ impl Registered for AssetDefinition { /// The prelude re-exports most commonly used traits, structs and macros from this crate. pub mod prelude { pub use super::{ - Asset, AssetDefinition, AssetDefinitionId, AssetId, AssetValue, AssetValueType, Mintable, + Asset, AssetDefinition, AssetDefinitionId, AssetId, AssetType, AssetValue, Mintable, NewAssetDefinition, }; } diff --git a/data_model/src/block.rs b/data_model/src/block.rs index 6e7c5814519..7a3f6781453 100644 --- a/data_model/src/block.rs +++ b/data_model/src/block.rs @@ -61,7 +61,7 @@ mod model { pub transactions_hash: HashOf>, /// Creation timestamp (unix time in milliseconds). #[getset(skip)] - pub timestamp_ms: u64, + pub creation_time_ms: u64, /// Value of view change index. Used to resolve soft forks. #[getset(skip)] pub view_change_index: u32, @@ -147,8 +147,8 @@ impl BlockHeader { } /// Creation timestamp - pub const fn timestamp(&self) -> Duration { - Duration::from_millis(self.timestamp_ms) + pub const fn creation_time(&self) -> Duration { + Duration::from_millis(self.creation_time_ms) } /// Consensus estimation @@ -291,13 +291,13 @@ impl SignedBlock { .hash() .expect("Tree is not empty"); let first_transaction = &genesis_transactions[0]; - let timestamp_ms = u64::try_from(first_transaction.creation_time().as_millis()) + let creation_time_ms = u64::try_from(first_transaction.creation_time().as_millis()) .expect("Must fit since Duration was created from u64 in creation_time()"); let header = BlockHeader { height: 1, prev_block_hash: None, transactions_hash, - timestamp_ms, + creation_time_ms, view_change_index: 0, consensus_estimation_ms: 0, }; diff --git a/data_model/src/events/data/events.rs b/data_model/src/events/data/events.rs index 766872cc0d2..faf5f540a0e 100644 --- a/data_model/src/events/data/events.rs +++ b/data_model/src/events/data/events.rs @@ -244,11 +244,11 @@ mod role { #[has_origin(role => role.id())] Created(Role), Deleted(RoleId), - /// [`Permission`]s with particular [`PermissionId`] + /// [`Permission`]s with particular [`Permission`] /// were removed from the role. #[has_origin(permission_removed => &permission_removed.role)] PermissionRemoved(RolePermissionChanged), - /// [`Permission`]s with particular [`PermissionId`] + /// [`Permission`]s with particular [`Permission`] /// were removed added to the role. #[has_origin(permission_added => &permission_added.role)] PermissionAdded(RolePermissionChanged), @@ -280,7 +280,7 @@ mod role { pub role: RoleId, // TODO: Skipped temporarily because of FFI #[getset(skip)] - pub permission: PermissionId, + pub permission: Permission, } } } @@ -345,7 +345,7 @@ mod account { pub account: AccountId, // TODO: Skipped temporarily because of FFI #[getset(skip)] - pub permission: PermissionId, + pub permission: Permission, } /// Depending on the wrapping event, [`AccountRoleChanged`] represents the granted or revoked role @@ -373,7 +373,7 @@ mod account { impl AccountPermissionChanged { /// Get permission id - pub fn permission(&self) -> &PermissionId { + pub fn permission(&self) -> &Permission { &self.permission } } diff --git a/data_model/src/events/pipeline.rs b/data_model/src/events/pipeline.rs index 731e194c505..6d74eec41e1 100644 --- a/data_model/src/events/pipeline.rs +++ b/data_model/src/events/pipeline.rs @@ -357,7 +357,7 @@ mod tests { transactions_hash: HashOf::from_untyped_unchecked(Hash::prehashed( [1_u8; Hash::LENGTH], )), - timestamp_ms: 0, + creation_time_ms: 0, view_change_index: 0, consensus_estimation_ms: 0, } diff --git a/data_model/src/executor.rs b/data_model/src/executor.rs index 4e030b1c3b6..448f849ff2f 100644 --- a/data_model/src/executor.rs +++ b/data_model/src/executor.rs @@ -13,7 +13,7 @@ use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; pub use self::model::*; -use crate::{permission::PermissionId, transaction::WasmSmartContract, JsonString}; +use crate::{name::Name, transaction::WasmSmartContract, JsonString}; #[model] mod model { @@ -82,7 +82,7 @@ mod model { /// Permission tokens supported by the executor. /// /// These IDs refer to the types in the schema. - pub permissions: BTreeSet, + pub permissions: BTreeSet, /// Type id in the schema. /// Corresponds to payload of `InstructionBox::Custom`. /// @@ -103,7 +103,7 @@ mod model { // currently it fails for all fields impl ExecutorDataModel { /// Getter - pub fn permissions(&self) -> &BTreeSet { + pub fn permissions(&self) -> &BTreeSet { &self.permissions } diff --git a/data_model/src/isi.rs b/data_model/src/isi.rs index c7024cb8d2f..e8b9dd5fc36 100644 --- a/data_model/src/isi.rs +++ b/data_model/src/isi.rs @@ -1250,7 +1250,7 @@ pub mod error { pub use self::model::*; use super::InstructionType; use crate::{ - asset::AssetValueType, + asset::AssetType, metadata, query::error::{FindError, QueryExecutionFail}, IdBox, @@ -1394,18 +1394,18 @@ pub mod error { #[ffi_type] pub enum TypeError { /// Asset Ids correspond to assets with different underlying types, {0} - AssetValueType(#[cfg_attr(feature = "std", source)] Mismatch), + AssetType(#[cfg_attr(feature = "std", source)] Mismatch), /// Numeric asset value type was expected, received: {0} NumericAssetValueTypeExpected( #[skip_from] #[skip_try_from] - AssetValueType, + AssetType, ), /// Store asset value type was expected, received: {0} StoreAssetValueTypeExpected( #[skip_from] #[skip_try_from] - AssetValueType, + AssetType, ), } @@ -1504,7 +1504,7 @@ pub mod error { TimeTriggerInThePast, } - /// Repetition of of `{instruction_type}` for id `{id}` + /// Repetition of of `{instruction}` for id `{id}` #[derive( Debug, displaydoc::Display, @@ -1523,7 +1523,7 @@ pub mod error { #[ffi_type] pub struct RepetitionError { /// Instruction type - pub instruction_type: InstructionType, + pub instruction: InstructionType, /// Id of the object being repeated pub id: IdBox, } diff --git a/data_model/src/lib.rs b/data_model/src/lib.rs index aecffef2df4..e271c27ed1e 100644 --- a/data_model/src/lib.rs +++ b/data_model/src/lib.rs @@ -688,7 +688,7 @@ mod model { /// [`RoleId`](`role::RoleId`) variant. RoleId(role::RoleId), /// [`Permission`](`permission::Permission`) variant. - PermissionId(permission::PermissionId), + Permission(permission::Permission), /// [`ParameterId`](`parameter::ParameterId`) variant. ParameterId(parameter::ParameterId), } @@ -974,7 +974,7 @@ impl_encode_as_id_box! { asset::AssetDefinitionId, asset::AssetId, trigger::TriggerId, - permission::PermissionId, + permission::Permission, role::RoleId, parameter::ParameterId, } diff --git a/data_model/src/permission.rs b/data_model/src/permission.rs index 253c1784d37..4594af79296 100644 --- a/data_model/src/permission.rs +++ b/data_model/src/permission.rs @@ -21,35 +21,6 @@ use super::*; mod model { use super::*; - /// Identifies a [`Permission`]. - /// The executor defines available permission names. - #[derive( - Debug, - Display, - Clone, - PartialEq, - Eq, - PartialOrd, - Ord, - Hash, - Constructor, - FromStr, - Getters, - Decode, - Encode, - Deserialize, - Serialize, - IntoSchema, - )] - #[getset(get = "pub")] - #[serde(transparent)] - #[repr(transparent)] - #[ffi_type(opaque)] - pub struct PermissionId { - /// Should be unique. - pub name: Name, - } - /// Stored proof of the account having a permission for a certain action. #[derive( Debug, @@ -67,11 +38,11 @@ mod model { Getters, )] #[ffi_type] - #[display(fmt = "PERMISSION `{id}` = `{payload}`")] + #[display(fmt = "PERMISSION `{name}` = `{payload}`")] #[getset(get = "pub")] pub struct Permission { /// Refers to a type defined in [`crate::executor::ExecutorDataModel`]. - pub id: PermissionId, + pub name: Name, /// Payload containing actual value. /// /// It is JSON-encoded, and its structure must correspond to the structure of @@ -83,9 +54,9 @@ mod model { impl Permission { /// Constructor - pub fn new(id: PermissionId, payload: impl Into) -> Self { + pub fn new(name: Name, payload: impl Into) -> Self { Self { - id, + name, payload: payload.into(), } } @@ -99,5 +70,5 @@ impl Permission { pub mod prelude { //! The prelude re-exports most commonly used traits, structs and macros from this crate. - pub use super::{Permission, PermissionId}; + pub use super::Permission; } diff --git a/data_model/src/query/cursor.rs b/data_model/src/query/cursor.rs index 3deaba04750..9f4b9ac6aad 100644 --- a/data_model/src/query/cursor.rs +++ b/data_model/src/query/cursor.rs @@ -16,11 +16,13 @@ use parity_scale_codec::{Decode, Encode, Input}; use serde::Serialize; pub use self::model::*; -use super::QueryId; -const QUERY_ID: &str = "query_id"; +const QUERY_ID: &str = "query"; const CURSOR: &str = "cursor"; +/// Unique id of a query +pub type QueryId = String; + #[model] mod model { use super::*; @@ -31,15 +33,15 @@ mod model { pub struct ForwardCursor { /// Unique ID of query. When provided in a query the query will look up if there /// is was already a query with a matching ID and resume returning result batches - pub query_id: Option, + pub query: Option, /// Pointer to the next element in the result set pub cursor: Option, } impl ForwardCursor { /// Create a new cursor. - pub const fn new(query_id: Option, cursor: Option) -> Self { - Self { query_id, cursor } + pub const fn new(query: Option, cursor: Option) -> Self { + Self { query, cursor } } } } @@ -51,7 +53,7 @@ mod candidate { #[derive(Decode, Deserialize)] struct ForwardCursorCandidate { - query_id: Option, + query: Option, cursor: Option, } @@ -62,9 +64,9 @@ mod candidate { { let candidate = ForwardCursorCandidate::deserialize(deserializer)?; - if let Some(query_id) = candidate.query_id { + if let Some(query_id) = candidate.query { Ok(ForwardCursor { - query_id: Some(query_id), + query: Some(query_id), cursor: candidate.cursor, }) } else if candidate.cursor.is_some() { @@ -79,9 +81,9 @@ mod candidate { fn decode(input: &mut I) -> Result { let candidate = ForwardCursorCandidate::decode(input)?; - if let Some(query_id) = candidate.query_id { + if let Some(query_id) = candidate.query { Ok(ForwardCursor { - query_id: Some(query_id), + query: Some(query_id), cursor: candidate.cursor, }) } else if candidate.cursor.is_some() { @@ -95,7 +97,7 @@ mod candidate { impl From for Vec<(&'static str, QueryId)> { fn from(cursor: ForwardCursor) -> Self { - match (cursor.query_id, cursor.cursor) { + match (cursor.query, cursor.cursor) { (Some(query_id), Some(cursor)) => { vec![(QUERY_ID, query_id), (CURSOR, cursor.to_string())] } diff --git a/data_model/src/query/mod.rs b/data_model/src/query/mod.rs index 92ec08b6750..aaa23ff4155 100644 --- a/data_model/src/query/mod.rs +++ b/data_model/src/query/mod.rs @@ -44,8 +44,6 @@ pub mod pagination; pub mod predicate; pub mod sorting; -const FETCH_SIZE: &str = "fetch_size"; - /// Default value for `fetch_size` parameter in queries. pub const DEFAULT_FETCH_SIZE: NonZeroU32 = nonzero!(10_u32); @@ -74,19 +72,6 @@ pub struct FetchSize { pub fetch_size: Option, } -impl FetchSize { - /// Converts self to iterator of tuples to be used in queries. - /// - /// The length of the output iterator is not constant and has either 0 or 1 value. - pub fn into_query_parameters( - self, - ) -> impl IntoIterator + Clone { - self.fetch_size - .map(|fetch_size| (FETCH_SIZE, fetch_size)) - .into_iter() - } -} - macro_rules! queries { ($($($meta:meta)* $item:item)+) => { pub use self::model::*; @@ -106,9 +91,6 @@ macro_rules! queries { }; } -/// Unique id of a query. -pub type QueryId = String; - /// Trait for typesafe query output pub trait Query: Into + seal::Sealed { /// Output type of query @@ -137,7 +119,7 @@ mod model { use strum::EnumDiscriminants; use super::*; - use crate::{block::SignedBlock, permission::PermissionId}; + use crate::block::SignedBlock; /// Sized container for all possible Queries. #[allow(clippy::enum_variant_names)] @@ -729,25 +711,25 @@ pub mod account { /// [`FindAccountsByDomainId`] Iroha Query gets [`Domain`]s id as input and /// finds all [`Account`]s under this [`Domain`]. #[derive(Display)] - #[display(fmt = "Find accounts under `{domain_id}` domain")] + #[display(fmt = "Find accounts under `{domain}` domain")] #[repr(transparent)] // SAFETY: `FindAccountsByDomainId` has no trap representation in `EvaluatesTo` #[ffi_type(unsafe {robust})] pub struct FindAccountsByDomainId { /// `Id` of the domain under which accounts should be found. - pub domain_id: DomainId, + pub domain: DomainId, } /// [`FindAccountsWithAsset`] Iroha Query gets [`AssetDefinition`]s id as input and /// finds all [`Account`]s storing [`Asset`] with such definition. #[derive(Display)] - #[display(fmt = "Find accounts with `{asset_definition_id}` asset")] + #[display(fmt = "Find accounts with `{asset_definition}` asset")] #[repr(transparent)] // SAFETY: `FindAccountsWithAsset` has no trap representation in `EvaluatesTo` #[ffi_type(unsafe {robust})] pub struct FindAccountsWithAsset { /// `Id` of the definition of the asset which should be stored in founded accounts. - pub asset_definition_id: AssetDefinitionId, + pub asset_definition: AssetDefinitionId, } } @@ -826,50 +808,50 @@ pub mod asset { /// [`FindAssetsByAccountId`] Iroha Query gets [`AccountId`] as input and find all [`Asset`]s /// owned by the [`Account`] in Iroha Peer. #[derive(Display)] - #[display(fmt = "Find assets owned by the `{account_id}` account")] + #[display(fmt = "Find assets owned by the `{account}` account")] #[repr(transparent)] // SAFETY: `FindAssetsByAccountId` has no trap representation in `EvaluatesTo` #[ffi_type(unsafe {robust})] pub struct FindAssetsByAccountId { /// [`AccountId`] under which assets should be found. - pub account_id: AccountId, + pub account: AccountId, } /// [`FindAssetsByAssetDefinitionId`] Iroha Query gets [`AssetDefinitionId`] as input and /// finds all [`Asset`]s with this [`AssetDefinition`] in Iroha Peer. #[derive(Display)] - #[display(fmt = "Find assets with `{asset_definition_id}` asset definition")] + #[display(fmt = "Find assets with `{asset_definition}` asset definition")] #[repr(transparent)] // SAFETY: `FindAssetsByAssetDefinitionId` has no trap representation in `EvaluatesTo` #[ffi_type(unsafe {robust})] pub struct FindAssetsByAssetDefinitionId { /// [`AssetDefinitionId`] with type of [`Asset`]s should be found. - pub asset_definition_id: AssetDefinitionId, + pub asset_definition: AssetDefinitionId, } /// [`FindAssetsByDomainId`] Iroha Query gets [`Domain`]s id as input and /// finds all [`Asset`]s under this [`Domain`] in Iroha [`Peer`]. #[derive(Display)] - #[display(fmt = "Find assets under the `{domain_id}` domain")] + #[display(fmt = "Find assets under the `{domain}` domain")] #[repr(transparent)] // SAFETY: `FindAssetsByDomainId` has no trap representation in `EvaluatesTo` #[ffi_type(unsafe {robust})] pub struct FindAssetsByDomainId { /// `Id` of the domain under which assets should be found. - pub domain_id: DomainId, + pub domain: DomainId, } /// [`FindAssetsByDomainIdAndAssetDefinitionId`] Iroha Query gets [`DomainId`] and /// [`AssetDefinitionId`] as inputs and finds [`Asset`]s under the [`Domain`] /// with this [`AssetDefinition`] in Iroha [`Peer`]. #[derive(Display)] - #[display(fmt = "Find assets under the `{domain_id}` domain with `{asset_definition_id}` asset definition")] + #[display(fmt = "Find assets under the `{domain}` domain with `{asset_definition}` asset definition")] #[ffi_type] pub struct FindAssetsByDomainIdAndAssetDefinitionId { /// `Id` of the domain under which assets should be found. - pub domain_id: DomainId, + pub domain: DomainId, /// [`AssetDefinitionId`] assets of which type should be found. - pub asset_definition_id: AssetDefinitionId, + pub asset_definition: AssetDefinitionId, } /// [`FindAssetQuantityById`] Iroha Query gets [`AssetId`] as input and finds [`Asset::quantity`] @@ -1088,24 +1070,24 @@ pub mod trigger { /// Find all triggers executable on behalf of the given account. #[derive(Display)] - #[display(fmt = "Find triggers executable on behalf of the `{account_id}` account")] + #[display(fmt = "Find triggers executable on behalf of the `{account}` account")] #[repr(transparent)] // SAFETY: `FindTriggersByAuthorityId` has no trap representation in `EvaluatesTo` #[ffi_type(unsafe {robust})] pub struct FindTriggersByAuthorityId { /// [`AccountId`] specifies the authority behind the trigger execution. - pub account_id: AccountId, + pub account: AccountId, } /// Find all triggers whose authority belongs to the given domain. #[derive(Display)] - #[display(fmt = "Find triggers with authority under `{domain_id}` domain")] + #[display(fmt = "Find triggers with authority under `{domain}` domain")] #[repr(transparent)] // SAFETY: `FindTriggersByAuthorityDomainId` has no trap representation in `EvaluatesTo` #[ffi_type(unsafe {robust})] pub struct FindTriggersByAuthorityDomainId { /// [`DomainId`] specifies the domain in which to search for triggers. - pub domain_id: DomainId, + pub domain: DomainId, } } @@ -1143,13 +1125,13 @@ pub mod transaction { /// [`FindTransactionsByAccountId`] Iroha Query finds all transactions included in a blockchain /// for the account #[derive(Display)] - #[display(fmt = "Find all transactions for `{account_id}` account")] + #[display(fmt = "Find all transactions for `{account}` account")] #[repr(transparent)] // SAFETY: `FindTransactionsByAccountId` has no trap representation in `EvaluatesTo` #[ffi_type(unsafe {robust})] pub struct FindTransactionsByAccountId { /// Signer's [`AccountId`] under which transactions should be found. - pub account_id: AccountId, + pub account: AccountId, } /// [`FindTransactionByHash`] Iroha Query finds a transaction (if any) @@ -1289,6 +1271,7 @@ pub mod http { /// Signature of the client who sends this query. pub signature: QuerySignature, /// Payload + #[serde(flatten)] pub payload: ClientQueryPayload, } @@ -1555,8 +1538,8 @@ pub mod error { Trigger(TriggerId), /// Role with id `{0}` not found Role(RoleId), - /// Failed to find [`Permission`] by id. - Permission(PermissionId), + /// Failed to find [`Permission`] + Permission(Permission), /// Parameter with id `{0}` not found Parameter(ParameterId), /// Failed to find public key: `{0}` @@ -1574,6 +1557,6 @@ pub mod prelude { account::prelude::*, asset::prelude::*, block::prelude::*, domain::prelude::*, executor::prelude::*, peer::prelude::*, permission::prelude::*, predicate::PredicateTrait, role::prelude::*, transaction::prelude::*, trigger::prelude::*, FetchSize, QueryBox, - QueryId, TransactionQueryOutput, + TransactionQueryOutput, }; } diff --git a/data_model/src/query/pagination.rs b/data_model/src/query/pagination.rs index 9b5fea05866..61943e7018f 100644 --- a/data_model/src/query/pagination.rs +++ b/data_model/src/query/pagination.rs @@ -19,9 +19,6 @@ use iroha_schema::IntoSchema; use parity_scale_codec::{Decode, Encode}; use serde::{Deserialize, Serialize}; -const PAGINATION_START: &str = "start"; -const PAGINATION_LIMIT: &str = "limit"; - /// Structure for pagination requests #[derive( Debug, @@ -50,25 +47,6 @@ pub struct Pagination { pub start: Option, } -impl Pagination { - /// Converts self to iterator of tuples to be used in queries - /// - /// The length of the output iterator is not constant and it's in (0..3) - pub fn into_query_parameters( - self, - ) -> impl IntoIterator + Clone { - let result_vec = match (self.start, self.limit) { - (Some(start), Some(limit)) => { - vec![(PAGINATION_LIMIT, limit.into()), (PAGINATION_START, start)] - } - (Some(start), None) => vec![(PAGINATION_START, start)], - (None, Some(limit)) => vec![(PAGINATION_LIMIT, limit.into())], - (None, None) => Vec::new(), - }; - result_vec.into_iter() - } -} - pub mod prelude { //! Prelude: re-export most commonly used traits, structs and macros from this module. pub use super::*; diff --git a/data_model/src/query/predicate.rs b/data_model/src/query/predicate.rs index 87b4e80917e..87826313597 100644 --- a/data_model/src/query/predicate.rs +++ b/data_model/src/query/predicate.rs @@ -601,7 +601,7 @@ pub mod string { IdBox::PeerId(id) => self.applies(&id.to_string()), IdBox::TriggerId(id) => self.applies(&id.to_string()), IdBox::RoleId(id) => self.applies(&id.to_string()), - IdBox::PermissionId(id) => self.applies(&id.to_string()), + IdBox::Permission(id) => self.applies(&id.to_string()), IdBox::ParameterId(id) => self.applies(&id.to_string()), } } @@ -1162,7 +1162,7 @@ pub mod value { QueryOutputPredicate::Display(pred) => pred.applies(&input.to_string()), QueryOutputPredicate::TimeStamp(pred) => match input { QueryOutputBox::Block(block) => { - pred.applies(block.header().timestamp().as_millis()) + pred.applies(block.header().creation_time().as_millis()) } _ => false, }, diff --git a/data_model/src/query/sorting.rs b/data_model/src/query/sorting.rs index 386e82a174b..82b2aeb595b 100644 --- a/data_model/src/query/sorting.rs +++ b/data_model/src/query/sorting.rs @@ -16,8 +16,6 @@ use serde::{Deserialize, Serialize}; pub use self::model::*; use crate::{name::Name, prelude::*}; -const SORT_BY_KEY: &str = "sort_by_metadata_key"; - #[model] mod model { use super::*; @@ -41,17 +39,6 @@ impl Sorting { } } -impl Sorting { - /// Converts self to iterator of tuples to be used in queries - /// - /// The length of the output iterator is not constant and has either 0 or 1 value - pub fn into_query_parameters(self) -> impl IntoIterator + Clone { - self.sort_by_metadata_key - .map(|key| (SORT_BY_KEY, key)) - .into_iter() - } -} - pub mod prelude { //! Prelude: re-export most commonly used traits, structs and macros from this module. pub use super::*; diff --git a/docs/source/references/schema.json b/docs/source/references/schema.json index e633ae613e1..abe35f2e0b0 100644 --- a/docs/source/references/schema.json +++ b/docs/source/references/schema.json @@ -157,7 +157,7 @@ }, { "name": "permission", - "type": "PermissionId" + "type": "Permission" } ] }, @@ -266,8 +266,8 @@ "type": "AssetDefinitionId" }, { - "name": "value_type", - "type": "AssetValueType" + "name": "type_", + "type": "AssetType" }, { "name": "mintable", @@ -512,30 +512,30 @@ } ] }, - "AssetValue": { + "AssetType": { "Enum": [ { "tag": "Numeric", "discriminant": 0, - "type": "Numeric" + "type": "NumericSpec" }, { "tag": "Store", - "discriminant": 1, - "type": "Metadata" + "discriminant": 1 } ] }, - "AssetValueType": { + "AssetValue": { "Enum": [ { "tag": "Numeric", "discriminant": 0, - "type": "NumericSpec" + "type": "Numeric" }, { "tag": "Store", - "discriminant": 1 + "discriminant": 1, + "type": "Metadata" } ] }, @@ -615,7 +615,7 @@ "type": "HashOf>" }, { - "name": "timestamp_ms", + "name": "creation_time_ms", "type": "u64" }, { @@ -1205,7 +1205,7 @@ "Struct": [ { "name": "permissions", - "type": "SortedVec" + "type": "SortedVec" }, { "name": "custom_instruction", @@ -1292,7 +1292,7 @@ "FindAccountsByDomainId": { "Struct": [ { - "name": "domain_id", + "name": "domain", "type": "DomainId" } ] @@ -1300,7 +1300,7 @@ "FindAccountsWithAsset": { "Struct": [ { - "name": "asset_definition_id", + "name": "asset_definition", "type": "AssetDefinitionId" } ] @@ -1368,7 +1368,7 @@ "FindAssetsByAccountId": { "Struct": [ { - "name": "account_id", + "name": "account", "type": "AccountId" } ] @@ -1376,7 +1376,7 @@ "FindAssetsByAssetDefinitionId": { "Struct": [ { - "name": "asset_definition_id", + "name": "asset_definition", "type": "AssetDefinitionId" } ] @@ -1384,7 +1384,7 @@ "FindAssetsByDomainId": { "Struct": [ { - "name": "domain_id", + "name": "domain", "type": "DomainId" } ] @@ -1392,11 +1392,11 @@ "FindAssetsByDomainIdAndAssetDefinitionId": { "Struct": [ { - "name": "domain_id", + "name": "domain", "type": "DomainId" }, { - "name": "asset_definition_id", + "name": "asset_definition", "type": "AssetDefinitionId" } ] @@ -1492,7 +1492,7 @@ { "tag": "Permission", "discriminant": 10, - "type": "PermissionId" + "type": "Permission" }, { "tag": "Parameter", @@ -1550,7 +1550,7 @@ "FindTransactionsByAccountId": { "Struct": [ { - "name": "account_id", + "name": "account", "type": "AccountId" } ] @@ -1578,7 +1578,7 @@ "FindTriggersByAuthorityDomainId": { "Struct": [ { - "name": "domain_id", + "name": "domain", "type": "DomainId" } ] @@ -1586,7 +1586,7 @@ "FindTriggersByAuthorityId": { "Struct": [ { - "name": "account_id", + "name": "account", "type": "AccountId" } ] @@ -1594,7 +1594,7 @@ "ForwardCursor": { "Struct": [ { - "name": "query_id", + "name": "query", "type": "Option" }, { @@ -1724,9 +1724,9 @@ "type": "RoleId" }, { - "tag": "PermissionId", + "tag": "Permission", "discriminant": 7, - "type": "PermissionId" + "type": "Permission" }, { "tag": "ParameterId", @@ -2372,15 +2372,15 @@ } ] }, - "Mismatch": { + "Mismatch": { "Struct": [ { "name": "expected", - "type": "AssetValueType" + "type": "AssetType" }, { "name": "actual", - "type": "AssetValueType" + "type": "AssetType" } ] }, @@ -2404,8 +2404,8 @@ "type": "AssetDefinitionId" }, { - "name": "value_type", - "type": "AssetValueType" + "name": "type_", + "type": "AssetType" }, { "name": "mintable", @@ -2668,8 +2668,8 @@ "Permission": { "Struct": [ { - "name": "id", - "type": "PermissionId" + "name": "name", + "type": "Name" }, { "name": "payload", @@ -2677,14 +2677,6 @@ } ] }, - "PermissionId": { - "Struct": [ - { - "name": "name", - "type": "Name" - } - ] - }, "PipelineEventBox": { "Enum": [ { @@ -3263,7 +3255,7 @@ "RepetitionError": { "Struct": [ { - "name": "instruction_type", + "name": "instruction", "type": "InstructionType" }, { @@ -3414,7 +3406,7 @@ }, { "name": "permission", - "type": "PermissionId" + "type": "Permission" } ] }, @@ -3745,12 +3737,12 @@ "value": "MetadataValueBox" } }, + "SortedVec": { + "Vec": "Name" + }, "SortedVec": { "Vec": "Permission" }, - "SortedVec": { - "Vec": "PermissionId" - }, "Sorting": { "Struct": [ { @@ -4224,19 +4216,19 @@ "TypeError": { "Enum": [ { - "tag": "AssetValueType", + "tag": "AssetType", "discriminant": 0, - "type": "Mismatch" + "type": "Mismatch" }, { "tag": "NumericAssetValueTypeExpected", "discriminant": 1, - "type": "AssetValueType" + "type": "AssetType" }, { "tag": "StoreAssetValueTypeExpected", "discriminant": 2, - "type": "AssetValueType" + "type": "AssetType" } ] }, diff --git a/genesis/src/lib.rs b/genesis/src/lib.rs index 095b5a50793..387f8363e30 100644 --- a/genesis/src/lib.rs +++ b/genesis/src/lib.rs @@ -261,7 +261,7 @@ impl GenesisDomainBuilder { } /// Add [`AssetDefinition`] to current domain. - pub fn asset(mut self, asset_name: Name, asset_value_type: AssetValueType) -> Self { + pub fn asset(mut self, asset_name: Name, asset_value_type: AssetType) -> Self { let asset_definition_id = AssetDefinitionId::new(self.domain_id.clone(), asset_name); let asset_definition = AssetDefinition::new(asset_definition_id, asset_value_type); self.instructions @@ -319,7 +319,7 @@ mod tests { .account(public_key["mad_hatter"].clone()) .asset( "hats".parse().unwrap(), - AssetValueType::Numeric(NumericSpec::default()), + AssetType::Numeric(NumericSpec::default()), ) .finish_domain(); diff --git a/schema/gen/src/lib.rs b/schema/gen/src/lib.rs index 312c3f23ce7..981d07badc8 100644 --- a/schema/gen/src/lib.rs +++ b/schema/gen/src/lib.rs @@ -86,15 +86,15 @@ types!( AssetId, AssetTransferBox, AssetValue, - AssetValueType, + AssetType, AtIndex, BTreeMap, BTreeMap, BTreeMap, BTreeMap, BTreeMap, + BTreeSet, BTreeSet, - BTreeSet, BatchedResponse, BatchedResponseV1, BlockEvent, @@ -228,7 +228,7 @@ types!( MintBox, MintabilityError, Mintable, - Mismatch, + Mismatch, Name, NewAccount, NewAssetDefinition, @@ -273,7 +273,6 @@ types!( PeerEventFilter, PeerEventSet, PeerId, - PermissionId, RolePermissionChanged, Permission, PipelineEventBox, diff --git a/smart_contract/executor/derive/src/permission.rs b/smart_contract/executor/derive/src/permission.rs index 0cb6f5c3a39..c062a068186 100644 --- a/smart_contract/executor/derive/src/permission.rs +++ b/smart_contract/executor/derive/src/permission.rs @@ -18,7 +18,7 @@ pub fn impl_derive_permission(input: &syn::DeriveInput) -> TokenStream { account_id.clone(), ) ) - .expect("`FindPermissionsByAccountId` query should never fail, it's a bug"); + .expect("INTERNAL BUG: `FindPermissionsByAccountId` should never fail"); account_tokens_cursor .into_iter() @@ -34,11 +34,9 @@ pub fn impl_derive_permission(input: &syn::DeriveInput) -> TokenStream { impl #impl_generics TryFrom<&::iroha_executor::data_model::permission::Permission> for #ident #ty_generics #where_clause { type Error = ::iroha_executor::TryFromDataModelObjectError; - fn try_from( - value: &::iroha_executor::data_model::permission::Permission, - ) -> core::result::Result { - if *value.id() != ::id() { - return Err(Self::Error::Id(value.id().name().clone())); + fn try_from(value: &::iroha_executor::data_model::permission::Permission) -> core::result::Result { + if *value.name() != ::name() { + return Err(Self::Error::UnknownName(value.name().clone())); } serde_json::from_str::(value.payload().as_ref()).map_err(Self::Error::Deserialize) @@ -48,7 +46,7 @@ pub fn impl_derive_permission(input: &syn::DeriveInput) -> TokenStream { impl #impl_generics From<#ident #ty_generics> for ::iroha_executor::data_model::permission::Permission #where_clause { fn from(value: #ident #ty_generics) -> Self { ::iroha_executor::data_model::permission::Permission::new( - <#ident as ::iroha_executor::permission::Permission>::id(), + <#ident as ::iroha_executor::permission::Permission>::name(), ::serde_json::to_value::<#ident #ty_generics>(value) .expect("INTERNAL BUG: Failed to serialize Executor data model entity"), ) diff --git a/smart_contract/executor/src/default/permissions.rs b/smart_contract/executor/src/default/permissions.rs index 735ef253942..4d2e6dd69bb 100644 --- a/smart_contract/executor/src/default/permissions.rs +++ b/smart_contract/executor/src/default/permissions.rs @@ -46,12 +46,12 @@ macro_rules! declare_permissions { type Error = $crate::TryFromDataModelObjectError; fn try_from(token: &$crate::data_model::permission::Permission) -> Result { - match token.id().name().as_ref() { $( + match token.name().as_ref() { $( stringify!($token_ty) => { let token = <$($token_path::)+$token_ty>::try_from(token)?; Ok(Self::$token_ty(token)) } )+ - _ => Err(Self::Error::Id(token.id().name().clone())) + _ => Err(Self::Error::UnknownName(token.name().clone())) } } } diff --git a/smart_contract/executor/src/lib.rs b/smart_contract/executor/src/lib.rs index 78b34b0f198..4e9e0b4046e 100644 --- a/smart_contract/executor/src/lib.rs +++ b/smart_contract/executor/src/lib.rs @@ -179,8 +179,8 @@ macro_rules! deny { /// Such objects are [`data_model::prelude::Permission`] and [`data_model::prelude::Parameter`]. #[derive(Debug)] pub enum TryFromDataModelObjectError { - /// Unexpected object id - Id(data_model::prelude::Name), + /// Unexpected object name + UnknownName(data_model::prelude::Name), /// Failed to deserialize object payload Deserialize(serde_json::Error), } @@ -188,7 +188,7 @@ pub enum TryFromDataModelObjectError { /// A convenience to build [`ExecutorDataModel`] from within the executor #[derive(Debug, Clone)] pub struct DataModelBuilder { - permissions: BTreeSet, + permissions: BTreeSet, custom_instruction: Option, schema: MetaMap, } @@ -225,7 +225,8 @@ impl DataModelBuilder { #[must_use] pub fn add_permission(mut self) -> Self { ::update_schema_map(&mut self.schema); - self.permissions.insert(::id()); + self.permissions + .insert(::name()); self } @@ -243,7 +244,7 @@ impl DataModelBuilder { pub fn remove_permission(mut self) -> Self { ::remove_from_schema(&mut self.schema); self.permissions - .remove(&::id()); + .remove(&::name()); self } @@ -256,7 +257,7 @@ impl DataModelBuilder { serde_json::to_value(&self.schema) .expect("INTERNAL BUG: Failed to serialize Executor data model entity") .into(), - )) + )); } } diff --git a/smart_contract/executor/src/permission.rs b/smart_contract/executor/src/permission.rs index a6ead932324..c11375903a9 100644 --- a/smart_contract/executor/src/permission.rs +++ b/smart_contract/executor/src/permission.rs @@ -17,12 +17,10 @@ pub trait Permission: fn is_owned_by(&self, account_id: &AccountId) -> bool; /// Permission id, according to [`IntoSchema`]. - fn id() -> PermissionId { - PermissionId::new( - ::type_name() - .parse() - .dbg_expect("Failed to parse permission id as `Name`"), - ) + fn name() -> Name { + ::type_name() + .parse() + .dbg_expect("Failed to parse permission id as `Name`") } } diff --git a/tools/kagami/src/genesis/generate.rs b/tools/kagami/src/genesis/generate.rs index fc4453daa17..97b841cc553 100644 --- a/tools/kagami/src/genesis/generate.rs +++ b/tools/kagami/src/genesis/generate.rs @@ -99,16 +99,13 @@ pub fn generate_default( .domain_with_metadata("wonderland".parse()?, meta.clone()) .account_with_metadata(ALICE_ID.signatory().clone(), meta.clone()) .account_with_metadata(BOB_ID.signatory().clone(), meta) - .asset( - "rose".parse()?, - AssetValueType::Numeric(NumericSpec::default()), - ) + .asset("rose".parse()?, AssetType::Numeric(NumericSpec::default())) .finish_domain() .domain("garden_of_live_flowers".parse()?) .account(CARPENTER_ID.signatory().clone()) .asset( "cabbage".parse()?, - AssetValueType::Numeric(NumericSpec::default()), + AssetType::Numeric(NumericSpec::default()), ) .finish_domain(); @@ -250,7 +247,7 @@ fn generate_synthetic( genesis.append_instruction( Register::asset_definition(AssetDefinition::new( asset_definition_id, - AssetValueType::Numeric(NumericSpec::default()), + AssetType::Numeric(NumericSpec::default()), )) .into(), ); diff --git a/tools/swarm/src/lib.rs b/tools/swarm/src/lib.rs index 73f4a885967..9194b66506d 100644 --- a/tools/swarm/src/lib.rs +++ b/tools/swarm/src/lib.rs @@ -196,7 +196,7 @@ mod tests { API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E GENESIS_PRIVATE_KEY: 802640FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E - GENESIS_SIGNED_FILE: /tmp/genesis.signed.scale + GENESIS: /tmp/genesis.signed.scale TOPOLOGY: '[{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"}]' ports: - 1337:1337 @@ -216,7 +216,7 @@ mod tests { kagami genesis sign /tmp/genesis.json \\ --public-key $$GENESIS_PUBLIC_KEY \\ --private-key $$GENESIS_PRIVATE_KEY \\ - --out-file $$GENESIS_SIGNED_FILE \\ + --out-file $$GENESIS \\ && \\ irohad --submit-genesis " @@ -254,7 +254,7 @@ mod tests { API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E GENESIS_PRIVATE_KEY: 802640FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E - GENESIS_SIGNED_FILE: /tmp/genesis.signed.scale + GENESIS: /tmp/genesis.signed.scale TOPOLOGY: '[{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"}]' ports: - 1337:1337 @@ -274,7 +274,7 @@ mod tests { kagami genesis sign /tmp/genesis.json \\ --public-key $$GENESIS_PUBLIC_KEY \\ --private-key $$GENESIS_PRIVATE_KEY \\ - --out-file $$GENESIS_SIGNED_FILE \\ + --out-file $$GENESIS \\ && \\ irohad --submit-genesis " @@ -301,7 +301,7 @@ mod tests { API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E GENESIS_PRIVATE_KEY: 802640FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E - GENESIS_SIGNED_FILE: /tmp/genesis.signed.scale + GENESIS: /tmp/genesis.signed.scale TOPOLOGY: '[{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"}]' ports: - 1337:1337 @@ -327,7 +327,7 @@ mod tests { kagami genesis sign /tmp/genesis.json \\ --public-key $$GENESIS_PUBLIC_KEY \\ --private-key $$GENESIS_PRIVATE_KEY \\ - --out-file $$GENESIS_SIGNED_FILE \\ + --out-file $$GENESIS \\ && \\ irohad --submit-genesis " @@ -354,9 +354,9 @@ mod tests { P2P_ADDRESS: 0.0.0.0:1337 API_ADDRESS: 0.0.0.0:8080 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' + TRUSTED_PEERS: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' GENESIS_PRIVATE_KEY: 802640FB8B867188E4952F1E83534B9B2E0A12D5122BD6F417CBC79D50D8A8C9C917B0F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E - GENESIS_SIGNED_FILE: /tmp/genesis.signed.scale + GENESIS: /tmp/genesis.signed.scale TOPOLOGY: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' ports: - 1337:1337 @@ -382,7 +382,7 @@ mod tests { kagami genesis sign /tmp/genesis.json \\ --public-key $$GENESIS_PUBLIC_KEY \\ --private-key $$GENESIS_PRIVATE_KEY \\ - --out-file $$GENESIS_SIGNED_FILE \\ + --out-file $$GENESIS \\ && \\ irohad --submit-genesis " @@ -396,7 +396,7 @@ mod tests { P2P_ADDRESS: 0.0.0.0:1338 API_ADDRESS: 0.0.0.0:8081 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' + TRUSTED_PEERS: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' ports: - 1338:1338 - 8081:8081 @@ -419,7 +419,7 @@ mod tests { P2P_ADDRESS: 0.0.0.0:1339 API_ADDRESS: 0.0.0.0:8082 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"}]' + TRUSTED_PEERS: '[{"address":"irohad3:1340","public_key":"ed012063ED3DFEDEBD8A86B4941CC4379D2EF0B74BDFE61F033FC0C89867D57C882A26"},{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"}]' ports: - 1339:1339 - 8082:8082 @@ -442,7 +442,7 @@ mod tests { P2P_ADDRESS: 0.0.0.0:1340 API_ADDRESS: 0.0.0.0:8083 GENESIS_PUBLIC_KEY: ed0120F9F92758E815121F637C9704DFDA54842BA937AA721C0603018E208D6E25787E - SUMERAGI_TRUSTED_PEERS: '[{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' + TRUSTED_PEERS: '[{"address":"irohad1:1338","public_key":"ed012064BD9B25BF8477144D03B26FC8CF5D8A354B2F780DA310EE69933DC1E86FBCE2"},{"address":"irohad0:1337","public_key":"ed012087FDCACF58B891947600B0C37795CADB5A2AE6DE612338FDA9489AB21CE427BA"},{"address":"irohad2:1339","public_key":"ed01208EA177921AF051CD12FC07E3416419320908883A1104B31401B650EEB820A300"}]' ports: - 1340:1340 - 8083:8083 diff --git a/tools/swarm/src/schema.rs b/tools/swarm/src/schema.rs index b6304648c67..e0005f45f6b 100644 --- a/tools/swarm/src/schema.rs +++ b/tools/swarm/src/schema.rs @@ -153,7 +153,7 @@ struct PeerEnv<'a> { genesis_public_key: &'a iroha_crypto::PublicKey, #[serde(skip_serializing_if = "std::collections::BTreeSet::is_empty")] #[serde_as(as = "serde_with::json::JsonString")] - sumeragi_trusted_peers: std::collections::BTreeSet<&'a iroha_data_model::peer::PeerId>, + trusted_peers: std::collections::BTreeSet<&'a iroha_data_model::peer::PeerId>, } impl<'a> PeerEnv<'a> { @@ -171,7 +171,7 @@ impl<'a> PeerEnv<'a> { p2p_address: iroha_primitives::addr::socket_addr!(0.0.0.0:port_p2p), api_address: iroha_primitives::addr::socket_addr!(0.0.0.0:port_api), genesis_public_key, - sumeragi_trusted_peers: topology + trusted_peers: topology .iter() .filter(|&peer| peer.public_key() != public_key) .collect(), @@ -186,7 +186,7 @@ struct GenesisEnv<'a> { #[serde(flatten)] base: PeerEnv<'a>, genesis_private_key: &'a iroha_crypto::ExposedPrivateKey, - genesis_signed_file: ContainerPath<'a>, + genesis: ContainerPath<'a>, #[serde_as(as = "serde_with::json::JsonString")] topology: std::collections::BTreeSet<&'a iroha_data_model::peer::PeerId>, } @@ -202,7 +202,7 @@ impl<'a> GenesisEnv<'a> { Self { base: PeerEnv::new(key_pair, ports, chain, genesis_public_key, topology), genesis_private_key, - genesis_signed_file: ContainerPath(GENESIS_SIGNED_FILE), + genesis: ContainerPath(GENESIS), topology: topology.iter().collect(), } } @@ -218,7 +218,7 @@ struct PortMapping(u16, u16); struct ContainerPath<'a>(&'a str); const CONTAINER_CONFIG_DIR: &str = "/config"; -const GENESIS_SIGNED_FILE: &str = "/tmp/genesis.signed.scale"; +const GENESIS: &str = "/tmp/genesis.signed.scale"; /// Mapping between `host:container` paths. #[derive(Copy, Clone, Debug)] @@ -297,7 +297,7 @@ const SIGN_AND_SUBMIT_GENESIS: &str = r#"/bin/sh -c " kagami genesis sign /tmp/genesis.json \\ --public-key $$GENESIS_PUBLIC_KEY \\ --private-key $$GENESIS_PRIVATE_KEY \\ - --out-file $$GENESIS_SIGNED_FILE \\ + --out-file $$GENESIS \\ && \\ irohad --submit-genesis ""#;