WIP Implementing core/ledger

This commit is contained in:
2026-02-09 09:52:20 +00:00
parent 55101752f5
commit 57e7c94f36
6 changed files with 190 additions and 17 deletions

View File

@@ -1,4 +1,46 @@
package main package main
import (
"fmt"
"time"
"git.michelsen.id/chron/core"
"github.com/google/uuid"
"lukechampine.com/blake3"
)
func main() { func main() {
payload := []byte{0, 1, 0, 1}
payloadDigest := blake3.Sum256(payload)
entryID, err := uuid.NewV7()
entryIDBytes, err := entryID.MarshalBinary()
if err != nil {
return
}
ledgerID, err := uuid.NewV7()
ledgerIDBytes, err := ledgerID.MarshalBinary()
if err != nil {
return
}
payloadID, err := uuid.NewV7()
payloadIDBytes, err := payloadID.MarshalBinary()
if err != nil {
return
}
entry := core.Entry{
EntryID: core.EntryID(entryIDBytes),
LedgerID: core.LedgerID(ledgerIDBytes),
Seq: 1,
Timestamp: time.Now(),
PayloadID: core.PayloadID(payloadIDBytes),
PayloadDigest: payloadDigest,
}
entryHash := core.HashEntry(entry)
entry.EntryHash = entryHash
fmt.Printf("Entry: %+v\n", entry)
fmt.Printf("EntryHash: %x\n", entryHash)
} }

View File

@@ -2,24 +2,27 @@ package core
import ( import (
"context" "context"
"io"
) )
type EntryStore interface { type EntryStore interface {
Append(ctx context.Context, entry Entry) (EntryID, error) Append(ctx context.Context, entry Entry) error
Redact(ctx context.Context, entryID EntryID) error
Get(ctx context.Context, entryID EntryID) (Entry, error) Get(ctx context.Context, entryID EntryID) (Entry, error)
GetBySeq(ctx context.Context, ledgerID LedgerID, seq uint64) (Entry, error)
ScanForwards(ctx context.Context, entryID EntryID) ([]EntryID, error) Delete(ctx context.Context, entryID EntryID) error
ScanBackwards(ctx context.Context, entryID EntryID) ([]EntryID, error)
Head(ctx context.Context, ledgerID LedgerID) (EntryID, error) Head(ctx context.Context, ledgerID LedgerID) (EntryID, error)
IsEmpty(ctx context.Context, ledgerID LedgerID) bool HeadSeq(context.Context, LedgerID) (uint64, error)
Tail(ctx context.Context, ledgerID LedgerID) (EntryID, error)
Iterator(ctx context.Context, ledgerLedgerID, startSeq uint64) (EntryIterator, error)
}
type EntryIterator interface {
Next() bool
Entry() Entry
} }
type PayloadStore interface { type PayloadStore interface {
Put(ctx context.Context, reader io.Reader) (PayloadID, error) Put(ctx context.Context, payload []byte) (PayloadID, error)
Get(ctx context.Context, payloadID PayloadID) ([]byte, error)
Delete(ctx context.Context, payloadID PayloadID) error Delete(ctx context.Context, payloadID PayloadID) error
} }

View File

