Browse Source

Vaguely working single-instance client.

cl-refactor
Gav Wood 11 years ago
parent
commit
ce10e98a08
  1. 48
      alephzero/Main.cpp
  2. 2
      alephzero/Main.h
  3. 9
      alephzero/Main.ui
  4. 2
      libethereum/BlockChain.h
  5. 17
      libethereum/Client.cpp
  6. 4
      libethereum/Client.h
  7. 2
      libethereum/Common.cpp
  8. 32
      libethereum/State.cpp
  9. 9
      libethereum/State.h

48
alephzero/Main.cpp

@ -51,6 +51,8 @@ void Main::readSettings()
}
m_client.setAddress(m_myKey.address());
writeSettings();
/*for (uint i = 0; !s.value(QString("peer%1").arg(i)).isNull(); ++i)
{
s.value(QString("peer%1").arg(i)).toString();
@ -59,6 +61,7 @@ void Main::readSettings()
void Main::refresh()
{
m_client.lock();
ui->balance->setText(QString::fromStdString(toString(m_client.state().balance(m_myKey.address()))) + " wei");
ui->peerCount->setText(QString::fromStdString(toString(m_client.peerCount())) + " peer(s)");
ui->address->setText(QString::fromStdString(asHex(m_client.state().address().asArray())));
@ -68,7 +71,42 @@ void Main::refresh()
auto d = m_client.blockChain().details();
auto diff = BlockInfo(m_client.blockChain().block()).difficulty;
ui->blockChain->setText(QString("%1 blocks @ (%3) - %2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)));
ui->blockChain->setText(QString("#%1 @%3 T%2").arg(d.number).arg(toLog2(d.totalDifficulty)).arg(toLog2(diff)));
auto acs = m_client.state().addresses();
ui->accounts->clear();
for (auto i: acs)
ui->accounts->addItem(QString("%1 wei @ %2").arg(toString(i.second).c_str()).arg(asHex(i.first.asArray()).c_str()));
ui->transactionQueue->clear();
for (pair<h256, bytes> const& i: m_client.transactionQueue().transactions())
{
Transaction t(i.second);
ui->transactionQueue->addItem(QString("%1 wei (%2 fee) @ %3 <- %4")
.arg(toString(t.value).c_str())
.arg(toString(t.fee).c_str())
.arg(asHex(t.receiveAddress.asArray()).c_str())
.arg(asHex(t.sender().asArray()).c_str()) );
}
ui->transactions->clear();
auto const& bc = m_client.blockChain();
for (auto h = bc.currentHash(); h != bc.genesisHash(); h = bc.details(h).parent)
{
auto d = bc.details(h);
ui->transactions->addItem(QString("# %1 ==== %2").arg(d.number).arg(asHex(h.asArray()).c_str()));
for (auto const& i: RLP(bc.block(h))[1])
{
Transaction t(i.data());
ui->transactions->addItem(QString("%1 wei (%2 fee) @ %3 <- %4")
.arg(toString(t.value).c_str())
.arg(toString(t.fee).c_str())
.arg(asHex(t.receiveAddress.asArray()).c_str())
.arg(asHex(t.sender().asArray()).c_str()) );
}
}
m_client.unlock();
}
void Main::on_net_toggled()
@ -81,7 +119,7 @@ void Main::on_net_toggled()
void Main::on_connect_clicked()
{
QString s = QInputDialog::getText(this, "Enter first peer", "Enter a peer to which a connection may be made", QLineEdit::Normal, "127.0.0.1:30303");
QString s = QInputDialog::getText(this, "Connect to a Network Peer", "Enter a peer to which a connection may be made:", QLineEdit::Normal, "127.0.0.1:30303");
string host = s.section(":", 0, 0).toStdString();
short port = s.section(":", 1).toInt();
m_client.connect(host, port);
@ -97,7 +135,7 @@ void Main::on_mine_toggled()
void Main::on_send_clicked()
{
Secret s = Secret(fromUserHex(ui->address->text().toStdString()));
Secret s = m_myKey.secret();
Address r = Address(fromUserHex(ui->destination->text().toStdString()));
m_client.transact(s, r, ui->value->value(), ui->fee->value());
refresh();
@ -106,6 +144,6 @@ void Main::on_send_clicked()
void Main::on_create_clicked()
{
KeyPair p = KeyPair::create();
QString s = QString::fromStdString("New key:\n" + asHex(p.secret().asArray()) + "\nAddress: " + asHex(p.address().asArray()));
QMessageBox::information(this, "New Key", s, QMessageBox::Ok);
QString s = QString::fromStdString("The new secret key is:\n" + asHex(p.secret().asArray()) + "\n\nAddress:\n" + asHex(p.address().asArray()));
QMessageBox::information(this, "Create Key", s, QMessageBox::Ok);
}

2
alephzero/Main.h

@ -3,6 +3,7 @@
#include <QAbstractListModel>
#include <QDialog>
#include <QMutex>
#include <libethereum/Client.h>
namespace Ui {
@ -37,6 +38,7 @@ private:
eth::KeyPair m_myKey;
std::vector<bi::tcp::endpoint> m_peers;
QMutex m_guiLock;
QTimer* m_refresh;
};

9
alephzero/Main.ui

@ -11,7 +11,7 @@
</rect>
</property>
<property name="windowTitle">
<string>Main</string>
<string>AlephZero Etherium Client</string>
</property>
<property name="sizeGripEnabled">
<bool>true</bool>
@ -158,17 +158,14 @@
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QTextEdit" name="transactions">
<property name="readOnly">
<bool>true</bool>
</property>
</widget>
<widget class="QListWidget" name="peers"/>
<widget class="QListWidget" name="accounts">
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
</widget>
<widget class="QListWidget" name="transactionQueue"/>
<widget class="QListWidget" name="transactions"/>
</widget>
</item>
<item>

2
libethereum/BlockChain.h

@ -100,6 +100,8 @@ public:
Address coinbaseAddress(h256 _hash) const;
Address coinbaseAddress() const { return coinbaseAddress(currentHash()); }
h256 genesisHash() const { return m_genesisHash; }
private:
/// Get fully populated from disk DB.
mutable std::map<h256, BlockDetails> m_details;

17
libethereum/Client.cpp

@ -83,6 +83,7 @@ void Client::stopMining()
void Client::transact(Secret _secret, Address _dest, u256 _amount, u256 _fee, u256s _data)
{
m_lock.lock();
Transaction t;
t.nonce = m_s.transactionsFrom(toAddress(_secret));
t.receiveAddress = _dest;
@ -91,10 +92,12 @@ void Client::transact(Secret _secret, Address _dest, u256 _amount, u256 _fee, u2
t.data = _data;
t.sign(_secret);
m_tq.attemptImport(t.rlp());
m_lock.unlock();
}
void Client::work()
{
m_lock.lock();
// 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.
@ -110,9 +113,11 @@ void Client::work()
m_s.sync(m_bc); // Resynchronise state with block chain & trans
m_s.sync(m_tq);
m_lock.unlock();
if (m_doMine)
{
// Mine for a while.
m_s.commitToMine(m_bc);
MineInfo mineInfo = m_s.mine(100);
m_mineProgress.best = max(m_mineProgress.best, mineInfo.best);
m_mineProgress.current = mineInfo.best;
@ -121,10 +126,22 @@ void Client::work()
if (mineInfo.completed())
{
// Import block.
m_lock.lock();
m_bc.attemptImport(m_s.blockData(), m_stateDB);
m_mineProgress.best = 0;
m_lock.unlock();
}
}
else
usleep(100000);
}
void Client::lock()
{
m_lock.lock();
}
void Client::unlock()
{
m_lock.unlock();
}

4
libethereum/Client.h

@ -48,6 +48,9 @@ public:
void transact(Secret _secret, Address _dest, u256 _amount, u256 _fee, u256s _data = u256s());
void lock();
void unlock();
State const& state() const { return m_s; }
BlockChain const& blockChain() const { return m_bc; }
TransactionQueue const& transactionQueue() const { return m_tq; }
@ -74,6 +77,7 @@ private:
State m_s; ///< The present state of the client.
PeerServer* m_net = nullptr; ///< Should run in background and send us events when blocks found and allow us to send blocks as required.
std::thread* m_work; ///< The work thread.
std::mutex m_lock;
enum { Active = 0, Deleting, Deleted } m_workState = Active;
bool m_doMine = false; ///< Are we supposed to be mining?
MineProgress m_mineProgress;

2
libethereum/Common.cpp

@ -175,7 +175,7 @@ KeyPair KeyPair::create()
static std::mt19937_64 s_eng(time(0));
std::uniform_int_distribution<byte> d(0, 255);
KeyPair ret;
for (uint i = 0; i < 20; ++i)
for (uint i = 0; i < 32; ++i)
ret.m_secret[i] = d(s_eng);
ret.m_address = toAddress(ret.m_secret);
return ret;

32
libethereum/State.cpp

@ -157,10 +157,6 @@ void State::sync(BlockChain const& _bc, h256 _block)
exit(1);
}
// TODO: why are the hashes different when the essentials are the same?
// cout << bi << endl;
// cout << m_currentBlock << endl;
if (bi == m_currentBlock)
{
// We mined the last block.
@ -199,6 +195,18 @@ void State::sync(BlockChain const& _bc, h256 _block)
}
}
map<Address, u256> State::addresses() const
{
map<Address, u256> ret;
for (auto i: m_cache)
if (i.second.type() != AddressType::Dead)
ret[i.first] = i.second.balance();
for (auto const& i: m_state)
if (m_cache.find(i.first) == m_cache.end())
ret[i.first] = RLP(i.second)[0].toInt<u256>();
return ret;
}
void State::resetCurrent()
{
m_transactions.clear();
@ -221,8 +229,7 @@ void State::sync(TransactionQueue& _tq)
// don't have it yet! Execute it now.
try
{
Transaction t(i.second);
execute(t, t.sender());
execute(i.second);
}
catch (InvalidNonce in)
{
@ -291,11 +298,11 @@ u256 State::playback(bytesConstRef _block, BlockInfo const& _grandParent, bool _
// Commit all cached state changes to the state trie.
commit();
// cout << m_state << endl << TrieDB<Address, Overlay>(&m_db, m_currentBlock.stateRoot);
// Hash the state trie and check against the state_root hash in m_currentBlock.
if (m_currentBlock.stateRoot != rootHash())
{
cout << "*** BAD STATE ROOT!" << endl;
cout << m_state << endl << TrieDB<Address, Overlay>(&m_db, m_currentBlock.stateRoot);
// Rollback the trie.
m_db.rollback();
throw InvalidStateRoot();
@ -322,6 +329,9 @@ u256 State::playback(bytesConstRef _block, BlockInfo const& _grandParent, bool _
// (i.e. all the transactions we executed).
void State::commitToMine(BlockChain const& _bc)
{
if (m_currentBlock.sha3Transactions != h256() || m_currentBlock.sha3Uncles != h256())
return;
RLPStream uncles;
Addresses uncleAddresses;
@ -483,7 +493,7 @@ bool State::execute(bytesConstRef _rlp)
try
{
Transaction t(_rlp);
execute(t, t.sender());
executeBare(t, t.sender());
// Add to the user-originated transactions that we've executed.
// NOTE: Here, contract-originated transactions will not get added to the transaction list.
@ -510,7 +520,7 @@ void State::applyRewards(Addresses const& _uncleAddresses)
addBalance(m_currentBlock.coinbaseAddress, r);
}
void State::execute(Transaction const& _t, Address _sender)
void State::executeBare(Transaction const& _t, Address _sender)
{
// Entry point for a contract-originated transaction.
@ -1050,7 +1060,7 @@ void State::execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _
}
t.nonce = transactionsFrom(_myAddress);
execute(t, _myAddress);
executeBare(t, _myAddress);
break;
}

9
libethereum/State.h

@ -59,6 +59,9 @@ public:
static Overlay openDB(std::string _path, bool _killExisting = false);
static Overlay openDB(bool _killExisting = false) { return openDB(std::string(), _killExisting); }
/// @returns the set containing all addresses currently in use in Ethereum.
std::map<Address, u256> addresses() const;
/// Cancels transactions and rolls back the state to the end of the previous block.
/// @warning This will only work for on any transactions after you called the last commitToMine().
/// It's one or the other.
@ -68,7 +71,9 @@ public:
/// Commits all transactions into the trie, compiles uncles and transactions list, applies all
/// rewards and populates the current block header with the appropriate hashes.
/// The only thing left to do after this is to actually mine().
/// @warning Only call this once!
///
/// This may be called multiple times and without issue, however, until the current state is cleared,
/// calls after the first are ignored.
void commitToMine(BlockChain const& _bc);
/// Attempt to find valid nonce for block that this state represents.
@ -166,7 +171,7 @@ private:
/// Execute a decoded transaction object, given a sender.
/// This will append @a _t to the transaction list and change the state accordingly.
void execute(Transaction const& _t, Address _sender);
void executeBare(Transaction const& _t, Address _sender);
/// Execute a contract transaction.
void execute(Address _myAddress, Address _txSender, u256 _txValue, u256 _txFee, u256s const& _txData, u256* o_totalFee);

Loading…
Cancel
Save