Skip to content

Fix Stake rate limit for target>1 #1091

Closed
@camfairchild

Description

@camfairchild
Contributor

Describe the bug

Currently, we rate limit staking transactions by checking how many staking transactions were done within a set interval, and limiting if it exceeds the set target.

The way we do this is flawed. In the get_stakes_this_interval_for_coldkey_hotkey function, we take the value stored in TotalHotkeyColdkeyStakesThisInterval of (num_stakes, last_stake_block).

We reset num_stakes to 0 if it has been more than stake_interval blocks since last_stake_block.
Otherwise we return num_stakes with no reset.

This passes the rate limit, and then we do the transaction. We then increment num_stakes and set last_stake_block to the current block.

This is fine for stake_interval == 1, but for anything greater, we run into an issue.
Example with stake_interval = n where n > 1:

  1. stake n - 1 times at block X
  2. wait stake_interval - 1 blocks
  3. stake 1 time at block X + stake_interval - 1
  4. wait for next block;
  5. stake again ==> failed, rate limited

Why does this fail?
In 4., we should expect the rate limit count to reset to 1 as we have only staked once in the last stake_interval blocks. However, because of the faulty logic, we actually just increase the count and rate limit for another stake_interval blocks.

Activity

camfairchild

camfairchild commented on Dec 12, 2024

@camfairchild
ContributorAuthor

Example:

#[test]
fn test_add_stake_under_limit_resets_old_stakes() {
    new_test_ext(1).execute_with(|| {
        let hotkey_account_id = U256::from(561337);
        let coldkey_account_id = U256::from(61337);
        let netuid: u16 = 1;
        let start_nonce: u64 = 0;
        let tempo: u16 = 13;
        let max_stakes = 5;
		let stake_interval = 10;

		SubtensorModule::set_stake_interval(stake_interval);
        SubtensorModule::set_target_stakes_per_interval(max_stakes);
        add_network(netuid, tempo, 0);
        register_ok_neuron(netuid, hotkey_account_id, coldkey_account_id, start_nonce);
        SubtensorModule::add_balance_to_coldkey_account(&coldkey_account_id, 60000);

		// Stake one less time than the max
		for _ in 0..(max_stakes - 1) {
			assert_ok!(SubtensorModule::add_stake(
				<<Test as Config>::RuntimeOrigin>::signed(coldkey_account_id),
				hotkey_account_id,
				1,
			));
		} // Should all succeed
		assert_eq!(SubtensorModule::get_stakes_this_interval_for_coldkey_hotkey(&coldkey_account_id, &hotkey_account_id), max_stakes - 1);

		// Wait one block less than the interval
		step_block((stake_interval - 1) as u16);

		// Stake one more time to reach the limit
		assert_ok!(SubtensorModule::add_stake(
			<<Test as Config>::RuntimeOrigin>::signed(coldkey_account_id),
			hotkey_account_id,
			1,
		));
		// Check the stakes are now at the limit
		assert_eq!(SubtensorModule::get_stakes_this_interval_for_coldkey_hotkey(&coldkey_account_id, &hotkey_account_id), max_stakes);

		// Should fail
        assert_err!(SubtensorModule::add_stake(
            <<Test as Config>::RuntimeOrigin>::signed(coldkey_account_id),
            hotkey_account_id,
            1,
        ), Error::<Test>::StakeRateLimitExceeded);

		// Wait one block more than the interval
		step_block(1); // This should reset the OLD stakes

		// Check the stakes are reset
		// Should be 1 because we only staked once within the interval
		assert_eq!(SubtensorModule::get_stakes_this_interval_for_coldkey_hotkey(&coldkey_account_id, &hotkey_account_id), 1);

		// Should succeed in this same block
		assert_ok!(SubtensorModule::add_stake(
			<<Test as Config>::RuntimeOrigin>::signed(coldkey_account_id),
			hotkey_account_id,
			1,
		));
    });
}
camfairchild

camfairchild commented on Dec 31, 2024

@camfairchild
ContributorAuthor

Closed by #1093 in #1119

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

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @camfairchild@ales-otf

      Issue actions

        Fix Stake rate limit for target>1 · Issue #1091 · opentensor/subtensor