Revision 34d6ac8915ee8173e1752d6db140648602c10b3a authored by iguerNL@Functori on 23 January 2023, 09:52:06 UTC, committed by Marge Bot on 23 January 2023, 12:57:17 UTC
1 parent 10318d8
liquidity_baking_per_block_votes.ml
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2022 Nomadic Labs <contact@nomadic-labs.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
(* Testing
-------
Component: Baker / liquidity baking
Invocation: dune exec tezt/tests/main.exe -- --file liquidity_baking_per_block_votes.ml
Subject: Run the baker with various arguments for the [--liquidity-baking-toggle-vote]
and [--votefile] options.
*)
let default_votefile = "per_block_votes.json"
let ensure_removal path p =
Lwt.finalize p @@ fun () ->
if Sys.file_exists path then Sys.remove path ;
unit
let baker_wait_for_vote baker =
Baker.wait_for baker "vote_for_liquidity_baking_toggle.v0" @@ fun json ->
JSON.as_string json |> Baker.liquidity_baking_vote_of_string_opt
let baker_wait_for_per_block_vote_file_error ?expected_id ?expected_file_path
baker =
Baker.wait_for baker "per_block_vote_file_error.v0" @@ fun json ->
let json = JSON.(json |=> 0) in
let id = JSON.(json |-> "id" |> as_string) in
let file_path = JSON.(json |-> "file_path" |> as_string) in
if
Option.fold ~none:true ~some:(String.equal id) expected_id
&& Option.fold ~none:true ~some:(String.equal file_path) expected_file_path
then Some (id, file_path)
else None
let vote_typ = Check.(convert Baker.liquidity_baking_vote_to_string string)
let check_vote ?__LOC__ expected_vote obtained_vote =
Check.(obtained_vote = expected_vote)
vote_typ
?__LOC__
~error_msg:"expected baker to vote %R, but it voted %L"
let check_vote_success ?__LOC__ expected_vote (baker, vote_test_result) =
match vote_test_result with
| Ok obtained_vote ->
check_vote ?__LOC__ expected_vote obtained_vote ;
baker
| Error (error, votefile') ->
Test.fail
?__LOC__
"Did not expect baker to fail reading the vote file '%s', got error: %s"
votefile'
error
let check_vote_error ?__LOC__ expected_error expected_file_path
(baker, vote_test_result) =
match vote_test_result with
| Ok _ ->
Test.fail
?__LOC__
"Did not expect baker to succeed, expected error '%s' with file_path \
'%s'"
expected_error
expected_file_path
| Error (obtained_error, obtained_file_path) ->
Check.(
(obtained_error = expected_error)
string
?__LOC__
~error_msg:"Expected to fail with error %R, got %L") ;
Check.(
(obtained_file_path = obtained_file_path)
string
?__LOC__
~error_msg:"Expected to fail with file path %R, got %L") ;
baker
let test_all_per_block_votes =
(* This test actually supports protocols >= 012. But unfortunately, because
it creates, uses and then deletes a file at a fixed location ([default_votefile]),
it cannot be run in parallel with itself for multiple protocols.
So we only run it on Alpha. *)
Protocol.register_test
~__FILE__
~title:"liquidity baking with per-block votes"
~tags:["liquidity"; "baking"; "votes"]
~supports:
(Protocol.Between_protocols (Protocol.number Alpha, Protocol.number Alpha))
@@ fun protocol ->
let ( >|= ) = Lwt.( >|= ) in
let error_prefix = "client." ^ Protocol.encoding_prefix protocol ^ "." in
if Sys.file_exists default_votefile then
Test.fail
~__LOC__
"this test will recreate and delete the file %s, which is already \
present on your system. This may be the result of a partial run of this \
test, in which case the file can safely be removed."
default_votefile ;
let parameters =
[
(["minimal_block_delay"], `String_of_int 2);
(["delay_increment_per_round"], `String_of_int 1);
]
in
let* parameter_file =
Protocol.write_parameter_file ~base:(Right (protocol, None)) parameters
in
let* node, client =
Client.init_with_protocol
`Client
~protocol
~parameter_file
~timestamp:Now
()
in
(* Note that per default, a baker launched with [run_vote_file] will
not set [--liquidity-baking-toggle-vote pass] as the normal baker
does. *)
let run_vote_file ?votefile ?liquidity_baking_toggle_vote baker =
let* () = Baker.terminate baker in
let delegates =
Array.map (fun Account.{alias; _} -> alias) Account.Bootstrap.keys
|> Array.to_list
in
let baker =
Baker.create
~liquidity_baking_toggle_vote
?votefile
~protocol
~delegates
node
client
in
let p_vote =
let* vote = baker_wait_for_vote baker in
return (baker, Ok vote)
in
let p_error =
let* error = baker_wait_for_per_block_vote_file_error baker in
return (baker, Error error)
in
let* () = Baker.run baker in
let* () = Baker.wait_for_ready baker in
Lwt.pick [p_vote; p_error]
in
let* baker = Baker.init ~protocol node client in
Log.info "Test [off] vote file" ;
let* baker =
let votefile = Baker.liquidity_baking_votefile Off in
run_vote_file ~votefile ~liquidity_baking_toggle_vote:On baker
>|= check_vote_success ~__LOC__ Off
in
Log.info "Test [on] vote file" ;
let* baker =
let votefile = Baker.liquidity_baking_votefile On in
run_vote_file ~votefile ~liquidity_baking_toggle_vote:Off baker
>|= check_vote_success ~__LOC__ On
in
Log.info "Test [pass] vote file" ;
let* baker =
let votefile = Baker.liquidity_baking_votefile Pass in
run_vote_file ~votefile ~liquidity_baking_toggle_vote:On baker
>|= check_vote_success ~__LOC__ Pass
in
Log.info "Test non-existant vote file" ;
let* baker =
let votefile = "nonexistant.json" in
if Sys.file_exists votefile then
Test.fail ~__LOC__ "Did not expect the file %s to exist" votefile ;
run_vote_file baker ~votefile ~liquidity_baking_toggle_vote:Pass
>|= check_vote_error
~__LOC__
(error_prefix ^ "Client_baking_forge.block_vote_file_not_found")
votefile
in
Log.info "Test invalid json in vote file" ;
let* baker =
let votefile = Temp.file "invalid-vote-file.json" in
Base.write_file votefile ~contents:{|{"liquidity_baking_toggle_vote": true|} ;
run_vote_file baker ~votefile ~liquidity_baking_toggle_vote:Pass
>|= check_vote_error
~__LOC__
(error_prefix ^ "Client_baking_forge.block_vote_file_invalid")
votefile
in
Log.info "Test vote file at default file location " ;
let* baker =
ensure_removal default_votefile @@ fun () ->
let _ = Baker.liquidity_baking_votefile ~path:default_votefile On in
run_vote_file baker >|= check_vote_success ~__LOC__ On
in
Log.info "Test caching of the votefile setting" ;
let* _baker =
ensure_removal default_votefile @@ fun () ->
let _ = Baker.liquidity_baking_votefile ~path:default_votefile On in
let* baker = run_vote_file baker >|= check_vote_success ~__LOC__ On in
(* Explicitly remove the votefile to check that the baker has retained its value *)
let p_error =
baker_wait_for_per_block_vote_file_error
~expected_id:
(error_prefix ^ "Client_baking_forge.block_vote_file_not_found")
~expected_file_path:default_votefile
baker
in
Sys.remove default_votefile ;
(* Wait to ensure the removal was detected by the baker *)
let* _ = p_error in
(* Now wait for the next vote event *)
let* vote = baker_wait_for_vote baker in
check_vote ~__LOC__ vote On ;
return baker
in
Log.info "Test [--votefile] overrides default file location " ;
let* baker =
ensure_removal default_votefile @@ fun () ->
let _ = Baker.liquidity_baking_votefile ~path:default_votefile On in
let votefile = Baker.liquidity_baking_votefile Off in
run_vote_file ~votefile baker >|= check_vote_success ~__LOC__ Off
in
(* Tests that using booleans (which was possible until Ithaca) is
not possible anymore, and other invalid contents. *)
let* _ =
Lwt_list.fold_left_s
(fun baker contents ->
Log.info "Test invalid vote file contents: %s" contents ;
let votefile = Temp.file "invalid-vote-file.json" in
Base.write_file votefile ~contents ;
run_vote_file baker ~votefile ~liquidity_baking_toggle_vote:Pass
>|= check_vote_error
(error_prefix
^ "Client_baking_forge.block_vote_file_wrong_content")
votefile)
baker
[
{|{"liquidity_baking_toggle_vote": true}|};
{|{"liquidity_baking_toggle_vote": false}|};
{|{"liquidity_baking_toggle": true}|};
]
in
unit
let register ~protocols = test_all_per_block_votes protocols
Computing file changes ...