Browse Source

Genesis block stuff.

cl-refactor
Gav Wood 11 years ago
parent
commit
cd45bb65d0
  1. 32
      libethereum/BlockChain.cpp
  2. 21
      libethereum/BlockChain.h
  3. 20
      libethereum/BlockInfo.cpp
  4. 8
      libethereum/BlockInfo.h
  5. 9
      libethereum/RLP.cpp
  6. 4
      libethereum/RLP.h
  7. 12
      libethereum/State.cpp

32
libethereum/BlockChain.cpp

@ -20,12 +20,16 @@
*/
#include "Common.h"
#include "BlockInfo.h"
#include "BlockChain.h"
using namespace std;
using namespace eth;
BlockChain::BlockChain()
{
// Initialise with the genesis as the last block on the longest chain.
m_lastBlockHash = m_genesisHash = BlockInfo::genesis().hash;
m_genesisBlock = BlockInfo::createGenesisBlock();
}
BlockChain::~BlockChain()
@ -35,3 +39,31 @@ BlockChain::~BlockChain()
void BlockChain::import(bytes const& _block)
{
}
bytesConstRef BlockChain::block(u256 _hash) const
{
auto it = m_cache.find(_hash);
if (it == m_cache.end())
{
// Load block from disk.
pair<u256, std::shared_ptr<MappedBlock>> loaded;
it = m_cache.insert(loaded).first;
}
return it->second->data();
}
bytesConstRef BlockChain::lastBlock() const
{
if (m_lastBlockHash == m_genesisHash)
return bytesConstRef((bytes*)&m_genesisBlock);
return block(m_lastBlockHash);
}
u256 BlockChain::lastBlockNumber() const
{
if (m_lastBlockHash == m_genesisHash)
return 0;
return m_numberAndParent[m_lastBlockHash].first;
}

21
libethereum/BlockChain.h

@ -40,30 +40,41 @@ private:
};
/**
* @brief Models the blockchain database.
* @brief Implements the blockchain database. All data this gives is disk-backed.
*/
class BlockChain
{
public:
BlockChain();
~BlockChain();
/// (Potentiall) renders invalid existing bytesConstRef returned by lastBlock.
/// To be called from main loop every 100ms or so.
void process();
/// Import block into disk-backed DB
void import(bytes const& _block);
/// Get the last block of the longest chain.
bytesConstRef lastBlock() const { return bytesConstRef(); }
bytesConstRef lastBlock() const; // TODO: switch to return MappedBlock or add the lock into vector_ref
/// Get the number of the last block of the longest chain.
u256 lastBlockNumber() const { return Invalid256; }
u256 lastBlockNumber() const;
bytesConstRef block(u256 _hash) const;
private:
// Get fully populated from disk DB.
/// Get fully populated from disk DB.
mutable std::map<u256, std::pair<u256, u256>> m_numberAndParent;
mutable std::multimap<u256, u256> m_children;
// Gets populated on demand and reduced after a while.
/// Gets populated on demand. Inactive nodes are pruned after a while.
mutable std::map<u256, std::shared_ptr<MappedBlock>> m_cache;
/// Hash of the last (valid) block on the longest chain.
u256 m_lastBlockHash;
u256 m_genesisHash;
bytes m_genesisBlock;
};
}

20
libethereum/BlockInfo.cpp

@ -27,11 +27,29 @@
using namespace std;
using namespace eth;
BlockInfo* BlockInfo::s_genesis = nullptr;
BlockInfo::BlockInfo()
{
number = Invalid256;
}
bytes BlockInfo::createGenesisBlock()
{
RLPStream block(3);
auto sha256EmptyList = sha256(RLPEmptyList);
block.appendList(7) << (uint)0 << sha256EmptyList << (uint)0 << sha256EmptyList << (uint)0 << (uint)0 << (uint)0;
block.appendRaw(RLPEmptyList);
block.appendRaw(RLPEmptyList);
return block.out();
}
void BlockInfo::populateGenesis()
{
bytes genesisBlock = createGenesisBlock();
populate(&genesisBlock, 0);
}
void BlockInfo::populate(bytesConstRef _block, u256 _number)
{
number = _number;
@ -70,5 +88,5 @@ void BlockInfo::verify(bytesConstRef _block, u256 _number)
// TODO: check difficulty against timestamp.
// TODO: check proof of work.
// TODO: check each transaction - allow any destination for the miner fees, but everything else must be exactly how we would do it.
// TODO: check each transaction - allow coinbaseAddress for the miner fees, but everything else must be exactly how we would do it.
}

