<commit_before>extern crate resp;
extern crate rusqlite;

use self::resp::{Value};
use self::rusqlite::{Connection};
use std::sync::{Arc, Mutex, MutexGuard};
use std::cmp;

type CommandResult = Result<Value, String>;

struct Command<'a> {
    name: String,
    arguments: Vec<&'a String>,
    connection_mutex: &'a Arc<Mutex<Connection>>
}

struct CommandSettings {
    name: &'static str,
    argument_count: i32,
    //handler: fn(&'a Command<'a>) -> CommandResult
}

enum Direction {
    Left,
    Right
}

const COMMAND_SETTINGS: [CommandSettings; 6] = [
    CommandSettings { name: "LLEN", argument_count: 1 }, //, handler: Command::llen }
    CommandSettings { name: "LPOP", argument_count: 1 },
    CommandSettings { name: "RPOP", argument_count: 1 },
    CommandSettings { name: "LPUSH", argument_count: -2 },
    CommandSettings { name: "RPUSH", argument_count: -2 },
    CommandSettings { name: "LRANGE", argument_count: 3 },
];

pub fn handle_input(ref value: Value, connection_mutex: &Arc<Mutex<Connection>>) -> (Value, bool) {
    match parse_command(value, connection_mutex) {
        Ok(mut command) => { command.handle_command() }
        Err(error)  => { (Value::Error(format!("ERR {}", error)), false) }
    }
}

fn parse_command<'a>(value: &'a Value, connection_mutex: &'a Arc<Mutex<Connection>>) -> Result<Command<'a>, &'static str> {
    if let &Value::Array(ref array) = value {
        parse_command_array(array, connection_mutex)
    }
    else {
        Err("expected array")
    }
}

fn parse_command_array<'a>(array: &'a Vec<Value>, connection_mutex: &'a Arc<Mutex<Connection>>) -> Result<Command<'a>, &'static str> {
    let iter = array.iter().map(|value|
        match *value {
            Value::String(ref string) | Value::Bulk(ref string) => Ok(string),
            _ => Err("all arguments should be strings")
        }
    );

    let strings = iter.collect::<Result<Vec<&String>, &'static str>>()?;
    let (head, tail) = strings.split_at(1);

    Ok(Command {
        name: head[0].to_uppercase(),
        arguments: tail.to_vec(),
        connection_mutex: connection_mutex
    })
}

impl<'a> Command<'a> {
    fn handle_command(&mut self) -> (Value, bool) {
        print!("command {}\n", self.name);

        match self.name.as_ref() {
            "QUIT" => (Value::String("OK".to_string()), true),
            _      => (self.handle_nonterminal_command(), false)
        }
    }

    fn valid_argument_count(&self, command: &CommandSettings) -> bool {
        (command.argument_count < 0 && self.arguments.len() as i32 >= -command.argument_count) ||
            (command.argument_count >= 0 && self.arguments.len() as i32 == command.argument_count)
    }

    fn handle_nonterminal_command(&mut self) -> Value {
        let all = COMMAND_SETTINGS;
        let settings = all.iter().find(|settings| settings.name == self.name);

        match settings {
            Some(settings) => {
                if self.valid_argument_count(settings) {
                    let result = match settings.name {
                        "LLEN" => self.llen(),
                        "LPUSH" => self.lpush(),
                        "RPUSH" => self.rpush(),
                        "LPOP" => self.lpop(),
                        "RPOP" => self.rpop(),
                        "LRANGE" => self.lrange(),
                        _ => unimplemented!(),
                    };

                    match result {
                        Ok(value)  => value,
                        Err(error) => Value::Error(format!("ERR {}", error))
                    }
                }
                else {
                    Value::Error("ERR wrong number of arguments".to_string())
                }
            }

            None => Value::Error("ERR unsupported".to_string())
        }
    }

    fn llen(&self) -> CommandResult {
        let key = self.arguments[0];

        let connection = self.lock_connection();
        self.count_list_items_value(&*connection, key)
    }

    fn lpop(&self) -> CommandResult {
        self.pop("ASC")
    }

    fn rpop(&self) -> CommandResult {
        self.pop("DESC")
    }

    fn lpush(&self) -> CommandResult {
        let key = self.arguments[0];
        let mut connection = self.lock_connection();

        self.push(&mut *connection, Direction::Left);

        self.count_list_items_value(&*connection, key)
    }

    fn rpush(&self) -> CommandResult {
        let key = self.arguments[0];
        let mut connection = self.lock_connection();

        self.push(&mut *connection, Direction::Right);

        self.count_list_items_value(&*connection, key)
    }

    fn lrange(&self) -> CommandResult {
        let key = self.arguments[0];
        let mut start: i64 = self.arguments[1].parse().map_err(|_| "start must be an integer")?;
        let mut stop: i64 = self.arguments[2].parse().map_err(|_| "stop must be an integer")?;

        let connection = self.lock_connection();

        if start < 0 || stop < -1 {
            let count = self.count_list_items(&connection, key);

            if start < 0  { start = cmp::max(0, count + start) }

            if stop < -1 {
                stop = count + stop;
                if stop < 0 { return Ok(Value::Array(vec![])); }
            }
        }

        if stop != -1 && start > stop { return Ok(Value::Array(vec![])); }

        let sql = match (start, stop) {
            (0, -1) => "".to_string(),
            (a, -1) => format!("LIMIT -1 OFFSET {}", a),
            (0, b)  => format!("LIMIT {}", b + 1),
            (a, b)  => format!("LIMIT {} OFFSET {}", b - a + 1, a),
        };

        let mut statement = connection.prepare(&format!("SELECT value FROM list_items WHERE key = ?1 ORDER BY position {}", sql)).unwrap();
        let rows = statement.query_map(&[key], |row| row.get(0)).unwrap();
        let result: Result<Vec<String>, _> = rows.collect();
        let values = result.unwrap().iter().map(|value| Value::String(value.clone())).collect();

        Ok(Value::Array(values))
    }

    // private

    fn pop(&self, order: &'static str) -> CommandResult {
        let key = self.arguments[0];

        let connection = self.lock_connection();
        let mut statement = connection.prepare(&format!("SELECT id, value FROM list_items WHERE key = ?1 ORDER BY position {} LIMIT 1", order)).unwrap();

        match statement.query_row(&[key], |row| (row.get(0), row.get(1))) {
            Ok(result) => {
                let (id, value): (i64, String) = result;

                connection.execute("DELETE FROM list_items WHERE id = ?1", &[&id]).unwrap();
                Ok(Value::Bulk(value))
            }

            Err(rusqlite::Error::QueryReturnedNoRows) => Ok(Value::NullArray),

            Err(e) => Err(e).unwrap()
        }
    }

    fn push(&self, connection: &mut Connection, direction: Direction) -> () {
        let key = self.arguments[0];

        {
            let tx = connection.transaction().unwrap();

            let next_position_sql = match direction {
                Direction::Left  => "coalesce(MIN(position), 0) - 1",
                Direction::Right => "coalesce(MAX(position), 0) + 1"
            };

            let sql = format!("INSERT INTO list_items (key, value, position) SELECT ?1, ?2, {} FROM list_items WHERE key = ?1", next_position_sql);

            self.arguments.iter().skip(1).map(|value| tx.execute(&sql, &[key, *value])).collect::<Result<Vec<_>, _>>().unwrap();

            tx.commit().unwrap();
        }
    }

    fn lock_connection(&self) -> MutexGuard<Connection> {
        (*self.connection_mutex).lock().unwrap()
    }

    fn count_list_items(&self, connection: &Connection, key: &String) -> i64 {
        let mut statement = connection.prepare("SELECT COUNT(*) AS c FROM list_items WHERE key = ?1").unwrap();
        statement.query_row(&[key], |row| row.get(0)).unwrap()
    }

    fn count_list_items_value(&self, connection: &Connection, key: &String) -> CommandResult {
        Ok(Value::Integer(self.count_list_items(connection, key)))
    }
}
<commit_msg>ltrim<commit_after>extern crate resp;
extern crate rusqlite;

use self::resp::{Value};
use self::rusqlite::{Connection};
use std::sync::{Arc, Mutex, MutexGuard};
use std::cmp;

type CommandResult = Result<Value, String>;

struct Command<'a> {
    name: String,
    arguments: Vec<&'a String>,
    connection_mutex: &'a Arc<Mutex<Connection>>
}

struct CommandSettings {
    name: &'static str,
    argument_count: i32,
    //handler: fn(&'a Command<'a>) -> CommandResult
}

enum Direction {
    Left,
    Right
}

const COMMAND_SETTINGS: [CommandSettings; 7] = [
    CommandSettings { name: "LLEN", argument_count: 1 }, //, handler: Command::llen }
    CommandSettings { name: "LPOP", argument_count: 1 },
    CommandSettings { name: "RPOP", argument_count: 1 },
    CommandSettings { name: "LPUSH", argument_count: -2 },
    CommandSettings { name: "RPUSH", argument_count: -2 },
    CommandSettings { name: "LRANGE", argument_count: 3 },
    CommandSettings { name: "LTRIM", argument_count: 3 },
];

pub fn handle_input(ref value: Value, connection_mutex: &Arc<Mutex<Connection>>) -> (Value, bool) {
    match parse_command(value, connection_mutex) {
        Ok(mut command) => { command.handle_command() }
        Err(error)  => { (Value::Error(format!("ERR {}", error)), false) }
    }
}

fn parse_command<'a>(value: &'a Value, connection_mutex: &'a Arc<Mutex<Connection>>) -> Result<Command<'a>, &'static str> {
    if let &Value::Array(ref array) = value {
        parse_command_array(array, connection_mutex)
    }
    else {
        Err("expected array")
    }
}

fn parse_command_array<'a>(array: &'a Vec<Value>, connection_mutex: &'a Arc<Mutex<Connection>>) -> Result<Command<'a>, &'static str> {
    let iter = array.iter().map(|value|
        match *value {
            Value::String(ref string) | Value::Bulk(ref string) => Ok(string),
            _ => Err("all arguments should be strings")
        }
    );

    let strings = iter.collect::<Result<Vec<&String>, &'static str>>()?;
    let (head, tail) = strings.split_at(1);

    Ok(Command {
        name: head[0].to_uppercase(),
        arguments: tail.to_vec(),
        connection_mutex: connection_mutex
    })
}

impl<'a> Command<'a> {
    fn handle_command(&mut self) -> (Value, bool) {
        print!("command {}\n", self.name);

        match self.name.as_ref() {
            "QUIT" => (Value::String("OK".to_string()), true),
            _      => (self.handle_nonterminal_command(), false)
        }
    }

    fn valid_argument_count(&self, command: &CommandSettings) -> bool {
        (command.argument_count < 0 && self.arguments.len() as i32 >= -command.argument_count) ||
            (command.argument_count >= 0 && self.arguments.len() as i32 == command.argument_count)
    }

