Skip to content

Commit

Permalink
[Fix] Use frc46_token crate across the board, fix Lotus compat layer. (
Browse files Browse the repository at this point in the history
  • Loading branch information
ruseinov authored Feb 19, 2024
1 parent bd07a59 commit cd20654
Show file tree
Hide file tree
Showing 9 changed files with 32 additions and 101 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions actors/datacap/src/v10/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
use fvm_ipld_encoding::tuple::*;
use fvm_shared3::address::Address;

use fil_actors_shared::frc46_token;
use frc46_token::token;

#[derive(Debug, Serialize_tuple, Deserialize_tuple)]
pub struct State {
pub governor: Address,
pub token: frc46_token::TokenState,
pub token: token::state::TokenState,
}
5 changes: 2 additions & 3 deletions actors/datacap/src/v11/state.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// Copyright 2019-2022 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use frc46_token::token;
use fvm_ipld_encoding::tuple::*;
use fvm_shared3::address::Address;

use fil_actors_shared::frc46_token;

#[derive(Debug, Serialize_tuple, Deserialize_tuple)]
pub struct State {
pub governor: Address,
pub token: frc46_token::TokenState,
pub token: token::state::TokenState,
}
4 changes: 2 additions & 2 deletions actors/datacap/src/v12/state.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// Copyright 2019-2022 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use fil_actors_shared::frc46_token;
use frc46_token::token;
use fvm_ipld_encoding::tuple::*;
use fvm_shared4::address::Address;

#[derive(Serialize_tuple, Deserialize_tuple, Debug)]
pub struct State {
pub governor: Address,
pub token: frc46_token::TokenState,
pub token: token::state::TokenState,
}
5 changes: 2 additions & 3 deletions actors/datacap/src/v9/state.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
// Copyright 2019-2022 ChainSafe Systems
// SPDX-License-Identifier: Apache-2.0, MIT

use frc46_token::token;
use fvm_ipld_encoding::tuple::*;
use fvm_shared::address::Address;

use fil_actors_shared::frc46_token;

#[derive(Debug, Serialize_tuple, Deserialize_tuple)]
pub struct State {
pub governor: Address,
pub token: frc46_token::TokenState,
pub token: token::state::TokenState,
}
14 changes: 6 additions & 8 deletions fil_actor_interface/src/builtin/datacap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use anyhow::{anyhow, Context};
use cid::Cid;
use fil_actor_datacap_state::v12::DATACAP_GRANULARITY;
use fil_actors_shared::ext::TokenStateExt;
use fvm_ipld_blockstore::Blockstore;
use fvm_shared::address::{Address, Payload};
use num::traits::Euclid;
Expand Down Expand Up @@ -82,6 +83,7 @@ impl State {
Err(anyhow::anyhow!("Unknown datacap actor code {}", code))
}

// NOTE: This code currently mimics that of Lotus and is only used for RPC compatibility.
pub fn verified_client_data_cap<BS>(
&self,
store: &BS,
Expand All @@ -96,14 +98,10 @@ impl State {
}?;

let int = match self {
State::V9(state) => state.token.get_balance(store, id),
State::V11(state) => state.token.get_balance(store, id),
State::V12(state) => state.token.get_balance(store, id),
State::V13(state) => state
.token
.get_balance(store, id)
.map(|balance| Some(crate::convert::from_token_v4_to_v3(balance)))
.map_err(|e| e.to_string().into()),
State::V9(state) => state.token.get_balance_opt(store, id),
State::V11(state) => state.token.get_balance_opt(store, id),
State::V12(state) => state.token.get_balance_opt(store, id),
State::V13(state) => state.token.get_balance_opt(store, id),
_ => return Err(anyhow!("not supported in actors > v8")),
}?;
Ok(int
Expand Down
4 changes: 0 additions & 4 deletions fil_actor_interface/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,6 @@ pub fn from_token_v4_to_v2(token: TokenAmountV4) -> TokenAmountV2 {
TokenAmountV2::from_atto(token.atto().clone())
}

pub fn from_token_v4_to_v3(token: TokenAmountV4) -> TokenAmountV3 {
TokenAmountV3::from_atto(token.atto().clone())
}

pub fn from_token_v2_to_v3(token: TokenAmountV2) -> TokenAmountV3 {
TokenAmountV3::from_atto(token.atto().clone())
}
Expand Down
1 change: 1 addition & 0 deletions fil_actors_shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ keywords.workspace = true
anyhow = { workspace = true }
cid = { workspace = true }
filecoin-proofs-api = { version = "16", default-features = false }
frc46_token = { workspace = true }
fvm_ipld_amt = { workspace = true }
fvm_ipld_bitfield = { workspace = true }
fvm_ipld_blockstore = { workspace = true }
Expand Down
95 changes: 16 additions & 79 deletions fil_actors_shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,96 +18,33 @@ pub extern crate fvm_ipld_hamt;
pub extern crate fvm_shared as fvm_shared2;
pub extern crate fvm_shared3;

use fvm_ipld_hamt::BytesKey;
use fvm_shared4::ActorID;
use integer_encoding::VarInt;

// code copied from `frc46_token`
pub mod frc46_token {
use crate::actor_id_key;
use cid::Cid;
pub mod ext {
use frc46_token::token::state::{actor_id_key, StateError, TokenState};
use fvm_ipld_blockstore::Blockstore;
use fvm_ipld_encoding::tuple::*;
use fvm_ipld_hamt::Hamt;
use fvm_ipld_hamt::{BytesKey, Error as HamtError};
use fvm_shared3::econ::TokenAmount;
use fvm_shared4::econ::TokenAmount;
use fvm_shared4::ActorID;

type Map<'bs, BS, K, V> = Hamt<&'bs BS, V, K>;
type BalanceMap<'bs, BS> = Map<'bs, BS, BytesKey, TokenAmount>;
type AllowanceMap<'bs, BS> = Map<'bs, BS, BytesKey, Cid>;

type Result<T> = std::result::Result<T, HamtError>;
type Result<T> = std::result::Result<T, StateError>;

/// This value has been chosen to optimise to reduce gas-costs when accessing the balances map. Non-
/// standard use cases of the token library might find a different value to be more efficient.
pub const DEFAULT_HAMT_BIT_WIDTH: u32 = 3;

/// An abstraction over the IPLD layer to get and modify token state without dealing with HAMTs etc.
///
/// This is a simple wrapper of state and in general does not account for token protocol level
/// checks such as ensuring necessary approvals are enforced during transfers. This is left for the
/// caller to handle. However, some invariants such as non-negative balances, allowances and total
/// supply are enforced.
#[derive(Serialize_tuple, Deserialize_tuple, PartialEq, Eq, Clone, Debug)]
pub struct TokenState {
/// Total supply of token
pub supply: TokenAmount,
/// Map<ActorId, TokenAmount> of balances as a Hamt
pub balances: Cid,
/// Map<ActorId, Map<ActorId, TokenAmount>> as a Hamt. Allowances are stored balances[owner][operator]
pub allowances: Cid,
/// Bit-width to use when loading Hamts
hamt_bit_width: u32,
/// Lotus compatibility layer.
pub trait TokenStateExt {
fn get_balance_opt<BS: Blockstore>(
&self,
bs: &BS,
owner: ActorID,
) -> Result<Option<TokenAmount>>;
}

impl TokenState {
/// Create a new token state-tree, without committing it (the root cid) to a blockstore
pub fn new<BS: Blockstore>(store: &BS) -> Result<Self> {
Self::new_with_bit_width(store, DEFAULT_HAMT_BIT_WIDTH)
}

/// Create a new token state-tree, without committing it (the root cid) to a blockstore
///
/// Explicitly sets the bit width of underlying Hamt structures. Caller must ensure
/// 1 <= hamt_bit_width <= 8.
pub fn new_with_bit_width<BS: Blockstore>(store: &BS, hamt_bit_width: u32) -> Result<Self> {
// Blockstore is still needed to create valid Cids for the Hamts
let empty_balance_map =
BalanceMap::new_with_bit_width(store, hamt_bit_width).flush()?;
let empty_allowances_map =
AllowanceMap::new_with_bit_width(store, hamt_bit_width).flush()?;

Ok(Self {
supply: Default::default(),
balances: empty_balance_map,
allowances: empty_allowances_map,
hamt_bit_width,
})
}

/// Get the balance of an ActorID from the currently stored state
pub fn get_balance<BS: Blockstore>(
impl TokenStateExt for TokenState {
fn get_balance_opt<BS: Blockstore>(
&self,
bs: &BS,
owner: ActorID,
) -> Result<Option<TokenAmount>> {
let balances = self.get_balance_map(bs)?;
balances
.get(&actor_id_key(owner))
.map(|amount_opt| amount_opt.map(|opt| opt.to_owned()))
}

/// Retrieve the balance map as a HAMT
pub fn get_balance_map<'bs, BS: Blockstore>(
&self,
bs: &'bs BS,
) -> Result<BalanceMap<'bs, BS>> {
BalanceMap::load_with_bit_width(&self.balances, bs, self.hamt_bit_width)
Ok(balances
.get(&actor_id_key(owner))?
.map(|amount_opt| amount_opt.to_owned()))
}
}
}

pub fn actor_id_key(a: ActorID) -> BytesKey {
a.encode_var_vec().into()
}

0 comments on commit cd20654

Please sign in to comment.