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