Fabcoin Core  0.16.2
P2P Digital Currency
AccountHolder.cpp
Go to the documentation of this file.
1 /*
2  This file is part of cpp-ethereum.
3 
4  cpp-ethereum is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  cpp-ethereum is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
16 */
24 #include "AccountHolder.h"
25 #include <random>
26 #include <libdevcore/Guards.h>
27 #include <libethereum/Client.h>
28 #include <libethcore/KeyManager.h>
29 
30 
31 using namespace std;
32 using namespace dev;
33 using namespace dev::eth;
34 
35 vector<TransactionSkeleton> g_emptyQueue;
36 static std::mt19937 g_randomNumberGenerator(utcTime());
37 static Mutex x_rngMutex;
38 
39 vector<Address> AccountHolder::allAccounts() const
40 {
41  vector<Address> accounts;
42  accounts += realAccounts();
43  for (auto const& pair: m_proxyAccounts)
44  if (!isRealAccount(pair.first))
45  accounts.push_back(pair.first);
46  return accounts;
47 }
48 
49 Address const& AccountHolder::defaultTransactAccount() const
50 {
51  auto accounts = realAccounts();
52  if (accounts.empty())
53  return ZeroAddress;
54  Address const* bestMatch = &*accounts.begin();
55  for (auto const& account: accounts)
56  if (m_client()->balanceAt(account) > m_client()->balanceAt(*bestMatch))
57  bestMatch = &account;
58  return *bestMatch;
59 }
60 
61 int AccountHolder::addProxyAccount(const Address& _account)
62 {
63  Guard g(x_rngMutex);
64  int id = std::uniform_int_distribution<int>(1)(g_randomNumberGenerator);
65  id = int(u256(FixedHash<32>(sha3(bytesConstRef((byte*)(&id), sizeof(int) / sizeof(byte))))));
66  if (isProxyAccount(_account) || id == 0 || m_transactionQueues.count(id))
67  return 0;
68  m_proxyAccounts.insert(make_pair(_account, id));
69  m_transactionQueues[id].first = _account;
70  return id;
71 }
72 
73 bool AccountHolder::removeProxyAccount(unsigned _id)
74 {
75  if (!m_transactionQueues.count(_id))
76  return false;
77  m_proxyAccounts.erase(m_transactionQueues[_id].first);
78  m_transactionQueues.erase(_id);
79  return true;
80 }
81 
82 void AccountHolder::queueTransaction(TransactionSkeleton const& _transaction)
83 {
84  if (!m_proxyAccounts.count(_transaction.from))
85  return;
86  int id = m_proxyAccounts[_transaction.from];
87  m_transactionQueues[id].second.push_back(_transaction);
88 }
89 
90 vector<TransactionSkeleton> const& AccountHolder::queuedTransactions(int _id) const
91 {
92  if (!m_transactionQueues.count(_id))
93  return g_emptyQueue;
94  return m_transactionQueues.at(_id).second;
95 }
96 
97 void AccountHolder::clearQueue(int _id)
98 {
99  if (m_transactionQueues.count(_id))
100  m_transactionQueues.at(_id).second.clear();
101 }
102 
103 AddressHash SimpleAccountHolder::realAccounts() const
104 {
105  return m_keyManager.accountsHash();
106 }
107 
108 TransactionNotification SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
109 {
111  bool locked = true;
112  if (m_unlockedAccounts.count(_t.from))
113  {
114  chrono::steady_clock::time_point start = m_unlockedAccounts[_t.from].first;
115  chrono::seconds duration(m_unlockedAccounts[_t.from].second);
116  auto end = start + duration;
117  if (start < end && chrono::steady_clock::now() < end)
118  locked = false;
119  }
120  ret.r = TransactionRepercussion::Locked;
121  if (locked && m_getAuthorisation)
122  {
123  if (m_getAuthorisation(_t, isProxyAccount(_t.from)))
124  locked = false;
125  else
126  ret.r = TransactionRepercussion::Refused;
127  }
128  if (locked)
129  return ret;
130  if (isRealAccount(_t.from))
131  {
132  if (Secret s = m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); }))
133  {
134  ret.r = TransactionRepercussion::Success;
135  tie(ret.hash, ret.created) = m_client()->submitTransaction(_t, s);
136  }
137  else
138  ret.r = TransactionRepercussion::Locked;
139  }
140  else if (isProxyAccount(_t.from))
141  {
142  ret.r = TransactionRepercussion::ProxySuccess;
143  queueTransaction(_t);
144  }
145  else
146  ret.r = TransactionRepercussion::UnknownAccount;
147  return ret;
148 }
149 
150 bool SimpleAccountHolder::unlockAccount(Address const& _account, string const& _password, unsigned _duration)
151 {
152  if (!m_keyManager.hasAccount(_account))
153  return false;
154 
155  if (_duration == 0)
156  // Lock it even if the password is wrong.
157  m_unlockedAccounts[_account].second = 0;
158 
159  m_keyManager.notePassword(_password);
160 
161  try
162  {
163  if (!m_keyManager.secret(_account, [&] { return _password; }, false))
164  return false;
165  }
166  catch (PasswordUnknown const&)
167  {
168  return false;
169  }
170  m_unlockedAccounts[_account] = make_pair(chrono::steady_clock::now(), _duration);
171 
172  return true;
173 }
174 
175 TransactionNotification FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
176 {
178  if (isRealAccount(_t.from))
179  {
180  if (m_accounts.count(_t.from))
181  {
182  ret.r = TransactionRepercussion::Success;
183  tie(ret.hash, ret.created) = m_client()->submitTransaction(_t, m_accounts[_t.from]);
184  }
185  else
186  ret.r = TransactionRepercussion::Locked;
187  }
188  else if (isProxyAccount(_t.from))
189  {
190  ret.r = TransactionRepercussion::ProxySuccess;
191  queueTransaction(_t);
192  }
193  else
194  ret.r = TransactionRepercussion::UnknownAccount;
195  return ret;
196 }
197 
198 
199 
Adapted from code found on http://stackoverflow.com/questions/180947/base64-decode-snippet-in-c Origi...
Definition: Arith256.cpp:15
uint8_t byte
Definition: Common.h:57
uint64_t utcTime()
Get the current time in seconds since the epoch in UTC.
Definition: Common.cpp:64
#define g(i)
Definition: sha.cpp:735
std::hash for asio::adress
Definition: Common.h:323
vector< TransactionSkeleton > g_emptyQueue
std::lock_guard< std::mutex > Guard
Definition: Guards.h:41
clock::duration duration
Definition: bench.h:50
Address ZeroAddress
The zero address.
Definition: Common.cpp:65
vector_ref< byte const > bytesConstRef
Definition: Common.h:77
Fixed-size raw-byte array container type, with an API optimised for storing hashes.
Definition: FixedHash.h:47
boost::multiprecision::number< boost::multiprecision::cpp_int_backend< 256, 256, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void >> u256
Definition: Common.h:125
TransactionRepercussion r
Definition: AccountHolder.h:55
clock::time_point time_point
Definition: bench.h:49
bool sha3(bytesConstRef _input, bytesRef o_output)
Calculate SHA3-256 hash of the given input and load it into the given output.
Definition: SHA3.cpp:214
std::mutex Mutex
Definition: Guards.h:37
std::unordered_set< h160 > AddressHash
A hash set of Ethereum addresses.
Definition: Common.h:71