feature: implement replica trait on replica contract abigen

buddies-main-deployment
James Prestwich 4 years ago
parent 8fb2db9269
commit fd838e0b0c
No known key found for this signature in database
GPG Key ID: 75A7F5C06D747046
  1. 2308
      rust/Cargo.lock
  2. 6
      rust/Cargo.toml
  3. 2
      rust/optics-base/Cargo.toml
  4. 11
      rust/optics-base/config/default.toml
  5. 52
      rust/optics-base/src/abis/ProcessingReplica.abi.json
  6. 156
      rust/optics-base/src/abis/mod.rs
  7. 15
      rust/optics-base/src/main.rs
  8. 99
      rust/optics-base/src/settings.rs
  9. 2
      rust/optics-core/src/accumulator/merkle.rs

2308
rust/Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -0,0 +1,6 @@
[workspace]
members = [
"optics-core",
"optics-base"
]

@ -7,7 +7,7 @@ edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.0.1", features = ["rt"] }
tokio = { version = "1.0.1", features = ["rt", "macros"] }
optics-core = { path = "../optics-core" }
config = "0.10"
serde = "1.0.120"

@ -1,10 +1,13 @@
[home]
chain = "Ethereum"
http = "http://localhost:8545"
slip44 = 52752
address = "0x0000000000000000000000000000000000000000"
chain = "Ethereum"
connection = { type = "Http", url = "http://localhost:8545" }
[replicas]
[replicas.Celo]
chain = "Ethereum"
slip44 = 60
address = "0x0000000000000000000000000000000000000000"
ws = "wss://"
chain = "Ethereum"
connection = { type = "Ws", url = "wss://" }

