Sub3.0模板進(jìn)化2修改aura為babe--by Skyh

node-template起始共識(shí)是Aura,就是Round Robin輪流出塊的簡(jiǎn)單機(jī)制,現(xiàn)在改成Babe就是基于插槽VRF的共識(shí)

1. 依賴修改

runtime的Cargo.toml搜索有兩處aura

pallet-aura = { version = "3.0.0", default-features = false }
sp-consensus-aura = { version = "0.9.0", default-features = false }
修改成:
pallet-babe = { version = "3.0.0", default-features = false }
sp-consensus-babe = { version = "0.9.0", default-features = false }
還有std中的

還有node的Cargo.toml也有兩處

sc-consensus-aura = "0.9.0"
sp-consensus-aura = "0.9.0"

2. 修改runtime的lib.rs, 搜索Aura

把SessionKey修改:

impl_opaque_keys! {
    pub struct SessionKeys {
        pub aura: Aura,
        pub grandpa: Grandpa,
    }
}
改成:
impl_opaque_keys! {
    pub struct SessionKeys {
        pub babe: Babe,
        pub grandpa: Grandpa,
    }
}

把a(bǔ)ura的定義改成:

parameter_types! {
    pub const EpochDuration: u64 = EPOCH_DURATION_IN_BLOCKS as u64;
    pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
    pub const ReportLongevity: u64 = 0; // by Skyh
        // BondingDuration::get() as u64 * SessionsPerEra::get() as u64 * EpochDuration::get(); // Kusama
}

impl pallet_babe::Config for Runtime {
    type EpochDuration = EpochDuration;
    type ExpectedBlockTime = ExpectedBlockTime;
    type EpochChangeTrigger = pallet_babe::ExternalTrigger;
    type KeyOwnerProofSystem = (); // Historical;
    type KeyOwnerProof =
    <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, pallet_babe::AuthorityId)>>::Proof;
    type KeyOwnerIdentification =
    <Self::KeyOwnerProofSystem as KeyOwnerProofSystem<(KeyTypeId, pallet_babe::AuthorityId)>>::IdentificationTuple;
    type HandleEquivocation = (); //pallet_babe::EquivocationHandler<Self::KeyOwnerIdentification, (), ReportLongevity>; // () Offences
    type WeightInfo = ();
}

修改construct_runtime的Aura:

construct_runtime!(
    pub enum Runtime where
        Block = Block,
        NodeBlock = opaque::Block,
        UncheckedExtrinsic = UncheckedExtrinsic
    {
        Sudo: pallet_sudo::{Module, Call, Config<T>, Storage, Event<T>},
        System: frame_system::{Module, Call, Config, Storage, Event<T>},
        Balances: pallet_balances::{Module, Call, Storage, Config<T>, Event<T>},
        Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent},
        TransactionPayment: pallet_transaction_payment::{Module, Storage},
        RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage},

        Babe: pallet_babe::{Module, Call, Storage, Config, Inherent, ValidateUnsigned},
        Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event, ValidateUnsigned},

        // Include the custom logic from the template pallet in the runtime.
        TemplateModule: template::{Module, Call, Storage, Event<T>},
    }
);

修改impl_runtime_apis中的AuraApi

impl sp_consensus_babe::BabeApi<Block> for Runtime {
        fn configuration() -> sp_consensus_babe::BabeGenesisConfiguration {
            sp_consensus_babe::BabeGenesisConfiguration {
                slot_duration: Babe::slot_duration(),
                epoch_length: EpochDuration::get(),
                c: PRIMARY_PROBABILITY,
                genesis_authorities: Babe::authorities(),
                randomness: Babe::randomness(),
                allowed_slots: sp_consensus_babe::AllowedSlots::PrimaryAndSecondaryPlainSlots,
            }
        }

        fn current_epoch_start() -> sp_consensus_babe::Slot {
            Babe::current_epoch_start()
        }

