Shell: Add `State.{Block,Valid_block}.iter_predecessors
This commit is contained in:
parent
b11a770dfa
commit
a2363ebd5b
@ -236,6 +236,65 @@ module Operation = struct
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let iter_predecessors
|
||||||
|
(type t)
|
||||||
|
(compare: t -> t -> int)
|
||||||
|
(predecessor: state -> t -> t option Lwt.t)
|
||||||
|
(date: t -> Time.t)
|
||||||
|
(fitness: t -> Fitness.fitness)
|
||||||
|
state ?max ?min_fitness ?min_date heads ~f =
|
||||||
|
let module Local = struct exception Exit end in
|
||||||
|
let pop, push =
|
||||||
|
(* Poor-man priority queue *)
|
||||||
|
let queue : t list ref = ref [] in
|
||||||
|
let pop () =
|
||||||
|
match !queue with
|
||||||
|
| [] -> None
|
||||||
|
| b :: bs -> queue := bs ; Some b in
|
||||||
|
let push b =
|
||||||
|
let rec loop = function
|
||||||
|
| [] -> [b]
|
||||||
|
| b' :: bs' as bs ->
|
||||||
|
let cmp = compare b b' in
|
||||||
|
if cmp = 0 then
|
||||||
|
bs
|
||||||
|
else if cmp < 0 then
|
||||||
|
b' :: loop bs'
|
||||||
|
else
|
||||||
|
b :: bs in
|
||||||
|
queue := loop !queue in
|
||||||
|
pop, push in
|
||||||
|
let check_count =
|
||||||
|
match max with
|
||||||
|
| None -> (fun () -> ())
|
||||||
|
| Some max ->
|
||||||
|
let cpt = ref 0 in
|
||||||
|
fun () ->
|
||||||
|
if !cpt >= max then raise Local.Exit ;
|
||||||
|
incr cpt in
|
||||||
|
let check_fitness =
|
||||||
|
match min_fitness with
|
||||||
|
| None -> (fun _ -> true)
|
||||||
|
| Some min_fitness ->
|
||||||
|
(fun b -> Fitness.compare min_fitness (fitness b) <= 0) in
|
||||||
|
let check_date =
|
||||||
|
match min_date with
|
||||||
|
| None -> (fun _ -> true)
|
||||||
|
| Some min_date -> (fun b -> Time.compare min_date (date b) <= 0) in
|
||||||
|
let rec loop () =
|
||||||
|
match pop () with
|
||||||
|
| None -> return ()
|
||||||
|
| Some b ->
|
||||||
|
check_count () ;
|
||||||
|
f b >>= fun () ->
|
||||||
|
predecessor state b >>= function
|
||||||
|
| None -> loop ()
|
||||||
|
| Some p ->
|
||||||
|
if check_fitness p && check_date p then push p ;
|
||||||
|
loop () in
|
||||||
|
List.iter push heads ;
|
||||||
|
try loop () with Local.Exit -> return ()
|
||||||
|
|
||||||
module Block = struct
|
module Block = struct
|
||||||
|
|
||||||
type shell_header = Store.shell_block_header = {
|
type shell_header = Store.shell_block_header = {
|
||||||
@ -368,6 +427,28 @@ module Block = struct
|
|||||||
return locator
|
return locator
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let iter_predecessors =
|
||||||
|
let compare b1 b2 =
|
||||||
|
match Fitness.compare b1.shell.fitness b2.shell.fitness with
|
||||||
|
| 0 -> begin
|
||||||
|
match Time.compare b1.shell.timestamp b2.shell.timestamp with
|
||||||
|
| 0 -> Block_hash.compare (hash b1) (hash b2)
|
||||||
|
| res -> res
|
||||||
|
end
|
||||||
|
| res -> res in
|
||||||
|
let predecessor state b =
|
||||||
|
read state b.shell.predecessor >|= function
|
||||||
|
| None -> None
|
||||||
|
| Some { data } ->
|
||||||
|
if Block_hash.equal data.shell.predecessor b.shell.predecessor
|
||||||
|
&& Block_hash.equal (hash b) b.shell.predecessor
|
||||||
|
then
|
||||||
|
None
|
||||||
|
else
|
||||||
|
Some data in
|
||||||
|
iter_predecessors compare predecessor
|
||||||
|
(fun b -> b.shell.timestamp) (fun b -> b.shell.fitness)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Valid_block = struct
|
module Valid_block = struct
|
||||||
@ -706,6 +787,25 @@ module Valid_block = struct
|
|||||||
Lwt.return vstate
|
Lwt.return vstate
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let iter_predecessors =
|
||||||
|
let compare b1 b2 =
|
||||||
|
match Fitness.compare b1.fitness b2.fitness with
|
||||||
|
| 0 -> begin
|
||||||
|
match Time.compare b1.timestamp b2.timestamp with
|
||||||
|
| 0 -> Block_hash.compare b1.hash b2.hash
|
||||||
|
| res -> res
|
||||||
|
end
|
||||||
|
| res -> res in
|
||||||
|
let predecessor state b =
|
||||||
|
if Block_hash.equal b.hash b.pred then
|
||||||
|
Lwt.return None
|
||||||
|
else
|
||||||
|
read state b.pred >|= function
|
||||||
|
| None | Some (Error _) -> None
|
||||||
|
| Some (Ok b) -> Some b in
|
||||||
|
iter_predecessors compare predecessor
|
||||||
|
(fun b -> b.timestamp) (fun b -> b.fitness)
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
module Blockchain = struct
|
module Blockchain = struct
|
||||||
|
@ -206,6 +206,22 @@ module Block : sig
|
|||||||
val block_locator:
|
val block_locator:
|
||||||
state -> int -> Block_hash.t -> Block_hash.t list tzresult Lwt.t
|
state -> int -> Block_hash.t -> Block_hash.t list tzresult Lwt.t
|
||||||
|
|
||||||
|
(** [iter_predecessors state blocks f] iter [f] on [blocks] and
|
||||||
|
their recursive (known) predecessors. Blocks are visited with a
|
||||||
|
decreasing fitness (then decreasing timestamp). If the optional
|
||||||
|
argument [max] is provided, the iteration is stopped after [max]
|
||||||
|
visited block. If [min_fitness] id provided, blocks with a
|
||||||
|
fitness lower than [min_fitness] are ignored. If [min_date],
|
||||||
|
blocks with a fitness lower than [min_date] are ignored. *)
|
||||||
|
val iter_predecessors:
|
||||||
|
state ->
|
||||||
|
?max:int ->
|
||||||
|
?min_fitness:Fitness.fitness ->
|
||||||
|
?min_date:Time.t ->
|
||||||
|
block list ->
|
||||||
|
f:(block -> unit Lwt.t) ->
|
||||||
|
unit tzresult Lwt.t
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
(** {2 Valid block} ***********************************************************)
|
(** {2 Valid block} ***********************************************************)
|
||||||
@ -297,6 +313,22 @@ module Valid_block : sig
|
|||||||
(/à la/ Bitcoin) for the block [h]. *)
|
(/à la/ Bitcoin) for the block [h]. *)
|
||||||
val block_locator: state -> int -> valid_block -> Block_hash.t list Lwt.t
|
val block_locator: state -> int -> valid_block -> Block_hash.t list Lwt.t
|
||||||
|
|
||||||
|
(** [iter_predecessors state blocks f] iter [f] on [blocks] and
|
||||||
|
their recursive predecessors. Blocks are visited with a
|
||||||
|
decreasing fitness (then decreasing timestamp). If the optional
|
||||||
|
argument [max] is provided, the iteration is stopped after [max]
|
||||||
|
visited block. If [min_fitness] id provided, blocks with a
|
||||||
|
fitness lower than [min_fitness] are ignored. If [min_date],
|
||||||
|
blocks with a fitness lower than [min_date] are ignored. *)
|
||||||
|
val iter_predecessors:
|
||||||
|
state ->
|
||||||
|
?max:int ->
|
||||||
|
?min_fitness:Fitness.fitness ->
|
||||||
|
?min_date:Time.t ->
|
||||||
|
valid_block list ->
|
||||||
|
f:(valid_block -> unit Lwt.t) ->
|
||||||
|
unit tzresult Lwt.t
|
||||||
|
|
||||||
(**/**)
|
(**/**)
|
||||||
|
|
||||||
(* Store function to be used by the validator. *)
|
(* Store function to be used by the validator. *)
|
||||||
|
Loading…
Reference in New Issue
Block a user