Add new gossip structure for supporting repairs (#4205)

* Add Epoch Slots to gossip

* Add new gossip structure to support Repair

* remove unnecessary clones

* Setup dummy fast repair in repair_service

* PR comments
This commit is contained in:
carllin
2019-05-08 13:50:32 -07:00
committed by GitHub
parent 965c1e0000
commit b8fd51e97d
5 changed files with 161 additions and 59 deletions

View File

@@ -3,6 +3,7 @@ use bincode::serialize;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::{Keypair, Signable, Signature};
use solana_sdk::transaction::Transaction;
use std::collections::HashSet;
use std::fmt;
/// CrdsValue that is replicated across the cluster
@@ -12,6 +13,58 @@ pub enum CrdsValue {
ContactInfo(ContactInfo),
/// * Merge Strategy - Latest wallclock is picked
Vote(Vote),
/// * Merge Strategy - Latest wallclock is picked
EpochSlots(EpochSlots),
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
pub struct EpochSlots {
pub from: Pubkey,
pub root: u64,
pub slots: HashSet<u64>,
pub signature: Signature,
pub wallclock: u64,
}
impl EpochSlots {
pub fn new(from: Pubkey, root: u64, slots: HashSet<u64>, wallclock: u64) -> Self {
Self {
from,
root,
slots,
signature: Signature::default(),
wallclock,
}
}
}
impl Signable for EpochSlots {
fn pubkey(&self) -> Pubkey {
self.from
}
fn signable_data(&self) -> Vec<u8> {
#[derive(Serialize)]
struct SignData<'a> {
root: u64,
slots: &'a HashSet<u64>,
wallclock: u64,
}
let data = SignData {
root: self.root,
slots: &self.slots,
wallclock: self.wallclock,
};
serialize(&data).expect("unable to serialize EpochSlots")
}
fn get_signature(&self) -> Signature {
self.signature
}
fn set_signature(&mut self, signature: Signature) {
self.signature = signature;
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
@@ -22,6 +75,17 @@ pub struct Vote {
pub wallclock: u64,
}
impl Vote {
pub fn new(from: &Pubkey, transaction: Transaction, wallclock: u64) -> Self {
Self {
from: *from,
transaction,
signature: Signature::default(),
wallclock,
}
}
}
impl Signable for Vote {
fn pubkey(&self) -> Pubkey {
self.from
@@ -29,12 +93,12 @@ impl Signable for Vote {
fn signable_data(&self) -> Vec<u8> {
#[derive(Serialize)]
struct SignData {
transaction: Transaction,
struct SignData<'a> {
transaction: &'a Transaction,
wallclock: u64,
}
let data = SignData {
transaction: self.transaction.clone(),
transaction: &self.transaction,
wallclock: self.wallclock,
};
serialize(&data).expect("unable to serialize Vote")
@@ -55,6 +119,7 @@ impl Signable for Vote {
pub enum CrdsValueLabel {
ContactInfo(Pubkey),
Vote(Pubkey),
EpochSlots(Pubkey),
}
impl fmt::Display for CrdsValueLabel {
@@ -62,6 +127,7 @@ impl fmt::Display for CrdsValueLabel {
match self {
CrdsValueLabel::ContactInfo(_) => write!(f, "ContactInfo({})", self.pubkey()),
CrdsValueLabel::Vote(_) => write!(f, "Vote({})", self.pubkey()),
CrdsValueLabel::EpochSlots(_) => write!(f, "EpochSlots({})", self.pubkey()),
}
}
}
@@ -71,17 +137,7 @@ impl CrdsValueLabel {
match self {
CrdsValueLabel::ContactInfo(p) => *p,
CrdsValueLabel::Vote(p) => *p,
}
}
}
impl Vote {
pub fn new(from: &Pubkey, transaction: Transaction, wallclock: u64) -> Self {
Vote {
from: *from,
transaction,
signature: Signature::default(),
wallclock,
CrdsValueLabel::EpochSlots(p) => *p,
}
}
}
@@ -94,6 +150,7 @@ impl CrdsValue {
match self {
CrdsValue::ContactInfo(contact_info) => contact_info.wallclock,
CrdsValue::Vote(vote) => vote.wallclock,
CrdsValue::EpochSlots(vote) => vote.wallclock,
}
}
pub fn label(&self) -> CrdsValueLabel {
@@ -102,6 +159,7 @@ impl CrdsValue {
CrdsValueLabel::ContactInfo(contact_info.pubkey())
}
CrdsValue::Vote(vote) => CrdsValueLabel::Vote(vote.pubkey()),
CrdsValue::EpochSlots(slots) => CrdsValueLabel::EpochSlots(slots.pubkey()),
}
}
pub fn contact_info(&self) -> Option<&ContactInfo> {
@@ -116,11 +174,18 @@ impl CrdsValue {
_ => None,
}
}
pub fn epoch_slots(&self) -> Option<&EpochSlots> {
match self {
CrdsValue::EpochSlots(slots) => Some(slots),
_ => None,
}
}
/// Return all the possible labels for a record identified by Pubkey.
pub fn record_labels(key: &Pubkey) -> [CrdsValueLabel; 2] {
pub fn record_labels(key: &Pubkey) -> [CrdsValueLabel; 3] {
[
CrdsValueLabel::ContactInfo(*key),
CrdsValueLabel::Vote(*key),
CrdsValueLabel::EpochSlots(*key),
]
}
}
@@ -130,12 +195,15 @@ impl Signable for CrdsValue {
match self {
CrdsValue::ContactInfo(contact_info) => contact_info.sign(keypair),
CrdsValue::Vote(vote) => vote.sign(keypair),
CrdsValue::EpochSlots(epoch_slots) => epoch_slots.sign(keypair),
};
}
fn verify(&self) -> bool {
match self {
CrdsValue::ContactInfo(contact_info) => contact_info.verify(),
CrdsValue::Vote(vote) => vote.verify(),
CrdsValue::EpochSlots(epoch_slots) => epoch_slots.verify(),
}
}
@@ -143,6 +211,7 @@ impl Signable for CrdsValue {
match self {
CrdsValue::ContactInfo(contact_info) => contact_info.pubkey(),
CrdsValue::Vote(vote) => vote.pubkey(),
CrdsValue::EpochSlots(epoch_slots) => epoch_slots.pubkey(),
}
}
@@ -169,12 +238,13 @@ mod test {
#[test]
fn test_labels() {
let mut hits = [false; 2];
let mut hits = [false; 3];
// this method should cover all the possible labels
for v in &CrdsValue::record_labels(&Pubkey::default()) {
match v {
CrdsValueLabel::ContactInfo(_) => hits[0] = true,
CrdsValueLabel::Vote(_) => hits[1] = true,
CrdsValueLabel::EpochSlots(_) => hits[2] = true,
}
}
assert!(hits.iter().all(|x| *x));
@@ -190,6 +260,11 @@ mod test {
assert_eq!(v.wallclock(), 0);
let key = v.clone().vote().unwrap().from;
assert_eq!(v.label(), CrdsValueLabel::Vote(key));
let v = CrdsValue::EpochSlots(EpochSlots::new(Pubkey::default(), 0, HashSet::new(), 0));
assert_eq!(v.wallclock(), 0);
let key = v.clone().epoch_slots().unwrap().from;
assert_eq!(v.label(), CrdsValueLabel::EpochSlots(key));
}
#[test]
fn test_signature() {
@@ -200,6 +275,13 @@ mod test {
verify_signatures(&mut v, &keypair, &wrong_keypair);
v = CrdsValue::Vote(Vote::new(&keypair.pubkey(), test_tx(), timestamp()));
verify_signatures(&mut v, &keypair, &wrong_keypair);
v = CrdsValue::EpochSlots(EpochSlots::new(
keypair.pubkey(),
0,
HashSet::new(),
timestamp(),
));
verify_signatures(&mut v, &keypair, &wrong_keypair);
}
fn verify_signatures(