Proto: prepare protocol interface for multipass validation
This commit is contained in:
parent
e314ac635d
commit
4c171c72a2
@ -93,6 +93,17 @@ let begin_application
|
||||
Fitness.to_int64 raw_block.shell.fitness >>=? fun fitness ->
|
||||
return { context ; fitness }
|
||||
|
||||
let begin_partial_application
|
||||
~ancestor_context
|
||||
~predecessor_timestamp
|
||||
~predecessor_fitness
|
||||
raw_block =
|
||||
begin_application
|
||||
~predecessor_context:ancestor_context
|
||||
~predecessor_timestamp
|
||||
~predecessor_fitness
|
||||
raw_block
|
||||
|
||||
let begin_construction
|
||||
~predecessor_context:context
|
||||
~predecessor_timestamp:_
|
||||
|
@ -31,7 +31,7 @@ done
|
||||
sleep 2
|
||||
|
||||
# autogenerated from the demo source
|
||||
protocol_version="PrqKneMJTqCkD5bXFb4w3nidsW9kem1DjmmchwFTHqztK7V3QRq"
|
||||
protocol_version="PrqRSDRSu849eAgN6UQXcZBAsK3jCHY7g9nQ6HWXAGkmDY4ffCH"
|
||||
|
||||
$admin_client inject protocol "$test_dir/demo"
|
||||
$admin_client list protocols
|
||||
|
@ -138,12 +138,17 @@ module type PROTOCOL = sig
|
||||
function should run quickly, as its main use is to reject bad
|
||||
blocks from the chain as early as possible. The input context
|
||||
is the one resulting of an ancestor block of same protocol
|
||||
version, not necessarily the one of its predecessor. *)
|
||||
val precheck_block:
|
||||
version. This ancestor of the current head is guaranteed to be
|
||||
more recent than `last_allowed_fork_level`.
|
||||
|
||||
The resulting `validation_state` will be used for multi-pass
|
||||
validation. *)
|
||||
val begin_partial_application:
|
||||
ancestor_context: Context.t ->
|
||||
ancestor_timestamp: Time.t ->
|
||||
predecessor_timestamp: Time.t ->
|
||||
predecessor_fitness: Fitness.t ->
|
||||
block_header ->
|
||||
unit tzresult Lwt.t
|
||||
validation_state tzresult Lwt.t
|
||||
|
||||
(** The first step in a block validation sequence. Initializes a
|
||||
validation context for validating a block. Takes as argument the
|
||||
|
@ -81,11 +81,12 @@ module Make (Context : CONTEXT) = struct
|
||||
val compare_operations: operation -> operation -> int
|
||||
type validation_state
|
||||
val current_context: validation_state -> context tzresult Lwt.t
|
||||
val precheck_block:
|
||||
val begin_partial_application:
|
||||
ancestor_context: context ->
|
||||
ancestor_timestamp: Time.t ->
|
||||
predecessor_timestamp: Time.t ->
|
||||
predecessor_fitness: Fitness.t ->
|
||||
block_header ->
|
||||
unit tzresult Lwt.t
|
||||
validation_state tzresult Lwt.t
|
||||
val begin_application:
|
||||
predecessor_context: context ->
|
||||
predecessor_timestamp: Time.t ->
|
||||
@ -631,11 +632,11 @@ module Make (Context : CONTEXT) = struct
|
||||
|
||||
module Lift(P : Updater.PROTOCOL) = struct
|
||||
include P
|
||||
let precheck_block
|
||||
~ancestor_context ~ancestor_timestamp
|
||||
let begin_partial_application
|
||||
~ancestor_context ~predecessor_timestamp ~predecessor_fitness
|
||||
raw_block =
|
||||
precheck_block
|
||||
~ancestor_context ~ancestor_timestamp
|
||||
begin_partial_application
|
||||
~ancestor_context ~predecessor_timestamp ~predecessor_fitness
|
||||
raw_block >|= wrap_error
|
||||
let begin_application
|
||||
~predecessor_context ~predecessor_timestamp
|
||||
|
@ -74,11 +74,12 @@ module Make (Context : CONTEXT) : sig
|
||||
val compare_operations: operation -> operation -> int
|
||||
type validation_state
|
||||
val current_context: validation_state -> context tzresult Lwt.t
|
||||
val precheck_block:
|
||||
val begin_partial_application:
|
||||
ancestor_context: context ->
|
||||
ancestor_timestamp: Time.t ->
|
||||
predecessor_timestamp: Time.t ->
|
||||
predecessor_fitness: Fitness.t ->
|
||||
block_header ->
|
||||
unit tzresult Lwt.t
|
||||
validation_state tzresult Lwt.t
|
||||
val begin_application:
|
||||
predecessor_context: context ->
|
||||
predecessor_timestamp: Time.t ->
|
||||
|
@ -324,12 +324,15 @@ let inject_operation
|
||||
~confirmations cctxt ~chain oph >>=? fun (h, i , j) ->
|
||||
Alpha_block_services.Operation.operation
|
||||
cctxt ~block:(`Hash (h, 0)) i j >>=? fun op' ->
|
||||
let Operation_metadata receipt = op'.receipt in
|
||||
match Apply_operation_result.kind_equal_list contents receipt.contents
|
||||
with
|
||||
| Some Apply_operation_result.Eq ->
|
||||
return (receipt : kind operation_metadata)
|
||||
| None -> failwith "Internal error: unexpected receipt."
|
||||
match op'.receipt with
|
||||
| No_operation_metadata ->
|
||||
failwith "Internal error: unexpected receipt."
|
||||
| Operation_metadata receipt ->
|
||||
match Apply_operation_result.kind_equal_list contents receipt.contents
|
||||
with
|
||||
| Some Apply_operation_result.Eq ->
|
||||
return (receipt : kind operation_metadata)
|
||||
| None -> failwith "Internal error: unexpected receipt."
|
||||
end >>=? fun result ->
|
||||
cctxt#message
|
||||
"@[<v 2>This sequence of operations was run:@,%a@]"
|
||||
|
@ -897,6 +897,7 @@ module Operation : sig
|
||||
proto: MBytes.t ;
|
||||
}
|
||||
val raw_encoding: raw Data_encoding.t
|
||||
val contents_list_encoding: packed_contents_list Data_encoding.t
|
||||
|
||||
type 'kind t = 'kind operation = {
|
||||
shell: Operation.shell_header ;
|
||||
|
@ -702,7 +702,7 @@ let contents_and_result_list_encoding =
|
||||
| Manager_operation _, Cons_and_result (_, _, _) ->
|
||||
Contents_and_result_list (Cons_and_result (op, res, rest))
|
||||
| _ -> Pervasives.failwith "cannot decode ill-formed combined operation result" in
|
||||
conv to_list of_list (list contents_and_result_encoding)
|
||||
conv to_list of_list (Variable.list contents_and_result_encoding)
|
||||
|
||||
type 'kind operation_metadata = {
|
||||
contents: 'kind contents_result_list ;
|
||||
@ -710,13 +710,27 @@ type 'kind operation_metadata = {
|
||||
|
||||
type packed_operation_metadata =
|
||||
| Operation_metadata : 'kind operation_metadata -> packed_operation_metadata
|
||||
| No_operation_metadata : packed_operation_metadata
|
||||
|
||||
let operation_metadata_encoding =
|
||||
def "operation.alpha.result" @@
|
||||
conv
|
||||
(fun (Operation_metadata { contents }) -> Contents_result_list contents)
|
||||
(fun (Contents_result_list contents) -> Operation_metadata { contents })
|
||||
contents_result_list_encoding
|
||||
union [
|
||||
case (Tag 0)
|
||||
~title:"Operation_metadata"
|
||||
contents_result_list_encoding
|
||||
(function
|
||||
| Operation_metadata { contents } ->
|
||||
Some (Contents_result_list contents)
|
||||
| _ -> None)
|
||||
(fun (Contents_result_list contents) -> Operation_metadata { contents }) ;
|
||||
case (Tag 1)
|
||||
~title:"No_operation_metadata"
|
||||
empty
|
||||
(function
|
||||
| No_operation_metadata -> Some ()
|
||||
| _ -> None)
|
||||
(fun () -> No_operation_metadata) ;
|
||||
]
|
||||
|
||||
type ('a, 'b) eq = Eq : ('a, 'a) eq
|
||||
|
||||
@ -850,18 +864,36 @@ let rec unpack_contents_list :
|
||||
|
||||
let operation_data_and_metadata_encoding =
|
||||
def "operation.alpha.operation_with_metadata" @@
|
||||
conv
|
||||
(fun (Operation_data op, Operation_metadata res) ->
|
||||
match kind_equal_list op.contents res.contents with
|
||||
| None -> Pervasives.failwith "cannot decode inconsistent combined operation result"
|
||||
| Some Eq ->
|
||||
(Contents_and_result_list
|
||||
(pack_contents_list op.contents res.contents),
|
||||
op.signature))
|
||||
(fun (Contents_and_result_list contents, signature) ->
|
||||
let op_contents, res_contents = unpack_contents_list contents in
|
||||
(Operation_data { contents = op_contents ; signature },
|
||||
Operation_metadata { contents = res_contents }))
|
||||
(obj2
|
||||
(req "contents" contents_and_result_list_encoding)
|
||||
(varopt "signature" Signature.encoding))
|
||||
union [
|
||||
case (Tag 0)
|
||||
~title:"Operation_with_metadata"
|
||||
(obj2
|
||||
(req "contents" (dynamic_size contents_and_result_list_encoding))
|
||||
(opt "signature" Signature.encoding))
|
||||
(function
|
||||
| (Operation_data _, No_operation_metadata) -> None
|
||||
| (Operation_data op, Operation_metadata res) ->
|
||||
match kind_equal_list op.contents res.contents with
|
||||
| None -> Pervasives.failwith "cannot decode inconsistent combined operation result"
|
||||
| Some Eq ->
|
||||
Some
|
||||
(Contents_and_result_list
|
||||
(pack_contents_list op.contents res.contents),
|
||||
op.signature))
|
||||
(fun (Contents_and_result_list contents, signature) ->
|
||||
let op_contents, res_contents = unpack_contents_list contents in
|
||||
(Operation_data { contents = op_contents ; signature },
|
||||
Operation_metadata { contents = res_contents })) ;
|
||||
case (Tag 1)
|
||||
~title:"Operation_without_metadata"
|
||||
(obj2
|
||||
(req "contents" (dynamic_size Operation.contents_list_encoding))
|
||||
(opt "signature" Signature.encoding))
|
||||
(function
|
||||
| (Operation_data op, No_operation_metadata) ->
|
||||
Some (Contents_list op.contents, op.signature)
|
||||
| (Operation_data _, Operation_metadata _) ->
|
||||
None)
|
||||
(fun (Contents_list contents, signature) ->
|
||||
(Operation_data { contents ; signature }, No_operation_metadata))
|
||||
]
|
||||
|
@ -39,6 +39,7 @@ type 'kind operation_metadata = {
|
||||
|
||||
and packed_operation_metadata =
|
||||
| Operation_metadata : 'kind operation_metadata -> packed_operation_metadata
|
||||
| No_operation_metadata : packed_operation_metadata
|
||||
|
||||
(** Result of applying a {!Operation.contents_list}. Follows the same structure. *)
|
||||
and 'kind contents_result_list =
|
||||
|
@ -26,6 +26,7 @@ let operation_data_encoding = Alpha_context.Operation.protocol_data_encoding
|
||||
|
||||
type operation_receipt = Apply_operation_result.packed_operation_metadata =
|
||||
| Operation_metadata : 'kind Apply_operation_result.operation_metadata -> operation_receipt
|
||||
| No_operation_metadata: operation_receipt
|
||||
let operation_receipt_encoding =
|
||||
Apply_operation_result.operation_metadata_encoding
|
||||
|
||||
@ -62,6 +63,10 @@ type validation_mode =
|
||||
block_header : Alpha_context.Block_header.t ;
|
||||
baker : Alpha_context.public_key_hash ;
|
||||
}
|
||||
| Partial_application of {
|
||||
block_header : Alpha_context.Block_header.t ;
|
||||
baker : Alpha_context.public_key_hash ;
|
||||
}
|
||||
| Partial_construction of {
|
||||
predecessor : Block_hash.t ;
|
||||
}
|
||||
@ -80,24 +85,33 @@ type validation_state =
|
||||
let current_context { ctxt ; _ } =
|
||||
return (Alpha_context.finalize ctxt).context
|
||||
|
||||
let precheck_block
|
||||
~ancestor_context:_
|
||||
~ancestor_timestamp:_
|
||||
_block_header =
|
||||
(* TODO: decide what properties should be checked *)
|
||||
return ()
|
||||
|
||||
let begin_application
|
||||
~predecessor_context:ctxt
|
||||
~predecessor_timestamp:pred_timestamp
|
||||
~predecessor_fitness:pred_fitness
|
||||
let begin_partial_application
|
||||
~ancestor_context:ctxt
|
||||
~predecessor_timestamp
|
||||
~predecessor_fitness
|
||||
(block_header : Alpha_context.Block_header.t) =
|
||||
let level = block_header.shell.level in
|
||||
let fitness = pred_fitness in
|
||||
let fitness = predecessor_fitness in
|
||||
let timestamp = block_header.shell.timestamp in
|
||||
Alpha_context.prepare ~level ~timestamp ~fitness ctxt >>=? fun ctxt ->
|
||||
Apply.begin_application
|
||||
ctxt block_header pred_timestamp >>=? fun (ctxt, baker) ->
|
||||
ctxt block_header predecessor_timestamp >>=? fun (ctxt, baker) ->
|
||||
let mode =
|
||||
Partial_application
|
||||
{ block_header ; baker = Signature.Public_key.hash baker } in
|
||||
return { mode ; ctxt ; op_count = 0 }
|
||||
|
||||
let begin_application
|
||||
~predecessor_context:ctxt
|
||||
~predecessor_timestamp
|
||||
~predecessor_fitness
|
||||
(block_header : Alpha_context.Block_header.t) =
|
||||
let level = block_header.shell.level in
|
||||
let fitness = predecessor_fitness in
|
||||
let timestamp = block_header.shell.timestamp in
|
||||
Alpha_context.prepare ~level ~timestamp ~fitness ctxt >>=? fun ctxt ->
|
||||
Apply.begin_application
|
||||
ctxt block_header predecessor_timestamp >>=? fun (ctxt, baker) ->
|
||||
let mode = Application { block_header ; baker = Signature.Public_key.hash baker } in
|
||||
return { mode ; ctxt ; op_count = 0 }
|
||||
|
||||
@ -133,20 +147,31 @@ let begin_construction
|
||||
let apply_operation
|
||||
({ mode ; ctxt ; op_count ; _ } as data)
|
||||
(operation : Alpha_context.packed_operation) =
|
||||
let { shell ; protocol_data = Operation_data protocol_data } = operation in
|
||||
let operation : _ Alpha_context.operation = { shell ; protocol_data } in
|
||||
let predecessor =
|
||||
match mode with
|
||||
| Partial_construction { predecessor }
|
||||
| Application
|
||||
{ block_header = { shell = { predecessor ; _ } ; _ } ; _ }
|
||||
| Full_construction { predecessor ; _ } ->
|
||||
predecessor in
|
||||
Apply.apply_operation ctxt Optimized predecessor
|
||||
(Alpha_context.Operation.hash operation)
|
||||
operation >>=? fun (ctxt, result) ->
|
||||
let op_count = op_count + 1 in
|
||||
return ({ data with ctxt ; op_count }, Operation_metadata result)
|
||||
match mode with
|
||||
| Partial_application _ when
|
||||
not (List.exists
|
||||
(Compare.Int.equal 0)
|
||||
(Alpha_context.Operation.acceptable_passes operation)) ->
|
||||
(* Multipass validation only considers operations in pass 0. *)
|
||||
let op_count = op_count + 1 in
|
||||
return ({ data with ctxt ; op_count }, No_operation_metadata)
|
||||
| _ ->
|
||||
let { shell ; protocol_data = Operation_data protocol_data } = operation in
|
||||
let operation : _ Alpha_context.operation = { shell ; protocol_data } in
|
||||
let predecessor =
|
||||
match mode with
|
||||
| Partial_application
|
||||
{ block_header = { shell = { predecessor ; _ } ; _ } ; _ }
|
||||
| Partial_construction { predecessor }
|
||||
| Application
|
||||
{ block_header = { shell = { predecessor ; _ } ; _ } ; _ }
|
||||
| Full_construction { predecessor ; _ } ->
|
||||
predecessor in
|
||||
Apply.apply_operation ctxt Optimized predecessor
|
||||
(Alpha_context.Operation.hash operation)
|
||||
operation >>=? fun (ctxt, result) ->
|
||||
let op_count = op_count + 1 in
|
||||
return ({ data with ctxt ; op_count }, Operation_metadata result)
|
||||
|
||||
let finalize_block { mode ; ctxt ; op_count } =
|
||||
match mode with
|
||||
@ -163,6 +188,12 @@ let finalize_block { mode ; ctxt ; op_count } =
|
||||
let ctxt = Alpha_context.finalize ctxt in
|
||||
return (ctxt, { Alpha_context.Block_header.baker ; level ;
|
||||
voting_period_kind })
|
||||
| Partial_application { baker ; _ } ->
|
||||
let level = Alpha_context. Level.current ctxt in
|
||||
Alpha_context.Vote.get_current_period_kind ctxt >>=? fun voting_period_kind ->
|
||||
let ctxt = Alpha_context.finalize ctxt in
|
||||
return (ctxt, { Alpha_context.Block_header.baker ; level ;
|
||||
voting_period_kind })
|
||||
| Application
|
||||
{ baker ; block_header = { protocol_data = { contents = protocol_data ; _ } ; _ } }
|
||||
| Full_construction { protocol_data ; baker ; _ } ->
|
||||
|
@ -14,6 +14,10 @@ type validation_mode =
|
||||
block_header : Alpha_context.Block_header.t ;
|
||||
baker : Alpha_context.public_key_hash ;
|
||||
}
|
||||
| Partial_application of {
|
||||
block_header : Alpha_context.Block_header.t ;
|
||||
baker : Alpha_context.public_key_hash ;
|
||||
}
|
||||
| Partial_construction of {
|
||||
predecessor : Block_hash.t ;
|
||||
}
|
||||
|
@ -592,6 +592,7 @@ end
|
||||
|
||||
let encoding = Encoding.operation_encoding
|
||||
let contents_encoding = Encoding.contents_encoding
|
||||
let contents_list_encoding = Encoding.contents_list_encoding
|
||||
let protocol_data_encoding = Encoding.protocol_data_encoding
|
||||
let unsigned_operation_encoding = Encoding.unsigned_operation_encoding
|
||||
let internal_operation_encoding = Encoding.internal_operation_encoding
|
||||
|
@ -149,6 +149,7 @@ val manager_kind: 'kind manager_operation -> 'kind Kind.manager
|
||||
|
||||
val encoding: packed_operation Data_encoding.t
|
||||
val contents_encoding: packed_contents Data_encoding.t
|
||||
val contents_list_encoding: packed_contents_list Data_encoding.t
|
||||
val protocol_data_encoding: packed_protocol_data Data_encoding.t
|
||||
val unsigned_operation_encoding: (Operation.shell_header * packed_contents_list) Data_encoding.t
|
||||
|
||||
|
@ -80,13 +80,6 @@ module Fitness = struct
|
||||
|
||||
end
|
||||
|
||||
let precheck_block
|
||||
~ancestor_context:_
|
||||
~ancestor_timestamp:_
|
||||
(raw_block: block_header) =
|
||||
Fitness.to_int64 raw_block.shell.fitness >>=? fun _ ->
|
||||
return ()
|
||||
|
||||
let begin_application
|
||||
~predecessor_context:context
|
||||
~predecessor_timestamp:_
|
||||
@ -95,6 +88,17 @@ let begin_application
|
||||
Fitness.to_int64 raw_block.shell.fitness >>=? fun fitness ->
|
||||
return { context ; fitness }
|
||||
|
||||
let begin_partial_application
|
||||
~ancestor_context
|
||||
~predecessor_timestamp
|
||||
~predecessor_fitness
|
||||
block_header =
|
||||
begin_application
|
||||
~predecessor_context:ancestor_context
|
||||
~predecessor_timestamp
|
||||
~predecessor_fitness
|
||||
block_header
|
||||
|
||||
let begin_construction
|
||||
~predecessor_context:context
|
||||
~predecessor_timestamp:_
|
||||
|
@ -92,14 +92,9 @@ type validation_state = Updater.validation_result
|
||||
let current_context ({ context ; _ } : validation_state) =
|
||||
return context
|
||||
|
||||
let precheck_block
|
||||
~ancestor_context:_
|
||||
~ancestor_timestamp:_
|
||||
_block_header =
|
||||
return ()
|
||||
|
||||
(* temporary hardcoded key to be removed... *)
|
||||
let protocol_parameters_key = [ "protocol_parameters" ]
|
||||
|
||||
let prepare_application ctxt command level timestamp fitness =
|
||||
match command with
|
||||
| Data.Command.Activate { protocol = hash ; fitness ; protocol_parameters } ->
|
||||
@ -131,6 +126,17 @@ let begin_application
|
||||
prepare_application ctxt block_header.protocol_data.command
|
||||
block_header.shell.level block_header.shell.timestamp block_header.shell.fitness
|
||||
|
||||
let begin_partial_application
|
||||
~ancestor_context
|
||||
~predecessor_timestamp
|
||||
~predecessor_fitness
|
||||
block_header =
|
||||
begin_application
|
||||
~predecessor_context:ancestor_context
|
||||
~predecessor_timestamp
|
||||
~predecessor_fitness
|
||||
block_header
|
||||
|
||||
let begin_construction
|
||||
~predecessor_context:ctxt
|
||||
~predecessor_timestamp:_
|
||||
|
Loading…
Reference in New Issue
Block a user