@acala-network/chopsticks 0.4.0 → 0.4.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/lib/blockchain/block-builder.js +4 -1
- package/lib/blockchain/index.d.ts +5 -3
- package/lib/blockchain/index.js +43 -4
- package/lib/blockchain/inherent/parachain/validation-data.d.ts +3 -9
- package/lib/blockchain/inherent/parachain/validation-data.js +3 -2
- package/lib/blockchain/txpool.d.ts +5 -1
- package/lib/blockchain/txpool.js +7 -2
- package/lib/cli.js +2 -1
- package/lib/rpc/dev/dry-run.d.ts +2 -0
- package/lib/rpc/dev/dry-run.js +75 -0
- package/lib/rpc/{dev.d.ts → dev/index.d.ts} +1 -1
- package/lib/rpc/{dev.js → dev/index.js} +6 -31
- package/lib/rpc/substrate/author.js +1 -1
- package/lib/server.js +1 -1
- package/lib/setup-with-server.js +1 -1
- package/lib/utils/time-travel.js +3 -2
- package/lib/xcm/downward.js +1 -1
- package/lib/xcm/horizontal.js +2 -6
- package/lib/xcm/upward.js +8 -13
- package/package.json +9 -8
- package/template/diff.html +3 -3
|
@@ -71,8 +71,11 @@ const newHeader = async (head) => {
|
|
|
71
71
|
],
|
|
72
72
|
},
|
|
73
73
|
...consensus.rest,
|
|
74
|
-
head.pushStorageLayer().set((0, utils_1.compactHex)(meta.query.randomness.notFirstBlock()), "Deleted" /* StorageValueKind.Deleted */),
|
|
75
74
|
];
|
|
75
|
+
if (meta.query.randomness) {
|
|
76
|
+
// reset notFirstBlock so randomness will skip validation
|
|
77
|
+
head.pushStorageLayer().set((0, utils_1.compactHex)(meta.query.randomness.notFirstBlock()), "Deleted" /* StorageValueKind.Deleted */);
|
|
78
|
+
}
|
|
76
79
|
}
|
|
77
80
|
const header = meta.registry.createType('Header', {
|
|
78
81
|
parentHash: head.hash,
|
|
@@ -4,7 +4,7 @@ import { HexString } from '@polkadot/util/types';
|
|
|
4
4
|
import { RegisteredTypes } from '@polkadot/types/types';
|
|
5
5
|
import { Api } from '../api';
|
|
6
6
|
import { Block } from './block';
|
|
7
|
-
import { BuildBlockMode, BuildBlockParams, HorizontalMessage, TxPool } from './txpool';
|
|
7
|
+
import { BuildBlockMode, BuildBlockParams, DownwardMessage, HorizontalMessage, TxPool, UpcomingBlockParams } from './txpool';
|
|
8
8
|
import { HeadState } from './head-state';
|
|
9
9
|
import { InherentProvider } from './inherent';
|
|
10
10
|
export interface Options {
|
|
@@ -38,7 +38,7 @@ export declare class Blockchain {
|
|
|
38
38
|
setHead(block: Block): Promise<void>;
|
|
39
39
|
submitExtrinsic(extrinsic: HexString): Promise<HexString>;
|
|
40
40
|
newBlock(params?: BuildBlockParams): Promise<Block>;
|
|
41
|
-
upcomingBlock(
|
|
41
|
+
upcomingBlock(params?: UpcomingBlockParams): Promise<Block>;
|
|
42
42
|
dryRunExtrinsic(extrinsic: HexString | {
|
|
43
43
|
call: HexString;
|
|
44
44
|
address: string;
|
|
@@ -46,6 +46,8 @@ export declare class Blockchain {
|
|
|
46
46
|
outcome: ApplyExtrinsicResult;
|
|
47
47
|
storageDiff: [HexString, HexString | null][];
|
|
48
48
|
}>;
|
|
49
|
-
dryRunHrmp(hrmp: Record<number, HorizontalMessage[]
|
|
49
|
+
dryRunHrmp(hrmp: Record<number, HorizontalMessage[]>, at?: HexString): Promise<[HexString, HexString | null][]>;
|
|
50
|
+
dryRunDmp(dmp: DownwardMessage[], at?: HexString): Promise<[HexString, HexString | null][]>;
|
|
51
|
+
dryRunUmp(ump: Record<number, HexString[]>, at?: HexString): Promise<[HexString, HexString | null][]>;
|
|
50
52
|
getInherents(): Promise<HexString[]>;
|
|
51
53
|
}
|
package/lib/blockchain/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const util_1 = require("@polkadot/util");
|
|
|
6
6
|
const block_1 = require("./block");
|
|
7
7
|
const txpool_1 = require("./txpool");
|
|
8
8
|
const head_state_1 = require("./head-state");
|
|
9
|
+
const utils_1 = require("../utils");
|
|
9
10
|
const logger_1 = require("../logger");
|
|
10
11
|
const block_builder_1 = require("./block-builder");
|
|
11
12
|
const logger = logger_1.defaultLogger.child({ name: 'blockchain' });
|
|
@@ -121,8 +122,8 @@ class Blockchain {
|
|
|
121
122
|
await this.#txpool.buildBlock(params);
|
|
122
123
|
return this.#head;
|
|
123
124
|
}
|
|
124
|
-
async upcomingBlock(
|
|
125
|
-
return this.#txpool.upcomingBlock(
|
|
125
|
+
async upcomingBlock(params) {
|
|
126
|
+
return this.#txpool.upcomingBlock(params);
|
|
126
127
|
}
|
|
127
128
|
async dryRunExtrinsic(extrinsic, at) {
|
|
128
129
|
await this.api.isReady;
|
|
@@ -136,12 +137,50 @@ class Blockchain {
|
|
|
136
137
|
const outcome = registry.createType('ApplyExtrinsicResult', result);
|
|
137
138
|
return { outcome, storageDiff };
|
|
138
139
|
}
|
|
139
|
-
async dryRunHrmp(hrmp) {
|
|
140
|
+
async dryRunHrmp(hrmp, at) {
|
|
140
141
|
await this.api.isReady;
|
|
141
|
-
const head = this.head;
|
|
142
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
143
|
+
if (!head) {
|
|
144
|
+
throw new Error(`Cannot find block ${at}`);
|
|
145
|
+
}
|
|
142
146
|
const inherents = await this.#inherentProvider.createInherents(head, { horizontalMessages: hrmp });
|
|
143
147
|
return (0, block_builder_1.dryRunInherents)(head, inherents);
|
|
144
148
|
}
|
|
149
|
+
async dryRunDmp(dmp, at) {
|
|
150
|
+
await this.api.isReady;
|
|
151
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
152
|
+
if (!head) {
|
|
153
|
+
throw new Error(`Cannot find block ${at}`);
|
|
154
|
+
}
|
|
155
|
+
const inherents = await this.#inherentProvider.createInherents(head, { downwardMessages: dmp });
|
|
156
|
+
return (0, block_builder_1.dryRunInherents)(head, inherents);
|
|
157
|
+
}
|
|
158
|
+
async dryRunUmp(ump, at) {
|
|
159
|
+
await this.api.isReady;
|
|
160
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
161
|
+
if (!head) {
|
|
162
|
+
throw new Error(`Cannot find block ${at}`);
|
|
163
|
+
}
|
|
164
|
+
const meta = await head.meta;
|
|
165
|
+
const needsDispatch = meta.registry.createType('Vec<u32>', Object.keys(ump));
|
|
166
|
+
const stroageValues = [
|
|
167
|
+
[(0, utils_1.compactHex)(meta.query.ump.needsDispatch()), needsDispatch.toHex()],
|
|
168
|
+
];
|
|
169
|
+
for (const [paraId, messages] of Object.entries(ump)) {
|
|
170
|
+
const upwardMessages = meta.registry.createType('Vec<Bytes>', messages);
|
|
171
|
+
if (upwardMessages.length === 0)
|
|
172
|
+
throw new Error('No upward meesage');
|
|
173
|
+
const queueSize = meta.registry.createType('(u32, u32)', [
|
|
174
|
+
upwardMessages.length,
|
|
175
|
+
upwardMessages.map((x) => x.byteLength).reduce((s, i) => s + i, 0),
|
|
176
|
+
]);
|
|
177
|
+
stroageValues.push([(0, utils_1.compactHex)(meta.query.ump.relayDispatchQueues(paraId)), upwardMessages.toHex()]);
|
|
178
|
+
stroageValues.push([(0, utils_1.compactHex)(meta.query.ump.relayDispatchQueueSize(paraId)), queueSize.toHex()]);
|
|
179
|
+
}
|
|
180
|
+
head.pushStorageLayer().setAll(stroageValues);
|
|
181
|
+
const inherents = await this.#inherentProvider.createInherents(head);
|
|
182
|
+
return (0, block_builder_1.dryRunInherents)(head, inherents);
|
|
183
|
+
}
|
|
145
184
|
async getInherents() {
|
|
146
185
|
await this.api.isReady;
|
|
147
186
|
const inherents = await this.#inherentProvider.createInherents(this.head);
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { HexString } from '@polkadot/util/types';
|
|
2
2
|
import { Block } from '../../block';
|
|
3
|
-
import { BuildBlockParams } from '../../txpool';
|
|
3
|
+
import { BuildBlockParams, DownwardMessage, HorizontalMessage } from '../../txpool';
|
|
4
4
|
import { CreateInherents } from '..';
|
|
5
5
|
export type ValidationData = {
|
|
6
|
-
downwardMessages:
|
|
7
|
-
|
|
8
|
-
msg: HexString;
|
|
9
|
-
}[];
|
|
10
|
-
horizontalMessages: Record<number, {
|
|
11
|
-
sent_at: number;
|
|
12
|
-
data: HexString;
|
|
13
|
-
}[]>;
|
|
6
|
+
downwardMessages: DownwardMessage[];
|
|
7
|
+
horizontalMessages: Record<number, HorizontalMessage[]>;
|
|
14
8
|
validationData: {
|
|
15
9
|
relayParentNumber: number;
|
|
16
10
|
relayParentStorageRoot: HexString;
|
|
@@ -80,7 +80,7 @@ class SetValidationData {
|
|
|
80
80
|
dmqMqcHeadHash = (0, util_crypto_1.blake2AsHex)((0, util_1.u8aConcat)(meta.registry.createType('Hash', dmqMqcHeadHash).toU8a(), meta.registry.createType('BlockNumber', sentAt).toU8a(), (0, util_crypto_1.blake2AsU8a)(meta.registry.createType('Bytes', msg).toU8a(), 256)), 256);
|
|
81
81
|
downwardMessages.push({
|
|
82
82
|
msg,
|
|
83
|
-
|
|
83
|
+
sentAt,
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
newEntries.push([dmqMqcHeadKey, dmqMqcHeadHash]);
|
|
@@ -92,6 +92,7 @@ class SetValidationData {
|
|
|
92
92
|
.createType('Vec<ParaId>', decoded[hrmpEgressChannelIndexKey])
|
|
93
93
|
.toJSON();
|
|
94
94
|
const hrmpMessages = {
|
|
95
|
+
// reset values, we just need the keys
|
|
95
96
|
...lodash_1.default.mapValues(extrinsic.horizontalMessages, () => []),
|
|
96
97
|
...(params?.horizontalMessages || {}),
|
|
97
98
|
};
|
|
@@ -120,7 +121,7 @@ class SetValidationData {
|
|
|
120
121
|
abridgedHrmp.totalSize = abridgedHrmp.totalSize + bytes.length;
|
|
121
122
|
paraMessages.push({
|
|
122
123
|
data,
|
|
123
|
-
|
|
124
|
+
sentAt,
|
|
124
125
|
});
|
|
125
126
|
}
|
|
126
127
|
horizontalMessages[sender] = paraMessages;
|
|
@@ -24,6 +24,10 @@ export interface BuildBlockParams {
|
|
|
24
24
|
horizontalMessages?: Record<number, HorizontalMessage[]>;
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
|
+
export interface UpcomingBlockParams {
|
|
28
|
+
skipCount?: number;
|
|
29
|
+
timeout?: number;
|
|
30
|
+
}
|
|
27
31
|
export declare class TxPool {
|
|
28
32
|
#private;
|
|
29
33
|
readonly event: EventEmitter;
|
|
@@ -31,5 +35,5 @@ export declare class TxPool {
|
|
|
31
35
|
get pendingExtrinsics(): HexString[];
|
|
32
36
|
submitExtrinsic(extrinsic: HexString): void;
|
|
33
37
|
buildBlock(params?: BuildBlockParams): Promise<void>;
|
|
34
|
-
upcomingBlock(
|
|
38
|
+
upcomingBlock(params?: UpcomingBlockParams): Promise<Block>;
|
|
35
39
|
}
|
package/lib/blockchain/txpool.js
CHANGED
|
@@ -54,10 +54,15 @@ class TxPool {
|
|
|
54
54
|
await this.#lastBuildBlockPromise;
|
|
55
55
|
this.#last.next(this.#chain.head);
|
|
56
56
|
}
|
|
57
|
-
async upcomingBlock(
|
|
57
|
+
async upcomingBlock(params) {
|
|
58
|
+
const { skipCount, timeout: millisecs } = { skipCount: 0, ...(params || {}) };
|
|
58
59
|
if (skipCount < 0)
|
|
59
60
|
throw new Error('skipCount needs to be greater or equal to 0');
|
|
60
|
-
|
|
61
|
+
let stream$ = this.#last.pipe();
|
|
62
|
+
if (millisecs) {
|
|
63
|
+
stream$ = stream$.pipe((0, operators_1.timeout)(millisecs));
|
|
64
|
+
}
|
|
65
|
+
return (0, rxjs_1.firstValueFrom)(stream$.pipe((0, operators_1.skip)(1 + skipCount), (0, operators_1.take)(1)));
|
|
61
66
|
}
|
|
62
67
|
async #buildBlock(wait, params) {
|
|
63
68
|
await this.#chain.api.isReady;
|
package/lib/cli.js
CHANGED
|
@@ -28,8 +28,9 @@ const processConfig = async (path) => {
|
|
|
28
28
|
};
|
|
29
29
|
const processArgv = async (argv) => {
|
|
30
30
|
if (argv.config) {
|
|
31
|
-
|
|
31
|
+
argv = { ...(await processConfig(argv.config)), ...argv };
|
|
32
32
|
}
|
|
33
|
+
argv.port = argv.port ?? (process.env.PORT ? Number(process.env.PORT) : 8000);
|
|
33
34
|
return argv;
|
|
34
35
|
};
|
|
35
36
|
const defaultOptions = {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.dev_dryRun = void 0;
|
|
7
|
+
const zod_1 = __importDefault(require("zod"));
|
|
8
|
+
const decoder_1 = require("../../utils/decoder");
|
|
9
|
+
const generate_html_diff_1 = require("../../utils/generate-html-diff");
|
|
10
|
+
const zHex = zod_1.default.custom((val) => /^0x\w+$/.test(val));
|
|
11
|
+
const zHash = zod_1.default.string().length(66).and(zHex);
|
|
12
|
+
const zParaId = zod_1.default.string().regex(/^\d+$/).transform(Number);
|
|
13
|
+
const dryRunSchema = zod_1.default.object({
|
|
14
|
+
raw: zod_1.default.boolean().optional(),
|
|
15
|
+
html: zod_1.default.boolean().optional(),
|
|
16
|
+
extrinsic: zHex
|
|
17
|
+
.or(zod_1.default.object({
|
|
18
|
+
call: zHex,
|
|
19
|
+
address: zHex,
|
|
20
|
+
}))
|
|
21
|
+
.optional(),
|
|
22
|
+
hrmp: zod_1.default
|
|
23
|
+
.record(zParaId, zod_1.default
|
|
24
|
+
.array(zod_1.default.object({
|
|
25
|
+
sentAt: zod_1.default.number(),
|
|
26
|
+
data: zHex,
|
|
27
|
+
}))
|
|
28
|
+
.min(1))
|
|
29
|
+
.optional(),
|
|
30
|
+
dmp: zod_1.default
|
|
31
|
+
.array(zod_1.default.object({
|
|
32
|
+
sentAt: zod_1.default.number(),
|
|
33
|
+
msg: zHex,
|
|
34
|
+
}))
|
|
35
|
+
.min(1)
|
|
36
|
+
.optional(),
|
|
37
|
+
ump: zod_1.default.record(zParaId, zod_1.default.array(zHex).min(1)).optional(),
|
|
38
|
+
at: zHash.optional(),
|
|
39
|
+
});
|
|
40
|
+
const dev_dryRun = async (context, [params]) => {
|
|
41
|
+
const { html, extrinsic, hrmp, dmp, ump, raw, at } = dryRunSchema.parse(params);
|
|
42
|
+
const dryRun = async () => {
|
|
43
|
+
if (extrinsic) {
|
|
44
|
+
const { outcome, storageDiff } = await context.chain.dryRunExtrinsic(extrinsic, at);
|
|
45
|
+
if (outcome.isErr) {
|
|
46
|
+
throw new Error(outcome.asErr.toString());
|
|
47
|
+
}
|
|
48
|
+
return storageDiff;
|
|
49
|
+
}
|
|
50
|
+
if (hrmp) {
|
|
51
|
+
return context.chain.dryRunHrmp(hrmp, at);
|
|
52
|
+
}
|
|
53
|
+
if (dmp) {
|
|
54
|
+
return context.chain.dryRunDmp(dmp, at);
|
|
55
|
+
}
|
|
56
|
+
if (ump) {
|
|
57
|
+
return context.chain.dryRunUmp(ump, at);
|
|
58
|
+
}
|
|
59
|
+
throw new Error('No extrinsic to run');
|
|
60
|
+
};
|
|
61
|
+
const storageDiff = await dryRun();
|
|
62
|
+
if (html) {
|
|
63
|
+
return (0, generate_html_diff_1.generateHtmlDiff)(context.chain.head, storageDiff);
|
|
64
|
+
}
|
|
65
|
+
if (raw) {
|
|
66
|
+
return storageDiff;
|
|
67
|
+
}
|
|
68
|
+
const [oldData, newData, delta] = await (0, decoder_1.decodeStorageDiff)(context.chain.head, storageDiff);
|
|
69
|
+
return {
|
|
70
|
+
old: oldData,
|
|
71
|
+
new: newData,
|
|
72
|
+
delta,
|
|
73
|
+
};
|
|
74
|
+
};
|
|
75
|
+
exports.dev_dryRun = dev_dryRun;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const shared_1 = require("
|
|
4
|
-
const set_storage_1 = require("
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
const time_travel_1 = require("../utils/time-travel");
|
|
3
|
+
const shared_1 = require("../shared");
|
|
4
|
+
const set_storage_1 = require("../../utils/set-storage");
|
|
5
|
+
const logger_1 = require("../../logger");
|
|
6
|
+
const dry_run_1 = require("./dry-run");
|
|
7
|
+
const time_travel_1 = require("../../utils/time-travel");
|
|
9
8
|
const logger = logger_1.defaultLogger.child({ name: 'rpc-dev' });
|
|
10
9
|
const handlers = {
|
|
11
10
|
dev_newBlock: async (context, [param]) => {
|
|
@@ -41,31 +40,6 @@ const handlers = {
|
|
|
41
40
|
await (0, time_travel_1.timeTravel)(context.chain, timestamp);
|
|
42
41
|
return timestamp;
|
|
43
42
|
},
|
|
44
|
-
dev_dryRun: async (context, [{ html, extrinsic, hrmp, raw }]) => {
|
|
45
|
-
const dryRun = async () => {
|
|
46
|
-
if (extrinsic) {
|
|
47
|
-
const { outcome, storageDiff } = await context.chain.dryRunExtrinsic(extrinsic);
|
|
48
|
-
if (outcome.isErr) {
|
|
49
|
-
throw new Error(outcome.asErr.toString());
|
|
50
|
-
}
|
|
51
|
-
return storageDiff;
|
|
52
|
-
}
|
|
53
|
-
return context.chain.dryRunHrmp(hrmp);
|
|
54
|
-
};
|
|
55
|
-
const storageDiff = await dryRun();
|
|
56
|
-
if (html) {
|
|
57
|
-
return (0, generate_html_diff_1.generateHtmlDiff)(context.chain.head, storageDiff);
|
|
58
|
-
}
|
|
59
|
-
if (raw) {
|
|
60
|
-
return storageDiff;
|
|
61
|
-
}
|
|
62
|
-
const [oldData, newData, delta] = await (0, decoder_1.decodeStorageDiff)(context.chain.head, storageDiff);
|
|
63
|
-
return {
|
|
64
|
-
old: oldData,
|
|
65
|
-
new: newData,
|
|
66
|
-
delta,
|
|
67
|
-
};
|
|
68
|
-
},
|
|
69
43
|
dev_setHead: async (context, [hashOrNumber]) => {
|
|
70
44
|
let block;
|
|
71
45
|
if (typeof hashOrNumber === 'number') {
|
|
@@ -81,5 +55,6 @@ const handlers = {
|
|
|
81
55
|
await context.chain.setHead(block);
|
|
82
56
|
return block.hash;
|
|
83
57
|
},
|
|
58
|
+
dev_dryRun: dry_run_1.dev_dryRun,
|
|
84
59
|
};
|
|
85
60
|
exports.default = handlers;
|
package/lib/server.js
CHANGED
|
@@ -51,7 +51,7 @@ const createServer = async (handler, port) => {
|
|
|
51
51
|
let wss;
|
|
52
52
|
let listenPort;
|
|
53
53
|
for (let i = 0; i < 5; i++) {
|
|
54
|
-
const preferPort = (port
|
|
54
|
+
const preferPort = (port ?? 0) > 0 ? (port ?? 0) + i : 0;
|
|
55
55
|
logger.debug('Try starting on port %d', preferPort);
|
|
56
56
|
const [maybeWss, maybeListenPort] = await createWS(preferPort);
|
|
57
57
|
if (maybeWss && maybeListenPort) {
|
package/lib/setup-with-server.js
CHANGED
|
@@ -7,7 +7,7 @@ const shared_1 = require("./rpc/shared");
|
|
|
7
7
|
const setup_1 = require("./setup");
|
|
8
8
|
const setupWithServer = async (argv) => {
|
|
9
9
|
const context = await (0, setup_1.setup)(argv);
|
|
10
|
-
const port = argv.port
|
|
10
|
+
const port = argv.port ?? 8000;
|
|
11
11
|
if (argv.genesis) {
|
|
12
12
|
// mine 1st block when starting from genesis to set some mock validation data
|
|
13
13
|
await context.chain.newBlock();
|
package/lib/utils/time-travel.js
CHANGED
|
@@ -7,9 +7,10 @@ const executor_1 = require("../executor");
|
|
|
7
7
|
const set_storage_1 = require("./set-storage");
|
|
8
8
|
const getCurrentSlot = async (chain) => {
|
|
9
9
|
const meta = await chain.head.meta;
|
|
10
|
+
// use raw key here because some chain did not expose those storage to metadata
|
|
10
11
|
const slotRaw = meta.consts.babe
|
|
11
|
-
? await chain.head.get(
|
|
12
|
-
: await chain.head.get(
|
|
12
|
+
? await chain.head.get('0x1cb6f36e027abb2091cfb5110ab5087f06155b3cd9a8c9e5e9a23fd5dc13a5ed') // babe.currentSlot
|
|
13
|
+
: await chain.head.get('0x57f8dc2f5ab09467896f47300f04243806155b3cd9a8c9e5e9a23fd5dc13a5ed'); // aura.currentSlot
|
|
13
14
|
if (!slotRaw)
|
|
14
15
|
throw new Error('Cannot find current slot');
|
|
15
16
|
return meta.registry.createType('Slot', (0, util_1.hexToU8a)(slotRaw)).toNumber();
|
package/lib/xcm/downward.js
CHANGED
|
@@ -13,7 +13,7 @@ const connectDownward = async (relaychain, parachain) => {
|
|
|
13
13
|
const value = pairs[0][1];
|
|
14
14
|
if (!value)
|
|
15
15
|
return;
|
|
16
|
-
const meta = await
|
|
16
|
+
const meta = await head.meta;
|
|
17
17
|
const downwardMessageQueuesKey = (0, utils_1.compactHex)(meta.query.dmp.downwardMessageQueues(paraId));
|
|
18
18
|
// clear relaychain message queue
|
|
19
19
|
await (0, set_storage_1.setStorage)(relaychain, [[downwardMessageQueuesKey, null]], head.hash);
|
package/lib/xcm/horizontal.js
CHANGED
|
@@ -4,7 +4,6 @@ exports.connectHorizontal = void 0;
|
|
|
4
4
|
const util_1 = require("@polkadot/util");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
6
|
const _1 = require(".");
|
|
7
|
-
const set_storage_1 = require("../utils/set-storage");
|
|
8
7
|
const connectHorizontal = async (parachains) => {
|
|
9
8
|
for (const [id, chain] of Object.entries(parachains)) {
|
|
10
9
|
const meta = await chain.head.meta;
|
|
@@ -13,17 +12,14 @@ const connectHorizontal = async (parachains) => {
|
|
|
13
12
|
const value = pairs[0][1];
|
|
14
13
|
if (!value)
|
|
15
14
|
return;
|
|
16
|
-
const meta = await
|
|
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);
|
|
15
|
+
const meta = await head.meta;
|
|
20
16
|
const outboundHrmpMessage = meta.registry
|
|
21
17
|
.createType('Vec<PolkadotCorePrimitivesOutboundHrmpMessage>', (0, util_1.hexToU8a)(value))
|
|
22
18
|
.toJSON();
|
|
23
19
|
_1.logger.info({ outboundHrmpMessage }, 'outboundHrmpMessage');
|
|
24
20
|
for (const { recipient, data } of outboundHrmpMessage) {
|
|
25
21
|
const horizontalMessages = {
|
|
26
|
-
[Number(id)]: [{ sentAt:
|
|
22
|
+
[Number(id)]: [{ sentAt: head.number, data }],
|
|
27
23
|
};
|
|
28
24
|
const receiver = parachains[recipient];
|
|
29
25
|
if (receiver) {
|
package/lib/xcm/upward.js
CHANGED
|
@@ -4,34 +4,29 @@ exports.connectUpward = void 0;
|
|
|
4
4
|
const util_1 = require("@polkadot/util");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
6
|
const _1 = require(".");
|
|
7
|
-
const set_storage_1 = require("../utils/set-storage");
|
|
8
7
|
const connectUpward = async (parachain, relaychain) => {
|
|
9
8
|
const meta = await parachain.head.meta;
|
|
10
9
|
const paraId = await (0, utils_1.getParaId)(parachain);
|
|
11
10
|
const upwardMessagesKey = (0, utils_1.compactHex)(meta.query.parachainSystem.upwardMessages());
|
|
12
|
-
await parachain.headState.subscribeStorage([upwardMessagesKey], async (
|
|
11
|
+
await parachain.headState.subscribeStorage([upwardMessagesKey], async (_head, pairs) => {
|
|
13
12
|
const value = pairs[0][1];
|
|
14
13
|
if (!value)
|
|
15
14
|
return;
|
|
16
|
-
const
|
|
17
|
-
const
|
|
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));
|
|
15
|
+
const meta = await relaychain.head.meta;
|
|
16
|
+
const upwardMessages = meta.registry.createType('Vec<Bytes>', (0, util_1.hexToU8a)(value));
|
|
22
17
|
if (upwardMessages.length === 0)
|
|
23
18
|
return;
|
|
24
|
-
const queueSize =
|
|
19
|
+
const queueSize = meta.registry.createType('(u32, u32)', [
|
|
25
20
|
upwardMessages.length,
|
|
26
21
|
upwardMessages.map((x) => x.byteLength).reduce((s, i) => s + i, 0),
|
|
27
22
|
]);
|
|
28
|
-
const needsDispatch =
|
|
23
|
+
const needsDispatch = meta.registry.createType('Vec<u32>', [paraId]);
|
|
29
24
|
_1.logger.debug({ [paraId.toNumber()]: upwardMessages.toJSON(), queueSize: queueSize.toJSON() }, 'upward_message');
|
|
30
25
|
// TODO: make sure we append instead of replace
|
|
31
26
|
relaychain.head.pushStorageLayer().setAll([
|
|
32
|
-
[(0, utils_1.compactHex)(
|
|
33
|
-
[(0, utils_1.compactHex)(
|
|
34
|
-
[(0, utils_1.compactHex)(
|
|
27
|
+
[(0, utils_1.compactHex)(meta.query.ump.needsDispatch()), needsDispatch.toHex()],
|
|
28
|
+
[(0, utils_1.compactHex)(meta.query.ump.relayDispatchQueues(paraId)), upwardMessages.toHex()],
|
|
29
|
+
[(0, utils_1.compactHex)(meta.query.ump.relayDispatchQueueSize(paraId)), queueSize.toHex()],
|
|
35
30
|
]);
|
|
36
31
|
await relaychain.newBlock();
|
|
37
32
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acala-network/chopsticks",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"main": "./lib/index.js",
|
|
5
5
|
"types": "./lib/index.d.ts",
|
|
6
6
|
"author": "Bryan Chen <xlchen1291@gmail.com>",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"build": "rm -rf lib && tsc -p ./tsconfig.json",
|
|
13
13
|
"test": "vitest run",
|
|
14
14
|
"test:watch": "vitest",
|
|
15
|
-
"script:start": "cd ../..; ts-node packages/chopsticks/src/cli.ts",
|
|
15
|
+
"script:start": "cd ../..; ts-node --transpile-only packages/chopsticks/src/cli.ts",
|
|
16
16
|
"script:run": "LOG_LEVEL=trace ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config=../../configs/dev.yml",
|
|
17
17
|
"dev:karura": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config=../../configs/karura.yml",
|
|
18
18
|
"dev:acala": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config=../../configs/acala.yml",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"dev:moonbeam": "ts-node-dev --transpile-only --inspect --notify=false src/cli.ts -- dev --config=../../configs/moonbeam.yml"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@acala-network/chopsticks-executor": "0.4.
|
|
23
|
+
"@acala-network/chopsticks-executor": "0.4.2",
|
|
24
24
|
"@polkadot/api": "^9.14.2",
|
|
25
25
|
"@polkadot/rpc-provider": "^9.14.2",
|
|
26
26
|
"@polkadot/types": "^9.14.2",
|
|
@@ -32,9 +32,10 @@
|
|
|
32
32
|
"js-yaml": "^4.1.0",
|
|
33
33
|
"jsondiffpatch": "^0.4.1",
|
|
34
34
|
"lodash": "^4.17.21",
|
|
35
|
-
"pino": "^8.
|
|
36
|
-
"pino-pretty": "^9.
|
|
35
|
+
"pino": "^8.11.0",
|
|
36
|
+
"pino-pretty": "^9.4.0",
|
|
37
37
|
"reflect-metadata": "^0.1.13",
|
|
38
|
+
"rxjs": "^7.8.0",
|
|
38
39
|
"sqlite3": "^5.1.4",
|
|
39
40
|
"typeorm": "^0.3.12",
|
|
40
41
|
"ws": "^8.12.1",
|
|
@@ -44,11 +45,11 @@
|
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@types/js-yaml": "^4.0.5",
|
|
46
47
|
"@types/lodash": "^4.14.191",
|
|
47
|
-
"@types/node": "^18.14.
|
|
48
|
+
"@types/node": "^18.14.2",
|
|
48
49
|
"@types/prettier": "^2.7.2",
|
|
49
50
|
"@types/ws": "^8.5.4",
|
|
50
51
|
"@types/yargs": "^17.0.22",
|
|
51
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
52
|
+
"@typescript-eslint/eslint-plugin": "^5.54.0",
|
|
52
53
|
"@typescript-eslint/parser": "^5.53.0",
|
|
53
54
|
"eslint": "^8.34.0",
|
|
54
55
|
"eslint-config-prettier": "^8.6.0",
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
"ts-node": "^10.9.1",
|
|
59
60
|
"ts-node-dev": "^2.0.0",
|
|
60
61
|
"typescript": "^4.9.5",
|
|
61
|
-
"vitest": "^0.
|
|
62
|
+
"vitest": "^0.29.2"
|
|
62
63
|
},
|
|
63
64
|
"files": [
|
|
64
65
|
"lib",
|
package/template/diff.html
CHANGED
|
@@ -147,10 +147,10 @@
|
|
|
147
147
|
|
|
148
148
|
function renderDelta(value) {
|
|
149
149
|
if (/^\d+(,\d+)*$/.test(value[0]) && /^\d+(,\d+)*$/.test(value[1])) {
|
|
150
|
-
const oldValue =
|
|
151
|
-
const newValue =
|
|
150
|
+
const oldValue = BigInt(value[0].replace(/,/g, ''))
|
|
151
|
+
const newValue = BigInt(value[1].replace(/,/g, ''))
|
|
152
152
|
if (oldValue > 0 && newValue > 0) {
|
|
153
|
-
const delta =
|
|
153
|
+
const delta = newValue - oldValue
|
|
154
154
|
return (<span className="delta" >{delta > 0 ? '+' : ''}{delta.toLocaleString()}</span>)
|
|
155
155
|
}
|
|
156
156
|
}
|