@acala-network/chopsticks 0.2.3 → 0.3.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.
Files changed (57) hide show
  1. package/README.md +6 -0
  2. package/dist/api.d.ts +3 -2
  3. package/dist/api.js +15 -20
  4. package/dist/blockchain/block-builder.d.ts +4 -0
  5. package/dist/blockchain/block-builder.js +71 -0
  6. package/dist/blockchain/block.d.ts +5 -3
  7. package/dist/blockchain/block.js +22 -23
  8. package/dist/blockchain/head-state.d.ts +4 -2
  9. package/dist/blockchain/head-state.js +13 -7
  10. package/dist/blockchain/index.d.ts +7 -8
  11. package/dist/blockchain/index.js +26 -26
  12. package/dist/blockchain/inherent/index.d.ts +17 -0
  13. package/dist/blockchain/inherent/index.js +32 -0
  14. package/dist/blockchain/inherent/para-enter.d.ts +7 -0
  15. package/dist/blockchain/inherent/para-enter.js +33 -0
  16. package/dist/blockchain/inherent/parachain/validation-data.d.ts +25 -0
  17. package/dist/blockchain/{inherents.js → inherent/parachain/validation-data.js} +77 -46
  18. package/dist/blockchain/txpool.d.ts +17 -2
  19. package/dist/blockchain/txpool.js +46 -81
  20. package/dist/decode-key.d.ts +2 -0
  21. package/dist/decode-key.js +24 -0
  22. package/dist/executor.d.ts +17 -3
  23. package/dist/executor.js +43 -3
  24. package/dist/executor.test.js +16 -9
  25. package/dist/genesis-provider.d.ts +5 -0
  26. package/dist/genesis-provider.js +15 -3
  27. package/dist/index.d.ts +1 -18
  28. package/dist/index.js +43 -147
  29. package/dist/rpc/dev.js +11 -1
  30. package/dist/rpc/shared.d.ts +0 -4
  31. package/dist/rpc/substrate/author.d.ts +1 -1
  32. package/dist/rpc/substrate/author.js +7 -2
  33. package/dist/rpc/substrate/chain.js +2 -2
  34. package/dist/rpc/substrate/state.js +1 -1
  35. package/dist/rpc/substrate/system.js +3 -3
  36. package/dist/run-block.d.ts +2 -0
  37. package/dist/run-block.js +36 -0
  38. package/dist/schema/index.js +1 -1
  39. package/dist/server.d.ts +3 -3
  40. package/dist/server.js +26 -11
  41. package/dist/setup-with-server.d.ts +8 -0
  42. package/dist/setup-with-server.js +23 -0
  43. package/dist/setup.d.ts +10 -0
  44. package/dist/setup.js +62 -0
  45. package/dist/utils/index.d.ts +2 -0
  46. package/dist/utils/index.js +9 -1
  47. package/dist/utils/proof.d.ts +10 -2
  48. package/dist/utils/proof.js +12 -8
  49. package/dist/utils/set-storage.d.ts +2 -1
  50. package/dist/utils/time-travel.d.ts +5 -0
  51. package/dist/utils/time-travel.js +64 -0
  52. package/dist/xcm/index.d.ts +3 -0
  53. package/dist/xcm/index.js +67 -0
  54. package/package.json +5 -5
  55. package/dist/bindings.d.ts +0 -2
  56. package/dist/bindings.js +0 -31
  57. package/dist/blockchain/inherents.d.ts +0 -24
package/README.md CHANGED
@@ -57,3 +57,9 @@ Make sure you have setup Rust environment (>= 1.64).
57
57
  - Run Kusama fork
58
58
  - Edit configs/kusama.yml if needed. (e.g. update the block number)
59
59
  - `yarn start dev --config=configs/kusama.yml`
