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.

558 lines
20 KiB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
  1. # Application Development Guide
  2. ## ABCI Design
  3. The purpose of ABCI is to provide a clean interface between state
  4. transition machines on one computer and the mechanics of their
  5. replication across multiple computers. The former we call 'application
  6. logic' and the latter the 'consensus engine'. Application logic
  7. validates transactions and optionally executes transactions against some
  8. persistent state. A consensus engine ensures all transactions are
  9. replicated in the same order on every machine. We call each machine in a
  10. consensus engine a 'validator', and each validator runs the same
  11. transactions through the same application logic. In particular, we are
  12. interested in blockchain-style consensus engines, where transactions are
  13. committed in hash-linked blocks.
  14. The ABCI design has a few distinct components:
  15. - message protocol
  16. - pairs of request and response messages
  17. - consensus makes requests, application responds
  18. - defined using protobuf
  19. - server/client
  20. - consensus engine runs the client
  21. - application runs the server
  22. - two implementations:
  23. - async raw bytes
  24. - grpc
  25. - blockchain protocol
  26. - abci is connection oriented
  27. - Tendermint Core maintains three connections:
  28. - [mempool connection](#mempool-connection): for checking if
  29. transactions should be relayed before they are committed;
  30. only uses `CheckTx`
  31. - [consensus connection](#consensus-connection): for executing
  32. transactions that have been committed. Message sequence is
  33. -for every block -`BeginBlock, [DeliverTx, ...], EndBlock, Commit`
  34. - [query connection](#query-connection): for querying the
  35. application state; only uses Query and Info
  36. The mempool and consensus logic act as clients, and each maintains an
  37. open ABCI connection with the application, which hosts an ABCI server.
  38. Shown are the request and response types sent on each connection.
  39. ## Message Protocol
  40. The message protocol consists of pairs of requests and responses. Some
  41. messages have no fields, while others may include byte-arrays, strings,
  42. or integers. See the `message Request` and `message Response`
  43. definitions in [the protobuf definition
  44. file](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto),
  45. and the [protobuf
  46. documentation](https://developers.google.com/protocol-buffers/docs/overview)
  47. for more details.
  48. For each request, a server should respond with the corresponding
  49. response, where order of requests is preserved in the order of
  50. responses.
  51. ## Server
  52. To use ABCI in your programming language of choice, there must be a ABCI
  53. server in that language. Tendermint supports two kinds of implementation
  54. of the server:
  55. - Asynchronous, raw socket server (Tendermint Socket Protocol, also
  56. known as TSP or Teaspoon)
  57. - GRPC
  58. Both can be tested using the `abci-cli` by setting the `--abci` flag
  59. appropriately (ie. to `socket` or `grpc`).
  60. See examples, in various stages of maintenance, in
  61. [Go](https://github.com/tendermint/tendermint/tree/develop/abci/server),
  62. [JavaScript](https://github.com/tendermint/js-abci),
  63. [Python](https://github.com/tendermint/tendermint/tree/develop/abci/example/python3/abci),
  64. [C++](https://github.com/mdyring/cpp-tmsp), and
  65. [Java](https://github.com/jTendermint/jabci).
  66. ### GRPC
  67. If GRPC is available in your language, this is the easiest approach,
  68. though it will have significant performance overhead.
  69. To get started with GRPC, copy in the [protobuf
  70. file](https://github.com/tendermint/tendermint/blob/develop/abci/types/types.proto)
  71. and compile it using the GRPC plugin for your language. For instance,
  72. for golang, the command is `protoc --go_out=plugins=grpc:. types.proto`.
  73. See the [grpc documentation for more details](http://www.grpc.io/docs/).
  74. `protoc` will autogenerate all the necessary code for ABCI client and
  75. server in your language, including whatever interface your application
  76. must satisfy to be used by the ABCI server for handling requests.
  77. ### TSP
  78. If GRPC is not available in your language, or you require higher
  79. performance, or otherwise enjoy programming, you may implement your own
  80. ABCI server using the Tendermint Socket Protocol, known affectionately
  81. as Teaspoon. The first step is still to auto-generate the relevant data
  82. types and codec in your language using `protoc`. Messages coming over
  83. the socket are proto3 encoded, but additionally length-prefixed to
  84. facilitate use as a streaming protocol. proto3 doesn't have an
  85. official length-prefix standard, so we use our own. The first byte in
  86. the prefix represents the length of the Big Endian encoded length. The
  87. remaining bytes in the prefix are the Big Endian encoded length.
  88. For example, if the proto3 encoded ABCI message is 0xDEADBEEF (4
  89. bytes), the length-prefixed message is 0x0104DEADBEEF. If the proto3
  90. encoded ABCI message is 65535 bytes long, the length-prefixed message
  91. would be like 0x02FFFF....
  92. Note this prefixing does not apply for grpc.
  93. An ABCI server must also be able to support multiple connections, as
  94. Tendermint uses three connections.
  95. ## Client
  96. There are currently two use-cases for an ABCI client. One is a testing
  97. tool, as in the `abci-cli`, which allows ABCI requests to be sent via
  98. command line. The other is a consensus engine, such as Tendermint Core,
  99. which makes requests to the application every time a new transaction is
  100. received or a block is committed.
  101. It is unlikely that you will need to implement a client. For details of
  102. our client, see
  103. [here](https://github.com/tendermint/tendermint/tree/develop/abci/client).
  104. Most of the examples below are from [kvstore
  105. application](https://github.com/tendermint/tendermint/blob/develop/abci/example/kvstore/kvstore.go),
  106. which is a part of the abci repo. [persistent_kvstore
  107. application](https://github.com/tendermint/tendermint/blob/develop/abci/example/kvstore/persistent_kvstore.go)
  108. is used to show `BeginBlock`, `EndBlock` and `InitChain` example
  109. implementations.
  110. ## Blockchain Protocol
  111. In ABCI, a transaction is simply an arbitrary length byte-array. It is
  112. the application's responsibility to define the transaction codec as they
  113. please, and to use it for both CheckTx and DeliverTx.
  114. Note that there are two distinct means for running transactions,
  115. corresponding to stages of 'awareness' of the transaction in the
  116. network. The first stage is when a transaction is received by a
  117. validator from a client into the so-called mempool or transaction pool
  118. -this is where we use CheckTx. The second is when the transaction is
  119. successfully committed on more than 2/3 of validators - where we use
  120. DeliverTx. In the former case, it may not be necessary to run all the
  121. state transitions associated with the transaction, as the transaction
  122. may not ultimately be committed until some much later time, when the
  123. result of its execution will be different. For instance, an Ethereum
  124. ABCI app would check signatures and amounts in CheckTx, but would not
  125. actually execute any contract code until the DeliverTx, so as to avoid
  126. executing state transitions that have not been finalized.
  127. To formalize the distinction further, two explicit ABCI connections are
  128. made between Tendermint Core and the application: the mempool connection
  129. and the consensus connection. We also make a third connection, the query
  130. connection, to query the local state of the app.
  131. ### Mempool Connection
  132. The mempool connection is used _only_ for CheckTx requests. Transactions
  133. are run using CheckTx in the same order they were received by the
  134. validator. If the CheckTx returns `OK`, the transaction is kept in
  135. memory and relayed to other peers in the same order it was received.
  136. Otherwise, it is discarded.
  137. CheckTx requests run concurrently with block processing; so they should
  138. run against a copy of the main application state which is reset after
  139. every block. This copy is necessary to track transitions made by a
  140. sequence of CheckTx requests before they are included in a block. When a
  141. block is committed, the application must ensure to reset the mempool
  142. state to the latest committed state. Tendermint Core will then filter
  143. through all transactions in the mempool, removing any that were included
  144. in the block, and re-run the rest using CheckTx against the post-Commit
  145. mempool state (this behaviour can be turned off with
  146. `[mempool] recheck = false`).
  147. In go:
  148. ```
  149. func (app *KVStoreApplication) CheckTx(tx []byte) types.Result {
  150. return types.OK
  151. }
  152. ```
  153. In Java:
  154. ```
  155. ResponseCheckTx requestCheckTx(RequestCheckTx req) {
  156. byte[] transaction = req.getTx().toByteArray();
  157. // validate transaction
  158. if (notValid) {
  159. return ResponseCheckTx.newBuilder().setCode(CodeType.BadNonce).setLog("invalid tx").build();
  160. } else {
  161. return ResponseCheckTx.newBuilder().setCode(CodeType.OK).build();
  162. }
  163. }
  164. ```
  165. ### Replay Protection
  166. To prevent old transactions from being replayed, CheckTx must implement
  167. replay protection.
  168. Tendermint provides the first defence layer by keeping a lightweight
  169. in-memory cache of 100k (`[mempool] cache_size`) last transactions in
  170. the mempool. If Tendermint is just started or the clients sent more than
  171. 100k transactions, old transactions may be sent to the application. So
  172. it is important CheckTx implements some logic to handle them.
  173. There are cases where a transaction will (or may) become valid in some
  174. future state, in which case you probably want to disable Tendermint's
  175. cache. You can do that by setting `[mempool] cache_size = 0` in the
  176. config.
  177. ### Consensus Connection
  178. The consensus connection is used only when a new block is committed, and
  179. communicates all information from the block in a series of requests:
  180. `BeginBlock, [DeliverTx, ...], EndBlock, Commit`. That is, when a block
  181. is committed in the consensus, we send a list of DeliverTx requests (one
  182. for each transaction) sandwiched by BeginBlock and EndBlock requests,
  183. and followed by a Commit.
  184. ### DeliverTx
  185. DeliverTx is the workhorse of the blockchain. Tendermint sends the
  186. DeliverTx requests asynchronously but in order, and relies on the
  187. underlying socket protocol (ie. TCP) to ensure they are received by the
  188. app in order. They have already been ordered in the global consensus by
  189. the Tendermint protocol.
  190. DeliverTx returns a abci.Result, which includes a Code, Data, and Log.
  191. The code may be non-zero (non-OK), meaning the corresponding transaction
  192. should have been rejected by the mempool, but may have been included in
  193. a block by a Byzantine proposer.
  194. The block header will be updated (TODO) to include some commitment to
  195. the results of DeliverTx, be it a bitarray of non-OK transactions, or a
  196. merkle root of the data returned by the DeliverTx requests, or both.
  197. In go:
  198. ```
  199. // tx is either "key=value" or just arbitrary bytes
  200. func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result {
  201. parts := strings.Split(string(tx), "=")
  202. if len(parts) == 2 {
  203. app.state.Set([]byte(parts[0]), []byte(parts[1]))
  204. } else {
  205. app.state.Set(tx, tx)
  206. }
  207. return types.OK
  208. }
  209. ```
  210. In Java:
  211. ```
  212. /**
  213. * Using Protobuf types from the protoc compiler, we always start with a byte[]
  214. */
  215. ResponseDeliverTx deliverTx(RequestDeliverTx request) {
  216. byte[] transaction = request.getTx().toByteArray();
  217. // validate your transaction
  218. if (notValid) {
  219. return ResponseDeliverTx.newBuilder().setCode(CodeType.BadNonce).setLog("transaction was invalid").build();
  220. } else {
  221. ResponseDeliverTx.newBuilder().setCode(CodeType.OK).build();
  222. }
  223. }
  224. ```
  225. ### Commit
  226. Once all processing of the block is complete, Tendermint sends the
  227. Commit request and blocks waiting for a response. While the mempool may
  228. run concurrently with block processing (the BeginBlock, DeliverTxs, and
  229. EndBlock), it is locked for the Commit request so that its state can be
  230. safely reset during Commit. This means the app _MUST NOT_ do any
  231. blocking communication with the mempool (ie. broadcast_tx) during
  232. Commit, or there will be deadlock. Note also that all remaining
  233. transactions in the mempool are replayed on the mempool connection
  234. (CheckTx) following a commit.
  235. The app should respond to the Commit request with a byte array, which is
  236. the deterministic state root of the application. It is included in the
  237. header of the next block. It can be used to provide easily verified
  238. Merkle-proofs of the state of the application.
  239. It is expected that the app will persist state to disk on Commit. The
  240. option to have all transactions replayed from some previous block is the
  241. job of the [Handshake](#handshake).
  242. In go:
  243. ```
  244. func (app *KVStoreApplication) Commit() types.Result {
  245. hash := app.state.Hash()
  246. return types.NewResultOK(hash, "")
  247. }
  248. ```
  249. In Java:
  250. ```
  251. ResponseCommit requestCommit(RequestCommit requestCommit) {
  252. // update the internal app-state
  253. byte[] newAppState = calculateAppState();
  254. // and return it to the node
  255. return ResponseCommit.newBuilder().setCode(CodeType.OK).setData(ByteString.copyFrom(newAppState)).build();
  256. }
  257. ```
  258. ### BeginBlock
  259. The BeginBlock request can be used to run some code at the beginning of
  260. every block. It also allows Tendermint to send the current block hash
  261. and header to the application, before it sends any of the transactions.
  262. The app should remember the latest height and header (ie. from which it
  263. has run a successful Commit) so that it can tell Tendermint where to
  264. pick up from when it restarts. See information on the Handshake, below.
  265. In go:
  266. ```
  267. // Track the block hash and header information
  268. func (app *PersistentKVStoreApplication) BeginBlock(params types.RequestBeginBlock) {
  269. // update latest block info
  270. app.blockHeader = params.Header
  271. // reset valset changes
  272. app.changes = make([]*types.Validator, 0)
  273. }
  274. ```
  275. In Java:
  276. ```
  277. /*
  278. * all types come from protobuf definition
  279. */
  280. ResponseBeginBlock requestBeginBlock(RequestBeginBlock req) {
  281. Header header = req.getHeader();
  282. byte[] prevAppHash = header.getAppHash().toByteArray();
  283. long prevHeight = header.getHeight();
  284. long numTxs = header.getNumTxs();
  285. // run your pre-block logic. Maybe prepare a state snapshot, message components, etc
  286. return ResponseBeginBlock.newBuilder().build();
  287. }
  288. ```
  289. ### EndBlock
  290. The EndBlock request can be used to run some code at the end of every block.
  291. Additionally, the response may contain a list of validators, which can be used
  292. to update the validator set. To add a new validator or update an existing one,
  293. simply include them in the list returned in the EndBlock response. To remove
  294. one, include it in the list with a `power` equal to `0`. Validator's `address`
  295. field can be left empty. Tendermint core will take care of updating the
  296. validator set. Note the change in voting power must be strictly less than 1/3
  297. per block if you want a light client to be able to prove the transition
  298. externally. See the [light client
  299. docs](https://godoc.org/github.com/tendermint/tendermint/lite#hdr-How_We_Track_Validators)
  300. for details on how it tracks validators.
  301. In go:
  302. ```
  303. // Update the validator set
  304. func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
  305. return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates}
  306. }
  307. ```
  308. In Java:
  309. ```
  310. /*
  311. * Assume that one validator changes. The new validator has a power of 10
  312. */
  313. ResponseEndBlock requestEndBlock(RequestEndBlock req) {
  314. final long currentHeight = req.getHeight();
  315. final byte[] validatorPubKey = getValPubKey();
  316. ResponseEndBlock.Builder builder = ResponseEndBlock.newBuilder();
  317. builder.addDiffs(1, Types.Validator.newBuilder().setPower(10L).setPubKey(ByteString.copyFrom(validatorPubKey)).build());
  318. return builder.build();
  319. }
  320. ```
  321. ### Query Connection
  322. This connection is used to query the application without engaging
  323. consensus. It's exposed over the tendermint core rpc, so clients can
  324. query the app without exposing a server on the app itself, but they must
  325. serialize each query as a single byte array. Additionally, certain
  326. "standardized" queries may be used to inform local decisions, for
  327. instance about which peers to connect to.
  328. Tendermint Core currently uses the Query connection to filter peers upon
  329. connecting, according to IP address or node ID. For instance,
  330. returning non-OK ABCI response to either of the following queries will
  331. cause Tendermint to not connect to the corresponding peer:
  332. - `p2p/filter/addr/<ip addr>`, where `<ip addr>` is an IP address.
  333. - `p2p/filter/id/<id>`, where `<is>` is the hex-encoded node ID (the hash of
  334. the node's p2p pubkey).
  335. Note: these query formats are subject to change!
  336. In go:
  337. ```
  338. func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
  339. if reqQuery.Prove {
  340. value, proof, exists := app.state.Proof(reqQuery.Data)
  341. resQuery.Index = -1 // TODO make Proof return index
  342. resQuery.Key = reqQuery.Data
  343. resQuery.Value = value
  344. resQuery.Proof = proof
  345. if exists {
  346. resQuery.Log = "exists"
  347. } else {
  348. resQuery.Log = "does not exist"
  349. }
  350. return
  351. } else {
  352. index, value, exists := app.state.Get(reqQuery.Data)
  353. resQuery.Index = int64(index)
  354. resQuery.Value = value
  355. if exists {
  356. resQuery.Log = "exists"
  357. } else {
  358. resQuery.Log = "does not exist"
  359. }
  360. return
  361. }
  362. }
  363. ```
  364. In Java:
  365. ```
  366. ResponseQuery requestQuery(RequestQuery req) {
  367. final boolean isProveQuery = req.getProve();
  368. final ResponseQuery.Builder responseBuilder = ResponseQuery.newBuilder();
  369. if (isProveQuery) {
  370. com.app.example.ProofResult proofResult = generateProof(req.getData().toByteArray());
  371. final byte[] proofAsByteArray = proofResult.getAsByteArray();
  372. responseBuilder.setProof(ByteString.copyFrom(proofAsByteArray));
  373. responseBuilder.setKey(req.getData());
  374. responseBuilder.setValue(ByteString.copyFrom(proofResult.getData()));
  375. responseBuilder.setLog(result.getLogValue());
  376. } else {
  377. byte[] queryData = req.getData().toByteArray();
  378. final com.app.example.QueryResult result = generateQueryResult(queryData);
  379. responseBuilder.setIndex(result.getIndex());
  380. responseBuilder.setValue(ByteString.copyFrom(result.getValue()));
  381. responseBuilder.setLog(result.getLogValue());
  382. }
  383. return responseBuilder.build();
  384. }
  385. ```
  386. ### Handshake
  387. When the app or tendermint restarts, they need to sync to a common
  388. height. When an ABCI connection is first established, Tendermint will
  389. call `Info` on the Query connection. The response should contain the
  390. LastBlockHeight and LastBlockAppHash - the former is the last block for
  391. which the app ran Commit successfully, the latter is the response from
  392. that Commit.
  393. Using this information, Tendermint will determine what needs to be
  394. replayed, if anything, against the app, to ensure both Tendermint and
  395. the app are synced to the latest block height.
  396. If the app returns a LastBlockHeight of 0, Tendermint will just replay
  397. all blocks.
  398. In go:
  399. ```
  400. func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) {
  401. return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())}
  402. }
  403. ```
  404. In Java:
  405. ```
  406. ResponseInfo requestInfo(RequestInfo req) {
  407. final byte[] lastAppHash = getLastAppHash();
  408. final long lastHeight = getLastHeight();
  409. return ResponseInfo.newBuilder().setLastBlockAppHash(ByteString.copyFrom(lastAppHash)).setLastBlockHeight(lastHeight).build();
  410. }
  411. ```
  412. ### Genesis
  413. `InitChain` will be called once upon the genesis. `params` includes the
  414. initial validator set. Later on, it may be extended to take parts of the
  415. consensus params.
  416. In go:
  417. ```
  418. // Save the validators in the merkle tree
  419. func (app *PersistentKVStoreApplication) InitChain(params types.RequestInitChain) {
  420. for _, v := range params.Validators {
  421. r := app.updateValidator(v)
  422. if r.IsErr() {
  423. app.logger.Error("Error updating validators", "r", r)
  424. }
  425. }
  426. }
  427. ```
  428. In Java:
  429. ```
  430. /*
  431. * all types come from protobuf definition
  432. */
  433. ResponseInitChain requestInitChain(RequestInitChain req) {
  434. final int validatorsCount = req.getValidatorsCount();
  435. final List<Types.Validator> validatorsList = req.getValidatorsList();
  436. validatorsList.forEach((validator) -> {
  437. long power = validator.getPower();
  438. byte[] validatorPubKey = validator.getPubKey().toByteArray();
  439. // do somehing for validator setup in app
  440. });
  441. return ResponseInitChain.newBuilder().build();
  442. }
  443. ```