feat: Add P2P Domain Conflicts management
Implement comprehensive P2P domain conflict resolution allowing users to choose between local claim hashes and consensus-resolved hashes for domains where they have local claims but another claimant won consensus. Key features: - P2P Domain Conflicts UI tab in Local DNS section - Hash preference toggle (local vs resolved) with automatic client restart - Extended selector_cache.json to store hashPreferences alongside versionPreferences - DNS cache invalidation for immediate preference application - REST API endpoints for conflict detection and preference management - Automatic Holesail client restart when hash preferences change - Complete documentation updates across README, API docs, and glossary Resolves conflicts between local claims and consensus resolution by giving users control over which hash their domain resolves to, with seamless client management ensuring immediate effect.
This commit is contained in:
+59
-2
@@ -446,13 +446,69 @@ async function getConsensusState(domain) {
|
||||
}
|
||||
|
||||
async function getHashForDomain(domain) {
|
||||
const localWriter = getPersistentPublicKey();
|
||||
const hashPreference = state.hashPreferences.get(domain);
|
||||
|
||||
// Check if user has a hash preference set (from P2P Domain Conflicts configuration)
|
||||
if (hashPreference === 'local' && localWriter) {
|
||||
// User prefers to use their local claim hash
|
||||
const localHash = await getLocalClaimHash(domain, localWriter);
|
||||
if (localHash) {
|
||||
logInfo('Core', `Using local claim hash for ${domain} due to hash preference: ${localHash}`);
|
||||
return localHash;
|
||||
}
|
||||
// Fall back to resolved hash if local claim not found
|
||||
logWarn('Core', `Hash preference set to 'local' for ${domain} but local claim not found, falling back to resolved hash`);
|
||||
} else if (hashPreference === 'resolved') {
|
||||
logInfo('Core', `Using resolved consensus hash for ${domain} due to hash preference`);
|
||||
}
|
||||
|
||||
// Use resolved hash (default behavior or when preference is 'resolved')
|
||||
const consensusState = await getConsensusState(domain);
|
||||
|
||||
|
||||
if (consensusState.status === 'resolved') {
|
||||
if (!hashPreference) {
|
||||
logDebug('Core', `Using resolved consensus hash for ${domain} (no preference set): ${consensusState.hash}`);
|
||||
}
|
||||
return consensusState.hash;
|
||||
}
|
||||
|
||||
|
||||
// For backward compatibility, if no preference set and not resolved,
|
||||
// but user has a local claim, use local claim hash (default to 'local')
|
||||
if (!hashPreference && localWriter) {
|
||||
const localHash = await getLocalClaimHash(domain, localWriter);
|
||||
if (localHash) {
|
||||
logInfo('Core', `Using local claim hash for ${domain} (fallback, no preference set): ${localHash}`);
|
||||
return localHash;
|
||||
}
|
||||
}
|
||||
|
||||
// For backward compatibility, return null if not resolved
|
||||
logDebug('Core', `No hash available for ${domain} (not resolved, no local claim, or no preference)`);
|
||||
return null;
|
||||
}
|
||||
|
||||
async function getLocalClaimHash(domain, localWriter) {
|
||||
const pass = state.dnsPass;
|
||||
if (!pass || !localWriter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
await pass.ready();
|
||||
const allEntries = await getAllEntries(pass, true);
|
||||
const claimKey = `claim:${domain}:${localWriter}`;
|
||||
|
||||
for (const entry of allEntries) {
|
||||
if (entry.key === claimKey) {
|
||||
const parsed = parseClaimValue(entry.value);
|
||||
return parsed.hash;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logError('Core', `Error getting local claim hash for domain ${domain}: ${err.message}`);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -764,6 +820,7 @@ async function cleanupRedundantClientEntries() {
|
||||
module.exports = {
|
||||
getHashForDomain,
|
||||
getDomainSSLStatus,
|
||||
getLocalClaimHash,
|
||||
doAutoVotes,
|
||||
getAllEntries,
|
||||
autoVoteForDomain,
|
||||
|
||||
Reference in New Issue
Block a user