-
Notifications
You must be signed in to change notification settings - Fork 257
Description
Version(s) of tendermint-rs: v0.24.0-pre.2
Description
"privval" is an interface used by a Tendermint process (on validator nodes) to communicate with a signing backend (e.g. YubiHSM).
Previously, "privval" was over a custom socket protocol (implemented e.g. in tmkms) that leveraged Unix domain sockets or Tendermint P2P over TCP where Tendermint acted as a server, and a signing backend connected to it as a client.
In Tendermint 0.35, a new method for "privval" was introduced: the signer is a standard gRPC server/service, and Tendermint connects to it as a client.
In Tendermint 0.36, we expect the old "privval" custom socket protocol will be removed and only the gRPC-based "privval" interface will be provided.
Given these circumstances, I think it makes sense for tendermint-rs to support this interface via the following features:
- provide a "raw" service API definition by enabling
build_server(true)in tonic_build, probably via a feature-flag (as not every usage of tendermint-proto needs it) - provide a high-level wrapper over the raw service (likely in a new "tendermint-validator" crate) which should do the following:
- provide a basic gRPC server construction options for tonic's Server (e.g. TLS)
- do basic validation of requests:
- use the existing domain types
- check chain ids against the configured ones
- check the provided signer's state against the state in a request (see
update_consensus_statein tmkms https://github.com/iqlusioninc/tmkms/blob/main/src/chain/state.rs#L66 )
- return a cached public key or request a signature from a signing backend, and return corresponding responses
- provide a simple interface that can be implemented by different signer backends
Here's a sketch of the potential interface:
#[async_trait]
pub trait SignerProvider {
async fn sign(&self, signable_bytes: &[u8]) -> Result<Signature, Error>;
async fn load_pubkey(&self) -> Result<PublicKey, Error>;
async fn load_state(&self) -> Result<consensus::State, Error>;
async fn persist_state(&mut self, new_state: &consensus::State) -> Result<(), Error>;
}load_state and persist_state could potentially be in a separate trait, so that one can e.g. have a default file-based state persistence, but different signer backends are free to implement what makes sense in their context (e.g. write to CPU monotonic counters or an external service).
Definition of "done"
- a feature-flag in tendermint-proto to generate gRPC server definitions (
PrivValidatorApi,PrivValidatorApiServer...): tendermint-proto: Add a feature flag and generate gRPC server definitions #1137 - a new "tendermint-validator" crate that provides a default
PrivValidatorApiimplementation (validation of types via domain types, basic double signing checking, chain-id verification) with basic common constructors or configurations (e.g. to load the certificates for TLS) and an extensible way to plug in different signer providers (with a software signer given as a sample implementation)
Related issues: