<commit_before>#![feature(proc_macro)]

#[macro_use]
extern crate quote;
extern crate syn;
extern crate proc_macro;

use proc_macro::TokenStream;

mod args;

/// Splice an array of arguments into another term
///
/// `args` is a macro that’s used to splice a number of arguments into another term. This is
/// useful when you want to call a variadic term such as `branch` with a set of arguments produced at
/// runtime.
///
/// # Example
///
/// If `x` is greater than 5 return "big", otherwise return "small".
///
/// ```rust,ignore
/// let x = 10;
/// r.branch(args!(r.expr(x).gt(5), "big", "small"));
/// ```
#[proc_macro]
pub fn args(input: TokenStream) -> TokenStream {
    args::Args::new(&input.to_string())
        .process().tokens
        .as_str()
        .parse()
        .unwrap()
}
<commit_msg>cleanup docs<commit_after>#![feature(proc_macro)]

#[macro_use]
extern crate quote;
extern crate syn;
extern crate proc_macro;

use proc_macro::TokenStream;

mod args;

/// Splice an array of arguments into another term
///
/// `args` is a macro that’s used to splice a number of arguments into another term. This is
/// useful when you want to call a variadic term such as `branch` with a set of arguments produced at
/// runtime.
///
/// # Example
///
/// If `x` is greater than `5` return `big`, otherwise return `small`.
///
/// ```rust,ignore
/// r.branch(args!(r.expr(x).gt(5), "big", "small"));
/// ```
#[proc_macro]
pub fn args(input: TokenStream) -> TokenStream {
    args::Args::new(&input.to_string())
        .process().tokens
        .as_str()
        .parse()
        .unwrap()
}
<|endoftext|>


<commit_before>use rustc::lint::*;
use syntax::ast::*;
use syntax::ext::quote::rt::Span;
use utils::span_note_and_lint;

/// **What it does:** Checks for
///  - () being assigned to a variable
///  - () being passed to a function
///
/// **Why is this bad?** It is extremely unlikely that a user intended to
/// assign '()' to valiable. Instead,
/// Unit is what a block evaluates to when it returns nothing. This is
/// typically caused by a trailing
///   unintended semicolon.
///
/// **Known problems:** None.
///
/// **Example:**
/// * `let x = {"foo" ;}` when the user almost certainly intended `let x
/// ={"foo"}`

declare_lint! {
    pub UNIT_EXPR,
    Warn,
    "unintended assignment or use of a unit typed value"
}

#[derive(Copy, Clone)]
pub struct UnitExpr;

impl LintPass for UnitExpr {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_EXPR)
    }
}

impl EarlyLintPass for UnitExpr {
    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        if let ExprKind::Assign(ref _left, ref right) = expr.node {
            if let Some(span) = is_unit_expr(right) {
                span_note_and_lint(
                    cx,
                    UNIT_EXPR,
                    expr.span,
                        "This expression evaluates to the Unit type ()",
                    span,
                    "Consider removing the trailing semicolon",
                );
            }
        }
        if let ExprKind::MethodCall(ref _left, ref args) = expr.node {
            for arg in args {
                if let Some(span) = is_unit_expr(arg) {
                    span_note_and_lint(
                        cx,
                        UNIT_EXPR,
                        expr.span,
                        "This expression evaluates to the Unit type ()",
                        span,
                        "Consider removing the trailing semicolon",
                    );
                }
            }
        }
        if let ExprKind::Call(_, ref args) = expr.node {
            for arg in args {
                if let Some(span) = is_unit_expr(arg) {
                    span_note_and_lint(
                        cx,
                        UNIT_EXPR,
                        expr.span,
                        "This expression evaluates to the Unit type ()",
                        span,
                        "Consider removing the trailing semicolon",
                    );
                }
            }
        }
    }

    fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) {
        if let StmtKind::Local(ref local) = stmt.node {
            if local.pat.node == PatKind::Wild {
                return;
            }
            if let Some(ref expr) = local.init {
                if let Some(span) = is_unit_expr(expr) {
                    span_note_and_lint(
                        cx,
                        UNIT_EXPR,
                        expr.span,
                        "This expression evaluates to the Unit type ()",
                        span,
                        "Consider removing the trailing semicolon",
                    );
                }
            }
        }
    }
}
fn is_unit_expr(expr: &Expr) -> Option<Span> {
    match expr.node {
        ExprKind::Block(ref block) => if check_last_stmt_in_block(block) {
            Some(block.stmts[block.stmts.len() - 1].span)
        } else {
            None
        },
        ExprKind::If(_, ref then, ref else_) => {
            let check_then = check_last_stmt_in_block(then);
            if let Some(ref else_) = *else_ {
                let check_else = is_unit_expr(else_);
                if let Some(ref expr_else) = check_else {
                    return Some(*expr_else);
                }
            }
            if check_then {
                Some(expr.span)
            } else {
                None
            }
        },
        ExprKind::Match(ref _pattern, ref arms) => {
            for arm in arms {
                if let Some(expr) = is_unit_expr(&arm.body) {
                    return Some(expr);
                }
            }
            None
        },
        _ => None,
    }
}

fn check_last_stmt_in_block(block: &Block) -> bool {
    let final_stmt = &block.stmts[block.stmts.len() - 1];

    match final_stmt.node {
        StmtKind::Expr(_) => false,
        StmtKind::Semi(ref expr) => match expr.node {
            ExprKind::Break(_, _) | ExprKind::Ret(_) => false,
            _ => true,
        },
        _ => true,
    }
}
<commit_msg>Mention the false positive<commit_after>use rustc::lint::*;
use syntax::ast::*;
use syntax::ext::quote::rt::Span;
use utils::span_note_and_lint;

/// **What it does:** Checks for
///  - () being assigned to a variable
///  - () being passed to a function
///
/// **Why is this bad?** It is extremely unlikely that a user intended to
/// assign '()' to valiable. Instead,
/// Unit is what a block evaluates to when it returns nothing. This is
/// typically caused by a trailing
///   unintended semicolon.
///
/// **Known problems:** None.
///
/// **Example:**
/// * `let x = {"foo" ;}` when the user almost certainly intended `let x
/// ={"foo"}`

declare_lint! {
    pub UNIT_EXPR,
    Warn,
    "unintended assignment or use of a unit typed value"
}

#[derive(Copy, Clone)]
pub struct UnitExpr;

impl LintPass for UnitExpr {
    fn get_lints(&self) -> LintArray {
        lint_array!(UNIT_EXPR)
    }
}

impl EarlyLintPass for UnitExpr {
    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
        if let ExprKind::Assign(ref _left, ref right) = expr.node {
            if let Some(span) = is_unit_expr(right) {
                span_note_and_lint(
                    cx,
                    UNIT_EXPR,
                    expr.span,
                        "This expression evaluates to the Unit type ()",
                    span,
                    "Consider removing the trailing semicolon",
                );
            }
        }
        if let ExprKind::MethodCall(ref _left, ref args) = expr.node {
            for arg in args {
                if let Some(span) = is_unit_expr(arg) {
                    span_note_and_lint(
                        cx,
                        UNIT_EXPR,
                        expr.span,
                        "This expression evaluates to the Unit type ()",
                        span,
                        "Consider removing the trailing semicolon",
                    );
                }
            }
        }
        if let ExprKind::Call(_, ref args) = expr.node {
            for arg in args {
                if let Some(span) = is_unit_expr(arg) {
                    span_note_and_lint(
                        cx,
                        UNIT_EXPR,
                        expr.span,
                        "This expression evaluates to the Unit type ()",
                        span,
                        "Consider removing the trailing semicolon",
                    );
                }
            }
        }
    }

    fn check_stmt(&mut self, cx: &EarlyContext, stmt: &Stmt) {
        if let StmtKind::Local(ref local) = stmt.node {
            if local.pat.node == PatKind::Wild {
                return;
            }
            if let Some(ref expr) = local.init {
                if let Some(span) = is_unit_expr(expr) {
                    span_note_and_lint(
                        cx,
                        UNIT_EXPR,
                        expr.span,
                        "This expression evaluates to the Unit type ()",
                        span,
                        "Consider removing the trailing semicolon",
                    );
                }
            }
        }
    }
}
fn is_unit_expr(expr: &Expr) -> Option<Span> {
    match expr.node {
        ExprKind::Block(ref block) => if check_last_stmt_in_block(block) {
            Some(block.stmts[block.stmts.len() - 1].span)
        } else {
            None
        },
        ExprKind::If(_, ref then, ref else_) => {
            let check_then = check_last_stmt_in_block(then);
            if let Some(ref else_) = *else_ {
                let check_else = is_unit_expr(else_);
                if let Some(ref expr_else) = check_else {
                    return Some(*expr_else);
                }
            }
            if check_then {
                Some(expr.span)
            } else {
                None
            }
        },
        ExprKind::Match(ref _pattern, ref arms) => {
            for arm in arms {
                if let Some(expr) = is_unit_expr(&arm.body) {
                    return Some(expr);
                }
            }
            None
        },
        _ => None,
    }
}

fn check_last_stmt_in_block(block: &Block) -> bool {
    let final_stmt = &block.stmts[block.stmts.len() - 1];

    //Made a choice here to risk false positives on divergent macro invocations like `panic!()`
    match final_stmt.node {
        StmtKind::Expr(_) => false,
        StmtKind::Semi(ref expr) => match expr.node {
            ExprKind::Break(_, _) | ExprKind::Ret(_) => false,
            _ => true,
        },
        _ => true,
    }
}
<|endoftext|>


<commit_before>// use std::io::File;
use std::os;
use std::fmt;

#[repr(C)]
struct Complex {
    re: f32,
    im: f32,
}

#[link(name = "m")]
extern {
    fn csqrtf(z: Complex) -> Complex;
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        println!("open \"{}\" ...", args[1]);
        let z = Complex { re: -1.0, im: 0.0 };
        let z_sqrt = unsafe {
            csqrtf(z)
        };
        println!("the square root of {} is {}", z, z_sqrt);
    }
}

impl fmt::Show for Complex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < 0. {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}
<commit_msg>Read 7 bytes from file (should be "BLENDER") and close file again.<commit_after>use std::io::File;
use std::os;
use std::fmt;

#[repr(C)]
struct Complex {
    re: f32,
    im: f32,
}

#[link(name = "m")]
extern {
    fn csqrtf(z: Complex) -> Complex;
}

fn main() {
    let args = os::args();
    if args.len() != 2 {
        println!("usage: read_blend_file /path/to/file.blend");
    } else {
        let slice: &str = args[1].as_slice();
        println!("open \"{}\" ...", slice);
        {
            // read 7 bytes from the Blender file
            let path = Path::new(slice);
            let display = path.display();
            let mut file = match File::open(&path) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(file) => file,
            };
            let mut buf = [0u8, ..7];
            match file.read(buf) {
                Err(why) => fail!("couldn't open {}: {}", display, why.desc),
                Ok(_) => (),
            }
            println!("bytes read: {}{}{}{}{}{}{}",
                     buf[0] as char,
                     buf[1] as char,
                     buf[2] as char,
                     buf[3] as char,
                     buf[4] as char,
                     buf[5] as char,
                     buf[6] as char);
            // TODO: assert 7 bytes read are "BLENDER"
        } // file gets closed here
        // code below is temporary
        let z = Complex { re: -1.0, im: 0.0 };
        let z_sqrt = unsafe {
            csqrtf(z)
        };
        println!("the square root of {} is {}", z, z_sqrt);
    }
}

