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)
|
||||
})
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
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.
|
||||
* 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
|
||||
|
||||
const event = unsigned as Omit<Event, 'sig'>
|
||||
@@ -51,11 +62,13 @@ export function minePow(unsigned: UnsignedEvent, difficulty: number): Omit<Event
|
||||
event.tags.push(tag)
|
||||
|
||||
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) {
|
||||
count = 0
|
||||
event.created_at = now
|
||||
if (now !== event.created_at) {
|
||||
count = 0
|
||||
event.created_at = now
|
||||
}
|
||||
}
|
||||
|
||||
tag[1] = (++count).toString()
|
||||
|
||||
Reference in New Issue
Block a user