v0.1.0-pre.011
This commit is contained in:
@@ -3,9 +3,9 @@
|
||||
|
||||
//! Exact classic SPL Token dispatch for the common decode pipeline.
|
||||
|
||||
const TOKEN_SURFACES: &[crate::DecoderSurface] = &[crate::DecoderSurface {
|
||||
const TOKEN_SURFACES: &[crate::DcApiDecoderSurface] = &[crate::DcApiDecoderSurface {
|
||||
program_id: kb_program_ids::SPL_TOKEN_PROGRAM_ID,
|
||||
surface_code: crate::SPL_TOKEN_SURFACE_CODE,
|
||||
surface_code: crate::DC_SPL_TOKEN_SURFACE_CODE,
|
||||
priority: 100,
|
||||
}];
|
||||
|
||||
@@ -13,9 +13,9 @@ const PROGRAM_IDS: &[&str] = &[kb_program_ids::SPL_TOKEN_PROGRAM_ID];
|
||||
|
||||
/// Exact decoder for the classic SPL Token program.
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct SplTokenDecoder;
|
||||
pub struct DcSplTokenDecoder;
|
||||
|
||||
impl crate::ProtocolDecoder for crate::SplTokenDecoder {
|
||||
impl crate::DcApiProtocolDecoder for crate::DcSplTokenDecoder {
|
||||
fn decoder_name(&self) -> &'static str {
|
||||
return "kb_decoder_spl_token";
|
||||
}
|
||||
@@ -30,45 +30,45 @@ impl crate::ProtocolDecoder for crate::SplTokenDecoder {
|
||||
|
||||
fn supports_observation(
|
||||
&self,
|
||||
observation: &crate::ProgramObservation,
|
||||
) -> crate::DecoderSupport {
|
||||
return if crate::ProtocolDecoder::handles_program_id(self, &observation.program_id) {
|
||||
crate::DecoderSupport::Yes
|
||||
observation: &crate::MdProgramObservation,
|
||||
) -> crate::DcApiDecoderSupport {
|
||||
return if crate::DcApiProtocolDecoder::handles_program_id(self, &observation.program_id) {
|
||||
crate::DcApiDecoderSupport::Yes
|
||||
} else {
|
||||
crate::DecoderSupport::No
|
||||
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::SplTokenDecoder {
|
||||
fn identity(&self) -> crate::DecoderIdentity {
|
||||
return crate::DecoderIdentity {
|
||||
impl crate::DcApiInstructionDecoder for crate::DcSplTokenDecoder {
|
||||
fn identity(&self) -> crate::DcApiDecoderIdentity {
|
||||
return crate::DcApiDecoderIdentity {
|
||||
name: "spl_token".to_string(),
|
||||
version: env!("CARGO_PKG_VERSION").to_string(),
|
||||
};
|
||||
}
|
||||
|
||||
fn surfaces(&self) -> &'static [crate::DecoderSurface] {
|
||||
fn surfaces(&self) -> &'static [crate::DcApiDecoderSurface] {
|
||||
return TOKEN_SURFACES;
|
||||
}
|
||||
|
||||
fn coverage(&self) -> std::vec::Vec<crate::DecoderCoverageDeclaration> {
|
||||
return crate::SPL_TOKEN_INSTRUCTION_ENTRIES
|
||||
fn coverage(&self) -> std::vec::Vec<crate::DcApiDecoderCoverageDeclaration> {
|
||||
return crate::DC_SPL_TOKEN_INSTRUCTION_ENTRIES
|
||||
.iter()
|
||||
.map(|(tag, code, historical)| {
|
||||
return crate::DecoderCoverageDeclaration {
|
||||
return crate::DcApiDecoderCoverageDeclaration {
|
||||
program_id: kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string(),
|
||||
surface_code: std::option::Option::Some(
|
||||
crate::SPL_TOKEN_SURFACE_CODE.to_string(),
|
||||
crate::DC_SPL_TOKEN_SURFACE_CODE.to_string(),
|
||||
),
|
||||
entry_kind: crate::DecoderCoverageEntryKind::Instruction,
|
||||
entry_kind: crate::DcApiDecoderCoverageEntryKind::Instruction,
|
||||
entry_code: (*code).to_string(),
|
||||
discriminator_hex: std::option::Option::Some(format!("{tag:02x}")),
|
||||
historical: *historical,
|
||||
@@ -77,32 +77,39 @@ impl crate::InstructionDecoder for crate::SplTokenDecoder {
|
||||
.collect();
|
||||
}
|
||||
|
||||
fn recognize(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderRecognition {
|
||||
fn recognize(
|
||||
&self,
|
||||
input: &crate::MdCoreInstructionReplayInput,
|
||||
) -> crate::DcApiDecoderRecognition {
|
||||
if input.program_id != kb_program_ids::SPL_TOKEN_PROGRAM_ID {
|
||||
return crate::DecoderRecognition::incompatible();
|
||||
return crate::DcApiDecoderRecognition::incompatible();
|
||||
}
|
||||
let tag = crate::spl_token_payload_tag(input);
|
||||
let entry = tag.and_then(crate::spl_token_entry_for_tag);
|
||||
return crate::DecoderRecognition::compatible(
|
||||
let tag = crate::decoder_spl_token_payload_tag(input);
|
||||
let entry = tag.and_then(crate::decoder_spl_token_entry_for_tag);
|
||||
return crate::DcApiDecoderRecognition::compatible(
|
||||
entry.is_some(),
|
||||
100,
|
||||
std::option::Option::Some(crate::SPL_TOKEN_SURFACE_CODE.to_string()),
|
||||
std::option::Option::Some(crate::DC_SPL_TOKEN_SURFACE_CODE.to_string()),
|
||||
entry.map(|(_, code, _)| return code.to_string()),
|
||||
tag.map(|value| return format!("{value:02x}")),
|
||||
);
|
||||
}
|
||||
|
||||
fn decode(&self, input: &crate::CoreInstructionReplayInput) -> crate::DecoderExecutionResult {
|
||||
fn decode(
|
||||
&self,
|
||||
input: &crate::MdCoreInstructionReplayInput,
|
||||
) -> crate::DcApiDecoderExecutionResult {
|
||||
if input.program_id != kb_program_ids::SPL_TOKEN_PROGRAM_ID {
|
||||
return crate::DecoderExecutionResult::unsupported(std::option::Option::None);
|
||||
return crate::DcApiDecoderExecutionResult::unsupported(std::option::Option::None);
|
||||
}
|
||||
let result = crate::spl_token_decode(input);
|
||||
let result = crate::decoder_spl_token_decode(input);
|
||||
if matches!(
|
||||
result.status,
|
||||
crate::DecoderOutcomeStatus::Failed | crate::DecoderOutcomeStatus::Unsupported
|
||||
crate::DcApiDecoderOutcomeStatus::Failed
|
||||
| crate::DcApiDecoderOutcomeStatus::Unsupported
|
||||
) {
|
||||
tracing::error!(
|
||||
target: crate::SPL_TOKEN_TRACING_TARGET,
|
||||
target: crate::DC_SPL_TOKEN_TRACING_TARGET,
|
||||
action = "decode_failure",
|
||||
signature = %input.signature,
|
||||
slot = input.slot,
|
||||
@@ -118,7 +125,7 @@ impl crate::InstructionDecoder for crate::SplTokenDecoder {
|
||||
);
|
||||
}
|
||||
tracing::debug!(
|
||||
target: crate::SPL_TOKEN_TRACING_TARGET,
|
||||
target: crate::DC_SPL_TOKEN_TRACING_TARGET,
|
||||
action = "decode",
|
||||
signature = %input.signature,
|
||||
instruction_path = %input.instruction_path,
|
||||
@@ -142,8 +149,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,
|
||||
@@ -219,21 +226,21 @@ mod tests {
|
||||
#[test]
|
||||
fn exact_support_program_id_and_interface_match() {
|
||||
assert_eq!(spl_token_interface::ID.to_string(), kb_program_ids::SPL_TOKEN_PROGRAM_ID);
|
||||
let decoder = crate::SplTokenDecoder;
|
||||
assert_eq!(crate::InstructionDecoder::surfaces(&decoder).len(), 1);
|
||||
let observation = crate::ProgramObservation {
|
||||
signature: crate::Signature("signature".to_string()),
|
||||
slot: crate::Slot(1),
|
||||
instruction_path: crate::InstructionPath("0".to_string()),
|
||||
program_id: crate::ProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()),
|
||||
let decoder = crate::DcSplTokenDecoder;
|
||||
assert_eq!(crate::DcApiInstructionDecoder::surfaces(&decoder).len(), 1);
|
||||
let observation = crate::MdProgramObservation {
|
||||
signature: crate::MdSignature("signature".to_string()),
|
||||
slot: crate::MdSlot(1),
|
||||
instruction_path: crate::MdInstructionPath("0".to_string()),
|
||||
program_id: crate::MdProgramId(kb_program_ids::SPL_TOKEN_PROGRAM_ID.to_string()),
|
||||
discriminator_8: std::option::Option::None,
|
||||
data_len: 1,
|
||||
accounts_len: 0,
|
||||
failed: false,
|
||||
};
|
||||
assert_eq!(
|
||||
crate::ProtocolDecoder::supports_observation(&decoder, &observation),
|
||||
crate::DecoderSupport::Yes
|
||||
crate::DcApiProtocolDecoder::supports_observation(&decoder, &observation),
|
||||
crate::DcApiDecoderSupport::Yes
|
||||
);
|
||||
}
|
||||
|
||||
@@ -257,12 +264,12 @@ mod tests {
|
||||
);
|
||||
})
|
||||
.collect::<std::vec::Vec<_>>();
|
||||
let compiled_entries = crate::SPL_TOKEN_INSTRUCTION_ENTRIES
|
||||
let compiled_entries = crate::DC_SPL_TOKEN_INSTRUCTION_ENTRIES
|
||||
.iter()
|
||||
.map(|(tag, code, _)| return (*tag, *code))
|
||||
.collect::<std::vec::Vec<_>>();
|
||||
assert_eq!(matrix_entries, compiled_entries);
|
||||
assert_eq!(crate::InstructionDecoder::coverage(&crate::SplTokenDecoder).len(), 28);
|
||||
assert_eq!(crate::DcApiInstructionDecoder::coverage(&crate::DcSplTokenDecoder).len(), 28);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -324,7 +331,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn every_published_tag_decodes_and_matches_official_unpack() {
|
||||
for (tag, code, _) in crate::SPL_TOKEN_INSTRUCTION_ENTRIES {
|
||||
for (tag, code, _) in crate::DC_SPL_TOKEN_INSTRUCTION_ENTRIES {
|
||||
let wire = minimal_wire(*tag);
|
||||
let official = spl_token_interface::instruction::TokenInstruction::unpack(&wire);
|
||||
assert!(official.is_ok(), "official unpack rejected tag {tag}");
|
||||
@@ -336,8 +343,8 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &input);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &input);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded);
|
||||
assert_eq!(result.recognized_entry_code.as_deref(), std::option::Option::Some(*code));
|
||||
}
|
||||
}
|
||||
@@ -364,8 +371,8 @@ mod tests {
|
||||
true,
|
||||
"2/1",
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &input);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &input);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded);
|
||||
assert!(!result.observations[0].observation_committed);
|
||||
assert_eq!(
|
||||
result.observations[0].payload_json["parameters"]["amountRaw"],
|
||||
@@ -374,7 +381,7 @@ mod tests {
|
||||
assert_eq!(result.observations[0].payload_json["inference"]["mintInvented"], false);
|
||||
assert_eq!(
|
||||
result.observations[0].event.source_kind,
|
||||
crate::EventSourceKind::InnerInstruction
|
||||
crate::MdEventSourceKind::InnerInstruction
|
||||
);
|
||||
}
|
||||
|
||||
@@ -390,8 +397,9 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let suffix_result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &suffix);
|
||||
assert_eq!(suffix_result.status, crate::DecoderOutcomeStatus::Decoded);
|
||||
let suffix_result =
|
||||
crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &suffix);
|
||||
assert_eq!(suffix_result.status, crate::DcApiDecoderOutcomeStatus::Decoded);
|
||||
assert_eq!(suffix_result.observations[0].payload_json["wire"]["suffixLengthBytes"], 2);
|
||||
for wire in [std::vec::Vec::new(), std::vec![3, 1], std::vec![24, 0xff], std::vec![255]] {
|
||||
let input = input(
|
||||
@@ -402,8 +410,8 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &input);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Failed);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &input);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Failed);
|
||||
assert!(result.observations.is_empty());
|
||||
}
|
||||
let unknown = input(
|
||||
@@ -414,8 +422,8 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &unknown);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Unsupported);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &unknown);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Unsupported);
|
||||
assert!(!result.diagnostics.is_empty());
|
||||
}
|
||||
|
||||
@@ -432,8 +440,8 @@ mod tests {
|
||||
false,
|
||||
"4/2",
|
||||
);
|
||||
let result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &cinput);
|
||||
assert_eq!(result.status, crate::DecoderOutcomeStatus::Decoded);
|
||||
let result = crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &cinput);
|
||||
assert_eq!(result.status, crate::DcApiDecoderOutcomeStatus::Decoded);
|
||||
assert_eq!(result.observations.len(), 3);
|
||||
assert_eq!(result.observations[1].event.instruction_path.0, "4/2/batch/0");
|
||||
assert_eq!(result.observations[2].event.instruction_path.0, "4/2/batch/1");
|
||||
@@ -446,8 +454,9 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let nested_result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &nested);
|
||||
assert_eq!(nested_result.status, crate::DecoderOutcomeStatus::Failed);
|
||||
let nested_result =
|
||||
crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &nested);
|
||||
assert_eq!(nested_result.status, crate::DcApiDecoderOutcomeStatus::Failed);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -471,7 +480,8 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let simple_result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &simple);
|
||||
let simple_result =
|
||||
crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &simple);
|
||||
assert_eq!(simple_result.observations[0].payload_json["authority"]["form"], "single");
|
||||
let mut multisig_accounts = simple_accounts.as_array().cloned().unwrap_or_default();
|
||||
multisig_accounts
|
||||
@@ -490,7 +500,8 @@ mod tests {
|
||||
false,
|
||||
"0",
|
||||
);
|
||||
let multisig_result = crate::InstructionDecoder::decode(&crate::SplTokenDecoder, &multisig);
|
||||
let multisig_result =
|
||||
crate::DcApiInstructionDecoder::decode(&crate::DcSplTokenDecoder, &multisig);
|
||||
assert_eq!(multisig_result.observations[0].payload_json["authority"]["form"], "multisig");
|
||||
assert_eq!(
|
||||
multisig_result.observations[0].payload_json["authority"]["statefulMultisigValidation"],
|
||||
|
||||
Reference in New Issue
Block a user