Skip to content

Commit 723fc73

Browse files
committed
Rename total_score to nonce in sync message
1 parent ea56c0e commit 723fc73

File tree

6 files changed

+62
-99
lines changed

6 files changed

+62
-99
lines changed

core/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,4 +99,4 @@ pub use crate::service::ClientService;
9999
pub use crate::transaction::{
100100
LocalizedTransaction, PendingSignedTransactions, SignedTransaction, UnverifiedTransaction,
101101
};
102-
pub use crate::types::{BlockId, TransactionId};
102+
pub use crate::types::{BlockId, BlockStatus, TransactionId};

spec/Block-Synchronization-Extension.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ Message :=
1919
### Status
2020

2121
```
22-
Status(total_score, best_hash, genesis_hash)
22+
Status(nonce, best_hash, genesis_hash)
2323
```
2424

2525
Send current chain status to peer.
2626

2727
* Identifier: 0x01
28-
* Restriction: None
28+
* Restriction:
29+
* `nonce` SHOULD be monotonically increasing every time the message is sent.
2930

3031
## Request messages
3132

sync/src/block/downloader/header.rs

Lines changed: 28 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::sync::Arc;
2020
use std::time::Instant;
2121

2222
use ccore::encoded::Header;
23-
use ccore::{BlockChainClient, BlockId};
23+
use ccore::{BlockChainClient, BlockId, BlockStatus};
2424
use ctypes::BlockHash;
2525
use primitives::U256;
2626

@@ -31,65 +31,46 @@ const MAX_HEADER_QUEUE_LENGTH: usize = 1024;
3131
const MAX_RETRY: usize = 3;
3232
const MAX_WAIT: u64 = 15;
3333

34-
#[derive(Clone)]
35-
struct Pivot {
36-
hash: BlockHash,
37-
total_score: U256,
38-
}
39-
4034
#[derive(Clone)]
4135
pub struct HeaderDownloader {
4236
// NOTE: Use this member as minimum as possible.
4337
client: Arc<dyn BlockChainClient>,
4438

45-
total_score: U256,
39+
nonce: U256,
4640
best_hash: BlockHash,
47-
48-
pivot: Pivot,
41+
pivot: BlockHash,
4942
request_time: Option<Instant>,
5043
downloaded: HashMap<BlockHash, Header>,
5144
queued: HashMap<BlockHash, Header>,
5245
trial: usize,
5346
}
5447

