<commit_before>use std::io;
use std::net::SocketAddr;
use std::time::{SystemTime, Duration};

use crypto::{PublicKey, SecretKey, Hash};
use events::{Events, Reactor, NetworkConfiguration, Event, EventsConfiguration, Channel, MioChannel,
             Network, EventLoop, Milliseconds, EventHandler, Result as EventsResult,
             Error as EventsError};
use blockchain::{Blockchain, Schema, GenesisConfig, Transaction};
use messages::{Connect, RawMessage};
use self::timeout_adjuster::TimeoutAdjuster;

pub use self::state::{State, Round, Height, RequestData, ValidatorId, TxPool, ValidatorState};

mod basic;
mod consensus;
mod requests;

pub mod state; // TODO: temporary solution to get access to WAIT consts
pub mod timeout_adjuster;

#[derive(Debug)]
pub enum ExternalMessage {
    Transaction(Box<Transaction>),
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum NodeTimeout {
    Status,
    Round(u64, u32),
    Request(RequestData, Option<PublicKey>),
    Propose(u64, u32),
    PeerExchange,
}

#[derive(Clone)]
pub struct TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    inner: S,
}

pub struct NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub state: State,
    pub channel: S,
    pub blockchain: Blockchain,
    // TODO: move this into peer exchange service
    pub peer_discovery: Vec<SocketAddr>,
    timeout_adjuster: Box<TimeoutAdjuster>
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ListenerConfig {
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub address: SocketAddr,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NodeConfig {
    pub genesis: GenesisConfig,
    pub listen_address: SocketAddr,
    pub network: NetworkConfiguration,
    pub peers: Vec<SocketAddr>,
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
}

#[derive(Debug, Clone)]
pub struct Configuration {
    pub listener: ListenerConfig,
    pub events: EventsConfiguration,
    pub network: NetworkConfiguration,
    pub peer_discovery: Vec<SocketAddr>,
}

pub type NodeChannel = MioChannel<ExternalMessage, NodeTimeout>;

pub struct Node {
    reactor: Events<NodeHandler<NodeChannel>>,
}

impl<S> NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub fn new(blockchain: Blockchain, sender: S, config: Configuration) -> Self {
        // FIXME: remove unwraps here, use FATAL log level instead
        let (last_hash, last_height) = {
            let block = blockchain.last_block().unwrap();
            (block.hash(), block.height() + 1)
        };

        let stored = Schema::new(&blockchain.view()).get_actual_configuration().unwrap();
        info!("Create node with config={:#?}", stored);

        let validator_id = stored.validators
            .iter()
            .position(|pk| pk == &config.listener.public_key)
            .map(|id| id as ValidatorId);
        info!("Validator={:#?}", validator_id);
        let connect = Connect::new(&config.listener.public_key,
                                   sender.address(),
                                   sender.get_time(),
                                   &config.listener.secret_key);

        let mut state = State::new(validator_id,
                                   config.listener.public_key,
                                   config.listener.secret_key,
                                   stored,
                                   connect,
                                   last_hash,
                                   last_height,
                                   sender.get_time());

        let mut timeout_adjuster = Box::new(timeout_adjuster::Constant::default());
        let timeout = timeout_adjuster.adjust_timeout(&state, blockchain.view());
        state.set_propose_timeout(timeout);

        NodeHandler {
            state: state,
            channel: sender,
            blockchain: blockchain,
            peer_discovery: config.peer_discovery,
            timeout_adjuster: timeout_adjuster,
        }
    }

    pub fn propose_timeout(&self) -> Milliseconds {
        self.state().consensus_config().propose_timeout
    }

    pub fn round_timeout(&self) -> Milliseconds {
        self.state().consensus_config().round_timeout
    }

    pub fn status_timeout(&self) -> Milliseconds {
        self.state().consensus_config().status_timeout
    }

    pub fn peers_timeout(&self) -> Milliseconds {
        self.state().consensus_config().peers_timeout
    }

    pub fn txs_block_limit(&self) -> u32 {
        self.state().consensus_config().txs_block_limit
    }

    pub fn state(&self) -> &State {
        &self.state
    }

    pub fn initialize(&mut self) {
        info!("Start listening address={}", self.channel.address());
        for address in &self.peer_discovery.clone() {
            if address == &self.channel.address() {
                continue;
            }
            self.connect(address);
            info!("Try to connect with peer {}", address);
        }

        let round = 1;
        self.state.jump_round(round);
        info!("Jump to round {}", round);

        self.add_round_timeout();
        self.add_status_timeout();
        self.add_peer_exchange_timeout();
    }

    pub fn send_to_validator(&mut self, id: u32, message: &RawMessage) {
        // TODO: check validator id
        let public_key = self.state.validators()[id as usize];
        self.send_to_peer(public_key, message);
    }

    pub fn send_to_peer(&mut self, public_key: PublicKey, message: &RawMessage) {
        if let Some(conn) = self.state.peers().get(&public_key) {
            trace!("Send to addr: {}", conn.addr());
            self.channel.send_to(&conn.addr(), message.clone());
        } else {
            warn!("Hasn't connection with peer {:?}", public_key);
        }
    }

    pub fn send_to_addr(&mut self, address: &SocketAddr, message: &RawMessage) {
        trace!("Send to addr: {}", address);
        self.channel.send_to(address, message.clone());
    }

    // TODO: use Into<RawMessage>
    pub fn broadcast(&mut self, message: &RawMessage) {
        for conn in self.state.peers().values() {
            trace!("Send to addr: {}", conn.addr());
            self.channel.send_to(&conn.addr(), message.clone());
        }
    }

    pub fn connect(&mut self, address: &SocketAddr) {
        self.channel.connect(address);
    }

    pub fn request(&mut self, data: RequestData, peer: PublicKey) {
        let is_new = self.state.request(data.clone(), peer);
        if is_new {
            self.add_request_timeout(data, None);
        }
    }

    pub fn add_round_timeout(&mut self) {
        let time = self.round_start_time(self.state.round() + 1);
        trace!("ADD ROUND TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Round(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_propose_timeout(&mut self) {
        let adjusted_propose_timeout = self.state.propose_timeout();
        let time = self.round_start_time(self.state.round()) +
                   Duration::from_millis(adjusted_propose_timeout);

        trace!("ADD PROPOSE TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Propose(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_status_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::from_millis(self.status_timeout());
        self.channel.add_timeout(NodeTimeout::Status, time);
    }

    pub fn add_request_timeout(&mut self, data: RequestData, peer: Option<PublicKey>) {
        trace!("ADD REQUEST TIMEOUT");
        let time = self.channel.get_time() + data.timeout();
        self.channel.add_timeout(NodeTimeout::Request(data, peer), time);
    }

    pub fn add_peer_exchange_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::from_millis(self.peers_timeout());
        self.channel.add_timeout(NodeTimeout::PeerExchange, time);
    }

    pub fn last_block_hash(&self) -> Hash {
        self.blockchain
            .last_block()
            .unwrap()
            .hash()
    }

    pub fn round_start_time(&self, round: Round) -> SystemTime {
        let ms = (round - 1) as u64 * self.round_timeout();
        self.state.height_start_time() + Duration::from_millis(ms)
    }
}

impl<S> EventHandler for NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    type Timeout = NodeTimeout;
    type ApplicationEvent = ExternalMessage;

    fn handle_event(&mut self, event: Event) {
        match event {
            Event::Connected(addr) => self.handle_connected(&addr),
            Event::Disconnected(addr) => self.handle_disconnected(&addr),
            Event::Incoming(raw) => self.handle_message(raw),
            Event::Error(_) => {}
        }
    }

    fn handle_application_event(&mut self, event: Self::ApplicationEvent) {
        match event {
            ExternalMessage::Transaction(tx) => {
                self.handle_incoming_tx(tx);
            }
        }
    }

    fn handle_timeout(&mut self, timeout: Self::Timeout) {
        match timeout {
            NodeTimeout::Round(height, round) => self.handle_round_timeout(height, round),
            NodeTimeout::Request(data, peer) => self.handle_request_timeout(data, peer),
            NodeTimeout::Status => self.handle_status_timeout(),
            NodeTimeout::PeerExchange => self.handle_peer_exchange_timeout(),
            NodeTimeout::Propose(height, round) => self.handle_propose_timeout(height, round),
        }
    }
}

pub trait TransactionSend: Send + Sync {
    fn send<T: Transaction>(&self, tx: T) -> EventsResult<()>;
}

impl<S> TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub fn new(inner: S) -> TxSender<S> {
        TxSender { inner: inner }
    }
}

impl<S> TransactionSend for TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    fn send<T: Transaction>(&self, tx: T) -> EventsResult<()> {
        // TODO remove double data convertation
        if !tx.verify() {
            return Err(EventsError::new("Unable to verify transaction"));
        }
        let msg = ExternalMessage::Transaction(Box::new(tx));
        self.inner.post_event(msg)
    }
}

impl Node {
    pub fn new(blockchain: Blockchain, node_cfg: NodeConfig) -> Node {
        blockchain.create_genesis_block(node_cfg.genesis.clone()).unwrap();

        let config = Configuration {
            listener: ListenerConfig {
                public_key: node_cfg.public_key,
                secret_key: node_cfg.secret_key,
                address: node_cfg.listen_address,
            },
            network: node_cfg.network,
            events: EventsConfiguration::default(),
            peer_discovery: node_cfg.peers,
        };
        let network = Network::with_config(node_cfg.listen_address, config.network);
        let event_loop = EventLoop::configured(config.events.clone()).unwrap();
        let channel = NodeChannel::new(node_cfg.listen_address, event_loop.channel());
        let worker = NodeHandler::new(blockchain, channel, config);
        Node { reactor: Events::with_event_loop(network, worker, event_loop) }
    }

    pub fn run(&mut self) -> io::Result<()> {
        self.reactor.bind()?;
        self.reactor.handler_mut().initialize();
        self.reactor.run()
    }

    pub fn state(&self) -> &State {
        self.reactor.handler().state()
    }

    pub fn channel(&self) -> TxSender<NodeChannel> {
        TxSender::new(self.reactor.handler().channel.clone())
    }
}
<commit_msg>Add timeout adjuster setter<commit_after>use std::io;
use std::net::SocketAddr;
use std::time::{SystemTime, Duration};

use crypto::{PublicKey, SecretKey, Hash};
use events::{Events, Reactor, NetworkConfiguration, Event, EventsConfiguration, Channel, MioChannel,
             Network, EventLoop, Milliseconds, EventHandler, Result as EventsResult,
             Error as EventsError};
use blockchain::{Blockchain, Schema, GenesisConfig, Transaction};
use messages::{Connect, RawMessage};
use self::timeout_adjuster::TimeoutAdjuster;

pub use self::state::{State, Round, Height, RequestData, ValidatorId, TxPool, ValidatorState};

mod basic;
mod consensus;
mod requests;

pub mod state; // TODO: temporary solution to get access to WAIT consts
pub mod timeout_adjuster;

#[derive(Debug)]
pub enum ExternalMessage {
    Transaction(Box<Transaction>),
}

#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum NodeTimeout {
    Status,
    Round(u64, u32),
    Request(RequestData, Option<PublicKey>),
    Propose(u64, u32),
    PeerExchange,
}

#[derive(Clone)]
pub struct TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    inner: S,
}

