Genesis/Alpha: include chain id in signature for blocks and endorsements

This commit is contained in:
Benjamin Canou 2018-06-27 17:00:24 +02:00
parent 5575b8b8f2
commit 44ca820944
34 changed files with 135 additions and 81 deletions

View File

@ -79,6 +79,7 @@ module Fitness = struct
end end
let begin_application let begin_application
~chain_id:_
~predecessor_context:context ~predecessor_context:context
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_fitness:_ ~predecessor_fitness:_
@ -87,17 +88,20 @@ let begin_application
return { context ; fitness } return { context ; fitness }
let begin_partial_application let begin_partial_application
~chain_id
~ancestor_context ~ancestor_context
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
raw_block = raw_block =
begin_application begin_application
~chain_id
~predecessor_context:ancestor_context ~predecessor_context:ancestor_context
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
raw_block raw_block
let begin_construction let begin_construction
~chain_id:_
~predecessor_context:context ~predecessor_context:context
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_level:_ ~predecessor_level:_

View File

@ -31,7 +31,7 @@ done
sleep 2 sleep 2
# autogenerated from the demo source # autogenerated from the demo source
protocol_version="PsVi9P3i73N4zstqkty4EiL76cofTFkthzSQPfLmChCvF7JopPh" protocol_version="PsoXmK2EEBAsbFy7XHr8xB34jmArfrJQMRniTVdUsrSVu2VtRsr"
$admin_client inject protocol "$test_dir/demo" $admin_client inject protocol "$test_dir/demo"
$admin_client list protocols $admin_client list protocols

View File

@ -25,8 +25,8 @@ type secret_key =
| P256 of P256.Secret_key.t | P256 of P256.Secret_key.t
type watermark = type watermark =
| Block_header | Block_header of Chain_id.t
| Endorsement | Endorsement of Chain_id.t
| Generic_operation | Generic_operation
| Custom of MBytes.t | Custom of MBytes.t
@ -502,8 +502,8 @@ let of_p256 s = P256 s
let zero = of_ed25519 Ed25519.zero let zero = of_ed25519 Ed25519.zero
let bytes_of_watermark = function let bytes_of_watermark = function
| Block_header -> MBytes.of_string "\x01" | Block_header chain_id -> MBytes.concat "" [ MBytes.of_string "\x01" ; Chain_id.to_bytes chain_id ]
| Endorsement -> MBytes.of_string "\x02" | Endorsement chain_id -> MBytes.concat "" [ MBytes.of_string "\x02" ; Chain_id.to_bytes chain_id ]
| Generic_operation -> MBytes.of_string "\x03" | Generic_operation -> MBytes.of_string "\x03"
| Custom bytes -> bytes | Custom bytes -> bytes

View File

@ -23,8 +23,8 @@ type secret_key =
| P256 of P256.Secret_key.t | P256 of P256.Secret_key.t
type watermark = type watermark =
| Block_header | Block_header of Chain_id.t
| Endorsement | Endorsement of Chain_id.t
| Generic_operation | Generic_operation
| Custom of MBytes.t | Custom of MBytes.t

View File

@ -42,6 +42,7 @@
v1/ed25519.mli v1/ed25519.mli
v1/secp256k1.mli v1/secp256k1.mli
v1/p256.mli v1/p256.mli
v1/chain_id.mli
v1/signature.mli v1/signature.mli
v1/block_hash.mli v1/block_hash.mli
v1/operation_hash.mli v1/operation_hash.mli

View File

@ -0,0 +1,10 @@
(**************************************************************************)
(* *)
(* Copyright (c) 2014 - 2018. *)
(* Dynamic Ledger Solutions, Inc. <contact@tezos.com> *)
(* *)
(* All rights reserved. No warranty, explicit or implicit, provided. *)
(* *)
(**************************************************************************)
include S.HASH

View File

@ -18,8 +18,8 @@ type public_key =
| P256 of P256.Public_key.t | P256 of P256.Public_key.t
type watermark = type watermark =
| Block_header | Block_header of Chain_id.t
| Endorsement | Endorsement of Chain_id.t
| Generic_operation | Generic_operation
| Custom of MBytes.t | Custom of MBytes.t

View File

@ -144,6 +144,7 @@ module type PROTOCOL = sig
The resulting `validation_state` will be used for multi-pass The resulting `validation_state` will be used for multi-pass
validation. *) validation. *)
val begin_partial_application: val begin_partial_application:
chain_id: Chain_id.t ->
ancestor_context: Context.t -> ancestor_context: Context.t ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
@ -157,6 +158,7 @@ module type PROTOCOL = sig
[begin_application], so all the check performed by the former [begin_application], so all the check performed by the former
must be repeated in the latter. *) must be repeated in the latter. *)
val begin_application: val begin_application:
chain_id: Chain_id.t ->
predecessor_context: Context.t -> predecessor_context: Context.t ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
@ -173,6 +175,7 @@ module type PROTOCOL = sig
block header usually includes a signature, the header provided block header usually includes a signature, the header provided
to {!begin_construction} should includes a faked signature. *) to {!begin_construction} should includes a faked signature. *)
val begin_construction: val begin_construction:
chain_id: Chain_id.t ->
predecessor_context: Context.t -> predecessor_context: Context.t ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_level: Int32.t -> predecessor_level: Int32.t ->

View File

