From a4c11433f9f2cb8fd6a5e5ba01dfa01176b70dd6 Mon Sep 17 00:00:00 2001 From: Arvid Norberg Date: Tue, 21 May 2024 20:42:21 +0200 Subject: [PATCH] bump chia_rs to 0.8.0 and update G1Element handling (#18037) * bump chia_rs to 0.8.0 and update G1Element handling * use real keys and signatures in mempool tests --- chia/_tests/clvm/test_puzzles.py | 2 +- chia/_tests/core/mempool/test_mempool.py | 12 +-- .../core/mempool/test_mempool_manager.py | 73 +++++++++++++------ .../mempool/test_singleton_fast_forward.py | 45 ++++++++---- chia/_tests/core/util/test_cached_bls.py | 10 +-- chia/_tests/util/key_tool.py | 10 +-- chia/_tests/util/test_condition_tools.py | 36 ++++----- .../clawback/test_clawback_lifecycle.py | 3 +- chia/_tests/wallet/test_signer_protocol.py | 16 ++-- chia/consensus/block_body_validation.py | 5 +- chia/consensus/multiprocess_validation.py | 6 +- chia/full_node/mempool_manager.py | 6 +- chia/util/cached_bls.py | 29 ++------ chia/util/condition_tools.py | 19 ++--- chia/wallet/signer_protocol.py | 4 +- chia/wallet/util/debug_spend_bundle.py | 6 +- chia/wallet/wallet.py | 16 ++-- chia/wallet/wallet_state_manager.py | 16 ++-- setup.py | 2 +- tools/analyze-chain.py | 7 +- 20 files changed, 175 insertions(+), 148 deletions(-) diff --git a/chia/_tests/clvm/test_puzzles.py b/chia/_tests/clvm/test_puzzles.py index 58a2ee93a64a..46f2c12e46bb 100644 --- a/chia/_tests/clvm/test_puzzles.py +++ b/chia/_tests/clvm/test_puzzles.py @@ -233,7 +233,7 @@ def do_test_spend_p2_delegated_puzzle_or_hidden_puzzle_with_delegated_puzzle(hid assert synthetic_public_key == int_to_public_key(synthetic_offset) + hidden_pub_key_point - secret_exponent = key_lookup.dict.get(hidden_public_key) + secret_exponent = key_lookup.dict[G1Element.from_bytes(hidden_public_key)] assert int_to_public_key(secret_exponent) == hidden_pub_key_point synthetic_secret_exponent = secret_exponent + synthetic_offset diff --git a/chia/_tests/core/mempool/test_mempool.py b/chia/_tests/core/mempool/test_mempool.py index b4379d3dbeca..71bca0d4fcf1 100644 --- a/chia/_tests/core/mempool/test_mempool.py +++ b/chia/_tests/core/mempool/test_mempool.py @@ -6,7 +6,7 @@ from typing import Callable, Dict, List, Optional, Tuple import pytest -from chia_rs import G2Element +from chia_rs import G1Element, G2Element from clvm.casts import int_to_bytes from clvm_tools import binutils @@ -2161,7 +2161,7 @@ def test_create_coin_cost(self, softfork_height): ], ) def test_agg_sig_cost(self, condition, softfork_height): - pubkey = "abababababababababababababababababababababababab" + pubkey = "0x" + bytes(G1Element.generator()).hex() if softfork_height >= test_constants.HARD_FORK_FIX_HEIGHT: generator_base_cost = 40 @@ -2182,7 +2182,7 @@ def test_agg_sig_cost(self, condition, softfork_height): # this max cost is exactly enough for the AGG_SIG condition npc_result = generator_condition_tester( - f'({condition[0]} "{pubkey}" "foobar") ', + f'({condition[0]} {pubkey} "foobar") ', max_cost=generator_base_cost + 117 * COST_PER_BYTE + expected_cost, height=softfork_height, ) @@ -2193,7 +2193,7 @@ def test_agg_sig_cost(self, condition, softfork_height): # if we subtract one from max cost, this should fail npc_result = generator_condition_tester( - f'({condition[0]} "{pubkey}" "foobar") ', + f'({condition[0]} {pubkey} "foobar") ', max_cost=generator_base_cost + 117 * COST_PER_BYTE + expected_cost - 1, height=softfork_height, ) @@ -2219,7 +2219,7 @@ def test_agg_sig_cost(self, condition, softfork_height): @pytest.mark.parametrize("extra_arg", [' "baz"', ""]) @pytest.mark.parametrize("mempool", [True, False]) def test_agg_sig_extra_arg(self, condition, extra_arg, mempool, softfork_height): - pubkey = "abababababababababababababababababababababababab" + pubkey = "0x" + bytes(G1Element.generator()).hex() new_condition = condition in [ ConditionOpcode.AGG_SIG_PARENT, @@ -2258,7 +2258,7 @@ def test_agg_sig_extra_arg(self, condition, extra_arg, mempool, softfork_height) # this max cost is exactly enough for the AGG_SIG condition npc_result = generator_condition_tester( - f'({condition[0]} "{pubkey}" "foobar"{extra_arg}) ', + f'({condition[0]} {pubkey} "foobar"{extra_arg}) ', max_cost=11000000000, height=softfork_height, mempool_mode=mempool, diff --git a/chia/_tests/core/mempool/test_mempool_manager.py b/chia/_tests/core/mempool/test_mempool_manager.py index ef2fe1d1145c..e574e80271d1 100644 --- a/chia/_tests/core/mempool/test_mempool_manager.py +++ b/chia/_tests/core/mempool/test_mempool_manager.py @@ -5,7 +5,7 @@ from typing import Any, Awaitable, Callable, Collection, Dict, List, Optional, Set, Tuple import pytest -from chia_rs import ELIGIBLE_FOR_DEDUP, ELIGIBLE_FOR_FF, G1Element, G2Element +from chia_rs import ELIGIBLE_FOR_DEDUP, ELIGIBLE_FOR_FF, AugSchemeMPL, G2Element from chiabip158 import PyBIP158 from chia._tests.util.misc import invariant_check_mempool @@ -374,10 +374,12 @@ def test_compute_assert_height(conds: SpendBundleConditions, expected: TimelockC assert compute_assert_height(coin_records, conds) == expected -def spend_bundle_from_conditions(conditions: List[List[Any]], coin: Coin = TEST_COIN) -> SpendBundle: +def spend_bundle_from_conditions( + conditions: List[List[Any]], coin: Coin = TEST_COIN, aggsig: G2Element = G2Element() +) -> SpendBundle: solution = Program.to(conditions) coin_spend = make_spend(coin, IDENTITY_PUZZLE, solution) - return SpendBundle([coin_spend], G2Element()) + return SpendBundle([coin_spend], aggsig) async def add_spendbundle( @@ -393,8 +395,9 @@ async def generate_and_add_spendbundle( mempool_manager: MempoolManager, conditions: List[List[Any]], coin: Coin = TEST_COIN, + aggsig: G2Element = G2Element(), ) -> Tuple[SpendBundle, bytes32, Tuple[Optional[uint64], MempoolInclusionStatus, Optional[Err]]]: - sb = spend_bundle_from_conditions(conditions, coin) + sb = spend_bundle_from_conditions(conditions, coin, aggsig) sb_name = sb.name() result = await add_spendbundle(mempool_manager, sb, sb_name) return (sb, sb_name, result) @@ -567,11 +570,14 @@ async def test_same_sb_twice_with_eligible_coin() -> None: [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] sb1 = spend_bundle_from_conditions(sb1_conditions) + sk = AugSchemeMPL.key_gen(b"5" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, IDENTITY_PUZZLE_HASH, g1) sb2_conditions = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3], - [ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH], + [ConditionOpcode.AGG_SIG_UNSAFE, g1, IDENTITY_PUZZLE_HASH], ] - sb2 = spend_bundle_from_conditions(sb2_conditions, TEST_COIN2) + sb2 = spend_bundle_from_conditions(sb2_conditions, TEST_COIN2, sig) sb = SpendBundle.aggregate([sb1, sb2]) sb_name = sb.name() result = await add_spendbundle(mempool_manager, sb, sb_name) @@ -591,13 +597,16 @@ async def test_sb_twice_with_eligible_coin_and_different_spends_order() -> None: [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 2], ] sb1 = spend_bundle_from_conditions(sb1_conditions) - sb2_conditions = [ + sk = AugSchemeMPL.key_gen(b"6" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, IDENTITY_PUZZLE_HASH, g1) + sb2_conditions: List[List[Any]] = [ [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 3], - [ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH], + [ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), IDENTITY_PUZZLE_HASH], ] - sb2 = spend_bundle_from_conditions(sb2_conditions, TEST_COIN2) - sb3_conditions = [[ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH]] - sb3 = spend_bundle_from_conditions(sb3_conditions, TEST_COIN3) + sb2 = spend_bundle_from_conditions(sb2_conditions, TEST_COIN2, sig) + sb3_conditions = [[ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), IDENTITY_PUZZLE_HASH]] + sb3 = spend_bundle_from_conditions(sb3_conditions, TEST_COIN3, sig) sb = SpendBundle.aggregate([sb1, sb2, sb3]) sb_name = sb.name() reordered_sb = SpendBundle.aggregate([sb3, sb1, sb2]) @@ -1029,12 +1038,16 @@ async def get_unspent_lineage_info_for_puzzle_hash(_: bytes32) -> Optional[Unspe async def make_and_send_big_cost_sb(coin: Coin) -> None: conditions = [] - g1 = G1Element() + sk = AugSchemeMPL.key_gen(b"7" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, IDENTITY_PUZZLE_HASH, g1) + aggsig = G2Element() for _ in range(169): conditions.append([ConditionOpcode.AGG_SIG_UNSAFE, g1, IDENTITY_PUZZLE_HASH]) + aggsig += sig conditions.append([ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, coin.amount - 10_000_000]) # Create a spend bundle with a big enough cost that gets it close to the limit - _, _, res = await generate_and_add_spendbundle(mempool_manager, conditions, coin) + _, _, res = await generate_and_add_spendbundle(mempool_manager, conditions, coin, aggsig) assert res[1] == MempoolInclusionStatus.SUCCESS mempool_manager, coins = await setup_mempool_with_coins( @@ -1057,12 +1070,18 @@ async def make_and_send_big_cost_sb(coin: Coin) -> None: # Create 4 extra spend bundles with smaller FPC and smaller costs extra_sbs = [] extra_additions = [] + sk = AugSchemeMPL.key_gen(b"8" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, b"foobar", g1) for i in range(num_skipped_items + 1, num_skipped_items + 5): conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, coins[i].amount - 30_000]] # Make the first of these without eligible coins if i == num_skipped_items + 1: - conditions.append([ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH]) - sb, _, res = await generate_and_add_spendbundle(mempool_manager, conditions, coins[i]) + conditions.append([ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), b"foobar"]) + aggsig = sig + else: + aggsig = G2Element() + sb, _, res = await generate_and_add_spendbundle(mempool_manager, conditions, coins[i], aggsig) extra_sbs.append(sb) coin = Coin(coins[i].name(), IDENTITY_PUZZLE_HASH, uint64(coins[i].amount - 30_000)) extra_additions.append(coin) @@ -1169,9 +1188,13 @@ async def get_coin_records(coin_ids: Collection[bytes32]) -> List[CoinRecord]: def make_test_spendbundle(coin: Coin, *, fee: int = 0, eligible_spend: bool = False) -> SpendBundle: conditions = [[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, uint64(coin.amount - fee)]] + sig = G2Element() if not eligible_spend: - conditions.append([ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH]) - return spend_bundle_from_conditions(conditions, coin) + sk = AugSchemeMPL.key_gen(b"2" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, b"foobar", g1) + conditions.append([ConditionOpcode.AGG_SIG_UNSAFE, g1, b"foobar"]) + return spend_bundle_from_conditions(conditions, coin, sig) async def send_spendbundle( @@ -1343,11 +1366,16 @@ def test_run_for_cost_max_cost() -> None: def test_dedup_info_nothing_to_do() -> None: # No eligible coins, nothing to deduplicate, item gets considered normally + + sk = AugSchemeMPL.key_gen(b"3" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, b"foobar", g1) + conditions = [ - [ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH], + [ConditionOpcode.AGG_SIG_UNSAFE, g1, b"foobar"], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 1], ] - sb = spend_bundle_from_conditions(conditions, TEST_COIN) + sb = spend_bundle_from_conditions(conditions, TEST_COIN, sig) mempool_item = mempool_item_from_spendbundle(sb) assert mempool_item.npc_result.conds is not None eligible_coin_spends = EligibleCoinSpends() @@ -1453,11 +1481,14 @@ def test_dedup_info_eligible_3rd_time_another_2nd_time_and_one_non_eligible() -> ) sb1 = spend_bundle_from_conditions(initial_conditions, TEST_COIN) sb2 = spend_bundle_from_conditions(second_conditions, TEST_COIN2) + sk = AugSchemeMPL.key_gen(b"4" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, b"foobar", g1) sb3_conditions = [ - [ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH], + [ConditionOpcode.AGG_SIG_UNSAFE, g1, b"foobar"], [ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, 4], ] - sb3 = spend_bundle_from_conditions(sb3_conditions, TEST_COIN3) + sb3 = spend_bundle_from_conditions(sb3_conditions, TEST_COIN3, sig) sb = SpendBundle.aggregate([sb1, sb2, sb3]) mempool_item = mempool_item_from_spendbundle(sb) assert mempool_item.npc_result.conds is not None diff --git a/chia/_tests/core/mempool/test_singleton_fast_forward.py b/chia/_tests/core/mempool/test_singleton_fast_forward.py index 4a5ba4540af1..9fc4872d29e8 100644 --- a/chia/_tests/core/mempool/test_singleton_fast_forward.py +++ b/chia/_tests/core/mempool/test_singleton_fast_forward.py @@ -47,8 +47,11 @@ async def test_process_fast_forward_spends_nothing_to_do() -> None: async def get_unspent_lineage_info_for_puzzle_hash(_: bytes32) -> Optional[UnspentLineageInfo]: assert False # pragma: no cover - conditions = [[ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH]] - sb = spend_bundle_from_conditions(conditions, TEST_COIN) + sk = AugSchemeMPL.key_gen(b"b" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, b"foobar", g1) + conditions = [[ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), b"foobar"]] + sb = spend_bundle_from_conditions(conditions, TEST_COIN, sig) item = mempool_item_from_spendbundle(sb) # This coin is not eligible for fast forward assert item.bundle_coin_spends[TEST_COIN_ID].eligible_for_fast_forward is False @@ -252,16 +255,19 @@ async def make_and_send_spend_bundle( sim_client: SimClient, coin_spends: List[CoinSpend], is_eligible_for_ff: bool = True, + *, is_launcher_coin: bool = False, signing_puzzle: Optional[Program] = None, signing_coin: Optional[Coin] = None, + aggsig: G2Element = G2Element(), ) -> Tuple[MempoolInclusionStatus, Optional[Err]]: if is_launcher_coin or not is_eligible_for_ff: assert signing_puzzle is not None assert signing_coin is not None signature = sign_delegated_puz(signing_puzzle, signing_coin) + signature += aggsig else: - signature = G2Element() + signature = aggsig spend_bundle = SpendBundle(coin_spends, signature) status, error = await sim_client.push_tx(spend_bundle) if error is None: @@ -403,8 +409,12 @@ async def test_singleton_fast_forward_different_block(is_eligible_for_ff: bool) # Let's spend this first version, to create a bigger singleton child singleton_puzzle_hash = eve_coin_spend.coin.puzzle_hash inner_puzzle_hash = inner_puzzle.get_tree_hash() - inner_conditions = [ - [ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH], + + sk = AugSchemeMPL.key_gen(b"1" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, b"foobar", g1) + inner_conditions: List[List[Any]] = [ + [ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), b"foobar"], [ConditionOpcode.CREATE_COIN, inner_puzzle_hash, SINGLETON_CHILD_AMOUNT], ] singleton_coin_spend, singleton_signing_puzzle = make_singleton_coin_spend( @@ -423,6 +433,7 @@ async def test_singleton_fast_forward_different_block(is_eligible_for_ff: bool) is_eligible_for_ff, signing_puzzle=singleton_signing_puzzle, signing_coin=singleton, + aggsig=sig, ) unspent_lineage_info = await sim_client.service.coin_store.get_unspent_lineage_info_for_puzzle_hash( singleton_puzzle_hash @@ -448,6 +459,7 @@ async def test_singleton_fast_forward_different_block(is_eligible_for_ff: bool) is_eligible_for_ff, signing_puzzle=singleton_signing_puzzle, signing_coin=singleton, + aggsig=sig, ) if is_eligible_for_ff: # Instead of rejecting this as double spend, we perform a fast forward, @@ -492,8 +504,11 @@ async def test_singleton_fast_forward_same_block() -> None: # Let's spend this first version, to create a bigger singleton child singleton_puzzle_hash = eve_coin_spend.coin.puzzle_hash inner_puzzle_hash = inner_puzzle.get_tree_hash() - inner_conditions = [ - [ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH], + sk = AugSchemeMPL.key_gen(b"9" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, b"foobar", g1) + inner_conditions: List[List[Any]] = [ + [ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), b"foobar"], [ConditionOpcode.CREATE_COIN, inner_puzzle_hash, SINGLETON_CHILD_AMOUNT], ] singleton_coin_spend, _ = make_singleton_coin_spend(eve_coin_spend, singleton, inner_puzzle, inner_conditions) @@ -503,7 +518,7 @@ async def test_singleton_fast_forward_same_block() -> None: Program.to([[ConditionOpcode.CREATE_COIN, IDENTITY_PUZZLE_HASH, remaining_coin.amount - diff_to_balance]]) ) remaining_coin_spend = CoinSpend(remaining_coin, IDENTITY_PUZZLE, remaining_spend_solution) - await make_and_send_spend_bundle(sim, sim_client, [remaining_coin_spend, singleton_coin_spend]) + await make_and_send_spend_bundle(sim, sim_client, [remaining_coin_spend, singleton_coin_spend], aggsig=sig) unspent_lineage_info = await sim_client.service.coin_store.get_unspent_lineage_info_for_puzzle_hash( singleton_puzzle_hash ) @@ -519,19 +534,23 @@ async def test_singleton_fast_forward_same_block() -> None: # Now let's send 3 arbitrary spends of the already spent singleton in # one block. They should all properly fast forward random_amounts = [21, 17, 11] - signature = G2Element() + + sk = AugSchemeMPL.key_gen(b"a" * 32) + g1 = sk.get_g1() + sig = AugSchemeMPL.sign(sk, b"foobar", g1) for i in range(3): # This cost adjustment allows us to maintain the order of spends due to fee per # cost and amounts dynamics cost_factor = (i + 1) * 5 - inner_conditions = [ - [ConditionOpcode.AGG_SIG_UNSAFE, G1Element(), IDENTITY_PUZZLE_HASH] for _ in range(cost_factor) - ] + inner_conditions = [[ConditionOpcode.AGG_SIG_UNSAFE, bytes(g1), b"foobar"] for _ in range(cost_factor)] + aggsig = G2Element() + for _ in range(cost_factor): + aggsig += sig inner_conditions.append([ConditionOpcode.CREATE_COIN, inner_puzzle_hash, random_amounts[i]]) singleton_coin_spend, _ = make_singleton_coin_spend( eve_coin_spend, singleton, inner_puzzle, inner_conditions ) - status, error = await sim_client.push_tx(SpendBundle([singleton_coin_spend], signature)) + status, error = await sim_client.push_tx(SpendBundle([singleton_coin_spend], aggsig)) assert error is None assert status == MempoolInclusionStatus.SUCCESS diff --git a/chia/_tests/core/util/test_cached_bls.py b/chia/_tests/core/util/test_cached_bls.py index 20ecfad87d45..94fdab118654 100644 --- a/chia/_tests/core/util/test_cached_bls.py +++ b/chia/_tests/core/util/test_cached_bls.py @@ -1,6 +1,6 @@ from __future__ import annotations -from chia_rs import AugSchemeMPL, G1Element +from chia_rs import AugSchemeMPL from chia.util import cached_bls from chia.util.hash import std_hash @@ -11,7 +11,7 @@ def test_cached_bls(): n_keys = 10 seed = b"a" * 31 sks = [AugSchemeMPL.key_gen(seed + bytes([i])) for i in range(n_keys)] - pks = [bytes(sk.get_g1()) for sk in sks] + pks = [sk.get_g1() for sk in sks] msgs = [("msg-%d" % (i,)).encode() for i in range(n_keys)] sigs = [AugSchemeMPL.sign(sk, msg) for sk, msg in zip(sks, msgs)] @@ -22,7 +22,7 @@ def test_cached_bls(): sigs_half = sigs[: n_keys // 2] agg_sig_half = AugSchemeMPL.aggregate(sigs_half) - assert AugSchemeMPL.aggregate_verify([G1Element.from_bytes(pk) for pk in pks], msgs, agg_sig) + assert AugSchemeMPL.aggregate_verify(pks, msgs, agg_sig) # Verify with empty cache and populate it assert cached_bls.aggregate_verify(pks_half, msgs_half, agg_sig_half, True) @@ -46,12 +46,12 @@ def test_cached_bls_repeat_pk(): n_keys = 400 seed = b"a" * 32 sks = [AugSchemeMPL.key_gen(seed) for i in range(n_keys)] + [AugSchemeMPL.key_gen(std_hash(seed))] - pks = [bytes(sk.get_g1()) for sk in sks] + pks = [sk.get_g1() for sk in sks] msgs = [("msg-%d" % (i,)).encode() for i in range(n_keys + 1)] sigs = [AugSchemeMPL.sign(sk, msg) for sk, msg in zip(sks, msgs)] agg_sig = AugSchemeMPL.aggregate(sigs) - assert AugSchemeMPL.aggregate_verify([G1Element.from_bytes(pk) for pk in pks], msgs, agg_sig) + assert AugSchemeMPL.aggregate_verify(pks, msgs, agg_sig) assert cached_bls.aggregate_verify(pks, msgs, agg_sig, force_cache=True) diff --git a/chia/_tests/util/key_tool.py b/chia/_tests/util/key_tool.py index f916914ad116..7db56fc43382 100644 --- a/chia/_tests/util/key_tool.py +++ b/chia/_tests/util/key_tool.py @@ -3,7 +3,7 @@ from dataclasses import dataclass, field from typing import Dict, List -from chia_rs import AugSchemeMPL, G2Element, PrivateKey +from chia_rs import AugSchemeMPL, G1Element, G2Element, PrivateKey from chia._tests.core.make_block_generator import GROUP_ORDER, int_to_public_key from chia.simulator.block_tools import test_constants @@ -13,16 +13,16 @@ @dataclass class KeyTool: - dict: Dict[bytes, int] = field(default_factory=dict) + dict: Dict[G1Element, int] = field(default_factory=dict) def add_secret_exponents(self, secret_exponents: List[int]) -> None: for _ in secret_exponents: - self.dict[bytes(int_to_public_key(_))] = _ % GROUP_ORDER + self.dict[int_to_public_key(_)] = _ % GROUP_ORDER - def sign(self, public_key: bytes, message: bytes) -> G2Element: + def sign(self, public_key: G1Element, message: bytes) -> G2Element: secret_exponent = self.dict.get(public_key) if not secret_exponent: - raise ValueError("unknown pubkey %s" % public_key.hex()) + raise ValueError("unknown pubkey %s" % bytes(public_key).hex()) bls_private_key = PrivateKey.from_bytes(secret_exponent.to_bytes(32, "big")) return AugSchemeMPL.sign(bls_private_key, message) diff --git a/chia/_tests/util/test_condition_tools.py b/chia/_tests/util/test_condition_tools.py index 02c29dc4670e..51769faba735 100644 --- a/chia/_tests/util/test_condition_tools.py +++ b/chia/_tests/util/test_condition_tools.py @@ -8,7 +8,7 @@ from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program -from chia.types.blockchain_format.sized_bytes import bytes32, bytes48 +from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.condition_opcodes import ConditionOpcode from chia.types.condition_with_args import ConditionWithArgs from chia.types.spend_bundle_conditions import Spend, SpendBundleConditions @@ -29,8 +29,8 @@ def mk_agg_sig_conditions( opcode: ConditionOpcode, - agg_sig_data: List[Tuple[bytes, bytes]], - agg_sig_unsafe_data: List[Tuple[bytes, bytes]] = [], + agg_sig_data: List[Tuple[G1Element, bytes]], + agg_sig_unsafe_data: List[Tuple[G1Element, bytes]] = [], ) -> SpendBundleConditions: spend = Spend( coin_id=TEST_COIN.name(), @@ -69,18 +69,18 @@ def mk_agg_sig_conditions( ], ) def test_pkm_pairs_vs_for_conditions_dict(opcode: ConditionOpcode) -> None: - conds = mk_agg_sig_conditions(opcode, agg_sig_data=[(bytes48(PK1), b"msg1"), (bytes48(PK2), b"msg2")]) + conds = mk_agg_sig_conditions(opcode, agg_sig_data=[(PK1, b"msg1"), (PK2, b"msg2")]) pks, msgs = pkm_pairs(conds, b"foobar") result_aligned = [(x, y) for x, y in zip(pks, msgs)] conditions_dict = { - opcode: [ConditionWithArgs(opcode, [bytes48(PK1), b"msg1"]), ConditionWithArgs(opcode, [bytes48(PK2), b"msg2"])] + opcode: [ConditionWithArgs(opcode, [bytes(PK1), b"msg1"]), ConditionWithArgs(opcode, [bytes(PK2), b"msg2"])] } result2 = pkm_pairs_for_conditions_dict(conditions_dict, TEST_COIN, b"foobar") assert result_aligned == result2 # missing message argument with pytest.raises(ConsensusError, match="INVALID_CONDITION"): - conditions_dict = {opcode: [ConditionWithArgs(opcode, [bytes48(PK1)])]} + conditions_dict = {opcode: [ConditionWithArgs(opcode, [bytes(PK1)])]} result2 = pkm_pairs_for_conditions_dict(conditions_dict, TEST_COIN, b"foobar") with pytest.raises(ConsensusError, match="INVALID_CONDITION"): @@ -89,12 +89,12 @@ def test_pkm_pairs_vs_for_conditions_dict(opcode: ConditionOpcode) -> None: # extra argument with pytest.raises(ConsensusError, match="INVALID_CONDITION"): - conditions_dict = {opcode: [ConditionWithArgs(opcode, [bytes48(PK1), b"msg1", b"msg2"])]} + conditions_dict = {opcode: [ConditionWithArgs(opcode, [bytes(PK1), b"msg1", b"msg2"])]} result2 = pkm_pairs_for_conditions_dict(conditions_dict, TEST_COIN, b"foobar") # message too long with pytest.raises(ConsensusError, match="INVALID_CONDITION"): - conditions_dict = {opcode: [ConditionWithArgs(opcode, [bytes48(PK1), b"m" * 1025])]} + conditions_dict = {opcode: [ConditionWithArgs(opcode, [bytes(PK1), b"m" * 1025])]} result2 = pkm_pairs_for_conditions_dict(conditions_dict, TEST_COIN, b"foobar") @@ -136,7 +136,7 @@ def test_no_agg_sigs(self, opcode: ConditionOpcode) -> None: ], ) def test_agg_sig_conditions(self, opcode: ConditionOpcode, value: bytes) -> None: - conds = mk_agg_sig_conditions(opcode, agg_sig_data=[(bytes48(PK1), b"msg1"), (bytes48(PK2), b"msg2")]) + conds = mk_agg_sig_conditions(opcode, agg_sig_data=[(PK1, b"msg1"), (PK2, b"msg2")]) addendum = b"foobar" if opcode == ConditionOpcode.AGG_SIG_ME else std_hash(b"foobar" + opcode) pks, msgs = pkm_pairs(conds, b"foobar") assert [bytes(pk) for pk in pks] == [bytes(PK1), bytes(PK2)] @@ -155,9 +155,7 @@ def test_agg_sig_conditions(self, opcode: ConditionOpcode, value: bytes) -> None ], ) def test_agg_sig_unsafe(self, opcode: ConditionOpcode) -> None: - conds = mk_agg_sig_conditions( - opcode, agg_sig_data=[], agg_sig_unsafe_data=[(bytes48(PK1), b"msg1"), (bytes48(PK2), b"msg2")] - ) + conds = mk_agg_sig_conditions(opcode, agg_sig_data=[], agg_sig_unsafe_data=[(PK1, b"msg1"), (PK2, b"msg2")]) pks, msgs = pkm_pairs(conds, b"foobar") assert [bytes(pk) for pk in pks] == [bytes(PK1), bytes(PK2)] assert msgs == [b"msg1", b"msg2"] @@ -175,9 +173,7 @@ def test_agg_sig_unsafe(self, opcode: ConditionOpcode) -> None: ], ) def test_agg_sig_mixed(self, opcode: ConditionOpcode, value: bytes) -> None: - conds = mk_agg_sig_conditions( - opcode, agg_sig_data=[(bytes48(PK1), b"msg1")], agg_sig_unsafe_data=[(bytes48(PK2), b"msg2")] - ) + conds = mk_agg_sig_conditions(opcode, agg_sig_data=[(PK1, b"msg1")], agg_sig_unsafe_data=[(PK2, b"msg2")]) addendum = b"foobar" if opcode == ConditionOpcode.AGG_SIG_ME else std_hash(b"foobar" + opcode) pks, msgs = pkm_pairs(conds, b"foobar") assert [bytes(pk) for pk in pks] == [bytes(PK2), bytes(PK1)] @@ -196,9 +192,7 @@ def test_agg_sig_mixed(self, opcode: ConditionOpcode, value: bytes) -> None: ], ) def test_agg_sig_unsafe_restriction(self, opcode: ConditionOpcode) -> None: - conds = mk_agg_sig_conditions( - opcode, agg_sig_data=[], agg_sig_unsafe_data=[(bytes48(PK1), b"msg1"), (bytes48(PK2), b"msg2")] - ) + conds = mk_agg_sig_conditions(opcode, agg_sig_data=[], agg_sig_unsafe_data=[(PK1, b"msg1"), (PK2, b"msg2")]) with pytest.raises(ConsensusError, match="INVALID_CONDITION"): pkm_pairs(conds, b"msg1") @@ -216,11 +210,9 @@ class TestPkmPairsForConditionDict: def test_agg_sig_unsafe_restriction(self) -> None: ASU = ConditionOpcode.AGG_SIG_UNSAFE - conds = { - ASU: [ConditionWithArgs(ASU, [bytes48(PK1), b"msg1"]), ConditionWithArgs(ASU, [bytes48(PK2), b"msg2"])] - } + conds = {ASU: [ConditionWithArgs(ASU, [bytes(PK1), b"msg1"]), ConditionWithArgs(ASU, [bytes(PK2), b"msg2"])]} tuples = pkm_pairs_for_conditions_dict(conds, TEST_COIN, b"msg10") - assert tuples == [(bytes48(PK1), b"msg1"), (bytes48(PK2), b"msg2")] + assert tuples == [(PK1, b"msg1"), (PK2, b"msg2")] with pytest.raises(ConsensusError, match="INVALID_CONDITION"): pkm_pairs_for_conditions_dict(conds, TEST_COIN, b"msg1") diff --git a/chia/_tests/wallet/clawback/test_clawback_lifecycle.py b/chia/_tests/wallet/clawback/test_clawback_lifecycle.py index 7227e4af350f..cbc83b7523c0 100644 --- a/chia/_tests/wallet/clawback/test_clawback_lifecycle.py +++ b/chia/_tests/wallet/clawback/test_clawback_lifecycle.py @@ -75,10 +75,9 @@ def sign_coin_spend(self, coin_spend: CoinSpend, index: int) -> G2Element: conditions_dict = conditions_dict_for_solution(coin_spend.puzzle_reveal, coin_spend.solution, INFINITE_COST) signatures = [] - for pk_bytes, msg in pkm_pairs_for_conditions_dict( + for pk, msg in pkm_pairs_for_conditions_dict( conditions_dict, coin_spend.coin, DEFAULT_CONSTANTS.AGG_SIG_ME_ADDITIONAL_DATA ): - pk = G1Element.from_bytes(pk_bytes) signature = AugSchemeMPL.sign(synthetic_secret_key, msg) assert AugSchemeMPL.verify(pk, msg, signature) signatures.append(signature) diff --git a/chia/_tests/wallet/test_signer_protocol.py b/chia/_tests/wallet/test_signer_protocol.py index 715989dd52a2..9b293c5f2aa7 100644 --- a/chia/_tests/wallet/test_signer_protocol.py +++ b/chia/_tests/wallet/test_signer_protocol.py @@ -122,7 +122,7 @@ async def test_p2dohp_wallet_signer_protocol(wallet_environments: WalletTestFram SumHint( [pubkey.get_fingerprint().to_bytes(4, "big")], calculate_synthetic_offset(pubkey, DEFAULT_HIDDEN_PUZZLE_HASH).to_bytes(32, "big"), - wallet_state_manager.main_wallet.puzzle_for_pk(pubkey).uncurry()[1].at("f").as_atom(), + G1Element.from_bytes(wallet_state_manager.main_wallet.puzzle_for_pk(pubkey).uncurry()[1].at("f").as_atom()), ) ] assert utx.signing_instructions.key_hints.path_hints == [ @@ -184,7 +184,7 @@ async def test_p2dohp_wallet_signer_protocol(wallet_environments: WalletTestFram not_our_signing_instructions.key_hints, sum_hints=[ *not_our_signing_instructions.key_hints.sum_hints, - SumHint([bytes(not_our_pubkey)], std_hash(b"sum hint only"), bytes(G1Element())), + SumHint([bytes(not_our_pubkey)], std_hash(b"sum hint only"), G1Element()), ], ), ) @@ -284,7 +284,7 @@ async def test_p2blsdohp_execute_signing_instructions(wallet_environments: Walle sum_pk: G1Element = other_sk.get_g1() + root_pk signing_instructions: SigningInstructions = SigningInstructions( KeyHints( - [SumHint([root_fingerprint], test_name, bytes(sum_pk))], + [SumHint([root_fingerprint], test_name, sum_pk)], [], ), [SigningTarget(sum_pk.get_fingerprint().to_bytes(4, "big"), test_name, test_name)], @@ -335,7 +335,7 @@ async def test_p2blsdohp_execute_signing_instructions(wallet_environments: Walle sum_pk = child_sk.get_g1() + other_sk.get_g1() signing_instructions = SigningInstructions( KeyHints( - [SumHint([child_sk.get_g1().get_fingerprint().to_bytes(4, "big")], test_name, bytes(sum_pk))], + [SumHint([child_sk.get_g1().get_fingerprint().to_bytes(4, "big")], test_name, sum_pk)], [PathHint(root_fingerprint, [uint64(1), uint64(2), uint64(3), uint64(4)])], ), [SigningTarget(sum_pk.get_fingerprint().to_bytes(4, "big"), test_name, test_name)], @@ -370,8 +370,8 @@ async def test_p2blsdohp_execute_signing_instructions(wallet_environments: Walle SigningInstructions( KeyHints( [ - SumHint([child_sk.get_g1().get_fingerprint().to_bytes(4, "big")], test_name, bytes(sum_pk)), - SumHint([child_sk_2.get_g1().get_fingerprint().to_bytes(4, "big")], test_name_2, bytes(sum_pk_2)), + SumHint([child_sk.get_g1().get_fingerprint().to_bytes(4, "big")], test_name, sum_pk), + SumHint([child_sk_2.get_g1().get_fingerprint().to_bytes(4, "big")], test_name_2, sum_pk_2), ], [ PathHint(root_fingerprint, [uint64(1), uint64(2), uint64(3), uint64(4)]), @@ -412,7 +412,7 @@ async def test_p2blsdohp_execute_signing_instructions(wallet_environments: Walle ) unknown_sum_hint = SigningInstructions( KeyHints( - [SumHint([b"unknown fingerprint"], b"", bytes(G1Element()))], + [SumHint([b"unknown fingerprint"], b"", G1Element())], [], ), [], @@ -439,7 +439,7 @@ async def test_p2blsdohp_execute_signing_instructions(wallet_environments: Walle signing_responses = await wallet.execute_signing_instructions( SigningInstructions( KeyHints( - [SumHint([root_fingerprint], test_name, bytes(sum_pk))], + [SumHint([root_fingerprint], test_name, sum_pk)], [], ), [SigningTarget(sum_pk.get_fingerprint().to_bytes(4, "big"), test_name, test_name)], diff --git a/chia/consensus/block_body_validation.py b/chia/consensus/block_body_validation.py index bea455018549..03257b5a6e64 100644 --- a/chia/consensus/block_body_validation.py +++ b/chia/consensus/block_body_validation.py @@ -5,6 +5,7 @@ from dataclasses import dataclass, field from typing import Awaitable, Callable, Dict, List, Optional, Set, Tuple, Union +from chia_rs import G1Element from chiabip158 import PyBIP158 from chia.consensus.block_record import BlockRecord @@ -19,7 +20,7 @@ from chia.full_node.mempool_check_conditions import mempool_check_time_locks from chia.types.block_protocol import BlockInfo from chia.types.blockchain_format.coin import Coin -from chia.types.blockchain_format.sized_bytes import bytes32, bytes48 +from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.coin_record import CoinRecord from chia.types.full_block import FullBlock from chia.types.generator_types import BlockGenerator @@ -512,7 +513,7 @@ async def validate_block_body( return error, None # create hash_key list for aggsig check - pairs_pks: List[bytes48] = [] + pairs_pks: List[G1Element] = [] pairs_msgs: List[bytes] = [] if npc_result: assert npc_result.conds is not None diff --git a/chia/consensus/multiprocess_validation.py b/chia/consensus/multiprocess_validation.py index 6ec910d3f8a2..2fb06b1f8186 100644 --- a/chia/consensus/multiprocess_validation.py +++ b/chia/consensus/multiprocess_validation.py @@ -8,7 +8,7 @@ from dataclasses import dataclass from typing import Awaitable, Callable, Dict, List, Optional, Sequence, Tuple -from chia_rs import AugSchemeMPL, G1Element +from chia_rs import AugSchemeMPL from chia.consensus.block_header_validation import validate_finished_header_block from chia.consensus.block_record import BlockRecord @@ -126,10 +126,8 @@ def batch_pre_validate_blocks( if npc_result is not None and block.transactions_info is not None: assert npc_result.conds pairs_pks, pairs_msgs = pkm_pairs(npc_result.conds, constants.AGG_SIG_ME_ADDITIONAL_DATA) - # Using AugSchemeMPL.aggregate_verify, so it's safe to use from_bytes_unchecked - pks_objects: List[G1Element] = [G1Element.from_bytes_unchecked(pk) for pk in pairs_pks] if not AugSchemeMPL.aggregate_verify( - pks_objects, pairs_msgs, block.transactions_info.aggregated_signature + pairs_pks, pairs_msgs, block.transactions_info.aggregated_signature ): error_int = uint16(Err.BAD_AGGREGATE_SIGNATURE.value) else: diff --git a/chia/full_node/mempool_manager.py b/chia/full_node/mempool_manager.py index f4385fadd40a..3a7ad461fdeb 100644 --- a/chia/full_node/mempool_manager.py +++ b/chia/full_node/mempool_manager.py @@ -11,7 +11,7 @@ from chia_rs import ELIGIBLE_FOR_DEDUP, ELIGIBLE_FOR_FF from chia_rs import CoinSpend as RustCoinSpend -from chia_rs import GTElement +from chia_rs import G1Element, GTElement from chia_rs import Program as RustProgram from chia_rs import supports_fast_forward from chiabip158 import PyBIP158 @@ -27,7 +27,7 @@ from chia.full_node.mempool_check_conditions import get_name_puzzle_conditions, mempool_check_time_locks from chia.full_node.pending_tx_cache import ConflictTxCache, PendingTxCache from chia.types.blockchain_format.coin import Coin -from chia.types.blockchain_format.sized_bytes import bytes32, bytes48 +from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.clvm_cost import CLVMCost from chia.types.coin_record import CoinRecord from chia.types.eligible_coin_spends import EligibilityAndAdditions, UnspentLineageInfo @@ -78,7 +78,7 @@ def validate_clvm_and_signature( if result.error is not None: return Err(result.error), b"", {}, time.monotonic() - start_time - pks: List[bytes48] = [] + pks: List[G1Element] = [] msgs: List[bytes] = [] assert result.conds is not None pks, msgs = pkm_pairs(result.conds, additional_data) diff --git a/chia/util/cached_bls.py b/chia/util/cached_bls.py index b768fb7c507a..1eba5c248f48 100644 --- a/chia/util/cached_bls.py +++ b/chia/util/cached_bls.py @@ -1,22 +1,22 @@ from __future__ import annotations import functools -from typing import Dict, List, Optional, Sequence +from typing import List, Optional, Sequence from chia_rs import AugSchemeMPL, G1Element, G2Element, GTElement -from chia.types.blockchain_format.sized_bytes import bytes32, bytes48 +from chia.types.blockchain_format.sized_bytes import bytes32 from chia.util.hash import std_hash from chia.util.lru_cache import LRUCache def get_pairings( - cache: LRUCache[bytes32, GTElement], pks: List[bytes48], msgs: Sequence[bytes], force_cache: bool + cache: LRUCache[bytes32, GTElement], pks: List[G1Element], msgs: Sequence[bytes], force_cache: bool ) -> List[GTElement]: pairings: List[Optional[GTElement]] = [] missing_count: int = 0 for pk, msg in zip(pks, msgs): - aug_msg: bytes = pk + msg + aug_msg: bytes = bytes(pk) + msg h: bytes32 = std_hash(aug_msg) pairing: Optional[GTElement] = cache.get(h) if not force_cache and pairing is None: @@ -28,23 +28,12 @@ def get_pairings( return [] pairings.append(pairing) - # G1Element.from_bytes can be expensive due to subgroup check, so we avoid recomputing it with this cache - pk_bytes_to_g1: Dict[bytes48, G1Element] = {} ret: List[GTElement] = [] for i, pairing in enumerate(pairings): if pairing is None: - aug_msg = pks[i] + msgs[i] + aug_msg = bytes(pks[i]) + msgs[i] aug_hash: G2Element = AugSchemeMPL.g2_from_message(aug_msg) - - pk_parsed: Optional[G1Element] = pk_bytes_to_g1.get(pks[i]) - if pk_parsed is None: - # In this case, we use from_bytes instead of from_bytes_unchecked, because we will not be using - # the bls_signatures aggregate_verify method which performs the subgroup checks - pk_parsed = G1Element.from_bytes(pks[i]) - pk_bytes_to_g1[pks[i]] = pk_parsed - - pairing = aug_hash.pair(pk_parsed) - + pairing = aug_hash.pair(pks[i]) h = std_hash(aug_msg) cache.put(h, pairing) ret.append(pairing) @@ -58,7 +47,7 @@ def get_pairings( def aggregate_verify( - pks: List[bytes48], + pks: List[G1Element], msgs: Sequence[bytes], sig: G2Element, force_cache: bool = False, @@ -67,9 +56,7 @@ def aggregate_verify( pairings: List[GTElement] = get_pairings(cache, pks, msgs, force_cache) if len(pairings) == 0: # Using AugSchemeMPL.aggregate_verify, so it's safe to use from_bytes_unchecked - pks_objects: List[G1Element] = [G1Element.from_bytes_unchecked(pk) for pk in pks] - res: bool = AugSchemeMPL.aggregate_verify(pks_objects, msgs, sig) - return res + return AugSchemeMPL.aggregate_verify(pks, msgs, sig) pairings_prod: GTElement = functools.reduce(GTElement.__mul__, pairings) res = pairings_prod == sig.pair(G1Element.generator()) diff --git a/chia/util/condition_tools.py b/chia/util/condition_tools.py index 3fb21fd7e95b..e573992be4b4 100644 --- a/chia/util/condition_tools.py +++ b/chia/util/condition_tools.py @@ -3,12 +3,13 @@ from functools import lru_cache from typing import Callable, Dict, List, Tuple, Union +from chia_rs import G1Element from clvm.casts import int_from_bytes, int_to_bytes from chia.types.blockchain_format.coin import Coin from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.serialized_program import SerializedProgram -from chia.types.blockchain_format.sized_bytes import bytes32, bytes48 +from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.condition_opcodes import ConditionOpcode from chia.types.condition_with_args import ConditionWithArgs from chia.types.spend_bundle_conditions import Spend, SpendBundleConditions @@ -97,13 +98,13 @@ def make_aggsig_final_message( return msg + addendum + agg_sig_additional_data[opcode] -def pkm_pairs(conditions: SpendBundleConditions, additional_data: bytes) -> Tuple[List[bytes48], List[bytes]]: - ret: Tuple[List[bytes48], List[bytes]] = ([], []) +def pkm_pairs(conditions: SpendBundleConditions, additional_data: bytes) -> Tuple[List[G1Element], List[bytes]]: + ret: Tuple[List[G1Element], List[bytes]] = ([], []) data = agg_sig_additional_data(additional_data) for pk, msg in conditions.agg_sig_unsafe: - ret[0].append(bytes48(pk)) + ret[0].append(pk) ret[1].append(msg) for disallowed in data.values(): if msg.endswith(disallowed): @@ -121,7 +122,7 @@ def pkm_pairs(conditions: SpendBundleConditions, additional_data: bytes) -> Tupl ] for condition, items in condition_items_pairs: for pk, msg in items: - ret[0].append(bytes48(pk)) + ret[0].append(pk) ret[1].append(make_aggsig_final_message(condition, msg, spend, data)) return ret @@ -142,8 +143,8 @@ def pkm_pairs_for_conditions_dict( conditions_dict: Dict[ConditionOpcode, List[ConditionWithArgs]], coin: Coin, additional_data: bytes, -) -> List[Tuple[bytes48, bytes]]: - ret: List[Tuple[bytes48, bytes]] = [] +) -> List[Tuple[G1Element, bytes]]: + ret: List[Tuple[G1Element, bytes]] = [] data = agg_sig_additional_data(additional_data) @@ -152,7 +153,7 @@ def pkm_pairs_for_conditions_dict( for disallowed in data.values(): if cwa.vars[1].endswith(disallowed): raise ConsensusError(Err.INVALID_CONDITION) - ret.append((bytes48(cwa.vars[0]), cwa.vars[1])) + ret.append((G1Element.from_bytes(cwa.vars[0]), cwa.vars[1])) for opcode in [ ConditionOpcode.AGG_SIG_PARENT, @@ -165,7 +166,7 @@ def pkm_pairs_for_conditions_dict( ]: for cwa in conditions_dict.get(opcode, []): validate_cwa(cwa) - ret.append((bytes48(cwa.vars[0]), make_aggsig_final_message(opcode, cwa.vars[1], coin, data))) + ret.append((G1Element.from_bytes(cwa.vars[0]), make_aggsig_final_message(opcode, cwa.vars[1], coin, data))) return ret diff --git a/chia/wallet/signer_protocol.py b/chia/wallet/signer_protocol.py index 302dc0706f33..bd67644900f7 100644 --- a/chia/wallet/signer_protocol.py +++ b/chia/wallet/signer_protocol.py @@ -3,6 +3,8 @@ from dataclasses import dataclass from typing import List +from chia_rs import G1Element + from chia.types.blockchain_format.coin import Coin as _Coin from chia.types.blockchain_format.program import Program from chia.types.blockchain_format.serialized_program import SerializedProgram @@ -74,7 +76,7 @@ class SigningTarget(Streamable): class SumHint(Streamable): fingerprints: List[bytes] synthetic_offset: bytes - final_pubkey: bytes + final_pubkey: G1Element @clvm_streamable diff --git a/chia/wallet/util/debug_spend_bundle.py b/chia/wallet/util/debug_spend_bundle.py index 4165f50c8db1..9183387c2b77 100644 --- a/chia/wallet/util/debug_spend_bundle.py +++ b/chia/wallet/util/debug_spend_bundle.py @@ -2,7 +2,7 @@ from typing import List -from chia_rs import AugSchemeMPL, G1Element +from chia_rs import AugSchemeMPL from clvm import KEYWORD_FROM_ATOM from clvm_tools.binutils import disassemble as bu_disassemble @@ -106,8 +106,8 @@ def debug_spend_bundle(spend_bundle, agg_sig_additional_data=DEFAULT_CONSTANTS.A continue conditions = conditions_dict_for_solution(puzzle_reveal, solution, INFINITE_COST) - for pk_bytes, m in pkm_pairs_for_conditions_dict(conditions, coin, agg_sig_additional_data): - pks.append(G1Element.from_bytes(pk_bytes)) + for pk, m in pkm_pairs_for_conditions_dict(conditions, coin, agg_sig_additional_data): + pks.append(pk) msgs.append(m) print() cost, r = puzzle_reveal.run_with_cost(INFINITE_COST, solution) diff --git a/chia/wallet/wallet.py b/chia/wallet/wallet.py index 9e7ae3c7eb12..ec47f55db2aa 100644 --- a/chia/wallet/wallet.py +++ b/chia/wallet/wallet.py @@ -513,10 +513,9 @@ async def match_hinted_coin(self, coin: Coin, hint: bytes32) -> bool: return True return False - async def sum_hint_for_pubkey(self, pk: bytes) -> Optional[SumHint]: - pk_parsed: G1Element = G1Element.from_bytes(pk) + async def sum_hint_for_pubkey(self, pk: G1Element) -> Optional[SumHint]: dr: Optional[DerivationRecord] = await self.wallet_state_manager.puzzle_store.record_for_puzzle_hash( - puzzle_hash_for_synthetic_public_key(pk_parsed) + puzzle_hash_for_synthetic_public_key(pk) ) if dr is None: return None @@ -526,12 +525,11 @@ async def sum_hint_for_pubkey(self, pk: bytes) -> Optional[SumHint]: pk, ) - async def path_hint_for_pubkey(self, pk: bytes) -> Optional[PathHint]: - pk_parsed: G1Element = G1Element.from_bytes(pk) - index: Optional[uint32] = await self.wallet_state_manager.puzzle_store.index_for_pubkey(pk_parsed) + async def path_hint_for_pubkey(self, pk: G1Element) -> Optional[PathHint]: + index: Optional[uint32] = await self.wallet_state_manager.puzzle_store.index_for_pubkey(pk) if index is None: index = await self.wallet_state_manager.puzzle_store.index_for_puzzle_hash( - puzzle_hash_for_synthetic_public_key(pk_parsed) + puzzle_hash_for_synthetic_public_key(pk) ) root_pubkey: bytes = self.wallet_state_manager.root_pubkey.get_fingerprint().to_bytes(4, "big") if index is None: @@ -541,7 +539,7 @@ async def path_hint_for_pubkey(self, pk: bytes) -> Optional[PathHint]: try_owner_sk = master_sk_to_singleton_owner_sk( self.wallet_state_manager.private_key, uint32(pool_wallet_index) ) - if try_owner_sk.get_g1() == pk_parsed: + if try_owner_sk.get_g1() == pk: return PathHint( root_pubkey, [uint64(12381), uint64(8444), uint64(5), uint64(pool_wallet_index)], @@ -611,7 +609,7 @@ async def execute_signing_instructions( offset_pk = offset_sk.get_g1() pk_lookup[offset_pk.get_fingerprint()] = offset_pk sk_lookup[offset_pk.get_fingerprint()] = offset_sk - final_pubkey: G1Element = G1Element.from_bytes(sum_hint.final_pubkey) + final_pubkey: G1Element = sum_hint.final_pubkey final_fingerprint: int = final_pubkey.get_fingerprint() pk_lookup[final_fingerprint] = final_pubkey sum_hint_lookup[final_fingerprint] = [*fingerprints_we_have, offset_pk.get_fingerprint()] diff --git a/chia/wallet/wallet_state_manager.py b/chia/wallet/wallet_state_manager.py index 8a0993f1b8b8..035d7c3d3233 100644 --- a/chia/wallet/wallet_state_manager.py +++ b/chia/wallet/wallet_state_manager.py @@ -2588,20 +2588,20 @@ async def get_or_create_vc_wallet(self) -> VCWallet: return vc_wallet - async def sum_hint_for_pubkey(self, pk: bytes) -> Optional[SumHint]: + async def sum_hint_for_pubkey(self, pk: G1Element) -> Optional[SumHint]: return await self.main_wallet.sum_hint_for_pubkey(pk) - async def path_hint_for_pubkey(self, pk: bytes) -> Optional[PathHint]: + async def path_hint_for_pubkey(self, pk: G1Element) -> Optional[PathHint]: return await self.main_wallet.path_hint_for_pubkey(pk) - async def key_hints_for_pubkeys(self, pks: List[bytes]) -> KeyHints: + async def key_hints_for_pubkeys(self, pks: List[G1Element]) -> KeyHints: return KeyHints( [sum_hint for pk in pks for sum_hint in (await self.sum_hint_for_pubkey(pk),) if sum_hint is not None], [path_hint for pk in pks for path_hint in (await self.path_hint_for_pubkey(pk),) if path_hint is not None], ) async def gather_signing_info(self, coin_spends: List[Spend]) -> SigningInstructions: - pks: List[bytes] = [] + pks: List[G1Element] = [] signing_targets: List[SigningTarget] = [] for coin_spend in coin_spends: _coin_spend = coin_spend.as_coin_spend() @@ -2612,12 +2612,12 @@ async def gather_signing_info(self, coin_spends: List[Spend]) -> SigningInstruct self.constants.MAX_BLOCK_COST_CLVM, ) # Create signature - for pk_bytes, msg in pkm_pairs_for_conditions_dict( + for pk, msg in pkm_pairs_for_conditions_dict( conditions_dict, _coin_spend.coin, self.constants.AGG_SIG_ME_ADDITIONAL_DATA ): - pks.append(pk_bytes) - fingerprint: bytes = G1Element.from_bytes(pk_bytes).get_fingerprint().to_bytes(4, "big") - signing_targets.append(SigningTarget(fingerprint, msg, std_hash(pk_bytes + msg))) + pks.append(pk) + fingerprint: bytes = pk.get_fingerprint().to_bytes(4, "big") + signing_targets.append(SigningTarget(fingerprint, msg, std_hash(bytes(pk) + msg))) return SigningInstructions( await self.key_hints_for_pubkeys(pks), diff --git a/setup.py b/setup.py index 07ecce017572..3d7e4cabdc18 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ "chiapos==2.0.4", # proof of space "clvm==0.9.9", "clvm_tools==0.4.9", # Currying, Program.to, other conveniences - "chia_rs==0.7.0", + "chia_rs==0.8.0", "clvm-tools-rs==0.1.40", # Rust implementation of clvm_tools' compiler "aiohttp==3.9.4", # HTTP server for full node rpc "aiosqlite==0.20.0", # asyncio wrapper for sqlite, to store blocks diff --git a/tools/analyze-chain.py b/tools/analyze-chain.py index e330f14e7822..eb736e81dd84 100755 --- a/tools/analyze-chain.py +++ b/tools/analyze-chain.py @@ -16,7 +16,7 @@ from chia.consensus.default_constants import DEFAULT_CONSTANTS from chia.types.block_protocol import BlockInfo from chia.types.blockchain_format.serialized_program import SerializedProgram -from chia.types.blockchain_format.sized_bytes import bytes32, bytes48 +from chia.types.blockchain_format.sized_bytes import bytes32 from chia.types.full_block import FullBlock from chia.util.condition_tools import pkm_pairs from chia.util.full_block_utils import block_info_from_block, generator_from_block @@ -137,13 +137,12 @@ def default_call( if verify_signatures: assert isinstance(block, FullBlock) # create hash_key list for aggsig check - pairs_pks: List[bytes48] = [] + pairs_pks: List[G1Element] = [] pairs_msgs: List[bytes] = [] pairs_pks, pairs_msgs = pkm_pairs(result, DEFAULT_CONSTANTS.AGG_SIG_ME_ADDITIONAL_DATA) - pairs_g1s = [G1Element.from_bytes(x) for x in pairs_pks] assert block.transactions_info is not None assert block.transactions_info.aggregated_signature is not None - assert AugSchemeMPL.aggregate_verify(pairs_g1s, pairs_msgs, block.transactions_info.aggregated_signature) + assert AugSchemeMPL.aggregate_verify(pairs_pks, pairs_msgs, block.transactions_info.aggregated_signature) print( f"{hh.hex()}\t{height:7d}\t{cost:11d}\t{run_time:0.3f}\t{num_refs}\t{ref_lookup_time:0.3f}\t{fees:14}\t"