github.com/klaytn/klaytn@v1.10.2/consensus/istanbul/types.go (about)

     1  // Modifications Copyright 2018 The klaytn Authors
     2  // Copyright 2017 The go-ethereum Authors
     3  // This file is part of the go-ethereum library.
     4  //
     5  // The go-ethereum library is free software: you can redistribute it and/or modify
     6  // it under the terms of the GNU Lesser General Public License as published by
     7  // the Free Software Foundation, either version 3 of the License, or
     8  // (at your option) any later version.
     9  //
    10  // The go-ethereum library is distributed in the hope that it will be useful,
    11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    13  // GNU Lesser General Public License for more details.
    14  //
    15  // You should have received a copy of the GNU Lesser General Public License
    16  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    17  //
    18  // This file is derived from quorum/consensus/istanbul/types.go (2018/06/04).
    19  // Modified and improved for the klaytn development.
    20  
    21  package istanbul
    22  
    23  import (
    24  	"fmt"
    25  	"io"
    26  	"math/big"
    27  
    28  	"github.com/klaytn/klaytn/blockchain/types"
    29  	"github.com/klaytn/klaytn/common"
    30  	"github.com/klaytn/klaytn/rlp"
    31  )
    32  
    33  // Proposal supports retrieving height and serialized block to be used during Istanbul consensus.
    34  type Proposal interface {
    35  	// Number retrieves the sequence number of this proposal
    36  	Number() *big.Int
    37  
    38  	// Hash retrieves the hash of this proposal
    39  	Hash() common.Hash
    40  
    41  	EncodeRLP(w io.Writer) error
    42  
    43  	DecodeRLP(s *rlp.Stream) error
    44  
    45  	String() string
    46  
    47  	ParentHash() common.Hash
    48  
    49  	Header() *types.Header
    50  
    51  	WithSeal(header *types.Header) *types.Block
    52  }
    53  
    54  type Request struct {
    55  	Proposal Proposal
    56  }
    57  
    58  // View includes a round number and a sequence number.
    59  // Sequence is the block number we'd like to commit.
    60  // Each round has a number and is composed by 3 steps: preprepare, prepare and commit.
    61  //
    62  // If the given block is not accepted by validators, a round change will occur
    63  // and the validators start a new round with round+1.
    64  type View struct {
    65  	Round    *big.Int
    66  	Sequence *big.Int
    67  }
    68  
    69  // EncodeRLP serializes a View into the Klaytn RLP format.
    70  func (v *View) EncodeRLP(w io.Writer) error {
    71  	return rlp.Encode(w, []interface{}{v.Round, v.Sequence})
    72  }
    73  
    74  func (v *View) DecodeRLP(s *rlp.Stream) error {
    75  	var view struct {
    76  		Round    *big.Int
    77  		Sequence *big.Int
    78  	}
    79  
    80  	if err := s.Decode(&view); err != nil {
    81  		return err
    82  	}
    83  	v.Round, v.Sequence = view.Round, view.Sequence
    84  	return nil
    85  }
    86  
    87  func (v *View) String() string {
    88  	return fmt.Sprintf("{Round: %d, Sequence: %d}", v.Round.Uint64(), v.Sequence.Uint64())
    89  }
    90  
    91  // Cmp compares v and y and returns:
    92  // -1 if v < y
    93  //  0 if v == y
    94  // +1 if v > y
    95  func (v *View) Cmp(y *View) int {
    96  	sdiff := v.Sequence.Cmp(y.Sequence)
    97  	if sdiff != 0 {
    98  		return sdiff
    99  	}
   100  	rdiff := v.Round.Cmp(y.Round)
   101  	if rdiff != 0 {
   102  		return rdiff
   103  	}
   104  	return 0
   105  }
   106  
   107  type Preprepare struct {
   108  	View     *View
   109  	Proposal Proposal
   110  }
   111  
   112  func (b *Preprepare) EncodeRLP(w io.Writer) error {
   113  	return rlp.Encode(w, []interface{}{b.View, b.Proposal})
   114  }
   115  
   116  func (b *Preprepare) DecodeRLP(s *rlp.Stream) error {
   117  	var preprepare struct {
   118  		View     *View
   119  		Proposal *types.Block
   120  	}
   121  
   122  	if err := s.Decode(&preprepare); err != nil {
   123  		return err
   124  	}
   125  	b.View, b.Proposal = preprepare.View, preprepare.Proposal
   126  
   127  	return nil
   128  }
   129  
   130  type Subject struct {
   131  	View     *View
   132  	Digest   common.Hash
   133  	PrevHash common.Hash
   134  }
   135  
   136  func (b *Subject) EncodeRLP(w io.Writer) error {
   137  	return rlp.Encode(w, []interface{}{b.View, b.Digest, b.PrevHash})
   138  }
   139  
   140  func (b *Subject) DecodeRLP(s *rlp.Stream) error {
   141  	var subject struct {
   142  		View     *View
   143  		Digest   common.Hash
   144  		PrevHash common.Hash
   145  	}
   146  
   147  	if err := s.Decode(&subject); err != nil {
   148  		return err
   149  	}
   150  	b.View, b.Digest, b.PrevHash = subject.View, subject.Digest, subject.PrevHash
   151  
   152  	return nil
   153  }
   154  
   155  func (b *Subject) String() string {
   156  	return fmt.Sprintf("{View: %v, Digest: %v, ParentHash: %v}", b.View, b.Digest.String(), b.PrevHash.Hex())
   157  }
   158  
   159  type ConsensusMsg struct {
   160  	PrevHash common.Hash
   161  	Payload  []byte
   162  }