events marshal/unmarshal

This commit is contained in:
2025-05-21 23:11:58 -01:06
parent c8696d7417
commit 9abd35c5eb
3 changed files with 104 additions and 2 deletions

View File

@@ -8,7 +8,7 @@ fragmentation of user identity is a huge problem in web3 app development, every
the same problem exists also with centralized social networks, you can't just go to another venue and join the conversation, you have to have a whole new identity and as well as the problems that this enables malicious use, it also makes any efforts to build borderless social network communications applications basically impossible.
## nostr
## nostr...
[nostr](https://github.com/nostr-protocol/nostr) is a project that has paved the way for a mechanism by which users identities work seamlessly across multiple servers, mostly interoperable, but it is plagued with its association with Bitcoin and Jack Dorsey and a faux decentralised committee of grant giving organisations and people defining protocol specifications that are not well-thought-out and constantly changing, and worst, for no reason at all, it uses websockets, which makes implementation too complex and specialised for wide developer adoption.
@@ -16,4 +16,8 @@ the same problem exists also with centralized social networks, you can't just go
Instead of using websockets, `transit` uses standard HTTP REST API for messaging, authentication for access control is integrated into headers and instead of using uncommon cryptosystems, it uses standard, commonly used Blake3 hashes, ed25519 signatures and ChaCha20-Poly1305 encryption for protected data.
By using these well-supported, well understood protocol elements, we eliminate the friction for most web developers to build apps that interact with `transit` relays and enable the building of a multitude of different kinds of collaborative messaging and data storage applications with a single unified toolkit.
By using these well-supported, well understood protocol elements, we eliminate the friction for most web developers to build apps that interact with `transit` relays and enable the building of a multitude of different kinds of collaborative messaging and data storage applications with a single unified toolkit.
## Data Structure Design
The primary data structure

26
event/event.go Normal file
View File

@@ -0,0 +1,26 @@
package event
import (
"github.com/mleku/transit/content"
"github.com/mleku/transit/id"
"github.com/mleku/transit/kind"
"github.com/mleku/transit/mime"
"github.com/mleku/transit/pubkey"
"github.com/mleku/transit/signature"
"github.com/mleku/transit/tag"
)
// E is the event itself, that is hashed to generate
type E struct {
Pubkey *pubkey.P `json:"pubkey" doc:"public key of author of event in unpadded base64 URL encoding"`
Content *content.C `json:"content" doc:"content of event; if binary, has a prefix 'base64:' and is encoded in padded base64 URL encoding"`
Kind *kind.K `json:"kind" doc:"application/intent of event"`
Mimetype *mime.Type `json:"mimetype" doc:"standard IANA mimetype of encoding of content"`
Tags *tag.S `json:"tags" doc:"tags with keys and values, binary types like root, parent, event and user are encoded in unpadded base64 URL encoding"`
}
type Signed struct {
Id *id.I `json:"id" doc:"Blake3 hash of embedded event in base64 URL encoding"`
*E `json:"event" doc:"embedded event"`
Signature *signature.S `json:"sig" doc:"ed25519 signature on event"`
}

72
event/event_test.go Normal file
View File

@@ -0,0 +1,72 @@
package event
import (
"bytes"
"crypto/ed25519"
"encoding/json"
"testing"
"lukechampine.com/frand"
"github.com/mleku/transit/chk"
"github.com/mleku/transit/content"
"github.com/mleku/transit/id"
"github.com/mleku/transit/kind"
"github.com/mleku/transit/log"
"github.com/mleku/transit/mime"
"github.com/mleku/transit/pubkey"
"github.com/mleku/transit/tag"
)
func TestE(t *testing.T) {
e := &E{
Pubkey: generatePubkey(),
Content: content.New(`this is some content
with multiple lines
to show how it encodes
#winning`, false),
Kind: kind.New("forum/reply"),
Mimetype: mime.New("text/asciidoc"),
Tags: tag.NewTags(
tag.New("root", generateId()),
tag.New("parent", generateId()),
tag.New("event", generateId()),
tag.New("user", generatePubkey()),
tag.New("hashtag", "winning"),
tag.New("url", "http://example.com"),
),
}
var b []byte
var err error
if b, err = json.Marshal(e); chk.E(err) {
t.Fatal(err)
}
b1 := make([]byte, len(b))
copy(b1, b)
log.I.F("%s", b)
e2 := &E{}
if err = json.Unmarshal(b, e2); chk.E(err) {
t.Fatal(err)
}
log.I.S(e, e2)
var b2 []byte
if b2, err = json.Marshal(e2); chk.E(err) {
t.Fatal(err)
}
log.I.F("\n%s\n%s\n", b1, b2)
if !bytes.Equal(b1, b2) {
t.Fatal("failed to encode/decode")
}
}
func generatePubkey() (p *pubkey.P) {
var pub ed25519.PublicKey
pub, _, _ = ed25519.GenerateKey(frand.Reader)
pp := pubkey.New(pub)
return pp
}
func generateId() (i *id.I) { return id.New(frand.Bytes(32)) }