Skip to content

Commit bf60fc3

Browse files
committed
refactor: BlockRegistry error cases
1. Fix/simplify error checks on put. 1. The overflow checks were wrong. 2. We didn't check for CBOR. 2. Refactor errors and implement conversions. This will make the next patch easier.
1 parent 8df0d24 commit bf60fc3

File tree

3 files changed

+58
-26
lines changed

3 files changed

+58
-26
lines changed

fvm/src/kernel/blocks.rs

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
use std::convert::TryInto;
22

3-
use cid::Cid;
3+
use fvm_ipld_encoding::DAG_CBOR;
44
use thiserror::Error;
55

6+
use super::{ExecutionError, SyscallError};
7+
use crate::syscall_error;
8+
69
#[derive(Default)]
710
pub(crate) struct BlockRegistry {
811
blocks: Vec<Block>,
@@ -14,6 +17,7 @@ pub(crate) struct BlockRegistry {
1417
pub type BlockId = u32;
1518

1619
const FIRST_ID: BlockId = 1;
20+
const MAX_BLOCKS: u32 = i32::MAX as u32; // TODO: Limit
1721

1822
#[derive(Copy, Clone)]
1923
pub struct BlockStat {
@@ -61,19 +65,42 @@ impl Block {
6165
}
6266

6367
#[derive(Error, Debug)]
64-
pub enum BlockError {
65-
#[error("block {0} is unreachable")]
66-
Unreachable(Box<Cid>),
68+
pub enum BlockPutError {
6769
#[error("too many blocks have been written")]
6870
TooManyBlocks,
69-
#[error("block handle {0} does not exist, or is illegal")]
70-
InvalidHandle(BlockId),
71-
#[error("invalid multihash length or code")]
72-
InvalidMultihashSpec { length: u32, code: u64 },
7371
#[error("invalid or forbidden ipld codec")]
7472
InvalidCodec(u64),
75-
#[error("state {0} is missing from the local datastore")]
76-
MissingState(Box<Cid>), // boxed because CIDs are potentially large.
73+
}
74+
75+
impl From<BlockPutError> for super::SyscallError {
76+
fn from(e: BlockPutError) -> Self {
77+
match e {
78+
BlockPutError::TooManyBlocks => syscall_error!(LimitExceeded; "{}", e),
79+
BlockPutError::InvalidCodec(_) => syscall_error!(IllegalCodec; "{}", e),
80+
}
81+
}
82+
}
83+
84+
impl From<BlockPutError> for ExecutionError {
85+
fn from(e: BlockPutError) -> Self {
86+
ExecutionError::Syscall(e.into())
87+
}
88+
}
89+
90+
#[derive(Error, Debug)]
91+
#[error("block handle {0} does not exist, or is illegal")]
92+
pub struct InvalidHandleError(BlockId);
93+
94+
impl From<InvalidHandleError> for SyscallError {
95+
fn from(e: InvalidHandleError) -> Self {
96+
syscall_error!(InvalidHandle; "{}", e)
97+
}
98+
}
99+
100+
impl From<InvalidHandleError> for ExecutionError {
101+
fn from(e: InvalidHandleError) -> Self {
102+
ExecutionError::Syscall(e.into())
103+
}
77104
}
78105

79106
impl BlockRegistry {
@@ -84,41 +111,46 @@ impl BlockRegistry {
84111

85112
impl BlockRegistry {
86113
/// Adds a new block to the registry, and returns a handle to refer to it.
87-
pub fn put(&mut self, block: Block) -> Result<BlockId, BlockError> {
88-
// TODO: limit the code types we allow.
89-
let mut id: u32 = self
90-
.blocks
91-
.len()
92-
.try_into()
93-
.map_err(|_| BlockError::TooManyBlocks)?;
94-
id += FIRST_ID;
114+
pub fn put(&mut self, block: Block) -> Result<BlockId, BlockPutError> {
115+
if self.is_full() {
116+
return Err(BlockPutError::TooManyBlocks);
117+
}
118+
if block.codec != DAG_CBOR {
119+
return Err(BlockPutError::InvalidCodec(block.codec));
120+
}
121+
122+
let id = FIRST_ID + self.blocks.len() as u32;
95123
self.blocks.push(block);
96124
Ok(id)
97125
}
98126

99127
/// Gets the block associated with a block handle.
100-
pub fn get(&self, id: BlockId) -> Result<&Block, BlockError> {
128+
pub fn get(&self, id: BlockId) -> Result<&Block, InvalidHandleError> {
101129
if id < FIRST_ID {
102-
return Err(BlockError::InvalidHandle(id));
130+
return Err(InvalidHandleError(id));
103131
}
104132
id.try_into()
105133
.ok()
106134
.and_then(|idx: usize| self.blocks.get(idx - FIRST_ID as usize))
107-
.ok_or(BlockError::InvalidHandle(id))
135+
.ok_or(InvalidHandleError(id))
108136
}
109137

110138
/// Returns the size & codec of the specified block.
111-
pub fn stat(&self, id: BlockId) -> Result<BlockStat, BlockError> {
139+
pub fn stat(&self, id: BlockId) -> Result<BlockStat, InvalidHandleError> {
112140
if id < FIRST_ID {
113-
return Err(BlockError::InvalidHandle(id));
141+
return Err(InvalidHandleError(id));
114142
}
115143
id.try_into()
116144
.ok()
117145
.and_then(|idx: usize| self.blocks.get(idx - FIRST_ID as usize))
118-
.ok_or(BlockError::InvalidHandle(id))
146+
.ok_or(InvalidHandleError(id))
119147
.map(|b| BlockStat {
120148
codec: b.codec(),
121149
size: b.size(),
122150
})
123151
}
152+
153+
pub fn is_full(&self) -> bool {
154+
self.blocks.len() as u32 == MAX_BLOCKS
155+
}
124156
}

fvm/src/kernel/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pub use blocks::{BlockError, BlockId, BlockStat};
1+
pub use blocks::{BlockId, BlockStat};
22
use cid::Cid;
33
use fvm_ipld_encoding::RawBytes;
44
use fvm_shared::address::Address;

fvm/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
//! of your choice during the initialization of the consuming application.
88
99
pub use kernel::default::DefaultKernel;
10-
pub use kernel::{BlockError, Kernel};
10+
pub use kernel::Kernel;
1111

1212
pub mod call_manager;
1313
pub mod executor;

0 commit comments

Comments
 (0)