mirror of
https://github.com/vacp2p/status-rln-prover.git
synced 2026-01-06 20:23:50 -05:00
Add AccountSlashed event in KarmaSC contract (#52)
* Add AccountSlashed event in KarmaSC contract * Handle slash event in KarmaSCEventListener
This commit is contained in:
@@ -3,6 +3,7 @@ use alloy::{
|
||||
contract::Error as AlloyContractError,
|
||||
primitives::{Address, U256},
|
||||
providers::Provider,
|
||||
rpc::types::Log,
|
||||
sol_types::SolEvent,
|
||||
};
|
||||
use num_bigint::BigUint;
|
||||
@@ -14,14 +15,14 @@ use crate::user_db::UserDb;
|
||||
use crate::user_db_error::RegisterError;
|
||||
use smart_contract::{KarmaAmountExt, KarmaRLNSC, KarmaSC, RLNRegister};
|
||||
|
||||
pub(crate) struct RegistryListener {
|
||||
pub(crate) struct KarmaScEventListener {
|
||||
karma_sc_address: Address,
|
||||
rln_sc_address: Address,
|
||||
user_db: UserDb,
|
||||
minimal_amount: U256,
|
||||
}
|
||||
|
||||
impl RegistryListener {
|
||||
impl KarmaScEventListener {
|
||||
pub(crate) fn new(
|
||||
karma_sc_address: Address,
|
||||
rln_sc_address: Address,
|
||||
@@ -42,17 +43,13 @@ impl RegistryListener {
|
||||
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.karma_sc_address)
|
||||
.event(KarmaSC::Transfer::SIGNATURE);
|
||||
.event(KarmaSC::Transfer::SIGNATURE)
|
||||
.event(KarmaSC::AccountSlashed::SIGNATURE);
|
||||
|
||||
// Subscribe to logs matching the filter.
|
||||
let subscription = provider.subscribe_logs(&filter).await?;
|
||||
@@ -60,6 +57,21 @@ impl RegistryListener {
|
||||
|
||||
// Loop through the incoming event logs
|
||||
while let Some(log) = stream.next().await {
|
||||
match log.topic0() {
|
||||
Some(&KarmaSC::Transfer::SIGNATURE_HASH) => {
|
||||
self.transfer_event(&log, &karma_sc, &rln_sc)
|
||||
.await
|
||||
.map_err(AppError::RegistryError)?;
|
||||
}
|
||||
Some(&KarmaSC::AccountSlashed::SIGNATURE_HASH) => {
|
||||
self.slash_event(&log).await;
|
||||
}
|
||||
_ => {
|
||||
debug!("Received unknown topic from karma sc: {:?}", log);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
match KarmaSC::Transfer::decode_log_data(log.data()) {
|
||||
Ok(transfer_event) => {
|
||||
match self
|
||||
@@ -93,6 +105,64 @@ impl RegistryListener {
|
||||
// in order to avoid a too long service interruption?
|
||||
}
|
||||
}
|
||||
*/
|
||||
// TODO
|
||||
/*
|
||||
match KarmaSC::AccountSlashed::decode_log_data(log.data()) {
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Decode transfert event from log and call `handle_transfer_event`
|
||||
async fn transfer_event<
|
||||
E: Into<AlloyContractError>,
|
||||
KSC: KarmaAmountExt<Error = E>,
|
||||
RLNSC: RLNRegister<Error = E>,
|
||||
>(
|
||||
&self,
|
||||
log: &Log,
|
||||
karma_sc: &KSC,
|
||||
rln_sc: &RLNSC,
|
||||
) -> Result<(), HandleTransferError> {
|
||||
match KarmaSC::Transfer::decode_log_data(log.data()) {
|
||||
Ok(transfer_event) => {
|
||||
match self
|
||||
.handle_transfer_event(karma_sc, rln_sc, transfer_event)
|
||||
.await
|
||||
{
|
||||
Ok(addr) => {
|
||||
info!("Registered new user: {}", addr);
|
||||
}
|
||||
Err(HandleTransferError::Register(RegisterError::AlreadyRegistered(
|
||||
address,
|
||||
))) => {
|
||||
debug!("Already registered: {}", address);
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Unexpected error: {}", e);
|
||||
// Note: Err(e) == HandleTransferError::FetchBalanceOf
|
||||
// if we cannot fetch the user balance, something is seriously wrong
|
||||
// and the prover will fail here
|
||||
|
||||
// return Err(AppError::RegistryError(e));
|
||||
return Err(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error decoding log data: {:?}", e);
|
||||
// It's also useful to print the raw log data for debugging
|
||||
error!("Raw log topics: {:?}", log.topics());
|
||||
error!("Raw log data: {:?}", log.data());
|
||||
// Note: This can happen when
|
||||
// - SC code has been updated but not the Prover
|
||||
// - In the update process, the Prover has not been shutdown (yet)
|
||||
// in order to avoid a too long service interruption?
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -155,7 +225,7 @@ impl RegistryListener {
|
||||
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
|
||||
// Fail to register the 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
|
||||
@@ -170,6 +240,28 @@ impl RegistryListener {
|
||||
|
||||
Ok(to_address)
|
||||
}
|
||||
|
||||
/// Handle slash event from Karma smart contract
|
||||
async fn slash_event(&self, log: &Log) {
|
||||
match KarmaSC::AccountSlashed::decode_log_data(log.data()) {
|
||||
Ok(slash_event) => {
|
||||
let address_slashed: Address = slash_event.account;
|
||||
if !self.user_db.remove_user(&address_slashed, false) {
|
||||
error!("Cannot remove user ({:?}) from DB", address_slashed);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error decoding log data: {:?}", e);
|
||||
// It's also useful to print the raw log data for debugging
|
||||
error!("Raw log topics: {:?}", log.topics());
|
||||
error!("Raw log data: {:?}", log.data());
|
||||
// Note: This can happen when
|
||||
// - SC code has been updated but not the Prover
|
||||
// - In the update process, the Prover has not been shutdown (yet)
|
||||
// to avoid a too long service interruption?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -247,7 +339,7 @@ mod tests {
|
||||
assert!(user_db_service.get_user_db().get_user(&ADDR_2).is_none());
|
||||
|
||||
let minimal_amount = U256::from(25);
|
||||
let registry = RegistryListener {
|
||||
let registry = KarmaScEventListener {
|
||||
rln_sc_address: Default::default(),
|
||||
karma_sc_address: Default::default(),
|
||||
user_db,
|
||||
@@ -2,11 +2,11 @@ mod args;
|
||||
mod epoch_service;
|
||||
mod error;
|
||||
mod grpc_service;
|
||||
mod karma_sc_listener;
|
||||
pub mod metrics;
|
||||
mod mock;
|
||||
mod proof_generation;
|
||||
mod proof_service;
|
||||
mod registry_listener;
|
||||
mod rocksdb_operands;
|
||||
mod tier;
|
||||
mod tiers_listener;
|
||||
@@ -37,10 +37,10 @@ pub use crate::args::{ARGS_DEFAULT_GENESIS, AppArgs, AppArgsConfig};
|
||||
use crate::epoch_service::EpochService;
|
||||
use crate::error::AppError;
|
||||
use crate::grpc_service::GrpcProverService;
|
||||
use crate::karma_sc_listener::KarmaScEventListener;
|
||||
pub use crate::mock::MockUser;
|
||||
use crate::mock::read_mock_user;
|
||||
use crate::proof_service::ProofService;
|
||||
use crate::registry_listener::RegistryListener;
|
||||
use crate::tier::TierLimits;
|
||||
use crate::tiers_listener::TiersListener;
|
||||
use crate::user_db::{MERKLE_TREE_HEIGHT, UserDbConfig};
|
||||
@@ -150,7 +150,7 @@ pub async fn run_prover(app_args: AppArgs) -> Result<(), AppError> {
|
||||
// No registry listener when mock is enabled
|
||||
None
|
||||
} else {
|
||||
Some(RegistryListener::new(
|
||||
Some(KarmaScEventListener::new(
|
||||
app_args.ksc_address.unwrap(),
|
||||
app_args.rlnsc_address.unwrap(),
|
||||
user_db_service.get_user_db(),
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
use alloy::primitives::{Address, U256};
|
||||
use futures::FutureExt;
|
||||
use parking_lot::RwLock;
|
||||
use prover::{AppArgs, MockUser, run_prover};
|
||||
use std::io::Write;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
use std::num::NonZeroU64;
|
||||
use std::str::FromStr;
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
// third-party
|
||||
use alloy::primitives::{Address, U256};
|
||||
use futures::FutureExt;
|
||||
use parking_lot::RwLock;
|
||||
use tempfile::NamedTempFile;
|
||||
use tokio::task;
|
||||
use tokio::task::JoinSet;
|
||||
use tonic::Response;
|
||||
use tracing::{debug, info};
|
||||
use tracing_test::traced_test;
|
||||
|
||||
// use tracing_test::traced_test;
|
||||
// internal
|
||||
use prover::{AppArgs, MockUser, run_prover};
|
||||
pub mod prover_proto {
|
||||
// Include generated code (see build.rs)
|
||||
tonic::include_proto!("prover");
|
||||
@@ -220,7 +221,7 @@ async fn proof_collector(port: u16, proof_count: usize) -> Vec<RlnProofReply> {
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[traced_test]
|
||||
// #[traced_test]
|
||||
async fn test_grpc_gen_proof() {
|
||||
let mock_users = vec![
|
||||
MockUser {
|
||||
|
||||
@@ -5,15 +5,15 @@ edition = "2024"
|
||||
|
||||
[[bin]]
|
||||
name = "karma_sc_test"
|
||||
path = "src/karma_sc_test.rs"
|
||||
path = "src/bin_tests/karma_sc_test.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "karma_tiers_test"
|
||||
path = "src/karma_tiers_test.rs"
|
||||
path = "src/bin_tests/karma_tiers_test.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "rln_sc_test"
|
||||
path = "src/rln_sc_test.rs"
|
||||
path = "src/bin_tests/rln_sc_test.rs"
|
||||
|
||||
[dependencies]
|
||||
tokio.workspace = true
|
||||
|
||||
@@ -29,7 +29,8 @@ pub trait KarmaAmountExt {
|
||||
}
|
||||
|
||||
sol! {
|
||||
// https://github.com/vacp2p/staking-reward-streamer/blob/main/src/Karma.sol
|
||||
// https://github.com/status-im/status-network-monorepo/blob/develop/status-network-contracts/src/Karma.sol
|
||||
// OLD: https://github.com/vacp2p/staking-reward-streamer/blob/main/src/Karma.sol
|
||||
//
|
||||
// docker run -v ./:/sources ethereum/solc:stable --bin --via-ir --optimize --optimize-runs 1 --overwrite @openzeppelin/contracts=/sources/lib/openzeppelin-contracts/contracts @openzeppelin/contracts-upgradeable=/sources/lib/openzeppelin-contracts-upgradeable/contracts /sources/src/Karma.sol
|
||||
|
||||
@@ -53,6 +54,9 @@ sol! {
|
||||
|
||||
// From: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/IERC20.sol#L16
|
||||
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||
event AccountSlashed(
|
||||
address indexed account, uint256 amount, address indexed rewardRecipient, uint256 rewardAmount
|
||||
);
|
||||
|
||||
function balanceOf(address account) public view override returns (uint256);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user