Skip to content

Commit

Permalink
Merge pull request #1859 from subspace/tx-fee
Browse files Browse the repository at this point in the history
Collect the domain transaction fee and use as the operator reward
  • Loading branch information
NingLin-P authored Aug 24, 2023
2 parents a65d460 + 92c4cdc commit fc18225
Show file tree
Hide file tree
Showing 13 changed files with 389 additions and 10 deletions.
15 changes: 15 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions domains/client/domain-operator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ domain-client-message-relayer = { version = "0.1.0", path = "../relayer" }
domain-test-service = { version = "0.1.0", path = "../../test/service" }
domain-test-primitives = { version = "0.1.0", path = "../../test/primitives" }
evm-domain-test-runtime = { version = "0.1.0", path = "../../test/runtime/evm" }
frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
num-traits = "0.2.15"
pallet-balances = { version = "4.0.0-dev", git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
pallet-domains = { version = "0.1.0", path = "../../../crates/pallet-domains" }
Expand Down
10 changes: 8 additions & 2 deletions domains/client/domain-operator/src/domain_block_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,13 @@ where
})?
};

// Get the accumulated transaction fee of all transactions included in the block
// and used as the operator reward
let total_rewards = self
.client
.runtime_api()
.block_transaction_fee(header_hash)?;

let execution_receipt = ExecutionReceipt {
domain_block_number: header_number,
domain_block_hash: header_hash,
Expand All @@ -363,8 +370,7 @@ where
final_state_root: state_root,
execution_trace: trace,
execution_trace_root: sp_core::H256(trace_root),
// TODO: set proper value
total_rewards: Default::default(),
total_rewards,
};

