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
006dc9b3
Commit
006dc9b3
authored
May 24, 2016
by
yann300
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
align trace with geth trace
parent
7a90aee4
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
358 additions
and
183 deletions
+358
-183
asmCode.js
src/asmCode.js
+4
-0
basicPanel.js
src/basicPanel.js
+2
-27
buttonNavigator.js
src/buttonNavigator.js
+16
-3
calldataPanel.js
src/calldataPanel.js
+9
-1
callstackPanel.js
src/callstackPanel.js
+9
-1
codeResolver.js
src/codeResolver.js
+8
-3
debugger.js
src/debugger.js
+1
-1
memoryPanel.js
src/memoryPanel.js
+10
-27
stackPanel.js
src/stackPanel.js
+9
-1
stepManager.js
src/stepManager.js
+1
-1
storagePanel.js
src/storagePanel.js
+7
-18
traceAnalyser.js
src/traceAnalyser.js
+44
-35
traceCache.js
src/traceCache.js
+15
-4
traceManager.js
src/traceManager.js
+112
-21
traceManagerUtil.js
src/traceManagerUtil.js
+32
-6
traceRetriever.js
src/traceRetriever.js
+17
-5
traceStepManager.js
src/traceStepManager.js
+18
-12
txBrowser.js
src/txBrowser.js
+37
-10
vmDebugger.js
src/vmDebugger.js
+5
-5
web3Admin.js
src/web3Admin.js
+2
-2
No files found.
src/asmCode.js
View file @
006dc9b3
...
...
@@ -48,6 +48,9 @@ module.exports = React.createClass({
if
(
nextProps
.
currentStepIndex
<
0
)
return
codeResolver
.
setWeb3
(
this
.
context
.
web3
)
var
self
=
this
if
(
nextProps
.
currentStepIndex
===
0
)
{
self
.
ensureCodeLoaded
(
this
.
context
.
tx
.
to
,
nextProps
.
currentStepIndex
)
}
else
{
this
.
context
.
traceManager
.
getCurrentCalledAddressAt
(
nextProps
.
currentStepIndex
,
function
(
error
,
address
)
{
if
(
error
)
{
console
.
log
(
error
)
...
...
@@ -55,6 +58,7 @@ module.exports = React.createClass({
self
.
ensureCodeLoaded
(
address
,
nextProps
.
currentStepIndex
)
}
})
}
},
ensureCodeLoaded
:
function
(
address
,
currentStep
)
{
...
...
src/basicPanel.js
View file @
006dc9b3
...
...
@@ -6,8 +6,7 @@ module.exports = React.createClass({
getDefaultProps
:
function
()
{
return
{
data
:
null
,
name
:
null
,
renderRow
:
null
name
:
null
}
},
...
...
@@ -18,33 +17,9 @@ module.exports = React.createClass({
{
this
.
props
.
name
}
<
/div
>
<
div
style
=
{
style
.
panel
.
tableContainer
}
>
<
table
style
=
{
style
.
panel
.
table
}
>
<
tbody
>
{
this
.
renderItems
()}
<
/tbody
>
<
/table
>
<
pre
style
=
{
Object
.
assign
(
style
.
panel
.
table
,
style
.
font
)}
>
{
this
.
props
.
data
}
<
/pre
>
<
/div
>
<
/div
>
)
},
renderItems
:
function
()
{
if
(
!
this
.
props
.
data
)
{
return
[]
}
if
(
!
this
.
props
.
renderRow
)
{
var
ret
=
[]
for
(
var
key
in
this
.
props
.
data
)
{
ret
.
push
(
<
tr
key
=
{
key
}
>
<
td
>
<
pre
style
=
{
style
.
font
}
>
{
this
.
props
.
data
[
key
]}
<
/pre
>
<
/td
>
<
/tr>
)
}
return
ret
}
else
{
return
this
.
props
.
renderRow
(
this
.
props
.
data
)
}
}
})
src/buttonNavigator.js
View file @
006dc9b3
...
...
@@ -10,7 +10,8 @@ module.exports = React.createClass({
stepIntoBack
:
React
.
PropTypes
.
func
.
isRequired
,
stepIntoForward
:
React
.
PropTypes
.
func
.
isRequired
,
stepOverBack
:
React
.
PropTypes
.
func
.
isRequired
,
stepOverForward
:
React
.
PropTypes
.
func
.
isRequired
stepOverForward
:
React
.
PropTypes
.
func
.
isRequired
,
jumpNextCall
:
React
.
PropTypes
.
func
.
isRequired
},
render
:
function
()
{
...
...
@@ -28,15 +29,27 @@ module.exports = React.createClass({
<
button
onClick
=
{
this
.
props
.
stepIntoForward
}
disabled
=
{
this
.
checkButtonState
(
1
)}
>
Step
Into
Forward
<
/button
>
<
button
onClick
=
{
this
.
props
.
jumpNextCall
}
disabled
=
{
this
.
checkButtonState
(
1
)}
>
Jump
Next
Call
<
/button
>
<
/div
>
)
},
checkButtonState
:
function
(
incr
)
{
if
(
!
this
.
context
.
traceManager
)
{
return
false
}
var
self
=
this
this
.
context
.
traceManager
.
getLength
(
function
(
error
,
length
)
{
if
(
error
)
{
return
false
}
if
(
incr
===
-
1
)
{
return
this
.
props
.
step
===
0
?
'disabled'
:
''
return
self
.
props
.
step
===
0
?
'disabled'
:
''
}
else
if
(
incr
===
1
)
{
return
this
.
props
.
step
>=
this
.
props
.
max
-
1
?
'disabled'
:
''
return
self
.
props
.
step
>=
self
.
props
.
max
-
1
?
'disabled'
:
''
}
})
}
})
src/calldataPanel.js
View file @
006dc9b3
...
...
@@ -35,9 +35,17 @@ module.exports = React.createClass({
console
.
log
(
error
)
}
else
if
(
window
.
ethDebuggerSelectedItem
===
nextProps
.
currentStepIndex
)
{
self
.
setState
({
data
:
calldata
data
:
self
.
format
(
calldata
)
})
}
})
},
format
:
function
(
calldata
)
{
var
ret
=
''
for
(
var
key
in
calldata
)
{
ret
+=
calldata
[
key
]
+
'
\
n'
}
return
ret
}
})
src/callstackPanel.js
View file @
006dc9b3
...
...
@@ -35,9 +35,17 @@ module.exports = React.createClass({
console
.
log
(
error
)
}
else
if
(
window
.
ethDebuggerSelectedItem
===
nextProps
.
currentStepIndex
)
{
self
.
setState
({
data
:
callstack
data
:
self
.
format
(
callstack
)
})
}
})
},
format
:
function
(
callstack
)
{
var
ret
=
''
for
(
var
key
in
callstack
)
{
ret
+=
callstack
[
key
]
+
'
\
n'
}
return
ret
}
})
src/codeResolver.js
View file @
006dc9b3
...
...
@@ -18,7 +18,7 @@ module.exports = {
return
}
if
(
vmTraceIndex
===
0
&&
transaction
.
to
===
null
)
{
// start of the trace
if
(
address
===
'(Contract Creation Code)'
)
{
// start of the trace
callBack
(
address
,
this
.
cacheExecutingCode
(
address
,
transaction
.
input
).
code
)
return
}
...
...
@@ -41,9 +41,14 @@ module.exports = {
},
cacheExecutingCode
:
function
(
address
,
hexCode
)
{
var
codes
=
this
.
formatCode
(
hexCode
)
this
.
codes
[
address
]
=
codes
[
0
]
this
.
instructionsIndexByBytesOffset
[
address
]
=
codes
[
1
]
return
codes
},
formatCode
:
function
(
hexCode
)
{
var
code
=
codeUtils
.
nameOpCodes
(
new
Buffer
(
hexCode
.
substring
(
2
),
'hex'
))
this
.
codes
[
address
]
=
code
[
0
]
this
.
instructionsIndexByBytesOffset
[
address
]
=
code
[
1
]
return
{
code
:
code
[
0
],
instructionsIndexByBytesOffset
:
code
[
1
]
...
...
src/debugger.js
View file @
006dc9b3
...
...
@@ -61,7 +61,7 @@ module.exports = React.createClass({
tx
:
tx
})
var
self
=
this
this
.
state
.
traceManager
.
resolveTrace
(
blockNumber
,
txInde
x
,
function
(
success
)
{
this
.
state
.
traceManager
.
resolveTrace
(
t
x
,
function
(
success
)
{
console
.
log
(
'trace loaded '
+
success
)
self
.
setState
({
currentStepIndex
:
0
...
...
src/memoryPanel.js
View file @
006dc9b3
'use strict'
var
React
=
require
(
'react'
)
var
BasicPanel
=
require
(
'./basicPanel'
)
var
style
=
require
(
'./basicStyles'
)
module
.
exports
=
React
.
createClass
({
contextTypes
:
{
...
...
@@ -23,7 +22,7 @@ module.exports = React.createClass({
render
:
function
()
{
return
(
<
BasicPanel
name
=
'Memory'
data
=
{
this
.
state
.
data
}
renderRow
=
{
this
.
renderMemoryRow
}
/
>
<
BasicPanel
name
=
'Memory'
data
=
{
this
.
state
.
data
}
/
>
)
},
...
...
@@ -43,36 +42,20 @@ module.exports = React.createClass({
})
},
renderMemoryRow
:
function
(
data
)
{
var
ret
=
[]
if
(
data
)
{
for
(
var
key
in
data
)
{
var
memSlot
=
data
[
key
]
ret
.
push
(
<
tr
key
=
{
key
}
>
<
td
>
<
pre
style
=
{
style
.
font
}
>
{
memSlot
.
address
}
<
/pre
>
<
/td
>
<
td
>
<
pre
style
=
{
style
.
font
}
>
{
memSlot
.
content
.
raw
}
<
/pre
>
<
/td
>
<
td
>
<
pre
style
=
{
style
.
font
}
>
{
memSlot
.
content
.
ascii
}
<
/pre
>
<
/td
>
<
/tr>
)
formatMemory
:
function
(
mem
,
width
)
{
var
ret
=
''
if
(
!
mem
)
{
return
ret
}
if
(
!
mem
.
substr
)
{
mem
=
mem
.
join
(
''
)
// geth returns an array, eth return raw string
}
return
ret
},
formatMemory
:
function
(
mem
,
width
)
{
var
ret
=
[]
for
(
var
k
=
0
;
k
<
mem
.
length
;
k
+=
(
width
*
2
))
{
var
memory
=
mem
.
substr
(
k
,
width
*
2
)
ret
.
push
({
address
:
this
.
context
.
web3
.
toHex
(
k
),
content
:
this
.
tryAsciiFormat
(
memory
)
})
var
content
=
this
.
tryAsciiFormat
(
memory
)
ret
+=
this
.
context
.
web3
.
toHex
(
k
)
+
' '
+
content
.
raw
+
' '
+
content
.
ascii
+
'
\
n'
}
return
ret
},
...
...
src/stackPanel.js
View file @
006dc9b3
...
...
@@ -35,9 +35,17 @@ module.exports = React.createClass({
console
.
log
(
error
)
}
else
if
(
window
.
ethDebuggerSelectedItem
===
nextProps
.
currentStepIndex
)
{
self
.
setState
({
data
:
s
tack
data
:
s
elf
.
format
(
stack
)
})
}
})
},
format
:
function
(
stack
)
{
var
ret
=
''
for
(
var
key
in
stack
)
{
ret
+=
stack
[
key
]
+
'
\
n'
}
return
ret
}
})
src/stepManager.js
View file @
006dc9b3
...
...
@@ -33,7 +33,7 @@ module.exports = React.createClass({
stepIntoForward
=
{
this
.
stepIntoForward
}
stepOverBack
=
{
this
.
stepOverBack
}
stepOverForward
=
{
this
.
stepOverForward
}
jump
To
NextCall
=
{
this
.
jumpToNextCall
}
jumpNextCall
=
{
this
.
jumpToNextCall
}
max
=
{
this
.
state
.
traceLength
}
/
>
<
/div
>
)
...
...
src/storagePanel.js
View file @
006dc9b3
'use strict'
var
React
=
require
(
'react'
)
var
BasicPanel
=
require
(
'./basicPanel'
)
var
style
=
require
(
'./basicStyles'
)
module
.
exports
=
React
.
createClass
({
contextTypes
:
{
...
...
@@ -23,7 +22,7 @@ module.exports = React.createClass({
render
:
function
()
{
return
(
<
BasicPanel
name
=
'Storage'
data
=
{
this
.
state
.
data
}
renderRow
=
{
this
.
renderStorageRow
}
/
>
<
BasicPanel
name
=
'Storage'
data
=
{
this
.
state
.
data
}
/
>
)
},
...
...
@@ -32,31 +31,21 @@ module.exports = React.createClass({
if
(
window
.
ethDebuggerSelectedItem
!==
nextProps
.
currentStepIndex
)
return
var
self
=
this
this
.
context
.
traceManager
.
getStorageAt
(
nextProps
.
currentStepIndex
,
this
.
context
.
tx
.
blockNumber
.
toString
(),
this
.
context
.
tx
.
transactionIndex
,
function
(
error
,
storage
)
{
this
.
context
.
traceManager
.
getStorageAt
(
nextProps
.
currentStepIndex
,
this
.
context
.
tx
,
function
(
error
,
storage
)
{
if
(
error
)
{
console
.
log
(
error
)
}
else
if
(
window
.
ethDebuggerSelectedItem
===
nextProps
.
currentStepIndex
)
{
self
.
setState
({
data
:
s
torage
data
:
s
elf
.
formatStorage
(
storage
)
})
}
})
},
renderStorageRow
:
function
(
data
)
{
var
ret
=
[]
if
(
data
)
{
for
(
var
key
in
data
)
{
ret
.
push
(
<
tr
key
=
{
key
}
>
<
td
>
<
pre
style
=
{
style
.
font
}
>
{
key
}
<
/pre
>
<
/td
>
<
td
>
<
pre
style
=
{
style
.
font
}
>
{
data
[
key
]}
<
/pre
>
<
/td
>
<
/tr>
)
}
formatStorage
:
function
(
storage
)
{
var
ret
=
''
for
(
var
key
in
storage
)
{
ret
+=
key
+
' '
+
storage
[
key
]
+
'
\
n'
}
return
ret
}
...
...
src/traceAnalyser.js
View file @
006dc9b3
'use strict'
var
traceManagerUtil
=
require
(
'./traceManagerUtil'
)
function
TraceAnalyser
(
_cache
)
{
this
.
traceCache
=
_cache
this
.
trace
=
null
}
TraceAnalyser
.
prototype
.
analyse
=
function
(
trace
,
callback
)
{
TraceAnalyser
.
prototype
.
analyse
=
function
(
trace
,
root
,
callback
)
{
this
.
trace
=
trace
var
currentDepth
=
0
this
.
traceCache
.
pushStoreChanges
(
0
,
root
)
var
context
=
{
currentStorageAddress
:
trace
[
0
].
address
,
previousStorageAddress
:
trace
[
0
].
address
currentStorageAddress
:
root
,
previousStorageAddress
:
root
}
var
callStack
=
[]
for
(
var
k
in
this
.
trace
)
{
var
callStack
=
[
root
]
this
.
traceCache
.
pushCallStack
(
0
,
{
callStack
:
callStack
.
slice
(
0
)
})
for
(
var
k
=
0
;
k
<
this
.
trace
.
length
;
k
++
)
{
var
step
=
this
.
trace
[
k
]
this
.
buildCalldata
(
k
,
step
)
this
.
buildMemory
(
k
,
step
)
var
depth
=
this
.
buildDepth
(
k
,
step
,
currentDepth
,
callStack
)
if
(
depth
)
{
currentDepth
=
depth
}
this
.
buildDepth
(
k
,
step
,
callStack
)
context
=
this
.
buildStorage
(
k
,
step
,
context
)
}
callback
(
null
,
true
)
...
...
@@ -38,40 +42,45 @@ TraceAnalyser.prototype.buildMemory = function (index, step) {
}
TraceAnalyser
.
prototype
.
buildStorage
=
function
(
index
,
step
,
context
)
{
if
(
step
.
address
)
{
// new context
context
.
currentStorageAddress
=
step
.
address
this
.
traceCache
.
pushStoreChanges
(
index
,
context
.
currentStorageAddress
)
}
else
if
(
step
.
inst
===
'SSTORE'
)
{
this
.
traceCache
.
pushStoreChanges
(
index
,
context
.
currentStorageAddress
,
step
.
stack
[
step
.
stack
.
length
-
1
],
step
.
stack
[
step
.
stack
.
length
-
2
])
}
else
if
(
!
step
.
address
&&
step
.
depth
)
{
// returned from context
if
(
traceManagerUtil
.
newContextStorage
(
step
))
{
var
calledAddress
=
traceManagerUtil
.
resolveCalledAddress
(
index
,
this
.
trace
)
if
(
calledAddress
)
{
context
.
currentStorageAddress
=
calledAddress
}
else
{
console
.
log
(
'unable to build storage changes. '
+
index
+
' does not match with a CALL. storage changes will be corrupted'
)
}
this
.
traceCache
.
pushStoreChanges
(
index
+
1
,
context
.
currentStorageAddress
)
}
else
if
(
step
.
op
===
'SSTORE'
)
{
this
.
traceCache
.
pushStoreChanges
(
index
+
1
,
context
.
currentStorageAddress
,
step
.
stack
[
step
.
stack
.
length
-
1
],
step
.
stack
[
step
.
stack
.
length
-
2
])
}
else
if
(
!
step
.
op
===
'RETURN'
)
{
context
.
currentStorageAddress
=
context
.
previousStorageAddress
this
.
traceCache
.
pushStoreChanges
(
index
,
context
.
currentStorageAddress
)
this
.
traceCache
.
pushStoreChanges
(
index
+
1
,
context
.
currentStorageAddress
)
}
return
context
}
TraceAnalyser
.
prototype
.
buildDepth
=
function
(
index
,
step
,
c
urrentDepth
,
c
allStack
)
{
if
(
step
.
depth
===
undefined
)
return
if
(
step
.
depth
>
currentDepth
)
{
if
(
index
===
0
)
{
callStack
.
push
(
'0x'
+
step
.
address
)
// new context
TraceAnalyser
.
prototype
.
buildDepth
=
function
(
index
,
step
,
callStack
)
{
if
(
traceManagerUtil
.
isCallInstruction
(
step
)
&&
!
traceManagerUtil
.
isCallToPrecompiledContract
(
index
,
this
.
trace
))
{
var
newAddress
=
traceManagerUtil
.
resolveCalledAddress
(
index
,
this
.
trace
)
if
(
newAddress
)
{
callStack
.
push
(
newAddress
)
}
else
{
// getting the address from the stack
var
callTrace
=
this
.
trace
[
index
-
1
]
var
address
=
callTrace
.
stack
[
callTrace
.
stack
.
length
-
2
]
callStack
.
push
(
address
)
// new context
}
}
else
if
(
step
.
depth
<
currentDepth
)
{
callStack
.
pop
()
// returning from context
console
.
log
(
'unable to build depth changes. '
+
index
+
' does not match with a CALL. depth changes will be corrupted'
)
}
this
.
traceCache
.
pushCallChanges
(
step
,
index
+
1
)
this
.
traceCache
.
pushCallStack
(
index
+
1
,
{
callStack
:
callStack
.
slice
(
0
)
})
}
else
if
(
traceManagerUtil
.
isReturnInstruction
(
step
))
{
this
.
traceCache
.
pushCallChanges
(
step
,
index
)
this
.
traceCache
.
pushCallStack
(
index
,
{
stack
:
callStack
.
slice
(
0
),
depth
:
step
.
depth
callStack
:
callStack
.
slice
(
0
)
})
this
.
traceCache
.
pushDepthChanges
(
index
)
return
step
.
depth
callStack
.
pop
(
)
}
}
// 0x90a99e9dbfc38ce0fd6330f97a192a9ef27b8329b57309e8b2abe47a6fe74574
// 0xc0e95f27e1482ba09dea8162c4b4090e3d89e214416df2ce9d5517ff2107de19
module
.
exports
=
TraceAnalyser
src/traceCache.js
View file @
006dc9b3
...
...
@@ -5,9 +5,13 @@ function TraceCache () {
TraceCache
.
prototype
.
init
=
function
()
{
// ...Changes contains index in the vmtrace of the corresponding changes
this
.
depthChanges
=
[]
this
.
memoryChanges
=
[]
this
.
callChanges
=
[]
this
.
returnChanges
=
[]
this
.
calls
=
{}
this
.
callDataChanges
=
[]
this
.
memoryChanges
=
[]
this
.
storageChanges
=
[]
this
.
sstore
=
{}
// all sstore occurence in the trace
this
.
callStack
=
{}
// contains all callStack by vmtrace index (we need to rebuild it, callstack is not included in the vmtrace)
...
...
@@ -21,8 +25,15 @@ TraceCache.prototype.pushMemoryChanges = function (value) {
this
.
memoryChanges
.
push
(
value
)
}
TraceCache
.
prototype
.
pushDepthChanges
=
function
(
value
)
{
this
.
depthChanges
.
push
(
value
)
TraceCache
.
prototype
.
pushCallChanges
=
function
(
step
,
value
)
{
this
.
callChanges
.
push
(
value
)
this
.
calls
[
value
]
=
{
op
:
step
.
op
}
}
TraceCache
.
prototype
.
pushReturnChanges
=
function
(
value
)
{
this
.
returnChanges
.
push
(
value
)
}
TraceCache
.
prototype
.
pushCallStack
=
function
(
index
,
callStack
)
{
...
...
src/traceManager.js
View file @
006dc9b3
...
...
@@ -13,27 +13,36 @@ function TraceManager (_web3) {
this
.
traceAnalyser
=
new
TraceAnalyser
(
this
.
traceCache
)
this
.
traceRetriever
=
new
TraceRetriever
(
_web3
)
this
.
traceStepManager
=
new
TraceStepManager
(
this
.
traceAnalyser
)
this
.
tx
}
// init section
TraceManager
.
prototype
.
resolveTrace
=
function
(
blockNumber
,
txNumber
,
callback
)
{
this
.
isLoading
=
true
TraceManager
.
prototype
.
resolveTrace
=
function
(
tx
,
callback
)
{
this
.
tx
=
tx
this
.
init
()
if
(
!
this
.
web3
)
callback
(
false
)
this
.
isLoading
=
true
var
self
=
this
this
.
traceRetriever
.
getTrace
(
blockNumber
,
parseInt
(
txNumber
),
function
(
error
,
result
)
{
self
.
trace
=
result
this
.
traceRetriever
.
getTrace
(
tx
.
hash
,
function
(
error
,
result
)
{
if
(
error
)
{
console
.
log
(
error
)
self
.
isLoading
=
false
}
else
{
self
.
traceAnalyser
.
analyse
(
result
,
function
(
error
,
result
)
{
if
(
result
.
structLogs
.
length
>
0
)
{
self
.
trace
=
result
.
structLogs
self
.
traceAnalyser
.
analyse
(
result
.
structLogs
,
tx
.
to
,
function
(
error
,
result
)
{
if
(
error
)
{
console
.
log
(
error
)
callback
(
false
)
}
else
{
callback
(
true
)
}
self
.
isLoading
=
false
})
}
else
{
console
.
log
(
tx
.
hash
+
' is not a contract invokation or contract creation.'
)
self
.
isLoading
=
false
}
}
})
}
...
...
@@ -45,16 +54,24 @@ TraceManager.prototype.init = function () {
// API section
TraceManager
.
prototype
.
getLength
=
function
(
callback
)
{
if
(
!
this
.
trace
)
callback
(
'no trace available'
,
null
)
if
(
!
this
.
trace
)
{
callback
(
'no trace available'
,
null
)
}
else
{
callback
(
null
,
this
.
trace
.
length
)
}
}
TraceManager
.
prototype
.
getStorageAt
=
function
(
stepIndex
,
blockNumber
,
txIndex
,
callback
)
{
TraceManager
.
prototype
.
getStorageAt
=
function
(
stepIndex
,
tx
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
var
stoChange
=
traceManagerUtil
.
findLowerBound
(
stepIndex
,
this
.
traceCache
.
storageChanges
)
var
address
=
this
.
traceCache
.
sstore
[
stoChange
].
address
if
(
stoChange
===
undefined
)
return
callback
(
'no storage found'
,
null
)
var
self
=
this
this
.
traceRetriever
.
getStorage
(
blockNumber
,
txIndex
,
address
,
function
(
error
,
result
)
{
if
(
this
.
traceRetriever
.
debugStorageAtAvailable
())
{
var
address
=
this
.
traceCache
.
sstore
[
stoChange
].
address
this
.
traceRetriever
.
getStorage
(
tx
,
address
,
function
(
error
,
result
)
{
if
(
error
)
{
console
.
log
(
error
)
callback
(
error
,
null
)
...
...
@@ -63,21 +80,36 @@ TraceManager.prototype.getStorageAt = function (stepIndex, blockNumber, txIndex,
callback
(
null
,
storage
)
}
})
}
else
{
callback
(
null
,
this
.
trace
[
stoChange
].
storage
)
}
}
TraceManager
.
prototype
.
getCallDataAt
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
var
callDataChange
=
traceManagerUtil
.
findLowerBound
(
stepIndex
,
this
.
traceCache
.
callDataChanges
)
if
(
!
callDataChange
)
return
callback
(
'no calldata found'
,
null
)
if
(
callDataChange
===
undefined
)
return
callback
(
'no calldata found'
,
null
)
callback
(
null
,
[
this
.
trace
[
callDataChange
].
calldata
])
}
TraceManager
.
prototype
.
getCallStackAt
=
function
(
stepIndex
,
callback
)
{
var
callStackChange
=
traceManagerUtil
.
findLowerBound
(
stepIndex
,
this
.
traceCache
.
depthChanges
)
if
(
!
callStackChange
)
return
callback
(
'no callstack found'
,
null
)
callback
(
null
,
this
.
traceCache
.
callStack
[
callStackChange
].
stack
)
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
var
callStackChange
=
traceManagerUtil
.
findLowerBound
(
stepIndex
,
this
.
traceCache
.
callChanges
)
if
(
callStackChange
===
undefined
)
return
callback
(
'no callstack found'
,
null
)
callback
(
null
,
this
.
traceCache
.
callStack
[
callStackChange
].
callStack
)
}
TraceManager
.
prototype
.
getStackAt
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
var
stack
if
(
this
.
trace
[
stepIndex
].
stack
)
{
// there's always a stack
stack
=
this
.
trace
[
stepIndex
].
stack
.
slice
(
0
)
...
...
@@ -88,48 +120,103 @@ TraceManager.prototype.getStackAt = function (stepIndex, callback) {
}
}
TraceManager
.
prototype
.
getLastDepthIndexChangeSince
=
function
(
stepIndex
,
callback
)
{
var
depthIndex
=
traceManagerUtil
.
findLowerBound
(
stepIndex
,
this
.
traceCache
.
depthChanges
)
callback
(
null
,
depthIndex
)
TraceManager
.
prototype
.
getLastCallChangeSince
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
var
callChange
=
traceManagerUtil
.
findLowerBound
(
stepIndex
,
this
.
traceCache
.
callChanges
)
if
(
callChange
===
undefined
)
{
callback
(
null
,
0
)
}
else
{
callback
(
null
,
callChange
)
}
}
TraceManager
.
prototype
.
getCurrentCalledAddressAt
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
var
self
=
this
this
.
getLast
DepthIndex
ChangeSince
(
stepIndex
,
function
(
error
,
addressIndex
)
{
this
.
getLast
Call
ChangeSince
(
stepIndex
,
function
(
error
,
addressIndex
)
{
if
(
error
)
{
callback
(
error
,
null
)
}
else
{
callback
(
null
,
traceManagerUtil
.
resolveCalledAddress
(
addressIndex
,
self
.
trace
))
if
(
addressIndex
===
0
)
{
callback
(
null
,
self
.
tx
.
to
)
}
else
{
var
step
=
this
.
trace
[
addressIndex
]
if
(
traceManagerUtil
.
isCreateInstruction
(
step
))
{
callback
(
null
,
'(Contract Creation Code)'
)
}
else
{
var
callStack
=
self
.
traceCache
.
callStack
[
addressIndex
].
callStack
var
calledAddress
=
callStack
[
callStack
.
length
-
1
]
if
(
calledAddress
)
{
callback
(
null
,
calledAddress
)
}
else
{
callback
(
'unable to get current called address. '
+
stepIndex
+
' does not match with a CALL'
,
null
)
}
}
}
}
})
}
TraceManager
.
prototype
.
getMemoryAt
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
var
lastChanges
=
traceManagerUtil
.
findLowerBound
(
stepIndex
,
this
.
traceCache
.
memoryChanges
)
if
(
!
lastChanges
)
return
callback
(
'no memory found'
,
null
)
if
(
lastChanges
===
undefined
)
return
callback
(
'no memory found'
,
null
)
callback
(
null
,
this
.
trace
[
lastChanges
].
memory
)
}
TraceManager
.
prototype
.
getCurrentPC
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
callback
(
null
,
this
.
trace
[
stepIndex
].
pc
)
}
TraceManager
.
prototype
.
getCurrentStep
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
callback
(
null
,
this
.
trace
[
stepIndex
].
steps
)
}
TraceManager
.
prototype
.
getMemExpand
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
callback
(
null
,
this
.
trace
[
stepIndex
].
memexpand
?
this
.
trace
[
stepIndex
].
memexpand
:
''
)
}
TraceManager
.
prototype
.
getStepCost
=
function
(
stepIndex
,
callback
)
{
callback
(
null
,
this
.
trace
[
stepIndex
].
gascost
)
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
callback
(
null
,
this
.
trace
[
stepIndex
].
gasCost
)
}
TraceManager
.
prototype
.
getRemainingGas
=
function
(
stepIndex
,
callback
)
{
if
(
stepIndex
>=
this
.
trace
.
length
)
{
callback
(
'trace smaller than requested'
,
null
)
return
}
callback
(
null
,
this
.
trace
[
stepIndex
].
gas
)
}
TraceManager
.
prototype
.
isCreationStep
=
function
(
stepIndex
)
{
return
traceManagerUtil
.
isCreateInstruction
(
stepIndex
,
this
.
trace
)
}
// step section
TraceManager
.
prototype
.
findStepOverBack
=
function
(
currentStep
)
{
return
this
.
traceStepManager
.
findStepOverBack
(
currentStep
)
...
...
@@ -147,4 +234,8 @@ TraceManager.prototype.findStepOutForward = function (currentStep) {
return
this
.
traceStepManager
.
findStepOutForward
(
currentStep
)
}
TraceManager
.
prototype
.
findNextCall
=
function
(
currentStep
)
{
return
this
.
traceStepManager
.
findNextCall
(
currentStep
)
}
module
.
exports
=
TraceManager
src/traceManagerUtil.js
View file @
006dc9b3
...
...
@@ -24,13 +24,39 @@ module.exports = {
}
},
// vmTraceIndex has to point to a CALL, CODECALL, ...
resolveCalledAddress
:
function
(
vmTraceIndex
,
trace
)
{
var
address
=
trace
[
vmTraceIndex
].
address
if
(
vmTraceIndex
>
0
)
{
var
stack
=
trace
[
vmTraceIndex
-
1
].
stack
// callcode, delegatecall, ...
address
=
stack
[
stack
.
length
-
2
]
}
return
address
var
step
=
trace
[
vmTraceIndex
]
if
(
this
.
isCallInstruction
(
step
))
{
var
stack
=
step
.
stack
// callcode, delegatecall, ...
return
stack
[
stack
.
length
-
2
]
}
return
undefined
},
isCallInstruction
:
function
(
step
)
{
return
step
.
op
===
'CALL'
||
step
.
op
===
'CALLCODE'
||
step
.
op
===
'CREATE'
||
step
.
op
===
'DELEGATECALL'
},
isCreateInstruction
:
function
(
step
)
{
return
step
.
op
===
'CREATE'
},
isReturnInstruction
:
function
(
step
)
{
return
step
.
op
===
'RETURN'
},
newContextStorage
:
function
(
step
)
{
return
step
.
op
===
'CREATE'
||
step
.
op
===
'CALL'
},
isCallToPrecompiledContract
:
function
(
index
,
trace
)
{
// if stack empty => this is not a precompiled contract
var
step
=
trace
[
index
]
if
(
this
.
isCallInstruction
(
step
))
{
return
trace
[
index
+
1
].
stack
.
length
!==
0
}
else
{
return
false
}
}
}
src/traceRetriever.js
View file @
006dc9b3
...
...
@@ -4,22 +4,34 @@ function TraceRetriever (_web3) {
this
.
storages
=
{}
// contains all intial storage (by addresses)
}
TraceRetriever
.
prototype
.
getTrace
=
function
(
blockNumber
,
txNumber
,
callback
)
{
this
.
web3
.
debug
.
trace
(
blockNumber
,
parseInt
(
txNumber
),
function
(
error
,
result
)
{
TraceRetriever
.
prototype
.
getTrace
=
function
(
txHash
,
callback
)
{
var
options
=
{
disableStorage
:
this
.
debugStorageAtAvailable
(),
disableMemory
:
false
,
disableStack
:
false
,
fullStorage
:
!
this
.
debugStorageAtAvailable
()
}
this
.
web3
.
debug
.
traceTransaction
(
txHash
,
options
,
function
(
error
,
result
)
{
callback
(
error
,
result
)
})
}
TraceRetriever
.
prototype
.
getStorage
=
function
(
blockNumber
,
txIndex
,
address
,
callback
)
{
if
(
this
.
storages
[
address
])
{
TraceRetriever
.
prototype
.
getStorage
=
function
(
tx
,
address
,
callback
)
{
if
(
tx
.
to
===
'(Contract Creation Code)'
)
{
callback
(
null
,
{})
}
else
if
(
this
.
storages
[
address
])
{
callback
(
null
,
this
.
storages
[
address
])
}
else
{
var
self
=
this
this
.
web3
.
debug
.
storageAt
(
blockNumber
,
tx
Index
,
address
,
function
(
error
,
result
)
{
this
.
web3
.
debug
.
storageAt
(
tx
.
blockNumber
.
toString
(),
tx
.
transaction
Index
,
address
,
function
(
error
,
result
)
{
self
.
storages
[
address
]
=
result
callback
(
error
,
result
)
})
}
}
TraceRetriever
.
prototype
.
debugStorageAtAvailable
=
function
()
{
return
true
// storageAt not available if using geth
}
module
.
exports
=
TraceRetriever
src/traceStepManager.js
View file @
006dc9b3
'use strict'
var
traceManagerUtil
=
require
(
'./traceManagerUtil'
)
function
TraceStepManager
(
_traceAnalyser
)
{
this
.
traceAnalyser
=
_traceAnalyser
}
TraceStepManager
.
prototype
.
isCallInstruction
=
function
(
index
)
{
var
state
=
this
.
traceAnalyser
.
trace
[
index
]
return
state
.
instname
===
'CALL'
||
state
.
instname
===
'CALLCODE'
||
state
.
instname
===
'CREATE'
||
state
.
instname
===
'DELEGATECALL'
return
traceManagerUtil
.
isCallInstruction
(
state
)
}
TraceStepManager
.
prototype
.
isReturnInstruction
=
function
(
index
)
{
var
state
=
this
.
traceAnalyser
.
trace
[
index
]
return
state
.
instname
===
'RETURN'
return
traceManagerUtil
.
isReturnInstruction
(
state
)
}
TraceStepManager
.
prototype
.
findStepOverBack
=
function
(
currentStep
)
{
if
(
this
.
isReturnInstruction
(
currentStep
-
1
))
{
if
(
currentStep
===
0
)
return
0
return
this
.
findStepOutBack
(
currentStep
)
}
else
{
return
currentStep
-
1
}
}
TraceStepManager
.
prototype
.
findStepOverForward
=
function
(
currentStep
)
{
if
(
this
.
isCallInstruction
(
currentStep
))
{
if
(
currentStep
===
this
.
traceAnalyser
.
trace
.
length
-
1
)
return
currentStep
return
this
.
findStepOutForward
(
currentStep
)
}
else
{
return
currentStep
+
1
}
}
TraceStepManager
.
prototype
.
findStepOutBack
=
function
(
currentStep
)
{
...
...
@@ -49,7 +45,7 @@ TraceStepManager.prototype.findStepOutBack = function (currentStep) {
TraceStepManager
.
prototype
.
findStepOutForward
=
function
(
currentStep
)
{
var
i
=
currentStep
var
depth
=
0
while
(
++
i
<
this
.
traceAnalyser
.
length
)
{
while
(
++
i
<
this
.
traceAnalyser
.
trace
.
length
)
{
if
(
this
.
isReturnInstruction
(
i
))
{
if
(
depth
===
0
)
{
break
...
...
@@ -60,7 +56,17 @@ TraceStepManager.prototype.findStepOutForward = function (currentStep) {
depth
++
}
}
return
i
+
1
return
i
}
TraceStepManager
.
prototype
.
findNextCall
=
function
(
currentStep
)
{
var
i
=
currentStep
while
(
++
i
<
this
.
traceAnalyser
.
trace
.
length
)
{
if
(
this
.
isCallInstruction
(
i
))
{
return
i
}
}
return
currentStep
}
module
.
exports
=
TraceStepManager
src/txBrowser.js
View file @
006dc9b3
...
...
@@ -12,12 +12,23 @@ module.exports = React.createClass({
},
getInitialState
:
function
()
{
return
{
blockNumber
:
'1
382256'
,
txNumber
:
'1
'
,
from
:
''
,
to
:
''
,
hash
:
''
}
return
{
blockNumber
:
'1
000110'
,
txNumber
:
'0x71a6d583d16d142c5c3e8903060e8a4ee5a5016348a9448df6c3e63b68076ec4
'
,
from
:
''
,
to
:
''
,
hash
:
''
}
},
// creation 0xa9619e1d0a35b2c1d686f5b661b3abd87f998d2844e8e9cc905edb57fc9ce349
// invokation 0x71a6d583d16d142c5c3e8903060e8a4ee5a5016348a9448df6c3e63b68076ec4
submit
:
function
()
{
var
tx
=
this
.
context
.
web3
.
eth
.
getTransactionFromBlock
(
this
.
state
.
blockNumber
,
this
.
state
.
txNumber
)
var
tx
if
(
this
.
state
.
txNumber
.
indexOf
(
'0x'
)
!==
-
1
)
{
tx
=
this
.
context
.
web3
.
eth
.
getTransaction
(
this
.
state
.
txNumber
)
}
else
{
tx
=
this
.
context
.
web3
.
eth
.
getTransactionFromBlock
(
this
.
state
.
blockNumber
,
this
.
state
.
txNumber
)
}
if
(
tx
)
{
if
(
!
tx
.
to
)
{
tx
.
to
=
'(Contract Creation Code)'
}
this
.
setState
({
from
:
tx
.
from
,
to
:
tx
.
to
,
hash
:
tx
.
hash
})
this
.
props
.
onNewTxRequested
(
this
.
state
.
blockNumber
,
parseInt
(
this
.
state
.
txNumber
),
tx
)
}
else
{
...
...
@@ -25,6 +36,10 @@ module.exports = React.createClass({
}
},
updateTxhash
:
function
(
ev
)
{
this
.
state
.
hash
=
ev
.
target
.
value
},
updateBlockN
:
function
(
ev
)
{
this
.
state
.
blockNumber
=
ev
.
target
.
value
},
...
...
@@ -36,8 +51,8 @@ module.exports = React.createClass({
render
:
function
()
{
return
(
<
div
style
=
{
style
.
container
}
>
<
input
onChange
=
{
this
.
updateBlockN
}
type
=
'text'
placeholder
=
{
'Block number
or hash (default 1382256
)'
+
this
.
state
.
blockNumber
}
><
/input
>
<
input
onChange
=
{
this
.
updateTxN
}
type
=
'text'
placeholder
=
{
'Transaction Number
(default 1
) '
+
this
.
state
.
txNumber
}
><
/input
>
<
input
onChange
=
{
this
.
updateBlockN
}
type
=
'text'
placeholder
=
{
'Block number
(default 1000110
)'
+
this
.
state
.
blockNumber
}
><
/input
>
<
input
onChange
=
{
this
.
updateTxN
}
type
=
'text'
placeholder
=
{
'Transaction Number
or hash (default 2
) '
+
this
.
state
.
txNumber
}
><
/input
>
<
button
onClick
=
{
this
.
submit
}
>
Get
<
/button
>
...
...
@@ -45,16 +60,28 @@ module.exports = React.createClass({
<
table
>
<
tbody
>
<
tr
>
<
td
>
Hash
:
<
/td
>
<
td
>
{
this
.
state
.
hash
}
<
/td
>
<
td
>
Hash
:
<
/td
>
<
td
>
{
this
.
state
.
hash
}
<
/td
>
<
/tr
>
<
tr
>
<
td
>
From
:
<
/td
>
<
td
>
{
this
.
state
.
from
}
<
/td
>
<
td
>
From
:
<
/td
>
<
td
>
{
this
.
state
.
from
}
<
/td
>
<
/tr
>
<
tr
>
<
td
>
To
:
<
/td
>
<
td
>
{
this
.
state
.
to
}
<
/td
>
<
td
>
To
:
<
/td
>
<
td
>
{
this
.
state
.
to
}
<
/td
>
<
/tr
>
<
/tbody
>
<
/table
>
...
...
src/vmDebugger.js
View file @
006dc9b3
...
...
@@ -43,23 +43,23 @@ module.exports = React.createClass({
<
/div
>
<
/td
>
<
td
>
<
Calldata
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
Stack
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
/td
>
<
/tr
>
<
tr
>
<
td
>
<
St
ack
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
St
orage
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
/td
>
<
td
>
<
Callstack
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
Memory
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
/td
>
<
/tr
>
<
tr
>
<
td
>
<
Storage
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
Calldata
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
/td
>
<
td
>
<
Memory
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
Callstack
Panel
currentStepIndex
=
{
this
.
props
.
currentStepIndex
}
/
>
<
/td
>
<
/tr
>
<
/tbody
>
...
...
src/web3Admin.js
View file @
006dc9b3
...
...
@@ -96,8 +96,8 @@ module.exports = {
params
:
3
}),
new
web3
.
_extend
.
Method
({
name
:
'trace'
,
call
:
'debug_trace'
,
name
:
'trace
Transaction
'
,
call
:
'debug_trace
Transaction
'
,
inputFormatter
:
[
null
,
null
],
params
:
2
}),
...
...
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