[fortuna] script to setup a provider for all chains (#1229)
* auto register script * renaming * add comments * update abi file path * pre commit * pre commit * resolved some * better comment * resolve comments * fix bug * pre commit * fix * update version
This commit is contained in:
parent
7529b053e3
commit
ab10b9f5fa
|
@ -1,3 +1,4 @@
|
|||
/target
|
||||
config.yaml
|
||||
*secret*
|
||||
*private-key*
|
||||
|
|
|
@ -1486,7 +1486,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "fortuna"
|
||||
version = "3.2.0"
|
||||
version = "3.2.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"axum",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "fortuna"
|
||||
version = "3.2.0"
|
||||
version = "3.2.1"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
|
|
@ -9,6 +9,7 @@ RUN rustup default nightly-2023-07-23
|
|||
WORKDIR /src
|
||||
COPY fortuna fortuna
|
||||
COPY pythnet pythnet
|
||||
COPY target_chains/ethereum/entropy_sdk/solidity/abis target_chains/ethereum/entropy_sdk/solidity/abis
|
||||
|
||||
WORKDIR /src/fortuna
|
||||
|
||||
|
|
1020
fortuna/src/abi.json
1020
fortuna/src/abi.json
File diff suppressed because it is too large
Load Diff
|
@ -50,7 +50,10 @@ use {
|
|||
|
||||
// TODO: Programmatically generate this so we don't have to keep committed ABI in sync with the
|
||||
// contract in the same repo.
|
||||
abigen!(PythRandom, "src/abi.json");
|
||||
abigen!(
|
||||
PythRandom,
|
||||
"../target_chains/ethereum/entropy_sdk/solidity/abis/IEntropy.json"
|
||||
);
|
||||
|
||||
pub type SignablePythContract = PythRandom<
|
||||
TransformerMiddleware<SignerMiddleware<Provider<Http>, LocalWallet>, LegacyTxTransformer>,
|
||||
|
|
|
@ -3,6 +3,7 @@ mod get_request;
|
|||
mod register_provider;
|
||||
mod request_randomness;
|
||||
mod run;
|
||||
mod setup_provider;
|
||||
|
||||
pub use {
|
||||
generate::generate,
|
||||
|
@ -10,4 +11,5 @@ pub use {
|
|||
register_provider::register_provider,
|
||||
request_randomness::request_randomness,
|
||||
run::run,
|
||||
setup_provider::setup_provider,
|
||||
};
|
||||
|
|
|
@ -8,12 +8,9 @@ use {
|
|||
state::PebbleHashChain,
|
||||
},
|
||||
anyhow::Result,
|
||||
ethers::{
|
||||
signers::{
|
||||
LocalWallet,
|
||||
Signer,
|
||||
},
|
||||
types::Address,
|
||||
ethers::signers::{
|
||||
LocalWallet,
|
||||
Signer,
|
||||
},
|
||||
std::sync::Arc,
|
||||
};
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
use {
|
||||
crate::{
|
||||
chain::ethereum::SignablePythContract,
|
||||
command::{
|
||||
register_provider,
|
||||
register_provider::CommitmentMetadata,
|
||||
},
|
||||
config::{
|
||||
Config,
|
||||
RegisterProviderOptions,
|
||||
SetupProviderOptions,
|
||||
},
|
||||
state::{
|
||||
HashChainState,
|
||||
PebbleHashChain,
|
||||
},
|
||||
},
|
||||
anyhow::Result,
|
||||
ethers::signers::{
|
||||
LocalWallet,
|
||||
Signer,
|
||||
},
|
||||
std::sync::Arc,
|
||||
};
|
||||
|
||||
/// Setup provider for all the chains.
|
||||
/// 1. Register if there was no previous registration.
|
||||
/// 2. Re-register if there are no more random numbers to request on the contract.
|
||||
/// 3. Re-register if there is a mismatch in generated hash chain.
|
||||
/// 4. Update provider fee if there is a mismatch with the fee set on contract.
|
||||
/// 5. Update provider uri if there is a mismatch with the uri set on contract.
|
||||
pub async fn setup_provider(opts: &SetupProviderOptions) -> Result<()> {
|
||||
let config = Config::load(&opts.config.config)?;
|
||||
let private_key = opts.load_private_key()?;
|
||||
let secret = opts.randomness.load_secret()?;
|
||||
let provider_address = private_key.clone().parse::<LocalWallet>()?.address();
|
||||
|
||||
for (chain_id, chain_config) in &config.chains {
|
||||
// Initialize a Provider to interface with the EVM contract.
|
||||
let contract =
|
||||
Arc::new(SignablePythContract::from_config(&chain_config, &private_key).await?);
|
||||
let provider_info = contract.get_provider_info(provider_address).call().await?;
|
||||
tracing::info!("Provider info: {:?}", provider_info);
|
||||
|
||||
let mut register = false;
|
||||
|
||||
// This condition satisfies for both when there is no registration and when there are no
|
||||
// more random numbers left to request
|
||||
if provider_info.end_sequence_number <= provider_info.sequence_number {
|
||||
tracing::info!(
|
||||
"endSequenceNumber <= sequenceNumber. endSequenceNumber={0}, sequenceNumber={1}",
|
||||
provider_info.end_sequence_number,
|
||||
provider_info.sequence_number
|
||||
);
|
||||
tracing::info!("Registering to {}", &chain_id);
|
||||
register = true;
|
||||
} else {
|
||||
let metadata =
|
||||
bincode::deserialize::<CommitmentMetadata>(&provider_info.commitment_metadata)?;
|
||||
|
||||
let hash_chain = PebbleHashChain::from_config(
|
||||
&secret,
|
||||
&chain_id,
|
||||
&provider_address,
|
||||
&chain_config.contract_addr,
|
||||
&metadata.seed,
|
||||
metadata.chain_length,
|
||||
)?;
|
||||
let chain_state = HashChainState {
|
||||
offsets: vec![provider_info
|
||||
.original_commitment_sequence_number
|
||||
.try_into()?],
|
||||
hash_chains: vec![hash_chain],
|
||||
};
|
||||
|
||||
|
||||
if chain_state.reveal(provider_info.original_commitment_sequence_number)?
|
||||
!= provider_info.original_commitment
|
||||
{
|
||||
tracing::info!("The root of the generated hash chain for chain id {} does not match the commitment", &chain_id);
|
||||
tracing::info!("Registering to {}", &chain_id);
|
||||
register = true;
|
||||
}
|
||||
}
|
||||
|
||||
if register {
|
||||
register_provider(&RegisterProviderOptions {
|
||||
config: opts.config.clone(),
|
||||
chain_id: chain_id.clone(),
|
||||
private_key: private_key.clone(),
|
||||
randomness: opts.randomness.clone(),
|
||||
fee: opts.fee,
|
||||
uri: opts.uri.clone(),
|
||||
})
|
||||
.await?;
|
||||
} else {
|
||||
if provider_info.fee_in_wei != opts.fee {
|
||||
if let Some(r) = contract.set_provider_fee(opts.fee).send().await?.await? {
|
||||
tracing::info!("Updated provider fee: {:?}", r);
|
||||
}
|
||||
}
|
||||
|
||||
if bincode::deserialize::<String>(&provider_info.uri)? != opts.uri {
|
||||
if let Some(receipt) = contract
|
||||
.set_provider_uri(bincode::serialize(&opts.uri)?.into())
|
||||
.send()
|
||||
.await?
|
||||
.log_msg("Pending transfer hash")
|
||||
.await?
|
||||
{
|
||||
tracing::info!("Updated provider uri: {:?}", receipt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
|
@ -27,6 +27,7 @@ pub use {
|
|||
register_provider::RegisterProviderOptions,
|
||||
request_randomness::RequestRandomnessOptions,
|
||||
run::RunOptions,
|
||||
setup_provider::SetupProviderOptions,
|
||||
};
|
||||
|
||||
mod generate;
|
||||
|
@ -34,6 +35,7 @@ mod get_request;
|
|||
mod register_provider;
|
||||
mod request_randomness;
|
||||
mod run;
|
||||
mod setup_provider;
|
||||
|
||||
const DEFAULT_RPC_ADDR: &str = "127.0.0.1:34000";
|
||||
const DEFAULT_HTTP_ADDR: &str = "http://127.0.0.1:34000";
|
||||
|
@ -51,6 +53,10 @@ pub enum Options {
|
|||
/// Register a new provider with the Pyth Random oracle.
|
||||
RegisterProvider(RegisterProviderOptions),
|
||||
|
||||
/// Set up the provider for all the provided chains.
|
||||
/// It registers, re-registers, or updates provider config on chain.
|
||||
SetupProvider(SetupProviderOptions),
|
||||
|
||||
/// Request a random number from the contract.
|
||||
RequestRandomness(RequestRandomnessOptions),
|
||||
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
use {
|
||||
crate::config::{
|
||||
ConfigOptions,
|
||||
RandomnessOptions,
|
||||
},
|
||||
anyhow::Result,
|
||||
clap::Args,
|
||||
std::fs,
|
||||
};
|
||||
|
||||
#[derive(Args, Clone, Debug)]
|
||||
#[command(next_help_heading = "Setup Provider Options")]
|
||||
#[group(id = "SetupProviderOptions")]
|
||||
pub struct SetupProviderOptions {
|
||||
#[command(flatten)]
|
||||
pub config: ConfigOptions,
|
||||
|
||||
/// Path to a file containing a 20-byte (40 char) hex encoded Ethereum private key.
|
||||
/// This key is required to submit transactions (such as registering with the contract).
|
||||
#[arg(long = "private-key")]
|
||||
#[arg(env = "PRIVATE_KEY")]
|
||||
pub private_key_file: String,
|
||||
|
||||
#[command(flatten)]
|
||||
pub randomness: RandomnessOptions,
|
||||
|
||||
/// The fee to charge (in wei) for each requested random number
|
||||
#[arg(long = "pyth-contract-fee")]
|
||||
#[arg(default_value = "100")]
|
||||
pub fee: u128,
|
||||
|
||||
/// The URI where clients can retrieve random values from this provider,
|
||||
/// i.e., wherever fortuna for this provider will be hosted.
|
||||
#[arg(long = "uri")]
|
||||
#[arg(default_value = "")]
|
||||
pub uri: String,
|
||||
}
|
||||
|
||||
impl SetupProviderOptions {
|
||||
pub fn load_private_key(&self) -> Result<String> {
|
||||
return Ok((fs::read_to_string(&self.private_key_file))?);
|
||||
}
|
||||
}
|
|
@ -39,6 +39,7 @@ async fn main() -> Result<()> {
|
|||
config::Options::Generate(opts) => command::generate(&opts).await,
|
||||
config::Options::Run(opts) => command::run(&opts).await,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue