From ab6c0172e58b8517edc64a6cd48702bf61276308 Mon Sep 17 00:00:00 2001 From: Aayush Date: Fri, 11 Aug 2023 15:13:19 -0400 Subject: [PATCH] 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 +++++++++++++++++++++++++----- testing/conformance/src/externs.rs | 18 +++----------- testing/conformance/src/rand.rs | 26 +++++-------------- testing/conformance/src/vector.rs | 3 --- testing/integration/src/dummy.rs | 4 --- 8 files changed, 50 insertions(+), 59 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bf3429efa5..008bbc04ee 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 11e75eb562..c54cc823eb 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 dd2da16d28..5025ce74d1 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 96ba5b3239..785cb2ee5c 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/testing/conformance/src/externs.rs b/testing/conformance/src/externs.rs index 3abfec7d1e..9f65a9983b 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 204795d48c..30e5f09a60 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 8579673420..bc1459e6fa 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 3eeb37755f..1e7f1ebd9d 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)