@@ -3,6 +3,7 @@ use alloc::string::ToString;
33use alloc:: sync:: Arc ;
44use alloc:: vec:: Vec ;
55use core:: convert:: TryFrom ;
6+ use ergotree_ir:: ergo_tree:: ErgoTreeVersion ;
67
78use bytes:: Bytes ;
89use ergo_avltree_rust:: authenticated_tree_ops:: AuthenticatedTreeOps ;
@@ -201,7 +202,7 @@ pub(crate) static GET_MANY_EVAL_FN: EvalFn =
201202 } ;
202203
203204pub ( 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
266269pub ( 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