From 3cb91cb89c5bf28a9139c20061b6bd513da34a3c Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Mon, 13 Jun 2022 10:52:53 +0200 Subject: [PATCH] Scoru,Proto: limit the size of a wrapped proof --- .../lib_protocol/constants_repr.ml | 88 +++++++++++------- .../lib_protocol/constants_repr.mli | 3 + src/proto_alpha/lib_protocol/sc_rollups.ml | 91 ++++++++++--------- ...e client) RPC regression tests- others.out | 3 +- ...de light) RPC regression tests- others.out | 3 +- ...de proxy) RPC regression tests- others.out | 3 +- ...data_dir) RPC regression tests- others.out | 3 +- ...rver_rpc) RPC regression tests- others.out | 3 +- ...ommitments in the rollup node (no_comm.out | 6 +- 9 files changed, 121 insertions(+), 82 deletions(-) diff --git a/src/proto_alpha/lib_protocol/constants_repr.ml b/src/proto_alpha/lib_protocol/constants_repr.ml index f1c7ab23f378..8c72bf528424 100644 --- a/src/proto_alpha/lib_protocol/constants_repr.ml +++ b/src/proto_alpha/lib_protocol/constants_repr.ml @@ -59,43 +59,69 @@ let michelson_maximum_type_size = 2001 mechanism (see {Context.Cache}). *) let cache_layout_size = 3 +(* The {!Sc_rollups.wrapped_proof_encoding} uses unbounded sub-encodings. + To avoid attacks through too large proofs and long decoding times on public + nodes, we put another layer of security by restricting the maximum_size + to [30Kb]. + + Even if the operation size limit is currently [32Kb] (see + {!Constants_repr.max_operation_data_length}) the node's mempool can still + be spammed with larger proofs before detecting that the operations are + indeed larger than the limit. + + By design, the proofs should be created and verified for a single tick + which should limit the number of read/writes in the Merkle tree, and thefore, + limit the total size of a proof. Thus, [30Kb] can be lowered once we + have empirically observed that a valid proof can not be that large. + + Note that an encoded proof that is [30Kb] might still be not included + in a valid L1 operation. The refutation operation also contains other + information such as an inbox proof. We only put here an upper bound + for the size. +*) +let sc_max_wrapped_proof_binary_size = 30_000 + type fixed = unit let fixed_encoding = let open Data_encoding in conv (fun () -> - ( proof_of_work_nonce_size, - nonce_length, - max_anon_ops_per_block, - max_operation_data_length, - max_proposals_per_delegate, - max_micheline_node_count, - max_micheline_bytes_limit, - max_allowed_global_constant_depth, - cache_layout_size, - michelson_maximum_type_size )) - (fun ( _proof_of_work_nonce_size, - _nonce_length, - _max_anon_ops_per_block, - _max_operation_data_length, - _max_proposals_per_delegate, - _max_micheline_node_count, - _max_micheline_bytes_limit, - _max_allowed_global_constant_depth, - _cache_layout_size, - _michelson_maximum_type_size ) -> ()) - (obj10 - (req "proof_of_work_nonce_size" uint8) - (req "nonce_length" uint8) - (req "max_anon_ops_per_block" uint8) - (req "max_operation_data_length" int31) - (req "max_proposals_per_delegate" uint8) - (req "max_micheline_node_count" int31) - (req "max_micheline_bytes_limit" int31) - (req "max_allowed_global_constants_depth" int31) - (req "cache_layout_size" uint8) - (req "michelson_maximum_type_size" uint16)) + ( ( proof_of_work_nonce_size, + nonce_length, + max_anon_ops_per_block, + max_operation_data_length, + max_proposals_per_delegate, + max_micheline_node_count, + max_micheline_bytes_limit, + max_allowed_global_constant_depth, + cache_layout_size, + michelson_maximum_type_size ), + sc_max_wrapped_proof_binary_size )) + (fun ( ( _proof_of_work_nonce_size, + _nonce_length, + _max_anon_ops_per_block, + _max_operation_data_length, + _max_proposals_per_delegate, + _max_micheline_node_count, + _max_micheline_bytes_limit, + _max_allowed_global_constant_depth, + _cache_layout_size, + _michelson_maximum_type_size ), + _max_wrapped_proof_binary_size ) -> ()) + (merge_objs + (obj10 + (req "proof_of_work_nonce_size" uint8) + (req "nonce_length" uint8) + (req "max_anon_ops_per_block" uint8) + (req "max_operation_data_length" int31) + (req "max_proposals_per_delegate" uint8) + (req "max_micheline_node_count" int31) + (req "max_micheline_bytes_limit" int31) + (req "max_allowed_global_constants_depth" int31) + (req "cache_layout_size" uint8) + (req "michelson_maximum_type_size" uint16)) + (obj1 (req "max_wrapped_proof_binary_size" int31))) let fixed = () diff --git a/src/proto_alpha/lib_protocol/constants_repr.mli b/src/proto_alpha/lib_protocol/constants_repr.mli index 60c4bf1139d3..161185837c9b 100644 --- a/src/proto_alpha/lib_protocol/constants_repr.mli +++ b/src/proto_alpha/lib_protocol/constants_repr.mli @@ -72,6 +72,9 @@ val max_allowed_global_constant_depth : int *) val michelson_maximum_type_size : int +(** A size limit for {!Sc_rollups.wrapped_proof} binary encoding. *) +val sc_max_wrapped_proof_binary_size : int + type fixed val fixed_encoding : fixed Data_encoding.encoding diff --git a/src/proto_alpha/lib_protocol/sc_rollups.ml b/src/proto_alpha/lib_protocol/sc_rollups.ml index b43c26a5be00..f8dc13c41824 100644 --- a/src/proto_alpha/lib_protocol/sc_rollups.ml +++ b/src/proto_alpha/lib_protocol/sc_rollups.ml @@ -150,50 +150,53 @@ let wrapped_proof_module p = let wrapped_proof_encoding = let open Data_encoding in - union - ~tag_size:`Uint8 - [ - case - ~title:"Arithmetic PVM with proof" - (Tag 0) - Sc_rollup_arith.ProtocolImplementation.proof_encoding - (function - | Arith_pvm_with_proof pvm -> - let (module P : PVM_with_proof - with type proof = - Sc_rollup_arith.ProtocolImplementation.proof) = - pvm - in - Some P.proof - | _ -> None) - (fun proof -> - let module P = struct - include Sc_rollup_arith.ProtocolImplementation - - let proof = proof - end in - Arith_pvm_with_proof (module P)); - case - ~title:"Wasm 2.0.0 PVM with proof" - (Tag 1) - Sc_rollup_wasm.V2_0_0.ProtocolImplementation.proof_encoding - (function - | Wasm_2_0_0_pvm_with_proof pvm -> - let (module P : PVM_with_proof - with type proof = - Sc_rollup_wasm.V2_0_0.ProtocolImplementation.proof) = - pvm - in - Some P.proof - | _ -> None) - (fun proof -> - let module P = struct - include Sc_rollup_wasm.V2_0_0.ProtocolImplementation - - let proof = proof - end in - Wasm_2_0_0_pvm_with_proof (module P)); - ] + let encoding = + union + ~tag_size:`Uint8 + [ + case + ~title:"Arithmetic PVM with proof" + (Tag 0) + Sc_rollup_arith.ProtocolImplementation.proof_encoding + (function + | Arith_pvm_with_proof pvm -> + let (module P : PVM_with_proof + with type proof = + Sc_rollup_arith.ProtocolImplementation.proof) = + pvm + in + Some P.proof + | _ -> None) + (fun proof -> + let module P = struct + include Sc_rollup_arith.ProtocolImplementation + + let proof = proof + end in + Arith_pvm_with_proof (module P)); + case + ~title:"Wasm 2.0.0 PVM with proof" + (Tag 1) + Sc_rollup_wasm.V2_0_0.ProtocolImplementation.proof_encoding + (function + | Wasm_2_0_0_pvm_with_proof pvm -> + let (module P : PVM_with_proof + with type proof = + Sc_rollup_wasm.V2_0_0.ProtocolImplementation.proof) = + pvm + in + Some P.proof + | _ -> None) + (fun proof -> + let module P = struct + include Sc_rollup_wasm.V2_0_0.ProtocolImplementation + + let proof = proof + end in + Wasm_2_0_0_pvm_with_proof (module P)); + ] + in + check_size Constants_repr.sc_max_wrapped_proof_binary_size encoding let wrap_proof pvm_with_proof = let (module P : PVM_with_proof) = pvm_with_proof in diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- others.out index 08af28a81f4b..2dcff7529047 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode client) RPC regression tests- others.out @@ -5,7 +5,8 @@ "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, "max_micheline_bytes_limit": 50000, "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, - "michelson_maximum_type_size": 2001, "preserved_cycles": 2, + "michelson_maximum_type_size": 2001, + "max_wrapped_proof_binary_size": 30000, "preserved_cycles": 2, "blocks_per_cycle": 8, "blocks_per_commitment": 4, "blocks_per_stake_snapshot": 4, "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- others.out index 5921e5de50ed..56f90a3571b6 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode light) RPC regression tests- others.out @@ -5,7 +5,8 @@ "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, "max_micheline_bytes_limit": 50000, "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, - "michelson_maximum_type_size": 2001, "preserved_cycles": 2, + "michelson_maximum_type_size": 2001, + "max_wrapped_proof_binary_size": 30000, "preserved_cycles": 2, "blocks_per_cycle": 8, "blocks_per_commitment": 4, "blocks_per_stake_snapshot": 4, "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- others.out index b10b690d4c7e..4be9e6a5203f 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy) RPC regression tests- others.out @@ -5,7 +5,8 @@ "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, "max_micheline_bytes_limit": 50000, "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, - "michelson_maximum_type_size": 2001, "preserved_cycles": 2, + "michelson_maximum_type_size": 2001, + "max_wrapped_proof_binary_size": 30000, "preserved_cycles": 2, "blocks_per_cycle": 8, "blocks_per_commitment": 4, "blocks_per_stake_snapshot": 4, "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- others.out index 9cec6efb7351..e977b651c850 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_data_dir) RPC regression tests- others.out @@ -5,7 +5,8 @@ "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, "max_micheline_bytes_limit": 50000, "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, - "michelson_maximum_type_size": 2001, "preserved_cycles": 2, + "michelson_maximum_type_size": 2001, + "max_wrapped_proof_binary_size": 30000, "preserved_cycles": 2, "blocks_per_cycle": 8, "blocks_per_commitment": 4, "blocks_per_stake_snapshot": 4, "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", diff --git a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- others.out b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- others.out index 9cec6efb7351..e977b651c850 100644 --- a/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- others.out +++ b/tezt/tests/expected/RPC_test.ml/Alpha- (mode proxy_server_rpc) RPC regression tests- others.out @@ -5,7 +5,8 @@ "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, "max_micheline_bytes_limit": 50000, "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, - "michelson_maximum_type_size": 2001, "preserved_cycles": 2, + "michelson_maximum_type_size": 2001, + "max_wrapped_proof_binary_size": 30000, "preserved_cycles": 2, "blocks_per_cycle": 8, "blocks_per_commitment": 4, "blocks_per_stake_snapshot": 4, "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", diff --git a/tezt/tests/expected/sc_rollup.ml/Alpha- observing the correct handling of commitments in the rollup node (no_comm.out b/tezt/tests/expected/sc_rollup.ml/Alpha- observing the correct handling of commitments in the rollup node (no_comm.out index b96f66dbc781..726b690845e6 100644 --- a/tezt/tests/expected/sc_rollup.ml/Alpha- observing the correct handling of commitments in the rollup node (no_comm.out +++ b/tezt/tests/expected/sc_rollup.ml/Alpha- observing the correct handling of commitments in the rollup node (no_comm.out @@ -57,7 +57,8 @@ This sequence of operations was run: "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, "max_micheline_bytes_limit": 50000, "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, - "michelson_maximum_type_size": 2001, "preserved_cycles": 2, + "michelson_maximum_type_size": 2001, + "max_wrapped_proof_binary_size": 30000, "preserved_cycles": 2, "blocks_per_cycle": 8, "blocks_per_commitment": 4, "blocks_per_stake_snapshot": 4, "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", @@ -156,7 +157,8 @@ This sequence of operations was run: "max_proposals_per_delegate": 20, "max_micheline_node_count": 50000, "max_micheline_bytes_limit": 50000, "max_allowed_global_constants_depth": 10000, "cache_layout_size": 3, - "michelson_maximum_type_size": 2001, "preserved_cycles": 2, + "michelson_maximum_type_size": 2001, + "max_wrapped_proof_binary_size": 30000, "preserved_cycles": 2, "blocks_per_cycle": 8, "blocks_per_commitment": 4, "blocks_per_stake_snapshot": 4, "cycles_per_voting_period": 8, "hard_gas_limit_per_operation": "1040000", -- GitLab