@acala-network/chopsticks-core 0.8.5-5 → 0.9.0
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 → dist/cjs}/api.js +7 -7
- package/{lib → dist/cjs}/blockchain/block.js +1 -4
- package/{lib → dist/cjs}/genesis-provider.js +1 -1
- package/{lib → dist/cjs}/rpc/substrate/chain.js +1 -1
- package/{lib → dist/cjs}/utils/index.js +11 -1
- package/dist/esm/api.js +125 -0
- package/dist/esm/blockchain/block-builder.js +293 -0
- package/dist/esm/blockchain/block.js +277 -0
- package/dist/esm/blockchain/head-state.js +79 -0
- package/dist/esm/blockchain/index.js +413 -0
- package/dist/esm/blockchain/inherent/index.js +40 -0
- package/dist/esm/blockchain/inherent/para-enter.js +29 -0
- package/dist/esm/blockchain/inherent/parachain/babe-randomness.js +11 -0
- package/dist/esm/blockchain/inherent/parachain/nimbus-author-inherent.js +11 -0
- package/dist/esm/blockchain/inherent/parachain/validation-data.js +165 -0
- package/dist/esm/blockchain/storage-layer.js +215 -0
- package/dist/esm/blockchain/txpool.js +208 -0
- package/dist/esm/chopsticks-provider.js +156 -0
- package/dist/esm/database.js +1 -0
- package/dist/esm/genesis-provider.js +144 -0
- package/dist/esm/logger.js +34 -0
- package/dist/esm/offchain.js +36 -0
- package/dist/esm/rpc/index.js +10 -0
- package/dist/esm/rpc/shared.js +15 -0
- package/dist/esm/rpc/substrate/author.js +85 -0
- package/dist/esm/rpc/substrate/chain.js +84 -0
- package/dist/esm/rpc/substrate/index.js +18 -0
- package/dist/esm/rpc/substrate/payment.js +40 -0
- package/dist/esm/rpc/substrate/state.js +166 -0
- package/dist/esm/rpc/substrate/system.js +48 -0
- package/dist/esm/schema/index.js +11 -0
- package/dist/esm/setup.js +71 -0
- package/dist/esm/utils/decoder.js +95 -0
- package/dist/esm/utils/index.js +91 -0
- package/dist/esm/utils/key-cache.js +61 -0
- package/dist/esm/utils/proof.js +33 -0
- package/dist/esm/utils/set-storage.js +56 -0
- package/dist/esm/utils/time-travel.js +58 -0
- package/dist/esm/wasm-executor/browser-wasm-executor.mjs +32 -0
- package/dist/esm/wasm-executor/browser-worker.js +15 -0
- package/dist/esm/wasm-executor/index.js +146 -0
- package/dist/esm/wasm-executor/node-wasm-executor.mjs +29 -0
- package/dist/esm/wasm-executor/node-worker.js +15 -0
- package/dist/esm/xcm/downward.js +25 -0
- package/dist/esm/xcm/horizontal.js +25 -0
- package/dist/esm/xcm/index.js +20 -0
- package/dist/esm/xcm/upward.js +17 -0
- package/{lib → dist/types}/genesis-provider.d.ts +2 -2
- package/dist/types/index.d.ts +28 -0
- package/{lib → dist/types}/utils/index.d.ts +1 -0
- package/package.json +23 -14
- /package/{lib → dist/cjs}/blockchain/block-builder.js +0 -0
- /package/{lib → dist/cjs}/blockchain/head-state.js +0 -0
- /package/{lib → dist/cjs}/blockchain/index.js +0 -0
- /package/{lib → dist/cjs}/blockchain/inherent/index.js +0 -0
- /package/{lib → dist/cjs}/blockchain/inherent/para-enter.js +0 -0
- /package/{lib → dist/cjs}/blockchain/inherent/parachain/babe-randomness.js +0 -0
- /package/{lib → dist/cjs}/blockchain/inherent/parachain/nimbus-author-inherent.js +0 -0
- /package/{lib → dist/cjs}/blockchain/inherent/parachain/validation-data.js +0 -0
- /package/{lib → dist/cjs}/blockchain/storage-layer.js +0 -0
- /package/{lib → dist/cjs}/blockchain/txpool.js +0 -0
- /package/{lib → dist/cjs}/chopsticks-provider.js +0 -0
- /package/{lib → dist/cjs}/database.js +0 -0
- /package/{lib → dist/cjs}/index.js +0 -0
- /package/{lib → dist/cjs}/logger.js +0 -0
- /package/{lib → dist/cjs}/offchain.js +0 -0
- /package/{lib → dist/cjs}/rpc/index.js +0 -0
- /package/{lib → dist/cjs}/rpc/shared.js +0 -0
- /package/{lib → dist/cjs}/rpc/substrate/author.js +0 -0
- /package/{lib → dist/cjs}/rpc/substrate/index.js +0 -0
- /package/{lib → dist/cjs}/rpc/substrate/payment.js +0 -0
- /package/{lib → dist/cjs}/rpc/substrate/state.js +0 -0
- /package/{lib → dist/cjs}/rpc/substrate/system.js +0 -0
- /package/{lib → dist/cjs}/schema/index.js +0 -0
- /package/{lib → dist/cjs}/setup.js +0 -0
- /package/{lib → dist/cjs}/utils/decoder.js +0 -0
- /package/{lib → dist/cjs}/utils/key-cache.js +0 -0
- /package/{lib → dist/cjs}/utils/proof.js +0 -0
- /package/{lib → dist/cjs}/utils/set-storage.js +0 -0
- /package/{lib → dist/cjs}/utils/time-travel.js +0 -0
- /package/{lib → dist/cjs}/wasm-executor/browser-wasm-executor.mjs +0 -0
- /package/{lib → dist/cjs}/wasm-executor/browser-worker.js +0 -0
- /package/{lib → dist/cjs}/wasm-executor/index.js +0 -0
- /package/{lib → dist/cjs}/wasm-executor/node-wasm-executor.mjs +0 -0
- /package/{lib → dist/cjs}/wasm-executor/node-worker.js +0 -0
- /package/{lib → dist/cjs}/xcm/downward.js +0 -0
- /package/{lib → dist/cjs}/xcm/horizontal.js +0 -0
- /package/{lib → dist/cjs}/xcm/index.js +0 -0
- /package/{lib → dist/cjs}/xcm/upward.js +0 -0
- /package/{lib/index.d.ts → dist/esm/index.js} +0 -0
- /package/{lib → dist/types}/api.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/block-builder.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/block.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/head-state.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/index.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/inherent/index.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/inherent/para-enter.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/inherent/parachain/babe-randomness.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/inherent/parachain/nimbus-author-inherent.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/inherent/parachain/validation-data.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/storage-layer.d.ts +0 -0
- /package/{lib → dist/types}/blockchain/txpool.d.ts +0 -0
- /package/{lib → dist/types}/chopsticks-provider.d.ts +0 -0
- /package/{lib → dist/types}/database.d.ts +0 -0
- /package/{lib → dist/types}/logger.d.ts +0 -0
- /package/{lib → dist/types}/offchain.d.ts +0 -0
- /package/{lib → dist/types}/rpc/index.d.ts +0 -0
- /package/{lib → dist/types}/rpc/shared.d.ts +0 -0
- /package/{lib → dist/types}/rpc/substrate/author.d.ts +0 -0
- /package/{lib → dist/types}/rpc/substrate/chain.d.ts +0 -0
- /package/{lib → dist/types}/rpc/substrate/index.d.ts +0 -0
- /package/{lib → dist/types}/rpc/substrate/payment.d.ts +0 -0
- /package/{lib → dist/types}/rpc/substrate/state.d.ts +0 -0
- /package/{lib → dist/types}/rpc/substrate/system.d.ts +0 -0
- /package/{lib → dist/types}/schema/index.d.ts +0 -0
- /package/{lib → dist/types}/setup.d.ts +0 -0
- /package/{lib → dist/types}/utils/decoder.d.ts +0 -0
- /package/{lib → dist/types}/utils/key-cache.d.ts +0 -0
- /package/{lib → dist/types}/utils/proof.d.ts +0 -0
- /package/{lib → dist/types}/utils/set-storage.d.ts +0 -0
- /package/{lib → dist/types}/utils/time-travel.d.ts +0 -0
- /package/{lib → dist/types}/wasm-executor/browser-worker.d.ts +0 -0
- /package/{lib → dist/types}/wasm-executor/index.d.ts +0 -0
- /package/{lib → dist/types}/wasm-executor/node-worker.d.ts +0 -0
- /package/{lib → dist/types}/xcm/downward.d.ts +0 -0
- /package/{lib → dist/types}/xcm/horizontal.d.ts +0 -0
- /package/{lib → dist/types}/xcm/index.d.ts +0 -0
- /package/{lib → dist/types}/xcm/upward.d.ts +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { hexToU8a, u8aToHex } from '@polkadot/util';
|
|
2
|
+
import { compactHex } from '.';
|
|
3
|
+
import { getAuraSlotDuration } from '../wasm-executor';
|
|
4
|
+
import { setStorage } from './set-storage';
|
|
5
|
+
export const getCurrentSlot = async (chain) => {
|
|
6
|
+
const meta = await chain.head.meta;
|
|
7
|
+
// use raw key here because some chain did not expose those storage to metadata
|
|
8
|
+
const slotRaw = meta.consts.babe
|
|
9
|
+
? await chain.head.get('0x1cb6f36e027abb2091cfb5110ab5087f06155b3cd9a8c9e5e9a23fd5dc13a5ed') // babe.currentSlot
|
|
10
|
+
: await chain.head.get('0x57f8dc2f5ab09467896f47300f04243806155b3cd9a8c9e5e9a23fd5dc13a5ed'); // aura.currentSlot
|
|
11
|
+
if (!slotRaw)
|
|
12
|
+
throw new Error('Cannot find current slot');
|
|
13
|
+
return meta.registry.createType('Slot', hexToU8a(slotRaw)).toNumber();
|
|
14
|
+
};
|
|
15
|
+
export const getCurrentTimestamp = async (chain) => {
|
|
16
|
+
const meta = await chain.head.meta;
|
|
17
|
+
const timestamp = await chain.head.read('u64', meta.query.timestamp.now);
|
|
18
|
+
return timestamp?.toBigInt() ?? 0n;
|
|
19
|
+
};
|
|
20
|
+
export const getSlotDuration = async (chain) => {
|
|
21
|
+
const meta = await chain.head.meta;
|
|
22
|
+
return meta.consts.babe
|
|
23
|
+
? meta.consts.babe.expectedBlockTime.toNumber()
|
|
24
|
+
: meta.query.aura
|
|
25
|
+
? getAuraSlotDuration(await chain.head.wasm, meta.registry)
|
|
26
|
+
: 12000;
|
|
27
|
+
};
|
|
28
|
+
export const timeTravel = async (chain, timestamp) => {
|
|
29
|
+
const meta = await chain.head.meta;
|
|
30
|
+
const slotDuration = await getSlotDuration(chain);
|
|
31
|
+
const newSlot = Math.floor(timestamp / slotDuration);
|
|
32
|
+
// new timestamp
|
|
33
|
+
const storage = [
|
|
34
|
+
[compactHex(meta.query.timestamp.now()), u8aToHex(meta.registry.createType('u64', timestamp).toU8a())],
|
|
35
|
+
];
|
|
36
|
+
if (meta.consts.babe) {
|
|
37
|
+
// new slot
|
|
38
|
+
storage.push([
|
|
39
|
+
compactHex(meta.query.babe.currentSlot()),
|
|
40
|
+
u8aToHex(meta.registry.createType('Slot', newSlot).toU8a()),
|
|
41
|
+
]);
|
|
42
|
+
// new epoch
|
|
43
|
+
const epochDuration = meta.consts.babe.epochDuration.toNumber();
|
|
44
|
+
const newEpoch = Math.floor(timestamp / epochDuration);
|
|
45
|
+
storage.push([
|
|
46
|
+
compactHex(meta.query.babe.epochIndex()),
|
|
47
|
+
u8aToHex(meta.registry.createType('u64', newEpoch).toU8a()),
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
50
|
+
else if (meta.query.aura) {
|
|
51
|
+
// new slot
|
|
52
|
+
storage.push([
|
|
53
|
+
compactHex(meta.query.aura.currentSlot()),
|
|
54
|
+
u8aToHex(meta.registry.createType('Slot', newSlot).toU8a()),
|
|
55
|
+
]);
|
|
56
|
+
}
|
|
57
|
+
await setStorage(chain, storage);
|
|
58
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as Comlink from 'comlink'
|
|
2
|
+
import * as pkg from '@acala-network/chopsticks-executor'
|
|
3
|
+
|
|
4
|
+
const getRuntimeVersion = async (code) => {
|
|
5
|
+
await pkg.wasmReady
|
|
6
|
+
return pkg.get_runtime_version(code)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
// trie_version: 0 for old trie, 1 for new trie
|
|
10
|
+
const calculateStateRoot = async (entries, trie_version) => {
|
|
11
|
+
await pkg.wasmReady
|
|
12
|
+
return pkg.calculate_state_root(entries, trie_version)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const decodeProof = async (trieRootHash, keys, nodes) => {
|
|
16
|
+
await pkg.wasmReady
|
|
17
|
+
return pkg.decode_proof(trieRootHash, keys, nodes)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const createProof = async (nodes, entries) => {
|
|
21
|
+
await pkg.wasmReady
|
|
22
|
+
return pkg.create_proof(nodes, entries)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const runTask = async (task, callback) => {
|
|
26
|
+
await pkg.wasmReady
|
|
27
|
+
return pkg.run_task(task, callback, 'info')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const wasmExecutor = { runTask, getRuntimeVersion, calculateStateRoot, createProof, decodeProof }
|
|
31
|
+
|
|
32
|
+
Comlink.expose(wasmExecutor)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { wrap } from 'comlink';
|
|
2
|
+
export const startWorker = async () => {
|
|
3
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
4
|
+
// @ts-ignore
|
|
5
|
+
const worker = new Worker(new URL('browser-wasm-executor.mjs', import.meta.url), {
|
|
6
|
+
type: 'module',
|
|
7
|
+
name: 'chopsticks-wasm-executor',
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
remote: wrap(worker),
|
|
11
|
+
terminate: async () => {
|
|
12
|
+
worker.terminate();
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import * as Comlink from 'comlink';
|
|
2
|
+
import { hexToString, hexToU8a } from '@polkadot/util';
|
|
3
|
+
import { randomAsHex } from '@polkadot/util-crypto';
|
|
4
|
+
import _ from 'lodash';
|
|
5
|
+
import { PREFIX_LENGTH } from '../utils/key-cache';
|
|
6
|
+
import { defaultLogger, truncate } from '../logger';
|
|
7
|
+
import { stripChildPrefix } from '../utils';
|
|
8
|
+
const logger = defaultLogger.child({ name: 'executor' });
|
|
9
|
+
let __executor_worker;
|
|
10
|
+
const getWorker = async () => {
|
|
11
|
+
if (__executor_worker)
|
|
12
|
+
return __executor_worker;
|
|
13
|
+
const isNode = typeof process !== 'undefined' && process?.versions?.node; // true for node or bun
|
|
14
|
+
if (isNode) {
|
|
15
|
+
__executor_worker = import('./node-worker').then(({ startWorker }) => startWorker());
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
__executor_worker = import('./browser-worker').then(({ startWorker }) => startWorker());
|
|
19
|
+
}
|
|
20
|
+
return __executor_worker;
|
|
21
|
+
};
|
|
22
|
+
export const getRuntimeVersion = _.memoize(async (code) => {
|
|
23
|
+
const worker = await getWorker();
|
|
24
|
+
return worker.remote.getRuntimeVersion(code).then((version) => {
|
|
25
|
+
version.specName = hexToString(version.specName);
|
|
26
|
+
version.implName = hexToString(version.implName);
|
|
27
|
+
return version;
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
// trie_version: 0 for old trie, 1 for new trie
|
|
31
|
+
export const calculateStateRoot = async (entries, trie_version) => {
|
|
32
|
+
const worker = await getWorker();
|
|
33
|
+
return worker.remote.calculateStateRoot(entries, trie_version);
|
|
34
|
+
};
|
|
35
|
+
export const decodeProof = async (trieRootHash, keys, nodes) => {
|
|
36
|
+
const worker = await getWorker();
|
|
37
|
+
const result = await worker.remote.decodeProof(trieRootHash, keys, nodes);
|
|
38
|
+
return result.reduce((accum, [key, value]) => {
|
|
39
|
+
accum[key] = value;
|
|
40
|
+
return accum;
|
|
41
|
+
}, {});
|
|
42
|
+
};
|
|
43
|
+
export const createProof = async (nodes, entries) => {
|
|
44
|
+
const worker = await getWorker();
|
|
45
|
+
const [trieRootHash, newNodes] = await worker.remote.createProof(nodes, entries);
|
|
46
|
+
return { trieRootHash, nodes: newNodes };
|
|
47
|
+
};
|
|
48
|
+
export const runTask = async (task, callback = emptyTaskHandler) => {
|
|
49
|
+
const worker = await getWorker();
|
|
50
|
+
logger.trace(truncate(task), 'taskRun');
|
|
51
|
+
const response = await worker.remote.runTask(task, Comlink.proxy(callback));
|
|
52
|
+
if ('Call' in response) {
|
|
53
|
+
logger.trace(truncate(response.Call), 'taskResponse');
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
logger.trace({ response }, 'taskResponse');
|
|
57
|
+
}
|
|
58
|
+
return response;
|
|
59
|
+
};
|
|
60
|
+
export const taskHandler = (block) => {
|
|
61
|
+
return {
|
|
62
|
+
getStorage: async function (key) {
|
|
63
|
+
return block.get(key);
|
|
64
|
+
},
|
|
65
|
+
getStateRoot: async function () {
|
|
66
|
+
const header = await block.header;
|
|
67
|
+
return header.stateRoot.toHex();
|
|
68
|
+
},
|
|
69
|
+
getNextKey: async function (prefix, key) {
|
|
70
|
+
const [nextKey] = await block.getKeysPaged({
|
|
71
|
+
prefix: prefix.length === 2 /** 0x */ ? key.slice(0, PREFIX_LENGTH) : prefix,
|
|
72
|
+
pageSize: 1,
|
|
73
|
+
startKey: key,
|
|
74
|
+
});
|
|
75
|
+
return nextKey && stripChildPrefix(nextKey);
|
|
76
|
+
},
|
|
77
|
+
offchainGetStorage: async function (key) {
|
|
78
|
+
if (!block.chain.offchainWorker)
|
|
79
|
+
throw new Error('offchain worker not found');
|
|
80
|
+
return block.chain.offchainWorker.get(key);
|
|
81
|
+
},
|
|
82
|
+
offchainTimestamp: async function () {
|
|
83
|
+
return Date.now();
|
|
84
|
+
},
|
|
85
|
+
offchainRandomSeed: async function () {
|
|
86
|
+
return randomAsHex(32);
|
|
87
|
+
},
|
|
88
|
+
offchainSubmitTransaction: async function (tx) {
|
|
89
|
+
if (!block.chain.offchainWorker)
|
|
90
|
+
throw new Error('offchain worker not found');
|
|
91
|
+
try {
|
|
92
|
+
const hash = await block.chain.offchainWorker.pushExtrinsic(block, tx);
|
|
93
|
+
logger.trace({ hash }, 'offchainSubmitTransaction');
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
logger.trace({ error }, 'offchainSubmitTransaction');
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
export const emptyTaskHandler = {
|
|
104
|
+
getStorage: async function (_key) {
|
|
105
|
+
throw new Error('Method not implemented');
|
|
106
|
+
},
|
|
107
|
+
getStateRoot: async function () {
|
|
108
|
+
throw new Error('Method not implemented');
|
|
109
|
+
},
|
|
110
|
+
getNextKey: async function (_prefix, _key) {
|
|
111
|
+
throw new Error('Method not implemented');
|
|
112
|
+
},
|
|
113
|
+
offchainGetStorage: async function (_key) {
|
|
114
|
+
throw new Error('Method not implemented');
|
|
115
|
+
},
|
|
116
|
+
offchainTimestamp: async function () {
|
|
117
|
+
throw new Error('Method not implemented');
|
|
118
|
+
},
|
|
119
|
+
offchainRandomSeed: async function () {
|
|
120
|
+
throw new Error('Method not implemented');
|
|
121
|
+
},
|
|
122
|
+
offchainSubmitTransaction: async function (_tx) {
|
|
123
|
+
throw new Error('Method not implemented');
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
export const getAuraSlotDuration = _.memoize(async (wasm, registry) => {
|
|
127
|
+
const result = await runTask({
|
|
128
|
+
wasm,
|
|
129
|
+
calls: [['AuraApi_slot_duration', []]],
|
|
130
|
+
mockSignatureHost: false,
|
|
131
|
+
allowUnresolvedImports: false,
|
|
132
|
+
runtimeLogLevel: 0,
|
|
133
|
+
});
|
|
134
|
+
if ('Error' in result)
|
|
135
|
+
throw new Error(result.Error);
|
|
136
|
+
const slotDuration = registry.createType('u64', hexToU8a(result.Call.result)).toNumber();
|
|
137
|
+
return slotDuration;
|
|
138
|
+
});
|
|
139
|
+
export const releaseWorker = async () => {
|
|
140
|
+
if (!__executor_worker)
|
|
141
|
+
return;
|
|
142
|
+
const executor = await __executor_worker;
|
|
143
|
+
executor.remote[Comlink.releaseProxy]();
|
|
144
|
+
await executor.terminate();
|
|
145
|
+
__executor_worker = undefined;
|
|
146
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as Comlink from 'comlink'
|
|
2
|
+
import * as pkg from '@acala-network/chopsticks-executor'
|
|
3
|
+
import { parentPort } from 'node:worker_threads'
|
|
4
|
+
import nodeEndpoint from 'comlink/dist/umd/node-adapter.js'
|
|
5
|
+
|
|
6
|
+
const getRuntimeVersion = async (code) => {
|
|
7
|
+
return pkg.get_runtime_version(code)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// trie_version: 0 for old trie, 1 for new trie
|
|
11
|
+
const calculateStateRoot = async (entries, trie_version) => {
|
|
12
|
+
return pkg.calculate_state_root(entries, trie_version)
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const decodeProof = async (trieRootHash, keys, nodes) => {
|
|
16
|
+
return pkg.decode_proof(trieRootHash, keys, nodes)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const createProof = async (nodes, entries) => {
|
|
20
|
+
return pkg.create_proof(nodes, entries)
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const runTask = async (task, callback) => {
|
|
24
|
+
return pkg.run_task(task, callback, process.env.RUST_LOG)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const wasmExecutor = { runTask, getRuntimeVersion, calculateStateRoot, createProof, decodeProof }
|
|
28
|
+
|
|
29
|
+
Comlink.expose(wasmExecutor, nodeEndpoint(parentPort))
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { wrap } from 'comlink';
|
|
2
|
+
import nodeEndpoint from 'comlink/dist/umd/node-adapter.js';
|
|
3
|
+
import threads from 'node:worker_threads';
|
|
4
|
+
import url from 'node:url';
|
|
5
|
+
export const startWorker = async () => {
|
|
6
|
+
const worker = new threads.Worker(url.resolve(__filename, 'node-wasm-executor.mjs'), {
|
|
7
|
+
name: 'chopsticks-wasm-executor',
|
|
8
|
+
});
|
|
9
|
+
return {
|
|
10
|
+
remote: wrap(nodeEndpoint(worker)),
|
|
11
|
+
terminate: async () => {
|
|
12
|
+
await worker.terminate();
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { hexToU8a } from '@polkadot/util';
|
|
2
|
+
import { compactHex, getParaId } from '../utils';
|
|
3
|
+
import { logger } from '.';
|
|
4
|
+
import { setStorage } from '../utils/set-storage';
|
|
5
|
+
export const connectDownward = async (relaychain, parachain) => {
|
|
6
|
+
const meta = await relaychain.head.meta;
|
|
7
|
+
const paraId = await getParaId(parachain);
|
|
8
|
+
const downwardMessageQueuesKey = compactHex(meta.query.dmp.downwardMessageQueues(paraId));
|
|
9
|
+
await relaychain.headState.subscribeStorage([downwardMessageQueuesKey], async (head, pairs) => {
|
|
10
|
+
const value = pairs[0][1];
|
|
11
|
+
if (!value)
|
|
12
|
+
return;
|
|
13
|
+
const meta = await head.meta;
|
|
14
|
+
const downwardMessageQueuesKey = compactHex(meta.query.dmp.downwardMessageQueues(paraId));
|
|
15
|
+
// clear relaychain message queue
|
|
16
|
+
await setStorage(relaychain, [[downwardMessageQueuesKey, null]], head.hash);
|
|
17
|
+
const downwardMessages = meta.registry
|
|
18
|
+
.createType('Vec<PolkadotCorePrimitivesInboundDownwardMessage>', hexToU8a(value))
|
|
19
|
+
.toJSON();
|
|
20
|
+
if (downwardMessages.length === 0)
|
|
21
|
+
return;
|
|
22
|
+
logger.debug({ downwardMessages }, 'downward_message');
|
|
23
|
+
parachain.submitDownwardMessages(downwardMessages);
|
|
24
|
+
});
|
|
25
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { hexToU8a } from '@polkadot/util';
|
|
2
|
+
import { compactHex } from '../utils';
|
|
3
|
+
import { logger } from '.';
|
|
4
|
+
export const connectHorizontal = async (parachains) => {
|
|
5
|
+
for (const [id, chain] of Object.entries(parachains)) {
|
|
6
|
+
const meta = await chain.head.meta;
|
|
7
|
+
const hrmpOutboundMessagesKey = compactHex(meta.query.parachainSystem.hrmpOutboundMessages());
|
|
8
|
+
await chain.headState.subscribeStorage([hrmpOutboundMessagesKey], async (head, pairs) => {
|
|
9
|
+
const value = pairs[0][1];
|
|
10
|
+
if (!value)
|
|
11
|
+
return;
|
|
12
|
+
const meta = await head.meta;
|
|
13
|
+
const outboundHrmpMessage = meta.registry
|
|
14
|
+
.createType('Vec<PolkadotCorePrimitivesOutboundHrmpMessage>', hexToU8a(value))
|
|
15
|
+
.toJSON();
|
|
16
|
+
logger.info({ outboundHrmpMessage }, 'outboundHrmpMessage');
|
|
17
|
+
for (const { recipient, data } of outboundHrmpMessage) {
|
|
18
|
+
const receiver = parachains[recipient];
|
|
19
|
+
if (receiver) {
|
|
20
|
+
receiver.submitHorizontalMessages(Number(id), [{ sentAt: head.number, data }]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { connectDownward } from './downward';
|
|
2
|
+
import { connectHorizontal } from './horizontal';
|
|
3
|
+
import { connectUpward } from './upward';
|
|
4
|
+
import { defaultLogger } from '../logger';
|
|
5
|
+
import { getParaId } from '../utils';
|
|
6
|
+
export const logger = defaultLogger.child({ name: 'xcm' });
|
|
7
|
+
export const connectVertical = async (relaychain, parachain) => {
|
|
8
|
+
await connectDownward(relaychain, parachain);
|
|
9
|
+
await connectUpward(parachain, relaychain);
|
|
10
|
+
logger.info(`Connected relaychain '${await relaychain.api.getSystemChain()}' with parachain '${await parachain.api.getSystemChain()}'`);
|
|
11
|
+
};
|
|
12
|
+
export const connectParachains = async (parachains) => {
|
|
13
|
+
const list = {};
|
|
14
|
+
for (const chain of parachains) {
|
|
15
|
+
const paraId = await getParaId(chain);
|
|
16
|
+
list[paraId.toNumber()] = chain;
|
|
17
|
+
}
|
|
18
|
+
await connectHorizontal(list);
|
|
19
|
+
logger.info(`Connected parachains [${Object.keys(list)}]`);
|
|
20
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { hexToU8a } from '@polkadot/util';
|
|
2
|
+
import { compactHex, getParaId } from '../utils';
|
|
3
|
+
export const connectUpward = async (parachain, relaychain) => {
|
|
4
|
+
const meta = await parachain.head.meta;
|
|
5
|
+
const paraId = (await getParaId(parachain)).toNumber();
|
|
6
|
+
const upwardMessagesKey = compactHex(meta.query.parachainSystem.upwardMessages());
|
|
7
|
+
await parachain.headState.subscribeStorage([upwardMessagesKey], async (_head, pairs) => {
|
|
8
|
+
const value = pairs[0][1];
|
|
9
|
+
if (!value)
|
|
10
|
+
return;
|
|
11
|
+
const meta = await relaychain.head.meta;
|
|
12
|
+
const upwardMessages = meta.registry.createType('Vec<Bytes>', hexToU8a(value));
|
|
13
|
+
if (upwardMessages.length === 0)
|
|
14
|
+
return;
|
|
15
|
+
relaychain.submitUpwardMessages(paraId, upwardMessages.map((x) => x.toHex()));
|
|
16
|
+
});
|
|
17
|
+
};
|
|
@@ -26,7 +26,7 @@ export declare class GenesisProvider implements ProviderInterface {
|
|
|
26
26
|
get blockHash(): HexString;
|
|
27
27
|
getHeader: () => Promise<{
|
|
28
28
|
blockHash: `0x${string}`;
|
|
29
|
-
number:
|
|
29
|
+
number: `0x${string}`;
|
|
30
30
|
stateRoot: `0x${string}`;
|
|
31
31
|
digest: {
|
|
32
32
|
logs: never[];
|
|
@@ -36,7 +36,7 @@ export declare class GenesisProvider implements ProviderInterface {
|
|
|
36
36
|
block: {
|
|
37
37
|
header: {
|
|
38
38
|
blockHash: `0x${string}`;
|
|
39
|
-
number:
|
|
39
|
+
number: `0x${string}`;
|
|
40
40
|
stateRoot: `0x${string}`;
|
|
41
41
|
digest: {
|
|
42
42
|
logs: never[];
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Chopsticks core package. A common package for usage in both server and browser.
|
|
3
|
+
* It contains a local blockchain implementation, a transaction pool, a runtime executor and more!
|
|
4
|
+
*
|
|
5
|
+
* @privateRemarks
|
|
6
|
+
* Above is the package description for `chopsticks-core` package.
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
export * from './api';
|
|
11
|
+
export * from './blockchain';
|
|
12
|
+
export * from './blockchain/block';
|
|
13
|
+
export * from './blockchain/block-builder';
|
|
14
|
+
export * from './blockchain/txpool';
|
|
15
|
+
export * from './blockchain/storage-layer';
|
|
16
|
+
export * from './blockchain/head-state';
|
|
17
|
+
export * from './utils';
|
|
18
|
+
export * from './wasm-executor';
|
|
19
|
+
export * from './schema';
|
|
20
|
+
export * from './xcm';
|
|
21
|
+
export * from './setup';
|
|
22
|
+
export * from './database';
|
|
23
|
+
export * from './blockchain/inherent';
|
|
24
|
+
export * from './logger';
|
|
25
|
+
export * from './offchain';
|
|
26
|
+
export * from './chopsticks-provider';
|
|
27
|
+
export * from './genesis-provider';
|
|
28
|
+
export * from './rpc';
|
|
@@ -21,3 +21,4 @@ export declare const prefixedChildKey: (prefix: HexString, key: HexString) => st
|
|
|
21
21
|
export declare const isPrefixedChildKey: (key: HexString) => boolean;
|
|
22
22
|
export declare const splitChildKey: (key: HexString) => never[] | [`0x${string}`, `0x${string}`];
|
|
23
23
|
export declare const stripChildPrefix: (key: HexString) => `0x${string}`;
|
|
24
|
+
export declare const printRuntimeLogs: (logs: string[]) => void;
|
package/package.json
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@acala-network/chopsticks-core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"author": "Acala Developers <hello@acala.network>",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"clean": "rm -rf
|
|
8
|
-
"build": "tsc -p ./tsconfig.json
|
|
9
|
-
"copyfiles": "cp -r src/wasm-executor/*.mjs
|
|
7
|
+
"clean": "rm -rf dist",
|
|
8
|
+
"build": "yarn clean && tsc -p ./tsconfig.json && tsc -p ./tsconfig.esm.json && yarn copyfiles",
|
|
9
|
+
"copyfiles": "cp -r src/wasm-executor/*.mjs dist/cjs/wasm-executor/ && cp -r src/wasm-executor/*.mjs dist/esm/wasm-executor/",
|
|
10
10
|
"docs:prep": "typedoc"
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@acala-network/chopsticks-executor": "0.
|
|
13
|
+
"@acala-network/chopsticks-executor": "0.9.0",
|
|
14
14
|
"@polkadot/api": "^10.10.1",
|
|
15
15
|
"@polkadot/util-crypto": "^12.5.1",
|
|
16
16
|
"comlink": "^4.4.1",
|
|
@@ -25,23 +25,32 @@
|
|
|
25
25
|
"typescript": "^5.1.6"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
|
-
"
|
|
28
|
+
"dist/esm/**",
|
|
29
|
+
"dist/cjs/**",
|
|
30
|
+
"dist/types/**"
|
|
29
31
|
],
|
|
30
|
-
"main": "./
|
|
31
|
-
"
|
|
32
|
+
"main": "./dist/cjs/index.js",
|
|
33
|
+
"module": "./dist/esm/index.js",
|
|
34
|
+
"types": "./dist/types/index.d.ts",
|
|
32
35
|
"exports": {
|
|
33
36
|
".": {
|
|
34
|
-
"types": "./
|
|
35
|
-
"
|
|
37
|
+
"types": "./dist/types/index.d.ts",
|
|
38
|
+
"require": "./dist/cjs/index.js",
|
|
39
|
+
"import": "./dist/esm/index.js",
|
|
40
|
+
"default": "./dist/esm/index.js"
|
|
36
41
|
},
|
|
37
42
|
"./*": {
|
|
38
|
-
"types": "./
|
|
39
|
-
"
|
|
43
|
+
"types": "./dist/esm/index.d.ts",
|
|
44
|
+
"require": "./dist/cjs/index.js",
|
|
45
|
+
"import": "./dist/esm/index.js",
|
|
46
|
+
"default": "./dist/esm/index.js"
|
|
40
47
|
},
|
|
41
48
|
"./package.json": "./package.json"
|
|
42
49
|
},
|
|
43
50
|
"browser": {
|
|
44
|
-
"./
|
|
45
|
-
"./
|
|
51
|
+
"./dist/cjs/wasm-executor/node-wasm-executor.mjs": "./dist/cjs/wasm-executor/browser-wasm-executor.mjs",
|
|
52
|
+
"./dist/cjs/wasm-executor/node-worker.js": "./dist/cjs/wasm-executor/browser-worker.js",
|
|
53
|
+
"./dist/esm/wasm-executor/node-wasm-executor.mjs": "./dist/esm/wasm-executor/browser-wasm-executor.mjs",
|
|
54
|
+
"./dist/esm/wasm-executor/node-worker.js": "./dist/esm/wasm-executor/browser-worker.js"
|
|
46
55
|
}
|
|
47
56
|
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|