mirror of
https://github.com/luxfi/p2p.git
synced 2026-10-30 15:22:55 +00:00
github.com/luxfi/utils is now github.com/luxfi/util. Import paths and the module requirement follow the rename. Co-authored-by: Hanzo Dev <[email protected]>
94 lines
2.4 KiB
Go
94 lines
2.4 KiB
Go
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package peer
|
|
|
|
import (
|
|
"crypto"
|
|
"net/netip"
|
|
"sync"
|
|
|
|
"github.com/luxfi/crypto/bls"
|
|
"github.com/luxfi/node/utils/timer/mockable"
|
|
"github.com/luxfi/util"
|
|
)
|
|
|
|
// IPSigner will return a signedIP for the current value of our dynamic IP.
|
|
type IPSigner struct {
|
|
ip *utils.Atomic[netip.AddrPort]
|
|
clock mockable.Clock
|
|
tlsSigner crypto.Signer
|
|
blsSigner bls.Signer
|
|
|
|
// Must be held while accessing [signedIP]
|
|
signedIPLock sync.RWMutex
|
|
// Note that the values in [*signedIP] are constants and can be inspected
|
|
// without holding [signedIPLock].
|
|
signedIP *SignedIP
|
|
}
|
|
|
|
func NewIPSigner(
|
|
ip *utils.Atomic[netip.AddrPort],
|
|
tlsSigner crypto.Signer,
|
|
blsSigner bls.Signer,
|
|
) *IPSigner {
|
|
return &IPSigner{
|
|
ip: ip,
|
|
tlsSigner: tlsSigner,
|
|
blsSigner: blsSigner,
|
|
}
|
|
}
|
|
|
|
// GetSignedIP returns the signedIP of the current value of the provided
|
|
// dynamicIP. If the dynamicIP hasn't changed since the prior call to
|
|
// GetSignedIP, then the same [SignedIP] will be returned.
|
|
//
|
|
// It's safe for multiple goroutines to concurrently call GetSignedIP.
|
|
func (s *IPSigner) GetSignedIP() (*SignedIP, error) {
|
|
// Optimistically, the IP should already be signed. By grabbing a read lock
|
|
// here we enable full concurrency of new connections.
|
|
s.signedIPLock.RLock()
|
|
signedIP := s.signedIP
|
|
s.signedIPLock.RUnlock()
|
|
ip := s.ip.Get()
|
|
if signedIP != nil && signedIP.AddrPort == ip {
|
|
return signedIP, nil
|
|
}
|
|
|
|
// If our current IP hasn't been signed yet - then we should sign it.
|
|
s.signedIPLock.Lock()
|
|
defer s.signedIPLock.Unlock()
|
|
|
|
// It's possible that multiple threads read [n.signedIP] as incorrect at the
|
|
// same time, we should verify that we are the first thread to attempt to
|
|
// update it.
|
|
signedIP = s.signedIP
|
|
if signedIP != nil && signedIP.AddrPort == ip {
|
|
return signedIP, nil
|
|
}
|
|
|
|
// We should now sign our new IP at the current timestamp.
|
|
unsignedIP := UnsignedIP{
|
|
AddrPort: ip,
|
|
Timestamp: s.clock.Unix(),
|
|
}
|
|
signedIP, err := unsignedIP.Sign(s.tlsSigner, s.blsSigner)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
s.signedIP = signedIP
|
|
return s.signedIP, nil
|
|
}
|
|
|
|
// PublicKey returns the BLS public key for this IPSigner
|
|
func (s *IPSigner) PublicKey() *bls.PublicKey {
|
|
if s.blsSigner == nil {
|
|
return nil
|
|
}
|
|
return s.blsSigner.PublicKey()
|
|
}
|