    fn handle_nonterminal_command(&mut self) -> Value {
        let all = COMMAND_SETTINGS;
        let settings = all.iter().find(|settings| settings.name == self.name);

        match settings {
            Some(settings) => {
                if self.valid_argument_count(settings) {
                    let result = match settings.name {
                        "LLEN" => self.llen(),
                        "LPUSH" => self.lpush(),
                        "RPUSH" => self.rpush(),
                        "LPOP" => self.lpop(),
                        "RPOP" => self.rpop(),
                        "LRANGE" => self.lrange(),
                        "LTRIM" => self.ltrim(),
                        _ => unimplemented!(),
                    };

                    match result {
                        Ok(value)  => value,
                        Err(error) => Value::Error(format!("ERR {}", error))
                    }
                }
                else {
                    Value::Error("ERR wrong number of arguments".to_string())
                }
            }

            None => Value::Error("ERR unsupported".to_string())
        }
    }

    fn llen(&self) -> CommandResult {
        let key = self.arguments[0];

        let connection = self.lock_connection();
        self.count_list_items_value(&*connection, key)
    }

    fn lpop(&self) -> CommandResult {
        self.pop("ASC")
    }

    fn rpop(&self) -> CommandResult {
        self.pop("DESC")
    }

    fn lpush(&self) -> CommandResult {
        let key = self.arguments[0];
        let mut connection = self.lock_connection();

        self.push(&mut *connection, Direction::Left);

        self.count_list_items_value(&*connection, key)
    }

    fn rpush(&self) -> CommandResult {
        let key = self.arguments[0];
        let mut connection = self.lock_connection();

        self.push(&mut *connection, Direction::Right);

        self.count_list_items_value(&*connection, key)
    }

    fn lrange(&self) -> CommandResult {
        let key = self.arguments[0];
        let mut start: i64 = self.arguments[1].parse().map_err(|_| "start must be an integer")?;
        let mut stop: i64 = self.arguments[2].parse().map_err(|_| "stop must be an integer")?;

        let connection = self.lock_connection();

        // LATER : maybe use find_position_boundaries and parse_positions instead of this
        // this needs only one select rather than two in the case where start and stop >= 0
        // but then it uses order & limit which are probably slower on a huge table
        // investigate performance at a later date

        if start < 0 || stop < -1 {
            let count = self.count_list_items(&connection, key);

            if start < 0  { start = cmp::max(0, count + start) }

            if stop < -1 {
                stop = count + stop;
                if stop < 0 { return Ok(Value::Array(vec![])); }
            }
        }

        if stop != -1 && start > stop { return Ok(Value::Array(vec![])); }

        let sql = match (start, stop) {
            (0, -1) => "".to_string(),
            (a, -1) => format!("LIMIT -1 OFFSET {}", a),
            (0, b)  => format!("LIMIT {}", b + 1),
            (a, b)  => format!("LIMIT {} OFFSET {}", b - a + 1, a),
        };

        let mut statement = connection.prepare(&format!("SELECT value FROM list_items WHERE key = ?1 ORDER BY position {}", sql)).unwrap();
        let rows = statement.query_map(&[key], |row| row.get(0)).unwrap();
        let result: Result<Vec<String>, _> = rows.collect();
        let values = result.unwrap().iter().map(|value| Value::String(value.clone())).collect();

        Ok(Value::Array(values))
    }

    fn ltrim(&self) -> CommandResult {
        let key = self.arguments[0];
        let start: i64 = self.arguments[1].parse().map_err(|_| "start must be an integer")?;
        let stop: i64 = self.arguments[2].parse().map_err(|_| "stop must be an integer")?;

        if start != 0 || stop != -1 {
            let connection = self.lock_connection();

            let boundaries = self.find_position_boundaries(&*connection, key);
            let (start_position, stop_position) = self.parse_positions(boundaries, (start, stop));

            connection.execute("DELETE FROM list_items WHERE key = ?1 AND (position < ?2 OR position > ?3)", &[key, &start_position, &stop_position]).unwrap();
        }

        Ok(Value::String("OK".to_string()))
    }

    // private

    fn pop(&self, order: &'static str) -> CommandResult {
        let key = self.arguments[0];

        let connection = self.lock_connection();
        let mut statement = connection.prepare(&format!("SELECT id, value FROM list_items WHERE key = ?1 ORDER BY position {} LIMIT 1", order)).unwrap();

        match statement.query_row(&[key], |row| (row.get(0), row.get(1))) {
            Ok(result) => {
                let (id, value): (i64, String) = result;

                connection.execute("DELETE FROM list_items WHERE id = ?1", &[&id]).unwrap();
                Ok(Value::Bulk(value))
            }

            Err(rusqlite::Error::QueryReturnedNoRows) => Ok(Value::NullArray),

            Err(e) => Err(e).unwrap()
        }
    }

    fn push(&self, connection: &mut Connection, direction: Direction) -> () {
        let key = self.arguments[0];

        {
            let tx = connection.transaction().unwrap();

            let next_position_sql = match direction {
                Direction::Left  => "coalesce(MIN(position), 0) - 1",
                Direction::Right => "coalesce(MAX(position), 0) + 1"
            };

            let sql = format!("INSERT INTO list_items (key, value, position) SELECT ?1, ?2, {} FROM list_items WHERE key = ?1", next_position_sql);

            self.arguments.iter().skip(1).map(|value| tx.execute(&sql, &[key, *value])).collect::<Result<Vec<_>, _>>().unwrap();

            tx.commit().unwrap();
        }
    }

    fn lock_connection(&self) -> MutexGuard<Connection> {
        (*self.connection_mutex).lock().unwrap()
    }

    fn find_position_boundaries(&self, connection: &Connection, key: &String) -> (i64, i64) {
        let mut statement = connection.prepare("SELECT MIN(position), MAX(position) AS c FROM list_items WHERE key = ?1").unwrap();
        statement.query_row(&[key], |row| (row.get(0), row.get(1))).unwrap()
    }

    fn parse_positions(&self, (first_position, last_position) : (i64, i64), (start, stop): (i64, i64)) -> (i64, i64) {
        let start_position = match start {
            position if position < 0 => cmp::max(0, position + last_position + 1),
            position                 => position + first_position
        };

        let stop_position = match stop {
            position if position < 0 => cmp::max(0, position + last_position + 1),
            position                 => position + first_position
        };

        (start_position, stop_position)
    }

    fn count_list_items(&self, connection: &Connection, key: &String) -> i64 {
        let mut statement = connection.prepare("SELECT COUNT(*) AS c FROM list_items WHERE key = ?1").unwrap();
        statement.query_row(&[key], |row| row.get(0)).unwrap()
    }

