Skip to content

Commit

Permalink
drand v14 update: fix fetching around null tipsets (#1339)
Browse files Browse the repository at this point in the history
  • Loading branch information
noot authored Dec 18, 2021
1 parent 90e85d0 commit 356757e
Show file tree
Hide file tree
Showing 18 changed files with 459 additions and 221 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions blockchain/blocks/src/header/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -457,12 +457,10 @@ impl fmt::Display for BlockHeader {

#[cfg(test)]
mod tests {
use crate::{errors::Error, BlockHeader, Ticket, TipsetKeys};
use crate::{errors::Error, BlockHeader};
use address::Address;
use beacon::{BeaconEntry, BeaconPoint, BeaconSchedule, MockBeacon};
use cid::Code::Identity;
use encoding::Cbor;
use num_bigint::BigInt;

use std::sync::Arc;
use std::time::Duration;
Expand Down
125 changes: 1 addition & 124 deletions blockchain/chain/src/store/chain_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@ use async_std::channel::{self, bounded, Receiver};
use async_std::sync::RwLock;
use async_std::task;
use beacon::{BeaconEntry, IGNORE_DRAND_VAR};
use blake2b_simd::Params;
use blocks::{Block, BlockHeader, FullTipset, Tipset, TipsetKeys, TxMeta};
use byteorder::{BigEndian, WriteBytesExt};
use cid::Cid;
use cid::Code::Blake2b256;
use clock::ChainEpoch;
use crossbeam::atomic::AtomicCell;
use crypto::DomainSeparationTag;
use encoding::{blake2b_256, de::DeserializeOwned, from_slice, Cbor};
use encoding::{de::DeserializeOwned, from_slice, Cbor};
use forest_car::CarHeader;
use forest_ipld::recurse_links;
use futures::AsyncWrite;
Expand All @@ -32,7 +29,6 @@ use num_traits::Zero;
use serde::Serialize;
use state_tree::StateTree;
use std::error::Error as StdError;
use std::io::Write;
use std::sync::Arc;
use std::{
collections::{HashMap, HashSet, VecDeque},
Expand Down Expand Up @@ -290,107 +286,6 @@ where
}
}

pub async fn get_chain_randomness_looking_forward(
&self,
blocks: &TipsetKeys,
pers: DomainSeparationTag,
round: ChainEpoch,
entropy: &[u8],
) -> Result<[u8; 32], Box<dyn std::error::Error>> {
self.get_chain_randomness(blocks, pers, round, entropy, false)
.await
}

pub async fn get_chain_randomness_looking_backward(
&self,
blocks: &TipsetKeys,
pers: DomainSeparationTag,
round: ChainEpoch,
entropy: &[u8],
) -> Result<[u8; 32], Box<dyn std::error::Error>> {
self.get_chain_randomness(blocks, pers, round, entropy, true)
.await
}

/// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, ChainEpoch,
/// Entropy from the ticket chain.
pub async fn get_chain_randomness(
&self,
blocks: &TipsetKeys,
pers: DomainSeparationTag,
round: ChainEpoch,
entropy: &[u8],
lookback: bool,
) -> Result<[u8; 32], Box<dyn std::error::Error>> {
let ts = self.tipset_from_keys(blocks).await?;

if round > ts.epoch() {
return Err("cannot draw randomness from the future".into());
}

let search_height = if round < 0 { 0 } else { round };

let rand_ts = self.tipset_by_height(search_height, ts, lookback).await?;

draw_randomness(
rand_ts
.min_ticket()
.ok_or("No ticket exists for block")?
.vrfproof
.as_bytes(),
pers,
round,
entropy,
)
}

pub async fn get_beacon_randomness_looking_forward(
&self,
blocks: &TipsetKeys,
pers: DomainSeparationTag,
round: ChainEpoch,
entropy: &[u8],
) -> Result<[u8; 32], Box<dyn std::error::Error>> {
self.get_beacon_randomness(blocks, pers, round, entropy, false)
.await
}

pub async fn get_beacon_randomness_looking_backward(
&self,
blocks: &TipsetKeys,
pers: DomainSeparationTag,
round: ChainEpoch,
entropy: &[u8],
) -> Result<[u8; 32], Box<dyn std::error::Error>> {
self.get_beacon_randomness(blocks, pers, round, entropy, true)
.await
}

/// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, ChainEpoch,
/// Entropy from the latest beacon entry.
pub async fn get_beacon_randomness(
&self,
blocks: &TipsetKeys,
pers: DomainSeparationTag,
round: ChainEpoch,
entropy: &[u8],
lookback: bool,
) -> Result<[u8; 32], Box<dyn std::error::Error>> {
let ts = self.tipset_from_keys(blocks).await?;

if round > ts.epoch() {
return Err("cannot draw randomness from the future".into());
}

let search_height = if round < 0 { 0 } else { round };

let rand_ts = self.tipset_by_height(search_height, ts, lookback).await?;

let be = self.latest_beacon_entry(&rand_ts).await?;

draw_randomness(be.data(), pers, round, entropy)
}

/// Finds the latest beacon entry given a tipset up to 20 tipsets behind
pub async fn latest_beacon_entry(&self, ts: &Tipset) -> Result<BeaconEntry, Error> {
let check_for_beacon_entry = |ts: &Tipset| {
Expand Down Expand Up @@ -843,24 +738,6 @@ where
Ok(())
}

/// Computes a pseudorandom 32 byte Vec.
pub fn draw_randomness(
rbase: &[u8],
pers: DomainSeparationTag,
round: ChainEpoch,
entropy: &[u8],
) -> Result<[u8; 32], Box<dyn std::error::Error>> {
let mut state = Params::new().hash_length(32).to_state();
state.write_i64::<BigEndian>(pers as i64)?;
let vrf_digest = blake2b_256(rbase);
state.write_all(&vrf_digest)?;
state.write_i64::<BigEndian>(round as i64)?;
state.write_all(entropy)?;
let mut ret = [0u8; 32];
ret.clone_from_slice(state.finalize().as_bytes());
Ok(ret)
}

/// Returns a vector of cids from provided root cid
fn read_amt_cids<DB>(db: &DB, root: &Cid) -> Result<Vec<Cid>, Error>
where
Expand Down
6 changes: 3 additions & 3 deletions blockchain/chain_sync/src/tipset_syncer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1376,7 +1376,7 @@ async fn validate_block<
}
let r_beacon = header.beacon_entries().last().unwrap_or(&v_prev_beacon);
let miner_address_buf = header.miner_address().marshal_cbor()?;
let vrf_base = chain::draw_randomness(
let vrf_base = state_manager::chain_rand::draw_randomness(
r_beacon.data(),
DomainSeparationTag::ElectionProofProduction,
header.epoch(),
Expand Down Expand Up @@ -1447,7 +1447,7 @@ async fn validate_block<

let beacon_base = header.beacon_entries().last().unwrap_or(&v_prev_beacon);

let vrf_base = chain::draw_randomness(
let vrf_base = state_manager::chain_rand::draw_randomness(
beacon_base.data(),
DomainSeparationTag::TicketProduction,
header.epoch() - TICKET_RANDOMNESS_LOOKBACK,
Expand Down Expand Up @@ -1559,7 +1559,7 @@ fn verify_winning_post_proof<DB: BlockStore + Send + Sync + 'static, V: ProofVer
.iter()
.last()
.unwrap_or(prev_beacon_entry);
let rand = chain::draw_randomness(
let rand = state_manager::chain_rand::draw_randomness(
rand_base.data(),
DomainSeparationTag::WinningPoStChallengeSeed,
header.epoch(),
Expand Down
2 changes: 2 additions & 0 deletions blockchain/state_manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ features = ["statediff"]
[dependencies]
address = { package = "forest_address", version = "0.3" }
actor = { package = "actor_interface", path = "../../vm/actor_interface" }
blake2b_simd = "0.5.9"
byteorder = "1.3.4"
cid = { package = "forest_cid", version = "0.3" }
db = { package = "forest_db", version = "0.1" }
encoding = { package = "forest_encoding", version = "0.2.1" }
Expand Down
Loading

0 comments on commit 356757e

Please sign in to comment.