Skip to content
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

feat(entropy): Entropy inspection #1588

Merged
merged 4 commits into from
May 22, 2024
Merged
Show file tree
Hide file tree
Changes from 3 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
91 changes: 78 additions & 13 deletions apps/fortuna/Cargo.lock

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

1 change: 1 addition & 0 deletions apps/fortuna/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ utoipa-swagger-ui = { version = "3.1.4", features = ["axum"] }
once_cell = "1.18.0"
lazy_static = "1.4.0"
url = "2.5.0"
chrono = { version = "0.4.38", features = ["clock", "std"] , default-features = false}


[dev-dependencies]
Expand Down
2 changes: 2 additions & 0 deletions apps/fortuna/src/command.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod generate;
mod get_request;
mod inspect;
mod register_provider;
mod request_randomness;
mod run;
Expand All @@ -8,6 +9,7 @@ mod setup_provider;
pub use {
generate::generate,
get_request::get_request,
inspect::inspect,
register_provider::register_provider,
request_randomness::request_randomness,
run::run,
Expand Down
113 changes: 113 additions & 0 deletions apps/fortuna/src/command/inspect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
use {
crate::{
chain::ethereum::{
PythContract,
Request,
},
config::{
Config,
EthereumConfig,
InspectOptions,
},
},
anyhow::Result,
ethers::{
contract::Multicall,
middleware::Middleware,
prelude::{
Http,
Provider,
},
},
};

pub async fn inspect(opts: &InspectOptions) -> Result<()> {
match opts.chain_id.clone() {
Some(chain_id) => {
let chain_config = &Config::load(&opts.config.config)?.get_chain_config(&chain_id)?;
inspect_chain(chain_config, opts.num_requests).await?;
}
None => {
let config = Config::load(&opts.config.config)?;
for (chain_id, chain_config) in config.chains.iter() {
println!("Inspecting chain: {}", chain_id);
inspect_chain(chain_config, opts.num_requests).await?;
}
}
}
Ok(())
}

async fn inspect_chain(chain_config: &EthereumConfig, num_requests: u64) -> Result<()> {
let rpc_provider = Provider::<Http>::try_from(&chain_config.geth_rpc_addr)?;
let multicall_exists = rpc_provider
.get_code(ethers::contract::MULTICALL_ADDRESS, None)
.await
.expect("Failed to get code")
.len()
> 0;

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 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);
if multicall_exists {
println!("Using multicall");
let mut multicall = Multicall::new(
rpc_provider.clone(),
Some(ethers::contract::MULTICALL_ADDRESS),
)
.await?;
let batch_size = 100;
Copy link
Contributor

Choose a reason for hiding this comment

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

suggest putting this in InspectOptions with a default value, just in case it needs to be changed later.

while current_request_number > last_request_number {
multicall.clear_calls();
for _ in 0..batch_size {
if current_request_number == 0 {
break;
}
multicall.add_call(
contract.get_request(entropy_provider, current_request_number),
false,
);
current_request_number -= 1;
}
let return_data: Vec<Request> = multicall.call_array().await?;
for request in return_data {
process_request(rpc_provider.clone(), request).await?;
}
println!("Current request number: {}", current_request_number);
}
} else {
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)
.call()
.await?;
process_request(rpc_provider.clone(), request).await?;
current_request_number -= 1;
if current_request_number % 100 == 0 {
println!("Current request number: {}", current_request_number);
}
}
}
Ok(())
}

async fn process_request(rpc_provider: Provider<Http>, request: Request) -> Result<()> {
if request.sequence_number != 0 && request.is_request_with_callback {
let block = rpc_provider
.get_block(request.block_number)
.await?
.expect("Block not found");
let datetime = chrono::DateTime::from_timestamp(block.timestamp.as_u64() as i64, 0)
.expect("Invalid timestamp");
println!(
"{} sequence_number:{} block_number:{} requester:{}",
datetime, request.sequence_number, request.block_number, request.requester
);
}
Ok(())
}
5 changes: 5 additions & 0 deletions apps/fortuna/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ use {
pub use {
generate::GenerateOptions,
get_request::GetRequestOptions,
inspect::InspectOptions,
register_provider::RegisterProviderOptions,
request_randomness::RequestRandomnessOptions,
run::RunOptions,
Expand All @@ -38,6 +39,7 @@ pub use {

mod generate;
mod get_request;
mod inspect;
mod register_provider;
mod request_randomness;
mod run;
Expand Down Expand Up @@ -66,6 +68,9 @@ pub enum Options {
/// Request a random number from the contract.
RequestRandomness(RequestRandomnessOptions),

/// Inspect recent requests and find unfulfilled requests with callback.
Inspect(InspectOptions),
Copy link
Contributor

Choose a reason for hiding this comment

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

question about this: how do I tell that the request didn't get a callback from the result? It seems like the output simply prints out all of the requests that have happened.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

any request still stored in the contract is not fulfilled yet. We just iterate through the requests and find the ones where the callback flag is also true and print them out.


/// Generate a random number by running the entire protocol end-to-end
Generate(GenerateOptions),

Expand Down
24 changes: 24 additions & 0 deletions apps/fortuna/src/config/inspect.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use {
crate::{
api::ChainId,
config::ConfigOptions,
},
clap::Args,
};


#[derive(Args, Clone, Debug)]
#[command(next_help_heading = "Inspect Options")]
#[group(id = "Inspect")]
pub struct InspectOptions {
#[command(flatten)]
pub config: ConfigOptions,

/// Check the requests on this chain, or all chains if not specified.
#[arg(long = "chain-id")]
pub chain_id: Option<ChainId>,

/// The number of requests to inspect starting from the most recent request.
#[arg(long = "num-requests", default_value = "1000")]
pub num_requests: u64,
}
1 change: 1 addition & 0 deletions apps/fortuna/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ async fn main() -> Result<()> {
config::Options::RegisterProvider(opts) => command::register_provider(&opts).await,
config::Options::SetupProvider(opts) => command::setup_provider(&opts).await,
config::Options::RequestRandomness(opts) => command::request_randomness(&opts).await,
config::Options::Inspect(opts) => command::inspect(&opts).await,
}
}
Loading
Loading