From 3f7c704d2508e94a59e80ddb7a1a242042f8c436 Mon Sep 17 00:00:00 2001 From: noot Date: Wed, 15 Dec 2021 17:40:32 -0500 Subject: [PATCH 1/9] begin drand updates, move BeaconSchedule initialization to StateManager --- blockchain/chain/src/store/chain_store.rs | 107 +++++++++++++++------ blockchain/state_manager/src/chain_rand.rs | 8 +- blockchain/state_manager/src/lib.rs | 30 ++++-- forest/src/daemon.rs | 35 ++++--- utils/genesis/src/lib.rs | 59 ++++++++++-- 5 files changed, 177 insertions(+), 62 deletions(-) diff --git a/blockchain/chain/src/store/chain_store.rs b/blockchain/chain/src/store/chain_store.rs index 8db0fa5cd0b5..b230e99f0cfb 100644 --- a/blockchain/chain/src/store/chain_store.rs +++ b/blockchain/chain/src/store/chain_store.rs @@ -290,28 +290,6 @@ where } } - pub async fn get_chain_randomness_looking_forward( - &self, - blocks: &TipsetKeys, - pers: DomainSeparationTag, - round: ChainEpoch, - entropy: &[u8], - ) -> Result<[u8; 32], Box> { - 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> { - 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( @@ -344,18 +322,32 @@ where ) } - pub async fn get_beacon_randomness_looking_forward( + /// network v0-12 + pub async fn get_chain_randomness_v1( &self, blocks: &TipsetKeys, pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box> { - self.get_beacon_randomness(blocks, pers, round, entropy, false) + self.get_chain_randomness(blocks, pers, round, entropy, true) + .await + } + + /// network v13 onwards + pub async fn get_chain_randomness_v2( + &self, + blocks: &TipsetKeys, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + self.get_chain_randomness(blocks, pers, round, entropy, false) .await } - pub async fn get_beacon_randomness_looking_backward( + /// network v0-12; with lookback + pub async fn get_beacon_randomness_v1( &self, blocks: &TipsetKeys, pers: DomainSeparationTag, @@ -366,6 +358,36 @@ where .await } + /// network v13; without lookback + pub async fn get_beacon_randomness_v2( + &self, + blocks: &TipsetKeys, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + self.get_beacon_randomness(blocks, pers, round, entropy, false) + .await + } + + /// network v14 onwards + pub async fn get_beacon_randomness_v3( + &self, + blocks: &TipsetKeys, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + if round < 0 { + return self + .get_beacon_randomness_v2(blocks, pers, round, entropy) + .await; + } + + let beacon_entry = self.extract_beacon_entry_for_epoch(blocks, round).await?; + draw_randomness(beacon_entry.data(), pers, round, entropy) + } + /// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, ChainEpoch, /// Entropy from the latest beacon entry. pub async fn get_beacon_randomness( @@ -376,6 +398,31 @@ where entropy: &[u8], lookback: bool, ) -> Result<[u8; 32], Box> { + let rand_ts = self + .get_beacon_randomness_tipset(blocks, round, lookback) + .await?; + let be = self.latest_beacon_entry(&rand_ts).await?; + draw_randomness(be.data(), pers, round, entropy) + } + + pub async fn extract_beacon_entry_for_epoch( + &self, + blocks: &TipsetKeys, + epoch: ChainEpoch, + ) -> Result> { + let rand_ts = self + .get_beacon_randomness_tipset(blocks, epoch, false) + .await?; + // let round = self.beacon.beacon_for_epoch(epoch); + Err("unimplemented".into()) + } + + pub async fn get_beacon_randomness_tipset( + &self, + blocks: &TipsetKeys, + round: ChainEpoch, + lookback: bool, + ) -> Result, Box> { let ts = self.tipset_from_keys(blocks).await?; if round > ts.epoch() { @@ -384,11 +431,11 @@ where 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) + let res = self.tipset_by_height(search_height, ts, lookback).await; + match res { + Ok(rand_ts) => return Ok(rand_ts), + Err(e) => return Err(e.into()), + }; } /// Finds the latest beacon entry given a tipset up to 20 tipsets behind diff --git a/blockchain/state_manager/src/chain_rand.rs b/blockchain/state_manager/src/chain_rand.rs index bf6f1cb5028f..f29d42b7a7c2 100644 --- a/blockchain/state_manager/src/chain_rand.rs +++ b/blockchain/state_manager/src/chain_rand.rs @@ -36,7 +36,7 @@ where ) -> Result<[u8; 32], Box> { task::block_on( self.cs - .get_chain_randomness_looking_backward(&self.blks, pers, round, entropy), + .get_chain_randomness_v1(&self.blks, pers, round, entropy), ) } @@ -48,7 +48,7 @@ where ) -> Result<[u8; 32], Box> { task::block_on( self.cs - .get_beacon_randomness_looking_backward(&self.blks, pers, round, entropy), + .get_beacon_randomness_v1(&self.blks, pers, round, entropy), ) } @@ -60,7 +60,7 @@ where ) -> Result<[u8; 32], Box> { task::block_on( self.cs - .get_chain_randomness_looking_forward(&self.blks, pers, round, entropy), + .get_chain_randomness_v2(&self.blks, pers, round, entropy), ) } @@ -72,7 +72,7 @@ where ) -> Result<[u8; 32], Box> { task::block_on( self.cs - .get_beacon_randomness_looking_forward(&self.blks, pers, round, entropy), + .get_beacon_randomness_v2(&self.blks, pers, round, entropy), ) } } diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index 83a08a24722f..8b70033d9bb0 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -14,7 +14,7 @@ use actor::*; use address::{Address, BLSPublicKey, Payload, Protocol, BLS_PUB_LEN}; use async_log::span; use async_std::{sync::RwLock, task}; -use beacon::{Beacon, BeaconEntry, BeaconSchedule, IGNORE_DRAND_VAR}; +use beacon::{Beacon, BeaconEntry, BeaconSchedule, DrandBeacon, IGNORE_DRAND_VAR}; use blockstore::{BlockStore, BufferedBlockStore}; use chain::{draw_randomness, ChainStore, HeadChange}; use chain_rand::ChainRand; @@ -87,29 +87,45 @@ pub struct StateManager { cache: RwLock>>>>, publisher: Option>, genesis_info: GenesisInfo, + beacon: Arc>, } impl StateManager where DB: BlockStore + Send + Sync + 'static, { - pub fn new(cs: Arc>) -> Self { - Self { + pub async fn new(cs: Arc>) -> Result> { + let genesis = cs.genesis()?.ok_or("genesis header was none")?; + let beacon = Arc::new(networks::beacon_schedule_default(genesis.timestamp()).await?); + + Ok(Self { cs, cache: RwLock::new(HashMap::new()), publisher: None, genesis_info: GenesisInfo::default(), - } + beacon: beacon, + }) } /// Creates a constructor that passes in a HeadChange publisher. - pub fn new_with_publisher(cs: Arc>, chain_subs: Publisher) -> Self { - Self { + pub async fn new_with_publisher( + cs: Arc>, + chain_subs: Publisher, + ) -> Result> { + let genesis = cs.genesis()?.ok_or("genesis header was none")?; + let beacon = Arc::new(networks::beacon_schedule_default(genesis.timestamp()).await?); + + Ok(Self { cs, cache: RwLock::new(HashMap::new()), publisher: Some(chain_subs), genesis_info: GenesisInfo::default(), - } + beacon: beacon, + }) + } + + pub fn beacon_schedule(&self) -> Arc> { + self.beacon.clone() } /// Returns network version for the given epoch. diff --git a/forest/src/daemon.rs b/forest/src/daemon.rs index 0a582891cebc..92ad811826da 100644 --- a/forest/src/daemon.rs +++ b/forest/src/daemon.rs @@ -7,7 +7,7 @@ use chain::ChainStore; use chain_sync::ChainMuxer; use fil_types::verifier::FullVerifier; use forest_libp2p::{get_keypair, Libp2pService}; -use genesis::{import_chain, initialize_genesis}; +use genesis::{get_network_name_from_genesis, import_chain, read_genesis_header}; use message_pool::{MessagePool, MpoolConfig, MpoolRpcProvider}; use paramfetch::{get_params_default, SectorSizeOpt}; use rpc::start_rpc; @@ -124,15 +124,30 @@ pub(super) async fn start(config: Config) { let db = Arc::new(db); - // Initialize StateManager + // Initialize ChainStore let chain_store = Arc::new(ChainStore::new(Arc::clone(&db))); - let state_manager = Arc::new(StateManager::new(Arc::clone(&chain_store))); let publisher = chain_store.publisher(); // Read Genesis file // * When snapshot command implemented, this genesis does not need to be initialized - let (genesis, network_name) = initialize_genesis(config.genesis_file.as_ref(), &state_manager) + // let (genesis, network_name) = initialize_genesis(config.genesis_file.as_ref(), &state_manager) + // .await + // .unwrap(); + let genesis = read_genesis_header(config.genesis_file.as_ref(), &chain_store) + .await + .unwrap(); + + // Initialize StateManager + // let beacon = Arc::new( + // networks::beacon_schedule_default(genesis.min_timestamp()) + // .await + // .unwrap(), + // ); + let sm = StateManager::new(Arc::clone(&chain_store)).await.unwrap(); + let state_manager = Arc::new(sm); + + let network_name = get_network_name_from_genesis(&genesis, &state_manager) .await .unwrap(); @@ -172,18 +187,12 @@ pub(super) async fn start(config: Config) { .unwrap(), ); - let beacon = Arc::new( - networks::beacon_schedule_default(genesis.min_timestamp()) - .await - .unwrap(), - ); - // Initialize ChainMuxer let (tipset_sink, tipset_stream) = bounded(20); let chain_muxer_tipset_sink = tipset_sink.clone(); let chain_muxer = ChainMuxer::<_, _, FullVerifier, _>::new( Arc::clone(&state_manager), - beacon.clone(), + state_manager.beacon_schedule().clone(), Arc::clone(&mpool), network_send.clone(), network_rx, @@ -208,14 +217,14 @@ pub(super) async fn start(config: Config) { info!("JSON RPC Endpoint at {}", &rpc_listen); start_rpc::<_, _, FullVerifier>( Arc::new(RPCState { - state_manager, + state_manager: Arc::clone(&state_manager), keystore: keystore_rpc, mpool, bad_blocks, sync_state, network_send, network_name, - beacon, + beacon: state_manager.beacon_schedule(), // TODO: the RPCState can fetch this itself from the StateManager chain_store, new_mined_block_tx: tipset_sink, }), diff --git a/utils/genesis/src/lib.rs b/utils/genesis/src/lib.rs index 1f4275484cc1..63d2f9cff435 100644 --- a/utils/genesis/src/lib.rs +++ b/utils/genesis/src/lib.rs @@ -24,35 +24,78 @@ pub const EXPORT_SR_40: &[u8] = std::include_bytes!("export40.car"); /// Uses an optional file path or the default genesis to parse the genesis and determine if /// chain store has existing data for the given genesis. -pub async fn initialize_genesis( +pub async fn read_genesis_header( genesis_fp: Option<&String>, - state_manager: &StateManager, -) -> Result<(Tipset, String), Box> + cs: &ChainStore, +) -> Result> where - BS: BlockStore + Send + Sync + 'static, + DB: BlockStore + Send + Sync + 'static, { let genesis = match genesis_fp { Some(path) => { let file = File::open(path).await?; let reader = BufReader::new(file); - process_car(reader, state_manager.chain_store()).await? + process_car(reader, cs).await? } None => { debug!("No specified genesis in config. Using default genesis."); let reader = BufReader::<&[u8]>::new(DEFAULT_GENESIS); - process_car(reader, state_manager.chain_store()).await? + process_car(reader, cs).await? } }; info!("Initialized genesis: {}", genesis); + Ok(Tipset::new(vec![genesis])?) +} + +pub async fn get_network_name_from_genesis( + genesis_ts: &Tipset, + state_manager: &StateManager, +) -> Result> +where + BS: BlockStore + Send + Sync + 'static, +{ + // the genesis tipset has just one block, so fetch it + let genesis_header = genesis_ts.min_ticket_block(); // Get network name from genesis state. let network_name = state_manager - .get_network_name(genesis.state_root()) + .get_network_name(genesis_header.state_root()) .map_err(|e| format!("Failed to retrieve network name from genesis: {}", e))?; - Ok((Tipset::new(vec![genesis])?, network_name)) + Ok(network_name.to_string()) } +/// Uses an optional file path or the default genesis to parse the genesis and determine if +/// chain store has existing data for the given genesis. +// pub async fn initialize_genesis( +// genesis_fp: Option<&String>, +// state_manager: &StateManager, +// ) -> Result<(Tipset, String), Box> +// where +// BS: BlockStore + Send + Sync + 'static, +// { +// let genesis = match genesis_fp { +// Some(path) => { +// let file = File::open(path).await?; +// let reader = BufReader::new(file); +// process_car(reader, state_manager.chain_store()).await? +// } +// None => { +// debug!("No specified genesis in config. Using default genesis."); +// let reader = BufReader::<&[u8]>::new(DEFAULT_GENESIS); +// process_car(reader, state_manager.chain_store()).await? +// } +// }; + +// info!("Initialized genesis: {}", genesis); + +// // Get network name from genesis state. +// let network_name = state_manager +// .get_network_name(genesis.state_root()) +// .map_err(|e| format!("Failed to retrieve network name from genesis: {}", e))?; +// Ok((Tipset::new(vec![genesis])?, network_name)) +// } + async fn process_car( reader: R, chain_store: &ChainStore, From c70d88d27ba6ddebf4e5c3a6e232129804e69a07 Mon Sep 17 00:00:00 2001 From: noot Date: Wed, 15 Dec 2021 19:59:28 -0500 Subject: [PATCH 2/9] finish chain_rand implementation --- Cargo.lock | 2 + blockchain/chain/src/store/chain_store.rs | 334 ++++++++++----------- blockchain/chain_sync/src/tipset_syncer.rs | 6 +- blockchain/state_manager/Cargo.toml | 2 + blockchain/state_manager/src/chain_rand.rs | 234 +++++++++++++-- blockchain/state_manager/src/lib.rs | 44 ++- node/rpc/src/chain_api.rs | 2 - utils/genesis/src/lib.rs | 31 -- vm/interpreter/src/default_runtime.rs | 8 +- vm/interpreter/src/rand.rs | 8 +- 10 files changed, 428 insertions(+), 243 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43c90b82088a..296af9695d54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6371,6 +6371,8 @@ dependencies = [ "async-log", "async-std", "beacon", + "blake2b_simd", + "byteorder 1.4.3", "chain", "fil_clock", "fil_types", diff --git a/blockchain/chain/src/store/chain_store.rs b/blockchain/chain/src/store/chain_store.rs index b230e99f0cfb..e2b14cc1df0f 100644 --- a/blockchain/chain/src/store/chain_store.rs +++ b/blockchain/chain/src/store/chain_store.rs @@ -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; @@ -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}, @@ -290,153 +286,153 @@ where } } - /// 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> { - 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, - ) - } - - /// network v0-12 - pub async fn get_chain_randomness_v1( - &self, - blocks: &TipsetKeys, - pers: DomainSeparationTag, - round: ChainEpoch, - entropy: &[u8], - ) -> Result<[u8; 32], Box> { - self.get_chain_randomness(blocks, pers, round, entropy, true) - .await - } - - /// network v13 onwards - pub async fn get_chain_randomness_v2( - &self, - blocks: &TipsetKeys, - pers: DomainSeparationTag, - round: ChainEpoch, - entropy: &[u8], - ) -> Result<[u8; 32], Box> { - self.get_chain_randomness(blocks, pers, round, entropy, false) - .await - } - - /// network v0-12; with lookback - pub async fn get_beacon_randomness_v1( - &self, - blocks: &TipsetKeys, - pers: DomainSeparationTag, - round: ChainEpoch, - entropy: &[u8], - ) -> Result<[u8; 32], Box> { - self.get_beacon_randomness(blocks, pers, round, entropy, true) - .await - } - - /// network v13; without lookback - pub async fn get_beacon_randomness_v2( - &self, - blocks: &TipsetKeys, - pers: DomainSeparationTag, - round: ChainEpoch, - entropy: &[u8], - ) -> Result<[u8; 32], Box> { - self.get_beacon_randomness(blocks, pers, round, entropy, false) - .await - } - - /// network v14 onwards - pub async fn get_beacon_randomness_v3( - &self, - blocks: &TipsetKeys, - pers: DomainSeparationTag, - round: ChainEpoch, - entropy: &[u8], - ) -> Result<[u8; 32], Box> { - if round < 0 { - return self - .get_beacon_randomness_v2(blocks, pers, round, entropy) - .await; - } - - let beacon_entry = self.extract_beacon_entry_for_epoch(blocks, round).await?; - draw_randomness(beacon_entry.data(), pers, round, entropy) - } - - /// 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> { - let rand_ts = self - .get_beacon_randomness_tipset(blocks, round, lookback) - .await?; - let be = self.latest_beacon_entry(&rand_ts).await?; - draw_randomness(be.data(), pers, round, entropy) - } - - pub async fn extract_beacon_entry_for_epoch( - &self, - blocks: &TipsetKeys, - epoch: ChainEpoch, - ) -> Result> { - let rand_ts = self - .get_beacon_randomness_tipset(blocks, epoch, false) - .await?; - // let round = self.beacon.beacon_for_epoch(epoch); - Err("unimplemented".into()) - } - - pub async fn get_beacon_randomness_tipset( - &self, - blocks: &TipsetKeys, - round: ChainEpoch, - lookback: bool, - ) -> Result, Box> { - 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 res = self.tipset_by_height(search_height, ts, lookback).await; - match res { - Ok(rand_ts) => return Ok(rand_ts), - Err(e) => return Err(e.into()), - }; - } + // /// 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> { + // 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, + // ) + // } + + // /// network v0-12 + // pub async fn get_chain_randomness_v1( + // &self, + // blocks: &TipsetKeys, + // pers: DomainSeparationTag, + // round: ChainEpoch, + // entropy: &[u8], + // ) -> Result<[u8; 32], Box> { + // self.get_chain_randomness(blocks, pers, round, entropy, true) + // .await + // } + + // /// network v13 onwards + // pub async fn get_chain_randomness_v2( + // &self, + // blocks: &TipsetKeys, + // pers: DomainSeparationTag, + // round: ChainEpoch, + // entropy: &[u8], + // ) -> Result<[u8; 32], Box> { + // self.get_chain_randomness(blocks, pers, round, entropy, false) + // .await + // } + + // /// network v0-12; with lookback + // pub async fn get_beacon_randomness_v1( + // &self, + // blocks: &TipsetKeys, + // pers: DomainSeparationTag, + // round: ChainEpoch, + // entropy: &[u8], + // ) -> Result<[u8; 32], Box> { + // self.get_beacon_randomness(blocks, pers, round, entropy, true) + // .await + // } + + // /// network v13; without lookback + // pub async fn get_beacon_randomness_v2( + // &self, + // blocks: &TipsetKeys, + // pers: DomainSeparationTag, + // round: ChainEpoch, + // entropy: &[u8], + // ) -> Result<[u8; 32], Box> { + // self.get_beacon_randomness(blocks, pers, round, entropy, false) + // .await + // } + + // /// network v14 onwards + // pub async fn get_beacon_randomness_v3( + // &self, + // blocks: &TipsetKeys, + // pers: DomainSeparationTag, + // round: ChainEpoch, + // entropy: &[u8], + // ) -> Result<[u8; 32], Box> { + // if round < 0 { + // return self + // .get_beacon_randomness_v2(blocks, pers, round, entropy) + // .await; + // } + + // let beacon_entry = self.extract_beacon_entry_for_epoch(blocks, round).await?; + // draw_randomness(beacon_entry.data(), pers, round, entropy) + // } + + // /// 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> { + // let rand_ts = self + // .get_beacon_randomness_tipset(blocks, round, lookback) + // .await?; + // let be = self.latest_beacon_entry(&rand_ts).await?; + // draw_randomness(be.data(), pers, round, entropy) + // } + + // pub async fn extract_beacon_entry_for_epoch( + // &self, + // blocks: &TipsetKeys, + // epoch: ChainEpoch, + // ) -> Result> { + // let rand_ts = self + // .get_beacon_randomness_tipset(blocks, epoch, false) + // .await?; + // // let round = self.beacon.beacon_for_epoch(epoch); + // Err("unimplemented".into()) + // } + + // pub async fn get_beacon_randomness_tipset( + // &self, + // blocks: &TipsetKeys, + // round: ChainEpoch, + // lookback: bool, + // ) -> Result, Box> { + // 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 res = self.tipset_by_height(search_height, ts, lookback).await; + // match res { + // Ok(rand_ts) => return Ok(rand_ts), + // Err(e) => return Err(e.into()), + // }; + // } /// Finds the latest beacon entry given a tipset up to 20 tipsets behind pub async fn latest_beacon_entry(&self, ts: &Tipset) -> Result { @@ -890,23 +886,23 @@ where Ok(()) } -/// Computes a pseudorandom 32 byte Vec. -pub fn draw_randomness( - rbase: &[u8], - pers: DomainSeparationTag, - round: ChainEpoch, - entropy: &[u8], -) -> Result<[u8; 32], Box> { - let mut state = Params::new().hash_length(32).to_state(); - state.write_i64::(pers as i64)?; - let vrf_digest = blake2b_256(rbase); - state.write_all(&vrf_digest)?; - state.write_i64::(round as i64)?; - state.write_all(entropy)?; - let mut ret = [0u8; 32]; - ret.clone_from_slice(state.finalize().as_bytes()); - Ok(ret) -} +// /// Computes a pseudorandom 32 byte Vec. +// pub fn draw_randomness( +// rbase: &[u8], +// pers: DomainSeparationTag, +// round: ChainEpoch, +// entropy: &[u8], +// ) -> Result<[u8; 32], Box> { +// let mut state = Params::new().hash_length(32).to_state(); +// state.write_i64::(pers as i64)?; +// let vrf_digest = blake2b_256(rbase); +// state.write_all(&vrf_digest)?; +// state.write_i64::(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, root: &Cid) -> Result, Error> diff --git a/blockchain/chain_sync/src/tipset_syncer.rs b/blockchain/chain_sync/src/tipset_syncer.rs index 4f991dc09c82..e89b529ef497 100644 --- a/blockchain/chain_sync/src/tipset_syncer.rs +++ b/blockchain/chain_sync/src/tipset_syncer.rs @@ -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(), @@ -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, @@ -1559,7 +1559,7 @@ fn verify_winning_post_proof { blks: TipsetKeys, cs: Arc>, + beacon: Arc>, } -impl ChainRand { - pub fn new(blks: TipsetKeys, cs: Arc>) -> Self { - Self { blks, cs } +impl ChainRand +where + DB: BlockStore + Send + Sync + 'static, +{ + pub fn new( + blks: TipsetKeys, + cs: Arc>, + beacon: Arc>, + ) -> Self { + Self { blks, cs, beacon } + } + + /// 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> { + let ts = self.cs.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 + .cs + .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, + ) + } + + /// network v0-12 + pub async fn get_chain_randomness_v1( + &self, + blocks: &TipsetKeys, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + self.get_chain_randomness(blocks, pers, round, entropy, true) + .await + } + + /// network v13 onwards + pub async fn get_chain_randomness_v2( + &self, + blocks: &TipsetKeys, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + self.get_chain_randomness(blocks, pers, round, entropy, false) + .await + } + + /// network v0-12; with lookback + pub async fn get_beacon_randomness_v1( + &self, + blocks: &TipsetKeys, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + self.get_beacon_randomness(blocks, pers, round, entropy, true) + .await + } + + /// network v13; without lookback + pub async fn get_beacon_randomness_v2( + &self, + blocks: &TipsetKeys, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + self.get_beacon_randomness(blocks, pers, round, entropy, false) + .await + } + + /// network v14 onwards + pub async fn get_beacon_randomness_v3( + &self, + blocks: &TipsetKeys, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + if round < 0 { + return self + .get_beacon_randomness_v2(blocks, pers, round, entropy) + .await; + } + + let beacon_entry = self.extract_beacon_entry_for_epoch(blocks, round).await?; + draw_randomness(beacon_entry.data(), pers, round, entropy) + } + + /// 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> { + let rand_ts: Arc = self + .get_beacon_randomness_tipset(blocks, round, lookback) + .await?; + let be = self.cs.latest_beacon_entry(&rand_ts).await?; + draw_randomness(be.data(), pers, round, entropy) + } + + pub async fn extract_beacon_entry_for_epoch( + &self, + blocks: &TipsetKeys, + epoch: ChainEpoch, + ) -> Result> { + let mut rand_ts: Arc = self + .get_beacon_randomness_tipset(blocks, epoch, false) + .await?; + let (round, _) = self.beacon.beacon_for_epoch(epoch)?; + + for _ in 0..20 { + let cbe = rand_ts.blocks()[0].beacon_entries(); + for v in cbe.iter() { + if v.round() == round as u64 { + return Ok(v.clone()); + } + } + + rand_ts = self.cs.tipset_from_keys(rand_ts.parents()).await?; + } + + Err(format!( + "didn't find beacon for round {:?} (epoch {:?})", + round, epoch + ) + .into()) + } + + pub async fn get_beacon_randomness_tipset( + &self, + blocks: &TipsetKeys, + round: ChainEpoch, + lookback: bool, + ) -> Result, Box> { + let ts = self.cs.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 res = self.cs.tipset_by_height(search_height, ts, lookback).await; + match res { + Ok(rand_ts) => return Ok(rand_ts), + Err(e) => return Err(e.into()), + }; } } @@ -28,51 +208,57 @@ impl Rand for ChainRand where DB: BlockStore + Send + Sync + 'static, { - fn get_chain_randomness( + fn get_chain_randomness_v1( &self, pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box> { - task::block_on( - self.cs - .get_chain_randomness_v1(&self.blks, pers, round, entropy), - ) + task::block_on(self.get_chain_randomness_v1(&self.blks, pers, round, entropy)) } - fn get_beacon_randomness( + fn get_beacon_randomness_v1( &self, pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box> { - task::block_on( - self.cs - .get_beacon_randomness_v1(&self.blks, pers, round, entropy), - ) + task::block_on(self.get_beacon_randomness_v1(&self.blks, pers, round, entropy)) } - fn get_chain_randomness_looking_forward( + fn get_chain_randomness_v2( &self, pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box> { - task::block_on( - self.cs - .get_chain_randomness_v2(&self.blks, pers, round, entropy), - ) + task::block_on(self.get_chain_randomness_v2(&self.blks, pers, round, entropy)) } - fn get_beacon_randomness_looking_forward( + fn get_beacon_randomness_v2( &self, pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box> { - task::block_on( - self.cs - .get_beacon_randomness_v2(&self.blks, pers, round, entropy), - ) + task::block_on(self.get_beacon_randomness_v2(&self.blks, pers, round, entropy)) } } + +/// Computes a pseudorandom 32 byte Vec. +pub fn draw_randomness( + rbase: &[u8], + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], +) -> Result<[u8; 32], Box> { + let mut state = Params::new().hash_length(32).to_state(); + state.write_i64::(pers as i64)?; + let vrf_digest = blake2b_256(rbase); + state.write_all(&vrf_digest)?; + state.write_i64::(round as i64)?; + state.write_all(entropy)?; + let mut ret = [0u8; 32]; + ret.clone_from_slice(state.finalize().as_bytes()); + Ok(ret) +} diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index 8b70033d9bb0..7d153fd77fc7 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -4,7 +4,7 @@ #[macro_use] extern crate lazy_static; -mod chain_rand; +pub mod chain_rand; mod errors; mod utils; mod vm_circ_supply; @@ -16,7 +16,7 @@ use async_log::span; use async_std::{sync::RwLock, task}; use beacon::{Beacon, BeaconEntry, BeaconSchedule, DrandBeacon, IGNORE_DRAND_VAR}; use blockstore::{BlockStore, BufferedBlockStore}; -use chain::{draw_randomness, ChainStore, HeadChange}; +use chain::{ChainStore, HeadChange}; use chain_rand::ChainRand; use cid::Cid; use clock::ChainEpoch; @@ -154,6 +154,38 @@ where &self.cs } + /// 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> { + let chain_rand = ChainRand::new(blocks.to_owned(), self.cs.clone(), self.beacon.clone()); + chain_rand + .get_beacon_randomness(blocks, pers, round, entropy, lookback) + .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> { + let chain_rand = ChainRand::new(blocks.to_owned(), self.cs.clone(), self.beacon.clone()); + chain_rand + .get_chain_randomness(blocks, pers, round, entropy, lookback) + .await + } + /// Returns the network name from the init actor state. pub fn get_network_name(&self, st: &Cid) -> Result { let init_act = self @@ -425,7 +457,7 @@ where .await .ok_or_else(|| Error::Other("No heaviest tipset".to_string()))? }; - let chain_rand = ChainRand::new(ts.key().to_owned(), self.cs.clone()); + let chain_rand = ChainRand::new(ts.key().to_owned(), self.cs.clone(), self.beacon.clone()); self.call_raw::(message, &chain_rand, &ts) } @@ -452,7 +484,7 @@ where .tipset_state::(&ts) .await .map_err(|_| Error::Other("Could not load tipset state".to_string()))?; - let chain_rand = ChainRand::new(ts.key().to_owned(), self.cs.clone()); + let chain_rand = ChainRand::new(ts.key().to_owned(), self.cs.clone(), self.beacon.clone()); // TODO investigate: this doesn't use a buffered store in any way, and can lead to // state bloat potentially? @@ -679,7 +711,7 @@ where let miner_state = miner::State::load(self.blockstore(), &actor)?; let buf = address.marshal_cbor()?; - let prand = draw_randomness( + let prand = chain_rand::draw_randomness( rbase.data(), DomainSeparationTag::WinningPoStChallengeSeed, round, @@ -771,7 +803,7 @@ where let tipset_keys = TipsetKeys::new(block_headers.iter().map(|s| s.cid()).cloned().collect()); - let chain_rand = ChainRand::new(tipset_keys, self.cs.clone()); + let chain_rand = ChainRand::new(tipset_keys, self.cs.clone(), self.beacon.clone()); let base_fee = first_block.parent_base_fee().clone(); let blocks = self diff --git a/node/rpc/src/chain_api.rs b/node/rpc/src/chain_api.rs index 04b5f53bb461..4928aea92cf0 100644 --- a/node/rpc/src/chain_api.rs +++ b/node/rpc/src/chain_api.rs @@ -271,7 +271,6 @@ where let entropy = entropy.unwrap_or_default(); Ok(data .state_manager - .chain_store() .get_chain_randomness( &tsk, DomainSeparationTag::from_i64(pers).ok_or("invalid DomainSeparationTag")?, @@ -295,7 +294,6 @@ where Ok(data .state_manager - .chain_store() .get_beacon_randomness( &tsk, DomainSeparationTag::from_i64(pers).ok_or("invalid DomainSeparationTag")?, diff --git a/utils/genesis/src/lib.rs b/utils/genesis/src/lib.rs index 63d2f9cff435..3432bc674969 100644 --- a/utils/genesis/src/lib.rs +++ b/utils/genesis/src/lib.rs @@ -65,37 +65,6 @@ where Ok(network_name.to_string()) } -/// Uses an optional file path or the default genesis to parse the genesis and determine if -/// chain store has existing data for the given genesis. -// pub async fn initialize_genesis( -// genesis_fp: Option<&String>, -// state_manager: &StateManager, -// ) -> Result<(Tipset, String), Box> -// where -// BS: BlockStore + Send + Sync + 'static, -// { -// let genesis = match genesis_fp { -// Some(path) => { -// let file = File::open(path).await?; -// let reader = BufReader::new(file); -// process_car(reader, state_manager.chain_store()).await? -// } -// None => { -// debug!("No specified genesis in config. Using default genesis."); -// let reader = BufReader::<&[u8]>::new(DEFAULT_GENESIS); -// process_car(reader, state_manager.chain_store()).await? -// } -// }; - -// info!("Initialized genesis: {}", genesis); - -// // Get network name from genesis state. -// let network_name = state_manager -// .get_network_name(genesis.state_root()) -// .map_err(|e| format!("Failed to retrieve network name from genesis: {}", e))?; -// Ok((Tipset::new(vec![genesis])?, network_name)) -// } - async fn process_car( reader: R, chain_store: &ChainStore, diff --git a/vm/interpreter/src/default_runtime.rs b/vm/interpreter/src/default_runtime.rs index 10d7d99ba0ae..ab5a3010a4ab 100644 --- a/vm/interpreter/src/default_runtime.rs +++ b/vm/interpreter/src/default_runtime.rs @@ -666,11 +666,11 @@ where ) -> Result { let r = if rand_epoch > networks::UPGRADE_HYPERDRIVE_HEIGHT { self.rand - .get_chain_randomness_looking_forward(personalization, rand_epoch, entropy) + .get_chain_randomness_v2(personalization, rand_epoch, entropy) .map_err(|e| e.downcast_fatal("could not get randomness"))? } else { self.rand - .get_chain_randomness(personalization, rand_epoch, entropy) + .get_chain_randomness_v1(personalization, rand_epoch, entropy) .map_err(|e| e.downcast_fatal("could not get randomness"))? }; @@ -685,11 +685,11 @@ where ) -> Result { let r = if rand_epoch > networks::UPGRADE_HYPERDRIVE_HEIGHT { self.rand - .get_beacon_randomness_looking_forward(personalization, rand_epoch, entropy) + .get_beacon_randomness_v2(personalization, rand_epoch, entropy) .map_err(|e| e.downcast_fatal("could not get randomness"))? } else { self.rand - .get_beacon_randomness(personalization, rand_epoch, entropy) + .get_beacon_randomness_v1(personalization, rand_epoch, entropy) .map_err(|e| e.downcast_fatal("could not get randomness"))? }; Ok(Randomness(r.to_vec())) diff --git a/vm/interpreter/src/rand.rs b/vm/interpreter/src/rand.rs index 69ccac9ccf54..f55a2d60666f 100644 --- a/vm/interpreter/src/rand.rs +++ b/vm/interpreter/src/rand.rs @@ -9,14 +9,14 @@ use std::error::Error; pub trait Rand { /// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, /// ChainEpoch, Entropy from the ticket chain. - fn get_chain_randomness( + fn get_chain_randomness_v1( &self, pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box>; - fn get_chain_randomness_looking_forward( + fn get_chain_randomness_v2( &self, pers: DomainSeparationTag, round: ChainEpoch, @@ -25,14 +25,14 @@ pub trait Rand { /// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, /// ChainEpoch, Entropy from the latest beacon entry. - fn get_beacon_randomness( + fn get_beacon_randomness_v1( &self, pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box>; - fn get_beacon_randomness_looking_forward( + fn get_beacon_randomness_v2( &self, pers: DomainSeparationTag, round: ChainEpoch, From 27b53e9fa0c916638d3edbd2284cbea6ae4fe168 Mon Sep 17 00:00:00 2001 From: noot Date: Wed, 15 Dec 2021 20:18:32 -0500 Subject: [PATCH 3/9] update StateManager get_beacon_randomness --- blockchain/state_manager/src/chain_rand.rs | 9 +++++++++ blockchain/state_manager/src/lib.rs | 22 ++++++++++++++++++---- node/rpc/src/chain_api.rs | 1 - vm/interpreter/src/default_runtime.rs | 6 +++++- vm/interpreter/src/rand.rs | 7 +++++++ 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/blockchain/state_manager/src/chain_rand.rs b/blockchain/state_manager/src/chain_rand.rs index c6ef61482cba..cbfe22b3134f 100644 --- a/blockchain/state_manager/src/chain_rand.rs +++ b/blockchain/state_manager/src/chain_rand.rs @@ -243,6 +243,15 @@ where ) -> Result<[u8; 32], Box> { task::block_on(self.get_beacon_randomness_v2(&self.blks, pers, round, entropy)) } + + fn get_beacon_randomness_v3( + &self, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + task::block_on(self.get_beacon_randomness_v3(&self.blks, pers, round, entropy)) + } } /// Computes a pseudorandom 32 byte Vec. diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index 7d153fd77fc7..7a32252e4c29 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -162,12 +162,26 @@ where pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], - lookback: bool, + // lookback: bool, ) -> Result<[u8; 32], Box> { let chain_rand = ChainRand::new(blocks.to_owned(), self.cs.clone(), self.beacon.clone()); - chain_rand - .get_beacon_randomness(blocks, pers, round, entropy, lookback) - .await + match self.get_network_version(round) { + NetworkVersion::V14 => { + chain_rand + .get_beacon_randomness_v3(blocks, pers, round, entropy) + .await + } + NetworkVersion::V13 => { + chain_rand + .get_beacon_randomness_v2(blocks, pers, round, entropy) + .await + } + _ => { + chain_rand + .get_beacon_randomness_v1(blocks, pers, round, entropy) + .await + } + } } /// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, ChainEpoch, diff --git a/node/rpc/src/chain_api.rs b/node/rpc/src/chain_api.rs index 4928aea92cf0..939366a1db62 100644 --- a/node/rpc/src/chain_api.rs +++ b/node/rpc/src/chain_api.rs @@ -299,7 +299,6 @@ where DomainSeparationTag::from_i64(pers).ok_or("invalid DomainSeparationTag")?, epoch, &base64::decode(entropy)?, - epoch <= networks::UPGRADE_HYPERDRIVE_HEIGHT, ) .await?) } diff --git a/vm/interpreter/src/default_runtime.rs b/vm/interpreter/src/default_runtime.rs index ab5a3010a4ab..ec4f4ba76b01 100644 --- a/vm/interpreter/src/default_runtime.rs +++ b/vm/interpreter/src/default_runtime.rs @@ -683,7 +683,11 @@ where rand_epoch: ChainEpoch, entropy: &[u8], ) -> Result { - let r = if rand_epoch > networks::UPGRADE_HYPERDRIVE_HEIGHT { + let r = if rand_epoch >= networks::UPGRADE_ACTORS_V6_HEIGHT { + self.rand + .get_beacon_randomness_v3(personalization, rand_epoch, entropy) + .map_err(|e| e.downcast_fatal("could not get randomness"))? + } else if rand_epoch > networks::UPGRADE_HYPERDRIVE_HEIGHT { self.rand .get_beacon_randomness_v2(personalization, rand_epoch, entropy) .map_err(|e| e.downcast_fatal("could not get randomness"))? diff --git a/vm/interpreter/src/rand.rs b/vm/interpreter/src/rand.rs index f55a2d60666f..fd08a2f4378a 100644 --- a/vm/interpreter/src/rand.rs +++ b/vm/interpreter/src/rand.rs @@ -38,4 +38,11 @@ pub trait Rand { round: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box>; + + fn get_beacon_randomness_v3( + &self, + pers: DomainSeparationTag, + round: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box>; } From c5e1220a50d75755225fbfcc01315a3de9d60108 Mon Sep 17 00:00:00 2001 From: noot Date: Wed, 15 Dec 2021 20:21:09 -0500 Subject: [PATCH 4/9] cleanup --- blockchain/chain/src/store/chain_store.rs | 166 ---------------------- forest/src/daemon.rs | 8 -- 2 files changed, 174 deletions(-) diff --git a/blockchain/chain/src/store/chain_store.rs b/blockchain/chain/src/store/chain_store.rs index e2b14cc1df0f..11b4307d6807 100644 --- a/blockchain/chain/src/store/chain_store.rs +++ b/blockchain/chain/src/store/chain_store.rs @@ -286,154 +286,6 @@ where } } - // /// 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> { - // 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, - // ) - // } - - // /// network v0-12 - // pub async fn get_chain_randomness_v1( - // &self, - // blocks: &TipsetKeys, - // pers: DomainSeparationTag, - // round: ChainEpoch, - // entropy: &[u8], - // ) -> Result<[u8; 32], Box> { - // self.get_chain_randomness(blocks, pers, round, entropy, true) - // .await - // } - - // /// network v13 onwards - // pub async fn get_chain_randomness_v2( - // &self, - // blocks: &TipsetKeys, - // pers: DomainSeparationTag, - // round: ChainEpoch, - // entropy: &[u8], - // ) -> Result<[u8; 32], Box> { - // self.get_chain_randomness(blocks, pers, round, entropy, false) - // .await - // } - - // /// network v0-12; with lookback - // pub async fn get_beacon_randomness_v1( - // &self, - // blocks: &TipsetKeys, - // pers: DomainSeparationTag, - // round: ChainEpoch, - // entropy: &[u8], - // ) -> Result<[u8; 32], Box> { - // self.get_beacon_randomness(blocks, pers, round, entropy, true) - // .await - // } - - // /// network v13; without lookback - // pub async fn get_beacon_randomness_v2( - // &self, - // blocks: &TipsetKeys, - // pers: DomainSeparationTag, - // round: ChainEpoch, - // entropy: &[u8], - // ) -> Result<[u8; 32], Box> { - // self.get_beacon_randomness(blocks, pers, round, entropy, false) - // .await - // } - - // /// network v14 onwards - // pub async fn get_beacon_randomness_v3( - // &self, - // blocks: &TipsetKeys, - // pers: DomainSeparationTag, - // round: ChainEpoch, - // entropy: &[u8], - // ) -> Result<[u8; 32], Box> { - // if round < 0 { - // return self - // .get_beacon_randomness_v2(blocks, pers, round, entropy) - // .await; - // } - - // let beacon_entry = self.extract_beacon_entry_for_epoch(blocks, round).await?; - // draw_randomness(beacon_entry.data(), pers, round, entropy) - // } - - // /// 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> { - // let rand_ts = self - // .get_beacon_randomness_tipset(blocks, round, lookback) - // .await?; - // let be = self.latest_beacon_entry(&rand_ts).await?; - // draw_randomness(be.data(), pers, round, entropy) - // } - - // pub async fn extract_beacon_entry_for_epoch( - // &self, - // blocks: &TipsetKeys, - // epoch: ChainEpoch, - // ) -> Result> { - // let rand_ts = self - // .get_beacon_randomness_tipset(blocks, epoch, false) - // .await?; - // // let round = self.beacon.beacon_for_epoch(epoch); - // Err("unimplemented".into()) - // } - - // pub async fn get_beacon_randomness_tipset( - // &self, - // blocks: &TipsetKeys, - // round: ChainEpoch, - // lookback: bool, - // ) -> Result, Box> { - // 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 res = self.tipset_by_height(search_height, ts, lookback).await; - // match res { - // Ok(rand_ts) => return Ok(rand_ts), - // Err(e) => return Err(e.into()), - // }; - // } - /// Finds the latest beacon entry given a tipset up to 20 tipsets behind pub async fn latest_beacon_entry(&self, ts: &Tipset) -> Result { let check_for_beacon_entry = |ts: &Tipset| { @@ -886,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> { -// let mut state = Params::new().hash_length(32).to_state(); -// state.write_i64::(pers as i64)?; -// let vrf_digest = blake2b_256(rbase); -// state.write_all(&vrf_digest)?; -// state.write_i64::(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, root: &Cid) -> Result, Error> where diff --git a/forest/src/daemon.rs b/forest/src/daemon.rs index 92ad811826da..4c4b5e97f6a7 100644 --- a/forest/src/daemon.rs +++ b/forest/src/daemon.rs @@ -131,19 +131,11 @@ pub(super) async fn start(config: Config) { // Read Genesis file // * When snapshot command implemented, this genesis does not need to be initialized - // let (genesis, network_name) = initialize_genesis(config.genesis_file.as_ref(), &state_manager) - // .await - // .unwrap(); let genesis = read_genesis_header(config.genesis_file.as_ref(), &chain_store) .await .unwrap(); // Initialize StateManager - // let beacon = Arc::new( - // networks::beacon_schedule_default(genesis.min_timestamp()) - // .await - // .unwrap(), - // ); let sm = StateManager::new(Arc::clone(&chain_store)).await.unwrap(); let state_manager = Arc::new(sm); From 5c08d9bfe87ac95460249ab1c2354d1f0088a303 Mon Sep 17 00:00:00 2001 From: noot Date: Wed, 15 Dec 2021 20:26:20 -0500 Subject: [PATCH 5/9] more cleanup --- blockchain/state_manager/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index 7a32252e4c29..c8aacf2a8e77 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -162,7 +162,6 @@ where pers: DomainSeparationTag, round: ChainEpoch, entropy: &[u8], - // lookback: bool, ) -> Result<[u8; 32], Box> { let chain_rand = ChainRand::new(blocks.to_owned(), self.cs.clone(), self.beacon.clone()); match self.get_network_version(round) { From 26a22b32a9d663847e5a59da4d211d95a0339152 Mon Sep 17 00:00:00 2001 From: noot Date: Thu, 16 Dec 2021 12:32:17 -0500 Subject: [PATCH 6/9] fix extract_beacon_entry_for_epoch --- blockchain/state_manager/src/chain_rand.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/blockchain/state_manager/src/chain_rand.rs b/blockchain/state_manager/src/chain_rand.rs index cbfe22b3134f..d95f96546a24 100644 --- a/blockchain/state_manager/src/chain_rand.rs +++ b/blockchain/state_manager/src/chain_rand.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0, MIT use async_std::task; -use beacon::{BeaconEntry, BeaconSchedule, DrandBeacon}; +use beacon::{Beacon, BeaconEntry, BeaconSchedule, DrandBeacon}; use blake2b_simd::Params; use blockstore::BlockStore; use byteorder::{BigEndian, WriteBytesExt}; @@ -162,12 +162,13 @@ where let mut rand_ts: Arc = self .get_beacon_randomness_tipset(blocks, epoch, false) .await?; - let (round, _) = self.beacon.beacon_for_epoch(epoch)?; + let (_, beacon) = self.beacon.beacon_for_epoch(epoch)?; + let round = beacon.max_beacon_round_for_epoch(epoch); for _ in 0..20 { let cbe = rand_ts.blocks()[0].beacon_entries(); for v in cbe.iter() { - if v.round() == round as u64 { + if v.round() == round { return Ok(v.clone()); } } From 0d18c0c253b78ab658f9311b3ab05e544300a503 Mon Sep 17 00:00:00 2001 From: noot Date: Thu, 16 Dec 2021 16:15:04 -0500 Subject: [PATCH 7/9] attempt to fix tests --- blockchain/state_manager/src/lib.rs | 4 ++-- tests/conformance_tests/src/rand_replay.rs | 18 ++++++++++++++---- vm/actor/src/builtin/market/mod.rs | 2 +- vm/actor/src/builtin/miner/mod.rs | 1 - 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index c8aacf2a8e77..a086816c7bf2 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -103,7 +103,7 @@ where cache: RwLock::new(HashMap::new()), publisher: None, genesis_info: GenesisInfo::default(), - beacon: beacon, + beacon, }) } @@ -120,7 +120,7 @@ where cache: RwLock::new(HashMap::new()), publisher: Some(chain_subs), genesis_info: GenesisInfo::default(), - beacon: beacon, + beacon, }) } diff --git a/tests/conformance_tests/src/rand_replay.rs b/tests/conformance_tests/src/rand_replay.rs index a0970328bd17..7c1decf1b2d1 100644 --- a/tests/conformance_tests/src/rand_replay.rs +++ b/tests/conformance_tests/src/rand_replay.rs @@ -29,7 +29,7 @@ impl<'a> ReplayingRand<'a> { } impl Rand for ReplayingRand<'_> { - fn get_chain_randomness( + fn get_chain_randomness_v1( &self, dst: DomainSeparationTag, epoch: ChainEpoch, @@ -47,7 +47,7 @@ impl Rand for ReplayingRand<'_> { self.fallback.get_chain_randomness(dst, epoch, entropy) } } - fn get_beacon_randomness( + fn get_beacon_randomness_v1( &self, dst: DomainSeparationTag, epoch: ChainEpoch, @@ -66,7 +66,7 @@ impl Rand for ReplayingRand<'_> { } } // TODO: Check if this is going to be correct for when we integrate v5 Actors test vectors - fn get_beacon_randomness_looking_forward( + fn get_beacon_randomness_v2( &self, dst: DomainSeparationTag, epoch: ChainEpoch, @@ -85,7 +85,7 @@ impl Rand for ReplayingRand<'_> { } } // TODO: Check if this is going to be correct for when we integrate v5 Actors test vectors - fn get_chain_randomness_looking_forward( + fn get_chain_randomness_v2( &self, dst: DomainSeparationTag, epoch: ChainEpoch, @@ -103,4 +103,14 @@ impl Rand for ReplayingRand<'_> { self.fallback.get_chain_randomness(dst, epoch, entropy) } } + + fn get_beacon_randomness_v3( + &self, + dst: DomainSeparationTag, + epoch: ChainEpoch, + entropy: &[u8], + ) -> Result<[u8; 32], Box> { + // TODO + self.get_beacon_randomness_v2(dst, epoch, entropy) + } } diff --git a/vm/actor/src/builtin/market/mod.rs b/vm/actor/src/builtin/market/mod.rs index 5bc57a00c49a..bb2ae82ed119 100644 --- a/vm/actor/src/builtin/market/mod.rs +++ b/vm/actor/src/builtin/market/mod.rs @@ -477,7 +477,7 @@ impl Actor { // This should only fail on programmer error because all expected invalid conditions should be filtered in the first set of checks. // TODO: Check if we neeed to make the previous look non mut - for (vid, valid_deal) in params.deals.iter_mut().enumerate() { + for (vid, valid_deal) in valid_deals.iter().enumerate() { msm.lock_client_and_provider_balances(&valid_deal.proposal)?; let id = msm.generate_storage_deal_id(); diff --git a/vm/actor/src/builtin/miner/mod.rs b/vm/actor/src/builtin/miner/mod.rs index fb7c4c0ba3a9..c7fec5f8fd20 100644 --- a/vm/actor/src/builtin/miner/mod.rs +++ b/vm/actor/src/builtin/miner/mod.rs @@ -4011,7 +4011,6 @@ where "unlocked balance can not repay fee debt", ) })?; - info!("RepayDebtsOrAbort was called and succeeded"); Ok(res) } From 028e249471af3c7b1ebc9f19c1063dc95f6ba0de Mon Sep 17 00:00:00 2001 From: noot Date: Thu, 16 Dec 2021 17:56:49 -0500 Subject: [PATCH 8/9] lint, fix test issues --- blockchain/state_manager/src/chain_rand.rs | 13 +++++------ blockchain/state_manager/src/lib.rs | 14 +++++++++++- forest/src/daemon.rs | 2 +- tests/conformance_tests/src/rand_replay.rs | 22 ++++++++++++++----- tests/conformance_tests/src/stubs.rs | 16 ++++++++++---- .../tests/conformance_runner.rs | 2 +- utils/genesis/src/lib.rs | 14 +++++++++++- 7 files changed, 62 insertions(+), 21 deletions(-) diff --git a/blockchain/state_manager/src/chain_rand.rs b/blockchain/state_manager/src/chain_rand.rs index d95f96546a24..1feab4af62ef 100644 --- a/blockchain/state_manager/src/chain_rand.rs +++ b/blockchain/state_manager/src/chain_rand.rs @@ -36,7 +36,7 @@ where Self { blks, cs, beacon } } - /// Gets 32 bytes of randomness for ChainRand paramaterized by the DomainSeparationTag, ChainEpoch, + /// Gets 32 bytes of randomness for ChainRand parameterized by the DomainSeparationTag, ChainEpoch, /// Entropy from the ticket chain. pub async fn get_chain_randomness( &self, @@ -167,7 +167,7 @@ where for _ in 0..20 { let cbe = rand_ts.blocks()[0].beacon_entries(); - for v in cbe.iter() { + for v in cbe { if v.round() == round { return Ok(v.clone()); } @@ -197,11 +197,10 @@ where let search_height = if round < 0 { 0 } else { round }; - let res = self.cs.tipset_by_height(search_height, ts, lookback).await; - match res { - Ok(rand_ts) => return Ok(rand_ts), - Err(e) => return Err(e.into()), - }; + self.cs + .tipset_by_height(search_height, ts, lookback) + .await + .map_err(|e| e.into()) } } diff --git a/blockchain/state_manager/src/lib.rs b/blockchain/state_manager/src/lib.rs index a086816c7bf2..63e5698895fa 100644 --- a/blockchain/state_manager/src/lib.rs +++ b/blockchain/state_manager/src/lib.rs @@ -175,7 +175,19 @@ where .get_beacon_randomness_v2(blocks, pers, round, entropy) .await } - _ => { + NetworkVersion::V0 + | NetworkVersion::V1 + | NetworkVersion::V2 + | NetworkVersion::V3 + | NetworkVersion::V4 + | NetworkVersion::V5 + | NetworkVersion::V6 + | NetworkVersion::V7 + | NetworkVersion::V8 + | NetworkVersion::V9 + | NetworkVersion::V10 + | NetworkVersion::V11 + | NetworkVersion::V12 => { chain_rand .get_beacon_randomness_v1(blocks, pers, round, entropy) .await diff --git a/forest/src/daemon.rs b/forest/src/daemon.rs index 4c4b5e97f6a7..f4fb3ed2646f 100644 --- a/forest/src/daemon.rs +++ b/forest/src/daemon.rs @@ -184,7 +184,7 @@ pub(super) async fn start(config: Config) { let chain_muxer_tipset_sink = tipset_sink.clone(); let chain_muxer = ChainMuxer::<_, _, FullVerifier, _>::new( Arc::clone(&state_manager), - state_manager.beacon_schedule().clone(), + state_manager.beacon_schedule(), Arc::clone(&mpool), network_send.clone(), network_rx, diff --git a/tests/conformance_tests/src/rand_replay.rs b/tests/conformance_tests/src/rand_replay.rs index 7c1decf1b2d1..32b324b6c492 100644 --- a/tests/conformance_tests/src/rand_replay.rs +++ b/tests/conformance_tests/src/rand_replay.rs @@ -44,7 +44,7 @@ impl Rand for ReplayingRand<'_> { if let Some(bz) = self.matches(rule) { Ok(bz) } else { - self.fallback.get_chain_randomness(dst, epoch, entropy) + self.fallback.get_chain_randomness_v1(dst, epoch, entropy) } } fn get_beacon_randomness_v1( @@ -62,7 +62,7 @@ impl Rand for ReplayingRand<'_> { if let Some(bz) = self.matches(rule) { Ok(bz) } else { - self.fallback.get_beacon_randomness(dst, epoch, entropy) + self.fallback.get_beacon_randomness_v1(dst, epoch, entropy) } } // TODO: Check if this is going to be correct for when we integrate v5 Actors test vectors @@ -81,7 +81,7 @@ impl Rand for ReplayingRand<'_> { if let Some(bz) = self.matches(rule) { Ok(bz) } else { - self.fallback.get_beacon_randomness(dst, epoch, entropy) + self.fallback.get_beacon_randomness_v2(dst, epoch, entropy) } } // TODO: Check if this is going to be correct for when we integrate v5 Actors test vectors @@ -100,7 +100,7 @@ impl Rand for ReplayingRand<'_> { if let Some(bz) = self.matches(rule) { Ok(bz) } else { - self.fallback.get_chain_randomness(dst, epoch, entropy) + self.fallback.get_chain_randomness_v2(dst, epoch, entropy) } } @@ -110,7 +110,17 @@ impl Rand for ReplayingRand<'_> { epoch: ChainEpoch, entropy: &[u8], ) -> Result<[u8; 32], Box> { - // TODO - self.get_beacon_randomness_v2(dst, epoch, entropy) + 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_beacon_randomness_v3(dst, epoch, entropy) + } } } diff --git a/tests/conformance_tests/src/stubs.rs b/tests/conformance_tests/src/stubs.rs index 8cd6bb9cb7be..b3c96bc1f3d4 100644 --- a/tests/conformance_tests/src/stubs.rs +++ b/tests/conformance_tests/src/stubs.rs @@ -5,7 +5,7 @@ use super::*; pub struct TestRand; impl Rand for TestRand { - fn get_chain_randomness( + fn get_chain_randomness_v1( &self, _: DomainSeparationTag, _: ChainEpoch, @@ -13,7 +13,7 @@ impl Rand for TestRand { ) -> Result<[u8; 32], Box> { Ok(*b"i_am_random_____i_am_random_____") } - fn get_beacon_randomness( + fn get_beacon_randomness_v1( &self, _: DomainSeparationTag, _: ChainEpoch, @@ -21,7 +21,7 @@ impl Rand for TestRand { ) -> Result<[u8; 32], Box> { Ok(*b"i_am_random_____i_am_random_____") } - fn get_beacon_randomness_looking_forward( + fn get_beacon_randomness_v2( &self, _: DomainSeparationTag, _: ChainEpoch, @@ -29,7 +29,15 @@ impl Rand for TestRand { ) -> Result<[u8; 32], Box> { Ok(*b"i_am_random_____i_am_random_____") } - fn get_chain_randomness_looking_forward( + fn get_chain_randomness_v2( + &self, + _: DomainSeparationTag, + _: ChainEpoch, + _: &[u8], + ) -> Result<[u8; 32], Box> { + Ok(*b"i_am_random_____i_am_random_____") + } + fn get_beacon_randomness_v3( &self, _: DomainSeparationTag, _: ChainEpoch, diff --git a/tests/conformance_tests/tests/conformance_runner.rs b/tests/conformance_tests/tests/conformance_runner.rs index 64a918832779..7cdd412a100d 100644 --- a/tests/conformance_tests/tests/conformance_runner.rs +++ b/tests/conformance_tests/tests/conformance_runner.rs @@ -213,7 +213,7 @@ async fn execute_tipset_vector( ) -> Result<(), Box> { let bs = load_car(car).await?; let bs = Arc::new(bs); - let sm = Arc::new(StateManager::new(Arc::new(ChainStore::new(bs)))); + let sm = Arc::new(StateManager::new(Arc::new(ChainStore::new(bs))).await?); genesis::initialize_genesis(None, &sm).await.unwrap(); let base_epoch = variant.epoch; diff --git a/utils/genesis/src/lib.rs b/utils/genesis/src/lib.rs index 3432bc674969..12d8366f9bee 100644 --- a/utils/genesis/src/lib.rs +++ b/utils/genesis/src/lib.rs @@ -62,7 +62,19 @@ where let network_name = state_manager .get_network_name(genesis_header.state_root()) .map_err(|e| format!("Failed to retrieve network name from genesis: {}", e))?; - Ok(network_name.to_string()) + Ok(network_name) +} + +pub async fn initialize_genesis( + genesis_fp: Option<&String>, + state_manager: &StateManager, +) -> Result<(Tipset, String), Box> +where + BS: BlockStore + Send + Sync + 'static, +{ + let ts = read_genesis_header(genesis_fp, state_manager.chain_store()).await?; + let network_name = get_network_name_from_genesis(&ts, state_manager).await?; + Ok((ts, network_name)) } async fn process_car( From 19e9f71983d180606b9ac2966d9938e00423e540 Mon Sep 17 00:00:00 2001 From: noot Date: Fri, 17 Dec 2021 19:01:00 -0500 Subject: [PATCH 9/9] fix unit tests --- blockchain/blocks/src/header/mod.rs | 4 +--- forest/src/daemon.rs | 19 +++++++++++++++++-- node/rpc/src/sync_api.rs | 9 ++++++++- vm/interpreter/tests/transfer_test.rs | 17 +++++++++++++---- 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/blockchain/blocks/src/header/mod.rs b/blockchain/blocks/src/header/mod.rs index 9215190e265b..f7ca5eadf1bb 100644 --- a/blockchain/blocks/src/header/mod.rs +++ b/blockchain/blocks/src/header/mod.rs @@ -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; diff --git a/forest/src/daemon.rs b/forest/src/daemon.rs index f4fb3ed2646f..e74fd88e4de0 100644 --- a/forest/src/daemon.rs +++ b/forest/src/daemon.rs @@ -134,6 +134,7 @@ pub(super) async fn start(config: Config) { let genesis = read_genesis_header(config.genesis_file.as_ref(), &chain_store) .await .unwrap(); + chain_store.set_genesis(&genesis.blocks()[0]).unwrap(); // Initialize StateManager let sm = StateManager::new(Arc::clone(&chain_store)).await.unwrap(); @@ -260,13 +261,21 @@ pub(super) async fn start(config: Config) { #[cfg(not(any(feature = "interopnet", feature = "devnet")))] mod test { use super::*; + use address::Address; + use blocks::BlockHeader; use db::MemoryDB; #[async_std::test] async fn import_snapshot_from_file() { let db = Arc::new(MemoryDB::default()); let cs = Arc::new(ChainStore::new(db)); - let sm = Arc::new(StateManager::new(cs)); + let genesis_header = BlockHeader::builder() + .miner_address(Address::new_id(0)) + .timestamp(7777) + .build() + .unwrap(); + cs.set_genesis(&genesis_header).unwrap(); + let sm = Arc::new(StateManager::new(cs).await.unwrap()); import_chain::(&sm, "test_files/chain4.car", None, false) .await .expect("Failed to import chain"); @@ -275,7 +284,13 @@ mod test { async fn import_chain_from_file() { let db = Arc::new(MemoryDB::default()); let cs = Arc::new(ChainStore::new(db)); - let sm = Arc::new(StateManager::new(cs)); + let genesis_header = BlockHeader::builder() + .miner_address(Address::new_id(0)) + .timestamp(7777) + .build() + .unwrap(); + cs.set_genesis(&genesis_header).unwrap(); + let sm = Arc::new(StateManager::new(cs).await.unwrap()); import_chain::(&sm, "test_files/chain4.car", Some(0), false) .await .expect("Failed to import chain"); diff --git a/node/rpc/src/sync_api.rs b/node/rpc/src/sync_api.rs index ddcb2f149f29..717c570a3a63 100644 --- a/node/rpc/src/sync_api.rs +++ b/node/rpc/src/sync_api.rs @@ -109,6 +109,7 @@ where #[cfg(test)] mod tests { use super::*; + use address::Address; use async_std::channel::{bounded, Receiver}; use async_std::sync::RwLock; use async_std::task; @@ -138,7 +139,13 @@ mod tests { let (network_send, network_rx) = bounded(5); let db = Arc::new(MemoryDB::default()); let cs_arc = Arc::new(ChainStore::new(db.clone())); - let state_manager = Arc::new(StateManager::new(cs_arc.clone())); + let genesis_header = BlockHeader::builder() + .miner_address(Address::new_id(0)) + .timestamp(7777) + .build() + .unwrap(); + cs_arc.set_genesis(&genesis_header).unwrap(); + let state_manager = Arc::new(StateManager::new(cs_arc.clone()).await.unwrap()); let state_manager_for_thread = state_manager.clone(); let cs_for_test = cs_arc.clone(); let cs_for_chain = cs_arc.clone(); diff --git a/vm/interpreter/tests/transfer_test.rs b/vm/interpreter/tests/transfer_test.rs index 98b4445829a8..31f81cf0d45f 100644 --- a/vm/interpreter/tests/transfer_test.rs +++ b/vm/interpreter/tests/transfer_test.rs @@ -37,7 +37,7 @@ impl<'db> LookbackStateGetter<'db, MemoryDB> for MockStateLB<'db, MemoryDB> { struct MockRand; impl Rand for MockRand { - fn get_chain_randomness( + fn get_chain_randomness_v1( &self, _: DomainSeparationTag, _: ChainEpoch, @@ -45,7 +45,7 @@ impl Rand for MockRand { ) -> Result<[u8; 32], Box> { Ok(*b"i_am_random_____i_am_random_____") } - fn get_beacon_randomness( + fn get_beacon_randomness_v1( &self, _: DomainSeparationTag, _: ChainEpoch, @@ -54,7 +54,7 @@ impl Rand for MockRand { Ok(*b"i_am_random_____i_am_random_____") } - fn get_chain_randomness_looking_forward( + fn get_chain_randomness_v2( &self, _: DomainSeparationTag, _: ChainEpoch, @@ -63,7 +63,16 @@ impl Rand for MockRand { Ok(*b"i_am_random_____i_am_random_____") } - fn get_beacon_randomness_looking_forward( + fn get_beacon_randomness_v2( + &self, + _: DomainSeparationTag, + _: ChainEpoch, + _: &[u8], + ) -> Result<[u8; 32], Box> { + Ok(*b"i_am_random_____i_am_random_____") + } + + fn get_beacon_randomness_v3( &self, _: DomainSeparationTag, _: ChainEpoch,