mirror of
https://github.com/tendermint/tendermint.git
synced 2026-01-08 06:15:33 +00:00
Merge pull request #1701 from tendermint/bucky/abci-fixes
Bucky/abci fixes
This commit is contained in:
18
CHANGELOG.md
18
CHANGELOG.md
@@ -1,8 +1,22 @@
|
||||
# Changelog
|
||||
|
||||
## 0.19.10
|
||||
## 0.20.0
|
||||
|
||||
*June 6th, 2018*
|
||||
|
||||
BREAKING CHANGES
|
||||
|
||||
- [abci] Upgrade to
|
||||
[v0.11.0](https://github.com/tendermint/abci/blob/master/CHANGELOG.md#0110)
|
||||
- [abci] Query path for filtering peers by node ID changed from
|
||||
`p2p/filter/pubkey/<id>` to `p2p/filter/id/<id>`
|
||||
|
||||
NOTE: this release does not break any blockchain data structures or
|
||||
protocols other than the ABCI messages between Tendermint and the application.
|
||||
|
||||
Applications that upgrade for ABCI v0.11.0 should be able to continue running Tendermint
|
||||
v0.20.0 on blockchains created with v0.19.X
|
||||
|
||||
*TBD*
|
||||
|
||||
## 0.19.9
|
||||
|
||||
|
||||
8
Gopkg.lock
generated
8
Gopkg.lock
generated
@@ -238,8 +238,8 @@
|
||||
"server",
|
||||
"types"
|
||||
]
|
||||
revision = "7cf66f570e2f47b286985e2d688b0a400c028e4c"
|
||||
version = "v0.11.0-rc6"
|
||||
revision = "ebee2fe114020aa49c70bbbae50b7079fc7e7b90"
|
||||
version = "v0.11.0"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
@@ -313,7 +313,7 @@
|
||||
branch = "master"
|
||||
name = "golang.org/x/sys"
|
||||
packages = ["unix"]
|
||||
revision = "c11f84a56e43e20a78cee75a7c034031ecf57d1f"
|
||||
revision = "9527bec2660bd847c050fda93a0f0c6dee0800bb"
|
||||
|
||||
[[projects]]
|
||||
name = "golang.org/x/text"
|
||||
@@ -374,6 +374,6 @@
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "132980da98fc92b6c0dd988df07316a340f5fc91ee77593cf984ade4e3e5fd62"
|
||||
inputs-digest = "ae6792578b0664708339f4c05e020687d6b799ad6f8282394b919de69e403d1f"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tendermint/abci"
|
||||
version = "~0.11.0-rc6"
|
||||
version = "~0.11.0"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/tendermint/go-crypto"
|
||||
|
||||
@@ -267,17 +267,31 @@ func (h *Handshaker) ReplayBlocks(state sm.State, appHash []byte, appBlockHeight
|
||||
// If appBlockHeight == 0 it means that we are at genesis and hence should send InitChain
|
||||
if appBlockHeight == 0 {
|
||||
validators := types.TM2PB.Validators(state.Validators)
|
||||
csParams := types.TM2PB.ConsensusParams(h.genDoc.ConsensusParams)
|
||||
req := abci.RequestInitChain{
|
||||
Time: h.genDoc.GenesisTime.Unix(), // TODO
|
||||
ChainId: h.genDoc.ChainID,
|
||||
ConsensusParams: types.TM2PB.ConsensusParams(h.genDoc.ConsensusParams),
|
||||
ConsensusParams: csParams,
|
||||
Validators: validators,
|
||||
AppStateBytes: h.genDoc.AppStateJSON,
|
||||
}
|
||||
_, err := proxyApp.Consensus().InitChainSync(req)
|
||||
res, err := proxyApp.Consensus().InitChainSync(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// update the state
|
||||
if len(res.Validators) > 0 {
|
||||
vals, err := types.PB2TM.Validators(res.Validators)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
state.Validators = types.NewValidatorSet(vals)
|
||||
}
|
||||
if res.ConsensusParams != nil {
|
||||
// TODO
|
||||
}
|
||||
sm.SaveState(h.stateDB, state)
|
||||
}
|
||||
|
||||
// First handle edge cases and constraints on the storeBlockHeight
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/tendermint/abci/example/kvstore"
|
||||
@@ -634,3 +635,53 @@ func (bs *mockBlockStore) LoadBlockCommit(height int64) *types.Commit {
|
||||
func (bs *mockBlockStore) LoadSeenCommit(height int64) *types.Commit {
|
||||
return bs.commits[height-1]
|
||||
}
|
||||
|
||||
//----------------------------------------
|
||||
|
||||
func TestInitChainUpdateValidators(t *testing.T) {
|
||||
val, _ := types.RandValidator(true, 10)
|
||||
vals := types.NewValidatorSet([]*types.Validator{val})
|
||||
app := &initChainApp{vals: types.TM2PB.Validators(vals)}
|
||||
clientCreator := proxy.NewLocalClientCreator(app)
|
||||
|
||||
config := ResetConfig("proxy_test_")
|
||||
privVal := privval.LoadFilePV(config.PrivValidatorFile())
|
||||
stateDB, state, store := stateAndStore(config, privVal.GetPubKey())
|
||||
|
||||
oldValAddr := state.Validators.Validators[0].Address
|
||||
|
||||
// now start the app using the handshake - it should sync
|
||||
genDoc, _ := sm.MakeGenesisDocFromFile(config.GenesisFile())
|
||||
handshaker := NewHandshaker(stateDB, state, store, genDoc)
|
||||
proxyApp := proxy.NewAppConns(clientCreator, handshaker)
|
||||
if err := proxyApp.Start(); err != nil {
|
||||
t.Fatalf("Error starting proxy app connections: %v", err)
|
||||
}
|
||||
defer proxyApp.Stop()
|
||||
|
||||
// reload the state, check the validator set was updated
|
||||
state = sm.LoadState(stateDB)
|
||||
|
||||
newValAddr := state.Validators.Validators[0].Address
|
||||
expectValAddr := val.Address
|
||||
assert.NotEqual(t, oldValAddr, newValAddr)
|
||||
assert.Equal(t, newValAddr, expectValAddr)
|
||||
}
|
||||
|
||||
func newInitChainApp(vals []abci.Validator) *initChainApp {
|
||||
return &initChainApp{
|
||||
vals: vals,
|
||||
}
|
||||
}
|
||||
|
||||
// returns the vals on InitChain
|
||||
type initChainApp struct {
|
||||
abci.BaseApplication
|
||||
vals []abci.Validator
|
||||
}
|
||||
|
||||
func (ica *initChainApp) InitChain(req abci.RequestInitChain) abci.ResponseInitChain {
|
||||
return abci.ResponseInitChain{
|
||||
Validators: ica.vals,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,14 +49,14 @@ spec](https://github.com/tendermint/go-amino#computing-the-prefix-and-disambigua
|
||||
In what follows, we provide the type names and prefix bytes directly.
|
||||
Notice that when encoding byte-arrays, the length of the byte-array is appended
|
||||
to the PrefixBytes. Thus the encoding of a byte array becomes `<PrefixBytes>
|
||||
<Length> <ByteArray>`. In other words, to encode any type listed below you do not need to be
|
||||
familiar with amino encoding.
|
||||
You can simply use below table and concatenate Prefix || Length (of raw bytes) || raw bytes
|
||||
<Length> <ByteArray>`. In other words, to encode any type listed below you do not need to be
|
||||
familiar with amino encoding.
|
||||
You can simply use below table and concatenate Prefix || Length (of raw bytes) || raw bytes
|
||||
( while || stands for byte concatenation here).
|
||||
|
||||
| Type | Name | Prefix | Length |
|
||||
| ---- | ---- | ------ | ----- |
|
||||
| PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE62 | 0x20 |
|
||||
| ---- | ---- | ------ | ----- |
|
||||
| PubKeyEd25519 | tendermint/PubKeyEd25519 | 0x1624DE62 | 0x20 |
|
||||
| PubKeyLedgerEd25519 | tendermint/PubKeyLedgerEd25519 | 0x5C3453B2 | 0x20 |
|
||||
| PubKeySecp256k1 | tendermint/PubKeySecp256k1 | 0xEB5AE982 | 0x21 |
|
||||
| PrivKeyEd25519 | tendermint/PrivKeyEd25519 | 0xA3288912 | 0x40 |
|
||||
@@ -69,7 +69,7 @@ You can simply use below table and concatenate Prefix || Length (of raw bytes) |
|
||||
### Examples
|
||||
|
||||
1. For example, the 33-byte (or 0x21-byte in hex) Secp256k1 pubkey
|
||||
`020BD40F225A57ED383B440CF073BC5539D0341F5767D2BF2D78406D00475A2EE9`
|
||||
`020BD40F225A57ED383B440CF073BC5539D0341F5767D2BF2D78406D00475A2EE9`
|
||||
would be encoded as
|
||||
`EB5AE98221020BD40F225A57ED383B440CF073BC5539D0341F5767D2BF2D78406D00475A2EE9`
|
||||
|
||||
@@ -78,6 +78,31 @@ would be encoded as
|
||||
would be encoded as
|
||||
`16E1FEEA46304402201CD4B8C764D2FD8AF23ECFE6666CA8A53886D47754D951295D2D311E1FEA33BF02201E0F906BB1CF2C30EAACFFB032A7129358AFF96B9F79B06ACFFB18AC90C2ADD7`
|
||||
|
||||
### Addresses
|
||||
|
||||
Addresses for each public key types are computed as follows:
|
||||
|
||||
#### Ed25519
|
||||
|
||||
RIPEMD160 hash of the Amino encoded public key:
|
||||
|
||||
```
|
||||
address = RIPEMD160(AMINO(pubkey))
|
||||
```
|
||||
|
||||
NOTE: this will soon change to the truncated 20-bytes of the SHA256 of the raw
|
||||
public key
|
||||
|
||||
#### Secp256k1
|
||||
|
||||
RIPEMD160 hash of the SHA256 hash of the OpenSSL compressed public key:
|
||||
|
||||
```
|
||||
address = RIPEMD160(SHA256(pubkey))
|
||||
```
|
||||
|
||||
This is the same as Bitcoin.
|
||||
|
||||
## Other Common Types
|
||||
|
||||
### BitArray
|
||||
|
||||
@@ -52,20 +52,33 @@ objects in the `ResponseBeginBlock`:
|
||||
|
||||
```
|
||||
message Validator {
|
||||
bytes pub_key = 1;
|
||||
int64 power = 2;
|
||||
bytes address = 1;
|
||||
PubKey pub_key = 2;
|
||||
int64 power = 3;
|
||||
}
|
||||
|
||||
message PubKey {
|
||||
string type = 1;
|
||||
bytes data = 2;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The `pub_key` is the Amino encoded public key for the validator. For details on
|
||||
Amino encoded public keys, see the [section of the encoding spec](https://github.com/tendermint/tendermint/blob/master/docs/spec/blockchain/encoding.md#public-key-cryptography).
|
||||
The `pub_key` currently supports two types:
|
||||
- `type = "ed25519" and `data = <raw 32-byte public key>`
|
||||
- `type = "secp256k1" and `data = <33-byte OpenSSL compressed public key>`
|
||||
|
||||
If the address is provided, it must match the address of the pubkey, as
|
||||
specified [here](/docs/spec/blockchain/encoding.md#Addresses)
|
||||
|
||||
(Note: In the v0.19 series, the `pub_key` is the [Amino encoded public
|
||||
key](/docs/spec/blockchain/encoding.md#public-key-cryptography).
|
||||
For Ed25519 pubkeys, the Amino prefix is always "1624DE6220". For example, the 32-byte Ed25519 pubkey
|
||||
`76852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85` would be
|
||||
Amino encoded as
|
||||
`1624DE622076852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85`
|
||||
`1624DE622076852933A4686A721442E931A8415F62F5F1AEDF4910F1F252FB393F74C40C85`)
|
||||
|
||||
(Note: in old versions of Tendermint (pre-v0.19.0), the pubkey is just prefixed with a
|
||||
(Note: In old versions of Tendermint (pre-v0.19.0), the pubkey is just prefixed with a
|
||||
single type byte, so for ED25519 we'd have `pub_key = 0x1 | pub`)
|
||||
|
||||
The `power` is the new voting power for the validator, with the
|
||||
@@ -94,7 +107,7 @@ using the following paths, with no additional data:
|
||||
|
||||
- `/p2p/filter/addr/<IP:PORT>`, where `<IP:PORT>` denote the IP address and
|
||||
the port of the connection
|
||||
- `p2p/filter/pubkey/<ID>`, where `<ID>` is the peer node ID (ie. the
|
||||
- `p2p/filter/id/<ID>`, where `<ID>` is the peer node ID (ie. the
|
||||
pubkey.Address() for the peer's PubKey)
|
||||
|
||||
If either of these queries return a non-zero ABCI code, Tendermint will refuse
|
||||
|
||||
@@ -302,7 +302,7 @@ func NewNode(config *cfg.Config,
|
||||
return nil
|
||||
})
|
||||
sw.SetIDFilter(func(id p2p.ID) error {
|
||||
resQuery, err := proxyApp.Query().QuerySync(abci.RequestQuery{Path: cmn.Fmt("/p2p/filter/pubkey/%s", id)})
|
||||
resQuery, err := proxyApp.Query().QuerySync(abci.RequestQuery{Path: cmn.Fmt("/p2p/filter/id/%s", id)})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
fail "github.com/ebuchman/fail-test"
|
||||
@@ -278,6 +279,16 @@ func updateValidators(currentSet *types.ValidatorSet, updates []abci.Validator)
|
||||
}
|
||||
|
||||
address := pubkey.Address()
|
||||
|
||||
// If the app provided an address too, it must match.
|
||||
// This is just a sanity check.
|
||||
if len(v.Address) > 0 {
|
||||
if !bytes.Equal(address, v.Address) {
|
||||
return fmt.Errorf("Validator.Address (%X) does not match PubKey.Address (%X)",
|
||||
v.Address, address)
|
||||
}
|
||||
}
|
||||
|
||||
power := int64(v.Power)
|
||||
// mind the overflow from int64
|
||||
if power < 0 {
|
||||
|
||||
@@ -32,20 +32,26 @@ type tm2pb struct{}
|
||||
|
||||
func (tm2pb) Header(header *Header) abci.Header {
|
||||
return abci.Header{
|
||||
ChainID: header.ChainID,
|
||||
Height: header.Height,
|
||||
Time: header.Time.Unix(),
|
||||
NumTxs: int32(header.NumTxs), // XXX: overflow
|
||||
ChainID: header.ChainID,
|
||||
Height: header.Height,
|
||||
|
||||
Time: header.Time.Unix(),
|
||||
NumTxs: int32(header.NumTxs), // XXX: overflow
|
||||
TotalTxs: header.NumTxs,
|
||||
|
||||
LastBlockHash: header.LastBlockID.Hash,
|
||||
ValidatorsHash: header.ValidatorsHash,
|
||||
AppHash: header.AppHash,
|
||||
|
||||
// Proposer: TODO
|
||||
}
|
||||
}
|
||||
|
||||
func (tm2pb) Validator(val *Validator) abci.Validator {
|
||||
return abci.Validator{
|
||||
PubKey: TM2PB.PubKey(val.PubKey),
|
||||
Power: val.VotingPower,
|
||||
Address: val.PubKey.Address(),
|
||||
PubKey: TM2PB.PubKey(val.PubKey),
|
||||
Power: val.VotingPower,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,28 +107,24 @@ func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci.
|
||||
panic(val)
|
||||
}
|
||||
|
||||
abciEvidence := abci.Evidence{
|
||||
Validator: abci.Validator{
|
||||
Address: ev.Address(),
|
||||
PubKey: TM2PB.PubKey(val.PubKey),
|
||||
Power: val.VotingPower,
|
||||
},
|
||||
Height: ev.Height(),
|
||||
Time: evTime.Unix(),
|
||||
TotalVotingPower: valSet.TotalVotingPower(),
|
||||
}
|
||||
|
||||
// set type
|
||||
var evType string
|
||||
switch ev.(type) {
|
||||
case *DuplicateVoteEvidence:
|
||||
abciEvidence.Type = ABCIEvidenceTypeDuplicateVote
|
||||
evType = ABCIEvidenceTypeDuplicateVote
|
||||
case *MockGoodEvidence, MockGoodEvidence:
|
||||
abciEvidence.Type = ABCIEvidenceTypeMockGood
|
||||
evType = ABCIEvidenceTypeMockGood
|
||||
default:
|
||||
panic(fmt.Sprintf("Unknown evidence type: %v %v", ev, reflect.TypeOf(ev)))
|
||||
}
|
||||
|
||||
return abciEvidence
|
||||
return abci.Evidence{
|
||||
Type: evType,
|
||||
Validator: TM2PB.Validator(val),
|
||||
Height: ev.Height(),
|
||||
Time: evTime.Unix(),
|
||||
TotalVotingPower: valSet.TotalVotingPower(),
|
||||
}
|
||||
}
|
||||
|
||||
func (tm2pb) ValidatorFromPubKeyAndPower(pubkey crypto.PubKey, power int64) abci.Validator {
|
||||
@@ -165,3 +167,19 @@ func (pb2tm) PubKey(pubKey abci.PubKey) (crypto.PubKey, error) {
|
||||
return nil, fmt.Errorf("Unknown pubkey type %v", pubKey.Type)
|
||||
}
|
||||
}
|
||||
|
||||
func (pb2tm) Validators(vals []abci.Validator) ([]*Validator, error) {
|
||||
tmVals := make([]*Validator, len(vals))
|
||||
for i, v := range vals {
|
||||
pub, err := PB2TM.PubKey(v.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
tmVals[i] = &Validator{
|
||||
Address: v.Address,
|
||||
PubKey: pub,
|
||||
VotingPower: v.Power,
|
||||
}
|
||||
}
|
||||
return tmVals, nil
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@ package version
|
||||
// Version components
|
||||
const (
|
||||
Maj = "0"
|
||||
Min = "19"
|
||||
Fix = "10"
|
||||
Min = "20"
|
||||
Fix = "0"
|
||||
)
|
||||
|
||||
var (
|
||||
// Version is the current version of Tendermint
|
||||
// Must be a string because scripts like dist.sh read this file.
|
||||
Version = "0.19.10-dev"
|
||||
Version = "0.20.0-dev"
|
||||
|
||||
// GitCommit is the current HEAD set using ldflags.
|
||||
GitCommit string
|
||||
|
||||
Reference in New Issue
Block a user