@acala-network/chopsticks 0.2.3 → 0.3.1
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 +12 -1
- package/dist/api.d.ts +3 -2
- package/dist/api.js +15 -20
- package/dist/blockchain/block-builder.d.ts +5 -0
- package/dist/blockchain/block-builder.js +168 -0
- package/dist/blockchain/block.d.ts +6 -4
- package/dist/blockchain/block.js +22 -23
- package/dist/blockchain/head-state.d.ts +4 -2
- package/dist/blockchain/head-state.js +13 -7
- package/dist/blockchain/index.d.ts +13 -8
- package/dist/blockchain/index.js +44 -26
- package/dist/blockchain/inherent/index.d.ts +19 -0
- package/dist/blockchain/inherent/index.js +36 -0
- package/dist/blockchain/inherent/para-enter.d.ts +7 -0
- package/dist/blockchain/inherent/para-enter.js +33 -0
- 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/inherent/parachain/validation-data.d.ts +25 -0
- package/dist/blockchain/{inherents.js → inherent/parachain/validation-data.js} +77 -46
- package/dist/blockchain/txpool.d.ts +17 -2
- package/dist/blockchain/txpool.js +11 -107
- package/dist/dry-run.d.ts +2 -0
- package/dist/dry-run.js +30 -0
- package/dist/executor.d.ts +17 -3
- package/dist/executor.js +43 -3
- package/dist/executor.test.js +16 -9
- package/dist/genesis-provider.d.ts +5 -0
- package/dist/genesis-provider.js +15 -3
- package/dist/index.d.ts +1 -18
- package/dist/index.js +79 -148
- package/dist/rpc/dev.js +39 -2
- package/dist/rpc/shared.d.ts +0 -4
- package/dist/rpc/substrate/author.d.ts +1 -1
- package/dist/rpc/substrate/author.js +7 -2
- package/dist/rpc/substrate/chain.js +2 -2
- package/dist/rpc/substrate/state.js +1 -1
- package/dist/rpc/substrate/system.js +3 -3
- package/dist/run-block.d.ts +2 -0
- package/dist/run-block.js +47 -0
- package/dist/schema/index.js +1 -1
- package/dist/server.d.ts +3 -3
- package/dist/server.js +26 -11
- package/dist/setup-with-server.d.ts +8 -0
- package/dist/setup-with-server.js +23 -0
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +67 -0
- package/dist/utils/decoder.d.ts +17 -0
- package/dist/utils/decoder.js +101 -0
- package/dist/utils/generate-html-diff.d.ts +4 -0
- package/dist/utils/generate-html-diff.js +20 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +9 -1
- package/dist/utils/open-html.d.ts +1 -0
- package/dist/utils/open-html.js +9 -0
- package/dist/utils/proof.d.ts +10 -2
- package/dist/utils/proof.js +12 -8
- package/dist/utils/set-storage.d.ts +2 -1
- package/dist/utils/time-travel.d.ts +5 -0
- package/dist/utils/time-travel.js +64 -0
- package/dist/xcm/index.d.ts +3 -0
- package/dist/xcm/index.js +67 -0
- package/package.json +10 -7
- package/dist/bindings.d.ts +0 -2
- package/dist/bindings.js +0 -31
- package/dist/blockchain/inherents.d.ts +0 -24
package/dist/server.js
CHANGED
|
@@ -35,19 +35,34 @@ const parseRequest = (request) => {
|
|
|
35
35
|
return undefined;
|
|
36
36
|
}
|
|
37
37
|
};
|
|
38
|
-
const
|
|
39
|
-
logger.debug('Starting on port %d', port);
|
|
38
|
+
const createWS = async (port) => {
|
|
40
39
|
const wss = new ws_1.WebSocketServer({ port, maxPayload: 1024 * 1024 * 100 });
|
|
41
|
-
const promise = new Promise((resolve
|
|
40
|
+
const promise = new Promise((resolve) => {
|
|
42
41
|
wss.on('listening', () => {
|
|
43
|
-
|
|
44
|
-
resolve(wss.address().port);
|
|
42
|
+
resolve([wss, wss.address().port]);
|
|
45
43
|
});
|
|
46
|
-
wss.on('error', (
|
|
47
|
-
|
|
48
|
-
reject(err);
|
|
44
|
+
wss.on('error', (_) => {
|
|
45
|
+
resolve([]);
|
|
49
46
|
});
|
|
50
47
|
});
|
|
48
|
+
return promise;
|
|
49
|
+
};
|
|
50
|
+
const createServer = async (handler, port) => {
|
|
51
|
+
let wss;
|
|
52
|
+
let listenPort;
|
|
53
|
+
for (let i = 0; i < 5; i++) {
|
|
54
|
+
const preferPort = (port || 0) + i;
|
|
55
|
+
logger.debug('Try starting on port %d', preferPort);
|
|
56
|
+
const [maybeWss, maybeListenPort] = await createWS(preferPort);
|
|
57
|
+
if (maybeWss && maybeListenPort) {
|
|
58
|
+
wss = maybeWss;
|
|
59
|
+
listenPort = maybeListenPort;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (!wss || !listenPort) {
|
|
64
|
+
throw new Error(`Failed to create WebsocketServer at port ${port}`);
|
|
65
|
+
}
|
|
51
66
|
wss.on('connection', (ws) => {
|
|
52
67
|
logger.debug('New connection');
|
|
53
68
|
const send = (data) => {
|
|
@@ -131,10 +146,10 @@ const createServer = (port, handler) => {
|
|
|
131
146
|
});
|
|
132
147
|
});
|
|
133
148
|
return {
|
|
134
|
-
port:
|
|
149
|
+
port: listenPort,
|
|
135
150
|
close: () => new Promise((resolve, reject) => {
|
|
136
|
-
wss
|
|
137
|
-
wss
|
|
151
|
+
wss?.clients.forEach((socket) => socket.close());
|
|
152
|
+
wss?.close((err) => {
|
|
138
153
|
if (err) {
|
|
139
154
|
reject(err);
|
|
140
155
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Config } from './schema';
|
|
2
|
+
export declare const setupWithServer: (argv: Config) => Promise<{
|
|
3
|
+
close: () => Promise<void>;
|
|
4
|
+
listenPort: number;
|
|
5
|
+
chain: import("./blockchain").Blockchain;
|
|
6
|
+
api: import("./api").Api;
|
|
7
|
+
ws: import("@polkadot/rpc-provider/types").ProviderInterface;
|
|
8
|
+
}>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setupWithServer = void 0;
|
|
4
|
+
const server_1 = require("./server");
|
|
5
|
+
const rpc_1 = require("./rpc");
|
|
6
|
+
const shared_1 = require("./rpc/shared");
|
|
7
|
+
const setup_1 = require("./setup");
|
|
8
|
+
const setupWithServer = async (argv) => {
|
|
9
|
+
const context = await (0, setup_1.setup)(argv);
|
|
10
|
+
const port = argv.port || Number(process.env.PORT) || 8000;
|
|
11
|
+
if (argv.genesis) {
|
|
12
|
+
// mine 1st block when starting from genesis to set some mock validation data
|
|
13
|
+
await context.chain.newBlock();
|
|
14
|
+
}
|
|
15
|
+
const { close, port: listenPort } = await (0, server_1.createServer)((0, rpc_1.handler)(context), port);
|
|
16
|
+
shared_1.logger.info(`${await context.chain.api.getSystemChain()} RPC listening on port ${listenPort}`);
|
|
17
|
+
return {
|
|
18
|
+
...context,
|
|
19
|
+
close,
|
|
20
|
+
listenPort,
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
exports.setupWithServer = setupWithServer;
|
package/dist/setup.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import '@polkadot/types-codec';
|
|
2
|
+
import { ProviderInterface } from '@polkadot/rpc-provider/types';
|
|
3
|
+
import { Api } from './api';
|
|
4
|
+
import { Blockchain } from './blockchain';
|
|
5
|
+
import { Config } from './schema';
|
|
6
|
+
export declare const setup: (argv: Config) => Promise<{
|
|
7
|
+
chain: Blockchain;
|
|
8
|
+
api: Api;
|
|
9
|
+
ws: ProviderInterface;
|
|
10
|
+
}>;
|
package/dist/setup.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.setup = void 0;
|
|
4
|
+
require("@polkadot/types-codec");
|
|
5
|
+
const api_1 = require("@polkadot/api");
|
|
6
|
+
const api_2 = require("./api");
|
|
7
|
+
const blockchain_1 = require("./blockchain");
|
|
8
|
+
const genesis_provider_1 = require("./genesis-provider");
|
|
9
|
+
const inherent_1 = require("./blockchain/inherent");
|
|
10
|
+
const logger_1 = require("./logger");
|
|
11
|
+
const import_storage_1 = require("./utils/import-storage");
|
|
12
|
+
const db_1 = require("./db");
|
|
13
|
+
const time_travel_1 = require("./utils/time-travel");
|
|
14
|
+
const setup = async (argv) => {
|
|
15
|
+
let provider;
|
|
16
|
+
if (argv.genesis) {
|
|
17
|
+
if (typeof argv.genesis === 'string') {
|
|
18
|
+
provider = await genesis_provider_1.GenesisProvider.fromUrl(argv.genesis);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
provider = new genesis_provider_1.GenesisProvider(argv.genesis);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
provider = new api_1.WsProvider(argv.endpoint);
|
|
26
|
+
}
|
|
27
|
+
const api = new api_2.Api(provider);
|
|
28
|
+
await api.isReady;
|
|
29
|
+
let blockHash;
|
|
30
|
+
if (argv.block == null) {
|
|
31
|
+
blockHash = await api.getBlockHash();
|
|
32
|
+
}
|
|
33
|
+
else if (Number.isInteger(+argv.block)) {
|
|
34
|
+
blockHash = await api.getBlockHash(Number(argv.block));
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
blockHash = argv.block;
|
|
38
|
+
}
|
|
39
|
+
logger_1.defaultLogger.debug({ ...argv, blockHash }, 'Args');
|
|
40
|
+
let db;
|
|
41
|
+
if (argv.db) {
|
|
42
|
+
db = await (0, db_1.openDb)(argv.db);
|
|
43
|
+
}
|
|
44
|
+
const header = await api.getHeader(blockHash);
|
|
45
|
+
const inherents = new inherent_1.InherentProviders(new inherent_1.SetTimestamp(), [
|
|
46
|
+
new inherent_1.SetValidationData(),
|
|
47
|
+
new inherent_1.ParaInherentEnter(),
|
|
48
|
+
new inherent_1.SetNimbusAuthorInherent(),
|
|
49
|
+
new inherent_1.SetBabeRandomness(),
|
|
50
|
+
]);
|
|
51
|
+
const chain = new blockchain_1.Blockchain({
|
|
52
|
+
api,
|
|
53
|
+
buildBlockMode: argv['build-block-mode'],
|
|
54
|
+
inherentProvider: inherents,
|
|
55
|
+
db,
|
|
56
|
+
header: {
|
|
57
|
+
hash: blockHash,
|
|
58
|
+
number: Number(header.number),
|
|
59
|
+
},
|
|
60
|
+
});
|
|
61
|
+
if (argv.timestamp)
|
|
62
|
+
await (0, time_travel_1.timeTravel)(chain, argv.timestamp);
|
|
63
|
+
await (0, import_storage_1.importStorage)(chain, argv['import-storage']);
|
|
64
|
+
await (0, import_storage_1.overrideWasm)(chain, argv['wasm-override']);
|
|
65
|
+
return { chain, api, ws: provider };
|
|
66
|
+
};
|
|
67
|
+
exports.setup = setup;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import '@polkadot/types-codec';
|
|
2
|
+
import { Block } from '../blockchain/block';
|
|
3
|
+
import { HexString } from '@polkadot/util/types';
|
|
4
|
+
import { StorageEntry } from '@polkadot/types/primitive/types';
|
|
5
|
+
import { StorageKey } from '@polkadot/types';
|
|
6
|
+
export declare const decodeKey: (block: Block, key: HexString) => Promise<{
|
|
7
|
+
storage?: StorageEntry | undefined;
|
|
8
|
+
decodedKey?: StorageKey<import("@polkadot/types-codec/types").AnyTuple> | undefined;
|
|
9
|
+
}>;
|
|
10
|
+
export declare const decodeKeyValue: (block: Block, key: HexString, value?: HexString | null) => Promise<{
|
|
11
|
+
[x: string]: `0x${string}` | null | undefined;
|
|
12
|
+
} | {
|
|
13
|
+
[x: string]: {
|
|
14
|
+
[x: string]: import("@polkadot/types-codec/types").AnyJson;
|
|
15
|
+
};
|
|
16
|
+
}>;
|
|
17
|
+
export declare const decodeStorageDiff: (block: Block, diff: [HexString, HexString | null][]) => Promise<({} | undefined)[]>;
|
|
@@ -0,0 +1,101 @@
|
|
|
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.decodeStorageDiff = exports.decodeKeyValue = exports.decodeKey = void 0;
|
|
7
|
+
require("@polkadot/types-codec");
|
|
8
|
+
const util_crypto_1 = require("@polkadot/util-crypto");
|
|
9
|
+
const jsondiffpatch_1 = require("jsondiffpatch");
|
|
10
|
+
const util_1 = require("@polkadot/util");
|
|
11
|
+
const lodash_1 = __importDefault(require("lodash"));
|
|
12
|
+
const diffPatcher = (0, jsondiffpatch_1.create)({
|
|
13
|
+
array: { detectMove: false },
|
|
14
|
+
textDiff: { minLength: Number.MAX_VALUE }, // skip text diff
|
|
15
|
+
});
|
|
16
|
+
const cache = {};
|
|
17
|
+
const getStorageEntry = async (block, key) => {
|
|
18
|
+
for (const [prefix, storageEntry] of Object.entries(cache)) {
|
|
19
|
+
if (key.startsWith(prefix))
|
|
20
|
+
return storageEntry;
|
|
21
|
+
}
|
|
22
|
+
const meta = await block.meta;
|
|
23
|
+
for (const module of Object.values(meta.query)) {
|
|
24
|
+
for (const storage of Object.values(module)) {
|
|
25
|
+
const keyPrefix = (0, util_1.u8aToHex)(storage.keyPrefix());
|
|
26
|
+
if (key.startsWith(keyPrefix)) {
|
|
27
|
+
cache[keyPrefix] = storage;
|
|
28
|
+
return storage;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
throw new Error(`Cannot find key ${key}`);
|
|
33
|
+
};
|
|
34
|
+
const decodeKey = async (block, key) => {
|
|
35
|
+
const meta = await block.meta;
|
|
36
|
+
const storage = await getStorageEntry(block, key).catch(() => undefined);
|
|
37
|
+
const decodedKey = meta.registry.createType('StorageKey', key);
|
|
38
|
+
if (storage) {
|
|
39
|
+
decodedKey.setMeta(storage.meta);
|
|
40
|
+
return { storage, decodedKey };
|
|
41
|
+
}
|
|
42
|
+
return {};
|
|
43
|
+
};
|
|
44
|
+
exports.decodeKey = decodeKey;
|
|
45
|
+
const decodeKeyValue = async (block, key, value) => {
|
|
46
|
+
const meta = await block.meta;
|
|
47
|
+
const { storage, decodedKey } = await (0, exports.decodeKey)(block, key);
|
|
48
|
+
if (!storage || !decodedKey) {
|
|
49
|
+
return { [key]: value };
|
|
50
|
+
}
|
|
51
|
+
const decodeValue = () => {
|
|
52
|
+
if (!value)
|
|
53
|
+
return null;
|
|
54
|
+
if (storage.section === 'substrate' && storage.method === 'code') {
|
|
55
|
+
return `:code blake2_256 ${(0, util_crypto_1.blake2AsHex)(value, 256)} (${(0, util_1.hexToU8a)(value).length} bytes)`;
|
|
56
|
+
}
|
|
57
|
+
return meta.registry.createType(decodedKey.outputType, (0, util_1.hexToU8a)(value)).toHuman();
|
|
58
|
+
};
|
|
59
|
+
switch (decodedKey.args.length) {
|
|
60
|
+
case 2: {
|
|
61
|
+
return {
|
|
62
|
+
[storage.section]: {
|
|
63
|
+
[storage.method]: {
|
|
64
|
+
[decodedKey.args[0].toString()]: {
|
|
65
|
+
[decodedKey.args[1].toString()]: decodeValue(),
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
case 1: {
|
|
72
|
+
return {
|
|
73
|
+
[storage.section]: {
|
|
74
|
+
[storage.method]: {
|
|
75
|
+
[decodedKey.args[0].toString()]: decodeValue(),
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
default:
|
|
81
|
+
return {
|
|
82
|
+
[storage.section]: {
|
|
83
|
+
[storage.method]: decodeValue(),
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
exports.decodeKeyValue = decodeKeyValue;
|
|
89
|
+
const decodeStorageDiff = async (block, diff) => {
|
|
90
|
+
const parent = await block.parentBlock;
|
|
91
|
+
if (!parent)
|
|
92
|
+
throw new Error('Cannot find parent block');
|
|
93
|
+
const oldState = {};
|
|
94
|
+
const newState = {};
|
|
95
|
+
for (const [key, value] of diff) {
|
|
96
|
+
lodash_1.default.merge(oldState, await (0, exports.decodeKeyValue)(parent, key, (await parent.get(key))));
|
|
97
|
+
lodash_1.default.merge(newState, await (0, exports.decodeKeyValue)(block, key, value));
|
|
98
|
+
}
|
|
99
|
+
return [oldState, newState, diffPatcher.diff(oldState, newState)];
|
|
100
|
+
};
|
|
101
|
+
exports.decodeStorageDiff = decodeStorageDiff;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { Block } from '../blockchain/block';
|
|
2
|
+
import { HexString } from '@polkadot/util/types';
|
|
3
|
+
export declare const generateHtmlDiff: (block: Block, diff: [HexString, HexString | null][]) => Promise<string>;
|
|
4
|
+
export declare const generateHtmlDiffPreviewFile: (block: Block, diff: [HexString, HexString | null][], filename: string) => Promise<string>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateHtmlDiffPreviewFile = exports.generateHtmlDiff = void 0;
|
|
4
|
+
const decoder_1 = require("./decoder");
|
|
5
|
+
const node_fs_1 = require("node:fs");
|
|
6
|
+
const lodash_1 = require("lodash");
|
|
7
|
+
const generateHtmlDiff = async (block, diff) => {
|
|
8
|
+
const [left, _right, delta] = await (0, decoder_1.decodeStorageDiff)(block, diff);
|
|
9
|
+
const htmlTemplate = (0, node_fs_1.readFileSync)('./template/diff.html', 'utf-8');
|
|
10
|
+
return (0, lodash_1.template)(htmlTemplate)({ left: JSON.stringify(left), delta: JSON.stringify(delta) });
|
|
11
|
+
};
|
|
12
|
+
exports.generateHtmlDiff = generateHtmlDiff;
|
|
13
|
+
const generateHtmlDiffPreviewFile = async (block, diff, filename) => {
|
|
14
|
+
const html = await (0, exports.generateHtmlDiff)(block, diff);
|
|
15
|
+
(0, node_fs_1.mkdirSync)('./preview', { recursive: true });
|
|
16
|
+
const filePath = `./preview/${filename}.html`;
|
|
17
|
+
(0, node_fs_1.writeFileSync)(filePath, html);
|
|
18
|
+
return filePath;
|
|
19
|
+
};
|
|
20
|
+
exports.generateHtmlDiffPreviewFile = generateHtmlDiffPreviewFile;
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { HexString } from '@polkadot/util/types';
|
|
2
2
|
import { StorageKey } from '@polkadot/types';
|
|
3
|
+
import { Blockchain } from '../blockchain';
|
|
3
4
|
export type GetKeys = (startKey?: string) => Promise<StorageKey<any>[]>;
|
|
4
5
|
export type ProcessKey = (key: StorageKey<any>) => any;
|
|
5
6
|
export declare function fetchKeys(getKeys: GetKeys, processKey: ProcessKey): Promise<void>;
|
|
6
7
|
export declare function fetchKeysToArray(getKeys: GetKeys): Promise<StorageKey<any>[]>;
|
|
7
8
|
export declare const compactHex: (value: Uint8Array) => HexString;
|
|
9
|
+
export declare const getParaId: (chain: Blockchain) => Promise<import("@polkadot/types").u32>;
|
package/dist/utils/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.compactHex = exports.fetchKeysToArray = exports.fetchKeys = void 0;
|
|
3
|
+
exports.getParaId = exports.compactHex = exports.fetchKeysToArray = exports.fetchKeys = void 0;
|
|
4
4
|
const util_1 = require("@polkadot/util");
|
|
5
5
|
async function fetchKeys(getKeys, processKey) {
|
|
6
6
|
const processKeys = async (keys) => {
|
|
@@ -30,3 +30,11 @@ const compactHex = (value) => {
|
|
|
30
30
|
return (0, util_1.u8aToHex)((0, util_1.compactStripLength)(value)[1]);
|
|
31
31
|
};
|
|
32
32
|
exports.compactHex = compactHex;
|
|
33
|
+
const getParaId = async (chain) => {
|
|
34
|
+
const meta = await chain.head.meta;
|
|
35
|
+
const raw = await chain.head.get((0, exports.compactHex)(meta.query.parachainInfo.parachainId()));
|
|
36
|
+
if (!raw)
|
|
37
|
+
throw new Error('Cannot find parachain id');
|
|
38
|
+
return meta.registry.createType('u32', (0, util_1.hexToU8a)(raw));
|
|
39
|
+
};
|
|
40
|
+
exports.getParaId = getParaId;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const openHtml: (filePath: string) => void;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.openHtml = void 0;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
5
|
+
const openHtml = (filePath) => {
|
|
6
|
+
const start = process.platform == 'darwin' ? 'open' : process.platform == 'win32' ? 'start' : 'xdg-open';
|
|
7
|
+
(0, node_child_process_1.execSync)(start + ' ' + filePath);
|
|
8
|
+
};
|
|
9
|
+
exports.openHtml = openHtml;
|
package/dist/utils/proof.d.ts
CHANGED
|
@@ -1,7 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HrmpChannelId } from '@polkadot/types/interfaces';
|
|
2
2
|
import { u32 } from '@polkadot/types';
|
|
3
|
-
export declare const WELL_KNOWN_KEYS:
|
|
3
|
+
export declare const WELL_KNOWN_KEYS: {
|
|
4
|
+
EPOCH_INDEX: `0x${string}`;
|
|
5
|
+
CURRENT_BLOCK_RANDOMNESS: `0x${string}`;
|
|
6
|
+
ONE_EPOCH_AGO_RANDOMNESS: `0x${string}`;
|
|
7
|
+
TWO_EPOCHS_AGO_RANDOMNESS: `0x${string}`;
|
|
8
|
+
CURRENT_SLOT: `0x${string}`;
|
|
9
|
+
ACTIVE_CONFIG: `0x${string}`;
|
|
10
|
+
};
|
|
4
11
|
export declare const dmqMqcHead: (paraId: u32) => `0x${string}`;
|
|
5
12
|
export declare const upgradeGoAheadSignal: (paraId: u32) => `0x${string}`;
|
|
6
13
|
export declare const hrmpIngressChannelIndex: (paraId: u32) => `0x${string}`;
|
|
7
14
|
export declare const hrmpEgressChannelIndex: (paraId: u32) => `0x${string}`;
|
|
15
|
+
export declare const hrmpChannels: (channelId: HrmpChannelId) => `0x${string}`;
|
package/dist/utils/proof.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hrmpEgressChannelIndex = exports.hrmpIngressChannelIndex = exports.upgradeGoAheadSignal = exports.dmqMqcHead = exports.WELL_KNOWN_KEYS = void 0;
|
|
3
|
+
exports.hrmpChannels = exports.hrmpEgressChannelIndex = exports.hrmpIngressChannelIndex = exports.upgradeGoAheadSignal = exports.dmqMqcHead = exports.WELL_KNOWN_KEYS = void 0;
|
|
4
4
|
const util_1 = require("@polkadot/util");
|
|
5
5
|
const util_crypto_1 = require("@polkadot/util-crypto");
|
|
6
6
|
exports.WELL_KNOWN_KEYS = {
|
|
@@ -11,27 +11,31 @@ exports.WELL_KNOWN_KEYS = {
|
|
|
11
11
|
CURRENT_SLOT: '0x1cb6f36e027abb2091cfb5110ab5087f06155b3cd9a8c9e5e9a23fd5dc13a5ed',
|
|
12
12
|
ACTIVE_CONFIG: '0x06de3d8a54d27e44a9d5ce189618f22db4b49d95320d9021994c850f25b8e385',
|
|
13
13
|
};
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
return (0, util_1.u8aToHex)((0, util_1.u8aConcat)((0, util_1.hexToU8a)(prefix), (0, util_crypto_1.xxhashAsU8a)(id, 64), id));
|
|
14
|
+
const hash = (prefix, suffix) => {
|
|
15
|
+
return (0, util_1.u8aToHex)((0, util_1.u8aConcat)((0, util_1.hexToU8a)(prefix), (0, util_crypto_1.xxhashAsU8a)(suffix, 64), suffix));
|
|
17
16
|
};
|
|
18
17
|
const dmqMqcHead = (paraId) => {
|
|
19
18
|
const prefix = '0x63f78c98723ddc9073523ef3beefda0c4d7fefc408aac59dbfe80a72ac8e3ce5';
|
|
20
|
-
return
|
|
19
|
+
return hash(prefix, paraId.toU8a());
|
|
21
20
|
};
|
|
22
21
|
exports.dmqMqcHead = dmqMqcHead;
|
|
23
22
|
const upgradeGoAheadSignal = (paraId) => {
|
|
24
23
|
const prefix = '0xcd710b30bd2eab0352ddcc26417aa1949e94c040f5e73d9b7addd6cb603d15d3';
|
|
25
|
-
return
|
|
24
|
+
return hash(prefix, paraId.toU8a());
|
|
26
25
|
};
|
|
27
26
|
exports.upgradeGoAheadSignal = upgradeGoAheadSignal;
|
|
28
27
|
const hrmpIngressChannelIndex = (paraId) => {
|
|
29
28
|
const prefix = '0x6a0da05ca59913bc38a8630590f2627c1d3719f5b0b12c7105c073c507445948';
|
|
30
|
-
return
|
|
29
|
+
return hash(prefix, paraId.toU8a());
|
|
31
30
|
};
|
|
32
31
|
exports.hrmpIngressChannelIndex = hrmpIngressChannelIndex;
|
|
33
32
|
const hrmpEgressChannelIndex = (paraId) => {
|
|
34
33
|
const prefix = '0x6a0da05ca59913bc38a8630590f2627cf12b746dcf32e843354583c9702cc020';
|
|
35
|
-
return
|
|
34
|
+
return hash(prefix, paraId.toU8a());
|
|
36
35
|
};
|
|
37
36
|
exports.hrmpEgressChannelIndex = hrmpEgressChannelIndex;
|
|
37
|
+
const hrmpChannels = (channelId) => {
|
|
38
|
+
const prefix = '0x6a0da05ca59913bc38a8630590f2627cb6604cff828a6e3f579ca6c59ace013d';
|
|
39
|
+
return hash(prefix, channelId.toU8a());
|
|
40
|
+
};
|
|
41
|
+
exports.hrmpChannels = hrmpChannels;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { HexString } from '@polkadot/util/types';
|
|
1
2
|
import { Blockchain } from '../blockchain';
|
|
2
3
|
type RawStorageValues = [string, string | null][];
|
|
3
4
|
type StorageConfig = Record<string, Record<string, any>>;
|
|
4
5
|
export type StorageValues = RawStorageValues | StorageConfig;
|
|
5
|
-
export declare const setStorage: (chain: Blockchain, storage: StorageValues, blockHash?:
|
|
6
|
+
export declare const setStorage: (chain: Blockchain, storage: StorageValues, blockHash?: HexString) => Promise<HexString>;
|
|
6
7
|
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Blockchain } from '../blockchain';
|
|
2
|
+
export declare const getCurrentSlot: (chain: Blockchain) => Promise<number>;
|
|
3
|
+
export declare const getCurrentTimestamp: (chain: Blockchain) => Promise<number>;
|
|
4
|
+
export declare const getSlotDuration: (chain: Blockchain) => Promise<number>;
|
|
5
|
+
export declare const timeTravel: (chain: Blockchain, timestamp: number) => Promise<void>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.timeTravel = exports.getSlotDuration = exports.getCurrentTimestamp = exports.getCurrentSlot = void 0;
|
|
4
|
+
const util_1 = require("@polkadot/util");
|
|
5
|
+
const _1 = require(".");
|
|
6
|
+
const executor_1 = require("../executor");
|
|
7
|
+
const set_storage_1 = require("./set-storage");
|
|
8
|
+
const getCurrentSlot = async (chain) => {
|
|
9
|
+
const meta = await chain.head.meta;
|
|
10
|
+
const slotRaw = meta.consts.babe
|
|
11
|
+
? await chain.head.get((0, _1.compactHex)(meta.query.babe.currentSlot()))
|
|
12
|
+
: await chain.head.get((0, _1.compactHex)(meta.query.aura.currentSlot()));
|
|
13
|
+
if (!slotRaw)
|
|
14
|
+
throw new Error('Cannot find current slot');
|
|
15
|
+
return meta.registry.createType('Slot', (0, util_1.hexToU8a)(slotRaw)).toNumber();
|
|
16
|
+
};
|
|
17
|
+
exports.getCurrentSlot = getCurrentSlot;
|
|
18
|
+
const getCurrentTimestamp = async (chain) => {
|
|
19
|
+
const meta = await chain.head.meta;
|
|
20
|
+
const currentTimestampRaw = (await chain.head.get((0, _1.compactHex)(meta.query.timestamp.now()))) || '0x';
|
|
21
|
+
return meta.registry.createType('u64', (0, util_1.hexToU8a)(currentTimestampRaw)).toNumber();
|
|
22
|
+
};
|
|
23
|
+
exports.getCurrentTimestamp = getCurrentTimestamp;
|
|
24
|
+
const getSlotDuration = async (chain) => {
|
|
25
|
+
const meta = await chain.head.meta;
|
|
26
|
+
return meta.consts.babe
|
|
27
|
+
? meta.consts.babe.expectedBlockTime.toNumber()
|
|
28
|
+
: meta.query.aura
|
|
29
|
+
? (0, executor_1.getAuraSlotDuration)(await chain.head.wasm, meta.registry)
|
|
30
|
+
: 12_000;
|
|
31
|
+
};
|
|
32
|
+
exports.getSlotDuration = getSlotDuration;
|
|
33
|
+
const timeTravel = async (chain, timestamp) => {
|
|
34
|
+
const meta = await chain.head.meta;
|
|
35
|
+
const slotDuration = await (0, exports.getSlotDuration)(chain);
|
|
36
|
+
const newSlot = Math.floor(timestamp / slotDuration);
|
|
37
|
+
// new timestamp
|
|
38
|
+
const storage = [
|
|
39
|
+
[(0, _1.compactHex)(meta.query.timestamp.now()), (0, util_1.u8aToHex)(meta.registry.createType('u64', timestamp).toU8a())],
|
|
40
|
+
];
|
|
41
|
+
if (meta.consts.babe) {
|
|
42
|
+
// new slot
|
|
43
|
+
storage.push([
|
|
44
|
+
(0, _1.compactHex)(meta.query.babe.currentSlot()),
|
|
45
|
+
(0, util_1.u8aToHex)(meta.registry.createType('Slot', newSlot).toU8a()),
|
|
46
|
+
]);
|
|
47
|
+
// new epoch
|
|
48
|
+
const epochDuration = meta.consts.babe.epochDuration.toNumber();
|
|
49
|
+
const newEpoch = Math.floor(timestamp / epochDuration);
|
|
50
|
+
storage.push([
|
|
51
|
+
(0, _1.compactHex)(meta.query.babe.epochIndex()),
|
|
52
|
+
(0, util_1.u8aToHex)(meta.registry.createType('u64', newEpoch).toU8a()),
|
|
53
|
+
]);
|
|
54
|
+
}
|
|
55
|
+
else if (meta.query.aura) {
|
|
56
|
+
// new slot
|
|
57
|
+
storage.push([
|
|
58
|
+
(0, _1.compactHex)(meta.query.aura.currentSlot()),
|
|
59
|
+
(0, util_1.u8aToHex)(meta.registry.createType('Slot', newSlot).toU8a()),
|
|
60
|
+
]);
|
|
61
|
+
}
|
|
62
|
+
await (0, set_storage_1.setStorage)(chain, storage);
|
|
63
|
+
};
|
|
64
|
+
exports.timeTravel = timeTravel;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.connectParachains = exports.connectDownward = void 0;
|
|
4
|
+
const util_1 = require("@polkadot/util");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
const set_storage_1 = require("../utils/set-storage");
|
|
8
|
+
const logger = logger_1.defaultLogger.child({ name: 'xcm' });
|
|
9
|
+
const connectDownward = async (relaychain, parachain) => {
|
|
10
|
+
const meta = await relaychain.head.meta;
|
|
11
|
+
const paraId = await (0, utils_1.getParaId)(parachain);
|
|
12
|
+
const downwardMessageQueuesKey = (0, utils_1.compactHex)(meta.query.dmp.downwardMessageQueues(paraId));
|
|
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()}'`);
|
|
28
|
+
};
|
|
29
|
+
exports.connectDownward = connectDownward;
|
|
30
|
+
const connectParachains = async (parachains) => {
|
|
31
|
+
const list = {};
|
|
32
|
+
for (const chain of parachains) {
|
|
33
|
+
const paraId = await (0, utils_1.getParaId)(chain);
|
|
34
|
+
list[paraId.toNumber()] = chain;
|
|
35
|
+
}
|
|
36
|
+
await connectHorizontal(list);
|
|
37
|
+
logger.info('Parachains connected');
|
|
38
|
+
};
|
|
39
|
+
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
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acala-network/chopsticks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"author": "Bryan Chen <xlchen1291@gmail.com>",
|
|
@@ -24,10 +24,12 @@
|
|
|
24
24
|
"test:dev": "LOG_LEVEL=trace vitest --inspect",
|
|
25
25
|
"dev": "LOG_LEVEL=trace ts-node-dev --transpile-only --inspect --notify=false src/index.ts -- dev --config=configs/dev.yml",
|
|
26
26
|
"dev:karura": "ts-node-dev --transpile-only --inspect --notify=false src/index.ts -- dev --config=configs/karura.yml",
|
|
27
|
-
"dev:acala": "ts-node-dev --transpile-only --inspect --notify=false src/index.ts -- dev --config=configs/acala.yml"
|
|
27
|
+
"dev:acala": "ts-node-dev --transpile-only --inspect --notify=false src/index.ts -- dev --config=configs/acala.yml",
|
|
28
|
+
"dev:moonriver": "ts-node-dev --transpile-only --inspect --notify=false src/index.ts -- dev --config=configs/moonriver.yml",
|
|
29
|
+
"dev:moonbeam": "ts-node-dev --transpile-only --inspect --notify=false src/index.ts -- dev --config=configs/moonbeam.yml"
|
|
28
30
|
},
|
|
29
31
|
"dependencies": {
|
|
30
|
-
"@acala-network/chopsticks-executor": "0.
|
|
32
|
+
"@acala-network/chopsticks-executor": "0.3.0",
|
|
31
33
|
"@polkadot/api": "^9.10.1",
|
|
32
34
|
"@polkadot/rpc-provider": "^9.10.1",
|
|
33
35
|
"@polkadot/types": "^9.10.1",
|
|
@@ -35,8 +37,9 @@
|
|
|
35
37
|
"@polkadot/types-known": "^9.10.1",
|
|
36
38
|
"@polkadot/util": "^10.2.1",
|
|
37
39
|
"@polkadot/util-crypto": "^10.2.1",
|
|
38
|
-
"axios": "^1.2.
|
|
40
|
+
"axios": "^1.2.2",
|
|
39
41
|
"js-yaml": "^4.1.0",
|
|
42
|
+
"jsondiffpatch": "^0.4.1",
|
|
40
43
|
"lodash": "^4.17.21",
|
|
41
44
|
"pino": "^8.7.0",
|
|
42
45
|
"pino-pretty": "^9.1.1",
|
|
@@ -51,13 +54,13 @@
|
|
|
51
54
|
"devDependencies": {
|
|
52
55
|
"@types/js-yaml": "^4.0.5",
|
|
53
56
|
"@types/lodash": "^4.14.191",
|
|
54
|
-
"@types/node": "^18.11.
|
|
57
|
+
"@types/node": "^18.11.18",
|
|
55
58
|
"@types/rimraf": "^3",
|
|
56
59
|
"@types/ws": "^8.5.3",
|
|
57
|
-
"@types/yargs": "^17.0.
|
|
60
|
+
"@types/yargs": "^17.0.18",
|
|
58
61
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
|
59
62
|
"@typescript-eslint/parser": "^5.45.0",
|
|
60
|
-
"eslint": "^8.
|
|
63
|
+
"eslint": "^8.31.0",
|
|
61
64
|
"eslint-config-prettier": "^8.5.0",
|
|
62
65
|
"eslint-plugin-import": "^2.26.0",
|
|
63
66
|
"eslint-plugin-sort-imports-es6-autofix": "^0.6.0",
|
package/dist/bindings.d.ts
DELETED