1 #include "AdminEth.h"
2 #include "JsonHelper.h"
3 #include "SessionManager.h"
4 #include <jsonrpccpp/common/exception.h>
5 #include <libdevcore/CommonJS.h>
6 #include <libethashseal/Ethash.h>
7 #include <libethcore/KeyManager.h>
8 #include <libethereum/Client.h>
9 #include <libethereum/Executive.h>
10 #include <libethereum/StandardTrace.h>
11 using namespace std;
12 using namespace dev;
13 using namespace dev::rpc;
14 using namespace dev::eth;
15
AdminEth(eth::Client & _eth,eth::TrivialGasPricer & _gp,eth::KeyManager & _keyManager,SessionManager & _sm)16 AdminEth::AdminEth(eth::Client& _eth, eth::TrivialGasPricer& _gp, eth::KeyManager& _keyManager, SessionManager& _sm):
17 m_eth(_eth),
18 m_gp(_gp),
19 m_keyManager(_keyManager),
20 m_sm(_sm)
21 {}
22
admin_eth_setMining(bool _on,string const & _session)23 bool AdminEth::admin_eth_setMining(bool _on, string const& _session)
24 {
25 RPC_ADMIN;
26 if (_on)
27 m_eth.startSealing();
28 else
29 m_eth.stopSealing();
30 return true;
31 }
32
admin_eth_blockQueueStatus(string const & _session)33 Json::Value AdminEth::admin_eth_blockQueueStatus(string const& _session)
34 {
35 RPC_ADMIN;
36 Json::Value ret;
37 BlockQueueStatus bqs = m_eth.blockQueue().status();
38 ret["importing"] = (int)bqs.importing;
39 ret["verified"] = (int)bqs.verified;
40 ret["verifying"] = (int)bqs.verifying;
41 ret["unverified"] = (int)bqs.unverified;
42 ret["future"] = (int)bqs.future;
43 ret["unknown"] = (int)bqs.unknown;
44 ret["bad"] = (int)bqs.bad;
45 return ret;
46 }
47
admin_eth_setAskPrice(string const & _wei,string const & _session)48 bool AdminEth::admin_eth_setAskPrice(string const& _wei, string const& _session)
49 {
50 RPC_ADMIN;
51 m_gp.setAsk(jsToU256(_wei));
52 return true;
53 }
54
admin_eth_setBidPrice(string const & _wei,string const & _session)55 bool AdminEth::admin_eth_setBidPrice(string const& _wei, string const& _session)
56 {
57 RPC_ADMIN;
58 m_gp.setBid(jsToU256(_wei));
59 return true;
60 }
61
admin_eth_findBlock(string const & _blockHash,string const & _session)62 Json::Value AdminEth::admin_eth_findBlock(string const& _blockHash, string const& _session)
63 {
64 RPC_ADMIN;
65 h256 h(_blockHash);
66 if (m_eth.blockChain().isKnown(h))
67 return toJson(m_eth.blockChain().info(h));
68 switch(m_eth.blockQueue().blockStatus(h))
69 {
70 case QueueStatus::Ready:
71 return "ready";
72 case QueueStatus::Importing:
73 return "importing";
74 case QueueStatus::UnknownParent:
75 return "unknown parent";
76 case QueueStatus::Bad:
77 return "bad";
78 default:
79 return "unknown";
80 }
81 }
82
admin_eth_blockQueueFirstUnknown(string const & _session)83 string AdminEth::admin_eth_blockQueueFirstUnknown(string const& _session)
84 {
85 RPC_ADMIN;
86 return m_eth.blockQueue().firstUnknown().hex();
87 }
88
admin_eth_blockQueueRetryUnknown(string const & _session)89 bool AdminEth::admin_eth_blockQueueRetryUnknown(string const& _session)
90 {
91 RPC_ADMIN;
92 m_eth.retryUnknown();
93 return true;
94 }
95
admin_eth_allAccounts(string const & _session)96 Json::Value AdminEth::admin_eth_allAccounts(string const& _session)
97 {
98 RPC_ADMIN;
99 Json::Value ret;
100 u256 total = 0;
101 u256 pendingtotal = 0;
102 Address beneficiary;
103 for (auto const& address: m_keyManager.accounts())
104 {
105 auto pending = m_eth.balanceAt(address, PendingBlock);
106 auto latest = m_eth.balanceAt(address, LatestBlock);
107 Json::Value a;
108 if (address == beneficiary)
109 a["beneficiary"] = true;
110 a["address"] = toJS(address);
111 a["balance"] = toJS(latest);
112 a["nicebalance"] = formatBalance(latest);
113 a["pending"] = toJS(pending);
114 a["nicepending"] = formatBalance(pending);
115 ret["accounts"][m_keyManager.accountName(address)] = a;
116 total += latest;
117 pendingtotal += pending;
118 }
119 ret["total"] = toJS(total);
120 ret["nicetotal"] = formatBalance(total);
121 ret["pendingtotal"] = toJS(pendingtotal);
122 ret["nicependingtotal"] = formatBalance(pendingtotal);
123 return ret;
124 }
125
admin_eth_newAccount(Json::Value const & _info,string const & _session)126 Json::Value AdminEth::admin_eth_newAccount(Json::Value const& _info, string const& _session)
127 {
128 RPC_ADMIN;
129 if (!_info.isMember("name"))
130 throw jsonrpc::JsonRpcException("No member found: name");
131 string name = _info["name"].asString();
132 KeyPair kp = KeyPair::create();
133 h128 uuid;
134 if (_info.isMember("password"))
135 {
136 string password = _info["password"].asString();
137 string hint = _info["passwordHint"].asString();
138 uuid = m_keyManager.import(kp.secret(), name, password, hint);
139 }
140 else
141 uuid = m_keyManager.import(kp.secret(), name);
142 Json::Value ret;
143 ret["account"] = toJS(kp.pub());
144 ret["uuid"] = toUUID(uuid);
145 return ret;
146 }
147
admin_eth_setMiningBenefactor(string const & _uuidOrAddress,string const & _session)148 bool AdminEth::admin_eth_setMiningBenefactor(string const& _uuidOrAddress, string const& _session)
149 {
150 RPC_ADMIN;
151 return miner_setEtherbase(_uuidOrAddress);
152 }
153
admin_eth_inspect(string const & _address,string const & _session)154 Json::Value AdminEth::admin_eth_inspect(string const& _address, string const& _session)
155 {
156 RPC_ADMIN;
157 if (!isHash<Address>(_address))
158 throw jsonrpc::JsonRpcException("Invalid address given.");
159
160 Json::Value ret;
161 auto h = Address(fromHex(_address));
162 ret["storage"] = toJson(m_eth.storageAt(h, PendingBlock));
163 ret["balance"] = toJS(m_eth.balanceAt(h, PendingBlock));
164 ret["nonce"] = toJS(m_eth.countAt(h, PendingBlock));
165 ret["code"] = toJS(m_eth.codeAt(h, PendingBlock));
166 return ret;
167 }
168
blockHash(string const & _blockNumberOrHash) const169 h256 AdminEth::blockHash(string const& _blockNumberOrHash) const
170 {
171 if (isHash<h256>(_blockNumberOrHash))
172 return h256(_blockNumberOrHash.substr(_blockNumberOrHash.size() - 64, 64));
173 try
174 {
175 return m_eth.blockChain().numberHash(stoul(_blockNumberOrHash));
176 }
177 catch (...)
178 {
179 throw jsonrpc::JsonRpcException("Invalid argument");
180 }
181 }
182
admin_eth_vmTrace(string const & _blockNumberOrHash,int _txIndex,string const & _session)183 Json::Value AdminEth::admin_eth_vmTrace(string const& _blockNumberOrHash, int _txIndex, string const& _session)
184 {
185 RPC_ADMIN;
186
187 Json::Value ret;
188
189 if (_txIndex < 0)
190 throw jsonrpc::JsonRpcException("Negative index");
191 Block block = m_eth.block(blockHash(_blockNumberOrHash));
192 if ((unsigned)_txIndex < block.pending().size())
193 {
194 Transaction t = block.pending()[_txIndex];
195 State s(State::Null);
196 Executive e(s, block, _txIndex, m_eth.blockChain());
197 try
198 {
199 Json::Value traceJson{Json::arrayValue};
200 StandardTrace st{traceJson};
201 st.setShowMnemonics();
202 e.initialize(t);
203 if (!e.execute())
204 e.go(st.onOp());
205 e.finalize();
206 ret["structLogs"] = traceJson;
207 }
208 catch(Exception const& _e)
209 {
210 cwarn << diagnostic_information(_e);
211 }
212 }
213
214 return ret;
215 }
216
admin_eth_getReceiptByHashAndIndex(string const & _blockNumberOrHash,int _txIndex,string const & _session)217 Json::Value AdminEth::admin_eth_getReceiptByHashAndIndex(string const& _blockNumberOrHash, int _txIndex, string const& _session)
218 {
219 RPC_ADMIN;
220 if (_txIndex < 0)
221 throw jsonrpc::JsonRpcException("Negative index");
222 auto h = blockHash(_blockNumberOrHash);
223 if (!m_eth.blockChain().isKnown(h))
224 throw jsonrpc::JsonRpcException("Invalid/unknown block.");
225 auto rs = m_eth.blockChain().receipts(h);
226 if ((unsigned)_txIndex >= rs.receipts.size())
227 throw jsonrpc::JsonRpcException("Index too large.");
228 return toJson(rs.receipts[_txIndex]);
229 }
230
miner_start(int)231 bool AdminEth::miner_start(int)
232 {
233 m_eth.startSealing();
234 return true;
235 }
236
miner_stop()237 bool AdminEth::miner_stop()
238 {
239 m_eth.stopSealing();
240 return true;
241 }
242
miner_setEtherbase(string const & _uuidOrAddress)243 bool AdminEth::miner_setEtherbase(string const& _uuidOrAddress)
244 {
245 Address a;
246 h128 uuid = fromUUID(_uuidOrAddress);
247 if (uuid)
248 a = m_keyManager.address(uuid);
249 else if (isHash<Address>(_uuidOrAddress))
250 a = Address(_uuidOrAddress);
251 else
252 throw jsonrpc::JsonRpcException("Invalid UUID or address");
253
254 if (m_setMiningBenefactor)
255 m_setMiningBenefactor(a);
256 else
257 m_eth.setAuthor(a);
258 return true;
259 }
260
miner_setExtra(string const & _extraData)261 bool AdminEth::miner_setExtra(string const& _extraData)
262 {
263 m_eth.setExtraData(asBytes(_extraData));
264 return true;
265 }
266
miner_setGasPrice(string const & _gasPrice)267 bool AdminEth::miner_setGasPrice(string const& _gasPrice)
268 {
269 m_gp.setAsk(jsToU256(_gasPrice));
270 return true;
271 }
272
miner_hashrate()273 string AdminEth::miner_hashrate()
274 {
275 try
276 {
277 return toJS(asEthash(*m_eth.sealEngine()).hashrate());
278 }
279 catch (...)
280 {
281 throw jsonrpc::JsonRpcException("Hashrate not available - blockchain does not support mining.");
282 }
283 }
284