diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..3b125ccb1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cSpell.words": [ + "blbo" + ] +} \ No newline at end of file diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index 741d9a95b..721460397 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -1072,7 +1072,7 @@ impl BeaconChain { block_root: &Hash256, data_availability_boundary: Epoch, ) -> Result>, Error> { - match self.store.get_blobs(block_root)? { + match self.store.get_blobs(block_root, slot)? { Some(blobs) => Ok(Some(blobs)), None => { // Check for the corresponding block to understand whether we *should* have blobs. diff --git a/beacon_node/client/src/builder.rs b/beacon_node/client/src/builder.rs index e09d2621f..b91e29355 100644 --- a/beacon_node/client/src/builder.rs +++ b/beacon_node/client/src/builder.rs @@ -910,7 +910,7 @@ where self.db_path = Some(hot_path.into()); self.freezer_db_path = Some(cold_path.into()); - self.blobs_freezer_db_path = cold_blobs_path; + self.blobs_freezer_db_path = cold_blobs_path.clone(); let inner_spec = spec.clone(); let deposit_contract_deploy_block = context diff --git a/beacon_node/http_api/src/block_id.rs b/beacon_node/http_api/src/block_id.rs index 45c7bed1f..96e3d6fc8 100644 --- a/beacon_node/http_api/src/block_id.rs +++ b/beacon_node/http_api/src/block_id.rs @@ -218,7 +218,7 @@ impl BlockId { chain: &BeaconChain, ) -> Result>, warp::Rejection> { let root = self.root(chain)?.0; - match chain.store.get_blobs(&root) { + match chain.get_blobs(&root, None) { Ok(Some(blob)) => Ok(Arc::new(blob)), Ok(None) => Err(warp_utils::reject::custom_not_found(format!( "Blob with block root {} is not in the store", diff --git a/beacon_node/network/src/beacon_processor/worker/rpc_methods.rs b/beacon_node/network/src/beacon_processor/worker/rpc_methods.rs index 01b7cb43b..0c903ec33 100644 --- a/beacon_node/network/src/beacon_processor/worker/rpc_methods.rs +++ b/beacon_node/network/src/beacon_processor/worker/rpc_methods.rs @@ -795,12 +795,14 @@ impl Worker { // remove all skip slots let block_roots = block_roots.into_iter().flatten().collect::>(); + let mut slot_hint: Option = None; let mut blobs_sent = 0; let mut send_response = true; for root in block_roots { match self.chain.get_blobs(&root, data_availability_boundary) { Ok(Some(blobs)) => { + slot_hint = Some(blobs.beacon_block_slot + 1); blobs_sent += 1; self.send_network_message(NetworkMessage::SendResponse { peer_id, diff --git a/beacon_node/store/src/hot_cold_store.rs b/beacon_node/store/src/hot_cold_store.rs index 951dbd2ca..7d3abebbc 100644 --- a/beacon_node/store/src/hot_cold_store.rs +++ b/beacon_node/store/src/hot_cold_store.rs @@ -533,31 +533,27 @@ impl, Cold: ItemStore> HotColdDB Ok(()) } - pub fn get_blobs(&self, block_root: &Hash256) -> Result>, Error> { - // FIXME(sean) I was attempting to use a blob cache here but was getting deadlocks, - // may want to attempt to use one again - if let Some(bytes) = self - .hot_db - .get_bytes(DBColumn::BeaconBlob.into(), block_root.as_bytes())? - { - let ret = BlobsSidecar::from_ssz_bytes(&bytes)?; - self.blob_cache.lock().put(*block_root, ret.clone()); - Ok(Some(ret)) - } else { - let blobs_freezer = if let Some(ref cold_blobs_db) = self.cold_blobs_db { - cold_blobs_db - } else { - &self.cold_db - }; - - if let Some(ref blobs_bytes) = - blobs_freezer.get_bytes(DBColumn::BeaconBlob.into(), block_root.as_bytes())? - { - Ok(Some(BlobsSidecar::from_ssz_bytes(blobs_bytes)?)) - } else { - Ok(None) + /// Fetch a blobs sidecar from the store. + /// + /// If `slot` is provided then it will be used as a hint as to which database should + /// be checked first. + pub fn get_blobs( + &self, + block_root: &Hash256, + slot: Option, + ) -> Result>, Error> { + if let Some(slot) = slot { + if slot < self.get_split_slot() { + return match self.load_cold_blobs(block_root)? { + Some(blobs) => Ok(Some(blobs)), + None => self.load_hot_blobs(block_root), + }; } } + match self.load_hot_blobs(block_root)? { + Some(blobs) => Ok(Some(blobs)), + None => self.load_cold_blobs(block_root), + } } pub fn blobs_as_kv_store_ops( @@ -1236,6 +1232,41 @@ impl, Cold: ItemStore> HotColdDB }) } + /// Load a blobs sidecar from the hot database. + pub fn load_hot_blobs(&self, block_root: &Hash256) -> Result>, Error> { + // FIXME(sean) I was attempting to use a blob cache here but was getting deadlocks, + // may want to attempt to use one again + if let Some(bytes) = self + .hot_db + .get_bytes(DBColumn::BeaconBlob.into(), block_root.as_bytes())? + { + let ret = BlobsSidecar::from_ssz_bytes(&bytes)?; + self.blob_cache.lock().put(*block_root, ret.clone()); + Ok(Some(ret)) + } else { + Ok(None) + } + } + + /// Try to load a blobs from the freezer database. + /// + /// Return `None` if no blobs sidecar with `block_root` lies in the freezer. + pub fn load_cold_blobs(&self, block_root: &Hash256) -> Result>, Error> { + let blobs_freezer = if let Some(ref cold_blobs_db) = self.cold_blobs_db { + cold_blobs_db + } else { + &self.cold_db + }; + + if let Some(ref blobs_bytes) = + blobs_freezer.get_bytes(DBColumn::BeaconBlob.into(), block_root.as_bytes())? + { + Ok(Some(BlobsSidecar::from_ssz_bytes(blobs_bytes)?)) + } else { + Ok(None) + } + } + /// Get a reference to the `ChainSpec` used by the database. pub fn get_chain_spec(&self) -> &ChainSpec { &self.spec @@ -1994,7 +2025,7 @@ pub fn migrate_database, Cold: ItemStore>( } // Prepare migration of blobs to freezer. - if let Some(blobs) = store.get_blobs(&block_root)? { + if let Some(blobs) = store.get_blobs(&block_root, Some(slot))? { hot_db_ops.push(StoreOp::DeleteBlobs(block_root)); cold_blobs_db_ops.push(StoreOp::PutBlobs(block_root, Arc::new(blobs))); }