mirror of
https://github.com/nbd-wtf/nostr-tools.git
synced 2026-10-05 14:38:23 +00:00
nip13: let minePow keep a caller-chosen created_at (NIP-59 wraps) (#552)
* nip13: let minePow keep a caller-chosen created_at minePow refreshes created_at to the current second while it mines, which is right for a plain note but wrong for anything that has already chosen its timestamp: NIP-59 seals and gift wraps carry a randomized created_at up to two days in the past, and callers mining those lost it. This adds an opt-in keepCreatedAt option (default behaviour unchanged) with a test. * Delete bun.lock --------- Co-authored-by: Ronish Bhatt <16808243+sunmoonron@users.noreply.github.com>
This commit is contained in:
@@ -28,3 +28,23 @@ test('mines POW for an event', async () => {
|
|||||||
|
|
||||||
expect(getPow(event.id)).toBeGreaterThanOrEqual(difficulty)
|
expect(getPow(event.id)).toBeGreaterThanOrEqual(difficulty)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('keeps a caller-chosen created_at when asked', async () => {
|
||||||
|
const difficulty = 10
|
||||||
|
const createdAt = 1700000000 // a fixed, past timestamp, as NIP-59 wraps use
|
||||||
|
|
||||||
|
const event = minePow(
|
||||||
|
{
|
||||||
|
kind: 1,
|
||||||
|
tags: [],
|
||||||
|
content: 'Hello, world!',
|
||||||
|
created_at: createdAt,
|
||||||
|
pubkey: '79c2cae114ea28a981e7559b4fe7854a473521a8d22a66bbab9fa248eb820ff6',
|
||||||
|
},
|
||||||
|
difficulty,
|
||||||
|
{ keepCreatedAt: true },
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(event.created_at).toEqual(createdAt)
|
||||||
|
expect(getPow(event.id)).toBeGreaterThanOrEqual(difficulty)
|
||||||
|
})
|
||||||
|
|||||||
@@ -38,11 +38,22 @@ function getPowFromBytes(hash: Uint8Array): number {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type MinePowOptions = {
|
||||||
|
/**
|
||||||
|
* By default the miner refreshes `created_at` to the current second while it works and restarts the
|
||||||
|
* nonce whenever the second changes, so a long mining run still yields a fresh timestamp. Set this
|
||||||
|
* to `true` to leave `created_at` exactly as given. NIP-59 gift wraps and seals must carry a
|
||||||
|
* randomized timestamp (up to two days in the past), and any other caller that has already chosen a
|
||||||
|
* `created_at` needs it to survive mining.
|
||||||
|
*/
|
||||||
|
keepCreatedAt?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mine an event with the desired POW. This function mutates the event.
|
* Mine an event with the desired POW. This function mutates the event.
|
||||||
* Note that this operation is synchronous and should be run in a worker context to avoid blocking the main thread.
|
* Note that this operation is synchronous and should be run in a worker context to avoid blocking the main thread.
|
||||||
*/
|
*/
|
||||||
export function minePow(unsigned: UnsignedEvent, difficulty: number): Omit<Event, 'sig'> {
|
export function minePow(unsigned: UnsignedEvent, difficulty: number, options: MinePowOptions = {}): Omit<Event, 'sig'> {
|
||||||
let count = 0
|
let count = 0
|
||||||
|
|
||||||
const event = unsigned as Omit<Event, 'sig'>
|
const event = unsigned as Omit<Event, 'sig'>
|
||||||
@@ -51,11 +62,13 @@ export function minePow(unsigned: UnsignedEvent, difficulty: number): Omit<Event
|
|||||||
event.tags.push(tag)
|
event.tags.push(tag)
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const now = Math.floor(new Date().getTime() / 1000)
|
if (!options.keepCreatedAt) {
|
||||||
|
const now = Math.floor(new Date().getTime() / 1000)
|
||||||
|
|
||||||
if (now !== event.created_at) {
|
if (now !== event.created_at) {
|
||||||
count = 0
|
count = 0
|
||||||
event.created_at = now
|
event.created_at = now
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tag[1] = (++count).toString()
|
tag[1] = (++count).toString()
|
||||||
|
|||||||
Reference in New Issue
Block a user