pub struct NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub state: State,
    pub channel: S,
    pub blockchain: Blockchain,
    // TODO: move this into peer exchange service
    pub peer_discovery: Vec<SocketAddr>,
    timeout_adjuster: Box<TimeoutAdjuster>
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ListenerConfig {
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
    pub address: SocketAddr,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NodeConfig {
    pub genesis: GenesisConfig,
    pub listen_address: SocketAddr,
    pub network: NetworkConfiguration,
    pub peers: Vec<SocketAddr>,
    pub public_key: PublicKey,
    pub secret_key: SecretKey,
}

#[derive(Debug, Clone)]
pub struct Configuration {
    pub listener: ListenerConfig,
    pub events: EventsConfiguration,
    pub network: NetworkConfiguration,
    pub peer_discovery: Vec<SocketAddr>,
}

pub type NodeChannel = MioChannel<ExternalMessage, NodeTimeout>;

pub struct Node {
    reactor: Events<NodeHandler<NodeChannel>>,
}

impl<S> NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub fn new(blockchain: Blockchain, sender: S, config: Configuration) -> Self {
        // FIXME: remove unwraps here, use FATAL log level instead
        let (last_hash, last_height) = {
            let block = blockchain.last_block().unwrap();
            (block.hash(), block.height() + 1)
        };

        let stored = Schema::new(&blockchain.view()).get_actual_configuration().unwrap();
        info!("Create node with config={:#?}", stored);

        let validator_id = stored.validators
            .iter()
            .position(|pk| pk == &config.listener.public_key)
            .map(|id| id as ValidatorId);
        info!("Validator={:#?}", validator_id);
        let connect = Connect::new(&config.listener.public_key,
                                   sender.address(),
                                   sender.get_time(),
                                   &config.listener.secret_key);

        let mut state = State::new(validator_id,
                                   config.listener.public_key,
                                   config.listener.secret_key,
                                   stored,
                                   connect,
                                   last_hash,
                                   last_height,
                                   sender.get_time());

        let mut timeout_adjuster = Box::new(timeout_adjuster::Constant::default());
        let timeout = timeout_adjuster.adjust_timeout(&state, blockchain.view());
        state.set_propose_timeout(timeout);

        NodeHandler {
            state: state,
            channel: sender,
            blockchain: blockchain,
            peer_discovery: config.peer_discovery,
            timeout_adjuster: timeout_adjuster,
        }
    }

    fn set_timeout_adjuster(&mut self, adjuster: Box<timeout_adjuster::TimeoutAdjuster>) {
        self.timeout_adjuster = adjuster;
    }

    pub fn propose_timeout(&self) -> Milliseconds {
        self.state().consensus_config().propose_timeout
    }

    pub fn round_timeout(&self) -> Milliseconds {
        self.state().consensus_config().round_timeout
    }

    pub fn status_timeout(&self) -> Milliseconds {
        self.state().consensus_config().status_timeout
    }

    pub fn peers_timeout(&self) -> Milliseconds {
        self.state().consensus_config().peers_timeout
    }

    pub fn txs_block_limit(&self) -> u32 {
        self.state().consensus_config().txs_block_limit
    }

    pub fn state(&self) -> &State {
        &self.state
    }

    pub fn initialize(&mut self) {
        info!("Start listening address={}", self.channel.address());
        for address in &self.peer_discovery.clone() {
            if address == &self.channel.address() {
                continue;
            }
            self.connect(address);
            info!("Try to connect with peer {}", address);
        }

        let round = 1;
        self.state.jump_round(round);
        info!("Jump to round {}", round);

        self.add_round_timeout();
        self.add_status_timeout();
        self.add_peer_exchange_timeout();
    }

    pub fn send_to_validator(&mut self, id: u32, message: &RawMessage) {
        // TODO: check validator id
        let public_key = self.state.validators()[id as usize];
        self.send_to_peer(public_key, message);
    }

    pub fn send_to_peer(&mut self, public_key: PublicKey, message: &RawMessage) {
        if let Some(conn) = self.state.peers().get(&public_key) {
            trace!("Send to addr: {}", conn.addr());
            self.channel.send_to(&conn.addr(), message.clone());
        } else {
            warn!("Hasn't connection with peer {:?}", public_key);
        }
    }

    pub fn send_to_addr(&mut self, address: &SocketAddr, message: &RawMessage) {
        trace!("Send to addr: {}", address);
        self.channel.send_to(address, message.clone());
    }

    // TODO: use Into<RawMessage>
    pub fn broadcast(&mut self, message: &RawMessage) {
        for conn in self.state.peers().values() {
            trace!("Send to addr: {}", conn.addr());
            self.channel.send_to(&conn.addr(), message.clone());
        }
    }

    pub fn connect(&mut self, address: &SocketAddr) {
        self.channel.connect(address);
    }

    pub fn request(&mut self, data: RequestData, peer: PublicKey) {
        let is_new = self.state.request(data.clone(), peer);
        if is_new {
            self.add_request_timeout(data, None);
        }
    }

    pub fn add_round_timeout(&mut self) {
        let time = self.round_start_time(self.state.round() + 1);
        trace!("ADD ROUND TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Round(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_propose_timeout(&mut self) {
        let adjusted_propose_timeout = self.state.propose_timeout();
        let time = self.round_start_time(self.state.round()) +
                   Duration::from_millis(adjusted_propose_timeout);

        trace!("ADD PROPOSE TIMEOUT, time={:?}, height={}, round={}",
               time,
               self.state.height(),
               self.state.round());
        let timeout = NodeTimeout::Propose(self.state.height(), self.state.round());
        self.channel.add_timeout(timeout, time);
    }

    pub fn add_status_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::from_millis(self.status_timeout());
        self.channel.add_timeout(NodeTimeout::Status, time);
    }

    pub fn add_request_timeout(&mut self, data: RequestData, peer: Option<PublicKey>) {
        trace!("ADD REQUEST TIMEOUT");
        let time = self.channel.get_time() + data.timeout();
        self.channel.add_timeout(NodeTimeout::Request(data, peer), time);
    }

    pub fn add_peer_exchange_timeout(&mut self) {
        let time = self.channel.get_time() + Duration::from_millis(self.peers_timeout());
        self.channel.add_timeout(NodeTimeout::PeerExchange, time);
    }

    pub fn last_block_hash(&self) -> Hash {
        self.blockchain
            .last_block()
            .unwrap()
            .hash()
    }

    pub fn round_start_time(&self, round: Round) -> SystemTime {
        let ms = (round - 1) as u64 * self.round_timeout();
        self.state.height_start_time() + Duration::from_millis(ms)
    }
}

impl<S> EventHandler for NodeHandler<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    type Timeout = NodeTimeout;
    type ApplicationEvent = ExternalMessage;

    fn handle_event(&mut self, event: Event) {
        match event {
            Event::Connected(addr) => self.handle_connected(&addr),
            Event::Disconnected(addr) => self.handle_disconnected(&addr),
            Event::Incoming(raw) => self.handle_message(raw),
            Event::Error(_) => {}
        }
    }

    fn handle_application_event(&mut self, event: Self::ApplicationEvent) {
        match event {
            ExternalMessage::Transaction(tx) => {
                self.handle_incoming_tx(tx);
            }
        }
    }

    fn handle_timeout(&mut self, timeout: Self::Timeout) {
        match timeout {
            NodeTimeout::Round(height, round) => self.handle_round_timeout(height, round),
            NodeTimeout::Request(data, peer) => self.handle_request_timeout(data, peer),
            NodeTimeout::Status => self.handle_status_timeout(),
            NodeTimeout::PeerExchange => self.handle_peer_exchange_timeout(),
            NodeTimeout::Propose(height, round) => self.handle_propose_timeout(height, round),
        }
    }
}

pub trait TransactionSend: Send + Sync {
    fn send<T: Transaction>(&self, tx: T) -> EventsResult<()>;
}

impl<S> TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    pub fn new(inner: S) -> TxSender<S> {
        TxSender { inner: inner }
    }
}

impl<S> TransactionSend for TxSender<S>
    where S: Channel<ApplicationEvent = ExternalMessage, Timeout = NodeTimeout>
{
    fn send<T: Transaction>(&self, tx: T) -> EventsResult<()> {
        // TODO remove double data convertation
        if !tx.verify() {
            return Err(EventsError::new("Unable to verify transaction"));
        }
        let msg = ExternalMessage::Transaction(Box::new(tx));
        self.inner.post_event(msg)
    }
}

impl Node {
    pub fn new(blockchain: Blockchain, node_cfg: NodeConfig) -> Node {
        blockchain.create_genesis_block(node_cfg.genesis.clone()).unwrap();

        let config = Configuration {
            listener: ListenerConfig {
                public_key: node_cfg.public_key,
                secret_key: node_cfg.secret_key,
                address: node_cfg.listen_address,
            },
            network: node_cfg.network,
            events: EventsConfiguration::default(),
            peer_discovery: node_cfg.peers,
        };
        let network = Network::with_config(node_cfg.listen_address, config.network);
        let event_loop = EventLoop::configured(config.events.clone()).unwrap();
        let channel = NodeChannel::new(node_cfg.listen_address, event_loop.channel());
        let worker = NodeHandler::new(blockchain, channel, config);
        Node { reactor: Events::with_event_loop(network, worker, event_loop) }
    }

    pub fn run(&mut self) -> io::Result<()> {
        self.reactor.bind()?;
        self.reactor.handler_mut().initialize();
        self.reactor.run()
    }

    pub fn state(&self) -> &State {
        self.reactor.handler().state()
    }

    pub fn channel(&self) -> TxSender<NodeChannel> {
        TxSender::new(self.reactor.handler().channel.clone())
    }
}
<|endoftext|>


<commit_before><commit_msg>Start using clap<commit_after><|endoftext|>


<commit_before>use std::iter;
use std::fmt;
use std::cmp::Ordering;
use super::{ST, OrderedST};

pub struct Node<K, V> {
    key: K,
    val: V,
    left:  Option<Box<Node<K, V>>>,
    right: Option<Box<Node<K, V>>>
}

impl<K, V> Node<K, V> {
    pub fn new(key: K, val: V) -> Node<K, V> {
        Node {
            key: key,
            val: val,
            left: None,
            right: None
        }
    }
}

impl<K: fmt::Debug, V: fmt::Debug> Node<K, V> {
    fn dump(&self, depth: usize, f: &mut fmt::Formatter) {
        if depth == 0 {
            writeln!(f, "{:?}[{:?}]", self.key, self.val).unwrap();
        } else {
            writeln!(f, "{}+--{:?}[{:?}]", iter::repeat("|  ").take(depth-1).collect::<Vec<&str>>().concat(),
                     self.key, self.val).unwrap();
        }
        if self.left.is_some() {
            self.left.as_ref().unwrap().dump(depth + 1, f);
        }
        if self.right.is_some() {
            self.right.as_ref().unwrap().dump(depth + 1, f);
        }
    }
}

fn put<K: Ord, V>(x: Option<Box<Node<K,V>>>, key: K, val: V) -> Option<Box<Node<K,V>>> {
    let mut x = x;
    if x.is_none() {
        return Some(Box::new(Node::new(key, val)));
    }
    let cmp = key.cmp(&x.as_ref().unwrap().key);
    match cmp {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = put(left, key, val)
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = put(right, key, val)
        },
        Ordering::Equal => {
            x.as_mut().unwrap().val = val
        }
    }
    x
}

