Skip to content

feat: implement batching for multiple extrinsic calls to reduce trans…#764

Closed
mimalsm wants to merge 4 commits intoopentensor:stagingfrom
mimalsm:feature/batch-extrinsics
Closed

feat: implement batching for multiple extrinsic calls to reduce trans…#764
mimalsm wants to merge 4 commits intoopentensor:stagingfrom
mimalsm:feature/batch-extrinsics

Conversation

@mimalsm
Copy link

@mimalsm mimalsm commented Dec 16, 2025

…action fees

This commit implements comprehensive batching support for CLI commands that can submit multiple extrinsic calls, significantly reducing transaction fees for users. This addresses GitHub issue #567.

Core Changes:

  1. New Batching Interface (subtensor_interface.py)

    • Added sign_and_send_batch_extrinsic() method to support batching multiple GenericCall objects into a single transaction
    • Supports three batch types: 'batch', 'batch_all', and 'force_batch'
    • Defaults to 'batch_all' to ensure atomicity (all succeed or all fail)
    • Fully integrates with existing features: MEV protection, proxy transactions, era management, and nonce handling
    • Returns detailed results including success status, extrinsic receipt, and individual call results
  2. Stake Add Command Refactoring (stake/add.py)

    • Refactored to collect multiple stake operations (across different netuids and/or hotkeys) into a single batch transaction
    • Automatically uses batching when multiple --netuid or --hotkey arguments are provided
    • Optimized balance fetching using asyncio.gather for parallel queries
    • Enhanced display to show:
      • Individual stake changes per netuid/hotkey combination
      • Final coldkey balance change (previous_balance -> current_balance) * Clear visual feedback for each operation in the batch
  3. Stake Remove Command Refactoring (stake/remove.py)

    • Refactored unstake() to batch multiple remove_stake operations
    • Refactored unstake_all() to batch multiple unstake_all operations
    • Supports batching when:
      • Multiple --netuid arguments are provided
      • Multiple --hotkey arguments are provided * --include-hotkeys with multiple hotkeys is used
    • Optimized stake balance fetching using asyncio.gather
    • Enhanced display to show:
      • Individual unstake changes per netuid/hotkey
      • Remaining stake balances after operations * Final coldkey balance change (previous_balance -> current_balance)
    • Captures initial balance at function start for accurate display
  4. CLI Validation Updates (cli.py)

    • Removed restriction preventing unstake_all with multiple --include-hotkeys
    • Updated logic to properly initialize wallet when include_hotkeys is provided
    • Now supports batching unstake_all operations across multiple hotkeys

Technical Details:

  • Batch Type: Uses Utility.batch_all by default, ensuring atomic execution
  • Fee Savings: Multiple operations combined into single transaction fee
  • Backward Compatibility: Single operations still work as before (no batching)
  • Error Handling: batch_all ensures all operations succeed or fail together
  • Display Consistency: Balance changes shown consistently across all stake operations

Benefits:

  • Significant fee reduction when performing multiple stake/unstake operations
  • Improved user experience with clear feedback on all operations
  • Atomic operations prevent partial failures
  • Maintains all existing functionality (MEV protection, proxy, etc.)

Closes #567

…action fees

This commit implements comprehensive batching support for CLI commands that
can submit multiple extrinsic calls, significantly reducing transaction fees
for users. This addresses GitHub issue opentensor#567.

Core Changes:
=============

1. New Batching Interface (subtensor_interface.py)
   - Added sign_and_send_batch_extrinsic() method to support batching multiple
     GenericCall objects into a single transaction
   - Supports three batch types: 'batch', 'batch_all', and 'force_batch'
   - Defaults to 'batch_all' to ensure atomicity (all succeed or all fail)
   - Fully integrates with existing features: MEV protection, proxy transactions,
     era management, and nonce handling
   - Returns detailed results including success status, extrinsic receipt, and
     individual call results

2. Stake Add Command Refactoring (stake/add.py)
   - Refactored to collect multiple stake operations (across different netuids
     and/or hotkeys) into a single batch transaction
   - Automatically uses batching when multiple --netuid or --hotkey arguments
     are provided
   - Optimized balance fetching using asyncio.gather for parallel queries
   - Enhanced display to show:
     * Individual stake changes per netuid/hotkey combination
     * Final coldkey balance change (previous_balance -> current_balance)
     * Clear visual feedback for each operation in the batch

3. Stake Remove Command Refactoring (stake/remove.py)
   - Refactored unstake() to batch multiple remove_stake operations
   - Refactored unstake_all() to batch multiple unstake_all operations
   - Supports batching when:
     * Multiple --netuid arguments are provided
     * Multiple --hotkey arguments are provided
     * --include-hotkeys with multiple hotkeys is used
   - Optimized stake balance fetching using asyncio.gather
   - Enhanced display to show:
     * Individual unstake changes per netuid/hotkey
     * Remaining stake balances after operations
     * Final coldkey balance change (previous_balance -> current_balance)
   - Captures initial balance at function start for accurate display

4. CLI Validation Updates (cli.py)
   - Removed restriction preventing unstake_all with multiple --include-hotkeys
   - Updated logic to properly initialize wallet when include_hotkeys is provided
   - Now supports batching unstake_all operations across multiple hotkeys

Technical Details:
==================

- Batch Type: Uses Utility.batch_all by default, ensuring atomic execution
- Fee Savings: Multiple operations combined into single transaction fee
- Backward Compatibility: Single operations still work as before (no batching)
- Error Handling: batch_all ensures all operations succeed or fail together
- Display Consistency: Balance changes shown consistently across all stake operations

Benefits:
=========

- Significant fee reduction when performing multiple stake/unstake operations
- Improved user experience with clear feedback on all operations
- Atomic operations prevent partial failures
- Maintains all existing functionality (MEV protection, proxy, etc.)
Copy link
Contributor

@thewhaleking thewhaleking left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks nice, needs tests.

@mimalsm mimalsm requested a review from thewhaleking December 17, 2025 13:41
@mimalsm mimalsm force-pushed the feature/batch-extrinsics branch 2 times, most recently from 9461131 to cb80c5c Compare December 17, 2025 15:53
Comment on lines +510 to +531
call = await subtensor.substrate.compose_call(
call_module="SubtensorModule",
call_function="add_stake_limit",
call_params={
"hotkey": staking_address,
"netuid": netuid,
"amount_staked": am.rao,
"limit_price": price_with_tol.rao,
"allow_partial": allow_partial_stake,
},
)
else:
# Regular staking for root subnet or non-safe staking
call = await subtensor.substrate.compose_call(
call_module="SubtensorModule",
call_function="add_stake",
call_params={
"hotkey": staking_address,
"netuid": netuid,
"amount_staked": am.rao,
},
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you'll want to get the block_hash = chain head at the beginning of the function, and then, in these compose_call calls, pass the block_hash=block_hash, which will significantly speed things up (otherwise it needs to make a network call for each compose_call call.

@thewhaleking thewhaleking added the enhancement New feature or request label Dec 18, 2025
@mimalsm mimalsm force-pushed the feature/batch-extrinsics branch from cb80c5c to d0e0696 Compare December 22, 2025 18:39
@mimalsm
Copy link
Author

mimalsm commented Dec 22, 2025

I just noticed that many of my prs are all closed. giving up gittensor

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants