diff --git a/.github/workflows/vm-lint.yml b/.github/workflows/vm-lint.yml index 82e22742f47..89d61585638 100644 --- a/.github/workflows/vm-lint.yml +++ b/.github/workflows/vm-lint.yml @@ -17,7 +17,7 @@ jobs: steps: - uses: actions/setup-node@v1 with: - node-version: 8.x + node-version: 12.x - uses: actions/checkout@v1 - name: Cache node modules id: cache-node-modules diff --git a/.github/workflows/vm-nightly-test.yml b/.github/workflows/vm-nightly-test.yml index 27d92e4a01a..5a5aec2afd0 100644 --- a/.github/workflows/vm-nightly-test.yml +++ b/.github/workflows/vm-nightly-test.yml @@ -8,7 +8,7 @@ jobs: steps: - uses: actions/setup-node@v1 with: - node-version: 8.x + node-version: 12.x - uses: actions/checkout@v1 - run: npm install working-directory: '${{ env.cwd }}' @@ -27,7 +27,7 @@ jobs: steps: - uses: actions/setup-node@v1 with: - node-version: 8.x + node-version: 12.x - uses: actions/checkout@v1 - run: npm install working-directory: '${{ env.cwd }}' @@ -42,7 +42,7 @@ jobs: steps: - uses: actions/setup-node@v1 with: - node-version: 8.x + node-version: 12.x - uses: actions/checkout@v1 - run: npm install working-directory: '${{ env.cwd }}' @@ -57,7 +57,7 @@ jobs: steps: - uses: actions/setup-node@v1 with: - node-version: 8.x + node-version: 12.x - uses: actions/checkout@v1 - run: npm install working-directory: '${{ env.cwd }}' diff --git a/.github/workflows/vm-test.yml b/.github/workflows/vm-test.yml index 00401e597b9..f97ffc78235 100644 --- a/.github/workflows/vm-test.yml +++ b/.github/workflows/vm-test.yml @@ -25,14 +25,14 @@ jobs: steps: - uses: actions/setup-node@v1 with: - node-version: 8.x + node-version: 12.x - uses: actions/checkout@v1 - name: Cache node modules id: cache-node-modules uses: actions/cache@v1 with: path: node_modules - key: "${{ runner.os }}-node8-${{ hashFiles('**/package.json') }}" + key: "${{ runner.os }}-node12-${{ hashFiles('**/package.json') }}" - run: npm install if: steps.cache-node-modules.outputs.cache-hit != 'true' working-directory: '${{ env.cwd }}' @@ -51,14 +51,14 @@ jobs: steps: - uses: actions/setup-node@v1 with: - node-version: 8.x + node-version: 12.x - uses: actions/checkout@v1 - name: Cache node modules id: cache-node-modules uses: actions/cache@v1 with: path: node_modules - key: "${{ runner.os }}-node8-${{ hashFiles('**/package.json') }}" + key: "${{ runner.os }}-node12-${{ hashFiles('**/package.json') }}" - run: npm install if: steps.cache-node-modules.outputs.cache-hit != 'true' working-directory: '${{ env.cwd }}' @@ -73,14 +73,14 @@ jobs: steps: - uses: actions/setup-node@v1 with: - node-version: 8.x + node-version: 12.x - uses: actions/checkout@v1 - name: Cache node modules id: cache-node-modules uses: actions/cache@v1 with: path: node_modules - key: "${{ runner.os }}-node8-${{ hashFiles('**/package.json') }}" + key: "${{ runner.os }}-node12-${{ hashFiles('**/package.json') }}" - run: npm install if: steps.cache-node-modules.outputs.cache-hit != 'true' working-directory: '${{ env.cwd }}' diff --git a/packages/vm/CHANGELOG.md b/packages/vm/CHANGELOG.md index ff5da386676..3c704080148 100644 --- a/packages/vm/CHANGELOG.md +++ b/packages/vm/CHANGELOG.md @@ -352,7 +352,7 @@ vm.runTx( { tx: tx, }, - function(err, result) { + function (err, result) { if (err) { // Handle errors appropriately } diff --git a/packages/vm/README.md b/packages/vm/README.md index bbf25c260a7..4c62c5867f5 100644 --- a/packages/vm/README.md +++ b/packages/vm/README.md @@ -75,7 +75,7 @@ const PUSH1 = '60' // Note that numbers added are hex values, so '20' would be '32' as decimal e.g. const code = [PUSH1, '03', PUSH1, '05', ADD, STOP] -vm.on('step', function(data) { +vm.on('step', function (data) { console.log(`Opcode: ${data.opcode.name}\tStack: ${data.stack}`) }) @@ -83,11 +83,11 @@ vm.runCode({ code: Buffer.from(code.join(''), 'hex'), gasLimit: new BN(0xffff), }) - .then(results => { + .then((results) => { console.log('Returned : ' + results.returnValue.toString('hex')) console.log('gasUsed : ' + results.gasUsed.toString()) }) - .catch(err => console.log('Error : ' + err)) + .catch((err) => console.log('Error : ' + err)) ``` ## Example diff --git a/packages/vm/docs/classes/_exceptions_.vmerror.md b/packages/vm/docs/classes/_exceptions_.vmerror.md index 092e3f327de..7c9fc98a4ae 100644 --- a/packages/vm/docs/classes/_exceptions_.vmerror.md +++ b/packages/vm/docs/classes/_exceptions_.vmerror.md @@ -23,7 +23,7 @@ \+ **new VmError**(`error`: [ERROR](../enums/_exceptions_.error.md)): *[VmError](_exceptions_.vmerror.md)* -*Defined in [exceptions.ts:18](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/exceptions.ts#L18)* +*Defined in [exceptions.ts:19](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/exceptions.ts#L19)* **Parameters:** @@ -39,7 +39,7 @@ Name | Type | • **error**: *[ERROR](../enums/_exceptions_.error.md)* -*Defined in [exceptions.ts:17](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/exceptions.ts#L17)* +*Defined in [exceptions.ts:18](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/exceptions.ts#L18)* ___ @@ -47,4 +47,4 @@ ___ • **errorType**: *string* -*Defined in [exceptions.ts:18](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/exceptions.ts#L18)* +*Defined in [exceptions.ts:19](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/exceptions.ts#L19)* diff --git a/packages/vm/docs/classes/_index_.vm.md b/packages/vm/docs/classes/_index_.vm.md index 7a5f1d23162..3068678d4c2 100644 --- a/packages/vm/docs/classes/_index_.vm.md +++ b/packages/vm/docs/classes/_index_.vm.md @@ -27,17 +27,18 @@ This class is an AsyncEventEmitter, please consult the README to learn how to us * [allowUnlimitedContractSize](_index_.vm.md#allowunlimitedcontractsize) * [blockchain](_index_.vm.md#blockchain) * [opts](_index_.vm.md#opts) -* [pStateManager](_index_.vm.md#pstatemanager) * [stateManager](_index_.vm.md#statemanager) ### Methods * [copy](_index_.vm.md#copy) +* [init](_index_.vm.md#init) * [runBlock](_index_.vm.md#runblock) * [runBlockchain](_index_.vm.md#runblockchain) * [runCall](_index_.vm.md#runcall) * [runCode](_index_.vm.md#runcode) * [runTx](_index_.vm.md#runtx) +* [create](_index_.vm.md#static-create) ## Constructors @@ -45,7 +46,7 @@ This class is an AsyncEventEmitter, please consult the README to learn how to us \+ **new VM**(`opts`: [VMOpts](../interfaces/_index_.vmopts.md)): *[VM](_index_.vm.md)* -*Defined in [index.ts:75](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L75)* +*Defined in [index.ts:84](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L84)* Instantiates a new [VM](_index_.vm.md) Object. @@ -63,7 +64,7 @@ Name | Type | Default | Description | • **_common**: *Common* -*Defined in [index.ts:69](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L69)* +*Defined in [index.ts:68](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L68)* ___ @@ -71,7 +72,7 @@ ___ • **_emit**: *function* -*Defined in [index.ts:74](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L74)* +*Defined in [index.ts:73](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L73)* #### Type declaration: @@ -90,7 +91,7 @@ ___ • **_opcodes**: *OpcodeList* -*Defined in [index.ts:73](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L73)* +*Defined in [index.ts:72](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L72)* ___ @@ -98,7 +99,7 @@ ___ • **allowUnlimitedContractSize**: *boolean* -*Defined in [index.ts:72](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L72)* +*Defined in [index.ts:71](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L71)* ___ @@ -106,7 +107,7 @@ ___ • **blockchain**: *Blockchain* -*Defined in [index.ts:71](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L71)* +*Defined in [index.ts:70](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L70)* ___ @@ -114,15 +115,7 @@ ___ • **opts**: *[VMOpts](../interfaces/_index_.vmopts.md)* -*Defined in [index.ts:68](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L68)* - -___ - -### pStateManager - -• **pStateManager**: *PStateManager* - -*Defined in [index.ts:75](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L75)* +*Defined in [index.ts:67](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L67)* ___ @@ -130,7 +123,7 @@ ___ • **stateManager**: *[StateManager](_state_index_.statemanager.md)* -*Defined in [index.ts:70](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L70)* +*Defined in [index.ts:69](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L69)* ## Methods @@ -138,7 +131,7 @@ ___ ▸ **copy**(): *[VM](_index_.vm.md)* -*Defined in [index.ts:196](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L196)* +*Defined in [index.ts:220](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L220)* Returns a copy of the [VM](_index_.vm.md) instance. @@ -146,11 +139,21 @@ Returns a copy of the [VM](_index_.vm.md) instance. ___ +### init + +▸ **init**(): *Promise‹void›* + +*Defined in [index.ts:140](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L140)* + +**Returns:** *Promise‹void›* + +___ + ### runBlock ▸ **runBlock**(`opts`: [RunBlockOpts](../interfaces/_runblock_.runblockopts.md)): *Promise‹[RunBlockResult](../interfaces/_runblock_.runblockresult.md)›* -*Defined in [index.ts:160](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L160)* +*Defined in [index.ts:180](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L180)* Processes the `block` running all of the transactions it contains and updating the miner's account @@ -172,7 +175,7 @@ ___ ▸ **runBlockchain**(`blockchain`: any): *Promise‹void›* -*Defined in [index.ts:146](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L146)* +*Defined in [index.ts:165](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L165)* Processes blocks and adds them to the blockchain. @@ -192,7 +195,7 @@ ___ ▸ **runCall**(`opts`: [RunCallOpts](../interfaces/_runcall_.runcallopts.md)): *Promise‹[EVMResult](../interfaces/_evm_evm_.evmresult.md)›* -*Defined in [index.ts:180](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L180)* +*Defined in [index.ts:202](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L202)* runs a call (or create) operation. @@ -212,7 +215,7 @@ ___ ▸ **runCode**(`opts`: [RunCodeOpts](../interfaces/_runcode_.runcodeopts.md)): *Promise‹[ExecResult](../interfaces/_evm_evm_.execresult.md)›* -*Defined in [index.ts:189](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L189)* +*Defined in [index.ts:212](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L212)* Runs EVM code. @@ -232,7 +235,7 @@ ___ ▸ **runTx**(`opts`: [RunTxOpts](../interfaces/_runtx_.runtxopts.md)): *Promise‹[RunTxResult](../interfaces/_runtx_.runtxresult.md)›* -*Defined in [index.ts:171](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L171)* +*Defined in [index.ts:192](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L192)* Process a transaction. Run the vm. Transfers eth. Checks balances. @@ -247,3 +250,21 @@ Name | Type | `opts` | [RunTxOpts](../interfaces/_runtx_.runtxopts.md) | **Returns:** *Promise‹[RunTxResult](../interfaces/_runtx_.runtxresult.md)›* + +___ + +### `Static` create + +▸ **create**(`opts`: [VMOpts](../interfaces/_index_.vmopts.md)): *Promise‹[VM](_index_.vm.md)›* + +*Defined in [index.ts:80](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L80)* + +VM async constructor. Creates engine instance and initializes it. + +**Parameters:** + +Name | Type | Default | Description | +------ | ------ | ------ | ------ | +`opts` | [VMOpts](../interfaces/_index_.vmopts.md) | {} | VM engine constructor options | + +**Returns:** *Promise‹[VM](_index_.vm.md)›* diff --git a/packages/vm/docs/classes/_state_index_.statemanager.md b/packages/vm/docs/classes/_state_index_.statemanager.md index 53c604fcc9d..99525f4e2bc 100644 --- a/packages/vm/docs/classes/_state_index_.statemanager.md +++ b/packages/vm/docs/classes/_state_index_.statemanager.md @@ -59,7 +59,7 @@ state trie. \+ **new StateManager**(`opts`: [StateManagerOpts](../interfaces/_state_statemanager_.statemanageropts.md)): *[StateManager](_state_index_.statemanager.md)* -*Defined in [state/stateManager.ts:46](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L46)* +*Defined in [state/stateManager.ts:51](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L51)* Instantiate the StateManager interface. @@ -77,7 +77,7 @@ Name | Type | Default | • **_cache**: *Cache* -*Defined in [state/stateManager.ts:42](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L42)* +*Defined in [state/stateManager.ts:47](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L47)* ___ @@ -85,7 +85,7 @@ ___ • **_checkpointCount**: *number* -*Defined in [state/stateManager.ts:45](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L45)* +*Defined in [state/stateManager.ts:50](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L50)* ___ @@ -93,7 +93,7 @@ ___ • **_common**: *Common* -*Defined in [state/stateManager.ts:39](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L39)* +*Defined in [state/stateManager.ts:44](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L44)* ___ @@ -101,7 +101,7 @@ ___ • **_originalStorageCache**: *Map‹string, Map‹string, Buffer››* -*Defined in [state/stateManager.ts:46](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L46)* +*Defined in [state/stateManager.ts:51](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L51)* ___ @@ -109,7 +109,7 @@ ___ • **_storageTries**: *any* -*Defined in [state/stateManager.ts:41](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L41)* +*Defined in [state/stateManager.ts:46](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L46)* ___ @@ -117,7 +117,7 @@ ___ • **_touched**: *Set‹string›* -*Defined in [state/stateManager.ts:43](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L43)* +*Defined in [state/stateManager.ts:48](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L48)* ___ @@ -125,23 +125,23 @@ ___ • **_touchedStack**: *Set‹string›[]* -*Defined in [state/stateManager.ts:44](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L44)* +*Defined in [state/stateManager.ts:49](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L49)* ___ ### _trie -• **_trie**: *any* +• **_trie**: *Trie* -*Defined in [state/stateManager.ts:40](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L40)* +*Defined in [state/stateManager.ts:45](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L45)* ## Methods ### `Private` _getStorageTrie -▸ **_getStorageTrie**(`address`: Buffer, `cb`: any): *void* +▸ **_getStorageTrie**(`address`: Buffer): *Promise‹Trie›* -*Defined in [state/stateManager.ts:189](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L189)* +*Defined in [state/stateManager.ts:163](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L163)* Gets the storage trie for an account from the storage cache or does a lookup. @@ -151,17 +151,16 @@ cache or does a lookup. Name | Type | ------ | ------ | `address` | Buffer | -`cb` | any | -**Returns:** *void* +**Returns:** *Promise‹Trie›* ___ ### `Private` _lookupStorageTrie -▸ **_lookupStorageTrie**(`address`: Buffer, `cb`: any): *void* +▸ **_lookupStorageTrie**(`address`: Buffer): *Promise‹Trie›* -*Defined in [state/stateManager.ts:171](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L171)* +*Defined in [state/stateManager.ts:149](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L149)* Creates a storage trie from the primary storage trie for an account and saves this in the storage cache. @@ -171,37 +170,47 @@ for an account and saves this in the storage cache. Name | Type | ------ | ------ | `address` | Buffer | -`cb` | any | -**Returns:** *void* +**Returns:** *Promise‹Trie›* ___ ### `Private` _modifyContractStorage -▸ **_modifyContractStorage**(`address`: Buffer, `modifyTrie`: any, `cb`: any): *void* +▸ **_modifyContractStorage**(`address`: Buffer, `modifyTrie`: function): *Promise‹void›* -*Defined in [state/stateManager.ts:276](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L276)* +*Defined in [state/stateManager.ts:233](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L233)* -Modifies the storage trie of an account +Modifies the storage trie of an account. **Parameters:** -Name | Type | Description | ------- | ------ | ------ | -`address` | Buffer | Address of the account whose storage is to be modified | -`modifyTrie` | any | Function to modify the storage trie of the account | -`cb` | any | - | +▪ **address**: *Buffer* -**Returns:** *void* +Address of the account whose storage is to be modified + +▪ **modifyTrie**: *function* + +Function to modify the storage trie of the account + +▸ (`storageTrie`: Trie, `done`: Function): *void* + +**Parameters:** + +Name | Type | +------ | ------ | +`storageTrie` | Trie | +`done` | Function | + +**Returns:** *Promise‹void›* ___ ### accountIsEmpty -▸ **accountIsEmpty**(`address`: Buffer, `cb`: any): *void* +▸ **accountIsEmpty**(`address`: Buffer): *Promise‹boolean›* -*Defined in [state/stateManager.ts:573](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L573)* +*Defined in [state/stateManager.ts:482](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L482)* Checks if the `account` corresponding to `address` is empty as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161). @@ -210,57 +219,44 @@ EIP-161 (https://eips.ethereum.org/EIPS/eip-161). Name | Type | Description | ------ | ------ | ------ | -`address` | Buffer | Address to check | -`cb` | any | | +`address` | Buffer | Address to check | -**Returns:** *void* +**Returns:** *Promise‹boolean›* ___ ### checkpoint -▸ **checkpoint**(`cb`: any): *void* +▸ **checkpoint**(): *Promise‹void›* -*Defined in [state/stateManager.ts:346](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L346)* +*Defined in [state/stateManager.ts:302](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L302)* Checkpoints the current state of the StateManager instance. State changes that follow can then be committed by calling `commit` or `reverted` by calling rollback. -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### cleanupTouchedAccounts -▸ **cleanupTouchedAccounts**(`cb`: any): *void* +▸ **cleanupTouchedAccounts**(): *Promise‹void›* -*Defined in [state/stateManager.ts:594](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L594)* +*Defined in [state/stateManager.ts:497](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L497)* Removes accounts form the state trie that have been touched, as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161). -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### clearContractStorage -▸ **clearContractStorage**(`address`: Buffer, `cb`: any): *void* +▸ **clearContractStorage**(`address`: Buffer): *Promise‹void›* -*Defined in [state/stateManager.ts:329](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L329)* +*Defined in [state/stateManager.ts:290](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L290)* Clears all storage entries for the account corresponding to `address`. @@ -268,29 +264,22 @@ Clears all storage entries for the account corresponding to `address`. Name | Type | Description | ------ | ------ | ------ | -`address` | Buffer | Address to clear the storage of | -`cb` | any | Callback function | +`address` | Buffer | Address to clear the storage of | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### commit -▸ **commit**(`cb`: any): *void* +▸ **commit**(): *Promise‹void›* -*Defined in [state/stateManager.ts:359](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L359)* +*Defined in [state/stateManager.ts:313](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L313)* Commits the current change-set to the instance since the last call to checkpoint. -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ @@ -298,7 +287,7 @@ ___ ▸ **copy**(): *[StateManager](_state_index_.statemanager.md)* -*Defined in [state/stateManager.ts:72](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L72)* +*Defined in [state/stateManager.ts:77](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L77)* Copies the current instance of the `StateManager` at the last fully committed point, i.e. as if all current @@ -310,9 +299,9 @@ ___ ### dumpStorage -▸ **dumpStorage**(`address`: Buffer, `cb`: any): *void* +▸ **dumpStorage**(`address`: Buffer): *Promise‹[StorageDump](../interfaces/_state_statemanager_.storagedump.md)›* -*Defined in [state/stateManager.ts:479](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L479)* +*Defined in [state/stateManager.ts:410](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L410)* Dumps the the storage values for an `account` specified by `address`. @@ -321,37 +310,34 @@ Dumps the the storage values for an `account` specified by `address`. Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | The address of the `account` to return storage for | -`cb` | any | | -**Returns:** *void* +**Returns:** *Promise‹[StorageDump](../interfaces/_state_statemanager_.storagedump.md)›* + +- The state of the account as an `Object` map. +Keys are are the storage keys, values are the storage values as strings. +Both are represented as hex strings without the `0x` prefix. ___ ### generateCanonicalGenesis -▸ **generateCanonicalGenesis**(`cb`: any): *void* +▸ **generateCanonicalGenesis**(): *Promise‹void›* -*Defined in [state/stateManager.ts:519](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L519)* +*Defined in [state/stateManager.ts:442](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L442)* Generates a canonical genesis state on the instance based on the configured chain parameters. Will error if there are uncommitted checkpoints on the instance. -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### generateGenesis -▸ **generateGenesis**(`initState`: any, `cb`: any): *any* +▸ **generateGenesis**(`initState`: any): *Promise‹void›* -*Defined in [state/stateManager.ts:538](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L538)* +*Defined in [state/stateManager.ts:457](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L457)* Initializes the provided genesis state into the state trie @@ -359,18 +345,17 @@ Initializes the provided genesis state into the state trie Name | Type | Description | ------ | ------ | ------ | -`initState` | any | Object (address -> balance) | -`cb` | any | Callback function | +`initState` | any | Object (address -> balance) | -**Returns:** *any* +**Returns:** *Promise‹void›* ___ ### getAccount -▸ **getAccount**(`address`: Buffer, `cb`: any): *void* +▸ **getAccount**(`address`: Buffer): *Promise‹Account›* -*Defined in [state/stateManager.ts:90](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L90)* +*Defined in [state/stateManager.ts:86](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L86)* Gets the [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) associated with `address`. Returns an empty account if the account does not exist. @@ -379,18 +364,17 @@ associated with `address`. Returns an empty account if the account does not exis Name | Type | Description | ------ | ------ | ------ | -`address` | Buffer | Address of the `account` to get | -`cb` | any | | +`address` | Buffer | Address of the `account` to get | -**Returns:** *void* +**Returns:** *Promise‹Account›* ___ ### getContractCode -▸ **getContractCode**(`address`: Buffer, `cb`: any): *void* +▸ **getContractCode**(`address`: Buffer): *Promise‹Buffer›* -*Defined in [state/stateManager.ts:157](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L157)* +*Defined in [state/stateManager.ts:137](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L137)* Gets the code corresponding to the provided `address`. @@ -399,17 +383,19 @@ Gets the code corresponding to the provided `address`. Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address to get the `code` for | -`cb` | any | | -**Returns:** *void* +**Returns:** *Promise‹Buffer›* + +- Resolves with the code corresponding to the provided address. +Returns an empty `Buffer` if the account has no associated code. ___ ### getContractStorage -▸ **getContractStorage**(`address`: Buffer, `key`: Buffer, `cb`: any): *void* +▸ **getContractStorage**(`address`: Buffer, `key`: Buffer): *Promise‹Buffer›* -*Defined in [state/stateManager.ts:215](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L215)* +*Defined in [state/stateManager.ts:182](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L182)* Gets the storage value associated with the provided `address` and `key`. This method returns the shortest representation of the stored value. @@ -420,17 +406,20 @@ Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address of the account to get the storage for | `key` | Buffer | Key in the account's storage to get the value for. Must be 32 bytes long. | -`cb` | any | - | -**Returns:** *void* +**Returns:** *Promise‹Buffer›* + +- The storage value for the account +corresponding to the provided address at the provided key. +If this does not exists an empty `Buffer` is returned ___ ### getOriginalContractStorage -▸ **getOriginalContractStorage**(`address`: Buffer, `key`: Buffer, `cb`: any): *void* +▸ **getOriginalContractStorage**(`address`: Buffer, `key`: Buffer): *Promise‹Buffer›* -*Defined in [state/stateManager.ts:242](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L242)* +*Defined in [state/stateManager.ts:202](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L202)* Caches the storage value associated with the provided `address` and `key` on first invocation, and returns the cached (original) value from then @@ -443,56 +432,48 @@ Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address of the account to get the storage for | `key` | Buffer | Key in the account's storage to get the value for. Must be 32 bytes long. | -`cb` | any | - | -**Returns:** *void* +**Returns:** *Promise‹Buffer›* ___ ### getStateRoot -▸ **getStateRoot**(`cb`: any): *void* +▸ **getStateRoot**(): *Promise‹Buffer›* -*Defined in [state/stateManager.ts:415](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L415)* +*Defined in [state/stateManager.ts:362](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L362)* Gets the state-root of the Merkle-Patricia trie representation of the state of this StateManager. Will error if there are uncommitted checkpoints on the instance. -**Parameters:** +**Returns:** *Promise‹Buffer›* -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | | - -**Returns:** *void* +- Returns the state-root of the `StateManager` ___ ### hasGenesisState -▸ **hasGenesisState**(`cb`: any): *void* +▸ **hasGenesisState**(): *Promise‹boolean›* -*Defined in [state/stateManager.ts:508](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L508)* +*Defined in [state/stateManager.ts:431](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L431)* Checks whether the current instance has the canonical genesis state for the configured chain parameters. -**Parameters:** +**Returns:** *Promise‹boolean›* -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | | - -**Returns:** *void* +- Whether the storage trie contains the +canonical genesis state for the configured chain parameters. ___ ### putAccount -▸ **putAccount**(`address`: Buffer, `account`: Account, `cb`: any): *void* +▸ **putAccount**(`address`: Buffer, `account`: Account): *Promise‹void›* -*Defined in [state/stateManager.ts:101](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L101)* +*Defined in [state/stateManager.ts:97](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L97)* Saves an [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) into state under the provided `address`. @@ -502,18 +483,17 @@ into state under the provided `address`. Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address under which to store `account` | -`account` | Account | The [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) to store | -`cb` | any | Callback function | +`account` | Account | The [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) to store | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### putContractCode -▸ **putContractCode**(`address`: Buffer, `value`: Buffer, `cb`: any): *void* +▸ **putContractCode**(`address`: Buffer, `value`: Buffer): *Promise‹void›* -*Defined in [state/stateManager.ts:129](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L129)* +*Defined in [state/stateManager.ts:123](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L123)* Adds `value` to the state trie as code, and sets `codeHash` on the account corresponding to `address` to reference this. @@ -523,18 +503,17 @@ corresponding to `address` to reference this. Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address of the `account` to add the `code` for | -`value` | Buffer | The value of the `code` | -`cb` | any | Callback function | +`value` | Buffer | The value of the `code` | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### putContractStorage -▸ **putContractStorage**(`address`: Buffer, `key`: Buffer, `value`: Buffer, `cb`: any): *void* +▸ **putContractStorage**(`address`: Buffer, `key`: Buffer, `value`: Buffer): *Promise‹void›* -*Defined in [state/stateManager.ts:303](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L303)* +*Defined in [state/stateManager.ts:263](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L263)* Adds value to the state trie for the `account` corresponding to `address` at the provided `key`. @@ -545,37 +524,30 @@ Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address to set a storage value for | `key` | Buffer | Key to set the value at. Must be 32 bytes long. | -`value` | Buffer | Value to set at `key` for account corresponding to `address` | -`cb` | any | Callback function | +`value` | Buffer | Value to set at `key` for account corresponding to `address` | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### revert -▸ **revert**(`cb`: any): *void* +▸ **revert**(): *Promise‹void›* -*Defined in [state/stateManager.ts:377](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L377)* +*Defined in [state/stateManager.ts:331](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L331)* Reverts the current change-set to the instance since the last call to checkpoint. -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### setStateRoot -▸ **setStateRoot**(`stateRoot`: Buffer, `cb`: any): *void* +▸ **setStateRoot**(`stateRoot`: Buffer): *Promise‹void›* -*Defined in [state/stateManager.ts:437](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L437)* +*Defined in [state/stateManager.ts:378](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L378)* Sets the state of the instance to that represented by the provided `stateRoot`. Will error if there are uncommitted @@ -586,10 +558,9 @@ the state trie. Name | Type | Description | ------ | ------ | ------ | -`stateRoot` | Buffer | The state-root to reset the instance to | -`cb` | any | Callback function | +`stateRoot` | Buffer | The state-root to reset the instance to | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ @@ -597,7 +568,7 @@ ___ ▸ **touchAccount**(`address`: Buffer): *void* -*Defined in [state/stateManager.ts:118](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L118)* +*Defined in [state/stateManager.ts:113](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L113)* Marks an account as touched, according to the definition in [EIP-158](https://eips.ethereum.org/EIPS/eip-158). diff --git a/packages/vm/docs/classes/_state_statemanager_.statemanager.md b/packages/vm/docs/classes/_state_statemanager_.statemanager.md index e9989e5d196..64f78f975b7 100644 --- a/packages/vm/docs/classes/_state_statemanager_.statemanager.md +++ b/packages/vm/docs/classes/_state_statemanager_.statemanager.md @@ -59,7 +59,7 @@ state trie. \+ **new StateManager**(`opts`: [StateManagerOpts](../interfaces/_state_statemanager_.statemanageropts.md)): *[StateManager](_state_statemanager_.statemanager.md)* -*Defined in [state/stateManager.ts:46](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L46)* +*Defined in [state/stateManager.ts:51](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L51)* Instantiate the StateManager interface. @@ -77,7 +77,7 @@ Name | Type | Default | • **_cache**: *Cache* -*Defined in [state/stateManager.ts:42](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L42)* +*Defined in [state/stateManager.ts:47](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L47)* ___ @@ -85,7 +85,7 @@ ___ • **_checkpointCount**: *number* -*Defined in [state/stateManager.ts:45](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L45)* +*Defined in [state/stateManager.ts:50](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L50)* ___ @@ -93,7 +93,7 @@ ___ • **_common**: *Common* -*Defined in [state/stateManager.ts:39](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L39)* +*Defined in [state/stateManager.ts:44](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L44)* ___ @@ -101,7 +101,7 @@ ___ • **_originalStorageCache**: *Map‹string, Map‹string, Buffer››* -*Defined in [state/stateManager.ts:46](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L46)* +*Defined in [state/stateManager.ts:51](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L51)* ___ @@ -109,7 +109,7 @@ ___ • **_storageTries**: *any* -*Defined in [state/stateManager.ts:41](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L41)* +*Defined in [state/stateManager.ts:46](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L46)* ___ @@ -117,7 +117,7 @@ ___ • **_touched**: *Set‹string›* -*Defined in [state/stateManager.ts:43](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L43)* +*Defined in [state/stateManager.ts:48](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L48)* ___ @@ -125,23 +125,23 @@ ___ • **_touchedStack**: *Set‹string›[]* -*Defined in [state/stateManager.ts:44](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L44)* +*Defined in [state/stateManager.ts:49](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L49)* ___ ### _trie -• **_trie**: *any* +• **_trie**: *Trie* -*Defined in [state/stateManager.ts:40](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L40)* +*Defined in [state/stateManager.ts:45](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L45)* ## Methods ### `Private` _getStorageTrie -▸ **_getStorageTrie**(`address`: Buffer, `cb`: any): *void* +▸ **_getStorageTrie**(`address`: Buffer): *Promise‹Trie›* -*Defined in [state/stateManager.ts:189](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L189)* +*Defined in [state/stateManager.ts:163](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L163)* Gets the storage trie for an account from the storage cache or does a lookup. @@ -151,17 +151,16 @@ cache or does a lookup. Name | Type | ------ | ------ | `address` | Buffer | -`cb` | any | -**Returns:** *void* +**Returns:** *Promise‹Trie›* ___ ### `Private` _lookupStorageTrie -▸ **_lookupStorageTrie**(`address`: Buffer, `cb`: any): *void* +▸ **_lookupStorageTrie**(`address`: Buffer): *Promise‹Trie›* -*Defined in [state/stateManager.ts:171](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L171)* +*Defined in [state/stateManager.ts:149](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L149)* Creates a storage trie from the primary storage trie for an account and saves this in the storage cache. @@ -171,37 +170,47 @@ for an account and saves this in the storage cache. Name | Type | ------ | ------ | `address` | Buffer | -`cb` | any | -**Returns:** *void* +**Returns:** *Promise‹Trie›* ___ ### `Private` _modifyContractStorage -▸ **_modifyContractStorage**(`address`: Buffer, `modifyTrie`: any, `cb`: any): *void* +▸ **_modifyContractStorage**(`address`: Buffer, `modifyTrie`: function): *Promise‹void›* -*Defined in [state/stateManager.ts:276](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L276)* +*Defined in [state/stateManager.ts:233](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L233)* -Modifies the storage trie of an account +Modifies the storage trie of an account. **Parameters:** -Name | Type | Description | ------- | ------ | ------ | -`address` | Buffer | Address of the account whose storage is to be modified | -`modifyTrie` | any | Function to modify the storage trie of the account | -`cb` | any | - | +▪ **address**: *Buffer* -**Returns:** *void* +Address of the account whose storage is to be modified + +▪ **modifyTrie**: *function* + +Function to modify the storage trie of the account + +▸ (`storageTrie`: Trie, `done`: Function): *void* + +**Parameters:** + +Name | Type | +------ | ------ | +`storageTrie` | Trie | +`done` | Function | + +**Returns:** *Promise‹void›* ___ ### accountIsEmpty -▸ **accountIsEmpty**(`address`: Buffer, `cb`: any): *void* +▸ **accountIsEmpty**(`address`: Buffer): *Promise‹boolean›* -*Defined in [state/stateManager.ts:573](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L573)* +*Defined in [state/stateManager.ts:482](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L482)* Checks if the `account` corresponding to `address` is empty as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161). @@ -210,57 +219,44 @@ EIP-161 (https://eips.ethereum.org/EIPS/eip-161). Name | Type | Description | ------ | ------ | ------ | -`address` | Buffer | Address to check | -`cb` | any | | +`address` | Buffer | Address to check | -**Returns:** *void* +**Returns:** *Promise‹boolean›* ___ ### checkpoint -▸ **checkpoint**(`cb`: any): *void* +▸ **checkpoint**(): *Promise‹void›* -*Defined in [state/stateManager.ts:346](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L346)* +*Defined in [state/stateManager.ts:302](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L302)* Checkpoints the current state of the StateManager instance. State changes that follow can then be committed by calling `commit` or `reverted` by calling rollback. -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### cleanupTouchedAccounts -▸ **cleanupTouchedAccounts**(`cb`: any): *void* +▸ **cleanupTouchedAccounts**(): *Promise‹void›* -*Defined in [state/stateManager.ts:594](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L594)* +*Defined in [state/stateManager.ts:497](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L497)* Removes accounts form the state trie that have been touched, as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161). -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### clearContractStorage -▸ **clearContractStorage**(`address`: Buffer, `cb`: any): *void* +▸ **clearContractStorage**(`address`: Buffer): *Promise‹void›* -*Defined in [state/stateManager.ts:329](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L329)* +*Defined in [state/stateManager.ts:290](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L290)* Clears all storage entries for the account corresponding to `address`. @@ -268,29 +264,22 @@ Clears all storage entries for the account corresponding to `address`. Name | Type | Description | ------ | ------ | ------ | -`address` | Buffer | Address to clear the storage of | -`cb` | any | Callback function | +`address` | Buffer | Address to clear the storage of | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### commit -▸ **commit**(`cb`: any): *void* +▸ **commit**(): *Promise‹void›* -*Defined in [state/stateManager.ts:359](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L359)* +*Defined in [state/stateManager.ts:313](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L313)* Commits the current change-set to the instance since the last call to checkpoint. -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ @@ -298,7 +287,7 @@ ___ ▸ **copy**(): *[StateManager](_state_index_.statemanager.md)* -*Defined in [state/stateManager.ts:72](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L72)* +*Defined in [state/stateManager.ts:77](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L77)* Copies the current instance of the `StateManager` at the last fully committed point, i.e. as if all current @@ -310,9 +299,9 @@ ___ ### dumpStorage -▸ **dumpStorage**(`address`: Buffer, `cb`: any): *void* +▸ **dumpStorage**(`address`: Buffer): *Promise‹[StorageDump](../interfaces/_state_statemanager_.storagedump.md)›* -*Defined in [state/stateManager.ts:479](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L479)* +*Defined in [state/stateManager.ts:410](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L410)* Dumps the the storage values for an `account` specified by `address`. @@ -321,37 +310,34 @@ Dumps the the storage values for an `account` specified by `address`. Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | The address of the `account` to return storage for | -`cb` | any | | -**Returns:** *void* +**Returns:** *Promise‹[StorageDump](../interfaces/_state_statemanager_.storagedump.md)›* + +- The state of the account as an `Object` map. +Keys are are the storage keys, values are the storage values as strings. +Both are represented as hex strings without the `0x` prefix. ___ ### generateCanonicalGenesis -▸ **generateCanonicalGenesis**(`cb`: any): *void* +▸ **generateCanonicalGenesis**(): *Promise‹void›* -*Defined in [state/stateManager.ts:519](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L519)* +*Defined in [state/stateManager.ts:442](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L442)* Generates a canonical genesis state on the instance based on the configured chain parameters. Will error if there are uncommitted checkpoints on the instance. -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### generateGenesis -▸ **generateGenesis**(`initState`: any, `cb`: any): *any* +▸ **generateGenesis**(`initState`: any): *Promise‹void›* -*Defined in [state/stateManager.ts:538](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L538)* +*Defined in [state/stateManager.ts:457](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L457)* Initializes the provided genesis state into the state trie @@ -359,18 +345,17 @@ Initializes the provided genesis state into the state trie Name | Type | Description | ------ | ------ | ------ | -`initState` | any | Object (address -> balance) | -`cb` | any | Callback function | +`initState` | any | Object (address -> balance) | -**Returns:** *any* +**Returns:** *Promise‹void›* ___ ### getAccount -▸ **getAccount**(`address`: Buffer, `cb`: any): *void* +▸ **getAccount**(`address`: Buffer): *Promise‹Account›* -*Defined in [state/stateManager.ts:90](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L90)* +*Defined in [state/stateManager.ts:86](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L86)* Gets the [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) associated with `address`. Returns an empty account if the account does not exist. @@ -379,18 +364,17 @@ associated with `address`. Returns an empty account if the account does not exis Name | Type | Description | ------ | ------ | ------ | -`address` | Buffer | Address of the `account` to get | -`cb` | any | | +`address` | Buffer | Address of the `account` to get | -**Returns:** *void* +**Returns:** *Promise‹Account›* ___ ### getContractCode -▸ **getContractCode**(`address`: Buffer, `cb`: any): *void* +▸ **getContractCode**(`address`: Buffer): *Promise‹Buffer›* -*Defined in [state/stateManager.ts:157](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L157)* +*Defined in [state/stateManager.ts:137](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L137)* Gets the code corresponding to the provided `address`. @@ -399,17 +383,19 @@ Gets the code corresponding to the provided `address`. Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address to get the `code` for | -`cb` | any | | -**Returns:** *void* +**Returns:** *Promise‹Buffer›* + +- Resolves with the code corresponding to the provided address. +Returns an empty `Buffer` if the account has no associated code. ___ ### getContractStorage -▸ **getContractStorage**(`address`: Buffer, `key`: Buffer, `cb`: any): *void* +▸ **getContractStorage**(`address`: Buffer, `key`: Buffer): *Promise‹Buffer›* -*Defined in [state/stateManager.ts:215](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L215)* +*Defined in [state/stateManager.ts:182](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L182)* Gets the storage value associated with the provided `address` and `key`. This method returns the shortest representation of the stored value. @@ -420,17 +406,20 @@ Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address of the account to get the storage for | `key` | Buffer | Key in the account's storage to get the value for. Must be 32 bytes long. | -`cb` | any | - | -**Returns:** *void* +**Returns:** *Promise‹Buffer›* + +- The storage value for the account +corresponding to the provided address at the provided key. +If this does not exists an empty `Buffer` is returned ___ ### getOriginalContractStorage -▸ **getOriginalContractStorage**(`address`: Buffer, `key`: Buffer, `cb`: any): *void* +▸ **getOriginalContractStorage**(`address`: Buffer, `key`: Buffer): *Promise‹Buffer›* -*Defined in [state/stateManager.ts:242](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L242)* +*Defined in [state/stateManager.ts:202](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L202)* Caches the storage value associated with the provided `address` and `key` on first invocation, and returns the cached (original) value from then @@ -443,56 +432,48 @@ Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address of the account to get the storage for | `key` | Buffer | Key in the account's storage to get the value for. Must be 32 bytes long. | -`cb` | any | - | -**Returns:** *void* +**Returns:** *Promise‹Buffer›* ___ ### getStateRoot -▸ **getStateRoot**(`cb`: any): *void* +▸ **getStateRoot**(): *Promise‹Buffer›* -*Defined in [state/stateManager.ts:415](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L415)* +*Defined in [state/stateManager.ts:362](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L362)* Gets the state-root of the Merkle-Patricia trie representation of the state of this StateManager. Will error if there are uncommitted checkpoints on the instance. -**Parameters:** +**Returns:** *Promise‹Buffer›* -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | | - -**Returns:** *void* +- Returns the state-root of the `StateManager` ___ ### hasGenesisState -▸ **hasGenesisState**(`cb`: any): *void* +▸ **hasGenesisState**(): *Promise‹boolean›* -*Defined in [state/stateManager.ts:508](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L508)* +*Defined in [state/stateManager.ts:431](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L431)* Checks whether the current instance has the canonical genesis state for the configured chain parameters. -**Parameters:** +**Returns:** *Promise‹boolean›* -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | | - -**Returns:** *void* +- Whether the storage trie contains the +canonical genesis state for the configured chain parameters. ___ ### putAccount -▸ **putAccount**(`address`: Buffer, `account`: Account, `cb`: any): *void* +▸ **putAccount**(`address`: Buffer, `account`: Account): *Promise‹void›* -*Defined in [state/stateManager.ts:101](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L101)* +*Defined in [state/stateManager.ts:97](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L97)* Saves an [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) into state under the provided `address`. @@ -502,18 +483,17 @@ into state under the provided `address`. Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address under which to store `account` | -`account` | Account | The [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) to store | -`cb` | any | Callback function | +`account` | Account | The [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) to store | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### putContractCode -▸ **putContractCode**(`address`: Buffer, `value`: Buffer, `cb`: any): *void* +▸ **putContractCode**(`address`: Buffer, `value`: Buffer): *Promise‹void›* -*Defined in [state/stateManager.ts:129](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L129)* +*Defined in [state/stateManager.ts:123](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L123)* Adds `value` to the state trie as code, and sets `codeHash` on the account corresponding to `address` to reference this. @@ -523,18 +503,17 @@ corresponding to `address` to reference this. Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address of the `account` to add the `code` for | -`value` | Buffer | The value of the `code` | -`cb` | any | Callback function | +`value` | Buffer | The value of the `code` | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### putContractStorage -▸ **putContractStorage**(`address`: Buffer, `key`: Buffer, `value`: Buffer, `cb`: any): *void* +▸ **putContractStorage**(`address`: Buffer, `key`: Buffer, `value`: Buffer): *Promise‹void›* -*Defined in [state/stateManager.ts:303](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L303)* +*Defined in [state/stateManager.ts:263](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L263)* Adds value to the state trie for the `account` corresponding to `address` at the provided `key`. @@ -545,37 +524,30 @@ Name | Type | Description | ------ | ------ | ------ | `address` | Buffer | Address to set a storage value for | `key` | Buffer | Key to set the value at. Must be 32 bytes long. | -`value` | Buffer | Value to set at `key` for account corresponding to `address` | -`cb` | any | Callback function | +`value` | Buffer | Value to set at `key` for account corresponding to `address` | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### revert -▸ **revert**(`cb`: any): *void* +▸ **revert**(): *Promise‹void›* -*Defined in [state/stateManager.ts:377](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L377)* +*Defined in [state/stateManager.ts:331](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L331)* Reverts the current change-set to the instance since the last call to checkpoint. -**Parameters:** - -Name | Type | Description | ------- | ------ | ------ | -`cb` | any | Callback function | - -**Returns:** *void* +**Returns:** *Promise‹void›* ___ ### setStateRoot -▸ **setStateRoot**(`stateRoot`: Buffer, `cb`: any): *void* +▸ **setStateRoot**(`stateRoot`: Buffer): *Promise‹void›* -*Defined in [state/stateManager.ts:437](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L437)* +*Defined in [state/stateManager.ts:378](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L378)* Sets the state of the instance to that represented by the provided `stateRoot`. Will error if there are uncommitted @@ -586,10 +558,9 @@ the state trie. Name | Type | Description | ------ | ------ | ------ | -`stateRoot` | Buffer | The state-root to reset the instance to | -`cb` | any | Callback function | +`stateRoot` | Buffer | The state-root to reset the instance to | -**Returns:** *void* +**Returns:** *Promise‹void›* ___ @@ -597,7 +568,7 @@ ___ ▸ **touchAccount**(`address`: Buffer): *void* -*Defined in [state/stateManager.ts:118](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L118)* +*Defined in [state/stateManager.ts:113](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L113)* Marks an account as touched, according to the definition in [EIP-158](https://eips.ethereum.org/EIPS/eip-158). diff --git a/packages/vm/docs/enums/_exceptions_.error.md b/packages/vm/docs/enums/_exceptions_.error.md index a0e1c43a9e4..df88acdc2c3 100644 --- a/packages/vm/docs/enums/_exceptions_.error.md +++ b/packages/vm/docs/enums/_exceptions_.error.md @@ -18,6 +18,7 @@ * [STACK_UNDERFLOW](_exceptions_.error.md#stack_underflow) * [STATIC_STATE_CHANGE](_exceptions_.error.md#static_state_change) * [STOP](_exceptions_.error.md#stop) +* [VALUE_OVERFLOW](_exceptions_.error.md#value_overflow) ## Enumeration members @@ -114,3 +115,11 @@ ___ • **STOP**: = "stop" *Defined in [exceptions.ts:12](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/exceptions.ts#L12)* + +___ + +### VALUE_OVERFLOW + +• **VALUE_OVERFLOW**: = "value overflow" + +*Defined in [exceptions.ts:14](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/exceptions.ts#L14)* diff --git a/packages/vm/docs/interfaces/_index_.vmopts.md b/packages/vm/docs/interfaces/_index_.vmopts.md index f4a270a10e4..bb489f11b32 100644 --- a/packages/vm/docs/interfaces/_index_.vmopts.md +++ b/packages/vm/docs/interfaces/_index_.vmopts.md @@ -27,7 +27,7 @@ Options for instantiating a [VM](../classes/_index_.vm.md). • **activatePrecompiles**? : *undefined | false | true* -*Defined in [index.ts:53](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L53)* +*Defined in [index.ts:52](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L52)* If true, create entries in the state tree for the precompiled contracts, saving some gas the first time each of them is called. @@ -44,7 +44,7 @@ ___ • **allowUnlimitedContractSize**? : *undefined | false | true* -*Defined in [index.ts:57](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L57)* +*Defined in [index.ts:56](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L56)* Allows unlimited contract sizes while debugging. By setting this to `true`, the check for contract size limit of 24KB (see [EIP-170](https://git.io/vxZkK)) is bypassed @@ -54,7 +54,7 @@ ___ • **blockchain**? : *Blockchain* -*Defined in [index.ts:42](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L42)* +*Defined in [index.ts:41](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L41)* A [blockchain](https://github.com/ethereumjs/ethereumjs-blockchain) object for storing/retrieving blocks @@ -64,7 +64,7 @@ ___ • **chain**? : *undefined | string* -*Defined in [index.ts:25](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L25)* +*Defined in [index.ts:24](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L24)* The chain the VM operates on @@ -74,7 +74,7 @@ ___ • **common**? : *Common* -*Defined in [index.ts:58](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L58)* +*Defined in [index.ts:57](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L57)* ___ @@ -82,7 +82,7 @@ ___ • **hardfork**? : *undefined | string* -*Defined in [index.ts:29](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L29)* +*Defined in [index.ts:28](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L28)* Hardfork rules to be used @@ -92,7 +92,7 @@ ___ • **state**? : *any* -*Defined in [index.ts:38](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L38)* +*Defined in [index.ts:37](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L37)* A [merkle-patricia-tree](https://github.com/ethereumjs/merkle-patricia-tree) instance for the state tree (ignored if stateManager is passed) @@ -104,6 +104,6 @@ ___ • **stateManager**? : *[StateManager](../classes/_state_index_.statemanager.md)* -*Defined in [index.ts:33](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L33)* +*Defined in [index.ts:32](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/index.ts#L32)* A [StateManager](../classes/_state_index_.statemanager.md) instance to use as the state store (Beta API) diff --git a/packages/vm/docs/interfaces/_runtx_.runtxopts.md b/packages/vm/docs/interfaces/_runtx_.runtxopts.md index d2f405791fd..7d68753ef14 100644 --- a/packages/vm/docs/interfaces/_runtx_.runtxopts.md +++ b/packages/vm/docs/interfaces/_runtx_.runtxopts.md @@ -23,7 +23,7 @@ Options for the `runTx` method. • **block**? : *any* -*Defined in [runTx.ts:20](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L20)* +*Defined in [runTx.ts:19](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L19)* The block to which the `tx` belongs @@ -33,7 +33,7 @@ ___ • **skipBalance**? : *undefined | false | true* -*Defined in [runTx.ts:32](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L32)* +*Defined in [runTx.ts:31](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L31)* If true, skips the balance check @@ -43,7 +43,7 @@ ___ • **skipNonce**? : *undefined | false | true* -*Defined in [runTx.ts:28](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L28)* +*Defined in [runTx.ts:27](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L27)* If true, skips the nonce check @@ -53,6 +53,6 @@ ___ • **tx**: *Transaction* -*Defined in [runTx.ts:24](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L24)* +*Defined in [runTx.ts:23](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L23)* A [`Transaction`](https://github.com/ethereum/ethereumjs-tx) to run diff --git a/packages/vm/docs/interfaces/_runtx_.runtxresult.md b/packages/vm/docs/interfaces/_runtx_.runtxresult.md index dcc17584861..1e0cee21960 100644 --- a/packages/vm/docs/interfaces/_runtx_.runtxresult.md +++ b/packages/vm/docs/interfaces/_runtx_.runtxresult.md @@ -27,7 +27,7 @@ Execution result of a transaction • **amountSpent**: *BN* -*Defined in [runTx.ts:46](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L46)* +*Defined in [runTx.ts:45](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L45)* The amount of ether used by this transaction @@ -37,7 +37,7 @@ ___ • **bloom**: *Bloom* -*Defined in [runTx.ts:42](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L42)* +*Defined in [runTx.ts:41](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L41)* Bloom filter resulted from transaction @@ -71,7 +71,7 @@ ___ • **gasRefund**? : *BN* -*Defined in [runTx.ts:50](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L50)* +*Defined in [runTx.ts:49](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/runTx.ts#L49)* The amount of gas as that was refunded during the transaction (i.e. `gasUsed = totalGasConsumed - gasRefund`) diff --git a/packages/vm/docs/interfaces/_state_statemanager_.statemanageropts.md b/packages/vm/docs/interfaces/_state_statemanager_.statemanageropts.md index e24dfdbbba8..f540276587d 100644 --- a/packages/vm/docs/interfaces/_state_statemanager_.statemanageropts.md +++ b/packages/vm/docs/interfaces/_state_statemanager_.statemanageropts.md @@ -21,7 +21,7 @@ Options for constructing a [StateManager](../classes/_state_statemanager_.statem • **common**? : *Common* -*Defined in [state/stateManager.ts:27](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L27)* +*Defined in [state/stateManager.ts:32](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L32)* Parameters of the chain ([`Common`](https://github.com/ethereumjs/ethereumjs-common)) @@ -29,8 +29,8 @@ ___ ### `Optional` trie -• **trie**? : *any* +• **trie**? : *Trie* -*Defined in [state/stateManager.ts:31](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L31)* +*Defined in [state/stateManager.ts:36](https://github.com/ethereumjs/ethereumjs-vm/blob/master/packages/vm/lib/state/stateManager.ts#L36)* A [`merkle-patricia-tree`](https://github.com/ethereumjs/merkle-patricia-tree) instance diff --git a/packages/vm/examples/run-blockchain/index.ts b/packages/vm/examples/run-blockchain/index.ts index 61185c7c588..c5c17061a1e 100644 --- a/packages/vm/examples/run-blockchain/index.ts +++ b/packages/vm/examples/run-blockchain/index.ts @@ -2,14 +2,13 @@ import VM from '../../' import Account from 'ethereumjs-account' import Blockchain from 'ethereumjs-blockchain' -import * as utils from 'ethereumjs-util' -import { promisify } from 'util' -import PStateManager from '../../lib/state/promisified' +import { toBuffer, setLength } from 'ethereumjs-util' const Block = require('ethereumjs-block') const BlockHeader = require('ethereumjs-block/header.js') const testData = require('./test-data') const level = require('level') +const { promisify } = require('util') async function main() { const hardfork = testData.network.toLowerCase() @@ -39,7 +38,7 @@ async function main() { await vm.runBlockchain(blockchain) - const blockchainHead = await promisify(vm.blockchain.getHead.bind(vm.blockchain))() + const blockchainHead = await promisify(vm.blockchain.getHead.bind(vm.blockchain))() console.log('--- Finished processing the BlockChain ---') console.log('New head:', '0x' + blockchainHead.hash().toString('hex')) @@ -53,12 +52,10 @@ function setEthashCache(blockchain: any) { } async function setupPreConditions(vm: VM, testData: any) { - const psm = new PStateManager(vm.stateManager) - - await psm.checkpoint() + await vm.stateManager.checkpoint() for (const address of Object.keys(testData.pre)) { - const addressBuf = utils.toBuffer(address) + const addressBuf = toBuffer(address) const acctData = testData.pre[address] const account = new Account({ @@ -66,21 +63,21 @@ async function setupPreConditions(vm: VM, testData: any) { balance: acctData.balance, }) - await psm.putAccount(addressBuf, account) + await vm.stateManager.putAccount(addressBuf, account) for (const hexStorageKey of Object.keys(acctData.storage)) { - const val = utils.toBuffer(acctData.storage[hexStorageKey]) - const storageKey = utils.setLength(utils.toBuffer(hexStorageKey), 32) + const val = toBuffer(acctData.storage[hexStorageKey]) + const storageKey = setLength(toBuffer(hexStorageKey), 32) - await psm.putContractStorage(addressBuf, storageKey, val) + await vm.stateManager.putContractStorage(addressBuf, storageKey, val) } - const codeBuf = utils.toBuffer(acctData.code) + const codeBuf = toBuffer(acctData.code) - await psm.putContractCode(addressBuf, codeBuf) + await vm.stateManager.putContractCode(addressBuf, codeBuf) } - await psm.commit() + await vm.stateManager.commit() } async function setGenesisBlock(blockchain: any, hardfork: string) { @@ -92,14 +89,14 @@ async function setGenesisBlock(blockchain: any, hardfork: string) { async function putBlocks(blockchain: any, hardfork: string, testData: any) { for (const blockData of testData.blocks) { - const block = new Block(utils.toBuffer(blockData.rlp), { hardfork }) + const block = new Block(toBuffer(blockData.rlp), { hardfork }) await promisify(blockchain.putBlock.bind(blockchain))(block) } } main() .then(() => process.exit(0)) - .catch(err => { + .catch((err) => { console.error(err) process.exit(1) }) diff --git a/packages/vm/examples/run-solidity-contract/index.ts b/packages/vm/examples/run-solidity-contract/index.ts index c6a22cbdb87..90614aa44f0 100644 --- a/packages/vm/examples/run-solidity-contract/index.ts +++ b/packages/vm/examples/run-solidity-contract/index.ts @@ -3,12 +3,12 @@ import VM from '../../dist' import * as assert from 'assert' import * as path from 'path' import * as fs from 'fs' -import { promisify } from 'util' import * as util from 'ethereumjs-util' import Account from 'ethereumjs-account' import { Transaction } from 'ethereumjs-tx' const abi = require('ethereumjs-abi') const solc = require('solc') +const { promisify } = require('util') const INITIAL_GREETING = 'Hello, World!' const SECOND_GREETING = 'Hola, Mundo!' @@ -157,7 +157,7 @@ async function getGreeting(vm: VM, contractAddress: Buffer, caller: Buffer) { } async function main() { - const accountPk = new Buffer( + const accountPk = Buffer.from( 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex', ) @@ -211,7 +211,7 @@ async function main() { main() .then(() => process.exit(0)) - .catch(err => { + .catch((err) => { console.error(err) process.exit(1) }) diff --git a/packages/vm/examples/run-transactions-complete/index.ts b/packages/vm/examples/run-transactions-complete/index.ts index c456ad4e813..fb643bf960d 100644 --- a/packages/vm/examples/run-transactions-complete/index.ts +++ b/packages/vm/examples/run-transactions-complete/index.ts @@ -1,12 +1,10 @@ import VM from '../..' import Account from 'ethereumjs-account' import * as utils from 'ethereumjs-util' -import PStateManager from '../../lib/state/promisified' import { Transaction } from 'ethereumjs-tx' async function main() { const vm = new VM() - const psm = new PStateManager(vm.stateManager) // import the key pair // used to sign transactions and generate addresses @@ -25,7 +23,7 @@ async function main() { }) // Save the account - await psm.putAccount(address, account) + await vm.stateManager.putAccount(address, account) const rawTx1 = require('./raw-tx1') const rawTx2 = require('./raw-tx2') @@ -40,7 +38,7 @@ async function main() { // should have created a new account for the contract // in the state. Lets test to see if it did. - const createdAccount = await psm.getAccount(createdAddress) + const createdAccount = await vm.stateManager.getAccount(createdAddress) console.log('-------results-------') console.log('nonce: ' + createdAccount.nonce.toString('hex')) @@ -73,7 +71,7 @@ async function runTx(vm: VM, rawTx: any, privateKey: Buffer) { main() .then(() => process.exit(0)) - .catch(error => { + .catch((error) => { console.error(error) process.exit(1) }) diff --git a/packages/vm/lib/evm/eei.ts b/packages/vm/lib/evm/eei.ts index 3ddf31f4553..41cb5cef163 100644 --- a/packages/vm/lib/evm/eei.ts +++ b/packages/vm/lib/evm/eei.ts @@ -3,11 +3,11 @@ import { toBuffer } from 'ethereumjs-util' import Account from 'ethereumjs-account' import Blockchain from 'ethereumjs-blockchain' import Common from 'ethereumjs-common' -import PStateManager from '../state/promisified' +import { StateManager } from '../state/index' import { VmError, ERROR } from '../exceptions' import Message from './message' import EVM, { EVMResult } from './evm' -const promisify = require('util.promisify') +const { promisify } = require('util') /** * Environment data which is made available to EVM bytecode. @@ -52,13 +52,13 @@ export interface RunResult { export default class EEI { _env: Env _result: RunResult - _state: PStateManager + _state: StateManager _evm: EVM _lastReturned: Buffer _common: Common _gasLeft: BN - constructor(env: Env, state: PStateManager, evm: EVM, common: Common, gasLeft: BN) { + constructor(env: Env, state: StateManager, evm: EVM, common: Common, gasLeft: BN) { this._env = env this._state = state this._evm = evm diff --git a/packages/vm/lib/evm/evm.ts b/packages/vm/lib/evm/evm.ts index 1695bfc593e..9343b76cf91 100644 --- a/packages/vm/lib/evm/evm.ts +++ b/packages/vm/lib/evm/evm.ts @@ -9,7 +9,7 @@ import { } from 'ethereumjs-util' import Account from 'ethereumjs-account' import { ERROR, VmError } from '../exceptions' -import PStateManager from '../state/promisified' +import { StateManager } from '../state/index' import { getPrecompile, PrecompileFunc, ripemdPrecompileAddress } from './precompiles' import TxContext from './txContext' import Message from './message' @@ -93,7 +93,7 @@ export function OOGResult(gasLimit: BN): ExecResult { */ export default class EVM { _vm: any - _state: PStateManager + _state: StateManager _tx: TxContext _block: any /** @@ -103,7 +103,7 @@ export default class EVM { constructor(vm: any, txContext: TxContext, block: any) { this._vm = vm - this._state = this._vm.pStateManager + this._state = this._vm.stateManager this._tx = txContext this._block = block this._refund = new BN(0) diff --git a/packages/vm/lib/evm/interpreter.ts b/packages/vm/lib/evm/interpreter.ts index cec8d407c7a..676c30d6ce9 100644 --- a/packages/vm/lib/evm/interpreter.ts +++ b/packages/vm/lib/evm/interpreter.ts @@ -1,7 +1,6 @@ import BN = require('bn.js') import Common from 'ethereumjs-common' -import { StateManager } from '../state' -import PStateManager from '../state/promisified' +import { StateManager } from '../state/index' import { ERROR, VmError } from '../exceptions' import Memory from './memory' import Stack from './stack' @@ -52,13 +51,13 @@ export interface InterpreterStep { */ export default class Interpreter { _vm: any - _state: PStateManager + _state: StateManager _runState: RunState _eei: EEI constructor(vm: any, eei: EEI) { this._vm = vm // TODO: remove when not needed - this._state = vm.pStateManager + this._state = vm.stateManager this._eei = eei this._runState = { programCounter: 0, @@ -71,7 +70,7 @@ export default class Interpreter { validJumps: [], // TODO: Replace with EEI methods _common: this._vm._common, - stateManager: this._state._wrapped, + stateManager: this._state, eei: this._eei, } } diff --git a/packages/vm/lib/evm/opFns.ts b/packages/vm/lib/evm/opFns.ts index 2458d4d9c32..f2d966e5b72 100644 --- a/packages/vm/lib/evm/opFns.ts +++ b/packages/vm/lib/evm/opFns.ts @@ -33,25 +33,25 @@ export type OpHandler = SyncOpHandler | AsyncOpHandler // the opcode functions export const handlers: { [k: string]: OpHandler } = { - STOP: function(runState: RunState) { + STOP: function (runState: RunState) { trap(ERROR.STOP) }, - ADD: function(runState: RunState) { + ADD: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = a.add(b).mod(utils.TWO_POW256) runState.stack.push(r) }, - MUL: function(runState: RunState) { + MUL: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = a.mul(b).mod(utils.TWO_POW256) runState.stack.push(r) }, - SUB: function(runState: RunState) { + SUB: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = a.sub(b).toTwos(256) runState.stack.push(r) }, - DIV: function(runState: RunState) { + DIV: function (runState: RunState) { const [a, b] = runState.stack.popN(2) let r if (b.isZero()) { @@ -61,7 +61,7 @@ export const handlers: { [k: string]: OpHandler } = { } runState.stack.push(r) }, - SDIV: function(runState: RunState) { + SDIV: function (runState: RunState) { let [a, b] = runState.stack.popN(2) let r if (b.isZero()) { @@ -73,7 +73,7 @@ export const handlers: { [k: string]: OpHandler } = { } runState.stack.push(r) }, - MOD: function(runState: RunState) { + MOD: function (runState: RunState) { const [a, b] = runState.stack.popN(2) let r if (b.isZero()) { @@ -83,7 +83,7 @@ export const handlers: { [k: string]: OpHandler } = { } runState.stack.push(r) }, - SMOD: function(runState: RunState) { + SMOD: function (runState: RunState) { let [a, b] = runState.stack.popN(2) let r if (b.isZero()) { @@ -99,7 +99,7 @@ export const handlers: { [k: string]: OpHandler } = { } runState.stack.push(r) }, - ADDMOD: function(runState: RunState) { + ADDMOD: function (runState: RunState) { const [a, b, c] = runState.stack.popN(3) let r if (c.isZero()) { @@ -109,7 +109,7 @@ export const handlers: { [k: string]: OpHandler } = { } runState.stack.push(r) }, - MULMOD: function(runState: RunState) { + MULMOD: function (runState: RunState) { const [a, b, c] = runState.stack.popN(3) let r if (c.isZero()) { @@ -119,7 +119,7 @@ export const handlers: { [k: string]: OpHandler } = { } runState.stack.push(r) }, - EXP: function(runState: RunState) { + EXP: function (runState: RunState) { let [base, exponent] = runState.stack.popN(2) if (exponent.isZero()) { runState.stack.push(new BN(1)) @@ -142,13 +142,10 @@ export const handlers: { [k: string]: OpHandler } = { const r = redBase.redPow(exponent) runState.stack.push(r.fromRed()) }, - SIGNEXTEND: function(runState: RunState) { + SIGNEXTEND: function (runState: RunState) { let [k, val] = runState.stack.popN(2) if (k.ltn(31)) { - const signBit = k - .muln(8) - .iaddn(7) - .toNumber() + const signBit = k.muln(8).iaddn(7).toNumber() const mask = new BN(1).ishln(signBit).isubn(1) if (val.testn(signBit)) { val = val.or(mask.notn(256)) @@ -162,57 +159,57 @@ export const handlers: { [k: string]: OpHandler } = { runState.stack.push(val) }, // 0x10 range - bit ops - LT: function(runState: RunState) { + LT: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = new BN(a.lt(b) ? 1 : 0) runState.stack.push(r) }, - GT: function(runState: RunState) { + GT: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = new BN(a.gt(b) ? 1 : 0) runState.stack.push(r) }, - SLT: function(runState: RunState) { + SLT: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = new BN(a.fromTwos(256).lt(b.fromTwos(256)) ? 1 : 0) runState.stack.push(r) }, - SGT: function(runState: RunState) { + SGT: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = new BN(a.fromTwos(256).gt(b.fromTwos(256)) ? 1 : 0) runState.stack.push(r) }, - EQ: function(runState: RunState) { + EQ: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = new BN(a.eq(b) ? 1 : 0) runState.stack.push(r) }, - ISZERO: function(runState: RunState) { + ISZERO: function (runState: RunState) { const a = runState.stack.pop() const r = new BN(a.isZero() ? 1 : 0) runState.stack.push(r) }, - AND: function(runState: RunState) { + AND: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = a.and(b) runState.stack.push(r) }, - OR: function(runState: RunState) { + OR: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = a.or(b) runState.stack.push(r) }, - XOR: function(runState: RunState) { + XOR: function (runState: RunState) { const [a, b] = runState.stack.popN(2) const r = a.xor(b) runState.stack.push(r) }, - NOT: function(runState: RunState) { + NOT: function (runState: RunState) { const a = runState.stack.pop() const r = a.notn(256) runState.stack.push(r) }, - BYTE: function(runState: RunState) { + BYTE: function (runState: RunState) { const [pos, word] = runState.stack.popN(2) if (pos.gten(32)) { runState.stack.push(new BN(0)) @@ -222,7 +219,7 @@ export const handlers: { [k: string]: OpHandler } = { const r = new BN(word.shrn((31 - pos.toNumber()) * 8).andln(0xff)) runState.stack.push(r) }, - SHL: function(runState: RunState) { + SHL: function (runState: RunState) { const [a, b] = runState.stack.popN(2) if (!runState._common.gteHardfork('constantinople')) { trap(ERROR.INVALID_OPCODE) @@ -235,7 +232,7 @@ export const handlers: { [k: string]: OpHandler } = { const r = b.shln(a.toNumber()).iand(utils.MAX_INTEGER) runState.stack.push(r) }, - SHR: function(runState: RunState) { + SHR: function (runState: RunState) { const [a, b] = runState.stack.popN(2) if (!runState._common.gteHardfork('constantinople')) { trap(ERROR.INVALID_OPCODE) @@ -248,7 +245,7 @@ export const handlers: { [k: string]: OpHandler } = { const r = b.shrn(a.toNumber()) runState.stack.push(r) }, - SAR: function(runState: RunState) { + SAR: function (runState: RunState) { const [a, b] = runState.stack.popN(2) if (!runState._common.gteHardfork('constantinople')) { trap(ERROR.INVALID_OPCODE) @@ -277,7 +274,7 @@ export const handlers: { [k: string]: OpHandler } = { runState.stack.push(r) }, // 0x20 range - crypto - SHA3: function(runState: RunState) { + SHA3: function (runState: RunState) { const [offset, length] = runState.stack.popN(2) subMemUsage(runState, offset, length) let data = Buffer.alloc(0) @@ -292,25 +289,25 @@ export const handlers: { [k: string]: OpHandler } = { runState.stack.push(r) }, // 0x30 range - closure state - ADDRESS: function(runState: RunState) { + ADDRESS: function (runState: RunState) { runState.stack.push(new BN(runState.eei.getAddress())) }, - BALANCE: async function(runState: RunState) { + BALANCE: async function (runState: RunState) { const address = runState.stack.pop() const addressBuf = addressToBuffer(address) const balance = await runState.eei.getExternalBalance(addressBuf) runState.stack.push(balance) }, - ORIGIN: function(runState: RunState) { + ORIGIN: function (runState: RunState) { runState.stack.push(runState.eei.getTxOrigin()) }, - CALLER: function(runState: RunState) { + CALLER: function (runState: RunState) { runState.stack.push(runState.eei.getCaller()) }, - CALLVALUE: function(runState: RunState) { + CALLVALUE: function (runState: RunState) { runState.stack.push(runState.eei.getCallValue()) }, - CALLDATALOAD: function(runState: RunState) { + CALLDATALOAD: function (runState: RunState) { let pos = runState.stack.pop() if (pos.gt(runState.eei.getCallDataSize())) { runState.stack.push(new BN(0)) @@ -324,11 +321,11 @@ export const handlers: { [k: string]: OpHandler } = { runState.stack.push(r) }, - CALLDATASIZE: function(runState: RunState) { + CALLDATASIZE: function (runState: RunState) { const r = runState.eei.getCallDataSize() runState.stack.push(r) }, - CALLDATACOPY: function(runState: RunState) { + CALLDATACOPY: function (runState: RunState) { let [memOffset, dataOffset, dataLength] = runState.stack.popN(3) subMemUsage(runState, memOffset, dataLength) @@ -342,10 +339,10 @@ export const handlers: { [k: string]: OpHandler } = { runState.memory.extend(memOffsetNum, dataLengthNum) runState.memory.write(memOffsetNum, dataLengthNum, data) }, - CODESIZE: function(runState: RunState) { + CODESIZE: function (runState: RunState) { runState.stack.push(runState.eei.getCodeSize()) }, - CODECOPY: function(runState: RunState) { + CODECOPY: function (runState: RunState) { let [memOffset, codeOffset, length] = runState.stack.popN(3) subMemUsage(runState, memOffset, length) @@ -359,12 +356,12 @@ export const handlers: { [k: string]: OpHandler } = { runState.memory.extend(memOffsetNum, lengthNum) runState.memory.write(memOffsetNum, lengthNum, data) }, - EXTCODESIZE: async function(runState: RunState) { + EXTCODESIZE: async function (runState: RunState) { const address = runState.stack.pop() const size = await runState.eei.getExternalCodeSize(address) runState.stack.push(size) }, - EXTCODECOPY: async function(runState: RunState) { + EXTCODECOPY: async function (runState: RunState) { let [address, memOffset, codeOffset, length] = runState.stack.popN(4) // FIXME: for some reason this must come before subGas @@ -382,7 +379,7 @@ export const handlers: { [k: string]: OpHandler } = { runState.memory.extend(memOffsetNum, lengthNum) runState.memory.write(memOffsetNum, lengthNum, data) }, - EXTCODEHASH: async function(runState: RunState) { + EXTCODEHASH: async function (runState: RunState) { let address = runState.stack.pop() if (!runState._common.gteHardfork('constantinople')) { trap(ERROR.INVALID_OPCODE) @@ -403,10 +400,10 @@ export const handlers: { [k: string]: OpHandler } = { runState.stack.push(new BN(utils.keccak256(code))) }, - RETURNDATASIZE: function(runState: RunState) { + RETURNDATASIZE: function (runState: RunState) { runState.stack.push(runState.eei.getReturnDataSize()) }, - RETURNDATACOPY: function(runState: RunState) { + RETURNDATACOPY: function (runState: RunState) { let [memOffset, returnDataOffset, length] = runState.stack.popN(3) if (returnDataOffset.add(length).gt(runState.eei.getReturnDataSize())) { @@ -424,11 +421,11 @@ export const handlers: { [k: string]: OpHandler } = { runState.memory.extend(memOffsetNum, lengthNum) runState.memory.write(memOffsetNum, lengthNum, data) }, - GASPRICE: function(runState: RunState) { + GASPRICE: function (runState: RunState) { runState.stack.push(runState.eei.getTxGasPrice()) }, // '0x40' range - block operations - BLOCKHASH: async function(runState: RunState) { + BLOCKHASH: async function (runState: RunState) { const number = runState.stack.pop() const diff = runState.eei.getBlockNumber().sub(number) @@ -441,29 +438,29 @@ export const handlers: { [k: string]: OpHandler } = { const hash = await runState.eei.getBlockHash(number) runState.stack.push(hash) }, - COINBASE: function(runState: RunState) { + COINBASE: function (runState: RunState) { runState.stack.push(runState.eei.getBlockCoinbase()) }, - TIMESTAMP: function(runState: RunState) { + TIMESTAMP: function (runState: RunState) { runState.stack.push(runState.eei.getBlockTimestamp()) }, - NUMBER: function(runState: RunState) { + NUMBER: function (runState: RunState) { runState.stack.push(runState.eei.getBlockNumber()) }, - DIFFICULTY: function(runState: RunState) { + DIFFICULTY: function (runState: RunState) { runState.stack.push(runState.eei.getBlockDifficulty()) }, - GASLIMIT: function(runState: RunState) { + GASLIMIT: function (runState: RunState) { runState.stack.push(runState.eei.getBlockGasLimit()) }, - CHAINID: function(runState: RunState) { + CHAINID: function (runState: RunState) { if (!runState._common.gteHardfork('istanbul')) { trap(ERROR.INVALID_OPCODE) } runState.stack.push(runState.eei.getChainId()) }, - SELFBALANCE: function(runState: RunState) { + SELFBALANCE: function (runState: RunState) { if (!runState._common.gteHardfork('istanbul')) { trap(ERROR.INVALID_OPCODE) } @@ -471,16 +468,16 @@ export const handlers: { [k: string]: OpHandler } = { runState.stack.push(runState.eei.getSelfBalance()) }, // 0x50 range - 'storage' and execution - POP: function(runState: RunState) { + POP: function (runState: RunState) { runState.stack.pop() }, - MLOAD: function(runState: RunState) { + MLOAD: function (runState: RunState) { const pos = runState.stack.pop() subMemUsage(runState, pos, new BN(32)) const word = runState.memory.read(pos.toNumber(), 32) runState.stack.push(new BN(word)) }, - MSTORE: function(runState: RunState) { + MSTORE: function (runState: RunState) { let [offset, word] = runState.stack.popN(2) const buf = word.toArrayLike(Buffer, 'be', 32) subMemUsage(runState, offset, new BN(32)) @@ -488,7 +485,7 @@ export const handlers: { [k: string]: OpHandler } = { runState.memory.extend(offsetNum, 32) runState.memory.write(offsetNum, 32, buf) }, - MSTORE8: function(runState: RunState) { + MSTORE8: function (runState: RunState) { let [offset, byte] = runState.stack.popN(2) // NOTE: we're using a 'trick' here to get the least significant byte @@ -500,7 +497,7 @@ export const handlers: { [k: string]: OpHandler } = { runState.memory.extend(offsetNum, 1) runState.memory.write(offsetNum, 1, buf) }, - SLOAD: async function(runState: RunState) { + SLOAD: async function (runState: RunState) { let key = runState.stack.pop() const keyBuf = key.toArrayLike(Buffer, 'be', 32) @@ -508,7 +505,7 @@ export const handlers: { [k: string]: OpHandler } = { const valueBN = value.length ? new BN(value) : new BN(0) runState.stack.push(valueBN) }, - SSTORE: async function(runState: RunState) { + SSTORE: async function (runState: RunState) { if (runState.eei.isStatic()) { trap(ERROR.STATIC_STATE_CHANGE) } @@ -529,7 +526,7 @@ export const handlers: { [k: string]: OpHandler } = { updateSstoreGas(runState, found, value) await runState.eei.storageStore(keyBuf, value) }, - JUMP: function(runState: RunState) { + JUMP: function (runState: RunState) { const dest = runState.stack.pop() if (dest.gt(runState.eei.getCodeSize())) { trap(ERROR.INVALID_JUMP + ' at ' + describeLocation(runState)) @@ -543,7 +540,7 @@ export const handlers: { [k: string]: OpHandler } = { runState.programCounter = destNum }, - JUMPI: function(runState: RunState) { + JUMPI: function (runState: RunState) { let [dest, cond] = runState.stack.popN(2) if (!cond.isZero()) { if (dest.gt(runState.eei.getCodeSize())) { @@ -559,17 +556,17 @@ export const handlers: { [k: string]: OpHandler } = { runState.programCounter = destNum } }, - PC: function(runState: RunState) { + PC: function (runState: RunState) { runState.stack.push(new BN(runState.programCounter - 1)) }, - MSIZE: function(runState: RunState) { + MSIZE: function (runState: RunState) { runState.stack.push(runState.memoryWordCount.muln(32)) }, - GAS: function(runState: RunState) { + GAS: function (runState: RunState) { runState.stack.push(new BN(runState.eei.getGasLeft())) }, - JUMPDEST: function(runState: RunState) {}, - PUSH: function(runState: RunState) { + JUMPDEST: function (runState: RunState) {}, + PUSH: function (runState: RunState) { const numToPush = runState.opCode - 0x5f const loaded = new BN( runState.eei @@ -581,15 +578,15 @@ export const handlers: { [k: string]: OpHandler } = { runState.programCounter += numToPush runState.stack.push(loaded) }, - DUP: function(runState: RunState) { + DUP: function (runState: RunState) { const stackPos = runState.opCode - 0x7f runState.stack.dup(stackPos) }, - SWAP: function(runState: RunState) { + SWAP: function (runState: RunState) { const stackPos = runState.opCode - 0x8f runState.stack.swap(stackPos) }, - LOG: function(runState: RunState) { + LOG: function (runState: RunState) { if (runState.eei.isStatic()) { trap(ERROR.STATIC_STATE_CHANGE) } @@ -602,7 +599,7 @@ export const handlers: { [k: string]: OpHandler } = { } let topics = runState.stack.popN(topicsCount) - const topicsBuf = topics.map(function(a) { + const topicsBuf = topics.map(function (a) { return a.toArrayLike(Buffer, 'be', 32) }) @@ -621,7 +618,7 @@ export const handlers: { [k: string]: OpHandler } = { }, // '0xf0' range - closures - CREATE: async function(runState: RunState) { + CREATE: async function (runState: RunState) { if (runState.eei.isStatic()) { trap(ERROR.STATIC_STATE_CHANGE) } @@ -640,7 +637,7 @@ export const handlers: { [k: string]: OpHandler } = { const ret = await runState.eei.create(gasLimit, value, data) runState.stack.push(ret) }, - CREATE2: async function(runState: RunState) { + CREATE2: async function (runState: RunState) { if (!runState._common.gteHardfork('constantinople')) { trap(ERROR.INVALID_OPCODE) } @@ -672,7 +669,7 @@ export const handlers: { [k: string]: OpHandler } = { ) runState.stack.push(ret) }, - CALL: async function(runState: RunState) { + CALL: async function (runState: RunState) { let [ gasLimit, toAddress, @@ -718,7 +715,7 @@ export const handlers: { [k: string]: OpHandler } = { writeCallOutput(runState, outOffset, outLength) runState.stack.push(ret) }, - CALLCODE: async function(runState: RunState) { + CALLCODE: async function (runState: RunState) { let [ gasLimit, toAddress, @@ -752,7 +749,7 @@ export const handlers: { [k: string]: OpHandler } = { writeCallOutput(runState, outOffset, outLength) runState.stack.push(ret) }, - DELEGATECALL: async function(runState: RunState) { + DELEGATECALL: async function (runState: RunState) { const value = runState.eei.getCallValue() let [gasLimit, toAddress, inOffset, inLength, outOffset, outLength] = runState.stack.popN(6) const toAddressBuf = addressToBuffer(toAddress) @@ -771,7 +768,7 @@ export const handlers: { [k: string]: OpHandler } = { writeCallOutput(runState, outOffset, outLength) runState.stack.push(ret) }, - STATICCALL: async function(runState: RunState) { + STATICCALL: async function (runState: RunState) { const value = new BN(0) let [gasLimit, toAddress, inOffset, inLength, outOffset, outLength] = runState.stack.popN(6) const toAddressBuf = addressToBuffer(toAddress) @@ -790,7 +787,7 @@ export const handlers: { [k: string]: OpHandler } = { writeCallOutput(runState, outOffset, outLength) runState.stack.push(ret) }, - RETURN: function(runState: RunState) { + RETURN: function (runState: RunState) { const [offset, length] = runState.stack.popN(2) subMemUsage(runState, offset, length) let returnData = Buffer.alloc(0) @@ -799,7 +796,7 @@ export const handlers: { [k: string]: OpHandler } = { } runState.eei.finish(returnData) }, - REVERT: function(runState: RunState) { + REVERT: function (runState: RunState) { const [offset, length] = runState.stack.popN(2) subMemUsage(runState, offset, length) let returnData = Buffer.alloc(0) @@ -809,7 +806,7 @@ export const handlers: { [k: string]: OpHandler } = { runState.eei.revert(returnData) }, // '0x70', range - other - SELFDESTRUCT: async function(runState: RunState) { + SELFDESTRUCT: async function (runState: RunState) { let selfdestructToAddress = runState.stack.pop() if (runState.eei.isStatic()) { trap(ERROR.STATIC_STATE_CHANGE) @@ -904,31 +901,17 @@ function maxCallGas(gasLimit: BN, gasLeft: BN): BN { return gasLimit.gt(gasAllowed) ? gasAllowed : gasLimit } -function getContractStorage(runState: RunState, address: Buffer, key: Buffer) { - return new Promise((resolve, reject) => { - const cb = (err: Error | null, res: any) => { - if (err) return reject(err) - resolve(res) - } - runState.stateManager.getContractStorage(address, key, (err: Error, current: Buffer) => { - if (err) return cb(err, null) - if ( - runState._common.hardfork() === 'constantinople' || - runState._common.gteHardfork('istanbul') - ) { - runState.stateManager.getOriginalContractStorage( - address, - key, - (err: Error, original: Buffer) => { - if (err) return cb(err, null) - cb(null, { current, original }) - }, - ) - } else { - cb(null, current) - } - }) - }) +async function getContractStorage(runState: RunState, address: Buffer, key: Buffer) { + const current = await runState.stateManager.getContractStorage(address, key) + if ( + runState._common.hardfork() === 'constantinople' || + runState._common.gteHardfork('istanbul') + ) { + const original = await runState.stateManager.getOriginalContractStorage(address, key) + return { current, original } + } else { + return current + } } function updateSstoreGas(runState: RunState, found: any, value: Buffer) { diff --git a/packages/vm/lib/evm/precompiles/01-ecrecover.ts b/packages/vm/lib/evm/precompiles/01-ecrecover.ts index f3f095cd81d..c6c6aad43ac 100644 --- a/packages/vm/lib/evm/precompiles/01-ecrecover.ts +++ b/packages/vm/lib/evm/precompiles/01-ecrecover.ts @@ -4,7 +4,7 @@ import { PrecompileInput } from './types' import { OOGResult, ExecResult } from '../evm' const assert = require('assert') -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) const gasUsed = new BN(opts._common.param('gasPrices', 'ecRecover')) diff --git a/packages/vm/lib/evm/precompiles/02-sha256.ts b/packages/vm/lib/evm/precompiles/02-sha256.ts index 840c41a0562..acdb0a492ee 100644 --- a/packages/vm/lib/evm/precompiles/02-sha256.ts +++ b/packages/vm/lib/evm/precompiles/02-sha256.ts @@ -4,7 +4,7 @@ import { PrecompileInput } from './types' import { OOGResult, ExecResult } from '../evm' const assert = require('assert') -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) const data = opts.data diff --git a/packages/vm/lib/evm/precompiles/03-ripemd160.ts b/packages/vm/lib/evm/precompiles/03-ripemd160.ts index f0b5cf9750c..d3dd250e213 100644 --- a/packages/vm/lib/evm/precompiles/03-ripemd160.ts +++ b/packages/vm/lib/evm/precompiles/03-ripemd160.ts @@ -4,7 +4,7 @@ import { PrecompileInput } from './types' import { OOGResult, ExecResult } from '../evm' const assert = require('assert') -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) const data = opts.data diff --git a/packages/vm/lib/evm/precompiles/04-identity.ts b/packages/vm/lib/evm/precompiles/04-identity.ts index e8f7b573a4c..39d510c26e8 100644 --- a/packages/vm/lib/evm/precompiles/04-identity.ts +++ b/packages/vm/lib/evm/precompiles/04-identity.ts @@ -3,7 +3,7 @@ import { PrecompileInput } from './types' import { OOGResult, ExecResult } from '../evm' const assert = require('assert') -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) const data = opts.data diff --git a/packages/vm/lib/evm/precompiles/05-modexp.ts b/packages/vm/lib/evm/precompiles/05-modexp.ts index 291fa920c75..3cca203853c 100644 --- a/packages/vm/lib/evm/precompiles/05-modexp.ts +++ b/packages/vm/lib/evm/precompiles/05-modexp.ts @@ -67,7 +67,7 @@ function expmod(B: BN, E: BN, M: BN): BN { return res.fromRed() } -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) const data = opts.data diff --git a/packages/vm/lib/evm/precompiles/06-ecadd.ts b/packages/vm/lib/evm/precompiles/06-ecadd.ts index 84e7fe38526..f4fa4c155c6 100644 --- a/packages/vm/lib/evm/precompiles/06-ecadd.ts +++ b/packages/vm/lib/evm/precompiles/06-ecadd.ts @@ -4,7 +4,7 @@ import { OOGResult, ExecResult } from '../evm' const assert = require('assert') const bn128 = require('rustbn.js') -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) let inputData = opts.data diff --git a/packages/vm/lib/evm/precompiles/07-ecmul.ts b/packages/vm/lib/evm/precompiles/07-ecmul.ts index f79cf255146..3540eb88215 100644 --- a/packages/vm/lib/evm/precompiles/07-ecmul.ts +++ b/packages/vm/lib/evm/precompiles/07-ecmul.ts @@ -4,7 +4,7 @@ import { OOGResult, ExecResult } from '../evm' const assert = require('assert') const bn128 = require('rustbn.js') -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) const inputData = opts.data diff --git a/packages/vm/lib/evm/precompiles/08-ecpairing.ts b/packages/vm/lib/evm/precompiles/08-ecpairing.ts index 7bcd797c981..b8d5defffea 100644 --- a/packages/vm/lib/evm/precompiles/08-ecpairing.ts +++ b/packages/vm/lib/evm/precompiles/08-ecpairing.ts @@ -4,7 +4,7 @@ import { OOGResult, ExecResult } from '../evm' const assert = require('assert') const bn128 = require('rustbn.js') -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) const inputData = opts.data diff --git a/packages/vm/lib/evm/precompiles/09-blake2f.ts b/packages/vm/lib/evm/precompiles/09-blake2f.ts index 5b87233d5b3..b1b3297a769 100644 --- a/packages/vm/lib/evm/precompiles/09-blake2f.ts +++ b/packages/vm/lib/evm/precompiles/09-blake2f.ts @@ -320,7 +320,7 @@ const SIGMA8 = [ // Multiply them all by 2 to make them offsets into a uint32 buffer, // because this is Javascript and we don't have uint64s const SIGMA82 = new Uint8Array( - SIGMA8.map(function(x) { + SIGMA8.map(function (x) { return x * 2 }), ) @@ -376,7 +376,7 @@ export function F(h: Uint32Array, m: Uint32Array, t: Uint32Array, f: boolean, ro } } -export default function(opts: PrecompileInput): ExecResult { +export default function (opts: PrecompileInput): ExecResult { assert(opts.data) const data = opts.data diff --git a/packages/vm/lib/index.ts b/packages/vm/lib/index.ts index ecccaab5357..ae67acd1c0c 100644 --- a/packages/vm/lib/index.ts +++ b/packages/vm/lib/index.ts @@ -2,7 +2,7 @@ import BN = require('bn.js') import Account from 'ethereumjs-account' import Blockchain from 'ethereumjs-blockchain' import Common from 'ethereumjs-common' -import { StateManager } from './state' +import { StateManager } from './state/index' import { default as runCode, RunCodeOpts } from './runCode' import { default as runCall, RunCallOpts } from './runCall' import { default as runTx, RunTxOpts, RunTxResult } from './runTx' @@ -10,10 +10,9 @@ import { default as runBlock, RunBlockOpts, RunBlockResult } from './runBlock' import { EVMResult, ExecResult } from './evm/evm' import { OpcodeList, getOpcodesForHF } from './evm/opcodes' import runBlockchain from './runBlockchain' -import PStateManager from './state/promisified' -const promisify = require('util.promisify') const AsyncEventEmitter = require('async-eventemitter') const Trie = require('merkle-patricia-tree/secure.js') +const { promisify } = require('util') /** * Options for instantiating a [[VM]]. @@ -72,7 +71,6 @@ export default class VM extends AsyncEventEmitter { allowUnlimitedContractSize: boolean _opcodes: OpcodeList public readonly _emit: (topic: string, data: any) => Promise - public readonly pStateManager: PStateManager protected isInitialized: boolean = false /** * VM async constructor. Creates engine instance and initializes it. @@ -129,8 +127,6 @@ export default class VM extends AsyncEventEmitter { this.stateManager = new StateManager({ trie, common: this._common }) } - this.pStateManager = new PStateManager(this.stateManager) - this.blockchain = opts.blockchain || new Blockchain({ common: this._common }) this.allowUnlimitedContractSize = diff --git a/packages/vm/lib/runBlock.ts b/packages/vm/lib/runBlock.ts index dd8cd4c7c77..f75eb28275d 100644 --- a/packages/vm/lib/runBlock.ts +++ b/packages/vm/lib/runBlock.ts @@ -4,9 +4,9 @@ import { encode } from 'rlp' import VM from './index' import Bloom from './bloom' import { RunTxResult } from './runTx' -import PStateManager from './state/promisified' -const promisify = require('util.promisify') +import { StateManager } from './state/index' const Trie = require('merkle-patricia-tree') +const { promisify } = require('util') /** * Options for running a block. @@ -86,7 +86,7 @@ export default async function runBlock(this: VM, opts: RunBlockOpts): Promise { - const state = this.pStateManager + const state = this.stateManager const minerReward = new BN(this._common.param('pow', 'minerReward')) const ommers = block.uncleHeaders // Reward ommers @@ -284,7 +284,7 @@ function calculateMinerReward(minerReward: BN, ommersNum: number): BN { return reward } -async function rewardAccount(state: PStateManager, address: Buffer, reward: BN): Promise { +async function rewardAccount(state: StateManager, address: Buffer, reward: BN): Promise { const account = await state.getAccount(address) account.balance = toBuffer(new BN(account.balance).add(reward)) await state.putAccount(address, account) diff --git a/packages/vm/lib/runBlockchain.ts b/packages/vm/lib/runBlockchain.ts index f9ab7d4021a..60d32138971 100644 --- a/packages/vm/lib/runBlockchain.ts +++ b/packages/vm/lib/runBlockchain.ts @@ -1,6 +1,7 @@ import Blockchain from 'ethereumjs-blockchain' import VM from './index' const async = require('async') +const { callbackify } = require('util') /** * @ignore @@ -29,12 +30,15 @@ export default function runBlockchain(this: VM, blockchain: Blockchain): Promise function getStartingState(cb: any) { // if we are just starting or if a chain re-org has happened if (!headBlock || reorg) { - blockchain.getBlock(block.header.parentHash, function(err: any, parentBlock: any) { + blockchain.getBlock(block.header.parentHash, function (err: any, parentBlock: any) { parentState = parentBlock.header.stateRoot // generate genesis state if we are at the genesis block // we don't have the genesis state if (!headBlock) { - return self.stateManager.generateCanonicalGenesis(cb) + const generateCanonicalGenesis = callbackify( + self.stateManager.generateCanonicalGenesis.bind(self.stateManager), + ) + return generateCanonicalGenesis(cb) } else { cb(err) } @@ -57,9 +61,9 @@ export default function runBlockchain(this: VM, blockchain: Blockchain): Promise headBlock = block cb() }) - .catch(err => { + .catch((err) => { // remove invalid block - blockchain.delBlock(block.header.hash(), function() { + blockchain.delBlock(block.header.hash(), function () { cb(err) }) }) diff --git a/packages/vm/lib/runTx.ts b/packages/vm/lib/runTx.ts index 87d56ea97f7..50f0e01c71c 100644 --- a/packages/vm/lib/runTx.ts +++ b/packages/vm/lib/runTx.ts @@ -7,7 +7,6 @@ import Bloom from './bloom' import { default as EVM, EVMResult } from './evm/evm' import Message from './evm/message' import TxContext from './evm/txContext' -import PStateManager from './state/promisified' const Block = require('ethereumjs-block') /** @@ -72,8 +71,7 @@ export default async function runTx(this: VM, opts: RunTxOpts): Promise { const block = opts.block const tx = opts.tx - const state = this.pStateManager + const state = this.stateManager /** * The `beforeTx` event @@ -142,7 +140,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { value: tx.value, data: tx.data, }) - state._wrapped._clearOriginalStorageCache() + state._clearOriginalStorageCache() const evm = new EVM(this, txContext, block) const results = (await evm.executeMessage(message)) as RunTxResult @@ -186,7 +184,7 @@ async function _runTx(this: VM, opts: RunTxOpts): Promise { */ if (results.execResult.selfdestruct) { const keys = Object.keys(results.execResult.selfdestruct) - for (const k of keys) { + for await (const k of keys) { await state.putAccount(Buffer.from(k, 'hex'), new Account()) } } diff --git a/packages/vm/lib/state/cache.ts b/packages/vm/lib/state/cache.ts index 79201d40834..cf324f5cbdc 100644 --- a/packages/vm/lib/state/cache.ts +++ b/packages/vm/lib/state/cache.ts @@ -1,6 +1,6 @@ -const asyncLib = require('async') -const Tree = require('functional-red-black-tree') import Account from 'ethereumjs-account' +const Tree = require('functional-red-black-tree') +const { promisify } = require('util') /** * @ignore @@ -14,6 +14,10 @@ export default class Cache { this._cache = Tree() this._checkpoints = [] this._trie = trie + // Temporary promisifed methods until new release of `merkle-patricia-tree` + this._trie.p_get = promisify(this._trie.get.bind(this._trie)) + this._trie.p_put = promisify(this._trie.put.bind(this._trie)) + this._trie.p_del = promisify(this._trie.del.bind(this._trie)) } /** @@ -55,100 +59,70 @@ export default class Cache { /** * Looks up address in underlying trie. * @param address - Address of account - * @param cb - Callback with params (err, account) */ - _lookupAccount(address: Buffer, cb: any): void { - this._trie.get(address, (err: Error, raw: Buffer) => { - if (err) return cb(err) - var account = new Account(raw) - cb(null, account) - }) + async _lookupAccount(address: Buffer): Promise { + const raw = await this._trie.p_get(address) + const account = new Account(raw) + return account } /** * Looks up address in cache, if not found, looks it up * in the underlying trie. * @param key - Address of account - * @param cb - Callback with params (err, account) */ - getOrLoad(key: Buffer, cb: any): void { - const account = this.lookup(key) - if (account) { - asyncLib.nextTick(cb, null, account) - } else { - this._lookupAccount(key, (err: Error, account: Account) => { - if (err) return cb(err) - this._update(key, account, false, false) - cb(null, account) - }) + async getOrLoad(key: Buffer): Promise { + let account = this.lookup(key) + + if (!account) { + account = await this._lookupAccount(key) + this._update(key, account, false, false) } + + return account } /** * Warms cache by loading their respective account from trie * and putting them in cache. * @param addresses - Array of addresses - * @param cb - Callback */ - warm(addresses: string[], cb: any): void { - // shim till async supports iterators - const accountArr: string[] = [] - addresses.forEach(val => { - if (val) accountArr.push(val) - }) - - asyncLib.eachSeries( - accountArr, - (addressHex: string, done: any) => { - var address = Buffer.from(addressHex, 'hex') - this._lookupAccount(address, (err: Error, account: Account) => { - if (err) return done(err) - this._update(address, account, false, false) - done() - }) - }, - cb, - ) + async warm(addresses: string[]): Promise { + for await (let addressHex of addresses) { + if (addressHex) { + const address = Buffer.from(addressHex, 'hex') + const account = await this._lookupAccount(address) + this._update(address, account, false, false) + } + } } /** * Flushes cache by updating accounts that have been modified * and removing accounts that have been deleted. - * @param cb - Callback */ - flush(cb: any): void { + async flush(): Promise { const it = this._cache.begin let next = true - asyncLib.whilst( - () => next, - (done: any) => { - if (it.value && it.value.modified) { - it.value.modified = false - it.value.val = it.value.val.serialize() - this._trie.put(Buffer.from(it.key, 'hex'), it.value.val, (err: Error) => { - if (err) return done(err) - next = it.hasNext - it.next() - done() - }) - } else if (it.value && it.value.deleted) { - it.value.modified = false - it.value.deleted = false - it.value.val = new Account().serialize() - this._trie.del(Buffer.from(it.key, 'hex'), (err: Error) => { - if (err) return done(err) - next = it.hasNext - it.next() - done() - }) - } else { - next = it.hasNext - it.next() - asyncLib.nextTick(done) - } - }, - cb, - ) + while (next) { + if (it.value && it.value.modified) { + it.value.modified = false + it.value.val = it.value.val.serialize() + await this._trie.p_put(Buffer.from(it.key, 'hex'), it.value.val) + next = it.hasNext + it.next() + } else if (it.value && it.value.deleted) { + it.value.modified = false + it.value.deleted = false + it.value.val = new Account().serialize() + await this._trie.p_del(Buffer.from(it.key, 'hex')) + next = it.hasNext + it.next() + } else { + next = it.hasNext + it.next() + } + } } /** diff --git a/packages/vm/lib/state/promisified.ts b/packages/vm/lib/state/promisified.ts deleted file mode 100644 index 384b12f69a3..00000000000 --- a/packages/vm/lib/state/promisified.ts +++ /dev/null @@ -1,85 +0,0 @@ -const promisify = require('util.promisify') -import Account from 'ethereumjs-account' -import { default as StateManager, StorageDump } from './stateManager' - -/** - * Promisified wrapper around [[StateManager]] - * @ignore - */ -export default class PStateManager { - _wrapped: StateManager - - public readonly getAccount: (addr: Buffer) => Promise - public readonly putAccount: (addr: Buffer, account: Account) => Promise - public readonly putContractCode: (addr: Buffer, code: Buffer) => Promise - public readonly getContractCode: (addr: Buffer) => Promise - public readonly getContractStorage: (addr: Buffer, key: Buffer) => Promise - public readonly getOriginalContractStorage: (addr: Buffer, key: Buffer) => Promise - public readonly putContractStorage: (addr: Buffer, key: Buffer, value: Buffer) => Promise - public readonly clearContractStorage: (addr: Buffer) => Promise - public readonly checkpoint: () => Promise - public readonly commit: () => Promise - public readonly revert: () => Promise - public readonly getStateRoot: () => Promise - public readonly setStateRoot: (root: Buffer) => Promise - public readonly dumpStorage: (address: Buffer) => Promise - public readonly hasGenesisState: () => Promise - public readonly generateCanonicalGenesis: () => Promise - public readonly generateGenesis: (initState: any) => Promise - public readonly accountIsEmpty: (address: Buffer) => Promise - public readonly cleanupTouchedAccounts: () => Promise - - constructor(wrapped: StateManager) { - this._wrapped = wrapped - - // We cache these promisified function as they are called lots of times during the VM execution, - // and promisifying them each time has degrades its performance. - this.getAccount = promisify(this._wrapped.getAccount.bind(this._wrapped)) - - this.putAccount = promisify(this._wrapped.putAccount.bind(this._wrapped)) - - this.putContractCode = promisify(this._wrapped.putContractCode.bind(this._wrapped)) - - this.getContractCode = promisify(this._wrapped.getContractCode.bind(this._wrapped)) - - this.getContractStorage = promisify(this._wrapped.getContractStorage.bind(this._wrapped)) - - this.getOriginalContractStorage = promisify( - this._wrapped.getOriginalContractStorage.bind(this._wrapped), - ) - - this.putContractStorage = promisify(this._wrapped.putContractStorage.bind(this._wrapped)) - - this.clearContractStorage = promisify(this._wrapped.clearContractStorage.bind(this._wrapped)) - - this.checkpoint = promisify(this._wrapped.checkpoint.bind(this._wrapped)) - - this.commit = promisify(this._wrapped.commit.bind(this._wrapped)) - - this.revert = promisify(this._wrapped.revert.bind(this._wrapped)) - - this.getStateRoot = promisify(this._wrapped.getStateRoot.bind(this._wrapped)) - - this.setStateRoot = promisify(this._wrapped.setStateRoot.bind(this._wrapped)) - - this.dumpStorage = promisify(this._wrapped.dumpStorage.bind(this._wrapped)) - - this.hasGenesisState = promisify(this._wrapped.hasGenesisState.bind(this._wrapped)) - - this.generateCanonicalGenesis = promisify( - this._wrapped.generateCanonicalGenesis.bind(this._wrapped), - ) - - this.generateGenesis = promisify(this._wrapped.generateGenesis.bind(this._wrapped)) - - this.accountIsEmpty = promisify(this._wrapped.accountIsEmpty.bind(this._wrapped)) - - this.cleanupTouchedAccounts = promisify( - this._wrapped.cleanupTouchedAccounts.bind(this._wrapped), - ) - } - - copy(): PStateManager { - return new PStateManager(this._wrapped.copy()) - } -} diff --git a/packages/vm/lib/state/stateManager.ts b/packages/vm/lib/state/stateManager.ts index 75606c561c1..42875d981e0 100644 --- a/packages/vm/lib/state/stateManager.ts +++ b/packages/vm/lib/state/stateManager.ts @@ -1,7 +1,7 @@ const Set = require('core-js-pure/es/set') const Trie = require('merkle-patricia-tree/secure.js') -const asyncLib = require('async') -import * as utils from 'ethereumjs-util' +const { promisify } = require('util') +import { toBuffer, KECCAK256_NULL_S } from 'ethereumjs-util' import BN = require('bn.js') import { encode, decode } from 'rlp' import Common from 'ethereumjs-common' @@ -9,6 +9,11 @@ import { genesisStateByName } from 'ethereumjs-common/dist/genesisStates' import Account from 'ethereumjs-account' import Cache from './cache' import { ripemdPrecompileAddress } from '../evm/precompiles' +import { resolve } from 'dns' +import { doesNotReject } from 'assert' + +// Temporary type until new `merkle-patricia-tree` release with types +type Trie = any /** * Storage values of an account @@ -28,7 +33,7 @@ export interface StateManagerOpts { /** * A [`merkle-patricia-tree`](https://github.com/ethereumjs/merkle-patricia-tree) instance */ - trie?: any + trie?: Trie } /** @@ -37,7 +42,7 @@ export interface StateManagerOpts { */ export default class StateManager { _common: Common - _trie: any + _trie: Trie _storageTries: any _cache: Cache _touched: Set @@ -73,22 +78,14 @@ export default class StateManager { return new StateManager({ trie: this._trie.copy(), common: this._common }) } - /** - * Callback for `getAccount` method. - * @callback getAccount~callback - * @param error - an error that may have happened or `null` - * @param account - An [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) - * instance corresponding to the provided `address` - */ - /** * Gets the [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) * associated with `address`. Returns an empty account if the account does not exist. * @param address - Address of the `account` to get - * @param {getAccount~callback} cb */ - getAccount(address: Buffer, cb: any): void { - this._cache.getOrLoad(address, cb) + async getAccount(address: Buffer): Promise { + const account = await this._cache.getOrLoad(address) + return account } /** @@ -96,16 +93,14 @@ export default class StateManager { * into state under the provided `address`. * @param address - Address under which to store `account` * @param account - The [`ethereumjs-account`](https://github.com/ethereumjs/ethereumjs-account) to store - * @param cb - Callback function */ - putAccount(address: Buffer, account: Account, cb: any): void { + async putAccount(address: Buffer, account: Account): Promise { // TODO: dont save newly created accounts that have no balance // if (toAccount.balance.toString('hex') === '00') { // if they have money or a non-zero nonce or code, then write to tree this._cache.put(address, account) this.touchAccount(address) - // self._trie.put(addressHex, account.serialize(), cb) - cb() + // this._trie.put(addressHex, account.serialize(), cb) } /** @@ -124,43 +119,26 @@ export default class StateManager { * corresponding to `address` to reference this. * @param address - Address of the `account` to add the `code` for * @param value - The value of the `code` - * @param cb - Callback function */ - putContractCode(address: Buffer, value: Buffer, cb: any): void { - this.getAccount(address, (err: Error, account: Account) => { - if (err) { - return cb(err) - } - // TODO: setCode use trie.setRaw which creates a storage leak - account.setCode(this._trie, value, err => { - if (err) { - return cb(err) - } - this.putAccount(address, account, cb) - }) - }) + async putContractCode(address: Buffer, value: Buffer): Promise { + const account = await this.getAccount(address) + // TODO: setCode use trie.setRaw which creates a storage leak + const setCode = promisify(account.setCode.bind(account)) + await setCode(this._trie, value) + await this.putAccount(address, account) } - /** - * Callback for `getContractCode` method - * @callback getContractCode~callback - * @param error - an error that may have happened or `null` - * @param code - The code corresponding to the provided address. - * Returns an empty `Buffer` if the account has no associated code. - */ - /** * Gets the code corresponding to the provided `address`. * @param address - Address to get the `code` for - * @param {getContractCode~callback} cb + * @returns {Promise} - Resolves with the code corresponding to the provided address. + * Returns an empty `Buffer` if the account has no associated code. */ - getContractCode(address: Buffer, cb: any): void { - this.getAccount(address, (err: Error, account: Account) => { - if (err) { - return cb(err) - } - account.getCode(this._trie, cb) - }) + async getContractCode(address: Buffer): Promise { + const account = await this.getAccount(address) + const getCode = promisify(account.getCode.bind(account)) + const code = await getCode(this._trie) + return code } /** @@ -168,17 +146,13 @@ export default class StateManager { * for an account and saves this in the storage cache. * @private */ - _lookupStorageTrie(address: Buffer, cb: any): void { + async _lookupStorageTrie(address: Buffer): Promise { // from state trie - this.getAccount(address, (err: Error, account: Account) => { - if (err) { - return cb(err) - } - const storageTrie = this._trie.copy() - storageTrie.root = account.stateRoot - storageTrie._checkpoints = [] - cb(null, storageTrie) - }) + const account = await this.getAccount(address) + const storageTrie = this._trie.copy() + storageTrie.root = account.stateRoot + storageTrie._checkpoints = [] + return storageTrie } /** @@ -186,49 +160,35 @@ export default class StateManager { * cache or does a lookup. * @private */ - _getStorageTrie(address: Buffer, cb: any): void { - const storageTrie = this._storageTries[address.toString('hex')] + async _getStorageTrie(address: Buffer): Promise { // from storage cache - if (storageTrie) { - return cb(null, storageTrie) + let storageTrie = this._storageTries[address.toString('hex')] + if (!storageTrie) { + // lookup from state + storageTrie = await this._lookupStorageTrie(address) } - // lookup from state - this._lookupStorageTrie(address, cb) + return storageTrie } - /** - * Callback for `getContractStorage` method - * @callback getContractStorage~callback - * @param {Error} error an error that may have happened or `null` - * @param {Buffer} storageValue The storage value for the account - * corresponding to the provided address at the provided key. - * If this does not exists an empty `Buffer` is returned - */ - /** * Gets the storage value associated with the provided `address` and `key`. This method returns * the shortest representation of the stored value. * @param address - Address of the account to get the storage for * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. - * @param {getContractCode~callback} cb. + * @returns {Promise} - The storage value for the account + * corresponding to the provided address at the provided key. + * If this does not exists an empty `Buffer` is returned */ - getContractStorage(address: Buffer, key: Buffer, cb: any): void { + async getContractStorage(address: Buffer, key: Buffer): Promise { if (key.length !== 32) { - return cb(new Error('Storage key must be 32 bytes long')) + throw new Error('Storage key must be 32 bytes long') } - this._getStorageTrie(address, (err: Error, trie: any) => { - if (err) { - return cb(err) - } - trie.get(key, (err: Error, value: Buffer) => { - if (err) { - return cb(err) - } - const decoded = decode(value) - cb(null, decoded) - }) - }) + const trie = await this._getStorageTrie(address) + const trieGet = promisify(trie.get.bind(trie)) + const value = await trieGet(key) + const decoded = decode(value) + return decoded } /** @@ -239,9 +199,9 @@ export default class StateManager { * @param address - Address of the account to get the storage for * @param key - Key in the account's storage to get the value for. Must be 32 bytes long. */ - getOriginalContractStorage(address: Buffer, key: Buffer, cb: any): void { + async getOriginalContractStorage(address: Buffer, key: Buffer): Promise { if (key.length !== 32) { - return cb(new Error('Storage key must be 32 bytes long')) + throw new Error('Storage key must be 32 bytes long') } const addressHex = address.toString('hex') @@ -256,38 +216,38 @@ export default class StateManager { } if (map.has(keyHex)) { - cb(null, map.get(keyHex)) + return map.get(keyHex)! } else { - this.getContractStorage(address, key, (err: Error, current: Buffer) => { - if (err) return cb(err) - - map.set(keyHex, current) - cb(null, current) - }) + const current = await this.getContractStorage(address, key) + map.set(keyHex, current) + return current } } /** - * Modifies the storage trie of an account + * Modifies the storage trie of an account. * @private * @param address - Address of the account whose storage is to be modified * @param modifyTrie - Function to modify the storage trie of the account */ - _modifyContractStorage(address: Buffer, modifyTrie: any, cb: any): void { - this._getStorageTrie(address, (err: Error, storageTrie: any) => { - if (err) { - return cb(err) - } + async _modifyContractStorage( + address: Buffer, + modifyTrie: (storageTrie: Trie, done: Function) => void, + ): Promise { + return new Promise(async (resolve) => { + const storageTrie = await this._getStorageTrie(address) - modifyTrie(storageTrie, (err: Error) => { - if (err) return cb(err) + modifyTrie(storageTrie, async () => { // update storage cache this._storageTries[address.toString('hex')] = storageTrie + // update contract stateRoot const contract = this._cache.get(address) contract.stateRoot = storageTrie.root - this.putAccount(address, contract, cb) + + await this.putAccount(address, contract) this.touchAccount(address) + resolve() }) }) } @@ -298,83 +258,76 @@ export default class StateManager { * @param address - Address to set a storage value for * @param key - Key to set the value at. Must be 32 bytes long. * @param value - Value to set at `key` for account corresponding to `address` - * @param cb - Callback function */ - putContractStorage(address: Buffer, key: Buffer, value: Buffer, cb: any): void { + async putContractStorage(address: Buffer, key: Buffer, value: Buffer): Promise { if (key.length !== 32) { - return cb(new Error('Storage key must be 32 bytes long')) + throw new Error('Storage key must be 32 bytes long') } - this._modifyContractStorage( - address, - (storageTrie: any, done: any) => { - if (value && value.length) { - // format input - const encodedValue = encode(value) - storageTrie.put(key, encodedValue, done) - } else { - // deleting a value - storageTrie.del(key, done) - } - }, - cb, - ) + await this._modifyContractStorage(address, async (storageTrie, done) => { + if (value && value.length) { + // format input + const encodedValue = encode(value) + storageTrie.put(key, encodedValue, (err: Error) => { + if (err) throw err + done() + }) + } else { + // deleting a value + storageTrie.del(key, (err: Error) => { + if (err) throw err + done() + }) + } + }) } /** * Clears all storage entries for the account corresponding to `address`. * @param address - Address to clear the storage of - * @param cb - Callback function */ - clearContractStorage(address: Buffer, cb: any) { - this._modifyContractStorage( - address, - (storageTrie: any, done: any) => { - storageTrie.root = storageTrie.EMPTY_TRIE_ROOT - done() - }, - cb, - ) + async clearContractStorage(address: Buffer): Promise { + await this._modifyContractStorage(address, (storageTrie, done) => { + storageTrie.root = storageTrie.EMPTY_TRIE_ROOT + done() + }) } /** * Checkpoints the current state of the StateManager instance. * State changes that follow can then be committed by calling * `commit` or `reverted` by calling rollback. - * @param cb - Callback function */ - checkpoint(cb: any): void { + async checkpoint(): Promise { this._trie.checkpoint() this._cache.checkpoint() this._touchedStack.push(new Set(Array.from(this._touched))) this._checkpointCount++ - cb() } /** * Commits the current change-set to the instance since the * last call to checkpoint. - * @param cb - Callback function */ - commit(cb: any): void { + async commit(): Promise { // setup trie checkpointing - this._trie.commit(() => { - // setup cache checkpointing - this._cache.commit() - this._touchedStack.pop() - this._checkpointCount-- - - if (this._checkpointCount === 0) this._cache.flush(cb) - else cb() - }) + const trieCommit = promisify(this._trie.commit.bind(this._trie)) + await trieCommit() + // setup cache checkpointing + this._cache.commit() + this._touchedStack.pop() + this._checkpointCount-- + + if (this._checkpointCount === 0) { + await this._cache.flush() + } } /** * Reverts the current change-set to the instance since the * last call to checkpoint. - * @param cb - Callback function */ - revert(cb: any): void { + async revert(): Promise { // setup trie checkpointing this._trie.revert() // setup cache checkpointing @@ -394,36 +347,24 @@ export default class StateManager { this._touched = touched this._checkpointCount-- - if (this._checkpointCount === 0) this._cache.flush(cb) - else cb() + if (this._checkpointCount === 0) { + await this._cache.flush() + } } - /** - * Callback for `getStateRoot` method - * @callback getStateRoot~callback - * @param {Error} error an error that may have happened or `null`. - * Will be an error if the un-committed checkpoints on the instance. - * @param {Buffer} stateRoot The state-root of the `StateManager` - */ - /** * Gets the state-root of the Merkle-Patricia trie representation * of the state of this StateManager. Will error if there are uncommitted * checkpoints on the instance. - * @param {getStateRoot~callback} cb + * @returns {Promise} - Returns the state-root of the `StateManager` */ - getStateRoot(cb: any): void { + async getStateRoot(): Promise { if (this._checkpointCount !== 0) { - return cb(new Error('Cannot get state root with uncommitted checkpoints')) + throw new Error('Cannot get state root with uncommitted checkpoints') } - - this._cache.flush((err: Error) => { - if (err) { - return cb(err) - } - const stateRoot = this._trie.root - cb(null, stateRoot) - }) + await this._cache.flush() + const stateRoot = this._trie.root + return stateRoot } /** @@ -432,188 +373,136 @@ export default class StateManager { * checkpoints on the instance or if the state root does not exist in * the state trie. * @param stateRoot - The state-root to reset the instance to - * @param cb - Callback function */ - setStateRoot(stateRoot: Buffer, cb: any): void { + async setStateRoot(stateRoot: Buffer): Promise { if (this._checkpointCount !== 0) { - return cb(new Error('Cannot set state root with uncommitted checkpoints')) + throw new Error('Cannot set state root with uncommitted checkpoints') } - this._cache.flush((err: Error) => { - if (err) { - return cb(err) - } - if (stateRoot === this._trie.EMPTY_TRIE_ROOT) { - this._trie.root = stateRoot - this._cache.clear() - this._storageTries = {} - return cb() - } - this._trie.checkRoot(stateRoot, (err: Error, hasRoot: boolean) => { - if (err || !hasRoot) { - cb(err || new Error('State trie does not contain state root')) - } else { - this._trie.root = stateRoot - this._cache.clear() - this._storageTries = {} - cb() - } - }) - }) - } + await this._cache.flush() - /** - * Callback for `dumpStorage` method - * @callback dumpStorage~callback - * @param {Error} error an error that may have happened or `null` - * @param {Object} accountState The state of the account as an `Object` map. - * Keys are are the storage keys, values are the storage values as strings. - * Both are represented as hex strings without the `0x` prefix. - */ + if (stateRoot === this._trie.EMPTY_TRIE_ROOT) { + this._trie.root = stateRoot + this._cache.clear() + this._storageTries = {} + return + } + + const checkRoot = promisify(this._trie.checkRoot.bind(this._trie)) + const hasRoot = await checkRoot(stateRoot) + if (!hasRoot) { + throw new Error('State trie does not contain state root') + } + + this._trie.root = stateRoot + this._cache.clear() + this._storageTries = {} + } /** * Dumps the the storage values for an `account` specified by `address`. * @param address - The address of the `account` to return storage for - * @param {dumpStorage~callback} cb + * @returns {Promise} - The state of the account as an `Object` map. + * Keys are are the storage keys, values are the storage values as strings. + * Both are represented as hex strings without the `0x` prefix. */ - dumpStorage(address: Buffer, cb: any): void { - this._getStorageTrie(address, (err: Error, trie: any) => { - if (err) { - return cb(err) - } + async dumpStorage(address: Buffer): Promise { + return new Promise(async (resolve) => { + const trie = await this._getStorageTrie(address) const storage: StorageDump = {} const stream = trie.createReadStream() + stream.on('data', (val: any) => { storage[val.key.toString('hex')] = val.value.toString('hex') }) stream.on('end', () => { - cb(storage) + resolve(storage) }) }) } - /** - * Callback for `hasGenesisState` method - * @callback hasGenesisState~callback - * @param {Error} error an error that may have happened or `null` - * @param {Boolean} hasGenesisState Whether the storage trie contains the - * canonical genesis state for the configured chain parameters. - */ - /** * Checks whether the current instance has the canonical genesis state * for the configured chain parameters. - * @param {hasGenesisState~callback} cb + * @returns {Promise} - Whether the storage trie contains the + * canonical genesis state for the configured chain parameters. */ - hasGenesisState(cb: any): void { + async hasGenesisState(): Promise { const root = this._common.genesis().stateRoot - this._trie.checkRoot(root, cb) + const checkRoot = promisify(this._trie.checkRoot.bind(this._trie)) + return await checkRoot(root) } /** * Generates a canonical genesis state on the instance based on the * configured chain parameters. Will error if there are uncommitted * checkpoints on the instance. - * @param cb - Callback function */ - generateCanonicalGenesis(cb: any): void { + async generateCanonicalGenesis(): Promise { if (this._checkpointCount !== 0) { - return cb(new Error('Cannot create genesis state with uncommitted checkpoints')) + throw new Error('Cannot create genesis state with uncommitted checkpoints') } - this.hasGenesisState((err: Error, genesis: boolean) => { - if (!genesis && !err) { - this.generateGenesis(genesisStateByName(this._common.chainName()), cb) - } else { - cb(err) - } - }) + const genesis = await this.hasGenesisState() + if (!genesis) { + await this.generateGenesis(genesisStateByName(this._common.chainName())) + } } /** * Initializes the provided genesis state into the state trie * @param initState - Object (address -> balance) - * @param cb - Callback function */ - generateGenesis(initState: any, cb: any) { + async generateGenesis(initState: any): Promise { if (this._checkpointCount !== 0) { - return cb(new Error('Cannot create genesis state with uncommitted checkpoints')) + throw new Error('Cannot create genesis state with uncommitted checkpoints') } + const triePut = promisify(this._trie.put.bind(this._trie)) + const addresses = Object.keys(initState) - asyncLib.eachSeries( - addresses, - (address: string, done: any) => { - const account = new Account() - if (initState[address].slice(0, 2) === '0x') { - account.balance = new BN(initState[address].slice(2), 16).toArrayLike(Buffer) - } else { - account.balance = new BN(initState[address]).toArrayLike(Buffer) - } - const addressBuffer = utils.toBuffer(address) - this._trie.put(addressBuffer, account.serialize(), done) - }, - cb, - ) + for await (let address of addresses) { + const account = new Account() + if (initState[address].slice(0, 2) === '0x') { + account.balance = new BN(initState[address].slice(2), 16).toArrayLike(Buffer) + } else { + account.balance = new BN(initState[address]).toArrayLike(Buffer) + } + const addressBuffer = toBuffer(address) + await triePut(addressBuffer, account.serialize()) + } } - /** - * Callback for `accountIsEmpty` method - * @callback accountIsEmpty~callback - * @param {Error} error an error that may have happened or `null` - * @param {Boolean} empty True if the account is empty false otherwise - */ - /** * Checks if the `account` corresponding to `address` is empty as defined in * EIP-161 (https://eips.ethereum.org/EIPS/eip-161). * @param address - Address to check - * @param {accountIsEmpty~callback} cb */ - accountIsEmpty(address: Buffer, cb: any): void { - this.getAccount.bind(this)(address, (err: Error, account: Account) => { - if (err) { - return cb(err) - } + async accountIsEmpty(address: Buffer): Promise { + const account = await this.getAccount(address) - // should be replaced by account.isEmpty() once updated - cb( - null, - account.nonce.toString('hex') === '' && - account.balance.toString('hex') === '' && - account.codeHash.toString('hex') === utils.KECCAK256_NULL_S, - ) - }) + // should be replaced by account.isEmpty() once updated + return ( + account.nonce.toString('hex') === '' && + account.balance.toString('hex') === '' && + account.codeHash.toString('hex') === KECCAK256_NULL_S + ) } /** * Removes accounts form the state trie that have been touched, * as defined in EIP-161 (https://eips.ethereum.org/EIPS/eip-161). - * @param cb - Callback function */ - cleanupTouchedAccounts(cb: any): void { + async cleanupTouchedAccounts(): Promise { const touchedArray = Array.from(this._touched) - asyncLib.forEach( - touchedArray, - (addressHex: string, next: any) => { - const address = Buffer.from(addressHex, 'hex') - this.accountIsEmpty(address, (err: Error, empty: boolean) => { - if (err) { - next(err) - return - } - - if (empty) { - this._cache.del(address) - } - next(null) - }) - }, - () => { - this._touched.clear() - cb() - }, - ) + for await (let addressHex of touchedArray) { + const address = Buffer.from(addressHex, 'hex') + const empty = await this.accountIsEmpty(address) + if (empty) { + this._cache.del(address) + } + } + this._touched.clear() } /** diff --git a/packages/vm/package.json b/packages/vm/package.json index 7de3c66a244..dac94767975 100644 --- a/packages/vm/package.json +++ b/packages/vm/package.json @@ -55,12 +55,10 @@ "ethereumjs-common": "^1.5.0", "ethereumjs-tx": "^2.1.2", "ethereumjs-util": "^6.2.0", - "fake-merkle-patricia-tree": "^1.0.1", "functional-red-black-tree": "^1.0.1", "merkle-patricia-tree": "^2.3.2", "rustbn.js": "~0.2.0", - "safe-buffer": "^5.1.1", - "util.promisify": "^1.0.0" + "safe-buffer": "^5.1.1" }, "devDependencies": { "@ethereumjs/config-nyc": "^1.1.1", @@ -84,16 +82,16 @@ "level-mem": "^3.0.1", "minimist": "^1.1.1", "nyc": "^12.0.2", - "prettier": "^1.16.4", + "prettier": "^2.0.4", "rlp": "^2.2.3", "standard": "^10.0.0", "tap-spec": "^5.0.0", "tape": "4.6.3", - "ts-node": "^8.6.2", + "ts-node": "^8.8.2", "tslint": "^5.16.0", "typedoc": "next", "typedoc-plugin-markdown": "^2.2.17", - "typescript": "^3.4.3", + "typescript": "^3.8.2", "typestrict": "^1.0.2" }, "author": "mjbecze ", diff --git a/packages/vm/tests/BlockchainTestsRunner.js b/packages/vm/tests/BlockchainTestsRunner.js index 9c1190b07be..fb15913dfc3 100644 --- a/packages/vm/tests/BlockchainTestsRunner.js +++ b/packages/vm/tests/BlockchainTestsRunner.js @@ -1,43 +1,44 @@ const async = require('async') const testUtil = require('./util.js') const ethUtil = require('ethereumjs-util') -const Trie = require('merkle-patricia-tree/secure') +const { StateManager } = require('../lib/state') +const Common = require('ethereumjs-common').default const Block = require('ethereumjs-block') const Blockchain = require('ethereumjs-blockchain').default const BlockHeader = require('ethereumjs-block/header.js') const level = require('level') const levelMem = require('level-mem') -var cacheDB = level('./.cachedb') -module.exports = function runBlockchainTest (options, testData, t, cb) { - var blockchainDB = levelMem() - var state = new Trie() - var validate = false +const cacheDB = level('./.cachedb') +module.exports = function runBlockchainTest(options, testData, t, cb) { + const blockchainDB = levelMem() + const stateManager = new StateManager({ common: new Common('mainnet', options.forkConfigVM) }) + let validate = false // Only run with block validation when sealEngine present in test file // and being set to Ethash PoW validation if (testData.sealEngine && testData.sealEngine === 'Ethash') { validate = true } - var blockchain = new Blockchain({ + const blockchain = new Blockchain({ db: blockchainDB, hardfork: options.forkConfigVM, - validate: validate + validate: validate, }) if (validate) { blockchain.ethash.cacheDB = cacheDB } - var VM + let VM if (options.dist) { VM = require('../dist/index.js').default } else { VM = require('../lib/index').default } - var vm = new VM({ - state: state, + const vm = new VM({ + stateManager, blockchain: blockchain, - hardfork: options.forkConfigVM + hardfork: options.forkConfigVM, }) - var genesisBlock = new Block({ hardfork: options.forkConfigVM }) + const genesisBlock = new Block({ hardfork: options.forkConfigVM }) testData.homestead = true if (testData.homestead) { @@ -50,104 +51,123 @@ module.exports = function runBlockchainTest (options, testData, t, cb) { } }) } - async.series([ - // set up pre-state - function (done) { - testUtil.setupPreConditions(state, testData, function () { - done() - }) - }, - function (done) { - // create and add genesis block - genesisBlock.header = new BlockHeader(formatBlockHeader(testData.genesisBlockHeader), { - hardfork: options.forkConfigVM - }) - t.equal(state.root.toString('hex'), genesisBlock.header.stateRoot.toString('hex'), 'correct pre stateRoot') - if (testData.genesisRLP) { - t.equal(genesisBlock.serialize().toString('hex'), testData.genesisRLP.slice(2), 'correct genesis RLP') - } - blockchain.putGenesis(genesisBlock, function (err) { - done(err) - }) - }, - function (done) { - async.eachSeries(testData.blocks, function (raw, cb) { - try { - var block = new Block(Buffer.from(raw.rlp.slice(2), 'hex'), { - hardfork: options.forkConfigVM - }) - // forces the block into thinking they are homestead - if (testData.homestead) { - block.header.isHomestead = function () { - return true - } - block.uncleHeaders.forEach(function (uncle) { - uncle.isHomestead = function () { - return true + async.series( + [ + // set up pre-state + function (done) { + testUtil.setupPreConditions(stateManager._trie, testData, function () { + done() + }) + }, + function (done) { + // create and add genesis block + genesisBlock.header = new BlockHeader(formatBlockHeader(testData.genesisBlockHeader), { + hardfork: options.forkConfigVM, + }) + t.equal( + stateManager._trie.root.toString('hex'), + genesisBlock.header.stateRoot.toString('hex'), + 'correct pre stateRoot', + ) + if (testData.genesisRLP) { + t.equal( + genesisBlock.serialize().toString('hex'), + testData.genesisRLP.slice(2), + 'correct genesis RLP', + ) + } + blockchain.putGenesis(genesisBlock, function (err) { + done(err) + }) + }, + function (done) { + async.eachSeries( + testData.blocks, + function (raw, cb) { + try { + const block = new Block(Buffer.from(raw.rlp.slice(2), 'hex'), { + hardfork: options.forkConfigVM, + }) + // forces the block into thinking they are homestead + if (testData.homestead) { + block.header.isHomestead = function () { + return true + } + block.uncleHeaders.forEach(function (uncle) { + uncle.isHomestead = function () { + return true + } + }) + } + blockchain.putBlock(block, function (err) { + cb(err) + }) + } catch (err) { + if (err) { + t.fail(err) } - }) + cb() + } + }, + function () { + done() + }, + ) + }, + function setGenesisStateRoot(done) { + // This is a trick to avoid generating the canonical genesis + // state. Generating the genesis state is not needed because + // blockchain tests come with their own `pre` world state. + // TODO: Add option to `runBlockchain` not to generate genesis state. + vm._common.genesis().stateRoot = stateManager._trie.root + done() + }, + function runBlockchain(done) { + vm.runBlockchain() + .then(() => done()) + .catch(() => done()) + }, + function getHead(done) { + vm.blockchain.getHead(function (err, block) { + if (testData.lastblockhash.substr(0, 2) === '0x') { + // fix for BlockchainTests/GeneralStateTests/stRandom/* + testData.lastblockhash = testData.lastblockhash.substr(2) } - blockchain.putBlock(block, function (err) { - cb(err) - }) - } catch (err) { - if (err) { - t.fail(err) + t.equal(block.hash().toString('hex'), testData.lastblockhash, 'last block hash') + // if the test fails, then block.header is the prej because + // vm.runBlock has a check that prevents the actual postState from being + // imported if it is not equal to the expected postState. it is useful + // for debugging to skip this, so that verifyPostConditions will compare + // testData.postState to the actual postState, rather than to the preState. + if (!options.debug) { + // make sure the state is set before checking post conditions + stateManager._trie.root = block.header.stateRoot } - cb() + done(err) + }) + }, + function (done) { + if (options.debug) { + testUtil.verifyPostConditions(state, testData.postState, t, done) + } else { + done() } - }, function () { - done() - }) - }, - function setGenesisStateRoot (done) { - // This is a trick to avoid generating the canonical genesis - // state. Generating the genesis state is not needed because - // blockchain tests come with their own `pre` world state. - // TODO: Add option to `runBlockchain` not to generate genesis state. - vm._common.genesis().stateRoot = state.root - done() - }, - function runBlockchain (done) { - vm.runBlockchain() - .then(() => done()) - .catch(() => done()) + }, + ], + function () { + t.equal( + blockchain.meta.rawHead.toString('hex'), + testData.lastblockhash, + 'correct header block', + ) + cb() }, - function getHead (done) { - vm.blockchain.getHead(function (err, block) { - if (testData.lastblockhash.substr(0, 2) === '0x') { - // fix for BlockchainTests/GeneralStateTests/stRandom/* - testData.lastblockhash = testData.lastblockhash.substr(2) - } - t.equal(block.hash().toString('hex'), testData.lastblockhash, 'last block hash') - // if the test fails, then block.header is the preState because - // vm.runBlock has a check that prevents the actual postState from being - // imported if it is not equal to the expected postState. it is useful - // for debugging to skip this, so that verifyPostConditions will compare - // testData.postState to the actual postState, rather than to the preState. - if (!options.debug) { - // make sure the state is set before checking post conditions - state.root = block.header.stateRoot - } - done(err) - }) - }, - function (done) { - if (options.debug) { - testUtil.verifyPostConditions(state, testData.postState, t, done) - } else { - done() - } - } - ], function () { - t.equal(blockchain.meta.rawHead.toString('hex'), testData.lastblockhash, 'correct header block') - cb() - }) + ) } -function formatBlockHeader (data) { - var r = {} - var keys = Object.keys(data) +function formatBlockHeader(data) { + const r = {} + const keys = Object.keys(data) keys.forEach(function (key) { r[key] = ethUtil.addHexPrefix(data[key]) }) diff --git a/packages/vm/tests/GeneralStateTestsRunner.js b/packages/vm/tests/GeneralStateTestsRunner.js index e2a0f0d3e73..c8d8910accc 100644 --- a/packages/vm/tests/GeneralStateTestsRunner.js +++ b/packages/vm/tests/GeneralStateTestsRunner.js @@ -3,9 +3,11 @@ const testUtil = require('./util') const Trie = require('merkle-patricia-tree/secure') const ethUtil = require('ethereumjs-util') const Account = require('ethereumjs-account').default +const Common = require('ethereumjs-common').default const BN = ethUtil.BN +const { StateManager } = require('../lib/state') -function parseTestCases (forkConfigTestSuite, testData, data, gasLimit, value) { +function parseTestCases(forkConfigTestSuite, testData, data, gasLimit, value) { let testCases = [] if (testData['post'][forkConfigTestSuite]) { testCases = testData['post'][forkConfigTestSuite].map(testCase => { @@ -27,10 +29,10 @@ function parseTestCases (forkConfigTestSuite, testData, data, gasLimit, value) { tx.gasLimit = testData.transaction.gasLimit[testIndexes['gas']] tx.value = testData.transaction.value[testIndexes['value']] return { - 'transaction': tx, - 'postStateRoot': testCase['hash'], - 'env': testData['env'], - 'pre': testData['pre'] + transaction: tx, + postStateRoot: testCase['hash'], + env: testData['env'], + pre: testData['pre'], } }) } @@ -42,115 +44,115 @@ function parseTestCases (forkConfigTestSuite, testData, data, gasLimit, value) { return testCases } -function runTestCase (options, testData, t, cb) { - const state = new Trie() +function runTestCase(options, testData, t, cb) { + const stateManager = new StateManager({ common: new Common('mainnet', options.forkConfigVM) }) let block, vm - async.series([ - function (done) { - var VM - if (options.dist) { - VM = require('../dist/index.js').default - } else { - VM = require('../lib/index').default - } - vm = new VM({ - state: state, - hardfork: options.forkConfigVM - }) - testUtil.setupPreConditions(state, testData, done) - }, - function (done) { - var tx = testUtil.makeTx(testData.transaction, options.forkConfigVM) - block = testUtil.makeBlockFromEnv(testData.env) - tx._homestead = true - tx.enableHomestead = true - block.isHomestead = function () { - return true - } + async.series( + [ + function(done) { + let VM + if (options.dist) { + VM = require('../dist/index.js').default + } else { + VM = require('../lib/index').default + } + vm = new VM({ + stateManager, + hardfork: options.forkConfigVM, + }) + testUtil.setupPreConditions(stateManager._trie, testData, done) + }, + function(done) { + let tx = testUtil.makeTx(testData.transaction, options.forkConfigVM) + block = testUtil.makeBlockFromEnv(testData.env) + tx._homestead = true + tx.enableHomestead = true + block.isHomestead = function() { + return true + } - if (!tx.validate()) { - return done() - } + if (!tx.validate()) { + return done() + } - if (options.jsontrace) { - vm.on('step', function (e) { - let hexStack = [] - hexStack = e.stack.map(item => { - return '0x' + new BN(item).toString(16, 0) - }) + if (options.jsontrace) { + vm.on('step', function(e) { + let hexStack = [] + hexStack = e.stack.map(item => { + return '0x' + new BN(item).toString(16, 0) + }) - var opTrace = { - 'pc': e.pc, - 'op': e.opcode.opcode, - 'gas': '0x' + e.gasLeft.toString('hex'), - 'gasCost': '0x' + e.opcode.fee.toString(16), - 'stack': hexStack, - 'depth': e.depth, - 'opName': e.opcode.name - } - - t.comment(JSON.stringify(opTrace)) - }) - vm.on('afterTx', function (results) { - let stateRoot = { - 'stateRoot': vm.stateManager._trie.root.toString('hex') - } - t.comment(JSON.stringify(stateRoot)) - }) - } + const opTrace = { + pc: e.pc, + op: e.opcode.opcode, + gas: '0x' + e.gasLeft.toString('hex'), + gasCost: '0x' + e.opcode.fee.toString(16), + stack: hexStack, + depth: e.depth, + opName: e.opcode.name, + } - vm.runTx({ tx: tx, block: block }) - .then(() => done()) - .catch((err) => { - // If tx is invalid and coinbase is empty, the test harness - // expects the coinbase account to be deleted from state. - // Without this ecmul_0-3_5616_28000_96 would fail. - vm.stateManager.getAccount(block.header.coinbase, function (err, account) { - if (err) { - done() - return + t.comment(JSON.stringify(opTrace)) + }) + vm.on('afterTx', () => { + let stateRoot = { + stateRoot: stateManager._trie.root.toString('hex'), } + t.comment(JSON.stringify(stateRoot)) + }) + } + + vm.runTx({ tx, block }) + .then(() => done()) + .catch(async err => { + // If tx is invalid and coinbase is empty, the test harness + // expects the coinbase account to be deleted from state. + // Without this ecmul_0-3_5616_28000_96 would fail. + const account = await stateManager.getAccount(block.header.coinbase) if (new BN(account.balance).isZero()) { - async.series([ - (cb) => vm.stateManager.putAccount(block.header.coinbase, new Account(), cb), - (cb) => vm.stateManager.cleanupTouchedAccounts(cb), - (cb) => vm.stateManager._cache.flush(cb) - ], (err) => { - err = null - done() - }) - } else { - done() + await stateManager.putAccount(block.header.coinbase, new Account()) + await stateManager.cleanupTouchedAccounts() + await stateManager._cache.flush() } + done() }) - }) - }, - function (done) { - if (testData.postStateRoot.substr(0, 2) === '0x') { - testData.postStateRoot = testData.postStateRoot.substr(2) - } - t.equal(state.root.toString('hex'), testData.postStateRoot, 'the state roots should match') + }, + async function(done) { + if (testData.postStateRoot.substr(0, 2) === '0x') { + testData.postStateRoot = testData.postStateRoot.substr(2) + } + t.equal( + stateManager._trie.root.toString('hex'), + testData.postStateRoot, + 'the state roots should match', + ) - if (state.root.toString('hex') !== testData.postStateRoot.toString('hex')) { - // since General State Tests, postState keys are no longer included in - // the state test format. only postStateRoot, so can't debug expected post conditions - // testUtil.verifyPostConditions(state, testData.post, t, done) - done() - } else { - done() - } - } - ], cb) + if (stateRoot.toString('hex') !== testData.postStateRoot.toString('hex')) { + // since General State Tests, postState keys are no longer included in + // the state test format. only postStateRoot, so can't debug expected post conditions + // testUtil.verifyPostConditions(state, testData.post, t, done) + done() + } else { + done() + } + }, + ], + cb, + ) } -module.exports = function runStateTest (options, testData, t, cb) { +module.exports = function runStateTest(options, testData, t, cb) { try { - const testCases = parseTestCases(options.forkConfigTestSuite, testData, options.data, options.gasLimit, options.value) + const testCases = parseTestCases( + options.forkConfigTestSuite, + testData, + options.data, + options.gasLimit, + options.value, + ) if (testCases.length > 0) { - async.eachSeries(testCases, - (testCase, done) => runTestCase(options, testCase, t, done), - cb) + async.eachSeries(testCases, (testCase, done) => runTestCase(options, testCase, t, done), cb) } else { t.comment(`No ${options.forkConfigTestSuite} post state defined, skip test`) cb() diff --git a/packages/vm/tests/api/events.js b/packages/vm/tests/api/events.js index 6cc86e776c5..cda81b5f363 100644 --- a/packages/vm/tests/api/events.js +++ b/packages/vm/tests/api/events.js @@ -5,7 +5,7 @@ const Block = require('ethereumjs-block') const VM = require('../../dist/index').default tape('VM events', t => { - t.test('should the Block before running it', async st => { + t.test('should emit the Block before running it', async st => { const vm = new VM() let emitted @@ -18,7 +18,7 @@ tape('VM events', t => { await vm.runBlock({ block, generate: true, - skipBlockValidation: true + skipBlockValidation: true, }) st.equal(emitted, block) @@ -39,7 +39,7 @@ tape('VM events', t => { await vm.runBlock({ block, generate: true, - skipBlockValidation: true + skipBlockValidation: true, }) st.deepEqual(emitted.receipts, []) @@ -76,7 +76,7 @@ tape('VM events', t => { const tx = new Transaction({ gas: 200000, to: '0x1111111111111111111111111111111111111111', - value: 1 + value: 1, }) tx.sign(util.toBuffer('0xa5737ecdc1b89ca0091647e727ba082ed8953f29182e94adc397210dda643b07')) await vm.runTx({ tx, skipBalance: true }) @@ -97,7 +97,7 @@ tape('VM events', t => { const tx = new Transaction({ gas: 200000, to: '0x1111111111111111111111111111111111111111', - value: 1 + value: 1, }) tx.sign(util.toBuffer('0xa5737ecdc1b89ca0091647e727ba082ed8953f29182e94adc397210dda643b07')) await vm.runTx({ tx, skipBalance: true }) @@ -119,7 +119,7 @@ tape('VM events', t => { const tx = new Transaction({ gas: 200000, to: '0x1111111111111111111111111111111111111111', - value: 1 + value: 1, }) tx.sign(util.toBuffer('0xa5737ecdc1b89ca0091647e727ba082ed8953f29182e94adc397210dda643b07')) await vm.runTx({ tx, skipBalance: true }) @@ -142,7 +142,7 @@ tape('VM events', t => { // This deploys a contract which a single byte of code, 0x41. const tx = new Transaction({ gas: 200000, - data: '0x7f410000000000000000000000000000000000000000000000000000000000000060005260016000f3' + data: '0x7f410000000000000000000000000000000000000000000000000000000000000060005260016000f3', }) tx.sign(util.toBuffer('0xa5737ecdc1b89ca0091647e727ba082ed8953f29182e94adc397210dda643b07')) await vm.runTx({ tx, skipBalance: true }) @@ -165,14 +165,14 @@ tape('VM events', t => { // This deploys a contract which a single byte of code, 0x41. const tx = new Transaction({ gas: 200000, - data: '0x7f410000000000000000000000000000000000000000000000000000000000000060005260016000f3' + data: '0x7f410000000000000000000000000000000000000000000000000000000000000060005260016000f3', }) tx.sign(util.toBuffer('0xa5737ecdc1b89ca0091647e727ba082ed8953f29182e94adc397210dda643b07')) await vm.runTx({ tx, skipBalance: true }) st.equal( util.bufferToHex(emitted.code), - '0x7f410000000000000000000000000000000000000000000000000000000000000060005260016000f3' + '0x7f410000000000000000000000000000000000000000000000000000000000000060005260016000f3', ) st.end() diff --git a/packages/vm/tests/api/index.js b/packages/vm/tests/api/index.js index ed934e82184..e4094a06ae0 100644 --- a/packages/vm/tests/api/index.js +++ b/packages/vm/tests/api/index.js @@ -1,5 +1,5 @@ -const promisify = require('util.promisify') const tape = require('tape') +const { promisify } = require('util') const util = require('ethereumjs-util') const Block = require('ethereumjs-block') const Common = require('ethereumjs-common').default @@ -9,28 +9,28 @@ const { setupVM } = require('./utils') const { setupPreConditions } = require('../util') const testData = require('./testdata.json') -tape('VM with default blockchain', (t) => { - t.test('should instantiate without params', (st) => { +tape('VM with default blockchain', t => { + t.test('should instantiate without params', st => { const vm = new VM() st.ok(vm.stateManager) st.deepEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has default trie') st.end() }) - t.test('should be able to activate precompiles', async (st) => { + t.test('should be able to activate precompiles', async st => { let vm = new VM({ activatePrecompiles: true }) await vm.init() st.notDeepEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has different root') st.end() }) - t.test('should instantiate with async constructor', async (st) => { + t.test('should instantiate with async constructor', async st => { let vm = await VM.create({ activatePrecompiles: true }) st.notDeepEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has different root') st.end() }) - t.test('should work with trie (state) provided', async (st) => { + t.test('should work with trie (state) provided', async st => { let trie = new Trie() trie.isTestTrie = true let vm = new VM({ state: trie, activatePrecompiles: true }) @@ -40,7 +40,7 @@ tape('VM with default blockchain', (t) => { st.end() }) - t.test('should only accept common or chain and fork', (st) => { + t.test('should only accept common or chain and fork', st => { const common = new Common('mainnet') st.throws(() => new VM({ chain: 'a', common })) @@ -50,7 +50,7 @@ tape('VM with default blockchain', (t) => { st.end() }) - t.test('should accept a common object as option', async (st) => { + t.test('should accept a common object as option', async st => { const common = new Common('mainnet', 'istanbul') const vm = new VM({ common }) @@ -60,7 +60,7 @@ tape('VM with default blockchain', (t) => { st.end() }) - t.test('should only accept valid chain and fork', async (st) => { + t.test('should only accept valid chain and fork', async st => { let vm = new VM({ chain: 'ropsten', hardfork: 'byzantium' }) await vm.init() st.equal(vm.stateManager._common.param('gasPrices', 'ecAdd'), 500) @@ -75,71 +75,73 @@ tape('VM with default blockchain', (t) => { st.end() }) - t.test('should run blockchain without blocks', async (st) => { + t.test('should run blockchain without blocks', async st => { const vm = new VM() await vm.runBlockchain() st.end() }) }) -tape('VM with blockchain', (t) => { - t.test('should instantiate', async (st) => { +tape('VM with blockchain', t => { + t.test('should instantiate', async st => { const vm = setupVM() await vm.init() st.deepEqual(vm.stateManager._trie.root, util.KECCAK256_RLP, 'it has default trie') st.end() }) - t.test('should run blockchain without blocks', async (st) => { + t.test('should run blockchain without blocks', async st => { const vm = setupVM() await vm.runBlockchain() st.end() }) - t.test('should run blockchain with mocked runBlock', async (st) => { + t.test('should run blockchain with mocked runBlock', async st => { const vm = setupVM({ chain: 'goerli' }) await vm.init() - const genesis = new Block(Buffer.from(testData.genesisRLP.slice(2), 'hex'), { common: vm._common }) - const block = new Block(Buffer.from(testData.blocks[0].rlp.slice(2), 'hex'), { common: vm._common }) + const genesis = new Block(Buffer.from(testData.genesisRLP.slice(2), 'hex'), { + common: vm._common, + }) + const block = new Block(Buffer.from(testData.blocks[0].rlp.slice(2), 'hex'), { + common: vm._common, + }) await putGenesisP(vm.blockchain, genesis) st.equal(vm.blockchain.meta.genesis.toString('hex'), testData.genesisBlockHeader.hash.slice(2)) await putBlockP(vm.blockchain, block) const head = await getHeadP(vm.blockchain) - st.equal( - head.hash().toString('hex'), - testData.blocks[0].blockHeader.hash.slice(2) - ) + st.equal(head.hash().toString('hex'), testData.blocks[0].blockHeader.hash.slice(2)) const setupPreP = promisify(setupPreConditions) await setupPreP(vm.stateManager._trie, testData) - vm.runBlock = (block) => new Promise((resolve, reject) => reject(new Error('test'))) + vm.runBlock = block => new Promise((resolve, reject) => reject(new Error('test'))) vm.runBlockchain() - .then(() => st.fail('it hasn\'t returned any errors')) - .catch((e) => { - st.equal(e.message, 'test', 'it has correctly propagated runBlock\'s error') + .then(() => st.fail("it hasn't returned any errors")) + .catch(e => { + st.equal(e.message, 'test', "it has correctly propagated runBlock's error") st.end() }) }) - t.test('should run blockchain with blocks', async (st) => { + t.test('should run blockchain with blocks', async st => { const vm = setupVM({ chain: 'goerli' }) await vm.init() - const genesis = new Block(Buffer.from(testData.genesisRLP.slice(2), 'hex'), { common: vm._common }) - const block = new Block(Buffer.from(testData.blocks[0].rlp.slice(2), 'hex'), { common: vm._common }) + const genesis = new Block(Buffer.from(testData.genesisRLP.slice(2), 'hex'), { + common: vm._common, + }) + const block = new Block(Buffer.from(testData.blocks[0].rlp.slice(2), 'hex'), { + common: vm._common, + }) await putGenesisP(vm.blockchain, genesis) st.equal(vm.blockchain.meta.genesis.toString('hex'), testData.genesisBlockHeader.hash.slice(2)) await putBlockP(vm.blockchain, block) const head = await getHeadP(vm.blockchain) - st.equal( - head.hash().toString('hex'), - testData.blocks[0].blockHeader.hash.slice(2) - ) + st.equal(head.hash().toString('hex'), testData.blocks[0].blockHeader.hash.slice(2)) const setupPreP = promisify(setupPreConditions) await setupPreP(vm.stateManager._trie, testData) @@ -149,7 +151,7 @@ tape('VM with blockchain', (t) => { st.end() }) - t.test('should pass the correct Common object when copying the VM', async (st) => { + t.test('should pass the correct Common object when copying the VM', async st => { const vm = setupVM({ chain: 'goerli', hardfork: 'byzantium' }) await vm.init() @@ -164,6 +166,7 @@ tape('VM with blockchain', (t) => { }) }) -const putGenesisP = (blockchain, genesis) => promisify(blockchain.putGenesis.bind(blockchain))(genesis) +const putGenesisP = (blockchain, genesis) => + promisify(blockchain.putGenesis.bind(blockchain))(genesis) const putBlockP = (blockchain, block) => promisify(blockchain.putBlock.bind(blockchain))(block) -const getHeadP = (blockchain) => promisify(blockchain.getHead.bind(blockchain))() +const getHeadP = blockchain => promisify(blockchain.getHead.bind(blockchain))() diff --git a/packages/vm/tests/api/istanbul/eip-1884.js b/packages/vm/tests/api/istanbul/eip-1884.js index 9bed7877cfb..9a256afeb51 100644 --- a/packages/vm/tests/api/istanbul/eip-1884.js +++ b/packages/vm/tests/api/istanbul/eip-1884.js @@ -2,38 +2,38 @@ const tape = require('tape') const BN = require('bn.js') const Common = require('ethereumjs-common').default const VM = require('../../../dist/index').default -const PStateManager = require('../../../dist/state/promisified').default const { ERROR } = require('../../../dist/exceptions') const { createAccount } = require('../utils') const testCases = [ { chain: 'mainnet', hardfork: 'istanbul', selfbalance: '0xf1' }, - { chain: 'mainnet', hardfork: 'constantinople', err: ERROR.INVALID_OPCODE } + { chain: 'mainnet', hardfork: 'constantinople', err: ERROR.INVALID_OPCODE }, ] // SELFBALANCE PUSH8 0x00 MSTORE8 PUSH8 0x01 PUSH8 0x00 RETURN const code = ['47', '60', '00', '53', '60', '01', '60', '00', 'f3'] -tape('Istanbul: EIP-1884: SELFBALANCE', async (t) => { +tape('Istanbul: EIP-1884: SELFBALANCE', async t => { const addr = Buffer.from('00000000000000000000000000000000000000ff', 'hex') const runCodeArgs = { code: Buffer.from(code.join(''), 'hex'), gasLimit: new BN(0xffff), - address: addr + address: addr, } - for (const testCase of testCases) { + for await (const testCase of testCases) { const common = new Common(testCase.chain, testCase.hardfork) const vm = new VM({ common }) - const state = new PStateManager(vm.stateManager) const account = createAccount('0x00', testCase.selfbalance) - await state.putAccount(addr, account) + await vm.stateManager.putAccount(addr, account) try { const res = await vm.runCode(runCodeArgs) if (testCase.err) { t.equal(res.exceptionError.error, testCase.err) } else { t.assert(res.exceptionError === undefined) - t.assert(new BN(Buffer.from(testCase.selfbalance.slice(2), 'hex')).eq(new BN(res.returnValue))) + t.assert( + new BN(Buffer.from(testCase.selfbalance.slice(2), 'hex')).eq(new BN(res.returnValue)), + ) } } catch (e) { t.fail(e.message) diff --git a/packages/vm/tests/api/istanbul/eip-2200.js b/packages/vm/tests/api/istanbul/eip-2200.js index 1cb085eda49..94f2a4feb1e 100644 --- a/packages/vm/tests/api/istanbul/eip-2200.js +++ b/packages/vm/tests/api/istanbul/eip-2200.js @@ -2,7 +2,6 @@ const tape = require('tape') const BN = require('bn.js') const Common = require('ethereumjs-common').default const VM = require('../../../dist/index').default -const PStateManager = require('../../../dist/state/promisified').default const { ERROR } = require('../../../dist/exceptions') const { createAccount } = require('../utils') @@ -24,30 +23,36 @@ const testCases = [ { original: new BN(1), code: '60016000556001600055', used: 1612, refund: 0 }, // 1 -> 1 -> 1 { original: new BN(0), code: '600160005560006000556001600055', used: 40818, refund: 19200 }, // 0 -> 1 -> 0 -> 1 { original: new BN(1), code: '600060005560016000556000600055', used: 10818, refund: 19200 }, // 1 -> 0 -> 1 -> 0 - { original: new BN(1), gas: new BN(2306), code: '6001600055', used: 2306, refund: 0, err: ERROR.OUT_OF_GAS }, // 1 -> 1 (2300 sentry + 2xPUSH) - { original: new BN(1), gas: new BN(2307), code: '6001600055', used: 806, refund: 0 } // 1 -> 1 (2301 sentry + 2xPUSH) + { + original: new BN(1), + gas: new BN(2306), + code: '6001600055', + used: 2306, + refund: 0, + err: ERROR.OUT_OF_GAS, + }, // 1 -> 1 (2300 sentry + 2xPUSH) + { original: new BN(1), gas: new BN(2307), code: '6001600055', used: 806, refund: 0 }, // 1 -> 1 (2301 sentry + 2xPUSH) ] -tape('Istanbul: EIP-2200: net-metering SSTORE', async (t) => { +tape('Istanbul: EIP-2200: net-metering SSTORE', async t => { const caller = Buffer.from('0000000000000000000000000000000000000000', 'hex') const addr = Buffer.from('00000000000000000000000000000000000000ff', 'hex') const key = new BN(0).toArrayLike(Buffer, 'be', 32) - for (const testCase of testCases) { + for await (const testCase of testCases) { const common = new Common('mainnet', 'istanbul') const vm = new VM({ common }) - const state = new PStateManager(vm.stateManager) const account = createAccount('0x00', '0x00') - await state.putAccount(addr, account) - await state.putContractCode(addr, Buffer.from(testCase.code, 'hex')) + await vm.stateManager.putAccount(addr, account) + await vm.stateManager.putContractCode(addr, Buffer.from(testCase.code, 'hex')) if (!testCase.original.isZero()) { - await state.putContractStorage(addr, key, testCase.original) + await vm.stateManager.putContractStorage(addr, key, testCase.original) } const runCallArgs = { caller, gasLimit: testCase.gas ? testCase.gas : new BN(0xffffffffff), - to: addr + to: addr, } try { diff --git a/packages/vm/tests/api/runBlock.js b/packages/vm/tests/api/runBlock.js index 7a375a0ab42..3d6e2385ef6 100644 --- a/packages/vm/tests/api/runBlock.js +++ b/packages/vm/tests/api/runBlock.js @@ -1,16 +1,15 @@ -const promisify = require('util.promisify') const tape = require('tape') +const { promisify } = require('util') const Block = require('ethereumjs-block') const Common = require('ethereumjs-common').default const util = require('ethereumjs-util') const runBlock = require('../../dist/runBlock').default -const PStateManager = require('../../dist/state/promisified').default const { StateManager } = require('../../dist/state') const testData = require('./testdata.json') const { setupVM } = require('./utils') const { setupPreConditions } = require('../util') -function setup (vm = null) { +function setup(vm = null) { // Create a mock, if no real VM object provided. // The mock includes mocked runTx and runCall which // always return an error. @@ -18,11 +17,10 @@ function setup (vm = null) { const stateManager = new StateManager() vm = { stateManager, - pStateManager: new PStateManager(stateManager), emit: (e, val, cb) => cb(), _emit: (e, val) => new Promise((resolve, reject) => resolve()), runTx: (opts) => new Promise((resolve, reject) => reject(new Error('test'))), - _common: new Common('mainnet', 'byzantium') + _common: new Common('mainnet', 'byzantium'), } } @@ -31,8 +29,8 @@ function setup (vm = null) { data: testData, p: { runBlock: runBlock.bind(vm), - putAccount: promisify(vm.stateManager.putAccount.bind(vm.stateManager)) - } + putAccount: vm.stateManager.putAccount.bind(vm.stateManager), + }, } } @@ -40,7 +38,8 @@ tape('runBlock', async (t) => { const suite = setup() t.test('should fail without params', async (st) => { - await suite.p.runBlock() + await suite.p + .runBlock() .then(() => st.fail('should have returned error')) .catch((e) => st.ok(e.message.includes('invalid input'), 'correct error')) @@ -48,7 +47,8 @@ tape('runBlock', async (t) => { }) t.test('should fail without opts', async (st) => { - await suite.p.runBlock({}) + await suite.p + .runBlock({}) .then(() => st.fail('should have returned error')) .catch((e) => st.ok(e.message.includes('invalid input'), 'correct error')) @@ -60,7 +60,8 @@ tape('runBlock', async (t) => { // The mocked VM uses a mocked runTx // which always returns an error. - await suite.p.runBlock({ block, skipBlockValidation: true }) + await suite.p + .runBlock({ block, skipBlockValidation: true }) .then(() => t.fail('should have returned error')) .catch((e) => t.equal(e.message, 'test')) @@ -74,10 +75,11 @@ tape('should fail when block gas limit higher than 2^63-1', async (t) => { const block = new Block({ header: { ...suite.data.blocks[0].header, - gasLimit: Buffer.from('8000000000000000', 16) - } + gasLimit: Buffer.from('8000000000000000', 16), + }, }) - await suite.p.runBlock({ block }) + await suite.p + .runBlock({ block }) .then(() => t.fail('should have returned error')) .catch((e) => t.ok(e.message.includes('Invalid block'))) @@ -90,7 +92,8 @@ tape('should fail when block validation fails', async (t) => { const block = new Block(util.rlp.decode(suite.data.blocks[0].rlp)) block.validate = (_, cb) => cb(new Error('test')) - await suite.p.runBlock({ block }) + await suite.p + .runBlock({ block }) .then(() => t.fail('should have returned error')) .catch((e) => t.ok(e.message.includes('test'))) @@ -103,7 +106,8 @@ tape('should fail when tx gas limit higher than block gas limit', async (t) => { const block = new Block(util.rlp.decode(suite.data.blocks[0].rlp)) block.transactions[0].gasLimit = Buffer.from('3fefba', 'hex') - await suite.p.runBlock({ block, skipBlockValidation: true }) + await suite.p + .runBlock({ block, skipBlockValidation: true }) .then(() => t.fail('should have returned error')) .catch((e) => t.ok(e.message.includes('higher gas limit'))) @@ -123,13 +127,21 @@ tape('should run valid block', async (t) => { t.equal( suite.vm.stateManager._trie.root.toString('hex'), genesis.header.stateRoot.toString('hex'), - 'genesis state root should match calculated state root' + 'genesis state root should match calculated state root', ) - let res = await suite.p.runBlock({ block, root: suite.vm.stateManager._trie.root, skipBlockValidation: true }) + let res = await suite.p.runBlock({ + block, + root: suite.vm.stateManager._trie.root, + skipBlockValidation: true, + }) - t.error(res.error, 'runBlock shouldn\'t have returned error') - t.equal(res.results[0].gasUsed.toString('hex'), '5208', 'actual gas used should equal blockHeader gasUsed') + t.error(res.error, "runBlock shouldn't have returned error") + t.equal( + res.results[0].gasUsed.toString('hex'), + '5208', + 'actual gas used should equal blockHeader gasUsed', + ) t.end() }) diff --git a/packages/vm/tests/api/runBlockchain.js b/packages/vm/tests/api/runBlockchain.js index fcbe85d275f..e34971614f6 100644 --- a/packages/vm/tests/api/runBlockchain.js +++ b/packages/vm/tests/api/runBlockchain.js @@ -1,12 +1,11 @@ const tape = require('tape') const level = require('level-mem') -const promisify = require('util.promisify') +const { promisify } = require('util') const Blockchain = require('ethereumjs-blockchain').default const Block = require('ethereumjs-block') const Common = require('ethereumjs-common').default const util = require('ethereumjs-util') const runBlockchain = require('../../dist/runBlockchain').default -const PStateManager = require('../../dist/state/promisified').default const { StateManager } = require('../../dist/state') const { createGenesis } = require('./utils') @@ -15,13 +14,12 @@ tape('runBlockchain', (t) => { const blockchain = new Blockchain({ db: blockchainDB, chain: 'goerli', - validate: false + validate: false, }) - const stateManager = new StateManager({ common: new Common('goerli') }); + const stateManager = new StateManager({ common: new Common('goerli') }) const vm = { stateManager, - pStateManager: new PStateManager(stateManager), - blockchain: blockchain + blockchain: blockchain, } const putGenesisP = promisify(blockchain.putGenesis.bind(blockchain)) @@ -51,13 +49,14 @@ tape('runBlockchain', (t) => { t.test('should run with valid and invalid blocks', async (st) => { // Produce error on the third time runBlock is called let runBlockInvocations = 0 - vm.runBlock = (opts) => new Promise((resolve, reject) => { - runBlockInvocations++ - if (runBlockInvocations === 3) { - return reject(new Error('test')) - } - resolve({}) - }) + vm.runBlock = (opts) => + new Promise((resolve, reject) => { + runBlockInvocations++ + if (runBlockInvocations === 3) { + return reject(new Error('test')) + } + resolve({}) + }) const genesis = createGenesis({ chain: 'goerli' }) await putGenesisP(genesis) @@ -89,7 +88,7 @@ tape('runBlockchain', (t) => { }) }) -function createBlock (parent = null, n = 0, opts = {}) { +function createBlock(parent = null, n = 0, opts = {}) { opts.chain = opts.chain ? opts.chain : 'mainnet' if (parent === null) { return createGenesis(opts) diff --git a/packages/vm/tests/api/runTx.js b/packages/vm/tests/api/runTx.js index 3640de96a9e..bcd0b8aa40a 100644 --- a/packages/vm/tests/api/runTx.js +++ b/packages/vm/tests/api/runTx.js @@ -1,66 +1,69 @@ -const promisify = require('util.promisify') const tape = require('tape') +const { promisify } = require('util') const Transaction = require('ethereumjs-tx').Transaction const ethUtil = require('ethereumjs-util') const runTx = require('../../dist/runTx').default -const PStateManager = require('../../dist/state/promisified').default const { StateManager } = require('../../dist/state') const VM = require('../../dist/index').default const { createAccount } = require('./utils') -function setup (vm = null) { +function setup(vm = null) { if (vm === null) { - const stateManager = new StateManager({ }) + const stateManager = new StateManager({}) vm = { stateManager, - pStateManager: new PStateManager(stateManager), - emit: (e, val, cb) => { cb() }, - _emit: (e, val) => new Promise((resolve, reject) => resolve()) + emit: (e, val, cb) => { + cb() + }, + _emit: (e, val) => new Promise((resolve, reject) => resolve()), } } return { vm, runTx: runTx.bind(vm), - putAccount: promisify(vm.stateManager.putAccount.bind(vm.stateManager)) + putAccount: vm.stateManager.putAccount.bind(vm.stateManager), } } -tape('runTx', (t) => { +tape('runTx', t => { const suite = setup() - t.test('should fail to run without opts', async (st) => { - shouldFail(st, suite.runTx(), - (e) => st.ok(e.message.includes('invalid input'), 'should fail with appropriate error') + t.test('should fail to run without opts', async st => { + shouldFail(st, suite.runTx(), e => + st.ok(e.message.includes('invalid input'), 'should fail with appropriate error'), ) st.end() }) - t.test('should fail to run without tx', async (st) => { - shouldFail(st, suite.runTx({}), - (e) => st.ok(e.message.includes('invalid input'), 'should fail with appropriate error') + t.test('should fail to run without tx', async st => { + shouldFail(st, suite.runTx({}), e => + st.ok(e.message.includes('invalid input'), 'should fail with appropriate error'), ) st.end() }) - t.test('should fail to run without signature', async (st) => { + t.test('should fail to run without signature', async st => { const tx = getTransaction(false, true) - shouldFail(st, suite.runTx({ tx }), - (e) => st.ok(e.message.toLowerCase().includes('signature'), 'should fail with appropriate error') + shouldFail(st, suite.runTx({ tx }), e => + st.ok(e.message.toLowerCase().includes('signature'), 'should fail with appropriate error'), ) st.end() }) - t.test('should fail without sufficient funds', async (st) => { + t.test('should fail without sufficient funds', async st => { const tx = getTransaction(true, true) - shouldFail(st, suite.runTx({ tx }), - (e) => st.ok(e.message.toLowerCase().includes('enough funds'), 'error should include "enough funds"') + shouldFail(st, suite.runTx({ tx }), e => + st.ok( + e.message.toLowerCase().includes('enough funds'), + 'error should include "enough funds"', + ), ) st.end() }) }) -tape('should run simple tx without errors', async (t) => { +tape('should run simple tx without errors', async t => { let vm = new VM() const suite = setup(vm) @@ -130,22 +133,31 @@ tape('should fail when account balance overflows (create)', async t => { t.end() }) */ -function shouldFail (st, p, onErr) { +function shouldFail(st, p, onErr) { p.then(() => st.fail('runTx didnt return any errors')).catch(onErr) } -function getTransaction (sign = false, calculageGas = false, value = '0x00', createContract = false) { +function getTransaction( + sign = false, + calculageGas = false, + value = '0x00', + createContract = false, +) { let to = '0x0000000000000000000000000000000000000000' let data = '0x7f7465737432000000000000000000000000000000000000000000000000000000600057' - if (createContract){ + if (createContract) { to = undefined - data = '0x6080604052348015600f57600080fd5b50603e80601d6000396000f3fe6080604052600080fdfea' + - '265627a7a723158204aed884a44fd1747efccba1447a2aa2d9a4b06dd6021c4a3bbb993021e0a909e' + - '64736f6c634300050f0032' + data = + '0x6080604052348015600f57600080fd5b50603e80601d6000396000f3fe6080604052600080fdfea' + + '265627a7a723158204aed884a44fd1747efccba1447a2aa2d9a4b06dd6021c4a3bbb993021e0a909e' + + '64736f6c634300050f0032' } - const privateKey = Buffer.from('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex') + const privateKey = Buffer.from( + 'e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', + 'hex', + ) const txParams = { nonce: '0x00', gasPrice: 100, @@ -153,7 +165,7 @@ function getTransaction (sign = false, calculageGas = false, value = '0x00', cre to: to, value: value, data: data, - chainId: 3 + chainId: 3, } const tx = new Transaction(txParams) diff --git a/packages/vm/tests/api/state/cache.js b/packages/vm/tests/api/state/cache.js index f504af72867..d90c2566865 100644 --- a/packages/vm/tests/api/state/cache.js +++ b/packages/vm/tests/api/state/cache.js @@ -1,79 +1,78 @@ -const promisify = require('util.promisify') const tape = require('tape') +const { promisify } = require('util') const Trie = require('merkle-patricia-tree/secure.js') const Account = require('ethereumjs-account').default const Cache = require('../../../dist/state/cache').default const utils = require('../utils') -tape('cache initialization', (t) => { - t.test('should initialize', async (st) => { +tape('cache initialization', t => { + t.test('should initialize', async st => { const trie = new Trie() - const c = new Cache(trie) - st.ok(trie.root.equals(c._trie.root), 'initializes given trie') + const cache = new Cache(trie) + st.ok(trie.root.equals(cache._trie.root), 'initializes given trie') st.end() }) }) -tape('cache put and get account', (t) => { +tape('cache put and get account', t => { const trie = new Trie() - const c = new Cache(trie) - const flushP = promisify(c.flush.bind(c)) + const cache = new Cache(trie) const trieGetP = promisify(trie.get.bind(trie)) const addr = Buffer.from('cd2a3d9f938e13cd947ec05abc7fe734df8dd826', 'hex') const acc = utils.createAccount('0x00', '0xff11') - t.test('should fail to get non-existent account', async (st) => { - const res = c.get(addr) + t.test('should fail to get non-existent account', async st => { + const res = cache.get(addr) st.notOk(res.balance.equals(acc.balance)) st.end() }) - t.test('should put account', async (st) => { - c.put(addr, acc) - const res = c.get(addr) + t.test('should put account', async st => { + cache.put(addr, acc) + const res = cache.get(addr) st.ok(res.balance.equals(acc.balance)) st.end() }) - t.test('should not have flushed to trie', async (st) => { + t.test('should not have flushed to trie', async st => { const res = await trieGetP(addr) st.notOk(res) st.end() }) - t.test('should flush to trie', async (st) => { - await flushP() + t.test('should flush to trie', async st => { + await cache.flush() st.end() }) - t.test('trie should contain flushed account', async (st) => { + t.test('trie should contain flushed account', async st => { const raw = await trieGetP(addr) const res = new Account(raw) st.ok(res.balance.equals(acc.balance)) st.end() }) - t.test('should delete account from cache', async (st) => { - c.del(addr) + t.test('should delete account from cache', async st => { + cache.del(addr) - const res = c.get(addr) + const res = cache.get(addr) st.notOk(res.balance.equals(acc.balance)) st.end() }) - t.test('should warm cache and load account from trie', async (st) => { - await promisify(c.warm.bind(c))([addr]) + t.test('should warm cache and load account from trie', async st => { + await cache.warm([addr]) - const res = c.get(addr) + const res = cache.get(addr) st.ok(res.balance.equals(acc.balance)) st.end() }) - t.test('should update loaded account and flush it', async (st) => { + t.test('should update loaded account and flush it', async st => { const updatedAcc = utils.createAccount('0x00', '0xff00') - c.put(addr, updatedAcc) - await flushP() + cache.put(addr, updatedAcc) + await cache.flush() const raw = await trieGetP(addr) const res = new Account(raw) @@ -82,25 +81,25 @@ tape('cache put and get account', (t) => { }) }) -tape('cache checkpointing', (t) => { +tape('cache checkpointing', t => { const trie = new Trie() - const c = new Cache(trie) + const cache = new Cache(trie) const addr = Buffer.from('cd2a3d9f938e13cd947ec05abc7fe734df8dd826', 'hex') const acc = utils.createAccount('0x00', '0xff11') const updatedAcc = utils.createAccount('0x00', '0xff00') - t.test('should revert to correct state', async (st) => { - c.put(addr, acc) - c.checkpoint() - c.put(addr, updatedAcc) + t.test('should revert to correct state', async st => { + cache.put(addr, acc) + cache.checkpoint() + cache.put(addr, updatedAcc) - let res = c.get(addr) + let res = cache.get(addr) st.ok(res.balance.equals(updatedAcc.balance)) - c.revert() + cache.revert() - res = c.get(addr) + res = cache.get(addr) st.ok(res.balance.equals(acc.balance)) st.end() diff --git a/packages/vm/tests/api/state/stateManager.js b/packages/vm/tests/api/state/stateManager.js index cf6032fceb1..fbf6fb6424f 100644 --- a/packages/vm/tests/api/state/stateManager.js +++ b/packages/vm/tests/api/state/stateManager.js @@ -1,23 +1,20 @@ -const promisify = require('util.promisify') const tape = require('tape') const { parallel } = require('async') -const util = require('ethereumjs-util') +const { toBuffer, keccak256, KECCAK256_RLP } = require('ethereumjs-util') const Common = require('ethereumjs-common').default const { StateManager } = require('../../../dist/state') const { createAccount } = require('../utils') const { isRunningInKarma } = require('../../util') tape('StateManager', t => { - t.test('should instantiate', st => { + t.test('should instantiate', async st => { const stateManager = new StateManager() - st.deepEqual(stateManager._trie.root, util.KECCAK256_RLP, 'it has default root') + st.deepEqual(stateManager._trie.root, KECCAK256_RLP, 'it has default root') st.equal(stateManager._common.hardfork(), 'petersburg', 'it has default hardfork') - stateManager.getStateRoot((err, res) => { - st.error(err, 'getStateRoot returns no error') - st.deepEqual(res, util.KECCAK256_RLP, 'it has default root') - st.end() - }) + const res = await stateManager.getStateRoot() + st.deepEqual(res, KECCAK256_RLP, 'it has default root') + st.end() }) t.test('should clear the cache when the state root is set', async st => { @@ -25,37 +22,28 @@ tape('StateManager', t => { const addressBuffer = Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') const account = createAccount() - const getStateRoot = promisify((...args) => stateManager.getStateRoot(...args)) - const checkpoint = promisify((...args) => stateManager.checkpoint(...args)) - const putAccount = promisify((...args) => stateManager.putAccount(...args)) - const getAccount = promisify((...args) => stateManager.getAccount(...args)) - const commit = promisify((...args) => stateManager.commit(...args)) - const setStateRoot = promisify((...args) => stateManager.setStateRoot(...args)) - const putContractStorage = promisify((...args) => stateManager.putContractStorage(...args)) - const getContractStorage = promisify((...args) => stateManager.getContractStorage(...args)) - // test account storage cache - const initialStateRoot = await getStateRoot() - await checkpoint() - await putAccount(addressBuffer, account) + const initialStateRoot = await stateManager.getStateRoot() + await stateManager.checkpoint() + await stateManager.putAccount(addressBuffer, account) - const account0 = await getAccount(addressBuffer) + const account0 = await stateManager.getAccount(addressBuffer) st.equal( account0.balance.toString('hex'), account.balance.toString('hex'), 'account value is set in the cache', ) - await commit() - const account1 = await getAccount(addressBuffer) + await stateManager.commit() + const account1 = await stateManager.getAccount(addressBuffer) st.equal( account1.balance.toString('hex'), account.balance.toString('hex'), 'account value is set in the state trie', ) - await setStateRoot(initialStateRoot) - const account2 = await getAccount(addressBuffer) + await stateManager.setStateRoot(initialStateRoot) + const account2 = await stateManager.getAccount(addressBuffer) st.equal( account2.balance.toString('hex'), '', @@ -63,21 +51,21 @@ tape('StateManager', t => { ) // test contract storage cache - await checkpoint() - const key = util.toBuffer('0x1234567890123456789012345678901234567890123456789012345678901234') + await stateManager.checkpoint() + const key = toBuffer('0x1234567890123456789012345678901234567890123456789012345678901234') const value = Buffer.from('0x1234') - await putContractStorage(addressBuffer, key, value) + await stateManager.putContractStorage(addressBuffer, key, value) - const contract0 = await getContractStorage(addressBuffer, key) + const contract0 = await stateManager.getContractStorage(addressBuffer, key) st.equal( contract0.toString('hex'), value.toString('hex'), "contract key's value is set in the _storageTries cache", ) - await commit() - await setStateRoot(initialStateRoot) - const contract1 = await getContractStorage(addressBuffer, key) + await stateManager.commit() + await stateManager.setStateRoot(initialStateRoot) + const contract1 = await stateManager.getContractStorage(addressBuffer, key) st.equal( contract1.toString('hex'), '', @@ -93,22 +81,15 @@ tape('StateManager', t => { const stateManager = new StateManager() const account = createAccount() - await promisify(stateManager.putAccount.bind(stateManager))( - 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b', - account, - ) + await stateManager.putAccount('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', account) - let res = await promisify(stateManager.getAccount.bind(stateManager))( - 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b', - ) + let res = await stateManager.getAccount('a94f5374fce5edbc8e2a8697c15331677e6ebf0b') st.equal(res.balance.toString('hex'), 'fff384') stateManager._cache.clear() - res = await promisify(stateManager.getAccount.bind(stateManager))( - 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b', - ) + res = await stateManager.getAccount('a94f5374fce5edbc8e2a8697c15331677e6ebf0b') st.equal(stateManager._cache._cache.keys[0], 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b') @@ -121,13 +102,7 @@ tape('StateManager', t => { async st => { const stateManager = new StateManager() - const promisifiedAccountIsEmpty = promisify( - stateManager.accountIsEmpty.bind(stateManager), - function(err, result) { - return err || result - }, - ) - let res = await promisifiedAccountIsEmpty('a94f5374fce5edbc8e2a8697c15331677e6ebf0b') + let res = await stateManager.accountIsEmpty('a94f5374fce5edbc8e2a8697c15331677e6ebf0b') st.ok(res) @@ -141,18 +116,9 @@ tape('StateManager', t => { const stateManager = new StateManager() const account = createAccount('0x1', '0x1') - await promisify(stateManager.putAccount.bind(stateManager))( - 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b', - account, - ) + await stateManager.putAccount('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', account) - const promisifiedAccountIsEmpty = promisify( - stateManager.accountIsEmpty.bind(stateManager), - function(err, result) { - return err || result - }, - ) - let res = await promisifiedAccountIsEmpty('a94f5374fce5edbc8e2a8697c15331677e6ebf0b') + let res = await stateManager.accountIsEmpty('a94f5374fce5edbc8e2a8697c15331677e6ebf0b') st.notOk(res) @@ -174,13 +140,8 @@ tape('StateManager', t => { ) const stateManager = new StateManager() - const generateCanonicalGenesis = promisify((...args) => - stateManager.generateCanonicalGenesis(...args), - ) - const getStateRoot = promisify((...args) => stateManager.getStateRoot(...args)) - - await generateCanonicalGenesis() - let stateRoot = await getStateRoot() + await stateManager.generateCanonicalGenesis() + let stateRoot = await stateManager.getStateRoot() st.equals( stateRoot.toString('hex'), genesisData.genesis_state_root, @@ -193,13 +154,8 @@ tape('StateManager', t => { const expectedStateRoot = Buffer.from(common.genesis().stateRoot.slice(2), 'hex') const stateManager = new StateManager({ common: common }) - const generateCanonicalGenesis = promisify((...args) => - stateManager.generateCanonicalGenesis(...args), - ) - const getStateRoot = promisify((...args) => stateManager.getStateRoot(...args)) - - await generateCanonicalGenesis() - let stateRoot = await getStateRoot() + await stateManager.generateCanonicalGenesis() + let stateRoot = await stateManager.getStateRoot() st.true( stateRoot.equals(expectedStateRoot), @@ -214,25 +170,20 @@ tape('StateManager', t => { t.test('should generate the genesis state root correctly for all other chains', async st => { const chains = ['ropsten', 'rinkeby', 'kovan', 'goerli'] - for (const chain of chains) { + + for await (const chain of chains) { const common = new Common(chain, 'petersburg') const expectedStateRoot = Buffer.from(common.genesis().stateRoot.slice(2), 'hex') const stateManager = new StateManager({ common: common }) - const generateCanonicalGenesis = promisify((...args) => - stateManager.generateCanonicalGenesis(...args), - ) - const getStateRoot = promisify((...args) => stateManager.getStateRoot(...args)) - - await generateCanonicalGenesis() - let stateRoot = await getStateRoot() + await stateManager.generateCanonicalGenesis() + let stateRoot = await stateManager.getStateRoot() st.true( stateRoot.equals(expectedStateRoot), `generateCanonicalGenesis should produce correct state root for ${chain}`, ) } - st.end() }) @@ -241,23 +192,17 @@ tape('StateManager', t => { const addressBuffer = Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') const account = createAccount() - const putContractStorage = promisify((...args) => stateManager.putContractStorage(...args)) - - await promisify(stateManager.putAccount.bind(stateManager))( - 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b', - account, - ) + await stateManager.putAccount('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', account) - const key = util.toBuffer('0x1234567890123456789012345678901234567890123456789012345678901234') - const value = util.toBuffer('0x0a') // We used this value as its RLP encoding is also 0a - await putContractStorage(addressBuffer, key, value) + const key = toBuffer('0x1234567890123456789012345678901234567890123456789012345678901234') + const value = toBuffer('0x0a') // We used this value as its RLP encoding is also 0a + await stateManager.putContractStorage(addressBuffer, key, value) - stateManager.dumpStorage(addressBuffer, data => { - const expect = { [util.keccak256(key).toString('hex')]: '0a' } - st.deepEqual(data, expect, 'should dump storage value') + const data = await stateManager.dumpStorage(addressBuffer) + const expect = { [keccak256(key).toString('hex')]: '0a' } + st.deepEqual(data, expect, 'should dump storage value') - st.end() - }) + st.end() }) t.test('should pass Common object when copying the state manager', st => { @@ -278,9 +223,8 @@ tape('StateManager', t => { t.test("should validate the key's length when modifying a contract's storage", async st => { const stateManager = new StateManager() const addressBuffer = Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') - const putContractStorage = promisify((...args) => stateManager.putContractStorage(...args)) try { - await putContractStorage(addressBuffer, Buffer.alloc(12), util.toBuffer('0x1231')) + await stateManager.putContractStorage(addressBuffer, Buffer.alloc(12), toBuffer('0x1231')) } catch (e) { st.equal(e.message, 'Storage key must be 32 bytes long') st.end() @@ -294,9 +238,8 @@ tape('StateManager', t => { t.test("should validate the key's length when reading a contract's storage", async st => { const stateManager = new StateManager() const addressBuffer = Buffer.from('a94f5374fce5edbc8e2a8697c15331677e6ebf0b', 'hex') - const getContractStorage = promisify((...args) => stateManager.getContractStorage(...args)) try { - await getContractStorage(addressBuffer, Buffer.alloc(12)) + await stateManager.getContractStorage(addressBuffer, Buffer.alloc(12)) } catch (e) { st.equal(e.message, 'Storage key must be 32 bytes long') st.end() @@ -311,26 +254,19 @@ tape('StateManager', t => { tape('Original storage cache', async t => { const stateManager = new StateManager() - const putAccount = promisify(stateManager.putAccount.bind(stateManager)) - const putContractStorage = promisify(stateManager.putContractStorage.bind(stateManager)) - const getContractStorage = promisify(stateManager.getContractStorage.bind(stateManager)) - const getOriginalContractStorage = promisify( - stateManager.getOriginalContractStorage.bind(stateManager), - ) - const address = 'a94f5374fce5edbc8e2a8697c15331677e6ebf0b' const addressBuffer = Buffer.from(address, 'hex') const account = createAccount() - await putAccount(address, account) + await stateManager.putAccount(address, account) const key = Buffer.from('1234567890123456789012345678901234567890123456789012345678901234', 'hex') const value = Buffer.from('1234', 'hex') t.test('should initially have empty storage value', async st => { - const res = await getContractStorage(addressBuffer, key) + const res = await stateManager.getContractStorage(addressBuffer, key) st.deepEqual(res, Buffer.alloc(0)) - const origRes = await getOriginalContractStorage(addressBuffer, key) + const origRes = await stateManager.getOriginalContractStorage(addressBuffer, key) st.deepEqual(origRes, Buffer.alloc(0)) stateManager._clearOriginalStorageCache() @@ -339,26 +275,26 @@ tape('Original storage cache', async t => { }) t.test('should set original storage value', async st => { - await putContractStorage(addressBuffer, key, value) - const res = await getContractStorage(addressBuffer, key) + await stateManager.putContractStorage(addressBuffer, key, value) + const res = await stateManager.getContractStorage(addressBuffer, key) st.deepEqual(res, value) st.end() }) t.test('should get original storage value', async st => { - const res = await getOriginalContractStorage(addressBuffer, key) + const res = await stateManager.getOriginalContractStorage(addressBuffer, key) st.deepEqual(res, value) st.end() }) t.test('should return correct original value after modification', async st => { const newValue = Buffer.from('1235', 'hex') - await putContractStorage(addressBuffer, key, newValue) - const res = await getContractStorage(addressBuffer, key) + await stateManager.putContractStorage(addressBuffer, key, newValue) + const res = await stateManager.getContractStorage(addressBuffer, key) st.deepEqual(res, newValue) - const origRes = await getOriginalContractStorage(addressBuffer, key) + const origRes = await stateManager.getOriginalContractStorage(addressBuffer, key) st.deepEqual(origRes, value) st.end() }) @@ -370,24 +306,24 @@ tape('Original storage cache', async t => { ) const value2 = Buffer.from('12', 'hex') const value3 = Buffer.from('123', 'hex') - await putContractStorage(addressBuffer, key2, value2) + await stateManager.putContractStorage(addressBuffer, key2, value2) - let res = await getContractStorage(addressBuffer, key2) + let res = await stateManager.getContractStorage(addressBuffer, key2) st.deepEqual(res, value2) - let origRes = await getOriginalContractStorage(addressBuffer, key2) + let origRes = await stateManager.getOriginalContractStorage(addressBuffer, key2) st.deepEqual(origRes, value2) - await putContractStorage(addressBuffer, key2, value3) + await stateManager.putContractStorage(addressBuffer, key2, value3) - res = await getContractStorage(addressBuffer, key2) + res = await stateManager.getContractStorage(addressBuffer, key2) st.deepEqual(res, value3) - origRes = await getOriginalContractStorage(addressBuffer, key2) + origRes = await stateManager.getOriginalContractStorage(addressBuffer, key2) st.deepEqual(origRes, value2) // Check previous key - res = await getContractStorage(addressBuffer, key) + res = await stateManager.getContractStorage(addressBuffer, key) st.deepEqual(res, Buffer.from('1235', 'hex')) - origRes = await getOriginalContractStorage(addressBuffer, key) + origRes = await stateManager.getOriginalContractStorage(addressBuffer, key) st.deepEqual(origRes, value) st.end() @@ -395,7 +331,7 @@ tape('Original storage cache', async t => { t.test("getOriginalContractStorage should validate the key's length", async st => { try { - await getOriginalContractStorage(addressBuffer, Buffer.alloc(12)) + await stateManager.getOriginalContractStorage(addressBuffer, Buffer.alloc(12)) } catch (e) { st.equal(e.message, 'Storage key must be 32 bytes long') st.end() diff --git a/packages/vm/tests/util.js b/packages/vm/tests/util.js index 2b367d4f63e..68f0df8fd80 100644 --- a/packages/vm/tests/util.js +++ b/packages/vm/tests/util.js @@ -366,19 +366,19 @@ exports.makeRunCodeData = function(exec, account, block) { * @param {Function} done - callback when function is completed */ exports.setupPreConditions = function(state, testData, done) { - var keysOfPre = Object.keys(testData.pre) + const keysOfPre = Object.keys(testData.pre) async.eachSeries( keysOfPre, function(key, callback) { - var acctData = testData.pre[key] - var account = new Account() + const acctData = testData.pre[key] + const account = new Account() account.nonce = format(acctData.nonce) account.balance = format(acctData.balance) - var codeBuf = Buffer.from(acctData.code.slice(2), 'hex') - var storageTrie = state.copy() + const codeBuf = Buffer.from(acctData.code.slice(2), 'hex') + const storageTrie = state.copy() storageTrie.root = null async.series( diff --git a/packages/vm/typedoc.js b/packages/vm/typedoc.js index 4f2fe818441..3295d6020d4 100644 --- a/packages/vm/typedoc.js +++ b/packages/vm/typedoc.js @@ -18,7 +18,6 @@ module.exports = { 'lib/evm/stack.ts', 'lib/evm/txContext.ts', 'lib/state/cache.ts', - 'lib/state/promisified.ts', ], excludeNotExported: true, excludePrivate: true,