impl fmt::Show for Complex {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.im < 0. {
            write!(f, "{}-{}i", self.re, -self.im)
        } else {
            write!(f, "{}+{}i", self.re, self.im)
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate toml;
extern crate regex;

use base::math::*;
use self::clap::{App, Arg};
use self::regex::Regex;

pub struct Config {
    pub resolution: Dimension2u,
    pub window_mode: WindowMode,
    pub window_title: String,
    //sichtweite
    //Vsync
    //kantenglättung
    //steuerung
    //frames
    //seed
    //Chunkweite
}
impl Config{
    pub fn load_config() -> Config{
        let mut conf = Config::default();
        command_config(conf)
    }
}

impl Default for Config {
    fn default() -> Self {
        Config {
            resolution: Dimension2::new(1280, 720),
            window_mode: WindowMode::Windowed,
            window_title: format!("Plantex {}", env!("CARGO_PKG_VERSION")),
        }
    }
}

fn command_config(mut toml_config: Config) -> Config{
    let matches = App::new("Plantex")

        .arg(Arg::with_name("Resolution")
            .help("sets the Resolution to use")
            .takes_value(true)
            .long("resolution")
        )
        .get_matches();

    if let Some(ref res) = matches.value_of("Resolution"){
        let reg_res = Regex::new(r"^[1-9]\d{1,4}x[1-9]\d{1,4}").unwrap();
        if reg_res.is_match(res){
            let mut split_res = res.split("x");
            let vec_res = split_res.collect::<Vec<&str>>();
            let res_x = vec_res[0].parse::<u32>().unwrap();
            let res_y = vec_res[1].parse::<u32>().unwrap();
            toml_config.resolution = Dimension2::new(res_x, res_y);
        }else{}
    }

    toml_config
}
pub enum WindowMode {
    Windowed,
    // FullScreenWindow, // TODO: maybe add this
    FullScreen,
}
<commit_msg>edit help command<commit_after>extern crate clap;
extern crate toml;
extern crate regex;

use base::math::*;
use self::clap::{App, Arg};
use self::regex::Regex;

pub struct Config {
    pub resolution: Dimension2u,
    pub window_mode: WindowMode,
    pub window_title: String,
    //sichtweite
    //Vsync
    //kantenglättung
    //steuerung
    //frames
    //seed
    //Chunkweite
}
impl Config{
    pub fn load_config() -> Config{
        let mut conf = Config::default();
        command_config(conf)
    }
}

impl Default for Config {
    fn default() -> Self {
        Config {
            resolution: Dimension2::new(1280, 720),
            window_mode: WindowMode::Windowed,
            window_title: format!("Plantex {}", env!("CARGO_PKG_VERSION")),
        }
    }
}

fn command_config(mut toml_config: Config) -> Config{
    let matches = App::new("Plantex")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Game about Plants!")

        .arg(Arg::with_name("Resolution")
            .help("(e.g. =1280x720) 'Sets Resolution to new value'")
            .takes_value(true)
            .long("resolution")
        )
        .get_matches();

    if let Some(ref res) = matches.value_of("Resolution"){
        let reg_res = Regex::new(r"^[1-9]\d{1,4}x[1-9]\d{1,4}").unwrap();
        if reg_res.is_match(res){
            let mut split_res = res.split("x");
            let vec_res = split_res.collect::<Vec<&str>>();
            let res_x = vec_res[0].parse::<u32>().unwrap();
            let res_y = vec_res[1].parse::<u32>().unwrap();
            toml_config.resolution = Dimension2::new(res_x, res_y);
        }else{}
    }

    toml_config
}
pub enum WindowMode {
    Windowed,
    // FullScreenWindow, // TODO: maybe add this
    FullScreen,
}
<|endoftext|>


<commit_before>use log::info;
use parking_lot::Mutex;
use std::path::*;
use std::str::FromStr;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};

pub mod block;
pub mod index;
pub mod store;

pub use self::block::*;
pub use self::index::Indexer;
pub use self::store::BlockStore;

use crate::asset::{self, Asset, Balance};
use crate::crypto::*;
use crate::script::*;
use crate::tx::*;

pub struct Blockchain {
    indexer: Arc<Indexer>,
    store: Mutex<BlockStore>,
}

#[derive(Clone, Debug)]
pub struct Properties {
    pub height: u64,
    pub token_supply: Balance,
    pub network_fee: Balance,
}

impl Blockchain {
    ///
    /// Creates a new `Blockchain` with an associated indexer and backing
    /// storage is automatically created based on the given `path`.
    ///
    pub fn new(path: &Path) -> Blockchain {
        let indexer = Arc::new(Indexer::new(&Path::join(path, "index")));
        let store = BlockStore::new(&Path::join(path, "blklog"), Arc::clone(&indexer));
        Blockchain {
            indexer,
            store: Mutex::new(store),
        }
    }

    pub fn get_properties(&self) -> Properties {
        Properties {
            height: self.get_chain_height(),
            token_supply: self.indexer.get_token_supply(),
            network_fee: self
                .get_network_fee()
                .expect("unexpected error retrieving network fee"),
        }
    }

    #[inline(always)]
    pub fn get_owner(&self) -> OwnerTx {
        self.indexer.get_owner().expect("Failed to retrieve owner from index")
    }

    #[inline(always)]
    pub fn get_chain_height(&self) -> u64 {
        self.indexer.get_chain_height()
    }

    pub fn get_chain_head(&self) -> Arc<SignedBlock> {
        let store = self.store.lock();
        let height = store.get_chain_height();
        store.get(height).expect("Failed to get blockchain head")
    }

    pub fn get_block(&self, height: u64) -> Option<Arc<SignedBlock>> {
        let store = self.store.lock();
        store.get(height)
    }

    pub fn get_total_fee(&self, hash: &ScriptHash) -> Option<Balance> {
        let net_fee = self.get_network_fee()?;
        let addr_fee = self.get_address_fee(hash)?;
        Some(Balance {
            gold: net_fee.gold.add(&addr_fee.gold)?,
            silver: net_fee.silver.add(&addr_fee.silver)?,
        })
    }

    pub fn get_address_fee(&self, hash: &ScriptHash) -> Option<Balance> {
        use crate::constants::*;

        let mut tx_count = 1;
        let head = self.get_chain_height();
        for (delta, i) in (0..=head).rev().enumerate() {
            let block = self.get_block(i).unwrap();
            for tx in &block.transactions {
                let has_match = match tx {
                    TxVariant::OwnerTx(_) => false,
                    TxVariant::RewardTx(_) => false,
                    TxVariant::TransferTx(tx) => &tx.from == hash,
                };
                if has_match {
                    tx_count += 1;
                }
            }
            if delta + 1 == FEE_RESET_WINDOW {
                break;
            }
        }

        let prec = asset::MAX_PRECISION;
        let gold = GOLD_FEE_MIN.mul(&GOLD_FEE_MULT.pow(tx_count as u16, prec)?, prec)?;
        let silver = SILVER_FEE_MIN.mul(&SILVER_FEE_MULT.pow(tx_count as u16, prec)?, prec)?;
        Some(Balance { gold, silver })
    }

    pub fn get_network_fee(&self) -> Option<Balance> {
        // The network fee adjusts every 5 blocks so that users have a bigger time
        // frame to confirm the fee they want to spend without suddenly changing.
        use crate::constants::*;
        let max_height = self.get_chain_height();
        let max_height = max_height - (max_height % 5);
        let min_height = if max_height > NETWORK_FEE_AVG_WINDOW {
            max_height - NETWORK_FEE_AVG_WINDOW
        } else {
            0
        };

        let mut tx_count: u64 = 1;
        for i in min_height..=max_height {
            tx_count += self.get_block(i).unwrap().transactions.len() as u64;
        }
        tx_count /= NETWORK_FEE_AVG_WINDOW;
        if tx_count > u64::from(u16::max_value()) {
            return None;
        }

        let prec = asset::MAX_PRECISION;
        let gold = GOLD_FEE_MIN.mul(&GOLD_FEE_NET_MULT.pow(tx_count as u16, prec)?, prec)?;
        let silver = SILVER_FEE_MIN.mul(&SILVER_FEE_NET_MULT.pow(tx_count as u16, prec)?, prec)?;

        Some(Balance { gold, silver })
    }

    pub fn get_balance(&self, hash: &ScriptHash) -> Balance {
        self.indexer.get_balance(hash).unwrap_or_default()
    }

    pub fn get_balance_with_txs(&self, hash: &ScriptHash, txs: &[TxVariant]) -> Option<Balance> {
        let mut bal = self.indexer.get_balance(hash).unwrap_or_default();
        for tx in txs {
            match tx {
                TxVariant::OwnerTx(_) => {}
                TxVariant::RewardTx(tx) => {
                    if &tx.to == hash {
                        for reward in &tx.rewards {
                            bal.add(&reward)?;
                        }
                    }
                }
                TxVariant::TransferTx(tx) => {
                    if &tx.from == hash {
                        bal.sub(&tx.fee)?;
                        bal.sub(&tx.amount)?;
                    } else if &tx.to == hash {
                        bal.add(&tx.amount)?;
                    }
                }
            }
        }

        Some(bal)
    }

    pub fn insert_block(&self, block: SignedBlock) -> Result<(), String> {
        self.verify_block(&block, &self.get_chain_head())?;
        for tx in &block.transactions {
            self.index_tx(tx);
        }
        self.store.lock().insert(block);

        Ok(())
    }

    fn verify_block(&self, block: &SignedBlock, prev_block: &SignedBlock) -> Result<(), String> {
        if prev_block.height + 1 != block.height {
            return Err("invalid block height".to_owned());
        } else if !block.verify_tx_merkle_root() {
            return Err("invalid merkle root".to_owned());
        } else if !block.verify_previous_hash(prev_block) {
            return Err("invalid previous hash".to_owned());
        }

        let owner = self.get_owner();
        if !block.sig_pair.verify(block.calc_hash().as_ref()) {
            return Err("invalid block signature".to_owned());
        } else if block.sig_pair.pub_key != owner.minter {
            return Err("invalid owner signature".to_owned());
        }

        let len = block.transactions.len();
        for i in 0..len {
            let tx = &block.transactions[i];
            let txs = &block.transactions[0..i];
            if let Err(s) = self.verify_tx(tx, txs) {
                return Err(format!("tx verification failed: {}", s));
            }
        }

        Ok(())
    }

