Skip to content

Commit

Permalink
test cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
girazoki committed Oct 30, 2024
1 parent eddb050 commit b41acd5
Show file tree
Hide file tree
Showing 7 changed files with 283 additions and 498 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,14 @@ import "@tanssi/api-augment";
import { describeSuite, expect, beforeAll } from "@moonwall/cli";
import { ApiPromise } from "@polkadot/api";
import { KeyringPair } from "@moonwall/util";
import { fetchCollatorAssignmentTip, jumpSessions } from "util/block";
import { Keyring } from "@polkadot/keyring";
import { Header, BabeEquivocationProof } from "@polkadot/types/interfaces";
import { SpRuntimeHeader } from '@polkadot/types/lookup';
import { extrinsics } from "@polkadot/types/interfaces/definitions";
import { u8aToHex, hexToU8a, stringToHex, numberToHex, stringToU8a } from "@polkadot/util";
import { blake2AsHex } from "@polkadot/util-crypto";
import { u8aToHex } from "@polkadot/util";
import { jumpToSession } from "../../../util/block";
import { generateBabeEquivocationProof } from "../../../util/slashes";

describeSuite({
id: "DTR1304",
title: "Babe offences should trigger a slash",
title: "Babe slashes defer period confirmation",
foundationMethods: "dev",
testCases: ({ it, context }) => {
let polkadotJs: ApiPromise;
Expand All @@ -29,92 +25,40 @@ describeSuite({
});
it({
id: "E01",
title: "Babe offences trigger a slash+",
title: "Babe offences should be confirmed after defer period",
test: async function () {
// we crate one block so that we at least have one seal.
await jumpToSession(context, 1);

// Remove alice from invulnerables (just for the slash)
const removeAliceFromInvulnerables = await polkadotJs.tx.sudo.sudo(
polkadotJs.tx.externalValidators.removeWhitelisted(aliceStash.address)
).signAsync(alice)
const removeAliceFromInvulnerables = await polkadotJs.tx.sudo
.sudo(polkadotJs.tx.externalValidators.removeWhitelisted(aliceStash.address))
.signAsync(alice);
await context.createBlock([removeAliceFromInvulnerables]);

let baseHeader = await polkadotJs.rpc.chain.getHeader();
let baseHeader2 = await polkadotJs.rpc.chain.getHeader();

const header1: SpRuntimeHeader = polkadotJs.createType("SpRuntimeHeader", {
digest: baseHeader.digest,
extrinsicsRoot: baseHeader.extrinsicsRoot,
stateRoot: baseHeader.stateRoot,
parentHash: baseHeader.parentHash,
number: 1,
});

// we just change the block number
const header2: SpRuntimeHeader = polkadotJs.createType("SpRuntimeHeader", {
digest: baseHeader2.digest,
extrinsicsRoot: baseHeader2.extrinsicsRoot,
stateRoot: baseHeader2.stateRoot,
parentHash: baseHeader2.parentHash,
number: 2,
});

const sig1 = aliceBabePair.sign(blake2AsHex(header1.toU8a()));
const sig2 = aliceBabePair.sign(blake2AsHex(header2.toU8a()));

const slot = await polkadotJs.query.babe.currentSlot();

// let's inject the equivocation proof
const doubleVotingProof = await generateBabeEquivocationProof(polkadotJs, aliceBabePair);

const keyOwnershipProof = (await polkadotJs.call.babeApi.generateKeyOwnershipProof(
slot,
u8aToHex(aliceBabePair.publicKey)
)).unwrap();

// We don't care about the first 8 characters of the proof, as they
// correspond to SCALE encoded wrapping stuff we don't need.
//const keyOwnershipProofHex = `0x${keyOwnershipProof.toHuman().toString().slice(8)}`;

const digestItemSeal1: SpRuntimeDigestDigestItem = polkadotJs.createType(
"SpRuntimeDigestDigestItem",
{ Seal: [
stringToHex('BABE'),
u8aToHex(sig1)
]
}
);

const digestItemSeal2: SpRuntimeDigestDigestItem = polkadotJs.createType(
"SpRuntimeDigestDigestItem",
{ Seal: [
stringToHex('BABE'),
u8aToHex(sig2)
]
}
);

header1.digest.logs.push(digestItemSeal1);
header2.digest.logs.push(digestItemSeal2);
// generate key ownership proof
const keyOwnershipProof = (
await polkadotJs.call.babeApi.generateKeyOwnershipProof(
doubleVotingProof.slotNumber,
u8aToHex(aliceBabePair.publicKey)
)
).unwrap();

const doubleVotingProof: BabeEquivocationProof = polkadotJs.createType(
"BabeEquivocationProof",
{
offender: aliceBabePair.publicKey,
slotNumber: slot,
firstHeader: header1,
secondHeader: header2
}
);
const tx = polkadotJs.tx.sudo.sudoUncheckedWeight(
polkadotJs.tx.utility.dispatchAs(
{
system: { Signed: alice.address },
} as any,
polkadotJs.tx.babe.reportEquivocation(doubleVotingProof, keyOwnershipProof)), {
refTime: 1n,
proofSize: 1n
})
polkadotJs.tx.babe.reportEquivocation(doubleVotingProof, keyOwnershipProof)
),
{
refTime: 1n,
proofSize: 1n,
}
);

const signedTx = await tx.signAsync(alice);
await context.createBlock(signedTx);
Expand All @@ -123,26 +67,28 @@ describeSuite({
const DeferPeriod = 2;

// scheduled slashes
const expectedSlashes = await polkadotJs.query.externalValidatorSlashes.slashes(DeferPeriod +1);
const expectedSlashes = await polkadotJs.query.externalValidatorSlashes.slashes(DeferPeriod + 1);
expect(expectedSlashes.length).to.be.eq(1);
expect(u8aToHex(expectedSlashes[0].validator)).to.be.eq(u8aToHex(aliceStash.addressRaw));
// Put alice back to invulnerables
const addAliceFromInvulnerables = await polkadotJs.tx.sudo.sudo(
polkadotJs.tx.externalValidators.addWhitelisted(aliceStash.address)
).signAsync(alice)

// Put alice back to invulnerables
const addAliceFromInvulnerables = await polkadotJs.tx.sudo
.sudo(polkadotJs.tx.externalValidators.addWhitelisted(aliceStash.address))
.signAsync(alice);
await context.createBlock([addAliceFromInvulnerables]);

let sessionsPerEra = await polkadotJs.consts.externalValidators.sessionsPerEra;
const sessionsPerEra = await polkadotJs.consts.externalValidators.sessionsPerEra;

let currentIndex = await polkadotJs.query.session.currentIndex();
const currentIndex = await polkadotJs.query.session.currentIndex();

let targetSession = currentIndex*sessionsPerEra*(DeferPeriod +1);
const targetSession = currentIndex * sessionsPerEra * (DeferPeriod + 1);

await jumpToSession(context, targetSession);

// scheduled slashes
const expectedSlashesAfterDefer = await polkadotJs.query.externalValidatorSlashes.slashes(DeferPeriod +1);
const expectedSlashesAfterDefer = await polkadotJs.query.externalValidatorSlashes.slashes(
DeferPeriod + 1
);
expect(expectedSlashesAfterDefer.length).to.be.eq(1);
expect(expectedSlashesAfterDefer[0].confirmed.toHuman()).to.be.true;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,113 +2,55 @@ import "@tanssi/api-augment";
import { describeSuite, expect, beforeAll } from "@moonwall/cli";
import { ApiPromise } from "@polkadot/api";
import { KeyringPair } from "@moonwall/util";
import { fetchCollatorAssignmentTip, jumpSessions } from "util/block";
import { Keyring } from "@polkadot/keyring";
import { Header, BabeEquivocationProof } from "@polkadot/types/interfaces";
import { SpRuntimeHeader } from '@polkadot/types/lookup';
import { extrinsics } from "@polkadot/types/interfaces/definitions";
import { u8aToHex, hexToU8a, stringToHex, numberToHex, stringToU8a } from "@polkadot/util";
import { blake2AsHex } from "@polkadot/util-crypto";
import { u8aToHex } from "@polkadot/util";
import { jumpToSession } from "../../../util/block";
import { generateBabeEquivocationProof } from "../../../util/slashes";

describeSuite({
id: "DTR1302",
title: "Babe offences should trigger a slash",
title: "Babe offences invulnerables",
foundationMethods: "dev",
testCases: ({ it, context }) => {
let polkadotJs: ApiPromise;
let alice: KeyringPair;
let aliceBabePair: KeyringPair;
let aliceStash: KeyringPair;
beforeAll(async () => {
const keyringBabe = new Keyring({ type: "sr25519" });
aliceBabePair = keyringBabe.addFromUri("//Alice");
polkadotJs = context.polkadotJs();
alice = context.keyring.alice;
aliceStash = keyringBabe.addFromUri("//Alice//stash");
});
it({
id: "E01",
title: "Babe offences trigger a slash+",
title: "Babe offences do not trigger a slash to invulnerables",
test: async function () {
// we crate one block so that we at least have one seal.
await jumpToSession(context, 1);

let baseHeader = await polkadotJs.rpc.chain.getHeader();
let baseHeader2 = await polkadotJs.rpc.chain.getHeader();

const header1: SpRuntimeHeader = polkadotJs.createType("SpRuntimeHeader", {
digest: baseHeader.digest,
extrinsicsRoot: baseHeader.extrinsicsRoot,
stateRoot: baseHeader.stateRoot,
parentHash: baseHeader.parentHash,
number: 1,
});

// we just change the block number
const header2: SpRuntimeHeader = polkadotJs.createType("SpRuntimeHeader", {
digest: baseHeader2.digest,
extrinsicsRoot: baseHeader2.extrinsicsRoot,
stateRoot: baseHeader2.stateRoot,
parentHash: baseHeader2.parentHash,
number: 2,
});

const sig1 = aliceBabePair.sign(blake2AsHex(header1.toU8a()));
const sig2 = aliceBabePair.sign(blake2AsHex(header2.toU8a()));

const slot = await polkadotJs.query.babe.currentSlot();

// let's inject the equivocation proof
const doubleVotingProof = await generateBabeEquivocationProof(polkadotJs, aliceBabePair);

const keyOwnershipProof = (await polkadotJs.call.babeApi.generateKeyOwnershipProof(
slot,
u8aToHex(aliceBabePair.publicKey)
)).unwrap();
// generate key ownership proof
const keyOwnershipProof = (
await polkadotJs.call.babeApi.generateKeyOwnershipProof(
doubleVotingProof.slotNumber,
u8aToHex(aliceBabePair.publicKey)
)
).unwrap();

// We don't care about the first 8 characters of the proof, as they
// correspond to SCALE encoded wrapping stuff we don't need.
//const keyOwnershipProofHex = `0x${keyOwnershipProof.toHuman().toString().slice(8)}`;

const digestItemSeal1: SpRuntimeDigestDigestItem = polkadotJs.createType(
"SpRuntimeDigestDigestItem",
{ Seal: [
stringToHex('BABE'),
u8aToHex(sig1)
]
}
);

const digestItemSeal2: SpRuntimeDigestDigestItem = polkadotJs.createType(
"SpRuntimeDigestDigestItem",
{ Seal: [
stringToHex('BABE'),
u8aToHex(sig2)
]
}
);

header1.digest.logs.push(digestItemSeal1);
header2.digest.logs.push(digestItemSeal2);

const doubleVotingProof: BabeEquivocationProof = polkadotJs.createType(
"BabeEquivocationProof",
{
offender: aliceBabePair.publicKey,
slotNumber: slot,
firstHeader: header1,
secondHeader: header2
}
);
const tx = polkadotJs.tx.sudo.sudoUncheckedWeight(
polkadotJs.tx.utility.dispatchAs(
{
system: { Signed: alice.address },
} as any,
polkadotJs.tx.babe.reportEquivocation(doubleVotingProof, keyOwnershipProof)), {
refTime: 1n,
proofSize: 1n
})
polkadotJs.tx.babe.reportEquivocation(doubleVotingProof, keyOwnershipProof)
),
{
refTime: 1n,
proofSize: 1n,
}
);

const signedTx = await tx.signAsync(alice);
await context.createBlock(signedTx);
Expand All @@ -117,7 +59,7 @@ describeSuite({
const DeferPeriod = 2;

// Alice is an invulnerable, therefore she should not be slashed
const expectedSlashes = await polkadotJs.query.externalValidatorSlashes.slashes(DeferPeriod +1);
const expectedSlashes = await polkadotJs.query.externalValidatorSlashes.slashes(DeferPeriod + 1);
expect(expectedSlashes.length).to.be.eq(0);
},
});
Expand Down
Loading

0 comments on commit b41acd5

Please sign in to comment.