Skip to content

Commit 95321e5

Browse files
author
EchoBT
committed
fix: Use proper Substrate SR25519 derivation for peer ID
Previously used SHA256(mnemonic) which produced a different keypair than Bittensor. Now uses sp_core::sr25519::Pair::from_string() which is the same derivation as bittensor-rs. The peer ID is now derived from the actual SR25519 public key (hotkey), ensuring consistency between P2P identity and Bittensor identity. Bootnode peer ID: 12D3KooWEpZoR9A1fpMN4QGspuRSa9UYHYvnFda2GWkXXZyYgAkN Corresponding hotkey: 5GziQCcRpN8NCJktX343brnfuVe3w6gUYieeStXPD1Dag2At
1 parent 2be994d commit 95321e5

File tree

4 files changed

+24
-21
lines changed

4 files changed

+24
-21
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bins/validator-node/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ parking_lot = { workspace = true }
4545
uuid = { workspace = true }
4646
sha2 = { workspace = true }
4747
chrono = { workspace = true }
48+
sp-core = { workspace = true }

bins/validator-node/src/main.rs

Lines changed: 21 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -142,9 +142,9 @@ async fn main() -> Result<()> {
142142
// The internal keypair uses the same derivation as Bittensor (SR25519)
143143
let bittensor_seed = args.secret_key.clone();
144144

145-
// Derive keypair for internal use
146-
// Try to use the same derivation as Bittensor (SR25519 from mnemonic)
147-
let keypair = {
145+
// Derive keypair using proper Substrate SR25519 derivation (same as Bittensor)
146+
// This ensures the hotkey matches what Bittensor expects
147+
let (keypair, identity_seed) = {
148148
let secret = &args.secret_key;
149149

150150
// Strip 0x prefix if present
@@ -157,28 +157,29 @@ async fn main() -> Result<()> {
157157
}
158158
let mut arr = [0u8; 32];
159159
arr.copy_from_slice(&bytes);
160-
Keypair::from_bytes(&arr)?
160+
let kp = Keypair::from_bytes(&arr)?;
161+
(kp, arr)
161162
} else {
162-
// Mnemonic phrase - use BIP39 + SR25519 derivation (same as Bittensor)
163-
// We use sp_core to derive the same key as Bittensor
164-
use sha2::{Digest, Sha256};
163+
// Mnemonic phrase - use proper Substrate SR25519 derivation
164+
use sp_core::crypto::Pair as CryptoPair;
165+
use sp_core::sr25519;
165166

166-
// Hash the mnemonic to get a deterministic seed
167-
// This matches the internal derivation we need for signing
168-
let mut hasher = Sha256::new();
169-
hasher.update(secret.as_bytes());
170-
let hash = hasher.finalize();
167+
// Derive SR25519 keypair using same method as bittensor-rs
168+
let sr25519_pair = sr25519::Pair::from_string(secret, None)
169+
.map_err(|e| anyhow::anyhow!("Invalid mnemonic: {:?}", e))?;
171170

172-
let mut arr = [0u8; 32];
173-
arr.copy_from_slice(&hash);
171+
// Get the public key bytes (32 bytes) - this is the hotkey
172+
let pubkey_bytes: [u8; 32] = sr25519_pair.public().0;
173+
174+
// Use public key bytes as seed for internal Ed25519 keypair
175+
// This ensures peer ID is derived from the hotkey
176+
let kp = Keypair::from_bytes(&pubkey_bytes)?;
174177

175-
info!("Derived internal keypair from mnemonic");
176-
Keypair::from_bytes(&arr)?
178+
info!("Derived keypair from Substrate mnemonic (SR25519)");
179+
(kp, pubkey_bytes)
177180
}
178181
};
179182

180-
// Note: The actual Bittensor hotkey will be shown after connecting to Bittensor
181-
// The internal keypair is used for P2P message signing
182183
info!("Internal keypair derived (P2P signing)");
183184

184185
// Canonicalize data directory to ensure absolute paths for Docker
@@ -716,11 +717,11 @@ async fn main() -> Result<()> {
716717
})
717718
.unwrap_or_default();
718719

719-
// Create network node with deterministic peer ID from validator keypair
720+
// Create network node with deterministic peer ID derived from hotkey public key
720721
let node_config = NodeConfig {
721722
listen_addr: args.listen.parse()?,
722723
bootstrap_peers,
723-
identity_seed: Some(keypair.secret_bytes()),
724+
identity_seed: Some(identity_seed),
724725
..Default::default()
725726
};
726727

docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ services:
3232
- --data-dir
3333
- /data
3434
- --bootstrap-peer
35-
- /dns4/bootnode.platform.network/tcp/9000/p2p/12D3KooWQRUxZ7HkALjwTNybH4efMtnjQ9sBdUjzWc6TbuXHPvzM
35+
- /dns4/bootnode.platform.network/tcp/9000/p2p/12D3KooWEpZoR9A1fpMN4QGspuRSa9UYHYvnFda2GWkXXZyYgAkN
3636

3737
healthcheck:
3838
test: ["CMD", "curl", "-sf", "http://localhost:8080/health"]

0 commit comments

Comments
 (0)