forked from nostr/nostrweb
nip-13: add settings for mining difficulty and timeout
adding settings to change mining difficulty and timeout, so users can change or disable pow. also added some explanation and link to nip-13. setting arbitrary low default to 16 zero mining difficulty and 5 seconds timeout.
parent
a596121821
commit
898e7265c2
|
@ -10,7 +10,7 @@
|
|||
}
|
||||
@media (orientation: portrait) {
|
||||
.mbox {
|
||||
padding: 0 calc(.5 * var(--gap));
|
||||
padding: 0 var(--gap-half);
|
||||
}
|
||||
}
|
||||
.mbox:last-child {
|
||||
|
|
44
src/form.css
44
src/form.css
|
@ -43,6 +43,7 @@ label {
|
|||
transition: background-color var(--transition-duration);
|
||||
}
|
||||
|
||||
input[type="number"],
|
||||
input[type="password"],
|
||||
input[type="text"],
|
||||
input[type="url"],
|
||||
|
@ -54,6 +55,7 @@ textarea {
|
|||
margin: 0 0 1.2rem 0;
|
||||
padding: var(--padding);
|
||||
}
|
||||
input[type="number"]:focus,
|
||||
input[type="password"]:focus,
|
||||
input[type="text"]:focus,
|
||||
input[type="url"]:focus,
|
||||
|
@ -169,11 +171,13 @@ button:disabled {
|
|||
margin-left: var(--gap);
|
||||
}
|
||||
.form-inline button,
|
||||
.form-inline input[type="number"],
|
||||
.form-inline input[type="text"],
|
||||
.form-inline textarea {
|
||||
margin: .4rem 0;
|
||||
}
|
||||
|
||||
.form-inline input[type="number"],
|
||||
.form-inline input[type="text"],
|
||||
.form-inline textarea {
|
||||
flex-basis: 50%;
|
||||
|
@ -187,6 +191,46 @@ button:disabled {
|
|||
flex-grow: 0;
|
||||
}
|
||||
|
||||
label.number {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
gap: var(--gap);
|
||||
padding: 0;
|
||||
}
|
||||
* + label.number {
|
||||
margin: var(--gap) 0 0 0;
|
||||
}
|
||||
label.number span {
|
||||
flex-grow: 1;
|
||||
padding: 0 0 0 var(--padding);
|
||||
}
|
||||
label.number input[type="number"] {
|
||||
align-self: baseline;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
@media (orientation: landscape) {
|
||||
label.number span {
|
||||
align-self: center;
|
||||
}
|
||||
label.number input[type="number"] + span {
|
||||
padding: 0 var(--padding) 0 0;
|
||||
}
|
||||
}
|
||||
@media (orientation: portrait) {
|
||||
label.number {
|
||||
flex-direction: column;
|
||||
gap: var(--gap-half);
|
||||
padding: 0;
|
||||
}
|
||||
label.number span {
|
||||
padding: 0 var(--padding);
|
||||
}
|
||||
label.number input[type="number"] {
|
||||
align-self: stretch;
|
||||
}
|
||||
}
|
||||
|
||||
button#publish {
|
||||
align-self: end;
|
||||
order: 2;
|
||||
|
|
|
@ -83,6 +83,27 @@
|
|||
<button type="submit" name="publish" tabindex="0" disabled>publish</button>
|
||||
</div>
|
||||
</form>
|
||||
<form action="#" name="options">
|
||||
<label class="number" for="miningTarget">
|
||||
<span>
|
||||
mining difficulty<br>
|
||||
<small>
|
||||
with which difficulty to try to mine a proof of work when publishing events, such as: notes, replies, reactions and profile updates.
|
||||
use zero to disable mining.
|
||||
difficulty is defined as the number of leading zero bits, read more about
|
||||
<a href="https://github.com/nostr-protocol/nips/blob/master/13.md" target="_blank" rel="noopener noreferrer">proof of work (nip-13)</a>.
|
||||
</small>
|
||||
</span>
|
||||
<input type="number" name="mining_target" step="1" min="0" max="256" id="miningTarget" value="16">
|
||||
</label>
|
||||
<label class="number" for="miningTimeout">
|
||||
<span>
|
||||
mining timeout<br>
|
||||
<small>abort trying to find a proof if timeout (in seconds) exceeds. use 0 to mine without a time limit.</small>
|
||||
</span>
|
||||
<input type="number" name="mining_timeout" step="1" min="0" max="256" id="miningTimeout" value="5">
|
||||
</label>
|
||||
</form>
|
||||
<form action="#" name="settings" autocomplete="new-password">
|
||||
<label for="pubkey">public-key</label>
|
||||
<input type="text" id="pubkey" autocomplete="off">
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
--focus-outline: var(--focus-outline-width) var(--focus-outline-style) var(--focus-outline-color);
|
||||
--font-small: 1.2rem;
|
||||
--gap: 2.4rem;
|
||||
--gap-half: 1.2rem;
|
||||
--max-width: 96ch;
|
||||
}
|
||||
|
||||
|
|
33
src/main.js
33
src/main.js
|
@ -40,10 +40,6 @@ let pubkey = localStorage.getItem('pub_key') || (() => {
|
|||
return pubkey;
|
||||
})();
|
||||
|
||||
// arbitrary difficulty, still experimenting.
|
||||
// measured empirically, takes N sec on average to mine a text note event.
|
||||
const difficulty = 16;
|
||||
|
||||
const subList = [];
|
||||
const unSubAll = () => {
|
||||
subList.forEach(sub => sub.unsub());
|
||||
|
@ -756,6 +752,23 @@ function hideNewMessage(hide) {
|
|||
newMessageDiv.hidden = hide;
|
||||
}
|
||||
|
||||
// arbitrary difficulty default, still experimenting.
|
||||
let difficulty = JSON.parse(localStorage.getItem('mining_target')) ?? 16;
|
||||
const miningTargetInput = document.querySelector('#miningTarget');
|
||||
miningTargetInput.addEventListener('input', (e) => {
|
||||
localStorage.setItem('mining_target', miningTargetInput.valueAsNumber);
|
||||
difficulty = miningTargetInput.valueAsNumber;
|
||||
});
|
||||
miningTargetInput.value = difficulty;
|
||||
|
||||
let timeout = JSON.parse(localStorage.getItem('mining_timeout')) ?? 5;
|
||||
const miningTimeoutInput = document.querySelector('#miningTimeout');
|
||||
miningTimeoutInput.addEventListener('input', (e) => {
|
||||
localStorage.setItem('mining_timeout', miningTimeoutInput.valueAsNumber);
|
||||
timeout = miningTimeoutInput.valueAsNumber;
|
||||
});
|
||||
miningTimeoutInput.value = timeout;
|
||||
|
||||
async function upvote(eventId, eventPubkey) {
|
||||
const privatekey = localStorage.getItem('private_key');
|
||||
const note = replyList.find(r => r.id === eventId) || textNoteList.find(n => n.id === (eventId));
|
||||
|
@ -771,7 +784,7 @@ async function upvote(eventId, eventPubkey) {
|
|||
content: '+',
|
||||
tags,
|
||||
created_at: Math.floor(Date.now() * 0.001),
|
||||
}, difficulty, 10).catch(console.warn);
|
||||
}, difficulty, timeout).catch(console.warn);
|
||||
if (newReaction) {
|
||||
const sig = await signEvent(newReaction, privatekey).catch(console.error);
|
||||
if (sig) {
|
||||
|
@ -810,7 +823,7 @@ writeForm.addEventListener('submit', async (e) => {
|
|||
pubkey,
|
||||
tags,
|
||||
created_at: Math.floor(Date.now() * 0.001),
|
||||
}, difficulty, 10).catch(console.warn);
|
||||
}, difficulty, timeout).catch(console.warn);
|
||||
if (newEvent) {
|
||||
const sig = await signEvent(newEvent, privatekey).catch(onSendError);
|
||||
if (sig) {
|
||||
|
@ -954,7 +967,7 @@ profileForm.addEventListener('submit', async (e) => {
|
|||
content: JSON.stringify(Object.fromEntries(form)),
|
||||
tags: [],
|
||||
created_at: Math.floor(Date.now() * 0.001),
|
||||
}, difficulty, 10).catch(console.warn);
|
||||
}, difficulty, timeout).catch(console.warn);
|
||||
if (newProfile) {
|
||||
const sig = await signEvent(newProfile, privatekey).catch(console.error);
|
||||
if (sig) {
|
||||
|
@ -1031,8 +1044,12 @@ function validatePow(evt) {
|
|||
*
|
||||
* powEvent returns a rejected promise if the funtion runs for longer than timeout.
|
||||
* a zero timeout makes mineEvent run without a time limit.
|
||||
* a zero mining target just resolves the promise without trying to find a 'nonce'.
|
||||
*/
|
||||
function powEvent(evt, difficulty, timeout = 0) {
|
||||
function powEvent(evt, difficulty, timeout) {
|
||||
if (difficulty === 0) {
|
||||
return Promise.resolve(evt);
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const worker = new Worker('./worker.js');
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ input[type="radio"]:checked + label {
|
|||
.tab-content {
|
||||
max-width: var(--max-width);
|
||||
min-height: 200px;
|
||||
padding: calc(.5 * var(--gap)) 0 100px 0;
|
||||
padding: var(--gap-half) 0 100px 0;
|
||||
}
|
||||
.tabbed {
|
||||
align-items: start;
|
||||
|
|
Loading…
Reference in New Issue