erigon-pulse/cl/sentinel/utils.go
a 436493350e
Sentinel refactor (#8296)
1. changes sentinel to use an http-like interface

2. moves hexutil, crypto/blake2b, metrics packages to erigon-lib
2023-10-22 01:17:18 +02:00

117 lines
3.6 KiB
Go

// Copyright 2022 Erigon-Lightclient contributors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// package sentinel
package sentinel
import (
"crypto/ecdsa"
"fmt"
"net"
"time"
"github.com/btcsuite/btcd/btcec/v2"
"github.com/ledgerwatch/erigon/p2p/enode"
"github.com/ledgerwatch/log/v3"
"github.com/libp2p/go-libp2p/core/crypto"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/multiformats/go-multiaddr"
"github.com/pion/randutil"
)
func convertToInterfacePubkey(pubkey *ecdsa.PublicKey) (crypto.PubKey, error) {
xVal, yVal := new(btcec.FieldVal), new(btcec.FieldVal)
overflows := xVal.SetByteSlice(pubkey.X.Bytes())
if overflows {
return nil, fmt.Errorf("x value overflows")
}
overflows = yVal.SetByteSlice(pubkey.Y.Bytes())
if overflows {
return nil, fmt.Errorf("y value overflows")
}
newKey := crypto.PubKey((*crypto.Secp256k1PublicKey)(btcec.NewPublicKey(xVal, yVal)))
// Zero out temporary values.
xVal.Zero()
yVal.Zero()
return newKey, nil
}
func convertToAddrInfo(node *enode.Node) (*peer.AddrInfo, multiaddr.Multiaddr, error) {
multiAddr, err := convertToSingleMultiAddr(node)
if err != nil {
return nil, nil, err
}
info, err := peer.AddrInfoFromP2pAddr(multiAddr)
if err != nil {
return nil, nil, err
}
return info, multiAddr, nil
}
func convertToSingleMultiAddr(node *enode.Node) (multiaddr.Multiaddr, error) {
pubkey := node.Pubkey()
assertedKey, err := convertToInterfacePubkey(pubkey)
if err != nil {
return nil, fmt.Errorf("could not get pubkey: %w", err)
}
id, err := peer.IDFromPublicKey(assertedKey)
if err != nil {
return nil, fmt.Errorf("could not get peer id: %w", err)
}
return multiAddressBuilderWithID(node.IP().String(), "tcp", uint(node.TCP()), id)
}
func multiAddressBuilderWithID(ipAddr, protocol string, port uint, id peer.ID) (multiaddr.Multiaddr, error) {
parsedIP := net.ParseIP(ipAddr)
if parsedIP.To4() == nil && parsedIP.To16() == nil {
return nil, fmt.Errorf("invalid ip address provided: %s", ipAddr)
}
if id.String() == "" {
return nil, fmt.Errorf("empty peer id given")
}
if parsedIP.To4() != nil {
return multiaddr.NewMultiaddr(fmt.Sprintf("/ip4/%s/%s/%d/p2p/%s", ipAddr, protocol, port, id.String()))
}
return multiaddr.NewMultiaddr(fmt.Sprintf("/ip6/%s/%s/%d/p2p/%s", ipAddr, protocol, port, id.String()))
}
func convertToMultiAddr(nodes []*enode.Node) []multiaddr.Multiaddr {
multiAddrs := []multiaddr.Multiaddr{}
for _, node := range nodes {
// ignore nodes with no ip address stored
if node.IP() == nil {
continue
}
multiAddr, err := convertToSingleMultiAddr(node)
if err != nil {
log.Debug("[Sentinel] Could not convert to multiAddr", "err", err)
continue
}
multiAddrs = append(multiAddrs, multiAddr)
}
return multiAddrs
}
var shuffleSource = randutil.NewMathRandomGenerator()
func (s *Sentinel) oneSlotDuration() time.Duration {
return time.Duration(s.cfg.BeaconConfig.SecondsPerSlot) * time.Second
}
func (s *Sentinel) oneEpochDuration() time.Duration {
return s.oneSlotDuration() * time.Duration(s.cfg.BeaconConfig.SlotsPerEpoch)
}
// the cap for `inMesh` time scoring.
func (s *Sentinel) inMeshCap() float64 {
return float64((3600 * time.Second) / s.oneSlotDuration())
}