@feelyourprotocol/vm 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/LICENSE +373 -0
- package/README.md +583 -0
- package/dist/cjs/bloom/index.d.ts +29 -0
- package/dist/cjs/bloom/index.d.ts.map +1 -0
- package/dist/cjs/bloom/index.js +76 -0
- package/dist/cjs/bloom/index.js.map +1 -0
- package/dist/cjs/buildBlock.d.ts +118 -0
- package/dist/cjs/buildBlock.d.ts.map +1 -0
- package/dist/cjs/buildBlock.js +363 -0
- package/dist/cjs/buildBlock.js.map +1 -0
- package/dist/cjs/constructors.d.ts +9 -0
- package/dist/cjs/constructors.d.ts.map +1 -0
- package/dist/cjs/constructors.js +75 -0
- package/dist/cjs/constructors.js.map +1 -0
- package/dist/cjs/emitEVMProfile.d.ts +9 -0
- package/dist/cjs/emitEVMProfile.d.ts.map +1 -0
- package/dist/cjs/emitEVMProfile.js +130 -0
- package/dist/cjs/emitEVMProfile.js.map +1 -0
- package/dist/cjs/index.d.ts +11 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +36 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +3 -0
- package/dist/cjs/params.d.ts +3 -0
- package/dist/cjs/params.d.ts.map +1 -0
- package/dist/cjs/params.js +105 -0
- package/dist/cjs/params.js.map +1 -0
- package/dist/cjs/requests.d.ts +11 -0
- package/dist/cjs/requests.d.ts.map +1 -0
- package/dist/cjs/requests.js +208 -0
- package/dist/cjs/requests.js.map +1 -0
- package/dist/cjs/runBlock.d.ts +35 -0
- package/dist/cjs/runBlock.d.ts.map +1 -0
- package/dist/cjs/runBlock.js +797 -0
- package/dist/cjs/runBlock.js.map +1 -0
- package/dist/cjs/runFrameTx.d.ts +18 -0
- package/dist/cjs/runFrameTx.d.ts.map +1 -0
- package/dist/cjs/runFrameTx.js +313 -0
- package/dist/cjs/runFrameTx.js.map +1 -0
- package/dist/cjs/runTx.d.ts +18 -0
- package/dist/cjs/runTx.d.ts.map +1 -0
- package/dist/cjs/runTx.js +900 -0
- package/dist/cjs/runTx.js.map +1 -0
- package/dist/cjs/types.d.ts +452 -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/cjs/vm.d.ts +75 -0
- package/dist/cjs/vm.d.ts.map +1 -0
- package/dist/cjs/vm.js +111 -0
- package/dist/cjs/vm.js.map +1 -0
- package/dist/esm/bloom/index.d.ts +29 -0
- package/dist/esm/bloom/index.d.ts.map +1 -0
- package/dist/esm/bloom/index.js +72 -0
- package/dist/esm/bloom/index.js.map +1 -0
- package/dist/esm/buildBlock.d.ts +118 -0
- package/dist/esm/buildBlock.d.ts.map +1 -0
- package/dist/esm/buildBlock.js +358 -0
- package/dist/esm/buildBlock.js.map +1 -0
- package/dist/esm/constructors.d.ts +9 -0
- package/dist/esm/constructors.d.ts.map +1 -0
- package/dist/esm/constructors.js +72 -0
- package/dist/esm/constructors.js.map +1 -0
- package/dist/esm/emitEVMProfile.d.ts +9 -0
- package/dist/esm/emitEVMProfile.d.ts.map +1 -0
- package/dist/esm/emitEVMProfile.js +127 -0
- package/dist/esm/emitEVMProfile.js.map +1 -0
- package/dist/esm/index.d.ts +11 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +11 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +3 -0
- package/dist/esm/params.d.ts +3 -0
- package/dist/esm/params.d.ts.map +1 -0
- package/dist/esm/params.js +102 -0
- package/dist/esm/params.js.map +1 -0
- package/dist/esm/requests.d.ts +11 -0
- package/dist/esm/requests.d.ts.map +1 -0
- package/dist/esm/requests.js +204 -0
- package/dist/esm/requests.js.map +1 -0
- package/dist/esm/runBlock.d.ts +35 -0
- package/dist/esm/runBlock.d.ts.map +1 -0
- package/dist/esm/runBlock.js +790 -0
- package/dist/esm/runBlock.js.map +1 -0
- package/dist/esm/runFrameTx.d.ts +18 -0
- package/dist/esm/runFrameTx.d.ts.map +1 -0
- package/dist/esm/runFrameTx.js +310 -0
- package/dist/esm/runFrameTx.js.map +1 -0
- package/dist/esm/runTx.d.ts +18 -0
- package/dist/esm/runTx.d.ts.map +1 -0
- package/dist/esm/runTx.js +896 -0
- package/dist/esm/runTx.js.map +1 -0
- package/dist/esm/types.d.ts +452 -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/esm/vm.d.ts +75 -0
- package/dist/esm/vm.d.ts.map +1 -0
- package/dist/esm/vm.js +107 -0
- package/dist/esm/vm.js.map +1 -0
- package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
- package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
- package/package.json +117 -0
- package/src/bloom/index.ts +83 -0
- package/src/buildBlock.ts +470 -0
- package/src/constructors.ts +91 -0
- package/src/emitEVMProfile.ts +151 -0
- package/src/index.ts +10 -0
- package/src/params.ts +104 -0
- package/src/requests.ts +293 -0
- package/src/runBlock.ts +1022 -0
- package/src/runFrameTx.ts +411 -0
- package/src/runTx.ts +1203 -0
- package/src/types.ts +511 -0
- package/src/vm.ts +147 -0
|
@@ -0,0 +1,790 @@
|
|
|
1
|
+
import { createBlock, genRequestsRoot } from '@feelyourprotocol/block';
|
|
2
|
+
import { ConsensusType, Hardfork } from '@feelyourprotocol/common';
|
|
3
|
+
import {} from '@feelyourprotocol/evm';
|
|
4
|
+
import { MerklePatriciaTrie } from '@feelyourprotocol/mpt';
|
|
5
|
+
import { RLP } from '@feelyourprotocol/rlp';
|
|
6
|
+
import { TransactionType } from '@feelyourprotocol/tx';
|
|
7
|
+
import { Account, Address, BIGINT_0, BIGINT_1, BIGINT_8, EthereumJSErrorWithoutCode, GWEI_TO_WEI, KECCAK256_RLP, bigIntToAddressBytes, bigIntToBytes, bytesToHex, concatBytes, createAddressFromString, createBlockLevelAccessList, equalsBytes, hexToBytes, intToBytes, setLengthLeft, short, unprefixedHexToBytes, } from '@feelyourprotocol/util';
|
|
8
|
+
import { sha256 } from '@noble/hashes/sha2.js';
|
|
9
|
+
import debugDefault from 'debug';
|
|
10
|
+
import { Bloom } from "./bloom/index.js";
|
|
11
|
+
import { emitEVMProfile } from "./emitEVMProfile.js";
|
|
12
|
+
import { runTx } from "./index.js";
|
|
13
|
+
import { accumulateRequests } from "./requests.js";
|
|
14
|
+
const debug = debugDefault('vm:block');
|
|
15
|
+
const parentBeaconBlockRootAddress = createAddressFromString('0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02');
|
|
16
|
+
let enableProfiler = false;
|
|
17
|
+
const stateRootCPLabel = 'New state root, DAO HF, checkpoints, block validation';
|
|
18
|
+
const processTxsLabel = 'Tx processing [ use per-tx profiler for more details ]';
|
|
19
|
+
const withdrawalsRewardsCommitLabel = 'Withdrawals, Rewards, EVM journal commit';
|
|
20
|
+
const entireBlockLabel = 'Entire block';
|
|
21
|
+
/**
|
|
22
|
+
* Processes the `block` running all of the transactions it contains and updating the miner's account
|
|
23
|
+
*
|
|
24
|
+
* vm method modifies the state if successfully executed and header fields are valid.
|
|
25
|
+
* state modifications will be reverted if an exception is raised during execution or validation.
|
|
26
|
+
*
|
|
27
|
+
* @param {VM} vm
|
|
28
|
+
* @param {RunBlockOpts} opts - Default values for options:
|
|
29
|
+
* - `generate`: false
|
|
30
|
+
*/
|
|
31
|
+
export async function runBlock(vm, opts) {
|
|
32
|
+
if (vm['_opts'].profilerOpts?.reportAfterBlock === true) {
|
|
33
|
+
enableProfiler = true;
|
|
34
|
+
// eslint-disable-next-line no-console
|
|
35
|
+
console.time(entireBlockLabel);
|
|
36
|
+
}
|
|
37
|
+
const stateManager = vm.stateManager;
|
|
38
|
+
const { root } = opts;
|
|
39
|
+
const clearCache = opts.clearCache ?? true;
|
|
40
|
+
let { block } = opts;
|
|
41
|
+
const generateFields = opts.generate === true;
|
|
42
|
+
if (enableProfiler) {
|
|
43
|
+
const title = `Profiler run - Block ${block.header.number} (${bytesToHex(block.hash())} with ${block.transactions.length} txs`;
|
|
44
|
+
// eslint-disable-next-line no-console
|
|
45
|
+
console.log(title);
|
|
46
|
+
// eslint-disable-next-line no-console
|
|
47
|
+
console.time(stateRootCPLabel);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The `beforeBlock` event.
|
|
51
|
+
*
|
|
52
|
+
* @event Event: beforeBlock
|
|
53
|
+
* @type {Object}
|
|
54
|
+
* @property {Block} block emits the block that is about to be processed
|
|
55
|
+
*/
|
|
56
|
+
await vm._emit('beforeBlock', block);
|
|
57
|
+
const setHardforkUsed = opts.setHardfork ?? vm['_setHardfork'];
|
|
58
|
+
if (setHardforkUsed === true) {
|
|
59
|
+
vm.common.setHardforkBy({
|
|
60
|
+
blockNumber: block.header.number,
|
|
61
|
+
timestamp: block.header.timestamp,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
if (vm.common.isActivatedEIP(7928)) {
|
|
65
|
+
vm.evm.blockLevelAccessList = createBlockLevelAccessList();
|
|
66
|
+
}
|
|
67
|
+
if (vm.DEBUG) {
|
|
68
|
+
debug('-'.repeat(100));
|
|
69
|
+
debug(`Running block hash=${bytesToHex(block.hash())} number=${block.header.number} hardfork=${vm.common.hardfork()}`);
|
|
70
|
+
}
|
|
71
|
+
// Set state root if provided
|
|
72
|
+
if (root) {
|
|
73
|
+
if (vm.DEBUG) {
|
|
74
|
+
debug(`Set provided state root ${bytesToHex(root)} clearCache=${clearCache}`);
|
|
75
|
+
}
|
|
76
|
+
await stateManager.setStateRoot(root, clearCache);
|
|
77
|
+
}
|
|
78
|
+
if (vm.common.isActivatedEIP(7864)) {
|
|
79
|
+
// Initialize the access witness
|
|
80
|
+
if (vm.DEBUG) {
|
|
81
|
+
debug(`Initializing executionWitness`);
|
|
82
|
+
}
|
|
83
|
+
if (clearCache) {
|
|
84
|
+
stateManager.clearCaches();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// check for DAO support and if we should apply the DAO fork
|
|
88
|
+
if (vm.common.hardforkIsActiveOnBlock(Hardfork.Dao, block.header.number) &&
|
|
89
|
+
block.header.number === vm.common.hardforkBlock(Hardfork.Dao)) {
|
|
90
|
+
if (vm.DEBUG) {
|
|
91
|
+
debug(`Apply DAO hardfork`);
|
|
92
|
+
}
|
|
93
|
+
await vm.evm.journal.checkpoint();
|
|
94
|
+
await _applyDAOHardfork(vm.evm);
|
|
95
|
+
await vm.evm.journal.commit();
|
|
96
|
+
}
|
|
97
|
+
// Checkpoint state
|
|
98
|
+
await vm.evm.journal.checkpoint();
|
|
99
|
+
if (vm.DEBUG) {
|
|
100
|
+
debug(`block checkpoint`);
|
|
101
|
+
}
|
|
102
|
+
let result;
|
|
103
|
+
try {
|
|
104
|
+
result = await applyBlock(vm, block, opts);
|
|
105
|
+
if (vm.DEBUG) {
|
|
106
|
+
debug(`Received block results gasUsed=${result.gasUsed} bloom=${short(result.bloom.bitvector)} (${result.bloom.bitvector.length} bytes) receiptsRoot=${bytesToHex(result.receiptsRoot)} receipts=${result.receipts.length} txResults=${result.results.length}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
await vm.evm.journal.revert();
|
|
111
|
+
if (vm.DEBUG) {
|
|
112
|
+
debug(`block checkpoint reverted`);
|
|
113
|
+
}
|
|
114
|
+
if (enableProfiler) {
|
|
115
|
+
// eslint-disable-next-line no-console
|
|
116
|
+
console.timeEnd(withdrawalsRewardsCommitLabel);
|
|
117
|
+
}
|
|
118
|
+
throw err;
|
|
119
|
+
}
|
|
120
|
+
let requestsHash;
|
|
121
|
+
let requests;
|
|
122
|
+
if (block.common.isActivatedEIP(7685)) {
|
|
123
|
+
const sha256Function = vm.common.customCrypto.sha256 ?? sha256;
|
|
124
|
+
requests = await accumulateRequests(vm, result.results);
|
|
125
|
+
requestsHash = genRequestsRoot(requests, sha256Function);
|
|
126
|
+
}
|
|
127
|
+
const stateRoot = await stateManager.getStateRoot();
|
|
128
|
+
// Given the generate option, either set resulting header
|
|
129
|
+
// values to the current block, or validate the resulting
|
|
130
|
+
// header values against the current block.
|
|
131
|
+
if (generateFields) {
|
|
132
|
+
const logsBloom = result.bloom.bitvector;
|
|
133
|
+
const gasUsed = result.gasUsed;
|
|
134
|
+
const receiptTrie = result.receiptsRoot;
|
|
135
|
+
const transactionsTrie = await _genTxTrie(block);
|
|
136
|
+
const generatedFields = {
|
|
137
|
+
stateRoot,
|
|
138
|
+
logsBloom,
|
|
139
|
+
gasUsed,
|
|
140
|
+
receiptTrie,
|
|
141
|
+
transactionsTrie,
|
|
142
|
+
requestsHash,
|
|
143
|
+
};
|
|
144
|
+
const blockData = {
|
|
145
|
+
...block,
|
|
146
|
+
header: { ...block.header, ...generatedFields },
|
|
147
|
+
};
|
|
148
|
+
block = createBlock(blockData, { common: vm.common });
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
try {
|
|
152
|
+
if (vm.common.isActivatedEIP(7685)) {
|
|
153
|
+
if (!equalsBytes(block.header.requestsHash, requestsHash)) {
|
|
154
|
+
if (vm.DEBUG)
|
|
155
|
+
debug(`Invalid requestsHash received=${bytesToHex(block.header.requestsHash)} expected=${bytesToHex(requestsHash)}`);
|
|
156
|
+
const msg = _errorMsg('invalid requestsHash', vm, block);
|
|
157
|
+
throw EthereumJSErrorWithoutCode(msg);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Only validate the following headers if Stateless isn't activated
|
|
161
|
+
if (equalsBytes(result.receiptsRoot, block.header.receiptTrie) === false) {
|
|
162
|
+
if (vm.DEBUG) {
|
|
163
|
+
debug(`Invalid receiptTrie received=${bytesToHex(result.receiptsRoot)} expected=${bytesToHex(block.header.receiptTrie)}`);
|
|
164
|
+
}
|
|
165
|
+
const msg = _errorMsg('invalid receiptTrie', vm, block);
|
|
166
|
+
throw EthereumJSErrorWithoutCode(msg);
|
|
167
|
+
}
|
|
168
|
+
if (!(equalsBytes(result.bloom.bitvector, block.header.logsBloom) === true)) {
|
|
169
|
+
if (vm.DEBUG) {
|
|
170
|
+
debug(`Invalid bloom received=${bytesToHex(result.bloom.bitvector)} expected=${bytesToHex(block.header.logsBloom)}`);
|
|
171
|
+
}
|
|
172
|
+
const msg = _errorMsg('invalid bloom', vm, block);
|
|
173
|
+
throw EthereumJSErrorWithoutCode(msg);
|
|
174
|
+
}
|
|
175
|
+
if (result.gasUsed !== block.header.gasUsed) {
|
|
176
|
+
if (vm.DEBUG) {
|
|
177
|
+
debug(`Invalid gasUsed received=${result.gasUsed} expected=${block.header.gasUsed}`);
|
|
178
|
+
}
|
|
179
|
+
const msg = _errorMsg('invalid gasUsed', vm, block);
|
|
180
|
+
throw EthereumJSErrorWithoutCode(msg);
|
|
181
|
+
}
|
|
182
|
+
if (!(equalsBytes(stateRoot, block.header.stateRoot) === true)) {
|
|
183
|
+
if (vm.DEBUG) {
|
|
184
|
+
debug(`Invalid stateRoot received=${bytesToHex(stateRoot)} expected=${bytesToHex(block.header.stateRoot)}`);
|
|
185
|
+
}
|
|
186
|
+
const msg = _errorMsg(`invalid block stateRoot, got: ${bytesToHex(stateRoot)}, want: ${bytesToHex(block.header.stateRoot)}`, vm, block);
|
|
187
|
+
throw EthereumJSErrorWithoutCode(msg);
|
|
188
|
+
}
|
|
189
|
+
if (vm.common.isActivatedEIP(7864)) {
|
|
190
|
+
if (vm.evm.binaryTreeAccessWitness === undefined) {
|
|
191
|
+
throw Error(`binaryTreeAccessWitness required if binary tree (EIP-7864) is activated`);
|
|
192
|
+
}
|
|
193
|
+
// If binary tree is activated and executing statelessly, only validate the post-state
|
|
194
|
+
if ((await vm['_opts'].stateManager.verifyBinaryTreePostState(vm.evm.binaryTreeAccessWitness)) === false) {
|
|
195
|
+
throw EthereumJSErrorWithoutCode(`Binary tree post state verification failed on block ${block.header.number}`);
|
|
196
|
+
}
|
|
197
|
+
debug(`Binary tree post state verification succeeded`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (err) {
|
|
201
|
+
await vm.evm.journal.revert();
|
|
202
|
+
if (vm.DEBUG) {
|
|
203
|
+
debug(`block checkpoint reverted`);
|
|
204
|
+
}
|
|
205
|
+
throw err;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
// Persist state
|
|
209
|
+
await vm.evm.journal.commit();
|
|
210
|
+
if (vm.DEBUG) {
|
|
211
|
+
debug(`block checkpoint committed`);
|
|
212
|
+
}
|
|
213
|
+
if (enableProfiler) {
|
|
214
|
+
// eslint-disable-next-line no-console
|
|
215
|
+
console.timeEnd(withdrawalsRewardsCommitLabel);
|
|
216
|
+
}
|
|
217
|
+
const results = {
|
|
218
|
+
receipts: result.receipts,
|
|
219
|
+
logsBloom: result.bloom.bitvector,
|
|
220
|
+
results: result.results,
|
|
221
|
+
stateRoot,
|
|
222
|
+
gasUsed: result.gasUsed,
|
|
223
|
+
receiptsRoot: result.receiptsRoot,
|
|
224
|
+
preimages: result.preimages,
|
|
225
|
+
requestsHash,
|
|
226
|
+
requests,
|
|
227
|
+
blockLevelAccessList: vm.evm.blockLevelAccessList,
|
|
228
|
+
};
|
|
229
|
+
const afterBlockEvent = { ...results, block };
|
|
230
|
+
/**
|
|
231
|
+
* The `afterBlock` event
|
|
232
|
+
*
|
|
233
|
+
* @event Event: afterBlock
|
|
234
|
+
* @type {AfterBlockEvent}
|
|
235
|
+
* @property {AfterBlockEvent} result emits the results of processing a block
|
|
236
|
+
*/
|
|
237
|
+
await vm._emit('afterBlock', afterBlockEvent);
|
|
238
|
+
if (vm.DEBUG) {
|
|
239
|
+
debug(`Running block finished hash=${bytesToHex(block.hash())} number=${block.header.number} hardfork=${vm.common.hardfork()}`);
|
|
240
|
+
}
|
|
241
|
+
if (enableProfiler) {
|
|
242
|
+
// eslint-disable-next-line no-console
|
|
243
|
+
console.timeEnd(entireBlockLabel);
|
|
244
|
+
const logs = vm.evm.getPerformanceLogs();
|
|
245
|
+
if (logs.precompiles.length === 0 && logs.opcodes.length === 0) {
|
|
246
|
+
// eslint-disable-next-line no-console
|
|
247
|
+
console.log('No block txs with precompile or opcode execution.');
|
|
248
|
+
}
|
|
249
|
+
emitEVMProfile(logs.precompiles, 'Precompile performance');
|
|
250
|
+
emitEVMProfile(logs.opcodes, 'Opcodes performance');
|
|
251
|
+
vm.evm.clearPerformanceLogs();
|
|
252
|
+
}
|
|
253
|
+
return results;
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Validates and applies a block, computing the results of
|
|
257
|
+
* applying its transactions. vm method doesn't modify the
|
|
258
|
+
* block itself. It computes the block rewards and puts
|
|
259
|
+
* them on state (but doesn't persist the changes).
|
|
260
|
+
* @param {Block} block
|
|
261
|
+
* @param {RunBlockOpts} opts
|
|
262
|
+
*/
|
|
263
|
+
async function applyBlock(vm, block, opts) {
|
|
264
|
+
// Validate block
|
|
265
|
+
if (opts.skipBlockValidation !== true) {
|
|
266
|
+
if (block.header.gasLimit >= BigInt('0x8000000000000000')) {
|
|
267
|
+
const msg = _errorMsg('Invalid block with gas limit greater than (2^63 - 1)', vm, block);
|
|
268
|
+
throw EthereumJSErrorWithoutCode(msg);
|
|
269
|
+
}
|
|
270
|
+
else {
|
|
271
|
+
if (vm.DEBUG) {
|
|
272
|
+
debug(`Validate block`);
|
|
273
|
+
}
|
|
274
|
+
// TODO: decide what block validation method is appropriate here
|
|
275
|
+
if (opts.skipHeaderValidation !== true) {
|
|
276
|
+
if (typeof vm.blockchain.validateHeader === 'function') {
|
|
277
|
+
await vm.blockchain.validateHeader(block.header);
|
|
278
|
+
}
|
|
279
|
+
else {
|
|
280
|
+
throw EthereumJSErrorWithoutCode('cannot validate header: blockchain has no `validateHeader` method');
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
await block.validateData(false, true, opts.validateBlockSize ?? false);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (vm.common.isActivatedEIP(4788)) {
|
|
287
|
+
if (vm.DEBUG) {
|
|
288
|
+
debug(`accumulate parentBeaconBlockRoot`);
|
|
289
|
+
}
|
|
290
|
+
await accumulateParentBeaconBlockRoot(vm, block.header.parentBeaconBlockRoot, block.header.timestamp);
|
|
291
|
+
}
|
|
292
|
+
if (vm.common.isActivatedEIP(2935)) {
|
|
293
|
+
if (vm.DEBUG) {
|
|
294
|
+
debug(`accumulate parentBlockHash `);
|
|
295
|
+
}
|
|
296
|
+
await accumulateParentBlockHash(vm, block.header.number, block.header.parentHash);
|
|
297
|
+
}
|
|
298
|
+
if (enableProfiler) {
|
|
299
|
+
// eslint-disable-next-line no-console
|
|
300
|
+
console.timeEnd(stateRootCPLabel);
|
|
301
|
+
}
|
|
302
|
+
// Apply transactions
|
|
303
|
+
if (vm.DEBUG) {
|
|
304
|
+
debug(`Apply transactions`);
|
|
305
|
+
}
|
|
306
|
+
const blockResults = await applyTransactions(vm, block, opts);
|
|
307
|
+
if (enableProfiler) {
|
|
308
|
+
// eslint-disable-next-line no-console
|
|
309
|
+
console.time(withdrawalsRewardsCommitLabel);
|
|
310
|
+
}
|
|
311
|
+
// Add txResult preimages to the blockResults preimages
|
|
312
|
+
// Also add the coinbase preimage
|
|
313
|
+
if (opts.reportPreimages === true) {
|
|
314
|
+
if (vm.evm.stateManager.getAppliedKey === undefined) {
|
|
315
|
+
throw EthereumJSErrorWithoutCode('applyBlock: evm.stateManager.getAppliedKey can not be undefined if reportPreimages is true');
|
|
316
|
+
}
|
|
317
|
+
blockResults.preimages.set(bytesToHex(vm.evm.stateManager.getAppliedKey(block.header.coinbase.toBytes())), block.header.coinbase.toBytes());
|
|
318
|
+
for (const txResult of blockResults.results) {
|
|
319
|
+
if (txResult.preimages !== undefined) {
|
|
320
|
+
for (const [key, preimage] of txResult.preimages) {
|
|
321
|
+
blockResults.preimages.set(key, preimage);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (vm.common.isActivatedEIP(4895)) {
|
|
327
|
+
if (opts.reportPreimages === true)
|
|
328
|
+
vm.evm.journal.startReportingPreimages();
|
|
329
|
+
await assignWithdrawals(vm, block);
|
|
330
|
+
if (opts.reportPreimages === true && vm.evm.journal.preimages !== undefined) {
|
|
331
|
+
for (const [key, preimage] of vm.evm.journal.preimages) {
|
|
332
|
+
blockResults.preimages.set(key, preimage);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
await vm.evm.journal.cleanup();
|
|
336
|
+
}
|
|
337
|
+
// Pay ommers and miners
|
|
338
|
+
if (block.common.consensusType() === ConsensusType.ProofOfWork) {
|
|
339
|
+
await assignBlockRewards(vm, block);
|
|
340
|
+
}
|
|
341
|
+
if (vm.common.isActivatedEIP(7864) && vm.evm.systemBinaryTreeAccessWitness !== undefined) {
|
|
342
|
+
vm.evm.systemBinaryTreeAccessWitness?.commit();
|
|
343
|
+
if (vm.DEBUG) {
|
|
344
|
+
debug('Binary tree access witness aggregate costs:');
|
|
345
|
+
vm.evm.binaryTreeAccessWitness?.debugWitnessCost();
|
|
346
|
+
debug('System binary tree access witness aggregate costs:');
|
|
347
|
+
vm.evm.systemBinaryTreeAccessWitness?.debugWitnessCost();
|
|
348
|
+
}
|
|
349
|
+
vm.evm.binaryTreeAccessWitness?.merge(vm.evm.systemBinaryTreeAccessWitness);
|
|
350
|
+
}
|
|
351
|
+
return blockResults;
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* vm method runs the logic of EIP 2935 (save blockhashes to state)
|
|
355
|
+
* It will put the `parentHash` of the block to the storage slot of `block.number - 1` of the history storage contract.
|
|
356
|
+
* vm contract is used to retrieve BLOCKHASHes in EVM if EIP 2935 is activated.
|
|
357
|
+
* In case that the previous block of `block` is pre-EIP-2935 (so we are on the EIP 2935 fork block), additionally
|
|
358
|
+
* also add the currently available past blockhashes which are available by BLOCKHASH (so, the past 256 block hashes)
|
|
359
|
+
* @param vm The VM to run on
|
|
360
|
+
* @param block The current block to save the parent block hash of
|
|
361
|
+
*/
|
|
362
|
+
export async function accumulateParentBlockHash(vm, currentBlockNumber, parentHash) {
|
|
363
|
+
if (!vm.common.isActivatedEIP(2935)) {
|
|
364
|
+
throw EthereumJSErrorWithoutCode('Cannot call `accumulateParentBlockHash`: EIP 2935 is not active');
|
|
365
|
+
}
|
|
366
|
+
const historyAddress = new Address(bigIntToAddressBytes(vm.common.param('historyStorageAddress')));
|
|
367
|
+
const historyServeWindow = vm.common.param('historyServeWindow');
|
|
368
|
+
// getAccount with historyAddress will throw error as witnesses are not bundled
|
|
369
|
+
// but we need to put account so as to query later for slot
|
|
370
|
+
const code = await vm.stateManager.getCode(historyAddress);
|
|
371
|
+
if (code.length === 0) {
|
|
372
|
+
// Exit early, system contract has no code so no storage is written
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
async function putBlockHash(vm, hash, number) {
|
|
376
|
+
// ringKey is the key the hash is actually put in (it is a ring buffer)
|
|
377
|
+
const ringKey = number % historyServeWindow;
|
|
378
|
+
if (vm.common.isActivatedEIP(7864)) {
|
|
379
|
+
if (vm.evm.systemBinaryTreeAccessWitness === undefined) {
|
|
380
|
+
throw Error(`systemBinaryTreeAccessWitness required if binary tree (EIP-7864) is activated`);
|
|
381
|
+
}
|
|
382
|
+
// Add to system binary tree access witness so that it doesn't warm up tx accesses
|
|
383
|
+
vm.evm.systemBinaryTreeAccessWitness.writeAccountStorage(historyAddress, ringKey);
|
|
384
|
+
}
|
|
385
|
+
const key = setLengthLeft(bigIntToBytes(ringKey), 32);
|
|
386
|
+
if (vm.common.isActivatedEIP(7928)) {
|
|
387
|
+
vm.evm.blockLevelAccessList.addStorageWrite(historyAddress.toString(), key, hash, vm.evm.blockLevelAccessList.blockAccessIndex);
|
|
388
|
+
}
|
|
389
|
+
await vm.stateManager.putStorage(historyAddress, key, hash);
|
|
390
|
+
}
|
|
391
|
+
await putBlockHash(vm, parentHash, currentBlockNumber - BIGINT_1);
|
|
392
|
+
// do cleanup if the code was not deployed
|
|
393
|
+
await vm.evm.journal.cleanup();
|
|
394
|
+
}
|
|
395
|
+
export async function accumulateParentBeaconBlockRoot(vm, root, timestamp) {
|
|
396
|
+
if (!vm.common.isActivatedEIP(4788)) {
|
|
397
|
+
throw EthereumJSErrorWithoutCode('Cannot call `accumulateParentBeaconBlockRoot`: EIP 4788 is not active');
|
|
398
|
+
}
|
|
399
|
+
// Save the parentBeaconBlockRoot to the beaconroot stateful precompile ring buffers
|
|
400
|
+
const historicalRootsLength = BigInt(vm.common.param('historicalRootsLength'));
|
|
401
|
+
const timestampIndex = timestamp % historicalRootsLength;
|
|
402
|
+
const timestampExtended = timestampIndex + historicalRootsLength;
|
|
403
|
+
/**
|
|
404
|
+
* Note: (by Gabriel)
|
|
405
|
+
* Get account will throw an error in stateless execution b/c witnesses are not bundled
|
|
406
|
+
* But we do need an account so we are able to put the storage
|
|
407
|
+
*/
|
|
408
|
+
const code = await vm.stateManager.getCode(parentBeaconBlockRootAddress);
|
|
409
|
+
if (code.length === 0) {
|
|
410
|
+
// Exit early, system contract has no code so no storage is written
|
|
411
|
+
// TODO: verify with Gabriel that this is fine regarding binary trees (should we put an empty account?)
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
if (vm.common.isActivatedEIP(7928)) {
|
|
415
|
+
vm.evm.blockLevelAccessList.addStorageWrite(parentBeaconBlockRootAddress.toString(), setLengthLeft(bigIntToBytes(timestampIndex), 32), bigIntToBytes(timestamp), vm.evm.blockLevelAccessList.blockAccessIndex);
|
|
416
|
+
}
|
|
417
|
+
await vm.stateManager.putStorage(parentBeaconBlockRootAddress, setLengthLeft(bigIntToBytes(timestampIndex), 32), bigIntToBytes(timestamp));
|
|
418
|
+
if (vm.common.isActivatedEIP(7928)) {
|
|
419
|
+
vm.evm.blockLevelAccessList.addStorageWrite(parentBeaconBlockRootAddress.toString(), setLengthLeft(bigIntToBytes(timestampExtended), 32), root, vm.evm.blockLevelAccessList.blockAccessIndex);
|
|
420
|
+
}
|
|
421
|
+
await vm.stateManager.putStorage(parentBeaconBlockRootAddress, setLengthLeft(bigIntToBytes(timestampExtended), 32), root);
|
|
422
|
+
// do cleanup if the code was not deployed
|
|
423
|
+
await vm.evm.journal.cleanup();
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Applies the transactions in a block, computing the receipts
|
|
427
|
+
* as well as gas usage and some relevant data. vm method is
|
|
428
|
+
* side-effect free (it doesn't modify the block nor the state).
|
|
429
|
+
* @param {Block} block
|
|
430
|
+
* @param {RunBlockOpts} opts
|
|
431
|
+
*/
|
|
432
|
+
async function applyTransactions(vm, block, opts) {
|
|
433
|
+
if (enableProfiler) {
|
|
434
|
+
// eslint-disable-next-line no-console
|
|
435
|
+
console.time(processTxsLabel);
|
|
436
|
+
}
|
|
437
|
+
const bloom = new Bloom(undefined, vm.common);
|
|
438
|
+
// Block header gas accounting (EIP-7778: no refund subtraction)
|
|
439
|
+
let gasUsed = BIGINT_0;
|
|
440
|
+
// Receipt cumulative gas accounting (keeps tx refund subtraction semantics)
|
|
441
|
+
let receiptGasUsed = BIGINT_0;
|
|
442
|
+
let receiptTrie = undefined;
|
|
443
|
+
if (block.transactions.length !== 0) {
|
|
444
|
+
receiptTrie = new MerklePatriciaTrie({ common: vm.common });
|
|
445
|
+
}
|
|
446
|
+
const receipts = [];
|
|
447
|
+
const txResults = [];
|
|
448
|
+
/*
|
|
449
|
+
* Process transactions
|
|
450
|
+
*/
|
|
451
|
+
for (let txIdx = 0; txIdx < block.transactions.length; txIdx++) {
|
|
452
|
+
if (vm.common.isActivatedEIP(7928)) {
|
|
453
|
+
vm.evm.blockLevelAccessList.blockAccessIndex = txIdx + 1;
|
|
454
|
+
}
|
|
455
|
+
const tx = block.transactions[txIdx];
|
|
456
|
+
if (vm.DEBUG) {
|
|
457
|
+
debug(`Run tx ${txIdx + 1}/${block.transactions.length} gasLimit=${tx.gasLimit} type=${tx.type} (block gas used so far: ${gasUsed}/${block.header.gasLimit})`);
|
|
458
|
+
}
|
|
459
|
+
const gasLimitIsHigherThanBlock = block.header.gasLimit < tx.gasLimit + gasUsed;
|
|
460
|
+
if (gasLimitIsHigherThanBlock) {
|
|
461
|
+
const msg = _errorMsg('tx has a higher gas limit than the block', vm, block);
|
|
462
|
+
throw EthereumJSErrorWithoutCode(msg);
|
|
463
|
+
}
|
|
464
|
+
// Run the tx through the VM
|
|
465
|
+
const { skipBalance, skipNonce, skipHardForkValidation, reportPreimages } = opts;
|
|
466
|
+
const txRes = await runTx(vm, {
|
|
467
|
+
tx,
|
|
468
|
+
block,
|
|
469
|
+
skipBalance,
|
|
470
|
+
skipNonce,
|
|
471
|
+
skipHardForkValidation,
|
|
472
|
+
blockGasUsed: receiptGasUsed,
|
|
473
|
+
reportPreimages,
|
|
474
|
+
});
|
|
475
|
+
txResults.push(txRes);
|
|
476
|
+
if (vm.DEBUG) {
|
|
477
|
+
debug('-'.repeat(100));
|
|
478
|
+
}
|
|
479
|
+
// Add to total block gas usage
|
|
480
|
+
gasUsed += txRes.blockGasSpent;
|
|
481
|
+
receiptGasUsed += txRes.totalGasSpent;
|
|
482
|
+
if (vm.DEBUG) {
|
|
483
|
+
debug(`Add tx gas used (${txRes.blockGasSpent}) to total block gas usage (-> ${gasUsed})`);
|
|
484
|
+
}
|
|
485
|
+
// Combine blooms via bitwise OR
|
|
486
|
+
bloom.or(txRes.bloom);
|
|
487
|
+
// Add receipt to trie to later calculate receipt root
|
|
488
|
+
receipts.push(txRes.receipt);
|
|
489
|
+
const encodedReceipt = encodeReceipt(txRes.receipt, tx.type);
|
|
490
|
+
await receiptTrie.put(RLP.encode(txIdx), encodedReceipt);
|
|
491
|
+
}
|
|
492
|
+
if (enableProfiler) {
|
|
493
|
+
// eslint-disable-next-line no-console
|
|
494
|
+
console.timeEnd(processTxsLabel);
|
|
495
|
+
}
|
|
496
|
+
const receiptsRoot = receiptTrie !== undefined ? receiptTrie.root() : KECCAK256_RLP;
|
|
497
|
+
return {
|
|
498
|
+
bloom,
|
|
499
|
+
gasUsed,
|
|
500
|
+
preimages: new Map(),
|
|
501
|
+
receiptsRoot,
|
|
502
|
+
receipts,
|
|
503
|
+
results: txResults,
|
|
504
|
+
};
|
|
505
|
+
}
|
|
506
|
+
async function assignWithdrawals(vm, block) {
|
|
507
|
+
if (vm.common.isActivatedEIP(7928)) {
|
|
508
|
+
vm.evm.blockLevelAccessList.blockAccessIndex = block.transactions.length + 1;
|
|
509
|
+
}
|
|
510
|
+
const withdrawals = block.withdrawals;
|
|
511
|
+
for (const withdrawal of withdrawals) {
|
|
512
|
+
const { address, amount } = withdrawal;
|
|
513
|
+
// Withdrawal amount is represented in Gwei so needs to be
|
|
514
|
+
// converted to wei
|
|
515
|
+
// Note: event if amount is 0, still reward the account
|
|
516
|
+
// such that the account is touched and marked for cleanup if it is empty
|
|
517
|
+
await rewardAccount(vm.evm, address, amount * GWEI_TO_WEI, vm.common);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* Calculates block rewards for miner and ommers and puts
|
|
522
|
+
* the updated balances of their accounts to state.
|
|
523
|
+
*/
|
|
524
|
+
async function assignBlockRewards(vm, block) {
|
|
525
|
+
if (vm.DEBUG) {
|
|
526
|
+
debug(`Assign block rewards`);
|
|
527
|
+
}
|
|
528
|
+
const minerReward = vm.common.param('minerReward');
|
|
529
|
+
const ommers = block.uncleHeaders;
|
|
530
|
+
// Reward ommers
|
|
531
|
+
for (const ommer of ommers) {
|
|
532
|
+
const reward = calculateOmmerReward(ommer.number, block.header.number, minerReward);
|
|
533
|
+
const account = await rewardAccount(vm.evm, ommer.coinbase, reward, vm.common);
|
|
534
|
+
if (vm.DEBUG) {
|
|
535
|
+
debug(`Add uncle reward ${reward} to account ${ommer.coinbase} (-> ${account.balance})`);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
// Reward miner
|
|
539
|
+
const reward = calculateMinerReward(minerReward, ommers.length);
|
|
540
|
+
const account = await rewardAccount(vm.evm, block.header.coinbase, reward, vm.common);
|
|
541
|
+
if (vm.DEBUG) {
|
|
542
|
+
debug(`Add miner reward ${reward} to account ${block.header.coinbase} (-> ${account.balance})`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
function calculateOmmerReward(ommerBlockNumber, blockNumber, minerReward) {
|
|
546
|
+
const heightDiff = blockNumber - ommerBlockNumber;
|
|
547
|
+
let reward = ((BIGINT_8 - heightDiff) * minerReward) / BIGINT_8;
|
|
548
|
+
if (reward < BIGINT_0) {
|
|
549
|
+
reward = BIGINT_0;
|
|
550
|
+
}
|
|
551
|
+
return reward;
|
|
552
|
+
}
|
|
553
|
+
export function calculateMinerReward(minerReward, ommersNum) {
|
|
554
|
+
// calculate nibling reward
|
|
555
|
+
const niblingReward = minerReward / BigInt(32);
|
|
556
|
+
const totalNiblingReward = niblingReward * BigInt(ommersNum);
|
|
557
|
+
const reward = minerReward + totalNiblingReward;
|
|
558
|
+
return reward;
|
|
559
|
+
}
|
|
560
|
+
export async function rewardAccount(evm, address, reward, common) {
|
|
561
|
+
let account = await evm.stateManager.getAccount(address);
|
|
562
|
+
if (account === undefined) {
|
|
563
|
+
if (common.isActivatedEIP(7864) === true && reward !== BIGINT_0) {
|
|
564
|
+
if (evm.systemBinaryTreeAccessWitness === undefined) {
|
|
565
|
+
throw Error(`systemBinaryTreeAccessWitness required if binary tree (EIP-7864) is activated`);
|
|
566
|
+
}
|
|
567
|
+
evm.systemBinaryTreeAccessWitness.writeAccountHeader(address);
|
|
568
|
+
}
|
|
569
|
+
account = new Account();
|
|
570
|
+
}
|
|
571
|
+
const originalBalance = account.balance;
|
|
572
|
+
account.balance += reward;
|
|
573
|
+
if (common.isActivatedEIP(7928)) {
|
|
574
|
+
if (reward === BIGINT_0) {
|
|
575
|
+
evm.blockLevelAccessList?.addAddress(address.toString());
|
|
576
|
+
}
|
|
577
|
+
else {
|
|
578
|
+
evm.blockLevelAccessList.addBalanceChange(address.toString(), account.balance, evm.blockLevelAccessList.blockAccessIndex, originalBalance);
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
await evm.journal.putAccount(address, account);
|
|
582
|
+
if (common.isActivatedEIP(7864) === true && reward !== BIGINT_0) {
|
|
583
|
+
if (evm.systemBinaryTreeAccessWitness === undefined) {
|
|
584
|
+
throw Error(`systemBinaryTreeAccessWitness required if binary tree (EIP-7864) is activated`);
|
|
585
|
+
}
|
|
586
|
+
evm.systemBinaryTreeAccessWitness.writeAccountBasicData(address);
|
|
587
|
+
evm.systemBinaryTreeAccessWitness.readAccountCodeHash(address);
|
|
588
|
+
}
|
|
589
|
+
return account;
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Returns the encoded tx receipt.
|
|
593
|
+
*/
|
|
594
|
+
export function encodeReceipt(receipt, txType) {
|
|
595
|
+
const encoded = RLP.encode([
|
|
596
|
+
receipt.stateRoot ??
|
|
597
|
+
(receipt.status === 0 ? Uint8Array.from([]) : hexToBytes('0x01')),
|
|
598
|
+
bigIntToBytes(receipt.cumulativeBlockGasUsed),
|
|
599
|
+
receipt.bitvector,
|
|
600
|
+
receipt.logs,
|
|
601
|
+
]);
|
|
602
|
+
if (txType === TransactionType.Legacy) {
|
|
603
|
+
return encoded;
|
|
604
|
+
}
|
|
605
|
+
// Serialize receipt according to EIP-2718:
|
|
606
|
+
// `typed-receipt = tx-type || receipt-data`
|
|
607
|
+
return concatBytes(intToBytes(txType), encoded);
|
|
608
|
+
}
|
|
609
|
+
/**
|
|
610
|
+
* Apply the DAO fork changes to the VM
|
|
611
|
+
*/
|
|
612
|
+
async function _applyDAOHardfork(evm) {
|
|
613
|
+
const state = evm.stateManager;
|
|
614
|
+
/* DAO account list */
|
|
615
|
+
const DAOAccountList = DAOConfig.DAOAccounts;
|
|
616
|
+
const DAORefundContract = DAOConfig.DAORefundContract;
|
|
617
|
+
const DAORefundContractAddress = new Address(unprefixedHexToBytes(DAORefundContract));
|
|
618
|
+
if ((await state.getAccount(DAORefundContractAddress)) === undefined) {
|
|
619
|
+
await evm.journal.putAccount(DAORefundContractAddress, new Account());
|
|
620
|
+
}
|
|
621
|
+
let DAORefundAccount = await state.getAccount(DAORefundContractAddress);
|
|
622
|
+
if (DAORefundAccount === undefined) {
|
|
623
|
+
DAORefundAccount = new Account();
|
|
624
|
+
}
|
|
625
|
+
const originalDAORefundAccountBalance = DAORefundAccount.balance;
|
|
626
|
+
for (const addr of DAOAccountList) {
|
|
627
|
+
// retrieve the account and add it to the DAO's Refund accounts' balance.
|
|
628
|
+
const address = new Address(unprefixedHexToBytes(addr));
|
|
629
|
+
let account = await state.getAccount(address);
|
|
630
|
+
if (account === undefined) {
|
|
631
|
+
account = new Account();
|
|
632
|
+
}
|
|
633
|
+
DAORefundAccount.balance += account.balance;
|
|
634
|
+
// clear the accounts' balance
|
|
635
|
+
const originalBalance = account.balance;
|
|
636
|
+
account.balance = BIGINT_0;
|
|
637
|
+
await evm.journal.putAccount(address, account);
|
|
638
|
+
if (evm.common.isActivatedEIP(7928)) {
|
|
639
|
+
evm.blockLevelAccessList.addBalanceChange(address.toString(), account.balance, evm.blockLevelAccessList.blockAccessIndex, originalBalance);
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
// finally, put the Refund Account
|
|
643
|
+
await evm.journal.putAccount(DAORefundContractAddress, DAORefundAccount);
|
|
644
|
+
if (evm.common.isActivatedEIP(7928)) {
|
|
645
|
+
evm.blockLevelAccessList.addBalanceChange(DAORefundContractAddress.toString(), DAORefundAccount.balance, evm.blockLevelAccessList.blockAccessIndex, originalDAORefundAccountBalance);
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
async function _genTxTrie(block) {
|
|
649
|
+
if (block.transactions.length === 0) {
|
|
650
|
+
return KECCAK256_RLP;
|
|
651
|
+
}
|
|
652
|
+
const trie = new MerklePatriciaTrie({ common: block.common });
|
|
653
|
+
for (const [i, tx] of block.transactions.entries()) {
|
|
654
|
+
await trie.put(RLP.encode(i), tx.serialize());
|
|
655
|
+
}
|
|
656
|
+
return trie.root();
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Internal helper function to create an annotated error message
|
|
660
|
+
*
|
|
661
|
+
* @param msg Base error message
|
|
662
|
+
* @hidden
|
|
663
|
+
*/
|
|
664
|
+
function _errorMsg(msg, vm, block) {
|
|
665
|
+
const blockErrorStr = 'errorStr' in block ? block.errorStr() : 'block';
|
|
666
|
+
const errorMsg = `${msg} (${vm.errorStr()} -> ${blockErrorStr})`;
|
|
667
|
+
return errorMsg;
|
|
668
|
+
}
|
|
669
|
+
const DAOConfig = {
|
|
670
|
+
DAOAccounts: [
|
|
671
|
+
'd4fe7bc31cedb7bfb8a345f31e668033056b2728',
|
|
672
|
+
'b3fb0e5aba0e20e5c49d252dfd30e102b171a425',
|
|
673
|
+
'2c19c7f9ae8b751e37aeb2d93a699722395ae18f',
|
|
674
|
+
'ecd135fa4f61a655311e86238c92adcd779555d2',
|
|
675
|
+
'1975bd06d486162d5dc297798dfc41edd5d160a7',
|
|
676
|
+
'a3acf3a1e16b1d7c315e23510fdd7847b48234f6',
|
|
677
|
+
'319f70bab6845585f412ec7724b744fec6095c85',
|
|
678
|
+
'06706dd3f2c9abf0a21ddcc6941d9b86f0596936',
|
|
679
|
+
'5c8536898fbb74fc7445814902fd08422eac56d0',
|
|
680
|
+
'6966ab0d485353095148a2155858910e0965b6f9',
|
|
681
|
+
'779543a0491a837ca36ce8c635d6154e3c4911a6',
|
|
682
|
+
'2a5ed960395e2a49b1c758cef4aa15213cfd874c',
|
|
683
|
+
'5c6e67ccd5849c0d29219c4f95f1a7a93b3f5dc5',
|
|
684
|
+
'9c50426be05db97f5d64fc54bf89eff947f0a321',
|
|
685
|
+
'200450f06520bdd6c527622a273333384d870efb',
|
|
686
|
+
'be8539bfe837b67d1282b2b1d61c3f723966f049',
|
|
687
|
+
'6b0c4d41ba9ab8d8cfb5d379c69a612f2ced8ecb',
|
|
688
|
+
'f1385fb24aad0cd7432824085e42aff90886fef5',
|
|
689
|
+
'd1ac8b1ef1b69ff51d1d401a476e7e612414f091',
|
|
690
|
+
'8163e7fb499e90f8544ea62bbf80d21cd26d9efd',
|
|
691
|
+
'51e0ddd9998364a2eb38588679f0d2c42653e4a6',
|
|
692
|
+
'627a0a960c079c21c34f7612d5d230e01b4ad4c7',
|
|
693
|
+
'f0b1aa0eb660754448a7937c022e30aa692fe0c5',
|
|
694
|
+
'24c4d950dfd4dd1902bbed3508144a54542bba94',
|
|
695
|
+
'9f27daea7aca0aa0446220b98d028715e3bc803d',
|
|
696
|
+
'a5dc5acd6a7968a4554d89d65e59b7fd3bff0f90',
|
|
697
|
+
'd9aef3a1e38a39c16b31d1ace71bca8ef58d315b',
|
|
698
|
+
'63ed5a272de2f6d968408b4acb9024f4cc208ebf',
|
|
699
|
+
'6f6704e5a10332af6672e50b3d9754dc460dfa4d',
|
|
700
|
+
'77ca7b50b6cd7e2f3fa008e24ab793fd56cb15f6',
|
|
701
|
+
'492ea3bb0f3315521c31f273e565b868fc090f17',
|
|
702
|
+
'0ff30d6de14a8224aa97b78aea5388d1c51c1f00',
|
|
703
|
+
'9ea779f907f0b315b364b0cfc39a0fde5b02a416',
|
|
704
|
+
'ceaeb481747ca6c540a000c1f3641f8cef161fa7',
|
|
705
|
+
'cc34673c6c40e791051898567a1222daf90be287',
|
|
706
|
+
'579a80d909f346fbfb1189493f521d7f48d52238',
|
|
707
|
+
'e308bd1ac5fda103967359b2712dd89deffb7973',
|
|
708
|
+
'4cb31628079fb14e4bc3cd5e30c2f7489b00960c',
|
|
709
|
+
'ac1ecab32727358dba8962a0f3b261731aad9723',
|
|
710
|
+
'4fd6ace747f06ece9c49699c7cabc62d02211f75',
|
|
711
|
+
'440c59b325d2997a134c2c7c60a8c61611212bad',
|
|
712
|
+
'4486a3d68fac6967006d7a517b889fd3f98c102b',
|
|
713
|
+
'9c15b54878ba618f494b38f0ae7443db6af648ba',
|
|
714
|
+
'27b137a85656544b1ccb5a0f2e561a5703c6a68f',
|
|
715
|
+
'21c7fdb9ed8d291d79ffd82eb2c4356ec0d81241',
|
|
716
|
+
'23b75c2f6791eef49c69684db4c6c1f93bf49a50',
|
|
717
|
+
'1ca6abd14d30affe533b24d7a21bff4c2d5e1f3b',
|
|
718
|
+
'b9637156d330c0d605a791f1c31ba5890582fe1c',
|
|
719
|
+
'6131c42fa982e56929107413a9d526fd99405560',
|
|
720
|
+
'1591fc0f688c81fbeb17f5426a162a7024d430c2',
|
|
721
|
+
'542a9515200d14b68e934e9830d91645a980dd7a',
|
|
722
|
+
'c4bbd073882dd2add2424cf47d35213405b01324',
|
|
723
|
+
'782495b7b3355efb2833d56ecb34dc22ad7dfcc4',
|
|
724
|
+
'58b95c9a9d5d26825e70a82b6adb139d3fd829eb',
|
|
725
|
+
'3ba4d81db016dc2890c81f3acec2454bff5aada5',
|
|
726
|
+
'b52042c8ca3f8aa246fa79c3feaa3d959347c0ab',
|
|
727
|
+
'e4ae1efdfc53b73893af49113d8694a057b9c0d1',
|
|
728
|
+
'3c02a7bc0391e86d91b7d144e61c2c01a25a79c5',
|
|
729
|
+
'0737a6b837f97f46ebade41b9bc3e1c509c85c53',
|
|
730
|
+
'97f43a37f595ab5dd318fb46e7a155eae057317a',
|
|
731
|
+
'52c5317c848ba20c7504cb2c8052abd1fde29d03',
|
|
732
|
+
'4863226780fe7c0356454236d3b1c8792785748d',
|
|
733
|
+
'5d2b2e6fcbe3b11d26b525e085ff818dae332479',
|
|
734
|
+
'5f9f3392e9f62f63b8eac0beb55541fc8627f42c',
|
|
735
|
+
'057b56736d32b86616a10f619859c6cd6f59092a',
|
|
736
|
+
'9aa008f65de0b923a2a4f02012ad034a5e2e2192',
|
|
737
|
+
'304a554a310c7e546dfe434669c62820b7d83490',
|
|
738
|
+
'914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79',
|
|
739
|
+
'4deb0033bb26bc534b197e61d19e0733e5679784',
|
|
740
|
+
'07f5c1e1bc2c93e0402f23341973a0e043f7bf8a',
|
|
741
|
+
'35a051a0010aba705c9008d7a7eff6fb88f6ea7b',
|
|
742
|
+
'4fa802324e929786dbda3b8820dc7834e9134a2a',
|
|
743
|
+
'9da397b9e80755301a3b32173283a91c0ef6c87e',
|
|
744
|
+
'8d9edb3054ce5c5774a420ac37ebae0ac02343c6',
|
|
745
|
+
'0101f3be8ebb4bbd39a2e3b9a3639d4259832fd9',
|
|
746
|
+
'5dc28b15dffed94048d73806ce4b7a4612a1d48f',
|
|
747
|
+
'bcf899e6c7d9d5a215ab1e3444c86806fa854c76',
|
|
748
|
+
'12e626b0eebfe86a56d633b9864e389b45dcb260',
|
|
749
|
+
'a2f1ccba9395d7fcb155bba8bc92db9bafaeade7',
|
|
750
|
+
'ec8e57756626fdc07c63ad2eafbd28d08e7b0ca5',
|
|
751
|
+
'd164b088bd9108b60d0ca3751da4bceb207b0782',
|
|
752
|
+
'6231b6d0d5e77fe001c2a460bd9584fee60d409b',
|
|
753
|
+
'1cba23d343a983e9b5cfd19496b9a9701ada385f',
|
|
754
|
+
'a82f360a8d3455c5c41366975bde739c37bfeb8a',
|
|
755
|
+
'9fcd2deaff372a39cc679d5c5e4de7bafb0b1339',
|
|
756
|
+
'005f5cee7a43331d5a3d3eec71305925a62f34b6',
|
|
757
|
+
'0e0da70933f4c7849fc0d203f5d1d43b9ae4532d',
|
|
758
|
+
'd131637d5275fd1a68a3200f4ad25c71a2a9522e',
|
|
759
|
+
'bc07118b9ac290e4622f5e77a0853539789effbe',
|
|
760
|
+
'47e7aa56d6bdf3f36be34619660de61275420af8',
|
|
761
|
+
'acd87e28b0c9d1254e868b81cba4cc20d9a32225',
|
|
762
|
+
'adf80daec7ba8dcf15392f1ac611fff65d94f880',
|
|
763
|
+
'5524c55fb03cf21f549444ccbecb664d0acad706',
|
|
764
|
+
'40b803a9abce16f50f36a77ba41180eb90023925',
|
|
765
|
+
'fe24cdd8648121a43a7c86d289be4dd2951ed49f',
|
|
766
|
+
'17802f43a0137c506ba92291391a8a8f207f487d',
|
|
767
|
+
'253488078a4edf4d6f42f113d1e62836a942cf1a',
|
|
768
|
+
'86af3e9626fce1957c82e88cbf04ddf3a2ed7915',
|
|
769
|
+
'b136707642a4ea12fb4bae820f03d2562ebff487',
|
|
770
|
+
'dbe9b615a3ae8709af8b93336ce9b477e4ac0940',
|
|
771
|
+
'f14c14075d6c4ed84b86798af0956deef67365b5',
|
|
772
|
+
'ca544e5c4687d109611d0f8f928b53a25af72448',
|
|
773
|
+
'aeeb8ff27288bdabc0fa5ebb731b6f409507516c',
|
|
774
|
+
'cbb9d3703e651b0d496cdefb8b92c25aeb2171f7',
|
|
775
|
+
'6d87578288b6cb5549d5076a207456a1f6a63dc0',
|
|
776
|
+
'b2c6f0dfbb716ac562e2d85d6cb2f8d5ee87603e',
|
|
777
|
+
'accc230e8a6e5be9160b8cdf2864dd2a001c28b6',
|
|
778
|
+
'2b3455ec7fedf16e646268bf88846bd7a2319bb2',
|
|
779
|
+
'4613f3bca5c44ea06337a9e439fbc6d42e501d0a',
|
|
780
|
+
'd343b217de44030afaa275f54d31a9317c7f441e',
|
|
781
|
+
'84ef4b2357079cd7a7c69fd7a37cd0609a679106',
|
|
782
|
+
'da2fef9e4a3230988ff17df2165440f37e8b1708',
|
|
783
|
+
'f4c64518ea10f995918a454158c6b61407ea345c',
|
|
784
|
+
'7602b46df5390e432ef1c307d4f2c9ff6d65cc97',
|
|
785
|
+
'bb9bc244d798123fde783fcc1c72d3bb8c189413',
|
|
786
|
+
'807640a13483f8ac783c557fcdf27be11ea4ac7a',
|
|
787
|
+
],
|
|
788
|
+
DAORefundContract: 'bf4ed7b27f1d666546e30d74d50d173d20bca754',
|
|
789
|
+
};
|
|
790
|
+
//# sourceMappingURL=runBlock.js.map
|