@@ -1,12 +1,107 @@
package core package core
import (
"context"
"time"
"github.com/google/uuid"
"lukechampine.com/blake3"
)
type Ledger struct { type Ledger struct {
LedgerID LedgerID
entryStore EntryStore entryStore EntryStore
payloadStore PayloadStore payloadStore PayloadStore
LedgerID LedgerID hashChaining bool
} }
func NewLedger(entryStore EntryStore, payloadStore PayloadStore) (*Ledger, error) { func NewLedger(entryStore EntryStore, payloadStore PayloadStore) (*Ledger, error) {
id, err := uuid.NewV7()
if err != nil {
return nil, err
}
idByes, err := id.MarshalBinary()
if err != nil {
return nil, err
}
return &Ledger{
LedgerID: LedgerID(idByes),
entryStore: entryStore,
payloadStore: payloadStore,
}, nil
}
func (l *Ledger) ID() LedgerID {
return l.LedgerID
}
func (l *Ledger) Head() (Entry, error) {
panic("unimplemented")
}
func (l *Ledger) Append(ctx context.Context, payload []byte) (EntryID, error) {
payloadDigest := blake3.Sum256(payload)
payloadID, err := l.payloadStore.Put(ctx, payload)
if err != nil {
return EntryID{}, err
}
entryID, err := uuid.NewV7()
entryIDBytes, err := entryID.MarshalBinary()
if err != nil {
return EntryID{}, err
}
head, err := l.Head()
if err != nil {
return EntryID{}, err
}
entry := Entry{
EntryID: EntryID(entryIDBytes),
LedgerID: l.LedgerID,
Seq: head.Seq + 1,
Timestamp: time.Now(),
PayloadID: payloadID,
PayloadDigest: payloadDigest,
}
entryHash := HashEntry(entry)
entry.EntryHash = entryHash
err = l.entryStore.Append(ctx, entry)
if err != nil {
return EntryID{}, err
}
return EntryID(entryIDBytes), nil
}
func (l *Ledger) Get(ctx context.Context, seq uint64) (Entry, []byte, error) {
entry, err := l.entryStore.GetBySeq(ctx, l.LedgerID, seq)
if err != nil {
return Entry{}, nil, err
}
payload, err := l.payloadStore.Get(ctx, entry.PayloadID)
if err != nil {
return Entry{}, nil, err
}
return entry, payload, nil
}
func (l *Ledger) GetEntry(ctx context.Context, seq uint64) (Entry, error) {
panic("unimplemented")
}
func (l *Ledger) GetPayload(ctx context.Context, seq uint64) ([]byte, error) {
panic("unimplemented")
}
func (l *Ledger) Iter(ctx context.Context, startSeq uint64) (EntryIterator, error) {
panic("unimplemented") panic("unimplemented")
} }

View File

@@ -1,15 +1,17 @@
package core package core
import ( import (
"encoding/binary"
"time" "time"
"lukechampine.com/blake3"
) )
type LedgerID [16]byte type LedgerID [16]byte
type EntryID [16]byte type EntryID [16]byte
type PayloadID [16]byte type PayloadID [16]byte
type Hash [32]byte type Hash32 [32]byte
type Entry struct { type Entry struct {
EntryID EntryID EntryID EntryID
@@ -19,9 +21,31 @@ type Entry struct {
Timestamp time.Time Timestamp time.Time
Nonce [16]byte PayloadID PayloadID
Commitment Hash PayloadDigest Hash32
PreviousHash Hash PreviousHash Hash32
EntryHash Hash EntryHash Hash32
}
func HashEntry(e Entry) Hash32 {
b := make([]byte, 0, 128)
b = append(b, "chron.entry.v1"...)
b = append(b, e.LedgerID[:]...)
var buf [8]byte
binary.LittleEndian.PutUint64(buf[:], e.Seq)
b = append(b, buf[:]...)
binary.LittleEndian.PutUint64(buf[:], uint64(e.Timestamp.UTC().UnixNano()))
b = append(b, buf[:]...)
b = append(b, e.EntryID[:]...)
b = append(b, e.PayloadID[:]...)
b = append(b, e.PayloadDigest[:]...)
b = append(b, e.PreviousHash[:]...)
sum := blake3.Sum256(b)
return Hash32(sum)
} }

5
go.mod
View File

@@ -3,3 +3,8 @@ module git.michelsen.id/chron
go 1.25.5 go 1.25.5
require github.com/google/uuid v1.6.0 require github.com/google/uuid v1.6.0
require (
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
lukechampine.com/blake3 v1.4.1 // indirect
)

4
go.sum
View File

@@ -1,2 +1,6 @@
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
lukechampine.com/blake3 v1.4.1 h1:I3Smz7gso8w4/TunLKec6K2fn+kyKtDxr/xcQEN84Wg=
lukechampine.com/blake3 v1.4.1/go.mod h1:QFosUxmjB8mnrWFSNwKmvxHpfY72bmD2tQ0kBMM3kwo=