Proto: export Data_encoding.t for block headers and operationss

Previously we were only exporting parsing function. This will allow
to move out of the protocol some `helpers` RPCs.
This commit is contained in:
Grégoire Henry 2018-04-20 23:04:33 +02:00 committed by Benjamin Canou
parent afa335ff48
commit c85e27605b
41 changed files with 529 additions and 380 deletions

View File

@ -7,15 +7,25 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
type operation = Operation_hash.t type block_header_data = MBytes.t
let max_operation_data_length = 42 type block_header = {
shell : Block_header.shell_header ;
protocol_data : block_header_data ;
}
let block_header_data_encoding =
Data_encoding.(obj1 (req "random_data" Variable.bytes))
type operation_data = unit
type operation = {
shell : Operation.shell_header ;
protocol_data : operation_data ;
}
let operation_data_encoding = Data_encoding.unit
let max_block_length = 42 let max_block_length = 42
let validation_passes = [] let validation_passes = []
let acceptable_passes _op = [] let acceptable_passes _op = []
let parse_operation h _ = Ok h
let compare_operations _ _ = 0 let compare_operations _ _ = 0
type validation_state = { type validation_state = {
@ -57,16 +67,15 @@ end
let precheck_block let precheck_block
~ancestor_context:_ ~ancestor_context:_
~ancestor_timestamp:_ ~ancestor_timestamp:_
raw_block = (_raw_block : block_header) =
Fitness.to_int64 raw_block.Block_header.shell.fitness >>=? fun _ ->
return () return ()
let begin_application let begin_application
~predecessor_context:context ~predecessor_context:context
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_fitness:_ ~predecessor_fitness:_
raw_block = (raw_block : block_header) =
Fitness.to_int64 raw_block.Block_header.shell.fitness >>=? fun fitness -> Fitness.to_int64 raw_block.shell.fitness >>=? fun fitness ->
return { context ; fitness } return { context ; fitness }
let begin_construction let begin_construction

View File

@ -20,8 +20,8 @@ sleep 2
dictator_secret="unencrypted:edsk31vznjHSSpGExDMHYASz45VZqXN4DPxvsa4hAyY8dHM28cZzp6" dictator_secret="unencrypted:edsk31vznjHSSpGExDMHYASz45VZqXN4DPxvsa4hAyY8dHM28cZzp6"
# autogenerated from the demo source # autogenerated from the demo source
protocol_version="Ps1ZDZdgRP4PFDkzmFpiYtE7gJHioavCMxC96i9zJsK6URwSXSJ" protocol_version="PsbyjqSF59ENfaQxUcRqVa4DXjzUG8gP2NVEGiXpN3GntcXrV8Q"
protocol_short="Ps1ZDZdgRP4PFD" protocol_short="PsbyjqSF59ENfa"
bake bake

View File

@ -14,7 +14,7 @@ show_logs="no"
sleep 2 sleep 2
# autogenerated from the demo source # autogenerated from the demo source
protocol_version="PsxS1brZfzzXCiFwirbMtQr4X5XR6SiHQ46HajpFDdk9GBXR6vy" protocol_version="PsbyjqSF59ENfaQxUcRqVa4DXjzUG8gP2NVEGiXpN3GntcXrV8Q"
$admin_client inject protocol "$test_dir/demo" $admin_client inject protocol "$test_dir/demo"
$admin_client list protocols $admin_client list protocols

View File

@ -20,8 +20,8 @@ sleep 2
dictator_secret="unencrypted:edsk31vznjHSSpGExDMHYASz45VZqXN4DPxvsa4hAyY8dHM28cZzp6" dictator_secret="unencrypted:edsk31vznjHSSpGExDMHYASz45VZqXN4DPxvsa4hAyY8dHM28cZzp6"
# autogenerated from the demo source # autogenerated from the demo source
protocol_version="Ps1ZDZdgRP4PFDkzmFpiYtE7gJHioavCMxC96i9zJsK6URwSXSJ" protocol_version="PsbyjqSF59ENfaQxUcRqVa4DXjzUG8gP2NVEGiXpN3GntcXrV8Q"
protocol_short="Ps1ZDZdgRP4PFD" protocol_short="PsbyjqSF59ENfa"
bake bake

View File

@ -67,13 +67,29 @@ module type PROTOCOL = sig
operation's quota for each pass. *) operation's quota for each pass. *)
val validation_passes: quota list val validation_passes: quota list
(** The version specific type of operations. *) (** The version specific type of blocks. *)
type operation type block_header_data
(** The parsing / preliminary validation function for (** Encoding for version specific part of block headers. *)
operations. Similar to {!parse_block}. *) val block_header_data_encoding: block_header_data Data_encoding.t
val parse_operation:
Operation_hash.t -> Operation.t -> operation tzresult (** A fully parsed block header. *)
type block_header = {
shell: Block_header.shell_header ;
protocol_data: block_header_data ;
}
(** The version specific type of operations. *)
type operation_data
(** Encoding for version specific part of operations. *)
val operation_data_encoding: operation_data Data_encoding.t
(** A fully parsed operation. *)
type operation = {
shell: Operation.shell_header ;
protocol_data: operation_data ;
}
(** The Validation passes in which an operation can appear. (** The Validation passes in which an operation can appear.
For instance [[0]] if it only belongs to the first pass. For instance [[0]] if it only belongs to the first pass.
@ -106,7 +122,7 @@ module type PROTOCOL = sig
val precheck_block: val precheck_block:
ancestor_context: Context.t -> ancestor_context: Context.t ->
ancestor_timestamp: Time.t -> ancestor_timestamp: Time.t ->
Block_header.t -> block_header ->
unit tzresult Lwt.t unit tzresult Lwt.t
(** The first step in a block validation sequence. Initializes a (** The first step in a block validation sequence. Initializes a
@ -119,7 +135,7 @@ module type PROTOCOL = sig
predecessor_context: Context.t -> predecessor_context: Context.t ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
Block_header.t -> block_header ->
validation_state tzresult Lwt.t validation_state tzresult Lwt.t
(** Initializes a validation context for constructing a new block (** Initializes a validation context for constructing a new block
@ -138,7 +154,7 @@ module type PROTOCOL = sig
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
predecessor: Block_hash.t -> predecessor: Block_hash.t ->
timestamp: Time.t -> timestamp: Time.t ->
?protocol_data: MBytes.t -> ?protocol_data: block_header_data ->
unit -> validation_state tzresult Lwt.t unit -> validation_state tzresult Lwt.t
(** Called after {!begin_application} (or {!begin_construction}) and (** Called after {!begin_application} (or {!begin_construction}) and

View File

@ -61,9 +61,18 @@ module Make (Context : CONTEXT) = struct
type 'a tzresult type 'a tzresult
val max_block_length: int val max_block_length: int
val validation_passes: quota list val validation_passes: quota list
type operation type block_header_data
val parse_operation: val block_header_data_encoding: block_header_data Data_encoding.t
Operation_hash.t -> Operation.t -> operation tzresult type block_header = {
shell: Block_header.shell_header ;
protocol_data: block_header_data ;
}
type operation_data
val operation_data_encoding: operation_data Data_encoding.t
type operation = {
shell: Operation.shell_header ;
protocol_data: operation_data ;
}
val acceptable_passes: operation -> int list val acceptable_passes: operation -> int list
val compare_operations: operation -> operation -> int val compare_operations: operation -> operation -> int
type validation_state type validation_state
@ -71,13 +80,13 @@ module Make (Context : CONTEXT) = struct
val precheck_block: val precheck_block:
ancestor_context: context -> ancestor_context: context ->
ancestor_timestamp: Time.t -> ancestor_timestamp: Time.t ->
Block_header.t -> block_header ->
unit tzresult Lwt.t unit tzresult Lwt.t
val begin_application: val begin_application:
predecessor_context: context -> predecessor_context: context ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
Block_header.t -> block_header ->
validation_state tzresult Lwt.t validation_state tzresult Lwt.t
val begin_construction: val begin_construction:
predecessor_context: context -> predecessor_context: context ->
@ -86,7 +95,7 @@ module Make (Context : CONTEXT) = struct
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
predecessor: Block_hash.t -> predecessor: Block_hash.t ->
timestamp: Time.t -> timestamp: Time.t ->
?protocol_data: MBytes.t -> ?protocol_data: block_header_data ->
unit -> validation_state tzresult Lwt.t unit -> validation_state tzresult Lwt.t
val apply_operation: val apply_operation:
validation_state -> operation -> validation_state tzresult Lwt.t validation_state -> operation -> validation_state tzresult Lwt.t
@ -150,7 +159,10 @@ module Make (Context : CONTEXT) = struct
val wrap_error : 'a Error_monad.tzresult -> 'a tzresult val wrap_error : 'a Error_monad.tzresult -> 'a tzresult
module Lift (P : Updater.PROTOCOL) : PROTOCOL module Lift (P : Updater.PROTOCOL) : PROTOCOL
with type operation = P.operation with type block_header_data = P.block_header_data
and type block_header = P.block_header
and type operation_data = P.operation_data
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 ['block] proto_rpc_context :
@ -642,7 +654,6 @@ module Make (Context : CONTEXT) = struct
let apply_operation c o = let apply_operation c o =
apply_operation c o >|= wrap_error apply_operation c o >|= wrap_error
let finalize_block c = finalize_block c >|= wrap_error let finalize_block c = finalize_block c >|= wrap_error
let parse_operation h b = parse_operation h b |> wrap_error
let init c bh = init c bh >|= wrap_error let init c bh = init c bh >|= wrap_error
end end

View File

@ -54,9 +54,18 @@ module Make (Context : CONTEXT) : sig
type 'a tzresult type 'a tzresult
val max_block_length: int val max_block_length: int
val validation_passes: quota list val validation_passes: quota list
type operation type block_header_data
val parse_operation: val block_header_data_encoding: block_header_data Data_encoding.t
Operation_hash.t -> Operation.t -> operation tzresult type block_header = {
shell: Block_header.shell_header ;
protocol_data: block_header_data ;
}
type operation_data
val operation_data_encoding: operation_data Data_encoding.t
type operation = {
shell: Operation.shell_header ;
protocol_data: operation_data ;
}
val acceptable_passes: operation -> int list val acceptable_passes: operation -> int list
val compare_operations: operation -> operation -> int val compare_operations: operation -> operation -> int
type validation_state type validation_state
@ -64,13 +73,13 @@ module Make (Context : CONTEXT) : sig
val precheck_block: val precheck_block:
ancestor_context: context -> ancestor_context: context ->
ancestor_timestamp: Time.t -> ancestor_timestamp: Time.t ->
Block_header.t -> block_header ->
unit tzresult Lwt.t unit tzresult Lwt.t
val begin_application: val begin_application:
predecessor_context: context -> predecessor_context: context ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
Block_header.t -> block_header ->
validation_state tzresult Lwt.t validation_state tzresult Lwt.t
val begin_construction: val begin_construction:
predecessor_context: context -> predecessor_context: context ->
@ -79,7 +88,7 @@ module Make (Context : CONTEXT) : sig
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
predecessor: Block_hash.t -> predecessor: Block_hash.t ->
timestamp: Time.t -> timestamp: Time.t ->
?protocol_data: MBytes.t -> ?protocol_data: block_header_data ->
unit -> validation_state tzresult Lwt.t unit -> validation_state tzresult Lwt.t
val apply_operation: val apply_operation:
validation_state -> operation -> validation_state tzresult Lwt.t validation_state -> operation -> validation_state tzresult Lwt.t
@ -143,7 +152,10 @@ module Make (Context : CONTEXT) : sig
val wrap_error : 'a Error_monad.tzresult -> 'a tzresult val wrap_error : 'a Error_monad.tzresult -> 'a tzresult
module Lift (P : Updater.PROTOCOL) : PROTOCOL module Lift (P : Updater.PROTOCOL) : PROTOCOL
with type operation = P.operation with type block_header_data = P.block_header_data
and type block_header = P.block_header
and type operation_data = P.operation_data
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 ['block] proto_rpc_context :

View File

@ -142,15 +142,31 @@ let apply_block
operations Proto.validation_passes >>=? fun () -> operations Proto.validation_passes >>=? fun () ->
let operation_hashes = List.map (List.map Operation.hash) operations in let operation_hashes = List.map (List.map Operation.hash) operations in
check_liveness chain_state pred hash operation_hashes operations >>=? fun () -> check_liveness chain_state pred hash operation_hashes operations >>=? fun () ->
mapi2_s (fun pass -> map2_s begin fun op_hash raw -> begin
Lwt.return (Proto.parse_operation op_hash raw) match
|> trace (invalid_block hash (Cannot_parse_operation op_hash)) >>=? fun op -> Data_encoding.Binary.of_bytes
let allowed_pass = Proto.acceptable_passes op in Proto.block_header_data_encoding
fail_unless (List.mem pass allowed_pass) header.protocol_data with
(invalid_block hash | None ->
(Unallowed_pass { operation = op_hash ; fail (invalid_block hash Cannot_parse_block_header)
pass ; allowed_pass } )) >>=? fun () -> | Some protocol_data ->
return op return ({ shell = header.shell ; protocol_data } : Proto.block_header)
end >>=? fun header ->
mapi2_s (fun pass -> map2_s begin fun op_hash op ->
match
Data_encoding.Binary.of_bytes
Proto.operation_data_encoding
op.Operation.proto with
| None ->
fail (invalid_block hash (Cannot_parse_operation op_hash))
| Some protocol_data ->
let op = { Proto.shell = op.shell ; protocol_data } in
let allowed_pass = Proto.acceptable_passes op in
fail_unless (List.mem pass allowed_pass)
(invalid_block hash
(Unallowed_pass { operation = op_hash ;
pass ; allowed_pass } )) >>=? fun () ->
return op
end) end)
operation_hashes operation_hashes
operations >>=? fun parsed_operations -> operations >>=? fun parsed_operations ->

View File

@ -82,6 +82,18 @@ let start_prevalidation
Context.reset_test_chain Context.reset_test_chain
predecessor_context predecessor predecessor_context predecessor
timestamp >>= fun predecessor_context -> timestamp >>= fun predecessor_context ->
begin
match protocol_data with
| None -> return None
| Some protocol_data ->
match
Data_encoding.Binary.of_bytes
Proto.block_header_data_encoding
protocol_data
with
| None -> failwith "Invalid block header"
| Some protocol_data -> return (Some protocol_data)
end >>=? fun protocol_data ->
Proto.begin_construction Proto.begin_construction
~predecessor_context ~predecessor_context
~predecessor_timestamp ~predecessor_timestamp
@ -105,7 +117,13 @@ let prevalidate
let ops = let ops =
List.map List.map
(fun (h, op) -> (fun (h, op) ->
(h, op, Proto.parse_operation h op |> record_trace Parse_error)) let parsed_op =
match Data_encoding.Binary.of_bytes
Proto.operation_data_encoding
op.Operation.proto with
| None -> error Parse_error
| Some protocol_data -> Ok ({ shell = op.shell ; protocol_data }: Proto.operation) in
(h, op, parsed_op))
ops in ops in
let invalid_ops = let invalid_ops =
List.filter_map List.filter_map

View File

@ -76,6 +76,13 @@ let block _state ?(context = Context_hash.zero) ?(operations = []) (pred: State.
protocol_data = MBytes.of_string name ; protocol_data = MBytes.of_string name ;
} }
let parsed_block ({ shell ; protocol_data } : Block_header.t) =
let protocol_data =
Data_encoding.Binary.of_bytes_exn
Proto.block_header_data_encoding
protocol_data in
({ shell ; protocol_data } : Proto.block_header)
let build_valid_chain state vtbl pred names = let build_valid_chain state vtbl pred names =
Lwt_list.fold_left_s Lwt_list.fold_left_s
(fun pred name -> (fun pred name ->
@ -91,7 +98,7 @@ let build_valid_chain state vtbl pred names =
~predecessor_context ~predecessor_context
~predecessor_timestamp: pred_header.shell.timestamp ~predecessor_timestamp: pred_header.shell.timestamp
~predecessor_fitness: pred_header.shell.fitness ~predecessor_fitness: pred_header.shell.fitness
block >>=? fun vstate -> (parsed_block block) >>=? fun vstate ->
(* no operations *) (* no operations *)
Proto.finalize_block vstate Proto.finalize_block vstate
end >>=? fun ctxt -> end >>=? fun ctxt ->
@ -404,5 +411,5 @@ let wrap (n, f) =
end end
end end
let tests =List.map wrap tests let tests = List.map wrap tests

View File

@ -30,6 +30,7 @@ type block_error =
| Unallowed_pass of { operation: Operation_hash.t ; | Unallowed_pass of { operation: Operation_hash.t ;
pass: int ; pass: int ;
allowed_pass: int list } allowed_pass: int list }
| Cannot_parse_block_header
let block_error_encoding = let block_error_encoding =
let open Data_encoding in let open Data_encoding in
@ -213,6 +214,8 @@ let pp_block_error ppf = function
\ while only the following passes are allowed: @[<h>%a@]" \ while only the following passes are allowed: @[<h>%a@]"
Operation_hash.pp_short operation pass Operation_hash.pp_short operation pass
Format.(pp_print_list pp_print_int) allowed_pass Format.(pp_print_list pp_print_int) allowed_pass
| Cannot_parse_block_header ->
Format.fprintf ppf "Failed to parse the block header."
type error += type error +=
| Invalid_block of | Invalid_block of

View File

@ -30,6 +30,7 @@ type block_error =
| Unallowed_pass of { operation: Operation_hash.t ; | Unallowed_pass of { operation: Operation_hash.t ;
pass: int ; pass: int ;
allowed_pass: int list } allowed_pass: int list }
| Cannot_parse_block_header
type error += type error +=
| Invalid_block of | Invalid_block of

View File

@ -27,10 +27,13 @@ let forge_block_header
cctxt block >>=? fun stamp_threshold -> cctxt 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 protocol_data : Block_header.protocol_data = let contents =
{ priority ; seed_nonce_hash ; proof_of_work_nonce } in { Block_header.priority ; seed_nonce_hash ; proof_of_work_nonce } in
if Baking.check_header_proof_of_work_stamp shell protocol_data stamp_threshold then if Baking.check_header_proof_of_work_stamp shell contents stamp_threshold then
let unsigned_header = Block_header.forge_unsigned shell protocol_data in let unsigned_header =
Data_encoding.Binary.to_bytes_exn
Alpha_context.Block_header.unsigned_encoding
(shell, contents) in
Client_keys.append delegate_sk ~watermark:Block_header unsigned_header Client_keys.append delegate_sk ~watermark:Block_header unsigned_header
else else
loop () in loop () in
@ -41,9 +44,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 =
Alpha_context.Block_header.forge_unsigned_protocol_data Data_encoding.Binary.to_bytes_exn
{ priority ; seed_nonce_hash ; Alpha_context.Block_header.protocol_data_encoding
proof_of_work_nonce = empty_proof_of_work_nonce } { contents = { priority ; seed_nonce_hash ;
proof_of_work_nonce = empty_proof_of_work_nonce } ;
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 =
@ -95,13 +100,14 @@ let () =
let classify_operations (ops: Operation.raw list) = let classify_operations (ops: Operation.raw 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 -> (fun (op: Operation.raw) ->
match Operation.parse op with match Data_encoding.Binary.of_bytes Operation.protocol_data_encoding op.proto with
| Ok o -> | 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 o) (Proto_alpha.Main.acceptable_passes
| Error _ -> ()) { 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 []

View File

@ -31,7 +31,7 @@ let preapply
get_branch cctxt block branch >>=? fun branch -> get_branch cctxt block branch >>=? fun branch ->
let bytes = let bytes =
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
Operation.unsigned_operation_encoding Operation.unsigned_encoding
({ branch }, contents) in ({ branch }, contents) in
let watermark = let watermark =
match contents with match contents with
@ -49,8 +49,7 @@ let preapply
end >>=? fun signature -> end >>=? fun signature ->
let op = let op =
{ shell = { branch } ; { shell = { branch } ;
contents ; protocol_data = { contents ; signature } } in
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 block >>=? fun bh ->
Alpha_services.Helpers.apply_operation cctxt Alpha_services.Helpers.apply_operation cctxt

View File

@ -18,7 +18,7 @@ val preapply:
Block_services.block -> Block_services.block ->
?branch:int -> ?branch:int ->
?src_sk:Client_keys.sk_uri -> ?src_sk:Client_keys.sk_uri ->
proto_operation -> Operation.contents ->
result tzresult Lwt.t result tzresult Lwt.t
val inject_operation: val inject_operation:
@ -27,7 +27,7 @@ val inject_operation:
?confirmations:int -> ?confirmations:int ->
?branch:int -> ?branch:int ->
?src_sk:Client_keys.sk_uri -> ?src_sk:Client_keys.sk_uri ->
proto_operation -> Operation.contents ->
result tzresult Lwt.t result tzresult Lwt.t
val originated_contracts: operation_result -> Contract.t list tzresult val originated_contracts: operation_result -> Contract.t list tzresult

View File

@ -134,7 +134,8 @@ let pp_balance_updates ppf = function
Format.fprintf ppf "@[<v 0>%a@]" Format.fprintf ppf "@[<v 0>%a@]"
(Format.pp_print_list pp_one) balance_updates (Format.pp_print_list pp_one) balance_updates
let pp_operation_result ppf ({ contents ; _ }, operation_result) = let pp_operation_result ppf
({ protocol_data = { contents ; _ } }, operation_result) =
Format.fprintf ppf "@[<v 0>" ; Format.fprintf ppf "@[<v 0>" ;
begin match contents, operation_result with begin match contents, operation_result with
| Anonymous_operations ops, Anonymous_operations_result rs -> | Anonymous_operations ops, Anonymous_operations_result rs ->

View File

@ -27,7 +27,11 @@ end
include Operation_repr include Operation_repr
module Operation = struct module Operation = struct
type t = operation type t = operation = {
shell: Operation.shell_header ;
protocol_data: protocol_data ;
}
let unsigned_encoding = unsigned_operation_encoding
include Operation_repr include Operation_repr
end end
module Block_header = Block_header_repr module Block_header = Block_header_repr

View File

@ -683,10 +683,14 @@ module Block_header : sig
type t = { type t = {
shell: Block_header.shell_header ; shell: Block_header.shell_header ;
protocol_data: protocol_data ; protocol_data: protocol_data ;
signature: Signature.t ;
} }
and protocol_data = { and protocol_data = {
contents: contents ;
signature: Signature.t ;
}
and contents = {
priority: int ; priority: int ;
seed_nonce_hash: Nonce_hash.t option ; seed_nonce_hash: Nonce_hash.t option ;
proof_of_work_nonce: MBytes.t ; proof_of_work_nonce: MBytes.t ;
@ -702,39 +706,27 @@ module Block_header : sig
val encoding: block_header Data_encoding.encoding val encoding: block_header Data_encoding.encoding
val raw_encoding: raw Data_encoding.t val raw_encoding: raw Data_encoding.t
val contents_encoding: contents Data_encoding.t
val unsigned_encoding: (shell_header * contents) Data_encoding.t
val protocol_data_encoding: protocol_data Data_encoding.encoding val protocol_data_encoding: protocol_data Data_encoding.encoding
val shell_header_encoding: shell_header Data_encoding.encoding val shell_header_encoding: shell_header Data_encoding.encoding
val max_header_length: int val max_header_length: int
(** The maximum size of block headers in bytes *) (** The maximum size of block headers in bytes *)
val parse: Block_header.t -> block_header tzresult
(** Parse the protocol-specific part of a block header. *)
val parse_unsigned_protocol_data: MBytes.t -> protocol_data tzresult
(** Parse the (unsigned) protocol-specific part of a block header. *)
val forge_unsigned_protocol_data: protocol_data -> MBytes.t
(** [forge_header proto_hdr] is the binary serialization
(using [protocol_data_encoding]) of the protocol-specific part
of a block header, without the signature. *)
val forge_unsigned:
Block_header.shell_header -> protocol_data -> MBytes.t
(** [forge_header shell_hdr proto_hdr] is the binary serialization
(using [unsigned_header_encoding]) of a block header,
comprising both the shell and the protocol part of the header,
without the signature. *)
end end
type operation = { type operation = {
shell: Operation.shell_header ; shell: Operation.shell_header ;
contents: proto_operation ; protocol_data: protocol_data ;
signature: signature option ;
} }
and proto_operation = and protocol_data = {
contents: contents ;
signature: Signature.t option ;
}
and contents =
| Anonymous_operations of anonymous_operation list | Anonymous_operations of anonymous_operation list
| Sourced_operation of sourced_operation | Sourced_operation of sourced_operation
@ -822,37 +814,35 @@ type internal_operation = {
module Operation : sig module Operation : sig
type nonrec contents = contents
val contents_encoding: contents Data_encoding.t
type nonrec protocol_data = protocol_data
val protocol_data_encoding: protocol_data Data_encoding.t
val unsigned_encoding: (Operation.shell_header * contents) Data_encoding.t
type raw = Operation.t = { type raw = Operation.t = {
shell: Operation.shell_header ; shell: Operation.shell_header ;
proto: MBytes.t ; proto: MBytes.t ;
} }
val raw_encoding: raw Data_encoding.t val raw_encoding: raw Data_encoding.t
type t = operation type t = operation = {
shell: Operation.shell_header ;
protocol_data: protocol_data ;
}
val encoding: operation Data_encoding.t val encoding: operation Data_encoding.t
val hash: operation -> Operation_hash.t val hash: operation -> Operation_hash.t
val hash_raw: raw -> Operation_hash.t val hash_raw: raw -> Operation_hash.t
type error += Cannot_parse_operation (* `Branch *)
val parse: Operation.t -> operation tzresult
val acceptable_passes: operation -> int list val acceptable_passes: operation -> int list
val parse_proto:
MBytes.t -> (proto_operation * signature option) tzresult Lwt.t
type error += Missing_signature (* `Permanent *) type error += Missing_signature (* `Permanent *)
type error += Invalid_signature (* `Permanent *) type error += Invalid_signature (* `Permanent *)
val check_signature: public_key -> operation -> unit tzresult Lwt.t val check_signature: public_key -> operation -> unit tzresult Lwt.t
val forge: Operation.shell_header -> proto_operation -> MBytes.t
val proto_operation_encoding: proto_operation Data_encoding.t
val unsigned_operation_encoding:
(Operation.shell_header * proto_operation) Data_encoding.t
val internal_operation_encoding: internal_operation Data_encoding.t val internal_operation_encoding: internal_operation Data_encoding.t
end end

View File

@ -51,6 +51,25 @@ module S = struct
end 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 () =
let open Services_registration in let open Services_registration in
register0_fullctxt S.operations begin fun ctxt () () -> register0_fullctxt S.operations begin fun ctxt () () ->
@ -58,21 +77,21 @@ let () =
ctxt.operations () >>= fun operations -> ctxt.operations () >>= fun operations ->
map2_s map2_s
(map2_s (fun h op -> (map2_s (fun h op ->
Lwt.return (Operation.parse op) >>=? fun op -> Lwt.return (parse_operation op) >>=? fun op ->
return (h, op))) return (h, op)))
operation_hashes operations operation_hashes operations
end ; end ;
register0_fullctxt S.header begin fun { block_header ; _ } () () -> register0_fullctxt S.header begin fun { block_header ; _ } () () ->
Lwt.return (Block_header.parse block_header) >>=? fun block_header -> Lwt.return (parse_block_header block_header) >>=? fun block_header ->
return block_header return block_header
end ; end ;
register0_fullctxt S.priority begin fun { block_header ; _ } () () -> register0_fullctxt S.priority begin fun { block_header ; _ } () () ->
Lwt.return (Block_header.parse block_header) >>=? fun block_header -> Lwt.return (parse_block_header block_header) >>=? fun block_header ->
return block_header.protocol_data.priority return block_header.protocol_data.contents.priority
end ; end ;
opt_register0_fullctxt S.seed_nonce_hash begin fun { block_header ; _ } () ( )-> opt_register0_fullctxt S.seed_nonce_hash begin fun { block_header ; _ } () ( )->
Lwt.return (Block_header.parse block_header) >>=? fun block_header -> Lwt.return (parse_block_header block_header) >>=? fun block_header ->
return block_header.protocol_data.seed_nonce_hash return block_header.protocol_data.contents.seed_nonce_hash
end end
let operations ctxt block = let operations ctxt block =

View File

@ -625,7 +625,7 @@ let apply_anonymous_operation ctxt kind =
add_rewards ctxt seed_nonce_revelation_tip >>=? fun ctxt -> add_rewards ctxt seed_nonce_revelation_tip >>=? fun ctxt ->
return (ctxt, Seed_nonce_revelation_result [(* FIXME *)]) return (ctxt, Seed_nonce_revelation_result [(* FIXME *)])
| Double_endorsement_evidence { op1 ; op2 } -> begin | Double_endorsement_evidence { op1 ; op2 } -> begin
match op1.contents, op2.contents with match op1.protocol_data.contents, op2.protocol_data.contents with
| Sourced_operation (Consensus_operation (Endorsements e1)), | Sourced_operation (Consensus_operation (Endorsements e1)),
Sourced_operation (Consensus_operation (Endorsements e2)) Sourced_operation (Consensus_operation (Endorsements e2))
when Raw_level.(e1.level = e2.level) && when Raw_level.(e1.level = e2.level) &&
@ -682,10 +682,10 @@ let apply_anonymous_operation ctxt kind =
last = oldest_level }) >>=? fun () -> last = oldest_level }) >>=? fun () ->
let level = Level.from_raw ctxt raw_level in let level = Level.from_raw ctxt raw_level in
Roll.baking_rights_owner Roll.baking_rights_owner
ctxt level ~priority:bh1.protocol_data.priority >>=? fun delegate1 -> ctxt level ~priority:bh1.protocol_data.contents.priority >>=? fun delegate1 ->
Baking.check_signature bh1 delegate1 >>=? fun () -> Baking.check_signature bh1 delegate1 >>=? fun () ->
Roll.baking_rights_owner Roll.baking_rights_owner
ctxt level ~priority:bh2.protocol_data.priority >>=? fun delegate2 -> ctxt level ~priority:bh2.protocol_data.contents.priority >>=? fun delegate2 ->
Baking.check_signature bh2 delegate2 >>=? fun () -> Baking.check_signature bh2 delegate2 >>=? fun () ->
fail_unless fail_unless
(Signature.Public_key.equal delegate1 delegate2) (Signature.Public_key.equal delegate1 delegate2)
@ -717,7 +717,7 @@ let apply_anonymous_operation ctxt kind =
let apply_operation ctxt mode pred_block hash operation = let apply_operation ctxt mode pred_block hash operation =
let ctxt = Contract.init_origination_nonce ctxt hash in let ctxt = Contract.init_origination_nonce ctxt hash in
begin match operation.contents with begin match operation.protocol_data.contents with
| Anonymous_operations ops -> | Anonymous_operations ops ->
fold_left_s fold_left_s
(fun (ctxt, acc) op -> (fun (ctxt, acc) op ->
@ -759,9 +759,6 @@ let may_start_new_cycle ctxt =
return ctxt return ctxt
let begin_full_construction ctxt pred_timestamp protocol_data = let begin_full_construction ctxt pred_timestamp protocol_data =
Lwt.return
(Block_header.parse_unsigned_protocol_data
protocol_data) >>=? fun protocol_data ->
Baking.check_baking_rights Baking.check_baking_rights
ctxt protocol_data pred_timestamp >>=? fun delegate_pk -> ctxt protocol_data pred_timestamp >>=? fun delegate_pk ->
let delegate_pkh = Signature.Public_key.hash delegate_pk in let delegate_pkh = Signature.Public_key.hash delegate_pk in
@ -778,10 +775,10 @@ let begin_application ctxt block_header pred_timestamp =
Baking.check_proof_of_work_stamp ctxt block_header >>=? fun () -> Baking.check_proof_of_work_stamp ctxt block_header >>=? fun () ->
Baking.check_fitness_gap ctxt block_header >>=? fun () -> Baking.check_fitness_gap ctxt block_header >>=? fun () ->
Baking.check_baking_rights Baking.check_baking_rights
ctxt block_header.protocol_data pred_timestamp >>=? fun delegate_pk -> ctxt block_header.protocol_data.contents pred_timestamp >>=? fun delegate_pk ->
Baking.check_signature block_header delegate_pk >>=? fun () -> Baking.check_signature block_header delegate_pk >>=? fun () ->
let has_commitment = let has_commitment =
match block_header.protocol_data.seed_nonce_hash with match block_header.protocol_data.contents.seed_nonce_hash with
| None -> false | None -> false
| Some _ -> true in | Some _ -> true in
fail_unless fail_unless
@ -790,7 +787,7 @@ let begin_application ctxt block_header pred_timestamp =
{ expected = current_level.expected_commitment }) >>=? fun () -> { expected = current_level.expected_commitment }) >>=? fun () ->
let delegate_pkh = Signature.Public_key.hash delegate_pk in let delegate_pkh = Signature.Public_key.hash delegate_pk in
Baking.freeze_baking_deposit ctxt Baking.freeze_baking_deposit ctxt
block_header.protocol_data delegate_pkh >>=? fun (ctxt, deposit) -> block_header.protocol_data.contents delegate_pkh >>=? fun (ctxt, deposit) ->
let ctxt = Fitness.increase ctxt in let ctxt = Fitness.increase ctxt in
return (ctxt, delegate_pk, deposit) return (ctxt, delegate_pk, deposit)
@ -818,7 +815,7 @@ let finalize_application ctxt protocol_data delegate =
return ctxt return ctxt
let compare_operations op1 op2 = let compare_operations op1 op2 =
match op1.contents, op2.contents with match op1.protocol_data.contents, op2.protocol_data.contents with
| Anonymous_operations _, Anonymous_operations _ -> 0 | Anonymous_operations _, Anonymous_operations _ -> 0
| Anonymous_operations _, Sourced_operation _ -> -1 | Anonymous_operations _, Sourced_operation _ -> -1
| Sourced_operation _, Anonymous_operations _ -> 1 | Sourced_operation _, Anonymous_operations _ -> 1

View File

@ -251,25 +251,29 @@ let check_hash hash stamp_threshold =
let word = MBytes.get_int64 bytes 0 in let word = MBytes.get_int64 bytes 0 in
Compare.Uint64.(word <= stamp_threshold) Compare.Uint64.(word <= stamp_threshold)
let check_header_proof_of_work_stamp shell protocol_data stamp_threshold = let check_header_proof_of_work_stamp shell contents stamp_threshold =
let hash = let hash =
Block_header.hash Block_header.hash
{ shell ; protocol_data ; signature = Signature.zero } in { shell ; protocol_data = { contents ; signature = Signature.zero } } in
check_hash hash stamp_threshold check_hash hash stamp_threshold
let check_proof_of_work_stamp ctxt block = let check_proof_of_work_stamp ctxt block =
let proof_of_work_threshold = Constants.proof_of_work_threshold ctxt in let proof_of_work_threshold = Constants.proof_of_work_threshold ctxt in
if check_header_proof_of_work_stamp if check_header_proof_of_work_stamp
block.Block_header.shell block.Block_header.shell
block.protocol_data block.protocol_data.contents
proof_of_work_threshold then proof_of_work_threshold then
return () return ()
else else
fail Invalid_stamp fail Invalid_stamp
let check_signature block key = let check_signature block key =
let check_signature key { Block_header.protocol_data ; shell ; signature } = let check_signature key
let unsigned_header = Block_header.forge_unsigned shell protocol_data in { Block_header.shell ; protocol_data = { contents ; signature } } =
let unsigned_header =
Data_encoding.Binary.to_bytes_exn
Block_header.unsigned_encoding
(shell, contents) in
Signature.check ~watermark:Block_header key signature unsigned_header in Signature.check ~watermark:Block_header key signature unsigned_header in
if check_signature key block then if check_signature key block then
return () return ()

View File

@ -39,7 +39,7 @@ val minimal_time: context -> int -> Time.t -> Time.t tzresult Lwt.t
funds to claim baking rights. *) funds to claim baking rights. *)
val freeze_baking_deposit: val freeze_baking_deposit:
context -> context ->
Block_header.protocol_data -> Block_header.contents ->
public_key_hash -> public_key_hash ->
(context * Tez.t) tzresult Lwt.t (context * Tez.t) tzresult Lwt.t
@ -58,7 +58,7 @@ val freeze_endorsement_deposit:
* the deposit have been payed if the slot is below [Constants.first_free_baking_slot]. * the deposit have been payed if the slot is below [Constants.first_free_baking_slot].
*) *)
val check_baking_rights: val check_baking_rights:
context -> Block_header.protocol_data -> Time.t -> context -> Block_header.contents -> Time.t ->
public_key tzresult Lwt.t public_key tzresult Lwt.t
(** [check_endorsements_rights c slots]: (** [check_endorsements_rights c slots]:
@ -108,7 +108,7 @@ val check_signature: Block_header.t -> public_key -> unit tzresult Lwt.t
is does not impact the proof-of-work stamp. The stamp is checked on is does not impact the proof-of-work stamp. The stamp is checked on
the hash of a block header whose signature has been zeroed-out. *) the hash of a block header whose signature has been zeroed-out. *)
val check_header_proof_of_work_stamp: val check_header_proof_of_work_stamp:
Block_header.shell_header -> Block_header.protocol_data -> int64 -> bool Block_header.shell_header -> Block_header.contents -> int64 -> bool
(** verify if the proof of work stamp is valid *) (** verify if the proof of work stamp is valid *)
val check_proof_of_work_stamp: val check_proof_of_work_stamp:

View File

@ -9,14 +9,17 @@
(** Block header *) (** Block header *)
(** Exported type *)
type t = { type t = {
shell: Block_header.shell_header ; shell: Block_header.shell_header ;
protocol_data: protocol_data ; protocol_data: protocol_data ;
signature: Signature.t ;
} }
and protocol_data = { and protocol_data = {
contents: contents ;
signature: Signature.t ;
}
and contents = {
priority: int ; priority: int ;
seed_nonce_hash: Nonce_hash.t option ; seed_nonce_hash: Nonce_hash.t option ;
proof_of_work_nonce: MBytes.t ; proof_of_work_nonce: MBytes.t ;
@ -30,7 +33,7 @@ type shell_header = Block_header.shell_header
let raw_encoding = Block_header.encoding let raw_encoding = Block_header.encoding
let shell_header_encoding = Block_header.shell_header_encoding let shell_header_encoding = Block_header.shell_header_encoding
let protocol_data_encoding = let contents_encoding =
let open Data_encoding in let open Data_encoding in
conv conv
(fun { priority ; seed_nonce_hash ; proof_of_work_nonce } -> (fun { priority ; seed_nonce_hash ; proof_of_work_nonce } ->
@ -43,28 +46,31 @@ let protocol_data_encoding =
(Fixed.bytes Constants_repr.proof_of_work_nonce_size)) (Fixed.bytes Constants_repr.proof_of_work_nonce_size))
(opt "seed_nonce_hash" Nonce_hash.encoding)) (opt "seed_nonce_hash" Nonce_hash.encoding))
let signed_protocol_data_encoding = let protocol_data_encoding =
let open Data_encoding in let open Data_encoding in
merge_objs conv
protocol_data_encoding (fun { contents ; signature } -> (contents, signature))
(obj1 (req "signature" Signature.encoding)) (fun (contents, signature) -> { contents ; signature })
(merge_objs
contents_encoding
(obj1 (req "signature" Signature.encoding)))
let unsigned_header_encoding = let unsigned_encoding =
let open Data_encoding in let open Data_encoding in
merge_objs merge_objs
Block_header.shell_header_encoding Block_header.shell_header_encoding
protocol_data_encoding contents_encoding
let encoding = let encoding =
let open Data_encoding in let open Data_encoding in
conv conv
(fun { shell ; protocol_data ; signature } -> (fun { shell ; protocol_data } ->
(shell, (protocol_data, signature))) (shell, protocol_data))
(fun (shell, (protocol_data, signature)) -> (fun (shell, protocol_data) ->
{ shell ; protocol_data ; signature }) { shell ; protocol_data })
(merge_objs (merge_objs
Block_header.shell_header_encoding Block_header.shell_header_encoding
signed_protocol_data_encoding) protocol_data_encoding)
(** Constants *) (** Constants *)
@ -74,47 +80,16 @@ let max_header_length =
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
signed_protocol_data_encoding protocol_data_encoding
(fake, Signature.zero) { contents = fake ; signature = Signature.zero}
(** Header parsing entry point *) (** Header parsing entry point *)
type error +=
| Cant_parse_protocol_data
let parse
({ shell = { level ; proto_level ; predecessor ;
timestamp ; fitness ; validation_passes ; operations_hash ;
context } ;
protocol_data } : Block_header.t) : block_header tzresult =
match
Data_encoding.Binary.of_bytes signed_protocol_data_encoding protocol_data
with
| None -> Error [Cant_parse_protocol_data]
| Some (protocol_data, signature) ->
let shell =
{ Block_header.level ; proto_level ; predecessor ;
timestamp ; fitness ; validation_passes ; operations_hash ;
context } in
Ok { shell ; protocol_data ; signature }
let parse_unsigned_protocol_data bytes =
match Data_encoding.Binary.of_bytes protocol_data_encoding bytes with
| None -> Error [Cant_parse_protocol_data]
| Some proto -> Ok proto
let forge_unsigned shell proto =
Data_encoding.Binary.to_bytes_exn unsigned_header_encoding (shell, proto)
let forge_unsigned_protocol_data proto =
Data_encoding.Binary.to_bytes_exn protocol_data_encoding proto
let hash_raw = Block_header.hash let hash_raw = Block_header.hash
let hash { shell ; protocol_data ; signature } = let hash { shell ; protocol_data } =
Block_header.hash Block_header.hash
{ shell ; { shell ;
protocol_data = protocol_data =
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
signed_protocol_data_encoding protocol_data_encoding
(protocol_data, signature ) } protocol_data }

View File

@ -7,14 +7,17 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
(** Exported type *)
type t = { type t = {
shell: Block_header.shell_header ; shell: Block_header.shell_header ;
protocol_data: protocol_data ; protocol_data: protocol_data ;
signature: Signature.t ;
} }
and protocol_data = { and protocol_data = {
contents: contents ;
signature: Signature.t ;
}
and contents = {
priority: int ; priority: int ;
seed_nonce_hash: Nonce_hash.t option ; seed_nonce_hash: Nonce_hash.t option ;
proof_of_work_nonce: MBytes.t ; proof_of_work_nonce: MBytes.t ;
@ -27,29 +30,13 @@ type shell_header = Block_header.shell_header
val encoding: block_header Data_encoding.encoding val encoding: block_header Data_encoding.encoding
val raw_encoding: raw Data_encoding.t val raw_encoding: raw Data_encoding.t
val contents_encoding: contents Data_encoding.t
val unsigned_encoding: (Block_header.shell_header * contents) Data_encoding.t
val protocol_data_encoding: protocol_data Data_encoding.encoding val protocol_data_encoding: protocol_data Data_encoding.encoding
val shell_header_encoding: shell_header Data_encoding.encoding val shell_header_encoding: shell_header Data_encoding.encoding
val max_header_length: int val max_header_length: int
(** The maximum size of block headers in bytes *) (** The maximum size of block headers in bytes *)
val parse: Block_header.t -> block_header tzresult
(** Parse the (signed) protocol-specific part of a block header. *)
val parse_unsigned_protocol_data: MBytes.t -> protocol_data tzresult
(** Parse the (unsigned) protocol-specific part of a block header. *)
val forge_unsigned_protocol_data: protocol_data -> MBytes.t
(** [forge_header proto_hdr] is the binary serialization
(using [protocol_data_encoding]) of the protocol-specific part
of a block header, without the signature. *)
val forge_unsigned:
Block_header.shell_header -> protocol_data -> MBytes.t
(** [forge_header shell_hdr proto_hdr] is the binary serialization
(using [unsigned_header_encoding]) of a block header,
comprising both the shell and the protocol part of the header,
without the signature. *)
val hash: block_header -> Block_hash.t val hash: block_header -> Block_hash.t
val hash_raw: raw -> Block_hash.t val hash_raw: raw -> Block_hash.t

View File

@ -9,6 +9,31 @@
open Alpha_context open Alpha_context
type error +=
| Cannot_parse_operation (* `Branch *)
| Cant_parse_block_header
let () =
register_error_kind
`Branch
~id:"operation.cannot_parse"
~title:"Cannot parse operation"
~description:"The operation is ill-formed \
or for another protocol version"
~pp:(fun ppf () ->
Format.fprintf ppf "The operation cannot be parsed")
Data_encoding.unit
(function Cannot_parse_operation -> Some () | _ -> None)
(fun () -> Cannot_parse_operation)
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 Cannot_parse_operation
module S = struct module S = struct
open Data_encoding open Data_encoding
@ -135,13 +160,14 @@ module I = struct
let apply_operation ctxt () (pred_block, hash, forged_operation, signature) = let apply_operation ctxt () (pred_block, hash, forged_operation, signature) =
(* ctxt accept_failing_script baker_contract pred_block block_prio operation *) (* ctxt accept_failing_script baker_contract pred_block block_prio operation *)
match Data_encoding.Binary.of_bytes match Data_encoding.Binary.of_bytes
Operation.unsigned_operation_encoding Operation.unsigned_encoding
forged_operation with forged_operation with
| None -> Error_monad.fail Operation.Cannot_parse_operation | None -> fail Cannot_parse_operation
| Some (shell, contents) -> | Some (shell, contents) ->
let operation = { shell ; contents ; signature } in let operation = { shell ; protocol_data = { contents ; signature } } in
Apply.apply_operation ctxt Readable pred_block hash operation Apply.apply_operation
>>=? fun (_, result) -> return result ctxt Readable pred_block hash operation >>=? fun (_, result) ->
return result
end end
@ -259,7 +285,7 @@ module Forge = struct
RPC_service.post_service RPC_service.post_service
~description:"Forge an operation" ~description:"Forge an operation"
~query: RPC_query.empty ~query: RPC_query.empty
~input: Operation.unsigned_operation_encoding ~input: Operation.unsigned_encoding
~output: ~output:
(obj1 (obj1
(req "operation" bytes)) (req "operation" bytes))
@ -289,11 +315,13 @@ module Forge = struct
let () = let () =
let open Services_registration in let open Services_registration in
register0_noctxt S.operations begin fun () (shell, proto) -> register0_noctxt S.operations begin fun () (shell, proto) ->
return (Operation.forge shell proto) return (Data_encoding.Binary.to_bytes_exn
Operation.unsigned_encoding (shell, proto))
end ; end ;
register0_noctxt S.protocol_data begin fun () register0_noctxt S.protocol_data begin fun ()
(priority, seed_nonce_hash, proof_of_work_nonce) -> (priority, seed_nonce_hash, proof_of_work_nonce) ->
return (Block_header.forge_unsigned_protocol_data return (Data_encoding.Binary.to_bytes_exn
Block_header.contents_encoding
{ priority ; seed_nonce_hash ; proof_of_work_nonce }) { priority ; seed_nonce_hash ; proof_of_work_nonce })
end end
@ -489,37 +517,47 @@ module Parse = struct
Roll.delegate_pubkey ctxt manager Roll.delegate_pubkey ctxt manager
end >>=? fun public_key -> end >>=? fun public_key ->
Operation.check_signature public_key Operation.check_signature public_key
{ signature ; shell ; contents } { shell ; protocol_data = { contents ; signature } }
| Sourced_operation (Consensus_operation (Endorsements { level ; slots ; _ })) -> | Sourced_operation (Consensus_operation (Endorsements { level ; slots ; _ })) ->
let level = Level.from_raw ctxt level in let level = Level.from_raw ctxt level in
Baking.check_endorsements_rights ctxt level slots >>=? fun public_key -> Baking.check_endorsements_rights ctxt level slots >>=? fun public_key ->
Operation.check_signature public_key Operation.check_signature public_key
{ signature ; shell ; contents } { shell ; protocol_data = { contents ; signature } }
| Sourced_operation (Amendment_operation { source ; _ }) -> | Sourced_operation (Amendment_operation { source ; _ }) ->
Roll.delegate_pubkey ctxt source >>=? fun source -> Roll.delegate_pubkey ctxt source >>=? fun source ->
Operation.check_signature source Operation.check_signature source
{ signature ; shell ; contents } { shell ; protocol_data = { contents ; signature } }
| Sourced_operation (Dictator_operation _) -> | Sourced_operation (Dictator_operation _) ->
let key = Constants.dictator_pubkey ctxt in let key = Constants.dictator_pubkey ctxt in
Operation.check_signature key Operation.check_signature key
{ signature ; shell ; contents } { shell ; protocol_data = { contents ; signature } }
end end
let parse_protocol_data protocol_data =
match
Data_encoding.Binary.of_bytes
Block_header.protocol_data_encoding
protocol_data
with
| None -> failwith "Cant_parse_protocol_data"
| Some protocol_data -> return protocol_data
let () = let () =
let open Services_registration in let open Services_registration in
register0 S.operations begin fun ctxt () (operations, check) -> register0 S.operations begin fun ctxt () (operations, check) ->
map_s begin fun raw -> map_s begin fun raw ->
Lwt.return (Operation.parse raw) >>=? fun op -> Lwt.return (parse_operation raw) >>=? fun op ->
begin match check with begin match check with
| Some true -> I.check_signature ctxt op.signature op.shell op.contents | Some true ->
I.check_signature ctxt
op.protocol_data.signature op.shell op.protocol_data.contents
| Some false | None -> return () | Some false | None -> return ()
end >>|? fun () -> op end >>|? fun () -> op
end operations end operations
end ; end ;
register0_noctxt S.block begin fun () raw_block -> register0_noctxt S.block begin fun () raw_block ->
Lwt.return (Block_header.parse raw_block) >>=? fun { protocol_data ; _ } -> parse_protocol_data raw_block.protocol_data
return protocol_data
end end
let operations ctxt block ?check operations = let operations ctxt block ?check operations =

View File

@ -9,6 +9,10 @@
open Alpha_context open Alpha_context
type error +=
| Cannot_parse_operation (* `Branch *)
| Cant_parse_block_header
val minimal_time: val minimal_time:
'a #RPC_context.simple -> 'a #RPC_context.simple ->
?priority:int -> 'a -> Time.t shell_tzresult Lwt.t ?priority:int -> 'a -> Time.t shell_tzresult Lwt.t

View File

@ -9,9 +9,22 @@
(* Tezos Protocol Implementation - Protocol Signature Instance *) (* Tezos Protocol Implementation - Protocol Signature Instance *)
type operation = Alpha_context.operation type block_header_data = Alpha_context.Block_header.protocol_data
type block_header = Alpha_context.Block_header.t = {
shell: Block_header.shell_header ;
protocol_data: block_header_data ;
}
let block_header_data_encoding = Alpha_context.Block_header.protocol_data_encoding
type operation_data = Alpha_context.Operation.protocol_data
type operation = Alpha_context.Operation.t = {
shell: Operation.shell_header ;
protocol_data: operation_data ;
}
let operation_data_encoding = Alpha_context.Operation.protocol_data_encoding
let parse_operation _hash op = Alpha_context.Operation.parse op
let acceptable_passes = Alpha_context.Operation.acceptable_passes let acceptable_passes = Alpha_context.Operation.acceptable_passes
let max_block_length = let max_block_length =
@ -36,7 +49,7 @@ type validation_mode =
} }
| Full_construction of { | Full_construction of {
predecessor : Block_hash.t ; predecessor : Block_hash.t ;
protocol_data : Alpha_context.Block_header.protocol_data ; protocol_data : Alpha_context.Block_header.contents ;
baker : Alpha_context.public_key_hash ; baker : Alpha_context.public_key_hash ;
} }
@ -53,17 +66,15 @@ let current_context { ctxt ; _ } =
let precheck_block let precheck_block
~ancestor_context:_ ~ancestor_context:_
~ancestor_timestamp:_ ~ancestor_timestamp:_
raw_block = _block_header =
Lwt.return (Alpha_context.Block_header.parse raw_block) >>=? fun _ -> (* TODO: decide what properties should be checked *)
(* TODO: decide what other properties should be checked *)
return () return ()
let begin_application let begin_application
~predecessor_context:ctxt ~predecessor_context:ctxt
~predecessor_timestamp:pred_timestamp ~predecessor_timestamp:pred_timestamp
~predecessor_fitness:pred_fitness ~predecessor_fitness:pred_fitness
raw_block = (block_header : Alpha_context.Block_header.t) =
Lwt.return (Alpha_context.Block_header.parse raw_block) >>=? fun block_header ->
let level = block_header.shell.level in let level = block_header.shell.level in
let fitness = pred_fitness in let fitness = pred_fitness in
let timestamp = block_header.shell.timestamp in let timestamp = block_header.shell.timestamp in
@ -80,7 +91,7 @@ let begin_construction
~predecessor_fitness:pred_fitness ~predecessor_fitness:pred_fitness
~predecessor ~predecessor
~timestamp ~timestamp
?protocol_data ?(protocol_data : block_header_data option)
() = () =
let level = Int32.succ pred_level in let level = Int32.succ pred_level in
let fitness = pred_fitness in let fitness = pred_fitness in
@ -94,7 +105,7 @@ let begin_construction
| Some proto_header -> | Some proto_header ->
Apply.begin_full_construction Apply.begin_full_construction
ctxt pred_timestamp ctxt pred_timestamp
proto_header >>=? fun (ctxt, protocol_data, baker, deposit) -> proto_header.contents >>=? fun (ctxt, protocol_data, baker, deposit) ->
let mode = let mode =
let baker = Signature.Public_key.hash baker in let baker = Signature.Public_key.hash baker in
Full_construction { predecessor ; baker ; protocol_data } in Full_construction { predecessor ; baker ; protocol_data } in
@ -121,7 +132,7 @@ let finalize_block { mode ; ctxt ; op_count ; deposit = _ } =
let ctxt = Alpha_context.finalize ctxt in let ctxt = Alpha_context.finalize ctxt in
return ctxt return ctxt
| Application | Application
{ baker ; block_header = { protocol_data ; _ } } { baker ; block_header = { protocol_data = { contents = protocol_data ; _ } ; _ } }
| Full_construction { protocol_data ; baker ; _ } -> | Full_construction { protocol_data ; baker ; _ } ->
Apply.finalize_application ctxt protocol_data baker >>=? fun ctxt -> Apply.finalize_application ctxt protocol_data baker >>=? fun ctxt ->
let { level ; _ } : Alpha_context.Level.t = let { level ; _ } : Alpha_context.Level.t =

View File

@ -19,7 +19,7 @@ type validation_mode =
} }
| Full_construction of { | Full_construction of {
predecessor : Block_hash.t ; predecessor : Block_hash.t ;
protocol_data : Alpha_context.Block_header.protocol_data ; protocol_data : Alpha_context.Block_header.contents ;
baker : Alpha_context.public_key_hash ; baker : Alpha_context.public_key_hash ;
} }
@ -30,5 +30,8 @@ type validation_state =
deposit : Alpha_context.Tez.t ; deposit : Alpha_context.Tez.t ;
} }
include Updater.PROTOCOL with type operation = Alpha_context.Operation.t include Updater.PROTOCOL with type block_header_data = Alpha_context.Block_header.protocol_data
and type block_header = Alpha_context.Block_header.t
and type operation_data = Alpha_context.Operation.protocol_data
and type operation = Alpha_context.operation
and type validation_state := validation_state and type validation_state := validation_state

View File

@ -18,11 +18,15 @@ let raw_encoding = Operation.encoding
type operation = { type operation = {
shell: Operation.shell_header ; shell: Operation.shell_header ;
contents: proto_operation ; protocol_data: protocol_data ;
}
and protocol_data = {
contents: contents ;
signature: Signature.t option ; signature: Signature.t option ;
} }
and proto_operation = and contents =
| Anonymous_operations of anonymous_operation list | Anonymous_operations of anonymous_operation list
| Sourced_operation of sourced_operation | Sourced_operation of sourced_operation
@ -307,7 +311,7 @@ module Encoding = struct
(function Dictator_operation op -> Some op | _ -> None) (function Dictator_operation op -> Some op | _ -> None)
(fun op -> Dictator_operation op) (fun op -> Dictator_operation op)
let signed_operations_case tag = let sourced_operation_case tag =
case tag case tag
(union [ (union [
consensus_kind_case (Tag 0) ; consensus_kind_case (Tag 0) ;
@ -374,7 +378,7 @@ module Encoding = struct
) )
(fun ((), id, secret) -> Activation { id ; secret }) (fun ((), id, secret) -> Activation { id ; secret })
let unsigned_operation_case tag op_encoding = let anonymous_operations_case tag op_encoding =
case tag case tag
(obj1 (obj1
(req "operations" (req "operations"
@ -388,40 +392,42 @@ module Encoding = struct
(function Anonymous_operations ops -> Some ops | _ -> None) (function Anonymous_operations ops -> Some ops | _ -> None)
(fun ops -> Anonymous_operations ops) (fun ops -> Anonymous_operations ops)
let mu_proto_operation_encoding op_encoding = let contents_encoding op_encoding =
union [ union [
signed_operations_case (Tag 0) ; sourced_operation_case (Tag 0) ;
unsigned_operation_case (Tag 1) op_encoding ; anonymous_operations_case (Tag 1) op_encoding ;
] ]
let mu_signed_proto_operation_encoding op_encoding = let protocol_data_encoding op_encoding =
merge_objs conv
(mu_proto_operation_encoding op_encoding) (fun { contents ; signature } -> (contents, signature))
(obj1 (varopt "signature" Signature.encoding)) (fun (contents, signature) -> { contents ; signature })
(merge_objs
(contents_encoding op_encoding)
(obj1 (varopt "signature" Signature.encoding)))
let operation_encoding = let operation_encoding =
mu "operation" mu "operation"
(fun encoding -> (fun encoding ->
conv conv
(fun { shell ; contents ; signature } -> (fun { shell ; protocol_data } -> (shell, protocol_data))
(shell, (contents, signature))) (fun (shell, protocol_data) -> { shell ; protocol_data })
(fun (shell, (contents, signature)) ->
{ shell ; contents ; signature })
(merge_objs (merge_objs
Operation.shell_header_encoding Operation.shell_header_encoding
(mu_signed_proto_operation_encoding encoding))) (protocol_data_encoding encoding)))
let proto_operation_encoding =
mu_proto_operation_encoding operation_encoding
let signed_proto_operation_encoding = let contents_encoding =
mu_signed_proto_operation_encoding operation_encoding contents_encoding operation_encoding
let protocol_data_encoding =
protocol_data_encoding operation_encoding
let unsigned_operation_encoding = let unsigned_operation_encoding =
def "operation.alpha.unsigned_operation" @@ def "operation.alpha.unsigned_operation" @@
merge_objs merge_objs
Operation.shell_header_encoding Operation.shell_header_encoding
proto_operation_encoding contents_encoding
let internal_operation_encoding = let internal_operation_encoding =
conv conv
@ -439,33 +445,14 @@ module Encoding = struct
])) ]))
end end
type error += Cannot_parse_operation
let encoding = Encoding.operation_encoding let encoding = Encoding.operation_encoding
let contents_encoding = Encoding.contents_encoding
let () = let protocol_data_encoding = Encoding.protocol_data_encoding
register_error_kind let unsigned_operation_encoding = Encoding.unsigned_operation_encoding
`Branch let internal_operation_encoding = Encoding.internal_operation_encoding
~id:"operation.cannot_parse"
~title:"Cannot parse operation"
~description:"The operation is ill-formed \
or for another protocol version"
~pp:(fun ppf () ->
Format.fprintf ppf "The operation cannot be parsed")
Data_encoding.unit
(function Cannot_parse_operation -> Some () | _ -> None)
(fun () -> Cannot_parse_operation)
let parse (op: Operation.t) =
match Data_encoding.Binary.of_bytes
Encoding.signed_proto_operation_encoding
op.proto with
| Some (contents, signature) ->
ok { shell = op.shell ; contents ; signature }
| None -> error Cannot_parse_operation
let acceptable_passes op = let acceptable_passes op =
match op.contents with match op.protocol_data.contents with
| Sourced_operation (Consensus_operation _) -> [0] | Sourced_operation (Consensus_operation _) -> [0]
| Sourced_operation (Amendment_operation _ | Dictator_operation _) -> [1] | Sourced_operation (Amendment_operation _ | Dictator_operation _) -> [1]
| Anonymous_operations _ -> [2] | Anonymous_operations _ -> [2]
@ -498,18 +485,16 @@ let () =
(function Missing_signature -> Some () | _ -> None) (function Missing_signature -> Some () | _ -> None)
(fun () -> Missing_signature) (fun () -> Missing_signature)
let forge shell proto = let check_signature key { shell ; protocol_data } =
Data_encoding.Binary.to_bytes_exn match protocol_data.contents, protocol_data.signature with
Encoding.unsigned_operation_encoding (shell, proto)
let check_signature key { shell ; contents ; signature } =
match contents, signature with
| Anonymous_operations _, _ -> return () | Anonymous_operations _, _ -> return ()
| Sourced_operation _, None -> | Sourced_operation _, None ->
fail Missing_signature fail Missing_signature
| Sourced_operation (Consensus_operation _), Some signature -> | Sourced_operation (Consensus_operation _), Some signature ->
(* Safe for baking *) (* Safe for baking *)
let unsigned_operation = forge shell contents in let unsigned_operation =
Data_encoding.Binary.to_bytes_exn
unsigned_operation_encoding (shell, protocol_data.contents) in
if Signature.check if Signature.check
~watermark:Endorsement ~watermark:Endorsement
key signature unsigned_operation then key signature unsigned_operation then
@ -518,7 +503,9 @@ let check_signature key { shell ; contents ; signature } =
fail Invalid_signature fail Invalid_signature
| Sourced_operation _, Some signature -> | Sourced_operation _, Some signature ->
(* Unsafe for baking *) (* Unsafe for baking *)
let unsigned_operation = forge shell contents in let unsigned_operation =
Data_encoding.Binary.to_bytes_exn
unsigned_operation_encoding (shell, protocol_data.contents) in
if Signature.check if Signature.check
~watermark:Generic_operation ~watermark:Generic_operation
key signature unsigned_operation then key signature unsigned_operation then
@ -526,19 +513,10 @@ let check_signature key { shell ; contents ; signature } =
else else
fail Invalid_signature fail Invalid_signature
let parse_proto bytes =
match Data_encoding.Binary.of_bytes
Encoding.signed_proto_operation_encoding
bytes with
| Some (proto, signature) -> return (proto, signature)
| None -> fail Cannot_parse_operation
let hash_raw = Operation.hash let hash_raw = Operation.hash
let hash o = let hash o =
let proto = let proto =
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
Encoding.signed_proto_operation_encoding protocol_data_encoding
(o.contents, o.signature) in o.protocol_data in
Operation.hash { shell = o.shell ; proto } Operation.hash { shell = o.shell ; proto }
include Encoding

View File

@ -18,11 +18,15 @@ val raw_encoding: raw Data_encoding.t
type operation = { type operation = {
shell: Operation.shell_header ; shell: Operation.shell_header ;
contents: proto_operation ; protocol_data: protocol_data ;
}
and protocol_data = {
contents: contents ;
signature: Signature.t option ; signature: Signature.t option ;
} }
and proto_operation = and contents =
| Anonymous_operations of anonymous_operation list | Anonymous_operations of anonymous_operation list
| Sourced_operation of sourced_operation | Sourced_operation of sourced_operation
@ -102,21 +106,16 @@ and dictator_operation =
and counter = Int32.t and counter = Int32.t
type error += Cannot_parse_operation (* `Branch *)
val encoding: operation Data_encoding.t val encoding: operation Data_encoding.t
val contents_encoding: contents Data_encoding.t
val protocol_data_encoding: protocol_data Data_encoding.t
val unsigned_operation_encoding: (Operation.shell_header * contents) Data_encoding.t
val hash_raw: raw -> Operation_hash.t val hash_raw: raw -> Operation_hash.t
val hash: operation -> Operation_hash.t val hash: operation -> Operation_hash.t
val parse: Operation.t -> operation tzresult
val acceptable_passes: operation -> int list val acceptable_passes: operation -> int list
val parse_proto:
MBytes.t ->
(proto_operation * Signature.t option) tzresult Lwt.t
type error += Missing_signature (* `Permanent *) type error += Missing_signature (* `Permanent *)
type error += Invalid_signature (* `Permanent *) type error += Invalid_signature (* `Permanent *)
@ -124,14 +123,6 @@ type error += Invalid_signature (* `Permanent *)
val check_signature: val check_signature:
Signature.Public_key.t -> operation -> unit tzresult Lwt.t Signature.Public_key.t -> operation -> unit tzresult Lwt.t
val forge: Operation.shell_header -> proto_operation -> MBytes.t
val proto_operation_encoding:
proto_operation Data_encoding.t
val unsigned_operation_encoding:
(Operation.shell_header * proto_operation) Data_encoding.t
type internal_operation = { type internal_operation = {
source: Contract_repr.contract ; source: Contract_repr.contract ;
operation: manager_operation ; operation: manager_operation ;

View File

@ -14,7 +14,7 @@ open Alpha_context
val operation : val operation :
tc:context -> ?src:Helpers_account.t -> tc:context -> ?src:Helpers_account.t ->
Block_hash.t -> Tezos_base.Operation.shell_header -> proto_operation -> Block_hash.t -> Tezos_base.Operation.shell_header -> Operation.contents ->
(Contract.contract list * context) proto_tzresult Lwt.t (Contract.contract list * context) proto_tzresult Lwt.t
val transaction : val transaction :

View File

@ -13,12 +13,13 @@ open Error_monad
type shell_header = Block_header.shell_header type shell_header = Block_header.shell_header
type tezos_header = Block_header.t type tezos_header = Block_header.t
type protocol_data = Proto_alpha.Alpha_context.Block_header.protocol_data type protocol_data = Proto_alpha.Alpha_context.Block_header.protocol_data
type contents = Proto_alpha.Alpha_context.Block_header.contents
type operation_header = Operation.shell_header type operation_header = Operation.shell_header
type init_block = { type init_block = {
pred_block_hash : Block_hash.t ; pred_block_hash : Block_hash.t ;
pred_shell_header : shell_header ; pred_shell_header : shell_header ;
protocol_data : protocol_data ; protocol_data : contents ;
op_header : operation_header ; op_header : operation_header ;
sourced_operations : (Proto_alpha.Main.operation * Helpers_account.t) list ; sourced_operations : (Proto_alpha.Main.operation * Helpers_account.t) list ;
operation_hashs : Operation_hash.t list ; operation_hashs : Operation_hash.t list ;
@ -40,7 +41,7 @@ let get_op_header_res (res : result) : operation_header = {
branch = res.hash branch = res.hash
} }
let get_protocol_data priority commit : protocol_data = { let get_protocol_data priority commit : Alpha_context.Block_header.contents = {
priority ; priority ;
proof_of_work_nonce = Helpers_crypto.generate_proof_of_work_nonce (); proof_of_work_nonce = Helpers_crypto.generate_proof_of_work_nonce ();
seed_nonce_hash = seed_nonce_hash =
@ -68,7 +69,8 @@ let init (pred_shell_header : shell_header) pred_block_hash
let (sourced_operations, operation_hashs) = List.split src_ops_hashs in let (sourced_operations, operation_hashs) = List.split src_ops_hashs in
let protocol_data = get_protocol_data priority true in let protocol_data = get_protocol_data priority true in
let protocol_data_bytes = let protocol_data_bytes =
Proto_alpha.Alpha_context.Block_header.forge_unsigned_protocol_data Data_encoding.Binary.to_bytes_exn
Proto_alpha.Alpha_context.Block_header.contents_encoding
protocol_data protocol_data
in in
let timestamp = let timestamp =
@ -155,7 +157,9 @@ let begin_construction_pre (init_block: init_block) =
~predecessor_fitness: init_block.pred_shell_header.fitness ~predecessor_fitness: init_block.pred_shell_header.fitness
~predecessor: init_block.pred_block_hash ~predecessor: init_block.pred_block_hash
~timestamp: init_block.timestamp ~timestamp: init_block.timestamp
~protocol_data: init_block.protocol_data_bytes ~protocol_data:
(Alpha_context.Block_header.{ contents = init_block.protocol_data ;
signature = Signature.zero })
() ()

View File

@ -14,13 +14,14 @@ open Proto_alpha
type shell_header = Block_header.shell_header type shell_header = Block_header.shell_header
type tezos_header = Block_header.t type tezos_header = Block_header.t
type protocol_data = Alpha_context.Block_header.protocol_data type protocol_data = Alpha_context.Block_header.protocol_data
type contents = Proto_alpha.Alpha_context.Block_header.contents
type operation_header = Operation.shell_header type operation_header = Operation.shell_header
(** Block before application *) (** Block before application *)
type init_block = { type init_block = {
pred_block_hash : Block_hash.t; pred_block_hash : Block_hash.t;
pred_shell_header : shell_header; pred_shell_header : shell_header;
protocol_data : protocol_data; protocol_data : contents;
op_header : operation_header; op_header : operation_header;
sourced_operations : sourced_operations :
(Main.operation * Helpers_account.t) list; (Main.operation * Helpers_account.t) list;
@ -40,20 +41,20 @@ type result = {
tezos_context : Alpha_context.t; tezos_context : Alpha_context.t;
} }
val get_op_header_res : result -> operation_header val get_op_header_res : result -> operation_header
val get_protocol_data : int -> bool -> protocol_data val get_protocol_data : int -> bool -> contents
val get_op_header : Block_hash.t -> operation_header val get_op_header : Block_hash.t -> operation_header
val make_sourced_operation : val make_sourced_operation :
Operation.shell_header -> Operation.shell_header ->
Alpha_context.proto_operation * Alpha_context.Operation.contents *
Helpers_account.t -> Helpers_account.t ->
((Proto_alpha.Main.operation * Helpers_account.t) * Operation_hash.t) proto_tzresult ((Proto_alpha.Main.operation * Helpers_account.t) * Operation_hash.t) proto_tzresult
val init : val init :
shell_header -> Block_hash.t -> Int32.t -> int -> shell_header -> Block_hash.t -> Int32.t -> int ->
(Alpha_context.proto_operation * Helpers_account.t) list -> (Alpha_context.Operation.contents * Helpers_account.t) list ->
Context.t -> init_block proto_tzresult Context.t -> init_block proto_tzresult
val init_of_result : val init_of_result :
?priority:int -> res:result -> ?priority:int -> res:result ->
ops:(Alpha_context.proto_operation * Helpers_account.t) list -> ops:(Alpha_context.Operation.contents * Helpers_account.t) list ->
init_block proto_tzresult init_block proto_tzresult
val get_level : string option -> int32 val get_level : string option -> int32
val get_header_hash : val get_header_hash :
@ -64,11 +65,11 @@ val begin_construction_pre :
val make : init_block -> result proto_tzresult Lwt.t val make : init_block -> result proto_tzresult Lwt.t
val make_init : val make_init :
shell_header -> Block_hash.t -> Int32.t -> int -> shell_header -> Block_hash.t -> Int32.t -> int ->
(Alpha_context.proto_operation * Helpers_account.t) list -> (Alpha_context.Operation.contents * Helpers_account.t) list ->
Context.t -> result proto_tzresult Lwt.t Context.t -> result proto_tzresult Lwt.t
val of_res : val of_res :
?priority:int -> ?priority:int ->
?ops:(Alpha_context.proto_operation * Helpers_account.t) list -> ?ops:(Alpha_context.Operation.contents * Helpers_account.t) list ->
res:result -> res:result ->
unit -> result proto_tzresult Lwt.t unit -> result proto_tzresult Lwt.t
val endorsement : val endorsement :

View File

@ -76,7 +76,7 @@ let main () =
} in } in
let protocol_data = let protocol_data =
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
Alpha_context.Block_header.protocol_data_encoding Alpha_context.Block_header.contents_encoding
(Helpers_block.get_protocol_data 0 true) in (Helpers_block.get_protocol_data 0 true) in
let tezos_header = { Block_header.shell = header ; protocol_data } in let tezos_header = { Block_header.shell = header ; protocol_data } in
Proto_alpha.init context header >>=? fun validation -> Proto_alpha.init context header >>=? fun validation ->

View File

@ -108,27 +108,39 @@ let sign src oph protop =
Some Signature.Endorsement Some Signature.Endorsement
| _ -> | _ ->
Some Generic_operation in Some Generic_operation in
let bytes = Operation.forge oph protop in let signature =
match src with match src with
| None -> bytes, None | None -> None
| Some src -> | Some src ->
let signature = let contents =
Signature.sign ?watermark src.Helpers_account.ppk bytes in Data_encoding.Binary.to_bytes_exn
Signature.concat bytes signature, Some signature Operation.unsigned_encoding (oph, protop) in
Some (Signature.sign ?watermark src.Helpers_account.ppk contents) in
let proto_bytes =
Data_encoding.Binary.to_bytes_exn
Operation.protocol_data_encoding
{ contents = protop ; signature } in
(proto_bytes, signature)
let main_of_proto (src: Helpers_account.t) operation_header protocol_operation = let main_of_proto (src: Helpers_account.t) operation_header protocol_operation =
let (proto,_) = sign (Some src) operation_header protocol_operation in let (proto,_) = sign (Some src) operation_header protocol_operation in
let data_operation: Tezos_base.Operation.t = let data_operation: Tezos_base.Operation.t =
{shell = operation_header ; proto} in {shell = operation_header ; proto} in
let hash = Tezos_base.Operation.hash data_operation in let hash = Tezos_base.Operation.hash data_operation in
Proto_alpha.Main.parse_operation hash data_operation >>? fun op -> match Data_encoding.Binary.of_bytes
ok (op, hash) Operation.protocol_data_encoding proto with
| None ->
Error []
| Some op ->
ok ({ shell = operation_header ; protocol_data = op }, hash)
let apply_of_proto let apply_of_proto
(source: Helpers_account.t option) operation_header protocol_operation = (source: Helpers_account.t option) operation_header protocol_operation =
let (_proto, signature) = sign source operation_header protocol_operation in let (_proto, signature) = sign source operation_header protocol_operation in
{ {
shell = operation_header ; shell = operation_header ;
contents = protocol_operation ; protocol_data = {
signature contents = protocol_operation ;
signature
}
} }

View File

@ -12,7 +12,7 @@ open Alpha_context
(** Functions building operations *) (** Functions building operations *)
val sourced : sourced_operation -> proto_operation val sourced : sourced_operation -> Operation.contents
val manager : val manager :
Helpers_account.t -> ?fee:Tez.tez -> manager_operation list -> Helpers_account.t -> ?fee:Tez.tez -> manager_operation list ->
@ -20,7 +20,7 @@ val manager :
val manager_full : val manager_full :
Helpers_account.t -> ?fee:Tez.tez -> manager_operation list -> Helpers_account.t -> ?fee:Tez.tez -> manager_operation list ->
Alpha_environment.Context.t -> Z.t -> proto_operation proto_tzresult Lwt.t Alpha_environment.Context.t -> Z.t -> Operation.contents proto_tzresult Lwt.t
val transaction : val transaction :
?parameters:Script.expr -> Tez.t -> Contract.contract -> ?parameters:Script.expr -> Tez.t -> Contract.contract ->
@ -34,20 +34,20 @@ val delegation : public_key_hash -> manager_operation
val delegation_full : val delegation_full :
?fee:Tez.tez -> Helpers_account.t -> public_key_hash -> Alpha_environment.Context.t -> ?fee:Tez.tez -> Helpers_account.t -> public_key_hash -> Alpha_environment.Context.t ->
proto_operation proto_tzresult Lwt.t Operation.contents proto_tzresult Lwt.t
val script_origination_full : val script_origination_full :
Script.t option -> Helpers_account.t -> Tez.t -> Z.t -> Alpha_environment.Context.t -> Script.t option -> Helpers_account.t -> Tez.t -> Z.t -> Alpha_environment.Context.t ->
proto_operation proto_tzresult Lwt.t Operation.contents proto_tzresult Lwt.t
val origination_full : val origination_full :
?spendable:bool -> ?delegatable:bool -> ?fee:Tez.tez -> ?spendable:bool -> ?delegatable:bool -> ?fee:Tez.tez ->
Helpers_account.t -> Tez.t -> Z.t -> Alpha_environment.Context.t -> Helpers_account.t -> Tez.t -> Z.t -> Alpha_environment.Context.t ->
proto_operation proto_tzresult Lwt.t Operation.contents proto_tzresult Lwt.t
val transaction_full : val transaction_full :
?fee:Tez.tez -> ?parameters:Proto_alpha.Alpha_context.Script.expr -> Helpers_account.t -> Contract.contract -> Tez.t -> Z.t -> ?fee:Tez.tez -> ?parameters:Proto_alpha.Alpha_context.Script.expr -> Helpers_account.t -> Contract.contract -> Tez.t -> Z.t ->
Alpha_environment.Context.t -> proto_operation proto_tzresult Lwt.t Alpha_environment.Context.t -> Operation.contents proto_tzresult Lwt.t
val amendment_operation : val amendment_operation :
Helpers_account.t -> amendment_operation -> sourced_operation Helpers_account.t -> amendment_operation -> sourced_operation
@ -56,16 +56,16 @@ val endorsements :
?slot:int -> Block_hash.t -> Raw_level.t -> consensus_operation ?slot:int -> Block_hash.t -> Raw_level.t -> consensus_operation
val endorsement_full : val endorsement_full :
?slot:int -> Block_hash.t -> Raw_level.t -> proto_operation ?slot:int -> Block_hash.t -> Raw_level.t -> Operation.contents
val sign : val sign :
Helpers_account.t option -> Tezos_base.Operation.shell_header -> Helpers_account.t option -> Tezos_base.Operation.shell_header ->
proto_operation -> MBytes.t * Signature.t option Operation.contents -> MBytes.t * Signature.t option
val main_of_proto : val main_of_proto :
Helpers_account.t -> Tezos_base.Operation.shell_header -> Helpers_account.t -> Tezos_base.Operation.shell_header ->
proto_operation -> (Main.operation * Operation_hash.t) proto_tzresult Operation.contents -> (Main.operation * Operation_hash.t) proto_tzresult
val apply_of_proto : val apply_of_proto :
Helpers_account.t option -> Tezos_base.Operation.shell_header -> Helpers_account.t option -> Tezos_base.Operation.shell_header ->
proto_operation -> operation Operation.contents -> operation

View File

@ -7,15 +7,27 @@
(* *) (* *)
(**************************************************************************) (**************************************************************************)
type operation = Operation_hash.t
type block_header_data = MBytes.t
type block_header = {
shell : Block_header.shell_header ;
protocol_data : block_header_data ;
}
let block_header_data_encoding =
Data_encoding.(obj1 (req "random_data" Variable.bytes))
type operation_data = unit
type operation = {
shell : Operation.shell_header ;
protocol_data : operation_data ;
}
let operation_data_encoding = Data_encoding.unit
let max_operation_data_length = 42 let max_operation_data_length = 42
let max_block_length = 42 let max_block_length = 42
let validation_passes = [] let validation_passes = []
let acceptable_passes _op = [] let acceptable_passes _op = []
let parse_operation h _ = Ok h
let compare_operations _ _ = 0 let compare_operations _ _ = 0
type validation_state = { type validation_state = {
@ -57,16 +69,16 @@ end
let precheck_block let precheck_block
~ancestor_context:_ ~ancestor_context:_
~ancestor_timestamp:_ ~ancestor_timestamp:_
raw_block = (raw_block: block_header) =
Fitness.to_int64 raw_block.Block_header.shell.fitness >>=? fun _ -> Fitness.to_int64 raw_block.shell.fitness >>=? fun _ ->
return () return ()
let begin_application let begin_application
~predecessor_context:context ~predecessor_context:context
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_fitness:_ ~predecessor_fitness:_
raw_block = (raw_block: block_header) =
Fitness.to_int64 raw_block.Block_header.shell.fitness >>=? fun fitness -> Fitness.to_int64 raw_block.shell.fitness >>=? fun fitness ->
return { context ; fitness } return { context ; fitness }
let begin_construction let begin_construction

View File

@ -0,0 +1,12 @@
(**************************************************************************)
(* *)
(* Copyright (c) 2014 - 2018. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
(** Tezos Protocol Implementation - Protocol Signature Instance *)
include Updater.PROTOCOL with type block_header_data = MBytes.t

View File

@ -14,13 +14,14 @@ 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 = Data_encoding.Binary.to_bytes_exn Data.Command.encoding command in let protocol_data =
Data_encoding.Binary.to_bytes_exn
Proto_genesis.block_header_data_encoding
{ command ; signature = Signature.zero } in
Block_services.preapply Block_services.preapply
cctxt block ~timestamp ~protocol_data cctxt block ~timestamp ~protocol_data
[] >>=? fun { shell_header } -> [] >>=? fun { shell_header } ->
let blk = let blk = Data.Command.forge shell_header command in
Data_encoding.Binary.to_bytes_exn Block_header.encoding
{ shell = shell_header ; protocol_data } 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 []

View File

@ -32,17 +32,31 @@ let () =
(function Invalid_signature -> Some () | _ -> None) (function Invalid_signature -> Some () | _ -> None)
(fun () -> Invalid_signature) (fun () -> Invalid_signature)
type operation = unit type operation_data = unit
let parse_operation _h _op = Error [] type operation = {
shell: Operation.shell_header ;
protocol_data: operation_data ;
}
let operation_data_encoding = Data_encoding.unit
let acceptable_passes _op = [] let acceptable_passes _op = []
let compare_operations _ _ = 0 let compare_operations _ _ = 0
let validation_passes = [] let validation_passes = []
type block = { type block_header_data = {
shell: Block_header.shell_header ;
command: Data.Command.t ; command: Data.Command.t ;
signature: Signature.t ; signature: Signature.t ;
} }
type block_header = {
shell: Block_header.shell_header ;
protocol_data: block_header_data ;
}
let block_header_data_encoding =
Data_encoding.conv
(fun { command ; signature } -> (command, signature))
(fun (command, signature) -> { command ; signature })
Data.Command.signed_encoding
let max_block_length = let max_block_length =
Data_encoding.Binary.length Data_encoding.Binary.length
@ -51,14 +65,7 @@ let max_block_length =
delay = 0L }) delay = 0L })
+ Signature.size + Signature.size
let parse_block { Block_header.shell ; protocol_data } : block tzresult = let check_signature ctxt { shell ; protocol_data = { command ; signature } } =
match
Data_encoding.Binary.of_bytes Data.Command.signed_encoding protocol_data
with
| None -> Error [Parsing_error]
| Some (command, signature) -> Ok { shell ; command ; signature }
let check_signature ctxt { shell ; command ; signature } =
let bytes = Data.Command.forge shell command in let bytes = Data.Command.forge shell command in
Data.Pubkey.get_pubkey ctxt >>= fun public_key -> Data.Pubkey.get_pubkey ctxt >>= fun public_key ->
fail_unless fail_unless
@ -73,8 +80,7 @@ let current_context ({ context ; _ } : validation_state) =
let precheck_block let precheck_block
~ancestor_context:_ ~ancestor_context:_
~ancestor_timestamp:_ ~ancestor_timestamp:_
raw_block = _block_header =
Lwt.return (parse_block raw_block) >>=? fun _ ->
return () return ()
(* temporary hardcoded key to be removed... *) (* temporary hardcoded key to be removed... *)
@ -106,12 +112,11 @@ let begin_application
~predecessor_context:ctxt ~predecessor_context:ctxt
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_fitness:_ ~predecessor_fitness:_
raw_block = block_header =
Data.Init.check_inited ctxt >>=? fun () -> Data.Init.check_inited ctxt >>=? fun () ->
Lwt.return (parse_block raw_block) >>=? fun block -> check_signature ctxt block_header >>=? fun () ->
check_signature ctxt block >>=? fun () -> prepare_application ctxt block_header.protocol_data.command
prepare_application ctxt block.command block_header.shell.level block_header.shell.timestamp block_header.shell.fitness
block.shell.level block.shell.timestamp block.shell.fitness
let begin_construction let begin_construction
~predecessor_context:ctxt ~predecessor_context:ctxt
@ -130,12 +135,9 @@ let begin_construction
max_operation_data_length = 0 ; max_operation_data_length = 0 ;
last_allowed_fork_level = 0l ; last_allowed_fork_level = 0l ;
} }
| Some command -> | Some { command ; _ }->
match Data_encoding.Binary.of_bytes Data.Command.encoding command with Data.Init.check_inited ctxt >>=? fun () ->
| None -> failwith "Failed to parse proto header" prepare_application ctxt command level timestamp fitness
| Some command ->
Data.Init.check_inited ctxt >>=? fun () ->
prepare_application ctxt command level timestamp fitness
let apply_operation _vctxt _ = let apply_operation _vctxt _ =
Lwt.return (Error []) (* absurd *) Lwt.return (Error []) (* absurd *)

View File

@ -9,4 +9,9 @@
(** Tezos Protocol Implementation - Protocol Signature Instance *) (** Tezos Protocol Implementation - Protocol Signature Instance *)
include Updater.PROTOCOL type block_header_data = {
command: Data.Command.t ;
signature: Signature.t ;
}
include Updater.PROTOCOL with type block_header_data := block_header_data