From 0b33e5a6dabe9a4a6804778e529d5a3e20531491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Henry?= Date: Wed, 15 Feb 2017 20:38:00 +0100 Subject: [PATCH] Shell/RPC: Implements `/block//predecessors --- src/client/client_node_rpcs.ml | 1 + src/client/client_node_rpcs.mli | 3 +++ src/node/shell/node.ml | 28 +++++++++++++++++++++++----- src/node/shell/node.mli | 3 +++ src/node/shell/node_rpc.ml | 10 +++++++++- src/node/shell/node_rpc_services.ml | 11 +++++++++-- src/node/shell/node_rpc_services.mli | 2 ++ 7 files changed, 50 insertions(+), 8 deletions(-) diff --git a/src/client/client_node_rpcs.ml b/src/client/client_node_rpcs.ml index cd06ca6a5..996770581 100644 --- a/src/client/client_node_rpcs.ml +++ b/src/client/client_node_rpcs.ml @@ -178,6 +178,7 @@ module Blocks = struct } let net cctxt h = call_service1 cctxt Services.Blocks.net h () let predecessor cctxt h = call_service1 cctxt Services.Blocks.predecessor h () + let predecessors cctxt h l = call_service1 cctxt Services.Blocks.predecessors h l let hash cctxt h = call_service1 cctxt Services.Blocks.hash h () let timestamp cctxt h = call_service1 cctxt Services.Blocks.timestamp h () let fitness cctxt h = call_service1 cctxt Services.Blocks.fitness h () diff --git a/src/client/client_node_rpcs.mli b/src/client/client_node_rpcs.mli index c141bdab6..c8724bfa4 100644 --- a/src/client/client_node_rpcs.mli +++ b/src/client/client_node_rpcs.mli @@ -59,6 +59,9 @@ module Blocks : sig val predecessor: Client_commands.context -> block -> Block_hash.t Lwt.t + val predecessors: + Client_commands.context -> + block -> int -> Block_hash.t list Lwt.t val hash: Client_commands.context -> block -> Block_hash.t Lwt.t diff --git a/src/node/shell/node.ml b/src/node/shell/node.ml index f432d851f..a08209734 100644 --- a/src/node/shell/node.ml +++ b/src/node/shell/node.ml @@ -432,10 +432,28 @@ module RPC = struct Block_hash.Map.empty (test_heads @ heads) in Lwt.return map - let predecessors net_state ignored len head = + let predecessors node len head = + let rec loop net_db acc len hash (block: State.Block_header.t) = + if Block_hash.equal block.shell.predecessor hash then + Lwt.return (List.rev acc) + else begin + if len = 0 then + Lwt.return (List.rev acc) + else + let hash = block.shell.predecessor in + Distributed_db.Block_header.read_exn net_db hash >>= fun block -> + loop net_db (hash :: acc) (len-1) hash block + end in + try + Distributed_db.read_block_exn + node.distributed_db head >>= fun (net_db, block) -> + loop net_db [] len head block + with Not_found -> Lwt.return_nil + + let predecessors_bi state ignored len head = try let rec loop acc len hash = - State.Valid_block.read_exn net_state hash >>= fun block -> + State.Valid_block.read_exn state hash >>= fun block -> let bi = convert block in if Block_hash.equal bi.predecessor hash then Lwt.return (List.rev (bi :: acc)) @@ -455,7 +473,7 @@ module RPC = struct Distributed_db.read_block_exn node.distributed_db head >>= fun (net_db, _block) -> let net_state = Distributed_db.state net_db in - predecessors net_state ignored len head >|= fun predecessors -> + predecessors_bi net_state ignored len head >|= fun predecessors -> let ignored = List.fold_right (fun x s -> Block_hash.Set.add x.hash s) @@ -463,8 +481,8 @@ module RPC = struct ignored, predecessors :: acc ) (Block_hash.Set.empty, []) - heads >|= fun (_, blocks) -> - List.rev blocks + heads >>= fun (_, blocks) -> + Lwt.return (List.rev blocks) let block_watcher node = let stream, shutdown = Distributed_db.watch_block node.distributed_db in diff --git a/src/node/shell/node.mli b/src/node/shell/node.mli index dc63dfbfb..398bacb3f 100644 --- a/src/node/shell/node.mli +++ b/src/node/shell/node.mli @@ -43,6 +43,9 @@ module RPC : sig t -> (block_info Lwt_stream.t * Watcher.stopper) val heads: t -> block_info Block_hash.Map.t Lwt.t + val predecessors: + t -> int -> Block_hash.t -> Block_hash.t list Lwt.t + val list: t -> int -> Block_hash.t list -> block_info list list Lwt.t diff --git a/src/node/shell/node_rpc.ml b/src/node/shell/node_rpc.ml index 18b758524..3c7ce2651 100644 --- a/src/node/shell/node_rpc.ml +++ b/src/node/shell/node_rpc.ml @@ -41,6 +41,13 @@ let register_bi_dir node dir = RPC.Answer.return bi.predecessor in RPC.register1 dir Services.Blocks.predecessor implementation in + let dir = + let implementation b len = + Node.RPC.block_info node b >>= fun bi -> + Node.RPC.predecessors node len bi.hash >>= fun hashes -> + RPC.Answer.return hashes in + RPC.register1 dir + Services.Blocks.predecessors implementation in let dir = let implementation b () = Node.RPC.block_info node b >>= fun bi -> @@ -367,7 +374,8 @@ let get_protocols node hash () = let build_rpc_directory node = let dir = RPC.empty in - let dir = RPC.register0 dir Services.Blocks.list (list_blocks node) in + let dir = + RPC.register0 dir Services.Blocks.list (list_blocks node) in let dir = register_bi_dir node dir in let dir = let implementation block = diff --git a/src/node/shell/node_rpc_services.ml b/src/node/shell/node_rpc_services.ml index 63f687443..86cf7afce 100644 --- a/src/node/shell/node_rpc_services.ml +++ b/src/node/shell/node_rpc_services.ml @@ -194,6 +194,15 @@ module Blocks = struct ~output: (obj1 (req "predecessor" Block_hash.encoding)) RPC.Path.(block_path / "predecessor") + let predecessors = + RPC.service + ~description: + "...." + ~input: (obj1 (req "length" Data_encoding.uint16)) + ~output: (obj1 + (req "blocks" (Data_encoding.list Block_hash.encoding))) + RPC.Path.(block_path / "predecessors") + let hash = RPC.service ~description:"Returns the block's id." @@ -378,8 +387,6 @@ module Blocks = struct ~output: (obj1 (req "blocks" (list (list block_info_encoding)))) RPC.Path.(root / "blocks") - - end module Operations = struct diff --git a/src/node/shell/node_rpc_services.mli b/src/node/shell/node_rpc_services.mli index b310cb459..8e1e801ef 100644 --- a/src/node/shell/node_rpc_services.mli +++ b/src/node/shell/node_rpc_services.mli @@ -44,6 +44,8 @@ module Blocks : sig (unit, unit * block, unit, net) RPC.service val predecessor: (unit, unit * block, unit, Block_hash.t) RPC.service + val predecessors: + (unit, unit * block , int, Block_hash.t list) RPC.service val hash: (unit, unit * block, unit, Block_hash.t) RPC.service val timestamp: