Alpha/RPC: use query string for delegation rights

This commit is contained in:
Grégoire Henry 2018-04-20 14:55:07 +02:00 committed by Benjamin Canou
parent 7b758dbca8
commit 482dbb116c
21 changed files with 453 additions and 480 deletions

View File

@ -30,13 +30,12 @@ let commands () =
iter_s (fun d -> Client_keys.get_key cctxt d >>|? fun _ -> ()) delegates >>=? fun () ->
run_daemon cctxt ?max_priority ~endorsement_delay ~endorsement ~baking ~denunciation delegates) ;
command ~group ~desc: "Forge and inject an endorsement operation."
(args1 max_priority_arg)
no_options
(prefixes [ "endorse"; "for" ]
@@ Client_keys.Public_key_hash.source_param
~name:"baker" ~desc: "name of the delegate owning the endorsement right"
@@ stop)
(fun max_priority delegate cctxt ->
endorse_block cctxt ?max_priority delegate) ;
(fun () delegate cctxt -> endorse_block cctxt delegate) ;
command ~group ~desc: "Forge and inject block using the delegate rights."
(args4 max_priority_arg force_switch
free_baking_switch minimal_timestamp_switch)

View File

@ -82,14 +82,14 @@ end = struct
end
let get_signing_slots cctxt ?max_priority ?(chain = `Main) block delegate level =
Alpha_services.Delegate.Endorser.rights_for_delegate cctxt
?max_priority ~first_level:level ~last_level:level
(chain, block) delegate >>=? fun possibilities ->
let slots =
List.map (fun (_,slot) -> slot)
@@ List.filter (fun (l, _) -> l = level) possibilities in
return slots
let get_signing_slots cctxt ?(chain = `Main) block delegate level =
Alpha_services.Delegate.Endorsing_rights.get cctxt
~levels:[level]
~delegates:[delegate]
(chain, block) >>=? fun possibilities ->
match possibilities with
| [{ slots }] -> return slots
| _ -> return []
let inject_endorsement
(cctxt : #Proto_alpha.full)
@ -130,7 +130,7 @@ let check_endorsement cctxt level slot =
let forge_endorsement (cctxt : #Proto_alpha.full)
?(chain = `Main) block
~src_sk ?slots ?max_priority src_pk =
~src_sk ?slots src_pk =
let src_pkh = Signature.Public_key.hash src_pk in
Block_services.Metadata.protocol_data
cctxt ~chain ~block () >>=? fun { level = { level } } ->
@ -139,7 +139,7 @@ let forge_endorsement (cctxt : #Proto_alpha.full)
| Some slots -> return slots
| None ->
get_signing_slots
cctxt ?max_priority ~chain block src_pkh level >>=? function
cctxt ~chain block src_pkh level >>=? function
| [] -> cctxt#error "No slot found at level %a" Raw_level.pp level
| slots -> return slots
end >>=? fun slots ->

View File

@ -16,7 +16,6 @@ val forge_endorsement:
Block_services.block ->
src_sk:Client_keys.sk_uri ->
?slots:int list ->
?max_priority:int ->
public_key ->
Operation_hash.t tzresult Lwt.t

View File

@ -153,15 +153,15 @@ let forge_block cctxt ?(chain = `Main) block
| `Set priority -> begin
Alpha_services.Helpers.minimal_time
cctxt (chain, block) ~priority >>=? fun time ->
return (priority, time)
return (priority, Some time)
end
| `Auto (src_pkh, max_priority, free_baking) ->
Alpha_services.Helpers.next_level cctxt (chain, block) >>=? fun { level } ->
Alpha_services.Delegate.Baker.rights_for_delegate cctxt
Alpha_services.Delegate.Baking_rights.get cctxt
?max_priority
~first_level:level
~last_level:level
(chain, block) src_pkh >>=? fun possibilities ->
~levels:[level]
~delegates:[src_pkh]
(chain, block) >>=? fun possibilities ->
try
begin
if free_baking then
@ -169,8 +169,12 @@ let forge_block cctxt ?(chain = `Main) block
else
return 0
end >>=? fun min_prio ->
let _, prio, time =
List.find (fun (l,p,_) -> l = level && p >= min_prio) possibilities in
let { Alpha_services.Delegate.Baking_rights.priority = prio ;
timestamp = time } =
List.find
(fun (p : Alpha_services.Delegate.Baking_rights.t) ->
p.level = level && p.priority >= min_prio)
possibilities in
return (prio, time)
with Not_found ->
failwith "No slot found at level %a" Raw_level.pp level
@ -179,8 +183,10 @@ let forge_block cctxt ?(chain = `Main) block
(* Raw_level.pp level priority >>= fun () -> *)
begin
match timestamp, minimal_timestamp with
| None, timestamp -> return timestamp
| Some timestamp, minimal_timestamp ->
| None, None -> return (Time.now ())
| None, Some timestamp -> return timestamp
| Some timestamp, None -> return timestamp
| Some timestamp, Some minimal_timestamp ->
if timestamp < minimal_timestamp then
failwith
"Proposed timestamp %a is earlier than minimal timestamp %a"
@ -325,29 +331,22 @@ let get_baking_slot cctxt
let chain = `Hash bi.chain_id in
let block = `Hash (bi.hash, 0) in
let level = Raw_level.succ bi.level.level in
Lwt_list.filter_map_p
(fun delegate ->
Alpha_services.Delegate.Baker.rights_for_delegate cctxt
?max_priority
~first_level:level
~last_level:level
(chain, block) delegate >>= function
| Error errs ->
log_error "Error while fetching baking possibilities:\n%a"
pp_print_error errs ;
Lwt.return_none
| Ok slots ->
let convert = fun (_lvl, slot, timestamp) ->
(timestamp, (bi, slot, delegate)) in
Lwt.return (Some (List.map convert slots)))
delegates >>= fun slots ->
let sorted_slots =
List.sort
(fun (t1,_) (t2,_) -> Time.compare t1 t2)
(List.flatten slots) in
match sorted_slots with
| [] -> Lwt.return None
| slot :: _ -> Lwt.return (Some slot)
Alpha_services.Delegate.Baking_rights.get cctxt
?max_priority
~levels:[level]
~delegates
(chain, block) >>= function
| Error errs ->
log_error "Error while fetching baking possibilities:\n%a"
pp_print_error errs ;
Lwt.return_none
| Ok [] ->
Lwt.return_none
| Ok ((slot : Alpha_services.Delegate.Baking_rights.t) :: _) ->
match slot.timestamp with
| None -> Lwt.return_none
| Some timestamp ->
Lwt.return_some (timestamp, (bi, slot.priority, slot.delegate))
let rec insert_baking_slot slot = function
| [] -> [slot]

View File

@ -44,10 +44,10 @@ let bake_block (cctxt : #Proto_alpha.full)
cctxt#message "Injected block %a" Block_hash.pp_short block_hash >>= fun () ->
return ()
let endorse_block cctxt ?max_priority delegate =
let endorse_block cctxt delegate =
Client_keys.get_key cctxt delegate >>=? fun (_src_name, src_pk, src_sk) ->
Client_baking_endorsement.forge_endorsement cctxt
cctxt#block ?max_priority ~src_sk src_pk >>=? fun oph ->
cctxt#block ~src_sk src_pk >>=? fun oph ->
cctxt#answer "Operation successfully injected in the node." >>= fun () ->
cctxt#answer "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
return ()

View File

@ -26,7 +26,6 @@ val bake_block:
(** Endorse a block *)
val endorse_block:
#Proto_alpha.full ->
?max_priority:int ->
Client_keys.Public_key_hash.t ->
unit Error_monad.tzresult Lwt.t

View File

@ -560,17 +560,14 @@ module Endorse = struct
sign ~watermark:Endorsement src_sk shell contents
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
(`Main, block) delegate >>=? fun possibilities ->
let slots =
List.map (fun (_,slot) -> slot)
@@ List.filter (fun (l, _) -> l = level) possibilities in
return slots
Alpha_services.Delegate.Endorsing_rights.get
!rpc_ctxt ~delegates:[delegate] ~levels:[level]
(`Main, block) >>=? function
| [{ slots }] -> return slots
| _ -> return []
let endorse
?slot
@ -596,15 +593,15 @@ module Endorse = struct
(* 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 (`Main, block) account.pkh
~max_priority:16
~first_level:level
~last_level:level >>|? fun slots ->
List.iter (fun (_,slot) -> result.(slot) <- account) slots
in
Alpha_services.Delegate.Endorsing_rights.get
!rpc_ctxt (`Main, block)
~delegates:[account.pkh]
~levels:[level] >>|? function
| [{ slots }] ->
List.iter (fun s -> result.(s) <- account) slots
| _ -> () in
let { Account.b1 ; b2 ; b3 ; b4 ; b5 } = Account.bootstrap_accounts in
let result = Array.make 16 b1 in
let result = Array.make 32 b1 in
Block_services.Metadata.protocol_data
!rpc_ctxt ~chain:`Main ~block () >>=? fun { level } ->
let level = level.level in
@ -616,18 +613,18 @@ module Endorse = struct
return result
let endorsement_rights
?(max_priority = 1024)
(contract : Account.t) block =
Block_services.Metadata.protocol_data
!rpc_ctxt ~chain:`Main ~block () >>=? fun { level } ->
let level = level.level in
let delegate = contract.pkh in
Alpha_services.Delegate.Endorser.rights_for_delegate
Alpha_services.Delegate.Endorsing_rights.get
!rpc_ctxt
~max_priority
~first_level:level
~last_level:level
(`Main, block) delegate
~levels:[level]
~delegates:[delegate]
(`Main, block) >>=? function
| [{ level ; slots }] -> return (List.map (fun s -> (level, s)) slots)
| _ -> return []
end

View File

@ -122,7 +122,6 @@ module Endorse : sig
Account.t array tzresult Lwt.t
val endorsement_rights :
?max_priority:int ->
Account.t ->
Block_services.block ->
(Raw_level.t * int) list tzresult Lwt.t

View File

@ -352,9 +352,10 @@ let apply_consensus_operation_content ctxt
Operation.check_signature delegate operation >>=? fun () ->
let delegate = Signature.Public_key.hash delegate in
let ctxt = Fitness.increase ~gap:(List.length slots) ctxt in
Baking.freeze_endorsement_deposit ctxt delegate >>=? fun ctxt ->
Baking.freeze_endorsement_deposit
ctxt delegate (List.length slots) >>=? fun ctxt ->
Global.get_last_block_priority ctxt >>=? fun block_priority ->
Baking.endorsement_reward ctxt ~block_priority >>=? fun reward ->
Baking.endorsement_reward ctxt ~block_priority (List.length slots) >>=? fun reward ->
Delegate.freeze_rewards ctxt delegate reward >>=? fun ctxt ->
return (ctxt, Endorsements_result (delegate, slots))

View File

@ -151,6 +151,18 @@ let minimal_time c priority pred_timestamp =
(cumsum_time_between_blocks
pred_timestamp (Constants.time_between_blocks c) (Int32.succ priority))
let earlier_predecessor_timestamp ctxt level =
let current = Level.current ctxt in
let current_timestamp = Timestamp.current ctxt in
let gap = Level.diff level current in
let step = List.hd (Constants.time_between_blocks ctxt) in
if Compare.Int32.(gap < 1l) then
failwith "Baking.earlier_block_timestamp: past block."
else
Lwt.return (Period.mult (Int32.pred gap) step) >>=? fun delay ->
Lwt.return Timestamp.(current_timestamp +? delay) >>=? fun result ->
return result
let freeze_baking_deposit ctxt { Block_header.priority ; _ } delegate =
if Compare.Int.(priority >= Constants.first_free_baking_slot ctxt)
then return (ctxt, Tez.zero)
@ -160,8 +172,9 @@ let freeze_baking_deposit ctxt { Block_header.priority ; _ } delegate =
|> trace Cannot_freeze_baking_deposit >>=? fun ctxt ->
return (ctxt, deposit)
let freeze_endorsement_deposit ctxt delegate =
let freeze_endorsement_deposit ctxt delegate n =
let deposit = Constants.endorsement_security_deposit ctxt in
Lwt.return (Tez.(deposit *? Int64.of_int n)) >>=? fun deposit ->
Delegate.freeze_deposit ctxt delegate deposit
|> trace Cannot_freeze_endorsement_deposit
@ -196,11 +209,12 @@ let paying_priorities c =
type error += Incorrect_priority
let endorsement_reward ctxt ~block_priority:prio =
let endorsement_reward ctxt ~block_priority:prio n =
if Compare.Int.(prio >= 0)
then
Lwt.return
Tez.(Constants.endorsement_reward ctxt /? (Int64.(succ (of_int prio))))
Tez.(Constants.endorsement_reward ctxt /? (Int64.(succ (of_int prio)))) >>=? fun tez ->
Lwt.return Tez.(tez *? Int64.of_int n)
else fail Incorrect_priority
let baking_priorities c level =

View File

@ -50,7 +50,7 @@ val freeze_baking_deposit:
Raise an error if the baker account does not have enough
funds to claim endorsement rights *)
val freeze_endorsement_deposit:
context -> public_key_hash -> context tzresult Lwt.t
context -> public_key_hash -> int -> context tzresult Lwt.t
(** [check_baking_rights ctxt block pred_timestamp] verifies that:
* the contract that owned the roll at cycle start has the block signer as delegate.
@ -69,7 +69,7 @@ val check_endorsements_rights:
context -> Level.t -> int list -> public_key tzresult Lwt.t
(** Returns the endorsement reward calculated w.r.t a given priotiry. *)
val endorsement_reward: context -> block_priority:int -> Tez.t tzresult Lwt.t
val endorsement_reward: context -> block_priority:int -> int -> Tez.t tzresult Lwt.t
(** [baking_priorities ctxt level] is the lazy list of contract's
public key hashes that are allowed to bake for [level]. *)
@ -120,3 +120,5 @@ val check_fitness_gap:
context -> Block_header.t -> unit tzresult Lwt.t
val dawn_of_a_new_cycle: context -> Cycle.t option tzresult Lwt.t
val earlier_predecessor_timestamp: context -> Level.t -> Timestamp.t tzresult Lwt.t

View File

@ -9,13 +9,6 @@
open Alpha_context
let slots_range_encoding =
let open Data_encoding in
(obj3
(opt "max_priority" int31)
(opt "first_level" Raw_level.encoding)
(opt "last_level" Raw_level.encoding))
type info = {
balance: Tez.t ;
frozen_balance: Tez.t ;
@ -38,13 +31,13 @@ let info_encoding =
{ balance ; frozen_balance ; frozen_balances ; delegated_balance ;
delegated_contracts ; deactivated ; grace_period })
(obj7
(req "balance" Tez.encoding)
(req "frozen_balance" Tez.encoding)
(req "frozen_balances" Delegate.frozen_balances_encoding)
(req "delegated_balance" Tez.encoding)
(req "delegated_contracts" (list Contract_hash.encoding))
(req "deactivated" bool)
(req "grace_period" Cycle.encoding))
(req "balance" Tez.encoding)
(req "frozen_balance" Tez.encoding)
(req "frozen_balances" Delegate.frozen_balances_encoding)
(req "delegated_balance" Tez.encoding)
(req "delegated_contracts" (list Contract_hash.encoding))
(req "deactivated" bool)
(req "grace_period" Cycle.encoding))
module S = struct
@ -230,313 +223,264 @@ let deactivated ctxt block pkh =
let grace_period ctxt block pkh =
RPC_context.make_call1 S.grace_period ctxt block pkh () ()
let requested_levels ~default ctxt cycles levels =
match levels, cycles with
| [], [] ->
return [default]
| levels, cycles ->
(* explicitly fail when requested levels or cycle are in the past...
or too far in the future... *)
(* check_levels levels >>=? fun () -> *)
(* check_cycles levels >>=? fun () -> *)
let levels =
List.sort_uniq
Level.compare
(List.concat (List.map (Level.from_raw ctxt) levels ::
List.map (Level.levels_in_cycle ctxt) cycles)) in
map_p
(fun level ->
let current_level = Level.current ctxt in
if Level.(level <= current_level) then
return (level, None)
else
Baking.earlier_predecessor_timestamp
ctxt level >>=? fun timestamp ->
return (level, Some timestamp))
levels
module Baker = struct
module Baking_rights = struct
type t = {
level: Raw_level.t ;
delegate: Signature.Public_key_hash.t ;
priority: int ;
timestamp: Timestamp.t option ;
}
let encoding =
let open Data_encoding in
conv
(fun { level ; delegate ; priority ; timestamp } ->
(level, delegate, priority, timestamp))
(fun (level, delegate, priority, timestamp) ->
{ level ; delegate ; priority ; timestamp })
(obj4
(req "level" Raw_level.encoding)
(req "delegate" Signature.Public_key_hash.encoding)
(req "priority" uint16)
(opt "timestamp" Timestamp.encoding))
module S = struct
open Data_encoding
let custom_root =
RPC_path.(open_root / "helpers" / "rights" / "baking")
RPC_path.(open_root / "helpers" / "baking_rights")
let slot_encoding =
(obj3
(req "level" Raw_level.encoding)
(req "priority" int31)
(req "timestamp" Timestamp.encoding))
type baking_rights_query = {
levels: Raw_level.t list ;
cycles: Cycle.t list ;
delegates: Signature.Public_key_hash.t list ;
max_priority: int option ;
all: bool ;
}
let rights =
RPC_service.post_service
~description:
"List delegates allowed to bake for the next level, \
ordered by priority."
~query: RPC_query.empty
~input: (obj1 (opt "max_priority" int31))
~output: (obj2
(req "level" Raw_level.encoding)
(req "baking_rights"
(list
(obj2
(req "delegate" Signature.Public_key_hash.encoding)
(req "timestamp" Timestamp.encoding)))))
let baking_rights_query =
let open RPC_query in
query (fun levels cycles delegates max_priority all ->
{ levels ; cycles ; delegates ; max_priority ; all })
|+ multi_field "level" Raw_level.arg (fun t -> t.levels)
|+ multi_field "cycle" Cycle.arg (fun t -> t.cycles)
|+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> t.delegates)
|+ opt_field "max_priority" RPC_arg.int (fun t -> t.max_priority)
|+ flag "all" (fun t -> t.all)
|> seal
let baking_rights =
RPC_service.get_service
~description: "...FIXME..."
~query: baking_rights_query
~output: (list encoding)
custom_root
let rights_for_level =
RPC_service.post_service
~description:
"List delegates allowed to bake for a given level, \
ordered by priority."
~query: RPC_query.empty
~input: (obj1 (opt "max_priority" int31))
~output: (obj2
(req "level" Raw_level.encoding)
(req "delegates"
(list Signature.Public_key_hash.encoding)))
RPC_path.(custom_root / "level" /: Raw_level.arg)
(* let levels = *)
(* RPC_service.post_service *)
(* ~description: *)
(* "List level for which we might computed baking rights." *)
(* ~query: RPC_query.empty *)
(* ~input: empty *)
(* ~output: (obj1 (req "levels" (list Raw_level.encoding))) *)
(* RPC_path.(custom_root / "level") *)
let rights_for_delegate =
RPC_service.post_service
~description: "Future baking rights for a given delegate."
~query: RPC_query.empty
~input: slots_range_encoding
~output: (Data_encoding.list slot_encoding)
RPC_path.(custom_root / "delegate" /: Signature.Public_key_hash.rpc_arg)
(* let delegates = *)
(* RPC_service.post_service *)
(* ~description: *)
(* "List delegates with baking rights." *)
(* ~query: RPC_query.empty *)
(* ~input: empty *)
(* ~output: (obj1 (req "delegates" *)
(* (list Signature.Public_key_hash.encoding))) *)
(* RPC_path.(custom_root / "delegate") *)
end
module I = struct
let baking_priorities ctxt max_prio (level, pred_timestamp) =
Baking.baking_priorities ctxt level >>=? fun contract_list ->
let rec loop l acc priority =
if Compare.Int.(priority >= max_prio) then
return (List.rev acc)
else
let Misc.LCons (pk, next) = l in
let delegate = Signature.Public_key.hash pk in
begin
match pred_timestamp with
| None -> return None
| Some pred_timestamp ->
Baking.minimal_time ctxt priority pred_timestamp >>=? fun t ->
return (Some t)
end>>=? fun timestamp ->
let acc =
{ level = level.level ; delegate ; priority ; timestamp } :: acc in
next () >>=? fun l ->
loop l acc (priority+1) in
loop contract_list [] 0
let default_max_baking_priority ctxt arg =
let default = Constants.first_free_baking_slot ctxt in
match arg with
| None -> 2 * default
| Some m -> m
let baking_rights_for_level ctxt level max =
let max = default_max_baking_priority ctxt max in
Baking.baking_priorities ctxt level >>=? fun contract_list ->
let rec loop l n =
match n with
| 0 -> return []
| n ->
let Misc.LCons (h, t) = l in
t () >>=? fun t ->
loop t (pred n) >>=? fun t ->
return (Signature.Public_key.hash h :: t)
in
loop contract_list max >>=? fun prio ->
return (level.level, prio)
let baking_rights ctxt () max =
let level = Level.succ ctxt (Level.current ctxt) in
baking_rights_for_level ctxt level max >>=? fun (raw_level, slots) ->
begin
Lwt_list.filter_map_p (fun x -> x) @@
List.mapi
(fun prio c ->
let timestamp = Timestamp.current ctxt in
Baking.minimal_time ctxt prio timestamp >>= function
| Error _ -> Lwt.return None
| Ok minimal_timestamp -> Lwt.return (Some (c, minimal_timestamp)))
slots
end >>= fun timed_slots ->
return (raw_level, timed_slots)
let baking_rights_for_delegate
ctxt contract () (max_priority, min_level, max_level) =
let max_priority = default_max_baking_priority ctxt max_priority in
let current_level = Level.succ ctxt (Level.current ctxt) in
let min_level = match min_level with
| None -> current_level
| Some l -> Level.from_raw ctxt l in
let max_level =
match max_level with
| Some max_level -> Level.from_raw ctxt max_level
| None ->
Level.last_level_in_cycle ctxt @@
current_level.cycle in
let rec loop level =
if Level.(>) level max_level
then return []
else
loop (Level.succ ctxt level) >>=? fun t ->
Baking.first_baking_priorities
ctxt ~max_priority contract level >>=? fun priorities ->
let raw_level = level.level in
Error_monad.map_s
(fun priority ->
let timestamp = Timestamp.current ctxt in
Baking.minimal_time ctxt priority timestamp >>=? fun time ->
return (raw_level, priority, time))
priorities >>=? fun priorities ->
return (priorities @ t)
in
loop min_level
end
let remove_duplicated_delegates rights =
List.rev @@ fst @@
List.fold_left
(fun (acc, previous) r ->
if Signature.Public_key_hash.Set.mem r.delegate previous then
(acc, previous)
else
(r :: acc,
Signature.Public_key_hash.Set.add r.delegate previous))
([], Signature.Public_key_hash.Set.empty)
rights
let () =
let open Services_registration in
register0 S.rights I.baking_rights ;
register1 S.rights_for_level begin fun ctxt raw_level () max ->
let level = Level.from_raw ctxt raw_level in
I.baking_rights_for_level ctxt level max
end;
register1 S.rights_for_delegate I.baking_rights_for_delegate
register0 S.baking_rights begin fun ctxt q () ->
requested_levels
~default:
(Level.succ ctxt (Level.current ctxt), Some (Timestamp.current ctxt))
ctxt q.cycles q.levels >>=? fun levels ->
let max_priority =
match q.max_priority with
| None -> 64
| Some max -> max in
map_p (baking_priorities ctxt max_priority) levels >>=? fun rights ->
let rights =
if q.all then
rights
else
List.map remove_duplicated_delegates rights in
let rights = List.concat rights in
match q.delegates with
| [] -> return rights
| _ :: _ as delegates ->
let is_requested p =
List.exists (Signature.Public_key_hash.equal p.delegate) delegates in
return (List.filter is_requested rights)
end
let rights ctxt ?max_priority block =
RPC_context.make_call0 S.rights ctxt block () max_priority
let rights_for_level ctxt ?max_priority block level =
RPC_context.make_call1 S.rights_for_level ctxt block level () max_priority
let rights_for_delegate ctxt ?max_priority ?first_level ?last_level block delegate =
RPC_context.make_call1 S.rights_for_delegate ctxt block delegate ()
(max_priority, first_level, last_level)
let get ctxt
?(levels = []) ?(cycles = []) ?(delegates = []) ?(all = false)
?max_priority block =
RPC_context.make_call0 S.baking_rights ctxt block
{ levels ; cycles ; delegates ; max_priority ; all }
()
end
module Endorser = struct
module Endorsing_rights = struct
type t = {
level: Raw_level.t ;
delegate: Signature.Public_key_hash.t ;
slots: int list ;
estimated_time: Time.t option ;
}
let encoding =
let open Data_encoding in
conv
(fun { level ; delegate ; slots ; estimated_time } ->
(level, delegate, slots, estimated_time))
(fun (level, delegate, slots, estimated_time) ->
{ level ; delegate ; slots ; estimated_time })
(obj4
(req "level" Raw_level.encoding)
(req "delegate" Signature.Public_key_hash.encoding)
(req "slots" (list uint16))
(opt "estimated_time" Timestamp.encoding))
module S = struct
open Data_encoding
let custom_root =
RPC_path.(open_root / "helpers" / "rights" / "endorsement")
RPC_path.(open_root / "helpers" / "endorsing_rights")
let slot_encoding =
(obj2
(req "level" Raw_level.encoding)
(req "priority" int31))
type endorsing_rights_query = {
levels: Raw_level.t list ;
cycles: Cycle.t list ;
delegates: Signature.Public_key_hash.t list ;
}
let rights =
RPC_service.post_service
~description:
"List delegates allowed to endorse for the current block."
~query: RPC_query.empty
~input: (obj1 (opt "max_priority" int31))
~output: (obj2
(req "level" Raw_level.encoding)
(req "delegates"
(list Signature.Public_key_hash.encoding)))
let endorsing_rights_query =
let open RPC_query in
query (fun levels cycles delegates ->
{ levels ; cycles ; delegates })
|+ multi_field "level" Raw_level.arg (fun t -> t.levels)
|+ multi_field "cycle" Cycle.arg (fun t -> t.cycles)
|+ multi_field "delegate" Signature.Public_key_hash.rpc_arg (fun t -> t.delegates)
|> seal
let endorsing_rights =
RPC_service.get_service
~description: "...FIXME..."
~query: endorsing_rights_query
~output: (list encoding)
custom_root
let rights_for_level =
RPC_service.post_service
~description:
"List delegates allowed to endorse blocks for a given level."
~query: RPC_query.empty
~input: (obj1 (opt "max_priority" int31))
~output: (obj2
(req "level" Raw_level.encoding)
(req "delegates"
(list Signature.Public_key_hash.encoding)))
RPC_path.(custom_root / "level" /: Raw_level.arg)
(* let levels = *)
(* RPC_service.post_service *)
(* ~description: *)
(* "List level for which we might computed endorsement rights." *)
(* ~query: RPC_query.empty *)
(* ~input: empty *)
(* ~output: (obj1 (req "levels" (list Raw_level.encoding))) *)
(* RPC_path.(custom_root / "level") *)
let rights_for_delegate =
RPC_service.post_service
~description: "Compute endorsement rights for a given delegate."
~query: RPC_query.empty
~input: slots_range_encoding
~output: (Data_encoding.list slot_encoding)
RPC_path.(custom_root / "delegate" /: Signature.Public_key_hash.rpc_arg)
(* let delegates = *)
(* RPC_service.post_service *)
(* ~description: *)
(* "List delegates with endorsement rights." *)
(* ~query: RPC_query.empty *)
(* ~input: empty *)
(* ~output: (obj1 (req "delegates" *)
(* (list Signature.Public_key_hash.encoding))) *)
(* RPC_path.(custom_root / "delegate") *)
end
module I = struct
let default_max_endorsement_priority ctxt arg =
let default = Constants.endorsers_per_block ctxt in
match arg with
| None -> default
| Some m -> m
let endorsement_rights ctxt level max =
let max = default_max_endorsement_priority ctxt max in
Baking.endorsement_priorities ctxt level >>=? fun contract_list ->
let rec loop l n =
match n with
| 0 -> return []
| n ->
let Misc.LCons (h, t) = l in
t () >>=? fun t ->
loop t (pred n) >>=? fun t ->
return (Signature.Public_key.hash h :: t)
in
loop contract_list max >>=? fun prio ->
return (level.level, prio)
let endorsement_rights_for_delegate
ctxt contract () (max_priority, min_level, max_level) =
let current_level = Level.current ctxt in
let max_priority = default_max_endorsement_priority ctxt max_priority in
let min_level = match min_level with
| None -> current_level
| Some l -> Level.from_raw ctxt l in
let max_level =
match max_level with
| None -> min_level
| Some l -> Level.from_raw ctxt l in
let rec loop level =
if Level.(>) level max_level
then return []
else
loop (Level.succ ctxt level) >>=? fun t ->
Baking.first_endorsement_slots
ctxt ~max_priority contract level >>=? fun slots ->
let raw_level = level.level in
let slots = List.rev_map (fun slot -> (raw_level, slot)) slots in
return (List.rev_append slots t)
in
loop min_level
end
let endorsement_slots ctxt (level, estimated_time) =
let max_slot = Constants.endorsers_per_block ctxt in
Baking.endorsement_priorities ctxt level >>=? fun contract_list ->
let build (delegate, slots) = {
level = level.level ; delegate ; slots ; estimated_time
} in
let rec loop l map slot =
if Compare.Int.(slot >= max_slot) then
return (List.map build (Signature.Public_key_hash.Map.bindings map))
else
let Misc.LCons (pk, next) = l in
let delegate = Signature.Public_key.hash pk in
let slots =
match Signature.Public_key_hash.Map.find_opt delegate map with
| None -> [slot]
| Some slots -> slot :: slots in
let map = Signature.Public_key_hash.Map.add delegate slots map in
next () >>=? fun l ->
loop l map (slot+1) in
loop contract_list Signature.Public_key_hash.Map.empty 0
let () =
let open Services_registration in
register0 S.rights begin fun ctxt () max ->
let level = Level.current ctxt in
I.endorsement_rights ctxt level max
end ;
register1 S.rights_for_level begin fun ctxt raw_level () max ->
let level = Level.from_raw ctxt raw_level in
I.endorsement_rights ctxt level max
end ;
register1 S.rights_for_delegate I.endorsement_rights_for_delegate
register0 S.endorsing_rights begin fun ctxt q () ->
requested_levels
~default: (Level.current ctxt, Some (Timestamp.current ctxt))
ctxt q.cycles q.levels >>=? fun levels ->
map_p (endorsement_slots ctxt) levels >>=? fun rights ->
let rights = List.concat rights in
match q.delegates with
| [] -> return rights
| _ :: _ as delegates ->
let is_requested p =
List.exists (Signature.Public_key_hash.equal p.delegate) delegates in
return (List.filter is_requested rights)
end
let rights ctxt ?max_priority block =
RPC_context.make_call0 S.rights ctxt block () max_priority
let rights_for_level ctxt ?max_priority block level =
RPC_context.make_call1 S.rights_for_level ctxt block level () max_priority
let rights_for_delegate ctxt ?max_priority ?first_level ?last_level block delegate =
RPC_context.make_call1 S.rights_for_delegate ctxt block delegate ()
(max_priority, first_level, last_level)
let get ctxt
?(levels = []) ?(cycles = []) ?(delegates = []) block =
RPC_context.make_call0 S.endorsing_rights ctxt block
{ levels ; cycles ; delegates }
()
end
let endorsement_rights ctxt level =
Endorsing_rights.endorsement_slots ctxt (level, None) >>=? fun l ->
return (List.map (fun { Endorsing_rights.delegate ; _ } -> delegate) l)
let baking_rights ctxt max_priority =
let max = match max_priority with None -> 64 | Some m -> m in
let level = Level.current ctxt in
Baking_rights.baking_priorities ctxt max (level, None) >>=? fun l ->
return (level.level,
List.map
(fun { Baking_rights.delegate ; timestamp ; _ } ->
(delegate, timestamp)) l)
let baking_rights = Baker.I.baking_rights
let endorsement_rights = Endorser.I.endorsement_rights

View File

@ -68,50 +68,73 @@ val grace_period:
Cycle.t shell_tzresult Lwt.t
module Baker : sig
module Baking_rights : sig
val rights:
'a #RPC_context.simple -> ?max_priority:int -> 'a ->
(Raw_level.t * (Signature.Public_key_hash.t * Time.t) list) shell_tzresult Lwt.t
type t = {
level: Raw_level.t ;
delegate: Signature.Public_key_hash.t ;
priority: int ;
timestamp: Timestamp.t option ;
}
val rights_for_level:
'a #RPC_context.simple -> ?max_priority:int -> 'a -> Raw_level.t ->
(Raw_level.t * Signature.Public_key_hash.t list) shell_tzresult Lwt.t
(** Compute the baking rights. By default, it computes the baking
rights for the next block and only returns the first available
priority for bakers that appears in the 64 first priorities.
val rights_for_delegate:
The optional arguments [levels] and [cycles] allows to compute
baking for an explicit list of levels or for all the levels of the given
cycles.
The optional argument [delegates] allows to filter
the non-explicitly listed delegates out of the resulting list.
When [all=false], the function only returns the minimal priority
for each delegates. When [all=true], all priorities are returned. *)
val get:
'a #RPC_context.simple ->
?max_priority:int -> ?first_level:Raw_level.t -> ?last_level:Raw_level.t ->
'a -> Signature.Public_key_hash.t ->
(Raw_level.t * int * Time.t) list shell_tzresult Lwt.t
?levels: Raw_level.t list ->
?cycles: Cycle.t list ->
?delegates: Signature.public_key_hash list ->
?all: bool ->
?max_priority: int ->
'a -> t list shell_tzresult Lwt.t
end
module Endorser : sig
module Endorsing_rights : sig
val rights:
'a #RPC_context.simple -> ?max_priority:int -> 'a ->
(Raw_level.t * Signature.Public_key_hash.t list) shell_tzresult Lwt.t
type t = {
level: Raw_level.t ;
delegate: Signature.Public_key_hash.t ;
slots: int list ;
estimated_time: Timestamp.t option ;
}
val rights_for_level:
'a #RPC_context.simple -> ?max_priority:int -> 'a -> Raw_level.t ->
(Raw_level.t * Signature.Public_key_hash.t list) shell_tzresult Lwt.t
(** Compute the endorsing rights. By default, it computes the
endorsing rights for the next block.
val rights_for_delegate:
The optional arguments [levels] and [cycles] allows to compute
baking for an explicit list of levels or for all the levels of
the given cycles.
The optional argument [delegates] allows to filter the
non-explicitly listed delegates out of the resulting list.. *)
val get:
'a #RPC_context.simple ->
?max_priority:int -> ?first_level:Raw_level.t -> ?last_level:Raw_level.t ->
'a -> Signature.Public_key_hash.t ->
(Raw_level.t * int) list shell_tzresult Lwt.t
?levels: Raw_level.t list ->
?cycles: Cycle.t list ->
?delegates: Signature.public_key_hash list ->
'a -> t list shell_tzresult Lwt.t
end
(* temporary export *)
(* temporary export for deprecated unit test *)
val endorsement_rights:
Alpha_context.t ->
Level.t ->
int option -> (Raw_level.t * public_key_hash list) tzresult Lwt.t
public_key_hash list tzresult Lwt.t
val baking_rights:
Alpha_context.t ->
unit ->
int option ->
(Raw_level.t * (public_key_hash * Time.t) list) tzresult Lwt.t
(Raw_level.t * (public_key_hash * Time.t option) list) tzresult Lwt.t

View File

@ -30,14 +30,8 @@ let get_first_different_bakers ctxt =
let get_first_different_endorsers ctxt =
Context.get_endorsers ctxt >>=? fun endorsers ->
let endorsers = List.combine endorsers (0--((List.length endorsers) - 1)) in
let endorser_1 = List.hd endorsers in
let endorser_2 =
List.find (fun (endorser, _slot) ->
Signature.Public_key_hash.(<>)
(fst endorser_1) endorser)
(List.tl endorsers)
in
let endorser_1 = (List.hd endorsers).delegate in
let endorser_2 = (List.hd (List.tl endorsers)).delegate in
return (endorser_1, endorser_2)
(** Bake two block at the same level using the same policy (i.e. same

View File

@ -30,14 +30,8 @@ let get_first_different_bakers ctxt =
let get_first_different_endorsers ctxt =
Context.get_endorsers ctxt >>=? fun endorsers ->
let endorsers = List.combine endorsers (0--((List.length endorsers) - 1)) in
let endorser_1 = List.hd endorsers in
let endorser_2 =
List.find (fun (endorser, _slot) ->
Signature.Public_key_hash.(<>)
(fst endorser_1) endorser)
(List.tl endorsers)
in
let endorser_1 = (List.hd endorsers) in
let endorser_2 = (List.hd (List.tl endorsers)) in
return (endorser_1, endorser_2)
let block_fork b =
@ -59,8 +53,8 @@ let valid_double_endorsement_evidence () =
block_fork b >>=? fun (blk_a, blk_b) ->
Context.get_endorser (B blk_a) 0 >>=? fun delegate ->
Op.endorsement ~delegate (B blk_a) 0 >>=? fun endorsement_a ->
Op.endorsement ~delegate (B blk_b) 0 >>=? fun endorsement_b ->
Op.endorsement ~delegate (B blk_a) [0] >>=? fun endorsement_a ->
Op.endorsement ~delegate (B blk_b) [0] >>=? fun endorsement_b ->
Block.bake ~operations:[endorsement_a] blk_a >>=? fun blk_a ->
(* Block.bake ~operations:[endorsement_b] blk_b >>=? fun _ -> *)
@ -89,7 +83,7 @@ let invalid_double_endorsement () =
Context.init 10 >>=? fun (b, _) ->
Block.bake b >>=? fun b ->
Op.endorsement (B b) 0 >>=? fun endorsement ->
Op.endorsement (B b) [0] >>=? fun endorsement ->
Block.bake ~operation:endorsement b >>=? fun b ->
Op.double_endorsement (B b) endorsement endorsement >>=? fun operation ->
@ -105,8 +99,8 @@ let too_early_double_endorsement_evidence () =
block_fork b >>=? fun (blk_a, blk_b) ->
Context.get_endorser (B blk_a) 0 >>=? fun delegate ->
Op.endorsement ~delegate (B blk_a) 0 >>=? fun endorsement_a ->
Op.endorsement ~delegate (B blk_b) 0 >>=? fun endorsement_b ->
Op.endorsement ~delegate (B blk_a) [0] >>=? fun endorsement_a ->
Op.endorsement ~delegate (B blk_b) [0] >>=? fun endorsement_b ->
Op.double_endorsement (B b) endorsement_a endorsement_b >>=? fun operation ->
Block.bake ~operation b >>= fun res ->
@ -124,8 +118,8 @@ let too_late_double_endorsement_evidence () =
block_fork b >>=? fun (blk_a, blk_b) ->
Context.get_endorser (B blk_a) 0 >>=? fun delegate ->
Op.endorsement ~delegate (B blk_a) 0 >>=? fun endorsement_a ->
Op.endorsement ~delegate (B blk_b) 0 >>=? fun endorsement_b ->
Op.endorsement ~delegate (B blk_a) [0] >>=? fun endorsement_a ->
Op.endorsement ~delegate (B blk_b) [0] >>=? fun endorsement_b ->
fold_left_s (fun blk _ -> Block.bake_until_cycle_end blk)
blk_a (1 -- (preserved_cycles + 1)) >>=? fun blk ->
@ -143,10 +137,10 @@ let different_delegates () =
block_fork b >>=? fun (blk_a, blk_b) ->
get_first_different_endorsers (B blk_a)
>>=? fun ((endorser_a, slot_a), (endorser_b, slot_b)) ->
>>=? fun (endorser_a, endorser_b) ->
Op.endorsement ~delegate:endorser_a (B blk_a) slot_a >>=? fun e_a ->
Op.endorsement ~delegate:endorser_b (B blk_b) slot_b >>=? fun e_b ->
Op.endorsement ~delegate:endorser_a.delegate (B blk_a) endorser_a.slots >>=? fun e_a ->
Op.endorsement ~delegate:endorser_b.delegate (B blk_b) endorser_b.slots >>=? fun e_b ->
Op.double_endorsement (B blk_a) e_a e_b >>=? fun operation ->
Block.bake ~operation blk_a >>= fun res ->
Assert.proto_error ~loc:__LOC__ res begin function
@ -160,10 +154,10 @@ let wrong_delegate () =
block_fork b >>=? fun (blk_a, blk_b) ->
get_first_different_endorsers (B blk_a)
>>=? fun ((_endorser_a, slot_a), (endorser_b, slot_b)) ->
>>=? fun (endorser_a, endorser_b) ->
Op.endorsement ~delegate:endorser_b (B blk_a) slot_a >>=? fun endorsement_a ->
Op.endorsement ~delegate:endorser_b (B blk_b) slot_b >>=? fun endorsement_b ->
Op.endorsement ~delegate:endorser_b.delegate (B blk_a) endorser_a.slots >>=? fun endorsement_a ->
Op.endorsement ~delegate:endorser_b.delegate (B blk_b) endorser_b.slots >>=? fun endorsement_b ->
Op.double_endorsement (B blk_a) endorsement_a endorsement_b >>=? fun operation ->
Block.bake ~operation blk_a >>= fun e ->

View File

@ -61,16 +61,17 @@ let assert_endorser_balance_consistency ~loc ?(priority=0) ?(nb_baking=0) ~nb_en
(** Apply a single endorsement from the slot 0 endorser *)
let simple_endorsement () =
Context.init 5 >>=? fun (b, _) ->
let slot = 0 in
Incremental.begin_construction b >>=? fun inc ->
let slot = 1 in
Context.get_endorser (B b) slot >>=? fun endorser ->
Op.endorsement ~delegate:endorser (I inc) slot >>=? fun op ->
Incremental.add_operation inc op >>=? fun inc ->
Context.Contract.balance (B b) (Contract.implicit_contract endorser) >>=? fun initial_balance ->
Op.endorsement ~delegate:endorser (B b) [slot] >>=? fun op ->
Context.Contract.balance (B b)
(Contract.implicit_contract endorser) >>=? fun initial_balance ->
Block.bake
~policy:(Excluding [endorser])
~operations:[op]
b >>=? fun b2 ->
assert_endorser_balance_consistency ~loc:__LOC__
(I inc) ~nb_endorsement:1 endorser initial_balance
(B b2) ~nb_endorsement:1 endorser initial_balance
(** Apply a maximum number of endorsement. A endorser can be selected
twice. *)
@ -80,29 +81,25 @@ let max_endorsement () =
Context.get_endorsers (B b) >>=? fun endorsers ->
Assert.equal_int ~loc:__LOC__
(List.length endorsers) endorsers_per_block >>=? fun () ->
(List.length (List.concat (List.map (fun { Alpha_services.Delegate.Endorsing_rights.slots } -> slots) endorsers))) endorsers_per_block >>=? fun () ->
fold_left_s (fun (ops, balances) (delegate, slot) ->
fold_left_s (fun (delegates, ops, balances) (endorser : Alpha_services.Delegate.Endorsing_rights.t) ->
let delegate = endorser.delegate in
Context.Contract.balance (B b) (Contract.implicit_contract delegate) >>=? fun balance ->
Op.endorsement ~delegate (B b) slot >>=? fun op ->
return (op :: ops, balance :: balances)
Op.endorsement ~delegate (B b) endorser.slots >>=? fun op ->
return (delegate :: delegates, op :: ops, (List.length endorser.slots, balance) :: balances)
)
([], [])
(List.combine endorsers (0--(endorsers_per_block - 1))) >>=? fun (ops, previous_balances) ->
([], [], [])
endorsers >>=? fun (delegates, ops, previous_balances) ->
Block.bake ~policy:(Excluding endorsers) ~operations:(List.rev ops) b >>=? fun b ->
let count acc =
List.find_all ((=) acc) endorsers |> List.length
in
Block.bake ~policy:(Excluding delegates) ~operations:(List.rev ops) b >>=? fun b ->
(* One account can endorse more than one time per level, we must
check that the bonds are summed up *)
iter_s (fun (endorser_account, previous_balance) ->
let nb_endorsement = count endorser_account in
iter_s (fun (endorser_account, (nb_endorsement, previous_balance)) ->
assert_endorser_balance_consistency ~loc:__LOC__
(B b) ~nb_endorsement endorser_account previous_balance
) (List.combine endorsers (List.rev previous_balances))
) (List.combine delegates previous_balances)
(** Check that an endorser balance is consistent with a different piority *)
let consistent_priority () =
@ -118,7 +115,7 @@ let consistent_priority () =
in
Context.Contract.balance (B b) (Contract.implicit_contract endorser) >>=? fun balance ->
Op.endorsement ~delegate:endorser (B b) slot >>=? fun operation ->
Op.endorsement ~delegate:endorser (B b) [slot] >>=? fun operation ->
Block.bake ~policy:( Excluding [ endorser ] ) ~operation b >>=? fun b ->
assert_endorser_balance_consistency ~loc:__LOC__ ~priority:15
@ -142,7 +139,7 @@ let consistent_priorities () =
in
Context.Contract.balance (B b) (Contract.implicit_contract endorser) >>=? fun balance ->
Op.endorsement ~delegate:endorser (B b) slot >>=? fun operation ->
Op.endorsement ~delegate:endorser (B b) [slot] >>=? fun operation ->
Block.bake ~policy:( Excluding [ endorser ] ) ~operation b >>=? fun b ->
assert_endorser_balance_consistency ~loc:__LOC__ ~priority
@ -158,7 +155,7 @@ let reward_retrieval () =
let slot = 0 in
Context.get_endorser (B b) slot >>=? fun endorser ->
Context.Contract.balance (B b) (Contract.implicit_contract endorser) >>=? fun balance ->
Op.endorsement ~delegate:endorser (B b) slot >>=? fun operation ->
Op.endorsement ~delegate:endorser (B b) [slot] >>=? fun operation ->
Block.bake ~policy:(Excluding [ endorser ]) ~operation b >>=? fun b ->
(* Bake (preserved_cycles + 1) cycles *)
fold_left_s (fun b _ ->
@ -178,7 +175,7 @@ let wrong_endorsement_predecessor () =
Context.get_endorser (B b) 0 >>=? fun genesis_endorser ->
Block.bake b >>=? fun b' ->
Op.endorsement ~delegate:genesis_endorser ~signing_context:(B b') (B b) 0 >>=? fun operation ->
Op.endorsement ~delegate:genesis_endorser ~signing_context:(B b') (B b) [0] >>=? fun operation ->
Block.bake ~operation b' >>= fun res ->
Assert.proto_error ~loc:__LOC__ res begin function
@ -192,7 +189,7 @@ let invalid_endorsement_level () =
Context.init 5 >>=? fun (b, _) ->
Context.get_level (B b) >>=? fun genesis_level ->
Block.bake b >>=? fun b ->
Op.endorsement ~level:genesis_level (B b) 0 >>=? fun operation ->
Op.endorsement ~level:genesis_level (B b) [0] >>=? fun operation ->
Block.bake ~operation b >>= fun res ->
Assert.proto_error ~loc:__LOC__ res begin function
@ -204,9 +201,9 @@ let invalid_endorsement_level () =
let duplicate_endorsement () =
Context.init 5 >>=? fun (b, _) ->
Incremental.begin_construction b >>=? fun inc ->
Op.endorsement (B b) 0 >>=? fun operation ->
Op.endorsement (B b) [0] >>=? fun operation ->
Incremental.add_operation inc operation >>=? fun inc ->
Op.endorsement (B b) 0 >>=? fun operation ->
Op.endorsement (B b) [0] >>=? fun operation ->
Incremental.add_operation inc operation >>= fun res ->
Assert.proto_error ~loc:__LOC__ res begin function
@ -219,8 +216,8 @@ let invalid_endorsement_slot () =
Context.init 64 >>=? fun (b, _) ->
Context.get_constants (B b) >>=? fun Constants.
{ parametric = { endorsers_per_block ; _ } ; _ } ->
Op.endorsement (B b) (endorsers_per_block + 1) >>=? fun operation ->
Context.get_endorser (B b) 0 >>=? fun endorser ->
Op.endorsement ~delegate:endorser (B b) [endorsers_per_block + 1] >>=? fun operation ->
Block.bake ~operation b >>= fun res ->

View File

@ -43,26 +43,31 @@ type baker_policy =
| Excluding of public_key_hash list
let get_next_baker_by_priority priority block =
Alpha_services.Delegate.Baker.rights rpc_ctxt
~max_priority:(priority+1) block >>=? fun (_, bakers) ->
let pkh, timestamp = List.nth bakers priority in
return (pkh, priority, timestamp)
Alpha_services.Delegate.Baking_rights.get rpc_ctxt
~all:true
~max_priority:(priority+1) block >>=? fun bakers ->
let { Alpha_services.Delegate.Baking_rights.delegate = pkh ;
timestamp} = List.find (fun { Alpha_services.Delegate.Baking_rights.priority = p } -> p = priority) bakers in
return (pkh, priority, Option.unopt_exn (Failure "") timestamp)
let get_next_baker_by_account pkh block =
Alpha_services.Delegate.Baker.rights rpc_ctxt
~max_priority:30 block >>=? fun (_, bakers) ->
let ((_pkh, timestamp), priority) = Test_utils.findi
(fun (pkh', _) -> Signature.Public_key_hash.equal pkh pkh')
bakers in
return (pkh, priority, timestamp)
Alpha_services.Delegate.Baking_rights.get rpc_ctxt
~delegates:[pkh]
~max_priority:256 block >>=? fun bakers ->
let { Alpha_services.Delegate.Baking_rights.delegate = pkh ;
timestamp ; priority } = List.hd bakers in
return (pkh, priority, Option.unopt_exn (Failure "") timestamp)
let get_next_baker_excluding excludes block =
Alpha_services.Delegate.Baker.rights rpc_ctxt
~max_priority:((List.length excludes)+10) block >>=? fun (_, bakers) ->
let (pkh,timestamp),priority = Test_utils.findi
(fun (pkh, _) -> not (List.mem pkh excludes))
Alpha_services.Delegate.Baking_rights.get rpc_ctxt
~max_priority:256 block >>=? fun bakers ->
let { Alpha_services.Delegate.Baking_rights.delegate = pkh ;
timestamp ; priority } =
List.find
(fun { Alpha_services.Delegate.Baking_rights.delegate } ->
not (List.mem delegate excludes))
bakers in
return (pkh, priority, timestamp)
return (pkh, priority, Option.unopt_exn (Failure "") timestamp)
let dispatch_policy = function
| By_priority p -> get_next_baker_by_priority p
@ -112,9 +117,14 @@ module Forge = struct
(* Finds the baker that should sign from the header *)
let baker_of_a_block header =
let priority = header.contents.priority in
Alpha_services.Delegate.Baker.rights rpc_ctxt
~max_priority:(priority+1) pred >>=? fun (_, bakers) ->
let pkh, _ = List.nth bakers priority in
Alpha_services.Delegate.Baking_rights.get rpc_ctxt
~all:true
~max_priority:(priority+1)
pred >>=? fun bakers ->
let { Alpha_services.Delegate.Baking_rights.delegate = pkh } =
List.find
(fun { Alpha_services.Delegate.Baking_rights.priority = p } -> p = priority)
bakers in
Account.find pkh
in
baker_of_a_block { shell ; contents } >>=? fun delegate ->

View File

@ -64,21 +64,23 @@ let rpc_ctxt = object
end
let get_endorsers ctxt =
Alpha_services.Delegate.Endorser.rights
rpc_ctxt ctxt >>=? fun (_level, endorsers) ->
return endorsers
Alpha_services.Delegate.Endorsing_rights.get rpc_ctxt ctxt
let get_endorser ctxt slot =
Alpha_services.Delegate.Endorser.rights
~max_priority:(slot+1) rpc_ctxt ctxt >>=? fun (_level, endorsers) ->
try return (List.nth endorsers slot)
Alpha_services.Delegate.Endorsing_rights.get
rpc_ctxt ctxt >>=? fun endorsers ->
try return (List.find (fun {Alpha_services.Delegate.Endorsing_rights.slots} -> List.mem slot slots) endorsers).delegate
with _ ->
failwith "Failed to lookup endorsers for ctxt %a, slot %d."
Block_hash.pp_short (branch ctxt) slot
let get_bakers ctxt =
Alpha_services.Delegate.Baker.rights rpc_ctxt ~max_priority:30 ctxt >>=? fun (_, bakers) ->
return (List.map fst bakers)
Alpha_services.Delegate.Baking_rights.get
~max_priority:256
rpc_ctxt ctxt >>=? fun bakers ->
return (List.map
(fun p -> p.Alpha_services.Delegate.Baking_rights.delegate)
bakers)
let get_constants b =
Alpha_services.Constants.all rpc_ctxt b

View File

@ -18,7 +18,7 @@ val branch: t -> Block_hash.t
val get_level: t -> Raw_level.t tzresult Lwt.t
val get_endorsers: t -> public_key_hash list tzresult Lwt.t
val get_endorsers: t -> Alpha_services.Delegate.Endorsing_rights.t list tzresult Lwt.t
val get_endorser: t -> int -> public_key_hash tzresult Lwt.t

View File

@ -25,10 +25,10 @@ let sign ?(watermark = Signature.Generic_operation) sk ctxt contents =
}
let endorsement ?delegate ?level ctxt =
fun ?(signing_context=ctxt) slot ->
fun ?(signing_context=ctxt) slots ->
begin
match delegate with
| None -> Context.get_endorser ctxt slot
| None -> Context.get_endorser ctxt (List.hd slots)
| Some delegate -> return delegate
end >>=? fun delegate_pkh ->
Account.find delegate_pkh >>=? fun delegate ->
@ -38,7 +38,7 @@ let endorsement ?delegate ?level ctxt =
| Some level -> return level
end >>=? fun level ->
let op =
let operations = Endorsements { block = Context.branch ctxt ; level ; slots = [slot] } in
let operations = Endorsements { block = Context.branch ctxt ; level ; slots = slots } in
Sourced_operation (Consensus_operation operations) in
return (sign ~watermark:Signature.Endorsement delegate.sk signing_context op)
@ -107,7 +107,7 @@ let miss_signed_endorsement ?level ctxt slot =
end >>=? fun level ->
Context.get_endorser ctxt slot >>=? fun real_delegate_pkh ->
let delegate = Account.find_alternate real_delegate_pkh in
endorsement ~delegate:delegate.pkh ~level ctxt slot
endorsement ~delegate:delegate.pkh ~level ctxt [slot]
let transaction ?fee ?gas_limit ?storage_limit ?parameters ctxt
(src:Contract.t) (dst:Contract.t)

View File

@ -14,7 +14,7 @@ val endorsement:
?delegate:public_key_hash ->
?level:Raw_level.t ->
Context.t -> ?signing_context:Context.t ->
int -> Operation.t tzresult Lwt.t
int list -> Operation.t tzresult Lwt.t
val miss_signed_endorsement:
?level:Raw_level.t ->