You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

150 lines
5.1 KiB

  1. // Copyright 2017-2018 DERO Project. All rights reserved.
  2. // Use of this source code in any form is governed by RESEARCH license.
  3. // license can be found in the LICENSE file.
  4. // GPG: 0F39 E425 8C65 3947 702A 8234 08B2 0360 A03A 9DE8
  5. //
  6. //
  7. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
  8. // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  10. // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  11. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  12. // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  13. // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  14. // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  15. // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  16. package rpcserver
  17. import "io"
  18. import "fmt"
  19. import "time"
  20. import "sync"
  21. import "sync/atomic"
  22. //import "context"
  23. import "net/http"
  24. //import "github.com/intel-go/fastjson"
  25. import "github.com/osamingo/jsonrpc"
  26. import log "github.com/sirupsen/logrus"
  27. import "github.com/deroproject/derosuite/globals"
  28. import "github.com/deroproject/derosuite/blockchain"
  29. /* this file implements the rpcserver api, so as wallet and block explorer tools can work without migration */
  30. // all components requiring access to blockchain must use , this struct to communicate
  31. // this structure must be update while mutex
  32. type RPCServer struct {
  33. Exit_Event chan bool // blockchain is shutting down and we must quit ASAP
  34. sync.RWMutex
  35. }
  36. var Exit_In_Progress bool
  37. var chain *blockchain.Blockchain
  38. var logger *log.Entry
  39. func RPCServer_Start(params map[string]interface{}) (*RPCServer, error) {
  40. var err error
  41. var r RPCServer
  42. _ = err
  43. r.Exit_Event = make(chan bool)
  44. logger = globals.Logger.WithFields(log.Fields{"com": "RPC"}) // all components must use this logger
  45. chain = params["chain"].(*blockchain.Blockchain)
  46. // test whether chain is okay
  47. if chain.Get_Height() == 0 {
  48. return nil, fmt.Errorf("Chain DOES NOT have genesis block")
  49. }
  50. go r.Run()
  51. logger.Infof("RPC server started")
  52. atomic.AddUint32(&globals.Subsystem_Active, 1) // increment subsystem
  53. return &r, nil
  54. }
  55. // shutdown the rpc server component
  56. func (r *RPCServer) RPCServer_Stop() {
  57. Exit_In_Progress = true
  58. close(r.Exit_Event) // send signal to all connections to exit
  59. // TODO we must wait for connections to kill themselves
  60. time.Sleep(1 * time.Second)
  61. logger.Infof("RPC Shutdown")
  62. atomic.AddUint32(&globals.Subsystem_Active, ^uint32(0)) // this decrement 1 fom subsystem
  63. }
  64. func (r *RPCServer) Run() {
  65. mr := jsonrpc.NewMethodRepository()
  66. if err := mr.RegisterMethod("Main.Echo", EchoHandler{}, EchoParams{}, EchoResult{}); err != nil {
  67. log.Fatalln(err)
  68. }
  69. // install getblockcount handler
  70. if err := mr.RegisterMethod("getblockcount", GetBlockCount_Handler{}, GetBlockCount_Params{}, GetBlockCount_Result{}); err != nil {
  71. log.Fatalln(err)
  72. }
  73. // install on_getblockhash
  74. if err := mr.RegisterMethod("on_getblockhash", On_GetBlockHash_Handler{}, On_GetBlockHash_Params{}, On_GetBlockHash_Result{}); err != nil {
  75. log.Fatalln(err)
  76. }
  77. // install getblocktemplate handler
  78. if err := mr.RegisterMethod("getblocktemplate", GetBlockTemplate_Handler{}, GetBlockTemplate_Params{}, GetBlockTemplate_Result{}); err != nil {
  79. log.Fatalln(err)
  80. }
  81. // submitblock handler
  82. if err := mr.RegisterMethod("submitblock", SubmitBlock_Handler{}, SubmitBlock_Params{}, SubmitBlock_Result{}); err != nil {
  83. log.Fatalln(err)
  84. }
  85. if err := mr.RegisterMethod("getlastblockheader", GetLastBlockHeader_Handler{}, GetLastBlockHeader_Params{}, GetLastBlockHeader_Result{}); err != nil {
  86. log.Fatalln(err)
  87. }
  88. if err := mr.RegisterMethod("getblockheaderbyhash", GetBlockHeaderByHash_Handler{}, GetBlockHeaderByHash_Params{}, GetBlockHeaderByHash_Result{}); err != nil {
  89. log.Fatalln(err)
  90. }
  91. if err := mr.RegisterMethod("getblockheaderbyheight", GetBlockHeaderByHeight_Handler{}, GetBlockHeaderByHeight_Params{}, GetBlockHeaderByHeight_Result{}); err != nil {
  92. log.Fatalln(err)
  93. }
  94. if err := mr.RegisterMethod("getblock", GetBlock_Handler{}, GetBlock_Params{}, GetBlock_Result{}); err != nil {
  95. log.Fatalln(err)
  96. }
  97. if err := mr.RegisterMethod("get_info", GetInfo_Handler{}, GetInfo_Params{}, GetInfo_Result{}); err != nil {
  98. log.Fatalln(err)
  99. }
  100. if err := mr.RegisterMethod("gettxpool", GetTxPool_Handler{}, GetTxPool_Params{}, GetTxPool_Result{}); err != nil {
  101. log.Fatalln(err)
  102. }
  103. http.HandleFunc("/", hello)
  104. http.Handle("/json_rpc", mr)
  105. // handle nasty http requests
  106. http.HandleFunc("/getoutputs.bin", getoutputs) // stream any outputs to server, can make wallet work offline
  107. http.HandleFunc("/gettransactions", gettransactions)
  108. //http.HandleFunc("/json_rpc/debug", mr.ServeDebug)
  109. if err := http.ListenAndServe("127.0.0.1:9999", http.DefaultServeMux); err != nil {
  110. log.Fatalln(err)
  111. }
  112. }
  113. func hello(w http.ResponseWriter, r *http.Request) {
  114. io.WriteString(w, "Hello world!")
  115. }