-
Notifications
You must be signed in to change notification settings - Fork 26
fix: only store one node info and update that #738
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: unstable
Are you sure you want to change the base?
Conversation
| their_metadata: &NodeMetadata, | ||
| ) { | ||
| if let Some(our_metadata) = &self.node_info.metadata { | ||
| if let Some(our_metadata) = self.node_metadata() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this function be moved to the handshake module?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a node_metadata function on the handshake module, I just added another one in network.rs as a shortcut, calling the one in the handshake module.
|
@claude review this PR |
|
Claude finished @diegomrsantos's task —— View job PR Review: Fix handshake regressionTodo List
Review SummaryThis PR successfully fixes the handshake regression by consolidating Detailed AnalysisArchitectural Improvements ✅Single Source of Truth: The PR correctly consolidates Before (problematic): // In Network struct
node_info: NodeInfo, // Duplicate storage
// In AnchorBehaviour (via handshake::Behaviour)
handshake.node_info // Original storageAfter (clean): // Only in handshake::Behaviour
node_info: NodeInfo, // Single source of truthCode Quality ✅
Correctness Verification ✅
Response to Review Comment@diegomrsantos asked:
Referring to My assessment: No, the function is correctly placed in the
Recommendation: Keep the function where it is. The new accessor methods provide clean boundaries without needing to move metric recording logic into the protocol layer. Potential ConcernsNone identified. The changes are minimal, focused, and correct. Testing RecommendationsWhile the existing handshake tests in
This would verify the end-to-end flow of the regression fix. ConclusionVerdict: Approve ✅ This is a well-executed fix that:
The PR successfully addresses the regression where handshakes were failing due to stale | |
|
@claude suggest how a test like the one described below could be implemented:
|
|
I'll analyze this and get back to you. |
|
Claude finished @diegomrsantos's task —— View job Test Implementation SuggestionsBased on my analysis of the codebase, here's a comprehensive guide for implementing the integration test you described. OverviewThe test should verify the end-to-end flow of:
Test LocationAdd the test to Implementation ApproachOption 1: Unit Test (Simpler, Recommended)This approach tests the handshake behavior directly without involving the full network stack. #[tokio::test]
async fn metadata_update_propagates_to_handshake() {
*DEBUG;
// Create initial node info with empty subnets
let node_info = node_info("test", "v1.0.0");
let keypair1 = Keypair::generate_ed25519();
let keypair2 = Keypair::generate_ed25519();
let mut local_swarm = create_test_swarm(keypair1, node_info.clone());
let mut remote_swarm = create_test_swarm(keypair2, node_info);
tokio::spawn(async move {
// Step 1: Subscribe to a subnet by updating metadata
let subnet_id = SubnetId::new(5);
{
let behaviour = local_swarm.behaviour_mut();
let metadata = behaviour.node_metadata_mut()
.as_mut()
.expect("metadata should exist");
// Subscribe to subnet 5
metadata.set_subscribed(subnet_id, true)
.expect("should set subscribed");
// Verify the metadata was updated correctly
assert!(metadata.subnets.contains('1'), "subnet bitfield should be updated");
// More specifically, check that bit 5 is set
let subnet_bytes = hex::decode(&metadata.subnets).expect("valid hex");
let byte_index = *subnet_id as usize / 8;
let bit_index = *subnet_id % 8;
assert_eq!(subnet_bytes[byte_index] & (1 << bit_index), 1 << bit_index);
}
// Step 2: Verify accessor methods return the updated metadata
{
let behaviour = local_swarm.behaviour();
let metadata = behaviour.node_metadata()
.as_ref()
.expect("metadata should exist");
let subnet_bytes = hex::decode(&metadata.subnets).expect("valid hex");
let byte_index = *subnet_id as usize / 8;
let bit_index = *subnet_id % 8;
assert_eq!(subnet_bytes[byte_index] & (1 << bit_index), 1 << bit_index,
"accessor should return updated metadata");
}
// Step 3: Perform handshake and verify the updated metadata is sent
local_swarm.listen().with_memory_addr_external().await;
remote_swarm.connect(&mut local_swarm).await;
let ([local_event], [remote_event]): ([Event; 1], [Event; 1]) =
drive(&mut local_swarm, &mut remote_swarm).await;
// Verify remote peer received the updated subnet information
match remote_event {
Event::Completed { their_info, .. } => {
let their_metadata = their_info.metadata
.expect("should have metadata");
// Check that the remote peer received our updated subnet subscription
let subnet_bytes = hex::decode(&their_metadata.subnets).expect("valid hex");
let byte_index = *subnet_id as usize / 8;
let bit_index = *subnet_id % 8;
assert_eq!(
subnet_bytes[byte_index] & (1 << bit_index),
1 << bit_index,
"remote peer should receive updated subnet subscription in handshake"
);
}
Event::Failed { error, .. } => {
panic!("Handshake should succeed, but got error: {:?}", error);
}
}
// Verify local handshake also completed
assert_completed(local_event, *remote_swarm.local_peer_id(), "v1.0.0");
})
.await
.expect("test completed");
}Key dependencies needed: use subnet_service::SubnetId; // Add to imports at top of test moduleOption 2: Integration Test (More Complex)If you want to test the full network stack integration including how Location: Create use std::time::Duration;
use subnet_service::{SubnetEvent, SubnetId};
use tokio::time::timeout;
#[tokio::test]
async fn subnet_subscription_updates_handshake_metadata() {
// This would require:
// 1. Creating two full Network instances
// 2. Sending a SubnetEvent::Join to one network
// 3. Establishing a connection between them
// 4. Verifying the handshake includes the updated metadata
// Note: This is more complex as it requires:
// - Mock or real subnet event channels
// - Full network setup with all dependencies
// - Proper async coordination
}Why Option 2 is more complex:
RecommendationUse Option 1 for the following reasons:
The existing tests in
Additional Test VariationsYou might also want to add these related tests: Test Multiple Subnet Updates#[tokio::test]
async fn multiple_subnet_updates_all_propagate() {
// Subscribe to subnets 3, 7, and 12
// Verify all are present in handshake metadata
}Test Subnet Unsubscribe#[tokio::test]
async fn subnet_unsubscribe_propagates() {
// Subscribe to subnet 5, then unsubscribe
// Verify the bit is cleared in handshake metadata
}Testing the Regression Fix SpecificallyTo directly test the regression that was fixed (where #[tokio::test]
async fn metadata_accessors_reference_same_storage() {
let node_info = node_info("test", "v1.0.0");
let keypair = Keypair::generate_ed25519();
let mut swarm = create_test_swarm(keypair, node_info);
let subnet_id = SubnetId::new(10);
// Update via mutable accessor
{
let behaviour = swarm.behaviour_mut();
behaviour.node_metadata_mut()
.as_mut()
.expect("metadata exists")
.set_subscribed(subnet_id, true)
.expect("should subscribe");
}
// Read via immutable accessor - should see the same update
{
let behaviour = swarm.behaviour();
let metadata = behaviour.node_metadata()
.as_ref()
.expect("metadata exists");
let subnet_bytes = hex::decode(&metadata.subnets).expect("valid hex");
let byte_index = *subnet_id as usize / 8;
let bit_index = *subnet_id % 8;
assert_eq!(
subnet_bytes[byte_index] & (1 << bit_index),
1 << bit_index,
"accessor methods should reference the same underlying storage"
);
}
}SummaryThe recommended approach is to add the unit test to
This directly validates the regression fix while remaining simple, fast, and maintainable. |

Issue Addressed
We recently introduced a regression where we fail all handshakes. The root cause for this is that we started storing the
NodeInfoin a new place but did not adjust all places to use this.Proposed Changes
Network::node_infoNetwork::node_infoto use new accessors instead