    pub fn verify_tx(&self, tx: &TxVariant, additional_txs: &[TxVariant]) -> Result<(), String> {
        macro_rules! check_amt {
            ($asset:expr, $name:expr) => {
                if $asset.amount < 0 {
                    return Err(format!("{} must be greater than 0", $name));
                }
            };
        }

        macro_rules! check_suf_bal {
            ($asset:expr) => {
                if $asset.amount < 0 {
                    return Err("insufficient balance".to_owned());
                }
            };
        }

        check_amt!(tx.fee, "fee");
        match tx {
            TxVariant::OwnerTx(tx) => {
                let pairs = &tx.signature_pairs;
                if pairs.len() != 2 {
                    return Err("not enough signatures to change ownership".to_owned());
                }
                let owner = self.get_owner();
                if !(pairs[0].pub_key == owner.minter && pairs[1].pub_key == tx.wallet) {
                    return Err("signatures don't match previous ownership".to_owned())
                }
                let mut buf = Vec::with_capacity(4096);
                tx.encode(&mut buf);
                for sig_pair in &tx.signature_pairs {
                    if !sig_pair.verify(&buf) {
                        return Err("signature validation failed".to_owned())
                    }
                }
            }
            TxVariant::RewardTx(tx) => {
                if !tx.signature_pairs.is_empty() {
                    return Err("reward transaction must not be signed".to_owned());
                }
            }
            TxVariant::TransferTx(transfer) => {
                if transfer.fee.symbol != transfer.amount.symbol {
                    return Err("symbol mismatch between fee and amount".to_owned());
                } else if transfer.from != ScriptHash::from(&transfer.script) {
                    return Err("from and script hash mismatch".to_owned());
                }

                let success = ScriptEngine::checked_new(tx, &transfer.script)
                    .ok_or_else(|| "failed to initialize script engine")?
                    .eval()
                    .map_err(|e| format!("{}: {:?}", e.pos, e.err))?;
                if !success {
                    return Err("script returned false".to_owned());
                }

                let mut bal = self
                    .get_balance_with_txs(&transfer.from, additional_txs)
                    .ok_or_else(|| "failed to get balance")?;
                bal.sub(&transfer.fee)
                    .ok_or("failed to subtract fee")?
                    .sub(&transfer.amount)
                    .ok_or("failed to subtract amount")?;
                check_suf_bal!(&bal.gold);
                check_suf_bal!(&bal.silver);
            }
        }
        Ok(())
    }

    fn index_tx(&self, tx: &TxVariant) {
        match tx {
            TxVariant::OwnerTx(tx) => {
                self.indexer.set_owner(tx);
            }
            TxVariant::RewardTx(tx) => {
                let mut bal = self.get_balance(&tx.to);
                let mut supply = self.indexer.get_token_supply();
                for r in &tx.rewards {
                    bal.add(r).unwrap();
                    supply.add(r).unwrap();
                }
                self.indexer.set_balance(&tx.to, &bal);
                self.indexer.set_token_supply(&supply);
            }
            TxVariant::TransferTx(tx) => {
                let mut from_bal = self.get_balance(&tx.from);
                let mut to_bal = self.get_balance(&tx.to);

                from_bal.sub(&tx.fee).unwrap().sub(&tx.amount).unwrap();
                to_bal.add(&tx.amount).unwrap();

                self.indexer.set_balance(&tx.from, &from_bal);
                self.indexer.set_balance(&tx.to, &to_bal);
            }
        }
    }

    pub fn create_genesis_block(&self, minter_key: &KeyPair) {
        use sodiumoxide::crypto::hash::sha256::Digest;

        info!("=> Generating new block chain");
        let wallet_key = KeyPair::gen_keypair();
        info!("=> Wallet private key: {}", wallet_key.1.to_wif());
        info!("=> Wallet public key: {}", wallet_key.0.to_wif());

        let timestamp = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs() as u32;

        let owner_tx = OwnerTx {
            base: Tx {
                tx_type: TxType::OWNER,
                fee: Asset::from_str("0 GOLD").unwrap(),
                timestamp,
                signature_pairs: Vec::new(),
            },
            minter: minter_key.0.clone(),
            wallet: wallet_key.0.clone().into(),
        };

        let transactions = {
            let mut vec = Vec::with_capacity(2);
            vec.push(TxVariant::RewardTx(RewardTx {
                base: Tx {
                    tx_type: TxType::REWARD,
                    fee: Asset::from_str("0 GOLD").unwrap(),
                    timestamp,
                    signature_pairs: Vec::new(),
                },
                to: wallet_key.0.into(),
                rewards: vec![Asset::from_str("1 GOLD").unwrap()],
            }));
            vec.push(TxVariant::OwnerTx(owner_tx.clone()));
            vec
        };

        let block = (Block {
            height: 0,
            previous_hash: Digest::from_slice(&[0u8; 32]).unwrap(),
            tx_merkle_root: Digest::from_slice(&[0u8; 32]).unwrap(),
            timestamp: timestamp as u32,
            transactions,
        })
        .sign(&minter_key);

        self.store.lock().insert_genesis(block);
        self.indexer.set_owner(&owner_tx);
    }
}
<commit_msg>Remove genesis reward tx<commit_after>use log::info;
use parking_lot::Mutex;
use std::path::*;
use std::str::FromStr;
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};

pub mod block;
pub mod index;
pub mod store;

pub use self::block::*;
pub use self::index::Indexer;
pub use self::store::BlockStore;

use crate::asset::{self, Asset, Balance};
use crate::crypto::*;
use crate::script::*;
use crate::tx::*;

pub struct Blockchain {
    indexer: Arc<Indexer>,
    store: Mutex<BlockStore>,
}

#[derive(Clone, Debug)]
pub struct Properties {
    pub height: u64,
    pub token_supply: Balance,
    pub network_fee: Balance,
}

impl Blockchain {
    ///
    /// Creates a new `Blockchain` with an associated indexer and backing
    /// storage is automatically created based on the given `path`.
    ///
    pub fn new(path: &Path) -> Blockchain {
        let indexer = Arc::new(Indexer::new(&Path::join(path, "index")));
        let store = BlockStore::new(&Path::join(path, "blklog"), Arc::clone(&indexer));
        Blockchain {
            indexer,
            store: Mutex::new(store),
        }
    }

    pub fn get_properties(&self) -> Properties {
        Properties {
            height: self.get_chain_height(),
            token_supply: self.indexer.get_token_supply(),
            network_fee: self
                .get_network_fee()
                .expect("unexpected error retrieving network fee"),
        }
    }

    #[inline(always)]
    pub fn get_owner(&self) -> OwnerTx {
        self.indexer.get_owner().expect("Failed to retrieve owner from index")
    }

    #[inline(always)]
    pub fn get_chain_height(&self) -> u64 {
        self.indexer.get_chain_height()
    }

    pub fn get_chain_head(&self) -> Arc<SignedBlock> {
        let store = self.store.lock();
        let height = store.get_chain_height();
        store.get(height).expect("Failed to get blockchain head")
    }

    pub fn get_block(&self, height: u64) -> Option<Arc<SignedBlock>> {
        let store = self.store.lock();
        store.get(height)
    }

    pub fn get_total_fee(&self, hash: &ScriptHash) -> Option<Balance> {
        let net_fee = self.get_network_fee()?;
        let addr_fee = self.get_address_fee(hash)?;
        Some(Balance {
            gold: net_fee.gold.add(&addr_fee.gold)?,
            silver: net_fee.silver.add(&addr_fee.silver)?,
        })
    }

    pub fn get_address_fee(&self, hash: &ScriptHash) -> Option<Balance> {
        use crate::constants::*;

        let mut tx_count = 1;
        let head = self.get_chain_height();
        for (delta, i) in (0..=head).rev().enumerate() {
            let block = self.get_block(i).unwrap();
            for tx in &block.transactions {
                let has_match = match tx {
                    TxVariant::OwnerTx(_) => false,
                    TxVariant::RewardTx(_) => false,
                    TxVariant::TransferTx(tx) => &tx.from == hash,
                };
                if has_match {
                    tx_count += 1;
                }
            }
            if delta + 1 == FEE_RESET_WINDOW {
                break;
            }
        }

        let prec = asset::MAX_PRECISION;
        let gold = GOLD_FEE_MIN.mul(&GOLD_FEE_MULT.pow(tx_count as u16, prec)?, prec)?;
        let silver = SILVER_FEE_MIN.mul(&SILVER_FEE_MULT.pow(tx_count as u16, prec)?, prec)?;
        Some(Balance { gold, silver })
    }

    pub fn get_network_fee(&self) -> Option<Balance> {
        // The network fee adjusts every 5 blocks so that users have a bigger time
        // frame to confirm the fee they want to spend without suddenly changing.
        use crate::constants::*;
        let max_height = self.get_chain_height();
        let max_height = max_height - (max_height % 5);
        let min_height = if max_height > NETWORK_FEE_AVG_WINDOW {
            max_height - NETWORK_FEE_AVG_WINDOW
        } else {
            0
        };

        let mut tx_count: u64 = 1;
        for i in min_height..=max_height {
            tx_count += self.get_block(i).unwrap().transactions.len() as u64;
        }
        tx_count /= NETWORK_FEE_AVG_WINDOW;
        if tx_count > u64::from(u16::max_value()) {
            return None;
        }

        let prec = asset::MAX_PRECISION;
        let gold = GOLD_FEE_MIN.mul(&GOLD_FEE_NET_MULT.pow(tx_count as u16, prec)?, prec)?;
        let silver = SILVER_FEE_MIN.mul(&SILVER_FEE_NET_MULT.pow(tx_count as u16, prec)?, prec)?;

        Some(Balance { gold, silver })
    }

    pub fn get_balance(&self, hash: &ScriptHash) -> Balance {
        self.indexer.get_balance(hash).unwrap_or_default()
    }

    pub fn get_balance_with_txs(&self, hash: &ScriptHash, txs: &[TxVariant]) -> Option<Balance> {
        let mut bal = self.indexer.get_balance(hash).unwrap_or_default();
        for tx in txs {
            match tx {
                TxVariant::OwnerTx(_) => {}
                TxVariant::RewardTx(tx) => {
                    if &tx.to == hash {
                        for reward in &tx.rewards {
                            bal.add(&reward)?;
                        }
                    }
                }
                TxVariant::TransferTx(tx) => {
                    if &tx.from == hash {
                        bal.sub(&tx.fee)?;
                        bal.sub(&tx.amount)?;
                    } else if &tx.to == hash {
                        bal.add(&tx.amount)?;
                    }
                }
            }
        }

        Some(bal)
    }

    pub fn insert_block(&self, block: SignedBlock) -> Result<(), String> {
        self.verify_block(&block, &self.get_chain_head())?;
        for tx in &block.transactions {
            self.index_tx(tx);
        }
        self.store.lock().insert(block);

        Ok(())
    }

    fn verify_block(&self, block: &SignedBlock, prev_block: &SignedBlock) -> Result<(), String> {
        if prev_block.height + 1 != block.height {
            return Err("invalid block height".to_owned());
        } else if !block.verify_tx_merkle_root() {
            return Err("invalid merkle root".to_owned());
        } else if !block.verify_previous_hash(prev_block) {
            return Err("invalid previous hash".to_owned());
        }

        let owner = self.get_owner();
        if !block.sig_pair.verify(block.calc_hash().as_ref()) {
            return Err("invalid block signature".to_owned());
        } else if block.sig_pair.pub_key != owner.minter {
            return Err("invalid owner signature".to_owned());
        }

        let len = block.transactions.len();
        for i in 0..len {
            let tx = &block.transactions[i];
            let txs = &block.transactions[0..i];
            if let Err(s) = self.verify_tx(tx, txs) {
                return Err(format!("tx verification failed: {}", s));
            }
        }

        Ok(())
    }

