Skip to content

Commit

Permalink
plugin: Send a heartbeat as first message
Browse files Browse the repository at this point in the history
The heartbeat serves two purposes: 1) start sending the entire state
to the signer, so it can cache it locally, and 2) trigger a pruning
round on the signer state.
  • Loading branch information
cdecker committed Nov 17, 2023
1 parent c2062af commit 941c47a
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
1 change: 1 addition & 0 deletions libs/gl-client/src/signer/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ impl Resolver {
// we do an early pass:
let accept = match req {
// Commands that simply have no context to check against
Message::GetHeartbeat(_) => true,
Message::Ecdh(_) => true,
Message::Ping(_) => true,
Message::Pong(_) => true,
Expand Down
41 changes: 40 additions & 1 deletion libs/gl-plugin/src/node/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -282,9 +282,48 @@ impl Node for PluginNodeServer {
let mut stream = self.stage.mystream().await;
let signer_state = self.signer_state.clone();
let ctx = self.ctx.clone();

tokio::spawn(async move {
trace!("hsmd hsm_id={} request processor started", hsm_id);

{
// We start by immediately injecting a
// vls_protocol::Message::GetHeartbeat. This serves two
// purposes: already send the initial snapshot of the
// signer state to the signer as early as possible, and
// triggering a pruning on the signer, if enabled. In
// incremental mode this ensures that any subsequent,
// presumably time-critical messages, do not have to carry
// the large state with them.

let state = signer_state.lock().await.clone();
let state: Vec<gl_client::pb::SignerStateEntry> = state.into();
let state: Vec<pb::SignerStateEntry> = state
.into_iter()
.map(|s| pb::SignerStateEntry {
key: s.key,
version: s.version,
value: s.value,
})
.collect();

let msg = vls_protocol::msgs::GetHeartbeat {};
use vls_protocol::msgs::SerBolt;
let req = crate::pb::HsmRequest {
// Notice that the request_counter starts at 1000, to
// avoid collisions.
request_id: 0,
signer_state: state,
raw: msg.as_vec(),
requests: vec![], // No pending requests yet, nothing to authorize.
context: None,
};

if let Err(e) = tx.send(Ok(req)).await {
log::warn!("Failed to send heartbeat message to signer: {}", e);
}
}

loop {
let mut req = match stream.next().await {
Err(e) => {
Expand Down
5 changes: 4 additions & 1 deletion libs/gl-signerproxy/src/hsmproxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,10 @@ async fn grpc_connect() -> Result<GrpcClient, Error> {

pub async fn run() -> Result<(), Error> {
let args: Vec<String> = std::env::args().collect();
let request_counter = Arc::new(atomic::AtomicUsize::new(0));

// Start the counter at 1000 so we can inject some message before
// real requests if we want to.
let request_counter = Arc::new(atomic::AtomicUsize::new(1000));
if args.len() == 2 && args[1] == "--version" {
println!("{}", version());
return Ok(());
Expand Down

0 comments on commit 941c47a

Please sign in to comment.