mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-05-14 03:59:30 +00:00
Merge branch 'marvin/refactor-wallet-pub-acc' into marvin/keycard-commands
This commit is contained in:
commit
58fdb7e74c
@ -9,6 +9,8 @@ use sha2::{Digest as _, Sha256};
|
|||||||
|
|
||||||
use crate::{AccountId, error::NssaError};
|
use crate::{AccountId, error::NssaError};
|
||||||
|
|
||||||
|
const PREFIX: &[u8; 32] = b"/LEE/v0.3/Message/Privacy/\x00\x00\x00\x00\x00\x00";
|
||||||
|
|
||||||
pub type ViewTag = u8;
|
pub type ViewTag = u8;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
|
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
|
||||||
@ -121,8 +123,6 @@ impl Message {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn hash_message(&self) -> [u8; 32] {
|
pub fn hash_message(&self) -> [u8; 32] {
|
||||||
const PREFIX: &[u8; 32] = b"/LEE/v0.3/Message/Privacy/\x00\x00\x00\x00\x00\x00";
|
|
||||||
|
|
||||||
let mut bytes = Vec::with_capacity(
|
let mut bytes = Vec::with_capacity(
|
||||||
PREFIX
|
PREFIX
|
||||||
.len()
|
.len()
|
||||||
@ -140,16 +140,13 @@ impl Message {
|
|||||||
pub mod tests {
|
pub mod tests {
|
||||||
use nssa_core::{
|
use nssa_core::{
|
||||||
Commitment, EncryptionScheme, Nullifier, NullifierPublicKey, SharedSecretKey,
|
Commitment, EncryptionScheme, Nullifier, NullifierPublicKey, SharedSecretKey,
|
||||||
account::Account,
|
account::{Account, AccountId, Nonce},
|
||||||
encryption::{EphemeralPublicKey, ViewingPublicKey},
|
encryption::{EphemeralPublicKey, ViewingPublicKey},
|
||||||
program::{BlockValidityWindow, TimestampValidityWindow},
|
program::{BlockValidityWindow, TimestampValidityWindow},
|
||||||
};
|
};
|
||||||
use sha2::{Digest as _, Sha256};
|
use sha2::{Digest as _, Sha256};
|
||||||
|
|
||||||
use crate::{
|
use super::{EncryptedAccountData, Message, PREFIX};
|
||||||
AccountId,
|
|
||||||
privacy_preserving_transaction::message::{EncryptedAccountData, Message},
|
|
||||||
};
|
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn message_for_tests() -> Message {
|
pub fn message_for_tests() -> Message {
|
||||||
@ -190,6 +187,58 @@ pub mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hash_message_privacy_pinned() {
|
||||||
|
let msg = Message {
|
||||||
|
public_account_ids: vec![AccountId::new([42_u8; 32])],
|
||||||
|
nonces: vec![Nonce(5)],
|
||||||
|
public_post_states: vec![],
|
||||||
|
encrypted_private_post_states: vec![],
|
||||||
|
new_commitments: vec![],
|
||||||
|
new_nullifiers: vec![],
|
||||||
|
block_validity_window: BlockValidityWindow::new_unbounded(),
|
||||||
|
timestamp_validity_window: TimestampValidityWindow::new_unbounded(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let public_account_ids_bytes: &[u8] = &[42_u8; 32];
|
||||||
|
let nonces_bytes: &[u8] = &[1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
// all remaining vec fields are empty: u32 len=0
|
||||||
|
let empty_vec_bytes: &[u8] = &[0_u8; 4];
|
||||||
|
// validity windows: unbounded = {from: None (0u8), to: None (0u8)}
|
||||||
|
let unbounded_window_bytes: &[u8] = &[0_u8; 2];
|
||||||
|
|
||||||
|
let expected_borsh_vec: Vec<u8> = [
|
||||||
|
&[1_u8, 0, 0, 0], // public_account_ids
|
||||||
|
public_account_ids_bytes,
|
||||||
|
nonces_bytes,
|
||||||
|
empty_vec_bytes, // public_post_state
|
||||||
|
empty_vec_bytes, // encrypted_private_post_states
|
||||||
|
empty_vec_bytes, // new_commitments
|
||||||
|
empty_vec_bytes, // new_nullifiers
|
||||||
|
unbounded_window_bytes, // block_validity_window
|
||||||
|
unbounded_window_bytes, // timestamp_validity_window
|
||||||
|
]
|
||||||
|
.concat();
|
||||||
|
let expected_borsh: &[u8] = &expected_borsh_vec;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
borsh::to_vec(&msg).unwrap(),
|
||||||
|
expected_borsh,
|
||||||
|
"`privacy_preserving_transaction::hash_message()`: expected borsh order has changed"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut preimage = Vec::with_capacity(PREFIX.len() + expected_borsh.len());
|
||||||
|
preimage.extend_from_slice(PREFIX);
|
||||||
|
preimage.extend_from_slice(expected_borsh);
|
||||||
|
let expected_hash: [u8; 32] = Sha256::digest(&preimage).into();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
msg.hash_message(),
|
||||||
|
expected_hash,
|
||||||
|
"`privacy_preserving_transaction::hash_message()`: serialization has changed"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encrypted_account_data_constructor() {
|
fn encrypted_account_data_constructor() {
|
||||||
let npk = NullifierPublicKey::from(&[1; 32]);
|
let npk = NullifierPublicKey::from(&[1; 32]);
|
||||||
|
|||||||
@ -8,6 +8,8 @@ use sha2::{Digest as _, Sha256};
|
|||||||
|
|
||||||
use crate::{AccountId, error::NssaError, program::Program};
|
use crate::{AccountId, error::NssaError, program::Program};
|
||||||
|
|
||||||
|
const PREFIX: &[u8; 32] = b"/LEE/v0.3/Message/Public/\x00\x00\x00\x00\x00\x00\x00";
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
|
#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
|
||||||
pub struct Message {
|
pub struct Message {
|
||||||
pub program_id: ProgramId,
|
pub program_id: ProgramId,
|
||||||
@ -67,8 +69,6 @@ impl Message {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn hash_message(&self) -> [u8; 32] {
|
pub fn hash_message(&self) -> [u8; 32] {
|
||||||
const PREFIX: &[u8; 32] = b"/LEE/v0.3/Message/Public/\x00\x00\x00\x00\x00\x00\x00";
|
|
||||||
|
|
||||||
let mut bytes = Vec::with_capacity(
|
let mut bytes = Vec::with_capacity(
|
||||||
PREFIX
|
PREFIX
|
||||||
.len()
|
.len()
|
||||||
@ -81,3 +81,59 @@ impl Message {
|
|||||||
Sha256::digest(bytes).into()
|
Sha256::digest(bytes).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use nssa_core::account::{AccountId, Nonce};
|
||||||
|
use sha2::{Digest as _, Sha256};
|
||||||
|
|
||||||
|
use super::{Message, PREFIX};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn hash_message_public_pinned() {
|
||||||
|
let msg = Message::new_preserialized(
|
||||||
|
[1_u32; 8],
|
||||||
|
vec![AccountId::new([42_u8; 32])],
|
||||||
|
vec![Nonce(5)],
|
||||||
|
vec![],
|
||||||
|
);
|
||||||
|
|
||||||
|
// program_id: [1_u32; 8], each word as LE u32
|
||||||
|
let program_id_bytes: &[u8] = &[
|
||||||
|
1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1,
|
||||||
|
0, 0, 0,
|
||||||
|
];
|
||||||
|
// account_ids: AccountId([42_u8; 32])
|
||||||
|
let account_ids_bytes: &[u8] = &[42_u8; 32];
|
||||||
|
// nonces: u32 len=1, then Nonce(5) as LE u128
|
||||||
|
let nonces_bytes: &[u8] = &[1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
let instruction_data_bytes: &[u8] = &[0_u8; 4];
|
||||||
|
|
||||||
|
let expected_borsh_vec: Vec<u8> = [
|
||||||
|
program_id_bytes,
|
||||||
|
&[1_u8, 0, 0, 0], // account_ids len=1
|
||||||
|
account_ids_bytes,
|
||||||
|
nonces_bytes,
|
||||||
|
instruction_data_bytes,
|
||||||
|
]
|
||||||
|
.concat();
|
||||||
|
let expected_borsh: &[u8] = &expected_borsh_vec;
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
borsh::to_vec(&msg).unwrap(),
|
||||||
|
expected_borsh,
|
||||||
|
"`public_transaction::hash_message()`: expected borsh order has changed"
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut preimage = Vec::with_capacity(PREFIX.len() + expected_borsh.len());
|
||||||
|
preimage.extend_from_slice(PREFIX);
|
||||||
|
preimage.extend_from_slice(expected_borsh);
|
||||||
|
let expected_hash: [u8; 32] = Sha256::digest(&preimage).into();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
msg.hash_message(),
|
||||||
|
expected_hash,
|
||||||
|
"`public_transaction::hash_message()`: serialization has changed"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -164,6 +164,87 @@ impl From<InitialAccountData> for PersistentAccountData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use key_protocol::key_management::key_tree::{
|
||||||
|
chain_index::ChainIndex, keys_public::ChildKeysPublic,
|
||||||
|
};
|
||||||
|
use nssa::{AccountId, PrivateKey, PublicKey};
|
||||||
|
|
||||||
|
use super::PersistentAccountDataPublic;
|
||||||
|
|
||||||
|
// Root public account keys derived from a known test seed; see key_protocol's keys_public tests.
|
||||||
|
const CSK_BYTES: [u8; 32] = [
|
||||||
|
40, 35, 239, 19, 53, 178, 250, 55, 115, 12, 34, 3, 153, 153, 72, 170, 190, 36, 172, 36,
|
||||||
|
202, 148, 181, 228, 35, 222, 58, 84, 156, 24, 146, 86,
|
||||||
|
];
|
||||||
|
const CPK_BYTES: [u8; 32] = [
|
||||||
|
219, 141, 130, 105, 11, 203, 187, 124, 112, 75, 223, 22, 11, 164, 153, 127, 59, 247, 244,
|
||||||
|
166, 75, 66, 242, 224, 35, 156, 161, 75, 41, 51, 76, 245,
|
||||||
|
];
|
||||||
|
const CCC: [u8; 32] = [
|
||||||
|
238, 94, 84, 154, 56, 224, 80, 218, 133, 249, 179, 222, 9, 24, 17, 252, 120, 127, 222, 13,
|
||||||
|
146, 126, 232, 239, 113, 9, 194, 219, 190, 48, 187, 155,
|
||||||
|
];
|
||||||
|
|
||||||
|
fn make_child_keys_public() -> ChildKeysPublic {
|
||||||
|
ChildKeysPublic {
|
||||||
|
csk: PrivateKey::try_new(CSK_BYTES).unwrap(),
|
||||||
|
cpk: PublicKey::try_new(CPK_BYTES).unwrap(),
|
||||||
|
ccc: CCC,
|
||||||
|
cci: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_public_account_data(data: Option<ChildKeysPublic>) -> PersistentAccountDataPublic {
|
||||||
|
PersistentAccountDataPublic {
|
||||||
|
account_id: AccountId::new([0u8; 32]),
|
||||||
|
chain_index: ChainIndex::root(),
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn persistent_account_data_public_roundtrip_some() {
|
||||||
|
let original = make_public_account_data(Some(make_child_keys_public()));
|
||||||
|
let json = serde_json::to_string(&original).unwrap();
|
||||||
|
let decoded: PersistentAccountDataPublic = serde_json::from_str(&json).unwrap();
|
||||||
|
let keys = decoded.data.expect("data should be Some after roundtrip");
|
||||||
|
assert_eq!(keys.csk, PrivateKey::try_new(CSK_BYTES).unwrap());
|
||||||
|
assert_eq!(keys.cpk, PublicKey::try_new(CPK_BYTES).unwrap());
|
||||||
|
assert_eq!(keys.ccc, CCC);
|
||||||
|
assert_eq!(keys.cci, None);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn persistent_account_data_public_roundtrip_none() {
|
||||||
|
let original = make_public_account_data(None);
|
||||||
|
let json = serde_json::to_string(&original).unwrap();
|
||||||
|
let decoded: PersistentAccountDataPublic = serde_json::from_str(&json).unwrap();
|
||||||
|
assert!(decoded.data.is_none());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn persistent_account_data_public_legacy_shape_deserializes() {
|
||||||
|
let legacy_json = r#"{
|
||||||
|
"account_id": "11111111111111111111111111111111",
|
||||||
|
"chain_index": [],
|
||||||
|
"data": {
|
||||||
|
"csk": "2823ef1335b2fa37730c2203999948aabe24ac24ca94b5e423de3a549c189256",
|
||||||
|
"cpk": "db8d82690bcbbb7c704bdf160ba4997f3bf7f4a64b42f2e0239ca14b29334cf5",
|
||||||
|
"ccc": [238,94,84,154,56,224,80,218,133,249,179,222,9,24,17,252,120,127,222,13,146,126,232,239,113,9,194,219,190,48,187,155],
|
||||||
|
"cci": null
|
||||||
|
}
|
||||||
|
}"#;
|
||||||
|
let decoded: PersistentAccountDataPublic = serde_json::from_str(legacy_json).unwrap();
|
||||||
|
let keys = decoded.data.expect("legacy shape deserializes as Some");
|
||||||
|
assert_eq!(keys.csk, PrivateKey::try_new(CSK_BYTES).unwrap());
|
||||||
|
assert_eq!(keys.cpk, PublicKey::try_new(CPK_BYTES).unwrap());
|
||||||
|
assert_eq!(keys.ccc, CCC);
|
||||||
|
assert_eq!(keys.cci, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct GasConfig {
|
pub struct GasConfig {
|
||||||
/// Gas spent per deploying one byte of data.
|
/// Gas spent per deploying one byte of data.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user