admin.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506
  1. package main
  2. import (
  3. "errors"
  4. "fmt"
  5. "strconv"
  6. "time"
  7. "github.com/ethereum/go-ethereum/cmd/utils"
  8. "github.com/ethereum/go-ethereum/common"
  9. "github.com/ethereum/go-ethereum/core/state"
  10. "github.com/ethereum/go-ethereum/core/types"
  11. "github.com/ethereum/go-ethereum/core/vm"
  12. "github.com/ethereum/go-ethereum/logger/glog"
  13. "github.com/ethereum/go-ethereum/rlp"
  14. "github.com/ethereum/go-ethereum/rpc"
  15. "github.com/ethereum/go-ethereum/xeth"
  16. "github.com/robertkrimen/otto"
  17. )
  18. /*
  19. node admin bindings
  20. */
  21. func (js *jsre) adminBindings() {
  22. ethO, _ := js.re.Get("eth")
  23. eth := ethO.Object()
  24. eth.Set("transactions", js.transactions)
  25. eth.Set("resend", js.resend)
  26. js.re.Set("admin", struct{}{})
  27. t, _ := js.re.Get("admin")
  28. admin := t.Object()
  29. admin.Set("suggestPeer", js.suggestPeer)
  30. admin.Set("startRPC", js.startRPC)
  31. admin.Set("stopRPC", js.stopRPC)
  32. admin.Set("nodeInfo", js.nodeInfo)
  33. admin.Set("peers", js.peers)
  34. admin.Set("newAccount", js.newAccount)
  35. admin.Set("unlock", js.unlock)
  36. admin.Set("import", js.importChain)
  37. admin.Set("export", js.exportChain)
  38. admin.Set("verbosity", js.verbosity)
  39. admin.Set("progress", js.downloadProgress)
  40. admin.Set("miner", struct{}{})
  41. t, _ = admin.Get("miner")
  42. miner := t.Object()
  43. miner.Set("start", js.startMining)
  44. miner.Set("stop", js.stopMining)
  45. miner.Set("hashrate", js.hashrate)
  46. miner.Set("setExtra", js.setExtra)
  47. admin.Set("debug", struct{}{})
  48. t, _ = admin.Get("debug")
  49. debug := t.Object()
  50. debug.Set("backtrace", js.backtrace)
  51. debug.Set("printBlock", js.printBlock)
  52. debug.Set("dumpBlock", js.dumpBlock)
  53. debug.Set("getBlockRlp", js.getBlockRlp)
  54. debug.Set("setHead", js.setHead)
  55. debug.Set("processBlock", js.debugBlock)
  56. }
  57. func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
  58. var block *types.Block
  59. if len(call.ArgumentList) > 0 {
  60. if call.Argument(0).IsNumber() {
  61. num, _ := call.Argument(0).ToInteger()
  62. block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
  63. } else if call.Argument(0).IsString() {
  64. hash, _ := call.Argument(0).ToString()
  65. block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
  66. } else {
  67. return nil, errors.New("invalid argument for dump. Either hex string or number")
  68. }
  69. return block, nil
  70. }
  71. return nil, errors.New("requires block number or block hash as argument")
  72. }
  73. type tx struct {
  74. tx *types.Transaction
  75. To string
  76. From string
  77. Nonce string
  78. Value string
  79. Data string
  80. GasLimit string
  81. GasPrice string
  82. }
  83. func newTx(t *types.Transaction) *tx {
  84. from, _ := t.From()
  85. var to string
  86. if t := t.To(); t != nil {
  87. to = t.Hex()
  88. }
  89. return &tx{
  90. tx: t,
  91. To: to,
  92. From: from.Hex(),
  93. Value: t.Amount.String(),
  94. Nonce: strconv.Itoa(int(t.Nonce())),
  95. Data: "0x" + common.Bytes2Hex(t.Data()),
  96. GasLimit: t.GasLimit.String(),
  97. GasPrice: t.GasPrice().String(),
  98. }
  99. }
  100. func (js *jsre) transactions(call otto.FunctionCall) otto.Value {
  101. txs := js.ethereum.TxPool().GetTransactions()
  102. ltxs := make([]*tx, len(txs))
  103. for i, tx := range txs {
  104. ltxs[i] = newTx(tx)
  105. }
  106. return js.re.ToVal(ltxs)
  107. }
  108. func (js *jsre) resend(call otto.FunctionCall) otto.Value {
  109. if len(call.ArgumentList) == 0 {
  110. fmt.Println("first argument must be a transaction")
  111. return otto.FalseValue()
  112. }
  113. v, err := call.Argument(0).Export()
  114. if err != nil {
  115. fmt.Println(err)
  116. return otto.FalseValue()
  117. }
  118. if tx, ok := v.(*tx); ok {
  119. gl, gp := tx.GasLimit, tx.GasPrice
  120. if len(call.ArgumentList) > 1 {
  121. gp = call.Argument(1).String()
  122. }
  123. if len(call.ArgumentList) > 2 {
  124. gl = call.Argument(2).String()
  125. }
  126. ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data)
  127. if err != nil {
  128. fmt.Println(err)
  129. return otto.FalseValue()
  130. }
  131. js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx})
  132. return js.re.ToVal(ret)
  133. }
  134. fmt.Println("first argument must be a transaction")
  135. return otto.FalseValue()
  136. }
  137. func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
  138. block, err := js.getBlock(call)
  139. if err != nil {
  140. fmt.Println(err)
  141. return otto.UndefinedValue()
  142. }
  143. if block == nil {
  144. fmt.Println("block not found")
  145. return otto.UndefinedValue()
  146. }
  147. old := vm.Debug
  148. vm.Debug = true
  149. _, err = js.ethereum.BlockProcessor().RetryProcess(block)
  150. if err != nil {
  151. glog.Infoln(err)
  152. }
  153. vm.Debug = old
  154. return otto.UndefinedValue()
  155. }
  156. func (js *jsre) setHead(call otto.FunctionCall) otto.Value {
  157. block, err := js.getBlock(call)
  158. if err != nil {
  159. fmt.Println(err)
  160. return otto.UndefinedValue()
  161. }
  162. if block == nil {
  163. fmt.Println("block not found")
  164. return otto.UndefinedValue()
  165. }
  166. js.ethereum.ChainManager().SetHead(block)
  167. return otto.UndefinedValue()
  168. }
  169. func (js *jsre) downloadProgress(call otto.FunctionCall) otto.Value {
  170. current, max := js.ethereum.Downloader().Stats()
  171. return js.re.ToVal(fmt.Sprintf("%d/%d", current, max))
  172. }
  173. func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
  174. block, err := js.getBlock(call)
  175. if err != nil {
  176. fmt.Println(err)
  177. return otto.UndefinedValue()
  178. }
  179. if block == nil {
  180. fmt.Println("block not found")
  181. return otto.UndefinedValue()
  182. }
  183. encoded, _ := rlp.EncodeToBytes(block)
  184. return js.re.ToVal(fmt.Sprintf("%x", encoded))
  185. }
  186. func (js *jsre) setExtra(call otto.FunctionCall) otto.Value {
  187. extra, err := call.Argument(0).ToString()
  188. if err != nil {
  189. fmt.Println(err)
  190. return otto.UndefinedValue()
  191. }
  192. if len(extra) > 1024 {
  193. fmt.Println("error: cannot exceed 1024 bytes")
  194. return otto.UndefinedValue()
  195. }
  196. js.ethereum.Miner().SetExtra([]byte(extra))
  197. return otto.UndefinedValue()
  198. }
  199. func (js *jsre) hashrate(otto.FunctionCall) otto.Value {
  200. return js.re.ToVal(js.ethereum.Miner().HashRate())
  201. }
  202. func (js *jsre) backtrace(call otto.FunctionCall) otto.Value {
  203. tracestr, err := call.Argument(0).ToString()
  204. if err != nil {
  205. fmt.Println(err)
  206. return otto.UndefinedValue()
  207. }
  208. glog.GetTraceLocation().Set(tracestr)
  209. return otto.UndefinedValue()
  210. }
  211. func (js *jsre) verbosity(call otto.FunctionCall) otto.Value {
  212. v, err := call.Argument(0).ToInteger()
  213. if err != nil {
  214. fmt.Println(err)
  215. return otto.UndefinedValue()
  216. }
  217. glog.SetV(int(v))
  218. return otto.UndefinedValue()
  219. }
  220. func (js *jsre) startMining(call otto.FunctionCall) otto.Value {
  221. _, err := call.Argument(0).ToInteger()
  222. if err != nil {
  223. fmt.Println(err)
  224. return otto.FalseValue()
  225. }
  226. // threads now ignored
  227. err = js.ethereum.StartMining()
  228. if err != nil {
  229. fmt.Println(err)
  230. return otto.FalseValue()
  231. }
  232. return otto.TrueValue()
  233. }
  234. func (js *jsre) stopMining(call otto.FunctionCall) otto.Value {
  235. js.ethereum.StopMining()
  236. return otto.TrueValue()
  237. }
  238. func (js *jsre) startRPC(call otto.FunctionCall) otto.Value {
  239. addr, err := call.Argument(0).ToString()
  240. if err != nil {
  241. fmt.Println(err)
  242. return otto.FalseValue()
  243. }
  244. port, err := call.Argument(1).ToInteger()
  245. if err != nil {
  246. fmt.Println(err)
  247. return otto.FalseValue()
  248. }
  249. corsDomain := js.corsDomain
  250. if len(call.ArgumentList) > 2 {
  251. corsDomain, err = call.Argument(2).ToString()
  252. if err != nil {
  253. fmt.Println(err)
  254. return otto.FalseValue()
  255. }
  256. }
  257. config := rpc.RpcConfig{
  258. ListenAddress: addr,
  259. ListenPort: uint(port),
  260. CorsDomain: corsDomain,
  261. }
  262. xeth := xeth.New(js.ethereum, nil)
  263. err = rpc.Start(xeth, config)
  264. if err != nil {
  265. fmt.Printf(err.Error())
  266. return otto.FalseValue()
  267. }
  268. return otto.TrueValue()
  269. }
  270. func (js *jsre) stopRPC(call otto.FunctionCall) otto.Value {
  271. if rpc.Stop() == nil {
  272. return otto.TrueValue()
  273. }
  274. return otto.FalseValue()
  275. }
  276. func (js *jsre) suggestPeer(call otto.FunctionCall) otto.Value {
  277. nodeURL, err := call.Argument(0).ToString()
  278. if err != nil {
  279. fmt.Println(err)
  280. return otto.FalseValue()
  281. }
  282. err = js.ethereum.SuggestPeer(nodeURL)
  283. if err != nil {
  284. fmt.Println(err)
  285. return otto.FalseValue()
  286. }
  287. return otto.TrueValue()
  288. }
  289. func (js *jsre) unlock(call otto.FunctionCall) otto.Value {
  290. addr, err := call.Argument(0).ToString()
  291. if err != nil {
  292. fmt.Println(err)
  293. return otto.FalseValue()
  294. }
  295. seconds, err := call.Argument(2).ToInteger()
  296. if err != nil {
  297. fmt.Println(err)
  298. return otto.FalseValue()
  299. }
  300. arg := call.Argument(1)
  301. var passphrase string
  302. if arg.IsUndefined() {
  303. fmt.Println("Please enter a passphrase now.")
  304. passphrase, err = readPassword("Passphrase: ", true)
  305. if err != nil {
  306. utils.Fatalf("%v", err)
  307. }
  308. } else {
  309. passphrase, err = arg.ToString()
  310. if err != nil {
  311. fmt.Println(err)
  312. return otto.FalseValue()
  313. }
  314. }
  315. am := js.ethereum.AccountManager()
  316. err = am.TimedUnlock(common.FromHex(addr), passphrase, time.Duration(seconds)*time.Second)
  317. if err != nil {
  318. fmt.Printf("Unlock account failed '%v'\n", err)
  319. return otto.FalseValue()
  320. }
  321. return otto.TrueValue()
  322. }
  323. func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
  324. arg := call.Argument(0)
  325. var passphrase string
  326. if arg.IsUndefined() {
  327. fmt.Println("The new account will be encrypted with a passphrase.")
  328. fmt.Println("Please enter a passphrase now.")
  329. auth, err := readPassword("Passphrase: ", true)
  330. if err != nil {
  331. utils.Fatalf("%v", err)
  332. }
  333. confirm, err := readPassword("Repeat Passphrase: ", false)
  334. if err != nil {
  335. utils.Fatalf("%v", err)
  336. }
  337. if auth != confirm {
  338. utils.Fatalf("Passphrases did not match.")
  339. }
  340. passphrase = auth
  341. } else {
  342. var err error
  343. passphrase, err = arg.ToString()
  344. if err != nil {
  345. fmt.Println(err)
  346. return otto.FalseValue()
  347. }
  348. }
  349. acct, err := js.ethereum.AccountManager().NewAccount(passphrase)
  350. if err != nil {
  351. fmt.Printf("Could not create the account: %v", err)
  352. return otto.UndefinedValue()
  353. }
  354. return js.re.ToVal("0x" + common.Bytes2Hex(acct.Address))
  355. }
  356. func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value {
  357. return js.re.ToVal(js.ethereum.NodeInfo())
  358. }
  359. func (js *jsre) peers(call otto.FunctionCall) otto.Value {
  360. return js.re.ToVal(js.ethereum.PeersInfo())
  361. }
  362. func (js *jsre) importChain(call otto.FunctionCall) otto.Value {
  363. if len(call.ArgumentList) == 0 {
  364. fmt.Println("err: require file name")
  365. return otto.FalseValue()
  366. }
  367. fn, err := call.Argument(0).ToString()
  368. if err != nil {
  369. fmt.Println(err)
  370. return otto.FalseValue()
  371. }
  372. if err := utils.ImportChain(js.ethereum.ChainManager(), fn); err != nil {
  373. fmt.Println("Import error: ", err)
  374. return otto.FalseValue()
  375. }
  376. return otto.TrueValue()
  377. }
  378. func (js *jsre) exportChain(call otto.FunctionCall) otto.Value {
  379. if len(call.ArgumentList) == 0 {
  380. fmt.Println("err: require file name")
  381. return otto.FalseValue()
  382. }
  383. fn, err := call.Argument(0).ToString()
  384. if err != nil {
  385. fmt.Println(err)
  386. return otto.FalseValue()
  387. }
  388. if err := utils.ExportChain(js.ethereum.ChainManager(), fn); err != nil {
  389. fmt.Println(err)
  390. return otto.FalseValue()
  391. }
  392. return otto.TrueValue()
  393. }
  394. func (js *jsre) printBlock(call otto.FunctionCall) otto.Value {
  395. var block *types.Block
  396. if len(call.ArgumentList) > 0 {
  397. if call.Argument(0).IsNumber() {
  398. num, _ := call.Argument(0).ToInteger()
  399. block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
  400. } else if call.Argument(0).IsString() {
  401. hash, _ := call.Argument(0).ToString()
  402. block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
  403. } else {
  404. fmt.Println("invalid argument for dump. Either hex string or number")
  405. }
  406. } else {
  407. block = js.ethereum.ChainManager().CurrentBlock()
  408. }
  409. if block == nil {
  410. fmt.Println("block not found")
  411. return otto.UndefinedValue()
  412. }
  413. fmt.Println(block)
  414. return otto.UndefinedValue()
  415. }
  416. func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
  417. var block *types.Block
  418. if len(call.ArgumentList) > 0 {
  419. if call.Argument(0).IsNumber() {
  420. num, _ := call.Argument(0).ToInteger()
  421. block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
  422. } else if call.Argument(0).IsString() {
  423. hash, _ := call.Argument(0).ToString()
  424. block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
  425. } else {
  426. fmt.Println("invalid argument for dump. Either hex string or number")
  427. }
  428. } else {
  429. block = js.ethereum.ChainManager().CurrentBlock()
  430. }
  431. if block == nil {
  432. fmt.Println("block not found")
  433. return otto.UndefinedValue()
  434. }
  435. statedb := state.New(block.Root(), js.ethereum.StateDb())
  436. dump := statedb.RawDump()
  437. return js.re.ToVal(dump)
  438. }