        fn current_epoch() -> sp_consensus_babe::Epoch {
            Babe::current_epoch()
        }

        fn next_epoch() -> sp_consensus_babe::Epoch {
            Babe::next_epoch()
        }

        fn generate_key_ownership_proof(
            _slot: sp_consensus_babe::Slot,
            authority_id: sp_consensus_babe::AuthorityId,
        ) -> Option<sp_consensus_babe::OpaqueKeyOwnershipProof> {
            use codec::Encode;

            Historical::prove((sp_consensus_babe::KEY_TYPE, authority_id))
                .map(|p| p.encode())
                .map(sp_consensus_babe::OpaqueKeyOwnershipProof::new)
        }

        fn submit_report_equivocation_unsigned_extrinsic(
            equivocation_proof: sp_consensus_babe::EquivocationProof<<Block as BlockT>::Header>,
            key_owner_proof: sp_consensus_babe::OpaqueKeyOwnershipProof,
            ) -> Option<()> {
            let key_owner_proof = key_owner_proof.decode()?;

            Babe::submit_unsigned_equivocation_report(
                equivocation_proof,
                key_owner_proof,
                )
        }
    }

坑:在這里,高度抽象化必須對(duì)應(yīng)看人家項(xiàng)目使用Historical,所以必須在runtime中加入:

# historical的特性
pallet-session = { version = "3.0.0", default-features = false, features = ["historical"] }

impl pallet_session::historical::Config for Runtime {
    type FullIdentification = pallet_staking::Exposure<AccountId, Balance>;
    type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
}

Historical: session_historical::{Module},

坑2:也要加入staking, 這算耦合么,暫時(shí)沒有好的解決方法

pallet-staking = { version = "3.0.0", default-features = false }

也在babe和grandpa加入KeyOwnerProofSystem為Historical
編譯報(bào)錯(cuò)要實(shí)現(xiàn)super的session的config


image.png

3. 被逼加入session和staking

具體代碼

parameter_types! {
    pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17);
}

impl pallet_session::Config for Runtime {
    type Event = Event;
    type ValidatorId = <Self as frame_system::Config>::AccountId;
    type ValidatorIdOf = pallet_staking::StashOf<Self>;

    type Keys = SessionKeys;
    type ShouldEndSession = Babe;
    type NextSessionRotation = Babe;
    type SessionManager = pallet_session::historical::NoteHistoricalRoot<Self, Staking>;
    type SessionHandler = <SessionKeys as OpaqueKeys>::KeyTypeIdProviders;
    type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
    type WeightInfo = ();
}

impl pallet_session::historical::Config for Runtime {
    type FullIdentification = pallet_staking::Exposure<AccountId, Balance>;
    type FullIdentificationOf = pallet_staking::ExposureOf<Runtime>;
}

又必須加入staking

pallet_staking_reward_curve::build! {
    const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
        min_inflation: 0_025_000,
        max_inflation: 0_100_000,
        ideal_stake: 0_500_000,
        falloff: 0_050_000,
        max_piece_count: 40,
        test_precision: 0_005_000,
    );
}

parameter_types! {
    pub const SessionsPerEra: sp_staking::SessionIndex = 3; // 3 hours
    pub const BondingDuration: pallet_staking::EraIndex = 4; // 12 hours
    pub const SlashDeferDuration: pallet_staking::EraIndex = 2; // 6 hours
    pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
    pub const ElectionLookahead: BlockNumber = EPOCH_DURATION_IN_BLOCKS / 4;

    pub const MaxNominatorRewardedPerValidator: u32 = 64;
    pub const MaxIterations: u32 = 5;
    // 0.05%. The higher the value, the more strict solution acceptance becomes.
    pub MinSolutionScoreBump: Perbill = Perbill::from_rational_approximation(5u32, 10_000);
    pub StakingUnsignedPriority: TransactionPriority =
        Perbill::from_percent(90) * TransactionPriority::max_value();
}

