diff --git a/solo-chains/runtime/dancelight/src/lib.rs b/solo-chains/runtime/dancelight/src/lib.rs index 98b2255b7..bf87423ed 100644 --- a/solo-chains/runtime/dancelight/src/lib.rs +++ b/solo-chains/runtime/dancelight/src/lib.rs @@ -519,9 +519,17 @@ impl pallet_timestamp::Config for Runtime { type WeightInfo = weights::pallet_timestamp::SubstrateWeight; } +pub struct RewardPoints; + +impl pallet_authorship::EventHandler> for RewardPoints { + fn note_author(author: AccountId) { + ExternalValidatorsRewards::reward_by_ids(vec![(author, 20u32)]) + } +} + impl pallet_authorship::Config for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; - type EventHandler = (); + type EventHandler = RewardPoints; } impl_opaque_keys! { diff --git a/solo-chains/runtime/dancelight/src/tests/common/mod.rs b/solo-chains/runtime/dancelight/src/tests/common/mod.rs index c29deae89..6bd3027b0 100644 --- a/solo-chains/runtime/dancelight/src/tests/common/mod.rs +++ b/solo-chains/runtime/dancelight/src/tests/common/mod.rs @@ -673,6 +673,12 @@ impl ExtBuilder { .assimilate_storage(&mut t) .unwrap(); + snowbridge_pallet_system::GenesisConfig:: { + ..Default::default() + } + .assimilate_storage(&mut t) + .unwrap(); + if self.safe_xcm_version.is_some() { // Disable run_block checks in XCM tests, because the XCM emulator runs on_initialize and // on_finalize automatically diff --git a/test/suites/dev-tanssi-relay/external-validators-rewards/test_external_validator_reward_candidates.ts b/test/suites/dev-tanssi-relay/external-validators-rewards/test_external_validator_reward_candidates.ts new file mode 100644 index 000000000..5c9d328c7 --- /dev/null +++ b/test/suites/dev-tanssi-relay/external-validators-rewards/test_external_validator_reward_candidates.ts @@ -0,0 +1,70 @@ +import "@tanssi/api-augment"; +import { describeSuite, customDevRpcRequest, expect, beforeAll } from "@moonwall/cli"; +import { ApiPromise, Keyring } from "@polkadot/api"; +import { jumpToSession } from "util/block"; + +describeSuite({ + id: "DTR1601", + title: "Paras inherent tests", + foundationMethods: "dev", + + testCases: ({ it, context }) => { + let polkadotJs: ApiPromise; + + beforeAll(async () => { + polkadotJs = context.polkadotJs(); + }); + + it({ + id: "E01", + title: "para candidates should trigger reward info", + test: async function () { + const keyring = new Keyring({ type: "sr25519" }); + const aliceStash = keyring.addFromUri("//Alice//stash"); + await context.createBlock(); + // Send RPC call to enable para inherent candidate generation + await customDevRpcRequest("mock_enableParaInherentCandidate", []); + // Since collators are not assigned until session 2, we need to go till session 2 to actually see heads being injected + await jumpToSession(context, 3); + await context.createBlock(); + + // we are still in era 0 + const validatorRewards = await context + .polkadotJs() + .query.externalValidatorsRewards.rewardPointsForEra(0); + const totalRewards = validatorRewards.total.toBigInt(); + + const blockNumber = (await polkadotJs.rpc.chain.getHeader()).number.toBigInt(); + + // Validators get 20 points for creating a block, so if they included a candidate, they will get more than 20 + expect(totalRewards).to.be.greaterThan(20n * blockNumber); + // All of them come from alice as she is the only one validating candidates + expect(validatorRewards.individual.toHuman()[aliceStash.address]).to.be.eq(totalRewards.toString()); + }, + }); + + it({ + id: "E02", + title: "Check rewards storage clears after historyDepth", + test: async function () { + const sessionsPerEra = await polkadotJs.consts.externalValidators.sessionsPerEra; + const historyDepth = await polkadotJs.consts.externalValidatorsRewards.historyDepth; + + const currentIndex = await polkadotJs.query.session.currentIndex(); + + const targetSession = + currentIndex.toNumber() + sessionsPerEra.toNumber() * (historyDepth.toNumber() + 1); + + await jumpToSession(context, targetSession); + + const validatorRewards = await context + .polkadotJs() + .query.externalValidatorsRewards.rewardPointsForEra(0); + const totalRewards = validatorRewards.total.toBigInt(); + + // rewards should have expired + expect(totalRewards).to.be.equal(0n); + }, + }); + }, +}); diff --git a/test/suites/dev-tanssi-relay/external-validators-rewards/test_external_validator_rewards.ts b/test/suites/dev-tanssi-relay/external-validators-rewards/test_external_validator_rewards.ts index dc4ef52ea..72737d8a3 100644 --- a/test/suites/dev-tanssi-relay/external-validators-rewards/test_external_validator_rewards.ts +++ b/test/suites/dev-tanssi-relay/external-validators-rewards/test_external_validator_rewards.ts @@ -1,10 +1,10 @@ import "@tanssi/api-augment"; -import { describeSuite, customDevRpcRequest, expect, beforeAll } from "@moonwall/cli"; +import { describeSuite, expect, beforeAll } from "@moonwall/cli"; import { ApiPromise, Keyring } from "@polkadot/api"; import { jumpToSession } from "util/block"; describeSuite({ - id: "DTR1601", + id: "DTR1602", title: "Paras inherent tests", foundationMethods: "dev", @@ -22,11 +22,6 @@ describeSuite({ const keyring = new Keyring({ type: "sr25519" }); const aliceStash = keyring.addFromUri("//Alice//stash"); await context.createBlock(); - // Send RPC call to enable para inherent candidate generation - await customDevRpcRequest("mock_enableParaInherentCandidate", []); - // Since collators are not assigned until session 2, we need to go till session 2 to actually see heads being injected - await jumpToSession(context, 3); - await context.createBlock(); // we are still in era 0 const validatorRewards = await context @@ -34,8 +29,11 @@ describeSuite({ .query.externalValidatorsRewards.rewardPointsForEra(0); const totalRewards = validatorRewards.total.toBigInt(); - expect(totalRewards).to.be.greaterThan(0n); - // All of them come from alice as she is the only one validating candidates + const blockNumber = (await polkadotJs.rpc.chain.getHeader()).number.toBigInt(); + + // 20 points per block + expect(totalRewards).toBe(20n * blockNumber); + // All of them come from alice as she is the only one producing blocks expect(validatorRewards.individual.toHuman()[aliceStash.address]).to.be.eq(totalRewards.toString()); }, });