    pub fn verify_tx(&self, tx: &TxVariant, additional_txs: &[TxVariant]) -> Result<(), String> {
        macro_rules! check_amt {
            ($asset:expr, $name:expr) => {
                if $asset.amount < 0 {
                    return Err(format!("{} must be greater than 0", $name));
                }
            };
        }

        macro_rules! check_suf_bal {
            ($asset:expr) => {
                if $asset.amount < 0 {
                    return Err("insufficient balance".to_owned());
                }
            };
        }

        check_amt!(tx.fee, "fee");
        match tx {
            TxVariant::OwnerTx(tx) => {
                let pairs = &tx.signature_pairs;
                if pairs.len() != 2 {
                    return Err("not enough signatures to change ownership".to_owned());
                }
                let owner = self.get_owner();
                if !(pairs[0].pub_key == owner.minter && pairs[1].pub_key == tx.wallet) {
                    return Err("signatures don't match previous ownership".to_owned())
                }
                let mut buf = Vec::with_capacity(4096);
                tx.encode(&mut buf);
                for sig_pair in &tx.signature_pairs {
                    if !sig_pair.verify(&buf) {
                        return Err("signature validation failed".to_owned())
                    }
                }
            }
            TxVariant::RewardTx(tx) => {
                if !tx.signature_pairs.is_empty() {
                    return Err("reward transaction must not be signed".to_owned());
                }
            }
            TxVariant::TransferTx(transfer) => {
                if transfer.fee.symbol != transfer.amount.symbol {
                    return Err("symbol mismatch between fee and amount".to_owned());
                } else if transfer.from != ScriptHash::from(&transfer.script) {
                    return Err("from and script hash mismatch".to_owned());
                }

                let success = ScriptEngine::checked_new(tx, &transfer.script)
                    .ok_or_else(|| "failed to initialize script engine")?
                    .eval()
                    .map_err(|e| format!("{}: {:?}", e.pos, e.err))?;
                if !success {
                    return Err("script returned false".to_owned());
                }

                let mut bal = self
                    .get_balance_with_txs(&transfer.from, additional_txs)
                    .ok_or_else(|| "failed to get balance")?;
                bal.sub(&transfer.fee)
                    .ok_or("failed to subtract fee")?
                    .sub(&transfer.amount)
                    .ok_or("failed to subtract amount")?;
                check_suf_bal!(&bal.gold);
                check_suf_bal!(&bal.silver);
            }
        }
        Ok(())
    }

    fn index_tx(&self, tx: &TxVariant) {
        match tx {
            TxVariant::OwnerTx(tx) => {
                self.indexer.set_owner(tx);
            }
            TxVariant::RewardTx(tx) => {
                let mut bal = self.get_balance(&tx.to);
                let mut supply = self.indexer.get_token_supply();
                for r in &tx.rewards {
                    bal.add(r).unwrap();
                    supply.add(r).unwrap();
                }
                self.indexer.set_balance(&tx.to, &bal);
                self.indexer.set_token_supply(&supply);
            }
            TxVariant::TransferTx(tx) => {
                let mut from_bal = self.get_balance(&tx.from);
                let mut to_bal = self.get_balance(&tx.to);

                from_bal.sub(&tx.fee).unwrap().sub(&tx.amount).unwrap();
                to_bal.add(&tx.amount).unwrap();

                self.indexer.set_balance(&tx.from, &from_bal);
                self.indexer.set_balance(&tx.to, &to_bal);
            }
        }
    }