60
+
61
+ - Setup XCM multichain (UpwardMessages not yet supported)
62
+ **_NOTE:_** You can also connect multiple parachains without a relaychain
63
+ ```bash
64
+ yarn start xcm --relaychain=configs/kusama.yml --parachain=configs/karura.yml --parachain=configs/statemine.yml
65
+ ```
package/dist/api.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { ExtDef } from '@polkadot/types/extrinsic/signedExtensions/types';
2
2
  import { HexString } from '@polkadot/util/types';
3
3
  import { ProviderInterface } from '@polkadot/rpc-provider/types';
4
+ import { WsProvider } from '@polkadot/rpc-provider';
4
5
  type ChainProperties = {
5
6
  ss58Format?: number;
6
7
  tokenDecimals?: number[];
@@ -27,14 +28,14 @@ export declare class Api {
27
28
  readonly signedExtensions: ExtDef;
28
29
  constructor(provider: ProviderInterface, signedExtensions?: ExtDef);
29
30
  disconnect(): Promise<void>;
30
- get isReady(): Promise<void>;
31
+ get isReady(): Promise<void> | Promise<WsProvider>;
31
32
  get chain(): Promise<string>;
32
33
  get chainProperties(): Promise<ChainProperties>;
33
34
  getSystemName(): Promise<string>;
34
35
  getSystemProperties(): Promise<ChainProperties>;
35
36
  getSystemChain(): Promise<string>;
36
37
  getMetadata(hash?: string): Promise<string>;
37
- getBlockHash(blockNumber?: number): Promise<string>;
38
+ getBlockHash(blockNumber?: number): Promise<`0x${string}`>;
38
39
  getHeader(hash?: string): Promise<Header>;
39
40
  getBlock(hash?: string): Promise<SignedBlock>;
40
41
  getStorage(key: string, hash?: string): Promise<string>;
package/dist/api.js CHANGED
@@ -1,44 +1,39 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Api = void 0;
4
+ const rpc_provider_1 = require("@polkadot/rpc-provider");
4
5
  class Api {
5
6
  #provider;
6
- #isReady;
7
+ #ready;
7
8
  #chain;
8
9
  #chainProperties;
9
10
  signedExtensions;
10
11
  constructor(provider, signedExtensions) {
11
12
  this.#provider = provider;
12
13
  this.signedExtensions = signedExtensions || {};
13
- this.#isReady = new Promise((resolve, reject) => {
14
- if (this.#provider.isConnected) {
15
- setTimeout(resolve, 500);
16
- }
17
- else {
18
- this.#provider.on('connected', () => {
19
- setTimeout(resolve, 500);
20
- });
21
- }
22
- this.#provider.on('error', reject);
23
- });
24
- this.#provider.on('disconnected', () => {
25
- // TODO: reconnect
26
- console.warn('Api disconnected');
27
- });
28
- this.#chain = this.#isReady.then(() => this.getSystemChain());
29
- this.#chainProperties = this.#isReady.then(() => this.getSystemProperties());
30
- this.#provider.connect();
31
14
  }
32
15
  async disconnect() {
33
16
  return this.#provider.disconnect();
34
17
  }
35
18
  get isReady() {
36
- return this.#isReady;
19
+ if (this.#provider instanceof rpc_provider_1.WsProvider) {
20
+ return this.#provider.isReady;
21
+ }
22
+ if (!this.#ready) {
23
+ this.#ready = this.#provider.connect();
24
+ }
25
+ return this.#ready;
37
26
  }
38
27
  get chain() {
28
+ if (!this.#chain) {
29
+ this.#chain = this.getSystemChain();
30
+ }
39
31
  return this.#chain;
40
32
  }
41
33
  get chainProperties() {
34
+ if (!this.#chainProperties) {
35
+ this.#chainProperties = this.getSystemProperties();
36
+ }
42
37
  return this.#chainProperties;
43
38
  }
