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

fix(fortuna): Eip1559 fixes #1597

Merged
merged 4 commits into from
May 23, 2024
Merged
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 = "5.4.0"
version = "5.4.1"
edition = "2021"

[dependencies]
Expand Down
26 changes: 15 additions & 11 deletions apps/fortuna/src/chain/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ abigen!(
);

pub type SignablePythContract = PythRandom<
GasOracleMiddleware<
TransformerMiddleware<
TransformerMiddleware<
GasOracleMiddleware<
NonceManagerMiddleware<SignerMiddleware<Provider<Http>, LocalWallet>>,
LegacyTxTransformer,
EthProviderOracle<Provider<Http>>,
>,
EthProviderOracle<Provider<Http>>,
LegacyTxTransformer,
>,
>;
pub type PythContract = PythRandom<Provider<Http>>;
Expand Down Expand Up @@ -102,11 +102,15 @@ impl SignablePythContract {
) -> Result<SignablePythContract> {
let provider = Provider::<Http>::try_from(&chain_config.geth_rpc_addr)?;
let chain_id = provider.get_chainid().await?;

let eip1559_supported = provider
.get_block(ethers::prelude::BlockNumber::Latest)
.await?
.ok_or_else(|| anyhow!("Latest block not found"))?
.base_fee_per_gas
.is_some();
let gas_oracle = EthProviderOracle::new(provider.clone());

let transformer = LegacyTxTransformer {
use_legacy_tx: chain_config.legacy_tx,
use_legacy_tx: !eip1559_supported,
};

let wallet__ = private_key
Expand All @@ -117,12 +121,12 @@ impl SignablePythContract {

Ok(PythRandom::new(
chain_config.contract_addr,
Arc::new(GasOracleMiddleware::new(
TransformerMiddleware::new(
Arc::new(TransformerMiddleware::new(
GasOracleMiddleware::new(
NonceManagerMiddleware::new(SignerMiddleware::new(provider, wallet__), address),
transformer,
gas_oracle,
),
gas_oracle,
transformer,
)),
))
}
Expand Down
151 changes: 86 additions & 65 deletions apps/fortuna/src/command/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use {
config::{
Commitment,
Config,
EthereumConfig,
ProviderConfig,
RunOptions,
},
Expand Down Expand Up @@ -149,77 +150,23 @@ pub async fn run_keeper(

pub async fn run(opts: &RunOptions) -> Result<()> {
let config = Config::load(&opts.config.config)?;
let provider_config = ProviderConfig::load(&opts.provider_config.provider_config)?;
let secret = opts.randomness.load_secret()?;
let (tx_exit, rx_exit) = watch::channel(false);

let mut chains: HashMap<ChainId, BlockchainState> = HashMap::new();
for (chain_id, chain_config) in &config.chains {
let contract = Arc::new(PythContract::from_config(&chain_config)?);
let provider_chain_config = provider_config.get_chain_config(chain_id)?;
let mut provider_commitments = provider_chain_config.get_sorted_commitments();
let provider_info = contract.get_provider_info(opts.provider).call().await?;
let latest_metadata =
bincode::deserialize::<CommitmentMetadata>(&provider_info.commitment_metadata)
.map_err(|e| {
anyhow!(
"Chain: {} - Failed to deserialize commitment metadata: {}",
&chain_id,
e
)
})?;

provider_commitments.push(Commitment {
seed: latest_metadata.seed,
chain_length: latest_metadata.chain_length,
original_commitment_sequence_number: provider_info.original_commitment_sequence_number,
});

// TODO: we may want to load the hash chain in a lazy/fault-tolerant way. If there are many blockchains,
// then it's more likely that some RPC fails. We should tolerate these faults and generate the hash chain
// later when a user request comes in for that chain.

let mut offsets = Vec::<usize>::new();
let mut hash_chains = Vec::<PebbleHashChain>::new();

for commitment in &provider_commitments {
let offset = commitment.original_commitment_sequence_number.try_into()?;
offsets.push(offset);

let pebble_hash_chain = PebbleHashChain::from_config(
&secret,
&chain_id,
&opts.provider,
&chain_config.contract_addr,
&commitment.seed,
commitment.chain_length,
)?;
hash_chains.push(pebble_hash_chain);
}

let chain_state = HashChainState {
offsets,
hash_chains,
};

if chain_state.reveal(provider_info.original_commitment_sequence_number)?
!= provider_info.original_commitment
{
return Err(anyhow!("The root of the generated hash chain for chain id {} does not match the commitment. Are the secret and chain length configured correctly?", &chain_id).into());
} else {
tracing::info!("Root of chain id {} matches commitment", &chain_id);
let state = setup_chain_state(&opts, &secret, chain_id, chain_config).await;
match state {
Ok(state) => {
chains.insert(chain_id.clone(), state);
}
Err(e) => {
tracing::error!("Failed to setup {} {}", chain_id, e);
}
}

let state = api::BlockchainState {
id: chain_id.clone(),
state: Arc::new(chain_state),
contract,
provider_address: opts.provider,
reveal_delay_blocks: chain_config.reveal_delay_blocks,
confirmed_block_status: chain_config.confirmed_block_status,
};

chains.insert(chain_id.clone(), state);
}
if chains.is_empty() {
return Err(anyhow!("No chains were successfully setup"));
}


Expand Down Expand Up @@ -254,6 +201,80 @@ pub async fn run(opts: &RunOptions) -> Result<()> {
Ok(())
}

async fn setup_chain_state(
opts: &&RunOptions,
secret: &String,
chain_id: &ChainId,
chain_config: &EthereumConfig,
) -> Result<BlockchainState> {
let provider_config = ProviderConfig::load(&opts.provider_config.provider_config)?;
let contract = Arc::new(PythContract::from_config(&chain_config)?);
let provider_chain_config = provider_config.get_chain_config(chain_id)?;
let mut provider_commitments = provider_chain_config.get_sorted_commitments();
let provider_info = contract.get_provider_info(opts.provider).call().await?;
let latest_metadata = bincode::deserialize::<CommitmentMetadata>(
&provider_info.commitment_metadata,
)
.map_err(|e| {
anyhow!(
"Chain: {} - Failed to deserialize commitment metadata: {}",
&chain_id,
e
)
})?;

provider_commitments.push(Commitment {
seed: latest_metadata.seed,
chain_length: latest_metadata.chain_length,
original_commitment_sequence_number: provider_info.original_commitment_sequence_number,
});

// TODO: we may want to load the hash chain in a lazy/fault-tolerant way. If there are many blockchains,
// then it's more likely that some RPC fails. We should tolerate these faults and generate the hash chain
// later when a user request comes in for that chain.

let mut offsets = Vec::<usize>::new();
let mut hash_chains = Vec::<PebbleHashChain>::new();

for commitment in &provider_commitments {
let offset = commitment.original_commitment_sequence_number.try_into()?;
offsets.push(offset);

let pebble_hash_chain = PebbleHashChain::from_config(
&secret,
&chain_id,
&opts.provider,
&chain_config.contract_addr,
&commitment.seed,
commitment.chain_length,
)?;
hash_chains.push(pebble_hash_chain);
}

let chain_state = HashChainState {
offsets,
hash_chains,
};

if chain_state.reveal(provider_info.original_commitment_sequence_number)?
!= provider_info.original_commitment
{
return Err(anyhow!("The root of the generated hash chain for chain id {} does not match the commitment. Are the secret and chain length configured correctly?", &chain_id).into());
} else {
tracing::info!("Root of chain id {} matches commitment", &chain_id);
}

let state = BlockchainState {
id: chain_id.clone(),
state: Arc::new(chain_state),
contract,
provider_address: opts.provider,
reveal_delay_blocks: chain_config.reveal_delay_blocks,
confirmed_block_status: chain_config.confirmed_block_status,
};
Ok(state)
}


#[derive(Clone, Debug, Hash, PartialEq, Eq, EncodeLabelSet)]
pub struct ChainLabel {
Expand Down
4 changes: 0 additions & 4 deletions apps/fortuna/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,6 @@ pub struct EthereumConfig {
/// its commitment.
pub reveal_delay_blocks: BlockNumber,

/// Use the legacy transaction format (for networks without EIP 1559)
#[serde(default)]
pub legacy_tx: bool,

/// The BlockStatus of the block that is considered confirmed.
/// For example, Finalized, Safe, Latest
#[serde(default)]
Expand Down
Loading