v0.1.0-pre.011
This commit is contained in:
@@ -3,20 +3,20 @@
|
||||
|
||||
//! Exact SPL Memo v1, v3 and v4 dispatch for the common decode pipeline.
|
||||
|
||||
const MEMO_SURFACES: &[crate::DecoderSurface] = &[
|
||||
crate::DecoderSurface {
|
||||
const MEMO_SURFACES: &[crate::DcApiDecoderSurface] = &[
|
||||
crate::DcApiDecoderSurface {
|
||||
program_id: kb_program_ids::SPL_MEMO_V1_PROGRAM_ID,
|
||||
surface_code: crate::SPL_MEMO_V1_SURFACE_CODE,
|
||||
surface_code: crate::DC_SPL_MEMO_V1_SURFACE_CODE,
|
||||
priority: 100,
|
||||
},
|
||||
crate::DecoderSurface {
|
||||
crate::DcApiDecoderSurface {
|
||||
program_id: kb_program_ids::SPL_MEMO_V3_PROGRAM_ID,
|
||||
surface_code: crate::SPL_MEMO_V3_SURFACE_CODE,
|
||||
surface_code: crate::DC_SPL_MEMO_V3_SURFACE_CODE,
|
||||
priority: 100,
|
||||
},
|
||||
crate::DecoderSurface {
|
||||
crate::DcApiDecoderSurface {
|
||||
program_id: kb_program_ids::SPL_MEMO_V4_PROGRAM_ID,
|
||||
surface_code: crate::SPL_MEMO_V4_SURFACE_CODE,
|
||||
surface_code: crate::DC_SPL_MEMO_V4_SURFACE_CODE,
|
||||
priority: 100,
|
||||
},
|
||||
];
|
||||
@@ -29,9 +29,9 @@ const LEGACY_PROGRAM_IDS: &[&str] = &[
|
||||
|
||||
/// Exact decoder for the three registered SPL Memo generations.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct SplMemoDecoder;
|
||||
pub struct DcSplMemoDecoder;
|
||||
|
||||
impl crate::ProtocolDecoder for crate::SplMemoDecoder {
|
||||
impl crate::DcApiProtocolDecoder for crate::DcSplMemoDecoder {
|
||||
fn decoder_name(&self) -> &'static str {
|
||||
return "kb_decoder_spl_memo";
|
||||
}
|
||||
@@ -46,42 +46,42 @@ impl crate::ProtocolDecoder for crate::SplMemoDecoder {
|
||||
|
||||
fn supports_observation(
|
||||
&self,
|
||||
observation: &crate::ProgramObservation,
|
||||
) -> crate::DecoderSupport {
|
||||
if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) {
|
||||
return crate::DecoderSupport::Yes;
|
||||
observation: &crate::MdProgramObservation,
|
||||
) -> crate::DcApiDecoderSupport {
|
||||
if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) {
|
||||
return crate::DcApiDecoderSupport::Yes;
|
||||
}
|
||||
return crate::DecoderSupport::No;
|
||||
return crate::DcApiDecoderSupport::No;
|
||||
}
|
||||
|
||||
fn decode_observation(
|
||||
&self,
|
||||
_observation: &crate::ProgramObservation,
|
||||
) -> kb_core::Result<std::vec::Vec<crate::DecodedProtocolEvent>> {
|
||||
_observation: &crate::MdProgramObservation,
|
||||
) -> kb_core::Result<std::vec::Vec<crate::MdDecodedProtocolEvent>> {
|
||||
return std::result::Result::Ok(std::vec::Vec::new());
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::InstructionDecoder for crate::SplMemoDecoder {
|
||||
fn identity(&self) -> crate::DecoderIdentity {
|
||||
return crate::DecoderIdentity {
|
||||
impl crate::DcApiInstructionDecoder for crate::DcSplMemoDecoder {
|
||||
fn identity(&self) -> crate::DcApiDecoderIdentity {
|
||||
return crate::DcApiDecoderIdentity {
|
||||
name: "spl_memo".to_string(),
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
};
|
||||
}
|
||||
|
||||
fn surfaces(&self) -> &'static [crate::DecoderSurface] {
|
||||
fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] {
|
||||
return MEMO_SURFACES;
|
||||
}
|
||||
|
||||
fn coverage(&self) -> std::vec::Vec<crate::DecoderCoverageDeclaration> {
|
||||
fn coverage(&self) -> std::vec::Vec<crate::DcApiDecoderCoverageDeclaration> {
|
||||
return MEMO_SURFACES
|
||||
.iter()
|
||||
.map(|surface| {
|
||||
return crate::DecoderCoverageDeclaration {
|
||||
return crate::DcApiDecoderCoverageDeclaration {
|
||||
program_id: surface.program_id.to_string(),
|
||||
surface_code: std::option::Option::Some(surface.surface_code.to_string()),
|
||||
entry_kind: crate::DecoderCoverageEntryKind::Instruction,
|
||||
entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction,
|
||||
entry_code: "add_memo".to_string(),
|
||||
discriminator_hex: std::option::Option::None,
|
||||
historical: surface.program_id != kb_program_ids::SPL_MEMO_V4_PROGRAM_ID,
|
||||
@@ -90,15 +90,18 @@ impl crate::InstructionDecoder for crate::SplMemoDecoder {
|
||||
.collect();
|
||||
}
|
||||
|
||||
fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition {
|
||||
fn recognize(
|
||||
&self,
|
||||
input: &crate::MdCoreInstructionReplayInput,
|
||||
) -> crate::DcApiDecoderRecognition {
|
||||
let surface = MEMO_SURFACES
|
||||
.iter()
|
||||
.find(|surface| return surface.program_id == input.program_id);
|
||||
let surface = match surface {
|
||||
std::option::Option::Some(value) => value,
|
||||
std::option::Option::None => return crate::DecoderRecognition::incompatible(),
|
||||
std::option::Option::None => return crate::DcApiDecoderRecognition::incompatible(),
|
||||
};
|
||||
return crate::DecoderRecognition::compatible(
|
||||
return crate::DcApiDecoderRecognition::compatible(
|
||||
true,
|
||||
surface.priority,
|
||||
std::option::Option::Some(surface.surface_code.to_string()),
|
||||
@@ -107,17 +110,21 @@ impl crate::InstructionDecoder for crate::SplMemoDecoder {
|
||||
);
|
||||
}
|
||||
|
||||
fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult {
|
||||
fn decode(
|
||||
&self,
|
||||
input: &crate::MdCoreInstructionReplayInput,
|
||||
) -> crate::DcApiDecoderExecutionResult {
|
||||
if !LEGACY_PROGRAM_IDS.contains(&input.program_id.as_str()) {
|
||||
return crate::DecoderExecutionResult::unsupported(std::option::Option::None);
|
||||
return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None);
|
||||
}
|
||||
let result = crate::spl_memo_decode(input);
|
||||
let result = crate::decoder_spl_memo_decode(input);
|
||||
if matches!(
|
||||
result.status,
|
||||
crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported
|
||||
crate::DcApiDecoderOutcomeStatus::Failed
|
||||
| crate::DcApiDecoderOutcomeStatus::Unsupported
|
||||
) {
|
||||
tracing::error!(
|
||||
target: crate::SPL_MEMO_TRACING_TARGET,
|
||||
target: crate::DC_SPL_MEMO_TRACING_TARGET,
|
||||
action = "decode_failure",
|
||||
signature = %input.signature,
|
||||
slot = input.slot,
|
||||
@@ -134,7 +141,7 @@ impl crate::InstructionDecoder for crate::SplMemoDecoder {
|
||||
);
|
||||
}
|
||||
tracing::debug!(
|
||||
target: crate::SPL_MEMO_TRACING_TARGET,
|
||||
target: crate::DC_SPL_MEMO_TRACING_TARGET,
|
||||
action = "decode",
|
||||
signature = %input.signature,
|
||||
instruction_path = %input.instruction_path,
|
||||
@@ -159,8 +166,8 @@ mod tests {
|
||||
keys: serde_json::Value,
|
||||
failed: bool,
|
||||
path: &str,
|
||||
) -> crate::CoreInstructionReplayInput {
|
||||
let result = crate::CoreInstructionReplayInput::new(
|
||||
) -> crate::MdCoreInstructionReplayInput {
|
||||
let result = crate::MdCoreInstructionReplayInput::new(
|
||||
format!("signature:{path}"),
|
||||
"signature",
|
||||
42,
|
||||
@@ -198,13 +205,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn exact_support_and_interface_ids_cover_all_generations() {
|
||||
let decoder = crate::SplMemoDecoder;
|
||||
let decoder = crate::DcSplMemoDecoder;
|
||||
assert_eq!(spl_memo_interface::v1::ID.to_string(), kb_program_ids::SPL_MEMO_V1_PROGRAM_ID);
|
||||
assert_eq!(spl_memo_interface::v3::ID.to_string(), kb_program_ids::SPL_MEMO_V3_PROGRAM_ID);
|
||||
assert_eq!(spl_memo_interface::v4::ID.to_string(), kb_program_ids::SPL_MEMO_V4_PROGRAM_ID);
|
||||
assert_eq!(crate::InstructionDecoder::surfaces(&decoder).len(), 3);
|
||||
assert_eq!(crate::DcApiInstructionDecoder::surfaces(&decoder).len(), 3);
|
||||
assert!(
|
||||
crate::InstructionDecoder::coverage(&decoder)
|
||||
crate::DcApiInstructionDecoder::coverage(&decoder)
|
||||
.iter()
|
||||
.all(|entry| return entry.entry_code == "add_memo")
|
||||
);
|
||||
@@ -225,8 +232,8 @@ mod tests {
|
||||
false,
|
||||
path,
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded);
|
||||
assert_eq!(
|
||||
result.observations[0].payload_json["payloadLengthBytes"],
|
||||
serde_json::json!(payload.len())
|
||||
@@ -235,9 +242,9 @@ mod tests {
|
||||
assert_eq!(
|
||||
result.observations[0].event.source_kind,
|
||||
if path.contains('/') {
|
||||
crate::EventSourceKind::InnerInstruction
|
||||
crate::MdEventSourceKind::InnerInstruction
|
||||
} else {
|
||||
crate::EventSourceKind::Instruction
|
||||
crate::MdEventSourceKind::Instruction
|
||||
}
|
||||
);
|
||||
}
|
||||
@@ -254,7 +261,7 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let v1_result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &v1);
|
||||
let v1_result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &v1);
|
||||
assert_eq!(v1_result.observations[0].event.event_name.0, "add_memo");
|
||||
assert_eq!(
|
||||
v1_result.observations[0].payload_json["signerValidation"]["status"],
|
||||
@@ -264,7 +271,7 @@ mod tests {
|
||||
[kb_program_ids::SPL_MEMO_V3_PROGRAM_ID, kb_program_ids::SPL_MEMO_V4_PROGRAM_ID]
|
||||
{
|
||||
let input = input(program_id, b"signed", accounts.clone(), keys.clone(), false, "0");
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input);
|
||||
assert_eq!(result.observations[0].event.event_name.0, "invalid_memo_attempt");
|
||||
assert_eq!(
|
||||
result.observations[0].payload_json["signerValidation"]["status"],
|
||||
@@ -284,7 +291,8 @@ mod tests {
|
||||
true,
|
||||
"0",
|
||||
);
|
||||
let invalid_result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &invalid);
|
||||
let invalid_result =
|
||||
crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &invalid);
|
||||
assert_eq!(invalid_result.observations[0].event.event_name.0, "invalid_memo_attempt");
|
||||
assert_eq!(
|
||||
invalid_result.observations[0].payload_json["utf8Validation"]["status"],
|
||||
@@ -300,7 +308,7 @@ mod tests {
|
||||
"0",
|
||||
);
|
||||
let failed_result =
|
||||
crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &valid_failed);
|
||||
crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &valid_failed);
|
||||
assert_eq!(failed_result.observations[0].event.event_name.0, "memo_intent");
|
||||
assert!(!failed_result.observations[0].observation_committed);
|
||||
assert_eq!(
|
||||
@@ -322,7 +330,7 @@ mod tests {
|
||||
]);
|
||||
let input =
|
||||
input(kb_program_ids::SPL_MEMO_V4_PROGRAM_ID, b"ordered", accounts, keys, false, "0");
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input);
|
||||
assert_eq!(result.observations[0].payload_json["accounts"][0]["pubkey"], "first");
|
||||
assert_eq!(result.observations[0].payload_json["accounts"][0]["writable"], true);
|
||||
assert_eq!(result.observations[0].payload_json["accounts"][2]["pubkey"], "first");
|
||||
@@ -346,7 +354,7 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input);
|
||||
assert_eq!(
|
||||
result.observations[0].payload_json["payloadSha256"],
|
||||
"ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"
|
||||
@@ -355,7 +363,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn payload_bound_accepts_limit_and_rejects_oversize_and_malformed_base64() {
|
||||
let at_limit = std::vec![b'x'; crate::SPL_MEMO_MAX_PAYLOAD_BYTES];
|
||||
let at_limit = std::vec![b'x'; crate::DC_SPL_MEMO_MAX_PAYLOAD_BYTES];
|
||||
let cinput = input(
|
||||
kb_program_ids::SPL_MEMO_V4_PROGRAM_ID,
|
||||
at_limit.as_slice(),
|
||||
@@ -364,9 +372,9 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &cinput);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded);
|
||||
let oversize = std::vec![b'x'; crate::SPL_MEMO_MAX_PAYLOAD_BYTES + 1];
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &cinput);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded);
|
||||
let oversize = std::vec![b'x'; crate::DC_SPL_MEMO_MAX_PAYLOAD_BYTES + 1];
|
||||
let cinput = input(
|
||||
kb_program_ids::SPL_MEMO_V4_PROGRAM_ID,
|
||||
oversize.as_slice(),
|
||||
@@ -375,8 +383,8 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &cinput);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &cinput);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed);
|
||||
let mut malformed = input(
|
||||
kb_program_ids::SPL_MEMO_V4_PROGRAM_ID,
|
||||
b"valid",
|
||||
@@ -387,8 +395,8 @@ mod tests {
|
||||
);
|
||||
malformed.instruction_payload_json =
|
||||
std::option::Option::Some(serde_json::json!({"dataBase64":"%%%"}));
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &malformed);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &malformed);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed);
|
||||
assert!(result.observations.is_empty());
|
||||
}
|
||||
|
||||
@@ -402,10 +410,11 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let recognition = crate::InstructionDecoder::recognize(&crate::SplMemoDecoder, &input);
|
||||
let recognition =
|
||||
crate::DcApiInstructionDecoder::recognize(&crate::DcSplMemoDecoder, &input);
|
||||
assert!(!recognition.compatible);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplMemoDecoder, &input);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Unsupported);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplMemoDecoder, &input);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Unsupported);
|
||||
assert!(result.observations.is_empty());
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user