// Copyright 2017 The go-ethereum Authors // This file is part of the go-ethereum library. // // The go-ethereum library is free software: you can redistribute it and/or modify // it under the terms of the GNU Lesser General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // The go-ethereum library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public License // along with the go-ethereum library. If not, see . package istanbul import ( "fmt" "io" "math/big" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" ) // Proposal supports retrieving height and serialized block to be used during Istanbul consensus. type Proposal interface { // Number retrieves the sequence number of this proposal. Number() *big.Int // Hash retrieves the hash of this proposal. Hash() common.Hash EncodeRLP(w io.Writer) error DecodeRLP(s *rlp.Stream) error String() string } type Request struct { Proposal Proposal } // View includes a round number and a sequence number. // Sequence is the block number we'd like to commit. // Each round has a number and is composed by 3 steps: preprepare, prepare and commit. // // If the given block is not accepted by validators, a round change will occur // and the validators start a new round with round+1. type View struct { Round *big.Int Sequence *big.Int } // EncodeRLP serializes b into the Ethereum RLP format. func (v *View) EncodeRLP(w io.Writer) error { return rlp.Encode(w, []interface{}{v.Round, v.Sequence}) } // DecodeRLP implements rlp.Decoder, and load the consensus fields from a RLP stream. func (v *View) DecodeRLP(s *rlp.Stream) error { var view struct { Round *big.Int Sequence *big.Int } if err := s.Decode(&view); err != nil { return err } v.Round, v.Sequence = view.Round, view.Sequence return nil } func (v *View) String() string { return fmt.Sprintf("{Round: %d, Sequence: %d}", v.Round.Uint64(), v.Sequence.Uint64()) } // Cmp compares v and y and returns: // -1 if v < y // 0 if v == y // +1 if v > y func (v *View) Cmp(y *View) int { if v.Sequence.Cmp(y.Sequence) != 0 { return v.Sequence.Cmp(y.Sequence) } if v.Round.Cmp(y.Round) != 0 { return v.Round.Cmp(y.Round) } return 0 } type Preprepare struct { View *View Proposal Proposal } // EncodeRLP serializes b into the Ethereum RLP format. func (b *Preprepare) EncodeRLP(w io.Writer) error { return rlp.Encode(w, []interface{}{b.View, b.Proposal}) } // DecodeRLP implements rlp.Decoder, and load the consensus fields from a RLP stream. func (b *Preprepare) DecodeRLP(s *rlp.Stream) error { var preprepare struct { View *View Proposal *types.Block } if err := s.Decode(&preprepare); err != nil { return err } b.View, b.Proposal = preprepare.View, preprepare.Proposal return nil } type Subject struct { View *View Digest common.Hash } // EncodeRLP serializes b into the Ethereum RLP format. func (b *Subject) EncodeRLP(w io.Writer) error { return rlp.Encode(w, []interface{}{b.View, b.Digest}) } // DecodeRLP implements rlp.Decoder, and load the consensus fields from a RLP stream. func (b *Subject) DecodeRLP(s *rlp.Stream) error { var subject struct { View *View Digest common.Hash } if err := s.Decode(&subject); err != nil { return err } b.View, b.Digest = subject.View, subject.Digest return nil } func (b *Subject) String() string { return fmt.Sprintf("{View: %v, Digest: %v}", b.View, b.Digest.String()) }