Skip to content

Commit 478d4f5

Browse files
committed
Gather signatures and actually submit scores to chain
1 parent 7873f2a commit 478d4f5

File tree

6 files changed

+239
-54
lines changed

6 files changed

+239
-54
lines changed

finality-aleph/src/abft/current/performance/service.rs

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,31 @@
1+
use std::collections::HashMap;
2+
13
use current_aleph_bft::NodeCount;
24
use futures::{
35
channel::{mpsc, oneshot},
46
StreamExt,
57
};
68
use log::{debug, error, warn};
9+
use parity_scale_codec::Encode;
10+
use sp_runtime::traits::Hash as _;
711

812
use crate::{
913
abft::{
1014
current::performance::{scorer::Scorer, Batch},
1115
LOG_TARGET,
1216
},
17+
aleph_primitives::{
18+
crypto::SignatureSet, AuthoritySignature, Hash, Hashing, RawScore, Score, ScoreNonce,
19+
},
1320
data_io::AlephData,
1421
metrics::ScoreMetrics,
1522
party::manager::Runnable,
16-
Hasher, UnverifiedHeader,
23+
runtime_api::RuntimeApi,
24+
Hasher, SessionId, UnverifiedHeader,
1725
};
1826

27+
const SCORE_SUBMISSION_PERIOD: usize = 300;
28+
1929
struct FinalizationWrapper<UH, FH>
2030
where
2131
UH: UnverifiedHeader,
@@ -59,26 +69,41 @@ where
5969
}
6070

6171
/// A service computing the performance score of ABFT nodes based on batches of ordered units.
62-
pub struct Service<UH>
72+
pub struct Service<UH, RA>
6373
where
6474
UH: UnverifiedHeader,
75+
RA: RuntimeApi,
6576
{
6677
my_index: usize,
78+
session_id: SessionId,
6779
batches_from_abft: mpsc::UnboundedReceiver<Batch<UH>>,
80+
hashes_for_aggregator: mpsc::UnboundedSender<Hash>,
81+
signatures_from_aggregator: mpsc::UnboundedReceiver<(Hash, SignatureSet<AuthoritySignature>)>,
82+
runtime_api: RA,
83+
pending_scores: HashMap<Hash, Score>,
84+
nonce: ScoreNonce,
6885
scorer: Scorer,
6986
metrics: ScoreMetrics,
7087
}
7188

72-
impl<UH> Service<UH>
89+
impl<UH, RA> Service<UH, RA>
7390
where
7491
UH: UnverifiedHeader,
92+
RA: RuntimeApi,
7593
{
7694
/// Create a new service, together with a unit finalization handler that should be passed to
7795
/// ABFT. It will wrap the provided finalization handler and call it in the background.
7896
pub fn new<FH>(
7997
my_index: usize,
8098
n_members: usize,
99+
session_id: SessionId,
81100
finalization_handler: FH,
101+
hashes_for_aggregator: mpsc::UnboundedSender<Hash>,
102+
signatures_from_aggregator: mpsc::UnboundedReceiver<(
103+
Hash,
104+
SignatureSet<AuthoritySignature>,
105+
)>,
106+
runtime_api: RA,
82107
metrics: ScoreMetrics,
83108
) -> (
84109
Self,
@@ -91,34 +116,81 @@ where
91116
(
92117
Service {
93118
my_index,
119+
session_id,
94120
batches_from_abft,
121+
hashes_for_aggregator,
122+
signatures_from_aggregator,
123+
runtime_api,
124+
pending_scores: HashMap::new(),
125+
nonce: 0,
95126
scorer: Scorer::new(NodeCount(n_members)),
96127
metrics,
97128
},
98129
FinalizationWrapper::new(finalization_handler, batches_for_us),
99130
)
100131
}
132+
133+
fn make_score(&mut self, points: RawScore) -> Score {
134+
let result = Score {
135+
session_id: self.session_id.0,
136+
nonce: self.nonce,
137+
points,
138+
};
139+
self.nonce += 1;
140+
result
141+
}
101142
}
102143

