@@ -12,6 +12,7 @@ use libp2p::{
12
12
core,
13
13
core:: { muxing:: StreamMuxerBox , transport:: Boxed } ,
14
14
dns,
15
+ gossipsub:: { GossipsubConfig , GossipsubEvent , GossipsubMessage , Topic as GossipsubTopic , TopicHash } ,
15
16
identity:: Keypair ,
16
17
kad:: { GetRecordOk , KademliaConfig , KademliaEvent , QueryId , QueryResult , Quorum , Record } ,
17
18
noise,
@@ -47,6 +48,7 @@ pub struct Config {
47
48
pub message : MessageConfig ,
48
49
pub limit : LimitConfig ,
49
50
pub kademlia : KademliaConfig ,
51
+ pub gossipsub : GossipsubConfig ,
50
52
}
51
53
52
54
#[ derive( Debug , Error ) ]
@@ -74,6 +76,9 @@ pub enum NetworkError {
74
76
75
77
#[ error( "DHT PutRecord error: {0:?}" ) ]
76
78
DhtPutRecord ( libp2p:: kad:: PutRecordError ) ,
79
+
80
+ #[ error( "Gossipsub Publish error: {0:?}" ) ]
81
+ GossipsubPublish ( libp2p:: gossipsub:: error:: PublishError )
77
82
}
78
83
79
84
impl From < libp2p:: kad:: store:: Error > for NetworkError {
@@ -94,8 +99,13 @@ impl From<libp2p::kad::PutRecordError> for NetworkError {
94
99
}
95
100
}
96
101
97
- type NimiqSwarm = Swarm < NimiqBehaviour > ;
102
+ impl From < libp2p:: gossipsub:: error:: PublishError > for NetworkError {
103
+ fn from ( e : libp2p:: gossipsub:: error:: PublishError ) -> Self {
104
+ Self :: GossipsubPublish ( e)
105
+ }
106
+ }
98
107
108
+ type NimiqSwarm = Swarm < NimiqBehaviour > ;
99
109
#[ derive( Debug ) ]
100
110
pub enum NetworkAction {
101
111
Dial {
@@ -115,12 +125,27 @@ pub enum NetworkAction {
115
125
value : Vec < u8 > ,
116
126
output : oneshot:: Sender < Result < ( ) , NetworkError > > ,
117
127
} ,
128
+ RegisterTopic {
129
+ topic_hash : TopicHash ,
130
+ output : mpsc:: Sender < ( GossipsubMessage , Arc < Peer > ) > ,
131
+ } ,
132
+ Subscribe {
133
+ topic_name : & ' static str ,
134
+ output : oneshot:: Sender < TopicHash > ,
135
+ } ,
136
+ Publish {
137
+ topic_name : & ' static str ,
138
+ data : Vec < u8 > ,
139
+ output : oneshot:: Sender < Result < ( ) , NetworkError > > ,
140
+ } ,
118
141
}
119
142
120
143
#[ derive( Default ) ]
121
144
struct TaskState {
122
145
dht_puts : HashMap < QueryId , oneshot:: Sender < Result < ( ) , NetworkError > > > ,
123
146
dht_gets : HashMap < QueryId , oneshot:: Sender < Result < Vec < u8 > , NetworkError > > > ,
147
+ gossip_sub : HashMap < TopicHash , oneshot:: Sender < TopicHash > > ,
148
+ gossip_topics : HashMap < TopicHash , mpsc:: Sender < ( GossipsubMessage , Arc < Peer > ) > > ,
124
149
}
125
150
126
151
pub struct Network {
@@ -274,6 +299,30 @@ impl Network {
274
299
_ => { }
275
300
}
276
301
}
302
+ NimiqEvent :: Gossip ( event) => {
303
+ match event {
304
+ GossipsubEvent :: Message ( peer_id, msg_id, msg) => {
305
+ log:: trace!( "Received message {:?} from peer {:?}: {:?}" , msg_id, peer_id, msg) ;
306
+ for topic in msg. topics . iter ( ) {
307
+ if let Some ( output) = state. gossip_topics . get ( & topic) {
308
+ // let peer = Self::get_peer(peer_id).unwrap();
309
+ // output.send((msg, peer));
310
+ } else {
311
+ log:: warn!( "Unknown topic hash: {:?}" , topic) ;
312
+ }
313
+ }
314
+ }
315
+ GossipsubEvent :: Subscribed { peer_id, topic } => {
316
+ log:: trace!( "Peer {:?} subscribed to topic: {:?}" , peer_id, topic) ;
317
+ if let Some ( output) = state. gossip_sub . remove ( & topic) {
318
+ output. send ( topic) . ok ( ) ;
319
+ }
320
+ }
321
+ GossipsubEvent :: Unsubscribed { peer_id, topic } => {
322
+ log:: trace!( "Peer {:?} unsubscribed to topic: {:?}" , peer_id, topic) ;
323
+ }
324
+ }
325
+ }
277
326
}
278
327
}
279
328
_ => { }
@@ -316,6 +365,22 @@ impl Network {
316
365
}
317
366
}
318
367
}
368
+ NetworkAction :: RegisterTopic { topic_hash, output } => {
369
+ state. gossip_topics . insert ( topic_hash, output) ;
370
+ }
371
+ NetworkAction :: Subscribe { topic_name, output } => {
372
+ let topic = GossipsubTopic :: new ( topic_name. into ( ) ) ;
373
+ if swarm. gossipsub . subscribe ( topic. clone ( ) ) {
374
+ state. gossip_sub . insert ( topic. sha256_hash ( ) , output) ;
375
+ } else {
376
+ log:: warn!( "Already subscribed to topic: {:?}" , topic_name) ;
377
+ drop ( output) ;
378
+ }
379
+ }
380
+ NetworkAction :: Publish { topic_name, data, output } => {
381
+ let topic = GossipsubTopic :: new ( topic_name. into ( ) ) ;
382
+ output. send ( swarm. gossipsub . publish ( & topic, data) . map_err ( Into :: into) ) . ok ( ) ;
383
+ }
319
384
}
320
385
321
386
Ok ( ( ) )
@@ -344,18 +409,61 @@ impl NetworkInterface for Network {
344
409
self . events_tx . subscribe ( )
345
410
}
346
411
347
- async fn subscribe < T > ( _topic : & T ) -> Box < dyn Stream < Item = ( T :: Item , Self :: PeerType ) > + Send >
412
+ async fn subscribe < T > ( & self , topic : & T ) -> Box < dyn Stream < Item = ( T :: Item , Arc < Self :: PeerType > ) > + Send >
348
413
where
349
414
T : Topic + Sync ,
350
415
{
351
- unimplemented ! ( )
416
+ let ( output_tx, output_rx) = oneshot:: channel ( ) ;
417
+
418
+ self . action_tx
419
+ . lock ( )
420
+ . await
421
+ . send ( NetworkAction :: Subscribe {
422
+ topic_name : topic. topic ( ) ,
423
+ output : output_tx,
424
+ } )
425
+ . await ;
426
+
427
+ let topic_hash = output_rx. await . expect ( "Already subscribed to topic" ) ;
428
+ let ( tx, rx) = mpsc:: channel ( 16 ) ;
429
+
430
+ self . action_tx
431
+ . lock ( )
432
+ . await
433
+ . send ( NetworkAction :: RegisterTopic {
434
+ topic_hash,
435
+ output : tx,
436
+ } )
437
+ . await ;
438
+
439
+ let test = rx. map ( |( msg, peer) |
440
+ {
441
+ let item = msg. data ;
442
+ ( item , peer)
443
+ } ) . into_inner ( ) ;
444
+ Box :: new ( test)
352
445
}
353
446
354
- async fn publish < T > ( _topic : & T , _item : <T as Topic >:: Item )
447
+ async fn publish < T > ( & self , topic : & T , item : <T as Topic >:: Item ) -> Result < ( ) , Self :: Error >
355
448
where
356
449
T : Topic + Sync ,
357
450
{
358
- unimplemented ! ( )
451
+ let ( output_tx, output_rx) = oneshot:: channel ( ) ;
452
+
453
+ let mut buf = vec ! [ ] ;
454
+ item. serialize ( & mut buf) ?;
455
+
456
+ self . action_tx
457
+ . lock ( )
458
+ . await
459
+ . send ( NetworkAction :: Publish {
460
+ topic_name : topic. topic ( ) ,
461
+ data : buf,
462
+ output : output_tx,
463
+ } )
464
+ . await ?;
465
+
466
+ output_rx. await ?
359
467
}
360
468
361
469
async fn dht_get < K , V > ( & self , k : & K ) -> Result < V , Self :: Error >
@@ -482,6 +590,7 @@ mod tests {
482
590
message : Default :: default ( ) ,
483
591
limit : Default :: default ( ) ,
484
592
kademlia : Default :: default ( ) ,
593
+ gossipsub : Default :: default ( ) ,
485
594
}
486
595
}
487
596
0 commit comments