diff --git a/packages/networks/src/chains/polkadot.ts b/packages/networks/src/chains/polkadot.ts index 1bd90a36..825c3274 100644 --- a/packages/networks/src/chains/polkadot.ts +++ b/packages/networks/src/chains/polkadot.ts @@ -15,11 +15,11 @@ const getInitStorages = () => ({ Account: [[[defaultAccounts.alice.address], { providers: 1, data: { free: 10 * 1e12 } }]], }, ParasDisputes: { - // those can makes block building super slow + // these can makes block building super slow $removePrefix: ['disputes'], }, Dmp: { - // clear existing dmp to avoid impact test result + // clear existing dmp to avoid impacting test result $removePrefix: ['downwardMessageQueues'], }, }) diff --git a/packages/tests/people/polkadot/authority.e2e.test.ts b/packages/tests/people/polkadot/authority.e2e.test.ts new file mode 100644 index 00000000..91a015a5 --- /dev/null +++ b/packages/tests/people/polkadot/authority.e2e.test.ts @@ -0,0 +1,9 @@ +import { describe } from 'vitest' + +import { peoplePolkadot, polkadot } from '@e2e-test/networks/chains' + +import { addIdentityThenKill } from '../shared.js' + +describe('Polkadot people chain: Adding a username authority (as root from the relay chain) works', async () => { + await addIdentityThenKill(polkadot, peoplePolkadot) +}) diff --git a/packages/tests/people/shared.ts b/packages/tests/people/shared.ts index 02ade8cc..5359b5de 100644 --- a/packages/tests/people/shared.ts +++ b/packages/tests/people/shared.ts @@ -1,6 +1,7 @@ import { BN } from 'bn.js' import { assert } from 'vitest' +import { ApiPromise } from '@polkadot/api' import { Chain, defaultAccounts } from '@e2e-test/networks' import { ITuple } from '@polkadot/types/types' import { Option, Vec, u128, u32 } from '@polkadot/types' @@ -10,9 +11,24 @@ import { PalletIdentityRegistrarInfo, PalletIdentityRegistration, } from '@polkadot/types/lookup' -import { aliceRegistrar } from '@e2e-test/networks/chains' import { setupNetworks } from '@e2e-test/shared' +/** + * Identity to be used in tests. + */ +const identity = { + email: { Raw: 'test_address@test.io' }, + legal: { Raw: 'FirstName LastName' }, + matrix: { Raw: '@test:test_server.io' }, + twitter: { Raw: '@test_twitter' }, + github: { Raw: 'test_github' }, + discord: { Raw: 'test_discord' }, + web: { Raw: 'http://test.te/me' }, + image: { Raw: 'test' }, + display: { Raw: 'Test Display' }, + pgpFingerprint: 'a1b2c3d4e5f6g7h8i9j1', +} + /** * Test the process of * 1. setting an identity, @@ -28,19 +44,6 @@ export async function setIdentityThenRequestAndProvideJudgement< >(peopleChain: Chain) { const [peopleClient] = await setupNetworks(peopleChain) - const identity = { - email: { raw: 'test_address@test.io' }, - legal: { raw: 'FirstName LastName' }, - matrix: { raw: '@test:test_server.io' }, - twitter: { Raw: '@test_twitter' }, - github: { Raw: 'test_github' }, - discord: { Raw: 'test_discord' }, - web: { Raw: 'http://test.te/me' }, - image: { raw: 'test' }, - display: { raw: 'Test Display' }, - pgpFingerprint: 'a1b2c3d4e5f6g7h8i9j1', - } - const querier = peopleClient.api.query const txApi = peopleClient.api.tx @@ -58,6 +61,7 @@ export async function setIdentityThenRequestAndProvideJudgement< const registrationInfo: PalletIdentityRegistration = identityInfoReply.unwrap()[0] const identityInfo = registrationInfo.info + assert(identityInfo.eq(identity)) console.log(identityInfo.toHuman()) assert( registrationInfo.judgements.isEmpty, @@ -142,19 +146,6 @@ export async function setIdentityThenRequesThenCancelThenClear< >(peopleChain: Chain) { const [peopleClient] = await setupNetworks(peopleChain) - const identity = { - email: { raw: 'test_address@test.io' }, - legal: { raw: 'FirstName LastName' }, - matrix: { raw: '@test:test_server.io' }, - twitter: { Raw: '@test_twitter' }, - github: { Raw: 'test_github' }, - discord: { Raw: 'test_discord' }, - web: { Raw: 'http://test.te/me' }, - image: { raw: 'test' }, - display: { raw: 'Test Display' }, - pgpFingerprint: 'a1b2c3d4e5f6g7h8i9j1', - } - const querier = peopleClient.api.query const txApi = peopleClient.api.tx @@ -247,19 +238,6 @@ export async function setIdentityThenAddSubsThenRemove< >(peopleChain: Chain) { const [peopleClient] = await setupNetworks(peopleChain) - const identity = { - email: { raw: 'test_address@test.io' }, - legal: { raw: 'FirstName LastName' }, - matrix: { raw: '@test:test_server.io' }, - twitter: { Raw: '@test_twitter' }, - github: { Raw: 'test_github' }, - discord: { Raw: 'test_discord' }, - web: { Raw: 'http://test.te/me' }, - image: { raw: 'test' }, - display: { raw: 'Test Display' }, - pgpFingerprint: 'a1b2c3d4e5f6g7h8i9j1', - } - const querier = peopleClient.api.query const txApi = peopleClient.api.tx @@ -505,3 +483,129 @@ export async function addRegistrarViaRelayAsRoot< assert(registrarsAfterParaBlock.length === 3) assertionHelper(registrarsAfterParaBlock, 'Registrars after parachain block differ from expected') } + +async function sendXcmFromRelay( + relayClient: { api: ApiPromise }, + encodedChainCallData: `0x${string}`, + paraId: number, + requireWeightAtMost = { proofSize: '10000', refTime: '100000000' }, +) { + // Destination of the XCM message sent from the relay chain to the parachain via `xcmPallet` + const dest = { + V4: { + parents: 0, + interior: { + X1: [ + { + Parachain: paraId, + }, + ], + }, + }, + } + + // The message being sent to the parachain, containing a call to be executed in the parachain: + // an origin-restricted extrinsic from the `identity` pallet, to be executed as a `SuperUser`. + const message = { + V4: [ + { + UnpaidExecution: { + weightLimit: 'Unlimited', + checkOrigin: null, + }, + }, + { + Transact: { + call: { + encoded: encodedChainCallData, + }, + originKind: 'SuperUser', + requireWeightAtMost, + }, + }, + ], + } + + const xcmTx = relayClient.api.tx.xcmPallet.send(dest, message) + const encodedRelayCallData = xcmTx.method.toHex() + + /** + * Execution of XCM call via RPC `dev_setStorage` + */ + + const number = (await relayClient.api.rpc.chain.getHeader()).number.toNumber() + + await relayClient.api.rpc('dev_setStorage', { + scheduler: { + agenda: [ + [ + [number + 1], + [ + { + call: { + Inline: encodedRelayCallData, + }, + origin: { + system: 'Root', + }, + }, + ], + ], + ], + }, + }) +} + +/** + * Test the process of setting up an identity, then forcibly removing it. + * + * It uses the parachain's relay to send an XCM message forcing execution of the normally gated + * `kill_identity` call as `SuperUser`. + * + * @param relayChain Relay chain on which the test will be run: Polkadot or Kusama. + * Must have `xcmpPallet` available. + * @param peopleChain People parachain whose registrars will be modified and asserted upon. + */ +export async function addIdentityThenKill< + TCustom extends Record | undefined, + TInitStoragesRelay extends Record> | undefined, + TInitStoragesPara extends Record> | undefined, +>(relayChain: Chain, peopleChain: Chain) { + /** + * Setup relay and parachain clients + */ + + const [relayClient, peopleClient] = await setupNetworks(relayChain, peopleChain) + + const querier = peopleClient.api.query + const txApi = peopleClient.api.tx + + /** + * Set Bob's on-chain identity + */ + + const setIdTx = txApi.identity.setIdentity(identity) + await setIdTx.signAndSend(defaultAccounts.bob) + + await peopleClient.chain.newBlock() + + const identityInfoReply = await querier.identity.identityOf(defaultAccounts.bob.address) + const registrationInfo: PalletIdentityRegistration = identityInfoReply.unwrap()[0] + const identityInfo = registrationInfo.info + assert(identityInfo.eq(identity)) + + /** + * Kill identity forcibly + */ + + const killIdentityTx = peopleClient.api.tx.identity.killIdentity(defaultAccounts.bob.address) + const encodedPeopleChainCallData = killIdentityTx.method.toHex() + + sendXcmFromRelay(relayClient, encodedPeopleChainCallData, 1004) + + await relayClient.chain.newBlock() + await peopleClient.chain.newBlock() + + const bobIdentity = await peopleClient.api.query.identity.identityOf(defaultAccounts.bob.address) + console.log(bobIdentity.isNone) +}