generated from PaulRBerg/hardhat-template
-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #125 from gnosisguild/hmza/evm_caller
Aggregator Publishing to Smart contract
- Loading branch information
Showing
11 changed files
with
285 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
use actix::prelude::*; | ||
use alloy::primitives::{Address, Bytes, U256}; | ||
use std::collections::HashMap; | ||
use std::sync::Arc; | ||
|
||
use crate::{ | ||
events::EnclaveEvent, | ||
evm_contracts::EVMContract, | ||
sortition::{GetNodes, Sortition}, | ||
EventBus, | ||
}; | ||
pub struct EvmCaller { | ||
contracts: HashMap<String, Arc<EVMContract>>, | ||
bus: Addr<EventBus>, | ||
sortition: Addr<Sortition>, | ||
} | ||
|
||
impl Actor for EvmCaller { | ||
type Context = Context<Self>; | ||
} | ||
|
||
impl EvmCaller { | ||
pub fn new( | ||
bus: Addr<EventBus>, | ||
sortition: Addr<Sortition>, | ||
) -> Self { | ||
Self { | ||
contracts: HashMap::new(), | ||
bus, | ||
sortition, | ||
} | ||
} | ||
|
||
pub fn add_contract(&mut self, name: &str, contract: Arc<EVMContract>) { | ||
self.contracts.insert(name.to_string(), contract); | ||
} | ||
|
||
pub fn attach( | ||
bus: Addr<EventBus>, | ||
sortition: Addr<Sortition>, | ||
) -> Addr<Self> { | ||
let addr = Self::new(bus.clone(), sortition).start(); | ||
|
||
bus.do_send(crate::Subscribe::new( | ||
"PublicKeyAggregated", | ||
addr.clone().recipient(), | ||
)); | ||
|
||
bus.do_send(crate::Subscribe::new( | ||
"PlaintextAggregated", | ||
addr.clone().recipient(), | ||
)); | ||
|
||
addr | ||
} | ||
} | ||
|
||
#[derive(Message)] | ||
#[rtype(result = "()")] | ||
pub struct AddContract { | ||
pub name: String, | ||
pub contract: Arc<EVMContract>, | ||
} | ||
|
||
impl Handler<AddContract> for EvmCaller { | ||
type Result = (); | ||
|
||
fn handle(&mut self, msg: AddContract, _: &mut Self::Context) -> Self::Result { | ||
self.add_contract(&msg.name, msg.contract); | ||
} | ||
} | ||
|
||
impl Handler<EnclaveEvent> for EvmCaller { | ||
type Result = ResponseActFuture<Self, ()>; | ||
|
||
fn handle(&mut self, msg: EnclaveEvent, _ctx: &mut Self::Context) -> Self::Result { | ||
let contracts = self.contracts.clone(); | ||
let sortition = self.sortition.clone(); | ||
|
||
Box::pin( | ||
async move { | ||
match msg { | ||
EnclaveEvent::PublicKeyAggregated { data, .. } => { | ||
if let Some(contract) = contracts.get("registry") { | ||
let nodes = sortition.send(GetNodes).await.unwrap_or_default(); | ||
let nodes: Vec<Address> = nodes | ||
.into_iter() | ||
.filter_map(|node| node.parse().ok()) | ||
.collect(); | ||
|
||
match contract | ||
.publish_committee( | ||
U256::from_str_radix(&data.e3_id.0, 10).unwrap(), | ||
nodes, | ||
Bytes::from(data.pubkey), | ||
) | ||
.await | ||
{ | ||
Ok(tx) => println!("Published committee public key {:?}", tx.transaction_hash), | ||
Err(e) => eprintln!("Failed to publish committee public key: {:?}", e), | ||
} | ||
} | ||
} | ||
EnclaveEvent::PlaintextAggregated { data, .. } => { | ||
if let Some(contract) = contracts.get("enclave") { | ||
println!("Publishing plaintext output {:?}", data.e3_id); | ||
match contract | ||
.publish_plaintext_output( | ||
U256::from_str_radix(&data.e3_id.0, 10).unwrap(), | ||
Bytes::from(data.decrypted_output), | ||
Bytes::from(vec![1]), // TODO: Implement proof generation | ||
) | ||
.await | ||
{ | ||
Ok(tx) => println!("Published plaintext output {:?}", tx.transaction_hash), | ||
Err(e) => eprintln!("Failed to publish plaintext: {:?}", e), | ||
} | ||
} | ||
} | ||
_ => {} | ||
} | ||
} | ||
.into_actor(self) | ||
.map(|_, _, _| ()), | ||
) | ||
} | ||
} | ||
|
||
|
||
pub async fn connect_evm_caller( | ||
bus: Addr<EventBus>, | ||
sortition: Addr<Sortition>, | ||
rpc_url: &str, | ||
enclave_contract: Address, | ||
registry_contract: Address, | ||
) -> Result<Addr<EvmCaller>, anyhow::Error> { | ||
let evm_caller = EvmCaller::attach(bus.clone(), sortition.clone()); | ||
|
||
let enclave_instance = EVMContract::new(rpc_url, enclave_contract).await?; | ||
let registry_instance = EVMContract::new(rpc_url, registry_contract).await?; | ||
|
||
evm_caller.send(AddContract { | ||
name: "enclave".to_string(), | ||
contract: Arc::new(enclave_instance), | ||
}).await?; | ||
|
||
evm_caller.send(AddContract { | ||
name: "registry".to_string(), | ||
contract: Arc::new(registry_instance), | ||
}).await?; | ||
|
||
Ok(evm_caller) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
use alloy::{ | ||
network::{Ethereum, EthereumWallet}, | ||
primitives::{Address, Bytes, U256}, | ||
providers::{ | ||
fillers::{ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller, WalletFiller}, | ||
Identity, ProviderBuilder, RootProvider, | ||
}, | ||
rpc::types::TransactionReceipt, | ||
signers::local::PrivateKeySigner, | ||
sol, | ||
transports::BoxTransport, | ||
}; | ||
use anyhow::Result; | ||
use std::env; | ||
use std::sync::Arc; | ||
|
||
sol! { | ||
#[derive(Debug)] | ||
#[sol(rpc)] | ||
contract Enclave { | ||
function publishPlaintextOutput(uint256 e3Id, bytes memory plaintextOutput, bytes memory proof) external returns (bool success); | ||
} | ||
|
||
#[derive(Debug)] | ||
#[sol(rpc)] | ||
contract RegistryFilter { | ||
function publishCommittee(uint256 e3Id, address[] memory nodes, bytes memory publicKey) external onlyOwner; | ||
} | ||
} | ||
|
||
type ContractProvider = FillProvider< | ||
JoinFill< | ||
JoinFill<JoinFill<JoinFill<Identity, GasFiller>, NonceFiller>, ChainIdFiller>, | ||
WalletFiller<EthereumWallet>, | ||
>, | ||
RootProvider<BoxTransport>, | ||
BoxTransport, | ||
Ethereum, | ||
>; | ||
|
||
pub struct EVMContract { | ||
pub provider: Arc<ContractProvider>, | ||
pub contract_address: Address, | ||
} | ||
|
||
impl EVMContract { | ||
pub async fn new(rpc_url: &str, contract_address: Address) -> Result<Self> { | ||
let signer: PrivateKeySigner = env::var("PRIVATE_KEY")?.parse()?; | ||
let wallet = EthereumWallet::from(signer.clone()); | ||
let provider = ProviderBuilder::new() | ||
.with_recommended_fillers() | ||
.wallet(wallet) | ||
.on_builtin(rpc_url) | ||
.await?; | ||
|
||
Ok(Self { | ||
provider: Arc::new(provider), | ||
contract_address: contract_address, | ||
}) | ||
} | ||
|
||
pub async fn publish_plaintext_output( | ||
&self, | ||
e3_id: U256, | ||
plaintext_output: Bytes, | ||
proof: Bytes, | ||
) -> Result<TransactionReceipt> { | ||
let contract = Enclave::new(self.contract_address, &self.provider); | ||
let builder = contract.publishPlaintextOutput(e3_id, plaintext_output, proof); | ||
let receipt = builder.send().await?.get_receipt().await?; | ||
Ok(receipt) | ||
} | ||
|
||
pub async fn publish_committee( | ||
&self, | ||
e3_id: U256, | ||
nodes: Vec<Address>, | ||
public_key: Bytes, | ||
) -> Result<TransactionReceipt> { | ||
let contract = RegistryFilter::new(self.contract_address, &self.provider); | ||
let builder = contract.publishCommittee(e3_id, nodes, public_key); | ||
let receipt = builder.send().await?.get_receipt().await?; | ||
Ok(receipt) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.