nip13: fix slice pointer race issue on DoWork()

This commit is contained in:
fiatjaf
2024-08-21 16:53:40 -03:00
parent 83bd196bae
commit 2fc34e0de8

View File

@@ -99,19 +99,30 @@ func DoWork(ctx context.Context, event nostr.Event, targetDifficulty int) (nostr
ctx, cancel := context.WithCancel(ctx) ctx, cancel := context.WithCancel(ctx)
nthreads := runtime.NumCPU() nthreads := runtime.NumCPU()
var nonceTag nostr.Tag tagCh := make(chan nostr.Tag)
for i := 0; i < nthreads; i++ { for i := 0; i < nthreads; i++ {
// we must copy the tags here otherwise only a pointer to them will be copied below
// and that will cause all sorts of weird races when computing the difficulty
event.Tags = append(nostr.Tags{}, event.Tags...)
go func(event nostr.Event, nonce uint64) { go func(event nostr.Event, nonce uint64) {
// we make a tag here and add it -- later we will just overwrite it on each iteration
tag := nostr.Tag{"nonce", "", strconv.Itoa(targetDifficulty)} tag := nostr.Tag{"nonce", "", strconv.Itoa(targetDifficulty)}
event.Tags = append(event.Tags, tag) event.Tags = append(event.Tags, tag)
for { for {
// try 10000 times (~30ms) // try 10000 times (~30ms)
for n := 0; n < 10000; n++ { for n := 0; n < 10000; n++ {
tag[1] = strconv.FormatUint(nonce, 10) tag[1] = strconv.FormatUint(nonce, 10)
if Difficulty(event.GetID()) >= targetDifficulty { if Difficulty(event.GetID()) >= targetDifficulty {
nonceTag = tag // must select{} here otherwise a goroutine that finds a good nonce
// right after the first will get stuck in the ch forever
select {
case tagCh <- tag:
case <-ctx.Done():
}
cancel() cancel()
return return
} }
@@ -130,11 +141,10 @@ func DoWork(ctx context.Context, event nostr.Event, targetDifficulty int) (nostr
}(event, uint64(i)) }(event, uint64(i))
} }
<-ctx.Done() select {
case <-ctx.Done():
if nonceTag != nil { return nil, ErrGenerateTimeout
return nonceTag, nil case tag := <-tagCh:
return tag, nil
} }
return nil, ErrGenerateTimeout
} }