v0.1.0-pre.011
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
|
||||
//! Stable compliance-audit projections for committed native bytecode mutations and execution profiles.
|
||||
|
||||
const ACCEPTED_FAMILIES: &[crate::EventFamily] = &[crate::EventFamily::Audit];
|
||||
const ACCEPTED_FAMILIES: &[crate::MdEventFamily] = &[crate::MdEventFamily::Audit];
|
||||
const COMPUTE_BUDGET_SURFACE: &str = "solana_native_compute_budget";
|
||||
const COMPUTE_BUDGET_ENTRIES: &[&str] = &[
|
||||
"request_units_deprecated",
|
||||
@@ -47,9 +47,9 @@ impl ProjectionKind {
|
||||
|
||||
/// Stable compliance-audit materializer for native bytecode mutations and execution profiles.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct ComplianceAuditMaterializer;
|
||||
pub struct MtComplianceAuditMaterializer;
|
||||
|
||||
impl crate::Materializer for crate::ComplianceAuditMaterializer {
|
||||
impl crate::MtMaterializer for crate::MtComplianceAuditMaterializer {
|
||||
fn materializer_name(&self) -> &'static str {
|
||||
return "kb_materializer_compliance_audit";
|
||||
}
|
||||
@@ -58,36 +58,36 @@ impl crate::Materializer for crate::ComplianceAuditMaterializer {
|
||||
return env!("CARGO_PKG_VERSION");
|
||||
}
|
||||
|
||||
fn accepts_event(&self, event: &crate::DecodedProtocolEvent) -> bool {
|
||||
return event.event_family == crate::EventFamily::Audit
|
||||
fn accepts_event(&self, event: &crate::MdDecodedProtocolEvent) -> bool {
|
||||
return event.event_family == crate::MdEventFamily::Audit
|
||||
&& projection(event.surface_code.0.as_str(), event.event_name.0.as_str()).is_some();
|
||||
}
|
||||
|
||||
fn materialize_event(
|
||||
&self,
|
||||
event: &crate::DecodedProtocolEvent,
|
||||
) -> kb_core::Result<std::vec::Vec<crate::MaterializedEvent>> {
|
||||
if !crate::Materializer::accepts_event(self, event) {
|
||||
event: &crate::MdDecodedProtocolEvent,
|
||||
) -> kb_core::Result<std::vec::Vec<crate::MdMaterializedEvent>> {
|
||||
if !crate::MtMaterializer::accepts_event(self, event) {
|
||||
return std::result::Result::Ok(std::vec::Vec::new());
|
||||
}
|
||||
return std::result::Result::Ok(std::vec::Vec::new());
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::EventMaterializer for crate::ComplianceAuditMaterializer {
|
||||
fn identity(&self) -> crate::MaterializerIdentity {
|
||||
return crate::MaterializerIdentity {
|
||||
impl crate::MtApiEventMaterializer for crate::MtComplianceAuditMaterializer {
|
||||
fn identity(&self) -> crate::MtApiMaterializerIdentity {
|
||||
return crate::MtApiMaterializerIdentity {
|
||||
name: "solana_native_compliance_audit".to_string(),
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
};
|
||||
}
|
||||
|
||||
fn accepted_families(&self) -> &'static [crate::EventFamily] {
|
||||
fn accepted_families(&self) -> &'static [crate::MdEventFamily] {
|
||||
return ACCEPTED_FAMILIES;
|
||||
}
|
||||
|
||||
fn accepts_observation(&self, observation: &crate::DecodedObservation) -> bool {
|
||||
return observation.event.event_family == crate::EventFamily::Audit
|
||||
fn accepts_observation(&self, observation: &crate::DcApiDecodedObservation) -> bool {
|
||||
return observation.event.event_family == crate::MdEventFamily::Audit
|
||||
&& projection(
|
||||
observation.event.surface_code.0.as_str(),
|
||||
observation.event.event_name.0.as_str(),
|
||||
@@ -97,15 +97,15 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer {
|
||||
|
||||
fn transaction_policy(
|
||||
&self,
|
||||
_family: crate::EventFamily,
|
||||
) -> crate::MaterializationTransactionPolicy {
|
||||
return crate::MaterializationTransactionPolicy::SuccessfulOrFailedAudit;
|
||||
_family: crate::MdEventFamily,
|
||||
) -> crate::MtApiMaterializationTransactionPolicy {
|
||||
return crate::MtApiMaterializationTransactionPolicy::SuccessfulOrFailedAudit;
|
||||
}
|
||||
|
||||
fn materialize(
|
||||
&self,
|
||||
observation: &crate::DecodedObservation,
|
||||
) -> crate::MaterializerExecutionResult {
|
||||
observation: &crate::DcApiDecodedObservation,
|
||||
) -> crate::MtApiMaterializerExecutionResult {
|
||||
let projection = match projection(
|
||||
observation.event.surface_code.0.as_str(),
|
||||
observation.event.event_name.0.as_str(),
|
||||
@@ -113,24 +113,24 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => {
|
||||
tracing::debug!(
|
||||
target: crate::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET,
|
||||
target: crate::MT_COMPLIANCE_AUDIT_TRACING_TARGET,
|
||||
action = "materialize_compliance_audit",
|
||||
surface_code = %observation.event.surface_code.0.as_str(),
|
||||
entry_code = %observation.event.event_name.0.as_str(),
|
||||
accepted = false,
|
||||
"ignore observation outside supported native compliance-audit projections"
|
||||
);
|
||||
return crate::MaterializerExecutionResult::ignored();
|
||||
return crate::MtApiMaterializerExecutionResult::ignored();
|
||||
},
|
||||
};
|
||||
if observation.event.event_family != crate::EventFamily::Audit {
|
||||
return crate::MaterializerExecutionResult::ignored();
|
||||
if observation.event.event_family != crate::MdEventFamily::Audit {
|
||||
return crate::MtApiMaterializerExecutionResult::ignored();
|
||||
}
|
||||
if projection != ProjectionKind::ComputeBudgetProfile
|
||||
&& (observation.transaction_failed || !observation.observation_committed)
|
||||
{
|
||||
tracing::debug!(
|
||||
target: crate::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET,
|
||||
target: crate::MT_COMPLIANCE_AUDIT_TRACING_TARGET,
|
||||
action = "materialize_compliance_audit",
|
||||
surface_code = %observation.event.surface_code.0.as_str(),
|
||||
entry_code = %observation.event.event_name.0.as_str(),
|
||||
@@ -138,7 +138,7 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer {
|
||||
transaction_failed = observation.transaction_failed,
|
||||
"refuse uncommitted native bytecode mutation observation"
|
||||
);
|
||||
return crate::MaterializerExecutionResult::refused(
|
||||
return crate::MtApiMaterializerExecutionResult::refused(
|
||||
"failed_transaction_compliance_audit_refused",
|
||||
"failed or uncommitted native observations cannot create committed bytecode mutation outputs",
|
||||
);
|
||||
@@ -157,10 +157,10 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer {
|
||||
if projection == ProjectionKind::ComputeBudgetProfile {
|
||||
return materialize_compute_budget_profile(observation, parameters, operation);
|
||||
}
|
||||
let output = crate::MaterializedOutput {
|
||||
let output = crate::MtApiMaterializedOutput {
|
||||
output_key: projection
|
||||
.output_key(observation.event.surface_code.0.as_str(), operation.as_str()),
|
||||
family: crate::MaterializedEventFamily::ComplianceAudit,
|
||||
family: crate::MdMaterializedEventFamily::ComplianceAudit,
|
||||
payload_json: serde_json::json!({
|
||||
"projectionVersion": 1,
|
||||
"projectionSemantics": "committed_instruction_compliance_audit_event",
|
||||
@@ -178,7 +178,7 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer {
|
||||
}),
|
||||
};
|
||||
tracing::debug!(
|
||||
target: crate::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET,
|
||||
target: crate::MT_COMPLIANCE_AUDIT_TRACING_TARGET,
|
||||
action = "materialize_compliance_audit",
|
||||
surface_code = %observation.event.surface_code.0.as_str(),
|
||||
entry_code = %observation.event.event_name.0.as_str(),
|
||||
@@ -186,8 +186,8 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer {
|
||||
output_count = 1_usize,
|
||||
"materialize committed native bytecode mutation observation"
|
||||
);
|
||||
return crate::MaterializerExecutionResult {
|
||||
status: crate::MaterializerOutcomeStatus::Inserted,
|
||||
return crate::MtApiMaterializerExecutionResult {
|
||||
status: crate::MtApiMaterializerOutcomeStatus::Inserted,
|
||||
outputs: std::vec![output],
|
||||
diagnostics: std::vec::Vec::new(),
|
||||
};
|
||||
@@ -195,17 +195,17 @@ impl crate::EventMaterializer for crate::ComplianceAuditMaterializer {
|
||||
}
|
||||
|
||||
fn materialize_compute_budget_profile(
|
||||
observation: &crate::DecodedObservation,
|
||||
observation: &crate::DcApiDecodedObservation,
|
||||
parameters: serde_json::Value,
|
||||
operation: std::string::String,
|
||||
) -> crate::MaterializerExecutionResult {
|
||||
) -> crate::MtApiMaterializerExecutionResult {
|
||||
let profile = parameters.get("transactionProfile").cloned().unwrap_or(serde_json::Value::Null);
|
||||
if !compute_budget_profile_emits(&profile) {
|
||||
return crate::MaterializerExecutionResult::ignored();
|
||||
return crate::MtApiMaterializerExecutionResult::ignored();
|
||||
}
|
||||
let output = crate::MaterializedOutput {
|
||||
let output = crate::MtApiMaterializedOutput {
|
||||
output_key: "transaction_compute_budget_profile:0".to_string(),
|
||||
family: crate::MaterializedEventFamily::ComplianceAudit,
|
||||
family: crate::MdMaterializedEventFamily::ComplianceAudit,
|
||||
payload_json: serde_json::json!({
|
||||
"projectionVersion": 1,
|
||||
"projectionSemantics": "transaction_compute_budget_profile",
|
||||
@@ -225,7 +225,7 @@ fn materialize_compute_budget_profile(
|
||||
}),
|
||||
};
|
||||
tracing::debug!(
|
||||
target: crate::MATERIALIZER_COMPLIANCE_AUDIT_TRACING_TARGET,
|
||||
target: crate::MT_COMPLIANCE_AUDIT_TRACING_TARGET,
|
||||
action = "materialize_compute_budget_profile",
|
||||
surface_code = %observation.event.surface_code.0.as_str(),
|
||||
entry_code = %observation.event.event_name.0.as_str(),
|
||||
@@ -233,8 +233,8 @@ fn materialize_compute_budget_profile(
|
||||
transaction_failed = observation.transaction_failed,
|
||||
"materialize native Compute Budget transaction profile"
|
||||
);
|
||||
return crate::MaterializerExecutionResult {
|
||||
status: crate::MaterializerOutcomeStatus::Inserted,
|
||||
return crate::MtApiMaterializerExecutionResult {
|
||||
status: crate::MtApiMaterializerOutcomeStatus::Inserted,
|
||||
outputs: std::vec![output],
|
||||
diagnostics: std::vec::Vec::new(),
|
||||
};
|
||||
@@ -349,21 +349,21 @@ mod tests {
|
||||
transaction_failed: bool,
|
||||
accounts: serde_json::Value,
|
||||
parameters: serde_json::Value,
|
||||
) -> crate::DecodedObservation {
|
||||
return crate::DecodedObservation {
|
||||
) -> crate::DcApiDecodedObservation {
|
||||
return crate::DcApiDecodedObservation {
|
||||
event_key: format!("{entry_code}:0"),
|
||||
event: crate::DecodedProtocolEvent {
|
||||
signature: crate::Signature("signature".to_string()),
|
||||
slot: crate::Slot(42),
|
||||
instruction_path: crate::InstructionPath("0".to_string()),
|
||||
program_id: crate::ProgramId("program-id".to_string()),
|
||||
protocol_code: crate::ProtocolCode("solana_native".to_string()),
|
||||
surface_code: crate::SurfaceCode(surface_code.to_string()),
|
||||
event_code: crate::EventCode(format!("{surface_code}.{entry_code}")),
|
||||
event_name: crate::EventName(entry_code.to_string()),
|
||||
event_family: crate::EventFamily::Audit,
|
||||
source_kind: crate::EventSourceKind::Instruction,
|
||||
confidence: crate::DecoderConfidence::ManualExact,
|
||||
event: crate::MdDecodedProtocolEvent {
|
||||
signature: crate::MdSignature("signature".to_string()),
|
||||
slot: crate::MdSlot(42),
|
||||
instruction_path: crate::MdInstructionPath("0".to_string()),
|
||||
program_id: crate::MdProgramId("program-id".to_string()),
|
||||
protocol_code: crate::MdProtocolCode("solana_native".to_string()),
|
||||
surface_code: crate::MdSurfaceCode(surface_code.to_string()),
|
||||
event_code: crate::MdEventCode(format!("{surface_code}.{entry_code}")),
|
||||
event_name: crate::MdEventName(entry_code.to_string()),
|
||||
event_family: crate::MdEventFamily::Audit,
|
||||
source_kind: crate::MdEventSourceKind::Instruction,
|
||||
confidence: crate::MdDecoderConfidence::ManualExact,
|
||||
},
|
||||
payload_json: serde_json::json!({"accounts": accounts, "parameters": parameters}),
|
||||
transaction_failed,
|
||||
@@ -373,9 +373,9 @@ mod tests {
|
||||
std::option::Option::None
|
||||
},
|
||||
observation_committed: !transaction_failed,
|
||||
proof: crate::DecoderProof {
|
||||
kind: crate::DecoderProofKind::Manual,
|
||||
confidence: crate::DecoderConfidence::ManualExact,
|
||||
proof: crate::DcApiDecoderProof {
|
||||
kind: crate::DcApiDecoderProofKind::Manual,
|
||||
confidence: crate::MdDecoderConfidence::ManualExact,
|
||||
evidence: std::vec!["fixture".to_string()],
|
||||
},
|
||||
};
|
||||
@@ -387,7 +387,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn loader_write_variants_create_bounded_code_audits() {
|
||||
let materializer = crate::ComplianceAuditMaterializer;
|
||||
let materializer = crate::MtComplianceAuditMaterializer;
|
||||
for (surface, target_role, authority_role) in [
|
||||
(super::BPF_LOADER_DEPRECATED_SURFACE, "program_account", "missing"),
|
||||
(super::BPF_LOADER_SURFACE, "program_account", "missing"),
|
||||
@@ -409,9 +409,9 @@ mod tests {
|
||||
"bytesPrefixHex": "0102",
|
||||
}),
|
||||
);
|
||||
let result = crate::EventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted);
|
||||
assert_eq!(result.outputs[0].family, crate::MaterializedEventFamily::ComplianceAudit);
|
||||
let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted);
|
||||
assert_eq!(result.outputs[0].family, crate::MdMaterializedEventFamily::ComplianceAudit);
|
||||
assert_eq!(result.outputs[0].payload_json["projection"]["targetAccount"], "target111");
|
||||
assert_eq!(result.outputs[0].payload_json["projection"]["bytesSha256"], "abc");
|
||||
assert_eq!(
|
||||
@@ -423,7 +423,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn loader_v4_copy_preserves_source_and_bounded_ranges() {
|
||||
let materializer = crate::ComplianceAuditMaterializer;
|
||||
let materializer = crate::MtComplianceAuditMaterializer;
|
||||
let observation = observation(
|
||||
super::LOADER_V4_SURFACE,
|
||||
"copy",
|
||||
@@ -435,7 +435,7 @@ mod tests {
|
||||
]),
|
||||
serde_json::json!({"destinationOffset": 8, "sourceOffset": 4, "length": 16}),
|
||||
);
|
||||
let result = crate::EventMaterializer::materialize(&materializer, &observation);
|
||||
let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(
|
||||
result.outputs[0].output_key,
|
||||
"program_loader_code:solana_native_loader_v4:copy:0"
|
||||
@@ -449,7 +449,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn compute_budget_profile_is_emitted_only_by_profile_emitter() {
|
||||
let materializer = crate::ComplianceAuditMaterializer;
|
||||
let materializer = crate::MtComplianceAuditMaterializer;
|
||||
let emitter = observation(
|
||||
super::COMPUTE_BUDGET_SURFACE,
|
||||
"set_compute_unit_limit",
|
||||
@@ -469,10 +469,10 @@ mod tests {
|
||||
}
|
||||
}),
|
||||
);
|
||||
let emitted = crate::EventMaterializer::materialize(&materializer, &emitter);
|
||||
assert_eq!(emitted.status, crate::MaterializerOutcomeStatus::Inserted);
|
||||
let emitted = crate::MtApiEventMaterializer::materialize(&materializer, &emitter);
|
||||
assert_eq!(emitted.status, crate::MtApiMaterializerOutcomeStatus::Inserted);
|
||||
assert_eq!(emitted.outputs[0].output_key, "transaction_compute_budget_profile:0");
|
||||
assert_eq!(emitted.outputs[0].family, crate::MaterializedEventFamily::ComplianceAudit);
|
||||
assert_eq!(emitted.outputs[0].family, crate::MdMaterializedEventFamily::ComplianceAudit);
|
||||
assert_eq!(emitted.outputs[0].payload_json["profile"]["computeBudgetInstructionCount"], 2);
|
||||
let non_emitter = observation(
|
||||
super::COMPUTE_BUDGET_SURFACE,
|
||||
@@ -486,13 +486,13 @@ mod tests {
|
||||
}
|
||||
}),
|
||||
);
|
||||
let ignored = crate::EventMaterializer::materialize(&materializer, &non_emitter);
|
||||
assert_eq!(ignored.status, crate::MaterializerOutcomeStatus::Ignored);
|
||||
let ignored = crate::MtApiEventMaterializer::materialize(&materializer, &non_emitter);
|
||||
assert_eq!(ignored.status, crate::MtApiMaterializerOutcomeStatus::Ignored);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_compute_budget_profile_remains_audit_materializable() {
|
||||
let materializer = crate::ComplianceAuditMaterializer;
|
||||
let materializer = crate::MtComplianceAuditMaterializer;
|
||||
let observation = observation(
|
||||
super::COMPUTE_BUDGET_SURFACE,
|
||||
"set_compute_unit_price",
|
||||
@@ -506,14 +506,14 @@ mod tests {
|
||||
}
|
||||
}),
|
||||
);
|
||||
let result = crate::EventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(result.status, crate::MaterializerOutcomeStatus::Inserted);
|
||||
let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Inserted);
|
||||
assert_eq!(result.outputs[0].payload_json["transactionSucceeded"], false);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn failed_code_mutation_is_refused() {
|
||||
let materializer = crate::ComplianceAuditMaterializer;
|
||||
let materializer = crate::MtComplianceAuditMaterializer;
|
||||
let observation = observation(
|
||||
super::LOADER_V4_SURFACE,
|
||||
"write",
|
||||
@@ -521,14 +521,14 @@ mod tests {
|
||||
serde_json::json!([account("program_account", "target111")]),
|
||||
serde_json::json!({"offset": 0, "byteLength": 1, "bytesSha256": "abc"}),
|
||||
);
|
||||
let result = crate::EventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(result.status, crate::MaterializerOutcomeStatus::Refused);
|
||||
let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Refused);
|
||||
assert!(result.outputs.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unrelated_audit_observation_is_ignored() {
|
||||
let materializer = crate::ComplianceAuditMaterializer;
|
||||
let materializer = crate::MtComplianceAuditMaterializer;
|
||||
let observation = observation(
|
||||
"other_surface",
|
||||
"write",
|
||||
@@ -536,13 +536,13 @@ mod tests {
|
||||
serde_json::json!([]),
|
||||
serde_json::json!({}),
|
||||
);
|
||||
let result = crate::EventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(result.status, crate::MaterializerOutcomeStatus::Ignored);
|
||||
let result = crate::MtApiEventMaterializer::materialize(&materializer, &observation);
|
||||
assert_eq!(result.status, crate::MtApiMaterializerOutcomeStatus::Ignored);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn output_serialization_is_deterministic() {
|
||||
let materializer = crate::ComplianceAuditMaterializer;
|
||||
let materializer = crate::MtComplianceAuditMaterializer;
|
||||
let observation = observation(
|
||||
super::BPF_LOADER_UPGRADEABLE_SURFACE,
|
||||
"write",
|
||||
@@ -558,8 +558,8 @@ mod tests {
|
||||
"bytesPrefixHex": "0102",
|
||||
}),
|
||||
);
|
||||
let first = crate::EventMaterializer::materialize(&materializer, &observation);
|
||||
let second = crate::EventMaterializer::materialize(&materializer, &observation);
|
||||
let first = crate::MtApiEventMaterializer::materialize(&materializer, &observation);
|
||||
let second = crate::MtApiEventMaterializer::materialize(&materializer, &observation);
|
||||
let first_json = match serde_json::to_string(&first) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => {
|
||||
|
||||
Reference in New Issue
Block a user