move member function get_memos() out of SpendBundle and into a free-function living in the wallet code. It does not belong to the full node. Also rename it to indicate that it's expensive (and dangerous) to call (#9907)

This commit is contained in:
Arvid Norberg 2022-01-24 06:45:41 +01:00 committed by GitHub
parent 5f4e39480e
commit 77db90ba6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 58 additions and 44 deletions

View File

@ -2,20 +2,17 @@ import dataclasses
import warnings
from dataclasses import dataclass
from typing import List, Dict
from typing import List
from blspy import AugSchemeMPL, G2Element
from clvm.casts import int_from_bytes
from chia.consensus.default_constants import DEFAULT_CONSTANTS
from chia.types.blockchain_format.coin import Coin
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.util.streamable import Streamable, dataclass_from_dict, recurse_jsonify, streamable
from chia.wallet.util.debug_spend_bundle import debug_spend_bundle
from .blockchain_format.program import Program
from .coin_spend import CoinSpend
from .condition_opcodes import ConditionOpcode
@dataclass(frozen=True)
@ -80,27 +77,6 @@ class SpendBundle(Streamable):
return result
def get_memos(self) -> Dict[bytes32, List[bytes]]:
"""
Retrieves the memos for additions in this spend_bundle, which are formatted as a list in the 3rd parameter of
CREATE_COIN. If there are no memos, the addition coin_id is not included. If they are not formatted as a list
of bytes, they are not included. This is expensive to call, it should not be used in full node code.
"""
memos: Dict[bytes32, List[bytes]] = {}
for coin_spend in self.coin_spends:
result = Program.from_bytes(bytes(coin_spend.puzzle_reveal)).run(
Program.from_bytes(bytes(coin_spend.solution))
)
for condition in result.as_python():
if condition[0] == ConditionOpcode.CREATE_COIN and len(condition) >= 4:
# If only 3 elements (opcode + 2 args), there is no memo, this is ph, amount
coin_added = Coin(coin_spend.coin.name(), bytes32(condition[1]), int_from_bytes(condition[2]))
if type(condition[3]) != list:
# If it's not a list, it's not the correct format
continue
memos[coin_added.name()] = condition[3]
return memos
# Note that `coin_spends` used to have the bad name `coin_solutions`.
# Some API still expects this name. For now, we accept both names.
#

View File

@ -46,6 +46,7 @@ from chia.wallet.util.wallet_types import WalletType, AmountWithPuzzlehash
from chia.wallet.wallet import Wallet
from chia.wallet.wallet_coin_record import WalletCoinRecord
from chia.wallet.wallet_info import WalletInfo
from chia.wallet.util.compute_memos import compute_memos
# This should probably not live in this file but it's for experimental right now
@ -720,7 +721,7 @@ class CATWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=spend_bundle.name(),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
]

View File

