use xhex everywhere.
This commit is contained in:
10
envelopes.go
10
envelopes.go
@@ -1,7 +1,6 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -10,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/mailru/easyjson"
|
"github.com/mailru/easyjson"
|
||||||
jwriter "github.com/mailru/easyjson/jwriter"
|
jwriter "github.com/mailru/easyjson/jwriter"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -187,7 +187,7 @@ func (v *CountEnvelope) FromJSON(data string) error {
|
|||||||
if err := json.Unmarshal(unsafe.Slice(unsafe.StringData(arr[2].Raw), len(arr[2].Raw)), &countResult); err == nil && countResult.Count != nil {
|
if err := json.Unmarshal(unsafe.Slice(unsafe.StringData(arr[2].Raw), len(arr[2].Raw)), &countResult); err == nil && countResult.Count != nil {
|
||||||
v.Count = countResult.Count
|
v.Count = countResult.Count
|
||||||
if len(countResult.HLL) == 512 {
|
if len(countResult.HLL) == 512 {
|
||||||
v.HyperLogLog, err = hex.DecodeString(countResult.HLL)
|
v.HyperLogLog, err = HexDecodeString(countResult.HLL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid \"hll\" value in COUNT message: %w", err)
|
return fmt.Errorf("invalid \"hll\" value in COUNT message: %w", err)
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ func (v CountEnvelope) MarshalJSON() ([]byte, error) {
|
|||||||
if v.HyperLogLog != nil {
|
if v.HyperLogLog != nil {
|
||||||
w.RawString(`,"hll":"`)
|
w.RawString(`,"hll":"`)
|
||||||
hllHex := make([]byte, 512)
|
hllHex := make([]byte, 512)
|
||||||
hex.Encode(hllHex, v.HyperLogLog)
|
xhex.Encode(hllHex, v.HyperLogLog)
|
||||||
w.Buffer.AppendBytes(hllHex)
|
w.Buffer.AppendBytes(hllHex)
|
||||||
w.RawString(`"`)
|
w.RawString(`"`)
|
||||||
}
|
}
|
||||||
@@ -365,7 +365,7 @@ func (v *OKEnvelope) FromJSON(data string) error {
|
|||||||
if len(arr) < 4 {
|
if len(arr) < 4 {
|
||||||
return fmt.Errorf("failed to decode OK envelope: missing fields")
|
return fmt.Errorf("failed to decode OK envelope: missing fields")
|
||||||
}
|
}
|
||||||
if _, err := hex.Decode(v.EventID[:], []byte(arr[1].Str)); err != nil {
|
if err := xhex.Decode(v.EventID[:], []byte(arr[1].Str)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
v.OK = arr[2].Raw == "true"
|
v.OK = arr[2].Raw == "true"
|
||||||
@@ -377,7 +377,7 @@ func (v *OKEnvelope) FromJSON(data string) error {
|
|||||||
func (v OKEnvelope) MarshalJSON() ([]byte, error) {
|
func (v OKEnvelope) MarshalJSON() ([]byte, error) {
|
||||||
w := jwriter.Writer{NoEscapeHTML: true}
|
w := jwriter.Writer{NoEscapeHTML: true}
|
||||||
w.RawString(`["OK","`)
|
w.RawString(`["OK","`)
|
||||||
w.RawString(hex.EncodeToString(v.EventID[:]))
|
w.RawString(HexEncodeToString(v.EventID[:]))
|
||||||
w.RawString(`",`)
|
w.RawString(`",`)
|
||||||
ok := "false"
|
ok := "false"
|
||||||
if v.OK {
|
if v.OK {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
"testing"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseMessage(t *testing.T) {
|
func TestParseMessage(t *testing.T) {
|
||||||
@@ -139,6 +139,6 @@ func TestParseMessage(t *testing.T) {
|
|||||||
|
|
||||||
func mustSigFromHex(sigStr string) [64]byte {
|
func mustSigFromHex(sigStr string) [64]byte {
|
||||||
var sig [64]byte
|
var sig [64]byte
|
||||||
hex.Decode(sig[:], unsafe.Slice(unsafe.StringData(sigStr), 128))
|
xhex.Decode(sig[:], unsafe.Slice(unsafe.StringData(sigStr), 128))
|
||||||
return sig
|
return sig
|
||||||
}
|
}
|
||||||
|
|||||||
11
event.go
11
event.go
@@ -2,10 +2,10 @@ package nostr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/mailru/easyjson"
|
"github.com/mailru/easyjson"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Event represents a Nostr event.
|
// Event represents a Nostr event.
|
||||||
@@ -38,15 +38,12 @@ func (evt Event) CheckID() bool {
|
|||||||
func (evt Event) Serialize() []byte {
|
func (evt Event) Serialize() []byte {
|
||||||
// the serialization process is just putting everything into a JSON array
|
// the serialization process is just putting everything into a JSON array
|
||||||
// so the order is kept. See NIP-01
|
// so the order is kept. See NIP-01
|
||||||
dst := make([]byte, 0, 100+len(evt.Content)+len(evt.Tags)*80)
|
dst := make([]byte, 4+64, 100+len(evt.Content)+len(evt.Tags)*80)
|
||||||
return serializeEventInto(evt, dst)
|
|
||||||
}
|
|
||||||
|
|
||||||
func serializeEventInto(evt Event, dst []byte) []byte {
|
|
||||||
// the header portion is easy to serialize
|
// the header portion is easy to serialize
|
||||||
// [0,"pubkey",created_at,kind,[
|
// [0,"pubkey",created_at,kind,[
|
||||||
dst = append(dst, `[0,"`...)
|
copy(dst, `[0,"`)
|
||||||
dst = hex.AppendEncode(dst, evt.PubKey[:])
|
xhex.Encode(dst[4:4+64], evt.PubKey[:]) // there will always be such capacity
|
||||||
dst = append(dst, `",`...)
|
dst = append(dst, `",`...)
|
||||||
dst = append(dst, strconv.FormatInt(int64(evt.CreatedAt), 10)...)
|
dst = append(dst, strconv.FormatInt(int64(evt.CreatedAt), 10)...)
|
||||||
dst = append(dst, `,`...)
|
dst = append(dst, `,`...)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
|
|
||||||
jlexer "github.com/mailru/easyjson/jlexer"
|
jlexer "github.com/mailru/easyjson/jlexer"
|
||||||
jwriter "github.com/mailru/easyjson/jwriter"
|
jwriter "github.com/mailru/easyjson/jwriter"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func easyjsonDecodeEvent(in *jlexer.Lexer, out *Event) {
|
func easyjsonDecodeEvent(in *jlexer.Lexer, out *Event) {
|
||||||
@@ -29,12 +28,12 @@ func easyjsonDecodeEvent(in *jlexer.Lexer, out *Event) {
|
|||||||
case "id":
|
case "id":
|
||||||
b := in.UnsafeBytes()
|
b := in.UnsafeBytes()
|
||||||
if len(b) == 64 {
|
if len(b) == 64 {
|
||||||
hex.Decode(out.ID[:], b)
|
xhex.Decode(out.ID[:], b)
|
||||||
}
|
}
|
||||||
case "pubkey":
|
case "pubkey":
|
||||||
b := in.UnsafeBytes()
|
b := in.UnsafeBytes()
|
||||||
if len(b) == 64 {
|
if len(b) == 64 {
|
||||||
hex.Decode(out.PubKey[:], b)
|
xhex.Decode(out.PubKey[:], b)
|
||||||
}
|
}
|
||||||
case "created_at":
|
case "created_at":
|
||||||
out.CreatedAt = Timestamp(in.Int64())
|
out.CreatedAt = Timestamp(in.Int64())
|
||||||
@@ -73,7 +72,7 @@ func easyjsonDecodeEvent(in *jlexer.Lexer, out *Event) {
|
|||||||
case "sig":
|
case "sig":
|
||||||
b := in.UnsafeBytes()
|
b := in.UnsafeBytes()
|
||||||
if len(b) == 128 {
|
if len(b) == 128 {
|
||||||
hex.Decode(out.Sig[:], b)
|
xhex.Decode(out.Sig[:], b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
in.WantComma()
|
in.WantComma()
|
||||||
@@ -92,12 +91,12 @@ func easyjsonEncodeEvent(out *jwriter.Writer, in Event) {
|
|||||||
|
|
||||||
if in.ID != ZeroID {
|
if in.ID != ZeroID {
|
||||||
out.RawString(",\"id\":\"")
|
out.RawString(",\"id\":\"")
|
||||||
out.RawString(hex.EncodeToString(in.ID[:]) + "\"")
|
out.RawString(HexEncodeToString(in.ID[:]) + "\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
if in.PubKey != ZeroPK {
|
if in.PubKey != ZeroPK {
|
||||||
out.RawString(",\"pubkey\":\"")
|
out.RawString(",\"pubkey\":\"")
|
||||||
out.RawString(hex.EncodeToString(in.PubKey[:]) + "\"")
|
out.RawString(HexEncodeToString(in.PubKey[:]) + "\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
out.RawString(",\"created_at\":")
|
out.RawString(",\"created_at\":")
|
||||||
@@ -125,7 +124,7 @@ func easyjsonEncodeEvent(out *jwriter.Writer, in Event) {
|
|||||||
|
|
||||||
if in.Sig != [64]byte{} {
|
if in.Sig != [64]byte{} {
|
||||||
out.RawString(",\"sig\":\"")
|
out.RawString(",\"sig\":\"")
|
||||||
out.RawString(hex.EncodeToString(in.Sig[:]) + "\"")
|
out.RawString(HexEncodeToString(in.Sig[:]) + "\"")
|
||||||
}
|
}
|
||||||
|
|
||||||
out.RawByte('}')
|
out.RawByte('}')
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand/v2"
|
"math/rand/v2"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEventParsingAndVerifying(t *testing.T) {
|
func TestEventParsingAndVerifying(t *testing.T) {
|
||||||
@@ -36,7 +36,7 @@ func TestEventParsingAndVerifying(t *testing.T) {
|
|||||||
|
|
||||||
func TestEventSerialization(t *testing.T) {
|
func TestEventSerialization(t *testing.T) {
|
||||||
sig := [64]byte{}
|
sig := [64]byte{}
|
||||||
hex.Decode(sig[:], []byte("ed08d2dd5b0f7b6a3cdc74643d4adee3158ddede9cc848e8cd97630c097001acc2d052d2d3ec2b7ac4708b2314b797106d1b3c107322e61b5e5cc2116e099b79"))
|
xhex.Decode(sig[:], []byte("ed08d2dd5b0f7b6a3cdc74643d4adee3158ddede9cc848e8cd97630c097001acc2d052d2d3ec2b7ac4708b2314b797106d1b3c107322e61b5e5cc2116e099b79"))
|
||||||
|
|
||||||
events := []Event{
|
events := []Event{
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package bluge
|
package bluge
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -23,6 +22,6 @@ func (id eventIdentifier) Field() string {
|
|||||||
|
|
||||||
func (id eventIdentifier) Term() []byte {
|
func (id eventIdentifier) Term() []byte {
|
||||||
idhex := make([]byte, 64)
|
idhex := make([]byte, 64)
|
||||||
hex.Encode(idhex, id[:])
|
xhex.Encode(idhex, id[:])
|
||||||
return idhex
|
return idhex
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package boltdb
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"fiatjaf.com/nostr/eventstore/codec/betterbinary"
|
"fiatjaf.com/nostr/eventstore/codec/betterbinary"
|
||||||
"fiatjaf.com/nostr/nip45"
|
"fiatjaf.com/nostr/nip45"
|
||||||
"fiatjaf.com/nostr/nip45/hyperloglog"
|
"fiatjaf.com/nostr/nip45/hyperloglog"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -174,11 +174,11 @@ func (b *BoltBackend) countEventsHLLCached(filter nostr.Filter) (uint32, *hyperl
|
|||||||
binary.BigEndian.PutUint16(cacheKey[0:2], uint16(filter.Kinds[0]))
|
binary.BigEndian.PutUint16(cacheKey[0:2], uint16(filter.Kinds[0]))
|
||||||
switch filter.Kinds[0] {
|
switch filter.Kinds[0] {
|
||||||
case 3:
|
case 3:
|
||||||
hex.Decode(cacheKey[2:2+8], []byte(filter.Tags["p"][0][0:8*2]))
|
xhex.Decode(cacheKey[2:2+8], []byte(filter.Tags["p"][0][0:8*2]))
|
||||||
case 7:
|
case 7:
|
||||||
hex.Decode(cacheKey[2:2+8], []byte(filter.Tags["e"][0][0:8*2]))
|
xhex.Decode(cacheKey[2:2+8], []byte(filter.Tags["e"][0][0:8*2]))
|
||||||
case 1111:
|
case 1111:
|
||||||
hex.Decode(cacheKey[2:2+8], []byte(filter.Tags["E"][0][0:8*2]))
|
xhex.Decode(cacheKey[2:2+8], []byte(filter.Tags["E"][0][0:8*2]))
|
||||||
}
|
}
|
||||||
|
|
||||||
var count uint32
|
var count uint32
|
||||||
@@ -204,7 +204,7 @@ func (b *BoltBackend) updateHyperLogLogCachedValues(txn *bbolt.Tx, evt nostr.Eve
|
|||||||
|
|
||||||
for ref, offset := range nip45.HyperLogLogEventPubkeyOffsetsAndReferencesForEvent(evt) {
|
for ref, offset := range nip45.HyperLogLogEventPubkeyOffsetsAndReferencesForEvent(evt) {
|
||||||
// setup cache key (reusing buffer)
|
// setup cache key (reusing buffer)
|
||||||
hex.Decode(cacheKey[2:2+8], []byte(ref[0:8*2]))
|
xhex.Decode(cacheKey[2:2+8], []byte(ref[0:8*2]))
|
||||||
|
|
||||||
// fetch hll value from cache db
|
// fetch hll value from cache db
|
||||||
hll := hyperloglog.New(offset)
|
hll := hyperloglog.New(offset)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"iter"
|
"iter"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -12,6 +11,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
"go.etcd.io/bbolt"
|
"go.etcd.io/bbolt"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ func (b *BoltBackend) getTagIndexPrefix(tagName string, tagValue string) (bucket
|
|||||||
if len(tagValue) == 64 {
|
if len(tagValue) == 64 {
|
||||||
// but we actually only use the first 8 bytes, with letter (tag name) prefix
|
// but we actually only use the first 8 bytes, with letter (tag name) prefix
|
||||||
k = make([]byte, 1+8+4+8)
|
k = make([]byte, 1+8+4+8)
|
||||||
if _, err := hex.Decode(k[1:1+8], []byte(tagValue[0:8*2])); err == nil {
|
if err := xhex.Decode(k[1:1+8], []byte(tagValue[0:8*2])); err == nil {
|
||||||
k[0] = letterPrefix
|
k[0] = letterPrefix
|
||||||
return indexTag32, k
|
return indexTag32, k
|
||||||
}
|
}
|
||||||
@@ -294,7 +294,7 @@ func (b *BoltBackend) getTagIndexPrefix(tagName string, tagValue string) (bucket
|
|||||||
spl := strings.Split(tagValue, ":")
|
spl := strings.Split(tagValue, ":")
|
||||||
if len(spl) == 3 && len(spl[1]) == 64 {
|
if len(spl) == 3 && len(spl[1]) == 64 {
|
||||||
k = make([]byte, 1+2+8+30+4+8)
|
k = make([]byte, 1+2+8+30+4+8)
|
||||||
if _, err := hex.Decode(k[1+2:1+2+8], []byte(spl[1][0:8*2])); err == nil {
|
if err := xhex.Decode(k[1+2:1+2+8], []byte(spl[1][0:8*2])); err == nil {
|
||||||
if kind, err := strconv.ParseUint(spl[0], 10, 16); err == nil {
|
if kind, err := strconv.ParseUint(spl[0], 10, 16); err == nil {
|
||||||
k[0] = letterPrefix
|
k[0] = letterPrefix
|
||||||
k[1] = byte(kind >> 8)
|
k[1] = byte(kind >> 8)
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package lmdb
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
@@ -11,6 +10,7 @@ import (
|
|||||||
"fiatjaf.com/nostr/nip45"
|
"fiatjaf.com/nostr/nip45"
|
||||||
"fiatjaf.com/nostr/nip45/hyperloglog"
|
"fiatjaf.com/nostr/nip45/hyperloglog"
|
||||||
"github.com/PowerDNS/lmdb-go/lmdb"
|
"github.com/PowerDNS/lmdb-go/lmdb"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (b *LMDBBackend) CountEvents(filter nostr.Filter) (uint32, error) {
|
func (b *LMDBBackend) CountEvents(filter nostr.Filter) (uint32, error) {
|
||||||
@@ -185,11 +185,11 @@ func (b *LMDBBackend) countEventsHLLCached(filter nostr.Filter) (uint32, *hyperl
|
|||||||
binary.BigEndian.PutUint16(cacheKey[0:2], uint16(filter.Kinds[0]))
|
binary.BigEndian.PutUint16(cacheKey[0:2], uint16(filter.Kinds[0]))
|
||||||
switch filter.Kinds[0] {
|
switch filter.Kinds[0] {
|
||||||
case 3:
|
case 3:
|
||||||
hex.Decode(cacheKey[2:2+8], []byte(filter.Tags["p"][0][0:8*2]))
|
xhex.Decode(cacheKey[2:2+8], []byte(filter.Tags["p"][0][0:8*2]))
|
||||||
case 7:
|
case 7:
|
||||||
hex.Decode(cacheKey[2:2+8], []byte(filter.Tags["e"][0][0:8*2]))
|
xhex.Decode(cacheKey[2:2+8], []byte(filter.Tags["e"][0][0:8*2]))
|
||||||
case 1111:
|
case 1111:
|
||||||
hex.Decode(cacheKey[2:2+8], []byte(filter.Tags["E"][0][0:8*2]))
|
xhex.Decode(cacheKey[2:2+8], []byte(filter.Tags["E"][0][0:8*2]))
|
||||||
}
|
}
|
||||||
|
|
||||||
var count uint32
|
var count uint32
|
||||||
@@ -217,7 +217,7 @@ func (b *LMDBBackend) updateHyperLogLogCachedValues(txn *lmdb.Txn, evt nostr.Eve
|
|||||||
|
|
||||||
for ref, offset := range nip45.HyperLogLogEventPubkeyOffsetsAndReferencesForEvent(evt) {
|
for ref, offset := range nip45.HyperLogLogEventPubkeyOffsetsAndReferencesForEvent(evt) {
|
||||||
// setup cache key (reusing buffer)
|
// setup cache key (reusing buffer)
|
||||||
hex.Decode(cacheKey[2:2+8], []byte(ref[0:8*2]))
|
xhex.Decode(cacheKey[2:2+8], []byte(ref[0:8*2]))
|
||||||
|
|
||||||
// fetch hll value from cache db
|
// fetch hll value from cache db
|
||||||
hll := hyperloglog.New(offset)
|
hll := hyperloglog.New(offset)
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"iter"
|
"iter"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -13,6 +12,7 @@ import (
|
|||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"github.com/PowerDNS/lmdb-go/lmdb"
|
"github.com/PowerDNS/lmdb-go/lmdb"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
type iterator struct {
|
type iterator struct {
|
||||||
@@ -244,7 +244,7 @@ func (b *LMDBBackend) getIndexKeysForEvent(evt nostr.Event) iter.Seq[key] {
|
|||||||
// now the p-tag+kind+date
|
// now the p-tag+kind+date
|
||||||
if dbi == b.indexTag32 && tag[0] == "p" {
|
if dbi == b.indexTag32 && tag[0] == "p" {
|
||||||
k := make([]byte, 8+2+4)
|
k := make([]byte, 8+2+4)
|
||||||
hex.Decode(k[0:8], []byte(tag[1][0:8*2]))
|
xhex.Decode(k[0:8], []byte(tag[1][0:8*2]))
|
||||||
binary.BigEndian.PutUint16(k[8:8+2], uint16(evt.Kind))
|
binary.BigEndian.PutUint16(k[8:8+2], uint16(evt.Kind))
|
||||||
binary.BigEndian.PutUint32(k[8+2:8+2+4], uint32(evt.CreatedAt))
|
binary.BigEndian.PutUint32(k[8+2:8+2+4], uint32(evt.CreatedAt))
|
||||||
dbi := b.indexPTagKind
|
dbi := b.indexPTagKind
|
||||||
@@ -276,7 +276,7 @@ func (b *LMDBBackend) getTagIndexPrefix(tagName string, tagValue string) (lmdb.D
|
|||||||
if len(tagValue) == 64 {
|
if len(tagValue) == 64 {
|
||||||
// but we actually only use the first 8 bytes, with letter (tag name) prefix
|
// but we actually only use the first 8 bytes, with letter (tag name) prefix
|
||||||
k = make([]byte, 1+8+4)
|
k = make([]byte, 1+8+4)
|
||||||
if _, err := hex.Decode(k[1:1+8], []byte(tagValue[0:8*2])); err == nil {
|
if err := xhex.Decode(k[1:1+8], []byte(tagValue[0:8*2])); err == nil {
|
||||||
k[0] = letterPrefix
|
k[0] = letterPrefix
|
||||||
offset = 1 + 8
|
offset = 1 + 8
|
||||||
dbi = b.indexTag32
|
dbi = b.indexTag32
|
||||||
@@ -288,7 +288,7 @@ func (b *LMDBBackend) getTagIndexPrefix(tagName string, tagValue string) (lmdb.D
|
|||||||
spl := strings.Split(tagValue, ":")
|
spl := strings.Split(tagValue, ":")
|
||||||
if len(spl) == 3 && len(spl[1]) == 64 {
|
if len(spl) == 3 && len(spl[1]) == 64 {
|
||||||
k = make([]byte, 1+2+8+30+4)
|
k = make([]byte, 1+2+8+30+4)
|
||||||
if _, err := hex.Decode(k[1+2:1+2+8], []byte(spl[1][0:8*2])); err == nil {
|
if err := xhex.Decode(k[1+2:1+2+8], []byte(spl[1][0:8*2])); err == nil {
|
||||||
if kind, err := strconv.ParseUint(spl[0], 10, 16); err == nil {
|
if kind, err := strconv.ParseUint(spl[0], 10, 16); err == nil {
|
||||||
k[0] = letterPrefix
|
k[0] = letterPrefix
|
||||||
k[1] = byte(kind >> 8)
|
k[1] = byte(kind >> 8)
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package lmdb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"fiatjaf.com/nostr/eventstore/internal"
|
"fiatjaf.com/nostr/eventstore/internal"
|
||||||
"github.com/PowerDNS/lmdb-go/lmdb"
|
"github.com/PowerDNS/lmdb-go/lmdb"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
type query struct {
|
type query struct {
|
||||||
@@ -76,7 +76,7 @@ func (b *LMDBBackend) prepareQueries(filter nostr.Filter) (
|
|||||||
|
|
||||||
for _, kind := range filter.Kinds {
|
for _, kind := range filter.Kinds {
|
||||||
k := make([]byte, 8+2)
|
k := make([]byte, 8+2)
|
||||||
if _, err := hex.Decode(k[0:8], []byte(value[0:8*2])); err != nil {
|
if err := xhex.Decode(k[0:8], []byte(value[0:8*2])); err != nil {
|
||||||
return nil, nil, nil, "", nil, 0, fmt.Errorf("invalid 'p' tag '%s'", value)
|
return nil, nil, nil, "", nil, 0, fmt.Errorf("invalid 'p' tag '%s'", value)
|
||||||
}
|
}
|
||||||
binary.BigEndian.PutUint16(k[8:8+2], uint16(kind))
|
binary.BigEndian.PutUint16(k[8:8+2], uint16(kind))
|
||||||
@@ -93,7 +93,7 @@ func (b *LMDBBackend) prepareQueries(filter nostr.Filter) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
k := make([]byte, 8)
|
k := make([]byte, 8)
|
||||||
if _, err := hex.Decode(k[0:8], []byte(value[0:8*2])); err != nil {
|
if err := xhex.Decode(k[0:8], []byte(value[0:8*2])); err != nil {
|
||||||
return nil, nil, nil, "", nil, 0, fmt.Errorf("invalid 'p' tag '%s'", value)
|
return nil, nil, nil, "", nil, 0, fmt.Errorf("invalid 'p' tag '%s'", value)
|
||||||
}
|
}
|
||||||
queries[i] = query{i: i, dbi: b.indexPTagKind, prefix: k[0:8], keySize: 8 + 2 + 4}
|
queries[i] = query{i: i, dbi: b.indexPTagKind, prefix: k[0:8], keySize: 8 + 2 + 4}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package mmm
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"iter"
|
"iter"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -11,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"github.com/PowerDNS/lmdb-go/lmdb"
|
"github.com/PowerDNS/lmdb-go/lmdb"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
type iterator struct {
|
type iterator struct {
|
||||||
@@ -229,7 +229,7 @@ func (il *IndexingLayer) getIndexKeysForEvent(evt nostr.Event) iter.Seq[key] {
|
|||||||
// now the p-tag+kind+date
|
// now the p-tag+kind+date
|
||||||
if dbi == il.indexTag32 && tag[0] == "p" {
|
if dbi == il.indexTag32 && tag[0] == "p" {
|
||||||
k := make([]byte, 8+2+4)
|
k := make([]byte, 8+2+4)
|
||||||
hex.Decode(k[0:8], []byte(tag[1][0:8*2]))
|
xhex.Decode(k[0:8], []byte(tag[1][0:8*2]))
|
||||||
binary.BigEndian.PutUint16(k[8:8+2], uint16(evt.Kind))
|
binary.BigEndian.PutUint16(k[8:8+2], uint16(evt.Kind))
|
||||||
binary.BigEndian.PutUint32(k[8+2:8+2+4], uint32(evt.CreatedAt))
|
binary.BigEndian.PutUint32(k[8+2:8+2+4], uint32(evt.CreatedAt))
|
||||||
dbi := il.indexPTagKind
|
dbi := il.indexPTagKind
|
||||||
@@ -261,7 +261,7 @@ func (il *IndexingLayer) getTagIndexPrefix(tagName string, tagValue string) (lmd
|
|||||||
if len(tagValue) == 64 {
|
if len(tagValue) == 64 {
|
||||||
// but we actually only use the first 8 bytes, with letter (tag name) prefix
|
// but we actually only use the first 8 bytes, with letter (tag name) prefix
|
||||||
k = make([]byte, 1+8+4)
|
k = make([]byte, 1+8+4)
|
||||||
if _, err := hex.Decode(k[1:1+8], []byte(tagValue[0:8*2])); err == nil {
|
if err := xhex.Decode(k[1:1+8], []byte(tagValue[0:8*2])); err == nil {
|
||||||
k[0] = letterPrefix
|
k[0] = letterPrefix
|
||||||
offset = 1 + 8
|
offset = 1 + 8
|
||||||
dbi = il.indexTag32
|
dbi = il.indexTag32
|
||||||
@@ -273,7 +273,7 @@ func (il *IndexingLayer) getTagIndexPrefix(tagName string, tagValue string) (lmd
|
|||||||
spl := strings.Split(tagValue, ":")
|
spl := strings.Split(tagValue, ":")
|
||||||
if len(spl) == 3 && len(spl[1]) == 64 {
|
if len(spl) == 3 && len(spl[1]) == 64 {
|
||||||
k = make([]byte, 1+2+8+30+4)
|
k = make([]byte, 1+2+8+30+4)
|
||||||
if _, err := hex.Decode(k[1+2:1+2+8], []byte(spl[1][0:8*2])); err == nil {
|
if err := xhex.Decode(k[1+2:1+2+8], []byte(spl[1][0:8*2])); err == nil {
|
||||||
if kind, err := strconv.ParseUint(spl[0], 10, 16); err == nil {
|
if kind, err := strconv.ParseUint(spl[0], 10, 16); err == nil {
|
||||||
k[0] = letterPrefix
|
k[0] = letterPrefix
|
||||||
k[1] = byte(kind >> 8)
|
k[1] = byte(kind >> 8)
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package mmm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"fiatjaf.com/nostr/eventstore/internal"
|
"fiatjaf.com/nostr/eventstore/internal"
|
||||||
"github.com/PowerDNS/lmdb-go/lmdb"
|
"github.com/PowerDNS/lmdb-go/lmdb"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
type query struct {
|
type query struct {
|
||||||
@@ -77,7 +77,7 @@ func (il *IndexingLayer) prepareQueries(filter nostr.Filter) (
|
|||||||
|
|
||||||
for _, kind := range filter.Kinds {
|
for _, kind := range filter.Kinds {
|
||||||
k := make([]byte, 8+2)
|
k := make([]byte, 8+2)
|
||||||
if _, err := hex.Decode(k[0:8], []byte(value[0:8*2])); err != nil {
|
if err := xhex.Decode(k[0:8], []byte(value[0:8*2])); err != nil {
|
||||||
return nil, nil, nil, "", nil, 0, fmt.Errorf("invalid 'p' tag '%s'", value)
|
return nil, nil, nil, "", nil, 0, fmt.Errorf("invalid 'p' tag '%s'", value)
|
||||||
}
|
}
|
||||||
binary.BigEndian.PutUint16(k[8:8+2], uint16(kind))
|
binary.BigEndian.PutUint16(k[8:8+2], uint16(kind))
|
||||||
@@ -94,7 +94,7 @@ func (il *IndexingLayer) prepareQueries(filter nostr.Filter) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
k := make([]byte, 8)
|
k := make([]byte, 8)
|
||||||
if _, err := hex.Decode(k[0:8], []byte(value[0:8*2])); err != nil {
|
if err := xhex.Decode(k[0:8], []byte(value[0:8*2])); err != nil {
|
||||||
return nil, nil, nil, "", nil, 0, fmt.Errorf("invalid 'p' tag '%s'", value)
|
return nil, nil, nil, "", nil, 0, fmt.Errorf("invalid 'p' tag '%s'", value)
|
||||||
}
|
}
|
||||||
queries[i] = query{i: i, dbi: il.indexPTagKind, prefix: k[0:8], keySize: 8 + 2 + 4, timestampSize: 4}
|
queries[i] = query{i: i, dbi: il.indexPTagKind, prefix: k[0:8], keySize: 8 + 2 + 4, timestampSize: 4}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -42,7 +41,7 @@ func runBenchmarkOn(b *testing.B, db eventstore.Store) {
|
|||||||
Content: fmt.Sprintf("hello %d", i),
|
Content: fmt.Sprintf("hello %d", i),
|
||||||
Tags: nostr.Tags{
|
Tags: nostr.Tags{
|
||||||
{"t", fmt.Sprintf("t%d", i)},
|
{"t", fmt.Sprintf("t%d", i)},
|
||||||
{"e", hex.EncodeToString(eTag)},
|
{"e", nostr.HexEncodeToString(eTag)},
|
||||||
{"p", ref.Hex()},
|
{"p", ref.Hex()},
|
||||||
},
|
},
|
||||||
Kind: nostr.Kind(i % 10),
|
Kind: nostr.Kind(i % 10),
|
||||||
@@ -70,7 +69,7 @@ func runBenchmarkOn(b *testing.B, db eventstore.Store) {
|
|||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
eTag := make([]byte, 32)
|
eTag := make([]byte, 32)
|
||||||
binary.BigEndian.PutUint16(eTag, uint16(i))
|
binary.BigEndian.PutUint16(eTag, uint16(i))
|
||||||
eTags[i] = hex.EncodeToString(eTag)
|
eTags[i] = nostr.HexEncodeToString(eTag)
|
||||||
}
|
}
|
||||||
filters = append(filters, nostr.Filter{Kinds: []nostr.Kind{9}, Tags: nostr.TagMap{"e": eTags}})
|
filters = append(filters, nostr.Filter{Kinds: []nostr.Kind{9}, Tags: nostr.TagMap{"e": eTags}})
|
||||||
filters = append(filters, nostr.Filter{Kinds: []nostr.Kind{5}, Tags: nostr.TagMap{"e": eTags, "t": []string{"t5"}}})
|
filters = append(filters, nostr.Filter{Kinds: []nostr.Kind{5}, Tags: nostr.TagMap{"e": eTags, "t": []string{"t5"}}})
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -29,7 +28,7 @@ func runSecondTestOn(t *testing.T, db eventstore.Store) {
|
|||||||
Content: fmt.Sprintf("hello %d", i),
|
Content: fmt.Sprintf("hello %d", i),
|
||||||
Tags: nostr.Tags{
|
Tags: nostr.Tags{
|
||||||
{"t", fmt.Sprintf("t%d", i)},
|
{"t", fmt.Sprintf("t%d", i)},
|
||||||
{"e", hex.EncodeToString(eTag)},
|
{"e", nostr.HexEncodeToString(eTag)},
|
||||||
{"p", ref.Hex()},
|
{"p", ref.Hex()},
|
||||||
},
|
},
|
||||||
Kind: nostr.Kind(i % 10),
|
Kind: nostr.Kind(i % 10),
|
||||||
@@ -49,7 +48,7 @@ func runSecondTestOn(t *testing.T, db eventstore.Store) {
|
|||||||
for i := 0; i < 20; i++ {
|
for i := 0; i < 20; i++ {
|
||||||
eTag := make([]byte, 32)
|
eTag := make([]byte, 32)
|
||||||
binary.BigEndian.PutUint16(eTag, uint16(i))
|
binary.BigEndian.PutUint16(eTag, uint16(i))
|
||||||
eTags[i] = hex.EncodeToString(eTag)
|
eTags[i] = nostr.HexEncodeToString(eTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
filters := []nostr.Filter{
|
filters := []nostr.Filter{
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
|
|
||||||
jlexer "github.com/mailru/easyjson/jlexer"
|
jlexer "github.com/mailru/easyjson/jlexer"
|
||||||
jwriter "github.com/mailru/easyjson/jwriter"
|
jwriter "github.com/mailru/easyjson/jwriter"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func easyjsonDecodeFilter(in *jlexer.Lexer, out *Filter) {
|
func easyjsonDecodeFilter(in *jlexer.Lexer, out *Filter) {
|
||||||
@@ -42,7 +41,7 @@ func easyjsonDecodeFilter(in *jlexer.Lexer, out *Filter) {
|
|||||||
id := ID{}
|
id := ID{}
|
||||||
b := in.UnsafeBytes()
|
b := in.UnsafeBytes()
|
||||||
if len(b) == 64 {
|
if len(b) == 64 {
|
||||||
hex.Decode(id[:], b)
|
xhex.Decode(id[:], b)
|
||||||
}
|
}
|
||||||
out.IDs = append(out.IDs, id)
|
out.IDs = append(out.IDs, id)
|
||||||
in.WantComma()
|
in.WantComma()
|
||||||
@@ -79,7 +78,7 @@ func easyjsonDecodeFilter(in *jlexer.Lexer, out *Filter) {
|
|||||||
pk := PubKey{}
|
pk := PubKey{}
|
||||||
b := in.UnsafeBytes()
|
b := in.UnsafeBytes()
|
||||||
if len(b) == 64 {
|
if len(b) == 64 {
|
||||||
hex.Decode(pk[:], b)
|
xhex.Decode(pk[:], b)
|
||||||
}
|
}
|
||||||
out.Authors = append(out.Authors, pk)
|
out.Authors = append(out.Authors, pk)
|
||||||
in.WantComma()
|
in.WantComma()
|
||||||
@@ -140,7 +139,7 @@ func easyjsonEncodeFilter(out *jwriter.Writer, in Filter) {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
out.RawByte(',')
|
out.RawByte(',')
|
||||||
}
|
}
|
||||||
out.RawString("\"" + hex.EncodeToString(id[:]) + "\"")
|
out.RawString("\"" + HexEncodeToString(id[:]) + "\"")
|
||||||
}
|
}
|
||||||
out.RawByte(']')
|
out.RawByte(']')
|
||||||
}
|
}
|
||||||
@@ -178,7 +177,7 @@ func easyjsonEncodeFilter(out *jwriter.Writer, in Filter) {
|
|||||||
if i > 0 {
|
if i > 0 {
|
||||||
out.RawByte(',')
|
out.RawByte(',')
|
||||||
}
|
}
|
||||||
out.RawString("\"" + hex.EncodeToString(pk[:]) + "\"")
|
out.RawString("\"" + HexEncodeToString(pk[:]) + "\"")
|
||||||
}
|
}
|
||||||
out.RawByte(']')
|
out.RawByte(']')
|
||||||
}
|
}
|
||||||
|
|||||||
2
go.mod
2
go.mod
@@ -43,6 +43,8 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/dgraph-io/ristretto/v2 v2.3.0
|
github.com/dgraph-io/ristretto/v2 v2.3.0
|
||||||
github.com/go-git/go-git/v5 v5.16.3
|
github.com/go-git/go-git/v5 v5.16.3
|
||||||
|
github.com/templexxx/cpu v0.0.1
|
||||||
|
github.com/templexxx/xhex v0.0.0-20200614015412-aed53437177b
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -247,6 +247,10 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
|
||||||
|
github.com/templexxx/cpu v0.0.1 h1:hY4WdLOgKdc8y13EYklu9OUTXik80BkxHoWvTO6MQQY=
|
||||||
|
github.com/templexxx/cpu v0.0.1/go.mod h1:w7Tb+7qgcAlIyX4NhLuDKt78AHA5SzPmq0Wj6HiEnnk=
|
||||||
|
github.com/templexxx/xhex v0.0.0-20200614015412-aed53437177b h1:XeDLE6c9mzHpdv3Wb1+pWBaWv/BlHK0ZYIu/KaL6eHg=
|
||||||
|
github.com/templexxx/xhex v0.0.0-20200614015412-aed53437177b/go.mod h1:7rwmCH0wC2fQvNEvPZ3sKXukhyCTyiaZ5VTZMQYpZKQ=
|
||||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
"golang.org/x/exp/constraints"
|
"golang.org/x/exp/constraints"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ func extractEventID(jsonStr string) ID {
|
|||||||
|
|
||||||
// get 64 characters of the id
|
// get 64 characters of the id
|
||||||
var id [32]byte
|
var id [32]byte
|
||||||
hex.Decode(id[:], unsafe.Slice(unsafe.StringData(jsonStr[start:start+64]), 64))
|
xhex.Decode(id[:], unsafe.Slice(unsafe.StringData(jsonStr[start:start+64]), 64))
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ func extractEventPubKey(jsonStr string) PubKey {
|
|||||||
|
|
||||||
// get 64 characters of the pubkey
|
// get 64 characters of the pubkey
|
||||||
var pk [32]byte
|
var pk [32]byte
|
||||||
hex.Decode(pk[:], unsafe.Slice(unsafe.StringData(jsonStr[start:start+64]), 64))
|
xhex.Decode(pk[:], unsafe.Slice(unsafe.StringData(jsonStr[start:start+64]), 64))
|
||||||
return pk
|
return pk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
keys.go
26
keys.go
@@ -2,7 +2,6 @@ package nostr
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
|
||||||
stdjson "encoding/json"
|
stdjson "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -11,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
var KeyOne = SecretKey{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
var KeyOne = SecretKey{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
||||||
@@ -36,11 +36,11 @@ func Generate() SecretKey {
|
|||||||
type SecretKey [32]byte
|
type SecretKey [32]byte
|
||||||
|
|
||||||
func (sk SecretKey) String() string { return "sk::" + sk.Hex() }
|
func (sk SecretKey) String() string { return "sk::" + sk.Hex() }
|
||||||
func (sk SecretKey) Hex() string { return hex.EncodeToString(sk[:]) }
|
func (sk SecretKey) Hex() string { return HexEncodeToString(sk[:]) }
|
||||||
func (sk SecretKey) Public() PubKey { return GetPublicKey(sk) }
|
func (sk SecretKey) Public() PubKey { return GetPublicKey(sk) }
|
||||||
func (pk SecretKey) MarshalJSON() ([]byte, error) {
|
func (pk SecretKey) MarshalJSON() ([]byte, error) {
|
||||||
res := make([]byte, 66)
|
res := make([]byte, 66)
|
||||||
hex.Encode(res[1:], pk[:])
|
xhex.Encode(res[1:], pk[:])
|
||||||
res[0] = '"'
|
res[0] = '"'
|
||||||
res[65] = '"'
|
res[65] = '"'
|
||||||
return res, nil
|
return res, nil
|
||||||
@@ -50,7 +50,7 @@ func (pk *SecretKey) UnmarshalJSON(buf []byte) error {
|
|||||||
if len(buf) != 66 {
|
if len(buf) != 66 {
|
||||||
return fmt.Errorf("must be a hex string of 64 characters")
|
return fmt.Errorf("must be a hex string of 64 characters")
|
||||||
}
|
}
|
||||||
if _, err := hex.Decode(pk[:], buf[1:65]); err != nil {
|
if err := xhex.Decode(pk[:], buf[1:65]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -65,7 +65,7 @@ func SecretKeyFromHex(skh string) (SecretKey, error) {
|
|||||||
return sk, fmt.Errorf("secret key should be at most 64-char hex, got '%s'", skh)
|
return sk, fmt.Errorf("secret key should be at most 64-char hex, got '%s'", skh)
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, err := hex.Decode(sk[:], unsafe.Slice(unsafe.StringData(skh), 64)); err != nil {
|
if err := xhex.Decode(sk[:], unsafe.Slice(unsafe.StringData(skh), 64)); err != nil {
|
||||||
return sk, fmt.Errorf("'%s' is not valid hex: %w", skh, err)
|
return sk, fmt.Errorf("'%s' is not valid hex: %w", skh, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ func SecretKeyFromHex(skh string) (SecretKey, error) {
|
|||||||
|
|
||||||
func MustSecretKeyFromHex(idh string) SecretKey {
|
func MustSecretKeyFromHex(idh string) SecretKey {
|
||||||
id := SecretKey{}
|
id := SecretKey{}
|
||||||
if _, err := hex.Decode(id[:], unsafe.Slice(unsafe.StringData(idh), 64)); err != nil {
|
if err := xhex.Decode(id[:], unsafe.Slice(unsafe.StringData(idh), 64)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return id
|
return id
|
||||||
@@ -107,10 +107,10 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (pk PubKey) String() string { return "pk::" + pk.Hex() }
|
func (pk PubKey) String() string { return "pk::" + pk.Hex() }
|
||||||
func (pk PubKey) Hex() string { return hex.EncodeToString(pk[:]) }
|
func (pk PubKey) Hex() string { return HexEncodeToString(pk[:]) }
|
||||||
func (pk PubKey) MarshalJSON() ([]byte, error) {
|
func (pk PubKey) MarshalJSON() ([]byte, error) {
|
||||||
res := make([]byte, 66)
|
res := make([]byte, 66)
|
||||||
hex.Encode(res[1:], pk[:])
|
xhex.Encode(res[1:], pk[:])
|
||||||
res[0] = '"'
|
res[0] = '"'
|
||||||
res[65] = '"'
|
res[65] = '"'
|
||||||
return res, nil
|
return res, nil
|
||||||
@@ -120,7 +120,7 @@ func (pk *PubKey) UnmarshalJSON(buf []byte) error {
|
|||||||
if len(buf) != 66 {
|
if len(buf) != 66 {
|
||||||
return fmt.Errorf("must be a hex string of 64 characters")
|
return fmt.Errorf("must be a hex string of 64 characters")
|
||||||
}
|
}
|
||||||
if _, err := hex.Decode(pk[:], buf[1:65]); err != nil {
|
if err := xhex.Decode(pk[:], buf[1:65]); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if _, err := schnorr.ParsePubKey(pk[:]); err != nil {
|
if _, err := schnorr.ParsePubKey(pk[:]); err != nil {
|
||||||
@@ -134,7 +134,7 @@ func PubKeyFromHex(pkh string) (PubKey, error) {
|
|||||||
if len(pkh) != 64 {
|
if len(pkh) != 64 {
|
||||||
return pk, fmt.Errorf("pubkey should be 64-char hex, got '%s'", pkh)
|
return pk, fmt.Errorf("pubkey should be 64-char hex, got '%s'", pkh)
|
||||||
}
|
}
|
||||||
if _, err := hex.Decode(pk[:], unsafe.Slice(unsafe.StringData(pkh), 64)); err != nil {
|
if err := xhex.Decode(pk[:], unsafe.Slice(unsafe.StringData(pkh), 64)); err != nil {
|
||||||
return pk, fmt.Errorf("'%s' is not valid hex: %w", pkh, err)
|
return pk, fmt.Errorf("'%s' is not valid hex: %w", pkh, err)
|
||||||
}
|
}
|
||||||
if _, err := schnorr.ParsePubKey(pk[:]); err != nil {
|
if _, err := schnorr.ParsePubKey(pk[:]); err != nil {
|
||||||
@@ -148,7 +148,7 @@ func PubKeyFromHexCheap(pkh string) (PubKey, error) {
|
|||||||
if len(pkh) != 64 {
|
if len(pkh) != 64 {
|
||||||
return pk, fmt.Errorf("pubkey should be 64-char hex, got '%s'", pkh)
|
return pk, fmt.Errorf("pubkey should be 64-char hex, got '%s'", pkh)
|
||||||
}
|
}
|
||||||
if _, err := hex.Decode(pk[:], unsafe.Slice(unsafe.StringData(pkh), 64)); err != nil {
|
if err := xhex.Decode(pk[:], unsafe.Slice(unsafe.StringData(pkh), 64)); err != nil {
|
||||||
return pk, fmt.Errorf("'%s' is not valid hex: %w", pkh, err)
|
return pk, fmt.Errorf("'%s' is not valid hex: %w", pkh, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,7 +157,9 @@ func PubKeyFromHexCheap(pkh string) (PubKey, error) {
|
|||||||
|
|
||||||
func MustPubKeyFromHex(pkh string) PubKey {
|
func MustPubKeyFromHex(pkh string) PubKey {
|
||||||
pk := PubKey{}
|
pk := PubKey{}
|
||||||
hex.Decode(pk[:], unsafe.Slice(unsafe.StringData(pkh), 64))
|
if err := xhex.Decode(pk[:], unsafe.Slice(unsafe.StringData(pkh), 64)); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
return pk
|
return pk
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package blossom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
@@ -128,7 +127,7 @@ func (bs BlossomServer) handleUpload(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hash := sha256.Sum256(b)
|
hash := sha256.Sum256(b)
|
||||||
hhash := hex.EncodeToString(hash[:])
|
hhash := nostr.HexEncodeToString(hash[:])
|
||||||
mimeType := mime.TypeByExtension(ext)
|
mimeType := mime.TypeByExtension(ext)
|
||||||
if mimeType == "" {
|
if mimeType == "" {
|
||||||
mimeType = "application/octet-stream"
|
mimeType = "application/octet-stream"
|
||||||
@@ -443,7 +442,7 @@ func (bs BlossomServer) handleMirror(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
// calculate sha256
|
// calculate sha256
|
||||||
hash := sha256.Sum256(body)
|
hash := sha256.Sum256(body)
|
||||||
hhash := hex.EncodeToString(hash[:])
|
hhash := nostr.HexEncodeToString(hash[:])
|
||||||
|
|
||||||
// verify hash against x tag
|
// verify hash against x tag
|
||||||
if auth.Tags.FindWithValue("x", hhash) == nil {
|
if auth.Tags.FindWithValue("x", hhash) == nil {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package khatru
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -76,7 +75,7 @@ func (rl *Relay) HandleWebsocket(w http.ResponseWriter, r *http.Request) {
|
|||||||
ws := &WebSocket{
|
ws := &WebSocket{
|
||||||
conn: conn,
|
conn: conn,
|
||||||
Request: r,
|
Request: r,
|
||||||
Challenge: rl.ChallengePrefix + hex.EncodeToString(challenge),
|
Challenge: rl.ChallengePrefix + nostr.HexEncodeToString(challenge),
|
||||||
AuthedPublicKeys: make([]nostr.PubKey, 0),
|
AuthedPublicKeys: make([]nostr.PubKey, 0),
|
||||||
negentropySessions: xsync.NewMapOf[string, *NegentropySession](),
|
negentropySessions: xsync.NewMapOf[string, *NegentropySession](),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -99,7 +98,7 @@ func (rl *Relay) HandleNIP86(w http.ResponseWriter, r *http.Request) {
|
|||||||
goto respond
|
goto respond
|
||||||
}
|
}
|
||||||
|
|
||||||
if pht := evt.Tags.FindWithValue("payload", hex.EncodeToString(payloadHash[:])); pht == nil {
|
if pht := evt.Tags.FindWithValue("payload", nostr.HexEncodeToString(payloadHash[:])); pht == nil {
|
||||||
resp.Error = "invalid auth event payload hash"
|
resp.Error = "invalid auth event payload hash"
|
||||||
goto respond
|
goto respond
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
"crypto/cipher"
|
"crypto/cipher"
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -23,7 +22,7 @@ func ComputeSharedSecret(pub nostr.PubKey, sk [32]byte) (sharedSecret []byte, er
|
|||||||
// adding 02 to signal that this is a compressed public key (33 bytes)
|
// adding 02 to signal that this is a compressed public key (33 bytes)
|
||||||
pubKey, err := btcec.ParsePubKey(append([]byte{2}, pub[:]...))
|
pubKey, err := btcec.ParsePubKey(append([]byte{2}, pub[:]...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing receiver public key '%s': %w", "02"+hex.EncodeToString(pub[:]), err)
|
return nil, fmt.Errorf("error parsing receiver public key '%s': %w", "02"+nostr.HexEncodeToString(pub[:]), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return btcec.GenerateSharedSecret(privKey, pubKey), nil
|
return btcec.GenerateSharedSecret(privKey, pubKey), nil
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package nip04
|
package nip04
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -56,8 +55,8 @@ func TestEncryptionAndDecryptionWithMultipleLengths(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestNostrToolsCompatibility(t *testing.T) {
|
func TestNostrToolsCompatibility(t *testing.T) {
|
||||||
sk1, _ := hex.DecodeString("92996316beebf94171065a714cbf164d1f56d7ad9b35b329d9fc97535bf25352")
|
sk1, _ := nostr.HexDecodeString("92996316beebf94171065a714cbf164d1f56d7ad9b35b329d9fc97535bf25352")
|
||||||
sk2, _ := hex.DecodeString("591c0c249adfb9346f8d37dfeed65725e2eea1d7a6e99fa503342f367138de84")
|
sk2, _ := nostr.HexDecodeString("591c0c249adfb9346f8d37dfeed65725e2eea1d7a6e99fa503342f367138de84")
|
||||||
pk2 := nostr.GetPublicKey([32]byte(sk2))
|
pk2 := nostr.GetPublicKey([32]byte(sk2))
|
||||||
shared, _ := ComputeSharedSecret(pk2, [32]byte(sk1))
|
shared, _ := ComputeSharedSecret(pk2, [32]byte(sk1))
|
||||||
ciphertext := "A+fRnU4aXS4kbTLfowqAww==?iv=QFYUrl5or/n/qamY79ze0A=="
|
ciphertext := "A+fRnU4aXS4kbTLfowqAww==?iv=QFYUrl5or/n/qamY79ze0A=="
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
package nip06
|
package nip06
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"fiatjaf.com/nostr"
|
||||||
|
|
||||||
"github.com/tyler-smith/go-bip32"
|
"github.com/tyler-smith/go-bip32"
|
||||||
"github.com/tyler-smith/go-bip39"
|
"github.com/tyler-smith/go-bip39"
|
||||||
)
|
)
|
||||||
@@ -47,7 +46,7 @@ func PrivateKeyFromSeed(seed []byte) (string, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return hex.EncodeToString(next.Key), nil
|
return nostr.HexEncodeToString(next.Key), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateWords(words string) bool {
|
func ValidateWords(words string) bool {
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package nip19
|
package nip19
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEncodeNpub(t *testing.T) {
|
func TestEncodeNpub(t *testing.T) {
|
||||||
@@ -17,7 +17,7 @@ func TestEncodeNpub(t *testing.T) {
|
|||||||
func TestEncodeNsec(t *testing.T) {
|
func TestEncodeNsec(t *testing.T) {
|
||||||
skh := "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"
|
skh := "3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d"
|
||||||
var sk [32]byte
|
var sk [32]byte
|
||||||
hex.Decode(sk[:], []byte(skh))
|
xhex.Decode(sk[:], []byte(skh))
|
||||||
nsec := EncodeNsec(sk)
|
nsec := EncodeNsec(sk)
|
||||||
assert.Equal(t, "nsec180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsgyumg0", nsec, "produced an unexpected nsec string")
|
assert.Equal(t, "nsec180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsgyumg0", nsec, "produced an unexpected nsec string")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import (
|
|||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
@@ -162,7 +161,7 @@ func Decrypt(b64ciphertextWrapped string, conversationKey [32]byte) (string, err
|
|||||||
return string(unpadded), nil
|
return string(unpadded), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxThreshold, _ = hex.DecodeString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141")
|
var maxThreshold, _ = nostr.HexDecodeString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141")
|
||||||
|
|
||||||
func GenerateConversationKey(pub nostr.PubKey, sk nostr.SecretKey) ([32]byte, error) {
|
func GenerateConversationKey(pub nostr.PubKey, sk nostr.SecretKey) ([32]byte, error) {
|
||||||
var ck [32]byte
|
var ck [32]byte
|
||||||
@@ -236,7 +235,7 @@ func computeSharedSecret(pub nostr.PubKey, sk [32]byte) (sharedSecret [32]byte,
|
|||||||
pubKey, err := btcec.ParsePubKey(append([]byte{2}, pub[:]...))
|
pubKey, err := btcec.ParsePubKey(append([]byte{2}, pub[:]...))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sharedSecret, fmt.Errorf("error parsing receiver public key '%s': %w",
|
return sharedSecret, fmt.Errorf("error parsing receiver public key '%s': %w",
|
||||||
"02"+hex.EncodeToString(pub[:]), err)
|
"02"+nostr.HexEncodeToString(pub[:]), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var point, result secp256k1.JacobianPoint
|
var point, result secp256k1.JacobianPoint
|
||||||
|
|||||||
@@ -2,12 +2,12 @@ package nip44
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func assertCryptPriv(t *testing.T, skh1 string, skh2 string, conversationKey string, salt string, plaintext string, expected string) {
|
func assertCryptPriv(t *testing.T, skh1 string, skh2 string, conversationKey string, salt string, plaintext string, expected string) {
|
||||||
@@ -19,7 +19,7 @@ func assertCryptPriv(t *testing.T, skh1 string, skh2 string, conversationKey str
|
|||||||
|
|
||||||
assertConversationKeyGenerationPub(t, skh1, pub2.Hex(), conversationKey)
|
assertConversationKeyGenerationPub(t, skh1, pub2.Hex(), conversationKey)
|
||||||
|
|
||||||
customNonce, err := hex.DecodeString(salt)
|
customNonce, err := nostr.HexDecodeString(salt)
|
||||||
require.NoErrorf(t, err, "hex decode failed for salt: %v", err)
|
require.NoErrorf(t, err, "hex decode failed for salt: %v", err)
|
||||||
|
|
||||||
actual, err := Encrypt(plaintext, k1, WithCustomNonce(customNonce))
|
actual, err := Encrypt(plaintext, k1, WithCustomNonce(customNonce))
|
||||||
@@ -70,13 +70,13 @@ func assertMessageKeyGeneration(t *testing.T, conversationKey string, salt strin
|
|||||||
convNonce, err := hexDecode32Array(salt)
|
convNonce, err := hexDecode32Array(salt)
|
||||||
require.NoErrorf(t, err, "hex decode failed for nonce: %v", err)
|
require.NoErrorf(t, err, "hex decode failed for nonce: %v", err)
|
||||||
|
|
||||||
expectedChaChaKey, err := hex.DecodeString(chachaKey)
|
expectedChaChaKey, err := nostr.HexDecodeString(chachaKey)
|
||||||
require.NoErrorf(t, err, "hex decode failed for chacha key: %v", err)
|
require.NoErrorf(t, err, "hex decode failed for chacha key: %v", err)
|
||||||
|
|
||||||
expectedChaChaNonce, err := hex.DecodeString(chachaSalt)
|
expectedChaChaNonce, err := nostr.HexDecodeString(chachaSalt)
|
||||||
require.NoErrorf(t, err, "hex decode failed for chacha nonce: %v", err)
|
require.NoErrorf(t, err, "hex decode failed for chacha nonce: %v", err)
|
||||||
|
|
||||||
expectedHmacKey, err := hex.DecodeString(hmacKey)
|
expectedHmacKey, err := nostr.HexDecodeString(hmacKey)
|
||||||
require.NoErrorf(t, err, "hex decode failed for hmac key: %v", err)
|
require.NoErrorf(t, err, "hex decode failed for hmac key: %v", err)
|
||||||
|
|
||||||
actualChaChaKey, actualChaChaNonce, actualHmacKey, err := messageKeys(convKey, convNonce)
|
actualChaChaKey, actualChaChaNonce, actualHmacKey, err := messageKeys(convKey, convNonce)
|
||||||
@@ -92,7 +92,7 @@ func assertCryptLong(t *testing.T, conversationKey string, salt string, pattern
|
|||||||
convKey, err := hexDecode32Array(conversationKey)
|
convKey, err := hexDecode32Array(conversationKey)
|
||||||
require.NoErrorf(t, err, "hex decode failed for convKey: %v", err)
|
require.NoErrorf(t, err, "hex decode failed for convKey: %v", err)
|
||||||
|
|
||||||
customNonce, err := hex.DecodeString(salt)
|
customNonce, err := nostr.HexDecodeString(salt)
|
||||||
require.NoErrorf(t, err, "hex decode failed for salt: %v", err)
|
require.NoErrorf(t, err, "hex decode failed for salt: %v", err)
|
||||||
|
|
||||||
plaintext := ""
|
plaintext := ""
|
||||||
@@ -101,7 +101,7 @@ func assertCryptLong(t *testing.T, conversationKey string, salt string, pattern
|
|||||||
}
|
}
|
||||||
h := sha256.New()
|
h := sha256.New()
|
||||||
h.Write([]byte(plaintext))
|
h.Write([]byte(plaintext))
|
||||||
actualPlaintextSha256 := hex.EncodeToString(h.Sum(nil))
|
actualPlaintextSha256 := nostr.HexEncodeToString(h.Sum(nil))
|
||||||
require.Equalf(t, plaintextSha256, actualPlaintextSha256, "invalid plaintext sha256 hash: %v", err)
|
require.Equalf(t, plaintextSha256, actualPlaintextSha256, "invalid plaintext sha256 hash: %v", err)
|
||||||
|
|
||||||
actualPayload, err := Encrypt(plaintext, convKey, WithCustomNonce(customNonce))
|
actualPayload, err := Encrypt(plaintext, convKey, WithCustomNonce(customNonce))
|
||||||
@@ -109,7 +109,7 @@ func assertCryptLong(t *testing.T, conversationKey string, salt string, pattern
|
|||||||
|
|
||||||
h.Reset()
|
h.Reset()
|
||||||
h.Write([]byte(actualPayload))
|
h.Write([]byte(actualPayload))
|
||||||
actualPayloadSha256 := hex.EncodeToString(h.Sum(nil))
|
actualPayloadSha256 := nostr.HexEncodeToString(h.Sum(nil))
|
||||||
require.Equalf(t, payloadSha256, actualPayloadSha256, "invalid payload sha256 hash: %v", err)
|
require.Equalf(t, payloadSha256, actualPayloadSha256, "invalid payload sha256 hash: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1051,7 +1051,7 @@ func TestMessageKeyGeneration033(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func hexDecode32Array(hexString string) (res [32]byte, err error) {
|
func hexDecode32Array(hexString string) (res [32]byte, err error) {
|
||||||
_, err = hex.Decode(res[:], []byte(hexString))
|
err = xhex.Decode(res[:], []byte(hexString))
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package nip46
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"net/url"
|
"net/url"
|
||||||
@@ -56,7 +55,7 @@ func ConnectBunker(
|
|||||||
pool,
|
pool,
|
||||||
onAuth,
|
onAuth,
|
||||||
)
|
)
|
||||||
_, err = bunker.RPC(ctx, "connect", []string{hex.EncodeToString(parsed.HostPubKey[:]), parsed.Secret})
|
_, err = bunker.RPC(ctx, "connect", []string{nostr.HexEncodeToString(parsed.HostPubKey[:]), parsed.Secret})
|
||||||
return bunker, err
|
return bunker, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package nip46
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -131,7 +130,7 @@ func (p *DynamicSigner) HandleRequest(ctx context.Context, event nostr.Event) (
|
|||||||
|
|
||||||
result = "ack"
|
result = "ack"
|
||||||
case "get_public_key":
|
case "get_public_key":
|
||||||
result = hex.EncodeToString(session.PublicKey[:])
|
result = nostr.HexEncodeToString(session.PublicKey[:])
|
||||||
case "sign_event":
|
case "sign_event":
|
||||||
if len(req.Params) != 1 {
|
if len(req.Params) != 1 {
|
||||||
resultErr = fmt.Errorf("wrong number of arguments to 'sign_event'")
|
resultErr = fmt.Errorf("wrong number of arguments to 'sign_event'")
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package nip46
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
@@ -90,7 +89,7 @@ func (p *StaticKeySigner) HandleRequest(_ context.Context, event nostr.Event) (
|
|||||||
result = "ack"
|
result = "ack"
|
||||||
harmless = true
|
harmless = true
|
||||||
case "get_public_key":
|
case "get_public_key":
|
||||||
result = hex.EncodeToString(session.PublicKey[:])
|
result = nostr.HexEncodeToString(session.PublicKey[:])
|
||||||
harmless = true
|
harmless = true
|
||||||
case "sign_event":
|
case "sign_event":
|
||||||
if len(req.Params) != 1 {
|
if len(req.Params) != 1 {
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ package nip60
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"fiatjaf.com/nostr"
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
"github.com/btcsuite/btcd/btcec/v2/schnorr"
|
||||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||||
@@ -66,7 +66,7 @@ func createBlindedMessages(
|
|||||||
if _, err := rand.Read(secretBytes); err != nil {
|
if _, err := rand.Read(secretBytes); err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
secret = hex.EncodeToString(secretBytes)
|
secret = nostr.HexEncodeToString(secretBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
B_, r, err := crypto.BlindMessage(secret, r)
|
B_, r, err := crypto.BlindMessage(secret, r)
|
||||||
@@ -92,7 +92,7 @@ func signInput(
|
|||||||
return "", fmt.Errorf("failed to sign: %w", err)
|
return "", fmt.Errorf("failed to sign: %w", err)
|
||||||
}
|
}
|
||||||
witness, _ := json.Marshal(nut11.P2PKWitness{
|
witness, _ := json.Marshal(nut11.P2PKWitness{
|
||||||
Signatures: []string{hex.EncodeToString(signature.Serialize())},
|
Signatures: []string{nostr.HexEncodeToString(signature.Serialize())},
|
||||||
})
|
})
|
||||||
return string(witness), nil
|
return string(witness), nil
|
||||||
}
|
}
|
||||||
@@ -101,14 +101,14 @@ func signOutput(
|
|||||||
privateKey *btcec.PrivateKey,
|
privateKey *btcec.PrivateKey,
|
||||||
output cashu.BlindedMessage,
|
output cashu.BlindedMessage,
|
||||||
) (string, error) {
|
) (string, error) {
|
||||||
msg, _ := hex.DecodeString(output.B_)
|
msg, _ := nostr.HexDecodeString(output.B_)
|
||||||
hash := sha256.Sum256(msg)
|
hash := sha256.Sum256(msg)
|
||||||
signature, err := schnorr.Sign(privateKey, hash[:])
|
signature, err := schnorr.Sign(privateKey, hash[:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to sign: %w", err)
|
return "", fmt.Errorf("failed to sign: %w", err)
|
||||||
}
|
}
|
||||||
witness, _ := json.Marshal(nut11.P2PKWitness{
|
witness, _ := json.Marshal(nut11.P2PKWitness{
|
||||||
Signatures: []string{hex.EncodeToString(signature.Serialize())},
|
Signatures: []string{nostr.HexEncodeToString(signature.Serialize())},
|
||||||
})
|
})
|
||||||
return string(witness), nil
|
return string(witness), nil
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ func constructProofs(
|
|||||||
dleq = &cashu.DLEQProof{
|
dleq = &cashu.DLEQProof{
|
||||||
E: blindedSignature.DLEQ.E,
|
E: blindedSignature.DLEQ.E,
|
||||||
S: blindedSignature.DLEQ.S,
|
S: blindedSignature.DLEQ.S,
|
||||||
R: hex.EncodeToString(prep.rs[i].Serialize()),
|
R: nostr.HexEncodeToString(prep.rs[i].Serialize()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,7 +170,7 @@ func unblindSignature(C_str string, r *secp256k1.PrivateKey, key *secp256k1.Publ
|
|||||||
string,
|
string,
|
||||||
error,
|
error,
|
||||||
) {
|
) {
|
||||||
C_bytes, err := hex.DecodeString(C_str)
|
C_bytes, err := nostr.HexDecodeString(C_str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -180,14 +180,14 @@ func unblindSignature(C_str string, r *secp256k1.PrivateKey, key *secp256k1.Publ
|
|||||||
}
|
}
|
||||||
|
|
||||||
C := crypto.UnblindSignature(C_, r, key)
|
C := crypto.UnblindSignature(C_, r, key)
|
||||||
Cstr := hex.EncodeToString(C.SerializeCompressed())
|
Cstr := nostr.HexEncodeToString(C.SerializeCompressed())
|
||||||
return Cstr, nil
|
return Cstr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ParseKeysetKeys(keys nut01.KeysMap) (map[uint64]*btcec.PublicKey, error) {
|
func ParseKeysetKeys(keys nut01.KeysMap) (map[uint64]*btcec.PublicKey, error) {
|
||||||
parsedKeys := make(map[uint64]*btcec.PublicKey)
|
parsedKeys := make(map[uint64]*btcec.PublicKey)
|
||||||
for amount, pkh := range keys {
|
for amount, pkh := range keys {
|
||||||
pkb, err := hex.DecodeString(pkh)
|
pkb, err := nostr.HexDecodeString(pkh)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package nip60
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
|
|
||||||
@@ -42,7 +41,7 @@ func (opts SendOptions) asSpendingCondition(refund *btcec.PublicKey) *nut10.Spen
|
|||||||
|
|
||||||
return &nut10.SpendingCondition{
|
return &nut10.SpendingCondition{
|
||||||
Kind: nut10.HTLC,
|
Kind: nut10.HTLC,
|
||||||
Data: hex.EncodeToString(opts.Hashlock[:]),
|
Data: nostr.HexEncodeToString(opts.Hashlock[:]),
|
||||||
Tags: nut11.SerializeP2PKTags(tags),
|
Tags: nut11.SerializeP2PKTags(tags),
|
||||||
}
|
}
|
||||||
} else if opts.P2PK != nil {
|
} else if opts.P2PK != nil {
|
||||||
@@ -62,7 +61,7 @@ func (opts SendOptions) asSpendingCondition(refund *btcec.PublicKey) *nut10.Spen
|
|||||||
|
|
||||||
return &nut10.SpendingCondition{
|
return &nut10.SpendingCondition{
|
||||||
Kind: nut10.P2PK,
|
Kind: nut10.P2PK,
|
||||||
Data: hex.EncodeToString(opts.P2PK.SerializeCompressed()),
|
Data: nostr.HexEncodeToString(opts.P2PK.SerializeCompressed()),
|
||||||
Tags: nut11.SerializeP2PKTags(tags),
|
Tags: nut11.SerializeP2PKTags(tags),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package nip60
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -344,7 +343,7 @@ func (w *Wallet) SetPrivateKey(ctx context.Context, privateKey string) error {
|
|||||||
return fmt.Errorf("can't do write operations: missing PublishUpdate function")
|
return fmt.Errorf("can't do write operations: missing PublishUpdate function")
|
||||||
}
|
}
|
||||||
|
|
||||||
skb, err := hex.DecodeString(privateKey)
|
skb, err := nostr.HexDecodeString(privateKey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -378,7 +377,7 @@ func (w *Wallet) toEvent(ctx context.Context, kr nostr.Keyer, evt *nostr.Event)
|
|||||||
|
|
||||||
encryptedTags := make(nostr.Tags, 0, 1+len(w.Mints))
|
encryptedTags := make(nostr.Tags, 0, 1+len(w.Mints))
|
||||||
if w.PrivateKey != nil {
|
if w.PrivateKey != nil {
|
||||||
encryptedTags = append(encryptedTags, nostr.Tag{"privkey", hex.EncodeToString(w.PrivateKey.Serialize())})
|
encryptedTags = append(encryptedTags, nostr.Tag{"privkey", nostr.HexEncodeToString(w.PrivateKey.Serialize())})
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mint := range w.Mints {
|
for _, mint := range w.Mints {
|
||||||
@@ -433,7 +432,7 @@ func (w *Wallet) parse(ctx context.Context, kr nostr.Keyer, evt *nostr.Event) er
|
|||||||
case "mint":
|
case "mint":
|
||||||
mints = append(mints, tag[1])
|
mints = append(mints, tag[1])
|
||||||
case "privkey":
|
case "privkey":
|
||||||
skb, err := hex.DecodeString(tag[1])
|
skb, err := nostr.HexDecodeString(tag[1])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse private key: %w", err)
|
return fmt.Errorf("failed to parse private key: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package nip61
|
package nip61
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
@@ -52,7 +51,7 @@ func verifyProofDLEQ(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
CBytes, err := hex.DecodeString(proof.C)
|
CBytes, err := nostr.HexDecodeString(proof.C)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -88,7 +87,7 @@ func VerifyBlindSignatureDLEQ(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
B_bytes, err := hex.DecodeString(B_str)
|
B_bytes, err := nostr.HexDecodeString(B_str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -97,7 +96,7 @@ func VerifyBlindSignatureDLEQ(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
C_bytes, err := hex.DecodeString(C_str)
|
C_bytes, err := nostr.HexDecodeString(C_str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -115,13 +114,13 @@ func parseDLEQ(dleq cashu.DLEQProof) (
|
|||||||
*btcec.PrivateKey,
|
*btcec.PrivateKey,
|
||||||
error,
|
error,
|
||||||
) {
|
) {
|
||||||
ebytes, err := hex.DecodeString(dleq.E)
|
ebytes, err := nostr.HexDecodeString(dleq.E)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
e := secp256k1.PrivKeyFromBytes(ebytes)
|
e := secp256k1.PrivKeyFromBytes(ebytes)
|
||||||
|
|
||||||
sbytes, err := hex.DecodeString(dleq.S)
|
sbytes, err := nostr.HexDecodeString(dleq.S)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -131,7 +130,7 @@ func parseDLEQ(dleq cashu.DLEQProof) (
|
|||||||
return e, s, nil, nil
|
return e, s, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
rbytes, err := hex.DecodeString(dleq.R)
|
rbytes, err := nostr.HexDecodeString(dleq.R)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package negentropy
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"math"
|
"math"
|
||||||
@@ -72,12 +71,12 @@ func (n *Negentropy) Start() string {
|
|||||||
output.WriteByte(protocolVersion)
|
output.WriteByte(protocolVersion)
|
||||||
n.SplitRange(0, n.storage.Size(), InfiniteBound, output)
|
n.SplitRange(0, n.storage.Size(), InfiniteBound, output)
|
||||||
|
|
||||||
return hex.EncodeToString(output.Bytes())
|
return nostr.HexEncodeToString(output.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Negentropy) Reconcile(msg string) (string, error) {
|
func (n *Negentropy) Reconcile(msg string) (string, error) {
|
||||||
n.initialized = true
|
n.initialized = true
|
||||||
msgb, err := hex.DecodeString(msg)
|
msgb, err := nostr.HexDecodeString(msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@@ -99,7 +98,7 @@ func (n *Negentropy) Reconcile(msg string) (string, error) {
|
|||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return hex.EncodeToString(output), nil
|
return nostr.HexEncodeToString(output), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Negentropy) reconcileAux(reader *bytes.Reader) ([]byte, error) {
|
func (n *Negentropy) reconcileAux(reader *bytes.Reader) ([]byte, error) {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package blossom
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
@@ -16,7 +15,7 @@ func (c *Client) List(ctx context.Context) ([]BlobDescriptor, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bds := make([]BlobDescriptor, 0, 100)
|
bds := make([]BlobDescriptor, 0, 100)
|
||||||
err = c.httpCall(ctx, "GET", "list/"+hex.EncodeToString(pubkey[:]), "", func() string {
|
err = c.httpCall(ctx, "GET", "list/"+nostr.HexEncodeToString(pubkey[:]), "", func() string {
|
||||||
return c.authorizationHeader(ctx, func(evt *nostr.Event) {
|
return c.authorizationHeader(ctx, func(evt *nostr.Event) {
|
||||||
evt.Tags = append(evt.Tags, nostr.Tag{"t", "list"})
|
evt.Tags = append(evt.Tags, nostr.Tag{"t", "list"})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package blossom
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"mime"
|
"mime"
|
||||||
@@ -47,7 +46,7 @@ func (c *Client) UploadBlob(ctx context.Context, file io.ReadSeeker, contentType
|
|||||||
err = c.httpCall(ctx, "PUT", "upload", contentType, func() string {
|
err = c.httpCall(ctx, "PUT", "upload", contentType, func() string {
|
||||||
return c.authorizationHeader(ctx, func(evt *nostr.Event) {
|
return c.authorizationHeader(ctx, func(evt *nostr.Event) {
|
||||||
evt.Tags = append(evt.Tags, nostr.Tag{"t", "upload"})
|
evt.Tags = append(evt.Tags, nostr.Tag{"t", "upload"})
|
||||||
evt.Tags = append(evt.Tags, nostr.Tag{"x", hex.EncodeToString(hash[:])})
|
evt.Tags = append(evt.Tags, nostr.Tag{"x", nostr.HexEncodeToString(hash[:])})
|
||||||
})
|
})
|
||||||
}, file, size, &bd)
|
}, file, size, &bd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
15
pointers.go
15
pointers.go
@@ -1,7 +1,6 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -56,13 +55,13 @@ func ProfilePointerFromTag(refTag Tag) (ProfilePointer, error) {
|
|||||||
// MatchesEvent checks if the pointer matches an event.
|
// MatchesEvent checks if the pointer matches an event.
|
||||||
func (ep ProfilePointer) MatchesEvent(_ Event) bool { return false }
|
func (ep ProfilePointer) MatchesEvent(_ Event) bool { return false }
|
||||||
func (ep ProfilePointer) AsFilter() Filter { return Filter{Authors: []PubKey{ep.PublicKey}} }
|
func (ep ProfilePointer) AsFilter() Filter { return Filter{Authors: []PubKey{ep.PublicKey}} }
|
||||||
func (ep ProfilePointer) AsTagReference() string { return hex.EncodeToString(ep.PublicKey[:]) }
|
func (ep ProfilePointer) AsTagReference() string { return HexEncodeToString(ep.PublicKey[:]) }
|
||||||
|
|
||||||
func (ep ProfilePointer) AsTag() Tag {
|
func (ep ProfilePointer) AsTag() Tag {
|
||||||
if len(ep.Relays) > 0 {
|
if len(ep.Relays) > 0 {
|
||||||
return Tag{"p", hex.EncodeToString(ep.PublicKey[:]), ep.Relays[0]}
|
return Tag{"p", HexEncodeToString(ep.PublicKey[:]), ep.Relays[0]}
|
||||||
}
|
}
|
||||||
return Tag{"p", hex.EncodeToString(ep.PublicKey[:])}
|
return Tag{"p", HexEncodeToString(ep.PublicKey[:])}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EventPointer represents a pointer to a nostr event.
|
// EventPointer represents a pointer to a nostr event.
|
||||||
@@ -98,18 +97,18 @@ func EventPointerFromTag(refTag Tag) (EventPointer, error) {
|
|||||||
|
|
||||||
func (ep EventPointer) MatchesEvent(evt Event) bool { return evt.ID == ep.ID }
|
func (ep EventPointer) MatchesEvent(evt Event) bool { return evt.ID == ep.ID }
|
||||||
func (ep EventPointer) AsFilter() Filter { return Filter{IDs: []ID{ep.ID}} }
|
func (ep EventPointer) AsFilter() Filter { return Filter{IDs: []ID{ep.ID}} }
|
||||||
func (ep EventPointer) AsTagReference() string { return hex.EncodeToString(ep.ID[:]) }
|
func (ep EventPointer) AsTagReference() string { return HexEncodeToString(ep.ID[:]) }
|
||||||
|
|
||||||
// AsTag converts the pointer to a Tag.
|
// AsTag converts the pointer to a Tag.
|
||||||
func (ep EventPointer) AsTag() Tag {
|
func (ep EventPointer) AsTag() Tag {
|
||||||
if len(ep.Relays) > 0 {
|
if len(ep.Relays) > 0 {
|
||||||
if ep.Author != [32]byte{} {
|
if ep.Author != [32]byte{} {
|
||||||
return Tag{"e", hex.EncodeToString(ep.ID[:]), ep.Relays[0], hex.EncodeToString(ep.Author[:])}
|
return Tag{"e", HexEncodeToString(ep.ID[:]), ep.Relays[0], HexEncodeToString(ep.Author[:])}
|
||||||
} else {
|
} else {
|
||||||
return Tag{"e", hex.EncodeToString(ep.ID[:]), ep.Relays[0]}
|
return Tag{"e", HexEncodeToString(ep.ID[:]), ep.Relays[0]}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Tag{"e", hex.EncodeToString(ep.ID[:])}
|
return Tag{"e", HexEncodeToString(ep.ID[:])}
|
||||||
}
|
}
|
||||||
|
|
||||||
// EntityPointer represents a pointer to a nostr entity (addressable event).
|
// EntityPointer represents a pointer to a nostr entity (addressable event).
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
|
|
||||||
jlexer "github.com/mailru/easyjson/jlexer"
|
jlexer "github.com/mailru/easyjson/jlexer"
|
||||||
jwriter "github.com/mailru/easyjson/jwriter"
|
jwriter "github.com/mailru/easyjson/jwriter"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
func easyjson33014d6eDecodeFiatjafComNostr(in *jlexer.Lexer, out *ProfilePointer) {
|
func easyjson33014d6eDecodeFiatjafComNostr(in *jlexer.Lexer, out *ProfilePointer) {
|
||||||
@@ -30,7 +29,7 @@ func easyjson33014d6eDecodeFiatjafComNostr(in *jlexer.Lexer, out *ProfilePointer
|
|||||||
if in.IsNull() {
|
if in.IsNull() {
|
||||||
in.Skip()
|
in.Skip()
|
||||||
} else {
|
} else {
|
||||||
hex.Decode(out.PublicKey[:], in.UnsafeBytes())
|
xhex.Decode(out.PublicKey[:], in.UnsafeBytes())
|
||||||
}
|
}
|
||||||
case "relays":
|
case "relays":
|
||||||
if in.IsNull() {
|
if in.IsNull() {
|
||||||
@@ -137,7 +136,7 @@ func easyjson33014d6eDecodeFiatjafComNostr1(in *jlexer.Lexer, out *EventPointer)
|
|||||||
if in.IsNull() {
|
if in.IsNull() {
|
||||||
in.Skip()
|
in.Skip()
|
||||||
} else {
|
} else {
|
||||||
hex.Decode(out.ID[:], in.UnsafeBytes())
|
xhex.Decode(out.ID[:], in.UnsafeBytes())
|
||||||
}
|
}
|
||||||
case "relays":
|
case "relays":
|
||||||
if in.IsNull() {
|
if in.IsNull() {
|
||||||
@@ -164,7 +163,7 @@ func easyjson33014d6eDecodeFiatjafComNostr1(in *jlexer.Lexer, out *EventPointer)
|
|||||||
if in.IsNull() {
|
if in.IsNull() {
|
||||||
in.Skip()
|
in.Skip()
|
||||||
} else {
|
} else {
|
||||||
hex.Decode(out.Author[:], in.UnsafeBytes())
|
xhex.Decode(out.Author[:], in.UnsafeBytes())
|
||||||
}
|
}
|
||||||
case "kind":
|
case "kind":
|
||||||
out.Kind = Kind(in.Uint16())
|
out.Kind = Kind(in.Uint16())
|
||||||
@@ -262,7 +261,7 @@ func easyjson33014d6eDecodeFiatjafComNostr2(in *jlexer.Lexer, out *EntityPointer
|
|||||||
if in.IsNull() {
|
if in.IsNull() {
|
||||||
in.Skip()
|
in.Skip()
|
||||||
} else {
|
} else {
|
||||||
hex.Decode(out.PublicKey[:], in.UnsafeBytes())
|
xhex.Decode(out.PublicKey[:], in.UnsafeBytes())
|
||||||
}
|
}
|
||||||
case "kind":
|
case "kind":
|
||||||
out.Kind = Kind(in.Uint16())
|
out.Kind = Kind(in.Uint16())
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package schema
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"slices"
|
"slices"
|
||||||
@@ -12,6 +11,7 @@ import (
|
|||||||
|
|
||||||
"fiatjaf.com/nostr"
|
"fiatjaf.com/nostr"
|
||||||
"github.com/segmentio/encoding/json"
|
"github.com/segmentio/encoding/json"
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -186,7 +186,7 @@ func (v *Validator) validateNext(tag nostr.Tag, index int, this *nextSpec) (fail
|
|||||||
if len(tag[index]) != 40 {
|
if len(tag[index]) != 40 {
|
||||||
return index, fmt.Errorf("invalid gitcommit at tag '%s', index %d", tag[0], index)
|
return index, fmt.Errorf("invalid gitcommit at tag '%s', index %d", tag[0], index)
|
||||||
}
|
}
|
||||||
if _, err := hex.Decode(gitcommitdummydecoder, unsafe.Slice(unsafe.StringData(tag[index]), 40)); err != nil {
|
if err := xhex.Decode(gitcommitdummydecoder, unsafe.Slice(unsafe.StringData(tag[index]), 40)); err != nil {
|
||||||
return index, fmt.Errorf("invalid gitcommit at tag '%s', index %d", tag[0], index)
|
return index, fmt.Errorf("invalid gitcommit at tag '%s', index %d", tag[0], index)
|
||||||
}
|
}
|
||||||
case "free":
|
case "free":
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package sdk
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -57,7 +56,7 @@ func (sys *System) PrepareNoteEvent(ctx context.Context, evt *nostr.Event) (targ
|
|||||||
case nostr.ProfilePointer:
|
case nostr.ProfilePointer:
|
||||||
pk = b.PublicKey
|
pk = b.PublicKey
|
||||||
// add p tag if not already present
|
// add p tag if not already present
|
||||||
if tag := evt.Tags.FindWithValue("p", hex.EncodeToString(b.PublicKey[:])); tag == nil {
|
if tag := evt.Tags.FindWithValue("p", nostr.HexEncodeToString(b.PublicKey[:])); tag == nil {
|
||||||
evt.Tags = append(evt.Tags, b.AsTag())
|
evt.Tags = append(evt.Tags, b.AsTag())
|
||||||
}
|
}
|
||||||
case nostr.EventPointer:
|
case nostr.EventPointer:
|
||||||
@@ -77,7 +76,7 @@ func (sys *System) PrepareNoteEvent(ctx context.Context, evt *nostr.Event) (targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add e tag if not already present
|
// add e tag if not already present
|
||||||
if tag := evt.Tags.FindWithValue("q", hex.EncodeToString(b.ID[:])); tag != nil {
|
if tag := evt.Tags.FindWithValue("q", nostr.HexEncodeToString(b.ID[:])); tag != nil {
|
||||||
if len(tag) == 2 {
|
if len(tag) == 2 {
|
||||||
tag = append(tag, relay) // shove this relay hint here
|
tag = append(tag, relay) // shove this relay hint here
|
||||||
}
|
}
|
||||||
|
|||||||
15
types.go
15
types.go
@@ -1,10 +1,11 @@
|
|||||||
package nostr
|
package nostr
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
stdjson "encoding/json"
|
stdjson "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// RelayEvent represents an event received from a specific relay.
|
// RelayEvent represents an event received from a specific relay.
|
||||||
@@ -24,11 +25,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (id ID) String() string { return "id::" + id.Hex() }
|
func (id ID) String() string { return "id::" + id.Hex() }
|
||||||
func (id ID) Hex() string { return hex.EncodeToString(id[:]) }
|
func (id ID) Hex() string { return HexEncodeToString(id[:]) }
|
||||||
|
|
||||||
func (id ID) MarshalJSON() ([]byte, error) {
|
func (id ID) MarshalJSON() ([]byte, error) {
|
||||||
res := make([]byte, 66)
|
res := make([]byte, 66)
|
||||||
hex.Encode(res[1:], id[:])
|
xhex.Encode(res[1:], id[:])
|
||||||
res[0] = '"'
|
res[0] = '"'
|
||||||
res[65] = '"'
|
res[65] = '"'
|
||||||
return res, nil
|
return res, nil
|
||||||
@@ -36,9 +37,9 @@ func (id ID) MarshalJSON() ([]byte, error) {
|
|||||||
|
|
||||||
func (id *ID) UnmarshalJSON(buf []byte) error {
|
func (id *ID) UnmarshalJSON(buf []byte) error {
|
||||||
if len(buf) != 66 {
|
if len(buf) != 66 {
|
||||||
return fmt.Errorf("must be a hex string of 64 characters")
|
return fmt.Errorf("must be a quoted hex string of 64 characters")
|
||||||
}
|
}
|
||||||
_, err := hex.Decode(id[:], buf[1:65])
|
err := xhex.Decode(id[:], buf[1:65])
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ func IDFromHex(idh string) (ID, error) {
|
|||||||
if len(idh) != 64 {
|
if len(idh) != 64 {
|
||||||
return id, fmt.Errorf("pubkey should be 64-char hex, got '%s'", idh)
|
return id, fmt.Errorf("pubkey should be 64-char hex, got '%s'", idh)
|
||||||
}
|
}
|
||||||
if _, err := hex.Decode(id[:], unsafe.Slice(unsafe.StringData(idh), 64)); err != nil {
|
if err := xhex.Decode(id[:], unsafe.Slice(unsafe.StringData(idh), 64)); err != nil {
|
||||||
return id, fmt.Errorf("'%s' is not valid hex: %w", idh, err)
|
return id, fmt.Errorf("'%s' is not valid hex: %w", idh, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ func IDFromHex(idh string) (ID, error) {
|
|||||||
|
|
||||||
func MustIDFromHex(idh string) ID {
|
func MustIDFromHex(idh string) ID {
|
||||||
id := ID{}
|
id := ID{}
|
||||||
if _, err := hex.Decode(id[:], unsafe.Slice(unsafe.StringData(idh), 64)); err != nil {
|
if err := xhex.Decode(id[:], unsafe.Slice(unsafe.StringData(idh), 64)); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
return id
|
return id
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
"github.com/templexxx/cpu"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestIDJSONEncoding(t *testing.T) {
|
func TestIDJSONEncoding(t *testing.T) {
|
||||||
@@ -25,8 +26,10 @@ func TestIDJSONEncoding(t *testing.T) {
|
|||||||
require.Error(t, err)
|
require.Error(t, err)
|
||||||
|
|
||||||
// test unmarshaling invalid hex
|
// test unmarshaling invalid hex
|
||||||
err = json.Unmarshal([]byte(`"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"`), &id2)
|
if !cpu.X86.HasAVX2 {
|
||||||
require.Error(t, err)
|
err = json.Unmarshal([]byte(`"zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"`), &id2)
|
||||||
|
require.Error(t, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPubKeyJSONEncoding(t *testing.T) {
|
func TestPubKeyJSONEncoding(t *testing.T) {
|
||||||
|
|||||||
27
utils.go
27
utils.go
@@ -3,9 +3,11 @@ package nostr
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"cmp"
|
"cmp"
|
||||||
"encoding/hex"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"slices"
|
"slices"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/templexxx/xhex"
|
||||||
)
|
)
|
||||||
|
|
||||||
// IsValidRelayURL checks if a URL is a valid relay URL (ws:// or wss://).
|
// IsValidRelayURL checks if a URL is a valid relay URL (ws:// or wss://).
|
||||||
@@ -20,6 +22,27 @@ func IsValidRelayURL(u string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HexEncodeToString encodes src into a hex string.
|
||||||
|
func HexEncodeToString(src []byte) string {
|
||||||
|
dst := make([]byte, len(src)*2)
|
||||||
|
xhex.Encode(dst, src)
|
||||||
|
return unsafe.String(unsafe.SliceData(dst), len(dst))
|
||||||
|
}
|
||||||
|
|
||||||
|
// HexDecodeString decodes a hex string into bytes.
|
||||||
|
func HexDecodeString(s string) ([]byte, error) {
|
||||||
|
src := unsafe.Slice(unsafe.StringData(s), len(s))
|
||||||
|
if len(src)%2 != 0 {
|
||||||
|
return nil, xhex.ErrLength
|
||||||
|
}
|
||||||
|
dst := make([]byte, len(src)/2)
|
||||||
|
err := xhex.Decode(dst, src)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dst, nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsValid32ByteHex checks if a string is a valid 32-byte hex string.
|
// IsValid32ByteHex checks if a string is a valid 32-byte hex string.
|
||||||
func IsValid32ByteHex(thing string) bool {
|
func IsValid32ByteHex(thing string) bool {
|
||||||
if !isLowerHex(thing) {
|
if !isLowerHex(thing) {
|
||||||
@@ -28,7 +51,7 @@ func IsValid32ByteHex(thing string) bool {
|
|||||||
if len(thing) != 64 {
|
if len(thing) != 64 {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_, err := hex.DecodeString(thing)
|
_, err := HexDecodeString(thing)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user