Skip to content

Commit

Permalink
Actor events for the verified registry (#1456)
Browse files Browse the repository at this point in the history
* verifreg-balance-event-working

* allocation and allocation removed

* add more info to tests

* finish all events

* address review

* address review
  • Loading branch information
aarshkshah1992 authored Oct 25, 2023
1 parent 1e50065 commit 7500bab
Show file tree
Hide file tree
Showing 9 changed files with 433 additions and 124 deletions.
49 changes: 49 additions & 0 deletions actors/verifreg/src/emit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// A namespace for helpers that build and emit verified registry events.

use crate::{ActorError, AllocationID};
use crate::{ClaimID, DataCap};
use fil_actors_runtime::runtime::Runtime;
use fil_actors_runtime::EventBuilder;
use fvm_shared::ActorID;

/// Indicates a new value for a verifier's datacap balance.
/// Note that receiving this event does not necessarily mean the balance has changed.
/// The value is in datacap whole units (not TokenAmount).
pub fn verifier_balance(
rt: &impl Runtime,
verifier: ActorID,
new_balance: &DataCap,
) -> Result<(), ActorError> {
rt.emit_event(
&EventBuilder::new()
.typ("verifier-balance")
.field_indexed("verifier", &verifier)
.field("balance", new_balance)
.build()?,
)
}

/// Indicates a new allocation has been made.
pub fn allocation(rt: &impl Runtime, id: AllocationID) -> Result<(), ActorError> {
rt.emit_event(&EventBuilder::new().typ("allocation").field_indexed("id", &id).build()?)
}

/// Indicates an expired allocation has been removed.
pub fn allocation_removed(rt: &impl Runtime, id: AllocationID) -> Result<(), ActorError> {
rt.emit_event(&EventBuilder::new().typ("allocation-removed").field_indexed("id", &id).build()?)
}

/// Indicates an allocation has been claimed.
pub fn claim(rt: &impl Runtime, id: ClaimID) -> Result<(), ActorError> {
rt.emit_event(&EventBuilder::new().typ("claim").field_indexed("id", &id).build()?)
}

/// Indicates an existing claim has been updated (e.g. with a longer term).
pub fn claim_updated(rt: &impl Runtime, id: ClaimID) -> Result<(), ActorError> {
rt.emit_event(&EventBuilder::new().typ("claim-updated").field_indexed("id", &id).build()?)
}

/// Indicates an expired claim has been removed.
pub fn claim_removed(rt: &impl Runtime, id: ClaimID) -> Result<(), ActorError> {
rt.emit_event(&EventBuilder::new().typ("claim-removed").field_indexed("id", &id).build()?)
}
85 changes: 58 additions & 27 deletions actors/verifreg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub use self::types::*;
#[cfg(feature = "fil-actor")]
fil_actors_runtime::wasm_trampoline!(Actor);

pub mod emit;
pub mod expiration;
pub mod ext;
pub mod state;
Expand Down Expand Up @@ -103,44 +104,48 @@ impl Actor {
}

let verifier = resolve_to_actor_id(rt, &params.address, true)?;
let verifier = Address::new_id(verifier);
let verifier_addr = Address::new_id(verifier);

let st: State = rt.state()?;
rt.validate_immediate_caller_is(std::iter::once(&st.root_key))?;

// Disallow root as a verifier.
if verifier == st.root_key {
if verifier_addr == st.root_key {
return Err(actor_error!(illegal_argument, "Rootkey cannot be added as verifier"));
}

// Disallow existing clients as verifiers.
let token_balance = balance(rt, &verifier)?;
let token_balance = balance(rt, &verifier_addr)?;
if token_balance.is_positive() {
return Err(actor_error!(
illegal_argument,
"verified client {} cannot become a verifier",
verifier
verifier_addr
));
}

// Store the new verifier and allowance (over-writing).
rt.transaction(|st: &mut State, rt| {
st.put_verifier(rt.store(), &verifier, &params.allowance)
st.put_verifier(rt.store(), &verifier_addr, &params.allowance)
.context("failed to add verifier")
})
})?;

emit::verifier_balance(rt, verifier, &params.allowance)
}

pub fn remove_verifier(
rt: &impl Runtime,
params: RemoveVerifierParams,
) -> Result<(), ActorError> {
let verifier = resolve_to_actor_id(rt, &params.verifier, false)?;
let verifier = Address::new_id(verifier);
let verifier_addr = Address::new_id(verifier);

rt.transaction(|st: &mut State, rt| {
rt.validate_immediate_caller_is(std::iter::once(&st.root_key))?;
st.remove_verifier(rt.store(), &verifier).context("failed to remove verifier")
})
st.remove_verifier(rt.store(), &verifier_addr).context("failed to remove verifier")
})?;

emit::verifier_balance(rt, verifier, &DataCap::zero())
}

