feat: Add separate message for conflict claim removalImplement removeConflictDomainClaim: message type to distinguish betweenfull domain cleanup and conflict claim removal, ensuring other peers'claims are preserved when removing conflicting claims.- Add sendConflictClaimRemoval() function for notification broadcasting- Add handler for removeConflictDomainClaim: messages that updates consensus but does NOT remove other peers' claims- Modify removal logic to conditionally broadcast based on claimant status: - Resolved claimants: broadcast remove_domain: (full cleanup) - Non-resolved claimants: broadcast removeConflictDomainClaim: (notification only)- Update admin routes and SDK to use conditional broadcastingPrevents cross-peer claim deletion when removing conflict claims whilemaintaining proper consensus updates and full cleanup functionality.

This commit is contained in:
Raven Scott
2025-12-26 17:28:37 -05:00
parent 6e1c3f6863
commit 9b68e728fd
4 changed files with 60 additions and 16 deletions
+10 -3
View File
@@ -205,17 +205,24 @@ async function handleDomainsRoutes(req, res) {
// Full removal: user is the resolved claimant
logInfo('Admin', `User is resolved claimant for ${domain}, performing full cleanup`);
await atomicDomainCleanup(domain);
// Broadcast full removal request (triggers other peers to clean up their claims)
if (state.sendRemovalRequest) {
state.sendRemovalRequest(domain);
}
} else {
// Partial removal: user has claim but isn't the resolved claimant
// Partial removal: user has claim but isn't the resolved claimant (conflict scenario)
// This includes cases where:
// - Consensus is not resolved
// - User is not the resolved claimant (conflict scenario)
// - Resolved claimant is null/undefined
logInfo('Admin', `User is NOT resolved claimant for ${domain} (status=${consensusState.status}, resolvedClaimant=${consensusState.resolvedClaimant}), removing only own claim and votes`);
await removeOwnClaimAndVotes(domain, localWriter);
// Broadcast conflict claim removal notification (does NOT trigger other peers to remove)
if (state.sendConflictClaimRemoval) {
state.sendConflictClaimRemoval(domain);
}
if (state.sendRemovalRequest) {
state.sendRemovalRequest(domain);
}
// Cleanup hash preferences if domain was removed
+10 -3
View File
@@ -205,17 +205,24 @@ async function handleDomainsRoutes(req, res) {
// Full removal: user is the resolved claimant
logInfo('Admin', `User is resolved claimant for ${domain}, performing full cleanup`);
await atomicDomainCleanup(domain);
// Broadcast full removal request (triggers other peers to clean up their claims)
if (state.sendRemovalRequest) {
state.sendRemovalRequest(domain);
}
} else {
// Partial removal: user has claim but isn't the resolved claimant
// Partial removal: user has claim but isn't the resolved claimant (conflict scenario)
// This includes cases where:
// - Consensus is not resolved
// - User is not the resolved claimant (conflict scenario)
// - Resolved claimant is null/undefined
logInfo('Admin', `User is NOT resolved claimant for ${domain} (status=${consensusState.status}, resolvedClaimant=${consensusState.resolvedClaimant}), removing only own claim and votes`);
await removeOwnClaimAndVotes(domain, localWriter);
// Broadcast conflict claim removal notification (does NOT trigger other peers to remove)
if (state.sendConflictClaimRemoval) {
state.sendConflictClaimRemoval(domain);
}
if (state.sendRemovalRequest) {
state.sendRemovalRequest(domain);
}
// Cleanup hash preferences if domain was removed
+10 -5
View File
@@ -669,15 +669,20 @@ const sdk = {
if (isResolvedClaimant) {
// Full removal: user is the resolved claimant
await atomicDomainCleanup(domain);
} else {
// Partial removal: user has claim but isn't the resolved claimant
await removeOwnClaimAndVotes(domain, localWriter);
}
// Broadcast removal request to peers if available
// Broadcast full removal request (triggers other peers to clean up their claims)
if (state.sendRemovalRequest) {
state.sendRemovalRequest(domain);
}
} else {
// Partial removal: user has claim but isn't the resolved claimant (conflict scenario)
await removeOwnClaimAndVotes(domain, localWriter);
// Broadcast conflict claim removal notification (does NOT trigger other peers to remove)
if (state.sendConflictClaimRemoval) {
state.sendConflictClaimRemoval(domain);
}
}
},
/**
+25
View File
@@ -520,6 +520,14 @@ async function main() {
}
state.sendConsensusRequest = sendConsensusRequest;
// Function to send conflict claim removal notification to all peers
function sendConflictClaimRemoval(domain) {
// Use channel-manager broadcast to send to all peers
const count = channelManager.broadcastToPeers(CORE_DOMAIN, 'request', `removeConflictDomainClaim:${domain}`);
logDebug('Main', `Sent conflict claim removal notification for ${domain} to ${count} peers`);
}
state.sendConflictClaimRemoval = sendConflictClaimRemoval;
// Register invite channel for sending/receiving invites
channelManager.registerPluginChannel(CORE_DOMAIN, 'invite', {
encoding: 'string',
@@ -959,6 +967,23 @@ async function main() {
const allEntries = await getAllEntries();
await autoVoteForDomain(domain, allEntries);
}
} else if (message.startsWith('removeConflictDomainClaim:')) {
const domain = message.slice(26); // Length of "removeConflictDomainClaim:"
logDebug('Swarm', `Received conflict claim removal notification for domain: ${domain}`);
// This is just a notification - don't remove anything
// The peer that sent this already removed their own conflict claim
// We should invalidate cache to refresh consensus state, but NOT remove our claims
const { invalidateEntriesCache } = require('./includes/core/core');
invalidateEntriesCache();
// Trigger consensus recalculation since a claim was removed
const { doAutoVotes } = require('./includes/core/core');
doAutoVotes().catch(err => {
logWarn('Swarm', `Error recalculating consensus after conflict claim removal: ${err.message}`);
});
logInfo('Swarm', `Processed conflict claim removal notification for ${domain} - other claims preserved`);
} else {
logWarn('Swarm', `Unknown message from ${peerId}: ${message}`);
}