-
Notifications
You must be signed in to change notification settings - Fork 989
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
HardFork3 #3334
HardFork3 #3334
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -133,12 +133,18 @@ pub const FLOONET_FIRST_HARD_FORK: u64 = 185_040; | |
/// Floonet second hard fork height, set to happen around 2019-12-19 | ||
pub const FLOONET_SECOND_HARD_FORK: u64 = 298_080; | ||
|
||
/// Floonet second hard fork height, set to happen around 2020-06-20 | ||
pub const FLOONET_THIRD_HARD_FORK: u64 = 552_960; | ||
|
||
/// AutomatedTesting and UserTesting first hard fork height. | ||
pub const TESTING_FIRST_HARD_FORK: u64 = 3; | ||
|
||
/// AutomatedTesting and UserTesting second hard fork height. | ||
pub const TESTING_SECOND_HARD_FORK: u64 = 6; | ||
|
||
/// AutomatedTesting and UserTesting third hard fork height. | ||
pub const TESTING_THIRD_HARD_FORK: u64 = 9; | ||
tromp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
/// Compute possible block version at a given height, implements | ||
/// 6 months interval scheduled hard forks for the first 2 years. | ||
pub fn header_version(height: u64) -> HeaderVersion { | ||
|
@@ -151,8 +157,10 @@ pub fn header_version(height: u64) -> HeaderVersion { | |
HeaderVersion(1) | ||
} else if height < FLOONET_SECOND_HARD_FORK { | ||
HeaderVersion(2) | ||
} else if height < 3 * HARD_FORK_INTERVAL { | ||
} else if height < FLOONET_THIRD_HARD_FORK { | ||
HeaderVersion(3) | ||
} else if height < 4 * HARD_FORK_INTERVAL { | ||
HeaderVersion(4) | ||
} else { | ||
HeaderVersion(hf_interval) | ||
} | ||
|
@@ -162,8 +170,10 @@ pub fn header_version(height: u64) -> HeaderVersion { | |
HeaderVersion(1) | ||
} else if height < TESTING_SECOND_HARD_FORK { | ||
HeaderVersion(2) | ||
} else if height < 3 * HARD_FORK_INTERVAL { | ||
} else if height < TESTING_THIRD_HARD_FORK { | ||
HeaderVersion(3) | ||
} else if height < 4 * HARD_FORK_INTERVAL { | ||
HeaderVersion(4) | ||
} else { | ||
HeaderVersion(hf_interval) | ||
} | ||
|
@@ -174,7 +184,7 @@ pub fn header_version(height: u64) -> HeaderVersion { | |
/// Check whether the block version is valid at a given height, implements | ||
/// 6 months interval scheduled hard forks for the first 2 years. | ||
pub fn valid_header_version(height: u64, version: HeaderVersion) -> bool { | ||
height < 3 * HARD_FORK_INTERVAL && version == header_version(height) | ||
height < 4 * HARD_FORK_INTERVAL && version == header_version(height) | ||
} | ||
Comment on lines
186
to
188
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just realized this logic is only correct for This is not specific to this PR and I don't think it has a material impact here - but we should revisit this. Tracking here - #3335 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't floonet and usertesting be limited to 2 years worth of block just like mainnet is for version 4? Of course that will be changed downward at the next HF, but for now it looks fine to me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah maybe that is fine actually. 👍 |
||
|
||
/// Number of blocks used to calculate difficulty adjustments | ||
|
@@ -194,8 +204,7 @@ pub const DIFFICULTY_DAMP_FACTOR: u64 = 3; | |
pub const AR_SCALE_DAMP_FACTOR: u64 = 13; | ||
|
||
/// Compute weight of a graph as number of siphash bits defining the graph | ||
/// Must be made dependent on height to phase out C31 in early 2020 | ||
/// Later phase outs are on hold for now | ||
/// The height dependence allows a 30-week linear transition from C31+ to C32+ starting after 1 year | ||
pub fn graph_weight(height: u64, edge_bits: u8) -> u64 { | ||
let mut xpr_edge_bits = edge_bits as u64; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
// Copyright 2020 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. | ||
|
||
//! Implementation of Cuckarooz Cycle, based on Cuckoo Cycle designed by | ||
//! John Tromp. Ported to Rust from https://github.com/tromp/cuckoo. | ||
//! | ||
//! Cuckarooz is a variation of Cuckaroo that's tweaked at the third HardFork | ||
//! to maintain ASIC-Resistance, as introduced in | ||
//! https://forum.grin.mw/t/introducing-the-final-tweak-cuckarooz | ||
//! It completes the choices of undirected vs directed edges and bipartite vs | ||
//! monopartite graphs, and is named after the last letter of the alphabet | ||
//! accordingly. | ||
|
||
use crate::global; | ||
use crate::pow::common::{CuckooParams, EdgeType}; | ||
use crate::pow::error::{Error, ErrorKind}; | ||
use crate::pow::siphash::siphash_block; | ||
use crate::pow::{PoWContext, Proof}; | ||
|
||
/// Instantiate a new CuckaroozContext as a PowContext. Note that this can't | ||
/// be moved in the PoWContext trait as this particular trait needs to be | ||
/// convertible to an object trait. | ||
pub fn new_cuckarooz_ctx<T>( | ||
edge_bits: u8, | ||
proof_size: usize, | ||
) -> Result<Box<dyn PoWContext<T>>, Error> | ||
where | ||
T: EdgeType + 'static, | ||
{ | ||
let params = CuckooParams::new(edge_bits, proof_size)?; | ||
Ok(Box::new(CuckaroozContext { params })) | ||
} | ||
|
||
/// Cuckarooz cycle context. Only includes the verifier for now. | ||
pub struct CuckaroozContext<T> | ||
where | ||
T: EdgeType, | ||
{ | ||
params: CuckooParams<T>, | ||
} | ||
|
||
impl<T> PoWContext<T> for CuckaroozContext<T> | ||
where | ||
T: EdgeType, | ||
{ | ||
fn set_header_nonce( | ||
&mut self, | ||
header: Vec<u8>, | ||
nonce: Option<u32>, | ||
_solve: bool, | ||
) -> Result<(), Error> { | ||
self.params.reset_header_nonce(header, nonce) | ||
} | ||
|
||
fn find_cycles(&mut self) -> Result<Vec<Proof>, Error> { | ||
unimplemented!() | ||
} | ||
|
||
fn verify(&self, proof: &Proof) -> Result<(), Error> { | ||
if proof.proof_size() != global::proofsize() { | ||
return Err(ErrorKind::Verification("wrong cycle length".to_owned()).into()); | ||
} | ||
let nonces = &proof.nonces; | ||
let mut uvs = vec![0u64; 2 * proof.proof_size()]; | ||
let mut xoruv: u64 = 0; | ||
|
||
for n in 0..proof.proof_size() { | ||
if nonces[n] > to_u64!(self.params.edge_mask) { | ||
return Err(ErrorKind::Verification("edge too big".to_owned()).into()); | ||
} | ||
if n > 0 && nonces[n] <= nonces[n - 1] { | ||
return Err(ErrorKind::Verification("edges not ascending".to_owned()).into()); | ||
} | ||
// 21 is standard siphash rotation constant | ||
let edge = to_edge!( | ||
T, | ||
siphash_block(&self.params.siphash_keys, nonces[n], 21, true) | ||
); | ||
uvs[2 * n] = to_u64!(edge & self.params.edge_mask); | ||
uvs[2 * n + 1] = to_u64!((edge >> 32) & self.params.edge_mask); | ||
xoruv ^= uvs[2 * n] ^ uvs[2 * n + 1]; | ||
} | ||
if xoruv != 0 { | ||
return Err(ErrorKind::Verification("endpoints don't match up".to_owned()).into()); | ||
} | ||
let mut n = 0; | ||
let mut i = 0; | ||
let mut j; | ||
loop { | ||
// follow cycle | ||
j = i; | ||
let mut k = j; | ||
loop { | ||
k = (k + 1) % (2 * self.params.proof_size); | ||
if k == i { | ||
break; | ||
} | ||
if uvs[k] == uvs[i] { | ||
// find other edge endpoint matching one at i | ||
if j != i { | ||
return Err(ErrorKind::Verification("branch in cycle".to_owned()).into()); | ||
} | ||
j = k; | ||
} | ||
} | ||
if j == i { | ||
return Err(ErrorKind::Verification("cycle dead ends".to_owned()).into()); | ||
} | ||
i = j ^ 1; | ||
n += 1; | ||
if i == 0 { | ||
break; | ||
} | ||
} | ||
if n == self.params.proof_size { | ||
Ok(()) | ||
} else { | ||
Err(ErrorKind::Verification("cycle too short".to_owned()).into()) | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
|
||
// empty header, nonce 71 | ||
static V1_19_HASH: [u64; 4] = [ | ||
0xd129f63fba4d9a85, | ||
0x457dcb3666c5e09c, | ||
0x045247a2e2ee75f7, | ||
0x1a0f2e1bcb9d93ff, | ||
]; | ||
static V1_19_SOL: [u64; 42] = [ | ||
0x33b6, 0x487b, 0x88b7, 0x10bf6, 0x15144, 0x17cb7, 0x22621, 0x2358e, 0x23775, 0x24fb3, | ||
0x26b8a, 0x2876c, 0x2973e, 0x2f4ba, 0x30a62, 0x3a36b, 0x3ba5d, 0x3be67, 0x3ec56, 0x43141, | ||
0x4b9c5, 0x4fa06, 0x51a5c, 0x523e5, 0x53d08, 0x57d34, 0x5c2de, 0x60bba, 0x62509, 0x64d69, | ||
0x6803f, 0x68af4, 0x6bd52, 0x6f041, 0x6f900, 0x70051, 0x7097d, 0x735e8, 0x742c2, 0x79ae5, | ||
0x7f64d, 0x7fd49, | ||
]; | ||
|
||
// empty header, nonce 15 | ||
static V2_29_HASH: [u64; 4] = [ | ||
0x34bb4c75c929a2f5, | ||
0x21df13263aa81235, | ||
0x37d00939eae4be06, | ||
0x473251cbf6941553, | ||
]; | ||
static V2_29_SOL: [u64; 42] = [ | ||
0x49733a, 0x1d49107, 0x253d2ca, 0x5ad5e59, 0x5b671bd, 0x5dcae1c, 0x5f9a589, 0x65e9afc, | ||
0x6a59a45, 0x7d9c6d3, 0x7df96e4, 0x8b26174, 0xa17b430, 0xa1c8c0d, 0xa8a0327, 0xabd7402, | ||
0xacb7c77, 0xb67524f, 0xc1c15a6, 0xc7e2c26, 0xc7f5d8d, 0xcae478a, 0xdea9229, 0xe1ab49e, | ||
0xf57c7db, 0xfb4e8c5, 0xff314aa, 0x110ccc12, 0x143e546f, 0x17007af8, 0x17140ea2, | ||
0x173d7c5d, 0x175cd13f, 0x178b8880, 0x1801edc5, 0x18c8f56b, 0x18c8fe6d, 0x19f1a31a, | ||
0x1bb028d1, 0x1caaa65a, 0x1cf29bc2, 0x1dbde27d, | ||
]; | ||
|
||
#[test] | ||
fn cuckarooz19_29_vectors() { | ||
global::set_local_chain_type(global::ChainTypes::Mainnet); | ||
let mut ctx19 = new_impl::<u64>(19, 42); | ||
ctx19.params.siphash_keys = V1_19_HASH.clone(); | ||
assert!(ctx19 | ||
.verify(&Proof::new(V1_19_SOL.to_vec().clone())) | ||
.is_ok()); | ||
assert!(ctx19.verify(&Proof::zero(42)).is_err()); | ||
let mut ctx29 = new_impl::<u64>(29, 42); | ||
ctx29.params.siphash_keys = V2_29_HASH.clone(); | ||
assert!(ctx29 | ||
.verify(&Proof::new(V2_29_SOL.to_vec().clone())) | ||
.is_ok()); | ||
assert!(ctx29.verify(&Proof::zero(42)).is_err()); | ||
} | ||
|
||
fn new_impl<T>(edge_bits: u8, proof_size: usize) -> CuckaroozContext<T> | ||
where | ||
T: EdgeType, | ||
{ | ||
let params = CuckooParams::new(edge_bits, proof_size).unwrap(); | ||
CuckaroozContext { params } | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For reference the exact time is currently 2020-06-19 18:49:36 +0000 UTC