doc.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. // Copyright (c) 2014-2017 The btcsuite developers
  2. // Use of this source code is governed by an ISC
  3. // license that can be found in the LICENSE file.
  4. /*
  5. Package rpcclient implements a websocket-enabled Bitcoin JSON-RPC client.
  6. Overview
  7. This client provides a robust and easy to use client for interfacing with a
  8. Bitcoin RPC server that uses a pktd/bitcoin core compatible Bitcoin JSON-RPC
  9. API. This client has been tested with pktd (https://github.com/pkt-cash/pktd),
  10. pktwallet (https://github.com/pkt-cash/pktwallet), and
  11. bitcoin core (https://github.com/bitcoin).
  12. In addition to the compatible standard HTTP POST JSON-RPC API, pktd and
  13. pktwallet provide a websocket interface that is more efficient than the standard
  14. HTTP POST method of accessing RPC. The section below discusses the differences
  15. between HTTP POST and websockets.
  16. By default, this client assumes the RPC server supports websockets and has
  17. TLS enabled. In practice, this currently means it assumes you are talking to
  18. pktd or pktwallet by default. However, configuration options are provided to
  19. fall back to HTTP POST and disable TLS to support talking with inferior bitcoin
  20. core style RPC servers.
  21. Websockets vs HTTP POST
  22. In HTTP POST-based JSON-RPC, every request creates a new HTTP connection,
  23. issues the call, waits for the response, and closes the connection. This adds
  24. quite a bit of overhead to every call and lacks flexibility for features such as
  25. notifications.
  26. In contrast, the websocket-based JSON-RPC interface provided by pktd and
  27. pktwallet only uses a single connection that remains open and allows
  28. asynchronous bi-directional communication.
  29. The websocket interface supports all of the same commands as HTTP POST, but they
  30. can be invoked without having to go through a connect/disconnect cycle for every
  31. call. In addition, the websocket interface provides other nice features such as
  32. the ability to register for asynchronous notifications of various events.
  33. Synchronous vs Asynchronous API
  34. The client provides both a synchronous (blocking) and asynchronous API.
  35. The synchronous (blocking) API is typically sufficient for most use cases. It
  36. works by issuing the RPC and blocking until the response is received. This
  37. allows straightforward code where you have the response as soon as the function
  38. returns.
  39. The asynchronous API works on the concept of futures. When you invoke the async
  40. version of a command, it will quickly return an instance of a type that promises
  41. to provide the result of the RPC at some future time. In the background, the
  42. RPC call is issued and the result is stored in the returned instance. Invoking
  43. the Receive method on the returned instance will either return the result
  44. immediately if it has already arrived, or block until it has. This is useful
  45. since it provides the caller with greater control over concurrency.
  46. Notifications
  47. The first important part of notifications is to realize that they will only
  48. work when connected via websockets. This should intuitively make sense
  49. because HTTP POST mode does not keep a connection open!
  50. All notifications provided by pktd require registration to opt-in. For example,
  51. if you want to be notified when funds are received by a set of addresses, you
  52. register the addresses via the NotifyReceived (or NotifyReceivedAsync) function.
  53. Notification Handlers
  54. Notifications are exposed by the client through the use of callback handlers
  55. which are setup via a NotificationHandlers instance that is specified by the
  56. caller when creating the client.
  57. It is important that these notification handlers complete quickly since they
  58. are intentionally in the main read loop and will block further reads until
  59. they complete. This provides the caller with the flexibility to decide what to
  60. do when notifications are coming in faster than they are being handled.
  61. In particular this means issuing a blocking RPC call from a callback handler
  62. will cause a deadlock as more server responses won't be read until the callback
  63. returns, but the callback would be waiting for a response. Thus, any
  64. additional RPCs must be issued an a completely decoupled manner.
  65. Automatic Reconnection
  66. By default, when running in websockets mode, this client will automatically
  67. keep trying to reconnect to the RPC server should the connection be lost. There
  68. is a back-off in between each connection attempt until it reaches one try per
  69. minute. Once a connection is re-established, all previously registered
  70. notifications are automatically re-registered and any in-flight commands are
  71. re-issued. This means from the caller's perspective, the request simply takes
  72. longer to complete.
  73. The caller may invoke the Shutdown method on the client to force the client
  74. to cease reconnect attempts and return ErrClientShutdown for all outstanding
  75. commands.
  76. The automatic reconnection can be disabled by setting the DisableAutoReconnect
  77. flag to true in the connection config when creating the client.
  78. Minor RPC Server Differences and Chain/Wallet Separation
  79. Some of the commands are extensions specific to a particular RPC server. For
  80. example, the DebugLevel call is an extension only provided by pktd (and
  81. pktwallet passthrough). Therefore if you call one of these commands against
  82. an RPC server that doesn't provide them, you will get an unimplemented error
  83. from the server. An effort has been made to call out which commmands are
  84. extensions in their documentation.
  85. Also, it is important to realize that pktd intentionally separates the wallet
  86. functionality into a separate process named pktwallet. This means if you are
  87. connected to the pktd RPC server directly, only the RPCs which are related to
  88. chain services will be available. Depending on your application, you might only
  89. need chain-related RPCs. In contrast, pktwallet provides pass through treatment
  90. for chain-related RPCs, so it supports them in addition to wallet-related RPCs.
  91. Errors
  92. There are 3 categories of errors that will be returned throughout this package:
  93. - Errors related to the client connection such as authentication, endpoint,
  94. disconnect, and shutdown
  95. - Errors that occur before communicating with the remote RPC server such as
  96. command creation and marshaling errors or issues talking to the remote
  97. server
  98. - Errors returned from the remote RPC server like unimplemented commands,
  99. nonexistent requested blocks and transactions, malformed data, and incorrect
  100. networks
  101. The first category of errors are typically one of ErrInvalidAuth,
  102. ErrInvalidEndpoint, ErrClientDisconnect, or ErrClientShutdown.
  103. NOTE: The ErrClientDisconnect will not be returned unless the
  104. DisableAutoReconnect flag is set since the client automatically handles
  105. reconnect by default as previously described.
  106. The second category of errors typically indicates a programmer error and as such
  107. the type can vary, but usually will be best handled by simply showing/logging
  108. it.
  109. The third category of errors, that is errors returned by the server, can be
  110. detected by type asserting the error in a *btcjson.RPCError. For example, to
  111. detect if a command is unimplemented by the remote RPC server:
  112. amount, err := client.GetBalance("")
  113. if err != nil {
  114. if jerr, ok := err.(*btcjson.RPCError); ok {
  115. switch jerr.Code {
  116. case btcjson.ErrRPCUnimplemented:
  117. // Handle not implemented error
  118. // Handle other specific errors you care about
  119. }
  120. }
  121. // Log or otherwise handle the error knowing it was not one returned
  122. // from the remote RPC server.
  123. }
  124. Example Usage
  125. The following full-blown client examples are in the examples directory:
  126. - bitcoincorehttp
  127. Connects to a bitcoin core RPC server using HTTP POST mode with TLS disabled
  128. and gets the current block count
  129. - pktdwebsockets
  130. Connects to a pktd RPC server using TLS-secured websockets, registers for
  131. block connected and block disconnected notifications, and gets the current
  132. block count
  133. - pktwalletwebsockets
  134. Connects to a pktwallet RPC server using TLS-secured websockets, registers
  135. for notifications about changes to account balances, and gets a list of
  136. unspent transaction outputs (utxos) the wallet can sign
  137. */
  138. package rpcclient