    fn count_list_items_value(&self, connection: &Connection, key: &String) -> CommandResult {
        Ok(Value::Integer(self.count_list_items(connection, key)))
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main for building the genesis generation utility.

use std::io::{BufRead, Write};
use std::sync::Arc;
use std::{fs, io, path, process};

use chrono::prelude::Utc;
use chrono::{Datelike, Duration, Timelike};
use curl;
use rpassword;
use serde_json;

use cuckoo_miner as cuckoo;
use grin_chain as chain;
use grin_core as core;
use grin_miner_plugin as plugin;
use grin_store as store;
use grin_util as util;
use grin_wallet as wallet;

use grin_core::core::hash::Hashed;
use grin_core::core::verifier_cache::LruVerifierCache;
use grin_keychain::{BlindingFactor, ExtKeychain, Keychain};

static BCHAIN_INFO_URL: &str = "https://blockchain.info/latestblock";
static BCYPHER_URL: &str = "https://api.blockcypher.com/v1/btc/main";
static BCHAIR_URL: &str = "https://api.blockchair.com/bitcoin/blocks?limit=2";

static GENESIS_RS_PATH: &str = "../../core/src/genesis.rs";
static PLUGIN_PATH: &str = "./cuckaroo_mean_cuda_29.cuckooplugin";
static WALLET_SEED_PATH: &str = "./wallet.seed";

fn main() {
	if !path::Path::new(GENESIS_RS_PATH).exists() {
		panic!(
			"File {} not found, make sure you're running this from the gen_gen directory",
			GENESIS_RS_PATH
		);
	}
	if !path::Path::new(PLUGIN_PATH).exists() {
		panic!(
			"File {} not found, make sure you're running this from the gen_gen directory",
			PLUGIN_PATH
		);
	}
	if !path::Path::new(WALLET_SEED_PATH).exists() {
		panic!(
			"File {} not found, make sure you're running this from the gen_gen directory",
			WALLET_SEED_PATH
		);
	}

	// get the latest bitcoin hash
	let h1 = get_bchain_head();
	let h2 = get_bcypher_head();
	let h3 = get_bchair_head();
	if h1 != h2 || h1 != h3 {
		panic!(
			"Bitcoin chain head is inconsistent, please retry ({}, {}, {}).",
			h1, h2, h3
		);
	}
	println!("Using bitcoin block hash {}", h1);

	// build the basic parts of the genesis block header
	let mut gen = core::genesis::genesis_main();
	gen.header.timestamp = Utc::now() + Duration::minutes(30);
	gen.header.prev_root = core::core::hash::Hash::from_hex(&h1).unwrap();

	// build the wallet seed and derive a coinbase from local wallet.seed
	let seed = wallet::WalletSeed::from_file(
		&wallet::WalletConfig::default(),
		&rpassword::prompt_password_stdout("Password: ").unwrap()
	).unwrap();
	let keychain: ExtKeychain = seed.derive_keychain().unwrap();
	let key_id = ExtKeychain::derive_key_id(2, 1, 0, 0, 0);
	let reward = core::libtx::reward::output(&keychain, &key_id, 0).unwrap();
	gen = gen.with_reward(reward.0, reward.1);

	{
		// setup a tmp chain to set block header roots
		core::global::set_mining_mode(core::global::ChainTypes::AutomatedTesting);
		let tmp_chain = setup_chain(".grin.tmp", core::pow::mine_genesis_block().unwrap());
		tmp_chain.set_txhashset_roots(&mut gen).unwrap();
	}

	// mine a Cuckaroo29 block
	core::global::set_mining_mode(core::global::ChainTypes::Mainnet);
	let plugin_lib = cuckoo::PluginLibrary::new(PLUGIN_PATH).unwrap();
	let mut params = plugin_lib.get_default_params();
	params.mutate_nonce = false;
	let solver_ctx = plugin_lib.create_solver_ctx(&mut params);

	let mut solver_sols = plugin::SolverSolutions::default();
	let mut solver_stats = plugin::SolverStats::default();
	let mut nonce = 0;
	while solver_sols.num_sols == 0 {
		solver_sols = plugin::SolverSolutions::default();
		gen.header.pow.nonce = nonce;
		let _ = plugin_lib.run_solver(
			solver_ctx,
			gen.header.pre_pow(),
			nonce,
			1,
			&mut solver_sols,
			&mut solver_stats,
		);
		if solver_stats.has_errored {
			println!(
				"Plugin {} has errored, device: {}. Reason: {}",
				solver_stats.get_plugin_name(),
				solver_stats.get_device_name(),
				solver_stats.get_error_reason(),
			);
			return;
		}

		nonce += 1;
	}

	// Set the PoW solution and make sure the block is mostly valid
	gen.header.pow.proof.nonces = solver_sols.sols[0].to_u64s();
	assert!(gen.header.pow.is_secondary(), "Not a secondary header");
	println!("Built genesis:\n{:?}", gen);
	core::pow::verify_size(&gen.header).unwrap();
	gen.validate(
		&BlindingFactor::zero(),
		Arc::new(util::RwLock::new(LruVerifierCache::new())),
	)
	.unwrap();

	println!("\nFinal genesis cyclehash: {}", gen.hash().to_hex());
	let gen_bin = core::ser::ser_vec(&gen).unwrap();
	println!("Final genesis full hash: {}\n", gen_bin.hash().to_hex());

	update_genesis_rs(&gen);
	println!("genesis.rs has been updated, check it and run mainnet_genesis_hash test");
	println!("also check bitcoin block {} hasn't been orphaned.", h1);
	println!("press c+enter to proceed.");
	let mut input = String::new();
	io::stdin().read_line(&mut input).unwrap();
	if input != "c\n" {
		return;
	}

	// Commit genesis block info in git and tag
	process::Command::new("git")
		.args(&["commit", "-am", "Minor: finalized genesis block"])
		.status()
		.expect("git commit failed");
	process::Command::new("git")
		.args(&["tag", "-a", "v1.0", "-m", "Mainnet release"])
		.status()
		.expect("git tag failed");
	process::Command::new("git")
		.args(&["push", "origin", "v1.0"])
		.status()
		.expect("git tag push failed");
	println!("All done!");
}

fn update_genesis_rs(gen: &core::core::Block) {
	// set the replacement patterns
	let mut replacements = vec![];
	replacements.push((
		"timestamp".to_string(),
		format!(
			"Utc.ymd({}, {}, {}).and_hms({}, {}, {})",
			gen.header.timestamp.date().year(),
			gen.header.timestamp.date().month(),
			gen.header.timestamp.date().day(),
			gen.header.timestamp.time().hour(),
			gen.header.timestamp.time().minute(),
			gen.header.timestamp.time().second(),
		),
	));
	replacements.push((
		"prev_root".to_string(),
		format!(
			"Hash::from_hex(\"{}\").unwrap()",
			gen.header.prev_root.to_hex()
		),
	));
	replacements.push((
		"output_root".to_string(),
		format!(
			"Hash::from_hex(\"{}\").unwrap()",
			gen.header.output_root.to_hex()
		),
	));
	replacements.push((
		"range_proof_root".to_string(),
		format!(
			"Hash::from_hex(\"{}\").unwrap()",
			gen.header.range_proof_root.to_hex()
		),
	));
	replacements.push((
		"kernel_root".to_string(),
		format!(
			"Hash::from_hex(\"{}\").unwrap()",
			gen.header.kernel_root.to_hex()
		),
	));
	replacements.push((
		"total_kernel_offset".to_string(),
		format!(
			"BlindingFactor::from_hex(\"{}\").unwrap()",
			gen.header.total_kernel_offset.to_hex()
		),
	));
	replacements.push(("nonce".to_string(), format!("{}", gen.header.pow.nonce)));
	replacements.push((
		"nonces".to_string(),
		format!("vec!{:?}", gen.header.pow.proof.nonces),
	));
	replacements.push((
		"excess".to_string(),
		format!(
			"Commitment::from_vec(util::from_hex({:x?}.to_string()).unwrap())",
			util::to_hex(gen.kernels()[0].excess.0.to_vec())
		),
	));
	replacements.push((
		"excess_sig".to_string(),
		format!(
			"Signature::from_raw_data(&{:?}).unwrap()",
			gen.kernels()[0].excess_sig.to_raw_data().to_vec(),
		),
	));
	replacements.push((
		"commit".to_string(),
		format!(
			"Commitment::from_vec(util::from_hex({:x?}.to_string()).unwrap())",
			util::to_hex(gen.outputs()[0].commitment().0.to_vec())
		),
	));
	replacements.push((
		"proof".to_string(),
		format!("{:?}", gen.outputs()[0].proof.bytes().to_vec()),
	));

	// check each possible replacement in the file, remove the replacement from
	// the list when found to avoid double replacements
	let mut replaced = String::new();
	{
		let genesis_rs = fs::File::open(GENESIS_RS_PATH).unwrap();
		let reader = io::BufReader::new(&genesis_rs);
		for rline in reader.lines() {
			let line = rline.unwrap();
			let mut has_replaced = false;
			if line.contains("REPLACE") {
				for (pos, replacement) in replacements.iter().enumerate() {
					if line.contains(&replacement.0) {
						replaced.push_str(&format!("{}: {},\n", replacement.0, replacement.1));
						replacements.remove(pos);
						has_replaced = true;
						break;
					}
				}
			}
			if !has_replaced {
				replaced.push_str(&format!("{}\n", line));
			}
		}
	}
	let mut genesis_rs = fs::File::create(GENESIS_RS_PATH).unwrap();
	genesis_rs.write_all(replaced.as_bytes()).unwrap();
}

fn setup_chain(dir_name: &str, genesis: core::core::Block) -> chain::Chain {
	util::init_test_logger();
	let _ = fs::remove_dir_all(dir_name);
	let verifier_cache = Arc::new(util::RwLock::new(
		core::core::verifier_cache::LruVerifierCache::new(),
	));
	let db_env = Arc::new(store::new_env(dir_name.to_string()));
	chain::Chain::init(
		dir_name.to_string(),
		db_env,
		Arc::new(chain::types::NoopAdapter {}),
		genesis,
		core::pow::verify_size,
		verifier_cache,
		false,
		Arc::new(util::Mutex::new(util::StopState::new())),
	)
	.unwrap()
}

fn get_bchain_head() -> String {
	get_json(BCHAIN_INFO_URL)["hash"]
		.as_str()
		.unwrap()
		.to_string()
}

fn get_bcypher_head() -> String {
	get_json(BCYPHER_URL)["hash"].as_str().unwrap().to_string()
}

fn get_bchair_head() -> String {
	get_json(BCHAIR_URL)["data"][0]["hash"]
		.as_str()
		.unwrap()
		.to_string()
}

fn get_json(url: &str) -> serde_json::Value {
	let mut body = Vec::new();
	let mut easy = curl::easy::Easy::new();
	easy.url(url).unwrap();
	{
		let mut transfer = easy.transfer();
		transfer
			.write_function(|data| {
				body.extend_from_slice(data);
				Ok(data.len())
			})
			.unwrap();
		transfer.perform().unwrap();
	}
	serde_json::from_slice(&body).unwrap()
}

<commit_msg>Fix gen_gen bitcoin root setting (#2206)<commit_after>// Copyright 2018 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main for building the genesis generation utility.

use std::io::{BufRead, Write};
use std::sync::Arc;
use std::{fs, io, path};

use chrono::prelude::Utc;
use chrono::{Datelike, Duration, Timelike};
use curl;
use rpassword;
use serde_json;

use cuckoo_miner as cuckoo;
use grin_chain as chain;
use grin_core as core;
use grin_miner_plugin as plugin;
use grin_store as store;
use grin_util as util;
use grin_wallet as wallet;

use grin_core::core::hash::Hashed;
use grin_core::core::verifier_cache::LruVerifierCache;
use grin_keychain::{BlindingFactor, ExtKeychain, Keychain};

static BCHAIN_INFO_URL: &str = "https://blockchain.info/latestblock";
static BCYPHER_URL: &str = "https://api.blockcypher.com/v1/btc/main";
static BCHAIR_URL: &str = "https://api.blockchair.com/bitcoin/blocks?limit=2";

static GENESIS_RS_PATH: &str = "../../core/src/genesis.rs";
static PLUGIN_PATH: &str = "./cuckaroo_mean_cuda_29.cuckooplugin";
static WALLET_SEED_PATH: &str = "./wallet.seed";

fn main() {
	if !path::Path::new(GENESIS_RS_PATH).exists() {
		panic!(
			"File {} not found, make sure you're running this from the gen_gen directory",
			GENESIS_RS_PATH
		);
	}
	if !path::Path::new(PLUGIN_PATH).exists() {
		panic!(
			"File {} not found, make sure you're running this from the gen_gen directory",
			PLUGIN_PATH
		);
	}
	if !path::Path::new(WALLET_SEED_PATH).exists() {
		panic!(
			"File {} not found, make sure you're running this from the gen_gen directory",
			WALLET_SEED_PATH
		);
	}

	// get the latest bitcoin hash
	let h1 = get_bchain_head();
	let h2 = get_bcypher_head();
	let h3 = get_bchair_head();
	if h1 != h2 || h1 != h3 {
		panic!(
			"Bitcoin chain head is inconsistent, please retry ({}, {}, {}).",
			h1, h2, h3
		);
	}
	println!("Using bitcoin block hash {}", h1);

	// build the basic parts of the genesis block header
	let mut gen = core::genesis::genesis_main();

	// build the wallet seed and derive a coinbase from local wallet.seed
	let seed = wallet::WalletSeed::from_file(
		&wallet::WalletConfig::default(),
		&rpassword::prompt_password_stdout("Password: ").unwrap(),
	)
	.unwrap();
	let keychain: ExtKeychain = seed.derive_keychain().unwrap();
	let key_id = ExtKeychain::derive_key_id(2, 1, 0, 0, 0);
	let reward = core::libtx::reward::output(&keychain, &key_id, 0).unwrap();
	gen = gen.with_reward(reward.0, reward.1);

	{
		// setup a tmp chain to set block header roots
		core::global::set_mining_mode(core::global::ChainTypes::AutomatedTesting);
		let tmp_chain = setup_chain(".grin.tmp", core::pow::mine_genesis_block().unwrap());
		tmp_chain.set_txhashset_roots(&mut gen).unwrap();
	}

	// sets the timestamp and prev_root from the bitcoin block (needs to be
	// after set_txhashset roots to not get overwritten)
	gen.header.timestamp = Utc::now() + Duration::minutes(30);
	gen.header.prev_root = core::core::hash::Hash::from_hex(&h1).unwrap();

	// mine a Cuckaroo29 block
	core::global::set_mining_mode(core::global::ChainTypes::Mainnet);
	let plugin_lib = cuckoo::PluginLibrary::new(PLUGIN_PATH).unwrap();
	let mut params = plugin_lib.get_default_params();
	params.mutate_nonce = false;
	let solver_ctx = plugin_lib.create_solver_ctx(&mut params);

	let mut solver_sols = plugin::SolverSolutions::default();
	let mut solver_stats = plugin::SolverStats::default();
	let mut nonce = 0;
	while solver_sols.num_sols == 0 {
		solver_sols = plugin::SolverSolutions::default();
		gen.header.pow.nonce = nonce;
		let _ = plugin_lib.run_solver(
			solver_ctx,
			gen.header.pre_pow(),
			nonce,
			1,
			&mut solver_sols,
			&mut solver_stats,
		);
		if solver_stats.has_errored {
			println!(
				"Plugin {} has errored, device: {}. Reason: {}",
				solver_stats.get_plugin_name(),
				solver_stats.get_device_name(),
				solver_stats.get_error_reason(),
			);
			return;
		}

		nonce += 1;
	}

	// Set the PoW solution and make sure the block is mostly valid
	gen.header.pow.proof.nonces = solver_sols.sols[0].to_u64s();
	assert!(gen.header.pow.is_secondary(), "Not a secondary header");
	println!("Built genesis:\n{:?}", gen);
	core::pow::verify_size(&gen.header).unwrap();
	gen.validate(
		&BlindingFactor::zero(),
		Arc::new(util::RwLock::new(LruVerifierCache::new())),
	)
	.unwrap();

	println!("\nFinal genesis cyclehash: {}", gen.hash().to_hex());
	let gen_bin = core::ser::ser_vec(&gen).unwrap();
	println!("Final genesis full hash: {}\n", gen_bin.hash().to_hex());

	update_genesis_rs(&gen);
	println!("genesis.rs has been updated, check it and run mainnet_genesis_hash test");
	println!("also check bitcoin block {} hasn't been orphaned.", h1);
	println!("All done!");
}

fn update_genesis_rs(gen: &core::core::Block) {
	// set the replacement patterns
	let mut replacements = vec![];
	replacements.push((
		"timestamp".to_string(),
		format!(
			"Utc.ymd({}, {}, {}).and_hms({}, {}, {})",
			gen.header.timestamp.date().year(),
			gen.header.timestamp.date().month(),
			gen.header.timestamp.date().day(),
			gen.header.timestamp.time().hour(),
			gen.header.timestamp.time().minute(),
			gen.header.timestamp.time().second(),
		),
	));
	replacements.push((
		"prev_root".to_string(),
		format!(
			"Hash::from_hex(\"{}\").unwrap()",
			gen.header.prev_root.to_hex()
		),
	));
	replacements.push((
		"output_root".to_string(),
		format!(
			"Hash::from_hex(\"{}\").unwrap()",
			gen.header.output_root.to_hex()
		),
	));
	replacements.push((
		"range_proof_root".to_string(),
		format!(
			"Hash::from_hex(\"{}\").unwrap()",
			gen.header.range_proof_root.to_hex()
		),
	));
	replacements.push((
		"kernel_root".to_string(),
		format!(
			"Hash::from_hex(\"{}\").unwrap()",
			gen.header.kernel_root.to_hex()
		),
	));
	replacements.push((
		"total_kernel_offset".to_string(),
		format!(
			"BlindingFactor::from_hex(\"{}\").unwrap()",
			gen.header.total_kernel_offset.to_hex()
		),
	));
	replacements.push(("nonce".to_string(), format!("{}", gen.header.pow.nonce)));
	replacements.push((
		"nonces".to_string(),
		format!("vec!{:?}", gen.header.pow.proof.nonces),
	));
	replacements.push((
		"excess".to_string(),
		format!(
			"Commitment::from_vec(util::from_hex({:x?}.to_string()).unwrap())",
			util::to_hex(gen.kernels()[0].excess.0.to_vec())
		),
	));
	replacements.push((
		"excess_sig".to_string(),
		format!(
			"Signature::from_raw_data(&{:?}).unwrap()",
			gen.kernels()[0].excess_sig.to_raw_data().to_vec(),
		),
	));
	replacements.push((
		"commit".to_string(),
		format!(
			"Commitment::from_vec(util::from_hex({:x?}.to_string()).unwrap())",
			util::to_hex(gen.outputs()[0].commitment().0.to_vec())
		),
	));
	replacements.push((
		"proof".to_string(),
		format!("{:?}", gen.outputs()[0].proof.bytes().to_vec()),
	));

	// check each possible replacement in the file, remove the replacement from
	// the list when found to avoid double replacements
	let mut replaced = String::new();
	{
		let genesis_rs = fs::File::open(GENESIS_RS_PATH).unwrap();
		let reader = io::BufReader::new(&genesis_rs);
		for rline in reader.lines() {
			let line = rline.unwrap();
			let mut has_replaced = false;
			if line.contains("REPLACE") {
				for (pos, replacement) in replacements.iter().enumerate() {
					if line.contains(&replacement.0) {
						replaced.push_str(&format!("{}: {},\n", replacement.0, replacement.1));
						replacements.remove(pos);
						has_replaced = true;
						break;
					}
				}
			}
			if !has_replaced {
				replaced.push_str(&format!("{}\n", line));
			}
		}
	}
	let mut genesis_rs = fs::File::create(GENESIS_RS_PATH).unwrap();
	genesis_rs.write_all(replaced.as_bytes()).unwrap();
}

fn setup_chain(dir_name: &str, genesis: core::core::Block) -> chain::Chain {
	util::init_test_logger();
	let _ = fs::remove_dir_all(dir_name);
	let verifier_cache = Arc::new(util::RwLock::new(
		core::core::verifier_cache::LruVerifierCache::new(),
	));
	let db_env = Arc::new(store::new_env(dir_name.to_string()));
	chain::Chain::init(
		dir_name.to_string(),
		db_env,
		Arc::new(chain::types::NoopAdapter {}),
		genesis,
		core::pow::verify_size,
		verifier_cache,
		false,
		Arc::new(util::Mutex::new(util::StopState::new())),
	)
	.unwrap()
}

fn get_bchain_head() -> String {
	get_json(BCHAIN_INFO_URL)["hash"]
		.as_str()
		.unwrap()
		.to_string()
}

fn get_bcypher_head() -> String {
	get_json(BCYPHER_URL)["hash"].as_str().unwrap().to_string()
}

fn get_bchair_head() -> String {
	get_json(BCHAIR_URL)["data"][0]["hash"]
		.as_str()
		.unwrap()
		.to_string()
}

fn get_json(url: &str) -> serde_json::Value {
	let mut body = Vec::new();
	let mut easy = curl::easy::Easy::new();
	easy.url(url).unwrap();
	{
		let mut transfer = easy.transfer();
		transfer
			.write_function(|data| {
				body.extend_from_slice(data);
				Ok(data.len())
			})
			.unwrap();
		transfer.perform().unwrap();
	}
	serde_json::from_slice(&body).unwrap()
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![allow(unreachable_code)]
#![allow(unused_parens)]

#![recursion_limit = "256"]

use std::cell::Cell;
use std::mem::swap;

// Just a grab bag of stuff that you wouldn't want to actually write.

fn strange() -> bool { let _x: bool = return true; }

fn funny() {
    fn f(_x: ()) { }
    f(return);
}

fn what() {
    fn the(x: &Cell<bool>) {
        return while !x.get() { x.set(true); };
    }
    let i = &Cell::new(false);
    let dont = {||the(i)};
    dont();
    assert!((i.get()));
}

fn zombiejesus() {
    loop {
        while (return) {
            if (return) {
                match (return) {
                    1 => {
                        if (return) {
                            return
                        } else {
                            return
                        }
                    }
                    _ => { return }
                };
            } else if (return) {
                return;
            }
        }
        if (return) { break; }
    }
}

fn notsure() {
    let mut _x: isize;
    let mut _y = (_x = 0) == (_x = 0);
    let mut _z = (_x = 0) < (_x = 0);
    let _a = (_x += 0) == (_x = 0);
    let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z);
}

fn canttouchthis() -> usize {
    fn p() -> bool { true }
    let _a = (assert!((true)) == (assert!(p())));
    let _c = (assert!((p())) == ());
    let _b: bool = (println!("{}", 0) == (return 0));
}

fn angrydome() {
    loop { if break { } }
    let mut i = 0;
    loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => panic!("wat") } }
      break; }
}