    pub fn create_genesis_block(&self, minter_key: &KeyPair) {
        use sodiumoxide::crypto::hash::sha256::Digest;

        info!("=> Generating new block chain");
        let wallet_key = KeyPair::gen_keypair();
        info!("=> Wallet private key: {}", wallet_key.1.to_wif());
        info!("=> Wallet public key: {}", wallet_key.0.to_wif());

        let timestamp = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs() as u32;

        let owner_tx = OwnerTx {
            base: Tx {
                tx_type: TxType::OWNER,
                fee: Asset::from_str("0 GOLD").unwrap(),
                timestamp,
                signature_pairs: Vec::new(),
            },
            minter: minter_key.0.clone(),
            wallet: wallet_key.0.clone().into(),
        };

        let block = (Block {
            height: 0,
            previous_hash: Digest::from_slice(&[0u8; 32]).unwrap(),
            tx_merkle_root: Digest::from_slice(&[0u8; 32]).unwrap(),
            timestamp: timestamp as u32,
            transactions: vec![TxVariant::OwnerTx(owner_tx.clone())],
        })
        .sign(&minter_key);

        self.store.lock().insert_genesis(block);
        self.indexer.set_owner(&owner_tx);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::database::PgPoolConnection;
use crate::{
    models::events::{Event, EventModel},
    schema::{block_metadata_transactions, transactions, user_transactions},
};
use aptos_rest_client::aptos_api_types::{
    BlockMetadataTransaction as APIBlockMetadataTransaction, Transaction as APITransaction,
    TransactionInfo, UserTransaction as APIUserTransaction, U64,
};
use diesel::RunQueryDsl;
use futures::future::Either;

#[derive(Debug, Queryable, Insertable, AsChangeset)]
#[diesel(table_name = "transactions")]
pub struct Transaction {
    #[diesel(column_name = type)]
    pub type_: String,
    pub payload: serde_json::Value,
    pub version: i64,
    pub hash: String,
    pub state_root_hash: String,
    pub event_root_hash: String,
    pub gas_used: i64,
    pub success: bool,
    pub vm_status: String,
    pub accumulator_root_hash: String,
    // Default time columns
    pub inserted_at: chrono::NaiveDateTime,
}

impl Transaction {
    pub fn get_by_hash(transaction_hash: String, connection: &PgPoolConnection) {
        let transactions = transactions::table.load::<Transaction>(connection)?;
        let user_transactions = UserTransaction::belonging_to(&transactions)
            .load::<UserTransaction>(&connection)?
            .grouped_by(&users);
        let block_metadata_transactions = BlockMetadataTransaction::belonging_to(&transactions)
            .load::<BlockMetadataTransaction>(&connection)?
            .grouped_by(&users);
        (transactions, user_transactions, block_metadata_transactions)
    }

    pub fn get_by_version(version: u64) {}

    pub fn from_transaction(
        transaction: &APITransaction,
    ) -> (
        Transaction,
        Option<Either<UserTransaction, BlockMetadataTransaction>>,
        Option<Vec<Event>>,
    ) {
        match transaction {
            APITransaction::UserTransaction(tx) => (
                Self::from_transaction_info(
                    &tx.info,
                    serde_json::to_value(&tx.request.payload).unwrap(),
                    transaction.type_str().to_string(),
                ),
                Some(Either::Left(UserTransaction::from_transaction(tx))),
                EventModel::from_events(tx.info.hash.to_string(), &tx.events),
            ),
            APITransaction::GenesisTransaction(tx) => (
                Self::from_transaction_info(
                    &tx.info,
                    serde_json::to_value(&tx.payload).unwrap(),
                    transaction.type_str().to_string(),
                ),
                None,
                EventModel::from_events(tx.info.hash.to_string(), &tx.events),
            ),
            APITransaction::BlockMetadataTransaction(tx) => (
                Self::from_transaction_info(
                    &tx.info,
                    serde_json::Value::Null,
                    transaction.type_str().to_string(),
                ),
                Some(Either::Right(BlockMetadataTransaction::from_transaction(
                    tx,
                ))),
                None,
            ),
            _ => unreachable!(),
        }
    }

    fn from_transaction_info(
        info: &TransactionInfo,
        payload: serde_json::Value,
        type_: String,
    ) -> Self {
        Self {
            type_,
            payload,
            version: *info.version.inner() as i64,
            hash: info.hash.to_string(),
            state_root_hash: info.state_root_hash.to_string(),
            event_root_hash: info.event_root_hash.to_string(),
            gas_used: *info.gas_used.inner() as i64,
            success: info.success,
            vm_status: info.vm_status.clone(),
            accumulator_root_hash: info.accumulator_root_hash.to_string(),
            inserted_at: chrono::Utc::now().naive_utc(),
        }
    }
}

#[derive(Debug, Queryable, Insertable, AsChangeset, Associations)]
#[belongs_to(Transaction, foreign_key = "hash")]
#[diesel(table_name = "user_transactions")]
pub struct UserTransaction {
    pub hash: String,
    pub signature: serde_json::Value,
    pub sender: String,
    pub sequence_number: i64,
    pub max_gas_amount: i64,

    // from UserTransactionRequest
    pub expiration_timestamp_secs: chrono::NaiveDateTime,

    // from UserTransaction
    pub timestamp: chrono::NaiveDateTime,

    // Default time columns
    pub inserted_at: chrono::NaiveDateTime,
}

impl UserTransaction {
    pub fn from_transaction(tx: &APIUserTransaction) -> Self {
        Self {
            hash: tx.info.hash.to_string(),
            signature: serde_json::to_value(&tx.request.signature).unwrap(),
            sender: tx.request.sender.inner().to_hex_literal(),
            sequence_number: *tx.request.sequence_number.inner() as i64,
            max_gas_amount: *tx.request.max_gas_amount.inner() as i64,
            expiration_timestamp_secs: chrono::NaiveDateTime::from_timestamp(
                *tx.request.expiration_timestamp_secs.inner() as i64,
                0,
            ),
            timestamp: parse_timestamp(tx.timestamp, tx.info.version),
            inserted_at: chrono::Utc::now().naive_utc(),
        }
    }
}

#[derive(Debug, Queryable, Insertable, AsChangeset, Associations)]
#[belongs_to(Transaction, foreign_key = "hash")]
#[diesel(table_name = "block_metadata_transactions")]
pub struct BlockMetadataTransaction {
    pub hash: String,
    pub id: String,
    pub round: i64,
    pub previous_block_votes: serde_json::Value,
    pub proposer: String,
    pub timestamp: chrono::NaiveDateTime,

    // Default time columns
    pub inserted_at: chrono::NaiveDateTime,
}

impl BlockMetadataTransaction {
    pub fn from_transaction(tx: &APIBlockMetadataTransaction) -> Self {
        Self {
            hash: tx.info.hash.to_string(),
            id: tx.id.to_string(),
            round: *tx.round.inner() as i64,
            previous_block_votes: serde_json::to_value(&tx.previous_block_votes).unwrap(),
            proposer: tx.proposer.inner().to_hex_literal(),
            // time is in milliseconds, but chronos wants seconds
            timestamp: parse_timestamp(tx.timestamp, tx.info.version),
            inserted_at: chrono::Utc::now().naive_utc(),
        }
    }
}

fn parse_timestamp(ts: U64, version: U64) -> chrono::NaiveDateTime {
    chrono::NaiveDateTime::from_timestamp_opt(*ts.inner() as i64 / 1000000, 0)
        .unwrap_or_else(|| panic!("Could not parse timestamp {:?} for version {}", ts, version))
}

// Prevent conflicts with other things named `Transaction`
pub type BlockMetadataTransactionModel = BlockMetadataTransaction;
pub type TransactionModel = Transaction;
pub type UserTransactionModel = UserTransaction;
<commit_msg>Add query helpers<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

// This is required because a diesel macro makes clippy sad
#![allow(clippy::unused_unit)]

use crate::{
    database::PgPoolConnection,
    models::events::{Event, EventModel},
    schema::{block_metadata_transactions, transactions, user_transactions},
};
use aptos_rest_client::aptos_api_types::{
    BlockMetadataTransaction as APIBlockMetadataTransaction, Transaction as APITransaction,
    TransactionInfo, UserTransaction as APIUserTransaction, U64,
};
use diesel::{
    BelongingToDsl, ExpressionMethods, GroupedBy, OptionalExtension, QueryDsl, RunQueryDsl,
};
use futures::future::Either;

#[derive(Debug, Queryable, Insertable, AsChangeset, Identifiable)]
#[primary_key(hash)]
#[diesel(table_name = "transactions")]
pub struct Transaction {
    #[diesel(column_name = type)]
    pub type_: String,
    pub payload: serde_json::Value,
    pub version: i64,
    pub hash: String,
    pub state_root_hash: String,
    pub event_root_hash: String,
    pub gas_used: i64,
    pub success: bool,
    pub vm_status: String,
    pub accumulator_root_hash: String,
    // Default time columns
    pub inserted_at: chrono::NaiveDateTime,
}

impl Transaction {
    pub fn get_many_by_version(
        start_version: i64,
        number_to_get: i64,
        connection: &PgPoolConnection,
    ) -> diesel::QueryResult<
        Vec<(
            Transaction,
            Option<UserTransaction>,
            Option<BlockMetadataTransaction>,
        )>,
    > {
        let mut transactions = transactions::table
            .filter(transactions::version.ge(start_version))
            .limit(number_to_get)
            .load::<Transaction>(connection)?;

        let mut user_transactions: Vec<Vec<UserTransaction>> =
            UserTransaction::belonging_to(&transactions)
                .load::<UserTransaction>(connection)?
                .grouped_by(&transactions);

        let mut block_metadata_transactions: Vec<Vec<BlockMetadataTransaction>> =
            BlockMetadataTransaction::belonging_to(&transactions)
                .load::<BlockMetadataTransaction>(connection)?
                .grouped_by(&transactions);

        // Convert to the nice result tuple
        let mut result = vec![];
        while !transactions.is_empty() {
            result.push((
                transactions.pop().unwrap(),
                user_transactions.pop().unwrap().pop(),
                block_metadata_transactions.pop().unwrap().pop(),
            ))
        }

        Ok(result)
    }

    pub fn get_by_version(
        version: u64,
        connection: &PgPoolConnection,
    ) -> diesel::QueryResult<(
        Transaction,
        Option<UserTransaction>,
        Option<BlockMetadataTransaction>,
    )> {
        let transaction = transactions::table
            .filter(transactions::version.eq(version as i64))
            .first::<Transaction>(connection)?;

        let (user_transaction, block_metadata_transaction) =
            transaction.get_details_for_transaction(connection)?;

        Ok((transaction, user_transaction, block_metadata_transaction))
    }

    pub fn get_by_hash(
        transaction_hash: &str,
        connection: &PgPoolConnection,
    ) -> diesel::QueryResult<(
        Transaction,
        Option<UserTransaction>,
        Option<BlockMetadataTransaction>,
    )> {
        let transaction = transactions::table
            .filter(transactions::hash.eq(&transaction_hash))
            .first::<Transaction>(connection)?;

        let (user_transaction, block_metadata_transaction) =
            transaction.get_details_for_transaction(connection)?;

        Ok((transaction, user_transaction, block_metadata_transaction))
    }

    fn get_details_for_transaction(
        &self,
        connection: &PgPoolConnection,
    ) -> diesel::QueryResult<(Option<UserTransaction>, Option<BlockMetadataTransaction>)> {
        let mut user_transaction: Option<UserTransaction> = None;
        let mut block_metadata_transaction: Option<BlockMetadataTransaction> = None;

        match self.type_.as_str() {
            "user_transaction" => {
                user_transaction = user_transactions::table
                    .filter(user_transactions::hash.eq(&self.hash))
                    .first::<UserTransaction>(connection)
                    .optional()?;
            }
            "block_metadata_transaction" => {
                block_metadata_transaction = block_metadata_transactions::table
                    .filter(block_metadata_transactions::hash.eq(&self.hash))
                    .first::<BlockMetadataTransaction>(connection)
                    .optional()?;
            }
            _ => unreachable!("Unknown transaction type: {}", &self.type_),
        };
        Ok((user_transaction, block_metadata_transaction))
    }

    pub fn from_transaction(
        transaction: &APITransaction,
    ) -> (
        Transaction,
        Option<Either<UserTransaction, BlockMetadataTransaction>>,
        Option<Vec<Event>>,
    ) {
        match transaction {
            APITransaction::UserTransaction(tx) => (
                Self::from_transaction_info(
                    &tx.info,
                    serde_json::to_value(&tx.request.payload).unwrap(),
                    transaction.type_str().to_string(),
                ),
                Some(Either::Left(UserTransaction::from_transaction(tx))),
                EventModel::from_events(tx.info.hash.to_string(), &tx.events),
            ),
            APITransaction::GenesisTransaction(tx) => (
                Self::from_transaction_info(
                    &tx.info,
                    serde_json::to_value(&tx.payload).unwrap(),
                    transaction.type_str().to_string(),
                ),
                None,
                EventModel::from_events(tx.info.hash.to_string(), &tx.events),
            ),
            APITransaction::BlockMetadataTransaction(tx) => (
                Self::from_transaction_info(
                    &tx.info,
                    serde_json::Value::Null,
                    transaction.type_str().to_string(),
                ),
                Some(Either::Right(BlockMetadataTransaction::from_transaction(
                    tx,
                ))),
                None,
            ),
            _ => unreachable!(),
        }
    }

    fn from_transaction_info(
        info: &TransactionInfo,
        payload: serde_json::Value,
        type_: String,
    ) -> Self {
        Self {
            type_,
            payload,
            version: *info.version.inner() as i64,
            hash: info.hash.to_string(),
            state_root_hash: info.state_root_hash.to_string(),
            event_root_hash: info.event_root_hash.to_string(),
            gas_used: *info.gas_used.inner() as i64,
            success: info.success,
            vm_status: info.vm_status.clone(),
            accumulator_root_hash: info.accumulator_root_hash.to_string(),
            inserted_at: chrono::Utc::now().naive_utc(),
        }
    }
}

#[derive(Debug, Queryable, Identifiable, Insertable, AsChangeset, Associations)]
#[belongs_to(Transaction, foreign_key = "hash")]
#[primary_key(hash)]
#[diesel(table_name = "user_transactions")]
pub struct UserTransaction {
    pub hash: String,
    pub signature: serde_json::Value,
    pub sender: String,
    pub sequence_number: i64,
    pub max_gas_amount: i64,

    // from UserTransactionRequest
    pub expiration_timestamp_secs: chrono::NaiveDateTime,

    // from UserTransaction
    pub timestamp: chrono::NaiveDateTime,

    // Default time columns
    pub inserted_at: chrono::NaiveDateTime,
}

impl UserTransaction {
    pub fn from_transaction(tx: &APIUserTransaction) -> Self {
        Self {
            hash: tx.info.hash.to_string(),
            signature: serde_json::to_value(&tx.request.signature).unwrap(),
            sender: tx.request.sender.inner().to_hex_literal(),
            sequence_number: *tx.request.sequence_number.inner() as i64,
            max_gas_amount: *tx.request.max_gas_amount.inner() as i64,
            expiration_timestamp_secs: chrono::NaiveDateTime::from_timestamp(
                *tx.request.expiration_timestamp_secs.inner() as i64,
                0,
            ),
            timestamp: parse_timestamp(tx.timestamp, tx.info.version),
            inserted_at: chrono::Utc::now().naive_utc(),
        }
    }
}

#[derive(Debug, Queryable, Identifiable, Insertable, AsChangeset, Associations)]
#[belongs_to(Transaction, foreign_key = "hash")]
#[primary_key("hash")]
#[diesel(table_name = "block_metadata_transactions")]
pub struct BlockMetadataTransaction {
    pub hash: String,
    pub id: String,
    pub round: i64,
    pub previous_block_votes: serde_json::Value,
    pub proposer: String,
    pub timestamp: chrono::NaiveDateTime,

    // Default time columns
    pub inserted_at: chrono::NaiveDateTime,
}

impl BlockMetadataTransaction {
    pub fn from_transaction(tx: &APIBlockMetadataTransaction) -> Self {
        Self {
            hash: tx.info.hash.to_string(),
            id: tx.id.to_string(),
            round: *tx.round.inner() as i64,
            previous_block_votes: serde_json::to_value(&tx.previous_block_votes).unwrap(),
            proposer: tx.proposer.inner().to_hex_literal(),
            // time is in milliseconds, but chronos wants seconds
            timestamp: parse_timestamp(tx.timestamp, tx.info.version),
            inserted_at: chrono::Utc::now().naive_utc(),
        }
    }
}

fn parse_timestamp(ts: U64, version: U64) -> chrono::NaiveDateTime {
    chrono::NaiveDateTime::from_timestamp_opt(*ts.inner() as i64 / 1000000, 0)
        .unwrap_or_else(|| panic!("Could not parse timestamp {:?} for version {}", ts, version))
}

// Prevent conflicts with other things named `Transaction`
pub type BlockMetadataTransactionModel = BlockMetadataTransaction;
pub type TransactionModel = Transaction;
pub type UserTransactionModel = UserTransaction;
<|endoftext|>


<commit_before>#[macro_use]
extern crate pest;

use pest::prelude::*;

impl_rdp! {
    grammar! {
        // precedence climbing
        expression = _{ // rule is silent because it's the rule we're matching
            { ["("] ~ expression ~ [")"] | number } // primary
            addition       = { plus  | minus } // precedence 0
            multiplication = { times | slash } // precedence 1
        }
        number = @{ ["-"]? ~ (["0"] | ['1'..'9'] ~ ['0'..'9']*) } // atomic because it cannot
        plus   =  { ["+"] }                                       // accept white-space
        minus  =  { ["-"] }
        times  =  { ["*"] }
        slash  =  { ["/"] }

        whitespace = _{ [" "] } // whitespce gets run between all rules
    }

    process! {
        compute(&self) -> i32 { // return an i32 in the end
            (&number: number) => number.parse::<i32>().unwrap(), // capture number as &str
            (_: addition, left: compute(), sign, right: compute()) => { // get left & right by
                match sign.rule {                                       // calling compute
                    Rule::plus  => left + right,
                    Rule::minus => left - right,
                    _ => unreachable!()
                }
            },
            (_: multiplication, left: compute(), sign, right: compute()) => {
                match sign.rule {
                    Rule::times => left * right,
                    Rule::slash => left / right,
                    _ => unreachable!()
                }
            }
        }
    }
}

fn main() {
    let mut parser = Rdp::new(StringInput::new("(3 + (9 + 3 * 4 + (3 + 1) / 2 - 4)) * 2"));

    parser.expression();

    println!("{}", parser.compute()); // prints 44
}
<commit_msg>85 Show an example how to use different associativities.<commit_after>#[macro_use]
extern crate pest;

use pest::prelude::*;

impl_rdp! {
    grammar! {
        // precedence climbing
        expression = _{ // rule is silent because it's the rule we're matching
            { ["("] ~ expression ~ [")"] | number } // primary
            addition       = { plus  | minus } // precedence 0
            multiplication = { times | slash } // precedence 1
            exponention    = {< pow }          // precedence 2; NB: exponention is right associative.
        }
        number = @{ ["-"]? ~ (["0"] | ['1'..'9'] ~ ['0'..'9']*) } // atomic because it cannot
        plus   =  { ["+"] }                                       // accept white-space
        minus  =  { ["-"] }
        times  =  { ["*"] }
        slash  =  { ["/"] }
        pow    =  { ["^"] }

        whitespace = _{ [" "] } // whitespce gets run between all rules
    }

    process! {
        compute(&self) -> i32 { // return an i32 in the end
            (&number: number) => number.parse::<i32>().unwrap(), // capture number as &str
            (_: addition, left: compute(), sign, right: compute()) => { // get left & right by
                match sign.rule {                                       // calling compute
                    Rule::plus  => left + right,
                    Rule::minus => left - right,
                    _ => unreachable!()
                }
            },
            (_: multiplication, left: compute(), sign, right: compute()) => {
                match sign.rule {
                    Rule::times => left * right,
                    Rule::slash => left / right,
                    _ => unreachable!()
                }
            },
            (_: exponention, left: compute(), sign, right: compute()) => {
                match sign.rule {
                    Rule::pow => left.pow(right as u32),
                    _ => unreachable!()
                }
            }
        }
    }
}

fn main() {
    let expressions = [
        "(3 + (9 + 3 * 4 + (3 + 1) / 2 - 4)) * 2",
        "2^2^2^2", // This should be 65536 and not 256 because it is right associative.
    ];
    for exp in expressions.into_iter() {
        let mut parser = Rdp::new(StringInput::new(exp.clone()));
        parser.expression();
        println!("{} = {}", exp, parser.compute());
    }
}
<|endoftext|>


<commit_before>//! Tracks minimal sets of mutually incomparable elements of a partial order.

// use progress::CountMap;
use order::PartialOrder;

/// A set of mutually incomparable elements.
///
/// An antichain is a set of partially ordered elements, each of which is incomparable to the others.
/// This antichain implementation allows you to repeatedly introduce elements to the antichain, and
/// which will evict larger elements to maintain the *minimal* antichain, those incomparable elements
/// no greater than any other element.
#[derive(Default, Clone, Debug)]
pub struct Antichain<T> {
    elements: Vec<T>
}

impl<T: PartialOrder> Antichain<T> {
    /// Updates the `Antichain` if the element is not greater than or equal to some present element.
    ///
    /// Returns true if element is added to the set
    pub fn insert(&mut self, element: T) -> bool {
        if !self.elements.iter().any(|x| x.less_equal(&element)) {
            self.elements.retain(|x| !element.less_equal(x));
            self.elements.push(element);
            true
        }
        else {
            false
        }
    }

    /// Creates a new empty `Antichain`.
    pub fn new() -> Antichain<T> { Antichain { elements: Vec::new() } }

    /// Creates a new singleton `Antichain`.
    pub fn from_elem(element: T) -> Antichain<T> { Antichain { elements: vec![element] } }

    /// Clears the contents of the antichain.
    pub fn clear(&mut self) { self.elements.clear() }

    /// Returns true if any item in the antichain is strictly less than the argument.
    #[inline]
    pub fn less_than(&self, time: &T) -> bool {
        self.elements.iter().any(|x| x.less_than(time))
    }

    /// Returns true if any item in the antichain is less than or equal to the argument.
    #[inline]
    pub fn less_equal(&self, time: &T) -> bool {
        self.elements.iter().any(|x| x.less_equal(time))
    }

    /// Returns true if every element of `other` is greater or equal to some element of `self`.
    #[inline]
    pub fn dominates(&self, other: &Antichain<T>) -> bool {
        other.elements().iter().all(|t2| self.elements().iter().any(|t1| t1.less_equal(t2)))
    }

    /// Reveals the elements in the antichain.
    #[inline] pub fn elements(&self) -> &[T] { &self.elements[..] }
}

/// An antichain based on a multiset whose elements frequencies can be updated.
///
/// The `MutableAntichain` maintains frequencies for many elements of type `T`, and exposes the set
/// of elements with positive count not greater than any other elements with positive count. The
/// antichain may both advance and retreat; the changes do not all need to be to elements greater or
/// equal to some elements of the frontier.
///
/// The type `T` must implement `PartialOrder` as well as `Ord`. The implementation of the `Ord` trait
/// is used to efficiently organize the updates for cancellation, and to efficiently determine the lower
/// bounds, and only needs to not contradict the `PartialOrder` implementation (that is, if `PartialOrder`
/// orders two elements, the so does the `Ord` implementation).
///
/// The `MutableAntichain` implementation is done with the intent that updates to it are done in batches,
/// and it is acceptable to rebuild the frontier from scratch when a batch of updates change it. This means
/// that it can be expensive to maintain a large number of counts and change few elements near the frontier.
///
/// There is an `update_dirty` method for single updates that leave the `MutableAntichain` in a dirty state,
/// but I strongly recommend against using them unless you must (on part of timely progress tracking seems
/// to be greatly simplified by access to this)
#[derive(Default, Debug, Clone)]
pub struct MutableAntichain<T: PartialOrder+Ord> {
    dirty: usize,
    updates: Vec<(T, i64)>,
    frontier: Vec<T>,
    frontier_temp: Vec<T>,
}

impl<T: PartialOrder+Ord+Clone+'static> MutableAntichain<T> {
    /// Creates a new empty `MutableAntichain`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let frontier = MutableAntichain::<usize>::new();
    /// assert!(frontier.is_empty());
    ///```
    #[inline]
    pub fn new() -> MutableAntichain<T> {
        MutableAntichain {
            dirty: 0,
            updates: Vec::new(),
            frontier:  Vec::new(),
            frontier_temp: Vec::new(),
        }
    }

    /// Removes all elements.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::<usize>::new();
    /// frontier.clear();
    /// assert!(frontier.is_empty());
    ///```
    #[inline]
    pub fn clear(&mut self) {
        self.dirty = 0;
        self.updates.clear();
        self.frontier.clear();
        self.frontier_temp.clear();
    }

    /// Reveals the minimal elements with positive count.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::<usize>::new();
    /// assert!(frontier.frontier().len() == 0);
    ///```
    #[inline]
    pub fn frontier(&self) -> &[T] {
        debug_assert_eq!(self.dirty, 0);
        &self.frontier
    }

    /// Creates a new singleton `MutableAntichain`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(0u64);
    /// assert_eq!(frontier.frontier(), &[0u64]);
    ///```
    #[inline]
    pub fn new_bottom(bottom: T) -> MutableAntichain<T> {
        MutableAntichain {
            dirty: 0,
            updates: vec![(bottom.clone(), 1)],
            frontier: vec![bottom.clone()],
            frontier_temp: Vec::new(),
        }
    }

    /// Returns true if there are no elements in the `MutableAntichain`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::<usize>::new();
    /// assert!(frontier.is_empty());
    ///```
    #[inline]
    pub fn is_empty(&self) -> bool {
        debug_assert_eq!(self.dirty, 0);
        self.frontier.is_empty()
    }

    /// Returns true if any item in the `MutableAntichain` is strictly less than the argument.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(1u64);
    /// assert!(!frontier.less_than(&0));
    /// assert!(!frontier.less_than(&1));
    /// assert!(frontier.less_than(&2));
    ///```
    #[inline]
    pub fn less_than(&self, time: &T) -> bool {
        debug_assert_eq!(self.dirty, 0);
        self.frontier.iter().any(|x| x.less_than(time))
    }

    /// Returns true if any item in the `MutableAntichain` is less than or equal to the argument.
    #[inline]
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(1u64);
    /// assert!(!frontier.less_equal(&0));
    /// assert!(frontier.less_equal(&1));
    /// assert!(frontier.less_equal(&2));
    ///```
    pub fn less_equal(&self, time: &T) -> bool {
        debug_assert_eq!(self.dirty, 0);
        self.frontier.iter().any(|x| x.less_equal(time))
    }

    /// Allows a single-element push, but dirties the antichain and prevents inspection until cleaned.
    ///
    /// At the moment inspection is prevented via panic, so best be careful (this should probably be fixed).
    /// It is *very* important if you want to use this method that very soon afterwards you call something
    /// akin to `update_iter`, perhaps with a `None` argument if you have no more data, as this method will
    /// tidy up the internal representation.
    #[inline]
    pub fn update_dirty(&mut self, time: T, delta: i64) {
        self.updates.push((time, delta));
        self.dirty += 1;
    }

    /// Applies updates to the antichain and applies `action` to each frontier change.
    ///
    /// This method applies a batch of updates and if any affects the frontier it is rebuilt.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(1u64);
    /// frontier.update_iter(vec![(1, -1), (2, 1)].into_iter());
    /// assert_eq!(frontier.frontier(), &[2]);
    ///```
    #[inline]
    pub fn update_iter<I>(&mut self, updates: I)
    where
        I: IntoIterator<Item = (T, i64)>
    {
        self.update_iter_and(updates, |_,_| { });
    }

    /// Applies updates to the antichain and applies `action` to each frontier change.
    ///
    /// This method applies a batch of updates and if any affects the frontier it is rebuilt.
    /// Once rebuilt, `action` is called with the corresponding changes to the frontier, which
    /// should be various times and `{ +1, -1 }` differences.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(1u64);
    /// let mut changes = Vec::new();
    /// frontier.update_iter_and(vec![(1, -1), (2, 1)].into_iter(), |time, diff| {
    ///     changes.push((time.clone(), diff));
    /// });
    /// assert_eq!(frontier.frontier(), &[2]);
    /// changes.sort();
    /// assert_eq!(&changes[..], &[(1, -1), (2, 1)]);
    ///```
    #[inline]
    pub fn update_iter_and<I, A>(&mut self, updates: I, action: A)
    where
        I: IntoIterator<Item = (T, i64)>,
        A: FnMut(&T, i64)
    {
        // track whether a rebuild is needed.
        let mut rebuild_required = false;

        for (time, delta) in updates {
            self.updates.push((time, delta));
            self.dirty += 1;
        }

        // determine if recently pushed data requires rebuilding the frontier.
        // note: this may be required even with an empty iterator, due to dirty data in self.updates.
        while self.dirty > 0 {

            let time = &self.updates[self.updates.len() - self.dirty].0;
            let delta = self.updates[self.updates.len() - self.dirty].1;

            let beyond_frontier = self.frontier.iter().any(|f| f.less_than(time));
            let before_frontier = !self.frontier.iter().any(|f| f.less_equal(time));
            rebuild_required = rebuild_required || !(beyond_frontier || (delta < 0 && before_frontier));

            self.dirty -= 1;
        }

        if rebuild_required {
            self.rebuild_and(action);
        }
    }

    /// Sorts and consolidates `self.updates` and applies `action` to any frontier changes.
    ///
    /// This method is meant to be used for bulk updates to the frontier, and does more work than one might do
    /// for single updates, but is meant to be an efficient way to process multiple updates together. This is
    /// especially true when we want to apply very large numbers of updates.
    fn rebuild_and<A: FnMut(&T, i64)>(&mut self, mut action: A) {

        // sort and consolidate updates; retain non-zero accumulations.
        if !self.updates.is_empty() {
            self.updates.sort_by(|x,y| x.0.cmp(&y.0));
            for i in 0 .. self.updates.len() - 1 {
                if self.updates[i].0 == self.updates[i+1].0 {
                    self.updates[i+1].1 += self.updates[i].1;
                    self.updates[i].1 = 0;
                }
            }
            self.updates.retain(|x| x.1 != 0);
        }

        // build new frontier using strictly positive times.
        // as the times are sorted, we don't need to worry that we might displace frontier elements.
        for time in self.updates.iter().filter(|x| x.1 > 0) {
            if !self.frontier_temp.iter().any(|f| f.less_than(&time.0)) {
                self.frontier_temp.push(time.0.clone());
            }
        }

        // TODO: This is quadratic in the frontier size, but could be linear (with a merge).
        for time in self.frontier.iter() {
            if !self.frontier_temp.contains(time) {
                action(time, -1);
            }
        }
        ::std::mem::swap(&mut self.frontier, &mut self.frontier_temp);
        for time in self.frontier.iter() {
            if !self.frontier_temp.contains(time) {
                action(time, 1);
            }
        }
        self.frontier_temp.clear();
    }
}
<commit_msg>optimize rebuild test<commit_after>//! Tracks minimal sets of mutually incomparable elements of a partial order.

// use progress::CountMap;
use order::PartialOrder;

/// A set of mutually incomparable elements.
///
/// An antichain is a set of partially ordered elements, each of which is incomparable to the others.
/// This antichain implementation allows you to repeatedly introduce elements to the antichain, and
/// which will evict larger elements to maintain the *minimal* antichain, those incomparable elements
/// no greater than any other element.
#[derive(Default, Clone, Debug)]
pub struct Antichain<T> {
    elements: Vec<T>
}

impl<T: PartialOrder> Antichain<T> {
    /// Updates the `Antichain` if the element is not greater than or equal to some present element.
    ///
    /// Returns true if element is added to the set
    pub fn insert(&mut self, element: T) -> bool {
        if !self.elements.iter().any(|x| x.less_equal(&element)) {
            self.elements.retain(|x| !element.less_equal(x));
            self.elements.push(element);
            true
        }
        else {
            false
        }
    }

