Skip to main content

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