Skip to content

Commit 91e8cf2

Browse files
committed
fix: address comments
1 parent 012f3ed commit 91e8cf2

File tree

6 files changed

+83
-16
lines changed

6 files changed

+83
-16
lines changed

apps/fortuna/src/api.rs

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ pub struct ApiMetrics {
4343

4444
#[derive(Clone)]
4545
pub struct ApiState {
46-
pub chains: Arc<RwLock<HashMap<ChainId, BlockchainState>>>,
46+
pub chains: Arc<RwLock<HashMap<ChainId, ApiBlockChainState>>>,
4747

4848
pub metrics_registry: Arc<RwLock<Registry>>,
4949

@@ -53,7 +53,7 @@ pub struct ApiState {
5353

5454
impl ApiState {
5555
pub async fn new(
56-
chains: Arc<RwLock<HashMap<ChainId, BlockchainState>>>,
56+
chains: Arc<RwLock<HashMap<ChainId, ApiBlockChainState>>>,
5757
metrics_registry: Arc<RwLock<Registry>>,
5858
) -> ApiState {
5959
let metrics = ApiMetrics {
@@ -94,6 +94,12 @@ pub struct BlockchainState {
9494
pub confirmed_block_status: BlockStatus,
9595
}
9696

97+
#[derive(Clone)]
98+
pub enum ApiBlockChainState {
99+
Uninitialized,
100+
Initialized(BlockchainState),
101+
}
102+
97103
pub enum RestError {
98104
/// The caller passed a sequence number that isn't within the supported range
99105
InvalidSequenceNumber,
@@ -108,6 +114,9 @@ pub enum RestError {
108114
/// The server cannot currently communicate with the blockchain, so is not able to verify
109115
/// which random values have been requested.
110116
TemporarilyUnavailable,
117+
/// The server is not able to process the request because the blockchain initialization
118+
/// has not been completed yet.
119+
Uninitialized,
111120
/// A catch-all error for all other types of errors that could occur during processing.
112121
Unknown,
113122
}
@@ -137,6 +146,11 @@ impl IntoResponse for RestError {
137146
"This service is temporarily unavailable",
138147
)
139148
.into_response(),
149+
RestError::Uninitialized => (
150+
StatusCode::SERVICE_UNAVAILABLE,
151+
"The service is not yet initialized for this chain, please try again in a few minutes",
152+
)
153+
.into_response(),
140154
RestError::Unknown => (
141155
StatusCode::INTERNAL_SERVER_ERROR,
142156
"An unknown error occurred processing the request",
@@ -172,6 +186,7 @@ pub fn get_register_uri(base_uri: &str, chain_id: &str) -> Result<String> {
172186

173187
#[cfg(test)]
174188
mod test {
189+
use crate::api::ApiBlockChainState;
175190
use {
176191
crate::{
177192
api::{self, ApiState, BinaryEncoding, Blob, BlockchainState, GetRandomValueResponse},
@@ -228,8 +243,14 @@ mod test {
228243
};
229244

230245
let mut chains = HashMap::new();
231-
chains.insert("ethereum".into(), eth_state);
232-
chains.insert("avalanche".into(), avax_state);
246+
chains.insert(
247+
"ethereum".into(),
248+
ApiBlockChainState::Initialized(eth_state),
249+
);
250+
chains.insert(
251+
"avalanche".into(),
252+
ApiBlockChainState::Initialized(avax_state),
253+
);
233254

234255
let api_state = ApiState::new(Arc::new(RwLock::new(chains)), metrics_registry).await;
235256

apps/fortuna/src/api/revelation.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::api::ApiBlockChainState;
12
use crate::chain::reader::BlockNumber;
23
use {
34
crate::api::{ChainId, RequestLabel, RestError},
@@ -52,6 +53,13 @@ pub async fn revelation(
5253
.ok_or(RestError::InvalidChainId)?
5354
.clone();
5455

56+
let state = match state {
57+
ApiBlockChainState::Initialized(state) => state,
58+
ApiBlockChainState::Uninitialized => {
59+
return Err(RestError::Uninitialized);
60+
}
61+
};
62+
5563
let current_block_number_fut = state
5664
.contract
5765
.get_block_number(state.confirmed_block_status);

apps/fortuna/src/command/register_provider.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub async fn register_provider_from_config(
5252

5353
let commitment_length = provider_config.chain_length;
5454
tracing::info!("Generating hash chain");
55-
let chain = PebbleHashChain::from_config(
55+
let chain = PebbleHashChain::from_config_async(
5656
&secret,
5757
chain_id,
5858
&private_key_string.parse::<LocalWallet>()?.address(),

apps/fortuna/src/command/run.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use {
22
crate::{
3-
api::{self, BlockchainState, ChainId},
3+
api::{self, ApiBlockChainState, BlockchainState, ChainId},
44
chain::ethereum::InstrumentedPythContract,
55
command::register_provider::CommitmentMetadata,
66
config::{Commitment, Config, EthereumConfig, RunOptions},
@@ -24,7 +24,7 @@ use {
2424

2525
pub async fn run_api(
2626
socket_addr: SocketAddr,
27-
chains: Arc<RwLock<HashMap<String, api::BlockchainState>>>,
27+
chains: Arc<RwLock<HashMap<String, ApiBlockChainState>>>,
2828
metrics_registry: Arc<RwLock<Registry>>,
2929
mut rx_exit: watch::Receiver<bool>,
3030
) -> Result<()> {
@@ -91,7 +91,13 @@ pub async fn run(opts: &RunOptions) -> Result<()> {
9191
if keeper_private_key_option.is_none() {
9292
tracing::info!("Not starting keeper service: no keeper private key specified. Please add one to the config if you would like to run the keeper service.")
9393
}
94-
let chains: Arc<RwLock<HashMap<ChainId, BlockchainState>>> = Default::default();
94+
let chains: Arc<RwLock<HashMap<ChainId, ApiBlockChainState>>> = Arc::new(RwLock::new(
95+
config
96+
.chains
97+
.keys()
98+
.map(|chain_id| (chain_id.clone(), ApiBlockChainState::Uninitialized))
99+
.collect(),
100+
));
95101
for (chain_id, chain_config) in config.chains.clone() {
96102
let keeper_metrics = keeper_metrics.clone();
97103
let keeper_private_key_option = keeper_private_key_option.clone();
@@ -111,7 +117,10 @@ pub async fn run(opts: &RunOptions) -> Result<()> {
111117
match state {
112118
Ok(state) => {
113119
keeper_metrics.add_chain(chain_id.clone(), state.provider_address);
114-
chains.write().await.insert(chain_id.clone(), state.clone());
120+
chains.write().await.insert(
121+
chain_id.clone(),
122+
ApiBlockChainState::Initialized(state.clone()),
123+
);
115124
if let Some(keeper_private_key) = keeper_private_key_option {
116125
spawn(keeper::run_keeper_threads(
117126
keeper_private_key,
@@ -204,7 +213,7 @@ async fn setup_chain_state(
204213
let offset = commitment.original_commitment_sequence_number.try_into()?;
205214
offsets.push(offset);
206215

207-
let pebble_hash_chain = PebbleHashChain::from_config(
216+
let pebble_hash_chain = PebbleHashChain::from_config_async(
208217
secret,
209218
chain_id,
210219
provider,

apps/fortuna/src/command/setup_provider.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ async fn setup_chain_provider(
112112
);
113113
register = true;
114114
} else {
115-
let hash_chain = PebbleHashChain::from_config(
115+
let hash_chain = PebbleHashChain::from_config_async(
116116
&secret,
117117
chain_id,
118118
&provider_address,

apps/fortuna/src/state.rs

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,24 +43,53 @@ impl PebbleHashChain {
4343
}
4444
}
4545

46-
pub async fn from_config(
46+
fn generate_secret(
4747
secret: &str,
4848
chain_id: &ChainId,
4949
provider_address: &Address,
5050
contract_address: &Address,
5151
random: &[u8; 32],
52-
chain_length: u64,
53-
sample_interval: u64,
54-
) -> Result<Self> {
52+
) -> Result<[u8; 32]> {
5553
let mut input: Vec<u8> = vec![];
5654
input.extend_from_slice(&hex::decode(secret.trim())?);
5755
input.extend_from_slice(chain_id.as_bytes());
5856
input.extend_from_slice(provider_address.as_bytes());
5957
input.extend_from_slice(contract_address.as_bytes());
6058
input.extend_from_slice(random);
61-
6259
let secret: [u8; 32] = Keccak256::digest(input).into();
60+
Ok(secret)
61+
}
6362

63+
pub fn from_config(
64+
secret: &str,
65+
chain_id: &ChainId,
66+
provider_address: &Address,
67+
contract_address: &Address,
68+
random: &[u8; 32],
69+
chain_length: u64,
70+
sample_interval: u64,
71+
) -> Result<Self> {
72+
let secret: [u8; 32] =
73+
Self::generate_secret(secret, chain_id, provider_address, contract_address, random)?;
74+
Ok(Self::new(
75+
secret,
76+
chain_length.try_into()?,
77+
sample_interval.try_into()?,
78+
))
79+
}
80+
81+
/// Asynchronous version of `from_config` that runs the computation in a blocking thread.
82+
pub async fn from_config_async(
83+
secret: &str,
84+
chain_id: &ChainId,
85+
provider_address: &Address,
86+
contract_address: &Address,
87+
random: &[u8; 32],
88+
chain_length: u64,
89+
sample_interval: u64,
90+
) -> Result<Self> {
91+
let secret: [u8; 32] =
92+
Self::generate_secret(secret, chain_id, provider_address, contract_address, random)?;
6493
let chain_length: usize = chain_length.try_into()?;
6594
let sample_interval: usize = sample_interval.try_into()?;
6695
let hash_chain = spawn_blocking(move || Self::new(secret, chain_length, sample_interval))

0 commit comments

Comments
 (0)