Skip to content
Permalink
Browse files

fix issue

  • Loading branch information...
vincenthz committed Mar 12, 2019
2 parents 2fc6c73 + fb25b59 commit daf3c81f95bcbde2a6781a6294daed7ada98b396
@@ -18,11 +18,6 @@
//! to the beginning of the chain. We often call this number
//! the block Date.
//!
//! # HasTransaction and Transaction
//!
//! These traits are mainly fit for the purpose of the Unspent Transaction
//! Output (UTxO) model.
//!
//! # Ledger
//!
//! this trait is to make sure we are following the Transactions of the chain
@@ -173,43 +168,12 @@ pub trait Transaction: Serialize + Deserialize {
type Inputs: ?Sized;
/// The iterable type of transaction outputs (if none use `Option<()>` and return `None`).
type Outputs: ?Sized;
/// a unique identifier of the transaction. For 2 different transactions
/// we must have 2 different `Id` values.
type Id: TransactionId;

/// Returns a reference that can be used to iterate over transaction's inputs.
fn inputs(&self) -> &Self::Inputs;

/// Returns a reference that can be used to iterate over transaction's outputs.
fn outputs(&self) -> &Self::Outputs;

/// return the Transaction's identifier.
fn id(&self) -> Self::Id;
}

/// Accessor to transactions within a block
///
/// This trait is generic enough to show there is multiple types
/// of transaction possibles:
///
/// * UTxO
/// * certificate registrations
/// * ...
pub trait HasTransaction {
/// The type of transactions in this block.
type Transaction;

/// Returns an iterator over the transactions in the block.
///
/// Note that the iterator is dynamically allocated, and the iterator's
/// `next` method is invoked via dynamic dispatch. The method
/// `for_each_transaction` provides a statically monomorphised
/// alternative.
fn transactions<'a>(&'a self) -> Box<Iterator<Item = &Self::Transaction> + 'a>;

fn for_each_transaction<F>(&self, f: F)
where
F: FnMut(&Self::Transaction);
}

/// Updates type needs to implement this feature so we can easily
@@ -232,57 +196,26 @@ pub trait Update {
fn empty() -> Self;
}

pub trait State: Sized + Clone {
type Error: std::error::Error;
type Content: Message;

fn apply<I>(&self, contents: I) -> Result<Self, Self::Error>
where
I: IntoIterator<Item = Self::Content>;
}

/// Define the Ledger side of the blockchain. This is not really on the blockchain
/// but should be able to maintain a valid state of the overall blockchain at a given
/// `Block`.
pub trait Ledger: Sized {
/// a Ledger Update. An atomic representation of a set of changes
/// into the ledger's state.
///
/// This can be seen like a git Diff where we can see what is going
/// to be removed from the Ledger state and what is going to be added.
type Update: Update;

pub trait Ledger<T: Transaction>: Sized {
/// Ledger's errors
type Error: std::error::Error;

type Transaction: Transaction;

/// check the input exists in the given ledger state
///
/// i.e. in the UTxO model the Input will be something like the Transaction's Id
/// and the index of the output within the output array.
/// If the Output is not present it is possible that it does not exist or has
/// already been spent in another transaction.
fn input<'a>(
fn input<'a, I>(
&'a self,
input: &<Self::Transaction as Transaction>::Input,
) -> Result<&'a <Self::Transaction as Transaction>::Output, Self::Error>;

/// create a new Update from the given transaction.
fn diff_transaction(
&self,
transaction: &Self::Transaction,
) -> Result<Self::Update, Self::Error>;

/// create a combined Update from the given transactions
///
fn diff<'a, I>(&self, transactions: I) -> Result<Self::Update, Self::Error>
where
I: IntoIterator<Item = &'a Self::Transaction> + Sized,
Self::Transaction: 'a,
{
let mut update = Self::Update::empty();

for transaction in transactions {
update.union(self.diff_transaction(transaction)?);
}

Ok(update)
}

/// apply an update to the leger.
fn apply(&mut self, update: Self::Update) -> Result<&mut Self, Self::Error>;
input: <T as Transaction>::Input,
) -> Result<&'a <T as Transaction>::Output, Self::Error>;
}

/// Trait identifying the leader identifier type.
@@ -297,17 +230,6 @@ pub trait LeaderId: Eq + Clone + Hash + Debug {}
/// This is also the same interface that is used to detect if we are the
/// leader for the block at the given date.
pub trait LeaderSelection {
/// a leader selection Update. This is an atomic representation of
/// the set of changes to apply to the leader selection state.
///
/// Having an atomic representation of the changes allow other
/// interesting properties:
///
/// * generic testing;
/// * diff based storage;
///
type Update: Update;

/// the block that we will get the information from
type Block: Block;

@@ -317,21 +239,6 @@ pub trait LeaderSelection {
/// Identifier of the leader (e.g. a public key).
type LeaderId: LeaderId;

/// given a Block, create an Update diff to see what are the changes
/// that will come with this new block.
///
/// This function is also responsible to check the validity of the block
/// within the blockchain but not to check the Transactional entities.
/// The transaction part are verified with the [`Transaction::diff`]
/// method.
///
/// Here we want to check the validity of the consensus and of the block
/// signature.
fn diff(&self, input: &Self::Block) -> Result<Self::Update, Self::Error>;

/// apply the Update to the LeaderSelection
fn apply(&mut self, update: Self::Update) -> Result<(), Self::Error>;

/// return the ID of the leader of the blockchain at the given
/// date.
fn get_leader_at(
@@ -344,18 +251,9 @@ pub trait LeaderSelection {
/// the blockchain protocol update details:
///
pub trait Settings {
type Update: Update;
type Block: Block;
type Error: std::error::Error;

/// read the block update settings and see if we need to store
/// updates. Protocols may propose vote mechanism, this Update
/// and the settings need to keep track of these here.
fn diff(&self, input: &Self::Block) -> Result<Self::Update, Self::Error>;

/// apply the Update to the Settings
fn apply(&mut self, update: Self::Update) -> Result<(), Self::Error>;

/// return the tip of the current branch
///
fn tip(&self) -> <Self::Block as Block>::Id;
@@ -329,7 +329,7 @@ impl property::Update for GenesisSelectionDiff {
}

impl LeaderSelection for GenesisLeaderSelection {
type Update = GenesisSelectionDiff;
type Update = Update;
type Block = Block;
type Error = Error;
type LeaderId = PublicLeader;
@@ -408,7 +408,7 @@ impl LeaderSelection for GenesisLeaderSelection {
.collect();
snapshots.insert(date.epoch, self.get_stake_distribution());
assert!(snapshots.len() <= 2);
update.stake_snapshots = Some(snapshots);
update.genesis.stake_snapshots = Some(snapshots);
}

for msg in input.contents.iter() {
@@ -436,10 +436,12 @@ impl LeaderSelection for GenesisLeaderSelection {
// key. Probably that should void the reward
// account (rather than be a no-op).
assert!(!update
.genesis
.stake_key_deregistrations
.contains(&reg.data.stake_key_id));

update
.genesis
.stake_key_registrations
.insert(reg.data.stake_key_id.clone());
}
@@ -465,9 +467,11 @@ impl LeaderSelection for GenesisLeaderSelection {
// deregistrations of a key in the same
// block.
assert!(!update
.genesis
.stake_key_registrations
.contains(&reg.data.stake_key_id));
update
.genesis
.stake_key_deregistrations
.insert(reg.data.stake_key_id.clone());
}
@@ -515,6 +519,7 @@ impl LeaderSelection for GenesisLeaderSelection {
}

update
.genesis
.delegations
.insert(reg.data.stake_key_id.clone(), reg.data.pool_id.clone());
}
@@ -532,7 +537,10 @@ impl LeaderSelection for GenesisLeaderSelection {
}

if self.delegation_state.stake_pool_exists(&reg.data.pool_id)
|| update.new_stake_pools.contains_key(&reg.data.pool_id)
|| update
.genesis
.new_stake_pools
.contains_key(&reg.data.pool_id)
{
// FIXME: support re-registration to change pool parameters.
return Err(Error {
@@ -548,6 +556,7 @@ impl LeaderSelection for GenesisLeaderSelection {
// FIXME: should pool_id be a previously registered stake key?

update
.genesis
.new_stake_pools
.insert(reg.data.pool_id.clone(), reg.data.clone());
}
@@ -564,7 +573,10 @@ impl LeaderSelection for GenesisLeaderSelection {
)),
});
}
update.retired_stake_pools.insert(ret.data.pool_id.clone());
update
.genesis
.retired_stake_pools
.insert(ret.data.pool_id.clone());
} else {
return Err(Error {
kind: ErrorKind::InvalidBlockMessage,
@@ -579,54 +591,61 @@ impl LeaderSelection for GenesisLeaderSelection {
}
}

update.next_date = ValueDiff::Replace(self.pos.next_date, new_pos.next_date);
update.bft_blocks = ValueDiff::Replace(self.pos.bft_blocks, new_pos.bft_blocks);
update.genesis_blocks = ValueDiff::Replace(self.pos.genesis_blocks, new_pos.genesis_blocks);
update.genesis.next_date = ValueDiff::Replace(self.pos.next_date, new_pos.next_date);
update.genesis.bft_blocks = ValueDiff::Replace(self.pos.bft_blocks, new_pos.bft_blocks);
update.genesis.genesis_blocks =
ValueDiff::Replace(self.pos.genesis_blocks, new_pos.genesis_blocks);

Ok(update)
}

fn apply(&mut self, update: Self::Update) -> Result<(), Self::Error> {
if !update.next_date.check(&self.pos.next_date)
|| !update.bft_blocks.check(&self.pos.bft_blocks)
|| !update.genesis_blocks.check(&self.pos.genesis_blocks)
if !update.genesis.next_date.check(&self.pos.next_date)
|| !update.genesis.bft_blocks.check(&self.pos.bft_blocks)
|| !update
.genesis
.genesis_blocks
.check(&self.pos.genesis_blocks)
{
return Err(Error {
kind: ErrorKind::InvalidStateUpdate,
cause: Some(Box::new(GenesisPraosError::UpdateIsInvalid)),
});
}

for stake_key_id in update.stake_key_registrations {
for stake_key_id in update.genesis.stake_key_registrations {
self.delegation_state.register_stake_key(stake_key_id);
}

for stake_key_id in update.stake_key_deregistrations {
for stake_key_id in update.genesis.stake_key_deregistrations {
self.delegation_state.deregister_stake_key(&stake_key_id);
}

for (pool_id, new_stake_pool) in update.new_stake_pools {
for (pool_id, new_stake_pool) in update.genesis.new_stake_pools {
self.delegation_state.register_stake_pool(
pool_id,
new_stake_pool.kes_public_key,
new_stake_pool.vrf_public_key,
);
}

for (stake_key_id, pool_id) in update.delegations {
for (stake_key_id, pool_id) in update.genesis.delegations {
self.delegation_state.delegate_stake(stake_key_id, pool_id);
}

// FIXME: the pool should be retired at the end of a specified epoch.
for pool_id in update.retired_stake_pools {
for pool_id in update.genesis.retired_stake_pools {
self.delegation_state.deregister_stake_pool(&pool_id);
}

update.next_date.apply_to(&mut self.pos.next_date);
update.bft_blocks.apply_to(&mut self.pos.bft_blocks);
update.genesis_blocks.apply_to(&mut self.pos.genesis_blocks);
update.genesis.next_date.apply_to(&mut self.pos.next_date);
update.genesis.bft_blocks.apply_to(&mut self.pos.bft_blocks);
update
.genesis
.genesis_blocks
.apply_to(&mut self.pos.genesis_blocks);

if let Some(stake_snapshots) = update.stake_snapshots {
if let Some(stake_snapshots) = update.genesis.stake_snapshots {
self.stake_snapshots = stake_snapshots;
}

@@ -40,10 +40,11 @@ pub enum PublicLeader {
GenesisPraos(GenesisPraosLeader),
}

#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone)]
pub struct Update {
pub(crate) previous_leader: PublicLeader,
pub(crate) next_leader: PublicLeader,
pub(crate) genesis: genesis::GenesisSelectionDiff,
}

pub enum Leader {
@@ -66,14 +67,17 @@ impl property::Update for Update {
Update {
previous_leader: PublicLeader::None,
next_leader: PublicLeader::None,
genesis: genesis::GenesisSelectionDiff::empty(),
}
}
fn union(&mut self, other: Self) -> &mut Self {
self.next_leader = other.next_leader;
self.genesis.union(other.genesis);
self
}
fn inverse(mut self) -> Self {
std::mem::swap(&mut self.previous_leader, &mut self.next_leader);
self.genesis = self.genesis.inverse();
self
}
}
Oops, something went wrong.

0 comments on commit daf3c81

Please sign in to comment.
You can’t perform that action at this time.