Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
B
baas-ide
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
guxukai
baas-ide
Commits
d839c519
Commit
d839c519
authored
May 03, 2021
by
yann300
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix vmContext & txRunnerVM
parent
7abd9e50
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
125 additions
and
211 deletions
+125
-211
execution-context.js
apps/remix-ide/src/blockchain/execution-context.js
+0
-112
txRunnerVM.ts
libs/remix-lib/src/execution/txRunnerVM.ts
+49
-47
transactions.ts
libs/remix-simulator/src/methods/transactions.ts
+1
-1
vm-context.ts
libs/remix-simulator/src/vm-context.ts
+75
-51
No files found.
apps/remix-ide/src/blockchain/execution-context.js
View file @
d839c519
...
...
@@ -2,11 +2,6 @@
'use strict'
import
Web3
from
'web3'
import
EventManager
from
'../lib/events'
import
{
rlp
,
keccak
,
bufferToHex
}
from
'ethereumjs-util'
import
{
Web3VmProvider
}
from
'../web3Provider/web3VmProvider'
import
VM
from
'@ethereumjs/vm'
import
Common
from
'@ethereumjs/common'
import
StateManager
from
'@ethereumjs/vm/dist/state/stateManager'
let
web3
...
...
@@ -18,82 +13,6 @@ if (typeof window !== 'undefined' && typeof window.ethereum !== 'undefined') {
}
/*
extend vm state manager and instanciate VM
*/
class
StateManagerCommonStorageDump
extends
StateManager
{
constructor
()
{
super
()
/*
* dictionary containing keccak(b) as key and b as value. used to get the initial value from its hash.
* type: { [key: string]: string }
*/
this
.
keyHashes
=
{}
}
putContractStorage
(
address
,
key
,
value
)
{
this
.
keyHashes
[
keccak
(
key
).
toString
(
'hex'
)]
=
bufferToHex
(
key
)
return
super
.
putContractStorage
(
address
,
key
,
value
)
}
async
dumpStorage
(
address
)
{
let
trie
try
{
trie
=
await
this
.
_getStorageTrie
(
address
)
}
catch
(
e
)
{
console
.
log
(
e
)
throw
e
}
return
new
Promise
((
resolve
,
reject
)
=>
{
try
{
const
storage
=
{}
const
stream
=
trie
.
createReadStream
()
stream
.
on
(
'data'
,
(
val
)
=>
{
const
value
=
rlp
.
decode
(
val
.
value
)
storage
[
'0x'
+
val
.
key
.
toString
(
'hex'
)]
=
{
key
:
this
.
keyHashes
[
val
.
key
.
toString
(
'hex'
)],
value
:
'0x'
+
value
.
toString
(
'hex'
)
}
})
stream
.
on
(
'end'
,
function
()
{
resolve
(
storage
)
})
}
catch
(
e
)
{
reject
(
e
)
}
})
}
async
getStateRoot
(
force
=
false
)
{
await
this
.
_cache
.
flush
()
const
stateRoot
=
this
.
_trie
.
root
return
stateRoot
}
async
setStateRoot
(
stateRoot
)
{
await
this
.
_cache
.
flush
()
if
(
stateRoot
===
this
.
_trie
.
EMPTY_TRIE_ROOT
)
{
this
.
_trie
.
root
=
stateRoot
this
.
_cache
.
clear
()
this
.
_storageTries
=
{}
return
}
const
hasRoot
=
await
this
.
_trie
.
checkRoot
(
stateRoot
)
if
(
!
hasRoot
)
{
throw
new
Error
(
'State trie does not contain state root'
)
}
this
.
_trie
.
root
=
stateRoot
this
.
_cache
.
clear
()
this
.
_storageTries
=
{}
}
}
/*
trigger contextChanged, web3EndpointChanged
*/
export
class
ExecutionContext
{
...
...
@@ -103,15 +22,6 @@ export class ExecutionContext {
this
.
blockGasLimitDefault
=
4300000
this
.
blockGasLimit
=
this
.
blockGasLimitDefault
this
.
currentFork
=
'berlin'
this
.
vms
=
{
/*
byzantium: createVm('byzantium'),
constantinople: createVm('constantinople'),
petersburg: createVm('petersburg'),
istanbul: createVm('istanbul'),
*/
berlin
:
this
.
createVm
(
'berlin'
)
}
this
.
mainNetGenesisHash
=
'0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3'
this
.
customNetWorks
=
{}
this
.
blocks
=
{}
...
...
@@ -129,20 +39,6 @@ export class ExecutionContext {
}
}
createVm
(
hardfork
)
{
const
stateManager
=
new
StateManagerCommonStorageDump
()
const
common
=
new
Common
({
chain
:
'mainnet'
,
hardfork
})
const
vm
=
new
VM
({
common
,
activatePrecompiles
:
true
,
stateManager
:
stateManager
})
const
web3vm
=
new
Web3VmProvider
()
web3vm
.
setVM
(
vm
)
return
{
vm
,
web3vm
,
stateManager
,
common
}
}
askPermission
()
{
// metamask
if
(
ethereum
&&
typeof
ethereum
.
enable
===
'function'
)
ethereum
.
enable
()
...
...
@@ -217,14 +113,6 @@ export class ExecutionContext {
return
new
Web3
()
}
vm
()
{
return
this
.
vms
[
this
.
currentFork
].
vm
}
vmObject
()
{
return
this
.
vms
[
this
.
currentFork
]
}
setContext
(
context
,
endPointUrl
,
confirmCb
,
infoCb
)
{
this
.
executionContext
=
context
this
.
executionContextChange
(
context
,
endPointUrl
,
confirmCb
,
infoCb
,
null
)
...
...
libs/remix-lib/src/execution/txRunnerVM.ts
View file @
d839c519
'use strict'
import
{
Transaction
}
from
'
ethereumjs-
tx'
import
Block
from
'ethereumjs-
block'
import
{
BN
,
bufferToHex
}
from
'ethereumjs-util'
import
{
Transaction
}
from
'
@ethereumjs/
tx'
import
{
Block
}
from
'@ethereumjs/
block'
import
{
BN
,
bufferToHex
,
Address
}
from
'ethereumjs-util'
import
{
EventManager
}
from
'../eventManager'
import
{
LogsManager
}
from
'./logsManager'
export
class
TxRunnerVM
{
event
_api
blockNumber
runAsync
pendingTxs
...
...
@@ -16,14 +15,15 @@ export class TxRunnerVM {
blocks
txs
logsManager
getVM
:
()
=>
any
commonContext
getVMObject
:
()
=>
any
constructor
(
vmaccounts
,
api
,
getVM
)
{
constructor
(
vmaccounts
,
api
,
getVM
Object
)
{
this
.
event
=
new
EventManager
()
this
.
logsManager
=
new
LogsManager
()
// has a default for now for backwards compatability
this
.
getVM
=
getVM
this
.
_api
=
api
this
.
getVM
Object
=
getVMObject
this
.
commonContext
=
this
.
getVMObject
().
common
this
.
blockNumber
=
0
this
.
runAsync
=
true
this
.
blockNumber
=
0
// The VM is running in Homestead mode, which started at this block.
...
...
@@ -53,54 +53,56 @@ export class TxRunnerVM {
if
(
!
account
)
{
return
callback
(
'Invalid account selected'
)
}
if
(
Number
.
isInteger
(
gasLimit
))
{
gasLimit
=
'0x'
+
gasLimit
.
toString
(
16
)
}
this
.
getVMObject
().
stateManager
.
getAccount
(
Address
.
fromString
(
from
)).
then
((
res
)
=>
{
// See https://github.com/ethereumjs/ethereumjs-tx/blob/master/docs/classes/transaction.md#constructor
// for initialization fields and their types
value
=
value
?
parseInt
(
value
)
:
0
const
tx
=
Transaction
.
fromTxData
({
nonce
:
new
BN
(
res
.
nonce
),
gasPrice
:
'0x1'
,
gasLimit
:
gasLimit
,
to
:
to
,
value
:
value
,
data
:
Buffer
.
from
(
data
.
slice
(
2
),
'hex'
)
},
{
common
:
this
.
commonContext
}).
sign
(
account
.
privateKey
)
const
coinbases
=
[
'0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a'
,
'0x8945a1288dc78a6d8952a92c77aee6730b414778'
,
'0x94d76e24f818426ae84aa404140e8d5f60e10e7e'
]
const
difficulties
=
[
new
BN
(
'69762765929000'
,
10
),
new
BN
(
'70762765929000'
,
10
),
new
BN
(
'71762765929000'
,
10
)]
var
block
=
Block
.
fromBlockData
({
header
:
{
timestamp
:
timestamp
||
(
new
Date
().
getTime
()
/
1000
|
0
),
number
:
self
.
blockNumber
,
coinbase
:
coinbases
[
self
.
blockNumber
%
coinbases
.
length
],
difficulty
:
difficulties
[
self
.
blockNumber
%
difficulties
.
length
],
gasLimit
:
new
BN
(
gasLimit
.
replace
(
'0x'
,
''
),
16
).
imuln
(
2
)
},
transactions
:
[
tx
]
},
{
common
:
this
.
commonContext
})
this
.
getVM
().
stateManager
.
getAccount
(
Buffer
.
from
(
from
.
replace
(
'0x'
,
''
),
'hex'
),
(
err
,
res
)
=>
{
if
(
err
)
{
callback
(
'Account not found'
)
if
(
!
useCall
)
{
++
self
.
blockNumber
this
.
runBlockInVm
(
tx
,
block
,
callback
)
}
else
{
// See https://github.com/ethereumjs/ethereumjs-tx/blob/master/docs/classes/transaction.md#constructor
// for initialization fields and their types
value
=
value
?
parseInt
(
value
)
:
0
const
tx
=
new
Transaction
({
nonce
:
new
BN
(
res
.
nonce
),
gasPrice
:
'0x1'
,
gasLimit
:
gasLimit
,
to
:
to
,
value
:
value
,
data
:
Buffer
.
from
(
data
.
slice
(
2
),
'hex'
)
})
tx
.
sign
(
account
.
privateKey
)
const
coinbases
=
[
'0x0e9281e9c6a0808672eaba6bd1220e144c9bb07a'
,
'0x8945a1288dc78a6d8952a92c77aee6730b414778'
,
'0x94d76e24f818426ae84aa404140e8d5f60e10e7e'
]
const
difficulties
=
[
new
BN
(
'69762765929000'
,
10
),
new
BN
(
'70762765929000'
,
10
),
new
BN
(
'71762765929000'
,
10
)]
const
block
=
new
Block
({
header
:
{
timestamp
:
timestamp
||
(
new
Date
().
getTime
()
/
1000
|
0
),
number
:
self
.
blockNumber
,
coinbase
:
coinbases
[
self
.
blockNumber
%
coinbases
.
length
],
difficulty
:
difficulties
[
self
.
blockNumber
%
difficulties
.
length
],
gasLimit
:
new
BN
(
gasLimit
,
10
).
imuln
(
2
)
},
transactions
:
[
tx
],
uncleHeaders
:
[]
})
if
(
!
useCall
)
{
++
self
.
blockNumber
this
.
runBlockInVm
(
tx
,
block
,
callback
)
}
else
{
this
.
getVM
().
stateManager
.
checkpoint
(()
=>
{
this
.
runBlockInVm
(
tx
,
block
,
(
err
,
result
)
=>
{
this
.
getVM
().
stateManager
.
revert
(()
=>
{
callback
(
err
,
result
)
})
this
.
getVMObject
().
stateManager
.
checkpoint
().
then
(()
=>
{
this
.
runBlockInVm
(
tx
,
block
,
(
err
,
result
)
=>
{
this
.
getVMObject
().
stateManager
.
revert
().
then
(()
=>
{
callback
(
err
,
result
)
})
})
}
}
)
}
}).
catch
((
e
)
=>
{
callback
(
e
)
})
}
runBlockInVm
(
tx
,
block
,
callback
)
{
this
.
getVM
()
.
runBlock
({
block
:
block
,
generate
:
true
,
skipBlockValidation
:
true
,
skipBalance
:
false
}).
then
((
results
)
=>
{
this
.
getVM
Object
().
vm
.
runBlock
({
block
:
block
,
generate
:
true
,
skipBlockValidation
:
true
,
skipBalance
:
false
}).
then
((
results
)
=>
{
const
result
=
results
.
results
[
0
]
if
(
result
)
{
const
status
=
result
.
execResult
.
exceptionError
?
0
:
1
...
...
libs/remix-simulator/src/methods/transactions.ts
View file @
d839c519
...
...
@@ -40,7 +40,7 @@ export class Transactions {
}
}
this
.
txRunnerVMInstance
=
new
TxRunnerVM
(
accounts
,
api
,
_
=>
this
.
vmContext
.
vm
())
this
.
txRunnerVMInstance
=
new
TxRunnerVM
(
accounts
,
api
,
_
=>
this
.
vmContext
.
vm
Object
())
this
.
txRunnerInstance
=
new
TxRunner
(
this
.
txRunnerVMInstance
,
{
runAsync
:
false
})
this
.
txRunnerInstance
.
vmaccounts
=
accounts
}
...
...
libs/remix-simulator/src/vm-context.ts
View file @
d839c519
...
...
@@ -2,61 +2,82 @@
'use strict'
import
Web3
from
'web3'
import
{
rlp
,
keccak
,
bufferToHex
}
from
'ethereumjs-util'
import
{
vm
,
execution
}
from
'@remix-project/remix-lib'
const
EthJSVM
=
require
(
'ethereumjs-vm'
).
default
const
StateManager
=
require
(
'ethereumjs-vm/dist/state/stateManager'
).
default
import
{
vm
as
remixLibVm
,
execution
}
from
'@remix-project/remix-lib'
import
VM
from
'@ethereumjs/vm'
import
Common
from
'@ethereumjs/common'
import
StateManager
from
'@ethereumjs/vm/dist/state/stateManager'
import
{
StorageDump
}
from
'@ethereumjs/vm/dist/state/interface'
/*
extend vm state manager and instanciate VM
*/
class
StateManagerCommonStorageDump
extends
StateManager
{
constructor
(
arg
)
{
super
(
arg
)
keyHashes
:
{
[
key
:
string
]:
string
}
constructor
()
{
super
()
this
.
keyHashes
=
{}
}
putContractStorage
(
address
,
key
,
value
,
cb
)
{
putContractStorage
(
address
,
key
,
value
)
{
this
.
keyHashes
[
keccak
(
key
).
toString
(
'hex'
)]
=
bufferToHex
(
key
)
super
.
putContractStorage
(
address
,
key
,
value
,
cb
)
return
super
.
putContractStorage
(
address
,
key
,
value
)
}
dumpStorage
(
address
,
cb
)
{
this
.
_getStorageTrie
(
address
,
(
err
,
trie
)
=>
{
if
(
err
)
{
return
cb
(
err
)
async
dumpStorage
(
address
)
{
let
trie
try
{
trie
=
await
this
.
_getStorageTrie
(
address
)
}
catch
(
e
)
{
console
.
log
(
e
)
throw
e
}
return
new
Promise
<
StorageDump
>
((
resolve
,
reject
)
=>
{
try
{
const
storage
=
{}
const
stream
=
trie
.
createReadStream
()
stream
.
on
(
'data'
,
(
val
)
=>
{
const
value
=
rlp
.
decode
(
val
.
value
)
storage
[
'0x'
+
val
.
key
.
toString
(
'hex'
)]
=
{
key
:
this
.
keyHashes
[
val
.
key
.
toString
(
'hex'
)],
value
:
'0x'
+
value
.
toString
(
'hex'
)
}
})
stream
.
on
(
'end'
,
function
()
{
resolve
(
storage
)
})
}
catch
(
e
)
{
reject
(
e
)
}
const
storage
=
{}
const
stream
=
trie
.
createReadStream
()
stream
.
on
(
'data'
,
(
val
)
=>
{
const
value
=
rlp
.
decode
(
val
.
value
)
storage
[
'0x'
+
val
.
key
.
toString
(
'hex'
)]
=
{
key
:
this
.
keyHashes
[
val
.
key
.
toString
(
'hex'
)],
value
:
'0x'
+
value
.
toString
(
'hex'
)
}
})
stream
.
on
(
'end'
,
function
()
{
cb
(
storage
)
})
})
}
getStateRoot
(
cb
)
{
const
checkpoint
=
this
.
_checkpointCount
this
.
_checkpointCount
=
0
super
.
getStateRoot
((
err
,
stateRoot
)
=>
{
this
.
_checkpointCount
=
checkpoint
cb
(
err
,
stateRoot
)
})
async
getStateRoot
(
force
=
false
)
{
await
this
.
_cache
.
flush
()
const
stateRoot
=
this
.
_trie
.
root
return
stateRoot
}
setStateRoot
(
stateRoot
,
cb
)
{
const
checkpoint
=
this
.
_checkpointCount
this
.
_checkpointCount
=
0
super
.
setStateRoot
(
stateRoot
,
(
err
)
=>
{
this
.
_checkpointCount
=
checkpoint
cb
(
err
)
})
async
setStateRoot
(
stateRoot
)
{
await
this
.
_cache
.
flush
()
if
(
stateRoot
===
this
.
_trie
.
EMPTY_TRIE_ROOT
)
{
this
.
_trie
.
root
=
stateRoot
this
.
_cache
.
clear
()
this
.
_storageTries
=
{}
return
}
const
hasRoot
=
await
this
.
_trie
.
checkRoot
(
stateRoot
)
if
(
!
hasRoot
)
{
throw
new
Error
(
'State trie does not contain state root'
)
}
this
.
_trie
.
root
=
stateRoot
this
.
_cache
.
clear
()
this
.
_storageTries
=
{}
}
}
...
...
@@ -79,7 +100,7 @@ export class VMContext {
constructor
()
{
this
.
blockGasLimitDefault
=
4300000
this
.
blockGasLimit
=
this
.
blockGasLimitDefault
this
.
currentFork
=
'
muirGlacier
'
this
.
currentFork
=
'
berlin
'
this
.
vms
=
{
/*
byzantium: createVm('byzantium'),
...
...
@@ -87,7 +108,7 @@ export class VMContext {
petersburg: createVm('petersburg'),
istanbul: createVm('istanbul'),
*/
muirGlacier
:
this
.
createVm
(
'muirGlacier
'
)
berlin
:
this
.
createVm
(
'berlin
'
)
}
this
.
blocks
=
{}
this
.
latestBlockNumber
=
0
...
...
@@ -97,22 +118,21 @@ export class VMContext {
}
createVm
(
hardfork
)
{
const
stateManager
=
new
StateManagerCommonStorageDump
({})
stateManager
.
checkpoint
(()
=>
{})
const
ethvm
=
new
EthJSVM
({
const
stateManager
=
new
StateManagerCommonStorageDump
()
const
common
=
new
Common
({
chain
:
'mainnet'
,
hardfork
})
const
vm
=
new
VM
({
common
,
activatePrecompiles
:
true
,
blockchain
:
stateManager
.
blockchain
,
stateManager
:
stateManager
,
hardfork
:
hardfork
stateManager
:
stateManager
})
ethvm
.
blockchain
.
validate
=
false
this
.
web3vm
=
new
v
m
.
Web3VMProvider
()
this
.
web3vm
.
setVM
(
eth
vm
)
return
{
vm
:
ethvm
,
web3vm
:
this
.
web3vm
,
stateManager
}
const
web3vm
=
new
remixLibV
m
.
Web3VMProvider
()
web3vm
.
setVM
(
vm
)
return
{
vm
,
web3vm
,
stateManager
,
common
}
}
web3
()
{
return
this
.
web3vm
return
this
.
vms
[
this
.
currentFork
].
web3vm
}
blankWeb3
()
{
...
...
@@ -123,6 +143,10 @@ export class VMContext {
return
this
.
vms
[
this
.
currentFork
].
vm
}
vmObject
()
{
return
this
.
vms
[
this
.
currentFork
]
}
addBlock
(
block
)
{
let
blockNumber
=
'0x'
+
block
.
header
.
number
.
toString
(
'hex'
)
if
(
blockNumber
===
'0x'
)
{
...
...
@@ -133,7 +157,7 @@ export class VMContext {
this
.
blocks
[
blockNumber
]
=
block
this
.
latestBlockNumber
=
blockNumber
this
.
logsManager
.
checkBlock
(
blockNumber
,
block
,
this
.
web3
vm
)
this
.
logsManager
.
checkBlock
(
blockNumber
,
block
,
this
.
web3
()
)
}
trackTx
(
tx
,
block
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment