/*
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 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/>.
*/
/** @file main.cpp
* @ author Gav Wood < i @ gavwood . com >
* @ date 2014
* Ethereum client .
*/
# if ETH_ETHASHCL
# define __CL_ENABLE_EXCEPTIONS
# define CL_USE_DEPRECATED_OPENCL_2_0_APIS
# if defined(__clang__)
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunused-parameter"
# include <libethash-cl/cl.hpp>
# pragma clang diagnostic pop
# else
# include <libethash-cl/cl.hpp>
# endif
# endif
# include <functional>
# include <boost/filesystem.hpp>
# include <boost/algorithm/string.hpp>
#if 0
# include <libdevcore/TrieDB.h>
# include <libdevcore/TrieHash.h>
# include <libdevcore/RangeMask.h>
# include <libdevcore/Log.h>
# include <libdevcore/Common.h>
# include <libdevcore/CommonData.h>
# include <libdevcore/RLP.h>
# include <libdevcore/TransientDirectory.h>
# include <libdevcore/CommonIO.h>
# include <libdevcrypto/SecretStore.h>
# include <libp2p/All.h>
# include <libethcore/Farm.h>
# include <libdevcore/FileSystem.h>
# include <libethereum/All.h>
# include <libethcore/KeyManager.h>
# include <libethereum/AccountDiff.h>
# include <libethereum/DownloadMan.h>
# include <libethereum/Client.h>
# include <liblll/All.h>
# include <libwhisper/WhisperPeer.h>
# include <libwhisper/WhisperHost.h>
# include <test/JsonSpiritHeaders.h>
using namespace std ;
using namespace dev ;
using namespace dev : : eth ;
using namespace dev : : p2p ;
using namespace dev : : shh ;
namespace js = json_spirit ;
namespace fs = boost : : filesystem ;
# else
# include <libethcore/Sealer.h>
# include <libethcore/BasicAuthority.h>
# include <libethcore/BlockInfo.h>
# include <libethcore/Ethash.h>
# include <libethcore/Params.h>
# include <libethereum/All.h>
# include <libethereum/AccountDiff.h>
# include <libethereum/DownloadMan.h>
# include <libethereum/Client.h>
using namespace std ;
using namespace dev ;
using namespace eth ;
# endif
#if 0
int main ( )
{
BlockInfo bi ;
bi . difficulty = c_genesisDifficulty ;
bi . gasLimit = c_genesisGasLimit ;
bi . number ( ) = 1 ;
bi . parentHash ( ) = sha3 ( " parentHash " ) ;
bytes sealedData ;
{
KeyPair kp ( sha3 ( " test " ) ) ;
SealEngineFace * se = BasicAuthority : : createSealEngine ( ) ;
se - > setOption ( " authority " , rlp ( kp . secret ( ) ) ) ;
se - > setOption ( " authorities " , rlpList ( kp . address ( ) ) ) ;
cdebug < < se - > sealers ( ) ;
bool done = false ;
se - > onSealGenerated ( [ & ] ( SealFace const * seal ) {
sealedData = seal - > sealedHeader ( bi ) ;
done = true ;
} ) ;
se - > generateSeal ( bi ) ;
while ( ! done )
this_thread : : sleep_for ( chrono : : milliseconds ( 50 ) ) ;
BasicAuthority : : BlockHeader sealed = BasicAuthority : : BlockHeader : : fromHeader ( sealedData , CheckEverything ) ;
cdebug < < sealed . sig ( ) ;
}
{
SealEngineFace * se = Ethash : : createSealEngine ( ) ;
cdebug < < se - > sealers ( ) ;
bool done = false ;
se - > setSealer ( " cpu " ) ;
se - > onSealGenerated ( [ & ] ( SealFace const * seal ) {
sealedData = seal - > sealedHeader ( bi ) ;
done = true ;
} ) ;
se - > generateSeal ( bi ) ;
while ( ! done )
this_thread : : sleep_for ( chrono : : milliseconds ( 50 ) ) ;
Ethash : : BlockHeader sealed = Ethash : : BlockHeader : : fromHeader ( sealedData , CheckEverything ) ;
cdebug < < sealed . nonce ( ) ;
}
return 0 ;
}
# elif 0
int main ( )
{
cdebug < < pbkdf2 ( " password " , asBytes ( " salt " ) , 1 , 32 ) ;
cdebug < < pbkdf2 ( " password " , asBytes ( " salt " ) , 1 , 16 ) ;
cdebug < < pbkdf2 ( " password " , asBytes ( " salt " ) , 2 , 16 ) ;
cdebug < < pbkdf2 ( " testpassword " , fromHex ( " de5742f1f1045c402296422cee5a8a9ecf0ac5bf594deca1170d22aef33a79cf " ) , 262144 , 16 ) ;
return 0 ;
}
# elif 0
int main ( )
{
cdebug < < " EXP " ;
vector < bytes > data ;
for ( unsigned i = 0 ; i < 10000 ; + + i )
data . push_back ( rlp ( i ) ) ;
h256 ret ;
DEV_TIMED ( " triedb " )
{
MemoryDB mdb ;
GenericTrieDB < MemoryDB > t ( & mdb ) ;
t . init ( ) ;
unsigned i = 0 ;
for ( auto const & d : data )
t . insert ( rlp ( i + + ) , d ) ;
ret = t . root ( ) ;
}
cdebug < < ret ;
DEV_TIMED ( " hash256 " )
ret = orderedTrieRoot ( data ) ;
cdebug < < ret ;
}
# elif 0
int main ( )
{
KeyManager keyman ;
if ( keyman . exists ( ) )
keyman . load ( " foo " ) ;
else
keyman . create ( " foo " ) ;
Address a ( " 9cab1cc4e8fe528267c6c3af664a1adbce810b5f " ) ;
// keyman.importExisting(fromUUID("441193ae-a767-f1c3-48ba-dd6610db5ed0"), "{\"name\":\"Gavin Wood - Main identity\"}", "bar", "{\"hint\":\"Not foo.\"}");
// Address a2 = keyman.address(keyman.import(Secret::random(), "Key with no additional security."));
// cdebug << toString(a2);
Address a2 ( " 19c486071651b2650449ba3c6a807f316a73e8fe " ) ;
cdebug < < keyman . accountDetails ( ) ;
cdebug < < " Secret key for " < < a < < " is " < < keyman . secret ( a , [ ] ( ) { return " bar " ; } ) ;
cdebug < < " Secret key for " < < a2 < < " is " < < keyman . secret ( a2 ) ;
}
# elif 0
int main ( )
{
DownloadMan man ;
DownloadSub s0 ( man ) ;
DownloadSub s1 ( man ) ;
DownloadSub s2 ( man ) ;
man . resetToChain ( h256s ( { u256 ( 0 ) , u256 ( 1 ) , u256 ( 2 ) , u256 ( 3 ) , u256 ( 4 ) , u256 ( 5 ) , u256 ( 6 ) , u256 ( 7 ) , u256 ( 8 ) } ) , 0 ) ;
assert ( ( s0 . nextFetch ( 2 ) = = h256Set { ( u256 ) 7 , ( u256 ) 8 } ) ) ;
assert ( ( s1 . nextFetch ( 2 ) = = h256Set { ( u256 ) 5 , ( u256 ) 6 } ) ) ;
assert ( ( s2 . nextFetch ( 2 ) = = h256Set { ( u256 ) 3 , ( u256 ) 4 } ) ) ;
s0 . noteBlock ( u256 ( 8 ) ) ;
s0 . doneFetch ( ) ;
assert ( ( s0 . nextFetch ( 2 ) = = h256Set { ( u256 ) 2 , ( u256 ) 7 } ) ) ;
s1 . noteBlock ( u256 ( 6 ) ) ;
s1 . noteBlock ( u256 ( 5 ) ) ;
s1 . doneFetch ( ) ;
assert ( ( s1 . nextFetch ( 2 ) = = h256Set { ( u256 ) 0 , ( u256 ) 1 } ) ) ;
s0 . doneFetch ( ) ; // TODO: check exact semantics of doneFetch & nextFetch. Not sure if they're right -> doneFetch calls resetFetch which kills all the info of past fetches.
cdebug < < s0 . nextFetch ( 2 ) ;
assert ( ( s0 . nextFetch ( 2 ) = = h256Set { ( u256 ) 3 , ( u256 ) 4 } ) ) ;
/* RangeMask<unsigned> m(0, 100);
cnote < < m ;
m + = UnsignedRange ( 3 , 10 ) ;
cnote < < m ;
m + = UnsignedRange ( 11 , 16 ) ;
cnote < < m ;
m + = UnsignedRange ( 10 , 11 ) ;
cnote < < m ;
cnote < < ~ m ;
cnote < < ( ~ m ) . lowest ( 10 ) ;
for ( auto i : ( ~ m ) . lowest ( 10 ) )
cnote < < i ; */
return 0 ;
}
# elif 0
int main ( )
{
KeyPair u = KeyPair : : create ( ) ;
KeyPair cb = KeyPair : : create ( ) ;
OverlayDB db ;
State s ( cb . address ( ) , db , BaseState : : Empty ) ;
cnote < < s . rootHash ( ) ;
s . addBalance ( u . address ( ) , 1 * ether ) ;
Address c = s . newContract ( 1000 * ether , compileLLL ( " (suicide (caller)) " ) ) ;
s . commit ( ) ;
State before = s ;
cnote < < " State before transaction: " < < before ;
Transaction t ( 0 , 10000 , 10000 , c , bytes ( ) , 0 , u . secret ( ) ) ;
cnote < < " Transaction: " < < t ;
cnote < < s . balance ( c ) ;
s . execute ( LastHashes ( ) , t . rlp ( ) ) ;
cnote < < " State after transaction: " < < s ;
cnote < < before . diff ( s ) ;
}
# elif 0
int main ( )
{
GenericFarm < EthashProofOfWork > f ;
BlockInfo genesis = CanonBlockChain : : genesis ( ) ;
genesis . difficulty = 1 < < 18 ;
cdebug < < genesis . boundary ( ) ;
auto mine = [ ] ( GenericFarm < EthashProofOfWork > & f , BlockInfo const & g , unsigned timeout ) {
BlockInfo bi = g ;
bool completed = false ;
f . onSolutionFound ( [ & ] ( EthashProofOfWork : : Solution sol )
{
bi . proof = sol ;
return completed = true ;
} ) ;
f . setWork ( bi ) ;
for ( unsigned i = 0 ; ! completed & & i < timeout * 10 ; + + i , cout < < f . miningProgress ( ) < < " \r " < < flush )
this_thread : : sleep_for ( chrono : : milliseconds ( 100 ) ) ;
cout < < endl < < flush ;
cdebug < < bi . mixHash < < bi . nonce < < ( Ethash : : verify ( bi ) ? " GOOD " : " bad " ) ;
} ;
Ethash : : prep ( genesis ) ;
genesis . difficulty = u256 ( 1 ) < < 40 ;
genesis . noteDirty ( ) ;
f . startCPU ( ) ;
mine ( f , genesis , 10 ) ;
f . startGPU ( ) ;
cdebug < < " Good: " ;
genesis . difficulty = 1 < < 18 ;
genesis . noteDirty ( ) ;
mine ( f , genesis , 30 ) ;
cdebug < < " Bad: " ;
genesis . difficulty = ( u256 ( 1 ) < < 40 ) ;
genesis . noteDirty ( ) ;
mine ( f , genesis , 30 ) ;
f . stop ( ) ;
return 0 ;
}
# elif 1
int main ( )
{
bytes tx = fromHex ( " f84c01028332dcd58004801ba024843272ee176277535489859cbd275686023fe64aabd158b6fcdf2ae6a1ab6ba02f252a5016a48e5ec8d17aefaf4324d29b9e123fa623dc5a60539b3ad3610c95 " ) ;
Transaction t ( tx , CheckTransaction : : None ) ;
Public p = recover ( t . signature ( ) , t . sha3 ( WithoutSignature ) ) ;
cnote < < t . signature ( ) . r ;
cnote < < t . signature ( ) . s ;
cnote < < t . signature ( ) . v ;
cnote < < p ;
cnote < < toAddress ( p ) ;
cnote < < t . sender ( ) ;
}
# elif 0
void mine ( State & s , BlockChain const & _bc , SealEngineFace * _se )
{
s . commitToSeal ( _bc ) ;
Notified < bytes > sealed ;
_se - > onSealGenerated ( [ & ] ( bytes const & sealedHeader ) { sealed = sealedHeader ; } ) ;
_se - > generateSeal ( s . info ( ) ) ;
sealed . waitNot ( { } ) ;
s . sealBlock ( sealed ) ;
}
int main ( )
{
cnote < < " Testing State... " ;
KeyPair me = sha3 ( " Gav Wood " ) ;
KeyPair myMiner = sha3 ( " Gav's Miner " ) ;
// KeyPair you = sha3("123");
Defaults : : setDBPath ( boost : : filesystem : : temp_directory_path ( ) . string ( ) + " / " + toString ( chrono : : system_clock : : now ( ) . time_since_epoch ( ) . count ( ) ) ) ;
using Sealer = Ethash ;
CanonBlockChain < Sealer > bc ;
auto gbb = bc . headerData ( bc . genesisHash ( ) ) ;
assert ( Sealer : : BlockHeader ( bc . headerData ( bc . genesisHash ( ) ) , IgnoreSeal , bc . genesisHash ( ) , HeaderData ) ) ;
SealEngineFace * se = Sealer : : createSealEngine ( ) ;
KeyPair kp ( sha3 ( " test " ) ) ;
se - > setOption ( " authority " , rlp ( kp . secret ( ) ) ) ;
se - > setOption ( " authorities " , rlpList ( kp . address ( ) ) ) ;
OverlayDB stateDB = State : : openDB ( bc . genesisHash ( ) ) ;
cnote < < bc ;
Block s = bc . genesisBlock ( stateDB ) ;
s . setBeneficiary ( myMiner . address ( ) ) ;
cnote < < s ;
// Sync up - this won't do much until we use the last state.
s . sync ( bc ) ;
cnote < < s ;
// Mine to get some ether!
mine ( s , bc , se ) ;
bytes minedBlock = s . blockData ( ) ;
cnote < < " Mined block is " < < BlockInfo ( minedBlock ) . stateRoot ( ) ;
bc . import ( minedBlock , stateDB ) ;
cnote < < bc ;
s . sync ( bc ) ;
cnote < < s ;
cnote < < " Miner now has " < < s . balance ( myMiner . address ( ) ) ;
s . resetCurrent ( ) ;
cnote < < " Miner now has " < < s . balance ( myMiner . address ( ) ) ;
// Inject a transaction to transfer funds from miner to me.
Transaction t ( 1000 , 10000 , 30000 , me . address ( ) , bytes ( ) , s . transactionsFrom ( myMiner . address ( ) ) , myMiner . secret ( ) ) ;
assert ( t . sender ( ) = = myMiner . address ( ) ) ;
s . execute ( bc . lastHashes ( ) , t ) ;
cnote < < s ;
// Mine to get some ether and set in stone.
s . commitToSeal ( bc ) ;
s . commitToSeal ( bc ) ;
mine ( s , bc , se ) ;
bc . attemptImport ( s . blockData ( ) , stateDB ) ;
cnote < < bc ;
s . sync ( bc ) ;
cnote < < s ;
return 0 ;
}
# else
int main ( )
{
string tempDir = boost : : filesystem : : temp_directory_path ( ) . string ( ) + " / " + toString ( chrono : : system_clock : : now ( ) . time_since_epoch ( ) . count ( ) ) ;
KeyPair myMiner = sha3 ( " Gav's Miner " ) ;
p2p : : Host net ( " Test " ) ;
cdebug < < " Path: " < < tempDir ;
Client c ( & net , tempDir ) ;
c . setBeneficiary ( myMiner . address ( ) ) ;
this_thread : : sleep_for ( chrono : : milliseconds ( 1000 ) ) ;
c . startMining ( ) ;
this_thread : : sleep_for ( chrono : : milliseconds ( 6000 ) ) ;
c . stopMining ( ) ;
return 0 ;
}
# endif