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);
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);
return block.out();
@ -82,7 +82,7 @@ void BlockInfo::populate(bytesConstRef _block)
sha3Transactions = header[4].toHash<h256>();
difficulty = header[5].toInt<u256>();
timestamp = header[6].toInt<u256>();
extraData = header[7].toHash<h256>();
extraData = header[7].toBytes();
nonce = header[8].toInt<u256>();
}
catch (RLP::BadCast)

2
libethereum/BlockInfo.h

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

4
libethereum/Common.cpp

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

15
libethereum/Dagger.cpp

@ -20,6 +20,20 @@ using namespace std::chrono;
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()
{
}
@ -130,4 +144,5 @@ h256 Dagger::eval(h256 const& _root, u256 const& _nonce)
return get(bsha);
}
#endif
}

17
libethereum/Dagger.h

@ -2,9 +2,24 @@
#include "Common.h"
#define FAKE_DAGGER 1
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.
class Dagger
{
@ -26,6 +41,8 @@ private:
u256 m_nonce;
};
#endif
}

2
libethereum/RLP.h

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

7
libethereum/State.cpp

@ -20,6 +20,7 @@
*/
#include <secp256k1.h>
#include <boost/filesystem.hpp>
#if WIN32
#pragma warning(push)
#pragma warning(disable:4244)
@ -58,9 +59,11 @@ State::State(Address _coinbaseAddress): m_state(&m_db), m_ourAddress(_coinbaseAd
m_previousBlock = BlockInfo::genesis();
m_currentBlock.coinbaseAddress = m_ourAddress;
boost::filesystem::create_directory(string(getenv("HOME")) + "/.ethereum/");
ldb::Options o;
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_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.
// (i.e. all the transactions we executed).
void State::prepareToMine(BlockChain const& _bc)
void State::commitToMine(BlockChain const& _bc)
{
RLPStream uncles;
if (m_previousBlock != BlockInfo::genesis())

24
libethereum/State.h

@ -48,28 +48,35 @@ class BlockChain;
class State
{
public:
/// Construct null state object.
// State() {}
/// Construct state object.
explicit State(Address _coinbaseAddress);
/// Compiles uncles and transactions list, and puts hashes into the current block header.
void prepareToMine(BlockChain const& _bc);
/// Cancels transactions and rolls back the state to the end of the previous block.
/// @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.
/// @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);
/// Get the complete current block, including valid nonce.
/// Only valid after mine() returns true.
bytes const& blockData() const { return m_currentBytes; }
/// Sync our state with the block chain.
/// This basically involves wiping ourselves if we've been superceded and rebuilding from the transaction queue.
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);
/// 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.
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().
/// Any failure will be critical.
u256 playback(bytesConstRef _block);

32
test/state.cpp

@ -24,9 +24,39 @@
using namespace std;
using namespace eth;
struct KeyPair
{
KeyPair() {}
KeyPair(PrivateKey _k): priv(_k), addr(toPublic(_k)) {}
PrivateKey priv;
Address addr;
};
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;
}

Loading…
Cancel
Save