@@ -21,11 +21,8 @@ import (
2121 "golang.org/x/crypto/cryptobyte"
2222)
2323
24- const csLen = 32
25-
2624var (
27- ErrChecksumInvalid = errors .New ("Invalid checksum" )
28- ErrClosed = errors .New ("Handle is closed" )
25+ ErrClosed = errors .New ("Handle is closed" )
2926)
3027
3128type NewOpts struct {
@@ -50,76 +47,12 @@ type Handle struct {
5047
5148 indices map [uint32 ]* Index
5249 aas map [uint32 ]* os.File
50+ evs map [uint32 ]* os.File
5351 trees map [uint32 ]* Tree
5452
5553 batchNumbersCache []uint32 // cache for existing batches
5654}
5755
58- type QueuedAssertion struct {
59- Checksum []byte
60- Assertion mtc.Assertion
61- }
62-
63- func (a * QueuedAssertion ) UnmarshalBinary (data []byte ) error {
64- var (
65- s cryptobyte.String = cryptobyte .String (data )
66- checksum [csLen ]byte
67- )
68- if ! s .CopyBytes (checksum [:]) {
69- return mtc .ErrTruncated
70- }
71-
72- a .Checksum = make ([]byte , csLen )
73- copy (a .Checksum , checksum [:])
74-
75- checksum2 := sha256 .Sum256 ([]byte (s ))
76- if ! bytes .Equal (checksum2 [:], checksum [:]) {
77- return ErrChecksumInvalid
78- }
79-
80- if err := a .Assertion .UnmarshalBinary ([]byte (s )); err != nil {
81- return err
82- }
83-
84- return nil
85- }
86-
87- func (a * QueuedAssertion ) marshalAndCheckAssertion () ([]byte , error ) {
88- buf , err := a .Assertion .MarshalBinary ()
89- if err != nil {
90- return nil , err
91- }
92-
93- checksum2 := sha256 .Sum256 ([]byte (buf ))
94- if a .Checksum == nil {
95- a .Checksum = checksum2 [:]
96- } else if ! bytes .Equal (checksum2 [:], a .Checksum ) {
97- return nil , ErrChecksumInvalid
98- }
99-
100- return buf , nil
101- }
102-
103- // If set, checks whether the Checksum is correct. If not set, sets the
104- // Checksum to the correct value.
105- func (a * QueuedAssertion ) Check () error {
106- _ , err := a .marshalAndCheckAssertion ()
107- return err
108- }
109-
110- func (a * QueuedAssertion ) MarshalBinary () ([]byte , error ) {
111- var b cryptobyte.Builder
112-
113- buf , err := a .marshalAndCheckAssertion ()
114- if err != nil {
115- return nil , err
116- }
117- b .AddBytes (a .Checksum )
118- b .AddBytes (buf )
119-
120- return b .Bytes ()
121- }
122-
12356func (ca * Handle ) Params () mtc.CAParams {
12457 return ca .params
12558}
@@ -137,6 +70,10 @@ func (ca *Handle) Close() error {
13770 r .Close ()
13871 }
13972
73+ for _ , r := range ca .evs {
74+ r .Close ()
75+ }
76+
14077 for _ , t := range ca .trees {
14178 t .Close ()
14279 }
@@ -165,7 +102,7 @@ func (h *Handle) dropQueue() error {
165102//
166103// For each entry, if checksum is not nil, makes sure the assertion
167104// matches the checksum
168- func (h * Handle ) QueueMultiple (it func (yield func (qa QueuedAssertion ) error ) error ) error {
105+ func (h * Handle ) QueueMultiple (it func (yield func (ar mtc. AssertionRequest ) error ) error ) error {
169106 if h .closed {
170107 return ErrClosed
171108 }
@@ -177,8 +114,8 @@ func (h *Handle) QueueMultiple(it func(yield func(qa QueuedAssertion) error) err
177114 defer w .Close ()
178115 bw := bufio .NewWriter (w )
179116
180- if err := it (func (qa QueuedAssertion ) error {
181- buf , err := qa .MarshalBinary ()
117+ if err := it (func (ar mtc. AssertionRequest ) error {
118+ buf , err := ar .MarshalBinary ()
182119 if err != nil {
183120 return err
184121 }
@@ -208,14 +145,9 @@ func (h *Handle) QueueMultiple(it func(yield func(qa QueuedAssertion) error) err
208145// Queue assertion for publication.
209146//
210147// If checksum is not nil, makes sure assertion matches the checksum.
211- func (h * Handle ) Queue (a mtc.Assertion , checksum []byte ) error {
212- return h .QueueMultiple (func (yield func (qa QueuedAssertion ) error ) error {
213- return yield (
214- QueuedAssertion {
215- Checksum : checksum ,
216- Assertion : a ,
217- },
218- )
148+ func (h * Handle ) Queue (ar mtc.AssertionRequest ) error {
149+ return h .QueueMultiple (func (yield func (ar mtc.AssertionRequest ) error ) error {
150+ return yield (ar )
219151 })
220152}
221153
@@ -227,6 +159,7 @@ func Open(path string) (*Handle, error) {
227159 path : path ,
228160 indices : make (map [uint32 ]* Index ),
229161 aas : make (map [uint32 ]* os.File ),
162+ evs : make (map [uint32 ]* os.File ),
230163 trees : make (map [uint32 ]* Tree ),
231164 }
232165 if err := h .lock (); err != nil {
@@ -282,6 +215,10 @@ func (h Handle) aaPath(number uint32) string {
282215 return gopath .Join (h .batchPath (number ), "abridged-assertions" )
283216}
284217
218+ func (h Handle ) evPath (number uint32 ) string {
219+ return gopath .Join (h .batchPath (number ), "evidence" )
220+ }
221+
285222func (h Handle ) batchPath (number uint32 ) string {
286223 return gopath .Join (h .batchesPath (), fmt .Sprintf ("%d" , number ))
287224}
@@ -387,7 +324,7 @@ func (h *Handle) listBatchRange() (mtc.BatchRange, error) {
387324}
388325
389326// Calls f on each assertion queued to be published.
390- func (h * Handle ) WalkQueue (f func (QueuedAssertion ) error ) error {
327+ func (h * Handle ) WalkQueue (f func (mtc. AssertionRequest ) error ) error {
391328 r , err := os .OpenFile (h .queuePath (), os .O_RDONLY , 0 )
392329 if err != nil {
393330 return fmt .Errorf ("Opening queue: %w" , err )
@@ -400,7 +337,7 @@ func (h *Handle) WalkQueue(f func(QueuedAssertion) error) error {
400337 var (
401338 prefix [2 ]byte
402339 aLen uint16
403- qa QueuedAssertion
340+ ar mtc. AssertionRequest
404341 )
405342 _ , err := io .ReadFull (br , prefix [:])
406343 if err == io .EOF {
@@ -418,12 +355,12 @@ func (h *Handle) WalkQueue(f func(QueuedAssertion) error) error {
418355 return fmt .Errorf ("Reading queue: %w" , err )
419356 }
420357
421- err = qa .UnmarshalBinary (buf )
358+ err = ar .UnmarshalBinary (buf )
422359 if err != nil {
423360 return fmt .Errorf ("Parsing queue: %w" , err )
424361 }
425362
426- err = f (qa )
363+ err = f (ar )
427364 if err != nil {
428365 return err
429366 }
@@ -489,6 +426,14 @@ func (h *Handle) closeBatch(batch uint32) error {
489426 delete (h .aas , batch )
490427 }
491428
429+ if r , ok := h .evs [batch ]; ok {
430+ err := r .Close ()
431+ if err != nil {
432+ return fmt .Errorf ("closing evidence for %d: %w" , batch , err )
433+ }
434+ delete (h .evs , batch )
435+ }
436+
492437 if r , ok := h .trees [batch ]; ok {
493438 err := r .Close ()
494439 if err != nil {
@@ -545,10 +490,25 @@ func (ca *Handle) aaFileFor(batch uint32) (*os.File, error) {
545490 return r , nil
546491}
547492
493+ // Returns file handle to evidence file for the given batch.
494+ func (ca * Handle ) evFileFor (batch uint32 ) (* os.File , error ) {
495+ if r , ok := ca .evs [batch ]; ok {
496+ return r , nil
497+ }
498+
499+ r , err := os .Open (ca .evPath (batch ))
500+ if err != nil {
501+ return nil , err
502+ }
503+
504+ return r , nil
505+ }
506+
548507type keySearchResult struct {
549508 Batch uint32
550509 SequenceNumber uint64
551510 Offset uint64
511+ EvidenceOffset uint64
552512}
553513
554514// Returns the certificate for an issued assertion
@@ -589,7 +549,46 @@ func (ca *Handle) CertificateFor(a mtc.Assertion) (*mtc.BikeshedCertificate, err
589549 }, nil
590550}
591551
592- // Search for AbridgedAssertions's batch/seqno/offset by key.
552+ var errShortCircuit = errors .New ("short circuit" )
553+
554+ // Returns the evidence for an issued assertion
555+ func (ca * Handle ) EvidenceFor (a mtc.Assertion ) (* mtc.Evidence , error ) {
556+ aa := a .Abridge ()
557+ var key [mtc .HashLen ]byte
558+ err := aa .Key (key [:])
559+ if err != nil {
560+ return nil , err
561+ }
562+ res , err := ca .aaByKey (key [:])
563+ if err != nil {
564+ return nil , fmt .Errorf ("searching by key: %w" , err )
565+ }
566+
567+ if res == nil {
568+ return nil , fmt .Errorf ("no assertion with key %x on record" , key )
569+ }
570+
571+ var ev * mtc.Evidence
572+ evFile , err := ca .evFileFor (res .Batch )
573+ if err != nil {
574+ return nil , err
575+ }
576+ _ , err = evFile .Seek (int64 (res .EvidenceOffset ), 0 )
577+ if err != nil {
578+ return nil , err
579+ }
580+ err = mtc .UnmarshalEvidenceEntries (evFile , func (_ int , ev2 * mtc.Evidence ) error {
581+ ev = ev2
582+ return errShortCircuit
583+ })
584+ if err != errShortCircuit {
585+ return nil , err
586+ }
587+
588+ return ev , nil
589+ }
590+
591+ // Search for AbridgedAssertions's batch/seqno/offset/evidence_offset by key.
593592func (ca * Handle ) aaByKey (key []byte ) (* keySearchResult , error ) {
594593 batches , err := ca .listBatchRange ()
595594 if err != nil {
@@ -600,7 +599,7 @@ func (ca *Handle) aaByKey(key []byte) (*keySearchResult, error) {
600599 return nil , nil
601600 }
602601
603- for batch := batches .End - 1 ; batch <= batches .End ; batch -- {
602+ for batch := batches .End - 1 ; batch >= batches . Begin && batch <= batches .End ; batch -- {
604603 res , err := ca .aaByKeyIn (batch , key )
605604 if err != nil {
606605 return nil , fmt .Errorf ("Searching in batch %d: %w" , batch , err )
@@ -610,6 +609,7 @@ func (ca *Handle) aaByKey(key []byte) (*keySearchResult, error) {
610609 Batch : batch ,
611610 SequenceNumber : res .SequenceNumber ,
612611 Offset : res .Offset ,
612+ EvidenceOffset : res .EvidenceOffset ,
613613 }, nil
614614 }
615615 }
@@ -760,6 +760,7 @@ func (h *Handle) issueBatch(number uint32, empty bool) error {
760760 "tree" ,
761761 "signed-validity-window" ,
762762 "abridged-assertions" ,
763+ "evidence" ,
763764 "index" ,
764765 },
765766 )
@@ -884,7 +885,7 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
884885 prevHeads = w .ValidityWindow .TreeHeads
885886 }
886887
887- // Read queue and write abridged-assertions
888+ // Read queue and write abridged-assertions and evidence
888889 aasPath := gopath .Join (dir , "abridged-assertions" )
889890 aasW , err := os .Create (aasPath )
890891 if err != nil {
@@ -893,23 +894,48 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
893894 defer aasW .Close ()
894895 aasBW := bufio .NewWriter (aasW )
895896
897+ evPath := gopath .Join (dir , "evidence" )
898+ evW , err := os .Create (evPath )
899+ if err != nil {
900+ return fmt .Errorf ("creating %s: %w" , evPath , err )
901+ }
902+ defer evW .Close ()
903+ evBW := bufio .NewWriter (evW )
904+
896905 if ! empty {
897- err = h .WalkQueue (func (qa QueuedAssertion ) error {
898- aa := qa .Assertion .Abridge ()
906+ err = h .WalkQueue (func (ar mtc. AssertionRequest ) error {
907+ aa := ar .Assertion .Abridge ()
899908 buf , err := aa .MarshalBinary ()
900909 if err != nil {
901- return fmt .Errorf ("Marshalling assertion %x: %w" , qa .Checksum , err )
910+ return fmt .Errorf ("Marshalling assertion %x: %w" , ar .Checksum , err )
902911 }
903912
904913 _ , err = aasBW .Write (buf )
905914 if err != nil {
906915 return fmt .Errorf (
907916 "Writing assertion %x to %s: %w" ,
908- qa .Checksum ,
917+ ar .Checksum ,
909918 aasPath ,
910919 err ,
911920 )
912921 }
922+
923+ ev := ar .Evidence
924+ buf , err = ev .MarshalBinary ()
925+ if err != nil {
926+ return fmt .Errorf ("Marshalling evidence %x: %w" , ar .Checksum , err )
927+ }
928+
929+ _ , err = evBW .Write (buf )
930+ if err != nil {
931+ return fmt .Errorf (
932+ "Writing evidence %x to %s: %w" ,
933+ ar .Checksum ,
934+ evPath ,
935+ err ,
936+ )
937+ }
938+
913939 return nil
914940 })
915941 if err != nil {
@@ -932,6 +958,21 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
932958 }
933959 defer aasR .Close ()
934960
961+ err = evBW .Flush ()
962+ if err != nil {
963+ return fmt .Errorf ("flushing %s: %w" , evPath , err )
964+ }
965+
966+ err = evW .Close ()
967+ if err != nil {
968+ return fmt .Errorf ("closing %s: %w" , evPath , err )
969+ }
970+ evR , err := os .OpenFile (evPath , os .O_RDONLY , 0 )
971+ if err != nil {
972+ return fmt .Errorf ("opening %s: %w" , evPath , err )
973+ }
974+ defer evR .Close ()
975+
935976 // Compute tree
936977 tree , err := batch .ComputeTree (bufio .NewReader (aasR ))
937978 if err != nil {
@@ -970,7 +1011,7 @@ func (h *Handle) issueBatchTo(dir string, batch mtc.Batch, empty bool) error {
9701011
9711012 defer indexW .Close ()
9721013
973- err = ComputeIndex (aasR , indexW )
1014+ err = ComputeIndex (aasR , evR , indexW )
9741015 if err != nil {
9751016 return fmt .Errorf ("computing %s to start: %w" , indexPath , err )
9761017 }
0 commit comments