1 // Aleth: Ethereum C++ client, tools and libraries.
2 // Copyright 2015-2019 Aleth Authors.
3 // Licensed under the GNU General Public License, Version 3.
4 
5 
6 #include "Eth.h"
7 #include "AccountHolder.h"
8 #include <jsonrpccpp/common/exception.h>
9 #include <libdevcore/CommonData.h>
10 #include <libethashseal/Ethash.h>
11 #include <libethcore/CommonJS.h>
12 #include <libethereum/Client.h>
13 #include <libweb3jsonrpc/JsonHelper.h>
14 #include <libwebthree/WebThree.h>
15 #include <csignal>
16 
17 using namespace std;
18 using namespace jsonrpc;
19 using namespace dev;
20 using namespace eth;
21 using namespace shh;
22 using namespace dev::rpc;
23 
Eth(eth::Interface & _eth,eth::AccountHolder & _ethAccounts)24 Eth::Eth(eth::Interface& _eth, eth::AccountHolder& _ethAccounts):
25 	m_eth(_eth),
26 	m_ethAccounts(_ethAccounts)
27 {
28 }
29 
eth_protocolVersion()30 string Eth::eth_protocolVersion()
31 {
32 	return toJS(eth::c_protocolVersion);
33 }
34 
eth_coinbase()35 string Eth::eth_coinbase()
36 {
37 	return toJS(client()->author());
38 }
39 
eth_hashrate()40 string Eth::eth_hashrate()
41 {
42     try
43     {
44         return toJS(getEthash().hashrate());
45     }
46     catch (InvalidSealEngine const&)
47     {
48         BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
49     }
50     catch (std::exception const&)
51     {
52         BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR));
53     }
54 }
55 
eth_mining()56 bool Eth::eth_mining()
57 {
58     try
59     {
60         return getEthash().isMining();
61     }
62     catch (InvalidSealEngine const&)
63     {
64         BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
65     }
66     catch (std::exception const&)
67     {
68         BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INTERNAL_ERROR));
69     }
70 }
71 
eth_gasPrice()72 string Eth::eth_gasPrice()
73 {
74 	return toJS(client()->gasBidPrice());
75 }
76 
eth_accounts()77 Json::Value Eth::eth_accounts()
78 {
79 	return toJson(m_ethAccounts.allAccounts());
80 }
81 
eth_blockNumber()82 string Eth::eth_blockNumber()
83 {
84 	return toJS(client()->number());
85 }
86 
87 
eth_getBalance(string const & _address,string const & _blockNumber)88 string Eth::eth_getBalance(string const& _address, string const& _blockNumber)
89 {
90 	try
91 	{
92 		return toJS(client()->balanceAt(jsToAddress(_address), jsToBlockNumber(_blockNumber)));
93 	}
94 	catch (...)
95 	{
96 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
97 	}
98 }
99 
eth_getStorageAt(string const & _address,string const & _position,string const & _blockNumber)100 string Eth::eth_getStorageAt(string const& _address, string const& _position, string const& _blockNumber)
101 {
102 	try
103 	{
104 		return toJS(toCompactBigEndian(client()->stateAt(jsToAddress(_address), jsToU256(_position), jsToBlockNumber(_blockNumber)), 32));
105 	}
106 	catch (...)
107 	{
108 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
109 	}
110 }
111 
eth_getStorageRoot(string const & _address,string const & _blockNumber)112 string Eth::eth_getStorageRoot(string const& _address, string const& _blockNumber)
113 {
114 	try
115 	{
116 		return toString(client()->stateRootAt(jsToAddress(_address), jsToBlockNumber(_blockNumber)));
117 	}
118 	catch (...)
119 	{
120 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
121 	}
122 }
123 
eth_pendingTransactions()124 Json::Value Eth::eth_pendingTransactions()
125 {
126 	//Return list of transaction that being sent by local accounts
127 	Transactions ours;
128 	for (Transaction const& pending:client()->pending())
129 	{
130 		for (Address const& account:m_ethAccounts.allAccounts())
131 		{
132 			if (pending.sender() == account)
133 			{
134 				ours.push_back(pending);
135 				break;
136 			}
137 		}
138 	}
139 
140 	return toJson(ours);
141 }
142 
eth_getTransactionCount(string const & _address,string const & _blockNumber)143 string Eth::eth_getTransactionCount(string const& _address, string const& _blockNumber)
144 {
145     try
146     {
147         return toString(client()->countAt(jsToAddress(_address), jsToBlockNumber(_blockNumber)));
148     }
149     catch (...)
150     {
151         BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
152     }
153 }
154 
eth_getBlockTransactionCountByHash(string const & _blockHash)155 Json::Value Eth::eth_getBlockTransactionCountByHash(string const& _blockHash)
156 {
157 	try
158 	{
159 		h256 blockHash = jsToFixed<32>(_blockHash);
160 		if (!client()->isKnown(blockHash))
161 			return Json::Value(Json::nullValue);
162 
163 		return toJS(client()->transactionCount(blockHash));
164 	}
165 	catch (...)
166 	{
167 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
168 	}
169 }
170 
eth_getBlockTransactionCountByNumber(string const & _blockNumber)171 Json::Value Eth::eth_getBlockTransactionCountByNumber(string const& _blockNumber)
172 {
173 	try
174 	{
175 		BlockNumber blockNumber = jsToBlockNumber(_blockNumber);
176 		if (!client()->isKnown(blockNumber))
177 			return Json::Value(Json::nullValue);
178 
179 		return toJS(client()->transactionCount(jsToBlockNumber(_blockNumber)));
180 	}
181 	catch (...)
182 	{
183 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
184 	}
185 }
186 
eth_getUncleCountByBlockHash(string const & _blockHash)187 Json::Value Eth::eth_getUncleCountByBlockHash(string const& _blockHash)
188 {
189 	try
190 	{
191 		h256 blockHash = jsToFixed<32>(_blockHash);
192 		if (!client()->isKnown(blockHash))
193 			return Json::Value(Json::nullValue);
194 
195 		return toJS(client()->uncleCount(blockHash));
196 	}
197 	catch (...)
198 	{
199 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
200 	}
201 }
202 
eth_getUncleCountByBlockNumber(string const & _blockNumber)203 Json::Value Eth::eth_getUncleCountByBlockNumber(string const& _blockNumber)
204 {
205 	try
206 	{
207 		BlockNumber blockNumber = jsToBlockNumber(_blockNumber);
208 		if (!client()->isKnown(blockNumber))
209 			return Json::Value(Json::nullValue);
210 
211 		return toJS(client()->uncleCount(blockNumber));
212 	}
213 	catch (...)
214 	{
215 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
216 	}
217 }
218 
eth_getCode(string const & _address,string const & _blockNumber)219 string Eth::eth_getCode(string const& _address, string const& _blockNumber)
220 {
221 	try
222 	{
223 		return toJS(client()->codeAt(jsToAddress(_address), jsToBlockNumber(_blockNumber)));
224 	}
225 	catch (...)
226 	{
227 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
228 	}
229 }
230 
setTransactionDefaults(TransactionSkeleton & _t)231 void Eth::setTransactionDefaults(TransactionSkeleton& _t)
232 {
233 	if (!_t.from)
234 		_t.from = m_ethAccounts.defaultTransactAccount();
235 }
236 
eth_sendTransaction(Json::Value const & _json)237 string Eth::eth_sendTransaction(Json::Value const& _json)
238 {
239 	try
240 	{
241 		TransactionSkeleton t = toTransactionSkeleton(_json);
242 		setTransactionDefaults(t);
243 		pair<bool, Secret> ar = m_ethAccounts.authenticate(t);
244 		if (!ar.first)
245 		{
246 			h256 txHash = client()->submitTransaction(t, ar.second);
247 			return toJS(txHash);
248 		}
249 		else
250 		{
251 			m_ethAccounts.queueTransaction(t);
252 			h256 emptyHash;
253 			return toJS(emptyHash); // TODO: give back something more useful than an empty hash.
254 		}
255 	}
256 	catch (Exception const&)
257 	{
258 		throw JsonRpcException(exceptionToErrorMessage());
259 	}
260 }
261 
eth_signTransaction(Json::Value const & _json)262 Json::Value Eth::eth_signTransaction(Json::Value const& _json)
263 {
264 	try
265 	{
266 		TransactionSkeleton ts = toTransactionSkeleton(_json);
267 		setTransactionDefaults(ts);
268 		ts = client()->populateTransactionWithDefaults(ts);
269 		pair<bool, Secret> ar = m_ethAccounts.authenticate(ts);
270 		Transaction t(ts, ar.second);
271 		RLPStream s;
272 		t.streamRLP(s);
273 		return toJson(t, s.out());
274 	}
275 	catch (Exception const&)
276 	{
277 		throw JsonRpcException(exceptionToErrorMessage());
278 	}
279 }
280 
eth_inspectTransaction(std::string const & _rlp)281 Json::Value Eth::eth_inspectTransaction(std::string const& _rlp)
282 {
283 	try
284 	{
285 		return toJson(Transaction(jsToBytes(_rlp, OnFailed::Throw), CheckTransaction::Everything));
286 	}
287 	catch (...)
288 	{
289 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
290 	}
291 }
292 
eth_sendRawTransaction(std::string const & _rlp)293 string Eth::eth_sendRawTransaction(std::string const& _rlp)
294 {
295 	try
296 	{
297 		// Don't need to check the transaction signature (CheckTransaction::None) since it will
298 		// be checked as a part of transaction import
299 		Transaction t(jsToBytes(_rlp, OnFailed::Throw), CheckTransaction::None);
300 		return toJS(client()->importTransaction(t));
301 	}
302 	catch (Exception const&)
303 	{
304 		throw JsonRpcException(exceptionToErrorMessage());
305 	}
306 }
307 
eth_call(Json::Value const & _json,string const & _blockNumber)308 string Eth::eth_call(Json::Value const& _json, string const& _blockNumber)
309 {
310 	try
311 	{
312 		TransactionSkeleton t = toTransactionSkeleton(_json);
313 		setTransactionDefaults(t);
314 		ExecutionResult er = client()->call(t.from, t.value, t.to, t.data, t.gas, t.gasPrice, jsToBlockNumber(_blockNumber), FudgeFactor::Lenient);
315 		return toJS(er.output);
316 	}
317 	catch (...)
318 	{
319 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
320 	}
321 }
322 
eth_estimateGas(Json::Value const & _json)323 string Eth::eth_estimateGas(Json::Value const& _json)
324 {
325 	try
326 	{
327 		TransactionSkeleton t = toTransactionSkeleton(_json);
328 		setTransactionDefaults(t);
329 		int64_t gas = static_cast<int64_t>(t.gas);
330 		return toJS(client()->estimateGas(t.from, t.value, t.to, t.data, gas, t.gasPrice, PendingBlock).first);
331 	}
332 	catch (...)
333 	{
334 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
335 	}
336 }
337 
eth_flush()338 bool Eth::eth_flush()
339 {
340 	client()->flushTransactions();
341 	return true;
342 }
343 
eth_getBlockByHash(string const & _blockHash,bool _includeTransactions)344 Json::Value Eth::eth_getBlockByHash(string const& _blockHash, bool _includeTransactions)
345 {
346 	try
347 	{
348 		h256 const h = jsToFixed<32>(_blockHash);
349 		if (!client()->isKnown(h))
350 			return Json::Value(Json::nullValue);
351 
352         Json::Value ret;
353         auto const blockDetails = client()->blockDetails(h);
354         auto const blockHeader = client()->blockInfo(h);
355         auto const uncleHashes = client()->uncleHashes(h);
356         auto* sealEngine = client()->sealEngine();
357         if (_includeTransactions)
358             ret = toJson(
359                 blockHeader, blockDetails, uncleHashes, client()->transactions(h), sealEngine);
360         else
361             ret = toJson(
362                 blockHeader, blockDetails, uncleHashes, client()->transactionHashes(h), sealEngine);
363         return ret;
364     }
365     catch (...)
366     {
367 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
368 	}
369 }
370 
eth_getBlockByNumber(string const & _blockNumber,bool _includeTransactions)371 Json::Value Eth::eth_getBlockByNumber(string const& _blockNumber, bool _includeTransactions)
372 {
373 	try
374 	{
375 		BlockNumber const h = jsToBlockNumber(_blockNumber);
376 		if (!client()->isKnown(h))
377 			return Json::Value(Json::nullValue);
378 
379         Json::Value ret;
380         auto const blockDetails = client()->blockDetails(h);
381         auto const blockHeader = client()->blockInfo(h);
382         auto const uncleHashes = client()->uncleHashes(h);
383         auto* sealEngine = client()->sealEngine();
384         if (_includeTransactions)
385             ret = toJson(
386                 blockHeader, blockDetails, uncleHashes, client()->transactions(h), sealEngine);
387         else
388             ret = toJson(
389                 blockHeader, blockDetails, uncleHashes, client()->transactionHashes(h), sealEngine);
390         return ret;
391     }
392 	catch (...)
393 	{
394 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
395 	}
396 }
397 
eth_getTransactionByHash(string const & _transactionHash)398 Json::Value Eth::eth_getTransactionByHash(string const& _transactionHash)
399 {
400 	try
401 	{
402 		h256 h = jsToFixed<32>(_transactionHash);
403 		if (!client()->isKnownTransaction(h))
404 			return Json::Value(Json::nullValue);
405 
406 		return toJson(client()->localisedTransaction(h));
407 	}
408 	catch (...)
409 	{
410 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
411 	}
412 }
413 
eth_getTransactionByBlockHashAndIndex(string const & _blockHash,string const & _transactionIndex)414 Json::Value Eth::eth_getTransactionByBlockHashAndIndex(string const& _blockHash, string const& _transactionIndex)
415 {
416 	try
417 	{
418 		h256 bh = jsToFixed<32>(_blockHash);
419 		unsigned ti = jsToInt(_transactionIndex);
420 		if (!client()->isKnownTransaction(bh, ti))
421 			return Json::Value(Json::nullValue);
422 
423 		return toJson(client()->localisedTransaction(bh, ti));
424 	}
425 	catch (...)
426 	{
427 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
428 	}
429 }
430 
eth_getTransactionByBlockNumberAndIndex(string const & _blockNumber,string const & _transactionIndex)431 Json::Value Eth::eth_getTransactionByBlockNumberAndIndex(string const& _blockNumber, string const& _transactionIndex)
432 {
433 	try
434 	{
435 		BlockNumber bn = jsToBlockNumber(_blockNumber);
436 		h256 bh = client()->hashFromNumber(bn);
437 		unsigned ti = jsToInt(_transactionIndex);
438 		if (!client()->isKnownTransaction(bh, ti))
439 			return Json::Value(Json::nullValue);
440 
441 		return toJson(client()->localisedTransaction(bh, ti));
442 	}
443 	catch (...)
444 	{
445 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
446 	}
447 }
448 
eth_getTransactionReceipt(string const & _transactionHash)449 Json::Value Eth::eth_getTransactionReceipt(string const& _transactionHash)
450 {
451 	try
452 	{
453 		h256 h = jsToFixed<32>(_transactionHash);
454 		if (!client()->isKnownTransaction(h))
455 			return Json::Value(Json::nullValue);
456 
457 		return toJson(client()->localisedTransactionReceipt(h));
458 	}
459 	catch (...)
460 	{
461 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
462 	}
463 }
464 
eth_getUncleByBlockHashAndIndex(string const & _blockHash,string const & _uncleIndex)465 Json::Value Eth::eth_getUncleByBlockHashAndIndex(string const& _blockHash, string const& _uncleIndex)
466 {
467 	try
468 	{
469 		return toJson(client()->uncle(jsToFixed<32>(_blockHash), jsToInt(_uncleIndex)), client()->sealEngine());
470 	}
471 	catch (...)
472 	{
473 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
474 	}
475 }
476 
eth_getUncleByBlockNumberAndIndex(string const & _blockNumber,string const & _uncleIndex)477 Json::Value Eth::eth_getUncleByBlockNumberAndIndex(string const& _blockNumber, string const& _uncleIndex)
478 {
479 	try
480 	{
481 		return toJson(client()->uncle(jsToBlockNumber(_blockNumber), jsToInt(_uncleIndex)), client()->sealEngine());
482 	}
483 	catch (...)
484 	{
485 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
486 	}
487 }
488 
eth_newFilter(Json::Value const & _json)489 string Eth::eth_newFilter(Json::Value const& _json)
490 {
491 	try
492 	{
493 		return toJS(client()->installWatch(toLogFilter(_json, *client())));
494 	}
495 	catch (...)
496 	{
497 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
498 	}
499 }
500 
eth_newFilterEx(Json::Value const & _json)501 string Eth::eth_newFilterEx(Json::Value const& _json)
502 {
503 	try
504 	{
505 		return toJS(client()->installWatch(toLogFilter(_json)));
506 	}
507 	catch (...)
508 	{
509 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
510 	}
511 }
512 
eth_newBlockFilter()513 string Eth::eth_newBlockFilter()
514 {
515 	h256 filter = dev::eth::ChainChangedFilter;
516 	return toJS(client()->installWatch(filter));
517 }
518 
eth_newPendingTransactionFilter()519 string Eth::eth_newPendingTransactionFilter()
520 {
521 	h256 filter = dev::eth::PendingChangedFilter;
522 	return toJS(client()->installWatch(filter));
523 }
524 
eth_uninstallFilter(string const & _filterId)525 bool Eth::eth_uninstallFilter(string const& _filterId)
526 {
527 	try
528 	{
529 		return client()->uninstallWatch(jsToInt(_filterId));
530 	}
531 	catch (...)
532 	{
533 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
534 	}
535 }
536 
eth_getFilterChanges(string const & _filterId)537 Json::Value Eth::eth_getFilterChanges(string const& _filterId)
538 {
539 	try
540 	{
541 		int id = jsToInt(_filterId);
542 		auto entries = client()->checkWatch(id);
543 //		if (entries.size())
544 //			cnote << "FIRING WATCH" << id << entries.size();
545 		return toJson(entries);
546 	}
547 	catch (...)
548 	{
549 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
550 	}
551 }
552 
eth_getFilterChangesEx(string const & _filterId)553 Json::Value Eth::eth_getFilterChangesEx(string const& _filterId)
554 {
555 	try
556 	{
557 		int id = jsToInt(_filterId);
558 		auto entries = client()->checkWatch(id);
559 //		if (entries.size())
560 //			cnote << "FIRING WATCH" << id << entries.size();
561 		return toJsonByBlock(entries);
562 	}
563 	catch (...)
564 	{
565 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
566 	}
567 }
568 
eth_getFilterLogs(string const & _filterId)569 Json::Value Eth::eth_getFilterLogs(string const& _filterId)
570 {
571 	try
572 	{
573 		return toJson(client()->logs(jsToInt(_filterId)));
574 	}
575 	catch (...)
576 	{
577 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
578 	}
579 }
580 
eth_getFilterLogsEx(string const & _filterId)581 Json::Value Eth::eth_getFilterLogsEx(string const& _filterId)
582 {
583 	try
584 	{
585 		return toJsonByBlock(client()->logs(jsToInt(_filterId)));
586 	}
587 	catch (...)
588 	{
589 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
590 	}
591 }
592 
eth_getLogs(Json::Value const & _json)593 Json::Value Eth::eth_getLogs(Json::Value const& _json)
594 {
595 	try
596 	{
597 		return toJson(client()->logs(toLogFilter(_json, *client())));
598 	}
599 	catch (...)
600 	{
601 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
602 	}
603 }
604 
eth_getLogsEx(Json::Value const & _json)605 Json::Value Eth::eth_getLogsEx(Json::Value const& _json)
606 {
607 	try
608 	{
609 		return toJsonByBlock(client()->logs(toLogFilter(_json)));
610 	}
611 	catch (...)
612 	{
613 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
614 	}
615 }
616 
eth_getWork()617 Json::Value Eth::eth_getWork()
618 {
619 	try
620 	{
621 		Json::Value ret(Json::arrayValue);
622         auto r = client()->getWork();
623         ret.append(toJS(get<0>(r)));
624 		ret.append(toJS(get<1>(r)));
625 		ret.append(toJS(get<2>(r)));
626 		return ret;
627 	}
628 	catch (...)
629 	{
630 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
631 	}
632 }
633 
eth_syncing()634 Json::Value Eth::eth_syncing()
635 {
636 	dev::eth::SyncStatus sync = client()->syncStatus();
637 	if (sync.state == SyncState::Idle || !sync.majorSyncing)
638 		return Json::Value(false);
639 
640 	Json::Value info(Json::objectValue);
641 	info["startingBlock"] = sync.startBlockNumber;
642 	info["highestBlock"] = sync.highestBlockNumber;
643 	info["currentBlock"] = sync.currentBlockNumber;
644 	return info;
645 }
646 
eth_chainId()647 string Eth::eth_chainId()
648 {
649 	return toJS(client()->chainId());
650 }
651 
eth_submitWork(string const & _nonce,string const &,string const & _mixHash)652 bool Eth::eth_submitWork(string const& _nonce, string const&, string const& _mixHash)
653 {
654 	try
655 	{
656         return getEthash().submitEthashWork(
657             jsToFixed<32>(_mixHash), jsToFixed<Nonce::size>(_nonce));
658     }
659 	catch (...)
660 	{
661 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
662 	}
663 }
664 
eth_submitHashrate(string const & _hashes,string const & _id)665 bool Eth::eth_submitHashrate(string const& _hashes, string const& _id)
666 {
667 	try
668     {
669         getEthash().submitExternalHashrate(jsToInt<32>(_hashes), jsToFixed<32>(_id));
670         return true;
671 	}
672 	catch (...)
673 	{
674 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
675 	}
676 }
677 
eth_register(string const & _address)678 string Eth::eth_register(string const& _address)
679 {
680 	try
681 	{
682 		return toJS(m_ethAccounts.addProxyAccount(jsToAddress(_address)));
683 	}
684 	catch (...)
685 	{
686 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
687 	}
688 }
689 
eth_unregister(string const & _accountId)690 bool Eth::eth_unregister(string const& _accountId)
691 {
692 	try
693 	{
694 		return m_ethAccounts.removeProxyAccount(jsToInt(_accountId));
695 	}
696 	catch (...)
697 	{
698 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
699 	}
700 }
701 
eth_fetchQueuedTransactions(string const & _accountId)702 Json::Value Eth::eth_fetchQueuedTransactions(string const& _accountId)
703 {
704 	try
705 	{
706 		auto id = jsToInt(_accountId);
707 		Json::Value ret(Json::arrayValue);
708 		// TODO: throw an error on no account with given id
709 		for (TransactionSkeleton const& t: m_ethAccounts.queuedTransactions(id))
710 			ret.append(toJson(t));
711 		m_ethAccounts.clearQueue(id);
712 		return ret;
713 	}
714 	catch (...)
715 	{
716 		BOOST_THROW_EXCEPTION(JsonRpcException(Errors::ERROR_RPC_INVALID_PARAMS));
717 	}
718 }
719 
exceptionToErrorMessage()720 string dev::rpc::exceptionToErrorMessage()
721 {
722 	string ret;
723 	try
724 	{
725 		throw;
726 	}
727 	// Transaction submission exceptions
728 	catch (ZeroSignatureTransaction const&)
729 	{
730 		ret = "Zero signature transaction.";
731 	}
732 	catch (GasPriceTooLow const&)
733 	{
734 		ret = "Pending transaction with same nonce but higher gas price exists.";
735 	}
736 	catch (OutOfGasIntrinsic const&)
737 	{
738 		ret = "Transaction gas amount is less than the intrinsic gas amount for this transaction type.";
739 	}
740     catch (BlockGasLimitReached const& _ex)
741     {
742         string errorString = "Block gas limit reached! ";
743         cwarn << errorString + _ex.what();
744         ret = errorString;
745     }
746 	catch (InvalidNonce const&)
747 	{
748 		ret = "Invalid transaction nonce.";
749 	}
750 	catch (PendingTransactionAlreadyExists const&)
751 	{
752 		ret = "Same transaction already exists in the pending transaction queue.";
753 	}
754 	catch (TransactionAlreadyInChain const&)
755 	{
756 		ret = "Transaction is already in the blockchain.";
757 	}
758 	catch (NotEnoughCash const&)
759 	{
760 		ret = "Account balance is too low (balance < value + gas * gas price).";
761 	}
762 	catch (InvalidSignature const&)
763 	{
764 		ret = "Invalid transaction signature.";
765 	}
766 	// Acount holder exceptions
767 	catch (AccountLocked const&)
768 	{
769 		ret = "Account is locked.";
770 	}
771 	catch (UnknownAccount const&)
772 	{
773 		ret = "Unknown account.";
774 	}
775 	catch (TransactionRefused const&)
776 	{
777 		ret = "Transaction rejected by user.";
778 	}
779 	catch (...)
780 	{
781 		ret = "Invalid RPC parameters.";
782 	}
783 	return ret;
784 }
785 
getEthash()786 Ethash& Eth::getEthash()
787 {
788     return asEthash(*client()->sealEngine());
789 }
790