Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relaychain ParaInherentEnter #120

Merged
merged 3 commits into from
Jan 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 26 additions & 8 deletions e2e/__snapshots__/xcm.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -317,6 +317,24 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
},
"topics": [],
},
{
"event": {
"data": {
"dispatchInfo": {
"class": "Mandatory",
"paysFee": "Yes",
"weight": "85,212,000",
},
},
"index": "0x0000",
"method": "ExtrinsicSuccess",
"section": "system",
},
"phase": {
"ApplyExtrinsic": "1",
},
"topics": [],
},
{
"event": {
"data": {
Expand All @@ -328,7 +346,7 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
"section": "balances",
},
"phase": {
"ApplyExtrinsic": "1",
"ApplyExtrinsic": "2",
},
"topics": [],
},
Expand All @@ -344,7 +362,7 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
"section": "balances",
},
"phase": {
"ApplyExtrinsic": "1",
"ApplyExtrinsic": "2",
},
"topics": [],
},
Expand All @@ -360,7 +378,7 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
"section": "xcmPallet",
},
"phase": {
"ApplyExtrinsic": "1",
"ApplyExtrinsic": "2",
},
"topics": [],
},
Expand All @@ -375,7 +393,7 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
"section": "balances",
},
"phase": {
"ApplyExtrinsic": "1",
"ApplyExtrinsic": "2",
},
"topics": [],
},
Expand All @@ -389,7 +407,7 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
"section": "treasury",
},
"phase": {
"ApplyExtrinsic": "1",
"ApplyExtrinsic": "2",
},
"topics": [],
},
Expand All @@ -404,7 +422,7 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
"section": "balances",
},
"phase": {
"ApplyExtrinsic": "1",
"ApplyExtrinsic": "2",
},
"topics": [],
},
Expand All @@ -420,7 +438,7 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
"section": "transactionPayment",
},
"phase": {
"ApplyExtrinsic": "1",
"ApplyExtrinsic": "2",
},
"topics": [],
},
Expand All @@ -438,7 +456,7 @@ exports[`XCM > Polkadot send downward messages to Acala 1`] = `
"section": "system",
},
"phase": {
"ApplyExtrinsic": "1",
"ApplyExtrinsic": "2",
},
"topics": [],
},
Expand Down
11 changes: 6 additions & 5 deletions e2e/helper.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { ApiPromise, WsProvider } from '@polkadot/api'
import { Codec } from '@polkadot/types/types'
import { HexString } from '@polkadot/util/types'
import { Keyring } from '@polkadot/keyring'
import { beforeAll, beforeEach, expect, vi } from 'vitest'

import { Api } from '../src/api'
import { Blockchain } from '../src/blockchain'
import { BuildBlockMode } from '../src/blockchain/txpool'
import { GenesisProvider } from '../src/genesis-provider'
import { InherentProviders, SetTimestamp, SetValidationData } from '../src/blockchain/inherent'
import { InherentProviders, ParaInherentEnter, SetTimestamp, SetValidationData } from '../src/blockchain/inherent'
import { StorageValues } from '../src/utils/set-storage'
import { createServer } from '../src/server'
import { handler } from '../src/rpc'

export type SetupOption = {
endpoint?: string
blockHash?: string
blockHash?: HexString
mockSignatureHost?: boolean
allowUnresolvedImports?: boolean
genesis?: string
Expand All @@ -23,11 +24,11 @@ export type SetupOption = {
export const env = {
mandala: {
endpoint: 'wss://mandala-rpc.aca-staging.network/ws',
blockHash: '0x062327512615cd62ea8c57652a04a6c937b112f1410520d83e2fafb9776cdbe1',
blockHash: '0x062327512615cd62ea8c57652a04a6c937b112f1410520d83e2fafb9776cdbe1' as HexString,
},
rococo: {
endpoint: 'wss://rococo-rpc.polkadot.io',
blockHash: '0xd7fef00504decd41d5d2e9a04346f6bc639fd428083e3ca941f636a8f88d456a',
blockHash: '0xd7fef00504decd41d5d2e9a04346f6bc639fd428083e3ca941f636a8f88d456a' as HexString,
},
mandalaGenesis: {
genesis: 'https://raw.githubusercontent.com/AcalaNetwork/Acala/master/resources/mandala-dist.json',
Expand All @@ -51,7 +52,7 @@ export const setupAll = async ({

return {
async setup() {
const inherents = new InherentProviders(new SetTimestamp(), [new SetValidationData()])
const inherents = new InherentProviders(new SetTimestamp(), [new SetValidationData(), new ParaInherentEnter()])

const chain = new Blockchain({
api,
Expand Down
5 changes: 3 additions & 2 deletions e2e/time-travel.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { HexString } from '@polkadot/util/types'
import { chain, setupApi, ws } from './helper'
import { describe, expect, it } from 'vitest'
import { getCurrentTimestamp, getSlotDuration, timeTravel } from '../src/utils/time-travel'
Expand All @@ -6,12 +7,12 @@ describe.each([
{
chain: 'Polkadot',
endpoint: 'wss://rpc.polkadot.io',
blockHash: '0xb7fb7cfe79142652036e73f8044e0efbbbe7d3fb71cabc212efd5968c9041950',
blockHash: '0xb7fb7cfe79142652036e73f8044e0efbbbe7d3fb71cabc212efd5968c9041950' as HexString,
},
{
chain: 'Acala',
endpoint: 'wss://acala-rpc-1.aca-api.network',
blockHash: '0x1d9223c88161b512ebaac53c2c7df6dc6bd2731b12273b898f582af929cc5331',
blockHash: '0x1d9223c88161b512ebaac53c2c7df6dc6bd2731b12273b898f582af929cc5331' as HexString,
},
])('Can time-travel on $chain', async ({ endpoint, blockHash }) => {
setupApi({ endpoint, blockHash })
Expand Down
2 changes: 1 addition & 1 deletion src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class Api {
}

async getBlockHash(blockNumber?: number) {
return this.#provider.send<string>('chain_getBlockHash', Number.isInteger(blockNumber) ? [blockNumber] : [])
return this.#provider.send<HexString>('chain_getBlockHash', Number.isInteger(blockNumber) ? [blockNumber] : [])
}

async getHeader(hash?: string) {
Expand Down
2 changes: 1 addition & 1 deletion src/blockchain/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export class Block {
constructor(
chain: Blockchain,
public readonly number: number,
public readonly hash: string,
public readonly hash: HexString,
parentBlock?: Block,
block?: { header: Header; extrinsics: HexString[]; storage?: StorageLayerProvider }
) {
Expand Down
9 changes: 4 additions & 5 deletions src/blockchain/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface Options {
buildBlockMode?: BuildBlockMode
inherentProvider: InherentProvider
db?: DataSource
header: { number: number; hash: string }
header: { number: number; hash: HexString }
mockSignatureHost?: boolean
allowUnresolvedImports?: boolean
}
Expand Down Expand Up @@ -89,7 +89,7 @@ export class Blockchain {
return this.#blocksByNumber[number]
}

async getBlock(hash?: string): Promise<Block | undefined> {
async getBlock(hash?: HexString): Promise<Block | undefined> {
await this.api.isReady
if (hash == null) {
hash = this.head.hash
Expand All @@ -110,11 +110,10 @@ export class Blockchain {

newTempBlock(parent: Block, header: Header): Block {
const number = parent.number + 1
const hash =
'0x' +
const hash = ('0x' +
Math.round(Math.random() * 100000000)
.toString(16)
.padEnd(64, '0')
.padEnd(64, '0')) as HexString
const block = new Block(this, number, hash, parent, { header, extrinsics: [], storage: parent.storage })
this.#blocksByHash[hash] = block
return block
Expand Down
1 change: 1 addition & 0 deletions src/blockchain/inherent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { HexString } from '@polkadot/util/types'
import { getCurrentTimestamp, getSlotDuration } from '../../utils/time-travel'

export { SetValidationData } from './parachain/validation-data'
export { ParaInherentEnter } from './para-enter'

export interface CreateInherents {
createInherents(parent: Block, params?: BuildBlockParams['inherent']): Promise<HexString[]>
Expand Down
41 changes: 41 additions & 0 deletions src/blockchain/inherent/para-enter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { GenericExtrinsic } from '@polkadot/types'
import { HexString } from '@polkadot/util/types'

import { Block } from '../block'
import { BuildBlockParams } from '../txpool'
import { CreateInherents } from '.'

export class ParaInherentEnter implements CreateInherents {
async createInherents(parent: Block, _params?: BuildBlockParams['inherent']): Promise<HexString[]> {
const meta = await parent.meta
if (!meta.tx.paraInherent?.enter) {
return []
}

const extrinsics = await parent.extrinsics

const paraEnterExtrinsic = extrinsics.find((extrinsic) => {
const firstArg = meta.registry.createType<GenericExtrinsic>('GenericExtrinsic', extrinsic)?.args?.[0]
return firstArg && 'bitfields' in firstArg
})
if (!paraEnterExtrinsic) {
throw new Error('Missing paraInherent data from block')
}
const extrinsic = meta.registry
.createType<GenericExtrinsic>('GenericExtrinsic', paraEnterExtrinsic)
.args[0].toJSON() as any

const parentHeader = (await parent.header).toJSON()

const newData = {
...extrinsic,
bitfields: [],
backedCandidates: [],
parentHeader,
}

// TODO: fill with data

return [new GenericExtrinsic(meta.registry, meta.tx.paraInherent.enter(newData)).toHex()]
}
}
12 changes: 4 additions & 8 deletions src/blockchain/inherent/parachain/validation-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,15 +56,11 @@ export class SetValidationData implements CreateInherents {
return []
}

const parentBlock = await parent.parentBlock
if (!parentBlock) {
throw new Error('Parent block not found')
}
const extrinsics = await parentBlock.extrinsics
const extrinsics = await parent.extrinsics

let newData: ValidationData

if (parentBlock.number === 0) {
if (parent.number === 0) {
// chain started with genesis, mock 1st validationData
newData = MOCK_VALIDATION_DATA as ValidationData
} else {
Expand All @@ -83,7 +79,7 @@ export class SetValidationData implements CreateInherents {
const downwardMessages: { msg: HexString; sent_at: number }[] = []
const horizontalMessages: Record<number, { data: HexString; sent_at: number }[]> = {}

const paraId = await getParaId(parentBlock.chain)
const paraId = await getParaId(parent.chain)

const dmqMqcHeadKey = dmqMqcHead(paraId)
const hrmpIngressChannelIndexKey = hrmpIngressChannelIndex(paraId)
Expand Down Expand Up @@ -173,7 +169,7 @@ export class SetValidationData implements CreateInherents {
}

const upgradeKey = upgradeGoAheadSignal(paraId)
const pendingUpgrade = await parentBlock.get(compactHex(meta.query.parachainSystem.pendingValidationCode()))
const pendingUpgrade = await parent.get(compactHex(meta.query.parachainSystem.pendingValidationCode()))
if (pendingUpgrade) {
// send goAhead signal
const goAhead = meta.registry.createType('UpgradeGoAhead', 'GoAhead')
Expand Down
11 changes: 1 addition & 10 deletions src/blockchain/txpool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { Block } from './block'
import { Blockchain } from '.'
import { InherentProvider } from './inherent'
import { ResponseError } from '../rpc/shared'
import { compactHex } from '../utils'
import { defaultLogger, truncate, truncateStorageDiff } from '../logger'
import { getCurrentSlot } from '../utils/time-travel'

Expand Down Expand Up @@ -165,7 +164,7 @@ export class TxPool {

newBlock.pushStorageLayer().setAll(resp.storageDiff)

const inherents = await this.#inherentProvider.createInherents(newBlock, params?.inherent)
const inherents = await this.#inherentProvider.createInherents(head, params?.inherent)
for (const extrinsic of inherents) {
try {
const resp = await newBlock.call('BlockBuilder_apply_extrinsic', extrinsic)
Expand All @@ -188,14 +187,6 @@ export class TxPool {
}
}

if (meta.query.paraInherent?.included) {
// TODO: remvoe this once paraInherent.enter is implemented
// we are relaychain, however as we have not yet implemented the paraInherent.enter
// so need to do some trick to make the on_finalize check happy
const paraInherentIncludedKey = compactHex(meta.query.paraInherent.included())
newBlock.pushStorageLayer().set(paraInherentIncludedKey, '0x01')
}

const resp2 = await newBlock.call('BlockBuilder_finalize_block', '0x')

newBlock.pushStorageLayer().setAll(resp2.storageDiff)
Expand Down
3 changes: 2 additions & 1 deletion src/rpc/dev.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Handlers, ResponseError } from './shared'
import { HexString } from '@polkadot/util/types'
import { StorageValues, setStorage } from '../utils/set-storage'
import { defaultLogger } from '../logger'
import { timeTravel } from '../utils/time-travel'
Expand All @@ -23,7 +24,7 @@ const handlers: Handlers = {
return finalHash
},
dev_setStorages: async (context, params) => {
const [values, blockHash] = params as [StorageValues, string?]
const [values, blockHash] = params as [StorageValues, HexString?]
const hash = await setStorage(context.chain, values, blockHash).catch((error) => {
throw new ResponseError(1, error.toString())
})
Expand Down
2 changes: 1 addition & 1 deletion src/schema/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const configSchema = z
.object({
port: z.number().optional(),
endpoint: z.string().optional(),
block: z.union([z.string(), z.number()]).optional(),
block: z.union([z.string().length(66).startsWith('0x'), z.number()]).optional(),
'build-block-mode': z.nativeEnum(BuildBlockMode).optional(),
'import-storage': z.any().optional(),
'mock-signature-host': z.boolean().optional(),
Expand Down
7 changes: 4 additions & 3 deletions src/setup.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import '@polkadot/types-codec'
import { DataSource } from 'typeorm'
import { HexString } from '@polkadot/util/types'
import { ProviderInterface } from '@polkadot/rpc-provider/types'
import { WsProvider } from '@polkadot/api'

import { Api } from './api'
import { Blockchain } from './blockchain'
import { Config } from './schema'
import { GenesisProvider } from './genesis-provider'
import { InherentProviders, SetTimestamp, SetValidationData } from './blockchain/inherent'
import { InherentProviders, ParaInherentEnter, SetTimestamp, SetValidationData } from './blockchain/inherent'
import { defaultLogger } from './logger'
import { importStorage, overrideWasm } from './utils/import-storage'
import { openDb } from './db'
Expand Down Expand Up @@ -45,15 +46,15 @@ export const setup = async (argv: Config) => {

const header = await api.getHeader(blockHash)

const inherents = new InherentProviders(new SetTimestamp(), [new SetValidationData()])
const inherents = new InherentProviders(new SetTimestamp(), [new SetValidationData(), new ParaInherentEnter()])

const chain = new Blockchain({
api,
buildBlockMode: argv['build-block-mode'],
inherentProvider: inherents,
db,
header: {
hash: blockHash,
hash: blockHash as HexString,
number: Number(header.number),
},
})
Expand Down
Loading