v0.1.0-pre.061
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/lib.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(unreachable_pub)]
|
||||
@@ -12,9 +12,9 @@ mod environment;
|
||||
mod solana_ata_execution;
|
||||
mod solana_execution;
|
||||
mod solana_memo_execution;
|
||||
mod solana_token2022_devnet_execution;
|
||||
mod solana_token2022_devnet_scenarios;
|
||||
mod solana_token2022_validation;
|
||||
mod solana_token_2022_devnet_execution;
|
||||
mod solana_token_2022_devnet_scenarios;
|
||||
mod solana_token_2022_validation;
|
||||
mod solana_token_execution;
|
||||
mod solana_token_lifecycle;
|
||||
|
||||
@@ -58,6 +58,44 @@ pub use self::solana_memo_execution::DevnetMemoExecutionRequest;
|
||||
pub use self::solana_memo_execution::DevnetMemoExecutionSummary;
|
||||
/// Executes one SPL Memo v4 Devnet simulation or explicitly authorized submission.
|
||||
pub use self::solana_memo_execution::execute_devnet_memo;
|
||||
/// Complete request for one Devnet Token-2022 execution.
|
||||
pub use self::solana_token_2022_devnet_execution::DevnetSplToken2022ExecutionRequest;
|
||||
/// Complete result of one Devnet Token-2022 execution.
|
||||
pub use self::solana_token_2022_devnet_execution::DevnetSplToken2022ExecutionSummary;
|
||||
/// Executes one Devnet Token-2022 simulation or authorized submission.
|
||||
pub use self::solana_token_2022_devnet_execution::execute_devnet_spl_token_2022;
|
||||
/// Simulates one Devnet Token-2022 operation after stateful preflight.
|
||||
pub use self::solana_token_2022_devnet_execution::simulate_devnet_spl_token_2022;
|
||||
/// Stable category of one independent Devnet validation scenario.
|
||||
pub use self::solana_token_2022_devnet_scenarios::DevnetSplValidationFamily;
|
||||
/// Current implementation status of one Devnet validation scenario.
|
||||
pub use self::solana_token_2022_devnet_scenarios::DevnetSplValidationImplementationStatus;
|
||||
/// One independent Devnet validation scenario exposed to applications.
|
||||
pub use self::solana_token_2022_devnet_scenarios::DevnetSplValidationScenario;
|
||||
/// Returns the complete ordered Devnet scenario inventory.
|
||||
pub use self::solana_token_2022_devnet_scenarios::devnet_spl_validation_scenarios;
|
||||
/// Maximum number of evidence records accepted in one validation report.
|
||||
pub use self::solana_token_2022_validation::MAX_TOKEN_2022_VALIDATION_EVIDENCE;
|
||||
/// Required validation environment for one Token-2022 scenario.
|
||||
pub use self::solana_token_2022_validation::Token2022ValidationEnvironment;
|
||||
/// One bounded proof attached to a Token-2022 validation scenario.
|
||||
pub use self::solana_token_2022_validation::Token2022ValidationEvidence;
|
||||
/// Machine-readable Token-2022 validation matrix.
|
||||
pub use self::solana_token_2022_validation::Token2022ValidationMatrix;
|
||||
/// One scenario declared by the canonical validation matrix.
|
||||
pub use self::solana_token_2022_validation::Token2022ValidationMatrixScenario;
|
||||
/// Complete bounded Token-2022 validation report.
|
||||
pub use self::solana_token_2022_validation::Token2022ValidationReport;
|
||||
/// One declared Token-2022 validation scenario and its observed evidence.
|
||||
pub use self::solana_token_2022_validation::Token2022ValidationScenario;
|
||||
/// Exact status of one Token-2022 validation scenario.
|
||||
pub use self::solana_token_2022_validation::Token2022ValidationStatus;
|
||||
/// Loads and validates the canonical Token-2022 validation matrix.
|
||||
pub use self::solana_token_2022_validation::load_token_2022_validation_matrix;
|
||||
/// Validates one Token-2022 validation matrix.
|
||||
pub use self::solana_token_2022_validation::validate_token_2022_validation_matrix;
|
||||
/// Validates one bounded Token-2022 milestone report.
|
||||
pub use self::solana_token_2022_validation::validate_token_2022_validation_report;
|
||||
/// Complete request for one Devnet classic SPL Token execution.
|
||||
pub use self::solana_token_execution::DevnetSplTokenExecutionRequest;
|
||||
/// Complete result of one Devnet classic SPL Token execution.
|
||||
@@ -90,44 +128,6 @@ pub use self::solana_token_lifecycle::DevnetSplTokenLifecycleSummary;
|
||||
pub use self::solana_token_lifecycle::execute_devnet_spl_token_lifecycle;
|
||||
/// Prepares raw accounts for one controlled Devnet SPL Token lifecycle.
|
||||
pub use self::solana_token_lifecycle::prepare_devnet_spl_token_lifecycle_accounts;
|
||||
/// Complete request for one Devnet Token-2022 execution.
|
||||
pub use self::solana_token2022_devnet_execution::DevnetSplToken2022ExecutionRequest;
|
||||
/// Complete result of one Devnet Token-2022 execution.
|
||||
pub use self::solana_token2022_devnet_execution::DevnetSplToken2022ExecutionSummary;
|
||||
/// Executes one Devnet Token-2022 simulation or authorized submission.
|
||||
pub use self::solana_token2022_devnet_execution::execute_devnet_spl_token2022;
|
||||
/// Simulates one Devnet Token-2022 operation after stateful preflight.
|
||||
pub use self::solana_token2022_devnet_execution::simulate_devnet_spl_token2022;
|
||||
/// Stable category of one independent Devnet validation scenario.
|
||||
pub use self::solana_token2022_devnet_scenarios::DevnetSplValidationFamily;
|
||||
/// Current implementation status of one Devnet validation scenario.
|
||||
pub use self::solana_token2022_devnet_scenarios::DevnetSplValidationImplementationStatus;
|
||||
/// One independent Devnet validation scenario exposed to applications.
|
||||
pub use self::solana_token2022_devnet_scenarios::DevnetSplValidationScenario;
|
||||
/// Returns the complete ordered Devnet scenario inventory.
|
||||
pub use self::solana_token2022_devnet_scenarios::devnet_spl_validation_scenarios;
|
||||
/// Maximum number of evidence records accepted in one validation report.
|
||||
pub use self::solana_token2022_validation::MAX_TOKEN2022_VALIDATION_EVIDENCE;
|
||||
/// Required validation environment for one Token-2022 scenario.
|
||||
pub use self::solana_token2022_validation::Token2022ValidationEnvironment;
|
||||
/// One bounded proof attached to a Token-2022 validation scenario.
|
||||
pub use self::solana_token2022_validation::Token2022ValidationEvidence;
|
||||
/// Machine-readable Token-2022 validation matrix.
|
||||
pub use self::solana_token2022_validation::Token2022ValidationMatrix;
|
||||
/// One scenario declared by the canonical validation matrix.
|
||||
pub use self::solana_token2022_validation::Token2022ValidationMatrixScenario;
|
||||
/// Complete bounded Token-2022 validation report.
|
||||
pub use self::solana_token2022_validation::Token2022ValidationReport;
|
||||
/// One declared Token-2022 validation scenario and its observed evidence.
|
||||
pub use self::solana_token2022_validation::Token2022ValidationScenario;
|
||||
/// Exact status of one Token-2022 validation scenario.
|
||||
pub use self::solana_token2022_validation::Token2022ValidationStatus;
|
||||
/// Loads and validates the canonical Token-2022 validation matrix.
|
||||
pub use self::solana_token2022_validation::load_token2022_validation_matrix;
|
||||
/// Validates one Token-2022 validation matrix.
|
||||
pub use self::solana_token2022_validation::validate_token2022_validation_matrix;
|
||||
/// Validates one bounded Token-2022 milestone report.
|
||||
pub use self::solana_token2022_validation::validate_token2022_validation_report;
|
||||
|
||||
/// Canonical tracing target for demo pipeline scenarios.
|
||||
pub(crate) use self::constants::TRACING_TARGET;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_ata_execution.rs
|
||||
// version: 6
|
||||
// version: 7
|
||||
|
||||
//! Devnet ATA execution with stateful and canonical post-validation.
|
||||
|
||||
@@ -433,8 +433,10 @@ where
|
||||
},
|
||||
};
|
||||
let idempotent = second_replay.failed_inputs == 0
|
||||
&& second_replay.processing_error_inputs == 0
|
||||
&& second_replay.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialized_outputs == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
});
|
||||
@@ -885,11 +887,13 @@ where
|
||||
|
||||
fn decode_completed(summary: &kb_pipeline::DecodeReplaySummary) -> bool {
|
||||
return summary.failed_inputs == 0
|
||||
&& summary.processing_error_inputs == 0
|
||||
&& summary.unmatched == 0
|
||||
&& !summary.cancelled
|
||||
&& summary.completed >= 1
|
||||
&& summary.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.unsupported == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
})
|
||||
@@ -1182,8 +1186,10 @@ mod tests {
|
||||
}));
|
||||
assert!(summary.idempotence_replay.as_ref().is_some_and(|value| {
|
||||
return value.failed_inputs == 0
|
||||
&& value.processing_error_inputs == 0
|
||||
&& value.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialized_outputs == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_execution.rs
|
||||
// version: 7
|
||||
// version: 8
|
||||
|
||||
//! Devnet Solana execution orchestration with canonical post-validation.
|
||||
|
||||
@@ -767,11 +767,14 @@ where
|
||||
},
|
||||
};
|
||||
let processors_clean = decode.processors.iter().all(|processor| {
|
||||
return processor.failed == 0 && processor.unsupported == 0;
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.unsupported == 0;
|
||||
});
|
||||
let decoded_observations =
|
||||
decode.processors.iter().map(|processor| return processor.decoded).sum::<u64>();
|
||||
let decode_replayed = decode.failed_inputs == 0
|
||||
&& decode.processing_error_inputs == 0
|
||||
&& decode.unmatched == 0
|
||||
&& !decode.cancelled
|
||||
&& decode.completed >= 1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_memo_execution.rs
|
||||
// version: 2
|
||||
// version: 3
|
||||
|
||||
//! Devnet SPL Memo v4 execution with canonical post-validation.
|
||||
|
||||
@@ -499,8 +499,10 @@ where
|
||||
},
|
||||
};
|
||||
let idempotent = second_replay.failed_inputs == 0
|
||||
&& second_replay.processing_error_inputs == 0
|
||||
&& second_replay.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialized_outputs == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
});
|
||||
@@ -736,11 +738,13 @@ where
|
||||
|
||||
fn decode_completed(summary: &kb_pipeline::DecodeReplaySummary) -> bool {
|
||||
return summary.failed_inputs == 0
|
||||
&& summary.processing_error_inputs == 0
|
||||
&& summary.unmatched == 0
|
||||
&& !summary.cancelled
|
||||
&& summary.completed >= 1
|
||||
&& summary.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.unsupported == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
})
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_token2022_devnet_execution.rs
|
||||
// version: 2
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_token_2022_devnet_execution.rs
|
||||
// version: 4
|
||||
|
||||
//! Devnet Token-2022 execution with stateful and canonical post-validation.
|
||||
|
||||
@@ -112,7 +112,7 @@ struct PreparedToken2022Execution {
|
||||
}
|
||||
|
||||
/// Simulates one Devnet Token-2022 operation after stateful preflight.
|
||||
pub async fn simulate_devnet_spl_token2022<O>(
|
||||
pub async fn simulate_devnet_spl_token_2022<O>(
|
||||
http_pool: &kb_onchain_transport::HttpEndpointPool,
|
||||
profile: &kb_config::ProfileConfig,
|
||||
workspace_root: &std::path::Path,
|
||||
@@ -124,7 +124,7 @@ where
|
||||
{
|
||||
if request.submit {
|
||||
return std::result::Result::Err(kb_core::Error::config(
|
||||
"simulate_devnet_spl_token2022 requires submit=false",
|
||||
"simulate_devnet_spl_token_2022 requires submit=false",
|
||||
));
|
||||
}
|
||||
let prepared =
|
||||
@@ -137,7 +137,7 @@ where
|
||||
|
||||
/// Executes one Devnet Token-2022 simulation or authorized submission.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub async fn execute_devnet_spl_token2022<S, O>(
|
||||
pub async fn execute_devnet_spl_token_2022<S, O>(
|
||||
http_pool: &kb_onchain_transport::HttpEndpointPool,
|
||||
store: &S,
|
||||
profile: &kb_config::ProfileConfig,
|
||||
@@ -335,7 +335,7 @@ where
|
||||
&signature,
|
||||
false,
|
||||
request.force_post_validation_replay,
|
||||
&[kb_program_ids::SPL_TOKEN2022_PROGRAM_ID],
|
||||
&[kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID],
|
||||
decoders,
|
||||
materializers,
|
||||
observer,
|
||||
@@ -372,7 +372,7 @@ where
|
||||
};
|
||||
summary.materializations = rows
|
||||
.into_iter()
|
||||
.filter(|row| return row.source_decoder_name == "spl_token2022")
|
||||
.filter(|row| return row.source_decoder_name == "spl_token_2022")
|
||||
.collect();
|
||||
diagnostic.materialized =
|
||||
!summary.plan.policy.post_execution_validation.materialization_required
|
||||
@@ -382,7 +382,7 @@ where
|
||||
&signature,
|
||||
true,
|
||||
request.force_post_validation_replay,
|
||||
&[kb_program_ids::SPL_TOKEN2022_PROGRAM_ID],
|
||||
&[kb_program_ids::SPL_TOKEN_2022_PROGRAM_ID],
|
||||
decoders,
|
||||
materializers,
|
||||
observer,
|
||||
@@ -399,8 +399,10 @@ where
|
||||
},
|
||||
};
|
||||
let idempotent = second_replay.failed_inputs == 0
|
||||
&& second_replay.processing_error_inputs == 0
|
||||
&& second_replay.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialized_outputs == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
});
|
||||
@@ -463,7 +465,7 @@ where
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let readiness =
|
||||
match kb_pipeline::inspect_token2022_preflight(http_pool, &preflight_request).await {
|
||||
match kb_pipeline::inspect_token_2022_preflight(http_pool, &preflight_request).await {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
@@ -562,7 +564,7 @@ where
|
||||
crate::emit(
|
||||
observer,
|
||||
crate::SolanaExecutionProgressLevel::Info,
|
||||
"spl_token2022_simulation",
|
||||
"spl_token_2022_simulation",
|
||||
format!("simulating exact Token-2022 message {}", unsigned.message_hash()),
|
||||
std::option::Option::None,
|
||||
);
|
||||
@@ -623,7 +625,7 @@ fn preflight_request(
|
||||
kb_lib::ExSplToken2022Operation::Instruction { value } => value.as_ref(),
|
||||
kb_lib::ExSplToken2022Operation::Batch { instructions: _ } => {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"execution_spl_token2022_batch_not_supported",
|
||||
"execution_spl_token_2022_batch_not_supported",
|
||||
"Devnet Token-2022 validation scenarios require one non-batch operation",
|
||||
));
|
||||
},
|
||||
@@ -749,7 +751,7 @@ fn preflight_request(
|
||||
},
|
||||
_ => {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"execution_spl_token2022_devnet_operation_unsupported",
|
||||
"execution_spl_token_2022_devnet_operation_unsupported",
|
||||
format!(
|
||||
"Token-2022 Devnet validation does not expose {}",
|
||||
operation.operation_code()
|
||||
@@ -760,8 +762,8 @@ fn preflight_request(
|
||||
return std::result::Result::Ok(kb_pipeline::Token2022PreflightRequest {
|
||||
query_role: request.query_role.clone(),
|
||||
min_context_slot: std::option::Option::None,
|
||||
max_accounts: kb_pipeline::MAX_TOKEN2022_PREFLIGHT_ACCOUNTS,
|
||||
max_total_data_bytes: kb_pipeline::MAX_TOKEN2022_PREFLIGHT_TOTAL_BYTES,
|
||||
max_accounts: kb_pipeline::MAX_TOKEN_2022_PREFLIGHT_ACCOUNTS,
|
||||
max_total_data_bytes: kb_pipeline::MAX_TOKEN_2022_PREFLIGHT_TOTAL_BYTES,
|
||||
requirements,
|
||||
elgamal_registry: std::option::Option::None,
|
||||
});
|
||||
@@ -770,7 +772,7 @@ fn preflight_request(
|
||||
fn validate_single_authority(authority: &kb_lib::ExSplTokenAuthority) -> kb_core::Result<()> {
|
||||
if !authority.multisig_signers.is_empty() {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"execution_spl_token2022_devnet_multisig_not_supported",
|
||||
"execution_spl_token_2022_devnet_multisig_not_supported",
|
||||
"the Devnet validation UI currently supports one profile-wallet authority",
|
||||
));
|
||||
}
|
||||
@@ -910,7 +912,7 @@ fn validate_profile_wallet_signers(
|
||||
) -> kb_core::Result<()> {
|
||||
if required_signers.iter().any(|value| return value.as_str() != wallet_pubkey) {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"execution_spl_token2022_external_signer_unavailable",
|
||||
"execution_spl_token_2022_external_signer_unavailable",
|
||||
format!(
|
||||
"the Devnet Token orchestrator can sign only with profile wallet {}; required signers are {}",
|
||||
wallet_pubkey,
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_token2022_devnet_scenarios.rs
|
||||
// version: 5
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_token_2022_devnet_scenarios.rs
|
||||
// version: 6
|
||||
|
||||
//! Stable Devnet validation scenarios required to close milestone 0.4.6.
|
||||
|
||||
@@ -53,17 +53,17 @@ pub struct DevnetSplValidationScenario {
|
||||
/// Returns the complete ordered Devnet scenario inventory for milestone 0.4.6.
|
||||
pub fn devnet_spl_validation_scenarios() -> std::vec::Vec<crate::DevnetSplValidationScenario> {
|
||||
return vec![
|
||||
public_scenario("token2022_mint_to_checked", "Token-2022 MintToChecked", kb_lib::EX_SPL_TOKEN2022_MINT_TO_CHECKED_OPERATION, &["TOKEN2022_MINT", "TOKEN2022_SOURCE", "TOKEN2022_AUTHORITY", "TOKEN2022_DECIMALS", "TOKEN2022_MINT_AMOUNT_RAW"]),
|
||||
public_scenario("token2022_transfer_checked", "Token-2022 TransferChecked", kb_lib::EX_SPL_TOKEN2022_TRANSFER_CHECKED_OPERATION, &["TOKEN2022_SOURCE", "TOKEN2022_MINT", "TOKEN2022_DESTINATION", "TOKEN2022_AUTHORITY", "TOKEN2022_DECIMALS", "TOKEN2022_TRANSFER_AMOUNT_RAW"]),
|
||||
public_scenario("token2022_approve_checked", "Token-2022 ApproveChecked", kb_lib::EX_SPL_TOKEN2022_APPROVE_CHECKED_OPERATION, &["TOKEN2022_SOURCE", "TOKEN2022_MINT", "TOKEN2022_DELEGATE", "TOKEN2022_AUTHORITY", "TOKEN2022_DECIMALS", "TOKEN2022_APPROVE_AMOUNT_RAW"]),
|
||||
public_scenario("token2022_revoke", "Token-2022 Revoke", kb_lib::EX_SPL_TOKEN2022_REVOKE_OPERATION, &["TOKEN2022_SOURCE", "TOKEN2022_AUTHORITY"]),
|
||||
public_scenario("token2022_burn_checked", "Token-2022 BurnChecked", kb_lib::EX_SPL_TOKEN2022_BURN_CHECKED_OPERATION, &["TOKEN2022_SOURCE", "TOKEN2022_MINT", "TOKEN2022_AUTHORITY", "TOKEN2022_DECIMALS", "TOKEN2022_BURN_AMOUNT_RAW"]),
|
||||
public_scenario("token2022_freeze_account", "Token-2022 FreezeAccount", kb_lib::EX_SPL_TOKEN2022_FREEZE_ACCOUNT_OPERATION, &["TOKEN2022_SOURCE", "TOKEN2022_MINT", "TOKEN2022_FREEZE_AUTHORITY"]),
|
||||
public_scenario("token2022_thaw_account", "Token-2022 ThawAccount", kb_lib::EX_SPL_TOKEN2022_THAW_ACCOUNT_OPERATION, &["TOKEN2022_SOURCE", "TOKEN2022_MINT", "TOKEN2022_FREEZE_AUTHORITY"]),
|
||||
public_scenario("token2022_close_destination", "Token-2022 CloseAccount destination", kb_lib::EX_SPL_TOKEN2022_CLOSE_ACCOUNT_OPERATION, &["TOKEN2022_DESTINATION", "KB_DEVNET_WALLET_ADDRESS", "TOKEN2022_AUTHORITY"]),
|
||||
public_scenario("token_2022_mint_to_checked", "Token-2022 MintToChecked", kb_lib::EX_SPL_TOKEN_2022_MINT_TO_CHECKED_OPERATION, &["TOKEN_2022_MINT", "TOKEN_2022_SOURCE", "TOKEN_2022_AUTHORITY", "TOKEN_2022_DECIMALS", "TOKEN_2022_MINT_AMOUNT_RAW"]),
|
||||
public_scenario("token_2022_transfer_checked", "Token-2022 TransferChecked", kb_lib::EX_SPL_TOKEN_2022_TRANSFER_CHECKED_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_DESTINATION", "TOKEN_2022_AUTHORITY", "TOKEN_2022_DECIMALS", "TOKEN_2022_TRANSFER_AMOUNT_RAW"]),
|
||||
public_scenario("token_2022_approve_checked", "Token-2022 ApproveChecked", kb_lib::EX_SPL_TOKEN_2022_APPROVE_CHECKED_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_DELEGATE", "TOKEN_2022_AUTHORITY", "TOKEN_2022_DECIMALS", "TOKEN_2022_APPROVE_AMOUNT_RAW"]),
|
||||
public_scenario("token_2022_revoke", "Token-2022 Revoke", kb_lib::EX_SPL_TOKEN_2022_REVOKE_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_AUTHORITY"]),
|
||||
public_scenario("token_2022_burn_checked", "Token-2022 BurnChecked", kb_lib::EX_SPL_TOKEN_2022_BURN_CHECKED_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_AUTHORITY", "TOKEN_2022_DECIMALS", "TOKEN_2022_BURN_AMOUNT_RAW"]),
|
||||
public_scenario("token_2022_freeze_account", "Token-2022 FreezeAccount", kb_lib::EX_SPL_TOKEN_2022_FREEZE_ACCOUNT_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_FREEZE_AUTHORITY"]),
|
||||
public_scenario("token_2022_thaw_account", "Token-2022 ThawAccount", kb_lib::EX_SPL_TOKEN_2022_THAW_ACCOUNT_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "TOKEN_2022_FREEZE_AUTHORITY"]),
|
||||
public_scenario("token_2022_close_destination", "Token-2022 CloseAccount destination", kb_lib::EX_SPL_TOKEN_2022_CLOSE_ACCOUNT_OPERATION, &["TOKEN_2022_DESTINATION", "KB_DEVNET_WALLET_ADDRESS", "TOKEN_2022_AUTHORITY"]),
|
||||
registry_scenario("elgamal_registry_create", "ElGamal Registry CreateRegistry", "spl_elgamal_registry.create_registry", &["ELGAMAL_REGISTRY_ADDRESS", "ELGAMAL_PUBKEY_BASE64", "PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
||||
registry_scenario("elgamal_registry_update", "ElGamal Registry UpdateRegistry", "spl_elgamal_registry.update_registry", &["ELGAMAL_REGISTRY_ADDRESS", "ELGAMAL_PUBKEY_BASE64", "PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
||||
confidential_scenario("token2022_configure_confidential_account", "Token-2022 ConfigureAccountWithRegistry", kb_lib::EX_SPL_TOKEN2022_CONFIGURE_CONFIDENTIAL_TRANSFER_ACCOUNT_WITH_REGISTRY_OPERATION, &["TOKEN2022_SOURCE", "TOKEN2022_MINT", "ELGAMAL_REGISTRY_ADDRESS", "PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
||||
confidential_scenario("token_2022_configure_confidential_account", "Token-2022 ConfigureAccountWithRegistry", kb_lib::EX_SPL_TOKEN_2022_CONFIGURE_CONFIDENTIAL_TRANSFER_ACCOUNT_WITH_REGISTRY_OPERATION, &["TOKEN_2022_SOURCE", "TOKEN_2022_MINT", "ELGAMAL_REGISTRY_ADDRESS", "PUBKEY_VALIDITY_PROOF_CONTEXT"]),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_token2022_validation.rs
|
||||
// version: 5
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_token_2022_validation.rs
|
||||
// version: 6
|
||||
|
||||
//! Machine-readable validation evidence contract for the Token-2022 milestone.
|
||||
|
||||
/// Maximum number of evidence records accepted in one validation report.
|
||||
pub const MAX_TOKEN2022_VALIDATION_EVIDENCE: usize = 64;
|
||||
pub const MAX_TOKEN_2022_VALIDATION_EVIDENCE: usize = 64;
|
||||
|
||||
/// Required validation environment for one scenario.
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
|
||||
@@ -110,31 +110,31 @@ pub struct Token2022ValidationMatrixScenario {
|
||||
}
|
||||
|
||||
/// Loads and validates the canonical Token-2022 validation matrix.
|
||||
pub fn load_token2022_validation_matrix() -> kb_core::Result<crate::Token2022ValidationMatrix> {
|
||||
pub fn load_token_2022_validation_matrix() -> kb_core::Result<crate::Token2022ValidationMatrix> {
|
||||
let parsed = match serde_json::from_str::<crate::Token2022ValidationMatrix>(include_str!(
|
||||
"../../test-fixtures/contract-matrices/SPL_TOKEN2022_VALIDATION_MATRIX.json"
|
||||
"../../test-fixtures/contract-matrices/SPL_TOKEN_2022_VALIDATION_MATRIX.json"
|
||||
)) {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_matrix_invalid_json",
|
||||
"token_2022_validation_matrix_invalid_json",
|
||||
format!("Token-2022 validation matrix JSON is invalid: {error}"),
|
||||
));
|
||||
},
|
||||
};
|
||||
if let std::result::Result::Err(error) = validate_token2022_validation_matrix(&parsed) {
|
||||
if let std::result::Result::Err(error) = validate_token_2022_validation_matrix(&parsed) {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
return std::result::Result::Ok(parsed);
|
||||
}
|
||||
|
||||
/// Validates schema, scenario inventory, statuses, and observed evidence.
|
||||
pub fn validate_token2022_validation_matrix(
|
||||
pub fn validate_token_2022_validation_matrix(
|
||||
matrix: &crate::Token2022ValidationMatrix,
|
||||
) -> kb_core::Result<()> {
|
||||
if matrix.matrix_version != 2 || matrix.milestone != "0.4.6" {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_matrix_contract_mismatch",
|
||||
"token_2022_validation_matrix_contract_mismatch",
|
||||
"Token-2022 validation matrix must use version 2 for milestone 0.4.6",
|
||||
));
|
||||
}
|
||||
@@ -147,13 +147,13 @@ pub fn validate_token2022_validation_matrix(
|
||||
.collect::<std::vec::Vec<&str>>();
|
||||
if actual_statuses.as_slice() != expected_statuses {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_matrix_status_vocabulary_mismatch",
|
||||
"token_2022_validation_matrix_status_vocabulary_mismatch",
|
||||
"Token-2022 validation status vocabulary differs from the compiled contract",
|
||||
));
|
||||
}
|
||||
let expected_ids = [
|
||||
"offline_full_regression",
|
||||
"token2022_public_devnet",
|
||||
"token_2022_public_devnet",
|
||||
"elgamal_registry_devnet",
|
||||
"confidential_transfer_localnet_or_devnet",
|
||||
"confidential_mint_burn_localnet_or_devnet",
|
||||
@@ -169,16 +169,16 @@ pub fn validate_token2022_validation_matrix(
|
||||
.collect::<std::vec::Vec<&str>>();
|
||||
if actual_ids.as_slice() != expected_ids {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_matrix_scenario_inventory_mismatch",
|
||||
"token_2022_validation_matrix_scenario_inventory_mismatch",
|
||||
"Token-2022 validation scenario inventory or order differs from the compiled contract",
|
||||
));
|
||||
}
|
||||
for scenario in &matrix.scenarios {
|
||||
if scenario.required_evidence.is_empty()
|
||||
|| scenario.required_evidence.len() > crate::MAX_TOKEN2022_VALIDATION_EVIDENCE
|
||||
|| scenario.required_evidence.len() > crate::MAX_TOKEN_2022_VALIDATION_EVIDENCE
|
||||
{
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_matrix_required_evidence_invalid",
|
||||
"token_2022_validation_matrix_required_evidence_invalid",
|
||||
"Every Token-2022 validation scenario must declare bounded required evidence",
|
||||
));
|
||||
}
|
||||
@@ -186,7 +186,7 @@ pub fn validate_token2022_validation_matrix(
|
||||
for evidence_kind in &scenario.required_evidence {
|
||||
if evidence_kind.trim().is_empty() || !required.insert(evidence_kind.as_str()) {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_matrix_required_evidence_invalid",
|
||||
"token_2022_validation_matrix_required_evidence_invalid",
|
||||
"Required Token-2022 validation evidence must be non-empty and unique",
|
||||
));
|
||||
}
|
||||
@@ -199,7 +199,7 @@ pub fn validate_token2022_validation_matrix(
|
||||
.collect::<std::collections::BTreeSet<&str>>();
|
||||
if !required.iter().all(|kind| return observed.contains(kind)) {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_matrix_confirmed_without_required_evidence",
|
||||
"token_2022_validation_matrix_confirmed_without_required_evidence",
|
||||
format!(
|
||||
"Confirmed Token-2022 validation scenario {} lacks required evidence",
|
||||
scenario.id
|
||||
@@ -213,7 +213,7 @@ pub fn validate_token2022_validation_matrix(
|
||||
) && !scenario.evidence.is_empty()
|
||||
{
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_matrix_unobserved_with_evidence",
|
||||
"token_2022_validation_matrix_unobserved_with_evidence",
|
||||
"Not-run or unavailable Token-2022 scenarios must not retain observed evidence",
|
||||
));
|
||||
}
|
||||
@@ -229,7 +229,7 @@ pub struct Token2022ValidationReport {
|
||||
}
|
||||
|
||||
/// Validates that a milestone report is bounded, unique, and does not overclaim evidence.
|
||||
pub fn validate_token2022_validation_report(
|
||||
pub fn validate_token_2022_validation_report(
|
||||
report: &crate::Token2022ValidationReport,
|
||||
) -> kb_core::Result<()> {
|
||||
if report.scenarios.is_empty() {
|
||||
@@ -241,23 +241,23 @@ pub fn validate_token2022_validation_report(
|
||||
for scenario in &report.scenarios {
|
||||
if scenario.id.trim().is_empty() || !ids.insert(scenario.id.clone()) {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_scenario_identity_invalid",
|
||||
"token_2022_validation_scenario_identity_invalid",
|
||||
"Token-2022 validation scenario ids must be non-empty and unique",
|
||||
));
|
||||
}
|
||||
if scenario.evidence.len() > crate::MAX_TOKEN2022_VALIDATION_EVIDENCE {
|
||||
if scenario.evidence.len() > crate::MAX_TOKEN_2022_VALIDATION_EVIDENCE {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_evidence_limit_exceeded",
|
||||
"token_2022_validation_evidence_limit_exceeded",
|
||||
format!(
|
||||
"Token-2022 validation accepts at most {} evidence records per scenario",
|
||||
crate::MAX_TOKEN2022_VALIDATION_EVIDENCE
|
||||
crate::MAX_TOKEN_2022_VALIDATION_EVIDENCE
|
||||
),
|
||||
));
|
||||
}
|
||||
for evidence in &scenario.evidence {
|
||||
if evidence.kind.trim().is_empty() || evidence.value.trim().is_empty() {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_evidence_invalid",
|
||||
"token_2022_validation_evidence_invalid",
|
||||
"Token-2022 validation evidence kind and value must be non-empty",
|
||||
));
|
||||
}
|
||||
@@ -271,7 +271,7 @@ pub fn validate_token2022_validation_report(
|
||||
);
|
||||
if completed && scenario.evidence.is_empty() {
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_completed_without_evidence",
|
||||
"token_2022_validation_completed_without_evidence",
|
||||
"A completed Token-2022 validation scenario must retain evidence",
|
||||
));
|
||||
}
|
||||
@@ -284,7 +284,7 @@ pub fn validate_token2022_validation_report(
|
||||
&& !has_pipeline_evidence(scenario)
|
||||
{
|
||||
return std::result::Result::Err(kb_core::Error::new(
|
||||
"token2022_validation_confirmed_without_pipeline_evidence",
|
||||
"token_2022_validation_confirmed_without_pipeline_evidence",
|
||||
"A confirmed end-to-end Token-2022 scenario must retain hydration, extraction, replay, materialization, and idempotence evidence",
|
||||
));
|
||||
}
|
||||
@@ -362,11 +362,11 @@ mod tests {
|
||||
let report = crate::Token2022ValidationReport {
|
||||
scenarios: vec![scenario(crate::Token2022ValidationStatus::Confirmed)],
|
||||
};
|
||||
assert!(crate::validate_token2022_validation_report(&report).is_ok());
|
||||
assert!(crate::validate_token_2022_validation_report(&report).is_ok());
|
||||
let mut incomplete = scenario(crate::Token2022ValidationStatus::Confirmed);
|
||||
incomplete.evidence.retain(|evidence| return evidence.kind != "second_replay");
|
||||
assert!(
|
||||
crate::validate_token2022_validation_report(&crate::Token2022ValidationReport {
|
||||
crate::validate_token_2022_validation_report(&crate::Token2022ValidationReport {
|
||||
scenarios: vec![incomplete]
|
||||
})
|
||||
.is_err()
|
||||
@@ -381,7 +381,7 @@ mod tests {
|
||||
unavailable.id = "permissioned_burn_devnet".to_string();
|
||||
unavailable.evidence.clear();
|
||||
assert!(
|
||||
crate::validate_token2022_validation_report(&crate::Token2022ValidationReport {
|
||||
crate::validate_token_2022_validation_report(&crate::Token2022ValidationReport {
|
||||
scenarios: vec![not_run, unavailable]
|
||||
})
|
||||
.is_ok()
|
||||
@@ -393,7 +393,7 @@ mod tests {
|
||||
let first = scenario(crate::Token2022ValidationStatus::Confirmed);
|
||||
let duplicate = first.clone();
|
||||
assert!(
|
||||
crate::validate_token2022_validation_report(&crate::Token2022ValidationReport {
|
||||
crate::validate_token_2022_validation_report(&crate::Token2022ValidationReport {
|
||||
scenarios: vec![first, duplicate]
|
||||
})
|
||||
.is_err()
|
||||
@@ -401,7 +401,7 @@ mod tests {
|
||||
let mut failed = scenario(crate::Token2022ValidationStatus::Failed);
|
||||
failed.evidence.clear();
|
||||
assert!(
|
||||
crate::validate_token2022_validation_report(&crate::Token2022ValidationReport {
|
||||
crate::validate_token_2022_validation_report(&crate::Token2022ValidationReport {
|
||||
scenarios: vec![failed]
|
||||
})
|
||||
.is_err()
|
||||
@@ -410,7 +410,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn canonical_matrix_matches_compiled_inventory_and_observed_offline_evidence() {
|
||||
let matrix = crate::load_token2022_validation_matrix();
|
||||
let matrix = crate::load_token_2022_validation_matrix();
|
||||
assert!(matrix.is_ok());
|
||||
let matrix = match matrix {
|
||||
std::result::Result::Ok(value) => value,
|
||||
@@ -428,13 +428,13 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn confirmed_matrix_scenario_requires_every_declared_evidence_kind() {
|
||||
let matrix = crate::load_token2022_validation_matrix();
|
||||
let matrix = crate::load_token_2022_validation_matrix();
|
||||
assert!(matrix.is_ok());
|
||||
let mut matrix = match matrix {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => panic!("unexpected matrix error: {error}"),
|
||||
};
|
||||
matrix.scenarios[0].evidence.retain(|evidence| return evidence.kind != "clippy");
|
||||
assert!(crate::validate_token2022_validation_matrix(&matrix).is_err());
|
||||
assert!(crate::validate_token_2022_validation_matrix(&matrix).is_err());
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_token_execution.rs
|
||||
// version: 6
|
||||
// version: 7
|
||||
|
||||
//! Devnet classic SPL Token execution with stateful and canonical post-validation.
|
||||
|
||||
@@ -399,8 +399,10 @@ where
|
||||
},
|
||||
};
|
||||
let idempotent = second_replay.failed_inputs == 0
|
||||
&& second_replay.processing_error_inputs == 0
|
||||
&& second_replay.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialized_outputs == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
});
|
||||
@@ -956,11 +958,13 @@ where
|
||||
|
||||
pub(crate) fn decode_completed(summary: &kb_pipeline::DecodeReplaySummary) -> bool {
|
||||
return summary.failed_inputs == 0
|
||||
&& summary.processing_error_inputs == 0
|
||||
&& summary.unmatched == 0
|
||||
&& !summary.cancelled
|
||||
&& summary.completed >= 1
|
||||
&& summary.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.unsupported == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
})
|
||||
@@ -1207,7 +1211,9 @@ mod tests {
|
||||
};
|
||||
assert_eq!(first_replay.failed_inputs, 0);
|
||||
assert!(first_replay.processors.iter().all(|processor| {
|
||||
return processor.failed == 0 && processor.materialization_refused == 0;
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
}));
|
||||
let idempotence_replay = match summary.idempotence_replay.as_ref() {
|
||||
std::option::Option::Some(value) => value,
|
||||
@@ -1216,6 +1222,7 @@ mod tests {
|
||||
assert_eq!(idempotence_replay.failed_inputs, 0);
|
||||
assert!(idempotence_replay.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialized_outputs == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
}));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// file: kb-pipeline-demo-scenarios/src/solana_token_lifecycle.rs
|
||||
// version: 5
|
||||
// version: 6
|
||||
|
||||
//! Controlled Devnet lifecycle for freshly prepared classic SPL Token accounts.
|
||||
|
||||
@@ -707,8 +707,10 @@ where
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
let idempotent = second_replay.failed_inputs == 0
|
||||
&& second_replay.processing_error_inputs == 0
|
||||
&& second_replay.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialized_outputs == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
});
|
||||
@@ -1256,8 +1258,10 @@ fn validated_step(
|
||||
};
|
||||
let idempotence = summary.idempotence_replay.as_ref().is_some_and(|value| {
|
||||
return value.failed_inputs == 0
|
||||
&& value.processing_error_inputs == 0
|
||||
&& value.processors.iter().all(|processor| {
|
||||
return processor.failed == 0
|
||||
&& processor.processing_errors == 0
|
||||
&& processor.materialized_outputs == 0
|
||||
&& processor.materialization_refused == 0;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user