1- // Copyright 2025 Google LLC. All Rights Reserved.
1+ // Copyright 2026 Google LLC. All Rights Reserved.
22//
33// Licensed under the Apache License, Version 2.0 (the "License");
44// you may not use this file except in compliance with the License.
1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15- // logandmap is a binary that serves as a demo of how to run a log and a map in the
16- // same process.
17- // The log is a Tessera POSIX log, and the map is an in-memory verifiable index.
18- // A web server is hosted that allows lookups in the map to be performed.
19- // The log is updated periodically with entries of type LogEntry, and the map keys
20- // each of the module names from that struct to each of the indices in the log where
21- // an entry for that module is stored.
15+ // ct is a binary that indexes a static CT log (the input log) into a verifiable
16+ // index, and publishes the index checkpoints to a Tessera POSIX log (the output log).
17+ // A web server is hosted that allows lookups in the index to be performed.
2218package main
2319
2420import (
@@ -89,6 +85,16 @@ func run(ctx context.Context) error {
8985 if * storageDir == "" {
9086 return errors .New ("storage_dir must be set" )
9187 }
88+ if * inputLogUrl == "" {
89+ return errors .New ("monitoring_url must be set" )
90+ }
91+ if * origin == "" {
92+ return errors .New ("origin must be set" )
93+ }
94+ if * pubKey == "" {
95+ return errors .New ("public_key must be set" )
96+ }
97+
9298 outputLogDir := path .Join (* storageDir , "outputlog" )
9399 mapRoot := path .Join (* storageDir , "vindex" )
94100
@@ -112,10 +118,16 @@ func run(ctx context.Context) error {
112118 }
113119 }()
114120
115- outputLog , outputCloser := outputLogOrDie (ctx , outputLogDir )
121+ outputLog , outputCloser , err := newOutputLogFromFlags (ctx , outputLogDir )
122+ if err != nil {
123+ return err
124+ }
116125 defer outputCloser (ctx )
117126
118- inputLog := newStaticCTInputLogFromFlags ()
127+ inputLog , err := newStaticCTInputLogFromFlags ()
128+ if err != nil {
129+ return err
130+ }
119131
120132 vi , err := vindex .NewVerifiableIndex (ctx , inputLog , mapFn , outputLog , mapRoot , vindex.Options {
121133 PersistIndex : * persistIndex ,
@@ -148,7 +160,7 @@ func cutEntry(tile []byte) (entry []byte, rh tlog.Hash, rest []byte, err error)
148160 return entry , rh , rest , nil
149161}
150162
151- func newStaticCTInputLogFromFlags () * staticCTInputLog {
163+ func newStaticCTInputLogFromFlags () ( * staticCTInputLog , error ) {
152164 ua := userAgent
153165 if * userAgentInfo != "" {
154166 ua = fmt .Sprintf ("%s (%s)" , userAgent , * userAgentInfo )
@@ -157,24 +169,28 @@ func newStaticCTInputLogFromFlags() *staticCTInputLog {
157169 torchwood .WithTilePath (sunlight .TilePath ),
158170 torchwood .WithUserAgent (ua ))
159171 if err != nil {
160- klog . Exitf ("failed to create client : %v " , err )
172+ return nil , fmt . Errorf ("failed to create tile fetcher : %w " , err )
161173 }
162174 var tileReader torchwood.TileReader = fetcher
163175 if * persistentCacheDir != "" {
164176 tileReader , err = torchwood .NewPermanentCache (fetcher , * persistentCacheDir )
165177 if err != nil {
166- klog . Exitf ("failed to create permanent cache: %v " , err )
178+ return nil , fmt . Errorf ("failed to create permanent cache: %w " , err )
167179 }
168180 }
169181 client , err := torchwood .NewClient (tileReader , torchwood .WithCutEntry (cutEntry ))
170182 if err != nil {
171- klog .Exitf ("failed to create client: %v" , err )
183+ return nil , fmt .Errorf ("failed to create torchwood client: %w" , err )
184+ }
185+ v , err := verifierFromFlags ()
186+ if err != nil {
187+ return nil , err
172188 }
173189 return & staticCTInputLog {
174190 c : client ,
175191 f : fetcher ,
176- v : verifierFromFlags () ,
177- }
192+ v : v ,
193+ }, nil
178194}
179195
180196type staticCTInputLog struct {
@@ -224,45 +240,47 @@ func (l *staticCTInputLog) Leaves(ctx context.Context, start, end uint64) iter.S
224240 }
225241}
226242
227- // outputLogOrDie returns an output log using a POSIX log in the given directory.
228- func outputLogOrDie (ctx context.Context , outputLogDir string ) (log vindex.OutputLog , closer func (context.Context )) {
229- s , v := getOutputLogSignerVerifierOrDie ()
243+ func newOutputLogFromFlags (ctx context.Context , outputLogDir string ) (vindex.OutputLog , func (context.Context ), error ) {
244+ s , v , err := getOutputLogSignerVerifier ()
245+ if err != nil {
246+ return nil , nil , err
247+ }
230248
231249 l , c , err := vindex .NewOutputLog (ctx , outputLogDir , s , v , vindex.OutputLogOpts {})
232250 if err != nil {
233- klog . Exit ( err )
251+ return nil , nil , fmt . Errorf ( "failed to create output log: %w" , err )
234252 }
235- return l , c
253+ return l , c , nil
236254}
237255
238- func verifierFromFlags () note.Verifier {
256+ func verifierFromFlags () ( note.Verifier , error ) {
239257 if * origin == "" {
240- klog . Exitf ( "Must provide the --origin flag " )
258+ return nil , errors . New ( "origin must be set " )
241259 }
242260 if * pubKey == "" {
243- klog . Exitf ( "Must provide the --pub_key flag " )
261+ return nil , errors . New ( "public_key must be set " )
244262 }
245263 derBytes , err := base64 .StdEncoding .DecodeString (* pubKey )
246264 if err != nil {
247- klog . Exitf ( "Error decoding public key: %s " , err )
265+ return nil , fmt . Errorf ( "error decoding public key: %w " , err )
248266 }
249267 pub , err := x509 .ParsePKIXPublicKey (derBytes )
250268 if err != nil {
251- klog . Exitf ( "Error parsing public key: %v " , err )
269+ return nil , fmt . Errorf ( "error parsing public key: %w " , err )
252270 }
253271
254272 verifierKey , err := fnote .RFC6962VerifierString (* origin , pub )
255273 if err != nil {
256- klog . Exitf ( "Error creating RFC6962 verifier string: %v " , err )
274+ return nil , fmt . Errorf ( "error creating RFC6962 verifier string: %w " , err )
257275 }
258276 logSigV , err := fnote .NewVerifier (verifierKey )
259277 if err != nil {
260- klog . Exitf ( "Error creating verifier: %v " , err )
278+ return nil , fmt . Errorf ( "error creating verifier: %w " , err )
261279 }
262280
263281 klog .Infof ("Using verifier string: %v" , verifierKey )
264282
265- return logSigV
283+ return logSigV , nil
266284}
267285
268286// maintainMap reads entries from the log and sync them to the vindex.
@@ -301,25 +319,25 @@ func runWebServer(vi *vindex.VerifiableIndex, outLogDir string) {
301319
302320// Read output log private key from file or environment variable and generate the
303321// note Signer and Verifier pair for it.
304- func getOutputLogSignerVerifierOrDie () (note.Signer , note.Verifier ) {
322+ func getOutputLogSignerVerifier () (note.Signer , note.Verifier , error ) {
305323 var privKey string
306324 var err error
307325 if len (* outputLogPrivKeyFile ) > 0 {
308326 privKey , err = getKeyFile (* outputLogPrivKeyFile )
309327 if err != nil {
310- klog . Exitf ( "Unable to get private key: %v " , err )
328+ return nil , nil , fmt . Errorf ( "unable to get private key: %w " , err )
311329 }
312330 } else {
313331 privKey = os .Getenv ("OUTPUT_LOG_PRIVATE_KEY" )
314332 if len (privKey ) == 0 {
315- klog . Exit ( "Supply private key file path using --output_log_private_key or set OUTPUT_LOG_PRIVATE_KEY environment variable" )
333+ return nil , nil , errors . New ( "supply private key file path using --output_log_private_key or set OUTPUT_LOG_PRIVATE_KEY environment variable" )
316334 }
317335 }
318336 s , v , err := fnote .NewEd25519SignerVerifier (privKey )
319337 if err != nil {
320- klog . Exitf ( "Failed to get signer/verifier: %v " , err )
338+ return nil , nil , fmt . Errorf ( "failed to get signer/verifier: %w " , err )
321339 }
322- return s , v
340+ return s , v , nil
323341}
324342
325343func getKeyFile (path string ) (string , error ) {
0 commit comments