Browse Source

More work on big picture stuff.

cl-refactor
Gav Wood 11 years ago
parent
commit
e7ebf1e6b6
  1. 4
      eth/main.cpp
  2. 8
      libethereum/BlockChain.cpp
  3. 5
      libethereum/BlockChain.h
  4. 3
      libethereum/Exceptions.h
  5. 20
      libethereum/PeerNetwork.cpp
  6. 74
      libethereum/State.cpp
  7. 5
      libethereum/State.h
  8. 17
      libethereum/TransactionQueue.cpp
  9. 10
      libethereum/TransactionQueue.h
  10. 2
      test/main.cpp

4
eth/main.cpp

@ -31,9 +31,9 @@ int main()
// Our address.
Address us; // TODO: should be loaded from config file/set at command-line.
BlockChain bc; // TODO: Implement - should look for block database.
BlockChain bc; // TODO: Implement - should maintain block database.
TransactionQueue tq; // TODO: Implement.
State s(us);
State s(us); // TODO: Switch to disk-backed state (leveldb)
// s.restore(); // TODO: Implement - key optimisation.
// Synchronise the state according to the block chain - i.e. replay all transactions, in order. Will take a while if the state isn't restored.

8
libethereum/BlockChain.cpp

@ -36,6 +36,13 @@ BlockChain::~BlockChain()
{
}
std::vector<u256> blockChain() const
{
// TODO: return the current valid block chain from most recent to genesis.
// TODO: arguments for specifying a set of early-ends
return std::vector<u256>();
}
void BlockChain::import(bytes const& _block)
{
BlockInfo bi;
@ -59,6 +66,7 @@ void BlockChain::import(bytes const& _block)
bi.number = it->second.first + 1;
// CHECK ANCESTRY:
// TODO: check it hashes according to proof of work.
// TODO: check timestamp is after previous timestamp.
// TODO: check difficulty is correct given the two timestamps.

5
libethereum/BlockChain.h

@ -52,12 +52,17 @@ public:
/// To be called from main loop every 100ms or so.
void process();
/// Attempt to import the given block.
bool attemptImport(bytes const& _block) { try { import(_bytes); return true; } catch (...) { return false; } }
/// Import block into disk-backed DB
void import(bytes const& _block);
/// Get the last block of the longest chain.
bytesConstRef lastBlock() const; // TODO: switch to return MappedBlock or add the lock into vector_ref
std::vector<u256> blockChain()
/// Get the number of the last block of the longest chain.
u256 lastBlockNumber() const;

3
libethereum/Exceptions.h

@ -23,6 +23,7 @@ class InvalidTransactionsHash: public std::exception {};
class InvalidTransaction: public std::exception {};
class InvalidDifficulty: public std::exception {};
class InvalidTimestamp: public std::exception {};
class InvalidNonce: public std::exception {};
class InvalidNonce: public std::exception { public: InvalidNonce(u256 _required, u256 _candidate): required(_required), candidate(_candidate) {} u256 required; u256 candidate; };
class InvalidParentHash: public std::exception {};
}

20
libethereum/PeerNetwork.cpp

@ -39,23 +39,13 @@ void PeerNetwork::process()
void PeerNetwork::sync(BlockChain& _bc, TransactionQueue const& _tq)
{
/*
while (incomingBlock())
while (incomingData())
{
// import new block
bytes const& block = net.incomingBlock();
_bc.import(block);
net.popIncomingBlock();
// check block chain and make longest given all available blocks.
bc.rejig();
}
while (incomingTransaction())
{
bytes const& tx = net.incomingTransaction();
_tq.import(tx);
net.popIncomingTransaction();
bytes const& data = net.incomingData();
if (!tq.attemptImport(data) && !_bc.attemptImport(data))
handleMessage(data);
popIncoming();
}
*/
}

74
libethereum/State.cpp