fn evil_lincoln() { let _evil = println!("lincoln"); }

fn dots() {
    assert_eq!(String::from(".................................................."),
               format!("{:?}", .. .. .. .. .. .. .. .. .. .. .. .. ..
                               .. .. .. .. .. .. .. .. .. .. .. ..));
}

fn u8(u8: u8) {
    if u8 != 0u8 {
        assert_eq!(8u8, {
            macro_rules! u8 {
                (u8) => {
                    mod u8 {
                        pub fn u8<'u8: 'u8 + 'u8>(u8: &'u8 u8) -> &'u8 u8 {
                            "u8";
                            u8
                        }
                    }
                };
            }

            u8!(u8);
            let &u8: &u8 = u8::u8(&8u8);
            ::u8(0u8);
            u8
        });
    }
}

fn fishy() {
    assert_eq!(String::from("><>"),
               String::<>::from::<>("><>").chars::<>().rev::<>().collect::<String>());
}

fn union() {
    union union<'union> { union: &'union union<'union>, }
}

fn special_characters() {
    let val = !((|(..):(_,_),__@_|__)((&*"\\",'🤔')/**/,{})=={&[..=..][..];})//
    ;
    assert!(!val);
}

fn punch_card() -> impl std::fmt::Debug {
    ..=..=.. ..    .. .. .. ..    .. .. .. ..    .. ..=.. ..
    ..=.. ..=..    .. .. .. ..    .. .. .. ..    ..=..=..=..
    ..=.. ..=..    ..=.. ..=..    .. ..=..=..    .. ..=.. ..
    ..=..=.. ..    ..=.. ..=..    ..=.. .. ..    .. ..=.. ..
    ..=.. ..=..    ..=.. ..=..    .. ..=.. ..    .. ..=.. ..
    ..=.. ..=..    ..=.. ..=..    .. .. ..=..    .. ..=.. ..
    ..=.. ..=..    .. ..=..=..    ..=..=.. ..    .. ..=.. ..
}

fn r#match() {
    let val = match match match match match () {
        () => ()
    } {
        () => ()
    } {
        () => ()
    } {
        () => ()
    } {
        () => ()
    };
    assert_eq!(val, ());
}

pub fn main() {
    strange();
    funny();
    what();
    zombiejesus();
    notsure();
    canttouchthis();
    angrydome();
    evil_lincoln();
    dots();
    u8(8u8);
    fishy();
    union();
    special_characters();
    punch_card();
    r#match();
}
<commit_msg>Add nested 'yield' expression to weird expressions test<commit_after>#![feature(generators)]

#![allow(non_camel_case_types)]
#![allow(dead_code)]
#![allow(unreachable_code)]
#![allow(unused_parens)]

#![recursion_limit = "256"]

use std::cell::Cell;
use std::mem::swap;

// Just a grab bag of stuff that you wouldn't want to actually write.

fn strange() -> bool { let _x: bool = return true; }

fn funny() {
    fn f(_x: ()) { }
    f(return);
}

fn what() {
    fn the(x: &Cell<bool>) {
        return while !x.get() { x.set(true); };
    }
    let i = &Cell::new(false);
    let dont = {||the(i)};
    dont();
    assert!((i.get()));
}

fn zombiejesus() {
    loop {
        while (return) {
            if (return) {
                match (return) {
                    1 => {
                        if (return) {
                            return
                        } else {
                            return
                        }
                    }
                    _ => { return }
                };
            } else if (return) {
                return;
            }
        }
        if (return) { break; }
    }
}

