mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-04 06:13:10 +00:00
fix: account masks updates to safe state
This commit is contained in:
parent
2078867d7b
commit
90205c6330
@ -85,6 +85,8 @@ impl<'de> Deserialize<'de> for Account {
|
|||||||
///A strucure, which represents all the visible(public) information
|
///A strucure, which represents all the visible(public) information
|
||||||
///
|
///
|
||||||
/// known to each node about account `address`
|
/// known to each node about account `address`
|
||||||
|
///
|
||||||
|
/// Main usage is to encode data for other account
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct AccountPublicMask {
|
pub struct AccountPublicMask {
|
||||||
pub nullifier_public_key: AffinePoint,
|
pub nullifier_public_key: AffinePoint,
|
||||||
@ -99,16 +101,13 @@ impl AccountPublicMask {
|
|||||||
viewing_public_key_receiver: AffinePoint,
|
viewing_public_key_receiver: AffinePoint,
|
||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> (CipherText, Nonce) {
|
) -> (CipherText, Nonce) {
|
||||||
ephemeral_key_holder.encrypt_data(viewing_public_key_receiver, data)
|
//Using of parent Account fuction
|
||||||
|
Account::encrypt_data(ephemeral_key_holder, viewing_public_key_receiver, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn make_tag(&self) -> Tag {
|
pub fn make_tag(&self) -> Tag {
|
||||||
self.address[0]
|
self.address[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn produce_ephemeral_key_holder(&self) -> EphemeralKeyHolder {
|
|
||||||
EphemeralKeyHolder::new_os_random()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Account {
|
impl Account {
|
||||||
@ -139,10 +138,6 @@ impl Account {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn produce_ephemeral_key_holder(&self) -> EphemeralKeyHolder {
|
|
||||||
self.key_holder.produce_ephemeral_key_holder()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn encrypt_data(
|
pub fn encrypt_data(
|
||||||
ephemeral_key_holder: &EphemeralKeyHolder,
|
ephemeral_key_holder: &EphemeralKeyHolder,
|
||||||
viewing_public_key_receiver: AffinePoint,
|
viewing_public_key_receiver: AffinePoint,
|
||||||
@ -267,4 +262,13 @@ mod tests {
|
|||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
assert_eq!(account.utxos.len(), 1);
|
assert_eq!(account.utxos.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn accounts_accounts_mask_tag_consistency() {
|
||||||
|
let account = Account::new();
|
||||||
|
|
||||||
|
let account_mask = account.make_account_public_mask();
|
||||||
|
|
||||||
|
assert_eq!(account.make_tag(), account_mask.make_tag());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,6 @@ use aes_gcm::{aead::Aead, Aes256Gcm, KeyInit};
|
|||||||
use common::merkle_tree_public::TreeHashType;
|
use common::merkle_tree_public::TreeHashType;
|
||||||
use constants_types::{CipherText, Nonce};
|
use constants_types::{CipherText, Nonce};
|
||||||
use elliptic_curve::point::AffineCoordinates;
|
use elliptic_curve::point::AffineCoordinates;
|
||||||
use ephemeral_key_holder::EphemeralKeyHolder;
|
|
||||||
use k256::AffinePoint;
|
use k256::AffinePoint;
|
||||||
use log::info;
|
use log::info;
|
||||||
use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder};
|
use secret_holders::{SeedHolder, TopSecretKeyHolder, UTXOSecretKeyHolder};
|
||||||
@ -55,10 +54,6 @@ impl AddressKeyHolder {
|
|||||||
(ephemeral_public_key_sender * self.utxo_secret_key_holder.viewing_secret_key).into()
|
(ephemeral_public_key_sender * self.utxo_secret_key_holder.viewing_secret_key).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn produce_ephemeral_key_holder(&self) -> EphemeralKeyHolder {
|
|
||||||
EphemeralKeyHolder::new_os_random()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn decrypt_data(
|
pub fn decrypt_data(
|
||||||
&self,
|
&self,
|
||||||
ephemeral_public_key_sender: AffinePoint,
|
ephemeral_public_key_sender: AffinePoint,
|
||||||
@ -114,6 +109,8 @@ mod tests {
|
|||||||
use elliptic_curve::point::AffineCoordinates;
|
use elliptic_curve::point::AffineCoordinates;
|
||||||
use k256::{AffinePoint, ProjectivePoint, Scalar};
|
use k256::{AffinePoint, ProjectivePoint, Scalar};
|
||||||
|
|
||||||
|
use crate::key_management::ephemeral_key_holder::EphemeralKeyHolder;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -136,7 +133,7 @@ mod tests {
|
|||||||
|
|
||||||
// Generate a random ephemeral public key sender
|
// Generate a random ephemeral public key sender
|
||||||
let scalar = Scalar::random(&mut OsRng);
|
let scalar = Scalar::random(&mut OsRng);
|
||||||
let ephemeral_public_key_sender = (ProjectivePoint::generator() * scalar).to_affine();
|
let ephemeral_public_key_sender = (ProjectivePoint::GENERATOR * scalar).to_affine();
|
||||||
|
|
||||||
// Calculate shared secret
|
// Calculate shared secret
|
||||||
let shared_secret =
|
let shared_secret =
|
||||||
@ -151,9 +148,8 @@ mod tests {
|
|||||||
let address_key_holder = AddressKeyHolder::new_os_random();
|
let address_key_holder = AddressKeyHolder::new_os_random();
|
||||||
|
|
||||||
// Generate an ephemeral key and shared secret
|
// Generate an ephemeral key and shared secret
|
||||||
let ephemeral_public_key_sender = address_key_holder
|
let ephemeral_public_key_sender =
|
||||||
.produce_ephemeral_key_holder()
|
EphemeralKeyHolder::new_os_random().generate_ephemeral_public_key();
|
||||||
.generate_ephemeral_public_key();
|
|
||||||
let shared_secret =
|
let shared_secret =
|
||||||
address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender);
|
address_key_holder.calculate_shared_secret_receiver(ephemeral_public_key_sender);
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,7 @@ use common::{
|
|||||||
};
|
};
|
||||||
use k256::AffinePoint;
|
use k256::AffinePoint;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use public_context::PublicSCContext;
|
use sc_core::public_context::PublicSCContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use utxo::utxo_core::UTXO;
|
use utxo::utxo_core::UTXO;
|
||||||
|
|
||||||
@ -19,7 +19,6 @@ use crate::{config::NodeConfig, ActionData};
|
|||||||
|
|
||||||
pub mod accounts_store;
|
pub mod accounts_store;
|
||||||
pub mod block_store;
|
pub mod block_store;
|
||||||
pub mod public_context;
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize)]
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct AccMap {
|
pub struct AccMap {
|
||||||
@ -267,6 +266,12 @@ impl NodeChainStore {
|
|||||||
account_masks,
|
account_masks,
|
||||||
comitment_store_root: self.utxo_commitments_store.get_root().unwrap_or([0; 32]),
|
comitment_store_root: self.utxo_commitments_store.get_root().unwrap_or([0; 32]),
|
||||||
pub_tx_store_root: self.pub_tx_store.get_root().unwrap_or([0; 32]),
|
pub_tx_store_root: self.pub_tx_store.get_root().unwrap_or([0; 32]),
|
||||||
|
nullifiers_set: self
|
||||||
|
.nullifier_store
|
||||||
|
.iter()
|
||||||
|
.map(|item| item.utxo_hash)
|
||||||
|
.collect(),
|
||||||
|
commitments_tree: self.utxo_commitments_store.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,180 +0,0 @@
|
|||||||
use std::collections::BTreeMap;
|
|
||||||
|
|
||||||
use accounts::account_core::{AccountAddress, AccountPublicMask};
|
|
||||||
use common::merkle_tree_public::TreeHashType;
|
|
||||||
use serde::{ser::SerializeStruct, Serialize};
|
|
||||||
|
|
||||||
pub const PUBLIC_SC_CONTEXT: &str = "PublicSCContext";
|
|
||||||
pub const CALLER_ADDRESS: &str = "caller_address";
|
|
||||||
pub const CALLER_BALANCE: &str = "caller_balance";
|
|
||||||
pub const ACCOUNT_MASKS_KEYS_SORTED: &str = "account_masks_keys_sorted";
|
|
||||||
pub const ACCOUNT_MASKS_VALUES_SORTED: &str = "account_masks_values_sorted";
|
|
||||||
pub const COMMITMENT_STORE_ROOT: &str = "commitment_store_root";
|
|
||||||
pub const PUT_TX_STORE_ROOT: &str = "put_tx_store_root";
|
|
||||||
|
|
||||||
///Strucutre, representing context, given to a smart contract on a call
|
|
||||||
pub struct PublicSCContext {
|
|
||||||
pub caller_address: AccountAddress,
|
|
||||||
pub caller_balance: u64,
|
|
||||||
pub account_masks: BTreeMap<AccountAddress, AccountPublicMask>,
|
|
||||||
pub comitment_store_root: TreeHashType,
|
|
||||||
pub pub_tx_store_root: TreeHashType,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for PublicSCContext {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: serde::Serializer,
|
|
||||||
{
|
|
||||||
let mut account_masks_keys: Vec<[u8; 32]> = self.account_masks.keys().cloned().collect();
|
|
||||||
account_masks_keys.sort();
|
|
||||||
|
|
||||||
let mut account_mask_values: Vec<AccountPublicMask> =
|
|
||||||
self.account_masks.values().cloned().collect();
|
|
||||||
account_mask_values.sort_by(|left, right| left.address.cmp(&right.address));
|
|
||||||
|
|
||||||
let mut s = serializer.serialize_struct(PUBLIC_SC_CONTEXT, 7)?;
|
|
||||||
|
|
||||||
s.serialize_field(CALLER_ADDRESS, &self.caller_address)?;
|
|
||||||
s.serialize_field(CALLER_BALANCE, &self.caller_balance)?;
|
|
||||||
s.serialize_field(ACCOUNT_MASKS_KEYS_SORTED, &account_masks_keys)?;
|
|
||||||
s.serialize_field(ACCOUNT_MASKS_VALUES_SORTED, &account_mask_values)?;
|
|
||||||
s.serialize_field(COMMITMENT_STORE_ROOT, &self.comitment_store_root)?;
|
|
||||||
s.serialize_field(PUT_TX_STORE_ROOT, &self.pub_tx_store_root)?;
|
|
||||||
|
|
||||||
s.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PublicSCContext {
|
|
||||||
///Produces `u64` from bytes in a vector
|
|
||||||
///
|
|
||||||
/// Assumes, that vector of le_bytes
|
|
||||||
pub fn produce_u64_from_fit_vec(data: Vec<u8>) -> u64 {
|
|
||||||
let data_len = data.len();
|
|
||||||
|
|
||||||
assert!(data_len <= 8);
|
|
||||||
let mut le_bytes: [u8; 8] = [0; 8];
|
|
||||||
|
|
||||||
for (idx, item) in data.into_iter().enumerate() {
|
|
||||||
le_bytes[idx] = item
|
|
||||||
}
|
|
||||||
|
|
||||||
u64::from_le_bytes(le_bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
///Produces vector of `u64` from context
|
|
||||||
pub fn produce_u64_list_from_context(&self) -> Result<Vec<u64>, serde_json::Error> {
|
|
||||||
let mut u64_list = vec![];
|
|
||||||
|
|
||||||
let ser_data = serde_json::to_vec(self)?;
|
|
||||||
|
|
||||||
//`ToDo` Replace with `next_chunk` usage, when feature stabilizes in Rust
|
|
||||||
for i in 0..=(ser_data.len() / 8) {
|
|
||||||
let next_chunk: Vec<u8>;
|
|
||||||
|
|
||||||
if (i + 1) * 8 < ser_data.len() {
|
|
||||||
next_chunk = ser_data[(i * 8)..((i + 1) * 8)].iter().cloned().collect();
|
|
||||||
} else {
|
|
||||||
next_chunk = ser_data[(i * 8)..(ser_data.len())]
|
|
||||||
.iter()
|
|
||||||
.cloned()
|
|
||||||
.collect();
|
|
||||||
}
|
|
||||||
|
|
||||||
u64_list.push(PublicSCContext::produce_u64_from_fit_vec(next_chunk));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(u64_list)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use accounts::account_core::Account;
|
|
||||||
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
fn create_test_context() -> PublicSCContext {
|
|
||||||
let caller_address = [1; 32];
|
|
||||||
let comitment_store_root = [3; 32];
|
|
||||||
let pub_tx_store_root = [4; 32];
|
|
||||||
|
|
||||||
let mut account_masks = BTreeMap::new();
|
|
||||||
|
|
||||||
let acc_1 = Account::new();
|
|
||||||
let acc_2 = Account::new();
|
|
||||||
let acc_3 = Account::new();
|
|
||||||
|
|
||||||
account_masks.insert(acc_1.address, acc_1.make_account_public_mask());
|
|
||||||
account_masks.insert(acc_2.address, acc_2.make_account_public_mask());
|
|
||||||
account_masks.insert(acc_3.address, acc_3.make_account_public_mask());
|
|
||||||
|
|
||||||
PublicSCContext {
|
|
||||||
caller_address,
|
|
||||||
caller_balance: 100,
|
|
||||||
account_masks,
|
|
||||||
comitment_store_root,
|
|
||||||
pub_tx_store_root,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn bin_ser_stability_test() {
|
|
||||||
let test_context = create_test_context();
|
|
||||||
|
|
||||||
let serialization_1 = serde_json::to_vec(&test_context).unwrap();
|
|
||||||
let serialization_2 = serde_json::to_vec(&test_context).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(serialization_1, serialization_2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn correct_u64_production_from_fit_vec() {
|
|
||||||
let le_vec = vec![1, 1, 1, 1, 2, 1, 1, 1];
|
|
||||||
|
|
||||||
let num = PublicSCContext::produce_u64_from_fit_vec(le_vec);
|
|
||||||
|
|
||||||
assert_eq!(num, 72340177133043969);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn correct_u64_production_from_small_vec() {
|
|
||||||
//7 items instead of 8
|
|
||||||
let le_vec = vec![1, 1, 1, 1, 2, 1, 1];
|
|
||||||
|
|
||||||
let num = PublicSCContext::produce_u64_from_fit_vec(le_vec);
|
|
||||||
|
|
||||||
assert_eq!(num, 282583095116033);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn correct_u64_production_from_small_vec_le_bytes() {
|
|
||||||
//7 items instead of 8
|
|
||||||
let le_vec = vec![1, 1, 1, 1, 2, 1, 1];
|
|
||||||
let le_vec_res = [1, 1, 1, 1, 2, 1, 1, 0];
|
|
||||||
|
|
||||||
let num = PublicSCContext::produce_u64_from_fit_vec(le_vec);
|
|
||||||
|
|
||||||
assert_eq!(num.to_le_bytes(), le_vec_res);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn correct_u64_production_from_unfit_vec_should_panic() {
|
|
||||||
//9 items instead of 8
|
|
||||||
let le_vec = vec![1, 1, 1, 1, 2, 1, 1, 1, 1];
|
|
||||||
|
|
||||||
PublicSCContext::produce_u64_from_fit_vec(le_vec);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn consistent_len_of_context_commitments() {
|
|
||||||
let test_context = create_test_context();
|
|
||||||
|
|
||||||
let context_num_vec1 = test_context.produce_u64_list_from_context().unwrap();
|
|
||||||
let context_num_vec2 = test_context.produce_u64_list_from_context().unwrap();
|
|
||||||
|
|
||||||
assert_eq!(context_num_vec1.len(), context_num_vec2.len());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -5,7 +5,10 @@ use std::sync::{
|
|||||||
|
|
||||||
use common::ExecutionFailureKind;
|
use common::ExecutionFailureKind;
|
||||||
|
|
||||||
use accounts::account_core::{Account, AccountAddress};
|
use accounts::{
|
||||||
|
account_core::{Account, AccountAddress},
|
||||||
|
key_management::ephemeral_key_holder::EphemeralKeyHolder,
|
||||||
|
};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use chain_storage::NodeChainStore;
|
use chain_storage::NodeChainStore;
|
||||||
use common::transaction::{Transaction, TransactionPayload, TxKind};
|
use common::transaction::{Transaction, TransactionPayload, TxKind};
|
||||||
@ -197,7 +200,7 @@ impl NodeCore {
|
|||||||
|
|
||||||
let account = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
let account = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
||||||
|
|
||||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
let ephm_key_holder = EphemeralKeyHolder::new_os_random();
|
||||||
ephm_key_holder.log();
|
ephm_key_holder.log();
|
||||||
|
|
||||||
let eph_pub_key =
|
let eph_pub_key =
|
||||||
@ -286,7 +289,7 @@ impl NodeCore {
|
|||||||
|
|
||||||
let account = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
let account = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
||||||
|
|
||||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
let ephm_key_holder = EphemeralKeyHolder::new_os_random();
|
||||||
ephm_key_holder.log();
|
ephm_key_holder.log();
|
||||||
|
|
||||||
let eph_pub_key =
|
let eph_pub_key =
|
||||||
@ -401,7 +404,7 @@ impl NodeCore {
|
|||||||
.map(|(utxo, _)| utxo.clone())
|
.map(|(utxo, _)| utxo.clone())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
let ephm_key_holder = EphemeralKeyHolder::new_os_random();
|
||||||
ephm_key_holder.log();
|
ephm_key_holder.log();
|
||||||
|
|
||||||
let eph_pub_key =
|
let eph_pub_key =
|
||||||
@ -523,7 +526,7 @@ impl NodeCore {
|
|||||||
.map(|utxo| utxo.hash)
|
.map(|utxo| utxo.hash)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
let ephm_key_holder = EphemeralKeyHolder::new_os_random();
|
||||||
ephm_key_holder.log();
|
ephm_key_holder.log();
|
||||||
|
|
||||||
let eph_pub_key =
|
let eph_pub_key =
|
||||||
@ -669,7 +672,7 @@ impl NodeCore {
|
|||||||
.map(|(utxo, _)| utxo.clone())
|
.map(|(utxo, _)| utxo.clone())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
let ephm_key_holder = EphemeralKeyHolder::new_os_random();
|
||||||
ephm_key_holder.log();
|
ephm_key_holder.log();
|
||||||
|
|
||||||
let eph_pub_key =
|
let eph_pub_key =
|
||||||
@ -1387,7 +1390,7 @@ impl NodeCore {
|
|||||||
.map(|(utxo, _)| utxo.clone())
|
.map(|(utxo, _)| utxo.clone())
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
let ephm_key_holder = EphemeralKeyHolder::new_os_random();
|
||||||
ephm_key_holder.log();
|
ephm_key_holder.log();
|
||||||
|
|
||||||
let eph_pub_key =
|
let eph_pub_key =
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use accounts::account_core::Account;
|
use accounts::{account_core::Account, key_management::ephemeral_key_holder::EphemeralKeyHolder};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use common::transaction::{TransactionPayload, TxKind};
|
use common::transaction::{TransactionPayload, TxKind};
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
@ -40,7 +40,7 @@ pub fn encode_utxos_to_receivers(
|
|||||||
let mut all_encoded_data = vec![];
|
let mut all_encoded_data = vec![];
|
||||||
|
|
||||||
for (utxo, receiver) in utxos_receivers {
|
for (utxo, receiver) in utxos_receivers {
|
||||||
let ephm_key_holder = &receiver.produce_ephemeral_key_holder();
|
let ephm_key_holder = EphemeralKeyHolder::new_os_random();
|
||||||
|
|
||||||
let encoded_data = Account::encrypt_data(
|
let encoded_data = Account::encrypt_data(
|
||||||
&ephm_key_holder,
|
&ephm_key_holder,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user