@ -82,18 +82,21 @@ module Make (Context : CONTEXT) = struct
type validation_state type validation_state
val current_context: validation_state -> context tzresult Lwt.t val current_context: validation_state -> context tzresult Lwt.t
val begin_partial_application: val begin_partial_application:
chain_id: Chain_id.t ->
ancestor_context: context -> ancestor_context: context ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
block_header -> block_header ->
validation_state tzresult Lwt.t validation_state tzresult Lwt.t
val begin_application: val begin_application:
chain_id: Chain_id.t ->
predecessor_context: context -> predecessor_context: context ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
block_header -> block_header ->
validation_state tzresult Lwt.t validation_state tzresult Lwt.t
val begin_construction: val begin_construction:
chain_id: Chain_id.t ->
predecessor_context: context -> predecessor_context: context ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_level: Int32.t -> predecessor_level: Int32.t ->
@ -128,6 +131,7 @@ module Make (Context : CONTEXT) = struct
and type 'a Data_encoding.lazy_t = 'a Data_encoding.lazy_t and type 'a Data_encoding.lazy_t = 'a Data_encoding.lazy_t
and type 'a Lwt.t = 'a Lwt.t and type 'a Lwt.t = 'a Lwt.t
and type ('a, 'b) Pervasives.result = ('a, 'b) result and type ('a, 'b) Pervasives.result = ('a, 'b) result
and type Chain_id.t = Chain_id.t
and type Block_hash.t = Block_hash.t and type Block_hash.t = Block_hash.t
and type Operation_hash.t = Operation_hash.t and type Operation_hash.t = Operation_hash.t
and type Operation_list_hash.t = Operation_list_hash.t and type Operation_list_hash.t = Operation_list_hash.t
@ -397,6 +401,7 @@ module Make (Context : CONTEXT) = struct
| Ok _ as ok -> ok | Ok _ as ok -> ok
| Error errors -> Error (List.map (fun error -> Ecoproto_error error) errors) | Error errors -> Error (List.map (fun error -> Ecoproto_error error) errors)
module Chain_id = Chain_id
module Block_hash = Block_hash module Block_hash = Block_hash
module Operation_hash = Operation_hash module Operation_hash = Operation_hash
module Operation_list_hash = Operation_list_hash module Operation_list_hash = Operation_list_hash
@ -642,25 +647,25 @@ module Make (Context : CONTEXT) = struct
module Lift(P : Updater.PROTOCOL) = struct module Lift(P : Updater.PROTOCOL) = struct
include P include P
let begin_partial_application let begin_partial_application
~ancestor_context ~predecessor_timestamp ~predecessor_fitness ~chain_id ~ancestor_context ~predecessor_timestamp ~predecessor_fitness
raw_block = raw_block =
begin_partial_application begin_partial_application
~ancestor_context ~predecessor_timestamp ~predecessor_fitness ~chain_id ~ancestor_context ~predecessor_timestamp ~predecessor_fitness
raw_block >|= wrap_error raw_block >|= wrap_error
let begin_application let begin_application
~predecessor_context ~predecessor_timestamp ~chain_id ~predecessor_context ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
raw_block = raw_block =
begin_application begin_application
~predecessor_context ~predecessor_timestamp ~chain_id ~predecessor_context ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
raw_block >|= wrap_error raw_block >|= wrap_error
let begin_construction let begin_construction
~predecessor_context ~predecessor_timestamp ~chain_id ~predecessor_context ~predecessor_timestamp
~predecessor_level ~predecessor_fitness ~predecessor_level ~predecessor_fitness
~predecessor ~timestamp ?protocol_data () = ~predecessor ~timestamp ?protocol_data () =
begin_construction begin_construction
~predecessor_context ~predecessor_timestamp ~chain_id ~predecessor_context ~predecessor_timestamp
~predecessor_level ~predecessor_fitness ~predecessor_level ~predecessor_fitness
~predecessor ~timestamp ?protocol_data () >|= wrap_error ~predecessor ~timestamp ?protocol_data () >|= wrap_error
let current_context c = let current_context c =

View File

@ -75,18 +75,21 @@ module Make (Context : CONTEXT) : sig
type validation_state type validation_state
val current_context: validation_state -> context tzresult Lwt.t val current_context: validation_state -> context tzresult Lwt.t
val begin_partial_application: val begin_partial_application:
chain_id: Chain_id.t ->
ancestor_context: context -> ancestor_context: context ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
block_header -> block_header ->
validation_state tzresult Lwt.t validation_state tzresult Lwt.t
val begin_application: val begin_application:
chain_id: Chain_id.t ->
predecessor_context: context -> predecessor_context: context ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_fitness: Fitness.t -> predecessor_fitness: Fitness.t ->
block_header -> block_header ->
validation_state tzresult Lwt.t validation_state tzresult Lwt.t
val begin_construction: val begin_construction:
chain_id: Chain_id.t ->
predecessor_context: context -> predecessor_context: context ->
predecessor_timestamp: Time.t -> predecessor_timestamp: Time.t ->
predecessor_level: Int32.t -> predecessor_level: Int32.t ->
@ -121,6 +124,7 @@ module Make (Context : CONTEXT) : sig
and type 'a Data_encoding.lazy_t = 'a Data_encoding.lazy_t and type 'a Data_encoding.lazy_t = 'a Data_encoding.lazy_t
and type 'a Lwt.t = 'a Lwt.t and type 'a Lwt.t = 'a Lwt.t
and type ('a, 'b) Pervasives.result = ('a, 'b) result and type ('a, 'b) Pervasives.result = ('a, 'b) result
and type Chain_id.t = Chain_id.t
and type Block_hash.t = Block_hash.t and type Block_hash.t = Block_hash.t
and type Operation_hash.t = Operation_hash.t and type Operation_hash.t = Operation_hash.t
and type Operation_list_hash.t = Operation_list_hash.t and type Operation_list_hash.t = Operation_list_hash.t

View File

@ -241,6 +241,7 @@ let build_raw_rpc_directory
let predecessor = State.Block.hash block in let predecessor = State.Block.hash block in
let header = State.Block.shell_header block in let header = State.Block.shell_header block in
Next_proto.begin_construction Next_proto.begin_construction
~chain_id: (State.Block.chain_id block)
~predecessor_context:ctxt ~predecessor_context:ctxt
~predecessor_timestamp:header.timestamp ~predecessor_timestamp:header.timestamp
~predecessor_level:header.level ~predecessor_level:header.level