pub struct BST<K, V> {
    root: Option<Box<Node<K, V>>>
}

impl<K: Ord, V> ST<K, V> for BST<K, V> {
    fn new() -> BST<K, V> {
        BST { root: None }
    }

    fn get(&self, key: &K) -> Option<&V> {
        let mut x = self.root.as_ref();
        while x.is_some() {
            match key.cmp(&x.unwrap().key) {
                Ordering::Less => {
                    x = x.unwrap().left.as_ref();
                },
                Ordering::Greater => {
                    x = x.unwrap().right.as_ref();
                },
                Ordering::Equal  => {
                    return Some(&x.unwrap().val)
                }
            }
        }
        None
    }

    fn put(&mut self, key: K, val: V) {
        let root = self.root.take();
        self.root = put(root, key, val);
    }

    fn delete(&mut self, key: &K) {
        unimplemented!()
    }

    fn is_empty(&self) -> bool {
        self.root.is_none()
    }
    /// number of key-value pairs in the table
    fn size(&self) -> usize {
        unimplemented!()
    }
}

impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for BST<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.root.is_none() {
            write!(f, "<empty tree>")
        } else {
            self.root.as_ref().unwrap().dump(0, f);
            Ok(())
        }
    }
}

#[test]
fn test_binary_search_tree() {
    let mut t = BST::<char, usize>::new();
    for (i, c) in "SEARCHEXAMP".chars().enumerate() {
        t.put(c, i);
    }

    //println!("{:?}", t);
    assert_eq!(t.get('E'),  Some(&6));
}
<commit_msg>symbol_tables/binary_search_tree: implement floor for BST<commit_after>use std::iter;
use std::fmt;
use std::cmp::Ordering;
use super::{ST, OrderedST};

pub struct Node<K, V> {
    key: K,
    val: V,
    left:  Option<Box<Node<K, V>>>,
    right: Option<Box<Node<K, V>>>
}

impl<K, V> Node<K, V> {
    pub fn new(key: K, val: V) -> Node<K, V> {
        Node {
            key: key,
            val: val,
            left: None,
            right: None
        }
    }
}

impl<K: fmt::Debug, V: fmt::Debug> Node<K, V> {
    fn dump(&self, depth: usize, f: &mut fmt::Formatter) {
        if depth == 0 {
            writeln!(f, "{:?}[{:?}]", self.key, self.val).unwrap();
        } else {
            writeln!(f, "{}+--{:?}[{:?}]", iter::repeat("|  ").take(depth-1).collect::<Vec<&str>>().concat(),
                     self.key, self.val).unwrap();
        }
        if self.left.is_some() {
            self.left.as_ref().unwrap().dump(depth + 1, f);
        }
        if self.right.is_some() {
            self.right.as_ref().unwrap().dump(depth + 1, f);
        }
    }
}

fn put<K: Ord, V>(x: Option<Box<Node<K,V>>>, key: K, val: V) -> Option<Box<Node<K,V>>> {
    let mut x = x;
    if x.is_none() {
        return Some(Box::new(Node::new(key, val)));
    }
    let cmp = key.cmp(&x.as_ref().unwrap().key);
    match cmp {
        Ordering::Less => {
            let left = x.as_mut().unwrap().left.take();
            x.as_mut().unwrap().left = put(left, key, val)
        },
        Ordering::Greater => {
            let right = x.as_mut().unwrap().right.take();
            x.as_mut().unwrap().right = put(right, key, val)
        },
        Ordering::Equal => {
            x.as_mut().unwrap().val = val
        }
    }
    x
}

pub struct BST<K, V> {
    root: Option<Box<Node<K, V>>>
}

impl<K: Ord, V> ST<K, V> for BST<K, V> {
    fn new() -> BST<K, V> {
        BST { root: None }
    }

    fn get(&self, key: &K) -> Option<&V> {
        let mut x = self.root.as_ref();
        while x.is_some() {
            match key.cmp(&x.unwrap().key) {
                Ordering::Less => {
                    x = x.unwrap().left.as_ref();
                },
                Ordering::Greater => {
                    x = x.unwrap().right.as_ref();
                },
                Ordering::Equal  => {
                    return Some(&x.unwrap().val)
                }
            }
        }
        None
    }

    fn put(&mut self, key: K, val: V) {
        let root = self.root.take();
        self.root = put(root, key, val);
    }

    fn delete(&mut self, key: &K) {
        unimplemented!()
    }

    fn is_empty(&self) -> bool {
        self.root.is_none()
    }
    /// number of key-value pairs in the table
    fn size(&self) -> usize {
        unimplemented!()
    }
}

fn floor<'a, K: Ord, V>(x: Option<&'a Box<Node<K,V>>>, key: &K) -> Option<&'a Node<K,V>> {
    if x.is_none() {
        return None;
    }

    match key.cmp(&x.unwrap().key) {
        Ordering::Equal => {
            return Some(&(**x.unwrap()));
        },
        Ordering::Less => {
            return floor(x.unwrap().left.as_ref(), key);
        },
        _ => (),
    }

    let t = floor(x.unwrap().right.as_ref(), key);
    if t.is_some() {
        return t
    } else {
        return Some(x.unwrap())
    }
}

impl<K: Ord, V> OrderedST<K, V> for BST<K, V> {
    /// smallest key
    fn min(&self) -> Option<&K> {
        unimplemented!()
    }

    /// largest key
    fn max(&self) -> Option<&K> {
        unimplemented!()
    }

    /// largest key less than or equal to key
    fn floor(&self, key: &K) -> Option<&K> {
        let x = floor(self.root.as_ref(), key);
        if x.is_none() {
            None
        } else {
            Some(&x.unwrap().key)
        }
    }

    /// smallest key greater than or equal to key
    fn ceiling(&self, key: &K) -> Option<&K> {
        unimplemented!()
    }

    /// number of keys less than key
    fn rank(&self, key: &K) -> usize {
        unimplemented!()
    }

    /// key of rank k
    fn select(&self, k: usize) -> Option<&K> {
        unimplemented!()
    }

    /// delete smallest key
    fn delete_min(&mut self) {
        unimplemented!()
    }

    /// delete largest key
    fn delete_max(&mut self) {
        unimplemented!()
    }
}

impl<K: fmt::Debug, V: fmt::Debug> fmt::Debug for BST<K, V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.root.is_none() {
            write!(f, "<empty tree>")
        } else {
            self.root.as_ref().unwrap().dump(0, f);
            Ok(())
        }
    }
}

#[test]
fn test_binary_search_tree() {
    let mut t = BST::<char, usize>::new();
    for (i, c) in "SEARCHEXAMP".chars().enumerate() {
        t.put(c, i);
    }

    //println!("{:?}", t);
    assert_eq!(t.get(&'E'),  Some(&6));
    assert_eq!(t.floor(&'O'), Some(&'M'));
}
<|endoftext|>


<commit_before>#![feature(old_io, path, env, os, core)]

use std::env;
use std::str::StrExt;
use std::old_io::File;
use tokenizer::Tokenizer;
use interpreter::Interpreter;

mod tokenizer;
mod operations;
mod interpreter;

fn main() {
    let mut arguments = env::args();
    arguments.next();
    match arguments.next() {
        Some(filename) => {
            match File::open(&Path::new(filename)).read_to_string() {
                Ok(s) => {
                    let content = s.replace("\n", " ");
                    let words = content.split(' ').collect::<Vec<&str>>();
                    let mut tokenizer = Tokenizer::new(words);
                    let ops = tokenizer.tokenize();
                    let mut interpreter = Interpreter::new(ops);
                    interpreter.run();
                },
                Err(error) => panic!("{}", error),
            }
        },
        None => println!("Usage: groot file.groot"),
    }
}
<commit_msg>remove all warnings from latest nightly<commit_after>#![feature(old_io, old_path, env, core)]

use std::env;
use std::str::StrExt;
use std::old_io::File;
use tokenizer::Tokenizer;
use interpreter::Interpreter;

mod tokenizer;
mod operations;
mod interpreter;

fn main() {
    let mut arguments = env::args();
    arguments.next();
    match arguments.next() {
        Some(filename) => {
            match File::open(&Path::new(filename)).read_to_string() {
                Ok(s) => {
                    let content = s.replace("\n", " ");
                    let words = content.split(' ').collect::<Vec<&str>>();
                    let mut tokenizer = Tokenizer::new(words);
                    let ops = tokenizer.tokenize();
                    let mut interpreter = Interpreter::new(ops);
                    interpreter.run();
                },
                Err(error) => panic!("{}", error),
            }
        },
        None => println!("Usage: groot file.groot"),
    }
}
<|endoftext|>


<commit_before>extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use exonum::blockchain::{Blockchain, Service, GenesisConfig, Transaction, ApiContext};
use exonum::messages::{RawTransaction, RawMessage, FromRaw, Message};
use exonum::node::{Node, NodeConfig, NodeApiConfig, TransactionSend};
use exonum::storage::{Fork, MemoryDB, MapIndex};
use exonum::crypto::{PublicKey, Hash};
use exonum::encoding::{self, Field};
use exonum::api::{Api, ApiError};
use iron::prelude::*;
use iron::Handler;
use router::Router;

// // // // // // // // // // DATA STRUCTURE // // // // // // // // // //

encoding_struct! {
    struct Wallet {
        const SIZE = 48;

        field pub_key:            &PublicKey  [00 => 32]
        field name:               &str        [32 => 40]
        field balance:            u64         [40 => 48]
    }
}

impl Wallet {
    pub fn increase(&mut self, amount: u64) {
        let balance = self.balance() + amount;
        Field::write(&balance, &mut self.raw, 40, 48);
    }

    pub fn decrease(&mut self, amount: u64) {
        let balance = self.balance() - amount;
        Field::write(&balance, &mut self.raw, 40, 48);
    }
}

// // // // // // // // // // MESSAGES // // // // // // // // // //

pub const TX_WALLET_ID: u16 = 1;

message! {
    struct TxCreateWallet {
        const TYPE = SERVICE_ID;
        const ID = TX_WALLET_ID;
        const SIZE = 40;

        field pub_key:     &PublicKey  [00 => 32]
        field name:        &str        [32 => 40]
    }
}

impl TxCreateWallet {
    pub fn execute(&self, mut schema: CurrencySchema) {
        if let None = schema.wallet(self.pub_key()) {
            let wallet = Wallet::new(self.pub_key(), self.name(), 0);
            schema.wallets().put(self.pub_key(), wallet)
        }
    }
}

pub const TX_ISSUE_ID: u16 = 2;

message! {
    struct TxIssue {
        const TYPE = SERVICE_ID;
        const ID = TX_ISSUE_ID;
        const SIZE = 48;

        field pub_key:     &PublicKey  [00 => 32]
        field amount:      u64         [32 => 40]
        field seed:        u64         [40 => 48]
    }
}

impl TxIssue {
    pub fn execute(&self, mut schema: CurrencySchema) {
        if let Some(mut wallet) = schema.wallet(self.pub_key()) {
            wallet.increase(self.amount());
            schema.wallets().put(self.pub_key(), wallet)
        }
    }
}

pub const TX_TRANSFER_ID: u16 = 3;

