Skip to content

feat(fortuna): Support new Entropy v2 contract #2691

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/fortuna/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion apps/fortuna/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fortuna"
version = "7.5.3"
version = "8.0.0"
edition = "2021"

[lib]
Expand Down
4 changes: 3 additions & 1 deletion apps/fortuna/src/api/revelation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,9 @@ pub async fn revelation(
.ok_or(RestError::NoPendingRequest)?;
}
None => {
let maybe_request_fut = state.contract.get_request(state.provider_address, sequence);
let maybe_request_fut = state
.contract
.get_request_v2(state.provider_address, sequence);
let (maybe_request, current_block_number) =
try_join!(maybe_request_fut, current_block_number_fut).map_err(|e| {
tracing::error!(chain_id = chain_id, "RPC request failed {}", e);
Expand Down
26 changes: 9 additions & 17 deletions apps/fortuna/src/chain/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,29 +233,21 @@ impl InstrumentedPythContract {

#[async_trait]
impl<T: JsonRpcClient + 'static> EntropyReader for PythRandom<Provider<T>> {
async fn get_request(
async fn get_request_v2(
&self,
provider_address: Address,
sequence_number: u64,
) -> Result<Option<reader::Request>> {
let r = self
.get_request(provider_address, sequence_number)
// TODO: This doesn't work for lighlink right now. Figure out how to do this in lightlink
// .block(ethers::core::types::BlockNumber::Finalized)
let request = self
.get_request_v2(provider_address, sequence_number)
.call()
.await?;

// sequence_number == 0 means the request does not exist.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this removed? I know that this check exists in some other places, but if we want to be safe and avoid unintended changes, we can keep it as is?

if r.sequence_number != 0 {
Ok(Some(reader::Request {
provider: r.provider,
sequence_number: r.sequence_number,
block_number: r.block_number,
use_blockhash: r.use_blockhash,
}))
} else {
Ok(None)
}
Ok(Some(reader::Request {
provider: request.provider,
sequence_number: request.sequence_number,
block_number: request.block_number,
use_blockhash: request.use_blockhash,
}))
}

async fn get_block_number(&self, confirmed_block_status: BlockStatus) -> Result<BlockNumber> {
Expand Down
9 changes: 6 additions & 3 deletions apps/fortuna/src/chain/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,11 @@ pub trait EntropyReader: Send + Sync {
/// Get an in-flight request (if it exists)
/// Note that if we support additional blockchains in the future, the type of `provider` may
/// need to become more generic.
async fn get_request(&self, provider: Address, sequence_number: u64)
-> Result<Option<Request>>;
async fn get_request_v2(
&self,
provider: Address,
sequence_number: u64,
) -> Result<Option<Request>>;

async fn get_block_number(&self, confirmed_block_status: BlockStatus) -> Result<BlockNumber>;

Expand Down Expand Up @@ -142,7 +145,7 @@ pub mod mock {

#[async_trait]
impl EntropyReader for MockEntropyReader {
async fn get_request(
async fn get_request_v2(
&self,
provider: Address,
sequence_number: u64,
Expand Down
4 changes: 2 additions & 2 deletions apps/fortuna/src/command/get_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ pub async fn get_request(opts: &GetRequestOptions) -> Result<()> {
&Config::load(&opts.config.config)?.get_chain_config(&opts.chain_id)?,
)?);

let p = contract.get_provider_info(opts.provider).call().await?;
let p = contract.get_provider_info_v2(opts.provider).call().await?;

tracing::info!("Found provider: {:?}", p);

let r = contract
.get_request(opts.provider, opts.sequence)
.get_request_v2(opts.provider, opts.sequence)
.call()
.await?;
tracing::info!("Found request: {:?}", r);
Expand Down
17 changes: 10 additions & 7 deletions apps/fortuna/src/command/inspect.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use {
crate::{
chain::ethereum::{EntropyStructsRequest, PythContract},
chain::ethereum::{EntropyStructsV2Request, PythContract},
config::{Config, EthereumConfig, InspectOptions},
},
anyhow::Result,
Expand Down Expand Up @@ -43,7 +43,10 @@ async fn inspect_chain(

let contract = PythContract::from_config(chain_config)?;
let entropy_provider = contract.get_default_provider().call().await?;
let provider_info = contract.get_provider_info(entropy_provider).call().await?;
let provider_info = contract
.get_provider_info_v2(entropy_provider)
.call()
.await?;
let mut current_request_number = provider_info.sequence_number;
println!("Initial request number: {}", current_request_number);
let last_request_number = current_request_number.saturating_sub(num_requests);
Expand All @@ -61,12 +64,12 @@ async fn inspect_chain(
break;
}
multicall.add_call(
contract.get_request(entropy_provider, current_request_number),
contract.get_request_v2(entropy_provider, current_request_number),
false,
);
current_request_number -= 1;
}
let return_data: Vec<EntropyStructsRequest> = multicall.call_array().await?;
let return_data: Vec<EntropyStructsV2Request> = multicall.call_array().await?;
for request in return_data {
process_request(rpc_provider.clone(), request).await?;
}
Expand All @@ -76,7 +79,7 @@ async fn inspect_chain(
println!("Multicall not deployed in this chain, fetching requests one by one");
while current_request_number > last_request_number {
let request = contract
.get_request(entropy_provider, current_request_number)
.get_request_v2(entropy_provider, current_request_number)
.call()
.await?;
process_request(rpc_provider.clone(), request).await?;
Expand All @@ -91,9 +94,9 @@ async fn inspect_chain(

async fn process_request(
rpc_provider: Provider<Http>,
request: EntropyStructsRequest,
request: EntropyStructsV2Request,
) -> Result<()> {
if request.sequence_number != 0 && request.is_request_with_callback {
if request.sequence_number != 0 && request.callback_status != 0 {
let block = rpc_provider
.get_block(request.block_number)
.await?
Expand Down
2 changes: 1 addition & 1 deletion apps/fortuna/src/command/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ async fn setup_chain_state(
.cmp(&c2.original_commitment_sequence_number)
});

let provider_info = contract.get_provider_info(*provider).call().await?;
let provider_info = contract.get_provider_info_v2(*provider).call().await?;
let latest_metadata = bincode::deserialize::<CommitmentMetadata>(
&provider_info.commitment_metadata,
)
Expand Down
46 changes: 39 additions & 7 deletions apps/fortuna/src/command/setup_provider.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use {
crate::{
api::{get_register_uri, ChainId},
chain::ethereum::{EntropyStructsProviderInfo, SignablePythContract},
chain::ethereum::{EntropyStructsV2ProviderInfo, SignablePythContract},
command::register_provider::{register_provider_from_config, CommitmentMetadata},
config::{Config, EthereumConfig, SetupProviderOptions},
state::{HashChainState, PebbleHashChain},
Expand Down Expand Up @@ -76,7 +76,10 @@ async fn setup_chain_provider(
let contract = Arc::new(SignablePythContract::from_config(chain_config, &private_key).await?);

tracing::info!("Fetching provider info");
let provider_info = contract.get_provider_info(provider_address).call().await?;
let provider_info = contract
.get_provider_info_v2(provider_address)
.call()
.await?;
tracing::info!("Provider info: {:?}", provider_info);

let mut register = false;
Expand Down Expand Up @@ -147,7 +150,10 @@ async fn setup_chain_provider(
tracing::info!("Registered");
}

let provider_info = contract.get_provider_info(provider_address).call().await?;
let provider_info = contract
.get_provider_info_v2(provider_address)
.call()
.await?;

sync_fee(&contract, &provider_info, chain_config.fee)
.in_current_span()
Expand All @@ -174,12 +180,16 @@ async fn setup_chain_provider(
.in_current_span()
.await?;

sync_default_gas_limit(&contract, &provider_info, chain_config.gas_limit)
.in_current_span()
.await?;

Ok(())
}

async fn sync_uri(
contract: &Arc<SignablePythContract>,
provider_info: &EntropyStructsProviderInfo,
provider_info: &EntropyStructsV2ProviderInfo,
uri: String,
) -> Result<()> {
let uri_as_bytes: Bytes = AbiBytes::from(uri.as_str()).into();
Expand All @@ -199,7 +209,7 @@ async fn sync_uri(

async fn sync_fee(
contract: &Arc<SignablePythContract>,
provider_info: &EntropyStructsProviderInfo,
provider_info: &EntropyStructsV2ProviderInfo,
provider_fee: u128,
) -> Result<()> {
if provider_info.fee_in_wei != provider_fee {
Expand All @@ -218,7 +228,7 @@ async fn sync_fee(

async fn sync_fee_manager(
contract: &Arc<SignablePythContract>,
provider_info: &EntropyStructsProviderInfo,
provider_info: &EntropyStructsV2ProviderInfo,
fee_manager: Address,
) -> Result<()> {
if provider_info.fee_manager != fee_manager {
Expand All @@ -232,7 +242,7 @@ async fn sync_fee_manager(

async fn sync_max_num_hashes(
contract: &Arc<SignablePythContract>,
provider_info: &EntropyStructsProviderInfo,
provider_info: &EntropyStructsV2ProviderInfo,
max_num_hashes: u32,
) -> Result<()> {
if provider_info.max_num_hashes != max_num_hashes {
Expand All @@ -248,3 +258,25 @@ async fn sync_max_num_hashes(
}
Ok(())
}

async fn sync_default_gas_limit(
contract: &Arc<SignablePythContract>,
provider_info: &EntropyStructsV2ProviderInfo,
default_gas_limit: u32,
) -> Result<()> {
if provider_info.default_gas_limit != default_gas_limit {
tracing::info!(
"Updating provider default gas limit to {:?}",
default_gas_limit
);
if let Some(receipt) = contract
.set_default_gas_limit(default_gas_limit)
.send()
.await?
.await?
{
tracing::info!("Updated provider default gas limit to : {:?}", receipt);
}
}
Ok(())
}
5 changes: 4 additions & 1 deletion apps/fortuna/src/command/withdraw_fees.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,10 @@ pub async fn withdraw_fees_for_chain(
retained_balance: u128,
) -> Result<()> {
tracing::info!("Fetching fees for provider: {:?}", provider_address);
let provider_info = contract.get_provider_info(provider_address).call().await?;
let provider_info = contract
.get_provider_info_v2(provider_address)
.call()
.await?;
let fees = provider_info.accrued_fees_in_wei;
tracing::info!("Accrued fees: {} wei", fees);

Expand Down
43 changes: 1 addition & 42 deletions apps/fortuna/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ pub struct EthereumConfig {
pub legacy_tx: bool,

/// The gas limit to use for entropy callback transactions.
pub gas_limit: u64,
pub gas_limit: u32,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

u32 is the size of the field in the contract


/// The percentage multiplier to apply to priority fee estimates (100 = no change, e.g. 150 = 150% of base fee)
#[serde(default = "default_priority_fee_multiplier_pct")]
Expand Down Expand Up @@ -200,23 +200,6 @@ fn default_backlog_range() -> u64 {

#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
pub struct EscalationPolicyConfig {
// The keeper will perform the callback as long as the tx is within this percentage of the configured gas limit.
// Default value is 110, meaning a 10% tolerance over the configured value.
#[serde(default = "default_gas_limit_tolerance_pct")]
pub gas_limit_tolerance_pct: u64,

/// The initial gas multiplier to apply to the tx gas estimate
#[serde(default = "default_initial_gas_multiplier_pct")]
pub initial_gas_multiplier_pct: u64,

/// The gas multiplier to apply to the tx gas estimate during backoff retries.
/// The gas on each successive retry is multiplied by this value, with the maximum multiplier capped at `gas_multiplier_cap_pct`.
#[serde(default = "default_gas_multiplier_pct")]
pub gas_multiplier_pct: u64,
/// The maximum gas multiplier to apply to the tx gas estimate during backoff retries.
#[serde(default = "default_gas_multiplier_cap_pct")]
pub gas_multiplier_cap_pct: u64,

/// The fee multiplier to apply to the fee during backoff retries.
/// The initial fee is 100% of the estimate (which itself may be padded based on our chain configuration)
/// The fee on each successive retry is multiplied by this value, with the maximum multiplier capped at `fee_multiplier_cap_pct`.
Expand All @@ -226,22 +209,6 @@ pub struct EscalationPolicyConfig {
pub fee_multiplier_cap_pct: u64,
}

fn default_gas_limit_tolerance_pct() -> u64 {
110
}

fn default_initial_gas_multiplier_pct() -> u64 {
125
}

fn default_gas_multiplier_pct() -> u64 {
110
}

fn default_gas_multiplier_cap_pct() -> u64 {
600
}

fn default_fee_multiplier_pct() -> u64 {
110
}
Expand All @@ -253,10 +220,6 @@ fn default_fee_multiplier_cap_pct() -> u64 {
impl Default for EscalationPolicyConfig {
fn default() -> Self {
Self {
gas_limit_tolerance_pct: default_gas_limit_tolerance_pct(),
initial_gas_multiplier_pct: default_initial_gas_multiplier_pct(),
gas_multiplier_pct: default_gas_multiplier_pct(),
gas_multiplier_cap_pct: default_gas_multiplier_cap_pct(),
fee_multiplier_pct: default_fee_multiplier_pct(),
fee_multiplier_cap_pct: default_fee_multiplier_cap_pct(),
}
Expand All @@ -266,10 +229,6 @@ impl Default for EscalationPolicyConfig {
impl EscalationPolicyConfig {
pub fn to_policy(&self) -> EscalationPolicy {
EscalationPolicy {
gas_limit_tolerance_pct: self.gas_limit_tolerance_pct,
initial_gas_multiplier_pct: self.initial_gas_multiplier_pct,
gas_multiplier_pct: self.gas_multiplier_pct,
gas_multiplier_cap_pct: self.gas_multiplier_cap_pct,
fee_multiplier_pct: self.fee_multiplier_pct,
fee_multiplier_cap_pct: self.fee_multiplier_cap_pct,
}
Expand Down
Loading
Loading