From 9781a1c8ff6b669fe481f2cba7cfd80a091251f2 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Wed, 22 Jan 2020 03:01:21 -0800 Subject: [PATCH 1/7] Add rough draft of repeating timelock contract --- src/test/contracts/timelock_repeat.mligo | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/contracts/timelock_repeat.mligo diff --git a/src/test/contracts/timelock_repeat.mligo b/src/test/contracts/timelock_repeat.mligo new file mode 100644 index 000000000..a647a47a9 --- /dev/null +++ b/src/test/contracts/timelock_repeat.mligo @@ -0,0 +1,20 @@ +type storage = { + last_use: timestamp; + interval: int; + execute: unit -> operation list; +} + +let main (p,s: unit * storage) : operation list * storage = + if Current.time > (s.last_use + s.interval) + then + let s: storage = { + last_use = Current.time; + interval = s.interval; + execute = s.execute; + } + in + (s.execute (), s) + else + (* TODO: Add the time until next use to this message *) + (failwith "You have to wait before you can execute this contract again.": + operation list * storage) From d260e831d15e0ccef1193dc6fcc829cdce119b5b Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Wed, 22 Jan 2020 23:05:41 -0800 Subject: [PATCH 2/7] Add failing interval advance test for repeating timelock contract --- src/test/contracts/timelock_repeat.mligo | 8 ++- src/test/test.ml | 1 + src/test/time_lock_repeat_tests.ml | 76 ++++++++++++++++++++++++ src/test/time_lock_tests.ml | 6 +- 4 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 src/test/time_lock_repeat_tests.ml diff --git a/src/test/contracts/timelock_repeat.mligo b/src/test/contracts/timelock_repeat.mligo index a647a47a9..5efff81a9 100644 --- a/src/test/contracts/timelock_repeat.mligo +++ b/src/test/contracts/timelock_repeat.mligo @@ -1,14 +1,16 @@ type storage = { - last_use: timestamp; + next_use: timestamp; interval: int; execute: unit -> operation list; } let main (p,s: unit * storage) : operation list * storage = - if Current.time > (s.last_use + s.interval) + (* Multiple calls to Current.time give different values *) + let now: timestamp = Current.time in + if now > s.next_use then let s: storage = { - last_use = Current.time; + next_use = now + s.interval; interval = s.interval; execute = s.execute; } diff --git a/src/test/test.ml b/src/test/test.ml index b63e1ad5f..f6a638ca5 100644 --- a/src/test/test.ml +++ b/src/test/test.ml @@ -14,5 +14,6 @@ let () = Multisig_v2_tests.main ; Replaceable_id_tests.main ; Time_lock_tests.main ; + Time_lock_repeat_tests.main ; ] ; () diff --git a/src/test/time_lock_repeat_tests.ml b/src/test/time_lock_repeat_tests.ml new file mode 100644 index 000000000..b77714eeb --- /dev/null +++ b/src/test/time_lock_repeat_tests.ml @@ -0,0 +1,76 @@ +open Trace +open Test_helpers +open Ast_simplified + +let type_file f = + let%bind simplified = Ligo.Compile.Of_source.compile f (Syntax_name "cameligo") in + let%bind typed,state = Ligo.Compile.Of_simplified.compile simplified in + ok @@ (typed,state) + +let get_program = + let s = ref None in + fun () -> match !s with + | Some s -> ok s + | None -> ( + let%bind program = type_file "./contracts/timelock_repeat.mligo" in + s := Some program ; + ok program + ) + +let compile_main () = + let%bind simplified = Ligo.Compile.Of_source.compile "./contracts/timelock_repeat.mligo" (Syntax_name "cameligo") in + let%bind typed_prg,_ = Ligo.Compile.Of_simplified.compile simplified in + let%bind mini_c_prg = Ligo.Compile.Of_typed.compile typed_prg in + let%bind michelson_prg = Ligo.Compile.Of_mini_c.aggregate_and_compile_contract mini_c_prg "main" in + let%bind (_contract: Tezos_utils.Michelson.michelson) = + (* fails if the given entry point is not a valid contract *) + Ligo.Compile.Of_michelson.build_contract michelson_prg in + ok () + +let empty_op_list = + (e_typed_list [] t_operation) +let empty_message = e_lambda (Var.of_name "arguments") + (Some t_unit) (Some (t_list t_operation)) + empty_op_list + +let call msg = e_constructor "Call" msg +let mk_time st = + match Memory_proto_alpha.Protocol.Alpha_context.Timestamp.of_notation st with + | Some s -> ok s + | None -> simple_fail "bad timestamp notation" +let to_sec t = Tezos_utils.Time.Protocol.to_seconds t +let storage st interval execute = + e_ez_record [("next_use", e_timestamp (Int64.to_int @@ to_sec st)) ; + ("interval", e_int interval) ; + ("execute", execute)] + +let early_call () = + let%bind program,_ = get_program () in + let%bind predecessor_timestamp = mk_time "2000-01-01T00:10:10Z" in + let%bind lock_time = mk_time "2000-01-01T10:10:10Z" in + let init_storage = storage lock_time 86400 empty_message in + let options = + Proto_alpha_utils.Memory_proto_alpha.make_options ~predecessor_timestamp () in + let exp_failwith = "You have to wait before you can execute this contract again." in + expect_string_failwith ~options program "main" + (e_pair (e_unit ()) init_storage) exp_failwith + +(* Test that when we use the contract the next use time advances by correct interval *) +let interval_advance () = + let%bind program,_ = get_program () in + let%bind predecessor_timestamp = mk_time "2000-01-01T10:10:10Z" in + let%bind lock_time = mk_time "2000-01-01T00:10:10Z" in + let init_storage = storage lock_time 86400 empty_message in + (* It takes a second for Current.now to be called, awful hack *) + let%bind new_timestamp = mk_time "2000-01-02T10:10:11Z" in + let new_storage = storage new_timestamp 86400 empty_message in + let options = + Proto_alpha_utils.Memory_proto_alpha.make_options ~predecessor_timestamp () in + expect_eq ~options program "main" + (e_pair (e_unit ()) init_storage) (e_pair empty_op_list new_storage) + +let main = test_suite "Time Lock Repeating" [ + test "compile" compile_main ; + test "early call" early_call ; + test "interval advance" interval_advance ; + ] diff --git a/src/test/time_lock_tests.ml b/src/test/time_lock_tests.ml index 83830b11f..a3437461a 100644 --- a/src/test/time_lock_tests.ml +++ b/src/test/time_lock_tests.ml @@ -27,14 +27,14 @@ let compile_main () = ok () open Ast_simplified -let empty_op_list = +let empty_op_list = (e_typed_list [] t_operation) let empty_message = e_lambda (Var.of_name "arguments") (Some t_unit) (Some (t_list t_operation)) empty_op_list let call msg = e_constructor "Call" msg -let mk_time st = +let mk_time st = match Memory_proto_alpha.Protocol.Alpha_context.Timestamp.of_notation st with | Some s -> ok s | None -> simple_fail "bad timestamp notation" @@ -66,4 +66,4 @@ let main = test_suite "Time lock" [ test "compile" compile_main ; test "early call" early_call ; test "call on time" call_on_time ; - ] \ No newline at end of file + ] From 0636994ffb0a00a4c499039fe9bb508f402dddc3 Mon Sep 17 00:00:00 2001 From: John David Pressman Date: Thu, 23 Jan 2020 08:32:43 -0800 Subject: [PATCH 3/7] Fix interval advance test for repeating time lock contract --- src/test/time_lock_repeat_tests.ml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/test/time_lock_repeat_tests.ml b/src/test/time_lock_repeat_tests.ml index b77714eeb..cc6fbbf1b 100644 --- a/src/test/time_lock_repeat_tests.ml +++ b/src/test/time_lock_repeat_tests.ml @@ -55,6 +55,8 @@ let early_call () = expect_string_failwith ~options program "main" (e_pair (e_unit ()) init_storage) exp_failwith +let fake_uncompiled_empty_message = e_string "[lambda of type: (lambda unit (list operation)) ]" + (* Test that when we use the contract the next use time advances by correct interval *) let interval_advance () = let%bind program,_ = get_program () in @@ -63,11 +65,11 @@ let interval_advance () = let init_storage = storage lock_time 86400 empty_message in (* It takes a second for Current.now to be called, awful hack *) let%bind new_timestamp = mk_time "2000-01-02T10:10:11Z" in - let new_storage = storage new_timestamp 86400 empty_message in + let new_storage_fake = storage new_timestamp 86400 fake_uncompiled_empty_message in let options = Proto_alpha_utils.Memory_proto_alpha.make_options ~predecessor_timestamp () in expect_eq ~options program "main" - (e_pair (e_unit ()) init_storage) (e_pair empty_op_list new_storage) + (e_pair (e_unit ()) init_storage) (e_pair empty_op_list new_storage_fake) let main = test_suite "Time Lock Repeating" [ test "compile" compile_main ; From 6bcd75e5b6ebef99ef5962fe30db796c253d16ea Mon Sep 17 00:00:00 2001 From: Tom Jack Date: Thu, 23 Jan 2020 10:33:09 -0600 Subject: [PATCH 4/7] CI for "merge_requests" --- .gitlab-ci.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6a41afad7..29b49c950 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -95,6 +95,9 @@ local-dune-job: artifacts: paths: - _coverage_all + only: + - merge_requests + - dev # Run a docker build without publishing to the registry build-current-docker-image: @@ -105,9 +108,8 @@ build-current-docker-image: script: - sh scripts/build_docker_image.sh - sh scripts/test_cli.sh - except: - - master - - dev + only: + - merge_requests # When a MR/PR is merged to dev # take the previous build and publish it to Docker Hub @@ -135,6 +137,8 @@ build-and-package-debian-9: target_os: "debian" target_os_version: "9" <<: *build_binary + only: + - dev build-and-package-debian-10: <<: *docker @@ -145,6 +149,12 @@ build-and-package-debian-10: target_os: "debian" target_os_version: "10" <<: *build_binary + # this one is merge_requests and dev, because the debian 10 binary + # is used for build-current-docker-image and for + # build-and-publish-latest-docker-image + only: + - merge_requests + - dev build-and-package-ubuntu-18-04: <<: *docker @@ -155,6 +165,8 @@ build-and-package-ubuntu-18-04: target_os: "ubuntu" target_os_version: "18.04" <<: *build_binary + only: + - dev build-and-package-ubuntu-19-04: <<: *docker @@ -165,11 +177,12 @@ build-and-package-ubuntu-19-04: target_os: "ubuntu" target_os_version: "19.04" <<: *build_binary + only: + - dev -# Pages are deployed from both master & dev, be careful not to override 'next' +# Pages are deployed from dev, be careful not to override 'next' # in case something gets merged into 'dev' while releasing. pages: <<: *website_build only: - - master - dev From 6f4c147a31210b21d4124bc1a61e9e3334c9638d Mon Sep 17 00:00:00 2001 From: Tom Jack Date: Thu, 23 Jan 2020 11:47:24 -0600 Subject: [PATCH 5/7] Don't merge to master --- .gitlab-ci.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 29b49c950..be47c3829 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,6 +11,14 @@ stages: - build_and_deploy_docker - build_and_deploy_website +# TODO provide sensible CI for master +dont-merge-to-master: + stage: test + script: + - "false" + only: + - master + .build_binary: &build_binary # To run in sequence and save CPU usage, use stage: build_and_package_binaries stage: test From fd47f5103150346b4501873e2b89ba5ad8fcced8 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Fri, 20 Dec 2019 15:52:49 +0100 Subject: [PATCH 6/7] add a new CLI command: list-declarations --- src/bin/cli.ml | 16 +++++++++++++++- src/bin/expect_tests/help_tests.ml | 6 ++++++ src/main/compile/of_simplified.ml | 12 +++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/bin/cli.ml b/src/bin/cli.ml index 42cecfd4f..24cc13f77 100644 --- a/src/bin/cli.ml +++ b/src/bin/cli.ml @@ -410,6 +410,19 @@ let dump_changelog = let doc = "Dump the LIGO changelog to stdout." in (Term.ret term , Term.info ~doc cmdname) +let list_declarations = + let f source_file syntax = + toplevel ~display_format:(`Human_readable) @@ + let%bind simplified_prg = Compile.Of_source.compile source_file (Syntax_name syntax) in + let json_decl = List.map (fun decl -> `String decl) @@ Compile.Of_simplified.list_declarations simplified_prg in + ok @@ J.to_string @@ `Assoc [ ("source_file", `String source_file) ; ("declarations", `List json_decl) ] + in + let term = + Term.(const f $ source_file 0 $ syntax ) in + let cmdname = "list-declarations" in + let doc = "Subcommand: list all the top-level decalarations." in + (Term.ret term , Term.info ~doc cmdname) + let run ?argv () = Term.eval_choice ?argv main [ compile_file ; @@ -425,5 +438,6 @@ let run ?argv () = print_cst ; print_ast ; print_typed_ast ; - print_mini_c + print_mini_c ; + list_declarations ; ] diff --git a/src/bin/expect_tests/help_tests.ml b/src/bin/expect_tests/help_tests.ml index b385abd14..716837074 100644 --- a/src/bin/expect_tests/help_tests.ml +++ b/src/bin/expect_tests/help_tests.ml @@ -44,6 +44,9 @@ let%expect_test _ = Subcommand: interpret the expression in the context initialized by the provided source file. + list-declarations + Subcommand: list all the top-level decalarations. + measure-contract Subcommand: measure a contract's compiled size in bytes. @@ -117,6 +120,9 @@ let%expect_test _ = Subcommand: interpret the expression in the context initialized by the provided source file. + list-declarations + Subcommand: list all the top-level decalarations. + measure-contract Subcommand: measure a contract's compiled size in bytes. diff --git a/src/main/compile/of_simplified.ml b/src/main/compile/of_simplified.ml index 072243a9c..243ecd586 100644 --- a/src/main/compile/of_simplified.ml +++ b/src/main/compile/of_simplified.ml @@ -20,4 +20,14 @@ let apply (entry_point : string) (param : Ast_simplified.expression) : Ast_simpl ok applied let pretty_print formatter (program : Ast_simplified.program) = - Ast_simplified.PP.program formatter program \ No newline at end of file + Ast_simplified.PP.program formatter program + +let list_declarations (program : Ast_simplified.program) : string list = + List.fold_left + (fun prev el -> + let open Location in + let open Ast_simplified in + match el.wrap_content with + | Declaration_constant (var,_,_,_) -> (Var.to_name var)::prev + | _ -> prev) + [] program From ba0548d6b8dcc05ee4324c1925de84ea4f84d5c6 Mon Sep 17 00:00:00 2001 From: Lesenechal Remi Date: Thu, 23 Jan 2020 21:32:24 +0100 Subject: [PATCH 7/7] some list-declarations tests --- src/bin/expect_tests/eval_value_tests.ml | 10 ---------- src/bin/expect_tests/misc_cli_commands.ml | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 10 deletions(-) delete mode 100644 src/bin/expect_tests/eval_value_tests.ml create mode 100644 src/bin/expect_tests/misc_cli_commands.ml diff --git a/src/bin/expect_tests/eval_value_tests.ml b/src/bin/expect_tests/eval_value_tests.ml deleted file mode 100644 index ef4ccd1bd..000000000 --- a/src/bin/expect_tests/eval_value_tests.ml +++ /dev/null @@ -1,10 +0,0 @@ -open Cli_expect - -let%expect_test _ = - run_ligo_good [ "evaluate-value" ; "../../test/contracts/evaluation_tests.ligo" ; "a" ] ; - [%expect {| - {foo = +0 , bar = "bar"} |} ]; - - run_ligo_good [ "evaluate-value" ; "../../test/contracts/evaluation_tests.ligo" ; "b" ] ; - [%expect {| - 2 |} ] \ No newline at end of file diff --git a/src/bin/expect_tests/misc_cli_commands.ml b/src/bin/expect_tests/misc_cli_commands.ml new file mode 100644 index 000000000..b18de4873 --- /dev/null +++ b/src/bin/expect_tests/misc_cli_commands.ml @@ -0,0 +1,22 @@ +open Cli_expect + +(* evaluate-value *) +let%expect_test _ = + run_ligo_good [ "evaluate-value" ; "../../test/contracts/evaluation_tests.ligo" ; "a" ] ; + [%expect {| + {foo = +0 , bar = "bar"} |} ]; + + run_ligo_good [ "evaluate-value" ; "../../test/contracts/evaluation_tests.ligo" ; "b" ] ; + [%expect {| + 2 |} ] + +(* list-declarations *) +let%expect_test _ = + run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.ligo" ] ; + [%expect {| {"source_file":"../../test/contracts/loop.ligo","declarations":["inner_capture_in_conditional_block","dummy","nested_for_collection_local_var","nested_for_collection","for_collection_map_k","for_collection_map_kv","for_collection_empty","for_collection_with_patches","for_collection_comp_with_acc","for_collection_proc_call","for_collection_rhs_capture","for_collection_if_and_local_var","for_collection_set","for_collection_list","for_sum","while_sum","counter"]} |} ]; + + run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.mligo" ] ; + [%expect {| {"source_file":"../../test/contracts/loop.mligo","declarations":["counter_nest","aux_nest","counter","counter_simple","aux_simple"]} |} ]; + + run_ligo_good [ "list-declarations" ; "../../test/contracts/loop.religo" ] ; + [%expect {| {"source_file":"../../test/contracts/loop.religo","declarations":["counter_nest","aux_nest","counter","counter_simple","aux_simple"]} |} ]; \ No newline at end of file