v0.2.5-pre.010.fix.001
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
// file: crates/ksp-wallet-lib/src/payload.rs
|
||||
// version: 4
|
||||
// version: 5
|
||||
|
||||
//! Plaintext payload codecs protected inside native `.kspwallet` V1 compartments.
|
||||
|
||||
use base64::Engine; // rust-rules: derive-import
|
||||
use std::str::FromStr; // rust-rules: derive-import
|
||||
use base64::Engine; // rust-rules: trait-import
|
||||
use std::str::FromStr; // rust-rules: trait-import
|
||||
|
||||
/// Crate-internal `MetadataPayloadV1` state shared across the owning crate.
|
||||
pub(crate) struct MetadataPayloadV1 {
|
||||
pubkey: ksp_core_lib::Pubkey,
|
||||
alias: std::option::Option<std::string::String>,
|
||||
@@ -13,16 +14,19 @@ pub(crate) struct MetadataPayloadV1 {
|
||||
}
|
||||
|
||||
impl crate::MetadataPayloadV1 {
|
||||
/// Returns the current pubkey.
|
||||
pub(crate) const fn pubkey(&self) -> &ksp_core_lib::Pubkey {
|
||||
return &self.pubkey;
|
||||
}
|
||||
|
||||
/// Builds `MetadataPayloadV1` from info.
|
||||
pub(crate) fn from_info(info: &crate::WalletInfo) -> Self {
|
||||
let alias = info.alias().map(std::string::String::from);
|
||||
let notes = info.notes().to_vec();
|
||||
return Self { pubkey: *info.pubkey(), alias, notes };
|
||||
}
|
||||
|
||||
/// Updates alias.
|
||||
pub(crate) fn set_alias(&mut self, alias: std::option::Option<std::string::String>) -> ksp_core_lib::Result<()> {
|
||||
let validation_result = validate_alias(alias.as_deref());
|
||||
if let std::result::Result::Err(error) = validation_result {
|
||||
@@ -32,6 +36,7 @@ impl crate::MetadataPayloadV1 {
|
||||
return std::result::Result::Ok(());
|
||||
}
|
||||
|
||||
/// Adds note.
|
||||
pub(crate) fn add_note(&mut self, text: std::string::String) -> ksp_core_lib::Result<std::string::String> {
|
||||
if self.notes.len() >= crate::KSPWALLET_V1_MAX_NOTES {
|
||||
return std::result::Result::Err(metadata_error("Wallet note count exceeds the V1 limit", "metadata.notes"));
|
||||
@@ -40,7 +45,7 @@ impl crate::MetadataPayloadV1 {
|
||||
if let std::result::Result::Err(error) = validation_result {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
let note_id_bytes = match crate::crypto::random_bytes::<{ crate::KSPWALLET_V1_NOTE_ID_BYTES }>() {
|
||||
let note_id_bytes = match crate::random_bytes::<{ crate::KSPWALLET_V1_NOTE_ID_BYTES }>() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
@@ -54,6 +59,7 @@ impl crate::MetadataPayloadV1 {
|
||||
return std::result::Result::Ok(note_id);
|
||||
}
|
||||
|
||||
/// Updates note.
|
||||
pub(crate) fn update_note(&mut self, note_id: &str, text: std::string::String) -> ksp_core_lib::Result<()> {
|
||||
let validation_result = validate_note_text(text.as_str());
|
||||
if let std::result::Result::Err(error) = validation_result {
|
||||
@@ -70,6 +76,7 @@ impl crate::MetadataPayloadV1 {
|
||||
return std::result::Result::Err(note_not_found_error());
|
||||
}
|
||||
|
||||
/// Deletes note.
|
||||
pub(crate) fn delete_note(&mut self, note_id: &str) -> ksp_core_lib::Result<()> {
|
||||
let mut index = 0_usize;
|
||||
while index < self.notes.len() {
|
||||
@@ -82,6 +89,7 @@ impl crate::MetadataPayloadV1 {
|
||||
return std::result::Result::Err(note_not_found_error());
|
||||
}
|
||||
|
||||
/// Executes the crate-internal encode operation for `MetadataPayloadV1`.
|
||||
pub(crate) fn encode(&self) -> ksp_core_lib::Result<std::vec::Vec<u8>> {
|
||||
let validation_result = validate_alias(self.alias.as_deref());
|
||||
if let std::result::Result::Err(error) = validation_result {
|
||||
@@ -110,23 +118,26 @@ impl crate::MetadataPayloadV1 {
|
||||
return std::result::Result::Ok(serialized);
|
||||
}
|
||||
|
||||
/// Consumes this value and returns info.
|
||||
pub(crate) fn into_info(self, capability: crate::WalletCapability) -> crate::WalletInfo {
|
||||
return crate::WalletInfo::new(capability, self.pubkey, self.alias, self.notes);
|
||||
}
|
||||
}
|
||||
|
||||
/// Crate-internal `OwnerControlMaterialV1` state shared across the owning crate.
|
||||
pub(crate) struct OwnerControlMaterialV1 {
|
||||
admin_signing_secret: [u8; crate::crypto::SECRET_KEY_BYTES],
|
||||
admin_signing_secret: [u8; crate::SECRET_KEY_BYTES],
|
||||
metadata_key: crate::SecretKeyV1,
|
||||
secret_key: crate::SecretKeyV1,
|
||||
}
|
||||
|
||||
impl OwnerControlMaterialV1 {
|
||||
pub(crate) fn into_parts(mut self) -> ([u8; crate::crypto::SECRET_KEY_BYTES], crate::SecretKeyV1, crate::SecretKeyV1) {
|
||||
let mut admin_signing_secret = [0_u8; crate::crypto::SECRET_KEY_BYTES];
|
||||
/// Consumes this value and returns parts.
|
||||
pub(crate) fn into_parts(mut self) -> ([u8; crate::SECRET_KEY_BYTES], crate::SecretKeyV1, crate::SecretKeyV1) {
|
||||
let mut admin_signing_secret = [0_u8; crate::SECRET_KEY_BYTES];
|
||||
std::mem::swap(&mut admin_signing_secret, &mut self.admin_signing_secret);
|
||||
let metadata_key = std::mem::replace(&mut self.metadata_key, crate::SecretKeyV1::from_bytes([0_u8; crate::crypto::SECRET_KEY_BYTES]));
|
||||
let secret_key = std::mem::replace(&mut self.secret_key, crate::SecretKeyV1::from_bytes([0_u8; crate::crypto::SECRET_KEY_BYTES]));
|
||||
let metadata_key = std::mem::replace(&mut self.metadata_key, crate::SecretKeyV1::from_bytes([0_u8; crate::SECRET_KEY_BYTES]));
|
||||
let secret_key = std::mem::replace(&mut self.secret_key, crate::SecretKeyV1::from_bytes([0_u8; crate::SECRET_KEY_BYTES]));
|
||||
return (admin_signing_secret, metadata_key, secret_key);
|
||||
}
|
||||
}
|
||||
@@ -152,6 +163,7 @@ struct RawMetadataNoteV1 {
|
||||
text: std::string::String,
|
||||
}
|
||||
|
||||
/// Encodes initial metadata payload.
|
||||
pub(crate) fn encode_initial_metadata_payload(
|
||||
pubkey: ksp_core_lib::Pubkey,
|
||||
metadata: crate::WalletCreateMetadataV1,
|
||||
@@ -164,7 +176,6 @@ pub(crate) fn encode_initial_metadata_payload(
|
||||
if note_texts.len() > crate::KSPWALLET_V1_MAX_NOTES {
|
||||
return std::result::Result::Err(metadata_error("Wallet note count exceeds the V1 limit", "metadata.notes"));
|
||||
}
|
||||
|
||||
let mut notes = std::vec::Vec::with_capacity(note_texts.len());
|
||||
let mut note_ids = std::collections::BTreeSet::new();
|
||||
for text in note_texts {
|
||||
@@ -172,7 +183,7 @@ pub(crate) fn encode_initial_metadata_payload(
|
||||
if let std::result::Result::Err(error) = validation_result {
|
||||
return std::result::Result::Err(error);
|
||||
}
|
||||
let note_id_bytes = match crate::crypto::random_bytes::<{ crate::KSPWALLET_V1_NOTE_ID_BYTES }>() {
|
||||
let note_id_bytes = match crate::random_bytes::<{ crate::KSPWALLET_V1_NOTE_ID_BYTES }>() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
std::result::Result::Err(error) => return std::result::Result::Err(error),
|
||||
};
|
||||
@@ -182,7 +193,6 @@ pub(crate) fn encode_initial_metadata_payload(
|
||||
}
|
||||
notes.push(crate::WalletNote::new(note_id, text));
|
||||
}
|
||||
|
||||
let payload = crate::MetadataPayloadV1 { pubkey, alias, notes };
|
||||
let serialized = match payload.encode() {
|
||||
std::result::Result::Ok(value) => value,
|
||||
@@ -191,6 +201,7 @@ pub(crate) fn encode_initial_metadata_payload(
|
||||
return std::result::Result::Ok((serialized, payload));
|
||||
}
|
||||
|
||||
/// Decodes metadata payload.
|
||||
pub(crate) fn decode_metadata_payload(source: &[u8]) -> ksp_core_lib::Result<crate::MetadataPayloadV1> {
|
||||
if source.len() > crate::KSPWALLET_V1_MAX_METADATA_PLAINTEXT_BYTES {
|
||||
return std::result::Result::Err(metadata_error("Wallet metadata payload exceeds the V1 plaintext limit", "metadata"));
|
||||
@@ -207,7 +218,6 @@ pub(crate) fn decode_metadata_payload(source: &[u8]) -> ksp_core_lib::Result<cra
|
||||
if raw.notes.len() > crate::KSPWALLET_V1_MAX_NOTES {
|
||||
return std::result::Result::Err(metadata_error("Wallet note count exceeds the V1 limit", "metadata.notes"));
|
||||
}
|
||||
|
||||
let pubkey_result = ksp_core_lib::Pubkey::from_str(raw.pubkey.as_str());
|
||||
let pubkey = match pubkey_result {
|
||||
std::result::Result::Ok(value) => value,
|
||||
@@ -216,7 +226,6 @@ pub(crate) fn decode_metadata_payload(source: &[u8]) -> ksp_core_lib::Result<cra
|
||||
if pubkey.to_string() != raw.pubkey {
|
||||
return std::result::Result::Err(metadata_error("Wallet metadata Pubkey is not canonical Base58", "metadata.pubkey"));
|
||||
}
|
||||
|
||||
let mut notes = std::vec::Vec::with_capacity(raw.notes.len());
|
||||
let mut note_ids = std::collections::BTreeSet::new();
|
||||
for raw_note in raw.notes {
|
||||
@@ -239,8 +248,9 @@ pub(crate) fn decode_metadata_payload(source: &[u8]) -> ksp_core_lib::Result<cra
|
||||
return std::result::Result::Ok(crate::MetadataPayloadV1 { pubkey, alias: raw.alias, notes });
|
||||
}
|
||||
|
||||
/// Encodes owner control payload.
|
||||
pub(crate) fn encode_owner_control_payload(
|
||||
admin_signing_secret: &[u8; crate::crypto::SECRET_KEY_BYTES],
|
||||
admin_signing_secret: &[u8; crate::SECRET_KEY_BYTES],
|
||||
metadata_key: &crate::SecretKeyV1,
|
||||
secret_key: &crate::SecretKeyV1,
|
||||
) -> [u8; crate::KSPWALLET_V1_OWNER_CONTROL_PLAINTEXT_BYTES] {
|
||||
@@ -251,15 +261,16 @@ pub(crate) fn encode_owner_control_payload(
|
||||
return output;
|
||||
}
|
||||
|
||||
/// Decodes owner control payload.
|
||||
pub(crate) fn decode_owner_control_payload(source: &[u8]) -> ksp_core_lib::Result<OwnerControlMaterialV1> {
|
||||
if source.len() != crate::KSPWALLET_V1_OWNER_CONTROL_PLAINTEXT_BYTES {
|
||||
return std::result::Result::Err(metadata_error("Wallet OWNER-control payload length is invalid", "owner_control"));
|
||||
}
|
||||
let mut admin_signing_secret = [0_u8; crate::crypto::SECRET_KEY_BYTES];
|
||||
let mut admin_signing_secret = [0_u8; crate::SECRET_KEY_BYTES];
|
||||
admin_signing_secret.copy_from_slice(&source[0..32]);
|
||||
let mut metadata_key = [0_u8; crate::crypto::SECRET_KEY_BYTES];
|
||||
let mut metadata_key = [0_u8; crate::SECRET_KEY_BYTES];
|
||||
metadata_key.copy_from_slice(&source[32..64]);
|
||||
let mut secret_key = [0_u8; crate::crypto::SECRET_KEY_BYTES];
|
||||
let mut secret_key = [0_u8; crate::SECRET_KEY_BYTES];
|
||||
secret_key.copy_from_slice(&source[64..96]);
|
||||
return std::result::Result::Ok(OwnerControlMaterialV1 {
|
||||
admin_signing_secret,
|
||||
|
||||
Reference in New Issue
Block a user