@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,413 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _Blockchain_instances, _Blockchain_runtimeLogLevel, _Blockchain_txpool, _Blockchain_inherentProvider, _Blockchain_head, _Blockchain_blocksByNumber, _Blockchain_blocksByHash, _Blockchain_loadingBlocks, _Blockchain_maxMemoryBlockCount, _Blockchain_registerBlock;
|
|
13
|
+
import { blake2AsHex } from '@polkadot/util-crypto';
|
|
14
|
+
import { u8aConcat, u8aToHex } from '@polkadot/util';
|
|
15
|
+
import { Block } from './block';
|
|
16
|
+
import { TxPool } from './txpool';
|
|
17
|
+
import { HeadState } from './head-state';
|
|
18
|
+
import { OffchainWorker } from '../offchain';
|
|
19
|
+
import { compactHex } from '../utils';
|
|
20
|
+
import { defaultLogger } from '../logger';
|
|
21
|
+
import { dryRunExtrinsic, dryRunInherents } from './block-builder';
|
|
22
|
+
import { releaseWorker } from '../wasm-executor';
|
|
23
|
+
const logger = defaultLogger.child({ name: 'blockchain' });
|
|
24
|
+
/**
|
|
25
|
+
* Local blockchain which provides access to blocks, txpool and methods
|
|
26
|
+
* to manipulate the chain such as build blocks, submit extrinsics, xcm and more!
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
*
|
|
30
|
+
* ```ts
|
|
31
|
+
* const chain = new Blockchain({
|
|
32
|
+
* api,
|
|
33
|
+
* buildBlockMode: BuildBlockMode.Manual,
|
|
34
|
+
* inherentProvider: inherents,
|
|
35
|
+
* header: {
|
|
36
|
+
* hash: blockHash,
|
|
37
|
+
* number: Number(header.number),
|
|
38
|
+
* },
|
|
39
|
+
* mockSignatureHost: true,
|
|
40
|
+
* allowUnresolvedImports: true,
|
|
41
|
+
* registeredTypes: {},
|
|
42
|
+
* })
|
|
43
|
+
* // build a block
|
|
44
|
+
* chain.newBlock()
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export class Blockchain {
|
|
48
|
+
/**
|
|
49
|
+
* @param options - Options for instantiating the blockchain
|
|
50
|
+
*/
|
|
51
|
+
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost = false, allowUnresolvedImports = false, runtimeLogLevel = 0, registeredTypes = {}, offchainWorker = false, maxMemoryBlockCount = 500, }) {
|
|
52
|
+
_Blockchain_instances.add(this);
|
|
53
|
+
this.uid = Math.random().toString(36).substring(2);
|
|
54
|
+
_Blockchain_runtimeLogLevel.set(this, void 0);
|
|
55
|
+
_Blockchain_txpool.set(this, void 0);
|
|
56
|
+
_Blockchain_inherentProvider.set(this, void 0);
|
|
57
|
+
_Blockchain_head.set(this, void 0);
|
|
58
|
+
_Blockchain_blocksByNumber.set(this, new Map());
|
|
59
|
+
_Blockchain_blocksByHash.set(this, new Map());
|
|
60
|
+
_Blockchain_loadingBlocks.set(this, {}
|
|
61
|
+
/** For subscribing and managing the head state. */
|
|
62
|
+
);
|
|
63
|
+
_Blockchain_maxMemoryBlockCount.set(this, void 0);
|
|
64
|
+
this.api = api;
|
|
65
|
+
this.db = db;
|
|
66
|
+
this.mockSignatureHost = mockSignatureHost;
|
|
67
|
+
this.allowUnresolvedImports = allowUnresolvedImports;
|
|
68
|
+
__classPrivateFieldSet(this, _Blockchain_runtimeLogLevel, runtimeLogLevel, "f");
|
|
69
|
+
this.registeredTypes = registeredTypes;
|
|
70
|
+
__classPrivateFieldSet(this, _Blockchain_head, new Block(this, header.number, header.hash), "f");
|
|
71
|
+
__classPrivateFieldGet(this, _Blockchain_instances, "m", _Blockchain_registerBlock).call(this, __classPrivateFieldGet(this, _Blockchain_head, "f"));
|
|
72
|
+
__classPrivateFieldSet(this, _Blockchain_txpool, new TxPool(this, inherentProvider, buildBlockMode), "f");
|
|
73
|
+
__classPrivateFieldSet(this, _Blockchain_inherentProvider, inherentProvider, "f");
|
|
74
|
+
this.headState = new HeadState(__classPrivateFieldGet(this, _Blockchain_head, "f"));
|
|
75
|
+
if (offchainWorker) {
|
|
76
|
+
this.offchainWorker = new OffchainWorker();
|
|
77
|
+
}
|
|
78
|
+
__classPrivateFieldSet(this, _Blockchain_maxMemoryBlockCount, maxMemoryBlockCount, "f");
|
|
79
|
+
}
|
|
80
|
+
get head() {
|
|
81
|
+
return __classPrivateFieldGet(this, _Blockchain_head, "f");
|
|
82
|
+
}
|
|
83
|
+
get txPool() {
|
|
84
|
+
return __classPrivateFieldGet(this, _Blockchain_txpool, "f");
|
|
85
|
+
}
|
|
86
|
+
get runtimeLogLevel() {
|
|
87
|
+
return __classPrivateFieldGet(this, _Blockchain_runtimeLogLevel, "f");
|
|
88
|
+
}
|
|
89
|
+
set runtimeLogLevel(level) {
|
|
90
|
+
__classPrivateFieldSet(this, _Blockchain_runtimeLogLevel, level, "f");
|
|
91
|
+
logger.debug(`Runtime log level set to ${logger.level}`);
|
|
92
|
+
}
|
|
93
|
+
async saveBlockToDB(block) {
|
|
94
|
+
if (this.db) {
|
|
95
|
+
const { hash, number, header, extrinsics } = block;
|
|
96
|
+
// delete old ones with the same block number if any, keep the latest one
|
|
97
|
+
await this.db.saveBlock({
|
|
98
|
+
hash,
|
|
99
|
+
number,
|
|
100
|
+
header: (await header).toHex(),
|
|
101
|
+
extrinsics: await extrinsics,
|
|
102
|
+
parentHash: (await block.parentBlock)?.hash || null,
|
|
103
|
+
storageDiff: await block.storageDiff(),
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Try to load block from db and register it.
|
|
109
|
+
* If pass in number, get block by number, else get block by hash.
|
|
110
|
+
*/
|
|
111
|
+
async loadBlockFromDB(hashOrNumber) {
|
|
112
|
+
if (this.db) {
|
|
113
|
+
const blockData = typeof hashOrNumber === 'number'
|
|
114
|
+
? await this.db.queryBlockByNumber(hashOrNumber)
|
|
115
|
+
: await this.db.queryBlock(hashOrNumber);
|
|
116
|
+
if (blockData) {
|
|
117
|
+
const { hash, number, header, extrinsics } = blockData;
|
|
118
|
+
const parentHash = blockData.parentHash || undefined;
|
|
119
|
+
let parentBlock = parentHash ? __classPrivateFieldGet(this, _Blockchain_blocksByHash, "f").get(parentHash) : undefined;
|
|
120
|
+
if (!parentBlock) {
|
|
121
|
+
parentBlock = await this.getBlock(parentHash);
|
|
122
|
+
}
|
|
123
|
+
const storageDiff = blockData.storageDiff ?? undefined;
|
|
124
|
+
const registry = await this.head.registry;
|
|
125
|
+
const block = new Block(this, number, hash, parentBlock, {
|
|
126
|
+
header: registry.createType('Header', header),
|
|
127
|
+
extrinsics,
|
|
128
|
+
storage: parentBlock?.storage,
|
|
129
|
+
storageDiff,
|
|
130
|
+
});
|
|
131
|
+
__classPrivateFieldGet(this, _Blockchain_instances, "m", _Blockchain_registerBlock).call(this, block);
|
|
132
|
+
return block;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get block by number.
|
|
139
|
+
*/
|
|
140
|
+
async getBlockAt(number) {
|
|
141
|
+
if (number === null || number === undefined) {
|
|
142
|
+
return this.head;
|
|
143
|
+
}
|
|
144
|
+
if (number > __classPrivateFieldGet(this, _Blockchain_head, "f").number) {
|
|
145
|
+
return undefined;
|
|
146
|
+
}
|
|
147
|
+
if (!__classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").has(number)) {
|
|
148
|
+
const blockFromDB = await this.loadBlockFromDB(number);
|
|
149
|
+
if (blockFromDB) {
|
|
150
|
+
return blockFromDB;
|
|
151
|
+
}
|
|
152
|
+
const hash = await this.api.getBlockHash(number);
|
|
153
|
+
if (!hash) {
|
|
154
|
+
return undefined;
|
|
155
|
+
}
|
|
156
|
+
const block = new Block(this, number, hash);
|
|
157
|
+
__classPrivateFieldGet(this, _Blockchain_instances, "m", _Blockchain_registerBlock).call(this, block);
|
|
158
|
+
}
|
|
159
|
+
return __classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").get(number);
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Get block by hash.
|
|
163
|
+
*/
|
|
164
|
+
async getBlock(hash) {
|
|
165
|
+
await this.api.isReady;
|
|
166
|
+
if (hash == null) {
|
|
167
|
+
hash = this.head.hash;
|
|
168
|
+
}
|
|
169
|
+
if (!__classPrivateFieldGet(this, _Blockchain_blocksByHash, "f").has(hash)) {
|
|
170
|
+
const loadingBlock = __classPrivateFieldGet(this, _Blockchain_loadingBlocks, "f")[hash];
|
|
171
|
+
if (loadingBlock) {
|
|
172
|
+
await loadingBlock;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
const loadingBlock = (async () => {
|
|
176
|
+
try {
|
|
177
|
+
const blockFromDB = await this.loadBlockFromDB(hash);
|
|
178
|
+
if (!blockFromDB) {
|
|
179
|
+
const header = await this.api.getHeader(hash);
|
|
180
|
+
if (!header) {
|
|
181
|
+
throw new Error(`Block ${hash} not found`);
|
|
182
|
+
}
|
|
183
|
+
const block = new Block(this, Number(header.number), hash);
|
|
184
|
+
__classPrivateFieldGet(this, _Blockchain_instances, "m", _Blockchain_registerBlock).call(this, block);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
catch (e) {
|
|
188
|
+
logger.debug(`getBlock(${hash}) failed: ${e}`);
|
|
189
|
+
}
|
|
190
|
+
})();
|
|
191
|
+
__classPrivateFieldGet(this, _Blockchain_loadingBlocks, "f")[hash] = loadingBlock;
|
|
192
|
+
await loadingBlock;
|
|
193
|
+
delete __classPrivateFieldGet(this, _Blockchain_loadingBlocks, "f")[hash];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return __classPrivateFieldGet(this, _Blockchain_blocksByHash, "f").get(hash);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get all blocks in memory.
|
|
200
|
+
*/
|
|
201
|
+
blocksInMemory() {
|
|
202
|
+
return Array.from(__classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").values());
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Remove block from memory and db.
|
|
206
|
+
*/
|
|
207
|
+
async unregisterBlock(block) {
|
|
208
|
+
if (block.hash === this.head.hash) {
|
|
209
|
+
throw new Error('Cannot unregister head block');
|
|
210
|
+
}
|
|
211
|
+
if (__classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").get(block.number)?.hash === block.hash) {
|
|
212
|
+
__classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").delete(block.number);
|
|
213
|
+
}
|
|
214
|
+
__classPrivateFieldGet(this, _Blockchain_blocksByHash, "f").delete(block.hash);
|
|
215
|
+
// delete from db
|
|
216
|
+
if (this.db) {
|
|
217
|
+
await this.db.deleteBlock(block.hash);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
async onNewBlock(block) {
|
|
221
|
+
await this.setHead(block);
|
|
222
|
+
await this.saveBlockToDB(block);
|
|
223
|
+
}
|
|
224
|
+
/**
|
|
225
|
+
* Set block as head.
|
|
226
|
+
*/
|
|
227
|
+
async setHead(block) {
|
|
228
|
+
logger.debug({
|
|
229
|
+
number: block.number,
|
|
230
|
+
hash: block.hash,
|
|
231
|
+
}, 'setHead');
|
|
232
|
+
__classPrivateFieldSet(this, _Blockchain_head, block, "f");
|
|
233
|
+
__classPrivateFieldGet(this, _Blockchain_instances, "m", _Blockchain_registerBlock).call(this, block);
|
|
234
|
+
await this.headState.setHead(block);
|
|
235
|
+
if (this.offchainWorker) {
|
|
236
|
+
await this.offchainWorker.run(block);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Submit extrinsic to txpool.
|
|
241
|
+
*/
|
|
242
|
+
async submitExtrinsic(extrinsic) {
|
|
243
|
+
const validity = await this.validateExtrinsic(extrinsic);
|
|
244
|
+
if (validity.isOk) {
|
|
245
|
+
await __classPrivateFieldGet(this, _Blockchain_txpool, "f").submitExtrinsic(extrinsic);
|
|
246
|
+
return blake2AsHex(extrinsic, 256);
|
|
247
|
+
}
|
|
248
|
+
throw validity.asErr;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* Validate extrinsic by calling `TaggedTransactionQueue_validate_transaction`.
|
|
252
|
+
*/
|
|
253
|
+
async validateExtrinsic(extrinsic, source = '0x02' /** External */) {
|
|
254
|
+
const args = u8aToHex(u8aConcat(source, extrinsic, this.head.hash));
|
|
255
|
+
const res = await this.head.call('TaggedTransactionQueue_validate_transaction', [args]);
|
|
256
|
+
const registry = await this.head.registry;
|
|
257
|
+
return registry.createType('TransactionValidity', res.result);
|
|
258
|
+
}
|
|
259
|
+
submitUpwardMessages(id, ump) {
|
|
260
|
+
__classPrivateFieldGet(this, _Blockchain_txpool, "f").submitUpwardMessages(id, ump);
|
|
261
|
+
logger.debug({ id, ump }, 'submitUpwardMessages');
|
|
262
|
+
}
|
|
263
|
+
submitDownwardMessages(dmp) {
|
|
264
|
+
__classPrivateFieldGet(this, _Blockchain_txpool, "f").submitDownwardMessages(dmp);
|
|
265
|
+
logger.debug({ dmp }, 'submitDownwardMessages');
|
|
266
|
+
}
|
|
267
|
+
submitHorizontalMessages(id, hrmp) {
|
|
268
|
+
__classPrivateFieldGet(this, _Blockchain_txpool, "f").submitHorizontalMessages(id, hrmp);
|
|
269
|
+
logger.debug({ id, hrmp }, 'submitHorizontalMessages');
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Build a new block with optional params. Use this when you don't have all the {@link BuildBlockParams}
|
|
273
|
+
*/
|
|
274
|
+
async newBlock(params) {
|
|
275
|
+
await __classPrivateFieldGet(this, _Blockchain_txpool, "f").buildBlock(params);
|
|
276
|
+
return __classPrivateFieldGet(this, _Blockchain_head, "f");
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* Build a new block with {@link BuildBlockParams}.
|
|
280
|
+
*/
|
|
281
|
+
async newBlockWithParams(params) {
|
|
282
|
+
await __classPrivateFieldGet(this, _Blockchain_txpool, "f").buildBlockWithParams(params);
|
|
283
|
+
return __classPrivateFieldGet(this, _Blockchain_head, "f");
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Get the upcoming blocks.
|
|
287
|
+
*/
|
|
288
|
+
async upcomingBlocks() {
|
|
289
|
+
return __classPrivateFieldGet(this, _Blockchain_txpool, "f").upcomingBlocks();
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Dry run extrinsic in block `at`.
|
|
293
|
+
*/
|
|
294
|
+
async dryRunExtrinsic(extrinsic, at) {
|
|
295
|
+
await this.api.isReady;
|
|
296
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
297
|
+
if (!head) {
|
|
298
|
+
throw new Error(`Cannot find block ${at}`);
|
|
299
|
+
}
|
|
300
|
+
const registry = await head.registry;
|
|
301
|
+
const inherents = await __classPrivateFieldGet(this, _Blockchain_inherentProvider, "f").createInherents(head, {
|
|
302
|
+
transactions: [],
|
|
303
|
+
downwardMessages: [],
|
|
304
|
+
upwardMessages: [],
|
|
305
|
+
horizontalMessages: {},
|
|
306
|
+
});
|
|
307
|
+
const { result, storageDiff } = await dryRunExtrinsic(head, inherents, extrinsic);
|
|
308
|
+
const outcome = registry.createType('ApplyExtrinsicResult', result);
|
|
309
|
+
return { outcome, storageDiff };
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Dry run hrmp messages in block `at`.
|
|
313
|
+
* Return the storage diff.
|
|
314
|
+
*/
|
|
315
|
+
async dryRunHrmp(hrmp, at) {
|
|
316
|
+
await this.api.isReady;
|
|
317
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
318
|
+
if (!head) {
|
|
319
|
+
throw new Error(`Cannot find block ${at}`);
|
|
320
|
+
}
|
|
321
|
+
const inherents = await __classPrivateFieldGet(this, _Blockchain_inherentProvider, "f").createInherents(head, {
|
|
322
|
+
transactions: [],
|
|
323
|
+
downwardMessages: [],
|
|
324
|
+
upwardMessages: [],
|
|
325
|
+
horizontalMessages: hrmp,
|
|
326
|
+
});
|
|
327
|
+
return dryRunInherents(head, inherents);
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Dry run dmp messages in block `at`.
|
|
331
|
+
* Return the storage diff.
|
|
332
|
+
*/
|
|
333
|
+
async dryRunDmp(dmp, at) {
|
|
334
|
+
await this.api.isReady;
|
|
335
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
336
|
+
if (!head) {
|
|
337
|
+
throw new Error(`Cannot find block ${at}`);
|
|
338
|
+
}
|
|
339
|
+
const inherents = await __classPrivateFieldGet(this, _Blockchain_inherentProvider, "f").createInherents(head, {
|
|
340
|
+
transactions: [],
|
|
341
|
+
downwardMessages: dmp,
|
|
342
|
+
upwardMessages: [],
|
|
343
|
+
horizontalMessages: {},
|
|
344
|
+
});
|
|
345
|
+
return dryRunInherents(head, inherents);
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Dry run ump messages in block `at`.
|
|
349
|
+
* Return the storage diff.
|
|
350
|
+
*/
|
|
351
|
+
async dryRunUmp(ump, at) {
|
|
352
|
+
await this.api.isReady;
|
|
353
|
+
const head = at ? await this.getBlock(at) : this.head;
|
|
354
|
+
if (!head) {
|
|
355
|
+
throw new Error(`Cannot find block ${at}`);
|
|
356
|
+
}
|
|
357
|
+
const meta = await head.meta;
|
|
358
|
+
const needsDispatch = meta.registry.createType('Vec<u32>', Object.keys(ump));
|
|
359
|
+
const storageValues = [
|
|
360
|
+
[compactHex(meta.query.ump.needsDispatch()), needsDispatch.toHex()],
|
|
361
|
+
];
|
|
362
|
+
for (const [paraId, messages] of Object.entries(ump)) {
|
|
363
|
+
const upwardMessages = meta.registry.createType('Vec<Bytes>', messages);
|
|
364
|
+
if (upwardMessages.length === 0)
|
|
365
|
+
throw new Error('No upward meesage');
|
|
366
|
+
const queueSize = meta.registry.createType('(u32, u32)', [
|
|
367
|
+
upwardMessages.length,
|
|
368
|
+
upwardMessages.map((x) => x.byteLength).reduce((s, i) => s + i, 0),
|
|
369
|
+
]);
|
|
370
|
+
storageValues.push([compactHex(meta.query.ump.relayDispatchQueues(paraId)), upwardMessages.toHex()]);
|
|
371
|
+
storageValues.push([compactHex(meta.query.ump.relayDispatchQueueSize(paraId)), queueSize.toHex()]);
|
|
372
|
+
}
|
|
373
|
+
head.pushStorageLayer().setAll(storageValues);
|
|
374
|
+
const inherents = await __classPrivateFieldGet(this, _Blockchain_inherentProvider, "f").createInherents(head, {
|
|
375
|
+
transactions: [],
|
|
376
|
+
downwardMessages: [],
|
|
377
|
+
upwardMessages: [],
|
|
378
|
+
horizontalMessages: {},
|
|
379
|
+
});
|
|
380
|
+
return dryRunInherents(head, inherents);
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Get inherents of head.
|
|
384
|
+
*/
|
|
385
|
+
async getInherents() {
|
|
386
|
+
await this.api.isReady;
|
|
387
|
+
const inherents = await __classPrivateFieldGet(this, _Blockchain_inherentProvider, "f").createInherents(this.head, {
|
|
388
|
+
transactions: [],
|
|
389
|
+
downwardMessages: [],
|
|
390
|
+
upwardMessages: [],
|
|
391
|
+
horizontalMessages: {},
|
|
392
|
+
});
|
|
393
|
+
return inherents;
|
|
394
|
+
}
|
|
395
|
+
/**
|
|
396
|
+
* Close the db and release worker.
|
|
397
|
+
*/
|
|
398
|
+
async close() {
|
|
399
|
+
await releaseWorker();
|
|
400
|
+
await this.api.disconnect();
|
|
401
|
+
await this.db?.close();
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
_Blockchain_runtimeLogLevel = new WeakMap(), _Blockchain_txpool = new WeakMap(), _Blockchain_inherentProvider = new WeakMap(), _Blockchain_head = new WeakMap(), _Blockchain_blocksByNumber = new WeakMap(), _Blockchain_blocksByHash = new WeakMap(), _Blockchain_loadingBlocks = new WeakMap(), _Blockchain_maxMemoryBlockCount = new WeakMap(), _Blockchain_instances = new WeakSet(), _Blockchain_registerBlock = function _Blockchain_registerBlock(block) {
|
|
405
|
+
// if exceed max memory block count, delete the oldest block
|
|
406
|
+
if (__classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").size === __classPrivateFieldGet(this, _Blockchain_maxMemoryBlockCount, "f")) {
|
|
407
|
+
const { hash, number } = __classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").values().next().value;
|
|
408
|
+
__classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").delete(number);
|
|
409
|
+
__classPrivateFieldGet(this, _Blockchain_blocksByHash, "f").delete(hash);
|
|
410
|
+
}
|
|
411
|
+
__classPrivateFieldGet(this, _Blockchain_blocksByNumber, "f").set(block.number, block);
|
|
412
|
+
__classPrivateFieldGet(this, _Blockchain_blocksByHash, "f").set(block.hash, block);
|
|
413
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
|
|
2
|
+
if (kind === "m") throw new TypeError("Private method is not writable");
|
|
3
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
|
|
4
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
5
|
+
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
6
|
+
};
|
|
7
|
+
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
8
|
+
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
9
|
+
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
10
|
+
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
11
|
+
};
|
|
12
|
+
var _InherentProviders_base, _InherentProviders_providers;
|
|
13
|
+
import { GenericExtrinsic } from '@polkadot/types';
|
|
14
|
+
import { getCurrentTimestamp, getSlotDuration } from '../../utils/time-travel';
|
|
15
|
+
export { SetValidationData } from './parachain/validation-data';
|
|
16
|
+
export { ParaInherentEnter } from './para-enter';
|
|
17
|
+
export { SetBabeRandomness } from './parachain/babe-randomness';
|
|
18
|
+
export { SetNimbusAuthorInherent } from './parachain/nimbus-author-inherent';
|
|
19
|
+
export class SetTimestamp {
|
|
20
|
+
async createInherents(parent) {
|
|
21
|
+
const meta = await parent.meta;
|
|
22
|
+
const slotDuration = await getSlotDuration(parent.chain);
|
|
23
|
+
const currentTimestamp = await getCurrentTimestamp(parent.chain);
|
|
24
|
+
return [new GenericExtrinsic(meta.registry, meta.tx.timestamp.set(currentTimestamp + BigInt(slotDuration))).toHex()];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export class InherentProviders {
|
|
28
|
+
constructor(base, providers) {
|
|
29
|
+
_InherentProviders_base.set(this, void 0);
|
|
30
|
+
_InherentProviders_providers.set(this, void 0);
|
|
31
|
+
__classPrivateFieldSet(this, _InherentProviders_base, base, "f");
|
|
32
|
+
__classPrivateFieldSet(this, _InherentProviders_providers, providers, "f");
|
|
33
|
+
}
|
|
34
|
+
async createInherents(parent, params) {
|
|
35
|
+
const base = await __classPrivateFieldGet(this, _InherentProviders_base, "f").createInherents(parent, params);
|
|
36
|
+
const extra = await Promise.all(__classPrivateFieldGet(this, _InherentProviders_providers, "f").map((provider) => provider.createInherents(parent, params)));
|
|
37
|
+
return [...base, ...extra.flat()];
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
_InherentProviders_base = new WeakMap(), _InherentProviders_providers = new WeakMap();
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { GenericExtrinsic } from '@polkadot/types';
|
|
2
|
+
export class ParaInherentEnter {
|
|
3
|
+
async createInherents(parent, _params) {
|
|
4
|
+
const meta = await parent.meta;
|
|
5
|
+
if (!meta.tx.paraInherent?.enter) {
|
|
6
|
+
return [];
|
|
7
|
+
}
|
|
8
|
+
const extrinsics = await parent.extrinsics;
|
|
9
|
+
const paraEnterExtrinsic = extrinsics.find((extrinsic) => {
|
|
10
|
+
const firstArg = meta.registry.createType('GenericExtrinsic', extrinsic)?.args?.[0];
|
|
11
|
+
return firstArg && 'bitfields' in firstArg;
|
|
12
|
+
});
|
|
13
|
+
if (!paraEnterExtrinsic) {
|
|
14
|
+
throw new Error('Missing paraInherent data from block');
|
|
15
|
+
}
|
|
16
|
+
const extrinsic = meta.registry
|
|
17
|
+
.createType('GenericExtrinsic', paraEnterExtrinsic)
|
|
18
|
+
.args[0].toJSON();
|
|
19
|
+
const parentHeader = (await parent.header).toJSON();
|
|
20
|
+
const newData = {
|
|
21
|
+
...extrinsic,
|
|
22
|
+
bitfields: [],
|
|
23
|
+
backedCandidates: [],
|
|
24
|
+
parentHeader,
|
|
25
|
+
};
|
|
26
|
+
// TODO: fill with data
|
|
27
|
+
return [new GenericExtrinsic(meta.registry, meta.tx.paraInherent.enter(newData)).toHex()];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GenericExtrinsic } from '@polkadot/types';
|
|
2
|
+
// Support for Moonbeam pallet-randomness mandatory inherent
|
|
3
|
+
export class SetBabeRandomness {
|
|
4
|
+
async createInherents(parent, _params) {
|
|
5
|
+
const meta = await parent.meta;
|
|
6
|
+
if (!meta.tx.randomness?.setBabeRandomnessResults) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
return [new GenericExtrinsic(meta.registry, meta.tx.randomness.setBabeRandomnessResults()).toHex()];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { GenericExtrinsic } from '@polkadot/types';
|
|
2
|
+
// Support for Nimbus Author Inherent
|
|
3
|
+
export class SetNimbusAuthorInherent {
|
|
4
|
+
async createInherents(parent, _params) {
|
|
5
|
+
const meta = await parent.meta;
|
|
6
|
+
if (!meta.tx.authorInherent?.kickOffAuthorshipValidation) {
|
|
7
|
+
return [];
|
|
8
|
+
}
|
|
9
|
+
return [new GenericExtrinsic(meta.registry, meta.tx.authorInherent.kickOffAuthorshipValidation()).toHex()];
|
|
10
|
+
}
|
|
11
|
+
}
|