AccountHolder.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. /*
  2. This file is part of cpp-ethereum.
  3. cpp-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. cpp-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /** @file AccountHolder.cpp
  15. * @authors:
  16. * Christian R <c@ethdev.com>
  17. * Lefteris Karapetsas <lefteris@ethdev.com>
  18. * @date 2015
  19. */
  20. #include "AccountHolder.h"
  21. #include <random>
  22. #include <libdevcore/Guards.h>
  23. #include <libethereum/Client.h>
  24. #include <libethcore/KeyManager.h>
  25. using namespace std;
  26. using namespace dev;
  27. using namespace dev::eth;
  28. vector<TransactionSkeleton> g_emptyQueue;
  29. static std::mt19937 g_randomNumberGenerator(utcTime());
  30. static Mutex x_rngMutex;
  31. vector<Address> AccountHolder::allAccounts() const
  32. {
  33. vector<Address> accounts;
  34. accounts += realAccounts();
  35. for (auto const& pair: m_proxyAccounts)
  36. if (!isRealAccount(pair.first))
  37. accounts.push_back(pair.first);
  38. return accounts;
  39. }
  40. Address const& AccountHolder::defaultTransactAccount() const
  41. {
  42. auto accounts = realAccounts();
  43. if (accounts.empty())
  44. return ZeroAddress;
  45. Address const* bestMatch = &*accounts.begin();
  46. for (auto const& account: accounts)
  47. if (m_client()->balanceAt(account) > m_client()->balanceAt(*bestMatch))
  48. bestMatch = &account;
  49. return *bestMatch;
  50. }
  51. int AccountHolder::addProxyAccount(const Address& _account)
  52. {
  53. Guard g(x_rngMutex);
  54. int id = std::uniform_int_distribution<int>(1)(g_randomNumberGenerator);
  55. id = int(u256(FixedHash<32>(sha3(bytesConstRef((byte*)(&id), sizeof(int) / sizeof(byte))))));
  56. if (isProxyAccount(_account) || id == 0 || m_transactionQueues.count(id))
  57. return 0;
  58. m_proxyAccounts.insert(make_pair(_account, id));
  59. m_transactionQueues[id].first = _account;
  60. return id;
  61. }
  62. bool AccountHolder::removeProxyAccount(unsigned _id)
  63. {
  64. if (!m_transactionQueues.count(_id))
  65. return false;
  66. m_proxyAccounts.erase(m_transactionQueues[_id].first);
  67. m_transactionQueues.erase(_id);
  68. return true;
  69. }
  70. void AccountHolder::queueTransaction(TransactionSkeleton const& _transaction)
  71. {
  72. if (!m_proxyAccounts.count(_transaction.from))
  73. return;
  74. int id = m_proxyAccounts[_transaction.from];
  75. m_transactionQueues[id].second.push_back(_transaction);
  76. }
  77. vector<TransactionSkeleton> const& AccountHolder::queuedTransactions(int _id) const
  78. {
  79. if (!m_transactionQueues.count(_id))
  80. return g_emptyQueue;
  81. return m_transactionQueues.at(_id).second;
  82. }
  83. void AccountHolder::clearQueue(int _id)
  84. {
  85. if (m_transactionQueues.count(_id))
  86. m_transactionQueues.at(_id).second.clear();
  87. }
  88. AddressHash SimpleAccountHolder::realAccounts() const
  89. {
  90. return m_keyManager.accountsHash();
  91. }
  92. TransactionNotification SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
  93. {
  94. TransactionNotification ret;
  95. bool locked = true;
  96. if (m_unlockedAccounts.count(_t.from))
  97. {
  98. chrono::steady_clock::time_point start = m_unlockedAccounts[_t.from].first;
  99. chrono::seconds duration(m_unlockedAccounts[_t.from].second);
  100. auto end = start + duration;
  101. if (start < end && chrono::steady_clock::now() < end)
  102. locked = false;
  103. }
  104. ret.r = TransactionRepercussion::Locked;
  105. if (locked && m_getAuthorisation)
  106. {
  107. if (m_getAuthorisation(_t, isProxyAccount(_t.from)))
  108. locked = false;
  109. else
  110. ret.r = TransactionRepercussion::Refused;
  111. }
  112. if (locked)
  113. return ret;
  114. if (isRealAccount(_t.from))
  115. {
  116. if (Secret s = m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); }))
  117. {
  118. ret.r = TransactionRepercussion::Success;
  119. tie(ret.hash, ret.created) = m_client()->submitTransaction(_t, s);
  120. }
  121. else
  122. ret.r = TransactionRepercussion::Locked;
  123. }
  124. else if (isProxyAccount(_t.from))
  125. {
  126. ret.r = TransactionRepercussion::ProxySuccess;
  127. queueTransaction(_t);
  128. }
  129. else
  130. ret.r = TransactionRepercussion::UnknownAccount;
  131. return ret;
  132. }
  133. bool SimpleAccountHolder::unlockAccount(Address const& _account, string const& _password, unsigned _duration)
  134. {
  135. if (!m_keyManager.hasAccount(_account))
  136. return false;
  137. if (_duration == 0)
  138. // Lock it even if the password is wrong.
  139. m_unlockedAccounts[_account].second = 0;
  140. m_keyManager.notePassword(_password);
  141. try
  142. {
  143. if (!m_keyManager.secret(_account, [&] { return _password; }, false))
  144. return false;
  145. }
  146. catch (PasswordUnknown const&)
  147. {
  148. return false;
  149. }
  150. m_unlockedAccounts[_account] = make_pair(chrono::steady_clock::now(), _duration);
  151. return true;
  152. }
  153. TransactionNotification FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
  154. {
  155. TransactionNotification ret;
  156. if (isRealAccount(_t.from))
  157. {
  158. if (m_accounts.count(_t.from))
  159. {
  160. ret.r = TransactionRepercussion::Success;
  161. tie(ret.hash, ret.created) = m_client()->submitTransaction(_t, m_accounts[_t.from]);
  162. }
  163. else
  164. ret.r = TransactionRepercussion::Locked;
  165. }
  166. else if (isProxyAccount(_t.from))
  167. {
  168. ret.r = TransactionRepercussion::ProxySuccess;
  169. queueTransaction(_t);
  170. }
  171. else
  172. ret.r = TransactionRepercussion::UnknownAccount;
  173. return ret;
  174. }