diff --git a/libs/gl-client/src/signer/mod.rs b/libs/gl-client/src/signer/mod.rs index c84b9bb80..12035f675 100644 --- a/libs/gl-client/src/signer/mod.rs +++ b/libs/gl-client/src/signer/mod.rs @@ -441,6 +441,7 @@ impl Signer { raw: response.0.as_vec(), request_id: req.request_id, signer_state, + state_sketch: None }) } diff --git a/libs/gl-plugin/src/hsm.rs b/libs/gl-plugin/src/hsm.rs index 2a90878a3..9f0f763aa 100644 --- a/libs/gl-plugin/src/hsm.rs +++ b/libs/gl-plugin/src/hsm.rs @@ -63,6 +63,7 @@ impl Hsm for StagingHsmServer { request_id: req.request_id, raw: response, signer_state: Vec::new(), + state_sketch: None, })); } else if req.get_type() == 11 { debug!("Returning stashed init msg: {:?}", self.node_info.initmsg); @@ -70,6 +71,7 @@ impl Hsm for StagingHsmServer { request_id: req.request_id, raw: self.node_info.initmsg.clone(), signer_state: Vec::new(), // the signerproxy doesn't care about state + state_sketch: None })); } else if req.get_type() == 33 { debug!("Returning stashed dev-memleak response"); @@ -77,6 +79,7 @@ impl Hsm for StagingHsmServer { request_id: req.request_id, raw: vec![0, 133, 0], signer_state: Vec::new(), // the signerproxy doesn't care about state + state_sketch: None })); } diff --git a/libs/gl-plugin/src/node/mod.rs b/libs/gl-plugin/src/node/mod.rs index 6ce8d7b9b..eaa3171f2 100644 --- a/libs/gl-plugin/src/node/mod.rs +++ b/libs/gl-plugin/src/node/mod.rs @@ -317,6 +317,7 @@ impl Node for PluginNodeServer { raw: msg.as_vec(), requests: vec![], // No pending requests yet, nothing to authorize. context: None, + state_sketch: None, // TODO(cdecker) Make this a summary of our state. }; if let Err(e) = tx.send(Ok(req)).await { diff --git a/libs/gl-signerproxy/src/hsmproxy.rs b/libs/gl-signerproxy/src/hsmproxy.rs index 3413964d0..846ce08d6 100644 --- a/libs/gl-signerproxy/src/hsmproxy.rs +++ b/libs/gl-signerproxy/src/hsmproxy.rs @@ -101,6 +101,7 @@ async fn process_requests( request_id: request_counter.fetch_add(1, atomic::Ordering::Relaxed) as u32, requests: Vec::new(), signer_state: Vec::new(), + state_sketch: None, }); let start_time = tokio::time::Instant::now(); debug!("Got a message from node: {:?}", &req); diff --git a/libs/proto/greenlight.proto b/libs/proto/greenlight.proto index 8a15e0fce..d07a444b6 100644 --- a/libs/proto/greenlight.proto +++ b/libs/proto/greenlight.proto @@ -69,6 +69,12 @@ message HsmResponse { // A list of updated key-value-version tuples that is to be // merged into the state tracked by the plugin. repeated SignerStateEntry signer_state = 5; + + // A sketch summarizing the signer_state for the recipient to + // ensure that it has the latest state. Used in the + // differential sync to ensure that the diff is complete and + // doesn't miss some state changes. + SignerStateSketch state_sketch = 6; } message HsmRequest { @@ -83,6 +89,8 @@ message HsmRequest { // Currently active requests that are used to justify changes // in state. repeated PendingRequest requests = 5; + // Sketch to ensure we have the latest version + SignerStateSketch state_sketch = 6; } message Empty {} @@ -489,6 +497,23 @@ message SignerStateEntry { bytes value = 3; } +// A SignerStateSketch is a summary of the signer state, not including +// the values, but containing the metadata. It is used by the signer +// to tell the plugin about its current status, so the plugin doesn't +// send us an entire snapshot. In addition it can be used in the +// incremental mode to communicate the latest state, in order to allow +// asserting that we're not missing any state in the diff. +message SignerStateSketch { + repeated SketchEntry entries = 1; +} + +// The metadata of a single state entry. Does not include the value, +// and is used to communicate the version current state. +message SketchEntry { + uint64 version = 1; + string key = 2; +} + // This represents a grpc request that is currently pending, along // with the pubkey of the client issuing the request and a matching // signature. This allows the signer to verify that the state changes @@ -499,7 +524,7 @@ message PendingRequest { string uri = 2; bytes signature = 3; bytes pubkey = 4; - uint64 timestamp = 5; + uint64 timestamp = 5; } @@ -517,8 +542,8 @@ message NodeConfig { // The `GlConfig` is used to pass greenlight-specific startup parameters -// to the node. The `gl-plugin` will look for a serialized config object in -// the node's datastore to load these values from. Please refer to the +// to the node. The `gl-plugin` will look for a serialized config object in +// the node's datastore to load these values from. Please refer to the // individual fields to learn what they do. message GlConfig { string close_to_addr = 1;