github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/types.go (about)

     1  // Copyright 2017 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package istanbul
    18  
    19  import (
    20  	"fmt"
    21  	"io"
    22  	"math/big"
    23  
    24  	"github.com/ethereum/go-ethereum/common"
    25  	"github.com/ethereum/go-ethereum/core/types"
    26  	"github.com/ethereum/go-ethereum/rlp"
    27  )
    28  
    29  // UptimeEntry contains the uptime score of a validator during an epoch as well as the
    30  // last block they signed on
    31  type UptimeEntry struct {
    32  	ScoreTally      uint64
    33  	LastSignedBlock uint64
    34  }
    35  
    36  func (u *UptimeEntry) String() string {
    37  	return fmt.Sprintf("UptimeEntry { scoreTally: %v, lastBlock: %v}", u.ScoreTally, u.LastSignedBlock)
    38  }
    39  
    40  // Uptime contains the latest block for which uptime metrics were accounted for. It also contains
    41  // an array of Entries where the `i`th entry represents the uptime statistics of the `i`th validator
    42  // in the validator set for that epoch
    43  type Uptime struct {
    44  	LatestBlock uint64
    45  	Entries     []UptimeEntry
    46  }
    47  
    48  // Proposal supports retrieving height and serialized block to be used during Istanbul consensus.
    49  type Proposal interface {
    50  	// Number retrieves the sequence number of this proposal.
    51  	Number() *big.Int
    52  
    53  	Header() *types.Header
    54  
    55  	// Hash retrieves the hash of this block
    56  	Hash() common.Hash
    57  
    58  	// ParentHash retrieves the hash of this block's parent
    59  	ParentHash() common.Hash
    60  
    61  	EncodeRLP(w io.Writer) error
    62  
    63  	DecodeRLP(s *rlp.Stream) error
    64  }
    65  
    66  // ## Request ##############################################################
    67  
    68  type Request struct {
    69  	Proposal Proposal
    70  }
    71  
    72  // EncodeRLP serializes b into the Ethereum RLP format.
    73  func (b *Request) EncodeRLP(w io.Writer) error {
    74  	return rlp.Encode(w, []interface{}{b.Proposal})
    75  }
    76  
    77  // DecodeRLP implements rlp.Decoder, and load the consensus fields from a RLP stream.
    78  func (b *Request) DecodeRLP(s *rlp.Stream) error {
    79  	var request struct {
    80  		Proposal *types.Block
    81  	}
    82  
    83  	if err := s.Decode(&request); err != nil {
    84  		return err
    85  	}
    86  
    87  	b.Proposal = request.Proposal
    88  	return nil
    89  }
    90  
    91  // ## View ##############################################################
    92  
    93  // View includes a round number and a sequence number.
    94  // Sequence is the block number we'd like to commit.
    95  // Each round has a number and is composed by 3 steps: preprepare, prepare and commit.
    96  //
    97  // If the given block is not accepted by validators, a round change will occur
    98  // and the validators start a new round with round+1.
    99  type View struct {
   100  	Round    *big.Int
   101  	Sequence *big.Int
   102  }
   103  
   104  func (v *View) String() string {
   105  	if v.Round == nil || v.Sequence == nil {
   106  		return "Invalid"
   107  	}
   108  	return fmt.Sprintf("{Round: %d, Sequence: %d}", v.Round.Uint64(), v.Sequence.Uint64())
   109  }
   110  
   111  // Cmp compares v and y and returns:
   112  //   -1 if v <  y
   113  //    0 if v == y
   114  //   +1 if v >  y
   115  func (v *View) Cmp(y *View) int {
   116  	if v.Sequence.Cmp(y.Sequence) != 0 {
   117  		return v.Sequence.Cmp(y.Sequence)
   118  	}
   119  	if v.Round.Cmp(y.Round) != 0 {
   120  		return v.Round.Cmp(y.Round)
   121  	}
   122  	return 0
   123  }
   124  
   125  // ## RoundChangeCertificate ##############################################################
   126  
   127  type RoundChangeCertificate struct {
   128  	RoundChangeMessages []Message
   129  }
   130  
   131  func (b *RoundChangeCertificate) IsEmpty() bool {
   132  	return len(b.RoundChangeMessages) == 0
   133  }
   134  
   135  // ## Preprepare ##############################################################
   136  
   137  type Preprepare struct {
   138  	View                   *View
   139  	Proposal               Proposal
   140  	RoundChangeCertificate RoundChangeCertificate
   141  }
   142  
   143  type PreprepareData struct {
   144  	View                   *View
   145  	Proposal               *types.Block
   146  	RoundChangeCertificate RoundChangeCertificate
   147  }
   148  
   149  type PreprepareSummary struct {
   150  	View                          *View            `json:"view"`
   151  	ProposalHash                  common.Hash      `json:"proposalHash"`
   152  	RoundChangeCertificateSenders []common.Address `json:"roundChangeCertificateSenders"`
   153  }
   154  
   155  func (pp *Preprepare) HasRoundChangeCertificate() bool {
   156  	return !pp.RoundChangeCertificate.IsEmpty()
   157  }
   158  
   159  func (pp *Preprepare) AsData() *PreprepareData {
   160  	return &PreprepareData{
   161  		View:                   pp.View,
   162  		Proposal:               pp.Proposal.(*types.Block),
   163  		RoundChangeCertificate: pp.RoundChangeCertificate,
   164  	}
   165  }
   166  
   167  func (pp *Preprepare) Summary() *PreprepareSummary {
   168  	return &PreprepareSummary{
   169  		View:                          pp.View,
   170  		ProposalHash:                  pp.Proposal.Hash(),
   171  		RoundChangeCertificateSenders: MapMessagesToSenders(pp.RoundChangeCertificate.RoundChangeMessages),
   172  	}
   173  }
   174  
   175  // RLP Encoding ---------------------------------------------------------------
   176  
   177  // EncodeRLP serializes b into the Ethereum RLP format.
   178  func (pp *Preprepare) EncodeRLP(w io.Writer) error {
   179  	return rlp.Encode(w, pp.AsData())
   180  }
   181  
   182  // DecodeRLP implements rlp.Decoder, and load the consensus fields from a RLP stream.
   183  func (pp *Preprepare) DecodeRLP(s *rlp.Stream) error {
   184  	var data PreprepareData
   185  	if err := s.Decode(&data); err != nil {
   186  		return err
   187  	}
   188  	pp.View, pp.Proposal, pp.RoundChangeCertificate = data.View, data.Proposal, data.RoundChangeCertificate
   189  	return nil
   190  }
   191  
   192  // ## PreparedCertificate #####################################################
   193  
   194  type PreparedCertificate struct {
   195  	Proposal                Proposal
   196  	PrepareOrCommitMessages []Message
   197  }
   198  
   199  type PreparedCertificateData struct {
   200  	Proposal                *types.Block
   201  	PrepareOrCommitMessages []Message
   202  }
   203  
   204  type PreparedCertificateSummary struct {
   205  	ProposalHash   common.Hash      `json:"proposalHash"`
   206  	PrepareSenders []common.Address `json:"prepareSenders"`
   207  	CommitSenders  []common.Address `json:"commitSenders"`
   208  }
   209  
   210  func EmptyPreparedCertificate() PreparedCertificate {
   211  	emptyHeader := &types.Header{
   212  		Difficulty: big.NewInt(0),
   213  		Number:     big.NewInt(0),
   214  		GasLimit:   0,
   215  		GasUsed:    0,
   216  		Time:       big.NewInt(0),
   217  	}
   218  	block := &types.Block{}
   219  	block = block.WithRandomness(&types.EmptyRandomness)
   220  	block = block.WithEpochSnarkData(&types.EmptyEpochSnarkData)
   221  
   222  	return PreparedCertificate{
   223  		Proposal:                block.WithSeal(emptyHeader),
   224  		PrepareOrCommitMessages: []Message{},
   225  	}
   226  }
   227  
   228  func (pc *PreparedCertificate) IsEmpty() bool {
   229  	return len(pc.PrepareOrCommitMessages) == 0
   230  }
   231  
   232  func (pc *PreparedCertificate) AsData() *PreparedCertificateData {
   233  	return &PreparedCertificateData{
   234  		Proposal:                pc.Proposal.(*types.Block),
   235  		PrepareOrCommitMessages: pc.PrepareOrCommitMessages,
   236  	}
   237  }
   238  
   239  func (pc *PreparedCertificate) Summary() *PreparedCertificateSummary {
   240  	var prepareSenders, commitSenders []common.Address
   241  	for _, msg := range pc.PrepareOrCommitMessages {
   242  		if msg.Code == MsgPrepare {
   243  			prepareSenders = append(prepareSenders, msg.Address)
   244  		} else {
   245  			commitSenders = append(commitSenders, msg.Address)
   246  		}
   247  	}
   248  
   249  	return &PreparedCertificateSummary{
   250  		ProposalHash:   pc.Proposal.Hash(),
   251  		PrepareSenders: prepareSenders,
   252  		CommitSenders:  commitSenders,
   253  	}
   254  }
   255  
   256  // RLP Encoding ---------------------------------------------------------------
   257  
   258  // EncodeRLP serializes b into the Ethereum RLP format.
   259  func (pc *PreparedCertificate) EncodeRLP(w io.Writer) error {
   260  	return rlp.Encode(w, pc.AsData())
   261  }
   262  
   263  // DecodeRLP implements rlp.Decoder, and load the consensus fields from a RLP stream.
   264  func (pc *PreparedCertificate) DecodeRLP(s *rlp.Stream) error {
   265  	var data PreparedCertificateData
   266  	if err := s.Decode(&data); err != nil {
   267  		return err
   268  	}
   269  	pc.PrepareOrCommitMessages, pc.Proposal = data.PrepareOrCommitMessages, data.Proposal
   270  	return nil
   271  
   272  }
   273  
   274  // ## RoundChange #############################################################
   275  
   276  type RoundChange struct {
   277  	View                *View
   278  	PreparedCertificate PreparedCertificate
   279  }
   280  
   281  func (b *RoundChange) HasPreparedCertificate() bool {
   282  	return !b.PreparedCertificate.IsEmpty()
   283  }
   284  
   285  // EncodeRLP serializes b into the Ethereum RLP format.
   286  func (b *RoundChange) EncodeRLP(w io.Writer) error {
   287  	return rlp.Encode(w, []interface{}{b.View, &b.PreparedCertificate})
   288  }
   289  
   290  // DecodeRLP implements rlp.Decoder, and load the consensus fields from a RLP stream.
   291  func (b *RoundChange) DecodeRLP(s *rlp.Stream) error {
   292  	var roundChange struct {
   293  		View                *View
   294  		PreparedCertificate PreparedCertificate
   295  	}
   296  
   297  	if err := s.Decode(&roundChange); err != nil {
   298  		return err
   299  	}
   300  	b.View, b.PreparedCertificate = roundChange.View, roundChange.PreparedCertificate
   301  	return nil
   302  }
   303  
   304  // ## Subject #################################################################
   305  
   306  type Subject struct {
   307  	View   *View
   308  	Digest common.Hash
   309  }
   310  
   311  func (s *Subject) String() string {
   312  	return fmt.Sprintf("{View: %v, Digest: %v}", s.View, s.Digest.String())
   313  }
   314  
   315  // ## CommittedSubject #################################################################
   316  
   317  type CommittedSubject struct {
   318  	Subject               *Subject
   319  	CommittedSeal         []byte
   320  	EpochValidatorSetSeal []byte
   321  }
   322  
   323  // ## ForwardMessage #################################################################
   324  
   325  type ForwardMessage struct {
   326  	Msg           []byte
   327  	DestAddresses []common.Address
   328  }
   329  
   330  // ## Message #################################################################
   331  
   332  const (
   333  	MsgPreprepare uint64 = iota
   334  	MsgPrepare
   335  	MsgCommit
   336  	MsgRoundChange
   337  )
   338  
   339  type Message struct {
   340  	Code      uint64
   341  	Msg       []byte
   342  	Address   common.Address // The sender address
   343  	Signature []byte         // Signature of the Message using the private key associated with the "Address" field
   344  }
   345  
   346  // define the functions that needs to be provided for core.
   347  
   348  func (m *Message) Sign(signingFn func(data []byte) ([]byte, error)) error {
   349  	// Construct and encode a message with no signature
   350  	payloadNoSig, err := m.PayloadNoSig()
   351  	if err != nil {
   352  		return err
   353  	}
   354  	m.Signature, err = signingFn(payloadNoSig)
   355  	return err
   356  }
   357  
   358  func (m *Message) FromPayload(b []byte, validateFn func([]byte, []byte) (common.Address, error)) error {
   359  	// Decode Message
   360  	err := rlp.DecodeBytes(b, &m)
   361  	if err != nil {
   362  		return err
   363  	}
   364  
   365  	// Validate message (on a message without Signature)
   366  	if validateFn != nil {
   367  		var payload []byte
   368  		payload, err = m.PayloadNoSig()
   369  		if err != nil {
   370  			return err
   371  		}
   372  
   373  		signed_val_addr, err := validateFn(payload, m.Signature)
   374  		if err != nil {
   375  			return err
   376  		}
   377  		if signed_val_addr != m.Address {
   378  			return ErrInvalidSigner
   379  		}
   380  	}
   381  	return nil
   382  }
   383  
   384  func (m *Message) Payload() ([]byte, error) {
   385  	return rlp.EncodeToBytes(m)
   386  }
   387  
   388  func (m *Message) PayloadNoSig() ([]byte, error) {
   389  	return rlp.EncodeToBytes(&Message{
   390  		Code:      m.Code,
   391  		Msg:       m.Msg,
   392  		Address:   m.Address,
   393  		Signature: []byte{},
   394  	})
   395  }
   396  
   397  func (m *Message) Decode(val interface{}) error {
   398  	return rlp.DecodeBytes(m.Msg, val)
   399  }
   400  
   401  func (m *Message) String() string {
   402  	return fmt.Sprintf("{Code: %v, Address: %v}", m.Code, m.Address.String())
   403  }
   404  
   405  // MapMessagesToSenders map a list of Messages to the list of the sender addresses
   406  func MapMessagesToSenders(messages []Message) []common.Address {
   407  	returnList := make([]common.Address, len(messages))
   408  
   409  	for i, ms := range messages {
   410  		returnList[i] = ms.Address
   411  	}
   412  
   413  	return returnList
   414  }