Skip to content

Commit

Permalink
fixing merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
0xKitsune committed Nov 2, 2023
2 parents 3116960 + 8049299 commit 9a34906
Show file tree
Hide file tree
Showing 14 changed files with 153 additions and 301 deletions.
177 changes: 47 additions & 130 deletions bin/state_bridge_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,46 +10,30 @@ use ethers::prelude::{
SignerMiddleware, H160,
};
use ethers::providers::Middleware;
use futures::stream::FuturesUnordered;
use futures::StreamExt;
use serde::{Deserialize, Serialize};
use state_bridge::bridge::{IBridgedWorldID, IStateBridge, StateBridge};
use state_bridge::root::IWorldIDIdentityManager;
use state_bridge::abi::{
IBridgedWorldID, IStateBridge, IWorldIDIdentityManager,
};
use state_bridge::bridge::StateBridge;
use state_bridge::StateBridgeService;
use tracing::info;

// The state bridge service propagates roots from the world tree. Frequency of root propagation is specified
// by the relaying_period. This service will not propagate roots that have already been propagated before.
#[derive(Parser, Debug)]
#[clap(
name = "State Bridge Service",
about = "The state bridge service propagates roots according to the specified relaying_period by calling the propagateRoot() method on each specified World ID StateBridge. The state bridge service will also make sure that it doesn't propagate roots that have already been propagated and have finalized on the BridgedWorldID side."
about = "The state bridge service listens to root changes from the WorldIdIdentityManager and propagates them to each of the corresponding Layer 2s specified in the configuration file."
)]
struct Options {
#[clap(long, help = "Path to the TOML state bridge service config file")]
struct Opts {
#[clap(
short,
long,
help = "Path to the TOML state bridge service config file"
)]
config: PathBuf,
}

// Converts a u64 into a Duration using Duration::from_secs
mod duration_seconds {
use std::time::Duration;

use serde::{Deserialize, Deserializer, Serializer};

pub fn serialize<S>(duration: &Duration, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
s.serialize_u64(duration.as_secs())
}

pub fn deserialize<'de, D>(d: D) -> Result<Duration, D::Error>
where
D: Deserializer<'de>,
{
let secs = u64::deserialize(d)?;
Ok(Duration::from_secs(secs))
}
}

