RPC: add a hash+N and a hash-N notations

This commit is contained in:
Victor Allombert 2018-10-24 11:21:57 +02:00 committed by Grégoire Henry
parent 2352a78301
commit 60a6b76229
2 changed files with 44 additions and 10 deletions

View File

@ -339,12 +339,26 @@ let get_block chain_state = function
Chain.genesis chain_state Chain.genesis chain_state
| `Head n -> | `Head n ->
Chain.head chain_state >>= fun head -> Chain.head chain_state >>= fun head ->
if n = 0 then if n < 0 then
Lwt.fail Not_found
else if n = 0 then
Lwt.return head Lwt.return head
else else
State.Block.read_exn chain_state ~pred:n (State.Block.hash head) State.Block.read_exn chain_state ~pred:n (State.Block.hash head)
| `Hash (hash, n) -> | `Hash (hash, n) ->
State.Block.read_exn chain_state ~pred:n hash if n < 0 then
State.Block.read_exn chain_state hash >>= fun block ->
Chain.head chain_state >>= fun head ->
let head_level = State.Block.level head in
let block_level = State.Block.level block in
let target =
Int32.(to_int (sub head_level (sub block_level (of_int n)))) in
if target < 0 then
Lwt.fail Not_found
else
State.Block.read_exn chain_state ~pred:target (State.Block.hash head)
else
State.Block.read_exn chain_state ~pred:n hash
| `Level i -> | `Level i ->
Chain.head chain_state >>= fun head -> Chain.head chain_state >>= fun head ->
let target = Int32.(to_int (sub (State.Block.level head) i)) in let target = Int32.(to_int (sub (State.Block.level head) i)) in

View File

@ -61,12 +61,27 @@ type block = [
] ]
let parse_block s = let parse_block s =
let delims = ['~';'-';'+'] in
let count_delims s =
List.map
(fun d ->
(String.fold_left (fun i c -> if c = d then i+1 else i) 0 s), d)
delims in
let split_on_delim counts =
begin
match List.fold_left (fun i (v,_) -> i+v) 0 counts with
| 0 -> ([s], ' ')
| 1 -> let delim = List.assoc 1 counts in
(String.split delim s, delim)
| _ -> raise Exit
end in
try try
match String.split '~' s with match split_on_delim (count_delims s) with
| ["genesis"] -> Ok `Genesis | (["genesis"],_) -> Ok `Genesis
| ["head"] -> Ok (`Head 0) | (["head"],_) -> Ok (`Head 0)
| ["head"; n] -> Ok (`Head (int_of_string n)) | (["head"; n],'~') -> Ok (`Head (int_of_string n))
| [hol] -> | (["head"; n],'-') -> Ok (`Head (int_of_string n))
| ([hol],_) ->
begin begin
match Block_hash.of_b58check_opt hol with match Block_hash.of_b58check_opt hol with
Some h -> Ok (`Hash (h , 0)) Some h -> Ok (`Hash (h , 0))
@ -75,15 +90,19 @@ let parse_block s =
if Int32.(compare l (of_int 0)) < 0 then raise Exit if Int32.(compare l (of_int 0)) < 0 then raise Exit
else Ok (`Level (Int32.of_string s)) else Ok (`Level (Int32.of_string s))
end end
| [h ; n] -> Ok (`Hash (Block_hash.of_b58check_exn h, int_of_string n)) | ([h ; n],'~') -> Ok (`Hash (Block_hash.of_b58check_exn h, int_of_string n))
| ([h ; n],'-') -> Ok (`Hash (Block_hash.of_b58check_exn h, int_of_string n))
| ([h ; n],'+') -> Ok (`Hash (Block_hash.of_b58check_exn h, - int_of_string n))
| _ -> raise Exit | _ -> raise Exit
with _ -> Error "Cannot parse block identifier." with _ -> Error "Cannot parse block identifier."
let to_string = function let to_string = function
| `Genesis -> "genesis" | `Genesis -> "genesis"
| `Head 0 -> "head" | `Head 0 -> "head"
| `Head n when n < 0 -> Printf.sprintf "head+%d" (-n)
| `Head n -> Printf.sprintf "head~%d" n | `Head n -> Printf.sprintf "head~%d" n
| `Hash (h, 0) -> Block_hash.to_b58check h | `Hash (h, 0) -> Block_hash.to_b58check h
| `Hash (h, n) when n < 0 -> Printf.sprintf "%s+%d" (Block_hash.to_b58check h) (-n)
| `Hash (h, n) -> Printf.sprintf "%s~%d" (Block_hash.to_b58check h) n | `Hash (h, n) -> Printf.sprintf "%s~%d" (Block_hash.to_b58check h) n
| `Level i -> Printf.sprintf "%d" (Int32.to_int i) | `Level i -> Printf.sprintf "%d" (Int32.to_int i)
@ -93,8 +112,9 @@ let blocks_arg =
"A block identifier. This is either a block hash in Base58Check notation, \ "A block identifier. This is either a block hash in Base58Check notation, \
one the predefined aliases: 'genesis', 'head' \ one the predefined aliases: 'genesis', 'head' \
or a block level (index in the chain). \ or a block level (index in the chain). \
One might alse use 'head~N' or '<hash>~N' where N is an integer to \ One might also use 'head~N' or '<hash>~N' where N is an integer to \
denotes the Nth predecessors of the designated block." in denotes the Nth predecessor of the designated block.\
Also, '<hash>+N' denotes the Nth successor of a block." in
let construct = to_string in let construct = to_string in
let destruct = parse_block in let destruct = parse_block in
RPC_arg.make ~name ~descr ~construct ~destruct () RPC_arg.make ~name ~descr ~construct ~destruct ()