mirror of
https://github.com/sigp/lighthouse.git
synced 2026-04-19 13:58:28 +00:00
Merge branch 'master' into signature-scheme-update
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
[package]
|
||||
name = "vec_shuffle"
|
||||
name = "fisher_yates_shuffle"
|
||||
version = "0.1.0"
|
||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
12
eth2/utils/int_to_bytes/Cargo.toml
Normal file
12
eth2/utils/int_to_bytes/Cargo.toml
Normal file
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "int_to_bytes"
|
||||
version = "0.1.0"
|
||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bytes = "0.4"
|
||||
|
||||
[dev-dependencies]
|
||||
yaml-rust = "0.4.2"
|
||||
hex = "0.3"
|
||||
125
eth2/utils/int_to_bytes/src/lib.rs
Normal file
125
eth2/utils/int_to_bytes/src/lib.rs
Normal file
@@ -0,0 +1,125 @@
|
||||
use bytes::{BufMut, BytesMut};
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 1.
|
||||
pub fn int_to_bytes1(int: u8) -> Vec<u8> {
|
||||
vec![int]
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 2.
|
||||
pub fn int_to_bytes2(int: u16) -> Vec<u8> {
|
||||
let mut bytes = BytesMut::with_capacity(2);
|
||||
bytes.put_u16_le(int);
|
||||
bytes.to_vec()
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 3.
|
||||
///
|
||||
/// An `Option` is returned as Rust does not support a native
|
||||
/// `u24` type.
|
||||
///
|
||||
/// The Eth 2.0 specification uses `int.to_bytes(2, 'little')`, which throws an error if `int`
|
||||
/// doesn't fit within 3 bytes. The specification relies upon implicit asserts for some validity
|
||||
/// conditions, so we ensure the calling function is aware of the error condition as opposed to
|
||||
/// hiding it with a modulo.
|
||||
pub fn int_to_bytes3(int: u32) -> Option<Vec<u8>> {
|
||||
if int < 2_u32.pow(3 * 8) {
|
||||
let mut bytes = BytesMut::with_capacity(4);
|
||||
bytes.put_u32_le(int);
|
||||
Some(bytes[0..3].to_vec())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 4.
|
||||
pub fn int_to_bytes4(int: u32) -> Vec<u8> {
|
||||
let mut bytes = BytesMut::with_capacity(4);
|
||||
bytes.put_u32_le(int);
|
||||
bytes.to_vec()
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 8.
|
||||
pub fn int_to_bytes8(int: u64) -> Vec<u8> {
|
||||
let mut bytes = BytesMut::with_capacity(8);
|
||||
bytes.put_u64_le(int);
|
||||
bytes.to_vec()
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 32.
|
||||
pub fn int_to_bytes32(int: u64) -> Vec<u8> {
|
||||
let mut bytes = BytesMut::with_capacity(32);
|
||||
bytes.put_u64_le(int);
|
||||
bytes.resize(32, 0);
|
||||
bytes.to_vec()
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 48.
|
||||
pub fn int_to_bytes48(int: u64) -> Vec<u8> {
|
||||
let mut bytes = BytesMut::with_capacity(48);
|
||||
bytes.put_u64_le(int);
|
||||
bytes.resize(48, 0);
|
||||
bytes.to_vec()
|
||||
}
|
||||
|
||||
/// Returns `int` as little-endian bytes with a length of 96.
|
||||
pub fn int_to_bytes96(int: u64) -> Vec<u8> {
|
||||
let mut bytes = BytesMut::with_capacity(96);
|
||||
bytes.put_u64_le(int);
|
||||
bytes.resize(96, 0);
|
||||
bytes.to_vec()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use hex;
|
||||
use std::{fs::File, io::prelude::*, path::PathBuf};
|
||||
use yaml_rust::yaml;
|
||||
|
||||
#[test]
|
||||
fn int_to_bytes3_returns_none() {
|
||||
assert_eq!(int_to_bytes3(2_u32.pow(24)), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vectors() {
|
||||
/*
|
||||
* Test vectors are generated here:
|
||||
*
|
||||
* https://github.com/ethereum/eth2.0-test-generators
|
||||
*/
|
||||
let mut file = {
|
||||
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
file_path_buf.push("src/specs/test_vector_int_to_bytes.yml");
|
||||
|
||||
File::open(file_path_buf).unwrap()
|
||||
};
|
||||
|
||||
let mut yaml_str = String::new();
|
||||
|
||||
file.read_to_string(&mut yaml_str).unwrap();
|
||||
|
||||
let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
|
||||
let doc = &docs[0];
|
||||
let test_cases = doc["test_cases"].as_vec().unwrap();
|
||||
|
||||
for test_case in test_cases {
|
||||
let byte_length = test_case["byte_length"].as_i64().unwrap() as u64;
|
||||
let int = test_case["int"].as_i64().unwrap() as u64;
|
||||
let bytes_string = test_case["bytes"].clone().into_string().unwrap();
|
||||
let bytes = hex::decode(bytes_string.replace("0x", "")).unwrap();
|
||||
|
||||
match byte_length {
|
||||
1 => assert_eq!(int_to_bytes1(int as u8), bytes),
|
||||
2 => assert_eq!(int_to_bytes2(int as u16), bytes),
|
||||
3 => assert_eq!(int_to_bytes3(int as u32), Some(bytes)),
|
||||
4 => assert_eq!(int_to_bytes4(int as u32), bytes),
|
||||
8 => assert_eq!(int_to_bytes8(int), bytes),
|
||||
32 => assert_eq!(int_to_bytes32(int), bytes),
|
||||
48 => assert_eq!(int_to_bytes48(int), bytes),
|
||||
96 => assert_eq!(int_to_bytes96(int), bytes),
|
||||
_ => panic!("Unknown byte length in test vector."),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
215
eth2/utils/int_to_bytes/src/specs/test_vector_int_to_bytes.yml
Normal file
215
eth2/utils/int_to_bytes/src/specs/test_vector_int_to_bytes.yml
Normal file
@@ -0,0 +1,215 @@
|
||||
fork: tchaikovsky
|
||||
summary: Test vectors for the `int_to_bytes[n]` functions.`
|
||||
test_suite: int_to_bytes
|
||||
title: int_to_bytes Tests
|
||||
version: 1.0
|
||||
test_cases:
|
||||
- {byte_length: 1, bytes: '0x00', int: 0}
|
||||
- {byte_length: 1, bytes: '0x01', int: 1}
|
||||
- {byte_length: 1, bytes: '0xff', int: 255}
|
||||
- {byte_length: 1, bytes: '0xc0', int: 192}
|
||||
- {byte_length: 1, bytes: '0xc7', int: 199}
|
||||
- {byte_length: 1, bytes: '0xf2', int: 242}
|
||||
- {byte_length: 1, bytes: '0x26', int: 38}
|
||||
- {byte_length: 1, bytes: '0xfb', int: 251}
|
||||
- {byte_length: 1, bytes: '0xd5', int: 213}
|
||||
- {byte_length: 1, bytes: '0x74', int: 116}
|
||||
- {byte_length: 1, bytes: '0xa8', int: 168}
|
||||
- {byte_length: 1, bytes: '0xc6', int: 198}
|
||||
- {byte_length: 1, bytes: '0x3d', int: 61}
|
||||
- {byte_length: 1, bytes: '0xc2', int: 194}
|
||||
- {byte_length: 1, bytes: '0x68', int: 104}
|
||||
- {byte_length: 1, bytes: '0x64', int: 100}
|
||||
- {byte_length: 1, bytes: '0xc2', int: 194}
|
||||
- {byte_length: 1, bytes: '0x78', int: 120}
|
||||
- {byte_length: 1, bytes: '0x33', int: 51}
|
||||
- {byte_length: 2, bytes: '0x0000', int: 0}
|
||||
- {byte_length: 2, bytes: '0x0100', int: 1}
|
||||
- {byte_length: 2, bytes: '0xffff', int: 65535}
|
||||
- {byte_length: 2, bytes: '0xedea', int: 60141}
|
||||
- {byte_length: 2, bytes: '0x2d93', int: 37677}
|
||||
- {byte_length: 2, bytes: '0x611e', int: 7777}
|
||||
- {byte_length: 2, bytes: '0x637c', int: 31843}
|
||||
- {byte_length: 2, bytes: '0xe370', int: 28899}
|
||||
- {byte_length: 2, bytes: '0x96b3', int: 45974}
|
||||
- {byte_length: 2, bytes: '0xde44', int: 17630}
|
||||
- {byte_length: 2, bytes: '0xa009', int: 2464}
|
||||
- {byte_length: 2, bytes: '0xf6ba', int: 47862}
|
||||
- {byte_length: 2, bytes: '0xef76', int: 30447}
|
||||
- {byte_length: 2, bytes: '0x7e5f', int: 24446}
|
||||
- {byte_length: 2, bytes: '0x393d', int: 15673}
|
||||
- {byte_length: 2, bytes: '0xc820', int: 8392}
|
||||
- {byte_length: 2, bytes: '0x9031', int: 12688}
|
||||
- {byte_length: 2, bytes: '0x3963', int: 25401}
|
||||
- {byte_length: 2, bytes: '0x033d', int: 15619}
|
||||
- {byte_length: 3, bytes: '0x000000', int: 0}
|
||||
- {byte_length: 3, bytes: '0x010000', int: 1}
|
||||
- {byte_length: 3, bytes: '0xffffff', int: 16777215}
|
||||
- {byte_length: 3, bytes: '0x1fdfb2', int: 11722527}
|
||||
- {byte_length: 3, bytes: '0x2a7504', int: 292138}
|
||||
- {byte_length: 3, bytes: '0x09fb20', int: 2161417}
|
||||
- {byte_length: 3, bytes: '0xa4a6b2', int: 11708068}
|
||||
- {byte_length: 3, bytes: '0x17feb7', int: 12058135}
|
||||
- {byte_length: 3, bytes: '0x3ad0b1', int: 11653178}
|
||||
- {byte_length: 3, bytes: '0xbc92c6', int: 13013692}
|
||||
- {byte_length: 3, bytes: '0xb6c046', int: 4636854}
|
||||
- {byte_length: 3, bytes: '0x937f00', int: 32659}
|
||||
- {byte_length: 3, bytes: '0x8266cb', int: 13330050}
|
||||
- {byte_length: 3, bytes: '0x8136e9', int: 15283841}
|
||||
- {byte_length: 3, bytes: '0xe9e062', int: 6480105}
|
||||
- {byte_length: 3, bytes: '0x50d054', int: 5558352}
|
||||
- {byte_length: 3, bytes: '0xb95340', int: 4215737}
|
||||
- {byte_length: 3, bytes: '0x779f52', int: 5414775}
|
||||
- {byte_length: 3, bytes: '0x15aed0', int: 13676053}
|
||||
- {byte_length: 4, bytes: '0x00000000', int: 0}
|
||||
- {byte_length: 4, bytes: '0x01000000', int: 1}
|
||||
- {byte_length: 4, bytes: '0xffffffff', int: 4294967295}
|
||||
- {byte_length: 4, bytes: '0x389cd0ca', int: 3402669112}
|
||||
- {byte_length: 4, bytes: '0xfb29dc70', int: 1893476859}
|
||||
- {byte_length: 4, bytes: '0xf5f5c999', int: 2580149749}
|
||||
- {byte_length: 4, bytes: '0xf4f0b8d1', int: 3518558452}
|
||||
- {byte_length: 4, bytes: '0x830de883', int: 2213023107}
|
||||
- {byte_length: 4, bytes: '0xe3b4e843', int: 1139324131}
|
||||
- {byte_length: 4, bytes: '0x4c9ce594', int: 2498075724}
|
||||
- {byte_length: 4, bytes: '0xa9826dab', int: 2876080809}
|
||||
- {byte_length: 4, bytes: '0xc40aecb7', int: 3085699780}
|
||||
- {byte_length: 4, bytes: '0x55490416', int: 369379669}
|
||||
- {byte_length: 4, bytes: '0x4f2eedc5', int: 3320655439}
|
||||
- {byte_length: 4, bytes: '0xdd07257e', int: 2116356061}
|
||||
- {byte_length: 4, bytes: '0x481a57e9', int: 3914799688}
|
||||
- {byte_length: 4, bytes: '0x4556a493', int: 2477020741}
|
||||
- {byte_length: 4, bytes: '0xccb781ed', int: 3984701388}
|
||||
- {byte_length: 4, bytes: '0x6b994065', int: 1698732395}
|
||||
- {byte_length: 8, bytes: '0x0000000000000000', int: 0}
|
||||
- {byte_length: 8, bytes: '0x0100000000000000', int: 1}
|
||||
- {byte_length: 8, bytes: '0xffffffff00000000', int: 4294967295}
|
||||
- {byte_length: 8, bytes: '0x77d6e31400000000', int: 350475895}
|
||||
- {byte_length: 8, bytes: '0xf3e681bf00000000', int: 3212961523}
|
||||
- {byte_length: 8, bytes: '0x62fa7bd800000000', int: 3632003682}
|
||||
- {byte_length: 8, bytes: '0x82c67b4500000000', int: 1165739650}
|
||||
- {byte_length: 8, bytes: '0x52577fba00000000', int: 3128907602}
|
||||
- {byte_length: 8, bytes: '0x5eac939b00000000', int: 2610146398}
|
||||
- {byte_length: 8, bytes: '0x12ba143700000000', int: 924105234}
|
||||
- {byte_length: 8, bytes: '0x1d3b893a00000000', int: 982072093}
|
||||
- {byte_length: 8, bytes: '0x8262153000000000', int: 806707842}
|
||||
- {byte_length: 8, bytes: '0xbb9cc58e00000000', int: 2395315387}
|
||||
- {byte_length: 8, bytes: '0x76fef6d100000000', int: 3522625142}
|
||||
- {byte_length: 8, bytes: '0x0fc3d35700000000', int: 1473495823}
|
||||
- {byte_length: 8, bytes: '0xc7f851de00000000', int: 3729914055}
|
||||
- {byte_length: 8, bytes: '0x3a1e5cb200000000', int: 2992381498}
|
||||
- {byte_length: 8, bytes: '0x3b748e3400000000', int: 881751099}
|
||||
- {byte_length: 8, bytes: '0xdc92479600000000', int: 2521273052}
|
||||
- {byte_length: 32, bytes: '0x0000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 0}
|
||||
- {byte_length: 32, bytes: '0x0100000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1}
|
||||
- {byte_length: 32, bytes: '0xffffffff00000000000000000000000000000000000000000000000000000000',
|
||||
int: 4294967295}
|
||||
- {byte_length: 32, bytes: '0x2395ad4c00000000000000000000000000000000000000000000000000000000',
|
||||
int: 1286444323}
|
||||
- {byte_length: 32, bytes: '0x38a735b800000000000000000000000000000000000000000000000000000000',
|
||||
int: 3090523960}
|
||||
- {byte_length: 32, bytes: '0x5a9416e100000000000000000000000000000000000000000000000000000000',
|
||||
int: 3776353370}
|
||||
- {byte_length: 32, bytes: '0x220f757500000000000000000000000000000000000000000000000000000000',
|
||||
int: 1970605858}
|
||||
- {byte_length: 32, bytes: '0x65bf635200000000000000000000000000000000000000000000000000000000',
|
||||
int: 1382268773}
|
||||
- {byte_length: 32, bytes: '0x033f902200000000000000000000000000000000000000000000000000000000',
|
||||
int: 579878659}
|
||||
- {byte_length: 32, bytes: '0x2b2d58ab00000000000000000000000000000000000000000000000000000000',
|
||||
int: 2874682667}
|
||||
- {byte_length: 32, bytes: '0x15af31da00000000000000000000000000000000000000000000000000000000',
|
||||
int: 3660689173}
|
||||
- {byte_length: 32, bytes: '0xd260642e00000000000000000000000000000000000000000000000000000000',
|
||||
int: 778330322}
|
||||
- {byte_length: 32, bytes: '0xcdf8429700000000000000000000000000000000000000000000000000000000',
|
||||
int: 2537748685}
|
||||
- {byte_length: 32, bytes: '0xc9304b0500000000000000000000000000000000000000000000000000000000',
|
||||
int: 88813769}
|
||||
- {byte_length: 32, bytes: '0xf7b7ba0200000000000000000000000000000000000000000000000000000000',
|
||||
int: 45791223}
|
||||
- {byte_length: 32, bytes: '0x1ee262d900000000000000000000000000000000000000000000000000000000',
|
||||
int: 3647136286}
|
||||
- {byte_length: 32, bytes: '0xb34b03d300000000000000000000000000000000000000000000000000000000',
|
||||
int: 3540208563}
|
||||
- {byte_length: 32, bytes: '0x3d52db4d00000000000000000000000000000000000000000000000000000000',
|
||||
int: 1306219069}
|
||||
- {byte_length: 32, bytes: '0xd86db47900000000000000000000000000000000000000000000000000000000',
|
||||
int: 2041867736}
|
||||
- {byte_length: 48, bytes: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 0}
|
||||
- {byte_length: 48, bytes: '0x010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1}
|
||||
- {byte_length: 48, bytes: '0xffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 4294967295}
|
||||
- {byte_length: 48, bytes: '0x61aeae650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1705946721}
|
||||
- {byte_length: 48, bytes: '0xd1c08fac0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 2895102161}
|
||||
- {byte_length: 48, bytes: '0x6f36b6c90000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3384161903}
|
||||
- {byte_length: 48, bytes: '0x102f2f3b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 992947984}
|
||||
- {byte_length: 48, bytes: '0x0f53f9240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 620319503}
|
||||
- {byte_length: 48, bytes: '0x5c1d46b30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3007716700}
|
||||
- {byte_length: 48, bytes: '0x955791510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1368479637}
|
||||
- {byte_length: 48, bytes: '0xf934170f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 253179129}
|
||||
- {byte_length: 48, bytes: '0xc1a8b76f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1874307265}
|
||||
- {byte_length: 48, bytes: '0xdf3f62c20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3261218783}
|
||||
- {byte_length: 48, bytes: '0xbd741bc50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3306910909}
|
||||
- {byte_length: 48, bytes: '0xfe5dc5540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1422220798}
|
||||
- {byte_length: 48, bytes: '0x364f10df0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3742388022}
|
||||
- {byte_length: 48, bytes: '0x4a3909450000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1158232394}
|
||||
- {byte_length: 48, bytes: '0xe04760380000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 945833952}
|
||||
- {byte_length: 48, bytes: '0x755c78540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1417174133}
|
||||
- {byte_length: 96, bytes: '0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 0}
|
||||
- {byte_length: 96, bytes: '0x010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1}
|
||||
- {byte_length: 96, bytes: '0xffffffff0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 4294967295}
|
||||
- {byte_length: 96, bytes: '0xa3274ee20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3796772771}
|
||||
- {byte_length: 96, bytes: '0x1658135c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1544771606}
|
||||
- {byte_length: 96, bytes: '0x2af24fb30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3008361002}
|
||||
- {byte_length: 96, bytes: '0x9e6bc40a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 180644766}
|
||||
- {byte_length: 96, bytes: '0x0745b3c50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3316860167}
|
||||
- {byte_length: 96, bytes: '0xe1b59f830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 2208282081}
|
||||
- {byte_length: 96, bytes: '0x985a9e6e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1855871640}
|
||||
- {byte_length: 96, bytes: '0x3d4e3a090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 154816061}
|
||||
- {byte_length: 96, bytes: '0x6f5dfb630000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1677417839}
|
||||
- {byte_length: 96, bytes: '0x383cdecd0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3453893688}
|
||||
- {byte_length: 96, bytes: '0x38f55ceb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3948737848}
|
||||
- {byte_length: 96, bytes: '0xcd746f5d0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1567585485}
|
||||
- {byte_length: 96, bytes: '0x3d971e910000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 2434701117}
|
||||
- {byte_length: 96, bytes: '0x3adff0c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3237011258}
|
||||
- {byte_length: 96, bytes: '0x5ed40a710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 1896535134}
|
||||
- {byte_length: 96, bytes: '0x755d2ed40000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
|
||||
int: 3559808373}
|
||||
15
eth2/utils/swap_or_not_shuffle/Cargo.toml
Normal file
15
eth2/utils/swap_or_not_shuffle/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "swap_or_not_shuffle"
|
||||
version = "0.1.0"
|
||||
authors = ["Paul Hauner <paul@paulhauner.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bytes = "0.4"
|
||||
hashing = { path = "../hashing" }
|
||||
int_to_bytes = { path = "../int_to_bytes" }
|
||||
|
||||
[dev-dependencies]
|
||||
yaml-rust = "0.4.2"
|
||||
hex = "0.3"
|
||||
ethereum-types = "0.5"
|
||||
178
eth2/utils/swap_or_not_shuffle/src/lib.rs
Normal file
178
eth2/utils/swap_or_not_shuffle/src/lib.rs
Normal file
@@ -0,0 +1,178 @@
|
||||
use bytes::Buf;
|
||||
use hashing::hash;
|
||||
use int_to_bytes::{int_to_bytes1, int_to_bytes4};
|
||||
use std::cmp::max;
|
||||
use std::io::Cursor;
|
||||
|
||||
/// Return `p(index)` in a pseudorandom permutation `p` of `0...list_size-1` with ``seed`` as entropy.
|
||||
///
|
||||
/// Utilizes 'swap or not' shuffling found in
|
||||
/// https://link.springer.com/content/pdf/10.1007%2F978-3-642-32009-5_1.pdf
|
||||
/// See the 'generalized domain' algorithm on page 3.
|
||||
///
|
||||
/// Returns `None` under any of the following conditions:
|
||||
/// - `list_size == 0`
|
||||
/// - `index >= list_size`
|
||||
/// - `list_size > 2**24`
|
||||
/// - `list_size > usize::max_value() / 2`
|
||||
pub fn get_permutated_index(
|
||||
index: usize,
|
||||
list_size: usize,
|
||||
seed: &[u8],
|
||||
shuffle_round_count: u8,
|
||||
) -> Option<usize> {
|
||||
if list_size == 0
|
||||
|| index >= list_size
|
||||
|| list_size > usize::max_value() / 2
|
||||
|| list_size > 2_usize.pow(24)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
let mut index = index;
|
||||
for round in 0..shuffle_round_count {
|
||||
let pivot = bytes_to_int64(&hash_with_round(seed, round)[..]) as usize % list_size;
|
||||
let flip = (pivot + list_size - index) % list_size;
|
||||
let position = max(index, flip);
|
||||
let source = hash_with_round_and_position(seed, round, position)?;
|
||||
let byte = source[(position % 256) / 8];
|
||||
let bit = (byte >> (position % 8)) % 2;
|
||||
index = if bit == 1 { flip } else { index }
|
||||
}
|
||||
Some(index)
|
||||
}
|
||||
|
||||
fn hash_with_round_and_position(seed: &[u8], round: u8, position: usize) -> Option<Vec<u8>> {
|
||||
let mut seed = seed.to_vec();
|
||||
seed.append(&mut int_to_bytes1(round));
|
||||
/*
|
||||
* Note: the specification has an implicit assertion in `int_to_bytes4` that `position / 256 <
|
||||
* 2**24`. For efficiency, we do not check for that here as it is checked in `get_permutated_index`.
|
||||
*/
|
||||
seed.append(&mut int_to_bytes4((position / 256) as u32));
|
||||
Some(hash(&seed[..]))
|
||||
}
|
||||
|
||||
fn hash_with_round(seed: &[u8], round: u8) -> Vec<u8> {
|
||||
let mut seed = seed.to_vec();
|
||||
seed.append(&mut int_to_bytes1(round));
|
||||
hash(&seed[..])
|
||||
}
|
||||
|
||||
fn bytes_to_int64(bytes: &[u8]) -> u64 {
|
||||
let mut cursor = Cursor::new(bytes);
|
||||
cursor.get_u64_le()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use ethereum_types::H256 as Hash256;
|
||||
use hex;
|
||||
use std::{fs::File, io::prelude::*, path::PathBuf};
|
||||
use yaml_rust::yaml;
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn fuzz_test() {
|
||||
let max_list_size = 2_usize.pow(24);
|
||||
let test_runs = 1000;
|
||||
|
||||
// Test at max list_size with the end index.
|
||||
for _ in 0..test_runs {
|
||||
let index = max_list_size - 1;
|
||||
let list_size = max_list_size;
|
||||
let seed = Hash256::random();
|
||||
let shuffle_rounds = 90;
|
||||
|
||||
assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
|
||||
}
|
||||
|
||||
// Test at max list_size low indices.
|
||||
for i in 0..test_runs {
|
||||
let index = i;
|
||||
let list_size = max_list_size;
|
||||
let seed = Hash256::random();
|
||||
let shuffle_rounds = 90;
|
||||
|
||||
assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
|
||||
}
|
||||
|
||||
// Test at max list_size high indices.
|
||||
for i in 0..test_runs {
|
||||
let index = max_list_size - 1 - i;
|
||||
let list_size = max_list_size;
|
||||
let seed = Hash256::random();
|
||||
let shuffle_rounds = 90;
|
||||
|
||||
assert!(get_permutated_index(index, list_size, &seed[..], shuffle_rounds).is_some());
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_none_for_zero_length_list() {
|
||||
assert_eq!(None, get_permutated_index(100, 0, &[42, 42], 90));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_none_for_out_of_bounds_index() {
|
||||
assert_eq!(None, get_permutated_index(100, 100, &[42, 42], 90));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn returns_none_for_too_large_list() {
|
||||
assert_eq!(
|
||||
None,
|
||||
get_permutated_index(100, usize::max_value() / 2, &[42, 42], 90)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vectors() {
|
||||
/*
|
||||
* Test vectors are generated here:
|
||||
*
|
||||
* https://github.com/ethereum/eth2.0-test-generators
|
||||
*/
|
||||
let mut file = {
|
||||
let mut file_path_buf = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
file_path_buf.push("src/specs/test_vector_permutated_index.yml");
|
||||
|
||||
File::open(file_path_buf).unwrap()
|
||||
};
|
||||
|
||||
let mut yaml_str = String::new();
|
||||
|
||||
file.read_to_string(&mut yaml_str).unwrap();
|
||||
|
||||
let docs = yaml::YamlLoader::load_from_str(&yaml_str).unwrap();
|
||||
let doc = &docs[0];
|
||||
let test_cases = doc["test_cases"].as_vec().unwrap();
|
||||
|
||||
for (i, test_case) in test_cases.iter().enumerate() {
|
||||
let index = test_case["index"].as_i64().unwrap() as usize;
|
||||
let list_size = test_case["list_size"].as_i64().unwrap() as usize;
|
||||
let permutated_index = test_case["permutated_index"].as_i64().unwrap() as usize;
|
||||
let shuffle_round_count = test_case["shuffle_round_count"].as_i64().unwrap();
|
||||
let seed_string = test_case["seed"].clone().into_string().unwrap();
|
||||
let seed = hex::decode(seed_string.replace("0x", "")).unwrap();
|
||||
|
||||
let shuffle_round_count = if shuffle_round_count < (u8::max_value() as i64) {
|
||||
shuffle_round_count as u8
|
||||
} else {
|
||||
panic!("shuffle_round_count must be a u8")
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
Some(permutated_index),
|
||||
get_permutated_index(index, list_size, &seed[..], shuffle_round_count),
|
||||
"Failure on case #{} index: {}, list_size: {}, round_count: {}, seed: {}",
|
||||
i,
|
||||
index,
|
||||
list_size,
|
||||
shuffle_round_count,
|
||||
seed_string,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
fork: tchaikovsky
|
||||
summary: Test vectors for list shuffling using `get_permutated_index`
|
||||
test_suite: permutated_index
|
||||
title: Permutated Index Tests
|
||||
version: 1.0
|
||||
test_cases:
|
||||
- {index: 0, list_size: 1, permutated_index: 0, seed: '0xc0c7f226fbd574a8c63dc26864c27833ea931e7c70b34409ba765f3d2031633d',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 0, list_size: 2, permutated_index: 0, seed: '0xb20420b2b7b1c64600cbe962544052d0bbe13da403950d198d4f4ea28762953f',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1, list_size: 2, permutated_index: 0, seed: '0x11f1322c3a4cfce20efb7d7eca50291470043d6e8a2c62956e687571607d3f0e',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 0, list_size: 3, permutated_index: 2, seed: '0x5bd0af3f74fe6986bb99b3ecc0ea15a403456ce708c05ceeeddc0a4205caf072',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1, list_size: 3, permutated_index: 1, seed: '0xba06ff9bde03f37eddeacb261a51109676d549c1bea3b81edd82df68cc03a97f',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 2, list_size: 3, permutated_index: 2, seed: '0xf58a8970c63ca86dd3b8b8a615302ec06cddea1279bf4a2725c781ce6aba348d',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 0, list_size: 1024, permutated_index: 1005, seed: '0x383556e23fcb9e73c23ad33cfb50f4c098f49688a84b128c2885960e5f1b3982',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1023, list_size: 1024, permutated_index: 934, seed: '0x2ee5dab30ad1580cdabb175a4b1512cac5566866d65a15e9e22c8444f460c9dc',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 3925, list_size: 4040, permutated_index: 32, seed: '0x34a3c13f211e63c56e9e1187f31a56a4230d8d5bf5e584f0e4fe93946af91cce',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 885, list_size: 2417, permutated_index: 1822, seed: '0x1346e3970815107154b58b1eff411bfca3342ea0d8282a86304d79d62d5f3c52',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 840, list_size: 1805, permutated_index: 808, seed: '0x0810c104b75e25bf89c0066deebc3461937fc0e72ae04ee74f245616c15718df',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 881, list_size: 1788, permutated_index: 582, seed: '0x34adb35f3fc2880d220e520120a032bbaa0f4bd7a5fcf1c2269de21075e7a464',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1362, list_size: 1817, permutated_index: 1018, seed: '0xc9b0c76e11f4c3c3c38b447aca5352d93132ad5678da420ca2e69d92588e0fba',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 28, list_size: 111, permutated_index: 0, seed: '0x293145c31aeb3eb29ccdf3327d0f3dd4592cdfb2fad3703229c6c2e720dc792f',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 959, list_size: 2558, permutated_index: 2094, seed: '0xc9f4c5fbb2a397fd8ea36dbfcec0d733d0af7ec3a03d789a66231f3bc7cafa5e',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 887, list_size: 2406, permutated_index: 831, seed: '0x565729e0d5de524e6dee54d1b8b5882ad8e55c18a30462ac02c4bb86c27d26cb',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 3526, list_size: 3674, permutated_index: 3531, seed: '0x2951395b1a1bbda8d53b776c7fc8bdad6030de943c4e3f938202ac553f44381d',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 978, list_size: 3175, permutated_index: 2257, seed: '0x74aac23523cb45b7ee52d5d2f7b2d24ebc6bf2d63ef189efccabc4a16bb17cd8',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 37, list_size: 231, permutated_index: 48, seed: '0xe4083e61b31931bad662392758e8bc30a4ce7b26b6897c2221a3358f25fdc1d8',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 340, list_size: 693, permutated_index: 234, seed: '0x8089c1f242aa48c6611180f221c120e930adeecaf3084b2b85f9b1dfebe34f63',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 0, list_size: 9, permutated_index: 1, seed: '0x7fda0ab6a746b6b0206febb8259891e0e6f88bf52143b20d6c78caf7caf8e7b3',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 200, list_size: 1108, permutated_index: 952, seed: '0x87b210d000b5f57e9834388d4bc2b86ae8b31383fa10a34b029546c2ebabb807',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1408, list_size: 1531, permutated_index: 584, seed: '0x0670a78b38e0419aaead5d1cc8f40f58044b7076ced8193c08b580dd95a13555',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1704, list_size: 1863, permutated_index: 1022, seed: '0xdbf78665190a6133191e91ab35b1106e8984dfc0dfa36018004f880b431c2a14',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 793, list_size: 3938, permutated_index: 2607, seed: '0x54bf0192292ffae0bf39b39f12e0540b97591af0a2980d32f277bd33201395d3',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 14, list_size: 28, permutated_index: 10, seed: '0x43054417c6056404c586c907dfc5fceb66ebef541d143b00a3b676f3c0fbf4c5',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 2909, list_size: 3920, permutated_index: 726, seed: '0x5eabf289fdcfe0a3aba33a185fb1a4ae2f2b6f78daf61f5d356971e0cb270207',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1943, list_size: 1959, permutated_index: 1292, seed: '0xca86322db56927d727101e31c93f616f746317d29aa10d88f371592963de92aa',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1647, list_size: 2094, permutated_index: 1805, seed: '0x3cfe274230a112bc68614882645339fda2f134501a042079d620ec65cf8d3fa6',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1012, list_size: 1877, permutated_index: 216, seed: '0x7b5ff8a848af32d85c6d37c26e61a57e96780fcebc350ad1845e83fe5e4679ac',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 35, list_size: 2081, permutated_index: 1458, seed: '0x40691aa31a49c2391e025ec272c812510cb07c055f6201e84479499326330628',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1136, list_size: 2189, permutated_index: 1579, seed: '0x31a0deb2c8c5f809f413b7a36ec680ee8b19bbb9a39c4e207326155864bc8be5',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1775, list_size: 3434, permutated_index: 707, seed: '0x92f30d8556382b72a5797db811486e7a213e0145d6c946e5121aa6a8f761d164',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1109, list_size: 2010, permutated_index: 433, seed: '0x093fb976f2497361897012dfa6dc019009eda2e48bbeb4b7c56d4aa5da7d5f87',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 359, list_size: 538, permutated_index: 115, seed: '0xa79b35beacbe48c662d60884c704040024c55ab879e5f61521013c5f45eb3b70',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1259, list_size: 1473, permutated_index: 1351, seed: '0x02c53c9c6ddf259716ff02e49a294eba33e4ad255d7e90dbefdbc991adf603e5',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 2087, list_size: 2634, permutated_index: 1497, seed: '0xa5a4c57c5705ec697a74e6c7161191b18f58ca882a0fcc18f68dc3b57a1aa5b6',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 2069, list_size: 2511, permutated_index: 1837, seed: '0xe7051ebc07f2e7b4d4b28f48d1e42d7b9dcec31c240ca6e1a0c06139ccfc4b8f',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 1660, list_size: 3932, permutated_index: 3046, seed: '0x8687c029ffc443879527a64c31b7acbb38ab6e343779d0b2c6e250046fdb9de8',
|
||||
shuffle_round_count: 90}
|
||||
- {index: 379, list_size: 646, permutated_index: 32, seed: '0x17e854f4e80401345e13f72af45b221c9f7a840f6a8c1328ddf9c9ca9a088379',
|
||||
shuffle_round_count: 90}
|
||||
Reference in New Issue
Block a user