clementine_core/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
//! # Clementine 🍊
//!
//! Clementine is Citrea's BitVM-based, trust-minimized two-way peg program.
//! Please refer to the [whitepaper](https://citrea.xyz/clementine_whitepaper.pdf)
//! to understand the design of Clementine.
//!
//! Clementine Core is the backbone of Clementine. As the name suggests, it
//! provides the core functionalities for Clementine to operate.
//!
//! Most of the modules are self-explanatory and documented. Please refer
//! to the documentation of each module for more information.
//!
//! ## Binaries and Using Clementine
//!
//! Clementine's architecture is designed so that every actor is a separate
//! server. They all communicate with each other via gRPC.
//!
//! For this reason, Clementine Core provides a single main binary,
//! `clementine-core`, which acts as a server starter for every actor. There is
//! also a helper binary, `clementine-core-cli`, which is a command-line
//! interface for communicating with these servers. It is located in
//! `bin/cli.rs`.
//!
//! The [`cli`](cli) module provides the command-line interface for Clementine.
//! It is used in every binary.
//!
//! The [`config`](config) module is also essential for Clementine to operate.
//! It specifies essential variables for the protocol as well as the user's
//! environment setup.
//!
//! ## Utilizing Actors
//!
//! The core behavior of Clementine's actors is defined in the respective
//! modules:
//!
//! - [`operator`](operator)
//! - [`verifier`](verifier)
//! - [`aggregator`](aggregator)
//!
//! For all these modules, the [`actor`] module provides common utilities.
//!
//! ### Servers
//!
//! An actor is only meaningful if its server is running. For each actor, there
//! is a server module, which provides the server implementation.
//!
//! The main server architecture is defined in the `rpc/clementine.proto` file.
//! It is compiled to Rust code by the `tonic` library. Server logic for each
//! actor is defined in the respective server module in the [`rpc`](rpc) module.
//!
//! ## Building Transactions and Managing Flow with Tasks
//!
//! Clementine operates on Bitcoin transactions. The [`builder`](builder) module
//! provides utilities for building Bitcoin transactions based on the
//! specification (detailed in the whitepaper). The [`builder`](builder) module
//! can create a transaction according to the specification with the required
//! signatures, addresses, and scripts.
//!
//! Clementine requires a few background tasks to be running in order to operate
//! properly. The task interface is defined in the [`task`](task) module. These
//! tasks are:
//!
//! - The [`bitcoin_syncer`](bitcoin_syncer) module syncs Bitcoin blocks and
//!   transactions.
//! - The [`tx_sender`](tx_sender) module sends transactions to the Bitcoin network
//!   depending on the transaction type.
//! - The [`states`](states) module provides state machine implementations for
//!   managing some of the steps in the specification.
//!
//! There are other modules that are not tasks, but they are used in the tasks
//! and are important for the flow of Clementine:
//!
//! - The [`header_chain_prover`](header_chain_prover) module accepts Bitcoin block headers
//!   and prepares proofs for them.
//!
//! ### Communicating with the Outside
//!
//! Some steps require communicating with external systems:
//!
//! - The [`extended_rpc`](extended_rpc) module provides a client that talks with
//!   the Bitcoin node.
//! - The [`citrea`](citrea) module provides a client for interacting with Citrea.
//! - The [`bitvm_client`](bitvm_client) module provides a client for BitVM.
//! - The [`database`](database) module provides a database interface for
//!   interacting with the PostgreSQL database.
//!
//! ## Development Guidelines
//!
//! ### Error Handling
//!
//! There are rules about error handling in Clementine. Please refer to the
//! [`errors`](errors) module for more information.
//!
//! ### Testing Clementine
//!
//! There are a few quirks about testing Clementine. One of the main ones is
//! that there is no `tests` directory for integration tests. Rather, there is a
//! [`test`](test) module, which is compiled only if `test` is enabled by Cargo
//! (when running `cargo test`). That module provides common utilities for unit
//! and integration testing, as well as integration tests themselves. This is a
//! workaround for having common test utilities between unit and integration
//! tests.
//!
//! Please refer to the [`test`](test) module to check what utilities are
//! available for testing and how to use them.
//!
//! Also, if a new integration test file is added, it should be guarded by the
//! `#[cfg(feature = "integration-tests")]` attribute. This ensures that the
//! integration and unit tests can be run separately.

#![allow(clippy::too_many_arguments)]
#![allow(warnings)]

use bitcoin::{OutPoint, Txid};
use serde::{Deserialize, Serialize};

pub mod actor;
pub mod aggregator;
pub mod bitcoin_syncer;
pub mod bitvm_client;
pub mod builder;
pub mod citrea;
pub mod cli;
pub mod config;
pub mod constants;
pub mod database;
pub mod deposit;
pub mod errors;
pub mod extended_rpc;
pub mod header_chain_prover;
pub mod musig2;
pub mod operator;
pub mod rpc;
pub mod servers;
#[cfg(feature = "automation")]
pub mod states;
pub mod task;
#[cfg(feature = "automation")]
pub mod tx_sender;
pub mod utils;
pub mod verifier;

#[cfg(test)]
pub mod test;

macro_rules! impl_try_from_vec_u8 {
    ($name:ident, $size:expr) => {
        impl TryFrom<Vec<u8>> for $name {
            type Error = &'static str;

            fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
                if value.len() == $size {
                    Ok($name(value.try_into().unwrap()))
                } else {
                    Err(concat!("Expected a Vec<u8> of length ", stringify!($size)))
                }
            }
        }
    };
}

pub type ConnectorUTXOTree = Vec<Vec<OutPoint>>;
// pub type HashTree = Vec<Vec<HashType>>;
// pub type PreimageTree = Vec<Vec<PreimageType>>;
pub type InscriptionTxs = (OutPoint, Txid);

/// Type alias for EVM address
#[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct EVMAddress(#[serde(with = "hex::serde")] pub [u8; 20]);

impl_try_from_vec_u8!(EVMAddress, 20);

#[derive(Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct UTXO {
    pub outpoint: OutPoint,
    pub txout: bitcoin::TxOut,
}

#[derive(Clone, Debug, Copy, Serialize, Deserialize, PartialEq, sqlx::Type)]
#[sqlx(type_name = "bytea")]
pub struct ByteArray66(#[serde(with = "hex::serde")] pub [u8; 66]);

impl_try_from_vec_u8!(ByteArray66, 66);

#[derive(Clone, Debug, Copy, Serialize, Deserialize, PartialEq, sqlx::Type)]
#[sqlx(type_name = "bytea")]
pub struct ByteArray32(#[serde(with = "hex::serde")] pub [u8; 32]);

impl_try_from_vec_u8!(ByteArray32, 32);

#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq, sqlx::Type)]
#[sqlx(type_name = "bytea")]
pub struct ByteArray64(#[serde(with = "hex::serde")] pub [u8; 64]);

impl_try_from_vec_u8!(ByteArray64, 64);