diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index b2980ef2b516f23634fe5fddfc26ab0c274ff5bf..529363514f9754be3c333a833eb127de23afd6a9 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -187,9 +187,14 @@ Data Availability Layer (ongoing) Distribution of rollup operations data off-chain. (MRs :gl:`!5711`, :gl:`!5938`, :gl:`!6024`, :gl:`!5959`) + Breaking Changes ---------------- +- Deprecate timelock functionality, that is the `CHEST_OPEN` + instruction, in michelson to prevent origination of new contracts using. A + safer version of timelock will come in a future procotol. (MR :gl: `!6260`) + - Rename the parameter ``tokens_per_roll`` to ``minimal_stake``. (MR :gl:`!5897`) RPC Changes diff --git a/src/proto_alpha/lib_protocol/script_ir_translator.ml b/src/proto_alpha/lib_protocol/script_ir_translator.ml index efbfb5dc17dc1407fe21113bd1850645ff03654e..42db9ea6c7a40edfc613d05cc5fd1196d5d896a2 100644 --- a/src/proto_alpha/lib_protocol/script_ir_translator.ml +++ b/src/proto_alpha/lib_protocol/script_ir_translator.ml @@ -4201,8 +4201,10 @@ and parse_instr : (* Timelocks *) | ( Prim (loc, I_OPEN_CHEST, [], _), Item_t (Chest_key_t, Item_t (Chest_t, Item_t (Nat_t, rest))) ) -> - let instr = {apply = (fun k -> IOpen_chest (loc, k))} in - typed ctxt loc instr (Item_t (union_bytes_bool_t, rest)) + if legacy then + let instr = {apply = (fun k -> IOpen_chest (loc, k))} in + typed ctxt loc instr (Item_t (union_bytes_bool_t, rest)) + else fail (Deprecated_instruction I_OPEN_CHEST) (* Events *) | Prim (loc, I_EMIT, [], annot), Item_t (data, rest) -> check_packable ~legacy loc data >>?= fun () -> diff --git a/src/proto_alpha/lib_protocol/test/helpers/contract_helpers.ml b/src/proto_alpha/lib_protocol/test/helpers/contract_helpers.ml index ec4d76ef14250674f6e1508eb787a40ac6a67247..f7d8dd45bc64f8b0fd4108a00d246d70608ab2bf 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/contract_helpers.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/contract_helpers.ml @@ -38,10 +38,8 @@ let init () = (** Return contents of a given file as string. *) let read_file f = - let ic = open_in f in - let res = really_input_string ic (in_channel_length ic) in - close_in ic ; - res + In_channel.with_open_text f (fun ic -> + really_input_string ic (in_channel_length ic)) (** Loads a script from file. *) let load_script ~storage file = diff --git a/src/proto_alpha/lib_protocol/test/integration/michelson/test_timelock.ml b/src/proto_alpha/lib_protocol/test/integration/michelson/test_timelock.ml index 76f0b047940a6d3112e83171344d8ae013adbed5..4f0ac0df7bca47364af7a62193fd5791d6792a45 100644 --- a/src/proto_alpha/lib_protocol/test/integration/michelson/test_timelock.ml +++ b/src/proto_alpha/lib_protocol/test/integration/michelson/test_timelock.ml @@ -32,6 +32,7 @@ *) open Protocol +open Lwt_result_syntax let wrap e = Lwt.return (Environment.wrap_tzresult e) @@ -54,29 +55,44 @@ let simple_test () = assert (result = expected_result) ; return_unit +let deprecated_chest_open () = + (* Verify contract fails origination as OPEN_CHEST is marked as legacy (deprecated )*) + let* block, baker, source_contract, _src2 = Contract_helpers.init () in + let storage = "0xdeadbeef" in + let script = Contract_helpers.read_file "./contracts/timelock.tz" in + Contract_helpers.originate_contract_from_string_hash + ~script + ~storage + ~source_contract + ~baker + block + >>= function + | Ok _ -> Alcotest.fail "script originated successfully, expected an error" + | Error lst + when List.mem + ~equal:( = ) + (Environment.Ecoproto_error + (Script_tc_errors.Deprecated_instruction I_OPEN_CHEST)) + lst -> + return () + | Error errs -> + Alcotest.failf "Unexpected error: %a" Error_monad.pp_print_trace errs + +(* Test to verify open_chest correctness + DISABLED as open_chest is deprecated, but is expected to return. +*) let contract_test () = - (* Parse a Michelson contract from string. *) - let originate_contract file storage src b = - let load_file f = - let ic = open_in f in - let res = really_input_string ic (in_channel_length ic) in - close_in ic ; - res - in - let contract_string = load_file file in - let code = Expr.toplevel_from_string contract_string in - let storage = Expr.from_string storage in - let script = - Alpha_context.Script.{code = lazy_expr code; storage = lazy_expr storage} - in - Op.contract_origination (B b) src ~fee:(Test_tez.of_int 10) ~script - >>=? fun (operation, dst) -> - Incremental.begin_construction b >>=? fun incr -> - Incremental.add_operation incr operation >>=? fun incr -> - Incremental.finalize_block incr >|=? fun b -> (dst, b) + let* block, baker, source_contract, _src2 = Contract_helpers.init () in + let storage = "0xdeadbeef" in + let script = Contract_helpers.read_file "./contracts/timelock.tz" in + let* dst, _script, block = + Contract_helpers.originate_contract_from_string + ~script + ~storage + ~source_contract + ~baker + block in - Context.init3 ~consensus_threshold:0 () >>=? fun (b, (src, _c2, _c3)) -> - originate_contract "contracts/timelock.tz" "0xaa" src b >>=? fun (dst, b) -> let public, secret = Timelock.gen_rsa_keys () in let locked_value = Timelock.gen_locked_value public in let time = 1000 in @@ -109,9 +125,15 @@ let contract_test () = Alpha_context.Script.(lazy_expr (Expr.from_string michelson_string)) in let fee = Test_tez.of_int 10 in - Op.transaction ~fee (B b) src dst (Test_tez.of_int 3) ~parameters + Op.transaction + ~fee + (B block) + source_contract + dst + (Test_tez.of_int 3) + ~parameters >>=? fun operation -> - Incremental.begin_construction b >>=? fun incr -> + Incremental.begin_construction block >>=? fun incr -> Incremental.add_operation incr operation >>=? fun incr -> Incremental.finalize_block incr >>=? fun block -> Incremental.begin_construction block >>=? fun incr -> @@ -160,8 +182,29 @@ let contract_test () = check_storage chest_correct chest_key_incorrect "01" >>=? fun () -> return_unit +(** + Expect fail wrapper for tests that you expect to return Error or throw an exception. + Useful to keep tests enabled even if they fail, but still run them. + @param test_f test function that is expected to fail. + *) +let expect_fail_result_lwt test_f () = + let open Lwt_syntax in + try + let* res = test_f () in + match res with + | Ok _ -> Alcotest.fail "Expect failure" + | Error _ -> return_ok_unit + with _ -> return_ok_unit + let tests = [ Tztest.tztest "simple test" `Quick simple_test; - Tztest.tztest "contract test" `Quick contract_test; + Tztest.tztest + "verify chest_open fails origination" + `Quick + deprecated_chest_open; + Tztest.tztest + "contract test with chest_open (OK when it fails)" + `Quick + (expect_fail_result_lwt contract_test); ]