linera_sdk/abis/
controller.rs

1// Copyright (c) Zefchain Labs, Inc.
2// SPDX-License-Identifier: Apache-2.0
3
4use std::collections::HashSet;
5
6use async_graphql::{scalar, Request, Response, SimpleObject};
7use linera_sdk_derive::GraphQLMutationRootInCrate;
8use serde::{Deserialize, Serialize};
9
10use crate::linera_base_types::{
11    AccountOwner, ApplicationId, BlockHeight, ChainId, ContractAbi, DataBlobHash, MessagePolicy,
12    ServiceAbi,
13};
14
15pub struct ControllerAbi;
16
17impl ContractAbi for ControllerAbi {
18    type Operation = Operation;
19    type Response = ();
20}
21
22impl ServiceAbi for ControllerAbi {
23    type Query = Request;
24    type QueryResponse = Response;
25}
26
27/// Service are identified by the blob ID of the description.
28pub type ManagedServiceId = DataBlobHash;
29
30#[derive(Debug, Deserialize, Serialize, GraphQLMutationRootInCrate)]
31pub enum Operation {
32    /// Worker commands
33    ExecuteWorkerCommand {
34        owner: AccountOwner,
35        command: WorkerCommand,
36    },
37    /// Execute a controller command
38    ExecuteControllerCommand {
39        admin: AccountOwner,
40        command: ControllerCommand,
41    },
42    /// Local worker operation: moves a service from `local_pending_services` to
43    /// `local_services` and removes the previous workers' owners.
44    StartLocalService { service_id: ManagedServiceId },
45}
46
47/// A worker command
48#[derive(Clone, Debug, Deserialize, Serialize)]
49pub enum WorkerCommand {
50    /// Executed by workers to register themselves.
51    RegisterWorker { capabilities: Vec<String> },
52    /// Executed by workers to de-register themselves.
53    DeregisterWorker,
54}
55
56scalar!(WorkerCommand);
57
58/// A controller command
59#[derive(Clone, Debug, Deserialize, Serialize)]
60pub enum ControllerCommand {
61    /// Set the admin owners.
62    SetAdmins { admins: Option<Vec<AccountOwner>> },
63    /// Remove a worker. (This should not usually happen, but some workers may be broken
64    /// and need to be cleaned up.)
65    RemoveWorker { worker_id: ChainId },
66    /// Update the state of a particular service to be running on the specific workers.
67    UpdateService {
68        service_id: ManagedServiceId,
69        workers: Vec<ChainId>,
70    },
71    /// Remove a service from the map entirely.
72    RemoveService { service_id: ManagedServiceId },
73    /// Set the states of all services at once, possibly removing some of them.
74    UpdateAllServices {
75        services: Vec<(ManagedServiceId, Vec<ChainId>)>,
76    },
77    /// Update the state of a particular chain to be listened to on the specific workers.
78    UpdateChain {
79        chain_id: ChainId,
80        workers: Vec<ChainId>,
81    },
82    /// Remove a chain from the map entirely.
83    RemoveChain { chain_id: ChainId },
84    /// Set the states of all chains at once, possibly removing some of them.
85    UpdateAllChains {
86        chains: Vec<(ChainId, Vec<ChainId>)>,
87    },
88}
89
90scalar!(ControllerCommand);
91
92/// The description of a service worker.
93#[derive(Clone, Debug, Serialize, Deserialize, SimpleObject)]
94pub struct Worker {
95    /// The address used by the worker.
96    pub owner: AccountOwner,
97    /// Some tags denoting the capabilities of this worker. Each capability has a value
98    /// that the worker will read from its local environment and pass to the applications.
99    pub capabilities: Vec<String>,
100}
101
102/// The description of a service managed by the controller.
103#[derive(Clone, Debug, Serialize, Deserialize)]
104pub struct ManagedService {
105    /// The application ID running the service (e.g. pm-engine)
106    pub application_id: ApplicationId,
107    /// The role assumed by this service within the application (e.g. engine, event,
108    /// market-maker).
109    pub name: String,
110    /// The chain on which the service is run. Note that this is different from the worker
111    /// chains which typically only run the controller application for managing the worker
112    /// itself.
113    pub chain_id: ChainId,
114    /// The required capabilities for a worker to be useful (e.g. some API key).
115    /// Concretely, the worker will read its environment variable
116    pub requirements: Vec<String>,
117}
118
119scalar!(ManagedService);
120
121/// The description of a service that is going to be managed by the worker, but the worker
122/// should only start proposing once a given block height is reached.
123#[derive(Clone, Debug, Serialize, Deserialize)]
124pub struct PendingService {
125    /// The previous owners of the service chain, to be removed when this worker starts to
126    /// propose.
127    pub owners_to_remove: HashSet<AccountOwner>,
128    /// The chain height at which this worker is supposed to start proposing blocks.
129    pub start_block_height: BlockHeight,
130}
131
132scalar!(PendingService);
133
134/// The local state of a worker.
135// This is used to facilitate service queries.
136#[derive(Clone, Debug, Deserialize, Serialize)]
137pub struct LocalWorkerState {
138    /// The description of this worker as we registered it.
139    pub local_worker: Option<Worker>,
140    /// The services currently running locally.
141    pub local_services: Vec<ManagedService>,
142    /// The services awaiting being managed by this worker.
143    pub local_pending_services: Vec<(ManagedServiceId, (ChainId, PendingService))>,
144    /// The chains currently followed locally (besides ours and the active service
145    /// chains).
146    pub local_chains: Vec<ChainId>,
147    /// The message policy that should be followed by the worker.
148    pub local_message_policy: Vec<(ChainId, MessagePolicy)>,
149}
150
151scalar!(LocalWorkerState);