message! {
    struct TxTransfer {
        const TYPE = SERVICE_ID;
        const ID = TX_TRANSFER_ID;
        const SIZE = 80;

        field from:        &PublicKey  [00 => 32]
        field to:          &PublicKey  [32 => 64]
        field amount:      u64         [64 => 72]
        field seed:        u64         [72 => 80]
    }
}

impl TxTransfer {
    pub fn execute(&self, mut schema: CurrencySchema) {
        let sender = schema.wallet(self.from());
        let receiver = schema.wallet(self.to());
        if let (Some(mut sender), Some(mut receiver)) = (sender, receiver) {
            let amount = self.amount();
            if sender.balance() >= amount {
                sender.decrease(amount);
                receiver.increase(amount);
                println!("{:?} => {:?}", sender, receiver);
                let mut wallets = schema.wallets();
                wallets.put(self.from(), sender);
                wallets.put(self.to(), receiver);
            }
        }
    }
}

// // // // // // // // // // REST API // // // // // // // // // //

#[derive(Clone)]
struct CryptocurrencyApi<T> {
    channel: T,
}

impl<T: TransactionSend + Clone + 'static> Api for CryptocurrencyApi<T> {
    fn wire(&self, router: &mut Router) {

        #[derive(Serialize, Deserialize)]
        struct TransactionResult {
            tx_hash: Hash,
        }

        let self_ = self.clone();
        let transaction = move |req: &mut Request| -> IronResult<Response> {
            match req.get::<bodyparser::Struct<CurrencyTx>>() {
                Ok(Some(transaction)) => {
                    let tx_hash = transaction.hash();
                    self_.channel.send(transaction).map_err(|e| ApiError::Events(e))?;
                    let json = TransactionResult { tx_hash };
                    self_.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        };
        let route_post = "/v1/wallets/transaction";
        router.post(&route_post, transaction, "transaction");
    }
}

// // // // // // // // // // TRANSACTION // // // // // // // // // //

#[serde(untagged)]
#[derive(Debug, Clone, Serialize, Deserialize)]
enum CurrencyTx {
    Transfer(TxTransfer),
    Issue(TxIssue),
    CreateWallet(TxCreateWallet),
}

impl Message for CurrencyTx {
    fn raw(&self) -> &RawMessage {
        match *self {
            CurrencyTx::Transfer(ref msg) => msg.raw(),
            CurrencyTx::Issue(ref msg) => msg.raw(),
            CurrencyTx::CreateWallet(ref msg) => msg.raw(),
        }
    }
}

impl FromRaw for CurrencyTx {
    fn from_raw(raw: RawMessage) -> Result<Self, encoding::Error> {
        match raw.message_type() {
            TX_TRANSFER_ID => Ok(CurrencyTx::Transfer(TxTransfer::from_raw(raw)?)),
            TX_ISSUE_ID => Ok(CurrencyTx::Issue(TxIssue::from_raw(raw)?)),
            TX_WALLET_ID => Ok(CurrencyTx::CreateWallet(TxCreateWallet::from_raw(raw)?)),
            _ => Err(encoding::Error::IncorrectMessageType { message_type: raw.message_type() }),
        }
    }
}

impl Transaction for CurrencyTx {
    fn verify(&self) -> bool {
        match *self {
            CurrencyTx::CreateWallet(ref msg) => {
                self.verify_signature(msg.pub_key())
            },
            CurrencyTx::Issue(ref msg) => {
                self.verify_signature(msg.pub_key())
            },
            CurrencyTx::Transfer(ref msg) => {
                self.verify_signature(msg.from()) && (*msg.from() != *msg.to())
            },
        }
    }

    fn execute(&self, view: &mut Fork) {
        let schema = CurrencySchema { view };
        match *self {
            CurrencyTx::Transfer(ref msg) => msg.execute(schema),
            CurrencyTx::Issue(ref msg) => msg.execute(schema),
            CurrencyTx::CreateWallet(ref msg) => msg.execute(schema),
        }
    }
}

// // // // // // // // // // DATA SCHEMA // // // // // // // // // //

pub struct CurrencySchema<'a> {
    view: &'a mut Fork,
}

impl<'a> CurrencySchema<'a> {
    pub fn wallets(&mut self) -> MapIndex<&mut Fork, PublicKey, Wallet> {
        MapIndex::new(vec![20], self.view)
    }

    pub fn wallet(&mut self, pub_key: &PublicKey) -> Option<Wallet> {
        self.wallets().get(pub_key)
    }
}

// // // // // // // // // // SERVICE // // // // // // // // // //

pub const SERVICE_ID: u16 = 1;

struct CurrencyService;

impl Service for CurrencyService {
    fn service_name(&self) -> &'static str { "cryptocurrency" }

    fn service_id(&self) -> u16 { SERVICE_ID }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        CurrencyTx::from_raw(raw).map(|tx| Box::new(tx) as Box<Transaction>)
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = CryptocurrencyApi {
            channel: ctx.node_channel().clone(),
        };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

// // // // // // // // // // ENTRY POINT // // // // // // // // // //

fn main() {
    exonum::crypto::init();
    exonum::helpers::init_logger().unwrap();

    let db = MemoryDB::new();
    let services: Vec<Box<Service>> = vec![
        Box::new(CurrencyService),
    ];
    let blockchain = Blockchain::new(Box::new(db), services);

    let (public_key, secret_key) = exonum::crypto::gen_keypair();

    let peer = "0.0.0.0:2000".parse().unwrap();
    let api = "0.0.0.0:8000".parse().unwrap();

    let genesis = GenesisConfig::new(vec![public_key].into_iter());

    let api_cfg = NodeApiConfig {
        enable_blockchain_explorer: true,
        public_api_address: Some(api),
        private_api_address: None,
    };

    let node_cfg = NodeConfig {
        listen_address: peer,
        peers: vec![peer],
        public_key,
        secret_key,
        genesis,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
    };

    let mut node = Node::new(blockchain, node_cfg);
    node.run().unwrap();
}
<commit_msg>Reorder sections<commit_after>extern crate serde;
extern crate serde_json;
#[macro_use] extern crate serde_derive;
#[macro_use] extern crate exonum;
extern crate router;
extern crate bodyparser;
extern crate iron;

use exonum::blockchain::{Blockchain, Service, GenesisConfig, Transaction, ApiContext};
use exonum::messages::{RawTransaction, RawMessage, FromRaw, Message};
use exonum::node::{Node, NodeConfig, NodeApiConfig, TransactionSend};
use exonum::storage::{Fork, MemoryDB, MapIndex};
use exonum::crypto::{PublicKey, Hash};
use exonum::encoding::{self, Field};
use exonum::api::{Api, ApiError};
use iron::prelude::*;
use iron::Handler;
use router::Router;

// // // // // // // // // // PERSISTENT DATA // // // // // // // // // //

encoding_struct! {
    struct Wallet {
        const SIZE = 48;

        field pub_key:            &PublicKey  [00 => 32]
        field name:               &str        [32 => 40]
        field balance:            u64         [40 => 48]
    }
}

impl Wallet {
    pub fn increase(&mut self, amount: u64) {
        let balance = self.balance() + amount;
        Field::write(&balance, &mut self.raw, 40, 48);
    }

    pub fn decrease(&mut self, amount: u64) {
        let balance = self.balance() - amount;
        Field::write(&balance, &mut self.raw, 40, 48);
    }
}

// // // // // // // // // // MESSAGES // // // // // // // // // //

pub const TX_WALLET_ID: u16 = 1;

message! {
    struct TxCreateWallet {
        const TYPE = SERVICE_ID;
        const ID = TX_WALLET_ID;
        const SIZE = 40;

        field pub_key:     &PublicKey  [00 => 32]
        field name:        &str        [32 => 40]
    }
}

pub const TX_ISSUE_ID: u16 = 2;

message! {
    struct TxIssue {
        const TYPE = SERVICE_ID;
        const ID = TX_ISSUE_ID;
        const SIZE = 48;

        field pub_key:     &PublicKey  [00 => 32]
        field amount:      u64         [32 => 40]
        field seed:        u64         [40 => 48]
    }
}

pub const TX_TRANSFER_ID: u16 = 3;

message! {
    struct TxTransfer {
        const TYPE = SERVICE_ID;
        const ID = TX_TRANSFER_ID;
        const SIZE = 80;

        field from:        &PublicKey  [00 => 32]
        field to:          &PublicKey  [32 => 64]
        field amount:      u64         [64 => 72]
        field seed:        u64         [72 => 80]
    }
}

// // // // // // // // // // CONTRACTS // // // // // // // // // //

impl TxCreateWallet {
    pub fn execute(&self, mut schema: CurrencySchema) {
        if let None = schema.wallet(self.pub_key()) {
            let wallet = Wallet::new(self.pub_key(), self.name(), 0);
            schema.wallets().put(self.pub_key(), wallet)
        }
    }
}

impl TxIssue {
    pub fn execute(&self, mut schema: CurrencySchema) {
        if let Some(mut wallet) = schema.wallet(self.pub_key()) {
            wallet.increase(self.amount());
            schema.wallets().put(self.pub_key(), wallet)
        }
    }
}

impl TxTransfer {
    pub fn execute(&self, mut schema: CurrencySchema) {
        let sender = schema.wallet(self.from());
        let receiver = schema.wallet(self.to());
        if let (Some(mut sender), Some(mut receiver)) = (sender, receiver) {
            let amount = self.amount();
            if sender.balance() >= amount {
                sender.decrease(amount);
                receiver.increase(amount);
                println!("{:?} => {:?}", sender, receiver);
                let mut wallets = schema.wallets();
                wallets.put(self.from(), sender);
                wallets.put(self.to(), receiver);
            }
        }
    }
}

// // // // // // // // // // REST API // // // // // // // // // //

#[derive(Clone)]
struct CryptocurrencyApi<T> {
    channel: T,
}

impl<T: TransactionSend + Clone + 'static> Api for CryptocurrencyApi<T> {
    fn wire(&self, router: &mut Router) {

        #[derive(Serialize, Deserialize)]
        struct TransactionResult {
            tx_hash: Hash,
        }

        let self_ = self.clone();
        let transaction = move |req: &mut Request| -> IronResult<Response> {
            match req.get::<bodyparser::Struct<CurrencyTx>>() {
                Ok(Some(transaction)) => {
                    let tx_hash = transaction.hash();
                    self_.channel.send(transaction).map_err(|e| ApiError::Events(e))?;
                    let json = TransactionResult { tx_hash };
                    self_.ok_response(&serde_json::to_value(&json).unwrap())
                }
                Ok(None) => Err(ApiError::IncorrectRequest("Empty request body".into()))?,
                Err(e) => Err(ApiError::IncorrectRequest(Box::new(e)))?,
            }
        };
        let route_post = "/v1/wallets/transaction";
        router.post(&route_post, transaction, "transaction");
    }
}

// // // // // // // // // // BLOCKCHAIN TRANSACTION // // // // // // // // // //

#[serde(untagged)]
#[derive(Debug, Clone, Serialize, Deserialize)]
enum CurrencyTx {
    Transfer(TxTransfer),
    Issue(TxIssue),
    CreateWallet(TxCreateWallet),
}

impl Message for CurrencyTx {
    fn raw(&self) -> &RawMessage {
        match *self {
            CurrencyTx::Transfer(ref msg) => msg.raw(),
            CurrencyTx::Issue(ref msg) => msg.raw(),
            CurrencyTx::CreateWallet(ref msg) => msg.raw(),
        }
    }
}