8
libethereum/BlockInfo.h

@ -45,8 +45,16 @@ public:
bool operator==(BlockInfo const& _cmp) const { return hash == _cmp.hash && parentHash == _cmp.parentHash && nonce == _cmp.nonce && number == _cmp.number; }
static BlockInfo const& genesis() { if (!s_genesis) (s_genesis = new BlockInfo)->populateGenesis(); return *s_genesis; }
void populate(bytesConstRef _block, u256 _number);
void verify(bytesConstRef _block, u256 _number);
static bytes createGenesisBlock();
private:
void populateGenesis();
static BlockInfo* s_genesis;
};
}

9
libethereum/RLP.cpp

@ -24,6 +24,7 @@ using namespace std;
using namespace eth;
bytes eth::RLPNull = rlp("");
bytes eth::RLPEmptyList = rlpList();
RLP::iterator& RLP::iterator::operator++()
{
@ -124,6 +125,14 @@ RLPStream& RLPStream::append(std::string const& _s)
return *this;
}
RLPStream& RLPStream::appendRaw(bytes const& _s)
{
uint os = m_out.size();
m_out.resize(os + _s.size());
memcpy(m_out.data() + os, _s.data(), _s.size());
return *this;
}
RLPStream& RLPStream::appendList(uint _count)
{
if (_count < 0x38)

4
libethereum/RLP.h

@ -277,6 +277,7 @@ public:
RLPStream& append(bigint _s);
RLPStream& append(std::string const& _s);
RLPStream& appendList(uint _count);
RLPStream& appendRaw(bytes const& _rlp);
/// Shift operators for appending data items.
RLPStream& operator<<(uint _i) { return append(_i); }
@ -334,6 +335,9 @@ template <class ... _Ts> bytes rlpList(_Ts ... _ts)
/// The empty string in RLP format.
extern bytes RLPNull;
/// The empty list in RLP format.
extern bytes RLPEmptyList;
}
/// Human readable version of RLP.

12
libethereum/State.cpp

@ -41,7 +41,8 @@ u256 const State::c_txFee = 0;
State::State(Address _minerAddress): m_minerAddress(_minerAddress)
{
secp256k1_start();
// TODO: Initialise current block/previous block, ready for sync.
m_previousBlock = BlockInfo::genesis();
m_currentBlock.number = 1;
}
void State::sync(BlockChain const& _bc, TransactionQueue const& _tq)
@ -156,11 +157,15 @@ bool State::verify(bytes const& _block, uint _number)
void State::execute(Transaction const& _t, Address _sender)
{
// Entry point for a contract-originated transaction.
m_transactions.push_back(_t);
// Ignore invalid transactions.
if (_t.nonce != transactionsFrom(_sender))
throw InvalidNonce();
// Add to the transactions in
m_transactions.push_back(_t);
// Not considered invalid - just pointless.
if (balance(_sender) < _t.value + _t.fee)
throw NotEnoughCash();
@ -198,11 +203,14 @@ void State::execute(Transaction const& _t, Address _sender)
void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _txFee, u256s const& _txData, u256* _totalFee)
{
std::vector<u256> stack;
// Find our memory.
auto m = m_current.find(_myAddress);
if (m == m_current.end())
throw NoSuchContract();
auto& myMemory = m->second.memory();
// Set up some local functions.
auto require = [&](u256 _n)
{
if (stack.size() < _n)

Loading…
Cancel
Save