123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733 |
- /*
- 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 Eth.cpp
- * @authors:
- * Gav Wood <i@gavwood.com>
- * Marek Kotewicz <marek@ethdev.com>
- * @date 2014
- */
- #include <csignal>
- #include <jsonrpccpp/common/exception.h>
- #include <libdevcore/CommonData.h>
- #include <libevmcore/Instruction.h>
- #include <libethereum/Client.h>
- #include <libethashseal/EthashClient.h>
- #include <libwebthree/WebThree.h>
- #include <libethcore/CommonJS.h>
- #include <libweb3jsonrpc/JsonHelper.h>
- #include "Eth.h"
- #include "AccountHolder.h"
- #include "JsonHelper.h"
- using namespace std;
- using namespace jsonrpc;
- using namespace dev;
- using namespace eth;
- using namespace shh;
- using namespace dev::rpc;
- #if ETH_DEBUG
- const unsigned dev::SensibleHttpThreads = 1;
- #else
- const unsigned dev::SensibleHttpThreads = 4;
- #endif
- const unsigned dev::SensibleHttpPort = 8545;
- Eth::Eth(eth::Interface& _eth, eth::AccountHolder& _ethAccounts):
- m_eth(_eth),
- m_ethAccounts(_ethAccounts)
- {
- }
- string Eth::eth_protocolVersion()
- {
- return toJS(eth::c_protocolVersion);
- }
- string Eth::eth_coinbase()
- {
- return toJS(client()->author());
- }
- string Eth::eth_hashrate()
- {
- try
- {
- return toJS(asEthashClient(client())->hashrate());
- }
- catch (InvalidSealEngine&)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- bool Eth::eth_mining()
- {
- try
- {
- return asEthashClient(client())->isMining();
- }
- catch (InvalidSealEngine&)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_gasPrice()
- {
- return toJS(client()->gasBidPrice());
- }
- Json::Value Eth::eth_accounts()
- {
- return toJson(m_ethAccounts.allAccounts());
- }
- string Eth::eth_blockNumber()
- {
- return toJS(client()->number());
- }
- string Eth::eth_getBalance(string const& _address, string const& _blockNumber)
- {
- try
- {
- return toJS(client()->balanceAt(jsToAddress(_address), jsToBlockNumber(_blockNumber)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_getStorageAt(string const& _address, string const& _position, string const& _blockNumber)
- {
- try
- {
- return toJS(toCompactBigEndian(client()->stateAt(jsToAddress(_address), jsToU256(_position), jsToBlockNumber(_blockNumber)), 32));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_getStorageRoot(string const& _address, string const& _blockNumber)
- {
- try
- {
- return toString(client()->stateRootAt(jsToAddress(_address), jsToBlockNumber(_blockNumber)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_pendingTransactions()
- {
- //Return list of transaction that being sent by local accounts
- Transactions ours;
- for (Transaction const& pending:client()->pending())
- {
- for (Address const& account:m_ethAccounts.allAccounts())
- {
- if (pending.sender() == account)
- {
- ours.push_back(pending);
- break;
- }
- }
- }
- return toJS(ours);
- }
- string Eth::eth_getTransactionCount(string const& _address, string const& _blockNumber)
- {
- try
- {
- return toJS(client()->countAt(jsToAddress(_address), jsToBlockNumber(_blockNumber)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getBlockTransactionCountByHash(string const& _blockHash)
- {
- try
- {
- h256 blockHash = jsToFixed<32>(_blockHash);
- if (!client()->isKnown(blockHash))
- return Json::Value(Json::nullValue);
- return toJS(client()->transactionCount(blockHash));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getBlockTransactionCountByNumber(string const& _blockNumber)
- {
- try
- {
- BlockNumber blockNumber = jsToBlockNumber(_blockNumber);
- if (!client()->isKnown(blockNumber))
- return Json::Value(Json::nullValue);
- return toJS(client()->transactionCount(jsToBlockNumber(_blockNumber)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getUncleCountByBlockHash(string const& _blockHash)
- {
- try
- {
- h256 blockHash = jsToFixed<32>(_blockHash);
- if (!client()->isKnown(blockHash))
- return Json::Value(Json::nullValue);
- return toJS(client()->uncleCount(blockHash));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getUncleCountByBlockNumber(string const& _blockNumber)
- {
- try
- {
- BlockNumber blockNumber = jsToBlockNumber(_blockNumber);
- if (!client()->isKnown(blockNumber))
- return Json::Value(Json::nullValue);
- return toJS(client()->uncleCount(blockNumber));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_getCode(string const& _address, string const& _blockNumber)
- {
- try
- {
- return toJS(client()->codeAt(jsToAddress(_address), jsToBlockNumber(_blockNumber)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- void Eth::setTransactionDefaults(TransactionSkeleton& _t)
- {
- if (!_t.from)
- _t.from = m_ethAccounts.defaultTransactAccount();
- }
- string Eth::eth_sendTransaction(Json::Value const& _json)
- {
- try
- {
- TransactionSkeleton t = toTransactionSkeleton(_json);
- setTransactionDefaults(t);
- TransactionNotification n = m_ethAccounts.authenticate(t);
- switch (n.r)
- {
- case TransactionRepercussion::Success:
- return toJS(n.hash);
- case TransactionRepercussion::ProxySuccess:
- return toJS(n.hash);// TODO: give back something more useful than an empty hash.
- case TransactionRepercussion::UnknownAccount:
- BOOST_THROW_EXCEPTION(JsonRpcException("Account unknown."));
- case TransactionRepercussion::Locked:
- BOOST_THROW_EXCEPTION(JsonRpcException("Account is locked."));
- case TransactionRepercussion::Refused:
- BOOST_THROW_EXCEPTION(JsonRpcException("Transaction rejected by user."));
- case TransactionRepercussion::Unknown:
- BOOST_THROW_EXCEPTION(JsonRpcException("Unknown reason."));
- }
- }
- catch (JsonRpcException&)
- {
- throw;
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- return string();
- }
- string Eth::eth_signTransaction(Json::Value const& _json)
- {
- try
- {
- TransactionSkeleton t = toTransactionSkeleton(_json);
- setTransactionDefaults(t);
- TransactionNotification n = m_ethAccounts.authenticate(t);
- switch (n.r)
- {
- case TransactionRepercussion::Success:
- return toJS(n.hash);
- case TransactionRepercussion::ProxySuccess:
- return toJS(n.hash);// TODO: give back something more useful than an empty hash.
- default:
- // TODO: provide more useful information in the exception.
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_inspectTransaction(std::string const& _rlp)
- {
- try
- {
- return toJson(Transaction(jsToBytes(_rlp, OnFailed::Throw), CheckTransaction::Everything));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_sendRawTransaction(std::string const& _rlp)
- {
- try
- {
- if (client()->injectTransaction(jsToBytes(_rlp, OnFailed::Throw)) == ImportResult::Success)
- {
- Transaction tx(jsToBytes(_rlp, OnFailed::Throw), CheckTransaction::None);
- return toJS(tx.sha3());
- }
- else
- return toJS(h256());
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_call(Json::Value const& _json, string const& _blockNumber)
- {
- try
- {
- TransactionSkeleton t = toTransactionSkeleton(_json);
- setTransactionDefaults(t);
- ExecutionResult er = client()->call(t.from, t.value, t.to, t.data, t.gas, t.gasPrice, jsToBlockNumber(_blockNumber), FudgeFactor::Lenient);
- return toJS(er.output);
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_estimateGas(Json::Value const& _json)
- {
- try
- {
- TransactionSkeleton t = toTransactionSkeleton(_json);
- setTransactionDefaults(t);
- return toJS(client()->estimateGas(t.from, t.value, t.to, t.data, t.gas, t.gasPrice, PendingBlock).first);
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- bool Eth::eth_flush()
- {
- client()->flushTransactions();
- return true;
- }
- Json::Value Eth::eth_getBlockByHash(string const& _blockHash, bool _includeTransactions)
- {
- try
- {
- h256 h = jsToFixed<32>(_blockHash);
- if (!client()->isKnown(h))
- return Json::Value(Json::nullValue);
- if (_includeTransactions)
- return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactions(h), client()->sealEngine());
- else
- return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactionHashes(h), client()->sealEngine());
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getBlockByNumber(string const& _blockNumber, bool _includeTransactions)
- {
- try
- {
- BlockNumber h = jsToBlockNumber(_blockNumber);
- if (!client()->isKnown(h))
- return Json::Value(Json::nullValue);
- if (_includeTransactions)
- return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactions(h), client()->sealEngine());
- else
- return toJson(client()->blockInfo(h), client()->blockDetails(h), client()->uncleHashes(h), client()->transactionHashes(h), client()->sealEngine());
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getTransactionByHash(string const& _transactionHash)
- {
- try
- {
- h256 h = jsToFixed<32>(_transactionHash);
- if (!client()->isKnownTransaction(h))
- return Json::Value(Json::nullValue);
- return toJson(client()->localisedTransaction(h));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getTransactionByBlockHashAndIndex(string const& _blockHash, string const& _transactionIndex)
- {
- try
- {
- h256 bh = jsToFixed<32>(_blockHash);
- unsigned ti = jsToInt(_transactionIndex);
- if (!client()->isKnownTransaction(bh, ti))
- return Json::Value(Json::nullValue);
- return toJson(client()->localisedTransaction(bh, ti));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getTransactionByBlockNumberAndIndex(string const& _blockNumber, string const& _transactionIndex)
- {
- try
- {
- BlockNumber bn = jsToBlockNumber(_blockNumber);
- h256 bh = client()->hashFromNumber(bn);
- unsigned ti = jsToInt(_transactionIndex);
- if (!client()->isKnownTransaction(bh, ti))
- return Json::Value(Json::nullValue);
- return toJson(client()->localisedTransaction(bh, ti));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getTransactionReceipt(string const& _transactionHash)
- {
- try
- {
- h256 h = jsToFixed<32>(_transactionHash);
- if (!client()->isKnownTransaction(h))
- return Json::Value(Json::nullValue);
- return toJson(client()->localisedTransactionReceipt(h));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getUncleByBlockHashAndIndex(string const& _blockHash, string const& _uncleIndex)
- {
- try
- {
- return toJson(client()->uncle(jsToFixed<32>(_blockHash), jsToInt(_uncleIndex)), client()->sealEngine());
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getUncleByBlockNumberAndIndex(string const& _blockNumber, string const& _uncleIndex)
- {
- try
- {
- return toJson(client()->uncle(jsToBlockNumber(_blockNumber), jsToInt(_uncleIndex)), client()->sealEngine());
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_newFilter(Json::Value const& _json)
- {
- try
- {
- return toJS(client()->installWatch(toLogFilter(_json, *client())));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_newFilterEx(Json::Value const& _json)
- {
- try
- {
- return toJS(client()->installWatch(toLogFilter(_json)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_newBlockFilter()
- {
- h256 filter = dev::eth::ChainChangedFilter;
- return toJS(client()->installWatch(filter));
- }
- string Eth::eth_newPendingTransactionFilter()
- {
- h256 filter = dev::eth::PendingChangedFilter;
- return toJS(client()->installWatch(filter));
- }
- bool Eth::eth_uninstallFilter(string const& _filterId)
- {
- try
- {
- return client()->uninstallWatch(jsToInt(_filterId));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getFilterChanges(string const& _filterId)
- {
- try
- {
- int id = jsToInt(_filterId);
- auto entries = client()->checkWatch(id);
- // if (entries.size())
- // cnote << "FIRING WATCH" << id << entries.size();
- return toJson(entries);
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getFilterChangesEx(string const& _filterId)
- {
- try
- {
- int id = jsToInt(_filterId);
- auto entries = client()->checkWatch(id);
- // if (entries.size())
- // cnote << "FIRING WATCH" << id << entries.size();
- return toJsonByBlock(entries);
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getFilterLogs(string const& _filterId)
- {
- try
- {
- return toJson(client()->logs(jsToInt(_filterId)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getFilterLogsEx(string const& _filterId)
- {
- try
- {
- return toJsonByBlock(client()->logs(jsToInt(_filterId)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getLogs(Json::Value const& _json)
- {
- try
- {
- return toJson(client()->logs(toLogFilter(_json, *client())));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getLogsEx(Json::Value const& _json)
- {
- try
- {
- return toJsonByBlock(client()->logs(toLogFilter(_json)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_getWork()
- {
- try
- {
- Json::Value ret(Json::arrayValue);
- auto r = asEthashClient(client())->getEthashWork();
- ret.append(toJS(get<0>(r)));
- ret.append(toJS(get<1>(r)));
- ret.append(toJS(get<2>(r)));
- return ret;
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_syncing()
- {
- dev::eth::SyncStatus sync = client()->syncStatus();
- if (sync.state == SyncState::Idle || !sync.majorSyncing)
- return Json::Value(false);
- Json::Value info(Json::objectValue);
- info["startingBlock"] = sync.startBlockNumber;
- info["highestBlock"] = sync.highestBlockNumber;
- info["currentBlock"] = sync.currentBlockNumber;
- return info;
- }
- bool Eth::eth_submitWork(string const& _nonce, string const&, string const& _mixHash)
- {
- try
- {
- return asEthashClient(client())->submitEthashWork(jsToFixed<32>(_mixHash), jsToFixed<Nonce::size>(_nonce));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- bool Eth::eth_submitHashrate(string const& _hashes, string const& _id)
- {
- try
- {
- asEthashClient(client())->submitExternalHashrate(jsToInt<32>(_hashes), jsToFixed<32>(_id));
- return true;
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- string Eth::eth_register(string const& _address)
- {
- try
- {
- return toJS(m_ethAccounts.addProxyAccount(jsToAddress(_address)));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- bool Eth::eth_unregister(string const& _accountId)
- {
- try
- {
- return m_ethAccounts.removeProxyAccount(jsToInt(_accountId));
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
- Json::Value Eth::eth_fetchQueuedTransactions(string const& _accountId)
- {
- try
- {
- auto id = jsToInt(_accountId);
- Json::Value ret(Json::arrayValue);
- // TODO: throw an error on no account with given id
- for (TransactionSkeleton const& t: m_ethAccounts.queuedTransactions(id))
- ret.append(toJson(t));
- m_ethAccounts.clearQueue(id);
- return ret;
- }
- catch (...)
- {
- BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
- }
- }
|