@feelyourprotocol/blockchain 8141.0.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/README.md +269 -0
- package/dist/cjs/blockchain.d.ts +372 -0
- package/dist/cjs/blockchain.d.ts.map +1 -0
- package/dist/cjs/blockchain.js +1105 -0
- package/dist/cjs/blockchain.js.map +1 -0
- package/dist/cjs/consensus/casper.d.ts +16 -0
- package/dist/cjs/consensus/casper.d.ts.map +1 -0
- package/dist/cjs/consensus/casper.js +28 -0
- package/dist/cjs/consensus/casper.js.map +1 -0
- package/dist/cjs/consensus/clique.d.ts +164 -0
- package/dist/cjs/consensus/clique.d.ts.map +1 -0
- package/dist/cjs/consensus/clique.js +520 -0
- package/dist/cjs/consensus/clique.js.map +1 -0
- package/dist/cjs/consensus/ethash.d.ts +29 -0
- package/dist/cjs/consensus/ethash.d.ts.map +1 -0
- package/dist/cjs/consensus/ethash.js +48 -0
- package/dist/cjs/consensus/ethash.js.map +1 -0
- package/dist/cjs/consensus/index.d.ts +5 -0
- package/dist/cjs/consensus/index.d.ts.map +1 -0
- package/dist/cjs/consensus/index.js +10 -0
- package/dist/cjs/consensus/index.js.map +1 -0
- package/dist/cjs/constructors.d.ts +13 -0
- package/dist/cjs/constructors.d.ts.map +1 -0
- package/dist/cjs/constructors.js +80 -0
- package/dist/cjs/constructors.js.map +1 -0
- package/dist/cjs/db/cache.d.ts +17 -0
- package/dist/cjs/db/cache.d.ts.map +1 -0
- package/dist/cjs/db/cache.js +38 -0
- package/dist/cjs/db/cache.js.map +1 -0
- package/dist/cjs/db/constants.d.ts +23 -0
- package/dist/cjs/db/constants.d.ts.map +1 -0
- package/dist/cjs/db/constants.js +54 -0
- package/dist/cjs/db/constants.js.map +1 -0
- package/dist/cjs/db/helpers.d.ts +9 -0
- package/dist/cjs/db/helpers.d.ts.map +1 -0
- package/dist/cjs/db/helpers.js +68 -0
- package/dist/cjs/db/helpers.js.map +1 -0
- package/dist/cjs/db/manager.d.ts +78 -0
- package/dist/cjs/db/manager.d.ts.map +1 -0
- package/dist/cjs/db/manager.js +203 -0
- package/dist/cjs/db/manager.js.map +1 -0
- package/dist/cjs/db/operation.d.ts +45 -0
- package/dist/cjs/db/operation.d.ts.map +1 -0
- package/dist/cjs/db/operation.js +110 -0
- package/dist/cjs/db/operation.js.map +1 -0
- package/dist/cjs/helpers.d.ts +19 -0
- package/dist/cjs/helpers.d.ts.map +1 -0
- package/dist/cjs/helpers.js +34 -0
- package/dist/cjs/helpers.js.map +1 -0
- package/dist/cjs/index.d.ts +7 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +33 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/types.d.ts +219 -0
- package/dist/cjs/types.d.ts.map +1 -0
- package/dist/cjs/types.js +3 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/esm/blockchain.d.ts +372 -0
- package/dist/esm/blockchain.d.ts.map +1 -0
- package/dist/esm/blockchain.js +1101 -0
- package/dist/esm/blockchain.js.map +1 -0
- package/dist/esm/consensus/casper.d.ts +16 -0
- package/dist/esm/consensus/casper.d.ts.map +1 -0
- package/dist/esm/consensus/casper.js +24 -0
- package/dist/esm/consensus/casper.js.map +1 -0
- package/dist/esm/consensus/clique.d.ts +164 -0
- package/dist/esm/consensus/clique.d.ts.map +1 -0
- package/dist/esm/consensus/clique.js +516 -0
- package/dist/esm/consensus/clique.js.map +1 -0
- package/dist/esm/consensus/ethash.d.ts +29 -0
- package/dist/esm/consensus/ethash.d.ts.map +1 -0
- package/dist/esm/consensus/ethash.js +44 -0
- package/dist/esm/consensus/ethash.js.map +1 -0
- package/dist/esm/consensus/index.d.ts +5 -0
- package/dist/esm/consensus/index.d.ts.map +1 -0
- package/dist/esm/consensus/index.js +5 -0
- package/dist/esm/consensus/index.js.map +1 -0
- package/dist/esm/constructors.d.ts +13 -0
- package/dist/esm/constructors.d.ts.map +1 -0
- package/dist/esm/constructors.js +76 -0
- package/dist/esm/constructors.js.map +1 -0
- package/dist/esm/db/cache.d.ts +17 -0
- package/dist/esm/db/cache.d.ts.map +1 -0
- package/dist/esm/db/cache.js +34 -0
- package/dist/esm/db/cache.js.map +1 -0
- package/dist/esm/db/constants.d.ts +23 -0
- package/dist/esm/db/constants.d.ts.map +1 -0
- package/dist/esm/db/constants.js +46 -0
- package/dist/esm/db/constants.js.map +1 -0
- package/dist/esm/db/helpers.d.ts +9 -0
- package/dist/esm/db/helpers.d.ts.map +1 -0
- package/dist/esm/db/helpers.js +61 -0
- package/dist/esm/db/helpers.js.map +1 -0
- package/dist/esm/db/manager.d.ts +78 -0
- package/dist/esm/db/manager.d.ts.map +1 -0
- package/dist/esm/db/manager.js +199 -0
- package/dist/esm/db/manager.js.map +1 -0
- package/dist/esm/db/operation.d.ts +45 -0
- package/dist/esm/db/operation.d.ts.map +1 -0
- package/dist/esm/db/operation.js +106 -0
- package/dist/esm/db/operation.js.map +1 -0
- package/dist/esm/helpers.d.ts +19 -0
- package/dist/esm/helpers.d.ts.map +1 -0
- package/dist/esm/helpers.js +30 -0
- package/dist/esm/helpers.js.map +1 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/types.d.ts +219 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +2 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
- package/package.json +75 -0
- package/src/blockchain.ts +1353 -0
- package/src/consensus/casper.ts +33 -0
- package/src/consensus/clique.ts +633 -0
- package/src/consensus/ethash.ts +69 -0
- package/src/consensus/index.ts +5 -0
- package/src/constructors.ts +119 -0
- package/src/db/cache.ts +39 -0
- package/src/db/constants.ts +73 -0
- package/src/db/helpers.ts +81 -0
- package/src/db/manager.ts +243 -0
- package/src/db/operation.ts +152 -0
- package/src/helpers.ts +37 -0
- package/src/index.ts +12 -0
- package/src/types.ts +256 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CliqueConsensus = exports.CLIQUE_DIFF_NOTURN = exports.CLIQUE_DIFF_INTURN = exports.CLIQUE_NONCE_DROP = exports.CLIQUE_NONCE_AUTH = void 0;
|
|
4
|
+
const block_1 = require("@feelyourprotocol/block");
|
|
5
|
+
const common_1 = require("@feelyourprotocol/common");
|
|
6
|
+
const rlp_1 = require("@feelyourprotocol/rlp");
|
|
7
|
+
const util_1 = require("@feelyourprotocol/util");
|
|
8
|
+
const debug_1 = require("debug");
|
|
9
|
+
const debug = (0, debug_1.default)('blockchain:clique');
|
|
10
|
+
// Magic nonce number to vote on adding a new signer
|
|
11
|
+
exports.CLIQUE_NONCE_AUTH = new Uint8Array((0, util_1.hexToBytes)('0xffffffffffffffff').buffer);
|
|
12
|
+
// Magic nonce number to vote on removing a signer.
|
|
13
|
+
exports.CLIQUE_NONCE_DROP = new Uint8Array(8);
|
|
14
|
+
const CLIQUE_SIGNERS_KEY = 'CliqueSigners';
|
|
15
|
+
const CLIQUE_VOTES_KEY = 'CliqueVotes';
|
|
16
|
+
const CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY = 'CliqueBlockSignersSnapshot';
|
|
17
|
+
// Block difficulty for in-turn signatures
|
|
18
|
+
exports.CLIQUE_DIFF_INTURN = util_1.BIGINT_2;
|
|
19
|
+
// Block difficulty for out-of-turn signatures
|
|
20
|
+
exports.CLIQUE_DIFF_NOTURN = util_1.BIGINT_1;
|
|
21
|
+
/**
|
|
22
|
+
* This class encapsulates Clique-related consensus functionality when used with the Blockchain class.
|
|
23
|
+
* Note: reorgs which happen between epoch transitions, which change the internal voting state over the reorg
|
|
24
|
+
* will result in failure and is currently not supported.
|
|
25
|
+
* The hotfix for this could be: re-load the latest epoch block (this has the clique state in the extraData of the header)
|
|
26
|
+
* Now replay all blocks on top of it. This should validate the chain up to the new/reorged tip which previously threw.
|
|
27
|
+
*/
|
|
28
|
+
class CliqueConsensus {
|
|
29
|
+
constructor() {
|
|
30
|
+
/**
|
|
31
|
+
* Keep signer history data (signer states and votes)
|
|
32
|
+
* for all block numbers >= HEAD_BLOCK - CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT
|
|
33
|
+
*
|
|
34
|
+
* This defines a limit for reorgs on PoA clique chains.
|
|
35
|
+
*/
|
|
36
|
+
this.CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT = 200;
|
|
37
|
+
/**
|
|
38
|
+
* List with the latest signer states checkpointed on blocks where
|
|
39
|
+
* a change (added new or removed a signer) occurred.
|
|
40
|
+
*
|
|
41
|
+
* Format:
|
|
42
|
+
* [ [BLOCK_NUMBER_1, [SIGNER1, SIGNER 2,]], [BLOCK_NUMBER2, [SIGNER1, SIGNER3]], ...]
|
|
43
|
+
*
|
|
44
|
+
* The top element from the array represents the list of current signers.
|
|
45
|
+
* On reorgs elements from the array are removed until BLOCK_NUMBER > REORG_BLOCK.
|
|
46
|
+
*
|
|
47
|
+
* Always keep at least one item on the stack.
|
|
48
|
+
*/
|
|
49
|
+
this._cliqueLatestSignerStates = [];
|
|
50
|
+
/**
|
|
51
|
+
* List with the latest signer votes.
|
|
52
|
+
*
|
|
53
|
+
* Format:
|
|
54
|
+
* [ [BLOCK_NUMBER_1, [SIGNER, BENEFICIARY, AUTH]], [BLOCK_NUMBER_1, [SIGNER, BENEFICIARY, AUTH]] ]
|
|
55
|
+
* where AUTH = CLIQUE_NONCE_AUTH | CLIQUE_NONCE_DROP
|
|
56
|
+
*
|
|
57
|
+
* For votes all elements here must be taken into account with a
|
|
58
|
+
* block number >= LAST_EPOCH_BLOCK
|
|
59
|
+
* (nevertheless keep entries with blocks before EPOCH_BLOCK in case a reorg happens
|
|
60
|
+
* during an epoch change)
|
|
61
|
+
*
|
|
62
|
+
* On reorgs elements from the array are removed until BLOCK_NUMBER > REORG_BLOCK.
|
|
63
|
+
*/
|
|
64
|
+
this._cliqueLatestVotes = [];
|
|
65
|
+
/**
|
|
66
|
+
* List of signers for the last consecutive {@link Blockchain.cliqueSignerLimit} blocks.
|
|
67
|
+
* Kept as a snapshot for quickly checking for "recently signed" error.
|
|
68
|
+
* Format: [ [BLOCK_NUMBER, SIGNER_ADDRESS], ...]
|
|
69
|
+
*
|
|
70
|
+
* On reorgs elements from the array are removed until BLOCK_NUMBER > REORG_BLOCK.
|
|
71
|
+
*/
|
|
72
|
+
this._cliqueLatestBlockSigners = [];
|
|
73
|
+
// Skip DEBUG calls unless 'ethjs' included in environmental DEBUG variables
|
|
74
|
+
this.DEBUG = (0, util_1.isDebugEnabled)('ethjs');
|
|
75
|
+
this.algorithm = common_1.ConsensusAlgorithm.Clique;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
*
|
|
79
|
+
* @param param dictionary containing a {@link Blockchain} object
|
|
80
|
+
*
|
|
81
|
+
* Note: this method must be called before consensus checks are used or type errors will occur
|
|
82
|
+
*/
|
|
83
|
+
async setup({ blockchain }) {
|
|
84
|
+
this.blockchain = blockchain;
|
|
85
|
+
this._cliqueLatestSignerStates = await this.getCliqueLatestSignerStates();
|
|
86
|
+
this._cliqueLatestSignerStates.sort((a, b) => (a[0] > b[0] ? 1 : -1));
|
|
87
|
+
this._cliqueLatestVotes = await this.getCliqueLatestVotes();
|
|
88
|
+
this._cliqueLatestBlockSigners = await this.getCliqueLatestBlockSigners();
|
|
89
|
+
}
|
|
90
|
+
async genesisInit(genesisBlock) {
|
|
91
|
+
await this.cliqueSaveGenesisSigners(genesisBlock);
|
|
92
|
+
}
|
|
93
|
+
async validateConsensus(block) {
|
|
94
|
+
if (!this.blockchain) {
|
|
95
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)('blockchain not provided');
|
|
96
|
+
}
|
|
97
|
+
const { header } = block;
|
|
98
|
+
const valid = (0, block_1.cliqueVerifySignature)(header, this.cliqueActiveSigners(header.number));
|
|
99
|
+
if (!valid) {
|
|
100
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)('invalid PoA block signature (clique)');
|
|
101
|
+
}
|
|
102
|
+
if (this.cliqueCheckRecentlySigned(header)) {
|
|
103
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)('recently signed');
|
|
104
|
+
}
|
|
105
|
+
// validate checkpoint signers towards active signers on epoch transition blocks
|
|
106
|
+
if ((0, block_1.cliqueIsEpochTransition)(header)) {
|
|
107
|
+
// note: keep votes on epoch transition blocks in case of reorgs.
|
|
108
|
+
// only active (non-stale) votes will counted (if vote.blockNumber >= lastEpochBlockNumber
|
|
109
|
+
const checkpointSigners = (0, block_1.cliqueEpochTransitionSigners)(header);
|
|
110
|
+
const activeSigners = this.cliqueActiveSigners(header.number);
|
|
111
|
+
for (const [i, cSigner] of checkpointSigners.entries()) {
|
|
112
|
+
if (activeSigners[i]?.equals(cSigner) !== true) {
|
|
113
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)(`checkpoint signer not found in active signers list at index ${i}: ${cSigner}`);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
async validateDifficulty(header) {
|
|
119
|
+
if (!this.blockchain) {
|
|
120
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)('blockchain not provided');
|
|
121
|
+
}
|
|
122
|
+
if (header.difficulty !== exports.CLIQUE_DIFF_INTURN && header.difficulty !== exports.CLIQUE_DIFF_NOTURN) {
|
|
123
|
+
const msg = `difficulty for clique block must be INTURN (2) or NOTURN (1), received: ${header.difficulty}`;
|
|
124
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)(`${msg} ${header.errorStr()}`);
|
|
125
|
+
}
|
|
126
|
+
const signers = this.cliqueActiveSigners(header.number);
|
|
127
|
+
if (signers.length === 0) {
|
|
128
|
+
// abort if signers are unavailable
|
|
129
|
+
const msg = 'no signers available';
|
|
130
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)(`${msg} ${header.errorStr()}`);
|
|
131
|
+
}
|
|
132
|
+
const signerIndex = signers.findIndex((address) => address.equals((0, block_1.cliqueSigner)(header)));
|
|
133
|
+
const inTurn = header.number % BigInt(signers.length) === BigInt(signerIndex);
|
|
134
|
+
if ((inTurn && header.difficulty === exports.CLIQUE_DIFF_INTURN) ||
|
|
135
|
+
(!inTurn && header.difficulty === exports.CLIQUE_DIFF_NOTURN)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)(`'invalid clique difficulty ${header.errorStr()}`);
|
|
139
|
+
}
|
|
140
|
+
async newBlock(block, commonAncestor) {
|
|
141
|
+
// Clique: update signer votes and state
|
|
142
|
+
const { header } = block;
|
|
143
|
+
const commonAncestorNumber = commonAncestor?.number;
|
|
144
|
+
if (commonAncestorNumber !== undefined) {
|
|
145
|
+
await this._cliqueDeleteSnapshots(commonAncestorNumber + util_1.BIGINT_1);
|
|
146
|
+
for (let number = commonAncestorNumber + BigInt(1); number <= header.number; number++) {
|
|
147
|
+
const canonicalHeader = await this.blockchain.getCanonicalHeader(number);
|
|
148
|
+
await this._cliqueBuildSnapshots(canonicalHeader);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Save genesis signers to db
|
|
154
|
+
* @param genesisBlock genesis block
|
|
155
|
+
* @hidden
|
|
156
|
+
*/
|
|
157
|
+
async cliqueSaveGenesisSigners(genesisBlock) {
|
|
158
|
+
const genesisSignerState = [
|
|
159
|
+
util_1.BIGINT_0,
|
|
160
|
+
(0, block_1.cliqueEpochTransitionSigners)(genesisBlock.header),
|
|
161
|
+
];
|
|
162
|
+
await this.cliqueUpdateSignerStates(genesisSignerState);
|
|
163
|
+
this.DEBUG && debug(`[Block 0] Genesis block -> update signer states`);
|
|
164
|
+
await this.cliqueUpdateVotes();
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Save signer state to db
|
|
168
|
+
* @param signerState
|
|
169
|
+
* @hidden
|
|
170
|
+
*/
|
|
171
|
+
async cliqueUpdateSignerStates(signerState) {
|
|
172
|
+
if (signerState) {
|
|
173
|
+
const blockNumber = signerState[0];
|
|
174
|
+
const known = this._cliqueLatestSignerStates.find((value) => {
|
|
175
|
+
if (value[0] === blockNumber) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
if (known !== undefined) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
this._cliqueLatestSignerStates.push(signerState);
|
|
183
|
+
this._cliqueLatestSignerStates.sort((a, b) => (a[0] > b[0] ? 1 : -1));
|
|
184
|
+
}
|
|
185
|
+
// trim to CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT
|
|
186
|
+
const limit = this.CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT;
|
|
187
|
+
const blockSigners = this._cliqueLatestBlockSigners;
|
|
188
|
+
const lastBlockNumber = blockSigners[blockSigners.length - 1]?.[0];
|
|
189
|
+
if (lastBlockNumber) {
|
|
190
|
+
const blockLimit = lastBlockNumber - BigInt(limit);
|
|
191
|
+
const states = this._cliqueLatestSignerStates;
|
|
192
|
+
const lastItem = states[states.length - 1];
|
|
193
|
+
this._cliqueLatestSignerStates = states.filter((state) => state[0] >= blockLimit);
|
|
194
|
+
if (this._cliqueLatestSignerStates.length === 0) {
|
|
195
|
+
// always keep at least one item on the stack
|
|
196
|
+
this._cliqueLatestSignerStates.push(lastItem);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// save to db
|
|
200
|
+
const formatted = this._cliqueLatestSignerStates.map((state) => [
|
|
201
|
+
(0, util_1.bigIntToBytes)(state[0]),
|
|
202
|
+
state[1].map((a) => a.toBytes()),
|
|
203
|
+
]);
|
|
204
|
+
await this.blockchain.db.put(CLIQUE_SIGNERS_KEY, rlp_1.RLP.encode(formatted));
|
|
205
|
+
// Output active signers for debugging purposes
|
|
206
|
+
if (signerState !== undefined) {
|
|
207
|
+
let i = 0;
|
|
208
|
+
try {
|
|
209
|
+
for (const signer of this.cliqueActiveSigners(signerState[0])) {
|
|
210
|
+
this.DEBUG && debug(`Clique signer [${i}]: ${signer} (block: ${signerState[0]})`);
|
|
211
|
+
i++;
|
|
212
|
+
}
|
|
213
|
+
// eslint-disable-next-line no-empty
|
|
214
|
+
}
|
|
215
|
+
catch { }
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Update clique votes and save to db
|
|
220
|
+
* @param header BlockHeader
|
|
221
|
+
* @hidden
|
|
222
|
+
*/
|
|
223
|
+
async cliqueUpdateVotes(header) {
|
|
224
|
+
// Block contains a vote on a new signer
|
|
225
|
+
if (header && !header.coinbase.isZero()) {
|
|
226
|
+
const signer = (0, block_1.cliqueSigner)(header);
|
|
227
|
+
const beneficiary = header.coinbase;
|
|
228
|
+
const nonce = header.nonce;
|
|
229
|
+
const latestVote = [header.number, [signer, beneficiary, nonce]];
|
|
230
|
+
// Do two rounds here, one to execute on a potential previously reached consensus
|
|
231
|
+
// on the newly touched beneficiary, one with the added new vote
|
|
232
|
+
for (let round = 1; round <= 2; round++) {
|
|
233
|
+
// See if there is a new majority consensus to update the signer list
|
|
234
|
+
const lastEpochBlockNumber = header.number -
|
|
235
|
+
(header.number %
|
|
236
|
+
BigInt(this.blockchain.common.consensusConfig().epoch));
|
|
237
|
+
const limit = this.cliqueSignerLimit(header.number);
|
|
238
|
+
let activeSigners = [...this.cliqueActiveSigners(header.number)];
|
|
239
|
+
let consensus = false;
|
|
240
|
+
// AUTH vote analysis
|
|
241
|
+
let votes = this._cliqueLatestVotes.filter((vote) => {
|
|
242
|
+
return (vote[0] >= BigInt(lastEpochBlockNumber) &&
|
|
243
|
+
!vote[1][0].equals(signer) &&
|
|
244
|
+
vote[1][1].equals(beneficiary) &&
|
|
245
|
+
(0, util_1.equalsBytes)(vote[1][2], exports.CLIQUE_NONCE_AUTH));
|
|
246
|
+
});
|
|
247
|
+
const beneficiaryVotesAUTH = [];
|
|
248
|
+
for (const vote of votes) {
|
|
249
|
+
const num = beneficiaryVotesAUTH.filter((voteCMP) => {
|
|
250
|
+
return voteCMP.equals(vote[1][0]);
|
|
251
|
+
}).length;
|
|
252
|
+
if (num === 0) {
|
|
253
|
+
beneficiaryVotesAUTH.push(vote[1][0]);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
let numBeneficiaryVotesAUTH = beneficiaryVotesAUTH.length;
|
|
257
|
+
if (round === 2 && (0, util_1.equalsBytes)(nonce, exports.CLIQUE_NONCE_AUTH)) {
|
|
258
|
+
numBeneficiaryVotesAUTH += 1;
|
|
259
|
+
}
|
|
260
|
+
// Majority consensus
|
|
261
|
+
if (numBeneficiaryVotesAUTH >= limit) {
|
|
262
|
+
consensus = true;
|
|
263
|
+
// Authorize new signer
|
|
264
|
+
activeSigners.push(beneficiary);
|
|
265
|
+
activeSigners.sort((a, b) => {
|
|
266
|
+
// Sort by array size
|
|
267
|
+
const result = (0, util_1.toType)(a.toString(), util_1.TypeOutput.BigInt) < (0, util_1.toType)(b.toString(), util_1.TypeOutput.BigInt);
|
|
268
|
+
if (result) {
|
|
269
|
+
return -1;
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
return 1;
|
|
273
|
+
}
|
|
274
|
+
});
|
|
275
|
+
// Discard votes for added signer
|
|
276
|
+
this._cliqueLatestVotes = this._cliqueLatestVotes.filter((vote) => !vote[1][1].equals(beneficiary));
|
|
277
|
+
this.DEBUG &&
|
|
278
|
+
debug(`[Block ${header.number}] Clique majority consensus (AUTH ${beneficiary})`);
|
|
279
|
+
}
|
|
280
|
+
// DROP vote
|
|
281
|
+
votes = this._cliqueLatestVotes.filter((vote) => {
|
|
282
|
+
return (vote[0] >= BigInt(lastEpochBlockNumber) &&
|
|
283
|
+
!vote[1][0].equals(signer) &&
|
|
284
|
+
vote[1][1].equals(beneficiary) &&
|
|
285
|
+
(0, util_1.equalsBytes)(vote[1][2], exports.CLIQUE_NONCE_DROP));
|
|
286
|
+
});
|
|
287
|
+
const beneficiaryVotesDROP = [];
|
|
288
|
+
for (const vote of votes) {
|
|
289
|
+
const num = beneficiaryVotesDROP.filter((voteCMP) => {
|
|
290
|
+
return voteCMP.equals(vote[1][0]);
|
|
291
|
+
}).length;
|
|
292
|
+
if (num === 0) {
|
|
293
|
+
beneficiaryVotesDROP.push(vote[1][0]);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
let numBeneficiaryVotesDROP = beneficiaryVotesDROP.length;
|
|
297
|
+
if (round === 2 && (0, util_1.equalsBytes)(nonce, exports.CLIQUE_NONCE_DROP)) {
|
|
298
|
+
numBeneficiaryVotesDROP += 1;
|
|
299
|
+
}
|
|
300
|
+
// Majority consensus
|
|
301
|
+
if (numBeneficiaryVotesDROP >= limit) {
|
|
302
|
+
consensus = true;
|
|
303
|
+
// Drop signer
|
|
304
|
+
activeSigners = activeSigners.filter((signer) => !signer.equals(beneficiary));
|
|
305
|
+
this._cliqueLatestVotes = this._cliqueLatestVotes.filter(
|
|
306
|
+
// Discard votes from removed signer and for removed signer
|
|
307
|
+
(vote) => !vote[1][0].equals(beneficiary) && !vote[1][1].equals(beneficiary));
|
|
308
|
+
this.DEBUG &&
|
|
309
|
+
debug(`[Block ${header.number}] Clique majority consensus (DROP ${beneficiary})`);
|
|
310
|
+
}
|
|
311
|
+
if (round === 1) {
|
|
312
|
+
// Always add the latest vote to the history no matter if already voted
|
|
313
|
+
// the same vote or not
|
|
314
|
+
this._cliqueLatestVotes.push(latestVote);
|
|
315
|
+
this.DEBUG &&
|
|
316
|
+
debug(`[Block ${header.number}] New clique vote: ${signer} -> ${beneficiary} ${(0, util_1.equalsBytes)(nonce, exports.CLIQUE_NONCE_AUTH) ? 'AUTH' : 'DROP'}`);
|
|
317
|
+
}
|
|
318
|
+
if (consensus) {
|
|
319
|
+
if (round === 1) {
|
|
320
|
+
this.DEBUG &&
|
|
321
|
+
debug(`[Block ${header.number}] Clique majority consensus on existing votes -> update signer states`);
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
this.DEBUG &&
|
|
325
|
+
debug(`[Block ${header.number}] Clique majority consensus on new vote -> update signer states`);
|
|
326
|
+
}
|
|
327
|
+
const newSignerState = [header.number, activeSigners];
|
|
328
|
+
await this.cliqueUpdateSignerStates(newSignerState);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
// trim to lastEpochBlockNumber - CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT
|
|
334
|
+
const limit = this.CLIQUE_SIGNER_HISTORY_BLOCK_LIMIT;
|
|
335
|
+
const blockSigners = this._cliqueLatestBlockSigners;
|
|
336
|
+
const lastBlockNumber = blockSigners[blockSigners.length - 1]?.[0];
|
|
337
|
+
if (lastBlockNumber) {
|
|
338
|
+
const lastEpochBlockNumber = lastBlockNumber -
|
|
339
|
+
(lastBlockNumber %
|
|
340
|
+
BigInt(this.blockchain.common.consensusConfig().epoch));
|
|
341
|
+
const blockLimit = lastEpochBlockNumber - BigInt(limit);
|
|
342
|
+
this._cliqueLatestVotes = this._cliqueLatestVotes.filter((state) => state[0] >= blockLimit);
|
|
343
|
+
}
|
|
344
|
+
// save votes to db
|
|
345
|
+
const formatted = this._cliqueLatestVotes.map((v) => [
|
|
346
|
+
(0, util_1.bigIntToBytes)(v[0]),
|
|
347
|
+
[v[1][0].toBytes(), v[1][1].toBytes(), v[1][2]],
|
|
348
|
+
]);
|
|
349
|
+
await this.blockchain.db.put(CLIQUE_VOTES_KEY, rlp_1.RLP.encode(formatted));
|
|
350
|
+
}
|
|
351
|
+
/**
|
|
352
|
+
* Returns a list with the current block signers
|
|
353
|
+
*/
|
|
354
|
+
cliqueActiveSigners(blockNum) {
|
|
355
|
+
const signers = this._cliqueLatestSignerStates;
|
|
356
|
+
if (signers.length === 0) {
|
|
357
|
+
return [];
|
|
358
|
+
}
|
|
359
|
+
for (let i = signers.length - 1; i >= 0; i--) {
|
|
360
|
+
if (signers[i][0] < blockNum) {
|
|
361
|
+
return signers[i][1];
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)(`Could not load signers for block ${blockNum}`);
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Number of consecutive blocks out of which a signer may only sign one.
|
|
368
|
+
* Defined as `Math.floor(SIGNER_COUNT / 2) + 1` to enforce majority consensus.
|
|
369
|
+
* signer count -> signer limit:
|
|
370
|
+
* 1 -> 1, 2 -> 2, 3 -> 2, 4 -> 2, 5 -> 3, ...
|
|
371
|
+
* @hidden
|
|
372
|
+
*/
|
|
373
|
+
cliqueSignerLimit(blockNum) {
|
|
374
|
+
return Math.floor(this.cliqueActiveSigners(blockNum).length / 2) + 1;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Checks if signer was recently signed.
|
|
378
|
+
* Returns true if signed too recently: more than once per {@link CliqueConsensus.cliqueSignerLimit} consecutive blocks.
|
|
379
|
+
* @param header BlockHeader
|
|
380
|
+
* @hidden
|
|
381
|
+
*/
|
|
382
|
+
cliqueCheckRecentlySigned(header) {
|
|
383
|
+
if (header.isGenesis() || header.number === BigInt(1)) {
|
|
384
|
+
// skip genesis, first block
|
|
385
|
+
return false;
|
|
386
|
+
}
|
|
387
|
+
const limit = this.cliqueSignerLimit(header.number);
|
|
388
|
+
// construct recent block signers list with this block
|
|
389
|
+
let signers = this._cliqueLatestBlockSigners;
|
|
390
|
+
signers = signers.slice(signers.length < limit ? 0 : 1);
|
|
391
|
+
if (signers.length > 0 && signers[signers.length - 1][0] !== header.number - BigInt(1)) {
|
|
392
|
+
// if the last signed block is not one minus the head we are trying to compare
|
|
393
|
+
// we do not have a complete picture of the state to verify if too recently signed
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
signers.push([header.number, (0, block_1.cliqueSigner)(header)]);
|
|
397
|
+
const seen = signers.filter((s) => s[1].equals((0, block_1.cliqueSigner)(header))).length;
|
|
398
|
+
return seen > 1;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Remove clique snapshots with blockNumber higher than input.
|
|
402
|
+
* @param blockNumber - the block number from which we start deleting
|
|
403
|
+
* @hidden
|
|
404
|
+
*/
|
|
405
|
+
async _cliqueDeleteSnapshots(blockNumber) {
|
|
406
|
+
// remove blockNumber from clique snapshots
|
|
407
|
+
// (latest signer states, latest votes, latest block signers)
|
|
408
|
+
this._cliqueLatestSignerStates = this._cliqueLatestSignerStates.filter((s) => s[0] <= blockNumber);
|
|
409
|
+
await this.cliqueUpdateSignerStates();
|
|
410
|
+
this._cliqueLatestVotes = this._cliqueLatestVotes.filter((v) => v[0] <= blockNumber);
|
|
411
|
+
await this.cliqueUpdateVotes();
|
|
412
|
+
this._cliqueLatestBlockSigners = this._cliqueLatestBlockSigners.filter((s) => s[0] <= blockNumber);
|
|
413
|
+
await this.cliqueUpdateLatestBlockSigners();
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Update snapshot of latest clique block signers.
|
|
417
|
+
* Used for checking for 'recently signed' error.
|
|
418
|
+
* Length trimmed to {@link Blockchain.cliqueSignerLimit}.
|
|
419
|
+
* @param header BlockHeader
|
|
420
|
+
* @hidden
|
|
421
|
+
*/
|
|
422
|
+
async cliqueUpdateLatestBlockSigners(header) {
|
|
423
|
+
if (header) {
|
|
424
|
+
if (header.isGenesis()) {
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
// add this block's signer
|
|
428
|
+
const signer = [header.number, (0, block_1.cliqueSigner)(header)];
|
|
429
|
+
this._cliqueLatestBlockSigners.push(signer);
|
|
430
|
+
// trim length to `this.cliqueSignerLimit()`
|
|
431
|
+
const length = this._cliqueLatestBlockSigners.length;
|
|
432
|
+
const limit = this.cliqueSignerLimit(header.number);
|
|
433
|
+
if (length > limit) {
|
|
434
|
+
this._cliqueLatestBlockSigners = this._cliqueLatestBlockSigners.slice(length - limit, length);
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
// save to db
|
|
438
|
+
const formatted = this._cliqueLatestBlockSigners.map((b) => [
|
|
439
|
+
(0, util_1.bigIntToBytes)(b[0]),
|
|
440
|
+
b[1].toBytes(),
|
|
441
|
+
]);
|
|
442
|
+
await this.blockchain.db.put(CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY, rlp_1.RLP.encode(formatted));
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Fetches clique signers.
|
|
446
|
+
* @hidden
|
|
447
|
+
*/
|
|
448
|
+
async getCliqueLatestSignerStates() {
|
|
449
|
+
const signerStates = await this.blockchain.db.get(CLIQUE_SIGNERS_KEY);
|
|
450
|
+
if (signerStates === undefined)
|
|
451
|
+
return [];
|
|
452
|
+
const states = rlp_1.RLP.decode(signerStates);
|
|
453
|
+
return states.map((state) => {
|
|
454
|
+
const blockNum = (0, util_1.bytesToBigInt)(state[0]);
|
|
455
|
+
const addresses = state[1].map((bytes) => {
|
|
456
|
+
const address = new util_1.Address(bytes);
|
|
457
|
+
return address;
|
|
458
|
+
});
|
|
459
|
+
return [blockNum, addresses];
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Fetches clique votes.
|
|
464
|
+
* @hidden
|
|
465
|
+
*/
|
|
466
|
+
async getCliqueLatestVotes() {
|
|
467
|
+
const signerVotes = await this.blockchain.db.get(CLIQUE_VOTES_KEY);
|
|
468
|
+
if (signerVotes === undefined)
|
|
469
|
+
return [];
|
|
470
|
+
const votes = rlp_1.RLP.decode(signerVotes);
|
|
471
|
+
return votes.map((vote) => {
|
|
472
|
+
const blockNum = (0, util_1.bytesToBigInt)(vote[0]);
|
|
473
|
+
const signer = new util_1.Address(vote[1][0]);
|
|
474
|
+
const beneficiary = new util_1.Address(vote[1][1]);
|
|
475
|
+
const nonce = vote[1][2];
|
|
476
|
+
return [blockNum, [signer, beneficiary, nonce]];
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* Fetches snapshot of clique signers.
|
|
481
|
+
* @hidden
|
|
482
|
+
*/
|
|
483
|
+
async getCliqueLatestBlockSigners() {
|
|
484
|
+
const blockSigners = await this.blockchain.db.get(CLIQUE_BLOCK_SIGNERS_SNAPSHOT_KEY);
|
|
485
|
+
if (blockSigners === undefined)
|
|
486
|
+
return [];
|
|
487
|
+
const signers = rlp_1.RLP.decode(blockSigners);
|
|
488
|
+
return signers.map((s) => {
|
|
489
|
+
const blockNum = (0, util_1.bytesToBigInt)(s[0]);
|
|
490
|
+
const signer = new util_1.Address(s[1]);
|
|
491
|
+
return [blockNum, signer];
|
|
492
|
+
});
|
|
493
|
+
}
|
|
494
|
+
/**
|
|
495
|
+
* Build clique snapshots.
|
|
496
|
+
* @param header - the new block header
|
|
497
|
+
* @hidden
|
|
498
|
+
*/
|
|
499
|
+
async _cliqueBuildSnapshots(header) {
|
|
500
|
+
if (!(0, block_1.cliqueIsEpochTransition)(header)) {
|
|
501
|
+
await this.cliqueUpdateVotes(header);
|
|
502
|
+
}
|
|
503
|
+
await this.cliqueUpdateLatestBlockSigners(header);
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Helper to determine if a signer is in or out of turn for the next block.
|
|
507
|
+
* @param signer The signer address
|
|
508
|
+
*/
|
|
509
|
+
async cliqueSignerInTurn(signer, blockNum) {
|
|
510
|
+
const signers = this.cliqueActiveSigners(blockNum);
|
|
511
|
+
const signerIndex = signers.findIndex((address) => address.equals(signer));
|
|
512
|
+
if (signerIndex === -1) {
|
|
513
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)('Signer not found');
|
|
514
|
+
}
|
|
515
|
+
const { number } = await this.blockchain.getCanonicalHeadHeader();
|
|
516
|
+
return (number + BigInt(1)) % BigInt(signers.length) === BigInt(signerIndex);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
exports.CliqueConsensus = CliqueConsensus;
|
|
520
|
+
//# sourceMappingURL=clique.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clique.js","sourceRoot":"","sources":["../../../src/consensus/clique.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ConsensusAlgorithm } from '@feelyourprotocol/common';
|
|
2
|
+
import type { Block, BlockHeader } from '@feelyourprotocol/block';
|
|
3
|
+
import type { Blockchain } from '../index.ts';
|
|
4
|
+
import type { Consensus, ConsensusOptions } from '../types.ts';
|
|
5
|
+
export type MinimalEthashInterface = {
|
|
6
|
+
cacheDB?: any;
|
|
7
|
+
verifyPOW(block: Block): Promise<boolean>;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* This class encapsulates Ethash-related consensus functionality when used with the Blockchain class.
|
|
11
|
+
*/
|
|
12
|
+
export declare class EthashConsensus implements Consensus {
|
|
13
|
+
blockchain: Blockchain | undefined;
|
|
14
|
+
algorithm: ConsensusAlgorithm;
|
|
15
|
+
_ethash: MinimalEthashInterface;
|
|
16
|
+
private DEBUG;
|
|
17
|
+
private _debug;
|
|
18
|
+
constructor(ethash: MinimalEthashInterface);
|
|
19
|
+
validateConsensus(block: Block): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Checks that the block's `difficulty` matches the canonical difficulty of the parent header.
|
|
22
|
+
* @param header - header of block to be checked
|
|
23
|
+
*/
|
|
24
|
+
validateDifficulty(header: BlockHeader): Promise<void>;
|
|
25
|
+
genesisInit(): Promise<void>;
|
|
26
|
+
setup({ blockchain }: ConsensusOptions): Promise<void>;
|
|
27
|
+
newBlock(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=ethash.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ethash.d.ts","sourceRoot":"","sources":["../../../src/consensus/ethash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAIvD,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE3D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAE9D,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,CAAC,EAAE,GAAG,CAAA;IACb,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAA;CAC1C,CAAA;AAED;;GAEG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAC/C,UAAU,EAAE,UAAU,GAAG,SAAS,CAAA;IAClC,SAAS,EAAE,kBAAkB,CAAA;IAC7B,OAAO,EAAE,sBAAsB,CAAA;IAE/B,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAU;gBAEZ,MAAM,EAAE,sBAAsB;IAQpC,iBAAiB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAWpD;;;OAGG;IACG,kBAAkB,CAAC,MAAM,EAAE,WAAW;IAc/B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,UAAU,EAAE,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CACvC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EthashConsensus = void 0;
|
|
4
|
+
const common_1 = require("@feelyourprotocol/common");
|
|
5
|
+
const util_1 = require("@feelyourprotocol/util");
|
|
6
|
+
const debug_1 = require("debug");
|
|
7
|
+
/**
|
|
8
|
+
* This class encapsulates Ethash-related consensus functionality when used with the Blockchain class.
|
|
9
|
+
*/
|
|
10
|
+
class EthashConsensus {
|
|
11
|
+
constructor(ethash) {
|
|
12
|
+
this.DEBUG = (0, util_1.isDebugEnabled)('ethjs');
|
|
13
|
+
this._debug = (0, debug_1.default)('blockchain:ethash');
|
|
14
|
+
this.algorithm = common_1.ConsensusAlgorithm.Ethash;
|
|
15
|
+
this._ethash = ethash;
|
|
16
|
+
}
|
|
17
|
+
async validateConsensus(block) {
|
|
18
|
+
const valid = await this._ethash.verifyPOW(block);
|
|
19
|
+
if (!valid) {
|
|
20
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)('invalid POW');
|
|
21
|
+
}
|
|
22
|
+
this.DEBUG &&
|
|
23
|
+
this._debug(`valid PoW consensus block: number ${block.header.number} hash ${(0, util_1.bytesToHex)(block.hash())}`);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Checks that the block's `difficulty` matches the canonical difficulty of the parent header.
|
|
27
|
+
* @param header - header of block to be checked
|
|
28
|
+
*/
|
|
29
|
+
async validateDifficulty(header) {
|
|
30
|
+
if (!this.blockchain) {
|
|
31
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)('blockchain not provided');
|
|
32
|
+
}
|
|
33
|
+
const parentHeader = await this.blockchain['_getHeader'](header.parentHash);
|
|
34
|
+
if (header.ethashCanonicalDifficulty(parentHeader) !== header.difficulty) {
|
|
35
|
+
throw (0, util_1.EthereumJSErrorWithoutCode)(`invalid difficulty ${header.errorStr()}`);
|
|
36
|
+
}
|
|
37
|
+
this.DEBUG &&
|
|
38
|
+
this._debug(`valid difficulty header: number ${header.number} difficulty ${header.difficulty} parentHash ${(0, util_1.bytesToHex)(header.parentHash)}`);
|
|
39
|
+
}
|
|
40
|
+
async genesisInit() { }
|
|
41
|
+
async setup({ blockchain }) {
|
|
42
|
+
this.blockchain = blockchain;
|
|
43
|
+
this._ethash.cacheDB = this.blockchain.db;
|
|
44
|
+
}
|
|
45
|
+
async newBlock() { }
|
|
46
|
+
}
|
|
47
|
+
exports.EthashConsensus = EthashConsensus;
|
|
48
|
+
//# sourceMappingURL=ethash.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ethash.js","sourceRoot":"","sources":["../../../src/consensus/ethash.ts"],"names":[],"mappings":";;;AAAA,+CAAuD;AACvD,2CAAyF;AACzF,iCAAgC;AAYhC;;GAEG;AACH,MAAa,eAAe;IAQ1B,YAAY,MAA8B;QACxC,IAAI,CAAC,KAAK,GAAG,IAAA,qBAAc,EAAC,OAAO,CAAC,CAAA;QACpC,IAAI,CAAC,MAAM,GAAG,IAAA,eAAY,EAAC,mBAAmB,CAAC,CAAA;QAE/C,IAAI,CAAC,SAAS,GAAG,2BAAkB,CAAC,MAAM,CAAA;QAC1C,IAAI,CAAC,OAAO,GAAG,MAAM,CAAA;IACvB,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAAY;QAClC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;QACjD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAA,iCAA0B,EAAC,aAAa,CAAC,CAAA;QACjD,CAAC;QACD,IAAI,CAAC,KAAK;YACR,IAAI,CAAC,MAAM,CACT,qCAAqC,KAAK,CAAC,MAAM,CAAC,MAAM,SAAS,IAAA,iBAAU,EAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAC5F,CAAA;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CAAC,MAAmB;QAC1C,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YACrB,MAAM,IAAA,iCAA0B,EAAC,yBAAyB,CAAC,CAAA;QAC7D,CAAC;QACD,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAA;QAC3E,IAAI,MAAM,CAAC,yBAAyB,CAAC,YAAY,CAAC,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;YACzE,MAAM,IAAA,iCAA0B,EAAC,sBAAsB,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAA;QAC7E,CAAC;QACD,IAAI,CAAC,KAAK;YACR,IAAI,CAAC,MAAM,CACT,mCAAmC,MAAM,CAAC,MAAM,eAAe,MAAM,CAAC,UAAU,eAAe,IAAA,iBAAU,EAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAC/H,CAAA;IACL,CAAC;IAEM,KAAK,CAAC,WAAW,KAAmB,CAAC;IACrC,KAAK,CAAC,KAAK,CAAC,EAAE,UAAU,EAAoB;QACjD,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,EAAE,CAAA;IAC3C,CAAC;IACM,KAAK,CAAC,QAAQ,KAAmB,CAAC;CAC1C;AAnDD,0CAmDC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/consensus/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,CAAA"}
|