Edit me

[TOC]

服务器端

RPC的启动是下面流程: /home/pct/go/src/github.com/Baptist-Publication/chorus/src/chain/cmd/run.go 中添加run命令:

func init() {
   RootCmd.AddCommand(runCmd)

run命令会启动节点:

var runCmd = &cobra.Command{
   Use:   "run",
   Short: "Run a blockchain full-capacity node",
   Long:  ``,
   Args:  cobra.NoArgs,
   PreRun: func(cmd *cobra.Command, args []string) {

   },
   Run: func(cmd *cobra.Command, args []string) {
      env := viper.GetString("environment")
      logpath := viper.GetString("log_path")
      if logpath == "" {
         var err error
         if logpath, err = os.Getwd(); err != nil {
            cmd.Println(err)
            os.Exit(1)
         }
      }
      viper.Set("log_path", logpath)
      logger := log.Initialize(env, path.Join(logpath, "node.output.log"), path.Join(logpath, "node.err.log"))
      node.RunNode(logger, viper.GetViper())
   },
}

RunNode函数绑定地址和路由表:

func RunNode(logger *zap.Logger, config *viper.Viper) {
   node := NewNode(logger, config)
   if err := node.Start(); err != nil {
      cmn.Exit(cmn.Fmt("Failed to start node: %v", err))
   }
   if config.GetString("rpc_laddr") != "" {
      if _, err := node.StartRPC(); err != nil {
         cmn.PanicCrisis(err)
      }
   }
   if config.GetBool("pprof") {
      go func() {
         http.ListenAndServe(":6060", nil)
      }()
   }

   fmt.Printf("node (%s) is running on %s:%d ......\n", node.MainChainID, node.NodeInfo().ListenHost(), node.NodeInfo().ListenPort())

   cmn.TrapSignal(func() {
      node.Stop()
   })
}

端口为6060,路由表如下:

func (n *Node) rpcRoutes() map[string]*rpc.RPCFunc {
   h := newRPCHandler(n)
   return map[string]*rpc.RPCFunc{
      // subscribe/unsubscribe are reserved for websocket events.
      // "subscribe":   rpc.NewWSRPCFunc(SubscribeResult, argsWithChainID("event")),
      // "unsubscribe": rpc.NewWSRPCFunc(UnsubscribeResult, argsWithChainID("event")),

      // info API
      "organizations":        rpc.NewRPCFunc(h.Orgs, ""),
      "status":               rpc.NewRPCFunc(h.Status, argsWithChainID("")),
      "net_info":             rpc.NewRPCFunc(h.NetInfo, argsWithChainID("")),
      "blockchain":           rpc.NewRPCFunc(h.BlockchainInfo, argsWithChainID("minHeight,maxHeight")),
      "genesis":              rpc.NewRPCFunc(h.Genesis, argsWithChainID("")),
      "block":                rpc.NewRPCFunc(h.Block, argsWithChainID("height")),
      "validators":           rpc.NewRPCFunc(h.Validators, argsWithChainID("")),
      "dump_consensus_state": rpc.NewRPCFunc(h.DumpConsensusState, argsWithChainID("")),
      "unconfirmed_txs":      rpc.NewRPCFunc(h.UnconfirmedTxs, argsWithChainID("")),
      "num_unconfirmed_txs":  rpc.NewRPCFunc(h.NumUnconfirmedTxs, argsWithChainID("")),
      "num_archived_blocks":  rpc.NewRPCFunc(h.NumArchivedBlocks, argsWithChainID("")),
      "za_surveillance":      rpc.NewRPCFunc(h.ZaSurveillance, argsWithChainID("")),
      "core_version":         rpc.NewRPCFunc(h.CoreVersion, argsWithChainID("")),

      // broadcast API
      "broadcast_tx_commit": rpc.NewRPCFunc(h.BroadcastTxCommit, argsWithChainID("tx")),
      "broadcast_tx_sync":   rpc.NewRPCFunc(h.BroadcastTx, argsWithChainID("tx")),

      // query API
      "query":      rpc.NewRPCFunc(h.Query, argsWithChainID("query")),
      "info":       rpc.NewRPCFunc(h.Info, argsWithChainID("")),
      "event_code": rpc.NewRPCFunc(h.EventCode, argsWithChainID("code_hash")), // TODO now id is base-chain's name

      // control API
      // "dial_seeds":           rpc.NewRPCFunc(h.UnsafeDialSeeds, argsWithChainID("seeds")),
      "unsafe_flush_mempool": rpc.NewRPCFunc(h.UnsafeFlushMempool, argsWithChainID("")),
      // "unsafe_set_config":    rpc.NewRPCFunc(h.UnsafeSetConfig, argsWithChainID("type,key,value")),

      // profiler API
      // "unsafe_start_cpu_profiler": rpc.NewRPCFunc(UnsafeStartCPUProfilerResult, argsWithChainID("filename")),
      // "unsafe_stop_cpu_profiler":  rpc.NewRPCFunc(UnsafeStopCPUProfilerResult, argsWithChainID("")),
      // "unsafe_write_heap_profile": rpc.NewRPCFunc(UnsafeWriteHeapProfileResult, argsWithChainID("filename")),

      // specialOP API
      "request_special_op": rpc.NewRPCFunc(h.RequestSpecialOP, argsWithChainID("tx")),
      // "vote_special_op":    rpc.NewRPCFunc(h.VoteSpecialOP, argsWithChainID("tx")),
      // "request_vote_channel": rpc.NewRPCFunc(RequestForVoteChannel, "tx"),

      // refuse_list API
      "blacklist": rpc.NewRPCFunc(h.Blacklist, argsWithChainID("")),

      "non_empty_heights": rpc.NewRPCFunc(h.NonEmptyHeights, argsWithChainID("")),
   }
}

客户端调用

客户端调用部分比较简单,直接创建RPC并调用即可:

func (act nodeActions) jsonRPC(chainID string, p []byte) (*types.RPCResult, error) {
   clt := rpcclient.NewClientJSONRPC(logger, commons.QueryServer)
   tmResult := new(types.RPCResult)
   _, err := clt.Call("broadcast_tx_sync", []interface{}{chainID, p}, tmResult)
   if err != nil {
      return nil, err
   }
   return tmResult, nil
}
Tags: