From 9c22c04af6e57fce8f6ee07f8078cb9ebbe3d6a4 Mon Sep 17 00:00:00 2001 From: Aayush Date: Fri, 11 Aug 2023 15:13:19 -0400 Subject: [PATCH 1/3] feat: perform randomness hashing in the kernel --- Cargo.lock | 2 ++ fvm/Cargo.toml | 2 ++ fvm/src/externs/mod.rs | 14 ++--------- fvm/src/kernel/default.rs | 40 +++++++++++++++++++++++++----- fvm/src/lib.rs | 4 --- fvm/tests/dummy.rs | 4 --- testing/conformance/src/externs.rs | 18 +++----------- testing/conformance/src/rand.rs | 26 +++++-------------- testing/conformance/src/vector.rs | 3 --- testing/integration/src/dummy.rs | 4 --- 10 files changed, 50 insertions(+), 67 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf3429efa..008bbc04e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2326,6 +2326,8 @@ version = "3.5.0" dependencies = [ "anyhow", "arbitrary", + "blake2b_simd", + "byteorder", "cid 0.10.1", "derive_more", "filecoin-proofs-api", diff --git a/fvm/Cargo.toml b/fvm/Cargo.toml index 11e75eb56..c54cc823e 100644 --- a/fvm/Cargo.toml +++ b/fvm/Cargo.toml @@ -38,6 +38,8 @@ rand = "0.8.5" quickcheck = { version = "1", optional = true } once_cell = "1.18" minstant = "0.1.2" +blake2b_simd = "1.0.0" +byteorder = "1.4.3" [dev-dependencies] pretty_assertions = "1.3.0" diff --git a/fvm/src/externs/mod.rs b/fvm/src/externs/mod.rs index dd2da16d2..5025ce74d 100644 --- a/fvm/src/externs/mod.rs +++ b/fvm/src/externs/mod.rs @@ -23,21 +23,11 @@ pub trait Consensus { pub trait Rand { /// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, /// ChainEpoch, Entropy from the ticket chain. - fn get_chain_randomness( - &self, - pers: i64, - round: ChainEpoch, - entropy: &[u8], - ) -> anyhow::Result<[u8; 32]>; + fn get_chain_randomness(&self, round: ChainEpoch) -> anyhow::Result<[u8; 32]>; /// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, /// ChainEpoch, Entropy from the latest beacon entry. - fn get_beacon_randomness( - &self, - pers: i64, - round: ChainEpoch, - entropy: &[u8], - ) -> anyhow::Result<[u8; 32]>; + fn get_beacon_randomness(&self, round: ChainEpoch) -> anyhow::Result<[u8; 32]>; } /// Chain information provider. diff --git a/fvm/src/kernel/default.rs b/fvm/src/kernel/default.rs index 96ba5b323..785cb2ee5 100644 --- a/fvm/src/kernel/default.rs +++ b/fvm/src/kernel/default.rs @@ -6,6 +6,8 @@ use std::panic::{self, UnwindSafe}; use std::path::PathBuf; use anyhow::{anyhow, Context as _}; +use blake2b_simd::Params; +use byteorder::WriteBytesExt; use cid::Cid; use filecoin_proofs_api::{self as proofs, ProverId, PublicReplicaInfo, SectorId}; use fvm_ipld_blockstore::Blockstore; @@ -27,6 +29,7 @@ use lazy_static::lazy_static; use multihash::MultihashDigest; use rayon::iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}; use rayon::prelude::ParallelDrainRange; +use std::io::Write; use super::blocks::{Block, BlockRegistry}; use super::error::Result; @@ -745,6 +748,22 @@ where } } +fn draw_randomness( + rbase: &[u8; RANDOMNESS_LENGTH], + pers: i64, + round: ChainEpoch, + entropy: &[u8], +) -> anyhow::Result<[u8; RANDOMNESS_LENGTH]> { + let mut state = Params::new().hash_length(32).to_state(); + state.write_i64::(pers)?; + state.write_all(rbase)?; + state.write_i64::(round)?; + state.write_all(entropy)?; + let mut ret = [0u8; 32]; + ret.clone_from_slice(state.finalize().as_bytes()); + Ok(ret) +} + impl RandomnessOps for DefaultKernel where C: CallManager, @@ -763,12 +782,17 @@ where // TODO(M2): Check error code // Specifically, lookback length? - t.record( + + let digest = t.record( self.call_manager .externs() - .get_chain_randomness(personalization, rand_epoch, entropy) + .get_chain_randomness(rand_epoch) .or_illegal_argument(), - ) + )?; + + draw_randomness(&digest, personalization, rand_epoch, entropy).map_err(|e| { + syscall_error!(IllegalArgument; "failed to draw chain randmness {}", e).into() + }) } fn get_randomness_from_beacon( @@ -785,12 +809,16 @@ where // TODO(M2): Check error code // Specifically, lookback length? - t.record( + let digest = t.record( self.call_manager .externs() - .get_beacon_randomness(personalization, rand_epoch, entropy) + .get_beacon_randomness(rand_epoch) .or_illegal_argument(), - ) + )?; + + draw_randomness(&digest, personalization, rand_epoch, entropy).map_err(|e| { + syscall_error!(IllegalArgument; "failed to draw beacon randmness {}", e).into() + }) } } diff --git a/fvm/src/lib.rs b/fvm/src/lib.rs index ce7e468e2..dfc7229d4 100644 --- a/fvm/src/lib.rs +++ b/fvm/src/lib.rs @@ -77,9 +77,7 @@ mod test { impl Rand for DummyExterns { fn get_chain_randomness( &self, - _pers: i64, _round: fvm_shared::clock::ChainEpoch, - _entropy: &[u8], ) -> anyhow::Result<[u8; 32]> { let msg = "mel was here".as_bytes(); let mut out = [0u8; 32]; @@ -89,9 +87,7 @@ mod test { fn get_beacon_randomness( &self, - _pers: i64, _round: fvm_shared::clock::ChainEpoch, - _entropy: &[u8], ) -> anyhow::Result<[u8; 32]> { todo!() } diff --git a/fvm/tests/dummy.rs b/fvm/tests/dummy.rs index ccd707efa..377c102d5 100644 --- a/fvm/tests/dummy.rs +++ b/fvm/tests/dummy.rs @@ -35,18 +35,14 @@ impl Externs for DummyExterns {} impl Rand for DummyExterns { fn get_chain_randomness( &self, - _pers: i64, _round: fvm_shared::clock::ChainEpoch, - _entropy: &[u8], ) -> anyhow::Result<[u8; 32]> { todo!() } fn get_beacon_randomness( &self, - _pers: i64, _round: fvm_shared::clock::ChainEpoch, - _entropy: &[u8], ) -> anyhow::Result<[u8; 32]> { todo!() } diff --git a/testing/conformance/src/externs.rs b/testing/conformance/src/externs.rs index 3abfec7d1..9f65a9983 100644 --- a/testing/conformance/src/externs.rs +++ b/testing/conformance/src/externs.rs @@ -25,22 +25,12 @@ impl TestExterns { impl Externs for TestExterns {} impl Rand for TestExterns { - fn get_chain_randomness( - &self, - pers: i64, - round: ChainEpoch, - entropy: &[u8], - ) -> anyhow::Result<[u8; 32]> { - self.rand.get_chain_randomness(pers, round, entropy) + fn get_chain_randomness(&self, round: ChainEpoch) -> anyhow::Result<[u8; 32]> { + self.rand.get_chain_randomness(round) } - fn get_beacon_randomness( - &self, - pers: i64, - round: ChainEpoch, - entropy: &[u8], - ) -> anyhow::Result<[u8; 32]> { - self.rand.get_beacon_randomness(pers, round, entropy) + fn get_beacon_randomness(&self, round: ChainEpoch) -> anyhow::Result<[u8; 32]> { + self.rand.get_beacon_randomness(round) } } diff --git a/testing/conformance/src/rand.rs b/testing/conformance/src/rand.rs index 204795d48..30e5f09a6 100644 --- a/testing/conformance/src/rand.rs +++ b/testing/conformance/src/rand.rs @@ -20,11 +20,11 @@ pub struct ReplayingRand { pub struct TestFallbackRand; impl Rand for TestFallbackRand { - fn get_chain_randomness(&self, _: i64, _: ChainEpoch, _: &[u8]) -> anyhow::Result<[u8; 32]> { + fn get_chain_randomness(&self, _: ChainEpoch) -> anyhow::Result<[u8; 32]> { Ok(*b"i_am_random_____i_am_random_____") } - fn get_beacon_randomness(&self, _: i64, _: ChainEpoch, _: &[u8]) -> anyhow::Result<[u8; 32]> { + fn get_beacon_randomness(&self, _: ChainEpoch) -> anyhow::Result<[u8; 32]> { Ok(*b"i_am_random_____i_am_random_____") } } @@ -50,40 +50,26 @@ impl ReplayingRand { } impl Rand for ReplayingRand { - fn get_chain_randomness( - &self, - dst: i64, - epoch: ChainEpoch, - entropy: &[u8], - ) -> anyhow::Result<[u8; 32]> { + fn get_chain_randomness(&self, epoch: ChainEpoch) -> anyhow::Result<[u8; 32]> { let rule = RandomnessRule { kind: RandomnessKind::Chain, - dst, epoch, - entropy: entropy.to_vec(), }; if let Some(bz) = self.matches(rule) { Ok(bz) } else { - self.fallback.get_chain_randomness(dst, epoch, entropy) + self.fallback.get_chain_randomness(epoch) } } - fn get_beacon_randomness( - &self, - dst: i64, - epoch: ChainEpoch, - entropy: &[u8], - ) -> anyhow::Result<[u8; 32]> { + fn get_beacon_randomness(&self, epoch: ChainEpoch) -> anyhow::Result<[u8; 32]> { let rule = RandomnessRule { kind: RandomnessKind::Beacon, - dst, epoch, - entropy: entropy.to_vec(), }; if let Some(bz) = self.matches(rule) { Ok(bz) } else { - self.fallback.get_beacon_randomness(dst, epoch, entropy) + self.fallback.get_beacon_randomness(epoch) } } } diff --git a/testing/conformance/src/vector.rs b/testing/conformance/src/vector.rs index 857967342..bc1459e6f 100644 --- a/testing/conformance/src/vector.rs +++ b/testing/conformance/src/vector.rs @@ -117,10 +117,7 @@ pub enum RandomnessKind { #[derive(Debug, Deserialize_tuple, PartialEq, Eq, Clone)] pub struct RandomnessRule { pub kind: RandomnessKind, - pub dst: i64, pub epoch: ChainEpoch, - #[serde(with = "base64_bytes")] - pub entropy: Vec, } #[derive(Debug, Deserialize, Clone)] diff --git a/testing/integration/src/dummy.rs b/testing/integration/src/dummy.rs index 3eeb37755..1e7f1ebd9 100644 --- a/testing/integration/src/dummy.rs +++ b/testing/integration/src/dummy.rs @@ -14,9 +14,7 @@ impl Externs for DummyExterns {} impl Rand for DummyExterns { fn get_chain_randomness( &self, - _pers: i64, _round: fvm_shared::clock::ChainEpoch, - _entropy: &[u8], ) -> anyhow::Result<[u8; 32]> { let rng: String = thread_rng() .sample_iter(&Alphanumeric) @@ -29,9 +27,7 @@ impl Rand for DummyExterns { fn get_beacon_randomness( &self, - _pers: i64, _round: fvm_shared::clock::ChainEpoch, - _entropy: &[u8], ) -> anyhow::Result<[u8; 32]> { let rng: String = thread_rng() .sample_iter(&Alphanumeric) From d710e068d2cb7828e7c3ab9ed740bf9862d554be Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 16 Aug 2023 12:48:28 -0400 Subject: [PATCH 2/3] address review --- fvm/src/kernel/default.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/fvm/src/kernel/default.rs b/fvm/src/kernel/default.rs index 785cb2ee5..6a215b72c 100644 --- a/fvm/src/kernel/default.rs +++ b/fvm/src/kernel/default.rs @@ -759,9 +759,11 @@ fn draw_randomness( state.write_all(rbase)?; state.write_i64::(round)?; state.write_all(entropy)?; - let mut ret = [0u8; 32]; - ret.clone_from_slice(state.finalize().as_bytes()); - Ok(ret) + state + .finalize() + .as_bytes() + .try_into() + .map_err(anyhow::Error::from) } impl RandomnessOps for DefaultKernel From d002d4867edb05bbbc342fc90bcef24fd14cf69d Mon Sep 17 00:00:00 2001 From: Aayush Date: Wed, 16 Aug 2023 16:18:44 -0400 Subject: [PATCH 3/3] bump test vectors --- testing/conformance/test-vectors | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testing/conformance/test-vectors b/testing/conformance/test-vectors index e395f7feb..91d0ef7b9 160000 --- a/testing/conformance/test-vectors +++ b/testing/conformance/test-vectors @@ -1 +1 @@ -Subproject commit e395f7febb89b166da0da00f4e65cdac73fc22e3 +Subproject commit 91d0ef7b90f9df8deed63f2d7271ee007ed2494e