make timestamps into a struct with embedded value like the rest of the things
This commit is contained in:
109
event/canonical.go
Normal file
109
event/canonical.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package event
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
"realy.lol/hex"
|
||||
"realy.lol/json"
|
||||
"realy.lol/kind"
|
||||
"realy.lol/tags"
|
||||
"realy.lol/text"
|
||||
"realy.lol/timestamp"
|
||||
)
|
||||
|
||||
// ToCanonical converts the event to the canonical encoding used to derive the
|
||||
// event ID.
|
||||
func (ev *T) ToCanonical(dst by) (b by) {
|
||||
b = dst
|
||||
b = append(b, "[0,\""...)
|
||||
b = hex.EncAppend(b, ev.PubKey)
|
||||
b = append(b, "\","...)
|
||||
b = ev.CreatedAt.Marshal(b)
|
||||
b = append(b, ',')
|
||||
b = ev.Kind.Marshal(b)
|
||||
b = append(b, ',')
|
||||
b = ev.Tags.Marshal(b)
|
||||
b = append(b, ',')
|
||||
b = text.AppendQuote(b, ev.Content, text.NostrEscape)
|
||||
b = append(b, ']')
|
||||
return
|
||||
}
|
||||
|
||||
// GetIDBytes returns the raw SHA256 hash of the canonical form of an T.
|
||||
func (ev *T) GetIDBytes() by { return Hash(ev.ToCanonical(nil)) }
|
||||
|
||||
func NewCanonical() (a *json.Array) {
|
||||
a = &json.Array{
|
||||
V: []json.I{
|
||||
&json.Unsigned{}, // 0
|
||||
&json.Hex{}, // pubkey
|
||||
×tamp.T{}, // created_at
|
||||
&kind.T{}, // kind
|
||||
&tags.T{}, // tags
|
||||
&json.String{}, // content
|
||||
},
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func FromCanonical(b by) (ev *T, rem by, err er) {
|
||||
id := Hash(b)
|
||||
c := NewCanonical()
|
||||
if rem, err = c.Unmarshal(b); chk.E(err) {
|
||||
return
|
||||
}
|
||||
if len(rem) > 0 {
|
||||
log.I.F("rem %s", rem)
|
||||
}
|
||||
// unwrap the array
|
||||
x := (*c).V
|
||||
if v, ok := x[0].(*json.Unsigned); !ok {
|
||||
err = errorf.E("did not encode expected type in first field of canonical event %v %v",
|
||||
reflect.TypeOf(x[0]), x[0])
|
||||
return
|
||||
} else {
|
||||
if v.V != 0 {
|
||||
err = errorf.E("unexpected value %d in first field of canonical event, expect 0", v.V)
|
||||
return
|
||||
}
|
||||
}
|
||||
// create the event, use the ID hash to populate the ID
|
||||
ev = &T{ID: id}
|
||||
// unwrap the pubkey
|
||||
if v, ok := x[1].(*json.Hex); !ok {
|
||||
err = errorf.E("failed to decode pubkey from canonical form of event %s", b)
|
||||
return
|
||||
} else {
|
||||
ev.PubKey = v.V
|
||||
}
|
||||
// populate the timestamp field
|
||||
if v, ok := x[2].(*timestamp.T); !ok {
|
||||
err = errorf.E("did not encode expected type in third (created_at) field of canonical event %v %v",
|
||||
reflect.TypeOf(x[0]), x[0])
|
||||
} else {
|
||||
ev.CreatedAt = v
|
||||
}
|
||||
// populate the kind field
|
||||
if v, ok := x[3].(*kind.T); !ok {
|
||||
err = errorf.E("did not encode expected type in fourth (kind) field of canonical event %v %v",
|
||||
reflect.TypeOf(x[0]), x[0])
|
||||
} else {
|
||||
ev.Kind = v
|
||||
}
|
||||
// populate the tags field
|
||||
if v, ok := x[3].(*tags.T); !ok {
|
||||
err = errorf.E("did not encode expected type in fourth (tags) field of canonical event %v %v",
|
||||
reflect.TypeOf(x[0]), x[0])
|
||||
} else {
|
||||
ev.Tags = v
|
||||
}
|
||||
// populate the content field
|
||||
if v, ok := x[3].(*json.String); !ok {
|
||||
err = errorf.E("did not encode expected type in fourth (content) field of canonical event %v %v",
|
||||
reflect.TypeOf(x[0]), x[0])
|
||||
} else {
|
||||
ev.Content = v.V
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@@ -93,7 +93,7 @@ func main() {
|
||||
if len(rem) > 0 {
|
||||
log.I.F("remainder:\n%s", rem)
|
||||
}
|
||||
can := ev.ToCanonical()
|
||||
can := ev.ToCanonical(nil)
|
||||
eh := event.Hash(can)
|
||||
eq := equals(ev.ID, eh)
|
||||
if !eq {
|
||||
|
||||
@@ -40,7 +40,7 @@ type T struct {
|
||||
type Ts []*T
|
||||
|
||||
func (ev Ts) Len() no { return len(ev) }
|
||||
func (ev Ts) Less(i, j no) bo { return *ev[i].CreatedAt > *ev[j].CreatedAt }
|
||||
func (ev Ts) Less(i, j no) bo { return ev[i].CreatedAt.I64() > ev[j].CreatedAt.I64() }
|
||||
func (ev Ts) Swap(i, j no) { ev[i], ev[j] = ev[j], ev[i] }
|
||||
|
||||
type C chan *T
|
||||
@@ -49,21 +49,6 @@ func New() (ev *T) { return &T{} }
|
||||
|
||||
func (ev *T) Serialize() (b by) { return ev.Marshal(nil) }
|
||||
|
||||
func (ev *T) ToCanonical() (b by) {
|
||||
b = append(b, "[0,\""...)
|
||||
b = hex.EncAppend(b, ev.PubKey)
|
||||
b = append(b, "\","...)
|
||||
b = ev.CreatedAt.Marshal(b)
|
||||
b = append(b, ',')
|
||||
b = ev.Kind.Marshal(b)
|
||||
b = append(b, ',')
|
||||
b = ev.Tags.Marshal(b)
|
||||
b = append(b, ',')
|
||||
b = text.AppendQuote(b, ev.Content, text.NostrEscape)
|
||||
b = append(b, ']')
|
||||
return
|
||||
}
|
||||
|
||||
// stringy functions for retarded other libraries
|
||||
|
||||
func (ev *T) IDString() (s st) { return hex.Enc(ev.ID) }
|
||||
@@ -78,9 +63,6 @@ func Hash(in by) (out by) {
|
||||
return h[:]
|
||||
}
|
||||
|
||||
// GetIDBytes returns the raw SHA256 hash of the canonical form of an T.
|
||||
func (ev *T) GetIDBytes() by { return Hash(ev.ToCanonical()) }
|
||||
|
||||
func GenerateRandomTextNoteEvent(sign signer.I, maxSize no) (ev *T,
|
||||
err er) {
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ package event
|
||||
type Ascending []*T
|
||||
|
||||
func (ev Ascending) Len() no { return len(ev) }
|
||||
func (ev Ascending) Less(i, j no) bo { return *ev[i].CreatedAt < *ev[j].CreatedAt }
|
||||
func (ev Ascending) Less(i, j no) bo { return ev[i].CreatedAt.I64() < ev[j].CreatedAt.I64() }
|
||||
func (ev Ascending) Swap(i, j no) { ev[i], ev[j] = ev[j], ev[i] }
|
||||
|
||||
// Descending sorts a slice of events in reverse chronological order (newest
|
||||
@@ -12,5 +12,5 @@ func (ev Ascending) Swap(i, j no) { ev[i], ev[j] = ev[j], ev[i] }
|
||||
type Descending []*T
|
||||
|
||||
func (e Descending) Len() no { return len(e) }
|
||||
func (e Descending) Less(i, j no) bo { return *e[i].CreatedAt > *e[j].CreatedAt }
|
||||
func (e Descending) Less(i, j no) bo { return e[i].CreatedAt.I64() > e[j].CreatedAt.I64() }
|
||||
func (e Descending) Swap(i, j no) { e[i], e[j] = e[j], e[i] }
|
||||
|
||||
@@ -553,8 +553,7 @@ func GenFilter() (f *T, err er) {
|
||||
}
|
||||
}
|
||||
tn := no(timestamp.Now().I64())
|
||||
before := timestamp.T(tn - frand.Intn(10000))
|
||||
f.Since = &before
|
||||
f.Since = ×tamp.T{int64(tn - frand.Intn(10000))}
|
||||
f.Until = timestamp.Now()
|
||||
f.Search = by("token search text")
|
||||
return
|
||||
|
||||
@@ -21,6 +21,7 @@ func New[V uint | no | uint64 | uint32 | uint16 | uint8 | int64 | int32 | int16
|
||||
}
|
||||
|
||||
func (n *T) Uint64() uint64 { return n.N }
|
||||
func (n *T) Int64() int64 { return int64(n.N) }
|
||||
func (n *T) Uint16() uint16 { return uint16(n.N) }
|
||||
|
||||
var powers = []*T{
|
||||
|
||||
@@ -19,9 +19,7 @@ var _ keys.Element = &T{}
|
||||
|
||||
func New(c *timestamp.T) (p *T) { return &T{Val: c} }
|
||||
|
||||
func (c *T) Write(buf *bytes.Buffer) {
|
||||
buf.Write(c.Val.Bytes())
|
||||
}
|
||||
func (c *T) Write(buf *bytes.Buffer) { buf.Write(c.Val.Bytes()) }
|
||||
|
||||
func (c *T) Read(buf *bytes.Buffer) (el keys.Element) {
|
||||
b := make(by, Len)
|
||||
|
||||
@@ -158,18 +158,18 @@ func PrepareQueries(f *filter.T) (
|
||||
}
|
||||
// log.T.S("other", qs)
|
||||
}
|
||||
var until uint64 = math.MaxUint64
|
||||
var until int64 = math.MaxInt64
|
||||
if f.Until != nil {
|
||||
if fu := uint64(*f.Until); fu < until {
|
||||
if fu := f.Until.I64(); fu < until {
|
||||
until = fu - 1
|
||||
}
|
||||
}
|
||||
for i, q := range qs {
|
||||
qs[i].start = binary.BigEndian.AppendUint64(q.searchPrefix, until)
|
||||
qs[i].start = binary.BigEndian.AppendUint64(q.searchPrefix, uint64(until))
|
||||
}
|
||||
// this is where we'll end the iteration
|
||||
if f.Since != nil {
|
||||
if fs := uint64(*f.Since); fs > since {
|
||||
if fs := f.Since.U64(); fs > since {
|
||||
since = fs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
v1.2.40
|
||||
v1.2.41
|
||||
@@ -10,16 +10,13 @@ import (
|
||||
|
||||
// T is a convenience type for UNIX 64 bit timestamps of 1 second
|
||||
// precision.
|
||||
type T int64
|
||||
type T struct{ V int64 }
|
||||
|
||||
func New() (t *T) {
|
||||
tt := T(0)
|
||||
return &tt
|
||||
}
|
||||
func New() (t *T) { return &T{} }
|
||||
|
||||
// Now returns the current UNIX timestamp of the current second.
|
||||
func Now() *T {
|
||||
tt := T(time.Now().Unix())
|
||||
tt := T{time.Now().Unix()}
|
||||
return &tt
|
||||
}
|
||||
|
||||
@@ -28,7 +25,7 @@ func (t *T) U64() uint64 {
|
||||
if t == nil {
|
||||
return 0
|
||||
}
|
||||
return uint64(*t)
|
||||
return uint64(t.V)
|
||||
}
|
||||
|
||||
// I64 returns the current UNIX timestamp of the current second as int64.
|
||||
@@ -36,45 +33,37 @@ func (t *T) I64() int64 {
|
||||
if t == nil {
|
||||
return 0
|
||||
}
|
||||
return int64(*t)
|
||||
return t.V
|
||||
}
|
||||
|
||||
// Time converts a timestamp.Time value into a canonical UNIX 64 bit 1 second
|
||||
// precision timestamp.
|
||||
func (t *T) Time() time.Time { return time.Unix(int64(*t), 0) }
|
||||
func (t *T) Time() time.Time { return time.Unix(t.V, 0) }
|
||||
|
||||
// Int returns the timestamp as an int.
|
||||
func (t *T) Int() no {
|
||||
if t == nil {
|
||||
return 0
|
||||
}
|
||||
return no(*t)
|
||||
return no(t.V)
|
||||
}
|
||||
|
||||
func (t *T) Bytes() (b by) {
|
||||
b = make(by, 8)
|
||||
binary.BigEndian.PutUint64(b, uint64(*t))
|
||||
binary.BigEndian.PutUint64(b, uint64(t.V))
|
||||
return
|
||||
}
|
||||
|
||||
// FromTime returns a T from a time.Time
|
||||
func FromTime(t time.Time) *T {
|
||||
tt := T(t.Unix())
|
||||
return &tt
|
||||
}
|
||||
func FromTime(t time.Time) *T { return &T{t.Unix()} }
|
||||
|
||||
// FromUnix converts from a standard int64 unix timestamp.
|
||||
func FromUnix(t int64) *T {
|
||||
tt := T(t)
|
||||
return &tt
|
||||
}
|
||||
func (t *T) FromInt(i no) { *t = T(i) }
|
||||
func FromUnix(t int64) *T { return &T{t} }
|
||||
|
||||
func (t *T) FromInt(i no) { *t = T{int64(i)} }
|
||||
|
||||
// FromBytes converts from a string of raw bytes.
|
||||
func FromBytes(b by) *T {
|
||||
tt := T(binary.BigEndian.Uint64(b))
|
||||
return &tt
|
||||
}
|
||||
func FromBytes(b by) *T { return &T{int64(binary.BigEndian.Uint64(b))} }
|
||||
|
||||
func FromVarint(b by) (t *T, rem by, err er) {
|
||||
n, read := binary.Varint(b)
|
||||
@@ -82,13 +71,12 @@ func FromVarint(b by) (t *T, rem by, err er) {
|
||||
err = errorf.E("failed to decode varint timestamp %v", b)
|
||||
return
|
||||
}
|
||||
tt := T(n)
|
||||
t = &tt
|
||||
t = &T{n}
|
||||
rem = b[:read]
|
||||
return
|
||||
}
|
||||
|
||||
func ToVarint(dst by, t *T) by { return binary.AppendVarint(dst, int64(*t)) }
|
||||
func ToVarint(dst by, t *T) by { return binary.AppendVarint(dst, t.V) }
|
||||
|
||||
func (t *T) FromVarint(dst by) (b by) { return ToVarint(dst, t) }
|
||||
|
||||
@@ -99,14 +87,11 @@ func (t *T) String() (s st) {
|
||||
return unsafe.String(&b[0], len(b))
|
||||
}
|
||||
|
||||
func (t *T) Marshal(dst by) (b by) {
|
||||
tt := ints.New(t.U64())
|
||||
return tt.Marshal(dst)
|
||||
}
|
||||
func (t *T) Marshal(dst by) (b by) { return ints.New(t.U64()).Marshal(dst) }
|
||||
|
||||
func (t *T) Unmarshal(b by) (r by, err er) {
|
||||
n := ints.New(0)
|
||||
r, err = n.Unmarshal(b)
|
||||
*t = T(n.Uint64())
|
||||
*t = T{n.Int64()}
|
||||
return
|
||||
}
|
||||
|
||||
10
ws/pool.go
10
ws/pool.go
@@ -149,7 +149,7 @@ func (pool *SimplePool) subMany(c cx, urls []st, ff *filters.T,
|
||||
ctx, cancel := context.Cancel(c)
|
||||
_ = cancel // do this so `go vet` will stop complaining
|
||||
events := make(chan IncomingEvent)
|
||||
seenAlready := xsync.NewMapOf[st, timestamp.T]()
|
||||
seenAlready := xsync.NewMapOf[st, *timestamp.T]()
|
||||
ticker := time.NewTicker(time.Duration(seenAlreadyDropTick) * time.Second)
|
||||
eose := false
|
||||
pending := xsync.NewCounter()
|
||||
@@ -215,7 +215,7 @@ func (pool *SimplePool) subMany(c cx, urls []st, ff *filters.T,
|
||||
}
|
||||
if unique {
|
||||
if _, seen := seenAlready.LoadOrStore(evt.EventID().String(),
|
||||
*evt.CreatedAt); seen {
|
||||
evt.CreatedAt); seen {
|
||||
continue
|
||||
}
|
||||
}
|
||||
@@ -225,9 +225,9 @@ func (pool *SimplePool) subMany(c cx, urls []st, ff *filters.T,
|
||||
}
|
||||
case <-ticker.C:
|
||||
if eose {
|
||||
old := timestamp.T(timestamp.Now().Int() - seenAlreadyDropTick)
|
||||
seenAlready.Range(func(id st, value timestamp.T) bo {
|
||||
if value < old {
|
||||
old := ×tamp.T{int64(timestamp.Now().Int() - seenAlreadyDropTick)}
|
||||
seenAlready.Range(func(id st, value *timestamp.T) bo {
|
||||
if value.I64() < old.I64() {
|
||||
seenAlready.Delete(id)
|
||||
}
|
||||
return true
|
||||
|
||||
Reference in New Issue
Block a user