103144
#[async_trait::async_trait]
104-
impl<UH> Runnable for Service<UH>
145+
impl<UH, RA> Runnable for Service<UH, RA>
105146
where
106147
UH: UnverifiedHeader,
148+
RA: RuntimeApi,
107149
{
108150
async fn run(mut self, mut exit: oneshot::Receiver<()>) {
151+
let mut batch_counter = 1;
109152
loop {
110153
tokio::select! {
111154
maybe_batch = self.batches_from_abft.next() => {
112-
let score = match maybe_batch {
155+
let points = match maybe_batch {
113156
Some(batch) => self.scorer.process_batch(batch),
114157
None => {
115158
error!(target: LOG_TARGET, "Batches' channel closed, ABFT performance scoring terminating.");
116159
break;
117160
},
118161
};
119-
debug!(target: LOG_TARGET, "Received ABFT score: {:?}.", score);
120-
self.metrics.report_score(score[self.my_index]);
121-
// TODO(A0-4339): sometimes submit these scores to the chain.
162+
self.metrics.report_score(points[self.my_index]);
163+
if batch_counter % SCORE_SUBMISSION_PERIOD == 0 {
164+
let score = self.make_score(points);
165+
let score_hash = Hashing::hash_of(&score.encode());
166+
debug!(target: LOG_TARGET, "Gathering signature under ABFT score: {:?}.", score);
167+
self.pending_scores.insert(score_hash, score);
168+
if let Err(e) = self.hashes_for_aggregator.unbounded_send(score_hash) {
169+
error!(target: LOG_TARGET, "Failed to send score hash to signature aggregation: {}.", e);
170+
break;
171+
}
172+
}
173+
batch_counter += 1;
174+
}
175+
maybe_signed = self.signatures_from_aggregator.next() => {
176+
match maybe_signed {
177+
Some((hash, signature)) => {
178+
match self.pending_scores.remove(&hash) {
179+
Some(score) => {
180+
if let Err(e) = self.runtime_api.submit_abft_score(score, signature) {
181+
warn!(target: LOG_TARGET, "Failed to submit performance score to chain: {}.", e);
182+
}
183+
},
184+
None => {
185+
warn!(target: LOG_TARGET, "Received multisigned hash for unknown performance score, this shouldn't ever happen.");
186+
},
187+
}
188+
},
189+
None => {
190+
error!(target: LOG_TARGET, "Signatures' channel closed, ABFT performance scoring terminating.");
191+
break;
192+
},
193+
}
122194
}
123195
_ = &mut exit => {
124196
debug!(target: LOG_TARGET, "ABFT performance scoring task received exit signal. Terminating.");

finality-aleph/src/nodes.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use primitives::TransactionHash;
99
use rate_limiter::SharedRateLimiter;
1010
use sc_client_api::Backend;
1111
use sc_keystore::{Keystore, LocalKeystore};
12-
use sc_transaction_pool_api::TransactionPool;
12+
use sc_transaction_pool_api::{LocalTransactionPool, TransactionPool};
1313
use sp_consensus_aura::AuraApi;
1414

1515
use crate::{
@@ -60,7 +60,9 @@ where
6060
C: crate::ClientForAleph<Block, BE> + Send + Sync + 'static,
6161
C::Api: AlephSessionApi<Block> + AuraApi<Block, AuraId>,
6262
BE: Backend<Block> + 'static,
63-
TP: TransactionPool<Block = Block, Hash = TransactionHash> + 'static,
63+
TP: LocalTransactionPool<Block = Block>
64+
+ TransactionPool<Block = Block, Hash = TransactionHash>
65+
+ 'static,
6466
{
6567
let AlephConfig {
6668
authentication_network,
@@ -132,8 +134,10 @@ where
132134
}
133135
});
134136

137+
let runtime_api = RuntimeApiImpl::new(client.clone(), transaction_pool.clone());
138+
135139
let map_updater = SessionMapUpdater::new(
136-
AuthorityProviderImpl::new(client.clone(), RuntimeApiImpl::new(client.clone())),
140+
AuthorityProviderImpl::new(client.clone(), runtime_api.clone()),
137141
FinalityNotifierImpl::new(client.clone()),
138142
session_period,
139143
);
@@ -178,7 +182,7 @@ where
178182
);
179183

180184
let session_authority_provider =
181-
AuthorityProviderImpl::new(client.clone(), RuntimeApiImpl::new(client.clone()));
185+
AuthorityProviderImpl::new(client.clone(), runtime_api.clone());
182186
let verifier = VerifierCache::new(
183187
session_info.clone(),
184188
SubstrateFinalizationInfo::new(client.clone()),
@@ -225,7 +229,7 @@ where
225229
ValidatorIndexToAccountIdConverterImpl::new(
226230
client.clone(),
227231
session_info.clone(),
228-
RuntimeApiImpl::new(client.clone()),
232+
runtime_api.clone(),
229233
),
230234
);
231235

@@ -271,6 +275,7 @@ where
271275
spawn_handle,
272276
connection_manager,
273277
keystore,
278+
runtime_api,
274279
score_metrics,
275280
),
276281
session_info,

0 commit comments

Comments
 (0)