Skip to content

Commit

Permalink
track transfers in/out for each domain at the time of instantiation a…
Browse files Browse the repository at this point in the history
…nd ER confirmation
  • Loading branch information
vedhavyas committed Feb 12, 2024
1 parent b4336ed commit f603979
Show file tree
Hide file tree
Showing 10 changed files with 188 additions and 34 deletions.
36 changes: 30 additions & 6 deletions crates/pallet-domains/src/block_tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ use frame_support::{ensure, PalletError};
use scale_info::TypeInfo;
use sp_core::Get;
use sp_domains::merkle_tree::MerkleTree;
use sp_domains::{ConfirmedDomainBlock, DomainId, ExecutionReceipt, OperatorId};
use sp_runtime::traits::{BlockNumberProvider, CheckedSub, One, Saturating, Zero};
use sp_domains::{
ConfirmedDomainBlock, DomainId, DomainsTransfersTracker, ExecutionReceipt, OperatorId,
};
use sp_runtime::traits::{BlockNumberProvider, CheckedAdd, CheckedSub, One, Saturating, Zero};
use sp_std::cmp::Ordering;
use sp_std::collections::btree_map::BTreeMap;
use sp_std::vec::Vec;
Expand All @@ -34,6 +36,8 @@ pub enum Error {
InvalidExecutionTrace,
UnavailableConsensusBlockHash,
InvalidStateRoot,
BalanceOverflow,
DomainTransfersTracking,
}

#[derive(TypeInfo, Debug, Encode, Decode, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -344,6 +348,26 @@ pub(crate) fn process_execution_receipt<T: Config>(
execution_receipt.consensus_block_number,
);

// tracking the transfer
// 1. Block fees are burned on domain, so it is considered transferred out
// 2. XDM transfers from the Domain
// 3. XDM transfers into the domain
let transfer_out_balance = execution_receipt
.block_fees
.total_fees()
.and_then(|total| total.checked_add(&execution_receipt.transfers.transfers_out))
.ok_or(Error::BalanceOverflow)?;

// track the transfers out and then track transfers in
T::DomainsTransfersTracker::transfer_out(domain_id, transfer_out_balance)
.map_err(|_| Error::DomainTransfersTracking)?;

T::DomainsTransfersTracker::transfer_in(
domain_id,
execution_receipt.transfers.transfers_in,
)
.map_err(|_| Error::DomainTransfersTracking)?;

LatestConfirmedDomainBlock::<T>::insert(
domain_id,
ConfirmedDomainBlock {
Expand Down Expand Up @@ -371,8 +395,8 @@ pub(crate) fn process_execution_receipt<T: Config>(
let er_hash = execution_receipt.hash::<DomainHashingFor<T>>();
BlockTreeNodes::<T>::mutate(er_hash, |maybe_node| {
let node = maybe_node.as_mut().expect(
"The domain block of `CurrentHead` receipt is checked to be exist in `execution_receipt_type`; qed"
);
"The domain block of `CurrentHead` receipt is checked to be exist in `execution_receipt_type`; qed"
);
node.operator_ids.push(submitter);
});
}
Expand Down Expand Up @@ -687,7 +711,7 @@ mod tests {
H256::random(),
stale_receipt,
);
assert!(crate::Pallet::<Test>::submit_bundle(RawOrigin::None.into(), bundle,).is_err());
assert!(crate::Pallet::<Test>::submit_bundle(RawOrigin::None.into(), bundle).is_err());

assert_eq!(
BlockTreeNodes::<Test>::get(stale_receipt_hash)
Expand Down Expand Up @@ -735,7 +759,7 @@ mod tests {
H256::random(),
previous_head_receipt,
);
assert!(crate::Pallet::<Test>::submit_bundle(RawOrigin::None.into(), bundle,).is_err());
assert!(crate::Pallet::<Test>::submit_bundle(RawOrigin::None.into(), bundle).is_err());
});
}