@ -20,6 +20,7 @@ from chia.wallet.did_wallet.did_info import DIDInfo
from chia.wallet.lineage_proof import LineageProof
from chia.wallet.transaction_record import TransactionRecord
from chia.wallet.util.wallet_types import WalletType
from chia.wallet.util.compute_memos import compute_memos
from chia.wallet.wallet import Wallet
from chia.wallet.wallet_coin_record import WalletCoinRecord
from chia.wallet.wallet_info import WalletInfo
@ -129,7 +130,7 @@ class DIDWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=bytes32(token_bytes()),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(regular_record)
await self.standard_wallet.push_transaction(did_record)
@ -513,7 +514,7 @@ class DIDWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=token_bytes(),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
return spend_bundle
@ -582,7 +583,7 @@ class DIDWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=bytes32(token_bytes()),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
return spend_bundle
@ -649,7 +650,7 @@ class DIDWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=bytes32(token_bytes()),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
return spend_bundle
@ -718,7 +719,7 @@ class DIDWallet:
trade_id=None,
type=uint32(TransactionType.INCOMING_TX.value),
name=bytes32(token_bytes()),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
if filename is not None:
@ -859,7 +860,7 @@ class DIDWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=bytes32(token_bytes()),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
await self.standard_wallet.push_transaction(did_record)
new_did_info = DIDInfo(

View File

@ -29,6 +29,7 @@ from chia.wallet.rl_wallet.rl_wallet_puzzles import (
from chia.wallet.transaction_record import TransactionRecord
from chia.wallet.util.transaction_type import TransactionType
from chia.wallet.util.wallet_types import WalletType
from chia.wallet.util.compute_memos import compute_memos
from chia.wallet.wallet import Wallet
from chia.wallet.wallet_coin_record import WalletCoinRecord
from chia.wallet.wallet_info import WalletInfo
@ -320,7 +321,7 @@ class RLWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=spend_bundle.name(),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
asyncio.create_task(self.push_transaction(tx_record))
@ -546,7 +547,7 @@ class RLWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=spend_bundle.name(),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
async def rl_sign_transaction(self, spends: List[CoinSpend]) -> SpendBundle:
@ -623,7 +624,7 @@ class RLWallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=spend_bundle.name(),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
# This is for using the AC locked coin and aggregating it into wallet - must happen in same block as RL Mode 2

View File

@ -0,0 +1,28 @@
from typing import List, Dict
from clvm.casts import int_from_bytes
from chia.types.blockchain_format.program import Program
from chia.types.spend_bundle import SpendBundle
from chia.types.blockchain_format.sized_bytes import bytes32
from chia.types.blockchain_format.coin import Coin
from chia.types.condition_opcodes import ConditionOpcode
def compute_memos(bundle: SpendBundle) -> Dict[bytes32, List[bytes]]:
"""
Retrieves the memos for additions in this spend_bundle, which are formatted as a list in the 3rd parameter of
CREATE_COIN. If there are no memos, the addition coin_id is not included. If they are not formatted as a list
of bytes, they are not included. This is expensive to call, it should not be used in full node code.
"""
memos: Dict[bytes32, List[bytes]] = {}
for coin_spend in bundle.coin_spends:
result = Program.from_bytes(bytes(coin_spend.puzzle_reveal)).run(Program.from_bytes(bytes(coin_spend.solution)))
for condition in result.as_python():
if condition[0] == ConditionOpcode.CREATE_COIN and len(condition) >= 4:
# If only 3 elements (opcode + 2 args), there is no memo, this is ph, amount
coin_added = Coin(coin_spend.coin.name(), bytes32(condition[1]), int_from_bytes(condition[2]))
if type(condition[3]) != list:
# If it's not a list, it's not the correct format
continue
memos[coin_added.name()] = condition[3]
return memos

View File

@ -40,6 +40,7 @@ from chia.wallet.util.transaction_type import TransactionType
from chia.wallet.util.wallet_types import WalletType, AmountWithPuzzlehash
from chia.wallet.wallet_coin_record import WalletCoinRecord
from chia.wallet.wallet_info import WalletInfo
from chia.wallet.util.compute_memos import compute_memos
class Wallet:
@ -485,7 +486,7 @@ class Wallet:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=spend_bundle.name(),
memos=list(spend_bundle.get_memos().items()),
memos=list(compute_memos(spend_bundle).items()),
)
async def push_transaction(self, tx: TransactionRecord) -> None:

View File

@ -31,6 +31,7 @@ from chia.wallet.cat_wallet.cat_constants import DEFAULT_CATS
from chia.wallet.trading.trade_status import TradeStatus
from chia.wallet.transaction_record import TransactionRecord
from chia.wallet.transaction_sorting import SortKey
from chia.wallet.util.compute_memos import compute_memos
from tests.setup_nodes import bt, setup_simulators_and_wallets, self_hostname
from tests.time_out_assert import time_out_assert
@ -293,7 +294,7 @@ class TestWalletRpc:
addition.parent_coin_info, cr.confirmed_block_index
)
sb: SpendBundle = SpendBundle([spend], G2Element())
assert sb.get_memos() == {addition.name(): [b"hhh"]}
assert compute_memos(sb) == {addition.name(): [b"hhh"]}
found = True
assert found
@ -364,12 +365,16 @@ class TestWalletRpc:
# Checks that the memo can be retrieved
tx_confirmed = await client.get_transaction("1", send_tx_res.name)
assert tx_confirmed.confirmed
assert len(tx_confirmed.get_memos()) == 2
print(tx_confirmed.get_memos())
assert [b"FiMemo"] in tx_confirmed.get_memos().values()
assert [b"SeMemo"] in tx_confirmed.get_memos().values()
assert list(tx_confirmed.get_memos().keys())[0] in [a.name() for a in send_tx_res.spend_bundle.additions()]
assert list(tx_confirmed.get_memos().keys())[1] in [a.name() for a in send_tx_res.spend_bundle.additions()]
if isinstance(tx_confirmed, SpendBundle):
memos = compute_memos(tx_confirmed)
else:
memos = tx_confirmed.get_memos()
assert len(memos) == 2
print(memos)
assert [b"FiMemo"] in memos.values()
assert [b"SeMemo"] in memos.values()
assert list(memos.keys())[0] in [a.name() for a in send_tx_res.spend_bundle.additions()]
assert list(memos.keys())[1] in [a.name() for a in send_tx_res.spend_bundle.additions()]
##############
# CATS #

View File

@ -11,6 +11,7 @@ from chia.types.peer_info import PeerInfo
from chia.util.ints import uint16, uint32, uint64
from chia.wallet.derive_keys import master_sk_to_wallet_sk
from chia.wallet.util.transaction_type import TransactionType
from chia.wallet.util.compute_memos import compute_memos
from chia.wallet.transaction_record import TransactionRecord
from chia.wallet.wallet_node import WalletNode
from chia.wallet.wallet_state_manager import WalletStateManager
@ -617,7 +618,7 @@ class TestWalletSimulator:
trade_id=None,
type=uint32(TransactionType.OUTGOING_TX.value),
name=name,
memos=list(stolen_sb.get_memos().items()),
memos=list(compute_memos(stolen_sb).items()),
)
await wallet.push_transaction(stolen_tx)