github.com/coltonfike/e2c@v21.1.0+incompatible/core/types/istanbul.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 types
    18  
    19  import (
    20  	"errors"
    21  	"io"
    22  
    23  	"github.com/ethereum/go-ethereum/common"
    24  	"github.com/ethereum/go-ethereum/rlp"
    25  )
    26  
    27  var (
    28  	// IstanbulDigest represents a hash of "Istanbul practical byzantine fault tolerance"
    29  	// to identify whether the block is from Istanbul consensus engine
    30  	IstanbulDigest = common.HexToHash("0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365")
    31  
    32  	IstanbulExtraVanity = 32 // Fixed number of extra-data bytes reserved for validator vanity
    33  	IstanbulExtraSeal   = 65 // Fixed number of extra-data bytes reserved for validator seal
    34  
    35  	// ErrInvalidIstanbulHeaderExtra is returned if the length of extra-data is less than 32 bytes
    36  	ErrInvalidIstanbulHeaderExtra = errors.New("invalid istanbul header extra-data")
    37  )
    38  
    39  type IstanbulExtra struct {
    40  	Validators    []common.Address
    41  	Seal          []byte
    42  	CommittedSeal [][]byte
    43  }
    44  
    45  // EncodeRLP serializes ist into the Ethereum RLP format.
    46  func (ist *IstanbulExtra) EncodeRLP(w io.Writer) error {
    47  	return rlp.Encode(w, []interface{}{
    48  		ist.Validators,
    49  		ist.Seal,
    50  		ist.CommittedSeal,
    51  	})
    52  }
    53  
    54  // DecodeRLP implements rlp.Decoder, and load the istanbul fields from a RLP stream.
    55  func (ist *IstanbulExtra) DecodeRLP(s *rlp.Stream) error {
    56  	var istanbulExtra struct {
    57  		Validators    []common.Address
    58  		Seal          []byte
    59  		CommittedSeal [][]byte
    60  	}
    61  	if err := s.Decode(&istanbulExtra); err != nil {
    62  		return err
    63  	}
    64  	ist.Validators, ist.Seal, ist.CommittedSeal = istanbulExtra.Validators, istanbulExtra.Seal, istanbulExtra.CommittedSeal
    65  	return nil
    66  }
    67  
    68  // ExtractIstanbulExtra extracts all values of the IstanbulExtra from the header. It returns an
    69  // error if the length of the given extra-data is less than 32 bytes or the extra-data can not
    70  // be decoded.
    71  func ExtractIstanbulExtra(h *Header) (*IstanbulExtra, error) {
    72  	if len(h.Extra) < IstanbulExtraVanity {
    73  		return nil, ErrInvalidIstanbulHeaderExtra
    74  	}
    75  
    76  	var istanbulExtra *IstanbulExtra
    77  	err := rlp.DecodeBytes(h.Extra[IstanbulExtraVanity:], &istanbulExtra)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	return istanbulExtra, nil
    82  }
    83  
    84  // IstanbulFilteredHeader returns a filtered header which some information (like seal, committed seals)
    85  // are clean to fulfill the Istanbul hash rules. It returns nil if the extra-data cannot be
    86  // decoded/encoded by rlp.
    87  func IstanbulFilteredHeader(h *Header, keepSeal bool) *Header {
    88  	newHeader := CopyHeader(h)
    89  	istanbulExtra, err := ExtractIstanbulExtra(newHeader)
    90  	if err != nil {
    91  		return nil
    92  	}
    93  
    94  	if !keepSeal {
    95  		istanbulExtra.Seal = []byte{}
    96  	}
    97  	istanbulExtra.CommittedSeal = [][]byte{}
    98  
    99  	payload, err := rlp.EncodeToBytes(&istanbulExtra)
   100  	if err != nil {
   101  		return nil
   102  	}
   103  
   104  	newHeader.Extra = append(newHeader.Extra[:IstanbulExtraVanity], payload...)
   105  
   106  	return newHeader
   107  }