View File

@ -184,6 +184,7 @@ let apply_block
pred_context pred_hash header.shell.timestamp >>= fun context -> pred_context pred_hash header.shell.timestamp >>= fun context ->
(* TODO wrap 'proto_error' into 'block_error' *) (* TODO wrap 'proto_error' into 'block_error' *)
Proto.begin_application Proto.begin_application
~chain_id: (State.Chain.id chain_state)
~predecessor_context:context ~predecessor_context: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

View File

@ -65,7 +65,7 @@ let start_prevalidation
State.Block.header predecessor in State.Block.header predecessor in
State.Block.context predecessor >>= fun predecessor_context -> State.Block.context predecessor >>= fun predecessor_context ->
Context.get_protocol predecessor_context >>= fun protocol -> Context.get_protocol predecessor_context >>= fun protocol ->
let predecessor = State.Block.hash predecessor in let predecessor_hash = State.Block.hash predecessor in
begin begin
match Registered_protocol.get protocol with match Registered_protocol.get protocol with
| None -> | None ->
@ -77,7 +77,7 @@ let start_prevalidation
return protocol return protocol
end >>=? fun (module Proto) -> end >>=? fun (module Proto) ->
Context.reset_test_chain Context.reset_test_chain
predecessor_context predecessor predecessor_context predecessor_hash
timestamp >>= fun predecessor_context -> timestamp >>= fun predecessor_context ->
begin begin
match protocol_data with match protocol_data with
@ -92,11 +92,12 @@ let start_prevalidation
| Some protocol_data -> return_some protocol_data | Some protocol_data -> return_some protocol_data
end >>=? fun protocol_data -> end >>=? fun protocol_data ->
Proto.begin_construction Proto.begin_construction
~chain_id: (State.Block.chain_id predecessor)
~predecessor_context ~predecessor_context
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
~predecessor_level ~predecessor_level
~predecessor ~predecessor: predecessor_hash
~timestamp ~timestamp
?protocol_data ?protocol_data
() ()

View File

@ -97,6 +97,7 @@ let build_valid_chain state vtbl pred names =
let pred_header = State.Block.header pred in let pred_header = State.Block.header pred in
begin begin
Proto.begin_application Proto.begin_application
~chain_id: Chain_id.zero
~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

View File

