Browse Source

Merge branch 'upstream' into develop

cl-refactor
subtly 11 years ago
parent
commit
73bc2f070e
  1. 18
      CMakeLists.txt
  2. 35
      TODO
  3. 11
      alethzero/MainWin.cpp
  4. 10
      eth/main.cpp
  5. 4
      libethereum/AddressState.cpp
  6. 4
      libethereum/AddressState.h
  7. 51
      libethereum/BlockChain.cpp
  8. 15
      libethereum/BlockChain.h
  9. 4
      libethereum/BlockInfo.cpp
  10. 4
      libethereum/BlockInfo.h
  11. 38
      libethereum/Client.cpp
  12. 8
      libethereum/Client.h
  13. 4
      libethereum/Common.cpp
  14. 30
      libethereum/Common.h
  15. 4
      libethereum/Defaults.cpp
  16. 4
      libethereum/Defaults.h
  17. 4
      libethereum/FileSystem.cpp
  18. 4
      libethereum/FileSystem.h
  19. 4
      libethereum/MemTrie.cpp
  20. 4
      libethereum/MemTrie.h
  21. 441
      libethereum/PeerNetwork.cpp
  22. 27
      libethereum/PeerNetwork.h
  23. 4
      libethereum/RLP.cpp
  24. 12
      libethereum/RLP.h
  25. 27
      libethereum/State.cpp
  26. 9
      libethereum/State.h
  27. 4
      libethereum/Transaction.cpp
  28. 4
      libethereum/Transaction.h
  29. 4
      libethereum/TransactionQueue.cpp
  30. 4
      libethereum/TransactionQueue.h
  31. 4
      libethereum/TrieCommon.cpp
  32. 4
      libethereum/TrieCommon.h
  33. 4
      libethereum/TrieDB.cpp
  34. 4
      libethereum/TrieDB.h
  35. 4
      libethereum/TrieHash.cpp
  36. 4
      libethereum/TrieHash.h
  37. 4
      libethereum/UPnP.cpp
  38. 4
      libethereum/UPnP.h
  39. 4
      test/crypto.cpp
  40. 4
      test/dagger.cpp
  41. 4
      test/hexPrefix.cpp
  42. 4
      test/main.cpp
  43. 6
      test/peer.cpp
  44. 4
      test/rlp.cpp
  45. 4
      test/state.cpp
  46. 4
      test/trie.cpp

18
CMakeLists.txt

@ -5,11 +5,17 @@ set(CMAKE_AUTOMOC ON)
cmake_policy(SET CMP0015 NEW)
set(ETH_VERSION 0.2.3)
set(ETH_VERSION 0.2.6)
set(ETH_BUILD_TYPE ${CMAKE_BUILD_TYPE})
set(TARGET_PLATFORM CACHE STRING "linux")
# Default HEADLESS to 0.
set(HEADLESS CACHE BOOL 0)
if ("x${HEADLESS}" STREQUAL "x")
set(HEADLESS 0)
endif ()
# Default TARGET_PLATFORM to "linux".
set(TARGET_PLATFORM CACHE STRING "linux")
if ("x${TARGET_PLATFORM}" STREQUAL "x")
set(TARGET_PLATFORM "linux")
endif ()
@ -141,4 +147,10 @@ add_subdirectory(secp256k1)
add_subdirectory(libethereum)
add_subdirectory(test)
add_subdirectory(eth)
add_subdirectory(alethzero)
if (NOT HEADLESS)
add_subdirectory(alethzero)
endif ()
unset(HEADLESS CACHE)
#unset(TARGET_PLATFORM CACHE)

35
TODO

@ -7,12 +7,21 @@ Crypto stuff:
- kFromMessage
- Check all the tweak instructions.
Better handling of corrupt blocks.
- Kill DB & restart.
Network:
- Crypto on network. TLS?
- *** Exponential backoff on bad connection.
- NotInChain will be very bad for new peers - it'll run through until the genesis.
- Check how many it has first.
- Crypto on network - use id as public key?
- Make work with IPv6
- Peers rated.
- Useful/useless - new blocks/transactions or useful peers?
- Solid communications?
- Strategy for peer suggestion?
THREAD-SAFETY
- BlockChain
- TransactionQueue
- State
CLI client
- Implement CLI option "--help".
@ -23,22 +32,24 @@ General:
- Move over to new system.
- Remove block chain on protocol change (i.e. store protocol with block chain).
Robustness
- Remove aborts
- Recover from all exceptions.
- Store version alongside BC DB.
- Better handling of corrupt blocks.
- Kill DB & restart.
### Gav
GUI
- Make address/block chain list model-based, JIT populated.
- Make everything else model-based
- Qt/QML class.
For PoC2:
For PoC3:
- Shared contract acceptence tests.
- Use mining state for nonce.
Network:
- NotInChain will be very bad for new peers - it'll run through until the genesis.
- Check how many it has first.
BUG: need to discard transactions if nonce too old, even when not mining.
### Marko
Ubuntu builds

11
alethzero/MainWin.cpp

@ -24,7 +24,7 @@ Main::Main(QWidget *parent) :
{
setWindowFlags(Qt::Window);
ui->setupUi(this);
g_logPost = [=](std::string const& s, char const*) { ui->log->addItem(QString::fromStdString(s)); };
g_logPost = [=](std::string const& s, char const* c) { simpleDebugOut(s, c); ui->log->addItem(QString::fromStdString(s)); };
m_client = new Client("AlethZero");
readSettings();
@ -142,13 +142,12 @@ void Main::refresh()
ui->accounts->addItem(QString("%1 @ %2").arg(formatBalance(i.second).c_str()).arg(asHex(i.first.asArray()).c_str()));
ui->transactionQueue->clear();
for (pair<h256, bytes> const& i: m_client->transactionQueue().transactions())
for (pair<h256, Transaction> const& i: m_client->pending())
{
Transaction t(i.second);
ui->transactionQueue->addItem(QString("%1 @ %2 <- %3")
.arg(formatBalance(t.value).c_str())
.arg(asHex(t.receiveAddress.asArray()).c_str())
.arg(asHex(t.sender().asArray()).c_str()) );
.arg(formatBalance(i.second.value).c_str())
.arg(asHex(i.second.receiveAddress.asArray()).c_str())
.arg(asHex(i.second.sender().asArray()).c_str()) );
}
ui->transactions->clear();