parameter_types! {
    pub OffchainSolutionWeightLimit: Weight = BlockWeights::get()
        .get(DispatchClass::Normal)
        .max_extrinsic
        .expect("Normal extrinsics have weight limit configured by default; qed")
        .saturating_sub(BlockExecutionWeight::get());
}

pub type CurrencyToVote = frame_support::traits::U128CurrencyToVote;

// TODO: Kusama
// type SlashCancelOrigin = EnsureOneOf<
//  AccountId,
//  EnsureRoot<AccountId>,
//  pallet_collective::EnsureProportionAtLeast<_1, _2, AccountId, CouncilCollective>
// >;

impl pallet_staking::Config for Runtime {
    type Call = Call;
    type Event = Event;
    type UnixTime = Timestamp;

    type Currency = Balances;
    type CurrencyToVote = CurrencyToVote;
    type RewardRemainder = (); // TODO: Treasury
    type Slash = (); // TODO: Treasury
    type Reward = (); // rewards are minted from the voi

    type SessionInterface = Self;
    type NextNewSession = Session;
    type SessionsPerEra = SessionsPerEra;
    type BondingDuration = BondingDuration;
    type SlashDeferDuration = SlashDeferDuration;
    /// A super-majority of the council can cancel the slash.
    type SlashCancelOrigin = EnsureRoot<Self::AccountId>; // TODO: SlashCancelOrigin
    type RewardCurve = RewardCurve;
    type ElectionLookahead = ElectionLookahead;

    type MinSolutionScoreBump = MinSolutionScoreBump;
    type MaxIterations = MaxIterations;
    type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator;
    type UnsignedPriority = StakingUnsignedPriority; // Kusama
    type OffchainSolutionWeightLimit = OffchainSolutionWeightLimit;
    type WeightInfo = ();
}

坑3:staking需要實(shí)現(xiàn)SendTransactionTypes

impl<C> frame_system::offchain::SendTransactionTypes<C> for Runtime
    where
        Call: From<C>,
{
    type OverarchingCall = Call;
    type Extrinsic = UncheckedExtrinsic;
}

4. 修改chain_spec.rs和service.rs

chain_spec首先先引入 BabeId

use sp_consensus_babe::AuthorityId as BabeId;

// 加session_key
fn session_keys(
    babe: BabeId,
    grandpa: GrandpaId,
) -> SessionKeys {
    SessionKeys { babe, grandpa }
}

修改authority_keys_from_seed的AuraId

pub fn authority_keys_from_seed(seed: &str) -> (AccountId, AccountId, BabeId, GrandpaId) {
    (
        get_account_id_from_seed::<sr25519::Public>(&format!("{}//stash", seed)),
        get_account_id_from_seed::<sr25519::Public>(seed),
        get_from_seed::<BabeId>(seed),
        get_from_seed::<GrandpaId>(seed),
    )
}

再在testnet_genesis中修改aura:

pallet_babe: Some(Default::default()),
pallet_grandpa: Some(Default::default()),
pallet_session: Some(SessionConfig {
            keys: initial_authorities.iter().map(|x| {
                (x.0.clone(),
                 x.0.clone(),
                 session_keys(
                     x.2.clone(), x.3.clone()
                 ))
            }).collect::<Vec<_>>(),
        }),
        pallet_staking: Some(StakingConfig {
            validator_count: initial_authorities.len() as u32 * 2,
            minimum_validator_count: initial_authorities.len() as u32,
            stakers: initial_authorities
                .iter()
                .map(|x| (x.0.clone(), x.1.clone(), INITIAL_STAKING, StakerStatus::Validator))
                .collect(),
            invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(),
            slash_reward_fraction: Perbill::from_percent(10),
            ..Default::default()
        }),

寫在最后,這次修改在這里:
https://github.com/skyh24/node-template3/commit/513d4bad382baf1f65d90608143d1bc491e9de74

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容