mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-12 13:31:10 +00:00
validator -> authority
This commit is contained in:
@@ -117,37 +117,37 @@ struct VoteCounts {
|
||||
|
||||
/// Accumulates messages for a given round of BFT consensus.
|
||||
///
|
||||
/// This isn't tied to the "view" of a single validator. It
|
||||
/// This isn't tied to the "view" of a single authority. It
|
||||
/// keeps accurate track of the state of the BFT consensus based
|
||||
/// on all messages imported.
|
||||
#[derive(Debug)]
|
||||
pub struct Accumulator<Candidate, Digest, ValidatorId, Signature>
|
||||
pub struct Accumulator<Candidate, Digest, AuthorityId, Signature>
|
||||
where
|
||||
Candidate: Eq + Clone,
|
||||
Digest: Hash + Eq + Clone,
|
||||
ValidatorId: Hash + Eq,
|
||||
AuthorityId: Hash + Eq,
|
||||
Signature: Eq + Clone,
|
||||
{
|
||||
round_number: usize,
|
||||
threshold: usize,
|
||||
round_proposer: ValidatorId,
|
||||
round_proposer: AuthorityId,
|
||||
proposal: Option<Candidate>,
|
||||
prepares: HashMap<ValidatorId, (Digest, Signature)>,
|
||||
commits: HashMap<ValidatorId, (Digest, Signature)>,
|
||||
prepares: HashMap<AuthorityId, (Digest, Signature)>,
|
||||
commits: HashMap<AuthorityId, (Digest, Signature)>,
|
||||
vote_counts: HashMap<Digest, VoteCounts>,
|
||||
advance_round: HashSet<ValidatorId>,
|
||||
advance_round: HashSet<AuthorityId>,
|
||||
state: State<Candidate, Digest, Signature>,
|
||||
}
|
||||
|
||||
impl<Candidate, Digest, ValidatorId, Signature> Accumulator<Candidate, Digest, ValidatorId, Signature>
|
||||
impl<Candidate, Digest, AuthorityId, Signature> Accumulator<Candidate, Digest, AuthorityId, Signature>
|
||||
where
|
||||
Candidate: Eq + Clone,
|
||||
Digest: Hash + Eq + Clone,
|
||||
ValidatorId: Hash + Eq,
|
||||
AuthorityId: Hash + Eq,
|
||||
Signature: Eq + Clone,
|
||||
{
|
||||
/// Create a new state accumulator.
|
||||
pub fn new(round_number: usize, threshold: usize, round_proposer: ValidatorId) -> Self {
|
||||
pub fn new(round_number: usize, threshold: usize, round_proposer: AuthorityId) -> Self {
|
||||
Accumulator {
|
||||
round_number,
|
||||
threshold,
|
||||
@@ -184,7 +184,7 @@ impl<Candidate, Digest, ValidatorId, Signature> Accumulator<Candidate, Digest, V
|
||||
/// and authorization should have already been checked.
|
||||
pub fn import_message(
|
||||
&mut self,
|
||||
message: LocalizedMessage<Candidate, Digest, ValidatorId, Signature>,
|
||||
message: LocalizedMessage<Candidate, Digest, AuthorityId, Signature>,
|
||||
)
|
||||
{
|
||||
// message from different round.
|
||||
@@ -205,7 +205,7 @@ impl<Candidate, Digest, ValidatorId, Signature> Accumulator<Candidate, Digest, V
|
||||
fn import_proposal(
|
||||
&mut self,
|
||||
proposal: Candidate,
|
||||
sender: ValidatorId,
|
||||
sender: AuthorityId,
|
||||
) {
|
||||
if sender != self.round_proposer || self.proposal.is_some() { return }
|
||||
|
||||
@@ -216,7 +216,7 @@ impl<Candidate, Digest, ValidatorId, Signature> Accumulator<Candidate, Digest, V
|
||||
fn import_prepare(
|
||||
&mut self,
|
||||
digest: Digest,
|
||||
sender: ValidatorId,
|
||||
sender: AuthorityId,
|
||||
signature: Signature,
|
||||
) {
|
||||
// ignore any subsequent prepares by the same sender.
|
||||
@@ -259,7 +259,7 @@ impl<Candidate, Digest, ValidatorId, Signature> Accumulator<Candidate, Digest, V
|
||||
fn import_commit(
|
||||
&mut self,
|
||||
digest: Digest,
|
||||
sender: ValidatorId,
|
||||
sender: AuthorityId,
|
||||
signature: Signature,
|
||||
) {
|
||||
// ignore any subsequent commits by the same sender.
|
||||
@@ -299,7 +299,7 @@ impl<Candidate, Digest, ValidatorId, Signature> Accumulator<Candidate, Digest, V
|
||||
|
||||
fn import_advance_round(
|
||||
&mut self,
|
||||
sender: ValidatorId,
|
||||
sender: AuthorityId,
|
||||
) {
|
||||
self.advance_round.insert(sender);
|
||||
|
||||
@@ -327,7 +327,7 @@ mod tests {
|
||||
pub struct Digest(usize);
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Debug)]
|
||||
pub struct ValidatorId(usize);
|
||||
pub struct AuthorityId(usize);
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct Signature(usize, usize);
|
||||
@@ -342,7 +342,7 @@ mod tests {
|
||||
|
||||
let check_message = |r, d: &Digest, s: &Signature| {
|
||||
if r == 2 && d.0 == 600 && s.0 == 600 {
|
||||
Some(ValidatorId(s.1))
|
||||
Some(AuthorityId(s.1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -365,11 +365,11 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn accepts_proposal_from_proposer_only() {
|
||||
let mut accumulator = Accumulator::<_, Digest, _, _>::new(1, 7, ValidatorId(8));
|
||||
let mut accumulator = Accumulator::<_, Digest, _, _>::new(1, 7, AuthorityId(8));
|
||||
assert_eq!(accumulator.state(), &State::Begin);
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(5),
|
||||
sender: AuthorityId(5),
|
||||
signature: Signature(999, 5),
|
||||
message: Message::Propose(1, Candidate(999)),
|
||||
});
|
||||
@@ -377,7 +377,7 @@ mod tests {
|
||||
assert_eq!(accumulator.state(), &State::Begin);
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(8),
|
||||
sender: AuthorityId(8),
|
||||
signature: Signature(999, 8),
|
||||
message: Message::Propose(1, Candidate(999)),
|
||||
});
|
||||
@@ -387,11 +387,11 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn reaches_prepare_phase() {
|
||||
let mut accumulator = Accumulator::new(1, 7, ValidatorId(8));
|
||||
let mut accumulator = Accumulator::new(1, 7, AuthorityId(8));
|
||||
assert_eq!(accumulator.state(), &State::Begin);
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(8),
|
||||
sender: AuthorityId(8),
|
||||
signature: Signature(999, 8),
|
||||
message: Message::Propose(1, Candidate(999)),
|
||||
});
|
||||
@@ -400,7 +400,7 @@ mod tests {
|
||||
|
||||
for i in 0..6 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(999, i),
|
||||
message: Message::Prepare(1, Digest(999)),
|
||||
});
|
||||
@@ -409,7 +409,7 @@ mod tests {
|
||||
}
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(7),
|
||||
sender: AuthorityId(7),
|
||||
signature: Signature(999, 7),
|
||||
message: Message::Prepare(1, Digest(999)),
|
||||
});
|
||||
@@ -422,11 +422,11 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn prepare_to_commit() {
|
||||
let mut accumulator = Accumulator::new(1, 7, ValidatorId(8));
|
||||
let mut accumulator = Accumulator::new(1, 7, AuthorityId(8));
|
||||
assert_eq!(accumulator.state(), &State::Begin);
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(8),
|
||||
sender: AuthorityId(8),
|
||||
signature: Signature(999, 8),
|
||||
message: Message::Propose(1, Candidate(999)),
|
||||
});
|
||||
@@ -435,7 +435,7 @@ mod tests {
|
||||
|
||||
for i in 0..6 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(999, i),
|
||||
message: Message::Prepare(1, Digest(999)),
|
||||
});
|
||||
@@ -444,7 +444,7 @@ mod tests {
|
||||
}
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(7),
|
||||
sender: AuthorityId(7),
|
||||
signature: Signature(999, 7),
|
||||
message: Message::Prepare(1, Digest(999)),
|
||||
});
|
||||
@@ -456,7 +456,7 @@ mod tests {
|
||||
|
||||
for i in 0..6 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(999, i),
|
||||
message: Message::Commit(1, Digest(999)),
|
||||
});
|
||||
@@ -468,7 +468,7 @@ mod tests {
|
||||
}
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(7),
|
||||
sender: AuthorityId(7),
|
||||
signature: Signature(999, 7),
|
||||
message: Message::Commit(1, Digest(999)),
|
||||
});
|
||||
@@ -481,11 +481,11 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn prepare_to_advance() {
|
||||
let mut accumulator = Accumulator::new(1, 7, ValidatorId(8));
|
||||
let mut accumulator = Accumulator::new(1, 7, AuthorityId(8));
|
||||
assert_eq!(accumulator.state(), &State::Begin);
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(8),
|
||||
sender: AuthorityId(8),
|
||||
signature: Signature(999, 8),
|
||||
message: Message::Propose(1, Candidate(999)),
|
||||
});
|
||||
@@ -494,7 +494,7 @@ mod tests {
|
||||
|
||||
for i in 0..7 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(999, i),
|
||||
message: Message::Prepare(1, Digest(999)),
|
||||
});
|
||||
@@ -507,7 +507,7 @@ mod tests {
|
||||
|
||||
for i in 0..6 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(999, i),
|
||||
message: Message::AdvanceRound(1),
|
||||
});
|
||||
@@ -519,7 +519,7 @@ mod tests {
|
||||
}
|
||||
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(7),
|
||||
sender: AuthorityId(7),
|
||||
signature: Signature(999, 7),
|
||||
message: Message::AdvanceRound(1),
|
||||
});
|
||||
@@ -532,12 +532,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn conclude_different_than_proposed() {
|
||||
let mut accumulator = Accumulator::<Candidate, _, _, _>::new(1, 7, ValidatorId(8));
|
||||
let mut accumulator = Accumulator::<Candidate, _, _, _>::new(1, 7, AuthorityId(8));
|
||||
assert_eq!(accumulator.state(), &State::Begin);
|
||||
|
||||
for i in 0..7 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(999, i),
|
||||
message: Message::Prepare(1, Digest(999)),
|
||||
});
|
||||
@@ -550,7 +550,7 @@ mod tests {
|
||||
|
||||
for i in 0..7 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(999, i),
|
||||
message: Message::Commit(1, Digest(999)),
|
||||
});
|
||||
@@ -564,12 +564,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn begin_to_advance() {
|
||||
let mut accumulator = Accumulator::<Candidate, Digest, _, _>::new(1, 7, ValidatorId(8));
|
||||
let mut accumulator = Accumulator::<Candidate, Digest, _, _>::new(1, 7, AuthorityId(8));
|
||||
assert_eq!(accumulator.state(), &State::Begin);
|
||||
|
||||
for i in 0..7 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(1, i),
|
||||
message: Message::AdvanceRound(1),
|
||||
});
|
||||
@@ -583,12 +583,12 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn conclude_without_prepare() {
|
||||
let mut accumulator = Accumulator::<Candidate, _, _, _>::new(1, 7, ValidatorId(8));
|
||||
let mut accumulator = Accumulator::<Candidate, _, _, _>::new(1, 7, AuthorityId(8));
|
||||
assert_eq!(accumulator.state(), &State::Begin);
|
||||
|
||||
for i in 0..7 {
|
||||
accumulator.import_message(LocalizedMessage {
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
signature: Signature(999, i),
|
||||
message: Message::Commit(1, Digest(999)),
|
||||
});
|
||||
|
||||
@@ -76,8 +76,8 @@ pub trait Context {
|
||||
type Candidate: Debug + Eq + Clone;
|
||||
/// Candidate digest.
|
||||
type Digest: Debug + Hash + Eq + Clone;
|
||||
/// Validator ID.
|
||||
type ValidatorId: Debug + Hash + Eq + Clone;
|
||||
/// Authority ID.
|
||||
type AuthorityId: Debug + Hash + Eq + Clone;
|
||||
/// Signature.
|
||||
type Signature: Debug + Eq + Clone;
|
||||
/// A future that resolves when a round timeout is concluded.
|
||||
@@ -85,8 +85,8 @@ pub trait Context {
|
||||
/// A future that resolves when a proposal is ready.
|
||||
type CreateProposal: Future<Item=Self::Candidate>;
|
||||
|
||||
/// Get the local validator ID.
|
||||
fn local_id(&self) -> Self::ValidatorId;
|
||||
/// Get the local authority ID.
|
||||
fn local_id(&self) -> Self::AuthorityId;
|
||||
|
||||
/// Get the best proposal.
|
||||
fn proposal(&self) -> Self::CreateProposal;
|
||||
@@ -94,12 +94,12 @@ pub trait Context {
|
||||
/// Get the digest of a candidate.
|
||||
fn candidate_digest(&self, candidate: &Self::Candidate) -> Self::Digest;
|
||||
|
||||
/// Sign a message using the local validator ID.
|
||||
/// Sign a message using the local authority ID.
|
||||
fn sign_local(&self, message: Message<Self::Candidate, Self::Digest>)
|
||||
-> LocalizedMessage<Self::Candidate, Self::Digest, Self::ValidatorId, Self::Signature>;
|
||||
-> LocalizedMessage<Self::Candidate, Self::Digest, Self::AuthorityId, Self::Signature>;
|
||||
|
||||
/// Get the proposer for a given round of consensus.
|
||||
fn round_proposer(&self, round: usize) -> Self::ValidatorId;
|
||||
fn round_proposer(&self, round: usize) -> Self::AuthorityId;
|
||||
|
||||
/// Whether the candidate is valid.
|
||||
fn candidate_valid(&self, candidate: &Self::Candidate) -> bool;
|
||||
@@ -121,11 +121,11 @@ pub enum Communication<C, D, V, S> {
|
||||
|
||||
/// Type alias for a localized message using only type parameters from `Context`.
|
||||
// TODO: actual type alias when it's no longer a warning.
|
||||
pub struct ContextCommunication<C: Context + ?Sized>(pub Communication<C::Candidate, C::Digest, C::ValidatorId, C::Signature>);
|
||||
pub struct ContextCommunication<C: Context + ?Sized>(pub Communication<C::Candidate, C::Digest, C::AuthorityId, C::Signature>);
|
||||
|
||||
impl<C: Context + ?Sized> Clone for ContextCommunication<C>
|
||||
where
|
||||
LocalizedMessage<C::Candidate, C::Digest, C::ValidatorId, C::Signature>: Clone,
|
||||
LocalizedMessage<C::Candidate, C::Digest, C::AuthorityId, C::Signature>: Clone,
|
||||
PrepareJustification<C::Digest, C::Signature>: Clone,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
@@ -242,7 +242,7 @@ enum LocalState {
|
||||
// - a higher threshold-prepare is broadcast to us. in this case we can
|
||||
// advance to the round of the threshold-prepare. this is an indication
|
||||
// that we have experienced severe asynchrony/clock drift with the remainder
|
||||
// of the other validators, and it is unlikely that we can assist in
|
||||
// of the other authorities, and it is unlikely that we can assist in
|
||||
// consensus meaningfully. nevertheless we make an attempt.
|
||||
struct Strategy<C: Context> {
|
||||
nodes: usize,
|
||||
@@ -252,9 +252,9 @@ struct Strategy<C: Context> {
|
||||
local_state: LocalState,
|
||||
locked: Option<Locked<C::Digest, C::Signature>>,
|
||||
notable_candidates: HashMap<C::Digest, C::Candidate>,
|
||||
current_accumulator: Accumulator<C::Candidate, C::Digest, C::ValidatorId, C::Signature>,
|
||||
future_accumulator: Accumulator<C::Candidate, C::Digest, C::ValidatorId, C::Signature>,
|
||||
local_id: C::ValidatorId,
|
||||
current_accumulator: Accumulator<C::Candidate, C::Digest, C::AuthorityId, C::Signature>,
|
||||
future_accumulator: Accumulator<C::Candidate, C::Digest, C::AuthorityId, C::Signature>,
|
||||
local_id: C::AuthorityId,
|
||||
}
|
||||
|
||||
impl<C: Context> Strategy<C> {
|
||||
@@ -290,7 +290,7 @@ impl<C: Context> Strategy<C> {
|
||||
|
||||
fn import_message(
|
||||
&mut self,
|
||||
msg: LocalizedMessage<C::Candidate, C::Digest, C::ValidatorId, C::Signature>
|
||||
msg: LocalizedMessage<C::Candidate, C::Digest, C::AuthorityId, C::Signature>
|
||||
) {
|
||||
let round_number = msg.message.round_number();
|
||||
|
||||
|
||||
@@ -34,10 +34,10 @@ struct Candidate(usize);
|
||||
struct Digest(usize);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
|
||||
struct ValidatorId(usize);
|
||||
struct AuthorityId(usize);
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||
struct Signature(Message<Candidate, Digest>, ValidatorId);
|
||||
struct Signature(Message<Candidate, Digest>, AuthorityId);
|
||||
|
||||
struct SharedContext {
|
||||
node_count: usize,
|
||||
@@ -89,13 +89,13 @@ impl SharedContext {
|
||||
self.current_round += 1;
|
||||
}
|
||||
|
||||
fn round_proposer(&self, round: usize) -> ValidatorId {
|
||||
ValidatorId(round % self.node_count)
|
||||
fn round_proposer(&self, round: usize) -> AuthorityId {
|
||||
AuthorityId(round % self.node_count)
|
||||
}
|
||||
}
|
||||
|
||||
struct TestContext {
|
||||
local_id: ValidatorId,
|
||||
local_id: AuthorityId,
|
||||
proposal: Mutex<usize>,
|
||||
shared: Arc<Mutex<SharedContext>>,
|
||||
}
|
||||
@@ -103,12 +103,12 @@ struct TestContext {
|
||||
impl Context for TestContext {
|
||||
type Candidate = Candidate;
|
||||
type Digest = Digest;
|
||||
type ValidatorId = ValidatorId;
|
||||
type AuthorityId = AuthorityId;
|
||||
type Signature = Signature;
|
||||
type RoundTimeout = Box<Future<Item=(), Error=Error>>;
|
||||
type CreateProposal = FutureResult<Candidate, Error>;
|
||||
|
||||
fn local_id(&self) -> ValidatorId {
|
||||
fn local_id(&self) -> AuthorityId {
|
||||
self.local_id.clone()
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@ impl Context for TestContext {
|
||||
}
|
||||
|
||||
fn sign_local(&self, message: Message<Candidate, Digest>)
|
||||
-> LocalizedMessage<Candidate, Digest, ValidatorId, Signature>
|
||||
-> LocalizedMessage<Candidate, Digest, AuthorityId, Signature>
|
||||
{
|
||||
let signature = Signature(message.clone(), self.local_id.clone());
|
||||
LocalizedMessage {
|
||||
@@ -138,7 +138,7 @@ impl Context for TestContext {
|
||||
}
|
||||
}
|
||||
|
||||
fn round_proposer(&self, round: usize) -> ValidatorId {
|
||||
fn round_proposer(&self, round: usize) -> AuthorityId {
|
||||
self.shared.lock().unwrap().round_proposer(round)
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ fn consensus_completes_with_minimum_good() {
|
||||
.enumerate()
|
||||
.map(|(i, (tx, rx))| {
|
||||
let ctx = TestContext {
|
||||
local_id: ValidatorId(i),
|
||||
local_id: AuthorityId(i),
|
||||
proposal: Mutex::new(i),
|
||||
shared: shared_context.clone(),
|
||||
};
|
||||
@@ -234,7 +234,7 @@ fn consensus_does_not_complete_without_enough_nodes() {
|
||||
.enumerate()
|
||||
.map(|(i, (tx, rx))| {
|
||||
let ctx = TestContext {
|
||||
local_id: ValidatorId(i),
|
||||
local_id: AuthorityId(i),
|
||||
proposal: Mutex::new(i),
|
||||
shared: shared_context.clone(),
|
||||
};
|
||||
@@ -273,7 +273,7 @@ fn threshold_plus_one_locked_on_proposal_only_one_with_candidate() {
|
||||
round_number: locked_round,
|
||||
digest: locked_digest.clone(),
|
||||
signatures: (0..7)
|
||||
.map(|i| Signature(Message::Prepare(locked_round, locked_digest.clone()), ValidatorId(i)))
|
||||
.map(|i| Signature(Message::Prepare(locked_round, locked_digest.clone()), AuthorityId(i)))
|
||||
.collect()
|
||||
}.check(7, |_, _, s| Some(s.1.clone())).unwrap();
|
||||
|
||||
@@ -290,7 +290,7 @@ fn threshold_plus_one_locked_on_proposal_only_one_with_candidate() {
|
||||
.enumerate()
|
||||
.map(|(i, (tx, rx))| {
|
||||
let ctx = TestContext {
|
||||
local_id: ValidatorId(i),
|
||||
local_id: AuthorityId(i),
|
||||
proposal: Mutex::new(i),
|
||||
shared: shared_context.clone(),
|
||||
};
|
||||
|
||||
@@ -75,7 +75,7 @@ pub struct HandleIncoming<C: Context, I> {
|
||||
table: SharedTable<C>,
|
||||
messages_in: Fuse<I>,
|
||||
bft_out: mpsc::UnboundedSender<<C as TypeResolve>::BftCommunication>,
|
||||
local_id: C::ValidatorId,
|
||||
local_id: C::AuthorityId,
|
||||
requesting_about: FuturesUnordered<Checking<
|
||||
C::Digest,
|
||||
<C::CheckAvailability as IntoFuture>::Future,
|
||||
@@ -98,7 +98,7 @@ impl<C: Context, I> HandleIncoming<C, I> {
|
||||
self.table.sign_and_import(statement);
|
||||
}
|
||||
|
||||
fn import_message(&mut self, origin: C::ValidatorId, message: CheckedMessage<C>) {
|
||||
fn import_message(&mut self, origin: C::AuthorityId, message: CheckedMessage<C>) {
|
||||
match message {
|
||||
CheckedMessage::Bft(msg) => { let _ = self.bft_out.unbounded_send(msg); }
|
||||
CheckedMessage::Table(table_messages) => {
|
||||
@@ -161,7 +161,7 @@ impl<C: Context, I> HandleIncoming<C, I> {
|
||||
impl<C, I, E> HandleIncoming<C, I>
|
||||
where
|
||||
C: Context,
|
||||
I: Stream<Item=(C::ValidatorId, CheckedMessage<C>),Error=E>,
|
||||
I: Stream<Item=(C::AuthorityId, CheckedMessage<C>),Error=E>,
|
||||
C::CheckAvailability: IntoFuture<Error=E>,
|
||||
C::CheckCandidate: IntoFuture<Error=E>,
|
||||
{
|
||||
@@ -187,7 +187,7 @@ impl<C, I, E> HandleIncoming<C, I>
|
||||
impl<C, I, E> Future for HandleIncoming<C, I>
|
||||
where
|
||||
C: Context,
|
||||
I: Stream<Item=(C::ValidatorId, CheckedMessage<C>),Error=E>,
|
||||
I: Stream<Item=(C::AuthorityId, CheckedMessage<C>),Error=E>,
|
||||
C::CheckAvailability: IntoFuture<Error=E>,
|
||||
C::CheckCandidate: IntoFuture<Error=E>,
|
||||
{
|
||||
|
||||
@@ -16,18 +16,18 @@
|
||||
|
||||
//! Propagation and agreement of candidates.
|
||||
//!
|
||||
//! Validators are split into groups by parachain, and each validator might come
|
||||
//! up its own candidate for their parachain. Within groups, validators pass around
|
||||
//! Authorities are split into groups by parachain, and each authority might come
|
||||
//! up its own candidate for their parachain. Within groups, authorities pass around
|
||||
//! their candidates and produce statements of validity.
|
||||
//!
|
||||
//! Any candidate that receives majority approval by the validators in a group
|
||||
//! may be subject to inclusion, unless any validators flag that candidate as invalid.
|
||||
//! Any candidate that receives majority approval by the authorities in a group
|
||||
//! may be subject to inclusion, unless any authorities flag that candidate as invalid.
|
||||
//!
|
||||
//! Wrongly flagging as invalid should be strongly disincentivized, so that in the
|
||||
//! equilibrium state it is not expected to happen. Likewise with the submission
|
||||
//! of invalid blocks.
|
||||
//!
|
||||
//! Groups themselves may be compromised by malicious validators.
|
||||
//! Groups themselves may be compromised by malicious authorities.
|
||||
|
||||
#[macro_use]
|
||||
extern crate futures;
|
||||
@@ -57,8 +57,8 @@ pub mod tests;
|
||||
|
||||
/// Context necessary for agreement.
|
||||
pub trait Context: Send + Clone {
|
||||
/// A validator ID
|
||||
type ValidatorId: Debug + Hash + Eq + Clone + Ord;
|
||||
/// A authority ID
|
||||
type AuthorityId: Debug + Hash + Eq + Clone + Ord;
|
||||
/// The digest (hash or other unique attribute) of a candidate.
|
||||
type Digest: Debug + Hash + Eq + Clone;
|
||||
/// The group ID type
|
||||
@@ -83,8 +83,8 @@ pub trait Context: Send + Clone {
|
||||
|
||||
/// The statement batch type.
|
||||
type StatementBatch: StatementBatch<
|
||||
Self::ValidatorId,
|
||||
table::SignedStatement<Self::ParachainCandidate, Self::Digest, Self::ValidatorId, Self::Signature>,
|
||||
Self::AuthorityId,
|
||||
table::SignedStatement<Self::ParachainCandidate, Self::Digest, Self::AuthorityId, Self::Signature>,
|
||||
>;
|
||||
|
||||
/// Get the digest of a candidate.
|
||||
@@ -97,7 +97,7 @@ pub trait Context: Send + Clone {
|
||||
fn candidate_group(candidate: &Self::ParachainCandidate) -> Self::GroupId;
|
||||
|
||||
/// Get the primary for a given round.
|
||||
fn round_proposer(&self, round: usize) -> Self::ValidatorId;
|
||||
fn round_proposer(&self, round: usize) -> Self::AuthorityId;
|
||||
|
||||
/// Check a candidate for validity.
|
||||
fn check_validity(&self, candidate: &Self::ParachainCandidate) -> Self::CheckCandidate;
|
||||
@@ -120,8 +120,8 @@ pub trait Context: Send + Clone {
|
||||
fn proposal_valid<F>(&self, proposal: &Self::Proposal, check_candidate: F) -> bool
|
||||
where F: FnMut(&Self::ParachainCandidate) -> bool;
|
||||
|
||||
/// Get the local validator ID.
|
||||
fn local_id(&self) -> Self::ValidatorId;
|
||||
/// Get the local authority ID.
|
||||
fn local_id(&self) -> Self::AuthorityId;
|
||||
|
||||
/// Sign a table validity statement with the local key.
|
||||
fn sign_table_statement(
|
||||
@@ -142,18 +142,18 @@ pub trait TypeResolve {
|
||||
}
|
||||
|
||||
impl<C: Context> TypeResolve for C {
|
||||
type SignedTableStatement = table::SignedStatement<C::ParachainCandidate, C::Digest, C::ValidatorId, C::Signature>;
|
||||
type BftCommunication = bft::Communication<C::Proposal, C::Digest, C::ValidatorId, C::Signature>;
|
||||
type SignedTableStatement = table::SignedStatement<C::ParachainCandidate, C::Digest, C::AuthorityId, C::Signature>;
|
||||
type BftCommunication = bft::Communication<C::Proposal, C::Digest, C::AuthorityId, C::Signature>;
|
||||
type BftCommitted = bft::Committed<C::Proposal,C::Digest,C::Signature>;
|
||||
type Misbehavior = table::Misbehavior<C::ParachainCandidate, C::Digest, C::ValidatorId, C::Signature>;
|
||||
type Misbehavior = table::Misbehavior<C::ParachainCandidate, C::Digest, C::AuthorityId, C::Signature>;
|
||||
}
|
||||
|
||||
/// Information about a specific group.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct GroupInfo<V: Hash + Eq> {
|
||||
/// Validators meant to check validity of candidates.
|
||||
/// Authorities meant to check validity of candidates.
|
||||
pub validity_guarantors: HashSet<V>,
|
||||
/// Validators meant to check availability of candidate data.
|
||||
/// Authorities meant to check availability of candidate data.
|
||||
pub availability_guarantors: HashSet<V>,
|
||||
/// Number of votes needed for validity.
|
||||
pub needed_validity: usize,
|
||||
@@ -163,7 +163,7 @@ pub struct GroupInfo<V: Hash + Eq> {
|
||||
|
||||
struct TableContext<C: Context> {
|
||||
context: C,
|
||||
groups: HashMap<C::GroupId, GroupInfo<C::ValidatorId>>,
|
||||
groups: HashMap<C::GroupId, GroupInfo<C::AuthorityId>>,
|
||||
}
|
||||
|
||||
impl<C: Context> ::std::ops::Deref for TableContext<C> {
|
||||
@@ -175,7 +175,7 @@ impl<C: Context> ::std::ops::Deref for TableContext<C> {
|
||||
}
|
||||
|
||||
impl<C: Context> table::Context for TableContext<C> {
|
||||
type ValidatorId = C::ValidatorId;
|
||||
type AuthorityId = C::AuthorityId;
|
||||
type Digest = C::Digest;
|
||||
type GroupId = C::GroupId;
|
||||
type Signature = C::Signature;
|
||||
@@ -189,12 +189,12 @@ impl<C: Context> table::Context for TableContext<C> {
|
||||
C::candidate_group(candidate)
|
||||
}
|
||||
|
||||
fn is_member_of(&self, validator: &Self::ValidatorId, group: &Self::GroupId) -> bool {
|
||||
self.groups.get(group).map_or(false, |g| g.validity_guarantors.contains(validator))
|
||||
fn is_member_of(&self, authority: &Self::AuthorityId, group: &Self::GroupId) -> bool {
|
||||
self.groups.get(group).map_or(false, |g| g.validity_guarantors.contains(authority))
|
||||
}
|
||||
|
||||
fn is_availability_guarantor_of(&self, validator: &Self::ValidatorId, group: &Self::GroupId) -> bool {
|
||||
self.groups.get(group).map_or(false, |g| g.availability_guarantors.contains(validator))
|
||||
fn is_availability_guarantor_of(&self, authority: &Self::AuthorityId, group: &Self::GroupId) -> bool {
|
||||
self.groups.get(group).map_or(false, |g| g.availability_guarantors.contains(authority))
|
||||
}
|
||||
|
||||
fn requisite_votes(&self, group: &Self::GroupId) -> (usize, usize) {
|
||||
@@ -217,7 +217,7 @@ impl<C: Context> SharedTableInner<C> {
|
||||
&mut self,
|
||||
context: &TableContext<C>,
|
||||
statement: <C as TypeResolve>::SignedTableStatement,
|
||||
received_from: Option<C::ValidatorId>
|
||||
received_from: Option<C::AuthorityId>
|
||||
) -> Option<table::Summary<C::Digest, C::GroupId>> {
|
||||
self.table.import_statement(context, statement, received_from)
|
||||
}
|
||||
@@ -265,7 +265,7 @@ impl<C: Context> Clone for SharedTable<C> {
|
||||
|
||||
impl<C: Context> SharedTable<C> {
|
||||
/// Create a new shared table.
|
||||
pub fn new(context: C, groups: HashMap<C::GroupId, GroupInfo<C::ValidatorId>>) -> Self {
|
||||
pub fn new(context: C, groups: HashMap<C::GroupId, GroupInfo<C::AuthorityId>>) -> Self {
|
||||
SharedTable {
|
||||
context: Arc::new(TableContext { context, groups }),
|
||||
inner: Arc::new(Mutex::new(SharedTableInner {
|
||||
@@ -280,7 +280,7 @@ impl<C: Context> SharedTable<C> {
|
||||
pub fn import_statement(
|
||||
&self,
|
||||
statement: <C as TypeResolve>::SignedTableStatement,
|
||||
received_from: Option<C::ValidatorId>,
|
||||
received_from: Option<C::AuthorityId>,
|
||||
) -> Option<table::Summary<C::Digest, C::GroupId>> {
|
||||
self.inner.lock().import_statement(&*self.context, statement, received_from)
|
||||
}
|
||||
@@ -314,7 +314,7 @@ impl<C: Context> SharedTable<C> {
|
||||
/// Provide an iterator yielding pairs of (statement, received_from).
|
||||
pub fn import_statements<I, U>(&self, iterable: I) -> U
|
||||
where
|
||||
I: IntoIterator<Item=(<C as TypeResolve>::SignedTableStatement, Option<C::ValidatorId>)>,
|
||||
I: IntoIterator<Item=(<C as TypeResolve>::SignedTableStatement, Option<C::AuthorityId>)>,
|
||||
U: ::std::iter::FromIterator<table::Summary<C::Digest, C::GroupId>>,
|
||||
{
|
||||
let mut inner = self.inner.lock();
|
||||
@@ -351,7 +351,7 @@ impl<C: Context> SharedTable<C> {
|
||||
}
|
||||
|
||||
/// Get all witnessed misbehavior.
|
||||
pub fn get_misbehavior(&self) -> HashMap<C::ValidatorId, <C as TypeResolve>::Misbehavior> {
|
||||
pub fn get_misbehavior(&self) -> HashMap<C::AuthorityId, <C as TypeResolve>::Misbehavior> {
|
||||
self.inner.lock().table.get_misbehavior().clone()
|
||||
}
|
||||
|
||||
@@ -396,14 +396,14 @@ pub struct BftContext<C: Context> {
|
||||
impl<C: Context> bft::Context for BftContext<C>
|
||||
where C::Proposal: 'static,
|
||||
{
|
||||
type ValidatorId = C::ValidatorId;
|
||||
type AuthorityId = C::AuthorityId;
|
||||
type Digest = C::Digest;
|
||||
type Signature = C::Signature;
|
||||
type Candidate = C::Proposal;
|
||||
type RoundTimeout = Box<Future<Item=(),Error=Error>>;
|
||||
type CreateProposal = Box<Future<Item=Self::Candidate,Error=Error>>;
|
||||
|
||||
fn local_id(&self) -> Self::ValidatorId {
|
||||
fn local_id(&self) -> Self::AuthorityId {
|
||||
self.context.local_id()
|
||||
}
|
||||
|
||||
@@ -416,7 +416,7 @@ impl<C: Context> bft::Context for BftContext<C>
|
||||
}
|
||||
|
||||
fn sign_local(&self, message: bft::Message<Self::Candidate, Self::Digest>)
|
||||
-> bft::LocalizedMessage<Self::Candidate, Self::Digest, Self::ValidatorId, Self::Signature>
|
||||
-> bft::LocalizedMessage<Self::Candidate, Self::Digest, Self::AuthorityId, Self::Signature>
|
||||
{
|
||||
let sender = self.local_id();
|
||||
let signature = self.context.sign_bft_message(&message);
|
||||
@@ -427,7 +427,7 @@ impl<C: Context> bft::Context for BftContext<C>
|
||||
}
|
||||
}
|
||||
|
||||
fn round_proposer(&self, round: usize) -> Self::ValidatorId {
|
||||
fn round_proposer(&self, round: usize) -> Self::AuthorityId {
|
||||
self.context.round_proposer(round)
|
||||
}
|
||||
|
||||
@@ -533,7 +533,7 @@ pub fn agree<
|
||||
Context: ::Context + 'static,
|
||||
Context::CheckCandidate: IntoFuture<Error=Err>,
|
||||
Context::CheckAvailability: IntoFuture<Error=Err>,
|
||||
NetIn: Stream<Item=(Context::ValidatorId, Vec<Recovery::UncheckedMessage>),Error=Err> + 'static,
|
||||
NetIn: Stream<Item=(Context::AuthorityId, Vec<Recovery::UncheckedMessage>),Error=Err> + 'static,
|
||||
NetOut: Sink<SinkItem=OutgoingMessage<Context>> + 'static,
|
||||
Recovery: MessageRecovery<Context> + 'static,
|
||||
PropagateStatements: Stream<Item=Context::StatementBatch,Error=Err> + 'static,
|
||||
|
||||
@@ -16,14 +16,14 @@
|
||||
|
||||
//! The statement table.
|
||||
//!
|
||||
//! This stores messages other validators issue about candidates.
|
||||
//! This stores messages other authorities issue about candidates.
|
||||
//!
|
||||
//! These messages are used to create a proposal submitted to a BFT consensus process.
|
||||
//!
|
||||
//! Proposals are formed of sets of candidates which have the requisite number of
|
||||
//! validity and availability votes.
|
||||
//!
|
||||
//! Each parachain is associated with two sets of validators: those which can
|
||||
//! Each parachain is associated with two sets of authorities: those which can
|
||||
//! propose and attest to validity of candidates, and those who can only attest
|
||||
//! to availability.
|
||||
|
||||
@@ -36,8 +36,8 @@ use super::StatementBatch;
|
||||
|
||||
/// Context for the statement table.
|
||||
pub trait Context {
|
||||
/// A validator ID
|
||||
type ValidatorId: Debug + Hash + Eq + Clone;
|
||||
/// A authority ID
|
||||
type AuthorityId: Debug + Hash + Eq + Clone;
|
||||
/// The digest (hash or other unique attribute) of a candidate.
|
||||
type Digest: Debug + Hash + Eq + Clone;
|
||||
/// The group ID type
|
||||
@@ -53,16 +53,16 @@ pub trait Context {
|
||||
/// get the group of a candidate.
|
||||
fn candidate_group(candidate: &Self::Candidate) -> Self::GroupId;
|
||||
|
||||
/// Whether a validator is a member of a group.
|
||||
/// Whether a authority is a member of a group.
|
||||
/// Members are meant to submit candidates and vote on validity.
|
||||
fn is_member_of(&self, validator: &Self::ValidatorId, group: &Self::GroupId) -> bool;
|
||||
fn is_member_of(&self, authority: &Self::AuthorityId, group: &Self::GroupId) -> bool;
|
||||
|
||||
/// Whether a validator is an availability guarantor of a group.
|
||||
/// Whether a authority is an availability guarantor of a group.
|
||||
/// Guarantors are meant to vote on availability for candidates submitted
|
||||
/// in a group.
|
||||
fn is_availability_guarantor_of(
|
||||
&self,
|
||||
validator: &Self::ValidatorId,
|
||||
authority: &Self::AuthorityId,
|
||||
group: &Self::GroupId,
|
||||
) -> bool;
|
||||
|
||||
@@ -73,18 +73,18 @@ pub trait Context {
|
||||
/// Statements circulated among peers.
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
pub enum Statement<C, D> {
|
||||
/// Broadcast by a validator to indicate that this is his candidate for
|
||||
/// Broadcast by a authority to indicate that this is his candidate for
|
||||
/// inclusion.
|
||||
///
|
||||
/// Broadcasting two different candidate messages per round is not allowed.
|
||||
Candidate(C),
|
||||
/// Broadcast by a validator to attest that the candidate with given digest
|
||||
/// Broadcast by a authority to attest that the candidate with given digest
|
||||
/// is valid.
|
||||
Valid(D),
|
||||
/// Broadcast by a validator to attest that the auxiliary data for a candidate
|
||||
/// Broadcast by a authority to attest that the auxiliary data for a candidate
|
||||
/// with given digest is available.
|
||||
Available(D),
|
||||
/// Broadcast by a validator to attest that the candidate with given digest
|
||||
/// Broadcast by a authority to attest that the candidate with given digest
|
||||
/// is invalid.
|
||||
Invalid(D),
|
||||
}
|
||||
@@ -100,23 +100,23 @@ pub struct SignedStatement<C, D, V, S> {
|
||||
pub sender: V,
|
||||
}
|
||||
|
||||
// A unique trace for a class of valid statements issued by a validator.
|
||||
// A unique trace for a class of valid statements issued by a authority.
|
||||
//
|
||||
// We keep track of which statements we have received or sent to other validators
|
||||
// We keep track of which statements we have received or sent to other authorities
|
||||
// in order to prevent relaying the same data multiple times.
|
||||
//
|
||||
// The signature of the statement is replaced by the validator because the validator
|
||||
// The signature of the statement is replaced by the authority because the authority
|
||||
// is unique while signatures are not (at least under common schemes like
|
||||
// Schnorr or ECDSA).
|
||||
#[derive(Hash, PartialEq, Eq, Clone)]
|
||||
enum StatementTrace<V, D> {
|
||||
/// The candidate proposed by the validator.
|
||||
/// The candidate proposed by the authority.
|
||||
Candidate(V),
|
||||
/// A validity statement from that validator about the given digest.
|
||||
/// A validity statement from that authority about the given digest.
|
||||
Valid(V, D),
|
||||
/// An invalidity statement from that validator about the given digest.
|
||||
/// An invalidity statement from that authority about the given digest.
|
||||
Invalid(V, D),
|
||||
/// An availability statement from that validator about the given digest.
|
||||
/// An availability statement from that authority about the given digest.
|
||||
Available(V, D),
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ pub trait ResolveMisbehavior {
|
||||
}
|
||||
|
||||
impl<C: Context + ?Sized> ResolveMisbehavior for C {
|
||||
type Misbehavior = Misbehavior<C::Candidate, C::Digest, C::ValidatorId, C::Signature>;
|
||||
type Misbehavior = Misbehavior<C::Candidate, C::Digest, C::AuthorityId, C::Signature>;
|
||||
}
|
||||
|
||||
// kinds of votes for validity
|
||||
@@ -203,9 +203,9 @@ pub struct Summary<D, G> {
|
||||
pub struct CandidateData<C: Context> {
|
||||
group_id: C::GroupId,
|
||||
candidate: C::Candidate,
|
||||
validity_votes: HashMap<C::ValidatorId, ValidityVote<C::Signature>>,
|
||||
availability_votes: HashMap<C::ValidatorId, C::Signature>,
|
||||
indicated_bad_by: Vec<C::ValidatorId>,
|
||||
validity_votes: HashMap<C::AuthorityId, ValidityVote<C::Signature>>,
|
||||
availability_votes: HashMap<C::AuthorityId, C::Signature>,
|
||||
indicated_bad_by: Vec<C::AuthorityId>,
|
||||
}
|
||||
|
||||
impl<C: Context> CandidateData<C> {
|
||||
@@ -216,7 +216,7 @@ impl<C: Context> CandidateData<C> {
|
||||
|
||||
// Candidate data can be included in a proposal
|
||||
// if it has enough validity and availability votes
|
||||
// and no validators have called it bad.
|
||||
// and no authorities have called it bad.
|
||||
fn can_be_included(&self, validity_threshold: usize, availability_threshold: usize) -> bool {
|
||||
self.indicated_bad_by.is_empty()
|
||||
&& self.validity_votes.len() >= validity_threshold
|
||||
@@ -234,15 +234,15 @@ impl<C: Context> CandidateData<C> {
|
||||
}
|
||||
}
|
||||
|
||||
// validator metadata
|
||||
struct ValidatorData<C: Context> {
|
||||
// authority metadata
|
||||
struct AuthorityData<C: Context> {
|
||||
proposal: Option<(C::Digest, C::Signature)>,
|
||||
known_statements: HashSet<StatementTrace<C::ValidatorId, C::Digest>>,
|
||||
known_statements: HashSet<StatementTrace<C::AuthorityId, C::Digest>>,
|
||||
}
|
||||
|
||||
impl<C: Context> Default for ValidatorData<C> {
|
||||
impl<C: Context> Default for AuthorityData<C> {
|
||||
fn default() -> Self {
|
||||
ValidatorData {
|
||||
AuthorityData {
|
||||
proposal: None,
|
||||
known_statements: HashSet::default(),
|
||||
}
|
||||
@@ -251,15 +251,15 @@ impl<C: Context> Default for ValidatorData<C> {
|
||||
|
||||
/// Stores votes
|
||||
pub struct Table<C: Context> {
|
||||
validator_data: HashMap<C::ValidatorId, ValidatorData<C>>,
|
||||
detected_misbehavior: HashMap<C::ValidatorId, <C as ResolveMisbehavior>::Misbehavior>,
|
||||
authority_data: HashMap<C::AuthorityId, AuthorityData<C>>,
|
||||
detected_misbehavior: HashMap<C::AuthorityId, <C as ResolveMisbehavior>::Misbehavior>,
|
||||
candidate_votes: HashMap<C::Digest, CandidateData<C>>,
|
||||
}
|
||||
|
||||
impl<C: Context> Default for Table<C> {
|
||||
fn default() -> Self {
|
||||
Table {
|
||||
validator_data: HashMap::new(),
|
||||
authority_data: HashMap::new(),
|
||||
detected_misbehavior: HashMap::new(),
|
||||
candidate_votes: HashMap::new(),
|
||||
}
|
||||
@@ -307,15 +307,15 @@ impl<C: Context> Table<C> {
|
||||
}
|
||||
|
||||
/// Import a signed statement. Signatures should be checked for validity, and the
|
||||
/// sender should be checked to actually be a validator.
|
||||
/// sender should be checked to actually be a authority.
|
||||
///
|
||||
/// This can note the origin of the statement to indicate that he has
|
||||
/// seen it already.
|
||||
pub fn import_statement(
|
||||
&mut self,
|
||||
context: &C,
|
||||
statement: SignedStatement<C::Candidate, C::Digest, C::ValidatorId, C::Signature>,
|
||||
from: Option<C::ValidatorId>
|
||||
statement: SignedStatement<C::Candidate, C::Digest, C::AuthorityId, C::Signature>,
|
||||
from: Option<C::AuthorityId>
|
||||
) -> Option<Summary<C::Digest, C::GroupId>> {
|
||||
let SignedStatement { statement, signature, sender: signer } = statement;
|
||||
|
||||
@@ -375,7 +375,7 @@ impl<C: Context> Table<C> {
|
||||
|
||||
/// Access all witnessed misbehavior.
|
||||
pub fn get_misbehavior(&self)
|
||||
-> &HashMap<C::ValidatorId, <C as ResolveMisbehavior>::Misbehavior>
|
||||
-> &HashMap<C::AuthorityId, <C as ResolveMisbehavior>::Misbehavior>
|
||||
{
|
||||
&self.detected_misbehavior
|
||||
}
|
||||
@@ -383,8 +383,8 @@ impl<C: Context> Table<C> {
|
||||
/// Fill a statement batch and note messages seen by the targets.
|
||||
pub fn fill_batch<B>(&mut self, batch: &mut B)
|
||||
where B: StatementBatch<
|
||||
C::ValidatorId,
|
||||
SignedStatement<C::Candidate, C::Digest, C::ValidatorId, C::Signature>,
|
||||
C::AuthorityId,
|
||||
SignedStatement<C::Candidate, C::Digest, C::AuthorityId, C::Signature>,
|
||||
>
|
||||
{
|
||||
// naively iterate all statements so far, taking any that
|
||||
@@ -394,24 +394,24 @@ impl<C: Context> Table<C> {
|
||||
// entries out of a hashmap mutably -- we just move them out and
|
||||
// replace them when we're done.
|
||||
struct SwappedTargetData<'a, C: 'a + Context> {
|
||||
validator_data: &'a mut HashMap<C::ValidatorId, ValidatorData<C>>,
|
||||
target_data: Vec<(C::ValidatorId, ValidatorData<C>)>,
|
||||
authority_data: &'a mut HashMap<C::AuthorityId, AuthorityData<C>>,
|
||||
target_data: Vec<(C::AuthorityId, AuthorityData<C>)>,
|
||||
}
|
||||
|
||||
impl<'a, C: 'a + Context> Drop for SwappedTargetData<'a, C> {
|
||||
fn drop(&mut self) {
|
||||
for (id, data) in self.target_data.drain(..) {
|
||||
self.validator_data.insert(id, data);
|
||||
self.authority_data.insert(id, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// pre-fetch authority data for all the targets.
|
||||
let mut target_data = {
|
||||
let validator_data = &mut self.validator_data;
|
||||
let authority_data = &mut self.authority_data;
|
||||
let mut target_data = Vec::with_capacity(batch.targets().len());
|
||||
for target in batch.targets() {
|
||||
let active_data = match validator_data.get_mut(target) {
|
||||
let active_data = match authority_data.get_mut(target) {
|
||||
None => Default::default(),
|
||||
Some(x) => ::std::mem::replace(x, Default::default()),
|
||||
};
|
||||
@@ -420,7 +420,7 @@ impl<C: Context> Table<C> {
|
||||
}
|
||||
|
||||
SwappedTargetData {
|
||||
validator_data,
|
||||
authority_data,
|
||||
target_data
|
||||
}
|
||||
};
|
||||
@@ -503,8 +503,8 @@ impl<C: Context> Table<C> {
|
||||
|
||||
}
|
||||
|
||||
fn note_trace_seen(&mut self, trace: StatementTrace<C::ValidatorId, C::Digest>, known_by: C::ValidatorId) {
|
||||
self.validator_data.entry(known_by).or_insert_with(|| ValidatorData {
|
||||
fn note_trace_seen(&mut self, trace: StatementTrace<C::AuthorityId, C::Digest>, known_by: C::AuthorityId) {
|
||||
self.authority_data.entry(known_by).or_insert_with(|| AuthorityData {
|
||||
proposal: None,
|
||||
known_statements: HashSet::default(),
|
||||
}).known_statements.insert(trace);
|
||||
@@ -513,7 +513,7 @@ impl<C: Context> Table<C> {
|
||||
fn import_candidate(
|
||||
&mut self,
|
||||
context: &C,
|
||||
from: C::ValidatorId,
|
||||
from: C::AuthorityId,
|
||||
candidate: C::Candidate,
|
||||
signature: C::Signature,
|
||||
) -> (Option<<C as ResolveMisbehavior>::Misbehavior>, Option<Summary<C::Digest, C::GroupId>>) {
|
||||
@@ -531,10 +531,10 @@ impl<C: Context> Table<C> {
|
||||
);
|
||||
}
|
||||
|
||||
// check that validator hasn't already specified another candidate.
|
||||
// check that authority hasn't already specified another candidate.
|
||||
let digest = C::candidate_digest(&candidate);
|
||||
|
||||
let new_proposal = match self.validator_data.entry(from.clone()) {
|
||||
let new_proposal = match self.authority_data.entry(from.clone()) {
|
||||
Entry::Occupied(mut occ) => {
|
||||
// if digest is different, fetch candidate and
|
||||
// note misbehavior.
|
||||
@@ -543,7 +543,7 @@ impl<C: Context> Table<C> {
|
||||
if let Some((ref old_digest, ref old_sig)) = existing.proposal {
|
||||
if old_digest != &digest {
|
||||
const EXISTENCE_PROOF: &str =
|
||||
"when proposal first received from validator, candidate \
|
||||
"when proposal first received from authority, candidate \
|
||||
votes entry is created. proposal here is `Some`, therefore \
|
||||
candidate votes entry exists; qed";
|
||||
|
||||
@@ -568,7 +568,7 @@ impl<C: Context> Table<C> {
|
||||
}
|
||||
}
|
||||
Entry::Vacant(vacant) => {
|
||||
vacant.insert(ValidatorData {
|
||||
vacant.insert(AuthorityData {
|
||||
proposal: Some((digest.clone(), signature.clone())),
|
||||
known_statements: HashSet::new(),
|
||||
});
|
||||
@@ -599,7 +599,7 @@ impl<C: Context> Table<C> {
|
||||
fn validity_vote(
|
||||
&mut self,
|
||||
context: &C,
|
||||
from: C::ValidatorId,
|
||||
from: C::AuthorityId,
|
||||
digest: C::Digest,
|
||||
vote: ValidityVote<C::Signature>,
|
||||
) -> (Option<<C as ResolveMisbehavior>::Misbehavior>, Option<Summary<C::Digest, C::GroupId>>) {
|
||||
@@ -608,7 +608,7 @@ impl<C: Context> Table<C> {
|
||||
Some(votes) => votes,
|
||||
};
|
||||
|
||||
// check that this validator actually can vote in this group.
|
||||
// check that this authority actually can vote in this group.
|
||||
if !context.is_member_of(&from, &votes.group_id) {
|
||||
let (sig, valid) = match vote {
|
||||
ValidityVote::Valid(s) => (s, true),
|
||||
@@ -678,7 +678,7 @@ impl<C: Context> Table<C> {
|
||||
fn availability_vote(
|
||||
&mut self,
|
||||
context: &C,
|
||||
from: C::ValidatorId,
|
||||
from: C::AuthorityId,
|
||||
digest: C::Digest,
|
||||
signature: C::Signature,
|
||||
) -> (Option<<C as ResolveMisbehavior>::Misbehavior>, Option<Summary<C::Digest, C::GroupId>>) {
|
||||
@@ -687,7 +687,7 @@ impl<C: Context> Table<C> {
|
||||
Some(votes) => votes,
|
||||
};
|
||||
|
||||
// check that this validator actually can vote in this group.
|
||||
// check that this authority actually can vote in this group.
|
||||
if !context.is_availability_guarantor_of(&from, &votes.group_id) {
|
||||
return (
|
||||
Some(Misbehavior::UnauthorizedStatement(UnauthorizedStatement {
|
||||
@@ -714,14 +714,14 @@ mod tests {
|
||||
|
||||
fn create<C: Context>() -> Table<C> {
|
||||
Table {
|
||||
validator_data: HashMap::default(),
|
||||
authority_data: HashMap::default(),
|
||||
detected_misbehavior: HashMap::default(),
|
||||
candidate_votes: HashMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
|
||||
struct ValidatorId(usize);
|
||||
struct AuthorityId(usize);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
|
||||
struct GroupId(usize);
|
||||
@@ -739,11 +739,11 @@ mod tests {
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct TestContext {
|
||||
// v -> (validity, availability)
|
||||
validators: HashMap<ValidatorId, (GroupId, GroupId)>
|
||||
authorities: HashMap<AuthorityId, (GroupId, GroupId)>
|
||||
}
|
||||
|
||||
impl Context for TestContext {
|
||||
type ValidatorId = ValidatorId;
|
||||
type AuthorityId = AuthorityId;
|
||||
type Digest = Digest;
|
||||
type Candidate = Candidate;
|
||||
type GroupId = GroupId;
|
||||
@@ -759,18 +759,18 @@ mod tests {
|
||||
|
||||
fn is_member_of(
|
||||
&self,
|
||||
validator: &ValidatorId,
|
||||
authority: &AuthorityId,
|
||||
group: &GroupId
|
||||
) -> bool {
|
||||
self.validators.get(validator).map(|v| &v.0 == group).unwrap_or(false)
|
||||
self.authorities.get(authority).map(|v| &v.0 == group).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn is_availability_guarantor_of(
|
||||
&self,
|
||||
validator: &ValidatorId,
|
||||
authority: &AuthorityId,
|
||||
group: &GroupId
|
||||
) -> bool {
|
||||
self.validators.get(validator).map(|v| &v.1 == group).unwrap_or(false)
|
||||
self.authorities.get(authority).map(|v| &v.1 == group).unwrap_or(false)
|
||||
}
|
||||
|
||||
fn requisite_votes(&self, _id: &GroupId) -> (usize, usize) {
|
||||
@@ -781,9 +781,9 @@ mod tests {
|
||||
#[test]
|
||||
fn submitting_two_candidates_is_misbehavior() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(ValidatorId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(AuthorityId(1), (GroupId(2), GroupId(455)));
|
||||
map
|
||||
}
|
||||
};
|
||||
@@ -792,21 +792,21 @@ mod tests {
|
||||
let statement_a = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
|
||||
let statement_b = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 999)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
|
||||
table.import_statement(&context, statement_a, None);
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(1)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1)));
|
||||
|
||||
table.import_statement(&context, statement_b, None);
|
||||
assert_eq!(
|
||||
table.detected_misbehavior.get(&ValidatorId(1)).unwrap(),
|
||||
table.detected_misbehavior.get(&AuthorityId(1)).unwrap(),
|
||||
&Misbehavior::MultipleCandidates(MultipleCandidates {
|
||||
first: (Candidate(2, 100), Signature(1)),
|
||||
second: (Candidate(2, 999), Signature(1)),
|
||||
@@ -817,9 +817,9 @@ mod tests {
|
||||
#[test]
|
||||
fn submitting_candidate_from_wrong_group_is_misbehavior() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(ValidatorId(1), (GroupId(3), GroupId(455)));
|
||||
map.insert(AuthorityId(1), (GroupId(3), GroupId(455)));
|
||||
map
|
||||
}
|
||||
};
|
||||
@@ -828,18 +828,18 @@ mod tests {
|
||||
let statement = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
|
||||
table.import_statement(&context, statement, None);
|
||||
|
||||
assert_eq!(
|
||||
table.detected_misbehavior.get(&ValidatorId(1)).unwrap(),
|
||||
table.detected_misbehavior.get(&AuthorityId(1)).unwrap(),
|
||||
&Misbehavior::UnauthorizedStatement(UnauthorizedStatement {
|
||||
statement: SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -848,10 +848,10 @@ mod tests {
|
||||
#[test]
|
||||
fn unauthorized_votes() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(ValidatorId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(ValidatorId(2), (GroupId(3), GroupId(222)));
|
||||
map.insert(AuthorityId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(AuthorityId(2), (GroupId(3), GroupId(222)));
|
||||
map
|
||||
}
|
||||
};
|
||||
@@ -861,56 +861,56 @@ mod tests {
|
||||
let candidate_a = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
let candidate_a_digest = Digest(100);
|
||||
|
||||
let candidate_b = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(3, 987)),
|
||||
signature: Signature(2),
|
||||
sender: ValidatorId(2),
|
||||
sender: AuthorityId(2),
|
||||
};
|
||||
let candidate_b_digest = Digest(987);
|
||||
|
||||
table.import_statement(&context, candidate_a, None);
|
||||
table.import_statement(&context, candidate_b, None);
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(1)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(2)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2)));
|
||||
|
||||
// validator 1 votes for availability on 2's candidate.
|
||||
// authority 1 votes for availability on 2's candidate.
|
||||
let bad_availability_vote = SignedStatement {
|
||||
statement: Statement::Available(candidate_b_digest.clone()),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
table.import_statement(&context, bad_availability_vote, None);
|
||||
|
||||
assert_eq!(
|
||||
table.detected_misbehavior.get(&ValidatorId(1)).unwrap(),
|
||||
table.detected_misbehavior.get(&AuthorityId(1)).unwrap(),
|
||||
&Misbehavior::UnauthorizedStatement(UnauthorizedStatement {
|
||||
statement: SignedStatement {
|
||||
statement: Statement::Available(candidate_b_digest),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
// validator 2 votes for validity on 1's candidate.
|
||||
// authority 2 votes for validity on 1's candidate.
|
||||
let bad_validity_vote = SignedStatement {
|
||||
statement: Statement::Valid(candidate_a_digest.clone()),
|
||||
signature: Signature(2),
|
||||
sender: ValidatorId(2),
|
||||
sender: AuthorityId(2),
|
||||
};
|
||||
table.import_statement(&context, bad_validity_vote, None);
|
||||
|
||||
assert_eq!(
|
||||
table.detected_misbehavior.get(&ValidatorId(2)).unwrap(),
|
||||
table.detected_misbehavior.get(&AuthorityId(2)).unwrap(),
|
||||
&Misbehavior::UnauthorizedStatement(UnauthorizedStatement {
|
||||
statement: SignedStatement {
|
||||
statement: Statement::Valid(candidate_a_digest),
|
||||
signature: Signature(2),
|
||||
sender: ValidatorId(2),
|
||||
sender: AuthorityId(2),
|
||||
},
|
||||
})
|
||||
);
|
||||
@@ -919,10 +919,10 @@ mod tests {
|
||||
#[test]
|
||||
fn validity_double_vote_is_misbehavior() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(ValidatorId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(ValidatorId(2), (GroupId(2), GroupId(246)));
|
||||
map.insert(AuthorityId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(AuthorityId(2), (GroupId(2), GroupId(246)));
|
||||
map
|
||||
}
|
||||
};
|
||||
@@ -931,32 +931,32 @@ mod tests {
|
||||
let statement = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
let candidate_digest = Digest(100);
|
||||
|
||||
table.import_statement(&context, statement, None);
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(1)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1)));
|
||||
|
||||
let valid_statement = SignedStatement {
|
||||
statement: Statement::Valid(candidate_digest.clone()),
|
||||
signature: Signature(2),
|
||||
sender: ValidatorId(2),
|
||||
sender: AuthorityId(2),
|
||||
};
|
||||
|
||||
let invalid_statement = SignedStatement {
|
||||
statement: Statement::Invalid(candidate_digest.clone()),
|
||||
signature: Signature(2),
|
||||
sender: ValidatorId(2),
|
||||
sender: AuthorityId(2),
|
||||
};
|
||||
|
||||
table.import_statement(&context, valid_statement, None);
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(2)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2)));
|
||||
|
||||
table.import_statement(&context, invalid_statement, None);
|
||||
|
||||
assert_eq!(
|
||||
table.detected_misbehavior.get(&ValidatorId(2)).unwrap(),
|
||||
table.detected_misbehavior.get(&AuthorityId(2)).unwrap(),
|
||||
&Misbehavior::ValidityDoubleVote(ValidityDoubleVote::ValidityAndInvalidity(
|
||||
candidate_digest,
|
||||
Signature(2),
|
||||
@@ -968,9 +968,9 @@ mod tests {
|
||||
#[test]
|
||||
fn issue_and_vote_is_misbehavior() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(ValidatorId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(AuthorityId(1), (GroupId(2), GroupId(455)));
|
||||
map
|
||||
}
|
||||
};
|
||||
@@ -979,22 +979,22 @@ mod tests {
|
||||
let statement = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
let candidate_digest = Digest(100);
|
||||
|
||||
table.import_statement(&context, statement, None);
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(1)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1)));
|
||||
|
||||
let extra_vote = SignedStatement {
|
||||
statement: Statement::Valid(candidate_digest.clone()),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
|
||||
table.import_statement(&context, extra_vote, None);
|
||||
assert_eq!(
|
||||
table.detected_misbehavior.get(&ValidatorId(1)).unwrap(),
|
||||
table.detected_misbehavior.get(&AuthorityId(1)).unwrap(),
|
||||
&Misbehavior::ValidityDoubleVote(ValidityDoubleVote::IssuedAndValidity(
|
||||
(Candidate(2, 100), Signature(1)),
|
||||
(Digest(100), Signature(1)),
|
||||
@@ -1018,18 +1018,18 @@ mod tests {
|
||||
assert!(!candidate.can_be_included(validity_threshold, availability_threshold));
|
||||
|
||||
for i in 0..validity_threshold {
|
||||
candidate.validity_votes.insert(ValidatorId(i + 100), ValidityVote::Valid(Signature(i + 100)));
|
||||
candidate.validity_votes.insert(AuthorityId(i + 100), ValidityVote::Valid(Signature(i + 100)));
|
||||
}
|
||||
|
||||
assert!(!candidate.can_be_included(validity_threshold, availability_threshold));
|
||||
|
||||
for i in 0..availability_threshold {
|
||||
candidate.availability_votes.insert(ValidatorId(i + 255), Signature(i + 255));
|
||||
candidate.availability_votes.insert(AuthorityId(i + 255), Signature(i + 255));
|
||||
}
|
||||
|
||||
assert!(candidate.can_be_included(validity_threshold, availability_threshold));
|
||||
|
||||
candidate.indicated_bad_by.push(ValidatorId(1024));
|
||||
candidate.indicated_bad_by.push(AuthorityId(1024));
|
||||
|
||||
assert!(!candidate.can_be_included(validity_threshold, availability_threshold));
|
||||
}
|
||||
@@ -1037,9 +1037,9 @@ mod tests {
|
||||
#[test]
|
||||
fn candidate_import_gives_summary() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(ValidatorId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(AuthorityId(1), (GroupId(2), GroupId(455)));
|
||||
map
|
||||
}
|
||||
};
|
||||
@@ -1048,7 +1048,7 @@ mod tests {
|
||||
let statement = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
|
||||
let summary = table.import_statement(&context, statement, None)
|
||||
@@ -1063,10 +1063,10 @@ mod tests {
|
||||
#[test]
|
||||
fn candidate_vote_gives_summary() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(ValidatorId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(ValidatorId(2), (GroupId(2), GroupId(455)));
|
||||
map.insert(AuthorityId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(AuthorityId(2), (GroupId(2), GroupId(455)));
|
||||
map
|
||||
}
|
||||
};
|
||||
@@ -1075,23 +1075,23 @@ mod tests {
|
||||
let statement = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
let candidate_digest = Digest(100);
|
||||
|
||||
table.import_statement(&context, statement, None);
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(1)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1)));
|
||||
|
||||
let vote = SignedStatement {
|
||||
statement: Statement::Valid(candidate_digest.clone()),
|
||||
signature: Signature(2),
|
||||
sender: ValidatorId(2),
|
||||
sender: AuthorityId(2),
|
||||
};
|
||||
|
||||
let summary = table.import_statement(&context, vote, None)
|
||||
.expect("candidate vote to give summary");
|
||||
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(2)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2)));
|
||||
|
||||
assert_eq!(summary.candidate, Digest(100));
|
||||
assert_eq!(summary.group_id, GroupId(2));
|
||||
@@ -1102,10 +1102,10 @@ mod tests {
|
||||
#[test]
|
||||
fn availability_vote_gives_summary() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
map.insert(ValidatorId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(ValidatorId(2), (GroupId(5), GroupId(2)));
|
||||
map.insert(AuthorityId(1), (GroupId(2), GroupId(455)));
|
||||
map.insert(AuthorityId(2), (GroupId(5), GroupId(2)));
|
||||
map
|
||||
}
|
||||
};
|
||||
@@ -1114,23 +1114,23 @@ mod tests {
|
||||
let statement = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
let candidate_digest = Digest(100);
|
||||
|
||||
table.import_statement(&context, statement, None);
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(1)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(1)));
|
||||
|
||||
let vote = SignedStatement {
|
||||
statement: Statement::Available(candidate_digest.clone()),
|
||||
signature: Signature(2),
|
||||
sender: ValidatorId(2),
|
||||
sender: AuthorityId(2),
|
||||
};
|
||||
|
||||
let summary = table.import_statement(&context, vote, None)
|
||||
.expect("candidate vote to give summary");
|
||||
|
||||
assert!(!table.detected_misbehavior.contains_key(&ValidatorId(2)));
|
||||
assert!(!table.detected_misbehavior.contains_key(&AuthorityId(2)));
|
||||
|
||||
assert_eq!(summary.candidate, Digest(100));
|
||||
assert_eq!(summary.group_id, GroupId(2));
|
||||
@@ -1141,10 +1141,10 @@ mod tests {
|
||||
#[test]
|
||||
fn filling_batch_sets_known_flag() {
|
||||
let context = TestContext {
|
||||
validators: {
|
||||
authorities: {
|
||||
let mut map = HashMap::new();
|
||||
for i in 1..10 {
|
||||
map.insert(ValidatorId(i), (GroupId(2), GroupId(400 + i)));
|
||||
map.insert(AuthorityId(i), (GroupId(2), GroupId(400 + i)));
|
||||
}
|
||||
map
|
||||
}
|
||||
@@ -1154,7 +1154,7 @@ mod tests {
|
||||
let statement = SignedStatement {
|
||||
statement: Statement::Candidate(Candidate(2, 100)),
|
||||
signature: Signature(1),
|
||||
sender: ValidatorId(1),
|
||||
sender: AuthorityId(1),
|
||||
};
|
||||
|
||||
table.import_statement(&context, statement, None);
|
||||
@@ -1163,7 +1163,7 @@ mod tests {
|
||||
let statement = SignedStatement {
|
||||
statement: Statement::Valid(Digest(100)),
|
||||
signature: Signature(i),
|
||||
sender: ValidatorId(i),
|
||||
sender: AuthorityId(i),
|
||||
};
|
||||
|
||||
table.import_statement(&context, statement, None);
|
||||
@@ -1171,7 +1171,7 @@ mod tests {
|
||||
|
||||
let mut batch = VecBatch {
|
||||
max_len: 5,
|
||||
targets: (1..10).map(ValidatorId).collect(),
|
||||
targets: (1..10).map(AuthorityId).collect(),
|
||||
items: Vec::new(),
|
||||
};
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ use tokio_timer::Timer;
|
||||
use super::*;
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Clone, Copy)]
|
||||
struct ValidatorId(usize);
|
||||
struct AuthorityId(usize);
|
||||
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Clone)]
|
||||
struct Digest(Vec<usize>);
|
||||
@@ -52,8 +52,8 @@ struct Proposal {
|
||||
|
||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||
enum Signature {
|
||||
Table(ValidatorId, table::Statement<ParachainCandidate, Digest>),
|
||||
Bft(ValidatorId, bft::Message<Proposal, Digest>),
|
||||
Table(AuthorityId, table::Statement<ParachainCandidate, Digest>),
|
||||
Bft(AuthorityId, bft::Message<Proposal, Digest>),
|
||||
}
|
||||
|
||||
enum Error {
|
||||
@@ -72,11 +72,11 @@ struct SharedTestContext {
|
||||
#[derive(Debug, Clone)]
|
||||
struct TestContext {
|
||||
shared: Arc<SharedTestContext>,
|
||||
local_id: ValidatorId,
|
||||
local_id: AuthorityId,
|
||||
}
|
||||
|
||||
impl Context for TestContext {
|
||||
type ValidatorId = ValidatorId;
|
||||
type AuthorityId = AuthorityId;
|
||||
type Digest = Digest;
|
||||
type GroupId = GroupId;
|
||||
type Signature = Signature;
|
||||
@@ -87,8 +87,8 @@ impl Context for TestContext {
|
||||
type CheckAvailability = Box<Future<Item=bool,Error=Error>>;
|
||||
|
||||
type StatementBatch = VecBatch<
|
||||
ValidatorId,
|
||||
table::SignedStatement<ParachainCandidate, Digest, ValidatorId, Signature>
|
||||
AuthorityId,
|
||||
table::SignedStatement<ParachainCandidate, Digest, AuthorityId, Signature>
|
||||
>;
|
||||
|
||||
fn candidate_digest(candidate: &ParachainCandidate) -> Digest {
|
||||
@@ -106,8 +106,8 @@ impl Context for TestContext {
|
||||
candidate.group.clone()
|
||||
}
|
||||
|
||||
fn round_proposer(&self, round: usize) -> ValidatorId {
|
||||
ValidatorId(round % self.shared.n_authorities)
|
||||
fn round_proposer(&self, round: usize) -> AuthorityId {
|
||||
AuthorityId(round % self.shared.n_authorities)
|
||||
}
|
||||
|
||||
fn check_validity(&self, _candidate: &ParachainCandidate) -> Self::CheckCandidate {
|
||||
@@ -151,7 +151,7 @@ impl Context for TestContext {
|
||||
}
|
||||
}
|
||||
|
||||
fn local_id(&self) -> ValidatorId {
|
||||
fn local_id(&self) -> AuthorityId {
|
||||
self.local_id.clone()
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ impl<V, T> ::StatementBatch<V, T> for VecBatch<V, T> {
|
||||
}
|
||||
|
||||
fn make_group_assignments(n_authorities: usize, n_groups: usize)
|
||||
-> HashMap<GroupId, GroupInfo<ValidatorId>>
|
||||
-> HashMap<GroupId, GroupInfo<AuthorityId>>
|
||||
{
|
||||
let mut map = HashMap::new();
|
||||
let threshold = (n_authorities / n_groups) / 2;
|
||||
@@ -286,23 +286,23 @@ fn make_group_assignments(n_authorities: usize, n_groups: usize)
|
||||
map.entry(GroupId(primary_group))
|
||||
.or_insert_with(&make_blank_group)
|
||||
.validity_guarantors
|
||||
.insert(ValidatorId(a_id));
|
||||
.insert(AuthorityId(a_id));
|
||||
|
||||
for &availability_group in &availability_groups {
|
||||
map.entry(GroupId(availability_group))
|
||||
.or_insert_with(&make_blank_group)
|
||||
.availability_guarantors
|
||||
.insert(ValidatorId(a_id));
|
||||
.insert(AuthorityId(a_id));
|
||||
}
|
||||
}
|
||||
|
||||
map
|
||||
}
|
||||
|
||||
fn make_blank_batch<T>(n_authorities: usize) -> VecBatch<ValidatorId, T> {
|
||||
fn make_blank_batch<T>(n_authorities: usize) -> VecBatch<AuthorityId, T> {
|
||||
VecBatch {
|
||||
max_len: 20,
|
||||
targets: (0..n_authorities).map(ValidatorId).collect(),
|
||||
targets: (0..n_authorities).map(AuthorityId).collect(),
|
||||
items: Vec::new(),
|
||||
}
|
||||
}
|
||||
@@ -318,7 +318,7 @@ fn consensus_completes_with_minimum_good() {
|
||||
.num_slots(1 << 16)
|
||||
.build();
|
||||
|
||||
let (network, inputs, outputs) = Network::<(ValidatorId, OutgoingMessage<TestContext>)>::new(n - f);
|
||||
let (network, inputs, outputs) = Network::<(AuthorityId, OutgoingMessage<TestContext>)>::new(n - f);
|
||||
network.route_on_thread();
|
||||
|
||||
let shared_test_context = Arc::new(SharedTestContext {
|
||||
@@ -330,7 +330,7 @@ fn consensus_completes_with_minimum_good() {
|
||||
let groups = make_group_assignments(n, n_groups);
|
||||
|
||||
let authorities = inputs.into_iter().zip(outputs).enumerate().map(|(raw_id, (input, output))| {
|
||||
let id = ValidatorId(raw_id);
|
||||
let id = AuthorityId(raw_id);
|
||||
let context = TestContext {
|
||||
shared: shared_test_context.clone(),
|
||||
local_id: id,
|
||||
|
||||
Reference in New Issue
Block a user