Browse Source

Move to vitalik's PoW...

cl-refactor
Gav Wood 11 years ago
parent
commit
268168df60
  1. 23
      TODO
  2. 2
      alephzero/Main.cpp
  3. 5
      alephzero/alephzero.pro
  4. 4
      libethereum/BlockInfo.cpp
  5. 13
      libethereum/Client.cpp
  6. 5
      libethereum/Client.h
  7. 8
      libethereum/Dagger.cpp
  8. 2
      libethereum/Dagger.h
  9. 57
      libethereum/PeerNetwork.cpp
  10. 4
      libethereum/PeerNetwork.h
  11. 19
      libethereum/State.cpp
  12. 8
      libethereum/State.h

23
TODO

@ -10,21 +10,32 @@ Crypto stuff:
Better handling of corrupt blocks.
Network:
- Firewall-busting PeerConnections.
- Crypto on network.
- Firewall-busting PeerConnections. UPnP?
- Crypto on network. TLS?
- Respect idealPeerCount.
- Peer network traversal for peer discovery.
- Check peer utility (useful transactions & blocks passed) for when dismissing.
- Respect peer count & dismiss/collect/stop listening for peers as necessary.
### GAV
FOR ALPHA:
Network:
** Check peer utility (useful transactions & blocks passed) for when dismissing.
** Respect peer count & dismiss/collect/stop listening for peers as necessary.
** Manage GetBlocks properly; should work for when > 256 blocks away.
* Manage GetBlocks properly; should work for when > 256 blocks away.
UI:
** State panel shouldn't show pending (i.e. post-mined) transactions.
* State panel shouldn't show pending (i.e. post-mined) transactions.
PoW:
* Minute mine times.
Build:
* Windows build.
LATER:
Trie on DB.
- Move the restore point stuff into block restore points

2
alephzero/Main.cpp

@ -119,7 +119,7 @@ void Main::on_net_toggled()
void Main::on_connect_clicked()
{
QString s = QInputDialog::getText(this, "Connect to a Network Peer", "Enter a peer to which a connection may be made:", QLineEdit::Normal, "192.168.0.141:30303");
QString s = QInputDialog::getText(this, "Connect to a Network Peer", "Enter a peer to which a connection may be made:", QLineEdit::Normal, "54.201.244.25:30303");
string host = s.section(":", 0, 0).toStdString();
short port = s.section(":", 1).toInt();
m_client.connect(host, port);

5
alephzero/alephzero.pro

@ -6,14 +6,14 @@
QT += core gui widgets
QMAKE_CXXFLAGS += -std=c++11
TARGET = alephzero
TEMPLATE = app
QMAKE_CXXFLAGS += -std=c++11
QMAKE_LIBDIR += ../../cpp-ethereum-build/libethereum ../../secp256k1 ../../cryptopp562
LIBS += -Wl,-rpath,../../cpp-ethereum-build/libethereum -Wl,-rpath,../../secp256k1 -Wl,-rpath,../../cryptopp562 -lethereum -lsecp256k1 -lleveldb -lcryptopp -lgmp -lboost_filesystem -lboost_system
INCLUDEPATH = ../../secp256k1/include ../../cryptopp562 ../../cpp-ethereum
SOURCES += main.cpp\
Main.cpp
@ -22,6 +22,5 @@ HEADERS += Main.h
FORMS += Main.ui
INCLUDEPATH = ../../secp256k1/include ../../cryptopp562 ../../cpp-ethereum

4
libethereum/BlockInfo.cpp

@ -90,8 +90,8 @@ void BlockInfo::populate(bytesConstRef _block)
throw InvalidBlockFormat();
}
// check it hashes according to proof of work.
if (!Dagger::verify(headerHashWithoutNonce(), nonce, difficulty))
// check it hashes according to proof of work or that it's the genesis block.
if (parentHash && !Dagger::verify(headerHashWithoutNonce(), nonce, difficulty))
throw InvalidNonce();
}

13
libethereum/Client.cpp

