Skip to content

Commit

Permalink
Address review suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
Robin Bryce committed Oct 30, 2024
1 parent 6363dd4 commit 23d60cf
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 19 deletions.
9 changes: 3 additions & 6 deletions massifs/mmriver.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,15 @@ type MMRiverVerifiableProofsHeader struct {
VerifiableProofs MMRiverVerifiableProofs `cbor:"396,keyasint"`
}

/*
func SetMMRiverInclusionProofsHeader(
msg *commoncose.CoseSign1Message, massif MassifReader, mmrSize, mmrIndex uint64) error {
msg.Headers.Unprotected[VDSCoseReceiptProofsTag] = proofs
}*/

// VerifySignedInclusionReceipts verifies a signed COSE receipt encoded according to the MMRIVER VDS
// on success the produced root is returned.
// Signature verification failure is not an error, but the returned root will be nil and the result will be false.
// All other unexpected issues are returned as errors, with a false result and nil root.
// Note that MMRIVER receipts allow for multiple inclusion proofs to be attached to the receipt.
// This function returns true only if ALL receipts verify
//
// The candidates array provides the *candidate* values. Once verified, we can call them node values (or leaves),
// Note that any node value in the log may be proven by a receipt, not just leaves.
func VerifySignedInclusionReceipts(
ctx context.Context,
receipt *commoncose.CoseSign1Message,
Expand Down
38 changes: 28 additions & 10 deletions massifs/rootsigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,20 +177,38 @@ func (rs RootSigner) Sign1(
return encodable.MarshalCBOR()
}

// Note: regarding why and how we can pre-sign receipts:
//
// A specific advantage of MMR's is that we can pre-sign the protected headers
// for all receipts we will ever be asked for. The scitt endpoint then only has
// to copy the pre-signed receipt and *add* the inclusion path it is asked for.
//
// Importantly, this allows for self service *privacy preserving*, scitt
// compatible, receipts based on replicated copies of the log.
// signEmptyPeakReceipts signs and encodes a COSE Receipt (MMRIVER) for each
// peak in the accumulator.
//
// The most natural place to produce the pre-signed receipts is in the the log
// confirmer, because we are allways pre-signing *peaks* of the MMR. And the
// consistency between peaks (accumulators) is the concern of the sealer by way
// of LogConfirmer. And the most natural place to store them is in the massif seal.
// Whis is what we accomodate here.
// of LogConfirmer. And the most natural place to store them is in the massif
// seal. Which is what we accomodate here.
//
// It is a specific property of MMR based logs that proofs of inclusion always
// lead to an accumulator peak. This leads to the ability to pre-sign receipts
// *once* for all possible inclusion proofs in the current mmr state by simply
// singing the peak and leaving the proof empty. Because the proofs are never
// signed, (the are attached in the unprotected header), Those can be added on
// demand in a completely trustless way.
//
// Importantly, this allows for self service *privacy preserving*, scitt
// compatible, receipts based on replicated copies of the log. The signing key
// is not required to attach the proof.
//
// Notice that, due to the Low Update Frequency property, defined in
// https://eprint.iacr.org/2015/718.pdf, *many* MMR sizes will contain the same
// peak. Over time, the signed peak for any element changes less and less
// frequently (log base 2). This means, in addition to being able to pre-sign,
// the work required of a receipt holder to check the log remains consistent
// with their old receipt gets less and less. And, in the case of a receipt
// against an unequivocal log state, completely redundant. The receipt holders
// can also significantly compress the receipt data they retain.
//
// It is true, due to low update frequency, that many may be copies of earlier
// receipts, but the locality here means consumers only need to hit one blob and
// in doing so reveal less about their area of interest.
func (c *RootSigner) signEmptyPeakReceipts(
coseSigner cose.Signer,
publicKey *ecdsa.PublicKey,
Expand Down
6 changes: 3 additions & 3 deletions mmr/consistentroots.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ var (
// The order of the roots returned matches the order of the nodes in the accumulator.
//
// Args:
// - fromSize the size the complete MMR from which consistency was proven.
// - ifrom the last node index of the the complete MMR from which consistency was proven.
// - accumulatorfrom the node values correponding to the peaks of the accumulator at MMR(sizeA)
// - proofs the inclusion proofs for each node in accumulatorfrom in MMR(sizeB)
func ConsistentRoots(hasher hash.Hash, ifrom uint64, accumulatorfrom [][]byte, proofs [][][]byte) ([][]byte, error) {
Expand All @@ -36,9 +36,9 @@ func ConsistentRoots(hasher hash.Hash, ifrom uint64, accumulatorfrom [][]byte, p

roots := [][]byte{}

for iacc := 0; iacc < len(accumulatorfrom); iacc++ {
for i := 0; i < len(accumulatorfrom); i++ {
// remembering that peaks are 1 based (for now)
root := IncludedRoot(hasher, frompeaks[iacc], accumulatorfrom[iacc], proofs[iacc])
root := IncludedRoot(hasher, frompeaks[i], accumulatorfrom[i], proofs[i])
// The nature of MMR's is that many nodes are committed by the
// same accumulator peak, and that peak changes with
// low frequency.
Expand Down

0 comments on commit 23d60cf

Please sign in to comment.