fn notsure() {
    let mut _x: isize;
    let mut _y = (_x = 0) == (_x = 0);
    let mut _z = (_x = 0) < (_x = 0);
    let _a = (_x += 0) == (_x = 0);
    let _b = swap(&mut _y, &mut _z) == swap(&mut _y, &mut _z);
}

fn canttouchthis() -> usize {
    fn p() -> bool { true }
    let _a = (assert!((true)) == (assert!(p())));
    let _c = (assert!((p())) == ());
    let _b: bool = (println!("{}", 0) == (return 0));
}

fn angrydome() {
    loop { if break { } }
    let mut i = 0;
    loop { i += 1; if i == 1 { match (continue) { 1 => { }, _ => panic!("wat") } }
      break; }
}

fn evil_lincoln() { let _evil = println!("lincoln"); }

fn dots() {
    assert_eq!(String::from(".................................................."),
               format!("{:?}", .. .. .. .. .. .. .. .. .. .. .. .. ..
                               .. .. .. .. .. .. .. .. .. .. .. ..));
}

fn u8(u8: u8) {
    if u8 != 0u8 {
        assert_eq!(8u8, {
            macro_rules! u8 {
                (u8) => {
                    mod u8 {
                        pub fn u8<'u8: 'u8 + 'u8>(u8: &'u8 u8) -> &'u8 u8 {
                            "u8";
                            u8
                        }
                    }
                };
            }

            u8!(u8);
            let &u8: &u8 = u8::u8(&8u8);
            ::u8(0u8);
            u8
        });
    }
}

fn fishy() {
    assert_eq!(String::from("><>"),
               String::<>::from::<>("><>").chars::<>().rev::<>().collect::<String>());
}

fn union() {
    union union<'union> { union: &'union union<'union>, }
}

fn special_characters() {
    let val = !((|(..):(_,_),__@_|__)((&*"\\",'🤔')/**/,{})=={&[..=..][..];})//
    ;
    assert!(!val);
}

fn punch_card() -> impl std::fmt::Debug {
    ..=..=.. ..    .. .. .. ..    .. .. .. ..    .. ..=.. ..
    ..=.. ..=..    .. .. .. ..    .. .. .. ..    ..=..=..=..
    ..=.. ..=..    ..=.. ..=..    .. ..=..=..    .. ..=.. ..
    ..=..=.. ..    ..=.. ..=..    ..=.. .. ..    .. ..=.. ..
    ..=.. ..=..    ..=.. ..=..    .. ..=.. ..    .. ..=.. ..
    ..=.. ..=..    ..=.. ..=..    .. .. ..=..    .. ..=.. ..
    ..=.. ..=..    .. ..=..=..    ..=..=.. ..    .. ..=.. ..
}

fn r#match() {
    let val = match match match match match () {
        () => ()
    } {
        () => ()
    } {
        () => ()
    } {
        () => ()
    } {
        () => ()
    };
    assert_eq!(val, ());
}

fn i_yield() {
    static || {
        yield yield yield yield yield yield yield yield yield;
    };
}

pub fn main() {
    strange();
    funny();
    what();
    zombiejesus();
    notsure();
    canttouchthis();
    angrydome();
    evil_lincoln();
    dots();
    u8(8u8);
    fishy();
    union();
    special_characters();
    punch_card();
    r#match();
    i_yield();
}
<|endoftext|>


<commit_before>extern crate milagro_crypto;
extern crate serde;

use self::milagro_crypto::big::wrappers::{
    CURVE_Gx,
    CURVE_Gy,
    CURVE_Order,
    CURVE_Pxa,
    CURVE_Pya,
    CURVE_Pxb,
    CURVE_Pyb,
    BIG
};
use self::milagro_crypto::ecp::wrappers::ECP;
use self::milagro_crypto::ecp2::wrappers::ECP2;
use self::milagro_crypto::fp12::wrappers::FP12;

use errors::crypto::CryptoError;
use services::anoncreds::helpers::BytesView;

use self::milagro_crypto::randapi::Random;

extern crate rand;

use self::rand::os::{OsRng};
use self::rand::Rng;
use self::serde::ser::{Serialize, Serializer};
use self::serde::de::{Deserialize, Deserializer};

fn random_mod_order() -> Result<BIG, CryptoError> {
    let mut seed = vec![0; 32];
    let mut os_rng = OsRng::new().unwrap();
    os_rng.fill_bytes(&mut seed.as_mut_slice());
    let mut rng = Random::new(&seed);
    Ok(BIG::randomnum(&unsafe { CURVE_Order }.clone(), &mut rng))
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct PointG1 {
    point: ECP
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct PointG2 {
    point: ECP2
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct GroupOrderElement {
    bn: BIG
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Pair {
    pair: FP12
}

impl PointG1 {
    pub fn new() -> Result<PointG1, CryptoError> {
        // generate random point from the group G1
        let gen_g1: ECP = ECP::new_bigs(&unsafe { CURVE_Gx }.clone(), &unsafe { CURVE_Gy }.clone());
        let mut point = gen_g1;
        ECP::mul(&mut point, &random_mod_order()?);
        Ok(PointG1 {
            point: point
        })
    }

    pub fn new_inf() -> Result<PointG1, CryptoError> {
        let mut r = ECP::default();
        ECP::inf(&mut r);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn mul(&self, e: &GroupOrderElement) -> Result<PointG1, CryptoError> {
        let mut r = self.point;
        ECP::mul(&mut r, &e.bn);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn add(&self, q: &PointG1) -> Result<PointG1, CryptoError> {
        let mut r = self.point;
        ECP::add(&mut r, &q.point);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn sub(&self, q: &PointG1) -> Result<PointG1, CryptoError> {
        let mut r = self.point;
        ECP::sub(&mut r, &q.point);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn neg(&self) -> Result<PointG1, CryptoError> {
        let mut r = self.point;
        ECP::neg(&mut r);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn to_string(&self) -> Result<String, CryptoError> {
        unimplemented!();
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        unimplemented!();
    }

    pub fn from_bytes(b: &[u8]) -> Result<PointG1, CryptoError> {
        unimplemented!();
    }
}

impl PointG2 {
    pub fn new() -> Result<PointG2, CryptoError> {
        unimplemented!();
    }

    pub fn new_inf() -> Result<PointG2, CryptoError> {
        unimplemented!();
    }

    pub fn add(&self, q: &PointG2) -> Result<PointG2, CryptoError> {
        unimplemented!();
    }

    pub fn sub(&self, q: &PointG2) -> Result<PointG2, CryptoError> {
        unimplemented!();
    }

    pub fn mul(&self, e: &GroupOrderElement) -> Result<PointG2, CryptoError> {
        unimplemented!();
    }

    pub fn to_string(&self) -> Result<String, CryptoError> {
        unimplemented!();
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        unimplemented!();
    }

    pub fn from_bytes(b: &[u8]) -> Result<PointG1, CryptoError> {
        unimplemented!();
    }
}

impl GroupOrderElement {
    pub fn new() -> Result<GroupOrderElement, CryptoError> {
        // returns random element in 0, ..., GroupOrder-1
        Ok(GroupOrderElement {
            bn: random_mod_order()?
        })
    }

    pub fn pow_mod(&self, e: &GroupOrderElement) -> Result<GroupOrderElement, CryptoError> {
        let mut base = self.bn;
        let mut pow = e.bn;
        Ok(GroupOrderElement {
            bn: BIG::powmod(&mut base, &mut pow, &unsafe { CURVE_Order }.clone())
        })
    }

    pub fn add_mod(&self, r: &GroupOrderElement) -> Result<GroupOrderElement, CryptoError> {
        let mut sum = BIG::add(&self.bn, &r.bn);
        BIG::rmod(&mut sum, &unsafe { CURVE_Order }.clone());
        Ok(GroupOrderElement {
            bn: sum
        })
    }

    pub fn sub_mod(&self, r: &GroupOrderElement) -> Result<GroupOrderElement, CryptoError> {
        //need to use modneg if sub is negative
        let mut sub = BIG::sub(&self.bn, &r.bn);
        if sub < BIG::default() {
            let mut r: BIG = BIG::default();
            BIG::modneg(&mut r, &mut sub, &unsafe { CURVE_Order }.clone());
            Ok(GroupOrderElement {
                bn: r
            })
        } else {
            Ok(GroupOrderElement {
                bn: sub
            })
        }
    }

    pub fn mul_mod(&self, r: &GroupOrderElement) -> Result<GroupOrderElement, CryptoError> {
        Ok(GroupOrderElement {
            bn: BIG::modmul(&self.bn, &r.bn, &unsafe { CURVE_Order }.clone())
        })
    }

    pub fn inverse(&self) -> Result<GroupOrderElement, CryptoError> {
        Ok(GroupOrderElement {
            bn: BIG::invmodp(&self.bn, &unsafe { CURVE_Order }.clone())
        })
    }

    pub fn mod_neg(&self) -> Result<GroupOrderElement, CryptoError> {
        let mut r: BIG = BIG::default();
        let mut bn = self.bn;
        BIG::modneg(&mut r, &mut bn, &unsafe { CURVE_Order }.clone());
        Ok(GroupOrderElement {
            bn: r
        })
    }

    pub fn to_string(&self) -> Result<String, CryptoError> {
        unimplemented!();
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        let mut vec: [u8; 32] = [0; 32];
        BIG::toBytes(&mut vec, &self.bn);
        Ok(vec.to_vec())
    }

    pub fn from_bytes(b: &[u8]) -> Result<GroupOrderElement, CryptoError> {
        Ok(
            GroupOrderElement {
                bn: BIG::fromBytes(b)
            }
        )
    }
}

impl Pair {
    pub fn pair(p: &PointG1, q: &PointG2) -> Result<Pair, CryptoError> {
        unimplemented!();
    }

    pub fn mul(&self, b: &Pair) -> Result<Pair, CryptoError> {
        let mut pair = self.pair;
        FP12::mul(&mut pair, &b.pair);
        Ok(Pair {
            pair: pair
        })
    }

    pub fn pow(&self, b: &GroupOrderElement) -> Result<Pair, CryptoError> {
        let mut r = FP12::default();
        FP12::pow(&mut r, &self.pair, &b.bn);
        Ok(Pair {
            pair: r
        })
    }

    pub fn inverse(&self) -> Result<Pair, CryptoError> {
        let mut r = FP12::default();
        FP12::inv(&mut r, &self.pair);
        Ok(Pair {
            pair: r
        })
    }

    pub fn to_string(&self) -> Result<String, CryptoError> {
        unimplemented!();
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        unimplemented!();
    }

    pub fn from_bytes(b: &[u8]) -> Result<Pair, CryptoError> {
        unimplemented!();
    }
}

impl BytesView for Pair {
    fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        Ok(self.to_bytes()?)
    }
}

impl BytesView for PointG1 {
    fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        Ok(self.to_bytes()?)
    }
}

impl BytesView for GroupOrderElement {
    fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        Ok(self.to_bytes()?)
    }
}

impl Serialize for GroupOrderElement {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        unimplemented!();
    }
}

impl<'a> Deserialize<'a> for GroupOrderElement {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
        unimplemented!();
    }
}

impl Serialize for Pair {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        unimplemented!();
    }
}

impl<'a> Deserialize<'a> for Pair {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
        unimplemented!();
    }
}

impl Serialize for PointG1 {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        unimplemented!();
    }
}

impl<'a> Deserialize<'a> for PointG1 {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
        unimplemented!();
    }
}

