Skip to content

Commit f42ff56

Browse files
authored
Merge pull request #1499 from opentensor/devnet-ready
devnet deploy 4/2/2025
2 parents e81603e + 3e3be01 commit f42ff56

File tree

16 files changed

+637
-15
lines changed

16 files changed

+637
-15
lines changed

Cargo.lock

Lines changed: 5 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ futures = "0.3.30"
6767
hex = { version = "0.4", default-features = false }
6868
hex-literal = "0.4.1"
6969
jsonrpsee = { version = "0.24.4", default-features = false }
70+
libsecp256k1 = { version = "0.7.2", default-features = false }
7071
log = { version = "0.4.21", default-features = false }
7172
memmap2 = "0.9.4"
7273
ndarray = { version = "0.15.6", default-features = false }

pallets/subtensor/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ serde_bytes = { workspace = true, features = ["alloc"] }
3434
serde_with = { workspace = true, features = ["macros"] }
3535
sp-runtime = { workspace = true }
3636
sp-std = { workspace = true }
37+
libsecp256k1 = { workspace = true }
3738
log = { workspace = true }
3839
substrate-fixed = { workspace = true }
3940
pallet-transaction-payment = { workspace = true }
@@ -91,6 +92,7 @@ std = [
9192
"sp-tracing/std",
9293
"sp-version/std",
9394
"hex/std",
95+
"libsecp256k1/std",
9496
"log/std",
9597
"ndarray/std",
9698
"serde/std",

pallets/subtensor/src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ pub mod pallet {
7777
};
7878
use frame_system::pallet_prelude::*;
7979
use pallet_drand::types::RoundNumber;
80-
use sp_core::{ConstU32, H256};
80+
use sp_core::{ConstU32, H160, H256};
8181
use sp_runtime::traits::{Dispatchable, TrailingZeroInput};
8282
use sp_std::collections::vec_deque::VecDeque;
8383
use sp_std::vec;
@@ -1561,6 +1561,14 @@ pub mod pallet {
15611561
OptionQuery,
15621562
>;
15631563

1564+
/// =============================
1565+
/// ==== EVM related storage ====
1566+
/// =============================
1567+
#[pallet::storage]
1568+
/// --- DMAP (netuid, uid) --> (H160, last_block_where_ownership_was_proven)
1569+
pub type AssociatedEvmAddress<T: Config> =
1570+
StorageDoubleMap<_, Twox64Concat, u16, Twox64Concat, u16, (H160, u64), OptionQuery>;
1571+
15641572
/// ==================
15651573
/// ==== Genesis =====
15661574
/// ==================

pallets/subtensor/src/macros/dispatches.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod dispatches {
99
use frame_support::traits::schedule::DispatchTime;
1010
use frame_support::traits::schedule::v3::Anon as ScheduleAnon;
1111
use frame_system::pallet_prelude::BlockNumberFor;
12+
use sp_core::ecdsa::Signature;
1213
use sp_runtime::traits::Saturating;
1314

1415
use crate::MAX_CRV3_COMMIT_SIZE_BYTES;
@@ -1929,6 +1930,50 @@ mod dispatches {
19291930
Ok(())
19301931
}
19311932

1933+
/// Attempts to associate a hotkey with an EVM key.
1934+
///
1935+
/// The signature will be checked to see if the recovered public key matches the `evm_key` provided.
1936+
///
1937+
/// The EVM key is expected to sign the message according to this formula to produce the signature:
1938+
/// ```text
1939+
/// keccak_256(hotkey ++ keccak_256(block_number))
1940+
/// ```
1941+
///
1942+
/// # Arguments
1943+
/// * `origin` - The origin of the transaction, which must be signed by the coldkey that owns the `hotkey`.
1944+
/// * `netuid` - The netuid that the `hotkey` belongs to.
1945+
/// * `hotkey` - The hotkey associated with the `origin`.
1946+
/// * `evm_key` - The EVM key to associate with the `hotkey`.
1947+
/// * `block_number` - The block number used in the `signature`.
1948+
/// * `signature` - A signed message by the `evm_key` containing the `hotkey` and the hashed `block_number`.
1949+
///
1950+
/// # Errors
1951+
/// Returns an error if:
1952+
/// * The transaction is not signed.
1953+
/// * The hotkey is not owned by the origin coldkey.
1954+
/// * The hotkey does not belong to the subnet identified by the netuid.
1955+
/// * The EVM key cannot be recovered from the signature.
1956+
/// * The EVM key recovered from the signature does not match the given EVM key.
1957+
///
1958+
/// # Events
1959+
/// May emit a `EvmKeyAssociated` event on success
1960+
#[pallet::call_index(93)]
1961+
#[pallet::weight((
1962+
Weight::from_parts(3_000_000, 0).saturating_add(T::DbWeight::get().reads_writes(2, 1)),
1963+
DispatchClass::Operational,
1964+
Pays::Yes
1965+
))]
1966+
pub fn associate_evm_key(
1967+
origin: T::RuntimeOrigin,
1968+
netuid: u16,
1969+
hotkey: T::AccountId,
1970+
evm_key: H160,
1971+
block_number: u64,
1972+
signature: Signature,
1973+
) -> DispatchResult {
1974+
Self::do_associate_evm_key(origin, netuid, hotkey, evm_key, block_number, signature)
1975+
}
1976+
19321977
/// Recycles alpha from a cold/hot key pair, reducing AlphaOut on a subnet
19331978
///
19341979
/// # Arguments

pallets/subtensor/src/macros/errors.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,5 +203,9 @@ mod errors {
203203
NotEnoughAlphaOutToRecycle,
204204
/// Cannot burn or recycle TAO from root subnet
205205
CannotBurnOrRecycleOnRootSubnet,
206+
/// Public key cannot be recovered.
207+
UnableToRecoverPublicKey,
208+
/// Recovered public key is invalid.
209+
InvalidRecoveredPublicKey,
206210
}
207211
}

pallets/subtensor/src/macros/events.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,18 @@ mod events {
294294
/// (coldkey, hotkey, amount, subnet_id)
295295
AlphaBurned(T::AccountId, T::AccountId, u64, u16),
296296

297+
/// An EVM key has been associated with a hotkey.
298+
EvmKeyAssociated {
299+
/// The subnet that the hotkey belongs to.
300+
netuid: u16,
301+
/// The hotkey associated with the EVM key.
302+
hotkey: T::AccountId,
303+
/// The EVM key being associated with the hotkey.
304+
evm_key: H160,
305+
/// The block where the association happened.
306+
block_associated: u64,
307+
},
308+
297309
/// CRV3 Weights have been successfully revealed.
298310
///
299311
/// - **netuid**: The network identifier.

pallets/subtensor/src/staking/remove_stake.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,21 @@ impl<T: Config> Pallet<T> {
134134
// Ensure that the hotkey has enough stake to withdraw.
135135
let alpha_unstaked =
136136
Self::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid);
137+
138+
if Self::validate_remove_stake(
139+
&coldkey,
140+
&hotkey,
141+
netuid,
142+
alpha_unstaked,
143+
alpha_unstaked,
144+
false,
145+
)
146+
.is_err()
147+
{
148+
// Don't unstake from this netuid
149+
continue;
150+
}
151+
137152
let fee = Self::calculate_staking_fee(
138153
Some((&hotkey, netuid)),
139154
&coldkey,
@@ -211,6 +226,21 @@ impl<T: Config> Pallet<T> {
211226
// Ensure that the hotkey has enough stake to withdraw.
212227
let alpha_unstaked =
213228
Self::get_stake_for_hotkey_and_coldkey_on_subnet(&hotkey, &coldkey, netuid);
229+
230+
if Self::validate_remove_stake(
231+
&coldkey,
232+
&hotkey,
233+
netuid,
234+
alpha_unstaked,
235+
alpha_unstaked,
236+
false,
237+
)
238+
.is_err()
239+
{
240+
// Don't unstake from this netuid
241+
continue;
242+
}
243+
214244
let fee = Self::calculate_staking_fee(
215245
Some((&hotkey, netuid)),
216246
&coldkey,

pallets/subtensor/src/staking/stake_utils.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,24 @@ impl<T: Config> Pallet<T> {
5858
}
5959
}
6060
pub fn update_moving_price(netuid: u16) {
61-
let blocks_since_registration = U96F32::saturating_from_num(
62-
Self::get_current_block_as_u64().saturating_sub(NetworkRegisteredAt::<T>::get(netuid)),
63-
);
61+
let blocks_since_start_call = U96F32::saturating_from_num({
62+
// We expect FirstEmissionBlockNumber to be set earlier, and we take the block when
63+
// `start_call` was called (first block before FirstEmissionBlockNumber).
64+
let start_call_block = FirstEmissionBlockNumber::<T>::get(netuid)
65+
.unwrap_or_default()
66+
.saturating_sub(1);
67+
68+
Self::get_current_block_as_u64().saturating_sub(start_call_block)
69+
});
6470

6571
// Use halving time hyperparameter. The meaning of this parameter can be best explained under
6672
// the assumption of a constant price and SubnetMovingAlpha == 0.5: It is how many blocks it
6773
// will take in order for the distance between current EMA of price and current price to shorten
6874
// by half.
6975
let halving_time = EMAPriceHalvingBlocks::<T>::get(netuid);
7076
let current_ma_unsigned = U96F32::saturating_from_num(SubnetMovingAlpha::<T>::get());
71-
let alpha: U96F32 = current_ma_unsigned.saturating_mul(blocks_since_registration.safe_div(
72-
blocks_since_registration.saturating_add(U96F32::saturating_from_num(halving_time)),
77+
let alpha: U96F32 = current_ma_unsigned.saturating_mul(blocks_since_start_call.safe_div(
78+
blocks_since_start_call.saturating_add(U96F32::saturating_from_num(halving_time)),
7379
));
7480
// Because alpha = b / (b + h), where b and h > 0, alpha < 1, so 1 - alpha > 0.
7581
// We can use unsigned type here: U96F32

pallets/subtensor/src/tests/coinbase.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ fn test_coinbase_moving_prices() {
190190
SubnetAlphaIn::<Test>::insert(netuid, 1_000_000);
191191
SubnetMechanism::<Test>::insert(netuid, 1);
192192
SubnetMovingPrice::<Test>::insert(netuid, I96F32::from_num(1));
193-
NetworkRegisteredAt::<Test>::insert(netuid, 1);
193+
FirstEmissionBlockNumber::<Test>::insert(netuid, 1);
194194

195195
// Updating the moving price keeps it the same.
196196
assert_eq!(
@@ -250,7 +250,7 @@ fn test_update_moving_price_initial() {
250250

251251
// Registered recently
252252
System::set_block_number(510);
253-
NetworkRegisteredAt::<Test>::insert(netuid, 500);
253+
FirstEmissionBlockNumber::<Test>::insert(netuid, 500);
254254

255255
SubtensorModule::update_moving_price(netuid);
256256

@@ -275,7 +275,7 @@ fn test_update_moving_price_after_time() {
275275

276276
// Registered long time ago
277277
System::set_block_number(144_000_500);
278-
NetworkRegisteredAt::<Test>::insert(netuid, 500);
278+
FirstEmissionBlockNumber::<Test>::insert(netuid, 500);
279279

280280
SubtensorModule::update_moving_price(netuid);
281281

0 commit comments

Comments
 (0)