Skip to content
This repository has been archived by the owner on Jun 11, 2022. It is now read-only.

Commit

Permalink
Merge remote-tracking branch 'origin/master' into chain-storage
Browse files Browse the repository at this point in the history
  • Loading branch information
edolstra committed Jan 11, 2019
2 parents 0e53198 + 7ba6f46 commit 653ae6b
Show file tree
Hide file tree
Showing 21 changed files with 868 additions and 115 deletions.
9 changes: 9 additions & 0 deletions .circleci/config.yml
Expand Up @@ -54,6 +54,9 @@ jobs:
done
- store_test_results:
path: ~/test-results
- store_artifacts:
path: ~/test-results
destination: test_results
- persist_to_workspace:
root: "."
paths:
Expand All @@ -80,6 +83,9 @@ jobs:
command: cargo junit --name ~/test-results/${CIRCLE_JOB}/results.xml
- store_test_results:
path: ~/test-results
- store_artifacts:
path: ~/test-results
destination: test_results
test_nightly:
docker:
- image: rustlang/rust:nightly
Expand All @@ -102,6 +108,9 @@ jobs:
command: cargo junit --name ~/test-results/${CIRCLE_JOB}/results.xml
- store_test_results:
path: ~/test-results
- store_artifacts:
path: ~/test-results
destination: test_results
coverage:
docker:
- image: ragnaroek/kcov:v33
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -5,6 +5,7 @@ members = [
"chain-storage-sqlite",
"chain-impl-mockchain",
"cardano",
"network-grpc",
"protocol",
"protocol-tokio",
"storage-units",
Expand Down
30 changes: 26 additions & 4 deletions cardano/src/block/block.rs
Expand Up @@ -80,6 +80,8 @@ pub enum BlockHeader {
MainBlockHeader(normal::BlockHeader),
}

impl core::property::Header for BlockHeader {}

/// BlockHeaders is a vector of block headers, as produced by
/// MsgBlocks.
#[derive(Debug, Clone)]
Expand Down Expand Up @@ -204,6 +206,8 @@ impl fmt::Display for Block {

impl chain_core::property::Block for Block {
type Id = HeaderHash;
type Date = BlockDate;
type Header = BlockHeader;

fn id(&self) -> Self::Id {
self.get_header().compute_hash()
Expand All @@ -213,21 +217,39 @@ impl chain_core::property::Block for Block {
self.get_header().get_previous_header()
}

type Date = BlockDate;

fn date(&self) -> Self::Date {
self.get_header().get_blockdate()
match self {
Block::MainBlock(ref block) => block.header.consensus.slot_id.into(),
Block::BoundaryBlock(ref block) => block.header.consensus.epoch.into(),
}
}

fn header(&self) -> BlockHeader {
self.get_header()
}
}

impl chain_core::property::Serializable for Block {
impl core::property::HasTransaction<TxAux> for Block {
fn transactions<'a>(&'a self) -> std::slice::Iter<'a, TxAux> {
match self {
&Block::BoundaryBlock(_) => [].iter(),
&Block::MainBlock(ref blk) => blk.body.tx.iter(),
}
}
}

impl core::property::Serialize for Block {
type Error = cbor_event::Error;

fn serialize<W: std::io::Write>(&self, mut writer: W) -> Result<(), Self::Error> {
let bytes = cbor!(self)?;
writer.write(&bytes)?;
Ok(())
}
}

impl core::property::Deserialize for Block {
type Error = cbor_event::Error;

fn deserialize<R: std::io::BufRead>(reader: R) -> Result<Self, Self::Error> {
Deserialize::deserialize(&mut Deserializer::from(reader))
Expand Down
5 changes: 5 additions & 0 deletions cardano/src/block/date.rs
@@ -1,5 +1,7 @@
use super::types::{EpochId, EpochSlotId, SlotId};

use chain_core::property;

use std::{
cmp::{Ord, Ordering},
error::Error,
Expand All @@ -16,6 +18,9 @@ pub enum BlockDate {
Boundary(EpochId),
Normal(EpochSlotId),
}

impl property::BlockDate for BlockDate {}

impl ::std::ops::Sub<BlockDate> for BlockDate {
type Output = usize;
fn sub(self, rhs: Self) -> Self::Output {
Expand Down
4 changes: 4 additions & 0 deletions cardano/src/block/types.rs
@@ -1,5 +1,6 @@
use super::normal::SscPayload;
use cbor_event::{self, de::Deserializer, se::Serializer};
use chain_core::property;
use hash::Blake2b256;
use util::try_from_slice::TryFromSlice;

Expand Down Expand Up @@ -47,6 +48,9 @@ impl HeaderHash {
self.0.as_hash_bytes()
}
}

impl property::BlockId for HeaderHash {}

impl fmt::Display for HeaderHash {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self.0, f)
Expand Down
3 changes: 3 additions & 0 deletions cardano/src/lib.rs
Expand Up @@ -15,11 +15,14 @@
//!
#![cfg_attr(feature = "with-bench", feature(test))]

extern crate chain_core;

#[cfg(feature = "generic-serialization")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "generic-serialization")]
extern crate serde;

#[cfg(test)]
extern crate serde_json;
#[cfg(test)]
Expand Down
26 changes: 23 additions & 3 deletions cardano/src/tx.rs
Expand Up @@ -11,7 +11,15 @@ use std::{
io::{BufRead, Write},
};

use hash::Blake2b256;
use crate::{
address::{AddrType, Attributes, ExtendedAddr, SpendingData},
coin::{self, Coin},
config::ProtocolMagic,
hash::Blake2b256,
hdwallet::{Signature, XPrv, XPub, SIGNATURE_SIZE, XPUB_SIZE},
merkle, redeem,
tags::SigningTag,
};

use cbor_event::{self, de::Deserializer, se::Serializer};
use config::ProtocolMagic;
Expand All @@ -29,6 +37,9 @@ use chain_core;
// given Tx, or a hash of a redeem address.
pub type TxId = Blake2b256;

// FIXME: This is dodgy because TxId is not currently a dedicated type.
impl property::TransactionId for TxId {}

pub fn redeem_pubkey_to_txid(
pubkey: &redeem::PublicKey,
protocol_magic: ProtocolMagic,
Expand Down Expand Up @@ -624,7 +635,7 @@ impl cbor_event::de::Deserialize for TxProof {
}
}

impl chain_core::property::Serializable for Tx {
impl chain_core::property::Serialize for Tx {
type Error = cbor_event::Error;

fn serialize<W: std::io::Write>(&self, writer: W) -> Result<(), Self::Error> {
Expand All @@ -633,13 +644,18 @@ impl chain_core::property::Serializable for Tx {
serializer.finalize();
Ok(())
}
}

impl chain_core::property::Deserialize for Tx {
type Error = cbor_event::Error;

fn deserialize<R: std::io::BufRead>(reader: R) -> Result<Self, Self::Error> {
let mut deserializer = cbor_event::de::Deserializer::from(reader);
deserializer.deserialize::<Self>()
}
}
impl chain_core::property::Serializable for TxAux {

impl chain_core::property::Serialize for TxAux {
type Error = cbor_event::Error;

fn serialize<W: std::io::Write>(&self, writer: W) -> Result<(), Self::Error> {
Expand All @@ -648,6 +664,10 @@ impl chain_core::property::Serializable for TxAux {
serializer.finalize();
Ok(())
}
}

impl chain_core::property::Deserialize for TxAux {
type Error = cbor_event::Error;

fn deserialize<R: std::io::BufRead>(reader: R) -> Result<Self, Self::Error> {
let mut deserializer = cbor_event::de::Deserializer::from(reader);
Expand Down
79 changes: 54 additions & 25 deletions chain-core/src/property.rs
Expand Up @@ -38,6 +38,29 @@
use std::fmt::Debug;
use std::hash::Hash;

/// Trait identifying the block identifier type.
pub trait BlockId: Eq + Ord + Clone + Debug + Hash + AsRef<[u8]> {
// FIXME: constant representing id length?

/// Construct a BlockId from a slice. FIXME: use TryFromSlice trait.
fn try_from_slice(slice: &[u8]) -> Option<Self>;
}

/// A trait representing block dates. Dates can be compared, ordered
/// and serialized as integers.
pub trait BlockDate: Eq + Ord + Clone {
fn serialize(&self) -> u64;
fn deserialize(n: u64) -> Self;
}

/// Trait identifying the transaction identifier type.
pub trait TransactionId: Eq + Hash {}

/// Trait identifying the block header type.
pub trait Header {}

impl Header for () {}

/// Block property
///
/// a block is part of a chain of block called Blockchain.
Expand All @@ -48,7 +71,7 @@ use std::hash::Hash;
/// recent block to the furthest/oldest block.
///
/// The Oldest block is called the Genesis Block.
pub trait Block: Serializable {
pub trait Block: Serialize + Deserialize {
/// the Block identifier. It must be unique. This mean that
/// 2 different blocks have 2 different identifiers.
///
Expand All @@ -62,6 +85,13 @@ pub trait Block: Serializable {
/// identifying the position of a block in a given epoch or era.
type Date: BlockDate;

/// The block header. If provided by the blockchain, the header
/// can be used to transmit block's metadata via a network protocol
/// or in other uses where the full content of the block is not desirable.
/// An implementation that does not feature headers can use the unit
/// type `()`.
type Header: Header;

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

Expand All @@ -71,34 +101,23 @@ pub trait Block: Serializable {

/// get the block date of the block
fn date(&self) -> Self::Date;
}

pub trait BlockId: Eq + Ord + Clone + Debug + Hash + AsRef<[u8]> {
// FIXME: constant representing id length?

/// Construct a BlockId from a slice. FIXME: use TryFromSlice trait.
fn try_from_slice(slice: &[u8]) -> Option<Self>;
}

/// A trait representing block dates. Dates can be compared, ordered
/// and serialized as integers.
pub trait BlockDate: Eq + Ord + Clone {
fn serialize(&self) -> u64;
fn deserialize(n: u64) -> Self;
/// Gets the block's header.
fn header(&self) -> Self::Header;
}

/// define a transaction within the blockchain. This transaction can be used
/// for the UTxO model. However it can also be used for any other elements that
/// the blockchain has (a transaction type to add Stacking Pools and so on...).
///
pub trait Transaction: Serializable {
pub trait Transaction: Serialize + Deserialize {
/// the input type of the transaction (if none use `()`).
type Input;
/// the output type of the transaction (if none use `()`).
type Output;
/// a unique identifier of the transaction. For 2 different transactions
/// we must have 2 different `Id` values.
type Id;
type Id: TransactionId;

fn inputs<'a>(&'a self) -> std::slice::Iter<'a, Self::Input>;
fn outputs<'a>(&'a self) -> std::slice::Iter<'a, Self::Output>;
Expand Down Expand Up @@ -213,15 +232,12 @@ pub trait LeaderSelection {
fn is_leader_at(&self, date: <Self::Block as Block>::Date) -> Result<bool, Self::Error>;
}

/// Define that an object can be written in a `Write` object or read from the
/// `Read` object.
pub trait Serializable: Sized {
/// Define that an object can be written to a `Write` object.
pub trait Serialize {
type Error: std::error::Error + From<std::io::Error>;

fn serialize<W: std::io::Write>(&self, writer: W) -> Result<(), Self::Error>;

fn deserialize<R: std::io::BufRead>(reader: R) -> Result<Self, Self::Error>;

/// Convenience method to serialize into a byte vector.
fn serialize_as_vec(&self) -> Result<Vec<u8>, Self::Error> {
let mut data = vec![];
Expand All @@ -230,23 +246,36 @@ pub trait Serializable: Sized {
}
}

/// Define that an object can be read from a `Read` object.
pub trait Deserialize: Sized {
type Error: std::error::Error + From<std::io::Error>;

fn deserialize<R: std::io::BufRead>(reader: R) -> Result<Self, Self::Error>;
}

impl<T: Serialize> Serialize for &T {
type Error = T::Error;

fn serialize<W: std::io::Write>(&self, writer: W) -> Result<(), T::Error> {
(**self).serialize(writer)
}
}

#[cfg(feature = "property-test-api")]
pub mod testing {
use super::*;
use quickcheck::{Arbitrary, Gen};
use std::io::Cursor;

/// test that any arbitrary given object can serialize and deserialize
/// back into itself (i.e. it is a bijection, or a one to one match
/// between the serialized bytes and the object)
pub fn serialization_bijection<T>(t: T) -> bool
where
T: Arbitrary + Serializable + Eq,
T: Arbitrary + Serialize + Deserialize + Eq,
{
let mut vec = Vec::new();
t.serialize(&mut vec).unwrap();
let cursor = Cursor::new(vec);
let decoded_t = <T as Serializable>::deserialize(cursor).unwrap();
let decoded_t = T::deserialize(&mut &vec[..]).unwrap();
decoded_t == t
}

Expand Down

0 comments on commit 653ae6b

Please sign in to comment.