Revision c4ad0d4f5cebd9e299eee24646105093756f8937 authored by Andrea Cerone on 01 November 2022, 13:25:14 UTC, committed by Andrea Cerone on 02 November 2022, 00:34:02 UTC
1 parent 68c63dc
injection_services.ml
(*****************************************************************************)
(* *)
(* Open Source License *)
(* Copyright (c) 2018 Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* Permission is hereby granted, free of charge, to any person obtaining a *)
(* copy of this software and associated documentation files (the "Software"),*)
(* to deal in the Software without restriction, including without limitation *)
(* the rights to use, copy, modify, merge, publish, distribute, sublicense, *)
(* and/or sell copies of the Software, and to permit persons to whom the *)
(* Software is furnished to do so, subject to the following conditions: *)
(* *)
(* The above copyright notice and this permission notice shall be included *)
(* in all copies or substantial portions of the Software. *)
(* *)
(* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR*)
(* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *)
(* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *)
(* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER*)
(* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *)
(* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *)
(* DEALINGS IN THE SOFTWARE. *)
(* *)
(*****************************************************************************)
type Error_monad.error += Injection_operations_error
type Error_monad.error += Injection_operation_succeed_case of Operation_hash.t
type Error_monad.error += Injection_operation_error_case of Operation_hash.t
let () =
let open Data_encoding in
register_error_kind
`Permanent
~id:"injection_operations_error"
~title:"Injection operations error"
~description:
"While injecting several operations at once, one or several injections \
failed."
~pp:(fun ppf () ->
Format.fprintf
ppf
"While injecting several operations, one or several injections failed. \
Errors are the one below in the trace.")
unit
(function Injection_operations_error -> Some () | _ -> None)
(function () -> Injection_operations_error) ;
register_error_kind
`Permanent
~id:"injection_operation_succeed_case"
~title:"Injection operation succeed"
~description:
"The injection of this operation succeed among a list of injections \
containing at least one error."
~pp:(fun ppf oph ->
Format.fprintf ppf "Injection of %a succeeded." Operation_hash.pp oph)
(obj1 (req "oph" Operation_hash.encoding))
(function Injection_operation_succeed_case oph -> Some oph | _ -> None)
(function oph -> Injection_operation_succeed_case oph) ;
register_error_kind
`Permanent
~id:"injection_operation_error_case"
~title:"Injection operation error"
~description:
"The injection of this operation failed. The error trace are the \
following errors in this list."
~pp:(fun ppf oph ->
Format.fprintf
ppf
"Injection of %a failed. Error is next."
Operation_hash.pp
oph)
(obj1 (req "oph" Operation_hash.encoding))
(function Injection_operation_error_case oph -> Some oph | _ -> None)
(function oph -> Injection_operation_error_case oph)
module S = struct
open Data_encoding
let path = RPC_path.(root / "injection")
let block_query =
let open RPC_query in
query (fun async force chain ->
object
method async = async
method force = force
method chain = chain
end)
|+ flag "async" (fun t -> t#async)
|+ flag "force" (fun t -> t#force)
|+ opt_field "chain" Chain_services.chain_arg (fun t -> t#chain)
|> seal
let block_param =
obj2
(req "data" bytes)
(req
"operations"
(list (dynamic_size (list (dynamic_size Operation.encoding)))))
let block =
RPC_service.post_service
~description:
"Inject a block in the node and broadcast it. The `operations` \
embedded in `blockHeader` might be pre-validated using a contextual \
RPCs from the latest block (e.g. '/blocks/head/context/preapply'). \
Returns the ID of the block. By default, the RPC will wait for the \
block to be validated before answering. If ?async is true, the \
function returns immediately. Otherwise, the block will be validated \
before the result is returned. If ?force is true, it will be injected \
even on non strictly increasing fitness. An optional ?chain parameter \
can be used to specify whether to inject on the test chain or the \
main chain."
~query:block_query
~input:block_param
~output:Block_hash.encoding
RPC_path.(path / "block")
let operation_query =
let open RPC_query in
query (fun async chain ->
object
method async = async
method chain = chain
end)
|+ flag "async" (fun t -> t#async)
|+ opt_field "chain" Chain_services.chain_arg (fun t -> t#chain)
|> seal
let operations_query =
let open RPC_query in
query (fun async force chain ->
object
method async = async
method force = force
method chain = chain
end)
|+ flag "async" (fun t -> t#async)
|+ flag "force" (fun t -> t#force)
|+ opt_field "chain" Chain_services.chain_arg (fun t -> t#chain)
|> seal
(* If [private_] is set, the [private/injection/operation] path is used,
* otherwise, it is [/injection/operation].
This RPC does less checks than [injection/operation] and should be used for
test or internal use only. The [private/] prefix is used to forbid the use
of such RPC on a public node *)
let operation ~private_ =
RPC_service.post_service
~description:
"Inject an operation in node and broadcast it. Returns the ID of the \
operation. The `signedOperationContents` should be constructed using \
contextual RPCs from the latest block and signed by the client. The \
injection of the operation will apply it on the current mempool \
context. This context may change at each operation injection or \
operation reception from peers. By default, the RPC will wait for the \
operation to be (pre-)validated before returning. However, if ?async \
is true, the function returns immediately. The optional ?chain \
parameter can be used to specify whether to inject on the test chain \
or the main chain."
~query:operation_query
~input:bytes
~output:Operation_hash.encoding
(if private_ then RPC_path.(root / "private" / "injection" / "operation")
else RPC_path.(path / "operation"))
let private_operations =
RPC_service.post_service
~description:
"Inject a list of operations in a node. If [force] is [true] then the \
operations are immediatly injected. The injection will succeed, but \
it does not mean the operations are (all) valid. In any case, the \
injection will be quick, hence [async] will be taken into account but \
should have almost no impact. If [async] is [true], all the promises \
returned by injecting an operation will be dropped. Each injection is \
done independently, and does not depend on the other injected \
operations result. Otherwise ([async]=[force]=[false]), for each \
operation, we record a list of promises. If all the injections \
succeed, the result is the list of operation hashes injected, \
otherwise an error (\"injection_operations_error\") is returned. This \
error is followed by markers for each operation: \
\"injection_operation_succeed\" for success and \
\"injection_operation_error\" for failure (followed by the errors \
specific to this injection)."
~query:operations_query
~input:(list (dynamic_size bytes))
~output:(list Operation_hash.encoding)
RPC_path.(root / "private" / "injection" / "operations")
let private_operation = operation ~private_:true
let operation = operation ~private_:false
let protocol_query =
let open RPC_query in
query (fun async ->
object
method async = async
end)
|+ flag "async" (fun t -> t#async)
|> seal
let protocol =
RPC_service.post_service
~description:
"Inject a protocol in node. Returns the ID of the protocol. If ?async \
is true, the function returns immediately. Otherwise, the protocol \
will be validated before the result is returned."
~query:protocol_query
~input:Protocol.encoding
~output:Protocol_hash.encoding
RPC_path.(path / "protocol")
end
open RPC_context
let block ctxt ?(async = false) ?(force = false) ?chain raw operations =
make_call
S.block
ctxt
()
(object
method async = async
method force = force
method chain = chain
end)
(raw, operations)
let operation_rpc ctxt ~private_rpc ?(async = false) ?chain operation =
make_call
(if private_rpc then S.private_operation else S.operation)
ctxt
()
(object
method async = async
method chain = chain
end)
operation
let private_operation ctxt ?async ?chain operation =
operation_rpc ctxt ~private_rpc:true ?async ?chain operation
let private_operations ctxt ?(async = false) ?(force = false) ?chain operations
=
make_call
S.private_operations
ctxt
()
(object
method async = async
method chain = chain
method force = force
end)
operations
let operation ctxt ?async ?chain operation =
operation_rpc ctxt ~private_rpc:false ?async ?chain operation
let protocol ctxt ?(async = false) protocol =
make_call
S.protocol
ctxt
()
(object
method async = async
end)
protocol
![swh spinner](/static/img/swh-spinner.gif)
Computing file changes ...