Skip to content

Commit

Permalink
feat: Signer accepts address or file path for init
Browse files Browse the repository at this point in the history
  • Loading branch information
sifnoc committed Nov 2, 2023
1 parent fda1e0b commit e1df685
Show file tree
Hide file tree
Showing 8 changed files with 127 additions and 42 deletions.
9 changes: 7 additions & 2 deletions backend/examples/summa_solvency_flow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use summa_backend::{
address_ownership::AddressOwnership,
round::{MstInclusionProof, Round},
},
contracts::signer::AddressInput,
tests::initialize_test_env,
};
use summa_solvency::merkle_sum_tree::utils::generate_leaf_hash;
Expand All @@ -25,11 +26,15 @@ async fn main() -> Result<(), Box<dyn Error>> {
//
// Each CEX prepares its own `signature` CSV file.
let signature_csv_path = "src/apis/csv/signatures.csv";

// Using AddressInput::Address to directly provide the summa_contract's address.
// For deployed contracts, if the address is stored in a config file,
// you can alternatively use AddressInput::Path to specify the file's path.
let mut address_ownership_client = AddressOwnership::new(
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
anvil.chain_id(),
anvil.endpoint().as_str(),
summa_contract.address(),
AddressInput::Address(summa_contract.address()),
signature_csv_path,
)
.unwrap();
Expand All @@ -54,7 +59,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", // anvil account [0]
anvil.chain_id(),
anvil.endpoint().as_str(),
summa_contract.address(),
AddressInput::Address(summa_contract.address()),
entry_csv,
asset_csv,
params_path,
Expand Down
5 changes: 5 additions & 0 deletions backend/scripts/update_verifier_contracts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,15 @@ echo "2. Deploying contracts to local environment"
cd ../contracts
npm install
npx hardhat node &
HARDHAT_PID=$!
sleep 5
npx hardhat run scripts/deploy.ts --network localhost

# Generate interface files for Backend
echo "3. Generating interface files for Backend"
cd ../backend
cargo build

# Wrap up
echo "Terminate hardhat node"
kill $HARDHAT_PID
10 changes: 6 additions & 4 deletions backend/src/apis/address_ownership.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use crate::contracts::{generated::summa_contract::AddressOwnershipProof, signer::SummaSigner};
use ethers::types::Address;
use crate::contracts::{
generated::summa_contract::AddressOwnershipProof,
signer::{AddressInput, SummaSigner},
};
use std::{error::Error, result::Result};

use super::csv_parser::parse_signature_csv;
Expand All @@ -14,14 +16,14 @@ impl AddressOwnership {
signer_key: &str,
chain_id: u64,
rpc_url: &str,
summa_sc_address: Address,
summa_address_input: AddressInput,
signature_csv_path: &str,
) -> Result<AddressOwnership, Box<dyn Error>> {
let address_ownership_proofs = parse_signature_csv(signature_csv_path)?;

Ok(AddressOwnership {
address_ownership_proofs,
signer: SummaSigner::new(signer_key, chain_id, rpc_url, summa_sc_address),
signer: SummaSigner::new(signer_key, chain_id, rpc_url, summa_address_input),
})
}

Expand Down
14 changes: 7 additions & 7 deletions backend/src/apis/round.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use ethers::{
abi::Address,
types::{Bytes, U256},
};
use ethers::types::{Bytes, U256};
use halo2_proofs::{
halo2curves::bn256::{Bn256, Fr as Fp, G1Affine},
plonk::{ProvingKey, VerifyingKey},
Expand All @@ -11,7 +8,10 @@ use serde::{Deserialize, Serialize};
use std::error::Error;

use super::csv_parser::parse_asset_csv;
use crate::contracts::{generated::summa_contract::summa::Asset, signer::SummaSigner};
use crate::contracts::{
generated::summa_contract::summa::Asset,
signer::{AddressInput, SummaSigner},
};
use summa_solvency::{
circuits::{
merkle_sum_tree::MstInclusionCircuit,
Expand Down Expand Up @@ -81,7 +81,7 @@ where
signer_key: &str,
chain_id: u64,
rpc_url: &str,
summa_sc_address: Address,
summa_address_input: AddressInput,
entry_csv_path: &str,
asset_csv_path: &str,
params_path: &str,
Expand All @@ -95,7 +95,7 @@ where
params_path,
)
.unwrap(),
signer: SummaSigner::new(signer_key, chain_id, rpc_url, summa_sc_address),
signer: SummaSigner::new(signer_key, chain_id, rpc_url, summa_address_input),
})
}

