v0.3.14-pre.005
This commit is contained in:
@@ -1,12 +1,12 @@
|
|||||||
# file: Cargo.toml
|
# file: Cargo.toml
|
||||||
# version: 571
|
# version: 572
|
||||||
|
|
||||||
[workspace]
|
[workspace]
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-store-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-raw-transaction-lib", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib", "crates/ksp-worker-api", "crates/ksp-worker-raw-transaction-ingest-lib"]
|
members = ["crates/ksp-app-backfill-desk", "crates/ksp-app-config-desk", "crates/ksp-app-solprices-desk", "crates/ksp-app-store-desk", "crates/ksp-app-wallet-desk", "crates/ksp-config-lib", "crates/ksp-core-lib", "crates/ksp-interface-lib", "crates/ksp-job-api", "crates/ksp-job-backfill-lib", "crates/ksp-logging-lib", "crates/ksp-offchain-transport-lib", "crates/ksp-onchain-transport-lib", "crates/ksp-program-api", "crates/ksp-raw-transaction-lib", "crates/ksp-store-api", "crates/ksp-store-lib", "crates/ksp-store-postgres-lib", "crates/ksp-wallet-lib", "crates/ksp-worker-api", "crates/ksp-worker-raw-transaction-ingest-lib"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.3.14-pre.4"
|
version = "0.3.14-pre.5"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
repository = "https://git.sasedev.com/Sasedev/khadhroony-solana-project"
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
|
// file: crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
|
||||||
// version: 4
|
// version: 5
|
||||||
|
|
||||||
|
/// Maximum number of proven redundant coverage epochs retained by one run-local continuity contract.
|
||||||
|
const MAX_RAW_TRANSACTION_INGEST_COVERAGE_EPOCHS: usize = 256;
|
||||||
/// Maximum number of simultaneously retained non-repaired run-local gaps.
|
/// Maximum number of simultaneously retained non-repaired run-local gaps.
|
||||||
const MAX_RAW_TRANSACTION_INGEST_OPEN_REPAIR_GAPS: usize = 64;
|
const MAX_RAW_TRANSACTION_INGEST_OPEN_REPAIR_GAPS: usize = 64;
|
||||||
/// Maximum number of run-local gaps that may actively repair at once.
|
/// Maximum number of run-local gaps that may actively repair at once.
|
||||||
@@ -23,6 +25,12 @@ pub(crate) enum RawTransactionIngestCoverageScope {
|
|||||||
KnownReferences([u8; 32]),
|
KnownReferences([u8; 32]),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
enum RawTransactionIngestCoverageRelation {
|
||||||
|
Exact,
|
||||||
|
Superset,
|
||||||
|
}
|
||||||
|
|
||||||
impl crate::RawTransactionIngestCoverageScope {
|
impl crate::RawTransactionIngestCoverageScope {
|
||||||
/// Creates one provider-neutral exact source scope from a stable family code and semantic fingerprint.
|
/// Creates one provider-neutral exact source scope from a stable family code and semantic fingerprint.
|
||||||
pub(crate) const fn exact_source_scope(family_code: &'static str, fingerprint: [u8; 32]) -> Self {
|
pub(crate) const fn exact_source_scope(family_code: &'static str, fingerprint: [u8; 32]) -> Self {
|
||||||
@@ -54,6 +62,19 @@ impl crate::RawTransactionIngestCoverageScope {
|
|||||||
fn is_known_references(&self) -> bool {
|
fn is_known_references(&self) -> bool {
|
||||||
return matches!(self, Self::KnownReferences(_));
|
return matches!(self, Self::KnownReferences(_));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn relation_to(&self, requirement: &Self) -> std::option::Option<RawTransactionIngestCoverageRelation> {
|
||||||
|
return match (self, requirement) {
|
||||||
|
(Self::FullLedgerTransactions, Self::FullLedgerTransactions) => std::option::Option::Some(RawTransactionIngestCoverageRelation::Exact),
|
||||||
|
(Self::FullLedgerTransactions, Self::ExactSourceScope(_, _)) => std::option::Option::Some(RawTransactionIngestCoverageRelation::Superset),
|
||||||
|
(Self::ExactSourceScope(family_code, fingerprint), Self::ExactSourceScope(required_family_code, required_fingerprint))
|
||||||
|
if family_code == required_family_code && fingerprint == required_fingerprint =>
|
||||||
|
{
|
||||||
|
std::option::Option::Some(RawTransactionIngestCoverageRelation::Exact)
|
||||||
|
},
|
||||||
|
_ => std::option::Option::None,
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
@@ -424,14 +445,14 @@ impl RawTransactionIngestTargetCoverage {
|
|||||||
if scope.is_known_references() {
|
if scope.is_known_references() {
|
||||||
return std::result::Result::Err(crate::runtime_error("continuity.known_references_not_target_scope"));
|
return std::result::Result::Err(crate::runtime_error("continuity.known_references_not_target_scope"));
|
||||||
}
|
}
|
||||||
if matches!(&scope, crate::RawTransactionIngestCoverageScope::FullLedgerTransactions) {
|
self.requirements.retain(|requirement| {
|
||||||
self.requirements.retain(|requirement| return requirement.commitment != commitment);
|
if requirement.commitment != commitment {
|
||||||
self.requirements.push(RawTransactionIngestCoverageRequirement { commitment, scope });
|
return true;
|
||||||
return std::result::Result::Ok(());
|
|
||||||
}
|
}
|
||||||
|
return scope.relation_to(&requirement.scope) != std::option::Option::Some(RawTransactionIngestCoverageRelation::Superset);
|
||||||
|
});
|
||||||
if self.requirements.iter().any(|requirement| {
|
if self.requirements.iter().any(|requirement| {
|
||||||
return requirement.commitment == commitment
|
return requirement.commitment == commitment && requirement.scope.relation_to(&scope).is_some();
|
||||||
&& (requirement.scope == crate::RawTransactionIngestCoverageScope::FullLedgerTransactions || requirement.scope == scope);
|
|
||||||
}) {
|
}) {
|
||||||
return std::result::Result::Ok(());
|
return std::result::Result::Ok(());
|
||||||
}
|
}
|
||||||
@@ -440,9 +461,133 @@ impl RawTransactionIngestTargetCoverage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
|
struct RawTransactionIngestCoverageRange {
|
||||||
|
end_slot: u64,
|
||||||
|
start_slot: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawTransactionIngestCoverageRange {
|
||||||
|
fn new(start_slot: u64, end_slot: u64) -> ksp_core_lib::Result<Self> {
|
||||||
|
if end_slot < start_slot {
|
||||||
|
return std::result::Result::Err(crate::runtime_error("continuity.coverage_range_reversed"));
|
||||||
|
}
|
||||||
|
return std::result::Result::Ok(Self { end_slot, start_slot });
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn contains_gap(self, gap: RawTransactionIngestGapRange) -> bool {
|
||||||
|
return self.start_slot <= gap.start_slot() && self.end_slot >= gap.end_slot();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
struct RawTransactionIngestCoverageEpoch {
|
||||||
|
commitment: ksp_onchain_transport_lib::SolanaCommitment,
|
||||||
|
epoch_id: u64,
|
||||||
|
range: RawTransactionIngestCoverageRange,
|
||||||
|
scope: crate::RawTransactionIngestCoverageScope,
|
||||||
|
source_key: [u8; 32],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawTransactionIngestCoverageEpoch {
|
||||||
|
fn new(
|
||||||
|
epoch_id: u64,
|
||||||
|
source_key: [u8; 32],
|
||||||
|
commitment: ksp_onchain_transport_lib::SolanaCommitment,
|
||||||
|
scope: crate::RawTransactionIngestCoverageScope,
|
||||||
|
range: RawTransactionIngestCoverageRange,
|
||||||
|
) -> ksp_core_lib::Result<Self> {
|
||||||
|
if epoch_id == 0 {
|
||||||
|
return std::result::Result::Err(crate::runtime_error("continuity.coverage_epoch_id_invalid"));
|
||||||
|
}
|
||||||
|
if let std::result::Result::Err(error) = scope.validate_configured_target_scope() {
|
||||||
|
return std::result::Result::Err(error);
|
||||||
|
}
|
||||||
|
return std::result::Result::Ok(Self { commitment, epoch_id, range, scope, source_key });
|
||||||
|
}
|
||||||
|
|
||||||
|
fn relation_to_requirement(
|
||||||
|
&self,
|
||||||
|
target_source_key: [u8; 32],
|
||||||
|
requirement: &RawTransactionIngestCoverageRequirement,
|
||||||
|
gap: RawTransactionIngestGapRange,
|
||||||
|
) -> std::option::Option<RawTransactionIngestCoverageRelation> {
|
||||||
|
if self.source_key == target_source_key || self.commitment != requirement.commitment || !self.range.contains_gap(gap) {
|
||||||
|
return std::option::Option::None;
|
||||||
|
}
|
||||||
|
return self.scope.relation_to(&requirement.scope);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RawTransactionIngestCoverageEpochLedger {
|
||||||
|
epochs: std::vec::Vec<RawTransactionIngestCoverageEpoch>,
|
||||||
|
next_epoch_id: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RawTransactionIngestCoverageEpochLedger {
|
||||||
|
fn new() -> Self {
|
||||||
|
return Self { epochs: std::vec::Vec::new(), next_epoch_id: 1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
fn redundant_relation_for_gap(
|
||||||
|
&self,
|
||||||
|
target_source_key: [u8; 32],
|
||||||
|
requirement: &RawTransactionIngestCoverageRequirement,
|
||||||
|
gap: RawTransactionIngestGapRange,
|
||||||
|
) -> std::option::Option<RawTransactionIngestCoverageRelation> {
|
||||||
|
let mut exact = false;
|
||||||
|
for epoch in &self.epochs {
|
||||||
|
match epoch.relation_to_requirement(target_source_key, requirement, gap) {
|
||||||
|
std::option::Option::Some(RawTransactionIngestCoverageRelation::Superset) => {
|
||||||
|
return std::option::Option::Some(RawTransactionIngestCoverageRelation::Superset);
|
||||||
|
},
|
||||||
|
std::option::Option::Some(RawTransactionIngestCoverageRelation::Exact) => exact = true,
|
||||||
|
std::option::Option::None => {},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if exact {
|
||||||
|
return std::option::Option::Some(RawTransactionIngestCoverageRelation::Exact);
|
||||||
|
}
|
||||||
|
return std::option::Option::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_invariants(&self, capabilities: &[crate::RawTransactionIngestContinuityCapabilityDescriptor]) -> ksp_core_lib::Result<()> {
|
||||||
|
if self.next_epoch_id == 0 || self.epochs.len() > MAX_RAW_TRANSACTION_INGEST_COVERAGE_EPOCHS {
|
||||||
|
return std::result::Result::Err(crate::runtime_error("continuity.coverage_epoch_inventory_invalid"));
|
||||||
|
}
|
||||||
|
let mut ids = std::collections::BTreeSet::new();
|
||||||
|
let mut highest_epoch_id = 0_u64;
|
||||||
|
for epoch in &self.epochs {
|
||||||
|
if epoch.epoch_id == 0 || !ids.insert(epoch.epoch_id) {
|
||||||
|
return std::result::Result::Err(crate::runtime_error("continuity.coverage_epoch_id_invalid"));
|
||||||
|
}
|
||||||
|
highest_epoch_id = highest_epoch_id.max(epoch.epoch_id);
|
||||||
|
if let std::result::Result::Err(error) = epoch.scope.validate_configured_target_scope() {
|
||||||
|
return std::result::Result::Err(error);
|
||||||
|
}
|
||||||
|
if RawTransactionIngestCoverageRange::new(epoch.range.start_slot, epoch.range.end_slot).is_err() {
|
||||||
|
return std::result::Result::Err(crate::runtime_error("continuity.coverage_epoch_range_invalid"));
|
||||||
|
}
|
||||||
|
let matching_capability = capabilities.iter().find(|capability| return capability.source_key == epoch.source_key);
|
||||||
|
let matching_capability = match matching_capability {
|
||||||
|
std::option::Option::Some(value) => value,
|
||||||
|
std::option::Option::None => return std::result::Result::Err(crate::runtime_error("continuity.coverage_epoch_source_unknown")),
|
||||||
|
};
|
||||||
|
if matching_capability.commitment != epoch.commitment || matching_capability.source_scope != epoch.scope {
|
||||||
|
return std::result::Result::Err(crate::runtime_error("continuity.coverage_epoch_capability_mismatch"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !self.epochs.is_empty() && self.next_epoch_id <= highest_epoch_id {
|
||||||
|
return std::result::Result::Err(crate::runtime_error("continuity.coverage_epoch_next_id_invalid"));
|
||||||
|
}
|
||||||
|
return std::result::Result::Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Run-local continuity contracts prepared from the exact caller-composed live-source aggregate before productive source execution.
|
/// Run-local continuity contracts prepared from the exact caller-composed live-source aggregate before productive source execution.
|
||||||
pub(crate) struct RawTransactionIngestContinuityContracts {
|
pub(crate) struct RawTransactionIngestContinuityContracts {
|
||||||
capabilities: std::vec::Vec<crate::RawTransactionIngestContinuityCapabilityDescriptor>,
|
capabilities: std::vec::Vec<crate::RawTransactionIngestContinuityCapabilityDescriptor>,
|
||||||
|
coverage_epochs: RawTransactionIngestCoverageEpochLedger,
|
||||||
gap_ledger: RawTransactionIngestGapLedger,
|
gap_ledger: RawTransactionIngestGapLedger,
|
||||||
target_coverage: RawTransactionIngestTargetCoverage,
|
target_coverage: RawTransactionIngestTargetCoverage,
|
||||||
}
|
}
|
||||||
@@ -470,11 +615,15 @@ impl crate::RawTransactionIngestContinuityContracts {
|
|||||||
std::result::Result::Ok(value) => value,
|
std::result::Result::Ok(value) => value,
|
||||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||||
};
|
};
|
||||||
|
let coverage_epochs = RawTransactionIngestCoverageEpochLedger::new();
|
||||||
|
if let std::result::Result::Err(error) = coverage_epochs.validate_invariants(capabilities.as_slice()) {
|
||||||
|
return std::result::Result::Err(error);
|
||||||
|
}
|
||||||
let gap_ledger = RawTransactionIngestGapLedger::new(network);
|
let gap_ledger = RawTransactionIngestGapLedger::new(network);
|
||||||
if let std::result::Result::Err(error) = gap_ledger.validate_invariants() {
|
if let std::result::Result::Err(error) = gap_ledger.validate_invariants() {
|
||||||
return std::result::Result::Err(error);
|
return std::result::Result::Err(error);
|
||||||
}
|
}
|
||||||
if !coverage_scope_catalog_is_complete() {
|
if !coverage_scope_catalog_is_complete() || !coverage_relation_catalog_is_complete() {
|
||||||
return std::result::Result::Err(crate::runtime_error("continuity.coverage_scope_catalog_invalid"));
|
return std::result::Result::Err(crate::runtime_error("continuity.coverage_scope_catalog_invalid"));
|
||||||
}
|
}
|
||||||
if MAX_RAW_TRANSACTION_INGEST_REPAIR_BLOCK_FETCH_IN_FLIGHT == 0
|
if MAX_RAW_TRANSACTION_INGEST_REPAIR_BLOCK_FETCH_IN_FLIGHT == 0
|
||||||
@@ -483,7 +632,7 @@ impl crate::RawTransactionIngestContinuityContracts {
|
|||||||
{
|
{
|
||||||
return std::result::Result::Err(crate::runtime_error("continuity.repair_bounds_invalid"));
|
return std::result::Result::Err(crate::runtime_error("continuity.repair_bounds_invalid"));
|
||||||
}
|
}
|
||||||
return std::result::Result::Ok(Self { capabilities, gap_ledger, target_coverage });
|
return std::result::Result::Ok(Self { capabilities, coverage_epochs, gap_ledger, target_coverage });
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Revalidates that the run-local contracts still correspond exactly to the caller-composed source count before tasks are spawned.
|
/// Revalidates that the run-local contracts still correspond exactly to the caller-composed source count before tasks are spawned.
|
||||||
@@ -491,6 +640,9 @@ impl crate::RawTransactionIngestContinuityContracts {
|
|||||||
if self.capabilities.len() != expected_source_count || self.target_coverage.requirements.is_empty() {
|
if self.capabilities.len() != expected_source_count || self.target_coverage.requirements.is_empty() {
|
||||||
return std::result::Result::Err(crate::runtime_error("continuity.source_inventory_mismatch"));
|
return std::result::Result::Err(crate::runtime_error("continuity.source_inventory_mismatch"));
|
||||||
}
|
}
|
||||||
|
if let std::result::Result::Err(error) = self.coverage_epochs.validate_invariants(self.capabilities.as_slice()) {
|
||||||
|
return std::result::Result::Err(error);
|
||||||
|
}
|
||||||
if let std::result::Result::Err(error) = self.gap_ledger.validate_invariants() {
|
if let std::result::Result::Err(error) = self.gap_ledger.validate_invariants() {
|
||||||
return std::result::Result::Err(error);
|
return std::result::Result::Err(error);
|
||||||
}
|
}
|
||||||
@@ -510,6 +662,68 @@ fn coverage_scope_catalog_is_complete() -> bool {
|
|||||||
&& known.is_known_references();
|
&& known.is_known_references();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn coverage_relation_catalog_is_complete() -> bool {
|
||||||
|
let target_scope = crate::RawTransactionIngestCoverageScope::ExactSourceScope("standard_logs", [7_u8; 32]);
|
||||||
|
let target_requirement =
|
||||||
|
RawTransactionIngestCoverageRequirement { commitment: ksp_onchain_transport_lib::SolanaCommitment::Confirmed, scope: target_scope.clone() };
|
||||||
|
let gap = match RawTransactionIngestGapRange::new(100, 110) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return false,
|
||||||
|
};
|
||||||
|
let full_range = match RawTransactionIngestCoverageRange::new(90, 120) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return false,
|
||||||
|
};
|
||||||
|
let partial_range = match RawTransactionIngestCoverageRange::new(100, 109) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return false,
|
||||||
|
};
|
||||||
|
let exact_epoch =
|
||||||
|
match RawTransactionIngestCoverageEpoch::new(1, [2_u8; 32], ksp_onchain_transport_lib::SolanaCommitment::Confirmed, target_scope, full_range) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return false,
|
||||||
|
};
|
||||||
|
let full_epoch = match RawTransactionIngestCoverageEpoch::new(
|
||||||
|
2,
|
||||||
|
[3_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
crate::RawTransactionIngestCoverageScope::FullLedgerTransactions,
|
||||||
|
full_range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return false,
|
||||||
|
};
|
||||||
|
let cross_family_epoch = match RawTransactionIngestCoverageEpoch::new(
|
||||||
|
3,
|
||||||
|
[4_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
crate::RawTransactionIngestCoverageScope::ExactSourceScope("helius_transaction", [7_u8; 32]),
|
||||||
|
full_range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return false,
|
||||||
|
};
|
||||||
|
let partial_epoch = match RawTransactionIngestCoverageEpoch::new(
|
||||||
|
4,
|
||||||
|
[5_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
crate::RawTransactionIngestCoverageScope::FullLedgerTransactions,
|
||||||
|
partial_range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(_) => return false,
|
||||||
|
};
|
||||||
|
let ledger = RawTransactionIngestCoverageEpochLedger {
|
||||||
|
epochs: std::vec![exact_epoch.clone(), full_epoch.clone(), cross_family_epoch.clone(), partial_epoch.clone()],
|
||||||
|
next_epoch_id: 5,
|
||||||
|
};
|
||||||
|
return ledger.redundant_relation_for_gap([1_u8; 32], &target_requirement, gap)
|
||||||
|
== std::option::Option::Some(RawTransactionIngestCoverageRelation::Superset)
|
||||||
|
&& exact_epoch.relation_to_requirement([2_u8; 32], &target_requirement, gap).is_none()
|
||||||
|
&& cross_family_epoch.relation_to_requirement([1_u8; 32], &target_requirement, gap).is_none()
|
||||||
|
&& partial_epoch.relation_to_requirement([1_u8; 32], &target_requirement, gap).is_none();
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[path = "../unit_tests/continuity.rs"]
|
#[path = "../unit_tests/continuity.rs"]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
|
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
|
||||||
// version: 28
|
// version: 29
|
||||||
|
|
||||||
//! External public, security, redaction and release-boundary hardening canaries through `v0.3.14-pre.004`.
|
//! External public, security, redaction and release-boundary hardening canaries through `v0.3.14-pre.005`.
|
||||||
|
|
||||||
fn network(value: &'static str) -> std::option::Option<ksp_store_lib::RawNetworkId> {
|
fn network(value: &'static str) -> std::option::Option<ksp_store_lib::RawNetworkId> {
|
||||||
let result = ksp_store_lib::RawNetworkId::new(value);
|
let result = ksp_store_lib::RawNetworkId::new(value);
|
||||||
@@ -1054,3 +1054,39 @@ fn v0_3_14_pre_004_yellowstone_replay_evidence_is_transport_owned_and_fail_close
|
|||||||
assert!(!transport.contains("replay_coverage_proven_count"));
|
assert!(!transport.contains("replay_coverage_proven_count"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn v0_3_14_pre_005_redundant_coverage_requires_exact_or_superset_proof_over_full_range() {
|
||||||
|
let continuity = include_str!("../src/continuity.rs");
|
||||||
|
let root = include_str!("../src/lib.rs");
|
||||||
|
for required in [
|
||||||
|
"RawTransactionIngestCoverageRelation",
|
||||||
|
"RawTransactionIngestCoverageEpoch",
|
||||||
|
"RawTransactionIngestCoverageEpochLedger",
|
||||||
|
"MAX_RAW_TRANSACTION_INGEST_COVERAGE_EPOCHS",
|
||||||
|
"self.source_key == target_source_key",
|
||||||
|
"self.commitment != requirement.commitment",
|
||||||
|
"!self.range.contains_gap(gap)",
|
||||||
|
"family_code == required_family_code && fingerprint == required_fingerprint",
|
||||||
|
"RawTransactionIngestCoverageRelation::Superset",
|
||||||
|
] {
|
||||||
|
assert!(continuity.contains(required), "required pre.005 conservative coverage guard missing: {required}");
|
||||||
|
}
|
||||||
|
for forbidden in [
|
||||||
|
"standard_logs\", \"helius_transaction",
|
||||||
|
"helius_transaction\", \"standard_logs",
|
||||||
|
"commitment >= requirement.commitment",
|
||||||
|
"commitment <= requirement.commitment",
|
||||||
|
"source_key == target_source_key &&",
|
||||||
|
] {
|
||||||
|
assert!(!continuity.contains(forbidden), "pre.005 introduced opportunistic coverage equivalence: {forbidden}");
|
||||||
|
}
|
||||||
|
for forbidden_public in [
|
||||||
|
"pub use self::continuity::RawTransactionIngestCoverageRelation",
|
||||||
|
"pub use self::continuity::RawTransactionIngestCoverageEpoch",
|
||||||
|
"pub use self::continuity::RawTransactionIngestTargetCoverage",
|
||||||
|
] {
|
||||||
|
assert!(!root.contains(forbidden_public), "pre.005 leaked private continuity proof type: {forbidden_public}");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
|
// file: crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
|
||||||
// version: 23
|
// version: 24
|
||||||
|
|
||||||
//! Release-completeness canaries through the `v0.3.14-pre.004` Yellowstone native replay-evidence tranche.
|
//! Release-completeness canaries through the `v0.3.14-pre.005` redundant-coverage proof tranche.
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn pre_010_production_module_inventory_is_exact() -> std::io::Result<()> {
|
fn pre_010_production_module_inventory_is_exact() -> std::io::Result<()> {
|
||||||
@@ -263,3 +263,22 @@ fn v0_3_14_pre_004_native_replay_evidence_canaries_are_present_without_public_re
|
|||||||
assert!(!root.contains("set_from_slot"));
|
assert!(!root.contains("set_from_slot"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn v0_3_14_pre_005_redundant_coverage_canaries_are_present_without_public_surface_growth() {
|
||||||
|
let continuity_tests = include_str!("../unit_tests/continuity.rs");
|
||||||
|
let hardening = include_str!("hardening.rs");
|
||||||
|
let root = include_str!("../src/lib.rs");
|
||||||
|
for required in [
|
||||||
|
"pre_005_scope_relations_are_exact_superset_and_cross_family_conservative",
|
||||||
|
"pre_005_coverage_epoch_requires_distinct_source_same_commitment_and_full_range",
|
||||||
|
"pre_005_cross_family_exact_scopes_never_become_redundant_by_fingerprint_alone",
|
||||||
|
"pre_005_coverage_epoch_ledger_is_bounded_monotone_and_capability_bound",
|
||||||
|
] {
|
||||||
|
assert!(continuity_tests.contains(required), "required pre.005 continuity proof canary missing: {required}");
|
||||||
|
}
|
||||||
|
assert!(hardening.contains("v0_3_14_pre_005_redundant_coverage_requires_exact_or_superset_proof_over_full_range"));
|
||||||
|
assert!(!root.contains("pub use self::continuity::RawTransactionIngestCoverageEpoch"));
|
||||||
|
assert!(!root.contains("pub use self::continuity::RawTransactionIngestCoverageRelation"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
|
// file: crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
|
||||||
// version: 3
|
// version: 4
|
||||||
|
|
||||||
fn network() -> std::option::Option<ksp_store_lib::RawNetworkId> {
|
fn network() -> std::option::Option<ksp_store_lib::RawNetworkId> {
|
||||||
return match ksp_store_lib::RawNetworkId::new("mainnet") {
|
return match ksp_store_lib::RawNetworkId::new("mainnet") {
|
||||||
@@ -275,3 +275,181 @@ fn pre_003_websocket_incident_anchor_rejects_missing_reason_reversal_and_oversiz
|
|||||||
assert!(oversized.close_at(100 + super::MAX_RAW_TRANSACTION_INGEST_REPAIR_RANGE_SLOTS).is_err());
|
assert!(oversized.close_at(100 + super::MAX_RAW_TRANSACTION_INGEST_REPAIR_RANGE_SLOTS).is_err());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pre_005_scope_relations_are_exact_superset_and_cross_family_conservative() {
|
||||||
|
let exact = exact_scope("standard_logs", 7);
|
||||||
|
let same = exact_scope("standard_logs", 7);
|
||||||
|
let different_filter = exact_scope("standard_logs", 8);
|
||||||
|
let different_family = exact_scope("helius_transaction", 7);
|
||||||
|
let full = crate::RawTransactionIngestCoverageScope::full_ledger_transactions();
|
||||||
|
assert_eq!(exact.relation_to(&same), std::option::Option::Some(super::RawTransactionIngestCoverageRelation::Exact));
|
||||||
|
assert_eq!(full.relation_to(&exact), std::option::Option::Some(super::RawTransactionIngestCoverageRelation::Superset));
|
||||||
|
assert_eq!(full.relation_to(&full), std::option::Option::Some(super::RawTransactionIngestCoverageRelation::Exact));
|
||||||
|
assert!(exact.relation_to(&full).is_none());
|
||||||
|
assert!(exact.relation_to(&different_filter).is_none());
|
||||||
|
assert!(exact.relation_to(&different_family).is_none());
|
||||||
|
assert!(crate::RawTransactionIngestCoverageScope::KnownReferences([7_u8; 32]).relation_to(&exact).is_none());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pre_005_coverage_epoch_requires_distinct_source_same_commitment_and_full_range() {
|
||||||
|
let target_requirement = super::RawTransactionIngestCoverageRequirement {
|
||||||
|
commitment: ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
scope: exact_scope("standard_logs", 9),
|
||||||
|
};
|
||||||
|
let gap = match super::RawTransactionIngestGapRange::new(100, 110) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected gap fixture failure: {error}"),
|
||||||
|
};
|
||||||
|
let full_range = match super::RawTransactionIngestCoverageRange::new(90, 120) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected coverage range failure: {error}"),
|
||||||
|
};
|
||||||
|
let partial_range = match super::RawTransactionIngestCoverageRange::new(100, 109) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected partial coverage range failure: {error}"),
|
||||||
|
};
|
||||||
|
let exact_epoch = match super::RawTransactionIngestCoverageEpoch::new(
|
||||||
|
1,
|
||||||
|
[2_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
exact_scope("standard_logs", 9),
|
||||||
|
full_range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected exact epoch failure: {error}"),
|
||||||
|
};
|
||||||
|
let full_epoch = match super::RawTransactionIngestCoverageEpoch::new(
|
||||||
|
2,
|
||||||
|
[3_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
crate::RawTransactionIngestCoverageScope::full_ledger_transactions(),
|
||||||
|
full_range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected full epoch failure: {error}"),
|
||||||
|
};
|
||||||
|
let partial_epoch = match super::RawTransactionIngestCoverageEpoch::new(
|
||||||
|
3,
|
||||||
|
[4_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
crate::RawTransactionIngestCoverageScope::full_ledger_transactions(),
|
||||||
|
partial_range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected partial epoch failure: {error}"),
|
||||||
|
};
|
||||||
|
let finalized_epoch = match super::RawTransactionIngestCoverageEpoch::new(
|
||||||
|
4,
|
||||||
|
[5_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Finalized,
|
||||||
|
crate::RawTransactionIngestCoverageScope::full_ledger_transactions(),
|
||||||
|
full_range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected finalized epoch failure: {error}"),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
exact_epoch.relation_to_requirement([1_u8; 32], &target_requirement, gap),
|
||||||
|
std::option::Option::Some(super::RawTransactionIngestCoverageRelation::Exact),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
full_epoch.relation_to_requirement([1_u8; 32], &target_requirement, gap),
|
||||||
|
std::option::Option::Some(super::RawTransactionIngestCoverageRelation::Superset),
|
||||||
|
);
|
||||||
|
assert!(exact_epoch.relation_to_requirement([2_u8; 32], &target_requirement, gap).is_none());
|
||||||
|
assert!(partial_epoch.relation_to_requirement([1_u8; 32], &target_requirement, gap).is_none());
|
||||||
|
assert!(finalized_epoch.relation_to_requirement([1_u8; 32], &target_requirement, gap).is_none());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pre_005_cross_family_exact_scopes_never_become_redundant_by_fingerprint_alone() {
|
||||||
|
let target_requirement = super::RawTransactionIngestCoverageRequirement {
|
||||||
|
commitment: ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
scope: exact_scope("standard_logs", 11),
|
||||||
|
};
|
||||||
|
let gap = match super::RawTransactionIngestGapRange::new(500, 510) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected gap fixture failure: {error}"),
|
||||||
|
};
|
||||||
|
let range = match super::RawTransactionIngestCoverageRange::new(490, 520) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected coverage range failure: {error}"),
|
||||||
|
};
|
||||||
|
let epoch = match super::RawTransactionIngestCoverageEpoch::new(
|
||||||
|
1,
|
||||||
|
[2_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
exact_scope("helius_transaction", 11),
|
||||||
|
range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected epoch failure: {error}"),
|
||||||
|
};
|
||||||
|
assert!(epoch.relation_to_requirement([1_u8; 32], &target_requirement, gap).is_none());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn pre_005_coverage_epoch_ledger_is_bounded_monotone_and_capability_bound() {
|
||||||
|
assert_eq!(super::MAX_RAW_TRANSACTION_INGEST_COVERAGE_EPOCHS, 256);
|
||||||
|
let matching = match capability(2, ksp_onchain_transport_lib::SolanaCommitment::Confirmed, exact_scope("standard_logs", 5)) {
|
||||||
|
std::option::Option::Some(value) => value,
|
||||||
|
std::option::Option::None => panic!("matching capability fixture unavailable"),
|
||||||
|
};
|
||||||
|
let range = match super::RawTransactionIngestCoverageRange::new(100, 200) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected coverage range failure: {error}"),
|
||||||
|
};
|
||||||
|
let epoch = match super::RawTransactionIngestCoverageEpoch::new(
|
||||||
|
1,
|
||||||
|
[2_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
exact_scope("standard_logs", 5),
|
||||||
|
range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected coverage epoch failure: {error}"),
|
||||||
|
};
|
||||||
|
let valid = super::RawTransactionIngestCoverageEpochLedger { epochs: std::vec![epoch.clone()], next_epoch_id: 2 };
|
||||||
|
assert!(valid.validate_invariants(std::slice::from_ref(&matching)).is_ok());
|
||||||
|
let requirement = super::RawTransactionIngestCoverageRequirement {
|
||||||
|
commitment: ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
scope: exact_scope("standard_logs", 5),
|
||||||
|
};
|
||||||
|
let gap = match super::RawTransactionIngestGapRange::new(120, 130) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected ledger gap failure: {error}"),
|
||||||
|
};
|
||||||
|
assert_eq!(
|
||||||
|
valid.redundant_relation_for_gap([1_u8; 32], &requirement, gap),
|
||||||
|
std::option::Option::Some(super::RawTransactionIngestCoverageRelation::Exact),
|
||||||
|
);
|
||||||
|
assert!(valid.redundant_relation_for_gap([2_u8; 32], &requirement, gap).is_none());
|
||||||
|
let stale = super::RawTransactionIngestCoverageEpochLedger { epochs: std::vec![epoch.clone()], next_epoch_id: 1 };
|
||||||
|
assert!(stale.validate_invariants(std::slice::from_ref(&matching)).is_err());
|
||||||
|
let unknown = super::RawTransactionIngestCoverageEpochLedger { epochs: std::vec![epoch], next_epoch_id: 2 };
|
||||||
|
assert!(unknown.validate_invariants(&[]).is_err());
|
||||||
|
let mut too_many = std::vec::Vec::new();
|
||||||
|
for index in 0..=super::MAX_RAW_TRANSACTION_INGEST_COVERAGE_EPOCHS {
|
||||||
|
let epoch_id = (index as u64) + 1;
|
||||||
|
let epoch = match super::RawTransactionIngestCoverageEpoch::new(
|
||||||
|
epoch_id,
|
||||||
|
[2_u8; 32],
|
||||||
|
ksp_onchain_transport_lib::SolanaCommitment::Confirmed,
|
||||||
|
exact_scope("standard_logs", 5),
|
||||||
|
range,
|
||||||
|
) {
|
||||||
|
std::result::Result::Ok(value) => value,
|
||||||
|
std::result::Result::Err(error) => panic!("unexpected bounded epoch failure: {error}"),
|
||||||
|
};
|
||||||
|
too_many.push(epoch);
|
||||||
|
}
|
||||||
|
let overflow =
|
||||||
|
super::RawTransactionIngestCoverageEpochLedger { epochs: too_many, next_epoch_id: (super::MAX_RAW_TRANSACTION_INGEST_COVERAGE_EPOCHS as u64) + 2 };
|
||||||
|
assert!(overflow.validate_invariants(std::slice::from_ref(&matching)).is_err());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|||||||
320
deltas/0.3.14/pre.005.md
Normal file
320
deltas/0.3.14/pre.005.md
Normal file
@@ -0,0 +1,320 @@
|
|||||||
|
<!-- file: deltas/0.3.14/pre.005.md -->
|
||||||
|
<!-- version: 1 -->
|
||||||
|
|
||||||
|
# Delta `0.3.14-pre.005` — preuve conservative de coverage redondante
|
||||||
|
|
||||||
|
## Base requise
|
||||||
|
|
||||||
|
```text
|
||||||
|
0.3.14-pre.004
|
||||||
|
workspace.package.version = 0.3.14-pre.4
|
||||||
|
deltas/0.3.14/pre.004.md présent
|
||||||
|
```
|
||||||
|
|
||||||
|
## Gate de la base
|
||||||
|
|
||||||
|
Le gate opérateur de `0.3.14-pre.004` est validé avant ouverture de cette tranche :
|
||||||
|
|
||||||
|
```text
|
||||||
|
cargo fmt --all : PASS
|
||||||
|
cargo fmt --all -- --check : PASS
|
||||||
|
audit Rust workspace rules : PASS
|
||||||
|
audit Markdown tables : PASS
|
||||||
|
cargo check --workspace : PASS
|
||||||
|
cargo clippy --workspace --all-targets --all-features -- -D warnings : PASS
|
||||||
|
cargo test -p ksp-onchain-transport-lib --all-targets --all-features : PASS
|
||||||
|
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features : PASS
|
||||||
|
```
|
||||||
|
|
||||||
|
Le gate Transport comprend notamment :
|
||||||
|
|
||||||
|
```text
|
||||||
|
391 unit tests : PASS
|
||||||
|
public_api : 53 PASS
|
||||||
|
release_completeness : 46 PASS
|
||||||
|
smokes live : ignorés par défaut conformément au contrat existant
|
||||||
|
```
|
||||||
|
|
||||||
|
Le gate Worker comprend notamment :
|
||||||
|
|
||||||
|
```text
|
||||||
|
120 unit tests : PASS
|
||||||
|
cross_layer_completeness : 8 PASS
|
||||||
|
dependency_boundary : 19 PASS
|
||||||
|
hardening : 29 PASS
|
||||||
|
public_api : 20 PASS
|
||||||
|
release_completeness : 6 PASS
|
||||||
|
```
|
||||||
|
|
||||||
|
## Objectif
|
||||||
|
|
||||||
|
Implémenter strictement la tranche `pre.005` du plan `035` :
|
||||||
|
|
||||||
|
```text
|
||||||
|
matérialiser les relations conservative Exact / Superset
|
||||||
|
matérialiser des epochs et ranges de coverage run-local bornés
|
||||||
|
n'autoriser une preuve redondante que depuis une source distincte
|
||||||
|
exiger un commitment strictement identique
|
||||||
|
exiger que l'epoch couvre intégralement la plage du gap
|
||||||
|
interdire toute équivalence opportuniste entre familles exactes différentes
|
||||||
|
conserver KnownReferences impropre à TargetCoverage
|
||||||
|
ne modifier encore aucune décision runtime de supervisor
|
||||||
|
ne déclencher aucun repair HTTP et aucun replay supplémentaire
|
||||||
|
```
|
||||||
|
|
||||||
|
## Relations de coverage
|
||||||
|
|
||||||
|
`RawTransactionIngestCoverageScope` possède maintenant une relation privée et directionnelle :
|
||||||
|
|
||||||
|
```text
|
||||||
|
FullLedgerTransactions -> FullLedgerTransactions : Exact
|
||||||
|
FullLedgerTransactions -> ExactSourceScope(...) : Superset
|
||||||
|
ExactSourceScope(family, fingerprint)
|
||||||
|
-> ExactSourceScope(même family, même fingerprint) : Exact
|
||||||
|
autres combinaisons : aucune relation prouvée
|
||||||
|
```
|
||||||
|
|
||||||
|
Cette relation est volontairement conservative.
|
||||||
|
|
||||||
|
Deux scopes exacts qui partagent le même fingerprint mais pas le même `family_code` ne sont jamais considérés équivalents. Ainsi, par exemple, aucune correspondance `standard_logs <-> helius_transaction` ou `standard_block <-> yellowstone` n'est inventée à partir d'une similarité de sélecteur.
|
||||||
|
|
||||||
|
La relation est également indépendante de l'identité provider/endpoint : cette indépendance vient uniquement du scope sémantique déjà normalisé, tandis que l'obligation de redondance exige une `source_key` différente.
|
||||||
|
|
||||||
|
## Commitments
|
||||||
|
|
||||||
|
La redondance requiert un commitment strictement identique :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Confirmed couvre seulement Confirmed
|
||||||
|
Finalized couvre seulement Finalized
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucune hiérarchie `Confirmed <-> Finalized` n'est inférée dans cette tranche.
|
||||||
|
|
||||||
|
## TargetCoverage
|
||||||
|
|
||||||
|
La construction de `RawTransactionIngestTargetCoverage` réutilise désormais la relation conservative plutôt qu'une comparaison ad hoc :
|
||||||
|
|
||||||
|
```text
|
||||||
|
un FullLedgerTransactions au même commitment subsume les requirements exacts
|
||||||
|
un requirement exact identique est dédupliqué
|
||||||
|
un scope exact cross-family reste distinct
|
||||||
|
un commitment différent reste distinct
|
||||||
|
KnownReferences reste interdit comme target scope
|
||||||
|
```
|
||||||
|
|
||||||
|
Aucune broadening cross-family n'est introduite.
|
||||||
|
|
||||||
|
## Epochs et ranges de coverage
|
||||||
|
|
||||||
|
La tranche matérialise des contrats privés :
|
||||||
|
|
||||||
|
```text
|
||||||
|
RawTransactionIngestCoverageRange
|
||||||
|
RawTransactionIngestCoverageEpoch
|
||||||
|
RawTransactionIngestCoverageEpochLedger
|
||||||
|
RawTransactionIngestCoverageRelation
|
||||||
|
```
|
||||||
|
|
||||||
|
Un `CoverageRange` est inclusif et rejette uniquement une plage inversée. Contrairement au `GapRange`, il n'est pas limité artificiellement à `MAX_RAW_TRANSACTION_INGEST_REPAIR_RANGE_SLOTS`, car un epoch de continuité saine peut être plus long qu'une seule obligation de repair.
|
||||||
|
|
||||||
|
Un epoch conserve :
|
||||||
|
|
||||||
|
```text
|
||||||
|
epoch_id
|
||||||
|
source_key
|
||||||
|
commitment
|
||||||
|
scope
|
||||||
|
range inclusif
|
||||||
|
```
|
||||||
|
|
||||||
|
Le ledger est run-local et borné à :
|
||||||
|
|
||||||
|
```text
|
||||||
|
MAX_RAW_TRANSACTION_INGEST_COVERAGE_EPOCHS = 256
|
||||||
|
```
|
||||||
|
|
||||||
|
Il vérifie :
|
||||||
|
|
||||||
|
```text
|
||||||
|
IDs non nuls et uniques
|
||||||
|
next_epoch_id strictement monotone
|
||||||
|
borne de cardinalité
|
||||||
|
range valide
|
||||||
|
scope admissible comme configured target scope
|
||||||
|
source_key présente dans l'inventaire exact des capabilities
|
||||||
|
commitment et scope strictement identiques à la capability de cette source
|
||||||
|
```
|
||||||
|
|
||||||
|
Le ledger est initialisé vide avec les autres continuity contracts. Aucune coverage n'est pré-déclarée à partir de la simple configuration d'une source.
|
||||||
|
|
||||||
|
## Preuve de redondance
|
||||||
|
|
||||||
|
Un epoch peut prouver une obligation uniquement si toutes les conditions suivantes sont vraies :
|
||||||
|
|
||||||
|
```text
|
||||||
|
source de preuve != source cible
|
||||||
|
commitment de preuve == commitment requis
|
||||||
|
range de preuve contient intégralement le GapRange inclusif
|
||||||
|
scope de preuve relation Exact ou Superset avec le scope requis
|
||||||
|
```
|
||||||
|
|
||||||
|
Un epoch partiel, une source identique, un commitment différent, un filtre différent ou une famille différente ne ferment donc aucune obligation.
|
||||||
|
|
||||||
|
`FullLedgerTransactions` peut fournir une preuve `Superset` d'un scope exact au même commitment, parce qu'il représente toutes les transactions de tous les blocs produits. L'inverse est interdit.
|
||||||
|
|
||||||
|
## Activation runtime
|
||||||
|
|
||||||
|
Cette tranche ne change pas encore la politique de source-loss/reconciliation :
|
||||||
|
|
||||||
|
```text
|
||||||
|
aucun gap n'est fermé automatiquement
|
||||||
|
aucune source n'est maintenue en vie grâce à cette preuve
|
||||||
|
aucune terminalité fail-closed de pre.003/pre.004 n'est encore remplacée
|
||||||
|
```
|
||||||
|
|
||||||
|
`pre.008` restera responsable de l'intégration de ces preuves dans le supervisor et le gap ledger. `pre.005` fournit uniquement le modèle conservative nécessaire.
|
||||||
|
|
||||||
|
## Tests ajoutés
|
||||||
|
|
||||||
|
Les unit tests Worker couvrent :
|
||||||
|
|
||||||
|
```text
|
||||||
|
Exact pour même famille + même fingerprint
|
||||||
|
Superset uniquement FullLedger -> exact
|
||||||
|
absence de relation exact -> FullLedger
|
||||||
|
absence de relation pour filtre exact différent
|
||||||
|
absence de relation cross-family malgré fingerprint identique
|
||||||
|
source distincte obligatoire
|
||||||
|
commitment strictement identique
|
||||||
|
range complet obligatoire
|
||||||
|
ledger borné à 256 epochs
|
||||||
|
next_epoch_id monotone
|
||||||
|
capability source/scope/commitment obligatoire
|
||||||
|
```
|
||||||
|
|
||||||
|
Les canaris `hardening` et `release_completeness` garantissent en plus :
|
||||||
|
|
||||||
|
```text
|
||||||
|
présence des contrats Exact/Superset/epoch
|
||||||
|
absence d'équivalence cross-family codée en dur
|
||||||
|
absence de hiérarchie opportuniste de commitment
|
||||||
|
absence d'exposition publique des nouveaux types de preuve
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fichiers ajoutés
|
||||||
|
|
||||||
|
```text
|
||||||
|
deltas/0.3.14/pre.005.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fichiers modifiés
|
||||||
|
|
||||||
|
```text
|
||||||
|
Cargo.toml
|
||||||
|
crates/ksp-worker-raw-transaction-ingest-lib/src/continuity.rs
|
||||||
|
crates/ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs
|
||||||
|
crates/ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs
|
||||||
|
crates/ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs
|
||||||
|
```
|
||||||
|
|
||||||
|
## Fichiers supprimés
|
||||||
|
|
||||||
|
```text
|
||||||
|
aucun
|
||||||
|
```
|
||||||
|
|
||||||
|
## Version Cargo
|
||||||
|
|
||||||
|
Conformément à `VER-ID-009`, cette nouvelle prerelease synchronise la version workspace :
|
||||||
|
|
||||||
|
```text
|
||||||
|
header Cargo.toml : 571 -> 572
|
||||||
|
workspace.package.version : 0.3.14-pre.4 -> 0.3.14-pre.5
|
||||||
|
```
|
||||||
|
|
||||||
|
Versions des fichiers modifiés :
|
||||||
|
|
||||||
|
```text
|
||||||
|
ksp-worker-raw-transaction-ingest-lib/src/continuity.rs : 4 -> 5
|
||||||
|
ksp-worker-raw-transaction-ingest-lib/tests/hardening.rs : 28 -> 29
|
||||||
|
ksp-worker-raw-transaction-ingest-lib/tests/release_completeness.rs : 23 -> 24
|
||||||
|
ksp-worker-raw-transaction-ingest-lib/unit_tests/continuity.rs : 3 -> 4
|
||||||
|
```
|
||||||
|
|
||||||
|
## Frontières préservées
|
||||||
|
|
||||||
|
```text
|
||||||
|
aucun changement Transport
|
||||||
|
aucun changement Config
|
||||||
|
aucun changement Store
|
||||||
|
aucun changement Job Backfill
|
||||||
|
aucune nouvelle dépendance
|
||||||
|
aucune nouvelle feature
|
||||||
|
aucun repair HTTP
|
||||||
|
aucun replay Worker
|
||||||
|
aucun nouveau socket/actor/retry
|
||||||
|
aucun set_from_slot dans Worker
|
||||||
|
aucune nouvelle surface publique Worker
|
||||||
|
aucune équivalence cross-family opportuniste
|
||||||
|
aucune hiérarchie implicite de commitment
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validations exécutées dans le sandbox de préparation
|
||||||
|
|
||||||
|
```text
|
||||||
|
python3 scripts/audit_rust_workspace_rules.py
|
||||||
|
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
|
||||||
|
scan des frontières et de la surface crate-root Worker
|
||||||
|
comparaison exacte 0.3.14-pre.004 -> 0.3.14-pre.005
|
||||||
|
contrôle des versions de fichiers modifiés
|
||||||
|
contrôle du contenu de l'archive delta
|
||||||
|
unzip -t de l'archive delta
|
||||||
|
réapplication de l'archive sur la base puis comparaison byte-exacte
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validations non exécutées dans le sandbox de préparation
|
||||||
|
|
||||||
|
Le sandbox ne fournit pas le toolchain Cargo/Rust. Les gates suivants restent à exécuter côté opérateur :
|
||||||
|
|
||||||
|
```text
|
||||||
|
cargo fmt --all
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
cargo check --workspace
|
||||||
|
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||||
|
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features
|
||||||
|
```
|
||||||
|
|
||||||
|
## Décisions prises
|
||||||
|
|
||||||
|
```text
|
||||||
|
coverage relationnelle directionnelle, jamais symétrisée implicitement
|
||||||
|
FullLedger est un superset d'un exact scope au même commitment
|
||||||
|
un exact scope n'est équivalent qu'à même family + même fingerprint
|
||||||
|
une redondance doit provenir d'une source_key distincte
|
||||||
|
un epoch doit contenir toute la plage du gap
|
||||||
|
aucune coverage initiale n'est créée depuis la configuration seule
|
||||||
|
pre.005 ne modifie pas encore la terminalité runtime
|
||||||
|
```
|
||||||
|
|
||||||
|
## Questions ouvertes
|
||||||
|
|
||||||
|
```text
|
||||||
|
aucune pour pre.005
|
||||||
|
```
|
||||||
|
|
||||||
|
## Tranche suivante
|
||||||
|
|
||||||
|
`pre.006` reste dédiée au scan HTTP de réparation : détection des capabilities run-wide réellement disponibles, fenêtres bornées, découverte `getBlocks`/`getBlocksWithLimit` conservative et récupération `getBlock observed`, sans broadening de scope.
|
||||||
|
|
||||||
|
## Gate opérateur après application
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cargo fmt --all
|
||||||
|
cargo fmt --all -- --check
|
||||||
|
python3 scripts/audit_rust_workspace_rules.py
|
||||||
|
python3 scripts/audit_markdown_tables.py README.md RULES.md ROADMAP.md CHANGELOG.md docs prompts crates deltas
|
||||||
|
cargo check --workspace
|
||||||
|
cargo clippy --workspace --all-targets --all-features -- -D warnings
|
||||||
|
cargo test -p ksp-worker-raw-transaction-ingest-lib --all-targets --all-features
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user