@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.
Files changed (128) hide show
  1. package/{lib → dist/cjs}/api.js +7 -7
  2. package/{lib → dist/cjs}/blockchain/block.js +1 -4
  3. package/{lib → dist/cjs}/genesis-provider.js +1 -1
  4. package/{lib → dist/cjs}/rpc/substrate/chain.js +1 -1
  5. package/{lib → dist/cjs}/utils/index.js +11 -1
  6. package/dist/esm/api.js +125 -0
  7. package/dist/esm/blockchain/block-builder.js +293 -0
  8. package/dist/esm/blockchain/block.js +277 -0
  9. package/dist/esm/blockchain/head-state.js +79 -0
  10. package/dist/esm/blockchain/index.js +413 -0
  11. package/dist/esm/blockchain/inherent/index.js +40 -0
  12. package/dist/esm/blockchain/inherent/para-enter.js +29 -0
  13. package/dist/esm/blockchain/inherent/parachain/babe-randomness.js +11 -0
  14. package/dist/esm/blockchain/inherent/parachain/nimbus-author-inherent.js +11 -0
  15. package/dist/esm/blockchain/inherent/parachain/validation-data.js +165 -0
  16. package/dist/esm/blockchain/storage-layer.js +215 -0
  17. package/dist/esm/blockchain/txpool.js +208 -0
  18. package/dist/esm/chopsticks-provider.js +156 -0
  19. package/dist/esm/database.js +1 -0
  20. package/dist/esm/genesis-provider.js +144 -0
  21. package/dist/esm/logger.js +34 -0
  22. package/dist/esm/offchain.js +36 -0
  23. package/dist/esm/rpc/index.js +10 -0
  24. package/dist/esm/rpc/shared.js +15 -0
  25. package/dist/esm/rpc/substrate/author.js +85 -0
  26. package/dist/esm/rpc/substrate/chain.js +84 -0
  27. package/dist/esm/rpc/substrate/index.js +18 -0
  28. package/dist/esm/rpc/substrate/payment.js +40 -0
  29. package/dist/esm/rpc/substrate/state.js +166 -0
  30. package/dist/esm/rpc/substrate/system.js +48 -0
  31. package/dist/esm/schema/index.js +11 -0
  32. package/dist/esm/setup.js +71 -0
  33. package/dist/esm/utils/decoder.js +95 -0
  34. package/dist/esm/utils/index.js +91 -0
  35. package/dist/esm/utils/key-cache.js +61 -0
  36. package/dist/esm/utils/proof.js +33 -0
  37. package/dist/esm/utils/set-storage.js +56 -0
  38. package/dist/esm/utils/time-travel.js +58 -0
  39. package/dist/esm/wasm-executor/browser-wasm-executor.mjs +32 -0
  40. package/dist/esm/wasm-executor/browser-worker.js +15 -0
  41. package/dist/esm/wasm-executor/index.js +146 -0
  42. package/dist/esm/wasm-executor/node-wasm-executor.mjs +29 -0
  43. package/dist/esm/wasm-executor/node-worker.js +15 -0
  44. package/dist/esm/xcm/downward.js +25 -0
  45. package/dist/esm/xcm/horizontal.js +25 -0
  46. package/dist/esm/xcm/index.js +20 -0
  47. package/dist/esm/xcm/upward.js +17 -0
  48. package/{lib → dist/types}/genesis-provider.d.ts +2 -2
  49. package/dist/types/index.d.ts +28 -0
  50. package/{lib → dist/types}/utils/index.d.ts +1 -0
  51. package/package.json +23 -14
  52. /package/{lib → dist/cjs}/blockchain/block-builder.js +0 -0
  53. /package/{lib → dist/cjs}/blockchain/head-state.js +0 -0
  54. /package/{lib → dist/cjs}/blockchain/index.js +0 -0
  55. /package/{lib → dist/cjs}/blockchain/inherent/index.js +0 -0
  56. /package/{lib → dist/cjs}/blockchain/inherent/para-enter.js +0 -0
  57. /package/{lib → dist/cjs}/blockchain/inherent/parachain/babe-randomness.js +0 -0
  58. /package/{lib → dist/cjs}/blockchain/inherent/parachain/nimbus-author-inherent.js +0 -0
  59. /package/{lib → dist/cjs}/blockchain/inherent/parachain/validation-data.js +0 -0
  60. /package/{lib → dist/cjs}/blockchain/storage-layer.js +0 -0
  61. /package/{lib → dist/cjs}/blockchain/txpool.js +0 -0
  62. /package/{lib → dist/cjs}/chopsticks-provider.js +0 -0
  63. /package/{lib → dist/cjs}/database.js +0 -0
  64. /package/{lib → dist/cjs}/index.js +0 -0
  65. /package/{lib → dist/cjs}/logger.js +0 -0
  66. /package/{lib → dist/cjs}/offchain.js +0 -0
  67. /package/{lib → dist/cjs}/rpc/index.js +0 -0
  68. /package/{lib → dist/cjs}/rpc/shared.js +0 -0
  69. /package/{lib → dist/cjs}/rpc/substrate/author.js +0 -0
  70. /package/{lib → dist/cjs}/rpc/substrate/index.js +0 -0
  71. /package/{lib → dist/cjs}/rpc/substrate/payment.js +0 -0
  72. /package/{lib → dist/cjs}/rpc/substrate/state.js +0 -0
  73. /package/{lib → dist/cjs}/rpc/substrate/system.js +0 -0
  74. /package/{lib → dist/cjs}/schema/index.js +0 -0
  75. /package/{lib → dist/cjs}/setup.js +0 -0
  76. /package/{lib → dist/cjs}/utils/decoder.js +0 -0
  77. /package/{lib → dist/cjs}/utils/key-cache.js +0 -0
  78. /package/{lib → dist/cjs}/utils/proof.js +0 -0
  79. /package/{lib → dist/cjs}/utils/set-storage.js +0 -0
  80. /package/{lib → dist/cjs}/utils/time-travel.js +0 -0
  81. /package/{lib → dist/cjs}/wasm-executor/browser-wasm-executor.mjs +0 -0
  82. /package/{lib → dist/cjs}/wasm-executor/browser-worker.js +0 -0
  83. /package/{lib → dist/cjs}/wasm-executor/index.js +0 -0
  84. /package/{lib → dist/cjs}/wasm-executor/node-wasm-executor.mjs +0 -0
  85. /package/{lib → dist/cjs}/wasm-executor/node-worker.js +0 -0
  86. /package/{lib → dist/cjs}/xcm/downward.js +0 -0
  87. /package/{lib → dist/cjs}/xcm/horizontal.js +0 -0
  88. /package/{lib → dist/cjs}/xcm/index.js +0 -0
  89. /package/{lib → dist/cjs}/xcm/upward.js +0 -0
  90. /package/{lib/index.d.ts → dist/esm/index.js} +0 -0
  91. /package/{lib → dist/types}/api.d.ts +0 -0
  92. /package/{lib → dist/types}/blockchain/block-builder.d.ts +0 -0
  93. /package/{lib → dist/types}/blockchain/block.d.ts +0 -0
  94. /package/{lib → dist/types}/blockchain/head-state.d.ts +0 -0
  95. /package/{lib → dist/types}/blockchain/index.d.ts +0 -0
  96. /package/{lib → dist/types}/blockchain/inherent/index.d.ts +0 -0
  97. /package/{lib → dist/types}/blockchain/inherent/para-enter.d.ts +0 -0
  98. /package/{lib → dist/types}/blockchain/inherent/parachain/babe-randomness.d.ts +0 -0
  99. /package/{lib → dist/types}/blockchain/inherent/parachain/nimbus-author-inherent.d.ts +0 -0
  100. /package/{lib → dist/types}/blockchain/inherent/parachain/validation-data.d.ts +0 -0
  101. /package/{lib → dist/types}/blockchain/storage-layer.d.ts +0 -0
  102. /package/{lib → dist/types}/blockchain/txpool.d.ts +0 -0
  103. /package/{lib → dist/types}/chopsticks-provider.d.ts +0 -0
  104. /package/{lib → dist/types}/database.d.ts +0 -0
  105. /package/{lib → dist/types}/logger.d.ts +0 -0
  106. /package/{lib → dist/types}/offchain.d.ts +0 -0
  107. /package/{lib → dist/types}/rpc/index.d.ts +0 -0
  108. /package/{lib → dist/types}/rpc/shared.d.ts +0 -0
  109. /package/{lib → dist/types}/rpc/substrate/author.d.ts +0 -0
  110. /package/{lib → dist/types}/rpc/substrate/chain.d.ts +0 -0
  111. /package/{lib → dist/types}/rpc/substrate/index.d.ts +0 -0
  112. /package/{lib → dist/types}/rpc/substrate/payment.d.ts +0 -0
  113. /package/{lib → dist/types}/rpc/substrate/state.d.ts +0 -0
  114. /package/{lib → dist/types}/rpc/substrate/system.d.ts +0 -0
  115. /package/{lib → dist/types}/schema/index.d.ts +0 -0
  116. /package/{lib → dist/types}/setup.d.ts +0 -0
  117. /package/{lib → dist/types}/utils/decoder.d.ts +0 -0
  118. /package/{lib → dist/types}/utils/key-cache.d.ts +0 -0
  119. /package/{lib → dist/types}/utils/proof.d.ts +0 -0
  120. /package/{lib → dist/types}/utils/set-storage.d.ts +0 -0
  121. /package/{lib → dist/types}/utils/time-travel.d.ts +0 -0
  122. /package/{lib → dist/types}/wasm-executor/browser-worker.d.ts +0 -0
  123. /package/{lib → dist/types}/wasm-executor/index.d.ts +0 -0
  124. /package/{lib → dist/types}/wasm-executor/node-worker.d.ts +0 -0
  125. /package/{lib → dist/types}/xcm/downward.d.ts +0 -0
  126. /package/{lib → dist/types}/xcm/horizontal.d.ts +0 -0
  127. /package/{lib → dist/types}/xcm/index.d.ts +0 -0
  128. /package/{lib → dist/types}/xcm/upward.d.ts +0 -0
