Module Tezt_mavryk.Operation_core

This module can be used to craft an operation without using client dedicated commands.

Overview

This module aims to replace the module Operation_legacy to provide an interface which is more extensible. In other words, supporting a new operation should be easier using this interface.

An unsigned operation is represented by the datatype t. t is a wrapper around a JSON representation of an operation. Some meta information needs to be provided to sign this operation. t is not signed a priori to ease writing tests with bad signatures.

This module also provides two functions to ease the injection of an operation: inject which should be called when the injection is expected to succeed, and inject_with_error when the injection is expected to fail.

Anyone is free to add support for new operations.

Manager operations

Manager operations represent most of the operations used by the tests. Those operations contain several parameters (see Manager.make) and can be batched. Wrapper like Manager.inject and Manager.inject_with_error are provided to ease the writing of tests.

type t

The abstract representation of an unsigned operation.

type operation := t
type consensus_kind =
  1. | Attestation of {
    1. with_dal : bool;
    }
  2. | Preattestation
type kind =
  1. | Consensus of {
    1. kind : consensus_kind;
    2. chain_id : string;
    }
  2. | Anonymous
  3. | Voting
  4. | Manager

The kind is necessary because it determines the watermark of an operation which is necessary for signing an operation. This type aims to be extended when other kinds of operations are added into this module.

val make : branch:string -> ?signer:Account.key -> kind:kind -> Tezt_wrapper.JSON.u -> t

make ~branch ?signer ~kind json client builds the representation of an unsigned operation.

val json : t -> Tezt_wrapper.JSON.u

json t gives the json representation of an unsigned operation.

val hex : ?protocol:Protocol.t -> ?signature:Mavryk_crypto.Signature.t -> t -> Client.t -> Hex.t Lwt.t

hex ?(protocol=None) ?(signature=None) t client computes the binary representation of an operation as a hexadecimal string. If protocol is given, the binary representation is computed using the encoding of operation from the protocol. Otherwise, a call to the forge_operations RPC is done to compute the binary representation. If signature is given, the hexadecimal represents the signed version of the operation. client is used to construct the binary representation of t.

  • parameter protocol

    controls whether the encoding of a protocol should be used to compute the binary representation of the operation rather than calling the forge_operations RPC to compute it.

  • parameter signature

    controls whether a signature should be attached to the operation.

val sign : ?protocol:Protocol.t -> t -> Client.t -> Mavryk_crypto.Signature.t Lwt.t

sign t client signs the raw representation of operation t by its signer (see make). client is used to construct the binary representation of t. Note that if no signer have been given to t the function returns Mavryk_crypto.Signature.zero.

val hash : t -> Client.t -> [ `OpHash of string ] Lwt.t

hash t client returns the hash of the operation

val byte_size : ?protocol:Protocol.t -> ?signature:Mavryk_crypto.Signature.t -> t -> Client.t -> int Lwt.t

Returns the size (in bytes) of the operation.

  • parameter protocol

    Allows using the operation encoding rather than using the forge_operations RPC to compute the hexadecimal representation of the operation.

  • parameter signature

    Allows to manually set the signature of the operation. When omitted, the operation is correctly signed using sign.

val inject : ?request:[ `Inject | `Notify ] -> ?force:bool -> ?protocol:Protocol.t -> ?signature:Mavryk_crypto.Signature.t -> ?error:Tezt_wrapper.Base.rex -> t -> Client.t -> [ `OpHash of string ] Lwt.t

inject ?(request=`Inject) ?(force=false) ?(signature=None) ?(error=None) t injects an operation into the node. The node is extracted from the Client. If a node cannot be extracted, the injection fails. If the injection succeeds, the hash of the operation is returned.

  • parameter dont_wait

    If true, the operation is injected without waiting on some node event. Making request ignore. Default is false.

  • parameter request

    If `Inject, we do not wait the prevalidator to classify the operation. This can create some flakyness in the test but is needed to test corner cases. If `Notify, the function waits for the prevalidator to classify the operation. However, the nodes need to activate the debug events for the prevalidator.

  • parameter force

    If true, the function succeeds even though the operation was classified with an error and was not propagated by the prevalidator. If false, the call fails if the prevalidator classified the operation with an error.

  • parameter protocol

    Allow using the operation encoding rather than using the forge_operations RPC to compute the hexadecimal representation of the operations.

  • parameter signature

    Allows to give manually the signature of the operation. The operation is signed when the signature is omitted.

  • parameter error

    If the injection is expecting to fail, allows to specify the expected error.

val spawn_inject : ?force:bool -> ?protocol:Protocol.t -> ?signature:Mavryk_crypto.Signature.t -> t -> Client.t -> Tezt_wrapper.JSON.t Runnable.process Lwt.t

Same as inject, but do not wait for the process to exit.

val inject_and_capture1_stderr : rex:Tezt_wrapper.Base.rex -> ?force:bool -> ?protocol:Protocol.t -> ?signature:Mavryk_crypto.Signature.t -> t -> Client.t -> string Lwt.t

Run spawn_inject then capture one group on stderr with rex.

val inject_and_capture2_stderr : rex:Tezt_wrapper.Base.rex -> ?force:bool -> ?protocol:Protocol.t -> ?signature:Mavryk_crypto.Signature.t -> t -> Client.t -> (string * string) Lwt.t

Run spawn_inject then capture two groups on stderr with rex.

val inject_operations : ?protocol:Protocol.t -> ?request:[ `Inject | `Notify ] -> ?force:bool -> ?error:Tezt_wrapper.Base.rex -> ?use_tmp_file:bool -> t list -> Client.t -> [ `OpHash of string ] list Lwt.t

inject_operations ?protocol ?request ?force ?error ?use_tmp_file ops client is similar as inject for a list of operations. This function calls the RPC RPC.post_private_injection_operations which is faster than calling the RPC used by inject several times. Note that this function should be used mainly when the time for injecting operations matters.

val make_run_operation_input : ?chain_id:string -> t -> Client.t -> Tezt_wrapper.JSON.u Lwt.t

Craft a json representing the full operation, in a format that is compatible with the run_operation RPC (RPC.post_chain_block_helpers_scripts_run_operation).

This json contains many more fields than the one produced by the json function above.

The operation is signed with Mavryk_crypto.Signature.zero, because the run_operation RPC skips signature checks anyway.

  • parameter chain_id

    Allows to manually provide the chain_id. If omitted, the chain_id is retrieved via RPC using the provided client.

  • parameter client

    The Client.t argument is used to retrieve the chain_id when it is not provided.

val make_preapply_operation_input : protocol:Protocol.t -> signature:Mavryk_crypto.Signature.t -> t -> Tezt_wrapper.JSON.u

Craft a json representing the full operation, in a format that is compatible with the preapply/operations RPC (RPC.post_chain_block_helpers_preapply_operations).

This json contains many more fields than the one produced by the json function above.

module Consensus : sig ... end
module Anonymous : sig ... end
module Voting : sig ... end

Voting operations (validation pass 1): proposals and ballot.

module Manager : sig ... end

Regular expressions for specific error messages.

Can be used as e.g.

val gas_limit_exceeded : Tezt_wrapper.Base.rex

Matches the client message for the Operation_quota_exceeded protocol error.

val conflict_error_with_needed_fee : Tezt_wrapper.Base.rex

Matches the message produced by Operation_conflict {new_hash; needed_fee_in_mumav = Some fee} from src/lib_shell_services/validation_errors.

Captures new_hash and fee.

val conflict_error_no_possible_fee : Tezt_wrapper.Base.rex

Matches the message produced by Operation_conflict {new_hash; needed_fee_in_mumav = None} from src/lib_shell_services/validation_errors.

Captures new_hash.

val rejected_by_full_mempool_with_needed_fee : Tezt_wrapper.Base.rex

Matches the message produced by Rejected_by_full_mempool {hash; needed_fee_in_mumav = Some fee} from src/lib_shell_services/validation_errors.

Captures hash and fee.

val rejected_by_full_mempool_no_possible_fee : Tezt_wrapper.Base.rex

Matches the message produced by Rejected_by_full_mempool {hash; needed_fee_in_mumav = None} from src/lib_shell_services/validation_errors.

Captures hash.

val dal_data_availibility_attester_not_in_committee : Tezt_wrapper.Base.rex

Matches the message produced by Dal_data_availibility_attester_not_in_committee {attester; level; slot} from src/proto_alpha/lib_protocol/dal_errors_repr.

Captures attester, level, and slot.

Calls inject_and_capture2_stderr and checks that the second captured group is expected_fee.

Intended to be used with conflict_error_with_needed_fee or rejected_by_full_mempool_with_needed_fee as rex.

val already_denounced : Tezt_wrapper.Base.rex

Matches the message produced by Already_denounced {kind; delegate; level} from src/proto_xxx/lib_protocol/validate_errors.

Captures delegate, level, kind.

val outdated_denunciation : Tezt_wrapper.Base.rex

Matches the message produced by Outdated_denunciation {kind; level; last_cycle} from src/proto_xxx/lib_protocol/validate_errors.

Captures kind, last_cycle, level.

val injection_error_unknown_branch : Tezt_wrapper.Base.rex

Matches the message Operation %a is branched on either: from src/lib_shell/prevalidator.ml.

Captures hash.