This set of changes adds a new feature to Derecho: The ability to make nodes in a group sign each version of a persistent object and record this signature in the persistence log. All nodes in the group are expected to share the same private key, since they are all replicas of the same service; the signatures are for the purpose of proving to an external client that the Derecho group has "committed" to this update and cannot later claim to have a persistent log with different updates. The signature on each version of a replicated object covers both the data in that version and the signature of the previous version, so a signature is only valid if it is part of a chain of valid signatures going back to the first version of the object.
To add signatures to a persistent field in a replicated object, pass the optional parameter enable_signatures with value true to the Persistent<T> constructor. Then, make the replicated object inherit from the marker interface derecho::SignedPersistentFields rather than derecho::PersistsFields. Finally, ensure the config option PERS/private_key_file in derecho.cfg is set to a path to a private key in PEM format. An example of setting up a Derecho group with signed persistent objects is provided in the new test program applications/tests/unit_tests/signed_log_test.cpp.
When signatures are enabled, an additional callback is available in CallbackSet called global_verified_callback. This function takes the same parameters as the persistence callback (subgroup ID and version number), and it will be called when a new version of a subgroup's state has been persisted with a valid signature by all replicas in that subgroup. Each node will first persist its own update and then validate the other nodes' signatures on that update, so global_verified_callback should always occur after global_persistence_callback.
A node can also manually retrieve and verify the signature on any version of a persistent field by calling the methods Persistent::getSignature and Persistent::verify. However, note that there is one signature per replicated object, and a replicated object may have more than one persistent field, so each persistent field in the object will actually have the same signature for a given version. The methods PersistentRegistry::getSignature and PersistentRegistry::verify provide a consistent way of finding and verifying the single signature for a particular version of a replicated object, regardless of how many signed persistent fields it has.
When signatures are not enabled on any persistent field, this feature has no effect on Derecho and all persistent updates are delivered normally. @songweijia and I have thoroughly tested the performance of persistent updates on this branch with no signatures enabled (using persistent_bw_test.cpp) and found that there was no difference in throughput compared to the same tests being run on the "master" branch.
This set of changes adds a new feature to Derecho: The ability to make nodes in a group sign each version of a persistent object and record this signature in the persistence log. All nodes in the group are expected to share the same private key, since they are all replicas of the same service; the signatures are for the purpose of proving to an external client that the Derecho group has "committed" to this update and cannot later claim to have a persistent log with different updates. The signature on each version of a replicated object covers both the data in that version and the signature of the previous version, so a signature is only valid if it is part of a chain of valid signatures going back to the first version of the object.
To add signatures to a persistent field in a replicated object, pass the optional parameter
enable_signatures
with valuetrue
to thePersistent<T>
constructor. Then, make the replicated object inherit from the marker interfacederecho::SignedPersistentFields
rather thanderecho::PersistsFields
. Finally, ensure the config option PERS/private_key_file in derecho.cfg is set to a path to a private key in PEM format. An example of setting up a Derecho group with signed persistent objects is provided in the new test program applications/tests/unit_tests/signed_log_test.cpp.When signatures are enabled, an additional callback is available in
CallbackSet
calledglobal_verified_callback
. This function takes the same parameters as the persistence callback (subgroup ID and version number), and it will be called when a new version of a subgroup's state has been persisted with a valid signature by all replicas in that subgroup. Each node will first persist its own update and then validate the other nodes' signatures on that update, soglobal_verified_callback
should always occur afterglobal_persistence_callback
.A node can also manually retrieve and verify the signature on any version of a persistent field by calling the methods
Persistent::getSignature
andPersistent::verify
. However, note that there is one signature per replicated object, and a replicated object may have more than one persistent field, so each persistent field in the object will actually have the same signature for a given version. The methodsPersistentRegistry::getSignature
andPersistentRegistry::verify
provide a consistent way of finding and verifying the single signature for a particular version of a replicated object, regardless of how many signed persistent fields it has.When signatures are not enabled on any persistent field, this feature has no effect on Derecho and all persistent updates are delivered normally. @songweijia and I have thoroughly tested the performance of persistent updates on this branch with no signatures enabled (using
persistent_bw_test.cpp
) and found that there was no difference in throughput compared to the same tests being run on the "master" branch.