Skip to content

Commit

Permalink
feat: introduce pre-tx settlement checks
Browse files Browse the repository at this point in the history
Currently, we only check for the agents' balances.
  • Loading branch information
Adamantios committed Nov 17, 2023
1 parent bf34819 commit ac1f252
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 13 deletions.
2 changes: 2 additions & 0 deletions packages/valory/agents/trader/aea-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,8 @@ models:
"stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1",
"stabilityai-stable-diffusion-768-v2-1"]}
staking_contract_address: ${str:0x5add592ce0a1B5DceCebB5Dcac086Cd9F9e3eA5C}
agent_balance_threshold: ${int:10000000000000000}
refill_check_interval: ${int:10}
---
public_id: valory/p2p_libp2p_client:0.1.0
type: connection
Expand Down
8 changes: 8 additions & 0 deletions packages/valory/services/trader/service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,8 @@ type: skill
"stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1",
"stabilityai-stable-diffusion-768-v2-1"]}
staking_contract_address: ${STAKING_CONTRACT_ADDRESS:str:0x5add592ce0a1B5DceCebB5Dcac086Cd9F9e3eA5C}
agent_balance_threshold: ${AGENT_BALANCE_THRESHOLD:int:10000000000000000}
refill_check_interval: ${REFILL_CHECK_INTERVAL:int:10}
benchmark_tool: &id005
args:
log_dir: ${LOG_DIR:str:/benchmarks}
Expand Down Expand Up @@ -192,6 +194,8 @@ type: skill
"stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1",
"stabilityai-stable-diffusion-768-v2-1"]}
staking_contract_address: ${STAKING_CONTRACT_ADDRESS:str:0x5add592ce0a1B5DceCebB5Dcac086Cd9F9e3eA5C}
agent_balance_threshold: ${AGENT_BALANCE_THRESHOLD:int:10000000000000000}
refill_check_interval: ${REFILL_CHECK_INTERVAL:int:10}
benchmark_tool: *id005
2:
models:
Expand Down Expand Up @@ -266,6 +270,8 @@ type: skill
"stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1",
"stabilityai-stable-diffusion-768-v2-1"]}
staking_contract_address: ${STAKING_CONTRACT_ADDRESS:str:0x5add592ce0a1B5DceCebB5Dcac086Cd9F9e3eA5C}
agent_balance_threshold: ${AGENT_BALANCE_THRESHOLD:int:10000000000000000}
refill_check_interval: ${REFILL_CHECK_INTERVAL:int:10}
benchmark_tool: *id005
3:
models:
Expand Down Expand Up @@ -340,6 +346,8 @@ type: skill
"stabilityai-stable-diffusion-xl-beta-v2-2-2", "stabilityai-stable-diffusion-512-v2-1",
"stabilityai-stable-diffusion-768-v2-1"]}
staking_contract_address: ${STAKING_CONTRACT_ADDRESS:str:0x5add592ce0a1B5DceCebB5Dcac086Cd9F9e3eA5C}
agent_balance_threshold: ${AGENT_BALANCE_THRESHOLD:int:10000000000000000}
refill_check_interval: ${REFILL_CHECK_INTERVAL:int:10}
benchmark_tool: *id005
---
public_id: valory/ledger:0.19.0
Expand Down
7 changes: 5 additions & 2 deletions packages/valory/skills/trader_abci/composition.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,13 @@
TransactionSubmissionAbciApp,
)
from packages.valory.skills.tx_settlement_multiplexer_abci.rounds import (
ChecksPassedRound,
FinishedBetPlacementTxRound,
FinishedDecisionRequestTxRound,
FinishedRedeemingTxRound,
FinishedStakingTxRound,
PostTxSettlementRound,
PreTxSettlementRound,
TxSettlementMultiplexerAbciApp,
)