#[derive(Deserialize, Serialize, Debug, Clone, PartialEq)]
struct BridgeConfig {
name: String,
Expand All @@ -58,14 +42,24 @@ struct BridgeConfig {
bridged_rpc_url: String,
}

// The config TOML file defines all the necessary parameters to spawn a state bridge service.
// rpc_url - HTTP rpc url for an Ethereum node (string)
// private_key - pk to an address that will call the propagateRoot() method on the StateBridge contract (string)
// world_id_address - WorldIDIdentityManager contract address (string)
// bridge_pair_addresses - List of StateBridge and BridgedWorldID contract address pairs (strings)
// bridged_world_id_addresses - List of BridgedWorldID contract addresses (strings)
// relaying_period: propagateRoot() call period time in seconds (u64)
// block_confirmations - Number of block confirmations required for the propagateRoot call on the StateBridge contract (optional number)
//TODO: lets update this to be a yaml file and then we can do something like the following:
// rpc_url: ""
// private_key: ""
// world_id_address: ""
// block_confirmations: ""
// state_bridges:
// optimism:
// state_bridge_address: ""
// bridged_world_id_address: ""
// bridged_rpc_url: ""
// relaying_period_seconds: 5
//
// arbitrum:
// state_bridge_address: ""
// bridged_world_id_address: ""
// bridged_rpc_url: ""
// relaying_period_seconds: 5

#[derive(Deserialize, Serialize, Debug, Clone)]
struct Config {
// RPC URL for the HTTP provider (World ID IdentityManager)
Expand All @@ -77,37 +71,25 @@ struct Config {
// List of `StateBridge` and `BridgedWorldID` pair addresses
bridge_configs: Vec<BridgeConfig>,
// `propagateRoot()` call period time in seconds
#[serde(with = "duration_seconds")]
relaying_period_seconds: Duration,
// Number of block confirmations required for the `propagateRoot` call on the `StateBridge`
// contract
#[serde(default = "default_block_confirmations")]
block_confirmations: usize,
}

fn default_block_confirmations() -> usize {
1usize
block_confirmations: Option<usize>,
}

#[tokio::main]
async fn main() -> eyre::Result<()> {
let options = Options::parse();

let contents = fs::read_to_string(&options.config)?;

let opts = Opts::parse();
let contents = fs::read_to_string(&opts.config)?;
let config: Config = toml::from_str(&contents)?;

let rpc_url = config.rpc_url;

let block_confirmations = config.block_confirmations;

spawn_state_bridge_service(
rpc_url,
config.rpc_url,
config.private_key,
config.world_id_address,
config.bridge_configs,
config.relaying_period_seconds,
block_confirmations,
config.block_confirmations.unwrap_or(0),
)
.await?;

Expand All @@ -127,15 +109,13 @@ async fn spawn_state_bridge_service(

let chain_id = provider.get_chainid().await?.as_u64();

let wallet = private_key
.parse::<LocalWallet>()
.expect("couldn't instantiate wallet from private key")
.with_chain_id(chain_id);
let wallet = private_key.parse::<LocalWallet>()?.with_chain_id(chain_id);
let wallet_address = wallet.address();

let middleware = SignerMiddleware::new(provider, wallet);
let middleware = NonceManagerMiddleware::new(middleware, wallet_address);
let middleware = Arc::new(middleware);
let signer_middleware = SignerMiddleware::new(provider, wallet);
let nonce_manager_middleware =
NonceManagerMiddleware::new(signer_middleware, wallet_address);
let middleware = Arc::new(nonce_manager_middleware);

let world_id_interface =
IWorldIDIdentityManager::new(world_id_address, middleware.clone());
Expand Down Expand Up @@ -187,75 +167,12 @@ async fn spawn_state_bridge_service(
info!("Added a bridge to {} to the state-bridge-service", name);
}

state_bridge_service.spawn().await?;

Ok(())
}

#[cfg(test)]
mod tests {
use std::str::FromStr;
use std::time::Duration;

use super::{Config, H160};
use crate::BridgeConfig;
let handles = state_bridge_service.spawn().await?;

#[tokio::test]
async fn test_deserialize_toml() -> eyre::Result<()> {
let config: Config = toml::from_str(
r#"
rpc_url = "127.0.0.1:8545"
private_key = "4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318"
world_id_address = "0x3f0BF744bb79A0b919f7DED73724ec20c43572B9"
bridge_configs = [
[
"Optimism",
"0x3f0BF744bb79A0b919f7DED73724ec20c43572B9",
"0x4f0BF744bb79A0b919f7DED73724ec20c43572B9",
"127.0.0.1:8545",
]
]
relaying_period_seconds = 5
"#)
.expect("couldn't deserialize toml-encoded string");

assert_eq!(
config.rpc_url,
String::from("127.0.0.1:8545"),
"RPC didn't match"
);
assert_eq!(config.private_key, String::from("4c0883a69102937d6231471b5dbb6204fe5129617082792ae468d01a3f362318"), "private key didn't match");
assert_eq!(
config.world_id_address,
H160::from_str("0x3f0BF744bb79A0b919f7DED73724ec20c43572B9")
.unwrap(),
"World ID address didn't match"
);
let bridged_configs: Vec<BridgeConfig> = vec![BridgeConfig {
name: "Optimism".to_string(),
state_bridge_address: H160::from_str(
"0x3f0BF744bb79A0b919f7DED73724ec20c43572B9",
)
.unwrap(),
bridged_world_id_address: H160::from_str(
"0x4f0BF744bb79A0b919f7DED73724ec20c43572B9",
)
.unwrap(),
bridged_rpc_url: "127.0.0.1:8545".to_string(),
}];

assert_eq!(config.bridge_configs, bridged_configs);
// assert it uses serde default 1 block confirmation
assert_eq!(
config.block_confirmations, 1usize,
"block confirmations didn't match"
);
assert_eq!(
config.relaying_period_seconds,
Duration::from_secs(5u64),
"relaying period didn't match"
);

Ok(())
let mut handles = handles.into_iter().collect::<FuturesUnordered<_>>();
while let Some(result) = handles.next().await {
result??;
}

Ok(())
}
2 changes: 0 additions & 2 deletions crates/common/src/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ pub fn init_datadog_subscriber(service_name: &str, level: Level) {
.init();
}

/// Extract the W3C Trace Context from the headers of a request and add them
/// to the current span.
pub fn trace_from_headers(headers: &http::HeaderMap) {
tracing::Span::current().set_parent(
opentelemetry::global::get_text_map_propagator(|propagator| {
Expand Down
23 changes: 23 additions & 0 deletions crates/state_bridge/src/abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use ethers::middleware::contract::abigen;

abigen!(
IWorldIDIdentityManager,
r#"[
function latestRoot() external returns (uint256)
event TreeChanged(uint256 indexed preRoot, uint8 indexed kind, uint256 indexed postRoot)
]"#;

IStateBridge,
r#"[
function propagateRoot() external
]"#;

IBridgedWorldID,
r#"[
event RootAdded(uint256 root, uint128 timestamp)
function latestRoot() public view virtual returns (uint256)
function receiveRoot(uint256 newRoot) external
]"#,
event_derives(serde::Deserialize, serde::Serialize)

);
61 changes: 18 additions & 43 deletions crates/state_bridge/src/bridge.rs
Original file line number Diff line number Diff line change
@@ -1,36 +1,17 @@
use std::sync::Arc;

use ethers::middleware::contract::abigen;
use ethers::providers::Middleware;
use ethers::types::H160;
use ruint::Uint;
use tokio::select;
use tokio::task::JoinHandle;
use tokio::time::{Duration, Instant};

use crate::abi::{IBridgedWorldID, IStateBridge};
use crate::error::StateBridgeError;
use crate::root::Hash;

abigen!(
IStateBridge,
r#"[
function propagateRoot() external
]"#;
);

abigen!(
IBridgedWorldID,
r#"[
event TreeChanged(uint256 indexed preRoot, uint8 indexed kind, uint256 indexed postRoot)
event RootAdded(uint256 root, uint128 timestamp)
function latestRoot() public view virtual returns (uint256)
function receiveRoot(uint256 newRoot) external
]"#,
event_derives(serde::Deserialize, serde::Serialize)
);

/// The `StateBridge` takes care of listening to roots propagated from the `WorldRoot` and
/// propagates them periodically every time `relaying_period` elapses and the root was updated.
/// The `StateBridge` is responsible for monitoring root changes from the `WorldRoot`, propagating the root to the corresponding Layer 2.
pub struct StateBridge<M: Middleware + 'static> {
/// Interface for the `StateBridge` contract
pub state_bridge: IStateBridge<M>,
Expand All @@ -43,15 +24,12 @@ pub struct StateBridge<M: Middleware + 'static> {
}

impl<M: Middleware> StateBridge<M> {
/// Initializes a StateBridge
/// # Arguments
///
/// `state_bridge`: `StateBridge` contract interface
///
/// `bridged_world_id`: `BridgedWorldID` contract interface
///
/// `relaying_period`: Time in between `propagateRoot()` calls
///
/// `block_confirmations: The number of blocks before a `propagateRoot()` call is considered finalized
/// * state_bridge - Interface to the StateBridge smart contract.
/// * bridged_world_id - Interface to the BridgedWorldID smart contract.
/// * relaying_period - Duration between successive propagateRoot() invocations.
/// * block_confirmations - Number of block confirmations required to consider a propagateRoot() transaction as finalized.
pub fn new(
state_bridge: IStateBridge<M>,
bridged_world_id: IBridgedWorldID<M>,
Expand All @@ -66,19 +44,14 @@ impl<M: Middleware> StateBridge<M> {
})
}

/// Initializes a StateBridge with address and middleware
///
/// `bridge_address`: `StateBridge` contract address
///
/// `canonical_middleware`: middleware for the chain where the `StateBridge` is deployed
/// # Arguments
///
/// `bridged_world_id_address`: `BridgedWorldID` contract address
///
/// `derived_middleware`: middleware for the chain where the `BridgedWorldID` is deployed
///
/// `relaying_period`: Time in between `propagateRoot()` calls
///
/// `block_confirmations: The number of block confirmations before a `propagateRoot()` transaction is considered finalized
/// * `bridge_address` - Address of the StateBridge contract.
/// * `canonical_middleware` - Middleware for interacting with the chain where StateBridge is deployed.
/// * `bridged_world_id_address` - Address of the BridgedWorldID contract.
/// * `derived_middleware` - Middleware for interacting with the chain where BridgedWorldID is deployed.
/// * `relaying_period` - Duration between `propagateRoot()` transactions.
/// * `block_confirmations` - Number of block confirmations before a`propagateRoot()` transaction is considered finalized.
pub fn new_from_parts(
bridge_address: H160,
canonical_middleware: Arc<M>,
Expand All @@ -103,9 +76,11 @@ impl<M: Middleware> StateBridge<M> {
})
}

/// Spawns the `StateBridge` which listens to the `WorldRoot` `TreeChanged` events for new roots to propagate.
/// Spawns a `StateBridge` task to listen for `TreeChanged` events from `WorldRoot` and propagate new roots.
///
/// # Arguments
///
/// `root_rx`: The root receiver that listens to the `WorldRoot` root sender
/// * `root_rx` - Receiver channel for roots from `WorldRoot`.
pub async fn spawn(
&self,
mut root_rx: tokio::sync::broadcast::Receiver<Hash>,
Expand Down
Loading

0 comments on commit 9a34906

Please sign in to comment.