Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

drand v14 update: fix fetching around null tipsets #1339

Merged
merged 10 commits into from
Dec 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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