admin.go 10 KB

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