admin.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "math/big"
  7. "strconv"
  8. "time"
  9. "github.com/rcrowley/go-metrics"
  10. "github.com/ethereum/ethash"
  11. "github.com/ethereum/go-ethereum/accounts"
  12. "github.com/ethereum/go-ethereum/cmd/utils"
  13. "github.com/ethereum/go-ethereum/common"
  14. "github.com/ethereum/go-ethereum/common/compiler"
  15. "github.com/ethereum/go-ethereum/common/natspec"
  16. "github.com/ethereum/go-ethereum/common/resolver"
  17. "github.com/ethereum/go-ethereum/core/state"
  18. "github.com/ethereum/go-ethereum/core/types"
  19. "github.com/ethereum/go-ethereum/core/vm"
  20. "github.com/ethereum/go-ethereum/crypto"
  21. "github.com/ethereum/go-ethereum/logger/glog"
  22. "github.com/ethereum/go-ethereum/rlp"
  23. "github.com/ethereum/go-ethereum/rpc"
  24. "github.com/ethereum/go-ethereum/xeth"
  25. "github.com/robertkrimen/otto"
  26. "gopkg.in/fatih/set.v0"
  27. )
  28. /*
  29. node admin bindings
  30. */
  31. func (js *jsre) adminBindings() {
  32. ethO, _ := js.re.Get("eth")
  33. eth := ethO.Object()
  34. eth.Set("pendingTransactions", js.pendingTransactions)
  35. eth.Set("resend", js.resend)
  36. eth.Set("sign", js.sign)
  37. js.re.Set("admin", struct{}{})
  38. t, _ := js.re.Get("admin")
  39. admin := t.Object()
  40. admin.Set("addPeer", js.addPeer)
  41. admin.Set("startRPC", js.startRPC)
  42. admin.Set("stopRPC", js.stopRPC)
  43. admin.Set("nodeInfo", js.nodeInfo)
  44. admin.Set("peers", js.peers)
  45. admin.Set("newAccount", js.newAccount)
  46. admin.Set("unlock", js.unlock)
  47. admin.Set("import", js.importChain)
  48. admin.Set("export", js.exportChain)
  49. admin.Set("verbosity", js.verbosity)
  50. admin.Set("progress", js.syncProgress)
  51. admin.Set("setSolc", js.setSolc)
  52. admin.Set("contractInfo", struct{}{})
  53. t, _ = admin.Get("contractInfo")
  54. cinfo := t.Object()
  55. // newRegistry officially not documented temporary option
  56. cinfo.Set("start", js.startNatSpec)
  57. cinfo.Set("stop", js.stopNatSpec)
  58. cinfo.Set("newRegistry", js.newRegistry)
  59. cinfo.Set("get", js.getContractInfo)
  60. cinfo.Set("register", js.register)
  61. cinfo.Set("registerUrl", js.registerUrl)
  62. // cinfo.Set("verify", js.verify)
  63. admin.Set("miner", struct{}{})
  64. t, _ = admin.Get("miner")
  65. miner := t.Object()
  66. miner.Set("start", js.startMining)
  67. miner.Set("stop", js.stopMining)
  68. miner.Set("hashrate", js.hashrate)
  69. miner.Set("setExtra", js.setExtra)
  70. miner.Set("setGasPrice", js.setGasPrice)
  71. miner.Set("startAutoDAG", js.startAutoDAG)
  72. miner.Set("stopAutoDAG", js.stopAutoDAG)
  73. miner.Set("makeDAG", js.makeDAG)
  74. admin.Set("txPool", struct{}{})
  75. t, _ = admin.Get("txPool")
  76. txPool := t.Object()
  77. txPool.Set("pending", js.allPendingTransactions)
  78. txPool.Set("queued", js.allQueuedTransactions)
  79. admin.Set("debug", struct{}{})
  80. t, _ = admin.Get("debug")
  81. debug := t.Object()
  82. js.re.Set("sleep", js.sleep)
  83. debug.Set("backtrace", js.backtrace)
  84. debug.Set("printBlock", js.printBlock)
  85. debug.Set("dumpBlock", js.dumpBlock)
  86. debug.Set("getBlockRlp", js.getBlockRlp)
  87. debug.Set("setHead", js.setHead)
  88. debug.Set("processBlock", js.debugBlock)
  89. debug.Set("seedhash", js.seedHash)
  90. debug.Set("insertBlock", js.insertBlockRlp)
  91. // undocumented temporary
  92. debug.Set("waitForBlocks", js.waitForBlocks)
  93. admin.Set("metrics", js.metrics)
  94. }
  95. // generic helper to getBlock by Number/Height or Hex depending on autodetected input
  96. // if argument is missing the current block is returned
  97. // if block is not found or there is problem with decoding
  98. // the appropriate value is returned and block is guaranteed to be nil
  99. func (js *jsre) getBlock(call otto.FunctionCall) (*types.Block, error) {
  100. var block *types.Block
  101. if len(call.ArgumentList) > 0 {
  102. if call.Argument(0).IsNumber() {
  103. num, _ := call.Argument(0).ToInteger()
  104. block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
  105. } else if call.Argument(0).IsString() {
  106. hash, _ := call.Argument(0).ToString()
  107. block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
  108. } else {
  109. return nil, errors.New("invalid argument for dump. Either hex string or number")
  110. }
  111. } else {
  112. block = js.ethereum.ChainManager().CurrentBlock()
  113. }
  114. if block == nil {
  115. return nil, errors.New("block not found")
  116. }
  117. return block, nil
  118. }
  119. func (js *jsre) seedHash(call otto.FunctionCall) otto.Value {
  120. if len(call.ArgumentList) > 0 {
  121. if call.Argument(0).IsNumber() {
  122. num, _ := call.Argument(0).ToInteger()
  123. hash, err := ethash.GetSeedHash(uint64(num))
  124. if err != nil {
  125. fmt.Println(err)
  126. return otto.UndefinedValue()
  127. }
  128. v, _ := call.Otto.ToValue(fmt.Sprintf("0x%x", hash))
  129. return v
  130. } else {
  131. fmt.Println("arg not a number")
  132. }
  133. } else {
  134. fmt.Println("requires number argument")
  135. }
  136. return otto.UndefinedValue()
  137. }
  138. func (js *jsre) allPendingTransactions(call otto.FunctionCall) otto.Value {
  139. txs := js.ethereum.TxPool().GetTransactions()
  140. ltxs := make([]*tx, len(txs))
  141. for i, tx := range txs {
  142. // no need to check err
  143. ltxs[i] = newTx(tx)
  144. }
  145. v, _ := call.Otto.ToValue(ltxs)
  146. return v
  147. }
  148. func (js *jsre) allQueuedTransactions(call otto.FunctionCall) otto.Value {
  149. txs := js.ethereum.TxPool().GetQueuedTransactions()
  150. ltxs := make([]*tx, len(txs))
  151. for i, tx := range txs {
  152. // no need to check err
  153. ltxs[i] = newTx(tx)
  154. }
  155. v, _ := call.Otto.ToValue(ltxs)
  156. return v
  157. }
  158. func (js *jsre) pendingTransactions(call otto.FunctionCall) otto.Value {
  159. txs := js.ethereum.TxPool().GetTransactions()
  160. // grab the accounts from the account manager. This will help with determening which
  161. // transactions should be returned.
  162. accounts, err := js.ethereum.AccountManager().Accounts()
  163. if err != nil {
  164. fmt.Println(err)
  165. return otto.UndefinedValue()
  166. }
  167. // Add the accouns to a new set
  168. accountSet := set.New()
  169. for _, account := range accounts {
  170. accountSet.Add(account.Address)
  171. }
  172. //ltxs := make([]*tx, len(txs))
  173. var ltxs []*tx
  174. for _, tx := range txs {
  175. if from, _ := tx.From(); accountSet.Has(from) {
  176. ltxs = append(ltxs, newTx(tx))
  177. }
  178. }
  179. v, _ := call.Otto.ToValue(ltxs)
  180. return v
  181. }
  182. func (js *jsre) resend(call otto.FunctionCall) otto.Value {
  183. if len(call.ArgumentList) == 0 {
  184. fmt.Println("first argument must be a transaction")
  185. return otto.FalseValue()
  186. }
  187. v, err := call.Argument(0).Export()
  188. if err != nil {
  189. fmt.Println(err)
  190. return otto.FalseValue()
  191. }
  192. if tx, ok := v.(*tx); ok {
  193. gl, gp := tx.GasLimit, tx.GasPrice
  194. if len(call.ArgumentList) > 1 {
  195. gp = call.Argument(1).String()
  196. }
  197. if len(call.ArgumentList) > 2 {
  198. gl = call.Argument(2).String()
  199. }
  200. ret, err := js.xeth.Transact(tx.From, tx.To, tx.Nonce, tx.Value, gl, gp, tx.Data)
  201. if err != nil {
  202. fmt.Println(err)
  203. return otto.FalseValue()
  204. }
  205. js.ethereum.TxPool().RemoveTransactions(types.Transactions{tx.tx})
  206. v, _ := call.Otto.ToValue(ret)
  207. return v
  208. }
  209. fmt.Println("first argument must be a transaction")
  210. return otto.FalseValue()
  211. }
  212. func (js *jsre) sign(call otto.FunctionCall) otto.Value {
  213. if len(call.ArgumentList) != 2 {
  214. fmt.Println("requires 2 arguments: eth.sign(signer, data)")
  215. return otto.UndefinedValue()
  216. }
  217. signer, err := call.Argument(0).ToString()
  218. if err != nil {
  219. fmt.Println(err)
  220. return otto.UndefinedValue()
  221. }
  222. data, err := call.Argument(1).ToString()
  223. if err != nil {
  224. fmt.Println(err)
  225. return otto.UndefinedValue()
  226. }
  227. signed, err := js.xeth.Sign(signer, data, false)
  228. if err != nil {
  229. fmt.Println(err)
  230. return otto.UndefinedValue()
  231. }
  232. v, _ := call.Otto.ToValue(signed)
  233. return v
  234. }
  235. func (js *jsre) debugBlock(call otto.FunctionCall) otto.Value {
  236. block, err := js.getBlock(call)
  237. if err != nil {
  238. fmt.Println(err)
  239. return otto.UndefinedValue()
  240. }
  241. tstart := time.Now()
  242. old := vm.Debug
  243. if len(call.ArgumentList) > 1 {
  244. vm.Debug, _ = call.Argument(1).ToBoolean()
  245. }
  246. _, err = js.ethereum.BlockProcessor().RetryProcess(block)
  247. if err != nil {
  248. fmt.Println(err)
  249. r, _ := call.Otto.ToValue(map[string]interface{}{"success": false, "time": time.Since(tstart).Seconds()})
  250. return r
  251. }
  252. vm.Debug = old
  253. r, _ := call.Otto.ToValue(map[string]interface{}{"success": true, "time": time.Since(tstart).Seconds()})
  254. return r
  255. }
  256. func (js *jsre) insertBlockRlp(call otto.FunctionCall) otto.Value {
  257. tstart := time.Now()
  258. var block types.Block
  259. if call.Argument(0).IsString() {
  260. blockRlp, _ := call.Argument(0).ToString()
  261. err := rlp.DecodeBytes(common.Hex2Bytes(blockRlp), &block)
  262. if err != nil {
  263. fmt.Println(err)
  264. return otto.UndefinedValue()
  265. }
  266. }
  267. old := vm.Debug
  268. vm.Debug = true
  269. _, err := js.ethereum.BlockProcessor().RetryProcess(&block)
  270. if err != nil {
  271. fmt.Println(err)
  272. r, _ := call.Otto.ToValue(map[string]interface{}{"success": false, "time": time.Since(tstart).Seconds()})
  273. return r
  274. }
  275. vm.Debug = old
  276. r, _ := call.Otto.ToValue(map[string]interface{}{"success": true, "time": time.Since(tstart).Seconds()})
  277. return r
  278. }
  279. func (js *jsre) setHead(call otto.FunctionCall) otto.Value {
  280. block, err := js.getBlock(call)
  281. if err != nil {
  282. fmt.Println(err)
  283. return otto.UndefinedValue()
  284. }
  285. js.ethereum.ChainManager().SetHead(block)
  286. return otto.UndefinedValue()
  287. }
  288. func (js *jsre) syncProgress(call otto.FunctionCall) otto.Value {
  289. pending, cached, importing, eta := js.ethereum.Downloader().Stats()
  290. v, _ := call.Otto.ToValue(map[string]interface{}{
  291. "pending": pending,
  292. "cached": cached,
  293. "importing": importing,
  294. "estimate": (eta / time.Second * time.Second).String(),
  295. })
  296. return v
  297. }
  298. func (js *jsre) getBlockRlp(call otto.FunctionCall) otto.Value {
  299. block, err := js.getBlock(call)
  300. if err != nil {
  301. fmt.Println(err)
  302. return otto.UndefinedValue()
  303. }
  304. encoded, _ := rlp.EncodeToBytes(block)
  305. v, _ := call.Otto.ToValue(fmt.Sprintf("%x", encoded))
  306. return v
  307. }
  308. func (js *jsre) setExtra(call otto.FunctionCall) otto.Value {
  309. extra, err := call.Argument(0).ToString()
  310. if err != nil {
  311. fmt.Println(err)
  312. return otto.UndefinedValue()
  313. }
  314. if len(extra) > 1024 {
  315. fmt.Println("error: cannot exceed 1024 bytes")
  316. return otto.UndefinedValue()
  317. }
  318. js.ethereum.Miner().SetExtra([]byte(extra))
  319. return otto.UndefinedValue()
  320. }
  321. func (js *jsre) setGasPrice(call otto.FunctionCall) otto.Value {
  322. gasPrice, err := call.Argument(0).ToString()
  323. if err != nil {
  324. fmt.Println(err)
  325. return otto.UndefinedValue()
  326. }
  327. js.ethereum.Miner().SetGasPrice(common.String2Big(gasPrice))
  328. return otto.UndefinedValue()
  329. }
  330. func (js *jsre) hashrate(call otto.FunctionCall) otto.Value {
  331. v, _ := call.Otto.ToValue(js.ethereum.Miner().HashRate())
  332. return v
  333. }
  334. func (js *jsre) makeDAG(call otto.FunctionCall) otto.Value {
  335. blockNumber, err := call.Argument(1).ToInteger()
  336. if err != nil {
  337. fmt.Println(err)
  338. return otto.FalseValue()
  339. }
  340. err = ethash.MakeDAG(uint64(blockNumber), "")
  341. if err != nil {
  342. return otto.FalseValue()
  343. }
  344. return otto.TrueValue()
  345. }
  346. func (js *jsre) startAutoDAG(otto.FunctionCall) otto.Value {
  347. js.ethereum.StartAutoDAG()
  348. return otto.TrueValue()
  349. }
  350. func (js *jsre) stopAutoDAG(otto.FunctionCall) otto.Value {
  351. js.ethereum.StopAutoDAG()
  352. return otto.TrueValue()
  353. }
  354. func (js *jsre) backtrace(call otto.FunctionCall) otto.Value {
  355. tracestr, err := call.Argument(0).ToString()
  356. if err != nil {
  357. fmt.Println(err)
  358. return otto.UndefinedValue()
  359. }
  360. glog.GetTraceLocation().Set(tracestr)
  361. return otto.UndefinedValue()
  362. }
  363. func (js *jsre) verbosity(call otto.FunctionCall) otto.Value {
  364. v, err := call.Argument(0).ToInteger()
  365. if err != nil {
  366. fmt.Println(err)
  367. return otto.UndefinedValue()
  368. }
  369. glog.SetV(int(v))
  370. return otto.UndefinedValue()
  371. }
  372. func (js *jsre) startMining(call otto.FunctionCall) otto.Value {
  373. var (
  374. threads int64
  375. err error
  376. )
  377. if len(call.ArgumentList) > 0 {
  378. threads, err = call.Argument(0).ToInteger()
  379. if err != nil {
  380. fmt.Println(err)
  381. return otto.FalseValue()
  382. }
  383. } else {
  384. threads = int64(js.ethereum.MinerThreads)
  385. }
  386. // switch on DAG autogeneration when miner starts
  387. js.ethereum.StartAutoDAG()
  388. err = js.ethereum.StartMining(int(threads))
  389. if err != nil {
  390. fmt.Println(err)
  391. return otto.FalseValue()
  392. }
  393. return otto.TrueValue()
  394. }
  395. func (js *jsre) stopMining(call otto.FunctionCall) otto.Value {
  396. js.ethereum.StopMining()
  397. js.ethereum.StopAutoDAG()
  398. return otto.TrueValue()
  399. }
  400. func (js *jsre) startRPC(call otto.FunctionCall) otto.Value {
  401. addr, err := call.Argument(0).ToString()
  402. if err != nil {
  403. fmt.Println(err)
  404. return otto.FalseValue()
  405. }
  406. port, err := call.Argument(1).ToInteger()
  407. if err != nil {
  408. fmt.Println(err)
  409. return otto.FalseValue()
  410. }
  411. corsDomain := js.corsDomain
  412. if len(call.ArgumentList) > 2 {
  413. corsDomain, err = call.Argument(2).ToString()
  414. if err != nil {
  415. fmt.Println(err)
  416. return otto.FalseValue()
  417. }
  418. }
  419. config := rpc.RpcConfig{
  420. ListenAddress: addr,
  421. ListenPort: uint(port),
  422. CorsDomain: corsDomain,
  423. }
  424. xeth := xeth.New(js.ethereum, nil)
  425. err = rpc.Start(xeth, config)
  426. if err != nil {
  427. fmt.Println(err)
  428. return otto.FalseValue()
  429. }
  430. return otto.TrueValue()
  431. }
  432. func (js *jsre) stopRPC(call otto.FunctionCall) otto.Value {
  433. if rpc.Stop() == nil {
  434. return otto.TrueValue()
  435. }
  436. return otto.FalseValue()
  437. }
  438. func (js *jsre) addPeer(call otto.FunctionCall) otto.Value {
  439. nodeURL, err := call.Argument(0).ToString()
  440. if err != nil {
  441. fmt.Println(err)
  442. return otto.FalseValue()
  443. }
  444. err = js.ethereum.AddPeer(nodeURL)
  445. if err != nil {
  446. fmt.Println(err)
  447. return otto.FalseValue()
  448. }
  449. return otto.TrueValue()
  450. }
  451. func (js *jsre) unlock(call otto.FunctionCall) otto.Value {
  452. addr, err := call.Argument(0).ToString()
  453. if err != nil {
  454. fmt.Println(err)
  455. return otto.FalseValue()
  456. }
  457. seconds, err := call.Argument(2).ToInteger()
  458. if err != nil {
  459. fmt.Println(err)
  460. return otto.FalseValue()
  461. }
  462. if seconds == 0 {
  463. seconds = accounts.DefaultAccountUnlockDuration
  464. }
  465. arg := call.Argument(1)
  466. var passphrase string
  467. if arg.IsUndefined() {
  468. fmt.Println("Please enter a passphrase now.")
  469. passphrase, err = utils.PromptPassword("Passphrase: ", true)
  470. if err != nil {
  471. fmt.Println(err)
  472. return otto.FalseValue()
  473. }
  474. } else {
  475. passphrase, err = arg.ToString()
  476. if err != nil {
  477. fmt.Println(err)
  478. return otto.FalseValue()
  479. }
  480. }
  481. am := js.ethereum.AccountManager()
  482. err = am.TimedUnlock(common.HexToAddress(addr), passphrase, time.Duration(seconds)*time.Second)
  483. if err != nil {
  484. fmt.Printf("Unlock account failed '%v'\n", err)
  485. return otto.FalseValue()
  486. }
  487. return otto.TrueValue()
  488. }
  489. func (js *jsre) newAccount(call otto.FunctionCall) otto.Value {
  490. arg := call.Argument(0)
  491. var passphrase string
  492. if arg.IsUndefined() {
  493. fmt.Println("The new account will be encrypted with a passphrase.")
  494. fmt.Println("Please enter a passphrase now.")
  495. auth, err := utils.PromptPassword("Passphrase: ", true)
  496. if err != nil {
  497. fmt.Println(err)
  498. return otto.FalseValue()
  499. }
  500. confirm, err := utils.PromptPassword("Repeat Passphrase: ", false)
  501. if err != nil {
  502. fmt.Println(err)
  503. return otto.FalseValue()
  504. }
  505. if auth != confirm {
  506. fmt.Println("Passphrases did not match.")
  507. return otto.FalseValue()
  508. }
  509. passphrase = auth
  510. } else {
  511. var err error
  512. passphrase, err = arg.ToString()
  513. if err != nil {
  514. fmt.Println(err)
  515. return otto.FalseValue()
  516. }
  517. }
  518. acct, err := js.ethereum.AccountManager().NewAccount(passphrase)
  519. if err != nil {
  520. fmt.Printf("Could not create the account: %v", err)
  521. return otto.UndefinedValue()
  522. }
  523. v, _ := call.Otto.ToValue(acct.Address.Hex())
  524. return v
  525. }
  526. func (js *jsre) nodeInfo(call otto.FunctionCall) otto.Value {
  527. v, _ := call.Otto.ToValue(js.ethereum.NodeInfo())
  528. return v
  529. }
  530. func (js *jsre) peers(call otto.FunctionCall) otto.Value {
  531. v, _ := call.Otto.ToValue(js.ethereum.PeersInfo())
  532. return v
  533. }
  534. func (js *jsre) importChain(call otto.FunctionCall) otto.Value {
  535. if len(call.ArgumentList) == 0 {
  536. fmt.Println("require file name. admin.importChain(filename)")
  537. return otto.FalseValue()
  538. }
  539. fn, err := call.Argument(0).ToString()
  540. if err != nil {
  541. fmt.Println(err)
  542. return otto.FalseValue()
  543. }
  544. if err := utils.ImportChain(js.ethereum.ChainManager(), fn); err != nil {
  545. fmt.Println("Import error: ", err)
  546. return otto.FalseValue()
  547. }
  548. return otto.TrueValue()
  549. }
  550. func (js *jsre) exportChain(call otto.FunctionCall) otto.Value {
  551. if len(call.ArgumentList) == 0 {
  552. fmt.Println("require file name: admin.exportChain(filename)")
  553. return otto.FalseValue()
  554. }
  555. fn, err := call.Argument(0).ToString()
  556. if err != nil {
  557. fmt.Println(err)
  558. return otto.FalseValue()
  559. }
  560. if err := utils.ExportChain(js.ethereum.ChainManager(), fn); err != nil {
  561. fmt.Println(err)
  562. return otto.FalseValue()
  563. }
  564. return otto.TrueValue()
  565. }
  566. func (js *jsre) printBlock(call otto.FunctionCall) otto.Value {
  567. block, err := js.getBlock(call)
  568. if err != nil {
  569. fmt.Println(err)
  570. return otto.UndefinedValue()
  571. }
  572. fmt.Println(block)
  573. return otto.UndefinedValue()
  574. }
  575. func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
  576. block, err := js.getBlock(call)
  577. if err != nil {
  578. fmt.Println(err)
  579. return otto.UndefinedValue()
  580. }
  581. statedb := state.New(block.Root(), js.ethereum.StateDb())
  582. dump := statedb.RawDump()
  583. v, _ := call.Otto.ToValue(dump)
  584. return v
  585. }
  586. func (js *jsre) waitForBlocks(call otto.FunctionCall) otto.Value {
  587. if len(call.ArgumentList) > 2 {
  588. fmt.Println("requires 0, 1 or 2 arguments: admin.debug.waitForBlock(minHeight, timeout)")
  589. return otto.FalseValue()
  590. }
  591. var n, timeout int64
  592. var timer <-chan time.Time
  593. var height *big.Int
  594. var err error
  595. args := len(call.ArgumentList)
  596. if args == 2 {
  597. timeout, err = call.Argument(1).ToInteger()
  598. if err != nil {
  599. fmt.Println(err)
  600. return otto.UndefinedValue()
  601. }
  602. timer = time.NewTimer(time.Duration(timeout) * time.Second).C
  603. }
  604. if args >= 1 {
  605. n, err = call.Argument(0).ToInteger()
  606. if err != nil {
  607. fmt.Println(err)
  608. return otto.UndefinedValue()
  609. }
  610. height = big.NewInt(n)
  611. }
  612. if args == 0 {
  613. height = js.xeth.CurrentBlock().Number()
  614. height.Add(height, common.Big1)
  615. }
  616. wait := js.wait
  617. js.wait <- height
  618. select {
  619. case <-timer:
  620. // if times out make sure the xeth loop does not block
  621. go func() {
  622. select {
  623. case wait <- nil:
  624. case <-wait:
  625. }
  626. }()
  627. return otto.UndefinedValue()
  628. case height = <-wait:
  629. }
  630. v, _ := call.Otto.ToValue(height.Uint64())
  631. return v
  632. }
  633. func (js *jsre) metrics(call otto.FunctionCall) otto.Value {
  634. // Iterate over all the metrics, and just dump for now
  635. counters := make(map[string]interface{})
  636. metrics.DefaultRegistry.Each(func(name string, metric interface{}) {
  637. switch metric := metric.(type) {
  638. case metrics.Meter:
  639. counters[name+"( 1 min)"] = int(metric.Rate1() * 60)
  640. counters[name+"( 5 min)"] = int(metric.Rate5() * 300)
  641. counters[name+"(15 min)"] = int(metric.Rate15() * 900)
  642. default:
  643. counters[name] = "Unknown metric type"
  644. }
  645. })
  646. // Flatten the counters into some metrics and return
  647. v, _ := call.Otto.ToValue(counters)
  648. return v
  649. }
  650. func (js *jsre) sleep(call otto.FunctionCall) otto.Value {
  651. sec, err := call.Argument(0).ToInteger()
  652. if err != nil {
  653. fmt.Println(err)
  654. return otto.FalseValue()
  655. }
  656. time.Sleep(time.Duration(sec) * time.Second)
  657. return otto.UndefinedValue()
  658. }
  659. func (js *jsre) setSolc(call otto.FunctionCall) otto.Value {
  660. if len(call.ArgumentList) != 1 {
  661. fmt.Println("needs 1 argument: admin.contractInfo.setSolc(solcPath)")
  662. return otto.FalseValue()
  663. }
  664. solcPath, err := call.Argument(0).ToString()
  665. if err != nil {
  666. return otto.FalseValue()
  667. }
  668. solc, err := js.xeth.SetSolc(solcPath)
  669. if err != nil {
  670. fmt.Println(err)
  671. return otto.FalseValue()
  672. }
  673. fmt.Println(solc.Info())
  674. return otto.TrueValue()
  675. }
  676. func (js *jsre) register(call otto.FunctionCall) otto.Value {
  677. if len(call.ArgumentList) != 4 {
  678. fmt.Println("requires 4 arguments: admin.contractInfo.register(fromaddress, contractaddress, contract, filename)")
  679. return otto.UndefinedValue()
  680. }
  681. sender, err := call.Argument(0).ToString()
  682. if err != nil {
  683. fmt.Println(err)
  684. return otto.UndefinedValue()
  685. }
  686. address, err := call.Argument(1).ToString()
  687. if err != nil {
  688. fmt.Println(err)
  689. return otto.UndefinedValue()
  690. }
  691. raw, err := call.Argument(2).Export()
  692. if err != nil {
  693. fmt.Println(err)
  694. return otto.UndefinedValue()
  695. }
  696. jsonraw, err := json.Marshal(raw)
  697. if err != nil {
  698. fmt.Println(err)
  699. return otto.UndefinedValue()
  700. }
  701. var contract compiler.Contract
  702. err = json.Unmarshal(jsonraw, &contract)
  703. if err != nil {
  704. fmt.Println(err)
  705. return otto.UndefinedValue()
  706. }
  707. filename, err := call.Argument(3).ToString()
  708. if err != nil {
  709. fmt.Println(err)
  710. return otto.UndefinedValue()
  711. }
  712. contenthash, err := compiler.ExtractInfo(&contract, filename)
  713. if err != nil {
  714. fmt.Println(err)
  715. return otto.UndefinedValue()
  716. }
  717. // sender and contract address are passed as hex strings
  718. codeb := js.xeth.CodeAtBytes(address)
  719. codehash := common.BytesToHash(crypto.Sha3(codeb))
  720. if err != nil {
  721. fmt.Println(err)
  722. return otto.UndefinedValue()
  723. }
  724. registry := resolver.New(js.xeth)
  725. _, err = registry.RegisterContentHash(common.HexToAddress(sender), codehash, contenthash)
  726. if err != nil {
  727. fmt.Println(err)
  728. return otto.UndefinedValue()
  729. }
  730. v, _ := call.Otto.ToValue(contenthash.Hex())
  731. return v
  732. }
  733. func (js *jsre) registerUrl(call otto.FunctionCall) otto.Value {
  734. if len(call.ArgumentList) != 3 {
  735. fmt.Println("requires 3 arguments: admin.contractInfo.register(fromaddress, contenthash, filename)")
  736. return otto.FalseValue()
  737. }
  738. sender, err := call.Argument(0).ToString()
  739. if err != nil {
  740. fmt.Println(err)
  741. return otto.FalseValue()
  742. }
  743. contenthash, err := call.Argument(1).ToString()
  744. if err != nil {
  745. fmt.Println(err)
  746. return otto.FalseValue()
  747. }
  748. url, err := call.Argument(2).ToString()
  749. if err != nil {
  750. fmt.Println(err)
  751. return otto.FalseValue()
  752. }
  753. registry := resolver.New(js.xeth)
  754. _, err = registry.RegisterUrl(common.HexToAddress(sender), common.HexToHash(contenthash), url)
  755. if err != nil {
  756. fmt.Println(err)
  757. return otto.FalseValue()
  758. }
  759. return otto.TrueValue()
  760. }
  761. func (js *jsre) getContractInfo(call otto.FunctionCall) otto.Value {
  762. if len(call.ArgumentList) != 1 {
  763. fmt.Println("requires 1 argument: admin.contractInfo.register(contractaddress)")
  764. return otto.FalseValue()
  765. }
  766. addr, err := call.Argument(0).ToString()
  767. if err != nil {
  768. fmt.Println(err)
  769. return otto.FalseValue()
  770. }
  771. infoDoc, err := natspec.FetchDocsForContract(addr, js.xeth, ds)
  772. if err != nil {
  773. fmt.Println(err)
  774. return otto.UndefinedValue()
  775. }
  776. var info compiler.ContractInfo
  777. err = json.Unmarshal(infoDoc, &info)
  778. if err != nil {
  779. fmt.Println(err)
  780. return otto.UndefinedValue()
  781. }
  782. v, _ := call.Otto.ToValue(info)
  783. return v
  784. }
  785. func (js *jsre) startNatSpec(call otto.FunctionCall) otto.Value {
  786. js.ethereum.NatSpec = true
  787. return otto.TrueValue()
  788. }
  789. func (js *jsre) stopNatSpec(call otto.FunctionCall) otto.Value {
  790. js.ethereum.NatSpec = false
  791. return otto.TrueValue()
  792. }
  793. func (js *jsre) newRegistry(call otto.FunctionCall) otto.Value {
  794. if len(call.ArgumentList) != 1 {
  795. fmt.Println("requires 1 argument: admin.contractInfo.newRegistry(adminaddress)")
  796. return otto.FalseValue()
  797. }
  798. addr, err := call.Argument(0).ToString()
  799. if err != nil {
  800. fmt.Println(err)
  801. return otto.FalseValue()
  802. }
  803. registry := resolver.New(js.xeth)
  804. err = registry.CreateContracts(common.HexToAddress(addr))
  805. if err != nil {
  806. fmt.Println(err)
  807. return otto.FalseValue()
  808. }
  809. return otto.TrueValue()
  810. }
  811. // internal transaction type which will allow us to resend transactions using `eth.resend`
  812. type tx struct {
  813. tx *types.Transaction
  814. To string
  815. From string
  816. Nonce string
  817. Value string
  818. Data string
  819. GasLimit string
  820. GasPrice string
  821. }
  822. func newTx(t *types.Transaction) *tx {
  823. from, _ := t.From()
  824. var to string
  825. if t := t.To(); t != nil {
  826. to = t.Hex()
  827. }
  828. return &tx{
  829. tx: t,
  830. To: to,
  831. From: from.Hex(),
  832. Value: t.Amount.String(),
  833. Nonce: strconv.Itoa(int(t.Nonce())),
  834. Data: "0x" + common.Bytes2Hex(t.Data()),
  835. GasLimit: t.GasLimit.String(),
  836. GasPrice: t.GasPrice().String(),
  837. }
  838. }