Expand Down
55 changes: 49 additions & 6 deletions crates/pallet-domains/src/domain_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,16 @@ use crate::{
use alloc::string::String;
use codec::{Decode, Encode};
use domain_runtime_primitives::MultiAccountId;
use frame_support::traits::fungible::{Inspect, MutateHold};
use frame_support::traits::tokens::{Fortitude, Preservation};
use frame_support::traits::fungible::{Inspect, Mutate, MutateHold};
use frame_support::traits::tokens::{Fortitude, Precision, Preservation};
use frame_support::weights::Weight;
use frame_support::{ensure, PalletError};
use frame_system::pallet_prelude::*;
use scale_info::TypeInfo;
use sp_core::Get;
use sp_domains::{
derive_domain_block_hash, DomainId, DomainsDigestItem, OperatorAllowList, RuntimeId,
RuntimeType,
derive_domain_block_hash, DomainId, DomainsDigestItem, DomainsTransfersTracker,
OperatorAllowList, RuntimeId, RuntimeType,
};
use sp_runtime::traits::{CheckedAdd, Zero};
use sp_runtime::DigestItem;
Expand All @@ -44,6 +44,8 @@ pub enum Error {
FailedToGenerateGenesisStateRoot,
DomainNotFound,
NotDomainOwner,
InitialBalanceOverflow,
TransfersTracker,
FailedToGenerateRawGenesis(crate::runtime_registry::Error),
}

Expand All @@ -68,6 +70,20 @@ pub struct DomainConfig<AccountId: Ord, Balance> {
pub initial_balances: Vec<(MultiAccountId, Balance)>,
}

impl<AccountId, Balance> DomainConfig<AccountId, Balance>
where
AccountId: Ord,
Balance: Zero + CheckedAdd,
{
pub(crate) fn total_issuance(&self) -> Option<Balance> {
self.initial_balances
.iter()
.try_fold(Balance::zero(), |total, (_, balance)| {
total.checked_add(balance)
})
}
}

#[derive(TypeInfo, Debug, Encode, Decode, Clone, PartialEq, Eq)]
pub struct DomainObject<Number, ReceiptHash, AccountId: Ord, Balance> {
/// The address of the domain creator, used to validate updating the domain config.
Expand Down Expand Up @@ -146,13 +162,29 @@ pub(crate) fn do_instantiate_domain<T: Config>(
}
};

// TODO: burn the total initial balance for domain from the domain owner account
// burn total issuance on domain from owners account and track the domain balance
let total_issuance = domain_config
.total_issuance()
.ok_or(Error::InitialBalanceOverflow)?;

T::Currency::burn_from(
&owner_account_id,
total_issuance,
Precision::Exact,
Fortitude::Polite,
)
.map_err(|_| Error::InsufficientFund)?;

T::DomainsTransfersTracker::transfer_in(domain_id, total_issuance)
.map_err(|_| Error::TransfersTracker)?;

let genesis_receipt = {
let state_version = runtime_obj.version.state_version();
let raw_genesis = runtime_obj
.into_complete_raw_genesis::<T>(
domain_id,
domain_runtime_info,
total_issuance,
domain_config.initial_balances.clone(),
)
.map_err(Error::FailedToGenerateRawGenesis)?;
Expand Down Expand Up @@ -443,7 +475,9 @@ mod tests {
Balances::make_free_balance_be(
&creator,
<Test as Config>::DomainInstantiationDeposit::get()
+ <Test as pallet_balances::Config>::ExistentialDeposit::get(),
// for domain total issuance
+ 1_000_000 * SSC
+ <Test as pallet_balances::Config>::ExistentialDeposit::get(),
);

// should fail due to invalid account ID type
Expand All @@ -461,6 +495,15 @@ mod tests {
1_000_000 * SSC,
)];

// Set enough fund to creator
Balances::make_free_balance_be(
&creator,
<Test as Config>::DomainInstantiationDeposit::get()
// for domain total issuance
+ 1_000_000 * SSC
+ <Test as pallet_balances::Config>::ExistentialDeposit::get(),
);

// should be successful
let domain_id =
do_instantiate_domain::<Test>(domain_config.clone(), creator, created_at).unwrap();
Expand Down
10 changes: 8 additions & 2 deletions crates/pallet-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ mod pallet {
use sp_core::H256;
use sp_domains::bundle_producer_election::ProofOfElectionError;
use sp_domains::{
BundleDigest, ConfirmedDomainBlock, DomainId, EpochIndex, GenesisDomain, OperatorAllowList,
OperatorId, OperatorPublicKey, RuntimeId, RuntimeType,
BundleDigest, ConfirmedDomainBlock, DomainId, DomainsTransfersTracker, EpochIndex,
GenesisDomain, OperatorAllowList, OperatorId, OperatorPublicKey, RuntimeId, RuntimeType,
};
use sp_domains_fraud_proof::fraud_proof::FraudProof;
use sp_domains_fraud_proof::InvalidTransactionCode;
Expand Down Expand Up @@ -311,6 +311,9 @@ mod pallet {

/// Storage fee interface used to deal with bundle storage fee
type StorageFee: StorageFee<BalanceOf<Self>>;

/// Transfers tracker.
type DomainsTransfersTracker: DomainsTransfersTracker<BalanceOf<Self>>;
}

#[pallet::pallet]
Expand All @@ -333,6 +336,7 @@ mod pallet {

/// Starting EVM chain ID for evm runtimes.
pub struct StartingEVMChainId;

impl Get<EVMChainId> for StartingEVMChainId {
fn get() -> EVMChainId {
// after looking at `https://chainlist.org/?testnets=false`
Expand Down Expand Up @@ -1497,10 +1501,12 @@ impl<T: Config> Pallet<T> {
let domain_obj = DomainRegistry::<T>::get(domain_id)?;
let runtime_object = RuntimeRegistry::<T>::get(domain_obj.domain_config.runtime_id)?;
let runtime_type = runtime_object.runtime_type.clone();
let total_issuance = domain_obj.domain_config.total_issuance()?;
let raw_genesis = runtime_object
.into_complete_raw_genesis::<T>(
domain_id,
domain_obj.domain_runtime_info,
total_issuance,
domain_obj.domain_config.initial_balances,
)
.ok()?;
Expand Down
24 changes: 9 additions & 15 deletions crates/pallet-domains/src/runtime_registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ pub enum Error {
MaxScheduledBlockNumber,
FailedToDecodeRawGenesis,
RuntimeCodeNotFoundInRawGenesis,
InitialBalanceOverflow,
InvalidAccountIdType,
}

Expand Down Expand Up @@ -62,19 +61,11 @@ impl Default for DomainRuntimeInfo {
}

fn derive_initial_balances_storages<T: Config, AccountId: Encode>(
total_issuance: BalanceOf<T>,
balances: BTreeMap<AccountId, BalanceOf<T>>,
) -> Result<Vec<(StorageKey, StorageData)>, Error> {
let mut initial_storages = vec![];
let total_balance = balances
.iter()
.try_fold(BalanceOf::<T>::zero(), |total, (_, balance)| {
total.checked_add(balance)
})
.ok_or(Error::InitialBalanceOverflow)?;

) -> Vec<(StorageKey, StorageData)> {
let total_issuance_key = sp_domains::domain_total_issuance_storage_key();
initial_storages.push((total_issuance_key, StorageData(total_balance.encode())));

let mut initial_storages = vec![(total_issuance_key, StorageData(total_issuance.encode()))];
for (account_id, balance) in balances {
let account_storage_key = sp_domains::domain_account_storage_key(account_id);
let account_info = AccountInfo {
Expand All @@ -91,7 +82,7 @@ fn derive_initial_balances_storages<T: Config, AccountId: Encode>(
initial_storages.push((account_storage_key, StorageData(account_info.encode())))
}

Ok(initial_storages)
initial_storages
}

impl<Number, Hash> RuntimeObject<Number, Hash> {
Expand All @@ -100,6 +91,7 @@ impl<Number, Hash> RuntimeObject<Number, Hash> {
self,
domain_id: DomainId,
domain_runtime_info: DomainRuntimeInfo,
total_issuance: BalanceOf<T>,
initial_balances: Vec<(MultiAccountId, BalanceOf<T>)>,
) -> Result<RawGenesis, Error> {
let RuntimeObject {
Expand Down Expand Up @@ -128,8 +120,10 @@ impl<Number, Hash> RuntimeObject<Number, Hash> {
},
)
.ok_or(Error::InvalidAccountIdType)?;
raw_genesis
.set_top_storages(derive_initial_balances_storages::<T, _>(initial_balances)?);
raw_genesis.set_top_storages(derive_initial_balances_storages::<T, _>(
total_issuance,
initial_balances,
));
}
}

Expand Down
23 changes: 23 additions & 0 deletions crates/pallet-domains/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ frame_support::construct_runtime!(
type BlockNumber = u64;
type Hash = H256;
type AccountId = u128;

impl frame_system::Config for Test {
type BaseCallFilter = frame_support::traits::Everything;
type BlockWeights = ();
Expand Down Expand Up @@ -207,6 +208,7 @@ impl frame_support::traits::Randomness<Hash, BlockNumber> for MockRandomness {
}

const SLOT_DURATION: u64 = 1000;

impl pallet_timestamp::Config for Test {
/// A timestamp: milliseconds since the unix epoch.
type Moment = Moment;
Expand All @@ -216,13 +218,32 @@ impl pallet_timestamp::Config for Test {
}

pub struct DummyStorageFee;

impl StorageFee<Balance> for DummyStorageFee {
fn transaction_byte_fee() -> Balance {
SSC
}
fn note_storage_fees(_fee: Balance) {}
}

pub struct MockDomainsTransfersTracker;

impl sp_domains::DomainsTransfersTracker<Balance> for MockDomainsTransfersTracker {
type Error = ();

fn balance_on_domain(_domain_id: DomainId) -> Result<Balance, Self::Error> {
Ok(Default::default())
}

fn transfer_in(_domain_id: DomainId, _amount: Balance) -> Result<(), Self::Error> {
Ok(())
}

fn transfer_out(_domain_id: DomainId, _amount: Balance) -> Result<(), Self::Error> {
Ok(())
}
}

impl pallet_domains::Config for Test {
type RuntimeEvent = RuntimeEvent;
type DomainHash = sp_core::H256;
Expand Down Expand Up @@ -252,9 +273,11 @@ impl pallet_domains::Config for Test {
type SudoId = ();
type PalletId = DomainsPalletId;
type StorageFee = DummyStorageFee;
type DomainsTransfersTracker = MockDomainsTransfersTracker;
}

pub struct ExtrinsicStorageFees;

impl domain_pallet_executive::ExtrinsicStorageFees<Test> for ExtrinsicStorageFees {
fn extract_signer(_xt: MockUncheckedExtrinsic<Test>) -> (Option<AccountId>, DispatchInfo) {
(None, DispatchInfo::default())
Expand Down
10 changes: 9 additions & 1 deletion crates/sp-domains/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,14 @@ pub struct BundleDigest<Hash> {
pub size: u32,
}

#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone, Default)]
pub struct Transfers<Balance> {
/// Total transfers that came into the domain.
pub transfers_in: Balance,
/// Total transfers that went out of the domain.
pub transfers_out: Balance,
}

/// Receipt of a domain block execution.
#[derive(Debug, Decode, Encode, TypeInfo, PartialEq, Eq, Clone)]
pub struct ExecutionReceipt<Number, Hash, DomainNumber, DomainHash, Balance> {
Expand Down Expand Up @@ -487,7 +495,7 @@ pub struct ExecutionReceipt<Number, Hash, DomainNumber, DomainHash, Balance> {
/// storage fees are given to the consensus block author.
pub block_fees: BlockFees<Balance>,
/// List of transfers from this Domain to other chains
pub transfers: BTreeMap<ChainId, Balance>,
pub transfers: Transfers<Balance>,
}

impl<Number, Hash, DomainNumber, DomainHash, Balance>
Expand Down
1 change: 1 addition & 0 deletions crates/subspace-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,7 @@ impl pallet_domains::Config for Runtime {
type SudoId = SudoId;
type PalletId = DomainsPalletId;
type StorageFee = TransactionFees;
type DomainsTransfersTracker = Transporter;
}

parameter_types! {
Expand Down
Loading

0 comments on commit f603979

Please sign in to comment.