From 5c1f96f3a11c49949cd05648cd8fa8d7c3335fd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Henry?= Date: Fri, 29 Sep 2017 18:43:13 +0200 Subject: [PATCH] Shell: add the number of validation passes in the block header. --- src/client/client_node_rpcs.ml | 1 + src/client/client_node_rpcs.mli | 1 + src/client/embedded/demo/client_proto_main.ml | 1 + src/environment/v1/tezos_data.mli | 1 + src/node/db/store.ml | 16 +++++----------- src/node/db/store.mli | 1 - src/node/shell/distributed_db.ml | 17 ++++++++++------- src/node/shell/distributed_db.mli | 4 ++-- src/node/shell/node.ml | 5 +++++ src/node/shell/node_rpc_services.ml | 11 +++++++---- src/node/shell/node_rpc_services.mli | 1 + src/node/shell/state.ml | 16 +++++++--------- src/node/shell/state.mli | 2 +- src/node/shell/validator.ml | 7 +++++-- src/proto/alpha/block_header_repr.ml | 4 ++-- src/proto/genesis/services.ml | 2 +- src/utils/tezos_data.ml | 12 +++++++----- src/utils/tezos_data.mli | 1 + test/shell/test_state.ml | 2 ++ test/shell/test_store.ml | 5 ++--- 20 files changed, 62 insertions(+), 48 deletions(-) diff --git a/src/client/client_node_rpcs.ml b/src/client/client_node_rpcs.ml index 74f8b910c..7172af749 100644 --- a/src/client/client_node_rpcs.ml +++ b/src/client/client_node_rpcs.ml @@ -63,6 +63,7 @@ module Blocks = struct proto_level: int ; (* uint8 *) predecessor: Block_hash.t ; timestamp: Time.t ; + validation_passes: int ; (* uint8 *) operations_hash: Operation_list_list_hash.t ; fitness: MBytes.t list ; data: MBytes.t ; diff --git a/src/client/client_node_rpcs.mli b/src/client/client_node_rpcs.mli index 825e6ed45..9dd9d5f3e 100644 --- a/src/client/client_node_rpcs.mli +++ b/src/client/client_node_rpcs.mli @@ -99,6 +99,7 @@ module Blocks : sig proto_level: int ; (* uint8 *) predecessor: Block_hash.t ; timestamp: Time.t ; + validation_passes: int ; (* uint8 *) operations_hash: Operation_list_list_hash.t ; fitness: MBytes.t list ; data: MBytes.t ; diff --git a/src/client/embedded/demo/client_proto_main.ml b/src/client/embedded/demo/client_proto_main.ml index 0fcf2d2f8..3a756089f 100644 --- a/src/client/embedded/demo/client_proto_main.ml +++ b/src/client/embedded/demo/client_proto_main.ml @@ -53,6 +53,7 @@ let mine cctxt = level = Int32.succ bi.level ; timestamp = Time.now () ; fitness ; + validation_passes = 0 ; operations_hash = Operation_list_list_hash.empty } ; proto = MBytes.create 0 } >>=? fun bytes -> Client_node_rpcs.inject_block cctxt.rpc_config bytes [] >>=? fun hash -> diff --git a/src/environment/v1/tezos_data.mli b/src/environment/v1/tezos_data.mli index 38d39cfd3..0f88b57e7 100644 --- a/src/environment/v1/tezos_data.mli +++ b/src/environment/v1/tezos_data.mli @@ -69,6 +69,7 @@ module Block_header : sig proto_level: int ; (* uint8 *) predecessor: Block_hash.t ; timestamp: Time.t ; + validation_passes: int ; (* uint8 *) operations_hash: Operation_list_list_hash.t ; fitness: MBytes.t list ; } diff --git a/src/node/db/store.ml b/src/node/db/store.ml index f1dd7a5a4..acee8ef5a 100644 --- a/src/node/db/store.ml +++ b/src/node/db/store.ml @@ -85,7 +85,6 @@ module Block = struct type contents = { header: Block_header.t ; message: string ; - operation_list_count: int ; max_operations_ttl: int ; context: Context.commit ; } @@ -99,17 +98,12 @@ module Block = struct let encoding = let open Data_encoding in conv - (fun { header ; message ; operation_list_count ; - max_operations_ttl ; context } -> - (message, operation_list_count, max_operations_ttl, - context, header)) - (fun (message, operation_list_count, - max_operations_ttl, context, header) -> - { header ; message ; max_operations_ttl ; - operation_list_count ; context }) - (obj5 + (fun { header ; message ; max_operations_ttl ; context } -> + (message, max_operations_ttl, context, header)) + (fun (message, max_operations_ttl, context, header) -> + { header ; message ; max_operations_ttl ; context }) + (obj4 (req "message" string) - (req "operation_list_count" uint8) (req "max_operations_ttl" uint16) (req "context" Context.commit_encoding) (req "header" Block_header.encoding)) diff --git a/src/node/db/store.mli b/src/node/db/store.mli index fcb326384..0ff589c3d 100644 --- a/src/node/db/store.mli +++ b/src/node/db/store.mli @@ -88,7 +88,6 @@ module Block : sig type contents = { header: Block_header.t ; message: string ; - operation_list_count: int ; max_operations_ttl: int ; context: Context.commit ; } diff --git a/src/node/shell/distributed_db.ml b/src/node/shell/distributed_db.ml index f179f8bca..dc2ebd230 100644 --- a/src/node/shell/distributed_db.ml +++ b/src/node/shell/distributed_db.ml @@ -736,17 +736,18 @@ let read_all_operations net_db hash n = map_p (Raw_operation.Table.read net_db.operation_db.table) hashes) operations -let commit_block net_db hash n validation_result = +let commit_block net_db hash validation_result = Raw_block_header.Table.read net_db.block_header_db.table hash >>=? fun header -> - read_all_operations net_db hash n >>=? fun operations -> + read_all_operations net_db + hash header.shell.validation_passes >>=? fun operations -> State.Block.store net_db.net_state header operations validation_result >>=? fun res -> Raw_block_header.Table.clear net_db.block_header_db.table hash ; Raw_operation_hashes.clear_all - net_db.operation_hashes_db.table hash n ; + net_db.operation_hashes_db.table hash header.shell.validation_passes ; Raw_operations.clear_all - net_db.operations_db.table hash n ; + net_db.operations_db.table hash header.shell.validation_passes ; (* TODO: proper handling of the operations table by the prevalidator. *) List.iter (List.iter @@ -756,13 +757,15 @@ let commit_block net_db hash n validation_result = operations ; return res -let commit_invalid_block net_db hash n = +let commit_invalid_block net_db hash = Raw_block_header.Table.read net_db.block_header_db.table hash >>=? fun header -> State.Block.store_invalid net_db.net_state header >>=? fun res -> Raw_block_header.Table.clear net_db.block_header_db.table hash ; - Raw_operation_hashes.clear_all net_db.operation_hashes_db.table hash n ; - Raw_operations.clear_all net_db.operations_db.table hash n ; + Raw_operation_hashes.clear_all + net_db.operation_hashes_db.table hash header.shell.validation_passes ; + Raw_operations.clear_all + net_db.operations_db.table hash header.shell.validation_passes ; return res let inject_operation net_db h op = diff --git a/src/node/shell/distributed_db.mli b/src/node/shell/distributed_db.mli index 1244b9a90..2b33f20d1 100644 --- a/src/node/shell/distributed_db.mli +++ b/src/node/shell/distributed_db.mli @@ -43,10 +43,10 @@ val resolve_operation: net_db -> operation -> (Operation_hash.t * Operation.t) tzresult Lwt.t val commit_block: - net_db -> Block_hash.t -> int -> Updater.validation_result -> + net_db -> Block_hash.t -> Updater.validation_result -> State.Block.t option tzresult Lwt.t val commit_invalid_block: - net_db -> Block_hash.t -> int -> + net_db -> Block_hash.t -> bool tzresult Lwt.t val inject_block: t -> MBytes.t -> operation list list -> diff --git a/src/node/shell/node.ml b/src/node/shell/node.ml index 85fce9f43..20b22a930 100644 --- a/src/node/shell/node.ml +++ b/src/node/shell/node.ml @@ -143,6 +143,7 @@ module RPC = struct proto_level: int ; (* uint8 *) predecessor: Block_hash.t ; timestamp: Time.t ; + validation_passes: int ; (* uint8 *) operations_hash: Operation_list_list_hash.t ; fitness: MBytes.t list ; data: MBytes.t ; @@ -165,6 +166,7 @@ module RPC = struct proto_level = header.shell.proto_level ; predecessor = header.shell.predecessor ; timestamp = header.shell.timestamp ; + validation_passes = header.shell.validation_passes ; operations_hash = header.shell.operations_hash ; fitness = header.shell.fitness ; data = header.proto ; @@ -275,6 +277,7 @@ module RPC = struct fitness ; timestamp = Prevalidator.timestamp pv ; protocol ; + validation_passes = List.length operations ; operations_hash = Operation_list_list_hash.compute (List.map Operation_list_hash.compute operations) ; @@ -350,6 +353,7 @@ module RPC = struct proto_level ; predecessor = head_hash ; timestamp = Prevalidator.timestamp pv ; + validation_passes = List.length operation_hashes ; operations_hash ; fitness ; } ; @@ -501,6 +505,7 @@ module RPC = struct proto_level ; predecessor = State.Block.hash predecessor ; timestamp ; + validation_passes = 1 ; operations_hash ; fitness ; } in diff --git a/src/node/shell/node_rpc_services.ml b/src/node/shell/node_rpc_services.ml index 76dc1879f..34ca5e7c1 100644 --- a/src/node/shell/node_rpc_services.ml +++ b/src/node/shell/node_rpc_services.ml @@ -77,6 +77,7 @@ module Blocks = struct proto_level: int ; (* uint8 *) predecessor: Block_hash.t ; timestamp: Time.t ; + validation_passes: int ; (* uint8 *) operations_hash: Operation_list_list_hash.t ; fitness: MBytes.t list ; data: MBytes.t ; @@ -88,20 +89,22 @@ module Blocks = struct let block_info_encoding = conv (fun { hash ; net_id ; level ; proto_level ; predecessor ; - fitness ; timestamp ; protocol ; operations_hash ; data ; + fitness ; timestamp ; protocol ; + validation_passes ; operations_hash ; data ; operations ; test_network } -> ((hash, operations, protocol, test_network), { Block_header.shell = { net_id ; level ; proto_level ; predecessor ; - timestamp ; operations_hash ; fitness } ; + timestamp ; validation_passes ; operations_hash ; fitness } ; proto = data })) (fun ((hash, operations, protocol, test_network), { Block_header.shell = { net_id ; level ; proto_level ; predecessor ; - timestamp ; operations_hash ; fitness } ; + timestamp ; validation_passes ; operations_hash ; fitness } ; proto = data }) -> { hash ; net_id ; level ; proto_level ; predecessor ; - fitness ; timestamp ; protocol ; operations_hash ; data ; + fitness ; timestamp ; protocol ; + validation_passes ; operations_hash ; data ; operations ; test_network }) (dynamic_size (merge_objs diff --git a/src/node/shell/node_rpc_services.mli b/src/node/shell/node_rpc_services.mli index 47a0c6990..fef5d7d1e 100644 --- a/src/node/shell/node_rpc_services.mli +++ b/src/node/shell/node_rpc_services.mli @@ -39,6 +39,7 @@ module Blocks : sig proto_level: int ; (* uint8 *) predecessor: Block_hash.t ; timestamp: Time.t ; + validation_passes: int ; (* uint8 *) operations_hash: Operation_list_list_hash.t ; fitness: MBytes.t list ; data: MBytes.t ; diff --git a/src/node/shell/state.ml b/src/node/shell/state.ml index 17e101059..7142cdd02 100644 --- a/src/node/shell/state.ml +++ b/src/node/shell/state.ml @@ -114,13 +114,13 @@ module Locked_block = struct predecessor = genesis.block ; timestamp = genesis.time ; fitness = [] ; + validation_passes = 0 ; operations_hash = Operation_list_list_hash.empty ; } in let header : Block_header.t = { shell ; proto = MBytes.create 0 } in Store.Block.Contents.store (store, genesis.block) { Store.Block.header ; message = "Genesis" ; - operation_list_count = 0 ; max_operations_ttl = 0 ; - context = commit } >>= fun () -> + max_operations_ttl = 0 ; context = commit } >>= fun () -> Lwt.return header end @@ -311,9 +311,8 @@ module Block = struct let fitness b = (shell_header b).fitness let level b = (shell_header b).level let proto_level b = (shell_header b).proto_level + let validation_passes b = (shell_header b).validation_passes let message { contents = { message } } = message - let operation_list_count { contents = { operation_list_count } } = - operation_list_count let max_operations_ttl { contents = { max_operations_ttl } } = max_operations_ttl @@ -395,7 +394,6 @@ module Block = struct let contents = { Store.Block.header = block_header ; message ; - operation_list_count = List.length operations ; max_operations_ttl ; context = commit ; } in @@ -444,7 +442,7 @@ module Block = struct Watcher.create_stream net_state.block_watcher let operation_hashes { net_state ; hash ; contents } i = - if i < 0 || contents.operation_list_count <= i then + if i < 0 || contents.header.shell.validation_passes <= i then invalid_arg "State.Block.operations" ; Shared.use net_state.block_store begin fun store -> Store.Block.Operation_hashes.read_exn (store, hash) i >>= fun hashes -> @@ -456,11 +454,11 @@ module Block = struct Shared.use net_state.block_store begin fun store -> Lwt_list.map_p (Store.Block.Operation_hashes.read_exn (store, hash)) - (0 -- (contents.operation_list_count - 1)) + (0 -- (contents.header.shell.validation_passes - 1)) end let operations { net_state ; hash ; contents } i = - if i < 0 || contents.operation_list_count <= i then + if i < 0 || contents.header.shell.validation_passes <= i then invalid_arg "State.Block.operations" ; Shared.use net_state.block_store begin fun store -> Store.Block.Operation_path.read_exn (store, hash) i >>= fun path -> @@ -472,7 +470,7 @@ module Block = struct Shared.use net_state.block_store begin fun store -> Lwt_list.map_p (fun i -> Store.Block.Operations.read_exn (store, hash) i) - (0 -- (contents.operation_list_count - 1)) + (0 -- (contents.header.shell.validation_passes - 1)) end let context { net_state ; hash } = diff --git a/src/node/shell/state.mli b/src/node/shell/state.mli index 3eae5f89e..e5b113bd4 100644 --- a/src/node/shell/state.mli +++ b/src/node/shell/state.mli @@ -118,7 +118,7 @@ module Block : sig val shell_header: t -> Block_header.shell_header val timestamp: t -> Time.t val fitness: t -> Fitness.t - val operation_list_count: t -> int + val validation_passes: t -> int val net_id: t -> Net_id.t val net_state: t -> Net.t val level: t -> Int32.t diff --git a/src/node/shell/validator.ml b/src/node/shell/validator.ml index 985947085..187cf7c30 100644 --- a/src/node/shell/validator.ml +++ b/src/node/shell/validator.ml @@ -254,6 +254,9 @@ let apply_block net_state db Block_hash.pp_short hash >>= fun () -> Distributed_db.Operations.fetch db (hash, 0) block.shell.operations_hash >>= fun operations -> + fail_unless (block.shell.validation_passes <= 1) + (* TODO constant to be exported from the protocol... *) + (failure "unexpected error (TO BE REMOVED)") >>=? fun () -> let operation_hashes = List.map Operation.hash operations in lwt_debug "validation of %a: found operations" Block_hash.pp_short hash >>= fun () -> @@ -447,7 +450,7 @@ module Context_db = struct begin match data with | Ok data -> begin - Distributed_db.commit_block net_db hash 1 data >>=? function + Distributed_db.commit_block net_db hash data >>=? function | None -> (* Should not happen if the block is not validated twice *) assert false @@ -455,7 +458,7 @@ module Context_db = struct return (Ok block) end | Error err -> - Distributed_db.commit_invalid_block net_db hash 1 >>=? fun changed -> + Distributed_db.commit_invalid_block net_db hash >>=? fun changed -> assert changed ; return (Error err) end >>= function diff --git a/src/proto/alpha/block_header_repr.ml b/src/proto/alpha/block_header_repr.ml index 1d4d86784..c037ed104 100644 --- a/src/proto/alpha/block_header_repr.ml +++ b/src/proto/alpha/block_header_repr.ml @@ -82,14 +82,14 @@ type error += let parse ({ shell = { net_id ; level ; proto_level ; predecessor ; - timestamp ; fitness ; operations_hash } ; + timestamp ; fitness ; validation_passes ; operations_hash } ; proto } : Block_header.t) : block_header tzresult = match Data_encoding.Binary.of_bytes signed_proto_header_encoding proto with | None -> Error [Cant_parse_proto_header] | Some (proto, signature) -> let shell = { Block_header.net_id ; level ; proto_level ; predecessor ; - timestamp ; fitness ; operations_hash } in + timestamp ; fitness ; validation_passes ; operations_hash } in Ok { shell ; proto ; signature } let parse_unsigned_proto_header bytes = diff --git a/src/proto/genesis/services.ml b/src/proto/genesis/services.ml index 79f685820..22f571d0d 100644 --- a/src/proto/genesis/services.ml +++ b/src/proto/genesis/services.ml @@ -67,7 +67,7 @@ let rpc_services : Updater.rpc_context RPC.directory = (fun _ctxt ((net_id, level, proto_level, predecessor, timestamp, fitness), command) -> let shell = { Block_header.net_id ; level ; proto_level ; predecessor ; - timestamp ; fitness ; operations_hash } in + timestamp ; fitness ; validation_passes = 1 ; operations_hash } in let bytes = Data.Command.forge shell command in RPC.Answer.return bytes) in dir diff --git a/src/utils/tezos_data.ml b/src/utils/tezos_data.ml index b59dc3703..60310a1b4 100644 --- a/src/utils/tezos_data.ml +++ b/src/utils/tezos_data.ml @@ -172,6 +172,7 @@ module Block_header = struct proto_level: int ; (* uint8 *) predecessor: Block_hash.t ; timestamp: Time.t ; + validation_passes: int ; (* uint8 *) operations_hash: Operation_list_list_hash.t ; fitness: MBytes.t list ; } @@ -180,19 +181,20 @@ module Block_header = struct let open Data_encoding in conv (fun { net_id ; level ; proto_level ; predecessor ; - timestamp ; operations_hash ; fitness } -> + timestamp ; validation_passes ; operations_hash ; fitness } -> (net_id, level, proto_level, predecessor, - timestamp, operations_hash, fitness)) + timestamp, validation_passes, operations_hash, fitness)) (fun (net_id, level, proto_level, predecessor, - timestamp, operations_hash, fitness) -> + timestamp, validation_passes, operations_hash, fitness) -> { net_id ; level ; proto_level ; predecessor ; - timestamp ; operations_hash ; fitness }) - (obj7 + timestamp ; validation_passes ; operations_hash ; fitness }) + (obj8 (req "net_id" Net_id.encoding) (req "level" int32) (req "proto" uint8) (req "predecessor" Block_hash.encoding) (req "timestamp" Time.encoding) + (req "validation_pass" uint8) (req "operations_hash" Operation_list_list_hash.encoding) (req "fitness" Fitness.encoding)) diff --git a/src/utils/tezos_data.mli b/src/utils/tezos_data.mli index 3a5802f58..75e58934c 100644 --- a/src/utils/tezos_data.mli +++ b/src/utils/tezos_data.mli @@ -72,6 +72,7 @@ module Block_header : sig proto_level: int ; (* uint8 *) predecessor: Block_hash.t ; timestamp: Time.t ; + validation_passes: int ; (* uint8 *) operations_hash: Operation_list_list_hash.t ; fitness: MBytes.t list ; } diff --git a/test/shell/test_state.ml b/test/shell/test_state.ml index 355993950..9e0219723 100644 --- a/test/shell/test_state.ml +++ b/test/shell/test_state.ml @@ -72,6 +72,7 @@ let block _state ?(operations = []) pred_hash pred name : Block_header.t = level = Int32.succ pred.shell.level ; proto_level = pred.shell.proto_level ; predecessor = pred_hash ; + validation_passes = 1 ; timestamp ; operations_hash ; fitness } ; proto = MBytes.of_string name ; } @@ -114,6 +115,7 @@ let block _state ?(operations = []) (pred: State.Block.t) name level = Int32.succ pred_header.level ; proto_level = pred_header.proto_level ; predecessor = State.Block.hash pred ; + validation_passes = 1 ; timestamp ; operations_hash ; fitness } ; proto = MBytes.of_string name ; } diff --git a/test/shell/test_store.ml b/test/shell/test_store.ml index ee3e987b7..6e6821417 100644 --- a/test/shell/test_store.ml +++ b/test/shell/test_store.ml @@ -83,12 +83,12 @@ let lolblock ?(operations = []) header = level = 0l ; (* dummy *) proto_level = 0 ; (* dummy *) net_id ; + validation_passes = Random.int 32 ; predecessor = genesis_block ; operations_hash ; fitness = [MBytes.of_string @@ string_of_int @@ String.length header; MBytes.of_string @@ string_of_int @@ 12] } ; proto = MBytes.of_string header ; } ; - operation_list_count = Random.int 32 ; max_operations_ttl = 0 ; message = "" ; context = Context.dummy_commit ; @@ -108,8 +108,7 @@ let bh3' = let equal (b1: Store.Block.contents) (b2: Store.Block.contents) = Block_header.equal b1.header b2.header && - b1.message = b2.message && - b1.operation_list_count = b2.operation_list_count + b1.message = b2.message let check_block s h b = Store.Block.Contents.read (s, h) >>= function