@@ -79,13 +79,13 @@ class Api {
79
79
  return __classPrivateFieldGet(this, _Api_provider, "f").send('system_chain', []);
80
80
  }
81
81
  async getBlockHash(blockNumber) {
82
- return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getBlockHash', Number.isInteger(blockNumber) ? [blockNumber] : []);
82
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getBlockHash', Number.isInteger(blockNumber) ? [blockNumber] : [], !!blockNumber);
83
83
  }
84
84
  async getHeader(hash) {
85
- return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getHeader', hash ? [hash] : []);
85
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getHeader', hash ? [hash] : [], !!hash);
86
86
  }
87
87
  async getBlock(hash) {
88
- return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getBlock', hash ? [hash] : []);
88
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getBlock', hash ? [hash] : [], !!hash);
89
89
  }
90
90
  async getStorage(key, hash) {
91
91
  const [child, storageKey] = (0, utils_1.splitChildKey)(key);
@@ -94,14 +94,14 @@ class Api {
94
94
  const params = [child, storageKey];
95
95
  if (hash)
96
96
  params.push(hash);
97
- return __classPrivateFieldGet(this, _Api_provider, "f").send('childstate_getStorage', params);
97
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('childstate_getStorage', params, !!hash);
98
98
  }
99
99
  else {
100
100
  // main storage key, use state_getStorage
101
101
  const params = [key];
102
102
  if (hash)
103
103
  params.push(hash);
104
- return __classPrivateFieldGet(this, _Api_provider, "f").send('state_getStorage', params);
104
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('state_getStorage', params, !!hash);
105
105
  }
106
106
  }
