2021-03-11 20:27:12 +00:00
package node
import (
"context"
2023-01-13 23:58:22 +00:00
"math/rand"
2021-11-17 16:19:42 +00:00
"net"
2021-11-23 15:03:12 +00:00
"sync"
2021-03-15 23:59:18 +00:00
"time"
2021-03-11 20:27:12 +00:00
2023-05-12 21:52:42 +00:00
backoffv4 "github.com/cenkalti/backoff/v4"
2023-02-24 15:58:49 +00:00
golog "github.com/ipfs/go-log/v2"
2022-12-09 18:09:06 +00:00
"github.com/libp2p/go-libp2p"
"go.uber.org/zap"
2022-06-13 18:30:35 +00:00
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/p2p/enode"
2021-08-31 18:19:49 +00:00
2022-10-19 19:39:32 +00:00
"github.com/libp2p/go-libp2p/core/event"
"github.com/libp2p/go-libp2p/core/host"
"github.com/libp2p/go-libp2p/core/network"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/peerstore"
2023-02-16 16:17:52 +00:00
"github.com/libp2p/go-libp2p/core/protocol"
2023-05-12 21:52:42 +00:00
"github.com/libp2p/go-libp2p/p2p/host/autorelay"
2023-06-05 14:39:38 +00:00
"github.com/libp2p/go-libp2p/p2p/host/peerstore/pstoremem"
2023-05-12 21:52:42 +00:00
"github.com/libp2p/go-libp2p/p2p/protocol/circuitv2/proto"
2022-05-27 19:55:35 +00:00
ws "github.com/libp2p/go-libp2p/p2p/transport/websocket"
2021-03-11 20:27:12 +00:00
ma "github.com/multiformats/go-multiaddr"
2021-04-22 00:09:37 +00:00
2022-11-09 19:53:01 +00:00
"github.com/waku-org/go-waku/logging"
"github.com/waku-org/go-waku/waku/v2/discv5"
2023-08-03 16:21:15 +00:00
"github.com/waku-org/go-waku/waku/v2/peermanager"
2023-08-10 12:58:22 +00:00
wps "github.com/waku-org/go-waku/waku/v2/peerstore"
2023-09-14 15:00:06 +00:00
wakuprotocol "github.com/waku-org/go-waku/waku/v2/protocol"
2023-04-20 18:51:13 +00:00
"github.com/waku-org/go-waku/waku/v2/protocol/enr"
2022-11-09 19:53:01 +00:00
"github.com/waku-org/go-waku/waku/v2/protocol/filter"
2023-04-11 14:38:16 +00:00
"github.com/waku-org/go-waku/waku/v2/protocol/legacy_filter"
2022-11-09 19:53:01 +00:00
"github.com/waku-org/go-waku/waku/v2/protocol/lightpush"
"github.com/waku-org/go-waku/waku/v2/protocol/pb"
"github.com/waku-org/go-waku/waku/v2/protocol/peer_exchange"
"github.com/waku-org/go-waku/waku/v2/protocol/relay"
"github.com/waku-org/go-waku/waku/v2/protocol/store"
2023-03-09 15:48:25 +00:00
"github.com/waku-org/go-waku/waku/v2/rendezvous"
2022-12-09 03:08:04 +00:00
"github.com/waku-org/go-waku/waku/v2/timesource"
2022-11-09 19:53:01 +00:00
"github.com/waku-org/go-waku/waku/v2/utils"
2021-03-11 20:27:12 +00:00
)
2023-07-07 15:51:15 +00:00
const discoveryConnectTimeout = 20 * time . Second
2021-11-10 13:36:51 +00:00
type Peer struct {
2022-03-22 16:30:14 +00:00
ID peer . ID ` json:"peerID" `
2023-02-16 16:17:52 +00:00
Protocols [ ] protocol . ID ` json:"protocols" `
2022-03-22 16:30:14 +00:00
Addrs [ ] ma . Multiaddr ` json:"addrs" `
Connected bool ` json:"connected" `
2021-11-10 13:36:51 +00:00
}
2022-03-18 19:56:34 +00:00
type storeFactory func ( w * WakuNode ) store . Store
2023-04-10 15:20:07 +00:00
type byte32 = [ 32 ] byte
type IdentityCredential = struct {
IDTrapdoor byte32 ` json:"idTrapdoor" `
IDNullifier byte32 ` json:"idNullifier" `
IDSecretHash byte32 ` json:"idSecretHash" `
IDCommitment byte32 ` json:"idCommitment" `
2022-08-12 12:44:13 +00:00
}
2023-09-07 21:39:10 +00:00
type SpamHandler = func ( message * pb . WakuMessage , topic string ) error
2023-08-21 20:54:13 +00:00
2022-08-12 12:44:13 +00:00
type RLNRelay interface {
2023-04-10 15:20:07 +00:00
IdentityCredential ( ) ( IdentityCredential , error )
2023-08-24 18:42:50 +00:00
MembershipIndex ( ) uint
2022-08-12 12:44:13 +00:00
AppendRLNProof ( msg * pb . WakuMessage , senderEpochTime time . Time ) error
2023-09-07 21:39:10 +00:00
Validator ( spamHandler SpamHandler ) func ( ctx context . Context , message * pb . WakuMessage , topic string ) bool
2023-08-21 20:54:13 +00:00
Start ( ctx context . Context ) error
2023-08-18 13:59:37 +00:00
Stop ( ) error
2023-09-11 21:34:56 +00:00
IsReady ( ctx context . Context ) ( bool , error )
2022-08-12 12:44:13 +00:00
}
2021-03-11 20:27:12 +00:00
type WakuNode struct {
2022-12-09 03:08:04 +00:00
host host . Host
opts * WakuNodeParameters
log * zap . Logger
timesource timesource . Timesource
2023-08-16 01:40:00 +00:00
metrics Metrics
2021-04-15 02:19:31 +00:00
2023-07-07 12:35:22 +00:00
peerstore peerstore . Peerstore
2023-08-03 16:21:15 +00:00
peerConnector * peermanager . PeerConnectionStrategy
2023-06-05 14:39:38 +00:00
2023-04-11 14:38:16 +00:00
relay Service
lightPush Service
discoveryV5 Service
peerExchange Service
rendezvous Service
legacyFilter ReceptorService
2023-08-14 20:29:00 +00:00
filterFullNode ReceptorService
filterLightNode Service
2023-04-11 14:38:16 +00:00
store ReceptorService
rlnRelay RLNRelay
2023-01-06 22:37:57 +00:00
2023-05-12 21:52:42 +00:00
wakuFlag enr . WakuEnrBitfield
circuitRelayNodes chan peer . AddrInfo
2021-06-24 13:02:53 +00:00
2022-06-13 18:30:35 +00:00
localNode * enode . LocalNode
2023-05-05 09:49:15 +00:00
bcaster relay . Broadcaster
2021-04-15 02:19:31 +00:00
2021-10-06 15:34:39 +00:00
connectionNotif ConnectionNotifier
2021-06-16 10:14:22 +00:00
protocolEventSub event . Subscription
identificationEventSub event . Subscription
2021-11-17 16:19:42 +00:00
addressChangesSub event . Subscription
2023-02-07 13:45:06 +00:00
enrChangeCh chan struct { }
2021-06-16 10:14:22 +00:00
2021-11-24 20:11:24 +00:00
keepAliveMutex sync . Mutex
keepAliveFails map [ peer . ID ] int
2021-04-18 23:41:42 +00:00
cancel context . CancelFunc
2021-11-23 15:03:12 +00:00
wg * sync . WaitGroup
2021-06-16 10:14:22 +00:00
// Channel passed to WakuNode constructor
// receiving connection status notifications
2023-05-10 14:13:10 +00:00
connStatusChan chan <- ConnStatus
2022-03-18 19:56:34 +00:00
storeFactory storeFactory
2023-08-03 16:21:15 +00:00
peermanager * peermanager . PeerManager
2022-03-18 19:56:34 +00:00
}
func defaultStoreFactory ( w * WakuNode ) store . Store {
2023-08-16 01:40:00 +00:00
return store . NewWakuStore ( w . opts . messageProvider , w . peermanager , w . timesource , w . opts . prometheusReg , w . log )
2021-03-11 20:27:12 +00:00
}
2022-04-25 19:31:26 +00:00
// New is used to instantiate a WakuNode using a set of WakuNodeOptions
2023-01-06 22:37:57 +00:00
func New ( opts ... WakuNodeOption ) ( * WakuNode , error ) {
2023-05-15 18:44:36 +00:00
var err error
2021-04-18 23:41:42 +00:00
params := new ( WakuNodeParameters )
params . libP2POpts = DefaultLibP2POptions
2021-11-17 16:19:42 +00:00
opts = append ( DefaultWakuNodeOptions , opts ... )
2021-04-18 23:41:42 +00:00
for _ , opt := range opts {
err := opt ( params )
2021-03-11 20:27:12 +00:00
if err != nil {
return nil , err
}
}
2023-02-01 23:35:31 +00:00
if params . logger == nil {
params . logger = utils . Logger ( )
2023-06-05 14:39:38 +00:00
//golog.SetPrimaryCore(params.logger.Core())
2023-02-24 15:58:49 +00:00
golog . SetAllLoggers ( params . logLevel )
2023-02-01 23:35:31 +00:00
}
2022-06-13 18:30:35 +00:00
if params . privKey == nil {
prvKey , err := crypto . GenerateKey ( )
if err != nil {
return nil , err
}
params . privKey = prvKey
}
2022-03-22 13:12:58 +00:00
if params . enableWSS {
params . libP2POpts = append ( params . libP2POpts , libp2p . Transport ( ws . New , ws . WithTLSConfig ( params . tlsConfig ) ) )
2022-07-25 15:49:10 +00:00
} else {
// Enable WS transport by default
2022-03-22 13:12:58 +00:00
params . libP2POpts = append ( params . libP2POpts , libp2p . Transport ( ws . New ) )
}
2021-11-17 16:19:42 +00:00
// Setting default host address if none was provided
if params . hostAddr == nil {
2023-05-15 18:44:36 +00:00
params . hostAddr , err = net . ResolveTCPAddr ( "tcp" , "0.0.0.0:0" )
if err != nil {
return nil , err
}
err = WithHostAddress ( params . hostAddr ) ( params )
2021-11-17 16:19:42 +00:00
if err != nil {
return nil , err
}
}
2023-05-15 18:44:36 +00:00
2021-04-18 23:41:42 +00:00
if len ( params . multiAddr ) > 0 {
params . libP2POpts = append ( params . libP2POpts , libp2p . ListenAddrs ( params . multiAddr ... ) )
}
2021-03-11 20:27:12 +00:00
2022-06-13 18:30:35 +00:00
params . libP2POpts = append ( params . libP2POpts , params . Identity ( ) )
2021-03-15 16:07:23 +00:00
2021-10-15 02:15:02 +00:00
if params . addressFactory != nil {
params . libP2POpts = append ( params . libP2POpts , libp2p . AddrsFactory ( params . addressFactory ) )
}
2021-03-11 20:27:12 +00:00
w := new ( WakuNode )
2023-05-05 09:49:15 +00:00
w . bcaster = relay . NewBroadcaster ( 1024 )
2021-04-18 23:41:42 +00:00
w . opts = params
2022-01-18 18:17:06 +00:00
w . log = params . logger . Named ( "node2" )
2021-11-23 15:03:12 +00:00
w . wg = & sync . WaitGroup { }
2021-11-24 20:11:24 +00:00
w . keepAliveFails = make ( map [ peer . ID ] int )
2023-04-20 18:51:13 +00:00
w . wakuFlag = enr . NewWakuEnrBitfield ( w . opts . enableLightPush , w . opts . enableLegacyFilter , w . opts . enableStore , w . opts . enableRelay )
2023-05-12 21:52:42 +00:00
w . circuitRelayNodes = make ( chan peer . AddrInfo )
2023-08-16 01:40:00 +00:00
w . metrics = newMetrics ( params . prometheusReg )
w . metrics . RecordVersion ( Version , GitCommit )
2023-05-12 21:52:42 +00:00
2023-06-05 14:39:38 +00:00
// Setup peerstore wrapper
if params . peerstore != nil {
2023-08-10 12:58:22 +00:00
w . peerstore = wps . NewWakuPeerstore ( params . peerstore )
2023-06-05 14:39:38 +00:00
params . libP2POpts = append ( params . libP2POpts , libp2p . Peerstore ( w . peerstore ) )
} else {
ps , err := pstoremem . NewPeerstore ( )
if err != nil {
return nil , err
}
2023-08-10 12:58:22 +00:00
w . peerstore = wps . NewWakuPeerstore ( ps )
2023-06-05 14:39:38 +00:00
params . libP2POpts = append ( params . libP2POpts , libp2p . Peerstore ( w . peerstore ) )
}
2023-05-12 21:52:42 +00:00
// Use circuit relay with nodes received on circuitRelayNodes channel
params . libP2POpts = append ( params . libP2POpts , libp2p . EnableAutoRelayWithPeerSource (
func ( ctx context . Context , numPeers int ) <- chan peer . AddrInfo {
r := make ( chan peer . AddrInfo )
go func ( ) {
defer close ( r )
for ; numPeers != 0 ; numPeers -- {
select {
case v , ok := <- w . circuitRelayNodes :
if ! ok {
return
}
select {
case r <- v :
case <- ctx . Done ( ) :
return
}
case <- ctx . Done ( ) :
return
}
}
} ( )
return r
} ,
2023-09-20 06:54:16 +00:00
autorelay . WithMinInterval ( params . circuitRelayMinInterval ) ,
autorelay . WithBootDelay ( params . circuitRelayBootDelay ) ,
2023-05-12 21:52:42 +00:00
) )
2021-06-16 10:14:22 +00:00
2022-12-09 03:08:04 +00:00
if params . enableNTP {
w . timesource = timesource . NewNTPTimesource ( w . opts . ntpURLs , w . log )
} else {
w . timesource = timesource . NewDefaultClock ( )
}
2023-04-25 16:09:55 +00:00
w . localNode , err = enr . NewLocalnode ( w . opts . privKey )
2023-01-06 22:37:57 +00:00
if err != nil {
w . log . Error ( "creating localnode" , zap . Error ( err ) )
}
2023-08-15 01:27:51 +00:00
2023-08-03 16:21:15 +00:00
//Initialize peer manager.
2023-09-27 06:46:37 +00:00
w . peermanager = peermanager . NewPeerManager ( w . opts . maxPeerConnections , w . opts . peerStoreCapacity , w . log )
2023-01-06 22:37:57 +00:00
2023-08-30 14:33:57 +00:00
w . peerConnector , err = peermanager . NewPeerConnectionStrategy ( w . peermanager , discoveryConnectTimeout , w . log )
2023-01-13 23:58:22 +00:00
if err != nil {
w . log . Error ( "creating peer connection strategy" , zap . Error ( err ) )
}
2023-01-06 22:37:57 +00:00
if w . opts . enableDiscV5 {
err := w . mountDiscV5 ( )
if err != nil {
return nil , err
}
}
2023-08-16 01:40:00 +00:00
w . peerExchange , err = peer_exchange . NewWakuPeerExchange ( w . DiscV5 ( ) , w . peerConnector , w . peermanager , w . opts . prometheusReg , w . log )
2023-01-11 00:52:10 +00:00
if err != nil {
return nil , err
}
2023-01-06 22:37:57 +00:00
2023-07-27 17:04:08 +00:00
w . rendezvous = rendezvous . NewRendezvous ( w . opts . rendezvousDB , w . peerConnector , w . log )
2023-08-21 20:54:13 +00:00
2023-09-14 21:24:34 +00:00
w . relay = relay . NewWakuRelay ( w . bcaster , w . opts . minRelayPeersToPublish , w . timesource , w . opts . prometheusReg , w . log , w . opts . pubsubOpts ... )
2023-08-21 20:54:13 +00:00
if w . opts . enableRelay {
err = w . setupRLNRelay ( )
if err != nil {
return nil , err
}
}
2023-08-16 01:40:00 +00:00
w . legacyFilter = legacy_filter . NewWakuFilter ( w . bcaster , w . opts . isLegacyFilterFullNode , w . timesource , w . opts . prometheusReg , w . log , w . opts . legacyFilterOpts ... )
w . filterFullNode = filter . NewWakuFilterFullNode ( w . timesource , w . opts . prometheusReg , w . log , w . opts . filterOpts ... )
w . filterLightNode = filter . NewWakuFilterLightNode ( w . bcaster , w . peermanager , w . timesource , w . opts . prometheusReg , w . log )
w . lightPush = lightpush . NewWakuLightPush ( w . Relay ( ) , w . peermanager , w . opts . prometheusReg , w . log )
2023-01-10 12:43:26 +00:00
2022-03-18 19:56:34 +00:00
if params . storeFactory != nil {
w . storeFactory = params . storeFactory
} else {
w . storeFactory = defaultStoreFactory
}
2021-11-05 20:09:48 +00:00
if params . connStatusC != nil {
w . connStatusChan = params . connStatusC
2021-06-28 14:14:28 +00:00
}
2021-10-06 15:34:39 +00:00
2021-10-05 02:13:54 +00:00
return w , nil
}
2023-01-12 02:20:23 +00:00
func ( w * WakuNode ) watchMultiaddressChanges ( ctx context . Context ) {
2021-11-23 15:03:12 +00:00
defer w . wg . Done ( )
2021-11-17 16:19:42 +00:00
addrs := w . ListenAddresses ( )
first := make ( chan struct { } , 1 )
first <- struct { } { }
for {
select {
2023-01-06 22:37:57 +00:00
case <- ctx . Done ( ) :
2021-11-17 16:19:42 +00:00
return
case <- first :
2022-06-13 18:30:35 +00:00
w . log . Info ( "listening" , logging . MultiAddrs ( "multiaddr" , addrs ... ) )
2021-11-17 16:19:42 +00:00
case <- w . addressChangesSub . Out ( ) :
newAddrs := w . ListenAddresses ( )
2022-06-13 18:30:35 +00:00
diff := false
2021-11-17 16:19:42 +00:00
if len ( addrs ) != len ( newAddrs ) {
2022-06-13 18:30:35 +00:00
diff = true
2021-11-17 16:19:42 +00:00
} else {
for i := range newAddrs {
if addrs [ i ] . String ( ) != newAddrs [ i ] . String ( ) {
2022-06-13 18:30:35 +00:00
diff = true
2021-11-17 16:19:42 +00:00
break
}
}
}
2022-06-13 18:30:35 +00:00
if diff {
2021-11-17 16:19:42 +00:00
addrs = newAddrs
2022-06-13 18:30:35 +00:00
w . log . Info ( "listening addresses update received" , logging . MultiAddrs ( "multiaddr" , addrs ... ) )
2023-09-08 19:19:23 +00:00
err := w . setupENR ( ctx , addrs )
if err != nil {
w . log . Warn ( "could not update ENR" , zap . Error ( err ) )
}
2021-11-17 16:19:42 +00:00
}
}
}
}
2022-04-25 19:31:26 +00:00
// Start initializes all the protocols that were setup in the WakuNode
2023-01-06 22:37:57 +00:00
func ( w * WakuNode ) Start ( ctx context . Context ) error {
2023-08-03 16:21:15 +00:00
connGater := peermanager . NewConnectionGater ( w . log )
2023-06-05 14:39:38 +00:00
2023-01-06 22:37:57 +00:00
ctx , cancel := context . WithCancel ( ctx )
w . cancel = cancel
2022-12-09 03:08:04 +00:00
2023-07-06 21:47:25 +00:00
libP2POpts := append ( w . opts . libP2POpts , libp2p . ConnectionGater ( connGater ) )
host , err := libp2p . New ( libP2POpts ... )
2023-04-17 00:04:12 +00:00
if err != nil {
return err
}
2023-06-05 14:39:38 +00:00
host . Network ( ) . Notify ( & network . NotifyBundle {
DisconnectedF : func ( net network . Network , conn network . Conn ) {
go connGater . NotifyDisconnect ( conn . RemoteMultiaddr ( ) )
} ,
} )
2023-04-17 00:04:12 +00:00
w . host = host
if w . protocolEventSub , err = host . EventBus ( ) . Subscribe ( new ( event . EvtPeerProtocolsUpdated ) ) ; err != nil {
return err
}
if w . identificationEventSub , err = host . EventBus ( ) . Subscribe ( new ( event . EvtPeerIdentificationCompleted ) ) ; err != nil {
return err
}
if w . addressChangesSub , err = host . EventBus ( ) . Subscribe ( new ( event . EvtLocalAddressesUpdated ) ) ; err != nil {
return err
}
2023-08-16 01:40:00 +00:00
w . connectionNotif = NewConnectionNotifier ( ctx , w . host , w . opts . connNotifCh , w . metrics , w . log )
2023-01-06 22:37:57 +00:00
w . host . Network ( ) . Notify ( w . connectionNotif )
2023-02-15 18:43:51 +00:00
w . enrChangeCh = make ( chan struct { } , 10 )
2023-05-12 21:52:42 +00:00
w . wg . Add ( 4 )
2023-01-06 22:37:57 +00:00
go w . connectednessListener ( ctx )
2023-01-12 02:20:23 +00:00
go w . watchMultiaddressChanges ( ctx )
go w . watchENRChanges ( ctx )
2023-05-12 21:52:42 +00:00
go w . findRelayNodes ( ctx )
2023-01-06 22:37:57 +00:00
2023-04-17 00:04:12 +00:00
err = w . bcaster . Start ( ctx )
2023-04-14 21:50:44 +00:00
if err != nil {
return err
}
2023-01-06 22:37:57 +00:00
if w . opts . keepAliveInterval > time . Duration ( 0 ) {
w . wg . Add ( 1 )
2023-01-08 18:33:30 +00:00
go w . startKeepAlive ( ctx , w . opts . keepAliveInterval )
2022-06-19 21:47:39 +00:00
}
2021-12-06 10:49:13 +00:00
2023-04-17 00:04:12 +00:00
w . peerConnector . SetHost ( host )
2023-08-16 12:25:58 +00:00
w . peermanager . SetHost ( host )
2023-04-14 21:50:44 +00:00
err = w . peerConnector . Start ( ctx )
2023-01-13 23:58:22 +00:00
if err != nil {
return err
}
2023-01-06 22:37:57 +00:00
if w . opts . enableNTP {
err := w . timesource . Start ( ctx )
2022-12-09 03:08:04 +00:00
if err != nil {
return err
}
2021-04-18 23:41:42 +00:00
}
2023-08-24 14:25:17 +00:00
if w . opts . enableRLN {
err = w . startRlnRelay ( ctx )
if err != nil {
return err
}
}
2023-04-17 00:04:12 +00:00
w . relay . SetHost ( host )
2023-08-10 12:58:22 +00:00
2023-01-06 22:37:57 +00:00
if w . opts . enableRelay {
err := w . relay . Start ( ctx )
2021-12-08 13:00:20 +00:00
if err != nil {
return err
}
2023-09-19 06:05:29 +00:00
err = w . peermanager . SubscribeToRelayEvtBus ( w . relay . ( * relay . WakuRelay ) . Events ( ) )
if err != nil {
return err
}
2023-08-03 16:21:15 +00:00
w . peermanager . Start ( ctx )
2023-08-20 12:36:35 +00:00
w . registerAndMonitorReachability ( ctx )
2021-11-17 16:19:42 +00:00
}
2023-01-06 22:37:57 +00:00
w . store = w . storeFactory ( w )
2023-04-17 00:04:12 +00:00
w . store . SetHost ( host )
2023-01-06 22:37:57 +00:00
if w . opts . enableStore {
2023-05-05 09:49:15 +00:00
sub := w . bcaster . RegisterForAll ( )
err := w . startStore ( ctx , sub )
2022-10-23 13:13:43 +00:00
if err != nil {
return err
}
2023-01-06 22:37:57 +00:00
w . log . Info ( "Subscribing store to broadcaster" )
2021-11-17 16:19:42 +00:00
}
2023-04-17 00:04:12 +00:00
w . lightPush . SetHost ( host )
2023-01-06 22:37:57 +00:00
if w . opts . enableLightPush {
if err := w . lightPush . Start ( ctx ) ; err != nil {
2022-12-09 03:08:04 +00:00
return err
}
2021-06-16 10:14:22 +00:00
}
2023-04-17 00:04:12 +00:00
w . legacyFilter . SetHost ( host )
if w . opts . enableLegacyFilter {
2023-05-05 09:49:15 +00:00
sub := w . bcaster . RegisterForAll ( )
err := w . legacyFilter . Start ( ctx , sub )
2022-07-05 21:28:34 +00:00
if err != nil {
return err
}
2023-01-06 22:37:57 +00:00
w . log . Info ( "Subscribing filter to broadcaster" )
2022-07-05 21:28:34 +00:00
}
2023-08-14 20:29:00 +00:00
w . filterFullNode . SetHost ( host )
2023-04-17 00:04:12 +00:00
if w . opts . enableFilterFullNode {
2023-05-05 09:49:15 +00:00
sub := w . bcaster . RegisterForAll ( )
2023-08-14 20:29:00 +00:00
err := w . filterFullNode . Start ( ctx , sub )
2023-02-07 22:28:46 +00:00
if err != nil {
return err
}
w . log . Info ( "Subscribing filterV2 to broadcaster" )
2023-05-05 09:49:15 +00:00
2023-02-08 23:33:06 +00:00
}
2023-08-14 20:29:00 +00:00
w . filterLightNode . SetHost ( host )
2023-04-11 14:38:16 +00:00
if w . opts . enableFilterLightNode {
2023-08-14 20:29:00 +00:00
err := w . filterLightNode . Start ( ctx )
2023-02-08 23:33:06 +00:00
if err != nil {
return err
}
2023-02-07 22:28:46 +00:00
}
2023-01-13 23:58:22 +00:00
err = w . setupENR ( ctx , w . ListenAddresses ( ) )
2023-01-06 22:37:57 +00:00
if err != nil {
return err
}
2023-04-17 00:04:12 +00:00
w . peerExchange . SetHost ( host )
2023-01-06 22:37:57 +00:00
if w . opts . enablePeerExchange {
err := w . peerExchange . Start ( ctx )
if err != nil {
2021-11-01 12:38:03 +00:00
return err
}
2021-04-28 20:23:03 +00:00
}
2023-04-17 00:04:12 +00:00
w . rendezvous . SetHost ( host )
2023-07-31 18:58:50 +00:00
if w . opts . enableRendezvousPoint {
2023-03-09 15:48:25 +00:00
err := w . rendezvous . Start ( ctx )
if err != nil {
return err
}
}
2021-10-05 02:13:54 +00:00
return nil
2021-03-11 20:27:12 +00:00
}
2022-04-25 19:31:26 +00:00
// Stop stops the WakuNode and closess all connections to the host
2021-03-22 16:45:13 +00:00
func ( w * WakuNode ) Stop ( ) {
2023-01-06 22:37:57 +00:00
if w . cancel == nil {
return
}
2023-04-14 21:50:44 +00:00
w . bcaster . Stop ( )
2021-11-01 14:42:55 +00:00
2021-10-06 15:34:39 +00:00
defer w . connectionNotif . Close ( )
2021-06-16 10:14:22 +00:00
defer w . protocolEventSub . Close ( )
defer w . identificationEventSub . Close ( )
2021-11-17 16:19:42 +00:00
defer w . addressChangesSub . Close ( )
2021-06-24 13:02:53 +00:00
2023-01-06 22:37:57 +00:00
w . relay . Stop ( )
w . lightPush . Stop ( )
w . store . Stop ( )
2023-04-11 14:38:16 +00:00
w . legacyFilter . Stop ( )
2023-08-14 20:29:00 +00:00
w . filterFullNode . Stop ( )
2022-10-23 13:13:43 +00:00
2023-01-06 22:37:57 +00:00
if w . opts . enableDiscV5 {
2022-10-23 13:13:43 +00:00
w . discoveryV5 . Stop ( )
}
2023-05-18 15:22:19 +00:00
w . peerExchange . Stop ( )
2023-07-27 17:04:08 +00:00
w . rendezvous . Stop ( )
2022-10-23 13:13:43 +00:00
2023-01-13 23:58:22 +00:00
w . peerConnector . Stop ( )
2022-09-12 14:13:38 +00:00
_ = w . stopRlnRelay ( )
2021-10-01 18:37:52 +00:00
2023-01-06 22:37:57 +00:00
w . timesource . Stop ( )
2022-12-09 03:08:04 +00:00
2021-10-01 18:37:52 +00:00
w . host . Close ( )
2021-11-23 15:03:12 +00:00
2023-05-09 20:35:04 +00:00
w . cancel ( )
2021-11-23 15:03:12 +00:00
w . wg . Wait ( )
2023-02-09 13:03:05 +00:00
close ( w . enrChangeCh )
2023-04-14 21:50:44 +00:00
w . cancel = nil
2021-03-15 16:07:23 +00:00
}
2022-04-25 19:31:26 +00:00
// Host returns the libp2p Host used by the WakuNode
2021-03-15 16:07:23 +00:00
func ( w * WakuNode ) Host ( ) host . Host {
return w . host
}
2022-04-25 19:31:26 +00:00
// ID returns the base58 encoded ID from the host
2021-03-18 23:21:45 +00:00
func ( w * WakuNode ) ID ( ) string {
return w . host . ID ( ) . Pretty ( )
}
2023-01-12 02:20:23 +00:00
func ( w * WakuNode ) watchENRChanges ( ctx context . Context ) {
defer w . wg . Done ( )
var prevNodeVal string
for {
select {
case <- ctx . Done ( ) :
return
2023-02-07 13:45:06 +00:00
case <- w . enrChangeCh :
2023-01-12 02:20:23 +00:00
if w . localNode != nil {
currNodeVal := w . localNode . Node ( ) . String ( )
if prevNodeVal != currNodeVal {
if prevNodeVal == "" {
w . log . Info ( "enr record" , logging . ENode ( "enr" , w . localNode . Node ( ) ) )
} else {
w . log . Info ( "new enr record" , logging . ENode ( "enr" , w . localNode . Node ( ) ) )
}
prevNodeVal = currNodeVal
}
}
}
}
}
2022-04-25 19:31:26 +00:00
// ListenAddresses returns all the multiaddresses used by the host
2021-09-30 23:03:19 +00:00
func ( w * WakuNode ) ListenAddresses ( ) [ ] ma . Multiaddr {
2023-07-07 15:51:15 +00:00
return utils . EncapsulatePeerID ( w . host . ID ( ) , w . host . Addrs ( ) ... )
2021-04-04 17:05:33 +00:00
}
2022-06-13 18:30:35 +00:00
// ENR returns the ENR address of the node
func ( w * WakuNode ) ENR ( ) * enode . Node {
return w . localNode . Node ( )
}
2022-12-09 03:08:04 +00:00
// Timesource returns the timesource used by this node to obtain the current wall time
// Depending on the configuration it will be the local time or a ntp syncd time
func ( w * WakuNode ) Timesource ( ) timesource . Timesource {
return w . timesource
}
2022-04-25 19:31:26 +00:00
// Relay is used to access any operation related to Waku Relay protocol
2021-04-28 20:10:44 +00:00
func ( w * WakuNode ) Relay ( ) * relay . WakuRelay {
2023-01-06 22:37:57 +00:00
if result , ok := w . relay . ( * relay . WakuRelay ) ; ok {
return result
}
return nil
2021-03-15 16:07:23 +00:00
}
2022-04-25 19:31:26 +00:00
// Store is used to access any operation related to Waku Store protocol
2022-03-18 19:56:34 +00:00
func ( w * WakuNode ) Store ( ) store . Store {
2023-01-06 22:37:57 +00:00
return w . store . ( store . Store )
2021-11-01 12:38:03 +00:00
}
2023-04-11 14:38:16 +00:00
// LegacyFilter is used to access any operation related to Waku LegacyFilter protocol
func ( w * WakuNode ) LegacyFilter ( ) * legacy_filter . WakuFilter {
if result , ok := w . legacyFilter . ( * legacy_filter . WakuFilter ) ; ok {
2023-01-06 22:37:57 +00:00
return result
}
return nil
2021-06-10 12:59:51 +00:00
}
2023-04-11 14:38:16 +00:00
// FilterLightnode is used to access any operation related to Waku Filter protocol Full node feature
2023-08-14 20:29:00 +00:00
func ( w * WakuNode ) FilterFullNode ( ) * filter . WakuFilterFullNode {
if result , ok := w . filterFullNode . ( * filter . WakuFilterFullNode ) ; ok {
2023-04-11 14:38:16 +00:00
return result
}
return nil
}
2023-08-14 20:29:00 +00:00
// FilterFullNode is used to access any operation related to Waku Filter protocol Light node feature
func ( w * WakuNode ) FilterLightnode ( ) * filter . WakuFilterLightNode {
if result , ok := w . filterLightNode . ( * filter . WakuFilterLightNode ) ; ok {
2023-02-08 23:33:06 +00:00
return result
}
return nil
}
2022-04-25 19:31:26 +00:00
// Lightpush is used to access any operation related to Waku Lightpush protocol
2021-11-01 12:38:03 +00:00
func ( w * WakuNode ) Lightpush ( ) * lightpush . WakuLightPush {
2023-01-06 22:37:57 +00:00
if result , ok := w . lightPush . ( * lightpush . WakuLightPush ) ; ok {
return result
}
return nil
2021-11-01 12:38:03 +00:00
}
2022-04-25 19:31:26 +00:00
// DiscV5 is used to access any operation related to DiscoveryV5
2021-11-17 16:19:42 +00:00
func ( w * WakuNode ) DiscV5 ( ) * discv5 . DiscoveryV5 {
2023-01-06 22:37:57 +00:00
if result , ok := w . discoveryV5 . ( * discv5 . DiscoveryV5 ) ; ok {
return result
}
return nil
2021-11-17 16:19:42 +00:00
}
2022-10-23 13:13:43 +00:00
// PeerExchange is used to access any operation related to Peer Exchange
func ( w * WakuNode ) PeerExchange ( ) * peer_exchange . WakuPeerExchange {
2023-01-06 22:37:57 +00:00
if result , ok := w . peerExchange . ( * peer_exchange . WakuPeerExchange ) ; ok {
return result
}
return nil
2022-10-23 13:13:43 +00:00
}
2023-06-23 15:50:32 +00:00
// Rendezvous is used to access any operation related to Rendezvous
func ( w * WakuNode ) Rendezvous ( ) * rendezvous . Rendezvous {
if result , ok := w . rendezvous . ( * rendezvous . Rendezvous ) ; ok {
return result
}
return nil
}
2022-04-25 19:31:26 +00:00
// Broadcaster is used to access the message broadcaster that is used to push
// messages to different protocols
2023-05-05 09:49:15 +00:00
func ( w * WakuNode ) Broadcaster ( ) relay . Broadcaster {
2021-11-18 14:20:58 +00:00
return w . bcaster
}
2021-11-17 16:19:42 +00:00
func ( w * WakuNode ) mountDiscV5 ( ) error {
discV5Options := [ ] discv5 . DiscoveryV5Option {
discv5 . WithBootnodes ( w . opts . discV5bootnodes ) ,
discv5 . WithUDPPort ( w . opts . udpPort ) ,
discv5 . WithAutoUpdate ( w . opts . discV5autoUpdate ) ,
}
2023-02-08 16:02:06 +00:00
if w . opts . advertiseAddrs != nil {
discV5Options = append ( discV5Options , discv5 . WithAdvertiseAddr ( w . opts . advertiseAddrs ) )
2022-03-10 22:14:50 +00:00
}
2022-03-30 00:02:33 +00:00
var err error
2023-08-16 01:40:00 +00:00
w . discoveryV5 , err = discv5 . NewDiscoveryV5 ( w . opts . privKey , w . localNode , w . peerConnector , w . opts . prometheusReg , w . log , discV5Options ... )
2021-11-17 16:19:42 +00:00
2021-12-08 14:21:30 +00:00
return err
2021-11-17 16:19:42 +00:00
}
2023-05-05 09:49:15 +00:00
func ( w * WakuNode ) startStore ( ctx context . Context , sub relay . Subscription ) error {
err := w . store . Start ( ctx , sub )
2022-12-09 03:08:04 +00:00
if err != nil {
w . log . Error ( "starting store" , zap . Error ( err ) )
return err
}
2021-09-06 13:10:19 +00:00
2022-12-09 03:08:04 +00:00
return nil
2021-03-18 23:21:45 +00:00
}
2023-08-10 12:58:22 +00:00
// AddPeer is used to add a peer and the protocols it support to the node peerstore
2023-09-14 15:00:06 +00:00
// TODO: Need to update this for autosharding, to only take contentTopics and optional pubSubTopics or provide an alternate API only for contentTopics.
func ( w * WakuNode ) AddPeer ( address ma . Multiaddr , origin wps . Origin , pubSubTopics [ ] string , protocols ... protocol . ID ) ( peer . ID , error ) {
return w . peermanager . AddPeer ( address , origin , pubSubTopics , protocols ... )
2021-08-31 18:19:49 +00:00
}
2021-06-10 12:59:51 +00:00
2023-08-10 12:58:22 +00:00
// AddDiscoveredPeer to add a discovered peer to the node peerStore
2023-09-27 06:46:37 +00:00
func ( w * WakuNode ) AddDiscoveredPeer ( ID peer . ID , addrs [ ] ma . Multiaddr , origin wps . Origin , pubsubTopics [ ] string , connectNow bool ) {
2023-08-10 12:58:22 +00:00
p := peermanager . PeerData {
Origin : origin ,
AddrInfo : peer . AddrInfo {
ID : ID ,
Addrs : addrs ,
} ,
2023-09-14 15:00:06 +00:00
PubSubTopics : pubsubTopics ,
2021-09-30 16:01:53 +00:00
}
2023-09-27 06:46:37 +00:00
w . peermanager . AddDiscoveredPeer ( p , connectNow )
2021-06-28 14:14:28 +00:00
}
2022-04-25 19:31:26 +00:00
// DialPeerWithMultiAddress is used to connect to a peer using a multiaddress
2021-10-01 10:32:15 +00:00
func ( w * WakuNode ) DialPeerWithMultiAddress ( ctx context . Context , address ma . Multiaddr ) error {
2021-09-30 23:03:19 +00:00
info , err := peer . AddrInfoFromP2pAddr ( address )
if err != nil {
return err
}
2021-10-01 10:32:15 +00:00
return w . connect ( ctx , * info )
2021-09-30 23:03:19 +00:00
}
2022-04-25 19:31:26 +00:00
// DialPeer is used to connect to a peer using a string containing a multiaddress
2021-10-01 10:32:15 +00:00
func ( w * WakuNode ) DialPeer ( ctx context . Context , address string ) error {
2021-03-18 23:21:45 +00:00
p , err := ma . NewMultiaddr ( address )
if err != nil {
return err
}
info , err := peer . AddrInfoFromP2pAddr ( p )
if err != nil {
return err
}
2021-10-01 10:32:15 +00:00
return w . connect ( ctx , * info )
2021-09-06 13:10:19 +00:00
}
2023-05-10 14:13:10 +00:00
// DialPeerWithInfo is used to connect to a peer using its address information
func ( w * WakuNode ) DialPeerWithInfo ( ctx context . Context , peerInfo peer . AddrInfo ) error {
return w . connect ( ctx , peerInfo )
}
2021-10-01 10:32:15 +00:00
func ( w * WakuNode ) connect ( ctx context . Context , info peer . AddrInfo ) error {
err := w . host . Connect ( ctx , info )
2021-09-06 13:10:19 +00:00
if err != nil {
2023-08-10 12:58:22 +00:00
w . host . Peerstore ( ) . ( wps . WakuPeerstore ) . AddConnFailure ( info )
2021-09-06 13:10:19 +00:00
return err
}
2021-10-16 21:50:49 +00:00
2023-09-01 20:42:46 +00:00
for _ , addr := range info . Addrs {
// TODO: this is a temporary fix
// host.Connect adds the addresses with a TempAddressTTL
// however, identify will filter out all non IP addresses
// and expire all temporary addrs. So in the meantime, let's
2023-09-20 06:54:16 +00:00
// store dns4 addresses with a RecentlyConnectedAddrTTL, otherwise
2023-09-01 20:42:46 +00:00
// it will have trouble with the status fleet circuit relay addresses
// See https://github.com/libp2p/go-libp2p/issues/2550
_ , err := addr . ValueForProtocol ( ma . P_DNS4 )
if err == nil {
2023-09-20 06:54:16 +00:00
w . host . Peerstore ( ) . AddAddrs ( info . ID , info . Addrs , peerstore . RecentlyConnectedAddrTTL )
2023-09-01 20:42:46 +00:00
}
}
2023-08-10 12:58:22 +00:00
w . host . Peerstore ( ) . ( wps . WakuPeerstore ) . ResetConnFailures ( info )
2023-08-16 01:40:00 +00:00
w . metrics . RecordDial ( )
2021-09-06 13:10:19 +00:00
return nil
2021-03-18 23:21:45 +00:00
}
2021-03-24 20:39:12 +00:00
2022-04-25 19:31:26 +00:00
// DialPeerByID is used to connect to an already known peer
2021-10-01 10:32:15 +00:00
func ( w * WakuNode ) DialPeerByID ( ctx context . Context , peerID peer . ID ) error {
2021-08-31 19:17:56 +00:00
info := w . host . Peerstore ( ) . PeerInfo ( peerID )
2021-10-01 10:32:15 +00:00
return w . connect ( ctx , info )
2021-08-31 19:17:56 +00:00
}
2022-04-25 19:31:26 +00:00
// ClosePeerByAddress is used to disconnect from a peer using its multiaddress
2021-03-24 20:39:12 +00:00
func ( w * WakuNode ) ClosePeerByAddress ( address string ) error {
p , err := ma . NewMultiaddr ( address )
if err != nil {
return err
}
// Extract the peer ID from the multiaddr.
info , err := peer . AddrInfoFromP2pAddr ( p )
if err != nil {
return err
}
return w . ClosePeerById ( info . ID )
}
2022-04-25 19:31:26 +00:00
// ClosePeerById is used to close a connection to a peer
2021-03-24 20:39:12 +00:00
func ( w * WakuNode ) ClosePeerById ( id peer . ID ) error {
2021-09-06 13:10:19 +00:00
err := w . host . Network ( ) . ClosePeer ( id )
if err != nil {
return err
}
2021-09-06 13:34:58 +00:00
return nil
2021-03-24 20:39:12 +00:00
}
2022-04-25 19:31:26 +00:00
// PeerCount return the number of connected peers
2021-03-24 20:39:12 +00:00
func ( w * WakuNode ) PeerCount ( ) int {
2021-10-06 15:34:39 +00:00
return len ( w . host . Network ( ) . Peers ( ) )
2021-03-24 20:39:12 +00:00
}
2021-06-24 13:02:53 +00:00
2022-04-25 19:31:26 +00:00
// PeerStats returns a list of peers and the protocols supported by them
2021-11-10 13:36:51 +00:00
func ( w * WakuNode ) PeerStats ( ) PeerStats {
2021-08-31 20:51:22 +00:00
p := make ( PeerStats )
2021-10-06 15:34:39 +00:00
for _ , peerID := range w . host . Network ( ) . Peers ( ) {
protocols , err := w . host . Peerstore ( ) . GetProtocols ( peerID )
if err != nil {
continue
}
p [ peerID ] = protocols
2021-08-31 20:51:22 +00:00
}
return p
}
2022-12-09 18:09:06 +00:00
// Set the bootnodes on discv5
func ( w * WakuNode ) SetDiscV5Bootnodes ( nodes [ ] * enode . Node ) error {
w . opts . discV5bootnodes = nodes
2023-01-06 22:37:57 +00:00
return w . DiscV5 ( ) . SetBootnodes ( nodes )
2022-12-09 18:09:06 +00:00
}
2022-04-25 19:31:26 +00:00
// Peers return the list of peers, addresses, protocols supported and connection status
2021-11-10 13:36:51 +00:00
func ( w * WakuNode ) Peers ( ) ( [ ] * Peer , error ) {
var peers [ ] * Peer
for _ , peerId := range w . host . Peerstore ( ) . Peers ( ) {
connected := w . host . Network ( ) . Connectedness ( peerId ) == network . Connected
protocols , err := w . host . Peerstore ( ) . GetProtocols ( peerId )
if err != nil {
return nil , err
}
2023-07-07 15:51:15 +00:00
addrs := utils . EncapsulatePeerID ( peerId , w . host . Peerstore ( ) . Addrs ( peerId ) ... )
2021-11-10 13:36:51 +00:00
peers = append ( peers , & Peer {
ID : peerId ,
Protocols : protocols ,
Connected : connected ,
Addrs : addrs ,
} )
}
return peers , nil
}
2023-05-12 21:52:42 +00:00
2023-09-29 05:13:25 +00:00
// PeersByShard filters peers based on shard information following static sharding
func ( w * WakuNode ) PeersByStaticShard ( cluster uint16 , shard uint16 ) peer . IDSlice {
2023-09-14 15:00:06 +00:00
pTopic := wakuprotocol . NewStaticShardingPubsubTopic ( cluster , shard ) . String ( )
return w . peerstore . ( wps . WakuPeerstore ) . PeersByPubSubTopic ( pTopic )
}
2023-09-29 05:13:25 +00:00
// PeersByContentTopics filters peers based on contentTopic
func ( w * WakuNode ) PeersByContentTopic ( contentTopic string ) peer . IDSlice {
pTopic , err := wakuprotocol . GetPubSubTopicFromContentTopic ( contentTopic )
if err != nil {
return nil
}
return w . peerstore . ( wps . WakuPeerstore ) . PeersByPubSubTopic ( pTopic )
}
2023-05-12 21:52:42 +00:00
func ( w * WakuNode ) findRelayNodes ( ctx context . Context ) {
defer w . wg . Done ( )
// Feed peers more often right after the bootstrap, then backoff
bo := backoffv4 . NewExponentialBackOff ( )
bo . InitialInterval = 15 * time . Second
bo . Multiplier = 3
bo . MaxInterval = 1 * time . Hour
bo . MaxElapsedTime = 0 // never stop
t := backoffv4 . NewTicker ( bo )
defer t . Stop ( )
for {
select {
case <- t . C :
case <- ctx . Done ( ) :
return
}
peers , err := w . Peers ( )
if err != nil {
w . log . Error ( "failed to fetch peers" , zap . Error ( err ) )
continue
}
// Shuffle peers
rand . Seed ( time . Now ( ) . UnixNano ( ) )
rand . Shuffle ( len ( peers ) , func ( i , j int ) { peers [ i ] , peers [ j ] = peers [ j ] , peers [ i ] } )
for _ , p := range peers {
info := w . Host ( ) . Peerstore ( ) . PeerInfo ( p . ID )
supportedProtocols , err := w . Host ( ) . Peerstore ( ) . SupportsProtocols ( p . ID , proto . ProtoIDv2Hop )
if err != nil {
w . log . Error ( "could not check supported protocols" , zap . Error ( err ) )
continue
}
if len ( supportedProtocols ) == 0 {
continue
}
select {
case <- ctx . Done ( ) :
w . log . Debug ( "context done, auto-relay has enough peers" )
return
case w . circuitRelayNodes <- info :
w . log . Debug ( "published auto-relay peer info" , zap . Any ( "peer-id" , p . ID ) )
}
}
}
}