5548
impl HeaderDownloader {
56-
pub fn total_score(&self) -> U256 {
57-
self.total_score
58-
}
59-
60-
pub fn new(client: Arc<dyn BlockChainClient>, total_score: U256, best_hash: BlockHash) -> Self {
49+
pub fn new(client: Arc<dyn BlockChainClient>, nonce: U256, best_hash: BlockHash) -> Self {
6150
let best_header_hash = client.best_block_header().hash();
62-
let best_score = client.block_total_score(&BlockId::Latest).expect("Best block always exist");
6351

6452
Self {
6553
client,
6654

67-
total_score,
55+
nonce,
6856
best_hash,
69-
70-
pivot: Pivot {
71-
hash: best_header_hash,
72-
total_score: best_score,
73-
},
57+
pivot: best_header_hash,
7458
request_time: None,
7559
downloaded: HashMap::new(),
7660
queued: HashMap::new(),
7761
trial: 0,
7862
}
7963
}
8064

81-
pub fn update(&mut self, total_score: U256, best_hash: BlockHash) -> bool {
82-
match self.total_score.cmp(&total_score) {
65+
pub fn update(&mut self, nonce: U256, best_hash: BlockHash) -> bool {
66+
match self.nonce.cmp(&nonce) {
8367
Ordering::Equal => true,
8468
Ordering::Less => {
85-
self.total_score = total_score;
69+
self.nonce = nonce;
8670
self.best_hash = best_hash;
8771

8872
if self.client.block_header(&BlockId::Hash(best_hash)).is_some() {
89-
self.pivot = Pivot {
90-
hash: best_hash,
91-
total_score,
92-
}
73+
self.pivot = best_hash;
9374
}
9475
true
9576
}
@@ -108,25 +89,28 @@ impl HeaderDownloader {
10889
/// Find header from queued headers, downloaded cache and then from blockchain
10990
/// Panics if header dosn't exist
11091
fn pivot_header(&self) -> Header {
111-
match self.queued.get(&self.pivot.hash) {
92+
match self.queued.get(&self.pivot) {
11293
Some(header) => header.clone(),
113-
None => match self.downloaded.get(&self.pivot.hash) {
94+
None => match self.downloaded.get(&self.pivot) {
11495
Some(header) => header.clone(),
115-
None => self.client.block_header(&BlockId::Hash(self.pivot.hash)).unwrap(),
96+
None => self.client.block_header(&BlockId::Hash(self.pivot)).unwrap(),
11697
},
11798
}
11899
}
119100

120-
pub fn pivot_score(&self) -> U256 {
121-
self.pivot.total_score
122-
}
123-
124101
pub fn is_idle(&self) -> bool {
125-
let can_request = self.request_time.is_none() && self.total_score > self.pivot.total_score;
102+
let can_request = self.request_time.is_none() && self.best_hash != self.pivot;
126103

127104
self.is_valid() && (can_request || self.is_expired())
128105
}
129106

107+
pub fn is_lagging(&self) -> bool {
108+
let peer_status = self.client.block_status(&BlockId::Hash(self.best_hash));
109+
let best_hash = self.client.block_hash(&BlockId::Latest).expect("Best hash always exists");
110+
111+
peer_status == BlockStatus::InChain && self.best_hash != best_hash
112+
}
113+
130114
pub fn create_request(&mut self) -> Option<RequestMessage> {
131115
if !self.is_idle() {
132116
return None
@@ -154,37 +138,30 @@ impl HeaderDownloader {
154138
let pivot_header = self.pivot_header();
155139

156140
// This happens when best_hash is imported by other peer.
157-
if self.best_hash == self.pivot.hash {
141+
if self.best_hash == self.pivot {
158142
ctrace!(SYNC, "Ignore received headers, pivot already reached the best hash");
159-
} else if first_header_hash == self.pivot.hash {
143+
} else if first_header_hash == self.pivot {
160144
for header in headers.iter() {
161145
self.downloaded.insert(header.hash(), header.clone());
162146
}
163147

164148
// FIXME: skip known headers
165-
let new_scores = headers[1..].iter().fold(U256::zero(), |acc, header| acc + header.score());
166-
self.pivot = Pivot {
167-
hash: headers.last().expect("Last downloaded header must exist").hash(),
168-
total_score: self.pivot.total_score + new_scores,
169-
}
149+
self.pivot = headers.last().expect("Last downloaded header must exist").hash();
170150
} else if first_header_number < pivot_header.number() {
171151
ctrace!(
172152
SYNC,
173153
"Ignore received headers, pivot is already updated since headers are imported by other peers"
174154
);
175155
} else if first_header_number == pivot_header.number() {
176156
if pivot_header.number() != 0 {
177-
self.pivot = Pivot {
178-
hash: pivot_header.parent_hash(),
179-
total_score: self.pivot.total_score - pivot_header.score(),
180-
}
157+
self.pivot = pivot_header.parent_hash();
181158
}
182159
} else {
183160
cerror!(
184161
SYNC,
185-
"Invalid header update state. best_hash: {}, self.pivot.hash: {}, first_header_hash: {}",
162+
"Invalid header update state. best_hash: {}, self.pivot: {}, first_header_hash: {}",
186163
self.best_hash,
187-
self.pivot.hash,
164+
self.pivot,
188165
first_header_hash
189166
);
190167
}
@@ -203,10 +180,7 @@ impl HeaderDownloader {
203180
self.downloaded.remove(&hash);
204181

205182
if self.best_hash == hash {
206-
self.pivot = Pivot {
207-
hash,
208-
total_score: self.total_score,
209-
}
183+
self.pivot = hash;
210184
}
211185
}
212186
self.queued.shrink_to_fit();

sync/src/block/extension.rs

Lines changed: 22 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ pub struct Extension {
7575
token_generator: TokenGenerator,
7676
client: Arc<Client>,
7777
api: Box<dyn Api>,
78-
last_request: u64,
78+
nonce: u64,
7979
}
8080

8181
impl Extension {
@@ -125,7 +125,7 @@ impl Extension {
125125
token_generator: TokenGenerator::new(SYNC_EXPIRE_TOKEN_BEGIN, SYNC_EXPIRE_TOKEN_END),
126126
client,
127127
api,
128-
last_request: Default::default(),
128+
nonce: Default::default(),
129129
}
130130
}
131131

@@ -138,8 +138,8 @@ impl Extension {
138138
fn send_header_request(&mut self, id: &NodeId, request: RequestMessage) {
139139
if let Some(requests) = self.requests.get_mut(id) {
140140
ctrace!(SYNC, "Send header request to {}", id);
141-
let request_id = self.last_request;
142-
self.last_request += 1;
141+
let request_id = self.nonce;
142+
self.nonce += 1;
143143
requests.push((request_id, request.clone()));
144144
self.api.send(id, Arc::new(Message::Request(request_id, request).rlp_bytes().into_vec()));
145145
}
@@ -161,8 +161,8 @@ impl Extension {
161161

162162
if let Some(request) = self.body_downloader.create_request() {
163163
cdebug!(SYNC, "Request body to {} {:?}", id, request);
164-
let request_id = self.last_request;
165-
self.last_request += 1;
164+
let request_id = self.nonce;
165+
self.nonce += 1;
166166
requests.push((request_id, request.clone()));
167167
self.api.send(id, Arc::new(Message::Request(request_id, request).rlp_bytes().into_vec()));
168168

@@ -243,14 +243,15 @@ impl NetworkExtension<Event> for Extension {
243243
id,
244244
Arc::new(
245245
Message::Status {
246-
total_score: chain_info.best_proposal_score,
246+
nonce: U256::from(self.nonce),
247247
best_hash: chain_info.best_proposal_block_hash,
248248
genesis_hash: chain_info.genesis_hash,
249249
}
250250
.rlp_bytes()
251251
.into_vec(),
252252
),
253253
);
254+
self.nonce += 1;
254255
let t = self.connected_nodes.insert(*id);
255256
debug_assert!(t, "{} is already added to peer list", id);
256257

@@ -299,10 +300,10 @@ impl NetworkExtension<Event> for Extension {
299300
if let Ok(received_message) = UntrustedRlp::new(data).as_val() {
300301
match received_message {
301302
Message::Status {
302-
total_score,
303+
nonce,
303304
best_hash,
304305
genesis_hash,
305-
} => self.on_peer_status(id, total_score, best_hash, genesis_hash),
306+
} => self.on_peer_status(id, nonce, best_hash, genesis_hash),
306307
Message::Request(request_id, request) => self.on_peer_request(id, request_id, request),
307308
Message::Response(request_id, response) => self.on_peer_response(id, request_id, response),
308309
}
@@ -328,7 +329,6 @@ impl NetworkExtension<Event> for Extension {
328329
}
329330
State::SnapshotChunk(..) => unimplemented!(),
330331
State::Full => {
331-
let best_proposal_score = self.client.chain_info().best_proposal_score;
332332
for id in &peer_ids {
333333
let request =
334334
self.header_downloaders.get_mut(id).and_then(HeaderDownloader::create_request);
@@ -339,13 +339,7 @@ impl NetworkExtension<Event> for Extension {
339339
}
340340

341341
for id in peer_ids {
342-
let peer_score = if let Some(peer) = self.header_downloaders.get(&id) {
343-
peer.total_score()
344-
} else {
345-
U256::zero()
346-
};
347-
348-
if peer_score > best_proposal_score {
342+
if self.header_downloaders.get(&id).map_or(false, |d| !d.is_lagging()) {
349343
self.send_body_request(&id);
350344
}
351345
}
@@ -501,20 +495,21 @@ impl Extension {
501495
id,
502496
Arc::new(
503497
Message::Status {
504-
total_score: chain_info.best_proposal_score,
498+
nonce: U256::from(self.nonce),
505499
best_hash: chain_info.best_proposal_block_hash,
506500
genesis_hash: chain_info.genesis_hash,
507501
}
508502
.rlp_bytes()
509503
.into_vec(),
510504
),
511505
);
506+
self.nonce += 1;
512507
}
513508
}
514509
}
515510

516511
impl Extension {
517-
fn on_peer_status(&mut self, from: &NodeId, total_score: U256, best_hash: BlockHash, genesis_hash: BlockHash) {
512+
fn on_peer_status(&mut self, from: &NodeId, nonce: U256, best_hash: BlockHash, genesis_hash: BlockHash) {
518513
// Validity check
519514
if genesis_hash != self.client.chain_info().genesis_hash {
520515
cinfo!(SYNC, "Genesis hash mismatch with peer {}", from);
@@ -523,17 +518,17 @@ impl Extension {
523518

524519
match self.header_downloaders.entry(*from) {
525520
Entry::Occupied(mut peer) => {
526-
if !peer.get_mut().update(total_score, best_hash) {
521+
if !peer.get_mut().update(nonce, best_hash) {
527522
// FIXME: It should be an error level if the consensus is PoW.
528523
cdebug!(SYNC, "Peer #{} status updated but score is less than before", from);
529524
return
530525
}
531526
}
532527
Entry::Vacant(e) => {
533-
e.insert(HeaderDownloader::new(self.client.clone(), total_score, best_hash));
528+
e.insert(HeaderDownloader::new(self.client.clone(), nonce, best_hash));
534529
}
535530
}
536-
cinfo!(SYNC, "Peer #{} status update: total_score: {}, best_hash: {}", from, total_score, best_hash);
531+
cinfo!(SYNC, "Peer #{} status update: nonce: {}, best_hash: {}", from, nonce, best_hash);
537532
}
538533

539534
fn on_peer_request(&self, from: &NodeId, id: u64, request: RequestMessage) {
@@ -759,14 +754,12 @@ impl Extension {
759754
}
760755
State::SnapshotChunk(..) => {}
761756
State::Full => {
762-
let (mut completed, pivot_score_changed) = if let Some(peer) = self.header_downloaders.get_mut(from) {
763-
let before_pivot_score = peer.pivot_score();
757+
let (mut completed, is_lagging) = if let Some(peer) = self.header_downloaders.get_mut(from) {
764758
let encoded: Vec<_> = headers.iter().map(|h| EncodedHeader::new(h.rlp_bytes().to_vec())).collect();
765759
peer.import_headers(&encoded);
766-
let after_pivot_score = peer.pivot_score();
767-
(peer.downloaded(), before_pivot_score != after_pivot_score)
760+
(peer.downloaded(), peer.is_lagging())
768761
} else {
769-
(Vec::new(), false)
762+
(Vec::new(), true)
770763
};
771764
completed.sort_unstable_by_key(EncodedHeader::number);
772765

@@ -792,7 +785,7 @@ impl Extension {
792785
peer.mark_as_imported(exists);
793786
peer.create_request()
794787
});
795-
if pivot_score_changed {
788+
if !is_lagging {
796789
if let Some(request) = request {
797790
self.send_header_request(from, request);
798791
}
@@ -834,18 +827,11 @@ impl Extension {
834827
}
835828
}
836829

837-
let total_score = self.client.chain_info().best_proposal_score;
838830
let mut peer_ids: Vec<_> = self.header_downloaders.keys().cloned().collect();
839831
peer_ids.shuffle(&mut thread_rng());
840832

841833
for id in peer_ids {
842-
let peer_score = if let Some(peer) = self.header_downloaders.get(&id) {
843-
peer.total_score()
844-
} else {
845-
U256::zero()
846-
};
847-
848-
if peer_score > total_score {
834+
if self.header_downloaders.get(&id).map_or(false, |d| !d.is_lagging()) {
849835
self.send_body_request(&id);
850836
}
851837
}

0 commit comments

Comments
 (0)