@ -77,766 +77,5 @@ private:
std : : function < void ( ) > m_onFail ;
} ;
// TODO: Move it to cpp file. Not done to make review easier.
inline bytesConstRef VM : : go ( ExtVMFace & _ext , OnOpFunc const & _onOp , uint64_t _steps )
{
auto memNeed = [ ] ( dev : : u256 _offset , dev : : u256 _size ) { return _size ? ( bigint ) _offset + _size : ( bigint ) 0 ; } ;
if ( m_jumpDests . empty ( ) )
for ( unsigned i = 0 ; i < _ext . code . size ( ) ; + + i )
if ( _ext . code [ i ] = = ( byte ) Instruction : : JUMPDEST )
m_jumpDests . insert ( i ) ;
else if ( _ext . code [ i ] > = ( byte ) Instruction : : PUSH1 & & _ext . code [ i ] < = ( byte ) Instruction : : PUSH32 )
i + = _ext . code [ i ] - ( unsigned ) Instruction : : PUSH1 + 1 ;
u256 nextPC = m_curPC + 1 ;
auto osteps = _steps ;
for ( bool stopped = false ; ! stopped & & _steps - - ; m_curPC = nextPC , nextPC = m_curPC + 1 )
{
// INSTRUCTION...
Instruction inst = ( Instruction ) _ext . getCode ( m_curPC ) ;
// FEES...
bigint runGas = c_stepGas ;
bigint newTempSize = m_temp . size ( ) ;
bigint copySize = 0 ;
auto onOperation = [ & ] ( )
{
if ( _onOp )
_onOp ( osteps - _steps - 1 , inst , newTempSize > m_temp . size ( ) ? ( newTempSize - m_temp . size ( ) ) / 32 : bigint ( 0 ) , runGas , this , & _ext ) ;
} ;
// should work, but just seems to result in immediate errorless exit on initial execution. yeah. weird.
//m_onFail = std::function<void()>(onOperation);
switch ( inst )
{
case Instruction : : STOP :
runGas = 0 ;
break ;
case Instruction : : SUICIDE :
require ( 1 ) ;
runGas = 0 ;
break ;
case Instruction : : SSTORE :
require ( 2 ) ;
if ( ! _ext . store ( m_stack . back ( ) ) & & m_stack [ m_stack . size ( ) - 2 ] )
runGas = c_sstoreSetGas ;
else if ( _ext . store ( m_stack . back ( ) ) & & ! m_stack [ m_stack . size ( ) - 2 ] )
{
runGas = 0 ;
_ext . sub . refunds + = c_sstoreRefundGas ;
}
else
runGas = c_sstoreResetGas ;
break ;
case Instruction : : SLOAD :
require ( 1 ) ;
runGas = c_sloadGas ;
break ;
// These all operate on memory and therefore potentially expand it:
case Instruction : : MSTORE :
require ( 2 ) ;
newTempSize = ( bigint ) m_stack . back ( ) + 32 ;
break ;
case Instruction : : MSTORE8 :
require ( 2 ) ;
newTempSize = ( bigint ) m_stack . back ( ) + 1 ;
break ;
case Instruction : : MLOAD :
require ( 1 ) ;
newTempSize = ( bigint ) m_stack . back ( ) + 32 ;
break ;
case Instruction : : RETURN :
require ( 2 ) ;
newTempSize = memNeed ( m_stack . back ( ) , m_stack [ m_stack . size ( ) - 2 ] ) ;
break ;
case Instruction : : SHA3 :
require ( 2 ) ;
runGas = c_sha3Gas + ( m_stack [ m_stack . size ( ) - 2 ] + 31 ) / 32 * c_sha3WordGas ;
newTempSize = memNeed ( m_stack . back ( ) , m_stack [ m_stack . size ( ) - 2 ] ) ;
break ;
case Instruction : : CALLDATACOPY :
require ( 3 ) ;
copySize = m_stack [ m_stack . size ( ) - 3 ] ;
newTempSize = memNeed ( m_stack . back ( ) , m_stack [ m_stack . size ( ) - 3 ] ) ;
break ;
case Instruction : : CODECOPY :
require ( 3 ) ;
copySize = m_stack [ m_stack . size ( ) - 3 ] ;
newTempSize = memNeed ( m_stack . back ( ) , m_stack [ m_stack . size ( ) - 3 ] ) ;
break ;
case Instruction : : EXTCODECOPY :
require ( 4 ) ;
copySize = m_stack [ m_stack . size ( ) - 4 ] ;
newTempSize = memNeed ( m_stack [ m_stack . size ( ) - 2 ] , m_stack [ m_stack . size ( ) - 4 ] ) ;
break ;
case Instruction : : BALANCE :
require ( 1 ) ;
runGas = c_balanceGas ;
break ;
case Instruction : : LOG0 :
case Instruction : : LOG1 :
case Instruction : : LOG2 :
case Instruction : : LOG3 :
case Instruction : : LOG4 :
{
unsigned n = ( unsigned ) inst - ( unsigned ) Instruction : : LOG0 ;
require ( n + 2 ) ;
runGas = c_logGas + c_logTopicGas * n + ( bigint ) c_logDataGas * m_stack [ m_stack . size ( ) - 2 ] ;
newTempSize = memNeed ( m_stack [ m_stack . size ( ) - 1 ] , m_stack [ m_stack . size ( ) - 2 ] ) ;
break ;
}
case Instruction : : CALL :
case Instruction : : CALLCODE :
require ( 7 ) ;
runGas = ( bigint ) c_callGas + m_stack [ m_stack . size ( ) - 1 ] ;
newTempSize = std : : max ( memNeed ( m_stack [ m_stack . size ( ) - 6 ] , m_stack [ m_stack . size ( ) - 7 ] ) , memNeed ( m_stack [ m_stack . size ( ) - 4 ] , m_stack [ m_stack . size ( ) - 5 ] ) ) ;
break ;
case Instruction : : CREATE :
{
require ( 3 ) ;
newTempSize = memNeed ( m_stack [ m_stack . size ( ) - 2 ] , m_stack [ m_stack . size ( ) - 3 ] ) ;
runGas = c_createGas ;
break ;
}
case Instruction : : EXP :
{
require ( 2 ) ;
auto expon = m_stack [ m_stack . size ( ) - 2 ] ;
runGas = c_expGas + c_expByteGas * ( 32 - ( h256 ( expon ) . firstBitSet ( ) / 8 ) ) ;
break ;
}
case Instruction : : BLOCKHASH :
require ( 1 ) ;
break ;
case Instruction : : PC :
case Instruction : : MSIZE :
case Instruction : : GAS :
case Instruction : : JUMPDEST :
case Instruction : : ADDRESS :
case Instruction : : ORIGIN :
case Instruction : : CALLER :
case Instruction : : CALLVALUE :
case Instruction : : CALLDATASIZE :
case Instruction : : CODESIZE :
case Instruction : : GASPRICE :
case Instruction : : COINBASE :
case Instruction : : TIMESTAMP :
case Instruction : : NUMBER :
case Instruction : : DIFFICULTY :
case Instruction : : GASLIMIT :
case Instruction : : PUSH1 :
case Instruction : : PUSH2 :
case Instruction : : PUSH3 :
case Instruction : : PUSH4 :
case Instruction : : PUSH5 :
case Instruction : : PUSH6 :
case Instruction : : PUSH7 :
case Instruction : : PUSH8 :
case Instruction : : PUSH9 :
case Instruction : : PUSH10 :
case Instruction : : PUSH11 :
case Instruction : : PUSH12 :
case Instruction : : PUSH13 :
case Instruction : : PUSH14 :
case Instruction : : PUSH15 :
case Instruction : : PUSH16 :
case Instruction : : PUSH17 :
case Instruction : : PUSH18 :
case Instruction : : PUSH19 :
case Instruction : : PUSH20 :
case Instruction : : PUSH21 :
case Instruction : : PUSH22 :
case Instruction : : PUSH23 :
case Instruction : : PUSH24 :
case Instruction : : PUSH25 :
case Instruction : : PUSH26 :
case Instruction : : PUSH27 :
case Instruction : : PUSH28 :
case Instruction : : PUSH29 :
case Instruction : : PUSH30 :
case Instruction : : PUSH31 :
case Instruction : : PUSH32 :
break ;
case Instruction : : NOT :
case Instruction : : ISZERO :
case Instruction : : CALLDATALOAD :
case Instruction : : EXTCODESIZE :
case Instruction : : POP :
case Instruction : : JUMP :
require ( 1 ) ;
break ;
case Instruction : : ADD :
case Instruction : : MUL :
case Instruction : : SUB :
case Instruction : : DIV :
case Instruction : : SDIV :
case Instruction : : MOD :
case Instruction : : SMOD :
case Instruction : : LT :
case Instruction : : GT :
case Instruction : : SLT :
case Instruction : : SGT :
case Instruction : : EQ :
case Instruction : : AND :
case Instruction : : OR :
case Instruction : : XOR :
case Instruction : : BYTE :
case Instruction : : JUMPI :
case Instruction : : SIGNEXTEND :
require ( 2 ) ;
break ;
case Instruction : : ADDMOD :
case Instruction : : MULMOD :
require ( 3 ) ;
break ;
case Instruction : : DUP1 :
case Instruction : : DUP2 :
case Instruction : : DUP3 :
case Instruction : : DUP4 :
case Instruction : : DUP5 :
case Instruction : : DUP6 :
case Instruction : : DUP7 :
case Instruction : : DUP8 :
case Instruction : : DUP9 :
case Instruction : : DUP10 :
case Instruction : : DUP11 :
case Instruction : : DUP12 :
case Instruction : : DUP13 :
case Instruction : : DUP14 :
case Instruction : : DUP15 :
case Instruction : : DUP16 :
require ( 1 + ( int ) inst - ( int ) Instruction : : DUP1 ) ;
break ;
case Instruction : : SWAP1 :
case Instruction : : SWAP2 :
case Instruction : : SWAP3 :
case Instruction : : SWAP4 :
case Instruction : : SWAP5 :
case Instruction : : SWAP6 :
case Instruction : : SWAP7 :
case Instruction : : SWAP8 :
case Instruction : : SWAP9 :
case Instruction : : SWAP10 :
case Instruction : : SWAP11 :
case Instruction : : SWAP12 :
case Instruction : : SWAP13 :
case Instruction : : SWAP14 :
case Instruction : : SWAP15 :
case Instruction : : SWAP16 :
require ( ( int ) inst - ( int ) Instruction : : SWAP1 + 2 ) ;
break ;
default :
BOOST_THROW_EXCEPTION ( BadInstruction ( ) ) ;
}
newTempSize = ( newTempSize + 31 ) / 32 * 32 ;
if ( newTempSize > m_temp . size ( ) )
runGas + = c_memoryGas * ( newTempSize - m_temp . size ( ) ) / 32 ;
runGas + = c_copyGas * ( copySize + 31 ) / 32 ;
onOperation ( ) ;
// if (_onOp)
// _onOp(osteps - _steps - 1, inst, newTempSize > m_temp.size() ? (newTempSize - m_temp.size()) / 32 : bigint(0), runGas, this, &_ext);
if ( m_gas < runGas )
{
// Out of gas!
m_gas = 0 ;
BOOST_THROW_EXCEPTION ( OutOfGas ( ) ) ;
}
m_gas = ( u256 ) ( ( bigint ) m_gas - runGas ) ;
if ( newTempSize > m_temp . size ( ) )
m_temp . resize ( ( size_t ) newTempSize ) ;
// EXECUTE...
switch ( inst )
{
case Instruction : : ADD :
//pops two items and pushes S[-1] + S[-2] mod 2^256.
m_stack [ m_stack . size ( ) - 2 ] + = m_stack . back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : MUL :
//pops two items and pushes S[-1] * S[-2] mod 2^256.
m_stack [ m_stack . size ( ) - 2 ] * = m_stack . back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : SUB :
m_stack [ m_stack . size ( ) - 2 ] = m_stack . back ( ) - m_stack [ m_stack . size ( ) - 2 ] ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : DIV :
m_stack [ m_stack . size ( ) - 2 ] = m_stack [ m_stack . size ( ) - 2 ] ? m_stack . back ( ) / m_stack [ m_stack . size ( ) - 2 ] : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : SDIV :
m_stack [ m_stack . size ( ) - 2 ] = m_stack [ m_stack . size ( ) - 2 ] ? s2u ( u2s ( m_stack . back ( ) ) / u2s ( m_stack [ m_stack . size ( ) - 2 ] ) ) : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : MOD :
m_stack [ m_stack . size ( ) - 2 ] = m_stack [ m_stack . size ( ) - 2 ] ? m_stack . back ( ) % m_stack [ m_stack . size ( ) - 2 ] : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : SMOD :
m_stack [ m_stack . size ( ) - 2 ] = m_stack [ m_stack . size ( ) - 2 ] ? s2u ( u2s ( m_stack . back ( ) ) % u2s ( m_stack [ m_stack . size ( ) - 2 ] ) ) : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : EXP :
{
auto base = m_stack . back ( ) ;
auto expon = m_stack [ m_stack . size ( ) - 2 ] ;
m_stack . pop_back ( ) ;
m_stack . back ( ) = ( u256 ) boost : : multiprecision : : powm ( ( bigint ) base , ( bigint ) expon , bigint ( 2 ) < < 256 ) ;
break ;
}
case Instruction : : NOT :
m_stack . back ( ) = ~ m_stack . back ( ) ;
break ;
case Instruction : : LT :
m_stack [ m_stack . size ( ) - 2 ] = m_stack . back ( ) < m_stack [ m_stack . size ( ) - 2 ] ? 1 : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : GT :
m_stack [ m_stack . size ( ) - 2 ] = m_stack . back ( ) > m_stack [ m_stack . size ( ) - 2 ] ? 1 : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : SLT :
m_stack [ m_stack . size ( ) - 2 ] = u2s ( m_stack . back ( ) ) < u2s ( m_stack [ m_stack . size ( ) - 2 ] ) ? 1 : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : SGT :
m_stack [ m_stack . size ( ) - 2 ] = u2s ( m_stack . back ( ) ) > u2s ( m_stack [ m_stack . size ( ) - 2 ] ) ? 1 : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : EQ :
m_stack [ m_stack . size ( ) - 2 ] = m_stack . back ( ) = = m_stack [ m_stack . size ( ) - 2 ] ? 1 : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : ISZERO :
m_stack . back ( ) = m_stack . back ( ) ? 0 : 1 ;
break ;
case Instruction : : AND :
m_stack [ m_stack . size ( ) - 2 ] = m_stack . back ( ) & m_stack [ m_stack . size ( ) - 2 ] ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : OR :
m_stack [ m_stack . size ( ) - 2 ] = m_stack . back ( ) | m_stack [ m_stack . size ( ) - 2 ] ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : XOR :
m_stack [ m_stack . size ( ) - 2 ] = m_stack . back ( ) ^ m_stack [ m_stack . size ( ) - 2 ] ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : BYTE :
m_stack [ m_stack . size ( ) - 2 ] = m_stack . back ( ) < 32 ? ( m_stack [ m_stack . size ( ) - 2 ] > > ( unsigned ) ( 8 * ( 31 - m_stack . back ( ) ) ) ) & 0xff : 0 ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : ADDMOD :
m_stack [ m_stack . size ( ) - 3 ] = u256 ( ( bigint ( m_stack . back ( ) ) + bigint ( m_stack [ m_stack . size ( ) - 2 ] ) ) % m_stack [ m_stack . size ( ) - 3 ] ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : MULMOD :
m_stack [ m_stack . size ( ) - 3 ] = u256 ( ( bigint ( m_stack . back ( ) ) * bigint ( m_stack [ m_stack . size ( ) - 2 ] ) ) % m_stack [ m_stack . size ( ) - 3 ] ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : SIGNEXTEND :
if ( m_stack . back ( ) < 31 )
{
unsigned const testBit ( m_stack . back ( ) * 8 + 7 ) ;
u256 & number = m_stack [ m_stack . size ( ) - 2 ] ;
u256 mask = ( ( u256 ( 1 ) < < testBit ) - 1 ) ;
if ( boost : : multiprecision : : bit_test ( number , testBit ) )
number | = ~ mask ;
else
number & = mask ;
}
m_stack . pop_back ( ) ;
break ;
case Instruction : : SHA3 :
{
unsigned inOff = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned inSize = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
m_stack . push_back ( sha3 ( bytesConstRef ( m_temp . data ( ) + inOff , inSize ) ) ) ;
break ;
}
case Instruction : : ADDRESS :
m_stack . push_back ( fromAddress ( _ext . myAddress ) ) ;
break ;
case Instruction : : ORIGIN :
m_stack . push_back ( fromAddress ( _ext . origin ) ) ;
break ;
case Instruction : : BALANCE :
{
m_stack . back ( ) = _ext . balance ( asAddress ( m_stack . back ( ) ) ) ;
break ;
}
case Instruction : : CALLER :
m_stack . push_back ( fromAddress ( _ext . caller ) ) ;
break ;
case Instruction : : CALLVALUE :
m_stack . push_back ( _ext . value ) ;
break ;
case Instruction : : CALLDATALOAD :
{
if ( ( unsigned ) m_stack . back ( ) + ( uint64_t ) 31 < _ext . data . size ( ) )
m_stack . back ( ) = ( u256 ) * ( h256 const * ) ( _ext . data . data ( ) + ( unsigned ) m_stack . back ( ) ) ;
else
{
h256 r ;
for ( uint64_t i = ( unsigned ) m_stack . back ( ) , e = ( unsigned ) m_stack . back ( ) + ( uint64_t ) 32 , j = 0 ; i < e ; + + i , + + j )
r [ j ] = i < _ext . data . size ( ) ? _ext . data [ i ] : 0 ;
m_stack . back ( ) = ( u256 ) r ;
}
break ;
}
case Instruction : : CALLDATASIZE :
m_stack . push_back ( _ext . data . size ( ) ) ;
break ;
case Instruction : : CODESIZE :
m_stack . push_back ( _ext . code . size ( ) ) ;
break ;
case Instruction : : EXTCODESIZE :
m_stack . back ( ) = _ext . codeAt ( asAddress ( m_stack . back ( ) ) ) . size ( ) ;
break ;
case Instruction : : CALLDATACOPY :
case Instruction : : CODECOPY :
case Instruction : : EXTCODECOPY :
{
Address a ;
if ( inst = = Instruction : : EXTCODECOPY )
{
a = asAddress ( m_stack . back ( ) ) ;
m_stack . pop_back ( ) ;
}
unsigned offset = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
u256 index = m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned size = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned sizeToBeCopied ;
switch ( inst )
{
case Instruction : : CALLDATACOPY :
sizeToBeCopied = index + ( bigint ) size > ( u256 ) _ext . data . size ( ) ? ( u256 ) _ext . data . size ( ) < index ? 0 : _ext . data . size ( ) - ( unsigned ) index : size ;
memcpy ( m_temp . data ( ) + offset , _ext . data . data ( ) + ( unsigned ) index , sizeToBeCopied ) ;
break ;
case Instruction : : CODECOPY :
sizeToBeCopied = index + ( bigint ) size > ( u256 ) _ext . code . size ( ) ? ( u256 ) _ext . code . size ( ) < index ? 0 : _ext . code . size ( ) - ( unsigned ) index : size ;
memcpy ( m_temp . data ( ) + offset , _ext . code . data ( ) + ( unsigned ) index , sizeToBeCopied ) ;
break ;
case Instruction : : EXTCODECOPY :
sizeToBeCopied = index + ( bigint ) size > ( u256 ) _ext . codeAt ( a ) . size ( ) ? ( u256 ) _ext . codeAt ( a ) . size ( ) < index ? 0 : _ext . codeAt ( a ) . size ( ) - ( unsigned ) index : size ;
memcpy ( m_temp . data ( ) + offset , _ext . codeAt ( a ) . data ( ) + ( unsigned ) index , sizeToBeCopied ) ;
break ;
default :
// this is unreachable, but if someone introduces a bug in the future, he may get here.
assert ( false ) ;
BOOST_THROW_EXCEPTION ( InvalidOpcode ( ) < < errinfo_comment ( " CALLDATACOPY, CODECOPY or EXTCODECOPY instruction requested. " ) ) ;
break ;
}
memset ( m_temp . data ( ) + offset + sizeToBeCopied , 0 , size - sizeToBeCopied ) ;
break ;
}
case Instruction : : GASPRICE :
m_stack . push_back ( _ext . gasPrice ) ;
break ;
case Instruction : : BLOCKHASH :
m_stack . back ( ) = ( u256 ) _ext . blockhash ( m_stack . back ( ) ) ;
break ;
case Instruction : : COINBASE :
m_stack . push_back ( ( u160 ) _ext . currentBlock . coinbaseAddress ) ;
break ;
case Instruction : : TIMESTAMP :
m_stack . push_back ( _ext . currentBlock . timestamp ) ;
break ;
case Instruction : : NUMBER :
m_stack . push_back ( _ext . currentBlock . number ) ;
break ;
case Instruction : : DIFFICULTY :
m_stack . push_back ( _ext . currentBlock . difficulty ) ;
break ;
case Instruction : : GASLIMIT :
m_stack . push_back ( 1000000 ) ;
break ;
case Instruction : : PUSH1 :
case Instruction : : PUSH2 :
case Instruction : : PUSH3 :
case Instruction : : PUSH4 :
case Instruction : : PUSH5 :
case Instruction : : PUSH6 :
case Instruction : : PUSH7 :
case Instruction : : PUSH8 :
case Instruction : : PUSH9 :
case Instruction : : PUSH10 :
case Instruction : : PUSH11 :
case Instruction : : PUSH12 :
case Instruction : : PUSH13 :
case Instruction : : PUSH14 :
case Instruction : : PUSH15 :
case Instruction : : PUSH16 :
case Instruction : : PUSH17 :
case Instruction : : PUSH18 :
case Instruction : : PUSH19 :
case Instruction : : PUSH20 :
case Instruction : : PUSH21 :
case Instruction : : PUSH22 :
case Instruction : : PUSH23 :
case Instruction : : PUSH24 :
case Instruction : : PUSH25 :
case Instruction : : PUSH26 :
case Instruction : : PUSH27 :
case Instruction : : PUSH28 :
case Instruction : : PUSH29 :
case Instruction : : PUSH30 :
case Instruction : : PUSH31 :
case Instruction : : PUSH32 :
{
int i = ( int ) inst - ( int ) Instruction : : PUSH1 + 1 ;
nextPC = m_curPC + 1 ;
m_stack . push_back ( 0 ) ;
for ( ; i - - ; nextPC + + )
m_stack . back ( ) = ( m_stack . back ( ) < < 8 ) | _ext . getCode ( nextPC ) ;
break ;
}
case Instruction : : POP :
m_stack . pop_back ( ) ;
break ;
case Instruction : : DUP1 :
case Instruction : : DUP2 :
case Instruction : : DUP3 :
case Instruction : : DUP4 :
case Instruction : : DUP5 :
case Instruction : : DUP6 :
case Instruction : : DUP7 :
case Instruction : : DUP8 :
case Instruction : : DUP9 :
case Instruction : : DUP10 :
case Instruction : : DUP11 :
case Instruction : : DUP12 :
case Instruction : : DUP13 :
case Instruction : : DUP14 :
case Instruction : : DUP15 :
case Instruction : : DUP16 :
{
auto n = 1 + ( int ) inst - ( int ) Instruction : : DUP1 ;
m_stack . push_back ( m_stack [ m_stack . size ( ) - n ] ) ;
break ;
}
case Instruction : : SWAP1 :
case Instruction : : SWAP2 :
case Instruction : : SWAP3 :
case Instruction : : SWAP4 :
case Instruction : : SWAP5 :
case Instruction : : SWAP6 :
case Instruction : : SWAP7 :
case Instruction : : SWAP8 :
case Instruction : : SWAP9 :
case Instruction : : SWAP10 :
case Instruction : : SWAP11 :
case Instruction : : SWAP12 :
case Instruction : : SWAP13 :
case Instruction : : SWAP14 :
case Instruction : : SWAP15 :
case Instruction : : SWAP16 :
{
unsigned n = ( int ) inst - ( int ) Instruction : : SWAP1 + 2 ;
auto d = m_stack . back ( ) ;
m_stack . back ( ) = m_stack [ m_stack . size ( ) - n ] ;
m_stack [ m_stack . size ( ) - n ] = d ;
break ;
}
case Instruction : : MLOAD :
{
m_stack . back ( ) = ( u256 ) * ( h256 const * ) ( m_temp . data ( ) + ( unsigned ) m_stack . back ( ) ) ;
break ;
}
case Instruction : : MSTORE :
{
* ( h256 * ) & m_temp [ ( unsigned ) m_stack . back ( ) ] = ( h256 ) m_stack [ m_stack . size ( ) - 2 ] ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
}
case Instruction : : MSTORE8 :
{
m_temp [ ( unsigned ) m_stack . back ( ) ] = ( byte ) ( m_stack [ m_stack . size ( ) - 2 ] & 0xff ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
}
case Instruction : : SLOAD :
m_stack . back ( ) = _ext . store ( m_stack . back ( ) ) ;
break ;
case Instruction : : SSTORE :
_ext . setStore ( m_stack . back ( ) , m_stack [ m_stack . size ( ) - 2 ] ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : JUMP :
nextPC = m_stack . back ( ) ;
if ( ! m_jumpDests . count ( nextPC ) )
BOOST_THROW_EXCEPTION ( BadJumpDestination ( ) ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : JUMPI :
if ( m_stack [ m_stack . size ( ) - 2 ] )
{
nextPC = m_stack . back ( ) ;
if ( ! m_jumpDests . count ( nextPC ) )
BOOST_THROW_EXCEPTION ( BadJumpDestination ( ) ) ;
}
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : PC :
m_stack . push_back ( m_curPC ) ;
break ;
case Instruction : : MSIZE :
m_stack . push_back ( m_temp . size ( ) ) ;
break ;
case Instruction : : GAS :
m_stack . push_back ( m_gas ) ;
break ;
case Instruction : : JUMPDEST :
break ;
/* case Instruction::LOG0:
_ext . log ( { } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 1 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 2 ] ) ) ;
break ;
case Instruction : : LOG1 :
_ext . log ( { m_stack [ m_stack . size ( ) - 1 ] } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 2 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 3 ] ) ) ;
break ;
case Instruction : : LOG2 :
_ext . log ( { m_stack [ m_stack . size ( ) - 1 ] , m_stack [ m_stack . size ( ) - 2 ] } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 3 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 4 ] ) ) ;
break ;
case Instruction : : LOG3 :
_ext . log ( { m_stack [ m_stack . size ( ) - 1 ] , m_stack [ m_stack . size ( ) - 2 ] , m_stack [ m_stack . size ( ) - 3 ] } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 4 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 5 ] ) ) ;
break ;
case Instruction : : LOG4 :
_ext . log ( { m_stack [ m_stack . size ( ) - 1 ] , m_stack [ m_stack . size ( ) - 2 ] , m_stack [ m_stack . size ( ) - 3 ] , m_stack [ m_stack . size ( ) - 4 ] } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 5 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 6 ] ) ) ;
break ; */
case Instruction : : LOG0 :
_ext . log ( { } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 1 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 2 ] ) ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : LOG1 :
_ext . log ( { m_stack [ m_stack . size ( ) - 3 ] } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 1 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 2 ] ) ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : LOG2 :
_ext . log ( { m_stack [ m_stack . size ( ) - 3 ] , m_stack [ m_stack . size ( ) - 4 ] } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 1 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 2 ] ) ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : LOG3 :
_ext . log ( { m_stack [ m_stack . size ( ) - 3 ] , m_stack [ m_stack . size ( ) - 4 ] , m_stack [ m_stack . size ( ) - 5 ] } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 1 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 2 ] ) ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : LOG4 :
_ext . log ( { m_stack [ m_stack . size ( ) - 3 ] , m_stack [ m_stack . size ( ) - 4 ] , m_stack [ m_stack . size ( ) - 5 ] , m_stack [ m_stack . size ( ) - 6 ] } , bytesConstRef ( m_temp . data ( ) + ( unsigned ) m_stack [ m_stack . size ( ) - 1 ] , ( unsigned ) m_stack [ m_stack . size ( ) - 2 ] ) ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
m_stack . pop_back ( ) ;
break ;
case Instruction : : CREATE :
{
u256 endowment = m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned initOff = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned initSize = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
if ( _ext . balance ( _ext . myAddress ) > = endowment & & _ext . depth < 1024 )
{
_ext . subBalance ( endowment ) ;
m_stack . push_back ( ( u160 ) _ext . create ( endowment , m_gas , bytesConstRef ( m_temp . data ( ) + initOff , initSize ) , _onOp ) ) ;
}
else
m_stack . push_back ( 0 ) ;
break ;
}
case Instruction : : CALL :
case Instruction : : CALLCODE :
{
u256 gas = m_stack . back ( ) ;
m_stack . pop_back ( ) ;
Address receiveAddress = asAddress ( m_stack . back ( ) ) ;
m_stack . pop_back ( ) ;
u256 value = m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned inOff = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned inSize = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned outOff = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned outSize = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
if ( _ext . balance ( _ext . myAddress ) > = value & & _ext . depth < 1024 )
{
_ext . subBalance ( value ) ;
m_stack . push_back ( _ext . call ( inst = = Instruction : : CALL ? receiveAddress : _ext . myAddress , value , bytesConstRef ( m_temp . data ( ) + inOff , inSize ) , gas , bytesRef ( m_temp . data ( ) + outOff , outSize ) , _onOp , { } , receiveAddress ) ) ;
}
else
m_stack . push_back ( 0 ) ;
m_gas + = gas ;
break ;
}
case Instruction : : RETURN :
{
unsigned b = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
unsigned s = ( unsigned ) m_stack . back ( ) ;
m_stack . pop_back ( ) ;
return bytesConstRef ( m_temp . data ( ) + b , s ) ;
}
case Instruction : : SUICIDE :
{
Address dest = asAddress ( m_stack . back ( ) ) ;
_ext . suicide ( dest ) ;
// ...follow through to...
}
case Instruction : : STOP :
return bytesConstRef ( ) ;
}
}
if ( _steps = = ( uint64_t ) - 1 )
BOOST_THROW_EXCEPTION ( StepsDone ( ) ) ;
return bytesConstRef ( ) ;
}
}
}