Expand All @@ -89,7 +91,8 @@
FinishedRegistrationRound: UpdateBetsRound,
FinishedMarketManagerRound: SamplingRound,
FailedMarketManagerRound: ResetAndPauseRound,
FinishedDecisionMakerRound: RandomnessTransactionSubmissionRound,
FinishedDecisionMakerRound: PreTxSettlementRound,
ChecksPassedRound: RandomnessTransactionSubmissionRound,
RefillRequiredRound: ResetAndPauseRound,
FinishedTransactionSubmissionRound: PostTxSettlementRound,
FailedTransactionSubmissionRound: HandleFailedTxRound,
Expand All @@ -99,7 +102,7 @@
FinishedWithoutDecisionRound: RedeemRound,
FinishedWithoutRedeemingRound: CallCheckpointRound,
FinishedStakingRound: ResetAndPauseRound,
CheckpointCallPreparedRound: RandomnessTransactionSubmissionRound,
CheckpointCallPreparedRound: PreTxSettlementRound,
FinishedStakingTxRound: ResetAndPauseRound,
FinishedResetAndPauseRound: UpdateBetsRound,
FinishedResetAndPauseErrorRound: RegistrationRound,
Expand Down
7 changes: 6 additions & 1 deletion packages/valory/skills/trader_abci/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@
from packages.valory.skills.termination_abci.models import TerminationParams
from packages.valory.skills.trader_abci.composition import TraderAbciApp
from packages.valory.skills.transaction_settlement_abci.rounds import Event as TSEvent
from packages.valory.skills.tx_settlement_multiplexer_abci.models import (
TxSettlementMultiplexerParams,
)


