mirror of
https://github.com/vacp2p/status-rln-prover.git
synced 2026-01-08 05:03:54 -05:00
Add initial rln sc register in registry_listener (#33)
* Add initial rln sc register in registry_listener * Generic over alloy provider * Fix prover mock startup * Update handle_transfer_event documentation
This commit is contained in:
@@ -11,7 +11,7 @@ PRIVATE_KEY=__MY_PRIVATE_KEY__ RUST_LOG=debug cargo run -p prover_cli -- --no-co
|
||||
|
||||
### Run prover + Mock
|
||||
|
||||
RUST_LOG=debug cargo run -p prover_cli -- --ip 127.0.0.1 --metrics-ip 127.0.0.1 --mock-sc true --mock-user mock/mock_user_1.json
|
||||
RUST_LOG=debug cargo run -p prover_cli -- --ip 127.0.0.1 --metrics-ip 127.0.0.1 --mock-sc true --mock-user mock/mock_user_1.json --no-config
|
||||
|
||||
### Run prover + opentelemetry
|
||||
|
||||
@@ -23,9 +23,9 @@ RUST_LOG=debug cargo run -p prover_cli -- --ip 127.0.0.1 --metrics-ip 127.0.0.1
|
||||
### Run prover client (for tests)
|
||||
|
||||
* RUST_LOG=debug cargo run -p prover_client -- --help
|
||||
* RUST_LOG=debug cargo run -p prover_client -- -i 127.0.0.1 -p 42942 register-user
|
||||
* RUST_LOG=debug cargo run -p prover_client -- -i 127.0.0.1 -p 42942 send-transaction --tx-hash aa
|
||||
* RUST_LOG=debug cargo run -p prover_client -- -i 127.0.0.1 -p 42942 -a 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 get-user-tier-info
|
||||
* RUST_LOG=debug cargo run -p prover_client -- -i 127.0.0.1 -p 50051 register-user
|
||||
* RUST_LOG=debug cargo run -p prover_client -- -i 127.0.0.1 -p 50051 send-transaction --tx-hash aa
|
||||
* RUST_LOG=debug cargo run -p prover_client -- -i 127.0.0.1 -p 50051 -a 0xd8da6bf26964af9d7eed9e03e53415d37aa96045 get-user-tier-info
|
||||
|
||||
## Debug
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ option java_multiple_files = true;
|
||||
service RlnProver {
|
||||
|
||||
rpc SendTransaction (SendTransactionRequest) returns (SendTransactionReply);
|
||||
rpc RegisterUser (RegisterUserRequest) returns (RegisterUserReply);
|
||||
// rpc RegisterUser (RegisterUserRequest) returns (RegisterUserReply);
|
||||
// Server side streaming RPC: 1 request -> X responses (stream)
|
||||
rpc GetProofs(RlnProofFilter) returns (stream RlnProofReply);
|
||||
|
||||
@@ -171,6 +171,7 @@ message RlnProofError {
|
||||
string error = 2;
|
||||
}
|
||||
|
||||
/*
|
||||
message RegisterUserRequest {
|
||||
Address user = 14;
|
||||
}
|
||||
@@ -184,6 +185,7 @@ enum RegistrationStatus {
|
||||
message RegisterUserReply {
|
||||
RegistrationStatus status = 1;
|
||||
}
|
||||
*/
|
||||
|
||||
message GetUserTierInfoRequest {
|
||||
Address user = 1;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
use criterion::Criterion;
|
||||
use criterion::{BenchmarkId, Throughput};
|
||||
use criterion::{criterion_group, criterion_main};
|
||||
use std::io::Write;
|
||||
|
||||
// std
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
@@ -11,11 +12,12 @@ use std::time::Duration;
|
||||
use alloy::primitives::{Address, U256};
|
||||
use futures::FutureExt;
|
||||
use parking_lot::RwLock;
|
||||
use tempfile::NamedTempFile;
|
||||
use tokio::sync::Notify;
|
||||
use tokio::task::JoinSet;
|
||||
use tonic::Response;
|
||||
// internal
|
||||
use prover::{AppArgs, run_prover};
|
||||
use prover::{AppArgs, MockUser, run_prover};
|
||||
|
||||
// grpc
|
||||
pub mod prover_proto {
|
||||
@@ -23,38 +25,17 @@ pub mod prover_proto {
|
||||
tonic::include_proto!("prover");
|
||||
}
|
||||
use prover_proto::{
|
||||
Address as GrpcAddress, RegisterUserReply, RegisterUserRequest, RegistrationStatus,
|
||||
RlnProofFilter, RlnProofReply, SendTransactionReply, SendTransactionRequest, U256 as GrpcU256,
|
||||
Wei as GrpcWei, rln_prover_client::RlnProverClient,
|
||||
Address as GrpcAddress, RlnProofFilter, RlnProofReply, SendTransactionReply,
|
||||
SendTransactionRequest, U256 as GrpcU256, Wei as GrpcWei, rln_prover_client::RlnProverClient,
|
||||
};
|
||||
|
||||
async fn register_users(port: u16, addresses: Vec<Address>) {
|
||||
let url = format!("http://127.0.0.1:{}", port);
|
||||
let mut client = RlnProverClient::connect(url).await.unwrap();
|
||||
|
||||
for address in addresses {
|
||||
let addr = GrpcAddress {
|
||||
value: address.to_vec(),
|
||||
};
|
||||
|
||||
let request_0 = RegisterUserRequest { user: Some(addr) };
|
||||
let request = tonic::Request::new(request_0);
|
||||
let response: Response<RegisterUserReply> = client.register_user(request).await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
RegistrationStatus::try_from(response.into_inner().status).unwrap(),
|
||||
RegistrationStatus::Success
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
async fn proof_sender(port: u16, addresses: Vec<Address>, proof_count: usize) {
|
||||
let chain_id = GrpcU256 {
|
||||
// FIXME: LE or BE?
|
||||
value: U256::from(1).to_le_bytes::<32>().to_vec(),
|
||||
};
|
||||
|
||||
let url = format!("http://127.0.0.1:{}", port);
|
||||
let url = format!("http://127.0.0.1:{port}");
|
||||
let mut client = RlnProverClient::connect(url).await.unwrap();
|
||||
|
||||
let addr = GrpcAddress {
|
||||
@@ -85,7 +66,7 @@ async fn proof_sender(port: u16, addresses: Vec<Address>, proof_count: usize) {
|
||||
async fn proof_collector(port: u16, proof_count: usize) -> Vec<RlnProofReply> {
|
||||
let result = Arc::new(RwLock::new(vec![]));
|
||||
|
||||
let url = format!("http://127.0.0.1:{}", port);
|
||||
let url = format!("http://127.0.0.1:{port}");
|
||||
let mut client = RlnProverClient::connect(url).await.unwrap();
|
||||
|
||||
let request_0 = RlnProofFilter { address: None };
|
||||
@@ -107,7 +88,6 @@ async fn proof_collector(port: u16, proof_count: usize) -> Vec<RlnProofReply> {
|
||||
}
|
||||
|
||||
fn proof_generation_bench(c: &mut Criterion) {
|
||||
let start = std::time::Instant::now();
|
||||
let rayon_num_threads = std::env::var("RAYON_NUM_THREADS").unwrap_or("".to_string());
|
||||
let proof_service_count_default = 4;
|
||||
let proof_service_count = std::env::var("PROOF_SERVICE_COUNT")
|
||||
@@ -123,6 +103,24 @@ fn proof_generation_bench(c: &mut Criterion) {
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
// Write mock users to tempfile
|
||||
let mock_users = vec![
|
||||
MockUser {
|
||||
address: Address::from_str("0xd8da6bf26964af9d7eed9e03e53415d37aa96045").unwrap(),
|
||||
tx_count: 0,
|
||||
},
|
||||
MockUser {
|
||||
address: Address::from_str("0xb20a608c624Ca5003905aA834De7156C68b2E1d0").unwrap(),
|
||||
tx_count: 0,
|
||||
},
|
||||
];
|
||||
let addresses: Vec<Address> = mock_users.iter().map(|u| u.address).collect();
|
||||
let mock_users_as_str = serde_json::to_string(&mock_users).unwrap();
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
let temp_file_path = temp_file.path().to_path_buf();
|
||||
temp_file.write_all(mock_users_as_str.as_bytes()).unwrap();
|
||||
temp_file.flush().unwrap();
|
||||
|
||||
let port = 50051;
|
||||
let temp_folder = tempfile::tempdir().unwrap();
|
||||
let temp_folder_tree = tempfile::tempdir().unwrap();
|
||||
@@ -137,9 +135,9 @@ fn proof_generation_bench(c: &mut Criterion) {
|
||||
rlnsc_address: None,
|
||||
tsc_address: None,
|
||||
mock_sc: Some(true),
|
||||
mock_user: None,
|
||||
mock_user: Some(temp_file_path),
|
||||
config_path: Default::default(),
|
||||
no_config: Some(true),
|
||||
no_config: true,
|
||||
metrics_ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
|
||||
metrics_port: 30051,
|
||||
broadcast_channel_size: 100,
|
||||
@@ -148,10 +146,6 @@ fn proof_generation_bench(c: &mut Criterion) {
|
||||
proof_sender_channel_size: 100,
|
||||
};
|
||||
|
||||
let addresses = vec![
|
||||
Address::from_str("0xd8da6bf26964af9d7eed9e03e53415d37aa96045").unwrap(),
|
||||
Address::from_str("0xb20a608c624Ca5003905aA834De7156C68b2E1d0").unwrap(),
|
||||
];
|
||||
// Tokio notify - wait for some time after spawning run_prover then notify it's ready to accept
|
||||
// connections
|
||||
let notify_start = Arc::new(Notify::new());
|
||||
@@ -166,13 +160,12 @@ fn proof_generation_bench(c: &mut Criterion) {
|
||||
});
|
||||
|
||||
let notify_start_2 = notify_start.clone();
|
||||
let addresses_0 = addresses.clone();
|
||||
|
||||
// Wait for proof_collector to be connected and waiting for some proofs
|
||||
rt.block_on(async move {
|
||||
notify_start_2.notified().await;
|
||||
println!("Prover is ready, registering users...");
|
||||
register_users(port, addresses_0).await;
|
||||
println!("Prover is ready...");
|
||||
// register_users(port, addresses_0).await;
|
||||
});
|
||||
|
||||
println!("Starting benchmark...");
|
||||
@@ -185,6 +178,7 @@ fn proof_generation_bench(c: &mut Criterion) {
|
||||
let proof_count = proof_count as usize;
|
||||
|
||||
group.throughput(Throughput::Elements(proof_count as u64));
|
||||
#[allow(clippy::uninlined_format_args)]
|
||||
let benchmark_name = format!(
|
||||
"prover_proof_{}_proof_service_{}_rt_{}",
|
||||
proof_count, proof_service_count, rayon_num_threads
|
||||
@@ -208,14 +202,13 @@ fn proof_generation_bench(c: &mut Criterion) {
|
||||
);
|
||||
|
||||
group.finish();
|
||||
println!("Benchmark finished in {:?}", start.elapsed());
|
||||
}
|
||||
|
||||
criterion_group!(
|
||||
name = benches;
|
||||
config = Criterion::default()
|
||||
.sample_size(10)
|
||||
.measurement_time(Duration::from_secs(150))
|
||||
.measurement_time(Duration::from_secs(500))
|
||||
;
|
||||
targets = proof_generation_bench
|
||||
);
|
||||
|
||||
@@ -2,7 +2,6 @@ use std::net::IpAddr;
|
||||
use std::path::PathBuf;
|
||||
// third-party
|
||||
use alloy::primitives::Address;
|
||||
use clap::ArgAction::SetTrue;
|
||||
use clap::Parser;
|
||||
use clap_config::ClapConfig;
|
||||
use url::Url;
|
||||
@@ -44,7 +43,6 @@ pub struct AppArgs {
|
||||
#[arg(
|
||||
short = 'u',
|
||||
long = "ws-rpc-url",
|
||||
default_value = "wss://public.sepolia.rpc.status.network/ws",
|
||||
help = "Websocket rpc url (e.g. wss://eth-mainnet.g.alchemy.com/v2/your-api-key)"
|
||||
)]
|
||||
pub ws_rpc_url: Option<Url>,
|
||||
@@ -102,11 +100,11 @@ pub struct AppArgs {
|
||||
#[arg(
|
||||
long = "no-config",
|
||||
help = "Dont read a config file",
|
||||
default_missing_value = "true",
|
||||
action = SetTrue,
|
||||
help_heading = "config"
|
||||
required = false,
|
||||
action,
|
||||
help_heading = "Do not try to read config file"
|
||||
)]
|
||||
pub no_config: Option<bool>,
|
||||
pub no_config: bool,
|
||||
#[arg(
|
||||
long = "metrics-ip",
|
||||
default_value = "::1",
|
||||
|
||||
@@ -72,10 +72,17 @@ pub enum GetMerkleTreeProofError {
|
||||
MerkleTree(#[from] UserMerkleTreeIndexError),
|
||||
}
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
#[error(transparent)]
|
||||
pub struct RegisterSCError(#[from] alloy::contract::Error);
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum HandleTransferError {
|
||||
#[error(transparent)]
|
||||
Register(#[from] RegisterError),
|
||||
|
||||
#[error("Fail to register user in RLN SC: {0}")]
|
||||
ScRegister(#[from] RegisterSCError),
|
||||
#[error("Unable to query balance: {0}")]
|
||||
FetchBalanceOf(#[from] alloy::contract::Error),
|
||||
}
|
||||
|
||||
@@ -5,42 +5,33 @@ use std::net::SocketAddr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
// third-party
|
||||
use alloy::primitives::{Address, U256};
|
||||
use alloy::{primitives::Address, providers::Provider};
|
||||
use async_channel::Sender;
|
||||
use bytesize::ByteSize;
|
||||
use futures::TryFutureExt;
|
||||
use http::Method;
|
||||
use metrics::{counter, histogram};
|
||||
use num_bigint::BigUint;
|
||||
use smart_contract::RlnScError;
|
||||
use tokio::sync::{broadcast, mpsc};
|
||||
use tonic::{
|
||||
Request, Response, Status, codegen::tokio_stream::wrappers::ReceiverStream, transport::Server,
|
||||
};
|
||||
use tonic_web::GrpcWebLayer;
|
||||
use tower_http::cors::{Any, CorsLayer};
|
||||
use tracing::{debug, error};
|
||||
use tracing::{
|
||||
debug,
|
||||
// error
|
||||
};
|
||||
use url::Url;
|
||||
use zeroize::Zeroizing;
|
||||
// internal
|
||||
use crate::error::{AppError, ProofGenerationStringError};
|
||||
use crate::metrics::{
|
||||
GET_PROOFS_LISTENERS, GET_USER_TIER_INFO_REQUESTS, GaugeWrapper,
|
||||
PROOF_SERVICES_CHANNEL_QUEUE_LEN, SEND_TRANSACTION_REQUESTS, USER_REGISTERED,
|
||||
USER_REGISTERED_REQUESTS,
|
||||
PROOF_SERVICES_CHANNEL_QUEUE_LEN, SEND_TRANSACTION_REQUESTS,
|
||||
};
|
||||
use crate::proof_generation::{ProofGenerationData, ProofSendingData};
|
||||
use crate::user_db::{UserDb, UserTierInfo};
|
||||
use crate::user_db_error::RegisterError;
|
||||
use rln_proof::RlnIdentifier;
|
||||
use smart_contract::{
|
||||
KarmaAmountExt,
|
||||
KarmaRLNSC::KarmaRLNSCInstance,
|
||||
KarmaSC::KarmaSCInstance,
|
||||
MockKarmaRLNSc,
|
||||
MockKarmaSc,
|
||||
RLNRegister, // traits
|
||||
};
|
||||
use smart_contract::{KarmaAmountExt, KarmaSC::KarmaSCInstance, MockKarmaSc};
|
||||
|
||||
pub mod prover_proto {
|
||||
|
||||
@@ -53,9 +44,9 @@ pub mod prover_proto {
|
||||
use prover_proto::{
|
||||
GetUserTierInfoReply,
|
||||
GetUserTierInfoRequest,
|
||||
RegisterUserReply,
|
||||
RegisterUserRequest,
|
||||
RegistrationStatus,
|
||||
// RegisterUserReply,
|
||||
// RegisterUserRequest,
|
||||
// RegistrationStatus,
|
||||
RlnProof,
|
||||
RlnProofFilter,
|
||||
RlnProofReply,
|
||||
@@ -85,7 +76,7 @@ const PROVER_SERVICE_MESSAGE_ENCODING_MAX_SIZE: ByteSize = ByteSize::mib(5);
|
||||
const PROVER_TX_HASH_BYTESIZE: usize = 32;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProverService<KSC: KarmaAmountExt, RLNSC: RLNRegister> {
|
||||
pub struct ProverService<KSC: KarmaAmountExt> {
|
||||
proof_sender: Sender<ProofGenerationData>,
|
||||
user_db: UserDb,
|
||||
rln_identifier: Arc<RlnIdentifier>,
|
||||
@@ -94,17 +85,15 @@ pub struct ProverService<KSC: KarmaAmountExt, RLNSC: RLNRegister> {
|
||||
broadcast::Receiver<Result<ProofSendingData, ProofGenerationStringError>>,
|
||||
),
|
||||
karma_sc: KSC,
|
||||
karma_rln_sc: RLNSC,
|
||||
// karma_rln_sc: RLNSC,
|
||||
proof_sender_channel_size: usize,
|
||||
}
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl<KSC, RLNSC> RlnProver for ProverService<KSC, RLNSC>
|
||||
impl<KSC> RlnProver for ProverService<KSC>
|
||||
where
|
||||
KSC: KarmaAmountExt + Send + Sync + 'static,
|
||||
KSC::Error: std::error::Error + Send + Sync + 'static,
|
||||
RLNSC: RLNRegister + Send + Sync + 'static,
|
||||
RLNSC::Error: std::error::Error + Send + Sync + 'static,
|
||||
{
|
||||
#[tracing::instrument(skip(self), err, ret)]
|
||||
async fn send_transaction(
|
||||
@@ -166,6 +155,7 @@ where
|
||||
Ok(Response::new(reply))
|
||||
}
|
||||
|
||||
/*
|
||||
#[tracing::instrument(skip(self), err, ret)]
|
||||
async fn register_user(
|
||||
&self,
|
||||
@@ -215,6 +205,7 @@ where
|
||||
counter!(USER_REGISTERED.name, "prover" => "grpc").increment(1);
|
||||
Ok(Response::new(reply))
|
||||
}
|
||||
*/
|
||||
|
||||
type GetProofsStream = ReceiverStream<Result<RlnProofReply, Status>>;
|
||||
|
||||
@@ -292,7 +283,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct GrpcProverService {
|
||||
pub(crate) struct GrpcProverService<P: Provider> {
|
||||
pub proof_sender: Sender<ProofGenerationData>,
|
||||
pub broadcast_channel: (
|
||||
broadcast::Sender<Result<ProofSendingData, ProofGenerationStringError>>,
|
||||
@@ -302,31 +293,20 @@ pub(crate) struct GrpcProverService {
|
||||
pub rln_identifier: RlnIdentifier,
|
||||
pub user_db: UserDb,
|
||||
pub karma_sc_info: Option<(Url, Address)>,
|
||||
pub rln_sc_info: Option<(Url, Address)>,
|
||||
// pub rln_sc_info: Option<(Url, Address)>,
|
||||
pub provider: Option<P>,
|
||||
pub proof_sender_channel_size: usize,
|
||||
}
|
||||
|
||||
impl GrpcProverService {
|
||||
impl<P: Provider + Clone + Send + Sync + 'static> GrpcProverService<P> {
|
||||
pub(crate) async fn serve(&self) -> Result<(), AppError> {
|
||||
let karma_sc = if let Some(karma_sc_info) = self.karma_sc_info.as_ref() {
|
||||
KarmaSCInstance::try_new(karma_sc_info.0.clone(), karma_sc_info.1).await?
|
||||
let karma_sc = if let Some(karma_sc_info) = self.karma_sc_info.as_ref()
|
||||
&& let Some(provider) = self.provider.as_ref()
|
||||
{
|
||||
KarmaSCInstance::new(karma_sc_info.1, provider.clone())
|
||||
} else {
|
||||
panic!("Please provide karma_sc_info or use serve_with_mock");
|
||||
};
|
||||
let karma_rln_sc = if let Some(rln_sc_info) = self.rln_sc_info.as_ref() {
|
||||
let private_key = Zeroizing::new(std::env::var("PRIVATE_KEY").map_err(|_| {
|
||||
error!("PRIVATE_KEY environment variable is not set");
|
||||
AppError::RlnScError(RlnScError::EmptyPrivateKey)
|
||||
})?);
|
||||
KarmaRLNSCInstance::try_new_with_signer(
|
||||
rln_sc_info.0.clone(),
|
||||
rln_sc_info.1,
|
||||
private_key,
|
||||
)
|
||||
.await?
|
||||
} else {
|
||||
panic!("Please provide rln_sc_info or use serve_with_mock");
|
||||
};
|
||||
|
||||
let prover_service = ProverService {
|
||||
proof_sender: self.proof_sender.clone(),
|
||||
@@ -337,7 +317,6 @@ impl GrpcProverService {
|
||||
self.broadcast_channel.0.subscribe(),
|
||||
),
|
||||
karma_sc,
|
||||
karma_rln_sc,
|
||||
proof_sender_channel_size: self.proof_sender_channel_size,
|
||||
};
|
||||
|
||||
@@ -399,7 +378,7 @@ impl GrpcProverService {
|
||||
self.broadcast_channel.0.subscribe(),
|
||||
),
|
||||
karma_sc: MockKarmaSc {},
|
||||
karma_rln_sc: MockKarmaRLNSc {},
|
||||
// karma_rln_sc: MockKarmaRLNSc {},
|
||||
proof_sender_channel_size: self.proof_sender_channel_size,
|
||||
};
|
||||
|
||||
|
||||
@@ -22,10 +22,14 @@ mod proof_service_tests;
|
||||
mod user_db_tests;
|
||||
|
||||
// std
|
||||
use alloy::network::EthereumWallet;
|
||||
use std::net::SocketAddr;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
// third-party
|
||||
use alloy::primitives::U256;
|
||||
use alloy::providers::{ProviderBuilder, WsConnect};
|
||||
use alloy::signers::local::PrivateKeySigner;
|
||||
use chrono::{DateTime, Utc};
|
||||
use tokio::task::JoinSet;
|
||||
use tracing::{
|
||||
@@ -33,10 +37,12 @@ use tracing::{
|
||||
// error,
|
||||
// info
|
||||
};
|
||||
use zeroize::Zeroizing;
|
||||
// internal
|
||||
pub use crate::args::{AppArgs, AppArgsConfig};
|
||||
use crate::epoch_service::EpochService;
|
||||
use crate::grpc_service::GrpcProverService;
|
||||
pub use crate::mock::MockUser;
|
||||
use crate::mock::read_mock_user;
|
||||
use crate::proof_service::ProofService;
|
||||
use crate::registry_listener::RegistryListener;
|
||||
@@ -47,7 +53,7 @@ use crate::user_db_service::UserDbService;
|
||||
use crate::user_db_types::RateLimit;
|
||||
use rln_proof::RlnIdentifier;
|
||||
use smart_contract::KarmaTiers::KarmaTiersInstance;
|
||||
use smart_contract::TIER_LIMITS;
|
||||
use smart_contract::{KarmaTiersError, TIER_LIMITS};
|
||||
|
||||
const RLN_IDENTIFIER_NAME: &[u8] = b"test-rln-identifier";
|
||||
const PROVER_SPAM_LIMIT: RateLimit = RateLimit::new(10_000u64);
|
||||
@@ -62,11 +68,43 @@ pub async fn run_prover(
|
||||
let epoch_service = EpochService::try_from((Duration::from_secs(60 * 2), GENESIS))
|
||||
.expect("Failed to create epoch service");
|
||||
|
||||
// Alloy provider (Smart contract provider)
|
||||
let provider = if app_args.ws_rpc_url.is_some() {
|
||||
let ws = WsConnect::new(app_args.ws_rpc_url.clone().unwrap().as_str());
|
||||
let provider = ProviderBuilder::new()
|
||||
.connect_ws(ws)
|
||||
.await
|
||||
.map_err(KarmaTiersError::RpcTransportError)?;
|
||||
Some(provider)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Alloy provider + signer
|
||||
let provider_with_signer = if app_args.ws_rpc_url.is_some() {
|
||||
let pk: Zeroizing<String> =
|
||||
Zeroizing::new(std::env::var("PRIVATE_KEY").expect("Please provide a private key"));
|
||||
let pk_signer = PrivateKeySigner::from_str(pk.as_str())?;
|
||||
let wallet = EthereumWallet::from(pk_signer);
|
||||
|
||||
let ws = WsConnect::new(app_args.ws_rpc_url.clone().unwrap().as_str());
|
||||
let provider = ProviderBuilder::new()
|
||||
.wallet(wallet)
|
||||
.connect_ws(ws)
|
||||
.await
|
||||
.map_err(KarmaTiersError::RpcTransportError)?;
|
||||
Some(provider)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
let tier_limits = if app_args.ws_rpc_url.is_some() {
|
||||
TierLimits::from(
|
||||
KarmaTiersInstance::get_tiers(
|
||||
app_args.ws_rpc_url.clone().unwrap(),
|
||||
app_args.tsc_address.unwrap(),
|
||||
KarmaTiersInstance::get_tiers_from_provider(
|
||||
&provider.clone().unwrap(),
|
||||
&app_args.tsc_address.unwrap(),
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
@@ -92,7 +130,8 @@ pub async fn run_prover(
|
||||
if app_args.mock_sc.is_some()
|
||||
&& let Some(user_filepath) = app_args.mock_user.as_ref()
|
||||
{
|
||||
let mock_users = read_mock_user(user_filepath)?;
|
||||
let mock_users = read_mock_user(user_filepath);
|
||||
let mock_users = mock_users.unwrap();
|
||||
debug!("Mock - will register {} users", mock_users.len());
|
||||
for mock_user in mock_users {
|
||||
debug!(
|
||||
@@ -116,12 +155,14 @@ pub async fn run_prover(
|
||||
}
|
||||
|
||||
// Smart contract
|
||||
// FIXME: use provider
|
||||
let registry_listener = if app_args.mock_sc.is_some() {
|
||||
// debug!("No registry listener when mock is enabled");
|
||||
None
|
||||
} else {
|
||||
Some(RegistryListener::new(
|
||||
app_args.ws_rpc_url.clone().unwrap().as_str(),
|
||||
app_args.ksc_address.unwrap(),
|
||||
app_args.rlnsc_address.unwrap(),
|
||||
user_db_service.get_user_db(),
|
||||
PROVER_MINIMAL_AMOUNT_FOR_REGISTRATION,
|
||||
))
|
||||
@@ -131,7 +172,6 @@ pub async fn run_prover(
|
||||
None
|
||||
} else {
|
||||
Some(TiersListener::new(
|
||||
app_args.ws_rpc_url.clone().unwrap().as_str(),
|
||||
app_args.tsc_address.unwrap(),
|
||||
user_db_service.get_user_db(),
|
||||
))
|
||||
@@ -154,14 +194,13 @@ pub async fn run_prover(
|
||||
rln_identifier,
|
||||
user_db: user_db_service.get_user_db(),
|
||||
karma_sc_info: None,
|
||||
rln_sc_info: None,
|
||||
provider: provider.clone(),
|
||||
proof_sender_channel_size: app_args.proof_sender_channel_size,
|
||||
};
|
||||
|
||||
if app_args.ws_rpc_url.is_some() {
|
||||
let ws_rpc_url = app_args.ws_rpc_url.clone().unwrap();
|
||||
service.karma_sc_info = Some((ws_rpc_url.clone(), app_args.ksc_address.unwrap()));
|
||||
service.rln_sc_info = Some((ws_rpc_url, app_args.rlnsc_address.unwrap()));
|
||||
}
|
||||
service
|
||||
};
|
||||
@@ -187,10 +226,16 @@ pub async fn run_prover(
|
||||
}
|
||||
|
||||
if let Some(registry_listener) = registry_listener {
|
||||
set.spawn(async move { registry_listener.listen().await });
|
||||
let p = provider.clone().unwrap();
|
||||
set.spawn(async move {
|
||||
registry_listener
|
||||
.listen(p, provider_with_signer.unwrap())
|
||||
.await
|
||||
});
|
||||
}
|
||||
if let Some(tiers_listener) = tiers_listener {
|
||||
set.spawn(async move { tiers_listener.listen().await });
|
||||
let p = provider.clone().unwrap();
|
||||
set.spawn(async move { tiers_listener.listen(p).await });
|
||||
}
|
||||
set.spawn(async move { epoch_service.listen_for_new_epoch().await });
|
||||
set.spawn(async move { user_db_service.listen_for_epoch_changes().await });
|
||||
|
||||
@@ -218,8 +218,8 @@ mod tests {
|
||||
debug!("Now recovering secret hash...");
|
||||
let proof_values_0 = proof_values_store.first().unwrap();
|
||||
let proof_values_1 = proof_values_store.get(1).unwrap();
|
||||
println!("proof_values_0: {:?}", proof_values_0);
|
||||
println!("proof_values_1: {:?}", proof_values_1);
|
||||
println!("proof_values_0: {proof_values_0:?}");
|
||||
println!("proof_values_1: {proof_values_1:?}");
|
||||
let share1 = (proof_values_0.x, proof_values_0.y);
|
||||
let share2 = (proof_values_1.x, proof_values_1.y);
|
||||
|
||||
|
||||
@@ -2,54 +2,56 @@
|
||||
use alloy::{
|
||||
contract::Error as AlloyContractError,
|
||||
primitives::{Address, U256},
|
||||
providers::{Provider, ProviderBuilder, WsConnect},
|
||||
providers::Provider,
|
||||
sol_types::SolEvent,
|
||||
transports::{RpcError, TransportError},
|
||||
};
|
||||
use num_bigint::BigUint;
|
||||
use tonic::codegen::tokio_stream::StreamExt;
|
||||
use tracing::{debug, error, info};
|
||||
// internal
|
||||
use crate::error::{AppError, HandleTransferError};
|
||||
use crate::error::{AppError, HandleTransferError, RegisterSCError};
|
||||
use crate::user_db::UserDb;
|
||||
use crate::user_db_error::RegisterError;
|
||||
use smart_contract::{AlloyWsProvider, KarmaAmountExt, KarmaSC};
|
||||
use smart_contract::{KarmaAmountExt, KarmaRLNSC, KarmaSC, RLNRegister};
|
||||
|
||||
pub(crate) struct RegistryListener {
|
||||
rpc_url: String,
|
||||
sc_address: Address,
|
||||
karma_sc_address: Address,
|
||||
rln_sc_address: Address,
|
||||
user_db: UserDb,
|
||||
minimal_amount: U256,
|
||||
}
|
||||
|
||||
impl RegistryListener {
|
||||
pub(crate) fn new(
|
||||
rpc_url: &str,
|
||||
sc_address: Address,
|
||||
karma_sc_address: Address,
|
||||
rln_sc_address: Address,
|
||||
user_db: UserDb,
|
||||
minimal_amount: U256,
|
||||
) -> Self {
|
||||
Self {
|
||||
rpc_url: rpc_url.to_string(),
|
||||
sc_address,
|
||||
karma_sc_address,
|
||||
rln_sc_address,
|
||||
user_db,
|
||||
minimal_amount,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a provider (aka connect to websocket url)
|
||||
async fn setup_provider_ws(&self) -> Result<AlloyWsProvider, RpcError<TransportError>> {
|
||||
let ws = WsConnect::new(self.rpc_url.as_str());
|
||||
let provider = ProviderBuilder::new().connect_ws(ws).await?;
|
||||
Ok(provider)
|
||||
}
|
||||
|
||||
/// Listen to Smart Contract specified events
|
||||
pub(crate) async fn listen(&self) -> Result<(), AppError> {
|
||||
let provider = self.setup_provider_ws().await.map_err(AppError::from)?;
|
||||
let karma_sc = KarmaSC::new(self.sc_address, provider.clone());
|
||||
pub(crate) async fn listen<P: Provider + Clone, PS: Provider>(
|
||||
&self,
|
||||
provider: P,
|
||||
provider_with_signer: PS,
|
||||
) -> Result<(), AppError> {
|
||||
// let provider = self.setup_provider_ws().await.map_err(AppError::from)?;
|
||||
let karma_sc = KarmaSC::new(self.karma_sc_address, provider.clone());
|
||||
|
||||
// let provider_with_signer = self.setup_provider_with_signer(self.private_key.clone())
|
||||
// .await
|
||||
// .map_err(AppError::from)?;
|
||||
let rln_sc = KarmaRLNSC::new(self.rln_sc_address, provider_with_signer);
|
||||
|
||||
let filter = alloy::rpc::types::Filter::new()
|
||||
.address(self.sc_address)
|
||||
.address(self.karma_sc_address)
|
||||
.event(KarmaSC::Transfer::SIGNATURE);
|
||||
|
||||
// Subscribe to logs matching the filter.
|
||||
@@ -60,7 +62,10 @@ impl RegistryListener {
|
||||
while let Some(log) = stream.next().await {
|
||||
match KarmaSC::Transfer::decode_log_data(log.data()) {
|
||||
Ok(transfer_event) => {
|
||||
match self.handle_transfer_event(&karma_sc, transfer_event).await {
|
||||
match self
|
||||
.handle_transfer_event(&karma_sc, &rln_sc, transfer_event)
|
||||
.await
|
||||
{
|
||||
Ok(addr) => {
|
||||
info!("Registered new user: {}", addr);
|
||||
}
|
||||
@@ -93,10 +98,22 @@ impl RegistryListener {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// async fn handle_transfer_event(&self, karma_sc: &KarmaSCInstance<AlloyWsProvider>, transfer_event: KarmaSC::Transfer) -> Result<(), HandleTransferError> {
|
||||
async fn handle_transfer_event<E: Into<AlloyContractError>, KSC: KarmaAmountExt<Error = E>>(
|
||||
/// Handle transfer event from Karma smart contract
|
||||
///
|
||||
/// Handle 'Transfer' event but filter on Transfer event from a _mint call.
|
||||
/// As we can see here: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/53bb34057ed97ea9b36d550f1c2c413ef5b6c6bb/contracts/token/ERC20/ERC20.sol#L214
|
||||
/// _mint function emits a Transfer event (with from_adress set to 0x0). UserDb (on disk) is updated
|
||||
/// as well as RLN Smart contract.
|
||||
/// Can panic if RLN Smart contract registration fails, and UserDb remove fails too (but this should
|
||||
/// never happen)
|
||||
async fn handle_transfer_event<
|
||||
E: Into<AlloyContractError>,
|
||||
KSC: KarmaAmountExt<Error = E>,
|
||||
RLNSC: RLNRegister<Error = E>,
|
||||
>(
|
||||
&self,
|
||||
karma_sc: &KSC,
|
||||
rln_sc: &RLNSC,
|
||||
transfer_event: KarmaSC::Transfer,
|
||||
) -> Result<Address, HandleTransferError> {
|
||||
let from_address: Address = transfer_event.from;
|
||||
@@ -119,9 +136,25 @@ impl RegistryListener {
|
||||
};
|
||||
|
||||
if should_register {
|
||||
self.user_db
|
||||
let id_commitment = self
|
||||
.user_db
|
||||
.on_new_user(&to_address)
|
||||
.map_err(HandleTransferError::Register)?;
|
||||
|
||||
let id_co =
|
||||
U256::from_le_slice(BigUint::from(id_commitment).to_bytes_le().as_slice());
|
||||
|
||||
if let Err(e) = rln_sc.register_user(&to_address, id_co).await {
|
||||
// Fail to register user on smart contract
|
||||
// Remove the user in internal Db
|
||||
if !self.user_db.remove_user(&to_address, false) {
|
||||
// Fails if DB & SC are inconsistent
|
||||
panic!("Unable to register user to SC and to remove it from DB...");
|
||||
}
|
||||
|
||||
let e_ = RegisterSCError::from(e.into());
|
||||
return Err(HandleTransferError::ScRegister(e_));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,6 +178,9 @@ mod tests {
|
||||
|
||||
// const ADDR_1: Address = address!("0xd8da6bf26964af9d7eed9e03e53415d37aa96045");
|
||||
const ADDR_2: Address = address!("0xb20a608c624Ca5003905aA834De7156C68b2E1d0");
|
||||
|
||||
// Mock Karma Sc
|
||||
|
||||
struct MockKarmaSc {}
|
||||
|
||||
#[async_trait]
|
||||
@@ -155,6 +191,23 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
// Mock RLN Sc
|
||||
struct MockRLNSc {}
|
||||
|
||||
#[async_trait]
|
||||
impl RLNRegister for MockRLNSc {
|
||||
type Error = AlloyContractError;
|
||||
|
||||
async fn register_user(
|
||||
&self,
|
||||
_address: &Address,
|
||||
_identity_commitment: U256,
|
||||
) -> Result<(), Self::Error> {
|
||||
// println!("Registering user: {} with identity commitment: {}...", address, identity_commitment);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_handle_transfer_event() {
|
||||
let epoch = Epoch::from(11);
|
||||
@@ -177,8 +230,8 @@ mod tests {
|
||||
|
||||
let minimal_amount = U256::from(25);
|
||||
let registry = RegistryListener {
|
||||
rpc_url: "".to_string(),
|
||||
sc_address: Default::default(),
|
||||
rln_sc_address: Default::default(),
|
||||
karma_sc_address: Default::default(),
|
||||
user_db,
|
||||
minimal_amount: U256::from(25),
|
||||
};
|
||||
@@ -190,8 +243,9 @@ mod tests {
|
||||
};
|
||||
|
||||
let karma_sc = MockKarmaSc {};
|
||||
let rln_sc = MockRLNSc {};
|
||||
registry
|
||||
.handle_transfer_event(&karma_sc, transfer)
|
||||
.handle_transfer_event(&karma_sc, &rln_sc, transfer)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
@@ -355,7 +355,7 @@ mod tests {
|
||||
if let TierMatch::Matched(tier) = result {
|
||||
assert_eq!(tier.name, "Basic");
|
||||
} else {
|
||||
panic!("Expected TierMatch::Matched, got {:?}", result);
|
||||
panic!("Expected TierMatch::Matched, got {result:?}");
|
||||
}
|
||||
|
||||
// Case 4: Exact match on a tier boundary (start of second tier)
|
||||
@@ -363,7 +363,7 @@ mod tests {
|
||||
if let TierMatch::Matched(tier) = result {
|
||||
assert_eq!(tier.name, "Active");
|
||||
} else {
|
||||
panic!("Expected TierMatch::Matched, got {:?}", result);
|
||||
panic!("Expected TierMatch::Matched, got {result:?}");
|
||||
}
|
||||
|
||||
// Case 5: Karma within a tier range (between third tier)
|
||||
@@ -371,7 +371,7 @@ mod tests {
|
||||
if let TierMatch::Matched(tier) = result {
|
||||
assert_eq!(tier.name, "Regular");
|
||||
} else {
|
||||
panic!("Expected TierMatch, got {:?}", result);
|
||||
panic!("Expected TierMatch, got {result:?}");
|
||||
}
|
||||
|
||||
// Case 6: Exact match on max_karma (end of the third tier)
|
||||
@@ -379,7 +379,7 @@ mod tests {
|
||||
if let TierMatch::Matched(tier) = result {
|
||||
assert_eq!(tier.name, "Regular");
|
||||
} else {
|
||||
panic!("Expected TierMatch, got {:?}", result);
|
||||
panic!("Expected TierMatch, got {result:?}");
|
||||
}
|
||||
|
||||
// Case 7: Karma above all tiers
|
||||
|
||||
@@ -1,44 +1,30 @@
|
||||
// third-party
|
||||
use alloy::{
|
||||
primitives::Address,
|
||||
providers::{Provider, ProviderBuilder, WsConnect},
|
||||
sol_types::SolEvent,
|
||||
transports::{RpcError, TransportError},
|
||||
};
|
||||
use alloy::{primitives::Address, providers::Provider, sol_types::SolEvent};
|
||||
use futures::StreamExt;
|
||||
use tracing::error;
|
||||
// internal
|
||||
use crate::error::AppError;
|
||||
use crate::tier::TierLimits;
|
||||
use crate::user_db::UserDb;
|
||||
use smart_contract::KarmaTiers;
|
||||
use smart_contract::KarmaTiers::KarmaTiersInstance;
|
||||
use smart_contract::{AlloyWsProvider, KarmaTiers};
|
||||
|
||||
pub(crate) struct TiersListener {
|
||||
rpc_url: String,
|
||||
sc_address: Address,
|
||||
user_db: UserDb,
|
||||
}
|
||||
|
||||
impl TiersListener {
|
||||
pub(crate) fn new(rpc_url: &str, sc_address: Address, user_db: UserDb) -> Self {
|
||||
pub(crate) fn new(sc_address: Address, user_db: UserDb) -> Self {
|
||||
Self {
|
||||
rpc_url: rpc_url.to_string(),
|
||||
sc_address,
|
||||
user_db,
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a provider (aka connect to websocket url)
|
||||
async fn setup_provider_ws(&self) -> Result<AlloyWsProvider, RpcError<TransportError>> {
|
||||
let ws = WsConnect::new(self.rpc_url.as_str());
|
||||
let provider = ProviderBuilder::new().connect_ws(ws).await?;
|
||||
Ok(provider)
|
||||
}
|
||||
|
||||
/// Listen to Smart Contract specified events
|
||||
pub(crate) async fn listen(&self) -> Result<(), AppError> {
|
||||
let provider = self.setup_provider_ws().await.map_err(AppError::from)?;
|
||||
pub(crate) async fn listen<P: Provider + Clone>(&self, provider: P) -> Result<(), AppError> {
|
||||
// let provider = self.setup_provider_ws().await.map_err(AppError::from)?;
|
||||
|
||||
let filter = alloy::rpc::types::Filter::new()
|
||||
.address(self.sc_address)
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
use alloy::primitives::{Address, U256};
|
||||
use futures::FutureExt;
|
||||
use parking_lot::RwLock;
|
||||
use prover::{AppArgs, run_prover};
|
||||
use prover::{AppArgs, MockUser, run_prover};
|
||||
use std::io::Write;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use tempfile::NamedTempFile;
|
||||
use tokio::task;
|
||||
use tokio::task::JoinSet;
|
||||
use tonic::Response;
|
||||
use tracing::info;
|
||||
use tracing::{debug, info};
|
||||
use tracing_test::traced_test;
|
||||
|
||||
pub mod prover_proto {
|
||||
@@ -17,11 +19,12 @@ pub mod prover_proto {
|
||||
tonic::include_proto!("prover");
|
||||
}
|
||||
use crate::prover_proto::{
|
||||
Address as GrpcAddress, GetUserTierInfoReply, GetUserTierInfoRequest, RegisterUserReply,
|
||||
RegisterUserRequest, RegistrationStatus, RlnProofFilter, RlnProofReply, SendTransactionReply,
|
||||
SendTransactionRequest, U256 as GrpcU256, Wei as GrpcWei, rln_prover_client::RlnProverClient,
|
||||
Address as GrpcAddress, GetUserTierInfoReply, GetUserTierInfoRequest, RlnProofFilter,
|
||||
RlnProofReply, SendTransactionReply, SendTransactionRequest, U256 as GrpcU256, Wei as GrpcWei,
|
||||
rln_prover_client::RlnProverClient,
|
||||
};
|
||||
|
||||
/*
|
||||
async fn register_users(port: u16, addresses: Vec<Address>) {
|
||||
let url = format!("http://127.0.0.1:{}", port);
|
||||
let mut client = RlnProverClient::connect(url).await.unwrap();
|
||||
@@ -41,9 +44,10 @@ async fn register_users(port: u16, addresses: Vec<Address>) {
|
||||
);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
async fn query_user_info(port: u16, addresses: Vec<Address>) -> Vec<GetUserTierInfoReply> {
|
||||
let url = format!("http://127.0.0.1:{}", port);
|
||||
let url = format!("http://127.0.0.1:{port}");
|
||||
let mut client = RlnProverClient::connect(url).await.unwrap();
|
||||
|
||||
let mut result = vec![];
|
||||
@@ -62,6 +66,7 @@ async fn query_user_info(port: u16, addresses: Vec<Address>) -> Vec<GetUserTierI
|
||||
result
|
||||
}
|
||||
|
||||
/*
|
||||
#[tokio::test]
|
||||
#[traced_test]
|
||||
async fn test_grpc_register_users() {
|
||||
@@ -109,6 +114,7 @@ async fn test_grpc_register_users() {
|
||||
prover_handle.abort();
|
||||
tokio::time::sleep(Duration::from_secs(1)).await;
|
||||
}
|
||||
*/
|
||||
|
||||
async fn proof_sender(port: u16, addresses: Vec<Address>, proof_count: usize) {
|
||||
let start = std::time::Instant::now();
|
||||
@@ -118,7 +124,7 @@ async fn proof_sender(port: u16, addresses: Vec<Address>, proof_count: usize) {
|
||||
value: U256::from(1).to_le_bytes::<32>().to_vec(),
|
||||
};
|
||||
|
||||
let url = format!("http://127.0.0.1:{}", port);
|
||||
let url = format!("http://127.0.0.1:{port}");
|
||||
let mut client = RlnProverClient::connect(url).await.unwrap();
|
||||
|
||||
let addr = GrpcAddress {
|
||||
@@ -152,27 +158,13 @@ async fn proof_sender(port: u16, addresses: Vec<Address>, proof_count: usize) {
|
||||
count,
|
||||
start.elapsed().as_secs_f64()
|
||||
);
|
||||
|
||||
/*
|
||||
let tx_hash = U256::from(42).to_le_bytes::<32>().to_vec();
|
||||
let request_0 = SendTransactionRequest {
|
||||
gas_price: Some(wei),
|
||||
sender: Some(addr),
|
||||
chain_id: Some(chain_id),
|
||||
transaction_hash: tx_hash,
|
||||
};
|
||||
|
||||
let request = tonic::Request::new(request_0);
|
||||
let response: Response<SendTransactionReply> = client.send_transaction(request).await.unwrap();
|
||||
assert_eq!(response.into_inner().result, true);
|
||||
*/
|
||||
}
|
||||
|
||||
async fn proof_collector(port: u16, proof_count: usize) -> Vec<RlnProofReply> {
|
||||
let start = std::time::Instant::now();
|
||||
let result = Arc::new(RwLock::new(vec![]));
|
||||
|
||||
let url = format!("http://127.0.0.1:{}", port);
|
||||
let url = format!("http://127.0.0.1:{port}");
|
||||
let mut client = RlnProverClient::connect(url).await.unwrap();
|
||||
|
||||
let request_0 = RlnProofFilter { address: None };
|
||||
@@ -201,7 +193,7 @@ async fn proof_collector(port: u16, proof_count: usize) -> Vec<RlnProofReply> {
|
||||
};
|
||||
|
||||
let _res = tokio::time::timeout(Duration::from_secs(500), receiver).await;
|
||||
println!("_res: {:?}", _res);
|
||||
println!("_res: {_res:?}");
|
||||
let res = std::mem::take(&mut *result.write());
|
||||
println!(
|
||||
"[proof_collector] elapsed: {} secs",
|
||||
@@ -213,10 +205,29 @@ async fn proof_collector(port: u16, proof_count: usize) -> Vec<RlnProofReply> {
|
||||
#[tokio::test]
|
||||
#[traced_test]
|
||||
async fn test_grpc_gen_proof() {
|
||||
let addresses = vec![
|
||||
Address::from_str("0xd8da6bf26964af9d7eed9e03e53415d37aa96045").unwrap(),
|
||||
Address::from_str("0xb20a608c624Ca5003905aA834De7156C68b2E1d0").unwrap(),
|
||||
let mock_users = vec![
|
||||
MockUser {
|
||||
address: Address::from_str("0xd8da6bf26964af9d7eed9e03e53415d37aa96045").unwrap(),
|
||||
tx_count: 0,
|
||||
},
|
||||
MockUser {
|
||||
address: Address::from_str("0xb20a608c624Ca5003905aA834De7156C68b2E1d0").unwrap(),
|
||||
tx_count: 0,
|
||||
},
|
||||
];
|
||||
let addresses: Vec<Address> = mock_users.iter().map(|u| u.address).collect();
|
||||
|
||||
// Write mock users to tempfile
|
||||
let mock_users_as_str = serde_json::to_string(&mock_users).unwrap();
|
||||
let mut temp_file = NamedTempFile::new().unwrap();
|
||||
let temp_file_path = temp_file.path().to_path_buf();
|
||||
temp_file.write_all(mock_users_as_str.as_bytes()).unwrap();
|
||||
temp_file.flush().unwrap();
|
||||
debug!(
|
||||
"Mock user temp file path: {}",
|
||||
temp_file_path.to_str().unwrap()
|
||||
);
|
||||
//
|
||||
|
||||
let temp_folder = tempfile::tempdir().unwrap();
|
||||
let temp_folder_tree = tempfile::tempdir().unwrap();
|
||||
@@ -232,9 +243,9 @@ async fn test_grpc_gen_proof() {
|
||||
rlnsc_address: None,
|
||||
tsc_address: None,
|
||||
mock_sc: Some(true),
|
||||
mock_user: None,
|
||||
mock_user: Some(temp_file_path),
|
||||
config_path: Default::default(),
|
||||
no_config: Some(true),
|
||||
no_config: true,
|
||||
metrics_ip: IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)),
|
||||
metrics_port: 30031,
|
||||
broadcast_channel_size: 500,
|
||||
@@ -243,13 +254,16 @@ async fn test_grpc_gen_proof() {
|
||||
proof_sender_channel_size: 500,
|
||||
};
|
||||
|
||||
info!("Starting prover...");
|
||||
info!("Starting prover with args: {:?}", app_args);
|
||||
let prover_handle = task::spawn(run_prover(app_args));
|
||||
// Wait for the prover to be ready
|
||||
// Note: if unit test is failing - maybe add an optional notification when service is ready
|
||||
tokio::time::sleep(Duration::from_secs(5)).await;
|
||||
info!("Registering some users...");
|
||||
register_users(port, addresses.clone()).await;
|
||||
// info!("Registering some users...");
|
||||
// register_users(port, addresses.clone()).await;
|
||||
info!("Query info for these new users...");
|
||||
let res = query_user_info(port, addresses.clone()).await;
|
||||
assert_eq!(res.len(), addresses.len());
|
||||
|
||||
info!("Sending tx and collecting proofs...");
|
||||
let proof_count = 10;
|
||||
|
||||
@@ -9,17 +9,10 @@ pub mod prover_proto {
|
||||
tonic::include_proto!("prover");
|
||||
}
|
||||
|
||||
use crate::prover_proto::{GetUserTierInfoReply, GetUserTierInfoRequest, RegistrationStatus};
|
||||
use crate::prover_proto::{GetUserTierInfoReply, GetUserTierInfoRequest};
|
||||
use prover_proto::{
|
||||
Address as GrpcAddress,
|
||||
RegisterUserReply,
|
||||
RegisterUserRequest,
|
||||
SendTransactionReply,
|
||||
SendTransactionRequest,
|
||||
U256 as GrpcU256,
|
||||
Wei as GrpcWei,
|
||||
// RegistrationStatus,
|
||||
rln_prover_client::RlnProverClient,
|
||||
Address as GrpcAddress, SendTransactionReply, SendTransactionRequest, U256 as GrpcU256,
|
||||
Wei as GrpcWei, rln_prover_client::RlnProverClient,
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone, Parser)]
|
||||
@@ -47,8 +40,6 @@ pub struct AppArgs {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Subcommand)]
|
||||
pub(crate) enum Commands {
|
||||
#[command(about = "Register a new user")]
|
||||
RegisterUser, // (RegisterUserArgs),
|
||||
#[command(about = "Send a transaction")]
|
||||
SendTransaction(SendTransactionArgs),
|
||||
#[command(about = "Get user tier info")]
|
||||
@@ -83,19 +74,6 @@ async fn main() {
|
||||
};
|
||||
|
||||
match app_args.command {
|
||||
Commands::RegisterUser => {
|
||||
let request_0 = RegisterUserRequest {
|
||||
user: Some(grpc_addr),
|
||||
};
|
||||
let request = tonic::Request::new(request_0);
|
||||
let response: Response<RegisterUserReply> =
|
||||
client.register_user(request).await.unwrap();
|
||||
|
||||
println!(
|
||||
"RegisterUSerReply status: {:?}",
|
||||
RegistrationStatus::try_from(response.into_inner().status)
|
||||
);
|
||||
}
|
||||
Commands::SendTransaction(send_transaction_args) => {
|
||||
let chain_id = GrpcU256 {
|
||||
// FIXME: LE or BE?
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
use alloy::providers::{
|
||||
Identity, RootProvider,
|
||||
fillers::{BlobGasFiller, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller},
|
||||
};
|
||||
/*
|
||||
use alloy::network::{EthereumWallet};
|
||||
use alloy::providers::{Identity, RootProvider, fillers::{BlobGasFiller, ChainIdFiller, FillProvider, GasFiller, JoinFill, NonceFiller}, Provider, WsConnect, ProviderBuilder};
|
||||
use alloy::providers::fillers::WalletFiller;
|
||||
*/
|
||||
use alloy::providers::{Provider, ProviderBuilder, WsConnect};
|
||||
use alloy::transports::TransportError;
|
||||
|
||||
/*
|
||||
pub type AlloyWsProvider = FillProvider<
|
||||
JoinFill<
|
||||
Identity,
|
||||
@@ -10,3 +14,22 @@ pub type AlloyWsProvider = FillProvider<
|
||||
>,
|
||||
RootProvider,
|
||||
>;
|
||||
|
||||
pub type AlloyWsProviderWithSigner = FillProvider<
|
||||
JoinFill<
|
||||
JoinFill<
|
||||
Identity,
|
||||
JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>
|
||||
>,
|
||||
WalletFiller<EthereumWallet>
|
||||
>,
|
||||
RootProvider
|
||||
>;
|
||||
*/
|
||||
|
||||
#[allow(clippy::let_and_return)]
|
||||
pub async fn ws_provider(rpc_url: String) -> Result<impl Provider, TransportError> {
|
||||
let ws = WsConnect::new(rpc_url);
|
||||
let provider = ProviderBuilder::new().connect_ws(ws).await;
|
||||
provider
|
||||
}
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
// third-party
|
||||
use alloy::providers::Provider;
|
||||
use alloy::{
|
||||
primitives::{Address, U256},
|
||||
providers::{ProviderBuilder, WsConnect},
|
||||
providers::Provider,
|
||||
sol,
|
||||
transports::{RpcError, TransportErrorKind},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use url::Url;
|
||||
// internal
|
||||
use crate::AlloyWsProvider;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum KarmaScError {
|
||||
@@ -73,19 +69,8 @@ sol! {
|
||||
}
|
||||
}
|
||||
|
||||
impl KarmaSC::KarmaSCInstance<AlloyWsProvider> {
|
||||
pub async fn try_new(rpc_url: Url, address: Address) -> Result<Self, KarmaScError> {
|
||||
let ws = WsConnect::new(rpc_url.as_str());
|
||||
let provider = ProviderBuilder::new()
|
||||
.connect_ws(ws)
|
||||
.await
|
||||
.map_err(KarmaScError::RpcTransportError)?;
|
||||
Ok(KarmaSC::new(address, provider))
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T: Provider> KarmaAmountExt for KarmaSC::KarmaSCInstance<T> {
|
||||
impl<P: Provider> KarmaAmountExt for KarmaSC::KarmaSCInstance<P> {
|
||||
type Error = alloy::contract::Error;
|
||||
async fn karma_amount(&self, address: &Address) -> Result<U256, Self::Error> {
|
||||
self.balanceOf(*address).call().await
|
||||
@@ -97,9 +82,11 @@ impl<T: Provider> KarmaAmountExt for KarmaSC::KarmaSCInstance<T> {
|
||||
pub(crate) mod tests {
|
||||
use super::*;
|
||||
// third-party
|
||||
use alloy::primitives::U256;
|
||||
use alloy::primitives::address;
|
||||
use alloy::sol_types::SolCall;
|
||||
use alloy::{
|
||||
primitives::{U256, address},
|
||||
providers::ProviderBuilder,
|
||||
sol_types::SolCall,
|
||||
};
|
||||
use claims::assert_gt;
|
||||
|
||||
sol! {
|
||||
@@ -144,52 +131,6 @@ pub(crate) mod tests {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
#[tokio::test]
|
||||
async fn test_balance_of() {
|
||||
|
||||
let provider = ProviderBuilder::new()
|
||||
.connect_anvil_with_wallet()
|
||||
;
|
||||
|
||||
let contract_distributor = KarmaDistributorMock::deploy(&provider).await.unwrap();
|
||||
|
||||
// Deploy the KarmaTiers contract.
|
||||
let contract = KarmaSC::deploy(&provider).await.unwrap();
|
||||
// getTierCount call
|
||||
let addr = address!("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
|
||||
let call_1 = contract.balanceOf(addr);
|
||||
let result_1 = call_1.call().await.unwrap();
|
||||
println!("result_1: {:?}", result_1);
|
||||
assert_eq!(result_1, U256::from(0));
|
||||
|
||||
// let call_2_0 = contract.initialize(addr);
|
||||
// let tx_hash_2_0 = call_2_0.send().await.unwrap().watch().await.unwrap();
|
||||
// println!("tx_hash_2_0: {:?}", tx_hash_2_0);
|
||||
|
||||
// let call_2 = contract.mint(addr, U256::from(100));
|
||||
// let tx_hash_2 = call_2.send().await.unwrap().watch().await.unwrap();
|
||||
// println!("tx_hash_2: {:?}", tx_hash_2);
|
||||
|
||||
let call_2 = contract.totalSupply();
|
||||
let result_2 = call_2.call().await.unwrap();
|
||||
println!("result_2: {:?}", result_2);
|
||||
// assert_eq!(result_2, U256::from(0));
|
||||
|
||||
let call_2_2 = contract.name();
|
||||
let result_2_2 = call_2_2.call().await.unwrap();
|
||||
println!("result_2_2: {:?}", result_2_2);
|
||||
|
||||
let call_3_0 = contract.mint(addr, U256::from(1));
|
||||
let tx_hash_3 = call_3_0.send().await.unwrap().watch().await.unwrap();
|
||||
println!("tx_hash_3: {:?}", tx_hash_3);
|
||||
|
||||
let call_3 = contract.balanceOf(addr);
|
||||
let result_3 = call_3.call().await.unwrap();
|
||||
println!("result_3: {:?}", result_3);
|
||||
}
|
||||
*/
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_karma_amount() {
|
||||
let provider = ProviderBuilder::new().connect_anvil_with_wallet();
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
use alloy::primitives::Address;
|
||||
use alloy::providers::Provider;
|
||||
use clap::Parser;
|
||||
use rustls::crypto::aws_lc_rs;
|
||||
use smart_contract::{KarmaSC, KarmaScError};
|
||||
use smart_contract::{KarmaSC, KarmaScError, ws_provider};
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
|
||||
@@ -45,7 +46,8 @@ async fn main() -> Result<(), KarmaScError> {
|
||||
.map_err(|e| KarmaScError::SignerConnectionError(format!("Invalid URL: {e}")))?;
|
||||
|
||||
// Connect to Karma contract
|
||||
let karma_contract = KarmaSC::KarmaSCInstance::try_new(url, karma_contract_addr).await?;
|
||||
let provider = ws_provider(url.to_string()).await?.erased();
|
||||
let karma_contract = KarmaSC::KarmaSCInstance::new(karma_contract_addr, provider);
|
||||
|
||||
println!("Successfully connected to Karma contract at {karma_contract_addr}",);
|
||||
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
use std::{fmt::Formatter, str::FromStr};
|
||||
use std::fmt::Formatter;
|
||||
// third-party
|
||||
use alloy::providers::Provider;
|
||||
use alloy::{
|
||||
network::Ethereum,
|
||||
primitives::{Address, U256},
|
||||
providers::{ProviderBuilder, WsConnect},
|
||||
signers::local::PrivateKeySigner,
|
||||
sol,
|
||||
transports::{RpcError, TransportErrorKind},
|
||||
};
|
||||
use url::Url;
|
||||
// internal
|
||||
use crate::common::AlloyWsProvider;
|
||||
// use crate::common::AlloyWsProvider;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum KarmaTiersError {
|
||||
@@ -29,30 +25,6 @@ pub enum KarmaTiersError {
|
||||
TierCountTooHigh,
|
||||
}
|
||||
|
||||
/*
|
||||
sol! {
|
||||
// https://github.com/vacp2p/staking-reward-streamer/pull/224
|
||||
#[sol(rpc)]
|
||||
contract KarmaTiersSC {
|
||||
|
||||
event TiersUpdated();
|
||||
|
||||
struct Tier {
|
||||
uint256 minKarma;
|
||||
uint256 maxKarma;
|
||||
string name;
|
||||
uint32 txPerEpoch;
|
||||
}
|
||||
|
||||
// mapping(uint8 id => Tier tier) public tiers;
|
||||
// uint8 public currentTierId;
|
||||
Tier[] public tiers;
|
||||
|
||||
function getTierCount() external view returns (uint256 count);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
sol!(
|
||||
// https://github.com/vacp2p/staking-reward-streamer/pull/224
|
||||
// Compile bytecode using:
|
||||
@@ -161,7 +133,8 @@ sol!(
|
||||
}
|
||||
);
|
||||
|
||||
impl KarmaTiers::KarmaTiersInstance<AlloyWsProvider> {
|
||||
impl<P: Provider> KarmaTiers::KarmaTiersInstance<P> {
|
||||
/*
|
||||
/// Try to create a new instance with a signer
|
||||
pub async fn try_new_with_signer(
|
||||
rpc_url: Url,
|
||||
@@ -186,6 +159,9 @@ impl KarmaTiers::KarmaTiersInstance<AlloyWsProvider> {
|
||||
|
||||
Ok(KarmaTiers::new(address, provider))
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
/// Read smart contract `tiers` mapping
|
||||
pub async fn get_tiers(
|
||||
ws_rpc_url: Url,
|
||||
@@ -199,9 +175,10 @@ impl KarmaTiers::KarmaTiersInstance<AlloyWsProvider> {
|
||||
|
||||
Self::get_tiers_from_provider(&provider, &sc_address).await
|
||||
}
|
||||
*/
|
||||
|
||||
pub async fn get_tiers_from_provider<T: Provider>(
|
||||
provider: &T,
|
||||
pub async fn get_tiers_from_provider(
|
||||
provider: &P,
|
||||
sc_address: &Address,
|
||||
) -> Result<Vec<Tier>, KarmaTiersError> {
|
||||
let karma_tiers_sc = KarmaTiers::new(*sc_address, provider);
|
||||
@@ -258,32 +235,12 @@ impl KarmaTiers::KarmaTiersInstance<AlloyWsProvider> {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#[derive(Debug, Clone, Default, Copy, From, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct TierIndex(u8);
|
||||
|
||||
impl From<&TierIndex> for u8 {
|
||||
fn from(value: &TierIndex) -> u8 {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Add<u8> for TierIndex {
|
||||
type Output = TierIndex;
|
||||
|
||||
fn add(self, rhs: u8) -> Self::Output {
|
||||
Self(self.0 + rhs)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Tier {
|
||||
pub min_karma: U256,
|
||||
pub max_karma: U256,
|
||||
pub name: String,
|
||||
pub tx_per_epoch: u32,
|
||||
// pub active: bool,
|
||||
}
|
||||
|
||||
impl From<KarmaTiers::Tier> for Tier {
|
||||
@@ -297,34 +254,6 @@ impl From<KarmaTiers::Tier> for Tier {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl From<KarmaTiersSC::TierAdded> for Tier {
|
||||
fn from(tier_added: KarmaTiersSC::TierAdded) -> Self {
|
||||
Self {
|
||||
min_karma: tier_added.minKarma,
|
||||
max_karma: tier_added.maxKarma,
|
||||
name: tier_added.name,
|
||||
tx_per_epoch: tier_added.txPerEpoch,
|
||||
// active: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
impl From<KarmaTiersSC::TierUpdated> for Tier {
|
||||
fn from(tier_updated: KarmaTiersSC::TierUpdated) -> Self {
|
||||
Self {
|
||||
min_karma: tier_updated.minKarma,
|
||||
max_karma: tier_updated.maxKarma,
|
||||
name: tier_updated.name,
|
||||
tx_per_epoch: tier_updated.txPerEpoch,
|
||||
// active: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
impl From<KarmaTiers::tiersReturn> for Tier {
|
||||
fn from(tiers_return: KarmaTiers::tiersReturn) -> Self {
|
||||
Self {
|
||||
@@ -352,6 +281,7 @@ impl std::fmt::Debug for KarmaTiers::Tier {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::KarmaTiers::KarmaTiersInstance;
|
||||
use alloy::providers::ProviderBuilder;
|
||||
|
||||
impl PartialEq<KarmaTiers::Tier> for Tier {
|
||||
fn eq(&self, other: &KarmaTiers::Tier) -> bool {
|
||||
|
||||
@@ -1,9 +1,13 @@
|
||||
use alloy::network::EthereumWallet;
|
||||
use alloy::providers::{ProviderBuilder, WsConnect};
|
||||
use alloy::signers::local::PrivateKeySigner;
|
||||
use alloy::{
|
||||
hex,
|
||||
primitives::{Address, U256},
|
||||
};
|
||||
use clap::Parser;
|
||||
use rustls::crypto::aws_lc_rs;
|
||||
use smart_contract::KarmaTiers::KarmaTiersInstance;
|
||||
use smart_contract::{KarmaTiers, KarmaTiersError};
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
@@ -47,13 +51,22 @@ async fn main() -> Result<(), KarmaTiersError> {
|
||||
return Err(KarmaTiersError::EmptyPrivateKey);
|
||||
}
|
||||
|
||||
// Alloy provider + signer
|
||||
|
||||
let provider_with_signer = {
|
||||
let pk_signer = PrivateKeySigner::from_str(args.private_key.as_str()).unwrap();
|
||||
let wallet = EthereumWallet::from(pk_signer);
|
||||
|
||||
let ws = WsConnect::new(url.clone().as_str());
|
||||
ProviderBuilder::new()
|
||||
.wallet(wallet)
|
||||
.connect_ws(ws)
|
||||
.await
|
||||
.map_err(KarmaTiersError::RpcTransportError)?
|
||||
};
|
||||
|
||||
// Connect to KarmaTiers contract
|
||||
let karma_tiers_contract = KarmaTiers::KarmaTiersInstance::try_new_with_signer(
|
||||
url.clone(),
|
||||
contract_addr,
|
||||
args.private_key,
|
||||
)
|
||||
.await?;
|
||||
let karma_tiers_contract = KarmaTiersInstance::new(contract_addr, provider_with_signer.clone());
|
||||
|
||||
println!("Successfully connected to KarmaTiers contract for reading at {contract_addr}",);
|
||||
|
||||
@@ -90,7 +103,8 @@ async fn main() -> Result<(), KarmaTiersError> {
|
||||
|
||||
// Use the get_tiers function from karma_tiers.rs instead of duplicating code
|
||||
let current_tiers =
|
||||
KarmaTiers::KarmaTiersInstance::get_tiers(url.clone(), contract_addr).await?;
|
||||
KarmaTiersInstance::get_tiers_from_provider(&provider_with_signer, &contract_addr)
|
||||
.await?;
|
||||
|
||||
for (i, tier) in current_tiers.iter().enumerate() {
|
||||
println!(
|
||||
@@ -186,8 +200,11 @@ async fn main() -> Result<(), KarmaTiersError> {
|
||||
println!("============================");
|
||||
|
||||
// Use the get_tiers function from karma_tiers.rs instead of duplicating code
|
||||
let updated_tiers =
|
||||
KarmaTiers::KarmaTiersInstance::get_tiers(url.clone(), contract_addr).await?;
|
||||
let updated_tiers = KarmaTiersInstance::get_tiers_from_provider(
|
||||
&provider_with_signer,
|
||||
&contract_addr,
|
||||
)
|
||||
.await?;
|
||||
|
||||
for (i, tier) in updated_tiers.iter().enumerate() {
|
||||
println!(
|
||||
|
||||
@@ -4,7 +4,11 @@ mod karma_tiers;
|
||||
mod mock;
|
||||
mod rln_sc;
|
||||
|
||||
pub use common::AlloyWsProvider;
|
||||
pub use common::{
|
||||
// AlloyWsProvider,
|
||||
// AlloyWsProviderWithSigner,
|
||||
ws_provider,
|
||||
};
|
||||
pub use karma_sc::{KarmaAmountExt, KarmaSC, KarmaScError};
|
||||
pub use karma_tiers::{KarmaTiers, KarmaTiersError, Tier};
|
||||
pub use rln_sc::{KarmaRLNSC, RLNRegister, RlnScError};
|
||||
|
||||
@@ -27,10 +27,7 @@ impl RLNRegister for MockKarmaRLNSc {
|
||||
address: &Address,
|
||||
identity_commitment: U256,
|
||||
) -> Result<(), Self::Error> {
|
||||
debug!(
|
||||
"Register user ({}) with identity_commitment: {:?}",
|
||||
address, identity_commitment
|
||||
);
|
||||
debug!("Register user ({address}) with identity_commitment: {identity_commitment:?}");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,13 @@
|
||||
use alloy::primitives::U256;
|
||||
use alloy::providers::Provider;
|
||||
use alloy::{
|
||||
network::Ethereum,
|
||||
primitives::Address,
|
||||
providers::{ProviderBuilder, WsConnect},
|
||||
signers::local::PrivateKeySigner,
|
||||
sol,
|
||||
transports::{RpcError, TransportErrorKind},
|
||||
};
|
||||
use async_trait::async_trait;
|
||||
use std::str::FromStr;
|
||||
use url::Url;
|
||||
use zeroize::Zeroizing;
|
||||
// internal
|
||||
use crate::common::AlloyWsProvider;
|
||||
// use crate::common::AlloyWsProvider;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum RlnScError {
|
||||
@@ -70,6 +64,7 @@ sol! {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
impl KarmaRLNSC::KarmaRLNSCInstance<AlloyWsProvider> {
|
||||
pub async fn try_new_with_signer(
|
||||
rpc_url: Url,
|
||||
@@ -94,6 +89,7 @@ impl KarmaRLNSC::KarmaRLNSCInstance<AlloyWsProvider> {
|
||||
Ok(KarmaRLNSC::new(address, provider))
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
#[async_trait]
|
||||
impl<T: Provider> RLNRegister for KarmaRLNSC::KarmaRLNSCInstance<T> {
|
||||
@@ -120,6 +116,7 @@ mod tests {
|
||||
// third-party
|
||||
use crate::KarmaSC;
|
||||
use alloy::primitives::address;
|
||||
use alloy::providers::ProviderBuilder;
|
||||
use alloy::sol_types::SolCall;
|
||||
|
||||
#[tokio::test]
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
// std
|
||||
use std::str::FromStr;
|
||||
// third-party
|
||||
use alloy::network::EthereumWallet;
|
||||
use alloy::providers::{ProviderBuilder, WsConnect};
|
||||
use alloy::signers::local::PrivateKeySigner;
|
||||
use alloy::{
|
||||
hex,
|
||||
primitives::{Address, U256},
|
||||
@@ -8,9 +11,8 @@ use alloy::{
|
||||
use clap::Parser;
|
||||
use rustls::crypto::aws_lc_rs;
|
||||
use url::Url;
|
||||
use zeroize::Zeroizing;
|
||||
// internal
|
||||
use smart_contract::{KarmaRLNSC, RlnScError};
|
||||
use smart_contract::{KarmaRLNSC::KarmaRLNSCInstance, RlnScError};
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
@@ -49,9 +51,8 @@ async fn main() -> Result<(), RlnScError> {
|
||||
|
||||
println!("Connecting to RPC: {}", args.ws_rpc_url);
|
||||
|
||||
let contract_addr = Address::from_str(&args.contract_address).map_err(|e| {
|
||||
RlnScError::SignerConnectionError(format!("Invalid contract address: {}", e))
|
||||
})?;
|
||||
let contract_addr = Address::from_str(&args.contract_address)
|
||||
.map_err(|e| RlnScError::SignerConnectionError(format!("Invalid contract address: {e}")))?;
|
||||
|
||||
let test_identity_commitment = U256::from(args.test_identity_commitment);
|
||||
let test_user_address = Address::from_str(&args.test_user_address)
|
||||
@@ -65,12 +66,18 @@ async fn main() -> Result<(), RlnScError> {
|
||||
}
|
||||
|
||||
// Connect to KarmaRLN contract with signer
|
||||
let rln_contract = KarmaRLNSC::KarmaRLNSCInstance::try_new_with_signer(
|
||||
url,
|
||||
contract_addr,
|
||||
Zeroizing::new(args.private_key),
|
||||
)
|
||||
.await?;
|
||||
let provider_with_signer = {
|
||||
let pk_signer = PrivateKeySigner::from_str(args.private_key.as_str()).unwrap();
|
||||
let wallet = EthereumWallet::from(pk_signer);
|
||||
|
||||
let ws = WsConnect::new(url.clone().as_str());
|
||||
ProviderBuilder::new()
|
||||
.wallet(wallet)
|
||||
.connect_ws(ws)
|
||||
.await
|
||||
.map_err(RlnScError::RpcTransportError)?
|
||||
};
|
||||
let rln_contract = KarmaRLNSCInstance::new(contract_addr, provider_with_signer);
|
||||
|
||||
println!("Successfully connected to RLN contract with signer at {contract_addr}",);
|
||||
|
||||
@@ -92,11 +99,11 @@ async fn main() -> Result<(), RlnScError> {
|
||||
};
|
||||
|
||||
println!("Registry Info:");
|
||||
println!(" Set size: {}", set_size);
|
||||
println!(" Current index: {}", current_index);
|
||||
println!(" Karma address: {}", karma_address);
|
||||
println!(" Is full: {}", is_full);
|
||||
println!(" Available slots: {}", available_slots);
|
||||
println!(" Set size: {set_size}");
|
||||
println!(" Current index: {current_index}");
|
||||
println!(" Karma address: {karma_address}");
|
||||
println!(" Is full: {is_full}");
|
||||
println!(" Available slots: {available_slots}");
|
||||
}
|
||||
_ => {
|
||||
eprintln!("Failed to get registry info");
|
||||
@@ -107,7 +114,7 @@ async fn main() -> Result<(), RlnScError> {
|
||||
match rln_contract.members(test_identity_commitment).call().await {
|
||||
Ok(member) => {
|
||||
if member.userAddress != Address::ZERO {
|
||||
println!("Member {} is registered:", test_identity_commitment);
|
||||
println!("Member {test_identity_commitment} is registered:");
|
||||
println!(" User address: {}", member.userAddress);
|
||||
println!(" Index: {}", member.index);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user