diff --git a/CHANGES.rst b/CHANGES.rst index 491bc10b529f725980f2180fa9b7cd8c5968d68a..f8e0d307e4ef04f7a7f7eea2514347b8cc9fdafe 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -117,6 +117,17 @@ Node are not retro-compatible with previous octez versions (MR :gl:`!14398`). +- Environment variable ``TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING`` can be + set to ``yes`` or ``y`` to use yes-crypto in testing. With yes-cryptography + activated, signatures are faked and always considered valid. This should be + used for testing purposes only and/or with extreme care. This can put your + software at risk of being considered faulty/malicious if it fake signs + and exploited by attackers if it fake-checks signatures. + +- To avoid misusage of ``TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING`` + environment variable, if it is set to 'yes' or 'y', nodes must explicitly be + launched with the ``--allow-yes-crypto`` argument to run. + Client ------ diff --git a/docs/developer/proposal_testing.rst b/docs/developer/proposal_testing.rst index 32c0385d16b8b0693d95000d0a69b794587fe71b..a753d272267e288227ac067653118a4a23da09a6 100644 --- a/docs/developer/proposal_testing.rst +++ b/docs/developer/proposal_testing.rst @@ -147,11 +147,9 @@ Preparing the migration comprises the following steps: snapshot the Alpha protocol, 3. set ``user-activated upgrade`` that will trigger the migration at a given level, -4. patch the shell to obtain a ``yes-node`` that can fake baker signatures, if we - wish to import the context from Mainnet, -5. compile the project, -6. import a context from Mainnet, if so wished, and -7. create a ``yes-wallet`` that stores fake baker signatures, if we wish to import +4. compile the project, +5. import a context from Mainnet, if so wished, and +6. create a ``yes-wallet`` that stores fake baker signatures, if we wish to import the context from Mainnet. @@ -187,7 +185,7 @@ In our example we will use a snapshot file ``~/snapshot-mainnet.rolling`` which was taken at level ``1617344``. -The next subsections explain each of the individual steps 1--7. +The next subsections explain each of the individual steps 1--6. 1. Snapshot the Alpha Protocol @@ -309,30 +307,13 @@ As before, if we had opted for not snapshotting the Alpha protocol, we could pas the path ``src/proto_alpha`` as the parameter of the command above. If we are testing the migration on an empty context on the sandbox, then we -should proceed directly to Section `5. Compile the project`_. Otherwise, the next +should proceed directly to Section `4. Compile the project`_. Otherwise, the next two subsections detail how to produce credentials that will allow us to make the chain that we imported from Mainnet progress. -4. Patch the Shell to Obtain a Yes-Node -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If we would start a node imported from Mainnet, how could we bake new blocks and -make the chain progress? We do not know the private keys of existing bakers in -Mainnet! - -In order to produce credentials to make the chain imported from Mainnet -progress, we modify the code to produce a yes-node that forges and verifies -fake signatures. This can be achieved with a small patch to -``src/lib_crypto/signature.ml`` that replaces each signature with a -concatenation of a public key and a message, such that this fake signature is -still unique for each key and message. This patch is encoded as the git diff -contained in the file ``scripts/yes-node.patch``. We can apply this patch by -invoking:: - - $ ./scripts/patch-yes_node.sh - -5. Compile the Project +4. Compile the Project ~~~~~~~~~~~~~~~~~~~~~~ At this point we have to compile the Alpha protocol (or the snapshot Alpha @@ -343,7 +324,7 @@ project under the ``src`` folder by invoking:: $ make -6. Import a Context From Mainnet +5. Import a Context From Mainnet ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If we wish to test the migration in a realistic scenario, we need to import a @@ -379,7 +360,7 @@ Importing the context from a snapshot file is optional and should be performed only if we want to test the migration on a realistic context from Mainnet. Otherwise the migration will run on the sandbox. -7. Create a Yes-Wallet +6. Create a Yes-Wallet ~~~~~~~~~~~~~~~~~~~~~~ We also need to create a yes-wallet, which is a special wallet where secret @@ -416,7 +397,7 @@ therefore some commands like ``octez-client bake for`` will execute faster) and its keys will represent more than the 2/3rds of the attesting power for any given level. -Batch Steps 1--7 Above +Batch Steps 1--6 Above ~~~~~~~~~~~~~~~~~~~~~~ The script ``scripts/prepare_migration_test.sh`` batches steps 1--7 above. @@ -543,12 +524,21 @@ environment variable ``test_directory`` to the path of the test folder, such that we can run the node in the test folder later. Then it copies the contents of the original context folder into the test folder. + + +In order to produce credentials to make the chain imported from Mainnet +progress, we need our node to forge and verify fake signatures. This can be +achieved with the use of the ``TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING`` +evironment variable that replaces each signature with a concatenation of a +public key and a message, such that this fake signature is still unique for each +key and message. + Now, we can run the ``octez-node`` command by specifying the test folder ``$test_directory`` as the data directory. We will also specify the RPC address ``localhost``, such that the RPCs will be available at the url ``localhost:8732``. In our example, by invoking the following:: - $ ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost & + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost & We will now trigger the migration by baking blocks until the level reaches the one specified when setting the user-activated upgrades. The blocks can be baked @@ -556,14 +546,14 @@ with the yes-wallet created in step 5 above, and with any of the accounts ``foundation1`` to ``foundation8``. In our example, we can bake one block by running the following command:: - $ ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp .. note:: Prior to Tenderbake activation (i.e. to the Protocol I) this command requires a specific account to bake for. Any of ``foundation[1-8]`` accounts can be used to do it. - ``$ octez-client bake for foundation1 --minimal-timestamp`` + ``$ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y octez-client bake for foundation1 --minimal-timestamp`` If the chosen account ``foundation1`` ceases to have the priority to bake, we can switch to any of the remaining accounts ``foundation2`` to @@ -588,12 +578,12 @@ copy the context of the original folder into the test folder. In our example:: Now we run the node in the test folder by invoking:: - $ ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost & + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost & And finally, we bake the numbers of blocks specified by the user-activated upgrade, with the command:: - $ ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp Wrap up the Migration Procedure @@ -702,7 +692,6 @@ invoking the following eight commands):: $ ./scripts/snapshot_alpha.sh d_012 $ ./scripts/link_protocol.sh src/proto_012_* $ ./scripts/user_activated_upgrade.sh src/proto_012_* 1617344 - $ ./scripts/patch-yes_node.sh $ make $ ./octez-node snapshot import ~/mainnet.rolling --data-dir /tmp/octez-node-mainnet $ ./octez-node identity generate --data-dir /tmp/octez-node-mainnet @@ -714,13 +703,13 @@ Copy original folder into test folder:: Run the node`:: - $ ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost & + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost & Bake three blocks:: - $ ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp - $ ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp - $ ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp .. note:: Prior to Tenderbake activation (i.e. to the Protocol I) this command requires @@ -732,7 +721,7 @@ You should see the ``STITCHING!`` message! To test again, kill the node:: $ fg - ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost + TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost ^C Clean up by removing test folder and copying original folder into fresh @@ -744,13 +733,13 @@ test folder, and by removing files ``/tmp/yes-wallet/wallet_lock`` and Run the node:: - ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost & + TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-node run --synchronisation-threshold 0 --connections 0 --data-dir "$test_directory" --rpc-addr localhost & And bake three blocks:: - $ ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp - $ ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp - $ ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp + $ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d /tmp/yes-wallet bake for --minimal-timestamp You should see the ``STITCHING!`` message again! diff --git a/manifest/product_octez.ml b/manifest/product_octez.ml index 1e00d2b8fb9c8f12b807e26c2b113a40b3c6b940..11255f617b6078ea08a7de1c31e4f49242153750 100644 --- a/manifest/product_octez.ml +++ b/manifest/product_octez.ml @@ -712,6 +712,41 @@ let _octez_bls12_381_signature_tests = ~dep_globs_rec:["test_vectors/*"] (* See above *) +let octez_event_logging = + octez_lib + "event-logging" + ~internal_name:"tezos_event_logging" + ~path:"src/lib_event_logging" + ~synopsis:"Octez event logging library" + ~deps: + [ + octez_stdlib |> open_; + data_encoding |> open_; + octez_error_monad |> open_ |> open_ ~m:"TzLwtreslib"; + octez_lwt_result_stdlib; + uri; + ] + +let octez_event_logging_test_helpers = + octez_lib + "event-logging-test-helpers" + ~internal_name:"tezos_event_logging_test_helpers" + ~path:"src/lib_event_logging/test_helpers" + ~synopsis:"Test helpers for the event logging library" + ~deps: + [ + octez_stdlib; + octez_lwt_result_stdlib |> open_; + data_encoding; + octez_error_monad |> open_ |> open_ ~m:"TzLwtreslib"; + octez_event_logging |> open_; + octez_test_helpers |> open_; + tezt_core_lib |> open_; + alcotezt; + ] + ~linkall:true + ~bisect_ppx:No + let octez_crypto = octez_lib "crypto" @@ -732,6 +767,7 @@ let octez_crypto = zarith; bls12_381; octez_bls12_381_signature; + octez_event_logging; ] let _octez_crypto_tests = @@ -1366,41 +1402,6 @@ let _octez_epoxy_tx_tests = ~deps:[octez_epoxy_tx; octez_plonk_test_helpers; octez_aplonk] ~dune:(make_plonk_runtest_invocation ~package:"octez-libs") -let octez_event_logging = - octez_lib - "event-logging" - ~internal_name:"tezos_event_logging" - ~path:"src/lib_event_logging" - ~synopsis:"Octez event logging library" - ~deps: - [ - octez_stdlib |> open_; - data_encoding |> open_; - octez_error_monad |> open_ |> open_ ~m:"TzLwtreslib"; - octez_lwt_result_stdlib; - uri; - ] - -let octez_event_logging_test_helpers = - octez_lib - "event-logging-test-helpers" - ~internal_name:"tezos_event_logging_test_helpers" - ~path:"src/lib_event_logging/test_helpers" - ~synopsis:"Test helpers for the event logging library" - ~deps: - [ - octez_stdlib; - octez_lwt_result_stdlib |> open_; - data_encoding; - octez_error_monad |> open_ |> open_ ~m:"TzLwtreslib"; - octez_event_logging |> open_; - octez_test_helpers |> open_; - tezt_core_lib |> open_; - alcotezt; - ] - ~linkall:true - ~bisect_ppx:No - let octez_stdlib_unix = octez_lib "stdlib-unix" diff --git a/opam/octez-libs.opam b/opam/octez-libs.opam index 1aa1c0457af17d0e311fbcdfdc6e30c6b97bfaf2..bc9110ea538934b7d1fde3e5ada9431e4d347e5a 100644 --- a/opam/octez-libs.opam +++ b/opam/octez-libs.opam @@ -43,6 +43,7 @@ depends: [ "hacl-star" { >= "0.7.1" & < "0.8" } "hacl-star-raw" "bls12-381" { = version } + "octez-alcotezt" { = version } "secp256k1-internal" { >= "0.4.0" } "bigarray-compat" "eqaf" @@ -52,7 +53,6 @@ depends: [ "repr" "stdint" "octez-distributed-lwt-internal" { = version } - "octez-alcotezt" { = version } "aches-lwt" { >= "1.1.0" } "ipaddr" { >= "5.3.0" & < "6.0.0" } "ptime" { >= "1.1.0" } diff --git a/scripts/ci/lint_misc_check.sh b/scripts/ci/lint_misc_check.sh index 1c0200187a811c62b12339f4b75df1874256a883..711fdb09398e51b4753d8f6d1d68f4570fce0eb4 100755 --- a/scripts/ci/lint_misc_check.sh +++ b/scripts/ci/lint_misc_check.sh @@ -18,6 +18,3 @@ make lint-tests-pkg #- ODOC_WARN_ERROR=true dune build @src/proto_alpha/lib_protocol/doc # check that the hack-module patch applies cleanly git apply devtools/protocol-print/add-hack-module.patch - -# check that the patch-yes_node.sh applies correctly -scripts/patch-yes_node.sh --dry-run diff --git a/scripts/patch-yes_node.sh b/scripts/patch-yes_node.sh deleted file mode 100755 index 9eca2531ad37ad748f92d37ef863339dc3dd5961..0000000000000000000000000000000000000000 --- a/scripts/patch-yes_node.sh +++ /dev/null @@ -1,25 +0,0 @@ -#!/bin/sh - -# Exit on non-zero status -set -e - -# Patch the node sources: -# - the cryptographic library to use fake secret keys, -# - the stresstest command of each protocol that is not frozen to make it work -# on Tezos Mainnet - -for arg in "$@"; do - case $arg in - "--dry-run") - dry_run='--dry-run' - ;; - esac -done - -#shellcheck disable=SC2086 -patch $dry_run -p 1 < scripts/yes-node.patch - -for f in src/proto_*/lib_client_commands/client_proto_stresstest_commands.ml; do - #shellcheck disable=SC2086 - patch $dry_run -p 1 "$f" < scripts/yes-stresstest.patch -done diff --git a/scripts/prepare_migration_test.sh b/scripts/prepare_migration_test.sh index 62c390aa13089e6478f21619327b2dc4dcbb2139..8e841db2a81157f575b778088f53bc70eac782d4 100755 --- a/scripts/prepare_migration_test.sh +++ b/scripts/prepare_migration_test.sh @@ -62,12 +62,6 @@ generate_identities() { ./octez-node identity generate --data-dir "$f_context_dir" } -patch_yes_node() { - echo " -Patching the code to obtain a yes-node." - patch -p1 < ./scripts/yes-node.patch -} - create_yes_wallet() { yes_wallet="$tmp_dir/yes-wallet" if [ -d "$yes_wallet" ]; then @@ -218,8 +212,6 @@ commands above (the script needs not to be run again)." else # \$mig_level > 28082 - patch_yes_node - make if [ -n "$snapshot_path" ] && [ -f "$snapshot_path" ]; then @@ -239,10 +231,10 @@ $ ./octez-node identity generate --data-dir " echo " Use the following commands to start the node with the imported context: $ test_directory=\$(mktemp -d -t \"${context_dir##*/}-XXXX\") && cp -r \"$context_dir/.\" \"\$test_directory\" -$ ./octez-node run --connections 0 --data-dir \"\$test_directory\" --rpc-addr localhost & +$ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-node run --connections 0 --data-dir \"\$test_directory\" --rpc-addr localhost & Then bake blocks until the chain reaches level $mig_level with: -$ ./octez-client -d $yes_wallet bake for --minimal-timestamp +$ TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING=Y ./octez-client -d $yes_wallet bake for --minimal-timestamp In order to re-run the migration test, kill the node and delete spurious fil by using: diff --git a/scripts/yes-node.patch b/scripts/yes-node.patch deleted file mode 100644 index 8b98c1387b1ce49915a18a1b384313eaa8fed712..0000000000000000000000000000000000000000 --- a/scripts/yes-node.patch +++ /dev/null @@ -1,291 +0,0 @@ -diff --git a/src/lib_crypto/signature_v0.ml b/src/lib_crypto/signature_v0.ml -index 1827f52ef6..9f286777b7 100644 ---- a/src/lib_crypto/signature_v0.ml -+++ b/src/lib_crypto/signature_v0.ml -@@ -637,7 +637,7 @@ let pp_watermark ppf = - "Custom: 0x%s" - (try String.sub hexed 0 10 ^ "..." with Invalid_argument _ -> hexed) - --let sign ?watermark secret_key message = -+let _sign ?watermark secret_key message = - let watermark = Option.map bytes_of_watermark watermark in - match secret_key with - | Secret_key.Ed25519 sk -> of_ed25519 (Ed25519.sign ?watermark sk message) -@@ -667,6 +667,67 @@ let check ?watermark public_key signature message = - P256.check ?watermark pk signature message - | _ -> false - -+let fake_sign pk_bytes msg = -+ let msg = Blake2B.to_bytes @@ Blake2B.hash_bytes [msg] in -+ let half = size / 2 in -+ let tmp = Bytes.init size (fun _ -> '0') in -+ let all_or_half buf = Stdlib.min (Bytes.length buf) half in -+ Bytes.blit pk_bytes 0 tmp 0 (all_or_half pk_bytes) ; -+ Bytes.blit msg 0 tmp half (all_or_half msg) ; -+ of_bytes_exn tmp -+ -+type algo = Ed25519 | Secp256k1 | P256 -+ -+let fake_sign_from_pk pk msg = -+ let pk_bytes = Data_encoding.Binary.to_bytes_exn Public_key.encoding pk in -+ fake_sign pk_bytes msg -+ -+let hardcoded_sk algo : secret_key = -+ match -+ match algo with -+ | Ed25519 -> -+ Secret_key.of_b58check -+ "edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh" -+ | Secp256k1 -> -+ Secret_key.of_b58check -+ "spsk2XJu4wuYsHeuDaCktD3ECnnpn574ceSWHEJVvXTt7JP6ztySCL" -+ | P256 -> -+ Secret_key.of_b58check -+ "p2sk2k6YAkNJ8CySZCS3vGA5Ht6Lj6LXG3yb8UrHvMKZy7Ab8JUtWh" -+ with -+ | Ok key -> key -+ | _ -> assert false -+ -+let hardcoded_pk = -+ (* precompute signatures *) -+ let ed, secp, p = -+ ( Secret_key.to_public_key (hardcoded_sk Ed25519), -+ Secret_key.to_public_key (hardcoded_sk Secp256k1), -+ Secret_key.to_public_key (hardcoded_sk P256) ) -+ in -+ function Ed25519 -> ed | Secp256k1 -> secp | P256 -> p -+ -+let hardcoded_msg = Bytes.of_string "Cheers" -+ -+let hardcoded_sig = -+ (* precompute signatures *) -+ let ed, secp, p = -+ ( _sign (hardcoded_sk Ed25519) hardcoded_msg, -+ _sign (hardcoded_sk Secp256k1) hardcoded_msg, -+ _sign (hardcoded_sk P256) hardcoded_msg ) -+ in -+ function Ed25519 -> ed | Secp256k1 -> secp | P256 -> p -+ -+let algo_of_pk (pk : Public_key.t) = -+ match pk with -+ | Ed25519 _ -> Ed25519 -+ | Secp256k1 _ -> Secp256k1 -+ | P256 _ -> P256 -+ -+let check_harcoded_signature pk = -+ let algo = algo_of_pk pk in -+ check (hardcoded_pk algo) (hardcoded_sig algo) hardcoded_msg -+ - (* The following cache is a hack to work around a quadratic algorithm - in Tezos Mainnet protocols up to Edo. *) - -@@ -691,7 +752,7 @@ module Endorsement_cache = - - let endorsement_cache = Endorsement_cache.create 300 - --let check ?watermark public_key signature message = -+let _check ?watermark public_key signature message = - match watermark with - | Some (Endorsement _) -> ( - (* signature check cache only applies to endorsements *) -@@ -709,15 +770,37 @@ let check ?watermark public_key signature message = - res) - | _ -> check ?watermark public_key signature message - -+let fake_check ?watermark:_ pk _signature msg = -+ (* computing the fake signature do hash the message, -+ this operation is linear in the size of the message *) -+ let _ = check_harcoded_signature pk in -+ (* checking a valid, harcoded signature, to do at least once the crypto maths *) -+ ignore (fake_sign_from_pk pk msg) ; -+ true -+ -+let sign ?watermark:_ sk msg = -+ let pk_bytes = Data_encoding.Binary.to_bytes_exn Secret_key.encoding sk in -+ fake_sign pk_bytes msg -+ -+let check = fake_check -+ - let append ?watermark sk msg = Bytes.cat msg (to_bytes (sign ?watermark sk msg)) - - let concat msg signature = Bytes.cat msg (to_bytes signature) - --type algo = Ed25519 | Secp256k1 | P256 -- - let algos = [Ed25519; Secp256k1; P256] - --let generate_key ?(algo = Ed25519) ?seed () = -+let fake_generate_key (pkh, pk, _) = -+ let sk_of_pk (pk : public_key) : secret_key = -+ let pk_b = Data_encoding.Binary.to_bytes_exn Public_key.encoding pk in -+ let sk_b = Bytes.sub pk_b 0 33 in -+ let sk = Data_encoding.Binary.of_bytes_exn Secret_key.encoding sk_b in -+ sk -+ in -+ let fake_sk = sk_of_pk pk in -+ (pkh, pk, fake_sk) -+ -+let original_generate_key ?(algo = Ed25519) ?seed () = - match algo with - | Ed25519 -> - let pkh, pk, sk = Ed25519.generate_key ?seed () in -@@ -731,6 +814,12 @@ let generate_key ?(algo = Ed25519) ?seed () = - let pkh, pk, sk = P256.generate_key ?seed () in - (Public_key_hash.P256 pkh, Public_key.P256 pk, Secret_key.P256 sk) - -+let generate_key ?(algo = Ed25519) ?seed () = -+ (* We keep the original keys generation to stay as close as possible of the -+ initial performences. *) -+ let true_keys = original_generate_key ~algo ?seed () in -+ fake_generate_key true_keys -+ - let deterministic_nonce sk msg = - match sk with - | Secret_key.Ed25519 sk -> Ed25519.deterministic_nonce sk msg -diff --git a/src/lib_crypto/signature_v1.ml b/src/lib_crypto/signature_v1.ml -index 6f17d6c602..e1d89bf25d 100644 ---- a/src/lib_crypto/signature_v1.ml -+++ b/src/lib_crypto/signature_v1.ml -@@ -780,7 +780,7 @@ let pp_watermark ppf = - "Custom: 0x%s" - (try String.sub hexed 0 10 ^ "..." with Invalid_argument _ -> hexed) - --let sign ?watermark secret_key message = -+let _sign ?watermark secret_key message = - let watermark = Option.map bytes_of_watermark watermark in - match secret_key with - | Secret_key.Ed25519 sk -> of_ed25519 (Ed25519.sign ?watermark sk message) -@@ -817,6 +817,70 @@ let check ?watermark public_key signature message = - Bls.check ?watermark pk signature message - | _ -> false - -+let fake_sign pk_bytes msg = -+ let size = Ed25519.size in -+ let msg = Blake2B.to_bytes @@ Blake2B.hash_bytes [msg] in -+ let half = size / 2 in -+ let tmp = Bytes.init size (fun _ -> '0') in -+ let all_or_half buf = Stdlib.min (Bytes.length buf) half in -+ Bytes.blit pk_bytes 0 tmp 0 (all_or_half pk_bytes) ; -+ Bytes.blit msg 0 tmp half (all_or_half msg) ; -+ of_bytes_exn tmp -+ -+type algo = Ed25519 | Secp256k1 | P256 | Bls -+ -+let fake_sign_from_pk pk msg = -+ let pk_bytes = Data_encoding.Binary.to_bytes_exn Public_key.encoding pk in -+ fake_sign pk_bytes msg -+ -+let hardcoded_sk algo : secret_key = -+ match algo with -+ | Ed25519 -> -+ Secret_key.of_b58check_exn -+ "edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh" -+ | Secp256k1 -> -+ Secret_key.of_b58check_exn -+ "spsk2XJu4wuYsHeuDaCktD3ECnnpn574ceSWHEJVvXTt7JP6ztySCL" -+ | P256 -> -+ Secret_key.of_b58check_exn -+ "p2sk2k6YAkNJ8CySZCS3vGA5Ht6Lj6LXG3yb8UrHvMKZy7Ab8JUtWh" -+ | Bls -> -+ Secret_key.of_b58check_exn -+ "BLsk1hfuv6V8JJRaLDBJgPTRGLKusTZnTmWGrvSKYzUaMuzvPLmeGG" -+ -+let hardcoded_pk = -+ (* precompute signatures *) -+ let ed, secp, p, bls = -+ ( Secret_key.to_public_key (hardcoded_sk Ed25519), -+ Secret_key.to_public_key (hardcoded_sk Secp256k1), -+ Secret_key.to_public_key (hardcoded_sk P256), -+ Secret_key.to_public_key (hardcoded_sk Bls) ) -+ in -+ function Ed25519 -> ed | Secp256k1 -> secp | P256 -> p | Bls -> bls -+ -+let hardcoded_msg = Bytes.of_string "Cheers" -+ -+let hardcoded_sig = -+ (* precompute signatures *) -+ let ed, secp, p, bls = -+ ( _sign (hardcoded_sk Ed25519) hardcoded_msg, -+ _sign (hardcoded_sk Secp256k1) hardcoded_msg, -+ _sign (hardcoded_sk P256) hardcoded_msg, -+ _sign (hardcoded_sk Bls) hardcoded_msg ) -+ in -+ function Ed25519 -> ed | Secp256k1 -> secp | P256 -> p | Bls -> bls -+ -+let algo_of_pk (pk : Public_key.t) = -+ match pk with -+ | Ed25519 _ -> Ed25519 -+ | Secp256k1 _ -> Secp256k1 -+ | P256 _ -> P256 -+ | Bls _ -> Bls -+ -+let check_harcoded_signature pk = -+ let algo = algo_of_pk pk in -+ check (hardcoded_pk algo) (hardcoded_sig algo) hardcoded_msg -+ - (* The following cache is a hack to work around a quadratic algorithm - in Tezos Mainnet protocols up to Edo. *) - -@@ -841,7 +905,7 @@ module Endorsement_cache = - - let endorsement_cache = Endorsement_cache.create 300 - --let check ?watermark public_key signature message = -+let _check ?watermark public_key signature message = - match watermark with - | Some (Endorsement _) -> ( - (* signature check cache only applies to endorsements *) -@@ -859,15 +923,37 @@ let check ?watermark public_key signature message = - res) - | _ -> check ?watermark public_key signature message - -+let fake_check ?watermark:_ pk _signature msg = -+ (* computing the fake signature do hash the message, -+ this operation is linear in the size of the message *) -+ let _ = check_harcoded_signature pk in -+ (* checking a valid, harcoded signature, to do at least once the crypto maths *) -+ ignore (fake_sign_from_pk pk msg) ; -+ true -+ -+let sign ?watermark:_ sk msg = -+ let pk_bytes = Data_encoding.Binary.to_bytes_exn Secret_key.encoding sk in -+ fake_sign pk_bytes msg -+ -+let check = fake_check -+ - let append ?watermark sk msg = Bytes.cat msg (to_bytes (sign ?watermark sk msg)) - - let concat msg signature = Bytes.cat msg (to_bytes signature) - --type algo = Ed25519 | Secp256k1 | P256 | Bls -- - let algos = [Ed25519; Secp256k1; P256; Bls] - --let generate_key ?(algo = Ed25519) ?seed () = -+let fake_generate_key (pkh, pk, _) = -+ let sk_of_pk (pk : public_key) : secret_key = -+ let pk_b = Data_encoding.Binary.to_bytes_exn Public_key.encoding pk in -+ let sk_b = Bytes.sub pk_b 0 33 in -+ let sk = Data_encoding.Binary.of_bytes_exn Secret_key.encoding sk_b in -+ sk -+ in -+ let fake_sk = sk_of_pk pk in -+ (pkh, pk, fake_sk) -+ -+let original_generate_key ?(algo = Ed25519) ?seed () = - match algo with - | Ed25519 -> - let pkh, pk, sk = Ed25519.generate_key ?seed () in -@@ -884,6 +970,12 @@ let generate_key ?(algo = Ed25519) ?seed () = - let pkh, pk, sk = Bls.generate_key ?seed () in - (Public_key_hash.Bls pkh, Public_key.Bls pk, Secret_key.Bls sk) - -+let generate_key ?(algo = Ed25519) ?seed () = -+ (* We keep the original keys generation to stay as close as possible of the -+ initial performences. *) -+ let true_keys = original_generate_key ~algo ?seed () in -+ fake_generate_key true_keys -+ - let deterministic_nonce sk msg = - match sk with - | Secret_key.Ed25519 sk -> Ed25519.deterministic_nonce sk msg diff --git a/src/bin_node/node_run_command.ml b/src/bin_node/node_run_command.ml index 059a131a55b64d63871bbf9329a443f728bef747..d77680a748777020a161db48902790706a3a5f5c 100644 --- a/src/bin_node/node_run_command.ml +++ b/src/bin_node/node_run_command.ml @@ -823,7 +823,7 @@ let run ?verbosity ?sandbox ?target ?(cli_warnings = []) Lwt_utils.never_ending () let process sandbox verbosity target singleprocess force_history_mode_switch - args = + allow_yes_crypto args = let open Lwt_result_syntax in let verbosity = let open Internal_event in @@ -840,6 +840,13 @@ let process sandbox verbosity target singleprocess force_history_mode_switch Lwt.return_unit) args in + let* () = + if Tezos_crypto.Helpers.is_yes_crypto_enabled && not allow_yes_crypto then + failwith + "Yes crypto is enabled but the option '--allow-yes-crypto' was not \ + provided." + else return_unit + in let* () = match sandbox with | Some _ when config.data_dir = Config_file.default_data_dir -> @@ -970,11 +977,25 @@ module Term = struct ~doc ["force-history-mode-switch"]) + let allow_yes_crypto = + let open Cmdliner in + let doc = + Format.sprintf + "Allow usage of yes cryptography. This is used conjointly with the \ + `TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING` environment variable. \ + To actually enable yes crypto this option must be used and the \ + environment variable must be set to `true`. If only the environment \ + variable is set, the node will refuse to start." + in + Arg.( + value & flag + & info ~docs:Shared_arg.Manpage.misc_section ~doc ["allow-yes-crypto"]) + let term = Cmdliner.Term.( ret (const process $ sandbox $ verbosity $ target $ singleprocess - $ force_history_mode_switch $ Shared_arg.Term.args)) + $ force_history_mode_switch $ allow_yes_crypto $ Shared_arg.Term.args)) end module Manpage = struct diff --git a/src/lib_crypto/dune b/src/lib_crypto/dune index 6bf380d28712397c64bea2098a259e1a0bf9372e..f6014c63a1bc3cd7eabbdc8c96dd462bdaef6435 100644 --- a/src/lib_crypto/dune +++ b/src/lib_crypto/dune @@ -17,7 +17,8 @@ aches zarith bls12-381 - octez-libs.bls12-381-signature) + octez-libs.bls12-381-signature + octez-libs.event-logging) (flags (:standard) -open Tezos_stdlib diff --git a/src/lib_crypto/helpers.ml b/src/lib_crypto/helpers.ml index 994fc65d3ce685dc4b85e6b56b76b854ea04a5ba..12955b77e0ef639f34edbac84b8163372c4ba052 100644 --- a/src/lib_crypto/helpers.ml +++ b/src/lib_crypto/helpers.ml @@ -307,3 +307,46 @@ struct let encoding = encoding end) end + +(** This variable is used to enable yes-cryptography at runtime. + + With yes-cryptography activated, signatures are faked and always considered + valid. + + This can put your software at risk of being + - considered faulty/malicious if it fake signs, + - exploited by attackers if it fake-checks signatures. + + This should be used for testing purposes only and/or with extreme care.*) +let yes_crypto_environment_variable = + "TEZOS_USE_YES_CRYPTO_I_KNOW_WHAT_I_AM_DOING" + +type yes_crypto_kind = Fast | Yes | No + +let yes_crypto_kind = + match Sys.getenv_opt yes_crypto_environment_variable with + | None -> No + | Some x -> ( + match String.lowercase_ascii x with + | "yes" | "y" -> Yes + | "fast" -> Fast + | _ -> No) + +let is_yes_crypto_enabled = + match yes_crypto_kind with Yes | Fast -> true | No -> false + +module Events = struct + include Tezos_event_logging.Internal_event.Simple + + let yes_crypto_is_enabled = + declare_0 + ~level:Warning + ~section:["crypto"] + ~name:"yes_crypto_is_enabled" + ~msg:"yes-cryptography is enabled" + () +end + +let () = + if is_yes_crypto_enabled then + Events.(emit_at_top_level yes_crypto_is_enabled ()) diff --git a/src/lib_crypto/signature_v0.ml b/src/lib_crypto/signature_v0.ml index 1827f52ef661fe627001feb1549e098256cf99a8..6d2c6fd56d86ca8f65fb80f6dac030fe52f1c1c6 100644 --- a/src/lib_crypto/signature_v0.ml +++ b/src/lib_crypto/signature_v0.ml @@ -667,6 +667,72 @@ let check ?watermark public_key signature message = P256.check ?watermark pk signature message | _ -> false +type algo = Ed25519 | Secp256k1 | P256 + +let fake_sign_from_pk pk msg = + let pk_bytes = Data_encoding.Binary.to_bytes_exn Public_key.encoding pk in + let msg = Blake2B.to_bytes @@ Blake2B.hash_bytes [msg] in + let half = size / 2 in + let tmp = Bytes.init size (fun _ -> '0') in + let all_or_half buf = Stdlib.min (Bytes.length buf) half in + Bytes.blit pk_bytes 0 tmp 0 (all_or_half pk_bytes) ; + Bytes.blit msg 0 tmp half (all_or_half msg) ; + of_bytes_exn tmp + +let fake_sign ?watermark:_ sk msg = + let pk = Secret_key.to_public_key sk in + fake_sign_from_pk pk msg + +let hardcoded_sk algo : secret_key = + match + match algo with + | Ed25519 -> + Secret_key.of_b58check + "edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh" + | Secp256k1 -> + Secret_key.of_b58check + "spsk2XJu4wuYsHeuDaCktD3ECnnpn574ceSWHEJVvXTt7JP6ztySCL" + | P256 -> + Secret_key.of_b58check + "p2sk2k6YAkNJ8CySZCS3vGA5Ht6Lj6LXG3yb8UrHvMKZy7Ab8JUtWh" + with + | Ok key -> key + | _ -> assert false + +let hardcoded_pk = + (* precompute signatures *) + let ed, secp, p = + ( Secret_key.to_public_key (hardcoded_sk Ed25519), + Secret_key.to_public_key (hardcoded_sk Secp256k1), + Secret_key.to_public_key (hardcoded_sk P256) ) + in + function Ed25519 -> ed | Secp256k1 -> secp | P256 -> p + +let hardcoded_msg = Bytes.of_string "Cheers" + +let hardcoded_sig = + (* precompute signatures *) + let ed, secp, p = + ( sign (hardcoded_sk Ed25519) hardcoded_msg, + sign (hardcoded_sk Secp256k1) hardcoded_msg, + sign (hardcoded_sk P256) hardcoded_msg ) + in + function Ed25519 -> ed | Secp256k1 -> secp | P256 -> p + +let algo_of_pk (pk : Public_key.t) = + match pk with + | Ed25519 _ -> Ed25519 + | Secp256k1 _ -> Secp256k1 + | P256 _ -> P256 + +let fast_fake_sign ?watermark:_ sk _msg = + let pk = Secret_key.to_public_key sk in + hardcoded_sig (algo_of_pk pk) + +let check_harcoded_signature pk = + let algo = algo_of_pk pk in + check (hardcoded_pk algo) (hardcoded_sig algo) hardcoded_msg + (* The following cache is a hack to work around a quadratic algorithm in Tezos Mainnet protocols up to Edo. *) @@ -709,14 +775,45 @@ let check ?watermark public_key signature message = res) | _ -> check ?watermark public_key signature message +let fake_check ?watermark:_ pk _signature msg = + (* computing the fake signature do hash the message, + this operation is linear in the size of the message *) + ignore (fake_sign_from_pk pk msg) ; + (* checking a valid, harcoded signature, to do at least once the crypto maths *) + let _ = check_harcoded_signature pk in + true + +(* Fast checking does not simulate computation and directly returns true*) +let fast_fake_check ?watermark:_ _pk _signature _msg = true + +let sign = + match Sys.getenv_opt Helpers.yes_crypto_environment_variable with + | Some "fast" -> fast_fake_sign + | Some _ -> fake_sign + | None -> sign + +let check = + match Sys.getenv_opt Helpers.yes_crypto_environment_variable with + | Some "fast" -> fast_fake_check + | Some _ -> fake_check + | None -> check + let append ?watermark sk msg = Bytes.cat msg (to_bytes (sign ?watermark sk msg)) let concat msg signature = Bytes.cat msg (to_bytes signature) -type algo = Ed25519 | Secp256k1 | P256 - let algos = [Ed25519; Secp256k1; P256] +let fake_generate_key (pkh, pk, _) = + let sk_of_pk (pk : public_key) : secret_key = + let pk_b = Data_encoding.Binary.to_bytes_exn Public_key.encoding pk in + let sk_b = Bytes.sub pk_b 0 33 in + let sk = Data_encoding.Binary.of_bytes_exn Secret_key.encoding sk_b in + sk + in + let fake_sk = sk_of_pk pk in + (pkh, pk, fake_sk) + let generate_key ?(algo = Ed25519) ?seed () = match algo with | Ed25519 -> @@ -731,6 +828,12 @@ let generate_key ?(algo = Ed25519) ?seed () = let pkh, pk, sk = P256.generate_key ?seed () in (Public_key_hash.P256 pkh, Public_key.P256 pk, Secret_key.P256 sk) +let generate_key ?(algo = Ed25519) ?seed () = + let true_keys = generate_key ~algo ?seed () in + match Sys.getenv_opt Helpers.yes_crypto_environment_variable with + | Some _ -> fake_generate_key true_keys + | None -> true_keys + let deterministic_nonce sk msg = match sk with | Secret_key.Ed25519 sk -> Ed25519.deterministic_nonce sk msg diff --git a/src/lib_crypto/signature_v1.ml b/src/lib_crypto/signature_v1.ml index 6f17d6c602023f0081e0767a8fd9fdad6e77aded..a6313b5a6c4c0b1fea6e1f312c87221231d5939f 100644 --- a/src/lib_crypto/signature_v1.ml +++ b/src/lib_crypto/signature_v1.ml @@ -817,6 +817,75 @@ let check ?watermark public_key signature message = Bls.check ?watermark pk signature message | _ -> false +let fake_sign_from_pk pk msg = + let pk_bytes = Data_encoding.Binary.to_bytes_exn Public_key.encoding pk in + let size = Ed25519.size in + let msg = Blake2B.to_bytes @@ Blake2B.hash_bytes [msg] in + let half = size / 2 in + let tmp = Bytes.init size (fun _ -> '0') in + let all_or_half buf = Stdlib.min (Bytes.length buf) half in + Bytes.blit pk_bytes 0 tmp 0 (all_or_half pk_bytes) ; + Bytes.blit msg 0 tmp half (all_or_half msg) ; + of_bytes_exn tmp + +type algo = Ed25519 | Secp256k1 | P256 | Bls + +let fake_sign ?watermark:_ secret_key msg = + let pk = Secret_key.to_public_key secret_key in + fake_sign_from_pk pk msg + +let hardcoded_sk algo : secret_key = + match algo with + | Ed25519 -> + Secret_key.of_b58check_exn + "edsk3gUfUPyBSfrS9CCgmCiQsTCHGkviBDusMxDJstFtojtc1zcpsh" + | Secp256k1 -> + Secret_key.of_b58check_exn + "spsk2XJu4wuYsHeuDaCktD3ECnnpn574ceSWHEJVvXTt7JP6ztySCL" + | P256 -> + Secret_key.of_b58check_exn + "p2sk2k6YAkNJ8CySZCS3vGA5Ht6Lj6LXG3yb8UrHvMKZy7Ab8JUtWh" + | Bls -> + Secret_key.of_b58check_exn + "BLsk1hfuv6V8JJRaLDBJgPTRGLKusTZnTmWGrvSKYzUaMuzvPLmeGG" + +let hardcoded_pk = + (* precompute signatures *) + let ed, secp, p, bls = + ( Secret_key.to_public_key (hardcoded_sk Ed25519), + Secret_key.to_public_key (hardcoded_sk Secp256k1), + Secret_key.to_public_key (hardcoded_sk P256), + Secret_key.to_public_key (hardcoded_sk Bls) ) + in + function Ed25519 -> ed | Secp256k1 -> secp | P256 -> p | Bls -> bls + +let hardcoded_msg = Bytes.of_string "Cheers" + +let hardcoded_sig = + (* precompute signatures *) + let ed, secp, p, bls = + ( sign (hardcoded_sk Ed25519) hardcoded_msg, + sign (hardcoded_sk Secp256k1) hardcoded_msg, + sign (hardcoded_sk P256) hardcoded_msg, + sign (hardcoded_sk Bls) hardcoded_msg ) + in + function Ed25519 -> ed | Secp256k1 -> secp | P256 -> p | Bls -> bls + +let algo_of_pk (pk : Public_key.t) = + match pk with + | Ed25519 _ -> Ed25519 + | Secp256k1 _ -> Secp256k1 + | P256 _ -> P256 + | Bls _ -> Bls + +let fast_fake_sign ?watermark:_ sk _msg = + let pk = Secret_key.to_public_key sk in + hardcoded_sig (algo_of_pk pk) + +let check_harcoded_signature pk = + let algo = algo_of_pk pk in + check (hardcoded_pk algo) (hardcoded_sig algo) hardcoded_msg + (* The following cache is a hack to work around a quadratic algorithm in Tezos Mainnet protocols up to Edo. *) @@ -859,14 +928,45 @@ let check ?watermark public_key signature message = res) | _ -> check ?watermark public_key signature message +let fake_check ?watermark:_ pk _signature msg = + (* computing the fake signature do hash the message, + this operation is linear in the size of the message *) + ignore (fake_sign_from_pk pk msg) ; + (* checking a valid, harcoded signature, to do at least once the crypto maths *) + let _ = check_harcoded_signature pk in + true + +(* Fast checking does not simulate computation and directly returns true*) +let fast_fake_check ?watermark:_ _pk _signature _msg = true + +let sign = + match Helpers.yes_crypto_kind with + | Fast -> fast_fake_sign + | Yes -> fake_sign + | No -> sign + +let check = + match Helpers.yes_crypto_kind with + | Fast -> fast_fake_check + | Yes -> fake_check + | No -> check + let append ?watermark sk msg = Bytes.cat msg (to_bytes (sign ?watermark sk msg)) let concat msg signature = Bytes.cat msg (to_bytes signature) -type algo = Ed25519 | Secp256k1 | P256 | Bls - let algos = [Ed25519; Secp256k1; P256; Bls] +let fake_generate_key (pkh, pk, _) = + let sk_of_pk (pk : public_key) : secret_key = + let pk_b = Data_encoding.Binary.to_bytes_exn Public_key.encoding pk in + let sk_b = Bytes.sub pk_b 0 33 in + let sk = Data_encoding.Binary.of_bytes_exn Secret_key.encoding sk_b in + sk + in + let fake_sk = sk_of_pk pk in + (pkh, pk, fake_sk) + let generate_key ?(algo = Ed25519) ?seed () = match algo with | Ed25519 -> @@ -884,6 +984,18 @@ let generate_key ?(algo = Ed25519) ?seed () = let pkh, pk, sk = Bls.generate_key ?seed () in (Public_key_hash.Bls pkh, Public_key.Bls pk, Secret_key.Bls sk) +let fake_generate_key ?(algo = Ed25519) ?seed () = + let true_keys = generate_key ~algo ?seed () in + fake_generate_key true_keys + +let generate_key = + match Helpers.yes_crypto_kind with + | Fast | Yes -> + (* We keep the original keys generation to stay as close as possible of the + initial performance. *) + fake_generate_key + | No -> generate_key + let deterministic_nonce sk msg = match sk with | Secret_key.Ed25519 sk -> Ed25519.deterministic_nonce sk msg diff --git a/src/lib_event_logging/internal_event.ml b/src/lib_event_logging/internal_event.ml index 985280091dd6a6466c30233cdcd9c527fb0b7c6f..ab0e1dc21c738a9413e852740fe4c91927308d04 100644 --- a/src/lib_event_logging/internal_event.ml +++ b/src/lib_event_logging/internal_event.ml @@ -357,7 +357,6 @@ module All_sinks = struct (fun (TopLevel (ev, x)) -> handle ev None x) (List.rev !top_level_events) in - top_level_events := [] ; return_unit let close ?(except = fun _ -> false) () = diff --git a/src/proto_011_PtHangz2/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_011_PtHangz2/lib_client_commands/client_proto_stresstest_commands.ml index 5d395645d3df309183e478214f612a05f9083e6f..8d63e897a921449690d351c0742de87ba1e1e40f 100644 --- a/src/proto_011_PtHangz2/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_011_PtHangz2/lib_client_commands/client_proto_stresstest_commands.ml @@ -1137,4 +1137,12 @@ let generate_random_transactions = let commands = [generate_random_transactions] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_012_Psithaca/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_012_Psithaca/lib_client_commands/client_proto_stresstest_commands.ml index c5ac1cf13b0ff0cf7ae96b25a14f269190f4ba6d..3be5c6361479a383b22d008b9b2ddef8c9aa92bc 100644 --- a/src/proto_012_Psithaca/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_012_Psithaca/lib_client_commands/client_proto_stresstest_commands.ml @@ -1131,4 +1131,12 @@ let generate_random_transactions = let commands = [generate_random_transactions] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_013_PtJakart/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_013_PtJakart/lib_client_commands/client_proto_stresstest_commands.ml index 40e2081191602b8af322a457674a3759b2d925e4..d775f3240a0b34dbb2a30a722adc113db29d0ed1 100644 --- a/src/proto_013_PtJakart/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_013_PtJakart/lib_client_commands/client_proto_stresstest_commands.ml @@ -1298,4 +1298,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_014_PtKathma/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_014_PtKathma/lib_client_commands/client_proto_stresstest_commands.ml index 63c38641d8a92c9504682b77d563c35f90f401d7..28094b5787bbbef16151ba8d4a091ae7a16b6142 100644 --- a/src/proto_014_PtKathma/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_014_PtKathma/lib_client_commands/client_proto_stresstest_commands.ml @@ -1883,4 +1883,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_015_PtLimaPt/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_015_PtLimaPt/lib_client_commands/client_proto_stresstest_commands.ml index d3c608a051821edd49b7cd84653cbdbe34f6fedc..8c157efb41b802ad77a1b9f2aa62386270f0757c 100644 --- a/src/proto_015_PtLimaPt/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_015_PtLimaPt/lib_client_commands/client_proto_stresstest_commands.ml @@ -1970,4 +1970,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_016_PtMumbai/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_016_PtMumbai/lib_client_commands/client_proto_stresstest_commands.ml index d2daf0a97f44511c48a9c29dc41076f00b7fdd6d..9c0b9e58f05ac3a66b098740d6e60d1d255e97fd 100644 --- a/src/proto_016_PtMumbai/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_016_PtMumbai/lib_client_commands/client_proto_stresstest_commands.ml @@ -1970,4 +1970,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_017_PtNairob/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_017_PtNairob/lib_client_commands/client_proto_stresstest_commands.ml index 66177c69a2f7df311c9ad998184f2a3fd96c3926..5a9f488c8412c0749f7fd8da2d291182d6353e24 100644 --- a/src/proto_017_PtNairob/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_017_PtNairob/lib_client_commands/client_proto_stresstest_commands.ml @@ -1926,4 +1926,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_018_Proxford/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_018_Proxford/lib_client_commands/client_proto_stresstest_commands.ml index 9732c6f10d67209aac3fdce486d593c5b11fa6df..2452927edf5e3d6c8befb114baa10fe182ccf921 100644 --- a/src/proto_018_Proxford/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_018_Proxford/lib_client_commands/client_proto_stresstest_commands.ml @@ -1928,4 +1928,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_019_PtParisB/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_019_PtParisB/lib_client_commands/client_proto_stresstest_commands.ml index 66177c69a2f7df311c9ad998184f2a3fd96c3926..5a9f488c8412c0749f7fd8da2d291182d6353e24 100644 --- a/src/proto_019_PtParisB/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_019_PtParisB/lib_client_commands/client_proto_stresstest_commands.ml @@ -1926,4 +1926,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.ml index 66177c69a2f7df311c9ad998184f2a3fd96c3926..5a9f488c8412c0749f7fd8da2d291182d6353e24 100644 --- a/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_020_PsParisC/lib_client_commands/client_proto_stresstest_commands.ml @@ -1926,4 +1926,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/src/proto_alpha/lib_client_commands/client_proto_stresstest_commands.ml b/src/proto_alpha/lib_client_commands/client_proto_stresstest_commands.ml index 9c5d0405619cc0864d571c17fa9463ef5c12c050..a40c96d1ee9cf7bdd33c7f38c1286c92c13d0c5e 100644 --- a/src/proto_alpha/lib_client_commands/client_proto_stresstest_commands.ml +++ b/src/proto_alpha/lib_client_commands/client_proto_stresstest_commands.ml @@ -1927,4 +1927,12 @@ let commands = ] let commands network () = - match network with Some `Mainnet -> [] | Some `Testnet | None -> commands + (* Stresstest should not be used on mainnet. If the client is running with + the yes-crypto activated, operations won't be considered valid and should + not endanger the network nor the users funds. *) + match Sys.getenv_opt Tezos_crypto.Helpers.yes_crypto_environment_variable with + | Some _ -> commands + | None -> ( + match network with + | Some `Mainnet -> [] + | Some `Testnet | None -> commands) diff --git a/tezt/lib_tezos/client.ml b/tezt/lib_tezos/client.ml index 6aa2062c0d5efd99f4d766aa9a97f69c2fd342aa..0f4aa2a25fd2b36bf15cec0ddb42182c773ac66b 100644 --- a/tezt/lib_tezos/client.ml +++ b/tezt/lib_tezos/client.ml @@ -1123,10 +1123,11 @@ let spawn_bls_import_secret_key ?hooks ?(force = false) let bls_import_secret_key ?hooks ?force key sc_client = spawn_bls_import_secret_key ?hooks ?force key sc_client |> Process.check -let spawn_transfer ?hooks ?log_output ?endpoint ?(wait = "none") ?burn_cap ?fee - ?gas_limit ?safety_guard ?storage_limit ?counter ?entrypoint ?arg +let spawn_transfer ?env ?hooks ?log_output ?endpoint ?(wait = "none") ?burn_cap + ?fee ?gas_limit ?safety_guard ?storage_limit ?counter ?entrypoint ?arg ?(simulation = false) ?(force = false) ~amount ~giver ~receiver client = spawn_command + ?env ?log_output ?endpoint ?hooks diff --git a/tezt/lib_tezos/client.mli b/tezt/lib_tezos/client.mli index 32e5f7803924d0c026afdb11ec1189af28394432..1e11d82d06a797b696d6ae210ba4f1c14e566c30 100644 --- a/tezt/lib_tezos/client.mli +++ b/tezt/lib_tezos/client.mli @@ -873,6 +873,7 @@ val transfer : (** Same as [transfer], but do not wait for the process to exit. *) val spawn_transfer : + ?env:string String_map.t -> ?hooks:Process.hooks -> ?log_output:bool -> ?endpoint:endpoint -> diff --git a/tezt/lib_tezos/node.ml b/tezt/lib_tezos/node.ml index c9218684eb2f7ab0ba63584417f5fc5a51d5deb8..e5162070d990c0414ba1a9fe4b466d8c50535e72 100644 --- a/tezt/lib_tezos/node.ml +++ b/tezt/lib_tezos/node.ml @@ -45,6 +45,7 @@ type argument = | Disable_context_pruning | Storage_maintenance_delay of string | Force_history_mode_switch + | Allow_yes_crypto let make_argument = function | Network x -> ["--network"; x] @@ -82,6 +83,7 @@ let make_argument = function | Disable_context_pruning -> ["--disable-context-pruning"] | Storage_maintenance_delay x -> ["--storage-maintenance-delay"; x] | Force_history_mode_switch -> ["--force-history-mode-switch"] + | Allow_yes_crypto -> ["--allow-yes-crypto"] let make_arguments arguments = List.flatten (List.map make_argument arguments) @@ -108,7 +110,8 @@ let is_redundant = function | Enable_http_cache_headers, Enable_http_cache_headers | Disable_context_pruning, Disable_context_pruning | Storage_maintenance_delay _, Storage_maintenance_delay _ - | Force_history_mode_switch, Force_history_mode_switch -> + | Force_history_mode_switch, Force_history_mode_switch + | Allow_yes_crypto, Allow_yes_crypto -> true | Metrics_addr addr1, Metrics_addr addr2 -> addr1 = addr2 | Peer peer1, Peer peer2 -> peer1 = peer2 @@ -137,7 +140,8 @@ let is_redundant = function | Enable_http_cache_headers, _ | Disable_context_pruning, _ | Storage_maintenance_delay _, _ - | Force_history_mode_switch, _ -> + | Force_history_mode_switch, _ + | Allow_yes_crypto, _ -> false (* Some arguments should not be written in the config file by [Node.init] @@ -920,7 +924,7 @@ let runlike_command_arguments node command arguments = :: string_of_int node.persistent_state.max_active_rpc_connections :: command_args -let do_runlike_command ?(on_terminate = fun _ -> ()) ?event_level +let do_runlike_command ?env ?(on_terminate = fun _ -> ()) ?event_level ?event_sections_levels node arguments = (match node.status with | Not_running -> () @@ -940,6 +944,7 @@ let do_runlike_command ?(on_terminate = fun _ -> ()) ?event_level unit in run + ?env ?runner:node.persistent_state.runner ?event_level ?event_sections_levels @@ -948,8 +953,8 @@ let do_runlike_command ?(on_terminate = fun _ -> ()) ?event_level arguments ~on_terminate -let run ?patch_config ?on_terminate ?event_level ?event_sections_levels node - arguments = +let run ?env ?patch_config ?on_terminate ?event_level ?event_sections_levels + node arguments = let* () = match patch_config with | None -> Lwt.return_unit @@ -975,6 +980,7 @@ let run ?patch_config ?on_terminate ?event_level ?event_sections_levels node runlike_command_arguments node "run" args in do_runlike_command + ?env ?on_terminate ?event_level ?event_sections_levels diff --git a/tezt/lib_tezos/node.mli b/tezt/lib_tezos/node.mli index 542e900a7afd40adede5d1679eb8dc388051f81d..7f2c355863c67c0342b0b83be2b8f2e6c71835bb 100644 --- a/tezt/lib_tezos/node.mli +++ b/tezt/lib_tezos/node.mli @@ -103,6 +103,7 @@ type argument = | Disable_context_pruning (** [--disable_context-pruning] *) | Storage_maintenance_delay of string (** [--storage-maintenance-delay]*) | Force_history_mode_switch (** [--force-history-mode-switch] *) + | Allow_yes_crypto (** [--allow-yes-crypto] *) (** A TLS configuration for the node: paths to a [.crt] and a [.key] file. @@ -479,6 +480,7 @@ val spawn_reconstruct : t -> Process.t for a more precise semantic. *) val run : + ?env:string String_map.t -> ?patch_config:(JSON.t -> JSON.t) -> ?on_terminate:(Unix.process_status -> unit) -> ?event_level:Daemon.Level.default_level -> diff --git a/tezt/tests/main.ml b/tezt/tests/main.ml index aa91a4e1e6d57495569b37a89904824d084fc4d9..15da14726ce0b0ad155043fba428b49238cb5fe4 100644 --- a/tezt/tests/main.ml +++ b/tezt/tests/main.ml @@ -224,7 +224,8 @@ let register_protocol_tests_that_use_supports_correctly () = Dac.register ~protocols ; Timelock.register ~protocols ; Tzt_regression.register ~protocols ; - Dal.register ~protocols + Dal.register ~protocols ; + Yes_crypto.register ~protocols (* Regression tests are not easy to maintain for multiple protocols because one needs to update and maintain all the expected output files. Some of them, such as diff --git a/tezt/tests/yes_crypto.ml b/tezt/tests/yes_crypto.ml new file mode 100644 index 0000000000000000000000000000000000000000..43250b82e25ef968d9eaf7bd3a0162c5ff242a5f --- /dev/null +++ b/tezt/tests/yes_crypto.ml @@ -0,0 +1,103 @@ +(*****************************************************************************) +(* *) +(* SPDX-License-Identifier: MIT *) +(* SPDX-FileCopyrightText: 2024 Nomadic Labs *) +(* *) +(*****************************************************************************) + +(* Testing + ------- + Component: Client commands + Invocation: dune exec tezt/tests/main.exe -- --file yes_crypto.ml + Subject: Test yes_crypto +*) + +let team = Tag.layer1 + +let test_check_signature = + Protocol.register_test + ~__FILE__ + ~title:"Test yes crypto signatures can only be used with yes crypto checks" + ~tags:[team; "client"; "signature"; "check"; "yes_crypto"] + @@ fun protocol -> + let* node, client = Client.init_with_protocol `Client ~protocol () in + + Log.info + "Check operation signed by a vanilla client is accepted by a vanilla node" ; + let transfer = + Client.spawn_transfer + client + ~amount:(Tez.of_int 1) + ~giver:"bootstrap2" + ~receiver:"bootstrap1" + in + let bake1 = Client.spawn_bake_for client in + let* () = Process.check transfer in + let* () = Process.check bake1 in + + Log.info "Check operation signed by a yes-client is refused by a vanilla node" ; + let env = + String_map.add + Tezos_crypto.Helpers.yes_crypto_environment_variable + "y" + String_map.empty + in + + let yes_transfer = + Client.spawn_transfer + ~env + client + ~amount:(Tez.of_int 1) + ~giver:"bootstrap3" + ~receiver:"bootstrap1" + in + let* () = Process.check_error yes_transfer in + + Log.info "Restart node with yes_crypto enabled" ; + let* () = Node.kill node in + let* () = Node.run ~env node [Node.Allow_yes_crypto] in + let* () = Node.wait_for_ready node in + + Log.info "Check operation signed by a yes-client is accepted by a yes node" ; + let yes_transfer2 = + Client.spawn_transfer + ~env + client + ~amount:(Tez.of_int 1) + ~giver:"bootstrap4" + ~receiver:"bootstrap1" + in + let bake2 = Client.spawn_bake_for client in + let* () = Process.check bake2 in + let* () = Process.check yes_transfer2 in + + Log.info + "Check operation signed by a vanilla-client is accepted by a yes node" ; + let transfer2 = + Client.spawn_transfer + client + ~amount:(Tez.of_int 1) + ~giver:"bootstrap5" + ~receiver:"bootstrap1" + in + + let bake3 = Client.spawn_bake_for client in + let* () = Process.check bake3 in + let* () = Process.check transfer2 in + + Log.info + "Check that running a node with only environement variable is refused" ; + let* () = Node.kill node in + let* () = Node.run ~env node [] in + let* () = + Node.check_error + node + ~msg: + (rex + ".* Yes crypto is enabled but the option '--allow-yes-crypto' was \ + not provided.*") + in + + return () + +let register ~protocols = test_check_signature protocols