pub fn add_verified_client(
Expand Down Expand Up @@ -168,10 +173,11 @@ impl Actor {
}

// Validate caller is one of the verifiers, i.e. has an allowance (even if zero).
let verifier = rt.message().caller();
let verifier_cap = st
.get_verifier_cap(rt.store(), &verifier)?
.ok_or_else(|| actor_error!(not_found, "caller {} is not a verifier", verifier))?;
let verifier_addr = rt.message().caller();
let verifier_cap =
st.get_verifier_cap(rt.store(), &verifier_addr)?.ok_or_else(|| {
actor_error!(not_found, "caller {} is not a verifier", verifier_addr)
})?;

// Disallow existing verifiers as clients.
if st.get_verifier_cap(rt.store(), &client)?.is_some() {
Expand All @@ -194,8 +200,9 @@ impl Actor {

// Reduce verifier's cap.
let new_verifier_cap = verifier_cap - &params.allowance;
st.put_verifier(rt.store(), &verifier, &new_verifier_cap)
.context("failed to update verifier allowance")
st.put_verifier(rt.store(), &verifier_addr, &new_verifier_cap)
.context("failed to update verifier allowance")?;
emit::verifier_balance(rt, verifier_addr.id().unwrap(), &new_verifier_cap)
})?;

// Credit client token allowance.
Expand Down Expand Up @@ -328,12 +335,17 @@ impl Actor {
}

for id in to_remove {
let existing = allocs.remove(params.client, *id).context_code(
ExitCode::USR_ILLEGAL_STATE,
format!("failed to remove allocation {}", id),
)?;
// Unwrapping here as both paths to here should ensure the allocation exists.
recovered_datacap += existing.unwrap().size.0;
let existing = allocs
.remove(params.client, *id)
.context_code(
ExitCode::USR_ILLEGAL_STATE,
format!("failed to remove allocation {}", id),
)?
.unwrap(); // Unwrapping here as both paths to here should ensure the allocation exists.

emit::allocation_removed(rt, *id)?;

recovered_datacap += existing.size.0;
}

st.save_allocs(&mut allocs)?;
Expand Down Expand Up @@ -432,6 +444,9 @@ impl Actor {
if !inserted {
return Err(actor_error!(illegal_argument, "claim {} already exists", id));
}

emit::claim(rt, id)?;

allocs.remove(new_claim.client, id).context_code(
ExitCode::USR_ILLEGAL_STATE,
format!("failed to remove allocation {}", id),
Expand Down Expand Up @@ -547,6 +562,7 @@ impl Actor {
"HAMT put failure storing new claims",
)?;
batch_gen.add_success();
emit::claim_updated(rt, term.claim_id)?;
} else {
batch_gen.add_fail(ExitCode::USR_NOT_FOUND);
info!("no claim {} for provider {}", term.claim_id, term.provider);
Expand Down Expand Up @@ -590,10 +606,15 @@ impl Actor {
}

for id in to_remove {
claims.remove(params.provider, *id).context_code(
ExitCode::USR_ILLEGAL_STATE,
format!("failed to remove claim {}", id),
)?;
claims
.remove(params.provider, *id)
.context_code(
ExitCode::USR_ILLEGAL_STATE,
format!("failed to remove claim {}", id),
)?
.unwrap();

emit::claim_removed(rt, *id)?;
}

st.save_claims(&mut claims)?;
Expand Down Expand Up @@ -690,8 +711,18 @@ impl Actor {

// Save new allocations and updated claims.
let ids = rt.transaction(|st: &mut State, rt| {
let ids = st.insert_allocations(rt.store(), client, new_allocs)?;
st.put_claims(rt.store(), updated_claims)?;
let ids = st.insert_allocations(rt.store(), client, new_allocs.clone())?;

for id in ids.iter() {
emit::allocation(rt, *id)?;
}

st.put_claims(rt.store(), updated_claims.clone())?;

for (id, _) in updated_claims {
emit::claim_updated(rt, id)?;
}

Ok(ids)
})?;

Expand Down
67 changes: 65 additions & 2 deletions actors/verifreg/tests/harness/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use fil_actors_runtime::runtime::policy_constants::{
use fil_actors_runtime::runtime::Runtime;
use fil_actors_runtime::test_utils::*;
use fil_actors_runtime::{
make_empty_map, ActorError, AsActorError, BatchReturn, DATACAP_TOKEN_ACTOR_ADDR,
make_empty_map, ActorError, AsActorError, BatchReturn, EventBuilder, DATACAP_TOKEN_ACTOR_ADDR,
STORAGE_MARKET_ACTOR_ADDR, SYSTEM_ACTOR_ADDR, VERIFIED_REGISTRY_ACTOR_ADDR,
};

Expand Down Expand Up @@ -138,6 +138,13 @@ impl Harness {
ExitCode::OK,
None,
);
rt.expect_emitted_event(
EventBuilder::new()
.typ("verifier-balance")
.field_indexed("verifier", &verifier_resolved.id().unwrap())
.field("balance", &allowance)
.build()?,
);

let params = AddVerifierParams { address: *verifier, allowance: allowance.clone() };
let ret = rt.call::<VerifregActor>(
Expand All @@ -153,6 +160,13 @@ impl Harness {

pub fn remove_verifier(&self, rt: &MockRuntime, verifier: &Address) -> Result<(), ActorError> {
rt.expect_validate_caller_addr(vec![self.root]);
rt.expect_emitted_event(
EventBuilder::new()
.typ("verifier-balance")
.field_indexed("verifier", &verifier.id().unwrap())
.field("balance", &DataCap::zero())
.build()?,
);
rt.set_caller(*ACCOUNT_ACTOR_CODE_ID, self.root);
let ret = rt.call::<VerifregActor>(
Method::RemoveVerifier as MethodNum,
Expand Down Expand Up @@ -192,6 +206,7 @@ impl Harness {
verifier: &Address,
client: &Address,
allowance: &DataCap,
verifier_balance: &DataCap,
) -> Result<(), ActorError> {
rt.expect_validate_caller_any();
rt.set_caller(*ACCOUNT_ACTOR_CODE_ID, *verifier);
Expand All @@ -213,6 +228,13 @@ impl Harness {
);

let params = AddVerifiedClientParams { address: *client, allowance: allowance.clone() };
rt.expect_emitted_event(
EventBuilder::new()
.typ("verifier-balance")
.field_indexed("verifier", &verifier.id().unwrap())
.field("balance", &(verifier_balance - allowance))
.build()?,
);
let ret = rt.call::<VerifregActor>(
Method::AddVerifiedClient as MethodNum,
IpldBlock::serialize_cbor(&params).unwrap(),
Expand Down Expand Up @@ -265,10 +287,17 @@ impl Harness {
claim_allocs: Vec<SectorAllocationClaims>,
datacap_burnt: u64,
all_or_nothing: bool,
expect_claimed: Vec<AllocationID>,
) -> Result<ClaimAllocationsReturn, ActorError> {
rt.expect_validate_caller_type(vec![Type::Miner]);
rt.set_caller(*MINER_ACTOR_CODE_ID, Address::new_id(provider));

for id in expect_claimed.iter() {
rt.expect_emitted_event(
EventBuilder::new().typ("claim").field_indexed("id", &id).build()?,
);
}

if datacap_burnt > 0 {
rt.expect_send_simple(
DATACAP_TOKEN_ACTOR_ADDR,
Expand Down Expand Up @@ -302,9 +331,16 @@ impl Harness {
rt: &MockRuntime,
client: ActorID,
allocation_ids: Vec<AllocationID>,
expected_datacap: u64,
expect_removed: Vec<(AllocationID, Allocation)>,
) -> Result<RemoveExpiredAllocationsReturn, ActorError> {
rt.expect_validate_caller_any();
let mut expected_datacap = 0u64;
for (id, alloc) in expect_removed {
expected_datacap += alloc.size.0;
rt.expect_emitted_event(
EventBuilder::new().typ("allocation-removed").field_indexed("id", &id).build()?,
);
}

rt.expect_send_simple(
DATACAP_TOKEN_ACTOR_ADDR,
Expand Down Expand Up @@ -339,9 +375,16 @@ impl Harness {
rt: &MockRuntime,
provider: ActorID,
claim_ids: Vec<ClaimID>,
expect_removed: Vec<ClaimID>,
) -> Result<RemoveExpiredClaimsReturn, ActorError> {
rt.expect_validate_caller_any();

for id in expect_removed {
rt.expect_emitted_event(
EventBuilder::new().typ("claim-removed").field_indexed("id", &id).build()?,
);
}

let params = RemoveExpiredClaimsParams { provider, claim_ids };
let ret = rt
.call::<VerifregActor>(
Expand Down Expand Up @@ -390,6 +433,19 @@ impl Harness {
);
}

let allocs_req: AllocationRequests = payload.operator_data.deserialize().unwrap();
for id in expected_alloc_ids.iter() {
rt.expect_emitted_event(
EventBuilder::new().typ("allocation").field_indexed("id", &id).build()?,
);
}

for ext in allocs_req.extensions {
rt.expect_emitted_event(
EventBuilder::new().typ("claim-updated").field_indexed("id", &ext.claim).build()?,
);
}

rt.expect_validate_caller_addr(vec![DATACAP_TOKEN_ACTOR_ADDR]);
let ret = rt.call::<VerifregActor>(
Method::UniversalReceiverHook as MethodNum,
Expand Down Expand Up @@ -445,7 +501,14 @@ impl Harness {
&self,
rt: &MockRuntime,
params: &ExtendClaimTermsParams,
expected: Vec<ClaimID>,
) -> Result<ExtendClaimTermsReturn, ActorError> {
for id in expected.iter() {
rt.expect_emitted_event(
EventBuilder::new().typ("claim-updated").field_indexed("id", &id).build()?,
);
}

rt.expect_validate_caller_any();
let ret = rt
.call::<VerifregActor>(
Expand Down
Loading

0 comments on commit 7500bab

Please sign in to comment.