@ -37,6 +37,7 @@ Client::Client(std::string const& _clientVersion, Address _us, std::string const
// TODO: currently it contains keys for *all* blocks. Make it remove old ones.
m_s.sync(m_bc);
m_s.sync(m_tq);
m_changed = true;
m_work = new thread([&](){ while (m_workState != Deleting) work(); m_workState = Deleted; });
}
@ -93,6 +94,7 @@ void Client::transact(Secret _secret, Address _dest, u256 _amount, u256 _fee, u2
t.sign(_secret);
m_tq.attemptImport(t.rlp());
m_lock.unlock();
m_changed = true;
}
void Client::work()
@ -102,7 +104,8 @@ void Client::work()
// Synchronise block chain with network.
// Will broadcast any of our (new) transactions and blocks, and collect & add any of their (new) transactions and blocks.
if (m_net)
m_net->process(m_bc, m_tq, m_stateDB);
if (m_net->process(m_bc, m_tq, m_stateDB))
m_changed = true;
// Synchronise state to block chain.
// This should remove any transactions on our queue that are included within our state.
@ -110,8 +113,11 @@ void Client::work()
// This might mean reverting to an earlier state and replaying some blocks, or, (worst-case:
// if there are no checkpoints before our fork) reverting to the genesis block and replaying
// all blocks.
m_s.sync(m_bc); // Resynchronise state with block chain & trans
m_s.sync(m_tq);
// Resynchronise state with block chain & trans
if (m_s.sync(m_bc))
m_changed = true;
if (m_s.sync(m_tq))
m_changed = true;
m_lock.unlock();
if (m_doMine)
@ -130,6 +136,7 @@ void Client::work()
m_bc.attemptImport(m_s.blockData(), m_stateDB);
m_mineProgress.best = 0;
m_lock.unlock();
m_changed = true;
}
}
else

5
libethereum/Client.h

@ -51,6 +51,8 @@ public:
void lock();
void unlock();
bool changed() const { auto ret = m_changed; m_changed = false; return ret; }
State const& state() const { return m_s; }
BlockChain const& blockChain() const { return m_bc; }
TransactionQueue const& transactionQueue() const { return m_tq; }
@ -63,6 +65,7 @@ public:
void stopNetwork();
void setAddress(Address _us) { m_s.setAddress(_us); }
Address address() const { return m_s.address(); }
void startMining();
void stopMining();
MineProgress miningProgress() const { return m_mineProgress; }
@ -81,6 +84,8 @@ private:
enum { Active = 0, Deleting, Deleted } m_workState = Active;
bool m_doMine = false; ///< Are we supposed to be mining?
MineProgress m_mineProgress;
mutable bool m_changed;
};
}

8
libethereum/Dagger.cpp

@ -24,11 +24,11 @@ namespace eth
MineInfo Dagger::mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, uint _msTimeout, bool const& _continue)
{
MineInfo ret{toLog2(_difficulty), 0, false};
MineInfo ret{0, 0, false};
static std::mt19937_64 s_eng((time(0)));
o_solution = std::uniform_int_distribution<uint>(0, ~(uint)0)(s_eng);
u256 d = ((u256)1 << 235) - _difficulty;
u256 d = (u256)(((bigint)1 << 256) / _difficulty);
ret.requirement = toLog2(d);
// 2^ 0 32 64 128 256
@ -38,8 +38,8 @@ MineInfo Dagger::mine(u256& o_solution, h256 const& _root, u256 const& _difficul
for (auto startTime = steady_clock::now(); (steady_clock::now() - startTime) < milliseconds(_msTimeout) && _continue && !ret.completed; o_solution += 1)
{
auto e = (u256)eval(_root, o_solution);
ret.best = max(ret.best, 256 - toLog2(e));
if (e < d)
ret.best = max(ret.best, toLog2(e));
if (e <= d)
ret.completed = true;
}
return ret;

2
libethereum/Dagger.h

@ -25,7 +25,7 @@ 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 * 1000; }
static bool verify(h256 const& _root, u256 const& _nonce, u256 const& _difficulty) { return (bigint)(u256)eval(_root, _nonce) <= (bigint(1) << 256) / _difficulty; }
MineInfo mine(u256& o_solution, h256 const& _root, u256 const& _difficulty, uint _msTimeout = 100, bool const& _continue = bool(true));
};

57
libethereum/PeerNetwork.cpp