impl Serialize for PointG2 {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        unimplemented!();
    }
}

impl<'a> Deserialize<'a> for PointG2 {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
        unimplemented!();
    }
}<commit_msg>added serializer, deserializer and tests<commit_after>extern crate milagro_crypto;
extern crate serde;

use self::milagro_crypto::big::wrappers::{
    CURVE_Gx,
    CURVE_Gy,
    CURVE_Order,
    CURVE_Pxa,
    CURVE_Pya,
    CURVE_Pxb,
    CURVE_Pyb,
    BIG
};
use self::milagro_crypto::ecp::wrappers::ECP;
use self::milagro_crypto::ecp2::wrappers::ECP2;
use self::milagro_crypto::fp12::wrappers::FP12;

use errors::crypto::CryptoError;
use services::anoncreds::helpers::BytesView;

use self::milagro_crypto::randapi::Random;

extern crate rand;

use self::rand::os::{OsRng};
use self::rand::Rng;
use self::serde::ser::{Serialize, Serializer, Error as SError};
use self::serde::de::{Deserialize, Deserializer, Visitor, Error as DError};
use std::fmt;

fn random_mod_order() -> Result<BIG, CryptoError> {
    let mut seed = vec![0; 32];
    let mut os_rng = OsRng::new().unwrap();
    os_rng.fill_bytes(&mut seed.as_mut_slice());
    let mut rng = Random::new(&seed);
    Ok(BIG::randomnum(&unsafe { CURVE_Order }.clone(), &mut rng))
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct PointG1 {
    point: ECP
}

impl PointG1 {
    pub fn new() -> Result<PointG1, CryptoError> {
        // generate random point from the group G1
        let gen_g1: ECP = ECP::new_bigs(&unsafe { CURVE_Gx }.clone(), &unsafe { CURVE_Gy }.clone());
        let mut point = gen_g1;
        ECP::mul(&mut point, &random_mod_order()?);
        Ok(PointG1 {
            point: point
        })
    }

    pub fn new_inf() -> Result<PointG1, CryptoError> {
        let mut r = ECP::default();
        ECP::inf(&mut r);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn mul(&self, e: &GroupOrderElement) -> Result<PointG1, CryptoError> {
        let mut r = self.point;
        ECP::mul(&mut r, &e.bn);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn add(&self, q: &PointG1) -> Result<PointG1, CryptoError> {
        let mut r = self.point;
        ECP::add(&mut r, &q.point);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn sub(&self, q: &PointG1) -> Result<PointG1, CryptoError> {
        let mut r = self.point;
        ECP::sub(&mut r, &q.point);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn neg(&self) -> Result<PointG1, CryptoError> {
        let mut r = self.point;
        ECP::neg(&mut r);
        Ok(PointG1 {
            point: r
        })
    }

    pub fn to_string(&self) -> Result<String, CryptoError> {
        unimplemented!();
    }

    pub fn from_string(str: &str) -> Result<PointG1, CryptoError> {
        unimplemented!();
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        unimplemented!();
    }

    pub fn from_bytes(b: &[u8]) -> Result<PointG1, CryptoError> {
        unimplemented!();
    }
}

impl BytesView for PointG1 {
    fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        Ok(self.to_bytes()?)
    }
}

impl Serialize for PointG1 {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_newtype_struct("PointG1", &self.to_string().map_err(SError::custom)?)
    }
}

impl<'a> Deserialize<'a> for PointG1 {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
        struct PointG1Visitor;

        impl<'a> Visitor<'a> for PointG1Visitor {
            type Value = PointG1;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("expected PointG1")
            }

            fn visit_str<E>(self, value: &str) -> Result<PointG1, E>
                where E: DError
            {
                Ok(PointG1::from_string(value).map_err(DError::custom)?)
            }
        }

        deserializer.deserialize_str(PointG1Visitor)
    }
}

#[derive(Copy, Clone, PartialEq, Debug)]
pub struct PointG2 {
    point: ECP2
}

impl PointG2 {
    pub fn new() -> Result<PointG2, CryptoError> {
        unimplemented!();
    }

    pub fn new_inf() -> Result<PointG2, CryptoError> {
        unimplemented!();
    }

    pub fn add(&self, q: &PointG2) -> Result<PointG2, CryptoError> {
        let mut r = self.point;
        ECP2::add(&mut r, &q.point);
        Ok(PointG2 {
            point: r
        })
    }

    pub fn sub(&self, q: &PointG2) -> Result<PointG2, CryptoError> {
        let mut r = self.point;
        ECP2::sub(&mut r, &q.point);
        Ok(PointG2 {
            point: r
        })
    }

    pub fn mul(&self, e: &GroupOrderElement) -> Result<PointG2, CryptoError> {
        let mut r = self.point;
        ECP2::mul(&mut r, &e.bn);
        Ok(PointG2 {
            point: r
        })
    }

    pub fn to_string(&self) -> Result<String, CryptoError> {
        unimplemented!();
    }

    pub fn from_string(str: &str) -> Result<PointG2, CryptoError> {
        unimplemented!();
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        unimplemented!();
    }

    pub fn from_bytes(b: &[u8]) -> Result<PointG1, CryptoError> {
        unimplemented!();
    }
}

impl Serialize for PointG2 {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_newtype_struct("PointG2", &self.to_string().map_err(SError::custom)?)
    }
}

impl<'a> Deserialize<'a> for PointG2 {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
        struct PointG2Visitor;

        impl<'a> Visitor<'a> for PointG2Visitor {
            type Value = PointG2;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("expected PointG2")
            }

            fn visit_str<E>(self, value: &str) -> Result<PointG2, E>
                where E: DError
            {
                Ok(PointG2::from_string(value).map_err(DError::custom)?)
            }
        }

        deserializer.deserialize_str(PointG2Visitor)
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct GroupOrderElement {
    bn: BIG
}

impl GroupOrderElement {
    pub fn new() -> Result<GroupOrderElement, CryptoError> {
        // returns random element in 0, ..., GroupOrder-1
        Ok(GroupOrderElement {
            bn: random_mod_order()?
        })
    }

    pub fn pow_mod(&self, e: &GroupOrderElement) -> Result<GroupOrderElement, CryptoError> {
        let mut base = self.bn;
        let mut pow = e.bn;
        Ok(GroupOrderElement {
            bn: BIG::powmod(&mut base, &mut pow, &unsafe { CURVE_Order }.clone())
        })
    }

    pub fn add_mod(&self, r: &GroupOrderElement) -> Result<GroupOrderElement, CryptoError> {
        let mut sum = BIG::add(&self.bn, &r.bn);
        BIG::rmod(&mut sum, &unsafe { CURVE_Order }.clone());
        Ok(GroupOrderElement {
            bn: sum
        })
    }

    pub fn sub_mod(&self, r: &GroupOrderElement) -> Result<GroupOrderElement, CryptoError> {
        //need to use modneg if sub is negative
        let mut sub = BIG::sub(&self.bn, &r.bn);
        if sub < BIG::default() {
            let mut r: BIG = BIG::default();
            BIG::modneg(&mut r, &mut sub, &unsafe { CURVE_Order }.clone());
            Ok(GroupOrderElement {
                bn: r
            })
        } else {
            Ok(GroupOrderElement {
                bn: sub
            })
        }
    }

    pub fn mul_mod(&self, r: &GroupOrderElement) -> Result<GroupOrderElement, CryptoError> {
        Ok(GroupOrderElement {
            bn: BIG::modmul(&self.bn, &r.bn, &unsafe { CURVE_Order }.clone())
        })
    }

    pub fn inverse(&self) -> Result<GroupOrderElement, CryptoError> {
        Ok(GroupOrderElement {
            bn: BIG::invmodp(&self.bn, &unsafe { CURVE_Order }.clone())
        })
    }

    pub fn mod_neg(&self) -> Result<GroupOrderElement, CryptoError> {
        let mut r: BIG = BIG::default();
        let mut bn = self.bn;
        BIG::modneg(&mut r, &mut bn, &unsafe { CURVE_Order }.clone());
        Ok(GroupOrderElement {
            bn: r
        })
    }

    pub fn to_string(&self) -> Result<String, CryptoError> {
        unimplemented!();
    }

    pub fn from_string(str: &str) -> Result<GroupOrderElement, CryptoError> {
        unimplemented!();
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        let mut vec: [u8; 32] = [0; 32];
        BIG::toBytes(&mut vec, &self.bn);
        Ok(vec.to_vec())
    }

    pub fn from_bytes(b: &[u8]) -> Result<GroupOrderElement, CryptoError> {
        Ok(
            GroupOrderElement {
                bn: BIG::fromBytes(b)
            }
        )
    }
}

impl BytesView for GroupOrderElement {
    fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        Ok(self.to_bytes()?)
    }
}

impl Serialize for GroupOrderElement {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_newtype_struct("GroupOrderElement", &self.to_string().map_err(SError::custom)?)
    }
}

impl<'a> Deserialize<'a> for GroupOrderElement {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
        struct GroupOrderElementVisitor;

        impl<'a> Visitor<'a> for GroupOrderElementVisitor {
            type Value = GroupOrderElement;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("expected GroupOrderElement")
            }

            fn visit_str<E>(self, value: &str) -> Result<GroupOrderElement, E>
                where E: DError
            {
                Ok(GroupOrderElement::from_string(value).map_err(DError::custom)?)
            }
        }

        deserializer.deserialize_str(GroupOrderElementVisitor)
    }
}

#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Pair {
    pair: FP12
}

impl Pair {
    pub fn pair(p: &PointG1, q: &PointG2) -> Result<Pair, CryptoError> {
        unimplemented!();
    }

    pub fn mul(&self, b: &Pair) -> Result<Pair, CryptoError> {
        let mut pair = self.pair;
        FP12::mul(&mut pair, &b.pair);
        Ok(Pair {
            pair: pair
        })
    }

    pub fn pow(&self, b: &GroupOrderElement) -> Result<Pair, CryptoError> {
        let mut r = FP12::default();
        FP12::pow(&mut r, &self.pair, &b.bn);
        Ok(Pair {
            pair: r
        })
    }

    pub fn inverse(&self) -> Result<Pair, CryptoError> {
        let mut r = FP12::default();
        FP12::inv(&mut r, &self.pair);
        Ok(Pair {
            pair: r
        })
    }

    pub fn to_string(&self) -> Result<String, CryptoError> {
        unimplemented!();
    }

    pub fn from_string(str: &str) -> Result<Pair, CryptoError> {
        unimplemented!();
    }

