@acala-network/chopsticks 0.6.6 → 0.7.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/lib/blockchain/block-builder.js +5 -6
- package/lib/blockchain/block.d.ts +2 -1
- package/lib/blockchain/block.js +7 -2
- package/lib/blockchain/index.d.ts +6 -1
- package/lib/blockchain/index.js +16 -6
- package/lib/blockchain/inherent/parachain/validation-data.js +1 -1
- package/lib/blockchain/txpool.js +1 -1
- package/lib/cli.d.ts +2 -1
- package/lib/cli.js +12 -6
- package/lib/db/entities.js +2 -3
- package/lib/dry-run-preimage.js +0 -1
- package/lib/executor.d.ts +8 -10
- package/lib/executor.js +52 -19
- package/lib/genesis-provider.d.ts +2 -5
- package/lib/genesis-provider.js +5 -5
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -1
- package/lib/logger.js +4 -2
- package/lib/offchain.d.ts +10 -0
- package/lib/offchain.js +37 -0
- package/lib/run-block.js +1 -2
- package/lib/schema/index.d.ts +3 -0
- package/lib/schema/index.js +1 -0
- package/lib/setup.d.ts +1 -0
- package/lib/setup.js +2 -0
- package/lib/try-runtime.js +1 -1
- package/lib/utils/tunnel.d.ts +1 -0
- package/lib/utils/tunnel.js +16 -0
- package/package.json +12 -9
- package/template/diff.html +1 -1
|
@@ -129,6 +129,11 @@ const initNewBlock = async (head, header, inherents, storageLayer) => {
|
|
|
129
129
|
const buildBlock = async (head, inherents, extrinsics, ump, onApplyExtrinsicError) => {
|
|
130
130
|
const registry = await head.registry;
|
|
131
131
|
const header = await (0, exports.newHeader)(head);
|
|
132
|
+
logger.info({
|
|
133
|
+
number: head.number + 1,
|
|
134
|
+
extrinsicsCount: extrinsics.length,
|
|
135
|
+
umpCount: Object.keys(ump).length,
|
|
136
|
+
}, `Try building block #${(head.number + 1).toLocaleString()}`);
|
|
132
137
|
let layer;
|
|
133
138
|
// apply ump via storage override hack
|
|
134
139
|
if (Object.keys(ump).length > 0) {
|
|
@@ -202,12 +207,6 @@ const buildBlock = async (head, inherents, extrinsics, ump, onApplyExtrinsicErro
|
|
|
202
207
|
}
|
|
203
208
|
}
|
|
204
209
|
const { block: newBlock } = await initNewBlock(head, header, inherents, layer);
|
|
205
|
-
logger.info({
|
|
206
|
-
number: newBlock.number,
|
|
207
|
-
extrinsicsCount: extrinsics.length,
|
|
208
|
-
umpCount: Object.keys(ump).length,
|
|
209
|
-
tempHash: newBlock.hash,
|
|
210
|
-
}, `Try building block #${newBlock.number.toLocaleString()}`);
|
|
211
210
|
const pendingExtrinsics = [];
|
|
212
211
|
const includedExtrinsic = [];
|
|
213
212
|
// apply extrinsics
|
|
@@ -8,6 +8,7 @@ import type { RuntimeVersion } from '../executor';
|
|
|
8
8
|
export type TaskCallResponse = {
|
|
9
9
|
result: HexString;
|
|
10
10
|
storageDiff: [HexString, HexString | null][];
|
|
11
|
+
offchainStorageDiff: [HexString, HexString | null][];
|
|
11
12
|
runtimeLogs: string[];
|
|
12
13
|
};
|
|
13
14
|
export declare class Block {
|
|
@@ -40,5 +41,5 @@ export declare class Block {
|
|
|
40
41
|
get runtimeVersion(): Promise<RuntimeVersion>;
|
|
41
42
|
get metadata(): Promise<HexString>;
|
|
42
43
|
get meta(): Promise<DecoratedMeta>;
|
|
43
|
-
call(method: string, args: HexString[]
|
|
44
|
+
call(method: string, args: HexString[]): Promise<TaskCallResponse>;
|
|
44
45
|
}
|
package/lib/blockchain/block.js
CHANGED
|
@@ -165,12 +165,11 @@ class Block {
|
|
|
165
165
|
}
|
|
166
166
|
return this.#meta;
|
|
167
167
|
}
|
|
168
|
-
async call(method, args
|
|
168
|
+
async call(method, args) {
|
|
169
169
|
const wasm = await this.wasm;
|
|
170
170
|
const response = await (0, executor_1.runTask)({
|
|
171
171
|
wasm,
|
|
172
172
|
calls: [[method, args]],
|
|
173
|
-
storage,
|
|
174
173
|
mockSignatureHost: this.#chain.mockSignatureHost,
|
|
175
174
|
allowUnresolvedImports: this.#chain.allowUnresolvedImports,
|
|
176
175
|
runtimeLogLevel: this.#chain.runtimeLogLevel,
|
|
@@ -179,6 +178,12 @@ class Block {
|
|
|
179
178
|
for (const log of response.Call.runtimeLogs) {
|
|
180
179
|
logger_1.defaultLogger.info(`RuntimeLogs:\n${log}`);
|
|
181
180
|
}
|
|
181
|
+
if (this.chain.offchainWorker) {
|
|
182
|
+
// apply offchain storage
|
|
183
|
+
for (const [key, value] of response.Call.offchainStorageDiff) {
|
|
184
|
+
this.chain.offchainWorker.set(key, value);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
182
187
|
return response.Call;
|
|
183
188
|
}
|
|
184
189
|
if (response.Error)
|
|
@@ -2,11 +2,13 @@ import { ApplyExtrinsicResult } from '@polkadot/types/interfaces';
|
|
|
2
2
|
import { DataSource } from 'typeorm';
|
|
3
3
|
import { HexString } from '@polkadot/util/types';
|
|
4
4
|
import { RegisteredTypes } from '@polkadot/types/types';
|
|
5
|
+
import type { TransactionValidity } from '@polkadot/types/interfaces/txqueue';
|
|
5
6
|
import { Api } from '../api';
|
|
6
7
|
import { Block } from './block';
|
|
7
8
|
import { BuildBlockMode, BuildBlockParams, DownwardMessage, HorizontalMessage, TxPool } from './txpool';
|
|
8
9
|
import { HeadState } from './head-state';
|
|
9
10
|
import { InherentProvider } from './inherent';
|
|
11
|
+
import { OffchainWorker } from '../offchain';
|
|
10
12
|
export interface Options {
|
|
11
13
|
api: Api;
|
|
12
14
|
buildBlockMode?: BuildBlockMode;
|
|
@@ -20,6 +22,7 @@ export interface Options {
|
|
|
20
22
|
allowUnresolvedImports?: boolean;
|
|
21
23
|
runtimeLogLevel?: number;
|
|
22
24
|
registeredTypes: RegisteredTypes;
|
|
25
|
+
offchainWorker?: boolean;
|
|
23
26
|
}
|
|
24
27
|
export declare class Blockchain {
|
|
25
28
|
#private;
|
|
@@ -31,7 +34,8 @@ export declare class Blockchain {
|
|
|
31
34
|
readonly runtimeLogLevel: number;
|
|
32
35
|
readonly registeredTypes: RegisteredTypes;
|
|
33
36
|
readonly headState: HeadState;
|
|
34
|
-
|
|
37
|
+
readonly offchainWorker: OffchainWorker | undefined;
|
|
38
|
+
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost, allowUnresolvedImports, runtimeLogLevel, registeredTypes, offchainWorker, }: Options);
|
|
35
39
|
get head(): Block;
|
|
36
40
|
get txPool(): TxPool;
|
|
37
41
|
getBlockAt(number?: number): Promise<Block | undefined>;
|
|
@@ -39,6 +43,7 @@ export declare class Blockchain {
|
|
|
39
43
|
unregisterBlock(block: Block): void;
|
|
40
44
|
setHead(block: Block): Promise<void>;
|
|
41
45
|
submitExtrinsic(extrinsic: HexString): Promise<HexString>;
|
|
46
|
+
validateExtrinsic(extrinsic: HexString, source?: '0x00' | '0x01' | '0x02' /** External */): Promise<TransactionValidity>;
|
|
42
47
|
submitUpwardMessages(id: number, ump: HexString[]): void;
|
|
43
48
|
submitDownwardMessages(dmp: DownwardMessage[]): void;
|
|
44
49
|
submitHorizontalMessages(id: number, hrmp: HorizontalMessage[]): void;
|
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 offchain_1 = require("../offchain");
|
|
9
10
|
const utils_1 = require("../utils");
|
|
10
11
|
const logger_1 = require("../logger");
|
|
11
12
|
const block_builder_1 = require("./block-builder");
|
|
@@ -25,7 +26,8 @@ class Blockchain {
|
|
|
25
26
|
#blocksByHash = {};
|
|
26
27
|
#loadingBlocks = {};
|
|
27
28
|
headState;
|
|
28
|
-
|
|
29
|
+
offchainWorker;
|
|
30
|
+
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost = false, allowUnresolvedImports = false, runtimeLogLevel = 0, registeredTypes = {}, offchainWorker = false, }) {
|
|
29
31
|
this.api = api;
|
|
30
32
|
this.db = db;
|
|
31
33
|
this.mockSignatureHost = mockSignatureHost;
|
|
@@ -37,6 +39,9 @@ class Blockchain {
|
|
|
37
39
|
this.#txpool = new txpool_1.TxPool(this, inherentProvider, buildBlockMode);
|
|
38
40
|
this.#inherentProvider = inherentProvider;
|
|
39
41
|
this.headState = new head_state_1.HeadState(this.#head);
|
|
42
|
+
if (offchainWorker) {
|
|
43
|
+
this.offchainWorker = new offchain_1.OffchainWorker();
|
|
44
|
+
}
|
|
40
45
|
}
|
|
41
46
|
#registerBlock(block) {
|
|
42
47
|
this.#blocksByNumber[block.number] = block;
|
|
@@ -107,19 +112,24 @@ class Blockchain {
|
|
|
107
112
|
this.#head = block;
|
|
108
113
|
this.#registerBlock(block);
|
|
109
114
|
await this.headState.setHead(block);
|
|
115
|
+
if (this.offchainWorker) {
|
|
116
|
+
await this.offchainWorker.run(block);
|
|
117
|
+
}
|
|
110
118
|
}
|
|
111
119
|
async submitExtrinsic(extrinsic) {
|
|
112
|
-
const
|
|
113
|
-
const args = (0, util_1.u8aToHex)((0, util_1.u8aConcat)(source, extrinsic, this.head.hash));
|
|
114
|
-
const res = await this.head.call('TaggedTransactionQueue_validate_transaction', [args]);
|
|
115
|
-
const registry = await this.head.registry;
|
|
116
|
-
const validity = registry.createType('TransactionValidity', res.result);
|
|
120
|
+
const validity = await this.validateExtrinsic(extrinsic);
|
|
117
121
|
if (validity.isOk) {
|
|
118
122
|
await this.#txpool.submitExtrinsic(extrinsic);
|
|
119
123
|
return (0, util_crypto_1.blake2AsHex)(extrinsic, 256);
|
|
120
124
|
}
|
|
121
125
|
throw validity.asErr;
|
|
122
126
|
}
|
|
127
|
+
async validateExtrinsic(extrinsic, source = '0x02' /** External */) {
|
|
128
|
+
const args = (0, util_1.u8aToHex)((0, util_1.u8aConcat)(source, extrinsic, this.head.hash));
|
|
129
|
+
const res = await this.head.call('TaggedTransactionQueue_validate_transaction', [args]);
|
|
130
|
+
const registry = await this.head.registry;
|
|
131
|
+
return registry.createType('TransactionValidity', res.result);
|
|
132
|
+
}
|
|
123
133
|
submitUpwardMessages(id, ump) {
|
|
124
134
|
this.#txpool.submitUpwardMessages(id, ump);
|
|
125
135
|
logger.debug({ id, ump }, 'submitUpwardMessages');
|
|
@@ -150,7 +150,7 @@ class SetValidationData {
|
|
|
150
150
|
// make sure previous goAhead is removed
|
|
151
151
|
newEntries.push([upgradeKey, null]);
|
|
152
152
|
}
|
|
153
|
-
const { trieRootHash, nodes } = await (0, executor_1.createProof)(extrinsic.
|
|
153
|
+
const { trieRootHash, nodes } = await (0, executor_1.createProof)(extrinsic.relayChainState.trieNodes, newEntries);
|
|
154
154
|
newData = {
|
|
155
155
|
...extrinsic,
|
|
156
156
|
downwardMessages,
|
package/lib/blockchain/txpool.js
CHANGED
|
@@ -16,7 +16,7 @@ var BuildBlockMode;
|
|
|
16
16
|
BuildBlockMode[BuildBlockMode["Batch"] = 0] = "Batch";
|
|
17
17
|
BuildBlockMode[BuildBlockMode["Instant"] = 1] = "Instant";
|
|
18
18
|
BuildBlockMode[BuildBlockMode["Manual"] = 2] = "Manual";
|
|
19
|
-
})(BuildBlockMode
|
|
19
|
+
})(BuildBlockMode || (exports.BuildBlockMode = BuildBlockMode = {}));
|
|
20
20
|
class TxPool {
|
|
21
21
|
#chain;
|
|
22
22
|
#pool = [];
|
package/lib/cli.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
|
|
1
|
+
import { Config } from './schema';
|
|
2
|
+
export declare const fetchConfig: (path: string) => Promise<Config>;
|
package/lib/cli.js
CHANGED
|
@@ -3,12 +3,13 @@ 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.fetchConfig = void 0;
|
|
6
7
|
const node_path_1 = require("node:path");
|
|
8
|
+
const dotenv_1 = require("dotenv");
|
|
7
9
|
const helpers_1 = require("yargs/helpers");
|
|
8
10
|
const node_fs_1 = require("node:fs");
|
|
9
11
|
const lodash_1 = __importDefault(require("lodash"));
|
|
10
12
|
const axios_1 = __importDefault(require("axios"));
|
|
11
|
-
const dotenv_1 = __importDefault(require("dotenv"));
|
|
12
13
|
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
13
14
|
const yargs_1 = __importDefault(require("yargs"));
|
|
14
15
|
const _1 = require(".");
|
|
@@ -20,9 +21,9 @@ const utils_1 = require("./utils");
|
|
|
20
21
|
const shared_1 = require("./rpc/shared");
|
|
21
22
|
const run_block_1 = require("./run-block");
|
|
22
23
|
const try_runtime_1 = require("./try-runtime");
|
|
23
|
-
dotenv_1.
|
|
24
|
+
(0, dotenv_1.config)();
|
|
24
25
|
const CONFIGS_BASE_URL = 'https://raw.githubusercontent.com/AcalaNetwork/chopsticks/master/configs/';
|
|
25
|
-
const
|
|
26
|
+
const fetchConfig = async (path) => {
|
|
26
27
|
let file;
|
|
27
28
|
if ((0, utils_1.isUrl)(path)) {
|
|
28
29
|
file = await axios_1.default.get(path).then((x) => x.data);
|
|
@@ -48,9 +49,10 @@ const processConfig = async (path) => {
|
|
|
48
49
|
const config = js_yaml_1.default.load(lodash_1.default.template(file, { variable: 'env' })(process.env));
|
|
49
50
|
return schema_1.configSchema.parse(config);
|
|
50
51
|
};
|
|
52
|
+
exports.fetchConfig = fetchConfig;
|
|
51
53
|
const processArgv = async (argv) => {
|
|
52
54
|
if (argv.config) {
|
|
53
|
-
argv = { ...(await
|
|
55
|
+
argv = { ...(await (0, exports.fetchConfig)(argv.config)), ...argv };
|
|
54
56
|
}
|
|
55
57
|
argv.port = argv.port ?? (process.env.PORT ? Number(process.env.PORT) : 8000);
|
|
56
58
|
return argv;
|
|
@@ -80,6 +82,10 @@ const defaultOptions = {
|
|
|
80
82
|
desc: 'Runtime maximum log level [off = 0; error = 1; warn = 2; info = 3; debug = 4; trace = 5]',
|
|
81
83
|
number: true,
|
|
82
84
|
},
|
|
85
|
+
'offchain-worker': {
|
|
86
|
+
desc: 'Enable offchain worker',
|
|
87
|
+
boolean: true,
|
|
88
|
+
},
|
|
83
89
|
};
|
|
84
90
|
const mockOptions = {
|
|
85
91
|
'import-storage': {
|
|
@@ -219,14 +225,14 @@ const mockOptions = {
|
|
|
219
225
|
.alias('parachain', 'p'), async (argv) => {
|
|
220
226
|
const parachains = [];
|
|
221
227
|
for (const config of argv.parachain) {
|
|
222
|
-
const { chain } = await (0, _1.setupWithServer)(await
|
|
228
|
+
const { chain } = await (0, _1.setupWithServer)(await (0, exports.fetchConfig)(config));
|
|
223
229
|
parachains.push(chain);
|
|
224
230
|
}
|
|
225
231
|
if (parachains.length > 1) {
|
|
226
232
|
await (0, _1.connectParachains)(parachains);
|
|
227
233
|
}
|
|
228
234
|
if (argv.relaychain) {
|
|
229
|
-
const { chain: relaychain } = await (0, _1.setupWithServer)(await
|
|
235
|
+
const { chain: relaychain } = await (0, _1.setupWithServer)(await (0, exports.fetchConfig)(argv.relaychain));
|
|
230
236
|
for (const parachain of parachains) {
|
|
231
237
|
await (0, _1.connectVertical)(relaychain, parachain);
|
|
232
238
|
}
|
package/lib/db/entities.js
CHANGED
|
@@ -11,7 +11,7 @@ var __metadata = (this && this.__metadata) || function (k, v) {
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.KeyValuePair = void 0;
|
|
13
13
|
const typeorm_1 = require("typeorm");
|
|
14
|
-
let KeyValuePair = class KeyValuePair {
|
|
14
|
+
let KeyValuePair = exports.KeyValuePair = class KeyValuePair {
|
|
15
15
|
blockHash;
|
|
16
16
|
key;
|
|
17
17
|
value;
|
|
@@ -28,7 +28,6 @@ __decorate([
|
|
|
28
28
|
(0, typeorm_1.Column)({ nullable: true }),
|
|
29
29
|
__metadata("design:type", String)
|
|
30
30
|
], KeyValuePair.prototype, "value", void 0);
|
|
31
|
-
KeyValuePair = __decorate([
|
|
31
|
+
exports.KeyValuePair = KeyValuePair = __decorate([
|
|
32
32
|
(0, typeorm_1.Entity)()
|
|
33
33
|
], KeyValuePair);
|
|
34
|
-
exports.KeyValuePair = KeyValuePair;
|
package/lib/dry-run-preimage.js
CHANGED
package/lib/executor.d.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { HexString } from '@polkadot/util/types';
|
|
2
2
|
import { Block } from './blockchain/block';
|
|
3
|
+
import { JsCallback } from '@acala-network/chopsticks-executor';
|
|
3
4
|
import { Registry } from '@polkadot/types-codec/types';
|
|
4
5
|
import _ from 'lodash';
|
|
5
|
-
interface JsCallback {
|
|
6
|
-
getStorage: (key: HexString) => Promise<string | undefined>;
|
|
7
|
-
getPrefixKeys: (key: HexString) => Promise<string[]>;
|
|
8
|
-
getNextKey: (key: HexString) => Promise<string | undefined>;
|
|
9
|
-
}
|
|
10
6
|
export type RuntimeVersion = {
|
|
11
7
|
specName: string;
|
|
12
8
|
implName: string;
|
|
@@ -20,14 +16,13 @@ export type RuntimeVersion = {
|
|
|
20
16
|
export declare const getRuntimeVersion: (code: HexString) => Promise<RuntimeVersion>;
|
|
21
17
|
export declare const calculateStateRoot: (entries: [HexString, HexString][], trie_version: number) => Promise<HexString>;
|
|
22
18
|
export declare const decodeProof: (trieRootHash: HexString, keys: HexString[], nodes: HexString[]) => Promise<Record<`0x${string}`, `0x${string}` | null>>;
|
|
23
|
-
export declare const createProof: (
|
|
19
|
+
export declare const createProof: (nodes: HexString[], entries: [HexString, HexString | null][]) => Promise<{
|
|
24
20
|
trieRootHash: `0x${string}`;
|
|
25
21
|
nodes: `0x${string}`[];
|
|
26
22
|
}>;
|
|
27
23
|
export declare const runTask: (task: {
|
|
28
24
|
wasm: HexString;
|
|
29
25
|
calls: [string, HexString[]][];
|
|
30
|
-
storage: [HexString, HexString | null][];
|
|
31
26
|
mockSignatureHost: boolean;
|
|
32
27
|
allowUnresolvedImports: boolean;
|
|
33
28
|
runtimeLogLevel: number;
|
|
@@ -35,8 +30,11 @@ export declare const runTask: (task: {
|
|
|
35
30
|
export declare const taskHandler: (block: Block) => JsCallback;
|
|
36
31
|
export declare const emptyTaskHandler: {
|
|
37
32
|
getStorage: (_key: HexString) => Promise<never>;
|
|
38
|
-
|
|
39
|
-
getNextKey: (_key: HexString) => Promise<never>;
|
|
33
|
+
getStateRoot: () => Promise<never>;
|
|
34
|
+
getNextKey: (_prefix: HexString, _key: HexString) => Promise<never>;
|
|
35
|
+
offchainGetStorage: (_key: HexString) => Promise<never>;
|
|
36
|
+
offchainTimestamp: () => Promise<never>;
|
|
37
|
+
offchainRandomSeed: () => Promise<never>;
|
|
38
|
+
offchainSubmitTransaction: (_tx: HexString) => Promise<never>;
|
|
40
39
|
};
|
|
41
40
|
export declare const getAuraSlotDuration: ((wasm: HexString, registry: Registry) => Promise<number>) & _.MemoizedFunction;
|
|
42
|
-
export {};
|
package/lib/executor.js
CHANGED
|
@@ -5,8 +5,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getAuraSlotDuration = exports.emptyTaskHandler = exports.taskHandler = exports.runTask = exports.createProof = exports.decodeProof = exports.calculateStateRoot = exports.getRuntimeVersion = void 0;
|
|
7
7
|
const util_1 = require("@polkadot/util");
|
|
8
|
-
const
|
|
8
|
+
const util_crypto_1 = require("@polkadot/util-crypto");
|
|
9
9
|
const chopsticks_executor_1 = require("@acala-network/chopsticks-executor");
|
|
10
|
+
const key_cache_1 = require("./utils/key-cache");
|
|
10
11
|
const logger_1 = require("./logger");
|
|
11
12
|
const lodash_1 = __importDefault(require("lodash"));
|
|
12
13
|
const logger = logger_1.defaultLogger.child({ name: 'executor' });
|
|
@@ -31,14 +32,14 @@ const decodeProof = async (trieRootHash, keys, nodes) => {
|
|
|
31
32
|
}, {});
|
|
32
33
|
};
|
|
33
34
|
exports.decodeProof = decodeProof;
|
|
34
|
-
const createProof = async (
|
|
35
|
-
const result = await (0, chopsticks_executor_1.create_proof)(
|
|
35
|
+
const createProof = async (nodes, entries) => {
|
|
36
|
+
const result = await (0, chopsticks_executor_1.create_proof)(nodes, entries);
|
|
36
37
|
return { trieRootHash: result[0], nodes: result[1] };
|
|
37
38
|
};
|
|
38
39
|
exports.createProof = createProof;
|
|
39
40
|
const runTask = async (task, callback = exports.emptyTaskHandler) => {
|
|
40
41
|
logger.trace((0, logger_1.truncate)(task), 'taskRun');
|
|
41
|
-
const response = await (0, chopsticks_executor_1.run_task)(task, callback);
|
|
42
|
+
const response = await (0, chopsticks_executor_1.run_task)(task, callback, process.env.RUST_LOG);
|
|
42
43
|
if (response.Call) {
|
|
43
44
|
logger.trace((0, logger_1.truncate)(response.Call), 'taskResponse');
|
|
44
45
|
}
|
|
@@ -49,25 +50,46 @@ const runTask = async (task, callback = exports.emptyTaskHandler) => {
|
|
|
49
50
|
};
|
|
50
51
|
exports.runTask = runTask;
|
|
51
52
|
const taskHandler = (block) => {
|
|
52
|
-
const batchSize = 1000;
|
|
53
53
|
return {
|
|
54
54
|
getStorage: async function (key) {
|
|
55
55
|
return block.get(key);
|
|
56
56
|
},
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
while (startKey) {
|
|
61
|
-
const batch = await block.getKeysPaged({ prefix: key.slice(0, key_cache_1.PREFIX_LENGTH), pageSize: batchSize, startKey });
|
|
62
|
-
keys = keys.concat(batch);
|
|
63
|
-
startKey = batch[batchSize - 1];
|
|
64
|
-
}
|
|
65
|
-
return keys;
|
|
57
|
+
getStateRoot: async function () {
|
|
58
|
+
const header = await block.header;
|
|
59
|
+
return header.stateRoot.toHex();
|
|
66
60
|
},
|
|
67
|
-
getNextKey: async function (key) {
|
|
68
|
-
const [nextKey] = await block.getKeysPaged({
|
|
61
|
+
getNextKey: async function (prefix, key) {
|
|
62
|
+
const [nextKey] = await block.getKeysPaged({
|
|
63
|
+
prefix: prefix.length === 2 /** 0x */ ? key.slice(0, key_cache_1.PREFIX_LENGTH) : prefix,
|
|
64
|
+
pageSize: 1,
|
|
65
|
+
startKey: key,
|
|
66
|
+
});
|
|
69
67
|
return nextKey;
|
|
70
68
|
},
|
|
69
|
+
offchainGetStorage: async function (key) {
|
|
70
|
+
if (!block.chain.offchainWorker)
|
|
71
|
+
throw new Error('offchain worker not found');
|
|
72
|
+
return block.chain.offchainWorker.get(key);
|
|
73
|
+
},
|
|
74
|
+
offchainTimestamp: async function () {
|
|
75
|
+
return Date.now();
|
|
76
|
+
},
|
|
77
|
+
offchainRandomSeed: async function () {
|
|
78
|
+
return (0, util_crypto_1.randomAsHex)(32);
|
|
79
|
+
},
|
|
80
|
+
offchainSubmitTransaction: async function (tx) {
|
|
81
|
+
if (!block.chain.offchainWorker)
|
|
82
|
+
throw new Error('offchain worker not found');
|
|
83
|
+
try {
|
|
84
|
+
const hash = await block.chain.offchainWorker.pushExtrinsic(block, tx);
|
|
85
|
+
logger.trace({ hash }, 'offchainSubmitTransaction');
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
logger.trace({ error }, 'offchainSubmitTransaction');
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
},
|
|
71
93
|
};
|
|
72
94
|
};
|
|
73
95
|
exports.taskHandler = taskHandler;
|
|
@@ -75,10 +97,22 @@ exports.emptyTaskHandler = {
|
|
|
75
97
|
getStorage: async function (_key) {
|
|
76
98
|
throw new Error('Method not implemented');
|
|
77
99
|
},
|
|
78
|
-
|
|
100
|
+
getStateRoot: async function () {
|
|
101
|
+
throw new Error('Method not implemented');
|
|
102
|
+
},
|
|
103
|
+
getNextKey: async function (_prefix, _key) {
|
|
104
|
+
throw new Error('Method not implemented');
|
|
105
|
+
},
|
|
106
|
+
offchainGetStorage: async function (_key) {
|
|
107
|
+
throw new Error('Method not implemented');
|
|
108
|
+
},
|
|
109
|
+
offchainTimestamp: async function () {
|
|
110
|
+
throw new Error('Method not implemented');
|
|
111
|
+
},
|
|
112
|
+
offchainRandomSeed: async function () {
|
|
79
113
|
throw new Error('Method not implemented');
|
|
80
114
|
},
|
|
81
|
-
|
|
115
|
+
offchainSubmitTransaction: async function (_tx) {
|
|
82
116
|
throw new Error('Method not implemented');
|
|
83
117
|
},
|
|
84
118
|
};
|
|
@@ -86,7 +120,6 @@ exports.getAuraSlotDuration = lodash_1.default.memoize(async (wasm, registry) =>
|
|
|
86
120
|
const result = await (0, exports.runTask)({
|
|
87
121
|
wasm,
|
|
88
122
|
calls: [['AuraApi_slot_duration', []]],
|
|
89
|
-
storage: [],
|
|
90
123
|
mockSignatureHost: false,
|
|
91
124
|
allowUnresolvedImports: false,
|
|
92
125
|
runtimeLogLevel: 0,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { HexString } from '@polkadot/util/types';
|
|
2
|
+
import { JsCallback } from '@acala-network/chopsticks-executor';
|
|
2
3
|
import { ProviderInterface, ProviderInterfaceCallback, ProviderInterfaceEmitCb, ProviderInterfaceEmitted, ProviderStats } from '@polkadot/rpc-provider/types';
|
|
3
4
|
import { Genesis } from './schema';
|
|
4
5
|
export declare class GenesisProvider implements ProviderInterface {
|
|
@@ -36,11 +37,7 @@ export declare class GenesisProvider implements ProviderInterface {
|
|
|
36
37
|
extrinsics: never[];
|
|
37
38
|
};
|
|
38
39
|
}>;
|
|
39
|
-
get _jsCallback():
|
|
40
|
-
getStorage: (key: HexString) => Promise<string>;
|
|
41
|
-
getNextKey: (_key: HexString) => Promise<string>;
|
|
42
|
-
getPrefixKeys: (_key: HexString) => Promise<never[]>;
|
|
43
|
-
};
|
|
40
|
+
get _jsCallback(): JsCallback;
|
|
44
41
|
send: (method: string, params: unknown[], _isCacheable?: boolean) => Promise<any>;
|
|
45
42
|
subscribe: (_type: string, _method: string, _params: unknown[], _cb: ProviderInterfaceCallback) => Promise<number | string>;
|
|
46
43
|
unsubscribe: (_type: string, _method: string, _id: number | string) => Promise<boolean>;
|
package/lib/genesis-provider.js
CHANGED
|
@@ -99,14 +99,15 @@ class GenesisProvider {
|
|
|
99
99
|
get _jsCallback() {
|
|
100
100
|
const storage = this.#genesis.genesis.raw.top;
|
|
101
101
|
return {
|
|
102
|
+
...executor_1.emptyTaskHandler,
|
|
102
103
|
getStorage: async function (key) {
|
|
103
104
|
return storage[key];
|
|
104
105
|
},
|
|
105
|
-
|
|
106
|
-
return '
|
|
106
|
+
getStateRoot: async function () {
|
|
107
|
+
return '0x49416764844ff0d8bad851e8abe686dff9dd2de78621180ef8e9f99bb7a480f1';
|
|
107
108
|
},
|
|
108
|
-
|
|
109
|
-
return
|
|
109
|
+
getNextKey: async function (_prefix, _key) {
|
|
110
|
+
return undefined;
|
|
110
111
|
},
|
|
111
112
|
};
|
|
112
113
|
}
|
|
@@ -124,7 +125,6 @@ class GenesisProvider {
|
|
|
124
125
|
return (0, executor_1.runTask)({
|
|
125
126
|
wasm: code,
|
|
126
127
|
calls: [['Metadata_metadata', []]],
|
|
127
|
-
storage: [],
|
|
128
128
|
mockSignatureHost: false,
|
|
129
129
|
allowUnresolvedImports: true,
|
|
130
130
|
runtimeLogLevel: 0,
|
package/lib/index.d.ts
CHANGED
|
@@ -4,4 +4,5 @@ export { BuildBlockMode } from './blockchain/txpool';
|
|
|
4
4
|
export { connectParachains, connectVertical } from './xcm';
|
|
5
5
|
export { setup } from './setup';
|
|
6
6
|
export { setupWithServer } from './setup-with-server';
|
|
7
|
+
export { fetchConfig } from './cli';
|
|
7
8
|
export * from './blockchain/inherent';
|
package/lib/index.js
CHANGED
|
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.setupWithServer = exports.setup = exports.connectVertical = exports.connectParachains = exports.BuildBlockMode = exports.Blockchain = exports.Api = void 0;
|
|
17
|
+
exports.fetchConfig = exports.setupWithServer = exports.setup = exports.connectVertical = exports.connectParachains = exports.BuildBlockMode = exports.Blockchain = exports.Api = void 0;
|
|
18
18
|
var api_1 = require("./api");
|
|
19
19
|
Object.defineProperty(exports, "Api", { enumerable: true, get: function () { return api_1.Api; } });
|
|
20
20
|
var blockchain_1 = require("./blockchain");
|
|
@@ -28,4 +28,6 @@ var setup_1 = require("./setup");
|
|
|
28
28
|
Object.defineProperty(exports, "setup", { enumerable: true, get: function () { return setup_1.setup; } });
|
|
29
29
|
var setup_with_server_1 = require("./setup-with-server");
|
|
30
30
|
Object.defineProperty(exports, "setupWithServer", { enumerable: true, get: function () { return setup_with_server_1.setupWithServer; } });
|
|
31
|
+
var cli_1 = require("./cli");
|
|
32
|
+
Object.defineProperty(exports, "fetchConfig", { enumerable: true, get: function () { return cli_1.fetchConfig; } });
|
|
31
33
|
__exportStar(require("./blockchain/inherent"), exports);
|
package/lib/logger.js
CHANGED
|
@@ -12,15 +12,17 @@ exports.defaultLogger = (0, pino_1.default)({
|
|
|
12
12
|
},
|
|
13
13
|
});
|
|
14
14
|
const innerTruncate = (level = 0) => (val) => {
|
|
15
|
+
const verboseLog = !!process.env.VERBOSE_LOG;
|
|
16
|
+
const levelLimit = verboseLog ? 10 : 5;
|
|
15
17
|
if (val == null) {
|
|
16
18
|
return val;
|
|
17
19
|
}
|
|
18
|
-
if (level >
|
|
20
|
+
if (level > levelLimit) {
|
|
19
21
|
return '( Too Deep )';
|
|
20
22
|
}
|
|
21
23
|
switch (typeof val) {
|
|
22
24
|
case 'string':
|
|
23
|
-
if (val.length > 66) {
|
|
25
|
+
if (val.length > 66 && !verboseLog) {
|
|
24
26
|
return val.slice(0, 34) + '…' + val.slice(-32);
|
|
25
27
|
}
|
|
26
28
|
else {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Block } from './blockchain/block';
|
|
2
|
+
import { HexString } from '@polkadot/util/types';
|
|
3
|
+
export declare class OffchainWorker {
|
|
4
|
+
readonly pendingExtrinsics: HexString[];
|
|
5
|
+
readonly offchainStorage: Map<string, string | null | undefined>;
|
|
6
|
+
get(key: string): string | null | undefined;
|
|
7
|
+
set(key: string, value: string | null | undefined): void;
|
|
8
|
+
run(block: Block): Promise<void>;
|
|
9
|
+
pushExtrinsic(block: Block, extrinsic: HexString): Promise<`0x${string}`>;
|
|
10
|
+
}
|
package/lib/offchain.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OffchainWorker = void 0;
|
|
4
|
+
const util_crypto_1 = require("@polkadot/util-crypto");
|
|
5
|
+
const shared_1 = require("./rpc/shared");
|
|
6
|
+
const rxjs_1 = require("rxjs");
|
|
7
|
+
class OffchainWorker {
|
|
8
|
+
pendingExtrinsics = [];
|
|
9
|
+
offchainStorage = new Map();
|
|
10
|
+
get(key) {
|
|
11
|
+
return this.offchainStorage.get(key);
|
|
12
|
+
}
|
|
13
|
+
set(key, value) {
|
|
14
|
+
this.offchainStorage.set(key, value);
|
|
15
|
+
}
|
|
16
|
+
async run(block) {
|
|
17
|
+
shared_1.logger.info({ number: block.number, hash: block.hash }, `Run Offchain Worker for block #${block.number.toLocaleString()}`);
|
|
18
|
+
const header = await block.header;
|
|
19
|
+
await block.call('OffchainWorkerApi_offchain_worker', [header.toHex()]);
|
|
20
|
+
shared_1.logger.info(`Offchain Worker complete for block #${block.number.toLocaleString()}`);
|
|
21
|
+
const txs = this.pendingExtrinsics.splice(0);
|
|
22
|
+
if (txs.length > 0) {
|
|
23
|
+
rxjs_1.queueScheduler.schedule(async (transactions) => {
|
|
24
|
+
await block.chain.txPool.buildBlock({ transactions });
|
|
25
|
+
}, 100, txs);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
async pushExtrinsic(block, extrinsic) {
|
|
29
|
+
const validity = await block.chain.validateExtrinsic(extrinsic, '0x01');
|
|
30
|
+
if (validity.isOk) {
|
|
31
|
+
this.pendingExtrinsics.push(extrinsic);
|
|
32
|
+
return (0, util_crypto_1.blake2AsHex)(extrinsic, 256);
|
|
33
|
+
}
|
|
34
|
+
throw validity.asErr;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.OffchainWorker = OffchainWorker;
|
package/lib/run-block.js
CHANGED
|
@@ -10,11 +10,11 @@ const setup_1 = require("./setup");
|
|
|
10
10
|
const runBlock = async (argv) => {
|
|
11
11
|
const context = await (0, setup_1.setup)(argv, true);
|
|
12
12
|
const header = await context.chain.head.header;
|
|
13
|
-
const wasm = await context.chain.head.wasm;
|
|
14
13
|
const block = context.chain.head;
|
|
15
14
|
const parent = await block.parentBlock;
|
|
16
15
|
if (!parent)
|
|
17
16
|
throw Error('cant find parent block');
|
|
17
|
+
const wasm = await parent.wasm;
|
|
18
18
|
const calls = [['Core_initialize_block', [header.toHex()]]];
|
|
19
19
|
for (const extrinsic of await block.extrinsics) {
|
|
20
20
|
calls.push(['BlockBuilder_apply_extrinsic', [extrinsic]]);
|
|
@@ -23,7 +23,6 @@ const runBlock = async (argv) => {
|
|
|
23
23
|
const result = await (0, executor_1.runTask)({
|
|
24
24
|
wasm,
|
|
25
25
|
calls,
|
|
26
|
-
storage: [],
|
|
27
26
|
mockSignatureHost: false,
|
|
28
27
|
allowUnresolvedImports: false,
|
|
29
28
|
runtimeLogLevel: argv['runtime-log-level'] || 0,
|
package/lib/schema/index.d.ts
CHANGED
|
@@ -133,6 +133,7 @@ export declare const configSchema: z.ZodObject<{
|
|
|
133
133
|
timestamp: z.ZodOptional<z.ZodNumber>;
|
|
134
134
|
'registered-types': z.ZodOptional<z.ZodAny>;
|
|
135
135
|
'runtime-log-level': z.ZodOptional<z.ZodNumber>;
|
|
136
|
+
'offchain-worker': z.ZodOptional<z.ZodBoolean>;
|
|
136
137
|
}, "strict", z.ZodTypeAny, {
|
|
137
138
|
port?: number | undefined;
|
|
138
139
|
endpoint?: string | undefined;
|
|
@@ -159,6 +160,7 @@ export declare const configSchema: z.ZodObject<{
|
|
|
159
160
|
timestamp?: number | undefined;
|
|
160
161
|
'registered-types'?: any;
|
|
161
162
|
'runtime-log-level'?: number | undefined;
|
|
163
|
+
'offchain-worker'?: boolean | undefined;
|
|
162
164
|
}, {
|
|
163
165
|
port?: number | undefined;
|
|
164
166
|
endpoint?: string | undefined;
|
|
@@ -185,5 +187,6 @@ export declare const configSchema: z.ZodObject<{
|
|
|
185
187
|
timestamp?: number | undefined;
|
|
186
188
|
'registered-types'?: any;
|
|
187
189
|
'runtime-log-level'?: number | undefined;
|
|
190
|
+
'offchain-worker'?: boolean | undefined;
|
|
188
191
|
}>;
|
|
189
192
|
export type Config = z.infer<typeof configSchema>;
|
package/lib/schema/index.js
CHANGED
package/lib/setup.d.ts
CHANGED
package/lib/setup.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.setup = void 0;
|
|
4
|
+
require("./utils/tunnel");
|
|
4
5
|
require("@polkadot/types-codec");
|
|
5
6
|
const api_1 = require("@polkadot/api");
|
|
6
7
|
const api_2 = require("./api");
|
|
@@ -64,6 +65,7 @@ const setup = async (argv, runBlock = false) => {
|
|
|
64
65
|
allowUnresolvedImports: argv['allow-unresolved-imports'],
|
|
65
66
|
runtimeLogLevel: argv['runtime-log-level'],
|
|
66
67
|
registeredTypes: argv['registered-types'],
|
|
68
|
+
offchainWorker: argv['offchain-worker'],
|
|
67
69
|
});
|
|
68
70
|
if (argv.timestamp)
|
|
69
71
|
await (0, time_travel_1.timeTravel)(chain, argv.timestamp);
|
package/lib/try-runtime.js
CHANGED
|
@@ -17,7 +17,7 @@ const tryRuntime = async (argv) => {
|
|
|
17
17
|
},
|
|
18
18
|
});
|
|
19
19
|
const select_none = registry.createType('UpgradeCheckSelect', 'None');
|
|
20
|
-
const result = await block.call('TryRuntime_on_runtime_upgrade', [select_none.toHex()]
|
|
20
|
+
const result = await block.call('TryRuntime_on_runtime_upgrade', [select_none.toHex()]);
|
|
21
21
|
if (argv['html']) {
|
|
22
22
|
const filePath = await (0, generate_html_diff_1.generateHtmlDiffPreviewFile)(block, result.storageDiff, block.hash);
|
|
23
23
|
console.log(`Generated preview ${filePath}`);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import 'global-agent/bootstrap';
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
require("global-agent/bootstrap");
|
|
7
|
+
const npm_conf_1 = __importDefault(require("@pnpm/npm-conf"));
|
|
8
|
+
const npmConfig = (0, npm_conf_1.default)().config;
|
|
9
|
+
global.GLOBAL_AGENT.HTTP_PROXY =
|
|
10
|
+
process.env.HTTP_PROXY ||
|
|
11
|
+
process.env.http_proxy ||
|
|
12
|
+
process.env.HTTPS_PROXY ||
|
|
13
|
+
process.env.https_proxy ||
|
|
14
|
+
npmConfig.get('proxy') ||
|
|
15
|
+
npmConfig.get('https-proxy') ||
|
|
16
|
+
global.GLOBAL_AGENT.HTTP_PROXY;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acala-network/chopsticks",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.1",
|
|
4
4
|
"author": "Bryan Chen <xlchen1291@gmail.com>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": "./chopsticks.js",
|
|
@@ -16,30 +16,33 @@
|
|
|
16
16
|
"dev:moonbeam": "cd ../..; ts-node-dev --transpile-only --inspect --notify=false packages/chopsticks/src/cli.ts -- --config=configs/moonbeam.yml"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@acala-network/chopsticks-executor": "0.
|
|
20
|
-
"@
|
|
19
|
+
"@acala-network/chopsticks-executor": "0.7.1",
|
|
20
|
+
"@pnpm/npm-conf": "^2.2.2",
|
|
21
|
+
"@polkadot/api": "^10.9.1",
|
|
21
22
|
"axios": "^1.4.0",
|
|
23
|
+
"global-agent": "^3.0.0",
|
|
22
24
|
"js-yaml": "^4.1.0",
|
|
23
25
|
"jsondiffpatch": "^0.4.1",
|
|
24
26
|
"lodash": "^4.17.21",
|
|
25
27
|
"pino": "^8.14.1",
|
|
26
|
-
"pino-pretty": "^10.0.
|
|
28
|
+
"pino-pretty": "^10.0.1",
|
|
27
29
|
"reflect-metadata": "^0.1.13",
|
|
28
30
|
"sqlite3": "^5.1.6",
|
|
29
|
-
"typeorm": "^0.3.
|
|
31
|
+
"typeorm": "^0.3.17",
|
|
30
32
|
"ws": "^8.13.0",
|
|
31
33
|
"yargs": "^17.7.2",
|
|
32
34
|
"zod": "^3.21.4"
|
|
33
35
|
},
|
|
34
36
|
"devDependencies": {
|
|
37
|
+
"@types/global-agent": "^2.1.1",
|
|
35
38
|
"@types/js-yaml": "^4.0.5",
|
|
36
|
-
"@types/lodash": "^4.14.
|
|
37
|
-
"@types/node": "^20.2
|
|
38
|
-
"@types/ws": "^8.5.
|
|
39
|
+
"@types/lodash": "^4.14.195",
|
|
40
|
+
"@types/node": "^20.4.2",
|
|
41
|
+
"@types/ws": "^8.5.5",
|
|
39
42
|
"@types/yargs": "^17.0.24",
|
|
40
43
|
"ts-node": "^10.9.1",
|
|
41
44
|
"ts-node-dev": "^2.0.0",
|
|
42
|
-
"typescript": "^5.
|
|
45
|
+
"typescript": "^5.1.6"
|
|
43
46
|
},
|
|
44
47
|
"files": [
|
|
45
48
|
"lib",
|
package/template/diff.html
CHANGED