mirror of
https://source.quilibrium.com/quilibrium/ceremonyclient.git
synced 2024-12-24 23:55:18 +00:00
Merge branch 'rust-vdf' into 'v1.4.19'
Switch to Rust VDF See merge request quilibrium/ceremonyclient!2
This commit is contained in:
commit
62db30c54f
@ -4,3 +4,6 @@
|
||||
github.env
|
||||
Taskfile.yaml
|
||||
|
||||
# Rust
|
||||
target
|
||||
vdf/generated
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -8,3 +8,7 @@ ceremony-client
|
||||
.env.signers
|
||||
.task
|
||||
node-tmp-*
|
||||
build
|
||||
|
||||
# Rust
|
||||
target
|
||||
|
34
CONTRIBUTING.md
Normal file
34
CONTRIBUTING.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Local development
|
||||
|
||||
The following software is required for local development (assuming MacOS ARM):
|
||||
|
||||
- Go 1.20
|
||||
- Rust toolchain
|
||||
- GMP 6.3: `brew install gmp`
|
||||
- Install the Go plugin for uniffi-rs: `cargo install uniffi-bindgen-go --git https://github.com/NordSecurity/uniffi-bindgen-go --tag v0.2.1+v0.25.0`
|
||||
|
||||
# Building release binaries
|
||||
|
||||
The following is software is required to build release binaries (assuming MacOS
|
||||
ARM) :
|
||||
|
||||
- [Local development](#local-development) dependencies
|
||||
- Docker
|
||||
- [Taskfile](https://taskfile.dev/)
|
||||
|
||||
Then from the repo root use the following commands to build the release binaries
|
||||
that statically link the [native VDF](./crates/vdf) for the supported platforms:
|
||||
|
||||
```shell
|
||||
task build_node_arm64_macos
|
||||
task build_node_arm64_linux
|
||||
task build_node_arm64_macos
|
||||
```
|
||||
|
||||
The output binaries will be in `node/build`.
|
||||
|
||||
# Testing
|
||||
|
||||
Testing the [`vdf`](./vdf) and [`node`](./node) packages requires linking the
|
||||
[native VDF](./crates/vdf). The `test.sh` scripts in the respective directories
|
||||
help with this.
|
1201
Cargo.lock
generated
Normal file
1201
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
25
Cargo.toml
Normal file
25
Cargo.toml
Normal file
@ -0,0 +1,25 @@
|
||||
# Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
#
|
||||
# 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
|
||||
# and limitations under the License.
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/vdf",
|
||||
"crates/classgroup",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
# rpath = false is important to make Go bindings work
|
||||
rpath = false
|
||||
lto = true
|
||||
debug = false
|
||||
# panic = 'abort'
|
@ -1,4 +1,20 @@
|
||||
FROM golang:1.20.14-alpine3.19 as build
|
||||
FROM golang:1.20.14-bullseye as build-base
|
||||
|
||||
ENV PATH="${PATH}:/root/.cargo/bin/"
|
||||
|
||||
# Install GMP 6.2 (6.3 which MacOS is using only available on Debian unstable)
|
||||
RUN apt-get update && apt-get install -y \
|
||||
libgmp-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
COPY docker/rustup-init.sh /opt/rustup-init.sh
|
||||
|
||||
RUN /opt/rustup-init.sh -y --profile minimal
|
||||
|
||||
# Install uniffi-bindgen-go
|
||||
RUN cargo install uniffi-bindgen-go --git https://github.com/NordSecurity/uniffi-bindgen-go --tag v0.2.1+v0.25.0
|
||||
|
||||
FROM build-base as build
|
||||
|
||||
ENV GOEXPERIMENT=arenas
|
||||
ENV QUILIBRIUM_SIGNATURE_CHECK=false
|
||||
@ -7,16 +23,27 @@ WORKDIR /opt/ceremonyclient
|
||||
|
||||
COPY . .
|
||||
|
||||
## Generate Rust bindings for VDF
|
||||
WORKDIR /opt/ceremonyclient/vdf
|
||||
RUN ./generate.sh
|
||||
|
||||
# Build and install the node
|
||||
WORKDIR /opt/ceremonyclient/node
|
||||
|
||||
RUN go install ./...
|
||||
RUN ./build.sh && cp node /go/bin
|
||||
RUN go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
|
||||
|
||||
# Build and install qclient
|
||||
WORKDIR /opt/ceremonyclient/client
|
||||
|
||||
RUN go build -o qclient ./main.go
|
||||
|
||||
FROM alpine:3.19
|
||||
# Allows exporting single binary
|
||||
FROM scratch AS node
|
||||
COPY --from=build /go/bin/node /node
|
||||
ENTRYPOINT [ "/node" ]
|
||||
|
||||
FROM debian:bullseye
|
||||
|
||||
ARG NODE_VERSION
|
||||
ARG GIT_REPO
|
||||
|
@ -31,6 +31,22 @@ tasks:
|
||||
- echo -n "Max Key ID:" && echo " {{.MAX_KEY_ID}}"
|
||||
silent: true
|
||||
|
||||
build_node_arm64_macos:
|
||||
desc: Build the Quilibrium node binary for MacOS ARM. Assumes it's ran from the same platform. Outputs to node/build.
|
||||
cmds:
|
||||
- vdf/generate.sh
|
||||
- node/build.sh -o build/arm64_macos/node
|
||||
|
||||
build_node_arm64_linux:
|
||||
desc: Build the Quilibrium node binary for ARM64 Linux. Outputs to node/build.
|
||||
cmds:
|
||||
- docker build --platform linux/arm64 -f Dockerfile --output node/build/arm64_linux --target=node .
|
||||
|
||||
build_node_amd64_linux:
|
||||
desc: Build the Quilibrium node binary for AMD64 Linux. Outputs to node/build.
|
||||
cmds:
|
||||
- docker build --platform linux/amd64 -f Dockerfile --output node/build/amd64_linux --target=node .
|
||||
|
||||
build:source:
|
||||
desc: Build the Quilibrium docker image from source.
|
||||
cmds:
|
||||
|
@ -24,8 +24,8 @@ require (
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/crypto v0.24.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
source.quilibrium.com/quilibrium/monorepo/nekryptology v0.0.0-00010101000000-000000000000 // indirect
|
||||
|
@ -89,8 +89,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
||||
golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -103,8 +103,8 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
|
34
crates/classgroup/Cargo.toml
Normal file
34
crates/classgroup/Cargo.toml
Normal file
@ -0,0 +1,34 @@
|
||||
# Copyright 2018 POA Networks Ltd.
|
||||
#
|
||||
# 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
|
||||
# and limitations under the License.
|
||||
[package]
|
||||
name = "classgroup"
|
||||
version = "0.1.0"
|
||||
authors = ["Demi M. Obenour <demiobenour@gmail.com>"]
|
||||
description = """An implementation of class groups in Rust. Uses GMP for arithmetic."""
|
||||
keywords = ["classgroup", "vdf"]
|
||||
repository = "https://github.com/poanetwork/vdf"
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
num-traits = "0.2"
|
||||
libc = "0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = ">=0.2"
|
||||
|
||||
[[bench]]
|
||||
name = "classgroup-bench"
|
||||
harness = false
|
||||
path = "bench/bench.rs"
|
66
crates/classgroup/bench/bench.rs
Normal file
66
crates/classgroup/bench/bench.rs
Normal file
@ -0,0 +1,66 @@
|
||||
// Copyright 2018 POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
|
||||
use classgroup::{gmp_classgroup::GmpClassGroup, ClassGroup};
|
||||
use criterion::Criterion;
|
||||
use gmp::mpz::Mpz;
|
||||
use std::str::FromStr;
|
||||
|
||||
fn bench_square(c: &mut Criterion) {
|
||||
for _ in 0..2 {
|
||||
let m_2048 = -Mpz::from_str(
|
||||
"201493927071865251625903550712920535753645598483515670853547009\
|
||||
878440933309489362800393797428711071833308081461824159206915864\
|
||||
150805748296170245037221957772328044276705571745811271212292422\
|
||||
075849739248257870371300001313586036515879618764093772248760562\
|
||||
386804073478433157526816295216137723803793411828867470089409596\
|
||||
238958950007370719325959579892866588928887249912429688364409867\
|
||||
895510817680171869190054122881274299350947669820596157115994418\
|
||||
034091728887584373727555384075665624624856766441009974642693066\
|
||||
751400054217209981490667208950669417773785631693879782993019167\
|
||||
69407006303085854796535778826115224633447713584423",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let m_1024 = -Mpz::from_str(
|
||||
"-11208471744389096429663063172516742066731683613191418514476174383781\
|
||||
682509882427394963852743081347678693241523614532942268295868231081182\
|
||||
819214054220080323345750407342623884342617809879459211722505867733607\
|
||||
400509994975706778681543998242335468203860240586171413971485860382901\
|
||||
6409314686266660248501773529803183",
|
||||
)
|
||||
.unwrap();
|
||||
let group_1024 = GmpClassGroup::generator_for_discriminant(m_1024);
|
||||
let group_2048 = GmpClassGroup::generator_for_discriminant(m_2048);
|
||||
let (group_1024_clone, group_2048_clone) = (group_1024.clone(), group_2048.clone());
|
||||
c.bench_function("square 1024", move |b| {
|
||||
b.iter(|| group_1024_clone.clone().square())
|
||||
});
|
||||
c.bench_function("multiply 1024", move |b| {
|
||||
b.iter(|| &group_1024 * &group_1024)
|
||||
});
|
||||
c.bench_function("square 2048", move |b| {
|
||||
b.iter(|| group_2048_clone.clone().square())
|
||||
});
|
||||
c.bench_function("multiply 2048", move |b| {
|
||||
b.iter(|| &group_2048 * &group_2048)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_square);
|
||||
criterion_main!(benches);
|
16
crates/classgroup/build.rs
Normal file
16
crates/classgroup/build.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
let target = env::var("TARGET").expect("cargo should have set this");
|
||||
if target == "aarch64-apple-darwin" {
|
||||
println!("cargo:rustc-link-search=/opt/homebrew/Cellar/gmp/6.3.0/lib");
|
||||
} else if target == "aarch64-unknown-linux-gnu" {
|
||||
println!("cargo:rustc-link-search=/usr/lib/aarch64-linux-gnu/");
|
||||
} else if target == "x86_64-unknown-linux-gnu" {
|
||||
println!("cargo:rustc-link-search=/usr/lib/x86_64-linux-gnu/");
|
||||
} else {
|
||||
panic!("unsupported target {target}");
|
||||
}
|
||||
}
|
7
crates/classgroup/src/gmp/ffi.rs
Normal file
7
crates/classgroup/src/gmp/ffi.rs
Normal file
@ -0,0 +1,7 @@
|
||||
use super::mpz::*;
|
||||
|
||||
#[link(name = "gmp", kind = "static")]
|
||||
extern "C" {
|
||||
pub fn __gmpz_fdiv_q(q: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
|
||||
pub fn __gmpz_cdiv_q(q: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
|
||||
}
|
12
crates/classgroup/src/gmp/mod.rs
Normal file
12
crates/classgroup/src/gmp/mod.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#![warn(deprecated)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
extern crate libc;
|
||||
extern crate num_traits;
|
||||
|
||||
mod ffi;
|
||||
pub mod mpz;
|
||||
pub mod sign;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test;
|
1035
crates/classgroup/src/gmp/mpz.rs
Normal file
1035
crates/classgroup/src/gmp/mpz.rs
Normal file
File diff suppressed because it is too large
Load Diff
7
crates/classgroup/src/gmp/sign.rs
Normal file
7
crates/classgroup/src/gmp/sign.rs
Normal file
@ -0,0 +1,7 @@
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)]
|
||||
pub enum Sign {
|
||||
Negative,
|
||||
Zero,
|
||||
Positive,
|
||||
}
|
||||
|
582
crates/classgroup/src/gmp/test.rs
Normal file
582
crates/classgroup/src/gmp/test.rs
Normal file
@ -0,0 +1,582 @@
|
||||
use super::mpz::mp_limb_t;
|
||||
use std;
|
||||
use libc::c_int;
|
||||
|
||||
#[link(name = "gmp", kind = "static")]
|
||||
extern "C" {
|
||||
static __gmp_bits_per_limb: c_int;
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[allow(unsafe_code)]
|
||||
fn test_limb_size() {
|
||||
// We are assuming that the limb size is the same as the pointer size.
|
||||
assert_eq!(std::mem::size_of::<mp_limb_t>() * 8,
|
||||
unsafe { __gmp_bits_per_limb as usize });
|
||||
}
|
||||
|
||||
mod mpz {
|
||||
use super::super::mpz::Mpz;
|
||||
use super::super::mpz::ProbabPrimeResult;
|
||||
use super::super::sign::Sign;
|
||||
use std::str::FromStr;
|
||||
use std::convert::{From, Into};
|
||||
use std::{i64, u64};
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
|
||||
#[test]
|
||||
fn test_set() {
|
||||
let mut x: Mpz = From::<i64>::from(1000);
|
||||
let y: Mpz = From::<i64>::from(5000);
|
||||
assert!(x != y);
|
||||
x.set(&y);
|
||||
assert!(x == y);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_from_str_radix() {
|
||||
let mut x: Mpz = From::<i64>::from(1000);
|
||||
let y: Mpz = From::<i64>::from(5000);
|
||||
assert!(x != y);
|
||||
assert!(x.set_from_str_radix("5000", 10));
|
||||
assert!(x == y);
|
||||
assert!(!x.set_from_str_radix("aaaa", 2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_from_str_radix_lower_bound() {
|
||||
let _ = Mpz::from_str_radix("", 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_from_str_radix_upper_bound() {
|
||||
let _ = Mpz::from_str_radix("", 63);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_set_from_str_radix_lower_bound() {
|
||||
let mut x = Mpz::new();
|
||||
x.set_from_str_radix("", 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_set_from_str_radix_upper_bound() {
|
||||
let mut x = Mpz::new();
|
||||
x.set_from_str_radix("", 63);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_eq() {
|
||||
let x: Mpz = From::<i64>::from(4242142195);
|
||||
let y: Mpz = From::<i64>::from(4242142195);
|
||||
let z: Mpz = From::<i64>::from(4242142196);
|
||||
|
||||
assert!(x == y);
|
||||
assert!(x != z);
|
||||
assert!(y != z);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ord() {
|
||||
let x: Mpz = FromStr::from_str("40000000000000000000000").unwrap();
|
||||
let y: Mpz = FromStr::from_str("45000000000000000000000").unwrap();
|
||||
let z: Mpz = FromStr::from_str("50000000000000000000000").unwrap();
|
||||
|
||||
assert!(x < y && x < z && y < z);
|
||||
assert!(x <= x && x <= y && x <= z && y <= z);
|
||||
assert!(z > y && z > x && y > x);
|
||||
assert!(z >= z && z >= y && z >= x && y >= x);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_div_zero() {
|
||||
let x: Mpz = From::<i64>::from(1);
|
||||
let y = Mpz::new();
|
||||
drop(x / y)
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic]
|
||||
fn test_rem_zero() {
|
||||
let x: Mpz = From::<i64>::from(1);
|
||||
let y = Mpz::new();
|
||||
drop(x % y)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_div_round() {
|
||||
let x: Mpz = From::<i64>::from(2);
|
||||
let y: Mpz = From::<i64>::from(3);
|
||||
assert!((&x / &y).to_string() == (2i32 / 3).to_string());
|
||||
assert!((&x / -&y).to_string() == (2i32 / -3).to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rem() {
|
||||
let x: Mpz = From::<i64>::from(20);
|
||||
let y: Mpz = From::<i64>::from(3);
|
||||
assert!((&x % &y).to_string() == (20i32 % 3).to_string());
|
||||
assert!((&x % 3).to_string() == (20i32 % 3).to_string());
|
||||
assert!((&x % -&y).to_string() == (20i32 % -3).to_string());
|
||||
assert!((-&x % &y).to_string() == (-20i32 % 3).to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add() {
|
||||
let x: Mpz = From::<i64>::from(2);
|
||||
let y: Mpz = From::<i64>::from(3);
|
||||
let str5 = 5i32.to_string();
|
||||
assert!((&x + &y).to_string() == str5);
|
||||
assert!((&x + 3).to_string() == str5);
|
||||
assert!((&y + 2).to_string() == str5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sub() {
|
||||
let x: Mpz = From::<i64>::from(2);
|
||||
let y: Mpz = From::<i64>::from(3);
|
||||
assert!((&x - &y).to_string() == (-1i32).to_string());
|
||||
assert!((&y - &x).to_string() == 1i32.to_string());
|
||||
assert!((&y - 8).to_string() == (-5i32).to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mul() {
|
||||
let x: Mpz = From::<i64>::from(2);
|
||||
let y: Mpz = From::<i64>::from(3);
|
||||
assert!((&x * &y).to_string() == 6i32.to_string());
|
||||
assert!((&x * 3i64).to_string() == 6i32.to_string());
|
||||
assert!((&y * -5i64).to_string() == (-15i32).to_string());
|
||||
// check with values not fitting in 32 bits
|
||||
assert!((&x * 5000000000i64).to_string() == 10000000000i64.to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_str_radix() {
|
||||
let x: Mpz = From::<i64>::from(255);
|
||||
assert!(x.to_str_radix(16) == "ff".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_string() {
|
||||
let x: Mpz = FromStr::from_str("1234567890").unwrap();
|
||||
assert!(x.to_string() == "1234567890".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_str() {
|
||||
let x: Result<Mpz, _> = FromStr::from_str("foobar");
|
||||
assert!(x.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_clone() {
|
||||
let a: Mpz = From::<i64>::from(100);
|
||||
let b = a.clone();
|
||||
let aplusb: Mpz = From::<i64>::from(200);
|
||||
assert!(b == a);
|
||||
assert!(a + b == aplusb);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_int() {
|
||||
let x: Mpz = From::<i64>::from(150);
|
||||
assert!(x.to_string() == "150".to_string());
|
||||
assert!(x == FromStr::from_str("150").unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_from_slice_u8() {
|
||||
let v: Vec<u8> = vec!(255, 255);
|
||||
let x: Mpz = From::from(&v[..]);
|
||||
assert!(x.to_string() == "65535".to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_abs() {
|
||||
let x: Mpz = From::<i64>::from(1000);
|
||||
let y: Mpz = From::<i64>::from(-1000);
|
||||
assert!(-&x == y);
|
||||
assert!(x == -&y);
|
||||
assert!(x == y.abs());
|
||||
assert!(x.abs() == y.abs());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_div_floor() {
|
||||
let two: Mpz = From::<i64>::from(2);
|
||||
let eight: Mpz = From::<i64>::from(8);
|
||||
let minuseight: Mpz = From::<i64>::from(-8);
|
||||
let three: Mpz = From::<i64>::from(3);
|
||||
let minusthree: Mpz = From::<i64>::from(-3);
|
||||
assert_eq!(eight.div_floor(&three), two);
|
||||
assert_eq!(eight.div_floor(&minusthree), minusthree);
|
||||
assert_eq!(minuseight.div_floor(&three), minusthree);
|
||||
assert_eq!(minuseight.div_floor(&minusthree), two);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mod_floor() {
|
||||
let one: Mpz = From::<i64>::from(1);
|
||||
let minusone: Mpz = From::<i64>::from(-1);
|
||||
let two: Mpz = From::<i64>::from(2);
|
||||
let minustwo: Mpz = From::<i64>::from(-2);
|
||||
let three: Mpz = From::<i64>::from(3);
|
||||
let minusthree: Mpz = From::<i64>::from(-3);
|
||||
let eight: Mpz = From::<i64>::from(8);
|
||||
let minuseight: Mpz = From::<i64>::from(-8);
|
||||
assert_eq!(eight.mod_floor(&three), two);
|
||||
assert_eq!(eight.mod_floor(&minusthree), minusone);
|
||||
assert_eq!(minuseight.mod_floor(&three), one);
|
||||
assert_eq!(minuseight.mod_floor(&minusthree), minustwo);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitand() {
|
||||
let a = 0b1001_0111;
|
||||
let b = 0b1100_0100;
|
||||
let mpza: Mpz = From::<i64>::from(a);
|
||||
let mpzb: Mpz = From::<i64>::from(b);
|
||||
let mpzres: Mpz = From::<i64>::from(a & b);
|
||||
assert!(mpza & mpzb == mpzres);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitor() {
|
||||
let a = 0b1001_0111;
|
||||
let b = 0b1100_0100;
|
||||
let mpza: Mpz = From::<i64>::from(a);
|
||||
let mpzb: Mpz = From::<i64>::from(b);
|
||||
let mpzres: Mpz = From::<i64>::from(a | b);
|
||||
assert!(mpza | mpzb == mpzres);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bitxor() {
|
||||
let a = 0b1001_0111;
|
||||
let b = 0b1100_0100;
|
||||
let mpza: Mpz = From::<i64>::from(a);
|
||||
let mpzb: Mpz = From::<i64>::from(b);
|
||||
let mpzres: Mpz = From::<i64>::from(a ^ b);
|
||||
assert!(mpza ^ mpzb == mpzres);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_shifts() {
|
||||
let i = 227;
|
||||
let j: Mpz = From::<i64>::from(i);
|
||||
assert!((i << 4).to_string() == (&j << 4).to_string());
|
||||
assert!((-i << 4).to_string() == (-&j << 4).to_string());
|
||||
assert!((i >> 4).to_string() == (&j >> 4).to_string());
|
||||
assert!((-i >> 4).to_string() == (-&j >> 4).to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_compl() {
|
||||
let a: Mpz = From::<i64>::from(13);
|
||||
let b: Mpz = From::<i64>::from(-442);
|
||||
assert!(a.compl().to_string() == (!13i32).to_string());
|
||||
assert!(b.compl().to_string() == (!-442i32).to_string());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pow() {
|
||||
let a: Mpz = From::<i64>::from(2);
|
||||
let b: Mpz = From::<i64>::from(8);
|
||||
assert!(a.pow(3) == b);
|
||||
assert!(Mpz::ui_pow_ui(2, 3) == b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_powm() {
|
||||
let a: Mpz = From::<i64>::from(13);
|
||||
let b: Mpz = From::<i64>::from(7);
|
||||
let p: Mpz = From::<i64>::from(19);
|
||||
let c: Mpz = From::<i64>::from(10);
|
||||
assert!(a.powm(&b, &p) == c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_powm_sec() {
|
||||
let a: Mpz = From::<i64>::from(13);
|
||||
let b: Mpz = From::<i64>::from(7);
|
||||
let p: Mpz = From::<i64>::from(19);
|
||||
let c: Mpz = From::<i64>::from(10);
|
||||
assert!(a.powm_sec(&b, &p) == c);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_popcount() {
|
||||
assert_eq!(Mpz::from_str_radix("1010010011", 2).unwrap().popcount(), 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hamdist() {
|
||||
let a: Mpz = From::<i64>::from(0b1011_0001);
|
||||
let b: Mpz = From::<i64>::from(0b0010_1011);
|
||||
assert!(a.hamdist(&b) == 4);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bit_length() {
|
||||
let a: Mpz = From::<i64>::from(0b1011_0000_0001_0000);
|
||||
let b: Mpz = From::<i64>::from(0b101);
|
||||
assert!(a.bit_length() == 16);
|
||||
assert!(b.bit_length() == 3);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_probab_prime() {
|
||||
let prime: Mpz = From::<i64>::from(2);
|
||||
assert!(prime.probab_prime(15) == ProbabPrimeResult::Prime);
|
||||
|
||||
let not_prime: Mpz = From::<i64>::from(4);
|
||||
assert!(not_prime.probab_prime(15) == ProbabPrimeResult::NotPrime);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nextprime() {
|
||||
let a: Mpz = From::<i64>::from(123456);
|
||||
let b: Mpz = From::<i64>::from(123457);
|
||||
assert!(a.nextprime() == b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gcd() {
|
||||
let zero: Mpz = From::<i64>::from(0);
|
||||
let three: Mpz = From::<i64>::from(3);
|
||||
let six: Mpz = From::<i64>::from(6);
|
||||
let eighteen: Mpz = From::<i64>::from(18);
|
||||
let twentyfour: Mpz = From::<i64>::from(24);
|
||||
assert!(zero.gcd(&zero) == zero);
|
||||
assert!(three.gcd(&six) == three);
|
||||
assert!(eighteen.gcd(&twentyfour) == six);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gcdext() {
|
||||
let six: Mpz = From::<i64>::from(6);
|
||||
let eighteen: Mpz = From::<i64>::from(18);
|
||||
let twentyfour: Mpz = From::<i64>::from(24);
|
||||
let (g, s, t) = eighteen.gcdext(&twentyfour);
|
||||
assert!(g == six);
|
||||
assert!(g == s*eighteen + t*twentyfour);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lcm() {
|
||||
let zero: Mpz = From::<i64>::from(0);
|
||||
let three: Mpz = From::<i64>::from(3);
|
||||
let five: Mpz = From::<i64>::from(5);
|
||||
let six: Mpz = From::<i64>::from(6);
|
||||
let eighteen: Mpz = From::<i64>::from(18);
|
||||
let twentyfour: Mpz = From::<i64>::from(24);
|
||||
let seventytwo: Mpz = From::<i64>::from(72);
|
||||
assert!(zero.lcm(&five) == zero);
|
||||
assert!(five.lcm(&zero) == zero);
|
||||
assert!(three.lcm(&six) == six);
|
||||
assert!(eighteen.lcm(&twentyfour) == seventytwo);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_is_multiple_of() {
|
||||
let two: Mpz = From::<i64>::from(2);
|
||||
let three: Mpz = From::<i64>::from(3);
|
||||
let six: Mpz = From::<i64>::from(6);
|
||||
assert!(six.is_multiple_of(&two));
|
||||
assert!(six.is_multiple_of(&three));
|
||||
assert!(!three.is_multiple_of(&two));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_modulus() {
|
||||
let minusone: Mpz = From::<i64>::from(-1);
|
||||
let two: Mpz = From::<i64>::from(2);
|
||||
let three: Mpz = From::<i64>::from(3);
|
||||
assert_eq!(two.modulus(&three), two);
|
||||
assert_eq!(minusone.modulus(&three), two);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invert() {
|
||||
let two: Mpz = From::<i64>::from(2);
|
||||
let three: Mpz = From::<i64>::from(3);
|
||||
let four: Mpz = From::<i64>::from(4);
|
||||
let five: Mpz = From::<i64>::from(5);
|
||||
let eleven: Mpz = From::<i64>::from(11);
|
||||
assert!(three.invert(&eleven) == Some(four.clone()));
|
||||
assert!(four.invert(&eleven) == Some(three.clone()));
|
||||
assert!(two.invert(&five) == Some(three.clone()));
|
||||
assert!(three.invert(&five) == Some(two.clone()));
|
||||
assert!(two.invert(&four).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_one() {
|
||||
let onea: Mpz = From::<i64>::from(1);
|
||||
let oneb: Mpz = From::<i64>::from(1);
|
||||
assert!(onea == oneb);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_bit_fiddling() {
|
||||
let mut xs: Mpz = From::<i64>::from(0b1010_1000_0010_0011);
|
||||
assert!(xs.bit_length() == 16);
|
||||
let mut ys = [true, false, true, false,
|
||||
true, false, false, false,
|
||||
false, false, true, false,
|
||||
false, false, true, true];
|
||||
ys.reverse();
|
||||
for i in 0..xs.bit_length() {
|
||||
assert!(xs.tstbit(i) == ys[i]);
|
||||
}
|
||||
xs.setbit(0);
|
||||
ys[0] = true;
|
||||
xs.setbit(3);
|
||||
ys[3] = true;
|
||||
xs.clrbit(1);
|
||||
ys[1] = false;
|
||||
xs.clrbit(5);
|
||||
ys[5] = false;
|
||||
xs.combit(14);
|
||||
ys[14] = !ys[14];
|
||||
xs.combit(15);
|
||||
ys[15] = !ys[15];
|
||||
for i in 0..xs.bit_length() {
|
||||
assert!(xs.tstbit(i) == ys[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_root() {
|
||||
let x: Mpz = From::<i64>::from(123456);
|
||||
let y: Mpz = From::<i64>::from(49);
|
||||
assert!(x.root(3) == y);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sqrt() {
|
||||
let x: Mpz = From::<i64>::from(567);
|
||||
let y: Mpz = From::<i64>::from(23);
|
||||
assert!(x.sqrt() == y);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_short() {
|
||||
let zero: Mpz = From::<i64>::from(0);
|
||||
let one: Mpz = From::<i64>::from(1);
|
||||
let two = &one + &one;
|
||||
|
||||
let hash = |x : &Mpz| {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
x.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
|
||||
assert!(hash(&zero) != hash(&one));
|
||||
assert_eq!(hash(&one), hash(&(&two - &one)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hash_long() {
|
||||
let a = Mpz::from_str_radix("348917329847193287498312749187234192387", 10)
|
||||
.unwrap();
|
||||
let b = Mpz::from_str_radix("348917329847193287498312749187234192386", 10)
|
||||
.unwrap();
|
||||
let one: Mpz = From::<i64>::from(1);
|
||||
|
||||
let hash = |x : &Mpz| {
|
||||
let mut hasher = DefaultHasher::new();
|
||||
x.hash(&mut hasher);
|
||||
hasher.finish()
|
||||
};
|
||||
|
||||
assert!(hash(&a) != hash(&b));
|
||||
assert_eq!(hash(&a), hash(&(&b + &one)));
|
||||
assert_eq!(hash(&(&a - &a)), hash(&(&one - &one)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_vec_u8() {
|
||||
let minus_five: Mpz = From::<i64>::from(-5);
|
||||
let minus_one: Mpz = From::<i64>::from(-1);
|
||||
let zero: Mpz = From::<i64>::from(0);
|
||||
let one: Mpz = From::<i64>::from(1);
|
||||
let five: Mpz = From::<i64>::from(5);
|
||||
let xffff: Mpz = From::<i64>::from(65535);
|
||||
let max_u64: Mpz = From::<u64>::from(u64::MAX);
|
||||
|
||||
assert_eq!(Into::<Vec<u8>>::into(&minus_five), vec!(5u8));
|
||||
assert_eq!(Into::<Vec<u8>>::into(&minus_one), vec!(1u8));
|
||||
assert_eq!(Into::<Vec<u8>>::into(&zero), vec!(0u8));
|
||||
assert_eq!(Into::<Vec<u8>>::into(&one), vec!(1u8));
|
||||
assert_eq!(Into::<Vec<u8>>::into(&five), vec!(5u8));
|
||||
assert_eq!(Into::<Vec<u8>>::into(&xffff), vec!(255u8, 255u8));
|
||||
assert_eq!(Into::<Vec<u8>>::into(&max_u64), vec!(255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_u64() {
|
||||
let minus_five: Mpz = From::<i64>::from(-5);
|
||||
let minus_one: Mpz = From::<i64>::from(-1);
|
||||
let zero: Mpz = From::<i64>::from(0);
|
||||
let one: Mpz = From::<i64>::from(1);
|
||||
let five: Mpz = From::<i64>::from(5);
|
||||
let max_u64: Mpz = From::<u64>::from(u64::MAX);
|
||||
|
||||
assert_eq!(Into::<Option<u64>>::into(&minus_five), None);
|
||||
assert_eq!(Into::<Option<u64>>::into(&minus_one), None);
|
||||
assert_eq!(Into::<Option<u64>>::into(&zero), Some(0u64));
|
||||
assert_eq!(Into::<Option<u64>>::into(&one), Some(1u64));
|
||||
assert_eq!(Into::<Option<u64>>::into(&five), Some(5u64));
|
||||
assert_eq!(Into::<Option<u64>>::into(&max_u64), Some(u64::MAX));
|
||||
assert_eq!(Into::<Option<u64>>::into(&(&max_u64 + &one)), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_to_i64() {
|
||||
let min_i64: Mpz = From::<i64>::from(i64::MIN);
|
||||
let minus_five: Mpz = From::<i64>::from(-5);
|
||||
let minus_one: Mpz = From::<i64>::from(-1);
|
||||
let zero: Mpz = From::<i64>::from(0);
|
||||
let one: Mpz = From::<i64>::from(1);
|
||||
let five: Mpz = From::<i64>::from(5);
|
||||
let max_i64: Mpz = From::<i64>::from(i64::MAX);
|
||||
|
||||
assert_eq!(Into::<Option<i64>>::into(&(&min_i64 - &one)), None);
|
||||
assert_eq!(Into::<Option<i64>>::into(&min_i64), Some(i64::MIN));
|
||||
assert_eq!(Into::<Option<i64>>::into(&minus_five), Some(-5i64));
|
||||
assert_eq!(Into::<Option<i64>>::into(&minus_one), Some(-1i64));
|
||||
assert_eq!(Into::<Option<i64>>::into(&zero), Some(0i64));
|
||||
assert_eq!(Into::<Option<i64>>::into(&one), Some(1i64));
|
||||
assert_eq!(Into::<Option<i64>>::into(&five), Some(5i64));
|
||||
assert_eq!(Into::<Option<i64>>::into(&max_i64), Some(i64::MAX));
|
||||
assert_eq!(Into::<Option<i64>>::into(&(&max_i64 + &one)), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sign() {
|
||||
let zero: Mpz = From::<i64>::from(0);
|
||||
let five: Mpz = From::<i64>::from(5);
|
||||
let minus_five: Mpz = From::<i64>::from(-5);
|
||||
|
||||
assert_eq!(zero.sign(), Sign::Zero);
|
||||
assert_eq!(five.sign(), Sign::Positive);
|
||||
assert_eq!(minus_five.sign(), Sign::Negative);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_format() {
|
||||
let zero = Mpz::zero();
|
||||
assert_eq!(format!("{}", zero), "0");
|
||||
let zero = Mpz::from(-51213);
|
||||
assert_eq!(format!("{}", zero), "-51213");
|
||||
}
|
||||
}
|
90
crates/classgroup/src/gmp_classgroup/congruence.rs
Normal file
90
crates/classgroup/src/gmp_classgroup/congruence.rs
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
#![forbid(unsafe_code)]
|
||||
use self::ffi::Mpz;
|
||||
use super::ffi;
|
||||
|
||||
/// Stores temporary values for congruence computations, to avoid
|
||||
/// repeated allocations.
|
||||
///
|
||||
/// It is allowed (but inefficient) to generate a fresh `CongruenceContest`
|
||||
/// for each call to `solve_linear_congruence`.
|
||||
///
|
||||
/// `self.solve_linear_congruence` can be called no matter what values
|
||||
/// this struct’s public members hold, so long as they are valid `Mpz` values.
|
||||
/// However, the values of these members after such a call must not be relied
|
||||
/// on.
|
||||
#[derive(Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
pub struct CongruenceContext {
|
||||
pub g: Mpz,
|
||||
pub d: Mpz,
|
||||
pub q: Mpz,
|
||||
pub r: Mpz,
|
||||
}
|
||||
|
||||
// #[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
// struct NoCongruence;
|
||||
|
||||
impl Default for CongruenceContext {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
g: Mpz::new(),
|
||||
d: Mpz::new(),
|
||||
q: Mpz::new(),
|
||||
r: Mpz::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CongruenceContext {
|
||||
/// Solves `a*x = b (mod m)`, storing `x` in `mu`
|
||||
///
|
||||
/// This function may clobber any or all of `self`’s member variables.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the congruence could not be solved.
|
||||
pub fn solve_linear_congruence(
|
||||
&mut self,
|
||||
mu: &mut Mpz,
|
||||
v: Option<&mut Mpz>,
|
||||
a: &Mpz,
|
||||
b: &Mpz,
|
||||
m: &Mpz,
|
||||
) {
|
||||
ffi::mpz_gcdext(&mut self.g, &mut self.d, mu, a, m);
|
||||
if cfg!(test) {
|
||||
println!(
|
||||
"g = {}, d = {}, e = {}, a = {}, m = {}",
|
||||
self.g, self.d, mu, a, m
|
||||
);
|
||||
}
|
||||
if cfg!(debug_assertions) {
|
||||
ffi::mpz_fdiv_qr(&mut self.q, &mut self.r, b, &self.g);
|
||||
debug_assert!(self.r.is_zero(), "Could not solve the congruence ― did you pass a non-prime or a positive number to the command line tool?!");
|
||||
} else {
|
||||
ffi::mpz_divexact(&mut self.q, b, &self.g)
|
||||
}
|
||||
ffi::mpz_mul(&mut self.r, &self.q, &self.d);
|
||||
ffi::mpz_tdiv_r(mu, &self.r, m);
|
||||
if let Some(v) = v {
|
||||
if cfg!(debug_assertions) {
|
||||
ffi::mpz_fdiv_qr(v, &mut self.r, &m, &self.g);
|
||||
debug_assert!(self.r.is_zero(), "Could not solve the congruence ― did you pass a non-prime or a positive number to the command line tool?!");
|
||||
} else {
|
||||
ffi::mpz_divexact(v, &m, &self.g)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
340
crates/classgroup/src/gmp_classgroup/ffi.rs
Normal file
340
crates/classgroup/src/gmp_classgroup/ffi.rs
Normal file
@ -0,0 +1,340 @@
|
||||
// Copyright 2018 POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
//! FFI bindings to GMP. This module exists because the `rust-gmp` crate
|
||||
//! is too high-level. High-performance bignum computation requires that
|
||||
//! bignums be modified in-place, so that their storage can be reused.
|
||||
//! Furthermore, the `rust-gmp` crate doesn’t support many operations that
|
||||
//! this library requires.
|
||||
#![allow(unsafe_code)]
|
||||
pub use super::super::gmp::mpz::Mpz;
|
||||
use super::super::gmp::mpz::{mp_bitcnt_t, mp_limb_t};
|
||||
use libc::{c_int, c_long, c_ulong, c_void, size_t};
|
||||
// pub use c_ulong;
|
||||
use std::{mem, usize};
|
||||
// We use the unsafe versions to avoid unecessary allocations.
|
||||
#[link(name = "gmp", kind = "static")]
|
||||
extern "C" {
|
||||
fn __gmpz_gcdext(gcd: *mut Mpz, s: *mut Mpz, t: *mut Mpz, a: *const Mpz, b: *const Mpz);
|
||||
fn __gmpz_gcd(rop: *mut Mpz, op1: *const Mpz, op2: *const Mpz);
|
||||
fn __gmpz_fdiv_qr(q: *mut Mpz, r: *mut Mpz, b: *const Mpz, g: *const Mpz);
|
||||
fn __gmpz_fdiv_q(q: *mut Mpz, n: *const Mpz, d: *const Mpz);
|
||||
fn __gmpz_divexact(q: *mut Mpz, n: *const Mpz, d: *const Mpz);
|
||||
fn __gmpz_tdiv_q(q: *mut Mpz, n: *const Mpz, d: *const Mpz);
|
||||
fn __gmpz_mul(p: *mut Mpz, a: *const Mpz, b: *const Mpz);
|
||||
fn __gmpz_mul_2exp(rop: *mut Mpz, op1: *const Mpz, op2: mp_bitcnt_t);
|
||||
fn __gmpz_sub(rop: *mut Mpz, op1: *const Mpz, op2: *const Mpz);
|
||||
fn __gmpz_import(
|
||||
rop: *mut Mpz,
|
||||
count: size_t,
|
||||
order: c_int,
|
||||
size: size_t,
|
||||
endian: c_int,
|
||||
nails: size_t,
|
||||
op: *const c_void,
|
||||
);
|
||||
fn __gmpz_tdiv_r(r: *mut Mpz, n: *const Mpz, d: *const Mpz);
|
||||
fn __gmpz_sizeinbase(op: &Mpz, base: c_int) -> size_t;
|
||||
fn __gmpz_fdiv_q_ui(rop: *mut Mpz, op1: *const Mpz, op2: c_ulong) -> c_ulong;
|
||||
fn __gmpz_add(rop: *mut Mpz, op1: *const Mpz, op2: *const Mpz);
|
||||
fn __gmpz_add_ui(rop: *mut Mpz, op1: *const Mpz, op2: c_ulong);
|
||||
fn __gmpz_set_ui(rop: &mut Mpz, op: c_ulong);
|
||||
fn __gmpz_set_si(rop: &mut Mpz, op: c_long);
|
||||
fn __gmpz_cdiv_ui(n: &Mpz, d: c_ulong) -> c_ulong;
|
||||
fn __gmpz_fdiv_ui(n: &Mpz, d: c_ulong) -> c_ulong;
|
||||
fn __gmpz_tdiv_ui(n: &Mpz, d: c_ulong) -> c_ulong;
|
||||
fn __gmpz_export(
|
||||
rop: *mut c_void,
|
||||
countp: *mut size_t,
|
||||
order: c_int,
|
||||
size: size_t,
|
||||
endian: c_int,
|
||||
nails: size_t,
|
||||
op: &Mpz,
|
||||
) -> *mut c_void;
|
||||
fn __gmpz_powm(rop: *mut Mpz, base: *const Mpz, exp: *const Mpz, modulus: *const Mpz);
|
||||
}
|
||||
|
||||
// MEGA HACK: rust-gmp doesn’t expose the fields of this struct, so we must define
|
||||
// it ourselves and cast.
|
||||
//
|
||||
// Should be stable though, as only GMP can change it, and doing would break binary compatibility.
|
||||
#[repr(C)]
|
||||
struct MpzStruct {
|
||||
mp_alloc: c_int,
|
||||
mp_size: c_int,
|
||||
mp_d: *mut mp_limb_t,
|
||||
}
|
||||
|
||||
macro_rules! impl_div_ui {
|
||||
($t:ident, $i:ident, $f:expr) => {
|
||||
pub fn $i(n: &Mpz, d: $t) -> $t {
|
||||
use std::$t;
|
||||
let res = unsafe { $f(n, c_ulong::from(d)) };
|
||||
assert!(res <= $t::MAX.into());
|
||||
res as $t
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_div_ui!(u16, mpz_crem_u16, __gmpz_cdiv_ui);
|
||||
impl_div_ui!(u32, mpz_frem_u32, __gmpz_fdiv_ui);
|
||||
|
||||
/// Returns `true` if `z` is negative and not zero. Otherwise,
|
||||
/// returns `false`.
|
||||
#[inline]
|
||||
pub fn mpz_is_negative(z: &Mpz) -> bool {
|
||||
unsafe { (*(z as *const _ as *const MpzStruct)).mp_size < 0 }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mpz_powm(rop: &mut Mpz, base: &Mpz, exponent: &Mpz, modulus: &Mpz) {
|
||||
unsafe { __gmpz_powm(rop, base, exponent, modulus) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mpz_tdiv_r(r: &mut Mpz, n: &Mpz, d: &Mpz) {
|
||||
unsafe { __gmpz_tdiv_r(r, n, d) }
|
||||
}
|
||||
|
||||
/// Sets `g` to the GCD of `a` and `b`.
|
||||
#[inline]
|
||||
pub fn mpz_gcdext(gcd: &mut Mpz, s: &mut Mpz, t: &mut Mpz, a: &Mpz, b: &Mpz) {
|
||||
unsafe { __gmpz_gcdext(gcd, s, t, a, b) }
|
||||
}
|
||||
|
||||
/// Doubles `rop` in-place
|
||||
#[inline]
|
||||
pub fn mpz_double(rop: &mut Mpz) {
|
||||
if true {
|
||||
// slightly faster
|
||||
unsafe { __gmpz_mul_2exp(rop, rop, 1) }
|
||||
} else {
|
||||
unsafe { __gmpz_add(rop, rop, rop) }
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mpz_fdiv_qr(q: &mut Mpz, r: &mut Mpz, b: &Mpz, g: &Mpz) {
|
||||
unsafe { __gmpz_fdiv_qr(q, r, b, g) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mpz_fdiv_q_ui_self(rop: &mut Mpz, op: c_ulong) -> c_ulong {
|
||||
unsafe { __gmpz_fdiv_q_ui(rop, rop, op) }
|
||||
}
|
||||
|
||||
/// Unmarshals a buffer to an `Mpz`. `buf` is interpreted as a 2’s complement,
|
||||
/// big-endian integer. If the buffer is empty, zero is returned.
|
||||
pub fn import_obj(buf: &[u8]) -> Mpz {
|
||||
fn raw_import(buf: &[u8]) -> Mpz {
|
||||
let mut obj = Mpz::new();
|
||||
|
||||
unsafe { __gmpz_import(&mut obj, buf.len(), 1, 1, 1, 0, buf.as_ptr() as *const _) }
|
||||
obj
|
||||
}
|
||||
let is_negative = match buf.first() {
|
||||
None => return Mpz::zero(),
|
||||
Some(x) => x & 0x80 != 0,
|
||||
};
|
||||
if !is_negative {
|
||||
raw_import(buf)
|
||||
} else {
|
||||
let mut new_buf: Vec<_> = buf.iter().cloned().skip_while(|&x| x == 0xFF).collect();
|
||||
if new_buf.is_empty() {
|
||||
(-1).into()
|
||||
} else {
|
||||
for i in &mut new_buf {
|
||||
*i ^= 0xFF
|
||||
}
|
||||
!raw_import(&new_buf)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn three_gcd(rop: &mut Mpz, a: &Mpz, b: &Mpz, c: &Mpz) {
|
||||
unsafe {
|
||||
__gmpz_gcd(rop, a, b);
|
||||
__gmpz_gcd(rop, rop, c)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn size_in_bits(obj: &Mpz) -> usize {
|
||||
unsafe { __gmpz_sizeinbase(obj, 2) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mpz_add(rop: &mut Mpz, op1: &Mpz, op2: &Mpz) {
|
||||
unsafe { __gmpz_add(rop, op1, op2) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mpz_mul(rop: &mut Mpz, op1: &Mpz, op2: &Mpz) {
|
||||
unsafe { __gmpz_mul(rop, op1, op2) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mpz_divexact(q: &mut Mpz, n: &Mpz, d: &Mpz) {
|
||||
unsafe { __gmpz_divexact(q, n, d) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mpz_mul_2exp(rop: &mut Mpz, op1: &Mpz, op2: mp_bitcnt_t) {
|
||||
unsafe { __gmpz_mul_2exp(rop as *mut _ as *mut Mpz, op1, op2) }
|
||||
}
|
||||
|
||||
/// Divide `n` by `d`. Round towards -∞ and place the result in `q`.
|
||||
#[inline]
|
||||
pub fn mpz_fdiv_q(q: &mut Mpz, n: &Mpz, d: &Mpz) {
|
||||
if mpz_is_negative(n) == mpz_is_negative(d) {
|
||||
unsafe { __gmpz_tdiv_q(q, n, d) }
|
||||
} else {
|
||||
unsafe { __gmpz_fdiv_q(q, n, d) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets `rop` to `(-1) * op`
|
||||
#[inline]
|
||||
#[cfg(none)]
|
||||
pub fn mpz_neg(rop: &mut Mpz) {
|
||||
assert!(mem::size_of::<Mpz>() == mem::size_of::<MpzStruct>());
|
||||
unsafe {
|
||||
let ptr = rop as *mut _ as *mut MpzStruct;
|
||||
let v = (*ptr).mp_size;
|
||||
(*ptr).mp_size = -v;
|
||||
}
|
||||
}
|
||||
|
||||
/// Subtracts `op2` from `op1` and stores the result in `rop`.
|
||||
#[inline]
|
||||
pub fn mpz_sub(rop: &mut Mpz, op1: &Mpz, op2: &Mpz) {
|
||||
unsafe { __gmpz_sub(rop as *mut _ as *mut Mpz, op1, op2) }
|
||||
}
|
||||
|
||||
/// Exports `obj` to `v` as an array of 2’s complement, big-endian
|
||||
/// bytes. If `v` is too small to hold the result, returns `Err(s)`,
|
||||
/// where `s` is the size needed to hold the exported version of `obj`.
|
||||
pub fn export_obj(obj: &Mpz, v: &mut [u8]) -> Result<(), usize> {
|
||||
// Requires: offset < v.len() and v[offset..] be able to hold all of `obj`
|
||||
unsafe fn raw_export(v: &mut [u8], offset: usize, obj: &Mpz) -> usize {
|
||||
// SAFE as `offset` will always be in-bounds, since byte_len always <=
|
||||
// byte_len_needed and we check that v.len() >= byte_len_needed.
|
||||
let ptr = v.as_mut_ptr().add(offset) as *mut c_void;
|
||||
|
||||
// Necessary ― this byte may not be fully overwritten
|
||||
*(ptr as *mut u8) = 0;
|
||||
|
||||
// SAFE as __gmpz_export will *always* initialize this.
|
||||
let mut s: usize = mem::uninitialized();
|
||||
let ptr2 = __gmpz_export(ptr, &mut s, 1, 1, 1, 0, obj);
|
||||
assert_eq!(ptr, ptr2);
|
||||
if 0 == s {
|
||||
1
|
||||
} else {
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
let size = size_in_bits(obj);
|
||||
assert!(size > 0);
|
||||
|
||||
// Check to avoid integer overflow in later operations.
|
||||
if size > usize::MAX - 8 || v.len() > usize::MAX >> 3 {
|
||||
return Err(usize::MAX);
|
||||
}
|
||||
|
||||
// One additional bit is needed for the sign bit.
|
||||
let byte_len_needed = (size + 8) >> 3;
|
||||
if v.len() < byte_len_needed {
|
||||
return if v.is_empty() && obj.is_zero() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(byte_len_needed)
|
||||
};
|
||||
}
|
||||
let is_negative = mpz_is_negative(obj);
|
||||
|
||||
if is_negative {
|
||||
// MEGA HACK: GMP does not have a function to perform 2's complement
|
||||
let obj = !obj;
|
||||
debug_assert!(
|
||||
!mpz_is_negative(&obj),
|
||||
"bitwise negation of a negative number produced a negative number"
|
||||
);
|
||||
let new_byte_size = (size_in_bits(&obj) + 7) >> 3;
|
||||
let offset = v.len() - new_byte_size;
|
||||
|
||||
for i in &mut v[..offset] {
|
||||
*i = 0xFF
|
||||
}
|
||||
unsafe {
|
||||
assert_eq!(raw_export(v, offset, &obj), new_byte_size);
|
||||
}
|
||||
|
||||
// We had to do a one’s complement to get the data in a decent format,
|
||||
// so now we need to flip all of the bits back. LLVM should be able to
|
||||
// vectorize this loop easily.
|
||||
for i in &mut v[offset..] {
|
||||
*i ^= 0xFF
|
||||
}
|
||||
} else {
|
||||
// ...but GMP will not include that in the number of bytes it writes
|
||||
// (except for negative numbers)
|
||||
let byte_len = (size + 7) >> 3;
|
||||
assert!(byte_len > 0);
|
||||
|
||||
let offset = v.len() - byte_len;
|
||||
|
||||
// Zero out any leading bytes
|
||||
for i in &mut v[..offset] {
|
||||
*i = 0
|
||||
}
|
||||
unsafe {
|
||||
assert_eq!(raw_export(v, offset, &obj), byte_len);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn check_expected_bit_width() {
|
||||
let mut s: Mpz = (-2).into();
|
||||
assert_eq!(size_in_bits(&s), 2);
|
||||
s = !s;
|
||||
assert_eq!(s, 1.into());
|
||||
s.setbit(2);
|
||||
assert_eq!(s, 5.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_export() {
|
||||
let mut s: Mpz = 0x100.into();
|
||||
s = !s;
|
||||
let mut buf = [0, 0, 0];
|
||||
export_obj(&s, &mut buf).expect("buffer should be large enough");
|
||||
assert_eq!(buf, [0xFF, 0xFE, 0xFF]);
|
||||
export_obj(&Mpz::zero(), &mut []).unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_rem() {
|
||||
assert_eq!(mpz_crem_u16(&(-100i64).into(), 3), 1);
|
||||
assert_eq!(mpz_crem_u16(&(100i64).into(), 3), 2);
|
||||
}
|
||||
}
|
590
crates/classgroup/src/gmp_classgroup/mod.rs
Normal file
590
crates/classgroup/src/gmp_classgroup/mod.rs
Normal file
@ -0,0 +1,590 @@
|
||||
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
#![deny(unsafe_code)]
|
||||
use super::ClassGroup;
|
||||
use super::gmp::mpz::Mpz;
|
||||
use super::gmp::mpz::ProbabPrimeResult::NotPrime;
|
||||
use num_traits::{One, Zero};
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
cell::RefCell,
|
||||
mem::swap,
|
||||
ops::{Mul, MulAssign},
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
|
||||
mod congruence;
|
||||
pub(super) mod ffi;
|
||||
|
||||
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Clone)]
|
||||
pub struct GmpClassGroup {
|
||||
a: Mpz,
|
||||
b: Mpz,
|
||||
c: Mpz,
|
||||
discriminant: Mpz,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, PartialOrd, Eq, Ord, Clone, Hash, Debug)]
|
||||
pub struct Ctx {
|
||||
negative_a: Mpz,
|
||||
r: Mpz,
|
||||
denom: Mpz,
|
||||
old_a: Mpz,
|
||||
old_b: Mpz,
|
||||
ra: Mpz,
|
||||
s: Mpz,
|
||||
x: Mpz,
|
||||
congruence_context: congruence::CongruenceContext,
|
||||
h: Mpz,
|
||||
w: Mpz,
|
||||
m: Mpz,
|
||||
u: Mpz,
|
||||
a: Mpz,
|
||||
l: Mpz,
|
||||
j: Mpz,
|
||||
b: Mpz,
|
||||
k: Mpz,
|
||||
t: Mpz,
|
||||
mu: Mpz,
|
||||
v: Mpz,
|
||||
sigma: Mpz,
|
||||
lambda: Mpz,
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static CTX: RefCell<Ctx> = Default::default();
|
||||
}
|
||||
|
||||
impl GmpClassGroup {
|
||||
pub fn into_raw(self) -> (Mpz, Mpz) {
|
||||
(self.a, self.b)
|
||||
}
|
||||
|
||||
fn inner_multiply(&mut self, rhs: &Self, ctx: &mut Ctx) {
|
||||
self.assert_valid();
|
||||
rhs.assert_valid();
|
||||
|
||||
// g = (b1 + b2) / 2
|
||||
ffi::mpz_add(&mut ctx.congruence_context.g, &self.b, &rhs.b);
|
||||
ffi::mpz_fdiv_q_ui_self(&mut ctx.congruence_context.g, 2);
|
||||
|
||||
// h = (b2 - b1) / 2
|
||||
ffi::mpz_sub(&mut ctx.h, &rhs.b, &self.b);
|
||||
ffi::mpz_fdiv_q_ui_self(&mut ctx.h, 2);
|
||||
|
||||
debug_assert!(&ctx.h + &ctx.congruence_context.g == rhs.b);
|
||||
debug_assert!(&ctx.congruence_context.g - &ctx.h == self.b);
|
||||
|
||||
// w = gcd(a1, a2, g)
|
||||
ffi::three_gcd(&mut ctx.w, &self.a, &rhs.a, &ctx.congruence_context.g);
|
||||
|
||||
// j = w
|
||||
ctx.j.set(&ctx.w);
|
||||
|
||||
// s = a1/w
|
||||
ffi::mpz_fdiv_q(&mut ctx.s, &self.a, &ctx.w);
|
||||
|
||||
// t = a2/w
|
||||
ffi::mpz_fdiv_q(&mut ctx.t, &rhs.a, &ctx.w);
|
||||
|
||||
// u = g/w
|
||||
ffi::mpz_fdiv_q(&mut ctx.u, &ctx.congruence_context.g, &ctx.w);
|
||||
|
||||
// a = t*u
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.t, &ctx.u);
|
||||
|
||||
// b = h*u - s*c1
|
||||
ffi::mpz_mul(&mut ctx.b, &ctx.h, &ctx.u);
|
||||
ffi::mpz_mul(&mut ctx.m, &ctx.s, &self.c);
|
||||
ctx.b += &ctx.m;
|
||||
|
||||
// m = s*t
|
||||
ffi::mpz_mul(&mut ctx.m, &ctx.s, &ctx.t);
|
||||
ctx.congruence_context.solve_linear_congruence(
|
||||
&mut ctx.mu,
|
||||
Some(&mut ctx.v),
|
||||
&ctx.a,
|
||||
&ctx.b,
|
||||
&ctx.m,
|
||||
);
|
||||
|
||||
// a = t*v
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.t, &ctx.v);
|
||||
|
||||
// b = h - t * mu
|
||||
ffi::mpz_mul(&mut ctx.m, &ctx.t, &ctx.mu);
|
||||
ffi::mpz_sub(&mut ctx.b, &ctx.h, &ctx.m);
|
||||
|
||||
// m = s
|
||||
ctx.m.set(&ctx.s);
|
||||
|
||||
ctx.congruence_context.solve_linear_congruence(
|
||||
&mut ctx.lambda,
|
||||
Some(&mut ctx.sigma),
|
||||
&ctx.a,
|
||||
&ctx.b,
|
||||
&ctx.m,
|
||||
);
|
||||
|
||||
// k = mu + v*lambda
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.v, &ctx.lambda);
|
||||
ffi::mpz_add(&mut ctx.k, &ctx.mu, &ctx.a);
|
||||
|
||||
// l = (k*t - h)/s
|
||||
ffi::mpz_mul(&mut ctx.l, &ctx.k, &ctx.t);
|
||||
ffi::mpz_sub(&mut ctx.v, &ctx.l, &ctx.h);
|
||||
ffi::mpz_fdiv_q(&mut ctx.l, &ctx.v, &ctx.s);
|
||||
|
||||
// m = (t*u*k - h*u - c*s) / s*t
|
||||
ffi::mpz_mul(&mut ctx.m, &ctx.t, &ctx.u);
|
||||
ctx.m *= &ctx.k;
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.h, &ctx.u);
|
||||
ctx.m -= &ctx.a;
|
||||
ffi::mpz_mul(&mut ctx.a, &self.c, &ctx.s);
|
||||
ctx.m -= &ctx.a;
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.s, &ctx.t);
|
||||
ffi::mpz_fdiv_q(&mut ctx.lambda, &ctx.m, &ctx.a);
|
||||
|
||||
// A = s*t - r*u
|
||||
ffi::mpz_mul(&mut self.a, &ctx.s, &ctx.t);
|
||||
|
||||
// B = ju + mr - (kt + ls)
|
||||
ffi::mpz_mul(&mut self.b, &ctx.j, &ctx.u);
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.k, &ctx.t);
|
||||
self.b -= &ctx.a;
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.l, &ctx.s);
|
||||
self.b -= &ctx.a;
|
||||
|
||||
// C = kl - jm
|
||||
ffi::mpz_mul(&mut self.c, &ctx.k, &ctx.l);
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.j, &ctx.lambda);
|
||||
self.c -= &ctx.a;
|
||||
|
||||
self.inner_reduce(ctx);
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn new(a: Mpz, b: Mpz, c: Mpz, discriminant: Mpz) -> Self {
|
||||
let s = GmpClassGroup {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
discriminant,
|
||||
};
|
||||
s.assert_valid();
|
||||
s
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn assert_valid(&self) {
|
||||
if cfg!(debug_assertions) {
|
||||
let four: Mpz = 4u64.into();
|
||||
let four_ac: Mpz = four * &self.a * &self.c;
|
||||
assert!(&self.discriminant + four_ac == &self.b * &self.b);
|
||||
}
|
||||
}
|
||||
|
||||
fn inner_normalize(&mut self, ctx: &mut Ctx) {
|
||||
self.assert_valid();
|
||||
ctx.negative_a = -&self.a;
|
||||
if self.b > ctx.negative_a && self.b <= self.a {
|
||||
return;
|
||||
}
|
||||
ffi::mpz_sub(&mut ctx.r, &self.a, &self.b);
|
||||
ffi::mpz_mul_2exp(&mut ctx.denom, &self.a, 1);
|
||||
ffi::mpz_fdiv_q(&mut ctx.negative_a, &ctx.r, &ctx.denom);
|
||||
swap(&mut ctx.negative_a, &mut ctx.r);
|
||||
swap(&mut ctx.old_b, &mut self.b);
|
||||
ffi::mpz_mul(&mut ctx.ra, &ctx.r, &self.a);
|
||||
ffi::mpz_mul_2exp(&mut ctx.negative_a, &ctx.ra, 1);
|
||||
ffi::mpz_add(&mut self.b, &ctx.old_b, &ctx.negative_a);
|
||||
|
||||
ffi::mpz_mul(&mut ctx.negative_a, &ctx.ra, &ctx.r);
|
||||
ffi::mpz_add(&mut ctx.old_a, &self.c, &ctx.negative_a);
|
||||
|
||||
ffi::mpz_mul(&mut ctx.ra, &ctx.r, &ctx.old_b);
|
||||
ffi::mpz_add(&mut self.c, &ctx.old_a, &ctx.ra);
|
||||
|
||||
self.assert_valid();
|
||||
}
|
||||
|
||||
fn inner_reduce(&mut self, ctx: &mut Ctx) {
|
||||
self.inner_normalize(ctx);
|
||||
|
||||
while if ffi::mpz_is_negative(&self.b) {
|
||||
self.a >= self.c
|
||||
} else {
|
||||
self.a > self.c
|
||||
} {
|
||||
debug_assert!(!self.c.is_zero());
|
||||
ffi::mpz_add(&mut ctx.s, &self.c, &self.b);
|
||||
ffi::mpz_add(&mut ctx.x, &self.c, &self.c);
|
||||
swap(&mut self.b, &mut ctx.old_b);
|
||||
ffi::mpz_fdiv_q(&mut self.b, &ctx.s, &ctx.x);
|
||||
swap(&mut self.b, &mut ctx.s);
|
||||
swap(&mut self.a, &mut self.c);
|
||||
|
||||
// x = 2sc
|
||||
ffi::mpz_mul(&mut self.b, &ctx.s, &self.a);
|
||||
ffi::mpz_mul_2exp(&mut ctx.x, &self.b, 1);
|
||||
|
||||
// b = x - old_b
|
||||
ffi::mpz_sub(&mut self.b, &ctx.x, &ctx.old_b);
|
||||
|
||||
// x = b*s
|
||||
ffi::mpz_mul(&mut ctx.x, &ctx.old_b, &ctx.s);
|
||||
|
||||
// s = c*s^2
|
||||
ffi::mpz_mul(&mut ctx.old_b, &ctx.s, &ctx.s);
|
||||
ffi::mpz_mul(&mut ctx.s, &self.a, &ctx.old_b);
|
||||
|
||||
// c = s - x
|
||||
ffi::mpz_sub(&mut ctx.old_a, &ctx.s, &ctx.x);
|
||||
|
||||
// c += a
|
||||
self.c += &ctx.old_a;
|
||||
}
|
||||
self.inner_normalize(ctx);
|
||||
}
|
||||
|
||||
fn inner_square_impl(&mut self, ctx: &mut Ctx) {
|
||||
self.assert_valid();
|
||||
ctx.congruence_context.solve_linear_congruence(
|
||||
&mut ctx.mu,
|
||||
None,
|
||||
&self.b,
|
||||
&self.c,
|
||||
&self.a,
|
||||
);
|
||||
ffi::mpz_mul(&mut ctx.m, &self.b, &ctx.mu);
|
||||
ctx.m -= &self.c;
|
||||
ctx.m = ctx.m.div_floor(&self.a);
|
||||
|
||||
// New a
|
||||
ctx.old_a.set(&self.a);
|
||||
ffi::mpz_mul(&mut self.a, &ctx.old_a, &ctx.old_a);
|
||||
|
||||
// New b
|
||||
ffi::mpz_mul(&mut ctx.a, &ctx.mu, &ctx.old_a);
|
||||
ffi::mpz_double(&mut ctx.a);
|
||||
self.b -= &ctx.a;
|
||||
|
||||
// New c
|
||||
ffi::mpz_mul(&mut self.c, &ctx.mu, &ctx.mu);
|
||||
self.c -= &ctx.m;
|
||||
self.inner_reduce(ctx);
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn inner_square(&mut self, ctx: &mut Ctx) {
|
||||
if cfg!(debug_assertions) {
|
||||
let mut q = self.clone();
|
||||
q.inner_multiply(self, ctx);
|
||||
self.inner_square_impl(ctx);
|
||||
assert_eq!(*self, q);
|
||||
} else {
|
||||
self.inner_square_impl(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/// Call `cb` with a mutable reference to the context of type `Ctx`.
|
||||
///
|
||||
/// The reference cannot escape the closure and cannot be sent across
|
||||
/// threads.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called recursively. This library guarantees that it will
|
||||
/// never call this function from any function that takes a parameter of
|
||||
/// type `&mut Ctx`.
|
||||
pub fn with_context<T, U>(cb: T) -> U
|
||||
where
|
||||
T: FnOnce(&mut Ctx) -> U,
|
||||
{
|
||||
let mut opt = None;
|
||||
CTX.with(|x| opt = Some(cb(&mut x.borrow_mut())));
|
||||
opt.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GmpClassGroup {
|
||||
fn default() -> Self {
|
||||
GmpClassGroup {
|
||||
a: Mpz::new(),
|
||||
b: Mpz::new(),
|
||||
c: Mpz::new(),
|
||||
discriminant: Mpz::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Borrow<GmpClassGroup>> MulAssign<B> for GmpClassGroup {
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn mul_assign(&mut self, rhs: B) {
|
||||
let rhs = rhs.borrow();
|
||||
debug_assert!(self.discriminant == rhs.discriminant);
|
||||
GmpClassGroup::with_context(|ctx| self.inner_multiply(rhs, ctx));
|
||||
}
|
||||
}
|
||||
|
||||
impl super::BigNum for Mpz {
|
||||
fn probab_prime(&self, iterations: u32) -> bool {
|
||||
let reps: i32 = iterations.try_into().expect("Iterations fits into i32");
|
||||
self.probab_prime(reps) != NotPrime
|
||||
}
|
||||
|
||||
fn setbit(&mut self, bit_index: usize) {
|
||||
self.setbit(bit_index)
|
||||
}
|
||||
|
||||
fn mod_powm(&mut self, base: &Self, exponent: &Self, modulus: &Self) {
|
||||
ffi::mpz_powm(self, base, exponent, modulus)
|
||||
}
|
||||
}
|
||||
|
||||
impl super::BigNumExt for Mpz {
|
||||
fn frem_u32(&self, modulus: u32) -> u32 {
|
||||
ffi::mpz_frem_u32(self, modulus)
|
||||
}
|
||||
fn crem_u16(&mut self, modulus: u16) -> u16 {
|
||||
ffi::mpz_crem_u16(self, modulus)
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: Borrow<Self>> Mul<B> for GmpClassGroup {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn mul(mut self, rhs: B) -> Self {
|
||||
self *= rhs.borrow();
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B: Borrow<GmpClassGroup>> Mul<B> for &'a GmpClassGroup {
|
||||
type Output = GmpClassGroup;
|
||||
|
||||
#[inline(always)]
|
||||
fn mul(self, rhs: B) -> Self::Output {
|
||||
let mut s = Clone::clone(self.borrow());
|
||||
s *= rhs;
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
impl ClassGroup for GmpClassGroup {
|
||||
type BigNum = Mpz;
|
||||
|
||||
/// Normalize `self`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called within a call to `Self::with_context`.
|
||||
fn normalize(&mut self) {
|
||||
Self::with_context(|x| self.inner_normalize(x))
|
||||
}
|
||||
|
||||
#[cfg_attr(not(debug_assertions), inline(always))]
|
||||
fn inverse(&mut self) {
|
||||
self.assert_valid();
|
||||
self.b = -self.b.clone();
|
||||
}
|
||||
|
||||
fn serialize(&self, buf: &mut [u8]) -> Result<(), usize> {
|
||||
self.assert_valid();
|
||||
if buf.len() & 1 == 1 {
|
||||
// odd lengths do not make sense
|
||||
Err(0)
|
||||
} else {
|
||||
let len = buf.len() >> 1;
|
||||
ffi::export_obj(&self.a, &mut buf[..len])?;
|
||||
ffi::export_obj(&self.b, &mut buf[len..])
|
||||
}
|
||||
}
|
||||
|
||||
fn from_bytes(bytearray: &[u8], discriminant: Self::BigNum) -> Self {
|
||||
let len = (ffi::size_in_bits(&discriminant) + 16) >> 4;
|
||||
let a = ffi::import_obj(&bytearray[..len]);
|
||||
let b = ffi::import_obj(&bytearray[len..]);
|
||||
Self::from_ab_discriminant(a, b, discriminant)
|
||||
}
|
||||
|
||||
fn from_ab_discriminant(a: Self::BigNum, b: Self::BigNum, discriminant: Self::BigNum) -> Self {
|
||||
let mut four_a: Self::BigNum = 4u64.into();
|
||||
four_a *= &a;
|
||||
let c = (&b * &b - &discriminant) / four_a;
|
||||
Self {
|
||||
a,
|
||||
b,
|
||||
c,
|
||||
discriminant,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the discriminant of `self`.
|
||||
#[inline(always)]
|
||||
fn discriminant(&self) -> &Self::BigNum {
|
||||
&self.discriminant
|
||||
}
|
||||
|
||||
fn size_in_bits(num: &Self::BigNum) -> usize {
|
||||
ffi::size_in_bits(num)
|
||||
}
|
||||
|
||||
/// Reduce `self`.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called within a call to `Self::with_context`.
|
||||
fn reduce(&mut self) {
|
||||
Self::with_context(|x| self.inner_reduce(x))
|
||||
}
|
||||
|
||||
fn deserialize(buf: &[u8], discriminant: Self::BigNum) -> Self {
|
||||
let len = buf.len();
|
||||
debug_assert!(len != 0, "Cannot deserialize an empty buffer!");
|
||||
debug_assert!(len & 1 == 0, "Buffer must be of even length");
|
||||
let half_len = len >> 1;
|
||||
Self::from_ab_discriminant(
|
||||
ffi::import_obj(&buf[..half_len]),
|
||||
ffi::import_obj(&buf[half_len..]),
|
||||
discriminant,
|
||||
)
|
||||
}
|
||||
|
||||
/// Square `self`.ClassGroupPartial
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called within the scope of a call to `with_context`.
|
||||
fn square(&mut self) {
|
||||
Self::with_context(|ctx| self.inner_square(ctx))
|
||||
}
|
||||
|
||||
fn unsigned_deserialize_bignum(buf: &[u8]) -> Self::BigNum {
|
||||
buf.into()
|
||||
}
|
||||
|
||||
/// Square `self` `iterations` times.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if called within the scope of a call to `with_context`.
|
||||
fn repeated_square(&mut self, iterations: u64) {
|
||||
Self::with_context(|ctx| {
|
||||
for _ in 0..iterations {
|
||||
self.inner_square(ctx)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
fn generator_for_discriminant(discriminant: Self::BigNum) -> Self {
|
||||
let one: Mpz = One::one();
|
||||
let x: Mpz = &one - &discriminant;
|
||||
let mut form = Self::new(2.into(), one, x.div_floor(&8.into()), discriminant);
|
||||
form.reduce();
|
||||
form
|
||||
}
|
||||
|
||||
fn pow(&mut self, mut exponent: Mpz) {
|
||||
self.assert_valid();
|
||||
debug_assert!(exponent >= Mpz::zero());
|
||||
let mut state = self.identity();
|
||||
loop {
|
||||
let is_odd = exponent.tstbit(0);
|
||||
exponent >>= 1;
|
||||
if is_odd {
|
||||
state *= &*self
|
||||
}
|
||||
if exponent.is_zero() {
|
||||
*self = state;
|
||||
break;
|
||||
}
|
||||
self.square();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for Ctx {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
negative_a: Mpz::new(),
|
||||
r: Mpz::new(),
|
||||
denom: Mpz::new(),
|
||||
old_a: Mpz::new(),
|
||||
old_b: Mpz::new(),
|
||||
ra: Mpz::new(),
|
||||
s: Mpz::new(),
|
||||
x: Mpz::new(),
|
||||
congruence_context: Default::default(),
|
||||
w: Mpz::new(),
|
||||
m: Mpz::new(),
|
||||
u: Mpz::new(),
|
||||
l: Mpz::new(),
|
||||
j: Mpz::new(),
|
||||
t: Mpz::new(),
|
||||
a: Mpz::new(),
|
||||
b: Mpz::new(),
|
||||
k: Mpz::new(),
|
||||
h: Mpz::new(),
|
||||
mu: Mpz::new(),
|
||||
v: Mpz::new(),
|
||||
sigma: Mpz::new(),
|
||||
lambda: Mpz::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn do_compute(discriminant: Mpz, iterations: u64) -> GmpClassGroup {
|
||||
debug_assert!(discriminant < Zero::zero());
|
||||
debug_assert!(discriminant.probab_prime(50) != NotPrime);
|
||||
let mut f = GmpClassGroup::generator_for_discriminant(discriminant);
|
||||
f.repeated_square(iterations);
|
||||
f
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
#![allow(unused_imports)]
|
||||
use super::*;
|
||||
#[test]
|
||||
fn normalize() {
|
||||
let mut s = GmpClassGroup::new(
|
||||
16.into(),
|
||||
(-23).into(),
|
||||
5837_3892.into(),
|
||||
(-0xdead_beefi64).into(),
|
||||
);
|
||||
let mut new = GmpClassGroup {
|
||||
b: 9.into(),
|
||||
c: 5837_3885.into(),
|
||||
..s.clone()
|
||||
};
|
||||
s.normalize();
|
||||
assert_eq!(s, new);
|
||||
|
||||
s = GmpClassGroup {
|
||||
a: (1 << 16).into(),
|
||||
b: (-76951).into(),
|
||||
c: 36840.into(),
|
||||
..s
|
||||
};
|
||||
new = GmpClassGroup {
|
||||
b: 54121.into(),
|
||||
c: 25425.into(),
|
||||
..s.clone()
|
||||
};
|
||||
s.normalize();
|
||||
assert_eq!(s, new);
|
||||
}
|
||||
}
|
251
crates/classgroup/src/lib.rs
Normal file
251
crates/classgroup/src/lib.rs
Normal file
@ -0,0 +1,251 @@
|
||||
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
#![deny(unsafe_code)]
|
||||
use num_traits::{One, Zero};
|
||||
use std::ops::{Mul, MulAssign, Rem, ShlAssign};
|
||||
|
||||
pub mod gmp;
|
||||
|
||||
pub mod gmp_classgroup;
|
||||
pub use self::gmp_classgroup::{
|
||||
do_compute,
|
||||
ffi::{export_obj, import_obj},
|
||||
};
|
||||
pub trait BigNum:
|
||||
Zero
|
||||
+ One
|
||||
+ Clone
|
||||
+ PartialOrd
|
||||
+ std::fmt::Debug
|
||||
+ Rem
|
||||
+ ShlAssign<usize>
|
||||
+ for<'a> MulAssign<&'a Self>
|
||||
+ std::ops::Sub<u64, Output = Self>
|
||||
+ std::ops::Add<u64, Output = Self>
|
||||
+ std::convert::From<u64>
|
||||
+ for<'a> std::convert::From<&'a [u8]>
|
||||
+ std::ops::Shl<usize, Output = Self>
|
||||
+ std::ops::Shr<usize, Output = Self>
|
||||
+ std::ops::Neg<Output = Self>
|
||||
+ std::str::FromStr
|
||||
+ for<'a> std::ops::Div<&'a Self, Output = Self>
|
||||
+ Eq
|
||||
+ std::hash::Hash
|
||||
{
|
||||
fn probab_prime(&self, iterations: u32) -> bool;
|
||||
fn setbit(&mut self, offset: usize);
|
||||
fn mod_powm(&mut self, base: &Self, exponent: &Self, modulus: &Self);
|
||||
}
|
||||
|
||||
pub trait BigNumExt: BigNum {
|
||||
fn frem_u32(&self, modulus: u32) -> u32;
|
||||
fn crem_u16(&mut self, modulus: u16) -> u16;
|
||||
}
|
||||
|
||||
pub trait ClassGroup:
|
||||
Sized + Clone + for<'a> MulAssign<&'a Self> + for<'a> Mul<&'a Self> + PartialEq + std::fmt::Debug
|
||||
{
|
||||
type BigNum: BigNum;
|
||||
|
||||
/// Produces a `Self` from `a`, `b`, and a discriminant.
|
||||
fn from_ab_discriminant(a: Self::BigNum, b: Self::BigNum, discriminant: Self::BigNum) -> Self;
|
||||
|
||||
/// Unmarshals a `Self` from a byte array and discriminant.
|
||||
///
|
||||
/// The byte array will be in the format of two big-endian byte sequences
|
||||
/// concatenated together.
|
||||
fn from_bytes(bytearray: &[u8], discriminant: Self::BigNum) -> Self;
|
||||
|
||||
/// Computes the identity element of `Self` for a given discriminant.
|
||||
///
|
||||
/// If the discriminant is not valid, the result is unspecified.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This may panic (but is not required to) if the discriminant is not
|
||||
/// valid. If this function does not panic, the results of future
|
||||
/// operations are unspecified: they will not invoke undefined behavior,
|
||||
/// but may panic, loop forever, or just compute garbage.
|
||||
///
|
||||
/// In debug builds, this will always panic if the discriminant is invalid.
|
||||
fn identity_for_discriminant(discriminant: Self::BigNum) -> Self {
|
||||
Self::from_ab_discriminant(Self::BigNum::one(), Self::BigNum::one(), discriminant)
|
||||
}
|
||||
|
||||
/// Serializes `self` to a byte array. Returns `Err(s)` if there
|
||||
/// is not enough space in the buffer.
|
||||
///
|
||||
/// The data must be serialized in twos-complement, big-endian format.
|
||||
fn serialize(&self, buf: &mut [u8]) -> std::result::Result<(), usize>;
|
||||
|
||||
/// Deserializes a bignum from raw bytes. The bytes **must** be interpreted
|
||||
/// as a big-endian unsigned integer.
|
||||
fn unsigned_deserialize_bignum(_: &[u8]) -> Self::BigNum;
|
||||
|
||||
/// Reduce `self` in-place.
|
||||
fn reduce(&mut self);
|
||||
|
||||
/// Squares `self`, modifying it in-place.
|
||||
///
|
||||
/// A default implementation is provided, but implementations are suggested
|
||||
/// to override it for performance reasons.
|
||||
fn square(&mut self) {
|
||||
let s = self.clone();
|
||||
self.mul_assign(&s)
|
||||
}
|
||||
|
||||
/// Normalize `self`.
|
||||
fn normalize(&mut self);
|
||||
|
||||
/// The length of `num` in **bits**
|
||||
fn size_in_bits(num: &Self::BigNum) -> usize;
|
||||
|
||||
/// Gets the discriminant of `self`.
|
||||
fn discriminant(&self) -> &Self::BigNum;
|
||||
|
||||
/// Computes the identity element of a `ClassGroup`.
|
||||
fn identity(&self) -> Self {
|
||||
Self::identity_for_discriminant(self.discriminant().clone())
|
||||
}
|
||||
|
||||
/// Generates a *generator* for the class group of `Self`, given a
|
||||
/// discriminant.
|
||||
///
|
||||
/// If the discriminant is not valid, the result is unspecified.
|
||||
///
|
||||
/// # Relation to `Self::identity_for_discriminant`
|
||||
///
|
||||
/// This is *not* the same as `Self::identity_for_discriminant`: the
|
||||
/// identity element is *never* a generator for *any* group. This follows
|
||||
/// from their definitions: the identity element, when multiplied by another
|
||||
/// element, always gives that other element, whereas *every* element in the
|
||||
/// group is some power of a generator.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This may panic (but is not required to) if the discriminant is not
|
||||
/// valid. If this function does not panic, the results of future
|
||||
/// operations are unspecified: they will not invoke undefined behavior,
|
||||
/// but may panic, loop forever, or just compute garbage.
|
||||
///
|
||||
/// If the global allocator panics on running out of memory, then this
|
||||
/// function may panic in the same situation, but it may also just abort the
|
||||
/// program instead.
|
||||
///
|
||||
/// In debug builds, this will always panic if the discriminant is invalid.
|
||||
fn generator_for_discriminant(discriminant: Self::BigNum) -> Self {
|
||||
Self::from_ab_discriminant(2.into(), One::one(), discriminant)
|
||||
}
|
||||
|
||||
/// Replaces `*self` with its inverse.
|
||||
fn inverse(&mut self);
|
||||
|
||||
/// Squares `self` repeatedly in-place.
|
||||
///
|
||||
/// Implementors of this trait are encouraged to override this
|
||||
/// with a more efficient implementation, if one exists.
|
||||
fn repeated_square(&mut self, iterations: u64) {
|
||||
for _ in 0..iterations {
|
||||
self.square()
|
||||
}
|
||||
}
|
||||
|
||||
/// Exponentiation
|
||||
fn pow(&mut self, exponent: Self::BigNum);
|
||||
|
||||
/// Deserialization
|
||||
fn deserialize(buf: &[u8], discriminant: Self::BigNum) -> Self;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader},
|
||||
path::PathBuf,
|
||||
};
|
||||
|
||||
use super::{gmp_classgroup::GmpClassGroup, ClassGroup};
|
||||
use super::gmp::mpz::Mpz;
|
||||
|
||||
fn split_into_three_pieces(line: &str, c: char) -> [&str; 3] {
|
||||
let mut iter = line.split(c);
|
||||
let fst = iter.next().expect("bad test file");
|
||||
let snd = iter.next().expect("bad test file");
|
||||
let thd = iter.next().expect("bad test file");
|
||||
assert!(iter.next().is_none(), "bad test file");
|
||||
[fst, snd, thd]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multiplication_is_correct() {
|
||||
let manifest_path =
|
||||
std::env::var("CARGO_MANIFEST_DIR").expect("cargo should have set this");
|
||||
let mut path = PathBuf::from(&manifest_path);
|
||||
path.push("tests/multiply.txt");
|
||||
let mut f = BufReader::new(File::open(path).expect("test file missing or unreadable"));
|
||||
let mut buffer = String::new();
|
||||
loop {
|
||||
let bytes_read = f
|
||||
.read_line(&mut buffer)
|
||||
.expect("could not read from test file");
|
||||
assert!(bytes_read == buffer.len());
|
||||
if bytes_read == 0 {
|
||||
break;
|
||||
}
|
||||
if buffer.ends_with('\n') {
|
||||
buffer.pop();
|
||||
}
|
||||
if buffer.ends_with('\r') {
|
||||
buffer.pop();
|
||||
}
|
||||
let mut current_discriminant: Option<Mpz> = None;
|
||||
let q: Vec<_> = split_into_three_pieces(&buffer, '|')
|
||||
.iter()
|
||||
.map(|i| {
|
||||
let k = split_into_three_pieces(i, ',');
|
||||
|
||||
let a = Mpz::from_str_radix(k[0], 10).expect("bad test file");
|
||||
let b = Mpz::from_str_radix(k[1], 10).expect("bad test file");
|
||||
let c = Mpz::from_str_radix(k[2], 10).expect("bad test file");
|
||||
let mut discriminant: Mpz = &b * &b;
|
||||
let mut minuand: Mpz = (4u64).into();
|
||||
minuand *= &a * &c;
|
||||
discriminant -= &minuand;
|
||||
assert!(discriminant < Mpz::zero());
|
||||
// takes waaaay too long
|
||||
// assert!(discriminant.probab_prime(20) !=
|
||||
// gmp::mpz::ProbabPrimeResult::NotPrime);
|
||||
if let Some(ref q) = current_discriminant {
|
||||
assert_eq!(q, &discriminant, "mismatching discriminant in test files");
|
||||
} else {
|
||||
current_discriminant = Some(discriminant.clone());
|
||||
}
|
||||
GmpClassGroup::from_ab_discriminant(a, b, discriminant)
|
||||
})
|
||||
.collect();
|
||||
assert_eq!(q.len(), 3);
|
||||
if q[0] == q[1] {
|
||||
let mut i = q[0].clone();
|
||||
i.square();
|
||||
assert_eq!(i, q[2]);
|
||||
}
|
||||
assert_eq!(&q[1] * &q[0], q[2], "multiplication not valid");
|
||||
assert_eq!(&q[0] * &q[1], q[2], "multiplication not valid");
|
||||
buffer.clear();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
100
crates/classgroup/tests/multiply.txt
Normal file
100
crates/classgroup/tests/multiply.txt
Normal file
@ -0,0 +1,100 @@
|
||||
10000018491751458060893889018190756675058808109876974330719629294415871248770716417843542202672894233523533522085426391611508488462673577289978500560291881560964103822003262872704649110111368415677918460552197008588860300461769848797788221536509692873112178498610293735717449110462487732034905273446995235572,6192881975696225786035966982664995064937044822044587534644251299449043731778362309709151420033302511678628887337754750911692576543520793791684926797453257880919340267222510512181015985728296989735175472866965866872698457694161211487470544291337368825900113948256559852781942460432108372735686602775132351861,447562623961213317971342646547297454284223350038133828902656285846421695114449573517005802064814603287280139301229441755696758326577197667784458131993559071961595818908854193681416803619972011522725445624820104005456169532111411278882533391024720916070194718519556110684723979632586634811370262763099820931946|10000018491751458060893889018190756675058808109876974330719629294415871248770716417843542202672894233523533522085426391611508488462673577289978500560291881560964103822003262872704649110111368415677918460552197008588860300461769848797788221536509692873112178498610293735717449110462487732034905273446995235572,6192881975696225786035966982664995064937044822044587534644251299449043731778362309709151420033302511678628887337754750911692576543520793791684926797453257880919340267222510512181015985728296989735175472866965866872698457694161211487470544291337368825900113948256559852781942460432108372735686602775132351861,447562623961213317971342646547297454284223350038133828902656285846421695114449573517005802064814603287280139301229441755696758326577197667784458131993559071961595818908854193681416803619972011522725445624820104005456169532111411278882533391024720916070194718519556110684723979632586634811370262763099820931946|19255554116382770161579383715714909264782708765539029964624834623077914838241374452996111823462588737699221151887520236764901217774034554643488538519529924118839366411749516259835028878669578401436677730193218203890014064720579917095034628468204338354122803225577022412929359504950608508400413031048217497926,15092837287167018117143864462870004173493326087323162483214185994683512256473920528820058682931229518373567536566141901399624393736734616696317492646832399845295961581562413238135817545423153806714585874605091134049460217739322207059368564835209958877374166810803213938557201936549078491894191793263450700347,234893006768044042788914260913118901546740453084924505628085298368208613193607118822477736613870586900826160773678687890939302953916150044522278344184471658898873737893277827322372416620559784208443693756270533224257971092005354126278524692768704444715469609790946460097751182675767317515935452615150233004184
|
||||
10000041052183522790242850644893154590720039288612095879016416132777489378534703527529316376767361213758229530778215090392226004364711343494340009516684351602465954563523094253968698993441741189497557646486818525059302740665570749018871945434231968929038967533223013692831944903924891259290137962329173675618,1902993169831098968408340994163042640289698812843652994188396853325597449053613940738900681358483309978075948057374939279288006967407927201371876070720282077185512088102089011109098339510946105167168603912904329219763993441428070797711607939058596983469167495985136256807429373538982995591135613664471290691,648679116947253221704188706776650677211463611636395838310356904951972039958552218839434071543988637793619482253205477878855250277635662749169650536657554110192985236141029049474956216985923614316507072329807839408341849104680142145376380471455107520480114830913820742685234228885993868983705228973767491332409|10000041052183522790242850644893154590720039288612095879016416132777489378534703527529316376767361213758229530778215090392226004364711343494340009516684351602465954563523094253968698993441741189497557646486818525059302740665570749018871945434231968929038967533223013692831944903924891259290137962329173675618,1902993169831098968408340994163042640289698812843652994188396853325597449053613940738900681358483309978075948057374939279288006967407927201371876070720282077185512088102089011109098339510946105167168603912904329219763993441428070797711607939058596983469167495985136256807429373538982995591135613664471290691,648679116947253221704188706776650677211463611636395838310356904951972039958552218839434071543988637793619482253205477878855250277635662749169650536657554110192985236141029049474956216985923614316507072329807839408341849104680142145376380471455107520480114830913820742685234228885993868983705228973767491332409|11014730391994022921548019318564443238610906141262076480168925966763126765751815894971319798676750825680596366806816953155468468927850506963854768575341863098700465049052526243803093026353195834059474734029876952052212354875982568724849333989940233032713622829273608000126280643959163722728068472850088622786,10741667368771260991465304819723549356187315169745538829427954074292104964386739024958802023185700235860418655331632400858711212007319896932342251013222776723172845936147563193613725240374195945000924112718166206035243862199173787901602224623957181722190890413718871860292878014198837725481829866947825981913,591458717193488352905603034790202837072660316706237076413003353962226001987681937225165602501036312777007571264636495875979803481147253392478958512772229202313701414596984055959140281478236518410326724468820458881999271606689529119264353275033892327553507658401114443924515886686374958949587811834733084613494
|
||||
10000381915681932465973261183425742883776417480816046593820159088331265076946313439425523314444345253320002870252043057595684488140407211015115892705028395378796407813776706176594457902083795049968208905578343034404017956993894296039160788337679442024505335413399442760803039586109332233036553257459967307992,4817573728667361865336022581228097408185105735439009440346088109945423944514625700845976724084897576632126538284617885680024575350161902075565426943435359103696435860065323384485576321976518692508202982451179520762630115309722600967720404130152140308793673263051352095721900258702511325402177650727880246935,669873650881721761367318894015191721808238052876596531632606045247446982615721443478227885999211090819818334947786875090863090531638122013530669226521626152920347047659485744946461307259365312735407042929006458450763753134816736952808194188478460912675596404179851630644942038849386883091149385220764843706257|10000381915681932465973261183425742883776417480816046593820159088331265076946313439425523314444345253320002870252043057595684488140407211015115892705028395378796407813776706176594457902083795049968208905578343034404017956993894296039160788337679442024505335413399442760803039586109332233036553257459967307992,4817573728667361865336022581228097408185105735439009440346088109945423944514625700845976724084897576632126538284617885680024575350161902075565426943435359103696435860065323384485576321976518692508202982451179520762630115309722600967720404130152140308793673263051352095721900258702511325402177650727880246935,669873650881721761367318894015191721808238052876596531632606045247446982615721443478227885999211090819818334947786875090863090531638122013530669226521626152920347047659485744946461307259365312735407042929006458450763753134816736952808194188478460912675596404179851630644942038849386883091149385220764843706257|15406883651839353468888340788129827256524366500559993343402492794080742895081542466902089892082975781941021139173750937371748781682695257732868858255213590996446142784059996942302405311028161097993332331718537383888482114789770414489490580461393020737016788325059322912336073066124099655242000162998144490191,4360823987526422964670528620808397080272081276432190896883401768539814490180903410645821165307382339042226562722529652661460320310396511517028476587614669988004410806997734064375576646534713644939599630073534432499720811712867334091133681123961660738588960398432344316577526812821260889068523826290764750305,434737123855318232136803285518736106774596594589476825779021338309188039202684276728719741767739900154018854551253981210446831263812934806367418646532886786527458187655685060926749423401952358398253824964655841491692769761412354811289837062586506164527515355144754089246394187279961001728737349715244065290684
|
||||
10000382084844819863091735393428537123796094124029988695624509543701671917373805547793586171907452267004536696714359178508237591675470611568215269390130161491021123479579310299191808477715227540644280867131359924216029489859205866802370878621090778893635118109144685744213704279596306855259529008805569484738,-444155911792016461297666514223280647275019670279235098115904524278820479908555182212414682305357120850467322036353999623022556562078881846242421627622835673248504490647482104203937046492778180626801172318868765508903156634858880238203680354870853572676123032093150013906751911065758499256507194503286999359,567054671672969689387757610046141412714538710354002952292665369546607156429867011238555624731427279061383543924144630291236714076290759079492403352598432624404020019598559946194717566760077730429172494635087510893397235439040191683342313758118884331110227782487142203190483880485876667351431228811762752414559|10000382084844819863091735393428537123796094124029988695624509543701671917373805547793586171907452267004536696714359178508237591675470611568215269390130161491021123479579310299191808477715227540644280867131359924216029489859205866802370878621090778893635118109144685744213704279596306855259529008805569484738,-444155911792016461297666514223280647275019670279235098115904524278820479908555182212414682305357120850467322036353999623022556562078881846242421627622835673248504490647482104203937046492778180626801172318868765508903156634858880238203680354870853572676123032093150013906751911065758499256507194503286999359,567054671672969689387757610046141412714538710354002952292665369546607156429867011238555624731427279061383543924144630291236714076290759079492403352598432624404020019598559946194717566760077730429172494635087510893397235439040191683342313758118884331110227782487142203190483880485876667351431228811762752414559|25233315598122077418065976820332071042466787077699487654424387918664961172156179342884760885536120785360009215201873305025819279551843543582105904004062292352688557410351568671077765651689593128194982886401323218888273326531345494420553999096902303332712335656165115841742118280506588108873800795844703864919,-21589572107561067243363628128888045942080137348693403707950771695641329996718935854060105037586070646944119604332897696206540905887323628203932721112852139156892903280775223036949323848394414919310082155940615053363132829628799672709557839434529964085755781777411447385312731490258576057970445296620960747711,229349228584333455202515805454481561086661761655883453088894599746824713549123206719584169689814830025633382253625181015273278307916408839487283320828823538420290774632766998050162873483736921565586622385485530453983863042070274251829142359266901387980967335820672065096008596106715431022577378179753339164658
|
||||
10000535283948766913969186677763146947350893764133523013624566402396075467775122389351423347627366996308717336970472190566686266526440447170486872996146388310569838407203380788397656952824650289706008150444069157387402604479170310815759950456001810768733293842505752683896727400110806658910272623240889276302,3517715128667026666780257130236186883393464552180724243651182669587910084592324227192755249223315343739548139286489599592680626480533511441942660471947189354661549994487257423179947475122454624754426244988595239282883275819687054584105503928955994194464535141072191228405010641132986293339925974908519502951,570034118010650587062470713310391834950695503036920240298132931861980289236162947574989015145270228575455513419386383991154247888350856213235253786311087987346865298158646949041224197372582390632868027286119802250763817862749191433673344918830453654023465432067298969962772419746088402608223812814936545467246|10000535283948766913969186677763146947350893764133523013624566402396075467775122389351423347627366996308717336970472190566686266526440447170486872996146388310569838407203380788397656952824650289706008150444069157387402604479170310815759950456001810768733293842505752683896727400110806658910272623240889276302,3517715128667026666780257130236186883393464552180724243651182669587910084592324227192755249223315343739548139286489599592680626480533511441942660471947189354661549994487257423179947475122454624754426244988595239282883275819687054584105503928955994194464535141072191228405010641132986293339925974908519502951,570034118010650587062470713310391834950695503036920240298132931861980289236162947574989015145270228575455513419386383991154247888350856213235253786311087987346865298158646949041224197372582390632868027286119802250763817862749191433673344918830453654023465432067298969962772419746088402608223812814936545467246|59075354970692991755903146214605554332637224507205941847466515241658938543685224447213353186403252887052183944064961699964728259961938411627544944845776708313892390437907961447141588832103578886894741951168483053303302416173045780507296127716028825436246283574600092245162214148065236680479535423660537547914,6142586061770095737227904853540455719428485301510321654081360726874454746843797212863006221294314976215484969948774214251692404250673117267549442037815482195083213974160653516820675375995512277154295678704255795063545010227709473438581077714090470093020228882800682332012139884210689872621538573295925265993,96605184581646361029373732724432135349175091555904351927012123488431445097722589746711095342410196584277564279992867684018993498546178659279293376777551513451631505380655431533215245951077120355215801949799249196142928522335615942042353764886891560316955633828555662725473411497902686741832487630568702990486
|
||||
10000992092359348487480681816729833858083850458212481718635084324812805161168823645716695515173763020806162121153711923870750015861003941980870964102569907660333270160386745314618020099129085566179786211585530303068327607946822258160299176181360948584855686949828385515610423848592364973361809055890165682387,1387707194943048769069000645578034755727575677682880147095892736572338185330919801102067876481652092034533316677281336622039276010947331496276488954193596489132454018768653574924396409513550904384989555254933742194365096022768325215822785577085941233088045260998209615597763890732713200353258054623633203363,717334904486111082107761816895355357018690502858423612748563938578649989943228419203563081094256539563484346776479991186971459579979441405718434993605445911043337999222596585935065011724285592737227690661183256354762587476450143021573235732571046140183664111033663616265739167081365443050278073128430130275044|10000992092359348487480681816729833858083850458212481718635084324812805161168823645716695515173763020806162121153711923870750015861003941980870964102569907660333270160386745314618020099129085566179786211585530303068327607946822258160299176181360948584855686949828385515610423848592364973361809055890165682387,1387707194943048769069000645578034755727575677682880147095892736572338185330919801102067876481652092034533316677281336622039276010947331496276488954193596489132454018768653574924396409513550904384989555254933742194365096022768325215822785577085941233088045260998209615597763890732713200353258054623633203363,717334904486111082107761816895355357018690502858423612748563938578649989943228419203563081094256539563484346776479991186971459579979441405718434993605445911043337999222596585935065011724285592737227690661183256354762587476450143021573235732571046140183664111033663616265739167081365443050278073128430130275044|46482666589787057164981427600152979028584675170625944424946407599960201881805307116957471661211638766618134840736062752900079748534826618093953946800313092285412874757225443617416186449293441503680335786478712016820930243711850679772176006938838607901709770799483635364697553013258865109416434882051210741449,3101717798468321538599785648396208464189816894621339325506629294456148802654755640066207376362353269286149982363784579708988481769754035006891067923386713257060529140906313751403507998251605485836475302614223762235407657418301209467207199741940328204824018102771458491705342260612142478146285653246057987987,154379792819937466421655387360779358004857339117994029103954006768201464432625988196022580370956875717212647779858597489967018623693936133011607398083022906238217469025231498041115162395196295497816525433748189786409656276394144968660209259259055129261299657708619246489632848864169630941858852164482792598772
|
||||
100016993550415829135262361263254459069906572411523652885898601946150332160005753209165983241360621518247046578246408973951913750019427396230791395391900464740479884371689964652672891087059763533492805056734857093926525888370387953270730195624561287530833550654825448807998575583518751690880145682614320134626,97867808093652711513661030354940855898834960524171083907471520733521588237588575528935854367900557849089129501606401645574828485643984844895342166280487749477320616345326562522776423978127616648618120061233592736634312164206210712776242358394865817287600812334839844119000151584498625451416447766525556737091,101546865178620340984298080630771114165409461904937118589108835750643335026750315119287055941177105859697880165662377691746530085636458948369814197349790717060438350144172923110723731589639766266300381349821152919234474715235659078426677984814293485454727036020005038295982154861599467045526190910921111647828|100016993550415829135262361263254459069906572411523652885898601946150332160005753209165983241360621518247046578246408973951913750019427396230791395391900464740479884371689964652672891087059763533492805056734857093926525888370387953270730195624561287530833550654825448807998575583518751690880145682614320134626,97867808093652711513661030354940855898834960524171083907471520733521588237588575528935854367900557849089129501606401645574828485643984844895342166280487749477320616345326562522776423978127616648618120061233592736634312164206210712776242358394865817287600812334839844119000151584498625451416447766525556737091,101546865178620340984298080630771114165409461904937118589108835750643335026750315119287055941177105859697880165662377691746530085636458948369814197349790717060438350144172923110723731589639766266300381349821152919234474715235659078426677984814293485454727036020005038295982154861599467045526190910921111647828|38112895924354771000755967523257705692975308805226188158888846989042277994318034233632572801944291367363544635160689172507870767350780603573652174702847837195353422410303076999489362677424810242035375507542324255582549804459073498689456734177829753341266635299826832746075600445484602669454902196797110414268,29514825972671498452469428270002667581396743351651746797469797047436108385118786112979101930068512381300796319538713657519350359618509818562580593402643136639943548729030802553674984090829042397520519175389582956780710082733565916489480248905811215441925467758974481931055406921284703112579763389522667256173,209369197456369085510398489829077224010383063845121124974155708663637684112727148688124840116395472316273115362880530986565561714461662746456509765896943657967931982155109566457128704664240543108345283001161566864139257311910823070822151712032036583892036613154176268529246135956533435036580269691993608092680
|
||||
10001857278272414635783742468687626112156223003835485801536389954295572560863634462501676022563000509436968020300398791815574826898175032553202096799719821296404518525211113962533485614199031043964942385615363652892938675160040173449995570062547675787656647030050979129677693759900885701969029983016110814344,4689276451232458601825639665209988136946233783317430787463374655024892705415877731372938558103104801918261384975590626995047805878141047994265820723310810966786623993284261416684874325742989563037963206467146622805115830511715873009621433988190289268680824928937364349844265466118648518849937971040073290847,417151168234058306514924962236880342366392470330250088900617117412557071558608977094869379187282436222898630224671275148160961737937513168266914431807498623302460140528881877180166348694674662748849360025138764269398178107070427436885941278328572218964052739099341639294288244256170434477924203033934350673327|10001857278272414635783742468687626112156223003835485801536389954295572560863634462501676022563000509436968020300398791815574826898175032553202096799719821296404518525211113962533485614199031043964942385615363652892938675160040173449995570062547675787656647030050979129677693759900885701969029983016110814344,4689276451232458601825639665209988136946233783317430787463374655024892705415877731372938558103104801918261384975590626995047805878141047994265820723310810966786623993284261416684874325742989563037963206467146622805115830511715873009621433988190289268680824928937364349844265466118648518849937971040073290847,417151168234058306514924962236880342366392470330250088900617117412557071558608977094869379187282436222898630224671275148160961737937513168266914431807498623302460140528881877180166348694674662748849360025138764269398178107070427436885941278328572218964052739099341639294288244256170434477924203033934350673327|39512406098482423779120312488933213318036506673065796538336022993655638182250527755522829589375917826833348984821059004871245970343092490834408525776732580142621174939994986501353324355190007207510458548320626445520306240377159533568686613898702507848891809938754441261902406274233712558160571614302439957131,33458680315871522230740954658476053975126560151398110919331173177225767029941330426356821906446363070251030468052516656211641983986229753635879608148342626307073260672093693099423083101538134818421873088154104042575469404107414196063491342206675483762419581621360672445423968155195195983917204254937268665705,112538323552595379512976869360963431325956968605739748467981199043411580278581204995308070112281536994589175551282469490999392089726267157369534414758432876571069898487221813246689682731800084089695271351717243345819033451481449481940560204129785884663224360555776373560572513249146398346919605386672664225732
|
||||
10001885848475688153826124264809818246080666151576830718882253306412201821167674972767046901596625026072385280166547579462646990262300818624039744400633121727773879619930855094164710044647150456604915949836019563376717637829785627004484641494826695600821088683607312916171680087163211415876920408834836303184,-6401849646396930994521658626667447090190354097997530993450466589091600058118189817231880440719330366452128426380645424906405833189843064340607355709362044588398581812540592198712107929843518387144633043143678667045861106413931254718474764939962100744640406024944116893338624373426827575556627557030324975185,729010733894420808263762284440227341447693348621882426869722779163540379242011358298248405166128119693780872987746515732812024832371695093716504877119416045933332381529307504733200317114594647306152268108402837078447121693601055930678151182644443827620435481034522157377127949376404692708089215142290715182147|10001885848475688153826124264809818246080666151576830718882253306412201821167674972767046901596625026072385280166547579462646990262300818624039744400633121727773879619930855094164710044647150456604915949836019563376717637829785627004484641494826695600821088683607312916171680087163211415876920408834836303184,-6401849646396930994521658626667447090190354097997530993450466589091600058118189817231880440719330366452128426380645424906405833189843064340607355709362044588398581812540592198712107929843518387144633043143678667045861106413931254718474764939962100744640406024944116893338624373426827575556627557030324975185,729010733894420808263762284440227341447693348621882426869722779163540379242011358298248405166128119693780872987746515732812024832371695093716504877119416045933332381529307504733200317114594647306152268108402837078447121693601055930678151182644443827620435481034522157377127949376404692708089215142290715182147|29744618895999892950369062264736486891947372089326189805787662049365991492371249728993520356943689392647109012744687302300685788536119433016012855224253957313263294648625309856809103016565484862180956099939466843259337398301571034092060768935310042949815131108676382925915723778520018870120465703148469427226,-10209285996871914054868241646783255177966316197845761911887894869148957597460422378515655227929008210712234487944652632986850515682880041083632277387837772452379138668071836676947710588769042538916436601704393264463866941375385749221300434945563044575029802713999893603873804815268692854499670177122342861333,245667750146427110150677187685482906099978771660913415239953145936955067540313763536644215438217145059701666728130321490946010447912027178133916738527033418368981585094936292739042791746985193177096407440545894318127458296684680664341938696795502212145624334822453802110708189609055956050992529688916696742439
|
||||
10002016107047298540914373810554280751018084476212026169532336244000095667290766720576480147453702781819098831501724861337484902920323127318735651635800283580581543246660775103367813382337363027395892342097619966629022106712471908155888170784651450900253429516651100879214540932985016853993115133868182018064,3932953570343042122021312972484149360925874859667466184891542534824273073163448674737029662190753442883970728845641115381889397609743429783435425637213409939798177187589001177019943245975437142488968879145205618985792078085357316999616817143927979980310665100836939307474346180730761675171280731347158671449,501820428787763072597412186811130523406055528535842317937667844140331895435375780110188856271616785538949009425271158566975765518229735762290911833082144356638560737127790858277137050097833066958564259261818227652665496782587799644931796940046040067871968056722480981736692953918030967693251282638067356406145|10002016107047298540914373810554280751018084476212026169532336244000095667290766720576480147453702781819098831501724861337484902920323127318735651635800283580581543246660775103367813382337363027395892342097619966629022106712471908155888170784651450900253429516651100879214540932985016853993115133868182018064,3932953570343042122021312972484149360925874859667466184891542534824273073163448674737029662190753442883970728845641115381889397609743429783435425637213409939798177187589001177019943245975437142488968879145205618985792078085357316999616817143927979980310665100836939307474346180730761675171280731347158671449,501820428787763072597412186811130523406055528535842317937667844140331895435375780110188856271616785538949009425271158566975765518229735762290911833082144356638560737127790858277137050097833066958564259261818227652665496782587799644931796940046040067871968056722480981736692953918030967693251282638067356406145|64735528603519488065780804878324224417188886620278284672701068126880574848630151784368770212266476848015707656767389613750457721321054695685260658278678665196373574627583845291930832489025699028328049591231345912341357077706665618380075933900907723135182099099317242925058024706513979297237254597076227095551,4676767511975502628189775967741301363073348373643615464321451471292999156583060169457486234222367809825517380380305131875518326506653500784620820595247817795436795668446618561421217197076229074005115884048096800861583629462266306937502121558685767398985500271610752282597009278306418521631471902811873963535,77558909729073708624985274700160896365175589183029958928607160881016530406365743721430360419631842295388705380922110512036514218268293799548453381932743351256518434510701744265175175287358735767897041689462764452869200380851139430193325516047764774954110200096814808839955087651569998366318539183831351467636
|
||||
10002034549022819403076408239222347017099550415714472028923655065363879242538082883332046406086443448767298655226522786685511031384602322251464988942315474592768020948704552969250388174426697733005815698500285576084348657180234667772665672224649309035191988841439951539719672753703757656633080728573515972292,2010796810968504378931299158317582090146742925585241000850486049458701149088072887117382202081460750175074877155829037914121263394655667323321997117300425990805089503958548860857023509792455388955490579562907955528791083522774450681564161379845706643578690350999966442870934289738064461129972772676090524913,558321669961648887847428632824052548431625768519625138834794746205714201508858412984925892097351057558062620149468106508584560558388430324467000609767675063271492932614039773497135546738436362846803805003389182782828963768739992366197919348230812882254139576244708687275965273358081737826555824405654768290694|6826578859626734597480939133878569229694460186644971629457853526114421649076835335603573751879988329839397104649987465835398566386002039755592773568446984903389961798459390528478761929712163120494037385730792909171532085167309911050308445263496353865937264941597436020907055251736048076644006844409202248304,5916703632910582851125880793132408903816292476260991242513549737921610794279828040608017189829216974970365350284663821730060215581487763067707193344265376739551991053238254698337087591646614840450823227220261123886424801128338724411047128491092060105475853943890821103779036774500319107460531685286202841441,819164879939066316247739921674596158995075399415076526828586576697986820808489862654252316603348700696267835592140978359698748448462852314742485570195189002909951418034161212683212111469166114805395316595157859568773382000204444562394625047968122644730117571140576687713835978983039148632840884180063353321919|24525593055568742416097249604269483346856874441455178370798633512644823613408551383898889724136436641596007886888916843304556505396562460452498580122367837296026711996552032327466172455184570034171840642876125912558571322892683749487069829210684821264854566376842632617791479252532263566234814371052354893484,-1533308789349159850456496166928278185899248924637820082743446320631452265558278807739507468009525157831824183682096795742851767532204899527778707496003773066153051313109361171305769881696175185189326727846932831915940721252274125841396183853650527186995865126146441484052102425089961043364891055445991541807,227677657081722376213157149142023336288707753333770972277638057778548802624067098792373455123375286502620159760351354502534495438446400227420867854824820469572948638801811562066346273782346907474917163347261714943740349452378338981756888788776146521650040273657711500699241321825395413707817445618060462480902
|
||||
10002074125017355975599743151046242846511112798798396053226619327592735057422378177948114365284430939135093491265336806767482478919758311098907293451660632908142687429542305038471993566061112091142254674235636984969318093242303552823770654042157452160266396125764144057012639465935378258561790879307671193782,-2677875592705731980082114894429792995071386706298929334230749772186164127600272370546755010431170895608048375369668020170159823760294147973474095537503850192302837032131733237064875342982073993793395058782971441692000690573793255526540716486233592692407763281116363187020386252791667246848349317822548915689,648635985571325401692595356147567233561468612108663071405974903212101924183730392746938934107001054497457734923399698902258386855829500228588241165821030031659482670628135844118612829510920403042586089191580683729603024542404607259365592152472123612035976391470864076397175842526847201114587386293478162448846|10002074125017355975599743151046242846511112798798396053226619327592735057422378177948114365284430939135093491265336806767482478919758311098907293451660632908142687429542305038471993566061112091142254674235636984969318093242303552823770654042157452160266396125764144057012639465935378258561790879307671193782,-2677875592705731980082114894429792995071386706298929334230749772186164127600272370546755010431170895608048375369668020170159823760294147973474095537503850192302837032131733237064875342982073993793395058782971441692000690573793255526540716486233592692407763281116363187020386252791667246848349317822548915689,648635985571325401692595356147567233561468612108663071405974903212101924183730392746938934107001054497457734923399698902258386855829500228588241165821030031659482670628135844118612829510920403042586089191580683729603024542404607259365592152472123612035976391470864076397175842526847201114587386293478162448846|67949938415113064293161178659030590691132496955041316494045733862875749417850747302562113500007310852668303846586641135508462313201852828769777121178050596003427926460422904475476244906898063142012649435038037100034350908875980928269206397866321214852019966694130786407505714074230941338096203488261864055662,53288668959102688425004591339691466327049075866255869214424335604117440952293373897678874847548640712084573721941183729796456325294146528429835461394439973255133211226526484818899123041166158632993340470979352834271983572524972059884357370847142645448863117621210245351327485761671145696210503054900410821273,105899036571802576293359771771735244647493044658191270723159384029727618422730315689072753328136534522456073200532359330590111785906447289835484981246848193838501538977975954024004079425925298710095769756420575788761877694146481988831153103750420171232975154220500803062063592047512891980560706613446433318602
|
||||
1000253663479701075381410901780503799818388911512704954335021374915858764824090995263167708417293347017273433263645587016366542848367626143993424043714190337762737334693150155289579305664876408056173092807453213218218789600598025704962632695206955492435575043105375877466941810990278101450609180156411393563,66294252873466406327783927757894402143872047742685585398248434686370376436933447604037129338463580005900665059990247763362159976852149607009612276330769317942643706356713296053874697713940805071384498697200382739281769000631492714220560824564622672983217861541737814215572898066821664279189734871952442485,7449081821920052343907585734636804107890073716887030220252146886374375473495388497829441955869708386804952455148603275078999958645575875758803250484635047415319443379977946970239132988474813562402674036138638943113227930164450433318295035974410121827732702738775533740738542926454278142700154894632584181276846|1000253663479701075381410901780503799818388911512704954335021374915858764824090995263167708417293347017273433263645587016366542848367626143993424043714190337762737334693150155289579305664876408056173092807453213218218789600598025704962632695206955492435575043105375877466941810990278101450609180156411393563,66294252873466406327783927757894402143872047742685585398248434686370376436933447604037129338463580005900665059990247763362159976852149607009612276330769317942643706356713296053874697713940805071384498697200382739281769000631492714220560824564622672983217861541737814215572898066821664279189734871952442485,7449081821920052343907585734636804107890073716887030220252146886374375473495388497829441955869708386804952455148603275078999958645575875758803250484635047415319443379977946970239132988474813562402674036138638943113227930164450433318295035974410121827732702738775533740738542926454278142700154894632584181276846|24568037830590216352984530012697330969024585773239190902318728852976076281369516446912320948078334220155283803919583544158932277992855289960471883436534381687899324079630011764816867889328310023423094633012275199876596315083044545869380586009580913007036860399795245680314963399389559624688311082823805090231,5319068676363461453927187061672827259672166236556729558696928212559807675749791870496620364221934584448485936117599756917409724038460841591469075162277678937851596763739958878425260723977292640004766308405052660448827954872311329092739598965306131405515429262746842239243566030717413542127898656259746125971,303566913138393892567904204367686915490068122814370585780506941778399006742359108535463859108136357801343091343038391472615790503246239776473238906631454625779972045236751565874336398670607783613554147722203607531035833062634596664836955674449545888313212125443460195013735390947268982347767364377764736422042
|
||||
10002641226772515081987795211537787929272477458505554463354638964352971364408874452069546961937801811210947177338408164991078687591091465516969203874900752888301636133298179753283838003443413422949614854305289101035884523695670918489325845677592608946818353360132477183288514801318828834214935649039394032252,-8793160452550363276528664072517898739234784407606709040941098303790678596260001324417462973553168029853952326856848991111004093395583096302100461452777142804629182141499607986715453131122448708636069213611853518781262192482364818383993101471525466753092118188242931192181704912063647353300605222746836800483,492078265126922274690434467399394077805701275647322071646319840779745006934618899651871133218190471317339124114044099413606811819906582945782428482112475530640807894231223382852644187084233002016394775416098135698147532762509163053201184493973160623592655199338520312133914851239167130412730662124292772722504|10002641226772515081987795211537787929272477458505554463354638964352971364408874452069546961937801811210947177338408164991078687591091465516969203874900752888301636133298179753283838003443413422949614854305289101035884523695670918489325845677592608946818353360132477183288514801318828834214935649039394032252,-8793160452550363276528664072517898739234784407606709040941098303790678596260001324417462973553168029853952326856848991111004093395583096302100461452777142804629182141499607986715453131122448708636069213611853518781262192482364818383993101471525466753092118188242931192181704912063647353300605222746836800483,492078265126922274690434467399394077805701275647322071646319840779745006934618899651871133218190471317339124114044099413606811819906582945782428482112475530640807894231223382852644187084233002016394775416098135698147532762509163053201184493973160623592655199338520312133914851239167130412730662124292772722504|33269093498653459355911056721677057317009942094586213583836482429509057025072754420372439736248690513834971332175814464148672813487558426999636798377556094849446738441259743858358991688742216573871382813744898911570710319471125784318155373816902285919608190930249032332855663246217414413642466621378338134637,-10949330241414165733888189262458140426986707558351886540903470879800574033213186052244846799127577601176842705714647638204280400911455131674484085082600626371557414203990940725212684526037217982855212341310843343357217588085473017983047320842712153347738590477893040712557903922232099275263522420010197087053,148267471797952946823163847078479485183284021963476657656706944246030488584019895488346778002211592139277760491813666056346782934726026456786554441575227882221237740554377749215785707126496176370984922985820419829339644729974154901755996939823200818910973576565060260711661905159023290114040762532541467088824
|
||||
100032603932113584190385248548088424648269645571686859576017823592423034520849963520508387815309023735382902503732005885189155388332561494704539042592634007656219743816845911733895132144423102052942452746877943975353248517709377531317937542644854604549820822373960740354167669496547979026679046866602436687763,-99537978095529356699713913260068351078290498972088228356731296595606062051578098868796341286417844471545193824704430742131836251590438154579238324251435089098889846479244366361006756968943661462663756515208457066560709300104052348033879750430334191090716067038009316021882909761152311655341491437691827562957,100461141672958569681488420113742834080404730978030677210672600173957843011309217083950874294428866093615815291020711039763544235459696431813304652678133959812856917140520431023445877504376180839416510225066460002908711498876105285713692498849763216560421523587971326926569083287005470828615251682690932454480|100032603932113584190385248548088424648269645571686859576017823592423034520849963520508387815309023735382902503732005885189155388332561494704539042592634007656219743816845911733895132144423102052942452746877943975353248517709377531317937542644854604549820822373960740354167669496547979026679046866602436687763,-99537978095529356699713913260068351078290498972088228356731296595606062051578098868796341286417844471545193824704430742131836251590438154579238324251435089098889846479244366361006756968943661462663756515208457066560709300104052348033879750430334191090716067038009316021882909761152311655341491437691827562957,100461141672958569681488420113742834080404730978030677210672600173957843011309217083950874294428866093615815291020711039763544235459696431813304652678133959812856917140520431023445877504376180839416510225066460002908711498876105285713692498849763216560421523587971326926569083287005470828615251682690932454480|83415806280351408759589239958761219329310176984650613508633653230456890652830525586600995644504636518476026029385588047137454270096528621205370620292951275504650266248010650846690600983384462303830915876850693795019055500604246841544238285169828416374845816289496545562107780789460316448092131365832361151375,-74625562140946530658296843057459607794092129677035083950600450768713067569753818651802415894941493999582236546770594323673470134033058099517659971836561944651594028658674853294680303580112276880640835753725828631472628486095723473976221487197988748307970291488083264976555432132424815586850501052682570560083,107469811246399151523671670639445335406080264077456915839785825558020206498489889359444002816596192076606675057819088885526103113392920720840544571898931473254561406865074149733521627542981016723238264871496686055481103379945620155327472162297506458535202575738651893005921523712726080367985636694514383291872
|
||||
10003476324006195750203056589672528920142608070881173628253070002202847822896965018507956629750620754180015153597378490052619698657641883238019501085375230761464051022240631149609917748136390010621917552270797301343624990317089853119601059038653584566960989367701622621948512038032835888249299441269693147481,8948477894687501835769347042476812359286265266925800130378128090450514350343716170849427570408163707014128103924229513747579348337292452228930399170228437675863524232253003114523522760158376999688617602181401251377230973508602086745348949552684443228687100653278976227886870750067529496753791759215379958009,452977737155070764205462061852384767406000511527628419268926246340664360293838298755195741559726771936393803381121945775594031166662560564547853061983512305458290529662211961236299108870033900884457317683226459798783650763565076645131166564022405125204306354508519035128680777341173496414054336245228904798396|10003476324006195750203056589672528920142608070881173628253070002202847822896965018507956629750620754180015153597378490052619698657641883238019501085375230761464051022240631149609917748136390010621917552270797301343624990317089853119601059038653584566960989367701622621948512038032835888249299441269693147481,8948477894687501835769347042476812359286265266925800130378128090450514350343716170849427570408163707014128103924229513747579348337292452228930399170228437675863524232253003114523522760158376999688617602181401251377230973508602086745348949552684443228687100653278976227886870750067529496753791759215379958009,452977737155070764205462061852384767406000511527628419268926246340664360293838298755195741559726771936393803381121945775594031166662560564547853061983512305458290529662211961236299108870033900884457317683226459798783650763565076645131166564022405125204306354508519035128680777341173496414054336245228904798396|5651402082864001341383043857276519034370923662130513841623791595519661596270558403629904832806805434101124739144545597592273345291679321664787896528184481483087832442891723960004144034071036416654549567647433046035924426144596821847342448417665300158067728473706875334422169591609969538712389716925515442159,1090636869023214934530000512317584955330428598448445756182897777909589608376391586933678383330159027516570062459675025398064909568706408769200853022274439337235651672149891920445243421589467522791785184925567074521782213195039081340473683210796200673383772228925769534634646704414996683315287011695982045215,798320586788500330131894474104550120349737015590338005277237799938184156294041064946603812109197024144698401875127120433554460509300984485272200798966972702950997831115495437993447800151856526214460125938349981191215783025651707239371732305323555609927700663473758594406982664526774948117622844814657936546368
|
||||
10003857993456427654260743531593175331844381828365670865226962439897092670436459982112189381696267158765639464830025128699564487196364496581401927783840749033897594251479939418637644343310965529659395490594160241233118920895398385679767173659034336248678548857485551806702464695049628038493630764757131936433,499412956562517742917849279756715433309262335746117865845799881793024584024558389384536935608560698495018673505480555335883339312289660314988198774876439555916228389426783735627572745304130362478355104078356335948823975431983850031098878540627311553089477219658101715631431867688289331308014437329410794367,428065574132217643458625663050023831718642242887566540643235772550790937328471994487142052675941441071975523602876098842203000859003355118835451924426231099194913042875268766884651796522017073832982218720474562973379560560341143898312656272368395693435837758889298389279644428917154166725285871991579086938078|10003857993456427654260743531593175331844381828365670865226962439897092670436459982112189381696267158765639464830025128699564487196364496581401927783840749033897594251479939418637644343310965529659395490594160241233118920895398385679767173659034336248678548857485551806702464695049628038493630764757131936433,499412956562517742917849279756715433309262335746117865845799881793024584024558389384536935608560698495018673505480555335883339312289660314988198774876439555916228389426783735627572745304130362478355104078356335948823975431983850031098878540627311553089477219658101715631431867688289331308014437329410794367,428065574132217643458625663050023831718642242887566540643235772550790937328471994487142052675941441071975523602876098842203000859003355118835451924426231099194913042875268766884651796522017073832982218720474562973379560560341143898312656272368395693435837758889298389279644428917154166725285871991579086938078|5985067419244985135241171028798929574240680468883302468191968098879216438700233164875805694297003438862738484975665356224507623680806342430269752869889205306990703427045634087633153837909332034829737848013329051690528535659192743560129505700514703339932109459152656849997168043791609090148125676966411164474,-3013789663785982033470828503772197819235935022596925513202295899674251698616743229507943605240952571134961898221616756365279257136756498538053825862952363683344784599061589171181375336294364884944425024815089748650913141333142482818080242503626668488451409454453378105252995530177887117956522924628476106577,715867557387629444794828253143137494171652360384349041477991757900406478237922421388389881678979412011018924778952400351577186261046593876844081918575484239857072969176632122684840733871691016063878843026835488228409619596420110671483199617250854032506474798364927317129700200264636864303167131823097056257391
|
||||
100039629164915279615632745626755403195135344051296300065703707540722103090866387847978086519807842461360227602981314815898651188162817881999812578911179147999641525372151514639575701701027057192828570924656410854140601616073626299097374452319600612002632648030238739679305929396591878384845108611708173073473,-99956757702796747144330474031362091634322580823618978945421296776762235722820502139320048823797118970112849105309821058917042066320137328941305079762427354700730983116887319872947138001541985096571674792479594585340751798952938060950882542376800246430517653157385999869147535721348848735105635711972964679549,102428094420528235210038473992722778047449595066683562474358311327561453376741151333873834215335094090938635116665776111534217214948922896682406927145735733279560659220902423840693623822669973775960053647983979336042821226775972118591820157680473747907152458057697531888053067296726895267408102940444171410942|100039629164915279615632745626755403195135344051296300065703707540722103090866387847978086519807842461360227602981314815898651188162817881999812578911179147999641525372151514639575701701027057192828570924656410854140601616073626299097374452319600612002632648030238739679305929396591878384845108611708173073473,-99956757702796747144330474031362091634322580823618978945421296776762235722820502139320048823797118970112849105309821058917042066320137328941305079762427354700730983116887319872947138001541985096571674792479594585340751798952938060950882542376800246430517653157385999869147535721348848735105635711972964679549,102428094420528235210038473992722778047449595066683562474358311327561453376741151333873834215335094090938635116665776111534217214948922896682406927145735733279560659220902423840693623822669973775960053647983979336042821226775972118591820157680473747907152458057697531888053067296726895267408102940444171410942|59758487461561694442379025688208789272805646117766841371919206129104643340187013959248829747415979662207515324483234883850993532329266696739297473585807619628400010464577117227971680163239657561855113693233183544551556435408658445465178524557249837569329921343630595316681776567395248915519114258200940556334,-22671153376331064045596883212849524458683137875144383539728632975135493675352244172470558064096651200683764074233134897430860850593927295220691708458835598930765635309529560060316074048705829611628256591181426206810132007799209323907835404383161225433151628885627129593154801395506335278453552670824539376361,131822706075099232761447085662042248387269214384273446870979850351593187356535380305031128889463232587293325792397508871970239127171842305342534211852386333093595103295196214505820601536505750244236747510387243858827641299979267104558491688743963318805624534666949772263803599250156326714304699457238299478944
|
||||
10004832714804908103723742535198592770160203517705805986990840545592954373052531534772757807185128680232142411531940850138353354052288042367716414491900227710660117192168358032143450533265736882961031789512953512836372805323721228539257249690634554067409180163736018674169229333523619015614939108311094404955,-4106122534013672070279170985250180991164806091813516237606357362858804809149171076685686783446662860787711693312632306442369721226548746949829113367814838200945066703674460902843843266912498986340273761329459609877828321975866552396500360382623866557971900410837449507727615090091955001901337773500512564083,735528321490864741305341471765335107420487103909921951579694743548116478766357351448185791472115882125120532716552174779001460694927011404974670401193452353207309236668713919095870342289746072100419468138261516298395168201040490324057099586440436334562163475983175689744239719212727501982130267247535538654526|10004832714804908103723742535198592770160203517705805986990840545592954373052531534772757807185128680232142411531940850138353354052288042367716414491900227710660117192168358032143450533265736882961031789512953512836372805323721228539257249690634554067409180163736018674169229333523619015614939108311094404955,-4106122534013672070279170985250180991164806091813516237606357362858804809149171076685686783446662860787711693312632306442369721226548746949829113367814838200945066703674460902843843266912498986340273761329459609877828321975866552396500360382623866557971900410837449507727615090091955001901337773500512564083,735528321490864741305341471765335107420487103909921951579694743548116478766357351448185791472115882125120532716552174779001460694927011404974670401193452353207309236668713919095870342289746072100419468138261516298395168201040490324057099586440436334562163475983175689744239719212727501982130267247535538654526|49571248488801947323762143907209086317313166403240424924024453432101823875387693931106394388064932448674243115016411805337571297304108452331736192767907165219921775519019524307831072755876229558621548399009624087618962075649066655387832586784423916396427426550173498305707525522262009377144776100617511504479,-29828959784506381554151288596212589266056524896738496309595862456247322273883550277461362725785642216517361460931008602989968457887994880159243708746757201494721079152033527869271494859280160324467867179845744346034683576782637256359631403582150391967236780147449482496203963125132702633751829108018063107905,152851999786112534607728017818026345885853920855328921975341927606898018268835818661916681924713268354620755264611816045133624308753790454966902035653944158070765154497702110731650604894939030177902410742021315843443639601716505769494787447868225921446367758854610060178076102048397807948745556177069401434816
|
||||
10005026798525081885012940723882427584501711356233986451433820326862561577003483273848888665415005023331324845917111198606297565890343057122006058437816088078150993643095110440273546307247953190370321453395387856022986496964659738868016549698302294761145902566546443562453064814285197415999088360521895892448,-2012773415393071452341702894100369945009950648974284842979647951404344133571843387257391629610481617222572984474542523680934261770552452770758419481294248980432288030428538457156536090278813518012614750771478130023297469887908317305397718948039728500945544029263259198696111632370324283021118376979818613221,535224191733498084376882360698126323023228440191548650672747703583096856785431353632400792141685069598130344590929419053715450660967162173014581599286976146407034427713180051638727241035734570695485508350936098840329272631647750135734419630658939038108543820389342159392044477918576834926838103968922627914592|10005026798525081885012940723882427584501711356233986451433820326862561577003483273848888665415005023331324845917111198606297565890343057122006058437816088078150993643095110440273546307247953190370321453395387856022986496964659738868016549698302294761145902566546443562453064814285197415999088360521895892448,-2012773415393071452341702894100369945009950648974284842979647951404344133571843387257391629610481617222572984474542523680934261770552452770758419481294248980432288030428538457156536090278813518012614750771478130023297469887908317305397718948039728500945544029263259198696111632370324283021118376979818613221,535224191733498084376882360698126323023228440191548650672747703583096856785431353632400792141685069598130344590929419053715450660967162173014581599286976146407034427713180051638727241035734570695485508350936098840329272631647750135734419630658939038108543820389342159392044477918576834926838103968922627914592|22336292342012135551012779505885821083546735296581603650297115029465681138287871430168423025904988089547671399414611655350486697669350669877738276496552244732628186316333718561702084292478964766694437983324796248956801158028485684181499933232337147261336601523192790302252474972512181980447183622505293176152,-11674427075188626733931744428592651339949229796533683950532721050654863919331228509781516498261584604218739331608896593403871873856541410150113580209210756699310754431102708096662231135908839829374052715278169746619957236796967122303020947804850902024480676480363166504231340429878256710974972888619078138229,241221441172507985920847839600569201674621990755660781190984844223834501365279182693592593623964679309297220103180052193705500388401906318363940879681334805954355205327811300356578283407461158222974345862172435329520610152326479352290565487656045066487426033103805627728579179611865031310778705197856088085583
|
||||
10006672794990347502279526000879267078734551177313370372283212271611928222796898904661389050998596001740140300896360857122349676163698172929644657861948036337955651058773337605834505825285215111994884147090626904932283811767278804138486301736275150746935294318794069137540121225700303083939876242601120625682,-9838237801085818249924597009069669407425270661770560087620729925196161025957715438545136585598174869667669532449305460474170293173380362768481774634876936899174710462784386243070041206971463923591073715195084153396862556329146939171493281676244388685209328525900813769124322086835985741784348578408662428059,491155226409710325351546145673359292444301383692142579605004960553566299358747456958419756937691174297624212871558627081110141997099054271399339089662075140351079784991312987158527194379830582795343003721494456884032748354538831215203553329779263289722351779436025499608302937937453427548391343898256662436681|10006672794990347502279526000879267078734551177313370372283212271611928222796898904661389050998596001740140300896360857122349676163698172929644657861948036337955651058773337605834505825285215111994884147090626904932283811767278804138486301736275150746935294318794069137540121225700303083939876242601120625682,-9838237801085818249924597009069669407425270661770560087620729925196161025957715438545136585598174869667669532449305460474170293173380362768481774634876936899174710462784386243070041206971463923591073715195084153396862556329146939171493281676244388685209328525900813769124322086835985741784348578408662428059,491155226409710325351546145673359292444301383692142579605004960553566299358747456958419756937691174297624212871558627081110141997099054271399339089662075140351079784991312987158527194379830582795343003721494456884032748354538831215203553329779263289722351779436025499608302937937453427548391343898256662436681|31407608254280798910068647236171832681250921019767339322092058225211898617080663268645257485291372241381998253211825069099135787304279471888561584499577479790815455728926265455210044341705458408895536936732959677488304976642419035897631658694309182269500334892813396007185893728237634667266625229835842258012,-22092195466303851660176460286320107196721548719910482849923927669374860570040607441847880914766942886335893807802817619964909625774361248243281497972957437956640995020582500875700785617741050040570062784832399237969854446892064368205401494750753136317996032567462911904310221537322445611817601703460856421217,159599806073129555202146898538117276396235868652725582464386632067108341746813360586970644466851546908557689300426749066266037355857824949308514825360431584985378792225819436535456535877098069496677684472533670862820828085751117871568305588734769334428789980131666205325600082215182496839515396421731764800737
|
||||
10007655975072154117483238977535537637081635031134550457387493208328357153313126763724056490057039627482071052486779071595119245261713445964779121986765033599055846695490518512461118572219672259974233020703702627262496120864385268977830794693731299984872419878272800221037178910859958719636556859814167846842,-8361996877393239419962455468169075798408150795370677399435249551651328619535668258497248839588331109071829636371568824578953377032648893445576430394495769342785817892484051892349027624952023346102193243274713308717688268734992258026540569970994360123565176304254781068869111211172521527332383420931814632155,527575030718114283859783398581144142162250986653324445494333022369741458612967189239531512810665999743981788039851897018720856433180698951454061341786291502239652788707044944021930279936172715091766668769968367606820938741461139670556714129528610125247077397188304136573449554427712758172626387820770141650206|10007655975072154117483238977535537637081635031134550457387493208328357153313126763724056490057039627482071052486779071595119245261713445964779121986765033599055846695490518512461118572219672259974233020703702627262496120864385268977830794693731299984872419878272800221037178910859958719636556859814167846842,-8361996877393239419962455468169075798408150795370677399435249551651328619535668258497248839588331109071829636371568824578953377032648893445576430394495769342785817892484051892349027624952023346102193243274713308717688268734992258026540569970994360123565176304254781068869111211172521527332383420931814632155,527575030718114283859783398581144142162250986653324445494333022369741458612967189239531512810665999743981788039851897018720856433180698951454061341786291502239652788707044944021930279936172715091766668769968367606820938741461139670556714129528610125247077397188304136573449554427712758172626387820770141650206|34241072322144183964883259292388971270387490908021459682602920713448556112203521610314068181522265567865990070656464669642401927077378188525809052299062988871029831250362663444310773841166814396928628138166361702759595641474414467093470838454994055079747035830130336863078894622890889652436509718402679470062,1655044484629008994406707658240182084237566731635262662670986570402287449045651466425429233810999012995111207637792772902737734854633738760139439026788661518884592067665179528199667479368791803292009159500093938626059289257062277449763464663360562677734593664715953368375153510854218241931074507165471380277,153704107279914282661047729774770107006301606465000116416112632832793659221845961744254897413922500063463878032418234980336383112232225712099359203910269544199247014938285831933417628129448739918915220344920675471322163945672122675565456045357008398369947791399948189771245653263744530465795945375711800221494
|
||||
10007966435478170058236863959453072022400241955644959598691575049123018331553853255192930054734316870465371869338898000445140839711278341717767617282979890871322011741629926128943966839416929813730135095452717804664810492420201325502018871240152164282158649420833075991948508448454814819879697083763652090752,7668231477440831839423530692551370703245159224024821557501520508935072774934016430350932340192015949812739085292897564854127442271354000519287430094037838940253057942410525639491576166138997981100229304259461266977184946214511723634011266273522059488169041964372462366036564169749432744133670979109152595493,447718029574060000854039425364603339241323607028045749886344661853336043472604487444001370995744392053933719052361283419535725001600963164946166051448582948801443754508763343722896658178932382756498803522119159379373755295799841416904795415386643502857959662236798809639975132008241096398997653679085633708897|10007966435478170058236863959453072022400241955644959598691575049123018331553853255192930054734316870465371869338898000445140839711278341717767617282979890871322011741629926128943966839416929813730135095452717804664810492420201325502018871240152164282158649420833075991948508448454814819879697083763652090752,7668231477440831839423530692551370703245159224024821557501520508935072774934016430350932340192015949812739085292897564854127442271354000519287430094037838940253057942410525639491576166138997981100229304259461266977184946214511723634011266273522059488169041964372462366036564169749432744133670979109152595493,447718029574060000854039425364603339241323607028045749886344661853336043472604487444001370995744392053933719052361283419535725001600963164946166051448582948801443754508763343722896658178932382756498803522119159379373755295799841416904795415386643502857959662236798809639975132008241096398997653679085633708897|40511141969971494931196941724119791194752303140317604712667802312789797258087471388916305711860938934695113621471555129205767772174234194577636062024449049659844773057153826765602668788474097413358584157199226050803019714953337366130977602640661927789662051175267419967969752702153115129111296636218703221612,-10457935161594282983478001185436442312204066321569717319909561123122508532580035425990850447859762708795499274494409851573173766858979090795797351580839052039648316518437023326040967891533445612383815607198257699325318317220032705269084861881246335591645639989108557010113256147197407668582018981690523309277,110917353905486580092614272588489684725195855203152146381960572034045032865176004516881779898341056044802327638909692940931520745099129277448149432184154526338845672459752333598562775198340962552587031950250223610238795938815226253408453715102541267901432200534831078606195360844918970056237910632079232669397
|
||||
10008244313737062814090386880777002042274406310106728621588663972235471114422710824990333652789716385198940169070112715764189602790244309290680116655115170883594213904067142922764109544956215574952085160301875958128721493047843010586892757750339772804652221926614373576181872540979939178502806140149454950631,-2481333037464667013966629436643252131544342493286852105020088420979287811035788180793459525355154058635281869829040750298007562342275673082167816644462962921681726865943832615136603374637684966019868013077849325437190351276393203980513956812271998916894664710817164796538864396449149557648172823426916063171,517388856778664723601259064328056938198839891258102587545663260307743028813773980886782766877880248247356976487931222165792012525513693034189039784629831615801247177080220119155265743113547860287043754078724492811312457109356002302194457816150319735657096232303313256118001093875043014711306978887626524797260|10008244313737062814090386880777002042274406310106728621588663972235471114422710824990333652789716385198940169070112715764189602790244309290680116655115170883594213904067142922764109544956215574952085160301875958128721493047843010586892757750339772804652221926614373576181872540979939178502806140149454950631,-2481333037464667013966629436643252131544342493286852105020088420979287811035788180793459525355154058635281869829040750298007562342275673082167816644462962921681726865943832615136603374637684966019868013077849325437190351276393203980513956812271998916894664710817164796538864396449149557648172823426916063171,517388856778664723601259064328056938198839891258102587545663260307743028813773980886782766877880248247356976487931222165792012525513693034189039784629831615801247177080220119155265743113547860287043754078724492811312457109356002302194457816150319735657096232303313256118001093875043014711306978887626524797260|64779254867032834011440641150787867084487920384040666681242863744168381419066139445297813847374258248415619741363374551837200937516385938256833819108665346550630274436247175069020139650724403378810927075885582938267576954742862532587966930483553143703545329576408261048628895456023143683431401990598479630366,24927519754546965921961831708915463327214053646451495956699845075284971443847002280078538714647321447563383780925628397892739377674787824980025060340980938596623558107083184245064110657008379362919768477366918649506291628246060968841505524504481964062641513562929769991452205428879332678008403472520391251145,82309686205222727769575596923556209136176331852352419263671129190093456370915941776219688571948801625823542691573133895930427074460493264530457559070546811793879069016319253690636501038391024472030629593224593147217100960263693987497514077967804017050957134551364124670419141176242216681820543629095623072541
|
||||
10008352850657920583191404584913972319002983012580386292746025042416454380781500166787911252581886951373899680476686789855174455691633284341038191233672952065406558892215211615248443825941676410729187290225060888418790745853338806784833379906941049072152726050837490871126796612653775780560679723194628349029,-9709060422739575026005372809573612137660920177893029425373199378974797630708961048789082569968621509437270608151157000245230087521990222886335775421061577025607819009612244487407314145511220306148818899675596604132364981950337516654200767452148218615182517964628917157152074917236803799933149738760713914115,671115082942262350108425488433280481526339397188879799636007596624691786030758042881307602706684291172315374822828497006497958099138318651797094407888149790626224845978208367284081376364107905539290535619502916118224586762249253502377439399087435554291997555942600131361589961111751560971988821471576625969886|10008352850657920583191404584913972319002983012580386292746025042416454380781500166787911252581886951373899680476686789855174455691633284341038191233672952065406558892215211615248443825941676410729187290225060888418790745853338806784833379906941049072152726050837490871126796612653775780560679723194628349029,-9709060422739575026005372809573612137660920177893029425373199378974797630708961048789082569968621509437270608151157000245230087521990222886335775421061577025607819009612244487407314145511220306148818899675596604132364981950337516654200767452148218615182517964628917157152074917236803799933149738760713914115,671115082942262350108425488433280481526339397188879799636007596624691786030758042881307602706684291172315374822828497006497958099138318651797094407888149790626224845978208367284081376364107905539290535619502916118224586762249253502377439399087435554291997555942600131361589961111751560971988821471576625969886|16114275461489124968204609015452254643913218363912153828520620336762113684215205643094736684144935580728436126433843432822838401301502605946365466722979644980151185661620762014580187078928560591048729719792010275975517300898462040047538702188845074821092289043342754604938854931775373800424648368644203310763,13547284929895770484441101131779787363607604008853234716726800689182086390631494419380414868563006093483607315075063367989733593307441496946636597309123175793027336201138908596859844194042146843338047555922226658114601025214153360367295508810902077991437858537936819515034120605401664389985997179289268252367,418205108772032981216907044691421436420223410030163644353520139623926934302604091399665635789664245218369914570143791026851295152484545480995319870729672449287479092631425718630481935403940901614139408947960419781742920397934070995211934874602805252466775364873888815295833211854864682623780313523183909895620
|
||||
10008513012069041332156344897527216827073553214887592180214088737934259014714007486627977262733380816543933881903835772165306652083392244023687978336905351870998572186485570559256669905157006164174099943880073052263685924132434457096891529676454801384608866315724043225840413063557160938985851639441472622874,4312440429846754396035977404383353442711216523950513352151701783462030788529545110163564186199448542666033789397218053312248834710387435083551347290942668449155398673665487605130911092851155993391138549740383991056332072450757325017931588809593307558375428030693435084458386227675282989067613496797817920303,522058710434436061847099419719287842052400501259816466826452187248685474462894015989166683733824910524432920930163132078895575756633553848962708405953874665062957204347147145554667232000278570561581943016274309565656027423053224928776350261510971295444303769013653510888595366416887399411638422346190508715452|10008513012069041332156344897527216827073553214887592180214088737934259014714007486627977262733380816543933881903835772165306652083392244023687978336905351870998572186485570559256669905157006164174099943880073052263685924132434457096891529676454801384608866315724043225840413063557160938985851639441472622874,4312440429846754396035977404383353442711216523950513352151701783462030788529545110163564186199448542666033789397218053312248834710387435083551347290942668449155398673665487605130911092851155993391138549740383991056332072450757325017931588809593307558375428030693435084458386227675282989067613496797817920303,522058710434436061847099419719287842052400501259816466826452187248685474462894015989166683733824910524432920930163132078895575756633553848962708405953874665062957204347147145554667232000278570561581943016274309565656027423053224928776350261510971295444303769013653510888595366416887399411638422346190508715452|56624718412625747746001342620243125157932460809156476585686153252078788391585133765039303843105555487145302765475232301210334902069549060211140618709834572969221737838704380629832808447436726398836532031324189279819743594568958857642880728907272717965484249241620624993448126533648876371412676969976240808091,11251560979241989333315174860442827950692807971893794693178074029555222489351465658673586544289854384482236484135520000810924047294537285452423708542539424019529971512734796753346419671011832872098038047241101770150064698634673955572614027093346044433647412285209492755021945840975963737352969268461227245507,92751569706316371333649854241258112606711033359078430605766627827390581284909646252513959841970681664755979852330064323247275252913920697545008377769665486889671185641317526987823359091775252097776601502427528886408060350050959249578998479135473207338710170069765535652326679605884886200884837141964865764438
|
||||
10008863920545293758159888428446364046156260276486716019468090049016703539043486840953638396736429084536043888977532647111473229479529562166982909202873868243789742163658153824593686536088450915373691535781953841623992587097366077922476705574496276542011226471851020760887612018025249445972903686455787297913,2645740853855108763896589086717998001934973089513790734148937968197932490008236360599464772889429848037464262397763532307275971891237738829761101393275168415676294997564886931379267812086428886706751772215615432393366054082725778686112559307784475932288658665407220266586240637350907136870607040913290590611,793400754874236243676721564968016542454513488899050997526586540816446069760957715423992612546686769171106427349384375943641326144133116588670645501231299064478777846694278704641598622565613076600211712243453441442617903127555189233115008530187155578099336294750097716133611190867259168037807083105588642566246|10008863920545293758159888428446364046156260276486716019468090049016703539043486840953638396736429084536043888977532647111473229479529562166982909202873868243789742163658153824593686536088450915373691535781953841623992587097366077922476705574496276542011226471851020760887612018025249445972903686455787297913,2645740853855108763896589086717998001934973089513790734148937968197932490008236360599464772889429848037464262397763532307275971891237738829761101393275168415676294997564886931379267812086428886706751772215615432393366054082725778686112559307784475932288658665407220266586240637350907136870607040913290590611,793400754874236243676721564968016542454513488899050997526586540816446069760957715423992612546686769171106427349384375943641326144133116588670645501231299064478777846694278704641598622565613076600211712243453441442617903127555189233115008530187155578099336294750097716133611190867259168037807083105588642566246|27460683971089209913632788439277008206698726108421557048449583612748157436343375175859322164187154644764726127789104341389062435393682455959407312665088265825287372841830854948020646918675509930411197475014852013755108095396665264198600695220092526372517655520066812589582003333706156211987354238157895214440,-18754257799889030610388359385148211437538401837086321292345976113516028840634213460141894145979065231860481969629551490782467029876512509259774443102990636739699402915097564612184570929798790707857065137355337741260683852677325380877763634549633686621832440525952151518844155190936539038380094790162128388423,292316854113502420768516012912807278549304319263771926401370626456917590670162968070277533769157336622178624301667258725748409713154982300194605653065586096039574795291737865145837966259393195694514901162748686464295686525957546330665390520676177065848461958642958875916650558856747431365214941153816669348325
|
||||
10009505680139870683354483014980979080857116598143181111545123603173294088551257446784978515102956309603131729036042239470868522730508351640411841336927180142285333130556003408088825172687266397290471685595705033772539426652454509785808561354205994913107889793645231496289597484325916247643676615653797810040,-3204245228048542338423395469208468824364162898707311656951717207097770099550386735738728259011638956652924858793824233816950950613612534337274326306432643930039092581092193180132506302083387198832944317276664858711681950020725043153356848379502277900787129851654969895020729278524823784274520152043485072291,452691911613679447746063326513639174263793060004909642518772775706171480163325072807358357220816303993075973139644460675947299910587502105955195991864534504547078402941938298035649970749378328953718405749778603278187778609058449113337901162098857859007739511955733974919843773983479386171581120876366473480535|10009505680139870683354483014980979080857116598143181111545123603173294088551257446784978515102956309603131729036042239470868522730508351640411841336927180142285333130556003408088825172687266397290471685595705033772539426652454509785808561354205994913107889793645231496289597484325916247643676615653797810040,-3204245228048542338423395469208468824364162898707311656951717207097770099550386735738728259011638956652924858793824233816950950613612534337274326306432643930039092581092193180132506302083387198832944317276664858711681950020725043153356848379502277900787129851654969895020729278524823784274520152043485072291,452691911613679447746063326513639174263793060004909642518772775706171480163325072807358357220816303993075973139644460675947299910587502105955195991864534504547078402941938298035649970749378328953718405749778603278187778609058449113337901162098857859007739511955733974919843773983479386171581120876366473480535|57325550832595720002282991260198520855619892385753125887287449562869890287547556782700649421653735594090065432438621527792246214244092693717739414731384442034231735428582082971424584764012096459469280873967739009228670210741931717901688698237272251048307176343047617528247235108742851430347676100126914108357,40951175564652222245195473979961933400303424050552593889813171845223826940735103640121837889061263540857785714549429721536079825338211400035410823730435714524768011703151474601155984454456549759808694516594213778747991012336774365782807914607474811422076337673527879293888167855766653181026300408358374972063,86312387529619002943462127766854108620725875072481894074267557421849877085810739137001331161310595596779531729111999016553742317053715695938778491822422663861385491102185170957066107188324354310777066756950531425606616940837381593339739089909995724195482868610730939023987110641593221757790669575104910938446
|
||||
1000951516029909402241580153254201911805533650981363847468064026947791885513152190496939080952901855372998038682278000380636609527998130327379270561313029246942896140134101369621908911346125374976926115893278132230058065500703131104226075681633220114919188893134454475954292791954736302126634675741318978601,-932129972046203740107893826647984861393190609401184260933369527488206703962436872059299754006964658145411135715285131543309666916261147162906324852866784469362588174806798886084835311322495644384917815753456114043848321591684728503353583125390553182460085266457044328481386164295062361453557198381234996483,7741880922056878066612714130026240867522108473639420974553105203701418374724364127305856418938534523230858044879263234730427059699274843010051016880192588782731180142670836033616687676672699018701220814586539096635490574816118709819174615703862984275251303192202153140463446907523629847791487096446425558516238|1000951516029909402241580153254201911805533650981363847468064026947791885513152190496939080952901855372998038682278000380636609527998130327379270561313029246942896140134101369621908911346125374976926115893278132230058065500703131104226075681633220114919188893134454475954292791954736302126634675741318978601,-932129972046203740107893826647984861393190609401184260933369527488206703962436872059299754006964658145411135715285131543309666916261147162906324852866784469362588174806798886084835311322495644384917815753456114043848321591684728503353583125390553182460085266457044328481386164295062361453557198381234996483,7741880922056878066612714130026240867522108473639420974553105203701418374724364127305856418938534523230858044879263234730427059699274843010051016880192588782731180142670836033616687676672699018701220814586539096635490574816118709819174615703862984275251303192202153140463446907523629847791487096446425558516238|15746368080076547639613112548931198412928034872598867786846558772081390410891968919792236071990423045407820022126215168896502300352310051471939494022340800892491023480415508952796942181491516127339639471207019480870149174572084740672853889392694282271865099892527052018243852819055812247442628083006705785149,-1817913436531155250968687681482056128774282329369952888473920830262042372654938097136436607889208234812116291336524382413655603485552821293038078939629653209114696856829043835764482596948782168253580822692634503701439593841617763234039276530741649509861202111285883608345674200240173376261557395276050534745,492167869580416546150864341469450817106189778801161330939305290046708175512988010176297694665433672849671984872726657705850871343875774836983621356338570200418265577466209423429850230482380970478840847989123705290014954835386530282830688430538273550828822069628430975922343455045834201595340872511606366704728
|
||||
10009614232615212022005150149343932420969657134336251266196874043830583063114875468409344410544755395263952674188421355541706476649104687178621105860662213481607819203924674901060643908339267017280510002551378392012520463262809409257654601850085574494274200629627329653203473234690149811173235149360768384838,836267856629353024976937718074908246524235283001080657657057590803147642759710349203535369107634985057019274642907780561827986871269168282562729482602832882014993174240061797035451659603107102838592209619951864142851506020290496133563766536500833473922797379921857659870104796371847757654270012370698502999,784213921791375719854653276558811892255578032965532623567863494564671611248783758720878204565462346000781224582747048981949572160149632172258392213554094289354008679022701865566865099047150582908470578815534139684037571258726801746576984534581957278215217261339431677162978264928931155436559875241964125506266|91259641317840920388592572245493602418223311736654347455817117920969722081887399519379251381184940824844626111264019221904601665534920622151118371387906395484279959508114917794568416938471005687918332893135141888811509257566326226278046422522746020345472499138217410394253037717517813153026786742476211897426,65560628471815349730768404773504307627679453655870244754876894481952096786914419991524915369113837577161059316635270325176467655387763062001209403412378388608286732350937986269983898741335821089925199082458466627097168531389395465235586971316043725352106687336132311388859476958068300601993983492409770068953,97787509018580500559531280765247530593654008165836933101614934455794219747727474184974783904602569289723706867556213004773348953706945069163461128745310430174496134494281188144065521418637123474052338785100571778752720085930925320282428718659058820028049740359320116709840549247824331580105759766861379891210|75062088452630474843888448210053283462706588708992115575383926339301467347310815006622009334498696501710113137263962332974627478074375539845396462501277814094889463218705190380441269364077952749970929670210201903809188825244244127139203763727765293010747505303529125943832432756718681546490336041697468666190,5541281329506174033291380410034395388042944047800558435987093009948507724655465795692214345462752044394730637949505190953507095375192582819240934021514991426264136507386865262105651669874195906257084096658225527132816732104755767839079135854552727988309212343735183861434005237105894184406202983254934534757,104675750550793205502943520352684154101269712315945996783868759572927470248283594480842218327785617106312969404704918354113342765451442832450177716298160659447475598063377646514258038986139271814855804490712610499304684910754302950004231911223315677097295880861233808821150324765848314271787214250899197923793
|
||||
10009735080309013514440203870605983374104835055250399704317172848646825795572764221124512471397022599041102696110601760496809311877056400885225531243115647095694305859001567326435058426543669680082356076887117616533496794600222886637873441727978976019755009690240085029104982970925792121991104293242809524644,6716504442878527910519807778046246423810093302344836517925018933141102172400301207571530237654753113978791017298256211048865142019514745459130820608857728114059755451415522450033212605102272496818594519931368393561070233092047087381778868100623694505448318327728934167707696920045126563192647607794472189195,721610628334648695598193480418084731432879897882901829331594044580759141755040057210356863808123513214754128306537665937117531576524824114459745892010308401743734165555223754018460218362992047097741240949227118743681363740856040612578898979577195958019157067541288613303223475902295909138865214617457058483843|10009735080309013514440203870605983374104835055250399704317172848646825795572764221124512471397022599041102696110601760496809311877056400885225531243115647095694305859001567326435058426543669680082356076887117616533496794600222886637873441727978976019755009690240085029104982970925792121991104293242809524644,6716504442878527910519807778046246423810093302344836517925018933141102172400301207571530237654753113978791017298256211048865142019514745459130820608857728114059755451415522450033212605102272496818594519931368393561070233092047087381778868100623694505448318327728934167707696920045126563192647607794472189195,721610628334648695598193480418084731432879897882901829331594044580759141755040057210356863808123513214754128306537665937117531576524824114459745892010308401743734165555223754018460218362992047097741240949227118743681363740856040612578898979577195958019157067541288613303223475902295909138865214617457058483843|27431399959730041618757181598450126761864467783308250953166653158864868050165660437728250584906458406104160649372946064796764756251284036703521851065427172085011598154374858106257477054034049690307574700876194576753048475242472071051384544187235302865991596395901667453599382886279428660852987448092730327814,-12178152192814077151051956033210165813331619111090720689608458837738277955478946125067643676733373652534546194632007566276305197498317660468910084573634326652156582085984031315753626693903214933704476608819110626280721237157346811918265527840918335083118991187163668918374733603234110068582400025069332861471,264256662843741154538126874284653325441730644362235064492791411891511464369737085603945845443869261733906715033378896197504349395743395072323232105722154314007209047495860245950090828739984743068229024820070744102308175917924790982043751500738655732108120833669083027766207125418432774798887679934336031211189
|
||||
100097767925729329322181122349613179670027446504792908817095637890752573498574361347439148152051968207056866825997618536117991814714859714673883034645066867063812091504212589938420469209673745687587262010655197327448038749016704401923718318821311108473542621283106029369259039074767836862058509435455755610726,-100049042457569505632055807384899059068938967940837318894350268996535213352709148936435708901083176589583550587767198440304487034715449239754368855557475044885723026390661018171437823688972174609609018769743817618355306963644565862125983532960059011062792908538954329635940471395263688377520252608542030523093,101825233069512741038457795802309532831632092007485080725676678162290037786417230184436300741781748657320031840082727976574819880666874823641143033563613526015930298529985774382970686476257558271965201142223855170907771875249088691707619925926120372987467772228909661019762594761741996613700919454999805975044|100097767925729329322181122349613179670027446504792908817095637890752573498574361347439148152051968207056866825997618536117991814714859714673883034645066867063812091504212589938420469209673745687587262010655197327448038749016704401923718318821311108473542621283106029369259039074767836862058509435455755610726,-100049042457569505632055807384899059068938967940837318894350268996535213352709148936435708901083176589583550587767198440304487034715449239754368855557475044885723026390661018171437823688972174609609018769743817618355306963644565862125983532960059011062792908538954329635940471395263688377520252608542030523093,101825233069512741038457795802309532831632092007485080725676678162290037786417230184436300741781748657320031840082727976574819880666874823641143033563613526015930298529985774382970686476257558271965201142223855170907771875249088691707619925926120372987467772228909661019762594761741996613700919454999805975044|84308318710770953640248175476462028139373764391035194691231680218526343685551415536853656437464155941615590227223191821309564306137129412203074445224501367988293836354108333795252385654176431244360276218862523025987282479232565449230085787098609814824691928891608841637881937218976744434331438048491668714172,78229471895771291032128733343240907956513700512674961776679342047382405281968278678548353708794851883965121941126776164617402656831058062037098035411278996202926380143407188337949264849125051865072631849969234447888440699755954052452126159543200468837557873802507174337535425627611660644229281086936050355075,109360363649395746265656497473367613906192696966623732296103764282264963662145240362278977792876351026988778202744708027814748063715992412060773465595050876884872367497101878287000352814221891140816680001766329736587915177644869655423120132329944663172310205372239088325795595410385678741576083941746461375629
|
||||
1000990088197024747059083499592558231720263720277516776155079181049136503434198702340667607714363713879340855424897665647049377714485771691188931707633550660945052279457196551479047254741496420585602556120439906566870228385196796680534214981451257503126475671546702014976009092407415021171352670275245814728,725466386677782932169006961452587026457506864587404408874444216403861787891316322821563900402539391905854377725716394516795127638578550566829765062852138101610829715414344025748861390095121907615243675775588453320217679236986850051456109259336757301010447881360582473998540771452509411313781955577190588933,5517508390471385461294072894661016222336566054567430728481305159339660984012399389945095200514405410813099792232460346983221900276173777626934161693012967410321899909279792957271372152068664807744591895618427921351514391226515490690862669088614356482368865242803422288159831017511240290921861425877221350767081|1000990088197024747059083499592558231720263720277516776155079181049136503434198702340667607714363713879340855424897665647049377714485771691188931707633550660945052279457196551479047254741496420585602556120439906566870228385196796680534214981451257503126475671546702014976009092407415021171352670275245814728,725466386677782932169006961452587026457506864587404408874444216403861787891316322821563900402539391905854377725716394516795127638578550566829765062852138101610829715414344025748861390095121907615243675775588453320217679236986850051456109259336757301010447881360582473998540771452509411313781955577190588933,5517508390471385461294072894661016222336566054567430728481305159339660984012399389945095200514405410813099792232460346983221900276173777626934161693012967410321899909279792957271372152068664807744591895618427921351514391226515490690862669088614356482368865242803422288159831017511240290921861425877221350767081|46386382398471210654004936862977280764038033260370855702299152174715903684807635787033726061221737095817373565974565953991423132816014499962739297327315390959305555345973541148973281098200177613839273688191655843120140926599099288046020383471244522466342336148402764983519506510433171993666037668400990623062,30909786208868059159308250284546387617592958673051467586322533557805038169619650467442753505158926723729781335720702109207080121759415266351938588413071223894526233303271669156163543157906212613065654926067039001367294657463422342698879421926602847752406836893005886958919719183994605725308548242138957881171,124210879529497457542798731661855988692615123385567383434289407838970666113795793650595394981286850762118704131523110658152541154934468138859842609878663166338576053338898592108554591614195107201143517584467526852469899754023757894264352510613574752993978429183938806214485060920755151052534935466538850750938
|
||||
10010004064090651409010594639848304417245586560948860214310742766846249258119176243618948796060231286565945627267454791543296430719743208401586187196864109595450365240377376347430379493062158659135705093920261708675191488141331016387425285934969492844933812420736541635790559026628543841128935951718908539896,-1498575286639922441240963650822632036400568058110825911189335188996116649771598943688044499782411654295552472829397529434461014441578505662359180553723401992140786537396607735356416120600823531080136067285152784381639454281243980298334520221160338176676576774798710776186339169032737324810281860916038070823,768468744922072210410085870438045813460934852024069843981629956982064663744441536899640311347039303574749086761908444837858696612124820590763553776868490058405671131188766507451909827840059264627966884129949211264617246300058675643121776631374263858887287691658300066890342985411108805960696775940061827501049|10010004064090651409010594639848304417245586560948860214310742766846249258119176243618948796060231286565945627267454791543296430719743208401586187196864109595450365240377376347430379493062158659135705093920261708675191488141331016387425285934969492844933812420736541635790559026628543841128935951718908539896,-1498575286639922441240963650822632036400568058110825911189335188996116649771598943688044499782411654295552472829397529434461014441578505662359180553723401992140786537396607735356416120600823531080136067285152784381639454281243980298334520221160338176676576774798710776186339169032737324810281860916038070823,768468744922072210410085870438045813460934852024069843981629956982064663744441536899640311347039303574749086761908444837858696612124820590763553776868490058405671131188766507451909827840059264627966884129949211264617246300058675643121776631374263858887287691658300066890342985411108805960696775940061827501049|28314042997988233306636589016992476577770908296597830278146083272521268550372497996517202454826620755010065709821222609305573779332296860088326682557505516615132304908709189030516196077907461669993069872444768482204126654812645619744037494119483770734571472757955818228427379193994724836630122637837874512512,-3910830326710790111629753186982470489266159472894461132493344186147852161393575078274643639038642275689976708947162470525418556533103511874282953768387384089989557162835543128542264012421515524615699954054931189762734554550136613958599656445264920707571157499612722532218838749658906057952745224391208374423,271795782638036641105135359411824479015439355083041167763715963674151201738370794758665358014925962658456682314365819593590637317922383444961883165716906142863933218099402568928834160919844733051508148071302780085990761872080854429570287769745420760134784589649743625063761926379339662449726354233483569572692
|
||||
10010469709639397131321593392335940518221591944212653476848636010049901173327189141010003266402662587851391795365145565853592244249890218572600240492819519129624586319882991468883851157495158734614747790710618700576914513912845835699748008363226744953360119054075282875557290214809856164142199477757165509164,7505657900398833324827399204281082596119737445028635348485466721806081208043020690125518041418692182505619967598743043368451311836537618411006688337064144530591029793349206581566058245087905481171249541532084530428115422022022771262499445387394812364092046818720427959757560293344117843608115308687123143421,553113242511887630245562923692119334560619363555162251614925548023827683747558857060226873484593892808999168052131745589052836855443167606888604202950573221560622773360660465500305832700518144444548624823481416168401044677399877530532448619602616847965589554700283201541685397541240490155576228110029131773379|63201743899616470908035016615759783248572310773988939570648682086965508954735585744990615463863202134213890574490859916770336808958389758836363215334497075053557112818568576204445815232807749791417195377923291221271056534552496867547808556556792554364734430966783089440150789750091730879530896624414277659061,-55856955103087382729788364385235549210397677016869607285896429414455503436682728351867754944498329815149524455764192011560832811681933262606199210273482312024649522293283703849873542800068494104680666316436079341962770915103078184937312059708038123793720277348890693601123206211567358221715195838805665244815,99725721230004762208212433032530958477513183167215245049998941633413237167002350956483975841846292547322289722635488222088283425749457741260773683563042470151127137265045721725293085765918300826804733069413639039496778512157339321750973991239393851776816288547058721349853339439566413417882881431596395398482|10058483900212848371336105395105034597443877759659095074874545915088017898536154919284167493951088960283199509655255215299440632845548287448716500241460028925186589031890037337660582657444623147488470508614291087038125788600526809670994940639159256871538287711131658514500837340353796975836990505301624273881,-157799394991431658935500911446539445587307591494655221580870826914115793039596841571933100144135016253304167518063315606333327146563644719359095984750603598277704663545389186967829006269785943764149594510946914419779083189746476236548753466257639182993421200334901817261951648692278188884421732061466347929,549073390680838282030926276806663190640362547475399531148862958328951733805907419890212210186161292258493318221366553074237370828617692229205217240695895636477792753409007387702564155250318872755670718485591591748806803837858464359711143468897253705933551825195496604931204015549587680036788025676123194339726
|
||||
10010496751485016737255498721953568674323163915462879922384146496780957659766649785727318078913117215770623612059774196084160730194502430474210832948012098222392905483059314666266093994762308130821733627116456649448335020123456572070799012785074345756980230844151670979497392292798505519219012749959532875338,799688122820510610823764584829566759424107985411345815493636913295490164723810636027858758547620320075665083037412723404618585417481351642215686069179403481765070501469154817238059870792625025657772680475594951623612932084444307492923899340395814785386177783715246947669812896758158101579611206283404125383,756465676775987727565397432418408198121332665761199779426305954315978948084770158074763521327096161584122642931162604561074895576932338265005852611804594502809713943064130145585384616864112057298562543101439879468994210857521510834193578678095039312141817959445372442666042645305218271194929494814070515333525|10010496751485016737255498721953568674323163915462879922384146496780957659766649785727318078913117215770623612059774196084160730194502430474210832948012098222392905483059314666266093994762308130821733627116456649448335020123456572070799012785074345756980230844151670979497392292798505519219012749959532875338,799688122820510610823764584829566759424107985411345815493636913295490164723810636027858758547620320075665083037412723404618585417481351642215686069179403481765070501469154817238059870792625025657772680475594951623612932084444307492923899340395814785386177783715246947669812896758158101579611206283404125383,756465676775987727565397432418408198121332665761199779426305954315978948084770158074763521327096161584122642931162604561074895576932338265005852611804594502809713943064130145585384616864112057298562543101439879468994210857521510834193578678095039312141817959445372442666042645305218271194929494814070515333525|88526457805417802579401128655636200680578875592064917653502726799402631022732331707242469404309708934422669188417199074013672835521067841289769648786519913947468121765630841991231363845393790849492596901524640146832343923907202043034825750225542103503647484110551329413090031876302117118017242617457435270440,-55270872554503717308092985383981103433537850547649491053003970562528650386510337748001788465211336165026556518877922750831164872435215600571701093825986357449663403092607944719717658773706993903771608486872517959780200593880280040497747294339054563275578214457748886755324708980839180036767067720944832209613,94165686390158171873356770999242344439144784888928297429784348143756989501060133555039087406934644294830253094462126060631940792293289142829036758298101067851753964448066092115935075783351846337421975097419550731994478824011482838934049698582968608287926659413694080435137971696387627102349753238458722293238
|
||||
10010579112627452164700751672418124874438960016155391309411143579238371993812216949415371161492459719515415809121706298625750585115724165801767312632070537335293199529430577590690991572481217905708780746070115008642386973910356482808275744430781549387996153714070117005169542728240082244119738613459581149403,2350957735421970008675187616979703886327431020247822920032684793437439591770682963150195069182216167082120247951141628182676139493494439884424368912802413855370850694844333281369444099710260137140856858089878674493931790511953123605380418199403899915269505474711266010465371671818915910810005642457030207323,611423654589890839284741885001129722618409625326976389817674733477626186444470464645132913394627656053210319902647997769502456733804852681598112059600692683589494771437615834703370743285630660946188840487388799145726650756609808617614030574039934664771328233896579676781994740365464050319193605788676121096976|10010579112627452164700751672418124874438960016155391309411143579238371993812216949415371161492459719515415809121706298625750585115724165801767312632070537335293199529430577590690991572481217905708780746070115008642386973910356482808275744430781549387996153714070117005169542728240082244119738613459581149403,2350957735421970008675187616979703886327431020247822920032684793437439591770682963150195069182216167082120247951141628182676139493494439884424368912802413855370850694844333281369444099710260137140856858089878674493931790511953123605380418199403899915269505474711266010465371671818915910810005642457030207323,611423654589890839284741885001129722618409625326976389817674733477626186444470464645132913394627656053210319902647997769502456733804852681598112059600692683589494771437615834703370743285630660946188840487388799145726650756609808617614030574039934664771328233896579676781994740365464050319193605788676121096976|8039922802491265414309990967793279613501148402448480465019122506003939256870540144853780285033203931808455458595860030453208550342558408097242925918803433428637982781245121194507511100106884732787332881816376538778408183713312626895063525916116529477067428617194552870724443468826009500481151973572267660629,7782542056885878734681190877592906346631460224605439140627247356888850052165135682978538906914658013311431434956582299659243906965976772069489496351182726287233109256230929112390639759813836413367620416284403736856845659506160807594525033721234682734219240024280033734701579761670420320393555156688458386939,763000498381829086301710784279931419423976764939217073711509076091719761279556145759370750276614372372724227557071534934449510558501017918011817000937860419860520748646784487080323157808376840620794576624474012291138723116851111311356377966880000941424814810860193927148425226557672422373368027666445875216544
|
||||
10011186832308679529580531778689417394449477080570215256255872899524060756354513251052234139190381882237674326102549194541918465150411281044342531791718191209528218579215954684479017629118919205540336463087633388203942961094184672710469514635568862008937176486425382826532999400454876885123467677882356280867,-9760739041412831860016040329300538464595968662597654195818825742388623357499061055114241473465244979572894681398742727120008689894660036669893911021076723092236596538937507422477033501397620347314916527511417876669224922540378674704881346598392965888769411037021701309263621236037226524490335501235413158317,618797456627391285757491837806082074086781183030320963821992656495001963414332567515207750538267219197978733813073360730643354769504354220428586481088489050423524166052003546758616279336334294024003134192912678054276268653141558092399335706944717740861723542047714673114465932057975066598256237991004833528194|10011186832308679529580531778689417394449477080570215256255872899524060756354513251052234139190381882237674326102549194541918465150411281044342531791718191209528218579215954684479017629118919205540336463087633388203942961094184672710469514635568862008937176486425382826532999400454876885123467677882356280867,-9760739041412831860016040329300538464595968662597654195818825742388623357499061055114241473465244979572894681398742727120008689894660036669893911021076723092236596538937507422477033501397620347314916527511417876669224922540378674704881346598392965888769411037021701309263621236037226524490335501235413158317,618797456627391285757491837806082074086781183030320963821992656495001963414332567515207750538267219197978733813073360730643354769504354220428586481088489050423524166052003546758616279336334294024003134192912678054276268653141558092399335706944717740861723542047714673114465932057975066598256237991004833528194|16023810805641333724336357094511552886496985977223317205804900540875359074549841799895438359675279197334185032768159914670757201278192258514539721858337894442748764924011517017369466984819970583389409069776399176053947560735257602992978470081403520015409641979689232868403667818818613535419071872687266278871,-7532673756475565262302348084703438182578166716950696747316478761861175843795966574151023129542515752521204794815061142348575304950316771972303577053107419061405627955596801577300288807854600908796497666677601605740930719732644371749303298593761133443055158847238113190613766743442416892398264321417028494683,386004572289283022539377207289773679498488550299986782511093221618938108821853499898482934516175608928422720022347987369229961237741779367136076661442684969604660313702194515039707016073494920297591526290529740277402244949703587380758181579357976708139982649833967127198595634906215849970601175752843362414638
|
||||
10011352260197967961196723001882777157351136553686255118590538903088960848511094106778638364952379274889738636611531352467905470187088001978395724543759615578178012440339389212117360666565610883522821465968556183822388268042856072812425704980952391373927012924156734141733616109526841203308615171993851798580,-7221676671346271775547094631755878098073875121922187404285664906337078018452572717764275630077273635227060270555255283560769931807823554231983067592327106941484374528295871153247243771907559825959222732921231505238074239141672724791953035282099263068621712554135551648164407808630494744659356436708196075003,491103641942430897255353076452858177434280940975186423223949785500010643311551520732003340225232164561507795653594281473147298622615199173589020255105363616020518202959139902358320338695214760426102498591057589117988289772846024859991303086757574971564242450863802854515962057480781826855732055129393601722620|10011352260197967961196723001882777157351136553686255118590538903088960848511094106778638364952379274889738636611531352467905470187088001978395724543759615578178012440339389212117360666565610883522821465968556183822388268042856072812425704980952391373927012924156734141733616109526841203308615171993851798580,-7221676671346271775547094631755878098073875121922187404285664906337078018452572717764275630077273635227060270555255283560769931807823554231983067592327106941484374528295871153247243771907559825959222732921231505238074239141672724791953035282099263068621712554135551648164407808630494744659356436708196075003,491103641942430897255353076452858177434280940975186423223949785500010643311551520732003340225232164561507795653594281473147298622615199173589020255105363616020518202959139902358320338695214760426102498591057589117988289772846024859991303086757574971564242450863802854515962057480781826855732055129393601722620|47792242549528045573835222090102709180753366247917233792162207697772127315858077638348932444421521322861739464396186442116808539325522348191328660258855448870212049194866543072912231226457359914737534217070905308248553545640574239424386722275092722710319161088562287826715987711727881278079923845948791676890,8254269885969125051120540706292376386106399376632912551223385556280906209369492834220174830708813086153383708455555132979546664334186800724505969898808175578003259356450761612161617233904190263463404177018953974392386560633539661122851396041321655235390273818809845177966554527106703090511634271703426366333,102958270685953367083211535309354861429334576908033521565612066728144639011805671376037609804664223083707360606267980895711740633481159521495849279040716328723662579233841335201356070651023351445332747117601073346257424542725915546556026838056238556081287286460939074972020327613774707117438966240554700925838
|
||||
10011859648773232442448733215609838143695842496672408041181163963731715385957428830906426802116840506850796500226397482148532808790741216756533590408501689411024510944680051255986998627975919616236379312627952364824369227089618523233361113970064976301643797723660966748317498805671195280559795030489377669812,1389268097793948084201915587623858469968349389719030883277892933626050552994624565080658001697742466760286196070343106937791393185285082388402785127475337008454634105961822228566730985518119778298380464943436464040236734762976514693785454254940058632017513195975469702286256915116671279121716893380760195997,798259439380551890168577021365722645610234093426080631569938818141778075039283575889046619146360005141391892307832892070793699590106322160142086889812498495186005607708401945977916695847229243650515563078729723204186390753029064543583093290363210178756937751032079469629502953157831010865389293997646642560816|10011859648773232442448733215609838143695842496672408041181163963731715385957428830906426802116840506850796500226397482148532808790741216756533590408501689411024510944680051255986998627975919616236379312627952364824369227089618523233361113970064976301643797723660966748317498805671195280559795030489377669812,1389268097793948084201915587623858469968349389719030883277892933626050552994624565080658001697742466760286196070343106937791393185285082388402785127475337008454634105961822228566730985518119778298380464943436464040236734762976514693785454254940058632017513195975469702286256915116671279121716893380760195997,798259439380551890168577021365722645610234093426080631569938818141778075039283575889046619146360005141391892307832892070793699590106322160142086889812498495186005607708401945977916695847229243650515563078729723204186390753029064543583093290363210178756937751032079469629502953157831010865389293997646642560816|42206894030530619844844137895190664968269730414499521872109243265156383878372533066719066634351278056931106119952256575854241753055519807843572490047146976978089248439736200704784039417511594978273239033477711961360762067155137236184651290217781497985287933853456015958183471535758824703982061917287661765041,40970642478148233733033585114396071242748464687693709425944631778683899124773146938566992970029345645063087493796799166205427214444613129772321140093187953348169602638764727669726146858903079780374349625954437240902856681427277267635228715453381995681831199770224812459964590952867744306421769761996026104513,199285626990423651406783664663645910990492228214328517061400776387771491511391310851645339521126305819574623301901411324234792418046438608476979083398394165188934652648732128312553721596148859379616564443828216278968549632096439205379175627317399435861673444161870109940456991316291287290279435962880377080302
|
||||
10011942112859072995258791154733863477789940396938883213028206575320538554823437297402241742896497695874369416027516907850508925314968512498072222974096801648178807861791486753853486254133021354211722209138812867027895370716192265840613761606054294753819681190630045043947858812851889188252918713433862450937,-5571668968866828804921046721301654575883923332633233994134906673281267773210784380932788963105885600448276206900049033963090555880641132208787100277713410661373854250945949489885604664165828601242508315193830303811886340805084372525080806602568264342555171074951419758002241352180046540480238252242954050299,447717522759824444351173111605711384841786993787566688069178368722388364402515540644758414533643421974927299526439953604872416797996604293432960735663438930460329264500528581210531189312463600150764233828882749159851806734992346380036786298515789780808132282396713107095426662454069422796780131140784450873310|10011942112859072995258791154733863477789940396938883213028206575320538554823437297402241742896497695874369416027516907850508925314968512498072222974096801648178807861791486753853486254133021354211722209138812867027895370716192265840613761606054294753819681190630045043947858812851889188252918713433862450937,-5571668968866828804921046721301654575883923332633233994134906673281267773210784380932788963105885600448276206900049033963090555880641132208787100277713410661373854250945949489885604664165828601242508315193830303811886340805084372525080806602568264342555171074951419758002241352180046540480238252242954050299,447717522759824444351173111605711384841786993787566688069178368722388364402515540644758414533643421974927299526439953604872416797996604293432960735663438930460329264500528581210531189312463600150764233828882749159851806734992346380036786298515789780808132282396713107095426662454069422796780131140784450873310|27084975518223203685159476564968667757147005650320881882446538924664746760650597697153771281773275150298344920435750377585362202361041033907635631944580948271756519774659017735803323446011519248098440794538345241902148398434473456015090213973679829939390143526742895252747749904765235510343943624603085395760,-12790519385524034711380512698893130061457017090294213212099271214034680483663421242204264773620969593678221374876014811278470247764306480672296083402927981473695204988274213121345880281894543363725179804965957322222445321774678314607579703404237389600553993220560492758375020231080071561518133534954466259951,166721966963161057002408800656254458745347212698279982813080522419206471402712564010508086006697422863841361930966373632778322663543126671570353059325275245779405843551444614505569300692917404907917428765459530333591345110277642064762234238705296425159456946404870175457906061825086330206230526422507612458697
|
||||
10011955414042796957539613462833567748978021174979466353940011258968857683495843510716962870026112990120612239420094468274757074371715099897797764809018818677244411173050607051965491060861928470702220861911485527125770697960299381766502895029523905888655809759985815187019718331529320273577105879315557816044,-2903598288233181369386909069725761325455718972241715705067575929894098338713960225913955377920698582104810776546675110854231130224088963639880575858411672466883767586627134811452446768341259728766799505769981364639560814489840847334997666650046443822662727211952763808116443820225341403833059567092278686013,716711840847237503666263684416016435149389642949031161572660687058464860752744538837256522716160171257335781518708196625364621151126528577774399883526209845714231475374012476325785739496418344991482641972669482173664514234171584896006659617692101904655946713038460582513645370686741753929246439907983936752037|10011955414042796957539613462833567748978021174979466353940011258968857683495843510716962870026112990120612239420094468274757074371715099897797764809018818677244411173050607051965491060861928470702220861911485527125770697960299381766502895029523905888655809759985815187019718331529320273577105879315557816044,-2903598288233181369386909069725761325455718972241715705067575929894098338713960225913955377920698582104810776546675110854231130224088963639880575858411672466883767586627134811452446768341259728766799505769981364639560814489840847334997666650046443822662727211952763808116443820225341403833059567092278686013,716711840847237503666263684416016435149389642949031161572660687058464860752744538837256522716160171257335781518708196625364621151126528577774399883526209845714231475374012476325785739496418344991482641972669482173664514234171584896006659617692101904655946713038460582513645370686741753929246439907983936752037|83377818300427508414411209474182765418541299931790991979162498055814470115047955070666996621536705209820738216257135146862349180486198221400982101436215575798938096836021071281557720129695222554778979084677391347787960453403954349664348198928269790759939576077051077722913333980873848885097124565249932890109,-30688215255611971606034471669429848439589330363616017559694024730487742561639314516549592500671986661135255749032859202031979689977991786343363266117721953715761747898795102634113940122259396542403236218273245556434610755838474462460273735366438965428724794482250645649141152999575795556913839603294733616297,88860815315671630897460232604076507207530961201107386907073059232104245557771716637121266612833291311086440284416177092484049670682110328081485080434205469417936503447466464463362446293805166057694349242947508206617775986775538756539497474332372390720218420029346868304694279430904189373022716924576015411382
|
||||
10012228673376152026567450992902390970336864997567041834794435762949115261281228493411090141625349816927161690458296667158108080969724709444972658280448694411038715631967371509920701285876643071095813601274276803568595952200658716678278724478871970783503276566469041579910541903097002012017970816393023705126,-1525621196152714906745704861653134857598506051934926836340086172347518826544771422485438019089512861580045344082067612865732790885320087313117232977161635917848068594652072218066650842997301426696286712170439049522381084448274527064469835335059461198790200539335886996343589558210546809155519571241608841115,566490489998797306378193876913958339109032806676495000099448643263727848667893470101258216128095777975779077696408017781065855401798377205019264716443061687881268372472869438487229092017706767156974596159933038800310353717032995999433855144018018195220506116678554717313645342356609548972497509792111447080303|10012228673376152026567450992902390970336864997567041834794435762949115261281228493411090141625349816927161690458296667158108080969724709444972658280448694411038715631967371509920701285876643071095813601274276803568595952200658716678278724478871970783503276566469041579910541903097002012017970816393023705126,-1525621196152714906745704861653134857598506051934926836340086172347518826544771422485438019089512861580045344082067612865732790885320087313117232977161635917848068594652072218066650842997301426696286712170439049522381084448274527064469835335059461198790200539335886996343589558210546809155519571241608841115,566490489998797306378193876913958339109032806676495000099448643263727848667893470101258216128095777975779077696408017781065855401798377205019264716443061687881268372472869438487229092017706767156974596159933038800310353717032995999433855144018018195220506116678554717313645342356609548972497509792111447080303|43590031232680232081751882157307176889837208488946678228473969287186808910765585247541543237267000539198165783309913805801898560564494504170518670105700488271939383325260531063287350050801106407955825720824399992214830540252117419097263989404727460007269455161541372200543947623309137659512638261713267690824,-14075226919726761245118463757100097494169008867441262054574698130139530299753414803053777844415814847468435199262862690860015506966052100586678181635131495519430715844772863497248903106204345001653326109572317033217334530762155783910231739525445183612742122146838723561339801552140211476495875670393868085081,131240521940112916676543723913094551994900810880147949771730918304609983182487804507629012504949522364314455047343021279573082629269863237002108329413796491307563278912051552679953053070493799302202693873331428377723854674840449409246578209307981263784655485960382622975619701504230119584672038533695429676088
|
||||
1001288292714450803721216442216625955625371798611921786124245018047248562264647981975960215285171753909781321204807230585425114478278803844011930274438946371170816602064333453376960652483578633927890649034364140705267107257789492504807548712851379509812488664968862197781823935761608178854275129769647589581,118977223991225808492576983063622698908224268079465629025347336989392083161221074952362214752172730464574518166801398443928377167452950936101606770394549907364810511870992758058622270316795961219734709916323416843582267371642230512848102350867740488489154654911017481701711273952134350507762249130961129603,4253782247854217005640367062054391551273020323289717198551116404593406680781947315659948108589518702797872582317228254446273819182123102223859859093093126618316964313793208051942159218633324159151062222504543999694994085787779078206117679218461273671966899590739444942724001001618068559652898782396232628519674|1001288292714450803721216442216625955625371798611921786124245018047248562264647981975960215285171753909781321204807230585425114478278803844011930274438946371170816602064333453376960652483578633927890649034364140705267107257789492504807548712851379509812488664968862197781823935761608178854275129769647589581,118977223991225808492576983063622698908224268079465629025347336989392083161221074952362214752172730464574518166801398443928377167452950936101606770394549907364810511870992758058622270316795961219734709916323416843582267371642230512848102350867740488489154654911017481701711273952134350507762249130961129603,4253782247854217005640367062054391551273020323289717198551116404593406680781947315659948108589518702797872582317228254446273819182123102223859859093093126618316964313793208051942159218633324159151062222504543999694994085787779078206117679218461273671966899590739444942724001001618068559652898782396232628519674|28938807607695569686193558386017186559599585089880944105080644798657187851944851177349121001670507484268388813019981112914318210410185959709469975835597908447130200721022330232315439534240435891776843814205222365393996713243986623555128903274366840091822641672516816965782305494688964249039137567600077936606,24347068586442893587653361936682544233359974224524919385561963293036974216353969467745312829316424149479715944098504674533950906586338239024243122404600846692591968993298391467756407074710363297328032595080001517924404972784909440292445668484007116372818768610926770836254572445727057593300358575616247842763,152302535148483948223815371530668367432578267200771233287129083802472440010529096619024512937585549897229409792244544585546299937914900082139679373959823145377421946865824314455823557999559223736926801877211472988708620154393053288483777738533792797643686229459318486035573754517579909390578108894692032268889
|
||||
10012892006475941528884203206760641995368133321794055404979199342382084602756352644705532078779012887564604213637869579074484075768567055417796954674356138026767547529561933792018043105730958440781327057508393480700527196787164950646236383499370902496883935791129999602941562207002549251300455418372635519273,1454009605238489140114391427335527519147008275556174452371701295849315335234637169205945347453687617440824028465168238395128115858746597274081455839498538752590048744221995446875637484166488769782049750872805524958169087781809205120801537577068712904423342748390795604976651954642488089689583155223913397665,647808943230731060739626381975524675037163647891128462337945233305926315404323308376753006196333731632781667393569616294591379982170007646969372304454389485880137478967587874806562743050788204733473153064889810620961745850926397404102543921057382519028198560438333275110757811110797391594327323261044640054976|10012892006475941528884203206760641995368133321794055404979199342382084602756352644705532078779012887564604213637869579074484075768567055417796954674356138026767547529561933792018043105730958440781327057508393480700527196787164950646236383499370902496883935791129999602941562207002549251300455418372635519273,1454009605238489140114391427335527519147008275556174452371701295849315335234637169205945347453687617440824028465168238395128115858746597274081455839498538752590048744221995446875637484166488769782049750872805524958169087781809205120801537577068712904423342748390795604976651954642488089689583155223913397665,647808943230731060739626381975524675037163647891128462337945233305926315404323308376753006196333731632781667393569616294591379982170007646969372304454389485880137478967587874806562743050788204733473153064889810620961745850926397404102543921057382519028198560438333275110757811110797391594327323261044640054976|62940556237396653206223780718542562667295386352158429493270469961690767724114029222148067827069562399174914339449248246366326268552997433890745884344199015208364859348865726612586847277646257664344896903583225600388420348724002194132332892190932637136851080726053181726410409254132012307744554948406613929323,-48701511676436282890206508014619418354003032902027055232648782348677470406094053907961181547187251236573045647699655583258566497581891423764342023041779904338115306722370857935574573523817812044494597510209680776289279513137149479122384803569185846747971729826779306714510975413862168549755168167117700353327,112469164343071489234368373987004423456191302343816707379444012274611228263948855290569720261858996544051020707105809245289927202553907369725233852283792575569835413308417689095793467463934173594106404637573580430116767215310604286894257928685108943559541701617509990028119392117707508006024253191362515564488
|
||||
10012909351086759965456044227627057711408098785482672328633074337493434448564318338609803059310568728348413958910299881715937715018572879175542723270961874435550327968633029584188957768139340259030454592302362749027465867807734115139476094923287105973980458884201581736181829195017361330152871853820144480008,4004735351364710265644908449319598352103612215188460925760295665563484237162745827742855116753659687319941982652183152982522805963387540988424745778802028813186258777373064074552858455437921359277118582292259532327491507456668283228943221341315392967683928177537547570473748486481294902027111753951887811107,625070500924631773027293646808528931297961990338169633089637061010766445639876245993583660254312851352153995204943188734825803541904480394551165674837469282411059121521375161737576421883549419892239480294917943542161102975888315623576549465990742662361177906359742645436834392762941048730926726541953775339985|10012909351086759965456044227627057711408098785482672328633074337493434448564318338609803059310568728348413958910299881715937715018572879175542723270961874435550327968633029584188957768139340259030454592302362749027465867807734115139476094923287105973980458884201581736181829195017361330152871853820144480008,4004735351364710265644908449319598352103612215188460925760295665563484237162745827742855116753659687319941982652183152982522805963387540988424745778802028813186258777373064074552858455437921359277118582292259532327491507456668283228943221341315392967683928177537547570473748486481294902027111753951887811107,625070500924631773027293646808528931297961990338169633089637061010766445639876245993583660254312851352153995204943188734825803541904480394551165674837469282411059121521375161737576421883549419892239480294917943542161102975888315623576549465990742662361177906359742645436834392762941048730926726541953775339985|50884288706475165946257509654999208555658693396648687044835752784386552584102384977309647778026166442592405819250800637374065583324042092667913200394806282864115429746583280943890188029227669788614986056318825797041482189685920834253378958370006347565609320222176974991924753600658153514244660657255122224708,38124750578737274821917753227232162791003089617481557231259566762030985520934492451354616032457170217275564281951330766101660738724598191687885679545346283525262542724874642642872748420737930473130307644519437933305026842012536784886496944579276550709211116316390318564020889816097235068462785319614865578597,130062522389522343683740057432381314776477134408262105090740417520527750971142246152091337403925616258740469387086918783120971977871460574454924803144389152275224257452330149332865693355986252454785361887191345579925263888502541640915087986171712168495464223258466766753612088491549102305993177855419426172515
|
||||
10012949731508230844521554364973074187572984168621445800774150709798807735949381704091845966274845524513566631062798752350499554699759712145607818652191568463373664709797900265336143905874117568859521742454341137224521191983729963831041097053387797083787709902762145306866562987693831491238763225325353128845,-7151999616242866495807184767334673387014110620932054515899434747323053830494035687486485101495361247552977403879925385683437335608704813457204456533123612810231681288244199329093278043176840326889166441056953674708680650112341950599518566211501622893081961748190383051196092405691509055911825933224776999729,728959856841002416924230811929428724002543698647639902715200337469187398607311841753203087774058534727465005007422722827247541795373827101651083024979629054119806748202357685733330535940416577507509240075110229140018035405816024445205831928017961602089222683008780078758377712656395593651285944681456109357272|78605684766061357400507779695495682929810684632437884872357120089392494231881706222602069457907886449103098011256954019318391632581377073457287658351584831830230683661446071913790640516272177525020187886119102997352695696049059080937602038841787771510139456284931095360062636771451048097974369276252684666749,12001075534855282519055781006726767731199194746822836204491410167536180166431388377323739159072959927587441133024108242424202303987846968293631866746295774320809136575432861690259530718674237632206265488487198601880322884976030897140623633254152458705315742157972429278484090634288310049511931491105240527901,93151749819352486101012886560489221249552002889236789406862251708880381277922290057447780576080950571200028266859881169907512608303652032886801146810143008245384785580165444902988038417617761865310968792125862316413739796643982228185896004498606219961899388723793207292461251691711779811000343374670531988570|95620961524949716684140097524982794699249535271050516669544121744125934159117898820120095869213277316814159636331359612088008309956314498753337898007810553303289522178449103493384329227781778413500531168007453332099452587335790687068580171335323542117871903087433014777736086345342400718427907876478857651725,93982690612240904950679627999951286744516720026289165825378439518867065181987722717690665329424786689958612327347934970490613914683496125042910877240489318265091859294188434182919729530207613831730142844292090902152344156800509267822168626995816691703927249712872762026654985358484494213663737589506902782009,99292425117587212531473852181491241954331600716435740239461638370783102438068248269577051049726048567729703659744591520045688390816935889052570162756642088994924462717034854539966002991020871080627249804440896263676225604896518999268622239261793212314602300584784534836058487675621509713476733501463323785340
|
||||
10013285697697981291514875192049827757071760177573323421009966878146856227693938310986650067592898605619488251263628358029535725840627847357496217367653253065239804661689467675594407401100934372130923704422822224913415836705341468552018728686468194407664564227575182128302559705354560745061529474614082985076,6561642167054255252332139226189226301150630422474494620863616714017817447379372804603010573956570809208555270847201719676149529315047658055027624866235618098171962008631941847341271231615706090718182990766223922159167490454724094386151343698580819149354278973243680974477529170554988807127882542455236037061,528470097447394031501467541165507900676972213983504375431777006857690508074506764381712795328953309294516807977445847891975262681647237636757123951794958241571326610288116591734368211279530252114133992576937361883752806300690109922381969083425358175983601420535008716582685323406262131690670391327047692590496|10013285697697981291514875192049827757071760177573323421009966878146856227693938310986650067592898605619488251263628358029535725840627847357496217367653253065239804661689467675594407401100934372130923704422822224913415836705341468552018728686468194407664564227575182128302559705354560745061529474614082985076,6561642167054255252332139226189226301150630422474494620863616714017817447379372804603010573956570809208555270847201719676149529315047658055027624866235618098171962008631941847341271231615706090718182990766223922159167490454724094386151343698580819149354278973243680974477529170554988807127882542455236037061,528470097447394031501467541165507900676972213983504375431777006857690508074506764381712795328953309294516807977445847891975262681647237636757123951794958241571326610288116591734368211279530252114133992576937361883752806300690109922381969083425358175983601420535008716582685323406262131690670391327047692590496|34436981724331071994857876336695803178232447897168183469251879445354282383737983320261577504714614276116113259188008664067129808039959751651485877586471601565784430914037035998508212337945584341667506911125463475285113792006322617814372685212577273915390962094210529917778766692621996665878783549527139893242,32421657027122874777191628085590775058881834171831914535958291812982208823927027425208685420460283486647223529499620732980942837410329269106357656112224843439688604221190662744374320594231296457180058248568608247918397639378809724702503728912863511608290047988244839274296444657984762607288102260430546556327,160982437047557923662754621724904101004108273738876884592163845288132647289990060919034667221490978793506721749816537966400403944327808168366534024580437483775879522831741601830069730429889808208871000895202628107312664119771131677027106136972021612902580949354880064038858290748071858588504931122717671875719
|
||||
10013409568078797146570807857755720961248912529367151061974511181033586582464029378963193763825696350496154303179345126636835517120186897096948192379786846194127995559270109497428813513500508574813803534331316886434340387606885978254975074973425350503976585044856706375756665039166645930515210729176181994797,6863076338634175024934436723026392698236823689304369693969685928390616820215350991816780229964708018996782742906430454861638727991380590099557403163016242141034822837520016392592164770889783961757225608245037212056737255646000577024303400659319142788815209178052443133447533618473993771130005829940742472843,518144219445747450843112374880923475954988909716176430338161904285754222207619744119028881545602958596524518340559183715691125114950676034953086100367357569860971147170398898521979791627387469550508096062409978585338647803044577182942437027156401628087522267601972713267759073787404132654921721043098478369296|10013409568078797146570807857755720961248912529367151061974511181033586582464029378963193763825696350496154303179345126636835517120186897096948192379786846194127995559270109497428813513500508574813803534331316886434340387606885978254975074973425350503976585044856706375756665039166645930515210729176181994797,6863076338634175024934436723026392698236823689304369693969685928390616820215350991816780229964708018996782742906430454861638727991380590099557403163016242141034822837520016392592164770889783961757225608245037212056737255646000577024303400659319142788815209178052443133447533618473993771130005829940742472843,518144219445747450843112374880923475954988909716176430338161904285754222207619744119028881545602958596524518340559183715691125114950676034953086100367357569860971147170398898521979791627387469550508096062409978585338647803044577182942437027156401628087522267601972713267759073787404132654921721043098478369296|29934292569471815703363755226997845073545738667501237803957680847283080542129475423696483417806010171923751057450372494361758724728289501602492090448848706266885172109480272010048281849170055027096272553904872380723830007840644079815126735090510221286243662888112310922242506575820245103502418648518037684112,-21627427564859692871607980544502391995135725746472152647532172629071699503752589147589008201502208786678594136605740253912219755939688067145589663222363251747851181456245722891111913772396992196602024806546104102083185098682262204868868794139167512528524369543939531083241005579818092881356982615423576691605,176839029147532789455522785442738478049409371224700882039503756023790320876676330359714505430586793397649436855899139335082011213013721973064579158662211626800445041202290699798718862085318933995294002499387627536860514923891246937832235709964008507131234282169012371627871115559920941075179401745449676837538
|
||||
10013439159433989368964725373563382887574891949489700677050044742848904863973460805304293375442411192907083507310299969395983146408589524560833202656559624127327840001867965274370013167539210363322627273718141213894086509619780941576547772641539573210833142422223317097724915074066448586076045470572140906640,8310509330265721057433243761087295977033094222529694041792873186617167079529403730551603568975196878825930300295178836012162497002423788954615523897720318575793014458944774857654309162161287534450951840479782552544416928129945375223479302487034431413802055998746646446418560576461091628250104710978988283711,729371463016273963110544177662324936807730201765611306002068268068668637824971025044896789932884019488152669624502699796991126775679816762002628560217169359562928488795097209366461843162752726085374841269043547767926070040941464791696126630730708190840765048657149163857767697743125679328771823496672841634424|53070231924347082568804835060631378289496498123832644772276016787246416299549861270518581840230464146779761127524498364504195386387182521904349896158340177993161553682765729098600652803891496382298875979768509788803608935382898072295003870146958848103249920622300892108001270267505518700281027764636096833740,-10417045904363157434661773205739749791733323923523249180794936274249482583161962687848890485454386657190132561052636607343240275768181642068289523597327390757351630390400726183726689859598985450769013120294233573698641240921187000189001584616004996169093549349734180954432033587699679729849675222478884233311,137805678896928752296520072917407826444192224958002583188528402832110905130383122933446618731410797305667977506853537200263986333845054038041545138300862253525372279908216585177453144947870717454801757363277754721032068341587435554423804921498405475740879440309992782986462772299747827377706986933475774033684|56482649708459145913698445611252485312060512622120077359133908474066254680736347932747096146010188731146496181655662751016088725094095969432429720148408144169456178462601187248728823790080612841522193324466093276526908124707660336237710411213793152471895601301243018110500181075901054216803639852864737028850,49500528206529841911957152384541310290857923328806104231198472543790151686945922117895513040239668591093558926952515368216015961042415506812499837082111798870583213244606704215667322437109994138978691823955863634369767001231824513186587618556524171225612093890634215231765102523588484540352521700864775908391,139845177982276960575270039101197150993163035851524438788484301872591911839811648314287998492505051870128263318114638169162126726205946284015475459749582002542133038527256092765477445685371965587948783428628744556595668607565825917211361759008178572918967281201176709071648799305995083323084664578756735938622
|
||||
100137176306265990029733961444031383061223366889811053704411233166327830634077756142922727010656909223245031237249254709133350667800868491437148280477941194204587700926281351055456250199609042270725753605165960788792303060065875576152280599302149022622498012279559937562935558359151996671916418735428920407874,97779166460841276445850871197751897473918068054418745266060401791237288238653436085640513289818870139139618919771865928628062692360137571273452019987828179736062700190532592747648476510214800565987627353502647292543809222510700867942163153624606570877663088964161374448935565221244874684751958995844140920147,102256681515788126438883260779614224655986266663397201843001234522477597459794964756711032437403434184534404583233460968937962164574558546102488980641209149336930446800149993628815025349402768080588150480797996340762754608056907877670259116917971852689279794852877026737551375891068290636218096081379871615065|100137176306265990029733961444031383061223366889811053704411233166327830634077756142922727010656909223245031237249254709133350667800868491437148280477941194204587700926281351055456250199609042270725753605165960788792303060065875576152280599302149022622498012279559937562935558359151996671916418735428920407874,97779166460841276445850871197751897473918068054418745266060401791237288238653436085640513289818870139139618919771865928628062692360137571273452019987828179736062700190532592747648476510214800565987627353502647292543809222510700867942163153624606570877663088964161374448935565221244874684751958995844140920147,102256681515788126438883260779614224655986266663397201843001234522477597459794964756711032437403434184534404583233460968937962164574558546102488980641209149336930446800149993628815025349402768080588150480797996340762754608056907877670259116917971852689279794852877026737551375891068290636218096081379871615065|90230316563580194408667213300439360765549943827123723976699582813489678898952655680387614045807099591452452020884059027873359796950334151880947386773848115789736943898016681027189561282963394481712553688761042044178529870890932063063291912576811880180339151930033798900788177324802354824840693823677567948727,-51250096968515553727207440971544562384114008768089106206247467547899665759345213630706768471270630937078525436219387041016063211534659780348494492859921683763678230787094584046438254568966852960609578580031708027705688875405694260795850267621602038107210044773776590144869507841095128986805399917716889737097,94271497992835932562874103278757400032116756041765039747726332995183554964390204442288393334665236335700063020174534799860251424117225874828741908247259400897208844068836969114844343301370484015148786737029807531127609578040269356203181806490127049090765570457173053771731322678344641402857532580837050951380
|
||||
1001395889265586485395767421092943095772484906688205160639025138850588355434167443569518670890639224060287615982046173119211466447418875356487968111638376610456681184419174307282534045999642719677458693603373061246804412063778941537663208494251233702824916937867260454282227810431834716831538058300952240529,60445540632407873888807630431208524230030823670563578058253542014522089940657440267941912297376844686920437735513309169811551129412183931683096248710036617268265519243947751270645191479229689326385715524956466565650374324873653293511970021452999675894489762841364719216977754928108945414058693987652866277,5401452543992462314517473547060846830682300053665170002473827326781788915141651047957910827411217522592705590143110487190395657380723574363184777022159851917393607961064987992588915644654812213550360705959643031621136573608890274219923270810168453305278905475435769643968988593393956330128341342800859836282482|1001395889265586485395767421092943095772484906688205160639025138850588355434167443569518670890639224060287615982046173119211466447418875356487968111638376610456681184419174307282534045999642719677458693603373061246804412063778941537663208494251233702824916937867260454282227810431834716831538058300952240529,60445540632407873888807630431208524230030823670563578058253542014522089940657440267941912297376844686920437735513309169811551129412183931683096248710036617268265519243947751270645191479229689326385715524956466565650374324873653293511970021452999675894489762841364719216977754928108945414058693987652866277,5401452543992462314517473547060846830682300053665170002473827326781788915141651047957910827411217522592705590143110487190395657380723574363184777022159851917393607961064987992588915644654812213550360705959643031621136573608890274219923270810168453305278905475435769643968988593393956330128341342800859836282482|43569972642791160005757596858255828258440677425601503825448806514649923603624018287716685991744061240705340542732331922577472226472918231509238166036331218027449035406029770845535194662631393899654058445399116462950394778843477054303490660149914576382156352231393154632904722395547296167018467287872528029256,-25416175075838450919641769013264410597729745958193362136948110865397498509541978552163608664910111097484344111265508414674502206468095426484449495661952091027512836383946952942259134571474962916748153155124469369237399224386694894533985438381306408742628779331072259662078374717232763484127547679303302310423,127851513581210146707222534812462714415549658228702116548129323569875687997527570139914376876955894345964691178029394628745573178902316765592327648023513178993717765546280790932769863585265709550819660882599525799584893587529991012504312937097442098858522399473806578431530443021404617174701716319817659510588
|
||||
10014457466865501413264699180995213607651643403581155351850240885586127254516466035686557278805989563280873217997386135507560429328380625332058111008767730524810617486297285562994007263758369576890950982876431843971907525378186076190945281470031905336296565482376151661355756246367703162199805483942789509516,-9493045169000225624825724585241654877107258957466554573322941788423005986836702078635071088783742277452705183557515581054220105186163500969879785143181676844657120253295906990349839818041129525896218008774011956975336293108128480236859770511279248182237458109627660116415432972887068943678814730002774447323,568058498128347562017983106577404112679290790118077765226872096344304166614495246835964393367142362074124393647429278191341969083397190437238809441291521483431836555168421336650034272837791888742028164348356631901893675815620388348481938896223555723594783353067563133868242273893775394833482067029611721906579|10014457466865501413264699180995213607651643403581155351850240885586127254516466035686557278805989563280873217997386135507560429328380625332058111008767730524810617486297285562994007263758369576890950982876431843971907525378186076190945281470031905336296565482376151661355756246367703162199805483942789509516,-9493045169000225624825724585241654877107258957466554573322941788423005986836702078635071088783742277452705183557515581054220105186163500969879785143181676844657120253295906990349839818041129525896218008774011956975336293108128480236859770511279248182237458109627660116415432972887068943678814730002774447323,568058498128347562017983106577404112679290790118077765226872096344304166614495246835964393367142362074124393647429278191341969083397190437238809441291521483431836555168421336650034272837791888742028164348356631901893675815620388348481938896223555723594783353067563133868242273893775394833482067029611721906579|53924208564494923109968517258991384333718615783597634502228353963509962336751805354923463494565719411128406689879296751392427452179492575502279868846589843663305526485431433798862642111241114809566645178986499564696116126963309686958809916838000470566457881788520159467305886335238376585070031885019107861839,-39165088112891919485404645022206551911392044983195122526582505244941571614658605614311191813725723193620640489676510478992438060577861340792571425647895723271516089195795031639152263494946222662918005100610385322895768473350699779206361702599565733658715228168714169147264299885332019593127372341848528310877,112189763824528641217468278574322392988954546777239131658850758660466358827365295080995339889134329849615042048060538504294364321483596732194229239161149447040110980960983657967678809117682823152517826486688609621632734218254085881353576474560418869461310902870862203604502294697766172436420730459846253285376
|
||||
10014524612435081655051402581388141399758826121078479680077428037590919760198044078469208114625992172565561472610137633731570114446039320551421576820201144498480274752068507237188168464666743295560743051180514619150806895664325776982239371917265280309982409950396003685063877356037007592827997650696359708648,-1151946584820929060448198375444913319887694243637725495546164532401952339142382368891700429417009398962503441132652463153588614606824550308747271936296460648801898782148675402610858915130433609314541230955826121143276189468724039832396682232064702428868374548095200287491142543410829209121388657552507539861,755148183880958266120452185655234110618667867205538459331580575221728013160051641776310146717168795492323023035012567121444609095123943446710618919745199683082156201032014589922592096239933647413759449971964484414757026090967529868635390069577397530636511831668757182454799405458183267048363982001659170207347|10014524612435081655051402581388141399758826121078479680077428037590919760198044078469208114625992172565561472610137633731570114446039320551421576820201144498480274752068507237188168464666743295560743051180514619150806895664325776982239371917265280309982409950396003685063877356037007592827997650696359708648,-1151946584820929060448198375444913319887694243637725495546164532401952339142382368891700429417009398962503441132652463153588614606824550308747271936296460648801898782148675402610858915130433609314541230955826121143276189468724039832396682232064702428868374548095200287491142543410829209121388657552507539861,755148183880958266120452185655234110618667867205538459331580575221728013160051641776310146717168795492323023035012567121444609095123943446710618919745199683082156201032014589922592096239933647413759449971964484414757026090967529868635390069577397530636511831668757182454799405458183267048363982001659170207347|46183360432532901454553912811649590320395866004347241196844991991079215314437275037790647677890495653136878666779844887628869070006778207117633836660092513861015319661569732287838772799418674107359979430356246346034550280154482402202513605341927486676571446547869725605869822695502032982833841088921112910317,-14839171560103132001614843311520281027921489422034665235320812512225719145369465447283012912841921017696170329655940078247191555778130550993274994429848671209676820244675419866031667103832358269654123112505016252317575238332509399397558348115029597533711563469431946692326093523953990323828622920869190596305,164933181779897671999712222932130083401866004577771560343160060853528269308468525452931360567865498324819919495168385048274257865546801611749112060417208336526645794766502287072279593583106527746581118239327199774476900334621937982627978739872164479446504941326886004356233761306601172587310954186017120057146
|
||||
10015153163121593836478079113660124757348318592530821165639828390191159358973882062973457665510869038410016978521906069415643885467466803613263638452835291035274253082105374798431579187029855868716866951698965254377198199868261126247017409456764474165861037253182443325274363795830109568972878953062238823520,2382294090568001333199894323474279123934374114667847405540440750564854209907703388935432920732110218963078674073256448624811505546395497000378710736855311825351193195350046490926404354706980500837042629648272073851723169837427468358824989832884534921916167168920876623159906890551519514875606250679556403973,773658465692173962483130527303229646901934499596511207834787839028928145069426505005504820136922810366817841934360207193839133022641619097494932108724559232945611195348726835877676174729010759098808115181632361389730445448407363060843805088069390583778242530477288002693827656348092952397617162960252636436602|10015153163121593836478079113660124757348318592530821165639828390191159358973882062973457665510869038410016978521906069415643885467466803613263638452835291035274253082105374798431579187029855868716866951698965254377198199868261126247017409456764474165861037253182443325274363795830109568972878953062238823520,2382294090568001333199894323474279123934374114667847405540440750564854209907703388935432920732110218963078674073256448624811505546395497000378710736855311825351193195350046490926404354706980500837042629648272073851723169837427468358824989832884534921916167168920876623159906890551519514875606250679556403973,773658465692173962483130527303229646901934499596511207834787839028928145069426505005504820136922810366817841934360207193839133022641619097494932108724559232945611195348726835877676174729010759098808115181632361389730445448407363060843805088069390583778242530477288002693827656348092952397617162960252636436602|2334289880943001376407857326996263570161383789108737840675851906077977981768540714248105544895055900962482225672861273136265466132609608331964249615854131927898907957201650301595252550620756829520427054784019840985991520693282395588941752214974743008251596421642708049368885083348322205731564243670420111453,1451720076983591598762998723081545117923198868478265830640664361188690301293679623937617406037087334975387230852094993435248087727723628228521184122895045650428549727009619829664472593953602490826316016345941727517760259061554173070969494032097919619747777129170826368624036489935713881661043471800066640125,3318960568956834644312274599956969298741234864897695465866703354170475923995521916039531437101483638236150279927673715871252637092748519401149230098061946550109095773979423194478592673363716301124276065026975130628863523060647342416992862735921072287765667600233548851774826575592417995450427441845506696081388
|
||||
10015239581157875832393535763226085031936027674008799231064578015529654192320817181717861924169857992310709531421935508097069554814977182072669044193680614850544453265357095259368437732015348877933787885875170804438256215681419620514332393733243248548151757671725579685427667920968624432291421418590675885300,5094068907677575740286879080674249533942090145311835759008798415694966420126408035500684853222542571817165748053609110326610732625612063208376418866488998532875479258993000620044826461966140228426897339103003926919606128736757098245146058573375685873266553963971816210554103991392539430164989850926128708273,793368698167290739626939845245925598679004619304386735598558585912760256279890735283141314660505981777266664338091862952502183635644778863932176282239208069911448671090051312086285039683208751050938084831532228722294544316547609430035555984901118374565436615559075980852757981922632778527357570396074193505873|10015239581157875832393535763226085031936027674008799231064578015529654192320817181717861924169857992310709531421935508097069554814977182072669044193680614850544453265357095259368437732015348877933787885875170804438256215681419620514332393733243248548151757671725579685427667920968624432291421418590675885300,5094068907677575740286879080674249533942090145311835759008798415694966420126408035500684853222542571817165748053609110326610732625612063208376418866488998532875479258993000620044826461966140228426897339103003926919606128736757098245146058573375685873266553963971816210554103991392539430164989850926128708273,793368698167290739626939845245925598679004619304386735598558585912760256279890735283141314660505981777266664338091862952502183635644778863932176282239208069911448671090051312086285039683208751050938084831532228722294544316547609430035555984901118374565436615559075980852757981922632778527357570396074193505873|54841829397576178848410586601034860596951681568779361478370108261032921497569280442168530570346157404440784855573637229833444102498053726559151577392605738325853410653119896676062193149054976747541732412004218217068288550127184839213667255982218678702854737220904918059908451831872125006158411607941690397052,-13987639594862577439517093919564754940146287009709146462369986810150221519296281298521622497304190878362220137401179604871651085725669668566995040192751337189374220954170616856835063054456944563624013156491483611079953326833211481288513306777121436082074004700443915242579221138749893848640705537321387708809,145658957896464652977038505022308448361415349923894631554394890309500215673949920864830014124570888235622920757378372327525946059952077895236293799705256119864823158645268515234330467061529263252614881624406296566043408419602845128600163566622927193489899129202143975708704672075445501568437520798105023647844
|
||||
10016254093062341091793169016069728267098466973354611327776341296362926980734885768145505535610323176943330336454162903286601650062616238131379152236760546371204482195908361542328829078490793642835057146484428739306586521325328236448343779367153378279828280298660045704810418678221790320328995853516877961219,5290291792844776128036538578818355234036731339837804827682257620535756451822532868533550409363458436730292692155637706486234356872153487706954079157252741244973963860424508734267445638531496348565715559236158994920739250737957339663944820624379832490664101888239401802029497939684558696213321821587965089165,649562196414599732260624464563141423074514382020176141033151990702926870363780837252385965871530682720560442789827097838322398249975199460284454895932864056555126156062190575895999061116214790474483579500239339070750293285631666586984632253828693474154470829221739655058926181416125562534958534381263761974132|10016254093062341091793169016069728267098466973354611327776341296362926980734885768145505535610323176943330336454162903286601650062616238131379152236760546371204482195908361542328829078490793642835057146484428739306586521325328236448343779367153378279828280298660045704810418678221790320328995853516877961219,5290291792844776128036538578818355234036731339837804827682257620535756451822532868533550409363458436730292692155637706486234356872153487706954079157252741244973963860424508734267445638531496348565715559236158994920739250737957339663944820624379832490664101888239401802029497939684558696213321821587965089165,649562196414599732260624464563141423074514382020176141033151990702926870363780837252385965871530682720560442789827097838322398249975199460284454895932864056555126156062190575895999061116214790474483579500239339070750293285631666586984632253828693474154470829221739655058926181416125562534958534381263761974132|4371923964825216081284965901486251829658920327478160330494959761785570498729926171763697403539994609514035386549444286899305836316283570402957212167175599769519526858160920653621106184279087086218630872059466833612874880235324503114394586087353649281136173057014948419793113247251617601913225740371158264594,-1777711233855585326424402788112018092969733488690398670027508570423282261674718543600694888501454195345939794788269076453964223553057248156896791027286117126036185606587718958830247368692129308590218482424190086311842595428742140075700660885589198113766412954745249944832418277914084817045523687626938171785,1486753504481531714235052666066139608869409848938074431937349188798515713076253106271449862728854109674272536360912828894345019832890057397353770574425655506024994198304163182702822689738838001321557096641997078734385067590564038418788081682782254559978113888414124552326849527747130706995014118004294289090507
|
||||
100168933817004159727571823870862212374515071383247163682233493029515956409883385367746187285740348786673303354766599662884032925310153869913659930858915269690815416234679514078167380783771768659750083394948158950008326340270387586985723448583932705818464704601214600293828130344813737095058092807371622380596,94832715670637342331954204053963565603302480280224254821703778448479787031215111088413069986664424694762700821340882966261664606716747356784210807087846121536668261049472463334524682357378613143974178468771819549191894308095591279746614292380149290609465170348542192697415722868093623009037253233869856957249,102860441967964242444445722269341757702905607863364253263839843561869841563005656247302036622183568251273499262767768690361280263007610763737074443848261770701568579600837276156244861738658629562432640564576786387713071777708265072467592751700403901387393831303255944800743982818455033707731784929932463764787|100168933817004159727571823870862212374515071383247163682233493029515956409883385367746187285740348786673303354766599662884032925310153869913659930858915269690815416234679514078167380783771768659750083394948158950008326340270387586985723448583932705818464704601214600293828130344813737095058092807371622380596,94832715670637342331954204053963565603302480280224254821703778448479787031215111088413069986664424694762700821340882966261664606716747356784210807087846121536668261049472463334524682357378613143974178468771819549191894308095591279746614292380149290609465170348542192697415722868093623009037253233869856957249,102860441967964242444445722269341757702905607863364253263839843561869841563005656247302036622183568251273499262767768690361280263007610763737074443848261770701568579600837276156244861738658629562432640564576786387713071777708265072467592751700403901387393831303255944800743982818455033707731784929932463764787|77074101972769923370658023573461029047908280864501436531886214070884695444419790476920141159581106162534554398040667029684395317753749995140975694643351101153246406361333865778019332847126758508398386399309944270422140994351224794089223904030644354844471144608782627152160492615030406249102513998568586126653,41985809674026851301068939458342266766093613320697544468890621111459064094913132603897896518617407840492037076180430740254366932298578105226006922522339189157081422030305375009727018508446301230399756872145212262654632874007091596766171377732560260349745066521408866260391195589212337788533541057115385883425,110229138576369926974358954548772667512560757802376313780826844717365768043167923353943051327604684088175403151021231033281660580097059744410859188703138886987578267563448651782227630417696079180690392826925010189611494463744920925421564075513181916017454497019126236913116432477001913262238126225201422341436
|
||||
10016905787587129103970068378589209223718079791180726370802218768976971488497998963132244508629494308529380628538141221743580243393344335649567002150936320257090927900467530902572471077942584896593451110546304416815718151825873142786318484895510554032583903064792109176935301749381314577344473149515437073560,-4606191417439560848418163571752652850846391635765859587403508494460979835111500495993727812816590518091323150783186546267331220869638878833615969103418728210432746474134652280483753966001415196686238333974286033749286862708642243562674370580850529480084335445537434013760930078201975018692661527689582576651,605629172398620500162437997408160351967898827176789386195142449064206069917749164747262079121234714184955198496120255981525746584380916729025666697652941726995464456228081635615903549843932017595245592861355354651584306759089064045480854767640497444940703279199283744488071666641763271403206424800946819221209|10016905787587129103970068378589209223718079791180726370802218768976971488497998963132244508629494308529380628538141221743580243393344335649567002150936320257090927900467530902572471077942584896593451110546304416815718151825873142786318484895510554032583903064792109176935301749381314577344473149515437073560,-4606191417439560848418163571752652850846391635765859587403508494460979835111500495993727812816590518091323150783186546267331220869638878833615969103418728210432746474134652280483753966001415196686238333974286033749286862708642243562674370580850529480084335445537434013760930078201975018692661527689582576651,605629172398620500162437997408160351967898827176789386195142449064206069917749164747262079121234714184955198496120255981525746584380916729025666697652941726995464456228081635615903549843932017595245592861355354651584306759089064045480854767640497444940703279199283744488071666641763271403206424800946819221209|46304687373394436931218438666336335256163483212484332920442711829320278593351077938042811198542492407186729960199059393629663370119443451307712349370714705707036441431251782566272288509732854919564985572759872505231639307883389746522852343879592729064407291688011480357040596643477509242715875322162180945750,-27559962602683142671407402152656684625711978340483108455301920226275039655520624691717381412007576185077377268485337641259513780832297300630514833099989822452624240349981167585374487019267119021970798715861631920467292530317231419988216997273247875678528676583110608263771292353047679830100015076536212572871,134999594026951253395775325545499481323026670784912424362786946325493588697203309584859459643146426717172468824814166286260797091069281816967149658244654968987888219904891951992996909324931101736714925044299968419433398393443198400917682271553527341988170608553689440600718627726318712053029382276372293927321
|
||||
10018204832407485307717168433283551951171211565712475881182623460525924044598415564148247583748572210844295784844361310074903318189804960966908772513031346031383059069976302114174587533940128565286800673190990221782901119861314311455679210523773394109738879256410739142961640761546729001001316019848803176862,5319904375533742100925641023534751951391638893478820023967035481652261436239987131193126434052892185984232529181792190920674907331089418651303709226767934571557921846173913244300134187483219524696758678859856206200663423378880336983240402046185791279466371047694436246549133924131892629303395892591776395187,649443554629399472805877307531888884997294549224205118199170867300682218925831813905978113513120968194233947187441042861450829488125193696091497608405966874500722600331516590109468259720034716473854550338705028445661682847162605116427138852824514186119049574433700978648124399292078009263486664308050317605762|10018204832407485307717168433283551951171211565712475881182623460525924044598415564148247583748572210844295784844361310074903318189804960966908772513031346031383059069976302114174587533940128565286800673190990221782901119861314311455679210523773394109738879256410739142961640761546729001001316019848803176862,5319904375533742100925641023534751951391638893478820023967035481652261436239987131193126434052892185984232529181792190920674907331089418651303709226767934571557921846173913244300134187483219524696758678859856206200663423378880336983240402046185791279466371047694436246549133924131892629303395892591776395187,649443554629399472805877307531888884997294549224205118199170867300682218925831813905978113513120968194233947187441042861450829488125193696091497608405966874500722600331516590109468259720034716473854550338705028445661682847162605116427138852824514186119049574433700978648124399292078009263486664308050317605762|2096824613311195474736703091933491927179118439681576075463684305365113996801091784928235546455105051723066941197368294736517297176841884535935805063900042702255946184765201041823632273617760317603104813509978347996857764943233871467178918416729927262302333533232369242879390413535385046393166248041635195052,106494743809548339750384465880660679449902990323530191499768868050880389213560457433755933556230921885636912867886887645004590062925256300108980851523487384554584007694663026566980186001150284697993766392145530903618307059918756399086400576557720952521322359177695970013138988731324890614696675530003172189,3099537274480186341907264372921810635861168363663532429504499040028118656288725100184032700559268063816635775634703345843577214400172811320277070043994325333354476328328682954931303645039746659585813529747367061450073478508564524387846459195219414272058883943010351216728564728313947382708438971484753032540491
|
||||
10018324718324265352080889354041349230495045650756363847859249064826167700621077306379636998633382620068424485758426219639651755498284131150741688356919555549109464768469845299901089390604198312107185124929799165529332689261450442020302769382765032211061987664530506790585428478002180255625233322864976647458,-1506556466689461719964363510118987647616549995746954868616471745983245113792074110437071688516535364802439931589935160320446594866789971924891832800418288544496229576060497571654938278590804451001178571222736016531030712235951293438712713277945256316492298818368402112911658258565046390998975710669014707937,708633648140842422465025989226402132551754445128385378651747216241166649232185357696677838986015643979480257385865744447602978939236447538983280973796461564754777224324765925807967303202117722154439166886733422154436177593473337680099402130518111476687602398807958385973240844776043934886139211712396905414373|10018324718324265352080889354041349230495045650756363847859249064826167700621077306379636998633382620068424485758426219639651755498284131150741688356919555549109464768469845299901089390604198312107185124929799165529332689261450442020302769382765032211061987664530506790585428478002180255625233322864976647458,-1506556466689461719964363510118987647616549995746954868616471745983245113792074110437071688516535364802439931589935160320446594866789971924891832800418288544496229576060497571654938278590804451001178571222736016531030712235951293438712713277945256316492298818368402112911658258565046390998975710669014707937,708633648140842422465025989226402132551754445128385378651747216241166649232185357696677838986015643979480257385865744447602978939236447538983280973796461564754777224324765925807967303202117722154439166886733422154436177593473337680099402130518111476687602398807958385973240844776043934886139211712396905414373|27695493339474189059880649994786373673681195258723034498967136263221174895242876882887946040754182923842018399590448977999734476968405279409965275664350294423197625592498762797252651752487096596479518881899735472134497736489815871889587384160668070191112126826489102305651218385469424433736996571142100268141,4244952032054732923978416579691917713463067102733490131769022354718180777349838220573662792933493750823939044158056520471214587505994364897599832929831064732609354344151098280452640031958247121275726298011899146169585223669027857229201360814944532694404419990370729211245101258947186079227140704211123597077,256477087542010205875387979681474864287758986482727894664413009819175948644274490742191718780565989800083756066810584023109412061717270312386676508030363737098913494555400729954736934622756650518307368707185355806725304278546342578972238562139946071381611959969612417306120634997866733933066171286156441897864
|
||||
100183725937805337440102832154923451468884088040067509735031176134138272029603097931029532527171620687937178427853408917605171373483732022096443082050272616813579999826937201905718430121138104894761796713162794983612090638008542903172271321979734531328047767185223183894705715872373581190063338544430105324944,97967360545064065581782092795782542381718050317435898718948431525445051912029574864522929506831468927036372238440312318277489221772379035158891587900186742286147138092170859279721424649522055176445825889170777870731814816272149484567390197282747308726861433765864290861778135213069453090668850681241158130141,102026058802637364547431940124628332383045736950389197653455431566764985503089749509318465184383586821649550424369391712983254618997917250229615538329822378126555642981029789087346297188093481472570239624171949132198549570384613605722016512646835562730355439782372504448945801732597394795504733391497603335093|100183725937805337440102832154923451468884088040067509735031176134138272029603097931029532527171620687937178427853408917605171373483732022096443082050272616813579999826937201905718430121138104894761796713162794983612090638008542903172271321979734531328047767185223183894705715872373581190063338544430105324944,97967360545064065581782092795782542381718050317435898718948431525445051912029574864522929506831468927036372238440312318277489221772379035158891587900186742286147138092170859279721424649522055176445825889170777870731814816272149484567390197282747308726861433765864290861778135213069453090668850681241158130141,102026058802637364547431940124628332383045736950389197653455431566764985503089749509318465184383586821649550424369391712983254618997917250229615538329822378126555642981029789087346297188093481472570239624171949132198549570384613605722016512646835562730355439782372504448945801732597394795504733391497603335093|88007552516538570862938195555687347843271125145294862509637863339852312849461683699513427251868777755449793173646890377883712394792262777503483942996934326765981582162423696391672000556247247431253370862284402004050248548817767631668543644528300726312835546938100615886799945875203418182610947796762957426066,46229538931090505519067196461411597385016117678710797853895441617844339335997518932818211184588127766146461427860967017470462043930326616555616035492326025837765159149630918451827844844437116744925433303753825438769925710637787423788344940219740545569047456022116580673560308925831201666938083175493702647671,94949150488319392606413346466333119512866765599276437121309157049458742789511630485348500087618567561361017601972082423173906361345987933875129792711583865107081204947273992176380167405635064486260061816002217859656028475745573246943400761862339441042416462774614661346152692808807449954694367626488600259377
|
||||
10018622993047838712433185410421446815061984959152870777572656734193435222251946970691795794836467121595552277401220487788714277091933394850502637162917792769686767139849624312881217655116086523917779102305498425044983500792458780789534783880422443059521517950075233845690825129430658238084704480639376209109,-5642888291743578132708587871691433542854601085995709323535797030150736747981212204721414421313379808144339701595994626772514328521365374368168430420450149143091140909885716813202658261033852230689379211692039890782701731228409652608328076923100699005939261407374626950263084881921749869854247192520776393467,584355741641273221932263410866659097943618996328052690659780811632775391934038170008705223727517700749237903184431819452649538607172642783739379843963426355234430525043677403033326216332450474494227299404505243469315575849027861412999876408965870212198057391050926245137105584182883631254668161360450853213630|10018622993047838712433185410421446815061984959152870777572656734193435222251946970691795794836467121595552277401220487788714277091933394850502637162917792769686767139849624312881217655116086523917779102305498425044983500792458780789534783880422443059521517950075233845690825129430658238084704480639376209109,-5642888291743578132708587871691433542854601085995709323535797030150736747981212204721414421313379808144339701595994626772514328521365374368168430420450149143091140909885716813202658261033852230689379211692039890782701731228409652608328076923100699005939261407374626950263084881921749869854247192520776393467,584355741641273221932263410866659097943618996328052690659780811632775391934038170008705223727517700749237903184431819452649538607172642783739379843963426355234430525043677403033326216332450474494227299404505243469315575849027861412999876408965870212198057391050926245137105584182883631254668161360450853213630|24492216963212266409994030118552483730975075727585752220177989563872338705971497453471962798275543072636175655672560120906290569324009187038649563218726182874757477950170840864973817320145411108769238293767323154108926503045123037222803844779103784397763216133236290396907058542243428101056150879809315089176,-17735224044627622852810014209171696937481849587925646605967048837801771413294839162751742330787917315172217980725109761639973896911760524548506285715284414033504356013230406678376141516049028049732948719065205234900025147050216480775931691209693009856949654955944471263615211623003442072374457069595919699233,241918233622395884761827246850514897219165802162342296635123580790888932192977763833922926853355444881644755349323889380463316458550630788255600843973415342916444918642659362862569058232566277775534472941540495721557558697754452057639207696448965752690070221361062821443638513586031328286832012283835743514220
|
||||
10018933732727277902205269315771289076593947560040587959114941078087116999373425488340685401505876624281584630582917353725134238041079746342415896279966203184863826892445916822683268888700587092452305745538315423010290563725863170080340035065039975298577793326244665530455537053974727163555479979119191279926,-2305656050929911594001774361902538333750937712118410383814661797948886130836022054225957304174319742645328482100663492843669952358370802861270894168816436326458990297136526459920949376942432261379981780315229778535749028029896216855337892147060100885167806805043764484945583720350824386167496969085180728505,426903073734578001112620417146509321508736309565051582451873814142074420259405364041324675206078055851221135785335125834745297538613608978468731354815366776968439807098716134814276564770795992539739869501301828055278204465499226602180360134210119244471648153940999928351968352054963731820177407885865927236658|10018933732727277902205269315771289076593947560040587959114941078087116999373425488340685401505876624281584630582917353725134238041079746342415896279966203184863826892445916822683268888700587092452305745538315423010290563725863170080340035065039975298577793326244665530455537053974727163555479979119191279926,-2305656050929911594001774361902538333750937712118410383814661797948886130836022054225957304174319742645328482100663492843669952358370802861270894168816436326458990297136526459920949376942432261379981780315229778535749028029896216855337892147060100885167806805043764484945583720350824386167496969085180728505,426903073734578001112620417146509321508736309565051582451873814142074420259405364041324675206078055851221135785335125834745297538613608978468731354815366776968439807098716134814276564770795992539739869501301828055278204465499226602180360134210119244471648153940999928351968352054963731820177407885865927236658|26579833924289520389972900117950394438805828628221899849785251193277262506904016180015838661767033925903809658684422106275456221210787145479887893793178117616282806012189342470201902133434844784106437109753666637085736679857929223320267986046560553880930252162405414807068330327382869655263308507921578124762,-12071122961357042682227388807856025622183781701383406123339407125622773263556987057807120839167314088703384163940961495607053608272112660158109007999608142815575559883680071225874610842202742230050716632165554413346974345932440553672309803223445371844345386485359912292135145947019769810450457220546043659979,162236250544606905260439724773080091403174351417582646687611423124289071438608418146998192800378143503443566522030518800544598083530735564341780541276153264296511032654040655556029284610154943880012602862804365596003928006715967740792065055405085248350810462900711904458160412653922105321414238780026013533451
|
||||
10018948288270418016780081341685235002997245256040164792426543952818991311558791493453519174957285944783722833865026222848031081817691340856453828555107871396513690880005707344898646359417008593189440903277104626759357903337151059344508962185668959714673026792114793015152022487676173726198202553281736763192,-6995555163054430382942870868581755160069395592106884274460542261252343393118569480209218511916560630596078206970035597385154389463448089846021818488631352733935369530889081823095829009383638648970953617256944401187962256866752201837099775227177656065063350644379695273754386677388279021465213328634933930909,721042528909917874686430575245079781825221838112029624394686069315349560814178350680306853206143047638999149938695007663434153092166743090545673695580676514178586788701941454964134693721185647384090760708127649587795147765724504088383646300322664057264796405575462352962768416720670014119545119956267157763268|33152009177899700335521286237987596749114678289874326434440918518081126413178191723162867529955418655435996482622593235632019894996887430996202492483564865515014035645906573982414795827153656592748272697286574461771116159112804016039989028059075628750439940373451196506327787093378094310321443683918398305578,19078728942670828368834699251746230066071047051172922041653025393624623551743744386999716370764191631344442619983012078124921474009852416209669177199713374821106687471027572426997637428928400364743864020836844501941937756570061589022465875716319591910681201998018650317776190333584438330413688185262916051155,220283868712478416207788658621383280997894846941561822444891957123908778028879195278346553006033805168466857198910274082404942136780954015736899511278911633428569844883635491399257549871333616419819287122510218677255768780334985075712076521491595155945026941146633288297234150638278140903654693829381901681364|86660112777924566325641144753803400410997086305075442702977432289312131972915955256795072094482313726948480079751898750790544713440908592818334342498838917381523558133222779818572943010979268307136948067185583734409642160207725489813897991564467762533071090190022128208402492072833343072675416905847421692846,-52778887618554305290105838041380262564458801465646670949464065301477666757134518520029567230285725793439487930254994645696418125229532386083964770290005616954332222417663293453485136710527439679565903814537080125880293745499032607178356596254426977323351345945596998496291222195474053846483056964155485024969,91256009874012914314189895519654249139544913048606429213352879670217368386794747037392624823085153501261342847050224541672528576684432409807110715865396865727844957353872518329845940826549252426734698443465027159176074936925639415490497467627459134074448093109088470713684894800193345119623601342741289991431
|
||||
10019019997781066559943515640881506642517558843222778169026234770851975313720579259773361086779089551884331113250530982852069738010518159622349375335824689350970737457654843734623714224913981064444982445158390435699719229301999181267314607899665318687660691355693147862987025822541914292231182646321427861873,-3157363997717363888291408594979293600171398541934051160356171159608233287859036491344319963143369936444410446129850053542356863751408144208404845266526711359417425663346085658910109244458752728340593138106611282955961606114280076234921423984338932045399865574815874428373668830300085650219459974701588901291,427660300107522994538791232761616142662131142234945666620460681757069587002421636449099874675218488912225359428713775902235016576565531397345002001166527254555699729200052739867740788272516457497859568251192144704431298212101856469342734690447583085607097591547685515622397916186942279884556709767139560196364|10019019997781066559943515640881506642517558843222778169026234770851975313720579259773361086779089551884331113250530982852069738010518159622349375335824689350970737457654843734623714224913981064444982445158390435699719229301999181267314607899665318687660691355693147862987025822541914292231182646321427861873,-3157363997717363888291408594979293600171398541934051160356171159608233287859036491344319963143369936444410446129850053542356863751408144208404845266526711359417425663346085658910109244458752728340593138106611282955961606114280076234921423984338932045399865574815874428373668830300085650219459974701588901291,427660300107522994538791232761616142662131142234945666620460681757069587002421636449099874675218488912225359428713775902235016576565531397345002001166527254555699729200052739867740788272516457497859568251192144704431298212101856469342734690447583085607097591547685515622397916186942279884556709767139560196364|21550716916645018398165650019236850766796511258117069952017796540701386085912310717417651598467640925140901250417026118119274327376121328459299004640348530767025071918784935281870705231282717494840395458987826494640924389129904911635742804398745940919397702998940021391844339448198369222701583556010313045812,17308540888407999086403450710891722292596558140904996642436794702554735336548386086410226733754785281982433279805336861038046891710619959255360830608311138886000204010857210058502793117398659272632248311839231357476736302883731390652600445524351263663967663494261178750828036606884450644013387538641171794195,202180803355870010447215408817189049345827932931561109501494466474799106708426285256026437292412097802628616665602361337631758401467452446995726703770591794057694222974232570992815439680545736890553211079290478720762205284250715176457370298196341449115424087895906723941555883338741498383975320110297668277534
|
||||
10019269520234431826137367355034420920528860342846780753959912064827599010243316724633755419135436935645907443407020572618899291215095816080730065338555965834485853320180090560809076866724238012634325051855947616588404872824038021038592555404461140712393653058441964129349148722979422040489509372096847725674,4522869991076735362499160116541059903683984737748984347542239263701333187108105456062644949444149453629982469461841568384073346981390834850295332934943879978241839313265925834724485912067878288054867100877621399054735204930899125650232136163964080568519169554901660276496750207252542508193487574803619459009,749663683253588383775532442379228650764046549728574777396900821733935114135159669567652069917832665405176945410288020981482404785970875873582684426212358839598234585501899432885966938532819200647768194074040482435441119436072379143147234400064595949108182133121869311200924895068707591158185629325001898213097|10019269520234431826137367355034420920528860342846780753959912064827599010243316724633755419135436935645907443407020572618899291215095816080730065338555965834485853320180090560809076866724238012634325051855947616588404872824038021038592555404461140712393653058441964129349148722979422040489509372096847725674,4522869991076735362499160116541059903683984737748984347542239263701333187108105456062644949444149453629982469461841568384073346981390834850295332934943879978241839313265925834724485912067878288054867100877621399054735204930899125650232136163964080568519169554901660276496750207252542508193487574803619459009,749663683253588383775532442379228650764046549728574777396900821733935114135159669567652069917832665405176945410288020981482404785970875873582684426212358839598234585501899432885966938532819200647768194074040482435441119436072379143147234400064595949108182133121869311200924895068707591158185629325001898213097|16642018863761441710765797012067927359722077189969631448415362616699814913503672898852374525215334055299068298216385689523710707393718883505223743676435071846547044089283998146628167129062401919282532587286538467437993909697773987546172287165832896898434018866746267084068433592983100742343012553891013967598,4279618085412193426188644638927864595084294097891450444438077735383453062127268915528450003127312343513730070105859170701493137563013978799842440344152818674511355384686181809257130294212609318791976849425989687196701708107582124757707100916931554678238461537620568164241235565012338998887375426548345583339,451300244762011954040540232948856842185637826616664360199909803894796107535366932948228367749161671550552967885565839529658452718412544695138612399812114901538129955756634712380719016039028157710981132001101643596366369267735875381875175432502771795477425963992931644164806539340880034536557519705047322385756
|
||||
10019417926514296392019946929112818021632198703101505458649653394849455829204203329294836960034957633501294764450648155864378373289178486051989714219614702737597295310475376780688730971937576079121199314793519307265245938553456529418922522984552293638273911817508398110317305685502955048568809327523071451646,7901274255200127696618788587659559342110188499337362982289909048078505324309251529636836412429419509644512565320215289593933580545899621400755280134055539493035902983697255734323738954580031486643652880504218537900293807494750583881428021909372888539470375818772560108989429450107579283565673329101511361623,623699550931583586227312516211712634135558043787600676758608115259112248746313728815655527067581286781548781459656217474418345498402764321216306327583412055637930534007526887412883845579485648951016708462255973917762702757210736584322682381497339273737323760137458761222143566171226992185720766268284746949539|33994172292722720621983078916917152805135157553786453695681859425113486805780487896660717595372501233092400041645960826591356846046682770081212496668808601116475820169782887756136359474132767453083956483565660497074117273547864843066209384954581834231890370515327604527171929343867967182910635357940103381259,31993846672125961531384598386820046988679306439927918439126442104342750287165534338581303476671621941233213276321267207968356271919850887377330275696357098758109012385572207725576199219446164534402970313646005215676387512077572153065651471880735849343888575800500099273015977254516159942552263434250458169021,190897440537416564844354648094133803032782149306929915760090455032909782181885170078703110757010607891226613247221902350507051587112666985339761578838390574506735798985627221778883031220656445342689661417080864579978266745285225101384742969161503945655665695989381533846227380883303389726073267640913232240808|46223752318790909370837447383363380695209474743451082994109239582734730617406604327737568722130199854939421799114849872972877989567189718205858628003551407137904188277330292052370440786619825504842930785565096667031645779355485895793277208105594179243179236367866554346063343397949912203277267219196168228342,-11006265064354212636439188801633654461277681721343546696389358983928696946083632218719947786058303199938972841132237674419697191902116627029793522898887023505508883048022803011324802659223889838681052775013756116093960676539648227562055647315361638076266948642978861465645013053193461759019970585499519918551,135510058813836316466595636693848570774859961098724584660465530747418644245153590246150906297996570248784693174475582519076799984652691145697384165112598092893383581702308752699625740019767305915611482144859189733431647333812818245189583002227073705672065057825892795634209388635037930002295896526893410999911
|
||||
10019602901864092738325953873535047812547299524695025320532290515768840900630595544396879008556083370139972255849271116199083634435552540915196064651229780380925328336224573551564497154428220750159228126503023660786371036661986963326869101885946108118123565859605937169197265825780593487194236118858010532600,385562394428775749047853575173957314087625602564743010180946094529317438985024787344743900106472493168796231871305499111699051361035813309229378162588371556942740300961721890004066420192802443990741112403096930009444198021764517249355582327168404565052575639878289683556483174213973783173191751884045426337,783418388779217407199495491198572563161785093246466615634830075323053502538909242522004194931674520522772536562755280126097220160459899598091584353065112800205031495803329979380114748688327366649214078234380064643848371559165846159884696566323937944146599304471519733682046929885711023157291005000370881207583|10019602901864092738325953873535047812547299524695025320532290515768840900630595544396879008556083370139972255849271116199083634435552540915196064651229780380925328336224573551564497154428220750159228126503023660786371036661986963326869101885946108118123565859605937169197265825780593487194236118858010532600,385562394428775749047853575173957314087625602564743010180946094529317438985024787344743900106472493168796231871305499111699051361035813309229378162588371556942740300961721890004066420192802443990741112403096930009444198021764517249355582327168404565052575639878289683556483174213973783173191751884045426337,783418388779217407199495491198572563161785093246466615634830075323053502538909242522004194931674520522772536562755280126097220160459899598091584353065112800205031495803329979380114748688327366649214078234380064643848371559165846159884696566323937944146599304471519733682046929885711023157291005000370881207583|19818230550133203045823734101898906263121512206428289485014719092970295967340599816897147977749512129070950063889339566610951920388554330328298156066258170373411927366975503222525343688945315211747565841144619516815319867733346621311891854079913905473945585105165350274151561111090081792706060108559348689465,3535705381589141871228391312322719660822687473426523492896512078425893509048104602680687792493669387659393458499063851065894084002514574997947346565631807028562721897282782831306960899838643543821499923380013426924166037069379808013932912663720597103553887305082262913905822119893857258661880909162082386383,396232614221934638032209379440961132627800399045535096109310461742382984824006540071415151913091585171033970335144034008200593280126662125846778006926029922409396791751216059456912978293211117174561768028351334637727875808828406496707486419218523437819900629926847694284488804630237181598046520852448325184912
|
||||
10019618759445604574695938593576587154046024907827143734869384751181580594765954554297229655147503034078881467428687208204647162639839815171638500727552711523715462319701731893862102462479728615304020826611064530542284194703939928285119162487825469366941939907341692107287635698074740058272417655173119766470,-1495231899271916161022455577964100860902948284811380648472435397705462086200159484323324090415310461943736883556854457678257712744145878200402349694425772714427495950140611274533744925805188738644517051127445631541048041016411029423836592778690668280454275321001430386581000830461603779827661500573849313313,783469223238034771138196543049546952638608016561545783572815717469547125551690528706587314602219345674223915943792376346892343135362218779360461138111067908088830730205053230437782849794424701715846764766896886615248793041482000930114725702333293352788421520623938402925312326001614873502389289399996101695820|10019618759445604574695938593576587154046024907827143734869384751181580594765954554297229655147503034078881467428687208204647162639839815171638500727552711523715462319701731893862102462479728615304020826611064530542284194703939928285119162487825469366941939907341692107287635698074740058272417655173119766470,-1495231899271916161022455577964100860902948284811380648472435397705462086200159484323324090415310461943736883556854457678257712744145878200402349694425772714427495950140611274533744925805188738644517051127445631541048041016411029423836592778690668280454275321001430386581000830461603779827661500573849313313,783469223238034771138196543049546952638608016561545783572815717469547125551690528706587314602219345674223915943792376346892343135362218779360461138111067908088830730205053230437782849794424701715846764766896886615248793041482000930114725702333293352788421520623938402925312326001614873502389289399996101695820|42753617832955580018896456376048021312038672906196490293353833260191208069121641097415768067383199309083970209480148720670849061245193936234205337011636997701073642429299438906449136644520319530218401933372485811940869805081506160718825508067884253210821932270118450554609943933258707984251287707298966456434,17230882403850817862353558174953648187864024855604030801497255731670352761964080837026196910757872387822284474688098560486179344653906733048259368377140267627812727873134204479739477928295254560644024291521347574950750033700697110313592478883239065168888362080121017118321399563553912315660492325767550439625,185334720796235401233770375301583579692277465177160979515315309579304038663377302594175210667527463523713902806451243556694869849316694559583762178930255061453115298736511664428765337617081386042405590606496094216885684005811351670599975552269701611841562351169528636440894665534868320186990351387365005093446
|
||||
10019692946699738437088786776088494849594837049086417807717694310404351446172508582779767667693745900344488207593378322991177040183985344860702086830308533532509706853397521152883298228273128452797173239342923997882671035778655648164732292144430552486960912845252279998708953177942214236682313539500552760871,2604527605619485478722364121534608303298155156200794123073555280322873845863667712157493176540131822726294136122515227024701303496679207443255980148330176850776277321446427192954383305967741429509598325549628410919591073607402118557146971439755257250099080900555940132394424289156437827280461319685081840835,500718425039020767061203454192505123268716467124573838196978962956303476515938135055207132642966201859533626566887497521633145487747565092871485790754737106452537951081291971352805654412531250563576927867442028177911508524615458471957056998884949042800057393476930961808638050281181278355398049850987480026266|10019692946699738437088786776088494849594837049086417807717694310404351446172508582779767667693745900344488207593378322991177040183985344860702086830308533532509706853397521152883298228273128452797173239342923997882671035778655648164732292144430552486960912845252279998708953177942214236682313539500552760871,2604527605619485478722364121534608303298155156200794123073555280322873845863667712157493176540131822726294136122515227024701303496679207443255980148330176850776277321446427192954383305967741429509598325549628410919591073607402118557146971439755257250099080900555940132394424289156437827280461319685081840835,500718425039020767061203454192505123268716467124573838196978962956303476515938135055207132642966201859533626566887497521633145487747565092871485790754737106452537951081291971352805654412531250563576927867442028177911508524615458471957056998884949042800057393476930961808638050281181278355398049850987480026266|15699856336284744968275216258343503146645953756650748657692246165468174044843605062520381697859516745152728271221936503804746010309726370554190521588468426695997279591480421106636754720909204606127286384900034321176510676319624471022876412905986167145718126102692531020933251202001854123564019876070185880355,-14062166839366990397106911248374270143217677864591057546982352524148999437729801685798965579843060529335708158623771293637111706433187114619631528674568287241750380206758693785598159577574034470606603276333153981703961125634290277406642003061722480822932526131741380714977106447263763374124622526844984498859,322600729981396869806359195462894217882445977495880795669692121484810837171658548584546952485525802042033579797467228310295552846960328437752401071423653349872764602844139832402563063433112043761099494603274082871711473366936549010464198833941650861319850342621348528624209403813616631484437129382551268946870
|
||||
10019878828465334585310006306241539349820320632176313877609501227637096062920082798688866463474161563221707726590576927421178038553651876427988000587231398238649949818114022781306536860520405792494648694702226319794624629000713829609168795402418848754413215058377284034953425744232395623600320736707606263601,1457969396702138085449463993396644727452880810876852537963663018612951369129008613129868381569339225995112076334917995066335564006261425730889703965704362733694154907573251182502287488642500690958462811412545500622611307129116327910472660655763332350656262023349742750811995788737019311563028749123005882623,450291340913970001914821927902049497930656487941189505155449421740207064831253795807819514379798428822187833726946052293837627776646264129023306160855543475421211570474321370516290659041655321190880413623652464931091503946846331738732993987858421621514193715128900207229532916132573315382608752305324170212688|10019878828465334585310006306241539349820320632176313877609501227637096062920082798688866463474161563221707726590576927421178038553651876427988000587231398238649949818114022781306536860520405792494648694702226319794624629000713829609168795402418848754413215058377284034953425744232395623600320736707606263601,1457969396702138085449463993396644727452880810876852537963663018612951369129008613129868381569339225995112076334917995066335564006261425730889703965704362733694154907573251182502287488642500690958462811412545500622611307129116327910472660655763332350656262023349742750811995788737019311563028749123005882623,450291340913970001914821927902049497930656487941189505155449421740207064831253795807819514379798428822187833726946052293837627776646264129023306160855543475421211570474321370516290659041655321190880413623652464931091503946846331738732993987858421621514193715128900207229532916132573315382608752305324170212688|42833037907205783423276083695584027308854900022881436412191284154327219859963073830726581978719142468079055995456299937273491938799745755641832339881754413481117724798837471944396287268574687471412696368395253559323362777618554120629431245413190434891698142985970974309630607227057049486649455303551234276454,39533289765204979838239940217464189791925681811448897199438008522556423440885704979337332145873978223602711609006720684578384015360399795422483770905500296209984111909778890881255526888804755991926913525266473446809003766056812782710240729514579954010888129016691348159521572577875112811888010834450317724241,114445618247053384708154338158850812121782306445016732813783780022720172489813267526238634887903604880900808775058943405768328545540868455633901730958967680579278364092793074061036266572372464072327099841482886966487871555516444733955521438600902217517451457471166242011115873608622049499975622745683155293044
|
||||
10020286611438471830628019358455663881253310586699113562825236385112929540691864656311239753327727457544039348532845219250052901384983806849838772233628634015372101882756673893804993295286755978494686187836862364142553996432815511321224683238615875757382081170105089085250727802357622063598298344850144933258,-3518711690583590719591097309663537838033234040270517781284035777894691716513958367977437977244707408588621580445912322309023058291956527967904833369032334021917801602130557563969030363343390282689269679494383594614447232630864097161162053988664606910387710340058810601198928739842230703566256279504206597349,624519074467883157241759882142650482668439956786299222741478860768930417779553600133573019763129305374619657419598952403430928431333332942138935285782814167747294995855160857963617057240775629113016734743963566849367848417555290458534979590030936513460373735155075741191499370817771701007396549636851814063246|8984140046463484249883815882793946664284637844291004682379330614023973939307670161213321888699915249072065095665013984357459013131040423611078930602512682262356539184355252741789076484547599307370908468303880417320438645852556648240043112769759543510509999231273948875843246292758661134579579434257790056943,1015829211229239775971450394627474475125445320143707214965330038892897841144751214160653701706601947354240523693277132829250608515076685164228306669891554248890083979225036216154539270241518786129131737028646904986272214000689553330402618431223976598945398343370629254397826639390022921851207744783430299181,696229436805911789845333715373446839368886781044433762113742356470360747294068486152977041956647781976745992022313448046591023280602965461797453603661925762491060402477228052040796508933029960965488494546655270327536485285614615574903948243360057525231142937895796209410153481097105649076038536726330776071856|54848884991217637960566999744777250759299676195564728508167267655054271555707478739692179275489551583228746099712696785024768087317010330909987410610335755940330039266190842809649304513680352828151859917245186776225281746820196246056188053726348717015680880973426980177317094806038726097322528009147634772745,-6297694570572926762876118238570574530971092334512760425031884066392157325338148271545111848669911902764684562706179269339278979620083804367858431071965438609706945865206821584390347519912299967269039438763099113180095159546022212222371772149775642184659607016581991317838734844206339663600961049231899483767,114217089877346912860627247021964232304547591103532855496244374445579581677534108677722729277710412822218846458954885849274521645333106817369257230151814552428619784818123898009869914417388072106361002314975966932911313776975771180600386738223895005689517440276702703392932181245821359844597699717902940161882
|
||||
10020350829980446730171851653876883566847163081423697114380946239282341122006641305758856122547334357120649922140862854047676100901410759420113771337592330434048703781028710403003719890979006119445870636592350392949743016116360518402562929646175152381835283065319457849053035555929737557936105886116269575510,5109280702416633154295665717802160083976280911440360164357040723966034505263983198614731009455276771449649216657900445462253241694441028125347117381803166387820276260518904247537793302370100297043111469835733504997940289628818493126591029673530532890213508380205622484398576652164337711722991311438354895077,783009249844890893386725492620727464553802137797080547324163831661264002221403011235072342035014102836039015675936188668078646910670188403603171656900915122608838040537846311585633442130109085368959065613240580402159306705278726186443869273434480098383561830991110484097132938532579731404550435571781667457120|10020350829980446730171851653876883566847163081423697114380946239282341122006641305758856122547334357120649922140862854047676100901410759420113771337592330434048703781028710403003719890979006119445870636592350392949743016116360518402562929646175152381835283065319457849053035555929737557936105886116269575510,5109280702416633154295665717802160083976280911440360164357040723966034505263983198614731009455276771449649216657900445462253241694441028125347117381803166387820276260518904247537793302370100297043111469835733504997940289628818493126591029673530532890213508380205622484398576652164337711722991311438354895077,783009249844890893386725492620727464553802137797080547324163831661264002221403011235072342035014102836039015675936188668078646910670188403603171656900915122608838040537846311585633442130109085368959065613240580402159306705278726186443869273434480098383561830991110484097132938532579731404550435571781667457120|15925442580907323476159397125803944340654208405155024852617286343514956884706735535756801413937274485810029110697926230088903038708172843921662902925858010133310107241826173293821650453674715296467364194160263065021258375363251922427504055324499581378214158250201451314577475359578763255572268099357250433862,-7555018813268449946347299883155637510823174468910058845458344328340586029132905296413170968626375161086356436888766911933184468019856845539645923943455062521960029199818385839225962202237763532700191551972267033706448220551883282613693004882011515763441495954827960366711246754821589418038272565907011571371,493158713590448502858812148491777446425856175908645102112390069549258575786631074217529579034304661646702428496672314797453719364387931287920597953147023776521758543809562386644010437874871311725548645377471116791426470171042917330992088151061235643311858502168972419940204783448967903363982044887911681560644
|
||||
10020520888850607221318889209733010855356370939979030352174416847268871176606842611908448929226351061331244222832181615393476121893202716429497688626737367070357875341852767661277331348237224754401428337725087948250057680576003972340744936007808116625981445480427395587481367415686693519322831225744083857506,-3510865184553106032575534381192821350315875177100225193260562098432442799313338094676188269972656054940854032321449718355451351690660219631429988981801589127116014570347706272895437608443770068021130141264825492984427313262655182236186480543751195475768423487011396127341338009641051881511727659162848161119,631736658355910953992723930048397079196586052511742763210137641692860240361410089621711682505909275894759266095700988382555714505394268624248297891868203056209475282038131157087467910727013960998888913755441699771876897234334835639550616100989309716008969633105517000398222168491114030388197708472040972683126|10020520888850607221318889209733010855356370939979030352174416847268871176606842611908448929226351061331244222832181615393476121893202716429497688626737367070357875341852767661277331348237224754401428337725087948250057680576003972340744936007808116625981445480427395587481367415686693519322831225744083857506,-3510865184553106032575534381192821350315875177100225193260562098432442799313338094676188269972656054940854032321449718355451351690660219631429988981801589127116014570347706272895437608443770068021130141264825492984427313262655182236186480543751195475768423487011396127341338009641051881511727659162848161119,631736658355910953992723930048397079196586052511742763210137641692860240361410089621711682505909275894759266095700988382555714505394268624248297891868203056209475282038131157087467910727013960998888913755441699771876897234334835639550616100989309716008969633105517000398222168491114030388197708472040972683126|7743624975856046040306859618381122855435839505066655963077953345318192394961725484815279361678840380508650449544352702656790861663924047145774380332205220566837995316217250717822771650639012193352578327705393209628172084550305955102732361657948117240351750958876943333563882332223706621973470079325216233558,-1302101084353535785220069078550654080595332453473298993211431176604229397211571627224468015823760998656644913758576425096529602829962318111227560243799515644278666734720045652589883053894188670485823003998604116205699634345292108055002592831517880997584910995083278522924829895139882422136963697022188627761,817146068444645002282702401442161961453363715531517354922416373299365609662611633811411725714915989553805697260975442785287852917015804775140015044436435034561860932937633743951090004573111260937285724402644730836466114286731010063169028245934842509507242843981736397798548000353928823827450308171577842094862
|
||||
10020928293252284825691361744328291985679526412406671670547266480511907045983316758483586023724996977667177961315263269397743828323222195866600241379821175298238115703011379072606569390759148045042025527825985903353933863183965714600189445609817913064133950477152949408914363876047922634974111379776851043444,8142743010559227647391965354039043610167208616578224783916189122845589179285287981476385252457789283574398377141778580365522603626148442954692842646237080732477747098895946414915542936790529750280288364463486949414374698119959104763454330750738981793594749326992763123032351693132354526673391669903228534689,592964939014299189950759948556152413778070028508201513223477782517837089792535061751235218815245724595945353108562584681842937744985593454797280372456160144528618905336752579099036263281502692258180148097231362749391384857475259373320991218168838336648271137666762974150421876463236269917491554488254970217679|1349884692028663713443418855258970852876197688505766806916101525225125648882224033090914393786384981404185367136201476426040087000294669320520442557740324611111940178669433599306350594555401574017007121415045406126185440950248044705540071793090107212207268142684391021538262661004297297377597036659211434174,875208077680684118200876261868445011629698306468238985964846580756586701312125036248886125282325554453814339944800057599270619114144498434513170361313175501368378946075602194132049645256086611958223310749365652107262190169934699379958455541016773996539749758645125590779000274985163557422936755735709025447,4389763511378485954501282191747251660999265924712682485695638493214865378547677386856476228802410653501422368180730844272453992845175409659922990510986478738442978379229425566565975718386747664393902959866984083918397026705604419570614664652992630348606149487368881973666571039701786237266865588917768672714852|5132295574467316848841777686734617679960174295612803556136691640948831222631657128041983413228627956037030789543068853182770008751639881188344733284990628383483491534738190385257771536358960825091917844011611151709882253457446948086421180899165481250089224998180312937340245384853080966454437114981749282088,4739229759958591334649295599424854432655955954287517912213597569502250150023192426249576133181257597090869245470242256174272934097508617180274802785425851556700817333154643929185825330049486269453049410315760063060060300773867433992976428473895933388104059320286367359084036012644394853593574323294698599047,1155642354763640840161317866632512711606463189115904666846240158382151567767869875575965412366883980252176109447698054839109820546539837615968386168917753356894372414795267678454138557008897676758489406076799290056896394919016510966326013771652656266881913835619564662608220574395369543699406086980500479286021
|
||||
1002117978472811787753331928095730917976095264113100009019616793747721435107135088389509812754479746771762680547024275550906766428627777497396364614972130274470274918515966945652987824482224985008334448385591915791378703701911471719689908547324909949135740705163689874051360252727792128439306172396510982072,-605384264858430906616142488992272359132356724983679496986875094989266808748892270936577381465129550495430948251840196888998891525556778784313001078991820767039598015715393254809115469379426480017252950332375890914475777381882010670869152139638115965300974540658001803028482400664131564914546111105190254697,5913050976191825085156815974405378266929897129377882420061135471366299940142986781640170880340909029950997987433372868814199338484242838439841578708925504283923079897355159590243914836924282498902916652661483948536914918309139164893684671128828548900808846820323860573206533041501286493089345814823705125482184|1002117978472811787753331928095730917976095264113100009019616793747721435107135088389509812754479746771762680547024275550906766428627777497396364614972130274470274918515966945652987824482224985008334448385591915791378703701911471719689908547324909949135740705163689874051360252727792128439306172396510982072,-605384264858430906616142488992272359132356724983679496986875094989266808748892270936577381465129550495430948251840196888998891525556778784313001078991820767039598015715393254809115469379426480017252950332375890914475777381882010670869152139638115965300974540658001803028482400664131564914546111105190254697,5913050976191825085156815974405378266929897129377882420061135471366299940142986781640170880340909029950997987433372868814199338484242838439841578708925504283923079897355159590243914836924282498902916652661483948536914918309139164893684671128828548900808846820323860573206533041501286493089345814823705125482184|40380288636863554747802272146363479186663329648459490067115808757434033306882038739884681373117979723495792330864501446629245889731229516933727403492773771957483850679041758865017396807842498482944854723605982182982516939476048881995525535805104281408686338183559590430185038164235953706463250800021094604474,-39534865948835591455192703514729394748021266253728249692602243000799548352268225360374954844443730084878434721021241498114475458481167089270721522242274850596448738616202710373135498775106936938952151771547223007405550740805387552512761050820125134092471485389585963771433812018574391368483598373549383847189,156418754990595886837540510636676538980249340054775526675231187766083040611703861850669234853631535367187296945071108522620946681763860321505477715553908841995650918300850635601347255855518666703848642329714582982193362014895765955759528160104377932684150225067984397783920984799879483126817672124425872829049
|
||||
10021358599463053436428121851639014288861925656265693598359693460594603335959883569550641125363212428397536880700859686977743945025535807563785786052244914761332363029072620567677261483868230251440566526595521949067385197316983806258145013751454322468391099167319094251906044804264200412596430324237392628100,709083183297048652772820333122772466256400885278203522245823989743215866042577745109340161132152908476855845193022669210873284198994493560336775521366659865852432460708969754436068709338598181470025481044065851120985245468046464349075382208377683917405549429133970439515821299430661611942330536123845644949,516570730285299534762323653103362077033679349887441156383985263227144702832028548168588332437855509742797208817471793880841971810641558363411834198813856099949994799818753787070184420373328485385171466383296907894871575302325766835865200237080249407408770698788688709844525521993129914019403957225364497263784|10021358599463053436428121851639014288861925656265693598359693460594603335959883569550641125363212428397536880700859686977743945025535807563785786052244914761332363029072620567677261483868230251440566526595521949067385197316983806258145013751454322468391099167319094251906044804264200412596430324237392628100,709083183297048652772820333122772466256400885278203522245823989743215866042577745109340161132152908476855845193022669210873284198994493560336775521366659865852432460708969754436068709338598181470025481044065851120985245468046464349075382208377683917405549429133970439515821299430661611942330536123845644949,516570730285299534762323653103362077033679349887441156383985263227144702832028548168588332437855509742797208817471793880841971810641558363411834198813856099949994799818753787070184420373328485385171466383296907894871575302325766835865200237080249407408770698788688709844525521993129914019403957225364497263784|45614503146354773723748422556503247371485318543120586857419562717702458851951901017328552145694380945314803604713256441070275022414069445773768101699000362770774983002903055045789385932735047082208988353464300453066243128392263161058473354625441431303590972274514200470903553097396578608004283743393727480965,-18121746874119905746733087661833019801123133290011543785996868679743860577167772600952885673213204134707814090152450287251108460725457761668330446170883400606809709199165941064933022535458655256850936026007055165113021346772772048647561510274730081303287537167422875133875982474754404203878182518086566378039,115286014209231820841785285504789236723202458419099047051127275140595097884705397561562945865060894329450657461353202401141562369532605474636151114816630008035888537731586842019104642780200033707263419710825605300157241899226642312799356394901240315456385563221341513078098381767868711376025198760539717198382
|
||||
10021467180917602737976485607440169246689782775819592060097133723376896163041617997117690261968456452635527584517534178504548298348503697184587408892932776130526709512085862666360259215825375712520283335147827351975626062358619071671249870717811464295853663335144999169566479738875598518880232950110692415860,5837741371138928752178739797917364838658798118140089345232324713852930065920933839519905580179654383108038638880741427980662680469791777270068068248248823295528533080598248956003543247574941878960563240116001302598572351690506654603050328390643642345907246472180377442808566360199364409627306574545050404961,447367712945794368035040617182455309390859836657260473211881159345841479208328013611245196832742331205848397804369783648021077720443154207595416670723327933025826385393654289188255079761853719682847837385185400997339750661153486494578411301935184740783631461198583032914565210707960404049019611688784713553950|10021467180917602737976485607440169246689782775819592060097133723376896163041617997117690261968456452635527584517534178504548298348503697184587408892932776130526709512085862666360259215825375712520283335147827351975626062358619071671249870717811464295853663335144999169566479738875598518880232950110692415860,5837741371138928752178739797917364838658798118140089345232324713852930065920933839519905580179654383108038638880741427980662680469791777270068068248248823295528533080598248956003543247574941878960563240116001302598572351690506654603050328390643642345907246472180377442808566360199364409627306574545050404961,447367712945794368035040617182455309390859836657260473211881159345841479208328013611245196832742331205848397804369783648021077720443154207595416670723327933025826385393654289188255079761853719682847837385185400997339750661153486494578411301935184740783631461198583032914565210707960404049019611688784713553950|37349917633767587717677900017226055640277491797128368066909216648299856708848885314856667952257677125356703617528489552040640666031343260644627231518748509259039268948250724796991429094425535890736981916444739110193691988414365116633947866879178749608358114634543684726462828729304210028284694641568628398966,28432301470760114127472799211494908630719349909135890789013779669649467182102043473145513283547284407986093529470668063517370252190889483927419539271833812410008532555047333957640590516339384293520187649830718680466604203963675273404448810489933228206090139475240540056839557201036234130668781355507913201183,125217411042216743409615853418748212447815557938720716586287232669270939052168073429461670911284540249994159813915524580152040717865022372477773851596046555005754956888615646701914356508633194785367798807957000924761874706728044310360895862676117058335122487191434401996751617050877596333038588838996255145412
|
||||
10021498468260956088123000232540981309673362233093607160766199611849988598018670545801586655713528191099718167654049219862424879654097800612715754405882205966256512537388088543329708772570689386840584832681600027519346949153293344313097460804932850840053785736778266237521116511372386612740914586110495537184,3731424607272136278046418371062826309603938690430502989163037797814883875895107208656392082954628965555189423854897982564780098075475012739517997385664143357277834178448678167762594236943371764347482562787414335427396456552673654489280935057856453787409277651050808844230948476551514072021069206021678774679,804130312590685641878596579775606667166276173286759021130255643061750446804433775305738231667374247846782607238734204509216228540137516790899866440807044660490591982953819190288555363659024778526537985822773652575997791262130221988665167762257066646395773224522658242462757313827560884465576118125526400301268|34167053368438934062493883132954265990697806318308586148616977663701145830016368570117108522767165162437388551633476818714638781998737588453423052906955047313659481428825017492981415212399429876112133486106544289854247118707826610748061980313138870978861241099932331052851628733408772936072321439631381625681,-3231990625187035132148669134941674343311291560670575472626948487039873506375201953961203524971750773872175368844083313789606744945666601496978495543448223413432959722175027775640416642119534579082078058359377011061266769493053544073177090778768228650034186796092538667273516567672252447273843436045477135595,235833074847574898390813679013790646015645150909185733872405459206523708909325302363230937825102097363178252008781874033668789787718772243559737247157023625992313606650868510119173526138833975525463395139358451436580786324137262685697090102400693677208248369147898653293586089386800659102730021728025849255818|64608837982278224108987963939830921137767130655870201859314566649037112194604993755919994541029928783963356571015929786284493006279718103094473109088356869444636451105877134516067500703977445578997872357043341015093673550983708510265625469154579844276561631683451922580837098594165662625287526508058436293986,15854906341458894966500422391448052536768193946037447623218750633953720338742777805649471066920966160101792990529839212517155533383911249825767111242302747793376405376781322851763232537121183798411448041082168628199040455135693063512226758138709898399548068871039436946823094929235771529576088321067557016361,125647737690478667744295859750549841902875194170056775019306475803353424716724181236654109541003077830795994847519888612974479612555855274394676374638319448048091194349835875247946393849792063872096400150096455332718354245732182310596592154379165437563189009506346555534189191250868232374253149843604451203312
|
||||
100215518435515616798081693150831119413586767021678884124518533924984792516593586077070489902053827517598088670562746849336597165534172718871853401767137095032008213339529086616777467841346280017019578258259797551450310087222690828893461467525694138266456717327225955476876417507053206969995585955166268406129,95057958551667401403353090513192344071592935246219146691681088413017107538601166978955721880254187942559271242509539286042857509266018196345088028113071042234423096387755035509877692642793106294014825987119124937967036662120185797721977723389759564327297787909379686186622926363357951464215904895677999421567,102919326722329333489116060760618421823222867295966177344707558731080005177983472593218329502964236109795974387237881276225611846575332218440299281932674994159773703889896299379022277106535867836949285795306043775879545666098740309487810106763993748938964994198360229518682147400433454886610366004026941047356|100215518435515616798081693150831119413586767021678884124518533924984792516593586077070489902053827517598088670562746849336597165534172718871853401767137095032008213339529086616777467841346280017019578258259797551450310087222690828893461467525694138266456717327225955476876417507053206969995585955166268406129,95057958551667401403353090513192344071592935246219146691681088413017107538601166978955721880254187942559271242509539286042857509266018196345088028113071042234423096387755035509877692642793106294014825987119124937967036662120185797721977723389759564327297787909379686186622926363357951464215904895677999421567,102919326722329333489116060760618421823222867295966177344707558731080005177983472593218329502964236109795974387237881276225611846575332218440299281932674994159773703889896299379022277106535867836949285795306043775879545666098740309487810106763993748938964994198360229518682147400433454886610366004026941047356|97265337163108204413956364816446311461172514617683583383746668715450840222180976393430496104553022674333721978573099848181220662887846947468935453182046364733749916475895309307017567642434296055225121834950440706059303257140878621147190170027097598386070490643511792242136161870345758898813890460055238965518,87547457109798873839305649757452333043926932497015596041815056726077989206997009131840148396020804211298638181409067017194388111483773222118240882283209994405160200490126585806391098433830826470475358556954973925001096433563812177048160467037091694157852152308504545492956027258260588167152638099756708452923,102515957029857878751803789736896993327202543313952394340885451428025600212535749454672085478483321275958139112689603772374702592116757008616636478536965453679964666255956305064090090239129654015924433954512354305722977754010864408774189090428174122344384620043576093595618564991259055360564491303523423085863
|
||||
100215518435515616798081693150831119413586767021678884124518533924984792516593586077070489902053827517598088670562746849336597165534172718871853401767137095032008213339529086616777467841346280017019578258259797551450310087222690828893461467525694138266456717327225955476876417507053206969995585955166268406129,95057958551667401403353090513192344071592935246219146691681088413017107538601166978955721880254187942559271242509539286042857509266018196345088028113071042234423096387755035509877692642793106294014825987119124937967036662120185797721977723389759564327297787909379686186622926363357951464215904895677999421567,102919326722329333489116060760618421823222867295966177344707558731080005177983472593218329502964236109795974387237881276225611846575332218440299281932674994159773703889896299379022277106535867836949285795306043775879545666098740309487810106763993748938964994198360229518682147400433454886610366004026941047356|97265337163108204413956364816446311461172514617683583383746668715450840222180976393430496104553022674333721978573099848181220662887846947468935453182046364733749916475895309307017567642434296055225121834950440706059303257140878621147190170027097598386070490643511792242136161870345758898813890460055238965518,87547457109798873839305649757452333043926932497015596041815056726077989206997009131840148396020804211298638181409067017194388111483773222118240882283209994405160200490126585806391098433830826470475358556954973925001096433563812177048160467037091694157852152308504545492956027258260588167152638099756708452923,102515957029857878751803789736896993327202543313952394340885451428025600212535749454672085478483321275958139112689603772374702592116757008616636478536965453679964666255956305064090090239129654015924433954512354305722977754010864408774189090428174122344384620043576093595618564991259055360564491303523423085863|36966589133632021596451231446360613869218644305972974964188922476722370035917724082641341991636532809500406571267262673636673259154835535079572834230006192461227395506315158937114124659074990425552664025796331234355303904150803244972310400202941266552149385712614489884410598364289566113507512621328083820598,-21149549205459986335385704446469107610959268704221609170214996514478740430167085550085863459876947711137447213809502018277525104101042350103376631096271919925064995296178696672186362840988476041323653097243744018198278462448741240768165379772727430920245528842325914682295445854217287403981994755438946746143,220927487842748418739085114242513506611909793723984315299233121420377274197319470229298268289856409101985756388437199198962449705412131211265923072982106236351953282676471404053070507026981693842676184502073850443982862759823135849927410711140706664324113248738142786497634534093355523248932828221913746822818
|
||||
1002171279912987474674729832690970557140429555644292059472271841324924331291685060249454596336585889404705002700240738701699260928512934819245660001207610075089195766056310376194900771895925996113770666776022108500330653518924376342638824072832759321658474598385675431858595122771183526939999696158578609708,826219028959713490046361889088584439498783654783530925153550597879152616132729000468702177706363955325292708928091882754198698376648310966516057873159349764829040425546512821864182430231493467696041840597321743210951783900165181749863389211006249005916285731575237461143803624956905795631847651371075603271,8037828098286918052259824988376802356784599160404526733485731117320394626772712632224126968007402853349764765913068975115077635719542022449549397610278043584259551667143554443745235133704301422592616247052815801996895563245349515275951060813799742580455732670079073038616591480535324416008144264918698168050014|1002171279912987474674729832690970557140429555644292059472271841324924331291685060249454596336585889404705002700240738701699260928512934819245660001207610075089195766056310376194900771895925996113770666776022108500330653518924376342638824072832759321658474598385675431858595122771183526939999696158578609708,826219028959713490046361889088584439498783654783530925153550597879152616132729000468702177706363955325292708928091882754198698376648310966516057873159349764829040425546512821864182430231493467696041840597321743210951783900165181749863389211006249005916285731575237461143803624956905795631847651371075603271,8037828098286918052259824988376802356784599160404526733485731117320394626772712632224126968007402853349764765913068975115077635719542022449549397610278043584259551667143554443745235133704301422592616247052815801996895563245349515275951060813799742580455732670079073038616591480535324416008144264918698168050014|56177784089692916832266345214421120674340798487038570515623153805048107174705903801913422904686022519185882309714950449353350144136176082122642988743155385846519789014579069658520240091050781441562176069717906258293112423657764692478227614483398005555460543943687308770699629754468588531994448652035243537193,-1367086938896255072793415069058299472671169571526909227192393757206171174220534221238412428332819898373711167739278653738196147736460040492805449727552702294473184951105379473908985544436596593693459127262500591594358945429165046595165680187593280155590732587752336804926254680443537232304173256876819864345,143394353759539327949427865403227850259090677769631111628953936665415814894670562885615312902238352976078395198035416430261300974094600135242231268642783230986499797624830094698405716034919055851528418996945744623233014619026973652777892429824489371625486460871462705495597542593148226840678864076948049036056
|
||||
10022430537581100668502883292824778933607339338765926026805737984600928768394291101969168677779321137283218236917508266473465030665219284863536608447940487677072083129795072785840083494425556238492937940196822995238448372796541954279303435932510765640503040286741618037016213243353519162818665268721728774804,1745450390765598318476765814191109791291817192933930838487529317598912090407141417101048723630667618601898718290746648849351810269839537783425961583377520701947088669609241693035013571476458016904170389418378228794668337339954300480921565354479003099904568784841604791321827362751710640603340143528678878307,505461416773210200375665916297012066614237052797213136609066313311545733018491487357728242574093909073856795981653867763762281713211234379922321747443616377604676750509494828442443340820844933440417718090216464110039019539088373064239526712549777394214168807828906636896179669124200810156121848745927583143473|10022430537581100668502883292824778933607339338765926026805737984600928768394291101969168677779321137283218236917508266473465030665219284863536608447940487677072083129795072785840083494425556238492937940196822995238448372796541954279303435932510765640503040286741618037016213243353519162818665268721728774804,1745450390765598318476765814191109791291817192933930838487529317598912090407141417101048723630667618601898718290746648849351810269839537783425961583377520701947088669609241693035013571476458016904170389418378228794668337339954300480921565354479003099904568784841604791321827362751710640603340143528678878307,505461416773210200375665916297012066614237052797213136609066313311545733018491487357728242574093909073856795981653867763762281713211234379922321747443616377604676750509494828442443340820844933440417718090216464110039019539088373064239526712549777394214168807828906636896179669124200810156121848745927583143473|62092481921639574438226283198332200678734028657724766941730022043809545444204108322446905830622252301375431538847493859046365695561521947886739278282380330944740137778796806258440017010320211759144908638103476555150573303911926239710190937911611647166321874200336757808613044926465128049757211183544247137033,-45250053315775064910191280612561362661486537888549446589078696876018947013616669550765115160411532144837380748629686624052593601626644191366587957076497250945144687082001936959339633808733565487985938465191480629685961056777143827741613522372695750936020580143021192692134512265227690413020620317312128938767,89818959533274049458857462069020739338602011671046728330943513188118466840658369260446327848180189713317967953477747595755322234416809755612045527023070344299134617743385420998285144607795275808302453674682604268889767229654448620219461284821255145925444306004911131336470833940664306256327917520781637949994
|
||||
10022447467429108159774355787589122715485396978224199367300758397771363796346073591552810427326339622121413685155961164725589610901918895551781900417862806225664599680621980718988526130452221161919053852672286805155084312599146807342205269705230729665300558186233143844168304167857171548003707472393702474384,1188885044590400163258159304120537014931301063692806659646722818307638465604090862597898645794165661603569562151904733849823451481071963642820939826997500655539582070601901658042242359967350311563512079177663668335375683704849269904109356286951724174166294895547399547486092075854607019467491563004574181747,451886511793730238078310968270671960837012936994555807769579552350299617939295621484477388940254813126337697555682035175155312684470552706006082326229489214590934446980684912399661406451818153885180492656373585024394872163807899894979861799817481760468528780471201306793514412189815424515752868704991093442748|10022447467429108159774355787589122715485396978224199367300758397771363796346073591552810427326339622121413685155961164725589610901918895551781900417862806225664599680621980718988526130452221161919053852672286805155084312599146807342205269705230729665300558186233143844168304167857171548003707472393702474384,1188885044590400163258159304120537014931301063692806659646722818307638465604090862597898645794165661603569562151904733849823451481071963642820939826997500655539582070601901658042242359967350311563512079177663668335375683704849269904109356286951724174166294895547399547486092075854607019467491563004574181747,451886511793730238078310968270671960837012936994555807769579552350299617939295621484477388940254813126337697555682035175155312684470552706006082326229489214590934446980684912399661406451818153885180492656373585024394872163807899894979861799817481760468528780471201306793514412189815424515752868704991093442748|40311793122681847438147936825674014314470693373123318161207015676732082581716792137317735331938108693356512243120485847992937858572985495883514340613966135614307974866016309204238807033530669264492564117724246353883749827195305324197399377631361609176376894124562777952015115546002574992839306368859847102214,-33025539083635098527284543501358773726385310602673068647569756256609245347645406103541323476799319282115094670558563042038040727572072629107289743928712116480609261863925810781181839890265471330792670893248452312920468922228853995606392415425665874155050360471274554137526685669823510791388257867791420447345,119104774305358145853754696022566395542085319811674406549968528384273306539129655277119394569116384064134522924495522726505126314830673393570305912602792523829301472113875383292982915986048501532006750975293601050038174705411480721485112499986909208662941192321772927410908019836648310546774872889908741289549
|
||||
10022730206246523605885847628248331589129959745152946800589982371582759735440896033124734292653525513269378463322751069994968860121969888496580966465696069881018097413525001416210515174455496944629883370533539582159385347137053307519490537337422600372155743988569466107652391801498216166822344049274248006914,729727310531644666459577636524370584122920562232400100508958613100574209791027073647329563436154072167135037277674792721862334569450792556614550488339055151138688316081220432057278684502305768700617734898572463248131416139418546546921772768563777642345566507958981323489827996692750181630164696164350792239,743420530670049129014551314283001582671251574132606225656558769248051872668919945335156046109684599461479010072698042194265131432439432111708952985059170648240550914992169145894926437588173425753889988734024781047390921725232442091277340971091116650569099484901188657501225210251920789312381353410873675482898|10022730206246523605885847628248331589129959745152946800589982371582759735440896033124734292653525513269378463322751069994968860121969888496580966465696069881018097413525001416210515174455496944629883370533539582159385347137053307519490537337422600372155743988569466107652391801498216166822344049274248006914,729727310531644666459577636524370584122920562232400100508958613100574209791027073647329563436154072167135037277674792721862334569450792556614550488339055151138688316081220432057278684502305768700617734898572463248131416139418546546921772768563777642345566507958981323489827996692750181630164696164350792239,743420530670049129014551314283001582671251574132606225656558769248051872668919945335156046109684599461479010072698042194265131432439432111708952985059170648240550914992169145894926437588173425753889988734024781047390921725232442091277340971091116650569099484901188657501225210251920789312381353410873675482898|72678153493282504157416115644391264652311137140691071678059939078869970502440343742868078709786102781757123551689967637475890683084227768997487411568948523707471659432320585674519265605598599734502760770267332905322559905487379207111063130039684891358469047921852095373415568614214678421199229135813148340086,-33947255666808860516772098102208086001134373039996489095024233296987004975315716216270171442041054094605710390151835995913332617034994068103936254773578912095997116516855870766220741602335129322709546766837859664219492792132163257557798382623121354098297535938342782377977312458602436715508338777893530715947,106484190269718620144286637065233814518223762302071472353291401620347574484719889974719727699170546479802692571973907348709106400438154108695479596777257546039047068390011589281587022778512291574952016353907379824791098458869045617748541670371657706126860369909581308416699070396340994092087729258233572584479
|
||||
10022801037884735919398225401015346770690037220981230548926941756106963920408338416095733094536206053772963879852109190901255264805008288279841331919785607478274212775267264447609163695284184368267756738466008982331882800742073245734831347575593957813641726104668466028052775256385701674654962758632735214325,-1581758127940839328365881014818315360646059541554455415456767586268677829342640676667660057584626141079060910685268398574862315277919005616512245424342499450499940252940175197812452339693288044870174334000429767858420712066019926176503980859313840839446940401868444636117019979796283038985302067912785275287,496761537019467923365643288264945659788228256979170730808696057920098575449994591930452099194380843846370073248896650848520976197841222484748214967557803091427696552713317560221122191533744679546984546053333189737767090004462878944114371161170193473185997313558677097782867340116873490763865370370260817678938|10022801037884735919398225401015346770690037220981230548926941756106963920408338416095733094536206053772963879852109190901255264805008288279841331919785607478274212775267264447609163695284184368267756738466008982331882800742073245734831347575593957813641726104668466028052775256385701674654962758632735214325,-1581758127940839328365881014818315360646059541554455415456767586268677829342640676667660057584626141079060910685268398574862315277919005616512245424342499450499940252940175197812452339693288044870174334000429767858420712066019926176503980859313840839446940401868444636117019979796283038985302067912785275287,496761537019467923365643288264945659788228256979170730808696057920098575449994591930452099194380843846370073248896650848520976197841222484748214967557803091427696552713317560221122191533744679546984546053333189737767090004462878944114371161170193473185997313558677097782867340116873490763865370370260817678938|11794018787280482940784484560654447929703367834543013693618622456325444683498014462584498990809979794991029406828035162064888206099231897450516338131683344468341641773247077777974904033180523619849644665052604243871182886239709602918372696154159689574416694382901020412810986466933364313296340223658056711860,1521303582082972784094072429213245037004474422912041747980341661334088522130166480999863587718878595218681652383126000473728595142115360315778132844751721718890137106680913339185860894697918722593994440198312742439897553470706013918108591714015302153342792691194124679477731145179750991721088470556891980683,422154249545788907790313192562529747503206514258177376656051975747255059759645179919603489351691318624495599133821906453410850735326793444201922900151270842818708202863054380424556183873836633029531584190623724167592312286966999660766414372084390763660497972689763908414494950088490657933080790950343854684683
|
||||
100229993686309443431652234853242745584964039848901396902154758000675611952948762456754223980100376888310959032918053199573371179952836402943594446966248713771392255748269391671122973567354604611827710836480143363448852247469233467634585666281897503837387248046923275198978369387627574778973203963568459570613,99141614774063628352404317381455383177814780210220526925227232275804977777537108958838490639289349073928621828114260050626184229387757267144939794360548040966543453766396248232212371430223357646841577045712198699745634479223254936354615654319866477688010773948549511551046967361375809493630740150224195152939,104882524400956127942658813062851389442407913609672222789148495255743494809906874598039501219688723468166574648371069153919928988258063568059818823680918241728433303999086584504182405446032391227196284068159574388579981415818096136448105143139694516800086480906674126689437313489030594417564677758780953521314|100229993686309443431652234853242745584964039848901396902154758000675611952948762456754223980100376888310959032918053199573371179952836402943594446966248713771392255748269391671122973567354604611827710836480143363448852247469233467634585666281897503837387248046923275198978369387627574778973203963568459570613,99141614774063628352404317381455383177814780210220526925227232275804977777537108958838490639289349073928621828114260050626184229387757267144939794360548040966543453766396248232212371430223357646841577045712198699745634479223254936354615654319866477688010773948549511551046967361375809493630740150224195152939,104882524400956127942658813062851389442407913609672222789148495255743494809906874598039501219688723468166574648371069153919928988258063568059818823680918241728433303999086584504182405446032391227196284068159574388579981415818096136448105143139694516800086480906674126689437313489030594417564677758780953521314|74350434749389969050012184990337127551177662105941520713519479144559556197790064845857130327167806787623076521428876751871163669518580183330141936425233250661556229643890019866856080560251792692090494599862764037832371889499003253542457382200017573287275373464647146587627430764219256453016377003846953421792,63957711791573361964387609614017192151897432836032720396105880275969302058600840013396804158201720534370023895822842857827830012733763196699928990175961939998886321856401382898475734879783268690655497427397663979021512999064707392335539401656442120559970485354029428771216688798043679886727502284879667604695,122094202522303244187343830185980046602374556531568820744954812272038371153739943186637285289631950376927966459293327247925407412742819149064968500238603572438294529950547276948751033111097715894035925769404645235126181286620345914299937264438033627270225587240098530161700877220337370607067995020225846162049
|
||||
100236185197041329075554833621063049933091933804804579181020863476728313391686305869039610612323226747485959655907451027539483829746780221656275287251359920572256326848112354466643258852396004468792417619989592999892771161118188446161121453052287245392349650298061886772129843629230859327769032485896380376,-23246228755139486121091450291914215536752934295258164744923084651696211557139982911633633936256958755233390860799953871691506689375274550434281909010783595844874773750530708001462730196953616598369162178869242223651107363158755851755977149870788847101056032248840046983417481075963548958473469668684959891,56573523673680298471644280373809509686143659597565817726545502453421314503494549466829923326874504507298291631695935926527600390521472116074127195438583945763976558015737054829572336871056542824657451863625497940311479875421301704568832621760721804490304525701867696665290350769186367013604263730372702025776917|100236185197041329075554833621063049933091933804804579181020863476728313391686305869039610612323226747485959655907451027539483829746780221656275287251359920572256326848112354466643258852396004468792417619989592999892771161118188446161121453052287245392349650298061886772129843629230859327769032485896380376,-23246228755139486121091450291914215536752934295258164744923084651696211557139982911633633936256958755233390860799953871691506689375274550434281909010783595844874773750530708001462730196953616598369162178869242223651107363158755851755977149870788847101056032248840046983417481075963548958473469668684959891,56573523673680298471644280373809509686143659597565817726545502453421314503494549466829923326874504507298291631695935926527600390521472116074127195438583945763976558015737054829572336871056542824657451863625497940311479875421301704568832621760721804490304525701867696665290350769186367013604263730372702025776917|15573203821391096660668742152065727671791482748659900060639926963022005424305428598384096201045285103243110012385503647750757013115954608677386233978142224494513680866630913236076316930192686744226921983870965664346251492074685634583531334565997695428546882772894918870424603926033309071559111059501203642333,6451721584690521069581901111974092204654122587875579916279551744658661205413364185368986076832511568929170794843492990781144450828332965740817648161987976580582338126230945095334678085775013660661642032765404588316501300352495628863315640949745573214882043885532409624351786399389352651138436910377540588715,364800994330757396882653090957020494991186585063682233319677342832051344502776958834410035811370111943816463424448302716551318762170472662165419035921367121365358358160571142517808605560056227966869017916492144933000445349984077920674346135535102210585266868874844995392794923436866721883251932973852604825116
|
||||
10023667082494025533694458923906062911614808800770741660171152481026059347510371753561616097379084784341713671154750835715019868680624888814365226032644794597463378220681171484265152741451558871527205613714299617780955377578029153710181790009777505367079339560569389236075705577562497976407198835496123421815,8237178824212969139758302266371465433903111044341794615829413365403141507594223080352356455683475273814082845524013102162873125179530876016035628585832833134556337909718743386830931466874558092486241907311137385119488677802975754525714977343935483066353264879509528297193753064624793968877384112576484389591,423224971588853021692214116546653537988666116441804013450094782696541031203993989512468938158606185066216192664407632356213925851579704646681338385590758369803509256824915492724160624602987883926813515751341908451718832678074898298694978135986894313441355375932022035725661361883088309484290780962315557040384|10023667082494025533694458923906062911614808800770741660171152481026059347510371753561616097379084784341713671154750835715019868680624888814365226032644794597463378220681171484265152741451558871527205613714299617780955377578029153710181790009777505367079339560569389236075705577562497976407198835496123421815,8237178824212969139758302266371465433903111044341794615829413365403141507594223080352356455683475273814082845524013102162873125179530876016035628585832833134556337909718743386830931466874558092486241907311137385119488677802975754525714977343935483066353264879509528297193753064624793968877384112576484389591,423224971588853021692214116546653537988666116441804013450094782696541031203993989512468938158606185066216192664407632356213925851579704646681338385590758369803509256824915492724160624602987883926813515751341908451718832678074898298694978135986894313441355375932022035725661361883088309484290780962315557040384|26149581659024134542252839056088737943459101230098434304929833472689045273647101980834416767117184344850968739815058973073425320764635194473778310753733774870500611744687135320440722493629102059325894273417025541554717397282491317870553755571826770905575804901409545560793682652830798005534542887045797606186,-1697969983698485305905454448895722929114256960413081228420951351866600414430800217182268923658152076765210118720420817273440690524435493363475828642615467592516719174944772197605654745416391960101282581330420264887754748587983051609045080004443224578293135292425351561632174977350140009380537152490928076887,161609629862554141142708472275797044218689904367615056614920333643328937851927686237891781051003871507296405842898237370248243352582987628460341700892139196626441792037632328670727659225186548971653052724874684965299456515833967561157293186033533538079205556741150926459475886439855496878616457828726831550112
|
||||
10023862893594232582190646068648463209940952006884955056666263414474264317722655546318247009455771884983355234222787422801894657323776793269825967901010897328305149754199815134059038386803327107954623997783328925014573712361190412041544730846393144970158584993932522919092961533807689663994273510181230611975,-2760322820547873699921094239708262618123220686640344280427532457964735913231839541155448488755106353058077772483391926518490758309421884945189004380274532339303673658136307214150768559915038249044318636340829040623019533080008795877188365713108541851533478868182315253939354465782006188226272150540248455533,539774532098344028178575637715654362402942864818067869426574212334581836029933543954242820122684669884416483020859433711413498388105161261765872011520166122694643001745601237406507189268543940858796801993814111596277340371144355358041455940732653675597524992815557778776692308187755956982584432604519599405036|10023862893594232582190646068648463209940952006884955056666263414474264317722655546318247009455771884983355234222787422801894657323776793269825967901010897328305149754199815134059038386803327107954623997783328925014573712361190412041544730846393144970158584993932522919092961533807689663994273510181230611975,-2760322820547873699921094239708262618123220686640344280427532457964735913231839541155448488755106353058077772483391926518490758309421884945189004380274532339303673658136307214150768559915038249044318636340829040623019533080008795877188365713108541851533478868182315253939354465782006188226272150540248455533,539774532098344028178575637715654362402942864818067869426574212334581836029933543954242820122684669884416483020859433711413498388105161261765872011520166122694643001745601237406507189268543940858796801993814111596277340371144355358041455940732653675597524992815557778776692308187755956982584432604519599405036|48715243603698629821940426961114291788526831094737919680655564244368028434506892148169445801801507062147482077938401141271200004998443292904217897448972538551776558146708202066192286102689914350481841990540885514221263570815029978710961611989482704700171591369852446182654047272669614885074291437285365544460,15461979039278362276597154663342472093520340953601325231902305531667625678747495978358134272949704300055117324152966543774546452680787464009096008897144630532639259858616922948118805845884304673520502690819270668894425836172912196918903901652212033563796089034742441883378992888990103186375633458530164516317,112254170401540486949707124025758283679636240637378289192656933481574624585762302045534446659987957789349537165930984237831795400327841686426067814232036082567083362372524941094990583657803451112651533845361102072607539347050570081691100018981326399925221570110823787216043908322347678600920061436414622205345
|
||||
10024289314253109068181408824584907548682813194738591861732979563130066037537322274697443177137048505246344585833979570630525401656305713560413859208020518275537432959569499157916033857588787751319126726484190263493857704290501320067515311770609186057345956871152108834406551727855172143151298819670712846606,250504711193651543885319560950205973661493792695329060474635142907355144915197487552594082031949875905008463463563678142215091936373578313885813322111597330162926418717728507984924427400756505737871837782137693463723537653383553918621336520844369928180694979696895523967764933497235970432812594037072497051,715621301200572432492975207084152505969843326949635795107806123209445143151718517449817068713936125495042559248838811939558778417894618132276860461288711015473626724568542195567695133648202437411311798035098899324593482673311597084169133485553033610858821471717692594066324611630669968328053616507731719142856|10024289314253109068181408824584907548682813194738591861732979563130066037537322274697443177137048505246344585833979570630525401656305713560413859208020518275537432959569499157916033857588787751319126726484190263493857704290501320067515311770609186057345956871152108834406551727855172143151298819670712846606,250504711193651543885319560950205973661493792695329060474635142907355144915197487552594082031949875905008463463563678142215091936373578313885813322111597330162926418717728507984924427400756505737871837782137693463723537653383553918621336520844369928180694979696895523967764933497235970432812594037072497051,715621301200572432492975207084152505969843326949635795107806123209445143151718517449817068713936125495042559248838811939558778417894618132276860461288711015473626724568542195567695133648202437411311798035098899324593482673311597084169133485553033610858821471717692594066324611630669968328053616507731719142856|69691918841176288984823797473901681196094628879675315489755259444998436434953893357490252440851727841764856894926617359858762775119043951866997363697297297444653923770370354552225052699848341814307273549886449783549055935119439453155817735871573060612568620074695549908654214345458834165261842993120064731877,29396998803244259208706324369693841135210373137766178345587378836957006029896347992580130862460199303906902776177861781944189386331882004200746161097147483839158568813322086972498062377955537624817737605600339132204987534032119897113967273038860438816060235575010015500174845850861550917579850703027368690837,106032740697299793989572674990101926746114173477172287236417937947154096127701068054351010022541808717403069236123423199088480578855329299917113038220143550055260783011691574203288951873393089140671443554631887510834797278656898859315134431047639142121497581377857339388563046962362704012299890107532747273864
|
||||
10025428900225290685290151690469854982214932916715816521705584076773008242243937008766386881454192668460673460928145859037221457715710934570710912601758825277917537132977601878466722300639421318388444709119075347515835153260761313907776418189378977092187686581753209864749194659254262457796167519362282389944,8035407417908027120985682166291560102987169154314800046344974577695327891178900017914738842677039490694291401465931876496716613929624358740551659992744919248664062419629947961043318471204322567520912143542047278378993142962380418872588429956261466474640589358106914252999077869082097127384356318300378316515,526506212965607285294504652802203087863317784238837123201810456971631654056439372780456787465506517550858742170829690899565417756124817089047569475165769047941621936008499130409010932902058625548248971355379292220521819976269615165269965092960486278068237861168382524126578791019346639264332649030378056985183|10025428900225290685290151690469854982214932916715816521705584076773008242243937008766386881454192668460673460928145859037221457715710934570710912601758825277917537132977601878466722300639421318388444709119075347515835153260761313907776418189378977092187686581753209864749194659254262457796167519362282389944,8035407417908027120985682166291560102987169154314800046344974577695327891178900017914738842677039490694291401465931876496716613929624358740551659992744919248664062419629947961043318471204322567520912143542047278378993142962380418872588429956261466474640589358106914252999077869082097127384356318300378316515,526506212965607285294504652802203087863317784238837123201810456971631654056439372780456787465506517550858742170829690899565417756124817089047569475165769047941621936008499130409010932902058625548248971355379292220521819976269615165269965092960486278068237861168382524126578791019346639264332649030378056985183|22138319840700167895312881508181272807615611642960031764554010440709354488166777949391350577243475719290294812551529754345491786841502661934416467056115565617682227037416000132315258676326832664293472268496755124942179527934459542753167413348749025306046598965185451619481594689484505194124705909904529437016,-11131863740438194145696527360624732907005872365618169777307266620259512556501908857842536958655885195096195748687569086057992329814846073549253878495916056982261048696264863065937434987201822416655310303356962123778695372607503843603636308900759414300401601767853289915741229529512784406304245742359645877437,239100722014735247362237833086276623512072741916888955896402203382427372194255695065669877432592987292352301916479402236621014870053157629159394772682571609781590319296070407875820019520943129073048256367075297134176669670916790346961022995994025660850270895833918044332478002360056773821184240475743476227793
|
||||
10025696373056081323076067608649787757301021243808185859274808349280293058956119916709251366791092102112010300737183625444037192198725817688527600134257833611989912831501342672141015848343142445555687647450237725473967806277927764282835935236016323094913726640542283793306041765928288192544236949963888652742,-7551573577419239436071851881922105087510160439185121186338107875456959549550841973546977393389532111591614312842887678906809652876632858754122403767673808362967953534249136664179536748454994677273595591516700421480181975305574013927943181245218443636797391029556909610245497977668952560989113626530355626403,488551202347944315504020596344859283372184958565644254623325222360870646703286196267475027122265755221917465236349901297478448862017138325309245093096937651510172757567584161967211867376922683411877153052678659984267061266457787269417246896692832538104568250487618601354692837088103049130077128213591142309282|10025696373056081323076067608649787757301021243808185859274808349280293058956119916709251366791092102112010300737183625444037192198725817688527600134257833611989912831501342672141015848343142445555687647450237725473967806277927764282835935236016323094913726640542283793306041765928288192544236949963888652742,-7551573577419239436071851881922105087510160439185121186338107875456959549550841973546977393389532111591614312842887678906809652876632858754122403767673808362967953534249136664179536748454994677273595591516700421480181975305574013927943181245218443636797391029556909610245497977668952560989113626530355626403,488551202347944315504020596344859283372184958565644254623325222360870646703286196267475027122265755221917465236349901297478448862017138325309245093096937651510172757567584161967211867376922683411877153052678659984267061266457787269417246896692832538104568250487618601354692837088103049130077128213591142309282|60393031392510595353689024388979736338459176869905458858711562614756995826747740419365757994707737913997543366818386810567166008495382740947599739430340534765458717365457600414802742877973222192406990314478073640352910084093417199594859293029865969059185936671473103965892459853411850141569702842003428649274,38329753573953857590669151489102652306888210200689056278625104334993443543324622863340848043537460677248162565965074671978338401303611611484783137870568580776992301362308417714890643838644524909137849140837295996399799637901901974938629017550061052634048860038885099946489697555545683915123490961748882032563,86948805727102164020528697795654924433436758890959241635759391106001442581272485956111792521204085749386969011988358799013634480122996757146530322550896381169828204152724081141046858586814946327125019525970600049950459272456428386457599502469581747116784271717706447744628609754739530433937342398267975398266
|
||||
10025795277027889904587708106143218928217212795791943900096455901045016119560329143219194735847213817310006544292588010221295347093799623990992065640705758739633420740707391553060038825197435786302291280814741597987499076013530747593280825513696921556065232738339683658383829389180388637941998690144811369597,5684979695119467447669475199616030835217750876317308626399899267476547529035287916782085067945907170746605510283861183133612038067129245932165458949837306805149633974813244043762392619755476811530088171886491397765159164208502011381649757076514242464099478526057069033992519207091422655970324739132300656901,562007444349085595243678168150362315344210015071199683818344834829191775432825810670825147187078104135705553739701002486305372357596398874560795249464367016590567012959728033251032467564115881230202627660086530992291649152268041406000599974523312325932278194132351429623587227242904398909856612628818780435778|10025795277027889904587708106143218928217212795791943900096455901045016119560329143219194735847213817310006544292588010221295347093799623990992065640705758739633420740707391553060038825197435786302291280814741597987499076013530747593280825513696921556065232738339683658383829389180388637941998690144811369597,5684979695119467447669475199616030835217750876317308626399899267476547529035287916782085067945907170746605510283861183133612038067129245932165458949837306805149633974813244043762392619755476811530088171886491397765159164208502011381649757076514242464099478526057069033992519207091422655970324739132300656901,562007444349085595243678168150362315344210015071199683818344834829191775432825810670825147187078104135705553739701002486305372357596398874560795249464367016590567012959728033251032467564115881230202627660086530992291649152268041406000599974523312325932278194132351429623587227242904398909856612628818780435778|21268893649707309919570226960346372728495718162766890279898665692070832053021527941744710318344298178920800948932846738089018664772788493927580517099544523821251022066659574678369202749060209753445042621950578890219002532761197990179516522502045501310564866950615799259252489912339574839719060814022687315833,-16974163508967143175633640446755920949410222455507178592573412674696095005693865169009177473634493301741992193686041205183814819978515841920175784743689108590732720018205453159865088935842801461210617037675036778351747079803439546961298001090840400908639940207556458714733757110771041917290102952953525885901,267927541659497862467954399158595317217757334505550228883969422271210761133505257969057962914766286654857630940214532971487737583736851759345565614399969808206018020458924660929875641469250964043761370010683938550578868703713683401770700995854517531350144574746588257756156838858326386968013405064043171677102
|
||||
10027231464587935675639730747678568553908782143975994882531107664457436183429164280181747996889942331170488347016005448660418260392761004178712470722876674735769717730721096608074660784751458654872470573207263246635112395824536847938300087322544843942058256547417838850894365569811278659238183569174057618461,-4440267082761131414853294025879558077404333378765096794740543986499915534978609296838455472705453725784503668845242671918380807204902116758601260037461056825902249629220350908043324356588944839161111532952326818438147003761862650635018374512533491039199092599100710336766544058009407418500582600655649176731,648644865497954786776779349508457974872894617589720812073415733603605246322174185807123848556285887617844905639166726609275182111944451202589938026255239735903760010573449137429043799240258539000988138770732321918291392488327546867698375214486961050410251228096630089455328472100573545758827677160537099320072|10027231464587935675639730747678568553908782143975994882531107664457436183429164280181747996889942331170488347016005448660418260392761004178712470722876674735769717730721096608074660784751458654872470573207263246635112395824536847938300087322544843942058256547417838850894365569811278659238183569174057618461,-4440267082761131414853294025879558077404333378765096794740543986499915534978609296838455472705453725784503668845242671918380807204902116758601260037461056825902249629220350908043324356588944839161111532952326818438147003761862650635018374512533491039199092599100710336766544058009407418500582600655649176731,648644865497954786776779349508457974872894617589720812073415733603605246322174185807123848556285887617844905639166726609275182111944451202589938026255239735903760010573449137429043799240258539000988138770732321918291392488327546867698375214486961050410251228096630089455328472100573545758827677160537099320072|46009921711915221172675762660378602913284935911769009327398886576025556944392570855250807675821524214292205195685897041743100957229886916848065466280285331142834500895832407569582736664860239313946858454701727263963934792933919730548918244937925570913918752904708052633399310307728141781833372082621654521012,23113475896105025107394605331889841460333790037514477610982037645403180016015663190091781841332002225731097821541822074963875072814544317858697958764287783670995655541483455486482934375887626558700537105583870368524253911345190227270218382103667348149461739557925536602713765457923023851021682724701425292285,144158936962616263074854848511540730235089365933518189341717329619972562457005307870230026030935456404849352326770086269924745439466300887545713518178631945541398236558781981355199214433550895067837895099984050382102279411033270720567051341019780619857285120976043103941344405749600962507460384488305160927409
|
||||
10028350739307738239553437040783010537831658077620987335136512740169676263676747904072610524038617826531776850363823183733316438383606013506243196250082245650509414494066287488240898643357609392647649696817421880362011995934355791054933802156008906495889209763185641418699747996844644309107005112769042124318,-8707724909729199988066303291337645249173793540898282778024990496827621579508639942367666079187451324678862416133361451354021503910330702173658524643590899178624105480074443491370735876152164927759833250717689047284841393067105491783984924710355073809596596309834373465404107419929383484013294580151001556205,709758849546988349416271112886481225556022674837057904210411294800853958134290458192748393663317224087035819308413648727887254453418237510262143014913358121419251454923066768843049946946235581252429358021933518874438830803109875124372809973223871915099838973789742920465584130081571378073407884375094121268086|75318449301263415467735932548665333631833209464496019863964846786179367552717568503501179580307848690931127517090493242442668414948431300766436151276701082711193885234526326365772794857402011587084042826807831628195071551088506032974178171732912459672450935320336391563419572190330442739927553072512433668492,-37666884930926310053453757600840503983118095033807980727340808659295811653448510252245931091899049389573453471548035871058367468721695376360491358764096189091201995027259909431928638716214539254513869701208949761595174662474754859884399931318260163661631099379190898913272807941135716989109599181870658955411,98959195118263740892956000993748226884659367220332828268929254332674345256309662055166848715197441404549693155497652798902798133883715701424760429622411156195661335500009744018343869593442437677434882815576040667549098187431048868332096738149061496080175268157896224795266747997461998351291015430290846127991|78879828918733154172761232408717349879484411577276118445906917725867063887736403698268620449039366903222875325557071665537210036919488537356651491469585633888702020869953229589162929365722510146484615161939420331780149558523973332122378453822513488024388432239153051455307708434618917487055946350509115159954,76022832032228931560745697540761625684085285731069434889900171934534714627230254695020398894919788417337545845925550378316932977023401785630385785258013781974664129868656557307645950862628223235191878262315897562597443878541677560567949780990105397727409041603839660905756066382442879369790583798789010488305,108311876812780092185464248430819211209817518273155531596997245418001592611818208219323720419932959536655772814492616252593108875759365327114882816039706034356112007450695439375062874008822159624139628714241658551452565287963490475631456873365249553095821106476912177956653681222238113836907581862856535718737
|
||||
10028851844651833483859929571953137249991455639548429827963027247884276614126582614765754168788406967864569784762670102265610798647378386836840906226432130520069813697908016956233348000504802826879321612396642793367212498698674853695626535119160503473498038239103440516242421347929877540717111105756485685416,2125595786027029524418010744012416366895751257304333344547068089057782417304598028459234751630103098379533864111162338454453990302791615035666668646880454521909199231924063610130346480860493194786475025500179927152042631414216166076205706865335089506746163544867373884186074330874303125032398057106297186863,800913161978634698742609378449357774955505407483415355913501780948951093468088505693408572348493350961801168010893237963412292289122055848739177106855852125098292236006510856110523212361731635197072591774393685461794786770421350652687522647241859653967881884006552182286419954577117744245767788677817306762852|50429916262905224121199165505326103712322633321578675412441680250060233972857110270845245669993781820897616267433177701631160063889458653764653687193369398981186203131244488744056545097485284912257268749768458331368107477031080466529105477483573960360042156349879055924595032652993263006931935621163071940669,-27065457947223595691396496360583757525811978893552969421355220262690251856919447274985744020030753772138102799000695707517100290349316439468276434701083568894717249805760937039437729313480400330251378090593495078991541936054800615447964857892934462412215184000258243195317080477356913381022045983896051265339,162884360410278142867611075754290453359699000687335791914852080089316910769333692647979960993562595617317591055325367385753910502341805589561432506963888415490402296553372275035046411345233183682360113909981999769321373626395576042577426393704313732652524189312065702142816306042456646293512481995292218184630|53997723292458827021420578276444072896002053124414909531202213558828743141566632795132611868503445251027453958158504792518315802051451653007369750551307662332396699632827748059470875485288011830316694909885816703989889585271656952405885761371722676008299809654786389827849524552375005490619782071967768476620,-3921961296864439599504210025762424797468664702267290731411285739993844771294339132594454147684650522033462891630908841344585194018116919380259122700777039543903609394837238783496880317096351827072103366260798880944073390853134441762823497871536553346031444078137460262118850735234076150428857645894786599751,148801743068668131617014767083337764289837422117725728166091414005082627848729316116752646484455568027336119364510594603975358934000097718262611755893849397982664596027513725455266261222215386005085253076887565120162601272630243587251846986242350641739720550891898677287459766121608903079025422071040317411427
|
||||
10029389724354647916501896404393742667486460299990236556418317010668116357688170330436730152626311842309710400719826928488284825527027730454134618086311842571929328216480439284941404499751921093227604323134474990591797348436817566328316099817073417778247297081309102907064789976846493401165211794614652077581,-5748548483444797737722189452249937786310843486604864328602367281135708748614533947090219774019556230317272055169227525539578087511031078860820692360107715435130140444616499305586047090927584090418666083007681585523416727535418733837425822999564006750813702161869964846496575730545650729911357481033875975819,719895727819428792994563756994341424767785889195228293344753744212732679301708252203825226413012156273021174986595157595824763180256881701588113889797640827369987995936500880423386237711358833858185065722206691788564039408747808726964665919487597212670306097386648373066512338291830265434985728533154609458396|10029389724354647916501896404393742667486460299990236556418317010668116357688170330436730152626311842309710400719826928488284825527027730454134618086311842571929328216480439284941404499751921093227604323134474990591797348436817566328316099817073417778247297081309102907064789976846493401165211794614652077581,-5748548483444797737722189452249937786310843486604864328602367281135708748614533947090219774019556230317272055169227525539578087511031078860820692360107715435130140444616499305586047090927584090418666083007681585523416727535418733837425822999564006750813702161869964846496575730545650729911357481033875975819,719895727819428792994563756994341424767785889195228293344753744212732679301708252203825226413012156273021174986595157595824763180256881701588113889797640827369987995936500880423386237711358833858185065722206691788564039408747808726964665919487597212670306097386648373066512338291830265434985728533154609458396|8560998041202342563145796199673331908087223591151890019844277290088279806853407215903188817680041281745686724901293662893322531582604865370359246593736212994518909947445852055733198112706083016676348016714291995623917124402224705247934604030962953619706293397331305385867121828720733169551586472433525366937,-537975643989974344334263003423538768209474800355518283566587248897859525466409192148505701554962331296631250873445941844817525452815362174465113061273994639614043454341045805645253425898526417994404807933232055819444976823823121190979410608683098711316112363065614462414343124780847750195760827288806749811,842416466225224033183393216850362224780744722633748075411867357471068659147784175969996596348967969848559647034288532517371764252498077837862667546193299637156461175039504339023851201930547252305821527420041035325847162633397442876512610187216200063222815713605031344575281997919080197584636819283493689893368
|
||||
10029462828108406279939177067115161395010840703955688660855251935920272008672857135011101256731718086932191566776707625465927083826902687987460773347952918706606341231446896979494902183159052228641287627294356517943283997224691515527031637969828335115038316970291491432668820800917926368076854280638205187309,-6629646230072911423556297764360629625589965368903862583111147478898388162363395818084398589541887766856708633717083099875720612184669212924373539095145308857941719336023981955297255371765324592355503775749174475673743444341624220885937903545914339945102711106579165895756968511409705213351719512183267438507,782742743661597372172423816386424221021017552503284524697466177183281891845425353410464186233869636520966594583971179297268228166989165546064661406781232750204176842910595282543729669785450570724055031796400642778914378223882150571438409693254554219540729724954243581265311980228274664427499269984624348473720|10029462828108406279939177067115161395010840703955688660855251935920272008672857135011101256731718086932191566776707625465927083826902687987460773347952918706606341231446896979494902183159052228641287627294356517943283997224691515527031637969828335115038316970291491432668820800917926368076854280638205187309,-6629646230072911423556297764360629625589965368903862583111147478898388162363395818084398589541887766856708633717083099875720612184669212924373539095145308857941719336023981955297255371765324592355503775749174475673743444341624220885937903545914339945102711106579165895756968511409705213351719512183267438507,782742743661597372172423816386424221021017552503284524697466177183281891845425353410464186233869636520966594583971179297268228166989165546064661406781232750204176842910595282543729669785450570724055031796400642778914378223882150571438409693254554219540729724954243581265311980228274664427499269984624348473720|78667156036256111077611624900655903416490936286908879028793529978954307476546731244382117972535629204391216663640753691624585098486838208251820032478479477157140644001833697695041181016581251701307504852404041540782811897181398727717806959310986773271700555774873273014053192416692372242335858566589217791557,-11681938670990905592355073596188490162953864508666802257304897456361955348551384361326321552281799532866414312577544184561189074950098884814900830627703536569755802878449922371901033061871486784064588452214883192668082672979794267084922475962025561930112420060063420934779749780994794637529679089941387143427,100087743332058471063169855843669770171915090829420561680411008586982501053400685795132793033729482971332564612241450018617179058547543051543609602249472699027915450803902552375241387388609502154707845080333148480015751381946173697011349301767118798190494650916047348538729674905622316757245591467381527471900
|
46
crates/vdf/Cargo.toml
Normal file
46
crates/vdf/Cargo.toml
Normal file
@ -0,0 +1,46 @@
|
||||
# Copyright 2018 POA Networks Ltd.
|
||||
#
|
||||
# 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
|
||||
# and limitations under the License.
|
||||
[package]
|
||||
name = "vdf"
|
||||
version = "0.1.0"
|
||||
authors = ["Demi M. Obenour <demiobenour@gmail.com>"]
|
||||
readme = "README.md"
|
||||
keywords = ["vdf", "classgroup", "crypto", "cryptography"]
|
||||
repository = "https://github.com/poanetwork/vdf"
|
||||
license = "Apache-2.0"
|
||||
edition = "2018"
|
||||
description = "An implementation of Verifiable Delay Functions (VDFs) in Rust"
|
||||
|
||||
[lib]
|
||||
crate-type = ["lib", "staticlib"]
|
||||
name = "vdf"
|
||||
|
||||
[dependencies]
|
||||
classgroup = { path = "../classgroup", version = "^0.1.0" }
|
||||
num-traits = "0.2"
|
||||
sha2 = "0.8"
|
||||
bit-vec = "0.5"
|
||||
uniffi = { version= "0.25", features = ["cli"]}
|
||||
|
||||
[build-dependencies]
|
||||
uniffi = { version = "0.25", features = [ "build" ] }
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = ">=0.2"
|
||||
hex = "0.3"
|
||||
|
||||
[[bench]]
|
||||
name = "classgroup-bench"
|
||||
harness = false
|
||||
path = "bench/bench.rs"
|
223
crates/vdf/README.md
Normal file
223
crates/vdf/README.md
Normal file
@ -0,0 +1,223 @@
|
||||
# Verifiable Delay Function (VDF) Implementation in Rust
|
||||
|
||||
## What is a VDF?
|
||||
|
||||
A Verifiable Delay Function (VDF) is a function that requires substantial time
|
||||
to evaluate (even with a polynomial number of parallel processors) but can be
|
||||
very quickly verified as correct. VDFs can be used to construct randomness
|
||||
beacons with multiple applications in a distributed network environment. By
|
||||
introducing a time delay during evaluation, VDFs prevent malicious actors from
|
||||
influencing output. The output cannot be differentiated from a random number
|
||||
until the final result is computed. See <https://eprint.iacr.org/2018/712.pdf>
|
||||
for more details.
|
||||
|
||||
## Description
|
||||
|
||||
This VDF implementation is written in Rust. The GMP library is used for
|
||||
arithmetic and greatest common divisor (GCD) calculations. We use class groups
|
||||
to implement the approaches described in the following papers:
|
||||
|
||||
1. [Simple Verifiable Delay Functions](https://eprint.iacr.org/2018/627.pdf). Pietrzak, 2018
|
||||
2. [Efficient Verifiable Delay Functions](https://eprint.iacr.org/2018/623.pdf). Wesolowski, 2018
|
||||
|
||||
The chosen generator is (2, 1, c), where c is calculated from the provided
|
||||
discriminant. A form is represented internally (a, b, c), with the
|
||||
discriminant not being used in most omputations. This implementation performs
|
||||
reduction is performed after every multiplication and squaring, as not doing so
|
||||
did not give any gains in our benchmarks.
|
||||
|
||||
|
||||
This repo includes three crates:
|
||||
|
||||
* `classgroup`: a class group implementation, as well as a trait for class
|
||||
groups.
|
||||
* `vdf`: a Verifyable Delay Function (VDF) trait, as well as an
|
||||
implementation of that trait.
|
||||
* `vdf-cli`: a command-line interface to the vdf crate. It also includes
|
||||
additional commands, which are deprecated and will be replaced by a CLI to
|
||||
the classgroup crate.
|
||||
|
||||
## Usage
|
||||
|
||||
- Install [Rust]. We (POA Networks) have tested the code with the latest
|
||||
stable, beta, and nightly versions of Rust. It may work with older
|
||||
versions, but this is not guaranteed.
|
||||
- Install the [GNU Multiple Precision Library](https://gmplib.org/)
|
||||
* On Debian and derivatives (including Ubuntu):
|
||||
```sh
|
||||
$ sudo apt-get install -y libgmp-dev
|
||||
```
|
||||
* On Red Hat and derivatives (Fedora, CentOS)
|
||||
```sh
|
||||
$ sudo dnf -y install gmp-devel
|
||||
```
|
||||
- Download and prepare the repository
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/poanetwork/vdf.git
|
||||
$ cargo install --path=vdf-cli
|
||||
$ # or for the competition binary
|
||||
$ cargo install --path=vdf-competition
|
||||
```
|
||||
|
||||
### Command Line Interface
|
||||
|
||||
To initiate, use the `vdf-cli` command followed by 2 arguments:
|
||||
|
||||
- _challenge_: byte string of arbitrary length
|
||||
- _difficulty_: number of iterations, each iteration requires more time to evaluate
|
||||
|
||||
This generates the Weslowski proof of time. To generate the Pietrzak proof of
|
||||
time, pass `-tpietrzak`. For detailed usage information, run `vdf-cli --help`.
|
||||
|
||||
Once complete you will see the output, returned as a `Vec<u8>`. The CLI tool
|
||||
hex-encodes its output.
|
||||
|
||||
**Example**
|
||||
|
||||
```sh
|
||||
$ vdf-cli aa 100
|
||||
005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
|
||||
```
|
||||
|
||||
To verify, use the `vdi-cli` command with the same arguments and include the
|
||||
output.
|
||||
|
||||
**Example**
|
||||
|
||||
```sh
|
||||
$ vdf-cli aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
|
||||
Proof is valid
|
||||
```
|
||||
### VDF Library
|
||||
|
||||
<!--
|
||||
Keep as is, and possibly include argument explanations as well (for byte_length for example). May not be needed though is CLI is main user interaction tool.
|
||||
-->
|
||||
|
||||
```rust
|
||||
extern crate vdf;
|
||||
use vdf::{InvalidProof, PietrzakVDFParams, VDFParams, WesolowskiVDFParams, VDF};
|
||||
|
||||
/// The correct solution.
|
||||
const CORRECT_SOLUTION: &[u8] =
|
||||
b"\x00\x52\x71\xe8\xf9\xab\x2e\xb8\xa2\x90\x6e\x85\x1d\xfc\xb5\x54\x2e\x41\x73\xf0\x16\
|
||||
\xb8\x5e\x29\xd4\x81\xa1\x08\xdc\x82\xed\x3b\x3f\x97\x93\x7b\x7a\xa8\x24\x80\x11\x38\
|
||||
\xd1\x77\x1d\xea\x8d\xae\x2f\x63\x97\xe7\x6a\x80\x61\x3a\xfd\xa3\x0f\x2c\x30\xa3\x4b\
|
||||
\x04\x0b\xaa\xaf\xe7\x6d\x57\x07\xd6\x86\x89\x19\x3e\x5d\x21\x18\x33\xb3\x72\xa6\xa4\
|
||||
\x59\x1a\xbb\x88\xe2\xe7\xf2\xf5\xa5\xec\x81\x8b\x57\x07\xb8\x6b\x8b\x2c\x49\x5c\xa1\
|
||||
\x58\x1c\x17\x91\x68\x50\x9e\x35\x93\xf9\xa1\x68\x79\x62\x0a\x4d\xc4\xe9\x07\xdf\x45\
|
||||
\x2e\x8d\xd0\xff\xc4\xf1\x99\x82\x5f\x54\xec\x70\x47\x2c\xc0\x61\xf2\x2e\xb5\x4c\x48\
|
||||
\xd6\xaa\x5a\xf3\xea\x37\x5a\x39\x2a\xc7\x72\x94\xe2\xd9\x55\xdd\xe1\xd1\x02\xae\x2a\
|
||||
\xce\x49\x42\x93\x49\x2d\x31\xcf\xf2\x19\x44\xa8\xbc\xb4\x60\x89\x93\x06\x5c\x9a\x00\
|
||||
\x29\x2e\x8d\x3f\x46\x04\xe7\x46\x5b\x4e\xee\xfb\x49\x4f\x5b\xea\x10\x2d\xb3\x43\xbb\
|
||||
\x61\xc5\xa1\x5c\x7b\xdf\x28\x82\x06\x88\x5c\x13\x0f\xa1\xf2\xd8\x6b\xf5\xe4\x63\x4f\
|
||||
\xdc\x42\x16\xbc\x16\xef\x7d\xac\x97\x0b\x0e\xe4\x6d\x69\x41\x6f\x9a\x9a\xce\xe6\x51\
|
||||
\xd1\x58\xac\x64\x91\x5b";
|
||||
fn main() {
|
||||
// The length of the prime numbers generated, in bits.
|
||||
let num_bits: u16 = 2048;
|
||||
|
||||
// An instance of the VDF. Instances can be used arbitrarily many times.
|
||||
let pietrzak_vdf = PietrzakVDFParams(num_bits).new();
|
||||
|
||||
// Solve for the correct answer. This will take a minute or two.
|
||||
assert_eq!(
|
||||
&pietrzak_vdf.solve(b"\xaa", 10000).unwrap()[..],
|
||||
CORRECT_SOLUTION
|
||||
);
|
||||
|
||||
// Verify the answer. This should be far faster (less than a second).
|
||||
assert!(pietrzak_vdf.verify(b"\xaa", 10000, CORRECT_SOLUTION).is_ok());
|
||||
}
|
||||
```
|
||||
|
||||
## Benchmarks
|
||||
|
||||
Benchmarks are provided for the classgroup operations. To run benchmarks:
|
||||
|
||||
```sh
|
||||
$ ./bench.sh <your challenge here>
|
||||
```
|
||||
|
||||
Additional benchmarks are under development.
|
||||
|
||||
### Current Benchmarks
|
||||
|
||||
These were generated by `./bench.sh aadf`. Outliers could be due to preemption
|
||||
by the OS and/or hypervisor. Changes are relative to the previous test run
|
||||
done on the same machine. Since the previous run was done with different
|
||||
settings and/or code than reported here, these changes are not meaningful.
|
||||
|
||||
```text
|
||||
Benchmarking square with seed aadf: 512: Collecting 100 samples in estimated 5.0439 s (374k iteratio square with seed aadf: 512
|
||||
time: [13.301 us 13.333 us 13.372 us]
|
||||
change: [-22.286% -21.745% -21.225%] (p = 0.00 < 0.05)
|
||||
Performance has improved.
|
||||
Found 22 outliers among 100 measurements (22.00%)
|
||||
5 (5.00%) high mild
|
||||
17 (17.00%) high severe
|
||||
|
||||
Benchmarking multiply with seed aadf: 512: Collecting 100 samples in estimated 5.0452 s (293k iterat multiply with seed aadf: 512
|
||||
time: [17.219 us 17.251 us 17.287 us]
|
||||
change: [-24.323% -23.739% -23.149%] (p = 0.00 < 0.05)
|
||||
Performance has improved.
|
||||
Found 10 outliers among 100 measurements (10.00%)
|
||||
4 (4.00%) high mild
|
||||
6 (6.00%) high severe
|
||||
|
||||
Benchmarking square with seed aadf: 1024: Collecting 100 samples in estimated 5.0822 s (177k iterati square with seed aadf: 1024
|
||||
time: [28.672 us 28.716 us 28.767 us]
|
||||
change: [-29.947% -29.339% -28.708%] (p = 0.00 < 0.05)
|
||||
Performance has improved.
|
||||
Found 8 outliers among 100 measurements (8.00%)
|
||||
1 (1.00%) low mild
|
||||
1 (1.00%) high mild
|
||||
6 (6.00%) high severe
|
||||
|
||||
Benchmarking multiply with seed aadf: 1024: Collecting 100 samples in estimated 5.0886 s (136k itera multiply with seed aadf: 1024
|
||||
time: [37.163 us 37.207 us 37.254 us]
|
||||
change: [-21.403% -20.750% -20.170%] (p = 0.00 < 0.05)
|
||||
Performance has improved.
|
||||
Found 8 outliers among 100 measurements (8.00%)
|
||||
1 (1.00%) low mild
|
||||
1 (1.00%) high mild
|
||||
6 (6.00%) high severe
|
||||
|
||||
Benchmarking square with seed aadf: 2048: Collecting 100 samples in estimated 5.2519 s (76k iteratio square with seed aadf: 2048
|
||||
time: [69.115 us 69.254 us 69.430 us]
|
||||
change: [-28.091% -27.738% -27.341%] (p = 0.00 < 0.05)
|
||||
Performance has improved.
|
||||
Found 8 outliers among 100 measurements (8.00%)
|
||||
1 (1.00%) low mild
|
||||
1 (1.00%) high mild
|
||||
6 (6.00%) high severe
|
||||
|
||||
Benchmarking multiply with seed aadf: 2048: Collecting 100 samples in estimated 5.0554 s (56k iterat multiply with seed aadf: 2048
|
||||
time: [90.922 us 91.057 us 91.201 us]
|
||||
change: [-25.236% -24.794% -24.336%] (p = 0.00 < 0.05)
|
||||
Performance has improved.
|
||||
Found 13 outliers among 100 measurements (13.00%)
|
||||
2 (2.00%) low mild
|
||||
5 (5.00%) high mild
|
||||
6 (6.00%) high severe
|
||||
```
|
||||
|
||||
[Rust]: <https://doc.rust-lang.org/cargo/getting-started/installation.html>
|
||||
|
||||
|
||||
## License
|
||||
|
||||
Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
|
||||
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.
|
54
crates/vdf/bench/bench.rs
Normal file
54
crates/vdf/bench/bench.rs
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright 2018 POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
#[macro_use]
|
||||
extern crate criterion;
|
||||
|
||||
use hex;
|
||||
|
||||
use classgroup::{gmp_classgroup::GmpClassGroup, ClassGroup};
|
||||
use criterion::Criterion;
|
||||
use std::{cell::RefCell, env, rc::Rc};
|
||||
use vdf::create_discriminant;
|
||||
fn bench_square(c: &mut Criterion) {
|
||||
let bench_params = |c: &mut Criterion, len: u16, seed: &[u8]| {
|
||||
let i = Rc::new(RefCell::new(GmpClassGroup::generator_for_discriminant(
|
||||
create_discriminant(seed, len),
|
||||
)));
|
||||
{
|
||||
let i = i.clone();
|
||||
c.bench_function(
|
||||
&format!("square with seed {}: {}", hex::encode(seed), len),
|
||||
move |b| b.iter(|| i.borrow_mut().square()),
|
||||
);
|
||||
}
|
||||
{
|
||||
let multiplier = i.borrow().clone();
|
||||
c.bench_function(
|
||||
&format!("multiply with seed {}: {}", hex::encode(seed), len),
|
||||
move |b| b.iter(|| *i.borrow_mut() *= &multiplier),
|
||||
);
|
||||
}
|
||||
};
|
||||
let seed = env::var("VDF_BENCHMARK_SEED")
|
||||
.ok()
|
||||
.and_then(|x| hex::decode(x).ok())
|
||||
.expect("bug in calling script");
|
||||
for &i in &[512, 1024, 2048] {
|
||||
bench_params(c, i, &seed)
|
||||
}
|
||||
}
|
||||
|
||||
criterion_group!(benches, bench_square);
|
||||
criterion_main!(benches);
|
115
crates/vdf/build.rs
Normal file
115
crates/vdf/build.rs
Normal file
@ -0,0 +1,115 @@
|
||||
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
use std::{env, fs::File, io::Write, path::PathBuf, u16};
|
||||
|
||||
/// The number of odd primes less than 65536.
|
||||
const PRIMES_LEN: usize = 6541;
|
||||
|
||||
/// The number of integers that are:
|
||||
///
|
||||
/// * equal to 7 mod 8
|
||||
/// * not divisible by any prime number less than or equal to 13.
|
||||
/// * less than 8 * 3 * 5 * 7 * 11 * 13
|
||||
const RESIDUES_LEN: usize = 5760;
|
||||
|
||||
/// The number of odd prime numbers between 13 and 65536 exclusive.
|
||||
const SIEVE_INFO_LEN: usize = PRIMES_LEN - 5;
|
||||
|
||||
fn odd_primes_below_65536() -> Vec<usize> {
|
||||
const N: usize = 1 << 16;
|
||||
let mut sieve = vec![true; N >> 1];
|
||||
let mut q = (N as f64).powf(0.5) as usize;
|
||||
assert!(q * q <= N);
|
||||
q += 1;
|
||||
assert!(q * q > N);
|
||||
for i in (3..q).step_by(2) {
|
||||
if sieve[i >> 1] {
|
||||
for i in ((i * i >> 1)..sieve.len()).step_by(i) {
|
||||
sieve[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// mega cheat ― we know the exact size of this vector
|
||||
let res: Vec<_> = (1..N / 2)
|
||||
.filter(|&i| sieve[i])
|
||||
.map(|i| 2 * i + 1)
|
||||
.collect();
|
||||
assert_eq!(res.len(), PRIMES_LEN);
|
||||
res
|
||||
}
|
||||
|
||||
fn mod_exponentiation(base: usize, exponent: usize, modulus: usize) -> usize {
|
||||
assert!(base < u16::MAX.into());
|
||||
assert!(exponent < u16::MAX.into());
|
||||
assert!(modulus < u16::MAX.into());
|
||||
let (mut base, mut exponent, modulus) = (base as u32, exponent as u32, modulus as u32);
|
||||
let mut state = 1;
|
||||
loop {
|
||||
if exponent & 1 != 0 {
|
||||
state *= base;
|
||||
state %= modulus;
|
||||
}
|
||||
exponent >>= 1;
|
||||
if exponent == 0 {
|
||||
return state as _;
|
||||
}
|
||||
base *= base;
|
||||
base %= modulus;
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! const_fmt {
|
||||
() => {
|
||||
"#[allow(warnings)]\nconst {}: [{}; {}] = {:#?};\n\n";
|
||||
};
|
||||
}
|
||||
|
||||
/// A product of many small prime numbers. We precompute the numbers between
|
||||
/// `1` and `M` that are coprime to `M`. Any number whose residue modulo `M` is
|
||||
/// one of these is not divisible by any of the prime factors of `M`. This
|
||||
/// speeds up the generation of random prime numbers.
|
||||
const M: usize = 8 * 3 * 5 * 7 * 11 * 13;
|
||||
fn emit<T: std::fmt::Debug>(f: &mut dyn Write, name: &str, t: &str, obj: &[T]) {
|
||||
write!(f, const_fmt!(), name, t, obj.len(), obj).expect("i/o error in build script");
|
||||
}
|
||||
|
||||
/// Write the generated code to `f`.
|
||||
fn generate(f: &mut dyn Write) {
|
||||
write!(f, "const M: u32 = 8 * 3 * 5 * 7 * 11 * 13;\n\n").expect("i/o error");
|
||||
let residues: Vec<usize> = {
|
||||
let primes = [3, 5, 7, 11, 13];
|
||||
let not_divisible = |&x: &usize| primes.iter().all(|p| x % p != 0);
|
||||
(7..M).step_by(8).filter(not_divisible).collect()
|
||||
};
|
||||
assert_eq!(residues.len(), RESIDUES_LEN);
|
||||
emit(f, "RESIDUES", "u32", &residues[..]);
|
||||
let sieve_info: Vec<(usize, usize)> = odd_primes_below_65536()[5..]
|
||||
.iter()
|
||||
.map(|&i| (i, mod_exponentiation(M % i, i - 2, i)))
|
||||
.collect();
|
||||
assert_eq!(sieve_info.len(), SIEVE_INFO_LEN);
|
||||
emit(f, "SIEVE_INFO", "(u16, u16)", &sieve_info[..]);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
println!("cargo:rerun-if-changed=build.rs");
|
||||
|
||||
uniffi::generate_scaffolding("src/lib.udl").expect("uniffi generation failed");
|
||||
|
||||
let manifest_path = env::var("OUT_DIR").expect("cargo should have set this");
|
||||
let mut path = PathBuf::from(&manifest_path);
|
||||
path.push("constants.rs");
|
||||
let mut f = File::create(path).expect("cannot create constants.rs");
|
||||
generate(&mut f);
|
||||
}
|
199
crates/vdf/src/create_discriminant.rs
Normal file
199
crates/vdf/src/create_discriminant.rs
Normal file
@ -0,0 +1,199 @@
|
||||
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
//! Creation of discriminants.
|
||||
//!
|
||||
//! The [`pot`] tool does not accept a discriminant as a command-line argument.
|
||||
//! Instead, we generate the discriminant from a (much smaller) seed.
|
||||
//!
|
||||
//! For performance, we follow the Chia network's [`inkfish`] implementation
|
||||
//! of ["Close to Uniform Prime Number Generation With Fewer Random Bits"][1]
|
||||
//! by Pierre-Alain Fouque and Mehdi Tibouchi.
|
||||
//! We employ a table of precomputed constants generated by `build.rs`.
|
||||
//!
|
||||
//! [1]: https://eprint.iacr.org/2011/481.pdf
|
||||
//! [`inkfish`]: <https://github.com/Chia-Network/vdf-competition/blob/003b0d202d3b27058159f7a3f6a838e312e7d79e/inkfish/create_discriminant.py>
|
||||
//! [`pot`]: <https://github.com/Chia-Network/vdf-competition/blob/003b0d202d3b27058159f7a3f6a838e312e7d79e/inkfish/cmds.py>
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/constants.rs"));
|
||||
|
||||
use classgroup::BigNumExt;
|
||||
use num_traits::Zero;
|
||||
use sha2::{digest::FixedOutput, Digest, Sha256};
|
||||
use std::u16;
|
||||
|
||||
fn random_bytes_from_seed(seed: &[u8], byte_count: usize) -> Vec<u8> {
|
||||
assert!(byte_count <= 32 * ((1 << 16) - 1));
|
||||
let mut blob = Vec::with_capacity(byte_count);
|
||||
let mut extra: u16 = 0;
|
||||
while blob.len() < byte_count {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.input(seed);
|
||||
let extra_bits: [u8; 2] = [((extra & 0xFF00) >> 8) as _, (extra & 0xFF) as _];
|
||||
hasher.input(&extra_bits);
|
||||
blob.extend_from_slice(&hasher.fixed_result()[..]);
|
||||
extra += 1;
|
||||
}
|
||||
blob.resize(byte_count, 0);
|
||||
blob
|
||||
}
|
||||
|
||||
/// Create a discriminant from a seed (a byte string) and a bit length (a
|
||||
/// `u16`). The discriminant is guaranteed to be a negative prime number that
|
||||
/// fits in `length` bits, except with negligible probability (less than
|
||||
/// 2^(-100)). It is also guaranteed to equal 7 modulo 8.
|
||||
///
|
||||
/// This function uses sha256 to expand the seed. Therefore, different seeds
|
||||
/// will result in completely different discriminants with overwhelming
|
||||
/// probability, unless `length` is very small. However, this function is
|
||||
/// deterministic: if it is called twice with identical seeds and lengths, it
|
||||
/// will always return the same discriminant.
|
||||
///
|
||||
/// This function is guaranteed not to panic for any inputs whatsoever, unless
|
||||
/// memory allocation fails and the allocator in use panics in that case.
|
||||
pub fn create_discriminant<T: BigNumExt>(seed: &[u8], length: u16) -> T {
|
||||
let (mut n, residue) = {
|
||||
// The number of “extra” bits (that don’t evenly fit in a byte)
|
||||
let extra: u8 = (length as u8) & 7;
|
||||
|
||||
// The number of random bytes needed (the number of bytes that hold `length`
|
||||
// bits, plus 2).
|
||||
let random_bytes_len = ((usize::from(length) + 7) >> 3) + 2;
|
||||
let random_bytes = random_bytes_from_seed(seed, random_bytes_len);
|
||||
let (n, last_2) = random_bytes.split_at(random_bytes_len - 2);
|
||||
let numerator = (usize::from(last_2[0]) << 8) + usize::from(last_2[1]);
|
||||
|
||||
// If there are any extra bits, right shift `n` so that it fits
|
||||
// in `length` bits, discarding the least significant bits.
|
||||
let n = T::from(n) >> usize::from((8 - extra) & 7);
|
||||
(n, RESIDUES[numerator % RESIDUES.len()])
|
||||
};
|
||||
n.setbit(usize::from(length - 1));
|
||||
debug_assert!(n >= Zero::zero());
|
||||
let rem = n.frem_u32(M);
|
||||
|
||||
// HACK HACK `rust-gmp` doesn’t expose += and -= with i32 or i64
|
||||
if residue > rem {
|
||||
n = n + u64::from(residue - rem);
|
||||
} else {
|
||||
n = n - u64::from(rem - residue);
|
||||
}
|
||||
debug_assert!(n >= Zero::zero());
|
||||
|
||||
// This generates the smallest prime ≥ n that is of the form n + m*x.
|
||||
loop {
|
||||
// Speed up prime-finding by quickly ruling out numbers
|
||||
// that are known to be composite.
|
||||
let mut sieve = ::bit_vec::BitVec::from_elem(1 << 16, false);
|
||||
for &(p, q) in SIEVE_INFO.iter() {
|
||||
// The reference implementation changes the sign of `n` before taking its
|
||||
// remainder. Instead, we leave `n` as positive, but use ceiling
|
||||
// division instead of floor division. This is mathematically
|
||||
// equivalent and potentially faster.
|
||||
let mut i: usize = (n.crem_u16(p) as usize * q as usize) % p as usize;
|
||||
while i < sieve.len() {
|
||||
sieve.set(i, true);
|
||||
i += p as usize;
|
||||
}
|
||||
}
|
||||
|
||||
for (i, x) in sieve.iter().enumerate() {
|
||||
if !x {
|
||||
let q = u64::from(M) * u64::from(i as u32);
|
||||
n = n + q;
|
||||
if n.probab_prime(1) {
|
||||
return -n;
|
||||
}
|
||||
n = n - q;
|
||||
}
|
||||
}
|
||||
// M is set to a number with many prime factors so the results are
|
||||
// more uniform https://eprint.iacr.org/2011/481.pdf
|
||||
// TODO: Explain previous reference to https://eprint.iacr.org/2011/401.pdf
|
||||
n = n + (u64::from(M) * (1 << 16)) as u64
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use classgroup::{gmp_classgroup::GmpClassGroup, ClassGroup};
|
||||
type Mpz = <GmpClassGroup as ClassGroup>::BigNum;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[test]
|
||||
fn check_discriminant_1() {
|
||||
assert_eq!(
|
||||
create_discriminant::<Mpz>(b"\xaa", 40),
|
||||
(-685_537_176_559i64).into()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_discriminant_3() {
|
||||
assert_eq!(
|
||||
create_discriminant::<Mpz>(b"\xaa", 1024),
|
||||
Mpz::from_str(
|
||||
"-112084717443890964296630631725167420667316836131914185144761\
|
||||
7438378168250988242739496385274308134767869324152361453294226\
|
||||
8295868231081182819214054220080323345750407342623884342617809\
|
||||
8794592117225058677336074005099949757067786815439982423354682\
|
||||
0386024058617141397148586038290164093146862666602485017735298\
|
||||
03183"
|
||||
)
|
||||
.unwrap()
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_discriminant_2() {
|
||||
assert_eq!(
|
||||
create_discriminant::<Mpz>(b"\xaa", 2048),
|
||||
-Mpz::from_str(
|
||||
"201493927071865251625903550712920535753645598483515670853547009\
|
||||
878440933309489362800393797428711071833308081461824159206915864\
|
||||
150805748296170245037221957772328044276705571745811271212292422\
|
||||
075849739248257870371300001313586036515879618764093772248760562\
|
||||
386804073478433157526816295216137723803793411828867470089409596\
|
||||
238958950007370719325959579892866588928887249912429688364409867\
|
||||
895510817680171869190054122881274299350947669820596157115994418\
|
||||
034091728887584373727555384075665624624856766441009974642693066\
|
||||
751400054217209981490667208950669417773785631693879782993019167\
|
||||
69407006303085854796535778826115224633447713584423"
|
||||
)
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
#[test]
|
||||
fn check_random_bytes() {
|
||||
assert_eq!(
|
||||
&random_bytes_from_seed(b"\xaa", 7),
|
||||
b"\x9f\x9d*\xe5\xe7<\xcb"
|
||||
);
|
||||
assert_eq!(
|
||||
&random_bytes_from_seed(b"\xaa", 258)[..],
|
||||
&b"\x9f\x9d*\xe5\xe7<\xcbq\xa4q\x8e\
|
||||
\xbc\xf0\xe3:\xa2\x98\xf8\xbd\xdc\xaa\xcbi\xcb\x10\xff\x0e\xafv\xdb\xec!\xc4K\
|
||||
\xc6Jf\xf3\xa5\xda.7\xb7\xef\x87I\x85\xb8YX\xfc\xf2\x03\xa1\x8f4\xaf`\xab\xae]n\
|
||||
\xcc,g1\x12EI\xc7\xd5\xe2\xfc\x8b\x9a\xde\xd5\xf3\x8f'\xcd\x08\x0fU\xc7\xee\xa85\
|
||||
[>\x87]\x07\x82\x00\x13\xce\xf7\xc3/@\xef\x08v\x8f\x85\x87dm(1\x8b\xd9w\xffA]xzY\
|
||||
\xa0,\xebz\xff\x03$`\x91\xb66\x88-_\xa9\xf1\xc5\x8e,\x15\xae\x8f\x04\rvhnU3f\x84\
|
||||
[{$\xa6l\x95w\xa9\x1f\xba\xa8)\x05\xe6\x8f\x167o\x11/X\x9cl\xab\x9c\xcb}\xec\x88\
|
||||
\xf8\xa5\xabXpY\xb0\x88\xed@r\x05\xba\\\x03\xf6\x91\xf8\x03\xca\x18\x1c\xcdH\x1c\
|
||||
\x91\xe1V\xed;\x94oJ\xa8 \xa4\x97\xb7K\xce\xc4e\xea\xa2\xbf\x8b\x1f\x90\x87\xc8\
|
||||
\x15\xee\x0e\x0fPC:\xb5\xe1g\x97\xea/_\x86c\xaf\x12Wp\xfd\x11\xdb\x17\xe6\x9f\
|
||||
\xa5\x8a"[..]
|
||||
);
|
||||
}
|
||||
}
|
261
crates/vdf/src/lib.rs
Normal file
261
crates/vdf/src/lib.rs
Normal file
@ -0,0 +1,261 @@
|
||||
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
#![deny(warnings)]
|
||||
//! # Rust implementations of class groups and verifyable delay functions
|
||||
//!
|
||||
//! This repo includes three crates
|
||||
//!
|
||||
//! * `classgroup`, which includes a class group implementation, as well as a
|
||||
//! trait for class groups.
|
||||
//! * `vdf`, which includes a Verifyable Delay Function (VDF) trait, as well as
|
||||
//! an implementation of that trait.
|
||||
//! * `vdf-cli`, which includes a command-line interface to the `vdf` crate. It
|
||||
//! also includes additional commands, which are deprecated and will later be
|
||||
//! replaced by a CLI to the `classgroup` crate.
|
||||
//!
|
||||
//! ## Usage
|
||||
//!
|
||||
//! First, install Rust, Cargo, and the GNU Multiprecision Library (GMP). Then,
|
||||
//! follow one of the below steps.
|
||||
//!
|
||||
//! ### To use the command line interface
|
||||
//!
|
||||
//! ```sh
|
||||
//! $ git clone https://github.com/poanetwork/vdf
|
||||
//! $ cd vdf
|
||||
//! $ cargo install
|
||||
//! $ vdf-cli aa 100
|
||||
//! 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
|
||||
//! $ vdf-cli aa 100 005271e8f9ab2eb8a2906e851dfcb5542e4173f016b85e29d481a108dc82ed3b3f97937b7aa824801138d1771dea8dae2f6397e76a80613afda30f2c30a34b040baaafe76d5707d68689193e5d211833b372a6a4591abb88e2e7f2f5a5ec818b5707b86b8b2c495ca1581c179168509e3593f9a16879620a4dc4e907df452e8dd0ffc4f199825f54ec70472cc061f22eb54c48d6aa5af3ea375a392ac77294e2d955dde1d102ae2ace494293492d31cff21944a8bcb4608993065c9a00292e8d3f4604e7465b4eeefb494f5bea102db343bb61c5a15c7bdf288206885c130fa1f2d86bf5e4634fdc4216bc16ef7dac970b0ee46d69416f9a9acee651d158ac64915b
|
||||
//! Proof is valid
|
||||
//! ```
|
||||
//!
|
||||
//! ### To use the VDF library
|
||||
//!
|
||||
//! ```rust
|
||||
//! extern crate vdf;
|
||||
//! use vdf::{InvalidProof, PietrzakVDFParams, VDFParams, WesolowskiVDFParams, VDF};
|
||||
//! const CORRECT_SOLUTION: &[u8] =
|
||||
//! b"\x00\x52\x71\xe8\xf9\xab\x2e\xb8\xa2\x90\x6e\x85\x1d\xfc\xb5\x54\x2e\x41\x73\xf0\x16\
|
||||
//! \xb8\x5e\x29\xd4\x81\xa1\x08\xdc\x82\xed\x3b\x3f\x97\x93\x7b\x7a\xa8\x24\x80\x11\x38\
|
||||
//! \xd1\x77\x1d\xea\x8d\xae\x2f\x63\x97\xe7\x6a\x80\x61\x3a\xfd\xa3\x0f\x2c\x30\xa3\x4b\
|
||||
//! \x04\x0b\xaa\xaf\xe7\x6d\x57\x07\xd6\x86\x89\x19\x3e\x5d\x21\x18\x33\xb3\x72\xa6\xa4\
|
||||
//! \x59\x1a\xbb\x88\xe2\xe7\xf2\xf5\xa5\xec\x81\x8b\x57\x07\xb8\x6b\x8b\x2c\x49\x5c\xa1\
|
||||
//! \x58\x1c\x17\x91\x68\x50\x9e\x35\x93\xf9\xa1\x68\x79\x62\x0a\x4d\xc4\xe9\x07\xdf\x45\
|
||||
//! \x2e\x8d\xd0\xff\xc4\xf1\x99\x82\x5f\x54\xec\x70\x47\x2c\xc0\x61\xf2\x2e\xb5\x4c\x48\
|
||||
//! \xd6\xaa\x5a\xf3\xea\x37\x5a\x39\x2a\xc7\x72\x94\xe2\xd9\x55\xdd\xe1\xd1\x02\xae\x2a\
|
||||
//! \xce\x49\x42\x93\x49\x2d\x31\xcf\xf2\x19\x44\xa8\xbc\xb4\x60\x89\x93\x06\x5c\x9a\x00\
|
||||
//! \x29\x2e\x8d\x3f\x46\x04\xe7\x46\x5b\x4e\xee\xfb\x49\x4f\x5b\xea\x10\x2d\xb3\x43\xbb\
|
||||
//! \x61\xc5\xa1\x5c\x7b\xdf\x28\x82\x06\x88\x5c\x13\x0f\xa1\xf2\xd8\x6b\xf5\xe4\x63\x4f\
|
||||
//! \xdc\x42\x16\xbc\x16\xef\x7d\xac\x97\x0b\x0e\xe4\x6d\x69\x41\x6f\x9a\x9a\xce\xe6\x51\
|
||||
//! \xd1\x58\xac\x64\x91\x5b";
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let pietrzak_vdf = PietrzakVDFParams(2048).new();
|
||||
//! assert_eq!(
|
||||
//! &pietrzak_vdf.solve(b"\xaa", 100).unwrap()[..],
|
||||
//! CORRECT_SOLUTION
|
||||
//! );
|
||||
//! assert!(pietrzak_vdf.verify(b"\xaa", 100, CORRECT_SOLUTION).is_ok());
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! ### To run the benchmarks
|
||||
//!
|
||||
//! Benchmarks are provided for the classgroup operations. Run `cargo bench`
|
||||
//! to run them. Additional benchmarks are under development.
|
||||
use classgroup;
|
||||
|
||||
mod create_discriminant;
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub use self::{
|
||||
create_discriminant::create_discriminant,
|
||||
proof_pietrzak::{PietrzakVDF, PietrzakVDFParams},
|
||||
proof_wesolowski::{WesolowskiVDF, WesolowskiVDFParams},
|
||||
};
|
||||
|
||||
/// Message used to report an internal miscalculation of serialization buffer
|
||||
/// sizes.
|
||||
const INCORRECT_BUFFER_SIZE: &str =
|
||||
"internal error: incorrect buffer size calculation (this is a bug)";
|
||||
|
||||
mod proof_of_time;
|
||||
mod proof_pietrzak;
|
||||
mod proof_wesolowski;
|
||||
|
||||
uniffi::include_scaffolding!("lib");
|
||||
|
||||
/// An empty struct indicating verification failure.
|
||||
///
|
||||
/// For security reasons, the functions that perform verification *do not*
|
||||
/// return any information on failure. Use `VDF::validate_params` to check if
|
||||
/// the parameters are correct.
|
||||
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct InvalidProof;
|
||||
|
||||
/// An error return indicating an invalid number of iterations. The string is a
|
||||
/// human-readable message describing the valid iterations. It should not be
|
||||
/// interpreted by programs.
|
||||
#[derive(Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct InvalidIterations(String);
|
||||
|
||||
/// The type of VDF parameters.
|
||||
///
|
||||
/// Parameters represent public information that can be shared by all users
|
||||
/// of the protocol. As such, they must implement `Clone`, so that they can
|
||||
/// be duplicated. They also must implement `Send`, so that a parallel
|
||||
/// application can send them safely across threads.
|
||||
///
|
||||
/// The parameters *do not* include the difficulty level (usually an
|
||||
/// iteration count), since that can be separate for each invocation.
|
||||
///
|
||||
/// This must implement `Clone` and `Eq`.
|
||||
pub trait VDFParams: Clone + Eq {
|
||||
type VDF: VDF + Sized;
|
||||
|
||||
/// Creates an instance of this VDF from the given parameters.
|
||||
///
|
||||
/// # Performance
|
||||
///
|
||||
/// This method is expected to be fairly cheap. For example, it is okay if
|
||||
/// it allocates memory, but it should not perform expensive computations or
|
||||
/// I/O.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// This method **MUST NOT** fail due to invalid values for `params`. Such
|
||||
/// errors should be checked by the factory functions for `Self::Params`.
|
||||
///
|
||||
/// This function **MAY** panic for other reasons. For example, it is
|
||||
/// allowed to panic if an allocation fails, or if a needed external library
|
||||
/// could not be dynamically loaded.
|
||||
fn new(self) -> Self::VDF;
|
||||
}
|
||||
|
||||
/// A Verifiable Delay Function (VDF).
|
||||
///
|
||||
/// VDFs are problems that require a certain amount of time to solve, even on a
|
||||
/// parallel machine, but can be validated much more easily.
|
||||
///
|
||||
/// While VDFs are considered to be cryptographic primitives, they generally do
|
||||
/// *not* operate on highly sensitive data. As such, implementers of this trait
|
||||
/// **do not** guarantee that they will be immune to side-channel attacks, and
|
||||
/// consumers of this trait **MUST NOT** expect this.
|
||||
///
|
||||
/// Instances of this trait are *not* expected to be `Sync`. This allows them
|
||||
/// to reuse allocations (such as scratch memory) accross invocations without
|
||||
/// the need for locking. However, they **MUST** be `Send` and `Clone`, so that
|
||||
/// consumers can duplicate them and send them across threads.
|
||||
pub trait VDF: Send + Debug {
|
||||
/// Solve an instance of this VDF, with challenge `challenge` and difficulty
|
||||
/// `difficulty`.
|
||||
///
|
||||
/// The output is to be returned in a `Vec<u8>`, so it can be stored to disk
|
||||
/// or sent over the network.
|
||||
///
|
||||
/// # Challenge format
|
||||
///
|
||||
/// The challenge is an opaque byte string of arbitrary length.
|
||||
/// Implementors **MUST NOT** make any assumptions about its contents,
|
||||
/// and **MUST** produce distinct outputs for distinct challenges
|
||||
/// (except with negiligible probability).
|
||||
///
|
||||
/// This can be most easily implemented by using the challenge as part of
|
||||
/// the input of a cryptographic hash function. The VDFs provided in this
|
||||
/// crate use this strategy.
|
||||
///
|
||||
/// The difficulty must be checked before performing any expensive
|
||||
/// computations.
|
||||
///
|
||||
/// Most applications will generate the challenge using a
|
||||
/// cryptographically-secure pseudorandom number generator, but implementors
|
||||
/// **MUST NOT** rely on this. In particular, this function must be secure
|
||||
/// even if `challenge` is chosen by an adversary. Excessive values for
|
||||
/// `difficulty` may cause excessive resource consumption, but must not
|
||||
/// create any other vulnerabilities.
|
||||
///
|
||||
/// # Complexity
|
||||
///
|
||||
/// The VDFs in this crate consume memory that does not depend on
|
||||
/// `difficulty`, and time linearly proportional to `difficulty`.
|
||||
/// Implementors of this trait should document the resource use.
|
||||
///
|
||||
/// # Purity
|
||||
///
|
||||
/// This method must have no side effects. In particular, it must be
|
||||
/// **deterministic**: it must always return the same output for the same
|
||||
/// inputs, except with negligible probability. Furthermore, while it may
|
||||
/// change `self` via interior mutability, such changes must not affect
|
||||
/// future calls to this method, `Self::check_difficulty`, or
|
||||
/// `Self::verify`. They *may* affect the `Debug` output.
|
||||
fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>, InvalidIterations>;
|
||||
|
||||
/// Check that the difficulty is valid.
|
||||
///
|
||||
/// This must return `Ok` if and only if `difficulty` is valid. Otherwise,
|
||||
/// it must return `Err`.
|
||||
///
|
||||
/// # Rationale
|
||||
///
|
||||
/// It would be more ideomatic Rust to use the type system to enforce that a
|
||||
/// difficulty has been validated before use. However, I (Demi) have not
|
||||
/// yet figured out an object-safe way to do so.
|
||||
fn check_difficulty(&self, difficulty: u64) -> Result<(), InvalidIterations>;
|
||||
|
||||
/// Verifies an alleged solution of this VDF, with challenge `challenge` and
|
||||
/// difficulty `difficulty`. Return `Ok(())` on success, or
|
||||
/// `Err(InvalidProof)` on failure.
|
||||
///
|
||||
/// This function *does not* return any extended error information for
|
||||
/// security reasons. To check that the difficulty is correct, call
|
||||
/// `Self::check_difficulty`.
|
||||
///
|
||||
/// # Uniqueness of valid solutions
|
||||
///
|
||||
/// For any `(challenge, difficulty)` tuple, there must be at most one
|
||||
/// `alleged_solution` (as measured by `Eq`) that causes this function to
|
||||
/// return `Ok(())`. If the difficulty is valid (as determined by
|
||||
/// `check_difficulty`), there must be exactly one such solution; otherwise,
|
||||
/// there must be none.
|
||||
///
|
||||
/// # Purity
|
||||
///
|
||||
/// This method must have no side effects. In particular, it must be
|
||||
/// **deterministic**: it must always return the same output for the same
|
||||
/// inputs. Furthermore, while it may change `self` via interior
|
||||
/// mutability, such changes must not affect future calls to this method,
|
||||
/// `Self::prove`, or `Self::check_difficulty`. Such changes **MAY** affect
|
||||
/// debugging output.
|
||||
fn verify(
|
||||
&self,
|
||||
challenge: &[u8],
|
||||
difficulty: u64,
|
||||
alleged_solution: &[u8],
|
||||
) -> Result<(), InvalidProof>;
|
||||
}
|
||||
|
||||
/// Solve and prove with the Wesolowski VDF using the given parameters.
|
||||
/// Outputs the concatenated solution and proof (in this order).
|
||||
pub fn wesolowski_solve(int_size_bits: u16, challenge: &[u8], difficulty: u32) -> Vec<u8> {
|
||||
let vdf = WesolowskiVDFParams(int_size_bits).new();
|
||||
vdf.solve(challenge, difficulty.into()).expect("invalid difficulty")
|
||||
}
|
||||
|
||||
/// Verify with the Wesolowski VDF using the given parameters.
|
||||
/// `alleged_solution` is the output of `wesolowski_solve`.
|
||||
pub fn wesolowski_verify(int_size_bits: u16, challenge: &[u8], difficulty: u32, alleged_solution: &[u8]) -> bool {
|
||||
let vdf = WesolowskiVDFParams(int_size_bits).new();
|
||||
vdf.verify(challenge, difficulty.into(), alleged_solution).is_ok()
|
||||
}
|
4
crates/vdf/src/lib.udl
Normal file
4
crates/vdf/src/lib.udl
Normal file
@ -0,0 +1,4 @@
|
||||
namespace vdf {
|
||||
sequence<u8> wesolowski_solve(u16 int_size_bits, [ByRef] sequence<u8> challenge, u32 difficulty);
|
||||
boolean wesolowski_verify(u16 int_size_bits, [ByRef] sequence<u8> challenge, u32 difficulty, [ByRef] sequence<u8> alleged_solution);
|
||||
};
|
88
crates/vdf/src/proof_of_time.rs
Normal file
88
crates/vdf/src/proof_of_time.rs
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
use super::classgroup::ClassGroup;
|
||||
use std::{collections::HashMap, usize};
|
||||
|
||||
pub fn serialize<V: ClassGroup>(proof: &[V], y: &V, int_size_bits: usize) -> Vec<u8> {
|
||||
let proof_len = proof.len();
|
||||
let element_length = 2 * ((int_size_bits + 16) >> 4);
|
||||
let proof_len_in_bytes = (proof_len + 1) * element_length;
|
||||
let mut v = vec![0; proof_len_in_bytes];
|
||||
y.serialize(&mut v[0..element_length])
|
||||
.expect(super::INCORRECT_BUFFER_SIZE);
|
||||
for (index, group) in proof.iter().enumerate() {
|
||||
let offset = (index + 1) * element_length;
|
||||
group
|
||||
.serialize(&mut v[offset..offset + element_length])
|
||||
.expect(super::INCORRECT_BUFFER_SIZE)
|
||||
}
|
||||
v
|
||||
}
|
||||
pub fn deserialize_proof<T>(
|
||||
proof_blob: &[u8],
|
||||
discriminant: &T::BigNum,
|
||||
orig_length: usize,
|
||||
) -> Result<Vec<T>, ()>
|
||||
where
|
||||
T: ClassGroup,
|
||||
for<'a, 'b> &'a T: std::ops::Mul<&'b T, Output = T>,
|
||||
for<'a, 'b> &'a T::BigNum: std::ops::Mul<&'b T::BigNum, Output = T::BigNum>,
|
||||
{
|
||||
let length = T::size_in_bits(discriminant);
|
||||
if length > usize::MAX - 16 {
|
||||
return Err(());
|
||||
}
|
||||
let length = (length + 16) >> 4;
|
||||
if length == 0 {
|
||||
return Err(());
|
||||
}
|
||||
if orig_length != length {
|
||||
return Err(());
|
||||
}
|
||||
let length = length * 2;
|
||||
let proof_blob_length = proof_blob.len();
|
||||
let rem = proof_blob_length % length;
|
||||
if rem != 0 {
|
||||
return Err(());
|
||||
}
|
||||
let proof_len = proof_blob_length / length;
|
||||
let mut v = Vec::with_capacity(proof_len);
|
||||
for i in 0..proof_len {
|
||||
let offset = i * length;
|
||||
v.push(T::from_bytes(
|
||||
&proof_blob[offset..offset + length],
|
||||
discriminant.clone(),
|
||||
))
|
||||
}
|
||||
Ok(v)
|
||||
}
|
||||
|
||||
pub fn iterate_squarings<V, U>(mut x: V, powers_to_calculate: U) -> HashMap<u64, V>
|
||||
where
|
||||
V: ClassGroup,
|
||||
for<'a, 'b> &'a V: std::ops::Mul<&'b V, Output = V>,
|
||||
for<'a, 'b> &'a V::BigNum: std::ops::Mul<&'b V::BigNum, Output = V::BigNum>,
|
||||
U: Iterator<Item = u64>,
|
||||
{
|
||||
let mut powers_calculated = HashMap::new();
|
||||
let mut powers_to_calculate: Vec<u64> = powers_to_calculate.collect();
|
||||
powers_to_calculate.sort_unstable();
|
||||
let mut previous_power: u64 = 0;
|
||||
for ¤t_power in &powers_to_calculate {
|
||||
x.repeated_square(current_power - previous_power);
|
||||
powers_calculated.insert(current_power, x.clone());
|
||||
previous_power = current_power
|
||||
}
|
||||
powers_calculated
|
||||
}
|
466
crates/vdf/src/proof_pietrzak.rs
Normal file
466
crates/vdf/src/proof_pietrzak.rs
Normal file
@ -0,0 +1,466 @@
|
||||
// Copyright 2018 Chia Network Inc and POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
use super::proof_of_time::{deserialize_proof, iterate_squarings, serialize};
|
||||
use classgroup::{gmp_classgroup::GmpClassGroup, BigNumExt, ClassGroup};
|
||||
use num_traits::{One, Zero};
|
||||
use std::{fmt, num::ParseIntError, ops::Index, str::FromStr, u64, usize};
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Copy, Clone, Debug)]
|
||||
pub struct Iterations(u64);
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Copy, Clone, Debug)]
|
||||
pub enum InvalidIterations {
|
||||
OddNumber(u64),
|
||||
LessThan66(u64),
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||
pub struct ParseIterationsError {
|
||||
kind: Result<InvalidIterations, ParseIntError>,
|
||||
}
|
||||
|
||||
impl From<InvalidIterations> for ParseIterationsError {
|
||||
fn from(t: InvalidIterations) -> Self {
|
||||
Self { kind: Ok(t) }
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for ParseIterationsError {
|
||||
fn from(t: ParseIntError) -> Self {
|
||||
Self { kind: Err(t) }
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for InvalidIterations {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
InvalidIterations::OddNumber(s) => {
|
||||
write!(f, "Pietrzak iterations must be an even number, not {}", s)
|
||||
}
|
||||
InvalidIterations::LessThan66(s) => write!(
|
||||
f,
|
||||
"Pietrzak proof-of-time must run for at least 66 iterations, not {}",
|
||||
s
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Iterations> for u64 {
|
||||
fn from(t: Iterations) -> u64 {
|
||||
t.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseIterationsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.kind {
|
||||
Ok(ref q) => <InvalidIterations as fmt::Display>::fmt(q, f),
|
||||
Err(ref q) => <ParseIntError as fmt::Display>::fmt(q, f),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Iterations {
|
||||
type Err = ParseIterationsError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Self::new(s.parse::<u64>().map_err(ParseIterationsError::from)?)
|
||||
.map_err(ParseIterationsError::from)
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterations {
|
||||
pub fn new<T: Into<u64>>(iterations: T) -> Result<Iterations, InvalidIterations> {
|
||||
let iterations = iterations.into();
|
||||
if iterations & 1 != 0 {
|
||||
Err(InvalidIterations::OddNumber(iterations))
|
||||
} else if iterations < 66 {
|
||||
Err(InvalidIterations::LessThan66(iterations))
|
||||
} else {
|
||||
Ok(Iterations(iterations))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Selects a reasonable choice of cache size.
|
||||
fn approximate_i(t: Iterations) -> u64 {
|
||||
let x: f64 = (((t.0 >> 1) as f64) / 8.) * 2.0f64.ln();
|
||||
let w = x.ln() - x.ln().ln() + 0.25;
|
||||
(w / (2. * 2.0f64.ln())).round() as _
|
||||
}
|
||||
|
||||
fn sum_combinations<'a, T: IntoIterator<Item = &'a u64>>(numbers: T) -> Vec<u64> {
|
||||
let mut combinations = vec![0];
|
||||
for i in numbers {
|
||||
let mut new_combinations = combinations.clone();
|
||||
for j in combinations {
|
||||
new_combinations.push(i + j)
|
||||
}
|
||||
combinations = new_combinations
|
||||
}
|
||||
combinations.remove(0);
|
||||
combinations
|
||||
}
|
||||
|
||||
fn cache_indices_for_count(t: Iterations) -> Vec<u64> {
|
||||
let i: u64 = approximate_i(t);
|
||||
let mut curr_t = t.0;
|
||||
let mut intermediate_ts = vec![];
|
||||
for _ in 0..i {
|
||||
curr_t >>= 1;
|
||||
intermediate_ts.push(curr_t);
|
||||
if curr_t & 1 != 0 {
|
||||
curr_t += 1
|
||||
}
|
||||
}
|
||||
let mut cache_indices = sum_combinations(&intermediate_ts);
|
||||
cache_indices.sort();
|
||||
cache_indices.push(t.0);
|
||||
cache_indices
|
||||
}
|
||||
|
||||
fn generate_r_value<T>(x: &T, y: &T, sqrt_mu: &T, int_size_bits: usize) -> T::BigNum
|
||||
where
|
||||
T: ClassGroup,
|
||||
for<'a, 'b> &'a T: std::ops::Mul<&'b T, Output = T>,
|
||||
for<'a, 'b> &'a T::BigNum: std::ops::Mul<&'b T::BigNum, Output = T::BigNum>,
|
||||
{
|
||||
use sha2::{digest::FixedOutput, Digest, Sha256};
|
||||
|
||||
let size = (int_size_bits + 16) >> 4;
|
||||
let mut v = Vec::with_capacity(size * 2);
|
||||
for _ in 0..size * 2 {
|
||||
v.push(0)
|
||||
}
|
||||
let mut hasher = Sha256::new();
|
||||
for i in &[&x, &y, &sqrt_mu] {
|
||||
i.serialize(&mut v).expect(super::INCORRECT_BUFFER_SIZE);
|
||||
hasher.input(&v);
|
||||
}
|
||||
let res = hasher.fixed_result();
|
||||
T::unsigned_deserialize_bignum(&res[..16])
|
||||
}
|
||||
|
||||
fn create_proof_of_time_pietrzak<T>(
|
||||
challenge: &[u8],
|
||||
iterations: Iterations,
|
||||
int_size_bits: u16,
|
||||
) -> Vec<u8>
|
||||
where
|
||||
T: ClassGroup,
|
||||
<T as ClassGroup>::BigNum: BigNumExt,
|
||||
for<'a, 'b> &'a T: std::ops::Mul<&'b T, Output = T>,
|
||||
for<'a, 'b> &'a T::BigNum: std::ops::Mul<&'b T::BigNum, Output = T::BigNum>,
|
||||
{
|
||||
let discriminant = super::create_discriminant::create_discriminant(&challenge, int_size_bits);
|
||||
let x = T::from_ab_discriminant(2.into(), 1.into(), discriminant);
|
||||
|
||||
let delta = 8;
|
||||
let powers_to_calculate = cache_indices_for_count(iterations);
|
||||
let powers = iterate_squarings(x.clone(), powers_to_calculate.iter().cloned());
|
||||
let proof: Vec<T> = generate_proof(
|
||||
x,
|
||||
iterations,
|
||||
delta,
|
||||
&powers,
|
||||
&generate_r_value,
|
||||
usize::from(int_size_bits),
|
||||
);
|
||||
serialize(
|
||||
&proof,
|
||||
&powers[&iterations.into()],
|
||||
usize::from(int_size_bits),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn check_proof_of_time_pietrzak<T>(
|
||||
challenge: &[u8],
|
||||
proof_blob: &[u8],
|
||||
iterations: u64,
|
||||
length_in_bits: u16,
|
||||
) -> Result<(), super::InvalidProof>
|
||||
where
|
||||
T: ClassGroup,
|
||||
T::BigNum: BigNumExt,
|
||||
for<'a, 'b> &'a T: std::ops::Mul<&'b T, Output = T>,
|
||||
for<'a, 'b> &'a T::BigNum: std::ops::Mul<&'b T::BigNum, Output = T::BigNum>,
|
||||
{
|
||||
let discriminant = super::create_discriminant::create_discriminant(&challenge, length_in_bits);
|
||||
let x = T::from_ab_discriminant(2.into(), 1.into(), discriminant);
|
||||
let iterations = Iterations::new(iterations).map_err(|_| super::InvalidProof)?;
|
||||
if usize::MAX - 16 < length_in_bits.into() {
|
||||
// Proof way too long.
|
||||
return Err(super::InvalidProof);
|
||||
}
|
||||
let length: usize = (usize::from(length_in_bits) + 16usize) >> 4;
|
||||
if proof_blob.len() < 2 * length {
|
||||
// Invalid length of proof
|
||||
return Err(super::InvalidProof);
|
||||
}
|
||||
let result_bytes = &proof_blob[..length * 2];
|
||||
let proof_bytes = &proof_blob[length * 2..];
|
||||
let discriminant = x.discriminant().clone();
|
||||
let proof =
|
||||
deserialize_proof(proof_bytes, &discriminant, length).map_err(|()| super::InvalidProof)?;
|
||||
let y = T::from_bytes(result_bytes, discriminant);
|
||||
verify_proof(
|
||||
&x,
|
||||
&y,
|
||||
proof,
|
||||
iterations,
|
||||
8,
|
||||
&generate_r_value,
|
||||
length_in_bits.into(),
|
||||
)
|
||||
.map_err(|()| super::InvalidProof)
|
||||
}
|
||||
|
||||
fn calculate_final_t(t: Iterations, delta: usize) -> u64 {
|
||||
let mut curr_t = t.0;
|
||||
let mut ts = vec![];
|
||||
while curr_t != 2 {
|
||||
ts.push(curr_t);
|
||||
curr_t >>= 1;
|
||||
if curr_t & 1 == 1 {
|
||||
curr_t += 1
|
||||
}
|
||||
}
|
||||
ts.push(2);
|
||||
ts.push(1);
|
||||
assert!(ts.len() >= delta);
|
||||
ts[ts.len() - delta]
|
||||
}
|
||||
|
||||
pub fn generate_proof<T, U, V>(
|
||||
x: V,
|
||||
iterations: Iterations,
|
||||
delta: usize,
|
||||
powers: &T,
|
||||
generate_r_value: &U,
|
||||
int_size_bits: usize,
|
||||
) -> Vec<V>
|
||||
where
|
||||
T: for<'a> Index<&'a u64, Output = V>,
|
||||
U: Fn(&V, &V, &V, usize) -> V::BigNum,
|
||||
V: ClassGroup,
|
||||
for<'a, 'b> &'a V: std::ops::Mul<&'b V, Output = V>,
|
||||
for<'a, 'b> &'a V::BigNum: std::ops::Mul<&'b V::BigNum, Output = V::BigNum>,
|
||||
{
|
||||
let identity = x.identity();
|
||||
let i = approximate_i(iterations);
|
||||
let mut mus = vec![];
|
||||
let mut rs: Vec<V::BigNum> = vec![];
|
||||
let mut x_p = vec![x];
|
||||
let mut curr_t = iterations.0;
|
||||
|
||||
let mut y_p = vec![powers[&curr_t].clone()];
|
||||
|
||||
let mut ts = vec![];
|
||||
|
||||
let final_t = calculate_final_t(iterations, delta);
|
||||
|
||||
let mut round_index = 0;
|
||||
while curr_t != final_t {
|
||||
assert_eq!(curr_t & 1, 0);
|
||||
let half_t = curr_t >> 1;
|
||||
ts.push(half_t);
|
||||
assert!(round_index < 63);
|
||||
let denominator: u64 = 1 << (round_index + 1);
|
||||
|
||||
mus.push(if round_index < i {
|
||||
let mut mu = identity.clone();
|
||||
for numerator in (1..denominator).step_by(2) {
|
||||
let num_bits = 62 - denominator.leading_zeros() as usize;
|
||||
let mut r_prod: V::BigNum = One::one();
|
||||
for b in (0..num_bits).rev() {
|
||||
if 0 == (numerator & (1 << (b + 1))) {
|
||||
r_prod *= &rs[num_bits - b - 1]
|
||||
}
|
||||
}
|
||||
let mut t_sum = half_t;
|
||||
for b in 0..num_bits {
|
||||
if 0 != (numerator & (1 << (b + 1))) {
|
||||
t_sum += ts[num_bits - b - 1]
|
||||
}
|
||||
}
|
||||
let mut power = powers[&t_sum].clone();
|
||||
power.pow(r_prod);
|
||||
mu *= &power;
|
||||
}
|
||||
mu
|
||||
} else {
|
||||
let mut mu = x_p.last().unwrap().clone();
|
||||
for _ in 0..half_t {
|
||||
mu *= &mu.clone()
|
||||
}
|
||||
mu
|
||||
});
|
||||
let mut mu: V = mus.last().unwrap().clone();
|
||||
let last_r: V::BigNum = generate_r_value(&x_p[0], &y_p[0], &mu, int_size_bits);
|
||||
assert!(last_r >= Zero::zero());
|
||||
rs.push(last_r.clone());
|
||||
{
|
||||
let mut last_x: V = x_p.last().unwrap().clone();
|
||||
last_x.pow(last_r.clone());
|
||||
last_x *= μ
|
||||
x_p.push(last_x);
|
||||
}
|
||||
mu.pow(last_r);
|
||||
mu *= y_p.last().unwrap();
|
||||
y_p.push(mu);
|
||||
curr_t >>= 1;
|
||||
if curr_t & 1 != 0 {
|
||||
curr_t += 1;
|
||||
y_p.last_mut().unwrap().square();
|
||||
}
|
||||
round_index += 1
|
||||
}
|
||||
if cfg!(debug_assertions) {
|
||||
let mut last_y = y_p.last().unwrap().clone();
|
||||
let mut last_x = x_p.last().unwrap().clone();
|
||||
let one: V::BigNum = 1u64.into();
|
||||
last_y.pow(one.clone());
|
||||
assert_eq!(last_y, y_p.last().unwrap().clone());
|
||||
last_x.pow(one << final_t as usize);
|
||||
}
|
||||
mus
|
||||
}
|
||||
|
||||
pub fn verify_proof<T, U, V>(
|
||||
x_initial: &V,
|
||||
y_initial: &V,
|
||||
proof: T,
|
||||
t: Iterations,
|
||||
delta: usize,
|
||||
generate_r_value: &U,
|
||||
int_size_bits: usize,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
T: IntoIterator<Item = V>,
|
||||
U: Fn(&V, &V, &V, usize) -> V::BigNum,
|
||||
V: ClassGroup,
|
||||
for<'a, 'b> &'a V: std::ops::Mul<&'b V, Output = V>,
|
||||
for<'a, 'b> &'a V::BigNum: std::ops::Mul<&'b V::BigNum, Output = V::BigNum>,
|
||||
{
|
||||
let mut one: V::BigNum = One::one();
|
||||
let (mut x, mut y): (V, V) = (x_initial.clone(), y_initial.clone());
|
||||
let final_t = calculate_final_t(t, delta);
|
||||
let mut curr_t = t.0;
|
||||
for mut mu in proof {
|
||||
assert!(
|
||||
curr_t & 1 == 0,
|
||||
"Cannot have an odd number of iterations remaining"
|
||||
);
|
||||
let r = generate_r_value(x_initial, y_initial, &mu, int_size_bits);
|
||||
x.pow(r.clone());
|
||||
x *= μ
|
||||
mu.pow(r);
|
||||
y *= μ
|
||||
|
||||
curr_t >>= 1;
|
||||
if curr_t & 1 != 0 {
|
||||
curr_t += 1;
|
||||
y.square();
|
||||
}
|
||||
}
|
||||
one <<= final_t as _;
|
||||
x.pow(one);
|
||||
if x == y {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PietrzakVDF {
|
||||
int_size_bits: u16,
|
||||
}
|
||||
use super::InvalidIterations as Bad;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct PietrzakVDFParams(pub u16);
|
||||
impl super::VDFParams for PietrzakVDFParams {
|
||||
type VDF = PietrzakVDF;
|
||||
fn new(self) -> Self::VDF {
|
||||
PietrzakVDF {
|
||||
int_size_bits: self.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl super::VDF for PietrzakVDF {
|
||||
fn check_difficulty(&self, difficulty: u64) -> Result<(), Bad> {
|
||||
Iterations::new(difficulty)
|
||||
.map_err(|x| Bad(format!("{}", x)))
|
||||
.map(drop)
|
||||
}
|
||||
fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>, Bad> {
|
||||
Ok(create_proof_of_time_pietrzak::<GmpClassGroup>(
|
||||
challenge,
|
||||
Iterations::new(difficulty).map_err(|x| Bad(format!("{}", x)))?,
|
||||
self.int_size_bits,
|
||||
))
|
||||
}
|
||||
|
||||
fn verify(
|
||||
&self,
|
||||
challenge: &[u8],
|
||||
difficulty: u64,
|
||||
alleged_solution: &[u8],
|
||||
) -> Result<(), super::InvalidProof> {
|
||||
check_proof_of_time_pietrzak::<GmpClassGroup>(
|
||||
challenge,
|
||||
alleged_solution,
|
||||
difficulty,
|
||||
self.int_size_bits,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn check_approximate_i() {
|
||||
assert_eq!(approximate_i(Iterations(534)), 2);
|
||||
assert_eq!(approximate_i(Iterations(134)), 1);
|
||||
assert_eq!(approximate_i(Iterations(1024)), 2);
|
||||
}
|
||||
#[test]
|
||||
fn check_cache_indices() {
|
||||
assert_eq!(cache_indices_for_count(Iterations(66))[..], [33, 66]);
|
||||
assert_eq!(
|
||||
cache_indices_for_count(Iterations(534))[..],
|
||||
[134, 267, 401, 534]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_calculate_final_t() {
|
||||
assert_eq!(calculate_final_t(Iterations(1024), 8), 128);
|
||||
assert_eq!(calculate_final_t(Iterations(1000), 8), 126);
|
||||
assert_eq!(calculate_final_t(Iterations(100), 8), 100);
|
||||
}
|
||||
#[test]
|
||||
fn check_assuptions_about_stdlib() {
|
||||
assert_eq!(62 - u64::leading_zeros(1024u64), 9);
|
||||
let mut q: Vec<_> = (1..4).step_by(2).collect();
|
||||
assert_eq!(q[..], [1, 3]);
|
||||
q = (1..3).step_by(2).collect();
|
||||
assert_eq!(q[..], [1]);
|
||||
q = (1..2).step_by(2).collect();
|
||||
assert_eq!(q[..], [1]);
|
||||
}
|
||||
}
|
316
crates/vdf/src/proof_wesolowski.rs
Normal file
316
crates/vdf/src/proof_wesolowski.rs
Normal file
@ -0,0 +1,316 @@
|
||||
// Copyright 2018 POA Networks Ltd.
|
||||
//
|
||||
// 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.
|
||||
|
||||
use super::proof_of_time::{iterate_squarings, serialize};
|
||||
use classgroup::{gmp_classgroup::GmpClassGroup, BigNum, BigNumExt, ClassGroup};
|
||||
use sha2::{digest::FixedOutput, Digest, Sha256};
|
||||
use std::{cmp::Eq, collections::HashMap, hash::Hash, mem, u64, usize};
|
||||
use std::convert::TryInto;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WesolowskiVDF {
|
||||
int_size_bits: u16,
|
||||
}
|
||||
use super::InvalidIterations as Bad;
|
||||
|
||||
#[derive(Clone, Copy, Eq, PartialEq, PartialOrd, Ord, Hash, Debug)]
|
||||
pub struct WesolowskiVDFParams(pub u16);
|
||||
impl super::VDFParams for WesolowskiVDFParams {
|
||||
type VDF = WesolowskiVDF;
|
||||
fn new(self) -> Self::VDF {
|
||||
WesolowskiVDF {
|
||||
int_size_bits: self.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl super::VDF for WesolowskiVDF {
|
||||
fn check_difficulty(&self, _difficulty: u64) -> Result<(), Bad> {
|
||||
Ok(())
|
||||
}
|
||||
fn solve(&self, challenge: &[u8], difficulty: u64) -> Result<Vec<u8>, Bad> {
|
||||
if difficulty > usize::MAX as u64 {
|
||||
Err(Bad("Cannot have more that usize::MAX iterations".to_owned()))
|
||||
} else {
|
||||
Ok(create_proof_of_time_wesolowski::<
|
||||
<GmpClassGroup as ClassGroup>::BigNum,
|
||||
GmpClassGroup,
|
||||
>(
|
||||
challenge, difficulty as usize, self.int_size_bits
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn verify(
|
||||
&self,
|
||||
challenge: &[u8],
|
||||
difficulty: u64,
|
||||
alleged_solution: &[u8],
|
||||
) -> Result<(), super::InvalidProof> {
|
||||
check_proof_of_time_wesolowski::<<GmpClassGroup as ClassGroup>::BigNum, GmpClassGroup>(
|
||||
challenge,
|
||||
alleged_solution,
|
||||
difficulty,
|
||||
self.int_size_bits,
|
||||
)
|
||||
.map_err(|()| super::InvalidProof)
|
||||
}
|
||||
}
|
||||
/// To quote the original Python code:
|
||||
///
|
||||
/// > Create `L` and `k` parameters from papers, based on how many iterations
|
||||
/// > need to be performed, and how much memory should be used.
|
||||
pub fn approximate_parameters(t: f64) -> (usize, u8, u64) {
|
||||
let log_memory = (10_000_000.0f64).log2();
|
||||
let log_t = (t as f64).log2();
|
||||
let l = if log_t - log_memory > 0. {
|
||||
2.0f64.powf(log_memory - 20.).ceil()
|
||||
} else {
|
||||
1.
|
||||
};
|
||||
|
||||
let intermediate = t * (2.0f64).ln() / (2.0 * l);
|
||||
let k = (intermediate.ln() - intermediate.ln().ln() + 0.25)
|
||||
.round()
|
||||
.max(1.);
|
||||
|
||||
let w = (t / (t / k + l * (2.0f64).powf(k + 1.0)) - 2.0).floor();
|
||||
(l as _, k as _, w as _)
|
||||
}
|
||||
|
||||
fn u64_to_bytes(q: u64) -> [u8; 8] {
|
||||
if false {
|
||||
// This use of `std::mem::transumte` is correct, but still not justified.
|
||||
unsafe { std::mem::transmute(q.to_be()) }
|
||||
} else {
|
||||
[
|
||||
(q >> 56) as u8,
|
||||
(q >> 48) as u8,
|
||||
(q >> 40) as u8,
|
||||
(q >> 32) as u8,
|
||||
(q >> 24) as u8,
|
||||
(q >> 16) as u8,
|
||||
(q >> 8) as u8,
|
||||
q as u8,
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
/// Quote:
|
||||
///
|
||||
/// > Creates a random prime based on input s.
|
||||
fn hash_prime<T: BigNum>(seed: &[&[u8]], t: u32) -> T {
|
||||
let mut j = 0u64;
|
||||
loop {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.input(b"prime");
|
||||
hasher.input(u64_to_bytes(j));
|
||||
for i in seed {
|
||||
hasher.input(i);
|
||||
}
|
||||
hasher.input(t.to_be_bytes());
|
||||
let n = T::from(&hasher.fixed_result()[..16]);
|
||||
if n.probab_prime(1) {
|
||||
break n;
|
||||
}
|
||||
j += 1;
|
||||
}
|
||||
}
|
||||
|
||||
/// Quote:
|
||||
///
|
||||
/// > Get“s the ith block of `2^T // B`, such that `sum(get_block(i) * 2^(k*i))
|
||||
/// > = t^T // B`
|
||||
fn get_block<T: BigNumExt>(i: u64, k: u8, t: u64, b: &T) -> T {
|
||||
let mut res = T::from(0);
|
||||
let two = T::from(2);
|
||||
res.mod_powm(&two, &T::from(t - u64::from(k) * (i + 1)), b);
|
||||
res *= &((two >> 1) << (k as usize));
|
||||
res / b
|
||||
}
|
||||
|
||||
fn eval_optimized<T, U: BigNumExt, L: ClassGroup<BigNum = U> + Eq + Hash>(
|
||||
h: &L,
|
||||
b: &U,
|
||||
t: usize,
|
||||
k: u8,
|
||||
l: usize,
|
||||
powers: &T,
|
||||
) -> L
|
||||
where
|
||||
T: for<'a> std::ops::Index<&'a u64, Output = L>,
|
||||
{
|
||||
assert!(k > 0, "k cannot be zero");
|
||||
assert!(l > 0, "l cannot be zero");
|
||||
let kl = (k as usize)
|
||||
.checked_mul(l)
|
||||
.expect("computing k*l overflowed a u64");
|
||||
assert!(kl <= u64::MAX as _);
|
||||
assert!((kl as u64) < (1u64 << 53), "k*l overflowed an f64");
|
||||
assert!((t as u64) < (1u64 << 53), "t overflows an f64");
|
||||
assert!(
|
||||
k < (mem::size_of::<usize>() << 3) as u8,
|
||||
"k must be less than the number of bits in a usize"
|
||||
);
|
||||
let k1 = k >> 1;
|
||||
let k0 = k - k1;
|
||||
let mut x = h.identity();
|
||||
let identity = h.identity();
|
||||
let k_exp = 1usize << k;
|
||||
let k0_exp = 1usize << k0;
|
||||
let k1_exp = 1usize << k1;
|
||||
for j in (0..l).rev() {
|
||||
x.pow(U::from(k_exp as u64));
|
||||
let mut ys: HashMap<U, L> = HashMap::new();
|
||||
for b in 0..1usize << k {
|
||||
ys.entry(U::from(b as u64))
|
||||
.or_insert_with(|| identity.clone());
|
||||
}
|
||||
let end_of_loop = ((t as f64) / kl as f64).ceil() as usize;
|
||||
assert!(end_of_loop == 0 || (end_of_loop as u64 - 1).checked_mul(l as u64).is_some());
|
||||
for i in 0..end_of_loop {
|
||||
if t < k as usize * (i * l + j + 1) {
|
||||
continue;
|
||||
}
|
||||
let b = get_block((i as u64) * (l as u64), k, t as _, b);
|
||||
*ys.get_mut(&b).unwrap() *= &powers[&((i * kl) as _)];
|
||||
}
|
||||
|
||||
for b1 in 0..k1_exp {
|
||||
let mut z = identity.clone();
|
||||
for b0 in 0..k0_exp {
|
||||
z *= &ys[&U::from((b1 * k0_exp + b0) as u64)]
|
||||
}
|
||||
z.pow(U::from((b1 as u64) * (k0_exp as u64)));
|
||||
x *= &z;
|
||||
}
|
||||
|
||||
for b0 in 0..k0_exp {
|
||||
let mut z = identity.clone();
|
||||
for b1 in 0..k1_exp {
|
||||
z *= &ys[&U::from((b1 * k0_exp + b0) as u64)];
|
||||
}
|
||||
z.pow(U::from(b0 as u64));
|
||||
x *= &z;
|
||||
}
|
||||
}
|
||||
x
|
||||
}
|
||||
|
||||
pub fn generate_proof<U, T: BigNumExt, V: ClassGroup<BigNum = T> + Eq + Hash>(
|
||||
x: &V,
|
||||
iterations: u64,
|
||||
k: u8,
|
||||
l: usize,
|
||||
powers: &U,
|
||||
int_size_bits: usize,
|
||||
) -> V
|
||||
where
|
||||
U: for<'a> std::ops::Index<&'a u64, Output = V>,
|
||||
{
|
||||
let element_len = 2 * ((int_size_bits + 16) >> 4);
|
||||
let mut x_buf = vec![0; element_len];
|
||||
x.serialize(&mut x_buf[..])
|
||||
.expect(super::INCORRECT_BUFFER_SIZE);
|
||||
let mut y_buf = vec![0; element_len];
|
||||
powers[&iterations]
|
||||
.serialize(&mut y_buf[..])
|
||||
.expect(super::INCORRECT_BUFFER_SIZE);
|
||||
let b = hash_prime(
|
||||
&[&x_buf[..], &y_buf[..]],
|
||||
iterations.try_into().expect("iterations fit into u32")
|
||||
);
|
||||
eval_optimized(&x, &b, iterations as _, k, l, powers)
|
||||
}
|
||||
|
||||
/// Verify a proof, according to the Wesolowski paper.
|
||||
pub fn verify_proof<T: BigNum, V: ClassGroup<BigNum = T>>(
|
||||
mut x: V,
|
||||
y: &V,
|
||||
mut proof: V,
|
||||
t: u64,
|
||||
int_size_bits: usize,
|
||||
) -> Result<(), ()> {
|
||||
let element_len = 2 * ((int_size_bits + 16) >> 4);
|
||||
let mut x_buf = vec![0; element_len];
|
||||
x.serialize(&mut x_buf[..])
|
||||
.expect(super::INCORRECT_BUFFER_SIZE);
|
||||
let mut y_buf = vec![0; element_len];
|
||||
y.serialize(&mut y_buf[..])
|
||||
.expect(super::INCORRECT_BUFFER_SIZE);
|
||||
let b = hash_prime(
|
||||
&[&x_buf[..], &y_buf[..]],
|
||||
t.try_into().expect("iterations fit into u32")
|
||||
);
|
||||
let mut r = T::from(0);
|
||||
r.mod_powm(&T::from(2u64), &T::from(t), &b);
|
||||
proof.pow(b);
|
||||
x.pow(r);
|
||||
proof *= &x;
|
||||
if &proof == y {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_proof_of_time_wesolowski<T: BigNumExt, V: ClassGroup<BigNum = T> + Eq + Hash>(
|
||||
challenge: &[u8],
|
||||
iterations: usize,
|
||||
int_size_bits: u16,
|
||||
) -> Vec<u8>
|
||||
where
|
||||
for<'a, 'b> &'a V: std::ops::Mul<&'b V, Output = V>,
|
||||
for<'a, 'b> &'a V::BigNum: std::ops::Mul<&'b V::BigNum, Output = V::BigNum>,
|
||||
{
|
||||
let discriminant = super::create_discriminant::create_discriminant(&challenge, int_size_bits);
|
||||
let x = V::from_ab_discriminant(2.into(), 1.into(), discriminant);
|
||||
assert!((iterations as u128) < (1u128 << 53));
|
||||
let (l, k, _) = approximate_parameters(iterations as f64);
|
||||
let q = l.checked_mul(k as _).expect("bug");
|
||||
let powers = iterate_squarings(
|
||||
x.clone(),
|
||||
(0..=iterations / q + 1)
|
||||
.map(|i| i * q)
|
||||
.chain(Some(iterations))
|
||||
.map(|x| x as _),
|
||||
);
|
||||
let proof = generate_proof(&x, iterations as _, k, l, &powers, int_size_bits.into());
|
||||
serialize(&[proof], &powers[&(iterations as _)], int_size_bits.into())
|
||||
}
|
||||
|
||||
pub fn check_proof_of_time_wesolowski<T: BigNum, V: ClassGroup<BigNum = T>>(
|
||||
challenge: &[u8],
|
||||
proof_blob: &[u8],
|
||||
iterations: u64,
|
||||
int_size_bits: u16,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
T: BigNumExt,
|
||||
{
|
||||
let discriminant: T = super::create_discriminant::create_discriminant(challenge, int_size_bits);
|
||||
let x = V::from_ab_discriminant(2.into(), 1.into(), discriminant.clone());
|
||||
if (usize::MAX - 16) < int_size_bits.into() {
|
||||
return Err(());
|
||||
}
|
||||
let int_size = (usize::from(int_size_bits) + 16) >> 4;
|
||||
if int_size * 4 != proof_blob.len() {
|
||||
return Err(());
|
||||
}
|
||||
let (result_bytes, proof_bytes) = proof_blob.split_at(2 * int_size);
|
||||
let proof = ClassGroup::from_bytes(proof_bytes, discriminant.clone());
|
||||
let y = ClassGroup::from_bytes(result_bytes, discriminant);
|
||||
|
||||
verify_proof(x, &y, proof, iterations, int_size_bits.into())
|
||||
}
|
811
docker/rustup-init.sh
Executable file
811
docker/rustup-init.sh
Executable file
@ -0,0 +1,811 @@
|
||||
#!/bin/sh
|
||||
# shellcheck shell=dash
|
||||
# shellcheck disable=SC2039 # local is non-POSIX
|
||||
|
||||
# This is just a little script that can be downloaded from the internet to
|
||||
# install rustup. It just does platform detection, downloads the installer
|
||||
# and runs it.
|
||||
|
||||
# It runs on Unix shells like {a,ba,da,k,z}sh. It uses the common `local`
|
||||
# extension. Note: Most shells limit `local` to 1 var per line, contra bash.
|
||||
|
||||
# Some versions of ksh have no `local` keyword. Alias it to `typeset`, but
|
||||
# beware this makes variables global with f()-style function syntax in ksh93.
|
||||
# mksh has this alias by default.
|
||||
has_local() {
|
||||
# shellcheck disable=SC2034 # deliberately unused
|
||||
local _has_local
|
||||
}
|
||||
|
||||
has_local 2>/dev/null || alias local=typeset
|
||||
|
||||
is_zsh() {
|
||||
[ -n "${ZSH_VERSION-}" ]
|
||||
}
|
||||
|
||||
set -u
|
||||
|
||||
# If RUSTUP_UPDATE_ROOT is unset or empty, default it.
|
||||
RUSTUP_UPDATE_ROOT="${RUSTUP_UPDATE_ROOT:-https://static.rust-lang.org/rustup}"
|
||||
|
||||
# NOTICE: If you change anything here, please make the same changes in setup_mode.rs
|
||||
usage() {
|
||||
cat <<EOF
|
||||
rustup-init 1.27.1 (a8e4f5c64 2024-04-24)
|
||||
|
||||
The installer for rustup
|
||||
|
||||
Usage: rustup-init[EXE] [OPTIONS]
|
||||
|
||||
Options:
|
||||
-v, --verbose
|
||||
Enable verbose output
|
||||
-q, --quiet
|
||||
Disable progress output
|
||||
-y
|
||||
Disable confirmation prompt.
|
||||
--default-host <default-host>
|
||||
Choose a default host triple
|
||||
--default-toolchain <default-toolchain>
|
||||
Choose a default toolchain to install. Use 'none' to not install any toolchains at all
|
||||
--profile <profile>
|
||||
[default: default] [possible values: minimal, default, complete]
|
||||
-c, --component <components>...
|
||||
Component name to also install
|
||||
-t, --target <targets>...
|
||||
Target name to also install
|
||||
--no-update-default-toolchain
|
||||
Don't update any existing default toolchain after install
|
||||
--no-modify-path
|
||||
Don't configure the PATH environment variable
|
||||
-h, --help
|
||||
Print help
|
||||
-V, --version
|
||||
Print version
|
||||
EOF
|
||||
}
|
||||
|
||||
main() {
|
||||
downloader --check
|
||||
need_cmd uname
|
||||
need_cmd mktemp
|
||||
need_cmd chmod
|
||||
need_cmd mkdir
|
||||
need_cmd rm
|
||||
need_cmd rmdir
|
||||
|
||||
get_architecture || return 1
|
||||
local _arch="$RETVAL"
|
||||
assert_nz "$_arch" "arch"
|
||||
|
||||
local _ext=""
|
||||
case "$_arch" in
|
||||
*windows*)
|
||||
_ext=".exe"
|
||||
;;
|
||||
esac
|
||||
|
||||
local _url="${RUSTUP_UPDATE_ROOT}/dist/${_arch}/rustup-init${_ext}"
|
||||
|
||||
local _dir
|
||||
if ! _dir="$(ensure mktemp -d)"; then
|
||||
# Because the previous command ran in a subshell, we must manually
|
||||
# propagate exit status.
|
||||
exit 1
|
||||
fi
|
||||
local _file="${_dir}/rustup-init${_ext}"
|
||||
|
||||
local _ansi_escapes_are_valid=false
|
||||
if [ -t 2 ]; then
|
||||
if [ "${TERM+set}" = 'set' ]; then
|
||||
case "$TERM" in
|
||||
xterm*|rxvt*|urxvt*|linux*|vt*)
|
||||
_ansi_escapes_are_valid=true
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
fi
|
||||
|
||||
# check if we have to use /dev/tty to prompt the user
|
||||
local need_tty=yes
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
OPTIND=1
|
||||
if [ "${arg%%--*}" = "" ]; then
|
||||
# Long option (other than --help);
|
||||
# don't attempt to interpret it.
|
||||
continue
|
||||
fi
|
||||
while getopts :hy sub_arg "$arg"; do
|
||||
case "$sub_arg" in
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
y)
|
||||
# user wants to skip the prompt --
|
||||
# we don't need /dev/tty
|
||||
need_tty=no
|
||||
;;
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if $_ansi_escapes_are_valid; then
|
||||
printf "\33[1minfo:\33[0m downloading installer\n" 1>&2
|
||||
else
|
||||
printf '%s\n' 'info: downloading installer' 1>&2
|
||||
fi
|
||||
|
||||
ensure mkdir -p "$_dir"
|
||||
ensure downloader "$_url" "$_file" "$_arch"
|
||||
ensure chmod u+x "$_file"
|
||||
if [ ! -x "$_file" ]; then
|
||||
printf '%s\n' "Cannot execute $_file (likely because of mounting /tmp as noexec)." 1>&2
|
||||
printf '%s\n' "Please copy the file to a location where you can execute binaries and run ./rustup-init${_ext}." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "$need_tty" = "yes" ] && [ ! -t 0 ]; then
|
||||
# The installer is going to want to ask for confirmation by
|
||||
# reading stdin. This script was piped into `sh` though and
|
||||
# doesn't have stdin to pass to its children. Instead we're going
|
||||
# to explicitly connect /dev/tty to the installer's stdin.
|
||||
if [ ! -t 1 ]; then
|
||||
err "Unable to run interactively. Run with -y to accept defaults, --help for additional options"
|
||||
fi
|
||||
|
||||
ignore "$_file" "$@" < /dev/tty
|
||||
else
|
||||
ignore "$_file" "$@"
|
||||
fi
|
||||
|
||||
local _retval=$?
|
||||
|
||||
ignore rm "$_file"
|
||||
ignore rmdir "$_dir"
|
||||
|
||||
return "$_retval"
|
||||
}
|
||||
|
||||
check_proc() {
|
||||
# Check for /proc by looking for the /proc/self/exe link
|
||||
# This is only run on Linux
|
||||
if ! test -L /proc/self/exe ; then
|
||||
err "fatal: Unable to find /proc/self/exe. Is /proc mounted? Installation cannot proceed without /proc."
|
||||
fi
|
||||
}
|
||||
|
||||
get_bitness() {
|
||||
need_cmd head
|
||||
# Architecture detection without dependencies beyond coreutils.
|
||||
# ELF files start out "\x7fELF", and the following byte is
|
||||
# 0x01 for 32-bit and
|
||||
# 0x02 for 64-bit.
|
||||
# The printf builtin on some shells like dash only supports octal
|
||||
# escape sequences, so we use those.
|
||||
local _current_exe_head
|
||||
_current_exe_head=$(head -c 5 /proc/self/exe )
|
||||
if [ "$_current_exe_head" = "$(printf '\177ELF\001')" ]; then
|
||||
echo 32
|
||||
elif [ "$_current_exe_head" = "$(printf '\177ELF\002')" ]; then
|
||||
echo 64
|
||||
else
|
||||
err "unknown platform bitness"
|
||||
fi
|
||||
}
|
||||
|
||||
is_host_amd64_elf() {
|
||||
need_cmd head
|
||||
need_cmd tail
|
||||
# ELF e_machine detection without dependencies beyond coreutils.
|
||||
# Two-byte field at offset 0x12 indicates the CPU,
|
||||
# but we're interested in it being 0x3E to indicate amd64, or not that.
|
||||
local _current_exe_machine
|
||||
_current_exe_machine=$(head -c 19 /proc/self/exe | tail -c 1)
|
||||
[ "$_current_exe_machine" = "$(printf '\076')" ]
|
||||
}
|
||||
|
||||
get_endianness() {
|
||||
local cputype=$1
|
||||
local suffix_eb=$2
|
||||
local suffix_el=$3
|
||||
|
||||
# detect endianness without od/hexdump, like get_bitness() does.
|
||||
need_cmd head
|
||||
need_cmd tail
|
||||
|
||||
local _current_exe_endianness
|
||||
_current_exe_endianness="$(head -c 6 /proc/self/exe | tail -c 1)"
|
||||
if [ "$_current_exe_endianness" = "$(printf '\001')" ]; then
|
||||
echo "${cputype}${suffix_el}"
|
||||
elif [ "$_current_exe_endianness" = "$(printf '\002')" ]; then
|
||||
echo "${cputype}${suffix_eb}"
|
||||
else
|
||||
err "unknown platform endianness"
|
||||
fi
|
||||
}
|
||||
|
||||
# Detect the Linux/LoongArch UAPI flavor, with all errors being non-fatal.
|
||||
# Returns 0 or 234 in case of successful detection, 1 otherwise (/tmp being
|
||||
# noexec, or other causes).
|
||||
check_loongarch_uapi() {
|
||||
need_cmd base64
|
||||
|
||||
local _tmp
|
||||
if ! _tmp="$(ensure mktemp)"; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Minimal Linux/LoongArch UAPI detection, exiting with 0 in case of
|
||||
# upstream ("new world") UAPI, and 234 (-EINVAL truncated) in case of
|
||||
# old-world (as deployed on several early commercial Linux distributions
|
||||
# for LoongArch).
|
||||
#
|
||||
# See https://gist.github.com/xen0n/5ee04aaa6cecc5c7794b9a0c3b65fc7f for
|
||||
# source to this helper binary.
|
||||
ignore base64 -d > "$_tmp" <<EOF
|
||||
f0VMRgIBAQAAAAAAAAAAAAIAAgEBAAAAeAAgAAAAAABAAAAAAAAAAAAAAAAAAAAAQQAAAEAAOAAB
|
||||
AAAAAAAAAAEAAAAFAAAAAAAAAAAAAAAAACAAAAAAAAAAIAAAAAAAJAAAAAAAAAAkAAAAAAAAAAAA
|
||||
AQAAAAAABCiAAwUAFQAGABUAByCAAwsYggMAACsAC3iBAwAAKwAxen0n
|
||||
EOF
|
||||
|
||||
ignore chmod u+x "$_tmp"
|
||||
if [ ! -x "$_tmp" ]; then
|
||||
ignore rm "$_tmp"
|
||||
return 1
|
||||
fi
|
||||
|
||||
"$_tmp"
|
||||
local _retval=$?
|
||||
|
||||
ignore rm "$_tmp"
|
||||
return "$_retval"
|
||||
}
|
||||
|
||||
ensure_loongarch_uapi() {
|
||||
check_loongarch_uapi
|
||||
case $? in
|
||||
0)
|
||||
return 0
|
||||
;;
|
||||
234)
|
||||
echo >&2
|
||||
echo 'Your Linux kernel does not provide the ABI required by this Rust' >&2
|
||||
echo 'distribution. Please check with your OS provider for how to obtain a' >&2
|
||||
echo 'compatible Rust package for your system.' >&2
|
||||
echo >&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Warning: Cannot determine current system's ABI flavor, continuing anyway." >&2
|
||||
echo >&2
|
||||
echo 'Note that the official Rust distribution only works with the upstream' >&2
|
||||
echo 'kernel ABI. Installation will fail if your running kernel happens to be' >&2
|
||||
echo 'incompatible.' >&2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
get_architecture() {
|
||||
local _ostype _cputype _bitness _arch _clibtype
|
||||
_ostype="$(uname -s)"
|
||||
_cputype="$(uname -m)"
|
||||
_clibtype="gnu"
|
||||
|
||||
if [ "$_ostype" = Linux ]; then
|
||||
if [ "$(uname -o)" = Android ]; then
|
||||
_ostype=Android
|
||||
fi
|
||||
if ldd --version 2>&1 | grep -q 'musl'; then
|
||||
_clibtype="musl"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$_ostype" = Darwin ]; then
|
||||
# Darwin `uname -m` can lie due to Rosetta shenanigans. If you manage to
|
||||
# invoke a native shell binary and then a native uname binary, you can
|
||||
# get the real answer, but that's hard to ensure, so instead we use
|
||||
# `sysctl` (which doesn't lie) to check for the actual architecture.
|
||||
if [ "$_cputype" = i386 ]; then
|
||||
# Handling i386 compatibility mode in older macOS versions (<10.15)
|
||||
# running on x86_64-based Macs.
|
||||
# Starting from 10.15, macOS explicitly bans all i386 binaries from running.
|
||||
# See: <https://support.apple.com/en-us/HT208436>
|
||||
|
||||
# Avoid `sysctl: unknown oid` stderr output and/or non-zero exit code.
|
||||
if sysctl hw.optional.x86_64 2> /dev/null || true | grep -q ': 1'; then
|
||||
_cputype=x86_64
|
||||
fi
|
||||
elif [ "$_cputype" = x86_64 ]; then
|
||||
# Handling x86-64 compatibility mode (a.k.a. Rosetta 2)
|
||||
# in newer macOS versions (>=11) running on arm64-based Macs.
|
||||
# Rosetta 2 is built exclusively for x86-64 and cannot run i386 binaries.
|
||||
|
||||
# Avoid `sysctl: unknown oid` stderr output and/or non-zero exit code.
|
||||
if sysctl hw.optional.arm64 2> /dev/null || true | grep -q ': 1'; then
|
||||
_cputype=arm64
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$_ostype" = SunOS ]; then
|
||||
# Both Solaris and illumos presently announce as "SunOS" in "uname -s"
|
||||
# so use "uname -o" to disambiguate. We use the full path to the
|
||||
# system uname in case the user has coreutils uname first in PATH,
|
||||
# which has historically sometimes printed the wrong value here.
|
||||
if [ "$(/usr/bin/uname -o)" = illumos ]; then
|
||||
_ostype=illumos
|
||||
fi
|
||||
|
||||
# illumos systems have multi-arch userlands, and "uname -m" reports the
|
||||
# machine hardware name; e.g., "i86pc" on both 32- and 64-bit x86
|
||||
# systems. Check for the native (widest) instruction set on the
|
||||
# running kernel:
|
||||
if [ "$_cputype" = i86pc ]; then
|
||||
_cputype="$(isainfo -n)"
|
||||
fi
|
||||
fi
|
||||
|
||||
case "$_ostype" in
|
||||
|
||||
Android)
|
||||
_ostype=linux-android
|
||||
;;
|
||||
|
||||
Linux)
|
||||
check_proc
|
||||
_ostype=unknown-linux-$_clibtype
|
||||
_bitness=$(get_bitness)
|
||||
;;
|
||||
|
||||
FreeBSD)
|
||||
_ostype=unknown-freebsd
|
||||
;;
|
||||
|
||||
NetBSD)
|
||||
_ostype=unknown-netbsd
|
||||
;;
|
||||
|
||||
DragonFly)
|
||||
_ostype=unknown-dragonfly
|
||||
;;
|
||||
|
||||
Darwin)
|
||||
_ostype=apple-darwin
|
||||
;;
|
||||
|
||||
illumos)
|
||||
_ostype=unknown-illumos
|
||||
;;
|
||||
|
||||
MINGW* | MSYS* | CYGWIN* | Windows_NT)
|
||||
_ostype=pc-windows-gnu
|
||||
;;
|
||||
|
||||
*)
|
||||
err "unrecognized OS type: $_ostype"
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
case "$_cputype" in
|
||||
|
||||
i386 | i486 | i686 | i786 | x86)
|
||||
_cputype=i686
|
||||
;;
|
||||
|
||||
xscale | arm)
|
||||
_cputype=arm
|
||||
if [ "$_ostype" = "linux-android" ]; then
|
||||
_ostype=linux-androideabi
|
||||
fi
|
||||
;;
|
||||
|
||||
armv6l)
|
||||
_cputype=arm
|
||||
if [ "$_ostype" = "linux-android" ]; then
|
||||
_ostype=linux-androideabi
|
||||
else
|
||||
_ostype="${_ostype}eabihf"
|
||||
fi
|
||||
;;
|
||||
|
||||
armv7l | armv8l)
|
||||
_cputype=armv7
|
||||
if [ "$_ostype" = "linux-android" ]; then
|
||||
_ostype=linux-androideabi
|
||||
else
|
||||
_ostype="${_ostype}eabihf"
|
||||
fi
|
||||
;;
|
||||
|
||||
aarch64 | arm64)
|
||||
_cputype=aarch64
|
||||
;;
|
||||
|
||||
x86_64 | x86-64 | x64 | amd64)
|
||||
_cputype=x86_64
|
||||
;;
|
||||
|
||||
mips)
|
||||
_cputype=$(get_endianness mips '' el)
|
||||
;;
|
||||
|
||||
mips64)
|
||||
if [ "$_bitness" -eq 64 ]; then
|
||||
# only n64 ABI is supported for now
|
||||
_ostype="${_ostype}abi64"
|
||||
_cputype=$(get_endianness mips64 '' el)
|
||||
fi
|
||||
;;
|
||||
|
||||
ppc)
|
||||
_cputype=powerpc
|
||||
;;
|
||||
|
||||
ppc64)
|
||||
_cputype=powerpc64
|
||||
;;
|
||||
|
||||
ppc64le)
|
||||
_cputype=powerpc64le
|
||||
;;
|
||||
|
||||
s390x)
|
||||
_cputype=s390x
|
||||
;;
|
||||
riscv64)
|
||||
_cputype=riscv64gc
|
||||
;;
|
||||
loongarch64)
|
||||
_cputype=loongarch64
|
||||
ensure_loongarch_uapi
|
||||
;;
|
||||
*)
|
||||
err "unknown CPU type: $_cputype"
|
||||
|
||||
esac
|
||||
|
||||
# Detect 64-bit linux with 32-bit userland
|
||||
if [ "${_ostype}" = unknown-linux-gnu ] && [ "${_bitness}" -eq 32 ]; then
|
||||
case $_cputype in
|
||||
x86_64)
|
||||
if [ -n "${RUSTUP_CPUTYPE:-}" ]; then
|
||||
_cputype="$RUSTUP_CPUTYPE"
|
||||
else {
|
||||
# 32-bit executable for amd64 = x32
|
||||
if is_host_amd64_elf; then {
|
||||
echo "This host is running an x32 userland; as it stands, x32 support is poor," 1>&2
|
||||
echo "and there isn't a native toolchain -- you will have to install" 1>&2
|
||||
echo "multiarch compatibility with i686 and/or amd64, then select one" 1>&2
|
||||
echo "by re-running this script with the RUSTUP_CPUTYPE environment variable" 1>&2
|
||||
echo "set to i686 or x86_64, respectively." 1>&2
|
||||
echo 1>&2
|
||||
echo "You will be able to add an x32 target after installation by running" 1>&2
|
||||
echo " rustup target add x86_64-unknown-linux-gnux32" 1>&2
|
||||
exit 1
|
||||
}; else
|
||||
_cputype=i686
|
||||
fi
|
||||
}; fi
|
||||
;;
|
||||
mips64)
|
||||
_cputype=$(get_endianness mips '' el)
|
||||
;;
|
||||
powerpc64)
|
||||
_cputype=powerpc
|
||||
;;
|
||||
aarch64)
|
||||
_cputype=armv7
|
||||
if [ "$_ostype" = "linux-android" ]; then
|
||||
_ostype=linux-androideabi
|
||||
else
|
||||
_ostype="${_ostype}eabihf"
|
||||
fi
|
||||
;;
|
||||
riscv64gc)
|
||||
err "riscv64 with 32-bit userland unsupported"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Detect armv7 but without the CPU features Rust needs in that build,
|
||||
# and fall back to arm.
|
||||
# See https://github.com/rust-lang/rustup.rs/issues/587.
|
||||
if [ "$_ostype" = "unknown-linux-gnueabihf" ] && [ "$_cputype" = armv7 ]; then
|
||||
if ensure grep '^Features' /proc/cpuinfo | grep -E -q -v 'neon|simd'; then
|
||||
# At least one processor does not have NEON (which is asimd on armv8+).
|
||||
_cputype=arm
|
||||
fi
|
||||
fi
|
||||
|
||||
_arch="${_cputype}-${_ostype}"
|
||||
|
||||
RETVAL="$_arch"
|
||||
}
|
||||
|
||||
say() {
|
||||
printf 'rustup: %s\n' "$1"
|
||||
}
|
||||
|
||||
err() {
|
||||
say "$1" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
need_cmd() {
|
||||
if ! check_cmd "$1"; then
|
||||
err "need '$1' (command not found)"
|
||||
fi
|
||||
}
|
||||
|
||||
check_cmd() {
|
||||
command -v "$1" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
assert_nz() {
|
||||
if [ -z "$1" ]; then err "assert_nz $2"; fi
|
||||
}
|
||||
|
||||
# Run a command that should never fail. If the command fails execution
|
||||
# will immediately terminate with an error showing the failing
|
||||
# command.
|
||||
ensure() {
|
||||
if ! "$@"; then err "command failed: $*"; fi
|
||||
}
|
||||
|
||||
# This is just for indicating that commands' results are being
|
||||
# intentionally ignored. Usually, because it's being executed
|
||||
# as part of error handling.
|
||||
ignore() {
|
||||
"$@"
|
||||
}
|
||||
|
||||
# This wraps curl or wget. Try curl first, if not installed,
|
||||
# use wget instead.
|
||||
downloader() {
|
||||
# zsh does not split words by default, Required for curl retry arguments below.
|
||||
is_zsh && setopt local_options shwordsplit
|
||||
|
||||
local _dld
|
||||
local _ciphersuites
|
||||
local _err
|
||||
local _status
|
||||
local _retry
|
||||
if check_cmd curl; then
|
||||
_dld=curl
|
||||
elif check_cmd wget; then
|
||||
_dld=wget
|
||||
else
|
||||
_dld='curl or wget' # to be used in error message of need_cmd
|
||||
fi
|
||||
|
||||
if [ "$1" = --check ]; then
|
||||
need_cmd "$_dld"
|
||||
elif [ "$_dld" = curl ]; then
|
||||
check_curl_for_retry_support
|
||||
_retry="$RETVAL"
|
||||
get_ciphersuites_for_curl
|
||||
_ciphersuites="$RETVAL"
|
||||
if [ -n "$_ciphersuites" ]; then
|
||||
_err=$(curl $_retry --proto '=https' --tlsv1.2 --ciphers "$_ciphersuites" --silent --show-error --fail --location "$1" --output "$2" 2>&1)
|
||||
_status=$?
|
||||
else
|
||||
echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
|
||||
if ! check_help_for "$3" curl --proto --tlsv1.2; then
|
||||
echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
|
||||
_err=$(curl $_retry --silent --show-error --fail --location "$1" --output "$2" 2>&1)
|
||||
_status=$?
|
||||
else
|
||||
_err=$(curl $_retry --proto '=https' --tlsv1.2 --silent --show-error --fail --location "$1" --output "$2" 2>&1)
|
||||
_status=$?
|
||||
fi
|
||||
fi
|
||||
if [ -n "$_err" ]; then
|
||||
echo "$_err" >&2
|
||||
if echo "$_err" | grep -q 404$; then
|
||||
err "installer for platform '$3' not found, this may be unsupported"
|
||||
fi
|
||||
fi
|
||||
return $_status
|
||||
elif [ "$_dld" = wget ]; then
|
||||
if [ "$(wget -V 2>&1|head -2|tail -1|cut -f1 -d" ")" = "BusyBox" ]; then
|
||||
echo "Warning: using the BusyBox version of wget. Not enforcing strong cipher suites for TLS or TLS v1.2, this is potentially less secure"
|
||||
_err=$(wget "$1" -O "$2" 2>&1)
|
||||
_status=$?
|
||||
else
|
||||
get_ciphersuites_for_wget
|
||||
_ciphersuites="$RETVAL"
|
||||
if [ -n "$_ciphersuites" ]; then
|
||||
_err=$(wget --https-only --secure-protocol=TLSv1_2 --ciphers "$_ciphersuites" "$1" -O "$2" 2>&1)
|
||||
_status=$?
|
||||
else
|
||||
echo "Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure"
|
||||
if ! check_help_for "$3" wget --https-only --secure-protocol; then
|
||||
echo "Warning: Not enforcing TLS v1.2, this is potentially less secure"
|
||||
_err=$(wget "$1" -O "$2" 2>&1)
|
||||
_status=$?
|
||||
else
|
||||
_err=$(wget --https-only --secure-protocol=TLSv1_2 "$1" -O "$2" 2>&1)
|
||||
_status=$?
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
if [ -n "$_err" ]; then
|
||||
echo "$_err" >&2
|
||||
if echo "$_err" | grep -q ' 404 Not Found$'; then
|
||||
err "installer for platform '$3' not found, this may be unsupported"
|
||||
fi
|
||||
fi
|
||||
return $_status
|
||||
else
|
||||
err "Unknown downloader" # should not reach here
|
||||
fi
|
||||
}
|
||||
|
||||
check_help_for() {
|
||||
local _arch
|
||||
local _cmd
|
||||
local _arg
|
||||
_arch="$1"
|
||||
shift
|
||||
_cmd="$1"
|
||||
shift
|
||||
|
||||
local _category
|
||||
if "$_cmd" --help | grep -q 'For all options use the manual or "--help all".'; then
|
||||
_category="all"
|
||||
else
|
||||
_category=""
|
||||
fi
|
||||
|
||||
case "$_arch" in
|
||||
|
||||
*darwin*)
|
||||
if check_cmd sw_vers; then
|
||||
case $(sw_vers -productVersion) in
|
||||
10.*)
|
||||
# If we're running on macOS, older than 10.13, then we always
|
||||
# fail to find these options to force fallback
|
||||
if [ "$(sw_vers -productVersion | cut -d. -f2)" -lt 13 ]; then
|
||||
# Older than 10.13
|
||||
echo "Warning: Detected macOS platform older than 10.13"
|
||||
return 1
|
||||
fi
|
||||
;;
|
||||
11.*)
|
||||
# We assume Big Sur will be OK for now
|
||||
;;
|
||||
*)
|
||||
# Unknown product version, warn and continue
|
||||
echo "Warning: Detected unknown macOS major version: $(sw_vers -productVersion)"
|
||||
echo "Warning TLS capabilities detection may fail"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
;;
|
||||
|
||||
esac
|
||||
|
||||
for _arg in "$@"; do
|
||||
if ! "$_cmd" --help "$_category" | grep -q -- "$_arg"; then
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
true # not strictly needed
|
||||
}
|
||||
|
||||
# Check if curl supports the --retry flag, then pass it to the curl invocation.
|
||||
check_curl_for_retry_support() {
|
||||
local _retry_supported=""
|
||||
# "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
|
||||
if check_help_for "notspecified" "curl" "--retry"; then
|
||||
_retry_supported="--retry 3"
|
||||
if check_help_for "notspecified" "curl" "--continue-at"; then
|
||||
# "-C -" tells curl to automatically find where to resume the download when retrying.
|
||||
_retry_supported="--retry 3 -C -"
|
||||
fi
|
||||
fi
|
||||
|
||||
RETVAL="$_retry_supported"
|
||||
}
|
||||
|
||||
# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
|
||||
# if support by local tools is detected. Detection currently supports these curl backends:
|
||||
# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
|
||||
get_ciphersuites_for_curl() {
|
||||
if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then
|
||||
# user specified custom cipher suites, assume they know what they're doing
|
||||
RETVAL="$RUSTUP_TLS_CIPHERSUITES"
|
||||
return
|
||||
fi
|
||||
|
||||
local _openssl_syntax="no"
|
||||
local _gnutls_syntax="no"
|
||||
local _backend_supported="yes"
|
||||
if curl -V | grep -q ' OpenSSL/'; then
|
||||
_openssl_syntax="yes"
|
||||
elif curl -V | grep -iq ' LibreSSL/'; then
|
||||
_openssl_syntax="yes"
|
||||
elif curl -V | grep -iq ' BoringSSL/'; then
|
||||
_openssl_syntax="yes"
|
||||
elif curl -V | grep -iq ' GnuTLS/'; then
|
||||
_gnutls_syntax="yes"
|
||||
else
|
||||
_backend_supported="no"
|
||||
fi
|
||||
|
||||
local _args_supported="no"
|
||||
if [ "$_backend_supported" = "yes" ]; then
|
||||
# "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
|
||||
if check_help_for "notspecified" "curl" "--tlsv1.2" "--ciphers" "--proto"; then
|
||||
_args_supported="yes"
|
||||
fi
|
||||
fi
|
||||
|
||||
local _cs=""
|
||||
if [ "$_args_supported" = "yes" ]; then
|
||||
if [ "$_openssl_syntax" = "yes" ]; then
|
||||
_cs=$(get_strong_ciphersuites_for "openssl")
|
||||
elif [ "$_gnutls_syntax" = "yes" ]; then
|
||||
_cs=$(get_strong_ciphersuites_for "gnutls")
|
||||
fi
|
||||
fi
|
||||
|
||||
RETVAL="$_cs"
|
||||
}
|
||||
|
||||
# Return cipher suite string specified by user, otherwise return strong TLS 1.2-1.3 cipher suites
|
||||
# if support by local tools is detected. Detection currently supports these wget backends:
|
||||
# GnuTLS and OpenSSL (possibly also LibreSSL and BoringSSL). Return value can be empty.
|
||||
get_ciphersuites_for_wget() {
|
||||
if [ -n "${RUSTUP_TLS_CIPHERSUITES-}" ]; then
|
||||
# user specified custom cipher suites, assume they know what they're doing
|
||||
RETVAL="$RUSTUP_TLS_CIPHERSUITES"
|
||||
return
|
||||
fi
|
||||
|
||||
local _cs=""
|
||||
if wget -V | grep -q '\-DHAVE_LIBSSL'; then
|
||||
# "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
|
||||
if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
|
||||
_cs=$(get_strong_ciphersuites_for "openssl")
|
||||
fi
|
||||
elif wget -V | grep -q '\-DHAVE_LIBGNUTLS'; then
|
||||
# "unspecified" is for arch, allows for possibility old OS using macports, homebrew, etc.
|
||||
if check_help_for "notspecified" "wget" "TLSv1_2" "--ciphers" "--https-only" "--secure-protocol"; then
|
||||
_cs=$(get_strong_ciphersuites_for "gnutls")
|
||||
fi
|
||||
fi
|
||||
|
||||
RETVAL="$_cs"
|
||||
}
|
||||
|
||||
# Return strong TLS 1.2-1.3 cipher suites in OpenSSL or GnuTLS syntax. TLS 1.2
|
||||
# excludes non-ECDHE and non-AEAD cipher suites. DHE is excluded due to bad
|
||||
# DH params often found on servers (see RFC 7919). Sequence matches or is
|
||||
# similar to Firefox 68 ESR with weak cipher suites disabled via about:config.
|
||||
# $1 must be openssl or gnutls.
|
||||
get_strong_ciphersuites_for() {
|
||||
if [ "$1" = "openssl" ]; then
|
||||
# OpenSSL is forgiving of unknown values, no problems with TLS 1.3 values on versions that don't support it yet.
|
||||
echo "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384"
|
||||
elif [ "$1" = "gnutls" ]; then
|
||||
# GnuTLS isn't forgiving of unknown values, so this may require a GnuTLS version that supports TLS 1.3 even if wget doesn't.
|
||||
# Begin with SECURE128 (and higher) then remove/add to build cipher suites. Produces same 9 cipher suites as OpenSSL but in slightly different order.
|
||||
echo "SECURE128:-VERS-SSL3.0:-VERS-TLS1.0:-VERS-TLS1.1:-VERS-DTLS-ALL:-CIPHER-ALL:-MAC-ALL:-KX-ALL:+AEAD:+ECDHE-ECDSA:+ECDHE-RSA:+AES-128-GCM:+CHACHA20-POLY1305:+AES-256-GCM"
|
||||
fi
|
||||
}
|
||||
|
||||
main "$@" || exit 1
|
36
node/build.sh
Executable file
36
node/build.sh
Executable file
@ -0,0 +1,36 @@
|
||||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
|
||||
# This script builds the node binary for the current platform and statically links it with VDF static lib.
|
||||
# Assumes that the VDF library has been built by running the generate.sh script in the `../vdf` directory.
|
||||
|
||||
ROOT_DIR="${ROOT_DIR:-$( cd "$(dirname "$(realpath "$( dirname "${BASH_SOURCE[0]}" )")")" >/dev/null 2>&1 && pwd )}"
|
||||
|
||||
NODE_DIR="$ROOT_DIR/node"
|
||||
BINARIES_DIR="$ROOT_DIR/target/release"
|
||||
|
||||
pushd "$NODE_DIR" > /dev/null
|
||||
|
||||
export CGO_ENABLED=1
|
||||
export GOEXPERIMENT=arenas
|
||||
|
||||
os_type="$(uname)"
|
||||
case "$os_type" in
|
||||
"Darwin")
|
||||
# Check if the architecture is ARM
|
||||
if [[ "$(uname -m)" == "arm64" ]]; then
|
||||
# MacOS ld doesn't support -Bstatic and -Bdynamic, so it's important that there is only a static version of the library
|
||||
go build -ldflags "-linkmode 'external' -extldflags '-L$BINARIES_DIR -lvdf -ldl -lm'" "$@"
|
||||
else
|
||||
echo "Unsupported platform"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
"Linux")
|
||||
go build -ldflags "-linkmode 'external' -extldflags '-L$BINARIES_DIR -Wl,-Bstatic -lvdf -Wl,-Bdynamic -ldl -lm'" "$@"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported platform"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
@ -13,11 +13,11 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"go.uber.org/zap"
|
||||
"golang.org/x/crypto/sha3"
|
||||
"source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/vdf"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/config"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/keys"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/protobufs"
|
||||
"source.quilibrium.com/quilibrium/monorepo/node/tries"
|
||||
"source.quilibrium.com/quilibrium/monorepo/vdf"
|
||||
)
|
||||
|
||||
type WesolowskiFrameProver struct {
|
||||
@ -42,9 +42,7 @@ func (w *WesolowskiFrameProver) ProveMasterClockFrame(
|
||||
input = append(input, previousFrame.Output[:]...)
|
||||
|
||||
b := sha3.Sum256(input)
|
||||
v := vdf.New(difficulty, b)
|
||||
v.Execute()
|
||||
o := v.GetOutput()
|
||||
o := vdf.WesolowskiSolve(b, difficulty)
|
||||
|
||||
previousSelectorBytes := [516]byte{}
|
||||
copy(previousSelectorBytes[:], previousFrame.Output[:516])
|
||||
@ -113,11 +111,10 @@ func (w *WesolowskiFrameProver) VerifyMasterClockFrame(
|
||||
}
|
||||
|
||||
b := sha3.Sum256(input)
|
||||
v := vdf.New(frame.Difficulty, b)
|
||||
proof := [516]byte{}
|
||||
copy(proof[:], frame.Output)
|
||||
|
||||
if !v.Verify(proof) {
|
||||
if !vdf.WesolowskiVerify(b, frame.Difficulty, proof) {
|
||||
w.logger.Error("invalid proof",
|
||||
zap.Binary("filter", frame.Filter),
|
||||
zap.Uint64("frame_number", frame.FrameNumber),
|
||||
@ -159,10 +156,7 @@ func (w *WesolowskiFrameProver) CreateMasterGenesisFrame(
|
||||
error,
|
||||
) {
|
||||
b := sha3.Sum256(seed)
|
||||
v := vdf.New(difficulty, b)
|
||||
|
||||
v.Execute()
|
||||
o := v.GetOutput()
|
||||
o := vdf.WesolowskiSolve(b, difficulty)
|
||||
inputMessage := o[:]
|
||||
|
||||
w.logger.Debug("proving genesis frame")
|
||||
@ -178,10 +172,7 @@ func (w *WesolowskiFrameProver) CreateMasterGenesisFrame(
|
||||
}
|
||||
|
||||
b = sha3.Sum256(input)
|
||||
v = vdf.New(difficulty, b)
|
||||
|
||||
v.Execute()
|
||||
o = v.GetOutput()
|
||||
o = vdf.WesolowskiSolve(b, difficulty)
|
||||
|
||||
frame := &protobufs.ClockFrame{
|
||||
Filter: filter,
|
||||
@ -248,10 +239,7 @@ func (w *WesolowskiFrameProver) ProveDataClockFrame(
|
||||
input = append(input, commitmentInput...)
|
||||
|
||||
b := sha3.Sum256(input)
|
||||
v := vdf.New(difficulty, b)
|
||||
|
||||
v.Execute()
|
||||
o := v.GetOutput()
|
||||
o := vdf.WesolowskiSolve(b, difficulty)
|
||||
|
||||
// TODO: make this configurable for signing algorithms that allow
|
||||
// user-supplied hash functions
|
||||
@ -341,10 +329,7 @@ func (w *WesolowskiFrameProver) CreateDataGenesisFrame(
|
||||
}
|
||||
|
||||
b := sha3.Sum256(input)
|
||||
v := vdf.New(difficulty, b)
|
||||
|
||||
v.Execute()
|
||||
o := v.GetOutput()
|
||||
o := vdf.WesolowskiSolve(b, difficulty)
|
||||
|
||||
commitments := []*protobufs.InclusionCommitment{}
|
||||
for i, commit := range inclusionProof.InclusionCommitments {
|
||||
@ -438,7 +423,6 @@ func (w *WesolowskiFrameProver) VerifyDataClockFrame(
|
||||
}
|
||||
|
||||
b := sha3.Sum256(input)
|
||||
v := vdf.New(frame.Difficulty, b)
|
||||
proof := [516]byte{}
|
||||
copy(proof[:], frame.Output)
|
||||
|
||||
@ -458,7 +442,7 @@ func (w *WesolowskiFrameProver) VerifyDataClockFrame(
|
||||
)
|
||||
}
|
||||
}
|
||||
if !v.Verify(proof) {
|
||||
if !vdf.WesolowskiVerify(b, frame.Difficulty, proof) {
|
||||
return errors.Wrap(
|
||||
errors.New("invalid proof"),
|
||||
"verify clock frame",
|
||||
@ -585,11 +569,10 @@ func (w *WesolowskiFrameProver) VerifyWeakRecursiveProof(
|
||||
}
|
||||
|
||||
b := sha3.Sum256(input[:len(input)-516])
|
||||
v := vdf.New(difficulty, b)
|
||||
output := [516]byte{}
|
||||
copy(output[:], input[len(input)-516:])
|
||||
|
||||
if v.Verify(output) {
|
||||
if vdf.WesolowskiVerify(b, difficulty, output) {
|
||||
w.logger.Debug("verification succeeded")
|
||||
return true
|
||||
} else {
|
||||
@ -613,10 +596,7 @@ func (w *WesolowskiFrameProver) CalculateChallengeProof(
|
||||
instanceInput := binary.BigEndian.AppendUint32([]byte{}, core)
|
||||
instanceInput = append(instanceInput, input...)
|
||||
b := sha3.Sum256(instanceInput)
|
||||
v := vdf.New(uint32(calibratedDifficulty), b)
|
||||
|
||||
v.Execute()
|
||||
o := v.GetOutput()
|
||||
o := vdf.WesolowskiSolve(b, uint32(calibratedDifficulty))
|
||||
|
||||
output := make([]byte, 516)
|
||||
copy(output[:], o[:])
|
||||
@ -654,15 +634,13 @@ func (w *WesolowskiFrameProver) VerifyChallengeProof(
|
||||
skew := (assertedDifficulty * 12) / 10
|
||||
calibratedDifficulty := (int64(proofDuration) * 10000) / skew
|
||||
|
||||
v := vdf.New(uint32(calibratedDifficulty), b)
|
||||
check := v.Verify([516]byte(proof[i]))
|
||||
check := vdf.WesolowskiVerify(b, uint32(calibratedDifficulty), [516]byte(proof[i]))
|
||||
if !check {
|
||||
// TODO: Remove after 2024-05-28
|
||||
if time.Now().Before(config.GetMinimumVersionCutoff()) {
|
||||
calibratedDifficulty = (int64(proofDuration) / skew) * 10000
|
||||
|
||||
v = vdf.New(uint32(calibratedDifficulty), sha3.Sum256(input))
|
||||
check = v.Verify([516]byte(proof[i]))
|
||||
check = vdf.WesolowskiVerify(sha3.Sum256(input), uint32(calibratedDifficulty), [516]byte(proof[i]))
|
||||
if !check {
|
||||
return false
|
||||
}
|
||||
|
21
node/go.mod
21
node/go.mod
@ -5,6 +5,8 @@ go 1.20
|
||||
// A necessary hack until source.quilibrium.com is open to all
|
||||
replace source.quilibrium.com/quilibrium/monorepo/nekryptology => ../nekryptology
|
||||
|
||||
replace source.quilibrium.com/quilibrium/monorepo/vdf => ../vdf
|
||||
|
||||
replace github.com/libp2p/go-libp2p => ../go-libp2p
|
||||
|
||||
replace github.com/libp2p/go-libp2p-gostream => ../go-libp2p-gostream
|
||||
@ -23,6 +25,7 @@ require (
|
||||
gopkg.in/yaml.v2 v2.4.0
|
||||
source.quilibrium.com/quilibrium/monorepo/go-libp2p-blossomsub v0.0.0-00010101000000-000000000000
|
||||
source.quilibrium.com/quilibrium/monorepo/nekryptology v0.0.0-00010101000000-000000000000
|
||||
source.quilibrium.com/quilibrium/monorepo/vdf v0.0.0-00010101000000-000000000000
|
||||
)
|
||||
|
||||
require (
|
||||
@ -64,7 +67,7 @@ require (
|
||||
github.com/quic-go/qtls-go1-19 v0.3.3 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.2.3 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
golang.org/x/term v0.16.0
|
||||
golang.org/x/term v0.21.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
@ -144,7 +147,7 @@ require (
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
|
||||
github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/polydawn/refmt v0.89.0 // indirect
|
||||
github.com/prometheus/client_golang v1.16.0 // indirect
|
||||
@ -164,14 +167,14 @@ require (
|
||||
go.uber.org/fx v1.20.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0
|
||||
golang.org/x/crypto v0.18.0
|
||||
golang.org/x/crypto v0.24.0
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
|
||||
golang.org/x/mod v0.12.0 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/sync v0.6.0
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/net v0.25.0 // indirect
|
||||
golang.org/x/sync v0.7.0
|
||||
golang.org/x/sys v0.21.0
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
||||
gonum.org/v1/gonum v0.11.0 // indirect
|
||||
google.golang.org/grpc v1.58.2
|
||||
lukechampine.com/blake3 v1.2.1 // indirect
|
||||
|
23
node/go.sum
23
node/go.sum
@ -111,6 +111,7 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME
|
||||
github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
|
||||
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
@ -161,6 +162,7 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
|
||||
@ -229,11 +231,14 @@ github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZl
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
|
||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
@ -315,6 +320,7 @@ github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dz
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/mr-tron/base58 v1.1.3/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
@ -353,6 +359,7 @@ github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXS
|
||||
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
|
||||
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
@ -512,6 +519,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
|
||||
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63/go.mod h1:0v4NqG35kSWCMzLaMeX+IQrlSnVE/bqGSyC2cz/9Le8=
|
||||
@ -528,6 +537,8 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@ -548,6 +559,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@ -563,6 +576,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@ -585,14 +600,20 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
|
||||
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@ -616,6 +637,8 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E=
|
||||
golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
17
node/test.sh
Executable file
17
node/test.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
|
||||
# Run tests for the node package. Takes care of linking the native VDF.
|
||||
# Assumes that the VDF library has been built by running the generate.sh script in the `../vdf` directory.
|
||||
|
||||
ROOT_DIR="${ROOT_DIR:-$( cd "$(dirname "$(realpath "$( dirname "${BASH_SOURCE[0]}" )")")" >/dev/null 2>&1 && pwd )}"
|
||||
|
||||
NODE_DIR="$ROOT_DIR/node"
|
||||
BINARIES_DIR="$ROOT_DIR/target/release"
|
||||
|
||||
# Link the native VDF and execute tests
|
||||
pushd "$NODE_DIR" > /dev/null
|
||||
CGO_LDFLAGS="-L$BINARIES_DIR -lvdf -ldl" \
|
||||
CGO_ENABLED=1 \
|
||||
GOEXPERIMENT=arenas \
|
||||
go test "$@"
|
1
vdf/.gitignore
vendored
Normal file
1
vdf/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
generated
|
9
vdf/REAMDE.md
Normal file
9
vdf/REAMDE.md
Normal file
@ -0,0 +1,9 @@
|
||||
# VDF
|
||||
|
||||
Wrapper for the Rust implementation of the VDF (Verifiable Delay Function) in [crates/vdf](../crates/vdf).
|
||||
|
||||
## Generate Go bindings
|
||||
|
||||
```sh
|
||||
go generate
|
||||
```
|
14
vdf/generate.sh
Executable file
14
vdf/generate.sh
Executable file
@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
|
||||
ROOT_DIR="${ROOT_DIR:-$( cd "$(dirname "$(realpath "$( dirname "${BASH_SOURCE[0]}" )")")" >/dev/null 2>&1 && pwd )}"
|
||||
|
||||
RUST_VDF_PACKAGE="$ROOT_DIR/crates/vdf"
|
||||
BINDINGS_DIR="$ROOT_DIR/vdf"
|
||||
|
||||
# Build the Rust VDF package in release mode
|
||||
RUSTFLAGS='-L /opt/homebrew/Cellar/gmp/6.3.0/lib' cargo build -p vdf --release
|
||||
|
||||
# Generate Go bindings
|
||||
pushd "$RUST_VDF_PACKAGE" > /dev/null
|
||||
uniffi-bindgen-go src/lib.udl -o "$BINDINGS_DIR"/generated
|
12
vdf/go.mod
Normal file
12
vdf/go.mod
Normal file
@ -0,0 +1,12 @@
|
||||
module source.quilibrium.com/quilibrium/monorepo/vdf
|
||||
|
||||
go 1.20
|
||||
|
||||
// A necessary hack until source.quilibrium.com is open to all
|
||||
replace source.quilibrium.com/quilibrium/monorepo/nekryptology => ../nekryptology
|
||||
|
||||
require (
|
||||
golang.org/x/crypto v0.24.0 // indirect
|
||||
golang.org/x/sys v0.21.0 // indirect
|
||||
source.quilibrium.com/quilibrium/monorepo/nekryptology v0.0.0-00010101000000-000000000000 // indirect
|
||||
)
|
4
vdf/go.sum
Normal file
4
vdf/go.sum
Normal file
@ -0,0 +1,4 @@
|
||||
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
17
vdf/test.sh
Executable file
17
vdf/test.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
set -euxo pipefail
|
||||
|
||||
# Run tests for the vdf package. Takes care of linking the native VDF.
|
||||
# Assumes that the VDF library has been built by running the generate.sh script in the same directory.
|
||||
|
||||
ROOT_DIR="${ROOT_DIR:-$( cd "$(dirname "$(realpath "$( dirname "${BASH_SOURCE[0]}" )")")" >/dev/null 2>&1 && pwd )}"
|
||||
|
||||
NODE_DIR="$ROOT_DIR/vdf"
|
||||
BINARIES_DIR="$ROOT_DIR/target/release"
|
||||
|
||||
# Link the native VDF and execute tests
|
||||
pushd "$NODE_DIR" > /dev/null
|
||||
CGO_LDFLAGS="-L$BINARIES_DIR -lvdf -ldl" \
|
||||
CGO_ENABLED=1 \
|
||||
GOEXPERIMENT=arenas \
|
||||
go test "$@"
|
21
vdf/vdf.go
Normal file
21
vdf/vdf.go
Normal file
@ -0,0 +1,21 @@
|
||||
package vdf
|
||||
|
||||
import (
|
||||
generated "source.quilibrium.com/quilibrium/monorepo/vdf/generated/vdf"
|
||||
)
|
||||
|
||||
//go:generate ./generate.sh
|
||||
|
||||
const intSizeBits = uint16(2048)
|
||||
|
||||
// WesolowskiSolve Solve and prove with the Wesolowski VDF using the given parameters.
|
||||
// Outputs the concatenated solution and proof (in this order).
|
||||
func WesolowskiSolve(challenge [32]byte, difficulty uint32) [516]byte {
|
||||
return [516]byte(generated.WesolowskiSolve(intSizeBits, challenge[:], difficulty))
|
||||
}
|
||||
|
||||
// WesolowskiVerify Verify with the Wesolowski VDF using the given parameters.
|
||||
// `allegedSolution` is the output of `WesolowskiSolve`.
|
||||
func WesolowskiVerify(challenge [32]byte, difficulty uint32, allegedSolution [516]byte) bool {
|
||||
return generated.WesolowskiVerify(intSizeBits, challenge[:], difficulty, allegedSolution[:])
|
||||
}
|
53
vdf/vdf_test.go
Normal file
53
vdf/vdf_test.go
Normal file
@ -0,0 +1,53 @@
|
||||
package vdf_test
|
||||
|
||||
import (
|
||||
"golang.org/x/crypto/sha3"
|
||||
nekrovdf "source.quilibrium.com/quilibrium/monorepo/nekryptology/pkg/vdf"
|
||||
"source.quilibrium.com/quilibrium/monorepo/vdf"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func getChallenge(seed string) [32]byte {
|
||||
return sha3.Sum256([]byte(seed))
|
||||
}
|
||||
|
||||
func TestProveVerify(t *testing.T) {
|
||||
difficulty := uint32(10000)
|
||||
challenge := getChallenge("TestProveVerify")
|
||||
solution := vdf.WesolowskiSolve(challenge, difficulty)
|
||||
isOk := vdf.WesolowskiVerify(challenge, difficulty, solution)
|
||||
if !isOk {
|
||||
t.Fatalf("Verification failed")
|
||||
}
|
||||
}
|
||||
|
||||
func TestProveRustVerifyNekro(t *testing.T) {
|
||||
difficulty := uint32(100)
|
||||
challenge := getChallenge("TestProveRustVerifyNekro")
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
solution := vdf.WesolowskiSolve(challenge, difficulty)
|
||||
nekroVdf := nekrovdf.New(difficulty, challenge)
|
||||
isOk := nekroVdf.Verify(solution)
|
||||
if !isOk {
|
||||
t.Fatalf("Verification failed")
|
||||
}
|
||||
challenge = sha3.Sum256(solution[:])
|
||||
}
|
||||
}
|
||||
|
||||
func TestProveNekroVerifyRust(t *testing.T) {
|
||||
difficulty := uint32(100)
|
||||
challenge := getChallenge("TestProveNekroVerifyRust")
|
||||
|
||||
for i := 0; i < 100; i++ {
|
||||
nekroVdf := nekrovdf.New(difficulty, challenge)
|
||||
nekroVdf.Execute()
|
||||
proof := nekroVdf.GetOutput()
|
||||
isOk := vdf.WesolowskiVerify(challenge, difficulty, proof)
|
||||
if !isOk {
|
||||
t.Fatalf("Verification failed")
|
||||
}
|
||||
challenge = sha3.Sum256(proof[:])
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user