github.com/evdatsion/aphelion-dpos-bft@v0.32.1/types/protobuf.go (about)

     1  package types
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  	"time"
     7  
     8  	abci "github.com/evdatsion/aphelion-dpos-bft/abci/types"
     9  	"github.com/evdatsion/aphelion-dpos-bft/crypto"
    10  	"github.com/evdatsion/aphelion-dpos-bft/crypto/ed25519"
    11  	"github.com/evdatsion/aphelion-dpos-bft/crypto/secp256k1"
    12  )
    13  
    14  //-------------------------------------------------------
    15  // Use strings to distinguish types in ABCI messages
    16  
    17  const (
    18  	ABCIEvidenceTypeDuplicateVote = "duplicate/vote"
    19  	ABCIEvidenceTypeMockGood      = "mock/good"
    20  )
    21  
    22  const (
    23  	ABCIPubKeyTypeEd25519   = "ed25519"
    24  	ABCIPubKeyTypeSecp256k1 = "secp256k1"
    25  )
    26  
    27  // TODO: Make non-global by allowing for registration of more pubkey types
    28  var ABCIPubKeyTypesToAminoNames = map[string]string{
    29  	ABCIPubKeyTypeEd25519:   ed25519.PubKeyAminoName,
    30  	ABCIPubKeyTypeSecp256k1: secp256k1.PubKeyAminoName,
    31  }
    32  
    33  //-------------------------------------------------------
    34  
    35  // TM2PB is used for converting Tendermint ABCI to protobuf ABCI.
    36  // UNSTABLE
    37  var TM2PB = tm2pb{}
    38  
    39  type tm2pb struct{}
    40  
    41  func (tm2pb) Header(header *Header) abci.Header {
    42  	return abci.Header{
    43  		Version: abci.Version{
    44  			Block: header.Version.Block.Uint64(),
    45  			App:   header.Version.App.Uint64(),
    46  		},
    47  		ChainID:  header.ChainID,
    48  		Height:   header.Height,
    49  		Time:     header.Time,
    50  		NumTxs:   header.NumTxs,
    51  		TotalTxs: header.TotalTxs,
    52  
    53  		LastBlockId: TM2PB.BlockID(header.LastBlockID),
    54  
    55  		LastCommitHash: header.LastCommitHash,
    56  		DataHash:       header.DataHash,
    57  
    58  		ValidatorsHash:     header.ValidatorsHash,
    59  		NextValidatorsHash: header.NextValidatorsHash,
    60  		ConsensusHash:      header.ConsensusHash,
    61  		AppHash:            header.AppHash,
    62  		LastResultsHash:    header.LastResultsHash,
    63  
    64  		EvidenceHash:    header.EvidenceHash,
    65  		ProposerAddress: header.ProposerAddress,
    66  	}
    67  }
    68  
    69  func (tm2pb) Validator(val *Validator) abci.Validator {
    70  	return abci.Validator{
    71  		Address: val.PubKey.Address(),
    72  		Power:   val.VotingPower,
    73  	}
    74  }
    75  
    76  func (tm2pb) BlockID(blockID BlockID) abci.BlockID {
    77  	return abci.BlockID{
    78  		Hash:        blockID.Hash,
    79  		PartsHeader: TM2PB.PartSetHeader(blockID.PartsHeader),
    80  	}
    81  }
    82  
    83  func (tm2pb) PartSetHeader(header PartSetHeader) abci.PartSetHeader {
    84  	return abci.PartSetHeader{
    85  		Total: int32(header.Total),
    86  		Hash:  header.Hash,
    87  	}
    88  }
    89  
    90  // XXX: panics on unknown pubkey type
    91  func (tm2pb) ValidatorUpdate(val *Validator) abci.ValidatorUpdate {
    92  	return abci.ValidatorUpdate{
    93  		PubKey: TM2PB.PubKey(val.PubKey),
    94  		Power:  val.VotingPower,
    95  	}
    96  }
    97  
    98  // XXX: panics on nil or unknown pubkey type
    99  // TODO: add cases when new pubkey types are added to crypto
   100  func (tm2pb) PubKey(pubKey crypto.PubKey) abci.PubKey {
   101  	switch pk := pubKey.(type) {
   102  	case ed25519.PubKeyEd25519:
   103  		return abci.PubKey{
   104  			Type: ABCIPubKeyTypeEd25519,
   105  			Data: pk[:],
   106  		}
   107  	case secp256k1.PubKeySecp256k1:
   108  		return abci.PubKey{
   109  			Type: ABCIPubKeyTypeSecp256k1,
   110  			Data: pk[:],
   111  		}
   112  	default:
   113  		panic(fmt.Sprintf("unknown pubkey type: %v %v", pubKey, reflect.TypeOf(pubKey)))
   114  	}
   115  }
   116  
   117  // XXX: panics on nil or unknown pubkey type
   118  func (tm2pb) ValidatorUpdates(vals *ValidatorSet) []abci.ValidatorUpdate {
   119  	validators := make([]abci.ValidatorUpdate, vals.Size())
   120  	for i, val := range vals.Validators {
   121  		validators[i] = TM2PB.ValidatorUpdate(val)
   122  	}
   123  	return validators
   124  }
   125  
   126  func (tm2pb) ConsensusParams(params *ConsensusParams) *abci.ConsensusParams {
   127  	return &abci.ConsensusParams{
   128  		Block: &abci.BlockParams{
   129  			MaxBytes: params.Block.MaxBytes,
   130  			MaxGas:   params.Block.MaxGas,
   131  		},
   132  		Evidence: &abci.EvidenceParams{
   133  			MaxAge: params.Evidence.MaxAge,
   134  		},
   135  		Validator: &abci.ValidatorParams{
   136  			PubKeyTypes: params.Validator.PubKeyTypes,
   137  		},
   138  	}
   139  }
   140  
   141  // ABCI Evidence includes information from the past that's not included in the evidence itself
   142  // so Evidence types stays compact.
   143  // XXX: panics on nil or unknown pubkey type
   144  func (tm2pb) Evidence(ev Evidence, valSet *ValidatorSet, evTime time.Time) abci.Evidence {
   145  	_, val := valSet.GetByAddress(ev.Address())
   146  	if val == nil {
   147  		// should already have checked this
   148  		panic(val)
   149  	}
   150  
   151  	// set type
   152  	var evType string
   153  	switch ev.(type) {
   154  	case *DuplicateVoteEvidence:
   155  		evType = ABCIEvidenceTypeDuplicateVote
   156  	case MockGoodEvidence:
   157  		// XXX: not great to have test types in production paths ...
   158  		evType = ABCIEvidenceTypeMockGood
   159  	default:
   160  		panic(fmt.Sprintf("Unknown evidence type: %v %v", ev, reflect.TypeOf(ev)))
   161  	}
   162  
   163  	return abci.Evidence{
   164  		Type:             evType,
   165  		Validator:        TM2PB.Validator(val),
   166  		Height:           ev.Height(),
   167  		Time:             evTime,
   168  		TotalVotingPower: valSet.TotalVotingPower(),
   169  	}
   170  }
   171  
   172  // XXX: panics on nil or unknown pubkey type
   173  func (tm2pb) NewValidatorUpdate(pubkey crypto.PubKey, power int64) abci.ValidatorUpdate {
   174  	pubkeyABCI := TM2PB.PubKey(pubkey)
   175  	return abci.ValidatorUpdate{
   176  		PubKey: pubkeyABCI,
   177  		Power:  power,
   178  	}
   179  }
   180  
   181  //----------------------------------------------------------------------------
   182  
   183  // PB2TM is used for converting protobuf ABCI to Tendermint ABCI.
   184  // UNSTABLE
   185  var PB2TM = pb2tm{}
   186  
   187  type pb2tm struct{}
   188  
   189  func (pb2tm) PubKey(pubKey abci.PubKey) (crypto.PubKey, error) {
   190  	switch pubKey.Type {
   191  	case ABCIPubKeyTypeEd25519:
   192  		if len(pubKey.Data) != ed25519.PubKeyEd25519Size {
   193  			return nil, fmt.Errorf("Invalid size for PubKeyEd25519. Got %d, expected %d",
   194  				len(pubKey.Data), ed25519.PubKeyEd25519Size)
   195  		}
   196  		var pk ed25519.PubKeyEd25519
   197  		copy(pk[:], pubKey.Data)
   198  		return pk, nil
   199  	case ABCIPubKeyTypeSecp256k1:
   200  		if len(pubKey.Data) != secp256k1.PubKeySecp256k1Size {
   201  			return nil, fmt.Errorf("Invalid size for PubKeySecp256k1. Got %d, expected %d",
   202  				len(pubKey.Data), secp256k1.PubKeySecp256k1Size)
   203  		}
   204  		var pk secp256k1.PubKeySecp256k1
   205  		copy(pk[:], pubKey.Data)
   206  		return pk, nil
   207  	default:
   208  		return nil, fmt.Errorf("Unknown pubkey type %v", pubKey.Type)
   209  	}
   210  }
   211  
   212  func (pb2tm) ValidatorUpdates(vals []abci.ValidatorUpdate) ([]*Validator, error) {
   213  	tmVals := make([]*Validator, len(vals))
   214  	for i, v := range vals {
   215  		pub, err := PB2TM.PubKey(v.PubKey)
   216  		if err != nil {
   217  			return nil, err
   218  		}
   219  		tmVals[i] = NewValidator(pub, v.Power)
   220  	}
   221  	return tmVals, nil
   222  }