Skip to content

Commit

Permalink
[CHIA-714] Add usage of action scope throughout wallet codebase (#18128)
Browse files Browse the repository at this point in the history
* Add the concept of 'action scopes'

* Add `WalletActionScope`

* Fix CATWallet pending_change calculation

* Add action_scope: WalletActionScope to all tx endpoints

* Add usage of action scope throughout wallet codebase

* Add the concept of 'action scopes'

* pylint and test coverage

* add try/finally

* add try/except

* Undo giving a variable a name

* Fix CRCAT test

* Fix trade tests

* Fix cat test

* Fix miscellaneous test

* Fix miscellaneous test

* Fix miscellaneous test

* pylint

* Add auto claim test coverage

* Take advantage of extra_spends

* Fix tests

* test fixes

* pylint
  • Loading branch information
Quexington authored Jul 17, 2024
1 parent f48660c commit 0555889
Show file tree
Hide file tree
Showing 46 changed files with 2,687 additions and 3,480 deletions.
42 changes: 22 additions & 20 deletions chia/_tests/core/full_node/test_full_node.py
Original file line number Diff line number Diff line change
Expand Up @@ -185,14 +185,14 @@ async def test_block_compression(self, setup_two_nodes_and_wallet, empty_blockch
await full_node_1.wait_for_wallet_synced(wallet_node=wallet_node_1, timeout=30)

# Send a transaction to mempool
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tr] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope:
await wallet.generate_signed_transaction(
tx_size,
ph,
DEFAULT_TX_CONFIG,
action_scope,
)
[tr] = await wallet.wallet_state_manager.add_pending_transactions([tr])
[tr] = action_scope.side_effects.transactions
await time_out_assert(
10,
full_node_2.full_node.mempool_manager.get_spendbundle,
Expand All @@ -219,14 +219,14 @@ async def check_transaction_confirmed(transaction) -> bool:
assert len((await full_node_1.get_all_full_blocks())[-1].transactions_generator_ref_list) == 0

# Send another tx
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tr] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope:
await wallet.generate_signed_transaction(
20000,
ph,
DEFAULT_TX_CONFIG,
action_scope,
)
[tr] = await wallet.wallet_state_manager.add_pending_transactions([tr])
[tr] = action_scope.side_effects.transactions
await time_out_assert(
10,
full_node_2.full_node.mempool_manager.get_spendbundle,
Expand Down Expand Up @@ -260,58 +260,58 @@ async def check_transaction_confirmed(transaction) -> bool:
await full_node_1.wait_for_wallet_synced(wallet_node=wallet_node_1, timeout=30)

# Send another 2 tx
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tr] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope:
await wallet.generate_signed_transaction(
30000,
ph,
DEFAULT_TX_CONFIG,
action_scope,
)
[tr] = await wallet.wallet_state_manager.add_pending_transactions([tr])
[tr] = action_scope.side_effects.transactions
await time_out_assert(
10,
full_node_2.full_node.mempool_manager.get_spendbundle,
tr.spend_bundle,
tr.name,
)
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tr] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope:
await wallet.generate_signed_transaction(
40000,
ph,
DEFAULT_TX_CONFIG,
action_scope,
)
[tr] = await wallet.wallet_state_manager.add_pending_transactions([tr])
[tr] = action_scope.side_effects.transactions
await time_out_assert(
10,
full_node_2.full_node.mempool_manager.get_spendbundle,
tr.spend_bundle,
tr.name,
)

async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tr] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope:
await wallet.generate_signed_transaction(
50000,
ph,
DEFAULT_TX_CONFIG,
action_scope,
)
[tr] = await wallet.wallet_state_manager.add_pending_transactions([tr])
[tr] = action_scope.side_effects.transactions
await time_out_assert(
10,
full_node_2.full_node.mempool_manager.get_spendbundle,
tr.spend_bundle,
tr.name,
)

