mirror of https://github.com/poanetwork/quorum.git
148 lines
3.8 KiB
Go
148 lines
3.8 KiB
Go
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
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())
|
|
}
|