10
eth/main.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
* @author Gav Wood <i@gavwood.com>
@ -352,12 +352,12 @@ int main(int argc, char** argv)
cout << "Address: " << endl << asHex(us.address().asArray()) << endl;
c.startNetwork(listenPort, remoteHost, remotePort, mode, peers, publicIP, upnp);
eth::uint n = c.blockChain().details().number;
if (mining)
c.startMining();
while (true)
{
if (c.blockChain().details().number - n >= mining)
if (c.blockChain().details().number - n == mining)
c.stopMining();
else
c.startMining();
this_thread::sleep_for(chrono::milliseconds(100));
}
}

4
libethereum/AddressState.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AddressState.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/AddressState.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AddressState.h
* @author Gav Wood <i@gavwood.com>

51
libethereum/BlockChain.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BlockChain.cpp
* @author Gav Wood <i@gavwood.com>
@ -168,19 +168,21 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
auto tdIncrease = s.playback(&_block, bi, biParent, biGrandParent, true);
td = pd.totalDifficulty + tdIncrease;
#if !NDEBUG
#if PARANOIA
checkConsistency();
#endif
// All ok - insert into DB
m_details[newHash] = BlockDetails((uint)pd.number + 1, td, bi.parentHash, {});
m_detailsDB->Put(m_writeOptions, ldb::Slice((char const*)&newHash, 32), (ldb::Slice)eth::ref(m_details[newHash].rlp()));
{
lock_guard<mutex> l(m_lock);
m_details[newHash] = BlockDetails((uint)pd.number + 1, td, bi.parentHash, {});
m_details[bi.parentHash].children.push_back(newHash);
}
m_details[bi.parentHash].children.push_back(newHash);
m_detailsDB->Put(m_writeOptions, ldb::Slice((char const*)&newHash, 32), (ldb::Slice)eth::ref(m_details[newHash].rlp()));
m_detailsDB->Put(m_writeOptions, ldb::Slice((char const*)&bi.parentHash, 32), (ldb::Slice)eth::ref(m_details[bi.parentHash].rlp()));
m_db->Put(m_writeOptions, ldb::Slice((char const*)&newHash, 32), (ldb::Slice)ref(_block));
#if !NDEBUG
#if PARANOIA
checkConsistency();
#endif
}
@ -193,15 +195,15 @@ void BlockChain::import(bytes const& _block, Overlay const& _db)
// cnote << "Parent " << bi.parentHash << " has " << details(bi.parentHash).children.size() << " children.";
// This might be the new last block...
if (td > m_details[m_lastBlockHash].totalDifficulty)
if (td > details(m_lastBlockHash).totalDifficulty)
{
m_lastBlockHash = newHash;
m_detailsDB->Put(m_writeOptions, ldb::Slice("best"), ldb::Slice((char const*)&newHash, 32));
clog(BlockChainNote) << " Imported and best. Has" << details(bi.parentHash).children.size() << "siblings.";
clog(BlockChainNote) << " Imported and best. Has" << (details(bi.parentHash).children.size() - 1) << "siblings.";
}
else
{
clog(BlockChainNote) << " Imported but not best (oTD:" << m_details[m_lastBlockHash].totalDifficulty << ", TD:" << td << ")";
clog(BlockChainNote) << " Imported but not best (oTD:" << details(m_lastBlockHash).totalDifficulty << ", TD:" << td << ")";
}
}
@ -230,14 +232,26 @@ bytesConstRef BlockChain::block(h256 _hash) const
if (_hash == m_genesisHash)
return &m_genesisBlock;
m_db->Get(m_readOptions, ldb::Slice((char const*)&_hash, 32), &m_cache[_hash]);
return bytesConstRef(&m_cache[_hash]);
string d;
m_db->Get(m_readOptions, ldb::Slice((char const*)&_hash, 32), &d);
{
lock_guard<mutex> l(m_lock);
swap(m_cache[_hash], d);
return bytesConstRef(&m_cache[_hash]);
}
}
BlockDetails const& BlockChain::details(h256 _h) const
{
auto it = m_details.find(_h);
if (it == m_details.end())
std::map<h256, BlockDetails>::const_iterator it;
bool fetchRequired;
{
lock_guard<mutex> l(m_lock);
it = m_details.find(_h);
fetchRequired = (it == m_details.end());
}
if (fetchRequired)
{
std::string s;
m_detailsDB->Get(m_readOptions, ldb::Slice((char const*)&_h, 32), &s);
@ -246,8 +260,11 @@ BlockDetails const& BlockChain::details(h256 _h) const
// cout << "Not found in DB: " << _h << endl;
return NullBlockDetails;
}
bool ok;
tie(it, ok) = m_details.insert(make_pair(_h, BlockDetails(RLP(s))));
{
lock_guard<mutex> l(m_lock);
bool ok;
tie(it, ok) = m_details.insert(make_pair(_h, BlockDetails(RLP(s))));
}
}
return it->second;
}

15
libethereum/BlockChain.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BlockChain.h
* @author Gav Wood <i@gavwood.com>
@ -21,6 +21,7 @@
#pragma once
#include <mutex>
#include "Common.h"
#include "AddressState.h"
namespace ldb = leveldb;
@ -82,17 +83,14 @@ public:
BlockDetails const& details(h256 _hash) const;
BlockDetails const& details() const { return details(currentHash()); }
/// Get a given block (RLP format).
/// Get a given block (RLP format). Thread-safe.
bytesConstRef block(h256 _hash) const;
bytesConstRef block() const { return block(currentHash()); }
/// Get a given block (RLP format).
/// Get a given block (RLP format). Thread-safe.
h256 currentHash() const { return m_lastBlockHash; }
/// Get the coinbase address of a given block.
Address coinbaseAddress(h256 _hash) const;
Address coinbaseAddress() const { return coinbaseAddress(currentHash()); }
/// Get the hash of the genesis block.
h256 genesisHash() const { return m_genesisHash; }
std::vector<std::pair<Address, AddressState>> interestQueue() { std::vector<std::pair<Address, AddressState>> ret; swap(ret, m_interestQueue); return ret; }
@ -105,6 +103,7 @@ private:
/// Get fully populated from disk DB.
mutable std::map<h256, BlockDetails> m_details;
mutable std::map<h256, std::string> m_cache;
mutable std::mutex m_lock;
/// The queue of transactions that have happened that we're interested in.
std::map<Address, int> m_interest;

