@acala-network/chopsticks 0.9.1-2 → 0.9.1-3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/cli-options.js +30 -15
- package/dist/cjs/cli.js +69 -80
- package/dist/cjs/context.js +93 -64
- package/dist/cjs/index.js +32 -20
- package/dist/cjs/logger.js +18 -5
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/plugins/decode-key/index.js +23 -20
- package/dist/cjs/plugins/dry-run/cli.js +46 -41
- package/dist/cjs/plugins/dry-run/dry-run-extrinsic.js +37 -21
- package/dist/cjs/plugins/dry-run/dry-run-preimage.js +101 -47
- package/dist/cjs/plugins/dry-run/index.js +18 -17
- package/dist/cjs/plugins/dry-run/rpc.js +48 -74
- package/dist/cjs/plugins/follow-chain/index.js +78 -46
- package/dist/cjs/plugins/index.js +76 -40
- package/dist/cjs/plugins/new-block/index.js +21 -53
- package/dist/cjs/plugins/run-block/index.js +145 -104
- package/dist/cjs/plugins/set-block-build-mode/index.js +17 -25
- package/dist/cjs/plugins/set-head/index.js +13 -23
- package/dist/cjs/plugins/set-runtime-log-level/index.js +16 -23
- package/dist/cjs/plugins/set-storage/index.js +16 -35
- package/dist/cjs/plugins/time-travel/index.js +13 -23
- package/dist/cjs/plugins/try-runtime/index.js +51 -42
- package/dist/cjs/plugins/types.js +43 -18
- package/dist/cjs/rpc/index.js +30 -21
- package/dist/cjs/schema/index.js +77 -48
- package/dist/cjs/server.js +89 -65
- package/dist/cjs/setup-with-server.js +19 -13
- package/dist/cjs/types.js +30 -18
- package/dist/cjs/utils/decoder.js +32 -16
- package/dist/cjs/utils/generate-html-diff.js +38 -19
- package/dist/cjs/utils/index.js +20 -19
- package/dist/cjs/utils/open-html.js +12 -6
- package/dist/cjs/utils/override.js +40 -27
- package/dist/cjs/utils/tunnel.js +11 -14
- package/dist/esm/cli-options.js +11 -11
- package/dist/esm/cli.js +45 -60
- package/dist/esm/context.js +20 -24
- package/dist/esm/plugins/decode-key/index.js +9 -12
- package/dist/esm/plugins/dry-run/cli.js +32 -33
- package/dist/esm/plugins/dry-run/dry-run-extrinsic.js +18 -8
- package/dist/esm/plugins/dry-run/dry-run-preimage.js +72 -24
- package/dist/esm/plugins/dry-run/rpc.js +14 -24
- package/dist/esm/plugins/follow-chain/index.js +52 -28
- package/dist/esm/plugins/index.js +8 -6
- package/dist/esm/plugins/new-block/index.js +8 -9
- package/dist/esm/plugins/run-block/index.js +97 -65
- package/dist/esm/plugins/set-block-build-mode/index.js +4 -3
- package/dist/esm/plugins/set-head/index.js +2 -4
- package/dist/esm/plugins/set-runtime-log-level/index.js +4 -3
- package/dist/esm/plugins/set-storage/index.js +3 -4
- package/dist/esm/plugins/time-travel/index.js +2 -4
- package/dist/esm/plugins/try-runtime/index.js +33 -30
- package/dist/esm/rpc/index.js +18 -15
- package/dist/esm/schema/index.js +31 -18
- package/dist/esm/server.js +70 -52
- package/dist/esm/setup-with-server.js +3 -3
- package/dist/esm/types.js +12 -1
- package/dist/esm/utils/decoder.js +12 -4
- package/dist/esm/utils/generate-html-diff.js +10 -6
- package/dist/esm/utils/open-html.js +1 -1
- package/dist/esm/utils/override.js +11 -13
- package/dist/esm/utils/tunnel.js +1 -8
- package/package.json +13 -17
- package/dist/esm/package.json +0 -1
- /package/{chopsticks.js → chopsticks.cjs} +0 -0
package/dist/esm/context.js
CHANGED
|
@@ -3,13 +3,14 @@ import { GenesisProvider, defaultLogger, isUrl, setup, timeTravel } from '@acala
|
|
|
3
3
|
import { SqliteDatabase } from '@acala-network/chopsticks-db';
|
|
4
4
|
import { overrideStorage, overrideWasm } from './utils/override';
|
|
5
5
|
import axios from 'axios';
|
|
6
|
-
const logger = defaultLogger.child({
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
const logger = defaultLogger.child({
|
|
7
|
+
name: 'setup-context'
|
|
8
|
+
});
|
|
9
|
+
export const genesisFromUrl = async (url)=>{
|
|
10
|
+
const getFile = async (url)=>{
|
|
9
11
|
if (isUrl(url)) {
|
|
10
|
-
return axios.get(url).then((x)
|
|
11
|
-
}
|
|
12
|
-
else if (typeof process === 'object') {
|
|
12
|
+
return axios.get(url).then((x)=>x.data);
|
|
13
|
+
} else if (typeof process === 'object') {
|
|
13
14
|
const { lstatSync, readFileSync } = await import('node:fs');
|
|
14
15
|
if (lstatSync(url).isFile()) {
|
|
15
16
|
return JSON.parse(String(readFileSync(url)));
|
|
@@ -19,13 +20,12 @@ export const genesisFromUrl = async (url) => {
|
|
|
19
20
|
};
|
|
20
21
|
return new GenesisProvider(await getFile(url));
|
|
21
22
|
};
|
|
22
|
-
export const setupContext = async (argv, overrideParent = false)
|
|
23
|
+
export const setupContext = async (argv, overrideParent = false)=>{
|
|
23
24
|
let genesis;
|
|
24
25
|
if (argv.genesis) {
|
|
25
26
|
if (typeof argv.genesis === 'string') {
|
|
26
27
|
genesis = await genesisFromUrl(argv.genesis);
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
28
|
+
} else {
|
|
29
29
|
genesis = new GenesisProvider(argv.genesis);
|
|
30
30
|
}
|
|
31
31
|
}
|
|
@@ -40,7 +40,7 @@ export const setupContext = async (argv, overrideParent = false) => {
|
|
|
40
40
|
runtimeLogLevel: argv['runtime-log-level'],
|
|
41
41
|
registeredTypes: argv['registered-types'],
|
|
42
42
|
offchainWorker: argv['offchain-worker'],
|
|
43
|
-
maxMemoryBlockCount: argv['max-memory-block-count']
|
|
43
|
+
maxMemoryBlockCount: argv['max-memory-block-count']
|
|
44
44
|
});
|
|
45
45
|
// load block from db
|
|
46
46
|
if (chain.db) {
|
|
@@ -48,39 +48,35 @@ export const setupContext = async (argv, overrideParent = false) => {
|
|
|
48
48
|
let blockData = null;
|
|
49
49
|
if (typeof argv.resume === 'string' && argv.resume.startsWith('0x')) {
|
|
50
50
|
blockData = await chain.db.queryBlock(argv.resume);
|
|
51
|
-
}
|
|
52
|
-
else if (typeof argv.resume === 'boolean' || argv.resume === 'true') {
|
|
51
|
+
} else if (typeof argv.resume === 'boolean' || argv.resume === 'true') {
|
|
53
52
|
blockData = await chain.db.queryHighestBlock();
|
|
54
|
-
}
|
|
55
|
-
else if (Number.isInteger(+argv.resume)) {
|
|
53
|
+
} else if (Number.isInteger(+argv.resume)) {
|
|
56
54
|
blockData = await chain.db.queryBlockByNumber(+argv.resume);
|
|
57
|
-
}
|
|
58
|
-
else {
|
|
55
|
+
} else {
|
|
59
56
|
throw new Error(`Resume failed. Invalid resume option ${argv.resume}`);
|
|
60
57
|
}
|
|
61
58
|
if (blockData) {
|
|
62
59
|
const block = await chain.loadBlockFromDB(blockData.number);
|
|
63
|
-
block &&
|
|
60
|
+
block && await chain.setHead(block);
|
|
64
61
|
logger.info(`Resume from block ${blockData.number}, hash: ${blockData.hash}`);
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
62
|
+
} else {
|
|
67
63
|
throw new Error(`Resume failed. Cannot find block ${argv.resume}`);
|
|
68
64
|
}
|
|
69
65
|
}
|
|
70
66
|
}
|
|
71
|
-
if (argv.timestamp)
|
|
72
|
-
await timeTravel(chain, argv.timestamp);
|
|
67
|
+
if (argv.timestamp) await timeTravel(chain, argv.timestamp);
|
|
73
68
|
let at;
|
|
74
69
|
if (overrideParent) {
|
|
75
70
|
// in case of run block we need to apply wasm-override and import-storage to parent block
|
|
76
71
|
const block = await chain.head.parentBlock;
|
|
77
|
-
if (!block)
|
|
78
|
-
throw new Error('Cannot find parent block');
|
|
72
|
+
if (!block) throw new Error('Cannot find parent block');
|
|
79
73
|
at = block.hash;
|
|
80
74
|
}
|
|
81
75
|
// override wasm before importing storage, in case new pallets have been
|
|
82
76
|
// added that have storage imports
|
|
83
77
|
await overrideWasm(chain, argv['wasm-override'], at);
|
|
84
78
|
await overrideStorage(chain, argv['import-storage'], at);
|
|
85
|
-
return {
|
|
79
|
+
return {
|
|
80
|
+
chain
|
|
81
|
+
};
|
|
86
82
|
};
|
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
import { decodeKey } from '@acala-network/chopsticks-core';
|
|
2
2
|
import { defaultOptions } from '../../cli-options';
|
|
3
3
|
import { setupContext } from '../../context';
|
|
4
|
-
export const cli = (y)
|
|
5
|
-
y.command('decode-key <key>', 'Deocde a key', (yargs)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
...defaultOptions,
|
|
12
|
-
}), async (argv) => {
|
|
4
|
+
export const cli = (y)=>{
|
|
5
|
+
y.command('decode-key <key>', 'Deocde a key', (yargs)=>yargs.positional('key', {
|
|
6
|
+
desc: 'Key to decode',
|
|
7
|
+
type: 'string'
|
|
8
|
+
}).options({
|
|
9
|
+
...defaultOptions
|
|
10
|
+
}), async (argv)=>{
|
|
13
11
|
const context = await setupContext(argv);
|
|
14
12
|
const { storage, decodedKey } = decodeKey(await context.chain.head.meta, context.chain.head, argv.key);
|
|
15
13
|
if (storage && decodedKey) {
|
|
16
|
-
console.log(`${storage.section}.${storage.method}`, decodedKey.args.map((x)
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
14
|
+
console.log(`${storage.section}.${storage.method}`, decodedKey.args.map((x)=>JSON.stringify(x.toHuman())).join(', '));
|
|
15
|
+
} else {
|
|
19
16
|
console.log('Unknown');
|
|
20
17
|
}
|
|
21
18
|
process.exit(0);
|
|
@@ -1,41 +1,40 @@
|
|
|
1
1
|
import { defaultOptions, mockOptions } from '../../cli-options';
|
|
2
2
|
import { dryRunExtrinsic } from './dry-run-extrinsic';
|
|
3
3
|
import { dryRunPreimage } from './dry-run-preimage';
|
|
4
|
-
export const cli = (y)
|
|
5
|
-
y.command('dry-run', 'Dry run an extrinsic', (yargs)
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
4
|
+
export const cli = (y)=>{
|
|
5
|
+
y.command('dry-run', 'Dry run an extrinsic', (yargs)=>yargs.options({
|
|
6
|
+
...defaultOptions,
|
|
7
|
+
...mockOptions,
|
|
8
|
+
extrinsic: {
|
|
9
|
+
desc: 'Extrinsic or call to dry run. If you pass call here then address is required to fake signature',
|
|
10
|
+
string: true
|
|
11
|
+
},
|
|
12
|
+
address: {
|
|
13
|
+
desc: 'Address to fake sign extrinsic',
|
|
14
|
+
string: true
|
|
15
|
+
},
|
|
16
|
+
preimage: {
|
|
17
|
+
desc: 'Preimage to dry run',
|
|
18
|
+
string: true
|
|
19
|
+
},
|
|
20
|
+
at: {
|
|
21
|
+
desc: 'Block hash to dry run',
|
|
22
|
+
string: true
|
|
23
|
+
},
|
|
24
|
+
'output-path': {
|
|
25
|
+
desc: 'File path to print output',
|
|
26
|
+
string: true
|
|
27
|
+
},
|
|
28
|
+
html: {
|
|
29
|
+
desc: 'Generate html with storage diff'
|
|
30
|
+
},
|
|
31
|
+
open: {
|
|
32
|
+
desc: 'Open generated html'
|
|
33
|
+
}
|
|
34
|
+
}), async (argv)=>{
|
|
35
35
|
if (argv.preimage) {
|
|
36
36
|
await dryRunPreimage(argv);
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
37
|
+
} else {
|
|
39
38
|
await dryRunExtrinsic(argv);
|
|
40
39
|
}
|
|
41
40
|
});
|
|
@@ -4,9 +4,12 @@ import { defaultLogger } from '../../logger';
|
|
|
4
4
|
import { generateHtmlDiffPreviewFile } from '../../utils/generate-html-diff';
|
|
5
5
|
import { openHtml } from '../../utils/open-html';
|
|
6
6
|
import { setupContext } from '../../context';
|
|
7
|
-
export const dryRunExtrinsic = async (argv)
|
|
7
|
+
export const dryRunExtrinsic = async (argv)=>{
|
|
8
8
|
const context = await setupContext(argv);
|
|
9
|
-
const input = argv['address'] ? {
|
|
9
|
+
const input = argv['address'] ? {
|
|
10
|
+
call: argv['extrinsic'],
|
|
11
|
+
address: argv['address']
|
|
12
|
+
} : argv['extrinsic'];
|
|
10
13
|
const { outcome, storageDiff } = await context.chain.dryRunExtrinsic(input, argv['at']);
|
|
11
14
|
if (outcome.isErr) {
|
|
12
15
|
throw new Error(outcome.asErr.toString());
|
|
@@ -18,12 +21,19 @@ export const dryRunExtrinsic = async (argv) => {
|
|
|
18
21
|
if (argv['open']) {
|
|
19
22
|
openHtml(filePath);
|
|
20
23
|
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
} else if (argv['output-path']) {
|
|
25
|
+
writeFileSync(argv['output-path'], JSON.stringify({
|
|
26
|
+
outcome: outcome.toHuman(),
|
|
27
|
+
storageDiff
|
|
28
|
+
}, null, 2));
|
|
29
|
+
} else {
|
|
30
|
+
console.dir({
|
|
31
|
+
outcome: outcome.toHuman(),
|
|
32
|
+
storageDiff
|
|
33
|
+
}, {
|
|
34
|
+
depth: null,
|
|
35
|
+
colors: false
|
|
36
|
+
});
|
|
27
37
|
}
|
|
28
38
|
process.exit(0);
|
|
29
39
|
};
|
|
@@ -5,7 +5,7 @@ import { generateHtmlDiffPreviewFile } from '../../utils/generate-html-diff';
|
|
|
5
5
|
import { newHeader, printRuntimeLogs, runTask, setStorage, taskHandler } from '@acala-network/chopsticks-core';
|
|
6
6
|
import { openHtml } from '../../utils/open-html';
|
|
7
7
|
import { setupContext } from '../../context';
|
|
8
|
-
export const dryRunPreimage = async (argv)
|
|
8
|
+
export const dryRunPreimage = async (argv)=>{
|
|
9
9
|
const context = await setupContext(argv);
|
|
10
10
|
const extrinsic = argv['preimage'];
|
|
11
11
|
const block = context.chain.head;
|
|
@@ -15,23 +15,37 @@ export const dryRunPreimage = async (argv) => {
|
|
|
15
15
|
const hash = blake2AsHex(data, 256);
|
|
16
16
|
await setStorage(context.chain, {
|
|
17
17
|
Preimage: {
|
|
18
|
-
PreimageFor: [
|
|
18
|
+
PreimageFor: [
|
|
19
|
+
[
|
|
20
|
+
[
|
|
21
|
+
[
|
|
22
|
+
hash,
|
|
23
|
+
data.byteLength
|
|
24
|
+
]
|
|
25
|
+
],
|
|
26
|
+
extrinsic
|
|
27
|
+
]
|
|
28
|
+
],
|
|
19
29
|
StatusFor: [
|
|
20
30
|
[
|
|
21
|
-
[
|
|
31
|
+
[
|
|
32
|
+
hash
|
|
33
|
+
],
|
|
22
34
|
{
|
|
23
35
|
Requested: {
|
|
24
36
|
count: 1,
|
|
25
|
-
len: data.byteLength
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
]
|
|
29
|
-
]
|
|
37
|
+
len: data.byteLength
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
]
|
|
30
42
|
},
|
|
31
43
|
Scheduler: {
|
|
32
44
|
Agenda: [
|
|
33
45
|
[
|
|
34
|
-
[
|
|
46
|
+
[
|
|
47
|
+
block.number + 1
|
|
48
|
+
],
|
|
35
49
|
[
|
|
36
50
|
{
|
|
37
51
|
maybeId: '0x64656d6f637261633a0000000000000000000000000000000000000000000000',
|
|
@@ -39,29 +53,60 @@ export const dryRunPreimage = async (argv) => {
|
|
|
39
53
|
call: {
|
|
40
54
|
Lookup: {
|
|
41
55
|
hash: hash,
|
|
42
|
-
len: data.byteLength
|
|
43
|
-
}
|
|
56
|
+
len: data.byteLength
|
|
57
|
+
}
|
|
44
58
|
},
|
|
45
|
-
origin: {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
59
|
+
origin: {
|
|
60
|
+
system: {
|
|
61
|
+
Root: null
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
]
|
|
66
|
+
]
|
|
49
67
|
],
|
|
50
|
-
Lookup: [
|
|
51
|
-
|
|
68
|
+
Lookup: [
|
|
69
|
+
[
|
|
70
|
+
[
|
|
71
|
+
'0x64656d6f637261633a0000000000000000000000000000000000000000000000'
|
|
72
|
+
],
|
|
73
|
+
[
|
|
74
|
+
block.number + 1,
|
|
75
|
+
0
|
|
76
|
+
]
|
|
77
|
+
]
|
|
78
|
+
]
|
|
79
|
+
}
|
|
52
80
|
});
|
|
53
|
-
const calls = [
|
|
54
|
-
|
|
55
|
-
|
|
81
|
+
const calls = [
|
|
82
|
+
[
|
|
83
|
+
'Core_initialize_block',
|
|
84
|
+
[
|
|
85
|
+
header.toHex()
|
|
86
|
+
]
|
|
87
|
+
]
|
|
88
|
+
];
|
|
89
|
+
for (const inherent of (await block.chain.getInherents())){
|
|
90
|
+
calls.push([
|
|
91
|
+
'BlockBuilder_apply_extrinsic',
|
|
92
|
+
[
|
|
93
|
+
inherent
|
|
94
|
+
]
|
|
95
|
+
]);
|
|
56
96
|
}
|
|
57
|
-
calls.push([
|
|
58
|
-
|
|
97
|
+
calls.push([
|
|
98
|
+
'BlockBuilder_finalize_block',
|
|
99
|
+
[]
|
|
100
|
+
]);
|
|
101
|
+
defaultLogger.info({
|
|
102
|
+
preimage: registry.createType('Call', data).toHuman()
|
|
103
|
+
}, 'Dry run preimage');
|
|
59
104
|
const result = await runTask({
|
|
60
105
|
wasm: await block.wasm,
|
|
61
106
|
calls,
|
|
62
107
|
mockSignatureHost: false,
|
|
63
108
|
allowUnresolvedImports: false,
|
|
64
|
-
runtimeLogLevel: argv['runtime-log-level'] || 0
|
|
109
|
+
runtimeLogLevel: argv['runtime-log-level'] || 0
|
|
65
110
|
}, taskHandler(block));
|
|
66
111
|
if ('Error' in result) {
|
|
67
112
|
throw new Error(result.Error);
|
|
@@ -76,7 +121,10 @@ export const dryRunPreimage = async (argv) => {
|
|
|
76
121
|
// this is usefull to test something after preimage is applied
|
|
77
122
|
if (argv['extrinsic']) {
|
|
78
123
|
await context.chain.newBlock();
|
|
79
|
-
const input = argv['address'] ? {
|
|
124
|
+
const input = argv['address'] ? {
|
|
125
|
+
call: argv['extrinsic'],
|
|
126
|
+
address: argv['address']
|
|
127
|
+
} : argv['extrinsic'];
|
|
80
128
|
const { outcome, storageDiff } = await context.chain.dryRunExtrinsic(input);
|
|
81
129
|
if (outcome.isErr) {
|
|
82
130
|
throw new Error(outcome.asErr.toString());
|
|
@@ -2,35 +2,26 @@ import { z } from 'zod';
|
|
|
2
2
|
import { ResponseError } from '@acala-network/chopsticks-core';
|
|
3
3
|
import { decodeStorageDiff } from '../../utils/decoder';
|
|
4
4
|
import { generateHtmlDiff } from '../../utils/generate-html-diff';
|
|
5
|
-
const zHex = z.custom((val)
|
|
5
|
+
const zHex = z.custom((val)=>/^0x\w+$/.test(val));
|
|
6
6
|
const zHash = z.string().length(66).and(zHex);
|
|
7
7
|
const zParaId = z.string().regex(/^\d+$/).transform(Number);
|
|
8
8
|
const schema = z.object({
|
|
9
9
|
raw: z.boolean().optional(),
|
|
10
10
|
html: z.boolean().optional(),
|
|
11
|
-
extrinsic: zHex
|
|
12
|
-
.or(z.object({
|
|
11
|
+
extrinsic: zHex.or(z.object({
|
|
13
12
|
call: zHex,
|
|
14
|
-
address: zHex
|
|
15
|
-
}))
|
|
16
|
-
|
|
17
|
-
hrmp: z
|
|
18
|
-
.record(zParaId, z
|
|
19
|
-
.array(z.object({
|
|
13
|
+
address: zHex
|
|
14
|
+
})).optional(),
|
|
15
|
+
hrmp: z.record(zParaId, z.array(z.object({
|
|
20
16
|
sentAt: z.number(),
|
|
21
|
-
data: zHex
|
|
22
|
-
}))
|
|
23
|
-
|
|
24
|
-
.optional(),
|
|
25
|
-
dmp: z
|
|
26
|
-
.array(z.object({
|
|
17
|
+
data: zHex
|
|
18
|
+
})).min(1)).optional(),
|
|
19
|
+
dmp: z.array(z.object({
|
|
27
20
|
sentAt: z.number(),
|
|
28
|
-
msg: zHex
|
|
29
|
-
}))
|
|
30
|
-
.min(1)
|
|
31
|
-
.optional(),
|
|
21
|
+
msg: zHex
|
|
22
|
+
})).min(1).optional(),
|
|
32
23
|
ump: z.record(zParaId, z.array(zHex).min(1)).optional(),
|
|
33
|
-
at: zHash.optional()
|
|
24
|
+
at: zHash.optional()
|
|
34
25
|
});
|
|
35
26
|
// custom rpc name (optional). e.g. dryRun will be called as dev_dryRun
|
|
36
27
|
export const name = 'dryRun';
|
|
@@ -63,10 +54,9 @@ export const name = 'dryRun';
|
|
|
63
54
|
]
|
|
64
55
|
* await ws.send('dev_dryRun', params)
|
|
65
56
|
* ```
|
|
66
|
-
*/
|
|
67
|
-
export const rpc = async (context, [params]) => {
|
|
57
|
+
*/ export const rpc = async (context, [params])=>{
|
|
68
58
|
const { html, extrinsic, hrmp, dmp, ump, raw, at } = schema.parse(params);
|
|
69
|
-
const dryRun = async ()
|
|
59
|
+
const dryRun = async ()=>{
|
|
70
60
|
if (extrinsic) {
|
|
71
61
|
const { outcome, storageDiff } = await context.chain.dryRunExtrinsic(extrinsic, at);
|
|
72
62
|
if (outcome.isErr) {
|
|
@@ -96,6 +86,6 @@ export const rpc = async (context, [params]) => {
|
|
|
96
86
|
return {
|
|
97
87
|
old: oldState,
|
|
98
88
|
new: newState,
|
|
99
|
-
delta
|
|
89
|
+
delta
|
|
100
90
|
};
|
|
101
91
|
};
|
|
@@ -4,21 +4,31 @@ import { createServer } from '../../server';
|
|
|
4
4
|
import { defaultOptions } from '../../cli-options';
|
|
5
5
|
import { handler } from '../../rpc';
|
|
6
6
|
import { setupContext } from '../../context';
|
|
7
|
-
const logger = defaultLogger.child({
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
7
|
+
const logger = defaultLogger.child({
|
|
8
|
+
name: 'follow-chain'
|
|
9
|
+
});
|
|
10
|
+
const options = _.pick(defaultOptions, [
|
|
11
|
+
'endpoint',
|
|
12
|
+
'wasm-override',
|
|
13
|
+
'runtime-log-level',
|
|
14
|
+
'offchain-worker'
|
|
15
|
+
]);
|
|
16
|
+
export const cli = (y)=>{
|
|
17
|
+
y.command('follow-chain', 'Always follow the latest block on upstream', (yargs)=>yargs.options({
|
|
18
|
+
...options,
|
|
19
|
+
port: {
|
|
20
|
+
desc: 'Port to listen on',
|
|
21
|
+
number: true
|
|
22
|
+
},
|
|
23
|
+
'head-mode': {
|
|
24
|
+
desc: 'Head mode',
|
|
25
|
+
choices: [
|
|
26
|
+
'latest',
|
|
27
|
+
'finalized'
|
|
28
|
+
],
|
|
29
|
+
default: 'finalized'
|
|
30
|
+
}
|
|
31
|
+
}), async (argv)=>{
|
|
22
32
|
const port = argv.port ?? 8000;
|
|
23
33
|
const endpoint = argv.endpoint;
|
|
24
34
|
if (/^(https|http):\/\//.test(endpoint || '')) {
|
|
@@ -28,37 +38,51 @@ export const cli = (y) => {
|
|
|
28
38
|
const { close, port: listenPort } = await createServer(handler(context), port);
|
|
29
39
|
logger.info(`${await context.chain.api.getSystemChain()} RPC listening on port ${listenPort}`);
|
|
30
40
|
const chain = context.chain;
|
|
31
|
-
chain.api[argv.headMode === 'latest' ? 'subscribeRemoteNewHeads' : 'subscribeRemoteFinalizedHeads'](async (error, data)
|
|
41
|
+
chain.api[argv.headMode === 'latest' ? 'subscribeRemoteNewHeads' : 'subscribeRemoteFinalizedHeads'](async (error, data)=>{
|
|
32
42
|
try {
|
|
33
|
-
if (error)
|
|
34
|
-
|
|
35
|
-
|
|
43
|
+
if (error) throw error;
|
|
44
|
+
logger.info({
|
|
45
|
+
header: data
|
|
46
|
+
}, `Follow ${argv.headMode} head from upstream`);
|
|
36
47
|
const parent = await chain.getBlock(data.parentHash);
|
|
37
|
-
if (!parent)
|
|
38
|
-
throw Error(`Cannot find parent', ${data.parentHash}`);
|
|
48
|
+
if (!parent) throw Error(`Cannot find parent', ${data.parentHash}`);
|
|
39
49
|
const registry = await parent.registry;
|
|
40
50
|
const header = registry.createType('Header', data);
|
|
41
51
|
const wasm = await parent.wasm;
|
|
42
52
|
const block = new Block(chain, header.number.toNumber(), header.hash.toHex(), parent);
|
|
43
53
|
await chain.setHead(block);
|
|
44
|
-
const calls = [
|
|
45
|
-
|
|
46
|
-
|
|
54
|
+
const calls = [
|
|
55
|
+
[
|
|
56
|
+
'Core_initialize_block',
|
|
57
|
+
[
|
|
58
|
+
header.toHex()
|
|
59
|
+
]
|
|
60
|
+
]
|
|
61
|
+
];
|
|
62
|
+
for (const extrinsic of (await block.extrinsics)){
|
|
63
|
+
calls.push([
|
|
64
|
+
'BlockBuilder_apply_extrinsic',
|
|
65
|
+
[
|
|
66
|
+
extrinsic
|
|
67
|
+
]
|
|
68
|
+
]);
|
|
47
69
|
}
|
|
48
|
-
calls.push([
|
|
70
|
+
calls.push([
|
|
71
|
+
'BlockBuilder_finalize_block',
|
|
72
|
+
[]
|
|
73
|
+
]);
|
|
49
74
|
const result = await runTask({
|
|
50
75
|
wasm,
|
|
51
76
|
calls,
|
|
52
77
|
mockSignatureHost: false,
|
|
53
78
|
allowUnresolvedImports: false,
|
|
54
|
-
runtimeLogLevel: argv.runtimeLogLevel || 0
|
|
79
|
+
runtimeLogLevel: argv.runtimeLogLevel || 0
|
|
55
80
|
}, taskHandler(parent));
|
|
56
81
|
if ('Error' in result) {
|
|
57
82
|
throw new Error(result.Error);
|
|
58
83
|
}
|
|
59
84
|
printRuntimeLogs(result.Call.runtimeLogs);
|
|
60
|
-
}
|
|
61
|
-
catch (e) {
|
|
85
|
+
} catch (e) {
|
|
62
86
|
logger.error(e, 'Error when processing new head');
|
|
63
87
|
await close();
|
|
64
88
|
process.exit(1);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import _ from 'lodash';
|
|
2
2
|
import { defaultLogger } from '../logger';
|
|
3
|
-
const logger = defaultLogger.child({
|
|
3
|
+
const logger = defaultLogger.child({
|
|
4
|
+
name: 'plugin'
|
|
5
|
+
});
|
|
4
6
|
export const pluginHandlers = {};
|
|
5
7
|
const plugins = [
|
|
6
8
|
'decode-key',
|
|
@@ -13,10 +15,10 @@ const plugins = [
|
|
|
13
15
|
'set-runtime-log-level',
|
|
14
16
|
'set-storage',
|
|
15
17
|
'time-travel',
|
|
16
|
-
'try-runtime'
|
|
18
|
+
'try-runtime'
|
|
17
19
|
];
|
|
18
|
-
(async ()
|
|
19
|
-
for (const plugin of plugins)
|
|
20
|
+
(async ()=>{
|
|
21
|
+
for (const plugin of plugins){
|
|
20
22
|
const { rpc, name } = await import(`./${plugin}`);
|
|
21
23
|
if (rpc) {
|
|
22
24
|
const methodName = name || _.camelCase(plugin);
|
|
@@ -25,8 +27,8 @@ const plugins = [
|
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
29
|
})();
|
|
28
|
-
export const pluginExtendCli = async (y)
|
|
29
|
-
for (const plugin of plugins)
|
|
30
|
+
export const pluginExtendCli = async (y)=>{
|
|
31
|
+
for (const plugin of plugins){
|
|
30
32
|
const { cli } = await import(`./${plugin}`);
|
|
31
33
|
if (cli) {
|
|
32
34
|
cli(y);
|
|
@@ -37,8 +37,7 @@ import { defaultLogger } from '../../logger';
|
|
|
37
37
|
* // this will create two blocks with block height 100000001 and 100000002
|
|
38
38
|
* await ws.send('dev_newBlock', [{ count: 2, unsafeBlockHeight: 100000001 }])
|
|
39
39
|
* ```
|
|
40
|
-
*/
|
|
41
|
-
export const rpc = async (context, params) => {
|
|
40
|
+
*/ export const rpc = async (context, params)=>{
|
|
42
41
|
const [param] = params;
|
|
43
42
|
const { count, to, hrmp, ump, dmp, transactions, unsafeBlockHeight } = param || {};
|
|
44
43
|
const now = context.chain.head.number;
|
|
@@ -48,19 +47,19 @@ export const rpc = async (context, params) => {
|
|
|
48
47
|
if (unsafeBlockHeight < now) {
|
|
49
48
|
throw new ResponseError(1, 'unsafeBlockHeight must be greater than current block height');
|
|
50
49
|
}
|
|
51
|
-
for
|
|
52
|
-
const block = await context.chain
|
|
53
|
-
.newBlock({
|
|
50
|
+
for(let i = 0; i < finalCount; i++){
|
|
51
|
+
const block = await context.chain.newBlock({
|
|
54
52
|
transactions,
|
|
55
53
|
horizontalMessages: hrmp,
|
|
56
54
|
upwardMessages: ump,
|
|
57
55
|
downwardMessages: dmp,
|
|
58
|
-
unsafeBlockHeight: i === 0 ? unsafeBlockHeight : undefined
|
|
59
|
-
})
|
|
60
|
-
.catch((error) => {
|
|
56
|
+
unsafeBlockHeight: i === 0 ? unsafeBlockHeight : undefined
|
|
57
|
+
}).catch((error)=>{
|
|
61
58
|
throw new ResponseError(1, error.toString());
|
|
62
59
|
});
|
|
63
|
-
defaultLogger.debug({
|
|
60
|
+
defaultLogger.debug({
|
|
61
|
+
hash: block.hash
|
|
62
|
+
}, 'dev_newBlock');
|
|
64
63
|
finalHash = block.hash;
|
|
65
64
|
}
|
|
66
65
|
return finalHash;
|