mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-23 07:33:10 +00:00
Merge pull request #57 from vacp2p/provability
Implementation of Public State Provability
This commit is contained in:
commit
373e3b953d
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -1154,6 +1154,7 @@ dependencies = [
|
||||
"env_logger",
|
||||
"log",
|
||||
"monotree",
|
||||
"secp256k1-zkp",
|
||||
"sequencer_core",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@ -4685,6 +4686,7 @@ dependencies = [
|
||||
"log",
|
||||
"mempool",
|
||||
"rand 0.8.5",
|
||||
"secp256k1-zkp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"storage",
|
||||
@ -4975,6 +4977,7 @@ dependencies = [
|
||||
"monotree",
|
||||
"rocksdb",
|
||||
"rs_merkle",
|
||||
"secp256k1-zkp",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2 0.10.8",
|
||||
|
||||
@ -29,6 +29,7 @@ pub struct Account {
|
||||
///A strucure, which represents all the visible(public) information
|
||||
///
|
||||
/// known to each node about account `address`
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct AccountPublicMask {
|
||||
pub nullifier_public_key: AffinePoint,
|
||||
pub viewing_public_key: AffinePoint,
|
||||
|
||||
@ -40,6 +40,8 @@ impl From<SequencerRpcError> for SequencerClientError {
|
||||
pub enum ExecutionFailureKind {
|
||||
#[error("Failed to write into builder err: {0:?}")]
|
||||
WriteError(anyhow::Error),
|
||||
#[error("Failed to interact with a db err: {0:?}")]
|
||||
DBError(anyhow::Error),
|
||||
#[error("Failed to build builder err: {0:?}")]
|
||||
BuilderError(anyhow::Error),
|
||||
#[error("Failed prove execution err: {0:?}")]
|
||||
@ -70,4 +72,8 @@ impl ExecutionFailureKind {
|
||||
pub fn prove_error(err: anyhow::Error) -> Self {
|
||||
Self::ProveError(err)
|
||||
}
|
||||
|
||||
pub fn db_error(err: anyhow::Error) -> Self {
|
||||
Self::DBError(err)
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,6 +13,10 @@ sha2.workspace = true
|
||||
elliptic-curve.workspace = true
|
||||
monotree.workspace = true
|
||||
|
||||
[dependencies.secp256k1-zkp]
|
||||
workspace = true
|
||||
features = ["std", "rand-std", "rand", "serde", "global-context"]
|
||||
|
||||
[dependencies.storage]
|
||||
path = "../storage"
|
||||
|
||||
|
||||
@ -6,6 +6,7 @@ use elliptic_curve::{
|
||||
consts::{B0, B1},
|
||||
generic_array::GenericArray,
|
||||
};
|
||||
use secp256k1_zkp::PedersenCommitment;
|
||||
use sha2::digest::typenum::{UInt, UTerm};
|
||||
|
||||
pub type CipherText = Vec<u8>;
|
||||
@ -40,6 +41,8 @@ pub struct Transaction {
|
||||
pub encoded_data: Vec<(CipherText, Vec<u8>)>,
|
||||
///Transaction senders ephemeral pub key
|
||||
pub ephemeral_pub_key: Vec<u8>,
|
||||
///Public (Pedersen) commitment
|
||||
pub commitment: PedersenCommitment,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@ -62,4 +65,6 @@ pub struct TransactionPayload {
|
||||
pub encoded_data: Vec<(CipherText, Vec<u8>)>,
|
||||
///Transaction senders ephemeral pub key
|
||||
pub ephemeral_pub_key: Vec<u8>,
|
||||
///Public (Pedersen) commitment
|
||||
pub commitment: PedersenCommitment,
|
||||
}
|
||||
|
||||
@ -154,6 +154,45 @@ pub fn verify_commitment(
|
||||
commitment == *pedersen_commitment
|
||||
}
|
||||
|
||||
// new_commitment
|
||||
pub fn new_commitment(public_info: u64, secret_r: &[u8]) -> (Tweak, &[u8], PedersenCommitment) {
|
||||
let generator_blinding_factor = Tweak::new(&mut thread_rng());
|
||||
let commitment_secrets = CommitmentSecrets {
|
||||
value: public_info,
|
||||
value_blinding_factor: Tweak::from_slice(secret_r).unwrap(),
|
||||
generator_blinding_factor,
|
||||
};
|
||||
|
||||
let tag = tag_random();
|
||||
let commitment = commit(&commitment_secrets, tag);
|
||||
|
||||
(generator_blinding_factor, secret_r, commitment)
|
||||
}
|
||||
|
||||
// new_commitment for a Vec of values
|
||||
pub fn new_commitment_vec(
|
||||
public_info_vec: Vec<u64>,
|
||||
secret_r: &[u8],
|
||||
) -> (Tweak, &[u8], Vec<PedersenCommitment>) {
|
||||
let generator_blinding_factor = Tweak::new(&mut thread_rng());
|
||||
let tag = tag_random();
|
||||
|
||||
let vec_commitments = public_info_vec
|
||||
.into_iter()
|
||||
.map(|public_info| {
|
||||
let commitment_secrets = CommitmentSecrets {
|
||||
value: public_info,
|
||||
value_blinding_factor: Tweak::from_slice(secret_r).unwrap(),
|
||||
generator_blinding_factor,
|
||||
};
|
||||
|
||||
commit(&commitment_secrets, tag)
|
||||
})
|
||||
.collect();
|
||||
|
||||
(generator_blinding_factor, secret_r, vec_commitments)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
fn de_kernel(
|
||||
root_commitment: &[u8],
|
||||
|
||||
@ -11,6 +11,7 @@ use anyhow::Result;
|
||||
use config::NodeConfig;
|
||||
use executions::private_exec::{generate_commitments, generate_nullifiers};
|
||||
use log::info;
|
||||
use sc_core::proofs_circuits::pedersen_commitment_vec;
|
||||
use sequencer_client::{json::SendTxResponse, SequencerClient};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use storage::NodeChainStore;
|
||||
@ -29,6 +30,23 @@ pub mod executions;
|
||||
pub mod sequencer_client;
|
||||
pub mod storage;
|
||||
|
||||
fn vec_u8_to_vec_u64(bytes: Vec<u8>) -> Vec<u64> {
|
||||
// Pad with zeros to make sure it's a multiple of 8
|
||||
let mut padded = bytes.clone();
|
||||
while padded.len() % 8 != 0 {
|
||||
padded.push(0);
|
||||
}
|
||||
|
||||
padded
|
||||
.chunks(8)
|
||||
.map(|chunk| {
|
||||
let mut array = [0u8; 8];
|
||||
array.copy_from_slice(chunk);
|
||||
u64::from_le_bytes(array)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct MintMoneyPublicTx {
|
||||
pub acc: AccountAddress,
|
||||
@ -175,9 +193,9 @@ impl NodeCore {
|
||||
|
||||
let acc_map_read_guard = self.storage.read().await;
|
||||
|
||||
let accout = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
||||
let account = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
||||
|
||||
let ephm_key_holder = &accout.produce_ephemeral_key_holder();
|
||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
||||
ephm_key_holder.log();
|
||||
|
||||
let eph_pub_key =
|
||||
@ -185,14 +203,37 @@ impl NodeCore {
|
||||
|
||||
let encoded_data = Account::encrypt_data(
|
||||
&ephm_key_holder,
|
||||
accout.key_holder.viewing_public_key,
|
||||
account.key_holder.viewing_public_key,
|
||||
&serde_json::to_vec(&utxo).unwrap(),
|
||||
);
|
||||
|
||||
let tag = accout.make_tag();
|
||||
let tag = account.make_tag();
|
||||
|
||||
let comm = generate_commitments(&vec![utxo]);
|
||||
|
||||
// TODO: fix address when correspoding method will be added
|
||||
let sc_addr = "";
|
||||
|
||||
let sc_state = acc_map_read_guard
|
||||
.block_store
|
||||
.get_sc_sc_state(sc_addr)
|
||||
.map_err(ExecutionFailureKind::db_error)?;
|
||||
|
||||
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
|
||||
.into_iter()
|
||||
.map(|slice| vec_u8_to_vec_u64(slice.to_vec()))
|
||||
.collect();
|
||||
|
||||
let context = acc_map_read_guard.produce_context(account.address);
|
||||
|
||||
//Will not panic, as PublicScContext is serializable
|
||||
let context_public_info: Vec<u64> = context.produce_u64_list_from_context().unwrap();
|
||||
vec_values_u64.push(context_public_info);
|
||||
|
||||
let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect();
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
|
||||
|
||||
Ok((
|
||||
TransactionPayload {
|
||||
tx_kind: TxKind::Private,
|
||||
@ -210,6 +251,9 @@ impl NodeCore {
|
||||
.unwrap(),
|
||||
encoded_data: vec![(encoded_data.0, encoded_data.1.to_vec(), tag)],
|
||||
ephemeral_pub_key: eph_pub_key.to_vec(),
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
}
|
||||
.into(),
|
||||
result_hash,
|
||||
@ -227,9 +271,9 @@ impl NodeCore {
|
||||
|
||||
let acc_map_read_guard = self.storage.read().await;
|
||||
|
||||
let accout = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
||||
let account = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
||||
|
||||
let ephm_key_holder = &accout.produce_ephemeral_key_holder();
|
||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
||||
ephm_key_holder.log();
|
||||
|
||||
let eph_pub_key =
|
||||
@ -241,10 +285,10 @@ impl NodeCore {
|
||||
(
|
||||
Account::encrypt_data(
|
||||
&ephm_key_holder,
|
||||
accout.key_holder.viewing_public_key,
|
||||
account.key_holder.viewing_public_key,
|
||||
&serde_json::to_vec(&utxo).unwrap(),
|
||||
),
|
||||
accout.make_tag(),
|
||||
account.make_tag(),
|
||||
)
|
||||
})
|
||||
.map(|((ciphertext, nonce), tag)| (ciphertext, nonce.to_vec(), tag))
|
||||
@ -252,6 +296,29 @@ impl NodeCore {
|
||||
|
||||
let comm = generate_commitments(&utxos);
|
||||
|
||||
// TODO: fix address when correspoding method will be added
|
||||
let sc_addr = "";
|
||||
|
||||
let sc_state = acc_map_read_guard
|
||||
.block_store
|
||||
.get_sc_sc_state(sc_addr)
|
||||
.map_err(ExecutionFailureKind::db_error)?;
|
||||
|
||||
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
|
||||
.into_iter()
|
||||
.map(|slice| vec_u8_to_vec_u64(slice.to_vec()))
|
||||
.collect();
|
||||
|
||||
let context = acc_map_read_guard.produce_context(account.address);
|
||||
|
||||
//Will not panic, as PublicScContext is serializable
|
||||
let context_public_info: Vec<u64> = context.produce_u64_list_from_context().unwrap();
|
||||
vec_values_u64.push(context_public_info);
|
||||
|
||||
let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect();
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
|
||||
|
||||
Ok((
|
||||
TransactionPayload {
|
||||
tx_kind: TxKind::Private,
|
||||
@ -269,6 +336,9 @@ impl NodeCore {
|
||||
.unwrap(),
|
||||
encoded_data,
|
||||
ephemeral_pub_key: eph_pub_key.to_vec(),
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
}
|
||||
.into(),
|
||||
result_hashes,
|
||||
@ -283,11 +353,11 @@ impl NodeCore {
|
||||
) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> {
|
||||
let acc_map_read_guard = self.storage.read().await;
|
||||
|
||||
let accout = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap();
|
||||
let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap();
|
||||
|
||||
let nullifier = generate_nullifiers(
|
||||
&utxo,
|
||||
&accout
|
||||
&account
|
||||
.key_holder
|
||||
.utxo_secret_key_holder
|
||||
.nullifier_secret_key
|
||||
@ -306,7 +376,7 @@ impl NodeCore {
|
||||
.map(|(utxo, _)| utxo.clone())
|
||||
.collect();
|
||||
|
||||
let ephm_key_holder = &accout.produce_ephemeral_key_holder();
|
||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
||||
ephm_key_holder.log();
|
||||
|
||||
let eph_pub_key =
|
||||
@ -331,6 +401,29 @@ impl NodeCore {
|
||||
|
||||
let commitments = generate_commitments(&utxos);
|
||||
|
||||
// TODO: fix address when correspoding method will be added
|
||||
let sc_addr = "";
|
||||
|
||||
let sc_state = acc_map_read_guard
|
||||
.block_store
|
||||
.get_sc_sc_state(sc_addr)
|
||||
.map_err(ExecutionFailureKind::db_error)?;
|
||||
|
||||
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
|
||||
.into_iter()
|
||||
.map(|slice| vec_u8_to_vec_u64(slice.to_vec()))
|
||||
.collect();
|
||||
|
||||
let context = acc_map_read_guard.produce_context(account.address);
|
||||
|
||||
//Will not panic, as PublicScContext is serializable
|
||||
let context_public_info: Vec<u64> = context.produce_u64_list_from_context().unwrap();
|
||||
vec_values_u64.push(context_public_info);
|
||||
|
||||
let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect();
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
|
||||
|
||||
Ok((
|
||||
TransactionPayload {
|
||||
tx_kind: TxKind::Private,
|
||||
@ -348,6 +441,9 @@ impl NodeCore {
|
||||
.unwrap(),
|
||||
encoded_data,
|
||||
ephemeral_pub_key: eph_pub_key.to_vec(),
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
}
|
||||
.into(),
|
||||
utxo_hashes,
|
||||
@ -363,9 +459,9 @@ impl NodeCore {
|
||||
) -> Result<(Transaction, Vec<[u8; 32]>, Vec<[u8; 32]>), ExecutionFailureKind> {
|
||||
let acc_map_read_guard = self.storage.read().await;
|
||||
|
||||
let accout = acc_map_read_guard.acc_map.get(&utxos[0].owner).unwrap();
|
||||
let account = acc_map_read_guard.acc_map.get(&utxos[0].owner).unwrap();
|
||||
|
||||
let nsk = accout
|
||||
let nsk = account
|
||||
.key_holder
|
||||
.utxo_secret_key_holder
|
||||
.nullifier_secret_key
|
||||
@ -391,7 +487,7 @@ impl NodeCore {
|
||||
.map(|utxo| utxo.hash)
|
||||
.collect();
|
||||
|
||||
let ephm_key_holder = &accout.produce_ephemeral_key_holder();
|
||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
||||
ephm_key_holder.log();
|
||||
|
||||
let eph_pub_key =
|
||||
@ -438,6 +534,29 @@ impl NodeCore {
|
||||
|
||||
commitments.extend(commitments_1);
|
||||
|
||||
// TODO: fix address when correspoding method will be added
|
||||
let sc_addr = "";
|
||||
|
||||
let sc_state = acc_map_read_guard
|
||||
.block_store
|
||||
.get_sc_sc_state(sc_addr)
|
||||
.map_err(ExecutionFailureKind::db_error)?;
|
||||
|
||||
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
|
||||
.into_iter()
|
||||
.map(|slice| vec_u8_to_vec_u64(slice.to_vec()))
|
||||
.collect();
|
||||
|
||||
let context = acc_map_read_guard.produce_context(account.address);
|
||||
|
||||
//Will not panic, as PublicScContext is serializable
|
||||
let context_public_info: Vec<u64> = context.produce_u64_list_from_context().unwrap();
|
||||
vec_values_u64.push(context_public_info);
|
||||
|
||||
let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect();
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
|
||||
|
||||
Ok((
|
||||
TransactionPayload {
|
||||
tx_kind: TxKind::Private,
|
||||
@ -455,6 +574,9 @@ impl NodeCore {
|
||||
.unwrap(),
|
||||
encoded_data,
|
||||
ephemeral_pub_key: eph_pub_key.to_vec(),
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
}
|
||||
.into(),
|
||||
utxo_hashes_receiver,
|
||||
@ -472,6 +594,7 @@ impl NodeCore {
|
||||
|
||||
let account = acc_map_read_guard.acc_map.get(&acc).unwrap();
|
||||
|
||||
// TODO: add to transaction structure and do the check. Research has to update the scheme as well.
|
||||
let commitment = sc_core::transaction_payloads_tools::generate_secret_random_commitment(
|
||||
balance, account,
|
||||
)
|
||||
@ -523,6 +646,29 @@ impl NodeCore {
|
||||
|
||||
let commitments = generate_commitments(&utxos);
|
||||
|
||||
// TODO: fix address when correspoding method will be added
|
||||
let sc_addr = "";
|
||||
|
||||
let sc_state = acc_map_read_guard
|
||||
.block_store
|
||||
.get_sc_sc_state(sc_addr)
|
||||
.map_err(ExecutionFailureKind::db_error)?;
|
||||
|
||||
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
|
||||
.into_iter()
|
||||
.map(|slice| vec_u8_to_vec_u64(slice.to_vec()))
|
||||
.collect();
|
||||
|
||||
let context = acc_map_read_guard.produce_context(account.address);
|
||||
|
||||
//Will not panic, as PublicScContext is serializable
|
||||
let context_public_info: Vec<u64> = context.produce_u64_list_from_context().unwrap();
|
||||
vec_values_u64.push(context_public_info);
|
||||
|
||||
let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect();
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
|
||||
|
||||
Ok((
|
||||
TransactionPayload {
|
||||
tx_kind: TxKind::Shielded,
|
||||
@ -546,6 +692,9 @@ impl NodeCore {
|
||||
.unwrap(),
|
||||
encoded_data,
|
||||
ephemeral_pub_key: eph_pub_key.to_vec(),
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
}
|
||||
.into(),
|
||||
utxo_hashes,
|
||||
@ -566,11 +715,11 @@ impl NodeCore {
|
||||
.unwrap()
|
||||
.hash;
|
||||
|
||||
let accout = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap();
|
||||
let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap();
|
||||
|
||||
let nullifier = generate_nullifiers(
|
||||
&utxo,
|
||||
&accout
|
||||
&account
|
||||
.key_holder
|
||||
.utxo_secret_key_holder
|
||||
.nullifier_secret_key
|
||||
@ -580,6 +729,29 @@ impl NodeCore {
|
||||
|
||||
let (resulting_balances, receipt) = prove_send_utxo_deshielded(utxo, receivers)?;
|
||||
|
||||
// TODO: fix address when correspoding method will be added
|
||||
let sc_addr = "";
|
||||
|
||||
let sc_state = acc_map_read_guard
|
||||
.block_store
|
||||
.get_sc_sc_state(sc_addr)
|
||||
.map_err(ExecutionFailureKind::db_error)?;
|
||||
|
||||
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
|
||||
.into_iter()
|
||||
.map(|slice| vec_u8_to_vec_u64(slice.to_vec()))
|
||||
.collect();
|
||||
|
||||
let context = acc_map_read_guard.produce_context(account.address);
|
||||
|
||||
//Will not panic, as PublicScContext is serializable
|
||||
let context_public_info: Vec<u64> = context.produce_u64_list_from_context().unwrap();
|
||||
vec_values_u64.push(context_public_info);
|
||||
|
||||
let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect();
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
|
||||
|
||||
Ok(TransactionPayload {
|
||||
tx_kind: TxKind::Deshielded,
|
||||
execution_input: serde_json::to_vec(&ActionData::SendMoneyDeshieldedTx(
|
||||
@ -596,6 +768,9 @@ impl NodeCore {
|
||||
.unwrap(),
|
||||
encoded_data: vec![],
|
||||
ephemeral_pub_key: vec![],
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
}
|
||||
.into())
|
||||
}
|
||||
@ -661,6 +836,17 @@ impl NodeCore {
|
||||
//Considering proof time, needs to be done before proof
|
||||
let tx_roots = self.get_roots().await;
|
||||
|
||||
let public_context = {
|
||||
let read_guard = self.storage.read().await;
|
||||
|
||||
read_guard.produce_context(acc)
|
||||
};
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(
|
||||
//Will not panic, as public context is serializable
|
||||
public_context.produce_u64_list_from_context().unwrap(),
|
||||
);
|
||||
|
||||
let tx: Transaction =
|
||||
sc_core::transaction_payloads_tools::create_public_transaction_payload(
|
||||
serde_json::to_vec(&ActionData::MintMoneyPublicTx(MintMoneyPublicTx {
|
||||
@ -668,6 +854,9 @@ impl NodeCore {
|
||||
amount,
|
||||
}))
|
||||
.unwrap(),
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
)
|
||||
.into();
|
||||
tx.log();
|
||||
@ -1102,11 +1291,11 @@ impl NodeCore {
|
||||
) -> Result<(Transaction, Vec<(AccountAddress, [u8; 32])>), ExecutionFailureKind> {
|
||||
let acc_map_read_guard = self.storage.read().await;
|
||||
|
||||
let accout = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap();
|
||||
let account = acc_map_read_guard.acc_map.get(&utxo.owner).unwrap();
|
||||
|
||||
let nullifier = generate_nullifiers(
|
||||
&utxo,
|
||||
&accout
|
||||
&account
|
||||
.key_holder
|
||||
.utxo_secret_key_holder
|
||||
.nullifier_secret_key
|
||||
@ -1125,7 +1314,7 @@ impl NodeCore {
|
||||
.map(|(utxo, _)| utxo.clone())
|
||||
.collect();
|
||||
|
||||
let ephm_key_holder = &accout.produce_ephemeral_key_holder();
|
||||
let ephm_key_holder = &account.produce_ephemeral_key_holder();
|
||||
ephm_key_holder.log();
|
||||
|
||||
let eph_pub_key =
|
||||
@ -1164,6 +1353,29 @@ impl NodeCore {
|
||||
.collect(),
|
||||
});
|
||||
|
||||
// TODO: fix address when correspoding method will be added
|
||||
let sc_addr = "";
|
||||
|
||||
let sc_state = acc_map_read_guard
|
||||
.block_store
|
||||
.get_sc_sc_state(sc_addr)
|
||||
.map_err(ExecutionFailureKind::db_error)?;
|
||||
|
||||
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
|
||||
.into_iter()
|
||||
.map(|slice| vec_u8_to_vec_u64(slice.to_vec()))
|
||||
.collect();
|
||||
|
||||
let context = acc_map_read_guard.produce_context(account.address);
|
||||
|
||||
//Will not panic, as PublicScContext is serializable
|
||||
let context_public_info: Vec<u64> = context.produce_u64_list_from_context().unwrap();
|
||||
vec_values_u64.push(context_public_info);
|
||||
|
||||
let vec_public_info: Vec<u64> = vec_values_u64.into_iter().flatten().collect();
|
||||
|
||||
let (tweak, secret_r, commitment) = pedersen_commitment_vec(vec_public_info);
|
||||
|
||||
Ok((
|
||||
TransactionPayload {
|
||||
tx_kind: TxKind::Shielded,
|
||||
@ -1182,6 +1394,9 @@ impl NodeCore {
|
||||
.unwrap(),
|
||||
encoded_data,
|
||||
ephemeral_pub_key: eph_pub_key.to_vec(),
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
}
|
||||
.into(),
|
||||
utxo_hashes,
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use storage::sc_db_utils::DataBlob;
|
||||
use storage::{block::Block, RocksDBIO};
|
||||
|
||||
pub struct NodeBlockStore {
|
||||
@ -41,6 +42,10 @@ impl NodeBlockStore {
|
||||
pub fn put_block_at_id(&self, block: Block) -> Result<()> {
|
||||
Ok(self.dbio.put_block(block, false)?)
|
||||
}
|
||||
|
||||
pub fn get_sc_sc_state(&self, sc_addr: &str) -> Result<Vec<DataBlob>> {
|
||||
Ok(self.dbio.get_sc_sc_state(sc_addr)?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use accounts::account_core::{AccountAddress, AccountPublicMask};
|
||||
use serde::{ser::SerializeStruct, Serialize};
|
||||
use storage::merkle_tree_public::TreeHashType;
|
||||
|
||||
///Strucutre, representing context, given to a smart contract on a call
|
||||
@ -12,3 +13,164 @@ pub struct PublicSCContext {
|
||||
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("PublicSCContext", 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("nullifier_store_root", &self.nullifier_store_root)?;
|
||||
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 nullifier_store_root = [2; 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,
|
||||
nullifier_store_root,
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,6 +66,7 @@ pub fn cast_common_execution_error_into_rpc_error(comm_exec_err: ExecutionFailur
|
||||
match comm_exec_err {
|
||||
ExecutionFailureKind::BuilderError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::WriteError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::DBError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::DecodeError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::ProveError(_) => RpcError::new_internal_error(None, &error_string),
|
||||
ExecutionFailureKind::AmountMismatchError => {
|
||||
|
||||
@ -2,7 +2,7 @@ use bincode;
|
||||
use k256::Scalar;
|
||||
use monotree::hasher::Blake3;
|
||||
use monotree::{Hasher, Monotree};
|
||||
use rand::thread_rng;
|
||||
use rand::{thread_rng, RngCore};
|
||||
use secp256k1_zkp::{CommitmentSecrets, Generator, PedersenCommitment, Tag, Tweak, SECP256K1};
|
||||
use sha2::{Digest, Sha256};
|
||||
use storage::{
|
||||
@ -168,6 +168,32 @@ pub fn check_balances(public_info: u128, output_utxos: &[UTXO]) -> bool {
|
||||
public_info == total_output
|
||||
}
|
||||
|
||||
// new_commitment for a Vec of values
|
||||
pub fn pedersen_commitment_vec(
|
||||
public_info_vec: Vec<u64>,
|
||||
) -> (Tweak, [u8; 32], Vec<PedersenCommitment>) {
|
||||
let mut random_val: [u8; 32] = [0; 32];
|
||||
thread_rng().fill_bytes(&mut random_val);
|
||||
|
||||
let generator_blinding_factor = Tweak::new(&mut thread_rng());
|
||||
let tag = tag_random();
|
||||
|
||||
let vec_commitments = public_info_vec
|
||||
.into_iter()
|
||||
.map(|public_info| {
|
||||
let commitment_secrets = CommitmentSecrets {
|
||||
value: public_info,
|
||||
value_blinding_factor: Tweak::from_slice(&random_val).unwrap(),
|
||||
generator_blinding_factor,
|
||||
};
|
||||
|
||||
commit(&commitment_secrets, tag)
|
||||
})
|
||||
.collect();
|
||||
|
||||
(generator_blinding_factor, random_val, vec_commitments)
|
||||
}
|
||||
|
||||
// Verify Pedersen commitment
|
||||
|
||||
// takes the public_info, secret_r and pedersen_commitment and
|
||||
|
||||
@ -8,7 +8,12 @@ use utxo::utxo_core::UTXO;
|
||||
|
||||
use crate::proofs_circuits::{commit, generate_nullifiers, tag_random};
|
||||
|
||||
pub fn create_public_transaction_payload(execution_input: Vec<u8>) -> TransactionPayload {
|
||||
pub fn create_public_transaction_payload(
|
||||
execution_input: Vec<u8>,
|
||||
commitment: Vec<PedersenCommitment>,
|
||||
tweak: Tweak,
|
||||
secret_r: [u8; 32],
|
||||
) -> TransactionPayload {
|
||||
TransactionPayload {
|
||||
tx_kind: TxKind::Public,
|
||||
execution_input,
|
||||
@ -19,6 +24,9 @@ pub fn create_public_transaction_payload(execution_input: Vec<u8>) -> Transactio
|
||||
execution_proof_private: "".to_string(),
|
||||
encoded_data: vec![],
|
||||
ephemeral_pub_key: vec![],
|
||||
commitment,
|
||||
tweak,
|
||||
secret_r,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -21,3 +21,7 @@ path = "../mempool"
|
||||
|
||||
[dependencies.accounts]
|
||||
path = "../accounts"
|
||||
|
||||
[dependencies.secp256k1-zkp]
|
||||
workspace = true
|
||||
features = ["std", "rand-std", "rand", "serde", "global-context"]
|
||||
|
||||
@ -263,6 +263,7 @@ mod tests {
|
||||
use std::{fmt::format, path::PathBuf};
|
||||
|
||||
use rand::Rng;
|
||||
use secp256k1_zkp::Tweak;
|
||||
use storage::transaction::{Transaction, TxKind};
|
||||
use transaction_mempool::TransactionMempool;
|
||||
|
||||
@ -289,6 +290,8 @@ mod tests {
|
||||
utxo_commitments_spent_hashes: Vec<[u8; 32]>,
|
||||
utxo_commitments_created_hashes: Vec<[u8; 32]>,
|
||||
) -> Transaction {
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
Transaction {
|
||||
hash,
|
||||
tx_kind: TxKind::Private,
|
||||
@ -300,6 +303,9 @@ mod tests {
|
||||
execution_proof_private: "dummy_proof".to_string(),
|
||||
encoded_data: vec![],
|
||||
ephemeral_pub_key: vec![10, 11, 12],
|
||||
commitment: vec![],
|
||||
tweak: Tweak::new(&mut rng),
|
||||
secret_r: [0; 32],
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,3 +18,7 @@ rocksdb.workspace = true
|
||||
rs_merkle.workspace = true
|
||||
sha2.workspace = true
|
||||
monotree.workspace = true
|
||||
|
||||
[dependencies.secp256k1-zkp]
|
||||
workspace = true
|
||||
features = ["std", "rand-std", "rand", "serde", "global-context"]
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use log::info;
|
||||
use secp256k1_zkp::{PedersenCommitment, Tweak};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use sha2::{digest::FixedOutput, Digest};
|
||||
|
||||
@ -43,6 +44,12 @@ pub struct Transaction {
|
||||
pub encoded_data: Vec<(CipherText, Vec<u8>, Tag)>,
|
||||
///Transaction senders ephemeral pub key
|
||||
pub ephemeral_pub_key: Vec<u8>,
|
||||
///Public (Pedersen) commitment
|
||||
pub commitment: Vec<PedersenCommitment>,
|
||||
///tweak
|
||||
pub tweak: Tweak,
|
||||
///secret_r
|
||||
pub secret_r: [u8; 32],
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
@ -65,6 +72,12 @@ pub struct TransactionPayload {
|
||||
pub encoded_data: Vec<(CipherText, Vec<u8>, Tag)>,
|
||||
///Transaction senders ephemeral pub key
|
||||
pub ephemeral_pub_key: Vec<u8>,
|
||||
///Public (Pedersen) commitment
|
||||
pub commitment: Vec<PedersenCommitment>,
|
||||
///tweak
|
||||
pub tweak: Tweak,
|
||||
///secret_r
|
||||
pub secret_r: [u8; 32],
|
||||
}
|
||||
|
||||
impl From<TransactionPayload> for Transaction {
|
||||
@ -88,6 +101,9 @@ impl From<TransactionPayload> for Transaction {
|
||||
execution_proof_private: value.execution_proof_private,
|
||||
encoded_data: value.encoded_data,
|
||||
ephemeral_pub_key: value.ephemeral_pub_key,
|
||||
commitment: value.commitment,
|
||||
tweak: value.tweak,
|
||||
secret_r: value.secret_r,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user