@ -45,8 +45,10 @@ State::State(Address _minerAddress): m_minerAddress(_minerAddress)
m_currentBlock.number = 1;
}
void State::sync(BlockChain const& _bc, TransactionQueue const& _tq)
void State::sync(BlockChain const& _bc, TransactionQueue& _tq)
{
// BLOCK
BlockInfo bi;
try
{
@ -55,6 +57,7 @@ void State::sync(BlockChain const& _bc, TransactionQueue const& _tq)
}
catch (...)
{
// TODO: Slightly nicer handling? :-)
cerr << "ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl;
exit(1);
}
@ -79,6 +82,69 @@ void State::sync(BlockChain const& _bc, TransactionQueue const& _tq)
// New blocks available, or we've switched to a different branch. All change.
// TODO: Find most recent state dump and replay what's left.
// (Most recent state dump might end up being genesis.)
std::vector<u256> l = _bc.blockChain(); // TODO: take u256Set "restorePoints" argument so it needs only give us the chain up until some restore point in the past where we stored the state.
if (l.back() == BlockInfo::genesis().hash)
{
// Reset to genesis block.
m_current.clear();
m_previousBlock = BlockInfo::genesis();
}
else
{
// TODO: Begin at a restore point.
}
// Iterate through in reverse, playing back each of the blocks.
for (auto it = next(l.cbegin()); it != l.cend(); ++it)
playback(_bc.block(*it));
m_transactions.clear();
}
// TRANSACTIONS
auto ts = _tq.transactions();
for (auto const& i: ts)
if (!m_transactions.count(i.first))
// don't have it yet! Execute it now.
try
{
Transaction t(i.second);
execute(t, t.sender());
}
catch (InvalidNonce in)
{
if (in.required > in.candidate)
// too old
_tq.drop(i.first);
}
catch (...)
{
}
}
void State::playback(bytesConstRef _block)
{
BlockInfo bi;
try
{
bi.populate(_block, m_previousBlock.number + 1);
bi.verifyInternals(_block);
if (bi.parentHash != m_previousBlock.hash)
throw InvalidParentHash();
// All ok with the block generally. Play back the transactions now...
RLP txs = _block[1];
for (auto const& i: txs)
execute(i.data());
}
catch (...)
{
// TODO: Slightly nicer handling? :-)
cerr << "ERROR: Corrupt block-chain! Delete your block-chain DB and restart." << endl;
exit(1);
}
}
@ -149,13 +215,13 @@ void State::execute(Transaction const& _t, Address _sender)
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();
// Add to the transactions in
m_transactions.push_back(_t.sha3(), _t);
if (_t.receiveAddress)
{
subBalance(_sender, _t.value + _t.fee);

5
libethereum/State.h

@ -108,10 +108,13 @@ private:
/// Execute a contract transaction.
void execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _txFee, u256s const& _txData, u256* o_totalFee);
/// Execute all transactions within a given block.
void playback(bytesConstRef _block);
// TODO: std::hash<Address> and then move to unordered_map.
// Will need to sort on hash construction.
std::map<Address, AddressState> m_current; ///< The current state. We work with a C++ hash map rather than a Trie.
std::vector<Transaction> m_transactions; ///< The current list of transactions that we've included in the state.
std::map<u256, Transaction> m_transactions; ///< The current list of transactions that we've included in the state.
BlockInfo m_previousBlock; ///< The previous block's information.
BlockInfo m_currentBlock; ///< The current block's information.

17
libethereum/TransactionQueue.cpp

@ -19,6 +19,23 @@
* @date 2014
*/
#include "Transaction.h"
#include "TransactionQueue.h"
using namespace std;
using namespace eth;
void TransactionQueue::import(bytes const& _block)
{
// Check if we already know this transaction.
u256 h = sha3(_block);
if (m_hashes.count(h))
return;
// Check validity of _block as a transaction. To do this we just deserialise and attempt to determine the sender. If it doesn't work, the signature is bad.
// The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction).
Transaction t(_block);
u160 sender = t.sender();
// If valid, append to blocks.
m_data[h] = m_data;
}

10
libethereum/TransactionQueue.h

@ -34,10 +34,16 @@ class BlockChain;
class TransactionQueue
{
public:
void sync(BlockChain const& _bc) {}
bool attemptImport(bytes const& _block) { try { import(_bytes); return true; } catch (...) { return false; } }
void import(bytes const& _block);
void drop(u256 _txHash) { m_data.erase(_txHash); }
std::map<u256, bytes> const& transactions() const;
private:
std::vector<bytes> m_data;
std::map<u256, bytes> m_data; ///< the queue.
};
}

2
test/main.cpp

@ -38,7 +38,7 @@ int main()
{
// Test dagger
{
Dagger d(1);
Dagger d(0);
auto s = steady_clock::now();
cout << hex << d.eval(0);
cout << " " << dec << duration_cast<milliseconds>(steady_clock::now() - s).count() << " ms" << endl;

Loading…
Cancel
Save