ligo/src/proto_alpha/lib_baking/test/proto_alpha_helpers.ml

619 lines
20 KiB
OCaml
Raw Normal View History

(**************************************************************************)
(* *)
2018-02-05 21:17:03 +01:00
(* Copyright (c) 2014 - 2018. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
open Proto_alpha
open Alpha_context
let (//) = Filename.concat
let () = Random.self_init ()
let rpc_config = ref {
RPC_client.host = "localhost" ;
port = 8192 + Random.int 8192 ;
tls = false ;
logger = RPC_client.null_logger ;
}
2018-02-11 19:17:40 +01:00
let build_rpc_context config =
new Proto_alpha.wrap_proto_context @@
2018-02-11 19:17:40 +01:00
new RPC_client.http_ctxt config Media_type.all_media_types
let rpc_ctxt = ref (build_rpc_context !rpc_config)
2017-11-07 17:38:11 +01:00
(* Context that does not write to alias files *)
let no_write_context ?(block = `Head 0) config : #Client_context.full = object
inherit RPC_client.http_ctxt config Media_type.all_media_types
inherit Client_context.simple_printer (fun _ _ -> Lwt.return_unit)
2017-11-07 17:38:11 +01:00
method load : type a. string -> default:a -> a Data_encoding.encoding -> a Error_monad.tzresult Lwt.t =
fun _ ~default _ -> return default
method write : type a. string ->
a ->
a Data_encoding.encoding -> unit Error_monad.tzresult Lwt.t =
fun _ _ _ -> return ()
method block = block
method prompt : type a. (a, string) Client_context.lwt_format -> a =
Format.kasprintf (fun _ -> Lwt.return "")
method prompt_password : type a. (a, string) Client_context.lwt_format -> a =
Format.kasprintf (fun _ -> Lwt.return "")
2017-11-07 17:38:11 +01:00
end
let sandbox_parameters =
let json_result =
Data_encoding.Json.from_string {json|
{ "genesis_pubkey": "edpkuSLWfVU1Vq7Jg9FucPyKmma6otcMHac9zG4oU1KMHSTBpJuGQ2" }
|json} in
match json_result with
| Error err -> raise (Failure err)
| Ok json -> json
let protocol_parameters =
let json_result =
Data_encoding.Json.from_string {json|
{ "bootstrap_accounts": [
[ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav", "4000000000000" ],
[ "edpktzNbDAUjUk697W7gYg2CRuBQjyPxbEg8dLccYYwKSKvkPvjtV9", "4000000000000" ],
[ "edpkuTXkJDGcFd5nh6VvMz8phXxU3Bi7h6hqgywNFi1vZTfQNnS1RV", "4000000000000" ],
[ "edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU", "4000000000000" ],
[ "edpkv8EUUH68jmo3f7Um5PezmfGrRF24gnfLpH3sVNwJnV5bVCxL2n", "4000000000000" ]
],
"commitments": [
[ "tz1MawerETND6bqJqUe4cVBcDZn6Tiahrr2V", "btz1bRL4X5BWo2Fj4EsBdUwexXqgTf75uf1qa", "23932454669343" ],
[ "tz1X4maqF9tC1Yn4hzg1w5PLdeKm62qHS64V", "btz1SxjV1syBgftgKy721czKi3arVkVwYUFSv", "72954577464032" ],
[ "tz1SWBY7rWMutEuWRziDhC72gTGdo29KZaRj", "btz1LtoNCjiW23txBTenALaf5H6NKF1L3c1gw", "217487035428348" ],
[ "tz1amUjiZaevaxQy5w26LSf64bs77eNTJ8uY", "btz1SUd3mMhEBcWudrn8u361MVAec4WYCcFoy", "4092742372031" ],
[ "tz1Zaee3QBtD4ErY1CpjigTYtX3VxWB6Ft9a", "btz1MvBXf4orko1tsGmzkjLbpYSgnwUjEe81r", "17590039016550" ],
[ "tz1geDUUhfXK1EMj7LZdP9wfcoAxR3q2QExR", "btz1LoDZ3zsjgG3k3cqTpUMc9bsXbchu9qMXT", "26322312350555" ],
[ "tz1h3nY7jcZciJgAvgNvzgTnjuejEyiEqFGQ", "btz1RMfq456hFV5AeDiZcQuZhoMv2dMpb9hpP", "244951387881443" ],
[ "tz1VzL4Xrb3fL3ckuPqw8u4H7feMAkF4cesJ", "btz1Y9roTh4A7PsMBkp8AgdVFrqUDNaBE59y1", "80065050465525" ],
[ "tz1RUHg536oRKhPLFHi9hit3MKbve91jWjPC", "btz1Q1N2ePwhVw5ED3aaRVek6EBzYs1GDkSVD", "3569618927693" ],
[ "tz1M1LFbgctcPWxstKs21wgvSYBLUpaRwdx8", "btz1VFFVsVMYHd5WfaDTAt92BeQYGK8Ri4eLy", "9034781424478" ]
],
"time_between_blocks" : [ 1, 0 ],
"blocks_per_cycle" : 4,
"blocks_per_roll_snapshot" : 2,
"preserved_cycles" : 1,
"first_free_baking_slot" : 4,
"proof_of_work_threshold": -1
}
|json} in
match json_result with
| Error err -> raise (Failure err)
| Ok json ->
Data_encoding.Binary.to_bytes Data_encoding.json json
let vote_protocol_parameters =
let json_result =
Data_encoding.Json.from_string {json|
{ "bootstrap_accounts": [
[ "edpkuBknW28nW72KG6RoHtYW7p12T6GKc7nAbwYX5m8Wd9sDVC9yav", "4000000000000" ],
[ "edpktzNbDAUjUk697W7gYg2CRuBQjyPxbEg8dLccYYwKSKvkPvjtV9", "4000000000000" ],
[ "edpkuTXkJDGcFd5nh6VvMz8phXxU3Bi7h6hqgywNFi1vZTfQNnS1RV", "4000000000000" ],
[ "edpkuFrRoDSEbJYgxRtLx2ps82UdaYc1WwfS9sE11yhauZt5DgCHbU", "4000000000000" ],
[ "edpkv8EUUH68jmo3f7Um5PezmfGrRF24gnfLpH3sVNwJnV5bVCxL2n", "4000000000000" ]
],
"time_between_blocks" : [ 1, 0 ],
"blocks_per_cycle" : 4,
"blocks_per_roll_snapshot" : 2,
"preserved_cycles" : 1,
"first_free_baking_slot" : 4,
"blocks_per_voting_period": 2,
"proof_of_work_threshold": -1
}
|json} in
match json_result with
| Error err -> raise (Failure err)
| Ok json ->
Data_encoding.Binary.to_bytes Data_encoding.json json
let activate_alpha ?(vote = false) () =
let fitness = Fitness_repr.from_int64 0L in
2018-02-01 17:31:08 +01:00
let dictator_sk = Client_keys.Secret_key_locator.create
~scheme:"unencrypted"
~location:"edsk31vznjHSSpGExDMHYASz45VZqXN4DPxvsa4hAyY8dHM28cZzp6" in
let protocol_parameters =
if vote then vote_protocol_parameters else protocol_parameters in
Tezos_client_genesis.Client_proto_main.bake
(no_write_context ~block:(`Head 0) !rpc_config) (`Head 0)
(Activate { protocol = Proto_alpha.hash ;
fitness ;
protocol_parameters ;
})
dictator_sk
let init ?exe ?vote ?rpc_port () =
begin
match rpc_port with
| None -> ()
| Some port ->
rpc_config := { !rpc_config with port } ;
2018-02-11 19:17:40 +01:00
rpc_ctxt := build_rpc_context !rpc_config ;
end ;
let pid =
Node_helpers.fork_node
?exe
~port:!rpc_config.port
~sandbox:sandbox_parameters
() in
activate_alpha ?vote () >>=? fun hash ->
return (pid, hash)
let level block =
Alpha_services.Context.level !rpc_ctxt block
let rpc_raw_context block path depth =
Block_services.raw_context !rpc_ctxt block path depth
module Account = struct
type t = {
alias : string ;
sk : Signature.secret_key ;
pk : Signature.public_key ;
pkh : Signature.public_key_hash ;
contract : Contract.t ;
}
let encoding =
let open Data_encoding in
conv
(fun { alias ; sk ; pk ; pkh ; contract } ->
(alias, sk, pk, pkh, contract)
)
(fun (alias, sk, pk, pkh, contract) ->
{ alias ; sk ; pk ; pkh ; contract })
(obj5
(req "alias" string)
(req "sk" Signature.Secret_key.encoding)
(req "pk" Signature.Public_key.encoding)
(req "pkh" Signature.Public_key_hash.encoding)
(req "contract" Contract.encoding))
let pp_account ppf account =
let json = Data_encoding.Json.construct encoding account in
Format.fprintf ppf "%s" (Data_encoding.Json.to_string json)
let create ?keys alias =
let sk, pk = match keys with
| Some keys -> keys
| None -> let _, pk, sk = Signature.generate_key () in sk, pk in
let pkh = Signature.Public_key.hash pk in
let contract = Contract.implicit_contract pkh in
{ alias ; contract ; pkh ; pk ; sk }
type destination = {
alias : string ;
contract : Contract.t ;
pk : public_key ;
pkh : public_key_hash ;
}
let destination_encoding =
let open Data_encoding in
conv
(fun { alias ; pk ; pkh ; contract } ->
(alias, pk, pkh, contract))
(fun (alias, pk, pkh, contract) ->
{ alias ; pk ; pkh ; contract })
(obj4
(req "alias" string)
(req "pk" Signature.Public_key.encoding)
(req "pkh" Signature.Public_key_hash.encoding)
(req "contract" Contract.encoding))
let pp_destination ppf destination =
let json = Data_encoding.Json.construct destination_encoding destination in
Format.fprintf ppf "%s" (Data_encoding.Json.to_string json)
let create_destination ~alias ~contract ~pk =
let pkh = Signature.Public_key.hash pk in
{ alias ; contract ; pk ; pkh }
type bootstrap_accounts = { b1 : t ; b2 : t ; b3 : t ; b4 : t ; b5 : t ; }
let bootstrap_accounts =
let bootstrap1_sk =
2018-02-01 17:31:08 +01:00
"edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh" in
let bootstrap2_sk =
2018-02-01 17:31:08 +01:00
"edsk39qAm1fiMjgmPkw1EgQYkMzkJezLNewd7PLNHTkr6w9XA2zdfo" in
let bootstrap3_sk =
2018-02-01 17:31:08 +01:00
"edsk4ArLQgBTLWG5FJmnGnT689VKoqhXwmDPBuGx3z4cvwU9MmrPZZ" in
let bootstrap4_sk =
2018-02-01 17:31:08 +01:00
"edsk2uqQB9AY4FvioK2YMdfmyMrer5R8mGFyuaLLFfSRo8EoyNdht3" in
let bootstrap5_sk =
2018-02-01 17:31:08 +01:00
"edsk4QLrcijEffxV31gGdN2HU7UpyJjA8drFoNcmnB28n89YjPNRFm" in
let cpt = ref 0 in
2018-02-01 17:31:08 +01:00
match List.map begin fun sk ->
incr cpt ;
let sk = Signature.Secret_key.of_b58check_exn sk in
let alias = Printf.sprintf "bootstrap%d" !cpt in
let pk = Signature.Secret_key.to_public_key sk in
let pkh = Signature.Public_key.hash pk in
{ alias ; contract = Contract.implicit_contract pkh; pkh ; pk ; sk }
2018-02-01 17:31:08 +01:00
end [ bootstrap1_sk; bootstrap2_sk; bootstrap3_sk;
bootstrap4_sk; bootstrap5_sk; ]
with
| [ b1 ; b2 ; b3 ; b4 ; b5 ] -> { b1 ; b2 ; b3 ; b4 ; b5 }
| _ -> assert false
let transfer
?(block = `Head 0)
?(fee = Tez.fifty_cents)
~(account:t)
~destination
~amount () =
2018-02-01 17:31:08 +01:00
let src_sk = Client_keys.Secret_key_locator.create
~scheme:"unencrypted"
~location:(Signature.Secret_key.to_b58check account.sk) in
Client_proto_context.transfer
(new wrap_full (no_write_context !rpc_config ~block))
block
~source:account.contract
~src_pk:account.pk
2018-02-01 17:31:08 +01:00
~src_sk
~destination
~amount
~fee ()
let originate
?(block = `Head 0)
?delegate
?(fee = Tez.fifty_cents)
~(src:t)
~manager_pkh
~balance
() =
let delegatable, delegate = match delegate with
| None -> false, None
| Some delegate -> true, Some delegate in
2018-02-01 17:31:08 +01:00
let src_sk = Client_keys.Secret_key_locator.create
~scheme:"unencrypted"
~location:(Signature.Secret_key.to_b58check src.sk) in
2017-11-07 17:38:11 +01:00
Client_proto_context.originate_account
~source:src.contract
~src_pk:src.pk
2018-02-01 17:31:08 +01:00
~src_sk
~manager_pkh
~balance
~delegatable
?delegate
2017-11-07 17:38:11 +01:00
~fee
block
(new wrap_full (no_write_context !rpc_config))
2017-11-07 17:38:11 +01:00
()
let set_delegate
?(block = `Head 0)
?(fee = Tez.fifty_cents)
~contract
~manager_sk
2017-11-07 17:38:11 +01:00
~src_pk
delegate_opt =
2017-11-07 17:38:11 +01:00
Client_proto_context.set_delegate
(new wrap_full (no_write_context ~block !rpc_config))
2017-11-07 17:38:11 +01:00
block
~fee
2017-11-07 17:38:11 +01:00
contract
~src_pk
~manager_sk
delegate_opt
let balance ?(block = `Head 0) (account : t) =
Alpha_services.Contract.balance !rpc_ctxt
block account.contract
(* TODO: gather contract related functions in a Contract module? *)
let delegate ?(block = `Head 0) (contract : Contract.t) =
Alpha_services.Contract.delegate_opt !rpc_ctxt block contract
end
module Protocol = struct
open Account
let voting_period_kind ?(block = `Head 0) () =
Alpha_services.Context.voting_period_kind !rpc_ctxt block
let proposals ?(block = `Head 0) ~src:({ pkh; sk } : Account.t) proposals =
Block_services.info !rpc_ctxt block >>=? fun block_info ->
Alpha_services.Context.next_level !rpc_ctxt block >>=? fun next_level ->
Alpha_services.Forge.Amendment.proposals !rpc_ctxt block
~branch:block_info.hash
~source:pkh
~period:next_level.voting_period
~proposals
() >>=? fun bytes ->
let signed_bytes = Signature.append sk bytes in
return (Tezos_base.Operation.of_bytes_exn signed_bytes)
let ballot ?(block = `Head 0) ~src:({ pkh; sk } : Account.t) ~proposal ballot =
2018-02-11 19:17:40 +01:00
Block_services.info !rpc_ctxt block >>=? fun block_info ->
Alpha_services.Context.next_level !rpc_ctxt block >>=? fun next_level ->
Alpha_services.Forge.Amendment.ballot !rpc_ctxt block
~branch:block_info.hash
~source:pkh
~period:next_level.voting_period
~proposal
~ballot
() >>=? fun bytes ->
let signed_bytes = Signature.append sk bytes in
return (Tezos_base.Operation.of_bytes_exn signed_bytes)
end
module Assert = struct
let fail expected given msg =
Format.kasprintf Pervasives.failwith
"@[%s@ expected: %s@ got: %s@]" msg expected given
let fail_msg fmt = Format.kasprintf (fail "" "") fmt
let default_printer _ = ""
let equal ?(eq=(=)) ?(prn=default_printer) ?(msg="") x y =
if not (eq x y) then fail (prn x) (prn y) msg
let make_equal e p = equal ~eq:e ~prn:p
let equal_bool = make_equal (=) string_of_bool
let equal_int = make_equal (=) string_of_int
let equal_pkh ?msg pkh1 pkh2 =
let eq pkh1 pkh2 =
match pkh1, pkh2 with
| None, None -> true
| Some pkh1, Some pkh2 ->
Signature.Public_key_hash.equal pkh1 pkh2
| _ -> false in
let prn = function
| None -> "none"
| Some pkh -> Signature.Public_key_hash.to_b58check pkh in
equal ?msg ~prn ~eq pkh1 pkh2
let equal_tez ?msg tz1 tz2 =
let eq tz1 tz2 = Int64.equal (Tez.to_mutez tz1) (Tez.to_mutez tz2) in
let prn = Tez.to_string in
equal ?msg ~prn ~eq tz1 tz2
let balance_equal ?block ~msg account expected_balance =
Account.balance ?block account >>=? fun actual_balance ->
match Tez.of_mutez expected_balance with
| None ->
failwith "invalid tez constant"
| Some expected_balance ->
return (equal_tez ~msg expected_balance actual_balance)
let delegate_equal ?block ~msg contract expected_delegate =
Account.delegate ?block contract >>|? fun actual_delegate ->
equal_pkh ~msg expected_delegate actual_delegate
let ecoproto_error f = function
| Alpha_environment.Ecoproto_error error -> f error
| _ -> false
let hash op = Tezos_base.Operation.hash op
2018-02-02 16:26:02 +01:00
let contain_error ?(msg="") ~f = function
| Ok _ -> fail "Error _" "Ok _" msg
2018-02-02 16:26:02 +01:00
| Error error when not (List.exists f error) ->
let error_str = Format.asprintf "%a" Error_monad.pp_print_error error in
fail "" error_str msg
2018-02-02 16:26:02 +01:00
| _ -> ()
let failed_to_preapply ~msg ?op f =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin function
2017-11-01 04:13:23 -07:00
| Client_baking_forge.Failed_to_preapply (op', err) ->
begin
match op with
| None -> true
| Some op ->
let h = hash op and h' = hash op' in
Operation_hash.equal h h'
end && List.exists (ecoproto_error f) err
| _ -> false
end
let generic_economic_error ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:(ecoproto_error (fun _ -> true))
let unknown_contract ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin ecoproto_error (function
| Raw_context.Storage_error _ -> true
| _ -> false)
end
let non_existing_contract ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin ecoproto_error (function
| Contract_storage.Non_existing_contract _ -> true
| _ -> false)
end
let balance_too_low ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin ecoproto_error (function
| Contract.Balance_too_low _ -> true
| _ -> false)
end
let non_spendable ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin ecoproto_error (function
| Contract_storage.Unspendable_contract _ -> true
| _ -> false)
end
let inconsistent_pkh ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin ecoproto_error (function
| Contract_storage.Inconsistent_hash _ -> true
| _ -> false)
end
let inconsistent_public_key ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin ecoproto_error (function
| Contract_storage.Inconsistent_public_key _ -> true
| _ -> false)
end
let missing_public_key ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin ecoproto_error (function
2018-05-21 20:42:37 +02:00
| Contract_storage.Unrevealed_manager_key _ -> true
| _ -> false)
end
let non_delegatable ~msg =
2018-02-02 16:26:02 +01:00
contain_error ~msg ~f:begin ecoproto_error (function
2018-02-23 10:11:59 -05:00
| Delegate_storage.Non_delegatable_contract _ -> true
| _ -> false)
end
let check_protocol ?msg ~block h =
Block_services.protocol !rpc_ctxt block >>=? fun block_proto ->
return @@ equal
?msg
~prn:Protocol_hash.to_b58check
~eq:Protocol_hash.equal
block_proto h
let check_voting_period_kind ?msg ~block kind =
Alpha_services.Context.voting_period_kind !rpc_ctxt block
>>=? fun current_kind ->
return @@ equal
?msg
current_kind kind
let is_none ?(msg="") x =
if x <> None then fail "None" "Some _" msg
let is_some ?(msg="") x =
if x = None then fail "Some _" "None" msg
end
2017-11-01 08:42:37 -07:00
module Baking = struct
2017-11-20 03:37:06 +01:00
let bake block (contract: Account.t) operations =
let ctxt = (new wrap_full (no_write_context ~block !rpc_config)) in
Alpha_services.Context.next_level ctxt block >>=? fun level ->
let seed_nonce_hash =
if level.Level.expected_commitment then
let seed_nonce =
match Nonce.of_bytes @@
Rand.generate Constants.nonce_length with
| Error _ -> assert false
| Ok nonce -> nonce in
Some (Nonce.hash seed_nonce)
else
None in
2018-02-01 17:31:08 +01:00
let src_sk = Client_keys.Secret_key_locator.create
~scheme:"unencrypted"
~location:(Signature.Secret_key.to_b58check contract.sk) in
2017-11-01 04:13:23 -07:00
Client_baking_forge.forge_block
ctxt
block
~operations
~force:true
~best_effort:false
~sort:false
~priority:(`Auto (contract.pkh, Some 1024, false))
?seed_nonce_hash
2018-02-01 17:31:08 +01:00
~src_sk
()
end
module Endorse = struct
let forge_endorsement
block
src_sk
slot =
2018-02-11 19:17:40 +01:00
Block_services.info !rpc_ctxt block >>=? fun { hash ; _ } ->
Alpha_services.Context.level !rpc_ctxt (`Hash (hash, 0)) >>=? fun level ->
Alpha_services.Forge.Consensus.endorsement !rpc_ctxt
block
~branch:hash
~block:hash
~level:level.level
~slots:[slot]
() >>=? fun bytes ->
let signed_bytes = Signature.append src_sk bytes in
return (Tezos_base.Operation.of_bytes_exn signed_bytes)
let signing_slots
?(max_priority = 1024)
block
delegate
level =
Alpha_services.Delegate.Endorser.rights_for_delegate
!rpc_ctxt ~max_priority ~first_level:level ~last_level:level
block delegate >>=? fun possibilities ->
let slots =
List.map (fun (_,slot) -> slot)
@@ List.filter (fun (l, _) -> l = level) possibilities in
return slots
let endorse
?slot
(contract : Account.t)
block =
Alpha_services.Context.level !rpc_ctxt block >>=? fun { level } ->
begin
match slot with
| Some slot -> return slot
| None -> begin
signing_slots
block contract.Account.pkh
level >>=? function
| slot::_ -> return slot
| [] ->
failwith "No slot found at level %a" Raw_level.pp level
end
end >>=? fun slot ->
forge_endorsement block contract.sk slot
(* FIXME @vb: I don't understand this function, copied from @cago. *)
let endorsers_list block =
let get_endorser_list result (account : Account.t) level block =
Alpha_services.Delegate.Endorser.rights_for_delegate
!rpc_ctxt block account.pkh
~max_priority:16
~first_level:level
~last_level:level >>|? fun slots ->
List.iter (fun (_,slot) -> result.(slot) <- account) slots
in
let { Account.b1 ; b2 ; b3 ; b4 ; b5 } = Account.bootstrap_accounts in
let result = Array.make 16 b1 in
Alpha_services.Context.level !rpc_ctxt block >>=? fun level ->
let level = level.level in
get_endorser_list result b1 level block >>=? fun () ->
get_endorser_list result b2 level block >>=? fun () ->
get_endorser_list result b3 level block >>=? fun () ->
get_endorser_list result b4 level block >>=? fun () ->
get_endorser_list result b5 level block >>=? fun () ->
return result
let endorsement_rights
?(max_priority = 1024)
(contract : Account.t) block =
Alpha_services.Context.level !rpc_ctxt block >>=? fun level ->
let delegate = contract.pkh in
let level = level.level in
Alpha_services.Delegate.Endorser.rights_for_delegate
2018-02-11 19:17:40 +01:00
!rpc_ctxt
~max_priority
~first_level:level
~last_level:level
block delegate
end
let display_level block =
Alpha_services.Context.level !rpc_ctxt block >>=? fun lvl ->
Format.eprintf "Level: %a@." Level.pp_full lvl ;
return ()
let endorsement_security_deposit block =
Constants_services.endorsement_security_deposit !rpc_ctxt block