Browse Source

Fake dagger, and moves to test the state transitions.

cl-refactor
Gav Wood 11 years ago
parent
commit
406b283a05
  1. 4
      libethereum/BlockInfo.cpp
  2. 2
      libethereum/BlockInfo.h
  3. 4
      libethereum/Common.cpp
  4. 15
      libethereum/Dagger.cpp
  5. 17
      libethereum/Dagger.h
  6. 2
      libethereum/RLP.h
  7. 7
      libethereum/State.cpp
  8. 24
      libethereum/State.h
  9. 32
      test/state.cpp

4
libethereum/BlockInfo.cpp

@ -42,7 +42,7 @@ bytes BlockInfo::createGenesisBlock()
{ {
RLPStream block(3); RLPStream block(3);
auto sha3EmptyList = sha3(RLPEmptyList); auto sha3EmptyList = sha3(RLPEmptyList);
block.appendList(9) << (uint)0 << sha3EmptyList << (uint)0 << sha3(RLPNull) << sha3EmptyList << ((uint)1 << 36) << (uint)0 << (uint)0 << (uint)0; block.appendList(9) << h256() << sha3EmptyList << h160() << sha3(RLPNull) << sha3EmptyList << ((uint)1 << 36) << (uint)0 << string() << (uint)0;
block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList); block.appendRaw(RLPEmptyList);
return block.out(); return block.out();
@ -82,7 +82,7 @@ void BlockInfo::populate(bytesConstRef _block)
sha3Transactions = header[4].toHash<h256>(); sha3Transactions = header[4].toHash<h256>();
difficulty = header[5].toInt<u256>(); difficulty = header[5].toInt<u256>();
timestamp = header[6].toInt<u256>(); timestamp = header[6].toInt<u256>();
extraData = header[7].toHash<h256>(); extraData = header[7].toBytes();
nonce = header[8].toInt<u256>(); nonce = header[8].toInt<u256>();
} }
catch (RLP::BadCast) catch (RLP::BadCast)

2
libethereum/BlockInfo.h

@ -38,7 +38,7 @@ public:
h256 sha3Transactions; h256 sha3Transactions;
u256 difficulty; u256 difficulty;
u256 timestamp; u256 timestamp;
h256 extraData; bytes extraData;
u256 nonce; u256 nonce;
BlockInfo(); BlockInfo();

4
libethereum/Common.cpp

@ -144,8 +144,10 @@ h256 eth::sha3(bytesConstRef _input)
return ret; return ret;
} }
Address eth::toPublic(h256 _private) Address eth::toPublic(PrivateKey _private)
{ {
secp256k1_start();
bytes pubkey(65); bytes pubkey(65);
int pubkeylen = 65; int pubkeylen = 65;
int ret = secp256k1_ecdsa_seckey_verify(_private.data()); int ret = secp256k1_ecdsa_seckey_verify(_private.data());

15
libethereum/Dagger.cpp

@ -20,6 +20,20 @@ using namespace std::chrono;
namespace eth namespace eth
{ {
#if FAKE_DAGGER
bool Dagger::mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, uint _msTimeout)
{
o_solution = 0;
// evaluate until we run out of time
for (auto startTime = steady_clock::now(); (steady_clock::now() - startTime) < milliseconds(_msTimeout); o_solution += 1)
if (verify(_root, o_solution, _difficulty))
return true;
return false;
}
#else
Dagger::Dagger() Dagger::Dagger()
{ {
} }
@ -130,4 +144,5 @@ h256 Dagger::eval(h256 const& _root, u256 const& _nonce)
return get(bsha); return get(bsha);
} }
#endif
} }

17
libethereum/Dagger.h

@ -2,9 +2,24 @@
#include "Common.h" #include "Common.h"
#define FAKE_DAGGER 1
namespace eth namespace eth
{ {
#if FAKE_DAGGER
class Dagger
{
public:
static h256 eval(h256 const& _root, u256 const& _nonce) { h256 b = (h256)((u256)_root ^ _nonce); return sha3(bytesConstRef((byte const*)&b, 32)); }
static bool verify(h256 const& _root, u256 const& _nonce, u256 const& _difficulty) { return (u256)eval(_root, _nonce) > _difficulty; }
bool mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, uint _msTimeout = 100);
};
#else
/// Functions are not re-entrant. If you want to multi-thread, then use different classes for each thread. /// Functions are not re-entrant. If you want to multi-thread, then use different classes for each thread.
class Dagger class Dagger
{ {
@ -26,6 +41,8 @@ private:
u256 m_nonce; u256 m_nonce;
}; };
#endif
} }

2
libethereum/RLP.h

@ -164,7 +164,7 @@ public:
template <unsigned _N> explicit operator FixedHash<_N>() const { return toHash<_N>(); } template <unsigned _N> explicit operator FixedHash<_N>() const { return toHash<_N>(); }
/// Converts to bytearray. @returns the empty byte array if not a string. /// Converts to bytearray. @returns the empty byte array if not a string.
bytes toBytes() const { if (!isString()) return bytes(); bytes(payload().data(), payload().data() + items()); } bytes toBytes() const { if (!isString()) return bytes(); return bytes(payload().data(), payload().data() + items()); }
/// Converts to bytearray. @returns the empty byte array if not a string. /// Converts to bytearray. @returns the empty byte array if not a string.
bytesConstRef toBytesConstRef() const { if (!isString()) return bytesConstRef(); payload().cropped(0, items()); } bytesConstRef toBytesConstRef() const { if (!isString()) return bytesConstRef(); payload().cropped(0, items()); }
/// Converts to string. @returns the empty string if not a string. /// Converts to string. @returns the empty string if not a string.

7
libethereum/State.cpp

