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