    /// Creates a new empty `Antichain`.
    pub fn new() -> Antichain<T> { Antichain { elements: Vec::new() } }

    /// Creates a new singleton `Antichain`.
    pub fn from_elem(element: T) -> Antichain<T> { Antichain { elements: vec![element] } }

    /// Clears the contents of the antichain.
    pub fn clear(&mut self) { self.elements.clear() }

    /// Returns true if any item in the antichain is strictly less than the argument.
    #[inline]
    pub fn less_than(&self, time: &T) -> bool {
        self.elements.iter().any(|x| x.less_than(time))
    }

    /// Returns true if any item in the antichain is less than or equal to the argument.
    #[inline]
    pub fn less_equal(&self, time: &T) -> bool {
        self.elements.iter().any(|x| x.less_equal(time))
    }

    /// Returns true if every element of `other` is greater or equal to some element of `self`.
    #[inline]
    pub fn dominates(&self, other: &Antichain<T>) -> bool {
        other.elements().iter().all(|t2| self.elements().iter().any(|t1| t1.less_equal(t2)))
    }

    /// Reveals the elements in the antichain.
    #[inline] pub fn elements(&self) -> &[T] { &self.elements[..] }
}

/// An antichain based on a multiset whose elements frequencies can be updated.
///
/// The `MutableAntichain` maintains frequencies for many elements of type `T`, and exposes the set
/// of elements with positive count not greater than any other elements with positive count. The
/// antichain may both advance and retreat; the changes do not all need to be to elements greater or
/// equal to some elements of the frontier.
///
/// The type `T` must implement `PartialOrder` as well as `Ord`. The implementation of the `Ord` trait
/// is used to efficiently organize the updates for cancellation, and to efficiently determine the lower
/// bounds, and only needs to not contradict the `PartialOrder` implementation (that is, if `PartialOrder`
/// orders two elements, the so does the `Ord` implementation).
///
/// The `MutableAntichain` implementation is done with the intent that updates to it are done in batches,
/// and it is acceptable to rebuild the frontier from scratch when a batch of updates change it. This means
/// that it can be expensive to maintain a large number of counts and change few elements near the frontier.
///
/// There is an `update_dirty` method for single updates that leave the `MutableAntichain` in a dirty state,
/// but I strongly recommend against using them unless you must (on part of timely progress tracking seems
/// to be greatly simplified by access to this)
#[derive(Default, Debug, Clone)]
pub struct MutableAntichain<T: PartialOrder+Ord> {
    dirty: usize,
    updates: Vec<(T, i64)>,
    frontier: Vec<T>,
    frontier_temp: Vec<T>,
}

impl<T: PartialOrder+Ord+Clone+'static> MutableAntichain<T> {
    /// Creates a new empty `MutableAntichain`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let frontier = MutableAntichain::<usize>::new();
    /// assert!(frontier.is_empty());
    ///```
    #[inline]
    pub fn new() -> MutableAntichain<T> {
        MutableAntichain {
            dirty: 0,
            updates: Vec::new(),
            frontier:  Vec::new(),
            frontier_temp: Vec::new(),
        }
    }

