From a428d3e0c3d02ac8c9834c401663a1b1555114dc Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Thu, 5 May 2022 23:56:08 +0100 Subject: [PATCH 1/2] Proto: Scoru: RPC to fetch last cemented commitment hash and level --- src/proto_alpha/lib_plugin/plugin.ml | 37 ++++++++++++++ .../lib_protocol/alpha_context.mli | 3 ++ .../lib_protocol/sc_rollup_storage.ml | 12 +++++ .../lib_protocol/sc_rollup_storage.mli | 15 ++++++ .../test/unit/test_sc_rollup_storage.ml | 49 +++++++++++++++++++ 5 files changed, 116 insertions(+) diff --git a/src/proto_alpha/lib_plugin/plugin.ml b/src/proto_alpha/lib_plugin/plugin.ml index 8158f8e9ea73..5307a664c059 100644 --- a/src/proto_alpha/lib_plugin/plugin.ml +++ b/src/proto_alpha/lib_plugin/plugin.ml @@ -3183,6 +3183,20 @@ module RPC = struct ~output:Raw_level.encoding RPC_path.(path /: Sc_rollup.Address.rpc_arg / "initial_level") + let last_cemented_commitment_hash_with_level = + RPC_service.get_service + ~description: + "Level and hash of the last cemented commitment for a \ + smart-contract rollup" + ~query:RPC_query.empty + ~output: + (obj2 + (req "hash" Sc_rollup.Commitment_hash.encoding) + (req "level" Raw_level.encoding)) + RPC_path.( + path /: Sc_rollup.Address.rpc_arg + / "last_cemented_commitment_hash_with_level") + let root = RPC_service.get_service ~description:"List of all originated smart contract rollups" @@ -3217,6 +3231,19 @@ module RPC = struct @@ fun ctxt address () () -> Alpha_context.Sc_rollup.get_boot_sector ctxt address + let register_last_cemented_commitment_hash_with_level () = + Registration.register1 + ~chunked:false + S.last_cemented_commitment_hash_with_level + @@ fun ctxt address () () -> + let open Lwt_tzresult_syntax in + let+ (last_cemented_commitment, level, _ctxt) = + Alpha_context.Sc_rollup.last_cemented_commitment_hash_with_level + ctxt + address + in + (last_cemented_commitment, level) + let register_root () = Registration.register0 ~chunked:true S.root (fun context () () -> Sc_rollup.list context) @@ -3226,6 +3253,7 @@ module RPC = struct register_inbox () ; register_initial_level () ; register_boot_sector () ; + register_last_cemented_commitment_hash_with_level () ; register_root () let list ctxt block = RPC_context.make_call0 S.root ctxt block () () @@ -3233,6 +3261,15 @@ module RPC = struct let initial_level ctxt block sc_rollup_address = RPC_context.make_call1 S.initial_level ctxt block sc_rollup_address () () + let last_cemented_commitment_hash_with_level ctxt block sc_rollup_address = + RPC_context.make_call1 + S.last_cemented_commitment_hash_with_level + ctxt + block + sc_rollup_address + () + () + let boot_sector ctxt block sc_rollup_address = RPC_context.make_call1 S.boot_sector ctxt block sc_rollup_address () () end diff --git a/src/proto_alpha/lib_protocol/alpha_context.mli b/src/proto_alpha/lib_protocol/alpha_context.mli index 0ed90a5b8a0e..70c9b9413d09 100644 --- a/src/proto_alpha/lib_protocol/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/alpha_context.mli @@ -2637,6 +2637,9 @@ module Sc_rollup : sig val get_boot_sector : context -> t -> string tzresult Lwt.t + val last_cemented_commitment_hash_with_level : + context -> t -> (Commitment_hash.t * Raw_level.t * context) tzresult Lwt.t + module Internal_for_tests : sig val originated_sc_rollup : Origination_nonce.Internal_for_tests.t -> t end diff --git a/src/proto_alpha/lib_protocol/sc_rollup_storage.ml b/src/proto_alpha/lib_protocol/sc_rollup_storage.ml index 80d247b1000d..84b3c0efb102 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_storage.ml +++ b/src/proto_alpha/lib_protocol/sc_rollup_storage.ml @@ -775,3 +775,15 @@ let get_boot_sector ctxt rollup = match boot_sector with | None -> fail (Sc_rollup_does_not_exist rollup) | Some boot_sector -> return boot_sector + +let last_cemented_commitment_hash_with_level ctxt rollup = + let open Lwt_tzresult_syntax in + let* (commitment_hash, ctxt) = last_cemented_commitment ctxt rollup in + if Commitment_hash.(commitment_hash = zero) then + let+ initial_level = Storage.Sc_rollup.Initial_level.get ctxt rollup in + (commitment_hash, initial_level, ctxt) + else + let+ ({inbox_level; _}, ctxt) = + get_commitment_internal ctxt rollup commitment_hash + in + (commitment_hash, inbox_level, ctxt) diff --git a/src/proto_alpha/lib_protocol/sc_rollup_storage.mli b/src/proto_alpha/lib_protocol/sc_rollup_storage.mli index 2cbc5653873b..a2a8697e9754 100644 --- a/src/proto_alpha/lib_protocol/sc_rollup_storage.mli +++ b/src/proto_alpha/lib_protocol/sc_rollup_storage.mli @@ -416,3 +416,18 @@ val initial_level : (** [get_boot_sector ctxt sc_rollup] retrieves the boot sector for [sc_rollup]. *) val get_boot_sector : Raw_context.t -> Sc_rollup_repr.t -> string tzresult Lwt.t + +(* [last_cemented_commitment_hash_with_level ctxt sc_rollup] returns the hash + and level of the last cemented commitment (lcc) for [sc_rollup]. If the + rollup exists but no lcc exists, the initial commitment + `Sc_rollup.Commitment.zero` together with the rollup origination level is + returned. + + May fail with: + {ul + {li [Sc_rollup_does_not_exist] if [rollup] does not exist}} *) +val last_cemented_commitment_hash_with_level : + Raw_context.t -> + Sc_rollup_repr.t -> + (Sc_rollup_repr.Commitment_hash.t * Raw_level_repr.t * Raw_context.t) tzresult + Lwt.t diff --git a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml index 7b689e88cadc..d93dbec4a82e 100644 --- a/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml +++ b/src/proto_alpha/lib_protocol/test/unit/test_sc_rollup_storage.ml @@ -630,6 +630,42 @@ let test_cement_deadline_uses_oldest_add_time () = let* ctxt = lift @@ Sc_rollup_storage.cement_commitment ctxt rollup c1 in assert_commitment_hash_equal ~loc:__LOC__ ctxt c1 c2 +let test_last_cemented_commitment_hash_with_level () = + let* ctxt = new_context () in + let challenge_window = + Constants_storage.sc_rollup_challenge_window_in_blocks ctxt + in + let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in + let staker = + Sc_rollup_repr.Staker.of_b58check_exn "tz1SdKt9kjPp1HRQFkBmXtBhgMfvdgFhSjmG" + in + let inbox_level = Raw_level_repr.of_int32_exn 21l in + let* ctxt = lift @@ Sc_rollup_storage.deposit_stake ctxt rollup staker in + let commitment = + Sc_rollup_repr.Commitment. + { + predecessor = Sc_rollup_repr.Commitment_hash.zero; + inbox_level; + number_of_messages = number_of_messages_exn 3l; + number_of_ticks = number_of_ticks_exn 1232909l; + compressed_state = Sc_rollup_repr.State_hash.zero; + } + in + let* (c1, ctxt) = + lift @@ Sc_rollup_storage.refine_stake ctxt rollup staker commitment + in + let ctxt = Raw_context.Internal_for_tests.add_level ctxt challenge_window in + let* ctxt = lift @@ Sc_rollup_storage.cement_commitment ctxt rollup c1 in + let* (c1', inbox_level', ctxt) = + lift + @@ Sc_rollup_storage.last_cemented_commitment_hash_with_level ctxt rollup + in + let* () = assert_commitment_hash_equal ~loc:__LOC__ ctxt c1 c1' in + Assert.equal_int32 + ~loc:__LOC__ + (Raw_level_repr.to_int32 inbox_level) + (Raw_level_repr.to_int32 inbox_level') + let test_withdrawal_fails_when_not_staked_on_lcc () = let* ctxt = new_context () in let* (rollup, ctxt) = lift @@ new_sc_rollup ctxt in @@ -1336,6 +1372,11 @@ let test_last_cemented_commitment_of_missing_rollup () = ~loc:__LOC__ Sc_rollup_storage.last_cemented_commitment +let test_last_cemented_commitment_hash_with_level_of_missing_rollup () = + assert_fails_with_missing_rollup + ~loc:__LOC__ + Sc_rollup_storage.last_cemented_commitment_hash_with_level + let test_cement_commitment_of_missing_rollup () = assert_fails_with_missing_rollup ~loc:__LOC__ (fun ctxt rollup -> Sc_rollup_storage.cement_commitment @@ -1604,6 +1645,10 @@ let tests = "cement deadline uses oldest add time" `Quick test_cement_deadline_uses_oldest_add_time; + Tztest.tztest + "last cemented commitment hash and level returns correct information" + `Quick + test_last_cemented_commitment_hash_with_level; Tztest.tztest "cement with two stakers" `Quick test_cement_with_two_stakers; Tztest.tztest "no cement on conflict" `Quick test_no_cement_on_conflict; Tztest.tztest @@ -1678,6 +1723,10 @@ let tests = "fetching last final commitment of missing rollup fails" `Quick test_last_cemented_commitment_of_missing_rollup; + Tztest.tztest + "fetching last final commitment hash and level of missing rollup fails" + `Quick + test_last_cemented_commitment_hash_with_level_of_missing_rollup; Tztest.tztest "Finalizing commitment of missing rollup fails" `Quick -- GitLab From b1e2e211e9a1b8a109b714804712254ababbb8c8 Mon Sep 17 00:00:00 2001 From: Andrea Cerone Date: Thu, 5 May 2022 23:58:17 +0100 Subject: [PATCH 2/2] Tezt: test RPC to fetch last cemented commitment hash and level --- .../sc_rollup_get_lcc_hash_with_level.out | 31 +++++++++++ tezt/lib_tezos/RPC.ml | 8 +++ tezt/lib_tezos/RPC.mli | 10 ++++ tezt/tests/sc_rollup.ml | 55 +++++++++++++++++++ 4 files changed, 104 insertions(+) create mode 100644 tezt/_regressions/sc_rollup_get_lcc_hash_with_level.out diff --git a/tezt/_regressions/sc_rollup_get_lcc_hash_with_level.out b/tezt/_regressions/sc_rollup_get_lcc_hash_with_level.out new file mode 100644 index 000000000000..cb3bbc356dcf --- /dev/null +++ b/tezt/_regressions/sc_rollup_get_lcc_hash_with_level.out @@ -0,0 +1,31 @@ +sc_rollup_get_lcc_hash_with_level.out + +./tezos-client --wait none originate sc rollup from '[PUBLIC_KEY_HASH]' of kind arith booting with --burn-cap 9999999 +Node is bootstrapped. +Estimated gas: 1600.648 units (will add 100 for safety) +Estimated storage: 6522 bytes added (will add 20 for safety) +Operation successfully injected in the node. +Operation hash is '[OPERATION_HASH]' +NOT waiting for the operation to be included. +Use command + tezos-client wait for [OPERATION_HASH] to be included --confirmations 1 --branch [BLOCK_HASH] +and/or an external block explorer to make sure that it has been included. +This sequence of operations was run: + Manager signed operations: + From: [PUBLIC_KEY_HASH] + Fee to the baker: ꜩ0.000402 + Expected counter: 1 + Gas limit: 1701 + Storage limit: 6542 bytes + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ0.000402 + payload fees(the block proposer) ....... +ꜩ0.000402 + Originate smart contract rollup of kind arith with boot sector '' + This smart contract rollup origination was successfully applied + Consumed gas: 1600.648 + Storage size: 6522 bytes + Address: [SC_ROLLUP_HASH] + Balance updates: + [PUBLIC_KEY_HASH] ... -ꜩ1.6305 + storage fees ........................... +ꜩ1.6305 + diff --git a/tezt/lib_tezos/RPC.ml b/tezt/lib_tezos/RPC.ml index 8652dbb58404..32a903bc770e 100644 --- a/tezt/lib_tezos/RPC.ml +++ b/tezt/lib_tezos/RPC.ml @@ -764,6 +764,14 @@ module Sc_rollup = struct ~sc_rollup_address client = let path = path ~chain ~block ~sc_rollup_address @ ["boot_sector"] in Client.rpc ?endpoint ?hooks GET path client + + let get_last_cemented_commitment_hash_with_level ?endpoint ?hooks + ?(chain = "main") ?(block = "head") ~sc_rollup_address client = + let path = + path ~chain ~block ~sc_rollup_address + @ ["last_cemented_commitment_hash_with_level"] + in + Client.rpc ?endpoint ?hooks GET path client end let raw_bytes ?endpoint ?hooks ?(chain = "main") ?(block = "head") ?(path = []) diff --git a/tezt/lib_tezos/RPC.mli b/tezt/lib_tezos/RPC.mli index 43e6bb2841c8..5e49167be803 100644 --- a/tezt/lib_tezos/RPC.mli +++ b/tezt/lib_tezos/RPC.mli @@ -1047,6 +1047,16 @@ module Sc_rollup : sig sc_rollup_address:string -> Client.t -> JSON.t Lwt.t + + (** Call RPC /chain/[chain]/blocks/[block]/context/sc_rollup/[rollup_hash]/lcc_hash_with_level *) + val get_last_cemented_commitment_hash_with_level : + ?endpoint:Client.endpoint -> + ?hooks:Process.hooks -> + ?chain:string -> + ?block:string -> + sc_rollup_address:string -> + Client.t -> + JSON.t Lwt.t end val raw_bytes : diff --git a/tezt/tests/sc_rollup.ml b/tezt/tests/sc_rollup.ml index 1fafe18e459c..7d7eed4194aa 100644 --- a/tezt/tests/sc_rollup.ml +++ b/tezt/tests/sc_rollup.ml @@ -127,6 +127,11 @@ let number_of_messages (commitment : Sc_rollup_client.commitment) = let number_of_ticks (commitment : Sc_rollup_client.commitment) = commitment.number_of_ticks +let last_cemented_commitment_hash_with_level json = + let hash = JSON.(json |-> "hash" |> as_string) in + let level = JSON.(json |-> "level" |> as_int) in + (hash, level) + (* Tests @@ -325,6 +330,55 @@ let test_rollup_get_initial_level = client bootstrap) +(* Fetching the last cemented commitment info for a sc rollup + ---------------------------------------------------------- + + We can fetch the hash and level of the last cemented commitment. Initially, + this corresponds to `(Sc_rollup.Commitment_hash.zero, origination_level)`. +*) + +(* TODO: https://gitlab.com/tezos/tezos/-/issues/2944 + Revisit this test once the rollup node can cement commitments. *) +let test_rollup_get_last_cemented_commitment_hash_with_level = + let output_file _ = "sc_rollup_get_lcc_hash_with_level" in + test + ~__FILE__ + ~output_file + ~tags:["lcc_hash_with_level"] + "get last cemented commitment hash and inbox level of a sc rollup" + (fun protocol -> + setup ~protocol @@ fun node client bootstrap -> + ( with_fresh_rollup @@ fun sc_rollup_address _sc_rollup_node _filename -> + let* origination_level = RPC.get_current_level client in + + (* Bake 10 blocks to be sure that the origination_level of rollup is different + from the level of the head node. *) + let* () = repeat 10 (fun () -> Client.bake_for_and_wait client) in + let* lcc_info_json = + RPC.Sc_rollup.get_last_cemented_commitment_hash_with_level + ~sc_rollup_address + client + in + let (hash, level) = + last_cemented_commitment_hash_with_level lcc_info_json + in + (* The hardcoded value of `Sc_rollup.Commitment.zero` is + "scc12XhSULdV8bAav21e99VYLTpqAjTd7NU8Mn4zFdKPSA8auMbggG". *) + Check.( + (hash = "scc12XhSULdV8bAav21e99VYLTpqAjTd7NU8Mn4zFdKPSA8auMbggG") + string + ~error_msg:"expected value %L, got %R") ; + (* The level of the last cemented commitment should correspond to the + rollup origination level. *) + Check.( + (level = JSON.(origination_level |-> "level" |> as_int)) + int + ~error_msg:"expected value %L, got %R") ; + return () ) + node + client + bootstrap) + (* Pushing message in the inbox ---------------------------- @@ -1384,6 +1438,7 @@ let register ~protocols = test_rollup_client_gets_address protocols ; test_rollup_list protocols ; test_rollup_get_initial_level protocols ; + test_rollup_get_last_cemented_commitment_hash_with_level protocols ; test_rollup_inbox_size protocols ; test_rollup_inbox_current_messages_hash protocols ; test_rollup_inbox_of_rollup_node "basic" basic_scenario protocols ; -- GitLab