Skip to content

Commit

Permalink
Implement actor events from the verified registry
Browse files Browse the repository at this point in the history
  • Loading branch information
anorth committed Jul 16, 2023
1 parent b712d1e commit 74ae683
Show file tree
Hide file tree
Showing 7 changed files with 620 additions and 188 deletions.
105 changes: 105 additions & 0 deletions actors/verifreg/src/events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
use crate::{Allocation, AllocationID, Claim, ClaimID, DataCap};
use fil_actors_runtime::runtime::Runtime;
use fil_actors_runtime::{ActorError, EventBuilder};
use fvm_shared::ActorID;

// A namespace for helpers that build and emit verified registry events.
// REVIEW: would this be better as a simple module with pub fns, called as emit::verifier_balance()?
pub struct Emit {}

impl Emit {
/// 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()
.label("verifier-balance")
.value_indexed("verifier", &verifier)?
.value("balance", new_balance)?
.build(),
)
}

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

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

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

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

/// Indicates an expired claim has been removed.
pub fn claim_removed(rt: &impl Runtime, id: ClaimID, claim: &Claim) -> Result<(), ActorError> {
rt.emit_event(&EventBuilder::new().label("claim-removed").with_claim(id, claim)?.build())
}
}

trait WithAllocation {
fn with_allocation(
self,
id: AllocationID,
alloc: &Allocation,
) -> Result<EventBuilder, ActorError>;
}

impl WithAllocation for EventBuilder {
fn with_allocation(
self,
id: AllocationID,
alloc: &Allocation,
) -> Result<EventBuilder, ActorError> {
self.value_indexed("id", &id)?
.value_indexed("client", &alloc.client)?
.value_indexed("provider", &alloc.provider)?
.value_indexed("data-cid", &alloc.data)?
.value("data-size", &alloc.size)?
.value("term-min", &alloc.term_min)?
.value("term-max", &alloc.term_max)?
.value("expiration", &alloc.expiration)
}
}

trait WithClaim {
fn with_claim(self, id: ClaimID, claim: &Claim) -> Result<EventBuilder, ActorError>;
}

impl WithClaim for EventBuilder {
fn with_claim(self, id: ClaimID, claim: &Claim) -> Result<EventBuilder, ActorError> {
self.value_indexed("id", &id)?
.value_indexed("provider", &claim.provider)?
.value_indexed("client", &claim.client)?
.value_indexed("data-cid", &claim.data)?
.value("data-size", &claim.size)?
.value("term-min", &claim.term_min)?
.value("term-max", &claim.term_max)?
.value("term-start", &claim.term_start)?
.value("sector", &claim.sector)
}
}
85 changes: 54 additions & 31 deletions actors/verifreg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use frc46_token::token::types::{BurnParams, TransferParams};
use frc46_token::token::TOKEN_PRECISION;
use fvm_actor_utils::receiver::UniversalReceiverParams;
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_ipld_encoding::RawBytes;
use fvm_ipld_hamt::BytesKey;
use fvm_shared::address::Address;
Expand All @@ -14,6 +15,7 @@ use fvm_shared::bigint::BigInt;
use fvm_shared::clock::ChainEpoch;
use fvm_shared::econ::TokenAmount;
use fvm_shared::error::ExitCode;
use fvm_shared::sys::SendFlags;
use fvm_shared::{ActorID, HAMT_BIT_WIDTH, METHOD_CONSTRUCTOR};
use log::info;
use num_derive::FromPrimitive;
Expand All @@ -29,9 +31,8 @@ use fil_actors_runtime::{
VERIFIED_REGISTRY_ACTOR_ADDR,
};
use fil_actors_runtime::{ActorContext, AsActorError, BatchReturnGen};
use fvm_ipld_encoding::ipld_block::IpldBlock;
use fvm_shared::sys::SendFlags;

use crate::events::Emit;
use crate::ext::datacap::{DestroyParams, MintParams};

pub use self::state::Allocation;
Expand All @@ -42,6 +43,7 @@ pub use self::types::*;
#[cfg(feature = "fil-actor")]
fil_actors_runtime::wasm_trampoline!(Actor);

pub mod events;
pub mod expiration;
pub mod ext;
pub mod state;
Expand Down Expand Up @@ -103,44 +105,46 @@ 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 +172,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 +199,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 @@ -335,12 +341,16 @@ 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),
)?
// Unwrapping here as both paths should ensure the allocation exists.
.unwrap();
Emit::allocation_removed(rt, id, &existing)?;
recovered_datacap += existing.size.0;
}

st.save_allocs(&mut allocs)?;
Expand Down Expand Up @@ -426,7 +436,7 @@ impl Actor {
};

let inserted = claims
.put_if_absent(provider, claim_alloc.allocation_id, new_claim)
.put_if_absent(provider, claim_alloc.allocation_id, new_claim.clone())
.context_code(
ExitCode::USR_ILLEGAL_STATE,
format!("failed to write claim {}", claim_alloc.allocation_id),
Expand All @@ -440,6 +450,7 @@ impl Actor {
sector_claims.push(SectorAllocationClaimResult::default());
continue;
}
Emit::claim(rt, claim_alloc.allocation_id, &new_claim)?;

allocs.remove(claim_alloc.client, claim_alloc.allocation_id).context_code(
ExitCode::USR_ILLEGAL_STATE,
Expand Down Expand Up @@ -547,11 +558,12 @@ impl Actor {
}

let new_claim = Claim { term_max: term.term_max, ..*claim };
st_claims.put(term.provider, term.claim_id, new_claim).context_code(
st_claims.put(term.provider, term.claim_id, new_claim.clone()).context_code(
ExitCode::USR_ILLEGAL_STATE,
"HAMT put failure storing new claims",
)?;
batch_gen.add_success();
Emit::claim_updated(rt, term.claim_id, &new_claim)?;
} else {
batch_gen.add_fail(ExitCode::USR_NOT_FOUND);
info!("no claim {} for provider {}", term.claim_id, term.provider);
Expand Down Expand Up @@ -595,10 +607,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),
)?;
let removed = claims
.remove(params.provider, id)
.context_code(
ExitCode::USR_ILLEGAL_STATE,
format!("failed to remove claim {}", id),
)?
// Unwrapping here as all paths should ensure the claim exists.
.unwrap();
Emit::claim_removed(rt, id, &removed)?;
}

st.save_claims(&mut claims)?;
Expand Down Expand Up @@ -695,8 +712,14 @@ 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, alloc) in ids.iter().zip(new_allocs.iter()) {
Emit::allocation(rt, *id, alloc)?;
}
st.put_claims(rt.store(), updated_claims.clone())?;
for (id, claim) in updated_claims {
Emit::claim_updated(rt, id, &claim)?;
}
Ok(ids)
})?;

Expand Down
Loading

0 comments on commit 74ae683

Please sign in to comment.