impl FromRaw for CurrencyTx {
    fn from_raw(raw: RawMessage) -> Result<Self, encoding::Error> {
        match raw.message_type() {
            TX_TRANSFER_ID => Ok(CurrencyTx::Transfer(TxTransfer::from_raw(raw)?)),
            TX_ISSUE_ID => Ok(CurrencyTx::Issue(TxIssue::from_raw(raw)?)),
            TX_WALLET_ID => Ok(CurrencyTx::CreateWallet(TxCreateWallet::from_raw(raw)?)),
            _ => Err(encoding::Error::IncorrectMessageType { message_type: raw.message_type() }),
        }
    }
}

impl Transaction for CurrencyTx {
    fn verify(&self) -> bool {
        match *self {
            CurrencyTx::CreateWallet(ref msg) => {
                self.verify_signature(msg.pub_key())
            },
            CurrencyTx::Issue(ref msg) => {
                self.verify_signature(msg.pub_key())
            },
            CurrencyTx::Transfer(ref msg) => {
                self.verify_signature(msg.from()) && (*msg.from() != *msg.to())
            },
        }
    }

    fn execute(&self, view: &mut Fork) {
        let schema = CurrencySchema { view };
        match *self {
            CurrencyTx::Transfer(ref msg) => msg.execute(schema),
            CurrencyTx::Issue(ref msg) => msg.execute(schema),
            CurrencyTx::CreateWallet(ref msg) => msg.execute(schema),
        }
    }
}

// // // // // // // // // // STORAGE DATA LAYOUT // // // // // // // // // //

pub struct CurrencySchema<'a> {
    view: &'a mut Fork,
}

impl<'a> CurrencySchema<'a> {
    pub fn wallets(&mut self) -> MapIndex<&mut Fork, PublicKey, Wallet> {
        MapIndex::new(vec![20], self.view)
    }

    pub fn wallet(&mut self, pub_key: &PublicKey) -> Option<Wallet> {
        self.wallets().get(pub_key)
    }
}

// // // // // // // // // // SERVICE DECLARATION // // // // // // // // // //

pub const SERVICE_ID: u16 = 1;

struct CurrencyService;

impl Service for CurrencyService {
    fn service_name(&self) -> &'static str { "cryptocurrency" }

    fn service_id(&self) -> u16 { SERVICE_ID }

    fn tx_from_raw(&self, raw: RawTransaction) -> Result<Box<Transaction>, encoding::Error> {
        CurrencyTx::from_raw(raw).map(|tx| Box::new(tx) as Box<Transaction>)
    }

    fn public_api_handler(&self, ctx: &ApiContext) -> Option<Box<Handler>> {
        let mut router = Router::new();
        let api = CryptocurrencyApi {
            channel: ctx.node_channel().clone(),
        };
        api.wire(&mut router);
        Some(Box::new(router))
    }
}

// // // // // // // // // // ENTRY POINT // // // // // // // // // //

fn main() {
    exonum::crypto::init();
    exonum::helpers::init_logger().unwrap();

    let db = MemoryDB::new();
    let services: Vec<Box<Service>> = vec![
        Box::new(CurrencyService),
    ];
    let blockchain = Blockchain::new(Box::new(db), services);

    let (public_key, secret_key) = exonum::crypto::gen_keypair();

    let peer = "0.0.0.0:2000".parse().unwrap();
    let api = "0.0.0.0:8000".parse().unwrap();

    let genesis = GenesisConfig::new(vec![public_key].into_iter());

    let api_cfg = NodeApiConfig {
        enable_blockchain_explorer: true,
        public_api_address: Some(api),
        private_api_address: None,
    };

    let node_cfg = NodeConfig {
        listen_address: peer,
        peers: vec![peer],
        public_key,
        secret_key,
        genesis,
        network: Default::default(),
        whitelist: Default::default(),
        api: api_cfg,
    };

    let mut node = Node::new(blockchain, node_cfg);
    node.run().unwrap();
}
<|endoftext|>


<commit_before>//! Utility for controlling RGB header on MSI boards
//!
//! The RGB header is controlled by the NCT6795D Super I/O chip.
//!
//! The Advanced "mode" is enabled by writing 87 87 to PORT 1. It is later disabled by writing AA
//! to that same port. `07 12` then selects the bank 12h. This bank then looks like this:
//!
//! 00 |  ...
//! 10 |  ...
//! .  |
//! .  |
//! .  |
//! E0 | XX XX XX XX  PX XX XX XX  XX XX XX XX  XX XX XX XX
//! F0 | RR RR RR RR  GG GG GG GG  BB BB BB BB  XX XX TT TX
//!     --------------------------------------------------
//!      00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F
//!
//! Here:
//!
//! `R` - intensity of the red colour
//! `G` - intensity of the green colour
//! `B` - intensity of the blue colour
//!
//! There’s 8 distinct steps that can be specified, hence the four instances of `RR`, `GG` and
//! `BB`. These colours change every given interval specified in the `TTT` bytes. TTT has the bit
//! format like this: `bgrdt tttt tttt`
//!
//! Here `t` bits are a duration between changes from one colour to another (takes the next column
//! of RR GG BB);
//!
//! `d` bit specifies whether the RGB header is turned on (distinct from the motherboard lights).;
//!
//! `bgr` invert the intensity (`F` is 0%, `0` is 100%) for blue, green and red channels
//! respectively.
//!
//! `P` here is another bitmask of the form `pbbb`, where `p` specifies whether smooth pulsing
//! behaviour is enabled. `bbb` specifies duration between blinks. If `bbb` is `001`,
//! all lightning is turned off, including the one on the motherboard itself. `000` is always on.

extern crate clap;
#[macro_use]
extern crate error_chain;

use std::io::{self, Seek, Write, Read};
use std::fs;
use clap::{Arg, App, ArgMatches};

error_chain! {
    foreign_links {
        Io(::std::io::Error);
        Parse(::std::num::ParseIntError);
    }
}

const RGB_BANK: u8 = 0x12;
const NCT6795D_MASK: u16 = 0xD350;

const REG_DEVID_MSB: u8 = 0x20;
const REG_DEVID_LSB: u8 = 0x21;
const REDCELL: u8 = 0xf0;
const GREENCELL: u8 = 0xf4;
const BLUECELL: u8 = 0xf8;

fn inb(f: &mut fs::File, port: u16) -> io::Result<u8> {
    let mut d = [0u8];
    f.seek(io::SeekFrom::Start(port.into()))?;
    f.read(&mut d)?;
    Ok(d[0])
}

fn outb(f: &mut fs::File, port: u16, data: u8) -> io::Result<()> {
    f.seek(io::SeekFrom::Start(port.into()))?;
    f.write(&[data])?;
    Ok(())
}

fn write_byte_to_cell(f: &mut fs::File, base_port: u16, cell: u8, data: u8) -> io::Result<()> {
    outb(f, base_port, cell)?;
    outb(f, base_port + 1, data)
}

fn write_colour(f: &mut fs::File, base_port: u16, cell_offset: u8, data: u32) -> io::Result<()> {
    write_byte_to_cell(f, base_port, cell_offset, (data >> 24) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 1, (data >> 16) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 2, (data >> 8) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 3, data as u8)
}

fn run<'a>(f: &mut fs::File, base_port: u16, matches: ArgMatches<'a>) -> Result<()> {
    let disable = matches.is_present("DISABLE");
    let pulse = matches.is_present("PULSE");
    let ignore = matches.is_present("IGNORECHECK");
    let flash = matches.value_of("BLINK").expect("bug: BLINK argument").parse::<u8>()?;
    let red = u32::from_str_radix(matches.value_of("RED").expect("bug: RED argument"), 16)?;
    let green = u32::from_str_radix(matches.value_of("GREEN").expect("bug: GREEN argument"), 16)?;
    let blue = u32::from_str_radix(matches.value_of("BLUE").expect("bug: BLUE argument"), 16)?;
    let step_duration = matches.value_of("STEPDURATION").expect("bug: STEPDURATION argument")
                               .parse::<u16>()?;
    let invs = matches.values_of("INVHALF").map(|i| i.collect()).unwrap_or(Vec::new());

    // Check if indeed a NCT6795D
    if !ignore {
        outb(f, base_port, REG_DEVID_MSB)?;
        let msb = inb(f, base_port + 1)?;
        outb(f, base_port, REG_DEVID_LSB)?;
        let ident = (msb as u16) << 8 | inb(f, base_port + 1)? as u16;
        if ident & 0xFFF0 != NCT6795D_MASK {
            let err: Result<()> = Err("`--ignore-check` flag, which would skip the check, \
                                       is not specified (may be dangerous); \
                                       also try `--base-port`".into());
            return err.chain_err(|| format!("The sI/O chip identifies as {:x}, which does not \
                                            seem to be NCT6795D", ident));
        }
    }

    // Select the 0x12th bank.
    outb(f, base_port, 0x07)?;
    outb(f, base_port + 1, RGB_BANK)?;

    let e4_val = if disable { 1 } else { 0 } |
                 if pulse { 0b1000 } else { 0 } |
                 if flash == 0 { 0 } else { (flash + 1) & 0b111 };
    write_byte_to_cell(f, base_port, 0xe4, e4_val)?;
    write_colour(f, base_port, REDCELL, red)?;
    write_colour(f, base_port, GREENCELL, green)?;
    write_colour(f, base_port, BLUECELL, blue)?;

    write_byte_to_cell(f, base_port, 0xfe, step_duration as u8)?;
    let ff_val = (step_duration >> 8) as u8 & 1 |
                 0b10 | // if 0 disable lights on rgb header only, not on board
                 if invs.contains(&"b") { 0b10000 } else { 0 } |
                 if invs.contains(&"g") { 0b01000 } else { 0 } |
                 if invs.contains(&"r") { 0b00100 } else { 0 };
    write_byte_to_cell(f, base_port, 0xff, ff_val)?;

    Ok(())
}

/// Wrapper which enables and disables the advanced mode
fn run_wrap<'a>(matches: ArgMatches<'a>) -> Result<()> {
    let base_port = u16::from_str_radix(matches.value_of("BASEPORT")
                                               .expect("bug: BASEPORT argument"), 16)?;

    let mut f = fs::OpenOptions::new().read(true).write(true).open("/dev/port")
        .chain_err(|| { "could not open /dev/port; try sudo?" })?;
    // Enable the advanced mode.
    outb(&mut f, base_port, 0x87).chain_err(|| "could not enable advanced mode")?;
    outb(&mut f, base_port, 0x87).chain_err(|| "could not enable advanced mode")?;
    let r = run(&mut f, base_port, matches);
    // Disable the advanced mode.
    outb(&mut f, base_port, 0xAA).chain_err(|| "could not disable advanced mode")?;
    r.chain_err(|| "could not set the colour")
}

