@ -20,46 +20,52 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
type instrFn func ( instr instruction , env Environment , context * Context , memory * Memory , stack * stack )
type instrExFn func ( instr instruction , ret * big . Int , env Environment , context * Context , memory * Memory , stack * stack )
type programInstruction interface {
Do ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack )
}
type instrFn func ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack )
// Do executes the function. This implements programInstruction
func ( fn instrFn ) Do ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
fn ( instr , pc , env , contract , memory , stack )
}
type instruction struct {
op OpCode
pc uint64
fn instrFn
specFn instrExFn
data * big . Int
op OpCode
pc uint64
fn instrFn
data * big . Int
gas * big . Int
spop int
spush int
}
func opStaticJump ( instr instruction , ret * big . Int , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opStaticJump ( instr instruction , pc * uint64 , ret * big . Int , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
ret . Set ( instr . data )
}
func opAdd ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opAdd ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( U256 ( x . Add ( x , y ) ) )
}
func opSub ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSub ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( U256 ( x . Sub ( x , y ) ) )
}
func opMul ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opMul ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( U256 ( x . Mul ( x , y ) ) )
}
func opDiv ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opDiv ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
if y . Cmp ( common . Big0 ) != 0 {
stack . push ( U256 ( x . Div ( x , y ) ) )
@ -68,7 +74,7 @@ func opDiv(instr instruction, env Environment, context *Context, memory *Memory,
}
}
func opSdiv ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSdiv ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := S256 ( stack . pop ( ) ) , S256 ( stack . pop ( ) )
if y . Cmp ( common . Big0 ) == 0 {
stack . push ( new ( big . Int ) )
@ -88,7 +94,7 @@ func opSdiv(instr instruction, env Environment, context *Context, memory *Memory
}
}
func opMod ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opMod ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
if y . Cmp ( common . Big0 ) == 0 {
stack . push ( new ( big . Int ) )
@ -97,7 +103,7 @@ func opMod(instr instruction, env Environment, context *Context, memory *Memory,
}
}
func opSmod ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSmod ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := S256 ( stack . pop ( ) ) , S256 ( stack . pop ( ) )
if y . Cmp ( common . Big0 ) == 0 {
@ -117,12 +123,12 @@ func opSmod(instr instruction, env Environment, context *Context, memory *Memory
}
}
func opExp ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opExp ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( U256 ( x . Exp ( x , y , Pow256 ) ) )
}
func opSignExtend ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSignExtend ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
back := stack . pop ( )
if back . Cmp ( big . NewInt ( 31 ) ) < 0 {
bit := uint ( back . Uint64 ( ) * 8 + 7 )
@ -139,12 +145,12 @@ func opSignExtend(instr instruction, env Environment, context *Context, memory *
}
}
func opNot ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opNot ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x := stack . pop ( )
stack . push ( U256 ( x . Not ( x ) ) )
}
func opLt ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opLt ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
if x . Cmp ( y ) < 0 {
stack . push ( big . NewInt ( 1 ) )
@ -153,7 +159,7 @@ func opLt(instr instruction, env Environment, context *Context, memory *Memory,
}
}
func opGt ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opGt ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
if x . Cmp ( y ) > 0 {
stack . push ( big . NewInt ( 1 ) )
@ -162,7 +168,7 @@ func opGt(instr instruction, env Environment, context *Context, memory *Memory,
}
}
func opSlt ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSlt ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := S256 ( stack . pop ( ) ) , S256 ( stack . pop ( ) )
if x . Cmp ( S256 ( y ) ) < 0 {
stack . push ( big . NewInt ( 1 ) )
@ -171,7 +177,7 @@ func opSlt(instr instruction, env Environment, context *Context, memory *Memory,
}
}
func opSgt ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSgt ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := S256 ( stack . pop ( ) ) , S256 ( stack . pop ( ) )
if x . Cmp ( y ) > 0 {
stack . push ( big . NewInt ( 1 ) )
@ -180,7 +186,7 @@ func opSgt(instr instruction, env Environment, context *Context, memory *Memory,
}
}
func opEq ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opEq ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
if x . Cmp ( y ) == 0 {
stack . push ( big . NewInt ( 1 ) )
@ -189,7 +195,7 @@ func opEq(instr instruction, env Environment, context *Context, memory *Memory,
}
}
func opIszero ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opIszero ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x := stack . pop ( )
if x . Cmp ( common . Big0 ) > 0 {
stack . push ( new ( big . Int ) )
@ -198,19 +204,19 @@ func opIszero(instr instruction, env Environment, context *Context, memory *Memo
}
}
func opAnd ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opAnd ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( x . And ( x , y ) )
}
func opOr ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opOr ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( x . Or ( x , y ) )
}
func opXor ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opXor ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y := stack . pop ( ) , stack . pop ( )
stack . push ( x . Xor ( x , y ) )
}
func opByte ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opByte ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
th , val := stack . pop ( ) , stack . pop ( )
if th . Cmp ( big . NewInt ( 32 ) ) < 0 {
byte := big . NewInt ( int64 ( common . LeftPadBytes ( val . Bytes ( ) , 32 ) [ th . Int64 ( ) ] ) )
@ -219,7 +225,7 @@ func opByte(instr instruction, env Environment, context *Context, memory *Memory
stack . push ( new ( big . Int ) )
}
}
func opAddmod ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opAddmod ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y , z := stack . pop ( ) , stack . pop ( ) , stack . pop ( )
if z . Cmp ( Zero ) > 0 {
add := x . Add ( x , y )
@ -229,7 +235,7 @@ func opAddmod(instr instruction, env Environment, context *Context, memory *Memo
stack . push ( new ( big . Int ) )
}
}
func opMulmod ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opMulmod ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
x , y , z := stack . pop ( ) , stack . pop ( ) , stack . pop ( )
if z . Cmp ( Zero ) > 0 {
mul := x . Mul ( x , y )
@ -240,92 +246,92 @@ func opMulmod(instr instruction, env Environment, context *Context, memory *Memo
}
}
func opSha3 ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSha3 ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
offset , size := stack . pop ( ) , stack . pop ( )
hash := crypto . Sha3 ( memory . Get ( offset . Int64 ( ) , size . Int64 ( ) ) )
stack . push ( common . BytesToBig ( hash ) )
}
func opAddress ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
stack . push ( common . Bytes2Big ( contex t . Address ( ) . Bytes ( ) ) )
func opAddress ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( common . Bytes2Big ( contrac t . Address ( ) . Bytes ( ) ) )
}
func opBalance ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opBalance ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
addr := common . BigToAddress ( stack . pop ( ) )
balance := env . State ( ) . GetBalance ( addr )
balance := env . Db ( ) . GetBalance ( addr )
stack . push ( new ( big . Int ) . Set ( balance ) )
}
func opOrigin ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opOrigin ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( env . Origin ( ) . Big ( ) )
}
func opCaller ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
stack . push ( common . Bytes2Big ( contex t . caller . Address ( ) . Bytes ( ) ) )
func opCaller ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( common . Bytes2Big ( contrac t . caller . Address ( ) . Bytes ( ) ) )
}
func opCallValue ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
stack . push ( new ( big . Int ) . Set ( contex t . value ) )
func opCallValue ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( new ( big . Int ) . Set ( contrac t . value ) )
}
func opCalldataLoad ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
stack . push ( common . Bytes2Big ( getData ( contex t . Input , stack . pop ( ) , common . Big32 ) ) )
func opCalldataLoad ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( common . Bytes2Big ( getData ( contrac t . Input , stack . pop ( ) , common . Big32 ) ) )
}
func opCalldataSize ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
stack . push ( big . NewInt ( int64 ( len ( contex t . Input ) ) ) )
func opCalldataSize ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( big . NewInt ( int64 ( len ( contrac t . Input ) ) ) )
}
func opCalldataCopy ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opCalldataCopy ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
var (
mOff = stack . pop ( )
cOff = stack . pop ( )
l = stack . pop ( )
)
memory . Set ( mOff . Uint64 ( ) , l . Uint64 ( ) , getData ( contex t . Input , cOff , l ) )
memory . Set ( mOff . Uint64 ( ) , l . Uint64 ( ) , getData ( contrac t . Input , cOff , l ) )
}
func opExtCodeSize ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opExtCodeSize ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
addr := common . BigToAddress ( stack . pop ( ) )
l := big . NewInt ( int64 ( len ( env . State ( ) . GetCode ( addr ) ) ) )
l := big . NewInt ( int64 ( len ( env . Db ( ) . GetCode ( addr ) ) ) )
stack . push ( l )
}
func opCodeSize ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
l := big . NewInt ( int64 ( len ( contex t . Code ) ) )
func opCodeSize ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
l := big . NewInt ( int64 ( len ( contrac t . Code ) ) )
stack . push ( l )
}
func opCodeCopy ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opCodeCopy ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
var (
mOff = stack . pop ( )
cOff = stack . pop ( )
l = stack . pop ( )
)
codeCopy := getData ( contex t . Code , cOff , l )
codeCopy := getData ( contrac t . Code , cOff , l )
memory . Set ( mOff . Uint64 ( ) , l . Uint64 ( ) , codeCopy )
}
func opExtCodeCopy ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opExtCodeCopy ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
var (
addr = common . BigToAddress ( stack . pop ( ) )
mOff = stack . pop ( )
cOff = stack . pop ( )
l = stack . pop ( )
)
codeCopy := getData ( env . State ( ) . GetCode ( addr ) , cOff , l )
codeCopy := getData ( env . Db ( ) . GetCode ( addr ) , cOff , l )
memory . Set ( mOff . Uint64 ( ) , l . Uint64 ( ) , codeCopy )
}
func opGasprice ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
stack . push ( new ( big . Int ) . Set ( contex t . Price ) )
func opGasprice ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( new ( big . Int ) . Set ( contrac t . Price ) )
}
func opBlockhash ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opBlockhash ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
num := stack . pop ( )
n := new ( big . Int ) . Sub ( env . BlockNumber ( ) , common . Big257 )
@ -336,43 +342,43 @@ func opBlockhash(instr instruction, env Environment, context *Context, memory *M
}
}
func opCoinbase ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opCoinbase ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( env . Coinbase ( ) . Big ( ) )
}
func opTimestamp ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opTimestamp ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( U256 ( new ( big . Int ) . Set ( env . Time ( ) ) ) )
}
func opNumber ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opNumber ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( U256 ( new ( big . Int ) . Set ( env . BlockNumber ( ) ) ) )
}
func opDifficulty ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opDifficulty ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( U256 ( new ( big . Int ) . Set ( env . Difficulty ( ) ) ) )
}
func opGasLimit ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opGasLimit ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( U256 ( new ( big . Int ) . Set ( env . GasLimit ( ) ) ) )
}
func opPop ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opPop ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . pop ( )
}
func opPush ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opPush ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( new ( big . Int ) . Set ( instr . data ) )
}
func opDup ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opDup ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . dup ( int ( instr . data . Int64 ( ) ) )
}
func opSwap ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSwap ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . swap ( int ( instr . data . Int64 ( ) ) )
}
func opLog ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opLog ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
n := int ( instr . data . Int64 ( ) )
topics := make ( [ ] common . Hash , n )
mStart , mSize := stack . pop ( ) , stack . pop ( )
@ -381,85 +387,88 @@ func opLog(instr instruction, env Environment, context *Context, memory *Memory,
}
d := memory . Get ( mStart . Int64 ( ) , mSize . Int64 ( ) )
log := state . NewLog ( contex t . Address ( ) , topics , d , env . BlockNumber ( ) . Uint64 ( ) )
log := NewLog ( contrac t . Address ( ) , topics , d , env . BlockNumber ( ) . Uint64 ( ) )
env . AddLog ( log )
}
func opMload ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opMload ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
offset := stack . pop ( )
val := common . BigD ( memory . Get ( offset . Int64 ( ) , 32 ) )
stack . push ( val )
}
func opMstore ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opMstore ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
// pop value of the stack
mStart , val := stack . pop ( ) , stack . pop ( )
memory . Set ( mStart . Uint64 ( ) , 32 , common . BigToBytes ( val , 256 ) )
}
func opMstore8 ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opMstore8 ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
off , val := stack . pop ( ) . Int64 ( ) , stack . pop ( ) . Int64 ( )
memory . store [ off ] = byte ( val & 0xff )
}
func opSload ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSload ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
loc := common . BigToHash ( stack . pop ( ) )
val := env . State ( ) . GetState ( contex t . Address ( ) , loc ) . Big ( )
val := env . Db ( ) . GetState ( contrac t . Address ( ) , loc ) . Big ( )
stack . push ( val )
}
func opSstore ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opSstore ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
loc := common . BigToHash ( stack . pop ( ) )
val := stack . pop ( )
env . State ( ) . SetState ( contex t . Address ( ) , loc , common . BigToHash ( val ) )
env . Db ( ) . SetState ( contrac t . Address ( ) , loc , common . BigToHash ( val ) )
}
func opJump ( instr instruction , env Environment , context * Context , memory * Memory , stack * stack ) { }
func opJumpi ( instr instruction , env Environment , context * Context , memory * Memory , stack * stack ) { }
func opJumpdest ( instr instruction , env Environment , context * Context , memory * Memory , stack * stack ) { }
func opJump ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
}
func opJumpi ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
}
func opJumpdest ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
}
func opPc ( instr instruction , env Environment , context * Context , memory * Memory , stack * stack ) {
func opPc ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( new ( big . Int ) . Set ( instr . data ) )
}
func opMsize ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opMsize ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( big . NewInt ( int64 ( memory . Len ( ) ) ) )
}
func opGas ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
stack . push ( new ( big . Int ) . Set ( contex t . Gas ) )
func opGas ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
stack . push ( new ( big . Int ) . Set ( contrac t . Gas ) )
}
func opCreate ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opCreate ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
var (
value = stack . pop ( )
offset , size = stack . pop ( ) , stack . pop ( )
input = memory . Get ( offset . Int64 ( ) , size . Int64 ( ) )
gas = new ( big . Int ) . Set ( contex t . Gas )
gas = new ( big . Int ) . Set ( contrac t . Gas )
addr common . Address
ret [ ] byte
suberr error
)
contex t . UseGas ( contex t . Gas )
ret , suberr , ref : = env . Create ( contex t , input , gas , contex t . Price , value )
contrac t . UseGas ( contrac t . Gas )
ret , addr , suberr = env . Create ( contrac t , input , gas , contrac t . Price , value )
if suberr != nil {
stack . push ( new ( big . Int ) )
} else {
// gas < len(ret) * Createinstr.dataGas == NO_CODE
dataGas := big . NewInt ( int64 ( len ( ret ) ) )
dataGas . Mul ( dataGas , params . CreateDataGas )
if contex t . UseGas ( dataGas ) {
r ef . SetCode ( ret )
if contrac t . UseGas ( dataGas ) {
env . Db ( ) . SetCode ( addr , ret )
}
addr = ref . Address ( )
stack . push ( addr . Big ( ) )
}
}
func opCall ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opCall ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
gas := stack . pop ( )
// pop gas and value of the stack.
addr , value := stack . pop ( ) , stack . pop ( )
@ -478,7 +487,7 @@ func opCall(instr instruction, env Environment, context *Context, memory *Memory
gas . Add ( gas , params . CallStipend )
}
ret , err := env . Call ( contex t , address , args , gas , contex t . Price , value )
ret , err := env . Call ( contrac t , address , args , gas , contrac t . Price , value )
if err != nil {
stack . push ( new ( big . Int ) )
@ -490,7 +499,7 @@ func opCall(instr instruction, env Environment, context *Context, memory *Memory
}
}
func opCallCode ( instr instruction , env Environment , context * Contex t , memory * Memory , stack * stack ) {
func opCallCode ( instr instruction , pc * uint64 , env Environment , contract * Contrac t , memory * Memory , stack * stack ) {
gas := stack . pop ( )
// pop gas and value of the stack.
addr , value := stack . pop ( ) , stack . pop ( )
@ -509,7 +518,7 @@ func opCallCode(instr instruction, env Environment, context *Context, memory *Me
gas . Add ( gas , params . CallStipend )
}
ret , err := env . CallCode ( contex t , address , args , gas , contex t . Price , value )
ret , err := env . CallCode ( contrac t , address , args , gas , contrac t . Price , value )
if err != nil {
stack . push ( new ( big . Int ) )
@ -521,14 +530,58 @@ func opCallCode(instr instruction, env Environment, context *Context, memory *Me
}
}
func opReturn ( instr instruction , env Environment , context * Context , memory * Memory , stack * stack ) { }
func opStop ( instr instruction , env Environment , context * Context , memory * Memory , stack * stack ) { }
func opReturn ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
}
func opStop ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
}
func opSuicide ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
//receiver := env.Db().GetOrNewStateObject(common.BigToAddress(stack.pop()))
//receiver.AddBalance(balance)
balance := env . Db ( ) . GetBalance ( contract . Address ( ) )
env . Db ( ) . AddBalance ( common . BigToAddress ( stack . pop ( ) ) , balance )
env . Db ( ) . Delete ( contract . Address ( ) )
}
// following functions are used by the instruction jump table
// make log instruction function
func makeLog ( size int ) instrFn {
return func ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
topics := make ( [ ] common . Hash , size )
mStart , mSize := stack . pop ( ) , stack . pop ( )
for i := 0 ; i < size ; i ++ {
topics [ i ] = common . BigToHash ( stack . pop ( ) )
}
d := memory . Get ( mStart . Int64 ( ) , mSize . Int64 ( ) )
log := NewLog ( contract . Address ( ) , topics , d , env . BlockNumber ( ) . Uint64 ( ) )
env . AddLog ( log )
}
}
func opSuicide ( instr instruction , env Environment , context * Context , memory * Memory , stack * stack ) {
receiver := env . State ( ) . GetOrNewStateObject ( common . BigToAddress ( stack . pop ( ) ) )
balance := env . State ( ) . GetBalance ( context . Address ( ) )
// make push instruction function
func makePush ( size uint64 , bsize * big . Int ) instrFn {
return func ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
byts := getData ( contract . Code , new ( big . Int ) . SetUint64 ( * pc + 1 ) , bsize )
stack . push ( common . Bytes2Big ( byts ) )
* pc += size
}
}
receiver . AddBalance ( balance )
// make push instruction function
func makeDup ( size int64 ) instrFn {
return func ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
stack . dup ( int ( size ) )
}
}
env . State ( ) . Delete ( context . Address ( ) )
// make swap instruction function
func makeSwap ( size int64 ) instrFn {
// switch n + 1 otherwise n would be swapped with n
size += 1
return func ( instr instruction , pc * uint64 , env Environment , contract * Contract , memory * Memory , stack * stack ) {
stack . swap ( int ( size ) )
}
}