v0.2.5-pre.010.fix.001
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// file: crates/ksp-wallet-lib/unit_tests/administration.rs
|
||||
// version: 1
|
||||
// version: 2
|
||||
|
||||
const FULL_VECTOR: &[u8] = include_bytes!("../tests/fixtures/kspwallet_v1_full_vector.json");
|
||||
|
||||
@@ -10,7 +10,7 @@ fn runtime() -> tokio::runtime::Runtime {
|
||||
fn published_vector(name: &str) -> (tempfile::TempDir, std::path::PathBuf) {
|
||||
let directory = tempfile::Builder::new().prefix("ksp-wallet-admin-").tempdir().expect("Wallet administration test directory must be creatable");
|
||||
let path = directory.path().join(name);
|
||||
crate::persistence::persist_new_wallet_for_test(path.as_path(), FULL_VECTOR).expect("full Wallet vector must publish for administration test");
|
||||
crate::persist_new_wallet_for_test(path.as_path(), FULL_VECTOR).expect("full Wallet vector must publish for administration test");
|
||||
return (directory, path);
|
||||
}
|
||||
|
||||
@@ -26,14 +26,11 @@ fn owner_signing_is_deterministic_and_owner_rotation_preserves_solana_identity()
|
||||
let signature_before = owner.sign(message).expect("OWNER must sign");
|
||||
let signature_repeat = owner.sign(message).expect("OWNER repeated signature must succeed");
|
||||
assert_eq!(signature_before, signature_repeat);
|
||||
|
||||
runtime
|
||||
.block_on(owner.rotate_owner_password(path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre007-new-owner-password"))))
|
||||
.expect("OWNER password rotation must persist");
|
||||
|
||||
let old = runtime.block_on(crate::open_wallet_owner_file_v1(path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre005-owner-password"))));
|
||||
assert_eq!(old.expect_err("old OWNER password must stop unlocking current file").code(), crate::ERROR_CODE_OWNER_UNLOCK_FAILED);
|
||||
|
||||
let reopened = runtime
|
||||
.block_on(crate::open_wallet_owner_file_v1(path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre007-new-owner-password"))))
|
||||
.expect("new OWNER password must unlock current file");
|
||||
@@ -51,21 +48,17 @@ fn view_self_rotation_changes_only_the_current_view_credential() {
|
||||
let pubkey = *view.pubkey();
|
||||
let alias = view.alias().map(std::string::String::from);
|
||||
let notes = view.notes().to_vec();
|
||||
|
||||
runtime
|
||||
.block_on(view.rotate_view_password(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre007-new-view-password"))))
|
||||
.expect("VIEW self-rotation must persist");
|
||||
|
||||
let old = runtime.block_on(crate::open_wallet_view_file_v1(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))));
|
||||
assert_eq!(old.expect_err("old VIEW password must stop unlocking current file").code(), crate::ERROR_CODE_VIEW_UNLOCK_FAILED);
|
||||
|
||||
let reopened = runtime
|
||||
.block_on(crate::open_wallet_view_file_v1(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre007-new-view-password"))))
|
||||
.expect("new VIEW password must unlock current file");
|
||||
assert_eq!(*reopened.pubkey(), pubkey);
|
||||
assert_eq!(reopened.alias(), alias.as_deref());
|
||||
assert_eq!(reopened.notes(), notes.as_slice());
|
||||
|
||||
let owner = runtime
|
||||
.block_on(crate::open_wallet_owner_file_v1(path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre005-owner-password"))))
|
||||
.expect("VIEW self-rotation must not change OWNER credential");
|
||||
@@ -80,11 +73,9 @@ fn owner_rotates_view_without_old_view_password() {
|
||||
.block_on(crate::open_wallet_owner_file_v1(path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre005-owner-password"))))
|
||||
.expect("OWNER fixture must open");
|
||||
let pubkey = *owner.pubkey();
|
||||
|
||||
runtime
|
||||
.block_on(owner.rotate_view_password(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre007-owner-set-view-password"))))
|
||||
.expect("OWNER must rotate VIEW without old VIEW password");
|
||||
|
||||
let old = runtime.block_on(crate::open_wallet_view_file_v1(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))));
|
||||
assert_eq!(old.expect_err("old VIEW password must stop unlocking current file").code(), crate::ERROR_CODE_VIEW_UNLOCK_FAILED);
|
||||
let reopened = runtime
|
||||
@@ -101,7 +92,6 @@ fn owner_metadata_administration_is_visible_to_view_but_does_not_change_pubkey()
|
||||
.block_on(crate::open_wallet_owner_file_v1(path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre005-owner-password"))))
|
||||
.expect("OWNER fixture must open");
|
||||
let pubkey = *owner.pubkey();
|
||||
|
||||
runtime
|
||||
.block_on(owner.update_alias(path.as_path(), std::option::Option::Some(std::string::String::from("pre007-updated-alias"))))
|
||||
.expect("OWNER alias update must persist");
|
||||
@@ -109,14 +99,12 @@ fn owner_metadata_administration_is_visible_to_view_but_does_not_change_pubkey()
|
||||
runtime
|
||||
.block_on(owner.update_note(path.as_path(), note_id.as_str(), std::string::String::from("pre007-updated-note")))
|
||||
.expect("OWNER note update must persist");
|
||||
|
||||
let view = runtime
|
||||
.block_on(crate::open_wallet_view_file_v1(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))))
|
||||
.expect("VIEW must read OWNER-updated metadata");
|
||||
assert_eq!(*view.pubkey(), pubkey);
|
||||
assert_eq!(view.alias(), std::option::Option::Some("pre007-updated-alias"));
|
||||
assert!(view.notes().iter().any(|note| return note.id() == note_id.as_str() && note.text() == "pre007-updated-note"));
|
||||
|
||||
runtime.block_on(owner.delete_note(path.as_path(), note_id.as_str())).expect("OWNER note delete must persist");
|
||||
let view_after_delete = runtime
|
||||
.block_on(crate::open_wallet_view_file_v1(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))))
|
||||
@@ -139,14 +127,12 @@ fn strong_view_disable_and_recreate_change_current_view_authority_without_changi
|
||||
let before = crate::KspWalletEnvelopeV1::parse_json(before_bytes.as_slice()).expect("current Wallet must parse");
|
||||
let old_slot_id = *before.view_descriptor().slot_id().expect("fixture VIEW descriptor must have slot ID");
|
||||
let old_metadata_ciphertext = before.metadata().ciphertext().to_vec();
|
||||
|
||||
runtime.block_on(owner.disable_view(path.as_path())).expect("OWNER strong VIEW disable must persist");
|
||||
let locked_disabled = runtime.block_on(crate::inspect_locked_wallet_file_v1(path.as_path())).expect("disabled Wallet must inspect");
|
||||
assert!(!locked_disabled.view_enabled());
|
||||
let disabled_view =
|
||||
runtime.block_on(crate::open_wallet_view_file_v1(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))));
|
||||
assert_eq!(disabled_view.expect_err("disabled VIEW must not open").code(), crate::ERROR_CODE_CAPABILITY_INSUFFICIENT);
|
||||
|
||||
runtime
|
||||
.block_on(owner.recreate_view(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre007-recreated-view-password"))))
|
||||
.expect("OWNER strong VIEW recreate must persist");
|
||||
@@ -155,7 +141,6 @@ fn strong_view_disable_and_recreate_change_current_view_authority_without_changi
|
||||
let new_slot_id = *recreated.view_descriptor().slot_id().expect("recreated VIEW descriptor must have slot ID");
|
||||
assert_ne!(new_slot_id, old_slot_id);
|
||||
assert_ne!(recreated.metadata().ciphertext(), old_metadata_ciphertext.as_slice());
|
||||
|
||||
let old = runtime.block_on(crate::open_wallet_view_file_v1(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))));
|
||||
assert_eq!(old.expect_err("historical VIEW password must not unlock recreated current state").code(), crate::ERROR_CODE_VIEW_UNLOCK_FAILED);
|
||||
let recreated_view = runtime
|
||||
@@ -173,7 +158,6 @@ fn owner_note_mutation_reports_missing_identifier_without_persisting() {
|
||||
let mut owner = runtime
|
||||
.block_on(crate::open_wallet_owner_file_v1(path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre005-owner-password"))))
|
||||
.expect("OWNER fixture must open");
|
||||
|
||||
let result = runtime.block_on(owner.update_note(path.as_path(), "AAAAAAAAAAAAAAAAAAAAAA", std::string::String::from("must-not-persist")));
|
||||
assert_eq!(result.expect_err("missing note identifier must be rejected").code(), crate::ERROR_CODE_NOTE_NOT_FOUND);
|
||||
assert_eq!(std::fs::read(path.as_path()).expect("Wallet bytes must remain readable"), before);
|
||||
@@ -189,13 +173,11 @@ fn stale_owner_handle_cannot_overwrite_a_newer_authenticated_wallet_state() {
|
||||
let mut stale = runtime
|
||||
.block_on(crate::open_wallet_owner_file_v1(path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre005-owner-password"))))
|
||||
.expect("second OWNER handle must open on the same state");
|
||||
|
||||
runtime
|
||||
.block_on(first.update_alias(path.as_path(), std::option::Option::Some(std::string::String::from("first-writer"))))
|
||||
.expect("first OWNER mutation must persist");
|
||||
let stale_result = runtime.block_on(stale.update_alias(path.as_path(), std::option::Option::Some(std::string::String::from("stale-writer"))));
|
||||
assert_eq!(stale_result.expect_err("stale OWNER handle must not overwrite newer state").code(), crate::ERROR_CODE_STATE_CONFLICT);
|
||||
|
||||
let current = runtime
|
||||
.block_on(crate::open_wallet_view_file_v1(path.as_path(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))))
|
||||
.expect("VIEW must open the first writer's state");
|
||||
@@ -213,14 +195,12 @@ fn owner_handle_cannot_replace_a_different_authenticated_wallet_state() {
|
||||
let mut second = runtime
|
||||
.block_on(crate::open_wallet_owner_file_v1(second_path.as_path(), crate::OwnerPassword::new(std::string::String::from("pre005-owner-password"))))
|
||||
.expect("second OWNER handle must open");
|
||||
|
||||
runtime
|
||||
.block_on(second.update_alias(second_path.as_path(), std::option::Option::Some(std::string::String::from("different-authenticated-state"))))
|
||||
.expect("second Wallet must diverge before wrong-target canary");
|
||||
let wrong_target =
|
||||
runtime.block_on(first.update_alias(second_path.as_path(), std::option::Option::Some(std::string::String::from("must-not-overwrite-second-wallet"))));
|
||||
assert_eq!(wrong_target.expect_err("OWNER handle must not replace a different authenticated Wallet state").code(), crate::ERROR_CODE_STATE_CONFLICT);
|
||||
|
||||
let unchanged_first = runtime
|
||||
.block_on(crate::open_wallet_view_file_v1(first_path.as_path(), crate::ViewPassword::new(std::string::String::from("pre005-view-password"))))
|
||||
.expect("first Wallet must remain unchanged");
|
||||
|
||||
Reference in New Issue
Block a user