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

add execute block call in follow-chain #513

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
100 changes: 77 additions & 23 deletions packages/chopsticks/src/plugins/follow-chain/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Block, defaultLogger, printRuntimeLogs, runTask, taskHandler } from '@acala-network/chopsticks-core'
import { Header } from '@polkadot/types/interfaces'
import { Block as BlockType, Header } from '@polkadot/types/interfaces'
import { HexString } from '@polkadot/util/types'
import _ from 'lodash'
import type { Argv } from 'yargs'
Expand Down Expand Up @@ -29,12 +29,19 @@ export const cli = (y: Argv) => {
choices: ['latest', 'finalized'],
default: 'finalized',
},
'execute-block': {
desc: 'Call TryRuntime_execute_block, make sure the wasm is provided and built with `try-runtime` feature',
boolean: true,
},
}),
async (argv) => {
const port = argv.port ?? 8000
const endpoint = argv.endpoint as string
if (/^(https|http):\/\//.test(endpoint || '')) {
throw Error('http provider is not supported')
throw Error('http endpoint is not supported')
}
if (argv.executeBlock && !argv.wasmOverride) {
throw Error('`execute-block` requires `wasm-override`')
}

const context = await setupContext(argv as Config, true)
Expand All @@ -54,33 +61,80 @@ export const cli = (y: Argv) => {
const header = registry.createType<Header>('Header', data)
const wasm = await parent.wasm

const block = new Block(chain, header.number.toNumber(), header.hash.toHex(), parent)
const block = new Block(chain, header.number.toNumber(), header.hash.toHex(), parent, {
storage: parent.storage,
qiweiii marked this conversation as resolved.
Show resolved Hide resolved
})
await chain.setHead(block)

const calls: [string, HexString[]][] = [['Core_initialize_block', [header.toHex()]]]
{
// replay block
const calls: [string, HexString[]][] = [['Core_initialize_block', [header.toHex()]]]

for (const extrinsic of await block.extrinsics) {
calls.push(['BlockBuilder_apply_extrinsic', [extrinsic]])
}
for (const extrinsic of await block.extrinsics) {
calls.push(['BlockBuilder_apply_extrinsic', [extrinsic]])
}

calls.push(['BlockBuilder_finalize_block', []])

const runBlockResult = await runTask(
{
wasm,
calls,
mockSignatureHost: false,
allowUnresolvedImports: false,
runtimeLogLevel: (argv.runtimeLogLevel as number) || 0,
},
taskHandler(parent),
)

if ('Error' in runBlockResult) {
throw new Error(runBlockResult.Error)
}

calls.push(['BlockBuilder_finalize_block', []])

const result = await runTask(
{
wasm,
calls,
mockSignatureHost: false,
allowUnresolvedImports: false,
runtimeLogLevel: (argv.runtimeLogLevel as number) || 0,
},
taskHandler(parent),
)

if ('Error' in result) {
throw new Error(result.Error)
printRuntimeLogs(runBlockResult.Call.runtimeLogs)
}

printRuntimeLogs(result.Call.runtimeLogs)
{
// try execute block
if (!argv.executeBlock) return
registry.register({
TryStateSelect: {
_enum: {
None: null,
All: null,
RoundRobin: 'u32',
Only: 'Vec<Vec<u8>>',
},
},
})

const blockData = registry.createType<BlockType>('Block', {
header: await block.header,
extrinsics: await block.extrinsics,
})

const select_try_state = registry.createType('TryStateSelect', 'All')

const calls: [string, HexString[]][] = [
['TryRuntime_execute_block', [blockData.toHex(), '0x00', '0x00', select_try_state.toHex()]],
]

const executeBlockResult = await runTask(
{
wasm,
calls,
mockSignatureHost: false,
allowUnresolvedImports: false,
runtimeLogLevel: (argv.runtimeLogLevel as number) || 0,
},
taskHandler(parent),
)

if ('Error' in executeBlockResult) {
throw new Error(executeBlockResult.Error)
}
printRuntimeLogs(executeBlockResult.Call.runtimeLogs)
}
} catch (e) {
logger.error(e, 'Error when processing new head')
await close()
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/blockchain/block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ export class Block {
parentBlock?: Block,
block?: {
/** See `@polkadot/types/interfaces` Header */
header: Header
header?: Header
/** Extrinsics */
extrinsics: HexString[]
extrinsics?: HexString[]
/** Storage provider. Default to {@link RemoteStorageLayer} with {@link Blockchain.api chain.api} as remote. */
storage?: StorageLayerProvider
/** Storage diff to apply. */
Expand Down