diff --git a/crates/epiphany-core/src/codec.rs b/crates/epiphany-core/src/codec.rs index c423f38..3012b1d 100644 --- a/crates/epiphany-core/src/codec.rs +++ b/crates/epiphany-core/src/codec.rs @@ -3430,8 +3430,13 @@ fn decode_v2_score(bytes: &[u8]) -> Result { /// inherits core's conventions exactly, so core/ops stay consistent. See /// `DECISIONS.md` (P11-4 / the K↔J seam). /// -/// Implemented only for the value types operation payloads embed, not for every -/// `Codec` type, to keep the public surface intentional. +/// Implemented for the value types operation payloads embed, and — since +/// `spec/CONTRACT_CORE_DECODE_VECTORS.md` — for the value types the +/// cross-implementation decode-vector corpus (`crate::vectors`) pins: the +/// representative layouts of the Binary Format companion's +/// §"Representative Complete Layouts" and the schema-major-3 tuning-context +/// leaves. Not for every `Codec` type, to keep the public surface intentional; +/// the intent has simply widened to a second reason. pub trait CanonicalValue: Sized { /// The canonical bytes of this single value, using the same layout the /// whole-score codec uses for it. @@ -3508,6 +3513,19 @@ canonical_value! { // Repeat authoring (schema-major-2 revision) — CreateRepeatStructure // embeds the full value. RepeatStructure, + // Decode-vector corpus (`spec/CONTRACT_CORE_DECODE_VECTORS.md`): the fifth + // representative layout (`RationalTime` — the other four, `Pitch`, + // `TimeAnchor`, `Event`, `Slur`, are already above), plus the + // schema-major-3 tuning-context container and its four leaf types, frozen + // by Push 4b tranche 3b-i. None of these gain a byte layout here — every + // one already has a `Codec` impl the whole-score codec uses; this macro + // only makes that existing layout reachable per-value. + RationalTime, + ScoreTuningContext, + TuningOverride, + TuningScope, + SmuflVersionRequirement, + SmuflVersion, } #[cfg(test)] diff --git a/crates/epiphany-core/src/lib.rs b/crates/epiphany-core/src/lib.rs index 522b52d..da1d135 100644 --- a/crates/epiphany-core/src/lib.rs +++ b/crates/epiphany-core/src/lib.rs @@ -89,6 +89,7 @@ pub mod fuzz; pub mod generators; pub mod prepass; pub mod textvalue; +pub mod vectors; pub use ids::{ derive_system_id, AnalysisLayerId, AnalyticalAnnotationId, BarlineAlignmentGroupId, BeamId, diff --git a/crates/epiphany-core/src/vectors.rs b/crates/epiphany-core/src/vectors.rs new file mode 100644 index 0000000..d2f9569 --- /dev/null +++ b/crates/epiphany-core/src/vectors.rs @@ -0,0 +1,571 @@ +//! Decode conformance vectors for the `epiphany-core` score wire +//! (`spec/CONTRACT_CORE_DECODE_VECTORS.md`). +//! +//! See `epiphany_ops::vectors` for the corpus's purpose, its column shape, and +//! why `accept`/`reject` are never collapsed. This module extends the same +//! committed, cross-implementation corpus to the *oldest and most load-bearing* +//! wire format in the repository — the whole-`Score` codec — which had no +//! literal-byte vectors at all before this tranche (only round-trip locking, +//! which cannot see a self-consistent field reordering: see +//! `schema_major_3_tuning_context_wire_bytes_are_frozen` in `codec.rs`, and the +//! contract's account of the tranche-3b-i defect it golden-pins). +//! +//! Two families of surface: +//! +//! * **Leaves** — one per [`CanonicalValue`] type the corpus pins: the five +//! representative layouts of the Binary Format companion +//! (§"Representative Complete Layouts") — [`RationalTime`], [`TimeAnchor`], +//! [`Pitch`], [`Event`], [`Slur`] — plus the four schema-major-3 +//! tuning-context leaves ([`SmuflVersion`], [`SmuflVersionRequirement`], +//! [`TuningScope`], [`TuningOverride`]) and their container +//! ([`ScoreTuningContext`]). Every leaf routes through +//! [`CanonicalValue::decode_canonical`] — the same public, production API a +//! value-typed operation payload uses — never a decoder reimplemented here. +//! * **Whole `Score`, one per schema major** — `core.score_v0` through +//! `core.score_v3`, routed through [`Score::decode_canonical_versioned`]. +//! Majors 0–2 are **not** literal-byte-locked at the *current* layout: a +//! migration deliberately rewrites bytes (that is the point of +//! default-filling), so injectivity there means the input was already +//! canonical *at its own major* — `decode_vN_score` re-encodes through the +//! frozen `encode_vN_score` and rejects a mismatch, so a successful decode +//! already proves that. Only `core.score_v3` compares +//! `decoded.canonical_bytes() == bytes`. See the contract's "trap" section; +//! getting this backwards (comparing v0–v2 against the *current* encoding) +//! would fail on every vector, and "fixing" it by relaxing the check would +//! destroy what the vector pins. + +use epiphany_determinism::CanonicalF64; + +use crate::accidental::{SmuflVersion, SmuflVersionRequirement}; +use crate::codec::Codec; +use crate::event::{Event, PitchedEvent, StemConfiguration}; +use crate::graph::{ScoreTuningContext, Slur, SlurKind, SpanStyle}; +use crate::ids::{EventId, PitchId, ReplicaId, SlurId, VoiceId}; +use crate::pitch::{ + AcousticPitch, AcousticRealization, CmnNominal, IdentifiedPitch, Pitch, PitchSpaceId, + PitchSpacePosition, ScalePosition, TuningReference, TuningSystemId, +}; +use crate::time::{ + AnchorOffset, EventDuration, EventPosition, MusicalDuration, MusicalPosition, RationalTime, + TimeAnchor, +}; +use crate::tuning::{TuningOverride, TuningScope}; +use crate::{CanonicalValue, Score}; + +/// One vector: `(surface, verdict, class, name, bytes)`. See +/// `epiphany_ops::vectors::DecodeVector`. +pub type DecodeVector = (&'static str, &'static str, &'static str, String, Vec); + +fn row( + surface: &'static str, + verdict: &'static str, + class: &'static str, + name: impl Into, + bytes: Vec, +) -> DecodeVector { + (surface, verdict, class, name.into(), bytes) +} + +// =========================================================================== +// Shared fixture values. +// =========================================================================== + +/// A `cmn-12` pitch with an explicit cents-offset realization, so its +/// canonical bytes end in a length-prefixed [`CanonicalF64`] leaf (the last +/// 8 bytes are the raw IEEE-754 payload) — what the `core.pitch` reject vector +/// corrupts to a non-finite value. +fn pitch_with_cents(cents: f64) -> Pitch { + Pitch { + scale_position: ScalePosition { + space: PitchSpaceId::new("cmn-12"), + position: PitchSpacePosition::Cmn { + nominal: CmnNominal::C, + alteration: 0, + octave: 4, + }, + }, + acoustic: AcousticPitch { + tuning: TuningReference::Inherit, + realization: AcousticRealization::CentsOffset( + CanonicalF64::new(cents).expect("finite"), + ), + }, + } +} + +fn simple_event() -> Event { + Event::Pitched(PitchedEvent { + id: EventId::new(ReplicaId(1), 1), + voice: VoiceId::new(ReplicaId(1), 1), + position: EventPosition::Musical(MusicalPosition(RationalTime::zero())), + duration: EventDuration::Musical(MusicalDuration(RationalTime::new(1, 4).unwrap())), + pitches: vec![IdentifiedPitch { + id: PitchId::new(ReplicaId(1), 1), + pitch: pitch_with_cents(0.0), + }], + articulations: vec![], + dynamic: None, + ornaments: vec![], + stem: StemConfiguration, + grace: None, + }) +} + +fn simple_slur() -> Slur { + Slur { + id: SlurId::new(ReplicaId(1), 1), + start_event: EventId::new(ReplicaId(1), 1), + end_event: EventId::new(ReplicaId(1), 2), + kind: SlurKind::default(), + curvature_override: None, + style: SpanStyle::default(), + } +} + +/// The one `TuningOverride` embedded in [`loaded_tuning_context`]: a per-voice +/// override that sets `tuning_system` only, leaving `pitch_space` and +/// `reference` inherited — mirrors +/// `schema_major_3_tuning_context_wire_bytes_are_frozen`'s fixture exactly +/// (same field values), so these bytes are known-frozen wire content, not a +/// fresh layout. +fn one_override() -> TuningOverride { + TuningOverride { + scope: TuningScope::Voice(VoiceId::new(ReplicaId(1), 7)), + pitch_space: None, + tuning_system: Some(TuningSystemId::new("tet-19")), + reference: None, + } +} + +/// A non-default `ScoreTuningContext`: `smufl` at 1.12/1.18 (not the 1.4/1.4 +/// default) and one override, so both major-3 fields are real content, not +/// vacuously-default padding. Same fixture as +/// `schema_major_3_tuning_context_wire_bytes_are_frozen`. +fn loaded_tuning_context() -> ScoreTuningContext { + let mut ctx = ScoreTuningContext { + smufl: SmuflVersionRequirement { + minimum: SmuflVersion::from_decimal(1, "12").unwrap(), + authored_against: SmuflVersion::from_decimal(1, "18").unwrap(), + }, + ..ScoreTuningContext::default() + }; + ctx.overrides.push(one_override()); + ctx +} + +/// Encodes `ctx` with `overrides` written *before* `smufl` — the exact +/// regression this tranche exists to catch (Push 4b tranche 3b-i swapped +/// these two fields in both halves of `impl Codec for ScoreTuningContext`, +/// and the whole workspace suite plus 8/8 conformance still passed). The +/// frozen field order is `default_pitch_space` ⌢ `default_tuning_system` ⌢ +/// `reference` ⌢ `smufl` ⌢ `overrides`; this swaps the last two. +fn score_tuning_context_bytes_with_fields_swapped(ctx: &ScoreTuningContext) -> Vec { + let mut out = Vec::new(); + ctx.default_pitch_space.enc(&mut out); + ctx.default_tuning_system.enc(&mut out); + ctx.reference.enc(&mut out); + ctx.overrides.enc(&mut out); + ctx.smufl.enc(&mut out); + out +} + +/// Hand-encodes the *unreduced* rational `2/4`: there is no public +/// constructor that skips [`RationalTime`]'s reduce-on-construct invariant +/// (every constructor re-establishes it), so the only way to produce +/// non-canonical bytes for this leaf is to write them by hand, mirroring +/// [`RationalTime`]'s own `CanonicalEncode` (`time.rs`): a sign byte, then a +/// length-prefixed big-endian numerator magnitude, then a length-prefixed +/// big-endian denominator magnitude — wrapped in the outer `u32` leaf-length +/// prefix every embedded leaf carries. Decoding reduces `2/4` to `1/2`, so the +/// re-encoded bytes differ from these: the lenient-leaf-normalization case the +/// fifth representative layout exists to demonstrate (a guard *can* mask a +/// lenient inner codec; here the leaf's own strict check catches it directly). +fn unreduced_two_fourths() -> Vec { + let mut inner = Vec::new(); + inner.push(1); // sign: Plus + inner.extend_from_slice(&1u32.to_le_bytes()); // numerator magnitude length + inner.push(2); // numerator magnitude: 2 + inner.extend_from_slice(&1u32.to_le_bytes()); // denominator magnitude length + inner.push(4); // denominator magnitude: 4 + let mut out = Vec::new(); + out.extend_from_slice(&(inner.len() as u32).to_le_bytes()); // outer leaf length prefix + out.extend_from_slice(&inner); + out +} + +/// Corrupts a tagged union's leading discriminant byte to a value one past +/// every assigned tag, so the decoder's `match` falls through to its +/// `InvalidTag` arm regardless of which union this is. +fn with_invalid_leading_tag(bytes: &[u8], tag: u8) -> Vec { + let mut out = bytes.to_vec(); + out[0] = tag; + out +} + +/// Overwrites the trailing 8 bytes of an accept vector's bytes — the raw +/// IEEE-754 payload of a trailing [`CanonicalF64`] leaf (its 4-byte length +/// prefix precedes them) — with a non-finite bit pattern. +fn with_trailing_float_replaced(bytes: &[u8], value: f64) -> Vec { + let mut out = bytes.to_vec(); + let n = out.len(); + out[n - 8..].copy_from_slice(&value.to_le_bytes()); + out +} + +fn with_trailing_byte(bytes: &[u8]) -> Vec { + let mut out = bytes.to_vec(); + out.push(0); + out +} + +fn truncated(bytes: &[u8]) -> Vec { + let mut out = bytes.to_vec(); + out.pop(); + out +} + +// =========================================================================== +// The vectors. +// =========================================================================== + +/// Every `epiphany-core` decode vector: the leaf layouts, then the per-major +/// whole-`Score` snapshots. +pub fn decode_vectors() -> Vec { + let mut v: Vec = Vec::new(); + + // --- RationalTime (the fifth representative layout) -------------------- + const RT: &str = "core.rational_time"; + let eighth = RationalTime::new(1, 8).unwrap(); + v.push(row( + RT, + "accept", + "-", + "one_eighth", + eighth.canonical_bytes(), + )); + v.push(row( + RT, + "reject", + "unreduced-rational-time", + "two_fourths_unreduced", + unreduced_two_fourths(), + )); + + // --- TimeAnchor ---------------------------------------------------------- + const TA: &str = "core.time_anchor"; + let anchor = TimeAnchor::Event { + id: EventId::new(ReplicaId(1), 1), + offset: AnchorOffset::Musical(MusicalDuration(RationalTime::new(1, 4).unwrap())), + }; + let anchor_bytes = anchor.canonical_bytes(); + v.push(row(TA, "accept", "-", "event_anchor", anchor_bytes.clone())); + v.push(row( + TA, + "reject", + "out-of-range-discriminant", + "tag_9_one_past_the_vocabulary", + with_invalid_leading_tag(&anchor_bytes, 9), + )); + + // --- Pitch --------------------------------------------------------------- + const PITCH: &str = "core.pitch"; + let pitch_bytes = pitch_with_cents(1.5).canonical_bytes(); + v.push(row( + PITCH, + "accept", + "-", + "cents_offset", + pitch_bytes.clone(), + )); + v.push(row( + PITCH, + "reject", + "non-finite-float", + "cents_offset_nan", + with_trailing_float_replaced(&pitch_bytes, f64::NAN), + )); + + // --- Event ----------------------------------------------------------------- + const EVENT: &str = "core.event"; + let event_bytes = simple_event().canonical_bytes(); + v.push(row( + EVENT, + "accept", + "-", + "pitched_event", + event_bytes.clone(), + )); + v.push(row( + EVENT, + "reject", + "trailing-bytes", + "pitched_event_trailing", + with_trailing_byte(&event_bytes), + )); + + // --- Slur -------------------------------------------------------------- + const SLUR: &str = "core.slur"; + let slur_bytes = simple_slur().canonical_bytes(); + v.push(row(SLUR, "accept", "-", "simple_slur", slur_bytes.clone())); + v.push(row( + SLUR, + "reject", + "truncated", + "simple_slur_truncated", + truncated(&slur_bytes), + )); + + // --- ScoreTuningContext (schema major 3) -------------------------------- + const STC: &str = "core.score_tuning_context"; + let ctx = loaded_tuning_context(); + let ctx_bytes = ctx.canonical_bytes(); + v.push(row(STC, "accept", "-", "loaded_context", ctx_bytes)); + // THE direct regression vector for the 3b-i defect: bytes with `overrides` + // written before `smufl` must be rejected by the (correctly-ordered) + // decoder, even though a self-consistently-reordered codec would accept + // its own output. This is what a byte-literal corpus catches that + // round-trip locking cannot (see the module doc). + v.push(row( + STC, + "reject", + "swapped-major-3-field-order", + "overrides_before_smufl", + score_tuning_context_bytes_with_fields_swapped(&ctx), + )); + + // --- TuningOverride ------------------------------------------------------ + const TO: &str = "core.tuning_override"; + let override_bytes = one_override().canonical_bytes(); + v.push(row( + TO, + "accept", + "-", + "voice_scoped", + override_bytes.clone(), + )); + v.push(row( + TO, + "reject", + "trailing-bytes", + "voice_scoped_trailing", + with_trailing_byte(&override_bytes), + )); + + // --- TuningScope --------------------------------------------------------- + const TS: &str = "core.tuning_scope"; + let scope_bytes = TuningScope::Voice(VoiceId::new(ReplicaId(1), 7)).canonical_bytes(); + v.push(row(TS, "accept", "-", "voice", scope_bytes.clone())); + v.push(row( + TS, + "reject", + "out-of-range-discriminant", + "tag_9_one_past_the_vocabulary", + with_invalid_leading_tag(&scope_bytes, 9), + )); + + // --- SmuflVersionRequirement ----------------------------------------------- + const SVR: &str = "core.smufl_version_requirement"; + let svr_bytes = SmuflVersionRequirement { + minimum: SmuflVersion::from_decimal(1, "12").unwrap(), + authored_against: SmuflVersion::from_decimal(1, "18").unwrap(), + } + .canonical_bytes(); + v.push(row( + SVR, + "accept", + "-", + "one_twelve_one_eighteen", + svr_bytes.clone(), + )); + v.push(row( + SVR, + "reject", + "trailing-bytes", + "one_twelve_one_eighteen_trailing", + with_trailing_byte(&svr_bytes), + )); + + // --- SmuflVersion -------------------------------------------------------- + const SV: &str = "core.smufl_version"; + let sv_bytes = SmuflVersion::from_decimal(1, "4") + .unwrap() + .canonical_bytes(); + v.push(row(SV, "accept", "-", "one_four", sv_bytes.clone())); + v.push(row( + SV, + "reject", + "truncated", + "one_four_truncated", + truncated(&sv_bytes), + )); + + // --- Whole Score, one per schema major ----------------------------------- + // + // A single, real, well-formed `Score` (the positive generator's output — + // migration-safe: its schema-major-1/2/3 fields all sit at their canonical + // defaults, exactly what `valid_score`'s existing migration tests already + // rely on), encoded through each frozen per-major encoder. Majors 0-2 are + // genuinely *older* wire forms of the same value, synthesized via the + // pub(crate) `encode_vN_score` mirrors (never a fresh hand-rolled layout); + // major 3 is the live `canonical_bytes()`. + let score = crate::generators::valid_score(7); + let v0 = crate::codec::encode_v0_score(&score); + let v1 = crate::codec::encode_v1_score(&score); + let v2 = crate::codec::encode_v2_score(&score); + let v3 = score.canonical_bytes(); + + const SV0: &str = "core.score_v0"; + v.push(row(SV0, "accept", "-", "valid_score_seed_7", v0.clone())); + v.push(row( + SV0, + "reject", + "trailing-bytes", + "valid_score_seed_7_trailing", + with_trailing_byte(&v0), + )); + + const SV1: &str = "core.score_v1"; + v.push(row(SV1, "accept", "-", "valid_score_seed_7", v1.clone())); + v.push(row( + SV1, + "reject", + "trailing-bytes", + "valid_score_seed_7_trailing", + with_trailing_byte(&v1), + )); + + const SV2: &str = "core.score_v2"; + v.push(row(SV2, "accept", "-", "valid_score_seed_7", v2.clone())); + v.push(row( + SV2, + "reject", + "trailing-bytes", + "valid_score_seed_7_trailing", + with_trailing_byte(&v2), + )); + + const SV3: &str = "core.score_v3"; + v.push(row(SV3, "accept", "-", "valid_score_seed_7", v3.clone())); + v.push(row( + SV3, + "reject", + "trailing-bytes", + "valid_score_seed_7_trailing", + with_trailing_byte(&v3), + )); + + v +} + +// =========================================================================== +// Verification. +// =========================================================================== + +/// Runs `T`'s [`CanonicalValue::decode_canonical`] — the same public, +/// production API a value-typed operation payload decodes through — never a +/// decoder reimplemented in this module. +fn leaf_check(bytes: &[u8]) -> Result { + match T::decode_canonical(bytes) { + Ok(v) => Ok(v.canonical_bytes() == bytes), + Err(e) => Err(format!("{e}")), + } +} + +/// Runs [`Score::decode_canonical_versioned`] at `major`. Majors 0-2 report +/// injectivity as `true` unconditionally on a successful decode: migration +/// deliberately rewrites the bytes (default-filling new fields), so comparing +/// against the *current* `canonical_bytes()` would fail on every vector, and +/// `decode_vN_score`'s own re-encode-through-`encode_vN_score` guard already +/// proved the input canonical at *its own* major before returning `Ok` at all +/// (see the module doc's account of the contract's "trap"). Only major 3 +/// compares `decoded.canonical_bytes() == bytes` — the live layout, where that +/// comparison is exactly what injectivity means. +fn score_check(bytes: &[u8], major: u16) -> Result { + match Score::decode_canonical_versioned(bytes, major) { + Ok(decoded) => { + if major == 3 { + Ok(decoded.canonical_bytes() == bytes) + } else { + Ok(true) + } + } + Err(e) => Err(format!("{e}")), + } +} + +/// Applies `surface`'s decoder to `bytes`. See `epiphany_ops::vectors::check` +/// for the exact `Ok`/`Err` semantics. `None` when the surface is not owned by +/// this crate. +pub fn check(surface: &str, bytes: &[u8]) -> Option> { + match surface { + "core.rational_time" => Some(leaf_check::(bytes)), + "core.time_anchor" => Some(leaf_check::(bytes)), + "core.pitch" => Some(leaf_check::(bytes)), + "core.event" => Some(leaf_check::(bytes)), + "core.slur" => Some(leaf_check::(bytes)), + "core.score_tuning_context" => Some(leaf_check::(bytes)), + "core.tuning_override" => Some(leaf_check::(bytes)), + "core.tuning_scope" => Some(leaf_check::(bytes)), + "core.smufl_version_requirement" => Some(leaf_check::(bytes)), + "core.smufl_version" => Some(leaf_check::(bytes)), + "core.score_v0" => Some(score_check(bytes, 0)), + "core.score_v1" => Some(score_check(bytes, 1)), + "core.score_v2" => Some(score_check(bytes, 2)), + "core.score_v3" => Some(score_check(bytes, 3)), + _ => None, + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Each vector must get the verdict it declares — see + /// `epiphany_ops::vectors::tests::every_vector_gets_its_declared_verdict`. + #[test] + fn every_vector_gets_its_declared_verdict() { + for (surface, verdict, class, name, bytes) in decode_vectors() { + let result = check(surface, &bytes).expect("a surface this crate owns"); + match (verdict, &result) { + ("accept", Ok(true)) => {} + ("accept", Ok(false)) => { + panic!("{surface}/{name}: accepted but does not re-encode to its bytes") + } + ("reject", Err(_)) => {} + _ => panic!("{surface}/{name} ({class}): declared {verdict}, got {result:?}"), + } + } + } + + /// Every surface carries both verdicts, or the corpus pins half a + /// contract. + #[test] + fn every_surface_carries_both_verdicts() { + use std::collections::BTreeMap; + let mut seen: BTreeMap<&str, (bool, bool)> = BTreeMap::new(); + for (surface, verdict, ..) in decode_vectors() { + let e = seen.entry(surface).or_default(); + match verdict { + "accept" => e.0 = true, + "reject" => e.1 = true, + other => panic!("unknown verdict {other}"), + } + } + assert_eq!(seen.len(), 14, "surfaces: {:?}", seen.keys()); + for (surface, (accept, reject)) in seen { + assert!(accept, "{surface} has no accept vector"); + assert!(reject, "{surface} has no reject vector"); + } + } + + /// The mandatory regression vector for the 3b-i defect is present: it is + /// what makes this tranche's existence justified (see the module doc). + #[test] + fn the_3b_i_regression_vector_is_present() { + assert!(decode_vectors() + .iter() + .any(|(s, v, c, ..)| *s == "core.score_tuning_context" + && *v == "reject" + && *c == "swapped-major-3-field-order")); + } +} diff --git a/crates/epiphany-testkit/src/vectors.rs b/crates/epiphany-testkit/src/vectors.rs index 71e5354..0b3a944 100644 --- a/crates/epiphany-testkit/src/vectors.rs +++ b/crates/epiphany-testkit/src/vectors.rs @@ -74,7 +74,13 @@ fn from_hex(s: &str) -> Option> { .collect() } -/// Every vector, in a stable order: the operation layer, then the bundle wire. +/// Every vector, in a stable order: the operation layer, then the bundle wire, +/// then (last) the core score wire. Core is appended last deliberately: it +/// keeps the regenerated corpus diff purely additive when this surface first +/// lands, which is itself the proof that no existing vector's bytes moved — +/// i.e. that adding the core surfaces changed no existing wire form. A +/// nicer-looking dependency order (core before ops) would move all the +/// pre-existing lines and destroy that property. fn all() -> Vec<(String, String, String, String, Vec)> { let ops = epiphany_ops::vectors::decode_vectors() .into_iter() @@ -98,7 +104,18 @@ fn all() -> Vec<(String, String, String, String, Vec)> { b, ) }); - ops.chain(bundle).collect() + let core = epiphany_core::vectors::decode_vectors() + .into_iter() + .map(|(s, v, c, n, b)| { + ( + s.to_string(), + v.to_string(), + c.to_string(), + n.to_string(), + b, + ) + }); + ops.chain(bundle).chain(core).collect() } /// Renders the corpus file. @@ -163,7 +180,8 @@ pub fn verify(text: &str) -> Result> { let mut failures = Vec::new(); for row in &rows { let result = epiphany_ops::vectors::check(&row.surface, &row.bytes) - .or_else(|| epiphany_bundle::vectors::check(&row.surface, &row.bytes)); + .or_else(|| epiphany_bundle::vectors::check(&row.surface, &row.bytes)) + .or_else(|| epiphany_core::vectors::check(&row.surface, &row.bytes)); let Some(result) = result else { failures.push(format!("{}: no decoder owns this surface", row.surface)); continue; diff --git a/spec/CONTRACT_CORE_DECODE_VECTORS.md b/spec/CONTRACT_CORE_DECODE_VECTORS.md new file mode 100644 index 0000000..e3733e3 --- /dev/null +++ b/spec/CONTRACT_CORE_DECODE_VECTORS.md @@ -0,0 +1,208 @@ +# CONTRACT — the core decode-vector surface + +**Status:** dispatch-ready. Delivers the future revision the Binary Format +companion already prescribes (`binary_format.tex:3294-3296`) and closes the gap +found empirically in Push 4b tranche 3b-i. + +**Ratified by the user 2026-07-23:** +1. **Coverage** — the spec's five representative layouts, **plus** the + schema-major-3 tuning-context types, **plus** one whole-`Score` vector at each + schema major 0/1/2/3. +2. **Strictness** — `check()` calls **genuine public core API**, not a + harness-side wrapper, so a leaf reject vector exercises production code. + +--- + +## Why this exists + +`spec/vectors/decode_vectors.txt` is normative under `req:binfmt:decode-vectors`: +it is what a *second implementation* is checked against. Today it holds 65 +vectors across 5 surfaces (`ops.operation_kind_tag`, `ops.materialized_state`, +`bundle.block`, `bundle.manifest`, `bundle.operation_index`) and **nothing from +`epiphany-core`** — the score wire, the oldest and most load-bearing format in +the repo, has no cross-implementation vectors at all. + +The companion already asked for this (`binary_format.tex:3294`): "A future +revision should extend the corpus to the representative struct layouts of +Section~\ref{sec:values:representative}, which remain **round-trip locked rather +than literal-byte locked**." + +That is not theoretical. In tranche 3b-i the reviewer swapped `smufl` and +`overrides` in **both** halves of `ScoreTuningContext`'s codec — a +self-consistent reordering of a layout `req:binfmt:frozen-layout` freezes +permanently — and **the entire workspace suite (1283 tests) and all 8/8 +conformance rows passed.** Round-trip locking cannot see that. Only literal bytes +can. + +## The mechanism already exists — do not invent a new one + +- **`CanonicalValue`** (`codec.rs:3435`) is **public** and already implements + exactly the required discipline: decode, `finish()` (reject trailing bytes), + re-encode, and reject on mismatch. It already covers **four of the spec's + five** representative layouts — `Pitch`, `TimeAnchor`, `Event`, `Slur`. +- `Codec` and `Reader` are `pub(crate)` and **MUST stay that way.** A module + inside `epiphany-core` can use them directly; nothing new goes public except + the `CanonicalValue` impls below and the two `vectors` functions. +- `encode_v0_score` / `encode_v1_score` / `encode_v2_score` are `pub(crate)` — + an in-core `vectors` module can call them to synthesize genuine old-major bytes. + +## 1. Extend `CanonicalValue` + +Add to the `canonical_value!` list (`codec.rs:3476`), each because the corpus +pins it: + +- **`RationalTime`** — the fifth representative layout, and the only one + missing. It **normalizes on decode** (an unreduced fraction reduces to lowest + terms, `codec.rs:2570`), which makes it the exemplar of the spec's own warning + that "a guard on an outer value can *mask* a lenient inner codec". +- **`ScoreTuningContext`** — the schema-major-3 container whose silent + reorderability is the reason this tranche exists. +- **`TuningOverride`**, **`TuningScope`**, **`SmuflVersionRequirement`**, + **`SmuflVersion`** — the four leaf layouts frozen in 3b-i. + +Update the macro's doc rationale (`codec.rs:3433`, "Implemented only for the +value types operation payloads embed... to keep the public surface intentional") +to record the second reason: **and the types the decode-vector corpus pins**. +The surface stays intentional; the intent widened. + +If any of these lacks a `Codec` impl, stop and report rather than inventing a +byte layout — every one of them is already encoded inside `Score`, so the layout +exists and `CanonicalValue` must introduce **no new bytes** (that is the trait's +stated contract). + +## 2. New `crates/epiphany-core/src/vectors.rs` + +Mirror `epiphany-ops/src/vectors.rs` in shape and doc style: + +```rust +pub type DecodeVector = (&'static str, &'static str, &'static str, String, Vec); +pub fn decode_vectors() -> Vec; +pub fn check(surface: &str, bytes: &[u8]) -> Option>; +``` + +`check` semantics, exactly as the other two crates: `Err` = rejected, +`Ok(injective)` = accepted with whether it re-encodes to its own bytes. Route +every leaf surface through **`CanonicalValue::decode_canonical`** — the public +production API — never a locally re-implemented strictness check. + +### Surfaces + +Leaves (one per `CanonicalValue` type above): `core.rational_time`, +`core.time_anchor`, `core.pitch`, `core.event`, `core.slur`, +`core.score_tuning_context`, `core.tuning_override`, `core.tuning_scope`, +`core.smufl_version_requirement`, `core.smufl_version`. + +Whole `Score`, one per schema major: `core.score_v0`, `core.score_v1`, +`core.score_v2`, `core.score_v3`. + +**Every surface MUST carry both an `accept` and a `reject` vector** — +`every_surface_carries_both_verdicts` enforces it. If a surface cannot be given a +meaningful reject vector, fold it into its container rather than inventing a +contrived one, and say so in your report. + +### The trap in the per-major Score vectors + +For `core.score_v3`, injectivity is `decoded.canonical_bytes() == bytes`. + +For `core.score_v0/v1/v2` it is **NOT**. Migration deliberately produces a value +whose *current* encoding differs from the input bytes — that is the whole point +of a default-filling migration. `decode_vN_score` is already strictly canonical +**over its own wire form** (it re-encodes through `encode_vN_score` and rejects a +mismatch), so a successful `Score::decode_canonical_versioned(bytes, N)` already +proves the input was canonical at major N. Return `Ok(true)` there. **Do not +compare against `canonical_bytes()` for majors 0–2** — it will fail, and +"fixing" it by relaxing the vector would destroy the vector's meaning. + +### Reject classes — principled, not arbitrary + +The ops module's rule applies (`vectors.rs:10`): each class is one this +repository actually shipped a bug in, or one an injectivity fuzzer cannot see. +Draw from: + +- **unreduced `RationalTime`** — the lenient-leaf normalization case; +- **non-finite float** (NaN / ±inf bits) in a `CanonicalF64` leaf + (`NonFiniteFloat`); +- **unsorted or duplicated** `BTreeSet`/`BTreeMap` entries (order-preserving + sequence checks are invisible to a whole-value re-encode guard); +- **out-of-range discriminant** on a tagged union (`TimeAnchor`, `TuningScope`, + `PitchSpacePosition`); +- **trailing bytes** and **truncation**; +- **the swapped major-3 field order** — bytes encoding `ScoreTuningContext` with + `overrides` before `smufl`. This is the direct regression vector for the 3b-i + defect and MUST be present. + +## 3. Wire it into the testkit + +`crates/epiphany-testkit/src/vectors.rs`: +- `all()` (:78) — chain `epiphany_core::vectors::decode_vectors()`. +- the `check` dispatch (:165) — add `.or_else(|| epiphany_core::vectors::check(..))`. + +**Append core LAST**, after ops and bundle. This is deliberate: it keeps the +regenerated corpus diff **purely additive**, which *proves* no existing vector's +bytes moved — i.e. that this tranche changed no existing wire form. A +nicer-looking dependency order would move all 65 existing lines and destroy that +property. Update `all()`'s doc comment ("the operation layer, then the bundle +wire") accordingly. + +## 4. Regenerate + +`cargo run -q -p epiphany-testkit --example generate_vectors` + +`the_committed_corpus_matches_the_generator` fails on drift, so the regenerated +file must be committed. Confirm in your report that **the first 65 vectors are +byte-identical** to before. + +## 5. Spec + +Update the rationale at `binary_format.tex:3294-3296`: the "future revision" +it anticipates is now delivered for the representative layouts, and record that +the corpus additionally pins the schema-major-3 tuning-context layouts and the +per-major whole-`Score` forms. If §"The Decode Vector Corpus" enumerates +surfaces, extend that list. + +**No new `\label{req:...}`** — `req:binfmt:decode-vectors` already governs this +and needs no change. Requirement counts MUST stay **212 / 282 / 282**. + +## Do NOT + +- Make `Codec` or `Reader` public. +- Introduce any new byte layout. `CanonicalValue` must emit exactly the bytes the + whole-score codec already emits (its stated contract). If a value's per-type + bytes differ from its embedded bytes, that is a bug — stop and report it. +- Change any existing vector, or any wire form. +- Touch the editor track (`spec/PLAN_EDITOR_APP.md`, `CONTRACT_EDITOR_*`, + `crates/epiphany-editor-gui/goldens/`) or `.claude/worktrees/`. + +## The gate (report exact numbers) + +- `cargo fmt --all --check` +- `cargo clippy --workspace --all-targets` → 0 warnings +- `cargo test --workspace` → 0 failed (HEAD is at 1318; report the count) +- `RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps` → 0 +- `cargo run -q -p epiphany-testkit --example conformance_suite` → 8/8, and + report the vector count gate [7d] prints (65 today) +- `cargo test -p epiphany-testkit --test requirement_labels` → 6/6, counts + **212 / 282 / 282** + +## Prove the hole is closed — the deliverable that matters + +A corpus that does not catch the original defect is decoration. **Re-apply the +3b-i mutation** — swap `smufl` and `overrides` in *both* the `enc` and `dec` +halves of `impl Codec for ScoreTuningContext` (`codec.rs:1960`) — and confirm the +**corpus check now fails** (`every_vector_gets_its_declared_verdict` / +`the_committed_corpus_matches_the_generator`). Restore, and assert the anchor +text is back. Report the exact failure message. + +That mutation previously passed 1283 tests and 8/8 conformance. If it still +passes after this tranche, the tranche did not do its job. + +## What the reviewer will verify independently + +- The first 65 corpus vectors are byte-identical; the diff is purely additive. +- The 3b-i swap mutation is caught by the corpus. +- The per-major `Score` vectors genuinely decode at their stamped major, and + `core.score_v0/v1/v2` are *not* asserting `canonical_bytes()` equality. +- Every new `accept` vector's bytes equal the bytes the whole-score codec embeds + for that value (no new layout). +- No new public API beyond the `CanonicalValue` impls and the two `vectors` + functions; `Codec`/`Reader` still `pub(crate)`. diff --git a/spec/binary_format.pdf b/spec/binary_format.pdf index 3d6e821..e6183c6 100644 Binary files a/spec/binary_format.pdf and b/spec/binary_format.pdf differ diff --git a/spec/binary_format.tex b/spec/binary_format.tex index 9bf8708..770f0bc 100644 --- a/spec/binary_format.tex +++ b/spec/binary_format.tex @@ -240,7 +240,7 @@ {\Large\scshape\color{epiphanyslate}Binary Format}\\[6pt] {\large\itshape\color{epiphanyslate}A companion to the Core Specification}\\[14pt] {\color{epiphanygold}\rule{3in}{0.8pt}}\\[24pt] - {\normalsize\color{epiphanyink}Version 0.10.0 --- Schema major 3: the tuning context's SMuFL requirement and per-scope overrides reach the wire}\\[4pt] + {\normalsize\color{epiphanyink}Version 0.11.0 --- The decode vector corpus extends to the core score wire}\\[4pt] {\small\color{epiphanyslate}Normative for the byte layouts it defines} \vfill \end{titlepage} @@ -3294,6 +3294,29 @@ only}: implementations need not agree on an error taxonomy. A future revision should extend the corpus to the representative struct layouts of Section~\ref{sec:values:representative}, which remain round-trip locked rather than literal-byte locked. + + \textbf{Delivered (\texttt{spec/CONTRACT\_CORE\_DECODE\_VECTORS.md}).} The + corpus now additionally pins all five representative layouts of + Section~\ref{sec:values:representative} (\texttt{RationalTime}, + \texttt{TimeAnchor}, \texttt{Pitch}, \texttt{Event}, \texttt{Slur}), the + schema-major-3 tuning-context leaves (\texttt{SmuflVersion}, + \texttt{SmuflVersionRequirement}, \texttt{TuningScope}, + \texttt{TuningOverride}) and their container (\texttt{ScoreTuningContext}), + and one whole-\texttt{Score} snapshot at each schema major + \texttt{0}--\texttt{3}. The mandatory regression vector is the one that + motivated this extension: bytes encoding \texttt{ScoreTuningContext} with + \texttt{overrides} before \texttt{smufl} --- the exact self-consistent field + swap that previously passed the entire reference-implementation suite and + 8/8 conformance, because round-trip locking cannot see a decoder and + encoder agreeing on the wrong order. Each per-major whole-\texttt{Score} + vector genuinely decodes at its stamped major through + \texttt{Score::decode\ub canonical\ub versioned}; majors \texttt{0}--\texttt{2} + assert only that decoding succeeds (a migration deliberately rewrites bytes + to the current layout, so the injectivity check there is that the input was + already canonical \emph{at its own major}, which the frozen per-major + encoder's own re-encode guard already established), while major \texttt{3} + additionally asserts the decoded value re-encodes to exactly the input + bytes. \end{rationale} % =========================================================================== @@ -3439,6 +3462,19 @@ only}: implementations need not agree on an error taxonomy. \tablenums{2}. Semantics: core specification Chapter~4, \sectionsc{Score Tuning Context} / \sectionsc{SMuFL Versioning}; the staging ruling itself is Push~4b's own (\texttt{spec/CONTRACT\_PUSH4B\_3BI\_WIRE.md}). \\ + \today & Golden anchors & 0.11.0 --- Extends the decode vector corpus + (Section~\ref{sec:goldens:decode-vectors}) to \texttt{epiphany-core}'s score + wire, closing the gap \S0.9.0 left open and delivering the ``future + revision'' this section's own rationale anticipated: all five + representative layouts of Section~\ref{sec:values:representative} + (\texttt{RationalTime}, \texttt{TimeAnchor}, \texttt{Pitch}, \texttt{Event}, + \texttt{Slur}), the schema-major-3 tuning-context leaves and their + container, and one whole-\texttt{Score} vector per schema major + \texttt{0}--\texttt{3}. Includes the mandatory regression vector for the + tranche-3b-i defect (a swapped \texttt{smufl}/\texttt{overrides} field + order, which previously passed round-trip locking and 8/8 conformance). + No wire layout changed; no existing vector's bytes moved + (\texttt{spec/CONTRACT\_CORE\_DECODE\_VECTORS.md}). \\ \bottomrule \end{longtable} diff --git a/spec/vectors/decode_vectors.txt b/spec/vectors/decode_vectors.txt index 61ad350..eeda9b4 100644 --- a/spec/vectors/decode_vectors.txt +++ b/spec/vectors/decode_vectors.txt @@ -99,3 +99,59 @@ bundle.block accept - two_envelopes 0200000008000000aaaaaaaaaaaaaaaa0d000000bbbb bundle.block reject trailing-bytes two_envelopes_trailing 0200000008000000aaaaaaaaaaaaaaaa0d000000bbbbbbbbbbbbbbbbbbbbbbbbbb00 bundle.block reject truncated two_envelopes_truncated 0200000008000000aaaaaaaaaaaaaaaa0d000000bbbbbbbbbbbbbbbbbbbbbbbb bundle.block reject count-exceeds-remaining envelope_count_u32_max ffffffff08000000aaaaaaaaaaaaaaaa0d000000bbbbbbbbbbbbbbbbbbbbbbbbbb + +# core.rational_time +core.rational_time accept - one_eighth 0b0000000101000000010100000008 +core.rational_time reject unreduced-rational-time two_fourths_unreduced 0b0000000101000000020100000004 + +# core.time_anchor +core.time_anchor accept - event_anchor 001000000000000000000000010000000000000001000b0000000101000000010100000004 +core.time_anchor reject out-of-range-discriminant tag_9_one_past_the_vocabulary 091000000000000000000000010000000000000001000b0000000101000000010100000004 + +# core.pitch +core.pitch accept - cents_offset 06000000636d6e2d313200000004000108000000000000000000f83f +core.pitch reject non-finite-float cents_offset_nan 06000000636d6e2d313200000004000108000000000000000000f87f + +# core.event +core.event accept - pitched_event 0010000000000000000000000100000000000000011000000000000000000000010000000000000001000b0000000001000000000100000001000b000000010100000001010000000401000000100000000000000000000001000000000000000106000000636d6e2d313200000004000108000000000000000000000000000000000000000000 +core.event reject trailing-bytes pitched_event_trailing 0010000000000000000000000100000000000000011000000000000000000000010000000000000001000b0000000001000000000100000001000b000000010100000001010000000401000000100000000000000000000001000000000000000106000000636d6e2d31320000000400010800000000000000000000000000000000000000000000 + +# core.slur +core.slur accept - simple_slur 10000000000000000000000100000000000000011000000000000000000000010000000000000001100000000000000000000001000000000000000200000000 +core.slur reject truncated simple_slur_truncated 100000000000000000000001000000000000000110000000000000000000000100000000000000011000000000000000000000010000000000000002000000 + +# core.score_tuning_context +core.score_tuning_context accept - loaded_context 06000000636d6e2d3132060000007465742d313200050004080000000000000000807b4001000c0001001200010000000010000000000000000000000100000000000000070001060000007465742d313900 +core.score_tuning_context reject swapped-major-3-field-order overrides_before_smufl 06000000636d6e2d3132060000007465742d313200050004080000000000000000807b40010000000010000000000000000000000100000000000000070001060000007465742d31390001000c0001001200 + +# core.tuning_override +core.tuning_override accept - voice_scoped 0010000000000000000000000100000000000000070001060000007465742d313900 +core.tuning_override reject trailing-bytes voice_scoped_trailing 0010000000000000000000000100000000000000070001060000007465742d31390000 + +# core.tuning_scope +core.tuning_scope accept - voice 001000000000000000000000010000000000000007 +core.tuning_scope reject out-of-range-discriminant tag_9_one_past_the_vocabulary 091000000000000000000000010000000000000007 + +# core.smufl_version_requirement +core.smufl_version_requirement accept - one_twelve_one_eighteen 01000c0001001200 +core.smufl_version_requirement reject trailing-bytes one_twelve_one_eighteen_trailing 01000c000100120000 + +# core.smufl_version +core.smufl_version accept - one_four 01002800 +core.smufl_version reject truncated one_four_truncated 010028 + +# core.score_v0 +core.score_v0 accept - valid_score_seed_7 0000000100000010000000dc51e92c5024f4bb00000000000000000000000000000200000010000000dc51e92c5024f4bb000000000000000310000000dc51e92c5024f4bb00000000000000010200000010000000dc51e92c5024f4bb00000000000000040400000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb000000000000000b00000010000000dc51e92c5024f4bb000000000000000d0200000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb00000000000000100000000000000000000000000000000000000110000000dc51e92c5024f4bb000000000000001410000000dc51e92c5024f4bb00000000000000120200000010000000dc51e92c5024f4bb00000000000000150400000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb000000000000001c00000010000000dc51e92c5024f4bb000000000000001e0300000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb0000000000000023000000000000000000000000000000000000010000000000000000000000000003080000000000000000000000030800000040420f00000000000200000010000000dc51e92c5024f4bb000000000000000110000000dc51e92c5024f4bb0000000000000012000200000010000000dc51e92c5024f4bb00000000000000020a000000696e737472756d656e7410000000dc51e92c5024f4bb00000000000000130a000000696e737472756d656e740200000010000000dc51e92c5024f4bb00000000000000010500000073746166660010000000dc51e92c5024f4bb0000000000000002050010000000dc51e92c5024f4bb00000000000000120500000073746166660010000000dc51e92c5024f4bb0000000000000013050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000636d6e2d3132060000007465742d313200050004080000000000000000807b4000000000000d0000000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb0000000000000004000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000606000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000806000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000a06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000000b10000000dc51e92c5024f4bb0000000000000004000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000c06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb000000000000000d000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000f06000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001010000000dc51e92c5024f4bb000000000000000d000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001106000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb0000000000000015000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001706000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001906000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001b06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000001c10000000dc51e92c5024f4bb0000000000000015000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001d06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000001e000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002006000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002206000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000002310000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002406000000636d6e2d3132000200040000000000000000000000000000000000000000050000000001020304000000000000000008000000dc51e92c5024f4bb25000000000000000000000000000000 +core.score_v0 reject trailing-bytes valid_score_seed_7_trailing 0000000100000010000000dc51e92c5024f4bb00000000000000000000000000000200000010000000dc51e92c5024f4bb000000000000000310000000dc51e92c5024f4bb00000000000000010200000010000000dc51e92c5024f4bb00000000000000040400000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb000000000000000b00000010000000dc51e92c5024f4bb000000000000000d0200000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb00000000000000100000000000000000000000000000000000000110000000dc51e92c5024f4bb000000000000001410000000dc51e92c5024f4bb00000000000000120200000010000000dc51e92c5024f4bb00000000000000150400000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb000000000000001c00000010000000dc51e92c5024f4bb000000000000001e0300000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb0000000000000023000000000000000000000000000000000000010000000000000000000000000003080000000000000000000000030800000040420f00000000000200000010000000dc51e92c5024f4bb000000000000000110000000dc51e92c5024f4bb0000000000000012000200000010000000dc51e92c5024f4bb00000000000000020a000000696e737472756d656e7410000000dc51e92c5024f4bb00000000000000130a000000696e737472756d656e740200000010000000dc51e92c5024f4bb00000000000000010500000073746166660010000000dc51e92c5024f4bb0000000000000002050010000000dc51e92c5024f4bb00000000000000120500000073746166660010000000dc51e92c5024f4bb0000000000000013050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000636d6e2d3132060000007465742d313200050004080000000000000000807b4000000000000d0000000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb0000000000000004000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000606000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000806000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000a06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000000b10000000dc51e92c5024f4bb0000000000000004000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000c06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb000000000000000d000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000f06000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001010000000dc51e92c5024f4bb000000000000000d000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001106000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb0000000000000015000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001706000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001906000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001b06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000001c10000000dc51e92c5024f4bb0000000000000015000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001d06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000001e000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002006000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002206000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000002310000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002406000000636d6e2d3132000200040000000000000000000000000000000000000000050000000001020304000000000000000008000000dc51e92c5024f4bb2500000000000000000000000000000000 + +# core.score_v1 +core.score_v1 accept - valid_score_seed_7 0000000100000010000000dc51e92c5024f4bb00000000000000000000000000000200000010000000dc51e92c5024f4bb000000000000000310000000dc51e92c5024f4bb00000000000000010200000010000000dc51e92c5024f4bb00000000000000040400000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb000000000000000b00000010000000dc51e92c5024f4bb000000000000000d0200000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb00000000000000100000000000000000000000000000000000000110000000dc51e92c5024f4bb000000000000001410000000dc51e92c5024f4bb00000000000000120200000010000000dc51e92c5024f4bb00000000000000150400000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb000000000000001c00000010000000dc51e92c5024f4bb000000000000001e0300000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb0000000000000023000000000000000000000000000000000000010000000000000000000000000003080000000000000000000000030800000040420f00000000000200000010000000dc51e92c5024f4bb000000000000000110000000dc51e92c5024f4bb00000000000000120000080000000000000000405a40080000000000000000906240080000000000000000001e40080000000000000000001e40080000000000000000001e40080000000000000000001e400200000010000000dc51e92c5024f4bb00000000000000020a000000696e737472756d656e740010000000dc51e92c5024f4bb00000000000000130a000000696e737472756d656e74000200000010000000dc51e92c5024f4bb00000000000000010500000073746166660010000000dc51e92c5024f4bb0000000000000002050010000000dc51e92c5024f4bb00000000000000120500000073746166660010000000dc51e92c5024f4bb0000000000000013050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000636d6e2d3132060000007465742d313200050004080000000000000000807b4000000000000d0000000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb0000000000000004000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000606000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000806000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000a06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000000b10000000dc51e92c5024f4bb0000000000000004000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000c06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb000000000000000d000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000f06000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001010000000dc51e92c5024f4bb000000000000000d000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001106000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb0000000000000015000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001706000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001906000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001b06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000001c10000000dc51e92c5024f4bb0000000000000015000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001d06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000001e000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002006000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002206000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000002310000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002406000000636d6e2d3132000200040000000000000000000000000000000000000000050000000001020304000000000000000008000000dc51e92c5024f4bb25000000000000000000000000000000 +core.score_v1 reject trailing-bytes valid_score_seed_7_trailing 0000000100000010000000dc51e92c5024f4bb00000000000000000000000000000200000010000000dc51e92c5024f4bb000000000000000310000000dc51e92c5024f4bb00000000000000010200000010000000dc51e92c5024f4bb00000000000000040400000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb000000000000000b00000010000000dc51e92c5024f4bb000000000000000d0200000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb00000000000000100000000000000000000000000000000000000110000000dc51e92c5024f4bb000000000000001410000000dc51e92c5024f4bb00000000000000120200000010000000dc51e92c5024f4bb00000000000000150400000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb000000000000001c00000010000000dc51e92c5024f4bb000000000000001e0300000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb0000000000000023000000000000000000000000000000000000010000000000000000000000000003080000000000000000000000030800000040420f00000000000200000010000000dc51e92c5024f4bb000000000000000110000000dc51e92c5024f4bb00000000000000120000080000000000000000405a40080000000000000000906240080000000000000000001e40080000000000000000001e40080000000000000000001e40080000000000000000001e400200000010000000dc51e92c5024f4bb00000000000000020a000000696e737472756d656e740010000000dc51e92c5024f4bb00000000000000130a000000696e737472756d656e74000200000010000000dc51e92c5024f4bb00000000000000010500000073746166660010000000dc51e92c5024f4bb0000000000000002050010000000dc51e92c5024f4bb00000000000000120500000073746166660010000000dc51e92c5024f4bb0000000000000013050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000636d6e2d3132060000007465742d313200050004080000000000000000807b4000000000000d0000000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb0000000000000004000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000606000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000806000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000a06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000000b10000000dc51e92c5024f4bb0000000000000004000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000c06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb000000000000000d000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000f06000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001010000000dc51e92c5024f4bb000000000000000d000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001106000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb0000000000000015000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001706000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001906000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001b06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000001c10000000dc51e92c5024f4bb0000000000000015000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001d06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000001e000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002006000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002206000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000002310000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002406000000636d6e2d3132000200040000000000000000000000000000000000000000050000000001020304000000000000000008000000dc51e92c5024f4bb2500000000000000000000000000000000 + +# core.score_v2 +core.score_v2 accept - valid_score_seed_7 00000000000000000000000000000000000000000000000000000100000010000000dc51e92c5024f4bb00000000000000000000000000000200000010000000dc51e92c5024f4bb000000000000000310000000dc51e92c5024f4bb00000000000000010200000010000000dc51e92c5024f4bb00000000000000040400000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb000000000000000b00000010000000dc51e92c5024f4bb000000000000000d0200000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb00000000000000100000000000000000000000000000000000000110000000dc51e92c5024f4bb000000000000001410000000dc51e92c5024f4bb00000000000000120200000010000000dc51e92c5024f4bb00000000000000150400000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb000000000000001c00000010000000dc51e92c5024f4bb000000000000001e0300000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb0000000000000023000000000000000000000000000000000000010000000000000000000000000003080000000000000000000000030800000040420f00000000000200000010000000dc51e92c5024f4bb000000000000000110000000dc51e92c5024f4bb00000000000000120000080000000000000000405a40080000000000000000906240080000000000000000001e40080000000000000000001e40080000000000000000001e40080000000000000000001e400200000010000000dc51e92c5024f4bb00000000000000020a000000696e737472756d656e74000000000000000002000508000000000000000000f03f00000000000010000000dc51e92c5024f4bb00000000000000130a000000696e737472756d656e74000000000000000002000508000000000000000000f03f0000000000000200000010000000dc51e92c5024f4bb00000000000000010500000073746166660010000000dc51e92c5024f4bb00000000000000020508000000000000000000f03f00000000020010000000dc51e92c5024f4bb00000000000000120500000073746166660010000000dc51e92c5024f4bb00000000000000130508000000000000000000f03f00000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000636d6e2d3132060000007465742d313200050004080000000000000000807b4000000000000d0000000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb0000000000000004000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000606000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000806000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000a06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000000b10000000dc51e92c5024f4bb0000000000000004000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000c06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb000000000000000d000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000f06000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001010000000dc51e92c5024f4bb000000000000000d000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001106000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb0000000000000015000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001706000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001906000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001b06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000001c10000000dc51e92c5024f4bb0000000000000015000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001d06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000001e000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002006000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002206000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000002310000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002406000000636d6e2d3132000200040000000000000000000000000000000000000000050000000001020304000000000000000008000000dc51e92c5024f4bb25000000000000000000000000000000 +core.score_v2 reject trailing-bytes valid_score_seed_7_trailing 00000000000000000000000000000000000000000000000000000100000010000000dc51e92c5024f4bb00000000000000000000000000000200000010000000dc51e92c5024f4bb000000000000000310000000dc51e92c5024f4bb00000000000000010200000010000000dc51e92c5024f4bb00000000000000040400000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb000000000000000b00000010000000dc51e92c5024f4bb000000000000000d0200000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb00000000000000100000000000000000000000000000000000000110000000dc51e92c5024f4bb000000000000001410000000dc51e92c5024f4bb00000000000000120200000010000000dc51e92c5024f4bb00000000000000150400000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb000000000000001c00000010000000dc51e92c5024f4bb000000000000001e0300000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb0000000000000023000000000000000000000000000000000000010000000000000000000000000003080000000000000000000000030800000040420f00000000000200000010000000dc51e92c5024f4bb000000000000000110000000dc51e92c5024f4bb00000000000000120000080000000000000000405a40080000000000000000906240080000000000000000001e40080000000000000000001e40080000000000000000001e40080000000000000000001e400200000010000000dc51e92c5024f4bb00000000000000020a000000696e737472756d656e74000000000000000002000508000000000000000000f03f00000000000010000000dc51e92c5024f4bb00000000000000130a000000696e737472756d656e74000000000000000002000508000000000000000000f03f0000000000000200000010000000dc51e92c5024f4bb00000000000000010500000073746166660010000000dc51e92c5024f4bb00000000000000020508000000000000000000f03f00000000020010000000dc51e92c5024f4bb00000000000000120500000073746166660010000000dc51e92c5024f4bb00000000000000130508000000000000000000f03f00000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000636d6e2d3132060000007465742d313200050004080000000000000000807b4000000000000d0000000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb0000000000000004000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000606000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000806000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000a06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000000b10000000dc51e92c5024f4bb0000000000000004000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000c06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb000000000000000d000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000f06000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001010000000dc51e92c5024f4bb000000000000000d000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001106000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb0000000000000015000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001706000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001906000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001b06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000001c10000000dc51e92c5024f4bb0000000000000015000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001d06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000001e000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002006000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002206000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000002310000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002406000000636d6e2d3132000200040000000000000000000000000000000000000000050000000001020304000000000000000008000000dc51e92c5024f4bb2500000000000000000000000000000000 + +# core.score_v3 +core.score_v3 accept - valid_score_seed_7 00000000000000000000000000000000000000000000000000000100000010000000dc51e92c5024f4bb00000000000000000000000000000200000010000000dc51e92c5024f4bb000000000000000310000000dc51e92c5024f4bb00000000000000010200000010000000dc51e92c5024f4bb00000000000000040400000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb000000000000000b00000010000000dc51e92c5024f4bb000000000000000d0200000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb00000000000000100000000000000000000000000000000000000110000000dc51e92c5024f4bb000000000000001410000000dc51e92c5024f4bb00000000000000120200000010000000dc51e92c5024f4bb00000000000000150400000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb000000000000001c00000010000000dc51e92c5024f4bb000000000000001e0300000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb0000000000000023000000000000000000000000000000000000010000000000000000000000000003080000000000000000000000030800000040420f00000000000200000010000000dc51e92c5024f4bb000000000000000110000000dc51e92c5024f4bb00000000000000120000080000000000000000405a40080000000000000000906240080000000000000000001e40080000000000000000001e40080000000000000000001e40080000000000000000001e400200000010000000dc51e92c5024f4bb00000000000000020a000000696e737472756d656e74000000000000000002000508000000000000000000f03f00000000000010000000dc51e92c5024f4bb00000000000000130a000000696e737472756d656e74000000000000000002000508000000000000000000f03f0000000000000200000010000000dc51e92c5024f4bb00000000000000010500000073746166660010000000dc51e92c5024f4bb00000000000000020508000000000000000000f03f00000000020010000000dc51e92c5024f4bb00000000000000120500000073746166660010000000dc51e92c5024f4bb00000000000000130508000000000000000000f03f00000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000636d6e2d3132060000007465742d313200050004080000000000000000807b4001002800010028000000000000000000000d0000000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb0000000000000004000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000606000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000806000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000a06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000000b10000000dc51e92c5024f4bb0000000000000004000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000c06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb000000000000000d000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000f06000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001010000000dc51e92c5024f4bb000000000000000d000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001106000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb0000000000000015000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001706000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001906000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001b06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000001c10000000dc51e92c5024f4bb0000000000000015000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001d06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000001e000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002006000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002206000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000002310000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002406000000636d6e2d3132000200040000000000000000000000000000000000000000050000000001020304000000000000000008000000dc51e92c5024f4bb25000000000000000000000000000000 +core.score_v3 reject trailing-bytes valid_score_seed_7_trailing 00000000000000000000000000000000000000000000000000000100000010000000dc51e92c5024f4bb00000000000000000000000000000200000010000000dc51e92c5024f4bb000000000000000310000000dc51e92c5024f4bb00000000000000010200000010000000dc51e92c5024f4bb00000000000000040400000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb000000000000000b00000010000000dc51e92c5024f4bb000000000000000d0200000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb00000000000000100000000000000000000000000000000000000110000000dc51e92c5024f4bb000000000000001410000000dc51e92c5024f4bb00000000000000120200000010000000dc51e92c5024f4bb00000000000000150400000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb000000000000001c00000010000000dc51e92c5024f4bb000000000000001e0300000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb0000000000000023000000000000000000000000000000000000010000000000000000000000000003080000000000000000000000030800000040420f00000000000200000010000000dc51e92c5024f4bb000000000000000110000000dc51e92c5024f4bb00000000000000120000080000000000000000405a40080000000000000000906240080000000000000000001e40080000000000000000001e40080000000000000000001e40080000000000000000001e400200000010000000dc51e92c5024f4bb00000000000000020a000000696e737472756d656e74000000000000000002000508000000000000000000f03f00000000000010000000dc51e92c5024f4bb00000000000000130a000000696e737472756d656e74000000000000000002000508000000000000000000f03f0000000000000200000010000000dc51e92c5024f4bb00000000000000010500000073746166660010000000dc51e92c5024f4bb00000000000000020508000000000000000000f03f00000000020010000000dc51e92c5024f4bb00000000000000120500000073746166660010000000dc51e92c5024f4bb00000000000000130508000000000000000000f03f00000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000636d6e2d3132060000007465742d313200050004080000000000000000807b4001002800010028000000000000000000000d0000000010000000dc51e92c5024f4bb000000000000000510000000dc51e92c5024f4bb0000000000000004000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000606000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000000710000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000806000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000000910000000dc51e92c5024f4bb0000000000000004000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000a06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000000b10000000dc51e92c5024f4bb0000000000000004000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000c06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000000e10000000dc51e92c5024f4bb000000000000000d000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000000f06000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001010000000dc51e92c5024f4bb000000000000000d000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001106000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001610000000dc51e92c5024f4bb0000000000000015000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001706000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000001810000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001906000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000001a10000000dc51e92c5024f4bb0000000000000015000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001b06000000636d6e2d3132000200040000000000000000000000000010000000dc51e92c5024f4bb000000000000001c10000000dc51e92c5024f4bb0000000000000015000b0000000101000000030100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000001d06000000636d6e2d3132000300040000000000000000000000000010000000dc51e92c5024f4bb000000000000001f10000000dc51e92c5024f4bb000000000000001e000b0000000001000000000100000001000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002006000000636d6e2d3132000000040000000000000000000000000010000000dc51e92c5024f4bb000000000000002110000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000004000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002206000000636d6e2d3132000100040000000000000000000000000010000000dc51e92c5024f4bb000000000000002310000000dc51e92c5024f4bb000000000000001e000b0000000101000000010100000002000b00000001010000000101000000040100000010000000dc51e92c5024f4bb000000000000002406000000636d6e2d3132000200040000000000000000000000000000000000000000050000000001020304000000000000000008000000dc51e92c5024f4bb2500000000000000000000000000000000