Skip to content

Commit fbbc8ee

Browse files
committed
chore: address event-log v2 review nits
- tell the operator how to recover when the runtime event version conflicts: the value is fixed for the boot, so a new app-compose `event_log_version` needs a CVM restart - drop the two private `is_v1` helpers in favour of the existing `EventLogVersion::is_v1`, which AppCompose already uses - document why the runtime event lock waits without a timeout - explain in the Go SDK that a zero `Version` means V1, since the field is omitted from the wire format for V1 events
1 parent cf52392 commit fbbc8ee

4 files changed

Lines changed: 27 additions & 14 deletions

File tree

dstack/cc-eventlog/src/runtime_events.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,11 @@ pub struct RuntimeEvent {
3333
#[serde(with = "base64")]
3434
pub payload: Vec<u8>,
3535
/// Event log version
36-
#[serde(default, skip_serializing_if = "is_v1")]
36+
#[serde(default, skip_serializing_if = "EventLogVersion::is_v1")]
3737
#[codec(skip)]
3838
pub version: EventLogVersion,
3939
}
4040

41-
fn is_v1(version: &EventLogVersion) -> bool {
42-
matches!(version, EventLogVersion::V1)
43-
}
44-
4541
impl RuntimeEvent {
4642
pub fn new(event: String, payload: Vec<u8>, version: EventLogVersion) -> Self {
4743
Self {

dstack/cc-eventlog/src/tdx.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub struct TdxEvent {
4949
/// Skipped by scale codec for binary compat with legacy attestations
5050
/// (which only ever contain V1 events).
5151
/// Serde skips serialization when V1 so existing JSON outputs stay clean.
52-
#[serde(default, skip_serializing_if = "is_v1")]
52+
#[serde(default, skip_serializing_if = "EventLogVersion::is_v1")]
5353
#[codec(skip)]
5454
pub version: EventLogVersion,
5555

@@ -64,10 +64,6 @@ pub struct TdxEvent {
6464
pub preimage: Option<String>,
6565
}
6666

67-
fn is_v1(v: &EventLogVersion) -> bool {
68-
matches!(v, EventLogVersion::V1)
69-
}
70-
7167
impl TdxEvent {
7268
pub fn new(imr: u32, event_type: u32, event: String, event_payload: Vec<u8>) -> Self {
7369
Self {

dstack/dstack-attest/src/lib.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ const RUNTIME_EVENT_DIR: &str = "/run/log/dstack";
2323
const RUNTIME_EVENT_VERSION_FILE: &str = "/run/log/dstack/runtime_event_version";
2424
const RUNTIME_EVENT_LOCK_FILE: &str = "/run/log/dstack/runtime_event.lock";
2525

26+
/// Acquire the system-wide runtime event lock, blocking until it is available.
27+
///
28+
/// The wait is deliberately unbounded. The lock serializes the event-log append
29+
/// with the measurement-register extension, and that ordering is what makes
30+
/// replay reproduce the quoted register value. Proceeding after a timeout would
31+
/// break the invariant, and failing after one would abort a boot that is merely
32+
/// slow, so waiting is the only safe option. A holder that dies releases the
33+
/// lock automatically (flock is dropped when the file descriptor closes), which
34+
/// leaves a live but wedged holder as the sole way to block emission.
2635
fn runtime_event_lock() -> anyhow::Result<fs_err::File> {
2736
fs_err::create_dir_all(RUNTIME_EVENT_DIR)
2837
.context("failed to create runtime event log directory")?;
@@ -60,7 +69,9 @@ fn set_runtime_event_version_file(
6069
Ok(configured) => {
6170
anyhow::ensure!(
6271
configured.trim() == value,
63-
"runtime event version already set to {}",
72+
"runtime event version is already set to {} for this boot and cannot be \
73+
changed to {value}; the setting is fixed when system setup runs, so restart \
74+
the CVM to apply a new app-compose `event_log_version`",
6475
configured.trim()
6576
);
6677
Ok(())
@@ -105,7 +116,12 @@ mod runtime_event_version_tests {
105116
set_runtime_event_version_file(&path, EventLogVersion::V1).unwrap();
106117
set_runtime_event_version_file(&path, EventLogVersion::V1).unwrap();
107118
let err = set_runtime_event_version_file(&path, EventLogVersion::V2).unwrap_err();
108-
assert!(err.to_string().contains("already set to 1"));
119+
let message = err.to_string();
120+
assert!(message.contains("already set to 1"), "{message}");
121+
assert!(
122+
message.contains("restart the CVM"),
123+
"the conflict error must tell the operator how to apply a new version: {message}"
124+
);
109125
let _ = fs_err::remove_file(path);
110126
}
111127

sdk/go/dstack/client.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,13 @@ type EventLog struct {
130130
Digest string `json:"digest"`
131131
Event string `json:"event"`
132132
EventPayload string `json:"event_payload"`
133-
Version int `json:"version,omitempty"`
134-
Preimage string `json:"preimage,omitempty"`
133+
// Runtime event log version. The field is omitted from the wire format for
134+
// version 1, so a zero value means V1 rather than "unset"; treat 0 and 1
135+
// alike. Only dstack runtime events carry a version.
136+
Version int `json:"version,omitempty"`
137+
// Hex-encoded digest pre-image, present on V2 runtime events. When set,
138+
// sha384(hex_decode(Preimage)) equals Digest.
139+
Preimage string `json:"preimage,omitempty"`
135140
}
136141

137142
// Represents the TCB information

0 commit comments

Comments
 (0)