@acala-network/chopsticks 0.3.1 → 0.3.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/README.md +3 -2
- package/dist/blockchain/block-builder.d.ts +4 -1
- package/dist/blockchain/block-builder.js +28 -4
- package/dist/blockchain/head-state.js +11 -3
- package/dist/blockchain/index.d.ts +6 -1
- package/dist/blockchain/index.js +9 -2
- package/dist/blockchain/txpool.d.ts +2 -0
- package/dist/blockchain/txpool.js +15 -0
- package/dist/dry-run.js +6 -1
- package/dist/executor.d.ts +2 -1
- package/dist/executor.js +8 -7
- package/dist/index.js +14 -2
- package/dist/logger.d.ts +1 -3
- package/dist/logger.js +19 -13
- package/dist/rpc/dev.js +15 -0
- package/dist/rpc/index.js +4 -0
- package/dist/rpc/substrate/chain.js +5 -1
- package/dist/rpc/substrate/index.js +0 -4
- package/dist/rpc/substrate/system.js +15 -1
- package/dist/run-block.js +1 -1
- package/dist/schema/index.d.ts +6 -6
- package/dist/setup.js +2 -0
- package/dist/utils/decoder.js +9 -5
- package/dist/xcm/downward.d.ts +2 -0
- package/dist/xcm/downward.js +29 -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 +25 -27
package/README.md
CHANGED
|
@@ -31,7 +31,8 @@ Make sure you have setup Rust environment (>= 1.64).
|
|
|
31
31
|
- Use option `--html` to generate storage diff preview (add `--open` to automatically open file)
|
|
32
32
|
|
|
33
33
|
- Dry run extrinsic, same as `run-block`, example:
|
|
34
|
-
- `yarn start dry-run --config=configs/mandala.yml --html --open --extrinsic
|
|
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`
|
|
35
36
|
|
|
36
37
|
- Run a test node
|
|
37
38
|
- `yarn start dev --endpoint=wss://acala-rpc-2.aca-api.network/ws`
|
|
@@ -63,7 +64,7 @@ Make sure you have setup Rust environment (>= 1.64).
|
|
|
63
64
|
- Edit configs/kusama.yml if needed. (e.g. update the block number)
|
|
64
65
|
- `yarn start dev --config=configs/kusama.yml`
|
|
65
66
|
|
|
66
|
-
- Setup XCM multichain
|
|
67
|
+
- Setup XCM multichain
|
|
67
68
|
**_NOTE:_** You can also connect multiple parachains without a relaychain
|
|
68
69
|
```bash
|
|
69
70
|
yarn start xcm --relaychain=configs/kusama.yml --parachain=configs/karura.yml --parachain=configs/statemine.yml
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { Block, TaskCallResponse } from './block';
|
|
2
2
|
import { HexString } from '@polkadot/util/types';
|
|
3
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
|
|
4
|
+
export declare const dryRunExtrinsic: (head: Block, inherents: HexString[], extrinsic: HexString | {
|
|
5
|
+
call: HexString;
|
|
6
|
+
address: string;
|
|
7
|
+
}) => Promise<TaskCallResponse>;
|
|
5
8
|
export declare const dryRunInherents: (head: Block, inherents: HexString[]) => Promise<[HexString, HexString | null][]>;
|
|
@@ -94,14 +94,14 @@ const initNewBlock = async (head, header, inherents) => {
|
|
|
94
94
|
// initialize block
|
|
95
95
|
const { storageDiff } = await newBlock.call('Core_initialize_block', header.toHex());
|
|
96
96
|
newBlock.pushStorageLayer().setAll(storageDiff);
|
|
97
|
-
logger.trace((0, logger_1.
|
|
97
|
+
logger.trace((0, logger_1.truncate)(storageDiff), 'Initialize block');
|
|
98
98
|
}
|
|
99
99
|
// apply inherents
|
|
100
100
|
for (const extrinsic of inherents) {
|
|
101
101
|
try {
|
|
102
102
|
const { storageDiff } = await newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
|
|
103
103
|
newBlock.pushStorageLayer().setAll(storageDiff);
|
|
104
|
-
logger.trace((0, logger_1.
|
|
104
|
+
logger.trace((0, logger_1.truncate)(storageDiff), 'Applied inherent');
|
|
105
105
|
}
|
|
106
106
|
catch (e) {
|
|
107
107
|
logger.warn('Failed to apply inherents %o %s', e, e);
|
|
@@ -125,7 +125,7 @@ const buildBlock = async (head, inherents, extrinsics) => {
|
|
|
125
125
|
try {
|
|
126
126
|
const { storageDiff } = await newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
|
|
127
127
|
newBlock.pushStorageLayer().setAll(storageDiff);
|
|
128
|
-
logger.trace((0, logger_1.
|
|
128
|
+
logger.trace((0, logger_1.truncate)(storageDiff), 'Applied extrinsic');
|
|
129
129
|
}
|
|
130
130
|
catch (e) {
|
|
131
131
|
logger.info('Failed to apply extrinsic %o %s', e, e);
|
|
@@ -136,7 +136,7 @@ const buildBlock = async (head, inherents, extrinsics) => {
|
|
|
136
136
|
// finalize block
|
|
137
137
|
const { storageDiff } = await newBlock.call('BlockBuilder_finalize_block', '0x');
|
|
138
138
|
newBlock.pushStorageLayer().setAll(storageDiff);
|
|
139
|
-
logger.trace((0, logger_1.
|
|
139
|
+
logger.trace((0, logger_1.truncate)(storageDiff), 'Finalize block');
|
|
140
140
|
}
|
|
141
141
|
const blockData = registry.createType('Block', {
|
|
142
142
|
header,
|
|
@@ -155,8 +155,32 @@ const buildBlock = async (head, inherents, extrinsics) => {
|
|
|
155
155
|
};
|
|
156
156
|
exports.buildBlock = buildBlock;
|
|
157
157
|
const dryRunExtrinsic = async (head, inherents, extrinsic) => {
|
|
158
|
+
const registry = await head.registry;
|
|
158
159
|
const header = await newHeader(head);
|
|
159
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');
|
|
160
184
|
return newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
|
|
161
185
|
};
|
|
162
186
|
exports.dryRunExtrinsic = dryRunExtrinsic;
|
|
@@ -46,15 +46,23 @@ class HeadState {
|
|
|
46
46
|
async setHead(head) {
|
|
47
47
|
this.#head = head;
|
|
48
48
|
for (const cb of Object.values(this.#headListeners)) {
|
|
49
|
-
|
|
49
|
+
try {
|
|
50
|
+
cb(head);
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
logger.error(error, 'callback');
|
|
54
|
+
}
|
|
50
55
|
}
|
|
51
56
|
const diff = await this.#head.storageDiff();
|
|
52
57
|
for (const [keys, cb] of Object.values(this.#storageListeners)) {
|
|
53
58
|
const changed = keys.filter((key) => diff[key]).map((key) => [key, diff[key]]);
|
|
54
59
|
if (changed.length > 0) {
|
|
55
|
-
|
|
60
|
+
try {
|
|
61
|
+
cb(head, changed);
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
56
64
|
logger.error(error, 'callback');
|
|
57
|
-
}
|
|
65
|
+
}
|
|
58
66
|
}
|
|
59
67
|
}
|
|
60
68
|
Object.assign(this.#oldValues, diff);
|
|
@@ -20,6 +20,7 @@ export interface Options {
|
|
|
20
20
|
}
|
|
21
21
|
export declare class Blockchain {
|
|
22
22
|
#private;
|
|
23
|
+
readonly uid: string;
|
|
23
24
|
readonly api: Api;
|
|
24
25
|
readonly db: DataSource | undefined;
|
|
25
26
|
readonly mockSignatureHost: boolean;
|
|
@@ -34,7 +35,11 @@ export declare class Blockchain {
|
|
|
34
35
|
setHead(block: Block): Promise<void>;
|
|
35
36
|
submitExtrinsic(extrinsic: HexString): Promise<HexString>;
|
|
36
37
|
newBlock(params?: BuildBlockParams): Promise<Block>;
|
|
37
|
-
|
|
38
|
+
upcomingBlock(count?: number): Promise<Block>;
|
|
39
|
+
dryRunExtrinsic(extrinsic: HexString | {
|
|
40
|
+
call: HexString;
|
|
41
|
+
address: string;
|
|
42
|
+
}, at?: HexString): Promise<{
|
|
38
43
|
outcome: ApplyExtrinsicResult;
|
|
39
44
|
storageDiff: [HexString, HexString | null][];
|
|
40
45
|
}>;
|
package/dist/blockchain/index.js
CHANGED
|
@@ -10,6 +10,7 @@ const logger_1 = require("../logger");
|
|
|
10
10
|
const block_builder_1 = require("./block-builder");
|
|
11
11
|
const logger = logger_1.defaultLogger.child({ name: 'blockchain' });
|
|
12
12
|
class Blockchain {
|
|
13
|
+
uid = Math.random().toString(36).substring(2);
|
|
13
14
|
api;
|
|
14
15
|
db;
|
|
15
16
|
mockSignatureHost;
|
|
@@ -118,9 +119,15 @@ class Blockchain {
|
|
|
118
119
|
await this.#txpool.buildBlock(params);
|
|
119
120
|
return this.#head;
|
|
120
121
|
}
|
|
121
|
-
async
|
|
122
|
+
async upcomingBlock(count = 1) {
|
|
123
|
+
return this.#txpool.upcomingBlock(count);
|
|
124
|
+
}
|
|
125
|
+
async dryRunExtrinsic(extrinsic, at) {
|
|
122
126
|
await this.api.isReady;
|
|
123
|
-
const head = this.head;
|
|
127
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
128
|
+
if (!head) {
|
|
129
|
+
throw new Error(`Cannot find block ${at}`);
|
|
130
|
+
}
|
|
124
131
|
const registry = await head.registry;
|
|
125
132
|
const inherents = await this.#inherentProvider.createInherents(head);
|
|
126
133
|
const { result, storageDiff } = await (0, block_builder_1.dryRunExtrinsic)(head, inherents, extrinsic);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HexString } from '@polkadot/util/types';
|
|
2
|
+
import { Block } from './block';
|
|
2
3
|
import { Blockchain } from '.';
|
|
3
4
|
import { InherentProvider } from './inherent';
|
|
4
5
|
export declare enum BuildBlockMode {
|
|
@@ -26,4 +27,5 @@ export declare class TxPool {
|
|
|
26
27
|
get pendingExtrinsics(): HexString[];
|
|
27
28
|
submitExtrinsic(extrinsic: HexString): void;
|
|
28
29
|
buildBlock(params?: BuildBlockParams): Promise<void>;
|
|
30
|
+
upcomingBlock(count?: number): Promise<Block>;
|
|
29
31
|
}
|
|
@@ -4,6 +4,8 @@ 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 rxjs_1 = require("rxjs");
|
|
8
|
+
const operators_1 = require("rxjs/operators");
|
|
7
9
|
const lodash_1 = __importDefault(require("lodash"));
|
|
8
10
|
const block_builder_1 = require("./block-builder");
|
|
9
11
|
var BuildBlockMode;
|
|
@@ -18,6 +20,8 @@ class TxPool {
|
|
|
18
20
|
#mode;
|
|
19
21
|
#inherentProvider;
|
|
20
22
|
#lastBuildBlockPromise = Promise.resolve();
|
|
23
|
+
#last = new rxjs_1.ReplaySubject(1);
|
|
24
|
+
#upcoming = this.#last.pipe((0, rxjs_1.share)());
|
|
21
25
|
constructor(chain, inherentProvider, mode = BuildBlockMode.Batch) {
|
|
22
26
|
this.#chain = chain;
|
|
23
27
|
this.#mode = mode;
|
|
@@ -45,6 +49,17 @@ class TxPool {
|
|
|
45
49
|
const last = this.#lastBuildBlockPromise;
|
|
46
50
|
this.#lastBuildBlockPromise = this.#buildBlock(last, params);
|
|
47
51
|
await this.#lastBuildBlockPromise;
|
|
52
|
+
this.#last.next(this.#chain.head);
|
|
53
|
+
}
|
|
54
|
+
async upcomingBlock(count = 1) {
|
|
55
|
+
if (count < 1)
|
|
56
|
+
throw new Error('count needs to be greater than 0');
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const sub = this.#upcoming.pipe((0, operators_1.skip)(count - 1)).subscribe((block) => {
|
|
59
|
+
sub.unsubscribe();
|
|
60
|
+
resolve(block);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
48
63
|
}
|
|
49
64
|
async #buildBlock(wait, params) {
|
|
50
65
|
await this.#chain.api.isReady;
|
package/dist/dry-run.js
CHANGED
|
@@ -3,15 +3,20 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.dryRun = void 0;
|
|
4
4
|
const util_crypto_1 = require("@polkadot/util-crypto");
|
|
5
5
|
const node_fs_1 = require("node:fs");
|
|
6
|
+
const logger_1 = require("./logger");
|
|
6
7
|
const generate_html_diff_1 = require("./utils/generate-html-diff");
|
|
7
8
|
const open_html_1 = require("./utils/open-html");
|
|
8
9
|
const setup_1 = require("./setup");
|
|
9
10
|
const dryRun = async (argv) => {
|
|
10
11
|
const context = await (0, setup_1.setup)(argv);
|
|
11
|
-
const {
|
|
12
|
+
const input = argv['address'] ? { call: argv['extrinsic'], address: argv['address'] } : argv['extrinsic'];
|
|
13
|
+
const { outcome, storageDiff } = await context.chain.dryRunExtrinsic(input, argv['at']);
|
|
12
14
|
if (outcome.isErr) {
|
|
13
15
|
throw new Error(outcome.asErr.toString());
|
|
14
16
|
}
|
|
17
|
+
else {
|
|
18
|
+
logger_1.defaultLogger.info(outcome.toHuman(), 'dry_run_outcome');
|
|
19
|
+
}
|
|
15
20
|
if (argv['html']) {
|
|
16
21
|
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(context.chain.head, storageDiff, (0, util_crypto_1.blake2AsHex)(argv['extrinsic'], 256));
|
|
17
22
|
console.log(`Generated preview ${filePath}`);
|
package/dist/executor.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { HexString } from '@polkadot/util/types';
|
|
2
2
|
import { Block } from './blockchain/block';
|
|
3
3
|
import { Registry } from '@polkadot/types-codec/types';
|
|
4
|
+
import _ from 'lodash';
|
|
4
5
|
interface JsCallback {
|
|
5
6
|
getStorage: (key: HexString) => Promise<string | undefined>;
|
|
6
7
|
getPrefixKeys: (key: HexString) => Promise<string[]>;
|
|
@@ -36,5 +37,5 @@ export declare const emptyTaskHandler: {
|
|
|
36
37
|
getPrefixKeys: (_key: HexString) => Promise<never>;
|
|
37
38
|
getNextKey: (_key: HexString) => Promise<never>;
|
|
38
39
|
};
|
|
39
|
-
export declare const getAuraSlotDuration: ((wasm: HexString, registry: Registry) => Promise<number>) &
|
|
40
|
+
export declare const getAuraSlotDuration: ((wasm: HexString, registry: Registry) => Promise<number>) & _.MemoizedFunction;
|
|
40
41
|
export {};
|
package/dist/executor.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.getAuraSlotDuration = exports.emptyTaskHandler = exports.taskHandler = exports.runTask = exports.createProof = exports.decodeProof = exports.calculateStateRoot = exports.getRuntimeVersion = void 0;
|
|
4
|
-
const ws_1 = require("ws");
|
|
5
7
|
const util_1 = require("@polkadot/util");
|
|
6
|
-
global.WebSocket = ws_1.WebSocket;
|
|
7
8
|
const chopsticks_executor_1 = require("@acala-network/chopsticks-executor");
|
|
8
9
|
const logger_1 = require("./logger");
|
|
9
|
-
const lodash_1 = require("lodash");
|
|
10
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
10
11
|
const logger = logger_1.defaultLogger.child({ name: 'executor' });
|
|
11
12
|
const getRuntimeVersion = async (code) => {
|
|
12
13
|
return (0, chopsticks_executor_1.get_runtime_version)(code).then((version) => {
|
|
@@ -38,10 +39,10 @@ const createProof = async (trieRootHash, nodes, entries) => {
|
|
|
38
39
|
};
|
|
39
40
|
exports.createProof = createProof;
|
|
40
41
|
const runTask = async (task, callback = exports.emptyTaskHandler) => {
|
|
41
|
-
logger.trace(
|
|
42
|
+
logger.trace((0, logger_1.truncate)(task), 'taskRun');
|
|
42
43
|
const response = await (0, chopsticks_executor_1.run_task)(task, callback);
|
|
43
44
|
if (response.Call) {
|
|
44
|
-
logger.trace(
|
|
45
|
+
logger.trace((0, logger_1.truncate)(response.Call), 'taskResponse');
|
|
45
46
|
}
|
|
46
47
|
else {
|
|
47
48
|
logger.trace({ response }, 'taskResponse');
|
|
@@ -58,7 +59,7 @@ const taskHandler = (block) => {
|
|
|
58
59
|
return block.getKeysPaged({ prefix: key, pageSize: 1000, startKey: key });
|
|
59
60
|
},
|
|
60
61
|
getNextKey: async function (key) {
|
|
61
|
-
const keys = await block.getKeysPaged({ prefix:
|
|
62
|
+
const keys = await block.getKeysPaged({ prefix: '0x', pageSize: 1, startKey: key });
|
|
62
63
|
return keys[0];
|
|
63
64
|
},
|
|
64
65
|
};
|
|
@@ -75,7 +76,7 @@ exports.emptyTaskHandler = {
|
|
|
75
76
|
throw new Error('Method not implemented');
|
|
76
77
|
},
|
|
77
78
|
};
|
|
78
|
-
exports.getAuraSlotDuration =
|
|
79
|
+
exports.getAuraSlotDuration = lodash_1.default.memoize(async (wasm, registry) => {
|
|
79
80
|
const result = await (0, exports.runTask)({
|
|
80
81
|
wasm,
|
|
81
82
|
calls: [['AuraApi_slot_duration', '0x']],
|
package/dist/index.js
CHANGED
|
@@ -71,10 +71,18 @@ const defaultOptions = {
|
|
|
71
71
|
.command('dry-run', 'Dry run an extrinsic', (yargs) => yargs.options({
|
|
72
72
|
...defaultOptions,
|
|
73
73
|
extrinsic: {
|
|
74
|
-
desc: 'Extrinsic to dry run',
|
|
74
|
+
desc: 'Extrinsic or call to dry run. If you pass call here then address is required to fake signature',
|
|
75
75
|
string: true,
|
|
76
76
|
required: true,
|
|
77
77
|
},
|
|
78
|
+
address: {
|
|
79
|
+
desc: 'Address to fake sign extrinsic',
|
|
80
|
+
string: true,
|
|
81
|
+
},
|
|
82
|
+
at: {
|
|
83
|
+
desc: 'Block hash to dry run',
|
|
84
|
+
string: true,
|
|
85
|
+
},
|
|
78
86
|
'output-path': {
|
|
79
87
|
desc: 'File path to print output',
|
|
80
88
|
string: true,
|
|
@@ -106,6 +114,10 @@ const defaultOptions = {
|
|
|
106
114
|
desc: 'Mock signature host so any signature starts with 0xdeadbeef and filled by 0xcd is considered valid',
|
|
107
115
|
boolean: true,
|
|
108
116
|
},
|
|
117
|
+
'allow-unresolved-imports': {
|
|
118
|
+
desc: 'Allow wasm unresolved imports',
|
|
119
|
+
boolean: true,
|
|
120
|
+
},
|
|
109
121
|
}), async (argv) => {
|
|
110
122
|
await (0, setup_with_server_1.setupWithServer)(processArgv(argv));
|
|
111
123
|
})
|
|
@@ -150,7 +162,7 @@ const defaultOptions = {
|
|
|
150
162
|
if (argv.relaychain) {
|
|
151
163
|
const { chain: relaychain } = await (0, setup_with_server_1.setupWithServer)(processConfig(argv.relaychain));
|
|
152
164
|
for (const parachain of parachains) {
|
|
153
|
-
await (0, xcm_1.
|
|
165
|
+
await (0, xcm_1.connectVertical)(relaychain, parachain);
|
|
154
166
|
}
|
|
155
167
|
}
|
|
156
168
|
})
|
package/dist/logger.d.ts
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { HexString } from '@polkadot/util/types';
|
|
2
1
|
export declare const defaultLogger: import("pino").Logger<{
|
|
3
2
|
level: string;
|
|
4
3
|
transport: {
|
|
5
4
|
target: string;
|
|
6
5
|
};
|
|
7
6
|
}>;
|
|
8
|
-
export declare const truncate: (
|
|
9
|
-
export declare const truncateStorageDiff: (diff: [HexString, HexString | null][]) => [HexString, string | null][];
|
|
7
|
+
export declare const truncate: (val: any) => any;
|
package/dist/logger.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.truncate = exports.defaultLogger = void 0;
|
|
7
7
|
const pino_1 = __importDefault(require("pino"));
|
|
8
8
|
exports.defaultLogger = (0, pino_1.default)({
|
|
9
9
|
level: process.env.LOG_LEVEL || 'info',
|
|
@@ -11,19 +11,25 @@ exports.defaultLogger = (0, pino_1.default)({
|
|
|
11
11
|
target: 'pino-pretty',
|
|
12
12
|
},
|
|
13
13
|
});
|
|
14
|
-
const truncate = (
|
|
15
|
-
if (
|
|
16
|
-
return
|
|
14
|
+
const truncate = (val) => {
|
|
15
|
+
if (val == null) {
|
|
16
|
+
return val;
|
|
17
17
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
18
|
+
switch (typeof val) {
|
|
19
|
+
case 'string':
|
|
20
|
+
if (val.length > 66) {
|
|
21
|
+
return val.slice(0, 34) + '…' + val.slice(-32);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
return val;
|
|
25
|
+
}
|
|
26
|
+
case 'object':
|
|
27
|
+
if (Array.isArray(val)) {
|
|
28
|
+
return val.map(exports.truncate);
|
|
29
|
+
}
|
|
30
|
+
return Object.fromEntries(Object.entries(val).map(([k, v]) => [k, (0, exports.truncate)(v)]));
|
|
31
|
+
default:
|
|
32
|
+
return val;
|
|
23
33
|
}
|
|
24
34
|
};
|
|
25
35
|
exports.truncate = truncate;
|
|
26
|
-
const truncateStorageDiff = (diff) => {
|
|
27
|
-
return diff.map(([key, value]) => [key, (0, exports.truncate)(value)]);
|
|
28
|
-
};
|
|
29
|
-
exports.truncateStorageDiff = truncateStorageDiff;
|
package/dist/rpc/dev.js
CHANGED
|
@@ -66,5 +66,20 @@ const handlers = {
|
|
|
66
66
|
delta,
|
|
67
67
|
};
|
|
68
68
|
},
|
|
69
|
+
dev_setHead: async (context, [hashOrNumber]) => {
|
|
70
|
+
let block;
|
|
71
|
+
if (typeof hashOrNumber === 'number') {
|
|
72
|
+
const blockNumber = hashOrNumber > 0 ? hashOrNumber : context.chain.head.number + hashOrNumber;
|
|
73
|
+
block = await context.chain.getBlockAt(blockNumber);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
block = await context.chain.getBlock(hashOrNumber);
|
|
77
|
+
}
|
|
78
|
+
if (!block) {
|
|
79
|
+
throw new shared_1.ResponseError(1, `Block not found ${hashOrNumber}`);
|
|
80
|
+
}
|
|
81
|
+
await context.chain.setHead(block);
|
|
82
|
+
return block.hash;
|
|
83
|
+
},
|
|
69
84
|
};
|
|
70
85
|
exports.default = handlers;
|
package/dist/rpc/index.js
CHANGED
|
@@ -10,6 +10,10 @@ const substrate_1 = __importDefault(require("./substrate"));
|
|
|
10
10
|
const allHandlers = {
|
|
11
11
|
...substrate_1.default,
|
|
12
12
|
...dev_1.default,
|
|
13
|
+
rpc_methods: async () => Promise.resolve({
|
|
14
|
+
version: 1,
|
|
15
|
+
methods: Object.keys(allHandlers),
|
|
16
|
+
}),
|
|
13
17
|
};
|
|
14
18
|
const handler = (context) => ({ method, params }, subscriptionManager) => {
|
|
15
19
|
shared_1.logger.trace('Handling %s', method);
|
|
@@ -10,7 +10,11 @@ const handlers = {
|
|
|
10
10
|
return block.hash;
|
|
11
11
|
},
|
|
12
12
|
chain_getHeader: async (context, [hash]) => {
|
|
13
|
-
|
|
13
|
+
const block = await context.chain.getBlock(hash);
|
|
14
|
+
if (!block) {
|
|
15
|
+
throw new shared_1.ResponseError(1, `Block ${hash} not found`);
|
|
16
|
+
}
|
|
17
|
+
return await block.header;
|
|
14
18
|
},
|
|
15
19
|
chain_getBlock: async (context, [hash]) => {
|
|
16
20
|
const block = await context.chain.getBlock(hash);
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const util_1 = require("@polkadot/util");
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
3
5
|
const handlers = {
|
|
4
6
|
system_chain: async (context) => {
|
|
5
7
|
return context.chain.api.getSystemChain();
|
|
@@ -11,7 +13,8 @@ const handlers = {
|
|
|
11
13
|
return context.chain.api.getSystemName();
|
|
12
14
|
},
|
|
13
15
|
system_version: async (_context) => {
|
|
14
|
-
|
|
16
|
+
const { version } = JSON.parse((0, node_fs_1.readFileSync)('package.json', 'utf-8'));
|
|
17
|
+
return `chopsticks-v${version}`;
|
|
15
18
|
},
|
|
16
19
|
system_chainType: async (_context) => {
|
|
17
20
|
return 'Development';
|
|
@@ -23,5 +26,16 @@ const handlers = {
|
|
|
23
26
|
shouldhVePeers: false,
|
|
24
27
|
};
|
|
25
28
|
},
|
|
29
|
+
system_dryRun: async (context, [extrinsic, at]) => {
|
|
30
|
+
const { outcome } = await context.chain.dryRunExtrinsic(extrinsic, at);
|
|
31
|
+
return outcome.toHex();
|
|
32
|
+
},
|
|
33
|
+
system_accountNextIndex: async (context, [address]) => {
|
|
34
|
+
const head = context.chain.head;
|
|
35
|
+
const registry = await head.registry;
|
|
36
|
+
const account = registry.createType('AccountId', address);
|
|
37
|
+
const result = await head.call('AccountNonceApi_account_nonce', account.toHex());
|
|
38
|
+
return registry.createType('Index', (0, util_1.hexToU8a)(result.result)).toNumber();
|
|
39
|
+
},
|
|
26
40
|
};
|
|
27
41
|
exports.default = handlers;
|
package/dist/run-block.js
CHANGED
|
@@ -30,7 +30,7 @@ const runBlock = async (argv) => {
|
|
|
30
30
|
throw new Error(result.Error);
|
|
31
31
|
}
|
|
32
32
|
if (argv['html']) {
|
|
33
|
-
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(
|
|
33
|
+
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(parent, result.Call.storageDiff, block.hash);
|
|
34
34
|
console.log(`Generated preview ${filePath}`);
|
|
35
35
|
if (argv['open']) {
|
|
36
36
|
(0, open_html_1.openHtml)(filePath);
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -35,12 +35,12 @@ export declare const genesisSchema: z.ZodObject<{
|
|
|
35
35
|
}>;
|
|
36
36
|
}, "strip", z.ZodTypeAny, {
|
|
37
37
|
name: string;
|
|
38
|
+
id: string;
|
|
38
39
|
properties: {
|
|
39
40
|
ss58Format?: number | undefined;
|
|
40
41
|
tokenDecimals?: number | number[] | undefined;
|
|
41
42
|
tokenSymbol?: string | string[] | undefined;
|
|
42
43
|
};
|
|
43
|
-
id: string;
|
|
44
44
|
genesis: {
|
|
45
45
|
raw: {
|
|
46
46
|
top: Record<string, string>;
|
|
@@ -48,12 +48,12 @@ export declare const genesisSchema: z.ZodObject<{
|
|
|
48
48
|
};
|
|
49
49
|
}, {
|
|
50
50
|
name: string;
|
|
51
|
+
id: string;
|
|
51
52
|
properties: {
|
|
52
53
|
ss58Format?: number | undefined;
|
|
53
54
|
tokenDecimals?: number | number[] | undefined;
|
|
54
55
|
tokenSymbol?: string | string[] | undefined;
|
|
55
56
|
};
|
|
56
|
-
id: string;
|
|
57
57
|
genesis: {
|
|
58
58
|
raw: {
|
|
59
59
|
top: Record<string, string>;
|
|
@@ -105,12 +105,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
105
105
|
}>;
|
|
106
106
|
}, "strip", z.ZodTypeAny, {
|
|
107
107
|
name: string;
|
|
108
|
+
id: string;
|
|
108
109
|
properties: {
|
|
109
110
|
ss58Format?: number | undefined;
|
|
110
111
|
tokenDecimals?: number | number[] | undefined;
|
|
111
112
|
tokenSymbol?: string | string[] | undefined;
|
|
112
113
|
};
|
|
113
|
-
id: string;
|
|
114
114
|
genesis: {
|
|
115
115
|
raw: {
|
|
116
116
|
top: Record<string, string>;
|
|
@@ -118,12 +118,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
118
118
|
};
|
|
119
119
|
}, {
|
|
120
120
|
name: string;
|
|
121
|
+
id: string;
|
|
121
122
|
properties: {
|
|
122
123
|
ss58Format?: number | undefined;
|
|
123
124
|
tokenDecimals?: number | number[] | undefined;
|
|
124
125
|
tokenSymbol?: string | string[] | undefined;
|
|
125
126
|
};
|
|
126
|
-
id: string;
|
|
127
127
|
genesis: {
|
|
128
128
|
raw: {
|
|
129
129
|
top: Record<string, string>;
|
|
@@ -136,12 +136,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
136
136
|
db?: string | undefined;
|
|
137
137
|
genesis?: string | {
|
|
138
138
|
name: string;
|
|
139
|
+
id: string;
|
|
139
140
|
properties: {
|
|
140
141
|
ss58Format?: number | undefined;
|
|
141
142
|
tokenDecimals?: number | number[] | undefined;
|
|
142
143
|
tokenSymbol?: string | string[] | undefined;
|
|
143
144
|
};
|
|
144
|
-
id: string;
|
|
145
145
|
genesis: {
|
|
146
146
|
raw: {
|
|
147
147
|
top: Record<string, string>;
|
|
@@ -160,12 +160,12 @@ export declare const configSchema: z.ZodObject<{
|
|
|
160
160
|
db?: string | undefined;
|
|
161
161
|
genesis?: string | {
|
|
162
162
|
name: string;
|
|
163
|
+
id: string;
|
|
163
164
|
properties: {
|
|
164
165
|
ss58Format?: number | undefined;
|
|
165
166
|
tokenDecimals?: number | number[] | undefined;
|
|
166
167
|
tokenSymbol?: string | string[] | undefined;
|
|
167
168
|
};
|
|
168
|
-
id: string;
|
|
169
169
|
genesis: {
|
|
170
170
|
raw: {
|
|
171
171
|
top: Record<string, string>;
|
package/dist/setup.js
CHANGED
|
@@ -57,6 +57,8 @@ const setup = async (argv) => {
|
|
|
57
57
|
hash: blockHash,
|
|
58
58
|
number: Number(header.number),
|
|
59
59
|
},
|
|
60
|
+
mockSignatureHost: argv['mock-signature-host'],
|
|
61
|
+
allowUnresolvedImports: argv['allow-unresolved-imports'],
|
|
60
62
|
});
|
|
61
63
|
if (argv.timestamp)
|
|
62
64
|
await (0, time_travel_1.timeTravel)(chain, argv.timestamp);
|
package/dist/utils/decoder.js
CHANGED
|
@@ -13,8 +13,15 @@ const diffPatcher = (0, jsondiffpatch_1.create)({
|
|
|
13
13
|
array: { detectMove: false },
|
|
14
14
|
textDiff: { minLength: Number.MAX_VALUE }, // skip text diff
|
|
15
15
|
});
|
|
16
|
-
const
|
|
16
|
+
const _CACHE = {};
|
|
17
|
+
const getCache = (uid) => {
|
|
18
|
+
if (!_CACHE[uid]) {
|
|
19
|
+
_CACHE[uid] = {};
|
|
20
|
+
}
|
|
21
|
+
return _CACHE[uid];
|
|
22
|
+
};
|
|
17
23
|
const getStorageEntry = async (block, key) => {
|
|
24
|
+
const cache = getCache(block.chain.uid);
|
|
18
25
|
for (const [prefix, storageEntry] of Object.entries(cache)) {
|
|
19
26
|
if (key.startsWith(prefix))
|
|
20
27
|
return storageEntry;
|
|
@@ -87,13 +94,10 @@ const decodeKeyValue = async (block, key, value) => {
|
|
|
87
94
|
};
|
|
88
95
|
exports.decodeKeyValue = decodeKeyValue;
|
|
89
96
|
const decodeStorageDiff = async (block, diff) => {
|
|
90
|
-
const parent = await block.parentBlock;
|
|
91
|
-
if (!parent)
|
|
92
|
-
throw new Error('Cannot find parent block');
|
|
93
97
|
const oldState = {};
|
|
94
98
|
const newState = {};
|
|
95
99
|
for (const [key, value] of diff) {
|
|
96
|
-
lodash_1.default.merge(oldState, await (0, exports.decodeKeyValue)(
|
|
100
|
+
lodash_1.default.merge(oldState, await (0, exports.decodeKeyValue)(block, key, (await block.get(key))));
|
|
97
101
|
lodash_1.default.merge(newState, await (0, exports.decodeKeyValue)(block, key, value));
|
|
98
102
|
}
|
|
99
103
|
return [oldState, newState, diffPatcher.diff(oldState, newState)];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.connectDownward = void 0;
|
|
4
|
+
const util_1 = require("@polkadot/util");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const _1 = require(".");
|
|
7
|
+
const set_storage_1 = require("../utils/set-storage");
|
|
8
|
+
const connectDownward = async (relaychain, parachain) => {
|
|
9
|
+
const meta = await relaychain.head.meta;
|
|
10
|
+
const paraId = await (0, utils_1.getParaId)(parachain);
|
|
11
|
+
const downwardMessageQueuesKey = (0, utils_1.compactHex)(meta.query.dmp.downwardMessageQueues(paraId));
|
|
12
|
+
await relaychain.headState.subscribeStorage([downwardMessageQueuesKey], async (head, pairs) => {
|
|
13
|
+
const value = pairs[0][1];
|
|
14
|
+
if (!value)
|
|
15
|
+
return;
|
|
16
|
+
const meta = await relaychain.head.meta;
|
|
17
|
+
const downwardMessageQueuesKey = (0, utils_1.compactHex)(meta.query.dmp.downwardMessageQueues(paraId));
|
|
18
|
+
// clear relaychain message queue
|
|
19
|
+
await (0, set_storage_1.setStorage)(relaychain, [[downwardMessageQueuesKey, null]], head.hash);
|
|
20
|
+
const downwardMessages = meta.registry
|
|
21
|
+
.createType('Vec<PolkadotCorePrimitivesInboundDownwardMessage>', (0, util_1.hexToU8a)(value))
|
|
22
|
+
.toJSON();
|
|
23
|
+
if (downwardMessages.length === 0)
|
|
24
|
+
return;
|
|
25
|
+
_1.logger.debug({ downwardMessages }, 'downward_message');
|
|
26
|
+
await parachain.newBlock({ inherent: { downwardMessages } });
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
exports.connectDownward = connectDownward;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.connectHorizontal = void 0;
|
|
4
|
+
const util_1 = require("@polkadot/util");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const _1 = require(".");
|
|
7
|
+
const set_storage_1 = require("../utils/set-storage");
|
|
8
|
+
const connectHorizontal = async (parachains) => {
|
|
9
|
+
for (const [id, chain] of Object.entries(parachains)) {
|
|
10
|
+
const meta = await chain.head.meta;
|
|
11
|
+
const hrmpOutboundMessagesKey = (0, utils_1.compactHex)(meta.query.parachainSystem.hrmpOutboundMessages());
|
|
12
|
+
await chain.headState.subscribeStorage([hrmpOutboundMessagesKey], async (head, pairs) => {
|
|
13
|
+
const value = pairs[0][1];
|
|
14
|
+
if (!value)
|
|
15
|
+
return;
|
|
16
|
+
const meta = await chain.head.meta;
|
|
17
|
+
const hrmpOutboundMessagesKey = (0, utils_1.compactHex)(meta.query.parachainSystem.hrmpOutboundMessages());
|
|
18
|
+
// clear sender message queue
|
|
19
|
+
await (0, set_storage_1.setStorage)(chain, [[hrmpOutboundMessagesKey, null]], head.hash);
|
|
20
|
+
const outboundHrmpMessage = meta.registry
|
|
21
|
+
.createType('Vec<PolkadotCorePrimitivesOutboundHrmpMessage>', (0, util_1.hexToU8a)(value))
|
|
22
|
+
.toJSON();
|
|
23
|
+
_1.logger.info({ outboundHrmpMessage }, 'outboundHrmpMessage');
|
|
24
|
+
for (const { recipient, data } of outboundHrmpMessage) {
|
|
25
|
+
const horizontalMessages = {
|
|
26
|
+
[Number(id)]: [{ sentAt: chain.head.number, data }],
|
|
27
|
+
};
|
|
28
|
+
const receiver = parachains[recipient];
|
|
29
|
+
if (receiver) {
|
|
30
|
+
await receiver.newBlock({ inherent: { horizontalMessages } });
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
exports.connectHorizontal = connectHorizontal;
|
package/dist/xcm/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
1
|
import { Blockchain } from '../blockchain';
|
|
2
|
-
export declare const
|
|
2
|
+
export declare const logger: import("pino").default.Logger<{
|
|
3
|
+
level: string;
|
|
4
|
+
transport: {
|
|
5
|
+
target: string;
|
|
6
|
+
};
|
|
7
|
+
} & import("pino").default.ChildLoggerOptions>;
|
|
8
|
+
export declare const connectVertical: (relaychain: Blockchain, parachain: Blockchain) => Promise<void>;
|
|
3
9
|
export declare const connectParachains: (parachains: Blockchain[]) => Promise<void>;
|
package/dist/xcm/index.js
CHANGED
|
@@ -1,67 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.connectParachains = exports.
|
|
4
|
-
const
|
|
5
|
-
const
|
|
3
|
+
exports.connectParachains = exports.connectVertical = exports.logger = void 0;
|
|
4
|
+
const downward_1 = require("./downward");
|
|
5
|
+
const horizontal_1 = require("./horizontal");
|
|
6
|
+
const upward_1 = require("./upward");
|
|
6
7
|
const logger_1 = require("../logger");
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
await relaychain.headState.subscribeStorage([downwardMessageQueuesKey], async (head, pairs) => {
|
|
14
|
-
const value = pairs[0][1];
|
|
15
|
-
if (!value)
|
|
16
|
-
return;
|
|
17
|
-
const meta = await relaychain.head.meta;
|
|
18
|
-
const downwardMessageQueuesKey = (0, utils_1.compactHex)(meta.query.dmp.downwardMessageQueues(paraId));
|
|
19
|
-
// clear relaychain message queue
|
|
20
|
-
await (0, set_storage_1.setStorage)(relaychain, [[downwardMessageQueuesKey, null]], head.hash);
|
|
21
|
-
const downwardMessages = meta.registry
|
|
22
|
-
.createType('Vec<PolkadotCorePrimitivesInboundDownwardMessage>', (0, util_1.hexToU8a)(value))
|
|
23
|
-
.toJSON();
|
|
24
|
-
logger.debug({ downwardMessages }, 'downward_message');
|
|
25
|
-
await parachain.newBlock({ inherent: { downwardMessages } });
|
|
26
|
-
});
|
|
27
|
-
logger.info(`Connected relaychain '${await relaychain.api.getSystemChain()}' with parachain '${await parachain.api.getSystemChain()}'`);
|
|
8
|
+
const utils_1 = require("../utils");
|
|
9
|
+
exports.logger = logger_1.defaultLogger.child({ name: 'xcm' });
|
|
10
|
+
const connectVertical = async (relaychain, parachain) => {
|
|
11
|
+
await (0, downward_1.connectDownward)(relaychain, parachain);
|
|
12
|
+
await (0, upward_1.connectUpward)(parachain, relaychain);
|
|
13
|
+
exports.logger.info(`Connected relaychain '${await relaychain.api.getSystemChain()}' with parachain '${await parachain.api.getSystemChain()}'`);
|
|
28
14
|
};
|
|
29
|
-
exports.
|
|
15
|
+
exports.connectVertical = connectVertical;
|
|
30
16
|
const connectParachains = async (parachains) => {
|
|
31
17
|
const list = {};
|
|
32
18
|
for (const chain of parachains) {
|
|
33
19
|
const paraId = await (0, utils_1.getParaId)(chain);
|
|
34
20
|
list[paraId.toNumber()] = chain;
|
|
35
21
|
}
|
|
36
|
-
await connectHorizontal(list);
|
|
37
|
-
logger.info(
|
|
22
|
+
await (0, horizontal_1.connectHorizontal)(list);
|
|
23
|
+
exports.logger.info(`Connected parachains [${Object.keys(list)}]`);
|
|
38
24
|
};
|
|
39
25
|
exports.connectParachains = connectParachains;
|
|
40
|
-
const connectHorizontal = async (parachains) => {
|
|
41
|
-
for (const [id, chain] of Object.entries(parachains)) {
|
|
42
|
-
const meta = await chain.head.meta;
|
|
43
|
-
const hrmpOutboundMessagesKey = (0, utils_1.compactHex)(meta.query.parachainSystem.hrmpOutboundMessages());
|
|
44
|
-
await chain.headState.subscribeStorage([hrmpOutboundMessagesKey], async (head, pairs) => {
|
|
45
|
-
const value = pairs[0][1];
|
|
46
|
-
if (!value)
|
|
47
|
-
return;
|
|
48
|
-
const meta = await chain.head.meta;
|
|
49
|
-
const hrmpOutboundMessagesKey = (0, utils_1.compactHex)(meta.query.parachainSystem.hrmpOutboundMessages());
|
|
50
|
-
// clear sender message queue
|
|
51
|
-
await (0, set_storage_1.setStorage)(chain, [[hrmpOutboundMessagesKey, null]], head.hash);
|
|
52
|
-
const outboundHrmpMessage = meta.registry
|
|
53
|
-
.createType('Vec<PolkadotCorePrimitivesOutboundHrmpMessage>', (0, util_1.hexToU8a)(value))
|
|
54
|
-
.toJSON();
|
|
55
|
-
logger.info({ outboundHrmpMessage }, 'outboundHrmpMessage');
|
|
56
|
-
for (const { recipient, data } of outboundHrmpMessage) {
|
|
57
|
-
const horizontalMessages = {
|
|
58
|
-
[Number(id)]: [{ sentAt: chain.head.number, data }],
|
|
59
|
-
};
|
|
60
|
-
const receiver = parachains[recipient];
|
|
61
|
-
if (receiver) {
|
|
62
|
-
await receiver.newBlock({ inherent: { horizontalMessages } });
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.connectUpward = void 0;
|
|
4
|
+
const util_1 = require("@polkadot/util");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const _1 = require(".");
|
|
7
|
+
const set_storage_1 = require("../utils/set-storage");
|
|
8
|
+
const connectUpward = async (parachain, relaychain) => {
|
|
9
|
+
const meta = await parachain.head.meta;
|
|
10
|
+
const paraId = await (0, utils_1.getParaId)(parachain);
|
|
11
|
+
const upwardMessagesKey = (0, utils_1.compactHex)(meta.query.parachainSystem.upwardMessages());
|
|
12
|
+
await parachain.headState.subscribeStorage([upwardMessagesKey], async (head, pairs) => {
|
|
13
|
+
const value = pairs[0][1];
|
|
14
|
+
if (!value)
|
|
15
|
+
return;
|
|
16
|
+
const parachainMeta = await parachain.head.meta;
|
|
17
|
+
const upwardMessagesKey = (0, utils_1.compactHex)(parachainMeta.query.parachainSystem.upwardMessages());
|
|
18
|
+
// clear parachain message queue
|
|
19
|
+
await (0, set_storage_1.setStorage)(parachain, [[upwardMessagesKey, null]], head.hash);
|
|
20
|
+
const relaychainMeta = await relaychain.head.meta;
|
|
21
|
+
const upwardMessages = parachainMeta.registry.createType('Vec<Bytes>', (0, util_1.hexToU8a)(value));
|
|
22
|
+
if (upwardMessages.length === 0)
|
|
23
|
+
return;
|
|
24
|
+
const queueSize = parachainMeta.registry.createType('(u32, u32)', [
|
|
25
|
+
upwardMessages.length,
|
|
26
|
+
upwardMessages.map((x) => x.byteLength).reduce((s, i) => s + i, 0),
|
|
27
|
+
]);
|
|
28
|
+
const needsDispatch = parachainMeta.registry.createType('Vec<u32>', [paraId]);
|
|
29
|
+
_1.logger.debug({ [paraId.toNumber()]: upwardMessages.toJSON(), queueSize: queueSize.toJSON() }, 'upward_message');
|
|
30
|
+
// TODO: make sure we append instead of replace
|
|
31
|
+
relaychain.head.pushStorageLayer().setAll([
|
|
32
|
+
[(0, utils_1.compactHex)(relaychainMeta.query.ump.needsDispatch()), needsDispatch.toHex()],
|
|
33
|
+
[(0, utils_1.compactHex)(relaychainMeta.query.ump.relayDispatchQueues(paraId)), upwardMessages.toHex()],
|
|
34
|
+
[(0, utils_1.compactHex)(relaychainMeta.query.ump.relayDispatchQueueSize(paraId)), queueSize.toHex()],
|
|
35
|
+
]);
|
|
36
|
+
await relaychain.newBlock();
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
exports.connectUpward = connectUpward;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acala-network/chopsticks",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.3",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"author": "Bryan Chen <xlchen1291@gmail.com>",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"fix": "eslint . --ext .js,.ts --fix && prettier -w .",
|
|
17
17
|
"prepare": "husky install",
|
|
18
18
|
"start": "ts-node --transpile-only src/index.ts",
|
|
19
|
-
"build": "
|
|
19
|
+
"build": "rm -rf dist && tsc -p tsconfig.prod.json",
|
|
20
20
|
"build-wasm": "wasm-pack build executor --target nodejs --scope acala-network",
|
|
21
21
|
"build-wasm-logging": "yarn build-wasm --features=logging",
|
|
22
22
|
"check": "cd executor && cargo check --locked",
|
|
@@ -30,47 +30,45 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@acala-network/chopsticks-executor": "0.3.0",
|
|
33
|
-
"@polkadot/api": "^9.
|
|
34
|
-
"@polkadot/rpc-provider": "^9.
|
|
35
|
-
"@polkadot/types": "^9.
|
|
36
|
-
"@polkadot/types-codec": "^9.
|
|
37
|
-
"@polkadot/types-known": "^9.
|
|
38
|
-
"@polkadot/util": "^10.2.
|
|
39
|
-
"@polkadot/util-crypto": "^10.2.
|
|
40
|
-
"axios": "^1.2.
|
|
33
|
+
"@polkadot/api": "^9.11.3",
|
|
34
|
+
"@polkadot/rpc-provider": "^9.11.3",
|
|
35
|
+
"@polkadot/types": "^9.11.3",
|
|
36
|
+
"@polkadot/types-codec": "^9.11.3",
|
|
37
|
+
"@polkadot/types-known": "^9.11.3",
|
|
38
|
+
"@polkadot/util": "^10.2.6",
|
|
39
|
+
"@polkadot/util-crypto": "^10.2.6",
|
|
40
|
+
"axios": "^1.2.3",
|
|
41
41
|
"js-yaml": "^4.1.0",
|
|
42
42
|
"jsondiffpatch": "^0.4.1",
|
|
43
43
|
"lodash": "^4.17.21",
|
|
44
|
-
"pino": "^8.
|
|
44
|
+
"pino": "^8.8.0",
|
|
45
45
|
"pino-pretty": "^9.1.1",
|
|
46
46
|
"reflect-metadata": "^0.1.13",
|
|
47
|
-
"sqlite3": "^5.1.
|
|
47
|
+
"sqlite3": "^5.1.4",
|
|
48
48
|
"typeorm": "^0.3.11",
|
|
49
|
-
"typescript": "^4.9.
|
|
50
|
-
"ws": "^8.
|
|
49
|
+
"typescript": "^4.9.4",
|
|
50
|
+
"ws": "^8.12.0",
|
|
51
51
|
"yargs": "^17.6.2",
|
|
52
|
-
"zod": "^3.
|
|
52
|
+
"zod": "^3.20.2"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/js-yaml": "^4.0.5",
|
|
56
56
|
"@types/lodash": "^4.14.191",
|
|
57
57
|
"@types/node": "^18.11.18",
|
|
58
|
-
"@types/
|
|
59
|
-
"@types/
|
|
60
|
-
"@
|
|
61
|
-
"@typescript-eslint/
|
|
62
|
-
"
|
|
63
|
-
"eslint": "^8.
|
|
64
|
-
"eslint-
|
|
65
|
-
"eslint-plugin-import": "^2.26.0",
|
|
58
|
+
"@types/ws": "^8.5.4",
|
|
59
|
+
"@types/yargs": "^17.0.19",
|
|
60
|
+
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
|
61
|
+
"@typescript-eslint/parser": "^5.48.2",
|
|
62
|
+
"eslint": "^8.32.0",
|
|
63
|
+
"eslint-config-prettier": "^8.6.0",
|
|
64
|
+
"eslint-plugin-import": "^2.27.5",
|
|
66
65
|
"eslint-plugin-sort-imports-es6-autofix": "^0.6.0",
|
|
67
|
-
"husky": "^8.0.
|
|
66
|
+
"husky": "^8.0.3",
|
|
68
67
|
"lint-staged": "^13.1.0",
|
|
69
|
-
"prettier": "^2.8.
|
|
70
|
-
"rimraf": "^3.0.2",
|
|
68
|
+
"prettier": "^2.8.3",
|
|
71
69
|
"ts-node": "^10.9.1",
|
|
72
70
|
"ts-node-dev": "^2.0.0",
|
|
73
|
-
"vitest": "^0.
|
|
71
|
+
"vitest": "^0.27.2",
|
|
74
72
|
"wasm-pack": "^0.10.3"
|
|
75
73
|
},
|
|
76
74
|
"files": [
|