    pub fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        unimplemented!();
    }

    pub fn from_bytes(b: &[u8]) -> Result<Pair, CryptoError> {
        unimplemented!();
    }
}

impl BytesView for Pair {
    fn to_bytes(&self) -> Result<Vec<u8>, CryptoError> {
        Ok(self.to_bytes()?)
    }
}

impl Serialize for Pair {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_newtype_struct("Pair", &self.to_string().map_err(SError::custom)?)
    }
}

impl<'a> Deserialize<'a> for Pair {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> where D: Deserializer<'a> {
        struct PairVisitor;

        impl<'a> Visitor<'a> for PairVisitor {
            type Value = Pair;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("expected Pair")
            }

            fn visit_str<E>(self, value: &str) -> Result<Pair, E>
                where E: DError
            {
                Ok(Pair::from_string(value).map_err(DError::custom)?)
            }
        }

        deserializer.deserialize_str(PairVisitor)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use utils::logger::LoggerUtils;

    extern crate serde_json;

    #[derive(Serialize, Deserialize)]
    struct TestGroupOrderElementStructure {
        field: GroupOrderElement
    }

    #[derive(Serialize, Deserialize)]
    struct TestPointG1Structure {
        field: PointG1
    }

    #[derive(Serialize, Deserialize)]
    struct TestPointG2Structure {
        field: PointG2
    }

    #[derive(Serialize, Deserialize)]
    struct TestPairStructure {
        field: Pair
    }

    #[test]
    fn serialize_works_for_group_order_element() {

    }

    #[test]
    fn deserialize_works_for_group_order_element() {

    }

    #[test]
    fn serialize_works_for_point_g1() {

    }

    #[test]
    fn deserialize_works_for_point_g1() {

    }

    #[test]
    fn serialize_works_for_point_g2() {

    }

    #[test]
    fn deserialize_works_for_point_g2() {

    }
    #[test]
    fn serialize_works_for_pair() {

    }

    #[test]
    fn deserialize_works_for_pair() {

    }
}<|endoftext|>


<commit_before>use std::env;
use std::path::PathBuf;
use std::fs;
use std::path::Path;
use std::collections::BTreeMap;
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use std::fmt::Write as fmt_Write;

extern crate tempdir;
extern crate regex;

extern crate toml;

extern crate serde;
#[macro_use]
extern crate serde_derive;

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
struct TomlWorkspace {
    members: Vec<String>,
}

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
struct TomlPackage {
    name: String,
    version: String,
    publish: Option<bool>,
}

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
#[serde(rename_all = "kebab-case")]
pub struct DetailedTomlDependency {
    version: Option<String>,
    path: Option<String>
}

#[derive(Deserialize, Serialize, Clone, Debug)]
#[serde(untagged)]
pub enum TomlDependency {
    Simple(String),
    Detailed(DetailedTomlDependency),
}

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
struct TomlManifest {
    package: Option<TomlPackage>,
    workspace: Option<TomlWorkspace>,
    dependencies: Option<BTreeMap<String, TomlDependency>>,
}

fn find_repo_root() -> PathBuf {
    let candidates = &[".", ".."];
    for dir in candidates {
        let dir = Path::new(dir).to_owned();
        let mut file = dir.clone();
        file.push("CHANGELOG.md");
        if file.exists() {
            return dir;
        }
    }
    panic!("cannot find repository root");
}

/// Read `Cargo.toml` from specified directory.
fn read_crate_manifest(crate_path: &Path) -> TomlManifest {
    assert!(crate_path.is_dir());

    let mut cargo_toml = crate_path.to_owned();
    cargo_toml.push("Cargo.toml");

    let content = fs::read_to_string(&cargo_toml).expect(&format!("read {:?}", cargo_toml));

    toml::from_str(&content)
        .expect(&format!("parse toml {:?}", cargo_toml))
}

fn find_workspace_members(repo_root: &Path) -> Vec<String> {
    read_crate_manifest(repo_root).workspace.expect("workspace").members
}

#[derive(Debug)]
struct ParsedDependency {
    name: String,
    path: String,
}

#[derive(Debug)]
struct ParsedMember {
    /// Package name
    name: String,
    /// Path in the workspace
    member: String,
    /// Internal dep package names
    internal_deps: Vec<ParsedDependency>,
}

fn topo_sort(members: &mut [ParsedMember]) {
    'again: loop {
        for i in 0..members.len() {
            for j in i..members.len() {
                if i == j {
                    continue;
                }

                if members[i].internal_deps.iter().any(|d| d.name == members[j].name) {
                    members.swap(i, j);
                    // Native algorithm
                    continue 'again;
                }
            }
        }
        break;
    }
}

fn patch_crate(repo_root: &Path, member: &ParsedMember, new_version: &str) {
    let mut manifest_path = repo_root.to_owned();
    manifest_path.push(&member.member);
    manifest_path.push("Cargo.toml");

    let read = File::open(&manifest_path).expect(&format!("open manifest {:?}", manifest_path));
    let read = BufReader::new(read);

    #[derive(Debug, Eq, PartialEq)]
    enum WhereWeAre {
        Init,
        Package,
        Dependencies,
        Other,
    }

    let mut where_we_are = WhereWeAre::Init;

    let mut output = String::new();

    for line in read.lines() {
        let line = line.expect("line");

        let mut line_written = false;

        if line == "[package]" {
            where_we_are = WhereWeAre::Package;
        } else if line == "[dependencies]" {
            where_we_are = WhereWeAre::Dependencies;
        } else if line.starts_with("[") {
            where_we_are = WhereWeAre::Other;
        } else {
            match where_we_are {
                WhereWeAre::Package => {
                    if line.starts_with("version =") {
                        writeln!(output, "version = \"{}\"", new_version).expect("write");
                        line_written = true;
                    }
                }
                WhereWeAre::Dependencies => {
                    for dep in &member.internal_deps {
                        if line.starts_with(&format!("{} ", dep.name)) {
                            writeln!(
                                output,
                                "{} = {{ path = \"{}\", version = \"={}\" }}",
                                dep.name, dep.path, new_version)
                                .expect("write");
                            line_written = true;
                            break;
                        }
                    }
                }
                _ => {}
            }
        }

        if !line_written {
            writeln!(output, "{}", line).expect("write");
        }
    }

    fs::write(&manifest_path, &output).expect("write patched manifest back");
}

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();
    assert_eq!(1, args.len());
    let new_version = &args[0];

    let repo_root = find_repo_root();

    let members = find_workspace_members(&repo_root);

    let mut publish_members = Vec::new();

    for member in members {
        let mut crate_path = repo_root.to_owned();
        crate_path.push(&member);
        let manifest = read_crate_manifest(&crate_path);
        let package = manifest.package
            .expect(&format!("package in {}", member));
        let dependencies = manifest.dependencies
            .expect(&format!("dependencies in {}", member));
        if package.publish == Some(false) {
            continue;
        }
        if package.version == "0.0.0" {
            panic!("version must be 0.0.0 is !publish for {}", member);
        }
        if package.version == "0.1.0" {
            panic!("default version 1.0.0 in {}", member);
        }

        let name = package.name;

        let mut internal_deps = Vec::new();

        for (name, dep) in dependencies {
            if let TomlDependency::Detailed(d) = dep {
                let path = match d.path {
                    Some(path) => path,
                    None => {
                        // Not internal dependency
                        continue
                    },
                };
                let version = d.version.expect(&format!("version in dep of {}", member));
                assert!(version.starts_with("="), "dep version must start with =: {}", member);
                internal_deps.push(ParsedDependency {
                    name,
                    path,
                });
            }
        }

        publish_members.push(ParsedMember {
            name,
            member,
            internal_deps,
        });
    }

    topo_sort(&mut publish_members);

    for member in &publish_members {
        patch_crate(&repo_root, member, new_version);
    }

    for member in &publish_members {
        println!("cargo publish --manifest-path={}/Cargo.toml", member.member);
    }
}
<commit_msg>Update version self check<commit_after>use std::env;
use std::path::PathBuf;
use std::fs;
use std::path::Path;
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::fs::File;
use std::io::BufReader;
use std::io::BufRead;
use std::fmt::Write as fmt_Write;

extern crate tempdir;
extern crate regex;

extern crate toml;

extern crate serde;
#[macro_use]
extern crate serde_derive;

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
struct TomlWorkspace {
    members: Vec<String>,
}

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
struct TomlPackage {
    name: String,
    version: String,
    publish: Option<bool>,
}

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
#[serde(rename_all = "kebab-case")]
pub struct DetailedTomlDependency {
    version: Option<String>,
    path: Option<String>
}

#[derive(Deserialize, Serialize, Clone, Debug)]
#[serde(untagged)]
pub enum TomlDependency {
    Simple(String),
    Detailed(DetailedTomlDependency),
}

#[derive(Deserialize, Serialize, Clone, Debug, Default)]
struct TomlManifest {
    package: Option<TomlPackage>,
    workspace: Option<TomlWorkspace>,
    dependencies: Option<BTreeMap<String, TomlDependency>>,
}

fn find_repo_root() -> PathBuf {
    let candidates = &[".", ".."];
    for dir in candidates {
        let dir = Path::new(dir).to_owned();
        let mut file = dir.clone();
        file.push("CHANGELOG.md");
        if file.exists() {
            return dir;
        }
    }
    panic!("cannot find repository root");
}

/// Read `Cargo.toml` from specified directory.
fn read_crate_manifest(crate_path: &Path) -> TomlManifest {
    assert!(crate_path.is_dir());

    let mut cargo_toml = crate_path.to_owned();
    cargo_toml.push("Cargo.toml");

    let content = fs::read_to_string(&cargo_toml).expect(&format!("read {:?}", cargo_toml));

    toml::from_str(&content)
        .expect(&format!("parse toml {:?}", cargo_toml))
}

fn find_workspace_members(repo_root: &Path) -> Vec<String> {
    read_crate_manifest(repo_root).workspace.expect("workspace").members
}

#[derive(Debug)]
struct ParsedDependency {
    name: String,
    path: String,
}

#[derive(Debug)]
struct ParsedMember {
    /// Package name
    name: String,
    /// Path in the workspace
    member: String,
    /// Internal dep package names
    internal_deps: Vec<ParsedDependency>,
}

fn topo_sort(members: &mut [ParsedMember]) {
    'again: loop {
        for i in 0..members.len() {
            for j in i..members.len() {
                if i == j {
                    continue;
                }

                if members[i].internal_deps.iter().any(|d| d.name == members[j].name) {
                    members.swap(i, j);
                    // Native algorithm
                    continue 'again;
                }
            }
        }
        break;
    }
}

