Skip to content

Commit

Permalink
Merge pull request #310 from nomic-io/eth-conn-creation
Browse files Browse the repository at this point in the history
Eth connection creation call
  • Loading branch information
mappum authored Sep 28, 2024
2 parents 0ccfcbf + 2079c75 commit cccfcad
Show file tree
Hide file tree
Showing 2 changed files with 112 additions and 0 deletions.
20 changes: 20 additions & 0 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ const IBC_FEE_USATS: u64 = 1_000_000;
/// The fixed amount of nBTC fee required to make any application call, in
/// micro-satoshis.
const CALL_FEE_USATS: u64 = 100_000_000;
/// The fixed amount of nBTC fee required to create a new Ethereum connection,
/// in micro-satoshis.
const ETH_CREATE_CONNECTION_FEE_USATS: u64 = 10_000_000_000;

const OSMOSIS_CHANNEL_ID: &str = "channel-1";

const FROST_GROUP_INTERVAL: i64 = 10 * 60;
Expand Down Expand Up @@ -572,6 +576,22 @@ impl InnerApp {
Ok(())
}

#[call]
pub fn eth_create_connection(
&mut self,
chain_id: u32,
bridge_contract: Address,
token_contract: Address,
) -> Result<()> {
self.deduct_nbtc_fee(ETH_CREATE_CONNECTION_FEE_USATS.into())?;
// TODO: confirm that this is the right valset to use
let valset = self.bitcoin.checkpoints.active_sigset()?;

Ok(self
.ethereum

Check failure on line 591 in src/app.rs

View workflow job for this annotation

GitHub Actions / clippy

no field `ethereum` on type `&mut app::InnerApp`

error[E0609]: no field `ethereum` on type `&mut app::InnerApp` --> src/app.rs:591:14 | 591 | .ethereum | ^^^^^^^^ unknown field | = note: available fields are: `accounts`, `staking`, `airdrop`, `community_pool`, `incentive_pool` ... and 12 others
.create_connection(chain_id, bridge_contract, token_contract, valset)?)
}

#[call]
pub fn app_noop(&mut self) -> Result<()> {
Ok(())
Expand Down
92 changes: 92 additions & 0 deletions src/ethereum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,42 @@ impl Ethereum {
conn.sign(msg_index, pubkey, sig)
}

pub fn create_connection(
&mut self,
chain_id: u32,
bridge_contract: Address,
token_contract: Address,
valset: SignatorySet,
) -> Result<()> {
let Some(mut network) = self.networks.get_mut(chain_id)? else {
return Err(Error::App(format!("network with chain ID {} not found", chain_id)).into());
};

if network.connections.contains_key(bridge_contract)? {
return Err(Error::App(format!(
"connection with bridge contract address {} already exists",
bridge_contract
))
.into());
}

use sha2::{Digest, Sha256};

// TODO: connection id here is currently sha256(concat(chain_id,
// bridge_contract)), but connection ids may not need to be globally
// unique, so may not need to include chain id.
let id = {
let bytes = [chain_id.encode()?, bridge_contract.bytes().to_vec()].concat();
Sha256::digest(bytes).to_vec()
};

let connection = Connection::new(&id, bridge_contract, token_contract, valset);

network.connections.insert(bridge_contract, connection)?;

Ok(())
}

#[query]
pub fn to_sign(&self, xpub: Xpub) -> Result<ToSign> {
let mut to_sign = vec![];
Expand Down Expand Up @@ -1104,6 +1140,62 @@ mod tests {
Context::remove::<Paid>();
}

#[test]
fn create_connection() -> Result<()> {
let mut ethereum = Ethereum::default();

let secp = Secp256k1::new();

let xpriv = ExtendedPrivKey::new_master(bitcoin::Network::Regtest, &[0]).unwrap();
let xpub = ExtendedPubKey::from_priv(&secp, &xpriv);

let valset = SignatorySet {
index: 0,
signatories: vec![Signatory {
pubkey: derive_pubkey(&secp, xpub.into(), 0).unwrap().into(),
voting_power: 10_000_000_000,
}],
create_time: 0,
present_vp: 10_000_000_000,
possible_vp: 10_000_000_000,
};

let bridge_contract = Address::NULL;
let token_contract = Address::NULL;
let chain_id = 1337;

ethereum.networks.insert(
chain_id,
Network {
id: chain_id,
connections: Default::default(),
},
)?;

ethereum.create_connection(chain_id, bridge_contract, token_contract, valset.clone())?;

let network = ethereum.networks.get(chain_id)?.unwrap();

let connection = network.connections.get(bridge_contract)?.unwrap();

assert_eq!(
connection.id,
[
123, 72, 3, 32, 235, 251, 47, 68, 47, 142, 52, 47, 100, 168, 102, 9, 162, 101, 175,
100, 190, 57, 71, 128, 202, 242, 8, 223, 37, 6, 26, 109
]
);

let other_token_contract = Address::from([123; 20]);

// a connection can't be created for the same chain id and bridge contract
assert!(ethereum
.create_connection(chain_id, bridge_contract, other_token_contract, valset)
.is_err());

Ok(())
}

#[ignore]
#[tokio::test]
#[serial_test::serial]
Expand Down

0 comments on commit cccfcad

Please sign in to comment.