diff --git a/src/proto_alpha/lib_protocol/src/alpha_context.mli b/src/proto_alpha/lib_protocol/src/alpha_context.mli index 427fff9d4..06d0dc973 100644 --- a/src/proto_alpha/lib_protocol/src/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/src/alpha_context.mli @@ -245,6 +245,21 @@ end module Constants : sig + (** Fixed constants *) + type fixed = { + proof_of_work_nonce_size : int ; + nonce_length : int ; + max_revelations_per_block : int ; + seed_nonce_revelation_tip : Tez_repr.t ; + origination_burn : Tez_repr.t ; + block_security_deposit : Tez_repr.t ; + endorsement_security_deposit : Tez_repr.t ; + block_reward : Tez_repr.t ; + endorsement_reward : Tez_repr.t ; + } + val fixed_encoding: fixed Data_encoding.t + val fixed: fixed + val proof_of_work_nonce_size: int val block_reward: Tez.t val endorsement_reward: Tez.t @@ -255,6 +270,27 @@ module Constants : sig val endorsement_security_deposit: Tez.t val max_revelations_per_block: int + + (** Constants parameterized by context *) + type parametric = { + preserved_cycles: int ; + blocks_per_cycle: int32 ; + blocks_per_commitment: int32 ; + blocks_per_roll_snapshot: int32 ; + blocks_per_voting_period: int32 ; + time_between_blocks: Period_repr.t list ; + first_free_baking_slot: int ; + endorsers_per_block: int ; + max_gas: int ; + proof_of_work_threshold: int64 ; + dictator_pubkey: Ed25519.Public_key.t ; + max_operation_data_length: int ; + tokens_per_roll: Tez_repr.t ; + michelson_maximum_type_size: int; + } + val parametric_encoding: parametric Data_encoding.t + val parametric: context -> parametric + val preserved_cycles: context -> int val blocks_per_cycle: context -> int32 val blocks_per_commitment: context -> int32 @@ -270,6 +306,11 @@ module Constants : sig val tokens_per_roll: context -> Tez.t val michelson_maximum_type_size: context -> int + type t = { + fixed : fixed ; + parametric : parametric ; + } + val encoding: t Data_encoding.t end module Voting_period : sig diff --git a/src/proto_alpha/lib_protocol/src/constants_repr.ml b/src/proto_alpha/lib_protocol/src/constants_repr.ml index 82ac12d76..1a3a6808a 100644 --- a/src/proto_alpha/lib_protocol/src/constants_repr.ml +++ b/src/proto_alpha/lib_protocol/src/constants_repr.ml @@ -8,9 +8,9 @@ (**************************************************************************) let version_number = "\000" - let proof_of_work_nonce_size = 8 let nonce_length = 32 +let max_revelations_per_block = 32 (* 1/8 tez *) let seed_nonce_revelation_tip = @@ -38,9 +38,74 @@ let block_reward = let endorsement_reward = Tez_repr.(mul_exn one 2) -let max_revelations_per_block = 32 +type fixed = { + proof_of_work_nonce_size : int ; + nonce_length : int ; + max_revelations_per_block : int ; + seed_nonce_revelation_tip : Tez_repr.t ; + origination_burn : Tez_repr.t ; + block_security_deposit : Tez_repr.t ; + endorsement_security_deposit : Tez_repr.t ; + block_reward : Tez_repr.t ; + endorsement_reward : Tez_repr.t ; +} -type constants = { +let fixed_encoding = + let open Data_encoding in + conv + (fun c -> + ( c.proof_of_work_nonce_size, + c.nonce_length, + c.max_revelations_per_block, + c.seed_nonce_revelation_tip, + c.origination_burn, + c.block_security_deposit, + c.endorsement_security_deposit, + c.block_reward, + c.endorsement_reward )) + (fun ( proof_of_work_nonce_size, + nonce_length, + max_revelations_per_block, + seed_nonce_revelation_tip, + origination_burn, + block_security_deposit, + endorsement_security_deposit, + block_reward, + endorsement_reward) -> + { proof_of_work_nonce_size ; + nonce_length ; + max_revelations_per_block ; + seed_nonce_revelation_tip ; + origination_burn ; + block_security_deposit ; + endorsement_security_deposit ; + block_reward ; + endorsement_reward ; + } ) + (obj9 + (req "proof_of_work_nonce_size" uint8) + (req "nonce_length" uint8) + (req "max_revelations_per_block" uint8) + (req "seed_nonce_revelation_tip" Tez_repr.encoding) + (req "origination_burn" Tez_repr.encoding) + (req "block_security_deposit" Tez_repr.encoding) + (req "endorsement_security_deposit" Tez_repr.encoding) + (req "block_reward" Tez_repr.encoding) + (req "endorsement_reward" Tez_repr.encoding)) + +let fixed = { + proof_of_work_nonce_size ; + nonce_length ; + max_revelations_per_block ; + seed_nonce_revelation_tip ; + origination_burn ; + block_security_deposit ; + endorsement_security_deposit ; + block_reward ; + endorsement_reward ; +} + +type parametric = { preserved_cycles: int ; blocks_per_cycle: int32 ; blocks_per_commitment: int32 ; @@ -57,8 +122,6 @@ type constants = { michelson_maximum_type_size: int; } -let read_public_key = Ed25519.Public_key.of_b58check_exn - let default = { preserved_cycles = 5 ; blocks_per_cycle = 4096l ; @@ -73,7 +136,7 @@ let default = { proof_of_work_threshold = Int64.(sub (shift_left 1L 56) 1L) ; dictator_pubkey = - read_public_key + Ed25519.Public_key.of_b58check_exn "edpkugeDwmwuwyyD3Q5enapgEYDxZLtEUFFSrvVwXASQMVEqsvTqWu" ; max_operation_data_length = 16 * 1024 ; (* 16kB *) @@ -82,21 +145,22 @@ let default = { michelson_maximum_type_size = 1000 ; } -let opt (=) def v = if def = v then None else Some v -let unopt def = function None -> def | Some v -> v - let map_option f = function | None -> None | Some x -> Some (f x) module CompareListInt = Compare.List (Compare.Int) -let constants_encoding = - (* let open Data_encoding in *) - Data_encoding.conv +(* This encoding is used to read configuration files (e.g. sandbox.json) + where some fields can be missing, in that case they are replaced by + the default. *) +let sandbox_encoding = + let open Data_encoding in + conv (fun c -> let module Compare_time_between_blocks = Compare.List (Period_repr) in let module Compare_keys = Compare.List (Ed25519.Public_key) in + let opt (=) def v = if def = v then None else Some v in let preserved_cycles = opt Compare.Int.(=) default.preserved_cycles c.preserved_cycles @@ -168,6 +232,7 @@ let constants_encoding = max_operation_data_length, tokens_per_roll, michelson_maximum_type_size)), ()) -> + let unopt def = function None -> def | Some v -> v in { preserved_cycles = unopt default.preserved_cycles preserved_cycles ; blocks_per_cycle = @@ -198,40 +263,112 @@ let constants_encoding = michelson_maximum_type_size = unopt default.michelson_maximum_type_size michelson_maximum_type_size ; } ) - Data_encoding.( - merge_objs - (merge_objs - (obj9 - (opt "preserved_cycles" uint8) - (opt "blocks_per_cycle" int32) - (opt "blocks_per_commitment" int32) - (opt "blocks_per_roll_snapshot" int32) - (opt "blocks_per_voting_period" int32) - (opt "time_between_blocks" (list Period_repr.encoding)) - (opt "first_free_baking_slot" uint16) - (opt "endorsers_per_block" uint16) - (opt "instructions_per_transaction" int31)) - (obj5 - (opt "proof_of_work_threshold" int64) - (opt "dictator_pubkey" Ed25519.Public_key.encoding) - (opt "max_operation_data_length" int31) - (opt "tokens_per_roll" Tez_repr.encoding) - (opt "michelson_maximum_type_size" uint16) - )) - unit) + (merge_objs + (merge_objs + (obj9 + (opt "preserved_cycles" uint8) + (opt "blocks_per_cycle" int32) + (opt "blocks_per_commitment" int32) + (opt "blocks_per_roll_snapshot" int32) + (opt "blocks_per_voting_period" int32) + (opt "time_between_blocks" (list Period_repr.encoding)) + (opt "first_free_baking_slot" uint16) + (opt "endorsers_per_block" uint16) + (opt "instructions_per_transaction" int31)) + (obj5 + (opt "proof_of_work_threshold" int64) + (opt "dictator_pubkey" Ed25519.Public_key.encoding) + (opt "max_operation_data_length" int31) + (opt "tokens_per_roll" Tez_repr.encoding) + (opt "michelson_maximum_type_size" uint16) + )) + unit) -type error += Constant_read of string +let parametric_encoding = + let open Data_encoding in + conv + (fun c -> + (( c.preserved_cycles, + c.blocks_per_cycle, + c.blocks_per_commitment, + c.blocks_per_roll_snapshot, + c.blocks_per_voting_period, + c.time_between_blocks, + c.first_free_baking_slot, + c.endorsers_per_block, + c.max_gas), + ( c.proof_of_work_threshold, + c.dictator_pubkey, + c.max_operation_data_length, + c.tokens_per_roll, + c.michelson_maximum_type_size)) ) + (fun (( preserved_cycles, + blocks_per_cycle, + blocks_per_commitment, + blocks_per_roll_snapshot, + blocks_per_voting_period, + time_between_blocks, + first_free_baking_slot, + endorsers_per_block, + max_gas), + ( proof_of_work_threshold, + dictator_pubkey, + max_operation_data_length, + tokens_per_roll, + michelson_maximum_type_size)) -> + { preserved_cycles ; + blocks_per_cycle ; + blocks_per_commitment ; + blocks_per_roll_snapshot ; + blocks_per_voting_period ; + time_between_blocks ; + first_free_baking_slot ; + endorsers_per_block ; + max_gas ; + proof_of_work_threshold ; + dictator_pubkey ; + max_operation_data_length ; + tokens_per_roll ; + michelson_maximum_type_size ; + } ) + (merge_objs + (obj9 + (req "preserved_cycles" uint8) + (req "blocks_per_cycle" int32) + (req "blocks_per_commitment" int32) + (req "blocks_per_roll_snapshot" int32) + (req "blocks_per_voting_period" int32) + (req "time_between_blocks" (list Period_repr.encoding)) + (req "first_free_baking_slot" uint16) + (req "endorsers_per_block" uint16) + (req "instructions_per_transaction" int31)) + (obj5 + (req "proof_of_work_threshold" int64) + (req "dictator_pubkey" Ed25519.Public_key.encoding) + (req "max_operation_data_length" int31) + (req "tokens_per_roll" Tez_repr.encoding) + (req "michelson_maximum_type_size" uint16))) -let read = function +type t = { + fixed : fixed ; + parametric : parametric ; +} + +let encoding = + let open Data_encoding in + conv + (fun { fixed ; parametric } -> (fixed, parametric)) + (fun (fixed , parametric) -> { fixed ; parametric }) + (merge_objs fixed_encoding parametric_encoding) + +type error += Constant_read of exn + +let read_sandbox = function | None -> return default | Some json -> - match Data_encoding.Json.(destruct constants_encoding json) with - | exception (Data_encoding.Json.Cannot_destruct _ as exn) -> - Format.kasprintf - failwith "Invalid sandbox: %a %a" - (fun ppf -> Data_encoding.Json.print_error ppf) exn - Data_encoding.Json.pp json + match Data_encoding.Json.(destruct sandbox_encoding json) with + | exception exn -> fail (Constant_read exn) | c -> if Compare.Int32.(c.blocks_per_roll_snapshot > c.blocks_per_cycle) then failwith "Invalid sandbox: 'blocks_per_roll_snapshot > blocks_per_cycle'" diff --git a/src/proto_alpha/lib_protocol/src/constants_services.ml b/src/proto_alpha/lib_protocol/src/constants_services.ml index ec77abb2f..47de12cdf 100644 --- a/src/proto_alpha/lib_protocol/src/constants_services.ml +++ b/src/proto_alpha/lib_protocol/src/constants_services.ml @@ -104,6 +104,14 @@ module S = struct ~output: json_schema RPC_path.(custom_root / "errors") + let all = + RPC_service.post_service + ~description: "All constants" + ~query: RPC_query.empty + ~input: empty + ~output: Alpha_context.Constants.encoding + custom_root + end @@ -141,6 +149,11 @@ let () = end ; register0_noctxt S.errors begin fun () () -> return (Data_encoding.Json.(schema error_encoding)) + end ; + register0 S.all begin fun ctxt () () -> + let open Constants in + return { fixed = fixed ; + parametric = parametric ctxt } end let blocks_per_cycle ctxt block = @@ -165,3 +178,5 @@ let proof_of_work_threshold ctxt block = RPC_context.make_call0 S.proof_of_work_threshold ctxt block () () let errors ctxt block = RPC_context.make_call0 S.errors ctxt block () () +let all ctxt block = + RPC_context.make_call0 S.all ctxt block () () diff --git a/src/proto_alpha/lib_protocol/src/constants_services.mli b/src/proto_alpha/lib_protocol/src/constants_services.mli index aba683702..b60e22413 100644 --- a/src/proto_alpha/lib_protocol/src/constants_services.mli +++ b/src/proto_alpha/lib_protocol/src/constants_services.mli @@ -15,15 +15,15 @@ val preserved_cycles: val blocks_per_cycle: 'a #RPC_context.simple -> 'a -> int32 shell_tzresult Lwt.t -val blocks_per_voting_period: - 'a #RPC_context.simple -> 'a -> int32 shell_tzresult Lwt.t - val blocks_per_commitment: 'a #RPC_context.simple -> 'a -> int32 shell_tzresult Lwt.t val blocks_per_roll_snapshot: 'a #RPC_context.simple -> 'a -> int32 shell_tzresult Lwt.t +val blocks_per_voting_period: + 'a #RPC_context.simple -> 'a -> int32 shell_tzresult Lwt.t + val time_between_blocks: 'a #RPC_context.simple -> 'a -> Period.t list shell_tzresult Lwt.t @@ -41,3 +41,6 @@ val proof_of_work_threshold: val errors: 'a #RPC_context.simple -> 'a -> Data_encoding.json_schema shell_tzresult Lwt.t + +val all: + 'a #RPC_context.simple -> 'a -> Constants.t shell_tzresult Lwt.t diff --git a/src/proto_alpha/lib_protocol/src/constants_storage.ml b/src/proto_alpha/lib_protocol/src/constants_storage.ml index fd2ece4f3..47ff02167 100644 --- a/src/proto_alpha/lib_protocol/src/constants_storage.ml +++ b/src/proto_alpha/lib_protocol/src/constants_storage.ml @@ -49,3 +49,5 @@ let tokens_per_roll c = let michelson_maximum_type_size c = let constants = Raw_context.constants c in constants.michelson_maximum_type_size +let parametric c = + Raw_context.constants c diff --git a/src/proto_alpha/lib_protocol/src/raw_context.ml b/src/proto_alpha/lib_protocol/src/raw_context.ml index 334924a1b..05835bfcf 100644 --- a/src/proto_alpha/lib_protocol/src/raw_context.ml +++ b/src/proto_alpha/lib_protocol/src/raw_context.ml @@ -11,7 +11,7 @@ module Int_set = Set.Make (Compare.Int) type t = { context: Context.t ; - constants: Constants_repr.constants ; + constants: Constants_repr.parametric ; first_level: Raw_level_repr.t ; level: Level_repr.t ; timestamp: Time.t ; @@ -191,7 +191,7 @@ let get_proto_param ctxt = let set_constants ctxt constants = let bytes = Data_encoding.Binary.to_bytes - Constants_repr.constants_encoding constants in + Constants_repr.parametric_encoding constants in Context.set ctxt constants_key bytes let get_constants ctxt = @@ -200,7 +200,7 @@ let get_constants ctxt = failwith "Internal error: cannot read constants in context." | Some bytes -> match - Data_encoding.Binary.of_bytes Constants_repr.constants_encoding bytes + Data_encoding.Binary.of_bytes Constants_repr.parametric_encoding bytes with | None -> failwith "Internal error: cannot parse constants in context." @@ -253,7 +253,7 @@ let prepare_first_block ~level ~timestamp ~fitness ctxt = Lwt.return (Raw_level_repr.of_int32 level) >>=? fun first_level -> get_proto_param ctxt >>=? fun (param, ctxt) -> get_sandbox_param ctxt >>=? fun sandbox_param -> - Constants_repr.read sandbox_param >>=? fun constants -> + Constants_repr.read_sandbox sandbox_param >>=? fun constants -> Context.set ctxt version_key (MBytes.of_string version_value) >>= fun ctxt -> set_first_level ctxt first_level >>=? fun ctxt -> diff --git a/src/proto_alpha/lib_protocol/src/raw_context.mli b/src/proto_alpha/lib_protocol/src/raw_context.mli index d69454db5..e17fea0f4 100644 --- a/src/proto_alpha/lib_protocol/src/raw_context.mli +++ b/src/proto_alpha/lib_protocol/src/raw_context.mli @@ -59,7 +59,7 @@ val current_timestamp: context -> Time.t val current_fitness: context -> Int64.t val set_current_fitness: context -> Int64.t -> t -val constants: context -> Constants_repr.constants +val constants: context -> Constants_repr.parametric val first_level: context -> Raw_level_repr.t (** {1 Generic accessors} *************************************************)