You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

125 lines
3.5 KiB

/*
This file is part of cpp-ethereum.
cpp-ethereum is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
*/
/** @file AccountHolder.cpp
* @authors:
* Christian R <c@ethdev.com>
* Lefteris Karapetsas <lefteris@ethdev.com>
* @date 2015
*/
#include "AccountHolder.h"
#include <random>
#include <ctime>
#include <libdevcore/Guards.h>
#include <libethereum/Client.h>
#include <libethereum/KeyManager.h>
using namespace std;
using namespace dev;
using namespace dev::eth;
vector<TransactionSkeleton> g_emptyQueue;
static std::mt19937 g_randomNumberGenerator(time(0));
static Mutex x_rngMutex;
vector<Address> AccountHolder::allAccounts() const
{
vector<Address> accounts;
accounts += realAccounts();
for (auto const& pair: m_proxyAccounts)
if (!isRealAccount(pair.first))
accounts.push_back(pair.first);
return accounts;
}
Address const& AccountHolder::defaultTransactAccount() const
{
auto accounts = realAccounts();
if (accounts.empty())
return ZeroAddress;
Address const* bestMatch = &*accounts.begin();
for (auto const& account: accounts)
if (m_client()->balanceAt(account) > m_client()->balanceAt(*bestMatch))
bestMatch = &account;
return *bestMatch;
}
int AccountHolder::addProxyAccount(const Address& _account)
{
Guard g(x_rngMutex);
int id = std::uniform_int_distribution<int>(1)(g_randomNumberGenerator);
id = int(u256(FixedHash<32>(sha3(bytesConstRef((byte*)(&id), sizeof(int) / sizeof(byte))))));
if (isProxyAccount(_account) || id == 0 || m_transactionQueues.count(id))
return 0;
m_proxyAccounts.insert(make_pair(_account, id));
m_transactionQueues[id].first = _account;
return id;
}
bool AccountHolder::removeProxyAccount(unsigned _id)
{
if (!m_transactionQueues.count(_id))
return false;
m_proxyAccounts.erase(m_transactionQueues[_id].first);
m_transactionQueues.erase(_id);
return true;
}
void AccountHolder::queueTransaction(TransactionSkeleton const& _transaction)
{
if (!m_proxyAccounts.count(_transaction.from))
return;
int id = m_proxyAccounts[_transaction.from];
m_transactionQueues[id].second.push_back(_transaction);
}
vector<TransactionSkeleton> const& AccountHolder::queuedTransactions(int _id) const
{
if (!m_transactionQueues.count(_id))
return g_emptyQueue;
return m_transactionQueues.at(_id).second;
}
void AccountHolder::clearQueue(int _id)
{
if (m_transactionQueues.count(_id))
m_transactionQueues.at(_id).second.clear();
}
AddressHash SimpleAccountHolder::realAccounts() const
{
return m_keyManager.accounts();
}
void SimpleAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
{
if (isRealAccount(_t.from))
m_client()->submitTransaction(m_keyManager.secret(_t.from, [&](){ return m_getPassword(_t.from); }), _t);
else if (isProxyAccount(_t.from))
queueTransaction(_t);
}
void FixedAccountHolder::authenticate(dev::eth::TransactionSkeleton const& _t)
{
if (isRealAccount(_t.from))
m_client()->submitTransaction(m_accounts[_t.from], _t);
else if (isProxyAccount(_t.from))
queueTransaction(_t);
}