    /// Removes all elements.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::<usize>::new();
    /// frontier.clear();
    /// assert!(frontier.is_empty());
    ///```
    #[inline]
    pub fn clear(&mut self) {
        self.dirty = 0;
        self.updates.clear();
        self.frontier.clear();
        self.frontier_temp.clear();
    }

    /// Reveals the minimal elements with positive count.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::<usize>::new();
    /// assert!(frontier.frontier().len() == 0);
    ///```
    #[inline]
    pub fn frontier(&self) -> &[T] {
        debug_assert_eq!(self.dirty, 0);
        &self.frontier
    }

    /// Creates a new singleton `MutableAntichain`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(0u64);
    /// assert_eq!(frontier.frontier(), &[0u64]);
    ///```
    #[inline]
    pub fn new_bottom(bottom: T) -> MutableAntichain<T> {
        MutableAntichain {
            dirty: 0,
            updates: vec![(bottom.clone(), 1)],
            frontier: vec![bottom.clone()],
            frontier_temp: Vec::new(),
        }
    }

    /// Returns true if there are no elements in the `MutableAntichain`.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::<usize>::new();
    /// assert!(frontier.is_empty());
    ///```
    #[inline]
    pub fn is_empty(&self) -> bool {
        debug_assert_eq!(self.dirty, 0);
        self.frontier.is_empty()
    }

    /// Returns true if any item in the `MutableAntichain` is strictly less than the argument.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(1u64);
    /// assert!(!frontier.less_than(&0));
    /// assert!(!frontier.less_than(&1));
    /// assert!(frontier.less_than(&2));
    ///```
    #[inline]
    pub fn less_than(&self, time: &T) -> bool {
        debug_assert_eq!(self.dirty, 0);
        self.frontier.iter().any(|x| x.less_than(time))
    }

    /// Returns true if any item in the `MutableAntichain` is less than or equal to the argument.
    #[inline]
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(1u64);
    /// assert!(!frontier.less_equal(&0));
    /// assert!(frontier.less_equal(&1));
    /// assert!(frontier.less_equal(&2));
    ///```
    pub fn less_equal(&self, time: &T) -> bool {
        debug_assert_eq!(self.dirty, 0);
        self.frontier.iter().any(|x| x.less_equal(time))
    }

    /// Allows a single-element push, but dirties the antichain and prevents inspection until cleaned.
    ///
    /// At the moment inspection is prevented via panic, so best be careful (this should probably be fixed).
    /// It is *very* important if you want to use this method that very soon afterwards you call something
    /// akin to `update_iter`, perhaps with a `None` argument if you have no more data, as this method will
    /// tidy up the internal representation.
    #[inline]
    pub fn update_dirty(&mut self, time: T, delta: i64) {
        self.updates.push((time, delta));
        self.dirty += 1;
    }

    /// Applies updates to the antichain and applies `action` to each frontier change.
    ///
    /// This method applies a batch of updates and if any affects the frontier it is rebuilt.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(1u64);
    /// frontier.update_iter(vec![(1, -1), (2, 1)].into_iter());
    /// assert_eq!(frontier.frontier(), &[2]);
    ///```
    #[inline]
    pub fn update_iter<I>(&mut self, updates: I)
    where
        I: IntoIterator<Item = (T, i64)>
    {
        self.update_iter_and(updates, |_,_| { });
    }

    /// Applies updates to the antichain and applies `action` to each frontier change.
    ///
    /// This method applies a batch of updates and if any affects the frontier it is rebuilt.
    /// Once rebuilt, `action` is called with the corresponding changes to the frontier, which
    /// should be various times and `{ +1, -1 }` differences.
    ///
    /// #Examples
    ///
    ///```
    /// use timely::progress::frontier::MutableAntichain;
    ///
    /// let mut frontier = MutableAntichain::new_bottom(1u64);
    /// let mut changes = Vec::new();
    /// frontier.update_iter_and(vec![(1, -1), (2, 1)].into_iter(), |time, diff| {
    ///     changes.push((time.clone(), diff));
    /// });
    /// assert_eq!(frontier.frontier(), &[2]);
    /// changes.sort();
    /// assert_eq!(&changes[..], &[(1, -1), (2, 1)]);
    ///```
    #[inline]
    pub fn update_iter_and<I, A>(&mut self, updates: I, action: A)
    where
        I: IntoIterator<Item = (T, i64)>,
        A: FnMut(&T, i64)
    {
        for (time, delta) in updates {
            self.updates.push((time, delta));
            self.dirty += 1;
        }

        // track whether a rebuild is needed.
        let mut rebuild_required = false;

        // determine if recently pushed data requires rebuilding the frontier.
        // note: this may be required even with an empty iterator, due to dirty data in self.updates.
        while self.dirty > 0 && !rebuild_required {

            let time = &self.updates[self.updates.len() - self.dirty].0;
            let delta = self.updates[self.updates.len() - self.dirty].1;

            let beyond_frontier = self.frontier.iter().any(|f| f.less_than(time));
            let before_frontier = !self.frontier.iter().any(|f| f.less_equal(time));
            rebuild_required = rebuild_required || !(beyond_frontier || (delta < 0 && before_frontier));

            self.dirty -= 1;
        }
        self.dirty = 0;

        if rebuild_required {
            self.rebuild_and(action);
        }
    }

