From d253b5dd3e2f3181bf901d0bf8cd8e84d5bfe438 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 20 May 2025 14:00:51 +0200 Subject: [PATCH 1/3] Proto: Reveal tz4 again after migration --- src/proto_alpha/lib_protocol/manager_repr.ml | 53 +++++++++++++++++--- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/proto_alpha/lib_protocol/manager_repr.ml b/src/proto_alpha/lib_protocol/manager_repr.ml index b96a51401289..af6a2c0f1990 100644 --- a/src/proto_alpha/lib_protocol/manager_repr.ml +++ b/src/proto_alpha/lib_protocol/manager_repr.ml @@ -25,11 +25,21 @@ (* Tezos Protocol Implementation - Low level Repr. of Managers' keys *) -type manager_key = - | Hash of Signature.Public_key_hash.t - | Public_key of Signature.Public_key.t +(* In S, the type of the [Manager] storage has been changed to [manager_key_storage_type]. + This change is purely internal. Previously revealed keys are determined to be valid + or not at encoding time. This is necessary because the tz4 addresses that have been + revealed before S should be revealed again. After S, the revealed keys are + registered separately (tag 2). -type t = manager_key + To keep consistency, this type is projected on [manager_key], which has the same + types as before, and verifies the same invariants. This means that any member of + [Hash] needs to be revealed (regardless of if it was already revealed before S or not), + and member of [Public_key] are considered revealed. +*) +type manager_key_storage_type = + | Hash of Signature.Public_key_hash.t + | Public_key_before_S of Signature.Public_key.t + | Public_key_after_S of Signature.Public_key.t open Data_encoding @@ -46,7 +56,36 @@ let pubkey_case tag = tag ~title:"Public_key" Signature.Public_key.encoding - (function Public_key hash -> Some hash | _ -> None) - (fun hash -> Public_key hash) + (function Public_key_before_S pk -> Some pk | _ -> None) + (fun pk -> Public_key_before_S pk) + +let pubkey_ok_case tag = + case + tag + ~title:"Public_key_after_S" + Signature.Public_key.encoding + (function Public_key_after_S pk -> Some pk | _ -> None) + (fun pk -> Public_key_after_S pk) + +let encoding_legacy = + union [hash_case (Tag 0); pubkey_case (Tag 1); pubkey_ok_case (Tag 2)] + +type manager_key = + | Hash of Signature.Public_key_hash.t + | Public_key of Signature.Public_key.t + +type t = manager_key -let encoding = union [hash_case (Tag 0); pubkey_case (Tag 1)] +let encoding = + conv + (function + | Hash hash -> (Hash hash : manager_key_storage_type) + (* This encoding change only takes effect after S, so newly registered public keys + are stored as [Public_key_after_S] *) + | Public_key pk -> Public_key_after_S pk) + (function + | Hash hash -> Hash hash + | Public_key_before_S (Bls _ as pk) -> Hash (Signature.Public_key.hash pk) + | Public_key_before_S pk -> Public_key pk + | Public_key_after_S pk -> Public_key pk) + encoding_legacy -- GitLab From 0f662b8f84b93a6f379d77f6f6d43c8c819f58ce Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 20 May 2025 14:01:07 +0200 Subject: [PATCH 2/3] Tezt: test reveal migration --- tezt/tests/protocol_migration.ml | 163 ++++++++++++++++++++++++++++++- 1 file changed, 162 insertions(+), 1 deletion(-) diff --git a/tezt/tests/protocol_migration.ml b/tezt/tests/protocol_migration.ml index 479d9f921dad..53bffaed7f8f 100644 --- a/tezt/tests/protocol_migration.ml +++ b/tezt/tests/protocol_migration.ml @@ -1610,6 +1610,166 @@ let test_unstaked_requests_and_min_delegated () = in unit +let test_reveal_migration () = + let migrate_from = Protocol.R022 in + let migrate_to = Protocol.Alpha in + + Test.register + ~__FILE__ + ~title:"protocol migration for reveal" + ~tags:[team; "protocol"; "migration"; "reveal"] + @@ fun () -> + let* parameter_file = + Protocol.write_parameter_file + ~base:(Left (Protocol.parameter_file migrate_from)) + [] + in + let parameters = JSON.parse_file parameter_file in + let blocks_per_cycle = JSON.(get "blocks_per_cycle" parameters |> as_int) in + (* Migration at the end of cycle 1 *) + let migration_level = 2 * blocks_per_cycle in + let () = Local_helpers.print_parameters ~parameter_file ~migration_level in + let* client, _node = + Local_helpers.activate_protocol + ~parameter_file + ~migrate_from + ~migrate_to + ~migration_level + in + let check_not_revealed id = + let* metadata = + Client.RPC.call client + @@ RPC.get_chain_block_context_contract_manager_key ~id () + in + assert (JSON.is_null metadata) ; + return () + in + let check_revealed id = + let* metadata = + Client.RPC.call client + @@ RPC.get_chain_block_context_contract_manager_key ~id () + in + assert (not (JSON.is_null metadata)) ; + return () + in + (* Three new key pairs. + The first one will be revealed before the migration. It should still be revealed after. + The second will be revealed after, revelation is still possible. + The third one (tz4) will be revealed before, unrevealed by the migration, and rerevealed after. *) + let* fresh_account = Client.gen_and_show_keys ~sig_alg:"ed25519" client in + let* another_fresh_account = + Client.gen_and_show_keys ~sig_alg:"ed25519" client + in + let* fresh_account_tz4 = Client.gen_and_show_keys ~sig_alg:"bls" client in + + Log.info "Transfer tez to new keys" ; + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.one + ~giver:"bootstrap1" + ~receiver:fresh_account.alias + client + in + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.one + ~giver:"bootstrap2" + ~receiver:another_fresh_account.alias + client + in + let* () = + Client.transfer + ~burn_cap:Tez.one + ~amount:Tez.one + ~giver:"bootstrap3" + ~receiver:fresh_account_tz4.alias + client + in + let* () = Client.bake_for_and_wait client in + + (* No key has been revealed yet *) + let* () = check_not_revealed fresh_account.public_key_hash in + let* () = check_not_revealed fresh_account_tz4.public_key_hash in + let* () = check_not_revealed another_fresh_account.public_key_hash in + + (* Reveal key 1 *) + Log.info "Reveal %s" fresh_account.alias ; + let* () = Client.reveal ~src:fresh_account.alias client |> Runnable.run in + let* () = Client.bake_for_and_wait client in + let* () = check_revealed fresh_account.public_key_hash in + let* () = check_not_revealed fresh_account_tz4.public_key_hash in + + (* Reveal key 3 (tz4) *) + Log.info "Reveal %s" fresh_account_tz4.alias ; + let* () = Client.reveal ~src:fresh_account_tz4.alias client |> Runnable.run in + let* () = Client.bake_for_and_wait client in + let* () = check_revealed fresh_account.public_key_hash in + let* () = check_revealed fresh_account_tz4.public_key_hash in + + let* tz4_balance_before = + Client.RPC.call client + @@ RPC.get_chain_block_context_contract_balance + ~id:fresh_account_tz4.public_key_hash + () + in + + (* Wait for migration *) + Log.info "Bake until migration" ; + let* () = Client.bake_until_cycle ~target_cycle:2 client in + + (* Check balance after migration *) + let* tz4_balance_after_migration = + Client.RPC.call client + @@ RPC.get_chain_block_context_contract_balance + ~id:fresh_account_tz4.public_key_hash + () + in + assert ( + Int64.equal + (Tez.mutez_int64 tz4_balance_before) + (Tez.mutez_int64 tz4_balance_after_migration)) ; + + (* Check revelation status. key 3 has been unrevealed. *) + let* () = check_revealed fresh_account.public_key_hash in + let* () = check_not_revealed another_fresh_account.public_key_hash in + let* () = check_not_revealed fresh_account_tz4.public_key_hash in + + (* Reveal key 3 again *) + Log.info "Reveal %s" fresh_account_tz4.alias ; + let* () = + Client.reveal + ~fee:Tez.(of_mutez_int64 11_111L) + ~src:fresh_account_tz4.alias + client + |> Runnable.run + in + let* () = Client.bake_for_and_wait client in + let* () = check_revealed fresh_account_tz4.public_key_hash in + + (* Reveal key 2 *) + Log.info "Reveal %s" another_fresh_account.alias ; + let* () = + Client.reveal ~src:another_fresh_account.alias client |> Runnable.run + in + let* () = Client.bake_for_and_wait client in + let* () = check_revealed another_fresh_account.public_key_hash in + + (* Check balance after reveal *) + let* tz4_balance_after_reveal = + Client.RPC.call client + @@ RPC.get_chain_block_context_contract_balance + ~id:fresh_account_tz4.public_key_hash + () + in + assert ( + Int64.equal + (Tez.mutez_int64 tz4_balance_before) + (Int64.add 11_111L (Tez.mutez_int64 tz4_balance_after_reveal))) ; + + return () + let register ~migrate_from ~migrate_to = test_migration_for_whole_cycle ~migrate_from ~migrate_to ; test_migration_with_bakers ~migrate_from ~migrate_to () ; @@ -1617,4 +1777,5 @@ let register ~migrate_from ~migrate_to = test_forked_migration_manual ~migrate_from ~migrate_to () ; test_migration_with_snapshots ~migrate_from ~migrate_to ; test_unstaked_requests_many_delegates () ; - test_unstaked_requests_and_min_delegated () + test_unstaked_requests_and_min_delegated () ; + test_reveal_migration () -- GitLab From 0223a2c0c9a42e5247d838d08079394733b07326 Mon Sep 17 00:00:00 2001 From: Lucas Randazzo Date: Tue, 20 May 2025 16:01:05 +0200 Subject: [PATCH 3/3] Docs: update changelog --- docs/protocols/alpha.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/protocols/alpha.rst b/docs/protocols/alpha.rst index 371639d2003f..aae388897a01 100644 --- a/docs/protocols/alpha.rst +++ b/docs/protocols/alpha.rst @@ -58,6 +58,10 @@ Gas improvements Breaking Changes ---------------- +- Unrevealed tz4 addresses. Starting in this protocol, tz4 addresses need a proof of possession + provided at revelation. This forces existing tz4 addresses to provide such a proof. This does + not change anything about the revelation of new addresses, or non-tz4 addresses. (MR :gl:`!18078`) + RPC Changes ----------- -- GitLab