Rust区块链治理模块pallet-society的使用,实现去中心化社交网络与成员激励机制
Rust区块链治理模块pallet-society的使用,实现去中心化社交网络与成员激励机制
Society模块概述
Society模块是一个经济游戏,它激励用户参与并维护一个会员制社会。
用户类型
在任何时候,社会中的用户可以是以下类型之一:
- 投标者(Bidder) - 已提交加入社会意向的用户
- 候选人(Candidate) - 将被投票表决是否加入社会的用户
- 被暂停的候选人(Suspended Candidate) - 未能赢得投票的用户
- 成员(Member) - 社会的成员用户
- 被暂停的成员(Suspended Member) - 积累了太多惩罚或未能通过成员资格挑战的成员
在非暂停成员中,总是有:
- 首领(Head) - 免于暂停的成员
- 辩护者(Defender) - 成员资格受到质疑并需要再次投票表决的成员
工作机制
奖励
成员通过社会金库支付的奖励来激励参与。这些支付有成熟期,用户必须等待才能访问资金。
惩罚
成员可以被惩罚,通过削减他们未领取的奖励支付。此外,成员可以积累"惩罚",当达到最大惩罚限制时,他们会被暂停。
质疑者
在投票期间,随机选择一组成员作为"质疑者"。这些质疑者需要对当前候选人进行投票。如果他们不投票,他们的质疑者状态被视为拒绝投票,成员被视为"懒惰",并每次未投票都会获得一次惩罚。
成员资格挑战
每个挑战轮换期,随机选择一个现有成员来捍卫他们在社会中的成员资格。然后,其他成员可以投票决定这个辩护者是否应该留在社会中。简单多数票决定用户的结果。
社会金库
会员社会由一个独立的金库资助,由该模块管理。这个金库的一部分被放入社会资金池,用于确定接受的投标数量。
增长率
会员社会可以以每个轮换期最多10个被接受的候选人的速度增长,直到达到最大成员阈值。一旦达到这个阈值,候选人选择就会停滞,直到有新成员加入的空间。
用户生命周期
用户可以通过以下阶段:
+-------> User <----------+
| + |
| | |
+----------------------------------------------+
| | | | |
| | v | |
| | Bidder <-----------+ |
| | + | |
| | | + |
| | v Suspended |
| | Candidate +----> Candidate |
| | + + |
| | | | |
| + | | |
| Suspended +-------+ | |
| Member | | |
| ^ | | |
| | v | |
| +-------+ Member <----------+ |
| |
| |
+------------------Society---------------------+
接口
可调度函数
普通用户
bid
- 用户可以通过预留押金来投标加入会员社会unbid
- 用户可以撤回他们的加入投标,押金将被退还
成员
vouch
- 成员可以代表用户投标加入会员社会unvouch
- 成员可以撤销他们对用户的担保vote
- 成员可以投票批准或拒绝候选人加入社会的请求defender_vote
- 成员可以投票批准或拒绝辩护者继续会员资格payout
- 成员可以领取他们第一个成熟的支付unfound
- 允许创始人在他们是唯一成员时解散社会
超级用户
found
- 创始人来源可以初始化这个社会judge_suspended_member
- 暂停判决来源能够对暂停成员做出判决judge_suspended_candidate
- 暂停判决来源能够对暂停候选人做出判决set_max_membership
- ROOT来源可以更新社会的最大成员数
完整示例代码
// 1. 添加依赖到Cargo.toml
// pallet-society = "42.0.0"
// 2. 示例代码
use frame_support::{decl_module, decl_event, decl_storage, dispatch::DispatchResult, ensure};
use frame_system::{self as system, ensure_signed};
use sp_runtime::traits::{Hash, Zero};
use pallet_society::{self as society, Trait as SocietyTrait};
pub trait Trait: SocietyTrait + system::Trait {
type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
}
decl_event! {
pub enum Event<T> where AccountId = <T as system::Trait>::AccountId {
/// 新成员加入
NewMember(AccountId),
/// 成员被暂停
MemberSuspended(AccountId),
}
}
decl_storage! {
trait Store for Module<T: Trait> as SocietyModule {
/// 社交网络成员计数
MemberCount get(fn member_count): u32;
}
}
decl_module! {
pub struct Module<T: Trait> for enum Call where origin: T::Origin {
fn deposit_event() = default;
/// 加入社交网络
#[weight = 10_000]
pub fn join_society(origin) -> DispatchResult {
let who = ensure_signed(origin)?;
// 投标加入社会
<society::Module<T>>::bid(RawOrigin::Signed(who.clone()).into(), Default::default())?;
Ok(())
}
/// 投票赞成候选人
#[weight = 10_000]
pub fn vote_candidate(origin, candidate: T::AccountId, approve: bool) -> DispatchResult {
let who = ensure_signed(origin)?;
// 确保调用者是成员
ensure!(<society::Module<T>>::is_member(&who), "Only members can vote");
// 投票
<society::Module<T>>::vote(RawOrigin::Signed(who).into(), candidate, approve)?;
Ok(())
}
/// 领取奖励
#[weight = 10_000]
pub fn claim_reward(origin) -> DispatchResult {
let who = ensure_signed(origin)?;
// 确保调用者是成员
ensure!(<society::Module<T>>::is_member(&who), "Only members can claim rewards");
// 领取支付
<society::Module<T>>::payout(RawOrigin::Signed(who).into())?;
Ok(())
}
}
}
// 实现社会事件处理
impl<T: Trait> society::OnSocietyEvent<T::AccountId> for Module<T> {
fn on_new_member(member: &T::AccountId) {
MemberCount::mutate(|count| *count += 1);
Self::deposit_event(RawEvent::NewMember(member.clone()));
}
fn on_suspended_member(member: &T::AccountId) {
MemberCount::mutate(|count| *count -= 1);
Self::deposit_event(RawEvent::MemberSuspended(member.clone()));
}
}
这个示例展示了如何使用pallet-society构建一个去中心化的社交网络:
- 用户可以通过
join_society
函数投标加入网络 - 现有成员可以通过
vote_candidate
函数投票决定新成员 - 成员可以通过
claim_reward
函数领取他们的奖励 - 实现了事件处理来跟踪成员变化
要使用这个模块,你还需要配置runtime并集成到你的区块链中。这个示例提供了基本功能,可以根据需要扩展更多治理功能。
以下是基于您提供的内容整理的完整示例代码,展示了如何使用pallet-society
实现去中心化社交网络与成员激励机制:
// runtime/src/lib.rs
// 1. 集成pallet-society到runtime
impl pallet_society::Config for Runtime {
type Event = Event;
type Currency = Balances; // 使用Balances作为货币类型
type Randomness = RandomnessCollectiveFlip; // 随机性来源
type CandidateDeposit = ConstU128<100>; // 候选人押金100
type WrongSideDeduction = ConstU128<10>; // 错误判断扣除10
type MaxStrikes = ConstU32<3>; // 最大惩罚次数3次
type PeriodSpend = ConstU128<1000>; // 周期支出限额1000
type MembershipChanged = (); // 成员变更回调
type RotationPeriod = ConstU32<7>; // 7个区块为1个周期
type MaxLockDuration = ConstU32<365>; // 最大锁定365天
type FounderSetOrigin = EnsureRoot<AccountId>; // 仅root可设置创始人
type SuspensionJudgementOrigin = EnsureRoot<AccountId>; // 仅root可暂停成员
}
// 2. 自定义社交网络pallet
#[frame_support::pallet]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
#[pallet::config]
pub trait Config: frame_system::Config + pallet_society::Config {
type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
}
#[pallet::event]
#[pallet::generate_deposit(pub(super) fn deposit_event)]
pub enum Event<T: Config> {
/// 成员发布了消息
MessagePosted(T::AccountId),
/// 成员等级提升
MemberPromoted(T::AccountId, u8),
}
#[pallet::storage]
#[pallet::getter(fn messages)]
pub(super) type Messages<T: Config> = StorageMap<
_,
Blake2_128Concat,
T::AccountId,
Vec<Vec<u8>>,
ValueQuery
>;
#[pallet::storage]
#[pallet::getter(fn member_rank)]
pub(super) type MemberRank<T: Config> = StorageMap<
_,
Blake2_128Concat,
T::AccountId,
u8,
ValueQuery
>;
#[pallet::call]
impl<T: Config> Pallet<T> {
/// 发布社交消息
#[pallet::weight(10_000)]
pub fn post_message(origin: OriginFor<T>, message: Vec<u8>) -> DispatchResult {
let who = ensure_signed(origin)?;
// 验证是否为成员
ensure!(
pallet_society::Members::<T>::contains_key(&who),
Error::<T>::NotMember
);
// 存储消息
Messages::<T>::append(&who, message);
// 奖励5个代币
T::Currency::deposit_creating(&who, 5u32.into());
// 触发事件
Self::deposit_event(Event::MessagePosted(who));
Ok(())
}
/// 提升成员等级
#[pallet::weight(5_000)]
pub fn promote_member(origin: OriginFor<T>, target: T::AccountId) -> DispatchResult {
ensure_root(origin)?;
// 获取当前等级
let current_rank = MemberRank::<T>::get(&target);
let new_rank = current_rank.saturating_add(1);
// 更新等级
MemberRank::<T>::insert(&target, new_rank);
// 奖励10个代币
T::Currency::deposit_creating(&target, 10u32.into());
Self::deposit_event(Event::MemberPromoted(target, new_rank));
Ok(())
}
}
}
// 3. 自定义奖励机制实现
impl<T: Config> OnReapAccount<T::AccountId> for Pallet<T> {
fn on_reap_account(who: &T::AccountId) {
// 检查是否是活跃成员
if pallet_society::Members::<T>::contains_key(who) {
// 根据活跃度和等级计算奖励
let rank = MemberRank::<T>::get(who);
let message_count = Messages::<T>::decode_len(who).unwrap_or(0);
let reward = (rank as u32 * 2 + message_count as u32).into();
// 发放奖励
let _ = T::Currency::deposit_creating(who, reward);
}
}
}
// 4. 使用示例
#[cfg(test)]
mod tests {
use super::*;
use frame_support::{assert_ok, assert_noop};
#[test]
fn test_society_workflow() {
new_test_ext().execute_with(|| {
// 初始化
let alice = 1;
let bob = 2;
// Alice申请成为候选人
assert_ok!(Society::bid(
Origin::signed(alice),
100 // 押金100
));
// Bob作为现有成员投票
assert_ok!(Society::vote(
Origin::signed(bob),
alice,
true // 赞成
));
// Alice成为成员后发布消息
assert_ok!(SocialNetwork::post_message(
Origin::signed(alice),
b"Hello Society!".to_vec()
));
// 验证消息存储
assert_eq!(
SocialNetwork::messages(alice),
vec![b"Hello Society!".to_vec()]
);
// 提升Alice等级
assert_ok!(SocialNetwork::promote_member(
Origin::root(),
alice
));
// 验证等级提升
assert_eq!(SocialNetwork::member_rank(alice), 1);
});
}
}
代码说明:
-
runtime集成:配置了
pallet-society
的基本参数,包括押金金额、惩罚机制等 -
社交网络扩展:
- 实现了消息发布功能
post_message
- 添加了成员等级系统
MemberRank
- 每个社交行为都会获得代币奖励
- 实现了消息发布功能
-
奖励机制:
- 基础奖励:发布消息奖励5个代币
- 等级奖励:升级奖励10个代币
- 活跃度奖励:账户回收时根据等级和消息数发放奖励
-
治理功能:
- 成员投票机制
- 只有root账户可以提升成员等级
- 所有操作都需要成员身份验证
-
测试用例:展示了完整的从申请加入、投票、发消息到升级的流程
这个示例展示了如何基于pallet-society
构建一个完整的去中心化社交网络,包含成员管理、激励机制和等级系统等核心功能。