github.com/Blockdaemon/celo-blockchain@v0.0.0-20200129231733-e667f6b08419/consensus/istanbul/utils.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  	"encoding/hex"
    21  	"errors"
    22  	blscrypto "github.com/ethereum/go-ethereum/crypto/bls"
    23  	"math/big"
    24  
    25  	"github.com/ethereum/go-ethereum/common"
    26  	"github.com/ethereum/go-ethereum/crypto"
    27  	"github.com/ethereum/go-ethereum/log"
    28  	"github.com/ethereum/go-ethereum/p2p/enode"
    29  	"github.com/ethereum/go-ethereum/rlp"
    30  	"golang.org/x/crypto/sha3"
    31  )
    32  
    33  func RLPHash(v interface{}) (h common.Hash) {
    34  	hw := sha3.NewLegacyKeccak256()
    35  	rlp.Encode(hw, v)
    36  	hw.Sum(h[:0])
    37  	return h
    38  }
    39  
    40  // GetSignatureAddress gets the signer address from the signature
    41  func GetSignatureAddress(data []byte, sig []byte) (common.Address, error) {
    42  	// 1. Keccak data
    43  	hashData := crypto.Keccak256(data)
    44  	// 2. Recover public key
    45  	pubkey, err := crypto.SigToPub(hashData, sig)
    46  	if err != nil {
    47  		return common.Address{}, err
    48  	}
    49  	return crypto.PubkeyToAddress(*pubkey), nil
    50  }
    51  
    52  func CheckValidatorSignature(valSet ValidatorSet, data []byte, sig []byte) (common.Address, error) {
    53  	// 1. Get signature address
    54  	signer, err := GetSignatureAddress(data, sig)
    55  	if err != nil {
    56  		log.Error("Failed to get signer address", "err", err)
    57  		return common.Address{}, err
    58  	}
    59  
    60  	// 2. Check validator
    61  	if _, val := valSet.GetByAddress(signer); val != nil {
    62  		return val.Address(), nil
    63  	}
    64  
    65  	return common.Address{}, ErrUnauthorizedAddress
    66  }
    67  
    68  // Retrieves the block number within an epoch.  The return value will be 1-based.
    69  // There is a special case if the number == 0.  It is basically the last block of the 0th epoch, and should have a value of epochSize
    70  func GetNumberWithinEpoch(number uint64, epochSize uint64) uint64 {
    71  	number = number % epochSize
    72  	if number == 0 {
    73  		return epochSize
    74  	} else {
    75  		return number
    76  	}
    77  }
    78  
    79  func IsLastBlockOfEpoch(number uint64, epochSize uint64) bool {
    80  	return GetNumberWithinEpoch(number, epochSize) == epochSize
    81  }
    82  
    83  func IsFirstBlockOfEpoch(number uint64, epochSize uint64) bool {
    84  	return GetNumberWithinEpoch(number, epochSize) == 1
    85  }
    86  
    87  // Retrieves the epoch number given the block number.
    88  // There is a special case if the number == 0 (the genesis block).  That block will be in the
    89  // 1st epoch.
    90  func GetEpochNumber(number uint64, epochSize uint64) uint64 {
    91  	epochNumber := number / epochSize
    92  	if IsLastBlockOfEpoch(number, epochSize) {
    93  		return epochNumber
    94  	} else {
    95  		return epochNumber + 1
    96  	}
    97  }
    98  
    99  func GetEpochFirstBlockNumber(epochNumber uint64, epochSize uint64) (uint64, error) {
   100  	if epochNumber == 0 {
   101  		return 0, errors.New("No first block for epoch 0")
   102  	}
   103  
   104  	return ((epochNumber - 1) * epochSize) + 1, nil
   105  }
   106  
   107  func GetEpochLastBlockNumber(epochNumber uint64, epochSize uint64) uint64 {
   108  	if epochNumber == 0 {
   109  		return 0
   110  	}
   111  
   112  	firstBlockNum, _ := GetEpochFirstBlockNumber(epochNumber, epochSize)
   113  	return firstBlockNum + (epochSize - 1)
   114  }
   115  
   116  func GetValScoreTallyFirstBlockNumber(epochNumber uint64, epochSize uint64, lookbackWindowSize uint64) uint64 {
   117  	// We need to wait for the completion of the first window with the start window's block being the
   118  	// 2nd block of the epoch, before we start tallying the validator score for epoch "epochNumber".
   119  	// We can't include the epoch's first block since it's aggregated parent seals
   120  	// is for the previous epoch's valset.
   121  
   122  	epochFirstBlock, _ := GetEpochFirstBlockNumber(epochNumber, epochSize)
   123  	return epochFirstBlock + 1 + (lookbackWindowSize - 1)
   124  }
   125  
   126  func GetValScoreTallyLastBlockNumber(epochNumber uint64, epochSize uint64) uint64 {
   127  	// We stop tallying for epoch "epochNumber" at the second to last block of that epoch.
   128  	// We can't include that epoch's last block as part of the tally because the epoch val score is calculated
   129  	// using a tally that is updated AFTER a block is finalized.
   130  	// Note that it's possible to count up to the last block of the epoch, but it's much harder to implement
   131  	// than couting up to the second to last one.
   132  
   133  	return GetEpochLastBlockNumber(epochNumber, epochSize) - 1
   134  }
   135  
   136  func ValidatorSetDiff(oldValSet []ValidatorData, newValSet []ValidatorData) ([]ValidatorData, *big.Int) {
   137  	valSetMap := make(map[common.Address]bool)
   138  	oldValSetIndices := make(map[common.Address]int)
   139  
   140  	for i, oldVal := range oldValSet {
   141  		if (oldVal.Address != common.Address{}) {
   142  			valSetMap[oldVal.Address] = true
   143  			oldValSetIndices[oldValSet[i].Address] = i
   144  		}
   145  	}
   146  
   147  	var addedValidators []ValidatorData
   148  	for _, newVal := range newValSet {
   149  		index, ok := oldValSetIndices[newVal.Address]
   150  		if ok && (oldValSet[index].BLSPublicKey == newVal.BLSPublicKey) {
   151  			// We found a common validator.  Pop from the map
   152  			delete(valSetMap, newVal.Address)
   153  		} else {
   154  			// We found a new validator that is not in the old validator set
   155  			addedValidators = append(addedValidators, ValidatorData{
   156  				newVal.Address,
   157  				newVal.BLSPublicKey,
   158  			})
   159  		}
   160  	}
   161  
   162  	removedValidatorsBitmap := big.NewInt(0)
   163  	for rmVal := range valSetMap {
   164  		removedValidatorsBitmap = removedValidatorsBitmap.SetBit(removedValidatorsBitmap, oldValSetIndices[rmVal], 1)
   165  	}
   166  
   167  	return addedValidators, removedValidatorsBitmap
   168  }
   169  
   170  // This function assumes that valSet1 and valSet2 are ordered in the same way
   171  func CompareValidatorSlices(valSet1 []common.Address, valSet2 []common.Address) bool {
   172  	if len(valSet1) != len(valSet2) {
   173  		return false
   174  	}
   175  
   176  	for i := 0; i < len(valSet1); i++ {
   177  		if valSet1[i] != valSet2[i] {
   178  			return false
   179  		}
   180  	}
   181  
   182  	return true
   183  }
   184  
   185  func CompareValidatorPublicKeySlices(valSet1 []blscrypto.SerializedPublicKey, valSet2 []blscrypto.SerializedPublicKey) bool {
   186  	if len(valSet1) != len(valSet2) {
   187  		return false
   188  	}
   189  
   190  	for i := 0; i < len(valSet1); i++ {
   191  		if valSet1[i] != valSet2[i] {
   192  			return false
   193  		}
   194  	}
   195  
   196  	return true
   197  }
   198  
   199  func ConvertPublicKeysToStringSlice(publicKeys []blscrypto.SerializedPublicKey) []string {
   200  	publicKeyStrs := []string{}
   201  	for i := 0; i < len(publicKeys); i++ {
   202  		publicKeyStrs = append(publicKeyStrs, hex.EncodeToString(publicKeys[i][:]))
   203  	}
   204  
   205  	return publicKeyStrs
   206  }
   207  
   208  func GetNodeID(enodeURL string) (*enode.ID, error) {
   209  	node, err := enode.ParseV4(enodeURL)
   210  	if err != nil {
   211  		return nil, err
   212  	}
   213  
   214  	id := node.ID()
   215  	return &id, nil
   216  }