olas-operate-middleware 0.7.0__py3-none-any.whl → 0.8.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {olas_operate_middleware-0.7.0.dist-info → olas_operate_middleware-0.8.1.dist-info}/METADATA +1 -1
- {olas_operate_middleware-0.7.0.dist-info → olas_operate_middleware-0.8.1.dist-info}/RECORD +18 -17
- operate/bridge/providers/relay_provider.py +1 -1
- operate/cli.py +114 -105
- operate/ledger/profiles.py +9 -35
- operate/operate_types.py +10 -0
- operate/quickstart/claim_staking_rewards.py +1 -1
- operate/quickstart/reset_staking.py +1 -1
- operate/quickstart/run_service.py +19 -26
- operate/quickstart/terminate_on_chain_service.py +1 -1
- operate/quickstart/utils.py +0 -1
- operate/services/agent_runner.py +1 -1
- operate/services/manage.py +126 -99
- operate/services/service.py +24 -1
- operate/utils/ssl.py +133 -0
- {olas_operate_middleware-0.7.0.dist-info → olas_operate_middleware-0.8.1.dist-info}/LICENSE +0 -0
- {olas_operate_middleware-0.7.0.dist-info → olas_operate_middleware-0.8.1.dist-info}/WHEEL +0 -0
- {olas_operate_middleware-0.7.0.dist-info → olas_operate_middleware-0.8.1.dist-info}/entry_points.txt +0 -0
operate/operate_types.py
CHANGED
|
@@ -329,3 +329,13 @@ class AssetFundingValues(TypedDict):
|
|
|
329
329
|
|
|
330
330
|
|
|
331
331
|
FundingValues = t.Dict[str, AssetFundingValues] # str is the asset address
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
@dataclass
|
|
335
|
+
class MechMarketplaceConfig:
|
|
336
|
+
"""Mech Marketplace config."""
|
|
337
|
+
|
|
338
|
+
use_mech_marketplace: bool
|
|
339
|
+
mech_marketplace_address: str
|
|
340
|
+
priority_mech_address: str
|
|
341
|
+
priority_mech_service_id: int
|
|
@@ -73,7 +73,7 @@ def claim_staking_rewards(operate: "OperateApp", config_path: str) -> None:
|
|
|
73
73
|
config = configure_local_config(template, operate)
|
|
74
74
|
manager = operate.service_manager()
|
|
75
75
|
service = get_service(manager, template)
|
|
76
|
-
ask_password_if_needed(operate
|
|
76
|
+
ask_password_if_needed(operate)
|
|
77
77
|
|
|
78
78
|
# reload manger and config after setting operate.password
|
|
79
79
|
manager = operate.service_manager()
|
|
@@ -82,7 +82,7 @@ def reset_staking(operate: "OperateApp", config_path: str) -> None:
|
|
|
82
82
|
print("Cancelled.")
|
|
83
83
|
return
|
|
84
84
|
|
|
85
|
-
ask_password_if_needed(operate
|
|
85
|
+
ask_password_if_needed(operate)
|
|
86
86
|
manager = operate.service_manager()
|
|
87
87
|
service = get_service(manager, template)
|
|
88
88
|
|
|
@@ -37,14 +37,7 @@ from operate.account.user import UserAccount
|
|
|
37
37
|
from operate.constants import IPFS_ADDRESS, OPERATE_HOME
|
|
38
38
|
from operate.data import DATA_DIR
|
|
39
39
|
from operate.data.contracts.staking_token.contract import StakingTokenContract
|
|
40
|
-
from operate.ledger.profiles import
|
|
41
|
-
DEFAULT_PRIORITY_MECH_ADDRESS,
|
|
42
|
-
DEFAULT_PRIORITY_MECH_SERVICE_ID,
|
|
43
|
-
NO_STAKING_PROGRAM_ID,
|
|
44
|
-
STAKING,
|
|
45
|
-
get_staking_contract,
|
|
46
|
-
get_staking_program_mech_type,
|
|
47
|
-
)
|
|
40
|
+
from operate.ledger.profiles import NO_STAKING_PROGRAM_ID, STAKING, get_staking_contract
|
|
48
41
|
from operate.operate_types import (
|
|
49
42
|
Chain,
|
|
50
43
|
LedgerType,
|
|
@@ -208,9 +201,6 @@ def configure_local_config(
|
|
|
208
201
|
)
|
|
209
202
|
os.environ[f"{chain.upper()}_LEDGER_RPC"] = config.rpc[chain]
|
|
210
203
|
|
|
211
|
-
if config.password_migrated is None:
|
|
212
|
-
config.password_migrated = False
|
|
213
|
-
|
|
214
204
|
config.principal_chain = template["home_chain"]
|
|
215
205
|
|
|
216
206
|
home_chain = Chain.from_string(config.principal_chain)
|
|
@@ -396,15 +386,18 @@ def configure_local_config(
|
|
|
396
386
|
):
|
|
397
387
|
print_section("Please enter the arguments that will be used by the service.")
|
|
398
388
|
|
|
399
|
-
|
|
389
|
+
service_manager = operate.service_manager()
|
|
390
|
+
mech_configs = service_manager.get_mech_configs(
|
|
391
|
+
chain=config.principal_chain,
|
|
392
|
+
ledger_api=ledger_api,
|
|
393
|
+
staking_program_id=config.staking_program_id,
|
|
394
|
+
)
|
|
400
395
|
|
|
401
396
|
for env_var_name, env_var_data in template["env_variables"].items():
|
|
402
397
|
if env_var_data["provision_type"] == ServiceEnvProvisionType.USER:
|
|
403
398
|
# PRIORITY_MECH_ADDRESS and PRIORITY_MECH_SERVICE_ID are given dynamic default values
|
|
404
399
|
if env_var_name == "PRIORITY_MECH_ADDRESS":
|
|
405
|
-
env_var_data["value"] =
|
|
406
|
-
staking_program_mech_type
|
|
407
|
-
]
|
|
400
|
+
env_var_data["value"] = mech_configs.priority_mech_address
|
|
408
401
|
if (
|
|
409
402
|
env_var_name in config.user_provided_args
|
|
410
403
|
and env_var_data["value"] != config.user_provided_args[env_var_name]
|
|
@@ -412,9 +405,7 @@ def configure_local_config(
|
|
|
412
405
|
del config.user_provided_args[env_var_name]
|
|
413
406
|
|
|
414
407
|
if env_var_name == "PRIORITY_MECH_SERVICE_ID":
|
|
415
|
-
env_var_data["value"] =
|
|
416
|
-
DEFAULT_PRIORITY_MECH_SERVICE_ID.get(staking_program_mech_type, 0)
|
|
417
|
-
)
|
|
408
|
+
env_var_data["value"] = mech_configs.priority_mech_service_id
|
|
418
409
|
if (
|
|
419
410
|
env_var_name in config.user_provided_args
|
|
420
411
|
and env_var_data["value"] != config.user_provided_args[env_var_name]
|
|
@@ -456,7 +447,7 @@ def configure_local_config(
|
|
|
456
447
|
return config
|
|
457
448
|
|
|
458
449
|
|
|
459
|
-
def ask_password_if_needed(operate: "OperateApp"
|
|
450
|
+
def ask_password_if_needed(operate: "OperateApp") -> None:
|
|
460
451
|
"""Ask password if needed."""
|
|
461
452
|
if operate.user_account is None:
|
|
462
453
|
print_section("Set up local user account")
|
|
@@ -466,8 +457,6 @@ def ask_password_if_needed(operate: "OperateApp", config: QuickstartConfig) -> N
|
|
|
466
457
|
password=password,
|
|
467
458
|
path=operate._path / "user.json",
|
|
468
459
|
)
|
|
469
|
-
config.password_migrated = True
|
|
470
|
-
config.store()
|
|
471
460
|
else:
|
|
472
461
|
_password = None
|
|
473
462
|
while _password is None:
|
|
@@ -620,8 +609,8 @@ def _ask_funds_from_requirements(
|
|
|
620
609
|
return False
|
|
621
610
|
|
|
622
611
|
|
|
623
|
-
def
|
|
624
|
-
"""
|
|
612
|
+
def _maybe_create_master_eoa(operate: "OperateApp") -> None:
|
|
613
|
+
"""Maybe create the Master EOA."""
|
|
625
614
|
if not operate.wallet_manager.exists(ledger_type=LedgerType.ETHEREUM):
|
|
626
615
|
print("Creating the Master EOA...")
|
|
627
616
|
wallet, mnemonic = operate.wallet_manager.create(
|
|
@@ -636,9 +625,12 @@ def ensure_enough_funds(operate: "OperateApp", service: Service) -> None:
|
|
|
636
625
|
ask_or_get_from_env(
|
|
637
626
|
"Press enter to continue...", False, "CONTINUE", raise_if_missing=False
|
|
638
627
|
)
|
|
639
|
-
else:
|
|
640
|
-
wallet = operate.wallet_manager.load(ledger_type=LedgerType.ETHEREUM)
|
|
641
628
|
|
|
629
|
+
|
|
630
|
+
def ensure_enough_funds(operate: "OperateApp", service: Service) -> None:
|
|
631
|
+
"""Ensure enough funds."""
|
|
632
|
+
_maybe_create_master_eoa(operate)
|
|
633
|
+
wallet = operate.wallet_manager.load(ledger_type=LedgerType.ETHEREUM)
|
|
642
634
|
manager = operate.service_manager()
|
|
643
635
|
|
|
644
636
|
backup_owner = None
|
|
@@ -677,11 +669,12 @@ def run_service(
|
|
|
677
669
|
|
|
678
670
|
operate.service_manager().migrate_service_configs()
|
|
679
671
|
operate.wallet_manager.migrate_wallet_configs()
|
|
672
|
+
ask_password_if_needed(operate)
|
|
673
|
+
_maybe_create_master_eoa(operate)
|
|
680
674
|
|
|
681
675
|
config = configure_local_config(template, operate)
|
|
682
676
|
manager = operate.service_manager()
|
|
683
677
|
service = get_service(manager, template)
|
|
684
|
-
ask_password_if_needed(operate, config)
|
|
685
678
|
|
|
686
679
|
# reload manger and config after setting operate.password
|
|
687
680
|
manager = operate.service_manager(skip_dependency_check=skip_dependency_check)
|
|
@@ -62,7 +62,7 @@ def terminate_service(operate: "OperateApp", config_path: str) -> None:
|
|
|
62
62
|
return
|
|
63
63
|
|
|
64
64
|
config = configure_local_config(template, operate)
|
|
65
|
-
ask_password_if_needed(operate
|
|
65
|
+
ask_password_if_needed(operate)
|
|
66
66
|
manager = operate.service_manager()
|
|
67
67
|
service = get_service(manager, template)
|
|
68
68
|
ensure_enough_funds(operate, service)
|
operate/quickstart/utils.py
CHANGED
|
@@ -277,7 +277,6 @@ class QuickstartConfig(LocalResource):
|
|
|
277
277
|
|
|
278
278
|
path: Path
|
|
279
279
|
rpc: Optional[Dict[str, str]] = None
|
|
280
|
-
password_migrated: Optional[bool] = None
|
|
281
280
|
staking_program_id: Optional[str] = None
|
|
282
281
|
principal_chain: Optional[str] = None
|
|
283
282
|
user_provided_args: Optional[Dict[str, str]] = None
|
operate/services/agent_runner.py
CHANGED
|
@@ -71,7 +71,7 @@ AGENTS_SUPPORTED = {
|
|
|
71
71
|
owner="valory-xyz", repo="optimus", release="v0.0.103"
|
|
72
72
|
),
|
|
73
73
|
"dvilela/memeooorr": AgentRelease(
|
|
74
|
-
owner="valory-xyz", repo="meme-ooorr
|
|
74
|
+
owner="valory-xyz", repo="meme-ooorr", release="v0.0.101"
|
|
75
75
|
),
|
|
76
76
|
}
|
|
77
77
|
|
operate/services/manage.py
CHANGED
|
@@ -36,7 +36,7 @@ from pathlib import Path
|
|
|
36
36
|
import requests
|
|
37
37
|
from aea.helpers.base import IPFSHash
|
|
38
38
|
from aea.helpers.logging import setup_logger
|
|
39
|
-
from aea_ledger_ethereum import EthereumCrypto
|
|
39
|
+
from aea_ledger_ethereum import EthereumCrypto, LedgerApi
|
|
40
40
|
from autonomy.chain.base import registry_contracts
|
|
41
41
|
from autonomy.chain.config import CHAIN_PROFILES, ChainType
|
|
42
42
|
|
|
@@ -52,19 +52,18 @@ from operate.ledger import PUBLIC_RPCS, get_currency_denom
|
|
|
52
52
|
from operate.ledger.profiles import (
|
|
53
53
|
CONTRACTS,
|
|
54
54
|
DEFAULT_MASTER_EOA_FUNDS,
|
|
55
|
-
|
|
56
|
-
DEFAULT_PRIORITY_MECH_SERVICE_ID,
|
|
55
|
+
DEFAULT_PRIORITY_MECH,
|
|
57
56
|
OLAS,
|
|
58
57
|
STAKING,
|
|
59
58
|
USDC,
|
|
60
59
|
WRAPPED_NATIVE_ASSET,
|
|
61
60
|
get_staking_contract,
|
|
62
|
-
get_staking_program_mech_type,
|
|
63
61
|
)
|
|
64
62
|
from operate.operate_types import (
|
|
65
63
|
Chain,
|
|
66
64
|
FundingValues,
|
|
67
65
|
LedgerConfig,
|
|
66
|
+
MechMarketplaceConfig,
|
|
68
67
|
OnChainState,
|
|
69
68
|
ServiceEnvProvisionType,
|
|
70
69
|
ServiceTemplate,
|
|
@@ -520,6 +519,103 @@ class ServiceManager:
|
|
|
520
519
|
chain=chain,
|
|
521
520
|
)
|
|
522
521
|
|
|
522
|
+
def get_mech_configs(
|
|
523
|
+
self,
|
|
524
|
+
chain: str,
|
|
525
|
+
ledger_api: LedgerApi,
|
|
526
|
+
staking_program_id: str | None = None,
|
|
527
|
+
) -> MechMarketplaceConfig:
|
|
528
|
+
"""Get the mech configs."""
|
|
529
|
+
sftxb = self.get_eth_safe_tx_builder(
|
|
530
|
+
ledger_config=LedgerConfig(
|
|
531
|
+
chain=Chain(chain),
|
|
532
|
+
rpc=ledger_api.api.provider.endpoint_uri,
|
|
533
|
+
)
|
|
534
|
+
)
|
|
535
|
+
staking_contract = get_staking_contract(
|
|
536
|
+
chain=chain,
|
|
537
|
+
staking_program_id=staking_program_id,
|
|
538
|
+
)
|
|
539
|
+
if staking_contract is None:
|
|
540
|
+
return MechMarketplaceConfig(
|
|
541
|
+
use_mech_marketplace=False,
|
|
542
|
+
mech_marketplace_address=ZERO_ADDRESS,
|
|
543
|
+
priority_mech_address=ZERO_ADDRESS,
|
|
544
|
+
priority_mech_service_id=0,
|
|
545
|
+
)
|
|
546
|
+
|
|
547
|
+
target_staking_params = sftxb.get_staking_params(
|
|
548
|
+
staking_contract=get_staking_contract(
|
|
549
|
+
chain=chain,
|
|
550
|
+
staking_program_id=staking_program_id,
|
|
551
|
+
),
|
|
552
|
+
)
|
|
553
|
+
|
|
554
|
+
try:
|
|
555
|
+
# Try if activity checker is a MechActivityChecker contract
|
|
556
|
+
mech_activity_contract = t.cast(
|
|
557
|
+
MechActivityContract,
|
|
558
|
+
MechActivityContract.from_dir(
|
|
559
|
+
directory=str(DATA_DIR / "contracts" / "mech_activity")
|
|
560
|
+
),
|
|
561
|
+
)
|
|
562
|
+
|
|
563
|
+
priority_mech_address = (
|
|
564
|
+
mech_activity_contract.get_instance(
|
|
565
|
+
ledger_api=ledger_api,
|
|
566
|
+
contract_address=target_staking_params["activity_checker"],
|
|
567
|
+
)
|
|
568
|
+
.functions.agentMech()
|
|
569
|
+
.call()
|
|
570
|
+
)
|
|
571
|
+
use_mech_marketplace = False
|
|
572
|
+
mech_marketplace_address = ZERO_ADDRESS
|
|
573
|
+
priority_mech_service_id = 0
|
|
574
|
+
|
|
575
|
+
except Exception: # pylint: disable=broad-except
|
|
576
|
+
# Try if activity checker is a RequesterActivityChecker contract
|
|
577
|
+
try:
|
|
578
|
+
requester_activity_checker = t.cast(
|
|
579
|
+
RequesterActivityCheckerContract,
|
|
580
|
+
RequesterActivityCheckerContract.from_dir(
|
|
581
|
+
directory=str(
|
|
582
|
+
DATA_DIR / "contracts" / "requester_activity_checker"
|
|
583
|
+
)
|
|
584
|
+
),
|
|
585
|
+
)
|
|
586
|
+
|
|
587
|
+
mech_marketplace_address = (
|
|
588
|
+
requester_activity_checker.get_instance(
|
|
589
|
+
ledger_api=ledger_api,
|
|
590
|
+
contract_address=target_staking_params["activity_checker"],
|
|
591
|
+
)
|
|
592
|
+
.functions.mechMarketplace()
|
|
593
|
+
.call()
|
|
594
|
+
)
|
|
595
|
+
|
|
596
|
+
use_mech_marketplace = True
|
|
597
|
+
priority_mech_address, priority_mech_service_id = DEFAULT_PRIORITY_MECH[
|
|
598
|
+
mech_marketplace_address
|
|
599
|
+
]
|
|
600
|
+
|
|
601
|
+
except Exception as e: # pylint: disable=broad-except
|
|
602
|
+
self.logger.error(f"{e}: {traceback.format_exc()}")
|
|
603
|
+
self.logger.warning(
|
|
604
|
+
"Cannot determine type of activity checker contract. Using default parameters. "
|
|
605
|
+
"NOTE: This will be an exception in the future!"
|
|
606
|
+
)
|
|
607
|
+
priority_mech_address = "0x77af31De935740567Cf4fF1986D04B2c964A786a"
|
|
608
|
+
use_mech_marketplace = False
|
|
609
|
+
mech_marketplace_address = ZERO_ADDRESS
|
|
610
|
+
priority_mech_service_id = 0
|
|
611
|
+
|
|
612
|
+
return MechMarketplaceConfig(
|
|
613
|
+
use_mech_marketplace=use_mech_marketplace,
|
|
614
|
+
mech_marketplace_address=mech_marketplace_address,
|
|
615
|
+
priority_mech_address=priority_mech_address,
|
|
616
|
+
priority_mech_service_id=priority_mech_service_id,
|
|
617
|
+
)
|
|
618
|
+
|
|
523
619
|
def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,too-many-locals
|
|
524
620
|
self,
|
|
525
621
|
service_config_id: str,
|
|
@@ -556,10 +652,6 @@ class ServiceManager:
|
|
|
556
652
|
self.logger.info(f"Service state: {on_chain_state.name}")
|
|
557
653
|
|
|
558
654
|
current_staking_program = self._get_current_staking_program(service, chain)
|
|
559
|
-
staking_program_mech_type = get_staking_program_mech_type(
|
|
560
|
-
user_params.staking_program_id
|
|
561
|
-
)
|
|
562
|
-
self.logger.info(f"{staking_program_mech_type=}")
|
|
563
655
|
fallback_params = dict( # nosec
|
|
564
656
|
staking_contract=NULL_ADDRESS,
|
|
565
657
|
agent_ids=[user_params.agent_id],
|
|
@@ -588,94 +680,29 @@ class ServiceManager:
|
|
|
588
680
|
# TODO A customized, arbitrary computation mechanism should be devised.
|
|
589
681
|
env_var_to_value = {}
|
|
590
682
|
if chain == service.home_chain:
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
directory=str(DATA_DIR / "contracts" / "mech_activity")
|
|
597
|
-
),
|
|
598
|
-
)
|
|
599
|
-
|
|
600
|
-
agent_mech = (
|
|
601
|
-
mech_activity_contract.get_instance(
|
|
602
|
-
ledger_api=sftxb.ledger_api,
|
|
603
|
-
contract_address=target_staking_params["activity_checker"],
|
|
604
|
-
)
|
|
605
|
-
.functions.agentMech()
|
|
606
|
-
.call()
|
|
607
|
-
)
|
|
608
|
-
use_mech_marketplace = False
|
|
609
|
-
mech_marketplace_address = ZERO_ADDRESS
|
|
610
|
-
priority_mech_address = ZERO_ADDRESS
|
|
611
|
-
priority_mech_service_id = DEFAULT_PRIORITY_MECH_SERVICE_ID.get(
|
|
612
|
-
staking_program_mech_type, 0
|
|
613
|
-
)
|
|
614
|
-
|
|
615
|
-
except Exception: # pylint: disable=broad-except
|
|
616
|
-
# Try if activity checker is a RequesterActivityChecker contract
|
|
617
|
-
try:
|
|
618
|
-
requester_activity_checker = t.cast(
|
|
619
|
-
RequesterActivityCheckerContract,
|
|
620
|
-
RequesterActivityCheckerContract.from_dir(
|
|
621
|
-
directory=str(
|
|
622
|
-
DATA_DIR / "contracts" / "requester_activity_checker"
|
|
623
|
-
)
|
|
624
|
-
),
|
|
625
|
-
)
|
|
626
|
-
|
|
627
|
-
mech_marketplace_address = (
|
|
628
|
-
requester_activity_checker.get_instance(
|
|
629
|
-
ledger_api=sftxb.ledger_api,
|
|
630
|
-
contract_address=target_staking_params["activity_checker"],
|
|
631
|
-
)
|
|
632
|
-
.functions.mechMarketplace()
|
|
633
|
-
.call()
|
|
634
|
-
)
|
|
683
|
+
mech_configs: MechMarketplaceConfig = self.get_mech_configs(
|
|
684
|
+
chain=chain,
|
|
685
|
+
ledger_api=sftxb.ledger_api,
|
|
686
|
+
staking_program_id=user_params.staking_program_id,
|
|
687
|
+
)
|
|
635
688
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
agent_mech = priority_mech_address = service.env_variables[
|
|
645
|
-
"PRIORITY_MECH_ADDRESS"
|
|
646
|
-
]["value"]
|
|
647
|
-
else:
|
|
648
|
-
agent_mech = (
|
|
649
|
-
priority_mech_address
|
|
650
|
-
) = DEFAULT_PRIORITY_MECH_ADDRESS[staking_program_mech_type]
|
|
651
|
-
|
|
652
|
-
if (
|
|
653
|
-
"PRIORITY_MECH_SERVICE_ID" in service.env_variables
|
|
654
|
-
and service.env_variables["PRIORITY_MECH_SERVICE_ID"][
|
|
655
|
-
"provision_type"
|
|
656
|
-
]
|
|
657
|
-
== ServiceEnvProvisionType.USER
|
|
658
|
-
):
|
|
659
|
-
priority_mech_service_id = service.env_variables[
|
|
660
|
-
"PRIORITY_MECH_SERVICE_ID"
|
|
661
|
-
]["value"]
|
|
662
|
-
else:
|
|
663
|
-
priority_mech_service_id = DEFAULT_PRIORITY_MECH_SERVICE_ID.get(
|
|
664
|
-
staking_program_mech_type, 0
|
|
665
|
-
)
|
|
689
|
+
if (
|
|
690
|
+
"PRIORITY_MECH_ADDRESS" in service.env_variables
|
|
691
|
+
and service.env_variables["PRIORITY_MECH_ADDRESS"]["provision_type"]
|
|
692
|
+
== ServiceEnvProvisionType.USER
|
|
693
|
+
):
|
|
694
|
+
mech_configs.priority_mech_address = service.env_variables[
|
|
695
|
+
"PRIORITY_MECH_ADDRESS"
|
|
696
|
+
]["value"]
|
|
666
697
|
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
use_mech_marketplace = False
|
|
676
|
-
mech_marketplace_address = ZERO_ADDRESS
|
|
677
|
-
priority_mech_address = ZERO_ADDRESS
|
|
678
|
-
priority_mech_service_id = 0
|
|
698
|
+
if (
|
|
699
|
+
"PRIORITY_MECH_SERVICE_ID" in service.env_variables
|
|
700
|
+
and service.env_variables["PRIORITY_MECH_SERVICE_ID"]["provision_type"]
|
|
701
|
+
== ServiceEnvProvisionType.USER
|
|
702
|
+
):
|
|
703
|
+
mech_configs.priority_mech_service_id = service.env_variables[
|
|
704
|
+
"PRIORITY_MECH_SERVICE_ID"
|
|
705
|
+
]["value"]
|
|
679
706
|
|
|
680
707
|
env_var_to_value.update(
|
|
681
708
|
{
|
|
@@ -693,10 +720,10 @@ class ServiceManager:
|
|
|
693
720
|
"staking_contract"
|
|
694
721
|
),
|
|
695
722
|
"MECH_MARKETPLACE_CONFIG": (
|
|
696
|
-
f'{{"mech_marketplace_address":"{mech_marketplace_address}",'
|
|
697
|
-
f'"priority_mech_address":"{priority_mech_address}",'
|
|
723
|
+
f'{{"mech_marketplace_address":"{mech_configs.mech_marketplace_address}",'
|
|
724
|
+
f'"priority_mech_address":"{mech_configs.priority_mech_address}",'
|
|
698
725
|
f'"priority_mech_staking_instance_address":"0x998dEFafD094817EF329f6dc79c703f1CF18bC90",'
|
|
699
|
-
f'"priority_mech_service_id":{priority_mech_service_id},'
|
|
726
|
+
f'"priority_mech_service_id":{mech_configs.priority_mech_service_id},'
|
|
700
727
|
f'"requester_staking_instance_address":"{target_staking_params.get("staking_contract")}",'
|
|
701
728
|
f'"response_timeout":300}}'
|
|
702
729
|
),
|
|
@@ -706,9 +733,9 @@ class ServiceManager:
|
|
|
706
733
|
"MECH_ACTIVITY_CHECKER_CONTRACT": target_staking_params.get(
|
|
707
734
|
"activity_checker"
|
|
708
735
|
),
|
|
709
|
-
"MECH_CONTRACT_ADDRESS":
|
|
736
|
+
"MECH_CONTRACT_ADDRESS": mech_configs.priority_mech_address,
|
|
710
737
|
"MECH_REQUEST_PRICE": "10000000000000000",
|
|
711
|
-
"USE_MECH_MARKETPLACE": use_mech_marketplace,
|
|
738
|
+
"USE_MECH_MARKETPLACE": mech_configs.use_mech_marketplace,
|
|
712
739
|
}
|
|
713
740
|
)
|
|
714
741
|
|
operate/services/service.py
CHANGED
|
@@ -88,6 +88,7 @@ from operate.operate_types import (
|
|
|
88
88
|
from operate.resource import LocalResource
|
|
89
89
|
from operate.services.deployment_runner import run_host_deployment, stop_host_deployment
|
|
90
90
|
from operate.services.utils import tendermint
|
|
91
|
+
from operate.utils.ssl import create_ssl_certificate
|
|
91
92
|
|
|
92
93
|
|
|
93
94
|
# pylint: disable=no-member,redefined-builtin,too-many-instance-attributes,too-many-locals
|
|
@@ -686,13 +687,35 @@ class Deployment(LocalResource):
|
|
|
686
687
|
service = Service.load(path=self.path)
|
|
687
688
|
|
|
688
689
|
if use_docker or use_kubernetes:
|
|
689
|
-
|
|
690
|
+
ssl_key_path, ssl_cert_path = create_ssl_certificate(
|
|
691
|
+
ssl_dir=service.path / PERSISTENT_DATA_DIR / "ssl"
|
|
692
|
+
)
|
|
693
|
+
service.update_env_variables_values(
|
|
694
|
+
{
|
|
695
|
+
"STORE_PATH": "/data",
|
|
696
|
+
"SSL_KEY_PATH": (
|
|
697
|
+
Path("/data") / "ssl" / ssl_key_path.name
|
|
698
|
+
).as_posix(),
|
|
699
|
+
"SSL_CERT_PATH": (
|
|
700
|
+
Path("/data") / "ssl" / ssl_cert_path.name
|
|
701
|
+
).as_posix(),
|
|
702
|
+
}
|
|
703
|
+
)
|
|
690
704
|
service.consume_env_variables()
|
|
691
705
|
if use_docker:
|
|
692
706
|
self._build_docker(force=force, chain=chain)
|
|
693
707
|
if use_kubernetes:
|
|
694
708
|
self._build_kubernetes(force=force)
|
|
695
709
|
else:
|
|
710
|
+
ssl_key_path, ssl_cert_path = create_ssl_certificate(
|
|
711
|
+
ssl_dir=service.path / DEPLOYMENT / "ssl"
|
|
712
|
+
)
|
|
713
|
+
service.update_env_variables_values(
|
|
714
|
+
{
|
|
715
|
+
"SSL_KEY_PATH": str(ssl_key_path),
|
|
716
|
+
"SSL_CERT_PATH": str(ssl_cert_path),
|
|
717
|
+
}
|
|
718
|
+
)
|
|
696
719
|
service.consume_env_variables()
|
|
697
720
|
self._build_host(force=force, chain=chain)
|
|
698
721
|
|
operate/utils/ssl.py
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# ------------------------------------------------------------------------------
|
|
3
|
+
#
|
|
4
|
+
# Copyright 2025 Valory AG
|
|
5
|
+
#
|
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
# you may not use this file except in compliance with the License.
|
|
8
|
+
# You may obtain a copy of the License at
|
|
9
|
+
#
|
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
#
|
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
# See the License for the specific language governing permissions and
|
|
16
|
+
# limitations under the License.
|
|
17
|
+
#
|
|
18
|
+
# ------------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
"""SSL certificate utilities."""
|
|
21
|
+
|
|
22
|
+
import datetime
|
|
23
|
+
import logging
|
|
24
|
+
import typing as t
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
from cryptography import x509
|
|
28
|
+
from cryptography.hazmat.primitives import hashes, serialization
|
|
29
|
+
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
30
|
+
from cryptography.x509.oid import NameOID
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def create_ssl_certificate(
|
|
34
|
+
ssl_dir: Path,
|
|
35
|
+
key_filename: str = "key.pem",
|
|
36
|
+
cert_filename: str = "cert.pem",
|
|
37
|
+
validity_days: int = 365,
|
|
38
|
+
key_size: int = 2048,
|
|
39
|
+
common_name: str = "localhost",
|
|
40
|
+
) -> t.Tuple[Path, Path]:
|
|
41
|
+
"""
|
|
42
|
+
Create SSL certificate and private key files.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
ssl_dir: Path to the ssl directory
|
|
46
|
+
key_filename: Name of the private key file
|
|
47
|
+
cert_filename: Name of the certificate file
|
|
48
|
+
validity_days: Number of days the certificate is valid
|
|
49
|
+
key_size: RSA key size in bits
|
|
50
|
+
common_name: Common name for the certificate
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Tuple of (key_path, cert_path) as Path objects
|
|
54
|
+
"""
|
|
55
|
+
logger = logging.getLogger(__name__)
|
|
56
|
+
|
|
57
|
+
# Create SSL directory
|
|
58
|
+
ssl_dir.mkdir(parents=True, exist_ok=True)
|
|
59
|
+
|
|
60
|
+
key_path = ssl_dir / key_filename
|
|
61
|
+
cert_path = ssl_dir / cert_filename
|
|
62
|
+
|
|
63
|
+
# Generate RSA private key
|
|
64
|
+
private_key = rsa.generate_private_key(
|
|
65
|
+
public_exponent=65537,
|
|
66
|
+
key_size=key_size,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Create certificate subject and issuer
|
|
70
|
+
subject = issuer = x509.Name(
|
|
71
|
+
[
|
|
72
|
+
x509.NameAttribute(NameOID.COUNTRY_NAME, "CH"),
|
|
73
|
+
x509.NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Local"),
|
|
74
|
+
x509.NameAttribute(NameOID.LOCALITY_NAME, "Local"),
|
|
75
|
+
x509.NameAttribute(NameOID.ORGANIZATION_NAME, "Valory AG"),
|
|
76
|
+
x509.NameAttribute(NameOID.COMMON_NAME, common_name),
|
|
77
|
+
]
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
# Create certificate
|
|
81
|
+
cert = (
|
|
82
|
+
x509.CertificateBuilder()
|
|
83
|
+
.subject_name(subject)
|
|
84
|
+
.issuer_name(issuer)
|
|
85
|
+
.public_key(private_key.public_key())
|
|
86
|
+
.serial_number(1)
|
|
87
|
+
.not_valid_before(datetime.datetime.now(datetime.timezone.utc))
|
|
88
|
+
.not_valid_after(
|
|
89
|
+
datetime.datetime.now(datetime.timezone.utc)
|
|
90
|
+
+ datetime.timedelta(days=validity_days)
|
|
91
|
+
)
|
|
92
|
+
.add_extension(
|
|
93
|
+
x509.BasicConstraints(ca=False, path_length=None),
|
|
94
|
+
critical=True,
|
|
95
|
+
)
|
|
96
|
+
.add_extension(
|
|
97
|
+
x509.KeyUsage(
|
|
98
|
+
digital_signature=True,
|
|
99
|
+
key_encipherment=True,
|
|
100
|
+
key_agreement=False,
|
|
101
|
+
key_cert_sign=False,
|
|
102
|
+
crl_sign=False,
|
|
103
|
+
content_commitment=False,
|
|
104
|
+
data_encipherment=False,
|
|
105
|
+
encipher_only=False,
|
|
106
|
+
decipher_only=False,
|
|
107
|
+
),
|
|
108
|
+
critical=True,
|
|
109
|
+
)
|
|
110
|
+
.add_extension(
|
|
111
|
+
x509.ExtendedKeyUsage([x509.ExtendedKeyUsageOID.SERVER_AUTH]),
|
|
112
|
+
critical=True,
|
|
113
|
+
)
|
|
114
|
+
.sign(private_key, hashes.SHA256())
|
|
115
|
+
)
|
|
116
|
+
|
|
117
|
+
# Write private key to file
|
|
118
|
+
with open(key_path, "wb") as f:
|
|
119
|
+
f.write(
|
|
120
|
+
private_key.private_bytes(
|
|
121
|
+
encoding=serialization.Encoding.PEM,
|
|
122
|
+
format=serialization.PrivateFormat.PKCS8,
|
|
123
|
+
encryption_algorithm=serialization.NoEncryption(),
|
|
124
|
+
)
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Write certificate to file
|
|
128
|
+
with open(cert_path, "wb") as f:
|
|
129
|
+
f.write(cert.public_bytes(serialization.Encoding.PEM))
|
|
130
|
+
|
|
131
|
+
logger.info(f"SSL certificate created successfully at {key_path} and {cert_path}")
|
|
132
|
+
|
|
133
|
+
return key_path, cert_path
|
|
File without changes
|
|
File without changes
|
{olas_operate_middleware-0.7.0.dist-info → olas_operate_middleware-0.8.1.dist-info}/entry_points.txt
RENAMED
|
File without changes
|