@ -38,6 +38,8 @@ PeerSession::~PeerSession()
disconnect();
}
// TODO: BUG! 256 -> work out why things start to break with big packet sizes -> g.t. ~370 blocks.
bool PeerSession::interpret(RLP const& _r)
{
switch (_r[0].toInt<unsigned>())
@ -164,15 +166,15 @@ bool PeerSession::interpret(RLP const& _r)
latestNumber = m_server->m_chain->details(latest).number;
parentNumber = m_server->m_chain->details(parent).number;
uint count = min<uint>(latestNumber - parentNumber, baseCount);
cout << "Requires " << dec << (latestNumber - parentNumber) << " blocks from " << latestNumber << " to " << parentNumber << endl;
cout << latest << " - " << parent << endl;
// cout << "Requires " << dec << (latestNumber - parentNumber) << " blocks from " << latestNumber << " to " << parentNumber << endl;
// cout << latest << " - " << parent << endl;
prep(s);
s.appendList(2) << (uint)Blocks;
s.appendList(count);
uint endNumber = m_server->m_chain->details(parent).number;
uint startNumber = endNumber + count;
cout << "Sending " << dec << count << " blocks from " << startNumber << " to " << endNumber << endl;
// cout << "Sending " << dec << count << " blocks from " << startNumber << " to " << endNumber << endl;
uint n = latestNumber;
for (; n > startNumber; n--, h = m_server->m_chain->details(h).parent) {}
@ -181,7 +183,7 @@ bool PeerSession::interpret(RLP const& _r)
// cout << " " << dec << i << " " << h << endl;
s.appendRaw(m_server->m_chain->block(h));
}
cout << "Parent: " << h << endl;
// cout << "Parent: " << h << endl;
}
else if (parent != parents.back())
continue;
@ -256,10 +258,10 @@ void PeerSession::seal(bytes& _b)
_b[2] = 0x08;
_b[3] = 0x91;
uint32_t len = _b.size() - 8;
_b[4] = len >> 24;
_b[5] = len >> 16;
_b[6] = len >> 8;
_b[7] = len;
_b[4] = (len >> 24) & 0xff;
_b[5] = (len >> 16) & 0xff;
_b[6] = (len >> 8) & 0xff;
_b[7] = len & 0xff;
}
void PeerSession::sealAndSend(RLPStream& _s)
@ -275,13 +277,13 @@ void PeerSession::sendDestroy(bytes& _msg)
std::shared_ptr<bytes> buffer = std::make_shared<bytes>();
swap(*buffer, _msg);
assert((*buffer)[0] == 0x22);
cout << "Sending " << (buffer->size() - 8) << endl;
// cout << "Sending " << (buffer->size() - 8) << endl;
// cout << "Sending " << RLP(bytesConstRef(buffer.get()).cropped(8)) << endl;
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
{
if (ec)
dropped();
cout << length << " bytes written (EC: " << ec << ")" << endl;
// cout << length << " bytes written (EC: " << ec << ")" << endl;
});
}
@ -289,12 +291,12 @@ void PeerSession::send(bytesConstRef _msg)
{
std::shared_ptr<bytes> buffer = std::make_shared<bytes>(_msg.toBytes());
assert((*buffer)[0] == 0x22);
cout << "Sending " << (_msg.size() - 8) << endl;// RLP(bytesConstRef(buffer.get()).cropped(8)) << endl;
// cout << "Sending " << (_msg.size() - 8) << endl;// RLP(bytesConstRef(buffer.get()).cropped(8)) << endl;
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
{
if (ec)
dropped();
cout << length << " bytes written (EC: " << ec << ")" << endl;
// cout << length << " bytes written (EC: " << ec << ")" << endl;
});
}
@ -353,7 +355,7 @@ void PeerSession::doRead()
else
{
uint32_t len = fromBigEndian<uint32_t>(bytesConstRef(m_incoming.data() + 4, 4));
cout << "Received packet of " << len << " bytes" << endl;
// cout << "Received packet of " << len << " bytes" << endl;
if (m_incoming.size() - 8 < len)
break;
@ -418,7 +420,7 @@ void PeerServer::doAccept()
{
if (!ec)
{
std::cout << "Accepted connection from " << m_socket.remote_endpoint() << std::endl;
cout << "Accepted connection from " << m_socket.remote_endpoint() << std::endl;
auto p = std::make_shared<PeerSession>(this, std::move(m_socket), m_requiredNetworkId);
m_peers.push_back(p);
p->start();
@ -469,21 +471,30 @@ bool PeerServer::connect(bi::tcp::endpoint _ep)
}
}
void PeerServer::process(BlockChain& _bc)
bool PeerServer::process(BlockChain& _bc)
{
bool ret = false;
m_ioService.poll();
for (auto i = m_peers.begin(); i != m_peers.end();)
if (auto j = i->lock())
if (j->m_socket.is_open())
++i;
else
{
i = m_peers.erase(i);
ret = true;
}
else
{
i = m_peers.erase(i);
ret = true;
}
return ret;
}
void PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
{
bool ret = false;
if (m_latestBlockSent == h256())
{
// First time - just initialise.
@ -491,12 +502,16 @@ void PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
for (auto const& i: _tq.transactions())
m_transactionsSent.insert(i.first);
m_lastPeersRequest = chrono::steady_clock::now();
ret = true;
}
process(_bc);
if (process(_bc))
ret = true;
for (auto it = m_incomingTransactions.begin(); it != m_incomingTransactions.end(); ++it)
if (!_tq.import(*it))
if (_tq.import(*it))
ret = true;
else
m_transactionsSent.insert(sha3(*it)); // if we already had the transaction, then don't bother sending it on.
m_incomingTransactions.clear();
@ -559,6 +574,7 @@ void PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
_bc.import(*it, _o);
it = m_incomingBlocks.erase(it);
++accepted;
ret = true;
}
catch (UnknownParent)
{
@ -575,6 +591,10 @@ void PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
}
}
// platform for consensus of social contract.
// restricts your freedom but does so fairly. and that's the value proposition.
// guarantees that everyone else respect the rules of the system. (i.e. obeys laws).
// Connect to additional peers
// TODO: Need to avoid connecting to self & existing peers. Existing peers is easy, but need portable method of listing all addresses we can listen to avoid self.
/*
@ -598,6 +618,7 @@ void PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
connect(m_incomingPeers.back());
m_incomingPeers.pop_back();
}*/
return ret;
}
std::vector<PeerInfo> PeerServer::peers() const