107
107
  async getKeysPaged(prefix, pageSize, startKey, hash) {
@@ -113,7 +113,7 @@ class Api {
113
113
  if (hash)
114
114
  params.push(hash);
115
115
  return __classPrivateFieldGet(this, _Api_provider, "f")
116
- .send('childstate_getKeysPaged', params)
116
+ .send('childstate_getKeysPaged', params, !!hash)
117
117
  .then((keys) => keys.map((key) => (0, utils_1.prefixedChildKey)(child, key)));
118
118
  }
119
119
  else {
@@ -121,7 +121,7 @@ class Api {
121
121
  const params = [prefix, pageSize, startKey];
122
122
  if (hash)
123
123
  params.push(hash);
124
- return __classPrivateFieldGet(this, _Api_provider, "f").send('state_getKeysPaged', params);
124
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('state_getKeysPaged', params, !!hash);
125
125
  }
126
126
  }
127
127
  }
@@ -19,7 +19,6 @@ const util_1 = require("@polkadot/types-known/util");
19
19
  const util_2 = require("@polkadot/util");
20
20
  const storage_layer_1 = require("./storage-layer");
21
21
  const utils_1 = require("../utils");
22
- const logger_1 = require("../logger");
23
22
  const wasm_executor_1 = require("../wasm-executor");
