admin.go 22 KB

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