@ -20,6 +20,7 @@
*/ */
#include <secp256k1.h> #include <secp256k1.h>
#include <boost/filesystem.hpp>
#if WIN32 #if WIN32
#pragma warning(push) #pragma warning(push)
#pragma warning(disable:4244) #pragma warning(disable:4244)
@ -58,9 +59,11 @@ State::State(Address _coinbaseAddress): m_state(&m_db), m_ourAddress(_coinbaseAd
m_previousBlock = BlockInfo::genesis(); m_previousBlock = BlockInfo::genesis();
m_currentBlock.coinbaseAddress = m_ourAddress; m_currentBlock.coinbaseAddress = m_ourAddress;
boost::filesystem::create_directory(string(getenv("HOME")) + "/.ethereum/");
ldb::Options o; ldb::Options o;
ldb::DB* db = nullptr; ldb::DB* db = nullptr;
ldb::DB::Open(o, string(getenv("HOME")) + "/.ethereum++/state", &db); ldb::DB::Open(o, string(getenv("HOME")) + "/.ethereum/state", &db);
m_db.setDB(db); m_db.setDB(db);
m_state.init(); m_state.init();
@ -292,7 +295,7 @@ u256 State::playback(bytesConstRef _block, BlockInfo const& _grandParent)
// @returns the block that represents the difference between m_previousBlock and m_currentBlock. // @returns the block that represents the difference between m_previousBlock and m_currentBlock.
// (i.e. all the transactions we executed). // (i.e. all the transactions we executed).
void State::prepareToMine(BlockChain const& _bc) void State::commitToMine(BlockChain const& _bc)
{ {
RLPStream uncles; RLPStream uncles;
if (m_previousBlock != BlockInfo::genesis()) if (m_previousBlock != BlockInfo::genesis())

24
libethereum/State.h

@ -48,28 +48,35 @@ class BlockChain;
class State class State
{ {
public: public:
/// Construct null state object.
// State() {}
/// Construct state object. /// Construct state object.
explicit State(Address _coinbaseAddress); explicit State(Address _coinbaseAddress);
/// Compiles uncles and transactions list, and puts hashes into the current block header. /// Cancels transactions and rolls back the state to the end of the previous block.
void prepareToMine(BlockChain const& _bc); /// @warning This will only work for on any transactions after you called the last commitToMine().
/// It's one or the other.
void rollback() { m_cache.clear(); }
/// Prepares the current state for mining.
/// Commits all transactions into the trie, compiles uncles and transactions list, applies all
/// rewards and populates the current block header with the appropriate hashes.
/// The only thing left to do after this is to actually mine().
void commitToMine(BlockChain const& _bc);
/// Attempt to find valid nonce for block that this state represents. /// Attempt to find valid nonce for block that this state represents.
/// @param _msTimeout Timeout before return in milliseconds. /// @param _msTimeout Timeout before return in milliseconds.
/// @returns true if it got lucky. /// @returns true if it got lucky. In this case, call blockData() to get the block for
/// spreading far and wide.
bool mine(uint _msTimeout = 1000); bool mine(uint _msTimeout = 1000);
/// Get the complete current block, including valid nonce. /// Get the complete current block, including valid nonce.
/// Only valid after mine() returns true.
bytes const& blockData() const { return m_currentBytes; } bytes const& blockData() const { return m_currentBytes; }
/// Sync our state with the block chain. /// Sync our state with the block chain.
/// This basically involves wiping ourselves if we've been superceded and rebuilding from the transaction queue. /// This basically involves wiping ourselves if we've been superceded and rebuilding from the transaction queue.
void sync(BlockChain const& _bc); void sync(BlockChain const& _bc);
/// Sync with the block chain, but rather than synching to the latest block sync to the given block. /// Sync with the block chain, but rather than synching to the latest block, instead sync to the given block.
void sync(BlockChain const& _bc, h256 _blockHash); void sync(BlockChain const& _bc, h256 _blockHash);
/// Sync our transactions, killing those from the queue that we have and assimilating those that we don't. /// Sync our transactions, killing those from the queue that we have and assimilating those that we don't.
@ -137,9 +144,6 @@ private:
/// Commit all changes waiting in the address cache. /// Commit all changes waiting in the address cache.
void commit(); void commit();
/// Commit all changes waiting in the address cache.
void rollback() { m_cache.clear(); }
/// Execute the given block on our previous block. This will set up m_currentBlock first, then call the other playback(). /// Execute the given block on our previous block. This will set up m_currentBlock first, then call the other playback().
/// Any failure will be critical. /// Any failure will be critical.
u256 playback(bytesConstRef _block); u256 playback(bytesConstRef _block);

32
test/state.cpp

@ -24,9 +24,39 @@
using namespace std; using namespace std;
using namespace eth; using namespace eth;
struct KeyPair
{
KeyPair() {}
KeyPair(PrivateKey _k): priv(_k), addr(toPublic(_k)) {}
PrivateKey priv;
Address addr;
};
int stateTest() int stateTest()
{ {
State s(toPublic(sha3("123"))); KeyPair me = sha3("Gav Wood");
KeyPair myMiner = sha3("Gav's Miner");
// KeyPair you = sha3("123");
State s(myMiner.addr);
// Mine to get some ether!
s.mine();
bytes tx;
{
Transaction t;
t.nonce = s.transactionsFrom(myMiner.addr);
t.fee = 0;
t.value = 1; // 1 wei.
t.receiveAddress = me.addr;
t.sign(myMiner.priv);
tx = t.rlp();
}
cout << RLP(tx) << endl;
s.execute(tx);
// TODO: Mine to set in stone.
return 0; return 0;
} }

Loading…
Cancel
Save