@@ -6,11 +6,9 @@ use futures::{StreamExt, stream::SelectAll};
6
6
use tokio:: { spawn, sync:: mpsc, task:: JoinHandle } ;
7
7
use tokio_stream:: wrappers:: ReceiverStream ;
8
8
use tracing:: { debug, warn} ;
9
- use url:: Url ;
10
9
11
10
#[ derive( Debug ) ]
12
11
pub struct Multiwatcher {
13
- height : Height ,
14
12
threshold : usize ,
15
13
watchers : Vec < JoinHandle < ( ) > > ,
16
14
headers : BTreeMap < Height , HashMap < Header , HashSet < Id > > > ,
@@ -29,11 +27,10 @@ impl Drop for Multiwatcher {
29
27
}
30
28
31
29
impl Multiwatcher {
32
- pub fn new < C , H , I , N > ( configs : C , height : H , nsid : N , threshold : usize ) -> Self
30
+ pub fn new < C , H , N > ( configs : C , height : H , nsid : N , threshold : usize ) -> Self
33
31
where
34
32
C : IntoIterator < Item = Config > ,
35
33
H : Into < Height > ,
36
- I : IntoIterator < Item = Url > ,
37
34
N : Into < NamespaceId > ,
38
35
{
39
36
let height = height. into ( ) ;
@@ -49,52 +46,48 @@ impl Multiwatcher {
49
46
while tx. send ( ( id, w. next ( ) . await ) ) . await . is_ok ( ) { }
50
47
} ) ) ;
51
48
}
49
+ assert ! ( !watchers. is_empty( ) ) ;
52
50
Self {
53
- height,
54
51
threshold,
55
52
stream,
56
53
watchers,
57
54
headers : BTreeMap :: from_iter ( [ ( height, HashMap :: new ( ) ) ] ) ,
58
55
}
59
56
}
60
57
61
- pub async fn next ( & mut self ) -> Option < Header > {
58
+ pub async fn next ( & mut self ) -> Header {
62
59
loop {
63
- let ( i, hdr) = self . stream . next ( ) . await ? ;
60
+ let ( i, hdr) = self . stream . next ( ) . await . expect ( "watchers never terminate" ) ;
64
61
let h = Height :: from ( hdr. height ( ) ) ;
65
62
if Some ( h) < self . headers . first_entry ( ) . map ( |e| * e. key ( ) ) {
66
- debug ! ( %h, "ignoring header below minimum height" ) ;
63
+ debug ! ( height = %h, "ignoring header below minimum height" ) ;
67
64
continue ;
68
65
}
69
66
if self . has_voted ( h, i) {
70
- warn ! ( %h, "source sent multiple headers for same height" ) ;
67
+ warn ! ( height = %h, "source sent multiple headers for same height" ) ;
71
68
continue ;
72
69
}
73
- let votes = self . headers . entry ( h) . or_default ( ) ;
74
- if let Some ( ids ) = votes . get ( & hdr)
75
- && ids . len ( ) + 1 >= self . threshold
76
- {
77
- self . gc ( h ) ;
78
- return Some ( hdr) ;
70
+ let counter = self . headers . entry ( h) . or_default ( ) ;
71
+ let votes = counter . get ( & hdr) . map ( |ids| ids . len ( ) ) . unwrap_or ( 0 ) + 1 ;
72
+ if votes >= self . threshold {
73
+ self . headers . retain ( |k , _| * k > h ) ;
74
+ debug ! ( height = %h , "header available" ) ;
75
+ return hdr;
79
76
}
80
- votes. entry ( hdr) . or_default ( ) . insert ( i) ;
77
+ debug ! ( height = %h, %votes, "vote added" ) ;
78
+ counter. entry ( hdr) . or_default ( ) . insert ( i) ;
81
79
}
82
80
}
83
81
84
82
fn has_voted ( & self , height : Height , id : Id ) -> bool {
85
83
let Some ( m) = self . headers . get ( & height) else {
86
84
return false ;
87
85
} ;
88
- for v in m. values ( ) {
89
- if v . contains ( & id) {
86
+ for ids in m. values ( ) {
87
+ if ids . contains ( & id) {
90
88
return true ;
91
89
}
92
90
}
93
91
false
94
92
}
95
-
96
- fn gc ( & mut self , height : Height ) {
97
- self . headers . retain ( |h, _| * h >= height) ;
98
- self . height = height;
99
- }
100
93
}
0 commit comments