Skip to content

Commit afd34e0

Browse files
arajasekStebalien
authored andcommitted
feat: FVM no longer draws randomness for you (#1378)
1 parent 467e0d7 commit afd34e0

File tree

4 files changed

+84
-4
lines changed

4 files changed

+84
-4
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

runtime/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ blake2b_simd = { workspace = true, optional = true }
4444
hex = { workspace = true, optional = true }
4545
pretty_env_logger = { workspace = true, optional = true }
4646
rand = { workspace = true, optional = true }
47+
base64 = "0.21.2"
4748

4849
[dependencies.libsecp256k1]
4950
workspace = true

runtime/src/runtime/fvm.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use std::cell::RefCell;
3636

3737
use crate::runtime::actor_blockstore::ActorBlockstore;
3838
use crate::runtime::builtins::Type;
39+
use crate::runtime::randomness::draw_randomness;
3940
use crate::runtime::{
4041
ActorCode, ConsensusFault, DomainSeparationTag, MessageInfo, Policy, Primitives, RuntimePolicy,
4142
Verifier,
@@ -231,14 +232,21 @@ where
231232
rand_epoch: ChainEpoch,
232233
entropy: &[u8],
233234
) -> Result<[u8; RANDOMNESS_LENGTH], ActorError> {
234-
fvm::rand::get_chain_randomness(personalization as i64, rand_epoch, entropy).map_err(|e| {
235+
let digest = fvm::rand::get_chain_randomness(rand_epoch).map_err(|e| {
235236
match e {
236237
ErrorNumber::LimitExceeded => {
237238
actor_error!(illegal_argument; "randomness lookback exceeded: {}", e)
238239
}
239240
e => actor_error!(assertion_failed; "get chain randomness failed with an unexpected error: {}", e),
240241
}
241-
})
242+
})?;
243+
Ok(draw_randomness(
244+
fvm::crypto::hash_blake2b,
245+
&digest,
246+
personalization,
247+
rand_epoch,
248+
entropy,
249+
))
242250
}
243251

244252
fn get_randomness_from_beacon(
@@ -247,14 +255,21 @@ where
247255
rand_epoch: ChainEpoch,
248256
entropy: &[u8],
249257
) -> Result<[u8; RANDOMNESS_LENGTH], ActorError> {
250-
fvm::rand::get_beacon_randomness(personalization as i64, rand_epoch, entropy).map_err(|e| {
258+
let digest = fvm::rand::get_beacon_randomness(rand_epoch).map_err(|e| {
251259
match e {
252260
ErrorNumber::LimitExceeded => {
253261
actor_error!(illegal_argument; "randomness lookback exceeded: {}", e)
254262
}
255263
e => actor_error!(assertion_failed; "get beacon randomness failed with an unexpected error: {}", e),
256264
}
257-
})
265+
})?;
266+
Ok(draw_randomness(
267+
fvm::crypto::hash_blake2b,
268+
&digest,
269+
personalization,
270+
rand_epoch,
271+
entropy,
272+
))
258273
}
259274

260275
fn get_state_root(&self) -> Result<Cid, ActorError> {

runtime/src/runtime/randomness.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// Copyright 2019-2022 ChainSafe Systems
22
// SPDX-License-Identifier: Apache-2.0, MIT
33

4+
use fvm_shared::clock::ChainEpoch;
5+
use fvm_shared::randomness::RANDOMNESS_LENGTH;
46
use num_derive::FromPrimitive;
57
use serde_repr::*;
68

@@ -19,3 +21,64 @@ pub enum DomainSeparationTag {
1921
PoStChainCommit = 9,
2022
EvmPrevRandao = 10,
2123
}
24+
25+
#[allow(unused)]
26+
pub fn draw_randomness(
27+
hasher: impl FnOnce(&[u8]) -> [u8; 32],
28+
rbase: &[u8; RANDOMNESS_LENGTH],
29+
pers: DomainSeparationTag,
30+
round: ChainEpoch,
31+
entropy: &[u8],
32+
) -> [u8; RANDOMNESS_LENGTH] {
33+
let mut data = Vec::with_capacity(RANDOMNESS_LENGTH + 8 + 8 + entropy.len());
34+
35+
// Append the personalization value
36+
let i64_bytes = (pers as i64).to_be_bytes();
37+
data.extend_from_slice(&i64_bytes);
38+
39+
// Append the randomness
40+
data.extend_from_slice(rbase);
41+
42+
// Append the round
43+
let i64_bytes = round.to_be_bytes();
44+
data.extend_from_slice(&i64_bytes);
45+
46+
// Append the entropy
47+
data.extend_from_slice(entropy);
48+
49+
hasher(&data)
50+
//
51+
// fvm::crypto::hash_blake2b(&data)
52+
}
53+
54+
#[cfg(test)]
55+
mod tests {
56+
use crate::runtime::randomness::draw_randomness;
57+
use crate::runtime::DomainSeparationTag;
58+
use crate::test_utils::blake2b_256;
59+
use base64::Engine;
60+
61+
#[test]
62+
fn draw_randomness_test() {
63+
let expected_randomness = base64::engine::general_purpose::STANDARD
64+
.decode("3MCqcLHKZ+pil4MqTS9wjsd+yPvTuTrq8PkGjEo3tYQ=")
65+
.unwrap();
66+
67+
let digest = base64::engine::general_purpose::STANDARD
68+
.decode("GOobxkrhS1hiFA1EYUKZM3xsyVfy5Xy3bQ0gLPnecYs=")
69+
.unwrap();
70+
71+
let entropy = base64::engine::general_purpose::STANDARD.decode("RACZyzQ=").unwrap();
72+
73+
assert_eq!(
74+
expected_randomness,
75+
draw_randomness(
76+
blake2b_256,
77+
<&[u8; 32]>::try_from(digest.as_slice()).unwrap(),
78+
DomainSeparationTag::SealRandomness,
79+
2797727,
80+
entropy.as_slice(),
81+
)
82+
);
83+
}
84+
}

0 commit comments

Comments
 (0)