admin.go 25 KB

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