async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tr] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=True) as action_scope:
await wallet.generate_signed_transaction(
3000000000000,
ph,
DEFAULT_TX_CONFIG,
action_scope,
)
[tr] = await wallet.wallet_state_manager.add_pending_transactions([tr])
[tr] = action_scope.side_effects.transactions
await time_out_assert(
10,
full_node_2.full_node.mempool_manager.get_spendbundle,
Expand All @@ -338,12 +338,13 @@ async def check_transaction_confirmed(transaction) -> bool:

# Creates a standard_transaction and an anyone-can-spend tx
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tr] = await wallet.generate_signed_transaction(
await wallet.generate_signed_transaction(
30000,
Program.to(1).get_tree_hash(),
DEFAULT_TX_CONFIG,
action_scope,
)
[tr] = action_scope.side_effects.transactions
extra_spend = SpendBundle(
[
make_spend(
Expand Down Expand Up @@ -386,12 +387,13 @@ async def check_transaction_confirmed(transaction) -> bool:

# Make a standard transaction and an anyone-can-spend transaction
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tr] = await wallet.generate_signed_transaction(
await wallet.generate_signed_transaction(
30000,
Program.to(1).get_tree_hash(),
DEFAULT_TX_CONFIG,
action_scope,
)
[tr] = action_scope.side_effects.transactions
extra_spend = SpendBundle(
[
make_spend(
Expand Down
12 changes: 6 additions & 6 deletions chia/_tests/core/full_node/test_transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ async def peak_height(fna: FullNodeAPI):
await time_out_assert(20, peak_height, num_blocks, full_node_api_1)
await time_out_assert(20, peak_height, num_blocks, full_node_api_2)

async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tx] = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(
async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope:
await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(
10, ph1, DEFAULT_TX_CONFIG, action_scope, 0
)
[tx] = await wallet_0.wallet_state_manager.add_pending_transactions([tx])
[tx] = action_scope.side_effects.transactions

await time_out_assert(
10,
Expand Down Expand Up @@ -155,11 +155,11 @@ async def test_mempool_tx_sync(self, three_nodes_two_wallets, self_hostname, see
)
await time_out_assert(20, wallet_0.wallet_state_manager.main_wallet.get_confirmed_balance, funds)

async with wallet_0.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tx] = await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(
async with wallet_0.wallet_state_manager.new_action_scope(push=True) as action_scope:
await wallet_0.wallet_state_manager.main_wallet.generate_signed_transaction(
10, bytes32.random(seeded_random), DEFAULT_TX_CONFIG, action_scope, 0
)
[tx] = await wallet_0.wallet_state_manager.add_pending_transactions([tx])
[tx] = action_scope.side_effects.transactions

await time_out_assert(
10,
Expand Down
42 changes: 18 additions & 24 deletions chia/_tests/core/mempool/test_mempool_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -1622,11 +1622,11 @@ async def make_setup_and_coins(
for _ in range(2):
await farm_a_block(full_node_api, wallet_node, ph)
other_recipients = [Payment(puzzle_hash=p, amount=uint64(200), memos=[]) for p in phs[1:]]
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tx] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=False, sign=True) as action_scope:
await wallet.generate_signed_transaction(
uint64(200), phs[0], DEFAULT_TX_CONFIG, action_scope, primaries=other_recipients
)
[tx], _ = await wallet.wallet_state_manager.sign_transactions([tx])
[tx] = action_scope.side_effects.transactions
assert tx.spend_bundle is not None
await send_to_mempool(full_node_api, tx.spend_bundle)
await farm_a_block(full_node_api, wallet_node, ph)
Expand All @@ -1641,17 +1641,11 @@ async def make_setup_and_coins(
wallet, coins, ph = await make_setup_and_coins(full_node_api, wallet_node)

# Make sure spending AB then BC would generate a conflict for the latter
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tx_a] = await wallet.generate_signed_transaction(
uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[0].coin}
)
[tx_b] = await wallet.generate_signed_transaction(
uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[1].coin}
)
[tx_c] = await wallet.generate_signed_transaction(
uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[2].coin}
)
[tx_a, tx_b, tx_c], _ = await wallet.wallet_state_manager.sign_transactions([tx_a, tx_b, tx_c])
async with wallet.wallet_state_manager.new_action_scope(push=False, merge_spends=False, sign=True) as action_scope:
await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[0].coin})
await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[1].coin})
await wallet.generate_signed_transaction(uint64(30), ph, DEFAULT_TX_CONFIG, action_scope, coins={coins[2].coin})
[tx_a, tx_b, tx_c] = action_scope.side_effects.transactions
assert tx_a.spend_bundle is not None
assert tx_b.spend_bundle is not None
assert tx_c.spend_bundle is not None
Expand All @@ -1665,11 +1659,11 @@ async def make_setup_and_coins(
# Make sure DE and EF would aggregate on E when E is eligible for deduplication

# Create a coin with the identity puzzle hash
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tx] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=False, merge_spends=False, sign=True) as action_scope:
await wallet.generate_signed_transaction(
uint64(200), IDENTITY_PUZZLE_HASH, DEFAULT_TX_CONFIG, action_scope, coins={coins[3].coin}
)
[tx], _ = await wallet.wallet_state_manager.sign_transactions([tx])
[tx] = action_scope.side_effects.transactions
assert tx.spend_bundle is not None
await send_to_mempool(full_node_api, tx.spend_bundle)
await farm_a_block(full_node_api, wallet_node, ph)
Expand All @@ -1691,8 +1685,8 @@ async def make_setup_and_coins(
message = b"Identical spend aggregation test"
e_announcement = AssertCoinAnnouncement(asserted_id=e_coin_id, asserted_msg=message)
# Create transactions D and F that consume an announcement created by E
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tx_d] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=False, merge_spends=False, sign=True) as action_scope:
await wallet.generate_signed_transaction(
uint64(100),
ph,
DEFAULT_TX_CONFIG,
Expand All @@ -1701,7 +1695,7 @@ async def make_setup_and_coins(
coins={coins[4].coin},
extra_conditions=(e_announcement,),
)
[tx_f] = await wallet.generate_signed_transaction(
await wallet.generate_signed_transaction(
uint64(150),
ph,
DEFAULT_TX_CONFIG,
Expand All @@ -1710,7 +1704,7 @@ async def make_setup_and_coins(
coins={coins[5].coin},
extra_conditions=(e_announcement,),
)
[tx_d, tx_f], _ = await wallet.wallet_state_manager.sign_transactions([tx_d, tx_f])
[tx_d, tx_f] = action_scope.side_effects.transactions
assert tx_d.spend_bundle is not None
assert tx_f.spend_bundle is not None
# Create transaction E now that spends e_coin to create another eligible
Expand All @@ -1736,11 +1730,11 @@ async def make_setup_and_coins(
sb_e2 = spend_bundle_from_conditions(conditions, e_coin)
g_coin = coins[6].coin
g_coin_id = g_coin.name()
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[tx_g] = await wallet.generate_signed_transaction(
async with wallet.wallet_state_manager.new_action_scope(push=False, merge_spends=False, sign=True) as action_scope:
await wallet.generate_signed_transaction(
uint64(13), ph, DEFAULT_TX_CONFIG, action_scope, coins={g_coin}, extra_conditions=(e_announcement,)
)
[tx_g], _ = await wallet.wallet_state_manager.sign_transactions([tx_g])
[tx_g] = action_scope.side_effects.transactions
assert tx_g.spend_bundle is not None
sb_e2g = SpendBundle.aggregate([sb_e2, tx_g.spend_bundle])
sb_e2g_name = sb_e2g.name()
Expand Down
8 changes: 3 additions & 5 deletions chia/_tests/core/mempool/test_mempool_performance.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,9 @@ async def test_mempool_update_performance(
await time_out_assert(30, wallet_balance_at_least, True, wallet_node, send_amount + fee_amount)

ph = await wallet.get_new_puzzlehash()
async with wallet.wallet_state_manager.new_action_scope(push=False) as action_scope:
[big_transaction] = await wallet.generate_signed_transaction(
send_amount, ph, DEFAULT_TX_CONFIG, action_scope, fee_amount
)
[big_transaction], _ = await wallet.wallet_state_manager.sign_transactions([big_transaction])
async with wallet.wallet_state_manager.new_action_scope(push=False, sign=True) as action_scope:
await wallet.generate_signed_transaction(send_amount, ph, DEFAULT_TX_CONFIG, action_scope, fee_amount)
[big_transaction] = action_scope.side_effects.transactions
assert big_transaction.spend_bundle is not None
status, err = await full_node.add_transaction(
big_transaction.spend_bundle, big_transaction.spend_bundle.name(), test=True
Expand Down
23 changes: 11 additions & 12 deletions chia/_tests/pools/test_pool_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -533,8 +533,8 @@ async def test_absorb_self_multiple_coins(
assert bal["confirmed_wallet_balance"] == pool_expected_confirmed_balance

# Claim
absorb_tx: TransactionRecord = (await client.pw_absorb_rewards(2, uint64(fee), 1))["transaction"]
await full_node_api.process_transaction_records(records=[absorb_tx])
absorb_txs: List[TransactionRecord] = (await client.pw_absorb_rewards(2, uint64(fee), 1))["transactions"]
await full_node_api.process_transaction_records(records=absorb_txs)
main_expected_confirmed_balance -= fee
main_expected_confirmed_balance += 1_750_000_000_000
pool_expected_confirmed_balance -= 1_750_000_000_000
Expand Down Expand Up @@ -602,13 +602,14 @@ async def farming_to_pool() -> bool:

# Claim block_count * 1.75
ret = await client.pw_absorb_rewards(2, uint64(fee))
absorb_tx: TransactionRecord = ret["transaction"]
absorb_txs: List[TransactionRecord] = ret["transactions"]
if fee == 0:
assert ret["fee_transaction"] is None
else:
assert ret["fee_transaction"].fee_amount == fee
assert absorb_tx.fee_amount == fee
await full_node_api.process_transaction_records(records=[absorb_tx])
for tx in absorb_txs:
assert tx.fee_amount == fee
await full_node_api.process_transaction_records(records=absorb_txs)
main_expected_confirmed_balance -= fee
main_expected_confirmed_balance += block_count * 1_750_000_000_000

Expand Down Expand Up @@ -821,7 +822,7 @@ async def status_is_farming_to_pool() -> bool:
leave_pool_tx: Dict[str, Any] = await client.pw_self_pool(wallet_id, uint64(fee))
assert leave_pool_tx["transaction"].wallet_id == wallet_id
assert leave_pool_tx["transaction"].amount == 1
await full_node_api.wait_transaction_records_entered_mempool(records=[leave_pool_tx["transaction"]])
await full_node_api.wait_transaction_records_entered_mempool(records=leave_pool_tx["transactions"])

await full_node_api.farm_blocks_to_puzzlehash(count=1, farm_to=our_ph, guarantee_transaction_blocks=True)

Expand Down Expand Up @@ -897,7 +898,6 @@ async def status_is_farming_to_pool() -> bool:
assert pw_info.current.relative_lock_height == 5

await full_node_api.wait_for_wallet_synced(wallet_node=wallet_node, timeout=20)

join_pool_tx: TransactionRecord = (
await client.pw_join_pool(
wallet_id,
Expand Down Expand Up @@ -964,17 +964,16 @@ async def status_is_farming_to_pool() -> bool:
assert pw_info.current.pool_url == "https://pool-a.org"
assert pw_info.current.relative_lock_height == 5

join_pool_tx: TransactionRecord = (
join_pool_txs: List[TransactionRecord] = (
await client.pw_join_pool(
wallet_id,
pool_b_ph,
"https://pool-b.org",
uint32(10),
uint64(fee),
)
)["transaction"]
assert join_pool_tx is not None
await full_node_api.wait_transaction_records_entered_mempool(records=[join_pool_tx])
)["transactions"]
await full_node_api.wait_transaction_records_entered_mempool(records=join_pool_txs)
await full_node_api.farm_blocks_to_puzzlehash(count=1, farm_to=our_ph, guarantee_transaction_blocks=True)

async def status_is_leaving_no_blocks() -> bool:
Expand All @@ -992,7 +991,7 @@ async def status_is_leaving_no_blocks() -> bool:
force_overflow=True,
guarantee_transaction_block=True,
seed=32 * b"4",
transaction_data=join_pool_tx.spend_bundle,
transaction_data=next(tx.spend_bundle for tx in join_pool_txs if tx.spend_bundle is not None),
)

for block in more_blocks[-3:]:
Expand Down
Loading

0 comments on commit 0555889

Please sign in to comment.