Change the CLI to match the `pot` tool

Also reduce the number of Miller-Rabin iterations from 25 to 13 in
discriminant generation and the Wesolowski proof.
This commit is contained in:
Demi M. Obenour 2018-11-28 17:03:59 -05:00
parent 4557e607f4
commit bfe8265017
No known key found for this signature in database
GPG Key ID: B288B55FFF9C22C1
7 changed files with 72 additions and 135 deletions

View File

@ -21,9 +21,9 @@ follow one of the below steps.
$ git clone https://github.com/poanetwork/vdf
$ cd vdf
$ cargo install
$ vdf-cli prove aa 100
$ vdf-cli aa 100
005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
$ vdf-cli verify aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
$ vdf-cli aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
Proof is valid
```
### To use the VDF library

14
ci.sh
View File

@ -33,17 +33,7 @@ prove () {
(*) echo 'internal error' "$1" >&2; exit 1;;
esac
shift
exec ./target/release/vdf-cli "$fst_arg" -- prove -- "$@"
}
verify() {
fst_arg=$1
case a$1 in
(a-tpietrzak|a-twesolowski) :;;
(*) echo 'internal error' >&2; exit 1;;
esac
shift
exec ./target/release/vdf-cli "$fst_arg" -- verify -- "$@"
exec ./target/release/vdf-cli "$fst_arg" -- "$@"
}
test_output () {
@ -63,7 +53,7 @@ for proof_type in wesolowski pietrzak; do
printf "Checking proof of type %q on input %d... " "$proof_type" "$((count += 1))"
test_output "$correct_proof" ./target/release/vdf-cli "-t$proof_type" prove -- "$challenge" "$iterations"
printf "Checking verification of input %d... " "$count"
test_output 'Proof is valid' ./target/release/vdf-cli "-t$proof_type" verify -- "$challenge" "$iterations" "$correct_proof"
test_output 'Proof is valid' ./target/release/vdf-cli "-t$proof_type" prove -- "$challenge" "$iterations" "$correct_proof"
done < <(grep -E '^[a-f0-9]{64},[0-9]{2,4},[0-9a-f]+$' "$proof_type.csv")
done
"$k"

View File

@ -20,5 +20,7 @@ case $# in
(*) echo 'Must have 2 or 3 arguments' >&2; exit 1;;
esac
cmp <(~/.local/bin/pot -tpietrzak "-l${3-2048}" -- "$1" "$2") \
<(./vdf-cli prove -- "$@")
set -- "-l${3-2048}" -- "$1" "$2"
cmp <(~/.local/bin/pot -tpietrzak "$@") \
<(./vdf-cli "$@")

View File

@ -11,46 +11,21 @@
// 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.
#![deny(warnings)]
#![forbid(warnings)]
#![forbid(unsafe_code)]
use std::u64;
// use std::num::ParseIntError;
extern crate gmp;
use gmp::mpz::Mpz;
use std::cell::RefCell;
extern crate hex;
extern crate vdf;
use vdf::{InvalidProof, PietrzakVDFParams, VDFParams, WesolowskiVDFParams, VDF};
#[macro_use]
extern crate clap;
extern crate classgroup;
thread_local! {
static DISCRIMINANT: RefCell<Option<Mpz>> = RefCell::new(None);
}
fn is_bigint_ok(obj: String) -> Result<(), String> {
let s = match Mpz::from_str_radix(&obj, 0) {
Ok(m) => {
if m >= (-6i64).into() {
Err("m must be negative and ≤ -7".to_owned())
} else if m.probab_prime(if cfg!(debug_assertions) { 40 } else { 1 })
== gmp::mpz::ProbabPrimeResult::NotPrime
{
Err("m must be prime".to_owned())
} else {
DISCRIMINANT.with(|x| assert!(x.replace(Some(m)).is_none()));
Ok(())
}
}
Err(e) => Err(format!("{}: {:?}", e, obj)),
};
drop(obj);
s
}
fn parse_already_checked_args() -> (Mpz,) {
(DISCRIMINANT.with(|x| x.borrow_mut().take().unwrap()),)
}
use std::cell::RefCell;
use std::fs::File;
use std::io::Read;
use std::rc::Rc;
use std::u64;
use vdf::{InvalidProof, PietrzakVDFParams, VDFParams, WesolowskiVDFParams, VDF};
macro_rules! gen_validator {
($name:ident : $type:ty) => {
@ -66,7 +41,6 @@ macro_rules! gen_validator {
gen_validator!(is_u16_ok: u16);
gen_validator!(is_u64_ok: u64);
gen_validator!(is_hex_ok, hex::decode);
gen_validator!(is_bignum_ok, |x| Mpz::from_str_radix(x, 0));
fn check_iterations(is_pietrzak: bool, matches: &clap::ArgMatches) -> u64 {
let iterations = value_t!(matches, "NUM_ITERATIONS", u64).unwrap();
@ -80,7 +54,7 @@ fn check_iterations(is_pietrzak: bool, matches: &clap::ArgMatches) -> u64 {
}
}
fn main() -> Result<(), std::io::Error> {
fn main() {
let validate_proof_type = |x| {
if x == "pietrzak" || x == "wesolowski" {
Ok(())
@ -89,98 +63,69 @@ fn main() -> Result<(), std::io::Error> {
}
};
let matches = clap_app!(myapp =>
let proof_contents = Rc::new(RefCell::new(None));
let is_proof_ok = {
let proof_contents = proof_contents.clone();
move |proof: String| {
*proof_contents.borrow_mut() = Some(if proof.starts_with("@") {
let file_name = &proof[1..];
let mut file = File::open(file_name)
.map_err(|err| format!("Cound not open {:?}: {}", file_name, err))?;
let mut buf = Vec::new();
file.read_to_end(&mut buf)
.map_err(|err| format!("Cound not read {:?}: {}", file_name, err))?;
buf
} else {
hex::decode(&proof).map_err(|err| format!("Invalid hex {:?}: {}", proof, err))?
});
Ok(())
}
};
let matches = clap_app!(vdf =>
(version: crate_version!())
(author: "POA Networks Ltd. <poa.networks>")
(about: "CLI to Verifiable Delay Functions")
(@arg VERBOSE: -v --verbose "Log verbosely to stderr. This command does not currently log anything, so this option currently has no affect.")
(@arg TYPE: -t --type +takes_value {validate_proof_type} "The type of proof to generate")
(@subcommand compute =>
(@arg DISCRIMINANT: +required {is_bigint_ok} "The discriminant" )
(@arg NUM_ITERATIONS: +required {is_u64_ok} "The number of iterations")
)
(@subcommand prove =>
(@arg DISCRIMINANT_CHALLENGE: +required {is_hex_ok} "Hex-encoded challenge to derive the discriminant from" )
(@arg NUM_ITERATIONS: +required {is_u64_ok} "The number of iterations")
(@arg LENGTH: {is_u16_ok} "Length in bits of the discriminant (default: 2048)")
)
(@subcommand verify =>
(@arg DISCRIMINANT_CHALLENGE: +required {is_hex_ok} "Hex-encoded challenge to derive the discriminant from" )
(@arg NUM_ITERATIONS: +required {is_u64_ok} "The number of iterations")
(@arg PROOF: +required {is_hex_ok} "The proof")
(@arg LENGTH: {is_u16_ok} "Length in bits of the discriminant (default: 2048)")
)
(@subcommand dump =>
(@arg NUM: +required {is_bignum_ok} "The bignum to dump")
)
(@arg LENGTH: -l --length +takes_value {is_u16_ok} "Length in bits of the discriminant (default: 2048)")
(@arg DISCRIMINANT_CHALLENGE: +required {is_hex_ok} "Hex-encoded challenge to derive the discriminant from" )
(@arg NUM_ITERATIONS: +required {is_u64_ok} "The number of iterations")
(@arg PROOF: {is_proof_ok} "The hex-encoded proof, or @ followed by a file containing the proof as raw binary data")
)
.get_matches();
let is_pietrzak = matches
.value_of("TYPE")
.map(|x| x == "pietrzak")
.unwrap_or(true);
.unwrap_or(false);
let int_size_bits: u16 = matches
.value_of("LENGTH")
.unwrap_or("2048")
.parse()
.unwrap();
match matches.subcommand() {
("compute", Some(matches)) => {
let (discriminant,) = parse_already_checked_args();
println!(
"{}",
classgroup::do_compute(
discriminant,
matches.value_of("ITERATIONS").unwrap().parse().unwrap()
)
);
Ok(())
}
("verify", Some(matches)) => {
let iterations = check_iterations(is_pietrzak, &matches);
let challenge =
hex::decode(&matches.value_of("DISCRIMINANT_CHALLENGE").unwrap()).unwrap();
let length = matches.value_of("LENGTH").or(Some("2048")).unwrap();
let int_size_bits = u16::from_str_radix(length, 10).unwrap();
let proof = hex::decode(matches.value_of("PROOF").unwrap()).unwrap();
let iterations = check_iterations(is_pietrzak, &matches);
let challenge = hex::decode(&matches.value_of("DISCRIMINANT_CHALLENGE").unwrap()).unwrap();
let vdf: Box<VDF> = if is_pietrzak {
Box::new(PietrzakVDFParams(int_size_bits).new()) as _
} else {
Box::new(WesolowskiVDFParams(int_size_bits).new()) as _
};
match vdf.verify(&challenge, iterations, &proof) {
Ok(()) => {
println!("Proof is valid");
Ok(())
}
Err(InvalidProof) => {
println!("Invalid proof");
std::process::exit(1);
}
let vdf: Box<VDF> = if is_pietrzak {
Box::new(PietrzakVDFParams(int_size_bits).new()) as _
} else {
Box::new(WesolowskiVDFParams(int_size_bits).new()) as _
};
if let Some(proof) = matches.value_of_os("PROOF") {
drop(proof);
let actual_proof = proof_contents.borrow_mut().take().unwrap();
match vdf.verify(&challenge, iterations, &actual_proof) {
Ok(()) => println!("Proof is valid"),
Err(InvalidProof) => {
println!("Invalid proof");
std::process::exit(1)
}
}
("prove", Some(matches)) => {
let iterations = check_iterations(is_pietrzak, &matches);
let challenge =
hex::decode(&matches.value_of("DISCRIMINANT_CHALLENGE").unwrap()).unwrap();
let length = matches.value_of("LENGTH").or(Some("2048")).unwrap();
let int_size_bits = u16::from_str_radix(length, 10).unwrap();
let vdf: Box<VDF> = if is_pietrzak {
Box::new(PietrzakVDFParams(int_size_bits).new()) as _
} else {
Box::new(WesolowskiVDFParams(int_size_bits).new()) as _
};
let proof = vdf.solve(&challenge, iterations).unwrap();
println!("{}", hex::encode(&proof));
Ok(())
}
("dump", Some(matches)) => {
let v = Mpz::from_str_radix(matches.value_of("NUM").unwrap(), 0).unwrap();
let mut buf = vec![0u8; classgroup::export_obj(&v, &mut []).unwrap_err()];
classgroup::export_obj(&v, &mut buf).unwrap();
assert_eq!(&classgroup::import_obj(&buf), &v);
println!("Dumped output: {:x?}", buf);
Ok(())
}
_ => unreachable!(),
} else {
let proof = vdf
.solve(&challenge, iterations)
.expect("iterations should have been valiated earlier");
println!("{}", hex::encode(proof))
}
}

View File

@ -108,7 +108,7 @@ pub fn create_discriminant<T: BigNumExt>(seed: &[u8], length: u16) -> T {
if !x {
let q = u64::from(M) * u64::from(i);
n = n + q;
if n.probab_prime(25) {
if n.probab_prime(13) {
return -n;
}
n = n - q;

View File

@ -35,9 +35,9 @@
//! $ git clone https://github.com/poanetwork/vdf
//! $ cd vdf
//! $ cargo install
//! $ vdf-cli prove aa 100
//! $ vdf-cli aa 100
//! 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
//! $ vdf-cli verify aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
//! $ vdf-cli aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
//! Proof is valid
//! ```
//! ### To use the VDF library

View File

@ -119,7 +119,7 @@ fn hash_prime<T: BigNum>(seed: &[&[u8]]) -> T {
hasher.input(i);
}
let n = T::from(&hasher.fixed_result()[..16]);
if n.probab_prime(25) {
if n.probab_prime(13) {
break n;
}
j += 1;