Ok(DomainBlockResult {
Expand Down
69 changes: 69 additions & 0 deletions domains/client/domain-operator/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1816,3 +1816,72 @@ async fn test_restart_domain_operator() {
assert_eq!(ferdie.client.info().best_number, 11);
assert_eq!(alice.client.info().best_number, 10);
}

#[substrate_test_utils::test(flavor = "multi_thread")]
async fn test_domain_transaction_fee_and_operator_reward() {
let directory = TempDir::new().expect("Must be able to create temporary directory");

let mut builder = sc_cli::LoggerBuilder::new("");
builder.with_colors(false);
let _ = builder.init();

let tokio_handle = tokio::runtime::Handle::current();

// Start Ferdie
let mut ferdie = MockConsensusNode::run(
tokio_handle.clone(),
Ferdie,
BasePath::new(directory.path().join("ferdie")),
);

// Produce 1 consensus block to initialize genesis domain
ferdie.produce_block_with_slot(1.into()).await.unwrap();

// Run Alice (a evm domain authority node)
let mut alice = domain_test_service::DomainNodeBuilder::new(
tokio_handle.clone(),
Alice,
BasePath::new(directory.path().join("alice")),
)
.build_evm_node(Role::Authority, GENESIS_DOMAIN_ID, &mut ferdie)
.await;

produce_blocks!(ferdie, alice, 3).await.unwrap();

// Construct and submit an extrinsic with tip
let pre_alice_free_balance = alice.free_balance(Alice.to_account_id());
let tip = 123456;
let tx = alice.construct_extrinsic_with_tip(
alice.account_nonce(),
tip,
frame_system::Call::remark { remark: vec![] },
);
alice
.send_extrinsic(tx)
.await
.expect("Failed to send extrinsic");

// Produce a bundle that contains the just sent extrinsic
let (slot, bundle) = ferdie.produce_slot_and_wait_for_bundle_submission().await;
assert_eq!(bundle.unwrap().extrinsics.len(), 1);
produce_block_with!(ferdie.produce_block_with_slot(slot), alice)
.await
.unwrap();
let consensus_block_hash = ferdie.client.info().best_hash;

// Produce one more bundle, this bundle should contains the ER of the previous bundle
let (slot, bundle) = ferdie.produce_slot_and_wait_for_bundle_submission().await;
let receipt = bundle.unwrap().into_receipt();
assert_eq!(receipt.consensus_block_hash, consensus_block_hash);
produce_block_with!(ferdie.produce_block_with_slot(slot), alice)
.await
.unwrap();

// Transaction fee (including the tip) is deducted from alice's account
let alice_free_balance_changes =
pre_alice_free_balance - alice.free_balance(Alice.to_account_id());
assert!(alice_free_balance_changes >= tip as u128);

// All the transaction fee is collected as operator reward
assert_eq!(alice_free_balance_changes, receipt.total_rewards);
}
32 changes: 32 additions & 0 deletions domains/pallets/operator-rewards/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "pallet-operator-rewards"
version = "0.1.0"
authors = ["Subspace Labs <https://subspace.network>"]
edition = "2021"
license = "Apache-2.0"
homepage = "https://subspace.network"
repository = "https://github.com/subspace/subspace"
description = "Subspace node pallet for charging and re-distributing domain transaction fees"
include = [
"/src",
"/Cargo.toml",
]

[dependencies]
codec = { package = "parity-scale-codec", version = "3.6.3", default-features = false, features = ["derive"] }
frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
scale-info = { version = "2.7.0", default-features = false, features = ["derive"] }
sp-runtime = { version = "24.0.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
sp-std = { version = "8.0.0", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }

[features]
default = ["std"]
std = [
"codec/std",
"frame-support/std",
"frame-system/std",
"scale-info/std",
"sp-runtime/std",
"sp-std/std",
]
75 changes: 75 additions & 0 deletions domains/pallets/operator-rewards/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Copyright (C) 2023 Subspace Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Pallet Domain Transaction Fees

#![cfg_attr(not(feature = "std"), no_std)]

pub use pallet::*;

#[frame_support::pallet]
mod pallet {
use codec::{Codec, MaxEncodedLen};
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use scale_info::TypeInfo;
use sp_runtime::traits::{AtLeast32BitUnsigned, MaybeSerializeDeserialize, Saturating, Zero};
use sp_runtime::FixedPointOperand;
use sp_std::fmt::Debug;

#[pallet::config]
pub trait Config: frame_system::Config {
/// The balance of an account.
type Balance: Parameter
+ Member
+ AtLeast32BitUnsigned
+ Codec
+ Default
+ Copy
+ MaybeSerializeDeserialize
+ Debug
+ MaxEncodedLen
+ TypeInfo
+ FixedPointOperand;
}

/// The accumulated rewards of the current block
///
/// Currently, the only source of rewards is the transaction fees, in the furture it
/// will include the XDM reward.
#[pallet::storage]
#[pallet::getter(fn block_transaction_fee)]
pub(super) type BlockRewards<T: Config> = StorageValue<_, T::Balance, ValueQuery>;

/// Pallet operator-rewards to store the accumulated rewards of the current block
#[pallet::pallet]
#[pallet::without_storage_info]
pub struct Pallet<T>(_);

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(_now: BlockNumberFor<T>) -> Weight {
BlockRewards::<T>::set(Zero::zero());
T::DbWeight::get().writes(1)
}
}

impl<T: Config> Pallet<T> {
pub fn note_transaction_fees(tx_fee: T::Balance) {
let next_block_rewards = BlockRewards::<T>::get().saturating_add(tx_fee);
BlockRewards::<T>::set(next_block_rewards);
}
}
}
3 changes: 3 additions & 0 deletions domains/primitives/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ sp_api::decl_runtime_apis! {

/// Return the extrinsic weight
fn extrinsic_weight(ext: &Block::Extrinsic) -> Weight;

/// The accumulated transaction fee of all transactions included in the block
fn block_transaction_fee() -> Balance;
}

/// Api that construct inherent extrinsics.
Expand Down
2 changes: 2 additions & 0 deletions domains/runtime/evm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ log = { version = "0.4.19", default-features = false }
pallet-balances = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/substrate", rev = "55c157cff49b638a59d81a9f971f0f9a66829c71" }
pallet-base-fee = { version = "1.0.0-dev", default-features = false, git = "https://github.com/subspace/frontier", rev = "74483666645e121c0c5e6616f43fdfd8664ea0d3" }
pallet-domain-id = { version = "0.1.0", path = "../../pallets/domain-id", default-features = false }
pallet-operator-rewards = { version = "0.1.0", path = "../../pallets/operator-rewards", default-features = false }
pallet-ethereum = { version = "4.0.0-dev", default-features = false, git = "https://github.com/subspace/frontier", rev = "74483666645e121c0c5e6616f43fdfd8664ea0d3" }
pallet-evm = { version = "6.0.0-dev", default-features = false, git = "https://github.com/subspace/frontier", rev = "74483666645e121c0c5e6616f43fdfd8664ea0d3" }
pallet-evm-chain-id = { version = "1.0.0-dev", default-features = false, git = "https://github.com/subspace/frontier", rev = "74483666645e121c0c5e6616f43fdfd8664ea0d3" }
Expand Down Expand Up @@ -85,6 +86,7 @@ std = [
"pallet-balances/std",
"pallet-base-fee/std",
"pallet-domain-id/std",
"pallet-operator-rewards/std",
"pallet-ethereum/std",
"pallet-evm/std",
"pallet-evm-chain-id/std",
Expand Down
Loading

0 comments on commit fc18225

Please sign in to comment.