fn patch_crate(repo_root: &Path, member: &ParsedMember, new_version: &str) {
    let mut manifest_path = repo_root.to_owned();
    manifest_path.push(&member.member);
    manifest_path.push("Cargo.toml");

    let read = File::open(&manifest_path).expect(&format!("open manifest {:?}", manifest_path));
    let read = BufReader::new(read);

    #[derive(Debug, Eq, PartialEq)]
    enum WhereWeAre {
        Init,
        Package,
        Dependencies,
        Other,
    }

    let mut where_we_are = WhereWeAre::Init;

    let mut output = String::new();

    let mut version_patched = false;
    let mut internal_deps_seen = HashSet::new();

    for line in read.lines() {
        let line = line.expect("line");

        let mut line_written = false;

        if line == "[package]" {
            where_we_are = WhereWeAre::Package;
        } else if line == "[dependencies]" {
            where_we_are = WhereWeAre::Dependencies;
        } else if line.starts_with("[") {
            where_we_are = WhereWeAre::Other;
        } else {
            match where_we_are {
                WhereWeAre::Package => {
                    if line.starts_with("version =") {
                        assert!(!version_patched, "in {}", member.name);
                        version_patched = true;

                        writeln!(output, "version = \"{}\"", new_version).expect("write");
                        line_written = true;
                    }
                }
                WhereWeAre::Dependencies => {
                    for dep in &member.internal_deps {
                        if line.starts_with(&format!("{} ", dep.name)) {
                            let inserted = internal_deps_seen.insert(dep.name.clone());
                            assert!(inserted, "dep more than once in {}", member.name);

                            writeln!(
                                output,
                                "{} = {{ path = \"{}\", version = \"={}\" }}",
                                dep.name, dep.path, new_version)
                                .expect("write");
                            line_written = true;
                            break;
                        }
                    }
                }
                _ => {}
            }
        }

        if !line_written {
            writeln!(output, "{}", line).expect("write");
        }
    }

    assert!(version_patched, "in {}", member.name);
    assert_eq!(member.internal_deps.len(), internal_deps_seen.len(), "in {}", member.name);

    fs::write(&manifest_path, &output).expect("write patched manifest back");
}

fn main() {
    let args: Vec<String> = env::args().skip(1).collect();
    assert_eq!(1, args.len());
    let new_version = &args[0];

    let repo_root = find_repo_root();

    let members = find_workspace_members(&repo_root);

    let mut publish_members = Vec::new();

    for member in members {
        let mut crate_path = repo_root.to_owned();
        crate_path.push(&member);
        let manifest = read_crate_manifest(&crate_path);
        let package = manifest.package
            .expect(&format!("package in {}", member));
        let dependencies = manifest.dependencies
            .expect(&format!("dependencies in {}", member));
        if package.publish == Some(false) {
            continue;
        }
        if package.version == "0.0.0" {
            panic!("version must be 0.0.0 is !publish for {}", member);
        }
        if package.version == "0.1.0" {
            panic!("default version 1.0.0 in {}", member);
        }

        let name = package.name;

        let mut internal_deps = Vec::new();

        for (name, dep) in dependencies {
            if let TomlDependency::Detailed(d) = dep {
                let path = match d.path {
                    Some(path) => path,
                    None => {
                        // Not internal dependency
                        continue
                    },
                };
                let version = d.version.expect(&format!("version in dep of {}", member));
                assert!(version.starts_with("="), "dep version must start with =: {}", member);
                internal_deps.push(ParsedDependency {
                    name,
                    path,
                });
            }
        }

        publish_members.push(ParsedMember {
            name,
            member,
            internal_deps,
        });
    }

    topo_sort(&mut publish_members);

    for member in &publish_members {
        patch_crate(&repo_root, member, new_version);
    }

    for member in &publish_members {
        println!("cargo publish --manifest-path={}/Cargo.toml", member.member);
    }
}
<|endoftext|>


<commit_before>use chrono::*;
use std::io::prelude::*;
use render::Renderer;
use result;
use hyper::client;
use hyper::net::Fresh;
use hyper::method;
use hyper::Url;

pub struct InfluxDbRenderer<'a> {
    time: DateTime<UTC>,
    prefix: Option<String>,
    stream: &'a mut Write,
}

impl<'a> InfluxDbRenderer<'a> {
    pub fn new(time: DateTime<UTC>,
               prefix: Option<String>,
               stream: &'a mut Write)
               -> InfluxDbRenderer<'a> {
        InfluxDbRenderer {
            time: time,
            prefix: prefix,
            stream: stream,
        }
    }
}

impl<'a> Renderer for InfluxDbRenderer<'a> {
    fn render(&mut self, result: result::RequestLogAnalyzerResult) -> () {
		let client = client::Client::new();
		let res = client.post("http://localhost:8086/write?db=mydb")
					.body(&post_body(result))
					.send()
					.unwrap();
    }
}

fn post_body(result: result::RequestLogAnalyzerResult) -> String {
	let mut timing_values = String::from("");
	let mut error_rate_values = String::from("");

	match result.timing {
		Some(timing) => {
			timing_values = format!("\
				time_max={} \
				time_min={} \
				time_avg={} \
				time_median={} \
				time_90percent={}",
				timing.max,
				timing.min,
				timing.avg,
				timing.median,
				timing.percentile90);
		}
		None => warn!("No matching log lines in file."),
	}

	match result.error {
		Some(error) => {
			error_rate_values = format!("\
				client_error_4xx_rate={} \
				server_error_5xx_rate={}",
				error.client_error_4xx,
				error.server_error_5xx);
		}
		None => warn!("No matching log lines in file."),
	}

	format!("request_log count={} {} {}", result.count, timing_values, error_rate_values)
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::prelude::*;
    use std::str;
    use chrono::*;
    use analyzer;
    use super::*;

    struct MockTcpStream {
        write_calls: Vec<String>,
    }

    impl Write for MockTcpStream {
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.write_calls.push(str::from_utf8(buf).unwrap().to_string());
            Ok(1)
        }

        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    fn get_result_fixture() -> result::RequestLogAnalyzerResult {
        result::RequestLogAnalyzerResult {
            count: 3,
            timing: Some(analyzer::TimingResult {
                max: 100,
                min: 1,
                avg: 37,
                median: 10,
                percentile90: 100,
                count: 3,
            }),
            error: Some(analyzer::aggregated_error_rates::ErrorRatesResult {
                client_error_4xx: 0.1,
                server_error_5xx: 0.2,
            }),
        }
    }

	#[test]
	fn test_post_body() {
		let result = post_body(get_result_fixture());

		assert!(result.starts_with("request_log "));

		assert!(result.contains("count=3"));
		assert!(result.contains("time_max=100"));
		assert!(result.contains("time_min=1"));
		assert!(result.contains("time_avg=37"));
		assert!(result.contains("time_median=10"));
		assert!(result.contains("time_90percent=100"));
		assert!(result.contains("client_error_4xx_rate=0.1"));
		assert!(result.contains("server_error_5xx_rate=0.2"));

	}

	#[test]
	fn test_post_body_empty() {
		let result = post_body(result::RequestLogAnalyzerResult {
            count: 0,
            timing: None,
            error: None,
        });

		assert!(result.starts_with("request_log "));

		assert!(result.contains("count=0"));

		// Don't include empty fields
		assert!(!result.contains("time_max="));
		assert!(!result.contains("time_min="));
		assert!(!result.contains("time_avg="));
		assert!(!result.contains("time_median="));
		assert!(!result.contains("time_90percent="));
		assert!(!result.contains("client_error_4xx_rate="));
		assert!(!result.contains("server_error_5xx_rate="));
	}
}
<commit_msg>Base URL is the minimal Influx configuration<commit_after>use chrono::*;
use std::io::prelude::*;
use render::Renderer;
use result;
use hyper::client;
use hyper::net::Fresh;
use hyper::method;
use hyper::Url;

pub struct InfluxDbRenderer {
    write_url: String,
}

impl InfluxDbRenderer {
    pub fn new(write_url: String)
               -> InfluxDbRenderer {
        InfluxDbRenderer {
            write_url: write_url,
        }
    }
}

impl Renderer for InfluxDbRenderer {
    fn render(&mut self, result: result::RequestLogAnalyzerResult) -> () {
		let client = client::Client::new();
		let res = client.post(&self.write_url)
					.body(&post_body(result))
					.send()
					.unwrap();
    }
}

fn post_body(result: result::RequestLogAnalyzerResult) -> String {
	let mut timing_values = String::from("");
	let mut error_rate_values = String::from("");

	match result.timing {
		Some(timing) => {
			timing_values = format!("\
				time_max={} \
				time_min={} \
				time_avg={} \
				time_median={} \
				time_90percent={}",
				timing.max,
				timing.min,
				timing.avg,
				timing.median,
				timing.percentile90);
		}
		None => warn!("No matching log lines in file."),
	}

	match result.error {
		Some(error) => {
			error_rate_values = format!("\
				client_error_4xx_rate={} \
				server_error_5xx_rate={}",
				error.client_error_4xx,
				error.server_error_5xx);
		}
		None => warn!("No matching log lines in file."),
	}

	format!("request_log count={} {} {}", result.count, timing_values, error_rate_values)
}

#[cfg(test)]
mod tests {
    use std::io;
    use std::io::prelude::*;
    use std::str;
    use chrono::*;
    use analyzer;
    use super::*;

    struct MockTcpStream {
        write_calls: Vec<String>,
    }

    impl Write for MockTcpStream {
        fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
            self.write_calls.push(str::from_utf8(buf).unwrap().to_string());
            Ok(1)
        }

        fn flush(&mut self) -> io::Result<()> {
            Ok(())
        }
    }

    fn get_result_fixture() -> result::RequestLogAnalyzerResult {
        result::RequestLogAnalyzerResult {
            count: 3,
            timing: Some(analyzer::TimingResult {
                max: 100,
                min: 1,
                avg: 37,
                median: 10,
                percentile90: 100,
                count: 3,
            }),
            error: Some(analyzer::aggregated_error_rates::ErrorRatesResult {
                client_error_4xx: 0.1,
                server_error_5xx: 0.2,
            }),
        }
    }

	#[test]
	fn test_instantiate() {
		InfluxDbRenderer::new(String::from("http://example.com/write?db=testdb"));
	}

	#[test]
	fn test_post_body() {
		let result = post_body(get_result_fixture());

		assert!(result.starts_with("request_log "));

		assert!(result.contains("count=3"));
		assert!(result.contains("time_max=100"));
		assert!(result.contains("time_min=1"));
		assert!(result.contains("time_avg=37"));
		assert!(result.contains("time_median=10"));
		assert!(result.contains("time_90percent=100"));
		assert!(result.contains("client_error_4xx_rate=0.1"));
		assert!(result.contains("server_error_5xx_rate=0.2"));

	}

	#[test]
	fn test_post_body_empty() {
		let result = post_body(result::RequestLogAnalyzerResult {
            count: 0,
            timing: None,
            error: None,
        });

		assert!(result.starts_with("request_log "));

		assert!(result.contains("count=0"));

		// Don't include empty fields
		assert!(!result.contains("time_max="));
		assert!(!result.contains("time_min="));
		assert!(!result.contains("time_avg="));
		assert!(!result.contains("time_median="));
		assert!(!result.contains("time_90percent="));
		assert!(!result.contains("client_error_4xx_rate="));
		assert!(!result.contains("server_error_5xx_rate="));
	}
}
<|endoftext|>