Expand Down
2 changes: 1 addition & 1 deletion backend/src/contracts/deployments.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"31337":{"address":"0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"}}
{"31337":{"address":"0xdc64a140aa3e981100a9beca4e685f962f0cf6c9"}}
2 changes: 1 addition & 1 deletion backend/src/contracts/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod generated;
pub mod mock;
pub(crate) mod signer;
pub mod signer;
57 changes: 53 additions & 4 deletions backend/src/contracts/signer.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
use crate::contracts::generated::summa_contract::Summa;
use ethers::{
prelude::SignerMiddleware,
providers::{Http, Provider},
signers::{LocalWallet, Signer},
types::Address,
};
use std::{str::FromStr, sync::Arc, time::Duration};
use serde_json::Value;
use std::{
error::Error, fs::File, io::BufReader, path::Path, str::FromStr, sync::Arc, time::Duration,
};

use super::generated::summa_contract::{AddressOwnershipProof, Asset};
use crate::contracts::generated::summa_contract::Summa;

pub enum AddressInput {
Address(Address),
Path(String),
}

#[derive(Debug)]
pub struct SummaSigner {
Expand All @@ -20,8 +28,13 @@ impl SummaSigner {
/// * `signer_key` - The private key of wallet that will interact with the chain on behalf of the exchange
/// * `chain_id` - The chain id of the network
/// * `rpc_url` - The RPC URL of the network
/// * `address` - The address of the Summa contract
pub fn new(signer_key: &str, chain_id: u64, rpc_url: &str, address: Address) -> Self {
/// * `address_input` - Either the contract's direct address or a path to its config file.
pub fn new(
signer_key: &str,
chain_id: u64,
rpc_url: &str,
address_input: AddressInput,
) -> Self {
let wallet: LocalWallet = LocalWallet::from_str(signer_key).unwrap();

let provider = Provider::<Http>::try_from(rpc_url)
Expand All @@ -32,12 +45,48 @@ impl SummaSigner {
wallet.with_chain_id(chain_id),
));

let address = match address_input {
AddressInput::Address(address) => address,
AddressInput::Path(path) => {
let address = Self::get_deployment_address(path, chain_id).unwrap();
address
}
};

let contract = Summa::new(address, client);
Self {
summa_contract: contract,
}
}

pub fn get_summa_address(&self) -> Address {
self.summa_contract.address()
}

fn get_deployment_address<P: AsRef<Path>>(
path: P,
chain_id: u64,
) -> Result<Address, Box<dyn Error>> {
// Open file in RO mode with buffer
let file = File::open(path)?;
let reader = BufReader::new(file);

// Read the JSON contents of the file
let payload: Value = serde_json::from_reader(reader)?;

// Retrieve the contract address from the deployments.json file
let deployment_address: &Value = &payload.as_object().unwrap()
[chain_id.to_string().as_str()]
.as_object()
.unwrap()["address"];

let summa_address: &str = deployment_address.as_str().unwrap();

let address: Address = summa_address.parse().unwrap();

Ok(address)
}

pub async fn submit_proof_of_address_ownership(
&self,
address_ownership_proofs: Vec<AddressOwnershipProof>,
Expand Down
70 changes: 47 additions & 23 deletions backend/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,36 @@ mod test {
use std::error::Error;

use crate::apis::{address_ownership::AddressOwnership, round::Round};
use crate::contracts::generated::summa_contract::{
AddressOwnershipProof, AddressOwnershipProofSubmittedFilter, Asset,
SolvencyProofSubmittedFilter,
use crate::contracts::{
generated::summa_contract::{
AddressOwnershipProof, AddressOwnershipProofSubmittedFilter, Asset,
SolvencyProofSubmittedFilter,
},
signer::{AddressInput, SummaSigner},
};
use crate::tests::initialize_test_env;

#[tokio::test]
async fn test_deployed_address() -> Result<(), Box<dyn Error>> {
let (anvil, _, _, _, summa_contract) = initialize_test_env().await;

// Hardhat development environment, usually updates the address of a deployed contract in the `artifacts` directory.
// However, in our custom deployment script, `contracts/scripts/deploy.ts`,
// the address gets updated in `backend/src/contracts/deployments.json`.
let contract_address = summa_contract.address();

let summa_signer = SummaSigner::new(
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
anvil.chain_id(),
anvil.endpoint().as_str(),
AddressInput::Path("./src/contracts/deployments.json".into()), // the file contains the address of the deployed contract
);

assert_eq!(contract_address, summa_signer.get_summa_address());

Ok(())
}

#[tokio::test]
async fn test_round_features() -> Result<(), Box<dyn Error>> {
let (anvil, cex_addr_1, cex_addr_2, _, summa_contract) = initialize_test_env().await;
Expand All @@ -120,7 +144,7 @@ mod test {
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80",
anvil.chain_id(),
anvil.endpoint().as_str(),
summa_contract.address(),
AddressInput::Address(summa_contract.address()),
"src/apis/csv/signatures.csv",
)
.unwrap();
Expand All @@ -136,24 +160,24 @@ mod test {

assert_eq!(ownership_proof_logs.len(), 1);
assert_eq!(
ownership_proof_logs[0],
AddressOwnershipProofSubmittedFilter {
address_ownership_proofs: vec![AddressOwnershipProof {
chain: "ETH".to_string(),
cex_address: to_checksum(&cex_addr_1, None),
signature:
("0x089b32327d332c295dc3b8873c205b72153211de6dc1c51235782b091cefb9d06d6df2661b86a7d441cd322f125b84901486b150e684221a7b7636eb8182af551b").parse().unwrap(),
message: "Summa proof of solvency for CryptoExchange".encode().into(),
},AddressOwnershipProof {
chain: "ETH".to_string(),
cex_address:to_checksum(&cex_addr_2, None),
signature:
("0xb17a9e25265d3b88de7bfad81e7accad6e3d5612308ff83cc0fef76a34152b0444309e8fc3dea5139e49b6fc83a8553071a7af3d0cfd3fb8c1aea2a4c171729c1c").parse().unwrap(),
message: "Summa proof of solvency for CryptoExchange".encode().into(),
},
],
}
);
ownership_proof_logs[0],
AddressOwnershipProofSubmittedFilter {
address_ownership_proofs: vec![AddressOwnershipProof {
chain: "ETH".to_string(),
cex_address: to_checksum(&cex_addr_1, None),
signature:
("0x089b32327d332c295dc3b8873c205b72153211de6dc1c51235782b091cefb9d06d6df2661b86a7d441cd322f125b84901486b150e684221a7b7636eb8182af551b").parse().unwrap(),
message: "Summa proof of solvency for CryptoExchange".encode().into(),
},AddressOwnershipProof {
chain: "ETH".to_string(),
cex_address:to_checksum(&cex_addr_2, None),
signature:
("0xb17a9e25265d3b88de7bfad81e7accad6e3d5612308ff83cc0fef76a34152b0444309e8fc3dea5139e49b6fc83a8553071a7af3d0cfd3fb8c1aea2a4c171729c1c").parse().unwrap(),
message: "Summa proof of solvency for CryptoExchange".encode().into(),
},
],
}
);

// Initialize round
let asset_csv = "src/apis/csv/assets.csv";
Expand All @@ -164,7 +188,7 @@ mod test {
"0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", // anvil account [0]
anvil.chain_id(),
anvil.endpoint().as_str(),
summa_contract.address(),
AddressInput::Address(summa_contract.address()),
entry_csv,
asset_csv,
params_path,
Expand Down

0 comments on commit e1df685

Please sign in to comment.