Merge branch 'master' into ancaz/blockchain_reactor_reorg

This commit is contained in:
Anca Zamfir
2019-07-08 17:09:01 +02:00
96 changed files with 1833 additions and 1412 deletions

View File

@@ -44,7 +44,7 @@ module.exports = {
"/app-dev/app-development",
"/app-dev/subscribing-to-events-via-websocket",
"/app-dev/indexing-transactions",
"/app-dev/abci-spec",
"/spec/abci/abci",
"/app-dev/ecosystem"
]
},

View File

@@ -326,10 +326,18 @@ application easily in any language.
We have implemented the counter in a number of languages [see the
example directory](https://github.com/tendermint/tendermint/tree/develop/abci/example).
To run the Node JS version, `cd` to `example/js` and run
To run the Node.js version, fist download & install [the Javascript ABCI server](https://github.com/tendermint/js-abci):
```
node app.js
git clone https://github.com/tendermint/js-abci.git
cd js-abci
npm install abci
```
Now you can start the app:
```bash
node example/counter.js
```
(you'll have to kill the other counter application process). In another

View File

@@ -101,8 +101,8 @@ mempool state (this behaviour can be turned off with
In go:
```
func (app *KVStoreApplication) CheckTx(tx []byte) types.Result {
return types.OK
func (app *KVStoreApplication) CheckTx(req types.RequestCheckTx) types.ResponseCheckTx {
return types.ResponseCheckTx{Code: code.CodeTypeOK, GasWanted: 1}
}
```
@@ -133,8 +133,8 @@ the mempool. If Tendermint is just started or the clients sent more than
100k transactions, old transactions may be sent to the application. So
it is important CheckTx implements some logic to handle them.
There are cases where a transaction will (or may) become valid in some
future state, in which case you probably want to disable Tendermint's
If there are cases in your application where a transaction may become invalid in some
future state, you probably want to disable Tendermint's
cache. You can do that by setting `[mempool] cache_size = 0` in the
config.
@@ -168,14 +168,29 @@ In go:
```
// tx is either "key=value" or just arbitrary bytes
func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result {
parts := strings.Split(string(tx), "=")
if len(parts) == 2 {
app.state.Set([]byte(parts[0]), []byte(parts[1]))
} else {
app.state.Set(tx, tx)
}
return types.OK
func (app *KVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.ResponseDeliverTx {
var key, value []byte
parts := bytes.Split(req.Tx, []byte("="))
if len(parts) == 2 {
key, value = parts[0], parts[1]
} else {
key, value = req.Tx, req.Tx
}
app.state.db.Set(prefixKey(key), value)
app.state.Size += 1
events := []types.Event{
{
Type: "app",
Attributes: []cmn.KVPair{
{Key: []byte("creator"), Value: []byte("Cosmoshi Netowoko")},
{Key: []byte("key"), Value: key},
},
},
}
return types.ResponseDeliverTx{Code: code.CodeTypeOK, Events: events}
}
```
@@ -205,7 +220,7 @@ Once all processing of the block is complete, Tendermint sends the
Commit request and blocks waiting for a response. While the mempool may
run concurrently with block processing (the BeginBlock, DeliverTxs, and
EndBlock), it is locked for the Commit request so that its state can be
safely reset during Commit. This means the app _MUST NOT_ do any
safely updated during Commit. This means the app _MUST NOT_ do any
blocking communication with the mempool (ie. broadcast_tx) during
Commit, or there will be deadlock. Note also that all remaining
transactions in the mempool are replayed on the mempool connection
@@ -223,9 +238,14 @@ job of the [Handshake](#handshake).
In go:
```
func (app *KVStoreApplication) Commit() types.Result {
hash := app.state.Hash()
return types.NewResultOK(hash, "")
func (app *KVStoreApplication) Commit() types.ResponseCommit {
// Using a memdb - just return the big endian size of the db
appHash := make([]byte, 8)
binary.PutVarint(appHash, app.state.Size)
app.state.AppHash = appHash
app.state.Height += 1
saveState(app.state)
return types.ResponseCommit{Data: appHash}
}
```
@@ -256,12 +276,10 @@ In go:
```
// Track the block hash and header information
func (app *PersistentKVStoreApplication) BeginBlock(params types.RequestBeginBlock) {
// update latest block info
app.blockHeader = params.Header
// reset valset changes
app.changes = make([]*types.Validator, 0)
func (app *PersistentKVStoreApplication) BeginBlock(req types.RequestBeginBlock) types.ResponseBeginBlock {
// reset valset changes
app.ValUpdates = make([]types.ValidatorUpdate, 0)
return types.ResponseBeginBlock{}
}
```
@@ -303,7 +321,7 @@ In go:
```
// Update the validator set
func (app *PersistentKVStoreApplication) EndBlock(req types.RequestEndBlock) types.ResponseEndBlock {
return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates}
return types.ResponseEndBlock{ValidatorUpdates: app.ValUpdates}
}
```
@@ -347,43 +365,29 @@ Note: these query formats are subject to change!
In go:
```
func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
if reqQuery.Prove {
value, proof, exists := app.state.GetWithProof(reqQuery.Data)
resQuery.Index = -1 // TODO make Proof return index
resQuery.Key = reqQuery.Data
resQuery.Value = value
resQuery.Proof = proof
if exists {
resQuery.Log = "exists"
} else {
resQuery.Log = "does not exist"
}
return
} else {
index, value, exists := app.state.Get(reqQuery.Data)
resQuery.Index = int64(index)
resQuery.Value = value
if exists {
resQuery.Log = "exists"
} else {
resQuery.Log = "does not exist"
}
return
}
}
return
} else {
index, value, exists := app.state.Get(reqQuery.Data)
resQuery.Index = int64(index)
resQuery.Value = value
if exists {
resQuery.Log = "exists"
} else {
resQuery.Log = "does not exist"
}
return
}
func (app *KVStoreApplication) Query(reqQuery types.RequestQuery) (resQuery types.ResponseQuery) {
if reqQuery.Prove {
value := app.state.db.Get(prefixKey(reqQuery.Data))
resQuery.Index = -1 // TODO make Proof return index
resQuery.Key = reqQuery.Data
resQuery.Value = value
if value != nil {
resQuery.Log = "exists"
} else {
resQuery.Log = "does not exist"
}
return
} else {
resQuery.Key = reqQuery.Data
value := app.state.db.Get(prefixKey(reqQuery.Data))
resQuery.Value = value
if value != nil {
resQuery.Log = "exists"
} else {
resQuery.Log = "does not exist"
}
return
}
}
```
@@ -439,7 +443,11 @@ In go:
```
func (app *KVStoreApplication) Info(req types.RequestInfo) (resInfo types.ResponseInfo) {
return types.ResponseInfo{Data: fmt.Sprintf("{\"size\":%v}", app.state.Size())}
return types.ResponseInfo{
Data: fmt.Sprintf("{\"size\":%v}", app.state.Size),
Version: version.ABCIVersion,
AppVersion: ProtocolVersion.Uint64(),
}
}
```
@@ -463,13 +471,14 @@ In go:
```
// Save the validators in the merkle tree
func (app *PersistentKVStoreApplication) InitChain(params types.RequestInitChain) {
for _, v := range params.Validators {
r := app.updateValidator(v)
if r.IsErr() {
app.logger.Error("Error updating validators", "r", r)
}
}
func (app *PersistentKVStoreApplication) InitChain(req types.RequestInitChain) types.ResponseInitChain {
for _, v := range req.Validators {
r := app.updateValidator(v)
if r.IsErr() {
app.logger.Error("Error updating validators", "r", r)
}
}
return types.ResponseInitChain{}
}
```

View File

@@ -47,7 +47,7 @@ pairs of UTF-8 encoded strings (e.g. "account.owner": "Bob", "balance":
Example:
```
func (app *KVStoreApplication) DeliverTx(tx []byte) types.Result {
func (app *KVStoreApplication) DeliverTx(req types.RequestDeliverTx) types.Result {
...
tags := []cmn.KVPair{
{[]byte("account.name"), []byte("igor")},

View File

@@ -45,6 +45,8 @@ make build
to put the binary in `./build`.
_DISCLAIMER_ The binary of tendermint is build/installed without the DWARF symbol table. If you would like to build/install tendermint with the DWARF symbol and debug information, remove `-s -w` from `BUILD_FLAGS` in the make file.
The latest `tendermint version` is now installed.
## Run

View File

@@ -141,7 +141,7 @@ on them. All other fields in the `Response*` must be strictly deterministic.
## Block Execution
The first time a new blockchain is started, Tendermint calls
`InitChain`. From then on, the follow sequence of methods is executed for each
`InitChain`. From then on, the following sequence of methods is executed for each
block:
`BeginBlock, [DeliverTx], EndBlock, Commit`
@@ -296,6 +296,12 @@ Commit are included in the header of the next block.
- **Request**:
- `Tx ([]byte)`: The request transaction bytes
- `Type (CheckTxType)`: What type of `CheckTx` request is this? At present,
there are two possible values: `CheckTx_Unchecked` (the default, which says
that a full check is required), and `CheckTx_Checked` (when the mempool is
initiating a normal recheck of a transaction).
- `AdditionalData ([]byte)`: Reserved for future use. See
[here](https://github.com/tendermint/tendermint/issues/2127#issuecomment-456661420).
- **Response**:
- `Code (uint32)`: Response code
- `Data ([]byte)`: Result bytes, if any.

View File

@@ -218,7 +218,7 @@ func MerkleRoot(items [][]byte) []byte{
case 0:
return nil
case 1:
return leafHash(leafs[0])
return leafHash(items[0])
default:
k := getSplitPoint(len(items))
left := MerkleRoot(items[:k])

View File

@@ -59,7 +59,7 @@ type Validator struct {
When hashing the Validator struct, the address is not included,
because it is redundant with the pubkey.
The `state.Validators`, `state.LastValidators`, and `state.NextValidators`, must always by sorted by validator address,
The `state.Validators`, `state.LastValidators`, and `state.NextValidators`, must always be sorted by validator address,
so that there is a canonical order for computing the MerkleRoot.
We also define a `TotalVotingPower` function, to return the total voting power:

BIN
docs/tendermint-core-image.jpg Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 123 KiB

View File

@@ -138,14 +138,16 @@ max_subscriptions_per_client = 5
# See https://github.com/tendermint/tendermint/issues/3435
timeout_broadcast_tx_commit = "10s"
# The name of a file containing certificate that is used to create the HTTPS server.
# The path to a file containing certificate that is used to create the HTTPS server.
# Migth be either absolute path or path related to tendermint's config directory.
# If the certificate is signed by a certificate authority,
# the certFile should be the concatenation of the server's certificate, any intermediates,
# and the CA's certificate.
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run.
tls_cert_file = ""
# The name of a file containing matching private key that is used to create the HTTPS server.
# The path to a file containing matching private key that is used to create the HTTPS server.
# Migth be either absolute path or path related to tendermint's config directory.
# NOTE: both tls_cert_file and tls_key_file must be present for Tendermint to create HTTPS server. Otherwise, HTTP server is run.
tls_key_file = ""

View File

@@ -202,8 +202,10 @@ Note that raw hex cannot be used in `POST` transactions.
## Reset
**WARNING: UNSAFE** Only do this in development and only if you can
::: warning
**UNSAFE** Only do this in development and only if you can
afford to lose all blockchain data!
:::
To reset a blockchain, stop the node and run: