Making The Spam Bots Work

--

Spamming is still a major problem on email and bulletin boards. Why? Because it is free to post things and does not require a good deal of work. If it was more costly, it would likely result in much less spam. With Bitcoin, we make it difficult for the miners by asking them to find a nonce value for a block so that the hash of the block has a predefined number of zeroes. This means that each miner must commit a given amount of work in order to become part of the mining process. It will then be too costly for an adversary to try and take over the mining process, as they would have to invest in a large amount of hardware and pay for the associated energy costs. In the following, we see that the hash value of the block has a given number of zeros for the hash of the block:

With Nostr (Notes and Other Stuff Transmitted by Relays). we can use NIP-13 to generate a Proof of Work for notes and where we have a preceeding number of zero values for rthe ID. This provides a way of showing computation work. Overall it is used to deter spamming bots — as each of them would have to create considerable amount of work to produce spam messages. The difficulty is defined by the number of leading zero bits in the event ID. For example, if we have an ID of 00002b12c714aa9a93b5fafe4a7d1be5d2bf452481ee7229d3ae9c8e6777e2bb then we have four hex zero values, and thus have 16 zeros. This defines a difficulty of 16.

We can create the PoW with [here]:

<
ev := nostr.Event{
PubKey: pk,
CreatedAt: nostr.Now(),
Kind: nostr.KindTextNote,
Tags: nil,
Content: msg,
}

_,_=nip13.Generate(&ev,bits,1000000000)

This will create an ID with a given number of bits and with a time-out of 1,000,000,000 nanoseconds. This ID can then be checked by the receiver to have those numbers of zero bits. Otherwise, it will be rejected.

The following is some sample code [here]:

package main
import (
"fmt"
"os"
"strconv"
"github.com/nbd-wtf/go-nostr"
"github.com/nbd-wtf/go-nostr/nip19"
"github.com/nbd-wtf/go-nostr/nip13"
)
func main() {
msg:="Hello world!"
bits:=4
argCount := len(os.Args[1:])
if (argCount>0) {msg= string(os.Args[1])}
if (argCount>1) {bits,_= strconv.Atoi(os.Args[2])}
sk := nostr.GeneratePrivateKey()
pk, _ := nostr.GetPublicKey(sk)
nostr_priv, _ := nip19.EncodePrivateKey(sk)
nostr_pub, _ := nip19.EncodePublicKey(pk)
fmt.Printf("Private key %v\n",sk)
fmt.Printf("Public key: %v\n", pk)
fmt.Printf("Private Nosstr encoded: %v\n",nostr_priv)
fmt.Printf("Public Nosstr encoded: %v\n",nostr_pub)
fmt.Printf("Message: %s\n",msg)
fmt.Printf("Zero bits: %d\n",bits)

ev := nostr.Event{
PubKey: pk,
CreatedAt: nostr.Now(),
Kind: nostr.KindTextNote,
Tags: nil,
Content: msg,
}

// func Generate(event *nostr.Event, targetDifficulty int, timeout time.Duration)
_,_=nip13.Generate(&ev,bits,1000000000)
ev.Sign(sk)

fmt.Printf("\nEvent ID: %s\n",ev.ID)
fmt.Printf("Event Tags: %v\n",ev.Tags)
fmt.Printf("Event Content: %v\n",ev.Content)
fmt.Printf("Event Sig: %v\n",ev.Sig)
fmt.Printf("Event Kind: %v\n",ev.Kind)
fmt.Printf("Event CreatedAt: %v\n",ev.CreatedAt)
fmt.Printf("Event Pubkey: %v\n",ev.PubKey)
}

And a sample run with eight bits of zeros in the ID [here]:

Private key 368aaef73fb8d6d72e81d7550b4df265a551785898db7e42cb48d16d00512992
Public key: 04d0da5cd03eca7d0bcc85a93c4b0f629f6387c124fca0fe88ade0b99fe737df
Private Nosstr encoded: nsec1x692aaelhrtdwt5p6a2skn0jvkj4z7zcnrdhusktfrgk6qz39xfqgcasyv
Public Nosstr encoded: npub1qngd5hxs8m986z7vsk5ncjc0v20k8p7pyn72pl5g4hstn8l8xl0sgghnkk
Message: Testing 123
Zero bits: 8
Event ID: 008e0a0ef600ea4483ed1c0fec98eb23e3762d95aab516d7f6a3c2f88291c211
Event Tags: [[nonce 108 8]]
Event Content: Testing 123
Event Sig: 3966744cfe232dea2186ac96cfbc09acc10b6d8703d9bc27d59f1555cd5459ae365af527d5e54c4bda1e335b282691f74652bf5bde9b21d170ebf79a8c355ee1
Event Kind: 1
Event CreatedAt: 1714987090
Event Pubkey: 04d0da5cd03eca7d0bcc85a93c4b0f629f6387c124fca0fe88ade0b99fe737df

And a sample run with 14 bits of zeros in the ID [here]:

Private key 892459ced613d12a73045042d41367b32485736477ca75c6d2a169a574a3aeeb
Public key: 7836dd4328ccbb71508c2f7b3f9ebd44cbe18179eba51f86f88af08b4fba14a2
Private Nosstr encoded: nsec13yj9nnkkz0gj5ucy2ppdgym8kvjg2umywl98t3kj59562a9r4m4syecul5
Public Nosstr encoded: npub10qmd6segejahz5yv9aanl84agn97rqteawj3lphc3tcgkna6zj3qsjjlxm
Message: Testing 123
Zero bits: 14

Event ID: 000248fba3d1039e350956d182aad1e08fa8e260c9bb0f0c884ee97edf4509ba
Event Tags: [[nonce 18028 14]]
Event Content: Testing 123
Event Sig: f8530c9467accaff96686d2d50b23a40f4492e88dd0176543ec42779bbdc66dfbbf83dc9e1558bdc38951545c8b37e51a12d88ec9eb249c994c41a2bb25d726b
Event Kind: 1
Event CreatedAt: 1714987022
Event Pubkey: 7836dd4328ccbb71508c2f7b3f9ebd44cbe18179eba51f86f88af08b4fba14a2

--

--

Prof Bill Buchanan OBE FRSE
ASecuritySite: When Bob Met Alice

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.