44
39
  async getSystemName() {
@@ -0,0 +1,4 @@
1
+ import { Block } from './block';
2
+ import { Header } from '@polkadot/types/interfaces';
3
+ import { HexString } from '@polkadot/util/types';
4
+ export declare const buildBlock: (head: Block, header: Header, inherents: HexString[], extrinsics: HexString[]) => Promise<[Block, HexString[]]>;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildBlock = void 0;
4
+ const block_1 = require("./block");
5
+ const logger_1 = require("../logger");
6
+ const logger = logger_1.defaultLogger.child({ name: 'block-builder' });
7
+ const buildBlock = async (head, header, inherents, extrinsics) => {
8
+ const registry = await head.registry;
9
+ const pendingExtrinsics = [];
10
+ const blockNumber = header.number.toNumber();
11
+ const hash = `0x${Math.round(Math.random() * 100000000)
12
+ .toString(16)
13
+ .padEnd(64, '0')}`;
14
+ const newBlock = new block_1.Block(head.chain, blockNumber, hash, head, { header, extrinsics: [], storage: head.storage });
15
+ logger.info({
16
+ number: blockNumber,
17
+ extrinsicsCount: extrinsics.length,
18
+ tempHash: newBlock.hash,
19
+ }, `Building block #${blockNumber.toLocaleString()}`);
20
+ {
21
+ // initialize block
22
+ const { storageDiff } = await newBlock.call('Core_initialize_block', header.toHex());
23
+ logger.trace((0, logger_1.truncateStorageDiff)(storageDiff), 'Initialize block');
24
+ newBlock.pushStorageLayer().setAll(storageDiff);
25
+ }
26
+ // apply inherents
27
+ for (const extrinsic of inherents) {
28
+ try {
29
+ const { storageDiff } = await newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
30
+ newBlock.pushStorageLayer().setAll(storageDiff);
31
+ logger.trace((0, logger_1.truncateStorageDiff)(storageDiff), 'Applied inherent');
32
+ }
33
+ catch (e) {
34
+ logger.warn('Failed to apply inherents %o %s', e, e);
35
+ throw new Error('Failed to apply inherents');
36
+ }
37
+ }
38
+ // apply extrinsics
39
+ for (const extrinsic of extrinsics) {
40
+ try {
41
+ const { storageDiff } = await newBlock.call('BlockBuilder_apply_extrinsic', extrinsic);
42
+ newBlock.pushStorageLayer().setAll(storageDiff);
43
+ logger.trace((0, logger_1.truncateStorageDiff)(storageDiff), 'Applied extrinsic');
44
+ }
45
+ catch (e) {
46
+ logger.info('Failed to apply extrinsic %o %s', e, e);
47
+ pendingExtrinsics.push(extrinsic);
48
+ }
49
+ }
50
+ {
51
+ // finalize block
52
+ const { storageDiff } = await newBlock.call('BlockBuilder_finalize_block', '0x');
53
+ newBlock.pushStorageLayer().setAll(storageDiff);
54
+ logger.trace((0, logger_1.truncateStorageDiff)(storageDiff), 'Finalize block');
55
+ }
56
+ const blockData = registry.createType('Block', {
57
+ header,
58
+ extrinsics,
59
+ });
60
+ const storageDiff = await newBlock.storageDiff();
61
+ logger.trace(Object.entries(storageDiff).map(([key, value]) => [key, (0, logger_1.truncate)(value)]), 'Final block');
62
+ const finalBlock = new block_1.Block(head.chain, blockNumber, blockData.hash.toHex(), head, {
63
+ header,
64
+ extrinsics: [...inherents, ...extrinsics],
65
+ storage: head.storage,
66
+ storageDiff,
67
+ });
68
+ logger.info({ hash: finalBlock.hash, number: blockNumber }, `Block built #${blockNumber.toLocaleString()} hash ${finalBlock.hash}`);
69
+ return [finalBlock, pendingExtrinsics];
70
+ };
71
+ exports.buildBlock = buildBlock;
@@ -3,7 +3,7 @@ import { DecoratedMeta } from '@polkadot/types/metadata/decorate/types';
3
3
  import { TypeRegistry } from '@polkadot/types';
4
4
  import type { HexString } from '@polkadot/util/types';
5
5
  import { Blockchain } from '.';
6
- import { StorageLayer, StorageLayerProvider } from './storage-layer';
6
+ import { StorageLayer, StorageLayerProvider, StorageValue } from './storage-layer';
7
7
  import type { RuntimeVersion } from '../executor';
8
8
  export type TaskCallResponse = {
9
9
  result: HexString;
@@ -12,12 +12,14 @@ export type TaskCallResponse = {
12
12
  export declare class Block {
13
13
  #private;
14
14
  readonly number: number;
15
- readonly hash: string;
16
- constructor(chain: Blockchain, number: number, hash: string, parentBlock?: Block, block?: {
15
+ readonly hash: HexString;
16
+ constructor(chain: Blockchain, number: number, hash: HexString, parentBlock?: Block, block?: {
17
17
  header: Header;
18
18
  extrinsics: HexString[];
19
19
  storage?: StorageLayerProvider;
20
+ storageDiff?: Record<string, StorageValue | null>;
20
21
  });
22
+ get chain(): Blockchain;
21
23
  get header(): Header | Promise<Header>;
22
24
  get extrinsics(): HexString[] | Promise<HexString[]>;
23
25
  get parentBlock(): undefined | Block | Promise<Block | undefined>;
@@ -31,7 +31,18 @@ class Block {
31
31
  this.#extrinsics = block?.extrinsics;
32
32
  this.#baseStorage = block?.storage ?? new storage_layer_1.RemoteStorageLayer(chain.api, hash, chain.db);
33
33
  this.#storages = [];
34
- this.#registry = parentBlock?.registry;
34
+ const storageDiff = block?.storageDiff || {};
35
+ // if code doesn't change then reuse parent block's meta
36
+ if (!storageDiff[(0, util_2.stringToHex)(':code')]) {
37
+ this.#runtimeVersion = parentBlock?.runtimeVersion;
38
+ this.#metadata = parentBlock?.metadata;
39
+ this.#registry = parentBlock?.registry;
40
+ this.#meta = parentBlock?.meta;
41
+ }
42
+ this.pushStorageLayer().setAll(storageDiff);
43
+ }
44
+ get chain() {
45
+ return this.#chain;
35
46
  }
36
47
  get header() {
37
48
  if (!this.#header) {
@@ -90,16 +101,15 @@ class Block {
90
101
  return storage;
91
102
  }
92
103
  get wasm() {
93
- const getWasm = async () => {
94
- const wasmKey = (0, util_2.stringToHex)(':code');
95
- const wasm = await this.get(wasmKey);
96
- if (!wasm) {
97
- throw new Error('No wasm found');
98
- }
99
- return wasm;
100
- };
101
104
  if (!this.#wasm) {
102
- this.#wasm = getWasm();
105
+ this.#wasm = (async () => {
106
+ const wasmKey = (0, util_2.stringToHex)(':code');
107
+ const wasm = await this.get(wasmKey);
108
+ if (!wasm) {
109
+ throw new Error('No wasm found');
110
+ }
111
+ return wasm;
112
+ })();
103
113
  }
104
114
  return this.#wasm;
105
115
  }
@@ -138,17 +148,7 @@ class Block {
138
148
  }
139
149
  get metadata() {
140
150
  if (!this.#metadata) {
141
- this.#metadata = this.wasm.then(async (wasm) => {
142
- const response = await (0, executor_1.runTask)({
143
- blockHash: this.hash,
144
- wasm,
145
- calls: [['Metadata_metadata', '0x']],
146
- storage: [],
147
- mockSignatureHost: this.#chain.mockSignatureHost,
148
- allowUnresolvedImports: this.#chain.allowUnresolvedImports,
149
- });
150
- return (0, utils_1.compactHex)((0, util_2.hexToU8a)(response.Call.result));
151
- });
151
+ this.#metadata = this.call('Metadata_metadata', '0x').then((resp) => (0, utils_1.compactHex)((0, util_2.hexToU8a)(resp.result)));
152
152
  }
153
153
  return this.#metadata;
154
154
  }
@@ -164,13 +164,12 @@ class Block {
164
164
  async call(method, args, storage = []) {
165
165
  const wasm = await this.wasm;
166
166
  const response = await (0, executor_1.runTask)({
167
- blockHash: this.hash,
168
167
  wasm,
169
168
  calls: [[method, args]],
170
169
  storage,
171
170
  mockSignatureHost: this.#chain.mockSignatureHost,
172
171
  allowUnresolvedImports: this.#chain.allowUnresolvedImports,
173
- });
172
+ }, (0, executor_1.taskHandler)(this));
174
173
  if (response.Call)
175
174
  return response.Call;
176
175
  if (response.Error)
@@ -1,13 +1,15 @@
1
1
  import { Block } from './block';
2
+ type Callback = (block: Block, pairs: [string, string][]) => void | Promise<void>;
2
3
  export declare const randomId: () => string;
3
4
  export declare class HeadState {
4
5
  #private;
5
6
  constructor(head: Block);
6
7
  subscribeHead(cb: (block: Block) => void): string;
7
8
  unsubscribeHead(id: string): void;
8
- subscribeStorage(keys: string[], cb: (block: Block, pairs: [string, string][]) => void): Promise<string>;
9
+ subscribeStorage(keys: string[], cb: Callback): Promise<string>;
9
10
  unsubscribeStorage(id: string): void;
10
- subscrubeRuntimeVersion(cb: (block: Block) => void): string;
11
+ subscrubeRuntimeVersion(cb: (block: Block) => void): Promise<string>;
11
12
  unsubscribeRuntimeVersion(id: string): void;
12
13
  setHead(head: Block): Promise<void>;
13
14
  }
15
+ export {};
@@ -1,8 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HeadState = exports.randomId = void 0;
4
+ const util_1 = require("@polkadot/util");
5
+ const logger_1 = require("../logger");
4
6
  const randomId = () => Math.random().toString(36).substring(2);
5
7
  exports.randomId = randomId;
8
+ const logger = logger_1.defaultLogger.child({ name: 'head-state' });
6
9
  class HeadState {
7
10
  #headListeners = {};
8
11
  #storageListeners = {};
@@ -30,14 +33,15 @@ class HeadState {
30
33
  unsubscribeStorage(id) {
31
34
  delete this.#storageListeners[id];
32
35
  }
33
- subscrubeRuntimeVersion(cb) {
34
- // TODO: actually subscribe
35
- void cb;
36
- return (0, exports.randomId)();
36
+ async subscrubeRuntimeVersion(cb) {
37
+ const id = (0, exports.randomId)();
38
+ const codeKey = (0, util_1.stringToHex)(':code');
39
+ this.#storageListeners[id] = [[codeKey], cb];
40
+ this.#oldValues[codeKey] = await this.#head.get(codeKey);
41
+ return id;
37
42
  }
38
43
  unsubscribeRuntimeVersion(id) {
39
- // TODO: actually unsubscribe
40
- void id;
44
+ delete this.#storageListeners[id];
41
45
  }
42
46
  async setHead(head) {
43
47
  this.#head = head;
@@ -48,7 +52,9 @@ class HeadState {
48
52
  for (const [keys, cb] of Object.values(this.#storageListeners)) {
49
53
  const changed = keys.filter((key) => diff[key]).map((key) => [key, diff[key]]);
50
54
  if (changed.length > 0) {
51
- cb(head, changed);
55
+ await Promise.resolve(cb(head, changed)).catch((error) => {
56
+ logger.error(error, 'callback');
57
+ });
52
58
  }
53
59
  }
54
60
  Object.assign(this.#oldValues, diff);
@@ -1,11 +1,10 @@
1
1
  import { DataSource } from 'typeorm';
2
- import { Header } from '@polkadot/types/interfaces';
3
2
  import { HexString } from '@polkadot/util/types';
4
3
  import { Api } from '../api';
5
4
  import { Block } from './block';
6
- import { BuildBlockMode } from './txpool';
5
+ import { BuildBlockMode, BuildBlockParams } from './txpool';
7
6
  import { HeadState } from './head-state';
8
- import { InherentProvider } from './inherents';
7
+ import { InherentProvider } from './inherent';
9
8
  export interface Options {
10
9
  api: Api;
11
10
  buildBlockMode?: BuildBlockMode;
@@ -13,7 +12,7 @@ export interface Options {
13
12
  db?: DataSource;
14
13
  header: {
15
14
  number: number;
16
- hash: string;
15
+ hash: HexString;
17
16
  };
18
17
  mockSignatureHost?: boolean;
19
18
  allowUnresolvedImports?: boolean;
@@ -27,11 +26,11 @@ export declare class Blockchain {
27
26
  readonly headState: HeadState;
28
27
  constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost, allowUnresolvedImports, }: Options);
29
28
  get head(): Block;
29
+ get pendingExtrinsics(): HexString[];
30
30
  getBlockAt(number?: number): Promise<Block | undefined>;
31
- getBlock(hash?: string): Promise<Block | undefined>;
32
- newTempBlock(parent: Block, header: Header): Block;
31
+ getBlock(hash?: HexString): Promise<Block | undefined>;
33
32
  unregisterBlock(block: Block): void;
34
- setHead(block: Block): void;
33
+ setHead(block: Block): Promise<void>;
35
34
  submitExtrinsic(extrinsic: HexString): Promise<HexString>;
36
- newBlock(): Promise<Block>;
35
+ newBlock(params?: BuildBlockParams): Promise<Block>;
37
36
  }
@@ -6,9 +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 shared_1 = require("../rpc/shared");
10
9
  const logger_1 = require("../logger");
11
- const bindings_1 = require("../bindings");
12
10
  const logger = logger_1.defaultLogger.child({ name: 'blockchain' });
13
11
  class Blockchain {
14
12
  api;
@@ -19,6 +17,7 @@ class Blockchain {
19
17
  #head;
20
18
  #blocksByNumber = [];
21
19
  #blocksByHash = {};
20
+ #loadingBlocks = {};
22
21
  headState;
23
22
  constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost = false, allowUnresolvedImports = false, }) {
24
23
  this.api = api;
@@ -27,7 +26,6 @@ class Blockchain {
27
26
  this.allowUnresolvedImports = allowUnresolvedImports;
28
27
  this.#head = new block_1.Block(this, header.number, header.hash);
29
28
  this.#registerBlock(this.#head);
30
- (0, bindings_1.setupBindings)(this);
31
29
  this.#txpool = new txpool_1.TxPool(this, inherentProvider, buildBlockMode);
32
30
  this.headState = new head_state_1.HeadState(this.#head);
33
31
  }
@@ -38,6 +36,9 @@ class Blockchain {
38
36
  get head() {
39
37
  return this.#head;
40
38
  }
39
+ get pendingExtrinsics() {
40
+ return this.#txpool.pendingExtrinsics;
41
+ }
41
42
  async getBlockAt(number) {
42
43
  if (number === undefined) {
43
44
  return this.head;
@@ -58,29 +59,28 @@ class Blockchain {
58
59
  hash = this.head.hash;
59
60
  }
60
61
  if (!this.#blocksByHash[hash]) {
61
- try {
62
- const registry = await this.head.registry;
63
- const header = registry.createType('Header', await this.api.getHeader(hash));
64
- const block = new block_1.Block(this, header.number.toNumber(), hash);
65
- this.#registerBlock(block);
62
+ const loadingBlock = this.#loadingBlocks[hash];
63
+ if (loadingBlock) {
64
+ await loadingBlock;
66
65
  }
67
- catch (e) {
68
- logger.debug(`getBlock(${hash}) failed: ${e}`);
69
- return undefined;
66
+ else {
67
+ const loadingBlock = (async () => {
68
+ try {
69
+ const header = await this.api.getHeader(hash);
70
+ const block = new block_1.Block(this, Number(header.number), hash);
71
+ this.#registerBlock(block);
72
+ }
73
+ catch (e) {
74
+ logger.debug(`getBlock(${hash}) failed: ${e}`);
75
+ }
76
+ })();
77
+ this.#loadingBlocks[hash] = loadingBlock;
78
+ await loadingBlock;
79
+ delete this.#loadingBlocks[hash];
70
80
  }
71
81
  }
72
82
  return this.#blocksByHash[hash];
73
83
  }
74
- newTempBlock(parent, header) {
75
- const number = parent.number + 1;
76
- const hash = '0x' +
77
- Math.round(Math.random() * 100000000)
78
- .toString(16)
79
- .padEnd(64, '0');
80
- const block = new block_1.Block(this, number, hash, parent, { header, extrinsics: [], storage: parent.storage });
81
- this.#blocksByHash[hash] = block;
82
- return block;
83
- }
84
84
  unregisterBlock(block) {
85
85
  if (block.hash === this.head.hash) {
86
86
  throw new Error('Cannot unregister head block');
@@ -90,14 +90,14 @@ class Blockchain {
90
90
  }
91
91
  delete this.#blocksByHash[block.hash];
92
92
  }
93
- setHead(block) {
93
+ async setHead(block) {
94
94
  logger.debug({
95
95
  number: block.number,
96
96
  hash: block.hash,
97
97
  }, 'setHead');
98
98
  this.#head = block;
99
99
  this.#registerBlock(block);
100
- this.headState.setHead(block);
100
+ await this.headState.setHead(block);
101
101
  }
102
102
  async submitExtrinsic(extrinsic) {
103
103
  const source = '0x02'; // External
@@ -109,10 +109,10 @@ class Blockchain {
109
109
  this.#txpool.submitExtrinsic(extrinsic);
110
110
  return (0, util_crypto_1.blake2AsHex)(extrinsic, 256);
111
111
  }
112
- throw new shared_1.ResponseError(1, `Extrinsic is invalid: ${validity.asErr.toString()}`);
112
+ throw new Error(`Extrinsic is invalid: ${validity.asErr.toString()}`);
113
113
  }
114
- async newBlock() {
115
- await this.#txpool.buildBlock();
114
+ async newBlock(params) {
115
+ await this.#txpool.buildBlock(params);
116
116
  return this.#head;
117
117
  }
118
118
  }
@@ -0,0 +1,17 @@
1
+ import { Block } from '../block';
2
+ import { BuildBlockParams } from '../txpool';
3
+ import { HexString } from '@polkadot/util/types';
4
+ export { SetValidationData } from './parachain/validation-data';
5
+ export { ParaInherentEnter } from './para-enter';
6
+ export interface CreateInherents {
7
+ createInherents(parent: Block, params?: BuildBlockParams['inherent']): Promise<HexString[]>;
8
+ }
9
+ export type InherentProvider = CreateInherents;
10
+ export declare class SetTimestamp implements InherentProvider {
11
+ createInherents(parent: Block): Promise<HexString[]>;
12
+ }
13
+ export declare class InherentProviders implements InherentProvider {
14
+ #private;
15
+ constructor(base: InherentProvider, providers: CreateInherents[]);
16
+ createInherents(parent: Block, params?: BuildBlockParams['inherent']): Promise<HexString[]>;
17
+ }
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InherentProviders = exports.SetTimestamp = exports.ParaInherentEnter = exports.SetValidationData = void 0;
4
+ const types_1 = require("@polkadot/types");
5
+ const time_travel_1 = require("../../utils/time-travel");
6
+ var validation_data_1 = require("./parachain/validation-data");
7
+ Object.defineProperty(exports, "SetValidationData", { enumerable: true, get: function () { return validation_data_1.SetValidationData; } });
8
+ var para_enter_1 = require("./para-enter");
9
+ Object.defineProperty(exports, "ParaInherentEnter", { enumerable: true, get: function () { return para_enter_1.ParaInherentEnter; } });
10
+ class SetTimestamp {
11
+ async createInherents(parent) {
12
+ const meta = await parent.meta;
13
+ const slotDuration = await (0, time_travel_1.getSlotDuration)(parent.chain);
14
+ const currentTimestamp = await (0, time_travel_1.getCurrentTimestamp)(parent.chain);
15
+ return [new types_1.GenericExtrinsic(meta.registry, meta.tx.timestamp.set(currentTimestamp + slotDuration)).toHex()];
16
+ }
17
+ }
18
+ exports.SetTimestamp = SetTimestamp;
19
+ class InherentProviders {
20
+ #base;
21
+ #providers;
22
+ constructor(base, providers) {
23
+ this.#base = base;
24
+ this.#providers = providers;
25
+ }
26
+ async createInherents(parent, params) {
27
+ const base = await this.#base.createInherents(parent, params);
28
+ const extra = await Promise.all(this.#providers.map((provider) => provider.createInherents(parent, params)));
29
+ return [...base, ...extra.flat()];
30
+ }
31
+ }
32
+ exports.InherentProviders = InherentProviders;
@@ -0,0 +1,7 @@
1
+ import { HexString } from '@polkadot/util/types';
2
+ import { Block } from '../block';
3
+ import { BuildBlockParams } from '../txpool';
4
+ import { CreateInherents } from '.';
5
+ export declare class ParaInherentEnter implements CreateInherents {
6
+ createInherents(parent: Block, _params?: BuildBlockParams['inherent']): Promise<HexString[]>;
7
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ParaInherentEnter = void 0;
4
+ const types_1 = require("@polkadot/types");
5
+ class ParaInherentEnter {
6
+ async createInherents(parent, _params) {
7
+ const meta = await parent.meta;
8
+ if (!meta.tx.paraInherent?.enter) {
9
+ return [];
10
+ }
11
+ const extrinsics = await parent.extrinsics;
12
+ const paraEnterExtrinsic = extrinsics.find((extrinsic) => {
13
+ const firstArg = meta.registry.createType('GenericExtrinsic', extrinsic)?.args?.[0];
14
+ return firstArg && 'bitfields' in firstArg;
15
+ });
16
+ if (!paraEnterExtrinsic) {
17
+ throw new Error('Missing paraInherent data from block');
18
+ }
19
+ const extrinsic = meta.registry
20
+ .createType('GenericExtrinsic', paraEnterExtrinsic)
21
+ .args[0].toJSON();
22
+ const parentHeader = (await parent.header).toJSON();
23
+ const newData = {
24
+ ...extrinsic,
25
+ bitfields: [],
26
+ backedCandidates: [],
27
+ parentHeader,
28
+ };
29
+ // TODO: fill with data
30
+ return [new types_1.GenericExtrinsic(meta.registry, meta.tx.paraInherent.enter(newData)).toHex()];
31
+ }
32
+ }
33
+ exports.ParaInherentEnter = ParaInherentEnter;
@@ -0,0 +1,25 @@
1
+ import { HexString } from '@polkadot/util/types';
2
+ import { Block } from '../../../blockchain/block';
3
+ import { BuildBlockParams } from '../../txpool';
4
+ import { CreateInherents } from '..';
5
+ export type ValidationData = {
6
+ downwardMessages: {
7
+ sent_at: number;
8
+ msg: HexString;
9
+ }[];
10
+ horizontalMessages: Record<number, {
11
+ sent_at: number;
12
+ data: HexString;
13
+ }[]>;
14
+ validationData: {
15
+ relayParentNumber: number;
16
+ relayParentStorageRoot: HexString;
17
+ maxPovSize: number;
18
+ };
19
+ relayChainState: {
20
+ trieNodes: HexString[];
21
+ };
22
+ };
23
+ export declare class SetValidationData implements CreateInherents {
24
+ createInherents(parent: Block, params?: BuildBlockParams['inherent']): Promise<HexString[]>;
25
+ }