Append client version info to user graffiti by default (#9313)

Closes issue #9287


  


Co-Authored-By: Tan Chee Keong <tanck@sigmaprime.io>

Co-Authored-By: chonghe <44791194+chong-he@users.noreply.github.com>

Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
This commit is contained in:
chonghe
2026-06-15 14:03:13 +08:00
committed by GitHub
parent 378f01670b
commit d8e406b6ac
10 changed files with 203 additions and 41 deletions

View File

@@ -62,7 +62,7 @@ impl GraffitiSettings {
validator_graffiti
.map(|graffiti| Self::Specified {
graffiti,
policy: policy.unwrap_or(GraffitiPolicy::PreserveUserGraffiti),
policy: policy.unwrap_or_default(),
})
.unwrap_or(Self::Unspecified)
}
@@ -480,9 +480,9 @@ mod tests {
// for the case of empty append_graffiti_string, i.e., user-specified graffiti is 30-32 characters
graffiti.to_string()
} else {
// There is a space between the client version info and user graffiti
// There is a space between the user graffiti and client version info
// as defined in calculate_graffiti function in engine_api.rs
format!("{} {}", append_graffiti_string, graffiti)
format!("{} {}", graffiti, append_graffiti_string)
};
let expected_graffiti_prefix_bytes = expected_graffiti_string.as_bytes();

View File

@@ -832,16 +832,16 @@ impl ClientVersionV1 {
// 12 characters for append_graffiti_full, plus one character for spacing
// that leaves user specified graffiti to be 32-12-1 = 19 characters max, i.e., <20
if graffiti_length < 20 {
format!("{} {}", append_graffiti_full, graffiti_str)
format!("{} {}", graffiti_str, append_graffiti_full)
// user-specified graffiti is between 20-23 characters
} else if (20..24).contains(&graffiti_length) {
format!("{} {}", append_graffiti_one_byte, graffiti_str)
format!("{} {}", graffiti_str, append_graffiti_one_byte)
// user-specified graffiti is between 24-27 characters
} else if (24..28).contains(&graffiti_length) {
format!("{} {}", append_graffiti_no_commit, graffiti_str)
format!("{} {}", graffiti_str, append_graffiti_no_commit)
// user-specified graffiti is between 28-29 characters
} else if (28..30).contains(&graffiti_length) {
format!("{} {}", append_graffiti_only_el, graffiti_str)
format!("{} {}", graffiti_str, append_graffiti_only_el)
// if user-specified graffiti is between 30-32 characters, append nothing
} else {
return graffiti;

View File

@@ -7967,8 +7967,8 @@ impl ApiTester {
let graffiti = Some(Graffiti::from([0; GRAFFITI_BYTES_LEN]));
let builder_boost_factor = None;
// Default case where GraffitiPolicy is None
let default_path = self
// When GraffitiPolicy is None
let no_graffiti_policy_path = self
.client
.get_validator_blocks_v3_path(
slot,
@@ -7981,13 +7981,30 @@ impl ApiTester {
.await
.unwrap();
// Default case where GraffitiPolicy is AppendClientVersions
let default_path = self
.client
.get_validator_blocks_v3_path(
slot,
&randao_reveal,
graffiti.as_ref(),
SkipRandaoVerification::Yes,
builder_boost_factor,
Some(GraffitiPolicy::AppendClientVersions),
)
.await
.unwrap();
let query_none_path = no_graffiti_policy_path.query().unwrap_or("");
let query_default_path = default_path.query().unwrap_or("");
// When GraffitiPolicy is None, the HTTP API query path should not contain "graffiti_policy"
// When GraffitiPolicy is AppendClientVersions (default GraffitiPolicy), the HTTP API query path should not contain "graffiti_policy"
assert!(
!query_default_path.contains("graffiti_policy"),
"URL should not contain graffiti_policy parameter (same as PreserveUserGraffiti). URL is: {}",
query_default_path
);
// The HTTP API query path for GraffiliPolicy is None should be the same as the default (GraffitiPolicy = AppendClientVersions)
assert_eq!(query_none_path, query_default_path);
let preserve_path = self
.client
@@ -8003,36 +8020,86 @@ impl ApiTester {
.unwrap();
let query_preserve_path = preserve_path.query().unwrap_or("");
// When GraffitiPolicy is set to PreserveUserGraffiti, the HTTP API query path should not contain "graffiti_policy"
// When GraffitiPolicy is set to PreserveUserGraffiti, the HTTP API query path should contain "graffiti_policy"
assert!(
!query_preserve_path.contains("graffiti_policy"),
query_preserve_path.contains("graffiti_policy"),
"URL should not contain graffiti_policy parameter when using PreserveUserGraffiti. URL is: {}",
query_preserve_path
);
// The HTTP API query path for PreserveUserGraffiti should be the same as the default
assert_eq!(query_default_path, query_preserve_path);
self
}
let append_path = self
async fn get_validator_blocks_v4_path_graffiti_policy(self) -> Self {
let slot = self.chain.slot().unwrap();
let epoch = self.chain.epoch().unwrap();
let (_, randao_reveal) = self.get_test_randao(slot, epoch).await;
let graffiti = Some(Graffiti::from([0; GRAFFITI_BYTES_LEN]));
let builder_boost_factor = None;
// When GraffitiPolicy is None
let no_graffiti_policy_path = self
.client
.get_validator_blocks_v3_path(
.get_validator_blocks_v4_path(
slot,
&randao_reveal,
graffiti.as_ref(),
SkipRandaoVerification::No,
SkipRandaoVerification::Yes,
None,
builder_boost_factor,
None,
)
.await
.unwrap();
// Default case where GraffitiPolicy is AppendClientVersions
let default_path = self
.client
.get_validator_blocks_v4_path(
slot,
&randao_reveal,
graffiti.as_ref(),
SkipRandaoVerification::Yes,
None,
builder_boost_factor,
Some(GraffitiPolicy::AppendClientVersions),
)
.await
.unwrap();
let query_append_path = append_path.query().unwrap_or("");
// When GraffitiPolicy is AppendClientVersions, the HTTP API query path should contain "graffiti_policy"
let query_none_path = no_graffiti_policy_path.query().unwrap_or("");
let query_default_path = default_path.query().unwrap_or("");
// When GraffitiPolicy is AppendClientVersions (default GraffitiPolicy), the HTTP API query path should not contain "graffiti_policy"
assert!(
query_append_path.contains("graffiti_policy"),
"URL should contain graffiti_policy=AppendClientVersions parameter. URL is: {}",
query_append_path
!query_default_path.contains("graffiti_policy"),
"URL should not contain graffiti_policy parameter (same as PreserveUserGraffiti). URL is: {}",
query_default_path
);
// The HTTP API query path for GraffiliPolicy is None should be the same as the default (GraffitiPolicy = AppendClientVersions)
assert_eq!(query_none_path, query_default_path);
let preserve_path = self
.client
.get_validator_blocks_v4_path(
slot,
&randao_reveal,
graffiti.as_ref(),
SkipRandaoVerification::Yes,
None,
builder_boost_factor,
Some(GraffitiPolicy::PreserveUserGraffiti),
)
.await
.unwrap();
let query_preserve_path = preserve_path.query().unwrap_or("");
// When GraffitiPolicy is set to PreserveUserGraffiti, the HTTP API query path should contain "graffiti_policy"
assert!(
query_preserve_path.contains("graffiti_policy"),
"URL should not contain graffiti_policy parameter when using PreserveUserGraffiti. URL is: {}",
query_preserve_path
);
self
}
}
@@ -9531,10 +9598,12 @@ async fn get_beacon_rewards_attestations_fulu() {
}
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
async fn get_validator_blocks_v3_http_api_path() {
async fn get_validator_blocks_http_api_path() {
ApiTester::new()
.await
.get_validator_blocks_v3_path_graffiti_policy()
.await
.get_validator_blocks_v4_path_graffiti_policy()
.await;
}