@acala-network/chopsticks 0.3.0 → 0.3.2
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/README.md +8 -2
- package/dist/blockchain/block-builder.d.ts +7 -3
- package/dist/blockchain/block-builder.js +136 -15
- package/dist/blockchain/block.d.ts +1 -1
- package/dist/blockchain/index.d.ts +11 -1
- package/dist/blockchain/index.js +22 -0
- package/dist/blockchain/inherent/index.d.ts +2 -0
- package/dist/blockchain/inherent/index.js +5 -1
- package/dist/blockchain/inherent/parachain/babe-randomness.d.ts +7 -0
- package/dist/blockchain/inherent/parachain/babe-randomness.js +15 -0
- package/dist/blockchain/inherent/parachain/nimbus-author-inherent.d.ts +7 -0
- package/dist/blockchain/inherent/parachain/nimbus-author-inherent.js +15 -0
- package/dist/blockchain/txpool.js +1 -62
- package/dist/dry-run.d.ts +2 -0
- package/dist/dry-run.js +35 -0
- package/dist/executor.js +3 -3
- package/dist/index.js +51 -4
- package/dist/logger.d.ts +1 -3
- package/dist/logger.js +19 -13
- package/dist/rpc/dev.js +44 -2
- package/dist/rpc/substrate/system.js +4 -0
- package/dist/run-block.d.ts +1 -1
- package/dist/run-block.js +16 -5
- package/dist/setup.js +9 -2
- package/dist/utils/decoder.d.ts +17 -0
- package/dist/utils/decoder.js +105 -0
- package/dist/utils/generate-html-diff.d.ts +4 -0
- package/dist/utils/generate-html-diff.js +20 -0
- package/dist/utils/open-html.d.ts +1 -0
- package/dist/utils/open-html.js +9 -0
- package/dist/xcm/downward.d.ts +2 -0
- package/dist/xcm/downward.js +27 -0
- package/dist/xcm/horizontal.d.ts +2 -0
- package/dist/xcm/horizontal.js +36 -0
- package/dist/xcm/index.d.ts +7 -1
- package/dist/xcm/index.js +13 -55
- package/dist/xcm/upward.d.ts +2 -0
- package/dist/xcm/upward.js +39 -0
- package/package.json +6 -3
- package/dist/decode-key.d.ts +0 -2
- package/dist/decode-key.js +0 -24
package/README.md
CHANGED
|
@@ -26,7 +26,14 @@ Make sure you have setup Rust environment (>= 1.64).
|
|
|
26
26
|
- Replay latest block
|
|
27
27
|
- `yarn start run-block --endpoint=wss://acala-rpc-2.aca-api.network/ws`
|
|
28
28
|
- This will replay the last block and print out the changed storages
|
|
29
|
+
- Use option `--block` to replay certain block hash
|
|
29
30
|
- Use option `--output-path=<file_path>` to print out JSON file
|
|
31
|
+
- Use option `--html` to generate storage diff preview (add `--open` to automatically open file)
|
|
32
|
+
|
|
33
|
+
- Dry run extrinsic, same as `run-block`, example:
|
|
34
|
+
- `yarn start dry-run --config=configs/mandala.yml --html --open --extrinsic=0x39028400d43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d01183abac17ff331f8b65dbeddd27f014dedd892020cfdc6c40b574f6930f8cf391bde95997ae2edc5b1192a4036ea97804956c4b5497175c8d68b630301685889450200000a00008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a480284d717`
|
|
35
|
+
- Dry run call `yarn start dry-run --config=configs/mandala.yml --html --open --extrinsic=0xff00000080969800 --address=5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY --at=0x5f660b32489966cc707ecde831864aeecf9092c4983e75f9880313e9158d62b9`
|
|
36
|
+
|
|
30
37
|
- Run a test node
|
|
31
38
|
- `yarn start dev --endpoint=wss://acala-rpc-2.aca-api.network/ws`
|
|
32
39
|
- You have a test node running at `ws://localhost:8000`
|
|
@@ -34,7 +41,6 @@ Make sure you have setup Rust environment (>= 1.64).
|
|
|
34
41
|
- Submit any transaction to produce a new block in the in parallel reality
|
|
35
42
|
- (Optional) Pre-define/override storage using option `--import-storage=storage.[json/yaml]`. See example storage below.
|
|
36
43
|
```json5
|
|
37
|
-
// prettier-ignore
|
|
38
44
|
{
|
|
39
45
|
"Sudo": {
|
|
40
46
|
"Key": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
|
|
@@ -58,7 +64,7 @@ Make sure you have setup Rust environment (>= 1.64).
|
|
|
58
64
|
- Edit configs/kusama.yml if needed. (e.g. update the block number)
|
|
59
65
|
- `yarn start dev --config=configs/kusama.yml`
|
|
60
66
|
|
|
61
|
-
- Setup XCM multichain
|
|
67
|
+
- Setup XCM multichain
|
|
62
68
|
**_NOTE:_** You can also connect multiple parachains without a relaychain
|
|
63
69
|
```bash
|
|
64
70
|
yarn start xcm --relaychain=configs/kusama.yml --parachain=configs/karura.yml --parachain=configs/statemine.yml
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import { Block } from './block';
|
|
2
|
-
import { Header } from '@polkadot/types/interfaces';
|
|
1
|
+
import { Block, TaskCallResponse } from './block';
|
|
3
2
|
import { HexString } from '@polkadot/util/types';
|
|
4
|
-
export declare const buildBlock: (head: Block,
|
|
3
|
+
export declare const buildBlock: (head: Block, inherents: HexString[], extrinsics: HexString[]) => Promise<[Block, HexString[]]>;
|
|
4
|
+
export declare const dryRunExtrinsic: (head: Block, inherents: HexString[], extrinsic: HexString | {
|
|
5
|
+
call: HexString;
|
|
6
|
+
address: string;
|
|
7
|
+
}) => Promise<TaskCallResponse>;
|
|
8
|
+
export declare const dryRunInherents: (head: Block, inherents: HexString[]) => Promise<[HexString, HexString | null][]>;
|
|
@@ -1,46 +1,131 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.buildBlock = void 0;
|
|
3
|
+
exports.dryRunInherents = exports.dryRunExtrinsic = exports.buildBlock = void 0;
|
|
4
4
|
const block_1 = require("./block");
|
|
5
|
+
const util_1 = require("@polkadot/util");
|
|
6
|
+
const utils_1 = require("../utils");
|
|
5
7
|
const logger_1 = require("../logger");
|
|
8
|
+
const time_travel_1 = require("../utils/time-travel");
|
|
6
9
|
const logger = logger_1.defaultLogger.child({ name: 'block-builder' });
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
const getConsensus = (header) => {
|
|
11
|
+
if (header.digest.logs.length === 0)
|
|
12
|
+
return;
|
|
13
|
+
const preRuntime = header.digest.logs[0].asPreRuntime;
|
|
14
|
+
const [consensusEngine, slot] = preRuntime;
|
|
15
|
+
return { consensusEngine, slot, rest: header.digest.logs.slice(1) };
|
|
16
|
+
};
|
|
17
|
+
const getNewSlot = (digest, slotNumber) => {
|
|
18
|
+
if (digest.isPrimary) {
|
|
19
|
+
return {
|
|
20
|
+
primary: {
|
|
21
|
+
...digest.asPrimary.toJSON(),
|
|
22
|
+
slotNumber,
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
if (digest.isSecondaryPlain) {
|
|
27
|
+
return {
|
|
28
|
+
secondaryPlain: {
|
|
29
|
+
...digest.asSecondaryPlain.toJSON(),
|
|
30
|
+
slotNumber,
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
if (digest.isSecondaryVRF) {
|
|
35
|
+
return {
|
|
36
|
+
secondaryVRF: {
|
|
37
|
+
...digest.asSecondaryVRF.toJSON(),
|
|
38
|
+
slotNumber,
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return digest.toJSON();
|
|
43
|
+
};
|
|
44
|
+
const newHeader = async (head) => {
|
|
45
|
+
const meta = await head.meta;
|
|
46
|
+
const parentHeader = await head.header;
|
|
47
|
+
let newLogs = parentHeader.digest.logs;
|
|
48
|
+
const consensus = getConsensus(parentHeader);
|
|
49
|
+
if (consensus?.consensusEngine.isAura) {
|
|
50
|
+
const slot = await (0, time_travel_1.getCurrentSlot)(head.chain);
|
|
51
|
+
const newSlot = (0, util_1.compactAddLength)(meta.registry.createType('Slot', slot + 1).toU8a());
|
|
52
|
+
newLogs = [{ PreRuntime: [consensus.consensusEngine, newSlot] }, ...consensus.rest];
|
|
53
|
+
}
|
|
54
|
+
else if (consensus?.consensusEngine.isBabe) {
|
|
55
|
+
const slot = await (0, time_travel_1.getCurrentSlot)(head.chain);
|
|
56
|
+
const digest = meta.registry.createType('RawBabePreDigest', consensus.slot);
|
|
57
|
+
const newSlot = (0, util_1.compactAddLength)(meta.registry.createType('RawBabePreDigest', getNewSlot(digest, slot + 1)).toU8a());
|
|
58
|
+
newLogs = [{ PreRuntime: [consensus.consensusEngine, newSlot] }, ...consensus.rest];
|
|
59
|
+
}
|
|
60
|
+
else if (consensus?.consensusEngine?.toString() == 'nmbs') {
|
|
61
|
+
const nmbsKey = (0, util_1.stringToHex)('nmbs');
|
|
62
|
+
newLogs = [
|
|
63
|
+
{
|
|
64
|
+
// Using previous block author
|
|
65
|
+
PreRuntime: [
|
|
66
|
+
consensus.consensusEngine,
|
|
67
|
+
parentHeader.digest.logs
|
|
68
|
+
.find((log) => log.isPreRuntime && log.asPreRuntime[0].toHex() == nmbsKey)
|
|
69
|
+
?.asPreRuntime[1].toHex(),
|
|
70
|
+
],
|
|
71
|
+
},
|
|
72
|
+
...consensus.rest,
|
|
73
|
+
head.pushStorageLayer().set((0, utils_1.compactHex)(meta.query.randomness.notFirstBlock()), "Deleted" /* StorageValueKind.Deleted */),
|
|
74
|
+
];
|
|
75
|
+
}
|
|
76
|
+
const header = meta.registry.createType('Header', {
|
|
77
|
+
parentHash: head.hash,
|
|
78
|
+
number: head.number + 1,
|
|
79
|
+
stateRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
80
|
+
extrinsicsRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
81
|
+
digest: {
|
|
82
|
+
logs: newLogs,
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
return header;
|
|
86
|
+
};
|
|
87
|
+
const initNewBlock = async (head, header, inherents) => {
|
|
10
88
|
const blockNumber = header.number.toNumber();
|
|
11
89
|
const hash = `0x${Math.round(Math.random() * 100000000)
|
|
12
90
|
.toString(16)
|
|
13
91
|
.padEnd(64, '0')}`;
|
|
14
92
|
const newBlock = new block_1.Block(head.chain, blockNumber, hash, head, { header, extrinsics: [], storage: head.storage });
|
|
15
|
-
logger.info({
|
|
16
|
-
number: blockNumber,
|
|
17
|
-
extrinsicsCount: extrinsics.length,
|
|
18
|
-
tempHash: newBlock.hash,
|
|
19
|
-
}, `Building block #${blockNumber.toLocaleString()}`);
|
|
20
93
|
{
|
|
21
94
|
// initialize block
|
|
22
95
|
const { storageDiff } = await newBlock.call('Core_initialize_block', header.toHex());
|
|
23
|
-
logger.trace((0, logger_1.truncateStorageDiff)(storageDiff), 'Initialize block');
|
|
24
96
|
newBlock.pushStorageLayer().setAll(storageDiff);
|
|
97
|
+
logger.trace((0, logger_1.truncate)(storageDiff), 'Initialize block');
|
|
25
98
|
}
|
|
26
99
|
// apply inherents
|
|
27
100
|
for (const extrinsic of inherents) {
|
|
28
101
|
try {
|
|
29
102
|
const { storageDiff } = await newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
|
|
30
103
|
newBlock.pushStorageLayer().setAll(storageDiff);
|
|
31
|
-
logger.trace((0, logger_1.
|
|
104
|
+
logger.trace((0, logger_1.truncate)(storageDiff), 'Applied inherent');
|
|
32
105
|
}
|
|
33
106
|
catch (e) {
|
|
34
107
|
logger.warn('Failed to apply inherents %o %s', e, e);
|
|
35
108
|
throw new Error('Failed to apply inherents');
|
|
36
109
|
}
|
|
37
110
|
}
|
|
111
|
+
return newBlock;
|
|
112
|
+
};
|
|
113
|
+
const buildBlock = async (head, inherents, extrinsics) => {
|
|
114
|
+
const registry = await head.registry;
|
|
115
|
+
const header = await newHeader(head);
|
|
116
|
+
const newBlock = await initNewBlock(head, header, inherents);
|
|
117
|
+
logger.info({
|
|
118
|
+
number: newBlock.number,
|
|
119
|
+
extrinsicsCount: extrinsics.length,
|
|
120
|
+
tempHash: newBlock.hash,
|
|
121
|
+
}, `Building block #${newBlock.number.toLocaleString()}`);
|
|
122
|
+
const pendingExtrinsics = [];
|
|
38
123
|
// apply extrinsics
|
|
39
124
|
for (const extrinsic of extrinsics) {
|
|
40
125
|
try {
|
|
41
126
|
const { storageDiff } = await newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
|
|
42
127
|
newBlock.pushStorageLayer().setAll(storageDiff);
|
|
43
|
-
logger.trace((0, logger_1.
|
|
128
|
+
logger.trace((0, logger_1.truncate)(storageDiff), 'Applied extrinsic');
|
|
44
129
|
}
|
|
45
130
|
catch (e) {
|
|
46
131
|
logger.info('Failed to apply extrinsic %o %s', e, e);
|
|
@@ -51,7 +136,7 @@ const buildBlock = async (head, header, inherents, extrinsics) => {
|
|
|
51
136
|
// finalize block
|
|
52
137
|
const { storageDiff } = await newBlock.call('BlockBuilder_finalize_block', '0x');
|
|
53
138
|
newBlock.pushStorageLayer().setAll(storageDiff);
|
|
54
|
-
logger.trace((0, logger_1.
|
|
139
|
+
logger.trace((0, logger_1.truncate)(storageDiff), 'Finalize block');
|
|
55
140
|
}
|
|
56
141
|
const blockData = registry.createType('Block', {
|
|
57
142
|
header,
|
|
@@ -59,13 +144,49 @@ const buildBlock = async (head, header, inherents, extrinsics) => {
|
|
|
59
144
|
});
|
|
60
145
|
const storageDiff = await newBlock.storageDiff();
|
|
61
146
|
logger.trace(Object.entries(storageDiff).map(([key, value]) => [key, (0, logger_1.truncate)(value)]), 'Final block');
|
|
62
|
-
const finalBlock = new block_1.Block(head.chain,
|
|
147
|
+
const finalBlock = new block_1.Block(head.chain, newBlock.number, blockData.hash.toHex(), head, {
|
|
63
148
|
header,
|
|
64
149
|
extrinsics: [...inherents, ...extrinsics],
|
|
65
150
|
storage: head.storage,
|
|
66
151
|
storageDiff,
|
|
67
152
|
});
|
|
68
|
-
logger.info({ hash: finalBlock.hash, number:
|
|
153
|
+
logger.info({ hash: finalBlock.hash, number: newBlock.number }, `Block built #${newBlock.number.toLocaleString()} hash ${finalBlock.hash}`);
|
|
69
154
|
return [finalBlock, pendingExtrinsics];
|
|
70
155
|
};
|
|
71
156
|
exports.buildBlock = buildBlock;
|
|
157
|
+
const dryRunExtrinsic = async (head, inherents, extrinsic) => {
|
|
158
|
+
const registry = await head.registry;
|
|
159
|
+
const header = await newHeader(head);
|
|
160
|
+
const newBlock = await initNewBlock(head, header, inherents);
|
|
161
|
+
if (typeof extrinsic !== 'string') {
|
|
162
|
+
if (!head.chain.mockSignatureHost) {
|
|
163
|
+
throw new Error('Cannot fake signature because mock signature host is not enabled. Start chain with `mockSignatureHost: true`');
|
|
164
|
+
}
|
|
165
|
+
const meta = await head.meta;
|
|
166
|
+
const call = registry.createType('Call', (0, util_1.hexToU8a)(extrinsic.call));
|
|
167
|
+
const generic = registry.createType('GenericExtrinsic', call);
|
|
168
|
+
const accountRaw = await head.get((0, utils_1.compactHex)(meta.query.system.account(extrinsic.address)));
|
|
169
|
+
const account = registry.createType('AccountInfo', (0, util_1.hexToU8a)(accountRaw));
|
|
170
|
+
generic.signFake(extrinsic.address, {
|
|
171
|
+
blockHash: head.hash,
|
|
172
|
+
genesisHash: head.hash,
|
|
173
|
+
runtimeVersion: await head.runtimeVersion,
|
|
174
|
+
nonce: account.nonce,
|
|
175
|
+
});
|
|
176
|
+
const mockSignature = new Uint8Array(64);
|
|
177
|
+
mockSignature.fill(0xcd);
|
|
178
|
+
mockSignature.set([0xde, 0xad, 0xbe, 0xef]);
|
|
179
|
+
generic.signature.set(mockSignature);
|
|
180
|
+
logger_1.defaultLogger.info({ call: call.toHuman() }, 'dry_run_call');
|
|
181
|
+
return newBlock.call('BlockBuilder_apply_extrinsic', generic.toHex());
|
|
182
|
+
}
|
|
183
|
+
logger_1.defaultLogger.info({ call: registry.createType('GenericExtrinsic', (0, util_1.hexToU8a)(extrinsic)).toHuman() }, 'dry_run_extrinsic');
|
|
184
|
+
return newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
|
|
185
|
+
};
|
|
186
|
+
exports.dryRunExtrinsic = dryRunExtrinsic;
|
|
187
|
+
const dryRunInherents = async (head, inherents) => {
|
|
188
|
+
const header = await newHeader(head);
|
|
189
|
+
const newBlock = await initNewBlock(head, header, inherents);
|
|
190
|
+
return Object.entries(await newBlock.storageDiff());
|
|
191
|
+
};
|
|
192
|
+
exports.dryRunInherents = dryRunInherents;
|
|
@@ -32,7 +32,7 @@ export declare class Block {
|
|
|
32
32
|
}): Promise<string[]>;
|
|
33
33
|
pushStorageLayer(): StorageLayer;
|
|
34
34
|
popStorageLayer(): void;
|
|
35
|
-
storageDiff(): Promise<Record<
|
|
35
|
+
storageDiff(): Promise<Record<HexString, HexString | null>>;
|
|
36
36
|
get wasm(): Promise<`0x${string}`>;
|
|
37
37
|
setWasm(wasm: HexString): void;
|
|
38
38
|
get registry(): Promise<TypeRegistry>;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { ApplyExtrinsicResult } from '@polkadot/types/interfaces';
|
|
1
2
|
import { DataSource } from 'typeorm';
|
|
2
3
|
import { HexString } from '@polkadot/util/types';
|
|
3
4
|
import { Api } from '../api';
|
|
4
5
|
import { Block } from './block';
|
|
5
|
-
import { BuildBlockMode, BuildBlockParams } from './txpool';
|
|
6
|
+
import { BuildBlockMode, BuildBlockParams, HorizontalMessage } from './txpool';
|
|
6
7
|
import { HeadState } from './head-state';
|
|
7
8
|
import { InherentProvider } from './inherent';
|
|
8
9
|
export interface Options {
|
|
@@ -19,6 +20,7 @@ export interface Options {
|
|
|
19
20
|
}
|
|
20
21
|
export declare class Blockchain {
|
|
21
22
|
#private;
|
|
23
|
+
readonly uid: string;
|
|
22
24
|
readonly api: Api;
|
|
23
25
|
readonly db: DataSource | undefined;
|
|
24
26
|
readonly mockSignatureHost: boolean;
|
|
@@ -33,4 +35,12 @@ export declare class Blockchain {
|
|
|
33
35
|
setHead(block: Block): Promise<void>;
|
|
34
36
|
submitExtrinsic(extrinsic: HexString): Promise<HexString>;
|
|
35
37
|
newBlock(params?: BuildBlockParams): Promise<Block>;
|
|
38
|
+
dryRunExtrinsic(extrinsic: HexString | {
|
|
39
|
+
call: HexString;
|
|
40
|
+
address: string;
|
|
41
|
+
}, at?: HexString): Promise<{
|
|
42
|
+
outcome: ApplyExtrinsicResult;
|
|
43
|
+
storageDiff: [HexString, HexString | null][];
|
|
44
|
+
}>;
|
|
45
|
+
dryRunHrmp(hrmp: Record<number, HorizontalMessage[]>): Promise<[HexString, HexString | null][]>;
|
|
36
46
|
}
|
package/dist/blockchain/index.js
CHANGED
|
@@ -7,13 +7,16 @@ const block_1 = require("./block");
|
|
|
7
7
|
const txpool_1 = require("./txpool");
|
|
8
8
|
const head_state_1 = require("./head-state");
|
|
9
9
|
const logger_1 = require("../logger");
|
|
10
|
+
const block_builder_1 = require("./block-builder");
|
|
10
11
|
const logger = logger_1.defaultLogger.child({ name: 'blockchain' });
|
|
11
12
|
class Blockchain {
|
|
13
|
+
uid = Math.random().toString(36).substring(2);
|
|
12
14
|
api;
|
|
13
15
|
db;
|
|
14
16
|
mockSignatureHost;
|
|
15
17
|
allowUnresolvedImports;
|
|
16
18
|
#txpool;
|
|
19
|
+
#inherentProvider;
|
|
17
20
|
#head;
|
|
18
21
|
#blocksByNumber = [];
|
|
19
22
|
#blocksByHash = {};
|
|
@@ -27,6 +30,7 @@ class Blockchain {
|
|
|
27
30
|
this.#head = new block_1.Block(this, header.number, header.hash);
|
|
28
31
|
this.#registerBlock(this.#head);
|
|
29
32
|
this.#txpool = new txpool_1.TxPool(this, inherentProvider, buildBlockMode);
|
|
33
|
+
this.#inherentProvider = inherentProvider;
|
|
30
34
|
this.headState = new head_state_1.HeadState(this.#head);
|
|
31
35
|
}
|
|
32
36
|
#registerBlock(block) {
|
|
@@ -115,5 +119,23 @@ class Blockchain {
|
|
|
115
119
|
await this.#txpool.buildBlock(params);
|
|
116
120
|
return this.#head;
|
|
117
121
|
}
|
|
122
|
+
async dryRunExtrinsic(extrinsic, at) {
|
|
123
|
+
await this.api.isReady;
|
|
124
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
125
|
+
if (!head) {
|
|
126
|
+
throw new Error(`Cannot find block ${at}`);
|
|
127
|
+
}
|
|
128
|
+
const registry = await head.registry;
|
|
129
|
+
const inherents = await this.#inherentProvider.createInherents(head);
|
|
130
|
+
const { result, storageDiff } = await (0, block_builder_1.dryRunExtrinsic)(head, inherents, extrinsic);
|
|
131
|
+
const outcome = registry.createType('ApplyExtrinsicResult', result);
|
|
132
|
+
return { outcome, storageDiff };
|
|
133
|
+
}
|
|
134
|
+
async dryRunHrmp(hrmp) {
|
|
135
|
+
await this.api.isReady;
|
|
136
|
+
const head = this.head;
|
|
137
|
+
const inherents = await this.#inherentProvider.createInherents(head, { horizontalMessages: hrmp });
|
|
138
|
+
return (0, block_builder_1.dryRunInherents)(head, inherents);
|
|
139
|
+
}
|
|
118
140
|
}
|
|
119
141
|
exports.Blockchain = Blockchain;
|
|
@@ -3,6 +3,8 @@ import { BuildBlockParams } from '../txpool';
|
|
|
3
3
|
import { HexString } from '@polkadot/util/types';
|
|
4
4
|
export { SetValidationData } from './parachain/validation-data';
|
|
5
5
|
export { ParaInherentEnter } from './para-enter';
|
|
6
|
+
export { SetBabeRandomness } from './parachain/babe-randomness';
|
|
7
|
+
export { SetNimbusAuthorInherent } from './parachain/nimbus-author-inherent';
|
|
6
8
|
export interface CreateInherents {
|
|
7
9
|
createInherents(parent: Block, params?: BuildBlockParams['inherent']): Promise<HexString[]>;
|
|
8
10
|
}
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InherentProviders = exports.SetTimestamp = exports.ParaInherentEnter = exports.SetValidationData = void 0;
|
|
3
|
+
exports.InherentProviders = exports.SetTimestamp = exports.SetNimbusAuthorInherent = exports.SetBabeRandomness = exports.ParaInherentEnter = exports.SetValidationData = void 0;
|
|
4
4
|
const types_1 = require("@polkadot/types");
|
|
5
5
|
const time_travel_1 = require("../../utils/time-travel");
|
|
6
6
|
var validation_data_1 = require("./parachain/validation-data");
|
|
7
7
|
Object.defineProperty(exports, "SetValidationData", { enumerable: true, get: function () { return validation_data_1.SetValidationData; } });
|
|
8
8
|
var para_enter_1 = require("./para-enter");
|
|
9
9
|
Object.defineProperty(exports, "ParaInherentEnter", { enumerable: true, get: function () { return para_enter_1.ParaInherentEnter; } });
|
|
10
|
+
var babe_randomness_1 = require("./parachain/babe-randomness");
|
|
11
|
+
Object.defineProperty(exports, "SetBabeRandomness", { enumerable: true, get: function () { return babe_randomness_1.SetBabeRandomness; } });
|
|
12
|
+
var nimbus_author_inherent_1 = require("./parachain/nimbus-author-inherent");
|
|
13
|
+
Object.defineProperty(exports, "SetNimbusAuthorInherent", { enumerable: true, get: function () { return nimbus_author_inherent_1.SetNimbusAuthorInherent; } });
|
|
10
14
|
class SetTimestamp {
|
|
11
15
|
async createInherents(parent) {
|
|
12
16
|
const meta = await parent.meta;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HexString } from '@polkadot/util/types';
|
|
2
|
+
import { Block } from '../../../blockchain/block';
|
|
3
|
+
import { BuildBlockParams } from '../../txpool';
|
|
4
|
+
import { CreateInherents } from '..';
|
|
5
|
+
export declare class SetBabeRandomness implements CreateInherents {
|
|
6
|
+
createInherents(parent: Block, _params?: BuildBlockParams['inherent']): Promise<HexString[]>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SetBabeRandomness = void 0;
|
|
4
|
+
const types_1 = require("@polkadot/types");
|
|
5
|
+
// Support for Moonbeam pallet-randomness mandatory inherent
|
|
6
|
+
class SetBabeRandomness {
|
|
7
|
+
async createInherents(parent, _params) {
|
|
8
|
+
const meta = await parent.meta;
|
|
9
|
+
if (!meta.tx.randomness?.setBabeRandomnessResults) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
return [new types_1.GenericExtrinsic(meta.registry, meta.tx.randomness.setBabeRandomnessResults()).toHex()];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.SetBabeRandomness = SetBabeRandomness;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { HexString } from '@polkadot/util/types';
|
|
2
|
+
import { Block } from '../../../blockchain/block';
|
|
3
|
+
import { BuildBlockParams } from '../../txpool';
|
|
4
|
+
import { CreateInherents } from '..';
|
|
5
|
+
export declare class SetNimbusAuthorInherent implements CreateInherents {
|
|
6
|
+
createInherents(parent: Block, _params?: BuildBlockParams['inherent']): Promise<HexString[]>;
|
|
7
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SetNimbusAuthorInherent = void 0;
|
|
4
|
+
const types_1 = require("@polkadot/types");
|
|
5
|
+
// Support for Nimbus Author Inherent
|
|
6
|
+
class SetNimbusAuthorInherent {
|
|
7
|
+
async createInherents(parent, _params) {
|
|
8
|
+
const meta = await parent.meta;
|
|
9
|
+
if (!meta.tx.authorInherent?.kickOffAuthorshipValidation) {
|
|
10
|
+
return [];
|
|
11
|
+
}
|
|
12
|
+
return [new types_1.GenericExtrinsic(meta.registry, meta.tx.authorInherent.kickOffAuthorshipValidation()).toHex()];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.SetNimbusAuthorInherent = SetNimbusAuthorInherent;
|
|
@@ -4,50 +4,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.TxPool = exports.BuildBlockMode = void 0;
|
|
7
|
-
const util_1 = require("@polkadot/util");
|
|
8
7
|
const lodash_1 = __importDefault(require("lodash"));
|
|
9
8
|
const block_builder_1 = require("./block-builder");
|
|
10
|
-
const time_travel_1 = require("../utils/time-travel");
|
|
11
9
|
var BuildBlockMode;
|
|
12
10
|
(function (BuildBlockMode) {
|
|
13
11
|
BuildBlockMode[BuildBlockMode["Batch"] = 0] = "Batch";
|
|
14
12
|
BuildBlockMode[BuildBlockMode["Instant"] = 1] = "Instant";
|
|
15
13
|
BuildBlockMode[BuildBlockMode["Manual"] = 2] = "Manual";
|
|
16
14
|
})(BuildBlockMode = exports.BuildBlockMode || (exports.BuildBlockMode = {}));
|
|
17
|
-
const getConsensus = (header) => {
|
|
18
|
-
if (header.digest.logs.length === 0)
|
|
19
|
-
return;
|
|
20
|
-
const preRuntime = header.digest.logs[0].asPreRuntime;
|
|
21
|
-
const [consensusEngine, slot] = preRuntime;
|
|
22
|
-
return { consensusEngine, slot, rest: header.digest.logs.slice(1) };
|
|
23
|
-
};
|
|
24
|
-
const getNewSlot = (digest, slotNumber) => {
|
|
25
|
-
if (digest.isPrimary) {
|
|
26
|
-
return {
|
|
27
|
-
primary: {
|
|
28
|
-
...digest.asPrimary.toJSON(),
|
|
29
|
-
slotNumber,
|
|
30
|
-
},
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
if (digest.isSecondaryPlain) {
|
|
34
|
-
return {
|
|
35
|
-
secondaryPlain: {
|
|
36
|
-
...digest.asSecondaryPlain.toJSON(),
|
|
37
|
-
slotNumber,
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
if (digest.isSecondaryVRF) {
|
|
42
|
-
return {
|
|
43
|
-
secondaryVRF: {
|
|
44
|
-
...digest.asSecondaryVRF.toJSON(),
|
|
45
|
-
slotNumber,
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
return digest.toJSON();
|
|
50
|
-
};
|
|
51
15
|
class TxPool {
|
|
52
16
|
#chain;
|
|
53
17
|
#pool = [];
|
|
@@ -87,33 +51,8 @@ class TxPool {
|
|
|
87
51
|
await wait.catch(() => { }); // ignore error
|
|
88
52
|
const head = this.#chain.head;
|
|
89
53
|
const extrinsics = this.#pool.splice(0);
|
|
90
|
-
const meta = await head.meta;
|
|
91
|
-
const parentHeader = await head.header;
|
|
92
|
-
let newLogs = parentHeader.digest.logs;
|
|
93
|
-
const consensus = getConsensus(parentHeader);
|
|
94
|
-
if (consensus?.consensusEngine.isAura) {
|
|
95
|
-
const slot = await (0, time_travel_1.getCurrentSlot)(this.#chain);
|
|
96
|
-
const newSlot = (0, util_1.compactAddLength)(meta.registry.createType('Slot', slot + 1).toU8a());
|
|
97
|
-
newLogs = [{ PreRuntime: [consensus.consensusEngine, newSlot] }, ...consensus.rest];
|
|
98
|
-
}
|
|
99
|
-
else if (consensus?.consensusEngine.isBabe) {
|
|
100
|
-
const slot = await (0, time_travel_1.getCurrentSlot)(this.#chain);
|
|
101
|
-
const digest = meta.registry.createType('RawBabePreDigest', consensus.slot);
|
|
102
|
-
const newSlot = (0, util_1.compactAddLength)(meta.registry.createType('RawBabePreDigest', getNewSlot(digest, slot + 1)).toU8a());
|
|
103
|
-
newLogs = [{ PreRuntime: [consensus.consensusEngine, newSlot] }, ...consensus.rest];
|
|
104
|
-
}
|
|
105
|
-
const registry = await head.registry;
|
|
106
|
-
const header = registry.createType('Header', {
|
|
107
|
-
parentHash: head.hash,
|
|
108
|
-
number: head.number + 1,
|
|
109
|
-
stateRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
110
|
-
extrinsicsRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
|
111
|
-
digest: {
|
|
112
|
-
logs: newLogs,
|
|
113
|
-
},
|
|
114
|
-
});
|
|
115
54
|
const inherents = await this.#inherentProvider.createInherents(head, params?.inherent);
|
|
116
|
-
const [newBlock, pendingExtrinsics] = await (0, block_builder_1.buildBlock)(head,
|
|
55
|
+
const [newBlock, pendingExtrinsics] = await (0, block_builder_1.buildBlock)(head, inherents, extrinsics);
|
|
117
56
|
this.#pool.push(...pendingExtrinsics);
|
|
118
57
|
await this.#chain.setHead(newBlock);
|
|
119
58
|
}
|
package/dist/dry-run.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dryRun = void 0;
|
|
4
|
+
const util_crypto_1 = require("@polkadot/util-crypto");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
const generate_html_diff_1 = require("./utils/generate-html-diff");
|
|
8
|
+
const open_html_1 = require("./utils/open-html");
|
|
9
|
+
const setup_1 = require("./setup");
|
|
10
|
+
const dryRun = async (argv) => {
|
|
11
|
+
const context = await (0, setup_1.setup)(argv);
|
|
12
|
+
const input = argv['address'] ? { call: argv['extrinsic'], address: argv['address'] } : argv['extrinsic'];
|
|
13
|
+
const { outcome, storageDiff } = await context.chain.dryRunExtrinsic(input, argv['at']);
|
|
14
|
+
if (outcome.isErr) {
|
|
15
|
+
throw new Error(outcome.asErr.toString());
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
logger_1.defaultLogger.info(outcome.toHuman(), 'dry_run_outcome');
|
|
19
|
+
}
|
|
20
|
+
if (argv['html']) {
|
|
21
|
+
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(context.chain.head, storageDiff, (0, util_crypto_1.blake2AsHex)(argv['extrinsic'], 256));
|
|
22
|
+
console.log(`Generated preview ${filePath}`);
|
|
23
|
+
if (argv['open']) {
|
|
24
|
+
(0, open_html_1.openHtml)(filePath);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
else if (argv['output-path']) {
|
|
28
|
+
(0, node_fs_1.writeFileSync)(argv['output-path'], JSON.stringify({ outcome: outcome.toHuman(), storageDiff }, null, 2));
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
console.dir({ outcome: outcome.toHuman(), storageDiff }, { depth: null, colors: false });
|
|
32
|
+
}
|
|
33
|
+
process.exit(0);
|
|
34
|
+
};
|
|
35
|
+
exports.dryRun = dryRun;
|
package/dist/executor.js
CHANGED
|
@@ -38,10 +38,10 @@ const createProof = async (trieRootHash, nodes, entries) => {
|
|
|
38
38
|
};
|
|
39
39
|
exports.createProof = createProof;
|
|
40
40
|
const runTask = async (task, callback = exports.emptyTaskHandler) => {
|
|
41
|
-
logger.trace(
|
|
41
|
+
logger.trace((0, logger_1.truncate)(task), 'taskRun');
|
|
42
42
|
const response = await (0, chopsticks_executor_1.run_task)(task, callback);
|
|
43
43
|
if (response.Call) {
|
|
44
|
-
logger.trace(
|
|
44
|
+
logger.trace((0, logger_1.truncate)(response.Call), 'taskResponse');
|
|
45
45
|
}
|
|
46
46
|
else {
|
|
47
47
|
logger.trace({ response }, 'taskResponse');
|
|
@@ -58,7 +58,7 @@ const taskHandler = (block) => {
|
|
|
58
58
|
return block.getKeysPaged({ prefix: key, pageSize: 1000, startKey: key });
|
|
59
59
|
},
|
|
60
60
|
getNextKey: async function (key) {
|
|
61
|
-
const keys = await block.getKeysPaged({ prefix:
|
|
61
|
+
const keys = await block.getKeysPaged({ prefix: '0x', pageSize: 1, startKey: key });
|
|
62
62
|
return keys[0];
|
|
63
63
|
},
|
|
64
64
|
};
|