24
23
  /**
25
24
  * Block class.
@@ -264,9 +263,7 @@ class Block {
264
263
  runtimeLogLevel: __classPrivateFieldGet(this, _Block_chain, "f").runtimeLogLevel,
265
264
  }, (0, wasm_executor_1.taskHandler)(this));
266
265
  if ('Call' in response) {
267
- for (const log of response.Call.runtimeLogs) {
268
- logger_1.defaultLogger.info(`RuntimeLogs:\n${log}`);
269
- }
266
+ (0, utils_1.printRuntimeLogs)(response.Call.runtimeLogs);
270
267
  if (this.chain.offchainWorker) {
271
268
  // apply offchain storage
272
269
  for (const [key, value] of response.Call.offchainStorageDiff) {
@@ -53,7 +53,7 @@ class GenesisProvider {
53
53
  this.getHeader = async () => {
54
54
  return {
55
55
  blockHash: this.blockHash,
56
- number: 0,
56
+ number: '0x0',
57
57
  stateRoot: await __classPrivateFieldGet(this, _GenesisProvider_stateRoot, "f"),
58
58
  digest: {
59
59
  logs: [],
@@ -46,7 +46,7 @@ const chain_getBlock = async (context, [hash]) => {
46
46
  }
47
47
  return {
48
48
  block: {
49
- header: await block.header,
49
+ header: processHeader(await block.header),
50
50
  extrinsics: await block.extrinsics,
51
51
  },
52
52
  justifications: null,
@@ -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.stripChildPrefix = exports.splitChildKey = exports.isPrefixedChildKey = exports.prefixedChildKey = exports.defer = exports.isUrl = exports.getParaId = exports.compactHex = exports.fetchKeysToArray = exports.fetchKeys = void 0;
17
+ exports.printRuntimeLogs = exports.stripChildPrefix = exports.splitChildKey = exports.isPrefixedChildKey = exports.prefixedChildKey = exports.defer = exports.isUrl = exports.getParaId = exports.compactHex = exports.fetchKeysToArray = exports.fetchKeys = void 0;
18
18
  const util_1 = require("@polkadot/util");
19
19
  const hex_1 = require("@polkadot/util/hex");
20
20
  __exportStar(require("./set-storage"), exports);
@@ -107,3 +107,13 @@ const stripChildPrefix = (key) => {
107
107
  return storageKey;
108
108
  };
109
109
  exports.stripChildPrefix = stripChildPrefix;
110
+ const printRuntimeLogs = (logs) => {
111
+ if (!logs.length)
112
+ return;
113
+ console.group('RuntimeLogs:');
114
+ for (const log of logs) {
115
+ console.log(log);
116
+ }
117
+ console.groupEnd();
118
+ };
119
+ exports.printRuntimeLogs = printRuntimeLogs;
@@ -0,0 +1,125 @@
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 _Api_provider, _Api_ready, _Api_chain, _Api_chainProperties;
13
+ import { prefixedChildKey, splitChildKey, stripChildPrefix } from './utils';
14
+ /**
15
+ * API class. Calls provider to get on-chain data.
16
+ * Either `endpoint` or `genesis` porvider must be provided.
17
+ *
18
+ * @example Instantiate an API
19
+ *
20
+ * ```ts
21
+ * const provider = new WsProvider(options.endpoint)
22
+ * const api = new Api(provider)
23
+ * await api.isReady
24
+ * ```
25
+ */
26
+ export class Api {
27
+ constructor(provider, signedExtensions) {
28
+ _Api_provider.set(this, void 0);
29
+ _Api_ready.set(this, void 0);
30
+ _Api_chain.set(this, void 0);
31
+ _Api_chainProperties.set(this, void 0);
32
+ __classPrivateFieldSet(this, _Api_provider, provider, "f");
33
+ this.signedExtensions = signedExtensions || {};
34
+ }
35
+ async disconnect() {
36
+ return __classPrivateFieldGet(this, _Api_provider, "f").disconnect();
37
+ }
38
+ get isReady() {
39
+ if (!__classPrivateFieldGet(this, _Api_ready, "f")) {
40
+ if (__classPrivateFieldGet(this, _Api_provider, "f")['isReady']) {
41
+ __classPrivateFieldSet(this, _Api_ready, __classPrivateFieldGet(this, _Api_provider, "f")['isReady'], "f");
42
+ }
43
+ else {
44
+ __classPrivateFieldSet(this, _Api_ready, new Promise((resolve) => {
45
+ if (__classPrivateFieldGet(this, _Api_provider, "f").hasSubscriptions) {
46
+ __classPrivateFieldGet(this, _Api_provider, "f").on('connected', resolve);
47
+ __classPrivateFieldGet(this, _Api_provider, "f").connect();
48
+ }
49
+ else {
50
+ resolve();
51
+ }
52
+ }), "f");
53
+ }
54
+ }
55
+ return __classPrivateFieldGet(this, _Api_ready, "f");
56
+ }
57
+ get chain() {
58
+ if (!__classPrivateFieldGet(this, _Api_chain, "f")) {
59
+ __classPrivateFieldSet(this, _Api_chain, this.getSystemChain(), "f");
60
+ }
61
+ return __classPrivateFieldGet(this, _Api_chain, "f");
62
+ }
63
+ get chainProperties() {
64
+ if (!__classPrivateFieldGet(this, _Api_chainProperties, "f")) {
65
+ __classPrivateFieldSet(this, _Api_chainProperties, this.getSystemProperties(), "f");
66
+ }
67
+ return __classPrivateFieldGet(this, _Api_chainProperties, "f");
68
+ }
69
+ async getSystemName() {
70
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('system_name', []);
71
+ }
72
+ async getSystemProperties() {
73
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('system_properties', []);
74
+ }
75
+ async getSystemChain() {
76
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('system_chain', []);
77
+ }
78
+ async getBlockHash(blockNumber) {
79
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getBlockHash', Number.isInteger(blockNumber) ? [blockNumber] : [], !!blockNumber);
80
+ }
81
+ async getHeader(hash) {
82
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getHeader', hash ? [hash] : [], !!hash);
83
+ }
84
+ async getBlock(hash) {
85
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('chain_getBlock', hash ? [hash] : [], !!hash);
86
+ }
87
+ async getStorage(key, hash) {
88
+ const [child, storageKey] = splitChildKey(key);
89
+ if (child) {
90
+ // child storage key, use childstate_getStorage
91
+ const params = [child, storageKey];
92
+ if (hash)
93
+ params.push(hash);
94
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('childstate_getStorage', params, !!hash);
95
+ }
96
+ else {
97
+ // main storage key, use state_getStorage
98
+ const params = [key];
99
+ if (hash)
100
+ params.push(hash);
101
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('state_getStorage', params, !!hash);
102
+ }
103
+ }
104
+ async getKeysPaged(prefix, pageSize, startKey, hash) {
105
+ const [child, storageKey] = splitChildKey(prefix);
106
+ if (child) {
107
+ // child storage key, use childstate_getKeysPaged
108
+ // strip child prefix from startKey
109
+ const params = [child, storageKey, pageSize, stripChildPrefix(startKey)];
110
+ if (hash)
111
+ params.push(hash);
112
+ return __classPrivateFieldGet(this, _Api_provider, "f")
113
+ .send('childstate_getKeysPaged', params, !!hash)
114
+ .then((keys) => keys.map((key) => prefixedChildKey(child, key)));
115
+ }
116
+ else {
117
+ // main storage key, use state_getKeysPaged
118
+ const params = [prefix, pageSize, startKey];
119
+ if (hash)
120
+ params.push(hash);
121
+ return __classPrivateFieldGet(this, _Api_provider, "f").send('state_getKeysPaged', params, !!hash);
122
+ }
123
+ }
124
+ }
125
+ _Api_provider = new WeakMap(), _Api_ready = new WeakMap(), _Api_chain = new WeakMap(), _Api_chainProperties = new WeakMap();
@@ -0,0 +1,293 @@
1
+ import { Block } from './block';
2
+ import { StorageLayer, StorageValueKind } from './storage-layer';
3
+ import { compactAddLength, hexToU8a, stringToHex, u8aConcat } from '@polkadot/util';
4
+ import { compactHex } from '../utils';
5
+ import { defaultLogger, truncate } from '../logger';
6
+ import { getCurrentSlot } from '../utils/time-travel';
7
+ const logger = defaultLogger.child({ name: 'block-builder' });
8
+ const getConsensus = (header) => {
9
+ if (header.digest.logs.length === 0)
10
+ return;
11
+ const preRuntime = header.digest.logs[0].asPreRuntime;
12
+ const [consensusEngine, slot] = preRuntime;
13
+ return { consensusEngine, slot, rest: header.digest.logs.slice(1) };
14
+ };
15
+ const getNewSlot = (digest, slotNumber) => {
16
+ if (digest.isPrimary) {
17
+ return {
18
+ primary: {
19
+ ...digest.asPrimary.toJSON(),
20
+ slotNumber,
21
+ },
22
+ };
23
+ }
24
+ if (digest.isSecondaryPlain) {
25
+ return {
26
+ secondaryPlain: {
27
+ ...digest.asSecondaryPlain.toJSON(),
28
+ slotNumber,
29
+ },
30
+ };
31
+ }
32
+ if (digest.isSecondaryVRF) {
33
+ return {
34
+ secondaryVRF: {
35
+ ...digest.asSecondaryVRF.toJSON(),
36
+ slotNumber,
37
+ },
38
+ };
39
+ }
40
+ return digest.toJSON();
41
+ };
42
+ export const newHeader = async (head, unsafeBlockHeight) => {
43
+ const meta = await head.meta;
44
+ const parentHeader = await head.header;
45
+ let newLogs = parentHeader.digest.logs;
46
+ const consensus = getConsensus(parentHeader);
47
+ if (consensus?.consensusEngine.isAura) {
48
+ const slot = await getCurrentSlot(head.chain);
49
+ const newSlot = compactAddLength(meta.registry.createType('Slot', slot + 1).toU8a());
50
+ newLogs = [{ PreRuntime: [consensus.consensusEngine, newSlot] }, ...consensus.rest];
51
+ }
52
+ else if (consensus?.consensusEngine.isBabe) {
53
+ const slot = await getCurrentSlot(head.chain);
54
+ const digest = meta.registry.createType('RawBabePreDigest', consensus.slot);
55
+ const newSlot = compactAddLength(meta.registry.createType('RawBabePreDigest', getNewSlot(digest, slot + 1)).toU8a());
56
+ newLogs = [{ PreRuntime: [consensus.consensusEngine, newSlot] }, ...consensus.rest];
57
+ }
58
+ else if (consensus?.consensusEngine?.toString() == 'nmbs') {
59
+ const nmbsKey = stringToHex('nmbs');
60
+ newLogs = [
61
+ {
62
+ // Using previous block author
63
+ PreRuntime: [
64
+ consensus.consensusEngine,
65
+ parentHeader.digest.logs
66
+ .find((log) => log.isPreRuntime && log.asPreRuntime[0].toHex() == nmbsKey)
67
+ ?.asPreRuntime[1].toHex(),
68
+ ],
69
+ },
70
+ ...consensus.rest,
71
+ ];
72
+ if (meta.query.randomness) {
73
+ // TODO: shouldn't modify existing head
74
+ // reset notFirstBlock so randomness will skip validation
75
+ head.pushStorageLayer().set(compactHex(meta.query.randomness.notFirstBlock()), StorageValueKind.Deleted);
76
+ }
77
+ }
78
+ const header = meta.registry.createType('Header', {
79
+ parentHash: head.hash,
80
+ number: unsafeBlockHeight ?? head.number + 1,
81
+ stateRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
82
+ extrinsicsRoot: '0x0000000000000000000000000000000000000000000000000000000000000000',
83
+ digest: {
84
+ logs: newLogs,
85
+ },
86
+ });
87
+ return header;
88
+ };
89
+ const initNewBlock = async (head, header, inherents, storageLayer, callback) => {
90
+ const blockNumber = header.number.toNumber();
91
+ const hash = `0x${Math.round(Math.random() * 100000000)
92
+ .toString(16)
93
+ .padEnd(64, '0')}`;
94
+ const newBlock = new Block(head.chain, blockNumber, hash, head, {
95
+ header,
96
+ extrinsics: [],
97
+ storage: storageLayer ?? head.storage,
98
+ });
99
+ {
100
+ // initialize block
101
+ const resp = await newBlock.call('Core_initialize_block', [header.toHex()]);
102
+ newBlock.pushStorageLayer().setAll(resp.storageDiff);
103
+ callback?.onPhaseApplied?.('initialize', resp);
104
+ }
105
+ const layers = [];
106
+ // apply inherents
107
+ for (const extrinsic of inherents) {
108
+ try {
109
+ const resp = await newBlock.call('BlockBuilder_apply_extrinsic', [extrinsic]);
110
+ const layer = newBlock.pushStorageLayer();
111
+ layer.setAll(resp.storageDiff);
112
+ layers.push(layer);
113
+ callback?.onPhaseApplied?.(layers.length - 1, resp);
114
+ }
115
+ catch (e) {
116
+ logger.warn('Failed to apply inherents %o %s', e, e);
117
+ throw new Error('Failed to apply inherents');
118
+ }
119
+ }
120
+ return {
121
+ block: newBlock,
122
+ layers: layers,
123
+ };
124
+ };
125
+ export const buildBlock = async (head, inherents, extrinsics, ump, callbacks, unsafeBlockHeight) => {
126
+ const registry = await head.registry;
127
+ const header = await newHeader(head, unsafeBlockHeight);
128
+ const newBlockNumber = header.number.toNumber();
129
+ logger.info({
130
+ number: newBlockNumber,
131
+ extrinsicsCount: extrinsics.length,
132
+ umpCount: Object.keys(ump).length,
133
+ }, `Try building block #${newBlockNumber.toLocaleString()}`);
134
+ let layer;
135
+ // apply ump via storage override hack
136
+ if (Object.keys(ump).length > 0) {
137
+ const meta = await head.meta;
138
+ layer = new StorageLayer(head.storage);
139
+ for (const [paraId, upwardMessages] of Object.entries(ump)) {
140
+ const upwardMessagesU8a = upwardMessages.map((x) => hexToU8a(x));
141
+ const messagesCount = upwardMessages.length;
142
+ const messagesSize = upwardMessagesU8a.map((x) => x.length).reduce((s, i) => s + i, 0);
143
+ if (meta.query.ump) {
144
+ const queueSize = meta.registry.createType('(u32, u32)', [messagesCount, messagesSize]);
145
+ const messages = meta.registry.createType('Vec<Bytes>', upwardMessages);
146
+ // TODO: make sure we append instead of replace
147
+ layer.setAll([
148
+ [compactHex(meta.query.ump.relayDispatchQueues(paraId)), messages.toHex()],
149
+ [compactHex(meta.query.ump.relayDispatchQueueSize(paraId)), queueSize.toHex()],
150
+ ]);
151
+ }
152
+ else if (meta.query.messageQueue) {
153
+ // TODO: make sure we append instead of replace
154
+ const origin = { ump: { para: paraId } };
155
+ let last = 0;
156
+ let heap = new Uint8Array(0);
157
+ for (const message of upwardMessagesU8a) {
158
+ const payloadLen = message.length;
159
+ const header = meta.registry.createType('(u32, bool)', [payloadLen, false]);
160
+ last = heap.length;
161
+ heap = u8aConcat(heap, header.toU8a(), message);
162
+ }
163
+ layer.setAll([
164
+ [
165
+ compactHex(meta.query.messageQueue.bookStateFor(origin)),
166
+ meta.registry
167
+ .createType('PalletMessageQueueBookState', {
168
+ begin: 0,
169
+ end: 1,
170
+ count: 1,
171
+ readyNeighbours: { prev: origin, next: origin },
172
+ messageCount: messagesCount,
173
+ size_: messagesSize,
174
+ })
175
+ .toHex(),
176
+ ],
177
+ [
178
+ compactHex(meta.query.messageQueue.serviceHead(origin)),
179
+ meta.registry.createType('PolkadotRuntimeParachainsInclusionAggregateMessageOrigin', origin).toHex(),
180
+ ],
181
+ [
182
+ compactHex(meta.query.messageQueue.pages(origin, 0)),
183
+ meta.registry
184
+ .createType('PalletMessageQueuePage', {
185
+ remaining: messagesCount,
186
+ remaining_size: messagesSize,
187
+ first_index: 0,
188
+ first: 0,
189
+ last,
190
+ heap: compactAddLength(heap),
191
+ })
192
+ .toHex(),
193
+ ],
194
+ ]);
195
+ }
196
+ else {
197
+ throw new Error('Unknown ump storage');
198
+ }
199
+ logger.trace({ paraId, upwardMessages: truncate(upwardMessages) }, 'Pushed UMP');
200
+ }
201
+ if (meta.query.ump) {
202
+ const needsDispatch = meta.registry.createType('Vec<u32>', Object.keys(ump));
203
+ layer.set(compactHex(meta.query.ump.needsDispatch()), needsDispatch.toHex());
204
+ }
205
+ }
206
+ const { block: newBlock } = await initNewBlock(head, header, inherents, layer);
207
+ const pendingExtrinsics = [];
208
+ const includedExtrinsic = [];
209
+ // apply extrinsics
210
+ for (const extrinsic of extrinsics) {
211
+ try {
212
+ const resp = await newBlock.call('BlockBuilder_apply_extrinsic', [extrinsic]);
213
+ const outcome = registry.createType('ApplyExtrinsicResult', resp.result);
214
+ if (outcome.isErr) {
215
+ callbacks?.onApplyExtrinsicError?.(extrinsic, outcome.asErr);
216
+ continue;
217
+ }
218
+ newBlock.pushStorageLayer().setAll(resp.storageDiff);
219
+ includedExtrinsic.push(extrinsic);
220
+ callbacks?.onPhaseApplied?.(includedExtrinsic.length - 1, resp);
221
+ }
222
+ catch (e) {
223
+ logger.info('Failed to apply extrinsic %o %s', e, e);
224
+ pendingExtrinsics.push(extrinsic);
225
+ }
226
+ }
227
+ {
228
+ // finalize block
229
+ const resp = await newBlock.call('BlockBuilder_finalize_block', []);
230
+ newBlock.pushStorageLayer().setAll(resp.storageDiff);
231
+ callbacks?.onPhaseApplied?.('finalize', resp);
232
+ }
233
+ const blockData = registry.createType('Block', {
234
+ header,
235
+ extrinsics: includedExtrinsic,
236
+ });
237
+ const storageDiff = await newBlock.storageDiff();
238
+ if (logger.level.toLowerCase() === 'trace') {
239
+ logger.trace(Object.entries(storageDiff).map(([key, value]) => [key, truncate(value)]), 'Final block');
240
+ }
241
+ const finalBlock = new Block(head.chain, newBlock.number, blockData.hash.toHex(), head, {
242
+ header,
243
+ extrinsics: [...inherents, ...includedExtrinsic],
244
+ storage: head.storage,
245
+ storageDiff,
246
+ });
247
+ logger.info({
248
+ number: newBlock.number,
249
+ hash: finalBlock.hash,
250
+ extrinsics: truncate(includedExtrinsic),
251
+ pendingExtrinsicsCount: pendingExtrinsics.length,
252
+ ump: truncate(ump),
253
+ }, 'Block built');
254
+ return [finalBlock, pendingExtrinsics];
255
+ };
256
+ export const dryRunExtrinsic = async (head, inherents, extrinsic) => {
257
+ const registry = await head.registry;
258
+ const header = await newHeader(head);
259
+ const { block: newBlock } = await initNewBlock(head, header, inherents);
260
+ if (typeof extrinsic !== 'string') {
261
+ if (!head.chain.mockSignatureHost) {
262
+ throw new Error('Cannot fake signature because mock signature host is not enabled. Start chain with `mockSignatureHost: true`');
263
+ }
264
+ const meta = await head.meta;
265
+ const call = registry.createType('Call', hexToU8a(extrinsic.call));
266
+ const generic = registry.createType('GenericExtrinsic', call);
267
+ const accountRaw = await head.get(compactHex(meta.query.system.account(extrinsic.address)));
268
+ const account = registry.createType('AccountInfo', hexToU8a(accountRaw));
269
+ generic.signFake(extrinsic.address, {
270
+ blockHash: head.hash,
271
+ genesisHash: head.hash,
272
+ runtimeVersion: await head.runtimeVersion,
273
+ nonce: account.nonce,
274
+ });
275
+ const mockSignature = new Uint8Array(64);
276
+ mockSignature.fill(0xcd);
277
+ mockSignature.set([0xde, 0xad, 0xbe, 0xef]);
278
+ generic.signature.set(mockSignature);
279
+ defaultLogger.info({ call: call.toHuman() }, 'dry_run_call');
280
+ return newBlock.call('BlockBuilder_apply_extrinsic', [generic.toHex()]);
281
+ }
282
+ defaultLogger.info({ call: registry.createType('GenericExtrinsic', hexToU8a(extrinsic)).toHuman() }, 'dry_run_extrinsic');
283
+ return newBlock.call('BlockBuilder_apply_extrinsic', [extrinsic]);
284
+ };
285
+ export const dryRunInherents = async (head, inherents) => {
286
+ const header = await newHeader(head);
287
+ const { layers } = await initNewBlock(head, header, inherents);
288
+ const storage = {};
289
+ for (const layer of layers) {
290
+ await layer.mergeInto(storage);
291
+ }
292
+ return Object.entries(storage);
293
+ };