EventType = Union[
Expand Down Expand Up @@ -81,7 +84,9 @@ class RandomnessApi(ApiSpecs):
"""A model for randomness api specifications."""


class TraderParams(DecisionMakerParams, TerminationParams, StakingParams):
class TraderParams(
DecisionMakerParams, TerminationParams, StakingParams, TxSettlementMultiplexerParams
):
"""A model to represent the trader params."""


Expand Down
2 changes: 2 additions & 0 deletions packages/valory/skills/trader_abci/skill.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ models:
- stabilityai-stable-diffusion-512-v2-1
- stabilityai-stable-diffusion-768-v2-1
staking_contract_address: '0x5add592ce0a1B5DceCebB5Dcac086Cd9F9e3eA5C'
agent_balance_threshold: 10000000000000000
refill_check_interval: 10
class_name: TraderParams
network_subgraph:
args:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,102 @@

"""This package contains the behaviours of the transaction settlement multiplexer."""

from abc import ABC
from typing import Generator, Set, Type
from typing import Generator, Optional, Set, Type, cast

from aea.exceptions import AEAEnforceError

from packages.valory.protocols.ledger_api import LedgerApiMessage
from packages.valory.skills.abstract_round_abci.behaviours import (
AbstractRoundBehaviour,
BaseBehaviour,
)
from packages.valory.skills.decision_maker_abci.payloads import VotingPayload
from packages.valory.skills.tx_settlement_multiplexer_abci.models import (
TxSettlementMultiplexerParams,
)
from packages.valory.skills.tx_settlement_multiplexer_abci.rounds import (
PostTxSettlementRound,
PreTxSettlementRound,
SynchronizedData,
TxSettlementMultiplexerAbciApp,
)


class PostTxSettlementBehaviour(BaseBehaviour, ABC):
class PreTxSettlementBehaviour(BaseBehaviour):
"""
The pre transaction settlement behaviour.
This behaviour should be executed before a tx is sent via the transaction_settlement_abci.
"""

matching_round = PreTxSettlementRound

@property
def params(self) -> TxSettlementMultiplexerParams:
"""Return the params."""
return cast(TxSettlementMultiplexerParams, self.context.params)

def _get_balance(self, agent: str) -> Generator[None, None, Optional[int]]:
"""Get the given agent's balance."""
self.context.logger.info(f"Checking balance for agent with address {agent}...")
ledger_api_response = yield from self.get_ledger_api_response(
performative=LedgerApiMessage.Performative.GET_STATE, # type: ignore
ledger_callable="get_balance",
account=agent,
)

try:
balance = int(ledger_api_response.state.body["get_balance_result"])
except (AEAEnforceError, KeyError, ValueError, TypeError):
balance = None

if balance is None:
log_msg = f"Failed to get the balance for agent with address {agent}."
self.context.logger.error(f"{log_msg}: {ledger_api_response}")
return None

self.context.logger.info(f"The agent with address {agent} has {balance} WEI.")
return balance

def _check_balance(self, agent: str) -> Generator[None, None, bool]:
"""Check if the given agent's balance is sufficient."""
balance = None
while balance is None:
balance = yield from self._get_balance(agent)

threshold = self.params.agent_balance_threshold
refill_required = balance < threshold
if refill_required:
msg = f"Please refill agent with address {agent}. Balance is below {threshold}."
self.context.logger.warning(msg)

return refill_required

def _refill_required(self) -> Generator[None, None, bool]:
"""Check whether a refill is required."""
refill_required = False
for agent in self.synchronized_data.all_participants:
refill_required |= yield from self._check_balance(agent)
return refill_required

def async_act(self) -> Generator:
"""Check whether the agents' balances are sufficient."""
with self.context.benchmark_tool.measure(self.behaviour_id).local():
refill_required = yield from self._refill_required()
if refill_required:
# pause to give the user some time to refill before transitioning to the same round again
yield from self.sleep(self.params.refill_check_interval)

payload = VotingPayload(self.context.agent_address, not refill_required)

with self.context.benchmark_tool.measure(self.behaviour_id).consensus():
yield from self.send_a2a_transaction(payload)
yield from self.wait_until_round_end()

self.set_done()


class PostTxSettlementBehaviour(BaseBehaviour):
"""
The post transaction settlement behaviour.
Expand All @@ -60,4 +141,7 @@ class PostTxSettlementFullBehaviour(AbstractRoundBehaviour):

initial_behaviour_cls = PostTxSettlementBehaviour
abci_app_cls = TxSettlementMultiplexerAbciApp
behaviours: Set[Type[BaseBehaviour]] = {PostTxSettlementBehaviour} # type: ignore
behaviours: Set[Type[BaseBehaviour]] = {
PreTxSettlementBehaviour, # type: ignore
PostTxSettlementBehaviour, # type: ignore
}
17 changes: 16 additions & 1 deletion packages/valory/skills/tx_settlement_multiplexer_abci/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@

"""Custom objects for the TxSettlementMultiplexer ABCI application."""

from typing import Any

from packages.valory.skills.abstract_round_abci.models import BaseParams
from packages.valory.skills.abstract_round_abci.models import (
BenchmarkTool as BaseBenchmarkTool,
Expand All @@ -35,7 +37,20 @@

Requests = BaseRequests
BenchmarkTool = BaseBenchmarkTool
Params = BaseParams


class TxSettlementMultiplexerParams(BaseParams):
"""Staking parameters."""

def __init__(self, *args: Any, **kwargs: Any) -> None:
"""Initialize the parameters' object."""
self.agent_balance_threshold: int = self._ensure(
"agent_balance_threshold", kwargs, int
)
self.refill_check_interval: int = self._ensure(
"refill_check_interval", kwargs, int
)
super().__init__(*args, **kwargs)


class SharedState(BaseSharedState):
Expand Down
36 changes: 33 additions & 3 deletions packages/valory/skills/tx_settlement_multiplexer_abci/rounds.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@
BaseSynchronizedData,
CollectSameUntilThresholdRound,
DegenerateRound,
VotingRound,
get_name,
)
from packages.valory.skills.decision_maker_abci.payloads import VotingPayload
from packages.valory.skills.decision_maker_abci.states.base import SynchronizedData
from packages.valory.skills.decision_maker_abci.states.bet_placement import (
BetPlacementRound,
Expand All @@ -46,12 +48,26 @@
class Event(Enum):
"""Multiplexing events."""

CHECKS_PASSED = "checks_passed"
REFILL_REQUIRED = "refill_required"
DECISION_REQUESTING_DONE = "decision_requesting_done"
BET_PLACEMENT_DONE = "bet_placement_done"
REDEEMING_DONE = "redeeming_done"
STAKING_DONE = "staking_done"
ROUND_TIMEOUT = "round_timeout"
UNRECOGNIZED = "unrecognized"
NO_MAJORITY = "no_majority"


class PreTxSettlementRound(VotingRound):
"""A round that will be called before the tx settlement."""

payload_class = VotingPayload
synchronized_data_class = SynchronizedData
done_event = Event.CHECKS_PASSED
negative_event = Event.REFILL_REQUIRED
no_majority_event = Event.NO_MAJORITY
collection_key = get_name(SynchronizedData.participant_to_votes)


class PostTxSettlementRound(CollectSameUntilThresholdRound):
Expand Down Expand Up @@ -89,6 +105,10 @@ def end_block(self) -> Optional[Tuple[BaseSynchronizedData, Enum]]:
return synced_data, event


class ChecksPassedRound(DegenerateRound):
"""Round that represents all the pre tx settlement checks have passed."""


class FinishedDecisionRequestTxRound(DegenerateRound):
"""Finished decision requesting round."""

Expand Down Expand Up @@ -136,9 +156,15 @@ class TxSettlementMultiplexerAbciApp(AbciApp[Event]):
round timeout: 30.0
"""

initial_round_cls: AppState = PostTxSettlementRound
initial_states: Set[AppState] = {PostTxSettlementRound}
initial_round_cls: AppState = PreTxSettlementRound
initial_states: Set[AppState] = {PreTxSettlementRound, PostTxSettlementRound}
transition_function: AbciAppTransitionFunction = {
PreTxSettlementRound: {
Event.CHECKS_PASSED: ChecksPassedRound,
Event.REFILL_REQUIRED: PreTxSettlementRound,
Event.NO_MAJORITY: PreTxSettlementRound,
Event.ROUND_TIMEOUT: PreTxSettlementRound,
},
PostTxSettlementRound: {
Event.DECISION_REQUESTING_DONE: FinishedDecisionRequestTxRound,
Event.BET_PLACEMENT_DONE: FinishedBetPlacementTxRound,
Expand All @@ -147,6 +173,7 @@ class TxSettlementMultiplexerAbciApp(AbciApp[Event]):
Event.ROUND_TIMEOUT: PostTxSettlementRound,
Event.UNRECOGNIZED: FailedMultiplexerRound,
},
ChecksPassedRound: {},
FinishedDecisionRequestTxRound: {},
FinishedBetPlacementTxRound: {},
FinishedRedeemingTxRound: {},
Expand All @@ -157,16 +184,19 @@ class TxSettlementMultiplexerAbciApp(AbciApp[Event]):
Event.ROUND_TIMEOUT: 30.0,
}
final_states: Set[AppState] = {
ChecksPassedRound,
FinishedDecisionRequestTxRound,
FinishedBetPlacementTxRound,
FinishedRedeemingTxRound,
FinishedStakingTxRound,
FailedMultiplexerRound,
}
db_pre_conditions: Dict[AppState, Set[str]] = {
PostTxSettlementRound: {get_name(SynchronizedData.tx_submitter)}
PreTxSettlementRound: {get_name(SynchronizedData.tx_submitter)},
PostTxSettlementRound: {get_name(SynchronizedData.tx_submitter)},
}
db_post_conditions: Dict[AppState, Set[str]] = {
ChecksPassedRound: set(),
FinishedDecisionRequestTxRound: set(),
FinishedBetPlacementTxRound: set(),
FinishedRedeemingTxRound: set(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ fingerprint:
fingerprint_ignore_patterns: []
connections: []
contracts: []
protocols: []
protocols:
- valory/ledger_api:1.0.0:bafybeige5agrztgzfevyglf7mb4o7pzfttmq4f6zi765y4g2zvftbyowru
skills:
- valory/abstract_round_abci:0.1.0:bafybeid7neqpxxe4ualp23gxgrtpf6r5u3myr2mmc4uvwameyqshfdoydq
- valory/decision_maker_abci:0.1.0:bafybeighimm45dlkagx5uig2i4wa7ikmiajlcyqkpms64amm5osxrnzroi
Expand Down Expand Up @@ -124,7 +125,9 @@ models:
termination_sleep: 900
tx_timeout: 10.0
use_termination: false
class_name: Params
agent_balance_threshold: 10000000000000000
refill_check_interval: 10
class_name: TxSettlementMultiplexerParams
requests:
args: {}
class_name: Requests
Expand Down

0 comments on commit ac1f252

Please sign in to comment.