fn main() {
    let matches = App::new("msi-rgb")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(clap::AppSettings::ArgRequiredElseHelp)
        .arg(Arg::with_name("RED").required(true)
             .help("values of red colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("GREEN").required(true)
             .help("values of green colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("BLUE").required(true)
             .help("values of blue colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("INVHALF").long("invert").short("i").multiple(true)
             .takes_value(true).possible_values(&["r","g","b"])
             .help("invert the specified channel(s)"))
        .arg(Arg::with_name("PULSE").long("pulse").short("p")
             .help("smooth pulsing"))
        .arg(Arg::with_name("STEPDURATION").long("duration").short("d").takes_value(true)
             .default_value("25").validator(|s| { match s.parse::<u16>() {
                 Err(e) => Err(format!("{}", e)),
                 Ok(s) => if s > 511 { Err("duration must not exceed 511".into()) } else { Ok(()) }
             }})
             .help("duration between distinct steps of colours (0 - fastest, 511 - slowest"))
        .arg(Arg::with_name("BLINK").long("blink").short("b").takes_value(true).default_value("0")
             .possible_values(&["0", "1", "2", "3", "4", "5", "6"])
             .help("duration between blinks (from 0 to 6, 0 is always on, 6 is slowest)"))
        .arg(Arg::with_name("DISABLE").long("disable").short("x")
             .help("disable the RGB subsystem altogether"))
        .arg(Arg::with_name("IGNORECHECK").long("ignore-check")
             .help("ignore the result of sI/O identification check"))
        .arg(Arg::with_name("BASEPORT").long("base-port").default_value("4e")
             .help("base port to use. Values known to be in use are 4e and 2e"))
        .get_matches();

    ::std::process::exit(if let Err(e) = run_wrap(matches) {
        let _ = writeln!(::std::io::stderr(), "error: {}", e);
        for e in e.iter().skip(1) {
            let _ = writeln!(::std::io::stderr(), "    caused by: {}", e);
        }
        1
    } else {
        0
    });
}
<commit_msg>Try harder to enable the RGB header<commit_after>//! Utility for controlling RGB header on MSI boards
//!
//! The RGB header is controlled by the NCT6795D Super I/O chip.
//!
//! The Advanced "mode" is enabled by writing 87 87 to PORT 1. It is later disabled by writing AA
//! to that same port. `07 12` then selects the bank 12h. This bank then looks like this:
//!
//! 00 |  ...
//! 10 |  ...
//! .  |
//! .  |
//! .  |
//! E0 | EE XX XX XX  PX XX XX XX  XX XX XX XX  XX XX XX XX
//! F0 | RR RR RR RR  GG GG GG GG  BB BB BB BB  XX XX TT TX
//!     --------------------------------------------------
//!      00 01 02 03  04 05 06 07  08 09 0A 0B  0C 0D 0E 0F
//!
//! Here:
//!
//! `EE` – firstly sets RGB to enabled. If value = `0` disabled. If value = `e0` enabled… or
//! something. This probably configures the RGB header in some way, no idea what the value means
//! yet.
//!
//! `R` - intensity of the red colour
//! `G` - intensity of the green colour
//! `B` - intensity of the blue colour
//!
//! There’s 8 distinct steps that can be specified, hence the four instances of `RR`, `GG` and
//! `BB`. These colours change every given interval specified in the `TTT` bytes. TTT has the bit
//! format like this: `bgrdt tttt tttt`
//!
//! Here `t` bits are a duration between changes from one colour to another (takes the next column
//! of RR GG BB);
//!
//! `d` bit specifies whether the RGB header is turned on (distinct from the motherboard lights).;
//!
//! `bgr` invert the intensity (`F` is 0%, `0` is 100%) for blue, green and red channels
//! respectively.
//!
//! `P` here is another bitmask of the form `pbbb`, where `p` specifies whether smooth pulsing
//! behaviour is enabled. `bbb` specifies duration between blinks. If `bbb` is `001`,
//! all lightning is turned off, including the one on the motherboard itself. `000` is always on.

extern crate clap;
#[macro_use]
extern crate error_chain;

use std::io::{self, Seek, Write, Read};
use std::fs;
use clap::{Arg, App, ArgMatches};

error_chain! {
    foreign_links {
        Io(::std::io::Error);
        Parse(::std::num::ParseIntError);
    }
}

const RGB_BANK: u8 = 0x12;
const NCT6795D_MASK: u16 = 0xD350;

const REG_DEVID_MSB: u8 = 0x20;
const REG_DEVID_LSB: u8 = 0x21;
const REDCELL: u8 = 0xf0;
const GREENCELL: u8 = 0xf4;
const BLUECELL: u8 = 0xf8;

fn inb(f: &mut fs::File, port: u16) -> io::Result<u8> {
    let mut d = [0u8];
    f.seek(io::SeekFrom::Start(port.into()))?;
    f.read(&mut d)?;
    Ok(d[0])
}

fn outb(f: &mut fs::File, port: u16, data: u8) -> io::Result<()> {
    f.seek(io::SeekFrom::Start(port.into()))?;
    f.write(&[data])?;
    Ok(())
}

fn write_byte_to_cell(f: &mut fs::File, base_port: u16, cell: u8, data: u8) -> io::Result<()> {
    outb(f, base_port, cell)?;
    outb(f, base_port + 1, data)
}

fn write_colour(f: &mut fs::File, base_port: u16, cell_offset: u8, data: u32) -> io::Result<()> {
    write_byte_to_cell(f, base_port, cell_offset, (data >> 24) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 1, (data >> 16) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 2, (data >> 8) as u8)?;
    write_byte_to_cell(f, base_port, cell_offset + 3, data as u8)
}

fn run<'a>(f: &mut fs::File, base_port: u16, matches: ArgMatches<'a>) -> Result<()> {
    let disable = matches.is_present("DISABLE");
    let pulse = matches.is_present("PULSE");
    let ignore = matches.is_present("IGNORECHECK");
    let flash = matches.value_of("BLINK").expect("bug: BLINK argument").parse::<u8>()?;
    let red = u32::from_str_radix(matches.value_of("RED").expect("bug: RED argument"), 16)?;
    let green = u32::from_str_radix(matches.value_of("GREEN").expect("bug: GREEN argument"), 16)?;
    let blue = u32::from_str_radix(matches.value_of("BLUE").expect("bug: BLUE argument"), 16)?;
    let step_duration = matches.value_of("STEPDURATION").expect("bug: STEPDURATION argument")
                               .parse::<u16>()?;
    let invs = matches.values_of("INVHALF").map(|i| i.collect()).unwrap_or(Vec::new());

    // Check if indeed a NCT6795D
    if !ignore {
        outb(f, base_port, REG_DEVID_MSB)?;
        let msb = inb(f, base_port + 1)?;
        outb(f, base_port, REG_DEVID_LSB)?;
        let ident = (msb as u16) << 8 | inb(f, base_port + 1)? as u16;
        if ident & 0xFFF0 != NCT6795D_MASK {
            let err: Result<()> = Err("`--ignore-check` flag, which would skip the check, \
                                       is not specified (may be dangerous); \
                                       also try `--base-port`".into());
            return err.chain_err(|| format!("The sI/O chip identifies as {:x}, which does not \
                                            seem to be NCT6795D", ident));
        }
    }

    // Select the 0x12th bank.
    outb(f, base_port, 0x07)?;
    outb(f, base_port + 1, RGB_BANK)?;

    // Check if RGB control enabled?
    outb(f, base_port, 0xe0)?;
    let d = inb(f, base_port + 1)?;
    if d & 0xe0 != 0xe0 {
        outb(f, base_port + 1, 0xe0 | (d & !0xe0))?;
    }

    let e4_val = if disable { 1 } else { 0 } |
                 if pulse { 0b1000 } else { 0 } |
                 if flash == 0 { 0 } else { (flash + 1) & 0b111 };
    write_byte_to_cell(f, base_port, 0xe4, e4_val)?;

    write_byte_to_cell(f, base_port, 0xfe, step_duration as u8)?;
    let ff_val = (step_duration >> 8) as u8 & 1 |
                 0b10 | // if 0 disable lights on rgb header only, not on board
                 if invs.contains(&"b") { 0b10000 } else { 0 } |
                 if invs.contains(&"g") { 0b01000 } else { 0 } |
                 if invs.contains(&"r") { 0b00100 } else { 0 };
    write_byte_to_cell(f, base_port, 0xff, ff_val)?;

    write_colour(f, base_port, REDCELL, red)?;
    write_colour(f, base_port, GREENCELL, green)?;
    write_colour(f, base_port, BLUECELL, blue)?;

    Ok(())
}

/// Wrapper which enables and disables the advanced mode
fn run_wrap<'a>(matches: ArgMatches<'a>) -> Result<()> {
    let base_port = u16::from_str_radix(matches.value_of("BASEPORT")
                                               .expect("bug: BASEPORT argument"), 16)?;

    let mut f = fs::OpenOptions::new().read(true).write(true).open("/dev/port")
        .chain_err(|| { "could not open /dev/port; try sudo?" })?;
    // Enable the advanced mode.
    outb(&mut f, base_port, 0x87).chain_err(|| "could not enable advanced mode")?;
    outb(&mut f, base_port, 0x87).chain_err(|| "could not enable advanced mode")?;

    // These are something the built-in app does during initialization…
    // Purpose unclear
    // outb(&mut f, base_port, 0x07)?;
    // outb(&mut f, base_port + 1, 0x0B)?;
    // outb(&mut f, base_port, 0x60)?;
    // let a = inb(&mut f, base_port + 1)?;
    // outb(&mut f, base_port, 0x61)?;
    // let b = inb(&mut f, base_port + 1)?;
    // println!("{:x} {:x}", a, b);

    // purpose unclear
    // outb(&mut f, base_port, 0x07)?;
    // outb(&mut f, base_port + 1, 0x09)?;
    // outb(&mut f, base_port, 0x2c)?;
    // let c = inb(&mut f, base_port + 1)?;
    // println!("{:x}", c);

    // enables RGB? Nope...
    // outb(&mut f, base_port, 0x2c)?;
    // outb(&mut f, base_port + 1, 0x11)?;

    let r = run(&mut f, base_port, matches);
    // Disable the advanced mode.
    outb(&mut f, base_port, 0xAA).chain_err(|| "could not disable advanced mode")?;
    r.chain_err(|| "could not set the colour")
}

fn main() {
    let matches = App::new("msi-rgb")
        .version(option_env!("CARGO_PKG_VERSION").unwrap_or("0.0.0"))
        .about(option_env!("CARGO_PKG_DESCRIPTION").unwrap_or(""))
        .setting(clap::AppSettings::ArgRequiredElseHelp)
        .arg(Arg::with_name("RED").required(true)
             .help("values of red colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("GREEN").required(true)
             .help("values of green colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("BLUE").required(true)
             .help("values of blue colour (32 bit hex number, up to FFFFFFFF)"))
        .arg(Arg::with_name("INVHALF").long("invert").short("i").multiple(true)
             .takes_value(true).possible_values(&["r","g","b"])
             .help("invert the specified channel(s)"))
        .arg(Arg::with_name("PULSE").long("pulse").short("p")
             .help("smooth pulsing"))
        .arg(Arg::with_name("STEPDURATION").long("duration").short("d").takes_value(true)
             .default_value("25").validator(|s| { match s.parse::<u16>() {
                 Err(e) => Err(format!("{}", e)),
                 Ok(s) => if s > 511 { Err("duration must not exceed 511".into()) } else { Ok(()) }
             }})
             .help("duration between distinct steps of colours (0 - fastest, 511 - slowest"))
        .arg(Arg::with_name("BLINK").long("blink").short("b").takes_value(true).default_value("0")
             .possible_values(&["0", "1", "2", "3", "4", "5", "6"])
             .help("duration between blinks (from 0 to 6, 0 is always on, 6 is slowest)"))
        .arg(Arg::with_name("DISABLE").long("disable").short("x")
             .help("disable the RGB subsystem altogether"))
        .arg(Arg::with_name("IGNORECHECK").long("ignore-check")
             .help("ignore the result of sI/O identification check"))
        .arg(Arg::with_name("BASEPORT").long("base-port").default_value("4e")
             .help("base port to use. Values known to be in use are 4e and 2e"))
        .get_matches();

    ::std::process::exit(if let Err(e) = run_wrap(matches) {
        let _ = writeln!(::std::io::stderr(), "error: {}", e);
        for e in e.iter().skip(1) {
            let _ = writeln!(::std::io::stderr(), "    caused by: {}", e);
        }
        1
    } else {
        0
    });
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate "rust-md2" as md2;

use md2::{S, S2, md2_compress};
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::slice::bytes::copy_memory;

type Collision = Vec<Vec<u8>>;
type Collisions = Vec<Collision>;

fn find_collisions(k: uint) -> Collisions {
    let mut values = create_initial_state(k);
    let mut bytes = Vec::from_elem(k, 0u8);
    let mut collisions: HashMap<Vec<u8>,Collision> = HashMap::new();

    let rows = 16 - k;

    loop {
        copy_memory(values[rows].slice_mut(17, 17 + k), bytes.as_slice());
        copy_memory(values[rows].slice_mut(17 + 16, 17 + k + 16), bytes.as_slice());

        for row in range(rows + 1, 18) {
            // Fill row.
            for i in range(1, 49) {
                values[row][i] = S[values[row][i - 1] as uint] ^ values[row - 1][i];
            }

            // Next t value.
            values[row + 1][0] = values[row][48] + (row as u8) - 1;
        }

        let key = Vec::from_fn(17 - rows, |row| values[rows + 2 + row][0]);

        match collisions.entry(key) {
            Vacant(entry) => { entry.set(vec!(bytes.clone())); },
            Occupied(mut entry) => { entry.get_mut().push(bytes.clone()); }
        };

        if !increase(bytes.as_mut_slice()) {
            break;
        }
    }

    // Compute original messages for each collision.
    collisions.values().filter(|x| x.len() > 1).map(|collision| {
        collision.iter().map(|bytes| {
            copy_memory(values[rows].slice_mut(17, 17 + k), bytes.as_slice());
            copy_memory(values[rows].slice_mut(17 + 16, 17 + k + 16), bytes.as_slice());

            // Fill upper rectangles.
            for row in range(1, rows + 1).rev() {
                for col in range(17, 32 - row + 2) {
                    values[row - 1][col] = S[values[row][col - 1] as uint] ^ values[row][col];
                }
            }

            values[0].slice(17, 33).to_vec()
        }).collect()
    }).collect()
}

fn create_initial_state(k: uint) -> [[u8, ..49], ..19] {
    let rows = 16 - k;
    let mut values = [[0u8, ..49], ..19];

    for row in range(1, rows + 1) {
        // Fill row of T1.
        for i in range(1, 17) {
            values[row][i] = S[values[row][i - 1] as uint] ^ values[row - 1][i];
        }

        // Last bytes are equal.
        values[row][32] = values[row][16];
        values[row][48] = values[row][16];

        // Next t value.
        values[row + 1][0] = values[row][48] + (row as u8) - 1;
    }

    // Compute triangles.
    for col in range(0, rows) {
        for row in range(2 + col, rows + 1).rev() {
            values[row][32 - col - 1] = S2[(values[row][32 - col] ^ values[row - 1][32 - col]) as uint];
            values[row][48 - col - 1] = S2[(values[row][48 - col] ^ values[row - 1][48 - col]) as uint];
        }
    }

    values
}

fn increase(num: &mut [u8]) -> bool {
    let len = num.len();

    // Iterate bytes starting from the end.
    for i in range(0, len).rev() {
        if num[i] == 255 {
            continue;
        }

        // Increase.
        num[i] += 1;

        // Set all bytes right of the current index to zero.
        for i in range(i + 1, len) {
            num[i] = 0;
        }

        return true;
    }

    // Increasing any further would overflow.
    false
}

fn check_collisions(collisions: &Collisions) -> bool {
    let empty = [0u8, ..16];

    for collision in collisions.iter() {
        let mut first_hash: Option<[u8, ..16]> = None;

        for msg in collision.iter() {
            let md2 = md2_compress(&empty, msg.as_slice());

            match first_hash {
                Some(hash) => {
                    if hash != md2 {
                        return false;
                    }
                }
                None => first_hash = Some(md2)
            };
        }
    }

    true
}

fn main() {
    let collisions = find_collisions(2);
    if !check_collisions(&collisions) {
        panic!("invalid collision found :(");
    }

    println!("Found {} collisions.", collisions.iter().count());
}
<commit_msg>pass state to find_collisions()<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */

extern crate "rust-md2" as md2;

use md2::{S, S2, md2_compress};
use std::collections::HashMap;
use std::collections::hash_map::{Occupied, Vacant};
use std::slice::bytes::copy_memory;

type Collision = Vec<Vec<u8>>;
type Collisions = Vec<Collision>;

fn find_collisions(state: [[u8, ..49], ..19], k: uint) -> Collisions {
    let mut state = state;
    let mut bytes = Vec::from_elem(k, 0u8);
    let mut collisions: HashMap<Vec<u8>,Collision> = HashMap::new();

    let rows = 16 - k;

    loop {
        copy_memory(state[rows].slice_mut(17, 17 + k), bytes.as_slice());
        copy_memory(state[rows].slice_mut(17 + 16, 17 + k + 16), bytes.as_slice());

        for row in range(rows + 1, 18) {
            // Fill row.
            for i in range(1, 49) {
                state[row][i] = S[state[row][i - 1] as uint] ^ state[row - 1][i];
            }

            // Next t value.
            state[row + 1][0] = state[row][48] + (row as u8) - 1;
        }

        let key = Vec::from_fn(17 - rows, |row| state[rows + 2 + row][0]);

        match collisions.entry(key) {
            Vacant(entry) => { entry.set(vec!(bytes.clone())); },
            Occupied(mut entry) => { entry.get_mut().push(bytes.clone()); }
        };

        if !increase(bytes.as_mut_slice()) {
            break;
        }
    }

    // Compute original messages for each collision.
    collisions.values().filter(|x| x.len() > 1).map(|collision| {
        collision.iter().map(|bytes| {
            copy_memory(state[rows].slice_mut(17, 17 + k), bytes.as_slice());
            copy_memory(state[rows].slice_mut(17 + 16, 17 + k + 16), bytes.as_slice());

            // Fill upper rectangles.
            for row in range(1, rows + 1).rev() {
                for col in range(17, 32 - row + 2) {
                    state[row - 1][col] = S[state[row][col - 1] as uint] ^ state[row][col];
                }
            }

            state[0].slice(17, 33).to_vec()
        }).collect()
    }).collect()
}

fn create_initial_state(k: uint) -> [[u8, ..49], ..19] {
    let rows = 16 - k;
    let mut values = [[0u8, ..49], ..19];

    for row in range(1, rows + 1) {
        // Fill row of T1.
        for i in range(1, 17) {
            values[row][i] = S[values[row][i - 1] as uint] ^ values[row - 1][i];
        }

        // Last bytes are equal.
        values[row][32] = values[row][16];
        values[row][48] = values[row][16];

        // Next t value.
        values[row + 1][0] = values[row][48] + (row as u8) - 1;
    }

    // Compute triangles.
    for col in range(0, rows) {
        for row in range(2 + col, rows + 1).rev() {
            values[row][32 - col - 1] = S2[(values[row][32 - col] ^ values[row - 1][32 - col]) as uint];
            values[row][48 - col - 1] = S2[(values[row][48 - col] ^ values[row - 1][48 - col]) as uint];
        }
    }

    values
}

fn increase(num: &mut [u8]) -> bool {
    let len = num.len();

    // Iterate bytes starting from the end.
    for i in range(0, len).rev() {
        if num[i] == 255 {
            continue;
        }

        // Increase.
        num[i] += 1;

        // Set all bytes right of the current index to zero.
        for i in range(i + 1, len) {
            num[i] = 0;
        }

        return true;
    }

    // Increasing any further would overflow.
    false
}

fn check_collisions(collisions: &Collisions) -> bool {
    let empty = [0u8, ..16];

    for collision in collisions.iter() {
        let mut first_hash: Option<[u8, ..16]> = None;

        for msg in collision.iter() {
            let md2 = md2_compress(&empty, msg.as_slice());

            match first_hash {
                Some(hash) => {
                    if hash != md2 {
                        return false;
                    }
                }
                None => first_hash = Some(md2)
            };
        }
    }

    true
}

fn main() {
    let k = 2;
    let state = create_initial_state(k);
    let collisions = find_collisions(state.clone(), k);
    if !check_collisions(&collisions) {
        panic!("invalid collision found :(");
    }

    println!("Found {} collisions.", collisions.iter().count());
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "clippy", deny(warnings))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]

extern crate bs58;
extern crate byteorder;
extern crate clap;
extern crate crypto;
extern crate curve25519_dalek;
extern crate ocl_core as core;
extern crate ring;

mod address;
mod device;
mod pattern;
mod sha256;
mod util;

use clap::{App, Arg};
use core::{PlatformInfo, DeviceInfo, DeviceId, PlatformId};
use pattern::Pattern;
use ring::rand::SystemRandom;
use std::{str, thread, time};
use std::fs::File;
use std::io::{self, Read, Write};
use std::sync::Arc;
use std::sync::atomic;
use std::sync::mpsc::{self, Sender, Receiver};

fn main() {
    let matches = App::new("Zcash Vanity Address Generator")
        .version("0.0.1")
        .about("Generates Zcash shielded addresses (\"z-addrs\") that match given prefixes.")
        .arg(Arg::with_name("device")
             .short("d")
             .takes_value(true)
             .number_of_values(1)
             .multiple(true)
             .help("OpenCL device string: <platform>:<device>.\n\
                    Specify multiple times for multiple devices, e.g. -d 0:0 -d 0:1.\n\
                    If not specified, uses all available platforms and devices."))
        .arg(Arg::with_name("file")
             .short("f")
             .takes_value(true)
             .help("Load prefixes from file, one per line.\nCan be combined with --insensitive."))
        .arg(Arg::with_name("insensitive")
             .short("i")
             .help("Case-insensitive prefix search."))
        .arg(Arg::with_name("continue")
             .short("c")
             .help("Continue searching after a match is found."))
        .arg(Arg::with_name("pattern")
             .index(1)
             .help("Zcash address prefix to be matched."))
        .after_help("Matches will be printed to stdout; each z-addr on its own line followed by its spending key on the next line.\n\
                     You can import the spending key to your Zcash client using `zcash-cli z_importkey <key> <rescan>`.")
        .get_matches();

    let mut device_specifiers = if matches.is_present("device") {
        matches.values_of("device").unwrap().map(|s| {
            let mut values = s.split(':');
            (values.next().unwrap().parse::<usize>().unwrap(), values.next().unwrap().parse::<usize>().unwrap())
        }).collect()
    } else {
        vec![]
    };
    device_specifiers.sort();
    let mut device_specifiers_iter = device_specifiers.into_iter();

    let mut stderr = io::stderr();
    let mut devices = vec![];
    let mut device_specifier = device_specifiers_iter.next();
    let all_devices = device_specifier.is_none();
    for (i, &platform) in core::get_platform_ids().unwrap().iter().enumerate() {
        writeln!(&mut stderr, "Available devices on platform {}:", core::get_platform_info(&platform, PlatformInfo::Name)).unwrap();
        for (j, &device) in core::get_device_ids(&platform, None, None).unwrap().iter().enumerate() {
            writeln!(&mut stderr, "  {}:{} {}", i, j, core::get_device_info(device, DeviceInfo::Name)).unwrap();
            if all_devices || Some((i, j)) == device_specifier {
                devices.push((platform, device));
                device_specifier = device_specifiers_iter.next();
            }
        }
    }
    stderr.flush().unwrap();

    let mut patterns = if let Some(filename) = matches.value_of("file") {
        let mut file = File::open(&filename).unwrap();
        let mut contents = String::new();
        file.read_to_string(&mut contents).unwrap();
        contents.lines().map(|s| Pattern::new(s.to_string()).unwrap()).collect()
    } else {
        vec![Pattern::new(matches.value_of("pattern").unwrap_or("").to_string()).unwrap()]
    };

    if matches.is_present("insensitive") {
        patterns = patterns.iter().flat_map(|p| p.case_insensitive()).collect()
    }

    vanity(&devices, &patterns, !matches.is_present("continue"));
}

fn vanity(devices: &[(PlatformId, DeviceId)], patterns: &[Pattern], single_match: bool) {
    let mut pattern_prefixes: Vec<String> = patterns.into_iter().map(|p| p.prefix.to_owned()).collect();
    pattern_prefixes.sort();

    let mut pattern_ranges: Vec<(u64, u64)> = patterns.iter().map(|p| p.range).collect();
    pattern_ranges.sort_by_key(|r| r.0);

    // TODO: the pairs in pattern_words are guaranteed to be sorted, but only by virtue of
    // lexicographic ordering of the default base58 alphabet being equivalent to ordering of the
    // big-endian data.
    let mut pattern_words = vec![];
    let mut search_size = 0.0_f64;
    for (from, to) in pattern_ranges {
        pattern_words.push(from);
        pattern_words.push(to);
        search_size += 1.0_f64 + (to - from) as f64;
    }

    let (tx, rx): (Sender<u64>, Receiver<u64>) = mpsc::channel();
    let pattern_prefixes = Arc::new(pattern_prefixes);
    let pattern_words = Arc::new(pattern_words);
    let rng = Arc::new(SystemRandom::new());
    let finished = Arc::new(atomic::AtomicBool::new(false));

    for &device_specifier in devices {
        let tx = tx.clone();
        let pattern_prefixes = pattern_prefixes.clone();
        let pattern_words = pattern_words.clone();
        let rng = rng.clone();
        let finished = finished.clone();
        thread::spawn(move || {
            device::vanity_device(&*finished, &*rng, &tx, device_specifier.0, device_specifier.1, &*pattern_prefixes, &*pattern_words, single_match);
            finished.store(true, atomic::Ordering::Relaxed);
        });
    }
    drop(tx);

    let difficulty = 2.0_f64.powi(64) / search_size;
    let start = time::Instant::now();
    let mut cumulative_work = 0u64;
    let mut now = start;
    let mut stderr = io::stderr();

    while let Ok(work) = rx.recv() {
        cumulative_work += work;
        let now_elapsed = now.elapsed();

        if now_elapsed.as_secs() > 0 {
            let start_elapsed = start.elapsed();
            let start_elapsed_secs = (start_elapsed.as_secs() as f64) + (start_elapsed.subsec_nanos() as f64 / 1_000_000_000.0);

            let rate = cumulative_work as f64 / (now_elapsed.as_secs() as f64) + (now_elapsed.subsec_nanos() as f64 / 1_000_000_000.0);
            let lambda = rate / difficulty;
            let probability = 1. - (-start_elapsed_secs * lambda).exp();

            write!(&mut stderr, "\rElapsed: {:.0}/{:.0}s Rate: {:.0}/s Prob: {:.2}%", start_elapsed_secs, 1. / lambda, rate, 100. * probability).unwrap();
            stderr.flush().unwrap();

            cumulative_work = 0;
            now += now_elapsed;
        }
    }
}
<commit_msg>Fix version shown by --version.<commit_after>#![cfg_attr(feature = "clippy", deny(warnings))]
#![cfg_attr(feature = "clippy", feature(plugin))]
#![cfg_attr(feature = "clippy", plugin(clippy))]
#![cfg_attr(feature = "clippy", allow(too_many_arguments))]

extern crate bs58;
extern crate byteorder;
extern crate clap;
extern crate crypto;
extern crate curve25519_dalek;
extern crate ocl_core as core;
extern crate ring;

mod address;
mod device;
mod pattern;
mod sha256;
mod util;

use clap::{App, Arg};
use core::{PlatformInfo, DeviceInfo, DeviceId, PlatformId};
use pattern::Pattern;
use ring::rand::SystemRandom;
use std::{str, thread, time};
use std::fs::File;
use std::io::{self, Read, Write};
use std::sync::Arc;
use std::sync::atomic;
use std::sync::mpsc::{self, Sender, Receiver};

fn main() {
    let matches = App::new("Zcash Vanity Address Generator")
        .version(env!("CARGO_PKG_VERSION"))
        .about("Generates Zcash shielded addresses (\"z-addrs\") that match given prefixes.")
        .arg(Arg::with_name("device")
             .short("d")
             .takes_value(true)
             .number_of_values(1)
             .multiple(true)
             .help("OpenCL device string: <platform>:<device>.\n\
                    Specify multiple times for multiple devices, e.g. -d 0:0 -d 0:1.\n\
                    If not specified, uses all available platforms and devices."))
        .arg(Arg::with_name("file")
             .short("f")
             .takes_value(true)
             .help("Load prefixes from file, one per line.\nCan be combined with --insensitive."))
        .arg(Arg::with_name("insensitive")
             .short("i")
             .help("Case-insensitive prefix search."))
        .arg(Arg::with_name("continue")
             .short("c")
             .help("Continue searching after a match is found."))
        .arg(Arg::with_name("pattern")
             .index(1)
             .help("Zcash address prefix to be matched."))
        .after_help("Matches will be printed to stdout; each z-addr on its own line followed by its spending key on the next line.\n\
                     You can import the spending key to your Zcash client using `zcash-cli z_importkey <key> <rescan>`.")
        .get_matches();

    let mut device_specifiers = if matches.is_present("device") {
        matches.values_of("device").unwrap().map(|s| {
            let mut values = s.split(':');
            (values.next().unwrap().parse::<usize>().unwrap(), values.next().unwrap().parse::<usize>().unwrap())
        }).collect()
    } else {
        vec![]
    };
    device_specifiers.sort();
    let mut device_specifiers_iter = device_specifiers.into_iter();

    let mut stderr = io::stderr();
    let mut devices = vec![];
    let mut device_specifier = device_specifiers_iter.next();
    let all_devices = device_specifier.is_none();
    for (i, &platform) in core::get_platform_ids().unwrap().iter().enumerate() {
        writeln!(&mut stderr, "Available devices on platform {}:", core::get_platform_info(&platform, PlatformInfo::Name)).unwrap();
        for (j, &device) in core::get_device_ids(&platform, None, None).unwrap().iter().enumerate() {
            writeln!(&mut stderr, "  {}:{} {}", i, j, core::get_device_info(device, DeviceInfo::Name)).unwrap();
            if all_devices || Some((i, j)) == device_specifier {
                devices.push((platform, device));
                device_specifier = device_specifiers_iter.next();
            }
        }
    }
    stderr.flush().unwrap();

    let mut patterns = if let Some(filename) = matches.value_of("file") {
        let mut file = File::open(&filename).unwrap();
        let mut contents = String::new();
        file.read_to_string(&mut contents).unwrap();
        contents.lines().map(|s| Pattern::new(s.to_string()).unwrap()).collect()
    } else {
        vec![Pattern::new(matches.value_of("pattern").unwrap_or("").to_string()).unwrap()]
    };

    if matches.is_present("insensitive") {
        patterns = patterns.iter().flat_map(|p| p.case_insensitive()).collect()
    }

    vanity(&devices, &patterns, !matches.is_present("continue"));
}

fn vanity(devices: &[(PlatformId, DeviceId)], patterns: &[Pattern], single_match: bool) {
    let mut pattern_prefixes: Vec<String> = patterns.into_iter().map(|p| p.prefix.to_owned()).collect();
    pattern_prefixes.sort();

    let mut pattern_ranges: Vec<(u64, u64)> = patterns.iter().map(|p| p.range).collect();
    pattern_ranges.sort_by_key(|r| r.0);

    // TODO: the pairs in pattern_words are guaranteed to be sorted, but only by virtue of
    // lexicographic ordering of the default base58 alphabet being equivalent to ordering of the
    // big-endian data.
    let mut pattern_words = vec![];
    let mut search_size = 0.0_f64;
    for (from, to) in pattern_ranges {
        pattern_words.push(from);
        pattern_words.push(to);
        search_size += 1.0_f64 + (to - from) as f64;
    }

    let (tx, rx): (Sender<u64>, Receiver<u64>) = mpsc::channel();
    let pattern_prefixes = Arc::new(pattern_prefixes);
    let pattern_words = Arc::new(pattern_words);
    let rng = Arc::new(SystemRandom::new());
    let finished = Arc::new(atomic::AtomicBool::new(false));

    for &device_specifier in devices {
        let tx = tx.clone();
        let pattern_prefixes = pattern_prefixes.clone();
        let pattern_words = pattern_words.clone();
        let rng = rng.clone();
        let finished = finished.clone();
        thread::spawn(move || {
            device::vanity_device(&*finished, &*rng, &tx, device_specifier.0, device_specifier.1, &*pattern_prefixes, &*pattern_words, single_match);
            finished.store(true, atomic::Ordering::Relaxed);
        });
    }
    drop(tx);

    let difficulty = 2.0_f64.powi(64) / search_size;
    let start = time::Instant::now();
    let mut cumulative_work = 0u64;
    let mut now = start;
    let mut stderr = io::stderr();

    while let Ok(work) = rx.recv() {
        cumulative_work += work;
        let now_elapsed = now.elapsed();

        if now_elapsed.as_secs() > 0 {
            let start_elapsed = start.elapsed();
            let start_elapsed_secs = (start_elapsed.as_secs() as f64) + (start_elapsed.subsec_nanos() as f64 / 1_000_000_000.0);

            let rate = cumulative_work as f64 / (now_elapsed.as_secs() as f64) + (now_elapsed.subsec_nanos() as f64 / 1_000_000_000.0);
            let lambda = rate / difficulty;
            let probability = 1. - (-start_elapsed_secs * lambda).exp();

            write!(&mut stderr, "\rElapsed: {:.0}/{:.0}s Rate: {:.0}/s Prob: {:.2}%", start_elapsed_secs, 1. / lambda, rate, 100. * probability).unwrap();
            stderr.flush().unwrap();

            cumulative_work = 0;
            now += now_elapsed;
        }
    }
}
<|endoftext|>