    /// Sorts and consolidates `self.updates` and applies `action` to any frontier changes.
    ///
    /// This method is meant to be used for bulk updates to the frontier, and does more work than one might do
    /// for single updates, but is meant to be an efficient way to process multiple updates together. This is
    /// especially true when we want to apply very large numbers of updates.
    fn rebuild_and<A: FnMut(&T, i64)>(&mut self, mut action: A) {

        // sort and consolidate updates; retain non-zero accumulations.
        if !self.updates.is_empty() {
            self.updates.sort_by(|x,y| x.0.cmp(&y.0));
            for i in 0 .. self.updates.len() - 1 {
                if self.updates[i].0 == self.updates[i+1].0 {
                    self.updates[i+1].1 += self.updates[i].1;
                    self.updates[i].1 = 0;
                }
            }
            self.updates.retain(|x| x.1 != 0);
        }

        // build new frontier using strictly positive times.
        // as the times are sorted, we don't need to worry that we might displace frontier elements.
        for time in self.updates.iter().filter(|x| x.1 > 0) {
            if !self.frontier_temp.iter().any(|f| f.less_equal(&time.0)) {
                self.frontier_temp.push(time.0.clone());
            }
        }

        // TODO: This is quadratic in the frontier size, but could be linear (with a merge).
        for time in self.frontier.iter() {
            if !self.frontier_temp.contains(time) {
                action(time, -1);
            }
        }
        ::std::mem::swap(&mut self.frontier, &mut self.frontier_temp);
        for time in self.frontier.iter() {
            if !self.frontier_temp.contains(time) {
                action(time, 1);
            }
        }
        self.frontier_temp.clear();
    }
}
<|endoftext|>


<commit_before>//Other protocol modules implement their own Message types, that all wrap within the same ApiRequestMessage and ApiResponseMessage
use ::serialisation::*;

//Implement ToBytes and FromBytes
pub trait Message: Sized + Send + ToBytes + FromBytes {
	fn get_key(&self) -> i32;
}

pub struct ApiRequestMessage<T: Message> {
	pub api_key: i16,
	pub api_version: i16,
	pub correlation_id: i32,
	pub client_id: String,
	pub request: T
}

pub struct ApiResponseMessage<T: Message> {
	pub correlation_id: i32,
	pub response: T
}
<commit_msg>More serialisation blocking<commit_after>use std::io::{ Error, ErrorKind };

use ::serialisation::*;

//TODO: May need to be more general with ApiRequestMessage and ApiResponseMessage for serialisation
//Standard request/response type
pub trait Message: Sized + Send + ToBytes + FromBytes {
	fn get_key(&self) -> i32;
}

//Standard Kafka Request
pub struct ApiRequestMessage<T: Message> {
	pub api_key: i16,
	pub api_version: i16,
	pub correlation_id: i32,
	pub client_id: String,
	pub request: T
}
impl <T: Message> ToBytes for ApiRequestMessage<T> {
	fn to_bytes(&self) -> &[u8] {
		&[]
	}
}
impl <T: Message> FromBytes for ApiRequestMessage<T> {
	type Deserialised = ApiRequestMessage<T>;

	fn from_bytes(bytes: &[u8]) -> Result<ApiRequestMessage<T>, Error> {
		Err(Error::new(
			ErrorKind::Other,
			"implement"
		))
	}
}

//Standard Kafka Response
pub struct ApiResponseMessage<T: Message> {
	pub correlation_id: i32,
	pub response: T
}
impl <T: Message> ToBytes for ApiResponseMessage<T> {
	fn to_bytes(&self) -> &[u8] {
		&[]
	}
}
impl <T: Message> FromBytes for ApiResponseMessage<T> {
	type Deserialised = ApiResponseMessage<T>;

	fn from_bytes(bytes: &[u8]) -> Result<ApiResponseMessage<T>, Error> {
		Err(Error::new(
			ErrorKind::Other,
			"implement"
		))
	}
}<|endoftext|>


<commit_before>use super::*;
use op_code::OpCode;
use rle_ast;

pub struct Compiler {
    instructions: Vec<Instruction>,
}

impl Compiler {
    pub fn new() -> Self {
        Compiler {
            instructions: Vec::new(),
        }
    }

    pub fn compile(&mut self, src: &[rle_ast::Instruction]) {
        use rle_ast::Instruction::*;

        for instruction in src {
            match *instruction {
                Op((OpCode::Right, count)) =>
                    self.push(Instruction::Right(count)),
                Op((OpCode::Left, count)) =>
                    self.push(Instruction::Left(count)),
                Op((OpCode::Up, count)) => {
                    let amount = (count % 256) as u8;
                    self.push(Instruction::Change(amount));
                }
                Op((OpCode::Down, count)) => {
                    let amount = (256 - count % 256) as u8;
                    self.push(Instruction::Change(amount));
                }
                Op((OpCode::In, count)) => {
                    for _ in 0 .. count {
                        self.push(Instruction::In);
                    }
                }
                Op((OpCode::Out, count)) => {
                    for _ in 0 .. count {
                        self.push(Instruction::Out);
                    }
                }
                Op((OpCode::Begin, _)) | Op((OpCode::End, _)) =>
                    panic!("bad opcode"),

                Loop(ref body) => {
                    let peephole = set_zero_peephole(&body)
                        .or_else(|| find_zero_peephole(&body))
                        .or_else(|| offset_add_peephole(&body));

                    if let Some(instr) = peephole {
                        self.push(instr);
                    } else {
                        let begin_pc = self.instructions.len();
                        self.push(Instruction::JumpZero(0));
                        self.compile(&body);
                        let end_pc = self.instructions.len();
                        self.push(Instruction::JumpNotZero(begin_pc));
                        self.instructions[begin_pc] = Instruction::JumpZero(end_pc);
                    }
                }
            }
        }
    }

    pub fn into_program(self) -> Box<Program> {
        self.instructions.into_boxed_slice()
    }

    fn push(&mut self, instr: Instruction) {
        self.instructions.push(instr);
    }
}

pub fn set_zero_peephole(body: &[rle_ast::Instruction]) -> Option<Instruction> {
    if body.len() == 1 &&
        (body[0] == rle_ast::Instruction::Op((OpCode::Up, 1)) ||
         body[0] == rle_ast::Instruction::Op((OpCode::Down, 1))) {
        Some(Instruction::SetZero)
    } else {
        None
    }
}

pub fn find_zero_peephole(body: &[rle_ast::Instruction]) -> Option<Instruction> {
    if body.len() == 1 {
        match body[0] {
            rle_ast::Instruction::Op((OpCode::Right, count)) =>
                Some(Instruction::FindZeroRight(count)),
            rle_ast::Instruction::Op((OpCode::Left, count)) =>
                Some(Instruction::FindZeroLeft(count)),
            _ => None,
        }
    } else {
        None
    }
}

pub fn offset_add_peephole(body: &[rle_ast::Instruction]) -> Option<Instruction> {
    use rle_ast::Instruction::*;

    if body.len() == 4 {
        match (&body[0], &body[1], &body[2], &body[3]) {
            (&Op((OpCode::Down, 1)),
             &Op((OpCode::Right, count_l)),
             &Op((OpCode::Up, 1)),
             &Op((OpCode::Left, count_r))) if count_l == count_r => {
                Some(Instruction::OffsetAddRight(count_l))
            }
            (&Op((OpCode::Down, 1)),
             &Op((OpCode::Left, count_l)),
             &Op((OpCode::Up, 1)),
             &Op((OpCode::Right, count_r))) if count_l == count_r => {
                Some(Instruction::OffsetAddLeft(count_l))
            }
            _ => None,
        }
    } else {
        None
    }
}

pub fn compile(src: &[rle_ast::Instruction]) -> Box<Program> {
    let mut compiler = Compiler::new();
    compiler.compile(src);
    compiler.into_program()
}
<commit_msg>Workaround--don't peephole OffsetAddLeft(36).<commit_after>use super::*;
use op_code::OpCode;
use rle_ast;

pub struct Compiler {
    instructions: Vec<Instruction>,
}

impl Compiler {
    pub fn new() -> Self {
        Compiler {
            instructions: Vec::new(),
        }
    }

    pub fn compile(&mut self, src: &[rle_ast::Instruction]) {
        use rle_ast::Instruction::*;

        for instruction in src {
            match *instruction {
                Op((OpCode::Right, count)) =>
                    self.push(Instruction::Right(count)),
                Op((OpCode::Left, count)) =>
                    self.push(Instruction::Left(count)),
                Op((OpCode::Up, count)) => {
                    let amount = (count % 256) as u8;
                    self.push(Instruction::Change(amount));
                }
                Op((OpCode::Down, count)) => {
                    let amount = (256 - count % 256) as u8;
                    self.push(Instruction::Change(amount));
                }
                Op((OpCode::In, count)) => {
                    for _ in 0 .. count {
                        self.push(Instruction::In);
                    }
                }
                Op((OpCode::Out, count)) => {
                    for _ in 0 .. count {
                        self.push(Instruction::Out);
                    }
                }
                Op((OpCode::Begin, _)) | Op((OpCode::End, _)) =>
                    panic!("bad opcode"),

                Loop(ref body) => {
                    let peephole = set_zero_peephole(&body)
                        .or_else(|| find_zero_peephole(&body))
                        .or_else(|| offset_add_peephole(&body));

                    if let Some(instr) = peephole {
                        self.push(instr);
                    } else {
                        let begin_pc = self.instructions.len();
                        self.push(Instruction::JumpZero(0));
                        self.compile(&body);
                        let end_pc = self.instructions.len();
                        self.push(Instruction::JumpNotZero(begin_pc));
                        self.instructions[begin_pc] = Instruction::JumpZero(end_pc);
                    }
                }
            }
        }
    }

    pub fn into_program(self) -> Box<Program> {
        self.instructions.into_boxed_slice()
    }

    fn push(&mut self, instr: Instruction) {
        self.instructions.push(instr);
    }
}

pub fn set_zero_peephole(body: &[rle_ast::Instruction]) -> Option<Instruction> {
    if body.len() == 1 &&
        (body[0] == rle_ast::Instruction::Op((OpCode::Up, 1)) ||
         body[0] == rle_ast::Instruction::Op((OpCode::Down, 1))) {
        Some(Instruction::SetZero)
    } else {
        None
    }
}

pub fn find_zero_peephole(body: &[rle_ast::Instruction]) -> Option<Instruction> {
    if body.len() == 1 {
        match body[0] {
            rle_ast::Instruction::Op((OpCode::Right, count)) =>
                Some(Instruction::FindZeroRight(count)),
            rle_ast::Instruction::Op((OpCode::Left, count)) =>
                Some(Instruction::FindZeroLeft(count)),
            _ => None,
        }
    } else {
        None
    }
}

pub fn offset_add_peephole(body: &[rle_ast::Instruction]) -> Option<Instruction> {
    use rle_ast::Instruction::*;

    if body.len() == 4 {
        match (&body[0], &body[1], &body[2], &body[3]) {
            (&Op((OpCode::Down, 1)),
             &Op((OpCode::Right, count_l)),
             &Op((OpCode::Up, 1)),
             &Op((OpCode::Left, count_r))) if count_l == count_r => {
                Some(Instruction::OffsetAddRight(count_l))
            }

            (&Op((OpCode::Down, 1)),
             &Op((OpCode::Left, count_l)),
             &Op((OpCode::Up, 1)),
             &Op((OpCode::Right, count_r))) if count_l == count_r && count_l != 36 => {
                Some(Instruction::OffsetAddLeft(count_l))
            }

            _ => None,
        }
    } else {
        None
    }
}

pub fn compile(src: &[rle_ast::Instruction]) -> Box<Program> {
    let mut compiler = Compiler::new();
    compiler.compile(src);
    compiler.into_program()
}
<|endoftext|>