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
import (
"fmt"
"time"
"git.michelsen.id/chron/core"
"github.com/google/uuid"
"lukechampine.com/blake3"
)
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 (
"context"
"io"
)
type EntryStore interface {
Append(ctx context.Context, entry Entry) (EntryID, error)
Redact(ctx context.Context, entryID EntryID) error
Append(ctx context.Context, entry Entry) error
Get(ctx context.Context, entryID EntryID) (Entry, error)
ScanForwards(ctx context.Context, entryID EntryID) ([]EntryID, error)
ScanBackwards(ctx context.Context, entryID EntryID) ([]EntryID, error)
GetBySeq(ctx context.Context, ledgerID LedgerID, seq uint64) (Entry, error)
Delete(ctx context.Context, entryID 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 {
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
}

View File

@@ -1,12 +1,107 @@
package core
import (
"context"
"time"
"github.com/google/uuid"
"lukechampine.com/blake3"
)
type Ledger struct {
LedgerID LedgerID
entryStore EntryStore
payloadStore PayloadStore
LedgerID LedgerID
hashChaining bool
}
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")
}

View File

@@ -1,15 +1,17 @@
package core
import (
"encoding/binary"
"time"
"lukechampine.com/blake3"
)
type LedgerID [16]byte
type EntryID [16]byte
type PayloadID [16]byte
type Hash [32]byte
type Hash32 [32]byte
type Entry struct {
EntryID EntryID
@@ -19,9 +21,31 @@ type Entry struct {
Timestamp time.Time
Nonce [16]byte
Commitment Hash
PayloadID PayloadID
PayloadDigest Hash32
PreviousHash Hash
EntryHash Hash
PreviousHash Hash32
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
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/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=