Browse Source

Avoid recursion in TransactionQueue.

cl-refactor
Gav Wood 11 years ago
parent
commit
34ab7e8231
  1. 24
      libethereum/BlockQueue.cpp
  2. 37
      libethereum/Transaction.cpp
  3. 11
      libethereum/Transaction.h
  4. 12
      libethereum/TransactionQueue.cpp

24
libethereum/BlockQueue.cpp

@ -85,18 +85,20 @@ bool BlockQueue::import(bytesConstRef _block, BlockChain const& _bc)
return true;
}
void BlockQueue::noteReadyWithoutWriteGuard(h256 _b)
void BlockQueue::noteReadyWithoutWriteGuard(h256 _good)
{
auto r = m_future.equal_range(_b);
h256s good;
for (auto it = r.first; it != r.second; ++it)
h256s goodQueue(1, _good);
while (goodQueue.size())
{
m_futureSet.erase(it->second.first);
m_ready.push_back(it->second.second);
m_readySet.erase(it->second.first);
good.push_back(it->second.first);
auto r = m_future.equal_range(goodQueue.back());
goodQueue.pop_back();
for (auto it = r.first; it != r.second; ++it)
{
m_futureSet.erase(it->second.first);
m_ready.push_back(it->second.second);
m_readySet.erase(it->second.first);
goodQueue.push_back(it->second.first);
}
m_future.erase(r.first, r.second);
}
m_future.erase(r.first, r.second);
for (auto g: good)
noteReadyWithoutWriteGuard(g);
}

37
libethereum/Transaction.cpp

@ -29,7 +29,7 @@ using namespace eth;
#define ETH_ADDRESS_DEBUG 0
Transaction::Transaction(bytesConstRef _rlpData)
Transaction::Transaction(bytesConstRef _rlpData, bool _checkSender)
{
int field = 0;
RLP rlp(_rlpData);
@ -42,6 +42,8 @@ Transaction::Transaction(bytesConstRef _rlpData)
value = rlp[field = 4].toInt<u256>();
data = rlp[field = 5].toBytes();
vrs = Signature{ rlp[field = 6].toInt<byte>(), rlp[field = 7].toInt<u256>(), rlp[field = 8].toInt<u256>() };
if (_checkSender)
m_sender = sender();
}
catch (RLPException const&)
{
@ -63,27 +65,30 @@ Address Transaction::safeSender() const noexcept
Address Transaction::sender() const
{
secp256k1_start();
if (!m_sender)
{
secp256k1_start();
h256 sig[2] = { vrs.r, vrs.s };
h256 msg = sha3(false);
h256 sig[2] = { vrs.r, vrs.s };
h256 msg = sha3(false);
byte pubkey[65];
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact(msg.data(), 32, sig[0].data(), pubkey, &pubkeylen, 0, (int)vrs.v - 27))
throw InvalidSignature();
byte pubkey[65];
int pubkeylen = 65;
if (!secp256k1_ecdsa_recover_compact(msg.data(), 32, sig[0].data(), pubkey, &pubkeylen, 0, (int)vrs.v - 27))
throw InvalidSignature();
// TODO: check right160 is correct and shouldn't be left160.
auto ret = right160(eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
// TODO: check right160 is correct and shouldn't be left160.
m_sender = right160(eth::sha3(bytesConstRef(&(pubkey[1]), 64)));
#if ETH_ADDRESS_DEBUG
cout << "---- RECOVER -------------------------------" << endl;
cout << "MSG: " << msg << endl;
cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(vrs.v - 27) << "+27" << endl;
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
cout << "ADR: " << ret << endl;
cout << "---- RECOVER -------------------------------" << endl;
cout << "MSG: " << msg << endl;
cout << "R S V: " << sig[0] << " " << sig[1] << " " << (int)(vrs.v - 27) << "+27" << endl;
cout << "PUB: " << toHex(bytesConstRef(&(pubkey[1]), 64)) << endl;
cout << "ADR: " << ret << endl;
#endif
return ret;
}
return m_sender;
}
void Transaction::sign(Secret _priv)

11
libethereum/Transaction.h

@ -38,8 +38,8 @@ struct Signature
struct Transaction
{
Transaction() {}
Transaction(bytesConstRef _rlp);
Transaction(bytes const& _rlp): Transaction(&_rlp) {}
Transaction(bytesConstRef _rlp, bool _checkSender = false);
Transaction(bytes const& _rlp, bool _checkSender = false): Transaction(&_rlp, _checkSender) {}
bool operator==(Transaction const& _c) const { return receiveAddress == _c.receiveAddress && value == _c.value && data == _c.data; }
bool operator!=(Transaction const& _c) const { return !operator==(_c); }
@ -55,8 +55,8 @@ struct Transaction
Signature vrs; ///< The signature of the transaction. Encodes the sender.
Address safeSender() const noexcept; ///< Like sender() but will never throw.
Address sender() const; ///< Determine the sender of the transaction from the signature (and hash).
void sign(Secret _priv); ///< Sign the transaction.
Address sender() const; ///< Determine the sender of the transaction from the signature (and hash).
void sign(Secret _priv); ///< Sign the transaction.
bool isCreation() const { return !receiveAddress; }
@ -67,6 +67,9 @@ struct Transaction
std::string rlpString(bool _sig = true) const { return asString(rlp(_sig)); }
h256 sha3(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha3(s.out()); }
bytes sha3Bytes(bool _sig = true) const { RLPStream s; fillStream(s, _sig); return eth::sha3Bytes(s.out()); }
private:
mutable Address m_sender;
};
using Transactions = std::vector<Transaction>;

12
libethereum/TransactionQueue.cpp

@ -27,22 +27,22 @@
using namespace std;
using namespace eth;
bool TransactionQueue::import(bytesConstRef _block)
bool TransactionQueue::import(bytesConstRef _transactionRLP)
{
// Check if we already know this transaction.
h256 h = sha3(_block);
h256 h = sha3(_transactionRLP);
if (m_known.count(h))
return false;
try
{
// Check validity of _block as a transaction. To do this we just deserialise and attempt to determine the sender. If it doesn't work, the signature is bad.
// Check validity of _transactionRLP as a transaction. To do this we just deserialise and attempt to determine the sender.
// If it doesn't work, the signature is bad.
// The transaction's nonce may yet be invalid (or, it could be "valid" but we may be missing a marginally older transaction).
Transaction t(_block);
auto s = t.sender();
Transaction t(_transactionRLP, true);
// If valid, append to blocks.
m_current[h] = _block.toBytes();
m_current[h] = _transactionRLP.toBytes();
}
catch (InvalidTransactionFormat const& _e)
{

Loading…
Cancel
Save