From 44ca820944b6e45f21668c281f327c2e6c5cc972 Mon Sep 17 00:00:00 2001 From: Benjamin Canou Date: Wed, 27 Jun 2018 17:00:24 +0200 Subject: [PATCH] Genesis/Alpha: include chain id in signature for blocks and endorsements --- src/bin_client/test/demo/main.ml | 4 ++ src/bin_client/test/test_injection.sh | 2 +- src/lib_crypto/signature.ml | 8 ++-- src/lib_crypto/signature.mli | 4 +- src/lib_protocol_environment/sigs/jbuild | 1 + .../sigs/v1/chain_id.mli | 10 +++++ .../sigs/v1/signature.mli | 4 +- .../sigs/v1/updater.mli | 3 ++ .../tezos_protocol_environment.ml | 17 +++++--- .../tezos_protocol_environment.mli | 4 ++ src/lib_shell/block_directory.ml | 1 + src/lib_shell/block_validator.ml | 1 + src/lib_shell/prevalidation.ml | 7 ++-- src/lib_shell/test/test_state.ml | 1 + src/proto_alpha/lib_client/injection.ml | 21 ++++++---- .../lib_delegate/client_baking_endorsement.ml | 3 +- .../lib_delegate/client_baking_forge.ml | 3 +- .../lib_delegate/client_baking_simulator.ml | 1 + .../lib_delegate/test/proto_alpha_helpers.ml | 2 +- .../lib_protocol/src/alpha_context.mli | 4 +- src/proto_alpha/lib_protocol/src/apply.ml | 42 +++++++++---------- src/proto_alpha/lib_protocol/src/baking.ml | 8 ++-- src/proto_alpha/lib_protocol/src/baking.mli | 8 ++-- .../lib_protocol/src/helpers_services.ml | 2 +- src/proto_alpha/lib_protocol/src/main.ml | 18 ++++---- src/proto_alpha/lib_protocol/src/main.mli | 1 + .../lib_protocol/src/operation_repr.ml | 8 ++-- .../lib_protocol/src/operation_repr.mli | 4 +- .../lib_protocol/test/helpers/block.ml | 4 +- .../lib_protocol/test/helpers/incremental.ml | 1 + .../lib_protocol/test/helpers/op.ml | 2 +- src/proto_demo/lib_protocol/src/main.ml | 4 ++ .../lib_client/client_proto_main.ml | 3 +- src/proto_genesis/lib_protocol/src/main.ml | 10 +++-- 34 files changed, 135 insertions(+), 81 deletions(-) create mode 100644 src/lib_protocol_environment/sigs/v1/chain_id.mli diff --git a/src/bin_client/test/demo/main.ml b/src/bin_client/test/demo/main.ml index 4cc69b621..13be9b6db 100644 --- a/src/bin_client/test/demo/main.ml +++ b/src/bin_client/test/demo/main.ml @@ -79,6 +79,7 @@ module Fitness = struct end let begin_application + ~chain_id:_ ~predecessor_context:context ~predecessor_timestamp:_ ~predecessor_fitness:_ @@ -87,17 +88,20 @@ let begin_application return { context ; fitness } let begin_partial_application + ~chain_id ~ancestor_context ~predecessor_timestamp ~predecessor_fitness raw_block = begin_application + ~chain_id ~predecessor_context:ancestor_context ~predecessor_timestamp ~predecessor_fitness raw_block let begin_construction + ~chain_id:_ ~predecessor_context:context ~predecessor_timestamp:_ ~predecessor_level:_ diff --git a/src/bin_client/test/test_injection.sh b/src/bin_client/test/test_injection.sh index c1c6fc4bd..a6e734274 100755 --- a/src/bin_client/test/test_injection.sh +++ b/src/bin_client/test/test_injection.sh @@ -31,7 +31,7 @@ done sleep 2 # autogenerated from the demo source -protocol_version="PsVi9P3i73N4zstqkty4EiL76cofTFkthzSQPfLmChCvF7JopPh" +protocol_version="PsoXmK2EEBAsbFy7XHr8xB34jmArfrJQMRniTVdUsrSVu2VtRsr" $admin_client inject protocol "$test_dir/demo" $admin_client list protocols diff --git a/src/lib_crypto/signature.ml b/src/lib_crypto/signature.ml index f6cb66d1f..3284c3354 100644 --- a/src/lib_crypto/signature.ml +++ b/src/lib_crypto/signature.ml @@ -25,8 +25,8 @@ type secret_key = | P256 of P256.Secret_key.t type watermark = - | Block_header - | Endorsement + | Block_header of Chain_id.t + | Endorsement of Chain_id.t | Generic_operation | Custom of MBytes.t @@ -502,8 +502,8 @@ let of_p256 s = P256 s let zero = of_ed25519 Ed25519.zero let bytes_of_watermark = function - | Block_header -> MBytes.of_string "\x01" - | Endorsement -> MBytes.of_string "\x02" + | Block_header chain_id -> MBytes.concat "" [ MBytes.of_string "\x01" ; Chain_id.to_bytes chain_id ] + | Endorsement chain_id -> MBytes.concat "" [ MBytes.of_string "\x02" ; Chain_id.to_bytes chain_id ] | Generic_operation -> MBytes.of_string "\x03" | Custom bytes -> bytes diff --git a/src/lib_crypto/signature.mli b/src/lib_crypto/signature.mli index 52b43130f..4aabe8c0a 100644 --- a/src/lib_crypto/signature.mli +++ b/src/lib_crypto/signature.mli @@ -23,8 +23,8 @@ type secret_key = | P256 of P256.Secret_key.t type watermark = - | Block_header - | Endorsement + | Block_header of Chain_id.t + | Endorsement of Chain_id.t | Generic_operation | Custom of MBytes.t diff --git a/src/lib_protocol_environment/sigs/jbuild b/src/lib_protocol_environment/sigs/jbuild index b8fc366bb..c717550c4 100644 --- a/src/lib_protocol_environment/sigs/jbuild +++ b/src/lib_protocol_environment/sigs/jbuild @@ -42,6 +42,7 @@ v1/ed25519.mli v1/secp256k1.mli v1/p256.mli + v1/chain_id.mli v1/signature.mli v1/block_hash.mli v1/operation_hash.mli diff --git a/src/lib_protocol_environment/sigs/v1/chain_id.mli b/src/lib_protocol_environment/sigs/v1/chain_id.mli new file mode 100644 index 000000000..f7841dc59 --- /dev/null +++ b/src/lib_protocol_environment/sigs/v1/chain_id.mli @@ -0,0 +1,10 @@ +(**************************************************************************) +(* *) +(* Copyright (c) 2014 - 2018. *) +(* Dynamic Ledger Solutions, Inc. *) +(* *) +(* All rights reserved. No warranty, explicit or implicit, provided. *) +(* *) +(**************************************************************************) + +include S.HASH diff --git a/src/lib_protocol_environment/sigs/v1/signature.mli b/src/lib_protocol_environment/sigs/v1/signature.mli index 969a9041b..00d1bd502 100644 --- a/src/lib_protocol_environment/sigs/v1/signature.mli +++ b/src/lib_protocol_environment/sigs/v1/signature.mli @@ -18,8 +18,8 @@ type public_key = | P256 of P256.Public_key.t type watermark = - | Block_header - | Endorsement + | Block_header of Chain_id.t + | Endorsement of Chain_id.t | Generic_operation | Custom of MBytes.t diff --git a/src/lib_protocol_environment/sigs/v1/updater.mli b/src/lib_protocol_environment/sigs/v1/updater.mli index 8304a9eb2..6c8bd569f 100644 --- a/src/lib_protocol_environment/sigs/v1/updater.mli +++ b/src/lib_protocol_environment/sigs/v1/updater.mli @@ -144,6 +144,7 @@ module type PROTOCOL = sig The resulting `validation_state` will be used for multi-pass validation. *) val begin_partial_application: + chain_id: Chain_id.t -> ancestor_context: Context.t -> predecessor_timestamp: Time.t -> predecessor_fitness: Fitness.t -> @@ -157,6 +158,7 @@ module type PROTOCOL = sig [begin_application], so all the check performed by the former must be repeated in the latter. *) val begin_application: + chain_id: Chain_id.t -> predecessor_context: Context.t -> predecessor_timestamp: Time.t -> predecessor_fitness: Fitness.t -> @@ -173,6 +175,7 @@ module type PROTOCOL = sig block header usually includes a signature, the header provided to {!begin_construction} should includes a faked signature. *) val begin_construction: + chain_id: Chain_id.t -> predecessor_context: Context.t -> predecessor_timestamp: Time.t -> predecessor_level: Int32.t -> diff --git a/src/lib_protocol_environment/tezos_protocol_environment.ml b/src/lib_protocol_environment/tezos_protocol_environment.ml index 156d55011..ae2454d02 100644 --- a/src/lib_protocol_environment/tezos_protocol_environment.ml +++ b/src/lib_protocol_environment/tezos_protocol_environment.ml @@ -82,18 +82,21 @@ module Make (Context : CONTEXT) = struct type validation_state val current_context: validation_state -> context tzresult Lwt.t val begin_partial_application: + chain_id: Chain_id.t -> ancestor_context: context -> predecessor_timestamp: Time.t -> predecessor_fitness: Fitness.t -> block_header -> validation_state tzresult Lwt.t val begin_application: + chain_id: Chain_id.t -> predecessor_context: context -> predecessor_timestamp: Time.t -> predecessor_fitness: Fitness.t -> block_header -> validation_state tzresult Lwt.t val begin_construction: + chain_id: Chain_id.t -> predecessor_context: context -> predecessor_timestamp: Time.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 Lwt.t = 'a Lwt.t 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 Operation_hash.t = Operation_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 | Error errors -> Error (List.map (fun error -> Ecoproto_error error) errors) + module Chain_id = Chain_id module Block_hash = Block_hash module Operation_hash = Operation_hash module Operation_list_hash = Operation_list_hash @@ -642,25 +647,25 @@ module Make (Context : CONTEXT) = struct module Lift(P : Updater.PROTOCOL) = struct include P let begin_partial_application - ~ancestor_context ~predecessor_timestamp ~predecessor_fitness + ~chain_id ~ancestor_context ~predecessor_timestamp ~predecessor_fitness raw_block = begin_partial_application - ~ancestor_context ~predecessor_timestamp ~predecessor_fitness + ~chain_id ~ancestor_context ~predecessor_timestamp ~predecessor_fitness raw_block >|= wrap_error let begin_application - ~predecessor_context ~predecessor_timestamp + ~chain_id ~predecessor_context ~predecessor_timestamp ~predecessor_fitness raw_block = begin_application - ~predecessor_context ~predecessor_timestamp + ~chain_id ~predecessor_context ~predecessor_timestamp ~predecessor_fitness raw_block >|= wrap_error let begin_construction - ~predecessor_context ~predecessor_timestamp + ~chain_id ~predecessor_context ~predecessor_timestamp ~predecessor_level ~predecessor_fitness ~predecessor ~timestamp ?protocol_data () = begin_construction - ~predecessor_context ~predecessor_timestamp + ~chain_id ~predecessor_context ~predecessor_timestamp ~predecessor_level ~predecessor_fitness ~predecessor ~timestamp ?protocol_data () >|= wrap_error let current_context c = diff --git a/src/lib_protocol_environment/tezos_protocol_environment.mli b/src/lib_protocol_environment/tezos_protocol_environment.mli index faa538df4..0396faf13 100644 --- a/src/lib_protocol_environment/tezos_protocol_environment.mli +++ b/src/lib_protocol_environment/tezos_protocol_environment.mli @@ -75,18 +75,21 @@ module Make (Context : CONTEXT) : sig type validation_state val current_context: validation_state -> context tzresult Lwt.t val begin_partial_application: + chain_id: Chain_id.t -> ancestor_context: context -> predecessor_timestamp: Time.t -> predecessor_fitness: Fitness.t -> block_header -> validation_state tzresult Lwt.t val begin_application: + chain_id: Chain_id.t -> predecessor_context: context -> predecessor_timestamp: Time.t -> predecessor_fitness: Fitness.t -> block_header -> validation_state tzresult Lwt.t val begin_construction: + chain_id: Chain_id.t -> predecessor_context: context -> predecessor_timestamp: Time.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 Lwt.t = 'a Lwt.t 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 Operation_hash.t = Operation_hash.t and type Operation_list_hash.t = Operation_list_hash.t diff --git a/src/lib_shell/block_directory.ml b/src/lib_shell/block_directory.ml index acf1f122a..17893b0ed 100644 --- a/src/lib_shell/block_directory.ml +++ b/src/lib_shell/block_directory.ml @@ -241,6 +241,7 @@ let build_raw_rpc_directory let predecessor = State.Block.hash block in let header = State.Block.shell_header block in Next_proto.begin_construction + ~chain_id: (State.Block.chain_id block) ~predecessor_context:ctxt ~predecessor_timestamp:header.timestamp ~predecessor_level:header.level diff --git a/src/lib_shell/block_validator.ml b/src/lib_shell/block_validator.ml index 4938f939b..606a96567 100644 --- a/src/lib_shell/block_validator.ml +++ b/src/lib_shell/block_validator.ml @@ -184,6 +184,7 @@ let apply_block pred_context pred_hash header.shell.timestamp >>= fun context -> (* TODO wrap 'proto_error' into 'block_error' *) Proto.begin_application + ~chain_id: (State.Chain.id chain_state) ~predecessor_context:context ~predecessor_timestamp:pred_header.shell.timestamp ~predecessor_fitness:pred_header.shell.fitness diff --git a/src/lib_shell/prevalidation.ml b/src/lib_shell/prevalidation.ml index dcdc67a55..25e05bcd0 100644 --- a/src/lib_shell/prevalidation.ml +++ b/src/lib_shell/prevalidation.ml @@ -65,7 +65,7 @@ let start_prevalidation State.Block.header predecessor in State.Block.context predecessor >>= fun predecessor_context -> Context.get_protocol predecessor_context >>= fun protocol -> - let predecessor = State.Block.hash predecessor in + let predecessor_hash = State.Block.hash predecessor in begin match Registered_protocol.get protocol with | None -> @@ -77,7 +77,7 @@ let start_prevalidation return protocol end >>=? fun (module Proto) -> Context.reset_test_chain - predecessor_context predecessor + predecessor_context predecessor_hash timestamp >>= fun predecessor_context -> begin match protocol_data with @@ -92,11 +92,12 @@ let start_prevalidation | Some protocol_data -> return_some protocol_data end >>=? fun protocol_data -> Proto.begin_construction + ~chain_id: (State.Block.chain_id predecessor) ~predecessor_context ~predecessor_timestamp ~predecessor_fitness ~predecessor_level - ~predecessor + ~predecessor: predecessor_hash ~timestamp ?protocol_data () diff --git a/src/lib_shell/test/test_state.ml b/src/lib_shell/test/test_state.ml index 0467798bd..44595e42c 100644 --- a/src/lib_shell/test/test_state.ml +++ b/src/lib_shell/test/test_state.ml @@ -97,6 +97,7 @@ let build_valid_chain state vtbl pred names = let pred_header = State.Block.header pred in begin Proto.begin_application + ~chain_id: Chain_id.zero ~predecessor_context ~predecessor_timestamp: pred_header.shell.timestamp ~predecessor_fitness: pred_header.shell.fitness diff --git a/src/proto_alpha/lib_client/injection.ml b/src/proto_alpha/lib_client/injection.ml index 034ae6840..6589bd36b 100644 --- a/src/proto_alpha/lib_client/injection.ml +++ b/src/proto_alpha/lib_client/injection.ml @@ -21,7 +21,8 @@ let get_branch (rpc_config: #Proto_alpha.full) | `Genesis -> return `Genesis end >>=? fun block -> 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 = Operation_hash.t * 'kind operation * 'kind operation_metadata @@ -35,21 +36,23 @@ type 'kind result = let preapply (type t) (cctxt: #Proto_alpha.full) ~chain ~block ?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 = Data_encoding.Binary.to_bytes_exn Operation.unsigned_encoding ({ branch }, Contents_list contents) in - let watermark = - match contents with - | Single (Endorsement _) -> Signature.Endorsement - | _ -> Signature.Generic_operation in begin match src_sk with | None -> return_none | Some src_sk -> - Client_keys.sign cctxt - ~watermark src_sk bytes >>=? fun signature -> + begin match contents with + | 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 end >>=? fun signature -> let op : _ Operation.t = @@ -71,7 +74,7 @@ let preapply (type t) let simulate (type t) (cctxt: #Proto_alpha.full) ~chain ~block ?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 = { shell = { branch } ; protocol_data = { contents ; signature = None } } in diff --git a/src/proto_alpha/lib_delegate/client_baking_endorsement.ml b/src/proto_alpha/lib_delegate/client_baking_endorsement.ml index f9e95e74a..5ed358dbc 100644 --- a/src/proto_alpha/lib_delegate/client_baking_endorsement.ml +++ b/src/proto_alpha/lib_delegate/client_baking_endorsement.ml @@ -31,8 +31,9 @@ let inject_endorsement ~branch:hash ~level:level () >>=? fun bytes -> + Shell_services.Chain.chain_id cctxt ~chain () >>=? fun chain_id -> 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 -> State.record cctxt pkh level >>=? fun () -> return oph diff --git a/src/proto_alpha/lib_delegate/client_baking_forge.ml b/src/proto_alpha/lib_delegate/client_baking_forge.ml index 6de629b67..d4750094a 100644 --- a/src/proto_alpha/lib_delegate/client_baking_forge.ml +++ b/src/proto_alpha/lib_delegate/client_baking_forge.ml @@ -75,7 +75,8 @@ let forge_block_header Data_encoding.Binary.to_bytes_exn Alpha_context.Block_header.unsigned_encoding (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 = Alpha_context.Block_header.{ diff --git a/src/proto_alpha/lib_delegate/client_baking_simulator.ml b/src/proto_alpha/lib_delegate/client_baking_simulator.ml index f2c4e43f1..780a97afd 100644 --- a/src/proto_alpha/lib_delegate/client_baking_simulator.ml +++ b/src/proto_alpha/lib_delegate/client_baking_simulator.ml @@ -57,6 +57,7 @@ let begin_construction (_cctxt : #Proto_alpha.full) index predecessor = operations_hash = Operation_list_list_hash.zero ; } in Main.begin_construction + ~chain_id: predecessor.chain_id ~predecessor_context: context ~predecessor_timestamp: header.timestamp ~predecessor_fitness: header.fitness diff --git a/src/proto_alpha/lib_delegate/test/proto_alpha_helpers.ml b/src/proto_alpha/lib_delegate/test/proto_alpha_helpers.ml index 6a0f11afd..3b8c34b1a 100644 --- a/src/proto_alpha/lib_delegate/test/proto_alpha_helpers.ml +++ b/src/proto_alpha/lib_delegate/test/proto_alpha_helpers.ml @@ -555,7 +555,7 @@ module Endorse = struct let shell = { Tezos_base.Operation.branch = hash } in let contents = 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 block diff --git a/src/proto_alpha/lib_protocol/src/alpha_context.mli b/src/proto_alpha/lib_protocol/src/alpha_context.mli index 318c0b926..ea1b209a0 100644 --- a/src/proto_alpha/lib_protocol/src/alpha_context.mli +++ b/src/proto_alpha/lib_protocol/src/alpha_context.mli @@ -943,8 +943,8 @@ module Operation : sig type error += Missing_signature (* `Permanent *) type error += Invalid_signature (* `Permanent *) - val check_signature: public_key -> _ operation -> unit tzresult Lwt.t - val check_signature_sync: public_key -> _ operation -> unit tzresult + val check_signature: public_key -> Chain_id.t -> _ operation -> unit tzresult Lwt.t + val check_signature_sync: public_key -> Chain_id.t -> _ operation -> unit tzresult val internal_operation_encoding: packed_internal_operation Data_encoding.t diff --git a/src/proto_alpha/lib_protocol/src/apply.ml b/src/proto_alpha/lib_protocol/src/apply.ml index 007fb0e8b..3ecac6a9e 100644 --- a/src/proto_alpha/lib_protocol/src/apply.ml +++ b/src/proto_alpha/lib_protocol/src/apply.ml @@ -480,7 +480,7 @@ let apply_internal_manager_operations ctxt mode ~payer ops = apply ctxt [] ops 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 = let Manager_operation { source ; fee ; counter ; operation ; gas_limit ; storage_limit } = op in 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 change in the future, allowing several managers to group-sign a 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.spend ctxt source fee >>=? fun ctxt -> add_fees ctxt fee >>=? fun ctxt -> @@ -561,15 +561,15 @@ let rec mark_skipped let rec precheck_manager_contents_list : 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 = - fun ctxt raw_operation contents_list -> + fun ctxt chain_id raw_operation contents_list -> match contents_list with | 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) -> - precheck_manager_contents ctxt raw_operation op >>=? fun ctxt -> - precheck_manager_contents_list ctxt raw_operation rest + precheck_manager_contents ctxt chain_id raw_operation op >>=? fun ctxt -> + precheck_manager_contents_list ctxt chain_id raw_operation rest let rec apply_manager_contents_list_rec : type kind. @@ -656,7 +656,7 @@ let apply_manager_contents_list ctxt mode baker contents_list = | `Success ctxt -> Lwt.return (ctxt, results) let apply_contents_list - (type kind) ctxt mode pred_block baker + (type kind) ctxt chain_id mode pred_block baker (operation : kind operation) (contents_list : kind contents_list) : (context * kind contents_result_list) tzresult Lwt.t = @@ -670,7 +670,7 @@ let apply_contents_list fail_unless Raw_level.(succ level = current_level) 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) else let ctxt = record_endorsement ctxt delegate in @@ -716,8 +716,8 @@ let apply_contents_list (Outdated_double_endorsement_evidence { level = level.level ; last = oldest_level }) >>=? fun () -> - Baking.check_endorsement_rights ctxt op1 >>=? fun (delegate1, _, _) -> - Baking.check_endorsement_rights ctxt op2 >>=? fun (delegate2, _, _) -> + Baking.check_endorsement_rights ctxt chain_id op1 >>=? fun (delegate1, _, _) -> + Baking.check_endorsement_rights ctxt chain_id op2 >>=? fun (delegate2, _, _) -> fail_unless (Signature.Public_key_hash.equal delegate1 delegate2) (Inconsistent_double_endorsement_evidence @@ -765,10 +765,10 @@ let apply_contents_list let level = Level.from_raw ctxt raw_level in Roll.baking_rights_owner 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 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 (Signature.Public_key.equal delegate1 delegate2) (Inconsistent_double_baking_evidence @@ -805,7 +805,7 @@ let apply_contents_list end | Single (Proposals { source ; period ; proposals }) -> 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 fail_unless Voting_period.(level.voting_period = period) (Wrong_voting_period (level.voting_period, period)) >>=? fun () -> @@ -813,25 +813,25 @@ let apply_contents_list return (ctxt, Single_result Proposals_result) | Single (Ballot { source ; period ; proposal ; ballot }) -> 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 fail_unless Voting_period.(level.voting_period = period) (Wrong_voting_period (level.voting_period, period)) >>=? fun () -> Amendment.record_ballot ctxt source proposal ballot >>=? fun ctxt -> return (ctxt, Single_result Ballot_result) | 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) -> return (ctxt, result) | 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) -> 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 apply_contents_list - ctxt mode pred_block baker operation + ctxt chain_id mode pred_block baker operation operation.protocol_data.contents >>=? fun (ctxt, result) -> let ctxt = Gas.set_unlimited 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 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 Baking.check_proof_of_work_stamp ctxt block_header >>=? fun () -> Baking.check_fitness_gap ctxt block_header >>=? fun () -> Baking.check_baking_rights 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 = match block_header.protocol_data.contents.seed_nonce_hash with | None -> false diff --git a/src/proto_alpha/lib_protocol/src/baking.ml b/src/proto_alpha/lib_protocol/src/baking.ml index fe9e6c907..6a88f0f43 100644 --- a/src/proto_alpha/lib_protocol/src/baking.ml +++ b/src/proto_alpha/lib_protocol/src/baking.ml @@ -178,7 +178,7 @@ let endorsement_rights c level = Signature.Public_key_hash.Map.empty (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 Single (Endorsement { level ; _ }) = op.protocol_data.contents in begin @@ -190,7 +190,7 @@ let check_endorsement_rights ctxt (op : Kind.endorsement Operation.t) = match Signature.Public_key_hash.Map.fold (* no find_first *) (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 | Ok () -> Some (pkh, slots, used)) endorsements None @@ -241,14 +241,14 @@ let check_proof_of_work_stamp ctxt block = else fail Invalid_stamp -let check_signature block key = +let check_signature block chain_id key = let check_signature key { 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 chain_id) key signature unsigned_header in if check_signature key block then return_unit else diff --git a/src/proto_alpha/lib_protocol/src/baking.mli b/src/proto_alpha/lib_protocol/src/baking.mli index 2d6165291..79e403c13 100644 --- a/src/proto_alpha/lib_protocol/src/baking.mli +++ b/src/proto_alpha/lib_protocol/src/baking.mli @@ -44,7 +44,7 @@ val endorsement_rights: (** Check that the operation was signed by a delegate allowed to endorse at the level specified by the endorsement. *) 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 (** Returns the endorsement reward calculated w.r.t a given priority. *) @@ -67,9 +67,9 @@ val first_baking_priorities: Level.t -> int list tzresult Lwt.t -(** [check_signature ctxt block id] check if the block is signed with - the given key *) -val check_signature: Block_header.t -> public_key -> unit tzresult Lwt.t +(** [check_signature ctxt chain_id block id] check if the block is + signed with the given key, and belongs to the given [chain_id] *) +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 is valid for the given diffculty. The signature is not passed as it diff --git a/src/proto_alpha/lib_protocol/src/helpers_services.ml b/src/proto_alpha/lib_protocol/src/helpers_services.ml index 17aef6430..32d6e7dcb 100644 --- a/src/proto_alpha/lib_protocol/src/helpers_services.ml +++ b/src/proto_alpha/lib_protocol/src/helpers_services.ml @@ -254,7 +254,7 @@ module Scripts = struct return result | _ -> 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) -> return result diff --git a/src/proto_alpha/lib_protocol/src/main.ml b/src/proto_alpha/lib_protocol/src/main.ml index 7f8ac7734..2d3d7069d 100644 --- a/src/proto_alpha/lib_protocol/src/main.ml +++ b/src/proto_alpha/lib_protocol/src/main.ml @@ -78,6 +78,7 @@ type validation_mode = type validation_state = { mode : validation_mode ; + chain_id : Chain_id.t ; ctxt : Alpha_context.t ; op_count : int ; } @@ -86,6 +87,7 @@ let current_context { ctxt ; _ } = return (Alpha_context.finalize ctxt).context let begin_partial_application + ~chain_id ~ancestor_context:ctxt ~predecessor_timestamp ~predecessor_fitness @@ -95,13 +97,14 @@ let begin_partial_application let timestamp = block_header.shell.timestamp in Alpha_context.prepare ~level ~timestamp ~fitness ctxt >>=? fun ctxt -> Apply.begin_application - ctxt block_header predecessor_timestamp >>=? fun (ctxt, baker) -> + ctxt chain_id block_header predecessor_timestamp >>=? fun (ctxt, baker) -> let mode = Partial_application { block_header ; baker = Signature.Public_key.hash baker } in - return { mode ; ctxt ; op_count = 0 } + return { mode ; chain_id ; ctxt ; op_count = 0 } let begin_application + ~chain_id ~predecessor_context:ctxt ~predecessor_timestamp ~predecessor_fitness @@ -111,11 +114,12 @@ let begin_application let timestamp = block_header.shell.timestamp in Alpha_context.prepare ~level ~timestamp ~fitness ctxt >>=? fun ctxt -> Apply.begin_application - ctxt block_header predecessor_timestamp >>=? fun (ctxt, baker) -> + ctxt chain_id block_header predecessor_timestamp >>=? fun (ctxt, baker) -> let mode = Application { block_header ; baker = Signature.Public_key.hash baker } in - return { mode ; ctxt ; op_count = 0 } + return { mode ; chain_id ; ctxt ; op_count = 0 } let begin_construction + ~chain_id ~predecessor_context:ctxt ~predecessor_timestamp:pred_timestamp ~predecessor_level:pred_level @@ -142,10 +146,10 @@ let begin_construction Full_construction { predecessor ; baker ; protocol_data } in return (mode, ctxt) end >>=? fun (mode, ctxt) -> - return { mode ; ctxt ; op_count = 0 } + return { mode ; chain_id ; ctxt ; op_count = 0 } let apply_operation - ({ mode ; ctxt ; op_count ; _ } as data) + ({ mode ; chain_id ; ctxt ; op_count ; _ } as data) (operation : Alpha_context.packed_operation) = match mode with | Partial_application _ when @@ -169,7 +173,7 @@ let apply_operation | Partial_construction { predecessor } -> predecessor, Signature.Public_key_hash.zero in - Apply.apply_operation ctxt Optimized predecessor baker + Apply.apply_operation ctxt chain_id Optimized predecessor baker (Alpha_context.Operation.hash operation) operation >>=? fun (ctxt, result) -> let op_count = op_count + 1 in diff --git a/src/proto_alpha/lib_protocol/src/main.mli b/src/proto_alpha/lib_protocol/src/main.mli index f726376cd..9d8cd1299 100644 --- a/src/proto_alpha/lib_protocol/src/main.mli +++ b/src/proto_alpha/lib_protocol/src/main.mli @@ -29,6 +29,7 @@ type validation_mode = type validation_state = { mode : validation_mode ; + chain_id : Chain_id.t ; ctxt : Alpha_context.t ; op_count : int ; } diff --git a/src/proto_alpha/lib_protocol/src/operation_repr.ml b/src/proto_alpha/lib_protocol/src/operation_repr.ml index f9bdde259..15e694e30 100644 --- a/src/proto_alpha/lib_protocol/src/operation_repr.ml +++ b/src/proto_alpha/lib_protocol/src/operation_repr.ml @@ -644,7 +644,7 @@ let () = (function Missing_signature -> Some () | _ -> None) (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 unsigned_operation = Data_encoding.Binary.to_bytes_exn @@ -659,14 +659,14 @@ let check_signature_sync (type kind) key ({ shell ; protocol_data } : kind opera | Cons _, None -> Error [Missing_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 -> check ~watermark:Generic_operation (Contents_list contents) signature | Cons _ as contents, Some signature -> check ~watermark:Generic_operation (Contents_list contents) signature -let check_signature pk op = - Lwt.return (check_signature_sync pk op) +let check_signature pk chain_id op = + Lwt.return (check_signature_sync pk chain_id op) let hash_raw = Operation.hash let hash (o : _ operation) = diff --git a/src/proto_alpha/lib_protocol/src/operation_repr.mli b/src/proto_alpha/lib_protocol/src/operation_repr.mli index 2711c41a2..347ea2a54 100644 --- a/src/proto_alpha/lib_protocol/src/operation_repr.mli +++ b/src/proto_alpha/lib_protocol/src/operation_repr.mli @@ -163,9 +163,9 @@ type error += Missing_signature (* `Permanent *) type error += Invalid_signature (* `Permanent *) 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: - Signature.Public_key.t -> _ operation -> unit tzresult + Signature.Public_key.t -> Chain_id.t -> _ operation -> unit tzresult val internal_operation_encoding: diff --git a/src/proto_alpha/lib_protocol/test/helpers/block.ml b/src/proto_alpha/lib_protocol/test/helpers/block.ml index 73bb10eca..98a95dacb 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/block.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/block.ml @@ -118,7 +118,8 @@ module Forge = struct Data_encoding.Binary.to_bytes_exn Block_header.unsigned_encoding (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 } } |> return @@ -321,6 +322,7 @@ let apply header ?(operations = []) pred = begin let open Alpha_environment.Error_monad in Proto_alpha.Main.begin_application + ~chain_id: Chain_id.zero ~predecessor_context: pred.context ~predecessor_fitness: pred.header.shell.fitness ~predecessor_timestamp: pred.header.shell.timestamp diff --git a/src/proto_alpha/lib_protocol/test/helpers/incremental.ml b/src/proto_alpha/lib_protocol/test/helpers/incremental.ml index 065cade7b..11ef10aff 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/incremental.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/incremental.ml @@ -64,6 +64,7 @@ let begin_construction ?(priority=0) ?timestamp (predecessor : Block.t) = } ; } in M.begin_construction + ~chain_id: Chain_id.zero ~predecessor_context: predecessor.context ~predecessor_timestamp: predecessor.header.shell.timestamp ~predecessor_fitness: predecessor.header.shell.fitness diff --git a/src/proto_alpha/lib_protocol/test/helpers/op.ml b/src/proto_alpha/lib_protocol/test/helpers/op.ml index a788aa2b9..dd18d381b 100644 --- a/src/proto_alpha/lib_protocol/test/helpers/op.ml +++ b/src/proto_alpha/lib_protocol/test/helpers/op.ml @@ -40,7 +40,7 @@ let endorsement ?delegate ?level ctxt ?(signing_context = ctxt) () = | Some level -> return level end >>=? fun level -> 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) = Operation.pack (sign ?watermark sk ctxt contents) diff --git a/src/proto_demo/lib_protocol/src/main.ml b/src/proto_demo/lib_protocol/src/main.ml index 32c47a8a4..20c93d950 100644 --- a/src/proto_demo/lib_protocol/src/main.ml +++ b/src/proto_demo/lib_protocol/src/main.ml @@ -81,6 +81,7 @@ module Fitness = struct end let begin_application + ~chain_id:_ ~predecessor_context:context ~predecessor_timestamp:_ ~predecessor_fitness:_ @@ -89,17 +90,20 @@ let begin_application return { context ; fitness } let begin_partial_application + ~chain_id ~ancestor_context ~predecessor_timestamp ~predecessor_fitness block_header = begin_application + ~chain_id ~predecessor_context:ancestor_context ~predecessor_timestamp ~predecessor_fitness block_header let begin_construction + ~chain_id:_ ~predecessor_context:context ~predecessor_timestamp:_ ~predecessor_level:_ diff --git a/src/proto_genesis/lib_client/client_proto_main.ml b/src/proto_genesis/lib_client/client_proto_main.ml index f69dc91f0..6c392ce62 100644 --- a/src/proto_genesis/lib_client/client_proto_main.ml +++ b/src/proto_genesis/lib_client/client_proto_main.ml @@ -19,7 +19,8 @@ let bake cctxt ?(timestamp = Time.now ()) block command sk = cctxt ~block ~timestamp ~protocol_data [] >>=? fun (shell_header, _) -> 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 [] let int64_parameter = diff --git a/src/proto_genesis/lib_protocol/src/main.ml b/src/proto_genesis/lib_protocol/src/main.ml index b2add7d17..3bbcea37a 100644 --- a/src/proto_genesis/lib_protocol/src/main.ml +++ b/src/proto_genesis/lib_protocol/src/main.ml @@ -80,11 +80,11 @@ let max_block_length = 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 Data.Pubkey.get_pubkey ctxt >>= fun public_key -> fail_unless - (Signature.check public_key signature bytes) + (Signature.check ~watermark:(Block_header chain_id) public_key signature bytes) Invalid_signature type validation_state = Updater.validation_result @@ -117,27 +117,31 @@ let prepare_application ctxt command level timestamp fitness = } let begin_application + ~chain_id ~predecessor_context:ctxt ~predecessor_timestamp:_ ~predecessor_fitness:_ block_header = 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 block_header.shell.level block_header.shell.timestamp block_header.shell.fitness let begin_partial_application + ~chain_id ~ancestor_context ~predecessor_timestamp ~predecessor_fitness block_header = begin_application + ~chain_id ~predecessor_context:ancestor_context ~predecessor_timestamp ~predecessor_fitness block_header let begin_construction + ~chain_id:_ ~predecessor_context:ctxt ~predecessor_timestamp:_ ~predecessor_level:level