Derecho-Project / derecho

The main code repository for the Derecho project.
BSD 3-Clause "New" or "Revised" License
186 stars 47 forks source link

Fixed signature support to handle Delta-persistent objects #271

Closed etremel closed 5 months ago

etremel commented 6 months ago

My original implementation of signed persistent logs did not properly handle Delta-supporting Persistent fields in a few edge cases. Specifically, if a single Derecho Replicated object contains both a non-signed Persistent field and a signed Persistent field that has DeltaSupport enabled, it's possible for PersistentRegistry::sign() to produce the warning "Logic error: Version X was returned by getMinimumVersionAfter(), but it did not exist in any field" and then a subsequent handle_verify_request to produce the warning "Verification of version X failed!" because it attempts to verify an empty signature.

This happens when makeVersion is called on the Replicated object when only the non-signed Persistent field was updated, which means the non-signed field creates a log entry but the Delta-supporting signed field just advances its current version without creating a log entry (since there is no Delta data). Then in PersistentRegistry::sign(), getMinimumVersionAfter() will return the new version that is in the non-signed log as cur_nonempty_version, but updateSignature won't sign any data for this version because it doesn't exist in the signed field's log. Making things even worse, getMinimumLatestVersion() can't be used to properly detect the "current version" in this situation, because the getLatestVersion() method only returns the latest version that is in a log entry, not the current version recorded in the meta-header file (which is what's updated when a Delta-supporting object advances its current version).

I fixed this with several changes: