tezos-protocol-plugin-013-PtJakart
Library
Module
Module type
Parameter
Class
Class type
type error_classification = [
| `Branch_delayed of Tezos_base.TzPervasives.tztrace |
| `Branch_refused of Tezos_base.TzPervasives.tztrace |
| `Refused of Tezos_base.TzPervasives.tztrace |
| `Outdated of Tezos_base.TzPervasives.tztrace |
]
type nanotez = Q.t
val nanotez_enc : nanotez Tezos_base.TzPervasives.Data_encoding.t
val manager_op_replacement_factor_enc :
Q.t Tezos_base.TzPervasives.Data_encoding.t
type config = {
minimal_fees : Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.t; | |
minimal_nanotez_per_gas_unit : nanotez; | |
minimal_nanotez_per_byte : nanotez; | |
allow_script_failure : bool; | (* If |
clock_drift : Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Period.t
option; | |
replace_by_fee_factor : Q.t; | (* This field determines the amount of additional fees (given as a factor of the declared fees) a manager should add to an operation in order to (eventually) replace an existing (prechecked) one in the mempool. Note that other criteria, such as the gas ratio, are also taken into account to decide whether to accept the replacement or not. *) |
max_prechecked_manager_operations : int; | (* Maximal number of prechecked operations to keep. The mempool only keeps the |
}
val default_minimal_fees :
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.tez
val default_minimal_nanotez_per_gas_unit : Q.t
val default_minimal_nanotez_per_byte : Q.t
val quota : Environment_context.quota list
val managers_quota : Environment_context.quota
val default_config : config
val config_encoding : config Tezos_base.TzPervasives.Data_encoding.t
type manager_op_info = {
operation_hash : Tezos_crypto.Operation_hash.t; |
gas_limit : Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.fp; |
fee : Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.t; |
weight : Q.t; |
}
val op_weight_of_info : manager_op_info -> manager_op_weight
module ManagerOpWeightSet : sig ... end
type state = {
grandparent_level_start : Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Timestamp.t
option; | |
round_zero_duration : Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Period.t
option; | |
op_prechecked_managers : manager_op_info
Tezos_crypto.Signature.Public_key_hash.Map.t; | (* All managers that are the source of manager operations prechecked in the mempool. Each manager in the map is associated to a record of type |
operation_hash_to_manager : Tezos_crypto.Signature.Public_key_hash.t
Tezos_crypto.Operation_hash.Map.t; | (* Map of operation hash to manager used to remove a manager from |
prechecked_operations_count : int; | (* Number of prechecked manager operations. Invariants:
|
ops_prechecked : ManagerOpWeightSet.t; | |
min_prechecked_op_weight : manager_op_weight option; | (* The prechecked operation in
|
}
val empty : state
val init :
'a ->
?validation_state:Tezos_protocol_013_PtJakart.Protocol.validation_state ->
predecessor:Tezos_base.Block_header.t ->
unit ->
state Tezos_base.TzPervasives.tzresult Lwt.t
val on_flush :
'a ->
'b ->
?validation_state:Tezos_protocol_013_PtJakart.Protocol.validation_state ->
predecessor:Tezos_base.Block_header.t ->
unit ->
state Tezos_base.TzPervasives.tzresult Lwt.t
val remove : filter_state:state -> Tezos_crypto.Operation_hash.Map.key -> state
val get_manager_operation_gas_and_fee :
'a Tezos_protocol_013_PtJakart.Protocol.Alpha_context.contents_list ->
( Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.tez
* Tezos_raw_protocol_013_PtJakart.Fixed_point_repr.integral_tag
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.t,
Tezos_protocol_environment_013_PtJakart__Environment.Error_monad.error
Tezos_protocol_environment_013_PtJakart__Environment.Error_monad.trace )
result
type Tezos_protocol_013_PtJakart.Protocol.Environment.Error_monad.error +=
| Manager_restriction of {
} |
type Tezos_protocol_013_PtJakart.Protocol.Environment.Error_monad.error +=
| Manager_operation_replaced of {
} |
type Tezos_protocol_013_PtJakart.Protocol.Environment.Error_monad.error +=
| Fees_too_low_for_mempool of Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.t |
type Tezos_protocol_013_PtJakart.Protocol.Environment.Error_monad.error +=
| Removed_fees_too_low_for_mempool |
val better_fees_and_ratio :
config ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.integral ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.tez ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.integral ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.tez ->
bool
val check_manager_restriction :
config ->
state ->
Tezos_crypto.Signature.Public_key_hash.Map.key ->
fee:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.tez ->
gas_limit:
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.integral ->
[> `Fail of [> `Branch_delayed of Tezos_base.TzPervasives.error list ]
| `Fresh
| `Replace of Tezos_crypto.Operation_hash.t ]
val size_of_operation :
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Operation.packed_protocol_data ->
int
val weight_and_resources_manager_operation :
validation_state:Tezos_protocol_013_PtJakart.Protocol.validation_state ->
?size:int ->
fee:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.tez ->
gas:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.integral ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Operation.packed_protocol_data ->
Q.t * Q.t
Returns the weight and resources consumption of an operation. The weight corresponds to the one implemented by the baker, to decide which operations to put in a block first (the code is largely duplicated). See Tezos_baking_alpha
.Operation_selection.weight_manager
val weight_manager_operation :
validation_state:Tezos_protocol_013_PtJakart.Protocol.validation_state ->
?size:int ->
fee:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.tez ->
gas:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.integral ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Operation.packed_protocol_data ->
Q.t
Returns the weight of an operation, i.e. the fees w.r.t the gas and size consumption in the block.
val required_fee_manager_operation_weight :
op_resources:Q.t ->
min_weight:Q.t ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.t
Return fee for an operation that consumes op_resources
for its weight to be strictly greater than min_weight
.
val check_minimal_weight :
?validation_state:Tezos_protocol_013_PtJakart.Protocol.validation_state ->
config ->
state ->
fee:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.tez ->
gas_limit:
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.integral ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Operation.packed_protocol_data ->
[> `Fail of [> `Branch_delayed of Tezos_base.TzPervasives.error list ]
| `Weight_ok of
[> `No_replace | `Replace of Tezos_crypto.Operation_hash.t ] * Q.t list ]
Check if an operation as a weight (fees w.r.t gas and size) large enough to be prechecked and return said weight. In the case where the prechecked mempool is full, return an error if the weight is too small, or return the operation to be replaced otherwise.
val pre_filter_manager :
't. config ->
state ->
validation_state_before:
Tezos_protocol_013_PtJakart.Protocol.validation_state option ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.public_key_hash ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Operation.packed_protocol_data ->
't Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Kind.manager
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.contents_list ->
[ `Branch_delayed of Tezos_base.TzPervasives.tztrace
| `Branch_refused of Tezos_base.TzPervasives.tztrace
| `Outdated of Tezos_base.TzPervasives.tztrace
| `Passed_prefilter of Q.t list
| `Refused of Tezos_base.TzPervasives.tztrace ]
type Tezos_protocol_013_PtJakart.Protocol.Environment.Error_monad.error +=
| Consensus_operation_in_far_future |
consensus operation filtering
In Tenderbake, we increased a lot the number of consensus operations, therefore it seems necessary to be able to filter consensus operations that could be produced by a Byzantine baker mis-using its right to produce operations in future rounds or levels.
We consider the situation where the head is at level h_l
, round h_r
, and with timestamp h_ts
, with the predecessor of the head being at round hp_r
. We receive at a time now
a consensus operation for level op_l
and round op_r
.
A consensus operation is considered too far in the future, and therefore filtered, if the earliest possible starting time of its round is greater than the current time plus a safety margin of config.clock_drift
.
To consider potential level 2 reorgs, we first compute the expected timestamp of round zero at previous level hp0_ts
,
All ops at level p_l and round r' such that time(r') is greater than (now + drift) are deemed too far in the future:
h_r op_ts now+drift (h_l,r') hp0_ts h_0 h_l | | | +----+-----+---------+-------------------+--+-----+--------------+----------- | | | | | | | | h_ts h_r end time | now | earliest expected | | | | time of round r' |<----op_r rounds duration -------->| | | |<--------------- operations kept ---->|<-rejected----------... | |<-----------operations considered by the filter -----------...
For an operation on a proposal at the next level, we consider the minimum starting time of the operation's round, obtained by assuming that the proposal at the next level was built on top of a proposal at round 0 for the current level, itself based on a proposal at round 0 of previous level. Operations on proposal with higher levels are treated similarly.
All ops at the next level and round r' such that timestamp(r') > now+drift are deemed too far in the future.
r=0 r=1 h_r now now+drift (h_l+1,r') hp0_ts h_0 h_l h_l | | | +----+---- |-------+----+---------+----------+----------+---------- | | | | | | t0 | h_ts earliest expected | | | | time of round r' |<--- | earliest| | | next level| | | |<---------------------------------->| round_offset(r')
val acceptable :
drift:Tezos_raw_protocol_013_PtJakart__Alpha_context.Period.t ->
op_earliest_ts:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Timestamp.t ->
now_timestamp:
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Timestamp.time ->
( bool,
Tezos_protocol_environment_013_PtJakart__Environment.Error_monad.error
Tezos_protocol_environment_013_PtJakart__Environment.Error_monad.trace )
result
At a given level a consensus operation is acceptable if its earliest expected timestamp, op_earliest_ts
is below the current clock with an accepted drift for the clock given by a configuration.
val acceptable_op :
config:config ->
round_durations:
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Round.round_durations ->
round_zero_duration:
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Period.t ->
proposal_level:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Raw_level.t ->
proposal_round:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Round.t ->
proposal_timestamp:
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Timestamp.t ->
proposal_predecessor_level_start:
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Timestamp.t ->
op_level:
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Raw_level.raw_level ->
op_round:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Round.t ->
now_timestamp:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Timestamp.t ->
( bool,
Tezos_protocol_environment_013_PtJakart__Environment.Error_monad.error
Tezos_protocol_environment_013_PtJakart__Environment.Error_monad.trace )
result
Check that an operation with the given op_round
, at level op_level
is likely to be correct, meaning it could have been produced before now (+ the safety margin from configuration).
Given an operation at level greater or equal than/to the current level, we compute the expected timestamp of the operation's round. If the operation is at a greater level, we assume that it is based on the proposal at round zero of the current level.
All operations whose (level, round) is lower than or equal to the current head are deemed valid. Note that in case where their is a high drift in the computer clock, they might not have been considered valid by comparing their expected timestamp to the clock.
This is a stricter than necessary filter as it will reject operations that could be valid in the current timeframe if the proposal they endorse is built over a predecessor of the current proposal that would be of lower round than the current one.
What can we do that would be smarter: get current head's predecessor round and timestamp to compute the timestamp t0 of a predecessor that would have been proposed at round 0.
Timestamp of round at current level for an alternative head that would be based on such proposal would be computed based on t0. For level higher than current head, compute the round's earliest timestamp if all proposal passed at round 0 starting from t0.
val pre_filter_far_future_consensus_ops :
config ->
filter_state:state ->
?validation_state_before:
Tezos_protocol_013_PtJakart.Protocol.validation_state ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.consensus_content ->
bool Lwt.t
val pre_filter :
config ->
filter_state:state ->
?validation_state_before:
Tezos_protocol_013_PtJakart.Protocol.validation_state ->
Tezos_protocol_013_PtJakart.Protocol.Main.operation ->
[> `Branch_delayed of Tezos_base.TzPervasives.tztrace
| `Branch_refused of Tezos_base.TzPervasives.error list
| `Outdated of Tezos_base.TzPervasives.tztrace
| `Passed_prefilter of [> `High | `Low of Q.t list | `Medium ]
| `Refused of Tezos_base.TzPervasives.error list ]
Lwt.t
A quasi infinite amount of "valid" (pre)endorsements could be sent by a committee member, one for each possible round number.
This filter rejects (pre)endorsements that refer to a round that could not have been reached within the time span between the last head's timestamp and the current local clock.
We add config.clock_drift
time as a safety margin.
val precheck_manager :
't. config ->
state ->
Tezos_protocol_013_PtJakart.Protocol.validation_state ->
Tezos_crypto.Operation_hash.t ->
Tezos_base.Operation.shell_header ->
't Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Kind.manager
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.protocol_data ->
nb_successful_prechecks:int ->
fee:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Tez.t ->
gas_limit:Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Gas.Arith.fp ->
Tezos_protocol_013_PtJakart.Protocol.Alpha_context.public_key_hash ->
[> `Branch_delayed of Tezos_base.TzPervasives.tztrace
| `Branch_refused of Tezos_base.TzPervasives.tztrace
| `Outdated of Tezos_base.TzPervasives.tztrace
| `Prechecked_manager of
[ `No_replace
| `Replace of Tezos_crypto.Operation_hash.t * error_classification ]
| `Refused of Tezos_base.TzPervasives.tztrace ]
Lwt.t
val add_manager_restriction :
state ->
Tezos_crypto.Operation_hash.Map.key ->
manager_op_info ->
Tezos_crypto.Signature.Public_key_hash.Map.key ->
[< `No_replace | `Replace of Tezos_crypto.Operation_hash.Map.key * 'a ] ->
state
val precheck :
config ->
filter_state:state ->
validation_state:Tezos_protocol_013_PtJakart.Protocol.validation_state ->
Tezos_crypto.Operation_hash.t ->
Tezos_protocol_013_PtJakart.Protocol.Main.operation ->
nb_successful_prechecks:int ->
[ `Branch_delayed of Tezos_base.TzPervasives.tztrace
| `Branch_refused of Tezos_base.TzPervasives.tztrace
| `Outdated of Tezos_base.TzPervasives.tztrace
| `Passed_precheck of
state
* [ `No_replace
| `Replace of Tezos_crypto.Operation_hash.t * error_classification ]
| `Refused of Tezos_base.TzPervasives.tztrace
| `Undecided ]
Lwt.t
val post_filter_manager :
't. Tezos_protocol_013_PtJakart.Protocol.Alpha_context.t ->
state ->
't Tezos_protocol_013_PtJakart.Protocol.Alpha_context.Kind.manager
Tezos_protocol_013_PtJakart.Protocol.Apply_results.contents_result_list ->
config ->
[ `Passed_postfilter of state | `Refused of Tezos_base.TzPervasives.tztrace ]
val post_filter :
config ->
filter_state:state ->
validation_state_before:'a ->
validation_state_after:Tezos_protocol_013_PtJakart.Protocol.validation_state ->
('b
* Tezos_protocol_013_PtJakart.Protocol.Apply_results.packed_operation_metadata) ->
[ `Passed_postfilter of state | `Refused of Tezos_base.TzPervasives.tztrace ]
Lwt.t