From 3e7bc2888c4f23d3a362dd777ed28a4c9ab0b5ae Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Tue, 11 Dec 2018 00:39:39 +0000 Subject: [PATCH 01/27] Get last bitcon block hash, setup genesis header without PoW (for now) --- Cargo.toml | 1 + etc/gen_gen/Cargo.toml | 24 +++++++ etc/gen_gen/README.md | 18 ++++++ etc/gen_gen/src/bin/gen_gen.rs | 114 +++++++++++++++++++++++++++++++++ 4 files changed, 157 insertions(+) create mode 100644 etc/gen_gen/Cargo.toml create mode 100644 etc/gen_gen/README.md create mode 100644 etc/gen_gen/src/bin/gen_gen.rs diff --git a/Cargo.toml b/Cargo.toml index ad5625825..8a9fc7881 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ build = "src/build/build.rs" [workspace] members = ["api", "chain", "config", "core", "keychain", "p2p", "servers", "store", "util", "pool", "wallet"] +exclude = ["etc/gen_gen"] [[bin]] name = "grin" diff --git a/etc/gen_gen/Cargo.toml b/etc/gen_gen/Cargo.toml new file mode 100644 index 000000000..b90811c3f --- /dev/null +++ b/etc/gen_gen/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "grin_gen_gen" +version = "0.0.1" +edition = "2018" +authors = ["Grin Developers "] +description = "Utility to automate the generation of Grin's genesis block" +license = "Apache-2.0" +repository = "https://github.com/mimblewimble/grin" +keywords = [ "crypto", "grin", "mimblewimble" ] +readme = "README.md" + +[[bin]] +name = "gen_gen" +path = "src/bin/gen_gen.rs" + +[dependencies] +chrono = "0.4.4" +curl = "0.4.19" +serde_json = "1" +grin_core = "0.4.2" +grin_chain = "0.4.2" +grin_keychain = "0.4.2" +grin_store = "0.4.2" +grin_util = "0.4.2" diff --git a/etc/gen_gen/README.md b/etc/gen_gen/README.md new file mode 100644 index 000000000..d97b67579 --- /dev/null +++ b/etc/gen_gen/README.md @@ -0,0 +1,18 @@ +# Genesis Genesis + +This crate isn't strictly part of grin but allows the generation and release of a new Grin Genesis in an automated fashion. The process is the following: + +* Prepare a multisig output and kernel to use as coinbase. In the case of Grin mainnet, this is done and owned by the council treasurers. This can be down a few days prior. +* Grab the latest bitcoin block hash from publicly available APIs. +* Build a genesis block with the prepared coinbase and the bitcoin block hash as `prev_root`. The timestamp of the block is set to 30 min ahead to leave enough time to run a build and start a node. +* Mine the block so we have at least a valid Cuckatoo Cycle. We don't require a given difficulty for that solution. +* Finalize the block with the proof-of-work, setting a high-enough difficulty (to be agreed upon separately). +* Commit the block information to github. +* Tag version 1.0.0 (scary). + +N.B. This was written while listening to Genesis. Unfortunately, I'm not rich enough to do it while driving a Genesis. And that'd be dangerous. + +# Usage + +1. Build this crate. +2. From its root run `./target/release/gen-gen --coinbase --difficulty --tag ` diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs new file mode 100644 index 000000000..a2ee67ab3 --- /dev/null +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -0,0 +1,114 @@ +// 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::fs; +use std::sync::Arc; + +use chrono::Duration; +use chrono::prelude::Utc; +use curl; +use serde_json; + +use grin_chain as chain; +use grin_core as core; +use grin_store as store; +use grin_util as util; + +use grin_keychain::{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"; + +fn main() { + // 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."); + } + println!("Using bitcoin block hash {}", h1); + + // build the basic parts of the genesis block header, perhaps some of this + // can be moved to core + 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(); + gen.header.pow.proof.edge_bits = 29; + println!("Built genesis:\n{:?}", gen); + + // TODO get the proper keychain and/or raw coinbase + let keychain = ExtKeychain::from_random_seed().unwrap(); + let key_id = ExtKeychain::derive_key_id(0, 1, 0, 0, 0); + let reward = core::libtx::reward::output(&keychain, &key_id, 0, 0).unwrap(); + gen = gen.with_reward(reward.0, reward.1); + + { + // setup a tmp chain to set block header roots + let tmp_chain = setup_chain(".grin.tmp", core::pow::mine_genesis_block().unwrap()); + tmp_chain.set_txhashset_roots(&mut gen).unwrap(); + gen.header.output_mmr_size = 1; + gen.header.kernel_mmr_size = 1; + } + + // TODO mine a valid Cuckatoo29 solution + // TODO check again the bitcoin block to make sure it's not been orphaned + // TODO Commit genesis block info in git and tag +} + +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, + ).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() +} From 934b11d06f228162765c4eb3c69ad085a1de592e Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Tue, 11 Dec 2018 01:07:17 +0000 Subject: [PATCH 02/27] More a few properties to mainnet genesis. Don't get too excited, several are placeholders. --- Cargo.lock | 2 -- Cargo.toml | 1 + core/src/genesis.rs | 18 ++++++++++-------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c13bdd0a..c85e4cffc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -751,7 +751,6 @@ dependencies = [ "grin_keychain 0.4.2", "grin_store 0.4.2", "grin_util 0.4.2", - "grin_wallet 0.4.2", "lmdb-zero 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -854,7 +853,6 @@ dependencies = [ "grin_keychain 0.4.2", "grin_store 0.4.2", "grin_util 0.4.2", - "grin_wallet 0.4.2", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index ad5625825..8a9fc7881 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,7 @@ build = "src/build/build.rs" [workspace] members = ["api", "chain", "config", "core", "keychain", "p2p", "servers", "store", "util", "pool", "wallet"] +exclude = ["etc/gen_gen"] [[bin]] name = "grin" diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 01be438c4..e1f34a115 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -16,7 +16,6 @@ use chrono::prelude::{TimeZone, Utc}; -use consensus; use core; use global; use pow::{Difficulty, Proof, ProofOfWork}; @@ -110,7 +109,6 @@ pub fn genesis_testnet3() -> core::Block { pub fn genesis_testnet4() -> core::Block { core::Block::with_header(core::BlockHeader { height: 0, - // previous: core::hash::Hash([0xff; 32]), timestamp: Utc.ymd(2018, 10, 17).and_hms(20, 0, 0), pow: ProofOfWork { total_difficulty: Difficulty::from_num(global::initial_block_difficulty()), @@ -137,13 +135,17 @@ pub fn genesis_testnet4() -> core::Block { pub fn genesis_main() -> core::Block { core::Block::with_header(core::BlockHeader { height: 0, - // previous: core::hash::Hash([0xff; 32]), - timestamp: Utc.ymd(2018, 8, 14).and_hms(0, 0, 0), + timestamp: Utc.ymd(2019, 0, 15).and_hms(12, 0, 0), + output_mmr_size: 1, + kernel_mmr_size: 1, pow: ProofOfWork { - total_difficulty: Difficulty::from_num(global::initial_block_difficulty()), - secondary_scaling: 1, - nonce: global::get_genesis_nonce(), - proof: Proof::zero(consensus::PROOFSIZE), + total_difficulty: Difficulty::from_num(10_u64.pow(8)), + secondary_scaling: 1856, + nonce: 1, + proof: Proof { + nonces: vec![0; 42], + edge_bits: 29, + }, }, ..Default::default() }) From a58235f603ce72b9c3af346cefe592ff8d3e2235 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Tue, 11 Dec 2018 01:08:02 +0000 Subject: [PATCH 03/27] Trying to fix slight snafu --- etc/gen_gen/Cargo.toml | 24 +++++++ etc/gen_gen/README.md | 18 +++++ etc/gen_gen/src/bin/gen_gen.rs | 125 +++++++++++++++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 etc/gen_gen/Cargo.toml create mode 100644 etc/gen_gen/README.md create mode 100644 etc/gen_gen/src/bin/gen_gen.rs diff --git a/etc/gen_gen/Cargo.toml b/etc/gen_gen/Cargo.toml new file mode 100644 index 000000000..00a9024f9 --- /dev/null +++ b/etc/gen_gen/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "grin_gen_gen" +version = "0.0.1" +edition = "2018" +authors = ["Grin Developers "] +description = "Utility to automate the generation of Grin's genesis block" +license = "Apache-2.0" +repository = "https://github.com/mimblewimble/grin" +keywords = [ "crypto", "grin", "mimblewimble" ] +readme = "README.md" + +[[bin]] +name = "gen_gen" +path = "src/bin/gen_gen.rs" + +[dependencies] +chrono = "0.4.4" +curl = "0.4.19" +serde_json = "1" +grin_core = { path = "../../core", version = "0.4.2" } +grin_chain = "0.4.2" +grin_keychain = "0.4.2" +grin_store = "0.4.2" +grin_util = "0.4.2" diff --git a/etc/gen_gen/README.md b/etc/gen_gen/README.md new file mode 100644 index 000000000..d97b67579 --- /dev/null +++ b/etc/gen_gen/README.md @@ -0,0 +1,18 @@ +# Genesis Genesis + +This crate isn't strictly part of grin but allows the generation and release of a new Grin Genesis in an automated fashion. The process is the following: + +* Prepare a multisig output and kernel to use as coinbase. In the case of Grin mainnet, this is done and owned by the council treasurers. This can be down a few days prior. +* Grab the latest bitcoin block hash from publicly available APIs. +* Build a genesis block with the prepared coinbase and the bitcoin block hash as `prev_root`. The timestamp of the block is set to 30 min ahead to leave enough time to run a build and start a node. +* Mine the block so we have at least a valid Cuckatoo Cycle. We don't require a given difficulty for that solution. +* Finalize the block with the proof-of-work, setting a high-enough difficulty (to be agreed upon separately). +* Commit the block information to github. +* Tag version 1.0.0 (scary). + +N.B. This was written while listening to Genesis. Unfortunately, I'm not rich enough to do it while driving a Genesis. And that'd be dangerous. + +# Usage + +1. Build this crate. +2. From its root run `./target/release/gen-gen --coinbase --difficulty --tag ` diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs new file mode 100644 index 000000000..c7311a589 --- /dev/null +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -0,0 +1,125 @@ +// 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::fs; +use std::sync::Arc; + +use chrono::prelude::Utc; +use chrono::Duration; +use curl; +use serde_json; + +use grin_chain as chain; +use grin_core as core; +use grin_store as store; +use grin_util as util; + +use grin_keychain::{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"; + +fn main() { + // 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, perhaps some of this + // can be moved to core + 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(); + println!("Built genesis:\n{:?}", gen); + + // TODO get the proper keychain and/or raw coinbase + let keychain = ExtKeychain::from_random_seed().unwrap(); + let key_id = ExtKeychain::derive_key_id(0, 1, 0, 0, 0); + let reward = core::libtx::reward::output(&keychain, &key_id, 0, 0).unwrap(); + gen = gen.with_reward(reward.0, reward.1); + + { + // setup a tmp chain to set block header roots + let tmp_chain = setup_chain(".grin.tmp", core::pow::mine_genesis_block().unwrap()); + tmp_chain.set_txhashset_roots(&mut gen).unwrap(); + } + + // TODO mine a valid Cuckatoo29 solution + // TODO check again the bitcoin block to make sure it's not been orphaned + // TODO Commit genesis block info in git and tag +} + +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, + ) + .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() +} From 725499bbf0d21de6655d0c4525a5c4bada0d4f7a Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Tue, 11 Dec 2018 01:09:28 +0000 Subject: [PATCH 04/27] Trying to fix slight snafu --- etc/gen_gen/src/bin/gen_gen.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index f7b0c57fa..c7311a589 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -17,13 +17,8 @@ use std::fs; use std::sync::Arc; -<<<<<<< HEAD use chrono::prelude::Utc; use chrono::Duration; -======= -use chrono::Duration; -use chrono::prelude::Utc; ->>>>>>> 3e7bc2888c4f23d3a362dd777ed28a4c9ab0b5ae use curl; use serde_json; From 31e69e66ac14b8b549da7245eef23008d01ecc85 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Wed, 12 Dec 2018 23:29:06 +0000 Subject: [PATCH 05/27] Mine a valid Cuckaroo solution for genesis block --- etc/gen_gen/Cargo.toml | 6 ++++-- etc/gen_gen/src/bin/gen_gen.rs | 29 +++++++++++++++++++++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/etc/gen_gen/Cargo.toml b/etc/gen_gen/Cargo.toml index 00a9024f9..a985f6488 100644 --- a/etc/gen_gen/Cargo.toml +++ b/etc/gen_gen/Cargo.toml @@ -15,10 +15,12 @@ path = "src/bin/gen_gen.rs" [dependencies] chrono = "0.4.4" +cuckoo_miner = "0.4.2" curl = "0.4.19" -serde_json = "1" -grin_core = { path = "../../core", version = "0.4.2" } +grin_core = "0.4.2" grin_chain = "0.4.2" grin_keychain = "0.4.2" +grin_miner_plugin = "0.4.2" grin_store = "0.4.2" grin_util = "0.4.2" +serde_json = "1" diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index c7311a589..efea9185a 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -22,18 +22,23 @@ use chrono::Duration; use curl; 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_keychain::{ExtKeychain, Keychain}; +use grin_core::core::verifier_cache::LruVerifierCache; +use grin_keychain::{ExtKeychain, Keychain, BlindingFactor}; 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"; fn main() { + core::global::set_mining_mode(core::global::ChainTypes::Mainnet); + // get the latest bitcoin hash let h1 = get_bchain_head(); let h2 = get_bcypher_head(); @@ -65,7 +70,27 @@ fn main() { tmp_chain.set_txhashset_roots(&mut gen).unwrap(); } - // TODO mine a valid Cuckatoo29 solution + // mine a Cuckaroo29 block + let plugin_path = "cuckaroo_mean_cuda_29.cuckooplugin"; + let plugin_lib = cuckoo::PluginLibrary::new(plugin_path).unwrap(); + let solver_ctx = plugin_lib.create_solver_ctx(&mut plugin_lib.get_default_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(); + plugin_lib.run_solver(solver_ctx, gen.header.pre_pow(), nonce, 1, &mut solver_sols, &mut solver_stats); + nonce += 1; + } + + // set the PoW solution and make sure the block is mostly valid + gen.header.pow.nonce = solver_sols.sols[0].nonce as u64; + gen.header.pow.proof.nonces = solver_sols.sols[0].to_u64s(); + assert!(gen.header.pow.is_secondary(), "Not a secondary header"); + core::pow::verify_size(&gen.header).unwrap(); + gen.validate(&BlindingFactor::zero(), Arc::new(util::RwLock::new(LruVerifierCache::new()))).unwrap(); + // TODO check again the bitcoin block to make sure it's not been orphaned // TODO Commit genesis block info in git and tag } From 18416e85287f71beda1abb099a1b469485d5c547 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Thu, 13 Dec 2018 01:54:25 +0000 Subject: [PATCH 06/27] Use miner as library to get a solution for genesis. Replace final values in genesis.rs before committing it. --- core/src/genesis.rs | 28 +++++++- etc/gen_gen/src/bin/gen_gen.rs | 117 ++++++++++++++++++++++++++++++--- 2 files changed, 134 insertions(+), 11 deletions(-) diff --git a/core/src/genesis.rs b/core/src/genesis.rs index d26b3b9ae..98ed3aa97 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -20,6 +20,9 @@ use crate::core; use crate::global; use crate::pow::{Difficulty, Proof, ProofOfWork}; +use crate::core::hash::Hash; +use crate::keychain::BlindingFactor; + /// Genesis block definition for development networks. The proof of work size /// is small enough to mine it on the fly, so it does not contain its own /// proof of work solution. Can also be easily mutated for different tests. @@ -135,18 +138,37 @@ pub fn genesis_testnet4() -> core::Block { pub fn genesis_main() -> core::Block { core::Block::with_header(core::BlockHeader { height: 0, - timestamp: Utc.ymd(2019, 0, 15).and_hms(12, 0, 0), + timestamp: Utc.ymd(2019, 1, 15).and_hms(12, 0, 0), // REPLACE + prev_root: Hash::default(), // REPLACE + output_root: Hash::default(), // REPLACE + range_proof_root: Hash::default(), // REPLACE + kernel_root: Hash::default(), // REPLACE + total_kernel_offset: BlindingFactor::zero(), // REPLACE output_mmr_size: 1, kernel_mmr_size: 1, pow: ProofOfWork { total_difficulty: Difficulty::from_num(10_u64.pow(8)), secondary_scaling: 1856, - nonce: 1, + nonce: 1, // REPLACE proof: Proof { - nonces: vec![0; 42], + nonces: vec![0; 42], // REPLACE edge_bits: 29, }, }, ..Default::default() }) } + + +#[cfg(test)] +mod test { + use super::*; + + // TODO update the hash once genesis is set + #[test] + fn mainnet_genesis_hash() { + let gen_hash = genesis_main().hash(); + println!("mainnet genesis hash: {}", gen_hash.to_hex()); + //assert_eq!(gene_hash.to_hex, ""); + } +} diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index efea9185a..60f0f0e9e 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -14,11 +14,12 @@ //! Main for building the genesis generation utility. -use std::fs; +use std::{fs, io, path, process}; +use std::io::{BufRead, Write}; use std::sync::Arc; use chrono::prelude::Utc; -use chrono::Duration; +use chrono::{Duration, Timelike, Datelike}; use curl; use serde_json; @@ -30,14 +31,23 @@ use grin_store as store; use grin_util as util; use grin_core::core::verifier_cache::LruVerifierCache; -use grin_keychain::{ExtKeychain, Keychain, BlindingFactor}; +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"; + fn main() { core::global::set_mining_mode(core::global::ChainTypes::Mainnet); + 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); + } // get the latest bitcoin hash let h1 = get_bchain_head(); @@ -71,8 +81,7 @@ fn main() { } // mine a Cuckaroo29 block - let plugin_path = "cuckaroo_mean_cuda_29.cuckooplugin"; - let plugin_lib = cuckoo::PluginLibrary::new(plugin_path).unwrap(); + let plugin_lib = cuckoo::PluginLibrary::new(PLUGIN_PATH).unwrap(); let solver_ctx = plugin_lib.create_solver_ctx(&mut plugin_lib.get_default_params()); let mut solver_sols = plugin::SolverSolutions::default(); @@ -80,7 +89,14 @@ fn main() { let mut nonce = 0; while solver_sols.num_sols == 0 { solver_sols = plugin::SolverSolutions::default(); - plugin_lib.run_solver(solver_ctx, gen.header.pre_pow(), nonce, 1, &mut solver_sols, &mut solver_stats); + plugin_lib.run_solver( + solver_ctx, + gen.header.pre_pow(), + nonce, + 1, + &mut solver_sols, + &mut solver_stats, + ); nonce += 1; } @@ -89,10 +105,95 @@ fn main() { gen.header.pow.proof.nonces = solver_sols.sols[0].to_u64s(); assert!(gen.header.pow.is_secondary(), "Not a secondary header"); core::pow::verify_size(&gen.header).unwrap(); - gen.validate(&BlindingFactor::zero(), Arc::new(util::RwLock::new(LruVerifierCache::new()))).unwrap(); + gen.validate( + &BlindingFactor::zero(), + Arc::new(util::RwLock::new(LruVerifierCache::new())), + ) + .unwrap(); + + println!("Final genesis hash: {}", gen.hash().to_hex()); // TODO check again the bitcoin block to make sure it's not been orphaned - // TODO Commit genesis block info in git and tag + + update_genesis_rs(&gen); + println!("genesis.rs has been updated, check it and press c+enter to proceed."); + let mut input = String::new(); + io::stdin().read_line(&mut input).unwrap(); + if input != "c" { + 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) { + // TODO coinbase output and kernel + + // 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(( + "output_root".to_string(), + format!("Hash::from_hex(\"{}\")", gen.header.output_root.to_hex()), + )); + replacements.push(( + "range_proof_root".to_string(), + format!("Hash::from_hex(\"{}\")", gen.header.range_proof_root.to_hex()), + )); + replacements.push(( + "kernel_root".to_string(), + format!("Hash::from_hex(\"{}\")", gen.header.kernel_root.to_hex()), + )); + + // check each possible replacement in the file + 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 { From 2386ce3b8ac2962c2261e5360e2de5ee8e511d38 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Fri, 14 Dec 2018 00:46:41 +0000 Subject: [PATCH 07/27] Complete genesis replacement --- core/src/genesis.rs | 30 ++++++++---- core/src/global.rs | 2 + etc/gen_gen/Cargo.toml | 4 ++ etc/gen_gen/src/bin/gen_gen.rs | 83 +++++++++++++++++++++++++++------- 4 files changed, 95 insertions(+), 24 deletions(-) diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 98ed3aa97..1e90df646 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -19,6 +19,8 @@ use chrono::prelude::{TimeZone, Utc}; use crate::core; use crate::global; use crate::pow::{Difficulty, Proof, ProofOfWork}; +use crate::util::secp::Signature; +use crate::util::secp::pedersen::{Commitment, RangeProof}; use crate::core::hash::Hash; use crate::keychain::BlindingFactor; @@ -136,14 +138,14 @@ pub fn genesis_testnet4() -> core::Block { /// Placeholder for mainnet genesis block, will definitely change before /// release so no use trying to pre-mine it. pub fn genesis_main() -> core::Block { - core::Block::with_header(core::BlockHeader { + let gen = core::Block::with_header(core::BlockHeader { height: 0, timestamp: Utc.ymd(2019, 1, 15).and_hms(12, 0, 0), // REPLACE - prev_root: Hash::default(), // REPLACE - output_root: Hash::default(), // REPLACE - range_proof_root: Hash::default(), // REPLACE - kernel_root: Hash::default(), // REPLACE - total_kernel_offset: BlindingFactor::zero(), // REPLACE + prev_root: Hash::default(), // REPLACE + output_root: Hash::default(), // REPLACE + range_proof_root: Hash::default(), // REPLACE + kernel_root: Hash::default(), // REPLACE + total_kernel_offset: BlindingFactor::zero(), // REPLACE output_mmr_size: 1, kernel_mmr_size: 1, pow: ProofOfWork { @@ -156,10 +158,22 @@ pub fn genesis_main() -> core::Block { }, }, ..Default::default() - }) + }); + let kernel = core::TxKernel { + features: core::KernelFeatures::COINBASE_KERNEL, + fee: 0, + lock_height: 0, + excess: Commitment::from_vec(vec![]), // REPLACE + excess_sig: Signature::from_raw_data(&[0; 64]).unwrap(), //REPLACE + }; + let output = core::Output { + features: core::OutputFeatures::COINBASE_OUTPUT, + commit: Commitment::from_vec(vec![]), // REPLACE + proof: RangeProof::zero(), // REPLACE + }; + gen.with_reward(output, kernel) } - #[cfg(test)] mod test { use super::*; diff --git a/core/src/global.rs b/core/src/global.rs index 30a38374d..9384d1d75 100644 --- a/core/src/global.rs +++ b/core/src/global.rs @@ -311,6 +311,8 @@ pub fn get_genesis_nonce() -> u64 { ChainTypes::AutomatedTesting => 0, // Magic nonce for current genesis block at cuckatoo15 ChainTypes::UserTesting => 27944, + // Placeholder, obviously not the right value + ChainTypes::Mainnet => 0, // Magic nonce for genesis block for testnet2 (cuckatoo29) _ => panic!("Pre-set"), } diff --git a/etc/gen_gen/Cargo.toml b/etc/gen_gen/Cargo.toml index a985f6488..f1d394592 100644 --- a/etc/gen_gen/Cargo.toml +++ b/etc/gen_gen/Cargo.toml @@ -24,3 +24,7 @@ grin_miner_plugin = "0.4.2" grin_store = "0.4.2" grin_util = "0.4.2" serde_json = "1" + +[patch.crates-io] +grin_core = { path = "../../core" } +grin_keychain = { path = "../../keychain" } diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index 60f0f0e9e..7e4dea486 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -14,12 +14,12 @@ //! Main for building the genesis generation utility. -use std::{fs, io, path, process}; use std::io::{BufRead, Write}; use std::sync::Arc; +use std::{fs, io, path, process}; use chrono::prelude::Utc; -use chrono::{Duration, Timelike, Datelike}; +use chrono::{Datelike, Duration, Timelike}; use curl; use serde_json; @@ -43,10 +43,16 @@ static PLUGIN_PATH: &str = "cuckaroo_mean_cuda_29.cuckooplugin"; fn main() { core::global::set_mining_mode(core::global::ChainTypes::Mainnet); 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); + 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); + panic!( + "File {} not found, make sure you're running this from the gen_gen directory", + PLUGIN_PATH + ); } // get the latest bitcoin hash @@ -61,12 +67,10 @@ fn main() { } println!("Using bitcoin block hash {}", h1); - // build the basic parts of the genesis block header, perhaps some of this - // can be moved to core + // 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(); - println!("Built genesis:\n{:?}", gen); // TODO get the proper keychain and/or raw coinbase let keychain = ExtKeychain::from_random_seed().unwrap(); @@ -100,7 +104,7 @@ fn main() { nonce += 1; } - // set the PoW solution and make sure the block is mostly valid + // // set the PoW solution and make sure the block is mostly valid gen.header.pow.nonce = solver_sols.sols[0].nonce as u64; gen.header.pow.proof.nonces = solver_sols.sols[0].to_u64s(); assert!(gen.header.pow.is_secondary(), "Not a secondary header"); @@ -111,16 +115,17 @@ fn main() { ) .unwrap(); + println!("Built genesis:\n{:?}", gen); println!("Final genesis hash: {}", gen.hash().to_hex()); - // TODO check again the bitcoin block to make sure it's not been orphaned - update_genesis_rs(&gen); - println!("genesis.rs has been updated, check it and press c+enter to proceed."); + 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" { - return + return; } // Commit genesis block info in git and tag @@ -140,8 +145,6 @@ fn main() { } fn update_genesis_rs(gen: &core::core::Block) { - // TODO coinbase output and kernel - // set the replacement patterns let mut replacements = vec![]; replacements.push(( @@ -156,20 +159,68 @@ fn update_genesis_rs(gen: &core::core::Block) { gen.header.timestamp.time().second(), ), )); + replacements.push(( + "prev_root".to_string(), + format!("Hash::from_hex(\"{}\")", gen.header.prev_root.to_hex()), + )); replacements.push(( "output_root".to_string(), format!("Hash::from_hex(\"{}\")", gen.header.output_root.to_hex()), )); replacements.push(( "range_proof_root".to_string(), - format!("Hash::from_hex(\"{}\")", gen.header.range_proof_root.to_hex()), + format!( + "Hash::from_hex(\"{}\")", + gen.header.range_proof_root.to_hex() + ), )); replacements.push(( "kernel_root".to_string(), format!("Hash::from_hex(\"{}\")", gen.header.kernel_root.to_hex()), )); + replacements.push(( + "total_kernel_offset".to_string(), + format!("BlindingFactor::from_hex(\"{}\")", gen.header.total_kernel_offset.to_hex()), + )); + replacements.push(( + "nonce".to_string(), + format!("{}", gen.header.pow.nonce), + )); + replacements.push(( + "nonces".to_string(), + format!("{:x?}", gen.header.pow.proof.nonces), + )); + replacements.push(( + "excess".to_string(), + format!( + "Commitment::from_vec(util::from_hex(\"{:x?}\"))", + util::to_hex(gen.kernels()[0].excess.0.to_vec()) + ), + )); + replacements.push(( + "excess_sig".to_string(), + format!( + "Signature::from_raw_data(&util::from_hex(\"{:x?}\"))", + util::to_hex(gen.kernels()[0].excess_sig.to_raw_data().to_vec()) + ), + )); + replacements.push(( + "commit".to_string(), + format!( + "Commitment::from_vec(util::from_hex(\"{:x?}\"))", + util::to_hex(gen.outputs()[0].commitment().0.to_vec()) + ), + )); + replacements.push(( + "proof".to_string(), + format!( + "RangeProof::from_vec(util::from_hex(\"{:x?}\"))", + util::to_hex(gen.outputs()[0].proof.bytes().to_vec()) + ), + )); - // check each possible replacement in the file + // 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(); From 80726c7f8fb5774df7e85c47f019ab71a72fae2b Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Fri, 14 Dec 2018 02:56:45 +0000 Subject: [PATCH 08/27] Fixed various replacements to obtain a compilable, well-formed genesis --- core/src/core/block.rs | 4 +-- core/src/genesis.rs | 11 +++++++- etc/gen_gen/src/bin/gen_gen.rs | 50 ++++++++++++++++------------------ 3 files changed, 36 insertions(+), 29 deletions(-) diff --git a/core/src/core/block.rs b/core/src/core/block.rs index 220d88bc2..cf1e82adc 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -470,8 +470,8 @@ impl Block { /// Consumes this block and returns a new block with the coinbase output /// and kernels added pub fn with_reward(mut self, reward_out: Output, reward_kern: TxKernel) -> Block { - self.body.outputs.push(reward_out); - self.body.kernels.push(reward_kern); + self.body.outputs = vec![reward_out]; + self.body.kernels = vec![reward_kern]; self } diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 1e90df646..27f167949 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -14,12 +14,17 @@ //! Definition of the genesis block. Placeholder for now. +// required for genesis replacement +//! #![allow(unused_imports)] + use chrono::prelude::{TimeZone, Utc}; use crate::core; use crate::global; use crate::pow::{Difficulty, Proof, ProofOfWork}; +use crate::util; use crate::util::secp::Signature; +use crate::util::secp::constants::SINGLE_BULLET_PROOF_SIZE; use crate::util::secp::pedersen::{Commitment, RangeProof}; use crate::core::hash::Hash; @@ -135,6 +140,7 @@ pub fn genesis_testnet4() -> core::Block { ..Default::default() }) } + /// Placeholder for mainnet genesis block, will definitely change before /// release so no use trying to pre-mine it. pub fn genesis_main() -> core::Block { @@ -169,7 +175,10 @@ pub fn genesis_main() -> core::Block { let output = core::Output { features: core::OutputFeatures::COINBASE_OUTPUT, commit: Commitment::from_vec(vec![]), // REPLACE - proof: RangeProof::zero(), // REPLACE + proof: RangeProof { + plen: SINGLE_BULLET_PROOF_SIZE, + proof: [0; SINGLE_BULLET_PROOF_SIZE], // REPLACE + } }; gen.with_reward(output, kernel) } diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index 7e4dea486..3cea1a397 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -41,7 +41,6 @@ static GENESIS_RS_PATH: &str = "../../core/src/genesis.rs"; static PLUGIN_PATH: &str = "cuckaroo_mean_cuda_29.cuckooplugin"; fn main() { - core::global::set_mining_mode(core::global::ChainTypes::Mainnet); if !path::Path::new(GENESIS_RS_PATH).exists() { panic!( "File {} not found, make sure you're running this from the gen_gen directory", @@ -80,11 +79,13 @@ fn main() { { // 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 solver_ctx = plugin_lib.create_solver_ctx(&mut plugin_lib.get_default_params()); @@ -104,18 +105,18 @@ fn main() { nonce += 1; } - // // set the PoW solution and make sure the block is mostly valid + // set the PoW solution and make sure the block is mostly valid gen.header.pow.nonce = solver_sols.sols[0].nonce as u64; gen.header.pow.proof.nonces = solver_sols.sols[0].to_u64s(); assert!(gen.header.pow.is_secondary(), "Not a secondary header"); - core::pow::verify_size(&gen.header).unwrap(); + 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!("Built genesis:\n{:?}", gen); println!("Final genesis hash: {}", gen.hash().to_hex()); update_genesis_rs(&gen); @@ -124,7 +125,7 @@ fn main() { println!("press c+enter to proceed."); let mut input = String::new(); io::stdin().read_line(&mut input).unwrap(); - if input != "c" { + if input != "c\n" { return; } @@ -161,62 +162,59 @@ fn update_genesis_rs(gen: &core::core::Block) { )); replacements.push(( "prev_root".to_string(), - format!("Hash::from_hex(\"{}\")", gen.header.prev_root.to_hex()), + format!("Hash::from_hex(\"{}\").unwrap()", gen.header.prev_root.to_hex()), )); replacements.push(( "output_root".to_string(), - format!("Hash::from_hex(\"{}\")", gen.header.output_root.to_hex()), + format!("Hash::from_hex(\"{}\").unwrap()", gen.header.output_root.to_hex()), )); replacements.push(( "range_proof_root".to_string(), format!( - "Hash::from_hex(\"{}\")", + "Hash::from_hex(\"{}\").unwrap()", gen.header.range_proof_root.to_hex() ), )); replacements.push(( "kernel_root".to_string(), - format!("Hash::from_hex(\"{}\")", gen.header.kernel_root.to_hex()), + format!("Hash::from_hex(\"{}\").unwrap()", gen.header.kernel_root.to_hex()), )); replacements.push(( "total_kernel_offset".to_string(), - format!("BlindingFactor::from_hex(\"{}\")", gen.header.total_kernel_offset.to_hex()), - )); - replacements.push(( - "nonce".to_string(), - format!("{}", gen.header.pow.nonce), + 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!("{:x?}", gen.header.pow.proof.nonces), + format!("vec!{:x?}", gen.header.pow.proof.nonces), )); replacements.push(( "excess".to_string(), format!( - "Commitment::from_vec(util::from_hex(\"{:x?}\"))", + "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(&util::from_hex(\"{:x?}\"))", - util::to_hex(gen.kernels()[0].excess_sig.to_raw_data().to_vec()) + "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?}\"))", + "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!( - "RangeProof::from_vec(util::from_hex(\"{:x?}\"))", - util::to_hex(gen.outputs()[0].proof.bytes().to_vec()) - ), + format!("{:?}", gen.outputs()[0].proof.bytes().to_vec()), )); // check each possible replacement in the file, remove the replacement from @@ -237,9 +235,9 @@ fn update_genesis_rs(gen: &core::core::Block) { break; } } - if !has_replaced { - replaced.push_str(&format!("{}\n", line)); - } + } + if !has_replaced { + replaced.push_str(&format!("{}\n", line)); } } } From 23cf377d3df5926e1e3b3475864d8c0dc20a11e4 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Fri, 14 Dec 2018 04:51:35 +0000 Subject: [PATCH 09/27] Check plugin errors, uncomment PoW validation --- etc/gen_gen/src/bin/gen_gen.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index 3cea1a397..a6a09eb9e 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -102,6 +102,16 @@ fn main() { &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; } @@ -110,7 +120,7 @@ fn main() { 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(); + core::pow::verify_size(&gen.header).unwrap(); gen.validate( &BlindingFactor::zero(), Arc::new(util::RwLock::new(LruVerifierCache::new())), @@ -189,7 +199,7 @@ fn update_genesis_rs(gen: &core::core::Block) { replacements.push(("nonce".to_string(), format!("{}", gen.header.pow.nonce))); replacements.push(( "nonces".to_string(), - format!("vec!{:x?}", gen.header.pow.proof.nonces), + format!("vec!{:?}", gen.header.pow.proof.nonces), )); replacements.push(( "excess".to_string(), From 40e94f53b651030c9843dbbec46ae964fbccdb27 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Fri, 14 Dec 2018 04:51:52 +0000 Subject: [PATCH 10/27] rustfmt --- etc/gen_gen/src/bin/gen_gen.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index a6a09eb9e..9f7fb982e 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -108,7 +108,7 @@ fn main() { solver_stats.get_plugin_name(), solver_stats.get_device_name(), solver_stats.get_error_reason(), - ); + ); return; } @@ -172,11 +172,17 @@ fn update_genesis_rs(gen: &core::core::Block) { )); replacements.push(( "prev_root".to_string(), - format!("Hash::from_hex(\"{}\").unwrap()", gen.header.prev_root.to_hex()), + 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()), + format!( + "Hash::from_hex(\"{}\").unwrap()", + gen.header.output_root.to_hex() + ), )); replacements.push(( "range_proof_root".to_string(), @@ -187,7 +193,10 @@ fn update_genesis_rs(gen: &core::core::Block) { )); replacements.push(( "kernel_root".to_string(), - format!("Hash::from_hex(\"{}\").unwrap()", gen.header.kernel_root.to_hex()), + format!( + "Hash::from_hex(\"{}\").unwrap()", + gen.header.kernel_root.to_hex() + ), )); replacements.push(( "total_kernel_offset".to_string(), From 194235a5a78ddf4777544ec5f3e53d2c9f6cee27 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Fri, 14 Dec 2018 21:48:08 +0000 Subject: [PATCH 11/27] Fixes to nonce handling in genesis mining --- etc/gen_gen/src/bin/gen_gen.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index 9f7fb982e..c7fe4f3c9 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -38,7 +38,7 @@ 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 PLUGIN_PATH: &str = "./cuckaroo_mean_cuda_29.cuckooplugin"; fn main() { if !path::Path::new(GENESIS_RS_PATH).exists() { @@ -87,14 +87,17 @@ fn main() { // mine a Cuckaroo29 block core::global::set_mining_mode(core::global::ChainTypes::Mainnet); let plugin_lib = cuckoo::PluginLibrary::new(PLUGIN_PATH).unwrap(); - let solver_ctx = plugin_lib.create_solver_ctx(&mut plugin_lib.get_default_params()); + 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(); - plugin_lib.run_solver( + gen.header.pow.nonce = nonce; + let _ = plugin_lib.run_solver( solver_ctx, gen.header.pre_pow(), nonce, @@ -115,8 +118,7 @@ fn main() { nonce += 1; } - // set the PoW solution and make sure the block is mostly valid - gen.header.pow.nonce = solver_sols.sols[0].nonce as u64; + // 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); From a71af7adae2af755689e34aea3353b42c9cd0584 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Fri, 14 Dec 2018 22:12:54 +0000 Subject: [PATCH 12/27] Also produce full block hashes --- core/src/genesis.rs | 4 +++- etc/gen_gen/src/bin/gen_gen.rs | 5 ++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 27f167949..73d2661cb 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -187,11 +187,13 @@ pub fn genesis_main() -> core::Block { mod test { use super::*; - // TODO update the hash once genesis is set + // TODO hardcode the hashes once genesis is set #[test] fn mainnet_genesis_hash() { let gen_hash = genesis_main().hash(); println!("mainnet genesis hash: {}", gen_hash.to_hex()); + let gen_bin = core::ser::ser_vec(&genesis_main()).unwrap(); + println!("mainnet genesis full hash: {}\n", gen_bin.hash().to_hex()); //assert_eq!(gene_hash.to_hex, ""); } } diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index c7fe4f3c9..037e0b3e7 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -30,6 +30,7 @@ use grin_miner_plugin as plugin; use grin_store as store; use grin_util as util; +use grin_core::core::hash::Hashed; use grin_core::core::verifier_cache::LruVerifierCache; use grin_keychain::{BlindingFactor, ExtKeychain, Keychain}; @@ -129,7 +130,9 @@ fn main() { ) .unwrap(); - println!("Final genesis hash: {}", gen.hash().to_hex()); + 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"); From 052981d596280698bd363f784246e29e7250527c Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Fri, 14 Dec 2018 22:13:05 +0000 Subject: [PATCH 13/27] rustfmt --- core/src/genesis.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 73d2661cb..97048a534 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -23,9 +23,9 @@ use crate::core; use crate::global; use crate::pow::{Difficulty, Proof, ProofOfWork}; use crate::util; -use crate::util::secp::Signature; use crate::util::secp::constants::SINGLE_BULLET_PROOF_SIZE; use crate::util::secp::pedersen::{Commitment, RangeProof}; +use crate::util::secp::Signature; use crate::core::hash::Hash; use crate::keychain::BlindingFactor; @@ -178,7 +178,7 @@ pub fn genesis_main() -> core::Block { proof: RangeProof { plen: SINGLE_BULLET_PROOF_SIZE, proof: [0; SINGLE_BULLET_PROOF_SIZE], // REPLACE - } + }, }; gen.with_reward(output, kernel) } From cb0d09c4926cd05747d40273e4294a377c78c32a Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Fri, 14 Dec 2018 22:35:59 +0000 Subject: [PATCH 14/27] Fix genesis hash test --- core/src/genesis.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 97048a534..87e196e2f 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -186,13 +186,15 @@ pub fn genesis_main() -> core::Block { #[cfg(test)] mod test { use super::*; + use crate::ser; + use crate::core::hash::Hashed; // TODO hardcode the hashes once genesis is set #[test] fn mainnet_genesis_hash() { let gen_hash = genesis_main().hash(); println!("mainnet genesis hash: {}", gen_hash.to_hex()); - let gen_bin = core::ser::ser_vec(&genesis_main()).unwrap(); + let gen_bin = ser::ser_vec(&genesis_main()).unwrap(); println!("mainnet genesis full hash: {}\n", gen_bin.hash().to_hex()); //assert_eq!(gene_hash.to_hex, ""); } From 75d2c1cc5690a5a44d8194f48f72ea078922b9d0 Mon Sep 17 00:00:00 2001 From: jaspervdm Date: Tue, 18 Dec 2018 12:51:44 +0100 Subject: [PATCH 15/27] Switch commitments (#2157) --- config/src/comments.rs | 7 +++++ core/src/libtx/aggsig.rs | 9 +++--- core/src/libtx/build.rs | 4 +-- core/src/libtx/proof.rs | 6 ++-- core/src/libtx/reward.rs | 2 +- keychain/src/keychain.rs | 51 +++++++++++++++++++++----------- keychain/src/types.rs | 34 +++++++++++++++------ servers/src/mining/mine_block.rs | 2 +- wallet/src/lmdb_wallet.rs | 3 +- wallet/src/types.rs | 11 ++++--- wallet/tests/libwallet.rs | 20 ++++++++----- 11 files changed, 98 insertions(+), 51 deletions(-) diff --git a/config/src/comments.rs b/config/src/comments.rs index 305dff9ec..b8a62bb46 100644 --- a/config/src/comments.rs +++ b/config/src/comments.rs @@ -403,6 +403,13 @@ fn comments() -> HashMap { "dark_background_color_scheme".to_string(), " #Whether to use the black background color scheme for command line +" + .to_string(), + ); + retval.insert( + "use_switch_commitments".to_string(), + " +#Whether to use switch commitments for this wallet " .to_string(), ); diff --git a/core/src/libtx/aggsig.rs b/core/src/libtx/aggsig.rs index 6815e8348..50e213710 100644 --- a/core/src/libtx/aggsig.rs +++ b/core/src/libtx/aggsig.rs @@ -251,24 +251,25 @@ pub fn verify_partial_sig( /// let msg = kernel_sig_msg(0, height, KernelFeatures::DEFAULT_KERNEL).unwrap(); /// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap(); /// let pubkey = excess.to_pubkey(&secp).unwrap(); -/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, &key_id, Some(&pubkey)).unwrap(); +/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, Some(&pubkey)).unwrap(); /// ``` pub fn sign_from_key_id( secp: &Secp256k1, k: &K, msg: &Message, + value: u64, key_id: &Identifier, blind_sum: Option<&PublicKey>, ) -> Result where K: Keychain, { - let skey = k.derive_key(key_id)?; + let skey = k.derive_key(value, key_id)?; let sig = aggsig::sign_single( secp, &msg, - &skey.secret_key, + &skey, None, None, None, @@ -324,7 +325,7 @@ where /// let msg = kernel_sig_msg(0, height, KernelFeatures::DEFAULT_KERNEL).unwrap(); /// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap(); /// let pubkey = excess.to_pubkey(&secp).unwrap(); -/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, &key_id, Some(&pubkey)).unwrap(); +/// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, Some(&pubkey)).unwrap(); /// /// // Verify the signature from the excess commit /// let sig_verifies = diff --git a/core/src/libtx/build.rs b/core/src/libtx/build.rs index 267010d85..d4e75d710 100644 --- a/core/src/libtx/build.rs +++ b/core/src/libtx/build.rs @@ -54,7 +54,7 @@ where move |build, (tx, kern, sum)| -> (Transaction, TxKernel, BlindSum) { let commit = build.keychain.commit(value, &key_id).unwrap(); let input = Input::new(features, commit); - (tx.with_input(input), kern, sum.sub_key_id(key_id.to_path())) + (tx.with_input(input), kern, sum.sub_key_id(key_id.to_value_path(value))) }, ) } @@ -102,7 +102,7 @@ where proof: rproof, }), kern, - sum.add_key_id(key_id.to_path()), + sum.add_key_id(key_id.to_value_path(value)), ) }, ) diff --git a/core/src/libtx/proof.rs b/core/src/libtx/proof.rs index 28142607e..aa32f4983 100644 --- a/core/src/libtx/proof.rs +++ b/core/src/libtx/proof.rs @@ -26,7 +26,7 @@ where K: Keychain, { // hash(commit|wallet root secret key (m)) as nonce - let root_key = k.derive_key(&K::root_key_id())?.secret_key; + let root_key = k.derive_key(0, &K::root_key_id())?; let res = blake2::blake2b::blake2b(32, &commit.0, &root_key.0[..]); let res = res.as_bytes(); let mut ret_val = [0; 32]; @@ -53,11 +53,11 @@ where K: Keychain, { let commit = k.commit(amount, key_id)?; - let skey = k.derive_key(key_id)?; + let skey = k.derive_key(amount, key_id)?; let nonce = create_nonce(k, &commit)?; let message = ProofMessage::from_bytes(&key_id.serialize_path()); Ok(k.secp() - .bullet_proof(amount, skey.secret_key, nonce, extra_data, Some(message))) + .bullet_proof(amount, skey, nonce, extra_data, Some(message))) } /// Verify a proof diff --git a/core/src/libtx/reward.rs b/core/src/libtx/reward.rs index 094696abb..e114e4272 100644 --- a/core/src/libtx/reward.rs +++ b/core/src/libtx/reward.rs @@ -59,7 +59,7 @@ where // This output will not be spendable earlier than lock_height (and we sign this // here). let msg = kernel_sig_msg(0, height, KernelFeatures::COINBASE_KERNEL)?; - let sig = aggsig::sign_from_key_id(&secp, keychain, &msg, &key_id, Some(&pubkey))?; + let sig = aggsig::sign_from_key_id(&secp, keychain, &msg, value, &key_id, Some(&pubkey))?; let proof = TxKernel { features: KernelFeatures::COINBASE_KERNEL, diff --git a/keychain/src/keychain.rs b/keychain/src/keychain.rs index c5ea067e9..a99ef88d7 100644 --- a/keychain/src/keychain.rs +++ b/keychain/src/keychain.rs @@ -29,16 +29,18 @@ use crate::util::secp::{self, Message, Secp256k1, Signature}; pub struct ExtKeychain { secp: Secp256k1, master: ExtendedPrivKey, + use_switch_commitments: Option } impl Keychain for ExtKeychain { - fn from_seed(seed: &[u8]) -> Result { + fn from_seed(seed: &[u8], use_switch_commitments: bool) -> Result { let mut h = BIP32GrinHasher::new(); let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit); let master = ExtendedPrivKey::new_master(&secp, &mut h, seed)?; let keychain = ExtKeychain { secp: secp, master: master, + use_switch_commitments: Some(use_switch_commitments) }; Ok(keychain) } @@ -49,15 +51,16 @@ impl Keychain for ExtKeychain { let keychain = ExtKeychain { secp: secp, master: master, + use_switch_commitments: None }; Ok(keychain) } /// For testing - probably not a good idea to use outside of tests. - fn from_random_seed() -> Result { + fn from_random_seed(use_switch_commitments: bool) -> Result { let seed: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect(); let seed = blake2::blake2b::blake2b(32, &[], seed.as_bytes()); - ExtKeychain::from_seed(seed.as_bytes()) + ExtKeychain::from_seed(seed.as_bytes(), use_switch_commitments) } fn root_key_id() -> Identifier { @@ -68,19 +71,27 @@ impl Keychain for ExtKeychain { ExtKeychainPath::new(depth, d1, d2, d3, d4).to_identifier() } - fn derive_key(&self, id: &Identifier) -> Result { + fn derive_key(&self, amount: u64, id: &Identifier) -> Result { let mut h = BIP32GrinHasher::new(); let p = id.to_path(); - let mut sk = self.master; + let mut ext_key = self.master; for i in 0..p.depth { - sk = sk.ckd_priv(&self.secp, &mut h, p.path[i as usize])?; + ext_key = ext_key.ckd_priv(&self.secp, &mut h, p.path[i as usize])?; + } + + // Switch commitments have to be explicitly turned on or off + let use_switch = self.use_switch_commitments.ok_or(Error::SwitchCommitment)?; + if use_switch { + Ok(self.secp.blind_switch(amount, ext_key.secret_key)?) + } + else { + Ok(ext_key.secret_key) } - Ok(sk) } fn commit(&self, amount: u64, id: &Identifier) -> Result { - let key = self.derive_key(id)?; - let commit = self.secp.commit(amount, key.secret_key)?; + let key = self.derive_key(amount, id)?; + let commit = self.secp.commit(amount, key)?; Ok(commit) } @@ -89,9 +100,9 @@ impl Keychain for ExtKeychain { .positive_key_ids .iter() .filter_map(|k| { - let res = self.derive_key(&Identifier::from_path(&k)); + let res = self.derive_key(k.value, &Identifier::from_path(&k.ext_keychain_path)); if let Ok(s) = res { - Some(s.secret_key) + Some(s) } else { None } @@ -102,9 +113,9 @@ impl Keychain for ExtKeychain { .negative_key_ids .iter() .filter_map(|k| { - let res = self.derive_key(&Identifier::from_path(&k)); + let res = self.derive_key(k.value, &Identifier::from_path(&k.ext_keychain_path)); if let Ok(s) = res { - Some(s.secret_key) + Some(s) } else { None } @@ -131,9 +142,9 @@ impl Keychain for ExtKeychain { Ok(BlindingFactor::from_secret_key(sum)) } - fn sign(&self, msg: &Message, id: &Identifier) -> Result { - let skey = self.derive_key(id)?; - let sig = self.secp.sign(msg, &skey.secret_key)?; + fn sign(&self, msg: &Message, amount: u64, id: &Identifier) -> Result { + let skey = self.derive_key(amount, id)?; + let sig = self.secp.sign(msg, &skey)?; Ok(sig) } @@ -150,6 +161,10 @@ impl Keychain for ExtKeychain { fn secp(&self) -> &Secp256k1 { &self.secp } + + fn use_switch_commitments(&self) -> Option { + self.use_switch_commitments + } } #[cfg(test)] @@ -162,6 +177,7 @@ mod test { #[test] fn test_key_derivation() { let keychain = ExtKeychain::from_random_seed().unwrap(); + keychain.set_use_switch_commitments(true); let secp = keychain.secp(); let path = ExtKeychainPath::new(1, 1, 0, 0, 0); @@ -175,7 +191,7 @@ mod test { let commit = keychain.commit(0, &key_id).unwrap(); // now check we can use our key to verify a signature from this zero commitment - let sig = keychain.sign(&msg, &key_id).unwrap(); + let sig = keychain.sign(&msg, 0, &key_id).unwrap(); secp.verify_from_commit(&msg, &sig, &commit).unwrap(); } @@ -186,6 +202,7 @@ mod test { #[test] fn secret_key_addition() { let keychain = ExtKeychain::from_random_seed().unwrap(); + keychain.set_use_switch_commitments(false); let skey1 = SecretKey::from_slice( &keychain.secp, diff --git a/keychain/src/types.rs b/keychain/src/types.rs index d23fbc409..5081e063d 100644 --- a/keychain/src/types.rs +++ b/keychain/src/types.rs @@ -23,7 +23,7 @@ use std::ops::Add; use std::{error, fmt}; use crate::blake2::blake2b::blake2b; -use crate::extkey_bip32::{self, ChildNumber, ExtendedPrivKey}; +use crate::extkey_bip32::{self, ChildNumber}; use serde::{de, ser}; //TODO: Convert errors to use ErrorKind use crate::util; @@ -44,6 +44,7 @@ pub enum Error { KeyDerivation(extkey_bip32::Error), Transaction(String), RangeProof(String), + SwitchCommitment } impl From for Error { @@ -126,6 +127,13 @@ impl Identifier { ExtKeychainPath::from_identifier(&self) } + pub fn to_value_path(&self, value: u64) -> ValueExtKeychainPath { + ValueExtKeychainPath { + value, + ext_keychain_path: self.to_path() + } + } + /// output the path itself, for insertion into bulletproof /// recovery processes can grind through possiblities to find the /// correct length if required @@ -327,8 +335,8 @@ pub struct SplitBlindingFactor { /// factor as well as the "sign" with which they should be combined. #[derive(Clone, Debug, PartialEq)] pub struct BlindSum { - pub positive_key_ids: Vec, - pub negative_key_ids: Vec, + pub positive_key_ids: Vec, + pub negative_key_ids: Vec, pub positive_blinding_factors: Vec, pub negative_blinding_factors: Vec, } @@ -344,12 +352,12 @@ impl BlindSum { } } - pub fn add_key_id(mut self, path: ExtKeychainPath) -> BlindSum { + pub fn add_key_id(mut self, path: ValueExtKeychainPath) -> BlindSum { self.positive_key_ids.push(path); self } - pub fn sub_key_id(mut self, path: ExtKeychainPath) -> BlindSum { + pub fn sub_key_id(mut self, path: ValueExtKeychainPath) -> BlindSum { self.negative_key_ids.push(path); self } @@ -430,18 +438,26 @@ impl ExtKeychainPath { } } +/// Wrapper for amount + path +#[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize)] +pub struct ValueExtKeychainPath { + pub value: u64, + pub ext_keychain_path: ExtKeychainPath +} + pub trait Keychain: Sync + Send + Clone { - fn from_seed(seed: &[u8]) -> Result; + fn from_seed(seed: &[u8], use_switch_commitments: bool) -> Result; fn from_mnemonic(word_list: &str, extension_word: &str) -> Result; - fn from_random_seed() -> Result; + fn from_random_seed(use_switch_commitments: bool) -> Result; fn root_key_id() -> Identifier; fn derive_key_id(depth: u8, d1: u32, d2: u32, d3: u32, d4: u32) -> Identifier; - fn derive_key(&self, id: &Identifier) -> Result; + fn derive_key(&self, amount: u64, id: &Identifier) -> Result; fn commit(&self, amount: u64, id: &Identifier) -> Result; fn blind_sum(&self, blind_sum: &BlindSum) -> Result; - fn sign(&self, msg: &Message, id: &Identifier) -> Result; + fn sign(&self, msg: &Message, amount: u64, id: &Identifier) -> Result; fn sign_with_blinding(&self, _: &Message, _: &BlindingFactor) -> Result; fn secp(&self) -> &Secp256k1; + fn use_switch_commitments(&self) -> Option; } #[cfg(test)] diff --git a/servers/src/mining/mine_block.rs b/servers/src/mining/mine_block.rs index 3c4ccf115..28b84be2b 100644 --- a/servers/src/mining/mine_block.rs +++ b/servers/src/mining/mine_block.rs @@ -170,7 +170,7 @@ fn build_block( /// fn burn_reward(block_fees: BlockFees) -> Result<(core::Output, core::TxKernel, BlockFees), Error> { warn!("Burning block fees: {:?}", block_fees); - let keychain = ExtKeychain::from_random_seed().unwrap(); + let keychain = ExtKeychain::from_random_seed(true).unwrap(); let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); let (out, kernel) = crate::core::libtx::reward::output(&keychain, &key_id, block_fees.fees, block_fees.height) diff --git a/wallet/src/lmdb_wallet.rs b/wallet/src/lmdb_wallet.rs index acadf3651..99ad35bf9 100644 --- a/wallet/src/lmdb_wallet.rs +++ b/wallet/src/lmdb_wallet.rs @@ -140,8 +140,7 @@ where fn open_with_credentials(&mut self) -> Result<(), Error> { let wallet_seed = WalletSeed::from_file(&self.config, &self.passphrase) .context(ErrorKind::CallbackImpl("Error opening wallet"))?; - let keychain = wallet_seed.derive_keychain(); - self.keychain = Some(keychain.context(ErrorKind::CallbackImpl("Error deriving keychain"))?); + self.keychain = Some(wallet_seed.derive_keychain(self.config.use_switch_commitments).context(ErrorKind::CallbackImpl("Error deriving keychain"))?); Ok(()) } diff --git a/wallet/src/types.rs b/wallet/src/types.rs index 01678b308..2055ea7b0 100644 --- a/wallet/src/types.rs +++ b/wallet/src/types.rs @@ -50,13 +50,15 @@ pub struct WalletConfig { pub check_node_api_http_addr: String, // The directory in which wallet files are stored pub data_file_dir: String, - /// TLS ceritificate file + /// TLS certificate file pub tls_certificate_file: Option, - /// TLS ceritificate private key file + /// TLS certificate private key file pub tls_certificate_key: Option, /// Whether to use the black background color scheme for command line /// if enabled, wallet command output color will be suitable for black background terminal pub dark_background_color_scheme: Option, + /// Whether we want to use switch commitments for this wallet + pub use_switch_commitments: bool } impl Default for WalletConfig { @@ -72,6 +74,7 @@ impl Default for WalletConfig { tls_certificate_file: None, tls_certificate_key: None, dark_background_color_scheme: Some(true), + use_switch_commitments: false // TODO: possibly change to true when we want it on by default } } } @@ -121,8 +124,8 @@ impl WalletSeed { seed.as_bytes().to_vec() } - pub fn derive_keychain(&self) -> Result { - let result = K::from_seed(&self.0)?; + pub fn derive_keychain(&self, use_switch_commitments: bool) -> Result { + let result = K::from_seed(&self.0, use_switch_commitments)?; Ok(result) } diff --git a/wallet/tests/libwallet.rs b/wallet/tests/libwallet.rs index 0fb73e6f1..fcb942f21 100644 --- a/wallet/tests/libwallet.rs +++ b/wallet/tests/libwallet.rs @@ -32,14 +32,16 @@ fn kernel_sig_msg() -> secp::Message { #[test] fn aggsig_sender_receiver_interaction() { let sender_keychain = ExtKeychain::from_random_seed().unwrap(); + sender_keychain.set_use_switch_commitments(false); let receiver_keychain = ExtKeychain::from_random_seed().unwrap(); + receiver_keychain.set_use_switch_commitments(false); // Calculate the kernel excess here for convenience. // Normally this would happen during transaction building. let kernel_excess = { let id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let skey1 = sender_keychain.derive_key(&id1).unwrap().secret_key; - let skey2 = receiver_keychain.derive_key(&id1).unwrap().secret_key; + let skey1 = sender_keychain.derive_key(0, &id1).unwrap().secret_key; + let skey2 = receiver_keychain.derive_key(0, &id1).unwrap().secret_key; let keychain = ExtKeychain::from_random_seed().unwrap(); let blinding_factor = keychain @@ -62,7 +64,7 @@ fn aggsig_sender_receiver_interaction() { let (sender_pub_excess, _sender_pub_nonce) = { let keychain = sender_keychain.clone(); let id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let skey = keychain.derive_key(&id1).unwrap().secret_key; + let skey = keychain.derive_key(0, &id1).unwrap().secret_key; // dealing with an input here so we need to negate the blinding_factor // rather than use it as is @@ -85,7 +87,7 @@ fn aggsig_sender_receiver_interaction() { let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); // let blind = blind_sum.secret_key(&keychain.secp())?; - let blind = keychain.derive_key(&key_id).unwrap().secret_key; + let blind = keychain.derive_key(0, &key_id).unwrap().secret_key; rx_cx = Context::new(&keychain.secp(), blind); let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp()); @@ -236,7 +238,9 @@ fn aggsig_sender_receiver_interaction() { #[test] fn aggsig_sender_receiver_interaction_offset() { let sender_keychain = ExtKeychain::from_random_seed().unwrap(); + sender_keychain.set_use_switch_commitments(false); let receiver_keychain = ExtKeychain::from_random_seed().unwrap(); + receiver_keychain.set_use_switch_commitments(false); // This is the kernel offset that we use to split the key // Summing these at the block level prevents the @@ -247,8 +251,8 @@ fn aggsig_sender_receiver_interaction_offset() { // Normally this would happen during transaction building. let kernel_excess = { let id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let skey1 = sender_keychain.derive_key(&id1).unwrap().secret_key; - let skey2 = receiver_keychain.derive_key(&id1).unwrap().secret_key; + let skey1 = sender_keychain.derive_key(0, &id1).unwrap().secret_key; + let skey2 = receiver_keychain.derive_key(0, &id1).unwrap().secret_key; let keychain = ExtKeychain::from_random_seed().unwrap(); let blinding_factor = keychain @@ -274,7 +278,7 @@ fn aggsig_sender_receiver_interaction_offset() { let (sender_pub_excess, _sender_pub_nonce) = { let keychain = sender_keychain.clone(); let id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let skey = keychain.derive_key(&id1).unwrap().secret_key; + let skey = keychain.derive_key(0, &id1).unwrap().secret_key; // dealing with an input here so we need to negate the blinding_factor // rather than use it as is @@ -301,7 +305,7 @@ fn aggsig_sender_receiver_interaction_offset() { let keychain = receiver_keychain.clone(); let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let blind = keychain.derive_key(&key_id).unwrap().secret_key; + let blind = keychain.derive_key(0, &key_id).unwrap().secret_key; rx_cx = Context::new(&keychain.secp(), blind); let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp()); From 230fe191e0addc9a159e116f393a8d500c944a42 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Tue, 18 Dec 2018 15:44:55 +0000 Subject: [PATCH 16/27] [Floonet] Use switch commits for all blinding factors (#2178) * move wallet mods back into dirs * move wallet mod files * use switched keys for blinding factor in all cases * rustfmt * test fix * test fix * test fix * rustfmt * re-implement flag to turn off switch commit derivation * rustfmt --- Cargo.lock | 6 ++-- core/src/core/transaction.rs | 4 +-- core/tests/core.rs | 3 +- keychain/src/keychain.rs | 32 ++++++++----------- keychain/src/types.rs | 12 +++---- servers/src/mining/mine_block.rs | 2 +- util/Cargo.toml | 6 ++-- wallet/src/{adapters.rs => adapters/mod.rs} | 0 wallet/src/{libwallet.rs => libwallet/mod.rs} | 0 wallet/src/lmdb_wallet.rs | 6 +++- .../{node_clients.rs => node_clients/mod.rs} | 0 wallet/src/types.rs | 7 ++-- wallet/tests/libwallet.rs | 20 +++++------- 13 files changed, 45 insertions(+), 53 deletions(-) rename wallet/src/{adapters.rs => adapters/mod.rs} (100%) rename wallet/src/{libwallet.rs => libwallet/mod.rs} (100%) rename wallet/src/{node_clients.rs => node_clients/mod.rs} (100%) diff --git a/Cargo.lock b/Cargo.lock index e854c0e52..ff33ab8ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -865,7 +865,7 @@ dependencies = [ [[package]] name = "grin_secp256k1zkp" version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/mimblewimble/rust-secp256k1-zkp?tag=grin_integration_29#a245051ce72524696a787e60ff7a7e2a9551c699" dependencies = [ "arrayvec 0.3.25 (registry+https://github.com/rust-lang/crates.io-index)", "gcc 0.3.55 (registry+https://github.com/rust-lang/crates.io-index)", @@ -935,7 +935,7 @@ dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "grin_secp256k1zkp 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "grin_secp256k1zkp 0.7.2 (git+https://github.com/mimblewimble/rust-secp256k1-zkp?tag=grin_integration_29)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "log4rs 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2984,7 +2984,7 @@ dependencies = [ "checksum generic-array 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ef25c5683767570c2bbd7deba372926a55eaae9982d7726ee2a1050239d45b9d" "checksum git2 0.7.5 (registry+https://github.com/rust-lang/crates.io-index)" = "591f8be1674b421644b6c030969520bc3fa12114d2eb467471982ed3e9584e71" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum grin_secp256k1zkp 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aea95f8b846440f6a9caf0fd4c22c91c124f2a896d69d781f7dc0fa88e33b0ff" +"checksum grin_secp256k1zkp 0.7.2 (git+https://github.com/mimblewimble/rust-secp256k1-zkp?tag=grin_integration_29)" = "" "checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0" "checksum hmac 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "733e1b3ac906631ca01ebb577e9bb0f5e37a454032b9036b5eaea4013ed6f99a" "checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab" diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 10ba740dd..325faec1d 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -1391,7 +1391,7 @@ mod test { let nonce = 0; let short_id = input.short_id(&block_hash, nonce); - assert_eq!(short_id, ShortId::from_hex("df31d96e3cdb").unwrap()); + assert_eq!(short_id, ShortId::from_hex("c4b05f2ba649").unwrap()); // now generate the short_id for a *very* similar output (single feature flag // different) and check it generates a different short_id @@ -1401,6 +1401,6 @@ mod test { }; let short_id = input.short_id(&block_hash, nonce); - assert_eq!(short_id, ShortId::from_hex("784fc5afd5d9").unwrap()); + assert_eq!(short_id, ShortId::from_hex("3f0377c624e9").unwrap()); } } diff --git a/core/tests/core.rs b/core/tests/core.rs index 157b6d48c..acc391d00 100644 --- a/core/tests/core.rs +++ b/core/tests/core.rs @@ -75,7 +75,8 @@ fn tx_double_ser_deser() { #[test] #[should_panic(expected = "Keychain Error")] fn test_zero_commit_fails() { - let keychain = ExtKeychain::from_random_seed().unwrap(); + let mut keychain = ExtKeychain::from_random_seed().unwrap(); + keychain.set_use_switch_commits(false); let key_id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); // blinding should fail as signing with a zero r*G shouldn't work diff --git a/keychain/src/keychain.rs b/keychain/src/keychain.rs index a99ef88d7..cb10895cf 100644 --- a/keychain/src/keychain.rs +++ b/keychain/src/keychain.rs @@ -29,18 +29,18 @@ use crate::util::secp::{self, Message, Secp256k1, Signature}; pub struct ExtKeychain { secp: Secp256k1, master: ExtendedPrivKey, - use_switch_commitments: Option + use_switch_commits: bool, } impl Keychain for ExtKeychain { - fn from_seed(seed: &[u8], use_switch_commitments: bool) -> Result { + fn from_seed(seed: &[u8]) -> Result { let mut h = BIP32GrinHasher::new(); let secp = secp::Secp256k1::with_caps(secp::ContextFlag::Commit); let master = ExtendedPrivKey::new_master(&secp, &mut h, seed)?; let keychain = ExtKeychain { secp: secp, master: master, - use_switch_commitments: Some(use_switch_commitments) + use_switch_commits: true, }; Ok(keychain) } @@ -51,16 +51,16 @@ impl Keychain for ExtKeychain { let keychain = ExtKeychain { secp: secp, master: master, - use_switch_commitments: None + use_switch_commits: true, }; Ok(keychain) } /// For testing - probably not a good idea to use outside of tests. - fn from_random_seed(use_switch_commitments: bool) -> Result { + fn from_random_seed() -> Result { let seed: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect(); let seed = blake2::blake2b::blake2b(32, &[], seed.as_bytes()); - ExtKeychain::from_seed(seed.as_bytes(), use_switch_commitments) + ExtKeychain::from_seed(seed.as_bytes()) } fn root_key_id() -> Identifier { @@ -79,13 +79,9 @@ impl Keychain for ExtKeychain { ext_key = ext_key.ckd_priv(&self.secp, &mut h, p.path[i as usize])?; } - // Switch commitments have to be explicitly turned on or off - let use_switch = self.use_switch_commitments.ok_or(Error::SwitchCommitment)?; - if use_switch { - Ok(self.secp.blind_switch(amount, ext_key.secret_key)?) - } - else { - Ok(ext_key.secret_key) + match self.use_switch_commits { + true => Ok(self.secp.blind_switch(amount, ext_key.secret_key)?), + false => Ok(ext_key.secret_key), } } @@ -158,12 +154,12 @@ impl Keychain for ExtKeychain { Ok(sig) } - fn secp(&self) -> &Secp256k1 { - &self.secp + fn set_use_switch_commits(&mut self, value: bool) { + self.use_switch_commits = value; } - fn use_switch_commitments(&self) -> Option { - self.use_switch_commitments + fn secp(&self) -> &Secp256k1 { + &self.secp } } @@ -177,7 +173,6 @@ mod test { #[test] fn test_key_derivation() { let keychain = ExtKeychain::from_random_seed().unwrap(); - keychain.set_use_switch_commitments(true); let secp = keychain.secp(); let path = ExtKeychainPath::new(1, 1, 0, 0, 0); @@ -202,7 +197,6 @@ mod test { #[test] fn secret_key_addition() { let keychain = ExtKeychain::from_random_seed().unwrap(); - keychain.set_use_switch_commitments(false); let skey1 = SecretKey::from_slice( &keychain.secp, diff --git a/keychain/src/types.rs b/keychain/src/types.rs index 5081e063d..152e7be13 100644 --- a/keychain/src/types.rs +++ b/keychain/src/types.rs @@ -44,7 +44,7 @@ pub enum Error { KeyDerivation(extkey_bip32::Error), Transaction(String), RangeProof(String), - SwitchCommitment + SwitchCommitment, } impl From for Error { @@ -130,7 +130,7 @@ impl Identifier { pub fn to_value_path(&self, value: u64) -> ValueExtKeychainPath { ValueExtKeychainPath { value, - ext_keychain_path: self.to_path() + ext_keychain_path: self.to_path(), } } @@ -442,13 +442,13 @@ impl ExtKeychainPath { #[derive(Copy, Clone, PartialEq, Eq, Debug, Deserialize)] pub struct ValueExtKeychainPath { pub value: u64, - pub ext_keychain_path: ExtKeychainPath + pub ext_keychain_path: ExtKeychainPath, } pub trait Keychain: Sync + Send + Clone { - fn from_seed(seed: &[u8], use_switch_commitments: bool) -> Result; + fn from_seed(seed: &[u8]) -> Result; fn from_mnemonic(word_list: &str, extension_word: &str) -> Result; - fn from_random_seed(use_switch_commitments: bool) -> Result; + fn from_random_seed() -> Result; fn root_key_id() -> Identifier; fn derive_key_id(depth: u8, d1: u32, d2: u32, d3: u32, d4: u32) -> Identifier; fn derive_key(&self, amount: u64, id: &Identifier) -> Result; @@ -456,8 +456,8 @@ pub trait Keychain: Sync + Send + Clone { fn blind_sum(&self, blind_sum: &BlindSum) -> Result; fn sign(&self, msg: &Message, amount: u64, id: &Identifier) -> Result; fn sign_with_blinding(&self, _: &Message, _: &BlindingFactor) -> Result; + fn set_use_switch_commits(&mut self, value: bool); fn secp(&self) -> &Secp256k1; - fn use_switch_commitments(&self) -> Option; } #[cfg(test)] diff --git a/servers/src/mining/mine_block.rs b/servers/src/mining/mine_block.rs index 28b84be2b..3c4ccf115 100644 --- a/servers/src/mining/mine_block.rs +++ b/servers/src/mining/mine_block.rs @@ -170,7 +170,7 @@ fn build_block( /// fn burn_reward(block_fees: BlockFees) -> Result<(core::Output, core::TxKernel, BlockFees), Error> { warn!("Burning block fees: {:?}", block_fees); - let keychain = ExtKeychain::from_random_seed(true).unwrap(); + let keychain = ExtKeychain::from_random_seed().unwrap(); let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); let (out, kernel) = crate::core::libtx::reward::output(&keychain, &key_id, block_fees.fees, block_fees.height) diff --git a/util/Cargo.toml b/util/Cargo.toml index dd6e8f21d..cf2d22ad9 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -24,8 +24,8 @@ zip = "0.4" parking_lot = {version = "0.6"} [dependencies.grin_secp256k1zkp] -#git = "https://github.com/mimblewimble/rust-secp256k1-zkp" -#tag = "grin_integration_28" +git = "https://github.com/mimblewimble/rust-secp256k1-zkp" +tag = "grin_integration_29" #path = "../../rust-secp256k1-zkp" -version = "0.7.1" +#version = "0.7.1" features = ["bullet-proof-sizing"] diff --git a/wallet/src/adapters.rs b/wallet/src/adapters/mod.rs similarity index 100% rename from wallet/src/adapters.rs rename to wallet/src/adapters/mod.rs diff --git a/wallet/src/libwallet.rs b/wallet/src/libwallet/mod.rs similarity index 100% rename from wallet/src/libwallet.rs rename to wallet/src/libwallet/mod.rs diff --git a/wallet/src/lmdb_wallet.rs b/wallet/src/lmdb_wallet.rs index 99ad35bf9..4aa9da97e 100644 --- a/wallet/src/lmdb_wallet.rs +++ b/wallet/src/lmdb_wallet.rs @@ -140,7 +140,11 @@ where fn open_with_credentials(&mut self) -> Result<(), Error> { let wallet_seed = WalletSeed::from_file(&self.config, &self.passphrase) .context(ErrorKind::CallbackImpl("Error opening wallet"))?; - self.keychain = Some(wallet_seed.derive_keychain(self.config.use_switch_commitments).context(ErrorKind::CallbackImpl("Error deriving keychain"))?); + self.keychain = Some( + wallet_seed + .derive_keychain() + .context(ErrorKind::CallbackImpl("Error deriving keychain"))?, + ); Ok(()) } diff --git a/wallet/src/node_clients.rs b/wallet/src/node_clients/mod.rs similarity index 100% rename from wallet/src/node_clients.rs rename to wallet/src/node_clients/mod.rs diff --git a/wallet/src/types.rs b/wallet/src/types.rs index 2055ea7b0..fcdd68f4b 100644 --- a/wallet/src/types.rs +++ b/wallet/src/types.rs @@ -57,8 +57,6 @@ pub struct WalletConfig { /// Whether to use the black background color scheme for command line /// if enabled, wallet command output color will be suitable for black background terminal pub dark_background_color_scheme: Option, - /// Whether we want to use switch commitments for this wallet - pub use_switch_commitments: bool } impl Default for WalletConfig { @@ -74,7 +72,6 @@ impl Default for WalletConfig { tls_certificate_file: None, tls_certificate_key: None, dark_background_color_scheme: Some(true), - use_switch_commitments: false // TODO: possibly change to true when we want it on by default } } } @@ -124,8 +121,8 @@ impl WalletSeed { seed.as_bytes().to_vec() } - pub fn derive_keychain(&self, use_switch_commitments: bool) -> Result { - let result = K::from_seed(&self.0, use_switch_commitments)?; + pub fn derive_keychain(&self) -> Result { + let result = K::from_seed(&self.0)?; Ok(result) } diff --git a/wallet/tests/libwallet.rs b/wallet/tests/libwallet.rs index fcb942f21..04ef3ad46 100644 --- a/wallet/tests/libwallet.rs +++ b/wallet/tests/libwallet.rs @@ -32,16 +32,14 @@ fn kernel_sig_msg() -> secp::Message { #[test] fn aggsig_sender_receiver_interaction() { let sender_keychain = ExtKeychain::from_random_seed().unwrap(); - sender_keychain.set_use_switch_commitments(false); let receiver_keychain = ExtKeychain::from_random_seed().unwrap(); - receiver_keychain.set_use_switch_commitments(false); // Calculate the kernel excess here for convenience. // Normally this would happen during transaction building. let kernel_excess = { let id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let skey1 = sender_keychain.derive_key(0, &id1).unwrap().secret_key; - let skey2 = receiver_keychain.derive_key(0, &id1).unwrap().secret_key; + let skey1 = sender_keychain.derive_key(0, &id1).unwrap(); + let skey2 = receiver_keychain.derive_key(0, &id1).unwrap(); let keychain = ExtKeychain::from_random_seed().unwrap(); let blinding_factor = keychain @@ -64,7 +62,7 @@ fn aggsig_sender_receiver_interaction() { let (sender_pub_excess, _sender_pub_nonce) = { let keychain = sender_keychain.clone(); let id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let skey = keychain.derive_key(0, &id1).unwrap().secret_key; + let skey = keychain.derive_key(0, &id1).unwrap(); // dealing with an input here so we need to negate the blinding_factor // rather than use it as is @@ -87,7 +85,7 @@ fn aggsig_sender_receiver_interaction() { let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); // let blind = blind_sum.secret_key(&keychain.secp())?; - let blind = keychain.derive_key(0, &key_id).unwrap().secret_key; + let blind = keychain.derive_key(0, &key_id).unwrap(); rx_cx = Context::new(&keychain.secp(), blind); let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp()); @@ -238,9 +236,7 @@ fn aggsig_sender_receiver_interaction() { #[test] fn aggsig_sender_receiver_interaction_offset() { let sender_keychain = ExtKeychain::from_random_seed().unwrap(); - sender_keychain.set_use_switch_commitments(false); let receiver_keychain = ExtKeychain::from_random_seed().unwrap(); - receiver_keychain.set_use_switch_commitments(false); // This is the kernel offset that we use to split the key // Summing these at the block level prevents the @@ -251,8 +247,8 @@ fn aggsig_sender_receiver_interaction_offset() { // Normally this would happen during transaction building. let kernel_excess = { let id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let skey1 = sender_keychain.derive_key(0, &id1).unwrap().secret_key; - let skey2 = receiver_keychain.derive_key(0, &id1).unwrap().secret_key; + let skey1 = sender_keychain.derive_key(0, &id1).unwrap(); + let skey2 = receiver_keychain.derive_key(0, &id1).unwrap(); let keychain = ExtKeychain::from_random_seed().unwrap(); let blinding_factor = keychain @@ -278,7 +274,7 @@ fn aggsig_sender_receiver_interaction_offset() { let (sender_pub_excess, _sender_pub_nonce) = { let keychain = sender_keychain.clone(); let id1 = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let skey = keychain.derive_key(0, &id1).unwrap().secret_key; + let skey = keychain.derive_key(0, &id1).unwrap(); // dealing with an input here so we need to negate the blinding_factor // rather than use it as is @@ -305,7 +301,7 @@ fn aggsig_sender_receiver_interaction_offset() { let keychain = receiver_keychain.clone(); let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); - let blind = keychain.derive_key(0, &key_id).unwrap().secret_key; + let blind = keychain.derive_key(0, &key_id).unwrap(); rx_cx = Context::new(&keychain.secp(), blind); let (pub_excess, pub_nonce) = rx_cx.get_public_keys(&keychain.secp()); From aa9da6838bb2b245c5e6e17710bff7990e917adf Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Tue, 18 Dec 2018 16:44:03 +0000 Subject: [PATCH 17/27] rename tx log entry field tx_hex -> stored_tx (#2181) --- wallet/src/display.rs | 2 +- wallet/src/libwallet/internal/selection.rs | 2 +- wallet/src/libwallet/internal/tx.rs | 2 +- wallet/src/libwallet/types.rs | 7 +++---- wallet/src/lmdb_wallet.rs | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/wallet/src/display.rs b/wallet/src/display.rs index f5e24dbae..118118b19 100644 --- a/wallet/src/display.rs +++ b/wallet/src/display.rs @@ -177,7 +177,7 @@ pub fn txs( core::amount_to_hr_string(t.amount_debited - t.amount_credited, true) ) }; - let tx_data = match t.tx_hex { + let tx_data = match t.stored_tx { Some(t) => format!("{}", t), None => "None".to_owned(), }; diff --git a/wallet/src/libwallet/internal/selection.rs b/wallet/src/libwallet/internal/selection.rs index be2160ecb..3f6cda2b9 100644 --- a/wallet/src/libwallet/internal/selection.rs +++ b/wallet/src/libwallet/internal/selection.rs @@ -102,7 +102,7 @@ where let mut t = TxLogEntry::new(parent_key_id.clone(), TxLogEntryType::TxSent, log_id); t.tx_slate_id = Some(slate_id); let filename = format!("{}.grintx", slate_id); - t.tx_hex = Some(filename); + t.stored_tx = Some(filename); t.fee = Some(fee); let mut amount_debited = 0; t.num_inputs = lock_inputs.len(); diff --git a/wallet/src/libwallet/internal/tx.rs b/wallet/src/libwallet/internal/tx.rs index caac3359f..af7e1c906 100644 --- a/wallet/src/libwallet/internal/tx.rs +++ b/wallet/src/libwallet/internal/tx.rs @@ -196,7 +196,7 @@ where return Err(ErrorKind::TransactionDoesntExist(tx_id.to_string()))?; } let tx = tx_vec[0].clone(); - Ok((tx.confirmed, tx.tx_hex)) + Ok((tx.confirmed, tx.stored_tx)) } /// Update the stored transaction (this update needs to happen when the TX is finalised) diff --git a/wallet/src/libwallet/types.rs b/wallet/src/libwallet/types.rs index e49998111..29911a585 100644 --- a/wallet/src/libwallet/types.rs +++ b/wallet/src/libwallet/types.rs @@ -600,9 +600,8 @@ pub struct TxLogEntry { pub amount_debited: u64, /// Fee pub fee: Option, - // TODO: rename this to 'stored_tx_file' or something for mainnet - /// The transaction json itself, stored for reference or resending - pub tx_hex: Option, + /// Location of the store transaction, (reference or resending) + pub stored_tx: Option, } impl ser::Writeable for TxLogEntry { @@ -634,7 +633,7 @@ impl TxLogEntry { num_inputs: 0, num_outputs: 0, fee: None, - tx_hex: None, + stored_tx: None, } } diff --git a/wallet/src/lmdb_wallet.rs b/wallet/src/lmdb_wallet.rs index 4aa9da97e..49c015f5c 100644 --- a/wallet/src/lmdb_wallet.rs +++ b/wallet/src/lmdb_wallet.rs @@ -262,7 +262,7 @@ where } fn get_stored_tx(&self, entry: &TxLogEntry) -> Result, Error> { - let filename = match entry.tx_hex.clone() { + let filename = match entry.stored_tx.clone() { Some(f) => f, None => return Ok(None), }; From f43df5f601ed7a7b6f7fef4dd7a3a4e16c6fab26 Mon Sep 17 00:00:00 2001 From: John Tromp Date: Tue, 18 Dec 2018 19:26:34 +0100 Subject: [PATCH 18/27] [Floonet] add feature for height locked kernels (#2168) * add feature for height locked kernels * add function to compute kernel features appropriate for lock height, and use it * only sign kernel-features relevant fields; refactor Features * simplify invalid kernel logic * remove unused height arg to reward::output and run some rustfmt * replace nested if/else by match --- api/src/handlers/utils.rs | 4 +- api/src/types.rs | 11 +- chain/src/txhashset/utxo_view.rs | 4 +- chain/tests/data_file_integrity.rs | 4 +- chain/tests/mine_simple_chain.rs | 10 +- chain/tests/store_indices.rs | 2 +- chain/tests/test_coinbase_maturity.rs | 13 +-- core/src/core/block.rs | 6 +- core/src/core/compact_block.rs | 6 +- core/src/core/transaction.rs | 135 ++++++++++++++++++----- core/src/libtx/aggsig.rs | 8 +- core/src/libtx/build.rs | 6 +- core/src/libtx/reward.rs | 19 ++-- core/src/libtx/slate.rs | 9 +- core/tests/block.rs | 26 ++--- core/tests/common.rs | 2 +- core/tests/core.rs | 2 +- core/tests/transaction.rs | 4 +- core/tests/verifier_cache.rs | 2 +- pool/tests/block_building.rs | 2 +- pool/tests/block_reconciliation.rs | 6 +- pool/tests/transaction_pool.rs | 2 +- servers/src/mining/mine_block.rs | 2 +- wallet/src/libwallet/internal/updater.rs | 8 +- wallet/src/test_framework/mod.rs | 4 +- wallet/tests/libwallet.rs | 2 +- 26 files changed, 175 insertions(+), 124 deletions(-) diff --git a/api/src/handlers/utils.rs b/api/src/handlers/utils.rs index 2e2bc01e3..3b5c9d0df 100644 --- a/api/src/handlers/utils.rs +++ b/api/src/handlers/utils.rs @@ -44,8 +44,8 @@ pub fn get_output( // For now we can just try both (but this probably needs to be part of the api // params) let outputs = [ - OutputIdentifier::new(OutputFeatures::DEFAULT_OUTPUT, &commit), - OutputIdentifier::new(OutputFeatures::COINBASE_OUTPUT, &commit), + OutputIdentifier::new(OutputFeatures::PLAIN, &commit), + OutputIdentifier::new(OutputFeatures::COINBASE, &commit), ]; for x in outputs.iter() { diff --git a/api/src/types.rs b/api/src/types.rs index 2024d07fb..bb2469f35 100644 --- a/api/src/types.rs +++ b/api/src/types.rs @@ -251,10 +251,7 @@ impl OutputPrintable { block_header: Option<&core::BlockHeader>, include_proof: bool, ) -> OutputPrintable { - let output_type = if output - .features - .contains(core::transaction::OutputFeatures::COINBASE_OUTPUT) - { + let output_type = if output.is_coinbase() { OutputType::Coinbase } else { OutputType::Transaction @@ -278,11 +275,7 @@ impl OutputPrintable { // We require the rewind() to be stable even after the PMMR is pruned and // compacted so we can still recreate the necessary proof. let mut merkle_proof = None; - if output - .features - .contains(core::transaction::OutputFeatures::COINBASE_OUTPUT) - && !spent && block_header.is_some() - { + if output.is_coinbase() && !spent && block_header.is_some() { merkle_proof = chain.get_merkle_proof(&out_id, &block_header.unwrap()).ok() }; diff --git a/chain/src/txhashset/utxo_view.rs b/chain/src/txhashset/utxo_view.rs index 586ea108e..1b648ba72 100644 --- a/chain/src/txhashset/utxo_view.rs +++ b/chain/src/txhashset/utxo_view.rs @@ -16,7 +16,7 @@ use crate::core::core::hash::Hash; use crate::core::core::pmmr::{self, ReadonlyPMMR}; -use crate::core::core::{Block, BlockHeader, Input, Output, OutputFeatures, Transaction}; +use crate::core::core::{Block, BlockHeader, Input, Output, Transaction}; use crate::core::global; use crate::core::ser::PMMRIndexHashable; use crate::error::{Error, ErrorKind}; @@ -105,7 +105,7 @@ impl<'a> UTXOView<'a> { // outputs we are attempting to spend. let pos = inputs .iter() - .filter(|x| x.features.contains(OutputFeatures::COINBASE_OUTPUT)) + .filter(|x| x.is_coinbase()) .filter_map(|x| self.batch.get_output_pos(&x.commitment()).ok()) .max() .unwrap_or(0); diff --git a/chain/tests/data_file_integrity.rs b/chain/tests/data_file_integrity.rs index fdd10273c..d3cc0b8ad 100644 --- a/chain/tests/data_file_integrity.rs +++ b/chain/tests/data_file_integrity.rs @@ -83,7 +83,7 @@ fn data_files() { let prev = chain.head_header().unwrap(); let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter()); let pk = ExtKeychainPath::new(1, n as u32, 0, 0, 0).to_identifier(); - let reward = libtx::reward::output(&keychain, &pk, 0, prev.height).unwrap(); + let reward = libtx::reward::output(&keychain, &pk, 0).unwrap(); let mut b = core::core::Block::new(&prev, vec![], next_header_info.clone().difficulty, reward) .unwrap(); @@ -159,7 +159,7 @@ fn _prepare_block_nosum( let key_id = ExtKeychainPath::new(1, diff as u32, 0, 0, 0).to_identifier(); let fees = txs.iter().map(|tx| tx.fee()).sum(); - let reward = libtx::reward::output(kc, &key_id, fees, prev.height).unwrap(); + let reward = libtx::reward::output(kc, &key_id, fees).unwrap(); let mut b = match core::core::Block::new( prev, txs.into_iter().cloned().collect(), diff --git a/chain/tests/mine_simple_chain.rs b/chain/tests/mine_simple_chain.rs index 9ab310bf5..adcd930c3 100644 --- a/chain/tests/mine_simple_chain.rs +++ b/chain/tests/mine_simple_chain.rs @@ -70,7 +70,7 @@ fn mine_genesis_reward_chain() { let mut genesis = genesis::genesis_dev(); let keychain = keychain::ExtKeychain::from_random_seed().unwrap(); let key_id = keychain::ExtKeychain::derive_key_id(0, 1, 0, 0, 0); - let reward = reward::output(&keychain, &key_id, 0, 0).unwrap(); + let reward = reward::output(&keychain, &key_id, 0).unwrap(); genesis = genesis.with_reward(reward.0, reward.1); { @@ -103,7 +103,7 @@ where let prev = chain.head_header().unwrap(); let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter()); let pk = ExtKeychainPath::new(1, n as u32, 0, 0, 0).to_identifier(); - let reward = libtx::reward::output(keychain, &pk, 0, prev.height).unwrap(); + let reward = libtx::reward::output(keychain, &pk, 0).unwrap(); let mut b = core::core::Block::new(&prev, vec![], next_header_info.clone().difficulty, reward) .unwrap(); @@ -283,7 +283,7 @@ fn spend_in_fork_and_compact() { // so we can spend the coinbase later let b = prepare_block(&kc, &fork_head, &chain, 2); let out_id = OutputIdentifier::from_output(&b.outputs()[0]); - assert!(out_id.features.contains(OutputFeatures::COINBASE_OUTPUT)); + assert!(out_id.features.is_coinbase()); fork_head = b.header.clone(); chain .process_block(b.clone(), chain::Options::SKIP_POW) @@ -411,7 +411,7 @@ fn output_header_mappings() { let prev = chain.head_header().unwrap(); let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter()); let pk = ExtKeychainPath::new(1, n as u32, 0, 0, 0).to_identifier(); - let reward = libtx::reward::output(&keychain, &pk, 0, prev.height).unwrap(); + let reward = libtx::reward::output(&keychain, &pk, 0).unwrap(); reward_outputs.push(reward.0.clone()); let mut b = core::core::Block::new(&prev, vec![], next_header_info.clone().difficulty, reward) @@ -511,7 +511,7 @@ where let key_id = ExtKeychainPath::new(1, diff as u32, 0, 0, 0).to_identifier(); let fees = txs.iter().map(|tx| tx.fee()).sum(); - let reward = libtx::reward::output(kc, &key_id, fees, prev.height).unwrap(); + let reward = libtx::reward::output(kc, &key_id, fees).unwrap(); let mut b = match core::core::Block::new( prev, txs.into_iter().cloned().collect(), diff --git a/chain/tests/store_indices.rs b/chain/tests/store_indices.rs index 9ef7ae7a1..c5b4f04bb 100644 --- a/chain/tests/store_indices.rs +++ b/chain/tests/store_indices.rs @@ -62,7 +62,7 @@ fn test_various_store_indices() { setup_chain(&genesis, chain_store.clone()).unwrap(); - let reward = libtx::reward::output(&keychain, &key_id, 0, 1).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id, 0).unwrap(); let block = Block::new(&genesis.header, vec![], Difficulty::min(), reward).unwrap(); let block_hash = block.hash(); diff --git a/chain/tests/test_coinbase_maturity.rs b/chain/tests/test_coinbase_maturity.rs index 14d948a49..939797baf 100644 --- a/chain/tests/test_coinbase_maturity.rs +++ b/chain/tests/test_coinbase_maturity.rs @@ -14,7 +14,6 @@ use self::chain::types::NoopAdapter; use self::chain::ErrorKind; -use self::core::core::transaction; use self::core::core::verifier_cache::LruVerifierCache; use self::core::global::{self, ChainTypes}; use self::core::libtx::{self, build}; @@ -68,7 +67,7 @@ fn test_coinbase_maturity() { let key_id4 = ExtKeychainPath::new(1, 4, 0, 0, 0).to_identifier(); let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter()); - let reward = libtx::reward::output(&keychain, &key_id1, 0, prev.height).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id1, 0).unwrap(); let mut block = core::core::Block::new(&prev, vec![], Difficulty::min(), reward).unwrap(); block.header.timestamp = prev.timestamp + Duration::seconds(60); block.header.pow.secondary_scaling = next_header_info.secondary_scaling; @@ -85,9 +84,7 @@ fn test_coinbase_maturity() { assert_eq!(block.outputs().len(), 1); let coinbase_output = block.outputs()[0]; - assert!(coinbase_output - .features - .contains(transaction::OutputFeatures::COINBASE_OUTPUT)); + assert!(coinbase_output.is_coinbase()); chain .process_block(block.clone(), chain::Options::MINE) @@ -114,7 +111,7 @@ fn test_coinbase_maturity() { let txs = vec![coinbase_txn.clone()]; let fees = txs.iter().map(|tx| tx.fee()).sum(); - let reward = libtx::reward::output(&keychain, &key_id3, fees, prev.height).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id3, fees).unwrap(); let mut block = core::core::Block::new(&prev, txs, Difficulty::min(), reward).unwrap(); let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter()); block.header.timestamp = prev.timestamp + Duration::seconds(60); @@ -148,7 +145,7 @@ fn test_coinbase_maturity() { let keychain = ExtKeychain::from_random_seed().unwrap(); let pk = ExtKeychainPath::new(1, 1, 0, 0, 0).to_identifier(); - let reward = libtx::reward::output(&keychain, &pk, 0, prev.height).unwrap(); + let reward = libtx::reward::output(&keychain, &pk, 0).unwrap(); let mut block = core::core::Block::new(&prev, vec![], Difficulty::min(), reward).unwrap(); let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter()); block.header.timestamp = prev.timestamp + Duration::seconds(60); @@ -176,7 +173,7 @@ fn test_coinbase_maturity() { let txs = vec![coinbase_txn]; let fees = txs.iter().map(|tx| tx.fee()).sum(); let next_header_info = consensus::next_difficulty(1, chain.difficulty_iter()); - let reward = libtx::reward::output(&keychain, &key_id4, fees, prev.height).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id4, fees).unwrap(); let mut block = core::core::Block::new(&prev, txs, Difficulty::min(), reward).unwrap(); block.header.timestamp = prev.timestamp + Duration::seconds(60); diff --git a/core/src/core/block.rs b/core/src/core/block.rs index abe6c1d7d..bf474d3d8 100644 --- a/core/src/core/block.rs +++ b/core/src/core/block.rs @@ -28,7 +28,7 @@ use crate::core::compact_block::{CompactBlock, CompactBlockBody}; use crate::core::hash::{Hash, Hashed, ZERO_HASH}; use crate::core::verifier_cache::VerifierCache; use crate::core::{ - transaction, Commitment, Input, KernelFeatures, Output, OutputFeatures, Transaction, + transaction, Commitment, Input, Output, Transaction, TransactionBody, TxKernel, }; use crate::global; @@ -663,14 +663,14 @@ impl Block { .body .outputs .iter() - .filter(|out| out.features.contains(OutputFeatures::COINBASE_OUTPUT)) + .filter(|out| out.is_coinbase()) .collect::>(); let cb_kerns = self .body .kernels .iter() - .filter(|kernel| kernel.features.contains(KernelFeatures::COINBASE_KERNEL)) + .filter(|kernel| kernel.is_coinbase()) .collect::>(); { diff --git a/core/src/core/compact_block.rs b/core/src/core/compact_block.rs index 3b7aec424..031728069 100644 --- a/core/src/core/compact_block.rs +++ b/core/src/core/compact_block.rs @@ -19,7 +19,7 @@ use rand::{thread_rng, Rng}; use crate::core::block::{Block, BlockHeader, Error}; use crate::core::hash::Hashed; use crate::core::id::ShortIdentifiable; -use crate::core::{KernelFeatures, Output, OutputFeatures, ShortId, TxKernel}; +use crate::core::{Output, ShortId, TxKernel}; use crate::ser::{self, read_multi, Readable, Reader, VerifySortedAndUnique, Writeable, Writer}; /// Container for full (full) outputs and kernels and kern_ids for a compact block. @@ -168,7 +168,7 @@ impl From for CompactBlock { let out_full = block .outputs() .iter() - .filter(|x| x.features.contains(OutputFeatures::COINBASE_OUTPUT)) + .filter(|x| x.is_coinbase()) .cloned() .collect::>(); @@ -176,7 +176,7 @@ impl From for CompactBlock { let mut kern_ids = vec![]; for k in block.kernels() { - if k.features.contains(KernelFeatures::COINBASE_KERNEL) { + if k.is_coinbase() { kern_full.push(k.clone()); } else { kern_ids.push(k.short_id(&header.hash(), nonce)); diff --git a/core/src/core/transaction.rs b/core/src/core/transaction.rs index 325faec1d..d30ef4b55 100644 --- a/core/src/core/transaction.rs +++ b/core/src/core/transaction.rs @@ -40,10 +40,12 @@ bitflags! { /// Options for a kernel's structure or use #[derive(Serialize, Deserialize)] pub struct KernelFeatures: u8 { - /// No flags - const DEFAULT_KERNEL = 0b00000000; - /// Kernel matching a coinbase output - const COINBASE_KERNEL = 0b00000001; + /// plain kernel has fee, but no lock_height + const PLAIN = 0; + /// coinbase kernel has neither fee nor lock_height (both zero) + const COINBASE = 1; + /// absolute height locked kernel; has fee and lock_height + const HEIGHT_LOCKED = 2; } } @@ -202,7 +204,39 @@ impl PMMRable for TxKernel { } } +impl KernelFeatures { + /// Is this a coinbase kernel? + pub fn is_coinbase(&self) -> bool { + self.contains(KernelFeatures::COINBASE) + } + + /// Is this a plain kernel? + pub fn is_plain(&self) -> bool { + !self.is_coinbase() && !self.is_height_locked() + } + + /// Is this a height locked kernel? + pub fn is_height_locked(&self) -> bool { + self.contains(KernelFeatures::HEIGHT_LOCKED) + } +} + impl TxKernel { + /// Is this a coinbase kernel? + pub fn is_coinbase(&self) -> bool { + self.features.is_coinbase() + } + + /// Is this a plain kernel? + pub fn is_plain(&self) -> bool { + self.features.is_plain() + } + + /// Is this a height locked kernel? + pub fn is_height_locked(&self) -> bool { + self.features.is_height_locked() + } + /// Return the excess commitment for this tx_kernel. pub fn excess(&self) -> Commitment { self.excess @@ -219,6 +253,10 @@ impl TxKernel { /// as a public key and checking the signature verifies with the fee as /// message. pub fn verify(&self) -> Result<(), Error> { + if self.is_coinbase() && self.fee != 0 || !self.is_height_locked() && self.lock_height != 0 + { + return Err(Error::InvalidKernelFeatures); + } let secp = static_secp_instance(); let secp = secp.lock(); let sig = &self.excess_sig; @@ -242,7 +280,7 @@ impl TxKernel { /// Build an empty tx kernel with zero values. pub fn empty() -> TxKernel { TxKernel { - features: KernelFeatures::DEFAULT_KERNEL, + features: KernelFeatures::PLAIN, fee: 0, lock_height: 0, excess: Commitment::from_vec(vec![0; 33]), @@ -258,6 +296,7 @@ impl TxKernel { /// Builds a new tx kernel with the provided lock_height. pub fn with_lock_height(self, lock_height: u64) -> TxKernel { TxKernel { + features: kernel_features(lock_height), lock_height, ..self } @@ -583,25 +622,17 @@ impl TransactionBody { Ok(()) } - // Verify we have no outputs tagged as COINBASE_OUTPUT. + // Verify we have no outputs tagged as COINBASE. fn verify_output_features(&self) -> Result<(), Error> { - if self - .outputs - .iter() - .any(|x| x.features.contains(OutputFeatures::COINBASE_OUTPUT)) - { + if self.outputs.iter().any(|x| x.is_coinbase()) { return Err(Error::InvalidOutputFeatures); } Ok(()) } - // Verify we have no kernels tagged as COINBASE_KERNEL. + // Verify we have no kernels tagged as COINBASE. fn verify_kernel_features(&self) -> Result<(), Error> { - if self - .kernels - .iter() - .any(|x| x.features.contains(KernelFeatures::COINBASE_KERNEL)) - { + if self.kernels.iter().any(|x| x.is_coinbase()) { return Err(Error::InvalidKernelFeatures); } Ok(()) @@ -1078,6 +1109,16 @@ impl Input { pub fn commitment(&self) -> Commitment { self.commit } + + /// Is this a coinbase input? + pub fn is_coinbase(&self) -> bool { + self.features.is_coinbase() + } + + /// Is this a plain input? + pub fn is_plain(&self) -> bool { + self.features.is_plain() + } } bitflags! { @@ -1085,9 +1126,9 @@ bitflags! { #[derive(Serialize, Deserialize)] pub struct OutputFeatures: u8 { /// No flags - const DEFAULT_OUTPUT = 0b00000000; + const PLAIN = 0; /// Output is a coinbase output, must not be spent until maturity - const COINBASE_OUTPUT = 0b00000001; + const COINBASE = 1; } } @@ -1157,12 +1198,34 @@ impl PMMRable for Output { } } +impl OutputFeatures { + /// Is this a coinbase output? + pub fn is_coinbase(&self) -> bool { + self.contains(OutputFeatures::COINBASE) + } + + /// Is this a plain output? + pub fn is_plain(&self) -> bool { + !self.contains(OutputFeatures::COINBASE) + } +} + impl Output { /// Commitment for the output pub fn commitment(&self) -> Commitment { self.commit } + /// Is this a coinbase kernel? + pub fn is_coinbase(&self) -> bool { + self.features.is_coinbase() + } + + /// Is this a plain kernel? + pub fn is_plain(&self) -> bool { + self.features.is_plain() + } + /// Range proof for the output pub fn proof(&self) -> RangeProof { self.proof @@ -1288,25 +1351,43 @@ impl From for OutputIdentifier { /// to produce a 32 byte message to sign. /// /// testnet4: msg = (fee || lock_height) -/// mainnet: msg = hash(fee || lock_height || features) +/// mainnet: msg = hash(features) for coinbase kernels +/// hash(features || fee) for plain kernels +/// hash(features || fee || lock_height) for height locked kernels /// pub fn kernel_sig_msg( fee: u64, lock_height: u64, features: KernelFeatures, ) -> Result { + if features.is_coinbase() && fee != 0 || !features.is_height_locked() && lock_height != 0 { + return Err(Error::InvalidKernelFeatures); + } let msg = if global::is_testnet() { let mut bytes = [0; 32]; BigEndian::write_u64(&mut bytes[16..24], fee); BigEndian::write_u64(&mut bytes[24..], lock_height); secp::Message::from_slice(&bytes)? } else { - let hash = (fee, lock_height, features).hash(); + let hash = match features { + KernelFeatures::COINBASE => (features).hash(), + KernelFeatures::PLAIN => (features, fee).hash(), + _ => (features, fee, lock_height).hash(), + }; secp::Message::from_slice(&hash.as_bytes())? }; Ok(msg) } +/// kernel features as determined by lock height +pub fn kernel_features(lock_height: u64) -> KernelFeatures { + if lock_height > 0 { + KernelFeatures::HEIGHT_LOCKED + } else { + KernelFeatures::PLAIN + } +} + #[cfg(test)] mod test { use super::*; @@ -1325,7 +1406,7 @@ mod test { let sig = secp::Signature::from_raw_data(&[0; 64]).unwrap(); let kernel = TxKernel { - features: KernelFeatures::DEFAULT_KERNEL, + features: KernelFeatures::PLAIN, lock_height: 0, excess: commit, excess_sig: sig.clone(), @@ -1335,7 +1416,7 @@ mod test { let mut vec = vec![]; ser::serialize(&mut vec, &kernel).expect("serialized failed"); let kernel2: TxKernel = ser::deserialize(&mut &vec[..]).unwrap(); - assert_eq!(kernel2.features, KernelFeatures::DEFAULT_KERNEL); + assert_eq!(kernel2.features, KernelFeatures::PLAIN); assert_eq!(kernel2.lock_height, 0); assert_eq!(kernel2.excess, commit); assert_eq!(kernel2.excess_sig, sig.clone()); @@ -1343,7 +1424,7 @@ mod test { // now check a kernel with lock_height serialize/deserialize correctly let kernel = TxKernel { - features: KernelFeatures::DEFAULT_KERNEL, + features: KernelFeatures::HEIGHT_LOCKED, lock_height: 100, excess: commit, excess_sig: sig.clone(), @@ -1353,7 +1434,7 @@ mod test { let mut vec = vec![]; ser::serialize(&mut vec, &kernel).expect("serialized failed"); let kernel2: TxKernel = ser::deserialize(&mut &vec[..]).unwrap(); - assert_eq!(kernel2.features, KernelFeatures::DEFAULT_KERNEL); + assert_eq!(kernel2.features, KernelFeatures::HEIGHT_LOCKED); assert_eq!(kernel2.lock_height, 100); assert_eq!(kernel2.excess, commit); assert_eq!(kernel2.excess_sig, sig.clone()); @@ -1380,7 +1461,7 @@ mod test { let commit = keychain.commit(5, &key_id).unwrap(); let input = Input { - features: OutputFeatures::DEFAULT_OUTPUT, + features: OutputFeatures::PLAIN, commit: commit, }; @@ -1396,7 +1477,7 @@ mod test { // now generate the short_id for a *very* similar output (single feature flag // different) and check it generates a different short_id let input = Input { - features: OutputFeatures::COINBASE_OUTPUT, + features: OutputFeatures::COINBASE, commit: commit, }; diff --git a/core/src/libtx/aggsig.rs b/core/src/libtx/aggsig.rs index 50e213710..43e37ea53 100644 --- a/core/src/libtx/aggsig.rs +++ b/core/src/libtx/aggsig.rs @@ -241,14 +241,14 @@ pub fn verify_partial_sig( /// let commit = keychain.commit(value, &key_id).unwrap(); /// let rproof = proof::create(&keychain, value, &key_id, commit, None).unwrap(); /// let output = Output { -/// features: OutputFeatures::COINBASE_OUTPUT, +/// features: OutputFeatures::COINBASE, /// commit: commit, /// proof: rproof, /// }; /// let height = 20; /// let over_commit = secp.commit_value(reward(fees)).unwrap(); /// let out_commit = output.commitment(); -/// let msg = kernel_sig_msg(0, height, KernelFeatures::DEFAULT_KERNEL).unwrap(); +/// let msg = kernel_sig_msg(0, height, KernelFeatures::HEIGHT_LOCKED).unwrap(); /// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap(); /// let pubkey = excess.to_pubkey(&secp).unwrap(); /// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, Some(&pubkey)).unwrap(); @@ -315,14 +315,14 @@ where /// let commit = keychain.commit(value, &key_id).unwrap(); /// let rproof = proof::create(&keychain, value, &key_id, commit, None).unwrap(); /// let output = Output { -/// features: OutputFeatures::COINBASE_OUTPUT, +/// features: OutputFeatures::COINBASE, /// commit: commit, /// proof: rproof, /// }; /// let height = 20; /// let over_commit = secp.commit_value(reward(fees)).unwrap(); /// let out_commit = output.commitment(); -/// let msg = kernel_sig_msg(0, height, KernelFeatures::DEFAULT_KERNEL).unwrap(); +/// let msg = kernel_sig_msg(0, height, KernelFeatures::HEIGHT_LOCKED).unwrap(); /// let excess = secp.commit_sum(vec![out_commit], vec![over_commit]).unwrap(); /// let pubkey = excess.to_pubkey(&secp).unwrap(); /// let sig = aggsig::sign_from_key_id(&secp, &keychain, &msg, value, &key_id, Some(&pubkey)).unwrap(); diff --git a/core/src/libtx/build.rs b/core/src/libtx/build.rs index d4e75d710..f502f4d86 100644 --- a/core/src/libtx/build.rs +++ b/core/src/libtx/build.rs @@ -69,7 +69,7 @@ where "Building input (spending regular output): {}, {}", value, key_id ); - build_input(value, OutputFeatures::DEFAULT_OUTPUT, key_id) + build_input(value, OutputFeatures::PLAIN, key_id) } /// Adds a coinbase input spending a coinbase output. @@ -78,7 +78,7 @@ where K: Keychain, { debug!("Building input (spending coinbase): {}, {}", value, key_id); - build_input(value, OutputFeatures::COINBASE_OUTPUT, key_id) + build_input(value, OutputFeatures::COINBASE, key_id) } /// Adds an output with the provided value and key identifier from the @@ -97,7 +97,7 @@ where ( tx.with_output(Output { - features: OutputFeatures::DEFAULT_OUTPUT, + features: OutputFeatures::PLAIN, commit: commit, proof: rproof, }), diff --git a/core/src/libtx/reward.rs b/core/src/libtx/reward.rs index e114e4272..a85c12507 100644 --- a/core/src/libtx/reward.rs +++ b/core/src/libtx/reward.rs @@ -27,7 +27,6 @@ pub fn output( keychain: &K, key_id: &Identifier, fees: u64, - height: u64, ) -> Result<(Output, TxKernel), Error> where K: Keychain, @@ -40,7 +39,7 @@ where let rproof = proof::create(keychain, value, key_id, commit, None)?; let output = Output { - features: OutputFeatures::COINBASE_OUTPUT, + features: OutputFeatures::COINBASE, commit: commit, proof: rproof, }; @@ -53,22 +52,18 @@ where let pubkey = excess.to_pubkey(&secp)?; // NOTE: Remember we sign the fee *and* the lock_height. - // For a coinbase output the fee is 0 and the lock_height is - // the lock_height of the coinbase output itself, - // not the lock_height of the tx (there is no tx for a coinbase output). - // This output will not be spendable earlier than lock_height (and we sign this - // here). - let msg = kernel_sig_msg(0, height, KernelFeatures::COINBASE_KERNEL)?; + // For a coinbase output the fee is 0 and the lock_height is 0 + let msg = kernel_sig_msg(0, 0, KernelFeatures::COINBASE)?; let sig = aggsig::sign_from_key_id(&secp, keychain, &msg, value, &key_id, Some(&pubkey))?; let proof = TxKernel { - features: KernelFeatures::COINBASE_KERNEL, + features: KernelFeatures::COINBASE, excess: excess, excess_sig: sig, fee: 0, - // lock_height here is the height of the block (tx should be valid immediately) - // *not* the lock_height of the coinbase output (only spendable 1,000 blocks later) - lock_height: height, + // lock_height here is 0 + // *not* the maturity of the coinbase output (only spendable 1,440 blocks later) + lock_height: 0, }; Ok((output, proof)) } diff --git a/core/src/libtx/slate.rs b/core/src/libtx/slate.rs index fd9551da5..8816d028f 100644 --- a/core/src/libtx/slate.rs +++ b/core/src/libtx/slate.rs @@ -16,10 +16,10 @@ //! around during an interactive wallet exchange use crate::blake2::blake2b::blake2b; -use crate::core::committed::Committed; -use crate::core::transaction::{kernel_sig_msg, KernelFeatures, Transaction}; -use crate::core::verifier_cache::LruVerifierCache; use crate::core::amount_to_hr_string; +use crate::core::committed::Committed; +use crate::core::transaction::{kernel_features, kernel_sig_msg, Transaction}; +use crate::core::verifier_cache::LruVerifierCache; use crate::keychain::{BlindSum, BlindingFactor, Keychain}; use crate::libtx::error::{Error, ErrorKind}; use crate::libtx::{aggsig, build, tx_fee}; @@ -160,8 +160,7 @@ impl Slate { // Currently includes the fee and the lock_height. fn msg_to_sign(&self) -> Result { // Currently we only support interactively creating a tx with a "default" kernel. - let features = KernelFeatures::DEFAULT_KERNEL; - + let features = kernel_features(self.lock_height); let msg = kernel_sig_msg(self.fee, self.lock_height, features)?; Ok(msg) } diff --git a/core/tests/block.rs b/core/tests/block.rs index 9766a3419..908b94962 100644 --- a/core/tests/block.rs +++ b/core/tests/block.rs @@ -131,7 +131,7 @@ fn empty_block_with_coinbase_is_valid() { let coinbase_outputs = b .outputs() .iter() - .filter(|out| out.features.contains(OutputFeatures::COINBASE_OUTPUT)) + .filter(|out| out.is_coinbase()) .map(|o| o.clone()) .collect::>(); assert_eq!(coinbase_outputs.len(), 1); @@ -139,7 +139,7 @@ fn empty_block_with_coinbase_is_valid() { let coinbase_kernels = b .kernels() .iter() - .filter(|out| out.features.contains(KernelFeatures::COINBASE_KERNEL)) + .filter(|out| out.is_coinbase()) .map(|o| o.clone()) .collect::>(); assert_eq!(coinbase_kernels.len(), 1); @@ -152,7 +152,7 @@ fn empty_block_with_coinbase_is_valid() { } #[test] -// test that flipping the COINBASE_OUTPUT flag on the output features +// test that flipping the COINBASE flag on the output features // invalidates the block and specifically it causes verify_coinbase to fail // additionally verifying the merkle_inputs_outputs also fails fn remove_coinbase_output_flag() { @@ -161,12 +161,8 @@ fn remove_coinbase_output_flag() { let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); let mut b = new_block(vec![], &keychain, &prev, &key_id); - assert!(b.outputs()[0] - .features - .contains(OutputFeatures::COINBASE_OUTPUT)); - b.outputs_mut()[0] - .features - .remove(OutputFeatures::COINBASE_OUTPUT); + assert!(b.outputs()[0].is_coinbase()); + b.outputs_mut()[0].features = OutputFeatures::PLAIN; assert_eq!(b.verify_coinbase(), Err(Error::CoinbaseSumMismatch)); assert!(b @@ -179,7 +175,7 @@ fn remove_coinbase_output_flag() { } #[test] -// test that flipping the COINBASE_KERNEL flag on the kernel features +// test that flipping the COINBASE flag on the kernel features // invalidates the block and specifically it causes verify_coinbase to fail fn remove_coinbase_kernel_flag() { let keychain = ExtKeychain::from_random_seed().unwrap(); @@ -187,12 +183,8 @@ fn remove_coinbase_kernel_flag() { let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); let mut b = new_block(vec![], &keychain, &prev, &key_id); - assert!(b.kernels()[0] - .features - .contains(KernelFeatures::COINBASE_KERNEL)); - b.kernels_mut()[0] - .features - .remove(KernelFeatures::COINBASE_KERNEL); + assert!(b.kernels()[0].is_coinbase()); + b.kernels_mut()[0].features = KernelFeatures::PLAIN; // Flipping the coinbase flag results in kernels not summing correctly. assert_eq!( @@ -380,7 +372,7 @@ fn convert_block_to_compact_block() { cb.kern_ids()[0], b.kernels() .iter() - .find(|x| !x.features.contains(KernelFeatures::COINBASE_KERNEL)) + .find(|x| !x.is_coinbase()) .unwrap() .short_id(&cb.hash(), cb.nonce) ); diff --git a/core/tests/common.rs b/core/tests/common.rs index 5c2227629..0ef7494cd 100644 --- a/core/tests/common.rs +++ b/core/tests/common.rs @@ -92,7 +92,7 @@ where K: Keychain, { let fees = txs.iter().map(|tx| tx.fee()).sum(); - let reward_output = reward::output(keychain, &key_id, fees, previous_header.height).unwrap(); + let reward_output = reward::output(keychain, &key_id, fees).unwrap(); Block::new( &previous_header, txs.into_iter().cloned().collect(), diff --git a/core/tests/core.rs b/core/tests/core.rs index acc391d00..56940a7dc 100644 --- a/core/tests/core.rs +++ b/core/tests/core.rs @@ -122,7 +122,7 @@ fn build_tx_kernel() { let kern = &tx.kernels()[0]; kern.verify().unwrap(); - assert_eq!(kern.features, KernelFeatures::DEFAULT_KERNEL); + assert_eq!(kern.features, KernelFeatures::PLAIN); assert_eq!(kern.fee, tx.fee()); } diff --git a/core/tests/transaction.rs b/core/tests/transaction.rs index ced3c94ee..fc89f9774 100644 --- a/core/tests/transaction.rs +++ b/core/tests/transaction.rs @@ -31,7 +31,7 @@ fn test_output_ser_deser() { let proof = proof::create(&keychain, 5, &key_id, commit, None).unwrap(); let out = Output { - features: OutputFeatures::DEFAULT_OUTPUT, + features: OutputFeatures::PLAIN, commit: commit, proof: proof, }; @@ -40,7 +40,7 @@ fn test_output_ser_deser() { ser::serialize(&mut vec, &out).expect("serialized failed"); let dout: Output = ser::deserialize(&mut &vec[..]).unwrap(); - assert_eq!(dout.features, OutputFeatures::DEFAULT_OUTPUT); + assert_eq!(dout.features, OutputFeatures::PLAIN); assert_eq!(dout.commit, out.commit); assert_eq!(dout.proof, out.proof); } diff --git a/core/tests/verifier_cache.rs b/core/tests/verifier_cache.rs index ff7d62dc4..6a0b00857 100644 --- a/core/tests/verifier_cache.rs +++ b/core/tests/verifier_cache.rs @@ -38,7 +38,7 @@ fn test_verifier_cache_rangeproofs() { let proof = proof::create(&keychain, 5, &key_id, commit, None).unwrap(); let out = Output { - features: OutputFeatures::DEFAULT_OUTPUT, + features: OutputFeatures::PLAIN, commit: commit, proof: proof, }; diff --git a/pool/tests/block_building.rs b/pool/tests/block_building.rs index f31824a41..29dd0ba39 100644 --- a/pool/tests/block_building.rs +++ b/pool/tests/block_building.rs @@ -44,7 +44,7 @@ fn test_transaction_pool_block_building() { let height = prev_header.height + 1; let key_id = ExtKeychain::derive_key_id(1, height as u32, 0, 0, 0); let fee = txs.iter().map(|x| x.fee()).sum(); - let reward = libtx::reward::output(&keychain, &key_id, fee, height).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id, fee).unwrap(); let mut block = Block::new(&prev_header, txs, Difficulty::min(), reward).unwrap(); // Set the prev_root to the prev hash for testing purposes (no MMR to obtain a root from). diff --git a/pool/tests/block_reconciliation.rs b/pool/tests/block_reconciliation.rs index b9a324f80..6404cddd0 100644 --- a/pool/tests/block_reconciliation.rs +++ b/pool/tests/block_reconciliation.rs @@ -44,7 +44,7 @@ fn test_transaction_pool_block_reconciliation() { let header = { let height = 1; let key_id = ExtKeychain::derive_key_id(1, height as u32, 0, 0, 0); - let reward = libtx::reward::output(&keychain, &key_id, 0, height).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id, 0).unwrap(); let genesis = BlockHeader::default(); let mut block = Block::new(&genesis, vec![], Difficulty::min(), reward).unwrap(); @@ -63,7 +63,7 @@ fn test_transaction_pool_block_reconciliation() { let block = { let key_id = ExtKeychain::derive_key_id(1, 2, 0, 0, 0); let fees = initial_tx.fee(); - let reward = libtx::reward::output(&keychain, &key_id, fees, 0).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id, fees).unwrap(); let mut block = Block::new(&header, vec![initial_tx], Difficulty::min(), reward).unwrap(); // Set the prev_root to the prev hash for testing purposes (no MMR to obtain a root from). @@ -156,7 +156,7 @@ fn test_transaction_pool_block_reconciliation() { let block = { let key_id = ExtKeychain::derive_key_id(1, 3, 0, 0, 0); let fees = block_txs.iter().map(|tx| tx.fee()).sum(); - let reward = libtx::reward::output(&keychain, &key_id, fees, 0).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id, fees).unwrap(); let mut block = Block::new(&header, block_txs, Difficulty::min(), reward).unwrap(); // Set the prev_root to the prev hash for testing purposes (no MMR to obtain a root from). diff --git a/pool/tests/transaction_pool.rs b/pool/tests/transaction_pool.rs index 20799dfdf..1cf726108 100644 --- a/pool/tests/transaction_pool.rs +++ b/pool/tests/transaction_pool.rs @@ -43,7 +43,7 @@ fn test_the_transaction_pool() { let header = { let height = 1; let key_id = ExtKeychain::derive_key_id(1, height as u32, 0, 0, 0); - let reward = libtx::reward::output(&keychain, &key_id, 0, height).unwrap(); + let reward = libtx::reward::output(&keychain, &key_id, 0).unwrap(); let block = Block::new(&BlockHeader::default(), vec![], Difficulty::min(), reward).unwrap(); chain.update_db_for_block(&block); diff --git a/servers/src/mining/mine_block.rs b/servers/src/mining/mine_block.rs index 3c4ccf115..5aa3216b1 100644 --- a/servers/src/mining/mine_block.rs +++ b/servers/src/mining/mine_block.rs @@ -173,7 +173,7 @@ fn burn_reward(block_fees: BlockFees) -> Result<(core::Output, core::TxKernel, B let keychain = ExtKeychain::from_random_seed().unwrap(); let key_id = ExtKeychain::derive_key_id(1, 1, 0, 0, 0); let (out, kernel) = - crate::core::libtx::reward::output(&keychain, &key_id, block_fees.fees, block_fees.height) + crate::core::libtx::reward::output(&keychain, &key_id, block_fees.fees) .unwrap(); Ok((out, kernel, block_fees)) } diff --git a/wallet/src/libwallet/internal/updater.rs b/wallet/src/libwallet/internal/updater.rs index 26469ab6b..10228f697 100644 --- a/wallet/src/libwallet/internal/updater.rs +++ b/wallet/src/libwallet/internal/updater.rs @@ -458,13 +458,7 @@ where debug!("receive_coinbase: {:?}", block_fees); - let (out, kern) = reward::output( - wallet.keychain(), - &key_id, - block_fees.fees, - block_fees.height, - ) - .unwrap(); + let (out, kern) = reward::output(wallet.keychain(), &key_id, block_fees.fees).unwrap(); /* .context(ErrorKind::Keychain)?; */ Ok((out, kern, block_fees)) } diff --git a/wallet/src/test_framework/mod.rs b/wallet/src/test_framework/mod.rs index 23a1a7c3f..69f62772f 100644 --- a/wallet/src/test_framework/mod.rs +++ b/wallet/src/test_framework/mod.rs @@ -45,8 +45,8 @@ pub use self::{testclient::LocalWalletClient, testclient::WalletProxy}; /// Get an output from the chain locally and present it back as an API output fn get_output_local(chain: &chain::Chain, commit: &pedersen::Commitment) -> Option { let outputs = [ - OutputIdentifier::new(OutputFeatures::DEFAULT_OUTPUT, commit), - OutputIdentifier::new(OutputFeatures::COINBASE_OUTPUT, commit), + OutputIdentifier::new(OutputFeatures::PLAIN, commit), + OutputIdentifier::new(OutputFeatures::COINBASE, commit), ]; for x in outputs.iter() { diff --git a/wallet/tests/libwallet.rs b/wallet/tests/libwallet.rs index 04ef3ad46..3ca5ac974 100644 --- a/wallet/tests/libwallet.rs +++ b/wallet/tests/libwallet.rs @@ -26,7 +26,7 @@ use grin_wallet as wallet; use rand::thread_rng; fn kernel_sig_msg() -> secp::Message { - transaction::kernel_sig_msg(0, 0, transaction::KernelFeatures::DEFAULT_KERNEL).unwrap() + transaction::kernel_sig_msg(0, 0, transaction::KernelFeatures::PLAIN).unwrap() } #[test] From a42250445d1874e7c5347301135b6d4df33ad65f Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Tue, 18 Dec 2018 14:03:55 -0800 Subject: [PATCH 19/27] Floonet chain type and genesis, testnets cleanup (#2182) --- core/src/consensus.rs | 38 ++--------- core/src/genesis.rs | 133 +++++++++++++------------------------ core/src/global.rs | 66 ++++-------------- core/src/pow.rs | 2 +- core/tests/consensus.rs | 55 ++++----------- servers/src/grin/server.rs | 7 +- wallet/src/types.rs | 2 +- 7 files changed, 80 insertions(+), 223 deletions(-) diff --git a/core/src/consensus.rs b/core/src/consensus.rs index 804e5cd03..b14ec8d61 100644 --- a/core/src/consensus.rs +++ b/core/src/consensus.rs @@ -62,32 +62,13 @@ pub const COINBASE_MATURITY: u64 = DAY_HEIGHT; /// function of block height (time). Starts at 90% losing a percent /// approximately every week. Represented as an integer between 0 and 100. pub fn secondary_pow_ratio(height: u64) -> u64 { - if global::is_testnet() { - if height < T4_CUCKAROO_HARDFORK { - // Maintaining pre hardfork testnet4 behavior - 90u64.saturating_sub(height / WEEK_HEIGHT) - } else { - 90u64.saturating_sub(height / (2 * YEAR_HEIGHT / 90)) - } - } else { - // Mainnet (or testing mainnet code). - 90u64.saturating_sub(height / (2 * YEAR_HEIGHT / 90)) - } + 90u64.saturating_sub(height / (2 * YEAR_HEIGHT / 90)) } /// The AR scale damping factor to use. Dependent on block height /// to account for pre HF behavior on testnet4. -fn ar_scale_damp_factor(height: u64) -> u64 { - if global::is_testnet() { - if height < T4_CUCKAROO_HARDFORK { - DIFFICULTY_DAMP_FACTOR - } else { - AR_SCALE_DAMP_FACTOR - } - } else { - // Mainnet (or testing mainnet code). - AR_SCALE_DAMP_FACTOR - } +fn ar_scale_damp_factor(_height: u64) -> u64 { + AR_SCALE_DAMP_FACTOR } /// Cuckoo-cycle proof size (cycle length) @@ -99,10 +80,6 @@ pub const DEFAULT_MIN_EDGE_BITS: u8 = 31; /// Cuckaroo proof-of-work edge_bits, meant to be ASIC resistant. pub const SECOND_POW_EDGE_BITS: u8 = 29; -/// Block height at which testnet 4 hard forks to use Cuckaroo instead of -/// Cuckatoo for ASIC-resistant PoW -pub const T4_CUCKAROO_HARDFORK: u64 = 64_000; - /// Original reference edge_bits to compute difficulty factors for higher /// Cuckoo graph sizes, changing this would hard fork pub const BASE_EDGE_BITS: u8 = 24; @@ -332,15 +309,10 @@ where /// Count the number of "secondary" (AR) blocks in the provided window of blocks. /// Note: we skip the first one, but testnet4 was incorrectly including it before /// the hardfork. -fn ar_count(height: u64, diff_data: &[HeaderInfo]) -> u64 { - let mut to_skip = 1; - if global::is_testnet() && height < T4_CUCKAROO_HARDFORK { - // Maintain behavior of testnet4 pre-HF. - to_skip = 0; - } +fn ar_count(_height: u64, diff_data: &[HeaderInfo]) -> u64 { 100 * diff_data .iter() - .skip(to_skip) + .skip(1) .filter(|n| n.is_secondary) .count() as u64 } diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 87e196e2f..6eba2cdb3 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -46,99 +46,46 @@ pub fn genesis_dev() -> core::Block { }) } -/// First testnet genesis block, still subject to change (especially the date, -/// will hopefully come before Christmas). -pub fn genesis_testnet1() -> core::Block { - core::Block::with_header(core::BlockHeader { +/// Placeholder for floonet genesis block, will definitely change before +/// release +pub fn genesis_floo() -> core::Block { + let gen = core::Block::with_header(core::BlockHeader { height: 0, - timestamp: Utc.ymd(2017, 11, 16).and_hms(20, 0, 0), + timestamp: Utc.ymd(2018, 12, 20).and_hms(20, 0, 0), // REPLACE + prev_root: Hash::default(), // REPLACE + output_root: Hash::default(), // REPLACE + range_proof_root: Hash::default(), // REPLACE + kernel_root: Hash::default(), // REPLACE + total_kernel_offset: BlindingFactor::zero(), // REPLACE + output_mmr_size: 1, + kernel_mmr_size: 1, pow: ProofOfWork { - total_difficulty: Difficulty::min(), - secondary_scaling: 1, - nonce: 28205, - proof: Proof::new(vec![ - 0x21e, 0x7a2, 0xeae, 0x144e, 0x1b1c, 0x1fbd, 0x203a, 0x214b, 0x293b, 0x2b74, - 0x2bfa, 0x2c26, 0x32bb, 0x346a, 0x34c7, 0x37c5, 0x4164, 0x42cc, 0x4cc3, 0x55af, - 0x5a70, 0x5b14, 0x5e1c, 0x5f76, 0x6061, 0x60f9, 0x61d7, 0x6318, 0x63a1, 0x63fb, - 0x649b, 0x64e5, 0x65a1, 0x6b69, 0x70f8, 0x71c7, 0x71cd, 0x7492, 0x7b11, 0x7db8, - 0x7f29, 0x7ff8, - ]), - }, - ..Default::default() - }) -} - -/// Second testnet genesis block (cuckoo30). -pub fn genesis_testnet2() -> core::Block { - core::Block::with_header(core::BlockHeader { - height: 0, - // previous: core::hash::Hash([0xff; 32]), - timestamp: Utc.ymd(2018, 3, 26).and_hms(16, 0, 0), - pow: ProofOfWork { - total_difficulty: Difficulty::from_num(global::initial_block_difficulty()), - secondary_scaling: 1, - nonce: 1060, - proof: Proof::new(vec![ - 0x1940730, 0x333b9d0, 0x4739d6f, 0x4c6cfb1, 0x6e3d6c3, 0x74408a3, 0x7ba2bd2, - 0x83e2024, 0x8ca22b5, 0x9d39ab8, 0xb6646dd, 0xc6698b6, 0xc6f78fe, 0xc99b662, - 0xcf2ae8c, 0xcf41eed, 0xdd073e6, 0xded6af8, 0xf08d1a5, 0x1156a144, 0x11d1160a, - 0x131bb0a5, 0x137ad703, 0x13b0831f, 0x1421683f, 0x147e3c1f, 0x1496fda0, 0x150ba22b, - 0x15cc5bc6, 0x16edf697, 0x17ced40c, 0x17d84f9e, 0x18a515c1, 0x19320d9c, 0x19da4f6d, - 0x1b50bcb1, 0x1b8bc72f, 0x1c7b6964, 0x1d07b3a9, 0x1d189d4d, 0x1d1f9a15, 0x1dafcd41, - ]), - }, - ..Default::default() - }) -} - -/// Second testnet genesis block (cuckoo30). Temporary values for now. -pub fn genesis_testnet3() -> core::Block { - core::Block::with_header(core::BlockHeader { - height: 0, - // previous: core::hash::Hash([0xff; 32]), - timestamp: Utc.ymd(2018, 7, 8).and_hms(18, 0, 0), - pow: ProofOfWork { - total_difficulty: Difficulty::from_num(global::initial_block_difficulty()), - secondary_scaling: 1, - nonce: 4956988373127691, - proof: Proof::new(vec![ - 0xa420dc, 0xc8ffee, 0x10e433e, 0x1de9428, 0x2ed4cea, 0x52d907b, 0x5af0e3f, - 0x6b8fcae, 0x8319b53, 0x845ca8c, 0x8d2a13e, 0x8d6e4cc, 0x9349e8d, 0xa7a33c5, - 0xaeac3cb, 0xb193e23, 0xb502e19, 0xb5d9804, 0xc9ac184, 0xd4f4de3, 0xd7a23b8, - 0xf1d8660, 0xf443756, 0x10b833d2, 0x11418fc5, 0x11b8aeaf, 0x131836ec, 0x132ab818, - 0x13a46a55, 0x13df89fe, 0x145d65b5, 0x166f9c3a, 0x166fe0ef, 0x178cb36f, 0x185baf68, - 0x1bbfe563, 0x1bd637b4, 0x1cfc8382, 0x1d1ed012, 0x1e391ca5, 0x1e999b4c, 0x1f7c6d21, - ]), - }, - ..Default::default() - }) -} - -/// 4th testnet genesis block (cuckatoo29 AR, 30+ AF). Temporary values for now (Pow won't verify) -/// NB: Currently set to intenal pre-testnet values -pub fn genesis_testnet4() -> core::Block { - core::Block::with_header(core::BlockHeader { - height: 0, - timestamp: Utc.ymd(2018, 10, 17).and_hms(20, 0, 0), - pow: ProofOfWork { - total_difficulty: Difficulty::from_num(global::initial_block_difficulty()), - secondary_scaling: global::initial_graph_weight(), - nonce: 8612241555342799290, + total_difficulty: Difficulty::from_num(10_u64.pow(6)), + secondary_scaling: 1856, + nonce: 1, // REPLACE proof: Proof { - nonces: vec![ - 0x46f3b4, 0x1135f8c, 0x1a1596f, 0x1e10f71, 0x41c03ea, 0x63fe8e7, 0x65af34f, - 0x73c16d3, 0x8216dc3, 0x9bc75d0, 0xae7d9ad, 0xc1cb12b, 0xc65e957, 0xf67a152, - 0xfac6559, 0x100c3d71, 0x11eea08b, 0x1225dfbb, 0x124d61a1, 0x132a14b4, - 0x13f4ec38, 0x1542d236, 0x155f2df0, 0x1577394e, 0x163c3513, 0x19349845, - 0x19d46953, 0x19f65ed4, 0x1a0411b9, 0x1a2fa039, 0x1a72a06c, 0x1b02ddd2, - 0x1b594d59, 0x1b7bffd3, 0x1befe12e, 0x1c82e4cd, 0x1d492478, 0x1de132a5, - 0x1e578b3c, 0x1ed96855, 0x1f222896, 0x1fea0da6, - ], + nonces: vec![0; 42], // REPLACE edge_bits: 29, }, }, ..Default::default() - }) + }); + let kernel = core::TxKernel { + features: core::KernelFeatures::COINBASE, + fee: 0, + lock_height: 0, + excess: Commitment::from_vec(vec![]), // REPLACE + excess_sig: Signature::from_raw_data(&[0; 64]).unwrap(), //REPLACE + }; + let output = core::Output { + features: core::OutputFeatures::COINBASE, + commit: Commitment::from_vec(vec![]), // REPLACE + proof: RangeProof { + plen: SINGLE_BULLET_PROOF_SIZE, + proof: [0; SINGLE_BULLET_PROOF_SIZE], // REPLACE + }, + }; + gen.with_reward(output, kernel) } /// Placeholder for mainnet genesis block, will definitely change before @@ -166,14 +113,14 @@ pub fn genesis_main() -> core::Block { ..Default::default() }); let kernel = core::TxKernel { - features: core::KernelFeatures::COINBASE_KERNEL, + features: core::KernelFeatures::COINBASE, fee: 0, lock_height: 0, excess: Commitment::from_vec(vec![]), // REPLACE excess_sig: Signature::from_raw_data(&[0; 64]).unwrap(), //REPLACE }; let output = core::Output { - features: core::OutputFeatures::COINBASE_OUTPUT, + features: core::OutputFeatures::COINBASE, commit: Commitment::from_vec(vec![]), // REPLACE proof: RangeProof { plen: SINGLE_BULLET_PROOF_SIZE, @@ -189,6 +136,16 @@ mod test { use crate::ser; use crate::core::hash::Hashed; + // TODO hardcode the hashes once genesis is set + #[test] + fn floonet_genesis_hash() { + let gen_hash = genesis_floo().hash(); + println!("floonet genesis hash: {}", gen_hash.to_hex()); + let gen_bin = ser::ser_vec(&genesis_floo()).unwrap(); + println!("floonet genesis full hash: {}\n", gen_bin.hash().to_hex()); + //assert_eq!(gene_hash.to_hex, ""); + } + // TODO hardcode the hashes once genesis is set #[test] fn mainnet_genesis_hash() { diff --git a/core/src/global.rs b/core/src/global.rs index fbf51a98f..be7db1f74 100644 --- a/core/src/global.rs +++ b/core/src/global.rs @@ -20,7 +20,7 @@ use crate::consensus::HeaderInfo; use crate::consensus::{ graph_weight, BASE_EDGE_BITS, BLOCK_TIME_SEC, COINBASE_MATURITY, CUT_THROUGH_HORIZON, DAY_HEIGHT, DEFAULT_MIN_EDGE_BITS, DIFFICULTY_ADJUST_WINDOW, INITIAL_DIFFICULTY, PROOFSIZE, - SECOND_POW_EDGE_BITS, STATE_SYNC_THRESHOLD, T4_CUCKAROO_HARDFORK, UNIT_DIFFICULTY, + SECOND_POW_EDGE_BITS, STATE_SYNC_THRESHOLD, }; use crate::pow::{self, new_cuckaroo_ctx, new_cuckatoo_ctx, EdgeType, PoWContext}; /// An enum collecting sets of parameters used throughout the @@ -62,13 +62,6 @@ pub const TESTING_INITIAL_GRAPH_WEIGHT: u32 = 1; /// Testing initial block difficulty pub const TESTING_INITIAL_DIFFICULTY: u64 = 1; -/// Testnet 2 initial block difficulty, high to see how it goes -pub const TESTNET2_INITIAL_DIFFICULTY: u64 = 1000; - -/// Testnet 3 initial block difficulty, moderately high, taking into account -/// a 30x Cuckoo adjustment factor -pub const TESTNET3_INITIAL_DIFFICULTY: u64 = 30000; - /// If a peer's last updated difficulty is 2 hours ago and its difficulty's lower than ours, /// we're sure this peer is a stuck node, and we will kick out such kind of stuck peers. pub const STUCK_PEER_KICK_TIME: i64 = 2 * 3600 * 1000; @@ -79,13 +72,6 @@ const PEER_EXPIRATION_DAYS: i64 = 7 * 2; /// Constant that expresses defunct peer timeout in seconds to be used in checks. pub const PEER_EXPIRATION_REMOVE_TIME: i64 = PEER_EXPIRATION_DAYS * 24 * 3600; -/// Testnet 4 initial block difficulty -/// 1_000 times natural scale factor for cuckatoo29 -pub const TESTNET4_INITIAL_DIFFICULTY: u64 = 1_000 * UNIT_DIFFICULTY; - -/// Cuckatoo edge_bits on T4 -pub const TESTNET4_MIN_EDGE_BITS: u8 = 30; - /// Trigger compaction check on average every day for all nodes. /// Randomized per node - roll the dice on every block to decide. /// Will compact the txhashset to remove pruned data. @@ -101,21 +87,15 @@ pub enum ChainTypes { AutomatedTesting, /// For User testing UserTesting, - /// First test network - Testnet1, - /// Second test network - Testnet2, - /// Third test network - Testnet3, - /// Fourth test network - Testnet4, + /// Protocol testing network + Floonet, /// Main production network Mainnet, } impl Default for ChainTypes { fn default() -> ChainTypes { - ChainTypes::Testnet4 + ChainTypes::Floonet } } @@ -149,7 +129,7 @@ pub fn set_mining_mode(mode: ChainTypes) { /// Return either a cuckoo context or a cuckatoo context /// Single change point pub fn create_pow_context( - height: u64, + _height: u64, edge_bits: u8, proof_size: usize, max_sols: u32, @@ -163,12 +143,9 @@ where ChainTypes::Mainnet if edge_bits == 29 => new_cuckaroo_ctx(edge_bits, proof_size), ChainTypes::Mainnet => new_cuckatoo_ctx(edge_bits, proof_size, max_sols), - // T4 has Cuckatoo for everything up to hard fork, then Cuckaroo29 for AR - // and Cuckatoo30+ for AF PoW - ChainTypes::Testnet4 if edge_bits == 29 && height >= T4_CUCKAROO_HARDFORK => { - new_cuckaroo_ctx(edge_bits, proof_size) - } - ChainTypes::Testnet4 => new_cuckatoo_ctx(edge_bits, proof_size, max_sols), + // Same for Floonet + ChainTypes::Floonet if edge_bits == 29 => new_cuckaroo_ctx(edge_bits, proof_size), + ChainTypes::Floonet => new_cuckatoo_ctx(edge_bits, proof_size, max_sols), // Everything else is Cuckatoo only _ => new_cuckatoo_ctx(edge_bits, proof_size, max_sols), @@ -186,8 +163,6 @@ pub fn min_edge_bits() -> u8 { match *param_ref { ChainTypes::AutomatedTesting => AUTOMATED_TESTING_MIN_EDGE_BITS, ChainTypes::UserTesting => USER_TESTING_MIN_EDGE_BITS, - ChainTypes::Testnet1 => USER_TESTING_MIN_EDGE_BITS, - ChainTypes::Testnet4 => TESTNET4_MIN_EDGE_BITS, _ => DEFAULT_MIN_EDGE_BITS, } } @@ -200,7 +175,6 @@ pub fn base_edge_bits() -> u8 { match *param_ref { ChainTypes::AutomatedTesting => AUTOMATED_TESTING_MIN_EDGE_BITS, ChainTypes::UserTesting => USER_TESTING_MIN_EDGE_BITS, - ChainTypes::Testnet1 => USER_TESTING_MIN_EDGE_BITS, _ => BASE_EDGE_BITS, } } @@ -231,10 +205,7 @@ pub fn initial_block_difficulty() -> u64 { match *param_ref { ChainTypes::AutomatedTesting => TESTING_INITIAL_DIFFICULTY, ChainTypes::UserTesting => TESTING_INITIAL_DIFFICULTY, - ChainTypes::Testnet1 => TESTING_INITIAL_DIFFICULTY, - ChainTypes::Testnet2 => TESTNET2_INITIAL_DIFFICULTY, - ChainTypes::Testnet3 => TESTNET3_INITIAL_DIFFICULTY, - ChainTypes::Testnet4 => TESTNET4_INITIAL_DIFFICULTY, + ChainTypes::Floonet => INITIAL_DIFFICULTY, ChainTypes::Mainnet => INITIAL_DIFFICULTY, } } @@ -244,10 +215,7 @@ pub fn initial_graph_weight() -> u32 { match *param_ref { ChainTypes::AutomatedTesting => TESTING_INITIAL_GRAPH_WEIGHT, ChainTypes::UserTesting => TESTING_INITIAL_GRAPH_WEIGHT, - ChainTypes::Testnet1 => TESTING_INITIAL_GRAPH_WEIGHT, - ChainTypes::Testnet2 => TESTING_INITIAL_GRAPH_WEIGHT, - ChainTypes::Testnet3 => TESTING_INITIAL_GRAPH_WEIGHT, - ChainTypes::Testnet4 => graph_weight(0, SECOND_POW_EDGE_BITS) as u32, + ChainTypes::Floonet => graph_weight(0, SECOND_POW_EDGE_BITS) as u32, ChainTypes::Mainnet => graph_weight(0, SECOND_POW_EDGE_BITS) as u32, } } @@ -288,20 +256,14 @@ pub fn is_user_testing_mode() -> bool { /// Production defined as a live public network, testnet[n] or mainnet. pub fn is_production_mode() -> bool { let param_ref = CHAIN_TYPE.read(); - ChainTypes::Testnet1 == *param_ref - || ChainTypes::Testnet2 == *param_ref - || ChainTypes::Testnet3 == *param_ref - || ChainTypes::Testnet4 == *param_ref + ChainTypes::Floonet == *param_ref || ChainTypes::Mainnet == *param_ref } /// Are we in one of our (many) testnets? pub fn is_testnet() -> bool { let param_ref = CHAIN_TYPE.read(); - ChainTypes::Testnet1 == *param_ref - || ChainTypes::Testnet2 == *param_ref - || ChainTypes::Testnet3 == *param_ref - || ChainTypes::Testnet4 == *param_ref + ChainTypes::Floonet == *param_ref } /// Helper function to get a nonce known to create a valid POW on @@ -316,9 +278,9 @@ pub fn get_genesis_nonce() -> u64 { // Magic nonce for current genesis block at cuckatoo15 ChainTypes::UserTesting => 27944, // Placeholder, obviously not the right value + ChainTypes::Floonet => 0, + // Placeholder, obviously not the right value ChainTypes::Mainnet => 0, - // Magic nonce for genesis block for testnet2 (cuckatoo29) - _ => panic!("Pre-set"), } } diff --git a/core/src/pow.rs b/core/src/pow.rs index e3110c30f..52136afbb 100644 --- a/core/src/pow.rs +++ b/core/src/pow.rs @@ -69,7 +69,7 @@ pub fn verify_size(bh: &BlockHeader) -> Result<(), Error> { /// Mines a genesis block using the internal miner pub fn mine_genesis_block() -> Result { - let mut gen = genesis::genesis_testnet2(); + let mut gen = genesis::genesis_dev(); if global::is_user_testing_mode() || global::is_automated_testing_mode() { gen = genesis::genesis_dev(); gen.header.timestamp = Utc::now(); diff --git a/core/tests/consensus.rs b/core/tests/consensus.rs index 8178c456f..fbb1ab2cc 100644 --- a/core/tests/consensus.rs +++ b/core/tests/consensus.rs @@ -206,18 +206,6 @@ fn add_block( ret_chain_sim } -// Adds many defined blocks -fn add_blocks( - intervals: Vec, - chain_sim: Vec<(HeaderInfo, DiffStats)>, -) -> Vec<(HeaderInfo, DiffStats)> { - let mut return_chain = chain_sim.clone(); - for i in intervals { - return_chain = add_block(i, return_chain.clone()); - } - return_chain -} - // Adds another n 'blocks' to the iterator, with difficulty calculated fn add_block_repeated( interval: u64, @@ -355,25 +343,6 @@ fn adjustment_scenarios() { print_chain_sim(chain_sim); println!("*********************************************************"); - // Actual testnet 2 timings - let testnet2_intervals = [ - 2880, 16701, 1882, 3466, 614, 605, 1551, 538, 931, 23, 690, 1397, 2112, 2058, 605, 721, - 2148, 1605, 134, 1234, 1569, 482, 1775, 2732, 540, 958, 883, 3475, 518, 1346, 1926, 780, - 865, 269, 1079, 141, 105, 781, 289, 256, 709, 68, 165, 1813, 3899, 1458, 955, 2336, 239, - 674, 1059, 157, 214, 15, 157, 558, 1945, 1677, 1825, 1307, 1973, 660, 77, 3134, 410, 347, - 537, 649, 325, 370, 2271, 106, 19, 329, - ]; - - global::set_mining_mode(global::ChainTypes::Testnet2); - let chain_sim = create_chain_sim(global::initial_block_difficulty()); - let chain_sim = add_blocks(testnet2_intervals.to_vec(), chain_sim); - - println!(""); - println!("*********************************************************"); - println!("Scenario 6) Testnet2"); - println!("*********************************************************"); - print_chain_sim(chain_sim); - println!("*********************************************************"); } /// Checks different next_target adjustments and difficulty boundaries @@ -526,7 +495,7 @@ fn test_secondary_pow_ratio() { // Tests for testnet4 chain type (covers pre and post hardfork). { - global::set_mining_mode(global::ChainTypes::Testnet4); + global::set_mining_mode(global::ChainTypes::Floonet); assert_eq!(global::is_testnet(), true); assert_eq!(secondary_pow_ratio(1), 90); @@ -539,16 +508,16 @@ fn test_secondary_pow_ratio() { let one_week = 60 * 24 * 7; assert_eq!(secondary_pow_ratio(one_week - 1), 90); - assert_eq!(secondary_pow_ratio(one_week), 89); - assert_eq!(secondary_pow_ratio(one_week + 1), 89); + assert_eq!(secondary_pow_ratio(one_week), 90); + assert_eq!(secondary_pow_ratio(one_week + 1), 90); let two_weeks = one_week * 2; assert_eq!(secondary_pow_ratio(two_weeks - 1), 89); - assert_eq!(secondary_pow_ratio(two_weeks), 88); - assert_eq!(secondary_pow_ratio(two_weeks + 1), 88); + assert_eq!(secondary_pow_ratio(two_weeks), 89); + assert_eq!(secondary_pow_ratio(two_weeks + 1), 89); let t4_fork_height = 64_000; - assert_eq!(secondary_pow_ratio(t4_fork_height - 1), 84); + assert_eq!(secondary_pow_ratio(t4_fork_height - 1), 85); assert_eq!(secondary_pow_ratio(t4_fork_height), 85); assert_eq!(secondary_pow_ratio(t4_fork_height + 1), 85); @@ -572,9 +541,9 @@ fn test_secondary_pow_scale() { let window = DIFFICULTY_ADJUST_WINDOW; let mut hi = HeaderInfo::from_diff_scaling(Difficulty::from_num(10), 100); - // testnet4 testing + // floonet testing { - global::set_mining_mode(global::ChainTypes::Testnet4); + global::set_mining_mode(global::ChainTypes::Floonet); assert_eq!(global::is_testnet(), true); // all primary, factor should increase so it becomes easier to find a high @@ -582,13 +551,13 @@ fn test_secondary_pow_scale() { hi.is_secondary = false; assert_eq!( secondary_pow_scaling(1, &(0..window).map(|_| hi.clone()).collect::>()), - 147 + 106 ); // all secondary on 90%, factor should go down a bit hi.is_secondary = true; assert_eq!( secondary_pow_scaling(1, &(0..window).map(|_| hi.clone()).collect::>()), - 94 + 97 ); // all secondary on 1%, factor should go down to bound (divide by 2) assert_eq!( @@ -631,7 +600,7 @@ fn test_secondary_pow_scale() { .chain((0..(window * 95 / 100)).map(|_| hi.clone())) .collect::>() ), - 94 + 96 ); // 40% secondary, should come up based on 70 average assert_eq!( @@ -642,7 +611,7 @@ fn test_secondary_pow_scale() { .chain((0..(window * 4 / 10)).map(|_| hi.clone())) .collect::>() ), - 84 + 72 ); } diff --git a/servers/src/grin/server.rs b/servers/src/grin/server.rs index 89b1e3f9a..e8ace36d3 100644 --- a/servers/src/grin/server.rs +++ b/servers/src/grin/server.rs @@ -133,13 +133,10 @@ impl Server { )); let genesis = match config.chain_type { - global::ChainTypes::Testnet1 => genesis::genesis_testnet1(), - global::ChainTypes::Testnet2 => genesis::genesis_testnet2(), - global::ChainTypes::Testnet3 => genesis::genesis_testnet3(), - global::ChainTypes::Testnet4 => genesis::genesis_testnet4(), global::ChainTypes::AutomatedTesting => genesis::genesis_dev(), global::ChainTypes::UserTesting => genesis::genesis_dev(), - global::ChainTypes::Mainnet => genesis::genesis_testnet2(), //TODO: Fix, obviously + global::ChainTypes::Floonet => genesis::genesis_floo(), + global::ChainTypes::Mainnet => genesis::genesis_main(), }; info!("Starting server, genesis block: {}", genesis.hash()); diff --git a/wallet/src/types.rs b/wallet/src/types.rs index fcdd68f4b..3e25ae5fb 100644 --- a/wallet/src/types.rs +++ b/wallet/src/types.rs @@ -62,7 +62,7 @@ pub struct WalletConfig { impl Default for WalletConfig { fn default() -> WalletConfig { WalletConfig { - chain_type: Some(ChainTypes::Testnet4), + chain_type: Some(ChainTypes::Floonet), api_listen_interface: "127.0.0.1".to_string(), api_listen_port: 13415, api_secret_path: Some(".api_secret".to_string()), From 7812a9e8925ef8a5fb86c2a24fb5a89669a238e7 Mon Sep 17 00:00:00 2001 From: Yeastplume Date: Thu, 20 Dec 2018 13:10:36 +0000 Subject: [PATCH 20/27] [Floonet] Encrypt private slate data upon storage in DB (#2189) * xor encrypt stored nonce and blind sum in transaction data * rustfmt * stop doc tests splatting wallet files throughout --- wallet/src/libwallet/api.rs | 8 +++++ wallet/src/lmdb_wallet.rs | 66 +++++++++++++++++++++++++++++++++---- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/wallet/src/libwallet/api.rs b/wallet/src/libwallet/api.rs index 2dd9f88d1..a253a1de3 100644 --- a/wallet/src/libwallet/api.rs +++ b/wallet/src/libwallet/api.rs @@ -99,6 +99,7 @@ where /// use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; /// /// let mut wallet_config = WalletConfig::default(); + /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); /// /// // A NodeClient must first be created to handle communication between /// // the wallet and the node. @@ -148,6 +149,7 @@ where /// # use wallet::libwallet::api::APIOwner; /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; /// # let mut wallet_config = WalletConfig::default(); + /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); /// # let mut wallet:Arc>> = /// # Arc::new(Mutex::new( @@ -203,6 +205,7 @@ where /// # use wallet::libwallet::api::APIOwner; /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; /// # let mut wallet_config = WalletConfig::default(); + /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); /// # let mut wallet:Arc>> = /// # Arc::new(Mutex::new( @@ -256,6 +259,7 @@ where /// # use wallet::libwallet::api::APIOwner; /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; /// # let mut wallet_config = WalletConfig::default(); + /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); /// # let mut wallet:Arc>> = /// # Arc::new(Mutex::new( @@ -313,6 +317,7 @@ where /// # use wallet::libwallet::api::APIOwner; /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; /// # let mut wallet_config = WalletConfig::default(); + /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); /// # let mut wallet:Arc>> = /// # Arc::new(Mutex::new( @@ -389,6 +394,7 @@ where /// # use wallet::libwallet::api::APIOwner; /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; /// # let mut wallet_config = WalletConfig::default(); + /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); /// # let mut wallet:Arc>> = /// # Arc::new(Mutex::new( @@ -462,6 +468,7 @@ where /// # use wallet::libwallet::api::APIOwner; /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; /// # let mut wallet_config = WalletConfig::default(); + /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); /// # let mut wallet:Arc>> = /// # Arc::new(Mutex::new( @@ -575,6 +582,7 @@ where /// # use wallet::libwallet::api::APIOwner; /// # use wallet::{LMDBBackend, HTTPNodeClient, WalletBackend, WalletConfig}; /// # let mut wallet_config = WalletConfig::default(); + /// # wallet_config.data_file_dir = "test_output/doc/wallet1".to_owned(); /// # let node_client = HTTPNodeClient::new(&wallet_config.check_node_api_http_addr, None); /// # let mut wallet:Arc>> = /// # Arc::new(Mutex::new( diff --git a/wallet/src/lmdb_wallet.rs b/wallet/src/lmdb_wallet.rs index 49c015f5c..564bb4dd8 100644 --- a/wallet/src/lmdb_wallet.rs +++ b/wallet/src/lmdb_wallet.rs @@ -26,6 +26,8 @@ use serde_json; use failure::ResultExt; use uuid::Uuid; +use crate::blake2::blake2b::Blake2b; + use crate::keychain::{ChildNumber, ExtKeychain, Identifier, Keychain}; use crate::store::{self, option_to_not_found, to_key, to_key_u64}; @@ -35,6 +37,7 @@ use crate::libwallet::types::*; use crate::libwallet::{internal, Error, ErrorKind}; use crate::types::{WalletConfig, WalletSeed}; use crate::util; +use crate::util::secp::constants::SECRET_KEY_SIZE; use crate::util::secp::pedersen; pub const DB_DIR: &'static str = "db"; @@ -62,6 +65,39 @@ pub fn wallet_db_exists(config: WalletConfig) -> bool { db_path.exists() } +/// Helper to derive XOR keys for storing private transaction keys in the DB +/// (blind_xor_key, nonce_xor_key) +fn private_ctx_xor_keys( + keychain: &K, + slate_id: &[u8], +) -> Result<([u8; SECRET_KEY_SIZE], [u8; SECRET_KEY_SIZE]), Error> +where + K: Keychain, +{ + let root_key = keychain.derive_key(0, &K::root_key_id())?; + + // derive XOR values for storing secret values in DB + // h(root_key|slate_id|"blind") + let mut hasher = Blake2b::new(SECRET_KEY_SIZE); + hasher.update(&root_key.0[..]); + hasher.update(&slate_id[..]); + hasher.update(&"blind".as_bytes()[..]); + let blind_xor_key = hasher.finalize(); + let mut ret_blind = [0; SECRET_KEY_SIZE]; + ret_blind.copy_from_slice(&blind_xor_key.as_bytes()[0..SECRET_KEY_SIZE]); + + // h(root_key|slate_id|"nonce") + let mut hasher = Blake2b::new(SECRET_KEY_SIZE); + hasher.update(&root_key.0[..]); + hasher.update(&slate_id[..]); + hasher.update(&"nonce".as_bytes()[..]); + let nonce_xor_key = hasher.finalize(); + let mut ret_nonce = [0; SECRET_KEY_SIZE]; + ret_nonce.copy_from_slice(&nonce_xor_key.as_bytes()[0..SECRET_KEY_SIZE]); + + Ok((ret_blind, ret_nonce)) +} + pub struct LMDBBackend { db: store::Store, config: WalletConfig, @@ -232,11 +268,19 @@ where fn get_private_context(&mut self, slate_id: &[u8]) -> Result { let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec()); - option_to_not_found( + let (blind_xor_key, nonce_xor_key) = private_ctx_xor_keys(self.keychain(), slate_id)?; + + let mut ctx: Context = option_to_not_found( self.db.get_ser(&ctx_key), &format!("Slate id: {:x?}", slate_id.to_vec()), - ) - .map_err(|e| e.into()) + )?; + + for i in 0..SECRET_KEY_SIZE { + ctx.sec_key.0[i] = ctx.sec_key.0[i] ^ blind_xor_key[i]; + ctx.sec_nonce.0[i] = ctx.sec_nonce.0[i] ^ nonce_xor_key[i]; + } + + Ok(ctx) } fn acct_path_iter<'a>(&'a self) -> Box + 'a> { @@ -501,11 +545,21 @@ where self.save(out.clone()) } - //TODO: Keys stored unencrypted in DB.. not good - // should store keys as derivation paths instead fn save_private_context(&mut self, slate_id: &[u8], ctx: &Context) -> Result<(), Error> { let ctx_key = to_key(PRIVATE_TX_CONTEXT_PREFIX, &mut slate_id.to_vec()); - self.db.borrow().as_ref().unwrap().put_ser(&ctx_key, &ctx)?; + let (blind_xor_key, nonce_xor_key) = private_ctx_xor_keys(self.keychain(), slate_id)?; + + let mut s_ctx = ctx.clone(); + for i in 0..SECRET_KEY_SIZE { + s_ctx.sec_key.0[i] = s_ctx.sec_key.0[i] ^ blind_xor_key[i]; + s_ctx.sec_nonce.0[i] = s_ctx.sec_nonce.0[i] ^ nonce_xor_key[i]; + } + + self.db + .borrow() + .as_ref() + .unwrap() + .put_ser(&ctx_key, &s_ctx)?; Ok(()) } From b5fd06c2cbffa052bb9214e37f99b7ae1d3d6d62 Mon Sep 17 00:00:00 2001 From: yeastplume Date: Thu, 20 Dec 2018 13:15:46 +0000 Subject: [PATCH 21/27] Remove bzip2 dependency --- Cargo.lock | 22 ---------------------- util/Cargo.toml | 2 +- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff33ab8ac..c942ff751 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -192,24 +192,6 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bzip2" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bzip2-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cc" version = "1.0.25" @@ -2894,8 +2876,6 @@ name = "zip" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "msdos_time 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2927,8 +2907,6 @@ dependencies = [ "checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum bzip2 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42b7c3cbf0fa9c1b82308d57191728ca0256cb821220f4e2fd410a72ade26e3b" -"checksum bzip2-sys 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6584aa36f5ad4c9247f5323b0a42f37802b37a836f0ad87084d7a33961abe25f" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cexpr 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "42aac45e9567d97474a834efdee3081b3c942b2205be932092f53354ce503d6c" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" diff --git a/util/Cargo.toml b/util/Cargo.toml index cf2d22ad9..03a6b5851 100644 --- a/util/Cargo.toml +++ b/util/Cargo.toml @@ -20,7 +20,7 @@ serde_derive = "1" log4rs = { version = "0.8.1", features = ["rolling_file_appender", "compound_policy", "size_trigger", "fixed_window_roller"] } log = "0.4" walkdir = "2" -zip = "0.4" +zip = { version = "0.4", default-features = false } parking_lot = {version = "0.6"} [dependencies.grin_secp256k1zkp] From 7284cfec72d00122529e35b8caf65ffce2f5a756 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Thu, 20 Dec 2018 11:08:01 -0800 Subject: [PATCH 22/27] Changed magic number and seeds for Floonet (#2188) * Changed magic number and seeds for Floonet. * Genesis generator now loads a local wallet seed to build coinbase. --- etc/gen_gen/Cargo.toml | 16 +++++++++++----- etc/gen_gen/src/bin/gen_gen.rs | 23 +++++++++++++++++++---- p2p/src/msg.rs | 2 +- servers/src/grin/seed.rs | 15 ++++++++++++--- 4 files changed, 43 insertions(+), 13 deletions(-) diff --git a/etc/gen_gen/Cargo.toml b/etc/gen_gen/Cargo.toml index f1d394592..ae0c73829 100644 --- a/etc/gen_gen/Cargo.toml +++ b/etc/gen_gen/Cargo.toml @@ -17,14 +17,20 @@ path = "src/bin/gen_gen.rs" chrono = "0.4.4" cuckoo_miner = "0.4.2" curl = "0.4.19" -grin_core = "0.4.2" -grin_chain = "0.4.2" -grin_keychain = "0.4.2" +grin_core = { path = "../../core" } +grin_chain = { path = "../../chain" } +grin_keychain = { path = "../../keychain" } grin_miner_plugin = "0.4.2" -grin_store = "0.4.2" -grin_util = "0.4.2" +grin_store = { path = "../../store" } +grin_util = { path = "../../util" } +grin_wallet = { path = "../../wallet" } +rpassword = "2.0.0" serde_json = "1" [patch.crates-io] +grin_api = { path = "../../api" } grin_core = { path = "../../core" } +grin_chain = { path = "../../chain" } grin_keychain = { path = "../../keychain" } +grin_util = { path = "../../util" } +grin_wallet = { path = "../../wallet" } diff --git a/etc/gen_gen/src/bin/gen_gen.rs b/etc/gen_gen/src/bin/gen_gen.rs index 037e0b3e7..874480b5f 100644 --- a/etc/gen_gen/src/bin/gen_gen.rs +++ b/etc/gen_gen/src/bin/gen_gen.rs @@ -21,6 +21,7 @@ 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; @@ -29,6 +30,7 @@ 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; @@ -40,6 +42,7 @@ 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() { @@ -54,6 +57,12 @@ fn main() { 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(); @@ -72,10 +81,14 @@ fn main() { gen.header.timestamp = Utc::now() + Duration::minutes(30); gen.header.prev_root = core::core::hash::Hash::from_hex(&h1).unwrap(); - // TODO get the proper keychain and/or raw coinbase - let keychain = ExtKeychain::from_random_seed().unwrap(); - let key_id = ExtKeychain::derive_key_id(0, 1, 0, 0, 0); - let reward = core::libtx::reward::output(&keychain, &key_id, 0, 0).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); { @@ -284,6 +297,7 @@ fn setup_chain(dir_name: &str, genesis: core::core::Block) -> chain::Chain { core::pow::verify_size, verifier_cache, false, + Arc::new(util::Mutex::new(util::StopState::new())), ) .unwrap() } @@ -322,3 +336,4 @@ fn get_json(url: &str) -> serde_json::Value { } serde_json::from_slice(&body).unwrap() } + diff --git a/p2p/src/msg.rs b/p2p/src/msg.rs index 6e77ac076..f347cbed7 100644 --- a/p2p/src/msg.rs +++ b/p2p/src/msg.rs @@ -36,7 +36,7 @@ pub const PROTOCOL_VERSION: u32 = 1; pub const USER_AGENT: &'static str = concat!("MW/Grin ", env!("CARGO_PKG_VERSION")); /// Magic number expected in the header of every message -const MAGIC: [u8; 2] = [0x54, 0x34]; +const MAGIC: [u8; 2] = [0x53, 0x35]; /// Max theoretical size of a block filled with outputs. const MAX_BLOCK_SIZE: u64 = diff --git a/servers/src/grin/seed.rs b/servers/src/grin/seed.rs index 3e5a39117..e79d23e11 100644 --- a/servers/src/grin/seed.rs +++ b/servers/src/grin/seed.rs @@ -24,14 +24,18 @@ use std::net::{SocketAddr, ToSocketAddrs}; use std::sync::{mpsc, Arc}; use std::{cmp, io, str, thread, time}; +use crate::core::global; use crate::p2p; use crate::p2p::ChainAdapter; use crate::pool::DandelionConfig; use crate::util::{Mutex, StopState}; // DNS Seeds with contact email associated -const DNS_SEEDS: &'static [&'static str] = &[ - "t4.seed.grin-tech.org", // igno.peverell@protonmail.com +const MAINNET_DNS_SEEDS: &'static [&'static str] = &[ + "mainnet.seed.grin-tech.org", // igno.peverell@protonmail.com +]; +const FLOONET_DNS_SEEDS: &'static [&'static str] = &[ + "floonet.seed.grin-tech.org", // igno.peverell@protonmail.com ]; pub fn connect_and_monitor( @@ -331,7 +335,12 @@ fn listen_for_addrs( pub fn dns_seeds() -> Box Vec + Send> { Box::new(|| { let mut addresses: Vec = vec![]; - for dns_seed in DNS_SEEDS { + let net_seeds = if global::is_testnet() { + FLOONET_DNS_SEEDS + } else { + MAINNET_DNS_SEEDS + }; + for dns_seed in net_seeds { let temp_addresses = addresses.clone(); debug!("Retrieving seed nodes from dns {}", dns_seed); match (dns_seed.to_owned(), 0).to_socket_addrs() { From 439a3915f6f8dcf7d6e099888dcc89551ba909a0 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Thu, 20 Dec 2018 20:34:25 +0000 Subject: [PATCH 23/27] Floonet genesis block --- core/src/genesis.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/core/src/genesis.rs b/core/src/genesis.rs index 6eba2cdb3..cb4474987 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -51,20 +51,20 @@ pub fn genesis_dev() -> core::Block { pub fn genesis_floo() -> core::Block { let gen = core::Block::with_header(core::BlockHeader { height: 0, - timestamp: Utc.ymd(2018, 12, 20).and_hms(20, 0, 0), // REPLACE - prev_root: Hash::default(), // REPLACE - output_root: Hash::default(), // REPLACE - range_proof_root: Hash::default(), // REPLACE - kernel_root: Hash::default(), // REPLACE - total_kernel_offset: BlindingFactor::zero(), // REPLACE +timestamp: Utc.ymd(2018, 12, 20).and_hms(20, 58, 32), +prev_root: Hash::from_hex("ae144568a9ec32faf57e9ca5b5f0997d33f30bd3352fd84c953e6526d847c26b").unwrap(), +output_root: Hash::from_hex("47d2570266451203c62cd003c706e3ec37e9cb4292316744abfa68a1b133bc1c").unwrap(), +range_proof_root: Hash::from_hex("53ea93e80fe37e9a0cbb9c1a1ddf467213922481a4435921aacf55ffb3f388fc").unwrap(), +kernel_root: Hash::from_hex("3ff7655b2846a1313dd72e1c516a2fa262638fabc8e0d4c1dddf80773bbd472d").unwrap(), +total_kernel_offset: BlindingFactor::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(), output_mmr_size: 1, kernel_mmr_size: 1, pow: ProofOfWork { total_difficulty: Difficulty::from_num(10_u64.pow(6)), secondary_scaling: 1856, - nonce: 1, // REPLACE +nonce: 22, proof: Proof { - nonces: vec![0; 42], // REPLACE +nonces: vec![48398361, 50434294, 73758991, 93493375, 94716564, 101961133, 153506566, 159476458, 164019912, 208165915, 216747111, 218441011, 221663358, 262514197, 264746362, 278423427, 282069592, 284508695, 297003554, 327321117, 327780367, 329474453, 333639856, 356316379, 366419120, 381872178, 386038638, 389726932, 390055244, 392425788, 399530286, 426997994, 436531599, 456084550, 456375883, 459156409, 474067792, 480904139, 487380747, 489307817, 496780560, 530227836], edge_bits: 29, }, }, @@ -74,15 +74,15 @@ pub fn genesis_floo() -> core::Block { features: core::KernelFeatures::COINBASE, fee: 0, lock_height: 0, - excess: Commitment::from_vec(vec![]), // REPLACE - excess_sig: Signature::from_raw_data(&[0; 64]).unwrap(), //REPLACE +excess: Commitment::from_vec(util::from_hex("0817a9e97a070ba5f9fa185c093b4b13b262ed4b4712b6f7c92881b27168f9a2cb".to_string()).unwrap()), +excess_sig: Signature::from_raw_data(&[172, 131, 105, 224, 31, 11, 0, 70, 109, 54, 230, 184, 177, 138, 46, 137, 202, 215, 152, 37, 192, 132, 88, 254, 110, 76, 57, 32, 42, 13, 19, 89, 82, 89, 116, 66, 30, 132, 120, 148, 122, 100, 97, 38, 141, 219, 57, 184, 171, 130, 213, 235, 83, 202, 69, 13, 213, 60, 150, 172, 33, 37, 209, 57]).unwrap(), }; let output = core::Output { features: core::OutputFeatures::COINBASE, - commit: Commitment::from_vec(vec![]), // REPLACE +commit: Commitment::from_vec(util::from_hex("08f5523cbd8b2e1dae3eefdd9dd1069e0c8a7f055a0611da79f42530c5de0d044b".to_string()).unwrap()), proof: RangeProof { plen: SINGLE_BULLET_PROOF_SIZE, - proof: [0; SINGLE_BULLET_PROOF_SIZE], // REPLACE +proof: [47, 196, 194, 238, 233, 164, 218, 64, 54, 92, 83, 248, 225, 116, 189, 225, 202, 66, 213, 63, 195, 209, 238, 189, 153, 198, 231, 219, 3, 146, 102, 67, 26, 7, 199, 150, 160, 244, 48, 166, 113, 6, 241, 49, 133, 248, 201, 80, 34, 19, 118, 249, 44, 213, 215, 235, 228, 187, 215, 116, 212, 203, 232, 183, 12, 66, 29, 11, 28, 17, 212, 104, 126, 203, 103, 60, 176, 149, 182, 206, 70, 138, 180, 213, 76, 99, 25, 184, 40, 177, 197, 179, 71, 63, 19, 72, 253, 129, 115, 107, 90, 249, 39, 108, 134, 10, 231, 172, 172, 59, 207, 118, 175, 124, 197, 132, 73, 154, 148, 8, 73, 26, 231, 75, 24, 134, 199, 93, 15, 43, 45, 49, 69, 167, 194, 23, 114, 16, 117, 209, 127, 123, 18, 209, 12, 34, 219, 196, 37, 7, 226, 132, 70, 111, 113, 164, 203, 175, 105, 175, 196, 62, 225, 138, 162, 176, 190, 109, 96, 210, 15, 38, 245, 200, 83, 155, 185, 111, 85, 234, 6, 3, 246, 98, 175, 127, 94, 65, 29, 78, 27, 53, 32, 230, 85, 91, 195, 112, 84, 135, 56, 207, 213, 165, 40, 248, 238, 202, 225, 142, 79, 89, 81, 197, 138, 65, 14, 232, 145, 44, 73, 6, 43, 8, 43, 42, 127, 151, 68, 18, 19, 83, 14, 142, 180, 75, 25, 4, 97, 166, 237, 212, 187, 106, 154, 36, 223, 231, 177, 58, 70, 1, 195, 113, 144, 151, 45, 185, 0, 174, 116, 212, 122, 239, 96, 1, 122, 211, 41, 96, 230, 110, 242, 145, 176, 230, 55, 143, 142, 234, 151, 49, 151, 109, 252, 120, 147, 244, 178, 73, 196, 221, 150, 85, 69, 113, 50, 166, 92, 91, 98, 188, 77, 76, 48, 192, 112, 184, 108, 143, 134, 56, 46, 119, 21, 71, 247, 119, 133, 225, 72, 15, 158, 60, 64, 71, 57, 134, 243, 228, 58, 13, 58, 209, 71, 4, 72, 87, 129, 51, 46, 64, 188, 60, 157, 56, 120, 23, 2, 47, 143, 79, 176, 54, 3, 47, 227, 124, 70, 242, 8, 59, 113, 203, 51, 65, 138, 131, 121, 45, 131, 132, 171, 161, 49, 235, 129, 39, 164, 234, 69, 172, 95, 28, 180, 118, 163, 151, 148, 66, 65, 104, 222, 232, 154, 22, 30, 149, 196, 214, 163, 93, 76, 128, 142, 233, 106, 171, 213, 148, 59, 101, 56, 22, 127, 232, 4, 63, 111, 9, 188, 163, 40, 158, 24, 65, 81, 203, 231, 93, 197, 102, 170, 70, 239, 229, 13, 172, 110, 157, 226, 112, 182, 28, 150, 222, 62, 224, 94, 182, 220, 243, 236, 62, 156, 129, 220, 127, 155, 141, 0, 243, 159, 113, 28, 158, 95, 205, 35, 72, 132, 46, 235, 176, 146, 233, 93, 111, 4, 105, 236, 176, 165, 102, 168, 188, 121, 105, 175, 197, 114, 97, 40, 2, 165, 153, 85, 135, 114, 147, 95, 216, 50, 108, 52, 225, 186, 215, 110, 122, 230, 14, 246, 141, 180, 41, 22, 132, 58, 8, 31, 187, 221, 231, 14, 33, 52, 88, 219, 200, 77, 246, 134, 18, 0, 113, 144, 6, 146, 54, 24, 113, 14, 64, 182, 116, 229, 250, 201, 126, 84, 192, 80, 13, 57, 232, 55, 113, 139, 249, 166, 231, 123, 101, 236, 147, 144, 2, 9, 51, 2, 189, 188, 200, 66, 29, 16, 22, 150, 45, 220, 15, 161, 180, 214, 244, 104, 41, 77, 171, 246, 243, 56, 47, 63, 103, 216, 151, 199, 249, 169, 165, 119, 200, 243, 161, 83, 46, 225, 195, 92, 96, 150, 0, 165, 170, 14, 211, 226, 244, 70, 218, 137, 254, 197, 175, 208, 119, 199, 121, 4, 7, 190, 118, 55, 197, 208, 41, 109, 161, 34, 33, 210, 58, 99, 81, 97, 57, 156, 57, 144, 83, 97, 49, 248, 89, 201, 88, 169, 9, 211, 34, 136, 174, 195, 224, 51, 103, 12, 237, 172, 46, 216, 5, 168], }, }; gen.with_reward(output, kernel) From 84d4777545bcbf88d18f24c375222f3bc68aab98 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Thu, 20 Dec 2018 21:04:57 +0000 Subject: [PATCH 24/27] Add floonet to generated grin-server.toml comments --- config/src/comments.rs | 5 +- core/src/genesis.rs | 107 +++++++++++++++++++++++++++++++++++------ 2 files changed, 93 insertions(+), 19 deletions(-) diff --git a/config/src/comments.rs b/config/src/comments.rs index b8a62bb46..31eb398ed 100644 --- a/config/src/comments.rs +++ b/config/src/comments.rs @@ -73,10 +73,7 @@ fn comments() -> HashMap { #parameters used for mining as well as wallet output coinbase maturity. Can be: #AutomatedTesting - For CI builds and instant blockchain creation #UserTesting - For regular user testing (cuckoo 16) -#Testnet1 - Testnet1 genesis block (cuckoo 16) -#Testnet2 - Testnet2 genesis block (cuckoo 30) -#Testnet3 - Testnet3 genesis block (cuckoo 30) -#Testnet4 - Testnet4 genesis block (cuckatoo 29+) +#Floonet - For the long term Floonet test network " .to_string(), ); diff --git a/core/src/genesis.rs b/core/src/genesis.rs index cb4474987..abb555f7e 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -51,20 +51,42 @@ pub fn genesis_dev() -> core::Block { pub fn genesis_floo() -> core::Block { let gen = core::Block::with_header(core::BlockHeader { height: 0, -timestamp: Utc.ymd(2018, 12, 20).and_hms(20, 58, 32), -prev_root: Hash::from_hex("ae144568a9ec32faf57e9ca5b5f0997d33f30bd3352fd84c953e6526d847c26b").unwrap(), -output_root: Hash::from_hex("47d2570266451203c62cd003c706e3ec37e9cb4292316744abfa68a1b133bc1c").unwrap(), -range_proof_root: Hash::from_hex("53ea93e80fe37e9a0cbb9c1a1ddf467213922481a4435921aacf55ffb3f388fc").unwrap(), -kernel_root: Hash::from_hex("3ff7655b2846a1313dd72e1c516a2fa262638fabc8e0d4c1dddf80773bbd472d").unwrap(), -total_kernel_offset: BlindingFactor::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap(), + timestamp: Utc.ymd(2018, 12, 20).and_hms(20, 58, 32), + prev_root: Hash::from_hex( + "ae144568a9ec32faf57e9ca5b5f0997d33f30bd3352fd84c953e6526d847c26b", + ) + .unwrap(), + output_root: Hash::from_hex( + "47d2570266451203c62cd003c706e3ec37e9cb4292316744abfa68a1b133bc1c", + ) + .unwrap(), + range_proof_root: Hash::from_hex( + "53ea93e80fe37e9a0cbb9c1a1ddf467213922481a4435921aacf55ffb3f388fc", + ) + .unwrap(), + kernel_root: Hash::from_hex( + "3ff7655b2846a1313dd72e1c516a2fa262638fabc8e0d4c1dddf80773bbd472d", + ) + .unwrap(), + total_kernel_offset: BlindingFactor::from_hex( + "0000000000000000000000000000000000000000000000000000000000000000", + ) + .unwrap(), output_mmr_size: 1, kernel_mmr_size: 1, pow: ProofOfWork { total_difficulty: Difficulty::from_num(10_u64.pow(6)), secondary_scaling: 1856, -nonce: 22, + nonce: 22, proof: Proof { -nonces: vec![48398361, 50434294, 73758991, 93493375, 94716564, 101961133, 153506566, 159476458, 164019912, 208165915, 216747111, 218441011, 221663358, 262514197, 264746362, 278423427, 282069592, 284508695, 297003554, 327321117, 327780367, 329474453, 333639856, 356316379, 366419120, 381872178, 386038638, 389726932, 390055244, 392425788, 399530286, 426997994, 436531599, 456084550, 456375883, 459156409, 474067792, 480904139, 487380747, 489307817, 496780560, 530227836], + nonces: vec![ + 48398361, 50434294, 73758991, 93493375, 94716564, 101961133, 153506566, + 159476458, 164019912, 208165915, 216747111, 218441011, 221663358, 262514197, + 264746362, 278423427, 282069592, 284508695, 297003554, 327321117, 327780367, + 329474453, 333639856, 356316379, 366419120, 381872178, 386038638, 389726932, + 390055244, 392425788, 399530286, 426997994, 436531599, 456084550, 456375883, + 459156409, 474067792, 480904139, 487380747, 489307817, 496780560, 530227836, + ], edge_bits: 29, }, }, @@ -74,15 +96,70 @@ nonces: vec![48398361, 50434294, 73758991, 93493375, 94716564, 101961133, 153506 features: core::KernelFeatures::COINBASE, fee: 0, lock_height: 0, -excess: Commitment::from_vec(util::from_hex("0817a9e97a070ba5f9fa185c093b4b13b262ed4b4712b6f7c92881b27168f9a2cb".to_string()).unwrap()), -excess_sig: Signature::from_raw_data(&[172, 131, 105, 224, 31, 11, 0, 70, 109, 54, 230, 184, 177, 138, 46, 137, 202, 215, 152, 37, 192, 132, 88, 254, 110, 76, 57, 32, 42, 13, 19, 89, 82, 89, 116, 66, 30, 132, 120, 148, 122, 100, 97, 38, 141, 219, 57, 184, 171, 130, 213, 235, 83, 202, 69, 13, 213, 60, 150, 172, 33, 37, 209, 57]).unwrap(), + excess: Commitment::from_vec( + util::from_hex( + "0817a9e97a070ba5f9fa185c093b4b13b262ed4b4712b6f7c92881b27168f9a2cb".to_string(), + ) + .unwrap(), + ), + excess_sig: Signature::from_raw_data(&[ + 172, 131, 105, 224, 31, 11, 0, 70, 109, 54, 230, 184, 177, 138, 46, 137, 202, 215, 152, + 37, 192, 132, 88, 254, 110, 76, 57, 32, 42, 13, 19, 89, 82, 89, 116, 66, 30, 132, 120, + 148, 122, 100, 97, 38, 141, 219, 57, 184, 171, 130, 213, 235, 83, 202, 69, 13, 213, 60, + 150, 172, 33, 37, 209, 57, + ]) + .unwrap(), }; let output = core::Output { features: core::OutputFeatures::COINBASE, -commit: Commitment::from_vec(util::from_hex("08f5523cbd8b2e1dae3eefdd9dd1069e0c8a7f055a0611da79f42530c5de0d044b".to_string()).unwrap()), + commit: Commitment::from_vec( + util::from_hex( + "08f5523cbd8b2e1dae3eefdd9dd1069e0c8a7f055a0611da79f42530c5de0d044b".to_string(), + ) + .unwrap(), + ), proof: RangeProof { plen: SINGLE_BULLET_PROOF_SIZE, -proof: [47, 196, 194, 238, 233, 164, 218, 64, 54, 92, 83, 248, 225, 116, 189, 225, 202, 66, 213, 63, 195, 209, 238, 189, 153, 198, 231, 219, 3, 146, 102, 67, 26, 7, 199, 150, 160, 244, 48, 166, 113, 6, 241, 49, 133, 248, 201, 80, 34, 19, 118, 249, 44, 213, 215, 235, 228, 187, 215, 116, 212, 203, 232, 183, 12, 66, 29, 11, 28, 17, 212, 104, 126, 203, 103, 60, 176, 149, 182, 206, 70, 138, 180, 213, 76, 99, 25, 184, 40, 177, 197, 179, 71, 63, 19, 72, 253, 129, 115, 107, 90, 249, 39, 108, 134, 10, 231, 172, 172, 59, 207, 118, 175, 124, 197, 132, 73, 154, 148, 8, 73, 26, 231, 75, 24, 134, 199, 93, 15, 43, 45, 49, 69, 167, 194, 23, 114, 16, 117, 209, 127, 123, 18, 209, 12, 34, 219, 196, 37, 7, 226, 132, 70, 111, 113, 164, 203, 175, 105, 175, 196, 62, 225, 138, 162, 176, 190, 109, 96, 210, 15, 38, 245, 200, 83, 155, 185, 111, 85, 234, 6, 3, 246, 98, 175, 127, 94, 65, 29, 78, 27, 53, 32, 230, 85, 91, 195, 112, 84, 135, 56, 207, 213, 165, 40, 248, 238, 202, 225, 142, 79, 89, 81, 197, 138, 65, 14, 232, 145, 44, 73, 6, 43, 8, 43, 42, 127, 151, 68, 18, 19, 83, 14, 142, 180, 75, 25, 4, 97, 166, 237, 212, 187, 106, 154, 36, 223, 231, 177, 58, 70, 1, 195, 113, 144, 151, 45, 185, 0, 174, 116, 212, 122, 239, 96, 1, 122, 211, 41, 96, 230, 110, 242, 145, 176, 230, 55, 143, 142, 234, 151, 49, 151, 109, 252, 120, 147, 244, 178, 73, 196, 221, 150, 85, 69, 113, 50, 166, 92, 91, 98, 188, 77, 76, 48, 192, 112, 184, 108, 143, 134, 56, 46, 119, 21, 71, 247, 119, 133, 225, 72, 15, 158, 60, 64, 71, 57, 134, 243, 228, 58, 13, 58, 209, 71, 4, 72, 87, 129, 51, 46, 64, 188, 60, 157, 56, 120, 23, 2, 47, 143, 79, 176, 54, 3, 47, 227, 124, 70, 242, 8, 59, 113, 203, 51, 65, 138, 131, 121, 45, 131, 132, 171, 161, 49, 235, 129, 39, 164, 234, 69, 172, 95, 28, 180, 118, 163, 151, 148, 66, 65, 104, 222, 232, 154, 22, 30, 149, 196, 214, 163, 93, 76, 128, 142, 233, 106, 171, 213, 148, 59, 101, 56, 22, 127, 232, 4, 63, 111, 9, 188, 163, 40, 158, 24, 65, 81, 203, 231, 93, 197, 102, 170, 70, 239, 229, 13, 172, 110, 157, 226, 112, 182, 28, 150, 222, 62, 224, 94, 182, 220, 243, 236, 62, 156, 129, 220, 127, 155, 141, 0, 243, 159, 113, 28, 158, 95, 205, 35, 72, 132, 46, 235, 176, 146, 233, 93, 111, 4, 105, 236, 176, 165, 102, 168, 188, 121, 105, 175, 197, 114, 97, 40, 2, 165, 153, 85, 135, 114, 147, 95, 216, 50, 108, 52, 225, 186, 215, 110, 122, 230, 14, 246, 141, 180, 41, 22, 132, 58, 8, 31, 187, 221, 231, 14, 33, 52, 88, 219, 200, 77, 246, 134, 18, 0, 113, 144, 6, 146, 54, 24, 113, 14, 64, 182, 116, 229, 250, 201, 126, 84, 192, 80, 13, 57, 232, 55, 113, 139, 249, 166, 231, 123, 101, 236, 147, 144, 2, 9, 51, 2, 189, 188, 200, 66, 29, 16, 22, 150, 45, 220, 15, 161, 180, 214, 244, 104, 41, 77, 171, 246, 243, 56, 47, 63, 103, 216, 151, 199, 249, 169, 165, 119, 200, 243, 161, 83, 46, 225, 195, 92, 96, 150, 0, 165, 170, 14, 211, 226, 244, 70, 218, 137, 254, 197, 175, 208, 119, 199, 121, 4, 7, 190, 118, 55, 197, 208, 41, 109, 161, 34, 33, 210, 58, 99, 81, 97, 57, 156, 57, 144, 83, 97, 49, 248, 89, 201, 88, 169, 9, 211, 34, 136, 174, 195, 224, 51, 103, 12, 237, 172, 46, 216, 5, 168], + proof: [ + 47, 196, 194, 238, 233, 164, 218, 64, 54, 92, 83, 248, 225, 116, 189, 225, 202, 66, + 213, 63, 195, 209, 238, 189, 153, 198, 231, 219, 3, 146, 102, 67, 26, 7, 199, 150, + 160, 244, 48, 166, 113, 6, 241, 49, 133, 248, 201, 80, 34, 19, 118, 249, 44, 213, + 215, 235, 228, 187, 215, 116, 212, 203, 232, 183, 12, 66, 29, 11, 28, 17, 212, 104, + 126, 203, 103, 60, 176, 149, 182, 206, 70, 138, 180, 213, 76, 99, 25, 184, 40, 177, + 197, 179, 71, 63, 19, 72, 253, 129, 115, 107, 90, 249, 39, 108, 134, 10, 231, 172, + 172, 59, 207, 118, 175, 124, 197, 132, 73, 154, 148, 8, 73, 26, 231, 75, 24, 134, + 199, 93, 15, 43, 45, 49, 69, 167, 194, 23, 114, 16, 117, 209, 127, 123, 18, 209, + 12, 34, 219, 196, 37, 7, 226, 132, 70, 111, 113, 164, 203, 175, 105, 175, 196, 62, + 225, 138, 162, 176, 190, 109, 96, 210, 15, 38, 245, 200, 83, 155, 185, 111, 85, + 234, 6, 3, 246, 98, 175, 127, 94, 65, 29, 78, 27, 53, 32, 230, 85, 91, 195, 112, + 84, 135, 56, 207, 213, 165, 40, 248, 238, 202, 225, 142, 79, 89, 81, 197, 138, 65, + 14, 232, 145, 44, 73, 6, 43, 8, 43, 42, 127, 151, 68, 18, 19, 83, 14, 142, 180, 75, + 25, 4, 97, 166, 237, 212, 187, 106, 154, 36, 223, 231, 177, 58, 70, 1, 195, 113, + 144, 151, 45, 185, 0, 174, 116, 212, 122, 239, 96, 1, 122, 211, 41, 96, 230, 110, + 242, 145, 176, 230, 55, 143, 142, 234, 151, 49, 151, 109, 252, 120, 147, 244, 178, + 73, 196, 221, 150, 85, 69, 113, 50, 166, 92, 91, 98, 188, 77, 76, 48, 192, 112, + 184, 108, 143, 134, 56, 46, 119, 21, 71, 247, 119, 133, 225, 72, 15, 158, 60, 64, + 71, 57, 134, 243, 228, 58, 13, 58, 209, 71, 4, 72, 87, 129, 51, 46, 64, 188, 60, + 157, 56, 120, 23, 2, 47, 143, 79, 176, 54, 3, 47, 227, 124, 70, 242, 8, 59, 113, + 203, 51, 65, 138, 131, 121, 45, 131, 132, 171, 161, 49, 235, 129, 39, 164, 234, 69, + 172, 95, 28, 180, 118, 163, 151, 148, 66, 65, 104, 222, 232, 154, 22, 30, 149, 196, + 214, 163, 93, 76, 128, 142, 233, 106, 171, 213, 148, 59, 101, 56, 22, 127, 232, 4, + 63, 111, 9, 188, 163, 40, 158, 24, 65, 81, 203, 231, 93, 197, 102, 170, 70, 239, + 229, 13, 172, 110, 157, 226, 112, 182, 28, 150, 222, 62, 224, 94, 182, 220, 243, + 236, 62, 156, 129, 220, 127, 155, 141, 0, 243, 159, 113, 28, 158, 95, 205, 35, 72, + 132, 46, 235, 176, 146, 233, 93, 111, 4, 105, 236, 176, 165, 102, 168, 188, 121, + 105, 175, 197, 114, 97, 40, 2, 165, 153, 85, 135, 114, 147, 95, 216, 50, 108, 52, + 225, 186, 215, 110, 122, 230, 14, 246, 141, 180, 41, 22, 132, 58, 8, 31, 187, 221, + 231, 14, 33, 52, 88, 219, 200, 77, 246, 134, 18, 0, 113, 144, 6, 146, 54, 24, 113, + 14, 64, 182, 116, 229, 250, 201, 126, 84, 192, 80, 13, 57, 232, 55, 113, 139, 249, + 166, 231, 123, 101, 236, 147, 144, 2, 9, 51, 2, 189, 188, 200, 66, 29, 16, 22, 150, + 45, 220, 15, 161, 180, 214, 244, 104, 41, 77, 171, 246, 243, 56, 47, 63, 103, 216, + 151, 199, 249, 169, 165, 119, 200, 243, 161, 83, 46, 225, 195, 92, 96, 150, 0, 165, + 170, 14, 211, 226, 244, 70, 218, 137, 254, 197, 175, 208, 119, 199, 121, 4, 7, 190, + 118, 55, 197, 208, 41, 109, 161, 34, 33, 210, 58, 99, 81, 97, 57, 156, 57, 144, 83, + 97, 49, 248, 89, 201, 88, 169, 9, 211, 34, 136, 174, 195, 224, 51, 103, 12, 237, + 172, 46, 216, 5, 168, + ], }, }; gen.with_reward(output, kernel) @@ -133,17 +210,17 @@ pub fn genesis_main() -> core::Block { #[cfg(test)] mod test { use super::*; - use crate::ser; use crate::core::hash::Hashed; + use crate::ser; - // TODO hardcode the hashes once genesis is set #[test] fn floonet_genesis_hash() { let gen_hash = genesis_floo().hash(); println!("floonet genesis hash: {}", gen_hash.to_hex()); let gen_bin = ser::ser_vec(&genesis_floo()).unwrap(); println!("floonet genesis full hash: {}\n", gen_bin.hash().to_hex()); - //assert_eq!(gene_hash.to_hex, ""); + assert_eq!(gen_hash.to_hex(), "cb272478ee4abbf41a3d8cc8f2f828785cf38bd7f0dcacfdd6db5f8f2d8f6e24"); + assert_eq!(gen_bin.hash().to_hex(), "5fcc7afebc2dcfb98f982dd4d9ff7878fca45038d22677ef6360745c90505035"); } // TODO hardcode the hashes once genesis is set From 5faeeedf654efeb045b983d513b5f372c1497383 Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Thu, 20 Dec 2018 21:07:53 +0000 Subject: [PATCH 25/27] Test with final Floonet genesis hashes --- core/src/genesis.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/core/src/genesis.rs b/core/src/genesis.rs index abb555f7e..25e3a661d 100644 --- a/core/src/genesis.rs +++ b/core/src/genesis.rs @@ -219,8 +219,14 @@ mod test { println!("floonet genesis hash: {}", gen_hash.to_hex()); let gen_bin = ser::ser_vec(&genesis_floo()).unwrap(); println!("floonet genesis full hash: {}\n", gen_bin.hash().to_hex()); - assert_eq!(gen_hash.to_hex(), "cb272478ee4abbf41a3d8cc8f2f828785cf38bd7f0dcacfdd6db5f8f2d8f6e24"); - assert_eq!(gen_bin.hash().to_hex(), "5fcc7afebc2dcfb98f982dd4d9ff7878fca45038d22677ef6360745c90505035"); + assert_eq!( + gen_hash.to_hex(), + "cb272478ee4abbf41a3d8cc8f2f828785cf38bd7f0dcacfdd6db5f8f2d8f6e24" + ); + assert_eq!( + gen_bin.hash().to_hex(), + "5fcc7afebc2dcfb98f982dd4d9ff7878fca45038d22677ef6360745c90505035" + ); } // TODO hardcode the hashes once genesis is set From cab438efcb6fb001ec981a52d99f7267634944dc Mon Sep 17 00:00:00 2001 From: Ignotus Peverell Date: Thu, 20 Dec 2018 13:52:45 -0800 Subject: [PATCH 26/27] Fix get_header_for_output for genesis (#2192) --- chain/src/chain.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 70ab100ec..97e86ea9d 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -1139,6 +1139,9 @@ impl Chain { loop { let search_height = max - (max - min) / 2; let h = txhashset.get_header_by_height(search_height)?; + if search_height == 0 { + return Ok(h); + } let h_prev = txhashset.get_header_by_height(search_height - 1)?; if pos > h.output_mmr_size { min = search_height; From bf427672104fa7b8ed3738b99c4e3aea24428fbe Mon Sep 17 00:00:00 2001 From: Antioch Peverell Date: Thu, 20 Dec 2018 22:37:13 +0000 Subject: [PATCH 27/27] start search with min height 0 (#2195) --- chain/src/chain.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chain/src/chain.rs b/chain/src/chain.rs index 97e86ea9d..1afd67006 100644 --- a/chain/src/chain.rs +++ b/chain/src/chain.rs @@ -1130,7 +1130,7 @@ impl Chain { let (_, pos) = txhashset.is_unspent(output_ref)?; - let mut min = 1; + let mut min = 0; let mut max = { let head = self.head()?; head.height