abci/sync_api/
application.rs

1use crate::types::*;
2
3/// Trait for initialization and for queries from the user.
4pub trait Info {
5    /// Echo a string to test abci client/server implementation.
6    fn echo(&self, echo_request: RequestEcho) -> ResponseEcho {
7        ResponseEcho {
8            message: echo_request.message,
9        }
10    }
11
12    /// Return information about the application state.
13    ///
14    /// # Crash Recovery
15    ///
16    /// On startup, Tendermint calls the [`info`] method to get the **latest committed state** of the app. The app
17    /// **MUST** return information consistent with the last block it successfully completed [`commit`] for.
18    ///
19    /// If the app succesfully committed block `H` but not `H+1`, then
20    /// - `last_block_height = H`
21    /// - `last_block_app_hash = <hash returned by Commit for block H>`
22    ///
23    /// If the app failed during the [`commit`] of block `H`, then
24    /// - `last_block_height = H-1`
25    /// - `last_block_app_hash = <hash returned by Commit for block H-1, which is the hash in the header of block H>`
26    ///
27    /// [`info`]: self::Info::info
28    /// [`commit`]: self::Consensus::commit
29    fn info(&self, info_request: RequestInfo) -> ResponseInfo;
30
31    /// Set non-consensus critical application specific options.
32    fn set_option(&self, _set_option_request: RequestSetOption) -> ResponseSetOption {
33        Default::default()
34    }
35
36    /// Query for data from the application at current or past height.
37    fn query(&self, _query_request: RequestQuery) -> ResponseQuery {
38        Default::default()
39    }
40
41    /// Signals that messages queued on the client should be flushed to the server.
42    fn flush(&self, _flush_request: RequestFlush) -> ResponseFlush {
43        Default::default()
44    }
45}
46
47/// Trait for managing consensus of blockchain.
48///
49/// # Details
50///
51/// [_Consensus_] should maintain a `consensus_state` - the working state for block execution. It should be updated by
52/// the calls to [`begin_block`], [`deliver_tx`], and [`end_block`] during block execution and committed to disk as the
53/// **latest committed state** during [`commit`].
54///
55/// Updates made to the `consensus_state` by each method call must be readable by each subsequent method - ie. the
56/// updates are linearizable.
57///
58/// [_Consensus_]: self::Consensus
59/// [`begin_block`]: self::Consensus::begin_block
60/// [`deliver_tx`]: self::Consensus::deliver_tx
61/// [`end_block`]: self::Consensus::end_block
62/// [`commit`]: self::Consensus::commit
63pub trait Consensus {
64    /// Echo a string to test abci client/server implementation.
65    fn echo(&self, echo_request: RequestEcho) -> ResponseEcho {
66        ResponseEcho {
67            message: echo_request.message,
68        }
69    }
70
71    /// Called once upon genesis. Usually used to establish initial (genesis) state.
72    fn init_chain(&self, init_chain_request: RequestInitChain) -> ResponseInitChain;
73
74    /// Signals the beginning of a new block. Called prior to any [`deliver_tx`](self::Consensus::deliver_tx)s.
75    fn begin_block(&self, begin_block_request: RequestBeginBlock) -> ResponseBeginBlock;
76
77    /// Execute the transaction in full. The workhorse of the application.
78    fn deliver_tx(&self, deliver_tx_request: RequestDeliverTx) -> ResponseDeliverTx;
79
80    /// Signals the end of a block. Called after all transactions, prior to each [`commit`](self::Consensus::commit).
81    fn end_block(&self, end_block_request: RequestEndBlock) -> ResponseEndBlock;
82
83    /// Persist the application state.
84    ///
85    /// # Details
86    ///
87    /// Application state should only be persisted to disk during [`commit`].
88    ///
89    /// Before [`commit`] is called, Tendermint locks and flushes the mempool so that no new messages will be received
90    /// on the mempool connection. This provides an opportunity to safely update all three states ([_Consensus_],
91    /// [_Mempool_] and [_Info_]) to the **latest committed state** at once.
92    ///
93    /// When [`commit`] completes, it unlocks the mempool.
94    ///
95    /// # Warning
96    ///
97    /// If the ABCI application logic processing the [`commit`] message sends a `/broadcast_tx_sync` or
98    /// `/broadcast_tx_commit` and waits for the response before proceeding, it will deadlock. Executing those
99    /// `broadcast_tx` calls involves acquiring a lock that is held during the [`commit`] call, so it's not possible. If
100    /// you make the call to the `broadcast_tx` endpoints concurrently, that's no problem, it just can't be part of the
101    /// sequential logic of the [`commit`] function.
102    ///
103    /// [`commit`]: self::Consensus::commit
104    /// [_Consensus_]: self::Consensus
105    /// [_Mempool_]: self::Mempool
106    /// [_Info_]: self::Info
107    fn commit(&self, commit_request: RequestCommit) -> ResponseCommit;
108
109    /// Signals that messages queued on the client should be flushed to the server.
110    fn flush(&self, _flush_request: RequestFlush) -> ResponseFlush {
111        Default::default()
112    }
113}
114
115/// Trait for managing tendermint's mempool.
116///
117/// # Details
118///
119/// [_Mempool_] should maintain a `mempool_state` to sequentially process pending transactions in the mempool that have
120/// not yet been committed. It should be initialized to the latest committed state at the end of every [`commit`].
121///
122/// The `mempool_state` may be updated concurrently with the `consensus_state`, as messages may be sent concurrently on
123/// [_Consensus_] and [_Mempool_] connections. However, before calling [`commit`], Tendermint will lock and flush the
124/// mempool connection, ensuring that all existing [`check_tx`] are responded to and no new ones can begin.
125///
126/// After [`commit`], [`check_tx`] is run again on all transactions that remain in the node's local mempool after
127/// filtering those included in the block. To prevent the mempool from rechecking all transactions every time a block is
128/// committed, set the configuration option `mempool.recheck=false`.
129///
130/// Finally, the mempool will unlock and new transactions can be processed through [`check_tx`] again.
131///
132/// Note that [`check_tx`] doesn't have to check everything that affects transaction validity; the expensive things can
133/// be skipped. In fact, [`check_tx`] doesn't have to check anything; it might say that any transaction is a valid
134/// transaction. Unlike [`deliver_tx`], [`check_tx`] is just there as a sort of weak filter to keep invalid transactions
135/// out of the blockchain. It's weak, because a Byzantine node doesn't care about [`check_tx`]; it can propose a block
136/// full of invalid transactions if it wants.
137///
138/// [_Mempool_]: self::Mempool
139/// [`commit`]: self::Consensus::commit
140/// [_Consensus_]: self::Consensus
141/// [`deliver_tx`]: self::Consensus::deliver_tx
142/// [`check_tx`]: self::Mempool::check_tx
143pub trait Mempool {
144    /// Echo a string to test abci client/server implementation.
145    fn echo(&self, echo_request: RequestEcho) -> ResponseEcho {
146        ResponseEcho {
147            message: echo_request.message,
148        }
149    }
150
151    /// Guardian of the mempool: every node runs CheckTx before letting a transaction into its local mempool.
152    /// Technically optional - not involved in processing blocks.
153    fn check_tx(&self, check_tx_request: RequestCheckTx) -> ResponseCheckTx;
154
155    /// Signals that messages queued on the client should be flushed to the server.
156    fn flush(&self, _flush_request: RequestFlush) -> ResponseFlush {
157        Default::default()
158    }
159}
160
161/// Trait for serving and restoring tendermint's state sync snapshots.
162///
163/// # Details
164///
165/// State sync allows new nodes to rapidly bootstrap by discovering, fetching, and applying state
166/// machine snapshots instead of replaying historical blocks. For more details, see the state sync
167/// section.
168///
169/// When a new node is discovering snapshots in the P2P network, existing nodes will call
170/// [`list_snapshots`] on the application to retrieve any local state snapshots. The new node will
171/// offer these snapshots to its local application via [`offer_snapshot`].
172///
173/// Once the application accepts a snapshot and begins restoring it, Tendermint will fetch snapshot
174/// chunks from existing nodes via [`load_snapshot_chunk`] and apply them sequentially to the local
175/// application with `apply_snapshot_chunk`. When all chunks have been applied, the application
176/// `app_hash` is retrieved via an [`info`] query and compared to the blockchain's `app_hash`
177/// verified via light client.
178///
179/// [`list_snapshots`]: self::Snapshot::list_snapshots
180/// [`offer_snapshot`]: self::Snapshot::offer_snapshot
181/// [`load_snapshot_chunk`]: self::Snapshot::load_snapshot_chunk
182/// [`apply_snapshot_chunk`]: self::Snapshot::apply_snapshot_chunk
183/// [`info`]: self::Info::info
184pub trait Snapshot {
185    /// Echo a string to test abci client/server implementation.
186    fn echo(&self, echo_request: RequestEcho) -> ResponseEcho {
187        ResponseEcho {
188            message: echo_request.message,
189        }
190    }
191
192    /// Used during state sync to discover available snapshots on peers.
193    fn list_snapshots(
194        &self,
195        _list_snapshots_request: RequestListSnapshots,
196    ) -> ResponseListSnapshots {
197        Default::default()
198    }
199
200    /// OfferSnapshot is called when bootstrapping a node using state sync.
201    fn offer_snapshot(
202        &self,
203        _offer_snapshot_request: RequestOfferSnapshot,
204    ) -> ResponseOfferSnapshot {
205        Default::default()
206    }
207
208    /// Used during state sync to retrieve snapshot chunks from peers.
209    fn load_snapshot_chunk(
210        &self,
211        _load_snapshot_chunk_request: RequestLoadSnapshotChunk,
212    ) -> ResponseLoadSnapshotChunk {
213        Default::default()
214    }
215
216    /// Applies the snapshot chunks received from [`load_snapshot_chunk`](self::Snapshot::load_snapshot_chunk)
217    fn apply_snapshot_chunk(
218        &self,
219        _apply_snapshot_chunk_request: RequestApplySnapshotChunk,
220    ) -> ResponseApplySnapshotChunk {
221        Default::default()
222    }
223
224    /// Signals that messages queued on the client should be flushed to the server.
225    fn flush(&self, _flush_request: RequestFlush) -> ResponseFlush {
226        Default::default()
227    }
228}