4
libethereum/BlockInfo.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BlockInfo.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/BlockInfo.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file BlockInfo.h
* @author Gav Wood <i@gavwood.com>

38
libethereum/Client.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Client.cpp
* @author Gav Wood <i@gavwood.com>
@ -42,6 +42,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_mined = m_s;
m_changed = true;
static const char* c_threadName = "eth";
@ -68,7 +69,7 @@ void Client::startNetwork(short _listenPort, std::string const& _seedHost, short
m_net = new PeerServer(m_clientVersion, m_bc, 0, _listenPort, _mode, _publicIP, _upnp);
m_net->setIdealPeerCount(_peers);
if (_seedHost.size())
m_net->connect(_seedHost, _port);
connect(_seedHost, _port);
}
void Client::connect(std::string const& _seedHost, short _port)
@ -111,15 +112,19 @@ void Client::transact(Secret _secret, Address _dest, u256 _amount, u256s _data)
void Client::work()
{
m_lock.lock();
bool changed = false;
// Process network events.
// 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)
if (m_net->process(m_bc, m_tq, m_stateDB))
{
m_net->process();
lock_guard<mutex> l(m_lock);
if (m_net->sync(m_bc, m_tq, m_stateDB))
changed = true;
}
// Synchronise state to block chain.
// This should remove any transactions on our queue that are included within our state.
@ -127,18 +132,28 @@ 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.
// Resynchronise state with block chain & trans
if (m_s.sync(m_bc))
// Resynchronise state with block chain & trans
{
changed = true;
m_mined = m_s;
lock_guard<mutex> l(m_lock);
if (m_s.sync(m_bc))
{
changed = true;
m_miningStarted = true; // need to re-commit to mine.
if (!m_doMine)
m_mined = m_s;
}
if (m_mined.sync(m_tq))
{
changed = true;
m_miningStarted = true;
}
}
m_lock.unlock();
if (m_doMine)
{
if (m_miningStarted)
{
lock_guard<mutex> l(m_lock);
m_mined = m_s;
m_mined.sync(m_tq);
m_mined.commitToMine(m_bc);
@ -155,10 +170,9 @@ void Client::work()
if (mineInfo.completed)
{
// Import block.
m_lock.lock();
lock_guard<mutex> l(m_lock);
m_bc.attemptImport(m_mined.blockData(), m_stateDB);
m_mineProgress.best = 0;
m_lock.unlock();
m_changed = true;
m_miningStarted = true; // need to re-commit to mine.
}

8
libethereum/Client.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Client.h
* @author Gav Wood <i@gavwood.com>
@ -93,8 +93,8 @@ public:
State const& state() const { return m_s; }
/// Get the object representing the current canonical blockchain.
BlockChain const& blockChain() const { return m_bc; }
/// Get the object representing the transaction queue.
TransactionQueue const& transactionQueue() const { return m_tq; }
/// Get a map containing each of the pending transactions.
std::map<h256, Transaction> const& pending() const { return m_mined.pending(); }
void setClientVersion(std::string const& _name) { m_clientVersion = _name; }

4
libethereum/Common.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Common.cpp
* @author Gav Wood <i@gavwood.com>

30
libethereum/Common.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Common.h
* @author Gav Wood <i@gavwood.com>
@ -67,6 +67,18 @@ using u160Set = std::set<u160>;
template <class T, class Out> inline void toBigEndian(T _val, Out& o_out);
template <class T, class In> inline T fromBigEndian(In const& _bytes);
/// Convert a series of bytes to the corresponding string of hex duplets.
/// @param _w specifies the width of each of the elements. Defaults to two - enough to represent a byte.
/// @example asHex("A\x69") == "4169"
template <class _T>
std::string asHex(_T const& _data, int _w = 2)
{
std::ostringstream ret;
for (auto i: _data)
ret << std::hex << std::setfill('0') << std::setw(_w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
return ret.str();
}
template <unsigned N>
class FixedHash
{
@ -97,6 +109,8 @@ public:
FixedHash operator&(FixedHash const& _c) const { return FixedHash(*this) &= _c; }
FixedHash& operator~() { for (auto i = 0; i < N; ++i) m_data[i] = ~m_data[i]; return *this; }
std::string abridged() const { return asHex(ref().cropped(0, 4)); }
byte& operator[](unsigned _i) { return m_data[_i]; }
byte operator[](unsigned _i) const { return m_data[_i]; }
@ -252,18 +266,6 @@ inline bytes asBytes(std::string const& _b)
return bytes((byte const*)_b.data(), (byte const*)(_b.data() + _b.size()));
}
/// Convert a series of bytes to the corresponding string of hex duplets.
/// @param _w specifies the width of each of the elements. Defaults to two - enough to represent a byte.
/// @example asHex("A\x69") == "4169"
template <class _T>
std::string asHex(_T const& _data, int _w = 2)
{
std::ostringstream ret;
for (auto i: _data)
ret << std::hex << std::setfill('0') << std::setw(_w) << (int)(typename std::make_unsigned<decltype(i)>::type)i;
return ret.str();
}
/// Trims a given number of elements from the front of a collection.
/// Only works for POD element types.
template <class _T>

4
libethereum/Defaults.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Defaults.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/Defaults.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Defaults.h
* @author Gav Wood <i@gavwood.com>

4
libethereum/FileSystem.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file FileSystem.cpp
* @authors

4
libethereum/FileSystem.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file FileSystem.h
* @authors

4
libethereum/MemTrie.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MemTrie.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/MemTrie.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file MemTrie.h
* @author Gav Wood <i@gavwood.com>

441
libethereum/PeerNetwork.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file PeerNetwork.cpp
* @authors:
@ -45,9 +45,9 @@ using namespace eth;
static const int c_protocolVersion = 4;
static const eth::uint c_maxHashes = 256; ///< Maximum number of hashes GetChain will ever send.
static const eth::uint c_maxBlocks = 128; ///< Maximum number of blocks Blocks will ever send. BUG: if this gets too big (e.g. 2048) stuff starts going wrong.
static const eth::uint c_maxBlocksAsk = 2048; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
static const eth::uint c_maxHashes = 32; ///< Maximum number of hashes GetChain will ever send.
static const eth::uint c_maxBlocks = 32; ///< Maximum number of blocks Blocks will ever send. BUG: if this gets too big (e.g. 2048) stuff starts going wrong.
static const eth::uint c_maxBlocksAsk = 256; ///< Maximum number of blocks we ask to receive in Blocks (when using GetChain).
// Addresses we will skip during network interface discovery
// Use a vector as the list is small
@ -107,6 +107,23 @@ bi::tcp::endpoint PeerSession::endpoint() const
return bi::tcp::endpoint();
}
static std::string reasonOf(int _r)
{
switch (_r)
{
case DisconnectRequested: return "Disconnect was requested.";
case TCPError: return "Low-level TCP communication error.";
case BadProtocol: return "Data format error.";
case UselessPeer: return "Peer had no use for this node.";
case TooManyPeers: return "Peer had too many connections.";
case DuplicatePeer: return "Peer was already connected.";
case WrongGenesis: return "Disagreement over genesis block.";
case IncompatibleProtocol: return "Peer protocol versions are incompatible.";
case ClientQuit: return "Peer is exiting.";
default: return "Unknown reason.";
}
}
// TODO: BUG! 256 -> work out why things start to break with big packet sizes -> g.t. ~370 blocks.
bool PeerSession::interpret(RLP const& _r)
@ -123,16 +140,19 @@ bool PeerSession::interpret(RLP const& _r)
m_listenPort = _r[5].toInt<short>();
m_id = _r[6].toHash<h512>();
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "/" << m_networkId << "]" << asHex(m_id.ref().cropped(0, 4)) << showbase << hex << m_caps << dec << m_listenPort;
clogS(NetMessageSummary) << "Hello: " << clientVersion << "V[" << m_protocolVersion << "/" << m_networkId << "]" << m_id.abridged() << showbase << hex << m_caps << dec << m_listenPort;
if (m_server->m_peers.count(m_id) || !m_id)
{
// Already connected.
disconnect(DuplicatePeer);
}
m_server->m_peers[m_id] = shared_from_this();
if (m_server->m_peers.count(m_id))
if (auto l = m_server->m_peers[m_id].lock())
if (l.get() != this && l->isOpen())
{
// Already connected.
cwarn << "Already have peer id" << m_id.abridged() << "at" << l->endpoint() << "rather than" << endpoint();
disconnect(DuplicatePeer);
return false;
}
if (m_protocolVersion != c_protocolVersion || m_networkId != m_reqNetworkId)
if (m_protocolVersion != c_protocolVersion || m_networkId != m_reqNetworkId || !m_id)
{
disconnect(IncompatibleProtocol);
return false;
@ -145,15 +165,22 @@ bool PeerSession::interpret(RLP const& _r)
return false;
}
m_server->m_peers[m_id] = shared_from_this();
// Grab their block chain off them.
{
clogS(NetAllDetail) << "Want chain. Latest:" << m_server->m_latestBlockSent << ", number:" << m_server->m_chain->details(m_server->m_latestBlockSent).number;
unsigned count = std::min<unsigned>(c_maxHashes, m_server->m_chain->details(m_server->m_latestBlockSent).number + 1);
RLPStream s;
prep(s).appendList(2 + count);
s << GetChainPacket;
auto h = m_server->m_latestBlockSent;
for (unsigned i = 0; i < count; ++i, h = m_server->m_chain->details(h).parent)
{
clogS(NetAllDetail) << " " << i << ":" << h;
s << h;
}
s << c_maxBlocksAsk;
sealAndSend(s);
s.clear();
@ -167,18 +194,7 @@ bool PeerSession::interpret(RLP const& _r)
{
string reason = "Unspecified";
if (_r[1].isInt())
switch (_r[1].toInt<int>())
{
case DisconnectRequested: reason = "Disconnect was requested."; break;
case TCPError: reason = "Low-level TCP communication error."; break;
case BadProtocol: reason = "Data format error."; break;
case UselessPeer: reason = "Peer had no use for this node."; break;
case TooManyPeers: reason = "Peer had too many connections."; break;
case DuplicatePeer: reason = "Peer was already connected."; break;
case WrongGenesis: reason = "Disagreement over genesis block."; break;
case IncompatibleProtocol: reason = "Peer protocol versions are incompatible."; break;
case ClientQuit: reason = "Peer is exiting."; break;
}
reason = reasonOf(_r[1].toInt<int>());
clogS(NetMessageSummary) << "Disconnect (reason: " << reason << ")";
if (m_socket.is_open())
@ -244,9 +260,10 @@ bool PeerSession::interpret(RLP const& _r)
goto CONTINUE;
}
for (auto i: m_server->m_incomingPeers)
if (i.second == ep)
if (i.second.first == ep)
goto CONTINUE;
m_server->m_incomingPeers[id] = ep;
m_server->m_incomingPeers[id] = make_pair(ep, 0);
m_server->m_freePeers.push_back(id);
clogS(NetMessageDetail) << "New peer: " << ep << "(" << id << ")";
CONTINUE:;
}
@ -340,8 +357,13 @@ bool PeerSession::interpret(RLP const& _r)
uint n = latestNumber;
for (; n > startNumber; n--, h = m_server->m_chain->details(h).parent) {}
for (uint i = 0; h != parent && n > endNumber && i < count; ++i, --n, h = m_server->m_chain->details(h).parent)
for (uint i = 0; i < count; ++i, --n, h = m_server->m_chain->details(h).parent)
{
if (h == parent || n == endNumber)
{
cwarn << "BUG! Couldn't create the reply for GetChain!";
return true;
}
clogS(NetAllDetail) << " " << dec << i << " " << h;
s.appendRaw(m_server->m_chain->block(h));
}
@ -443,16 +465,38 @@ void PeerSession::sealAndSend(RLPStream& _s)
sendDestroy(b);
}
bool PeerSession::checkPacket(bytesConstRef _msg)
{
if (_msg.size() < 8)
return false;
if (!(_msg[0] == 0x22 && _msg[1] == 0x40 && _msg[2] == 0x08 && _msg[3] == 0x91))
return false;
uint32_t len = ((_msg[4] * 256 + _msg[5]) * 256 + _msg[6]) * 256 + _msg[7];
if (_msg.size() != len + 8)
return false;
RLP r(_msg.cropped(8));
if (r.actualSize() != len)
return false;
return true;
}
void PeerSession::sendDestroy(bytes& _msg)
{
clogS(NetLeft) << RLP(bytesConstRef(&_msg).cropped(8));
std::shared_ptr<bytes> buffer = std::make_shared<bytes>();
swap(*buffer, _msg);
assert((*buffer)[0] == 0x22);
if (!checkPacket(bytesConstRef(&*buffer)))
{
cwarn << "INVALID PACKET CONSTRUCTED!";
}
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
{
if (ec)
{
cwarn << "Error sending: " << ec.message();
dropped();
}
// cbug << length << " bytes written (EC: " << ec << ")";
});
}
@ -461,11 +505,17 @@ void PeerSession::send(bytesConstRef _msg)
{
clogS(NetLeft) << RLP(_msg.cropped(8));
std::shared_ptr<bytes> buffer = std::make_shared<bytes>(_msg.toBytes());
assert((*buffer)[0] == 0x22);
if (!checkPacket(_msg))
{
cwarn << "INVALID PACKET CONSTRUCTED!";
}
ba::async_write(m_socket, ba::buffer(*buffer), [=](boost::system::error_code ec, std::size_t length)
{
if (ec)
{
cwarn << "Error sending: " << ec.message();
dropped();
}
// cbug << length << " bytes written (EC: " << ec << ")";
});
}
@ -487,26 +537,19 @@ void PeerSession::dropped()
void PeerSession::disconnect(int _reason)
{
clogS(NetNote) << "Disconnecting (reason:" << reasonOf(_reason) << ")";
if (m_socket.is_open())
{
if (m_disconnect == chrono::steady_clock::time_point::max())
{
RLPStream s;
prep(s);
s.appendList(1) << DisconnectPacket << _reason;
s.appendList(2) << DisconnectPacket << _reason;
sealAndSend(s);
m_disconnect = chrono::steady_clock::now();
}
else
{
if (m_socket.is_open())
try {
clogS(NetNote) << "Closing " << m_socket.remote_endpoint();
} catch (...){}
else
clogS(NetNote) << "Remote closed on" << m_socket.native_handle();
m_socket.close();
}
dropped();
}
}
@ -514,7 +557,7 @@ void PeerSession::start()
{
RLPStream s;
prep(s);
s.appendList(m_server->m_public.port() ? 6 : 5) << HelloPacket << (uint)c_protocolVersion << (uint)m_server->m_requiredNetworkId << m_server->m_clientVersion << (m_server->m_mode == NodeMode::Full ? 0x07 : m_server->m_mode == NodeMode::PeerServer ? 0x01 : 0) << m_server->m_public.port() << m_server->m_key.pub();
s.appendList(7) << HelloPacket << (uint)c_protocolVersion << (uint)m_server->m_requiredNetworkId << m_server->m_clientVersion << (m_server->m_mode == NodeMode::Full ? 0x07 : m_server->m_mode == NodeMode::PeerServer ? 0x01 : 0) << m_server->m_public.port() << m_server->m_key.pub();
sealAndSend(s);
ping();
@ -528,7 +571,10 @@ void PeerSession::doRead()
m_socket.async_read_some(boost::asio::buffer(m_data), [this, self](boost::system::error_code ec, std::size_t length)
{
if (ec)
{
cwarn << "Error reading: " << ec.message();
dropped();
}
else
{
try
@ -546,17 +592,31 @@ void PeerSession::doRead()
else
{
uint32_t len = fromBigEndian<uint32_t>(bytesConstRef(m_incoming.data() + 4, 4));
if (m_incoming.size() - 8 < len)
uint32_t tlen = len + 8;
if (m_incoming.size() < tlen)
break;
// enough has come in.
// cerr << "Received " << len << ": " << asHex(bytesConstRef(m_incoming.data() + 8, len)) << endl;
RLP r(bytesConstRef(m_incoming.data() + 8, len));
if (!interpret(r))
// error
break;
memmove(m_incoming.data(), m_incoming.data() + len + 8, m_incoming.size() - (len + 8));
m_incoming.resize(m_incoming.size() - (len + 8));
auto data = bytesConstRef(m_incoming.data(), tlen);
if (!checkPacket(data))
{
cerr << "Received " << len << ": " << asHex(bytesConstRef(m_incoming.data() + 8, len)) << endl;
cwarn << "INVALID MESSAGE RECEIVED";
disconnect(BadProtocol);
}
else
{
RLP r(data.cropped(8));
if (!interpret(r))
{
// error
dropped();
return;
}
}
memmove(m_incoming.data(), m_incoming.data() + tlen, m_incoming.size() - tlen);
m_incoming.resize(m_incoming.size() - tlen);
}
}
doRead();
@ -765,12 +825,25 @@ void PeerServer::ensureAccepting()
}
m_accepting = false;
if (m_mode == NodeMode::PeerServer || m_peers.size() < m_idealPeerCount)
if (m_mode == NodeMode::PeerServer || m_peers.size() < m_idealPeerCount * 2)
ensureAccepting();
});
}
}
void PeerServer::connect(std::string const& _addr, uint _port) noexcept
{
try
{
connect(bi::tcp::endpoint(bi::address::from_string(_addr), _port));
}
catch (exception const& e)
{
// Couldn't connect
clog(NetNote) << "Bad host " << _addr << " (" << e.what() << ")";
}
}
void PeerServer::connect(bi::tcp::endpoint const& _ep)
{
clog(NetNote) << "Attempting connection to " << _ep;
@ -780,6 +853,15 @@ void PeerServer::connect(bi::tcp::endpoint const& _ep)
if (ec)
{
clog(NetNote) << "Connection refused to " << _ep << " (" << ec.message() << ")";
for (auto i = m_incomingPeers.begin(); i != m_incomingPeers.end(); ++i)
if (i->second.first == _ep && i->second.second < 3)
{
m_freePeers.push_back(i->first);
goto OK;
}
// for-else
clog(NetNote) << "Giving up.";
OK:;
}
else
{
@ -791,17 +873,10 @@ void PeerServer::connect(bi::tcp::endpoint const& _ep)
});
}
bool PeerServer::process(BlockChain& _bc)
bool PeerServer::sync()
{
bool ret = false;
m_ioService.poll();
auto n = chrono::steady_clock::now();
bool fullProcess = (n > m_lastFullProcess + chrono::seconds(1));
if (fullProcess)
m_lastFullProcess = n;
if (fullProcess)
if (isInitialised())
for (auto i = m_peers.begin(); i != m_peers.end();)
{
auto p = i->second.lock();
@ -817,10 +892,8 @@ bool PeerServer::process(BlockChain& _bc)
return ret;
}
bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
bool PeerServer::ensureInitialised(BlockChain& _bc, TransactionQueue& _tq)
{
bool ret = false;
if (m_latestBlockSent == h256())
{
// First time - just initialise.
@ -830,14 +903,16 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
for (auto const& i: _tq.transactions())
m_transactionsSent.insert(i.first);
m_lastPeersRequest = chrono::steady_clock::time_point::min();
m_lastFullProcess = chrono::steady_clock::time_point::min();
ret = true;
return true;
}
return false;
}
auto n = chrono::steady_clock::now();
bool fullProcess = (n > m_lastFullProcess + chrono::seconds(1));
bool PeerServer::sync(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
{
bool ret = ensureInitialised(_bc, _tq);
if (process(_bc))
if (sync())
ret = true;
if (m_mode == NodeMode::Full)
@ -850,118 +925,118 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
m_incomingTransactions.clear();
// Send any new transactions.
if (fullProcess)
for (auto j: m_peers)
if (auto p = j.second.lock())
{
bytes b;
uint n = 0;
for (auto const& i: _tq.transactions())
if ((!m_transactionsSent.count(i.first) && !p->m_knownTransactions.count(i.first)) || p->m_requireTransactions)
{
b += i.second;
++n;
m_transactionsSent.insert(i.first);
}
if (n)
{
RLPStream ts;
PeerSession::prep(ts);
ts.appendList(n + 1) << TransactionsPacket;
ts.appendRaw(b, n).swapOut(b);
seal(b);
p->send(&b);
}
p->m_knownTransactions.clear();
p->m_requireTransactions = false;
}
// Send any new blocks.
auto h = _bc.currentHash();
if (h != m_latestBlockSent)
{
// TODO: find where they diverge and send complete new branch.
RLPStream ts;
PeerSession::prep(ts);
ts.appendList(2) << BlocksPacket;
bytes b;
ts.appendRaw(_bc.block(_bc.currentHash())).swapOut(b);
seal(b);
for (auto j: m_peers)
if (auto p = j.second.lock())
{
bytes b;
uint n = 0;
for (auto const& i: _tq.transactions())
if ((!m_transactionsSent.count(i.first) && !p->m_knownTransactions.count(i.first)) || p->m_requireTransactions)
{
b += i.second;
++n;
m_transactionsSent.insert(i.first);
}
if (n)
{
RLPStream ts;
PeerSession::prep(ts);
ts.appendList(n + 1) << TransactionsPacket;
ts.appendRaw(b, n).swapOut(b);
seal(b);
if (!p->m_knownBlocks.count(_bc.currentHash()))
p->send(&b);
}
p->m_knownTransactions.clear();
p->m_requireTransactions = false;
p->m_knownBlocks.clear();
}
}
m_latestBlockSent = h;
// Send any new blocks.
auto h = _bc.currentHash();
if (h != m_latestBlockSent)
{
// TODO: find where they diverge and send complete new branch.
RLPStream ts;
PeerSession::prep(ts);
ts.appendList(2) << BlocksPacket;
bytes b;
ts.appendRaw(_bc.block(_bc.currentHash())).swapOut(b);
seal(b);
for (auto j: m_peers)
if (auto p = j.second.lock())
for (int accepted = 1, n = 0; accepted; ++n)
{
accepted = 0;
if (m_incomingBlocks.size())
for (auto it = prev(m_incomingBlocks.end());; --it)
{
try
{
if (!p->m_knownBlocks.count(_bc.currentHash()))
p->send(&b);
p->m_knownBlocks.clear();
_bc.import(*it, _o);
it = m_incomingBlocks.erase(it);
++accepted;
ret = true;
}
}
m_latestBlockSent = h;
for (int accepted = 1, n = 0; accepted; ++n)
{
accepted = 0;
if (m_incomingBlocks.size())
for (auto it = prev(m_incomingBlocks.end());; --it)
catch (UnknownParent)
{
try
{
_bc.import(*it, _o);
it = m_incomingBlocks.erase(it);
++accepted;
ret = true;
}
catch (UnknownParent)
{
// Don't (yet) know its parent. Leave it for later.
m_unknownParentBlocks.push_back(*it);
it = m_incomingBlocks.erase(it);
}
catch (...)
{
// Some other error - erase it.
it = m_incomingBlocks.erase(it);
}
if (it == m_incomingBlocks.begin())
break;
// Don't (yet) know its parent. Leave it for later.
m_unknownParentBlocks.push_back(*it);
it = m_incomingBlocks.erase(it);
}
if (!n && accepted)
{
for (auto i: m_unknownParentBlocks)
m_incomingBlocks.push_back(i);
m_unknownParentBlocks.clear();
catch (...)
{
// Some other error - erase it.
it = m_incomingBlocks.erase(it);
}
if (it == m_incomingBlocks.begin())
break;
}
if (!n && accepted)
{
for (auto i: m_unknownParentBlocks)
m_incomingBlocks.push_back(i);
m_unknownParentBlocks.clear();
}
}
// Connect to additional peers
while (m_peers.size() < m_idealPeerCount)
// Connect to additional peers
while (m_peers.size() < m_idealPeerCount)
{
if (m_freePeers.empty())
{
if (m_incomingPeers.empty())
if (chrono::steady_clock::now() > m_lastPeersRequest + chrono::seconds(10))
{
if (chrono::steady_clock::now() > m_lastPeersRequest + chrono::seconds(10))
{
RLPStream s;
bytes b;
(PeerSession::prep(s).appendList(1) << GetPeersPacket).swapOut(b);
seal(b);
for (auto const& i: m_peers)
if (auto p = i.second.lock())
if (p->isOpen())
p->send(&b);
m_lastPeersRequest = chrono::steady_clock::now();
}
RLPStream s;
bytes b;
(PeerSession::prep(s).appendList(1) << GetPeersPacket).swapOut(b);
seal(b);
for (auto const& i: m_peers)
if (auto p = i.second.lock())
if (p->isOpen())
p->send(&b);
m_lastPeersRequest = chrono::steady_clock::now();
}
if (!m_accepting)
ensureAccepting();
if (!m_accepting)
ensureAccepting();
break;
}
connect(m_incomingPeers.begin()->second);
m_incomingPeers.erase(m_incomingPeers.begin());
break;
}
auto x = time(0) % m_freePeers.size();
m_incomingPeers[m_freePeers[x]].second++;
connect(m_incomingPeers[m_freePeers[x]].first);
m_freePeers.erase(m_freePeers.begin() + x);
}
}
@ -969,29 +1044,26 @@ bool PeerServer::process(BlockChain& _bc, TransactionQueue& _tq, Overlay& _o)
// 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).
if (fullProcess)
{
// We'll keep at most twice as many as is ideal, halfing what counts as "too young to kill" until we get there.
for (uint old = 15000; m_peers.size() > m_idealPeerCount * 2 && old > 100; old /= 2)
while (m_peers.size() > m_idealPeerCount)
{
// look for worst peer to kick off
// first work out how many are old enough to kick off.
shared_ptr<PeerSession> worst;
unsigned agedPeers = 0;
for (auto i: m_peers)
if (auto p = i.second.lock())
if ((m_mode != NodeMode::PeerServer || p->m_caps != 0x01) && chrono::steady_clock::now() > p->m_connect + chrono::milliseconds(old)) // don't throw off new peers; peer-servers should never kick off other peer-servers.
{
++agedPeers;
if ((!worst || p->m_rating < worst->m_rating || (p->m_rating == worst->m_rating && p->m_connect > worst->m_connect))) // kill older ones
worst = p;
}
if (!worst || agedPeers <= m_idealPeerCount)
break;
worst->disconnect(TooManyPeers);
}
}
// We'll keep at most twice as many as is ideal, halfing what counts as "too young to kill" until we get there.
for (uint old = 15000; m_peers.size() > m_idealPeerCount * 2 && old > 100; old /= 2)
while (m_peers.size() > m_idealPeerCount)
{
// look for worst peer to kick off
// first work out how many are old enough to kick off.
shared_ptr<PeerSession> worst;
unsigned agedPeers = 0;
for (auto i: m_peers)
if (auto p = i.second.lock())
if ((m_mode != NodeMode::PeerServer || p->m_caps != 0x01) && chrono::steady_clock::now() > p->m_connect + chrono::milliseconds(old)) // don't throw off new peers; peer-servers should never kick off other peer-servers.
{
++agedPeers;
if ((!worst || p->m_rating < worst->m_rating || (p->m_rating == worst->m_rating && p->m_connect > worst->m_connect))) // kill older ones
worst = p;
}
if (!worst || agedPeers <= m_idealPeerCount)
break;
worst->disconnect(TooManyPeers);
}
return ret;
}
@ -1033,6 +1105,11 @@ void PeerServer::restorePeers(bytesConstRef _b)
{
for (auto i: RLP(_b))
{
m_incomingPeers.insert(make_pair((Public)i[2], bi::tcp::endpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<short>())));
auto k = (Public)i[2];
if (!m_incomingPeers.count(k))
{
m_incomingPeers.insert(make_pair(k, make_pair(bi::tcp::endpoint(bi::address_v4(i[0].toArray<byte, 4>()), i[1].toInt<short>()), 0)));
m_freePeers.push_back(k);
}
}
}

27
libethereum/PeerNetwork.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file PeerNetwork.h
* @author Gav Wood <i@gavwood.com>
@ -109,6 +109,9 @@ private:
void doWrite(std::size_t length);
bool interpret(RLP const& _r);
/// @returns true iff the _msg forms a valid message for sending or receiving on the network.
static bool checkPacket(bytesConstRef _msg);
static RLPStream& prep(RLPStream& _s);
void sealAndSend(RLPStream& _s);
void sendDestroy(bytes& _msg);
@ -158,14 +161,17 @@ public:
~PeerServer();
/// Connect to a peer explicitly.
void connect(std::string const& _addr, uint _port = 30303) { connect(bi::tcp::endpoint(bi::address::from_string(_addr), _port)); }
void connect(std::string const& _addr, uint _port = 30303) noexcept;
void connect(bi::tcp::endpoint const& _ep);
/// Sync with the BlockChain. It might contain one of our mined blocks, we might have new candidates from the network.
bool sync(BlockChain& _bc, TransactionQueue&, Overlay& _o);
bool sync();
/// 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.
bool process(BlockChain& _bc, TransactionQueue&, Overlay& _o);
bool process(BlockChain& _bc);
/// This won't touch alter the blockchain.
void process() { if (isInitialised()) m_ioService.poll(); }
/// Set ideal number of peers.
void setIdealPeerCount(unsigned _n) { m_idealPeerCount = _n; }
@ -192,6 +198,12 @@ private:
void populateAddresses();
void determinePublic(std::string const& _publicAddress, bool _upnp);
void ensureAccepting();
/// Check to see if the network peer-state initialisation has happened.
bool isInitialised() const { return m_latestBlockSent; }
/// Initialises the network peer-state, doing the stuff that needs to be once-only. @returns true if it really was first.
bool ensureInitialised(BlockChain& _bc, TransactionQueue& _tq);
std::map<Public, bi::tcp::endpoint> potentialPeers();
std::string m_clientVersion;
@ -214,7 +226,8 @@ private:
std::vector<bytes> m_incomingTransactions;
std::vector<bytes> m_incomingBlocks;
std::vector<bytes> m_unknownParentBlocks;
std::map<Public, bi::tcp::endpoint> m_incomingPeers;
std::vector<Public> m_freePeers;
std::map<Public, std::pair<bi::tcp::endpoint, unsigned>> m_incomingPeers;
h256 m_latestBlockSent;
std::set<h256> m_transactionsSent;
@ -222,8 +235,6 @@ private:
std::chrono::steady_clock::time_point m_lastPeersRequest;
unsigned m_idealPeerCount = 5;
std::chrono::steady_clock::time_point m_lastFullProcess;
std::vector<bi::address_v4> m_addresses;
std::vector<bi::address_v4> m_peerAddresses;

4
libethereum/RLP.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file RLP.cpp
* @author Gav Wood <i@gavwood.com>

12
libethereum/RLP.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file RLP.h
* @author Gav Wood <i@gavwood.com>
@ -229,14 +229,14 @@ public:
/// @returns the data payload. Valid for all types.
bytesConstRef payload() const { return isSingleByte() ? m_data.cropped(0, 1) : m_data.cropped(1 + lengthSize()); }
/// @returns the theoretical size of this item.
/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.
uint actualSize() const;
private:
/// Single-byte data payload.
bool isSingleByte() const { return !isNull() && m_data[0] < c_rlpDataImmLenStart; }
/// @returns the theoretical size of this item; if it's a list, will require a deep traversal which could take a while.
/// @note Under normal circumstances, is equivalent to m_data.size() - use that unless you know it won't work.
uint actualSize() const;
/// @returns the bytes used to encode the length of the data. Valid for all types.
uint lengthSize() const { if (isData() && m_data[0] > c_rlpDataIndLenZero) return m_data[0] - c_rlpDataIndLenZero; if (isList() && m_data[0] > c_rlpListIndLenZero) return m_data[0] - c_rlpListIndLenZero; return 0; }

27
libethereum/State.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file State.cpp
* @author Gav Wood <i@gavwood.com>
@ -274,6 +274,29 @@ void State::resetCurrent()
m_state.setRoot(m_currentBlock.stateRoot);
}
bool State::cull(TransactionQueue& _tq) const
{
bool ret = false;
auto ts = _tq.transactions();
for (auto const& i: ts)
if (!m_transactions.count(i.first))
try
{
Transaction t(i.second);
if (t.nonce <= transactionsFrom(t.sender()))
{
_tq.drop(i.first);
ret = true;
}
}
catch (...)
{
_tq.drop(i.first);
ret = true;
}
return ret;
}
bool State::sync(TransactionQueue& _tq)
{
// TRANSACTIONS

9
libethereum/State.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file State.h
* @author Gav Wood <i@gavwood.com>
@ -119,6 +119,8 @@ public:
/// Sync our transactions, killing those from the queue that we have and assimilating those that we don't.
bool sync(TransactionQueue& _tq);
/// Like sync but only operate on _tq, killing the invalid/old ones.
bool cull(TransactionQueue& _tq) const;
/// Execute a given transaction.
void execute(bytes const& _rlp) { return execute(&_rlp); }
@ -158,6 +160,9 @@ public:
/// The hash of the root of our state tree.
h256 rootHash() const { return m_state.root(); }
/// Get the list of pending transactions.
std::map<h256, Transaction> const& pending() const { return m_transactions; }
/// Finalise the block, applying the earned rewards.
void applyRewards(Addresses const& _uncleAddresses);

4
libethereum/Transaction.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Transaction.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/Transaction.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file Transaction.h
* @author Gav Wood <i@gavwood.com>

4
libethereum/TransactionQueue.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TransactionQueue.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/TransactionQueue.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TransactionQueue.h
* @author Gav Wood <i@gavwood.com>

4
libethereum/TrieCommon.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TrieCommon.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/TrieCommon.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TrieCommon.h
* @author Gav Wood <i@gavwood.com>

4
libethereum/TrieDB.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TrieDB.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/TrieDB.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TrieDB.h
* @author Gav Wood <i@gavwood.com>

4
libethereum/TrieHash.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TrieHash.cpp
* @author Gav Wood <i@gavwood.com>

4
libethereum/TrieHash.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file TrieHash.h
* @author Gav Wood <i@gavwood.com>

4
libethereum/UPnP.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file UPnP.cpp
* @authors:

4
libethereum/UPnP.h

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file UPnP.h
* @authors:

4
test/crypto.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file crypto.cpp
* @author Gav Wood <i@gavwood.com>

4
test/dagger.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file dagger.cpp
* @author Gav Wood <i@gavwood.com>

4
test/hexPrefix.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
* @author Gav Wood <i@gavwood.com>

4
test/main.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file main.cpp
* @author Gav Wood <i@gavwood.com>

6
test/peer.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file peer.cpp
* @author Gav Wood <i@gavwood.com>
@ -56,7 +56,7 @@ int peerTest(int argc, char** argv)
for (int i = 0; ; ++i)
{
this_thread::sleep_for(chrono::milliseconds(100));
pn.process(ch);
pn.sync();
if (!(i % 10))
pn.pingAll();
}

4
test/rlp.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file rlp.cpp
* @author Gav Wood <i@gavwood.com>

4
test/state.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file state.cpp
* @author Gav Wood <i@gavwood.com>

4
test/trie.cpp

@ -6,13 +6,13 @@
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Foobar is distributed in the hope that it will be useful,
cpp-ethereum is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar. If not, see <http://www.gnu.org/licenses/>.
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file trie.cpp
* @author Gav Wood <i@gavwood.com>

Loading…
Cancel
Save