Endorser: trust the node to choose the head
This commit is contained in:
parent
9d021032e1
commit
c55a462233
@ -37,7 +37,6 @@ let inject_endorsement
|
|||||||
State.record cctxt pkh level >>=? fun () ->
|
State.record cctxt pkh level >>=? fun () ->
|
||||||
return oph
|
return oph
|
||||||
|
|
||||||
|
|
||||||
let check_endorsement cctxt level pkh =
|
let check_endorsement cctxt level pkh =
|
||||||
State.get cctxt pkh >>=? function
|
State.get cctxt pkh >>=? function
|
||||||
| None -> return ()
|
| None -> return ()
|
||||||
@ -91,19 +90,17 @@ let forge_endorsement (cctxt : #Proto_alpha.full)
|
|||||||
type state = {
|
type state = {
|
||||||
delegates: public_key_hash list ;
|
delegates: public_key_hash list ;
|
||||||
delay: int64 ;
|
delay: int64 ;
|
||||||
(* invariant: only one slot per delegate *)
|
to_endorse : endorsement Signature.Public_key_hash.Table.t ;
|
||||||
mutable to_endorse : endorsement list ;
|
|
||||||
}
|
}
|
||||||
and endorsement = {
|
and endorsement = {
|
||||||
time: Time.t ;
|
time: Time.t ;
|
||||||
timeout: unit Lwt.t ;
|
timeout: unit Lwt.t ;
|
||||||
delegate: public_key_hash ;
|
delegate: public_key_hash ;
|
||||||
block: Client_baking_blocks.block_info ;
|
block: Client_baking_blocks.block_info ;
|
||||||
slots: int list ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let create_state delegates delay =
|
let create_state delegates delay =
|
||||||
{ delegates ; delay ; to_endorse=[] }
|
{ delegates ; delay ; to_endorse = Signature.Public_key_hash.Table.create 5 }
|
||||||
|
|
||||||
let get_delegates cctxt state =
|
let get_delegates cctxt state =
|
||||||
match state.delegates with
|
match state.delegates with
|
||||||
@ -113,15 +110,13 @@ let get_delegates cctxt state =
|
|||||||
| _ :: _ as delegates ->
|
| _ :: _ as delegates ->
|
||||||
return delegates
|
return delegates
|
||||||
|
|
||||||
let endorse_for_delegate cctxt { delegate ; block ; slots ; } =
|
let endorse_for_delegate cctxt { delegate ; block } =
|
||||||
let hash = block.hash in
|
let { Client_baking_blocks.hash ; level } = block in
|
||||||
let b = `Hash (hash, 0) in
|
let b = `Hash (hash, 0) in
|
||||||
let level = block.level in
|
|
||||||
Client_keys.get_key cctxt delegate >>=? fun (name, _pk, sk) ->
|
Client_keys.get_key cctxt delegate >>=? fun (name, _pk, sk) ->
|
||||||
lwt_debug "Endorsing %a for %s (level %a using %d slots)!"
|
lwt_debug "Endorsing %a for %s (level %a)!"
|
||||||
Block_hash.pp_short hash name
|
Block_hash.pp_short hash name
|
||||||
Raw_level.pp level
|
Raw_level.pp level >>= fun () ->
|
||||||
(List.length slots) >>= fun () ->
|
|
||||||
inject_endorsement cctxt
|
inject_endorsement cctxt
|
||||||
b hash level
|
b hash level
|
||||||
sk delegate >>=? fun oph ->
|
sk delegate >>=? fun oph ->
|
||||||
@ -139,26 +134,21 @@ let endorse_for_delegate cctxt { delegate ; block ; slots ; } =
|
|||||||
Operation_hash.pp_short oph >>= fun () ->
|
Operation_hash.pp_short oph >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let endorse_for cctxt = function
|
let endorse_for cctxt table =
|
||||||
| [] -> return []
|
let done_waiting = ref [] in
|
||||||
| endorsements ->
|
Signature.Public_key_hash.Table.filter_map_inplace
|
||||||
let done_waiting, still_waiting, errored =
|
(fun _ ({ timeout } as endorsement) ->
|
||||||
List.fold_left
|
|
||||||
(fun (r, s, f) ({ timeout } as endorsement) -> match Lwt.state timeout with
|
|
||||||
| Lwt.Return () -> (endorsement :: r, s, f)
|
|
||||||
| Lwt.Sleep -> (r, endorsement :: s, f)
|
|
||||||
| Lwt.Fail _ -> (r, s, endorsement :: f)
|
|
||||||
)
|
|
||||||
([], [], [])
|
|
||||||
endorsements
|
|
||||||
in
|
|
||||||
iter_p (endorse_for_delegate cctxt) done_waiting >>=? fun () ->
|
|
||||||
Lwt_list.iter_p (fun {timeout} ->
|
|
||||||
match Lwt.state timeout with
|
match Lwt.state timeout with
|
||||||
| Lwt.Fail f -> lwt_log_error "Endorsement failure: %s" (Printexc.to_string f)
|
| Lwt.Return () ->
|
||||||
| _ -> Lwt.return_unit) errored >>= fun () ->
|
done_waiting := endorsement :: !done_waiting ;
|
||||||
return still_waiting
|
None
|
||||||
|
| Lwt.Sleep ->
|
||||||
|
Some endorsement
|
||||||
|
| Lwt.Fail exn ->
|
||||||
|
log_error "Endorsement failure: %s" (Printexc.to_string exn) ;
|
||||||
|
None)
|
||||||
|
table ;
|
||||||
|
iter_p (endorse_for_delegate cctxt) !done_waiting
|
||||||
|
|
||||||
let allowed_to_endorse cctxt state (block: Client_baking_blocks.block_info) delegate time =
|
let allowed_to_endorse cctxt state (block: Client_baking_blocks.block_info) delegate time =
|
||||||
Client_keys.Public_key_hash.name cctxt delegate >>=? fun name ->
|
Client_keys.Public_key_hash.name cctxt delegate >>=? fun name ->
|
||||||
@ -166,8 +156,7 @@ let allowed_to_endorse cctxt state (block: Client_baking_blocks.block_info) dele
|
|||||||
Block_hash.pp_short block.hash name >>= fun () ->
|
Block_hash.pp_short block.hash name >>= fun () ->
|
||||||
let b = `Hash (block.hash, 0) in
|
let b = `Hash (block.hash, 0) in
|
||||||
let level = block.level in
|
let level = block.level in
|
||||||
get_signing_slots cctxt b delegate level >>=? fun slots ->
|
get_signing_slots cctxt b delegate level >>=? function
|
||||||
match slots with
|
|
||||||
| None ->
|
| None ->
|
||||||
lwt_debug "No slot found for %a/%s"
|
lwt_debug "No slot found for %a/%s"
|
||||||
Block_hash.pp_short block.hash name >>= fun () ->
|
Block_hash.pp_short block.hash name >>= fun () ->
|
||||||
@ -178,40 +167,25 @@ let allowed_to_endorse cctxt state (block: Client_baking_blocks.block_info) dele
|
|||||||
previously_endorsed_level cctxt delegate level >>=? function
|
previously_endorsed_level cctxt delegate level >>=? function
|
||||||
| true ->
|
| true ->
|
||||||
lwt_debug "Level %a (or higher) previously endorsed: do not endorse."
|
lwt_debug "Level %a (or higher) previously endorsed: do not endorse."
|
||||||
Raw_level.pp level >>= return
|
Raw_level.pp level >>= fun () ->
|
||||||
|
return ()
|
||||||
| false ->
|
| false ->
|
||||||
match Client_baking_scheduling.sleep_until time with
|
match Client_baking_scheduling.sleep_until time with
|
||||||
| None ->
|
| None ->
|
||||||
lwt_debug "Endorsment opportunity is passed." >>= fun () ->
|
lwt_debug "Endorsment opportunity is passed." >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
| Some timeout ->
|
| Some timeout ->
|
||||||
let neu = { time ; timeout ; delegate ; block; slots } in
|
let neu = { time ; timeout ; delegate ; block } in
|
||||||
match List.find_opt (fun { delegate = d } -> delegate = d) state.to_endorse with
|
Signature.Public_key_hash.Table.add state.to_endorse delegate neu ;
|
||||||
| None ->
|
|
||||||
state.to_endorse <- neu :: state.to_endorse;
|
|
||||||
return ()
|
|
||||||
| Some old ->
|
|
||||||
if Fitness.compare old.block.fitness neu.block.fitness < 0 then begin
|
|
||||||
let without_old =
|
|
||||||
List.filter (fun to_end ->
|
|
||||||
to_end.block.hash <> old.block.hash)
|
|
||||||
state.to_endorse in
|
|
||||||
state.to_endorse <- neu :: without_old;
|
|
||||||
return ()
|
|
||||||
end else
|
|
||||||
lwt_debug "Block %a is not the fittest: do not endorse."
|
|
||||||
Block_hash.pp_short neu.block.hash >>= fun () ->
|
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let prepare_endorsement (cctxt : #Proto_alpha.full) ~(max_past:int64) state bi =
|
let prepare_endorsement (cctxt : #Proto_alpha.full) ~(max_past:int64) state bi =
|
||||||
get_delegates cctxt state >>=? fun delegates ->
|
get_delegates cctxt state >>=? fun delegates ->
|
||||||
|
Signature.Public_key_hash.Table.clear state.to_endorse ;
|
||||||
iter_p
|
iter_p
|
||||||
(fun delegate ->
|
(fun delegate ->
|
||||||
let open Client_baking_blocks in
|
let open Client_baking_blocks in
|
||||||
if Time.compare bi.timestamp (Time.now ()) > 0 then
|
if Time.diff (Time.now ()) bi.timestamp > max_past then
|
||||||
lwt_log_info "Ignore block %a: forged in the future"
|
|
||||||
Block_hash.pp_short bi.hash >>= return
|
|
||||||
else if Time.diff (Time.now ()) bi.timestamp > max_past then
|
|
||||||
lwt_log_info "Ignore block %a: forged too far the past"
|
lwt_log_info "Ignore block %a: forged too far the past"
|
||||||
Block_hash.pp_short bi.hash >>= return
|
Block_hash.pp_short bi.hash >>= return
|
||||||
else
|
else
|
||||||
@ -221,12 +195,13 @@ let prepare_endorsement (cctxt : #Proto_alpha.full) ~(max_past:int64) state bi
|
|||||||
delegates
|
delegates
|
||||||
|
|
||||||
let compute_timeout state =
|
let compute_timeout state =
|
||||||
match state.to_endorse with
|
match Signature.Public_key_hash.Table.fold
|
||||||
|
(fun _ v acc -> v :: acc)
|
||||||
|
state.to_endorse [] with
|
||||||
| [] -> Lwt_utils.never_ending ()
|
| [] -> Lwt_utils.never_ending ()
|
||||||
| to_ends ->
|
| to_ends ->
|
||||||
Lwt.choose (List.map (fun to_end -> to_end.timeout) to_ends)
|
Lwt.choose (List.map (fun to_end -> to_end.timeout) to_ends)
|
||||||
|
|
||||||
|
|
||||||
let check_error f =
|
let check_error f =
|
||||||
f >>= function
|
f >>= function
|
||||||
| Ok () -> Lwt.return_unit
|
| Ok () -> Lwt.return_unit
|
||||||
@ -268,14 +243,11 @@ let create
|
|||||||
last_get_block := None;
|
last_get_block := None;
|
||||||
check_error @@ prepare_endorsement cctxt ~max_past state bi
|
check_error @@ prepare_endorsement cctxt ~max_past state bi
|
||||||
| `Timeout ->
|
| `Timeout ->
|
||||||
begin
|
|
||||||
endorse_for cctxt state.to_endorse >>= function
|
endorse_for cctxt state.to_endorse >>= function
|
||||||
| Ok still_waiting ->
|
| Ok () ->
|
||||||
state.to_endorse <- still_waiting ;
|
|
||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
lwt_log_error "Error while endorsing:@\n%a" pp_print_error errs
|
lwt_log_error "Error while endorsing:@\n%a" pp_print_error errs
|
||||||
end
|
|
||||||
end >>= fun () ->
|
end >>= fun () ->
|
||||||
worker_loop () in
|
worker_loop () in
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user