Nostr Proof of Work in GoWith 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. . |
Theory
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:
< 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 number of zero bit, otherwise it will be rejected.
Code
The following is some sample code:
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:
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
We can see that the nouce value required to create the ID is 108, 8. And a sample run with 14 bits of zeros in the ID:
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
We can see that the nouce value required to create the ID is 18028 14.