@ -1,18 +1,18 @@
/*
This file is part of cpp - ethereum .
This file is part of cpp - ethereum .
cpp - ethereum is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
cpp - ethereum is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
cpp - ethereum is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
cpp - ethereum is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with cpp - ethereum . If not , see < http : //www.gnu.org/licenses/>.
You should have received a copy of the GNU General Public License
along with cpp - ethereum . If not , see < http : //www.gnu.org/licenses/>.
*/
/** @file MixClient.cpp
* @ author Arkadiy Paronyan arkadiy @ ethdev . com
@ -48,29 +48,29 @@ namespace
struct MixPow //dummy POW
{
typedef int Solution ;
static void assignResult ( int , BlockInfo const & ) { }
static bool verify ( BlockInfo const & ) { return true ; }
typedef int Solution ;
static void assignResult ( int , BlockInfo const & ) { }
static bool verify ( BlockInfo const & ) { return true ; }
} ;
}
bytes MixBlockChain : : createGenesisBlock ( h256 _stateRoot )
{
RLPStream block ( 3 ) ;
block . appendList ( 15 )
< < h256 ( ) < < EmptyListSHA3 < < h160 ( ) < < _stateRoot < < EmptyTrie < < EmptyTrie
< < LogBloom ( ) < < c_mixGenesisDifficulty < < 0 < < c_genesisGasLimit < < 0 < < ( unsigned ) 0
< < std : : string ( ) < < h256 ( ) < < h64 ( u64 ( 42 ) ) ;
block . appendRaw ( RLPEmptyList ) ;
block . appendRaw ( RLPEmptyList ) ;
return block . out ( ) ;
RLPStream block ( 3 ) ;
block . appendList ( 15 )
< < h256 ( ) < < EmptyListSHA3 < < h160 ( ) < < _stateRoot < < EmptyTrie < < EmptyTrie
< < LogBloom ( ) < < c_mixGenesisDifficulty < < 0 < < c_genesisGasLimit < < 0 < < ( unsigned ) 0
< < std : : string ( ) < < h256 ( ) < < h64 ( u64 ( 42 ) ) ;
block . appendRaw ( RLPEmptyList ) ;
block . appendRaw ( RLPEmptyList ) ;
return block . out ( ) ;
}
MixClient : : MixClient ( std : : string const & _dbPath ) :
m_dbPath ( _dbPath )
m_dbPath ( _dbPath )
{
resetState ( std : : unordered_map < Address , Account > ( ) ) ;
resetState ( std : : unordered_map < Address , Account > ( ) ) ;
}
MixClient : : ~ MixClient ( )
@ -79,54 +79,54 @@ MixClient::~MixClient()
LocalisedLogEntries MixClient : : logs ( )
{
return m_watches . at ( 0 ) . changes ;
return m_watches . at ( 0 ) . changes ;
}
void MixClient : : resetState ( std : : unordered_map < Address , Account > const & _accounts , Secret const & _miner )
{
WriteGuard l ( x_state ) ;
Guard fl ( x_filtersWatches ) ;
m_filters . clear ( ) ;
m_watches . clear ( ) ;
//LogFilter filter;
//m_filters.insert(std::make_pair(filter.sha3(), filter));
//m_watches.insert(std::make_pair(0, ClientWatch(filter.sha3(), Reaping::Automatic)));
m_stateDB = OverlayDB ( ) ;
SecureTrieDB < Address , MemoryDB > accountState ( & m_stateDB ) ;
accountState . init ( ) ;
dev : : eth : : commit ( _accounts , static_cast < MemoryDB & > ( m_stateDB ) , accountState ) ;
h256 stateRoot = accountState . root ( ) ;
m_bc . reset ( ) ;
m_bc . reset ( new MixBlockChain ( m_dbPath , stateRoot ) ) ;
m_state = eth : : State ( m_stateDB , BaseState : : PreExisting , KeyPair ( _miner ) . address ( ) ) ;
m_state . sync ( bc ( ) ) ;
m_startState = m_state ;
WriteGuard lx ( x_executions ) ;
m_executions . clear ( ) ;
WriteGuard l ( x_state ) ;
Guard fl ( x_filtersWatches ) ;
m_filters . clear ( ) ;
m_watches . clear ( ) ;
//LogFilter filter;
//m_filters.insert(std::make_pair(filter.sha3(), filter));
//m_watches.insert(std::make_pair(0, ClientWatch(filter.sha3(), Reaping::Automatic)));
m_stateDB = OverlayDB ( ) ;
SecureTrieDB < Address , MemoryDB > accountState ( & m_stateDB ) ;
accountState . init ( ) ;
dev : : eth : : commit ( _accounts , static_cast < MemoryDB & > ( m_stateDB ) , accountState ) ;
h256 stateRoot = accountState . root ( ) ;
m_bc . reset ( ) ;
m_bc . reset ( new MixBlockChain ( m_dbPath , stateRoot ) ) ;
m_state = eth : : State ( m_stateDB , BaseState : : PreExisting , KeyPair ( _miner ) . address ( ) ) ;
m_state . sync ( bc ( ) ) ;
m_startState = m_state ;
WriteGuard lx ( x_executions ) ;
m_executions . clear ( ) ;
}
Transaction MixClient : : replaceGas ( Transaction const & _t , u256 const & _gas , Secret const & _secret )
{
Transaction ret ;
if ( _secret )
{
if ( _t . isCreation ( ) )
ret = Transaction ( _t . value ( ) , _t . gasPrice ( ) , _gas , _t . data ( ) , _t . nonce ( ) , _secret ) ;
else
ret = Transaction ( _t . value ( ) , _t . gasPrice ( ) , _gas , _t . receiveAddress ( ) , _t . data ( ) , _t . nonce ( ) , _secret ) ;
}
else
{
if ( _t . isCreation ( ) )
ret = Transaction ( _t . value ( ) , _t . gasPrice ( ) , _gas , _t . data ( ) , _t . nonce ( ) ) ;
else
ret = Transaction ( _t . value ( ) , _t . gasPrice ( ) , _gas , _t . receiveAddress ( ) , _t . data ( ) , _t . nonce ( ) ) ;
ret . forceSender ( _t . safeSender ( ) ) ;
}
return ret ;
Transaction ret ;
if ( _secret )
{
if ( _t . isCreation ( ) )
ret = Transaction ( _t . value ( ) , _t . gasPrice ( ) , _gas , _t . data ( ) , _t . nonce ( ) , _secret ) ;
else
ret = Transaction ( _t . value ( ) , _t . gasPrice ( ) , _gas , _t . receiveAddress ( ) , _t . data ( ) , _t . nonce ( ) , _secret ) ;
}
else
{
if ( _t . isCreation ( ) )
ret = Transaction ( _t . value ( ) , _t . gasPrice ( ) , _gas , _t . data ( ) , _t . nonce ( ) ) ;
else
ret = Transaction ( _t . value ( ) , _t . gasPrice ( ) , _gas , _t . receiveAddress ( ) , _t . data ( ) , _t . nonce ( ) ) ;
ret . forceSender ( _t . safeSender ( ) ) ;
}
return ret ;
}
void MixClient : : executeTransaction ( Transaction const & _t , State & _state , bool _call , bool _gasAuto , Secret const & _secret )
@ -193,19 +193,19 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
levels . resize ( ext . depth ) ;
machineStates . push_back ( MachineState {
steps ,
vm . curPC ( ) ,
inst ,
newMemSize ,
static_cast < u256 > ( gas ) ,
vm . stack ( ) ,
vm . memory ( ) ,
gasCost ,
ext . state ( ) . storage ( ext . myAddress ) ,
std : : move ( levels ) ,
codeIndex ,
dataIndex
} ) ;
steps ,
vm . curPC ( ) ,
inst ,
newMemSize ,
static_cast < u256 > ( gas ) ,
vm . stack ( ) ,
vm . memory ( ) ,
gasCost ,
ext . state ( ) . storage ( ext . myAddress ) ,
std : : move ( levels ) ,
codeIndex ,
dataIndex
} ) ;
} ;
execution . go ( onOp ) ;
@ -213,27 +213,29 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
switch ( er . excepted )
{
case TransactionException : : None :
break ;
case TransactionException : : NotEnoughCash :
BOOST_THROW_EXCEPTION ( Exception ( ) < < errinfo_comment ( " Insufficient balance for contract deployment " ) ) ;
case TransactionException : : OutOfGasBase :
case TransactionException : : OutOfGas :
BOOST_THROW_EXCEPTION ( OutOfGas ( ) < < errinfo_comment ( " Not enough gas " ) ) ;
case TransactionException : : BlockGasLimitReached :
BOOST_THROW_EXCEPTION ( OutOfGas ( ) < < errinfo_comment ( " Block gas limit reached " ) ) ;
case TransactionException : : OutOfStack :
BOOST_THROW_EXCEPTION ( Exception ( ) < < errinfo_comment ( " Out of stack " ) ) ;
case TransactionException : : StackUnderflow :
BOOST_THROW_EXCEPTION ( Exception ( ) < < errinfo_comment ( " Stack underflow " ) ) ;
//these should not happen in mix
case TransactionException : : Unknown :
case TransactionException : : BadInstruction :
case TransactionException : : BadJumpDestination :
case TransactionException : : InvalidSignature :
case TransactionException : : InvalidNonce :
BOOST_THROW_EXCEPTION ( Exception ( ) < < errinfo_comment ( " Internal execution error " ) ) ;
} ;
case TransactionException : : None :
break ;
case TransactionException : : NotEnoughCash :
BOOST_THROW_EXCEPTION ( Exception ( ) < < errinfo_comment ( " Insufficient balance for contract deployment " ) ) ;
case TransactionException : : OutOfGasIntrinsic :
case TransactionException : : OutOfGasBase :
case TransactionException : : OutOfGas :
BOOST_THROW_EXCEPTION ( OutOfGas ( ) < < errinfo_comment ( " Not enough gas " ) ) ;
case TransactionException : : BlockGasLimitReached :
BOOST_THROW_EXCEPTION ( OutOfGas ( ) < < errinfo_comment ( " Block gas limit reached " ) ) ;
case TransactionException : : OutOfStack :
BOOST_THROW_EXCEPTION ( Exception ( ) < < errinfo_comment ( " Out of stack " ) ) ;
case TransactionException : : StackUnderflow :
BOOST_THROW_EXCEPTION ( Exception ( ) < < errinfo_comment ( " Stack underflow " ) ) ;
//these should not happen in mix
case TransactionException : : Unknown :
case TransactionException : : BadInstruction :
case TransactionException : : BadJumpDestination :
case TransactionException : : InvalidSignature :
case TransactionException : : InvalidNonce :
case TransactionException : : BadRLP :
BOOST_THROW_EXCEPTION ( Exception ( ) < < errinfo_comment ( " Internal execution error " ) ) ;
}
ExecutionResult d ;
d . inputParameters = t . data ( ) ;
@ -299,149 +301,149 @@ void MixClient::executeTransaction(Transaction const& _t, State& _state, bool _c
void MixClient : : mine ( )
{
WriteGuard l ( x_state ) ;
m_state . commitToMine ( bc ( ) ) ;
m_state . completeMine < MixPow > ( 0 ) ;
bc ( ) . import ( m_state . blockData ( ) , m_state . db ( ) , ImportRequirements : : Default & ~ ImportRequirements : : ValidNonce ) ;
m_state . sync ( bc ( ) ) ;
m_startState = m_state ;
h256Set changed { dev : : eth : : PendingChangedFilter , dev : : eth : : ChainChangedFilter } ;
//noteChanged(changed);
WriteGuard l ( x_state ) ;
m_state . commitToMine ( bc ( ) ) ;
m_state . completeMine < MixPow > ( 0 ) ;
bc ( ) . import ( m_state . blockData ( ) , m_state . db ( ) , ImportRequirements : : Default & ~ ImportRequirements : : ValidNonce ) ;
m_state . sync ( bc ( ) ) ;
m_startState = m_state ;
h256Set changed { dev : : eth : : PendingChangedFilter , dev : : eth : : ChainChangedFilter } ;
//noteChanged(changed);
}
ExecutionResult MixClient : : lastExecution ( ) const
{
ReadGuard l ( x_executions ) ;
return m_executions . empty ( ) ? ExecutionResult ( ) : m_executions . back ( ) ;
ReadGuard l ( x_executions ) ;
return m_executions . empty ( ) ? ExecutionResult ( ) : m_executions . back ( ) ;
}
ExecutionResult MixClient : : execution ( unsigned _index ) const
{
ReadGuard l ( x_executions ) ;
return m_executions . at ( _index ) ;
ReadGuard l ( x_executions ) ;
return m_executions . at ( _index ) ;
}
State MixClient : : asOf ( h256 const & _block ) const
{
ReadGuard l ( x_state ) ;
return State ( m_stateDB , bc ( ) , _block ) ;
ReadGuard l ( x_state ) ;
return State ( m_stateDB , bc ( ) , _block ) ;
}
void MixClient : : submitTransaction ( Secret _secret , u256 _value , Address _dest , bytes const & _data , u256 _gas , u256 _gasPrice , bool _gasAuto )
{
WriteGuard l ( x_state ) ;
u256 n = m_state . transactionsFrom ( toAddress ( _secret ) ) ;
Transaction t ( _value , _gasPrice , _gas , _dest , _data , n , _secret ) ;
executeTransaction ( t , m_state , false , _gasAuto , _secret ) ;
WriteGuard l ( x_state ) ;
u256 n = m_state . transactionsFrom ( toAddress ( _secret ) ) ;
Transaction t ( _value , _gasPrice , _gas , _dest , _data , n , _secret ) ;
executeTransaction ( t , m_state , false , _gasAuto , _secret ) ;
}
Address MixClient : : submitTransaction ( Secret _secret , u256 _endowment , bytes const & _init , u256 _gas , u256 _gasPrice , bool _gasAuto )
{
WriteGuard l ( x_state ) ;
u256 n = m_state . transactionsFrom ( toAddress ( _secret ) ) ;
eth : : Transaction t ( _endowment , _gasPrice , _gas , _init , n , _secret ) ;
executeTransaction ( t , m_state , false , _gasAuto , _secret ) ;
Address address = right160 ( sha3 ( rlpList ( t . sender ( ) , t . nonce ( ) ) ) ) ;
return address ;
WriteGuard l ( x_state ) ;
u256 n = m_state . transactionsFrom ( toAddress ( _secret ) ) ;
eth : : Transaction t ( _endowment , _gasPrice , _gas , _init , n , _secret ) ;
executeTransaction ( t , m_state , false , _gasAuto , _secret ) ;
Address address = right160 ( sha3 ( rlpList ( t . sender ( ) , t . nonce ( ) ) ) ) ;
return address ;
}
dev : : eth : : ExecutionResult MixClient : : call ( Address const & _from , u256 _value , Address _dest , bytes const & _data , u256 _gas , u256 _gasPrice , BlockNumber _blockNumber , bool _gasAuto , FudgeFactor _ff )
{
( void ) _blockNumber ;
State temp = asOf ( eth : : PendingBlock ) ;
u256 n = temp . transactionsFrom ( _from ) ;
Transaction t ( _value , _gasPrice , _gas , _dest , _data , n ) ;
t . forceSender ( _from ) ;
if ( _ff = = FudgeFactor : : Lenient )
temp . addBalance ( _from , ( u256 ) ( t . gasRequired ( ) * t . gasPrice ( ) + t . value ( ) ) ) ;
WriteGuard lw ( x_state ) ; //TODO: lock is required only for last execution state
executeTransaction ( t , temp , true , _gasAuto ) ;
return lastExecution ( ) . result ;
( void ) _blockNumber ;
State temp = asOf ( eth : : PendingBlock ) ;
u256 n = temp . transactionsFrom ( _from ) ;
Transaction t ( _value , _gasPrice , _gas , _dest , _data , n ) ;
t . forceSender ( _from ) ;
if ( _ff = = FudgeFactor : : Lenient )
temp . addBalance ( _from , ( u256 ) ( t . gasRequired ( ) * t . gasPrice ( ) + t . value ( ) ) ) ;
WriteGuard lw ( x_state ) ; //TODO: lock is required only for last execution state
executeTransaction ( t , temp , true , _gasAuto ) ;
return lastExecution ( ) . result ;
}
void MixClient : : submitTransaction ( Secret _secret , u256 _value , Address _dest , bytes const & _data , u256 _gas , u256 _gasPrice )
{
submitTransaction ( _secret , _value , _dest , _data , _gas , _gasPrice , false ) ;
submitTransaction ( _secret , _value , _dest , _data , _gas , _gasPrice , false ) ;
}
Address MixClient : : submitTransaction ( Secret _secret , u256 _endowment , bytes const & _init , u256 _gas , u256 _gasPrice )
{
return submitTransaction ( _secret , _endowment , _init , _gas , _gasPrice , false ) ;
return submitTransaction ( _secret , _endowment , _init , _gas , _gasPrice , false ) ;
}
dev : : eth : : ExecutionResult MixClient : : call ( Address const & _from , u256 _value , Address _dest , bytes const & _data , u256 _gas , u256 _gasPrice , BlockNumber _blockNumber , eth : : FudgeFactor _ff )
{
return call ( _from , _value , _dest , _data , _gas , _gasPrice , _blockNumber , false , _ff ) ;
return call ( _from , _value , _dest , _data , _gas , _gasPrice , _blockNumber , false , _ff ) ;
}
dev : : eth : : ExecutionResult MixClient : : create ( Address const & _from , u256 _value , bytes const & _data , u256 _gas , u256 _gasPrice , BlockNumber _blockNumber , eth : : FudgeFactor _ff )
{
( void ) _blockNumber ;
u256 n ;
State temp ;
{
ReadGuard lr ( x_state ) ;
temp = asOf ( eth : : PendingBlock ) ;
n = temp . transactionsFrom ( _from ) ;
}
Transaction t ( _value , _gasPrice , _gas , _data , n ) ;
t . forceSender ( _from ) ;
if ( _ff = = FudgeFactor : : Lenient )
temp . addBalance ( _from , ( u256 ) ( t . gasRequired ( ) * t . gasPrice ( ) + t . value ( ) ) ) ;
WriteGuard lw ( x_state ) ; //TODO: lock is required only for last execution state
executeTransaction ( t , temp , true , false ) ;
return lastExecution ( ) . result ;
( void ) _blockNumber ;
u256 n ;
State temp ;
{
ReadGuard lr ( x_state ) ;
temp = asOf ( eth : : PendingBlock ) ;
n = temp . transactionsFrom ( _from ) ;
}
Transaction t ( _value , _gasPrice , _gas , _data , n ) ;
t . forceSender ( _from ) ;
if ( _ff = = FudgeFactor : : Lenient )
temp . addBalance ( _from , ( u256 ) ( t . gasRequired ( ) * t . gasPrice ( ) + t . value ( ) ) ) ;
WriteGuard lw ( x_state ) ; //TODO: lock is required only for last execution state
executeTransaction ( t , temp , true , false ) ;
return lastExecution ( ) . result ;
}
/*void MixClient::noteChanged(h256Set const& _filters)
{
for ( auto & i : m_watches )
if ( _filters . count ( i . second . id ) )
{
if ( m_filters . count ( i . second . id ) )
i . second . changes + = m_filters . at ( i . second . id ) . changes ;
else
i . second . changes . push_back ( LocalisedLogEntry ( SpecialLogEntry , 0 ) ) ;
}
for ( auto & i : m_filters )
i . second . changes . clear ( ) ;
for ( auto & i : m_watches )
if ( _filters . count ( i . second . id ) )
{
if ( m_filters . count ( i . second . id ) )
i . second . changes + = m_filters . at ( i . second . id ) . changes ;
else
i . second . changes . push_back ( LocalisedLogEntry ( SpecialLogEntry , 0 ) ) ;
}
for ( auto & i : m_filters )
i . second . changes . clear ( ) ;
} */
eth : : BlockInfo MixClient : : blockInfo ( ) const
{
ReadGuard l ( x_state ) ;
return BlockInfo ( bc ( ) . block ( ) ) ;
ReadGuard l ( x_state ) ;
return BlockInfo ( bc ( ) . block ( ) ) ;
}
void MixClient : : setAddress ( Address _us )
{
WriteGuard l ( x_state ) ;
m_state . setAddress ( _us ) ;
WriteGuard l ( x_state ) ;
m_state . setAddress ( _us ) ;
}
void MixClient : : startMining ( )
{
//no-op
//no-op
}
void MixClient : : stopMining ( )
{
//no-op
//no-op
}
bool MixClient : : isMining ( ) const
{
return false ;
return false ;
}
uint64_t MixClient : : hashrate ( ) const
{
return 0 ;
return 0 ;
}
eth : : MiningProgress MixClient : : miningProgress ( ) const
{
return eth : : MiningProgress ( ) ;
return eth : : MiningProgress ( ) ;
}
}