Skip to content

Commit eaaa74a

Browse files
author
Dev Kalra
authored
feat(Fortuna): add finality checks (#1322)
1 parent 281ef68 commit eaaa74a

File tree

8 files changed

+96
-30
lines changed

8 files changed

+96
-30
lines changed

fortuna/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

fortuna/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "fortuna"
3-
version = "3.2.4"
3+
version = "3.3.4"
44
edition = "2021"
55

66
[dependencies]

fortuna/src/api.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use {
22
crate::{
33
chain::reader::{
44
BlockNumber,
5+
BlockStatus,
56
EntropyReader,
67
},
78
state::HashChainState,
@@ -73,14 +74,17 @@ impl ApiState {
7374
#[derive(Clone)]
7475
pub struct BlockchainState {
7576
/// The hash chain(s) required to serve random numbers for this blockchain
76-
pub state: Arc<HashChainState>,
77+
pub state: Arc<HashChainState>,
7778
/// The contract that the server is fulfilling requests for.
78-
pub contract: Arc<dyn EntropyReader>,
79+
pub contract: Arc<dyn EntropyReader>,
7980
/// The address of the provider that this server is operating for.
80-
pub provider_address: Address,
81+
pub provider_address: Address,
8182
/// The server will wait for this many block confirmations of a request before revealing
8283
/// the random number.
83-
pub reveal_delay_blocks: BlockNumber,
84+
pub reveal_delay_blocks: BlockNumber,
85+
/// The BlockStatus of the block that is considered to be confirmed on the blockchain.
86+
/// For eg., Finalized, Safe
87+
pub confirmed_block_status: BlockStatus,
8488
}
8589

8690
pub struct Metrics {
@@ -203,7 +207,10 @@ mod test {
203207
BlockchainState,
204208
GetRandomValueResponse,
205209
},
206-
chain::reader::mock::MockEntropyReader,
210+
chain::reader::{
211+
mock::MockEntropyReader,
212+
BlockStatus,
213+
},
207214
state::{
208215
HashChainState,
209216
PebbleHashChain,
@@ -238,19 +245,21 @@ mod test {
238245
let eth_read = Arc::new(MockEntropyReader::with_requests(10, &[]));
239246

240247
let eth_state = BlockchainState {
241-
state: ETH_CHAIN.clone(),
242-
contract: eth_read.clone(),
243-
provider_address: PROVIDER,
244-
reveal_delay_blocks: 1,
248+
state: ETH_CHAIN.clone(),
249+
contract: eth_read.clone(),
250+
provider_address: PROVIDER,
251+
reveal_delay_blocks: 1,
252+
confirmed_block_status: BlockStatus::Latest,
245253
};
246254

247255
let avax_read = Arc::new(MockEntropyReader::with_requests(10, &[]));
248256

249257
let avax_state = BlockchainState {
250-
state: AVAX_CHAIN.clone(),
251-
contract: avax_read.clone(),
252-
provider_address: PROVIDER,
253-
reveal_delay_blocks: 2,
258+
state: AVAX_CHAIN.clone(),
259+
contract: avax_read.clone(),
260+
provider_address: PROVIDER,
261+
reveal_delay_blocks: 2,
262+
confirmed_block_status: BlockStatus::Latest,
254263
};
255264

256265
let api_state = ApiState::new(&[

fortuna/src/api/revelation.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ pub async fn revelation(
6262

6363
let maybe_request_fut = state.contract.get_request(state.provider_address, sequence);
6464

65-
let current_block_number_fut = state.contract.get_block_number();
65+
let current_block_number_fut = state
66+
.contract
67+
.get_block_number(state.confirmed_block_status);
6668

6769
let (maybe_request, current_block_number) =
6870
try_join!(maybe_request_fut, current_block_number_fut).map_err(|e| {

fortuna/src/chain/ethereum.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
use {
22
crate::{
3-
chain::{
4-
reader,
5-
reader::{
6-
BlockNumber,
7-
EntropyReader,
8-
},
3+
chain::reader::{
4+
self,
5+
BlockNumber,
6+
BlockStatus,
7+
EntropyReader,
98
},
109
config::EthereumConfig,
1110
},
1211
anyhow::{
1312
anyhow,
13+
Error,
1414
Result,
1515
},
1616
axum::async_trait,
@@ -39,7 +39,10 @@ use {
3939
LocalWallet,
4040
Signer,
4141
},
42-
types::transaction::eip2718::TypedTransaction,
42+
types::{
43+
transaction::eip2718::TypedTransaction,
44+
BlockNumber as EthersBlockNumber,
45+
},
4346
},
4447
sha3::{
4548
Digest,
@@ -209,7 +212,17 @@ impl EntropyReader for PythContract {
209212
}
210213
}
211214

212-
async fn get_block_number(&self) -> Result<BlockNumber> {
213-
Ok(self.client().get_block_number().await?.as_u64())
215+
async fn get_block_number(&self, confirmed_block_status: BlockStatus) -> Result<BlockNumber> {
216+
let block_number: EthersBlockNumber = confirmed_block_status.into();
217+
let block = self
218+
.client()
219+
.get_block(block_number)
220+
.await?
221+
.ok_or_else(|| Error::msg("pending block confirmation"))?;
222+
223+
Ok(block
224+
.number
225+
.ok_or_else(|| Error::msg("pending confirmation"))?
226+
.as_u64())
214227
}
215228
}

fortuna/src/chain/reader.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,37 @@
11
use {
22
anyhow::Result,
33
axum::async_trait,
4-
ethers::types::Address,
4+
ethers::types::{
5+
Address,
6+
BlockNumber as EthersBlockNumber,
7+
},
58
};
69

710
pub type BlockNumber = u64;
811

12+
#[derive(
13+
Copy, Clone, Debug, Default, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize,
14+
)]
15+
pub enum BlockStatus {
16+
/// Latest block
17+
#[default]
18+
Latest,
19+
/// Finalized block accepted as canonical
20+
Finalized,
21+
/// Safe head block
22+
Safe,
23+
}
24+
25+
impl Into<EthersBlockNumber> for BlockStatus {
26+
fn into(self) -> EthersBlockNumber {
27+
match self {
28+
BlockStatus::Latest => EthersBlockNumber::Latest,
29+
BlockStatus::Finalized => EthersBlockNumber::Finalized,
30+
BlockStatus::Safe => EthersBlockNumber::Safe,
31+
}
32+
}
33+
}
34+
935
/// EntropyReader is the read-only interface of the Entropy contract.
1036
#[async_trait]
1137
pub trait EntropyReader: Send + Sync {
@@ -15,7 +41,7 @@ pub trait EntropyReader: Send + Sync {
1541
async fn get_request(&self, provider: Address, sequence_number: u64)
1642
-> Result<Option<Request>>;
1743

18-
async fn get_block_number(&self) -> Result<BlockNumber>;
44+
async fn get_block_number(&self, confirmed_block_status: BlockStatus) -> Result<BlockNumber>;
1945
}
2046

2147
/// An in-flight request stored in the contract.
@@ -36,6 +62,7 @@ pub mod mock {
3662
use {
3763
crate::chain::reader::{
3864
BlockNumber,
65+
BlockStatus,
3966
EntropyReader,
4067
Request,
4168
},
@@ -114,7 +141,10 @@ pub mod mock {
114141
.map(|r| (*r).clone()))
115142
}
116143

117-
async fn get_block_number(&self) -> Result<BlockNumber> {
144+
async fn get_block_number(
145+
&self,
146+
confirmed_block_status: BlockStatus,
147+
) -> Result<BlockNumber> {
118148
Ok(*self.block_number.read().unwrap())
119149
}
120150
}

fortuna/src/command/run.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ pub async fn run(opts: &RunOptions) -> Result<()> {
9393
contract,
9494
provider_address: opts.provider,
9595
reveal_delay_blocks: chain_config.reveal_delay_blocks,
96+
confirmed_block_status: chain_config.confirmed_block_status,
9697
};
9798

9899
chains.insert(chain_id.clone(), state);

fortuna/src/config.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use {
22
crate::{
33
api::ChainId,
4-
chain::reader::BlockNumber,
4+
chain::reader::{
5+
BlockNumber,
6+
BlockStatus,
7+
},
58
},
69
anyhow::{
710
anyhow,
@@ -131,10 +134,18 @@ pub struct EthereumConfig {
131134
/// Address of a Pyth Randomness contract to interact with.
132135
pub contract_addr: Address,
133136

134-
/// How many blocks to wait before revealing the random number.
137+
/// reveal_delay_blocks - The difference between the block number with the
138+
/// confirmed_block_status(see below) and the block number of a request to
139+
/// Entropy should be greater than `reveal_delay_blocks` for Fortuna to reveal
140+
/// its commitment.
135141
pub reveal_delay_blocks: BlockNumber,
136142

137143
/// Use the legacy transaction format (for networks without EIP 1559)
138144
#[serde(default)]
139145
pub legacy_tx: bool,
146+
147+
/// The BlockStatus of the block that is considered confirmed.
148+
/// For example, Finalized, Safe, Latest
149+
#[serde(default)]
150+
pub confirmed_block_status: BlockStatus,
140151
}

0 commit comments

Comments
 (0)