Shell/RPC: rework /blocks
- start using `GET` and query parameters instead of `POST` when meaningful - inline parsed protocol data and metadata in block headers - inline parsed protocol data and metadata in operations - split the RPC in four categories: - static data, available explicitly in block headers and operations - static "metadata", information that were computed while validating a block or an operation, but which are not explicit in the block header (e.g. the baker of a block, the list of internal transfer... (currently not implemented, but that's WIP)) - "context" all the static data we may read in the context (contracts balance, list of delegates, ...) - "helpers" are some RPC that may perform some computation.
This commit is contained in:
parent
f02972bb8a
commit
d6f79edae2
@ -5,7 +5,7 @@ Usage
|
|||||||
*****
|
*****
|
||||||
|
|
||||||
In order to interact with a Tezos node, you may use RPC calls through the
|
In order to interact with a Tezos node, you may use RPC calls through the
|
||||||
client using this command ``tezos-admin-client rpc post <url>``.
|
client using this command ``tezos-admin-client rpc (get|post) <url>``.
|
||||||
|
|
||||||
For instance, if you wish to request the current balance of a given
|
For instance, if you wish to request the current balance of a given
|
||||||
block and contract, you can call the associated RPC via the command :
|
block and contract, you can call the associated RPC via the command :
|
||||||
|
@ -318,7 +318,7 @@ the appropriate value:
|
|||||||
|
|
||||||
$ ./alphanet.sh client list known identities
|
$ ./alphanet.sh client list known identities
|
||||||
my_identity: tz1iFY8aDskx9QGbgBy68SNAGgkc7AE2iG9H (public key known) (secret key known)
|
my_identity: tz1iFY8aDskx9QGbgBy68SNAGgkc7AE2iG9H (public key known) (secret key known)
|
||||||
$ ./alphanet.sh client rpc post /blocks/head/proto/helpers/rights/baking/delegate/tz1iFY8aDskx9QGbgBy68SNAGgkc7AE2iG9H with '{}'
|
$ ./alphanet.sh client rpc post /chains/main/blocks/head/helpers/rights/baking/delegate/tz1iFY8aDskx9QGbgBy68SNAGgkc7AE2iG9H with {}
|
||||||
{ "ok":
|
{ "ok":
|
||||||
[ { "level": 1400.000000, "priority": 2.000000,
|
[ { "level": 1400.000000, "priority": 2.000000,
|
||||||
"timestamp": "2017-05-19T03:21:52Z" },
|
"timestamp": "2017-05-19T03:21:52Z" },
|
||||||
|
@ -277,7 +277,7 @@ preconfigured for communicating the same-numbered node. For instance:
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ tezos-client rpc post blocks/head/hash
|
$ tezos-client rpc get /chains/main/blocks/head/hash
|
||||||
{ "hash": "BLockGenesisGenesisGenesisGenesisGenesisGeneskvg68z" }
|
{ "hash": "BLockGenesisGenesisGenesisGenesisGenesisGeneskvg68z" }
|
||||||
|
|
||||||
When you bootstrap a new network, the network is initialized with a
|
When you bootstrap a new network, the network is initialized with a
|
||||||
@ -288,11 +288,11 @@ activating the whole network. For instance:
|
|||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
$ tezos-client rpc post blocks/head/protocol
|
$ tezos-client rpc get /chains/main/blocks/head/metadata/next_protocol_hash
|
||||||
{ "protocol": "ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im" }
|
{ "protocol": "ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im" }
|
||||||
$ tezos-activate-alpha
|
$ tezos-activate-alpha
|
||||||
Injected BMBcK869jaHQDc
|
Injected BMBcK869jaHQDc
|
||||||
$ tezos-client rpc post blocks/head/protocol
|
$ tezos-client rpc get /chains/main/blocks/head/metadata/next_protocol_hash
|
||||||
{ "protocol": "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK" }
|
{ "protocol": "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK" }
|
||||||
|
|
||||||
Tune protocol alpha parameters
|
Tune protocol alpha parameters
|
||||||
|
@ -381,8 +381,8 @@ run_shell() {
|
|||||||
|
|
||||||
display_head() {
|
display_head() {
|
||||||
assert_node_uptodate
|
assert_node_uptodate
|
||||||
exec_docker tezos-client rpc post /blocks/head with '{}'
|
exec_docker tezos-client rpc get /chains/main/blocks/head
|
||||||
exec_docker tezos-client rpc post /blocks/head/proto/context/level with '{}'
|
exec_docker tezos-client rpc post /chains/main/blocks/head/context/level with {}
|
||||||
}
|
}
|
||||||
|
|
||||||
## Main ####################################################################
|
## Main ####################################################################
|
||||||
|
@ -19,10 +19,10 @@ configure_client() {
|
|||||||
|
|
||||||
wait_for_the_node_to_be_ready() {
|
wait_for_the_node_to_be_ready() {
|
||||||
local count=0
|
local count=0
|
||||||
if "$client" rpc post /blocks/head/hash >/dev/null 2>&1; then return; fi
|
if "$client" rpc get /chains/main/blocks/head/hash >/dev/null 2>&1; then return; fi
|
||||||
printf "Waiting for the node to initialize..."
|
printf "Waiting for the node to initialize..."
|
||||||
sleep 1
|
sleep 1
|
||||||
while ! "$client" rpc post /blocks/head/hash >/dev/null 2>&1
|
while ! "$client" rpc get /chains/main/blocks/head/hash >/dev/null 2>&1
|
||||||
do
|
do
|
||||||
count=$((count+1))
|
count=$((count+1))
|
||||||
if [ "$count" -ge 30 ]; then
|
if [ "$count" -ge 30 ]; then
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
open Client_config
|
open Client_config
|
||||||
|
|
||||||
let get_commands_for_version ctxt block protocol =
|
let get_commands_for_version ctxt block protocol =
|
||||||
Block_services.protocol ctxt block >>= function
|
Block_services.Empty.Metadata.next_protocol_hash ctxt ~block () >>= function
|
||||||
| Ok version -> begin
|
| Ok version -> begin
|
||||||
match protocol with
|
match protocol with
|
||||||
| None ->
|
| None ->
|
||||||
|
@ -13,13 +13,13 @@ $client -w none config update
|
|||||||
sleep 2
|
sleep 2
|
||||||
|
|
||||||
#tests for the rpc service raw_context
|
#tests for the rpc service raw_context
|
||||||
$client rpc post '/blocks/head/raw_context/version' | assert '{ "content": "616c706861" }'
|
$client rpc get '/chains/main/blocks/head/context/raw/version' | assert '"616c706861"'
|
||||||
$client rpc post '/blocks/head/raw_context/non-existent' | assert 'No service found at this URL'
|
$client rpc get '/chains/main/blocks/head/context/raw/non-existent' | assert 'No service found at this URL'
|
||||||
$client rpc post '/blocks/head/raw_context/delegates/?depth=2' | assert '{ "content":
|
$client rpc get '/chains/main/blocks/head/context/raw/delegates/?depth=3' | assert '{ "ed25519":
|
||||||
{ "ed25519":
|
{ "02": { "29": null }, "a9": { "ce": null }, "c5": { "5c": null },
|
||||||
{ "02": null, "a9": null, "c5": null, "da": null, "e7": null } } }'
|
"da": { "c9": null }, "e7": { "67": null } } }'
|
||||||
$client rpc post '/blocks/head/raw_context/non-existent?depth=-1' | assert 'No service found at this URL'
|
$client rpc get '/chains/main/blocks/head/context/raw/non-existent?depth=-1' | assert 'Unexpected server answer'
|
||||||
$client rpc post '/blocks/head/raw_context/non-existent?depth=0' | assert 'No service found at this URL'
|
$client rpc get '/chains/main/blocks/head/context/raw/non-existent?depth=0' | assert 'No service found at this URL'
|
||||||
|
|
||||||
bake
|
bake
|
||||||
|
|
||||||
|
@ -22,20 +22,19 @@ run_preflight() {
|
|||||||
-H "Access-Control-Request-Method: $cors_method" \
|
-H "Access-Control-Request-Method: $cors_method" \
|
||||||
-H "Access-Control-Request-Headers: $header" \
|
-H "Access-Control-Request-Headers: $header" \
|
||||||
-X $method \
|
-X $method \
|
||||||
-I -s http://localhost:18731/blocks/head/protocol > CURL.$id 2>&1
|
-I -s http://localhost:18731/chains/main/blocks/head/header/shell > CURL.$id 2>&1
|
||||||
}
|
}
|
||||||
|
|
||||||
run_request() {
|
run_request() {
|
||||||
local origin="$1"
|
local origin="$1"
|
||||||
curl -H "Origin: $origin" \
|
curl -H "Origin: $origin" \
|
||||||
-H "Content-Type: application/json" \
|
-H "Content-Type: application/json" \
|
||||||
--data-binary "{}" \
|
|
||||||
-D CURL.$id \
|
-D CURL.$id \
|
||||||
-s http://localhost:18731/blocks/head/protocol 2>&1 > /dev/null
|
-s http://localhost:18731/chains/main/blocks/head/header/shell 2>&1 > /dev/null
|
||||||
}
|
}
|
||||||
|
|
||||||
# Preflight
|
# Preflight
|
||||||
run_preflight "localhost" "OPTIONS" "POST" "Content-Type"
|
run_preflight "localhost" "OPTIONS" "GET" "Content-Type"
|
||||||
cat CURL.$id
|
cat CURL.$id
|
||||||
grep -q "access-control-allow-origin" CURL.$id
|
grep -q "access-control-allow-origin" CURL.$id
|
||||||
grep -q "access-control-allow-methods" CURL.$id
|
grep -q "access-control-allow-methods" CURL.$id
|
||||||
|
@ -37,7 +37,7 @@ $admin_client list protocols
|
|||||||
#these commands cannot be used in this case because the client does not
|
#these commands cannot be used in this case because the client does not
|
||||||
#know about the new protocol
|
#know about the new protocol
|
||||||
#$client --protocol $protocol_short bake for bootstrap1 -max-priority 512
|
#$client --protocol $protocol_short bake for bootstrap1 -max-priority 512
|
||||||
#$client --protocol $protocol_version rpc post /blocks/head with {}
|
#$client --protocol $protocol_version rpc get /chains/main/blocks/head
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo End of test
|
echo End of test
|
||||||
|
@ -19,7 +19,7 @@ protocol_version="PtamL2BUfeNFM2A8Thq2Wde8vNaVD9DhoARDVB41QsHFj89kQpT"
|
|||||||
$admin_client inject protocol "$test_dir/demo"
|
$admin_client inject protocol "$test_dir/demo"
|
||||||
$admin_client list protocols
|
$admin_client list protocols
|
||||||
$client activate protocol $protocol_version with fitness 1 and key dictator and parameters $parameters_file
|
$client activate protocol $protocol_version with fitness 1 and key dictator and parameters $parameters_file
|
||||||
answ=$($client -p ProtoALphaALph rpc post /blocks/head/protocol with {} 2>/dev/null)
|
answ=$($client -p ProtoALphaALph rpc get /chains/main/blocks/head/metadata/next_protocol_hash 2>/dev/null)
|
||||||
|
|
||||||
if ! grep "$protocol_version" <<< $answ ; then
|
if ! grep "$protocol_version" <<< $answ ; then
|
||||||
exit 1
|
exit 1
|
||||||
|
@ -37,7 +37,7 @@ $admin_client list protocols
|
|||||||
#these commands cannot be used in this case because the client does not
|
#these commands cannot be used in this case because the client does not
|
||||||
#know about the new protocol
|
#know about the new protocol
|
||||||
#$client --protocol $protocol_short bake for bootstrap1 -max-priority 512
|
#$client --protocol $protocol_short bake for bootstrap1 -max-priority 512
|
||||||
#$client --protocol $protocol_version rpc post /blocks/head with {}
|
#$client --protocol $protocol_version rpc get /chains/main/blocks/head
|
||||||
|
|
||||||
echo
|
echo
|
||||||
echo End of test
|
echo End of test
|
||||||
|
@ -40,7 +40,7 @@ assert_propagation_level() {
|
|||||||
level=$1
|
level=$1
|
||||||
printf "\n\nAsserting all nodes have reached level %s\n" "$level"
|
printf "\n\nAsserting all nodes have reached level %s\n" "$level"
|
||||||
for client in "${client_instances[@]}"; do
|
for client in "${client_instances[@]}"; do
|
||||||
( $client rpc post /blocks/head/proto/context/level \
|
( $client rpc post /chains/main/blocks/head/context/level with {} \
|
||||||
| assert_in_output "\"level\": $level" ) \
|
| assert_in_output "\"level\": $level" ) \
|
||||||
|| exit 2
|
|| exit 2
|
||||||
done
|
done
|
||||||
@ -51,7 +51,7 @@ assert_protocol() {
|
|||||||
proto=$1
|
proto=$1
|
||||||
printf "\n\nAsserting protocol propagation\n"
|
printf "\n\nAsserting protocol propagation\n"
|
||||||
for client in "${client_instances[@]}"; do
|
for client in "${client_instances[@]}"; do
|
||||||
( $client rpc post /blocks/head/protocol | assert_in_output "$proto" ) \
|
( $client rpc get /chains/main/blocks/head/metadata/next_protocol_hash | assert_in_output "$proto" ) \
|
||||||
|| exit 2
|
|| exit 2
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
@ -102,7 +102,7 @@ assert_contains_operation() {
|
|||||||
hash="$1"
|
hash="$1"
|
||||||
printf "Asserting operations list contains '$hash'\n"
|
printf "Asserting operations list contains '$hash'\n"
|
||||||
for client in "${client_instances[@]}"; do
|
for client in "${client_instances[@]}"; do
|
||||||
( $client rpc post /blocks/head/operations with {} \
|
( $client rpc get /chains/main/blocks/head/operation_hashes \
|
||||||
| assert_in_output $hash ) \
|
| assert_in_output $hash ) \
|
||||||
|| exit 2
|
|| exit 2
|
||||||
done
|
done
|
||||||
|
@ -57,10 +57,10 @@ cleanup_clients() {
|
|||||||
|
|
||||||
wait_for_the_node_to_be_ready() {
|
wait_for_the_node_to_be_ready() {
|
||||||
local count=0
|
local count=0
|
||||||
if $client rpc post blocks/head/hash >/dev/null 2>&1; then return; fi
|
if $client rpc get /chains/main/blocks/head/hash >/dev/null 2>&1; then return; fi
|
||||||
printf "Waiting for the node to initialize..."
|
printf "Waiting for the node to initialize..."
|
||||||
sleep 1
|
sleep 1
|
||||||
while ! $client rpc post blocks/head/hash >/dev/null 2>&1
|
while ! $client rpc get /chains/main/blocks/head/hash >/dev/null 2>&1
|
||||||
do
|
do
|
||||||
count=$((count+1))
|
count=$((count+1))
|
||||||
if [ "$count" -ge 30 ]; then
|
if [ "$count" -ge 30 ]; then
|
||||||
@ -301,7 +301,7 @@ The client is now properly initialized. In the rest of this shell
|
|||||||
session, you might now run \`tezos-client\` to communicate with a
|
session, you might now run \`tezos-client\` to communicate with a
|
||||||
tezos node launched with \`launch-sandboxed-node $1\`. For instance:
|
tezos node launched with \`launch-sandboxed-node $1\`. For instance:
|
||||||
|
|
||||||
tezos-client rpc post blocks/head/protocol
|
tezos-client rpc get /chains/main/blocks/head/metadata/protocol_hash
|
||||||
|
|
||||||
Note: if the current protocol version, as reported by the previous
|
Note: if the current protocol version, as reported by the previous
|
||||||
command, is "ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im", you
|
command, is "ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im", you
|
||||||
|
@ -207,7 +207,7 @@ let init_rpc (rpc_config: Node_config_file.rpc) node =
|
|||||||
failwith "Cannot resolve listening address: %S" addr
|
failwith "Cannot resolve listening address: %S" addr
|
||||||
| (addr, port) :: _ ->
|
| (addr, port) :: _ ->
|
||||||
let host = Ipaddr.V6.to_string addr in
|
let host = Ipaddr.V6.to_string addr in
|
||||||
let dir = Node_rpc.build_rpc_directory node in
|
let dir = Node.build_rpc_directory node in
|
||||||
let mode =
|
let mode =
|
||||||
match rpc_config.tls with
|
match rpc_config.tls with
|
||||||
| None -> `TCP (`Port port)
|
| None -> `TCP (`Port port)
|
||||||
|
@ -9,54 +9,98 @@
|
|||||||
|
|
||||||
let wait_for_operation_inclusion
|
let wait_for_operation_inclusion
|
||||||
(ctxt : #Client_context.full)
|
(ctxt : #Client_context.full)
|
||||||
|
~chain
|
||||||
?(predecessors = 10)
|
?(predecessors = 10)
|
||||||
?(confirmations = 1)
|
?(confirmations = 1)
|
||||||
operation_hash =
|
operation_hash =
|
||||||
let confirmed_blocks = Hashtbl.create confirmations in
|
|
||||||
|
(* Table of known blocks:
|
||||||
|
- None: if neither the block or its predecessors contains the operation
|
||||||
|
- (Some n): if the `n-th` predecessors of the block contains the operation *)
|
||||||
|
|
||||||
|
let blocks : int option Block_hash.Table.t =
|
||||||
|
Block_hash.Table.create confirmations in
|
||||||
|
|
||||||
|
(* Fetch _all_ the 'unknown' predecessors af a block. *)
|
||||||
|
|
||||||
|
let fetch_predecessors block =
|
||||||
|
let rec loop acc block =
|
||||||
|
Block_services.Empty.Header.Shell.predecessor
|
||||||
|
ctxt ~chain ~block:(`Hash (block, 0)) () >>=? fun predecessor ->
|
||||||
|
if Block_hash.Table.mem blocks predecessor then
|
||||||
|
return acc
|
||||||
|
else
|
||||||
|
loop (predecessor :: acc) predecessor
|
||||||
|
in
|
||||||
|
loop [block] block >>= function
|
||||||
|
| Ok blocks -> Lwt.return blocks
|
||||||
|
| Error err ->
|
||||||
|
ctxt#warning
|
||||||
|
"Error while fetching block (ignored): %a"
|
||||||
|
pp_print_error err >>= fun () ->
|
||||||
|
(* Will be retried when a new head arrives *)
|
||||||
|
Lwt.return [] in
|
||||||
|
|
||||||
|
(* Check whether a block as enough confirmations. This function
|
||||||
|
assumes that the block predecessor has been processed already. *)
|
||||||
|
|
||||||
let process block =
|
let process block =
|
||||||
Block_services.hash ctxt block >>=? fun hash ->
|
Block_services.Empty.hash ctxt ~chain ~block () >>=? fun hash ->
|
||||||
Block_services.predecessor ctxt block >>=? fun predecessor ->
|
Block_services.Empty.Header.Shell.predecessor
|
||||||
match Hashtbl.find_opt confirmed_blocks predecessor with
|
ctxt ~chain ~block () >>=? fun predecessor ->
|
||||||
|
match Block_hash.Table.find blocks predecessor with
|
||||||
| Some n ->
|
| Some n ->
|
||||||
ctxt#answer
|
ctxt#answer
|
||||||
"Operation received %d confirmations as of block: %a"
|
"Operation received %d confirmations as of block: %a"
|
||||||
(n+1) Block_hash.pp hash >>= fun () ->
|
(n+1) Block_hash.pp hash >>= fun () ->
|
||||||
if n+1 < confirmations then begin
|
if n+1 < confirmations then begin
|
||||||
Hashtbl.add confirmed_blocks hash (n+1) ;
|
Block_hash.Table.add blocks hash (Some (n+1)) ;
|
||||||
return false
|
return false
|
||||||
end else
|
end else
|
||||||
return true
|
return true
|
||||||
| None ->
|
| None ->
|
||||||
Block_services.operations
|
Block_services.Empty.Operation_hash.operation_hashes
|
||||||
ctxt ~contents:false block >>=? fun operations ->
|
ctxt ~chain ~block () >>=? fun operations ->
|
||||||
let in_block =
|
let in_block =
|
||||||
List.exists
|
List.exists
|
||||||
(List.exists
|
(List.exists
|
||||||
(fun (oph, _) -> Operation_hash.equal operation_hash oph))
|
(Operation_hash.equal operation_hash))
|
||||||
operations in
|
operations in
|
||||||
if not in_block then
|
if not in_block then begin
|
||||||
|
Block_hash.Table.add blocks hash None ;
|
||||||
return false
|
return false
|
||||||
else begin
|
end else begin
|
||||||
ctxt#answer
|
ctxt#answer
|
||||||
"Operation found in block: %a"
|
"Operation found in block: %a"
|
||||||
Block_hash.pp hash >>= fun () ->
|
Block_hash.pp hash >>= fun () ->
|
||||||
if confirmations <= 0 then
|
if confirmations <= 0 then
|
||||||
return true
|
return true
|
||||||
else begin
|
else begin
|
||||||
Hashtbl.add confirmed_blocks hash 0 ;
|
Block_hash.Table.add blocks hash (Some 0) ;
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
end in
|
end in
|
||||||
Block_services.monitor
|
|
||||||
~include_ops:false
|
Shell_services.Monitor.heads ctxt chain >>=? fun (stream, stop) ->
|
||||||
~length:predecessors ctxt >>=? fun (stream, stop) ->
|
Lwt_stream.get stream >>= function
|
||||||
|
| None -> assert false
|
||||||
|
| Some head ->
|
||||||
|
let rec loop n =
|
||||||
|
if n >= 0 then
|
||||||
|
process (`Hash (head, n)) >>=? function
|
||||||
|
| true ->
|
||||||
|
stop () ;
|
||||||
|
return ()
|
||||||
|
| false ->
|
||||||
|
loop (n-1)
|
||||||
|
else
|
||||||
let exception WrapError of error list in
|
let exception WrapError of error list in
|
||||||
let stream = Lwt_stream.map_list List.concat stream in
|
|
||||||
Lwt.catch
|
Lwt.catch
|
||||||
(fun () ->
|
(fun () ->
|
||||||
|
let stream = Lwt_stream.map_list_s fetch_predecessors stream in
|
||||||
Lwt_stream.find_s
|
Lwt_stream.find_s
|
||||||
(fun bi ->
|
(fun block ->
|
||||||
process (`Hash (bi.Block_services.hash, 0)) >>= function
|
process (`Hash (block, 0)) >>= function
|
||||||
| Ok b -> Lwt.return b
|
| Ok b -> Lwt.return b
|
||||||
| Error err ->
|
| Error err ->
|
||||||
Lwt.fail (WrapError err)) stream >>= return)
|
Lwt.fail (WrapError err)) stream >>= return)
|
||||||
@ -64,4 +108,9 @@ let wait_for_operation_inclusion
|
|||||||
| WrapError e -> Lwt.return (Error e)
|
| WrapError e -> Lwt.return (Error e)
|
||||||
| exn -> Lwt.fail exn) >>=? fun _ ->
|
| exn -> Lwt.fail exn) >>=? fun _ ->
|
||||||
stop () ;
|
stop () ;
|
||||||
return ()
|
return () in
|
||||||
|
Block_services.Empty.hash
|
||||||
|
ctxt ~block:(`Hash (head, predecessors+1)) () >>=? fun oldest ->
|
||||||
|
Block_hash.Table.add blocks oldest None ;
|
||||||
|
loop predecessors
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
val wait_for_operation_inclusion:
|
val wait_for_operation_inclusion:
|
||||||
#Client_context.full ->
|
#Client_context.full ->
|
||||||
|
chain:Chain_services.chain ->
|
||||||
?predecessors:int ->
|
?predecessors:int ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
Operation_hash.t ->
|
Operation_hash.t ->
|
||||||
|
@ -20,7 +20,7 @@ let commands () =
|
|||||||
(fun () blocks (cctxt : #Client_context.full) ->
|
(fun () blocks (cctxt : #Client_context.full) ->
|
||||||
iter_s
|
iter_s
|
||||||
(fun block ->
|
(fun block ->
|
||||||
Block_services.unmark_invalid cctxt block >>=? fun () ->
|
Chain_services.Invalid_blocks.delete cctxt block >>=? fun () ->
|
||||||
cctxt#message
|
cctxt#message
|
||||||
"Block %a no longer marked invalid."
|
"Block %a no longer marked invalid."
|
||||||
Block_hash.pp block >>= fun () ->
|
Block_hash.pp block >>= fun () ->
|
||||||
|
@ -26,7 +26,7 @@ let commands () = Clic.[
|
|||||||
~desc: "the prefix of the hash to complete" @@
|
~desc: "the prefix of the hash to complete" @@
|
||||||
stop)
|
stop)
|
||||||
(fun unique prefix (cctxt : #Client_context.full) ->
|
(fun unique prefix (cctxt : #Client_context.full) ->
|
||||||
Shell_services.complete
|
Block_services.Empty.Helpers.complete
|
||||||
cctxt ~block:cctxt#block prefix >>=? fun completions ->
|
cctxt ~block:cctxt#block prefix >>=? fun completions ->
|
||||||
match completions with
|
match completions with
|
||||||
| [] -> Pervasives.exit 3
|
| [] -> Pervasives.exit 3
|
||||||
|
@ -13,32 +13,14 @@ let skip_line ppf =
|
|||||||
Format.pp_print_newline ppf ();
|
Format.pp_print_newline ppf ();
|
||||||
return @@ Format.pp_print_newline ppf ()
|
return @@ Format.pp_print_newline ppf ()
|
||||||
|
|
||||||
let print_heads ppf heads =
|
let print_invalid_blocks ppf (b: Chain_services.invalid_block) =
|
||||||
Format.pp_print_list ~pp_sep:Format.pp_print_newline
|
|
||||||
(fun ppf blocks ->
|
|
||||||
Format.pp_print_list
|
|
||||||
~pp_sep:Format.pp_print_newline
|
|
||||||
Block_services.pp_block_info
|
|
||||||
ppf
|
|
||||||
blocks)
|
|
||||||
ppf heads
|
|
||||||
|
|
||||||
let print_rejected ppf = function
|
|
||||||
| [] -> Format.fprintf ppf "No invalid blocks."
|
|
||||||
| invalid ->
|
|
||||||
Format.pp_print_list
|
|
||||||
(fun ppf (hash, level, errors) ->
|
|
||||||
Format.fprintf ppf
|
Format.fprintf ppf
|
||||||
"@[<v 2>Hash: %a\
|
"@[<v 2>Hash: %a\
|
||||||
@ Level: %ld\
|
@ Level: %ld\
|
||||||
@ Errors: @[<v>%a@]@]"
|
@ %a@]"
|
||||||
Block_hash.pp hash
|
Block_hash.pp b.hash
|
||||||
level
|
b.level
|
||||||
(Format.pp_print_list ~pp_sep:Format.pp_print_newline
|
pp_print_error b.errors
|
||||||
Error_monad.pp)
|
|
||||||
errors)
|
|
||||||
ppf
|
|
||||||
invalid
|
|
||||||
|
|
||||||
let commands () =
|
let commands () =
|
||||||
let open Clic in
|
let open Clic in
|
||||||
@ -63,28 +45,22 @@ let commands () =
|
|||||||
(args1 output_arg)
|
(args1 output_arg)
|
||||||
(fixed [ "list" ; "heads" ])
|
(fixed [ "list" ; "heads" ])
|
||||||
(fun ppf cctxt ->
|
(fun ppf cctxt ->
|
||||||
Block_services.list ~include_ops:true ~length:1 cctxt >>=? fun heads ->
|
Chain_services.Blocks.list cctxt () >>=? fun heads ->
|
||||||
Format.fprintf ppf "%a@." print_heads heads ;
|
Format.fprintf ppf "@[<v>%a@]@."
|
||||||
|
(Format.pp_print_list Block_hash.pp)
|
||||||
|
(List.concat heads) ;
|
||||||
return ()) ;
|
return ()) ;
|
||||||
command ~group ~desc: "The blocks that have been marked invalid by the node."
|
command ~group ~desc: "The blocks that have been marked invalid by the node."
|
||||||
(args1 output_arg)
|
(args1 output_arg)
|
||||||
(fixed [ "list" ; "rejected" ; "blocks" ])
|
(fixed [ "list" ; "rejected" ; "blocks" ])
|
||||||
(fun ppf cctxt ->
|
(fun ppf cctxt ->
|
||||||
Block_services.list_invalid cctxt >>=? fun invalid ->
|
Chain_services.Invalid_blocks.list cctxt () >>=? function
|
||||||
Format.fprintf ppf "%a@." print_rejected invalid ;
|
| [] ->
|
||||||
return ()) ;
|
Format.fprintf ppf "No invalid blocks." ;
|
||||||
command ~group ~desc: "A full report of the node's state."
|
return ()
|
||||||
(args1 output_arg)
|
| _ :: _ as invalid ->
|
||||||
(fixed [ "full" ; "report" ])
|
Format.fprintf ppf "@[<v>%a@]@."
|
||||||
(fun ppf cctxt ->
|
(Format.pp_print_list print_invalid_blocks)
|
||||||
Block_services.list ~include_ops:true ~length:1 cctxt >>=? fun heads ->
|
invalid ;
|
||||||
Block_services.list_invalid cctxt >>=? fun invalid ->
|
|
||||||
Format.fprintf ppf
|
|
||||||
"@[<v 0>@{<title>Date@} %a@,\
|
|
||||||
@[<v 2>@{<title>Heads@}@,%a@]@,\
|
|
||||||
@[<v 2>@{<title>Rejected blocks@}@,%a@]@]"
|
|
||||||
Time.pp_hum (Time.now ())
|
|
||||||
print_heads heads
|
|
||||||
print_rejected invalid ;
|
|
||||||
return ()) ;
|
return ()) ;
|
||||||
]
|
]
|
||||||
|
@ -50,9 +50,7 @@ type quota = {
|
|||||||
|
|
||||||
type rpc_context = {
|
type rpc_context = {
|
||||||
block_hash: Block_hash.t ;
|
block_hash: Block_hash.t ;
|
||||||
block_header: Block_header.t ;
|
block_header: Block_header.shell_header ;
|
||||||
operation_hashes: unit -> Operation_hash.t list list Lwt.t ;
|
|
||||||
operations: unit -> Operation.t list list Lwt.t ;
|
|
||||||
context: Context.t ;
|
context: Context.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,9 +47,7 @@ module Make (Context : CONTEXT) = struct
|
|||||||
|
|
||||||
type rpc_context = {
|
type rpc_context = {
|
||||||
block_hash: Block_hash.t ;
|
block_hash: Block_hash.t ;
|
||||||
block_header: Block_header.t ;
|
block_header: Block_header.shell_header ;
|
||||||
operation_hashes: unit -> Operation_hash.t list list Lwt.t ;
|
|
||||||
operations: unit -> Operation.t list list Lwt.t ;
|
|
||||||
context: Context.t ;
|
context: Context.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,9 +169,9 @@ module Make (Context : CONTEXT) = struct
|
|||||||
and type operation = P.operation
|
and type operation = P.operation
|
||||||
and type validation_state = P.validation_state
|
and type validation_state = P.validation_state
|
||||||
|
|
||||||
class ['block] proto_rpc_context :
|
class ['chain, 'block] proto_rpc_context :
|
||||||
Tezos_rpc.RPC_context.t -> (unit, unit * 'block) RPC_path.t ->
|
Tezos_rpc.RPC_context.t -> (unit, (unit * 'chain) * 'block) RPC_path.t ->
|
||||||
['block] RPC_context.simple
|
[('chain * 'block)] RPC_context.simple
|
||||||
|
|
||||||
class ['block] proto_rpc_context_of_directory :
|
class ['block] proto_rpc_context_of_directory :
|
||||||
('block -> RPC_context.t) -> RPC_context.t RPC_directory.t ->
|
('block -> RPC_context.t) -> RPC_context.t RPC_directory.t ->
|
||||||
@ -589,9 +587,7 @@ module Make (Context : CONTEXT) = struct
|
|||||||
|
|
||||||
type nonrec rpc_context = rpc_context = {
|
type nonrec rpc_context = rpc_context = {
|
||||||
block_hash: Block_hash.t ;
|
block_hash: Block_hash.t ;
|
||||||
block_header: Block_header.t ;
|
block_header: Block_header.shell_header ;
|
||||||
operation_hashes: unit -> Operation_hash.t list list Lwt.t ;
|
|
||||||
operations: unit -> Operation.t list list Lwt.t ;
|
|
||||||
context: Context.t ;
|
context: Context.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -663,47 +659,47 @@ module Make (Context : CONTEXT) = struct
|
|||||||
let init c bh = init c bh >|= wrap_error
|
let init c bh = init c bh >|= wrap_error
|
||||||
end
|
end
|
||||||
|
|
||||||
class ['block] proto_rpc_context
|
class ['chain, 'block] proto_rpc_context
|
||||||
(t : Tezos_rpc.RPC_context.t)
|
(t : Tezos_rpc.RPC_context.t)
|
||||||
(prefix : (unit, unit * 'block) RPC_path.t) =
|
(prefix : (unit, (unit * 'chain) * 'block) RPC_path.t) =
|
||||||
object
|
object
|
||||||
method call_proto_service0
|
method call_proto_service0
|
||||||
: 'm 'q 'i 'o.
|
: 'm 'q 'i 'o.
|
||||||
([< RPC_service.meth ] as 'm, RPC_context.t,
|
([< RPC_service.meth ] as 'm, RPC_context.t,
|
||||||
RPC_context.t, 'q, 'i, 'o) RPC_service.t ->
|
RPC_context.t, 'q, 'i, 'o) RPC_service.t ->
|
||||||
'block -> 'q -> 'i -> 'o tzresult Lwt.t
|
('chain * 'block) -> 'q -> 'i -> 'o tzresult Lwt.t
|
||||||
= fun s block q i ->
|
= fun s (chain, block) q i ->
|
||||||
let s = RPC_service.subst0 s in
|
let s = RPC_service.subst0 s in
|
||||||
let s = RPC_service.prefix prefix s in
|
let s = RPC_service.prefix prefix s in
|
||||||
t#call_service s ((), block) q i
|
t#call_service s (((), chain), block) q i
|
||||||
method call_proto_service1
|
method call_proto_service1
|
||||||
: 'm 'a 'q 'i 'o.
|
: 'm 'a 'q 'i 'o.
|
||||||
([< RPC_service.meth ] as 'm, RPC_context.t,
|
([< RPC_service.meth ] as 'm, RPC_context.t,
|
||||||
RPC_context.t * 'a, 'q, 'i, 'o) RPC_service.t ->
|
RPC_context.t * 'a, 'q, 'i, 'o) RPC_service.t ->
|
||||||
'block -> 'a -> 'q -> 'i -> 'o tzresult Lwt.t
|
('chain * 'block) -> 'a -> 'q -> 'i -> 'o tzresult Lwt.t
|
||||||
= fun s block a1 q i ->
|
= fun s (chain, block) a1 q i ->
|
||||||
let s = RPC_service.subst1 s in
|
let s = RPC_service.subst1 s in
|
||||||
let s = RPC_service.prefix prefix s in
|
let s = RPC_service.prefix prefix s in
|
||||||
t#call_service s (((), block), a1) q i
|
t#call_service s ((((), chain), block), a1) q i
|
||||||
method call_proto_service2
|
method call_proto_service2
|
||||||
: 'm 'a 'b 'q 'i 'o.
|
: 'm 'a 'b 'q 'i 'o.
|
||||||
([< RPC_service.meth ] as 'm, RPC_context.t,
|
([< RPC_service.meth ] as 'm, RPC_context.t,
|
||||||
(RPC_context.t * 'a) * 'b, 'q, 'i, 'o) RPC_service.t ->
|
(RPC_context.t * 'a) * 'b, 'q, 'i, 'o) RPC_service.t ->
|
||||||
'block -> 'a -> 'b -> 'q -> 'i -> 'o tzresult Lwt.t
|
('chain * 'block) -> 'a -> 'b -> 'q -> 'i -> 'o tzresult Lwt.t
|
||||||
= fun s block a1 a2 q i ->
|
= fun s (chain, block) a1 a2 q i ->
|
||||||
let s = RPC_service.subst2 s in
|
let s = RPC_service.subst2 s in
|
||||||
let s = RPC_service.prefix prefix s in
|
let s = RPC_service.prefix prefix s in
|
||||||
t#call_service s ((((), block), a1), a2) q i
|
t#call_service s (((((), chain), block), a1), a2) q i
|
||||||
method call_proto_service3
|
method call_proto_service3
|
||||||
: 'm 'a 'b 'c 'q 'i 'o.
|
: 'm 'a 'b 'c 'q 'i 'o.
|
||||||
([< RPC_service.meth ] as 'm, RPC_context.t,
|
([< RPC_service.meth ] as 'm, RPC_context.t,
|
||||||
((RPC_context.t * 'a) * 'b) * 'c,
|
((RPC_context.t * 'a) * 'b) * 'c,
|
||||||
'q, 'i, 'o) RPC_service.t ->
|
'q, 'i, 'o) RPC_service.t ->
|
||||||
'block -> 'a -> 'b -> 'c -> 'q -> 'i -> 'o tzresult Lwt.t
|
('chain * 'block) -> 'a -> 'b -> 'c -> 'q -> 'i -> 'o tzresult Lwt.t
|
||||||
= fun s block a1 a2 a3 q i ->
|
= fun s (chain, block) a1 a2 a3 q i ->
|
||||||
let s = RPC_service.subst3 s in
|
let s = RPC_service.subst3 s in
|
||||||
let s = RPC_service.prefix prefix s in
|
let s = RPC_service.prefix prefix s in
|
||||||
t#call_service s (((((), block), a1), a2), a3) q i
|
t#call_service s ((((((), chain), block), a1), a2), a3) q i
|
||||||
end
|
end
|
||||||
|
|
||||||
class ['block] proto_rpc_context_of_directory conv dir : ['block] RPC_context.simple =
|
class ['block] proto_rpc_context_of_directory conv dir : ['block] RPC_context.simple =
|
||||||
|
@ -40,9 +40,7 @@ module Make (Context : CONTEXT) : sig
|
|||||||
|
|
||||||
type rpc_context = {
|
type rpc_context = {
|
||||||
block_hash: Block_hash.t ;
|
block_hash: Block_hash.t ;
|
||||||
block_header: Block_header.t ;
|
block_header: Block_header.shell_header ;
|
||||||
operation_hashes: unit -> Operation_hash.t list list Lwt.t ;
|
|
||||||
operations: unit -> Operation.t list list Lwt.t ;
|
|
||||||
context: Context.t ;
|
context: Context.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,9 +162,9 @@ module Make (Context : CONTEXT) : sig
|
|||||||
and type operation = P.operation
|
and type operation = P.operation
|
||||||
and type validation_state = P.validation_state
|
and type validation_state = P.validation_state
|
||||||
|
|
||||||
class ['block] proto_rpc_context :
|
class ['chain, 'block] proto_rpc_context :
|
||||||
Tezos_rpc.RPC_context.t -> (unit, unit * 'block) RPC_path.t ->
|
Tezos_rpc.RPC_context.t -> (unit, (unit * 'chain) * 'block) RPC_path.t ->
|
||||||
['block] RPC_context.simple
|
[('chain * 'block)] RPC_context.simple
|
||||||
|
|
||||||
class ['block] proto_rpc_context_of_directory :
|
class ['block] proto_rpc_context_of_directory :
|
||||||
('block -> RPC_context.t) -> RPC_context.t RPC_directory.t ->
|
('block -> RPC_context.t) -> RPC_context.t RPC_directory.t ->
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
(libraries (tezos-base
|
(libraries (tezos-base
|
||||||
tezos-stdlib-unix
|
tezos-stdlib-unix
|
||||||
tezos-micheline
|
tezos-micheline
|
||||||
|
tezos-shell-services
|
||||||
tezos-protocol-environment-shell
|
tezos-protocol-environment-shell
|
||||||
tezos-protocol-compiler.registerer
|
tezos-protocol-compiler.registerer
|
||||||
tezos-protocol-compiler.native
|
tezos-protocol-compiler.native
|
||||||
@ -16,6 +17,7 @@
|
|||||||
-open Tezos_base__TzPervasives
|
-open Tezos_base__TzPervasives
|
||||||
-open Tezos_stdlib_unix
|
-open Tezos_stdlib_unix
|
||||||
-open Tezos_micheline
|
-open Tezos_micheline
|
||||||
|
-open Tezos_shell_services
|
||||||
-open Tezos_storage))))
|
-open Tezos_storage))))
|
||||||
|
|
||||||
(alias
|
(alias
|
||||||
|
@ -8,8 +8,13 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
module type T = sig
|
module type T = sig
|
||||||
|
module P : sig
|
||||||
val hash: Protocol_hash.t
|
val hash: Protocol_hash.t
|
||||||
include Tezos_protocol_environment_shell.PROTOCOL
|
include Tezos_protocol_environment_shell.PROTOCOL
|
||||||
|
end
|
||||||
|
include (module type of (struct include P end))
|
||||||
|
module Block_services :
|
||||||
|
(module type of (struct include Block_services.Make(P)(P) end))
|
||||||
val complete_b58prefix : Context.t -> string -> string list Lwt.t
|
val complete_b58prefix : Context.t -> string -> string list Lwt.t
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -22,9 +27,13 @@ let build_v1 hash =
|
|||||||
end in
|
end in
|
||||||
let module Env = Tezos_protocol_environment_shell.MakeV1(Name)() in
|
let module Env = Tezos_protocol_environment_shell.MakeV1(Name)() in
|
||||||
(module struct
|
(module struct
|
||||||
|
module Raw = F(Env)
|
||||||
|
module P = struct
|
||||||
let hash = hash
|
let hash = hash
|
||||||
module P = F(Env)
|
include Env.Lift(Raw)
|
||||||
include Env.Lift(P)
|
end
|
||||||
|
include P
|
||||||
|
module Block_services = Block_services.Make(P)(P)
|
||||||
let complete_b58prefix = Env.Context.complete
|
let complete_b58prefix = Env.Context.complete
|
||||||
end : T)
|
end : T)
|
||||||
|
|
||||||
@ -68,8 +77,12 @@ module Register
|
|||||||
VersionTable.add
|
VersionTable.add
|
||||||
versions hash
|
versions hash
|
||||||
(module struct
|
(module struct
|
||||||
|
module P = struct
|
||||||
let hash = hash
|
let hash = hash
|
||||||
include Env.Lift(Proto)
|
include Env.Lift(Proto)
|
||||||
|
end
|
||||||
|
include P
|
||||||
|
module Block_services = Block_services.Make(P)(P)
|
||||||
let complete_b58prefix = Env.Context.complete
|
let complete_b58prefix = Env.Context.complete
|
||||||
end : T)
|
end : T)
|
||||||
|
|
||||||
|
@ -8,8 +8,13 @@
|
|||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
module type T = sig
|
module type T = sig
|
||||||
|
module P : sig
|
||||||
val hash: Protocol_hash.t
|
val hash: Protocol_hash.t
|
||||||
include Tezos_protocol_environment_shell.PROTOCOL
|
include Tezos_protocol_environment_shell.PROTOCOL
|
||||||
|
end
|
||||||
|
include (module type of (struct include P end))
|
||||||
|
module Block_services :
|
||||||
|
(module type of (struct include Block_services.Make(P)(P) end))
|
||||||
val complete_b58prefix : Context.t -> string -> string list Lwt.t
|
val complete_b58prefix : Context.t -> string -> string list Lwt.t
|
||||||
end
|
end
|
||||||
|
|
||||||
|
340
src/lib_shell/block_directory.ml
Normal file
340
src/lib_shell/block_directory.ml
Normal file
@ -0,0 +1,340 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
let rec read_partial_context context path depth =
|
||||||
|
(* non tail-recursive *)
|
||||||
|
if depth = 0 then
|
||||||
|
Lwt.return Block_services.Cut
|
||||||
|
else
|
||||||
|
(* try to read as file *)
|
||||||
|
Context.get context path >>= function
|
||||||
|
| Some v ->
|
||||||
|
Lwt.return (Block_services.Key v)
|
||||||
|
| None ->
|
||||||
|
(* try to read as directory *)
|
||||||
|
Context.fold context path ~init:[] ~f: begin fun k acc ->
|
||||||
|
match k with
|
||||||
|
| `Key k | `Dir k ->
|
||||||
|
read_partial_context context k (depth-1) >>= fun v ->
|
||||||
|
let k = List.nth k ((List.length k)-1) in
|
||||||
|
Lwt.return ((k,v)::acc)
|
||||||
|
end >>= fun l ->
|
||||||
|
Lwt.return (Block_services.Dir (List.rev l))
|
||||||
|
|
||||||
|
let rpc_directory
|
||||||
|
(module Proto : Block_services.PROTO)
|
||||||
|
(module Next_proto : Registered_protocol.T) =
|
||||||
|
|
||||||
|
let dir : State.Block.t RPC_directory.t ref =
|
||||||
|
ref RPC_directory.empty in
|
||||||
|
|
||||||
|
let register0 s f =
|
||||||
|
dir :=
|
||||||
|
RPC_directory.register !dir (RPC_service.subst0 s)
|
||||||
|
(fun block p q -> f block p q) in
|
||||||
|
let register1 s f =
|
||||||
|
dir :=
|
||||||
|
RPC_directory.register !dir (RPC_service.subst1 s)
|
||||||
|
(fun (block, a) p q -> f block a p q) in
|
||||||
|
let register2 s f =
|
||||||
|
dir :=
|
||||||
|
RPC_directory.register !dir (RPC_service.subst2 s)
|
||||||
|
(fun ((block, a), b) p q -> f block a b p q) in
|
||||||
|
|
||||||
|
let module Block_services = Block_services.Make(Proto)(Next_proto) in
|
||||||
|
let module S = Block_services.S in
|
||||||
|
|
||||||
|
register0 S.hash begin fun block () () ->
|
||||||
|
return (State.Block.hash block)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* block header *)
|
||||||
|
|
||||||
|
register0 S.Header.header begin fun block () () ->
|
||||||
|
let chain_id = State.Block.chain_id block in
|
||||||
|
let hash = State.Block.hash block in
|
||||||
|
let header = State.Block.header block in
|
||||||
|
let protocol_data =
|
||||||
|
Data_encoding.Binary.of_bytes_exn
|
||||||
|
Proto.block_header_data_encoding
|
||||||
|
header.protocol_data in
|
||||||
|
return { Block_services.hash ; chain_id ;
|
||||||
|
shell = header.shell ; protocol_data }
|
||||||
|
end ;
|
||||||
|
register0 S.Header.shell_header begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell
|
||||||
|
end ;
|
||||||
|
register0 S.Header.Shell.level begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell.level
|
||||||
|
end ;
|
||||||
|
register0 S.Header.Shell.protocol_level begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell.proto_level
|
||||||
|
end ;
|
||||||
|
register0 S.Header.Shell.predecessor begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell.predecessor
|
||||||
|
end ;
|
||||||
|
register0 S.Header.Shell.timestamp begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell.timestamp
|
||||||
|
end ;
|
||||||
|
register0 S.Header.Shell.validation_passes begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell.validation_passes
|
||||||
|
end ;
|
||||||
|
register0 S.Header.Shell.operations_hash begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell.operations_hash
|
||||||
|
end ;
|
||||||
|
register0 S.Header.Shell.fitness begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell.fitness
|
||||||
|
end ;
|
||||||
|
register0 S.Header.Shell.context_hash begin fun block () () ->
|
||||||
|
return (State.Block.header block).shell.context
|
||||||
|
end ;
|
||||||
|
register0 S.Header.protocol_data begin fun block () () ->
|
||||||
|
let header = State.Block.header block in
|
||||||
|
return
|
||||||
|
(Data_encoding.Binary.of_bytes_exn
|
||||||
|
Proto.block_header_data_encoding
|
||||||
|
header.protocol_data)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* block metadata *)
|
||||||
|
|
||||||
|
let metadata block =
|
||||||
|
let protocol_data =
|
||||||
|
Data_encoding.Binary.of_bytes_exn
|
||||||
|
Proto.block_header_metadata_encoding
|
||||||
|
(State.Block.metadata block) in
|
||||||
|
State.Block.test_chain block >>= fun test_chain_status ->
|
||||||
|
return {
|
||||||
|
Block_services.protocol_data ;
|
||||||
|
test_chain_status ;
|
||||||
|
max_operations_ttl = State.Block.max_operations_ttl block ;
|
||||||
|
max_operation_data_length = State.Block.max_operation_data_length block ;
|
||||||
|
max_block_header_length = Next_proto.max_block_length ;
|
||||||
|
operation_list_quota =
|
||||||
|
List.map
|
||||||
|
(fun { Tezos_protocol_environment_shell.max_size; max_op } ->
|
||||||
|
{ Tezos_shell_services.Block_services.max_size ; max_op } )
|
||||||
|
Next_proto.validation_passes ;
|
||||||
|
} in
|
||||||
|
|
||||||
|
register0 S.Metadata.metadata begin fun block () () ->
|
||||||
|
metadata block
|
||||||
|
end ;
|
||||||
|
register0 S.Metadata.protocol_data begin fun block () () ->
|
||||||
|
return
|
||||||
|
(Data_encoding.Binary.of_bytes_exn
|
||||||
|
Proto.block_header_metadata_encoding
|
||||||
|
(State.Block.metadata block))
|
||||||
|
end ;
|
||||||
|
register0 S.Metadata.protocol_hash begin fun _block () () ->
|
||||||
|
return Proto.hash
|
||||||
|
end ;
|
||||||
|
register0 S.Metadata.next_protocol_hash begin fun _block () () ->
|
||||||
|
return Next_proto.hash
|
||||||
|
end ;
|
||||||
|
register0 S.Metadata.test_chain_status begin fun block () () ->
|
||||||
|
State.Block.test_chain block >>= return
|
||||||
|
end ;
|
||||||
|
register0 S.Metadata.max_operations_ttl begin fun block () () ->
|
||||||
|
return (State.Block.max_operations_ttl block)
|
||||||
|
end ;
|
||||||
|
register0 S.Metadata.max_operation_data_length begin fun block () () ->
|
||||||
|
return (State.Block.max_operation_data_length block)
|
||||||
|
end ;
|
||||||
|
register0 S.Metadata.max_block_header_length begin fun _block () () ->
|
||||||
|
return (Next_proto.max_block_length) ;
|
||||||
|
end ;
|
||||||
|
register0 S.Metadata.operation_list_quota begin fun _block () () ->
|
||||||
|
return
|
||||||
|
(List.map
|
||||||
|
(fun { Tezos_protocol_environment_shell.max_size; max_op } ->
|
||||||
|
{ Tezos_shell_services.Block_services.max_size ; max_op } )
|
||||||
|
Next_proto.validation_passes)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* operations *)
|
||||||
|
|
||||||
|
let convert chain_id (op : Operation.t) metadata =
|
||||||
|
let protocol_data =
|
||||||
|
Data_encoding.Binary.of_bytes_exn
|
||||||
|
Proto.operation_data_encoding
|
||||||
|
op.proto in
|
||||||
|
let metadata =
|
||||||
|
Data_encoding.Binary.of_bytes_exn
|
||||||
|
Proto.operation_metadata_encoding
|
||||||
|
metadata in
|
||||||
|
{ Block_services.chain_id ;
|
||||||
|
hash = Operation.hash op ;
|
||||||
|
shell = op.shell ;
|
||||||
|
protocol_data ;
|
||||||
|
metadata ;
|
||||||
|
} in
|
||||||
|
|
||||||
|
let operations block =
|
||||||
|
State.Block.all_operations block >>= fun ops ->
|
||||||
|
State.Block.all_operations_metadata block >>= fun metadata ->
|
||||||
|
let chain_id = State.Block.chain_id block in
|
||||||
|
return (List.map2 (List.map2 (convert chain_id)) ops metadata) in
|
||||||
|
|
||||||
|
register0 S.Operation.operations begin fun block () () ->
|
||||||
|
operations block
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register1 S.Operation.operations_in_pass begin fun block i () () ->
|
||||||
|
State.Block.operations block i >>= fun (ops, _path) ->
|
||||||
|
State.Block.operations_metadata block i >>= fun metadata ->
|
||||||
|
let chain_id = State.Block.chain_id block in
|
||||||
|
return (List.map2 (convert chain_id) ops metadata)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register2 S.Operation.operation begin fun block i j () () ->
|
||||||
|
State.Block.operations block i >>= fun (ops, _path) ->
|
||||||
|
State.Block.operations_metadata block i >>= fun metadata ->
|
||||||
|
let chain_id = State.Block.chain_id block in
|
||||||
|
return (convert chain_id (List.nth ops j) (List.nth metadata j))
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* operation_hashes *)
|
||||||
|
|
||||||
|
register0 S.Operation_hash.operation_hashes begin fun block () () ->
|
||||||
|
State.Block.all_operation_hashes block >>= return
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register1 S.Operation_hash.operation_hashes_in_pass begin fun block i () () ->
|
||||||
|
State.Block.operation_hashes block i >>= fun (ops, _) ->
|
||||||
|
return ops
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register2 S.Operation_hash.operation_hash begin fun block i j () () ->
|
||||||
|
State.Block.operation_hashes block i >>= fun (ops, _) ->
|
||||||
|
return (List.nth ops j)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* context *)
|
||||||
|
|
||||||
|
register1 S.Context.Raw.read begin fun block path q () ->
|
||||||
|
let depth = Option.unopt ~default:max_int q#depth in
|
||||||
|
fail_unless (depth >= 0)
|
||||||
|
(Tezos_shell_services.Block_services.Invalid_depth_arg (path, depth)) >>=? fun () ->
|
||||||
|
State.Block.context block >>= fun context ->
|
||||||
|
Context.mem context path >>= fun mem ->
|
||||||
|
Context.dir_mem context path >>= fun dir_mem ->
|
||||||
|
if not (mem || dir_mem) then
|
||||||
|
Lwt.fail Not_found
|
||||||
|
else
|
||||||
|
read_partial_context context path depth >>= fun dir ->
|
||||||
|
return dir
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* info *)
|
||||||
|
|
||||||
|
register0 S.info begin fun block () () ->
|
||||||
|
let chain_id = State.Block.chain_id block in
|
||||||
|
let hash = State.Block.hash block in
|
||||||
|
let header = State.Block.header block in
|
||||||
|
let shell = header.shell in
|
||||||
|
let protocol_data =
|
||||||
|
Data_encoding.Binary.of_bytes_exn
|
||||||
|
Proto.block_header_data_encoding
|
||||||
|
header.protocol_data in
|
||||||
|
metadata block >>=? fun metadata ->
|
||||||
|
operations block >>=? fun operations ->
|
||||||
|
return { Block_services.hash ; chain_id ;
|
||||||
|
header = { shell ; protocol_data } ;
|
||||||
|
metadata ; operations }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* helpers *)
|
||||||
|
|
||||||
|
register0 S.Helpers.preapply begin fun block q p ->
|
||||||
|
let protocol_data =
|
||||||
|
Data_encoding.Binary.to_bytes_exn
|
||||||
|
Next_proto.block_header_data_encoding
|
||||||
|
p.protocol_data in
|
||||||
|
let operations =
|
||||||
|
List.map
|
||||||
|
(List.map
|
||||||
|
(fun (op : Next_proto.operation) ->
|
||||||
|
let proto =
|
||||||
|
Data_encoding.Binary.to_bytes_exn
|
||||||
|
Next_proto.operation_data_encoding
|
||||||
|
op.protocol_data in
|
||||||
|
{ Operation.shell = op.shell ; proto }))
|
||||||
|
p.operations in
|
||||||
|
Prevalidation.preapply
|
||||||
|
~predecessor:block
|
||||||
|
~timestamp:p.timestamp
|
||||||
|
~protocol_data
|
||||||
|
~sort_operations:q#sort_operations
|
||||||
|
operations
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register1 S.Helpers.complete begin fun block prefix () () ->
|
||||||
|
State.Block.context block >>= fun ctxt ->
|
||||||
|
Base58.complete prefix >>= fun l1 ->
|
||||||
|
Next_proto.complete_b58prefix ctxt prefix >>= fun l2 ->
|
||||||
|
return (l1 @ l2)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* merge protocol rpcs... *)
|
||||||
|
|
||||||
|
RPC_directory.merge
|
||||||
|
!dir
|
||||||
|
(RPC_directory.map
|
||||||
|
(fun block ->
|
||||||
|
State.Block.context block >>= fun context ->
|
||||||
|
Lwt.return Tezos_protocol_environment_shell.{
|
||||||
|
block_hash = State.Block.hash block ;
|
||||||
|
block_header = State.Block.shell_header block ;
|
||||||
|
context })
|
||||||
|
Next_proto.rpc_services)
|
||||||
|
|
||||||
|
let get_protocol hash =
|
||||||
|
match Registered_protocol.get hash with
|
||||||
|
| None -> raise Not_found
|
||||||
|
| Some protocol -> protocol
|
||||||
|
|
||||||
|
let get_directory block =
|
||||||
|
State.Block.get_rpc_directory block >>= function
|
||||||
|
| Some dir -> Lwt.return dir
|
||||||
|
| None ->
|
||||||
|
State.Block.protocol_hash block >>= fun next_protocol_hash ->
|
||||||
|
let next_protocol = get_protocol next_protocol_hash in
|
||||||
|
State.Block.predecessor block >>= function
|
||||||
|
| None ->
|
||||||
|
Lwt.return (rpc_directory
|
||||||
|
(module Block_services.Fake_protocol)
|
||||||
|
next_protocol)
|
||||||
|
| Some pred ->
|
||||||
|
State.Block.protocol_hash pred >>= fun protocol_hash ->
|
||||||
|
let (module Proto) = get_protocol protocol_hash in
|
||||||
|
State.Block.get_rpc_directory block >>= function
|
||||||
|
| Some dir -> Lwt.return dir
|
||||||
|
| None ->
|
||||||
|
let dir = rpc_directory (module Proto) next_protocol in
|
||||||
|
State.Block.set_rpc_directory block dir >>= fun () ->
|
||||||
|
Lwt.return dir
|
||||||
|
|
||||||
|
let get_block chain_state = function
|
||||||
|
| `Genesis ->
|
||||||
|
Chain.genesis chain_state
|
||||||
|
| `Head n ->
|
||||||
|
Chain.head chain_state >>= fun head ->
|
||||||
|
if n = 0 then
|
||||||
|
Lwt.return head
|
||||||
|
else
|
||||||
|
State.Block.read_exn chain_state ~pred:n (State.Block.hash head)
|
||||||
|
| `Hash (hash, n) ->
|
||||||
|
State.Block.read_exn chain_state ~pred:n hash
|
||||||
|
|
||||||
|
let build_rpc_directory chain_state block =
|
||||||
|
get_block chain_state block >>= fun block ->
|
||||||
|
get_directory block >>= fun dir ->
|
||||||
|
Lwt.return (RPC_directory.map (fun _ -> block) dir)
|
||||||
|
|
15
src/lib_shell/block_directory.mli
Normal file
15
src/lib_shell/block_directory.mli
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
val get_block: State.Chain.t -> Block_services.block -> State.Block.t Lwt.t
|
||||||
|
|
||||||
|
val build_rpc_directory:
|
||||||
|
State.Chain.t ->
|
||||||
|
Block_services.block ->
|
||||||
|
'a RPC_directory.t Lwt.t
|
159
src/lib_shell/chain_directory.ml
Normal file
159
src/lib_shell/chain_directory.ml
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
open Chain_services
|
||||||
|
|
||||||
|
let get_chain_id state = function
|
||||||
|
| `Main -> Lwt.return (State.Chain.main state)
|
||||||
|
| `Test -> begin
|
||||||
|
State.Chain.get_exn state (State.Chain.main state) >>= fun main_chain ->
|
||||||
|
State.Chain.test main_chain >>= function
|
||||||
|
| None -> Lwt.fail Not_found
|
||||||
|
| Some chain_id -> Lwt.return chain_id
|
||||||
|
end
|
||||||
|
| `Hash chain_id ->
|
||||||
|
Lwt.return chain_id
|
||||||
|
|
||||||
|
let get_chain state chain =
|
||||||
|
get_chain_id state chain >>= fun chain_id ->
|
||||||
|
State.Chain.get_exn state chain_id
|
||||||
|
|
||||||
|
let predecessors ignored length head =
|
||||||
|
let rec loop acc length block =
|
||||||
|
if length <= 0 then
|
||||||
|
Lwt.return (List.rev acc)
|
||||||
|
else
|
||||||
|
State.Block.predecessor block >>= function
|
||||||
|
| None ->
|
||||||
|
Lwt.return (List.rev acc)
|
||||||
|
| Some pred ->
|
||||||
|
if Block_hash.Set.mem (State.Block.hash block) ignored then
|
||||||
|
Lwt.return (List.rev acc)
|
||||||
|
else
|
||||||
|
loop (State.Block.hash pred :: acc) (length-1) pred
|
||||||
|
in
|
||||||
|
loop [State.Block.hash head] (length-1) head
|
||||||
|
|
||||||
|
let list_blocks chain_state ?(length = 1) ?min_date heads =
|
||||||
|
begin
|
||||||
|
match heads with
|
||||||
|
| [] ->
|
||||||
|
Chain.known_heads chain_state >>= fun heads ->
|
||||||
|
let heads =
|
||||||
|
match min_date with
|
||||||
|
| None -> heads
|
||||||
|
| Some min_date ->
|
||||||
|
List.fold_left
|
||||||
|
(fun acc block ->
|
||||||
|
let timestamp = State.Block.timestamp block in
|
||||||
|
if Time.(min_date <= timestamp) then block :: acc
|
||||||
|
else acc)
|
||||||
|
[] heads in
|
||||||
|
let sorted_heads =
|
||||||
|
List.sort
|
||||||
|
(fun b1 b2 ->
|
||||||
|
let f1 = State.Block.fitness b1 in
|
||||||
|
let f2 = State.Block.fitness b2 in
|
||||||
|
~- (Fitness.compare f1 f2))
|
||||||
|
heads in
|
||||||
|
Lwt.return (List.map (fun b -> Some b) sorted_heads)
|
||||||
|
| _ :: _ as heads ->
|
||||||
|
Lwt_list.map_p (State.Block.read_opt chain_state) heads
|
||||||
|
end >>= fun requested_heads ->
|
||||||
|
Lwt_list.fold_left_s
|
||||||
|
(fun (ignored, acc) head ->
|
||||||
|
match head with
|
||||||
|
| None -> Lwt.return (ignored, [])
|
||||||
|
| Some block ->
|
||||||
|
predecessors ignored length block >>= fun predecessors ->
|
||||||
|
let ignored =
|
||||||
|
List.fold_right Block_hash.Set.add predecessors ignored in
|
||||||
|
Lwt.return (ignored, predecessors :: acc))
|
||||||
|
(Block_hash.Set.empty, [])
|
||||||
|
requested_heads >>= fun (_, blocks) ->
|
||||||
|
return (List.rev blocks)
|
||||||
|
|
||||||
|
let rpc_directory =
|
||||||
|
|
||||||
|
let dir : State.Chain.t Lwt.t RPC_directory.t ref =
|
||||||
|
ref RPC_directory.empty in
|
||||||
|
|
||||||
|
let register0 s f =
|
||||||
|
dir :=
|
||||||
|
RPC_directory.register !dir (RPC_service.subst0 s)
|
||||||
|
(fun chain p q -> chain >>= fun chain -> f chain p q) in
|
||||||
|
let register1 s f =
|
||||||
|
dir :=
|
||||||
|
RPC_directory.register !dir (RPC_service.subst1 s)
|
||||||
|
(fun (chain, a) p q -> chain >>= fun chain -> f chain a p q) in
|
||||||
|
|
||||||
|
let register_dynamic_directory2 ?descr s f =
|
||||||
|
dir :=
|
||||||
|
RPC_directory.register_dynamic_directory
|
||||||
|
!dir ?descr (RPC_path.subst1 s)
|
||||||
|
(fun (chain, a) -> chain >>= fun chain -> f chain a) in
|
||||||
|
|
||||||
|
register0 S.chain_id begin fun chain () () ->
|
||||||
|
return (State.Chain.id chain)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* blocks *)
|
||||||
|
|
||||||
|
register0 S.Blocks.list begin fun chain q () ->
|
||||||
|
list_blocks chain ?length:q#length ?min_date:q#min_date q#heads
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register_dynamic_directory2
|
||||||
|
Block_services.path
|
||||||
|
Block_directory.build_rpc_directory ;
|
||||||
|
|
||||||
|
(* invalid_blocks *)
|
||||||
|
|
||||||
|
register0 S.Invalid_blocks.list begin fun chain () () ->
|
||||||
|
let convert (hash, level, errors) = { hash ; level ; errors } in
|
||||||
|
State.Block.list_invalid chain >>= fun blocks ->
|
||||||
|
return (List.map convert blocks)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register1 S.Invalid_blocks.get begin fun chain hash () () ->
|
||||||
|
State.Block.read_invalid chain hash >>= function
|
||||||
|
| None -> Lwt.fail Not_found
|
||||||
|
| Some { level ; errors } -> return { hash ; level ; errors }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register1 S.Invalid_blocks.delete begin fun chain hash () () ->
|
||||||
|
State.Block.unmark_invalid chain hash
|
||||||
|
end ;
|
||||||
|
|
||||||
|
!dir
|
||||||
|
|
||||||
|
let build_rpc_directory state validator =
|
||||||
|
|
||||||
|
let dir = ref rpc_directory in
|
||||||
|
|
||||||
|
(* Mempool *)
|
||||||
|
|
||||||
|
let register0 s f =
|
||||||
|
dir :=
|
||||||
|
RPC_directory.register !dir (RPC_service.subst0 s)
|
||||||
|
(fun chain p q -> chain >>= fun chain -> f chain p q) in
|
||||||
|
|
||||||
|
register0 S.Mempool.pending_operations begin fun chain () () ->
|
||||||
|
Validator.get_exn validator (State.Chain.id chain) >>= fun chain_validator ->
|
||||||
|
let pv_opt = Chain_validator.prevalidator chain_validator in
|
||||||
|
match pv_opt with
|
||||||
|
| Some pv ->
|
||||||
|
return (Prevalidator.operations pv)
|
||||||
|
| None ->
|
||||||
|
return (Preapply_result.empty, Operation_hash.Map.empty)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
RPC_directory.prefix Chain_services.path @@
|
||||||
|
RPC_directory.map (fun ((), chain) -> get_chain state chain) !dir
|
||||||
|
|
@ -7,16 +7,9 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
|
val get_chain_id: State.t -> Chain_services.chain -> Chain_id.t Lwt.t
|
||||||
|
val get_chain: State.t -> Chain_services.chain -> State.Chain.t Lwt.t
|
||||||
|
|
||||||
module S : sig
|
val rpc_directory: State.Chain.t Lwt.t RPC_directory.t
|
||||||
val pending_operations:
|
|
||||||
([ `POST ], unit,
|
|
||||||
unit , unit, unit,
|
|
||||||
error Preapply_result.t * Operation.t Operation_hash.Map.t) RPC_service.t
|
|
||||||
end
|
|
||||||
|
|
||||||
open RPC_context
|
val build_rpc_directory: State.t -> Validator.t -> unit RPC_directory.t
|
||||||
|
|
||||||
val pending_operations:
|
|
||||||
#simple ->
|
|
||||||
(error Preapply_result.t * Operation.t Operation_hash.Map.t) tzresult Lwt.t
|
|
@ -10,57 +10,11 @@
|
|||||||
open Lwt.Infix
|
open Lwt.Infix
|
||||||
open Worker_logging
|
open Worker_logging
|
||||||
|
|
||||||
let inject_operation validator ?chain_id bytes =
|
|
||||||
let t =
|
|
||||||
match Data_encoding.Binary.of_bytes Operation.encoding bytes with
|
|
||||||
| None -> failwith "Can't parse the operation"
|
|
||||||
| Some op ->
|
|
||||||
Validator.inject_operation validator ?chain_id op
|
|
||||||
in
|
|
||||||
let hash = Operation_hash.hash_bytes [bytes] in
|
|
||||||
Lwt.return (hash, t)
|
|
||||||
|
|
||||||
let inject_protocol state ?force:_ proto =
|
|
||||||
let proto_bytes =
|
|
||||||
Data_encoding.Binary.to_bytes_exn Protocol.encoding proto in
|
|
||||||
let hash = Protocol_hash.hash_bytes [proto_bytes] in
|
|
||||||
let validation =
|
|
||||||
Updater.compile hash proto >>= function
|
|
||||||
| false ->
|
|
||||||
failwith
|
|
||||||
"Compilation failed (%a)"
|
|
||||||
Protocol_hash.pp_short hash
|
|
||||||
| true ->
|
|
||||||
State.Protocol.store state proto >>= function
|
|
||||||
| None ->
|
|
||||||
failwith
|
|
||||||
"Previously registered protocol (%a)"
|
|
||||||
Protocol_hash.pp_short hash
|
|
||||||
| Some _ -> return ()
|
|
||||||
in
|
|
||||||
Lwt.return (hash, validation)
|
|
||||||
|
|
||||||
let inject_block validator ?force ?chain_id bytes operations =
|
|
||||||
Validator.validate_block
|
|
||||||
validator ?force ?chain_id bytes operations >>=? fun (hash, block) ->
|
|
||||||
return (hash, (block >>=? fun _ -> return ()))
|
|
||||||
|
|
||||||
type t = {
|
type t = {
|
||||||
state: State.t ;
|
state: State.t ;
|
||||||
distributed_db: Distributed_db.t ;
|
distributed_db: Distributed_db.t ;
|
||||||
validator: Validator.t ;
|
validator: Validator.t ;
|
||||||
mainchain_validator: Chain_validator.t ;
|
mainchain_validator: Chain_validator.t ;
|
||||||
inject_block:
|
|
||||||
?force:bool ->
|
|
||||||
?chain_id:Chain_id.t ->
|
|
||||||
MBytes.t -> Operation.t list list ->
|
|
||||||
(Block_hash.t * unit tzresult Lwt.t) tzresult Lwt.t ;
|
|
||||||
inject_operation:
|
|
||||||
?chain_id:Chain_id.t -> MBytes.t ->
|
|
||||||
(Operation_hash.t * unit tzresult Lwt.t) Lwt.t ;
|
|
||||||
inject_protocol:
|
|
||||||
?force:bool -> Protocol.t ->
|
|
||||||
(Protocol_hash.t * unit tzresult Lwt.t) Lwt.t ;
|
|
||||||
p2p: Distributed_db.p2p ; (* For P2P RPCs *)
|
p2p: Distributed_db.p2p ; (* For P2P RPCs *)
|
||||||
shutdown: unit -> unit Lwt.t ;
|
shutdown: unit -> unit Lwt.t ;
|
||||||
}
|
}
|
||||||
@ -139,12 +93,6 @@ and chain_validator_limits = Chain_validator.limits = {
|
|||||||
worker_limits : Worker_types.limits ;
|
worker_limits : Worker_types.limits ;
|
||||||
}
|
}
|
||||||
|
|
||||||
let may_create_chain state genesis =
|
|
||||||
State.Chain.get state (Chain_id.of_block_hash genesis.State.Chain.block) >>= function
|
|
||||||
| Ok chain -> Lwt.return chain
|
|
||||||
| Error _ ->
|
|
||||||
State.Chain.create state genesis
|
|
||||||
|
|
||||||
let create { genesis ; store_root ; context_root ;
|
let create { genesis ; store_root ; context_root ;
|
||||||
patch_context ; p2p = p2p_params ;
|
patch_context ; p2p = p2p_params ;
|
||||||
test_chain_max_tll = max_child_ttl }
|
test_chain_max_tll = max_child_ttl }
|
||||||
@ -178,381 +126,28 @@ let create { genesis ; store_root ; context_root ;
|
|||||||
distributed_db ;
|
distributed_db ;
|
||||||
validator ;
|
validator ;
|
||||||
mainchain_validator ;
|
mainchain_validator ;
|
||||||
inject_block = inject_block validator ;
|
|
||||||
inject_operation = inject_operation validator ;
|
|
||||||
inject_protocol = inject_protocol state ;
|
|
||||||
p2p ;
|
p2p ;
|
||||||
shutdown ;
|
shutdown ;
|
||||||
}
|
}
|
||||||
|
|
||||||
let shutdown node = node.shutdown ()
|
let shutdown node = node.shutdown ()
|
||||||
|
|
||||||
module RPC = struct
|
let build_rpc_directory node =
|
||||||
|
let dir : unit RPC_directory.t ref = ref RPC_directory.empty in
|
||||||
|
let merge d = dir := RPC_directory.merge !dir d in
|
||||||
|
let register0 s f =
|
||||||
|
dir := RPC_directory.register !dir s (fun () p q -> f p q) in
|
||||||
|
|
||||||
type block = Block_services.block
|
merge (Protocol_directory.build_rpc_directory node.state node.distributed_db) ;
|
||||||
type block_info = Block_services.block_info = {
|
merge (Shell_directory.build_rpc_directory
|
||||||
hash: Block_hash.t ;
|
node.state node.validator node.mainchain_validator) ;
|
||||||
chain_id: Chain_id.t ;
|
merge (Chain_directory.build_rpc_directory node.state node.validator) ;
|
||||||
level: Int32.t ;
|
merge (P2p.build_rpc_directory node.p2p) ;
|
||||||
proto_level: int ; (* uint8 *)
|
merge Worker_directory.rpc_directory ;
|
||||||
predecessor: Block_hash.t ;
|
|
||||||
timestamp: Time.t ;
|
|
||||||
validation_passes: int ; (* uint8 *)
|
|
||||||
operations_hash: Operation_list_list_hash.t ;
|
|
||||||
fitness: MBytes.t list ;
|
|
||||||
context: Context_hash.t ;
|
|
||||||
protocol_data: MBytes.t ;
|
|
||||||
operations: (Operation_hash.t * Operation.t) list list option ;
|
|
||||||
protocol: Protocol_hash.t ;
|
|
||||||
test_chain: Test_chain_status.t ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let convert (block: State.Block.t) =
|
register0 RPC_service.error_service begin fun () () ->
|
||||||
let hash = State.Block.hash block in
|
return (Data_encoding.Json.schema Error_monad.error_encoding)
|
||||||
let header = State.Block.header block in
|
end ;
|
||||||
State.Block.all_operations block >>= fun operations ->
|
|
||||||
let operations =
|
|
||||||
List.map (List.map (fun op -> (Operation.hash op, op))) operations in
|
|
||||||
State.Block.context block >>= fun context ->
|
|
||||||
Context.get_protocol context >>= fun protocol ->
|
|
||||||
Context.get_test_chain context >>= fun test_chain ->
|
|
||||||
Lwt.return {
|
|
||||||
hash ;
|
|
||||||
chain_id = State.Block.chain_id block ;
|
|
||||||
level = header.shell.level ;
|
|
||||||
proto_level = header.shell.proto_level ;
|
|
||||||
predecessor = header.shell.predecessor ;
|
|
||||||
timestamp = header.shell.timestamp ;
|
|
||||||
validation_passes = header.shell.validation_passes ;
|
|
||||||
operations_hash = header.shell.operations_hash ;
|
|
||||||
fitness = header.shell.fitness ;
|
|
||||||
context = header.shell.context ;
|
|
||||||
protocol_data = header.protocol_data ;
|
|
||||||
operations = Some operations ;
|
|
||||||
protocol ;
|
|
||||||
test_chain ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let inject_block node = node.inject_block
|
RPC_directory.register_describe_directory_service
|
||||||
let inject_operation node = node.inject_operation
|
!dir RPC_service.description_service
|
||||||
let inject_protocol node = node.inject_protocol
|
|
||||||
|
|
||||||
let raw_block_info node hash =
|
|
||||||
State.read_block node.state hash >>= function
|
|
||||||
| Some block ->
|
|
||||||
convert block
|
|
||||||
| None ->
|
|
||||||
Lwt.fail Not_found
|
|
||||||
|
|
||||||
let prevalidation_hash =
|
|
||||||
Block_hash.of_b58check_exn
|
|
||||||
"BLockPrevaLidationPrevaLidationPrevaLidationPrZ4mr6"
|
|
||||||
|
|
||||||
let get_validator node = function
|
|
||||||
| `Genesis | `Head _ -> node.mainchain_validator
|
|
||||||
| `Test_head _ ->
|
|
||||||
match Chain_validator.child node.mainchain_validator with
|
|
||||||
| None -> raise Not_found
|
|
||||||
| Some v -> v
|
|
||||||
|
|
||||||
let get_validator_per_hash node hash =
|
|
||||||
State.read_block_exn node.state hash >>= fun block ->
|
|
||||||
let chain_id = State.Block.chain_id block in
|
|
||||||
if Chain_id.equal (Chain_validator.chain_id node.mainchain_validator) chain_id then
|
|
||||||
Lwt.return (Some node.mainchain_validator)
|
|
||||||
else
|
|
||||||
match Chain_validator.child node.mainchain_validator with
|
|
||||||
| Some test_validator ->
|
|
||||||
if Chain_id.equal (Chain_validator.chain_id test_validator) chain_id then
|
|
||||||
Lwt.return_some test_validator
|
|
||||||
else
|
|
||||||
Lwt.return_none
|
|
||||||
| _ -> Lwt.return_none
|
|
||||||
|
|
||||||
let read_valid_block node h n =
|
|
||||||
State.read_block node.state ~pred:n h
|
|
||||||
|
|
||||||
let read_valid_block_exn node h n =
|
|
||||||
State.read_block_exn node.state ~pred:n h
|
|
||||||
|
|
||||||
let get_block node = function
|
|
||||||
| `Genesis ->
|
|
||||||
let chain_state = Chain_validator.chain_state node.mainchain_validator in
|
|
||||||
Chain.genesis chain_state
|
|
||||||
| ( `Head n | `Test_head n ) as block ->
|
|
||||||
let validator = get_validator node block in
|
|
||||||
let chain_state = Chain_validator.chain_state validator in
|
|
||||||
Chain.head chain_state >>= fun head ->
|
|
||||||
if n = 0 then
|
|
||||||
Lwt.return head
|
|
||||||
else
|
|
||||||
read_valid_block_exn node (State.Block.hash head) n
|
|
||||||
| `Hash (hash, n) ->
|
|
||||||
read_valid_block node hash n >>= function
|
|
||||||
| None -> Lwt.fail Not_found
|
|
||||||
| Some b -> Lwt.return b
|
|
||||||
|
|
||||||
let block_info node (block: block) =
|
|
||||||
get_block node block >>= convert
|
|
||||||
|
|
||||||
let rpc_context block : Tezos_protocol_environment_shell.rpc_context Lwt.t =
|
|
||||||
let block_hash = State.Block.hash block in
|
|
||||||
let block_header = State.Block.header block in
|
|
||||||
State.Block.context block >|= fun context ->
|
|
||||||
{ Tezos_protocol_environment_shell.block_hash ;
|
|
||||||
block_header ;
|
|
||||||
operation_hashes = (fun () -> State.Block.all_operation_hashes block) ;
|
|
||||||
operations = (fun () -> State.Block.all_operations block) ;
|
|
||||||
context ;
|
|
||||||
}
|
|
||||||
|
|
||||||
let get_rpc_context node block =
|
|
||||||
Lwt.catch begin fun () ->
|
|
||||||
get_block node block >>= fun block ->
|
|
||||||
rpc_context block >>= fun ctxt ->
|
|
||||||
Lwt.return (Some ctxt)
|
|
||||||
end begin
|
|
||||||
fun _ -> Lwt.return None
|
|
||||||
end
|
|
||||||
|
|
||||||
let operation_hashes node block =
|
|
||||||
get_block node block >>= fun block ->
|
|
||||||
State.Block.all_operation_hashes block
|
|
||||||
|
|
||||||
let operations node block =
|
|
||||||
get_block node block >>= fun block ->
|
|
||||||
State.Block.all_operations block
|
|
||||||
|
|
||||||
let pending_operations node =
|
|
||||||
let validator = get_validator node (`Head 0) in
|
|
||||||
let pv_opt = Chain_validator.prevalidator validator in
|
|
||||||
match pv_opt with
|
|
||||||
| Some pv ->
|
|
||||||
Lwt.return (Prevalidator.operations pv)
|
|
||||||
| None ->
|
|
||||||
Lwt.return (Preapply_result.empty, Operation_hash.Map.empty)
|
|
||||||
|
|
||||||
let protocols { state } =
|
|
||||||
State.Protocol.list state >>= fun set ->
|
|
||||||
Lwt.return (Protocol_hash.Set.elements set)
|
|
||||||
|
|
||||||
let protocol_content node hash =
|
|
||||||
State.Protocol.read node.state hash
|
|
||||||
|
|
||||||
let preapply
|
|
||||||
node block
|
|
||||||
~timestamp ~protocol_data ~sort_operations:sort ops =
|
|
||||||
get_block node block >>= fun predecessor ->
|
|
||||||
Prevalidation.start_prevalidation
|
|
||||||
~protocol_data ~predecessor ~timestamp () >>=? fun validation_state ->
|
|
||||||
let ops = List.map (List.map (fun x -> Operation.hash x, x)) ops in
|
|
||||||
Lwt_list.fold_left_s
|
|
||||||
(fun (validation_state, rs) ops ->
|
|
||||||
Prevalidation.prevalidate
|
|
||||||
validation_state ~sort ops >>= fun (validation_state, r) ->
|
|
||||||
Lwt.return (validation_state, rs @ [r]))
|
|
||||||
(validation_state, []) ops >>= fun (validation_state, rs) ->
|
|
||||||
let operations_hash =
|
|
||||||
Operation_list_list_hash.compute
|
|
||||||
(List.map
|
|
||||||
(fun r ->
|
|
||||||
Operation_list_hash.compute
|
|
||||||
(List.map fst r.Preapply_result.applied))
|
|
||||||
rs) in
|
|
||||||
Prevalidation.end_prevalidation
|
|
||||||
validation_state >>=? fun { fitness ; context ; message } ->
|
|
||||||
let pred_shell_header = State.Block.shell_header predecessor in
|
|
||||||
State.Block.protocol_hash predecessor >>= fun pred_protocol ->
|
|
||||||
Context.get_protocol context >>= fun protocol ->
|
|
||||||
let proto_level =
|
|
||||||
if Protocol_hash.equal protocol pred_protocol then
|
|
||||||
pred_shell_header.proto_level
|
|
||||||
else
|
|
||||||
((pred_shell_header.proto_level + 1) mod 256) in
|
|
||||||
let shell_header : Block_header.shell_header = {
|
|
||||||
level = Int32.succ pred_shell_header.level ;
|
|
||||||
proto_level ;
|
|
||||||
predecessor = State.Block.hash predecessor ;
|
|
||||||
timestamp ;
|
|
||||||
validation_passes = List.length rs ;
|
|
||||||
operations_hash ;
|
|
||||||
fitness ;
|
|
||||||
context = Context_hash.zero ; (* place holder *)
|
|
||||||
} in
|
|
||||||
begin
|
|
||||||
if Protocol_hash.equal protocol pred_protocol then
|
|
||||||
return (context, message)
|
|
||||||
else
|
|
||||||
match Registered_protocol.get protocol with
|
|
||||||
| None ->
|
|
||||||
fail (Block_validator_errors.Unavailable_protocol
|
|
||||||
{ block = State.Block.hash predecessor ; protocol })
|
|
||||||
| Some (module NewProto) ->
|
|
||||||
NewProto.init context shell_header >>=? fun { context ; message ; _ } ->
|
|
||||||
return (context, message)
|
|
||||||
end >>=? fun (context, message) ->
|
|
||||||
Context.commit ?message ~time:timestamp context >>= fun context ->
|
|
||||||
return ({ shell_header with context }, rs)
|
|
||||||
|
|
||||||
let complete node ?block str =
|
|
||||||
match block with
|
|
||||||
| None ->
|
|
||||||
Base58.complete str
|
|
||||||
| Some block ->
|
|
||||||
get_rpc_context node block >>= function
|
|
||||||
| None -> Lwt.fail Not_found
|
|
||||||
| Some { context = ctxt } ->
|
|
||||||
Context.get_protocol ctxt >>= fun protocol_hash ->
|
|
||||||
let (module Proto) = Registered_protocol.get_exn protocol_hash in
|
|
||||||
Base58.complete str >>= fun l1 ->
|
|
||||||
Proto.complete_b58prefix ctxt str >>= fun l2 ->
|
|
||||||
Lwt.return (l1 @ l2)
|
|
||||||
|
|
||||||
let context_dir node block =
|
|
||||||
get_rpc_context node block >>= function
|
|
||||||
| None -> Lwt.return None
|
|
||||||
| Some rpc_context ->
|
|
||||||
Context.get_protocol rpc_context.context >>= fun protocol_hash ->
|
|
||||||
let (module Proto) = Registered_protocol.get_exn protocol_hash in
|
|
||||||
let dir = RPC_directory.map (fun () -> Lwt.return rpc_context) Proto.rpc_services in
|
|
||||||
Lwt.return (Some (RPC_directory.map (fun _ -> ()) dir))
|
|
||||||
|
|
||||||
let context_raw_get node block ~path ~depth =
|
|
||||||
let open Block_services in
|
|
||||||
(* negative depth could be handled by a more informative error *)
|
|
||||||
if depth < 0 then Lwt.return_none else
|
|
||||||
get_rpc_context node block >>= function
|
|
||||||
| None -> Lwt.return_none
|
|
||||||
| Some rpc_context ->
|
|
||||||
let rec loop path depth = (* non tail-recursive *)
|
|
||||||
if depth = 0 then Lwt.return Cut else
|
|
||||||
(* try to read as file *)
|
|
||||||
Context.get rpc_context.context path >>= function
|
|
||||||
| Some v -> Lwt.return (Key v)
|
|
||||||
| None -> (* try to read as directory *)
|
|
||||||
Context.fold rpc_context.context path ~init:[]
|
|
||||||
~f:(fun k acc ->
|
|
||||||
match k with
|
|
||||||
| `Key k | `Dir k ->
|
|
||||||
loop k (depth-1) >>= fun v ->
|
|
||||||
let k = List.nth k ((List.length k)-1) in
|
|
||||||
Lwt.return ((k,v)::acc)) >>= fun l ->
|
|
||||||
Lwt.return (Dir (List.rev l))
|
|
||||||
in
|
|
||||||
Context.mem rpc_context.context path >>= fun mem ->
|
|
||||||
Context.dir_mem rpc_context.context path >>= fun dir_mem ->
|
|
||||||
if mem || dir_mem then
|
|
||||||
loop path depth >>= Lwt.return_some
|
|
||||||
else Lwt.return_none
|
|
||||||
|
|
||||||
let heads node =
|
|
||||||
let chain_state = Chain_validator.chain_state node.mainchain_validator in
|
|
||||||
Chain.known_heads chain_state >>= fun heads ->
|
|
||||||
begin
|
|
||||||
match Chain_validator.child node.mainchain_validator with
|
|
||||||
| None -> Lwt.return_nil
|
|
||||||
| Some test_validator ->
|
|
||||||
let chain_state = Chain_validator.chain_state test_validator in
|
|
||||||
Chain.known_heads chain_state
|
|
||||||
end >>= fun test_heads ->
|
|
||||||
Lwt_list.fold_left_s
|
|
||||||
(fun map block ->
|
|
||||||
convert block >|= fun bi ->
|
|
||||||
Block_hash.Map.add
|
|
||||||
(State.Block.hash block) bi map)
|
|
||||||
Block_hash.Map.empty (test_heads @ heads)
|
|
||||||
|
|
||||||
let predecessors node len head =
|
|
||||||
let rec loop acc len block =
|
|
||||||
if len = 0 then
|
|
||||||
Lwt.return (List.rev acc)
|
|
||||||
else
|
|
||||||
State.Block.predecessor block >>= function
|
|
||||||
| None -> Lwt.return (List.rev acc)
|
|
||||||
| Some block ->
|
|
||||||
loop (State.Block.hash block :: acc) (len-1) block
|
|
||||||
in
|
|
||||||
try
|
|
||||||
State.read_block_exn node.state head >>= fun block ->
|
|
||||||
loop [] len block
|
|
||||||
with Not_found -> Lwt.return_nil
|
|
||||||
|
|
||||||
let predecessors_bi ignored len head =
|
|
||||||
try
|
|
||||||
let rec loop acc len block =
|
|
||||||
convert block >>= fun bi ->
|
|
||||||
State.Block.predecessor block >>= function
|
|
||||||
| None ->
|
|
||||||
Lwt.return (List.rev (bi :: acc))
|
|
||||||
| Some pred ->
|
|
||||||
if len = 0 ||
|
|
||||||
Block_hash.Set.mem (State.Block.hash block) ignored then
|
|
||||||
Lwt.return (List.rev acc)
|
|
||||||
else
|
|
||||||
loop (bi :: acc) (len-1) pred
|
|
||||||
in
|
|
||||||
loop [] len head
|
|
||||||
with Not_found -> Lwt.return_nil
|
|
||||||
|
|
||||||
let list node len heads =
|
|
||||||
Lwt_list.fold_left_s
|
|
||||||
(fun (ignored, acc) head ->
|
|
||||||
State.read_block_exn node.state head >>= fun block ->
|
|
||||||
predecessors_bi ignored len block >>= fun predecessors ->
|
|
||||||
let ignored =
|
|
||||||
List.fold_right
|
|
||||||
(fun x s -> Block_hash.Set.add x.hash s)
|
|
||||||
predecessors ignored in
|
|
||||||
Lwt.return (ignored, predecessors :: acc)
|
|
||||||
)
|
|
||||||
(Block_hash.Set.empty, [])
|
|
||||||
heads >>= fun (_, blocks) ->
|
|
||||||
Lwt.return (List.rev blocks)
|
|
||||||
|
|
||||||
let list_invalid node =
|
|
||||||
State.Block.list_invalid (Chain_validator.chain_state node.mainchain_validator)
|
|
||||||
|
|
||||||
let unmark_invalid node block =
|
|
||||||
State.Block.unmark_invalid (Chain_validator.chain_state node.mainchain_validator) block
|
|
||||||
|
|
||||||
let block_header_watcher node =
|
|
||||||
Distributed_db.watch_block_header node.distributed_db
|
|
||||||
|
|
||||||
let block_watcher node =
|
|
||||||
let stream, shutdown = Validator.watcher node.validator in
|
|
||||||
Lwt_stream.map_s (fun block -> convert block) stream,
|
|
||||||
shutdown
|
|
||||||
|
|
||||||
let operation_watcher node =
|
|
||||||
Distributed_db.watch_operation node.distributed_db
|
|
||||||
|
|
||||||
let protocol_watcher node =
|
|
||||||
Distributed_db.Protocol.watch node.distributed_db
|
|
||||||
|
|
||||||
let bootstrapped node =
|
|
||||||
let block_stream, stopper =
|
|
||||||
Chain_validator.new_head_watcher node.mainchain_validator in
|
|
||||||
let first_run = ref true in
|
|
||||||
let next () =
|
|
||||||
if !first_run then begin
|
|
||||||
first_run := false ;
|
|
||||||
let chain_state = Chain_validator.chain_state node.mainchain_validator in
|
|
||||||
Chain.head chain_state >>= fun head ->
|
|
||||||
let head_hash = State.Block.hash head in
|
|
||||||
let head_header = State.Block.header head in
|
|
||||||
Lwt.return (Some (head_hash, head_header.shell.timestamp))
|
|
||||||
end else begin
|
|
||||||
Lwt.pick [
|
|
||||||
( Lwt_stream.get block_stream >|=
|
|
||||||
Option.map ~f:(fun b ->
|
|
||||||
(State.Block.hash b, (State.Block.header b).shell.timestamp)) ) ;
|
|
||||||
(Chain_validator.bootstrapped node.mainchain_validator >|= fun () -> None) ;
|
|
||||||
]
|
|
||||||
end in
|
|
||||||
let shutdown () = Lwt_watcher.shutdown stopper in
|
|
||||||
RPC_answer.{ next ; shutdown }
|
|
||||||
|
|
||||||
let build_p2p_rpc_directory (t : t) =
|
|
||||||
P2p.build_rpc_directory t.p2p
|
|
||||||
|
|
||||||
end
|
|
||||||
|
@ -47,94 +47,6 @@ val create:
|
|||||||
chain_validator_limits ->
|
chain_validator_limits ->
|
||||||
t tzresult Lwt.t
|
t tzresult Lwt.t
|
||||||
|
|
||||||
module RPC : sig
|
|
||||||
|
|
||||||
type block = Block_services.block
|
|
||||||
type block_info = Block_services.block_info
|
|
||||||
|
|
||||||
val inject_block:
|
|
||||||
t -> ?force:bool -> ?chain_id:Chain_id.t ->
|
|
||||||
MBytes.t -> Operation.t list list ->
|
|
||||||
(Block_hash.t * unit tzresult Lwt.t) tzresult Lwt.t
|
|
||||||
(** [inject_block node ?force bytes] tries to insert [bytes]
|
|
||||||
(supposedly the serialization of a block header) inside
|
|
||||||
[node]. If [?force] is true, the block will be inserted even on
|
|
||||||
non strictly increasing fitness. *)
|
|
||||||
|
|
||||||
val inject_operation:
|
|
||||||
t -> ?chain_id:Chain_id.t -> MBytes.t ->
|
|
||||||
(Operation_hash.t * unit tzresult Lwt.t) Lwt.t
|
|
||||||
val inject_protocol:
|
|
||||||
t -> ?force:bool -> Protocol.t ->
|
|
||||||
(Protocol_hash.t * unit tzresult Lwt.t) Lwt.t
|
|
||||||
|
|
||||||
val raw_block_info:
|
|
||||||
t -> Block_hash.t -> block_info Lwt.t
|
|
||||||
val block_header_watcher:
|
|
||||||
t -> (Block_hash.t * Block_header.t) Lwt_stream.t * Lwt_watcher.stopper
|
|
||||||
val block_watcher:
|
|
||||||
t -> (block_info Lwt_stream.t * Lwt_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
|
|
||||||
|
|
||||||
val list_invalid:
|
|
||||||
t -> (Block_hash.t * int32 * error list) list Lwt.t
|
|
||||||
|
|
||||||
val unmark_invalid:
|
|
||||||
t -> Block_hash.t -> unit tzresult Lwt.t
|
|
||||||
|
|
||||||
val block_info:
|
|
||||||
t -> block -> block_info Lwt.t
|
|
||||||
|
|
||||||
val operation_hashes:
|
|
||||||
t -> block -> Operation_hash.t list list Lwt.t
|
|
||||||
val operations:
|
|
||||||
t -> block -> Operation.t list list Lwt.t
|
|
||||||
val operation_watcher:
|
|
||||||
t -> (Operation_hash.t * Operation.t) Lwt_stream.t * Lwt_watcher.stopper
|
|
||||||
|
|
||||||
val pending_operations:
|
|
||||||
t ->
|
|
||||||
(error Preapply_result.t * Operation.t Operation_hash.Map.t) Lwt.t
|
|
||||||
|
|
||||||
val protocols:
|
|
||||||
t -> Protocol_hash.t list Lwt.t
|
|
||||||
val protocol_content:
|
|
||||||
t -> Protocol_hash.t -> Protocol.t tzresult Lwt.t
|
|
||||||
val protocol_watcher:
|
|
||||||
t -> (Protocol_hash.t * Protocol.t) Lwt_stream.t * Lwt_watcher.stopper
|
|
||||||
|
|
||||||
val context_dir:
|
|
||||||
t -> block -> 'a RPC_directory.t option Lwt.t
|
|
||||||
|
|
||||||
(** Returns the content of the context at the given [path] descending
|
|
||||||
recursively into directories as far as [depth] allows.
|
|
||||||
Returns [None] if a path in not in the context or if [depth] is
|
|
||||||
negative. *)
|
|
||||||
val context_raw_get:
|
|
||||||
t -> block -> path:string list -> depth:int ->
|
|
||||||
Block_services.raw_context_result option Lwt.t
|
|
||||||
|
|
||||||
val preapply:
|
|
||||||
t -> block ->
|
|
||||||
timestamp:Time.t -> protocol_data:MBytes.t ->
|
|
||||||
sort_operations:bool -> Operation.t list list ->
|
|
||||||
(Block_header.shell_header * error Preapply_result.t list) tzresult Lwt.t
|
|
||||||
|
|
||||||
val complete:
|
|
||||||
t -> ?block:block -> string -> string list Lwt.t
|
|
||||||
|
|
||||||
val bootstrapped:
|
|
||||||
t -> (Block_hash.t * Time.t) RPC_answer.stream
|
|
||||||
|
|
||||||
|
|
||||||
val build_p2p_rpc_directory: t -> unit RPC_directory.t
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
val shutdown: t -> unit Lwt.t
|
val shutdown: t -> unit Lwt.t
|
||||||
|
|
||||||
|
val build_rpc_directory: t -> unit RPC_directory.t
|
||||||
|
@ -1,503 +0,0 @@
|
|||||||
(**************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Copyright (c) 2014 - 2018. *)
|
|
||||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
|
||||||
(* *)
|
|
||||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
|
||||||
(* *)
|
|
||||||
(**************************************************************************)
|
|
||||||
|
|
||||||
open RPC_logging
|
|
||||||
|
|
||||||
let filter_bi operations (bi: Block_services.block_info) =
|
|
||||||
let bi = if operations then bi else { bi with operations = None } in
|
|
||||||
bi
|
|
||||||
|
|
||||||
let register_bi_dir node dir =
|
|
||||||
let dir =
|
|
||||||
let implementation b () include_ops =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return (filter_bi include_ops bi) in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.info implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () () =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return bi.hash in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.hash
|
|
||||||
implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () () =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return bi.chain_id in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.chain_id implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () () =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return bi.level in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.level implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () () =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return bi.predecessor in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.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 ->
|
|
||||||
return hashes in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.predecessors implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () () =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return bi.fitness in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.fitness implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () () =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return bi.timestamp in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.timestamp implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () () =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return bi.protocol in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.protocol implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () () =
|
|
||||||
Node.RPC.block_info node b >>= fun bi ->
|
|
||||||
return bi.test_chain in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.test_chain implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation b () { Block_services.S.contents } =
|
|
||||||
Node.RPC.operation_hashes node b >>= fun hashes ->
|
|
||||||
if contents then
|
|
||||||
Node.RPC.operations node b >>= fun ops ->
|
|
||||||
RPC_answer.return @@
|
|
||||||
List.map2 (List.map2 (fun h op -> h, Some op)) hashes ops
|
|
||||||
else
|
|
||||||
RPC_answer.return @@
|
|
||||||
List.map (List.map (fun h -> h, None)) hashes
|
|
||||||
in
|
|
||||||
RPC_directory.gen_register1 dir
|
|
||||||
Block_services.S.operations implementation in
|
|
||||||
|
|
||||||
let dir =
|
|
||||||
let implementation
|
|
||||||
b ()
|
|
||||||
{ Block_services.S.operations ; sort_operations ;
|
|
||||||
timestamp ; protocol_data } =
|
|
||||||
Node.RPC.preapply node b
|
|
||||||
~timestamp ~protocol_data ~sort_operations operations
|
|
||||||
>>=? fun (shell_header, operations) ->
|
|
||||||
return { Block_services.shell_header ; operations } in
|
|
||||||
RPC_directory.register1 dir
|
|
||||||
Block_services.S.preapply implementation in
|
|
||||||
dir
|
|
||||||
|
|
||||||
let rec insert_future_block (bi: Block_services.block_info) = function
|
|
||||||
| [] -> [bi]
|
|
||||||
| ({timestamp} as head: Block_services.block_info) :: tail as all ->
|
|
||||||
if Time.compare bi.timestamp timestamp < 0 then
|
|
||||||
bi :: all
|
|
||||||
else
|
|
||||||
head :: insert_future_block bi tail
|
|
||||||
|
|
||||||
let create_delayed_stream
|
|
||||||
~filtering ~include_ops requested_heads bi_stream delay =
|
|
||||||
let stream, push = Lwt_stream.create () in
|
|
||||||
let current_blocks =
|
|
||||||
ref (List.fold_left
|
|
||||||
(fun acc h -> Block_hash.Set.add h acc)
|
|
||||||
Block_hash.Set.empty requested_heads) in
|
|
||||||
let next_future_block, is_futur_block,
|
|
||||||
insert_future_block, pop_future_block =
|
|
||||||
let future_blocks = ref [] in (* FIXME *)
|
|
||||||
let future_blocks_set = ref Block_hash.Set.empty in
|
|
||||||
let next () =
|
|
||||||
match !future_blocks with
|
|
||||||
| [] -> None
|
|
||||||
| bi :: _ -> Some bi
|
|
||||||
and mem hash = Block_hash.Set.mem hash !future_blocks_set
|
|
||||||
and insert bi =
|
|
||||||
future_blocks := insert_future_block bi !future_blocks ;
|
|
||||||
future_blocks_set :=
|
|
||||||
Block_hash.Set.add bi.hash !future_blocks_set
|
|
||||||
and pop time =
|
|
||||||
match !future_blocks with
|
|
||||||
| {timestamp} as bi :: rest when Time.(timestamp <= time) ->
|
|
||||||
future_blocks := rest ;
|
|
||||||
future_blocks_set :=
|
|
||||||
Block_hash.Set.remove bi.hash !future_blocks_set ;
|
|
||||||
Some bi
|
|
||||||
| _ -> None in
|
|
||||||
next, mem, insert, pop in
|
|
||||||
let _block_watcher_worker =
|
|
||||||
let never_ending = fst (Lwt.wait ()) in
|
|
||||||
let rec worker_loop () =
|
|
||||||
lwt_debug "WWW worker_loop" >>= fun () ->
|
|
||||||
let time = Time.(add (now ()) (Int64.of_int ~-delay)) in
|
|
||||||
let migration_delay =
|
|
||||||
match next_future_block () with
|
|
||||||
| None -> never_ending
|
|
||||||
| Some bi ->
|
|
||||||
let delay = Time.diff bi.timestamp time in
|
|
||||||
if delay <= 0L then
|
|
||||||
Lwt.return_unit
|
|
||||||
else
|
|
||||||
Lwt_unix.sleep (Int64.to_float delay) in
|
|
||||||
Lwt.choose [(migration_delay >|= fun () -> `Migrate) ;
|
|
||||||
(Lwt_stream.get bi_stream >|= fun x -> `Block x) ]
|
|
||||||
>>= function
|
|
||||||
| `Block None ->
|
|
||||||
lwt_debug "WWW worker_loop None" >>= fun () ->
|
|
||||||
Lwt.return_unit
|
|
||||||
| `Block (Some (bi : Block_services.block_info)) ->
|
|
||||||
lwt_debug "WWW worker_loop Some" >>= fun () ->
|
|
||||||
begin
|
|
||||||
if not filtering
|
|
||||||
|| Block_hash.Set.mem bi.predecessor !current_blocks
|
|
||||||
|| is_futur_block bi.predecessor
|
|
||||||
then begin
|
|
||||||
let time = Time.(add (now ()) (Int64.of_int ~-delay)) in
|
|
||||||
if Time.(time < bi.timestamp) then begin
|
|
||||||
insert_future_block bi ;
|
|
||||||
Lwt.return_unit
|
|
||||||
end else begin
|
|
||||||
current_blocks :=
|
|
||||||
Block_hash.Set.remove bi.predecessor !current_blocks
|
|
||||||
|> Block_hash.Set.add bi.hash ;
|
|
||||||
push (Some [[filter_bi include_ops bi]]) ;
|
|
||||||
Lwt.return_unit
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
Lwt.return_unit
|
|
||||||
end
|
|
||||||
end >>= fun () ->
|
|
||||||
worker_loop ()
|
|
||||||
| `Migrate ->
|
|
||||||
lwt_debug "WWW worker_loop Migrate" >>= fun () ->
|
|
||||||
let time = Time.(add (now ()) (Int64.of_int ~-delay)) in
|
|
||||||
let rec migrate_future_blocks () =
|
|
||||||
match pop_future_block time with
|
|
||||||
| Some bi ->
|
|
||||||
push (Some [[filter_bi include_ops bi]]) ;
|
|
||||||
migrate_future_blocks ()
|
|
||||||
| None -> Lwt.return_unit in
|
|
||||||
migrate_future_blocks () >>= fun () ->
|
|
||||||
worker_loop ()
|
|
||||||
in
|
|
||||||
Lwt_utils.worker "block_watcher"
|
|
||||||
~run:worker_loop ~cancel:(fun () -> Lwt.return_unit) in
|
|
||||||
stream
|
|
||||||
|
|
||||||
let list_blocks
|
|
||||||
node ()
|
|
||||||
{ Block_services.S.include_ops ; length ; heads ; monitor ; delay ;
|
|
||||||
min_date; min_heads} =
|
|
||||||
let len = match length with None -> 1 | Some x -> x in
|
|
||||||
let monitor = match monitor with None -> false | Some x -> x in
|
|
||||||
let time =
|
|
||||||
match delay with
|
|
||||||
| None -> None
|
|
||||||
| Some delay -> Some (Time.(add (now ()) (Int64.of_int ~-delay))) in
|
|
||||||
begin
|
|
||||||
match heads with
|
|
||||||
| None ->
|
|
||||||
Node.RPC.heads node >>= fun heads ->
|
|
||||||
let heads = List.map snd (Block_hash.Map.bindings heads) in
|
|
||||||
let heads =
|
|
||||||
match min_date with
|
|
||||||
| None -> heads
|
|
||||||
| Some date ->
|
|
||||||
let min_heads =
|
|
||||||
match min_heads with
|
|
||||||
| None -> 0
|
|
||||||
| Some min_heads -> min_heads in
|
|
||||||
snd @@
|
|
||||||
List.fold_left (fun (min_heads, acc) (bi : Node.RPC.block_info) ->
|
|
||||||
min_heads - 1,
|
|
||||||
if Time.(>) bi.timestamp date || min_heads > 0 then bi :: acc
|
|
||||||
else acc)
|
|
||||||
(min_heads, []) heads in
|
|
||||||
begin
|
|
||||||
match time with
|
|
||||||
| None -> Lwt.return heads
|
|
||||||
| Some time ->
|
|
||||||
let rec current_predecessor (bi: Node.RPC.block_info) =
|
|
||||||
if Time.compare bi.timestamp time <= 0
|
|
||||||
|| bi.hash = bi.predecessor then
|
|
||||||
Lwt.return bi
|
|
||||||
else
|
|
||||||
Node.RPC.raw_block_info node bi.predecessor >>=
|
|
||||||
current_predecessor in
|
|
||||||
Lwt_list.map_p current_predecessor heads
|
|
||||||
end >|= fun heads_info ->
|
|
||||||
let sorted_infos =
|
|
||||||
List.sort
|
|
||||||
(fun
|
|
||||||
(bi1: Block_services.block_info)
|
|
||||||
(bi2: Block_services.block_info) ->
|
|
||||||
~- (Fitness.compare bi1.fitness bi2.fitness))
|
|
||||||
heads_info in
|
|
||||||
List.map
|
|
||||||
(fun ({ hash } : Block_services.block_info) -> hash)
|
|
||||||
sorted_infos
|
|
||||||
| Some heads ->
|
|
||||||
let known_block h =
|
|
||||||
try ignore (Node.RPC.raw_block_info node h) ; true
|
|
||||||
with Not_found -> false in
|
|
||||||
Lwt.return (List.filter known_block heads)
|
|
||||||
end >>= fun requested_heads ->
|
|
||||||
Node.RPC.list node len requested_heads >>= fun requested_blocks ->
|
|
||||||
if not monitor then
|
|
||||||
let infos =
|
|
||||||
List.map
|
|
||||||
(List.map (filter_bi include_ops))
|
|
||||||
requested_blocks in
|
|
||||||
RPC_answer.return infos
|
|
||||||
else begin
|
|
||||||
let (bi_stream, stopper) = Node.RPC.block_watcher node in
|
|
||||||
let stream =
|
|
||||||
match delay with
|
|
||||||
| None ->
|
|
||||||
Lwt_stream.map (fun bi -> [[filter_bi include_ops bi]]) bi_stream
|
|
||||||
| Some delay ->
|
|
||||||
let filtering = heads <> None in
|
|
||||||
create_delayed_stream
|
|
||||||
~filtering ~include_ops requested_heads bi_stream delay in
|
|
||||||
let shutdown () = Lwt_watcher.shutdown stopper in
|
|
||||||
let first_request = ref true in
|
|
||||||
let next () =
|
|
||||||
if not !first_request then begin
|
|
||||||
Lwt_stream.get stream
|
|
||||||
end else begin
|
|
||||||
first_request := false ;
|
|
||||||
let infos =
|
|
||||||
List.map (List.map (filter_bi include_ops)) requested_blocks in
|
|
||||||
Lwt.return (Some infos)
|
|
||||||
end in
|
|
||||||
RPC_answer.return_stream { next ; shutdown }
|
|
||||||
end
|
|
||||||
|
|
||||||
let list_invalid node () () =
|
|
||||||
Node.RPC.list_invalid node >>= return
|
|
||||||
|
|
||||||
let unmark_invalid node block () () =
|
|
||||||
Node.RPC.unmark_invalid node block
|
|
||||||
|
|
||||||
let list_protocols node () { Protocol_services.S.monitor ; contents } =
|
|
||||||
let monitor = match monitor with None -> false | Some x -> x in
|
|
||||||
let include_contents = match contents with None -> false | Some x -> x in
|
|
||||||
Node.RPC.protocols node >>= fun protocols ->
|
|
||||||
Lwt_list.map_p
|
|
||||||
(fun hash ->
|
|
||||||
if include_contents then
|
|
||||||
Node.RPC.protocol_content node hash >>= function
|
|
||||||
| Error _ -> Lwt.return (hash, None)
|
|
||||||
| Ok bytes -> Lwt.return (hash, Some bytes)
|
|
||||||
else
|
|
||||||
Lwt.return (hash, None))
|
|
||||||
protocols >>= fun protocols ->
|
|
||||||
if not monitor then
|
|
||||||
RPC_answer.return protocols
|
|
||||||
else
|
|
||||||
let stream, stopper = Node.RPC.protocol_watcher node in
|
|
||||||
let shutdown () = Lwt_watcher.shutdown stopper in
|
|
||||||
let first_request = ref true in
|
|
||||||
let next () =
|
|
||||||
if not !first_request then
|
|
||||||
Lwt_stream.get stream >>= function
|
|
||||||
| None -> Lwt.return_none
|
|
||||||
| Some (h, op) when include_contents -> Lwt.return (Some [h, Some op])
|
|
||||||
| Some (h, _) -> Lwt.return (Some [h, None])
|
|
||||||
else begin
|
|
||||||
first_request := false ;
|
|
||||||
Lwt.return (Some protocols)
|
|
||||||
end in
|
|
||||||
RPC_answer.return_stream { next ; shutdown }
|
|
||||||
|
|
||||||
let get_protocols node hash () () =
|
|
||||||
Node.RPC.protocol_content node hash
|
|
||||||
|
|
||||||
let build_rpc_directory node =
|
|
||||||
let dir = RPC_directory.empty in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.gen_register0 dir Block_services.S.list
|
|
||||||
(list_blocks node) in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register0 dir Block_services.S.list_invalid
|
|
||||||
(list_invalid node) in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register1 dir Block_services.S.unmark_invalid
|
|
||||||
(unmark_invalid node) in
|
|
||||||
let dir = register_bi_dir node dir in
|
|
||||||
let dir =
|
|
||||||
let implementation block =
|
|
||||||
Lwt.catch (fun () ->
|
|
||||||
Node.RPC.context_dir node block >>= function
|
|
||||||
| None -> Lwt.fail Not_found
|
|
||||||
| Some context_dir -> Lwt.return context_dir)
|
|
||||||
(fun _ -> Lwt.return RPC_directory.empty) in
|
|
||||||
RPC_directory.register_dynamic_directory1
|
|
||||||
~descr:
|
|
||||||
"All the RPCs which are specific to the protocol version."
|
|
||||||
dir (Block_services.S.proto_path ()) implementation in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.gen_register0 dir Protocol_services.S.list
|
|
||||||
(list_protocols node) in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register1 dir Protocol_services.S.contents
|
|
||||||
(get_protocols node) in
|
|
||||||
let dir =
|
|
||||||
let implementation () header =
|
|
||||||
let res =
|
|
||||||
Data_encoding.Binary.to_bytes_exn Block_header.encoding header in
|
|
||||||
RPC_answer.return res in
|
|
||||||
RPC_directory.gen_register0 dir Shell_services.S.forge_block_header
|
|
||||||
implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation ()
|
|
||||||
{ Shell_services.S.raw ; blocking ; force ; operations } =
|
|
||||||
begin
|
|
||||||
Node.RPC.inject_block
|
|
||||||
node ~force
|
|
||||||
raw operations >>=? fun (hash, wait) ->
|
|
||||||
(if blocking then wait else return ()) >>=? fun () -> return hash
|
|
||||||
end in
|
|
||||||
RPC_directory.register0 dir Shell_services.S.inject_block implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation () (contents, blocking, chain_id) =
|
|
||||||
Node.RPC.inject_operation
|
|
||||||
node ?chain_id contents >>= fun (hash, wait) ->
|
|
||||||
begin
|
|
||||||
(if blocking then wait else return ()) >>=? fun () -> return hash
|
|
||||||
end in
|
|
||||||
RPC_directory.register0 dir Shell_services.S.inject_operation implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation () (proto, blocking, force) =
|
|
||||||
Node.RPC.inject_protocol ?force node proto >>= fun (hash, wait) ->
|
|
||||||
begin
|
|
||||||
(if blocking then wait else return ()) >>=? fun () -> return hash
|
|
||||||
end in
|
|
||||||
RPC_directory.register0 dir Shell_services.S.inject_protocol implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation () () =
|
|
||||||
RPC_answer.return_stream (Node.RPC.bootstrapped node) in
|
|
||||||
RPC_directory.gen_register0 dir Shell_services.S.bootstrapped implementation in
|
|
||||||
let dir =
|
|
||||||
let implementation () () =
|
|
||||||
return Data_encoding.Json.(schema Error_monad.error_encoding) in
|
|
||||||
RPC_directory.register0 dir RPC_service.error_service implementation in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register1 dir Shell_services.S.complete
|
|
||||||
(fun s () () -> Node.RPC.complete node s >>= return) in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register2 dir Block_services.S.complete
|
|
||||||
(fun block s () () -> Node.RPC.complete node ~block s >>= return) in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register2 dir Block_services.S.raw_context
|
|
||||||
(fun block path q () ->
|
|
||||||
Node.RPC.context_raw_get node block ~path ~depth:q#depth >>= function
|
|
||||||
| None -> raise Not_found
|
|
||||||
| Some v -> return v)
|
|
||||||
in
|
|
||||||
|
|
||||||
(* Workers : Prevalidators *)
|
|
||||||
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register0 dir Worker_services.Prevalidators.S.list
|
|
||||||
(fun () () ->
|
|
||||||
return
|
|
||||||
(List.map
|
|
||||||
(fun (id, w) -> (id, Prevalidator.status w))
|
|
||||||
(Prevalidator.running_workers ()))) in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register1 dir Worker_services.Prevalidators.S.state
|
|
||||||
(fun chain_id () () ->
|
|
||||||
let w = List.assoc chain_id (Prevalidator.running_workers ()) in
|
|
||||||
return
|
|
||||||
{ Worker_types.status = Prevalidator.status w ;
|
|
||||||
pending_requests = Prevalidator.pending_requests w ;
|
|
||||||
backlog = Prevalidator.last_events w ;
|
|
||||||
current_request = Prevalidator.current_request w }) in
|
|
||||||
|
|
||||||
(* Workers : Block_validator *)
|
|
||||||
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register0 dir Worker_services.Block_validator.S.state
|
|
||||||
(fun () () ->
|
|
||||||
let w = Block_validator.running_worker () in
|
|
||||||
return
|
|
||||||
{ Worker_types.status = Block_validator.status w ;
|
|
||||||
pending_requests = Block_validator.pending_requests w ;
|
|
||||||
backlog = Block_validator.last_events w ;
|
|
||||||
current_request = Block_validator.current_request w }) in
|
|
||||||
|
|
||||||
(* Workers : Peer validators *)
|
|
||||||
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register1 dir Worker_services.Peer_validators.S.list
|
|
||||||
(fun chain_id () () ->
|
|
||||||
return
|
|
||||||
(List.filter_map
|
|
||||||
(fun ((id, peer_id), w) ->
|
|
||||||
if Chain_id.equal id chain_id then
|
|
||||||
Some (peer_id, Peer_validator.status w)
|
|
||||||
else None)
|
|
||||||
(Peer_validator.running_workers ()))) in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register2 dir Worker_services.Peer_validators.S.state
|
|
||||||
(fun chain_id peer_id () () ->
|
|
||||||
let w = List.assoc (chain_id, peer_id) (Peer_validator.running_workers ()) in
|
|
||||||
return
|
|
||||||
{ Worker_types.status = Peer_validator.status w ;
|
|
||||||
pending_requests = [] ;
|
|
||||||
backlog = Peer_validator.last_events w ;
|
|
||||||
current_request = Peer_validator.current_request w }) in
|
|
||||||
|
|
||||||
(* Workers : Net validators *)
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register0 dir Worker_services.Chain_validators.S.list
|
|
||||||
(fun () () ->
|
|
||||||
return
|
|
||||||
(List.map
|
|
||||||
(fun (id, w) -> (id, Chain_validator.status w))
|
|
||||||
(Chain_validator.running_workers ()))) in
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register1 dir Worker_services.Chain_validators.S.state
|
|
||||||
(fun chain_id () () ->
|
|
||||||
let w = List.assoc chain_id (Chain_validator.running_workers ()) in
|
|
||||||
return
|
|
||||||
{ Worker_types.status = Chain_validator.status w ;
|
|
||||||
pending_requests = Chain_validator.pending_requests w ;
|
|
||||||
backlog = Chain_validator.last_events w ;
|
|
||||||
current_request = Chain_validator.current_request w }) in
|
|
||||||
|
|
||||||
(* Network *)
|
|
||||||
let dir = RPC_directory.merge dir (Node.RPC.build_p2p_rpc_directory node) in
|
|
||||||
|
|
||||||
(* Mempool *)
|
|
||||||
let dir =
|
|
||||||
let implementation () () () =
|
|
||||||
Node.RPC.pending_operations node >>= fun res ->
|
|
||||||
return res in
|
|
||||||
RPC_directory.register dir
|
|
||||||
Mempool_services.S.pending_operations
|
|
||||||
implementation in
|
|
||||||
|
|
||||||
let dir =
|
|
||||||
RPC_directory.register_describe_directory_service
|
|
||||||
dir RPC_service.description_service in
|
|
||||||
|
|
||||||
|
|
||||||
dir
|
|
||||||
|
|
@ -54,7 +54,7 @@ type prevalidation_state =
|
|||||||
-> prevalidation_state
|
-> prevalidation_state
|
||||||
|
|
||||||
and 'a proto =
|
and 'a proto =
|
||||||
(module Registered_protocol.T with type validation_state = 'a)
|
(module Registered_protocol.T with type P.validation_state = 'a)
|
||||||
|
|
||||||
let start_prevalidation
|
let start_prevalidation
|
||||||
?protocol_data
|
?protocol_data
|
||||||
@ -166,3 +166,54 @@ let prevalidate
|
|||||||
let end_prevalidation (State { proto = (module Proto) ; state }) =
|
let end_prevalidation (State { proto = (module Proto) ; state }) =
|
||||||
Proto.finalize_block state >>=? fun (result, _metadata) ->
|
Proto.finalize_block state >>=? fun (result, _metadata) ->
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
let preapply ~predecessor ~timestamp ~protocol_data ~sort_operations:sort ops =
|
||||||
|
start_prevalidation
|
||||||
|
~protocol_data ~predecessor ~timestamp () >>=? fun validation_state ->
|
||||||
|
let ops = List.map (List.map (fun x -> Operation.hash x, x)) ops in
|
||||||
|
Lwt_list.fold_left_s
|
||||||
|
(fun (validation_state, rs) ops ->
|
||||||
|
prevalidate
|
||||||
|
validation_state ~sort ops >>= fun (validation_state, r) ->
|
||||||
|
Lwt.return (validation_state, rs @ [r]))
|
||||||
|
(validation_state, []) ops >>= fun (validation_state, rs) ->
|
||||||
|
let operations_hash =
|
||||||
|
Operation_list_list_hash.compute
|
||||||
|
(List.map
|
||||||
|
(fun r ->
|
||||||
|
Operation_list_hash.compute
|
||||||
|
(List.map fst r.Preapply_result.applied))
|
||||||
|
rs) in
|
||||||
|
end_prevalidation validation_state >>=? fun { fitness ; context ; message } ->
|
||||||
|
let pred_shell_header = State.Block.shell_header predecessor in
|
||||||
|
State.Block.protocol_hash predecessor >>= fun pred_protocol ->
|
||||||
|
Context.get_protocol context >>= fun protocol ->
|
||||||
|
let proto_level =
|
||||||
|
if Protocol_hash.equal protocol pred_protocol then
|
||||||
|
pred_shell_header.proto_level
|
||||||
|
else
|
||||||
|
((pred_shell_header.proto_level + 1) mod 256) in
|
||||||
|
let shell_header : Block_header.shell_header = {
|
||||||
|
level = Int32.succ pred_shell_header.level ;
|
||||||
|
proto_level ;
|
||||||
|
predecessor = State.Block.hash predecessor ;
|
||||||
|
timestamp ;
|
||||||
|
validation_passes = List.length rs ;
|
||||||
|
operations_hash ;
|
||||||
|
fitness ;
|
||||||
|
context = Context_hash.zero ; (* place holder *)
|
||||||
|
} in
|
||||||
|
begin
|
||||||
|
if Protocol_hash.equal protocol pred_protocol then
|
||||||
|
return (context, message)
|
||||||
|
else
|
||||||
|
match Registered_protocol.get protocol with
|
||||||
|
| None ->
|
||||||
|
fail (Block_validator_errors.Unavailable_protocol
|
||||||
|
{ block = State.Block.hash predecessor ; protocol })
|
||||||
|
| Some (module NewProto) ->
|
||||||
|
NewProto.init context shell_header >>=? fun { context ; message ; _ } ->
|
||||||
|
return (context, message)
|
||||||
|
end >>=? fun (context, message) ->
|
||||||
|
Context.commit ?message ~time:timestamp context >>= fun context ->
|
||||||
|
return ({ shell_header with context }, rs)
|
||||||
|
@ -23,3 +23,12 @@ val prevalidate :
|
|||||||
val end_prevalidation :
|
val end_prevalidation :
|
||||||
prevalidation_state ->
|
prevalidation_state ->
|
||||||
Tezos_protocol_environment_shell.validation_result tzresult Lwt.t
|
Tezos_protocol_environment_shell.validation_result tzresult Lwt.t
|
||||||
|
|
||||||
|
val preapply :
|
||||||
|
predecessor:State.Block.t ->
|
||||||
|
timestamp:Time.t ->
|
||||||
|
protocol_data:MBytes.t ->
|
||||||
|
sort_operations:bool ->
|
||||||
|
Operation.t list list ->
|
||||||
|
(Block_header.shell_header * error Preapply_result.t list) tzresult Lwt.t
|
||||||
|
|
||||||
|
57
src/lib_shell/protocol_directory.ml
Normal file
57
src/lib_shell/protocol_directory.ml
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
let build_rpc_directory state distributed_db =
|
||||||
|
|
||||||
|
let dir : unit RPC_directory.t ref = ref RPC_directory.empty in
|
||||||
|
let gen_register0 s f =
|
||||||
|
dir := RPC_directory.gen_register !dir s (fun () p q -> f p q) in
|
||||||
|
let register1 s f =
|
||||||
|
dir := RPC_directory.register !dir s (fun ((), a) p q -> f a p q) in
|
||||||
|
|
||||||
|
gen_register0 Protocol_services.S.list begin fun () p ->
|
||||||
|
let { Protocol_services.S.monitor ; contents } = p in
|
||||||
|
let monitor = match monitor with None -> false | Some x -> x in
|
||||||
|
let include_contents = match contents with None -> false | Some x -> x in
|
||||||
|
State.Protocol.list state >>= fun set ->
|
||||||
|
let protocols = Protocol_hash.Set.elements set in
|
||||||
|
Lwt_list.map_p
|
||||||
|
(fun hash ->
|
||||||
|
if include_contents then
|
||||||
|
State.Protocol.read state hash >>= function
|
||||||
|
| Error _ -> Lwt.return (hash, None)
|
||||||
|
| Ok bytes -> Lwt.return (hash, Some bytes)
|
||||||
|
else
|
||||||
|
Lwt.return (hash, None))
|
||||||
|
protocols >>= fun protocols ->
|
||||||
|
if not monitor then
|
||||||
|
RPC_answer.return protocols
|
||||||
|
else
|
||||||
|
let stream, stopper =
|
||||||
|
Distributed_db.Protocol.watch distributed_db in
|
||||||
|
let shutdown () = Lwt_watcher.shutdown stopper in
|
||||||
|
let first_request = ref true in
|
||||||
|
let next () =
|
||||||
|
if not !first_request then
|
||||||
|
Lwt_stream.get stream >>= function
|
||||||
|
| None -> Lwt.return_none
|
||||||
|
| Some (h, op) when include_contents -> Lwt.return (Some [h, Some op])
|
||||||
|
| Some (h, _) -> Lwt.return (Some [h, None])
|
||||||
|
else begin
|
||||||
|
first_request := false ;
|
||||||
|
Lwt.return (Some protocols)
|
||||||
|
end in
|
||||||
|
RPC_answer.return_stream { next ; shutdown }
|
||||||
|
end;
|
||||||
|
|
||||||
|
register1 Protocol_services.S.contents begin fun hash () () ->
|
||||||
|
State.Protocol.read state hash
|
||||||
|
end ;
|
||||||
|
|
||||||
|
!dir
|
11
src/lib_shell/protocol_directory.mli
Normal file
11
src/lib_shell/protocol_directory.mli
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
val build_rpc_directory:
|
||||||
|
State.t -> Distributed_db.t -> unit RPC_directory.t
|
179
src/lib_shell/shell_directory.ml
Normal file
179
src/lib_shell/shell_directory.ml
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
let inject_block validator ?force ?chain_id bytes operations =
|
||||||
|
Validator.validate_block
|
||||||
|
validator ?force ?chain_id bytes operations >>=? fun (hash, block) ->
|
||||||
|
return (hash, (block >>=? fun _ -> return ()))
|
||||||
|
|
||||||
|
let inject_operation validator ?chain_id bytes =
|
||||||
|
let t =
|
||||||
|
match Data_encoding.Binary.of_bytes Operation.encoding bytes with
|
||||||
|
| None -> failwith "Can't parse the operation"
|
||||||
|
| Some op ->
|
||||||
|
Validator.inject_operation validator ?chain_id op
|
||||||
|
in
|
||||||
|
let hash = Operation_hash.hash_bytes [bytes] in
|
||||||
|
Lwt.return (hash, t)
|
||||||
|
|
||||||
|
let inject_protocol state ?force:_ proto =
|
||||||
|
let proto_bytes =
|
||||||
|
Data_encoding.Binary.to_bytes_exn Protocol.encoding proto in
|
||||||
|
let hash = Protocol_hash.hash_bytes [proto_bytes] in
|
||||||
|
let validation =
|
||||||
|
Updater.compile hash proto >>= function
|
||||||
|
| false ->
|
||||||
|
failwith
|
||||||
|
"Compilation failed (%a)"
|
||||||
|
Protocol_hash.pp_short hash
|
||||||
|
| true ->
|
||||||
|
State.Protocol.store state proto >>= function
|
||||||
|
| None ->
|
||||||
|
failwith
|
||||||
|
"Previously registered protocol (%a)"
|
||||||
|
Protocol_hash.pp_short hash
|
||||||
|
| Some _ -> return ()
|
||||||
|
in
|
||||||
|
Lwt.return (hash, validation)
|
||||||
|
|
||||||
|
let build_rpc_directory state validator mainchain_validator =
|
||||||
|
|
||||||
|
let dir : unit RPC_directory.t ref = ref RPC_directory.empty in
|
||||||
|
let gen_register0 s f =
|
||||||
|
dir := RPC_directory.gen_register !dir s (fun () p q -> f p q) in
|
||||||
|
let register0 s f =
|
||||||
|
dir := RPC_directory.register !dir s (fun () p q -> f p q) in
|
||||||
|
let gen_register1 s f =
|
||||||
|
dir := RPC_directory.gen_register !dir s (fun ((), a) p q -> f a p q) in
|
||||||
|
|
||||||
|
register0 Shell_services.S.forge_block_header begin fun () header ->
|
||||||
|
return (Data_encoding.Binary.to_bytes_exn Block_header.encoding header)
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register0 Shell_services.S.inject_block begin fun () p ->
|
||||||
|
let { Shell_services.S.raw ; blocking ; force ; operations } = p in
|
||||||
|
inject_block validator ~force raw operations >>=? fun (hash, wait) ->
|
||||||
|
(if blocking then wait else return ()) >>=? fun () ->
|
||||||
|
return hash
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register0 Shell_services.S.inject_operation begin fun () p ->
|
||||||
|
let (contents, blocking, chain_id) = p in
|
||||||
|
inject_operation validator ?chain_id contents >>= fun (hash, wait) ->
|
||||||
|
(if blocking then wait else return ()) >>=? fun () ->
|
||||||
|
return hash
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register0 Shell_services.S.inject_protocol begin fun () p ->
|
||||||
|
let (proto, blocking, force) = p in
|
||||||
|
inject_protocol state ?force proto >>= fun (hash, wait) ->
|
||||||
|
(if blocking then wait else return ()) >>=? fun () ->
|
||||||
|
return hash
|
||||||
|
end ;
|
||||||
|
|
||||||
|
gen_register0 Shell_services.S.bootstrapped begin fun () () ->
|
||||||
|
let block_stream, stopper =
|
||||||
|
Chain_validator.new_head_watcher mainchain_validator in
|
||||||
|
let first_run = ref true in
|
||||||
|
let next () =
|
||||||
|
if !first_run then begin
|
||||||
|
first_run := false ;
|
||||||
|
let chain_state = Chain_validator.chain_state mainchain_validator in
|
||||||
|
Chain.head chain_state >>= fun head ->
|
||||||
|
let head_hash = State.Block.hash head in
|
||||||
|
let head_header = State.Block.header head in
|
||||||
|
Lwt.return (Some (head_hash, head_header.shell.timestamp))
|
||||||
|
end else begin
|
||||||
|
Lwt.pick [
|
||||||
|
( Lwt_stream.get block_stream >|=
|
||||||
|
Option.map ~f:(fun b ->
|
||||||
|
(State.Block.hash b, (State.Block.header b).shell.timestamp)) ) ;
|
||||||
|
(Chain_validator.bootstrapped mainchain_validator >|= fun () -> None) ;
|
||||||
|
]
|
||||||
|
end in
|
||||||
|
let shutdown () = Lwt_watcher.shutdown stopper in
|
||||||
|
RPC_answer.return_stream { next ; shutdown }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
gen_register0 Shell_services.S.Monitor.valid_blocks begin fun q () ->
|
||||||
|
let block_stream, stopper = State.watcher state in
|
||||||
|
let shutdown () = Lwt_watcher.shutdown stopper in
|
||||||
|
let in_chains block =
|
||||||
|
Lwt_list.map_p (Chain_directory.get_chain_id state) q#chains >>= function
|
||||||
|
| [] -> Lwt.return_true
|
||||||
|
| chains ->
|
||||||
|
let chain_id = State.Block.chain_id block in
|
||||||
|
Lwt.return (List.exists (Chain_id.equal chain_id) chains) in
|
||||||
|
let in_protocols block =
|
||||||
|
match q#protocols with
|
||||||
|
| [] -> Lwt.return_true
|
||||||
|
| protocols ->
|
||||||
|
State.Block.predecessor block >>= function
|
||||||
|
| None -> Lwt.return_false (* won't happen *)
|
||||||
|
| Some pred ->
|
||||||
|
State.Block.context pred >>= fun context ->
|
||||||
|
Context.get_protocol context >>= fun protocol ->
|
||||||
|
Lwt.return (List.exists (Protocol_hash.equal protocol) protocols) in
|
||||||
|
let in_next_protocols block =
|
||||||
|
match q#next_protocols with
|
||||||
|
| [] -> Lwt.return_true
|
||||||
|
| protocols ->
|
||||||
|
State.Block.context block >>= fun context ->
|
||||||
|
Context.get_protocol context >>= fun next_protocol ->
|
||||||
|
Lwt.return (List.exists (Protocol_hash.equal next_protocol) protocols) in
|
||||||
|
let stream =
|
||||||
|
Lwt_stream.filter_map_s
|
||||||
|
(fun block ->
|
||||||
|
in_chains block >>= fun in_chains ->
|
||||||
|
in_next_protocols block >>= fun in_next_protocols ->
|
||||||
|
in_protocols block >>= fun in_protocols ->
|
||||||
|
if in_chains && in_protocols && in_next_protocols then
|
||||||
|
Lwt.return_some
|
||||||
|
(State.Block.chain_id block, State.Block.hash block)
|
||||||
|
else
|
||||||
|
Lwt.return_none)
|
||||||
|
block_stream in
|
||||||
|
let next () = Lwt_stream.get stream in
|
||||||
|
RPC_answer.return_stream { next ; shutdown }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
gen_register1 Shell_services.S.Monitor.heads begin fun chain q () ->
|
||||||
|
(* TODO: when `chain = `Test`, should we reset then stream when
|
||||||
|
the `testnet` change, or dias we currently do ?? *)
|
||||||
|
Chain_directory.get_chain state chain >>= fun chain ->
|
||||||
|
Validator.get_exn validator (State.Chain.id chain) >>= fun chain_validator ->
|
||||||
|
let block_stream, stopper = Chain_validator.new_head_watcher chain_validator in
|
||||||
|
Chain.head chain >>= fun head ->
|
||||||
|
let shutdown () = Lwt_watcher.shutdown stopper in
|
||||||
|
let in_next_protocols block =
|
||||||
|
match q#next_protocols with
|
||||||
|
| [] -> Lwt.return_true
|
||||||
|
| protocols ->
|
||||||
|
State.Block.context block >>= fun context ->
|
||||||
|
Context.get_protocol context >>= fun next_protocol ->
|
||||||
|
Lwt.return (List.exists (Protocol_hash.equal next_protocol) protocols) in
|
||||||
|
let stream =
|
||||||
|
Lwt_stream.filter_map_s
|
||||||
|
(fun block ->
|
||||||
|
in_next_protocols block >>= fun in_next_protocols ->
|
||||||
|
if in_next_protocols then
|
||||||
|
Lwt.return_some (State.Block.hash block)
|
||||||
|
else
|
||||||
|
Lwt.return_none)
|
||||||
|
block_stream in
|
||||||
|
let first_call = ref true in
|
||||||
|
let next () =
|
||||||
|
if !first_call then begin
|
||||||
|
first_call := false ; Lwt.return_some (State.Block.hash head)
|
||||||
|
end else
|
||||||
|
Lwt_stream.get stream in
|
||||||
|
RPC_answer.return_stream { next ; shutdown }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
!dir
|
11
src/lib_shell/shell_directory.mli
Normal file
11
src/lib_shell/shell_directory.mli
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
val build_rpc_directory:
|
||||||
|
State.t -> Validator.t -> Chain_validator.t -> unit RPC_directory.t
|
@ -44,6 +44,8 @@ and chain_state = {
|
|||||||
context_index: Context.index Shared.t ;
|
context_index: Context.index Shared.t ;
|
||||||
block_watcher: block Lwt_watcher.input ;
|
block_watcher: block Lwt_watcher.input ;
|
||||||
chain_data: chain_data_state Shared.t ;
|
chain_data: chain_data_state Shared.t ;
|
||||||
|
block_rpc_directories:
|
||||||
|
block RPC_directory.t Protocol_hash.Map.t Protocol_hash.Table.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
and genesis = {
|
and genesis = {
|
||||||
@ -282,6 +284,7 @@ module Chain = struct
|
|||||||
block_store = Shared.create block_store ;
|
block_store = Shared.create block_store ;
|
||||||
context_index = Shared.create context_index ;
|
context_index = Shared.create context_index ;
|
||||||
block_watcher = Lwt_watcher.create_input () ;
|
block_watcher = Lwt_watcher.create_input () ;
|
||||||
|
block_rpc_directories = Protocol_hash.Table.create 7 ;
|
||||||
} in
|
} in
|
||||||
Lwt.return chain_state
|
Lwt.return chain_state
|
||||||
|
|
||||||
@ -722,6 +725,33 @@ module Block = struct
|
|||||||
read_exn chain_state tail >>= fun block ->
|
read_exn chain_state tail >>= fun block ->
|
||||||
Lwt.return_some (block, locator)
|
Lwt.return_some (block, locator)
|
||||||
|
|
||||||
|
let get_rpc_directory ({ chain_state ; _ } as block) =
|
||||||
|
read_opt chain_state block.contents.header.shell.predecessor >>= function
|
||||||
|
| None -> Lwt.return_none (* genesis *)
|
||||||
|
| Some pred ->
|
||||||
|
protocol_hash pred >>= fun protocol ->
|
||||||
|
match
|
||||||
|
Protocol_hash.Table.find_opt
|
||||||
|
chain_state.block_rpc_directories protocol
|
||||||
|
with
|
||||||
|
| None -> Lwt.return_none
|
||||||
|
| Some map ->
|
||||||
|
protocol_hash block >>= fun next_protocol ->
|
||||||
|
Lwt.return (Protocol_hash.Map.find_opt next_protocol map)
|
||||||
|
|
||||||
|
let set_rpc_directory ({ chain_state ; _ } as block) dir =
|
||||||
|
read_exn chain_state block.contents.header.shell.predecessor >>= fun pred ->
|
||||||
|
protocol_hash block >>= fun next_protocol ->
|
||||||
|
protocol_hash pred >>= fun protocol ->
|
||||||
|
let map =
|
||||||
|
Option.unopt ~default:Protocol_hash.Map.empty
|
||||||
|
(Protocol_hash.Table.find_opt chain_state.block_rpc_directories protocol)
|
||||||
|
in
|
||||||
|
Protocol_hash.Table.replace
|
||||||
|
chain_state.block_rpc_directories protocol
|
||||||
|
(Protocol_hash.Map.add next_protocol dir map) ;
|
||||||
|
Lwt.return_unit
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let watcher (state : global_state) =
|
let watcher (state : global_state) =
|
||||||
|
@ -153,6 +153,9 @@ module Block : sig
|
|||||||
function returns [None] when no block in the locator are known or
|
function returns [None] when no block in the locator are known or
|
||||||
if the first known block is invalid. *)
|
if the first known block is invalid. *)
|
||||||
|
|
||||||
|
val get_rpc_directory: block -> block RPC_directory.t option Lwt.t
|
||||||
|
val set_rpc_directory: block -> block RPC_directory.t -> unit Lwt.t
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
val read_block:
|
val read_block:
|
||||||
|
88
src/lib_shell/worker_directory.ml
Normal file
88
src/lib_shell/worker_directory.ml
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
let rpc_directory =
|
||||||
|
|
||||||
|
let dir : unit RPC_directory.t ref = ref RPC_directory.empty in
|
||||||
|
let register0 s f =
|
||||||
|
dir := RPC_directory.register !dir s (fun () p q -> f p q) in
|
||||||
|
let register1 s f =
|
||||||
|
dir := RPC_directory.register !dir s (fun ((), a) p q -> f a p q) in
|
||||||
|
let register2 s f =
|
||||||
|
dir := RPC_directory.register !dir s (fun (((), a), b) p q -> f a b p q) in
|
||||||
|
|
||||||
|
(* Workers : Prevalidators *)
|
||||||
|
|
||||||
|
register0 Worker_services.Prevalidators.S.list begin fun () () ->
|
||||||
|
return
|
||||||
|
(List.map
|
||||||
|
(fun (id, w) -> (id, Prevalidator.status w))
|
||||||
|
(Prevalidator.running_workers ()))
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register1 Worker_services.Prevalidators.S.state begin fun chain_id () () ->
|
||||||
|
let w = List.assoc chain_id (Prevalidator.running_workers ()) in
|
||||||
|
return
|
||||||
|
{ Worker_types.status = Prevalidator.status w ;
|
||||||
|
pending_requests = Prevalidator.pending_requests w ;
|
||||||
|
backlog = Prevalidator.last_events w ;
|
||||||
|
current_request = Prevalidator.current_request w }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* Workers : Block_validator *)
|
||||||
|
|
||||||
|
register0 Worker_services.Block_validator.S.state begin fun () () ->
|
||||||
|
let w = Block_validator.running_worker () in
|
||||||
|
return
|
||||||
|
{ Worker_types.status = Block_validator.status w ;
|
||||||
|
pending_requests = Block_validator.pending_requests w ;
|
||||||
|
backlog = Block_validator.last_events w ;
|
||||||
|
current_request = Block_validator.current_request w }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* Workers : Peer validators *)
|
||||||
|
|
||||||
|
register1 Worker_services.Peer_validators.S.list begin fun chain_id () () ->
|
||||||
|
return
|
||||||
|
(List.filter_map
|
||||||
|
(fun ((id, peer_id), w) ->
|
||||||
|
if Chain_id.equal id chain_id then
|
||||||
|
Some (peer_id, Peer_validator.status w)
|
||||||
|
else None)
|
||||||
|
(Peer_validator.running_workers ()))
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register2 Worker_services.Peer_validators.S.state begin fun chain_id peer_id () () ->
|
||||||
|
let w = List.assoc (chain_id, peer_id) (Peer_validator.running_workers ()) in
|
||||||
|
return
|
||||||
|
{ Worker_types.status = Peer_validator.status w ;
|
||||||
|
pending_requests = [] ;
|
||||||
|
backlog = Peer_validator.last_events w ;
|
||||||
|
current_request = Peer_validator.current_request w }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
(* Workers : Net validators *)
|
||||||
|
|
||||||
|
register0 Worker_services.Chain_validators.S.list begin fun () () ->
|
||||||
|
return
|
||||||
|
(List.map
|
||||||
|
(fun (id, w) -> (id, Chain_validator.status w))
|
||||||
|
(Chain_validator.running_workers ()))
|
||||||
|
end ;
|
||||||
|
|
||||||
|
register1 Worker_services.Chain_validators.S.state begin fun chain_id () () ->
|
||||||
|
let w = List.assoc chain_id (Chain_validator.running_workers ()) in
|
||||||
|
return
|
||||||
|
{ Worker_types.status = Chain_validator.status w ;
|
||||||
|
pending_requests = Chain_validator.pending_requests w ;
|
||||||
|
backlog = Chain_validator.last_events w ;
|
||||||
|
current_request = Chain_validator.current_request w }
|
||||||
|
end ;
|
||||||
|
|
||||||
|
!dir
|
@ -7,4 +7,4 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
val build_rpc_directory: Node.t -> unit RPC_directory.t
|
val rpc_directory: unit RPC_directory.t
|
File diff suppressed because it is too large
Load Diff
@ -7,223 +7,433 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
|
open Chain_services
|
||||||
|
|
||||||
type block = [
|
type block = [
|
||||||
| `Genesis
|
| `Genesis
|
||||||
| `Head of int
|
| `Head of int
|
||||||
| `Test_head of int
|
|
||||||
| `Hash of Block_hash.t * int
|
| `Hash of Block_hash.t * int
|
||||||
]
|
]
|
||||||
val parse_block: string -> (block, string) result
|
val parse_block: string -> (block, string) result
|
||||||
val to_string: block -> string
|
val to_string: block -> string
|
||||||
|
|
||||||
type block_info = {
|
type prefix = (unit * Chain_services.chain) * block
|
||||||
hash: Block_hash.t ;
|
val path: (Chain_services.prefix, Chain_services.prefix * block) RPC_path.t
|
||||||
chain_id: Chain_id.t ;
|
|
||||||
level: Int32.t ;
|
type operation_list_quota = {
|
||||||
proto_level: int ; (* uint8 *)
|
max_size: int ;
|
||||||
predecessor: Block_hash.t ;
|
max_op: int option ;
|
||||||
timestamp: Time.t ;
|
|
||||||
validation_passes: int ; (* uint8 *)
|
|
||||||
operations_hash: Operation_list_list_hash.t ;
|
|
||||||
fitness: MBytes.t list ;
|
|
||||||
context: Context_hash.t ;
|
|
||||||
protocol_data: MBytes.t ;
|
|
||||||
operations: (Operation_hash.t * Operation.t) list list option ;
|
|
||||||
protocol: Protocol_hash.t ;
|
|
||||||
test_chain: Test_chain_status.t ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val pp_block_info: Format.formatter -> block_info -> unit
|
type raw_context =
|
||||||
|
|
||||||
type preapply_result = {
|
|
||||||
shell_header: Block_header.shell_header ;
|
|
||||||
operations: error Preapply_result.t list ;
|
|
||||||
}
|
|
||||||
|
|
||||||
open RPC_context
|
|
||||||
|
|
||||||
val chain_id:
|
|
||||||
#simple -> block -> Chain_id.t tzresult Lwt.t
|
|
||||||
val level:
|
|
||||||
#simple -> block -> Int32.t tzresult Lwt.t
|
|
||||||
val predecessor:
|
|
||||||
#simple -> block -> Block_hash.t tzresult Lwt.t
|
|
||||||
val predecessors:
|
|
||||||
#simple -> block -> int -> Block_hash.t list tzresult Lwt.t
|
|
||||||
val hash:
|
|
||||||
#simple -> block -> Block_hash.t tzresult Lwt.t
|
|
||||||
val timestamp:
|
|
||||||
#simple -> block -> Time.t tzresult Lwt.t
|
|
||||||
val fitness:
|
|
||||||
#simple -> block -> MBytes.t list tzresult Lwt.t
|
|
||||||
val operations:
|
|
||||||
#simple -> ?contents:bool ->
|
|
||||||
block -> (Operation_hash.t * Operation.t option) list list tzresult Lwt.t
|
|
||||||
val protocol:
|
|
||||||
#simple -> block -> Protocol_hash.t tzresult Lwt.t
|
|
||||||
val test_chain:
|
|
||||||
#simple -> block -> Test_chain_status.t tzresult Lwt.t
|
|
||||||
|
|
||||||
val info:
|
|
||||||
#simple ->
|
|
||||||
?include_ops:bool -> block -> block_info tzresult Lwt.t
|
|
||||||
|
|
||||||
val list:
|
|
||||||
?include_ops:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
|
||||||
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
|
||||||
#simple ->
|
|
||||||
block_info list list tzresult Lwt.t
|
|
||||||
|
|
||||||
val monitor:
|
|
||||||
?include_ops:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
|
||||||
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
|
||||||
#streamed ->
|
|
||||||
(block_info list list Lwt_stream.t * stopper) tzresult Lwt.t
|
|
||||||
|
|
||||||
val preapply:
|
|
||||||
#simple -> block ->
|
|
||||||
?timestamp:Time.t ->
|
|
||||||
?sort:bool ->
|
|
||||||
protocol_data:MBytes.t ->
|
|
||||||
Operation.t list list -> preapply_result tzresult Lwt.t
|
|
||||||
|
|
||||||
val complete:
|
|
||||||
#simple -> block -> string -> string list tzresult Lwt.t
|
|
||||||
|
|
||||||
(** Encodes a directory structure returned from a context
|
|
||||||
query as a tree plus a special case [Cut] used when
|
|
||||||
the query is limited by a [depth] value.
|
|
||||||
[Cut] is encoded as [null] in json. *)
|
|
||||||
type raw_context_result =
|
|
||||||
| Key of MBytes.t
|
| Key of MBytes.t
|
||||||
| Dir of (string * raw_context_result) list
|
| Dir of (string * raw_context) list
|
||||||
| Cut
|
| Cut
|
||||||
|
|
||||||
(** Pretty-printer for raw_context_result *)
|
val pp_raw_context: Format.formatter -> raw_context -> unit
|
||||||
val raw_context_result_pp : raw_context_result -> string
|
|
||||||
|
|
||||||
val raw_context:
|
type error +=
|
||||||
#simple -> block -> string list -> int -> raw_context_result tzresult Lwt.t
|
| Invalid_depth_arg of (string list * int)
|
||||||
|
| Missing_key of string list
|
||||||
|
|
||||||
val unmark_invalid:
|
module type PROTO = sig
|
||||||
#simple -> Block_hash.t -> unit Error_monad.tzresult Lwt.t
|
val hash: Protocol_hash.t
|
||||||
val list_invalid:
|
type block_header_data
|
||||||
#simple -> (Block_hash.t * int32 * error list) list tzresult Lwt.t
|
val block_header_data_encoding: block_header_data Data_encoding.t
|
||||||
|
type block_header_metadata
|
||||||
|
val block_header_metadata_encoding:
|
||||||
|
block_header_metadata Data_encoding.t
|
||||||
|
type operation_data
|
||||||
|
val operation_data_encoding: operation_data Data_encoding.t
|
||||||
|
type operation_metadata
|
||||||
|
val operation_metadata_encoding: operation_metadata Data_encoding.t
|
||||||
|
type operation = {
|
||||||
|
shell: Operation.shell_header ;
|
||||||
|
protocol_data: operation_data ;
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
(** Signatures of all RPCs.
|
module Make(Proto : PROTO)(Next_proto : PROTO) : sig
|
||||||
This module is shared between the Client and the Node. *)
|
|
||||||
module S : sig
|
|
||||||
|
|
||||||
val blocks_arg : block RPC_arg.arg
|
val path: (unit, Chain_services.prefix * block) RPC_path.t
|
||||||
|
|
||||||
|
type raw_block_header = {
|
||||||
|
shell: Block_header.shell_header ;
|
||||||
|
protocol_data: Proto.block_header_data ;
|
||||||
|
}
|
||||||
|
|
||||||
|
type block_header = {
|
||||||
|
chain_id: Chain_id.t ;
|
||||||
|
hash: Block_hash.t ;
|
||||||
|
shell: Block_header.shell_header ;
|
||||||
|
protocol_data: Proto.block_header_data ;
|
||||||
|
}
|
||||||
|
|
||||||
|
type block_metadata = {
|
||||||
|
protocol_data: Proto.block_header_metadata ;
|
||||||
|
test_chain_status: Test_chain_status.t ;
|
||||||
|
max_operations_ttl: int ;
|
||||||
|
max_operation_data_length: int ;
|
||||||
|
max_block_header_length: int ;
|
||||||
|
operation_list_quota: operation_list_quota list ;
|
||||||
|
}
|
||||||
|
|
||||||
|
type operation = {
|
||||||
|
chain_id: Chain_id.t ;
|
||||||
|
hash: Operation_hash.t ;
|
||||||
|
shell: Operation.shell_header ;
|
||||||
|
protocol_data: Proto.operation_data ;
|
||||||
|
metadata: Proto.operation_metadata ;
|
||||||
|
}
|
||||||
|
|
||||||
|
type block_info = {
|
||||||
|
chain_id: Chain_id.t ;
|
||||||
|
hash: Block_hash.t ;
|
||||||
|
header: raw_block_header ;
|
||||||
|
metadata: block_metadata ;
|
||||||
|
operations: operation list list ;
|
||||||
|
}
|
||||||
|
|
||||||
|
open RPC_context
|
||||||
|
|
||||||
val info:
|
val info:
|
||||||
([ `POST ], unit,
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
unit * block, unit, bool,
|
unit -> block_info tzresult Lwt.t
|
||||||
block_info) RPC_service.t
|
|
||||||
val chain_id:
|
|
||||||
([ `POST ], unit,
|
|
||||||
unit * block, unit, unit,
|
|
||||||
Chain_id.t) RPC_service.t
|
|
||||||
val level:
|
|
||||||
([ `POST ], unit,
|
|
||||||
unit * block, unit, unit,
|
|
||||||
Int32.t) RPC_service.t
|
|
||||||
val predecessor:
|
|
||||||
([ `POST ], unit,
|
|
||||||
unit * block, unit, unit,
|
|
||||||
Block_hash.t) RPC_service.t
|
|
||||||
val predecessors:
|
|
||||||
([ `POST ], unit,
|
|
||||||
unit * block , unit, int,
|
|
||||||
Block_hash.t list) RPC_service.t
|
|
||||||
val hash:
|
val hash:
|
||||||
([ `POST ], unit,
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
unit * block, unit, unit,
|
unit -> Block_hash.t tzresult Lwt.t
|
||||||
Block_hash.t) RPC_service.t
|
|
||||||
|
module Header : sig
|
||||||
|
|
||||||
|
val header:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> block_header tzresult Lwt.t
|
||||||
|
val shell_header:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Block_header.shell_header tzresult Lwt.t
|
||||||
|
val protocol_data:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Proto.block_header_data tzresult Lwt.t
|
||||||
|
|
||||||
|
module Shell : sig
|
||||||
|
|
||||||
|
val level:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Int32.t tzresult Lwt.t
|
||||||
|
val protocol_level:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> int tzresult Lwt.t
|
||||||
|
val predecessor:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Block_hash.t tzresult Lwt.t
|
||||||
val timestamp:
|
val timestamp:
|
||||||
([ `POST ], unit,
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
unit * block, unit, unit,
|
unit -> Time.t tzresult Lwt.t
|
||||||
Time.t) RPC_service.t
|
val validation_passes:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> int tzresult Lwt.t
|
||||||
|
val operations_hash:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Operation_list_list_hash.t tzresult Lwt.t
|
||||||
val fitness:
|
val fitness:
|
||||||
([ `POST ], unit,
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
unit * block, unit, unit,
|
unit -> Fitness.t tzresult Lwt.t
|
||||||
MBytes.t list) RPC_service.t
|
val context_hash:
|
||||||
val context:
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
([ `POST ], unit,
|
unit -> Context_hash.t tzresult Lwt.t
|
||||||
unit * block, unit, unit,
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Metadata : sig
|
||||||
|
|
||||||
|
val metadata:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> block_metadata tzresult Lwt.t
|
||||||
|
val protocol_data:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Proto.block_header_metadata tzresult Lwt.t
|
||||||
|
val protocol_hash:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Protocol_hash.t tzresult Lwt.t
|
||||||
|
val next_protocol_hash:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Protocol_hash.t tzresult Lwt.t
|
||||||
|
val test_chain_status:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Test_chain_status.t tzresult Lwt.t
|
||||||
|
val max_operations_ttl:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> int tzresult Lwt.t
|
||||||
|
val max_operation_data_length:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> int tzresult Lwt.t
|
||||||
|
val max_block_header_length:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> int tzresult Lwt.t
|
||||||
|
val max_operation_list_length:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> operation_list_quota list tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Operation : sig
|
||||||
|
|
||||||
|
val operations:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> operation list list tzresult Lwt.t
|
||||||
|
val operations_in_pass:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
int -> operation list tzresult Lwt.t
|
||||||
|
val operation:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
int -> int -> operation tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Operation_hash : sig
|
||||||
|
|
||||||
|
val operation_hashes:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
unit -> Operation_hash.t list list tzresult Lwt.t
|
||||||
|
val operation_hashes_in_pass:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
int -> Operation_hash.t list tzresult Lwt.t
|
||||||
|
val operation_hash:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
int -> int -> Operation_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Context : sig
|
||||||
|
|
||||||
|
module Raw : sig
|
||||||
|
|
||||||
|
val read:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
?depth: int ->
|
||||||
|
string list -> raw_context tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Helpers : sig
|
||||||
|
|
||||||
|
val preapply:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
?sort:bool ->
|
||||||
|
timestamp:Time.t ->
|
||||||
|
protocol_data:Next_proto.block_header_data ->
|
||||||
|
Next_proto.operation list list ->
|
||||||
|
(Block_header.shell_header * error Preapply_result.t list) tzresult Lwt.t
|
||||||
|
|
||||||
|
val complete:
|
||||||
|
#simple -> ?chain:chain -> ?block:block ->
|
||||||
|
string -> string list tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module S : sig
|
||||||
|
|
||||||
|
val hash:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Block_hash.t) RPC_service.t
|
||||||
|
|
||||||
|
val info:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
block_info) RPC_service.t
|
||||||
|
|
||||||
|
module Header : sig
|
||||||
|
|
||||||
|
val header:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
block_header) RPC_service.t
|
||||||
|
|
||||||
|
val shell_header:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Block_header.shell_header) RPC_service.t
|
||||||
|
|
||||||
|
val protocol_data:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Proto.block_header_data) RPC_service.t
|
||||||
|
|
||||||
|
module Shell : sig
|
||||||
|
|
||||||
|
val level:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Int32.t) RPC_service.t
|
||||||
|
|
||||||
|
val protocol_level:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
int) RPC_service.t
|
||||||
|
|
||||||
|
val predecessor:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Block_hash.t) RPC_service.t
|
||||||
|
|
||||||
|
val timestamp:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Time.t) RPC_service.t
|
||||||
|
|
||||||
|
val validation_passes:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
int) RPC_service.t
|
||||||
|
|
||||||
|
val operations_hash:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Operation_list_list_hash.t) RPC_service.t
|
||||||
|
|
||||||
|
val fitness:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Fitness.t) RPC_service.t
|
||||||
|
|
||||||
|
val context_hash:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
Context_hash.t) RPC_service.t
|
Context_hash.t) RPC_service.t
|
||||||
|
|
||||||
(** Accepts queries of the form
|
end
|
||||||
/blocks/<id>/raw_context/<path>?depth=<n>
|
|
||||||
returning the sub-tree corresponding to <path> inside the context of
|
|
||||||
block <id>. The optional parameter <depth> controls the size of the
|
|
||||||
tree, default is 1.
|
|
||||||
Example:
|
|
||||||
tezos-client rpc post /blocks/head/raw_context/v1?depth=2
|
|
||||||
*)
|
|
||||||
val raw_context:
|
|
||||||
([ `POST ], unit,
|
|
||||||
(unit * block) * string list, <depth:int>, unit,
|
|
||||||
raw_context_result) RPC_service.t
|
|
||||||
|
|
||||||
type operations_param = {
|
end
|
||||||
contents: bool ;
|
|
||||||
}
|
|
||||||
val operations:
|
|
||||||
([ `POST ], unit,
|
|
||||||
unit * block, unit, operations_param,
|
|
||||||
(Operation_hash.t * Operation.t option) list list) RPC_service.t
|
|
||||||
|
|
||||||
val protocol:
|
module Metadata : sig
|
||||||
([ `POST ], unit,
|
|
||||||
unit * block, unit, unit,
|
val metadata:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
block_metadata) RPC_service.t
|
||||||
|
|
||||||
|
val protocol_data:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Proto.block_header_metadata) RPC_service.t
|
||||||
|
|
||||||
|
val protocol_hash:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
Protocol_hash.t) RPC_service.t
|
Protocol_hash.t) RPC_service.t
|
||||||
val test_chain:
|
|
||||||
([ `POST ], unit,
|
val next_protocol_hash:
|
||||||
unit * block, unit, unit,
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Protocol_hash.t) RPC_service.t
|
||||||
|
|
||||||
|
val test_chain_status:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
Test_chain_status.t) RPC_service.t
|
Test_chain_status.t) RPC_service.t
|
||||||
|
|
||||||
type list_param = {
|
val max_operations_ttl:
|
||||||
include_ops: bool ;
|
([ `GET ], prefix,
|
||||||
length: int option ;
|
prefix, unit, unit,
|
||||||
heads: Block_hash.t list option ;
|
int) RPC_service.t
|
||||||
monitor: bool option ;
|
|
||||||
delay: int option ;
|
|
||||||
min_date: Time.t option;
|
|
||||||
min_heads: int option;
|
|
||||||
}
|
|
||||||
val list:
|
|
||||||
([ `POST ], unit,
|
|
||||||
unit, unit, list_param,
|
|
||||||
block_info list list) RPC_service.t
|
|
||||||
|
|
||||||
val list_invalid:
|
val max_operation_data_length:
|
||||||
([ `POST ], unit,
|
([ `GET ], prefix,
|
||||||
unit, unit, unit,
|
prefix, unit, unit,
|
||||||
(Block_hash.t * int32 * error list) list) RPC_service.t
|
int) RPC_service.t
|
||||||
|
|
||||||
val unmark_invalid:
|
val max_block_header_length:
|
||||||
([ `POST ], unit,
|
([ `GET ], prefix,
|
||||||
unit * Block_hash.t, unit, unit,
|
prefix, unit, unit,
|
||||||
unit) RPC_service.t
|
int) RPC_service.t
|
||||||
|
|
||||||
|
val operation_list_quota:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
operation_list_quota list) RPC_service.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Operation : sig
|
||||||
|
|
||||||
|
val operations:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
operation list list) RPC_service.t
|
||||||
|
|
||||||
|
val operations_in_pass:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix * int, unit, unit,
|
||||||
|
operation list) RPC_service.t
|
||||||
|
|
||||||
|
val operation:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
(prefix * int) * int, unit, unit,
|
||||||
|
operation) RPC_service.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Operation_hash : sig
|
||||||
|
|
||||||
|
val operation_hashes:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Tezos_crypto.Operation_hash.t list list) RPC_service.t
|
||||||
|
|
||||||
|
val operation_hashes_in_pass:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix * int, unit, unit,
|
||||||
|
Tezos_crypto.Operation_hash.t list) RPC_service.t
|
||||||
|
|
||||||
|
val operation_hash:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
(prefix * int) * int, unit, unit,
|
||||||
|
Tezos_crypto.Operation_hash.t) RPC_service.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Context : sig
|
||||||
|
|
||||||
|
module Raw : sig
|
||||||
|
|
||||||
|
val read:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix * string list, < depth : int option >, unit,
|
||||||
|
raw_context) RPC_service.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Helpers : sig
|
||||||
|
|
||||||
type preapply_param = {
|
type preapply_param = {
|
||||||
timestamp: Time.t ;
|
timestamp: Time.t ;
|
||||||
protocol_data: MBytes.t ;
|
protocol_data: Next_proto.block_header_data ;
|
||||||
operations: Operation.t list list ;
|
operations: Next_proto.operation list list ;
|
||||||
sort_operations: bool ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val preapply:
|
val preapply:
|
||||||
([ `POST ], unit,
|
([ `POST ], prefix,
|
||||||
unit * block, unit, preapply_param,
|
prefix, < sort_operations : bool >, preapply_param,
|
||||||
preapply_result) RPC_service.t
|
Block_header.shell_header * error Preapply_result.t list) RPC_service.t
|
||||||
|
|
||||||
val complete:
|
val complete:
|
||||||
([ `POST ], unit,
|
([ `GET ], prefix,
|
||||||
(unit * block) * string, unit, unit,
|
prefix * string, unit, unit,
|
||||||
string list) RPC_service.t
|
string list) RPC_service.t
|
||||||
|
|
||||||
val proto_path: unit -> ('a, 'a * block) RPC_path.path
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
module Fake_protocol : PROTO
|
||||||
|
module Empty : (module type of Make(Fake_protocol)(Fake_protocol))
|
||||||
|
228
src/lib_shell_services/chain_services.ml
Normal file
228
src/lib_shell_services/chain_services.ml
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
open Data_encoding
|
||||||
|
|
||||||
|
type chain = [
|
||||||
|
| `Main
|
||||||
|
| `Test
|
||||||
|
| `Hash of Chain_id.t
|
||||||
|
]
|
||||||
|
|
||||||
|
let parse_chain s =
|
||||||
|
try
|
||||||
|
match s with
|
||||||
|
| "main" -> Ok `Main
|
||||||
|
| "test" -> Ok `Test
|
||||||
|
| h -> Ok (`Hash (Chain_id.of_b58check_exn h))
|
||||||
|
with _ -> Error "Cannot parse block identifier."
|
||||||
|
|
||||||
|
let to_string = function
|
||||||
|
| `Main -> "main"
|
||||||
|
| `Test -> "test"
|
||||||
|
| `Hash h -> Chain_id.to_b58check h
|
||||||
|
|
||||||
|
let chain_arg =
|
||||||
|
let name = "chain_id" in
|
||||||
|
let descr =
|
||||||
|
"A chain identifier. This is either a chain hash in Base58Check notation \
|
||||||
|
or a one the predefined aliases: 'main', 'test'." in
|
||||||
|
let construct = to_string in
|
||||||
|
let destruct = parse_chain in
|
||||||
|
RPC_arg.make ~name ~descr ~construct ~destruct ()
|
||||||
|
|
||||||
|
type prefix = unit * chain
|
||||||
|
let path = RPC_path.(root / "chains" /: chain_arg)
|
||||||
|
|
||||||
|
type invalid_block = {
|
||||||
|
hash: Block_hash.t ;
|
||||||
|
level: Int32.t ;
|
||||||
|
errors: error list ;
|
||||||
|
}
|
||||||
|
|
||||||
|
let invalid_block_encoding =
|
||||||
|
conv
|
||||||
|
(fun { hash ; level ; errors } -> (hash, level, errors))
|
||||||
|
(fun (hash, level, errors) -> { hash ; level ; errors })
|
||||||
|
(obj3
|
||||||
|
(req "block" Block_hash.encoding)
|
||||||
|
(req "level" int32)
|
||||||
|
(req "errors" RPC_error.encoding))
|
||||||
|
|
||||||
|
module S = struct
|
||||||
|
|
||||||
|
let path : prefix RPC_path.context = RPC_path.open_root
|
||||||
|
|
||||||
|
let chain_id =
|
||||||
|
RPC_service.get_service
|
||||||
|
~description:"The chain unique identifier."
|
||||||
|
~query: RPC_query.empty
|
||||||
|
~output: Chain_id.encoding
|
||||||
|
RPC_path.(path / "chain_id")
|
||||||
|
|
||||||
|
module Mempool = struct
|
||||||
|
|
||||||
|
let operation_encoding =
|
||||||
|
merge_objs
|
||||||
|
(obj1 (req "hash" Operation_hash.encoding))
|
||||||
|
Operation.encoding
|
||||||
|
|
||||||
|
let pending_operations =
|
||||||
|
(* TODO: branch_delayed/... *)
|
||||||
|
RPC_service.get_service
|
||||||
|
~description:
|
||||||
|
"List the not-yet-prevalidated operations."
|
||||||
|
~query: RPC_query.empty
|
||||||
|
~output:
|
||||||
|
(conv
|
||||||
|
(fun (preapplied, unprocessed) ->
|
||||||
|
({ preapplied with
|
||||||
|
Preapply_result.refused = Operation_hash.Map.empty },
|
||||||
|
Operation_hash.Map.bindings unprocessed))
|
||||||
|
(fun (preapplied, unprocessed) ->
|
||||||
|
(preapplied,
|
||||||
|
List.fold_right
|
||||||
|
(fun (h, op) m -> Operation_hash.Map.add h op m)
|
||||||
|
unprocessed Operation_hash.Map.empty))
|
||||||
|
(merge_objs
|
||||||
|
(dynamic_size
|
||||||
|
(Preapply_result.encoding RPC_error.encoding))
|
||||||
|
(obj1 (req "unprocessed" (list (dynamic_size operation_encoding))))))
|
||||||
|
RPC_path.(path / "mempool")
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Blocks = struct
|
||||||
|
|
||||||
|
let list_query =
|
||||||
|
let open RPC_query in
|
||||||
|
query (fun length heads min_date ->
|
||||||
|
object
|
||||||
|
method length = length
|
||||||
|
method heads = heads
|
||||||
|
method min_date = min_date
|
||||||
|
end)
|
||||||
|
|+ opt_field "length"
|
||||||
|
~descr:
|
||||||
|
"The requested number of predecessors to returns (per \
|
||||||
|
requested head)."
|
||||||
|
RPC_arg.int (fun x -> x#length)
|
||||||
|
|+ multi_field "head"
|
||||||
|
~descr:
|
||||||
|
"An empty argument requests blocks from the current heads. \
|
||||||
|
A non empty list allow to request specific fragment \
|
||||||
|
of the chain."
|
||||||
|
Block_hash.rpc_arg (fun x -> x#heads)
|
||||||
|
|+ opt_field "min_date"
|
||||||
|
~descr: "When `min_date` is provided, heads with a \
|
||||||
|
timestamp before `min_date` are filtered out"
|
||||||
|
Time.rpc_arg (fun x -> x#min_date)
|
||||||
|
|> seal
|
||||||
|
|
||||||
|
let path = RPC_path.(path / "blocks")
|
||||||
|
|
||||||
|
let list =
|
||||||
|
let open Data_encoding in
|
||||||
|
RPC_service.get_service
|
||||||
|
~description:
|
||||||
|
"Lists known heads of the blockchain sorted with decreasing fitness. \
|
||||||
|
Optional arguments allows to returns the list of predecessors for \
|
||||||
|
known heads or the list of predecessors for a given list of blocks."
|
||||||
|
~query: list_query
|
||||||
|
~output: (list (list Block_hash.encoding))
|
||||||
|
path
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Invalid_blocks = struct
|
||||||
|
|
||||||
|
let path = RPC_path.(path / "invalid_blocks")
|
||||||
|
|
||||||
|
let list =
|
||||||
|
RPC_service.get_service
|
||||||
|
~description:
|
||||||
|
"Lists blocks that have been declared invalid along with the errors \
|
||||||
|
that led to them being declared invalid."
|
||||||
|
~query: RPC_query.empty
|
||||||
|
~output: (list invalid_block_encoding)
|
||||||
|
path
|
||||||
|
|
||||||
|
let get =
|
||||||
|
RPC_service.get_service
|
||||||
|
~description: "The errors that appears during the block (in)validation."
|
||||||
|
~query: RPC_query.empty
|
||||||
|
~output: invalid_block_encoding
|
||||||
|
RPC_path.(path /: Block_hash.rpc_arg)
|
||||||
|
|
||||||
|
let delete =
|
||||||
|
RPC_service.delete_service
|
||||||
|
~description: "Remove an invalid block for the tezos storage"
|
||||||
|
~query: RPC_query.empty
|
||||||
|
~output: Data_encoding.empty
|
||||||
|
RPC_path.(path /: Block_hash.rpc_arg)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
let make_call0 s ctxt chain q p =
|
||||||
|
let s = RPC_service.prefix path s in
|
||||||
|
RPC_context.make_call1 s ctxt chain q p
|
||||||
|
|
||||||
|
let make_call1 s ctxt chain a q p =
|
||||||
|
let s = RPC_service.prefix path s in
|
||||||
|
RPC_context.make_call2 s ctxt chain a q p
|
||||||
|
|
||||||
|
let chain_id ctxt =
|
||||||
|
let f = make_call0 S.chain_id ctxt in
|
||||||
|
fun ?(chain = `Main) () ->
|
||||||
|
match chain with
|
||||||
|
| `Hash h -> return h
|
||||||
|
| _ -> f chain () ()
|
||||||
|
|
||||||
|
module Mempool = struct
|
||||||
|
|
||||||
|
let pending_operations ctxt ?(chain = `Main) () =
|
||||||
|
make_call0 S.Mempool.pending_operations ctxt chain () ()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Blocks = struct
|
||||||
|
|
||||||
|
let list ctxt =
|
||||||
|
let f = make_call0 S.Blocks.list ctxt in
|
||||||
|
fun ?(chain = `Main) ?(heads = []) ?length ?min_date () ->
|
||||||
|
f chain
|
||||||
|
(object
|
||||||
|
method heads = heads
|
||||||
|
method length = length
|
||||||
|
method min_date = min_date
|
||||||
|
end)
|
||||||
|
()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Invalid_blocks = struct
|
||||||
|
|
||||||
|
let list ctxt =
|
||||||
|
let f = make_call0 S.Invalid_blocks.list ctxt in
|
||||||
|
fun ?(chain = `Main) () ->
|
||||||
|
f chain () ()
|
||||||
|
|
||||||
|
let get ctxt =
|
||||||
|
let f = make_call1 S.Invalid_blocks.get ctxt in
|
||||||
|
fun ?(chain = `Main) block ->
|
||||||
|
f chain block () ()
|
||||||
|
|
||||||
|
let delete ctxt =
|
||||||
|
let f = make_call1 S.Invalid_blocks.delete ctxt in
|
||||||
|
fun ?(chain = `Main) block ->
|
||||||
|
f chain block () ()
|
||||||
|
|
||||||
|
end
|
126
src/lib_shell_services/chain_services.mli
Normal file
126
src/lib_shell_services/chain_services.mli
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
(**************************************************************************)
|
||||||
|
(* *)
|
||||||
|
(* Copyright (c) 2014 - 2018. *)
|
||||||
|
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
||||||
|
(* *)
|
||||||
|
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
||||||
|
(* *)
|
||||||
|
(**************************************************************************)
|
||||||
|
|
||||||
|
type chain = [
|
||||||
|
| `Main
|
||||||
|
| `Test
|
||||||
|
| `Hash of Chain_id.t
|
||||||
|
]
|
||||||
|
|
||||||
|
val parse_chain: string -> (chain, string) result
|
||||||
|
val to_string: chain -> string
|
||||||
|
|
||||||
|
val chain_arg: chain RPC_arg.t
|
||||||
|
|
||||||
|
type invalid_block = {
|
||||||
|
hash: Block_hash.t ;
|
||||||
|
level: Int32.t ;
|
||||||
|
errors: error list ;
|
||||||
|
}
|
||||||
|
|
||||||
|
type prefix = unit * chain
|
||||||
|
val path: (unit, prefix) RPC_path.path
|
||||||
|
|
||||||
|
open RPC_context
|
||||||
|
|
||||||
|
val chain_id:
|
||||||
|
#simple ->
|
||||||
|
?chain:chain ->
|
||||||
|
unit -> Chain_id.t tzresult Lwt.t
|
||||||
|
|
||||||
|
module Mempool : sig
|
||||||
|
|
||||||
|
val pending_operations:
|
||||||
|
#simple ->
|
||||||
|
?chain:chain ->
|
||||||
|
unit ->
|
||||||
|
(error Preapply_result.t * Operation.t Operation_hash.Map.t) tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Blocks : sig
|
||||||
|
|
||||||
|
val list:
|
||||||
|
#simple ->
|
||||||
|
?chain:chain ->
|
||||||
|
?heads:Block_hash.t list ->
|
||||||
|
?length:int ->
|
||||||
|
?min_date:Time.t ->
|
||||||
|
unit -> Block_hash.t list list tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Invalid_blocks : sig
|
||||||
|
|
||||||
|
val list:
|
||||||
|
#simple ->
|
||||||
|
?chain:chain ->
|
||||||
|
unit -> invalid_block list tzresult Lwt.t
|
||||||
|
|
||||||
|
val get:
|
||||||
|
#simple ->
|
||||||
|
?chain:chain ->
|
||||||
|
Block_hash.t -> invalid_block tzresult Lwt.t
|
||||||
|
|
||||||
|
val delete:
|
||||||
|
#simple ->
|
||||||
|
?chain:chain ->
|
||||||
|
Block_hash.t -> unit tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module S : sig
|
||||||
|
|
||||||
|
val chain_id:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
Chain_id.t) RPC_service.t
|
||||||
|
|
||||||
|
module Mempool : sig
|
||||||
|
|
||||||
|
val pending_operations:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix , unit, unit,
|
||||||
|
error Preapply_result.t * Operation.t Operation_hash.Map.t) RPC_service.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Blocks : sig
|
||||||
|
|
||||||
|
val path: (prefix, prefix) RPC_path.t
|
||||||
|
|
||||||
|
val list:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, < heads : Block_hash.t list;
|
||||||
|
length : int option;
|
||||||
|
min_date : Time.t option >, unit,
|
||||||
|
Block_hash.t list list) RPC_service.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module Invalid_blocks : sig
|
||||||
|
|
||||||
|
val list:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix, unit, unit,
|
||||||
|
invalid_block list) RPC_service.t
|
||||||
|
|
||||||
|
val get:
|
||||||
|
([ `GET ], prefix,
|
||||||
|
prefix * Block_hash.t, unit, unit,
|
||||||
|
invalid_block) RPC_service.t
|
||||||
|
|
||||||
|
val delete:
|
||||||
|
([ `DELETE ], prefix,
|
||||||
|
prefix * Block_hash.t, unit, unit,
|
||||||
|
unit) RPC_service.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
@ -4,7 +4,7 @@
|
|||||||
((name tezos_shell_services)
|
((name tezos_shell_services)
|
||||||
(public_name tezos-shell-services)
|
(public_name tezos-shell-services)
|
||||||
(libraries (tezos-base))
|
(libraries (tezos-base))
|
||||||
(flags (:standard -w -9+27-30-32-40@8
|
(flags (:standard -w +27@8
|
||||||
-safe-string
|
-safe-string
|
||||||
-open Tezos_base__TzPervasives))))
|
-open Tezos_base__TzPervasives))))
|
||||||
|
|
||||||
|
@ -1,48 +0,0 @@
|
|||||||
(**************************************************************************)
|
|
||||||
(* *)
|
|
||||||
(* Copyright (c) 2014 - 2018. *)
|
|
||||||
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
|
|
||||||
(* *)
|
|
||||||
(* All rights reserved. No warranty, explicit or implicit, provided. *)
|
|
||||||
(* *)
|
|
||||||
(**************************************************************************)
|
|
||||||
|
|
||||||
open Data_encoding
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module S = struct
|
|
||||||
|
|
||||||
let pending_operations =
|
|
||||||
let operation_encoding =
|
|
||||||
merge_objs
|
|
||||||
(obj1 (req "hash" Operation_hash.encoding))
|
|
||||||
Operation.encoding in
|
|
||||||
(* TODO: branch_delayed/... *)
|
|
||||||
RPC_service.post_service
|
|
||||||
~description:
|
|
||||||
"List the not-yet-prevalidated operations."
|
|
||||||
~query: RPC_query.empty
|
|
||||||
~input: empty
|
|
||||||
~output:
|
|
||||||
(conv
|
|
||||||
(fun (preapplied, unprocessed) ->
|
|
||||||
({ preapplied with
|
|
||||||
Preapply_result.refused = Operation_hash.Map.empty },
|
|
||||||
Operation_hash.Map.bindings unprocessed))
|
|
||||||
(fun (preapplied, unprocessed) ->
|
|
||||||
(preapplied,
|
|
||||||
List.fold_right
|
|
||||||
(fun (h, op) m -> Operation_hash.Map.add h op m)
|
|
||||||
unprocessed Operation_hash.Map.empty))
|
|
||||||
(merge_objs
|
|
||||||
(dynamic_size
|
|
||||||
(Preapply_result.encoding RPC_error.encoding))
|
|
||||||
(obj1 (req "unprocessed" (list (dynamic_size operation_encoding))))))
|
|
||||||
RPC_path.(root / "mempool" / "pending_operations")
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
open RPC_context
|
|
||||||
|
|
||||||
let pending_operations ctxt = make_call S.pending_operations ctxt () () ()
|
|
@ -124,19 +124,51 @@ module S = struct
|
|||||||
(req "timestamp" Time.encoding))
|
(req "timestamp" Time.encoding))
|
||||||
RPC_path.(root / "bootstrapped")
|
RPC_path.(root / "bootstrapped")
|
||||||
|
|
||||||
let complete =
|
module Monitor = struct
|
||||||
let prefix_arg =
|
|
||||||
let destruct s = Ok s
|
let path = RPC_path.(root / "monitor")
|
||||||
and construct s = s in
|
|
||||||
RPC_arg.make ~name:"prefix" ~destruct ~construct () in
|
let valid_blocks_query =
|
||||||
RPC_service.post_service
|
let open RPC_query in
|
||||||
~description: "Try to complete a prefix of a Base58Check-encoded data. \
|
query (fun protocols next_protocols chains -> object
|
||||||
This RPC is actually able to complete hashes of \
|
method protocols = protocols
|
||||||
block and hashes of operations."
|
method next_protocols = next_protocols
|
||||||
~query: RPC_query.empty
|
method chains = chains
|
||||||
~input: empty
|
end)
|
||||||
~output: (list string)
|
|+ multi_field "protocol"
|
||||||
RPC_path.(root / "complete" /: prefix_arg )
|
Protocol_hash.rpc_arg (fun t -> t#protocols)
|
||||||
|
|+ multi_field "next_protocol"
|
||||||
|
Protocol_hash.rpc_arg (fun t -> t#next_protocols)
|
||||||
|
|+ multi_field "chain"
|
||||||
|
Chain_services.chain_arg (fun t -> t#chains)
|
||||||
|
|> seal
|
||||||
|
|
||||||
|
let valid_blocks =
|
||||||
|
RPC_service.get_service
|
||||||
|
~description:""
|
||||||
|
~query: valid_blocks_query
|
||||||
|
~output: (obj2
|
||||||
|
(req "chain_id" Chain_id.encoding)
|
||||||
|
(req "hash" Block_hash.encoding))
|
||||||
|
RPC_path.(path / "valid_blocks")
|
||||||
|
|
||||||
|
let heads_query =
|
||||||
|
let open RPC_query in
|
||||||
|
query (fun next_protocols -> object
|
||||||
|
method next_protocols = next_protocols
|
||||||
|
end)
|
||||||
|
|+ multi_field "next_protocol"
|
||||||
|
Protocol_hash.rpc_arg (fun t -> t#next_protocols)
|
||||||
|
|> seal
|
||||||
|
|
||||||
|
let heads =
|
||||||
|
RPC_service.get_service
|
||||||
|
~description:""
|
||||||
|
~query: heads_query
|
||||||
|
~output: Block_hash.encoding
|
||||||
|
RPC_path.(path / "heads" /: Chain_services.chain_arg)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -162,9 +194,21 @@ let inject_protocol ctxt ?(async = false) ?force protocol =
|
|||||||
let bootstrapped ctxt =
|
let bootstrapped ctxt =
|
||||||
make_streamed_call S.bootstrapped ctxt () () ()
|
make_streamed_call S.bootstrapped ctxt () () ()
|
||||||
|
|
||||||
let complete ctxt ?block prefix =
|
module Monitor = struct
|
||||||
match block with
|
|
||||||
| None ->
|
module S = S.Monitor
|
||||||
make_call1 S.complete ctxt prefix () ()
|
|
||||||
| Some block ->
|
let valid_blocks
|
||||||
Block_services.complete ctxt block prefix
|
ctxt ?(chains = [`Main]) ?(protocols = []) ?(next_protocols = []) () =
|
||||||
|
make_streamed_call S.valid_blocks ctxt () (object
|
||||||
|
method chains = chains
|
||||||
|
method protocols = protocols
|
||||||
|
method next_protocols = next_protocols
|
||||||
|
end) ()
|
||||||
|
|
||||||
|
let heads ctxt ?(next_protocols = []) chain =
|
||||||
|
make_streamed_call S.heads ctxt ((), chain) (object
|
||||||
|
method next_protocols = next_protocols
|
||||||
|
end) ()
|
||||||
|
|
||||||
|
end
|
||||||
|
@ -41,9 +41,22 @@ val inject_protocol:
|
|||||||
val bootstrapped:
|
val bootstrapped:
|
||||||
#streamed -> ((Block_hash.t * Time.t) Lwt_stream.t * stopper) tzresult Lwt.t
|
#streamed -> ((Block_hash.t * Time.t) Lwt_stream.t * stopper) tzresult Lwt.t
|
||||||
|
|
||||||
val complete:
|
module Monitor : sig
|
||||||
#simple ->
|
|
||||||
?block:Block_services.block -> string -> string list tzresult Lwt.t
|
val valid_blocks:
|
||||||
|
#streamed ->
|
||||||
|
?chains:Chain_services.chain list ->
|
||||||
|
?protocols:Protocol_hash.t list ->
|
||||||
|
?next_protocols:Protocol_hash.t list ->
|
||||||
|
unit -> ((Chain_id.t * Block_hash.t) Lwt_stream.t * stopper) tzresult Lwt.t
|
||||||
|
|
||||||
|
val heads:
|
||||||
|
#streamed ->
|
||||||
|
?next_protocols:Protocol_hash.t list ->
|
||||||
|
Chain_services.chain ->
|
||||||
|
(Block_hash.t Lwt_stream.t * stopper) tzresult Lwt.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
module S : sig
|
module S : sig
|
||||||
|
|
||||||
@ -80,9 +93,21 @@ module S : sig
|
|||||||
unit, unit, unit,
|
unit, unit, unit,
|
||||||
Block_hash.t * Time.t) RPC_service.t
|
Block_hash.t * Time.t) RPC_service.t
|
||||||
|
|
||||||
val complete:
|
module Monitor : sig
|
||||||
([ `POST ], unit,
|
|
||||||
unit * string, unit, unit,
|
val valid_blocks:
|
||||||
string list) RPC_service.t
|
([ `GET ], unit,
|
||||||
|
unit, < chains : Chain_services.chain list;
|
||||||
|
next_protocols : Protocol_hash.t list;
|
||||||
|
protocols : Protocol_hash.t list >, unit,
|
||||||
|
Chain_id.t * Block_hash.t) RPC_service.t
|
||||||
|
|
||||||
|
val heads:
|
||||||
|
([ `GET ], unit,
|
||||||
|
unit * Chain_services.chain,
|
||||||
|
< next_protocols : Protocol_hash.t list >, unit,
|
||||||
|
Block_hash.t) RPC_service.t
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -13,12 +13,6 @@ module Prevalidators = struct
|
|||||||
|
|
||||||
module S = struct
|
module S = struct
|
||||||
|
|
||||||
let (chain_id_arg : Chain_id.t RPC_arg.t) =
|
|
||||||
RPC_arg.like
|
|
||||||
Chain_id.rpc_arg
|
|
||||||
~descr:"The chain identifier of whom the prevalidator is responsible."
|
|
||||||
"chain_id"
|
|
||||||
|
|
||||||
let list =
|
let list =
|
||||||
RPC_service.post_service
|
RPC_service.post_service
|
||||||
~description:"Lists the Prevalidator workers and their status."
|
~description:"Lists the Prevalidator workers and their status."
|
||||||
|
@ -17,68 +17,48 @@ type block_info = {
|
|||||||
fitness: MBytes.t list ;
|
fitness: MBytes.t list ;
|
||||||
timestamp: Time.t ;
|
timestamp: Time.t ;
|
||||||
protocol: Protocol_hash.t ;
|
protocol: Protocol_hash.t ;
|
||||||
|
next_protocol: Protocol_hash.t ;
|
||||||
level: Level.t ;
|
level: Level.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
let convert_block_info cctxt
|
let info cctxt ?(chain = `Main) block =
|
||||||
( { hash ; chain_id ; predecessor ; fitness ; timestamp ; protocol }
|
Chain_services.chain_id cctxt ~chain () >>=? fun chain_id ->
|
||||||
: Block_services.block_info ) =
|
Block_services.hash cctxt ~chain ~block () >>=? fun hash ->
|
||||||
Alpha_services.Context.level cctxt (`Hash (hash, 0)) >>= function
|
Block_services.Header.shell_header cctxt ~chain ~block () >>=? fun header ->
|
||||||
| Ok level ->
|
Block_services.Metadata.next_protocol_hash
|
||||||
Lwt.return
|
cctxt ~chain ~block () >>=? fun next_protocol ->
|
||||||
(Some { hash ; chain_id ; predecessor ;
|
Block_services.Metadata.protocol_hash
|
||||||
fitness ; timestamp ; protocol ; level })
|
cctxt ~chain ~block () >>=? fun protocol ->
|
||||||
| Error _ ->
|
Alpha_services.Context.level cctxt (chain, block) >>=? fun level ->
|
||||||
(* TODO log error *)
|
let { Tezos_base.Block_header.predecessor ; fitness ; timestamp ; _ } = header in
|
||||||
Lwt.return_none
|
return { hash ; chain_id ; predecessor ; fitness ;
|
||||||
|
timestamp ; protocol ; next_protocol ; level }
|
||||||
|
|
||||||
let convert_block_info_err cctxt
|
let monitor_valid_blocks cctxt ?chains ?protocols ?next_protocols () =
|
||||||
( { hash ; chain_id ; predecessor ; fitness ; timestamp ; protocol }
|
Shell_services.Monitor.valid_blocks cctxt
|
||||||
: Block_services.block_info ) =
|
?chains ?protocols ?next_protocols () >>=? fun (block_stream, _stop) ->
|
||||||
Alpha_services.Context.level cctxt (`Hash (hash, 0)) >>=? fun level ->
|
return (Lwt_stream.map_s
|
||||||
return { hash ; chain_id ; predecessor ; fitness ; timestamp ; protocol ; level }
|
(fun (chain, block) ->
|
||||||
|
info cctxt ~chain:(`Hash chain) (`Hash (block, 0))) block_stream)
|
||||||
|
|
||||||
let info cctxt ?include_ops block =
|
let monitor_heads cctxt ?next_protocols chain =
|
||||||
Block_services.info cctxt ?include_ops block >>=? fun block ->
|
Shell_services.Monitor.heads
|
||||||
convert_block_info_err cctxt block
|
cctxt ?next_protocols chain >>=? fun (block_stream, _stop) ->
|
||||||
|
return (Lwt_stream.map_s
|
||||||
|
(fun block -> info cctxt ~chain (`Hash (block, 0)))
|
||||||
|
block_stream)
|
||||||
|
|
||||||
let compare (bi1 : block_info) (bi2 : block_info) =
|
let blocks_from_cycle cctxt ?(chain = `Main) block cycle =
|
||||||
match Fitness.compare bi1.fitness bi2.fitness with
|
Block_services.hash cctxt ~chain ~block () >>=? fun hash ->
|
||||||
| 0 -> begin
|
Alpha_services.Context.level cctxt (chain, block) >>=? fun level ->
|
||||||
match compare bi1.level bi2.level with
|
Alpha_services.Helpers.levels cctxt (chain, block) cycle >>=? fun (first, last) ->
|
||||||
| 0 -> begin
|
|
||||||
match Time.compare bi1.timestamp bi2.timestamp with
|
|
||||||
| 0 -> Block_hash.compare bi1.predecessor bi2.predecessor
|
|
||||||
| x -> - x
|
|
||||||
end
|
|
||||||
| x -> - x
|
|
||||||
end
|
|
||||||
| x -> x
|
|
||||||
|
|
||||||
let sort_blocks cctxt ?(compare = compare) blocks =
|
|
||||||
Lwt_list.filter_map_p (convert_block_info cctxt) blocks >|= fun blocks ->
|
|
||||||
List.sort compare blocks
|
|
||||||
|
|
||||||
let monitor cctxt
|
|
||||||
?include_ops ?length ?heads ?delay
|
|
||||||
?min_date ?min_heads ?compare () =
|
|
||||||
Block_services.monitor
|
|
||||||
?include_ops ?length ?heads ?delay ?min_date ?min_heads
|
|
||||||
cctxt >>=? fun (block_stream, _stop) ->
|
|
||||||
let convert blocks =
|
|
||||||
sort_blocks cctxt ?compare (List.flatten blocks) >>= return in
|
|
||||||
return (Lwt_stream.map_s convert block_stream)
|
|
||||||
|
|
||||||
let blocks_from_cycle cctxt block cycle =
|
|
||||||
Alpha_services.Context.level cctxt block >>=? fun level ->
|
|
||||||
Alpha_services.Helpers.levels cctxt block cycle >>=? fun (first, last) ->
|
|
||||||
let length = Int32.to_int (Raw_level.diff level.level first) in
|
let length = Int32.to_int (Raw_level.diff level.level first) in
|
||||||
Block_services.predecessors cctxt block length >>=? fun blocks ->
|
Chain_services.Blocks.list cctxt ~heads:[hash] ~length () >>=? fun blocks ->
|
||||||
let blocks =
|
let blocks =
|
||||||
List.remove
|
List.remove
|
||||||
(length - (1 + Int32.to_int (Raw_level.diff last first))) blocks in
|
(length - (Int32.to_int (Raw_level.diff last first)))
|
||||||
|
(List.hd blocks) in
|
||||||
if Raw_level.(level.level = last) then
|
if Raw_level.(level.level = last) then
|
||||||
Block_services.hash cctxt block >>=? fun last ->
|
return (hash :: blocks)
|
||||||
return (last :: blocks)
|
|
||||||
else
|
else
|
||||||
return blocks
|
return blocks
|
||||||
|
@ -17,25 +17,32 @@ type block_info = {
|
|||||||
fitness: MBytes.t list ;
|
fitness: MBytes.t list ;
|
||||||
timestamp: Time.t ;
|
timestamp: Time.t ;
|
||||||
protocol: Protocol_hash.t ;
|
protocol: Protocol_hash.t ;
|
||||||
|
next_protocol: Protocol_hash.t ;
|
||||||
level: Level.t ;
|
level: Level.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
val info:
|
val info:
|
||||||
#Proto_alpha.rpc_context ->
|
#Proto_alpha.rpc_context ->
|
||||||
?include_ops:bool -> Block_services.block -> block_info tzresult Lwt.t
|
?chain:Chain_services.chain ->
|
||||||
|
Block_services.block ->
|
||||||
|
block_info tzresult Lwt.t
|
||||||
|
|
||||||
val compare:
|
val monitor_valid_blocks:
|
||||||
block_info -> block_info -> int
|
|
||||||
|
|
||||||
val monitor:
|
|
||||||
#Proto_alpha.rpc_context ->
|
#Proto_alpha.rpc_context ->
|
||||||
?include_ops:bool -> ?length:int -> ?heads:Block_hash.t list ->
|
?chains:Chain_services.chain list ->
|
||||||
?delay:int -> ?min_date:Time.t -> ?min_heads:int ->
|
?protocols:Protocol_hash.t list ->
|
||||||
?compare:(block_info -> block_info -> int) ->
|
?next_protocols:Protocol_hash.t list ->
|
||||||
unit -> block_info list tzresult Lwt_stream.t tzresult Lwt.t
|
unit -> block_info tzresult Lwt_stream.t tzresult Lwt.t
|
||||||
|
|
||||||
|
val monitor_heads:
|
||||||
|
#Proto_alpha.rpc_context ->
|
||||||
|
?next_protocols:Protocol_hash.t list ->
|
||||||
|
Chain_services.chain ->
|
||||||
|
block_info tzresult Lwt_stream.t tzresult Lwt.t
|
||||||
|
|
||||||
val blocks_from_cycle:
|
val blocks_from_cycle:
|
||||||
#Proto_alpha.rpc_context ->
|
#Proto_alpha.rpc_context ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
Cycle.t ->
|
Cycle.t ->
|
||||||
Block_hash.t list tzresult Lwt.t
|
Block_hash.t list tzresult Lwt.t
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
(* *)
|
(* *)
|
||||||
(**************************************************************************)
|
(**************************************************************************)
|
||||||
|
|
||||||
let run (cctxt : #Proto_alpha.full) ?max_priority ~delay ?min_date delegates ~endorsement ~denunciation ~baking =
|
let run (cctxt : #Proto_alpha.full) ?max_priority ~delay delegates ~endorsement ~denunciation ~baking =
|
||||||
begin
|
begin
|
||||||
match delegates with
|
match delegates with
|
||||||
| [] ->
|
| [] ->
|
||||||
@ -23,8 +23,7 @@ let run (cctxt : #Proto_alpha.full) ?max_priority ~delay ?min_date delegates ~en
|
|||||||
(* TODO really detach... *)
|
(* TODO really detach... *)
|
||||||
let endorsement =
|
let endorsement =
|
||||||
if endorsement then
|
if endorsement then
|
||||||
Client_baking_blocks.monitor
|
Client_baking_blocks.monitor_heads cctxt `Main >>=? fun block_stream ->
|
||||||
cctxt ?min_date ~min_heads:1 () >>=? fun block_stream ->
|
|
||||||
Client_baking_endorsement.create cctxt ~delay delegates block_stream >>= fun () ->
|
Client_baking_endorsement.create cctxt ~delay delegates block_stream >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
else
|
else
|
||||||
@ -41,12 +40,10 @@ let run (cctxt : #Proto_alpha.full) ?max_priority ~delay ?min_date delegates ~en
|
|||||||
in
|
in
|
||||||
let forge =
|
let forge =
|
||||||
if baking then begin
|
if baking then begin
|
||||||
Client_baking_blocks.monitor
|
Client_baking_blocks.monitor_heads
|
||||||
cctxt ?min_date ~min_heads:1 () >>=? fun block_stream ->
|
cctxt `Main >>=? fun block_stream ->
|
||||||
Client_baking_operations.monitor_endorsement
|
|
||||||
cctxt >>=? fun endorsement_stream ->
|
|
||||||
Client_baking_forge.create cctxt
|
Client_baking_forge.create cctxt
|
||||||
?max_priority delegates block_stream endorsement_stream >>=? fun () ->
|
?max_priority delegates block_stream >>=? fun () ->
|
||||||
return ()
|
return ()
|
||||||
end else
|
end else
|
||||||
return ()
|
return ()
|
||||||
|
@ -14,7 +14,6 @@ val run:
|
|||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
?max_priority: int ->
|
?max_priority: int ->
|
||||||
delay: int ->
|
delay: int ->
|
||||||
?min_date: Time.t ->
|
|
||||||
public_key_hash list ->
|
public_key_hash list ->
|
||||||
endorsement:bool ->
|
endorsement:bool ->
|
||||||
denunciation:bool ->
|
denunciation:bool ->
|
||||||
|
@ -82,33 +82,35 @@ end = struct
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let get_signing_slots cctxt ?max_priority block delegate level =
|
let get_signing_slots cctxt ?max_priority ?(chain = `Main) block delegate level =
|
||||||
Alpha_services.Delegate.Endorser.rights_for_delegate cctxt
|
Alpha_services.Delegate.Endorser.rights_for_delegate cctxt
|
||||||
?max_priority ~first_level:level ~last_level:level
|
?max_priority ~first_level:level ~last_level:level
|
||||||
block delegate >>=? fun possibilities ->
|
(chain, block) delegate >>=? fun possibilities ->
|
||||||
let slots =
|
let slots =
|
||||||
List.map (fun (_,slot) -> slot)
|
List.map (fun (_,slot) -> slot)
|
||||||
@@ List.filter (fun (l, _) -> l = level) possibilities in
|
@@ List.filter (fun (l, _) -> l = level) possibilities in
|
||||||
return slots
|
return slots
|
||||||
|
|
||||||
let inject_endorsement (cctxt : #Proto_alpha.full)
|
let inject_endorsement
|
||||||
block level ?async
|
(cctxt : #Proto_alpha.full)
|
||||||
|
?(chain = `Main) block level ?async
|
||||||
src_sk slots =
|
src_sk slots =
|
||||||
Block_services.info cctxt block >>=? fun bi ->
|
Chain_services.chain_id cctxt ~chain () >>=? fun chain_id ->
|
||||||
|
Block_services.hash cctxt ~chain ~block () >>=? fun hash ->
|
||||||
Alpha_services.Forge.Consensus.endorsement cctxt
|
Alpha_services.Forge.Consensus.endorsement cctxt
|
||||||
block
|
(chain, block)
|
||||||
~branch:bi.hash
|
~branch:hash
|
||||||
~block:bi.hash
|
~block:hash
|
||||||
~level:level
|
~level:level
|
||||||
~slots
|
~slots
|
||||||
() >>=? fun bytes ->
|
() >>=? fun bytes ->
|
||||||
Client_keys.append
|
Client_keys.append
|
||||||
src_sk ~watermark:Endorsement bytes >>=? fun signed_bytes ->
|
src_sk ~watermark:Endorsement bytes >>=? fun signed_bytes ->
|
||||||
Shell_services.inject_operation
|
Shell_services.inject_operation
|
||||||
cctxt ?async ~chain_id:bi.chain_id signed_bytes >>=? fun oph ->
|
cctxt ?async ~chain_id signed_bytes >>=? fun oph ->
|
||||||
iter_s
|
iter_s
|
||||||
(fun slot ->
|
(fun slot ->
|
||||||
State.record_endorsement cctxt level bi.hash slot oph)
|
State.record_endorsement cctxt level hash slot oph)
|
||||||
slots >>=? fun () ->
|
slots >>=? fun () ->
|
||||||
return oph
|
return oph
|
||||||
|
|
||||||
@ -127,22 +129,22 @@ let check_endorsement cctxt level slot =
|
|||||||
|
|
||||||
|
|
||||||
let forge_endorsement (cctxt : #Proto_alpha.full)
|
let forge_endorsement (cctxt : #Proto_alpha.full)
|
||||||
block
|
?(chain = `Main) block
|
||||||
~src_sk ?slots ?max_priority src_pk =
|
~src_sk ?slots ?max_priority src_pk =
|
||||||
let src_pkh = Signature.Public_key.hash src_pk in
|
let src_pkh = Signature.Public_key.hash src_pk in
|
||||||
Alpha_services.Context.level cctxt block >>=? fun { level } ->
|
Alpha_services.Context.level cctxt (chain, block) >>=? fun { level } ->
|
||||||
begin
|
begin
|
||||||
match slots with
|
match slots with
|
||||||
| Some slots -> return slots
|
| Some slots -> return slots
|
||||||
| None ->
|
| None ->
|
||||||
get_signing_slots
|
get_signing_slots
|
||||||
cctxt ?max_priority block src_pkh level >>=? function
|
cctxt ?max_priority ~chain block src_pkh level >>=? function
|
||||||
| [] -> cctxt#error "No slot found at level %a" Raw_level.pp level
|
| [] -> cctxt#error "No slot found at level %a" Raw_level.pp level
|
||||||
| slots -> return slots
|
| slots -> return slots
|
||||||
end >>=? fun slots ->
|
end >>=? fun slots ->
|
||||||
iter_s (check_endorsement cctxt level) slots >>=? fun () ->
|
iter_s (check_endorsement cctxt level) slots >>=? fun () ->
|
||||||
inject_endorsement cctxt
|
inject_endorsement cctxt
|
||||||
block level
|
~chain block level
|
||||||
src_sk slots
|
src_sk slots
|
||||||
|
|
||||||
|
|
||||||
@ -188,7 +190,7 @@ let drop_old_endorsement ~before state =
|
|||||||
(fun { block } -> Fitness.compare before block.fitness <= 0)
|
(fun { block } -> Fitness.compare before block.fitness <= 0)
|
||||||
state.to_endorse
|
state.to_endorse
|
||||||
|
|
||||||
let schedule_endorsements (cctxt : #Proto_alpha.full) state bis =
|
let schedule_endorsements (cctxt : #Proto_alpha.full) state bi =
|
||||||
let may_endorse (block: Client_baking_blocks.block_info) delegate time =
|
let may_endorse (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 ->
|
||||||
lwt_log_info "May endorse block %a for %s"
|
lwt_log_info "May endorse block %a for %s"
|
||||||
@ -253,9 +255,7 @@ let schedule_endorsements (cctxt : #Proto_alpha.full) state bis =
|
|||||||
get_delegates cctxt state >>=? fun delegates ->
|
get_delegates cctxt state >>=? fun delegates ->
|
||||||
iter_p
|
iter_p
|
||||||
(fun delegate ->
|
(fun delegate ->
|
||||||
iter_p
|
may_endorse bi delegate time)
|
||||||
(fun bi -> may_endorse bi delegate time)
|
|
||||||
bis)
|
|
||||||
delegates
|
delegates
|
||||||
|
|
||||||
let schedule_endorsements (cctxt : #Proto_alpha.full) state bis =
|
let schedule_endorsements (cctxt : #Proto_alpha.full) state bis =
|
||||||
@ -316,9 +316,9 @@ let compute_timeout state =
|
|||||||
let create (cctxt : #Proto_alpha.full) ~delay contracts block_stream =
|
let create (cctxt : #Proto_alpha.full) ~delay contracts block_stream =
|
||||||
lwt_log_info "Starting endorsement daemon" >>= fun () ->
|
lwt_log_info "Starting endorsement daemon" >>= fun () ->
|
||||||
Lwt_stream.get block_stream >>= function
|
Lwt_stream.get block_stream >>= function
|
||||||
| None | Some (Ok []) | Some (Error _) ->
|
| None | Some (Error _) ->
|
||||||
cctxt#error "Can't fetch the current block head."
|
cctxt#error "Can't fetch the current block head."
|
||||||
| Some (Ok (bi :: _ as initial_heads)) ->
|
| Some (Ok head) ->
|
||||||
let last_get_block = ref None in
|
let last_get_block = ref None in
|
||||||
let get_block () =
|
let get_block () =
|
||||||
match !last_get_block with
|
match !last_get_block with
|
||||||
@ -327,17 +327,17 @@ let create (cctxt : #Proto_alpha.full) ~delay contracts block_stream =
|
|||||||
last_get_block := Some t ;
|
last_get_block := Some t ;
|
||||||
t
|
t
|
||||||
| Some t -> t in
|
| Some t -> t in
|
||||||
let state = create_state contracts bi (Int64.of_int delay) in
|
let state = create_state contracts head (Int64.of_int delay) in
|
||||||
let rec worker_loop () =
|
let rec worker_loop () =
|
||||||
let timeout = compute_timeout state in
|
let timeout = compute_timeout state in
|
||||||
Lwt.choose [ (timeout >|= fun () -> `Timeout) ;
|
Lwt.choose [ (timeout >|= fun () -> `Timeout) ;
|
||||||
(get_block () >|= fun b -> `Hash b) ] >>= function
|
(get_block () >|= fun b -> `Hash b) ] >>= function
|
||||||
| `Hash (None | Some (Error _)) ->
|
| `Hash (None | Some (Error _)) ->
|
||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
| `Hash (Some (Ok bis)) ->
|
| `Hash (Some (Ok bi)) ->
|
||||||
Lwt.cancel timeout ;
|
Lwt.cancel timeout ;
|
||||||
last_get_block := None ;
|
last_get_block := None ;
|
||||||
schedule_endorsements cctxt state bis >>= fun () ->
|
schedule_endorsements cctxt state bi >>= fun () ->
|
||||||
worker_loop ()
|
worker_loop ()
|
||||||
| `Timeout ->
|
| `Timeout ->
|
||||||
begin
|
begin
|
||||||
@ -350,5 +350,5 @@ let create (cctxt : #Proto_alpha.full) ~delay contracts block_stream =
|
|||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
end >>= fun () ->
|
end >>= fun () ->
|
||||||
worker_loop () in
|
worker_loop () in
|
||||||
schedule_endorsements cctxt state initial_heads >>= fun () ->
|
schedule_endorsements cctxt state head >>= fun () ->
|
||||||
worker_loop ()
|
worker_loop ()
|
||||||
|
@ -12,6 +12,7 @@ open Alpha_context
|
|||||||
|
|
||||||
val forge_endorsement:
|
val forge_endorsement:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
src_sk:Client_keys.sk_uri ->
|
src_sk:Client_keys.sk_uri ->
|
||||||
?slots:int list ->
|
?slots:int list ->
|
||||||
@ -23,4 +24,4 @@ val create :
|
|||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
delay:int ->
|
delay:int ->
|
||||||
public_key_hash list ->
|
public_key_hash list ->
|
||||||
Client_baking_blocks.block_info list tzresult Lwt_stream.t -> unit Lwt.t
|
Client_baking_blocks.block_info tzresult Lwt_stream.t -> unit Lwt.t
|
||||||
|
@ -22,9 +22,10 @@ let generate_seed_nonce () =
|
|||||||
| Ok nonce -> nonce
|
| Ok nonce -> nonce
|
||||||
|
|
||||||
let forge_block_header
|
let forge_block_header
|
||||||
(cctxt : #Proto_alpha.full) block delegate_sk shell priority seed_nonce_hash =
|
(cctxt : #Proto_alpha.full)
|
||||||
|
?(chain = `Main) block delegate_sk shell priority seed_nonce_hash =
|
||||||
Alpha_services.Constants.proof_of_work_threshold
|
Alpha_services.Constants.proof_of_work_threshold
|
||||||
cctxt block >>=? fun stamp_threshold ->
|
cctxt (chain, block) >>=? fun stamp_threshold ->
|
||||||
let rec loop () =
|
let rec loop () =
|
||||||
let proof_of_work_nonce = generate_proof_of_work_nonce () in
|
let proof_of_work_nonce = generate_proof_of_work_nonce () in
|
||||||
let contents =
|
let contents =
|
||||||
@ -44,11 +45,11 @@ let empty_proof_of_work_nonce =
|
|||||||
(String.make Constants_repr.proof_of_work_nonce_size '\000')
|
(String.make Constants_repr.proof_of_work_nonce_size '\000')
|
||||||
|
|
||||||
let forge_faked_protocol_data ~priority ~seed_nonce_hash =
|
let forge_faked_protocol_data ~priority ~seed_nonce_hash =
|
||||||
Data_encoding.Binary.to_bytes_exn
|
Alpha_context.Block_header.{
|
||||||
Alpha_context.Block_header.protocol_data_encoding
|
contents = { priority ; seed_nonce_hash ;
|
||||||
{ contents = { priority ; seed_nonce_hash ;
|
|
||||||
proof_of_work_nonce = empty_proof_of_work_nonce } ;
|
proof_of_work_nonce = empty_proof_of_work_nonce } ;
|
||||||
signature = Signature.zero }
|
signature = Signature.zero
|
||||||
|
}
|
||||||
|
|
||||||
let assert_valid_operations_hash shell_header operations =
|
let assert_valid_operations_hash shell_header operations =
|
||||||
let operations_hash =
|
let operations_hash =
|
||||||
@ -64,14 +65,15 @@ let assert_valid_operations_hash shell_header operations =
|
|||||||
inconsistent header.")
|
inconsistent header.")
|
||||||
|
|
||||||
let inject_block cctxt
|
let inject_block cctxt
|
||||||
?force ?chain_id
|
?force ?(chain = `Main)
|
||||||
~shell_header ~priority ?seed_nonce_hash ~src_sk operations =
|
~shell_header ~priority ?seed_nonce_hash ~src_sk operations =
|
||||||
assert_valid_operations_hash shell_header operations >>=? fun () ->
|
assert_valid_operations_hash shell_header operations >>=? fun () ->
|
||||||
let block = `Hash (shell_header.Tezos_base.Block_header.predecessor, 0) in
|
let block = `Hash (shell_header.Tezos_base.Block_header.predecessor, 0) in
|
||||||
forge_block_header cctxt block
|
forge_block_header cctxt ~chain block
|
||||||
src_sk shell_header priority seed_nonce_hash >>=? fun signed_header ->
|
src_sk shell_header priority seed_nonce_hash >>=? fun signed_header ->
|
||||||
|
Chain_services.chain_id cctxt ~chain () >>=? fun chain_id ->
|
||||||
Shell_services.inject_block cctxt
|
Shell_services.inject_block cctxt
|
||||||
?force ?chain_id signed_header operations >>=? fun block_hash ->
|
?force ~chain_id signed_header operations >>=? fun block_hash ->
|
||||||
return block_hash
|
return block_hash
|
||||||
|
|
||||||
type error +=
|
type error +=
|
||||||
@ -97,21 +99,33 @@ let () =
|
|||||||
| _ -> None)
|
| _ -> None)
|
||||||
(fun (hash, err) -> Failed_to_preapply (hash, err))
|
(fun (hash, err) -> Failed_to_preapply (hash, err))
|
||||||
|
|
||||||
let classify_operations (ops: Operation.raw list) =
|
let classify_operations (ops: Operation.t list) =
|
||||||
let t = Array.make (List.length Proto_alpha.Main.validation_passes) [] in
|
let t = Array.make (List.length Proto_alpha.Main.validation_passes) [] in
|
||||||
List.iter
|
List.iter
|
||||||
(fun (op: Operation.raw) ->
|
(fun (op: Operation.t) ->
|
||||||
match Data_encoding.Binary.of_bytes Operation.protocol_data_encoding op.proto with
|
|
||||||
| Some o ->
|
|
||||||
List.iter
|
List.iter
|
||||||
(fun pass -> t.(pass) <- op :: t.(pass))
|
(fun pass -> t.(pass) <- op :: t.(pass))
|
||||||
(Proto_alpha.Main.acceptable_passes
|
(Proto_alpha.Main.acceptable_passes op))
|
||||||
{ shell = op.shell ; protocol_data = o })
|
|
||||||
| None -> ())
|
|
||||||
ops ;
|
ops ;
|
||||||
Array.fold_right (fun ops acc -> List.rev ops :: acc) t []
|
Array.fold_right (fun ops acc -> List.rev ops :: acc) t []
|
||||||
|
|
||||||
let forge_block cctxt block
|
let parse (op : Operation.raw) : Operation.t = {
|
||||||
|
shell = op.shell ;
|
||||||
|
protocol_data =
|
||||||
|
Data_encoding.Binary.of_bytes_exn
|
||||||
|
Alpha_context.Operation.protocol_data_encoding
|
||||||
|
op.proto
|
||||||
|
}
|
||||||
|
|
||||||
|
let forge (op : Operation.t) : Operation.raw = {
|
||||||
|
shell = op.shell ;
|
||||||
|
proto =
|
||||||
|
Data_encoding.Binary.to_bytes_exn
|
||||||
|
Alpha_context.Operation.protocol_data_encoding
|
||||||
|
op.protocol_data
|
||||||
|
}
|
||||||
|
|
||||||
|
let forge_block cctxt ?(chain = `Main) block
|
||||||
?force
|
?force
|
||||||
?operations ?(best_effort = operations = None) ?(sort = best_effort)
|
?operations ?(best_effort = operations = None) ?(sort = best_effort)
|
||||||
?timestamp
|
?timestamp
|
||||||
@ -120,9 +134,10 @@ let forge_block cctxt block
|
|||||||
begin
|
begin
|
||||||
match operations with
|
match operations with
|
||||||
| None ->
|
| None ->
|
||||||
Mempool_services.pending_operations
|
Chain_services.Mempool.pending_operations
|
||||||
cctxt >>=? fun (ops, pendings) ->
|
cctxt ~chain () >>=? fun (ops, pendings) ->
|
||||||
let ops =
|
let ops =
|
||||||
|
List.map parse @@
|
||||||
List.map snd @@
|
List.map snd @@
|
||||||
Operation_hash.Map.bindings @@
|
Operation_hash.Map.bindings @@
|
||||||
Operation_hash.Map.fold
|
Operation_hash.Map.fold
|
||||||
@ -137,20 +152,20 @@ let forge_block cctxt block
|
|||||||
match priority with
|
match priority with
|
||||||
| `Set priority -> begin
|
| `Set priority -> begin
|
||||||
Alpha_services.Helpers.minimal_time
|
Alpha_services.Helpers.minimal_time
|
||||||
cctxt block ~priority >>=? fun time ->
|
cctxt (chain, block) ~priority >>=? fun time ->
|
||||||
return (priority, time)
|
return (priority, time)
|
||||||
end
|
end
|
||||||
| `Auto (src_pkh, max_priority, free_baking) ->
|
| `Auto (src_pkh, max_priority, free_baking) ->
|
||||||
Alpha_services.Context.next_level cctxt block >>=? fun { level } ->
|
Alpha_services.Context.next_level cctxt (chain, block) >>=? fun { level } ->
|
||||||
Alpha_services.Delegate.Baker.rights_for_delegate cctxt
|
Alpha_services.Delegate.Baker.rights_for_delegate cctxt
|
||||||
?max_priority
|
?max_priority
|
||||||
~first_level:level
|
~first_level:level
|
||||||
~last_level:level
|
~last_level:level
|
||||||
block src_pkh >>=? fun possibilities ->
|
(chain, block) src_pkh >>=? fun possibilities ->
|
||||||
try
|
try
|
||||||
begin
|
begin
|
||||||
if free_baking then
|
if free_baking then
|
||||||
Alpha_services.Constants.first_free_baking_slot cctxt block
|
Alpha_services.Constants.first_free_baking_slot cctxt (chain, block)
|
||||||
else
|
else
|
||||||
return 0
|
return 0
|
||||||
end >>=? fun min_prio ->
|
end >>=? fun min_prio ->
|
||||||
@ -177,10 +192,13 @@ let forge_block cctxt block
|
|||||||
let request = List.length operations in
|
let request = List.length operations in
|
||||||
let protocol_data = forge_faked_protocol_data ~priority ~seed_nonce_hash in
|
let protocol_data = forge_faked_protocol_data ~priority ~seed_nonce_hash in
|
||||||
let operations = classify_operations operations in
|
let operations = classify_operations operations in
|
||||||
Block_services.preapply
|
Block_services.Helpers.preapply
|
||||||
cctxt block ~timestamp ~sort ~protocol_data operations >>=?
|
cctxt ~block ~timestamp ~sort ~protocol_data operations >>=?
|
||||||
fun { operations = result ; shell_header } ->
|
fun (shell_header, result) ->
|
||||||
let valid = List.fold_left (fun acc r -> acc + List.length r.Preapply_result.applied) 0 result in
|
let valid =
|
||||||
|
List.fold_left
|
||||||
|
(fun acc r -> acc + List.length r.Preapply_result.applied)
|
||||||
|
0 result in
|
||||||
lwt_log_info "Found %d valid operations (%d refused) for timestamp %a"
|
lwt_log_info "Found %d valid operations (%d refused) for timestamp %a"
|
||||||
valid (request - valid)
|
valid (request - valid)
|
||||||
Time.pp_hum timestamp >>= fun () ->
|
Time.pp_hum timestamp >>= fun () ->
|
||||||
@ -194,11 +212,12 @@ let forge_block cctxt block
|
|||||||
result
|
result
|
||||||
then
|
then
|
||||||
let operations =
|
let operations =
|
||||||
if not best_effort then operations
|
if not best_effort then
|
||||||
else List.map (fun l -> List.map snd l.Preapply_result.applied) result in
|
List.map (List.map forge) operations
|
||||||
Block_services.info cctxt block >>=? fun {chain_id} ->
|
else
|
||||||
|
List.map (fun l -> List.map snd l.Preapply_result.applied) result in
|
||||||
inject_block cctxt
|
inject_block cctxt
|
||||||
?force ~chain_id ~shell_header ~priority ?seed_nonce_hash ~src_sk
|
?force ~chain ~shell_header ~priority ?seed_nonce_hash ~src_sk
|
||||||
operations
|
operations
|
||||||
else
|
else
|
||||||
let result =
|
let result =
|
||||||
@ -226,6 +245,7 @@ let forge_block cctxt block
|
|||||||
Lwt.return_error @@
|
Lwt.return_error @@
|
||||||
List.filter_map
|
List.filter_map
|
||||||
(fun op ->
|
(fun op ->
|
||||||
|
let op = forge op in
|
||||||
let h = Tezos_base.Operation.hash op in
|
let h = Tezos_base.Operation.hash op in
|
||||||
try Some (Failed_to_preapply
|
try Some (Failed_to_preapply
|
||||||
(op, snd @@ Operation_hash.Map.find h result.refused))
|
(op, snd @@ Operation_hash.Map.find h result.refused))
|
||||||
@ -302,6 +322,7 @@ end
|
|||||||
|
|
||||||
let get_baking_slot cctxt
|
let get_baking_slot cctxt
|
||||||
?max_priority (bi: Client_baking_blocks.block_info) delegates =
|
?max_priority (bi: Client_baking_blocks.block_info) delegates =
|
||||||
|
let chain = `Hash bi.chain_id in
|
||||||
let block = `Hash (bi.hash, 0) in
|
let block = `Hash (bi.hash, 0) in
|
||||||
let level = Raw_level.succ bi.level.level in
|
let level = Raw_level.succ bi.level.level in
|
||||||
Lwt_list.filter_map_p
|
Lwt_list.filter_map_p
|
||||||
@ -310,7 +331,7 @@ let get_baking_slot cctxt
|
|||||||
?max_priority
|
?max_priority
|
||||||
~first_level:level
|
~first_level:level
|
||||||
~last_level:level
|
~last_level:level
|
||||||
block delegate >>= function
|
(chain, block) delegate >>= function
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
log_error "Error while fetching baking possibilities:\n%a"
|
log_error "Error while fetching baking possibilities:\n%a"
|
||||||
pp_print_error errs ;
|
pp_print_error errs ;
|
||||||
@ -370,8 +391,9 @@ let compute_timeout { future_slots } =
|
|||||||
else
|
else
|
||||||
Lwt_unix.sleep (Int64.to_float delay)
|
Lwt_unix.sleep (Int64.to_float delay)
|
||||||
|
|
||||||
let get_unrevealed_nonces (cctxt : #Proto_alpha.full) ?(force = false) block =
|
let get_unrevealed_nonces
|
||||||
Alpha_services.Context.next_level cctxt block >>=? fun level ->
|
(cctxt : #Proto_alpha.full) ?(force = false) ?(chain = `Main) block =
|
||||||
|
Alpha_services.Context.next_level cctxt (chain, block) >>=? fun level ->
|
||||||
let cur_cycle = level.cycle in
|
let cur_cycle = level.cycle in
|
||||||
match Cycle.pred cur_cycle with
|
match Cycle.pred cur_cycle with
|
||||||
| None -> return []
|
| None -> return []
|
||||||
@ -383,12 +405,12 @@ let get_unrevealed_nonces (cctxt : #Proto_alpha.full) ?(force = false) block =
|
|||||||
| None -> return None
|
| None -> return None
|
||||||
| Some nonce ->
|
| Some nonce ->
|
||||||
Alpha_services.Context.level
|
Alpha_services.Context.level
|
||||||
cctxt (`Hash (hash, 0)) >>=? fun level ->
|
cctxt (chain, `Hash (hash, 0)) >>=? fun level ->
|
||||||
if force then
|
if force then
|
||||||
return (Some (hash, (level.level, nonce)))
|
return (Some (hash, (level.level, nonce)))
|
||||||
else
|
else
|
||||||
Alpha_services.Nonce.get
|
Alpha_services.Nonce.get
|
||||||
cctxt block level.level >>=? function
|
cctxt (chain, block) level.level >>=? function
|
||||||
| Missing nonce_hash
|
| Missing nonce_hash
|
||||||
when Nonce.check_hash nonce nonce_hash ->
|
when Nonce.check_hash nonce nonce_hash ->
|
||||||
cctxt#warning "Found nonce for %a (level: %a)@."
|
cctxt#warning "Found nonce for %a (level: %a)@."
|
||||||
@ -455,8 +477,8 @@ let pop_baking_slots state =
|
|||||||
state.future_slots <- future_slots ;
|
state.future_slots <- future_slots ;
|
||||||
slots
|
slots
|
||||||
|
|
||||||
let insert_blocks cctxt ?max_priority state bis =
|
let insert_blocks cctxt ?max_priority state bi =
|
||||||
iter_s (insert_block cctxt ?max_priority state) bis >>= function
|
insert_block cctxt ?max_priority state bi >>= function
|
||||||
| Ok () ->
|
| Ok () ->
|
||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
| Error err ->
|
| Error err ->
|
||||||
@ -468,8 +490,9 @@ let bake (cctxt : #Proto_alpha.full) state =
|
|||||||
let seed_nonce_hash = Nonce.hash seed_nonce in
|
let seed_nonce_hash = Nonce.hash seed_nonce in
|
||||||
filter_map_s
|
filter_map_s
|
||||||
(fun (timestamp, (bi, priority, delegate)) ->
|
(fun (timestamp, (bi, priority, delegate)) ->
|
||||||
let block = `Hash (bi.Client_baking_blocks.hash, 0) in
|
let chain = `Hash bi.Client_baking_blocks.chain_id in
|
||||||
Alpha_services.Context.next_level cctxt block >>=? fun next_level ->
|
let block = `Hash (bi.hash, 0) in
|
||||||
|
Alpha_services.Context.next_level cctxt (chain, block) >>=? fun next_level ->
|
||||||
let timestamp =
|
let timestamp =
|
||||||
if Block_hash.equal bi.Client_baking_blocks.hash state.genesis then
|
if Block_hash.equal bi.Client_baking_blocks.hash state.genesis then
|
||||||
Time.now ()
|
Time.now ()
|
||||||
@ -479,9 +502,10 @@ let bake (cctxt : #Proto_alpha.full) state =
|
|||||||
lwt_debug "Try baking after %a (slot %d) for %s (%a)"
|
lwt_debug "Try baking after %a (slot %d) for %s (%a)"
|
||||||
Block_hash.pp_short bi.hash
|
Block_hash.pp_short bi.hash
|
||||||
priority name Time.pp_hum timestamp >>= fun () ->
|
priority name Time.pp_hum timestamp >>= fun () ->
|
||||||
Mempool_services.pending_operations cctxt
|
Chain_services.Mempool.pending_operations
|
||||||
>>=? fun (res, ops) ->
|
cctxt ~chain () >>=? fun (res, ops) ->
|
||||||
let operations =
|
let operations =
|
||||||
|
List.map parse @@
|
||||||
List.map snd @@
|
List.map snd @@
|
||||||
Operation_hash.Map.bindings @@
|
Operation_hash.Map.bindings @@
|
||||||
Operation_hash.Map.(fold add)
|
Operation_hash.Map.(fold add)
|
||||||
@ -495,14 +519,14 @@ let bake (cctxt : #Proto_alpha.full) state =
|
|||||||
let protocol_data =
|
let protocol_data =
|
||||||
forge_faked_protocol_data ~priority ~seed_nonce_hash in
|
forge_faked_protocol_data ~priority ~seed_nonce_hash in
|
||||||
let operations = classify_operations operations in
|
let operations = classify_operations operations in
|
||||||
Block_services.preapply cctxt block
|
Block_services.Helpers.preapply cctxt ~chain ~block
|
||||||
~timestamp ~sort:true ~protocol_data operations >>= function
|
~timestamp ~sort:true ~protocol_data operations >>= function
|
||||||
| Error errs ->
|
| Error errs ->
|
||||||
lwt_log_error "Error while prevalidating operations:@\n%a"
|
lwt_log_error "Error while prevalidating operations:@\n%a"
|
||||||
pp_print_error
|
pp_print_error
|
||||||
errs >>= fun () ->
|
errs >>= fun () ->
|
||||||
return None
|
return None
|
||||||
| Ok { operations ; shell_header } ->
|
| Ok (shell_header, operations) ->
|
||||||
lwt_debug
|
lwt_debug
|
||||||
"Computed candidate block after %a (slot %d): %a/%d fitness: %a"
|
"Computed candidate block after %a (slot %d): %a/%d fitness: %a"
|
||||||
Block_hash.pp_short bi.hash priority
|
Block_hash.pp_short bi.hash priority
|
||||||
@ -538,8 +562,9 @@ let bake (cctxt : #Proto_alpha.full) state =
|
|||||||
Block_hash.pp_short bi.hash priority
|
Block_hash.pp_short bi.hash priority
|
||||||
Fitness.pp shell_header.fitness >>= fun () ->
|
Fitness.pp shell_header.fitness >>= fun () ->
|
||||||
Client_keys.get_key cctxt delegate >>=? fun (_,_,src_sk) ->
|
Client_keys.get_key cctxt delegate >>=? fun (_,_,src_sk) ->
|
||||||
|
let chain = `Hash bi.Client_baking_blocks.chain_id in
|
||||||
inject_block cctxt
|
inject_block cctxt
|
||||||
~force:true ~chain_id:bi.chain_id
|
~force:true ~chain
|
||||||
~shell_header ~priority ?seed_nonce_hash ~src_sk
|
~shell_header ~priority ?seed_nonce_hash ~src_sk
|
||||||
operations
|
operations
|
||||||
|> trace_exn (Failure "Error while injecting block") >>=? fun block_hash ->
|
|> trace_exn (Failure "Error while injecting block") >>=? fun block_hash ->
|
||||||
@ -572,14 +597,12 @@ let bake (cctxt : #Proto_alpha.full) state =
|
|||||||
let create
|
let create
|
||||||
(cctxt : #Proto_alpha.full) ?max_priority delegates
|
(cctxt : #Proto_alpha.full) ?max_priority delegates
|
||||||
(block_stream:
|
(block_stream:
|
||||||
Client_baking_blocks.block_info list tzresult Lwt_stream.t)
|
Client_baking_blocks.block_info tzresult Lwt_stream.t) =
|
||||||
(endorsement_stream:
|
|
||||||
Client_baking_operations.valid_endorsement tzresult Lwt_stream.t) =
|
|
||||||
Lwt_stream.get block_stream >>= function
|
Lwt_stream.get block_stream >>= function
|
||||||
| None | Some (Ok [] | Error _) ->
|
| None | Some (Error _) ->
|
||||||
cctxt#error "Can't fetch the current block head."
|
cctxt#error "Can't fetch the current block head."
|
||||||
| Some (Ok (bi :: _ as initial_heads)) ->
|
| Some (Ok bi) ->
|
||||||
Block_services.hash cctxt `Genesis >>=? fun genesis_hash ->
|
Block_services.hash cctxt ~block:`Genesis () >>=? fun genesis_hash ->
|
||||||
let last_get_block = ref None in
|
let last_get_block = ref None in
|
||||||
let get_block () =
|
let get_block () =
|
||||||
match !last_get_block with
|
match !last_get_block with
|
||||||
@ -588,45 +611,24 @@ let create
|
|||||||
last_get_block := Some t ;
|
last_get_block := Some t ;
|
||||||
t
|
t
|
||||||
| Some t -> t in
|
| Some t -> t in
|
||||||
let last_get_endorsement = ref None in
|
|
||||||
let get_endorsement () =
|
|
||||||
match !last_get_endorsement with
|
|
||||||
| None ->
|
|
||||||
let t = Lwt_stream.get endorsement_stream in
|
|
||||||
last_get_endorsement := Some t ;
|
|
||||||
t
|
|
||||||
| Some t -> t in
|
|
||||||
let state = create_state genesis_hash delegates bi in
|
let state = create_state genesis_hash delegates bi in
|
||||||
insert_blocks cctxt ?max_priority state initial_heads >>= fun () ->
|
insert_blocks cctxt ?max_priority state bi >>= fun () ->
|
||||||
let rec worker_loop () =
|
let rec worker_loop () =
|
||||||
let timeout = compute_timeout state in
|
let timeout = compute_timeout state in
|
||||||
Lwt.choose [ (timeout >|= fun () -> `Timeout) ;
|
Lwt.choose [ (timeout >|= fun () -> `Timeout) ;
|
||||||
(get_block () >|= fun b -> `Hash b) ;
|
(get_block () >|= fun b -> `Hash b) ;
|
||||||
(get_endorsement () >|= fun e -> `Endorsement e) ;
|
|
||||||
] >>= function
|
] >>= function
|
||||||
| `Hash (None | Some (Error _))
|
| `Hash (None | Some (Error _)) ->
|
||||||
| `Endorsement (None | Some (Error _)) ->
|
|
||||||
Lwt.return_unit
|
Lwt.return_unit
|
||||||
| `Hash (Some (Ok bis)) -> begin
|
| `Hash (Some (Ok bi)) -> begin
|
||||||
Lwt.cancel timeout ;
|
Lwt.cancel timeout ;
|
||||||
last_get_block := None ;
|
last_get_block := None ;
|
||||||
lwt_debug
|
lwt_debug
|
||||||
"@[<hov 2>Discoverer blocks:@ %a@]"
|
"Discoverered block: %a"
|
||||||
(Format.pp_print_list
|
Block_hash.pp_short bi.Client_baking_blocks.hash >>= fun () ->
|
||||||
(fun ppf bi ->
|
insert_blocks cctxt ?max_priority state bi >>= fun () ->
|
||||||
Block_hash.pp_short ppf bi.Client_baking_blocks.hash))
|
|
||||||
bis
|
|
||||||
>>= fun () ->
|
|
||||||
insert_blocks cctxt ?max_priority state bis >>= fun () ->
|
|
||||||
worker_loop ()
|
worker_loop ()
|
||||||
end
|
end
|
||||||
| `Endorsement (Some (Ok e)) ->
|
|
||||||
Lwt.cancel timeout ;
|
|
||||||
last_get_endorsement := None ;
|
|
||||||
Client_keys.Public_key_hash.name cctxt
|
|
||||||
e.Client_baking_operations.source >>= fun _source ->
|
|
||||||
(* TODO *)
|
|
||||||
worker_loop ()
|
|
||||||
| `Timeout ->
|
| `Timeout ->
|
||||||
lwt_debug "Waking up for baking..." >>= fun () ->
|
lwt_debug "Waking up for baking..." >>= fun () ->
|
||||||
begin
|
begin
|
||||||
|
@ -19,7 +19,7 @@ val generate_seed_nonce: unit -> Nonce.t
|
|||||||
val inject_block:
|
val inject_block:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
?chain_id:Chain_id.t ->
|
?chain:Chain_services.chain ->
|
||||||
shell_header:Block_header.shell_header ->
|
shell_header:Block_header.shell_header ->
|
||||||
priority:int ->
|
priority:int ->
|
||||||
?seed_nonce_hash:Nonce_hash.t ->
|
?seed_nonce_hash:Nonce_hash.t ->
|
||||||
@ -37,9 +37,10 @@ type error +=
|
|||||||
|
|
||||||
val forge_block:
|
val forge_block:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
?operations:Operation.raw list ->
|
?operations:Operation.t list ->
|
||||||
?best_effort:bool ->
|
?best_effort:bool ->
|
||||||
?sort:bool ->
|
?sort:bool ->
|
||||||
?timestamp:Time.t ->
|
?timestamp:Time.t ->
|
||||||
@ -79,12 +80,12 @@ val create:
|
|||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
?max_priority: int ->
|
?max_priority: int ->
|
||||||
public_key_hash list ->
|
public_key_hash list ->
|
||||||
Client_baking_blocks.block_info list tzresult Lwt_stream.t ->
|
Client_baking_blocks.block_info tzresult Lwt_stream.t ->
|
||||||
Client_baking_operations.valid_endorsement tzresult Lwt_stream.t ->
|
|
||||||
unit tzresult Lwt.t
|
unit tzresult Lwt.t
|
||||||
|
|
||||||
val get_unrevealed_nonces:
|
val get_unrevealed_nonces:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
(Block_hash.t * (Raw_level.t * Nonce.t)) list tzresult Lwt.t
|
(Block_hash.t * (Raw_level.t * Nonce.t)) list tzresult Lwt.t
|
||||||
|
@ -10,7 +10,8 @@
|
|||||||
open Proto_alpha
|
open Proto_alpha
|
||||||
open Alpha_context
|
open Alpha_context
|
||||||
|
|
||||||
let bake_block (cctxt : #Proto_alpha.full) block
|
let bake_block (cctxt : #Proto_alpha.full)
|
||||||
|
?(chain = `Main) block
|
||||||
?force ?max_priority ?(free_baking=false) ?(minimal_timestamp=false)
|
?force ?max_priority ?(free_baking=false) ?(minimal_timestamp=false)
|
||||||
?src_sk delegate =
|
?src_sk delegate =
|
||||||
begin
|
begin
|
||||||
@ -20,7 +21,7 @@ let bake_block (cctxt : #Proto_alpha.full) block
|
|||||||
return src_sk
|
return src_sk
|
||||||
| Some sk -> return sk
|
| Some sk -> return sk
|
||||||
end >>=? fun src_sk ->
|
end >>=? fun src_sk ->
|
||||||
Alpha_services.Context.next_level cctxt block >>=? fun level ->
|
Alpha_services.Context.next_level cctxt (chain, block) >>=? fun level ->
|
||||||
let seed_nonce, seed_nonce_hash =
|
let seed_nonce, seed_nonce_hash =
|
||||||
if level.expected_commitment then
|
if level.expected_commitment then
|
||||||
let seed_nonce = Client_baking_forge.generate_seed_nonce () in
|
let seed_nonce = Client_baking_forge.generate_seed_nonce () in
|
||||||
@ -104,6 +105,5 @@ let run_daemon cctxt ?max_priority ~endorsement_delay delegates ~endorsement ~ba
|
|||||||
Client_baking_daemon.run cctxt
|
Client_baking_daemon.run cctxt
|
||||||
?max_priority
|
?max_priority
|
||||||
~delay:endorsement_delay
|
~delay:endorsement_delay
|
||||||
~min_date:((Time.add (Time.now ()) (Int64.neg 1800L)))
|
|
||||||
~endorsement ~baking ~denunciation
|
~endorsement ~baking ~denunciation
|
||||||
delegates
|
delegates
|
||||||
|
@ -13,6 +13,7 @@ open Alpha_context
|
|||||||
(** Mine a block *)
|
(** Mine a block *)
|
||||||
val bake_block:
|
val bake_block:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
?max_priority: int ->
|
?max_priority: int ->
|
||||||
|
@ -10,30 +10,31 @@
|
|||||||
open Proto_alpha
|
open Proto_alpha
|
||||||
open Alpha_context
|
open Alpha_context
|
||||||
|
|
||||||
let inject_seed_nonce_revelation rpc_config block ?async nonces =
|
let inject_seed_nonce_revelation rpc_config ?(chain = `Main) block ?async nonces =
|
||||||
let operations =
|
let operations =
|
||||||
List.map
|
List.map
|
||||||
(fun (level, nonce) ->
|
(fun (level, nonce) ->
|
||||||
Seed_nonce_revelation { level ; nonce }) nonces in
|
Seed_nonce_revelation { level ; nonce }) nonces in
|
||||||
Block_services.info rpc_config block >>=? fun bi ->
|
Chain_services.chain_id rpc_config ~chain () >>=? fun chain_id ->
|
||||||
|
Block_services.hash rpc_config ~chain ~block () >>=? fun branch ->
|
||||||
Alpha_services.Forge.Anonymous.operations rpc_config
|
Alpha_services.Forge.Anonymous.operations rpc_config
|
||||||
block ~branch:bi.hash operations >>=? fun bytes ->
|
(chain, block) ~branch operations >>=? fun bytes ->
|
||||||
Shell_services.inject_operation
|
Shell_services.inject_operation
|
||||||
rpc_config ?async ~chain_id:bi.chain_id
|
rpc_config ?async ~chain_id bytes >>=? fun oph ->
|
||||||
bytes >>=? fun oph ->
|
|
||||||
return oph
|
return oph
|
||||||
|
|
||||||
let forge_seed_nonce_revelation
|
let forge_seed_nonce_revelation
|
||||||
(cctxt: #Proto_alpha.full)
|
(cctxt: #Proto_alpha.full)
|
||||||
|
?(chain = `Main)
|
||||||
block nonces =
|
block nonces =
|
||||||
Block_services.hash cctxt block >>=? fun hash ->
|
Block_services.hash cctxt ~chain ~block () >>=? fun hash ->
|
||||||
match nonces with
|
match nonces with
|
||||||
| [] ->
|
| [] ->
|
||||||
cctxt#message "No nonce to reveal for block %a"
|
cctxt#message "No nonce to reveal for block %a"
|
||||||
Block_hash.pp_short hash >>= fun () ->
|
Block_hash.pp_short hash >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
| _ ->
|
| _ ->
|
||||||
inject_seed_nonce_revelation cctxt block nonces >>=? fun oph ->
|
inject_seed_nonce_revelation cctxt ~chain block nonces >>=? fun oph ->
|
||||||
cctxt#answer
|
cctxt#answer
|
||||||
"Operation successfully injected %d revelation(s) for %a."
|
"Operation successfully injected %d revelation(s) for %a."
|
||||||
(List.length nonces)
|
(List.length nonces)
|
||||||
|
@ -12,6 +12,7 @@ open Alpha_context
|
|||||||
|
|
||||||
val inject_seed_nonce_revelation:
|
val inject_seed_nonce_revelation:
|
||||||
#Proto_alpha.rpc_context ->
|
#Proto_alpha.rpc_context ->
|
||||||
|
?chain: Chain_services.chain ->
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
?async:bool ->
|
?async:bool ->
|
||||||
(Raw_level.t * Nonce.t) list ->
|
(Raw_level.t * Nonce.t) list ->
|
||||||
@ -19,6 +20,7 @@ val inject_seed_nonce_revelation:
|
|||||||
|
|
||||||
val forge_seed_nonce_revelation:
|
val forge_seed_nonce_revelation:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
|
?chain: Chain_services.chain ->
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
(Raw_level.t * Nonce.t) list ->
|
(Raw_level.t * Nonce.t) list ->
|
||||||
unit tzresult Lwt.t
|
unit tzresult Lwt.t
|
||||||
|
@ -150,7 +150,7 @@ let level block =
|
|||||||
Alpha_services.Context.level !rpc_ctxt block
|
Alpha_services.Context.level !rpc_ctxt block
|
||||||
|
|
||||||
let rpc_raw_context block path depth =
|
let rpc_raw_context block path depth =
|
||||||
Block_services.raw_context !rpc_ctxt block path depth
|
Block_services.Context.Raw.read !rpc_ctxt ~block ~depth path
|
||||||
|
|
||||||
module Account = struct
|
module Account = struct
|
||||||
|
|
||||||
@ -254,7 +254,8 @@ module Account = struct
|
|||||||
Tezos_signer_backends.Unencrypted.make_sk account.sk in
|
Tezos_signer_backends.Unencrypted.make_sk account.sk in
|
||||||
Client_proto_context.transfer
|
Client_proto_context.transfer
|
||||||
(new wrap_full (no_write_context !rpc_config ~block))
|
(new wrap_full (no_write_context !rpc_config ~block))
|
||||||
block
|
~chain:`Main
|
||||||
|
~block
|
||||||
~source:account.contract
|
~source:account.contract
|
||||||
~src_pk:account.pk
|
~src_pk:account.pk
|
||||||
~src_sk
|
~src_sk
|
||||||
@ -278,7 +279,8 @@ module Account = struct
|
|||||||
Tezos_signer_backends.Unencrypted.make_sk src.sk in
|
Tezos_signer_backends.Unencrypted.make_sk src.sk in
|
||||||
Client_proto_context.originate_account
|
Client_proto_context.originate_account
|
||||||
(new wrap_full (no_write_context !rpc_config))
|
(new wrap_full (no_write_context !rpc_config))
|
||||||
block
|
~chain:`Main
|
||||||
|
~block
|
||||||
~source:src.contract
|
~source:src.contract
|
||||||
~src_pk:src.pk
|
~src_pk:src.pk
|
||||||
~src_sk
|
~src_sk
|
||||||
@ -299,7 +301,8 @@ module Account = struct
|
|||||||
delegate_opt =
|
delegate_opt =
|
||||||
Client_proto_context.set_delegate
|
Client_proto_context.set_delegate
|
||||||
(new wrap_full (no_write_context ~block !rpc_config))
|
(new wrap_full (no_write_context ~block !rpc_config))
|
||||||
block
|
~chain:`Main
|
||||||
|
~block
|
||||||
~fee
|
~fee
|
||||||
contract
|
contract
|
||||||
~src_pk
|
~src_pk
|
||||||
@ -309,45 +312,55 @@ module Account = struct
|
|||||||
|
|
||||||
let balance ?(block = `Head 0) (account : t) =
|
let balance ?(block = `Head 0) (account : t) =
|
||||||
Alpha_services.Contract.balance !rpc_ctxt
|
Alpha_services.Contract.balance !rpc_ctxt
|
||||||
block account.contract
|
(`Main, block) account.contract
|
||||||
|
|
||||||
(* TODO: gather contract related functions in a Contract module? *)
|
(* TODO: gather contract related functions in a Contract module? *)
|
||||||
let delegate ?(block = `Head 0) (contract : Contract.t) =
|
let delegate ?(block = `Head 0) (contract : Contract.t) =
|
||||||
Alpha_services.Contract.delegate_opt !rpc_ctxt block contract
|
Alpha_services.Contract.delegate_opt !rpc_ctxt (`Main, block) contract
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let sign ?watermark src_sk shell contents =
|
||||||
|
let contents = Sourced_operation contents in
|
||||||
|
let bytes =
|
||||||
|
Data_encoding.Binary.to_bytes_exn
|
||||||
|
Operation.unsigned_encoding
|
||||||
|
(shell, contents) in
|
||||||
|
let signature = Some (Signature.sign ?watermark src_sk bytes) in
|
||||||
|
let protocol_data = { contents ; signature } in
|
||||||
|
return { shell ; protocol_data }
|
||||||
|
|
||||||
module Protocol = struct
|
module Protocol = struct
|
||||||
|
|
||||||
open Account
|
open Account
|
||||||
|
|
||||||
let voting_period_kind ?(block = `Head 0) () =
|
let voting_period_kind ?(block = `Head 0) () =
|
||||||
Alpha_services.Context.voting_period_kind !rpc_ctxt block
|
Alpha_services.Context.voting_period_kind !rpc_ctxt (`Main, block)
|
||||||
|
|
||||||
let proposals ?(block = `Head 0) ~src:({ pkh; sk } : Account.t) proposals =
|
let proposals ?(block = `Head 0) ~src:({ pkh; sk } : Account.t) proposals =
|
||||||
Block_services.info !rpc_ctxt block >>=? fun block_info ->
|
Block_services.hash !rpc_ctxt ~block () >>=? fun hash ->
|
||||||
Alpha_services.Context.next_level !rpc_ctxt block >>=? fun next_level ->
|
Alpha_services.Context.next_level
|
||||||
Alpha_services.Forge.Amendment.proposals !rpc_ctxt block
|
!rpc_ctxt (`Main, block) >>=? fun next_level ->
|
||||||
~branch:block_info.hash
|
let shell = { Tezos_base.Operation.branch = hash } in
|
||||||
~source:pkh
|
let contents =
|
||||||
~period:next_level.voting_period
|
Amendment_operation
|
||||||
~proposals
|
{ source = pkh ;
|
||||||
() >>=? fun bytes ->
|
operation = Proposals { period = next_level.voting_period ;
|
||||||
let signed_bytes = Signature.append ~watermark:Generic_operation sk bytes in
|
proposals } } in
|
||||||
return (Tezos_base.Operation.of_bytes_exn signed_bytes)
|
sign ~watermark:Generic_operation sk shell contents
|
||||||
|
|
||||||
let ballot ?(block = `Head 0) ~src:({ pkh; sk } : Account.t) ~proposal ballot =
|
let ballot ?(block = `Head 0) ~src:({ pkh; sk } : Account.t) ~proposal ballot =
|
||||||
Block_services.info !rpc_ctxt block >>=? fun block_info ->
|
Block_services.hash !rpc_ctxt ~block () >>=? fun hash ->
|
||||||
Alpha_services.Context.next_level !rpc_ctxt block >>=? fun next_level ->
|
Alpha_services.Context.next_level
|
||||||
Alpha_services.Forge.Amendment.ballot !rpc_ctxt block
|
!rpc_ctxt (`Main, block) >>=? fun next_level ->
|
||||||
~branch:block_info.hash
|
let shell = { Tezos_base.Operation.branch = hash } in
|
||||||
~source:pkh
|
let contents =
|
||||||
~period:next_level.voting_period
|
Amendment_operation
|
||||||
~proposal
|
{ source = pkh ;
|
||||||
~ballot
|
operation = Ballot { period = next_level.voting_period ;
|
||||||
() >>=? fun bytes ->
|
proposal ;
|
||||||
let signed_bytes = Signature.append ~watermark:Generic_operation sk bytes in
|
ballot } } in
|
||||||
return (Tezos_base.Operation.of_bytes_exn signed_bytes)
|
sign ~watermark:Generic_operation sk shell contents
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -415,7 +428,7 @@ module Assert = struct
|
|||||||
match op with
|
match op with
|
||||||
| None -> true
|
| None -> true
|
||||||
| Some op ->
|
| Some op ->
|
||||||
let h = hash op and h' = hash op' in
|
let h = Operation.hash op and h' = hash op' in
|
||||||
Operation_hash.equal h h'
|
Operation_hash.equal h h'
|
||||||
end && List.exists (ecoproto_error f) err
|
end && List.exists (ecoproto_error f) err
|
||||||
| _ -> false
|
| _ -> false
|
||||||
@ -473,7 +486,8 @@ module Assert = struct
|
|||||||
end
|
end
|
||||||
|
|
||||||
let check_protocol ?msg ~block h =
|
let check_protocol ?msg ~block h =
|
||||||
Block_services.protocol !rpc_ctxt block >>=? fun block_proto ->
|
Block_services.Metadata.next_protocol_hash
|
||||||
|
!rpc_ctxt ~block () >>=? fun block_proto ->
|
||||||
return @@ equal
|
return @@ equal
|
||||||
?msg
|
?msg
|
||||||
~prn:Protocol_hash.to_b58check
|
~prn:Protocol_hash.to_b58check
|
||||||
@ -481,7 +495,7 @@ module Assert = struct
|
|||||||
block_proto h
|
block_proto h
|
||||||
|
|
||||||
let check_voting_period_kind ?msg ~block kind =
|
let check_voting_period_kind ?msg ~block kind =
|
||||||
Alpha_services.Context.voting_period_kind !rpc_ctxt block
|
Alpha_services.Context.voting_period_kind !rpc_ctxt (`Main, block)
|
||||||
>>=? fun current_kind ->
|
>>=? fun current_kind ->
|
||||||
return @@ equal
|
return @@ equal
|
||||||
?msg
|
?msg
|
||||||
@ -498,7 +512,7 @@ module Baking = struct
|
|||||||
|
|
||||||
let bake block (contract: Account.t) operations =
|
let bake block (contract: Account.t) operations =
|
||||||
let ctxt = (new wrap_full (no_write_context ~block !rpc_config)) in
|
let ctxt = (new wrap_full (no_write_context ~block !rpc_config)) in
|
||||||
Alpha_services.Context.next_level ctxt block >>=? fun level ->
|
Alpha_services.Context.next_level ctxt (`Main, block) >>=? fun level ->
|
||||||
let seed_nonce_hash =
|
let seed_nonce_hash =
|
||||||
if level.Level.expected_commitment then
|
if level.Level.expected_commitment then
|
||||||
let seed_nonce =
|
let seed_nonce =
|
||||||
@ -531,17 +545,13 @@ module Endorse = struct
|
|||||||
block
|
block
|
||||||
src_sk
|
src_sk
|
||||||
slot =
|
slot =
|
||||||
Block_services.info !rpc_ctxt block >>=? fun { hash ; _ } ->
|
Block_services.hash !rpc_ctxt ~block () >>=? fun hash ->
|
||||||
Alpha_services.Context.level !rpc_ctxt (`Hash (hash, 0)) >>=? fun level ->
|
Alpha_services.Context.level !rpc_ctxt (`Main, block) >>=? fun { level } ->
|
||||||
Alpha_services.Forge.Consensus.endorsement !rpc_ctxt
|
let shell = { Tezos_base.Operation.branch = hash } in
|
||||||
block
|
let contents =
|
||||||
~branch:hash
|
Consensus_operation
|
||||||
~block:hash
|
(Endorsements { block = hash ; level ; slots = [ slot ]}) in
|
||||||
~level:level.level
|
sign ~watermark:Endorsement src_sk shell contents
|
||||||
~slots:[slot]
|
|
||||||
() >>=? fun bytes ->
|
|
||||||
let signed_bytes = Signature.append ~watermark:Endorsement src_sk bytes in
|
|
||||||
return (Tezos_base.Operation.of_bytes_exn signed_bytes)
|
|
||||||
|
|
||||||
let signing_slots
|
let signing_slots
|
||||||
?(max_priority = 1024)
|
?(max_priority = 1024)
|
||||||
@ -550,7 +560,7 @@ module Endorse = struct
|
|||||||
level =
|
level =
|
||||||
Alpha_services.Delegate.Endorser.rights_for_delegate
|
Alpha_services.Delegate.Endorser.rights_for_delegate
|
||||||
!rpc_ctxt ~max_priority ~first_level:level ~last_level:level
|
!rpc_ctxt ~max_priority ~first_level:level ~last_level:level
|
||||||
block delegate >>=? fun possibilities ->
|
(`Main, block) delegate >>=? fun possibilities ->
|
||||||
let slots =
|
let slots =
|
||||||
List.map (fun (_,slot) -> slot)
|
List.map (fun (_,slot) -> slot)
|
||||||
@@ List.filter (fun (l, _) -> l = level) possibilities in
|
@@ List.filter (fun (l, _) -> l = level) possibilities in
|
||||||
@ -560,7 +570,7 @@ module Endorse = struct
|
|||||||
?slot
|
?slot
|
||||||
(contract : Account.t)
|
(contract : Account.t)
|
||||||
block =
|
block =
|
||||||
Alpha_services.Context.level !rpc_ctxt block >>=? fun { level } ->
|
Alpha_services.Context.level !rpc_ctxt (`Main, block) >>=? fun { level } ->
|
||||||
begin
|
begin
|
||||||
match slot with
|
match slot with
|
||||||
| Some slot -> return slot
|
| Some slot -> return slot
|
||||||
@ -579,7 +589,7 @@ module Endorse = struct
|
|||||||
let endorsers_list block =
|
let endorsers_list block =
|
||||||
let get_endorser_list result (account : Account.t) level block =
|
let get_endorser_list result (account : Account.t) level block =
|
||||||
Alpha_services.Delegate.Endorser.rights_for_delegate
|
Alpha_services.Delegate.Endorser.rights_for_delegate
|
||||||
!rpc_ctxt block account.pkh
|
!rpc_ctxt (`Main, block) account.pkh
|
||||||
~max_priority:16
|
~max_priority:16
|
||||||
~first_level:level
|
~first_level:level
|
||||||
~last_level:level >>|? fun slots ->
|
~last_level:level >>|? fun slots ->
|
||||||
@ -587,7 +597,7 @@ module Endorse = struct
|
|||||||
in
|
in
|
||||||
let { Account.b1 ; b2 ; b3 ; b4 ; b5 } = Account.bootstrap_accounts in
|
let { Account.b1 ; b2 ; b3 ; b4 ; b5 } = Account.bootstrap_accounts in
|
||||||
let result = Array.make 16 b1 in
|
let result = Array.make 16 b1 in
|
||||||
Alpha_services.Context.level !rpc_ctxt block >>=? fun level ->
|
Alpha_services.Context.level !rpc_ctxt (`Main, block) >>=? fun level ->
|
||||||
let level = level.level in
|
let level = level.level in
|
||||||
get_endorser_list result b1 level block >>=? fun () ->
|
get_endorser_list result b1 level block >>=? fun () ->
|
||||||
get_endorser_list result b2 level block >>=? fun () ->
|
get_endorser_list result b2 level block >>=? fun () ->
|
||||||
@ -599,7 +609,7 @@ module Endorse = struct
|
|||||||
let endorsement_rights
|
let endorsement_rights
|
||||||
?(max_priority = 1024)
|
?(max_priority = 1024)
|
||||||
(contract : Account.t) block =
|
(contract : Account.t) block =
|
||||||
Alpha_services.Context.level !rpc_ctxt block >>=? fun level ->
|
Alpha_services.Context.level !rpc_ctxt (`Main, block) >>=? fun level ->
|
||||||
let delegate = contract.pkh in
|
let delegate = contract.pkh in
|
||||||
let level = level.level in
|
let level = level.level in
|
||||||
Alpha_services.Delegate.Endorser.rights_for_delegate
|
Alpha_services.Delegate.Endorser.rights_for_delegate
|
||||||
@ -607,17 +617,17 @@ module Endorse = struct
|
|||||||
~max_priority
|
~max_priority
|
||||||
~first_level:level
|
~first_level:level
|
||||||
~last_level:level
|
~last_level:level
|
||||||
block delegate
|
(`Main, block) delegate
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
let display_level block =
|
let display_level block =
|
||||||
Alpha_services.Context.level !rpc_ctxt block >>=? fun lvl ->
|
Alpha_services.Context.level !rpc_ctxt (`Main, block) >>=? fun lvl ->
|
||||||
Format.eprintf "Level: %a@." Level.pp_full lvl ;
|
Format.eprintf "Level: %a@." Level.pp_full lvl ;
|
||||||
return ()
|
return ()
|
||||||
|
|
||||||
let endorsement_security_deposit block =
|
let endorsement_security_deposit block =
|
||||||
Constants_services.endorsement_security_deposit !rpc_ctxt block
|
Constants_services.endorsement_security_deposit !rpc_ctxt (`Main, block)
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
Client_keys.register_signer
|
Client_keys.register_signer
|
||||||
|
@ -19,11 +19,11 @@ val init :
|
|||||||
forked Tezos node and the block info of the block from where the
|
forked Tezos node and the block info of the block from where the
|
||||||
tests will begin. *)
|
tests will begin. *)
|
||||||
|
|
||||||
val level : Block_services.block -> Alpha_context.Level.t tzresult Lwt.t
|
val level : Chain_services.chain * Block_services.block -> Alpha_context.Level.t tzresult Lwt.t
|
||||||
|
|
||||||
(** Calls the rpc service raw_context using the right rpc context *)
|
(** Calls the rpc service raw_context using the right rpc context *)
|
||||||
val rpc_raw_context : Block_services.block -> string list -> int ->
|
val rpc_raw_context : Block_services.block -> string list -> int ->
|
||||||
Block_services.raw_context_result tzresult Lwt.t
|
Block_services.raw_context tzresult Lwt.t
|
||||||
|
|
||||||
module Account : sig
|
module Account : sig
|
||||||
|
|
||||||
@ -103,7 +103,7 @@ module Baking : sig
|
|||||||
val bake:
|
val bake:
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
Account.t ->
|
Account.t ->
|
||||||
Operation.raw list ->
|
Operation.t list ->
|
||||||
Block_hash.t tzresult Lwt.t
|
Block_hash.t tzresult Lwt.t
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -114,7 +114,7 @@ module Endorse : sig
|
|||||||
?slot:int ->
|
?slot:int ->
|
||||||
Account.t ->
|
Account.t ->
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
Operation.raw tzresult Lwt.t
|
Operation.t tzresult Lwt.t
|
||||||
|
|
||||||
val endorsers_list :
|
val endorsers_list :
|
||||||
Block_services.block ->
|
Block_services.block ->
|
||||||
@ -134,14 +134,14 @@ module Protocol : sig
|
|||||||
?block:Block_services.block ->
|
?block:Block_services.block ->
|
||||||
src:Account.t ->
|
src:Account.t ->
|
||||||
Protocol_hash.t list ->
|
Protocol_hash.t list ->
|
||||||
Operation.raw tzresult Lwt.t
|
Operation.t tzresult Lwt.t
|
||||||
|
|
||||||
val ballot :
|
val ballot :
|
||||||
?block:Block_services.block ->
|
?block:Block_services.block ->
|
||||||
src:Account.t ->
|
src:Account.t ->
|
||||||
proposal:Protocol_hash.t ->
|
proposal:Protocol_hash.t ->
|
||||||
Vote.ballot ->
|
Vote.ballot ->
|
||||||
Operation.raw tzresult Lwt.t
|
Operation.t tzresult Lwt.t
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -166,7 +166,7 @@ module Assert : sig
|
|||||||
|
|
||||||
val failed_to_preapply:
|
val failed_to_preapply:
|
||||||
msg:string ->
|
msg:string ->
|
||||||
?op:Tezos_base.Operation.t ->
|
?op:Operation.t ->
|
||||||
(Alpha_environment.Error_monad.error ->
|
(Alpha_environment.Error_monad.error ->
|
||||||
bool) ->
|
bool) ->
|
||||||
'a tzresult -> unit
|
'a tzresult -> unit
|
||||||
|
@ -14,13 +14,13 @@ module Assert = Helpers.Assert
|
|||||||
A similar test is bin_client/test/test_basic.sh
|
A similar test is bin_client/test/test_basic.sh
|
||||||
*)
|
*)
|
||||||
let run blkid =
|
let run blkid =
|
||||||
let open Block_services in
|
|
||||||
|
|
||||||
|
let open Block_services in
|
||||||
let is_equal a = function
|
let is_equal a = function
|
||||||
| Ok b -> a = b
|
| Ok b -> a = b
|
||||||
| _ -> false
|
| _ -> false
|
||||||
in
|
in
|
||||||
let is_not_found : raw_context_result tzresult -> bool = function
|
let is_not_found : raw_context tzresult -> bool = function
|
||||||
| Error [RPC_context.Not_found _] -> true
|
| Error [RPC_context.Not_found _] -> true
|
||||||
| _ -> false
|
| _ -> false
|
||||||
in
|
in
|
||||||
@ -38,15 +38,24 @@ let run blkid =
|
|||||||
let tests = [((["version"],1), is_equal version);
|
let tests = [((["version"],1), is_equal version);
|
||||||
(([""],0), is_equal dir_depth0);
|
(([""],0), is_equal dir_depth0);
|
||||||
((["delegates";"ed25519"],2), is_equal dir_depth2);
|
((["delegates";"ed25519"],2), is_equal dir_depth2);
|
||||||
(([""],-1), is_not_found);
|
(* (([""],-1), is_not_found); *)
|
||||||
((["not-existent"],1), is_not_found);
|
((["not-existent"],1), is_not_found);
|
||||||
((["not-existent"],0), is_not_found);
|
((["not-existent"],0), is_not_found);
|
||||||
((["not-existent"],-1), is_not_found);
|
(* ((["not-existent"],-1), is_not_found); *)
|
||||||
] in
|
] in
|
||||||
|
|
||||||
|
let success = ref true in
|
||||||
iter_s (fun ((path,depth),predicate) ->
|
iter_s (fun ((path,depth),predicate) ->
|
||||||
Helpers.rpc_raw_context blkid path depth >>= fun result ->
|
Helpers.rpc_raw_context blkid path depth >>= fun result ->
|
||||||
return (assert (predicate result))
|
let res = predicate result in
|
||||||
) tests
|
Format.eprintf "/%s (%d) -> %B@." (String.concat "/" path) depth res ;
|
||||||
|
success := !success && res ;
|
||||||
|
return ()
|
||||||
|
) tests >>=? fun () ->
|
||||||
|
if !success then
|
||||||
|
return ()
|
||||||
|
else
|
||||||
|
failwith "Error!"
|
||||||
|
|
||||||
let exe = try Sys.argv.(1) with _ -> "tezos-node"
|
let exe = try Sys.argv.(1) with _ -> "tezos-node"
|
||||||
let rpc_port = try int_of_string Sys.argv.(2) with _ -> 18500
|
let rpc_port = try int_of_string Sys.argv.(2) with _ -> 18500
|
||||||
|
@ -16,7 +16,7 @@ let demo_protocol =
|
|||||||
"ProtoDemoDemoDemoDemoDemoDemoDemoDemoDemoDemoD3c8k9"
|
"ProtoDemoDemoDemoDemoDemoDemoDemoDemoDemoDemoD3c8k9"
|
||||||
|
|
||||||
let print_level head =
|
let print_level head =
|
||||||
level (`Hash (head, 0)) >>=? fun lvl ->
|
level (`Main, `Hash (head, 0)) >>=? fun lvl ->
|
||||||
return @@ Format.eprintf "voting_period = %a.%ld@."
|
return @@ Format.eprintf "voting_period = %a.%ld@."
|
||||||
Voting_period.pp lvl.voting_period lvl.voting_period_position
|
Voting_period.pp lvl.voting_period lvl.voting_period_position
|
||||||
|
|
||||||
|
@ -13,11 +13,11 @@ open Tezos_micheline
|
|||||||
open Client_proto_contracts
|
open Client_proto_contracts
|
||||||
open Client_keys
|
open Client_keys
|
||||||
|
|
||||||
let get_balance (rpc : #Proto_alpha.rpc_context) block contract =
|
let get_balance (rpc : #Proto_alpha.rpc_context) ~chain ~block contract =
|
||||||
Alpha_services.Contract.balance rpc block contract
|
Alpha_services.Contract.balance rpc (chain, block) contract
|
||||||
|
|
||||||
let get_storage (rpc : #Proto_alpha.rpc_context) block contract =
|
let get_storage (rpc : #Proto_alpha.rpc_context) ~chain ~block contract =
|
||||||
Alpha_services.Contract.storage_opt rpc block contract
|
Alpha_services.Contract.storage_opt rpc (chain, block) contract
|
||||||
|
|
||||||
let parse_expression arg =
|
let parse_expression arg =
|
||||||
Lwt.return
|
Lwt.return
|
||||||
@ -25,9 +25,10 @@ let parse_expression arg =
|
|||||||
(Michelson_v1_parser.parse_expression arg))
|
(Michelson_v1_parser.parse_expression arg))
|
||||||
|
|
||||||
let append_reveal
|
let append_reveal
|
||||||
cctxt block
|
cctxt ~chain ~block
|
||||||
~source ~src_pk ops =
|
~source ~src_pk ops =
|
||||||
Alpha_services.Contract.manager_key cctxt block source >>=? fun (_pkh, pk) ->
|
Alpha_services.Contract.manager_key
|
||||||
|
cctxt (chain, block) source >>=? fun (_pkh, pk) ->
|
||||||
let is_reveal = function
|
let is_reveal = function
|
||||||
| Reveal _ -> true
|
| Reveal _ -> true
|
||||||
| _ -> false in
|
| _ -> false in
|
||||||
@ -37,7 +38,7 @@ let append_reveal
|
|||||||
| _ -> return ops
|
| _ -> return ops
|
||||||
|
|
||||||
let transfer (cctxt : #Proto_alpha.full)
|
let transfer (cctxt : #Proto_alpha.full)
|
||||||
block ?confirmations
|
~chain ~block ?confirmations
|
||||||
?branch ~source ~src_pk ~src_sk ~destination ?arg
|
?branch ~source ~src_pk ~src_sk ~destination ?arg
|
||||||
~amount ~fee ?(gas_limit = Z.minus_one) ?(storage_limit = -1L) () =
|
~amount ~fee ?(gas_limit = Z.minus_one) ?(storage_limit = -1L) () =
|
||||||
begin match arg with
|
begin match arg with
|
||||||
@ -47,26 +48,28 @@ let transfer (cctxt : #Proto_alpha.full)
|
|||||||
| None -> return None
|
| None -> return None
|
||||||
end >>=? fun parameters ->
|
end >>=? fun parameters ->
|
||||||
Alpha_services.Contract.counter
|
Alpha_services.Contract.counter
|
||||||
cctxt block source >>=? fun pcounter ->
|
cctxt (chain, block) source >>=? fun pcounter ->
|
||||||
let counter = Int32.succ pcounter in
|
let counter = Int32.succ pcounter in
|
||||||
let parameters = Option.map ~f:Script.lazy_expr parameters in
|
let parameters = Option.map ~f:Script.lazy_expr parameters in
|
||||||
let operations = [Transaction { amount ; parameters ; destination }] in
|
let operations = [Transaction { amount ; parameters ; destination }] in
|
||||||
append_reveal cctxt block ~source ~src_pk operations >>=? fun operations ->
|
append_reveal cctxt ~chain ~block
|
||||||
|
~source ~src_pk operations >>=? fun operations ->
|
||||||
let contents =
|
let contents =
|
||||||
Sourced_operation
|
Sourced_operation
|
||||||
(Manager_operations { source ; fee ; counter ;
|
(Manager_operations { source ; fee ; counter ;
|
||||||
gas_limit ; storage_limit ; operations }) in
|
gas_limit ; storage_limit ; operations }) in
|
||||||
Injection.inject_operation cctxt block ?confirmations
|
Injection.inject_operation cctxt ~chain ~block ?confirmations
|
||||||
?branch ~src_sk contents >>=? fun (_oph, _op, result as res) ->
|
?branch ~src_sk contents >>=? fun (_oph, _op, result as res) ->
|
||||||
Lwt.return (Injection.originated_contracts result) >>=? fun contracts ->
|
Lwt.return (Injection.originated_contracts result) >>=? fun contracts ->
|
||||||
return (res, contracts)
|
return (res, contracts)
|
||||||
|
|
||||||
let reveal cctxt
|
let reveal cctxt
|
||||||
block ?confirmations
|
~chain ~block ?confirmations
|
||||||
?branch ~source ~src_pk ~src_sk ~fee () =
|
?branch ~source ~src_pk ~src_sk ~fee () =
|
||||||
Alpha_services.Contract.counter cctxt block source >>=? fun pcounter ->
|
Alpha_services.Contract.counter
|
||||||
|
cctxt (chain, block) source >>=? fun pcounter ->
|
||||||
let counter = Int32.succ pcounter in
|
let counter = Int32.succ pcounter in
|
||||||
append_reveal cctxt block ~source ~src_pk [] >>=? fun operations ->
|
append_reveal cctxt ~chain ~block ~source ~src_pk [] >>=? fun operations ->
|
||||||
match operations with
|
match operations with
|
||||||
| [] ->
|
| [] ->
|
||||||
failwith "The manager key was previously revealed."
|
failwith "The manager key was previously revealed."
|
||||||
@ -76,24 +79,25 @@ let reveal cctxt
|
|||||||
(Manager_operations { source ; fee ; counter ;
|
(Manager_operations { source ; fee ; counter ;
|
||||||
gas_limit = Z.zero ; storage_limit = 0L ;
|
gas_limit = Z.zero ; storage_limit = 0L ;
|
||||||
operations }) in
|
operations }) in
|
||||||
Injection.inject_operation cctxt block ?confirmations
|
Injection.inject_operation cctxt ~chain ~block ?confirmations
|
||||||
?branch ~src_sk contents >>=? fun res ->
|
?branch ~src_sk contents >>=? fun res ->
|
||||||
return res
|
return res
|
||||||
|
|
||||||
let originate
|
let originate
|
||||||
cctxt block ?confirmations
|
cctxt ~chain ~block ?confirmations
|
||||||
?branch ~source ~src_pk ~src_sk ~fee
|
?branch ~source ~src_pk ~src_sk ~fee
|
||||||
?(gas_limit = Z.minus_one) ?(storage_limit = -1L) origination =
|
?(gas_limit = Z.minus_one) ?(storage_limit = -1L) origination =
|
||||||
Alpha_services.Contract.counter cctxt block source >>=? fun pcounter ->
|
Alpha_services.Contract.counter
|
||||||
|
cctxt (chain, block) source >>=? fun pcounter ->
|
||||||
let counter = Int32.succ pcounter in
|
let counter = Int32.succ pcounter in
|
||||||
let operations = [origination] in
|
let operations = [origination] in
|
||||||
append_reveal
|
append_reveal
|
||||||
cctxt block ~source ~src_pk operations >>=? fun operations ->
|
cctxt ~chain ~block ~source ~src_pk operations >>=? fun operations ->
|
||||||
let contents =
|
let contents =
|
||||||
Sourced_operation
|
Sourced_operation
|
||||||
(Manager_operations { source ; fee ; counter ;
|
(Manager_operations { source ; fee ; counter ;
|
||||||
gas_limit ; storage_limit ; operations }) in
|
gas_limit ; storage_limit ; operations }) in
|
||||||
Injection.inject_operation cctxt block ?confirmations
|
Injection.inject_operation cctxt ~chain ~block ?confirmations
|
||||||
?branch ~src_sk contents >>=? fun (_oph, _op, result as res) ->
|
?branch ~src_sk contents >>=? fun (_oph, _op, result as res) ->
|
||||||
Lwt.return (Injection.originated_contracts result) >>=? function
|
Lwt.return (Injection.originated_contracts result) >>=? function
|
||||||
| [ contract ] -> return (res, contract)
|
| [ contract ] -> return (res, contract)
|
||||||
@ -103,7 +107,7 @@ let originate
|
|||||||
(List.length contracts)
|
(List.length contracts)
|
||||||
|
|
||||||
let originate_account
|
let originate_account
|
||||||
cctxt block ?confirmations
|
cctxt ~chain ~block ?confirmations
|
||||||
?branch ~source ~src_pk ~src_sk ~manager_pkh
|
?branch ~source ~src_pk ~src_sk ~manager_pkh
|
||||||
?(delegatable = false) ?delegate ~balance ~fee () =
|
?(delegatable = false) ?delegate ~balance ~fee () =
|
||||||
let origination =
|
let origination =
|
||||||
@ -115,32 +119,32 @@ let originate_account
|
|||||||
credit = balance ;
|
credit = balance ;
|
||||||
preorigination = None } in
|
preorigination = None } in
|
||||||
originate
|
originate
|
||||||
cctxt block ?confirmations
|
cctxt ~chain ~block ?confirmations
|
||||||
?branch ~source ~gas_limit:Z.zero~src_pk ~src_sk ~fee origination
|
?branch ~source ~gas_limit:Z.zero~src_pk ~src_sk ~fee origination
|
||||||
|
|
||||||
let delegate_contract cctxt
|
let delegate_contract cctxt
|
||||||
block ?branch ?confirmations
|
~chain ~block ?branch ?confirmations
|
||||||
~source ~src_pk ~src_sk
|
~source ~src_pk ~src_sk
|
||||||
~fee delegate_opt =
|
~fee delegate_opt =
|
||||||
Alpha_services.Contract.counter
|
Alpha_services.Contract.counter
|
||||||
cctxt block source >>=? fun pcounter ->
|
cctxt (chain, block) source >>=? fun pcounter ->
|
||||||
let counter = Int32.succ pcounter in
|
let counter = Int32.succ pcounter in
|
||||||
let operations = [Delegation delegate_opt] in
|
let operations = [Delegation delegate_opt] in
|
||||||
append_reveal
|
append_reveal
|
||||||
cctxt block ~source ~src_pk operations >>=? fun operations ->
|
cctxt ~chain ~block ~source ~src_pk operations >>=? fun operations ->
|
||||||
let contents =
|
let contents =
|
||||||
Sourced_operation
|
Sourced_operation
|
||||||
(Manager_operations { source ; fee ; counter ;
|
(Manager_operations { source ; fee ; counter ;
|
||||||
gas_limit = Z.zero ; storage_limit = 0L ;
|
gas_limit = Z.zero ; storage_limit = 0L ;
|
||||||
operations }) in
|
operations }) in
|
||||||
Injection.inject_operation cctxt block ?confirmations
|
Injection.inject_operation cctxt ~chain ~block ?confirmations
|
||||||
?branch ~src_sk contents >>=? fun res ->
|
?branch ~src_sk contents >>=? fun res ->
|
||||||
return res
|
return res
|
||||||
|
|
||||||
let list_contract_labels
|
let list_contract_labels
|
||||||
(cctxt : #Proto_alpha.full)
|
(cctxt : #Proto_alpha.full)
|
||||||
block =
|
~chain ~block =
|
||||||
Alpha_services.Contract.list cctxt block >>=? fun contracts ->
|
Alpha_services.Contract.list cctxt (chain, block) >>=? fun contracts ->
|
||||||
map_s (fun h ->
|
map_s (fun h ->
|
||||||
begin match Contract.is_implicit h with
|
begin match Contract.is_implicit h with
|
||||||
| Some m -> begin
|
| Some m -> begin
|
||||||
@ -169,32 +173,39 @@ let message_added_contract (cctxt : #Proto_alpha.full) name =
|
|||||||
|
|
||||||
let get_manager
|
let get_manager
|
||||||
(cctxt : #Proto_alpha.full)
|
(cctxt : #Proto_alpha.full)
|
||||||
block source =
|
~chain ~block source =
|
||||||
Client_proto_contracts.get_manager
|
Client_proto_contracts.get_manager
|
||||||
cctxt block source >>=? fun src_pkh ->
|
cctxt ~chain ~block source >>=? fun src_pkh ->
|
||||||
Client_keys.get_key cctxt src_pkh >>=? fun (src_name, src_pk, src_sk) ->
|
Client_keys.get_key cctxt src_pkh >>=? fun (src_name, src_pk, src_sk) ->
|
||||||
return (src_name, src_pkh, src_pk, src_sk)
|
return (src_name, src_pkh, src_pk, src_sk)
|
||||||
|
|
||||||
let dictate rpc_config block ?confirmations command src_sk =
|
let dictate rpc_config ~chain ~block ?confirmations command src_sk =
|
||||||
let contents = Sourced_operation (Dictator_operation command) in
|
let contents = Sourced_operation (Dictator_operation command) in
|
||||||
Injection.inject_operation
|
Injection.inject_operation
|
||||||
rpc_config block ?confirmations
|
rpc_config ~chain ~block ?confirmations
|
||||||
~src_sk contents >>=? fun res ->
|
~src_sk contents >>=? fun res ->
|
||||||
return res
|
return res
|
||||||
|
|
||||||
let set_delegate cctxt block ?confirmations ~fee contract ~src_pk ~manager_sk opt_delegate =
|
let set_delegate
|
||||||
|
cctxt ~chain ~block ?confirmations
|
||||||
|
~fee contract ~src_pk ~manager_sk opt_delegate =
|
||||||
delegate_contract
|
delegate_contract
|
||||||
cctxt block ?confirmations ~source:contract ~src_pk ~src_sk:manager_sk ~fee opt_delegate
|
cctxt ~chain ~block ?confirmations
|
||||||
|
~source:contract ~src_pk ~src_sk:manager_sk ~fee opt_delegate
|
||||||
|
|
||||||
let register_as_delegate cctxt block ?confirmations ~fee ~manager_sk src_pk =
|
let register_as_delegate
|
||||||
|
cctxt ~chain ~block ?confirmations
|
||||||
|
~fee ~manager_sk src_pk =
|
||||||
let source = Signature.Public_key.hash src_pk in
|
let source = Signature.Public_key.hash src_pk in
|
||||||
delegate_contract
|
delegate_contract
|
||||||
cctxt block ?confirmations
|
cctxt ~chain ~block ?confirmations
|
||||||
~source:(Contract.implicit_contract source) ~src_pk ~src_sk:manager_sk ~fee
|
~source:(Contract.implicit_contract source) ~src_pk ~src_sk:manager_sk ~fee
|
||||||
(Some source)
|
(Some source)
|
||||||
|
|
||||||
let source_to_keys (wallet : #Proto_alpha.full) block source =
|
let source_to_keys (wallet : #Proto_alpha.full) ~chain ~block source =
|
||||||
get_manager wallet block source >>=? fun (_src_name, _src_pkh, src_pk, src_sk) ->
|
get_manager
|
||||||
|
wallet ~chain ~block
|
||||||
|
source >>=? fun (_src_name, _src_pkh, src_pk, src_sk) ->
|
||||||
return (src_pk, src_sk)
|
return (src_pk, src_sk)
|
||||||
|
|
||||||
let save_contract ~force cctxt alias_name contract =
|
let save_contract ~force cctxt alias_name contract =
|
||||||
@ -204,7 +215,7 @@ let save_contract ~force cctxt alias_name contract =
|
|||||||
|
|
||||||
let originate_contract
|
let originate_contract
|
||||||
(cctxt : #Proto_alpha.full)
|
(cctxt : #Proto_alpha.full)
|
||||||
block ?confirmations ?branch
|
~chain ~block ?confirmations ?branch
|
||||||
~fee
|
~fee
|
||||||
?gas_limit
|
?gas_limit
|
||||||
?storage_limit
|
?storage_limit
|
||||||
@ -231,7 +242,7 @@ let originate_contract
|
|||||||
delegatable ;
|
delegatable ;
|
||||||
credit = balance ;
|
credit = balance ;
|
||||||
preorigination = None } in
|
preorigination = None } in
|
||||||
originate cctxt block ?confirmations
|
originate cctxt ~chain ~block ?confirmations
|
||||||
?branch ~source ~src_pk ~src_sk ~fee ?gas_limit ?storage_limit origination
|
?branch ~source ~src_pk ~src_sk ~fee ?gas_limit ?storage_limit origination
|
||||||
|
|
||||||
type activation_key =
|
type activation_key =
|
||||||
@ -295,8 +306,10 @@ let read_key key =
|
|||||||
let pkh = Signature.Public_key.hash pk in
|
let pkh = Signature.Public_key.hash pk in
|
||||||
return (pkh, pk, sk)
|
return (pkh, pk, sk)
|
||||||
|
|
||||||
let claim_commitment (cctxt : #Proto_alpha.full)
|
let claim_commitment
|
||||||
?(encrypted = false) ?confirmations ?force block key name =
|
(cctxt : #Proto_alpha.full)
|
||||||
|
~chain ~block ?confirmations
|
||||||
|
?(encrypted = false) ?force key name =
|
||||||
read_key key >>=? fun (pkh, pk, sk) ->
|
read_key key >>=? fun (pkh, pk, sk) ->
|
||||||
fail_unless (Signature.Public_key_hash.equal pkh (Ed25519 key.pkh))
|
fail_unless (Signature.Public_key_hash.equal pkh (Ed25519 key.pkh))
|
||||||
(failure "@[<v 2>Inconsistent activation key:@ \
|
(failure "@[<v 2>Inconsistent activation key:@ \
|
||||||
@ -307,7 +320,9 @@ let claim_commitment (cctxt : #Proto_alpha.full)
|
|||||||
let contents =
|
let contents =
|
||||||
Anonymous_operations
|
Anonymous_operations
|
||||||
[ Activation { id = key.pkh ; activation_code = key.activation_code } ] in
|
[ Activation { id = key.pkh ; activation_code = key.activation_code } ] in
|
||||||
Injection.inject_operation cctxt ?confirmations block contents >>=? fun (_oph, _op, _result as res) ->
|
Injection.inject_operation
|
||||||
|
cctxt ?confirmations ~chain ~block
|
||||||
|
contents >>=? fun (_oph, _op, _result as res) ->
|
||||||
let pk_uri = Tezos_signer_backends.Unencrypted.make_pk pk in
|
let pk_uri = Tezos_signer_backends.Unencrypted.make_pk pk in
|
||||||
begin
|
begin
|
||||||
if encrypted then
|
if encrypted then
|
||||||
@ -322,7 +337,7 @@ let claim_commitment (cctxt : #Proto_alpha.full)
|
|||||||
return ()
|
return ()
|
||||||
| Some _confirmations ->
|
| Some _confirmations ->
|
||||||
Alpha_services.Contract.balance
|
Alpha_services.Contract.balance
|
||||||
cctxt (`Head 0)
|
cctxt (`Main, `Head 0)
|
||||||
(Contract.implicit_contract pkh) >>=? fun balance ->
|
(Contract.implicit_contract pkh) >>=? fun balance ->
|
||||||
cctxt#message "Account %s (%a) created with %s%a."
|
cctxt#message "Account %s (%a) created with %s%a."
|
||||||
name
|
name
|
||||||
|
@ -12,31 +12,36 @@ open Alpha_context
|
|||||||
|
|
||||||
val list_contract_labels :
|
val list_contract_labels :
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
(string * string * string) list tzresult Lwt.t
|
(string * string * string) list tzresult Lwt.t
|
||||||
|
|
||||||
val get_storage :
|
val get_storage :
|
||||||
#Proto_alpha.rpc_context ->
|
#Proto_alpha.rpc_context ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
Script.expr option tzresult Lwt.t
|
Script.expr option tzresult Lwt.t
|
||||||
|
|
||||||
val get_manager :
|
val get_manager :
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
(string * public_key_hash *
|
(string * public_key_hash *
|
||||||
public_key * Client_keys.sk_uri) tzresult Lwt.t
|
public_key * Client_keys.sk_uri) tzresult Lwt.t
|
||||||
|
|
||||||
val get_balance:
|
val get_balance:
|
||||||
#Proto_alpha.rpc_context ->
|
#Proto_alpha.rpc_context ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
Tez.t tzresult Lwt.t
|
Tez.t tzresult Lwt.t
|
||||||
|
|
||||||
val set_delegate :
|
val set_delegate :
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
fee:Tez.tez ->
|
fee:Tez.tez ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
@ -47,7 +52,8 @@ val set_delegate :
|
|||||||
|
|
||||||
val register_as_delegate:
|
val register_as_delegate:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
fee:Tez.tez ->
|
fee:Tez.tez ->
|
||||||
manager_sk:Client_keys.sk_uri ->
|
manager_sk:Client_keys.sk_uri ->
|
||||||
@ -56,13 +62,15 @@ val register_as_delegate:
|
|||||||
|
|
||||||
val source_to_keys:
|
val source_to_keys:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
(public_key * Client_keys.sk_uri) tzresult Lwt.t
|
(public_key * Client_keys.sk_uri) tzresult Lwt.t
|
||||||
|
|
||||||
val originate_account :
|
val originate_account :
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
?branch:int ->
|
?branch:int ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -84,7 +92,8 @@ val save_contract :
|
|||||||
|
|
||||||
val originate_contract:
|
val originate_contract:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
?branch:int ->
|
?branch:int ->
|
||||||
fee:Tez.t ->
|
fee:Tez.t ->
|
||||||
@ -104,7 +113,8 @@ val originate_contract:
|
|||||||
|
|
||||||
val transfer :
|
val transfer :
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
?branch:int ->
|
?branch:int ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -121,7 +131,8 @@ val transfer :
|
|||||||
|
|
||||||
val reveal :
|
val reveal :
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
?branch:int ->
|
?branch:int ->
|
||||||
source:Contract.t ->
|
source:Contract.t ->
|
||||||
@ -132,7 +143,8 @@ val reveal :
|
|||||||
|
|
||||||
val dictate :
|
val dictate :
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
dictator_operation ->
|
dictator_operation ->
|
||||||
Client_keys.sk_uri ->
|
Client_keys.sk_uri ->
|
||||||
@ -151,10 +163,11 @@ val activation_key_encoding: activation_key Data_encoding.t
|
|||||||
|
|
||||||
val claim_commitment:
|
val claim_commitment:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
?encrypted:bool ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
|
?encrypted:bool ->
|
||||||
?force:bool ->
|
?force:bool ->
|
||||||
Block_services.block ->
|
|
||||||
activation_key ->
|
activation_key ->
|
||||||
string ->
|
string ->
|
||||||
Injection.result tzresult Lwt.t
|
Injection.result tzresult Lwt.t
|
||||||
|
@ -129,13 +129,13 @@ let list_contracts cctxt =
|
|||||||
keys >>=? fun accounts ->
|
keys >>=? fun accounts ->
|
||||||
return (contracts @ accounts)
|
return (contracts @ accounts)
|
||||||
|
|
||||||
let get_manager cctxt block source =
|
let get_manager cctxt ~chain ~block source =
|
||||||
match Contract.is_implicit source with
|
match Contract.is_implicit source with
|
||||||
| Some hash -> return hash
|
| Some hash -> return hash
|
||||||
| None -> Alpha_services.Contract.manager cctxt block source
|
| None -> Alpha_services.Contract.manager cctxt (chain, block) source
|
||||||
|
|
||||||
let get_delegate cctxt block source =
|
let get_delegate cctxt ~chain ~block source =
|
||||||
Alpha_services.Contract.delegate_opt cctxt block source
|
Alpha_services.Contract.delegate_opt cctxt (chain, block) source
|
||||||
|
|
||||||
let may_check_key sourcePubKey sourcePubKeyHash =
|
let may_check_key sourcePubKey sourcePubKeyHash =
|
||||||
match sourcePubKey with
|
match sourcePubKey with
|
||||||
|
@ -43,13 +43,15 @@ val list_contracts:
|
|||||||
|
|
||||||
val get_manager:
|
val get_manager:
|
||||||
#Proto_alpha.rpc_context ->
|
#Proto_alpha.rpc_context ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
public_key_hash tzresult Lwt.t
|
public_key_hash tzresult Lwt.t
|
||||||
|
|
||||||
val get_delegate:
|
val get_delegate:
|
||||||
#Proto_alpha.rpc_context ->
|
#Proto_alpha.rpc_context ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
Contract.t ->
|
Contract.t ->
|
||||||
public_key_hash option tzresult Lwt.t
|
public_key_hash option tzresult Lwt.t
|
||||||
|
|
||||||
|
@ -86,51 +86,75 @@ let print_trace_result (cctxt : #Client_context.printer) ~show_source ~parsed =
|
|||||||
| Error errs ->
|
| Error errs ->
|
||||||
print_errors cctxt errs ~show_source ~parsed
|
print_errors cctxt errs ~show_source ~parsed
|
||||||
|
|
||||||
let get_contract cctxt block contract =
|
let get_contract cctxt ?(chain = `Main) block contract =
|
||||||
match contract with
|
match contract with
|
||||||
| Some contract -> return contract
|
| Some contract -> return contract
|
||||||
| None ->
|
| None ->
|
||||||
(* TODO use local contract by default *)
|
(* TODO use local contract by default *)
|
||||||
Alpha_services.Contract.list cctxt block >>|? List.hd
|
Alpha_services.Contract.list cctxt (chain, block) >>|? List.hd
|
||||||
|
|
||||||
let run
|
let run
|
||||||
|
(cctxt : #Proto_alpha.rpc_context)
|
||||||
|
?(chain = `Main)
|
||||||
|
block
|
||||||
?contract
|
?contract
|
||||||
?(amount = Tez.fifty_cents)
|
?(amount = Tez.fifty_cents)
|
||||||
~(program : Michelson_v1_parser.parsed)
|
~(program : Michelson_v1_parser.parsed)
|
||||||
~(storage : Michelson_v1_parser.parsed)
|
~(storage : Michelson_v1_parser.parsed)
|
||||||
~(input : Michelson_v1_parser.parsed)
|
~(input : Michelson_v1_parser.parsed)
|
||||||
block
|
() =
|
||||||
(cctxt : #RPC_context.simple) =
|
get_contract cctxt ~chain block contract >>=? fun contract ->
|
||||||
get_contract cctxt block contract >>=? fun contract ->
|
|
||||||
Alpha_services.Helpers.run_code cctxt
|
Alpha_services.Helpers.run_code cctxt
|
||||||
block program.expanded (storage.expanded, input.expanded, amount, contract)
|
(chain, block)
|
||||||
|
program.expanded (storage.expanded, input.expanded, amount, contract)
|
||||||
|
|
||||||
let trace
|
let trace
|
||||||
|
(cctxt : #Proto_alpha.rpc_context)
|
||||||
|
?(chain = `Main)
|
||||||
|
block
|
||||||
?contract
|
?contract
|
||||||
?(amount = Tez.fifty_cents)
|
?(amount = Tez.fifty_cents)
|
||||||
~(program : Michelson_v1_parser.parsed)
|
~(program : Michelson_v1_parser.parsed)
|
||||||
~(storage : Michelson_v1_parser.parsed)
|
~(storage : Michelson_v1_parser.parsed)
|
||||||
~(input : Michelson_v1_parser.parsed)
|
~(input : Michelson_v1_parser.parsed)
|
||||||
block
|
() =
|
||||||
(cctxt : #RPC_context.simple) =
|
get_contract cctxt ~chain block contract >>=? fun contract ->
|
||||||
get_contract cctxt block contract >>=? fun contract ->
|
|
||||||
Alpha_services.Helpers.trace_code cctxt
|
Alpha_services.Helpers.trace_code cctxt
|
||||||
block program.expanded (storage.expanded, input.expanded, amount, contract)
|
(chain, block)
|
||||||
|
program.expanded (storage.expanded, input.expanded, amount, contract)
|
||||||
|
|
||||||
let hash_and_sign ?gas (data : Michelson_v1_parser.parsed) (typ : Michelson_v1_parser.parsed) sk block cctxt =
|
let hash_and_sign
|
||||||
Alpha_services.Helpers.hash_data cctxt block (data.expanded, typ.expanded, gas) >>=? fun (hash, gas) ->
|
cctxt
|
||||||
|
?(chain = `Main)
|
||||||
|
block
|
||||||
|
?gas
|
||||||
|
(data : Michelson_v1_parser.parsed)
|
||||||
|
(typ : Michelson_v1_parser.parsed)
|
||||||
|
sk =
|
||||||
|
Alpha_services.Helpers.hash_data
|
||||||
|
cctxt (chain, block) (data.expanded, typ.expanded, gas) >>=? fun (hash, gas) ->
|
||||||
Client_keys.sign sk (MBytes.of_string hash) >>=? fun signature ->
|
Client_keys.sign sk (MBytes.of_string hash) >>=? fun signature ->
|
||||||
return (hash, Signature.to_b58check signature, gas)
|
return (hash, Signature.to_b58check signature, gas)
|
||||||
|
|
||||||
let typecheck_data
|
let typecheck_data
|
||||||
|
cctxt
|
||||||
|
?(chain = `Main)
|
||||||
|
block
|
||||||
?gas
|
?gas
|
||||||
~(data : Michelson_v1_parser.parsed)
|
~(data : Michelson_v1_parser.parsed)
|
||||||
~(ty : Michelson_v1_parser.parsed)
|
~(ty : Michelson_v1_parser.parsed)
|
||||||
block cctxt =
|
() =
|
||||||
Alpha_services.Helpers.typecheck_data cctxt block (data.expanded, ty.expanded, gas)
|
Alpha_services.Helpers.typecheck_data
|
||||||
|
cctxt (chain, block)
|
||||||
|
(data.expanded, ty.expanded, gas)
|
||||||
|
|
||||||
let typecheck_program ?gas (program : Michelson_v1_parser.parsed) block cctxt =
|
let typecheck_program
|
||||||
Alpha_services.Helpers.typecheck_code cctxt block (program.expanded, gas)
|
cctxt
|
||||||
|
?(chain = `Main)
|
||||||
|
block
|
||||||
|
?gas
|
||||||
|
(program : Michelson_v1_parser.parsed) =
|
||||||
|
Alpha_services.Helpers.typecheck_code cctxt (chain, block) (program.expanded, gas)
|
||||||
|
|
||||||
let print_typecheck_result
|
let print_typecheck_result
|
||||||
~emacs ~show_types ~print_source_on_error
|
~emacs ~show_types ~print_source_on_error
|
||||||
|
@ -15,25 +15,29 @@ module Program : Client_aliases.Alias
|
|||||||
with type t = Michelson_v1_parser.parsed Micheline_parser.parsing_result
|
with type t = Michelson_v1_parser.parsed Micheline_parser.parsing_result
|
||||||
|
|
||||||
val run :
|
val run :
|
||||||
|
#Proto_alpha.rpc_context ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
|
Block_services.block ->
|
||||||
?contract:Contract.t ->
|
?contract:Contract.t ->
|
||||||
?amount:Tez.t ->
|
?amount:Tez.t ->
|
||||||
program:Michelson_v1_parser.parsed ->
|
program:Michelson_v1_parser.parsed ->
|
||||||
storage:Michelson_v1_parser.parsed ->
|
storage:Michelson_v1_parser.parsed ->
|
||||||
input:Michelson_v1_parser.parsed ->
|
input:Michelson_v1_parser.parsed ->
|
||||||
Block_services.block ->
|
unit ->
|
||||||
#Proto_alpha.rpc_context ->
|
|
||||||
(Script.expr *
|
(Script.expr *
|
||||||
internal_operation list *
|
internal_operation list *
|
||||||
Contract.big_map_diff option) tzresult Lwt.t
|
Contract.big_map_diff option) tzresult Lwt.t
|
||||||
|
|
||||||
val trace :
|
val trace :
|
||||||
|
#Proto_alpha.rpc_context ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
|
Block_services.block ->
|
||||||
?contract:Contract.t ->
|
?contract:Contract.t ->
|
||||||
?amount:Tez.t ->
|
?amount:Tez.t ->
|
||||||
program:Michelson_v1_parser.parsed ->
|
program:Michelson_v1_parser.parsed ->
|
||||||
storage:Michelson_v1_parser.parsed ->
|
storage:Michelson_v1_parser.parsed ->
|
||||||
input:Michelson_v1_parser.parsed ->
|
input:Michelson_v1_parser.parsed ->
|
||||||
Block_services.block ->
|
unit ->
|
||||||
#Proto_alpha.rpc_context ->
|
|
||||||
(Script.expr *
|
(Script.expr *
|
||||||
internal_operation list *
|
internal_operation list *
|
||||||
Script_interpreter.execution_trace *
|
Script_interpreter.execution_trace *
|
||||||
@ -58,27 +62,31 @@ val print_trace_result :
|
|||||||
tzresult -> unit tzresult Lwt.t
|
tzresult -> unit tzresult Lwt.t
|
||||||
|
|
||||||
val hash_and_sign :
|
val hash_and_sign :
|
||||||
|
#Proto_alpha.full ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
|
Block_services.block ->
|
||||||
?gas:Z.t ->
|
?gas:Z.t ->
|
||||||
Michelson_v1_parser.parsed ->
|
Michelson_v1_parser.parsed ->
|
||||||
Michelson_v1_parser.parsed ->
|
Michelson_v1_parser.parsed ->
|
||||||
Client_keys.sk_uri ->
|
Client_keys.sk_uri ->
|
||||||
Block_services.block ->
|
|
||||||
#Proto_alpha.full ->
|
|
||||||
(string * string * Gas.t) tzresult Lwt.t
|
(string * string * Gas.t) tzresult Lwt.t
|
||||||
|
|
||||||
val typecheck_data :
|
val typecheck_data :
|
||||||
|
#Proto_alpha.rpc_context ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
|
Block_services.block ->
|
||||||
?gas:Z.t ->
|
?gas:Z.t ->
|
||||||
data:Michelson_v1_parser.parsed ->
|
data:Michelson_v1_parser.parsed ->
|
||||||
ty:Michelson_v1_parser.parsed ->
|
ty:Michelson_v1_parser.parsed ->
|
||||||
'a ->
|
unit ->
|
||||||
'a #Proto_alpha.Alpha_environment.RPC_context.simple ->
|
|
||||||
Gas.t tzresult Lwt.t
|
Gas.t tzresult Lwt.t
|
||||||
|
|
||||||
val typecheck_program :
|
val typecheck_program :
|
||||||
|
#Proto_alpha.rpc_context ->
|
||||||
|
?chain:Chain_services.chain ->
|
||||||
|
Block_services.block ->
|
||||||
?gas:Z.t ->
|
?gas:Z.t ->
|
||||||
Michelson_v1_parser.parsed ->
|
Michelson_v1_parser.parsed ->
|
||||||
Block_services.block ->
|
|
||||||
#Proto_alpha.rpc_context ->
|
|
||||||
(Script_tc_errors.type_map * Gas.t) tzresult Lwt.t
|
(Script_tc_errors.type_map * Gas.t) tzresult Lwt.t
|
||||||
|
|
||||||
val print_typecheck_result :
|
val print_typecheck_result :
|
||||||
|
@ -11,24 +11,24 @@ open Proto_alpha
|
|||||||
open Alpha_context
|
open Alpha_context
|
||||||
open Apply_operation_result
|
open Apply_operation_result
|
||||||
|
|
||||||
let get_branch rpc_config (block : Block_services.block) branch =
|
let get_branch (rpc_config: #Proto_alpha.full)
|
||||||
|
~chain ~(block : Block_services.block) branch =
|
||||||
let branch = Option.unopt ~default:0 branch in (* TODO export parameter *)
|
let branch = Option.unopt ~default:0 branch in (* TODO export parameter *)
|
||||||
begin
|
begin
|
||||||
match block with
|
match block with
|
||||||
| `Head n -> return (`Head (n+branch))
|
| `Head n -> return (`Head (n+branch))
|
||||||
| `Test_head n -> return (`Test_head (n+branch))
|
|
||||||
| `Hash (h,n) -> return (`Hash (h,n+branch))
|
| `Hash (h,n) -> return (`Hash (h,n+branch))
|
||||||
| `Genesis -> return `Genesis
|
| `Genesis -> return `Genesis
|
||||||
end >>=? fun block ->
|
end >>=? fun block ->
|
||||||
Block_services.hash rpc_config block >>=? fun hash ->
|
Block_services.hash rpc_config ~chain ~block () >>=? fun hash ->
|
||||||
return hash
|
return hash
|
||||||
|
|
||||||
type result = Operation_hash.t * operation * operation_result
|
type result = Operation_hash.t * operation * operation_result
|
||||||
|
|
||||||
let preapply
|
let preapply
|
||||||
cctxt block
|
(cctxt: #Proto_alpha.full) ~chain ~block
|
||||||
?branch ?src_sk contents =
|
?branch ?src_sk contents =
|
||||||
get_branch cctxt block branch >>=? fun branch ->
|
get_branch cctxt ~chain ~block branch >>=? fun branch ->
|
||||||
let bytes =
|
let bytes =
|
||||||
Data_encoding.Binary.to_bytes_exn
|
Data_encoding.Binary.to_bytes_exn
|
||||||
Operation.unsigned_encoding
|
Operation.unsigned_encoding
|
||||||
@ -51,9 +51,9 @@ let preapply
|
|||||||
{ shell = { branch } ;
|
{ shell = { branch } ;
|
||||||
protocol_data = { contents ; signature } } in
|
protocol_data = { contents ; signature } } in
|
||||||
let oph = Operation.hash op in
|
let oph = Operation.hash op in
|
||||||
Block_services.hash cctxt block >>=? fun bh ->
|
Block_services.hash cctxt ~chain ~block () >>=? fun bh ->
|
||||||
Alpha_services.Helpers.apply_operation cctxt
|
Alpha_services.Helpers.apply_operation cctxt
|
||||||
block bh oph bytes signature >>=? fun result ->
|
(chain, block) bh oph bytes signature >>=? fun result ->
|
||||||
return (oph, op, result)
|
return (oph, op, result)
|
||||||
|
|
||||||
let estimated_gas = function
|
let estimated_gas = function
|
||||||
@ -117,17 +117,18 @@ let detect_script_failure = function
|
|||||||
| _ -> Ok ()
|
| _ -> Ok ()
|
||||||
|
|
||||||
let may_patch_limits
|
let may_patch_limits
|
||||||
(cctxt : #Proto_alpha.full) block ?branch
|
(cctxt : #Proto_alpha.full) ~chain ~block ?branch
|
||||||
?src_sk contents =
|
?src_sk contents =
|
||||||
Alpha_services.Constants.hard_gas_limits cctxt block >>=? fun (_, gas_limit) ->
|
Alpha_services.Constants.hard_gas_limits cctxt (chain, block) >>=? fun (_, gas_limit) ->
|
||||||
Alpha_services.Constants.hard_storage_limits cctxt block >>=? fun (_, storage_limit) ->
|
Alpha_services.Constants.hard_storage_limits cctxt (chain, block) >>=? fun (_, storage_limit) ->
|
||||||
|
|
||||||
match contents with
|
match contents with
|
||||||
| Sourced_operation (Manager_operations c)
|
| Sourced_operation (Manager_operations c)
|
||||||
when c.gas_limit < Z.zero || gas_limit < c.gas_limit
|
when c.gas_limit < Z.zero || gas_limit < c.gas_limit
|
||||||
|| c.storage_limit < 0L || storage_limit < c.storage_limit ->
|
|| c.storage_limit < 0L || storage_limit < c.storage_limit ->
|
||||||
let contents =
|
let contents =
|
||||||
Sourced_operation (Manager_operations { c with gas_limit ; storage_limit }) in
|
Sourced_operation (Manager_operations { c with gas_limit ; storage_limit }) in
|
||||||
preapply cctxt block ?branch ?src_sk contents >>=? fun (_, _, result) ->
|
preapply cctxt ~chain ~block ?branch ?src_sk contents >>=? fun (_, _, result) ->
|
||||||
begin if c.gas_limit < Z.zero || gas_limit < c.gas_limit then
|
begin if c.gas_limit < Z.zero || gas_limit < c.gas_limit then
|
||||||
Lwt.return (estimated_gas result) >>=? fun gas ->
|
Lwt.return (estimated_gas result) >>=? fun gas ->
|
||||||
begin
|
begin
|
||||||
@ -160,11 +161,11 @@ let may_patch_limits
|
|||||||
| op -> return op
|
| op -> return op
|
||||||
|
|
||||||
let inject_operation
|
let inject_operation
|
||||||
cctxt block
|
cctxt ~chain ~block
|
||||||
?confirmations ?branch ?src_sk contents =
|
?confirmations ?branch ?src_sk contents =
|
||||||
may_patch_limits
|
may_patch_limits
|
||||||
cctxt block ?branch ?src_sk contents >>=? fun contents ->
|
cctxt ~chain ~block ?branch ?src_sk contents >>=? fun contents ->
|
||||||
preapply cctxt block
|
preapply cctxt ~chain ~block
|
||||||
?branch ?src_sk contents >>=? fun (_oph, op, result) ->
|
?branch ?src_sk contents >>=? fun (_oph, op, result) ->
|
||||||
begin match detect_script_failure result with
|
begin match detect_script_failure result with
|
||||||
| Ok () -> return ()
|
| Ok () -> return ()
|
||||||
@ -175,7 +176,7 @@ let inject_operation
|
|||||||
Lwt.return res
|
Lwt.return res
|
||||||
end >>=? fun () ->
|
end >>=? fun () ->
|
||||||
let bytes = Data_encoding.Binary.to_bytes_exn Operation.encoding op in
|
let bytes = Data_encoding.Binary.to_bytes_exn Operation.encoding op in
|
||||||
Block_services.chain_id cctxt block >>=? fun chain_id ->
|
Chain_services.chain_id cctxt ~chain () >>=? fun chain_id ->
|
||||||
Shell_services.inject_operation cctxt ~chain_id bytes >>=? fun oph ->
|
Shell_services.inject_operation cctxt ~chain_id bytes >>=? fun oph ->
|
||||||
cctxt#message "Operation successfully injected in the node." >>= fun () ->
|
cctxt#message "Operation successfully injected in the node." >>= fun () ->
|
||||||
cctxt#message "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
cctxt#message "Operation hash is '%a'." Operation_hash.pp oph >>= fun () ->
|
||||||
@ -185,7 +186,7 @@ let inject_operation
|
|||||||
| Some confirmations ->
|
| Some confirmations ->
|
||||||
cctxt#message "Waiting for the operation to be included..." >>= fun () ->
|
cctxt#message "Waiting for the operation to be included..." >>= fun () ->
|
||||||
Client_confirmations.wait_for_operation_inclusion
|
Client_confirmations.wait_for_operation_inclusion
|
||||||
~confirmations cctxt oph >>=? fun () ->
|
~confirmations cctxt ~chain oph >>=? fun () ->
|
||||||
return ()
|
return ()
|
||||||
end >>=? fun () ->
|
end >>=? fun () ->
|
||||||
cctxt#message
|
cctxt#message
|
||||||
|
@ -15,7 +15,8 @@ type result = Operation_hash.t * operation * operation_result
|
|||||||
|
|
||||||
val preapply:
|
val preapply:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?branch:int ->
|
?branch:int ->
|
||||||
?src_sk:Client_keys.sk_uri ->
|
?src_sk:Client_keys.sk_uri ->
|
||||||
Operation.contents ->
|
Operation.contents ->
|
||||||
@ -23,7 +24,8 @@ val preapply:
|
|||||||
|
|
||||||
val inject_operation:
|
val inject_operation:
|
||||||
#Proto_alpha.full ->
|
#Proto_alpha.full ->
|
||||||
Block_services.block ->
|
chain:Chain_services.chain ->
|
||||||
|
block:Block_services.block ->
|
||||||
?confirmations:int ->
|
?confirmations:int ->
|
||||||
?branch:int ->
|
?branch:int ->
|
||||||
?src_sk:Client_keys.sk_uri ->
|
?src_sk:Client_keys.sk_uri ->
|
||||||
|
@ -9,11 +9,16 @@
|
|||||||
|
|
||||||
module Name = struct let name = "alpha" end
|
module Name = struct let name = "alpha" end
|
||||||
module Alpha_environment = Tezos_protocol_environment_faked.MakeV1(Name)()
|
module Alpha_environment = Tezos_protocol_environment_faked.MakeV1(Name)()
|
||||||
include Tezos_protocol_alpha.Functor.Make(Alpha_environment)
|
module Proto = Tezos_protocol_alpha.Functor.Make(Alpha_environment)
|
||||||
|
module Block_services = struct
|
||||||
|
include Block_services
|
||||||
|
include Block_services.Make(Proto)(Proto)
|
||||||
|
end
|
||||||
|
include Proto
|
||||||
|
|
||||||
class type rpc_context = object
|
class type rpc_context = object
|
||||||
inherit RPC_context.json
|
inherit RPC_context.json
|
||||||
inherit [Block_services.block] Alpha_environment.RPC_context.simple
|
inherit [Chain_services.chain * Block_services.block] Alpha_environment.RPC_context.simple
|
||||||
end
|
end
|
||||||
|
|
||||||
class wrap_proto_context (t : RPC_context.json) : rpc_context = object
|
class wrap_proto_context (t : RPC_context.json) : rpc_context = object
|
||||||
@ -27,17 +32,20 @@ class wrap_proto_context (t : RPC_context.json) : rpc_context = object
|
|||||||
on_chunk: ('o -> unit) ->
|
on_chunk: ('o -> unit) ->
|
||||||
on_close: (unit -> unit) ->
|
on_close: (unit -> unit) ->
|
||||||
'p -> 'q -> 'i -> (unit -> unit) tzresult Lwt.t = t#call_streamed_service
|
'p -> 'q -> 'i -> (unit -> unit) tzresult Lwt.t = t#call_streamed_service
|
||||||
inherit [Block_services.block] Alpha_environment.proto_rpc_context
|
inherit [Chain_services.chain,
|
||||||
(t :> RPC_context.t) (Block_services.S.proto_path ())
|
Block_services.block] Alpha_environment.proto_rpc_context
|
||||||
|
(t :> RPC_context.t)
|
||||||
|
Block_services.path
|
||||||
end
|
end
|
||||||
|
|
||||||
class type full = object
|
class type full = object
|
||||||
inherit Client_context.full
|
inherit Client_context.full
|
||||||
inherit [Block_services.block] Alpha_environment.RPC_context.simple
|
inherit [Chain_services.chain * Block_services.block] Alpha_environment.RPC_context.simple
|
||||||
end
|
end
|
||||||
|
|
||||||
class wrap_full (t : Client_context.full) : full = object
|
class wrap_full (t : Client_context.full) : full = object
|
||||||
inherit Client_context.proxy_context t
|
inherit Client_context.proxy_context t
|
||||||
inherit [Block_services.block] Alpha_environment.proto_rpc_context
|
inherit [Chain_services.chain, Block_services.block] Alpha_environment.proto_rpc_context
|
||||||
(t :> RPC_context.t) (Block_services.S.proto_path ())
|
(t :> RPC_context.t)
|
||||||
|
Block_services.path
|
||||||
end
|
end
|
||||||
|
@ -56,8 +56,8 @@ let commands () =
|
|||||||
(switch ~doc:"output time in seconds" ~short:'s' ~long:"seconds" ()))
|
(switch ~doc:"output time in seconds" ~short:'s' ~long:"seconds" ()))
|
||||||
(fixed [ "get" ; "timestamp" ])
|
(fixed [ "get" ; "timestamp" ])
|
||||||
begin fun seconds (cctxt : Proto_alpha.full) ->
|
begin fun seconds (cctxt : Proto_alpha.full) ->
|
||||||
Block_services.timestamp
|
Block_services.Header.Shell.timestamp
|
||||||
cctxt cctxt#block >>=? fun v ->
|
cctxt ~block:cctxt#block () >>=? fun v ->
|
||||||
begin
|
begin
|
||||||
if seconds
|
if seconds
|
||||||
then cctxt#message "%Ld" (Time.to_seconds v)
|
then cctxt#message "%Ld" (Time.to_seconds v)
|
||||||
@ -70,7 +70,8 @@ let commands () =
|
|||||||
no_options
|
no_options
|
||||||
(fixed [ "list" ; "contracts" ])
|
(fixed [ "list" ; "contracts" ])
|
||||||
begin fun () (cctxt : Proto_alpha.full) ->
|
begin fun () (cctxt : Proto_alpha.full) ->
|
||||||
list_contract_labels cctxt cctxt#block >>=? fun contracts ->
|
list_contract_labels cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block >>=? fun contracts ->
|
||||||
Lwt_list.iter_s
|
Lwt_list.iter_s
|
||||||
(fun (alias, hash, kind) -> cctxt#message "%s%s%s" hash kind alias)
|
(fun (alias, hash, kind) -> cctxt#message "%s%s%s" hash kind alias)
|
||||||
contracts >>= fun () ->
|
contracts >>= fun () ->
|
||||||
@ -83,7 +84,9 @@ let commands () =
|
|||||||
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun () (_, contract) (cctxt : Proto_alpha.full) ->
|
begin fun () (_, contract) (cctxt : Proto_alpha.full) ->
|
||||||
get_balance cctxt cctxt#block contract >>=? fun amount ->
|
get_balance cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block
|
||||||
|
contract >>=? fun amount ->
|
||||||
cctxt#answer "%a %s" Tez.pp amount Client_proto_args.tez_sym >>= fun () ->
|
cctxt#answer "%a %s" Tez.pp amount Client_proto_args.tez_sym >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
end ;
|
end ;
|
||||||
@ -94,7 +97,9 @@ let commands () =
|
|||||||
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun () (_, contract) (cctxt : Proto_alpha.full) ->
|
begin fun () (_, contract) (cctxt : Proto_alpha.full) ->
|
||||||
get_storage cctxt cctxt#block contract >>=? function
|
get_storage cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block
|
||||||
|
contract >>=? function
|
||||||
| None ->
|
| None ->
|
||||||
cctxt#error "This is not a smart contract."
|
cctxt#error "This is not a smart contract."
|
||||||
| Some storage ->
|
| Some storage ->
|
||||||
@ -108,8 +113,9 @@ let commands () =
|
|||||||
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun () (_, contract) (cctxt : Proto_alpha.full) ->
|
begin fun () (_, contract) (cctxt : Proto_alpha.full) ->
|
||||||
Client_proto_contracts.get_manager
|
Client_proto_contracts.get_manager cctxt
|
||||||
cctxt cctxt#block contract >>=? fun manager ->
|
~chain:`Main ~block:cctxt#block
|
||||||
|
contract >>=? fun manager ->
|
||||||
Public_key_hash.rev_find cctxt manager >>=? fun mn ->
|
Public_key_hash.rev_find cctxt manager >>=? fun mn ->
|
||||||
Public_key_hash.to_source manager >>=? fun m ->
|
Public_key_hash.to_source manager >>=? fun m ->
|
||||||
cctxt#message "%s (%s)" m
|
cctxt#message "%s (%s)" m
|
||||||
@ -123,8 +129,9 @@ let commands () =
|
|||||||
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun () (_, contract) (cctxt : Proto_alpha.full) ->
|
begin fun () (_, contract) (cctxt : Proto_alpha.full) ->
|
||||||
Client_proto_contracts.get_delegate
|
Client_proto_contracts.get_delegate cctxt
|
||||||
cctxt cctxt#block contract >>=? function
|
~chain:`Main ~block:cctxt#block
|
||||||
|
contract >>=? function
|
||||||
| None ->
|
| None ->
|
||||||
cctxt#message "none" >>= fun () ->
|
cctxt#message "none" >>= fun () ->
|
||||||
return ()
|
return ()
|
||||||
@ -145,9 +152,11 @@ let commands () =
|
|||||||
~name: "mgr" ~desc: "new delegate of the contract"
|
~name: "mgr" ~desc: "new delegate of the contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun fee (_, contract) (_, delegate) (cctxt : Proto_alpha.full) ->
|
begin fun fee (_, contract) (_, delegate) (cctxt : Proto_alpha.full) ->
|
||||||
source_to_keys cctxt cctxt#block contract >>=? fun (src_pk, manager_sk) ->
|
source_to_keys cctxt
|
||||||
set_delegate
|
~chain:`Main ~block:cctxt#block
|
||||||
cctxt cctxt#block ?confirmations:cctxt#confirmations
|
contract >>=? fun (src_pk, manager_sk) ->
|
||||||
|
set_delegate cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block ?confirmations:cctxt#confirmations
|
||||||
contract (Some delegate) ~fee ~src_pk ~manager_sk >>=? fun _ ->
|
contract (Some delegate) ~fee ~src_pk ~manager_sk >>=? fun _ ->
|
||||||
return ()
|
return ()
|
||||||
end ;
|
end ;
|
||||||
@ -158,9 +167,11 @@ let commands () =
|
|||||||
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
@@ ContractAlias.destination_param ~name:"src" ~desc:"source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun fee (_, contract) (cctxt : Proto_alpha.full) ->
|
begin fun fee (_, contract) (cctxt : Proto_alpha.full) ->
|
||||||
source_to_keys cctxt cctxt#block contract >>=? fun (src_pk, manager_sk) ->
|
source_to_keys cctxt
|
||||||
set_delegate
|
~chain:`Main ~block:cctxt#block
|
||||||
cctxt cctxt#block ?confirmations:cctxt#confirmations
|
contract >>=? fun (src_pk, manager_sk) ->
|
||||||
|
set_delegate cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block ?confirmations:cctxt#confirmations
|
||||||
contract None ~fee ~src_pk ~manager_sk >>=? fun _ ->
|
contract None ~fee ~src_pk ~manager_sk >>=? fun _ ->
|
||||||
return ()
|
return ()
|
||||||
end ;
|
end ;
|
||||||
@ -183,20 +194,13 @@ let commands () =
|
|||||||
begin fun (fee, delegate, delegatable, force)
|
begin fun (fee, delegate, delegatable, force)
|
||||||
new_contract manager_pkh balance (_, source) (cctxt : Proto_alpha.full) ->
|
new_contract manager_pkh balance (_, source) (cctxt : Proto_alpha.full) ->
|
||||||
RawContractAlias.of_fresh cctxt force new_contract >>=? fun alias_name ->
|
RawContractAlias.of_fresh cctxt force new_contract >>=? fun alias_name ->
|
||||||
source_to_keys cctxt cctxt#block source >>=? fun (src_pk, src_sk) ->
|
source_to_keys cctxt
|
||||||
originate_account
|
~chain:`Main ~block:cctxt#block
|
||||||
cctxt
|
source >>=? fun (src_pk, src_sk) ->
|
||||||
cctxt#block
|
originate_account cctxt
|
||||||
?confirmations:cctxt#confirmations
|
~chain:`Main ~block:cctxt#block ?confirmations:cctxt#confirmations
|
||||||
~fee
|
~fee ?delegate ~delegatable ~manager_pkh ~balance
|
||||||
?delegate
|
~source ~src_pk ~src_sk () >>=? fun (_res, contract) ->
|
||||||
~delegatable
|
|
||||||
~manager_pkh
|
|
||||||
~balance
|
|
||||||
~source
|
|
||||||
~src_pk
|
|
||||||
~src_sk
|
|
||||||
() >>=? fun (_res, contract) ->
|
|
||||||
save_contract ~force cctxt alias_name contract >>=? fun () ->
|
save_contract ~force cctxt alias_name contract >>=? fun () ->
|
||||||
return ()
|
return ()
|
||||||
end ;
|
end ;
|
||||||
@ -226,8 +230,11 @@ let commands () =
|
|||||||
alias_name manager balance (_, source) program (cctxt : Proto_alpha.full) ->
|
alias_name manager balance (_, source) program (cctxt : Proto_alpha.full) ->
|
||||||
RawContractAlias.of_fresh cctxt force alias_name >>=? fun alias_name ->
|
RawContractAlias.of_fresh cctxt force alias_name >>=? fun alias_name ->
|
||||||
Lwt.return (Micheline_parser.no_parsing_error program) >>=? fun { expanded = code } ->
|
Lwt.return (Micheline_parser.no_parsing_error program) >>=? fun { expanded = code } ->
|
||||||
source_to_keys cctxt cctxt#block source >>=? fun (src_pk, src_sk) ->
|
source_to_keys cctxt
|
||||||
originate_contract cctxt cctxt#block ?confirmations:cctxt#confirmations
|
~chain:`Main ~block:cctxt#block
|
||||||
|
source >>=? fun (src_pk, src_sk) ->
|
||||||
|
originate_contract cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block ?confirmations:cctxt#confirmations
|
||||||
~fee ?gas_limit ?storage_limit ~delegate ~delegatable ~spendable ~initial_storage
|
~fee ?gas_limit ?storage_limit ~delegate ~delegatable ~spendable ~initial_storage
|
||||||
~manager ~balance ~source ~src_pk ~src_sk ~code () >>= fun errors ->
|
~manager ~balance ~source ~src_pk ~src_sk ~code () >>= fun errors ->
|
||||||
report_michelson_errors ~no_print_source ~msg:"origination simulation failed" cctxt errors >>= function
|
report_michelson_errors ~no_print_source ~msg:"origination simulation failed" cctxt errors >>= function
|
||||||
@ -250,8 +257,11 @@ let commands () =
|
|||||||
~name: "dst" ~desc: "name/literal of the destination contract"
|
~name: "dst" ~desc: "name/literal of the destination contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun (fee, gas_limit, storage_limit, arg, no_print_source) amount (_, source) (_, destination) cctxt ->
|
begin fun (fee, gas_limit, storage_limit, arg, no_print_source) amount (_, source) (_, destination) cctxt ->
|
||||||
source_to_keys cctxt cctxt#block source >>=? fun (src_pk, src_sk) ->
|
source_to_keys cctxt
|
||||||
transfer cctxt cctxt#block ?confirmations:cctxt#confirmations
|
~chain:`Main ~block:cctxt#block
|
||||||
|
source >>=? fun (src_pk, src_sk) ->
|
||||||
|
transfer cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block ?confirmations:cctxt#confirmations
|
||||||
~source ~fee ~src_pk ~src_sk ~destination ~arg ~amount ?gas_limit ?storage_limit () >>=
|
~source ~fee ~src_pk ~src_sk ~destination ~arg ~amount ?gas_limit ?storage_limit () >>=
|
||||||
report_michelson_errors ~no_print_source ~msg:"transfer simulation failed" cctxt >>= function
|
report_michelson_errors ~no_print_source ~msg:"transfer simulation failed" cctxt >>= function
|
||||||
| None -> return ()
|
| None -> return ()
|
||||||
@ -266,8 +276,11 @@ let commands () =
|
|||||||
~name: "src" ~desc: "name of the source contract"
|
~name: "src" ~desc: "name of the source contract"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun fee (_, source) cctxt ->
|
begin fun fee (_, source) cctxt ->
|
||||||
source_to_keys cctxt cctxt#block source >>=? fun (src_pk, src_sk) ->
|
source_to_keys cctxt
|
||||||
reveal cctxt cctxt#block ?confirmations:cctxt#confirmations
|
~chain:`Main ~block:cctxt#block
|
||||||
|
source >>=? fun (src_pk, src_sk) ->
|
||||||
|
reveal cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block ?confirmations:cctxt#confirmations
|
||||||
~source ~fee ~src_pk ~src_sk () >>=? fun _res ->
|
~source ~fee ~src_pk ~src_sk () >>=? fun _res ->
|
||||||
return ()
|
return ()
|
||||||
end;
|
end;
|
||||||
@ -281,8 +294,9 @@ let commands () =
|
|||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun fee src_pkh cctxt ->
|
begin fun fee src_pkh cctxt ->
|
||||||
Client_keys.get_key cctxt src_pkh >>=? fun (_, src_pk, src_sk) ->
|
Client_keys.get_key cctxt src_pkh >>=? fun (_, src_pk, src_sk) ->
|
||||||
register_as_delegate cctxt ?confirmations:cctxt#confirmations
|
register_as_delegate cctxt
|
||||||
~fee cctxt#block ~manager_sk:src_sk src_pk >>=? fun _res ->
|
~chain:`Main ~block:cctxt#block ?confirmations:cctxt#confirmations
|
||||||
|
~fee ~manager_sk:src_sk src_pk >>=? fun _res ->
|
||||||
return ()
|
return ()
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -309,8 +323,8 @@ let commands () =
|
|||||||
(fun ppf -> Data_encoding.Json.print_error ppf) exn
|
(fun ppf -> Data_encoding.Json.print_error ppf) exn
|
||||||
Data_encoding.Json.pp json
|
Data_encoding.Json.pp json
|
||||||
| key ->
|
| key ->
|
||||||
claim_commitment
|
claim_commitment cctxt
|
||||||
cctxt cctxt#block ?confirmations:cctxt#confirmations
|
~chain:`Main ~block:cctxt#block ?confirmations:cctxt#confirmations
|
||||||
~encrypted ~force key name >>=? fun _res ->
|
~encrypted ~force key name >>=? fun _res ->
|
||||||
return ()
|
return ()
|
||||||
);
|
);
|
||||||
@ -325,7 +339,8 @@ let commands () =
|
|||||||
~name:"password" ~desc:"dictator's key"
|
~name:"password" ~desc:"dictator's key"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun () hash seckey cctxt ->
|
begin fun () hash seckey cctxt ->
|
||||||
dictate cctxt cctxt#block
|
dictate cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block
|
||||||
(Activate hash) seckey >>=? fun _ ->
|
(Activate hash) seckey >>=? fun _ ->
|
||||||
return ()
|
return ()
|
||||||
end ;
|
end ;
|
||||||
@ -366,7 +381,7 @@ let commands () =
|
|||||||
fail_when (predecessors < 0)
|
fail_when (predecessors < 0)
|
||||||
(failure "check-previous cannot be negative") >>=? fun () ->
|
(failure "check-previous cannot be negative") >>=? fun () ->
|
||||||
Client_confirmations.wait_for_operation_inclusion ctxt
|
Client_confirmations.wait_for_operation_inclusion ctxt
|
||||||
~confirmations ~predecessors operation_hash >>=? fun _ ->
|
~chain:`Main ~confirmations ~predecessors operation_hash >>=? fun _ ->
|
||||||
return ()
|
return ()
|
||||||
end ;
|
end ;
|
||||||
|
|
||||||
@ -380,7 +395,8 @@ let commands () =
|
|||||||
~name:"password" ~desc:"dictator's key"
|
~name:"password" ~desc:"dictator's key"
|
||||||
@@ stop)
|
@@ stop)
|
||||||
begin fun () hash seckey cctxt ->
|
begin fun () hash seckey cctxt ->
|
||||||
dictate cctxt cctxt#block
|
dictate cctxt
|
||||||
|
~chain:`Main ~block:cctxt#block
|
||||||
(Activate_testchain hash) seckey >>=? fun _res ->
|
(Activate_testchain hash) seckey >>=? fun _res ->
|
||||||
return ()
|
return ()
|
||||||
end ;
|
end ;
|
||||||
|
@ -55,7 +55,7 @@ let commands () =
|
|||||||
with _ -> failwith "invalid gas limit (must be a positive number)")) in
|
with _ -> failwith "invalid gas limit (must be a positive number)")) in
|
||||||
let resolve_max_gas cctxt block = function
|
let resolve_max_gas cctxt block = function
|
||||||
| None ->
|
| None ->
|
||||||
Alpha_services.Constants.hard_gas_limits cctxt block >>=? fun (_, gas) ->
|
Alpha_services.Constants.hard_gas_limits cctxt (`Main, block) >>=? fun (_, gas) ->
|
||||||
return gas
|
return gas
|
||||||
| Some gas -> return gas in
|
| Some gas -> return gas in
|
||||||
let data_parameter =
|
let data_parameter =
|
||||||
@ -123,10 +123,10 @@ let commands () =
|
|||||||
Lwt.return @@ Micheline_parser.no_parsing_error program >>=? fun program ->
|
Lwt.return @@ Micheline_parser.no_parsing_error program >>=? fun program ->
|
||||||
let show_source = not no_print_source in
|
let show_source = not no_print_source in
|
||||||
(if trace_exec then
|
(if trace_exec then
|
||||||
trace ~amount ~program ~storage ~input cctxt#block cctxt >>= fun res ->
|
trace cctxt cctxt#block ~amount ~program ~storage ~input () >>= fun res ->
|
||||||
print_trace_result cctxt ~show_source ~parsed:program res
|
print_trace_result cctxt ~show_source ~parsed:program res
|
||||||
else
|
else
|
||||||
run ~amount ~program ~storage ~input cctxt#block cctxt >>= fun res ->
|
run cctxt cctxt#block ~amount ~program ~storage ~input () >>= fun res ->
|
||||||
print_run_result cctxt ~show_source ~parsed:program res)) ;
|
print_run_result cctxt ~show_source ~parsed:program res)) ;
|
||||||
command ~group ~desc: "Ask the node to typecheck a program."
|
command ~group ~desc: "Ask the node to typecheck a program."
|
||||||
(args4 show_types_switch emacs_mode_switch no_print_source_flag custom_gas_flag)
|
(args4 show_types_switch emacs_mode_switch no_print_source_flag custom_gas_flag)
|
||||||
@ -137,7 +137,7 @@ let commands () =
|
|||||||
match program with
|
match program with
|
||||||
| program, [] ->
|
| program, [] ->
|
||||||
resolve_max_gas cctxt cctxt#block original_gas >>=? fun original_gas ->
|
resolve_max_gas cctxt cctxt#block original_gas >>=? fun original_gas ->
|
||||||
typecheck_program ~gas:original_gas program cctxt#block cctxt >>= fun res ->
|
typecheck_program cctxt cctxt#block ~gas:original_gas program >>= fun res ->
|
||||||
print_typecheck_result
|
print_typecheck_result
|
||||||
~emacs:emacs_mode
|
~emacs:emacs_mode
|
||||||
~show_types
|
~show_types
|
||||||
@ -171,7 +171,8 @@ let commands () =
|
|||||||
@@ stop)
|
@@ stop)
|
||||||
(fun (no_print_source, custom_gas) data ty cctxt ->
|
(fun (no_print_source, custom_gas) data ty cctxt ->
|
||||||
resolve_max_gas cctxt cctxt#block custom_gas >>=? fun original_gas ->
|
resolve_max_gas cctxt cctxt#block custom_gas >>=? fun original_gas ->
|
||||||
Client_proto_programs.typecheck_data ~gas:original_gas ~data ~ty cctxt#block cctxt >>= function
|
Client_proto_programs.typecheck_data cctxt cctxt#block
|
||||||
|
~gas:original_gas ~data ~ty () >>= function
|
||||||
| Ok gas ->
|
| Ok gas ->
|
||||||
cctxt#message "@[<v 0>Well typed@,Gas remaining: %a@]"
|
cctxt#message "@[<v 0>Well typed@,Gas remaining: %a@]"
|
||||||
Proto_alpha.Alpha_context.Gas.pp gas >>= fun () ->
|
Proto_alpha.Alpha_context.Gas.pp gas >>= fun () ->
|
||||||
@ -198,8 +199,8 @@ let commands () =
|
|||||||
@@ stop)
|
@@ stop)
|
||||||
(fun custom_gas data typ cctxt ->
|
(fun custom_gas data typ cctxt ->
|
||||||
resolve_max_gas cctxt cctxt#block custom_gas >>=? fun original_gas ->
|
resolve_max_gas cctxt cctxt#block custom_gas >>=? fun original_gas ->
|
||||||
Alpha_services.Helpers.hash_data cctxt
|
Alpha_services.Helpers.hash_data cctxt (`Main, cctxt#block)
|
||||||
cctxt#block (data.expanded, typ.expanded, Some original_gas) >>= function
|
(data.expanded, typ.expanded, Some original_gas) >>= function
|
||||||
| Ok (hash, remaining_gas) ->
|
| Ok (hash, remaining_gas) ->
|
||||||
cctxt#message "%S@,Gas remaining: %a" hash
|
cctxt#message "%S@,Gas remaining: %a" hash
|
||||||
Proto_alpha.Alpha_context.Gas.pp remaining_gas >>= fun () ->
|
Proto_alpha.Alpha_context.Gas.pp remaining_gas >>= fun () ->
|
||||||
@ -231,7 +232,8 @@ let commands () =
|
|||||||
@@ stop)
|
@@ stop)
|
||||||
(fun gas data typ sk cctxt ->
|
(fun gas data typ sk cctxt ->
|
||||||
resolve_max_gas cctxt cctxt#block gas >>=? fun gas ->
|
resolve_max_gas cctxt cctxt#block gas >>=? fun gas ->
|
||||||
Client_proto_programs.hash_and_sign ~gas data typ sk cctxt#block cctxt >>= begin function
|
Client_proto_programs.hash_and_sign cctxt cctxt#block
|
||||||
|
~gas data typ sk >>= begin function
|
||||||
| Ok (hash, signature, current_gas) ->
|
| Ok (hash, signature, current_gas) ->
|
||||||
cctxt#message "@[<v 0>Hash: %S@,Signature: %S@,Remaining gas: %a@]"
|
cctxt#message "@[<v 0>Hash: %S@,Signature: %S@,Remaining gas: %a@]"
|
||||||
hash signature
|
hash signature
|
||||||
|
@ -11,98 +11,6 @@ open Alpha_context
|
|||||||
|
|
||||||
let custom_root = RPC_path.open_root
|
let custom_root = RPC_path.open_root
|
||||||
|
|
||||||
module S = struct
|
|
||||||
|
|
||||||
open Data_encoding
|
|
||||||
|
|
||||||
let operations =
|
|
||||||
RPC_service.post_service
|
|
||||||
~description: "All the operations of the block (fully decoded)."
|
|
||||||
~query: RPC_query.empty
|
|
||||||
~input: empty
|
|
||||||
~output: (list (list (merge_objs
|
|
||||||
(obj1 (req "hash" Operation_hash.encoding))
|
|
||||||
(dynamic_size Operation.encoding))))
|
|
||||||
RPC_path.(custom_root / "operations")
|
|
||||||
|
|
||||||
let header =
|
|
||||||
RPC_service.post_service
|
|
||||||
~description: "The header of the block (fully decoded)."
|
|
||||||
~query: RPC_query.empty
|
|
||||||
~input: empty
|
|
||||||
~output: Block_header.encoding
|
|
||||||
RPC_path.(custom_root / "header")
|
|
||||||
|
|
||||||
let priority =
|
|
||||||
RPC_service.post_service
|
|
||||||
~description: "Baking priority of the block."
|
|
||||||
~query: RPC_query.empty
|
|
||||||
~input: empty
|
|
||||||
~output: (obj1 (req "priority" uint16))
|
|
||||||
RPC_path.(custom_root / "header" / "priority")
|
|
||||||
|
|
||||||
let seed_nonce_hash =
|
|
||||||
RPC_service.post_service
|
|
||||||
~description: "Hash of the seed nonce of the block."
|
|
||||||
~query: RPC_query.empty
|
|
||||||
~input: empty
|
|
||||||
~output: Nonce_hash.encoding
|
|
||||||
RPC_path.(custom_root / "header" / "seed_nonce_hash")
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
let parse_operation (op: Operation.raw) =
|
|
||||||
match Data_encoding.Binary.of_bytes
|
|
||||||
Operation.protocol_data_encoding
|
|
||||||
op.proto with
|
|
||||||
| Some protocol_data ->
|
|
||||||
ok { shell = op.shell ; protocol_data }
|
|
||||||
| None -> error Helpers_services.Cannot_parse_operation
|
|
||||||
|
|
||||||
let parse_block_header
|
|
||||||
({ shell ; protocol_data } : Block_header.raw) : Block_header.t tzresult =
|
|
||||||
match
|
|
||||||
Data_encoding.Binary.of_bytes
|
|
||||||
Block_header.protocol_data_encoding
|
|
||||||
protocol_data
|
|
||||||
with
|
|
||||||
| None -> Error [Helpers_services.Cant_parse_block_header]
|
|
||||||
| Some protocol_data -> Ok { shell ; protocol_data }
|
|
||||||
|
|
||||||
|
|
||||||
let () =
|
|
||||||
let open Services_registration in
|
|
||||||
register0_fullctxt S.operations begin fun ctxt () () ->
|
|
||||||
ctxt.operation_hashes () >>= fun operation_hashes ->
|
|
||||||
ctxt.operations () >>= fun operations ->
|
|
||||||
map2_s
|
|
||||||
(map2_s (fun h op ->
|
|
||||||
Lwt.return (parse_operation op) >>=? fun op ->
|
|
||||||
return (h, op)))
|
|
||||||
operation_hashes operations
|
|
||||||
end ;
|
|
||||||
register0_fullctxt S.header begin fun { block_header ; _ } () () ->
|
|
||||||
Lwt.return (parse_block_header block_header) >>=? fun block_header ->
|
|
||||||
return block_header
|
|
||||||
end ;
|
|
||||||
register0_fullctxt S.priority begin fun { block_header ; _ } () () ->
|
|
||||||
Lwt.return (parse_block_header block_header) >>=? fun block_header ->
|
|
||||||
return block_header.protocol_data.contents.priority
|
|
||||||
end ;
|
|
||||||
opt_register0_fullctxt S.seed_nonce_hash begin fun { block_header ; _ } () ( )->
|
|
||||||
Lwt.return (parse_block_header block_header) >>=? fun block_header ->
|
|
||||||
return block_header.protocol_data.contents.seed_nonce_hash
|
|
||||||
end
|
|
||||||
|
|
||||||
let operations ctxt block =
|
|
||||||
RPC_context.make_call0 S.operations ctxt block () ()
|
|
||||||
let header ctxt block =
|
|
||||||
RPC_context.make_call0 S.header ctxt block () ()
|
|
||||||
let priority ctxt block =
|
|
||||||
RPC_context.make_call0 S.priority ctxt block () ()
|
|
||||||
let seed_nonce_hash ctxt block =
|
|
||||||
RPC_context.make_call0 S.seed_nonce_hash ctxt block () ()
|
|
||||||
|
|
||||||
module Context = struct
|
module Context = struct
|
||||||
|
|
||||||
module S = struct
|
module S = struct
|
||||||
|
@ -9,15 +9,6 @@
|
|||||||
|
|
||||||
open Alpha_context
|
open Alpha_context
|
||||||
|
|
||||||
val operations:
|
|
||||||
'a #RPC_context.simple -> 'a -> (Operation_hash.t * Operation.t) list list shell_tzresult Lwt.t
|
|
||||||
val header:
|
|
||||||
'a #RPC_context.simple -> 'a -> Block_header.t shell_tzresult Lwt.t
|
|
||||||
val priority:
|
|
||||||
'a #RPC_context.simple -> 'a -> int shell_tzresult Lwt.t
|
|
||||||
val seed_nonce_hash:
|
|
||||||
'a #RPC_context.simple -> 'a -> Nonce_hash.t shell_tzresult Lwt.t
|
|
||||||
|
|
||||||
module Context : sig
|
module Context : sig
|
||||||
|
|
||||||
val level:
|
val level:
|
||||||
|
@ -99,13 +99,30 @@ let metadata_encoding =
|
|||||||
(** Constants *)
|
(** Constants *)
|
||||||
|
|
||||||
let max_header_length =
|
let max_header_length =
|
||||||
let fake = { priority = 0 ;
|
let fake_shell = {
|
||||||
|
Block_header.level = 0l ;
|
||||||
|
proto_level = 0 ;
|
||||||
|
predecessor = Block_hash.zero ;
|
||||||
|
timestamp = Time.of_seconds 0L ;
|
||||||
|
validation_passes = 0 ;
|
||||||
|
operations_hash = Operation_list_list_hash.zero ;
|
||||||
|
fitness = Fitness_repr.from_int64 0L ;
|
||||||
|
context = Context_hash.zero ;
|
||||||
|
}
|
||||||
|
and fake_contents =
|
||||||
|
{ priority = 0 ;
|
||||||
proof_of_work_nonce =
|
proof_of_work_nonce =
|
||||||
MBytes.create Constants_repr.proof_of_work_nonce_size ;
|
MBytes.create Constants_repr.proof_of_work_nonce_size ;
|
||||||
seed_nonce_hash = Some Nonce_hash.zero } in
|
seed_nonce_hash = Some Nonce_hash.zero
|
||||||
|
} in
|
||||||
Data_encoding.Binary.length
|
Data_encoding.Binary.length
|
||||||
protocol_data_encoding
|
encoding
|
||||||
{ contents = fake ; signature = Signature.zero}
|
{ shell = fake_shell ;
|
||||||
|
protocol_data = {
|
||||||
|
contents = fake_contents ;
|
||||||
|
signature = Signature.zero ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
(** Header parsing entry point *)
|
(** Header parsing entry point *)
|
||||||
|
|
||||||
|
@ -11,20 +11,17 @@ open Alpha_context
|
|||||||
|
|
||||||
type rpc_context = {
|
type rpc_context = {
|
||||||
block_hash: Block_hash.t ;
|
block_hash: Block_hash.t ;
|
||||||
block_header: Block_header.raw ;
|
block_header: Block_header.shell_header ;
|
||||||
operation_hashes: unit -> Operation_hash.t list list Lwt.t ;
|
|
||||||
operations: unit -> Operation.raw list list Lwt.t ;
|
|
||||||
context: Alpha_context.t ;
|
context: Alpha_context.t ;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rpc_init (rpc_context : Updater.rpc_context Lwt.t) =
|
let rpc_init (rpc_context : Updater.rpc_context Lwt.t) =
|
||||||
rpc_context >>= fun { block_hash ; block_header ;
|
rpc_context >>= fun { block_hash ; block_header ; context } ->
|
||||||
operation_hashes ; operations ; context } ->
|
let level = block_header.level in
|
||||||
let level = block_header.shell.level in
|
let timestamp = block_header.timestamp in
|
||||||
let timestamp = block_header.shell.timestamp in
|
let fitness = block_header.fitness in
|
||||||
let fitness = block_header.shell.fitness in
|
|
||||||
Alpha_context.prepare ~level ~timestamp ~fitness context >>=? fun context ->
|
Alpha_context.prepare ~level ~timestamp ~fitness context >>=? fun context ->
|
||||||
return { block_hash ; block_header ; operation_hashes ; operations ; context }
|
return { block_hash ; block_header ; context }
|
||||||
|
|
||||||
let rpc_services = ref (RPC_directory.empty : Updater.rpc_context Lwt.t RPC_directory.t)
|
let rpc_services = ref (RPC_directory.empty : Updater.rpc_context Lwt.t RPC_directory.t)
|
||||||
|
|
||||||
|
@ -21,13 +21,9 @@ type t = {
|
|||||||
type block = t
|
type block = t
|
||||||
|
|
||||||
let rpc_context block =
|
let rpc_context block =
|
||||||
let operations_hashes =
|
|
||||||
lazy [ List.map Operation.hash block.operations ] in
|
|
||||||
Lwt.return {
|
Lwt.return {
|
||||||
Alpha_environment.Updater.block_hash = block.hash ;
|
Alpha_environment.Updater.block_hash = block.hash ;
|
||||||
block_header = (Block_header.raw block.header) ;
|
block_header = block.header.shell ;
|
||||||
operation_hashes = (fun () -> Lwt.return (Lazy.force operations_hashes)) ;
|
|
||||||
operations = (fun () -> Lwt.return [ List.map Operation.raw block.operations ]) ;
|
|
||||||
context = block.context ;
|
context = block.context ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,19 +24,10 @@ let predecessor { predecessor ; _ } = predecessor
|
|||||||
let level st = st.header.shell.level
|
let level st = st.header.shell.level
|
||||||
|
|
||||||
let rpc_context st =
|
let rpc_context st =
|
||||||
let operations = lazy (List.rev st.rev_operations) in
|
|
||||||
let operations_hashes =
|
|
||||||
lazy (List.map Operation.hash (Lazy.force operations)) in
|
|
||||||
let result = Alpha_context.finalize st.state.ctxt in
|
let result = Alpha_context.finalize st.state.ctxt in
|
||||||
Lwt.return {
|
Lwt.return {
|
||||||
Alpha_environment.Updater.block_hash = Block_hash.zero ;
|
Alpha_environment.Updater.block_hash = Block_hash.zero ;
|
||||||
block_header =
|
block_header = { st.header.shell with fitness = result.fitness } ;
|
||||||
Block_header.raw
|
|
||||||
{ st.header with
|
|
||||||
shell = { st.header.shell with fitness = result.fitness }} ;
|
|
||||||
operation_hashes = (fun () -> Lwt.return [Lazy.force operations_hashes]) ;
|
|
||||||
operations = (fun () ->
|
|
||||||
Lwt.return [List.map Operation.raw (Lazy.force operations)]) ;
|
|
||||||
context = result.context ;
|
context = result.context ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,13 +14,10 @@ let protocol =
|
|||||||
"ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im"
|
"ProtoGenesisGenesisGenesisGenesisGenesisGenesk612im"
|
||||||
|
|
||||||
let bake cctxt ?(timestamp = Time.now ()) block command sk =
|
let bake cctxt ?(timestamp = Time.now ()) block command sk =
|
||||||
let protocol_data =
|
let protocol_data = { command ; signature = Signature.zero } in
|
||||||
Data_encoding.Binary.to_bytes_exn
|
Block_services.Helpers.preapply
|
||||||
Proto_genesis.block_header_data_encoding
|
cctxt ~block ~timestamp ~protocol_data
|
||||||
{ command ; signature = Signature.zero } in
|
[] >>=? fun (shell_header, _) ->
|
||||||
Block_services.preapply
|
|
||||||
cctxt block ~timestamp ~protocol_data
|
|
||||||
[] >>=? fun { shell_header } ->
|
|
||||||
let blk = Data.Command.forge shell_header command in
|
let blk = Data.Command.forge shell_header command in
|
||||||
Client_keys.append sk blk >>=? fun signed_blk ->
|
Client_keys.append sk blk >>=? fun signed_blk ->
|
||||||
Shell_services.inject_block cctxt signed_blk []
|
Shell_services.inject_block cctxt signed_blk []
|
||||||
|
@ -9,4 +9,9 @@
|
|||||||
|
|
||||||
module Name = struct let name = "genesis" end
|
module Name = struct let name = "genesis" end
|
||||||
module Genesis_environment = Tezos_protocol_environment_faked.MakeV1(Name)()
|
module Genesis_environment = Tezos_protocol_environment_faked.MakeV1(Name)()
|
||||||
include Tezos_protocol_genesis.Functor.Make(Genesis_environment)
|
module Proto = Tezos_protocol_genesis.Functor.Make(Genesis_environment)
|
||||||
|
module Block_services = struct
|
||||||
|
include Block_services
|
||||||
|
include Block_services.Make(Proto)(Proto)
|
||||||
|
end
|
||||||
|
include Proto
|
||||||
|
Loading…
Reference in New Issue
Block a user