Skip to content

Commit 238d3a8

Browse files
committed
ergotree-interpreter: fix AvlTree.insert semantics for 6.0
1 parent bc70913 commit 238d3a8

File tree

1 file changed

+43
-20
lines changed

1 file changed

+43
-20
lines changed

ergotree-interpreter/src/eval/savltree.rs

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use alloc::string::ToString;
33
use alloc::sync::Arc;
44
use alloc::vec::Vec;
55
use core::convert::TryFrom;
6+
use ergotree_ir::ergo_tree::ErgoTreeVersion;
67

78
use bytes::Bytes;
89
use ergo_avltree_rust::authenticated_tree_ops::AuthenticatedTreeOps;
@@ -201,7 +202,7 @@ pub(crate) static GET_MANY_EVAL_FN: EvalFn =
201202
};
202203

203204
pub(crate) static INSERT_EVAL_FN: EvalFn =
204-
|_mc, _env, _ctx, obj, args| {
205+
|_mc, _env, ctx, obj, args| {
205206
let mut avl_tree_data = obj.try_extract_into::<AvlTreeData>()?;
206207

207208
if !avl_tree_data.tree_flags.insert_allowed() {
@@ -246,21 +247,23 @@ pub(crate) static INSERT_EVAL_FN: EvalFn =
246247
}))
247248
.is_err()
248249
{
249-
return Err(EvalError::AvlTree(format!(
250-
"Incorrect insert for {:?}",
251-
avl_tree_data
252-
)));
250+
if ctx.tree_version() >= ErgoTreeVersion::V3 {
251+
break;
252+
} else {
253+
return Err(EvalError::AvlTree(format!(
254+
"Incorrect insert for {:?}",
255+
avl_tree_data
256+
)));
257+
}
253258
}
254259
}
255-
if let Some(new_digest) = bv.digest() {
260+
Ok(if let Some(new_digest) = bv.digest() {
256261
let digest = ADDigest::scorex_parse_bytes(&new_digest)?;
257262
avl_tree_data.digest = digest;
258-
Ok(Value::Opt(Some(Box::new(Value::AvlTree(
259-
avl_tree_data.into(),
260-
)))))
263+
Value::Opt(Some(Box::new(Value::AvlTree(avl_tree_data.into()))))
261264
} else {
262-
Err(EvalError::AvlTree("Cannot update digest".into()))
263-
}
265+
Value::Opt(None)
266+
})
264267
};
265268

266269
pub(crate) static REMOVE_EVAL_FN: EvalFn =
@@ -621,9 +624,7 @@ mod tests {
621624
),
622625
true,
623626
);
624-
let initial_digest =
625-
ADDigest::scorex_parse_bytes(&prover.digest().unwrap().into_iter().collect::<Vec<_>>())
626-
.unwrap();
627+
let initial_digest = ADDigest::scorex_parse_bytes(&prover.digest().unwrap()).unwrap();
627628
let key1 = Bytes::from(vec![1u8]);
628629
let key2 = Bytes::from(vec![2u8; 1]);
629630
let key3 = Bytes::from(vec![3u8; 1]);
@@ -642,9 +643,7 @@ mod tests {
642643
prover.perform_one_operation(&op1).unwrap();
643644
prover.perform_one_operation(&op2).unwrap();
644645
prover.perform_one_operation(&op3).unwrap();
645-
let final_digest =
646-
ADDigest::scorex_parse_bytes(&prover.digest().unwrap().into_iter().collect::<Vec<_>>())
647-
.unwrap();
646+
let final_digest = ADDigest::scorex_parse_bytes(&prover.digest().unwrap()).unwrap();
648647
let proof: Constant = prover
649648
.generate_proof()
650649
.into_iter()
@@ -670,17 +669,17 @@ mod tests {
670669
SType::SColl(Arc::new(SType::SByte)),
671670
)))),
672671
v: Literal::Coll(CollKind::WrappedColl {
673-
items: Arc::new([pair1, pair2, pair3]),
672+
items: Arc::new([pair1.clone(), pair2.clone(), pair3.clone()]),
674673
elem_tpe: SType::STuple(STuple::pair(
675674
SType::SColl(Arc::new(SType::SByte)),
676675
SType::SColl(Arc::new(SType::SByte)),
677676
)),
678677
}),
679678
};
680679
let expr: Expr = MethodCall::new(
681-
obj,
680+
obj.clone(),
682681
savltree::INSERT_METHOD.clone(),
683-
vec![entries.into(), proof.into()],
682+
vec![entries.clone().into(), proof.clone().into()],
684683
)
685684
.unwrap()
686685
.into();
@@ -695,6 +694,30 @@ mod tests {
695694
} else {
696695
unreachable!();
697696
}
697+
698+
// perform invalid insertion (duplicate entries). Before v6.0 this would return an error. After 6.0 this will return None
699+
let duplicate_entries = Constant {
700+
v: Literal::Coll(CollKind::WrappedColl {
701+
items: Arc::new([pair1, pair2, pair3.clone(), pair3]),
702+
elem_tpe: SType::STuple(STuple::pair(
703+
SType::SColl(Arc::new(SType::SByte)),
704+
SType::SColl(Arc::new(SType::SByte)),
705+
)),
706+
}),
707+
..entries
708+
};
709+
let expr: Expr = MethodCall::new(
710+
obj,
711+
savltree::INSERT_METHOD.clone(),
712+
vec![duplicate_entries.into(), proof.into()],
713+
)
714+
.unwrap()
715+
.into();
716+
assert!(try_eval_out_with_version::<Value<'_>>(&expr, &force_any_val(), 0, 3).is_err());
717+
assert_eq!(
718+
try_eval_out_with_version::<Value<'_>>(&expr, &force_any_val(), 3, 3).unwrap(),
719+
Value::Opt(None)
720+
);
698721
}
699722
proptest! {
700723
#[test]

0 commit comments

Comments
 (0)