sp1_sdk/network/
builder.rs

1//! # Network Prover Builder
2//!
3//! This module provides a builder for the [`NetworkProver`].
4
5use alloy_primitives::Address;
6
7use crate::{
8    network::{signer::NetworkSigner, NetworkMode, TEE_NETWORK_RPC_URL},
9    NetworkProver,
10};
11
12#[cfg(feature = "tee-2fa")]
13use crate::network::retry::{self, DEFAULT_RETRY_TIMEOUT};
14
15/// A builder for the [`NetworkProver`].
16///
17/// The builder is used to configure the [`NetworkProver`] before it is built.
18#[derive(Default)]
19pub struct NetworkProverBuilder {
20    pub(crate) private_key: Option<String>,
21    pub(crate) rpc_url: Option<String>,
22    pub(crate) tee_signers: Option<Vec<Address>>,
23    pub(crate) signer: Option<NetworkSigner>,
24    pub(crate) network_mode: Option<NetworkMode>,
25}
26
27impl NetworkProverBuilder {
28    /// Sets the Secp256k1 private key (same format as the one used by Ethereum).
29    ///
30    /// # Details
31    /// Sets the private key that will be used sign requests sent to the network. By default, the
32    /// private key is read from the `NETWORK_PRIVATE_KEY` environment variable.
33    ///
34    /// # Example
35    /// ```rust,no_run
36    /// use sp1_sdk::ProverClient;
37    ///
38    /// let prover = ProverClient::builder().network().private_key("...").build();
39    /// ```
40    #[must_use]
41    pub fn private_key(mut self, private_key: &str) -> Self {
42        self.private_key = Some(private_key.to_string());
43        self
44    }
45
46    /// Sets the remote procedure call URL.
47    ///
48    /// # Details
49    /// The URL determines the network that the client will connect to. By default, the URL is
50    /// read from the `NETWORK_RPC_URL` environment variable.
51    ///
52    /// # Example
53    /// ```rust,no_run
54    /// use sp1_sdk::ProverClient;
55    ///
56    /// let prover = ProverClient::builder().network().rpc_url("...").build();
57    /// ```
58    #[must_use]
59    pub fn rpc_url(mut self, rpc_url: &str) -> Self {
60        self.rpc_url = Some(rpc_url.to_string());
61        self
62    }
63
64    /// Process proofs inside a TEE.
65    ///
66    /// # Details
67    /// In order to keep the inputs private, it is possible to route the proof
68    /// requests to a TEE enclave.
69    ///
70    /// # Example
71    /// ```rust,no_run
72    /// use sp1_sdk::ProverClient;
73    ///
74    /// let prover = ProverClient::builder().network().private().build();
75    /// ```
76    #[must_use]
77    pub fn private(mut self) -> Self {
78        self.rpc_url = Some(TEE_NETWORK_RPC_URL.to_string());
79        self
80    }
81
82    /// Sets the list of TEE signers, used for verifying TEE proofs.
83    #[must_use]
84    pub fn tee_signers(mut self, tee_signers: &[Address]) -> Self {
85        self.tee_signers = Some(tee_signers.to_vec());
86        self
87    }
88
89    /// Sets the network signer to use for signing requests.
90    ///
91    /// # Details
92    /// This method allows you to provide a custom signer implementation, such as AWS KMS or
93    /// a local private key signer. If both `signer` and `private_key` are provided, the signer
94    /// takes precedence.
95    ///
96    /// # Examples
97    ///
98    /// Using a local private key:
99    /// ```rust,no_run
100    /// use sp1_sdk::{NetworkSigner, ProverClient};
101    ///
102    /// let private_key = "...";
103    /// let signer = NetworkSigner::local(private_key).unwrap();
104    /// let prover = ProverClient::builder().network().signer(signer).build();
105    /// ```
106    ///
107    /// Using AWS KMS:
108    /// ```rust,no_run
109    /// use sp1_sdk::{NetworkSigner, ProverClient};
110    ///
111    /// # async fn example() {
112    /// let kms_key_arn = "arn:aws:kms:us-east-1:123456789:key/key-id";
113    /// let signer = NetworkSigner::aws_kms(kms_key_arn).await.unwrap();
114    /// let prover = ProverClient::builder().network().signer(signer).build();
115    /// # }
116    /// ```
117    #[must_use]
118    pub fn signer(mut self, signer: NetworkSigner) -> Self {
119        self.signer = Some(signer);
120        self
121    }
122
123    /// Builds a [`NetworkProver`].
124    ///
125    /// # Details
126    /// This method will build a [`NetworkProver`] with the given parameters. If `signer` is
127    /// provided, it will be used directly. Otherwise, if `private_key` is provided, a local
128    /// signer will be created from it. If neither is provided, the method will look for the
129    /// `NETWORK_PRIVATE_KEY` environment variable.
130    ///
131    /// # Examples
132    ///
133    /// Using a private key:
134    /// ```rust,no_run
135    /// use sp1_sdk::ProverClient;
136    ///
137    /// let prover = ProverClient::builder().network().private_key("...").rpc_url("...").build();
138    /// ```
139    ///
140    /// Using a local signer:
141    /// ```rust,no_run
142    /// use sp1_sdk::{NetworkSigner, ProverClient};
143    ///
144    /// let private_key = "...";
145    /// let signer = NetworkSigner::local(private_key).unwrap();
146    /// let prover = ProverClient::builder().network().signer(signer).build();
147    /// ```
148    ///
149    /// Using AWS KMS:
150    /// ```rust,no_run
151    /// use sp1_sdk::{NetworkSigner, ProverClient};
152    ///
153    /// # async fn example() {
154    /// let kms_key_arn = "arn:aws:kms:us-east-1:123456789:key/key-id";
155    /// let signer = NetworkSigner::aws_kms(kms_key_arn).await.unwrap();
156    /// let prover = ProverClient::builder().network().signer(signer).build();
157    /// # }
158    /// ```
159    #[must_use]
160    pub fn build(self) -> NetworkProver {
161        let signer = if let Some(provided_signer) = self.signer {
162            provided_signer
163        } else {
164            let private_key = self
165                .private_key
166                .or_else(|| std::env::var("NETWORK_PRIVATE_KEY").ok().filter(|k| !k.is_empty()))
167                .expect(
168                    "NETWORK_PRIVATE_KEY environment variable is not set. \
169                    Please set it to your private key or use the .private_key() method.",
170                );
171            NetworkSigner::local(&private_key).expect("Failed to create local signer")
172        };
173
174        let network_mode = self.network_mode.unwrap_or_default();
175
176        let rpc_url = match self.rpc_url {
177            Some(rpc_url) => rpc_url,
178            None => std::env::var("NETWORK_RPC_URL")
179                .unwrap_or_else(|_| super::utils::get_default_rpc_url_for_mode(network_mode)),
180        };
181
182        let tee_signers = self.tee_signers.unwrap_or_else(|| {
183            cfg_if::cfg_if! {
184                if #[cfg(feature = "tee-2fa")] {
185                    crate::utils::block_on(
186                        async {
187                            retry::retry_operation(
188                                || async {
189                                    crate::network::tee::get_tee_signers().await.map_err(Into::into)
190                                },
191                                Some(DEFAULT_RETRY_TIMEOUT),
192                                "get tee signers"
193                            ).await.expect("Failed to get TEE signers")
194                        }
195                    )
196                } else {
197                    vec![]
198                }
199            }
200        });
201
202        NetworkProver::new(signer, &rpc_url, network_mode).with_tee_signers(tee_signers)
203    }
204}