nson

package
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 27, 2024 License: GPL-2.0, MIT Imports: 14 Imported by: 0

README

NSON

A crazy way to encode Nostr events into valid JSON that is also much faster to decode as long as they are actually encoded using the strict NSON encoding and the decoder is prepared to read it using a NSON decoder.

See https://github.com/nostr-protocol/nips/pull/515.

Some benchmarks:

goos: linux
goarch: amd64
pkg: github.com/nbd-wtf/go-nostr/nson
cpu: AMD Ryzen 3 3200G with Radeon Vega Graphics
BenchmarkNSONEncoding/json.Marshal-4                6214            230680 ns/op
BenchmarkNSONEncoding/nson.Marshal-4                4520            319058 ns/op
BenchmarkNSONDecoding/json.Unmarshal-4              3741            280641 ns/op
BenchmarkNSONDecoding/nson.Unmarshal-4             46519             23762 ns/op
BenchmarkNSONDecoding/json.Unmarshal_+_sig_verification-4                    352           3218583 ns/op
BenchmarkNSONDecoding/nson.Unmarshal_+_sig_verification-4                    451           2739238 ns/op
PASS
ok      github.com/nbd-wtf/go-nostr/nson        8.291s

It takes a little while more to encode (although it's probably possible to optimize that), but decodes at 10x the speed of normal JSON.

The performance gain is real, but negligible once you add hash validation and signature verification, so it should be used wisely, mostly for situations in which the reader wouldn't care about the signature, e.g. reading from a local database.

How it works

It's explained better in the NIP proposal linked above, but the idea is that we encode field offset and sizes into a special JSON attribute called "nson", and then the reader can just pull the strings directly from the JSON blob without having to parse the full JSON syntax. Also for fields of static size we don't even need that. This is only possible because Nostr events have a static and strict format.

Update: comparison with easyjson

Another comparison, using the easyjson library that is already built in go-nostr, shows that the performance gains are only of 2x (the standard library JSON encoding is just too slow).

goos: linux
goarch: amd64
pkg: github.com/nbd-wtf/go-nostr/nson
cpu: AMD Ryzen 3 3200G with Radeon Vega Graphics
BenchmarkNSONEncoding/easyjson.Marshal-4                   21511             54849 ns/op
BenchmarkNSONEncoding/nson.Marshal-4                        4810            297624 ns/op
BenchmarkNSONDecoding/easyjson.Unmarshal-4                 25196             46652 ns/op
BenchmarkNSONDecoding/nson.Unmarshal-4                     61117             22933 ns/op
BenchmarkNSONDecoding/easyjson.Unmarshal+sig-4               303           4110988 ns/op
BenchmarkNSONDecoding/nson.Unmarshal+sig-4                   296           3881435 ns/op
PASS
ok      github.com/nbd-wtf/go-nostr/nson

Documentation

Index

Constants

View Source
const (
	IdStart        = 7
	IdEnd          = 7 + 64
	PubkeyStart    = 83
	PubkeyEnd      = 83 + 64
	SigStart       = 156
	SigEnd         = 156 + 128
	CreatedAtStart = 299
	CreatedAtEnd   = 299 + 10

	StringStart = 318     // the actual json string for the "nson" field
	ValuesStart = 318 + 2 // skipping the first byte which delimits the nson size

	MarkerStart = 309 // this is used just to determine if an event is nson or not
	MarkerEnd   = 317 // it's just the `,"nson":` (including ,": garbage to reduce false positives) part
)

Variables

View Source
var ErrNotNSON = fmt.Errorf("not nson")

Functions

func Marshal

func Marshal(evt *event.T) (string, error)

func MarshalBytes

func MarshalBytes(evt *event.T) ([]byte, error)

func Unmarshal

func Unmarshal(data string, evt *event.T) (err error)

Unmarshal turns a NSON string into a event.T struct.

func UnmarshalBytes

func UnmarshalBytes(data []byte, evt *event.T) (err error)

Types

type Event

type Event struct {
	// contains filtered or unexported fields
}

An Event is basically a wrapper over the string that makes it easy to get each event property (except tags).

func New

func New(nsonText string) Event

func (*Event) GetContent

func (ne *Event) GetContent() string

func (*Event) GetCreatedAt

func (ne *Event) GetCreatedAt() timestamp.T

func (*Event) GetID

func (ne *Event) GetID() string

func (*Event) GetKind

func (ne *Event) GetKind() int

func (*Event) GetPubkey

func (ne *Event) GetPubkey() string

func (*Event) GetSig

func (ne *Event) GetSig() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL