Restructure refimpl into go-lang and python subdirectories
Move Go reference implementation to refimpl/go-lang/ and add new Python reference implementation in refimpl/python/. Update build.sh with renamed draft and simplified tool paths. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
107
refimpl/go-lang/ect/ledger.go
Normal file
107
refimpl/go-lang/ect/ledger.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package ect
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
// LedgerEntry represents a single ECT record in the audit ledger (Section 9.3).
|
||||
type LedgerEntry struct {
|
||||
LedgerSequence int64 `json:"ledger_sequence"`
|
||||
TaskID string `json:"task_id"`
|
||||
AgentID string `json:"agent_id"`
|
||||
Action string `json:"action"`
|
||||
Parents []string `json:"parents"`
|
||||
ECTJWS string `json:"ect_jws"`
|
||||
SignatureVerified bool `json:"signature_verified"`
|
||||
VerificationTime time.Time `json:"verification_timestamp"`
|
||||
StoredTime time.Time `json:"stored_timestamp"`
|
||||
}
|
||||
|
||||
// Ledger is the audit ledger interface per Section 9. Append-only; lookup by tid.
|
||||
type Ledger interface {
|
||||
// Append records a verified ECT. Returns the new ledger sequence number or error.
|
||||
Append(ectJWS string, payload *Payload) (seq int64, err error)
|
||||
// GetByTid returns the payload for the given task ID, or nil.
|
||||
GetByTid(tid string) *Payload
|
||||
// Contains returns true if (tid, wid) exists. wid may be empty for global scope.
|
||||
Contains(tid, wid string) bool
|
||||
// ECTStore implementation for DAG validation
|
||||
ECTStore
|
||||
}
|
||||
|
||||
// MemoryLedger is an in-memory, append-only ECT store implementing Ledger and ECTStore.
|
||||
type MemoryLedger struct {
|
||||
mu sync.RWMutex
|
||||
seq int64
|
||||
byTid map[string]*Payload
|
||||
bySeq []LedgerEntry
|
||||
entries []LedgerEntry // full entries for audit
|
||||
}
|
||||
|
||||
// NewMemoryLedger creates an empty in-memory ledger.
|
||||
func NewMemoryLedger() *MemoryLedger {
|
||||
return &MemoryLedger{
|
||||
byTid: make(map[string]*Payload),
|
||||
bySeq: make([]LedgerEntry, 0),
|
||||
}
|
||||
}
|
||||
|
||||
// Append implements Ledger.
|
||||
func (m *MemoryLedger) Append(ectJWS string, payload *Payload) (int64, error) {
|
||||
if payload == nil {
|
||||
return 0, nil
|
||||
}
|
||||
m.mu.Lock()
|
||||
defer m.mu.Unlock()
|
||||
// Uniqueness: jti (task id) must not already exist (scoped by wid when present) per spec
|
||||
wid := payload.Wid
|
||||
if m.containsLocked(payload.Jti, wid) {
|
||||
return 0, ErrTaskIDExists
|
||||
}
|
||||
m.seq++
|
||||
entry := LedgerEntry{
|
||||
LedgerSequence: m.seq,
|
||||
TaskID: payload.Jti, // task id = jti per spec
|
||||
AgentID: payload.Iss,
|
||||
Action: payload.ExecAct,
|
||||
Parents: append([]string(nil), payload.Par...),
|
||||
ECTJWS: ectJWS,
|
||||
SignatureVerified: true,
|
||||
VerificationTime: time.Now().UTC(),
|
||||
StoredTime: time.Now().UTC(),
|
||||
}
|
||||
m.byTid[payload.Jti] = payload
|
||||
m.bySeq = append(m.bySeq, entry)
|
||||
m.entries = append(m.entries, entry)
|
||||
return m.seq, nil
|
||||
}
|
||||
|
||||
// GetByTid implements ECTStore and Ledger.
|
||||
func (m *MemoryLedger) GetByTid(tid string) *Payload {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.byTid[tid]
|
||||
}
|
||||
|
||||
// Contains implements ECTStore and Ledger.
|
||||
func (m *MemoryLedger) Contains(tid, wid string) bool {
|
||||
m.mu.RLock()
|
||||
defer m.mu.RUnlock()
|
||||
return m.containsLocked(tid, wid)
|
||||
}
|
||||
|
||||
func (m *MemoryLedger) containsLocked(tid, wid string) bool {
|
||||
p, ok := m.byTid[tid]
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if wid == "" {
|
||||
return true
|
||||
}
|
||||
return p.Wid == wid
|
||||
}
|
||||
|
||||
// ErrTaskIDExists is returned when appending an ECT whose jti already exists.
|
||||
var ErrTaskIDExists = errors.New("ect: task ID (jti) already exists in ledger")
|
||||
Reference in New Issue
Block a user