Lib_client_base: add branch option to wait for confirmation command
This commit is contained in:
parent
d30894b2f9
commit
cf3390448a
@ -33,7 +33,7 @@ let in_block operation_hash operations =
|
||||
raise (Found (i,j))) ops)
|
||||
operations ;
|
||||
None
|
||||
with Found (i,j) -> Some (i, j)
|
||||
with Found (i,j) -> Some (i, j)
|
||||
|
||||
let wait_for_bootstrapped (ctxt : #Client_context.full) =
|
||||
let display = ref false in
|
||||
@ -59,13 +59,22 @@ let wait_for_bootstrapped (ctxt : #Client_context.full) =
|
||||
ctxt#answer "Node is bootstrapped, ready for injecting operations." >>= fun () ->
|
||||
return_unit
|
||||
|
||||
type operation_status =
|
||||
| Confirmed of (Block_hash.t * int * int)
|
||||
| Pending
|
||||
| Still_not_found
|
||||
|
||||
let wait_for_operation_inclusion
|
||||
(ctxt : #Client_context.full)
|
||||
~chain
|
||||
?(predecessors = 10)
|
||||
?(confirmations = 1)
|
||||
?branch
|
||||
operation_hash =
|
||||
|
||||
let exception WrapError of error list in
|
||||
let exception Outdated of Operation_hash.t in
|
||||
|
||||
(* Table of known blocks:
|
||||
- None: if neither the block or its predecessors contains the operation
|
||||
- (Some ((hash, i, j), n)):
|
||||
@ -109,54 +118,82 @@ let wait_for_operation_inclusion
|
||||
(n+1) Block_hash.pp hash >>= fun () ->
|
||||
Block_hash.Table.add blocks hash (Some (block_with_op, n+1)) ;
|
||||
if n+1 < confirmations then begin
|
||||
return_none
|
||||
return Pending
|
||||
end else
|
||||
return_some block_with_op
|
||||
return (Confirmed block_with_op)
|
||||
| None ->
|
||||
Shell_services.Blocks.Operation_hashes.operation_hashes
|
||||
ctxt ~chain ~block () >>=? fun operations ->
|
||||
match in_block operation_hash operations with
|
||||
| None ->
|
||||
Block_hash.Table.add blocks hash None ;
|
||||
return_none
|
||||
return Still_not_found
|
||||
| Some (i, j) -> begin
|
||||
ctxt#answer
|
||||
"Operation found in block: %a (pass: %d, offset: %d)"
|
||||
Block_hash.pp hash i j >>= fun () ->
|
||||
Block_hash.Table.add blocks hash (Some ((hash, i, j), 0)) ;
|
||||
if confirmations <= 0 then
|
||||
return_some (hash, i, j)
|
||||
else begin
|
||||
return_none
|
||||
end
|
||||
return (Confirmed (hash, i, j))
|
||||
else
|
||||
return Pending
|
||||
end in
|
||||
|
||||
(* Checks if the given branch is considered alive.*)
|
||||
|
||||
let check_branch_alive () =
|
||||
match branch with
|
||||
| Some branch_hash ->
|
||||
Shell_services.Blocks.live_blocks
|
||||
ctxt ~chain ~block:(`Head 0) () >>= begin function
|
||||
| Ok live_blocks ->
|
||||
if Block_hash.Set.mem branch_hash live_blocks then
|
||||
Lwt.return_unit
|
||||
else
|
||||
ctxt#error
|
||||
"The operation %a is outdated and may \
|
||||
never be included in the chain.@,\
|
||||
We recommand to use an external block explorer."
|
||||
Operation_hash.pp operation_hash >>= fun () ->
|
||||
Lwt.fail (Outdated operation_hash)
|
||||
| Error err -> Lwt.fail (WrapError err)
|
||||
end
|
||||
| None -> Lwt.return_unit
|
||||
in
|
||||
|
||||
Shell_services.Monitor.heads ctxt chain >>=? fun (stream, stop) ->
|
||||
Lwt_stream.get stream >>= function
|
||||
| None -> assert false
|
||||
| Some (head, _) ->
|
||||
let rec loop n =
|
||||
if n >= 0 then
|
||||
(*Search for the operation in the n head predecessors*)
|
||||
let block = `Hash (head, n) in
|
||||
Shell_services.Blocks.hash ctxt ~chain ~block () >>=? fun hash ->
|
||||
Shell_services.Blocks.Header.shell_header ctxt
|
||||
~chain ~block () >>=? fun shell ->
|
||||
process hash shell >>=? function
|
||||
| Some block ->
|
||||
| Confirmed block ->
|
||||
stop () ;
|
||||
return block
|
||||
| None ->
|
||||
| Pending | Still_not_found ->
|
||||
loop (n-1)
|
||||
else
|
||||
let exception WrapError of error list in
|
||||
(*Search for the operation in new heads*)
|
||||
Lwt.catch
|
||||
(fun () ->
|
||||
(*Fetching potential unknown blocks from potential new heads*)
|
||||
let stream = Lwt_stream.map_list_s fetch_predecessors stream in
|
||||
Lwt_stream.find_s
|
||||
(fun (hash, header) ->
|
||||
process hash header >>= function
|
||||
| Ok None -> Lwt.return_false
|
||||
| Ok (Some _) -> Lwt.return_true
|
||||
| Ok Pending ->
|
||||
Lwt.return_false
|
||||
| Ok Still_not_found ->
|
||||
check_branch_alive () >>= fun () ->
|
||||
Lwt.return_false
|
||||
| Ok (Confirmed _) ->
|
||||
Lwt.return_true
|
||||
| Error err ->
|
||||
Lwt.fail (WrapError err)) stream >>= return)
|
||||
(function
|
||||
@ -170,29 +207,42 @@ let wait_for_operation_inclusion
|
||||
| None | Some None -> assert false
|
||||
| Some (Some (hash, _)) ->
|
||||
return hash in
|
||||
begin
|
||||
match branch with
|
||||
| Some branch_hash ->
|
||||
Shell_services.Blocks.Header.shell_header
|
||||
ctxt ~chain ~block:(`Hash(branch_hash,0)) () >>=? fun branch_header ->
|
||||
let branch_level = branch_header.Block_header.level in
|
||||
Shell_services.Blocks.Header.shell_header
|
||||
ctxt ~chain ~block:(`Hash (head,0)) () >>=? fun head_shell ->
|
||||
let head_level = head_shell.Block_header.level in
|
||||
return (Int32.(to_int (sub head_level branch_level)))
|
||||
| None -> return predecessors
|
||||
end
|
||||
>>=? fun block_hook ->
|
||||
Block_services.Empty.hash
|
||||
ctxt ~block:(`Hash (head, predecessors+1)) () >>=? fun oldest ->
|
||||
ctxt ~block:(`Hash (head, block_hook+1)) () >>=? fun oldest ->
|
||||
Block_hash.Table.add blocks oldest None ;
|
||||
loop predecessors
|
||||
loop block_hook
|
||||
|
||||
let lookup_operation_in_previous_block ctxt chain operation_hash i =
|
||||
Block_services.Empty.hash ctxt ~block:(`Head i) ()
|
||||
Block_services.Empty.hash ctxt ~block:(`Head i) ()
|
||||
>>=? fun block ->
|
||||
Shell_services.Blocks.Operation_hashes.operation_hashes ctxt ~chain
|
||||
Shell_services.Blocks.Operation_hashes.operation_hashes ctxt ~chain
|
||||
~block:(`Hash (block, 0)) ()
|
||||
>>=? fun operations ->
|
||||
>>=? fun operations ->
|
||||
match in_block operation_hash operations with
|
||||
| None -> return_none
|
||||
| Some (a, b) -> return_some (block, a, b)
|
||||
| Some (a, b) -> return_some (block, a, b)
|
||||
|
||||
let lookup_operation_in_previous_blocks
|
||||
(ctxt : #Client_context.full)
|
||||
~chain
|
||||
~predecessors
|
||||
operation_hash =
|
||||
let rec loop i =
|
||||
let rec loop i =
|
||||
if i = predecessors + 1 then
|
||||
return_none
|
||||
return_none
|
||||
else begin
|
||||
lookup_operation_in_previous_block ctxt chain operation_hash i >>=?
|
||||
function
|
||||
@ -200,4 +250,4 @@ let lookup_operation_in_previous_blocks
|
||||
| Some (block, a, b) -> return_some (block, a, b)
|
||||
end
|
||||
in
|
||||
loop 0
|
||||
loop 0
|
||||
|
@ -35,6 +35,7 @@ val wait_for_operation_inclusion:
|
||||
chain:Chain_services.chain ->
|
||||
?predecessors:int ->
|
||||
?confirmations:int ->
|
||||
?branch:Block_hash.t ->
|
||||
Operation_hash.t ->
|
||||
(Block_hash.t * int * int) tzresult Lwt.t
|
||||
|
||||
@ -48,4 +49,4 @@ val lookup_operation_in_previous_blocks:
|
||||
chain:Block_services.chain ->
|
||||
predecessors:int ->
|
||||
Operation_list_hash.elt ->
|
||||
(Block_hash.t * int * int) option tzresult Lwt.t
|
||||
(Block_hash.t * int * int) option tzresult Lwt.t
|
||||
|
@ -551,14 +551,14 @@ let inject_operation
|
||||
| None ->
|
||||
cctxt#message "@[<v 0>NOT waiting for the operation to be included.@,\
|
||||
Use command@,\
|
||||
\ tezos-client wait for %a to be included --confirmations 30@,\
|
||||
\ tezos-client wait for %a to be included --confirmations 30 --branch %a@,\
|
||||
and/or an external block explorer to make sure that it has been included.@]"
|
||||
Operation_hash.pp oph >>= fun () ->
|
||||
Operation_hash.pp oph Block_hash.pp op.shell.branch >>= fun () ->
|
||||
return result
|
||||
| Some confirmations ->
|
||||
cctxt#message "Waiting for the operation to be included..." >>= fun () ->
|
||||
Client_confirmations.wait_for_operation_inclusion
|
||||
~confirmations cctxt ~chain oph >>=? fun (h, i , j) ->
|
||||
~branch:op.shell.branch ~confirmations cctxt ~chain oph >>=? fun (h, i , j) ->
|
||||
Alpha_block_services.Operations.operation
|
||||
cctxt ~block:(`Hash (h, 0)) i j >>=? fun op' ->
|
||||
match op'.receipt with
|
||||
@ -594,9 +594,10 @@ let inject_operation
|
||||
"@[<v 0>The operation has only been included %d blocks ago.@,\
|
||||
We recommend to wait more.@,\
|
||||
Use command@,\
|
||||
\ tezos-client wait for %a to be included --confirmations 30@,\
|
||||
\ tezos-client wait for %a to be included --confirmations 30 \
|
||||
--branch %a@,\
|
||||
and/or an external block explorer.@]"
|
||||
number Operation_hash.pp oph
|
||||
number Operation_hash.pp oph Block_hash.pp op.shell.branch
|
||||
end >>= fun () ->
|
||||
return (oph, op.protocol_data.contents, result.contents)
|
||||
|
||||
|
@ -73,6 +73,12 @@ let non_negative_param =
|
||||
| Some i when i >= 0 -> return i
|
||||
| _ -> failwith "Parameter should be a non-negative integer literal")
|
||||
|
||||
let block_hash_param =
|
||||
Clic.parameter (fun _ s ->
|
||||
try return (Block_hash.of_b58check_exn s)
|
||||
with _ ->
|
||||
failwith "Parameter '%s' is an invalid block hash" s)
|
||||
|
||||
let group =
|
||||
{ Clic.name = "context" ;
|
||||
title = "Block contextual commands (see option -block)" }
|
||||
@ -567,11 +573,12 @@ let commands version () =
|
||||
]) @
|
||||
[
|
||||
command ~desc:"Wait until an operation is included in a block"
|
||||
(args2
|
||||
(args3
|
||||
(default_arg
|
||||
~long:"confirmations"
|
||||
~placeholder:"num_blocks"
|
||||
~doc:"do not end until after 'N' additional blocks after the operation appears"
|
||||
~doc:"wait until 'N' additional blocks after the operation \
|
||||
appears in the considered chain"
|
||||
~default:"0"
|
||||
non_negative_param)
|
||||
(default_arg
|
||||
@ -579,7 +586,12 @@ let commands version () =
|
||||
~placeholder:"num_blocks"
|
||||
~doc:"number of previous blocks to check"
|
||||
~default:"10"
|
||||
non_negative_param))
|
||||
non_negative_param)
|
||||
(arg
|
||||
~long:"branch"
|
||||
~placeholder:"block_hash"
|
||||
~doc:"hash of the oldest block where we should look for the operation"
|
||||
block_hash_param))
|
||||
(prefixes [ "wait" ; "for" ]
|
||||
@@ param
|
||||
~name:"operation"
|
||||
@ -591,9 +603,9 @@ let commands version () =
|
||||
| Some hash -> return hash))
|
||||
@@ prefixes [ "to" ; "be" ; "included" ]
|
||||
@@ stop)
|
||||
begin fun (confirmations, predecessors) operation_hash (ctxt : Proto_alpha.full) ->
|
||||
begin fun (confirmations, predecessors, branch) operation_hash (ctxt : Proto_alpha.full) ->
|
||||
Client_confirmations.wait_for_operation_inclusion ctxt
|
||||
~chain:`Main ~confirmations ~predecessors operation_hash >>=? fun _ ->
|
||||
~chain:`Main ~confirmations ~predecessors ?branch operation_hash >>=? fun _ ->
|
||||
return_unit
|
||||
end ;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user