@ -21,7 +21,8 @@ let get_branch (rpc_config: #Proto_alpha.full)
| `Genesis -> return `Genesis | `Genesis -> return `Genesis
end >>=? fun block -> end >>=? fun block ->
Shell_services.Blocks.hash rpc_config ~chain ~block () >>=? fun hash -> Shell_services.Blocks.hash rpc_config ~chain ~block () >>=? fun hash ->
return hash Shell_services.Chain.chain_id rpc_config ~chain () >>=? fun chain_id ->
return (chain_id, hash)
type 'kind preapply_result = type 'kind preapply_result =
Operation_hash.t * 'kind operation * 'kind operation_metadata Operation_hash.t * 'kind operation * 'kind operation_metadata
@ -35,21 +36,23 @@ type 'kind result =
let preapply (type t) let preapply (type t)
(cctxt: #Proto_alpha.full) ~chain ~block (cctxt: #Proto_alpha.full) ~chain ~block
?branch ?src_sk (contents : t contents_list) = ?branch ?src_sk (contents : t contents_list) =
get_branch cctxt ~chain ~block branch >>=? fun branch -> get_branch cctxt ~chain ~block branch >>=? fun (chain_id, branch) ->
let bytes = let bytes =
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
Operation.unsigned_encoding Operation.unsigned_encoding
({ branch }, Contents_list contents) in ({ branch }, Contents_list contents) in
let watermark =
match contents with
| Single (Endorsement _) -> Signature.Endorsement
| _ -> Signature.Generic_operation in
begin begin
match src_sk with match src_sk with
| None -> return_none | None -> return_none
| Some src_sk -> | Some src_sk ->
Client_keys.sign cctxt begin match contents with
~watermark src_sk bytes >>=? fun signature -> | Single (Endorsement _) ->
Client_keys.sign cctxt
~watermark:Signature.(Endorsement chain_id) src_sk bytes
| _ ->
Client_keys.sign cctxt
~watermark:Signature.Generic_operation src_sk bytes
end >>=? fun signature ->
return_some signature return_some signature
end >>=? fun signature -> end >>=? fun signature ->
let op : _ Operation.t = let op : _ Operation.t =
@ -71,7 +74,7 @@ let preapply (type t)
let simulate (type t) let simulate (type t)
(cctxt: #Proto_alpha.full) ~chain ~block (cctxt: #Proto_alpha.full) ~chain ~block
?branch (contents : t contents_list) = ?branch (contents : t contents_list) =
get_branch cctxt ~chain ~block branch >>=? fun branch -> get_branch cctxt ~chain ~block branch >>=? fun (_chain_id, branch) ->
let op : _ Operation.t = let op : _ Operation.t =
{ shell = { branch } ; { shell = { branch } ;
protocol_data = { contents ; signature = None } } in protocol_data = { contents ; signature = None } } in

View File

@ -31,8 +31,9 @@ let inject_endorsement
~branch:hash ~branch:hash
~level:level ~level:level
() >>=? fun bytes -> () >>=? fun bytes ->
Shell_services.Chain.chain_id cctxt ~chain () >>=? fun chain_id ->
Client_keys.append cctxt Client_keys.append cctxt
src_sk ~watermark:Endorsement bytes >>=? fun signed_bytes -> src_sk ~watermark:(Endorsement chain_id) bytes >>=? fun signed_bytes ->
Shell_services.Injection.operation cctxt ?async ~chain signed_bytes >>=? fun oph -> Shell_services.Injection.operation cctxt ?async ~chain signed_bytes >>=? fun oph ->
State.record cctxt pkh level >>=? fun () -> State.record cctxt pkh level >>=? fun () ->
return oph return oph

View File

@ -75,7 +75,8 @@ let forge_block_header
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
Alpha_context.Block_header.unsigned_encoding Alpha_context.Block_header.unsigned_encoding
(shell, contents) in (shell, contents) in
Client_keys.append cctxt delegate_sk ~watermark:Block_header unsigned_header Shell_services.Chain.chain_id cctxt ~chain () >>=? fun chain_id ->
Client_keys.append cctxt delegate_sk ~watermark:(Block_header chain_id) unsigned_header
let forge_faked_protocol_data ~priority ~seed_nonce_hash = let forge_faked_protocol_data ~priority ~seed_nonce_hash =
Alpha_context.Block_header.{ Alpha_context.Block_header.{

View File

@ -57,6 +57,7 @@ let begin_construction (_cctxt : #Proto_alpha.full) index predecessor =
operations_hash = Operation_list_list_hash.zero ; operations_hash = Operation_list_list_hash.zero ;
} in } in
Main.begin_construction Main.begin_construction
~chain_id: predecessor.chain_id
~predecessor_context: context ~predecessor_context: context
~predecessor_timestamp: header.timestamp ~predecessor_timestamp: header.timestamp
~predecessor_fitness: header.fitness ~predecessor_fitness: header.fitness

View File

@ -555,7 +555,7 @@ module Endorse = struct
let shell = { Tezos_base.Operation.branch = hash } in let shell = { Tezos_base.Operation.branch = hash } in
let contents = let contents =
Single (Endorsement { level }) in Single (Endorsement { level }) in
sign ~watermark:Endorsement src_sk shell (Contents_list contents) sign ~watermark:(Endorsement Chain_id.zero) src_sk shell (Contents_list contents)
let signing_slots let signing_slots
block block

View File

@ -943,8 +943,8 @@ module Operation : sig
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 -> Chain_id.t -> _ operation -> unit tzresult Lwt.t
val check_signature_sync: public_key -> _ operation -> unit tzresult val check_signature_sync: public_key -> Chain_id.t -> _ operation -> unit tzresult
val internal_operation_encoding: packed_internal_operation Data_encoding.t val internal_operation_encoding: packed_internal_operation Data_encoding.t

View File

@ -480,7 +480,7 @@ let apply_internal_manager_operations ctxt mode ~payer ops =
apply ctxt [] ops apply ctxt [] ops
let precheck_manager_contents let precheck_manager_contents
(type kind) ctxt raw_operation (op : kind Kind.manager contents) (type kind) ctxt chain_id raw_operation (op : kind Kind.manager contents)
: context tzresult Lwt.t = : context tzresult Lwt.t =
let Manager_operation { source ; fee ; counter ; operation ; gas_limit ; storage_limit } = op in let Manager_operation { source ; fee ; counter ; operation ; gas_limit ; storage_limit } = op in
Lwt.return (Gas.check_limit ctxt gas_limit) >>=? fun () -> Lwt.return (Gas.check_limit ctxt gas_limit) >>=? fun () ->
@ -498,7 +498,7 @@ let precheck_manager_contents
all operations are required to be from the same manager. This may all operations are required to be from the same manager. This may
change in the future, allowing several managers to group-sign a change in the future, allowing several managers to group-sign a
sequence of transactions. *) sequence of transactions. *)
Operation.check_signature public_key raw_operation >>=? fun () -> Operation.check_signature public_key chain_id raw_operation >>=? fun () ->
Contract.increment_counter ctxt source >>=? fun ctxt -> Contract.increment_counter ctxt source >>=? fun ctxt ->
Contract.spend ctxt source fee >>=? fun ctxt -> Contract.spend ctxt source fee >>=? fun ctxt ->
add_fees ctxt fee >>=? fun ctxt -> add_fees ctxt fee >>=? fun ctxt ->
@ -561,15 +561,15 @@ let rec mark_skipped
let rec precheck_manager_contents_list let rec precheck_manager_contents_list
: type kind. : type kind.
Alpha_context.t -> _ Operation.t -> kind Kind.manager contents_list -> Alpha_context.t -> Chain_id.t -> _ Operation.t -> kind Kind.manager contents_list ->
context tzresult Lwt.t = context tzresult Lwt.t =
fun ctxt raw_operation contents_list -> fun ctxt chain_id raw_operation contents_list ->
match contents_list with match contents_list with
| Single (Manager_operation _ as op) -> | Single (Manager_operation _ as op) ->
precheck_manager_contents ctxt raw_operation op precheck_manager_contents ctxt chain_id raw_operation op
| Cons (Manager_operation _ as op, rest) -> | Cons (Manager_operation _ as op, rest) ->
precheck_manager_contents ctxt raw_operation op >>=? fun ctxt -> precheck_manager_contents ctxt chain_id raw_operation op >>=? fun ctxt ->
precheck_manager_contents_list ctxt raw_operation rest precheck_manager_contents_list ctxt chain_id raw_operation rest
let rec apply_manager_contents_list_rec let rec apply_manager_contents_list_rec
: type kind. : type kind.
@ -656,7 +656,7 @@ let apply_manager_contents_list ctxt mode baker contents_list =
| `Success ctxt -> Lwt.return (ctxt, results) | `Success ctxt -> Lwt.return (ctxt, results)
let apply_contents_list let apply_contents_list
(type kind) ctxt mode pred_block baker (type kind) ctxt chain_id mode pred_block baker
(operation : kind operation) (operation : kind operation)
(contents_list : kind contents_list) (contents_list : kind contents_list)
: (context * kind contents_result_list) tzresult Lwt.t = : (context * kind contents_result_list) tzresult Lwt.t =
@ -670,7 +670,7 @@ let apply_contents_list
fail_unless fail_unless
Raw_level.(succ level = current_level) Raw_level.(succ level = current_level)
Invalid_endorsement_level >>=? fun () -> Invalid_endorsement_level >>=? fun () ->
Baking.check_endorsement_rights ctxt operation >>=? fun (delegate, slots, used) -> Baking.check_endorsement_rights ctxt chain_id operation >>=? fun (delegate, slots, used) ->
if used then fail (Duplicate_endorsement delegate) if used then fail (Duplicate_endorsement delegate)
else else
let ctxt = record_endorsement ctxt delegate in let ctxt = record_endorsement ctxt delegate in
@ -716,8 +716,8 @@ let apply_contents_list
(Outdated_double_endorsement_evidence (Outdated_double_endorsement_evidence
{ level = level.level ; { level = level.level ;
last = oldest_level }) >>=? fun () -> last = oldest_level }) >>=? fun () ->
Baking.check_endorsement_rights ctxt op1 >>=? fun (delegate1, _, _) -> Baking.check_endorsement_rights ctxt chain_id op1 >>=? fun (delegate1, _, _) ->
Baking.check_endorsement_rights ctxt op2 >>=? fun (delegate2, _, _) -> Baking.check_endorsement_rights ctxt chain_id op2 >>=? fun (delegate2, _, _) ->
fail_unless fail_unless
(Signature.Public_key_hash.equal delegate1 delegate2) (Signature.Public_key_hash.equal delegate1 delegate2)
(Inconsistent_double_endorsement_evidence (Inconsistent_double_endorsement_evidence
@ -765,10 +765,10 @@ let apply_contents_list
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.contents.priority >>=? fun delegate1 -> ctxt level ~priority:bh1.protocol_data.contents.priority >>=? fun delegate1 ->
Baking.check_signature bh1 delegate1 >>=? fun () -> Baking.check_signature bh1 chain_id delegate1 >>=? fun () ->
Roll.baking_rights_owner Roll.baking_rights_owner
ctxt level ~priority:bh2.protocol_data.contents.priority >>=? fun delegate2 -> ctxt level ~priority:bh2.protocol_data.contents.priority >>=? fun delegate2 ->
Baking.check_signature bh2 delegate2 >>=? fun () -> Baking.check_signature bh2 chain_id delegate2 >>=? fun () ->
fail_unless fail_unless
(Signature.Public_key.equal delegate1 delegate2) (Signature.Public_key.equal delegate1 delegate2)
(Inconsistent_double_baking_evidence (Inconsistent_double_baking_evidence
@ -805,7 +805,7 @@ let apply_contents_list
end end
| Single (Proposals { source ; period ; proposals }) -> | Single (Proposals { source ; period ; proposals }) ->
Roll.delegate_pubkey ctxt source >>=? fun delegate -> Roll.delegate_pubkey ctxt source >>=? fun delegate ->
Operation.check_signature delegate operation >>=? fun () -> Operation.check_signature delegate chain_id operation >>=? fun () ->
let level = Level.current ctxt in let level = Level.current ctxt in
fail_unless Voting_period.(level.voting_period = period) fail_unless Voting_period.(level.voting_period = period)
(Wrong_voting_period (level.voting_period, period)) >>=? fun () -> (Wrong_voting_period (level.voting_period, period)) >>=? fun () ->
@ -813,25 +813,25 @@ let apply_contents_list
return (ctxt, Single_result Proposals_result) return (ctxt, Single_result Proposals_result)
| Single (Ballot { source ; period ; proposal ; ballot }) -> | Single (Ballot { source ; period ; proposal ; ballot }) ->
Roll.delegate_pubkey ctxt source >>=? fun delegate -> Roll.delegate_pubkey ctxt source >>=? fun delegate ->
Operation.check_signature delegate operation >>=? fun () -> Operation.check_signature delegate chain_id operation >>=? fun () ->
let level = Level.current ctxt in let level = Level.current ctxt in
fail_unless Voting_period.(level.voting_period = period) fail_unless Voting_period.(level.voting_period = period)
(Wrong_voting_period (level.voting_period, period)) >>=? fun () -> (Wrong_voting_period (level.voting_period, period)) >>=? fun () ->
Amendment.record_ballot ctxt source proposal ballot >>=? fun ctxt -> Amendment.record_ballot ctxt source proposal ballot >>=? fun ctxt ->
return (ctxt, Single_result Ballot_result) return (ctxt, Single_result Ballot_result)
| Single (Manager_operation _) as op -> | Single (Manager_operation _) as op ->
precheck_manager_contents_list ctxt operation op >>=? fun ctxt -> precheck_manager_contents_list ctxt chain_id operation op >>=? fun ctxt ->
apply_manager_contents_list ctxt mode baker op >>= fun (ctxt, result) -> apply_manager_contents_list ctxt mode baker op >>= fun (ctxt, result) ->
return (ctxt, result) return (ctxt, result)
| Cons (Manager_operation _, _) as op -> | Cons (Manager_operation _, _) as op ->
precheck_manager_contents_list ctxt operation op >>=? fun ctxt -> precheck_manager_contents_list ctxt chain_id operation op >>=? fun ctxt ->
apply_manager_contents_list ctxt mode baker op >>= fun (ctxt, result) -> apply_manager_contents_list ctxt mode baker op >>= fun (ctxt, result) ->
return (ctxt, result) return (ctxt, result)
let apply_operation ctxt mode pred_block baker hash operation = let apply_operation ctxt chain_id mode pred_block baker hash operation =
let ctxt = Contract.init_origination_nonce ctxt hash in let ctxt = Contract.init_origination_nonce ctxt hash in
apply_contents_list apply_contents_list
ctxt mode pred_block baker operation ctxt chain_id mode pred_block baker operation
operation.protocol_data.contents >>=? fun (ctxt, result) -> operation.protocol_data.contents >>=? fun (ctxt, result) ->
let ctxt = Gas.set_unlimited ctxt in let ctxt = Gas.set_unlimited ctxt in
let ctxt = Contract.unset_origination_nonce ctxt in let ctxt = Contract.unset_origination_nonce ctxt in
@ -879,13 +879,13 @@ let begin_partial_construction ctxt =
let ctxt = init_endorsements ctxt rights in let ctxt = init_endorsements ctxt rights in
return ctxt return ctxt
let begin_application ctxt block_header pred_timestamp = let begin_application ctxt chain_id block_header pred_timestamp =
let current_level = Alpha_context.Level.current ctxt in let current_level = Alpha_context.Level.current ctxt in
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.contents 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 chain_id delegate_pk >>=? fun () ->
let has_commitment = let has_commitment =
match block_header.protocol_data.contents.seed_nonce_hash with match block_header.protocol_data.contents.seed_nonce_hash with
| None -> false | None -> false

View File

@ -178,7 +178,7 @@ let endorsement_rights c level =
Signature.Public_key_hash.Map.empty Signature.Public_key_hash.Map.empty
(0 --> (Constants.endorsers_per_block c - 1)) (0 --> (Constants.endorsers_per_block c - 1))
let check_endorsement_rights ctxt (op : Kind.endorsement Operation.t) = let check_endorsement_rights ctxt chain_id (op : Kind.endorsement Operation.t) =
let current_level = Level.current ctxt in let current_level = Level.current ctxt in
let Single (Endorsement { level ; _ }) = op.protocol_data.contents in let Single (Endorsement { level ; _ }) = op.protocol_data.contents in
begin begin
@ -190,7 +190,7 @@ let check_endorsement_rights ctxt (op : Kind.endorsement Operation.t) =
match match
Signature.Public_key_hash.Map.fold (* no find_first *) Signature.Public_key_hash.Map.fold (* no find_first *)
(fun pkh (pk, slots, used) acc -> (fun pkh (pk, slots, used) acc ->
match Operation.check_signature_sync pk op with match Operation.check_signature_sync pk chain_id op with
| Error _ -> acc | Error _ -> acc
| Ok () -> Some (pkh, slots, used)) | Ok () -> Some (pkh, slots, used))
endorsements None endorsements None
@ -241,14 +241,14 @@ let check_proof_of_work_stamp ctxt block =
else else
fail Invalid_stamp fail Invalid_stamp
let check_signature block key = let check_signature block chain_id key =
let check_signature key let check_signature key
{ Block_header.shell ; protocol_data = { contents ; signature } } = { Block_header.shell ; protocol_data = { contents ; signature } } =
let unsigned_header = let unsigned_header =
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
Block_header.unsigned_encoding Block_header.unsigned_encoding
(shell, contents) in (shell, contents) in
Signature.check ~watermark:Block_header key signature unsigned_header in Signature.check ~watermark:(Block_header chain_id) key signature unsigned_header in
if check_signature key block then if check_signature key block then
return_unit return_unit
else else

View File

@ -44,7 +44,7 @@ val endorsement_rights:
(** Check that the operation was signed by a delegate allowed (** Check that the operation was signed by a delegate allowed
to endorse at the level specified by the endorsement. *) to endorse at the level specified by the endorsement. *)
val check_endorsement_rights: val check_endorsement_rights:
context -> Kind.endorsement Operation.t -> context -> Chain_id.t -> Kind.endorsement Operation.t ->
(public_key_hash * int list * bool) tzresult Lwt.t (public_key_hash * int list * bool) tzresult Lwt.t
(** Returns the endorsement reward calculated w.r.t a given priority. *) (** Returns the endorsement reward calculated w.r.t a given priority. *)
@ -67,9 +67,9 @@ val first_baking_priorities:
Level.t -> Level.t ->
int list tzresult Lwt.t int list tzresult Lwt.t
(** [check_signature ctxt block id] check if the block is signed with (** [check_signature ctxt chain_id block id] check if the block is
the given key *) signed with the given key, and belongs to the given [chain_id] *)
val check_signature: Block_header.t -> public_key -> unit tzresult Lwt.t val check_signature: Block_header.t -> Chain_id.t -> public_key -> unit tzresult Lwt.t
(** Checks if the header that would be built from the given components (** Checks if the header that would be built from the given components
is valid for the given diffculty. The signature is not passed as it is valid for the given diffculty. The signature is not passed as it

View File

@ -254,7 +254,7 @@ module Scripts = struct
return result return result
| _ -> | _ ->
Apply.apply_contents_list Apply.apply_contents_list
ctxt Optimized shell.branch baker operation ctxt Chain_id.zero Optimized shell.branch baker operation
operation.protocol_data.contents >>=? fun (_ctxt, result) -> operation.protocol_data.contents >>=? fun (_ctxt, result) ->
return result return result

View File

@ -78,6 +78,7 @@ type validation_mode =
type validation_state = type validation_state =
{ mode : validation_mode ; { mode : validation_mode ;
chain_id : Chain_id.t ;
ctxt : Alpha_context.t ; ctxt : Alpha_context.t ;
op_count : int ; op_count : int ;
} }
@ -86,6 +87,7 @@ let current_context { ctxt ; _ } =
return (Alpha_context.finalize ctxt).context return (Alpha_context.finalize ctxt).context
let begin_partial_application let begin_partial_application
~chain_id
~ancestor_context:ctxt ~ancestor_context:ctxt
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
@ -95,13 +97,14 @@ let begin_partial_application
let timestamp = block_header.shell.timestamp in let timestamp = block_header.shell.timestamp in
Alpha_context.prepare ~level ~timestamp ~fitness ctxt >>=? fun ctxt -> Alpha_context.prepare ~level ~timestamp ~fitness ctxt >>=? fun ctxt ->
Apply.begin_application Apply.begin_application
ctxt block_header predecessor_timestamp >>=? fun (ctxt, baker) -> ctxt chain_id block_header predecessor_timestamp >>=? fun (ctxt, baker) ->
let mode = let mode =
Partial_application Partial_application
{ block_header ; baker = Signature.Public_key.hash baker } in { block_header ; baker = Signature.Public_key.hash baker } in
return { mode ; ctxt ; op_count = 0 } return { mode ; chain_id ; ctxt ; op_count = 0 }
let begin_application let begin_application
~chain_id
~predecessor_context:ctxt ~predecessor_context:ctxt
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
@ -111,11 +114,12 @@ let begin_application
let timestamp = block_header.shell.timestamp in let timestamp = block_header.shell.timestamp in
Alpha_context.prepare ~level ~timestamp ~fitness ctxt >>=? fun ctxt -> Alpha_context.prepare ~level ~timestamp ~fitness ctxt >>=? fun ctxt ->
Apply.begin_application Apply.begin_application
ctxt block_header predecessor_timestamp >>=? fun (ctxt, baker) -> ctxt chain_id block_header predecessor_timestamp >>=? fun (ctxt, baker) ->
let mode = Application { block_header ; baker = Signature.Public_key.hash baker } in let mode = Application { block_header ; baker = Signature.Public_key.hash baker } in
return { mode ; ctxt ; op_count = 0 } return { mode ; chain_id ; ctxt ; op_count = 0 }
let begin_construction let begin_construction
~chain_id
~predecessor_context:ctxt ~predecessor_context:ctxt
~predecessor_timestamp:pred_timestamp ~predecessor_timestamp:pred_timestamp
~predecessor_level:pred_level ~predecessor_level:pred_level
@ -142,10 +146,10 @@ let begin_construction
Full_construction { predecessor ; baker ; protocol_data } in Full_construction { predecessor ; baker ; protocol_data } in
return (mode, ctxt) return (mode, ctxt)
end >>=? fun (mode, ctxt) -> end >>=? fun (mode, ctxt) ->
return { mode ; ctxt ; op_count = 0 } return { mode ; chain_id ; ctxt ; op_count = 0 }
let apply_operation let apply_operation
({ mode ; ctxt ; op_count ; _ } as data) ({ mode ; chain_id ; ctxt ; op_count ; _ } as data)
(operation : Alpha_context.packed_operation) = (operation : Alpha_context.packed_operation) =
match mode with match mode with
| Partial_application _ when | Partial_application _ when
@ -169,7 +173,7 @@ let apply_operation
| Partial_construction { predecessor } | Partial_construction { predecessor }
-> predecessor, Signature.Public_key_hash.zero -> predecessor, Signature.Public_key_hash.zero
in in
Apply.apply_operation ctxt Optimized predecessor baker Apply.apply_operation ctxt chain_id Optimized predecessor baker
(Alpha_context.Operation.hash operation) (Alpha_context.Operation.hash operation)
operation >>=? fun (ctxt, result) -> operation >>=? fun (ctxt, result) ->
let op_count = op_count + 1 in let op_count = op_count + 1 in

View File

@ -29,6 +29,7 @@ type validation_mode =
type validation_state = type validation_state =
{ mode : validation_mode ; { mode : validation_mode ;
chain_id : Chain_id.t ;
ctxt : Alpha_context.t ; ctxt : Alpha_context.t ;
op_count : int ; op_count : int ;
} }

View File

@ -644,7 +644,7 @@ let () =
(function Missing_signature -> Some () | _ -> None) (function Missing_signature -> Some () | _ -> None)
(fun () -> Missing_signature) (fun () -> Missing_signature)
let check_signature_sync (type kind) key ({ shell ; protocol_data } : kind operation) = let check_signature_sync (type kind) key chain_id ({ shell ; protocol_data } : kind operation) =
let check ~watermark contents signature = let check ~watermark contents signature =
let unsigned_operation = let unsigned_operation =
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
@ -659,14 +659,14 @@ let check_signature_sync (type kind) key ({ shell ; protocol_data } : kind opera
| Cons _, None -> | Cons _, None ->
Error [Missing_signature] Error [Missing_signature]
| Single (Endorsement _) as contents, Some signature -> | Single (Endorsement _) as contents, Some signature ->
check ~watermark:Endorsement (Contents_list contents) signature check ~watermark:(Endorsement chain_id) (Contents_list contents) signature
| Single _ as contents, Some signature -> | Single _ as contents, Some signature ->
check ~watermark:Generic_operation (Contents_list contents) signature check ~watermark:Generic_operation (Contents_list contents) signature
| Cons _ as contents, Some signature -> | Cons _ as contents, Some signature ->
check ~watermark:Generic_operation (Contents_list contents) signature check ~watermark:Generic_operation (Contents_list contents) signature
let check_signature pk op = let check_signature pk chain_id op =
Lwt.return (check_signature_sync pk op) Lwt.return (check_signature_sync pk chain_id op)
let hash_raw = Operation.hash let hash_raw = Operation.hash
let hash (o : _ operation) = let hash (o : _ operation) =

View File

@ -163,9 +163,9 @@ type error += Missing_signature (* `Permanent *)
type error += Invalid_signature (* `Permanent *) type error += Invalid_signature (* `Permanent *)
val check_signature: val check_signature:
Signature.Public_key.t -> _ operation -> unit tzresult Lwt.t Signature.Public_key.t -> Chain_id.t -> _ operation -> unit tzresult Lwt.t
val check_signature_sync: val check_signature_sync:
Signature.Public_key.t -> _ operation -> unit tzresult Signature.Public_key.t -> Chain_id.t -> _ operation -> unit tzresult
val internal_operation_encoding: val internal_operation_encoding:

View File

@ -118,7 +118,8 @@ module Forge = struct
Data_encoding.Binary.to_bytes_exn Data_encoding.Binary.to_bytes_exn
Block_header.unsigned_encoding Block_header.unsigned_encoding
(shell, contents) in (shell, contents) in
let signature = Signature.sign ~watermark:Signature.Block_header delegate.sk unsigned_bytes in let signature =
Signature.sign ~watermark:Signature.(Block_header Chain_id.zero) delegate.sk unsigned_bytes in
Block_header.{ shell ; protocol_data = { contents ; signature } } |> Block_header.{ shell ; protocol_data = { contents ; signature } } |>
return return
@ -321,6 +322,7 @@ let apply header ?(operations = []) pred =
begin begin
let open Alpha_environment.Error_monad in let open Alpha_environment.Error_monad in
Proto_alpha.Main.begin_application Proto_alpha.Main.begin_application
~chain_id: Chain_id.zero
~predecessor_context: pred.context ~predecessor_context: pred.context
~predecessor_fitness: pred.header.shell.fitness ~predecessor_fitness: pred.header.shell.fitness
~predecessor_timestamp: pred.header.shell.timestamp ~predecessor_timestamp: pred.header.shell.timestamp

View File

@ -64,6 +64,7 @@ let begin_construction ?(priority=0) ?timestamp (predecessor : Block.t) =
} ; } ;
} in } in
M.begin_construction M.begin_construction
~chain_id: Chain_id.zero
~predecessor_context: predecessor.context ~predecessor_context: predecessor.context
~predecessor_timestamp: predecessor.header.shell.timestamp ~predecessor_timestamp: predecessor.header.shell.timestamp
~predecessor_fitness: predecessor.header.shell.fitness ~predecessor_fitness: predecessor.header.shell.fitness

View File

@ -40,7 +40,7 @@ let endorsement ?delegate ?level ctxt ?(signing_context = ctxt) () =
| Some level -> return level | Some level -> return level
end >>=? fun level -> end >>=? fun level ->
let op = Single (Endorsement { level }) in let op = Single (Endorsement { level }) in
return (sign ~watermark:Signature.Endorsement delegate.sk signing_context op) return (sign ~watermark:Signature.(Endorsement Chain_id.zero) delegate.sk signing_context op)
let sign ?watermark sk ctxt (Contents_list contents) = let sign ?watermark sk ctxt (Contents_list contents) =
Operation.pack (sign ?watermark sk ctxt contents) Operation.pack (sign ?watermark sk ctxt contents)

View File

@ -81,6 +81,7 @@ module Fitness = struct
end end
let begin_application let begin_application
~chain_id:_
~predecessor_context:context ~predecessor_context:context
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_fitness:_ ~predecessor_fitness:_
@ -89,17 +90,20 @@ let begin_application
return { context ; fitness } return { context ; fitness }
let begin_partial_application let begin_partial_application
~chain_id
~ancestor_context ~ancestor_context
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
block_header = block_header =
begin_application begin_application
~chain_id
~predecessor_context:ancestor_context ~predecessor_context:ancestor_context
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
block_header block_header
let begin_construction let begin_construction
~chain_id:_
~predecessor_context:context ~predecessor_context:context
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_level:_ ~predecessor_level:_

View File

@ -19,7 +19,8 @@ let bake cctxt ?(timestamp = Time.now ()) block command sk =
cctxt ~block ~timestamp ~protocol_data cctxt ~block ~timestamp ~protocol_data
[] >>=? fun (shell_header, _) -> [] >>=? fun (shell_header, _) ->
let blk = Data.Command.forge shell_header command in let blk = Data.Command.forge shell_header command in
Client_keys.append cctxt sk blk >>=? fun signed_blk -> Shell_services.Chain.chain_id cctxt ~chain:`Main () >>=? fun chain_id ->
Client_keys.append cctxt sk ~watermark:(Block_header chain_id) blk >>=? fun signed_blk ->
Shell_services.Injection.block cctxt signed_blk [] Shell_services.Injection.block cctxt signed_blk []
let int64_parameter = let int64_parameter =

View File

@ -80,11 +80,11 @@ let max_block_length =
let max_operation_data_length = 0 let max_operation_data_length = 0
let check_signature ctxt { shell ; protocol_data = { command ; signature } } = let check_signature ctxt ~chain_id { shell ; protocol_data = { 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
(Signature.check public_key signature bytes) (Signature.check ~watermark:(Block_header chain_id) public_key signature bytes)
Invalid_signature Invalid_signature
type validation_state = Updater.validation_result type validation_state = Updater.validation_result
@ -117,27 +117,31 @@ let prepare_application ctxt command level timestamp fitness =
} }
let begin_application let begin_application
~chain_id
~predecessor_context:ctxt ~predecessor_context:ctxt
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_fitness:_ ~predecessor_fitness:_
block_header = block_header =
Data.Init.check_inited ctxt >>=? fun () -> Data.Init.check_inited ctxt >>=? fun () ->
check_signature ctxt block_header >>=? fun () -> check_signature ctxt ~chain_id block_header >>=? fun () ->
prepare_application ctxt block_header.protocol_data.command prepare_application ctxt block_header.protocol_data.command
block_header.shell.level block_header.shell.timestamp block_header.shell.fitness block_header.shell.level block_header.shell.timestamp block_header.shell.fitness
let begin_partial_application let begin_partial_application
~chain_id
~ancestor_context ~ancestor_context
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
block_header = block_header =
begin_application begin_application
~chain_id
~predecessor_context:ancestor_context ~predecessor_context:ancestor_context
~predecessor_timestamp ~predecessor_timestamp
~predecessor_fitness ~predecessor_fitness
block_header block_header
let begin_construction let begin_construction
~chain_id:_
~predecessor_context:ctxt ~predecessor_context:ctxt
~predecessor_timestamp:_ ~predecessor_timestamp:_
~predecessor_level:level ~predecessor_level:level