mirror of
https://github.com/fluencelabs/tendermint
synced 2025-04-25 06:42:16 +00:00
See https://github.com/tendermint/tendermint/pull/3403/files#r266208947 In #3403 we unexposed BlockTimeIota from the ABCI, but it's still part of the ConsensusParams struct, so we have to remember to add it back after calling PB2TM.ConsensusParams. Instead, PB2TM.ConsensusParams should take it as an argument Fixes #3432
256 lines
6.6 KiB
Go
256 lines
6.6 KiB
Go
package types
|
|
|
|
import (
|
|
"fmt"
|
|
"reflect"
|
|
"time"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/crypto"
|
|
"github.com/tendermint/tendermint/crypto/ed25519"
|
|
"github.com/tendermint/tendermint/crypto/secp256k1"
|
|
)
|
|
|
|
//-------------------------------------------------------
|
|
// Use strings to distinguish types in ABCI messages
|
|
|
|
const (
|
|
ABCIEvidenceTypeDuplicateVote = "duplicate/vote"
|
|
ABCIEvidenceTypeMockGood = "mock/good"
|
|
)
|
|
|
|
const (
|
|
ABCIPubKeyTypeEd25519 = "ed25519"
|
|
ABCIPubKeyTypeSecp256k1 = "secp256k1"
|
|
)
|
|
|
|
// TODO: Make non-global by allowing for registration of more pubkey types
|
|
var ABCIPubKeyTypesToAminoNames = map[string]string{
|
|
ABCIPubKeyTypeEd25519: ed25519.PubKeyAminoName,
|
|
ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyAminoName,
|
|
}
|
|
|
|
//-------------------------------------------------------
|
|
|
|
// TM2PB is used for converting Tendermint ABCI to protobuf ABCI.
|
|
// UNSTABLE
|
|
var TM2PB = tm2pb{}
|
|
|
|
type tm2pb struct{}
|
|
|
|
func (tm2pb) Header(header *Header) abci.Header {
|
|
return abci.Header{
|
|
Version: abci.Version{
|
|
Block: header.Version.Block.Uint64(),
|
|
App: header.Version.App.Uint64(),
|
|
},
|
|
ChainID: header.ChainID,
|
|
Height: header.Height,
|
|
Time: header.Time,
|
|
NumTxs: header.NumTxs,
|
|
TotalTxs: header.TotalTxs,
|
|
|
|
LastBlockId: TM2PB.BlockID(header.LastBlockID),
|
|
|
|
LastCommitHash: header.LastCommitHash,
|
|
DataHash: header.DataHash,
|
|
|
|
ValidatorsHash: header.ValidatorsHash,
|
|
NextValidatorsHash: header.NextValidatorsHash,
|
|
ConsensusHash: header.ConsensusHash,
|
|
AppHash: header.AppHash,
|
|
LastResultsHash: header.LastResultsHash,
|
|
|
|
EvidenceHash: header.EvidenceHash,
|
|
ProposerAddress: header.ProposerAddress,
|
|
}
|
|
}
|
|
|
|
func (tm2pb) Validator(val *Validator) abci.Validator {
|
|
return abci.Validator{
|
|
Address: val.PubKey.Address(),
|
|
Power: val.VotingPower,
|
|
}
|
|
}
|
|
|
|
func (tm2pb) BlockID(blockID BlockID) abci.BlockID {
|
|
return abci.BlockID{
|
|
Hash: blockID.Hash,
|
|
PartsHeader: TM2PB.PartSetHeader(blockID.PartsHeader),
|
|
}
|
|
}
|
|
|
|
func (tm2pb) PartSetHeader(header PartSetHeader) abci.PartSetHeader {
|
|
return abci.PartSetHeader{
|
|
Total: int32(header.Total),
|
|
Hash: header.Hash,
|
|
}
|
|
}
|
|
|
|
// XXX: panics on unknown pubkey type
|
|
func (tm2pb) ValidatorUpdate(val *Validator) abci.ValidatorUpdate {
|
|
return abci.ValidatorUpdate{
|
|
PubKey: TM2PB.PubKey(val.PubKey),
|
|
Power: val.VotingPower,
|
|
}
|
|
}
|
|
|
|
// XXX: panics on nil or unknown pubkey type
|
|
// TODO: add cases when new pubkey types are added to crypto
|
|
func (tm2pb) PubKey(pubKey crypto.PubKey) abci.PubKey {
|
|
switch pk := pubKey.(type) {
|
|
case ed25519.PubKeyEd25519:
|
|
return abci.PubKey{
|
|
Type: ABCIPubKeyTypeEd25519,
|
|
Data: pk[:],
|
|
}
|
|
case secp256k1.PubKeySecp256k1:
|
|
return abci.PubKey{
|
|
Type: ABCIPubKeyTypeSecp256k1,
|
|
Data: pk[:],
|
|
}
|
|
default:
|
|
panic(fmt.Sprintf("unknown pubkey type: %v %v", pubKey, reflect.TypeOf(pubKey)))
|
|
}
|
|
}
|
|
|
|
// XXX: panics on nil or unknown pubkey type
|
|
func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate {
|
|
validators := make([]abci.ValidatorUpdate, vals.Size())
|
|
for i, val := range vals.Validators {
|
|
validators[i] = TM2PB.ValidatorUpdate(val)
|
|
}
|
|
return validators
|
|
}
|
|
|
|
func (tm2pb) ConsensusParams(params *ConsensusParams) *abci.ConsensusParams {
|
|
return &abci.ConsensusParams{
|
|
Block: &abci.BlockParams{
|
|
MaxBytes: params.Block.MaxBytes,
|
|
MaxGas: params.Block.MaxGas,
|
|
},
|
|
Evidence: &abci.EvidenceParams{
|
|
MaxAge: params.Evidence.MaxAge,
|
|
},
|
|
Validator: &abci.ValidatorParams{
|
|
PubKeyTypes: params.Validator.PubKeyTypes,
|
|
},
|
|
}
|
|
}
|
|
|
|
// ABCI Evidence includes information from the past that's not included in the evidence itself
|
|
// so Evidence types stays compact.
|
|
// XXX: panics on nil or unknown pubkey type
|
|
func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci.Evidence {
|
|
_, val := valSet.GetByAddress(ev.Address())
|
|
if val == nil {
|
|
// should already have checked this
|
|
panic(val)
|
|
}
|
|
|
|
// set type
|
|
var evType string
|
|
switch ev.(type) {
|
|
case *DuplicateVoteEvidence:
|
|
evType = ABCIEvidenceTypeDuplicateVote
|
|
case MockGoodEvidence:
|
|
// XXX: not great to have test types in production paths ...
|
|
evType = ABCIEvidenceTypeMockGood
|
|
default:
|
|
panic(fmt.Sprintf("Unknown evidence type: %v %v", ev, reflect.TypeOf(ev)))
|
|
}
|
|
|
|
return abci.Evidence{
|
|
Type: evType,
|
|
Validator: TM2PB.Validator(val),
|
|
Height: ev.Height(),
|
|
Time: evTime,
|
|
TotalVotingPower: valSet.TotalVotingPower(),
|
|
}
|
|
}
|
|
|
|
// XXX: panics on nil or unknown pubkey type
|
|
func (tm2pb) NewValidatorUpdate(pubkey crypto.PubKey, power int64) abci.ValidatorUpdate {
|
|
pubkeyABCI := TM2PB.PubKey(pubkey)
|
|
return abci.ValidatorUpdate{
|
|
PubKey: pubkeyABCI,
|
|
Power: power,
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
// PB2TM is used for converting protobuf ABCI to Tendermint ABCI.
|
|
// UNSTABLE
|
|
var PB2TM = pb2tm{}
|
|
|
|
type pb2tm struct{}
|
|
|
|
func (pb2tm) PubKey(pubKey abci.PubKey) (crypto.PubKey, error) {
|
|
switch pubKey.Type {
|
|
case ABCIPubKeyTypeEd25519:
|
|
if len(pubKey.Data) != ed25519.PubKeyEd25519Size {
|
|
return nil, fmt.Errorf("Invalid size for PubKeyEd25519. Got %d, expected %d",
|
|
len(pubKey.Data), ed25519.PubKeyEd25519Size)
|
|
}
|
|
var pk ed25519.PubKeyEd25519
|
|
copy(pk[:], pubKey.Data)
|
|
return pk, nil
|
|
case ABCIPubKeyTypeSecp256k1:
|
|
if len(pubKey.Data) != secp256k1.PubKeySecp256k1Size {
|
|
return nil, fmt.Errorf("Invalid size for PubKeySecp256k1. Got %d, expected %d",
|
|
len(pubKey.Data), secp256k1.PubKeySecp256k1Size)
|
|
}
|
|
var pk secp256k1.PubKeySecp256k1
|
|
copy(pk[:], pubKey.Data)
|
|
return pk, nil
|
|
default:
|
|
return nil, fmt.Errorf("Unknown pubkey type %v", pubKey.Type)
|
|
}
|
|
}
|
|
|
|
func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*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] = NewValidator(pub, v.Power)
|
|
}
|
|
return tmVals, nil
|
|
}
|
|
|
|
// BlockParams.TimeIotaMs is not exposed to the application. Therefore a caller
|
|
// must provide it.
|
|
func (pb2tm) ConsensusParams(csp *abci.ConsensusParams, blockTimeIotaMs int64) ConsensusParams {
|
|
params := ConsensusParams{
|
|
Block: BlockParams{},
|
|
Evidence: EvidenceParams{},
|
|
Validator: ValidatorParams{},
|
|
}
|
|
|
|
// we must defensively consider any structs may be nil
|
|
if csp.Block != nil {
|
|
params.Block = BlockParams{
|
|
MaxBytes: csp.Block.MaxBytes,
|
|
MaxGas: csp.Block.MaxGas,
|
|
TimeIotaMs: blockTimeIotaMs,
|
|
}
|
|
}
|
|
|
|
if csp.Evidence != nil {
|
|
params.Evidence = EvidenceParams{
|
|
MaxAge: csp.Evidence.MaxAge,
|
|
}
|
|
}
|
|
|
|
if csp.Validator != nil {
|
|
params.Validator = ValidatorParams{
|
|
PubKeyTypes: csp.Validator.PubKeyTypes,
|
|
}
|
|
}
|
|
|
|
return params
|
|
}
|