@acala-network/chopsticks 0.2.2 → 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.
- package/LICENSE +201 -0
- package/README.md +6 -0
- package/dist/api.d.ts +3 -2
- package/dist/api.js +15 -20
- package/dist/blockchain/block-builder.d.ts +4 -0
- package/dist/blockchain/block-builder.js +71 -0
- package/dist/blockchain/block.d.ts +12 -8
- package/dist/blockchain/block.js +34 -75
- package/dist/blockchain/head-state.d.ts +4 -2
- package/dist/blockchain/head-state.js +13 -7
- package/dist/blockchain/index.d.ts +14 -13
- package/dist/blockchain/index.js +31 -27
- package/dist/blockchain/inherent/index.d.ts +17 -0
- package/dist/blockchain/inherent/index.js +32 -0
- package/dist/blockchain/inherent/para-enter.d.ts +7 -0
- package/dist/blockchain/inherent/para-enter.js +33 -0
- package/dist/blockchain/inherent/parachain/validation-data.d.ts +25 -0
- package/dist/blockchain/{inherents.js → inherent/parachain/validation-data.js} +87 -55
- package/dist/blockchain/txpool.d.ts +19 -3
- package/dist/blockchain/txpool.js +46 -81
- package/dist/decode-key.d.ts +2 -0
- package/dist/decode-key.js +24 -0
- package/dist/executor.d.ts +23 -4
- package/dist/executor.js +60 -12
- package/dist/executor.test.js +16 -21
- package/dist/genesis-provider.d.ts +5 -0
- package/dist/genesis-provider.js +21 -2
- package/dist/index.d.ts +1 -21
- package/dist/index.js +43 -159
- package/dist/logger.d.ts +3 -1
- package/dist/logger.js +5 -1
- package/dist/rpc/dev.js +11 -1
- package/dist/rpc/index.js +0 -2
- package/dist/rpc/shared.d.ts +0 -6
- package/dist/rpc/substrate/author.d.ts +1 -1
- package/dist/rpc/substrate/author.js +7 -2
- package/dist/rpc/substrate/chain.js +2 -2
- package/dist/rpc/substrate/state.js +1 -1
- package/dist/rpc/substrate/system.js +3 -3
- package/dist/run-block.d.ts +2 -0
- package/dist/run-block.js +36 -0
- package/dist/schema/index.d.ts +2 -5
- package/dist/schema/index.js +1 -2
- package/dist/server.d.ts +3 -3
- package/dist/server.js +26 -11
- package/dist/setup-with-server.d.ts +8 -0
- package/dist/setup-with-server.js +23 -0
- package/dist/setup.d.ts +10 -0
- package/dist/setup.js +62 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.js +9 -1
- package/dist/utils/proof.d.ts +10 -2
- package/dist/utils/proof.js +12 -8
- package/dist/utils/set-storage.d.ts +2 -1
- package/dist/utils/set-storage.js +1 -1
- package/dist/utils/time-travel.d.ts +5 -0
- package/dist/utils/time-travel.js +64 -0
- package/dist/xcm/index.d.ts +3 -0
- package/dist/xcm/index.js +67 -0
- package/package.json +9 -10
- package/dist/blockchain/inherents.d.ts +0 -26
- package/dist/rpc/exec.d.ts +0 -3
- package/dist/rpc/exec.js +0 -44
- package/dist/task.d.ts +0 -38
- package/dist/task.js +0 -67
|
@@ -1,35 +1,36 @@
|
|
|
1
1
|
import { DataSource } from 'typeorm';
|
|
2
|
-
import {
|
|
2
|
+
import { HexString } from '@polkadot/util/types';
|
|
3
3
|
import { Api } from '../api';
|
|
4
4
|
import { Block } from './block';
|
|
5
|
-
import { BuildBlockMode } from './txpool';
|
|
5
|
+
import { BuildBlockMode, BuildBlockParams } from './txpool';
|
|
6
6
|
import { HeadState } from './head-state';
|
|
7
|
-
import { InherentProvider } from './
|
|
8
|
-
import { TaskManager } from '../task';
|
|
7
|
+
import { InherentProvider } from './inherent';
|
|
9
8
|
export interface Options {
|
|
10
9
|
api: Api;
|
|
11
|
-
tasks: TaskManager;
|
|
12
10
|
buildBlockMode?: BuildBlockMode;
|
|
13
11
|
inherentProvider: InherentProvider;
|
|
14
12
|
db?: DataSource;
|
|
15
13
|
header: {
|
|
16
14
|
number: number;
|
|
17
|
-
hash:
|
|
15
|
+
hash: HexString;
|
|
18
16
|
};
|
|
17
|
+
mockSignatureHost?: boolean;
|
|
18
|
+
allowUnresolvedImports?: boolean;
|
|
19
19
|
}
|
|
20
20
|
export declare class Blockchain {
|
|
21
21
|
#private;
|
|
22
22
|
readonly api: Api;
|
|
23
|
-
readonly tasks: TaskManager;
|
|
24
23
|
readonly db: DataSource | undefined;
|
|
24
|
+
readonly mockSignatureHost: boolean;
|
|
25
|
+
readonly allowUnresolvedImports: boolean;
|
|
25
26
|
readonly headState: HeadState;
|
|
26
|
-
constructor({ api,
|
|
27
|
+
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost, allowUnresolvedImports, }: Options);
|
|
27
28
|
get head(): Block;
|
|
29
|
+
get pendingExtrinsics(): HexString[];
|
|
28
30
|
getBlockAt(number?: number): Promise<Block | undefined>;
|
|
29
|
-
getBlock(hash?:
|
|
30
|
-
newTempBlock(parent: Block, header: Header): Block;
|
|
31
|
+
getBlock(hash?: HexString): Promise<Block | undefined>;
|
|
31
32
|
unregisterBlock(block: Block): void;
|
|
32
|
-
setHead(block: Block): void
|
|
33
|
-
submitExtrinsic(extrinsic:
|
|
34
|
-
newBlock(): Promise<Block>;
|
|
33
|
+
setHead(block: Block): Promise<void>;
|
|
34
|
+
submitExtrinsic(extrinsic: HexString): Promise<HexString>;
|
|
35
|
+
newBlock(params?: BuildBlockParams): Promise<Block>;
|
|
35
36
|
}
|
package/dist/blockchain/index.js
CHANGED
|
@@ -6,22 +6,24 @@ 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
10
|
const logger = logger_1.defaultLogger.child({ name: 'blockchain' });
|
|
12
11
|
class Blockchain {
|
|
13
12
|
api;
|
|
14
|
-
tasks;
|
|
15
13
|
db;
|
|
14
|
+
mockSignatureHost;
|
|
15
|
+
allowUnresolvedImports;
|
|
16
16
|
#txpool;
|
|
17
17
|
#head;
|
|
18
18
|
#blocksByNumber = [];
|
|
19
19
|
#blocksByHash = {};
|
|
20
|
+
#loadingBlocks = {};
|
|
20
21
|
headState;
|
|
21
|
-
constructor({ api,
|
|
22
|
+
constructor({ api, buildBlockMode, inherentProvider, db, header, mockSignatureHost = false, allowUnresolvedImports = false, }) {
|
|
22
23
|
this.api = api;
|
|
23
|
-
this.tasks = tasks;
|
|
24
24
|
this.db = db;
|
|
25
|
+
this.mockSignatureHost = mockSignatureHost;
|
|
26
|
+
this.allowUnresolvedImports = allowUnresolvedImports;
|
|
25
27
|
this.#head = new block_1.Block(this, header.number, header.hash);
|
|
26
28
|
this.#registerBlock(this.#head);
|
|
27
29
|
this.#txpool = new txpool_1.TxPool(this, inherentProvider, buildBlockMode);
|
|
@@ -34,6 +36,9 @@ class Blockchain {
|
|
|
34
36
|
get head() {
|
|
35
37
|
return this.#head;
|
|
36
38
|
}
|
|
39
|
+
get pendingExtrinsics() {
|
|
40
|
+
return this.#txpool.pendingExtrinsics;
|
|
41
|
+
}
|
|
37
42
|
async getBlockAt(number) {
|
|
38
43
|
if (number === undefined) {
|
|
39
44
|
return this.head;
|
|
@@ -54,29 +59,28 @@ class Blockchain {
|
|
|
54
59
|
hash = this.head.hash;
|
|
55
60
|
}
|
|
56
61
|
if (!this.#blocksByHash[hash]) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
const block = new block_1.Block(this, header.number.toNumber(), hash);
|
|
61
|
-
this.#registerBlock(block);
|
|
62
|
+
const loadingBlock = this.#loadingBlocks[hash];
|
|
63
|
+
if (loadingBlock) {
|
|
64
|
+
await loadingBlock;
|
|
62
65
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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];
|
|
66
80
|
}
|
|
67
81
|
}
|
|
68
82
|
return this.#blocksByHash[hash];
|
|
69
83
|
}
|
|
70
|
-
newTempBlock(parent, header) {
|
|
71
|
-
const number = parent.number + 1;
|
|
72
|
-
const hash = '0x' +
|
|
73
|
-
Math.round(Math.random() * 100000000)
|
|
74
|
-
.toString(16)
|
|
75
|
-
.padEnd(64, '0');
|
|
76
|
-
const block = new block_1.Block(this, number, hash, parent, { header, extrinsics: [], storage: parent.storage });
|
|
77
|
-
this.#blocksByHash[hash] = block;
|
|
78
|
-
return block;
|
|
79
|
-
}
|
|
80
84
|
unregisterBlock(block) {
|
|
81
85
|
if (block.hash === this.head.hash) {
|
|
82
86
|
throw new Error('Cannot unregister head block');
|
|
@@ -86,14 +90,14 @@ class Blockchain {
|
|
|
86
90
|
}
|
|
87
91
|
delete this.#blocksByHash[block.hash];
|
|
88
92
|
}
|
|
89
|
-
setHead(block) {
|
|
93
|
+
async setHead(block) {
|
|
90
94
|
logger.debug({
|
|
91
95
|
number: block.number,
|
|
92
96
|
hash: block.hash,
|
|
93
97
|
}, 'setHead');
|
|
94
98
|
this.#head = block;
|
|
95
99
|
this.#registerBlock(block);
|
|
96
|
-
this.headState.setHead(block);
|
|
100
|
+
await this.headState.setHead(block);
|
|
97
101
|
}
|
|
98
102
|
async submitExtrinsic(extrinsic) {
|
|
99
103
|
const source = '0x02'; // External
|
|
@@ -105,10 +109,10 @@ class Blockchain {
|
|
|
105
109
|
this.#txpool.submitExtrinsic(extrinsic);
|
|
106
110
|
return (0, util_crypto_1.blake2AsHex)(extrinsic, 256);
|
|
107
111
|
}
|
|
108
|
-
throw new
|
|
112
|
+
throw new Error(`Extrinsic is invalid: ${validity.asErr.toString()}`);
|
|
109
113
|
}
|
|
110
|
-
async newBlock() {
|
|
111
|
-
await this.#txpool.buildBlock();
|
|
114
|
+
async newBlock(params) {
|
|
115
|
+
await this.#txpool.buildBlock(params);
|
|
112
116
|
return this.#head;
|
|
113
117
|
}
|
|
114
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
|
+
}
|
|
@@ -1,24 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SetValidationData =
|
|
3
|
+
exports.SetValidationData = void 0;
|
|
4
4
|
const types_1 = require("@polkadot/types");
|
|
5
|
-
const utils_1 = require("../utils");
|
|
6
|
-
const executor_1 = require("../executor");
|
|
7
5
|
const util_1 = require("@polkadot/util");
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
this.#getTimestamp = getTimestamp;
|
|
13
|
-
}
|
|
14
|
-
async createInherents(meta, timestamp, _parent) {
|
|
15
|
-
return [new types_1.GenericExtrinsic(meta.registry, meta.tx.timestamp.set(timestamp)).toHex()];
|
|
16
|
-
}
|
|
17
|
-
getTimestamp(blockNumber) {
|
|
18
|
-
return this.#getTimestamp(blockNumber);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
exports.SetTimestamp = SetTimestamp;
|
|
6
|
+
const util_crypto_1 = require("@polkadot/util-crypto");
|
|
7
|
+
const utils_1 = require("../../../utils");
|
|
8
|
+
const executor_1 = require("../../../executor");
|
|
9
|
+
const proof_1 = require("../../../utils/proof");
|
|
22
10
|
const MOCK_VALIDATION_DATA = {
|
|
23
11
|
validationData: {
|
|
24
12
|
relayParentNumber: 1000,
|
|
@@ -43,60 +31,104 @@ const MOCK_VALIDATION_DATA = {
|
|
|
43
31
|
],
|
|
44
32
|
},
|
|
45
33
|
};
|
|
46
|
-
class InherentProviders {
|
|
47
|
-
#base;
|
|
48
|
-
#providers;
|
|
49
|
-
constructor(base, providers) {
|
|
50
|
-
this.#base = base;
|
|
51
|
-
this.#providers = providers;
|
|
52
|
-
}
|
|
53
|
-
async createInherents(meta, timestamp, parent) {
|
|
54
|
-
const base = await this.#base.createInherents(meta, timestamp, parent);
|
|
55
|
-
const extra = await Promise.all(this.#providers.map((provider) => provider.createInherents(meta, timestamp, parent)));
|
|
56
|
-
return [...base, ...extra.flat()];
|
|
57
|
-
}
|
|
58
|
-
getTimestamp(blockNumber) {
|
|
59
|
-
return this.#base.getTimestamp(blockNumber);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
exports.InherentProviders = InherentProviders;
|
|
63
34
|
class SetValidationData {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
constructor(tasks, expectedIndex) {
|
|
67
|
-
this.#tasks = tasks;
|
|
68
|
-
this.#expectedIndex = expectedIndex;
|
|
69
|
-
}
|
|
70
|
-
async createInherents(meta, _timestamp, parent) {
|
|
35
|
+
async createInherents(parent, params) {
|
|
36
|
+
const meta = await parent.meta;
|
|
71
37
|
if (!meta.tx.parachainSystem?.setValidationData) {
|
|
72
38
|
return [];
|
|
73
39
|
}
|
|
74
|
-
|
|
75
|
-
const parentBlock = await parent.parentBlock;
|
|
76
|
-
if (!parentBlock) {
|
|
77
|
-
throw new Error('Parent block not found');
|
|
78
|
-
}
|
|
79
|
-
const extrinsics = await parentBlock.extrinsics;
|
|
40
|
+
const extrinsics = await parent.extrinsics;
|
|
80
41
|
let newData;
|
|
81
|
-
if (
|
|
42
|
+
if (parent.number === 0) {
|
|
82
43
|
// chain started with genesis, mock 1st validationData
|
|
83
44
|
newData = MOCK_VALIDATION_DATA;
|
|
84
45
|
}
|
|
85
46
|
else {
|
|
86
|
-
const
|
|
87
|
-
|
|
47
|
+
const validationDataExtrinsic = extrinsics.find((extrinsic) => {
|
|
48
|
+
const firstArg = meta.registry.createType('GenericExtrinsic', extrinsic)?.args?.[0];
|
|
49
|
+
return firstArg && 'validationData' in firstArg;
|
|
50
|
+
});
|
|
51
|
+
if (!validationDataExtrinsic) {
|
|
52
|
+
throw new Error('Missing validation data from block');
|
|
53
|
+
}
|
|
54
|
+
const extrinsic = meta.registry
|
|
55
|
+
.createType('GenericExtrinsic', validationDataExtrinsic)
|
|
56
|
+
.args[0].toJSON();
|
|
88
57
|
const newEntries = [];
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
58
|
+
const downwardMessages = [];
|
|
59
|
+
const horizontalMessages = {};
|
|
60
|
+
const paraId = await (0, utils_1.getParaId)(parent.chain);
|
|
61
|
+
const dmqMqcHeadKey = (0, proof_1.dmqMqcHead)(paraId);
|
|
62
|
+
const hrmpIngressChannelIndexKey = (0, proof_1.hrmpIngressChannelIndex)(paraId);
|
|
63
|
+
const decoded = await (0, executor_1.decodeProof)(extrinsic.validationData.relayParentStorageRoot, [dmqMqcHeadKey, hrmpIngressChannelIndexKey], extrinsic.relayChainState.trieNodes);
|
|
64
|
+
// inject downward messages
|
|
65
|
+
if (params?.downwardMessages) {
|
|
66
|
+
let dmqMqcHeadHash = decoded[dmqMqcHeadKey];
|
|
67
|
+
if (!dmqMqcHeadHash)
|
|
68
|
+
throw new Error('Canoot find dmqMqcHead from validation data');
|
|
69
|
+
for (const { msg, sentAt } of params.downwardMessages) {
|
|
70
|
+
// calculate new hash
|
|
71
|
+
dmqMqcHeadHash = (0, util_crypto_1.blake2AsHex)((0, util_1.u8aConcat)(meta.registry.createType('Hash', dmqMqcHeadHash).toU8a(), meta.registry.createType('BlockNumber', sentAt).toU8a(), (0, util_crypto_1.blake2AsU8a)(meta.registry.createType('Bytes', msg).toU8a(), 256)), 256);
|
|
72
|
+
downwardMessages.push({
|
|
73
|
+
msg,
|
|
74
|
+
sent_at: sentAt,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
newEntries.push([dmqMqcHeadKey, dmqMqcHeadHash]);
|
|
78
|
+
}
|
|
79
|
+
const hrmpIngressChannels = meta.registry
|
|
80
|
+
.createType('Vec<ParaId>', decoded[hrmpIngressChannelIndexKey])
|
|
81
|
+
.toJSON();
|
|
82
|
+
// inject horizontal messages
|
|
83
|
+
if (params?.horizontalMessages) {
|
|
84
|
+
for (const [id, messages] of Object.entries(params.horizontalMessages)) {
|
|
85
|
+
const sender = Number(id);
|
|
86
|
+
if (hrmpIngressChannels.includes(sender)) {
|
|
87
|
+
const channelId = meta.registry.createType('HrmpChannelId', {
|
|
88
|
+
sender,
|
|
89
|
+
receiver: paraId.toNumber(),
|
|
90
|
+
});
|
|
91
|
+
const hrmpChannelKey = (0, proof_1.hrmpChannels)(channelId);
|
|
92
|
+
const decoded = await (0, executor_1.decodeProof)(extrinsic.validationData.relayParentStorageRoot, [hrmpChannelKey], extrinsic.relayChainState.trieNodes);
|
|
93
|
+
const abridgedHrmpRaw = decoded[hrmpChannelKey];
|
|
94
|
+
if (!abridgedHrmpRaw)
|
|
95
|
+
throw new Error('Canoot find hrmp channels from validation data');
|
|
96
|
+
const abridgedHrmp = meta.registry
|
|
97
|
+
.createType('AbridgedHrmpChannel', (0, util_1.hexToU8a)(abridgedHrmpRaw))
|
|
98
|
+
.toJSON();
|
|
99
|
+
const paraMessages = [];
|
|
100
|
+
for (const { data, sentAt } of messages) {
|
|
101
|
+
// calculate new hash
|
|
102
|
+
const bytes = meta.registry.createType('Bytes', data);
|
|
103
|
+
abridgedHrmp.mqcHead = (0, util_crypto_1.blake2AsHex)((0, util_1.u8aConcat)(meta.registry.createType('Hash', abridgedHrmp.mqcHead).toU8a(), meta.registry.createType('BlockNumber', sentAt).toU8a(), (0, util_crypto_1.blake2AsU8a)(bytes.toU8a(), 256)), 256);
|
|
104
|
+
abridgedHrmp.msgCount = abridgedHrmp.msgCount + 1;
|
|
105
|
+
abridgedHrmp.totalSize = abridgedHrmp.totalSize + bytes.length;
|
|
106
|
+
paraMessages.push({
|
|
107
|
+
data,
|
|
108
|
+
sent_at: sentAt,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
horizontalMessages[sender] = paraMessages;
|
|
112
|
+
newEntries.push([hrmpChannelKey, meta.registry.createType('AbridgedHrmpChannel', abridgedHrmp).toHex()]);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const upgradeKey = (0, proof_1.upgradeGoAheadSignal)(paraId);
|
|
117
|
+
const pendingUpgrade = await parent.get((0, utils_1.compactHex)(meta.query.parachainSystem.pendingValidationCode()));
|
|
118
|
+
if (pendingUpgrade) {
|
|
119
|
+
// send goAhead signal
|
|
94
120
|
const goAhead = meta.registry.createType('UpgradeGoAhead', 'GoAhead');
|
|
95
121
|
newEntries.push([upgradeKey, goAhead.toHex()]);
|
|
96
122
|
}
|
|
123
|
+
else {
|
|
124
|
+
// make sure previous goAhead is removed
|
|
125
|
+
newEntries.push([upgradeKey, null]);
|
|
126
|
+
}
|
|
97
127
|
const { trieRootHash, nodes } = await (0, executor_1.createProof)(extrinsic.validationData.relayParentStorageRoot, extrinsic.relayChainState.trieNodes, newEntries);
|
|
98
128
|
newData = {
|
|
99
129
|
...extrinsic,
|
|
130
|
+
downwardMessages,
|
|
131
|
+
horizontalMessages,
|
|
100
132
|
validationData: {
|
|
101
133
|
...extrinsic.validationData,
|
|
102
134
|
relayParentStorageRoot: trieRootHash,
|
|
@@ -1,13 +1,29 @@
|
|
|
1
|
+
import { HexString } from '@polkadot/util/types';
|
|
1
2
|
import { Blockchain } from '.';
|
|
2
|
-
import { InherentProvider } from './
|
|
3
|
+
import { InherentProvider } from './inherent';
|
|
3
4
|
export declare enum BuildBlockMode {
|
|
4
5
|
Batch = 0,
|
|
5
6
|
Instant = 1,
|
|
6
7
|
Manual = 2
|
|
7
8
|
}
|
|
9
|
+
export interface DownwardMessage {
|
|
10
|
+
sentAt: number;
|
|
11
|
+
msg: HexString;
|
|
12
|
+
}
|
|
13
|
+
export interface HorizontalMessage {
|
|
14
|
+
sentAt: number;
|
|
15
|
+
data: HexString;
|
|
16
|
+
}
|
|
17
|
+
export interface BuildBlockParams {
|
|
18
|
+
inherent?: {
|
|
19
|
+
downwardMessages?: DownwardMessage[];
|
|
20
|
+
horizontalMessages?: Record<number, HorizontalMessage[]>;
|
|
21
|
+
};
|
|
22
|
+
}
|
|
8
23
|
export declare class TxPool {
|
|
9
24
|
#private;
|
|
10
25
|
constructor(chain: Blockchain, inherentProvider: InherentProvider, mode?: BuildBlockMode);
|
|
11
|
-
|
|
12
|
-
|
|
26
|
+
get pendingExtrinsics(): HexString[];
|
|
27
|
+
submitExtrinsic(extrinsic: HexString): void;
|
|
28
|
+
buildBlock(params?: BuildBlockParams): Promise<void>;
|
|
13
29
|
}
|