First fully working version.
This commit is contained in:
parent
ecf248dfc2
commit
6cf5d6c50e
|
@ -362,49 +362,6 @@
|
||||||
return window.NostrTools.getPublicKey(randomKey);
|
return window.NostrTools.getPublicKey(randomKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate actual padding string based on requested bytes
|
|
||||||
function generatePaddingString(paddingInput) {
|
|
||||||
console.log('DEBUG: generatePaddingString called with:', paddingInput);
|
|
||||||
|
|
||||||
if (!paddingInput || paddingInput.trim() === '') {
|
|
||||||
console.log('DEBUG: No padding input, returning null');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cleanInput = paddingInput.trim();
|
|
||||||
|
|
||||||
// If no +/- prefix, assume it's addition
|
|
||||||
if (!/^[+-]/.test(cleanInput)) {
|
|
||||||
cleanInput = '+' + cleanInput;
|
|
||||||
console.log('DEBUG: Added + prefix, now:', cleanInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
const match = cleanInput.match(/^([+-])(\d+)$/);
|
|
||||||
if (!match) {
|
|
||||||
console.log('DEBUG: Padding format invalid, returning null');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const operation = match[1]; // "+" or "-"
|
|
||||||
const bytes = parseInt(match[2]);
|
|
||||||
|
|
||||||
console.log('DEBUG: Padding operation:', operation, 'bytes:', bytes);
|
|
||||||
|
|
||||||
if (operation === '-') {
|
|
||||||
// For removal, we'll return the operation and count
|
|
||||||
console.log('DEBUG: Returning removal padding:', cleanInput);
|
|
||||||
return cleanInput; // Keep as "-50" format
|
|
||||||
} else {
|
|
||||||
// For addition, generate actual padding string
|
|
||||||
// Use repeating digits: "0123456789012345..."
|
|
||||||
let paddingStr = '';
|
|
||||||
for (let i = 0; i < bytes; i++) {
|
|
||||||
paddingStr += (i % 10).toString();
|
|
||||||
}
|
|
||||||
console.log('DEBUG: Generated padding string:', paddingStr);
|
|
||||||
return paddingStr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generate random pubkey for testing (since we don't have real superballs yet)
|
// Generate random pubkey for testing (since we don't have real superballs yet)
|
||||||
function generateRandomPubkey(bounceId) {
|
function generateRandomPubkey(bounceId) {
|
||||||
|
@ -495,8 +452,13 @@
|
||||||
<input type="number" id="delay-${bounceId}" class="small-input" value="30" min="1">
|
<input type="number" id="delay-${bounceId}" class="small-input" value="30" min="1">
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label for="padding-${bounceId}">Padding (+N or -N bytes):</label>
|
<label for="padding-${bounceId}">Add Padding Bytes to This Event:</label>
|
||||||
<input type="text" id="padding-${bounceId}" class="small-input" placeholder="+150 or -50">
|
<input type="number" id="padding-${bounceId}" class="small-input" placeholder="150" min="0" step="1">
|
||||||
|
</div>
|
||||||
|
<div class="input-group" id="daemon-padding-${bounceId}">
|
||||||
|
<label for="add-padding-bytes-${bounceId}">Instruct Next Daemon to Add Padding (bytes):</label>
|
||||||
|
<input type="number" id="add-padding-bytes-${bounceId}" class="small-input" placeholder="256" min="0" step="1">
|
||||||
|
<small style="color: #666; font-size: 12px;">Only used when forwarding to another Superball</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<label for="payment-${bounceId}">Payment (optional):</label>
|
<label for="payment-${bounceId}">Payment (optional):</label>
|
||||||
|
@ -525,6 +487,15 @@
|
||||||
const auditTag = generateAuditTag();
|
const auditTag = generateAuditTag();
|
||||||
document.getElementById(`audit-tag-${bounceId}`).value = auditTag;
|
document.getElementById(`audit-tag-${bounceId}`).value = auditTag;
|
||||||
|
|
||||||
|
// Hide daemon padding field for final bounce (first one created)
|
||||||
|
if (bounces.length === 0) {
|
||||||
|
// This is the final bounce - hide daemon padding field since it makes no sense
|
||||||
|
const daemonPaddingDiv = document.getElementById(`daemon-padding-${bounceId}`);
|
||||||
|
if (daemonPaddingDiv) {
|
||||||
|
daemonPaddingDiv.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update bounce labels to reflect execution order
|
// Update bounce labels to reflect execution order
|
||||||
updateBounceLabels();
|
updateBounceLabels();
|
||||||
}
|
}
|
||||||
|
@ -588,7 +559,8 @@
|
||||||
const superballPubkey = document.getElementById(`superball-pubkey-${bounceId}`).value.trim();
|
const superballPubkey = document.getElementById(`superball-pubkey-${bounceId}`).value.trim();
|
||||||
const bounceRelays = document.getElementById(`bounce-relays-${bounceId}`).value.split(',').map(r => r.trim()).filter(r => r);
|
const bounceRelays = document.getElementById(`bounce-relays-${bounceId}`).value.split(',').map(r => r.trim()).filter(r => r);
|
||||||
const delay = parseInt(document.getElementById(`delay-${bounceId}`).value);
|
const delay = parseInt(document.getElementById(`delay-${bounceId}`).value);
|
||||||
const padding = document.getElementById(`padding-${bounceId}`).value.trim();
|
const builderPadding = parseInt(document.getElementById(`padding-${bounceId}`).value) || 0;
|
||||||
|
const addPaddingBytes = parseInt(document.getElementById(`add-padding-bytes-${bounceId}`).value) || 0;
|
||||||
const payment = document.getElementById(`payment-${bounceId}`).value.trim();
|
const payment = document.getElementById(`payment-${bounceId}`).value.trim();
|
||||||
|
|
||||||
// Debug the input values
|
// Debug the input values
|
||||||
|
@ -596,7 +568,8 @@
|
||||||
console.log(' - superballPubkey:', superballPubkey);
|
console.log(' - superballPubkey:', superballPubkey);
|
||||||
console.log(' - bounceRelays:', bounceRelays);
|
console.log(' - bounceRelays:', bounceRelays);
|
||||||
console.log(' - delay:', delay);
|
console.log(' - delay:', delay);
|
||||||
console.log(' - padding:', `"${padding}"`);
|
console.log(' - builderPadding:', builderPadding);
|
||||||
|
console.log(' - addPaddingBytes:', addPaddingBytes);
|
||||||
console.log(' - payment:', `"${payment}"`);
|
console.log(' - payment:', `"${payment}"`);
|
||||||
|
|
||||||
if (!superballPubkey || superballPubkey.length !== 64) {
|
if (!superballPubkey || superballPubkey.length !== 64) {
|
||||||
|
@ -640,19 +613,10 @@
|
||||||
audit: auditTag
|
audit: auditTag
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add optional fields
|
// Add daemon instruction to add padding when forwarding (if specified and not final bounce)
|
||||||
console.log('DEBUG: Processing padding field:', padding);
|
if (!isLastBounce && addPaddingBytes > 0) {
|
||||||
if (padding) {
|
routingInstructions.add_padding_bytes = addPaddingBytes;
|
||||||
const paddingStr = generatePaddingString(padding);
|
console.log('DEBUG: Added add_padding_bytes instruction:', addPaddingBytes);
|
||||||
console.log('DEBUG: Generated padding result:', paddingStr);
|
|
||||||
if (paddingStr !== null) {
|
|
||||||
routingInstructions.padding = paddingStr;
|
|
||||||
console.log('DEBUG: Added padding to routing instructions:', paddingStr);
|
|
||||||
} else {
|
|
||||||
console.log('DEBUG: Padding string was null, not adding to routing');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
console.log('DEBUG: No padding field provided');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payment) {
|
if (payment) {
|
||||||
|
@ -669,6 +633,18 @@
|
||||||
}
|
}
|
||||||
// Note: If this IS the last bounce (first one created), no 'p' field means final posting
|
// Note: If this IS the last bounce (first one created), no 'p' field means final posting
|
||||||
|
|
||||||
|
// Add builder padding to routing instructions (if specified)
|
||||||
|
if (builderPadding > 0) {
|
||||||
|
// Generate counting padding string (0123456789012...)
|
||||||
|
let paddingString = '';
|
||||||
|
for (let i = 0; i < builderPadding; i++) {
|
||||||
|
paddingString += (i % 10).toString();
|
||||||
|
}
|
||||||
|
routingInstructions.padding = paddingString;
|
||||||
|
|
||||||
|
console.log('DEBUG: Added', builderPadding, 'bytes of builder padding to routing instructions');
|
||||||
|
}
|
||||||
|
|
||||||
// Create the payload to encrypt
|
// Create the payload to encrypt
|
||||||
const payload = {
|
const payload = {
|
||||||
event: eventToWrap,
|
event: eventToWrap,
|
||||||
|
|
|
@ -899,13 +899,8 @@
|
||||||
const nostrEvent = message[2];
|
const nostrEvent = message[2];
|
||||||
addLogEntry('success', `Received EVENT from ${relayUrl}: ${nostrEvent.id.substring(0, 16)}...`);
|
addLogEntry('success', `Received EVENT from ${relayUrl}: ${nostrEvent.id.substring(0, 16)}...`);
|
||||||
|
|
||||||
// Truncate content for readability
|
// Log full event without truncation
|
||||||
const truncatedEvent = { ...nostrEvent };
|
addLogEntry('info', `Full received event:\n${JSON.stringify(nostrEvent, null, 2)}`);
|
||||||
if (truncatedEvent.content && truncatedEvent.content.length > 10) {
|
|
||||||
const content = truncatedEvent.content;
|
|
||||||
truncatedEvent.content = content.substring(0, 5) + '...' + content.substring(content.length - 5);
|
|
||||||
}
|
|
||||||
addLogEntry('info', `Full received event:\n${JSON.stringify(truncatedEvent, null, 2)}`);
|
|
||||||
handleIncomingEvent(nostrEvent);
|
handleIncomingEvent(nostrEvent);
|
||||||
} else if (message[0] === 'EOSE' && message[1] === subscriptionId) {
|
} else if (message[0] === 'EOSE' && message[1] === subscriptionId) {
|
||||||
addLogEntry('info', `End of stored events from ${relayUrl}`);
|
addLogEntry('info', `End of stored events from ${relayUrl}`);
|
||||||
|
@ -953,11 +948,19 @@
|
||||||
const innerEvent = decryptedPayload.event;
|
const innerEvent = decryptedPayload.event;
|
||||||
addLogEntry('info', `Discarding padding: "${decryptedPayload.padding}"`);
|
addLogEntry('info', `Discarding padding: "${decryptedPayload.padding}"`);
|
||||||
|
|
||||||
|
// DEBUG: Log the inner event BEFORE attempting second decryption
|
||||||
|
addLogEntry('info', `INNER EVENT BEFORE SECOND DECRYPTION:`);
|
||||||
|
addLogEntry('info', ` Inner event ID: ${innerEvent.id}`);
|
||||||
|
addLogEntry('info', ` Inner event pubkey: ${innerEvent.pubkey}`);
|
||||||
|
addLogEntry('info', ` Inner event content length: ${innerEvent.content.length}`);
|
||||||
|
addLogEntry('info', ` Inner event full JSON:\n${JSON.stringify(innerEvent, null, 2)}`);
|
||||||
|
|
||||||
// Second decryption to get the actual routing instructions that were encrypted for me
|
// Second decryption to get the actual routing instructions that were encrypted for me
|
||||||
|
// Use the inner event's pubkey, not the outer event's pubkey
|
||||||
decryptedPayload = await decryptRoutingEvent(innerEvent);
|
decryptedPayload = await decryptRoutingEvent(innerEvent);
|
||||||
|
|
||||||
if (!decryptedPayload) {
|
if (!decryptedPayload) {
|
||||||
addLogEntry('error', `Failed to decrypt inner event ${event.id.substring(0,16)}...`);
|
addLogEntry('error', `Failed to decrypt inner event ${innerEvent.id.substring(0,16)}...`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,13 +969,8 @@
|
||||||
addLogEntry('info', `Detected Type 1 (Routing Payload) - processing routing instructions directly`);
|
addLogEntry('info', `Detected Type 1 (Routing Payload) - processing routing instructions directly`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log the complete decrypted payload with truncated content
|
// Log the complete decrypted payload without truncation
|
||||||
const truncatedPayload = { ...decryptedPayload };
|
addLogEntry('info', `Final routing payload:\n${JSON.stringify(decryptedPayload, null, 2)}`);
|
||||||
if (truncatedPayload.event && truncatedPayload.event.content && truncatedPayload.event.content.length > 10) {
|
|
||||||
const content = truncatedPayload.event.content;
|
|
||||||
truncatedPayload.event.content = content.substring(0, 5) + '...' + content.substring(content.length - 5);
|
|
||||||
}
|
|
||||||
addLogEntry('info', `Final routing payload:\n${JSON.stringify(truncatedPayload, null, 2)}`);
|
|
||||||
|
|
||||||
// Parse routing instructions (these are from the builder, specific to this daemon)
|
// Parse routing instructions (these are from the builder, specific to this daemon)
|
||||||
const { event: wrappedEvent, routing } = decryptedPayload;
|
const { event: wrappedEvent, routing } = decryptedPayload;
|
||||||
|
@ -1020,11 +1018,32 @@
|
||||||
// Decrypt routing event using NIP-44 via NIP-07 interface
|
// Decrypt routing event using NIP-44 via NIP-07 interface
|
||||||
async function decryptRoutingEvent(event) {
|
async function decryptRoutingEvent(event) {
|
||||||
try {
|
try {
|
||||||
|
// DEBUG: Log full decryption attempt details
|
||||||
|
addLogEntry('info', `DEBUG DECRYPTION ATTEMPT:`);
|
||||||
|
addLogEntry('info', ` Event ID: ${event.id}`);
|
||||||
|
addLogEntry('info', ` Event pubkey (who signed): ${event.pubkey}`);
|
||||||
|
addLogEntry('info', ` My daemon pubkey: ${userPubkey}`);
|
||||||
|
addLogEntry('info', ` Content length: ${event.content.length}`);
|
||||||
|
addLogEntry('info', ` Full event JSON:\n${JSON.stringify(event, null, 2)}`);
|
||||||
|
|
||||||
|
// DEBUG: Log exact parameters being passed to NIP-44 decrypt
|
||||||
|
addLogEntry('info', ` CALLING window.nostr.nip44.decrypt() with:`);
|
||||||
|
addLogEntry('info', ` pubkey parameter: "${event.pubkey}"`);
|
||||||
|
addLogEntry('info', ` content parameter: "${event.content}"`);
|
||||||
|
addLogEntry('info', ` content parameter length: ${event.content.length}`);
|
||||||
|
addLogEntry('info', ` content parameter type: ${typeof event.content}`);
|
||||||
|
|
||||||
// Use window.nostr.nip44.decrypt() which handles the private key internally
|
// Use window.nostr.nip44.decrypt() which handles the private key internally
|
||||||
const decrypted = await window.nostr.nip44.decrypt(event.pubkey, event.content);
|
const decrypted = await window.nostr.nip44.decrypt(event.pubkey, event.content);
|
||||||
|
|
||||||
|
addLogEntry('success', ` Decryption successful! Decrypted length: ${decrypted.length}`);
|
||||||
|
addLogEntry('info', ` Decrypted preview: ${decrypted.substring(0, 100)}...`);
|
||||||
|
|
||||||
return JSON.parse(decrypted);
|
return JSON.parse(decrypted);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
addLogEntry('error', ` Decryption failed: ${error.message}`);
|
||||||
|
addLogEntry('error', ` Error details: ${JSON.stringify(error, null, 2)}`);
|
||||||
console.error('Decryption error:', error);
|
console.error('Decryption error:', error);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -1122,17 +1141,8 @@
|
||||||
|
|
||||||
addLogEntry('info', `DEBUG Creating padding payload with ${paddingData.length} bytes of padding`);
|
addLogEntry('info', `DEBUG Creating padding payload with ${paddingData.length} bytes of padding`);
|
||||||
|
|
||||||
// Log the complete padding payload with truncated content before encryption
|
// Log the complete padding payload before encryption
|
||||||
const truncatedPaddingPayload = { ...paddingPayload };
|
addLogEntry('info', `Padding payload to encrypt:\n${JSON.stringify(paddingPayload, null, 2)}`);
|
||||||
if (truncatedPaddingPayload.event && truncatedPaddingPayload.event.content && truncatedPaddingPayload.event.content.length > 10) {
|
|
||||||
const content = truncatedPaddingPayload.event.content;
|
|
||||||
truncatedPaddingPayload.event.content = content.substring(0, 5) + '...' + content.substring(content.length - 5);
|
|
||||||
}
|
|
||||||
if (truncatedPaddingPayload.padding && truncatedPaddingPayload.padding.length > 10) {
|
|
||||||
const padding = truncatedPaddingPayload.padding;
|
|
||||||
truncatedPaddingPayload.padding = padding.substring(0, 5) + '...' + padding.substring(padding.length - 5);
|
|
||||||
}
|
|
||||||
addLogEntry('info', `Padding payload to encrypt:\n${JSON.stringify(truncatedPaddingPayload, null, 2)}`);
|
|
||||||
|
|
||||||
// Encrypt padding payload to next Superball
|
// Encrypt padding payload to next Superball
|
||||||
let ephemeralKeyHex;
|
let ephemeralKeyHex;
|
||||||
|
@ -1169,13 +1179,8 @@
|
||||||
// Sign with ephemeral key
|
// Sign with ephemeral key
|
||||||
const signedEvent = window.NostrTools.finalizeEvent(routingEvent, ephemeralKey);
|
const signedEvent = window.NostrTools.finalizeEvent(routingEvent, ephemeralKey);
|
||||||
|
|
||||||
// Log the complete rewrapped event with truncated content before publishing
|
// Log the complete rewrapped event before publishing
|
||||||
const truncatedSignedEvent = { ...signedEvent };
|
addLogEntry('info', `Padding-wrapped event to publish:\n${JSON.stringify(signedEvent, null, 2)}`);
|
||||||
if (truncatedSignedEvent.content && truncatedSignedEvent.content.length > 10) {
|
|
||||||
const content = truncatedSignedEvent.content;
|
|
||||||
truncatedSignedEvent.content = content.substring(0, 5) + '...' + content.substring(content.length - 5);
|
|
||||||
}
|
|
||||||
addLogEntry('info', `Padding-wrapped event to publish:\n${JSON.stringify(truncatedSignedEvent, null, 2)}`);
|
|
||||||
|
|
||||||
// Publish to specified relays
|
// Publish to specified relays
|
||||||
await publishToRelays(signedEvent, routing.relays);
|
await publishToRelays(signedEvent, routing.relays);
|
||||||
|
@ -1200,13 +1205,8 @@
|
||||||
await Promise.any(pool.publish(relays, event));
|
await Promise.any(pool.publish(relays, event));
|
||||||
addLogEntry('success', `Published to relays: ${relays.join(', ')}`);
|
addLogEntry('success', `Published to relays: ${relays.join(', ')}`);
|
||||||
|
|
||||||
// Truncate content for readability
|
// Log full published event
|
||||||
const truncatedEvent = { ...event };
|
addLogEntry('info', `Full published event:\n${JSON.stringify(event, null, 2)}`);
|
||||||
if (truncatedEvent.content && truncatedEvent.content.length > 10) {
|
|
||||||
const content = truncatedEvent.content;
|
|
||||||
truncatedEvent.content = content.substring(0, 5) + '...' + content.substring(content.length - 5);
|
|
||||||
}
|
|
||||||
addLogEntry('info', `Full published event:\n${JSON.stringify(truncatedEvent, null, 2)}`);
|
|
||||||
} catch (aggregateError) {
|
} catch (aggregateError) {
|
||||||
const errorMessages = aggregateError.errors.map((err, index) =>
|
const errorMessages = aggregateError.errors.map((err, index) =>
|
||||||
`${relays[index]}: ${err.message}`
|
`${relays[index]}: ${err.message}`
|
||||||
|
|
Loading…
Reference in New Issue