Alpha/Vote: limit number of proposals per delegate to 20

This commit is contained in:
Marco Stronati 2018-11-20 22:51:30 +01:00 committed by Pierre Boutillier
parent 249bbbcb6d
commit 278ffb5a17
No known key found for this signature in database
GPG Key ID: C2F73508B56A193C
8 changed files with 85 additions and 12 deletions

View File

@ -346,6 +346,7 @@ module Constants : sig
nonce_length : int ;
max_revelations_per_block : int ;
max_operation_data_length : int ;
max_proposals_per_delegate : int ;
}
val fixed_encoding: fixed Data_encoding.t
val fixed: fixed
@ -354,6 +355,7 @@ module Constants : sig
val nonce_length: int
val max_revelations_per_block: int
val max_operation_data_length: int
val max_proposals_per_delegate: int
(** Constants parameterized by context *)
type parametric = {
@ -731,11 +733,14 @@ module Vote : sig
val record_proposal:
context -> Protocol_hash.t -> public_key_hash ->
context Lwt.t
context tzresult Lwt.t
val get_proposals:
context -> int32 Protocol_hash.Map.t tzresult Lwt.t
val clear_proposals: context -> context Lwt.t
val recorded_proposal_count_for_delegate:
context -> public_key_hash -> int tzresult Lwt.t
val listings_encoding : (Signature.Public_key_hash.t * int32) list Data_encoding.t
val freeze_listings: context -> context tzresult Lwt.t
val clear_listings: context -> context tzresult Lwt.t

View File

@ -121,6 +121,8 @@ type error += (* `Branch *)
| Invalid_proposal
| Unexpected_proposal
| Unauthorized_proposal
| Too_many_proposals
| Empty_proposal
| Unexpected_ballot
| Unauthorized_ballot
@ -175,17 +177,45 @@ let () =
~pp:(fun ppf () -> Format.fprintf ppf "Unauthorized ballot")
empty
(function Unauthorized_ballot -> Some () | _ -> None)
(fun () -> Unauthorized_ballot)
(fun () -> Unauthorized_ballot) ;
(* Too many proposals *)
register_error_kind
`Branch
~id:"too_many_proposals"
~title:"Too many proposals"
~description:"The delegate reached the maximum number of allowed proposals."
~pp:(fun ppf () -> Format.fprintf ppf "Too many proposals")
empty
(function Too_many_proposals -> Some () | _ -> None)
(fun () -> Too_many_proposals) ;
(* Empty proposal *)
register_error_kind
`Branch
~id:"empty_proposal"
~title:"Empty proposal"
~description:"Proposal lists cannot be empty."
~pp:(fun ppf () -> Format.fprintf ppf "Empty proposal")
empty
(function Empty_proposal -> Some () | _ -> None)
(fun () -> Empty_proposal)
let record_proposals ctxt delegate proposals =
begin match proposals with
| [] -> fail Empty_proposal
| _ :: _ -> return ()
end >>=? fun () ->
Vote.get_current_period_kind ctxt >>=? function
| Proposal ->
Vote.in_listings ctxt delegate >>= fun in_listings ->
if in_listings then
Lwt_list.fold_left_s
fold_left_s
(fun ctxt proposal ->
Vote.record_proposal ctxt proposal delegate)
ctxt proposals >>= return
ctxt proposals >>=? fun ctxt ->
Vote.recorded_proposal_count_for_delegate ctxt delegate >>=? fun count ->
if Compare.Int.(count > Constants.max_proposals_per_delegate) then
fail Too_many_proposals
else return ctxt
else
fail Unauthorized_proposal
| Testing_vote | Testing | Promotion_vote ->

View File

@ -31,6 +31,8 @@ val may_start_new_voting_cycle:
type error +=
| Unexpected_proposal
| Unauthorized_proposal
| Too_many_proposals
| Empty_proposal
val record_proposals:
context ->

View File

@ -27,13 +27,15 @@ let version_number = "\000"
let proof_of_work_nonce_size = 8
let nonce_length = 32
let max_revelations_per_block = 32
let max_operation_data_length = 16 * 1024 ; (* 16kB *)
let max_proposals_per_delegate = 20
let max_operation_data_length = 16 * 1024 (* 16kB *)
type fixed = {
proof_of_work_nonce_size : int ;
nonce_length : int ;
max_revelations_per_block : int ;
max_operation_data_length : int ;
max_proposals_per_delegate : int ;
}
let fixed_encoding =
@ -43,27 +45,32 @@ let fixed_encoding =
(c.proof_of_work_nonce_size,
c.nonce_length,
c.max_revelations_per_block,
c.max_operation_data_length))
c.max_operation_data_length,
c.max_proposals_per_delegate))
(fun (proof_of_work_nonce_size,
nonce_length,
max_revelations_per_block,
max_operation_data_length) ->
max_operation_data_length,
max_proposals_per_delegate) ->
{ proof_of_work_nonce_size ;
nonce_length ;
max_revelations_per_block ;
max_operation_data_length ;
max_proposals_per_delegate ;
} )
(obj4
(obj5
(req "proof_of_work_nonce_size" uint8)
(req "nonce_length" uint8)
(req "max_revelations_per_block" uint8)
(req "max_operation_data_length" int31))
(req "max_operation_data_length" int31)
(req "max_proposals_per_delegate" uint8))
let fixed = {
proof_of_work_nonce_size ;
nonce_length ;
max_revelations_per_block ;
max_operation_data_length ;
max_proposals_per_delegate ;
}
type parametric = {

View File

@ -159,6 +159,11 @@ module Contract = struct
(struct let name = ["counter"] end)
(Z)
module Proposals =
Indexed_context.Make_map
(struct let name = ["proposals"] end)
(Int)
(* Consume gas for serilization and deserialization of expr in this
module *)
module Make_carbonated_map_expr (N : Storage_sigs.NAME) = struct

View File

@ -178,6 +178,11 @@ module Contract : sig
and type value = Z.t
and type t := Raw_context.t
module Proposals : Indexed_data_storage
with type key = Contract_repr.t
and type value = int
and type t := Raw_context.t
module Code : Non_iterable_indexed_carbonated_data_storage
with type key = Contract_repr.t
and type value = Script_repr.lazy_expr

View File

@ -23,8 +23,18 @@
(* *)
(*****************************************************************************)
let record_proposal ctxt delegate proposal =
Storage.Vote.Proposals.add ctxt (delegate, proposal)
let recorded_proposal_count_for_delegate ctxt proposer =
let delegate = Contract_repr.implicit_contract proposer in
Storage.Contract.Proposals.get_option ctxt delegate >>=? function
| None -> return 0
| Some count -> return count
let record_proposal ctxt proposal proposer =
recorded_proposal_count_for_delegate ctxt proposer >>=? fun count ->
let delegate = Contract_repr.implicit_contract proposer in
Storage.Contract.Proposals.init_set ctxt delegate (count + 1) >>= fun ctxt ->
Storage.Vote.Proposals.add ctxt (proposal, proposer) >>= fun ctxt ->
return ctxt
let get_proposals ctxt =
Storage.Vote.Proposals.fold ctxt
@ -42,6 +52,10 @@ let get_proposals ctxt =
end)
let clear_proposals ctxt =
Storage.Delegates.fold ctxt ~init:ctxt ~f:begin fun proposer ctxt ->
let delegate = Contract_repr.implicit_contract proposer in
Storage.Contract.Proposals.remove ctxt delegate
end >>= fun ctxt ->
Storage.Vote.Proposals.clear ctxt
type ballots = {

View File

@ -23,9 +23,14 @@
(* *)
(*****************************************************************************)
(** Records a proposal per delegate *)
val record_proposal:
Raw_context.t -> Protocol_hash.t -> Signature.Public_key_hash.t ->
Raw_context.t Lwt.t
Raw_context.t tzresult Lwt.t
val recorded_proposal_count_for_delegate:
Raw_context.t -> Signature.Public_key_hash.t ->
int tzresult Lwt.t
val get_proposals:
Raw_context.t -> int32 Protocol_hash.Map.t tzresult Lwt.t