admin.go 18 KB

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