@ -137,6 +137,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "confirmAt",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "current",
@ -178,6 +191,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "lastProcessed",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
@ -236,6 +262,32 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "pending",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "previous",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{

@ -4,16 +4,162 @@ use ethers_core::types::{Address, H256, U256};
use std::sync::Arc;
use optics_core::{
traits::{ChainCommunicationError, Common, Home, State, TxOutcome},
Message, SignedUpdate, Update,
traits::{ChainCommunicationError, Common, Home, Replica, State, TxOutcome},
Encode, Message, SignedUpdate, Update,
};
abigen!(
ReplicaContractInternal,
"src/abis/ProcessingReplica.abi.json"
"optics-base/src/abis/ProcessingReplica.abi.json"
);
abigen!(HomeContractInternal, "src/abis/Home.abi.json");
#[derive(Debug)]
pub struct ReplicaContract<M>
where
M: ethers_providers::Middleware,
{
contract: ReplicaContractInternal<M>,
slip44: u32,
}
#[async_trait]
impl<M> Common for ReplicaContract<M>
where
M: ethers_providers::Middleware + 'static,
{
async fn status(&self, txid: H256) -> Result<Option<TxOutcome>, ChainCommunicationError> {
let receipt_opt = self
.contract
.client()
.get_transaction_receipt(txid)
.await
.map_err(|e| ChainCommunicationError::CustomError(Box::new(e)))?;
Ok(receipt_opt.map(Into::into))
}
fn origin_slip44(&self) -> u32 {
self.slip44
}
async fn updater(&self) -> Result<H256, ChainCommunicationError> {
Ok(self.contract.updater().call().await?.into())
}
async fn state(&self) -> Result<State, ChainCommunicationError> {
let state = self.contract.state().call().await?;
match state {
0 => Ok(State::Waiting),
1 => Ok(State::Failed),
_ => unreachable!(),
}
}
async fn current_root(&self) -> Result<H256, ChainCommunicationError> {
Ok(self.contract.current().call().await?.into())
}
async fn update(&self, update: &SignedUpdate) -> Result<TxOutcome, ChainCommunicationError> {
Ok(self
.contract
.update(
update.update.previous_root.to_fixed_bytes(),
update.update.new_root.to_fixed_bytes(),
update.signature.to_vec(),
)
.send()
.await?
.await?
.into())
}
async fn double_update(
&self,
left: &SignedUpdate,
right: &SignedUpdate,
) -> Result<TxOutcome, ChainCommunicationError> {
Ok(self
.contract
.double_update(
[
left.update.previous_root.to_fixed_bytes(),
right.update.previous_root.to_fixed_bytes(),
],
[
left.update.new_root.to_fixed_bytes(),
right.update.new_root.to_fixed_bytes(),
],
left.signature.to_vec(),
right.signature.to_vec(),
)
.send()
.await?
.await?
.into())
}
}
#[async_trait]
impl<M> Replica for ReplicaContract<M>
where
M: ethers_providers::Middleware + 'static,
{
async fn pending(&self) -> Result<Option<(H256, U256)>, ChainCommunicationError> {
let pending = self.contract.pending();
let confirm_at = self.contract.confirm_at();
let (pending, confirm_at) = tokio::join!(pending.call(), confirm_at.call());
let pending = pending?;
let confirm_at = confirm_at?;
if confirm_at.is_zero() {
Ok(None)
} else {
Ok(Some((pending.into(), confirm_at)))
}
}
async fn confirm(&self) -> Result<TxOutcome, ChainCommunicationError> {
Ok(self.contract.confirm().send().await?.await?.into())
}
async fn previous_root(&self) -> Result<H256, ChainCommunicationError> {
Ok(self.contract.previous().call().await?.into())
}
async fn prove(
&self,
leaf: H256,
index: u32,
proof: [H256; 32],
) -> Result<TxOutcome, ChainCommunicationError> {
let mut sol_proof: [[u8; 32]; 32] = Default::default();
sol_proof
.iter_mut()
.enumerate()
.for_each(|(i, elem)| *elem = proof[i].to_fixed_bytes());
Ok(self
.contract
.prove(leaf.into(), sol_proof, index.into())
.send()
.await?
.await?
.into())
}
async fn process(&self, message: &Message) -> Result<TxOutcome, ChainCommunicationError> {
Ok(self
.contract
.process(message.to_vec())
.send()
.await?
.await?
.into())
}
}
abigen!(HomeContractInternal, "optics-base/src/abis/Home.abi.json");
#[derive(Debug)]
pub struct HomeContract<M>
@ -131,7 +277,7 @@ where
.query()
.await?;
Ok(filters.into_iter().next().map(|f| f.message.clone()))
Ok(filters.into_iter().next().map(|f| f.message))
}
async fn sequences(&self, destination: u32) -> Result<u32, ChainCommunicationError> {

@ -1,10 +1,6 @@
mod abis;
mod settings;
use ethers_providers::{Http, Provider};
// use std::collections::HashMap;
use std::{convert::TryFrom, sync::Arc};
use optics_core::traits::{Home, Replica};
#[derive(Debug)]
@ -16,17 +12,8 @@ struct App {
async fn _main(settings: settings::Settings) {
println!("{:?}", &settings);
let home = {
let provider = Arc::new(Provider::<Http>::try_from(settings.home().url()).expect("!url"));
Box::new(abis::HomeContract::at(
0,
settings.home().address().into(),
provider,
))
};
let app = App {
home,
home: settings.home.try_into_home().await.expect("!home"),
replicas: vec![],
};
println!("{:?}", &app);

@ -1,61 +1,72 @@
use config::{Config, ConfigError, Environment, File};
use std::{collections::HashMap, env};
use std::{collections::HashMap, convert::TryFrom, env};
use ethers_core::types::{Address, H256};
use ethers_core::types::Address;
use ethers_providers::{Http, Provider, Ws};
use optics_core::traits::Home;
#[derive(Debug, serde::Deserialize)]
#[serde(untagged)]
pub(crate) enum Ethereum {
Http { address: Address, http: String },
Ws { address: Address, ws: String },
#[serde(tag = "type")]
pub(crate) enum EthereumConf {
Http { url: String },
Ws { url: String },
}
impl Ethereum {
pub fn url(&self) -> &str {
match self {
Self::Http { address: _, http } => &http,
Self::Ws { address: _, ws } => &ws,
}
}
pub fn address(&self) -> Address {
match self {
Self::Http { address, http: _ } => *address,
Self::Ws { address, ws: _ } => *address,
}
impl EthereumConf {
async fn try_home(&self, slip44: u32, address: Address) -> Result<Box<dyn Home>, String> {
let b: Box<dyn Home> = match self {
Self::Http { url } => {
let provider = Provider::<Http>::try_from(url.as_ref()).map_err(|_| "!url")?;
Box::new(crate::abis::HomeContract::at(
slip44,
address,
provider.into(),
))
}
Self::Ws { url } => {
let ws = Ws::connect(url).await.map_err(|_| "!ws connect")?;
let provider = Provider::new(ws);
Box::new(crate::abis::HomeContract::at(
slip44,
address,
provider.into(),
))
}
};
Ok(b)
}
}
#[derive(Debug, serde::Deserialize)]
#[serde(tag = "chain")]
pub(crate) enum Home {
Ethereum(Ethereum),
#[serde(tag = "chain", content = "connection")]
pub(crate) enum ChainConnection {
Ethereum(EthereumConf),
}
impl Home {
pub fn url(&self) -> &str {
match self {
Self::Ethereum(e) => e.url(),
}
}
#[derive(Debug, serde::Deserialize)]
pub(crate) struct ChainSetup {
slip44: u32,
address: String,
#[serde(flatten)]
connection: ChainConnection,
}
pub fn address(&self) -> H256 {
match self {
Self::Ethereum(e) => e.address().into(),
impl ChainSetup {
pub async fn try_into_home(&self) -> Result<Box<dyn Home>, String> {
match &self.connection {
ChainConnection::Ethereum(conf) => {
conf.try_home(self.slip44, self.address.parse().map_err(|_| "!address")?)
.await
}
}
}
}
#[derive(Debug, serde::Deserialize)]
#[serde(tag = "chain")]
pub(crate) enum Replica {
Ethereum(Ethereum),
}
#[derive(Debug, serde::Deserialize)]
pub(crate) struct Settings {
home: Home,
replicas: HashMap<String, Replica>,
pub(crate) home: ChainSetup,
pub(crate) replicas: HashMap<String, ChainSetup>,
}
impl Settings {
@ -74,13 +85,3 @@ impl Settings {
s.try_into()
}
}
impl Settings {
pub fn home(&self) -> &Home {
&self.home
}
pub fn replicas(&self) -> &HashMap<String, Replica> {
&self.replicas
}
}

@ -400,7 +400,7 @@ mod tests {
#[test]
fn big_test() {
let leaves: Vec<_> = (0..64).map(|i| H256::from_low_u64_be(i)).collect();
let leaves: Vec<_> = (0..64).map(H256::from_low_u64_be).collect();
let mut tree = MerkleTree::create(&[], 32);
leaves.iter().for_each(|leaf| {

Loading…
Cancel
Save