Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
G
Geth-Modification
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
张蕾
Geth-Modification
Commits
73761f7a
Commit
73761f7a
authored
May 28, 2014
by
obscuren
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Closure call now returns the total usage as well
* Return the used gas value based on the UseGas and ReturnGas
parent
1c01e9c0
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
138 additions
and
104 deletions
+138
-104
closure.go
ethchain/closure.go
+18
-4
state_manager.go
ethchain/state_manager.go
+24
-14
transaction_pool.go
ethchain/transaction_pool.go
+14
-4
vm.go
ethchain/vm.go
+82
-82
No files found.
ethchain/closure.go
View file @
73761f7a
...
...
@@ -22,8 +22,7 @@ type Closure struct {
Script
[]
byte
State
*
State
Gas
*
big
.
Int
Price
*
big
.
Int
Gas
,
UsedGas
,
Price
*
big
.
Int
Args
[]
byte
}
...
...
@@ -74,10 +73,12 @@ func (c *Closure) Address() []byte {
type
DebugHook
func
(
step
int
,
op
OpCode
,
mem
*
Memory
,
stack
*
Stack
,
stateObject
*
StateObject
)
bool
func
(
c
*
Closure
)
Call
(
vm
*
Vm
,
args
[]
byte
,
hook
DebugHook
)
([]
byte
,
error
)
{
func
(
c
*
Closure
)
Call
(
vm
*
Vm
,
args
[]
byte
,
hook
DebugHook
)
([]
byte
,
*
big
.
Int
,
error
)
{
c
.
Args
=
args
return
vm
.
RunClosure
(
c
,
hook
)
ret
,
err
:=
vm
.
RunClosure
(
c
,
hook
)
return
ret
,
c
.
UsedGas
,
err
}
func
(
c
*
Closure
)
Return
(
ret
[]
byte
)
[]
byte
{
...
...
@@ -93,10 +94,23 @@ func (c *Closure) Return(ret []byte) []byte {
return
ret
}
func
(
c
*
Closure
)
UseGas
(
gas
*
big
.
Int
)
bool
{
if
c
.
Gas
.
Cmp
(
gas
)
<
0
{
return
false
}
// Sub the amount of gas from the remaining
c
.
Gas
.
Sub
(
c
.
Gas
,
gas
)
c
.
UsedGas
.
Add
(
c
.
UsedGas
,
gas
)
return
true
}
// Implement the Callee interface
func
(
c
*
Closure
)
ReturnGas
(
gas
,
price
*
big
.
Int
,
state
*
State
)
{
// Return the gas to the closure
c
.
Gas
.
Add
(
c
.
Gas
,
gas
)
c
.
UsedGas
.
Sub
(
c
.
UsedGas
,
gas
)
}
func
(
c
*
Closure
)
Object
()
*
StateObject
{
...
...
ethchain/state_manager.go
View file @
73761f7a
...
...
@@ -106,7 +106,7 @@ func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Tra
usedGas
,
err
:=
sm
.
ApplyTransaction
(
state
,
block
,
tx
)
if
err
!=
nil
{
ethutil
.
Config
.
Log
.
Infoln
(
err
)
continue
//
continue
}
accumelative
:=
new
(
big
.
Int
)
.
Set
(
totalUsedGas
.
Add
(
totalUsedGas
,
usedGas
))
...
...
@@ -119,7 +119,7 @@ func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Tra
return
receipts
,
txs
}
func
(
sm
*
StateManager
)
ApplyTransaction
(
state
*
State
,
block
*
Block
,
tx
*
Transaction
)
(
*
big
.
Int
,
error
)
{
func
(
sm
*
StateManager
)
ApplyTransaction
(
state
*
State
,
block
*
Block
,
tx
*
Transaction
)
(
totalGasUsed
*
big
.
Int
,
err
error
)
{
/*
Applies transactions to the given state and creates new
state objects where needed.
...
...
@@ -129,9 +129,17 @@ func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transac
assume there's a return value. The return value will be set to
the script section of the state object.
*/
totalGasUsed
:=
big
.
NewInt
(
0
)
var
(
addTotalGas
=
func
(
gas
*
big
.
Int
)
{
totalGasUsed
.
Add
(
totalGasUsed
,
gas
)
}
gas
=
new
(
big
.
Int
)
script
[]
byte
)
totalGasUsed
=
big
.
NewInt
(
0
)
// Apply the transaction to the current state
err
:=
sm
.
Ethereum
.
TxPool
()
.
ProcessTransaction
(
tx
,
state
,
false
)
gas
,
err
=
sm
.
Ethereum
.
TxPool
()
.
ProcessTransaction
(
tx
,
state
,
false
)
addTotalGas
(
gas
)
if
tx
.
CreatesContract
()
{
if
err
==
nil
{
// Create a new state object and the transaction
...
...
@@ -141,30 +149,32 @@ func (sm *StateManager) ApplyTransaction(state *State, block *Block, tx *Transac
// Evaluate the initialization script
// and use the return value as the
// script section for the state object.
script
,
err
:=
sm
.
EvalScript
(
state
,
contract
.
Init
(),
contract
,
tx
,
block
)
script
,
gas
,
err
=
sm
.
EvalScript
(
state
,
contract
.
Init
(),
contract
,
tx
,
block
)
addTotalGas
(
gas
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"[STATE] Error during init script run %v"
,
err
)
err
=
fmt
.
Errorf
(
"[STATE] Error during init script run %v"
,
err
)
return
}
contract
.
script
=
script
state
.
UpdateStateObject
(
contract
)
}
else
{
return
nil
,
fmt
.
Errorf
(
"[STATE] Unable to create contract"
)
err
=
fmt
.
Errorf
(
"[STATE] Unable to create contract"
)
}
}
else
{
return
nil
,
fmt
.
Errorf
(
"[STATE] contract creation tx:
"
,
err
)
err
=
fmt
.
Errorf
(
"[STATE] contract creation tx: %v
"
,
err
)
}
}
else
{
// Find the state object at the "recipient" address. If
// there's an object attempt to run the script.
stateObject
:=
state
.
GetStateObject
(
tx
.
Recipient
)
if
err
==
nil
&&
stateObject
!=
nil
&&
len
(
stateObject
.
Script
())
>
0
{
sm
.
EvalScript
(
state
,
stateObject
.
Script
(),
stateObject
,
tx
,
block
)
}
else
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"[STATE] process:"
,
err
)
_
,
gas
,
err
=
sm
.
EvalScript
(
state
,
stateObject
.
Script
(),
stateObject
,
tx
,
block
)
addTotalGas
(
gas
)
}
}
return
totalGasUsed
,
nil
return
}
func
(
sm
*
StateManager
)
Process
(
block
*
Block
,
dontReact
bool
)
error
{
...
...
@@ -349,7 +359,7 @@ func (sm *StateManager) Stop() {
sm
.
bc
.
Stop
()
}
func
(
sm
*
StateManager
)
EvalScript
(
state
*
State
,
script
[]
byte
,
object
*
StateObject
,
tx
*
Transaction
,
block
*
Block
)
(
ret
[]
byte
,
err
error
)
{
func
(
sm
*
StateManager
)
EvalScript
(
state
*
State
,
script
[]
byte
,
object
*
StateObject
,
tx
*
Transaction
,
block
*
Block
)
(
ret
[]
byte
,
gas
*
big
.
Int
,
err
error
)
{
account
:=
state
.
GetAccount
(
tx
.
Sender
())
err
=
account
.
ConvertGas
(
tx
.
Gas
,
tx
.
GasPrice
)
...
...
@@ -369,7 +379,7 @@ func (sm *StateManager) EvalScript(state *State, script []byte, object *StateObj
Value
:
tx
.
Value
,
//Price: tx.GasPrice,
})
ret
,
err
=
closure
.
Call
(
vm
,
tx
.
Data
,
nil
)
ret
,
gas
,
err
=
closure
.
Call
(
vm
,
tx
.
Data
,
nil
)
// Update the account (refunds)
state
.
UpdateStateObject
(
account
)
...
...
ethchain/transaction_pool.go
View file @
73761f7a
...
...
@@ -91,28 +91,37 @@ func (pool *TxPool) addTransaction(tx *Transaction) {
// Process transaction validates the Tx and processes funds from the
// sender to the recipient.
func
(
pool
*
TxPool
)
ProcessTransaction
(
tx
*
Transaction
,
state
*
State
,
toContract
bool
)
(
err
error
)
{
func
(
pool
*
TxPool
)
ProcessTransaction
(
tx
*
Transaction
,
state
*
State
,
toContract
bool
)
(
gas
*
big
.
Int
,
err
error
)
{
defer
func
()
{
if
r
:=
recover
();
r
!=
nil
{
ethutil
.
Config
.
Log
.
Infoln
(
r
)
err
=
fmt
.
Errorf
(
"%v"
,
r
)
}
}()
gas
=
new
(
big
.
Int
)
addGas
:=
func
(
g
*
big
.
Int
)
{
gas
.
Add
(
gas
,
g
)
}
// Get the sender
sender
:=
state
.
GetAccount
(
tx
.
Sender
())
if
sender
.
Nonce
!=
tx
.
Nonce
{
return
fmt
.
Errorf
(
"[TXPL] Invalid account nonce, state nonce is %d transaction nonce is %d instead"
,
sender
.
Nonce
,
tx
.
Nonce
)
err
=
fmt
.
Errorf
(
"[TXPL] Invalid account nonce, state nonce is %d transaction nonce is %d instead"
,
sender
.
Nonce
,
tx
.
Nonce
)
return
}
txTotalBytes
:=
big
.
NewInt
(
int64
(
len
(
tx
.
Data
)))
txTotalBytes
.
Div
(
txTotalBytes
,
ethutil
.
Big32
)
addGas
(
new
(
big
.
Int
)
.
Mul
(
txTotalBytes
,
GasSStore
))
// Make sure there's enough in the sender's account. Having insufficient
// funds won't invalidate this transaction but simple ignores it.
//totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat))
totAmount
:=
new
(
big
.
Int
)
.
Add
(
tx
.
Value
,
new
(
big
.
Int
)
.
Mul
(
tx
.
Gas
,
tx
.
GasPrice
))
if
sender
.
Amount
.
Cmp
(
totAmount
)
<
0
{
return
fmt
.
Errorf
(
"[TXPL] Insufficient amount in sender's (%x) account"
,
tx
.
Sender
())
err
=
fmt
.
Errorf
(
"[TXPL] Insufficient amount in sender's (%x) account"
,
tx
.
Sender
())
return
}
//fmt.Println(tx)
// Get the receiver
receiver
:=
state
.
GetAccount
(
tx
.
Recipient
)
...
...
@@ -120,6 +129,7 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, state *State, toContract
// Send Tx to self
if
bytes
.
Compare
(
tx
.
Recipient
,
tx
.
Sender
())
==
0
{
addGas
(
GasTx
)
// Subtract the fee
sender
.
SubAmount
(
new
(
big
.
Int
)
.
Mul
(
GasTx
,
tx
.
GasPrice
))
}
else
{
...
...
ethchain/vm.go
View file @
73761f7a
...
...
@@ -21,11 +21,10 @@ var (
GasTx
=
big
.
NewInt
(
500
)
)
func
CalculateTxGas
(
initSize
,
scriptSize
*
big
.
Int
)
*
big
.
Int
{
func
CalculateTxGas
(
initSize
*
big
.
Int
)
*
big
.
Int
{
totalGas
:=
new
(
big
.
Int
)
totalGas
.
Add
(
totalGas
,
GasCreate
)
txTotalBytes
:=
new
(
big
.
Int
)
.
Add
(
initSize
,
scrip
tSize
)
txTotalBytes
:=
new
(
big
.
Int
)
.
Set
(
ini
tSize
)
txTotalBytes
.
Div
(
txTotalBytes
,
ethutil
.
Big32
)
totalGas
.
Add
(
totalGas
,
new
(
big
.
Int
)
.
Mul
(
txTotalBytes
,
GasSStore
))
...
...
@@ -92,12 +91,14 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
pc
:=
big
.
NewInt
(
0
)
// Current step count
step
:=
0
prevStep
:=
0
if
ethutil
.
Config
.
Debug
{
ethutil
.
Config
.
Log
.
Debugf
(
"# op
\n
"
)
}
for
{
prevStep
=
step
// The base for all big integer arithmetic
base
:=
new
(
big
.
Int
)
...
...
@@ -111,16 +112,16 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
gas
:=
new
(
big
.
Int
)
useGas
:=
func
(
amount
*
big
.
Int
)
{
setStepGasUsage
:=
func
(
amount
*
big
.
Int
)
{
gas
.
Add
(
gas
,
amount
)
}
switch
op
{
case
o
SHA3
:
useGas
(
GasSha
)
case
o
SLOAD
:
useGas
(
GasSLoad
)
case
o
SSTORE
:
case
SHA3
:
setStepGasUsage
(
GasSha
)
case
SLOAD
:
setStepGasUsage
(
GasSLoad
)
case
SSTORE
:
var
mult
*
big
.
Int
y
,
x
:=
stack
.
Peekn
()
val
:=
closure
.
GetMem
(
x
)
...
...
@@ -131,67 +132,64 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
else
{
mult
=
ethutil
.
Big1
}
useGas
(
new
(
big
.
Int
)
.
Mul
(
mult
,
GasSStore
))
case
o
BALANCE
:
useGas
(
GasBalance
)
case
o
CREATE
:
setStepGasUsage
(
new
(
big
.
Int
)
.
Mul
(
mult
,
GasSStore
))
case
BALANCE
:
setStepGasUsage
(
GasBalance
)
case
CREATE
:
require
(
3
)
args
:=
stack
.
Get
(
big
.
NewInt
(
3
))
initSize
:=
new
(
big
.
Int
)
.
Add
(
args
[
1
],
args
[
0
])
useGas
(
CalculateTxGas
(
initSize
,
ethutil
.
Big0
))
case
o
CALL
:
useGas
(
GasCall
)
case
oMLOAD
,
oMSIZE
,
oMSTORE8
,
o
MSTORE
:
useGas
(
GasMemory
)
setStepGasUsage
(
CalculateTxGas
(
initSize
))
case
CALL
:
setStepGasUsage
(
GasCall
)
case
MLOAD
,
MSIZE
,
MSTORE8
,
MSTORE
:
setStepGasUsage
(
GasMemory
)
default
:
useGas
(
GasStep
)
setStepGasUsage
(
GasStep
)
}
if
closure
.
Gas
.
Cmp
(
gas
)
<
0
{
if
!
closure
.
UseGas
(
gas
)
{
ethutil
.
Config
.
Log
.
Debugln
(
"Insufficient gas"
,
closure
.
Gas
,
gas
)
return
closure
.
Return
(
nil
),
fmt
.
Errorf
(
"insufficient gas %v %v"
,
closure
.
Gas
,
gas
)
}
// Sub the amount of gas from the remaining
closure
.
Gas
.
Sub
(
closure
.
Gas
,
gas
)
switch
op
{
case
o
LOG
:
case
LOG
:
stack
.
Print
()
mem
.
Print
()
// 0x20 range
case
o
ADD
:
case
ADD
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// (x + y) % 2 ** 256
base
.
Add
(
x
,
y
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
o
SUB
:
case
SUB
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// (x - y) % 2 ** 256
base
.
Sub
(
x
,
y
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
o
MUL
:
case
MUL
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// (x * y) % 2 ** 256
base
.
Mul
(
x
,
y
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
o
DIV
:
case
DIV
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// floor(x / y)
base
.
Div
(
x
,
y
)
// Pop result back on the stack
stack
.
Push
(
base
)
case
o
SDIV
:
case
SDIV
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// n > 2**255
...
...
@@ -208,12 +206,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
// Push result on to the stack
stack
.
Push
(
z
)
case
o
MOD
:
case
MOD
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
base
.
Mod
(
x
,
y
)
stack
.
Push
(
base
)
case
o
SMOD
:
case
SMOD
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// n > 2**255
...
...
@@ -230,17 +228,17 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
// Push result on to the stack
stack
.
Push
(
z
)
case
o
EXP
:
case
EXP
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
base
.
Exp
(
x
,
y
,
Pow256
)
stack
.
Push
(
base
)
case
o
NEG
:
case
NEG
:
require
(
1
)
base
.
Sub
(
Pow256
,
stack
.
Pop
())
stack
.
Push
(
base
)
case
o
LT
:
case
LT
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// x < y
...
...
@@ -249,7 +247,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
o
GT
:
case
GT
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// x > y
...
...
@@ -258,7 +256,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
o
EQ
:
case
EQ
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
// x == y
...
...
@@ -267,7 +265,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
o
NOT
:
case
NOT
:
require
(
1
)
x
:=
stack
.
Pop
()
if
x
.
Cmp
(
ethutil
.
BigFalse
)
==
0
{
...
...
@@ -277,7 +275,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
// 0x10 range
case
o
AND
:
case
AND
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
if
(
x
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
&&
(
y
.
Cmp
(
ethutil
.
BigTrue
)
>=
0
)
{
...
...
@@ -286,7 +284,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
o
OR
:
case
OR
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
if
(
x
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
||
(
y
.
Cmp
(
ethutil
.
BigInt0
)
>=
0
)
{
...
...
@@ -294,11 +292,11 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
else
{
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
o
XOR
:
case
XOR
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
stack
.
Push
(
base
.
Xor
(
x
,
y
))
case
o
BYTE
:
case
BYTE
:
require
(
2
)
val
,
th
:=
stack
.
Popn
()
if
th
.
Cmp
(
big
.
NewInt
(
32
))
<
0
{
...
...
@@ -308,92 +306,92 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
}
// 0x20 range
case
o
SHA3
:
case
SHA3
:
require
(
2
)
size
,
offset
:=
stack
.
Popn
()
data
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
stack
.
Push
(
ethutil
.
BigD
(
data
))
// 0x30 range
case
o
ADDRESS
:
case
ADDRESS
:
stack
.
Push
(
ethutil
.
BigD
(
closure
.
Object
()
.
Address
()))
case
o
BALANCE
:
case
BALANCE
:
stack
.
Push
(
closure
.
object
.
Amount
)
case
o
ORIGIN
:
case
ORIGIN
:
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
Origin
))
case
o
CALLER
:
case
CALLER
:
stack
.
Push
(
ethutil
.
BigD
(
closure
.
Callee
()
.
Address
()))
case
o
CALLVALUE
:
case
CALLVALUE
:
stack
.
Push
(
vm
.
vars
.
Value
)
case
o
CALLDATALOAD
:
case
CALLDATALOAD
:
require
(
1
)
offset
:=
stack
.
Pop
()
.
Int64
()
val
:=
closure
.
Args
[
offset
:
offset
+
32
]
stack
.
Push
(
ethutil
.
BigD
(
val
))
case
o
CALLDATASIZE
:
case
CALLDATASIZE
:
stack
.
Push
(
big
.
NewInt
(
int64
(
len
(
closure
.
Args
))))
case
o
GASPRICE
:
case
GASPRICE
:
stack
.
Push
(
closure
.
Price
)
// 0x40 range
case
o
PREVHASH
:
case
PREVHASH
:
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
PrevHash
))
case
o
COINBASE
:
case
COINBASE
:
stack
.
Push
(
ethutil
.
BigD
(
vm
.
vars
.
Coinbase
))
case
o
TIMESTAMP
:
case
TIMESTAMP
:
stack
.
Push
(
big
.
NewInt
(
vm
.
vars
.
Time
))
case
o
NUMBER
:
case
NUMBER
:
stack
.
Push
(
big
.
NewInt
(
int64
(
vm
.
vars
.
BlockNumber
)))
case
o
DIFFICULTY
:
case
DIFFICULTY
:
stack
.
Push
(
vm
.
vars
.
Diff
)
case
o
GASLIMIT
:
case
GASLIMIT
:
// TODO
stack
.
Push
(
big
.
NewInt
(
0
))
// 0x50 range
case
oPUSH1
,
oPUSH2
,
oPUSH3
,
oPUSH4
,
oPUSH5
,
oPUSH6
,
oPUSH7
,
oPUSH8
,
oPUSH9
,
oPUSH10
,
oPUSH11
,
oPUSH12
,
oPUSH13
,
oPUSH14
,
oPUSH15
,
oPUSH16
,
oPUSH17
,
oPUSH18
,
oPUSH19
,
oPUSH20
,
oPUSH21
,
oPUSH22
,
oPUSH23
,
oPUSH24
,
oPUSH25
,
oPUSH26
,
oPUSH27
,
oPUSH28
,
oPUSH29
,
oPUSH30
,
oPUSH31
,
o
PUSH32
:
a
:=
big
.
NewInt
(
int64
(
op
)
-
int64
(
o
PUSH1
)
+
1
)
case
PUSH1
,
PUSH2
,
PUSH3
,
PUSH4
,
PUSH5
,
PUSH6
,
PUSH7
,
PUSH8
,
PUSH9
,
PUSH10
,
PUSH11
,
PUSH12
,
PUSH13
,
PUSH14
,
PUSH15
,
PUSH16
,
PUSH17
,
PUSH18
,
PUSH19
,
PUSH20
,
PUSH21
,
PUSH22
,
PUSH23
,
PUSH24
,
PUSH25
,
PUSH26
,
PUSH27
,
PUSH28
,
PUSH29
,
PUSH30
,
PUSH31
,
PUSH32
:
a
:=
big
.
NewInt
(
int64
(
op
)
-
int64
(
PUSH1
)
+
1
)
pc
.
Add
(
pc
,
ethutil
.
Big1
)
data
:=
closure
.
Gets
(
pc
,
a
)
val
:=
ethutil
.
BigD
(
data
.
Bytes
())
// Push value to stack
stack
.
Push
(
val
)
pc
.
Add
(
pc
,
a
.
Sub
(
a
,
big
.
NewInt
(
1
)))
step
++
case
oPOP
:
step
+=
int
(
op
)
-
int
(
PUSH1
)
+
1
case
POP
:
require
(
1
)
stack
.
Pop
()
case
o
DUP
:
case
DUP
:
require
(
1
)
stack
.
Push
(
stack
.
Peek
())
case
o
SWAP
:
case
SWAP
:
require
(
2
)
x
,
y
:=
stack
.
Popn
()
stack
.
Push
(
y
)
stack
.
Push
(
x
)
case
o
MLOAD
:
case
MLOAD
:
require
(
1
)
offset
:=
stack
.
Pop
()
stack
.
Push
(
ethutil
.
BigD
(
mem
.
Get
(
offset
.
Int64
(),
32
)))
case
o
MSTORE
:
// Store the value at stack top-1 in to memory at location stack top
case
MSTORE
:
// Store the value at stack top-1 in to memory at location stack top
require
(
2
)
// Pop value of the stack
val
,
mStart
:=
stack
.
Popn
()
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
val
,
256
))
case
o
MSTORE8
:
case
MSTORE8
:
require
(
2
)
val
,
mStart
:=
stack
.
Popn
()
base
.
And
(
val
,
new
(
big
.
Int
)
.
SetInt64
(
0xff
))
mem
.
Set
(
mStart
.
Int64
(),
32
,
ethutil
.
BigToBytes
(
base
,
256
))
case
o
SLOAD
:
case
SLOAD
:
require
(
1
)
loc
:=
stack
.
Pop
()
val
:=
closure
.
GetMem
(
loc
)
//fmt.Println("get", val.BigInt(), "@", loc)
stack
.
Push
(
val
.
BigInt
())
case
o
SSTORE
:
case
SSTORE
:
require
(
2
)
val
,
loc
:=
stack
.
Popn
()
//fmt.Println("storing", val, "@", loc)
...
...
@@ -401,13 +399,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Add the change to manifest
vm
.
state
.
manifest
.
AddStorageChange
(
closure
.
Object
(),
loc
.
Bytes
(),
val
)
case
o
JUMP
:
case
JUMP
:
require
(
1
)
pc
=
stack
.
Pop
()
// Reduce pc by one because of the increment that's at the end of this for loop
//pc.Sub(pc, ethutil.Big1)
continue
case
o
JUMPI
:
case
JUMPI
:
require
(
2
)
cond
,
pos
:=
stack
.
Popn
()
if
cond
.
Cmp
(
ethutil
.
BigTrue
)
==
0
{
...
...
@@ -415,12 +413,12 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
//pc.Sub(pc, ethutil.Big1)
continue
}
case
o
PC
:
case
PC
:
stack
.
Push
(
pc
)
case
o
MSIZE
:
case
MSIZE
:
stack
.
Push
(
big
.
NewInt
(
int64
(
mem
.
Len
())))
// 0x60 range
case
o
CREATE
:
case
CREATE
:
require
(
3
)
value
:=
stack
.
Pop
()
...
...
@@ -439,9 +437,10 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Transfer all remaining gas to the new
// contract so it may run the init script
gas
:=
new
(
big
.
Int
)
.
Set
(
closure
.
Gas
)
closure
.
Gas
.
Sub
(
closure
.
Gas
,
gas
)
closure
.
UseGas
(
gas
)
// Create the closure
c
losure
:=
NewClosure
(
closure
.
callee
,
c
:=
NewClosure
(
closure
.
callee
,
closure
.
Object
(),
contract
.
initScript
,
vm
.
state
,
...
...
@@ -449,7 +448,8 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
closure
.
Price
)
// Call the closure and set the return value as
// main script.
closure
.
Script
,
err
=
closure
.
Call
(
vm
,
nil
,
hook
)
c
.
Script
,
_
,
err
=
c
.
Call
(
vm
,
nil
,
hook
)
if
err
!=
nil
{
stack
.
Push
(
ethutil
.
BigFalse
)
...
...
@@ -460,7 +460,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
vm
.
state
.
UpdateStateObject
(
contract
)
}
case
o
CALL
:
case
CALL
:
require
(
7
)
// Closure addr
addr
:=
stack
.
Pop
()
...
...
@@ -492,7 +492,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Copy
gas
=
new
(
big
.
Int
)
.
Set
(
closure
.
Gas
)
}
closure
.
Gas
.
Sub
(
closure
.
Gas
,
gas
)
closure
.
UseGas
(
gas
)
// Add the value to the state object
contract
.
AddAmount
(
value
)
...
...
@@ -500,7 +500,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
// Create a new callable closure
closure
:=
NewClosure
(
closure
.
Object
(),
contract
,
contract
.
script
,
vm
.
state
,
gas
,
closure
.
Price
)
// Executer the closure and get the return value (if any)
ret
,
err
:=
closure
.
Call
(
vm
,
args
,
hook
)
ret
,
_
,
err
:=
closure
.
Call
(
vm
,
args
,
hook
)
if
err
!=
nil
{
stack
.
Push
(
ethutil
.
BigFalse
)
// Reset the changes applied this object
...
...
@@ -516,13 +516,13 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
ethutil
.
Config
.
Log
.
Debugf
(
"Contract %x not found
\n
"
,
addr
.
Bytes
())
stack
.
Push
(
ethutil
.
BigFalse
)
}
case
o
RETURN
:
case
RETURN
:
require
(
2
)
size
,
offset
:=
stack
.
Popn
()
ret
:=
mem
.
Get
(
offset
.
Int64
(),
size
.
Int64
())
return
closure
.
Return
(
ret
),
nil
case
o
SUICIDE
:
case
SUICIDE
:
require
(
1
)
receiver
:=
vm
.
state
.
GetAccount
(
stack
.
Pop
()
.
Bytes
())
...
...
@@ -532,7 +532,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
closure
.
object
.
state
.
Purge
()
fallthrough
case
o
STOP
:
// Stop the closure
case
STOP
:
// Stop the closure
return
closure
.
Return
(
nil
),
nil
default
:
ethutil
.
Config
.
Log
.
Debugf
(
"Invalid opcode %x
\n
"
,
op
)
...
...
@@ -543,7 +543,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
pc
.
Add
(
pc
,
ethutil
.
Big1
)
if
hook
!=
nil
{
if
!
hook
(
step
-
1
,
op
,
mem
,
stack
,
closure
.
Object
())
{
if
!
hook
(
prevStep
,
op
,
mem
,
stack
,
closure
.
Object
())
{
return
nil
,
nil
}
}
...
...
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