Skip to content

Commit a2ea12f

Browse files
committed
fix(checkpoint): Relax Copy constraint to Clone
Previously, methods of `CheckPoint` were constrained by `D: Copy`, and this was to prevent a possible memory leak caused by the use of `mem::forget` in the Drop impl for `CheckPoint`. Since the memory leak concern has been addressed (#2056), we relax the constraint to `Clone` instead which permits instances of `CheckPoint<D>` where `D` is not necessarily a Copy type.
1 parent 4907581 commit a2ea12f

File tree

2 files changed

+14
-14
lines changed

2 files changed

+14
-14
lines changed

crates/chain/src/local_chain.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ fn apply_changeset_to_checkpoint<D>(
2828
changeset: &ChangeSet<D>,
2929
) -> Result<CheckPoint<D>, ApplyChangeSetError<D>>
3030
where
31-
D: ToBlockHash + fmt::Debug + Copy,
31+
D: ToBlockHash + fmt::Debug + Clone,
3232
{
3333
if let Some(start_height) = changeset.blocks.keys().next().cloned() {
3434
// changes after point of agreement
@@ -45,13 +45,13 @@ where
4545
}
4646
}
4747

48-
for (&height, &data) in &changeset.blocks {
48+
for (height, data) in &changeset.blocks {
4949
match data {
5050
Some(data) => {
51-
extension.insert(height, data);
51+
extension.insert(*height, data.clone());
5252
}
5353
None => {
54-
extension.remove(&height);
54+
extension.remove(height);
5555
}
5656
};
5757
}
@@ -248,7 +248,7 @@ impl<D> LocalChain<D> {
248248
// Methods where `D: ToBlockHash`
249249
impl<D> LocalChain<D>
250250
where
251-
D: ToBlockHash + fmt::Debug + Copy,
251+
D: ToBlockHash + fmt::Debug + Clone,
252252
{
253253
/// Constructs a [`LocalChain`] from genesis data.
254254
pub fn from_genesis(data: D) -> (Self, ChangeSet<D>) {
@@ -280,7 +280,7 @@ where
280280

281281
/// Construct a [`LocalChain`] from an initial `changeset`.
282282
pub fn from_changeset(changeset: ChangeSet<D>) -> Result<Self, MissingGenesisError> {
283-
let genesis_entry = changeset.blocks.get(&0).copied().flatten();
283+
let genesis_entry = changeset.blocks.get(&0).cloned().flatten();
284284
let genesis_data = match genesis_entry {
285285
Some(data) => data,
286286
None => return Err(MissingGenesisError),
@@ -430,7 +430,7 @@ where
430430
match cur.get(exp_height) {
431431
Some(cp) => {
432432
if cp.height() != exp_height
433-
|| Some(cp.hash()) != exp_data.map(|d| d.to_blockhash())
433+
|| Some(cp.hash()) != exp_data.as_ref().map(ToBlockHash::to_blockhash)
434434
{
435435
return false;
436436
}
@@ -596,7 +596,7 @@ impl std::error::Error for ApplyHeaderError {}
596596

597597
impl<D> LocalChain<D>
598598
where
599-
D: ToBlockHash + fmt::Debug + Copy,
599+
D: ToBlockHash + fmt::Debug + Clone,
600600
{
601601
/// Applies `update_tip` onto `original_tip`.
602602
///

crates/core/src/checkpoint.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ impl<D> CheckPoint<D> {
201201
// Methods where `D: ToBlockHash`
202202
impl<D> CheckPoint<D>
203203
where
204-
D: ToBlockHash + fmt::Debug + Copy,
204+
D: ToBlockHash + fmt::Debug + Clone,
205205
{
206206
/// Construct a new base [`CheckPoint`] from given `height` and `data` at the front of a linked
207207
/// list.
@@ -311,7 +311,7 @@ where
311311
// If we detect a conflict we need to revert to the previous checkpoint,
312312
// effectively displacing the old base. This will leave a gap in the chain
313313
// until the correct data is inserted.
314-
if base.is_conflict_of(height, data) {
314+
if base.is_conflict_of(height, &data) {
315315
base = base.prev().expect("cannot displace genesis block");
316316
}
317317

@@ -334,7 +334,7 @@ where
334334
return Err(self);
335335
}
336336
// The pushed data must not conflict with self.
337-
if self.is_conflict_of(height, data) {
337+
if self.is_conflict_of(height, &data) {
338338
return Err(self);
339339
}
340340
Ok(Self(Arc::new(CPInner {
@@ -351,7 +351,7 @@ where
351351
///
352352
/// This can happen whenever the incoming data tries to build upon the current
353353
/// height but `prev_blockhash` of `data` doesn't match the hash of this [`CheckPoint`].
354-
fn is_conflict_of(&self, height: u32, data: D) -> bool {
354+
fn is_conflict_of(&self, height: u32, data: &D) -> bool {
355355
self.height().saturating_add(1) == height
356356
&& data
357357
.prev_blockhash()
@@ -361,7 +361,7 @@ where
361361
/// Whether this [`CheckPoint`] may be considered a valid dependency (parent) of the given
362362
/// `height` and `data`.
363363
#[allow(unused)]
364-
fn is_dependency_of(&self, height: u32, data: D) -> bool {
364+
fn is_dependency_of(&self, height: u32, data: &D) -> bool {
365365
let height_diff = height.saturating_sub(self.height());
366366
// Either a gap exists, in which case there will not be a conflict
367367
height_diff > 1
@@ -413,7 +413,7 @@ pub struct CheckPointEntryIter<D> {
413413

414414
impl<D> Iterator for CheckPointEntryIter<D>
415415
where
416-
D: ToBlockHash + fmt::Debug + Copy,
416+
D: ToBlockHash + fmt::Debug + Clone,
417417
{
418418
type Item = CheckPointEntry<D>;
419419

0 commit comments

Comments
 (0)