4
libethereum/PeerNetwork.h

@ -120,8 +120,8 @@ public:
/// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network.
/// Conduct I/O, polling, syncing, whatever.
/// Ideally all time-consuming I/O is done in a background thread or otherwise asynchronously, but you get this call every 100ms or so anyway.
void process(BlockChain& _bc, TransactionQueue&, Overlay& _o);
void process(BlockChain& _bc);
bool process(BlockChain& _bc, TransactionQueue&, Overlay& _o);
bool process(BlockChain& _bc);
/// Set ideal number of peers.
void setIdealPeerCount(uint _n) { m_idealPeerCount = _n; }

19
libethereum/State.cpp

@ -135,13 +135,14 @@ void State::commit()
m_cache.clear();
}
void State::sync(BlockChain const& _bc)
bool State::sync(BlockChain const& _bc)
{
sync(_bc, _bc.currentHash());
return sync(_bc, _bc.currentHash());
}
void State::sync(BlockChain const& _bc, h256 _block)
bool State::sync(BlockChain const& _bc, h256 _block)
{
bool ret = false;
// BLOCK
BlockInfo bi;
try
@ -164,6 +165,7 @@ void State::sync(BlockChain const& _bc, h256 _block)
m_previousBlock = m_currentBlock;
resetCurrent();
m_currentNumber++;
ret = true;
}
else if (bi == m_previousBlock)
{
@ -192,7 +194,9 @@ void State::sync(BlockChain const& _bc, h256 _block)
m_currentNumber = _bc.details(_block).number + 1;
resetCurrent();
ret = true;
}
return ret;
}
map<Address, u256> State::addresses() const
@ -218,9 +222,10 @@ void State::resetCurrent()
m_state.setRoot(m_currentBlock.stateRoot);
}
void State::sync(TransactionQueue& _tq)
bool State::sync(TransactionQueue& _tq)
{
// TRANSACTIONS
bool ret = false;
auto ts = _tq.transactions();
for (auto const& i: ts)
if (!m_transactions.count(i.first))
@ -228,18 +233,24 @@ void State::sync(TransactionQueue& _tq)
try
{
execute(i.second);
ret = true;
}
catch (InvalidNonce const& in)
{
if (in.required > in.candidate)
{
// too old
_tq.drop(i.first);
ret = true;
}
}
catch (std::exception const&)
{
// Something else went wrong - drop it.
_tq.drop(i.first);
ret = true;
}
return ret;
}
u256 State::playback(bytesConstRef _block, bool _fullCommit)

8
libethereum/State.h

@ -88,13 +88,13 @@ public:
/// 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);
bool sync(BlockChain const& _bc);
/// 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);
bool sync(BlockChain const& _bc, h256 _blockHash);
/// Sync our transactions, killing those from the queue that we have and assimilating those that we don't.
void sync(TransactionQueue& _tq);
bool sync(TransactionQueue& _tq);
/// Execute a given transaction.
void execute(bytes const& _rlp) { return execute(&_rlp); }
@ -196,7 +196,7 @@ private:
Address m_ourAddress; ///< Our address (i.e. the address to which fees go).
Dagger m_dagger;
/// The fee structure. Values yet to be agreed on...
static const u256 c_stepFee;
static const u256 c_dataFee;

Loading…
Cancel
Save