@ -27,42 +27,56 @@ import (
"github.com/ethereum/go-ethereum/params"
)
func opAdd ( pc * uint64 , env * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
var bigZero = new ( big . Int )
func opAdd ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( U256 ( x . Add ( x , y ) ) )
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opSub ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSub ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( U256 ( x . Sub ( x , y ) ) )
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opMul ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opMul ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( U256 ( x . Mul ( x , y ) ) )
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opDiv ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opDiv ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
if y . Cmp ( common . Big0 ) != 0 {
stack . push ( U256 ( x . Div ( x , y ) ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opSdiv ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSdiv ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := S256 ( stack . pop ( ) ) , S256 ( stack . pop ( ) )
if y . Cmp ( common . Big0 ) == 0 {
stack . push ( new ( big . Int ) )
return nil , nil
} else {
n := new ( big . Int )
if new ( big . Int ) . Mul ( x , y ) . Cmp ( common . Big0 ) < 0 {
if evm . interpreter . intPool . get ( ) . Mul ( x , y ) . Cmp ( common . Big0 ) < 0 {
n . SetInt64 ( - 1 )
} else {
n . SetInt64 ( 1 )
@ -73,20 +87,22 @@ func opSdiv(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Sta
stack . push ( U256 ( res ) )
}
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opMod ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opMod ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
if y . Cmp ( common . Big0 ) == 0 {
stack . push ( new ( big . Int ) )
} else {
stack . push ( U256 ( x . Mod ( x , y ) ) )
}
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opSmod ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSmod ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := S256 ( stack . pop ( ) ) , S256 ( stack . pop ( ) )
if y . Cmp ( common . Big0 ) == 0 {
@ -104,16 +120,20 @@ func opSmod(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Sta
stack . push ( U256 ( res ) )
}
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opExp ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opExp ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
base , exponent := stack . pop ( ) , stack . pop ( )
stack . push ( math . Exp ( base , exponent ) )
evm . interpreter . intPool . put ( base , exponent )
return nil , nil
}
func opSignExtend ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSignExtend ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
back := stack . pop ( )
if back . Cmp ( big . NewInt ( 31 ) ) < 0 {
bit := uint ( back . Uint64 ( ) * 8 + 7 )
@ -128,198 +148,231 @@ func opSignExtend(pc *uint64, env *EVM, contract *Contract, memory *Memory, stac
stack . push ( U256 ( num ) )
}
evm . interpreter . intPool . put ( back )
return nil , nil
}
func opNot ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opNot ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x := stack . pop ( )
stack . push ( U256 ( x . Not ( x ) ) )
return nil , nil
}
func opLt ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opLt ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
if x . Cmp ( y ) < 0 {
stack . push ( big . NewInt ( 1 ) )
stack . push ( evm . interpreter . intPool . get ( ) . SetUint64 ( 1 ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( x , y )
return nil , nil
}
func opGt ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opGt ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
if x . Cmp ( y ) > 0 {
stack . push ( big . NewInt ( 1 ) )
stack . push ( evm . interpreter . intPool . get ( ) . SetUint64 ( 1 ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( x , y )
return nil , nil
}
func opSlt ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSlt ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := S256 ( stack . pop ( ) ) , S256 ( stack . pop ( ) )
if x . Cmp ( S256 ( y ) ) < 0 {
stack . push ( big . NewInt ( 1 ) )
stack . push ( evm . interpreter . intPool . get ( ) . SetUint64 ( 1 ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( x , y )
return nil , nil
}
func opSgt ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSgt ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := S256 ( stack . pop ( ) ) , S256 ( stack . pop ( ) )
if x . Cmp ( y ) > 0 {
stack . push ( big . NewInt ( 1 ) )
stack . push ( evm . interpreter . intPool . get ( ) . SetUint64 ( 1 ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( x , y )
return nil , nil
}
func opEq ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opEq ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
if x . Cmp ( y ) == 0 {
stack . push ( big . NewInt ( 1 ) )
stack . push ( evm . interpreter . intPool . get ( ) . SetUint64 ( 1 ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( x , y )
return nil , nil
}
func opIszero ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opIszero ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x := stack . pop ( )
if x . Cmp ( common . Big0 ) > 0 {
stack . push ( new ( big . Int ) )
} else {
stack . push ( big . NewInt ( 1 ) )
stack . push ( evm . interpreter . intPool . get ( ) . SetUint64 ( 1 ) )
}
evm . interpreter . intPool . put ( x )
return nil , nil
}
func opAnd ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opAnd ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( x . And ( x , y ) )
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opOr ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opOr ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( x . Or ( x , y ) )
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opXor ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opXor ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( x . Xor ( x , y ) )
evm . interpreter . intPool . put ( y )
return nil , nil
}
func opByte ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opByte ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
th , val := stack . pop ( ) , stack . pop ( )
if th . Cmp ( big . NewInt ( 32 ) ) < 0 {
byte := big . NewInt ( int64 ( common . LeftPadBytes ( val . Bytes ( ) , 32 ) [ th . Int64 ( ) ] ) )
byte := evm . interpreter . intPool . get ( ) . SetInt64 ( int64 ( common . LeftPadBytes ( val . Bytes ( ) , 32 ) [ th . Int64 ( ) ] ) )
stack . push ( byte )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( th , val )
return nil , nil
}
func opAddmod ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opAddmod ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y , z := stack . pop ( ) , stack . pop ( ) , stack . pop ( )
if z . Cmp ( Zero ) > 0 {
if z . Cmp ( big Zero) > 0 {
add := x . Add ( x , y )
add . Mod ( add , z )
stack . push ( U256 ( add ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( y , z )
return nil , nil
}
func opMulmod ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opMulmod ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
x , y , z := stack . pop ( ) , stack . pop ( ) , stack . pop ( )
if z . Cmp ( Zero ) > 0 {
if z . Cmp ( big Zero) > 0 {
mul := x . Mul ( x , y )
mul . Mod ( mul , z )
stack . push ( U256 ( mul ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( y , z )
return nil , nil
}
func opSha3 ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSha3 ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
offset , size := stack . pop ( ) , stack . pop ( )
data := memory . Get ( offset . Int64 ( ) , size . Int64 ( ) )
hash := crypto . Keccak256 ( data )
if en v . vmConfig . EnablePreimageRecording {
en v . StateDB . AddPreimage ( common . BytesToHash ( hash ) , data )
if evm . vmConfig . EnablePreimageRecording {
evm . StateDB . AddPreimage ( common . BytesToHash ( hash ) , data )
}
stack . push ( common . BytesToBig ( hash ) )
evm . interpreter . intPool . put ( offset , size )
return nil , nil
}
func opAddress ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opAddress ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( common . Bytes2Big ( contract . Address ( ) . Bytes ( ) ) )
return nil , nil
}
func opBalance ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opBalance ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
addr := common . BigToAddress ( stack . pop ( ) )
balance := en v . StateDB . GetBalance ( addr )
balance := evm . StateDB . GetBalance ( addr )
stack . push ( new ( big . Int ) . Set ( balance ) )
return nil , nil
}
func opOrigin ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( en v . Origin . Big ( ) )
func opOrigin ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( evm . Origin . Big ( ) )
return nil , nil
}
func opCaller ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opCaller ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( contract . Caller ( ) . Big ( ) )
return nil , nil
}
func opCallValue ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( new ( big . Int ) . Set ( contract . value ) )
func opCallValue ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( evm . interpreter . intPool . get ( ) . Set ( contract . value ) )
return nil , nil
}
func opCalldataLoad ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opCalldataLoad ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( common . Bytes2Big ( getData ( contract . Input , stack . pop ( ) , common . Big32 ) ) )
return nil , nil
}
func opCalldataSize ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( big . NewInt ( int64 ( len ( contract . Input ) ) ) )
func opCalldataSize ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( evm . interpreter . intPool . get ( ) . SetInt64 ( int64 ( len ( contract . Input ) ) ) )
return nil , nil
}
func opCalldataCopy ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opCalldataCopy ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
var (
mOff = stack . pop ( )
cOff = stack . pop ( )
l = stack . pop ( )
)
memory . Set ( mOff . Uint64 ( ) , l . Uint64 ( ) , getData ( contract . Input , cOff , l ) )
evm . interpreter . intPool . put ( mOff , cOff , l )
return nil , nil
}
func opExtCodeSize ( pc * uint64 , env * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
addr := common . BigToAddress ( stack . pop ( ) )
l := big . NewInt ( int64 ( env . StateDB . GetCodeSize ( addr ) ) )
stack . push ( l )
func opExtCodeSize ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
a := stack . pop ( )
addr := common . BigToAddress ( a )
a . SetInt64 ( int64 ( evm . StateDB . GetCodeSize ( addr ) ) )
stack . push ( a )
return nil , nil
}
func opCodeSize ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
l := big . NewInt ( int64 ( len ( contract . Code ) ) )
func opCodeSize ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
l := evm . interpreter . intPool . get ( ) . SetInt64 ( int64 ( len ( contract . Code ) ) )
stack . push ( l )
return nil , nil
}
func opCodeCopy ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opCodeCopy ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
var (
mOff = stack . pop ( )
cOff = stack . pop ( )
@ -328,113 +381,129 @@ func opCodeCopy(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack
codeCopy := getData ( contract . Code , cOff , l )
memory . Set ( mOff . Uint64 ( ) , l . Uint64 ( ) , codeCopy )
evm . interpreter . intPool . put ( mOff , cOff , l )
return nil , nil
}
func opExtCodeCopy ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opExtCodeCopy ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
var (
addr = common . BigToAddress ( stack . pop ( ) )
mOff = stack . pop ( )
cOff = stack . pop ( )
l = stack . pop ( )
)
codeCopy := getData ( en v . StateDB . GetCode ( addr ) , cOff , l )
codeCopy := getData ( evm . StateDB . GetCode ( addr ) , cOff , l )
memory . Set ( mOff . Uint64 ( ) , l . Uint64 ( ) , codeCopy )
evm . interpreter . intPool . put ( mOff , cOff , l )
return nil , nil
}
func opGasprice ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( new ( big . Int ) . Set ( en v . GasPrice ) )
func opGasprice ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( evm . interpreter . intPool . get ( ) . Set ( evm . GasPrice ) )
return nil , nil
}
func opBlockhash ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opBlockhash ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
num := stack . pop ( )
n := new ( big . Int ) . Sub ( en v . BlockNumber , common . Big257 )
if num . Cmp ( n ) > 0 && num . Cmp ( en v . BlockNumber ) < 0 {
stack . push ( en v . GetHash ( num . Uint64 ( ) ) . Big ( ) )
n := evm . interpreter . intPool . get ( ) . Sub ( evm . BlockNumber , common . Big257 )
if num . Cmp ( n ) > 0 && num . Cmp ( evm . BlockNumber ) < 0 {
stack . push ( evm . GetHash ( num . Uint64 ( ) ) . Big ( ) )
} else {
stack . push ( new ( big . Int ) )
}
evm . interpreter . intPool . put ( num , n )
return nil , nil
}
func opCoinbase ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( en v . Coinbase . Big ( ) )
func opCoinbase ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( evm . Coinbase . Big ( ) )
return nil , nil
}
func opTimestamp ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( U256 ( new ( big . Int ) . Set ( en v . Time ) ) )
func opTimestamp ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( U256 ( new ( big . Int ) . Set ( evm . Time ) ) )
return nil , nil
}
func opNumber ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( U256 ( new ( big . Int ) . Set ( en v . BlockNumber ) ) )
func opNumber ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( U256 ( new ( big . Int ) . Set ( evm . BlockNumber ) ) )
return nil , nil
}
func opDifficulty ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( U256 ( new ( big . Int ) . Set ( en v . Difficulty ) ) )
func opDifficulty ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( U256 ( new ( big . Int ) . Set ( evm . Difficulty ) ) )
return nil , nil
}
func opGasLimit ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( U256 ( new ( big . Int ) . Set ( en v . GasLimit ) ) )
func opGasLimit ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( U256 ( new ( big . Int ) . Set ( evm . GasLimit ) ) )
return nil , nil
}
func opPop ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . pop ( )
func opPop ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
evm . interpreter . intPool . put ( stack . pop ( ) )
return nil , nil
}
func opMload ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opMload ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
offset := stack . pop ( )
val := common . BigD ( memory . Get ( offset . Int64 ( ) , 32 ) )
stack . push ( val )
evm . interpreter . intPool . put ( offset )
return nil , nil
}
func opMstore ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opMstore ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
// pop value of the stack
mStart , val := stack . pop ( ) , stack . pop ( )
memory . Set ( mStart . Uint64 ( ) , 32 , common . BigToBytes ( val , 256 ) )
evm . interpreter . intPool . put ( mStart , val )
return nil , nil
}
func opMstore8 ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opMstore8 ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
off , val := stack . pop ( ) . Int64 ( ) , stack . pop ( ) . Int64 ( )
memory . store [ off ] = byte ( val & 0xff )
return nil , nil
}
func opSload ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSload ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
loc := common . BigToHash ( stack . pop ( ) )
val := en v . StateDB . GetState ( contract . Address ( ) , loc ) . Big ( )
val := evm . StateDB . GetState ( contract . Address ( ) , loc ) . Big ( )
stack . push ( val )
return nil , nil
}
func opSstore ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opSstore ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
loc := common . BigToHash ( stack . pop ( ) )
val := stack . pop ( )
env . StateDB . SetState ( contract . Address ( ) , loc , common . BigToHash ( val ) )
evm . StateDB . SetState ( contract . Address ( ) , loc , common . BigToHash ( val ) )
evm . interpreter . intPool . put ( val )
return nil , nil
}
func opJump ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opJump ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
pos := stack . pop ( )
if ! contract . jumpdests . has ( contract . CodeHash , contract . Code , pos ) {
nop := contract . GetOp ( pos . Uint64 ( ) )
return nil , fmt . Errorf ( "invalid jump destination (%v) %v" , nop , pos )
}
* pc = pos . Uint64 ( )
evm . interpreter . intPool . put ( pos )
return nil , nil
}
func opJumpi ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opJumpi ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
pos , cond := stack . pop ( ) , stack . pop ( )
if cond . Cmp ( common . BigTrue ) >= 0 {
if ! contract . jumpdests . has ( contract . CodeHash , contract . Code , pos ) {
@ -445,57 +514,62 @@ func opJumpi(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *St
} else {
* pc ++
}
evm . interpreter . intPool . put ( pos , cond )
return nil , nil
}
func opJumpdest ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opJumpdest ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
return nil , nil
}
func opPc ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( new ( big . Int ) . SetUint64 ( * pc ) )
func opPc ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( evm . interpreter . intPool . get ( ) . SetUint64 ( * pc ) )
return nil , nil
}
func opMsize ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( big . NewInt ( int64 ( memory . Len ( ) ) ) )
func opMsize ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( evm . interpreter . intPool . get ( ) . SetInt64 ( int64 ( memory . Len ( ) ) ) )
return nil , nil
}
func opGas ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( new ( big . Int ) . Set ( contract . Gas ) )
func opGas ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . push ( evm . interpreter . intPool . get ( ) . SetUint64 ( contract . Gas ) )
return nil , nil
}
func opCreate ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opCreate ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
var (
value = stack . pop ( )
offset , size = stack . pop ( ) , stack . pop ( )
input = memory . Get ( offset . Int64 ( ) , size . Int64 ( ) )
gas = new ( big . Int ) . Set ( contract . Gas )
gas = contract . Gas
)
if env . ChainConfig ( ) . IsEIP150 ( env . BlockNumber ) {
gas . Div ( gas , n64 )
gas = gas . Sub ( contract . Gas , gas )
if evm . ChainConfig ( ) . IsEIP150 ( evm . BlockNumber ) {
gas -= gas / 64
}
contract . UseGas ( gas )
_ , addr , suberr := en v . Create ( contract , input , gas , value )
_ , addr , returnGas , suberr := evm . Create ( contract , input , gas , value )
// Push item on the stack based on the returned error. If the ruleset is
// homestead we must check for CodeStoreOutOfGasError (homestead only
// rule) and treat as an error, if the ruleset is frontier we must
// ignore this error and pretend the operation was successful.
if en v . ChainConfig ( ) . IsHomestead ( en v . BlockNumber ) && suberr == ErrCodeStoreOutOfGas {
if evm . ChainConfig ( ) . IsHomestead ( evm . BlockNumber ) && suberr == ErrCodeStoreOutOfGas {
stack . push ( new ( big . Int ) )
} else if suberr != nil && suberr != ErrCodeStoreOutOfGas {
stack . push ( new ( big . Int ) )
} else {
stack . push ( addr . Big ( ) )
}
contract . Gas += returnGas
evm . interpreter . intPool . put ( value , offset , size )
return nil , nil
}
func opCall ( pc * uint64 , env * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
gas := stack . pop ( )
func opCall ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
gas := stack . pop ( ) . Uint64 ( )
// pop gas and value of the stack.
addr , value := stack . pop ( ) , stack . pop ( )
value = U256 ( value )
@ -509,25 +583,26 @@ func opCall(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *Sta
// Get the arguments from the memory
args := memory . Get ( inOffset . Int64 ( ) , inSize . Int64 ( ) )
if len ( value . Bytes ( ) ) > 0 {
gas . Add ( gas , params . CallStipend )
if value . BitLen ( ) > 0 {
gas += params . CallStipend
}
ret , err := env . Call ( contract , address , args , gas , value )
ret , returnGas , err := evm . Call ( contract , address , args , gas , value )
if err != nil {
stack . push ( new ( big . Int ) )
} else {
stack . push ( big . NewInt ( 1 ) )
memory . Set ( retOffset . Uint64 ( ) , retSize . Uint64 ( ) , ret )
}
contract . Gas += returnGas
evm . interpreter . intPool . put ( addr , value , inOffset , inSize , retOffset , retSize )
return nil , nil
}
func opCallCode ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
gas := stack . pop ( )
func opCallCode ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
gas := stack . pop ( ) . Uint64 ( )
// pop gas and value of the stack.
addr , value := stack . pop ( ) , stack . pop ( )
value = U256 ( value )
@ -541,12 +616,11 @@ func opCallCode(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack
// Get the arguments from the memory
args := memory . Get ( inOffset . Int64 ( ) , inSize . Int64 ( ) )
if len ( value . Bytes ( ) ) > 0 {
gas . Add ( gas , params . CallStipend )
if value . BitLen ( ) > 0 {
gas += params . CallStipend
}
ret , err := env . CallCode ( contract , address , args , gas , value )
ret , returnGas , err := evm . CallCode ( contract , address , args , gas , value )
if err != nil {
stack . push ( new ( big . Int ) )
@ -555,46 +629,54 @@ func opCallCode(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack
memory . Set ( retOffset . Uint64 ( ) , retSize . Uint64 ( ) , ret )
}
contract . Gas += returnGas
evm . interpreter . intPool . put ( addr , value , inOffset , inSize , retOffset , retSize )
return nil , nil
}
func opDelegateCall ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opDelegateCall ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
// if not homestead return an error. DELEGATECALL is not supported
// during pre-homestead.
if ! en v . ChainConfig ( ) . IsHomestead ( en v . BlockNumber ) {
if ! evm . ChainConfig ( ) . IsHomestead ( evm . BlockNumber ) {
return nil , fmt . Errorf ( "invalid opcode %x" , DELEGATECALL )
}
gas , to , inOffset , inSize , outOffset , outSize := stack . pop ( ) , stack . pop ( ) , stack . pop ( ) , stack . pop ( ) , stack . pop ( ) , stack . pop ( )
gas , to , inOffset , inSize , outOffset , outSize := stack . pop ( ) . Uint64 ( ) , stack . pop ( ) , stack . pop ( ) , stack . pop ( ) , stack . pop ( ) , stack . pop ( )
toAddr := common . BigToAddress ( to )
args := memory . Get ( inOffset . Int64 ( ) , inSize . Int64 ( ) )
ret , err := env . DelegateCall ( contract , toAddr , args , gas )
ret , returnGas , err := evm . DelegateCall ( contract , toAddr , args , gas )
if err != nil {
stack . push ( new ( big . Int ) )
} else {
stack . push ( big . NewInt ( 1 ) )
memory . Set ( outOffset . Uint64 ( ) , outSize . Uint64 ( ) , ret )
}
contract . Gas += returnGas
evm . interpreter . intPool . put ( to , inOffset , inSize , outOffset , outSize )
return nil , nil
}
func opReturn ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opReturn ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
offset , size := stack . pop ( ) , stack . pop ( )
ret := memory . GetPtr ( offset . Int64 ( ) , size . Int64 ( ) )
evm . interpreter . intPool . put ( offset , size )
return ret , nil
}
func opStop ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
func opStop ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
return nil , nil
}
func opSuicide ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
balance := en v . StateDB . GetBalance ( contract . Address ( ) )
en v . StateDB . AddBalance ( common . BigToAddress ( stack . pop ( ) ) , balance )
func opSuicide ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
balance := evm . StateDB . GetBalance ( contract . Address ( ) )
evm . StateDB . AddBalance ( common . BigToAddress ( stack . pop ( ) ) , balance )
en v . StateDB . Suicide ( contract . Address ( ) )
evm . StateDB . Suicide ( contract . Address ( ) )
return nil , nil
}
@ -603,7 +685,7 @@ func opSuicide(pc *uint64, env *EVM, contract *Contract, memory *Memory, stack *
// make log instruction function
func makeLog ( size int ) executionFunc {
return func ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
return func ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
topics := make ( [ ] common . Hash , size )
mStart , mSize := stack . pop ( ) , stack . pop ( )
for i := 0 ; i < size ; i ++ {
@ -611,22 +693,24 @@ func makeLog(size int) executionFunc {
}
d := memory . Get ( mStart . Int64 ( ) , mSize . Int64 ( ) )
en v . StateDB . AddLog ( & types . Log {
evm . StateDB . AddLog ( & types . Log {
Address : contract . Address ( ) ,
Topics : topics ,
Data : d ,
// This is a non-consensus field, but assigned here because
// core/state doesn't know the current block number.
BlockNumber : en v . BlockNumber . Uint64 ( ) ,
BlockNumber : evm . BlockNumber . Uint64 ( ) ,
} )
evm . interpreter . intPool . put ( mStart , mSize )
return nil , nil
}
}
// make push instruction function
func makePush ( size uint64 , bsize * big . Int ) executionFunc {
return func ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
byts := getData ( contract . Code , new ( big . Int ) . SetUint64 ( * pc + 1 ) , bsize )
return func ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
byts := getData ( contract . Code , evm . interpreter . intPool . get ( ) . SetUint64 ( * pc + 1 ) , bsize )
stack . push ( common . Bytes2Big ( byts ) )
* pc += size
return nil , nil
@ -635,7 +719,7 @@ func makePush(size uint64, bsize *big.Int) executionFunc {
// make push instruction function
func makeDup ( size int64 ) executionFunc {
return func ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
return func ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . dup ( int ( size ) )
return nil , nil
}
@ -645,7 +729,7 @@ func makeDup(size int64) executionFunc {
func makeSwap ( size int64 ) executionFunc {
// switch n + 1 otherwise n would be swapped with n
size += 1
return func ( pc * uint64 , en v * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
return func ( pc * uint64 , evm * EVM , contract * Contract , memory * Memory , stack * Stack ) ( [ ] byte , error ) {
stack . swap ( int ( size ) )
return nil , nil
}