Merge pull request #63 from vacp2p/Pravdyvyi/issue-fix

Various qol and fixes
This commit is contained in:
tyshko-rostyslav 2025-05-08 17:04:16 +02:00 committed by GitHub
commit 25ef949a97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 291 additions and 62 deletions

1
Cargo.lock generated
View File

@ -3150,6 +3150,7 @@ dependencies = [
"common",
"consensus",
"env_logger",
"hex",
"log",
"networking",
"node_core",

View File

@ -50,6 +50,12 @@ pub struct Transaction {
pub tweak: Tweak,
///secret_r
pub secret_r: [u8; 32],
///Hex-encoded address of a smart contract account called
pub sc_addr: String,
///Recorded changes in state of smart contract
///
/// First value represents vector of changes, second is new length of a state
pub state_changes: (serde_json::Value, usize),
}
#[derive(Debug, Serialize, Deserialize, Clone)]
@ -78,6 +84,12 @@ pub struct TransactionPayload {
pub tweak: Tweak,
///secret_r
pub secret_r: [u8; 32],
///Hex-encoded address of a smart contract account called
pub sc_addr: String,
///Recorded changes in state of smart contract
///
/// First value represents vector of changes, second is new length of a state
pub state_changes: (serde_json::Value, usize),
}
impl From<TransactionPayload> for Transaction {
@ -104,6 +116,8 @@ impl From<TransactionPayload> for Transaction {
commitment: value.commitment,
tweak: value.tweak,
secret_r: value.secret_r,
sc_addr: value.sc_addr,
state_changes: value.state_changes,
}
}
}

View File

@ -2,7 +2,7 @@ use std::path::Path;
use anyhow::{anyhow, Result};
use common::block::Block;
use storage::sc_db_utils::DataBlob;
use storage::sc_db_utils::{DataBlob, DataBlobChangeVariant};
use storage::RocksDBIO;
pub struct NodeBlockStore {
@ -44,6 +44,15 @@ impl NodeBlockStore {
Ok(self.dbio.put_block(block, false)?)
}
pub fn put_sc_sc_state(
&self,
sc_addr: &str,
length: usize,
modifications: Vec<DataBlobChangeVariant>,
) -> Result<()> {
Ok(self.dbio.put_sc_sc_state(sc_addr, length, modifications)?)
}
pub fn get_sc_sc_state(&self, sc_addr: &str) -> Result<Vec<DataBlob>> {
Ok(self.dbio.get_sc_sc_state(sc_addr)?)
}

View File

@ -105,11 +105,9 @@ impl NodeChainStore {
.collect(),
)?;
let eph_key_compressed = serde_json::to_vec(&tx.ephemeral_pub_key);
if let Ok(eph_key_compressed) = eph_key_compressed {
if !tx.encoded_data.is_empty() {
let ephemeral_public_key_sender =
serde_json::from_slice::<AffinePoint>(&eph_key_compressed)?;
serde_json::from_slice::<AffinePoint>(&tx.ephemeral_pub_key)?;
for (ciphertext, nonce, tag) in tx.encoded_data.clone() {
let slice = nonce.as_slice();

View File

@ -7,6 +7,7 @@ use common::ExecutionFailureKind;
use accounts::account_core::{Account, AccountAddress};
use anyhow::Result;
use chain_storage::NodeChainStore;
use common::transaction::{Transaction, TransactionPayload, TxKind};
use config::NodeConfig;
use executions::private_exec::{generate_commitments, generate_nullifiers};
@ -14,7 +15,7 @@ use log::info;
use sc_core::proofs_circuits::pedersen_commitment_vec;
use sequencer_client::{json::SendTxResponse, SequencerClient};
use serde::{Deserialize, Serialize};
use storage::NodeChainStore;
use storage::sc_db_utils::DataBlobChangeVariant;
use tokio::{sync::RwLock, task::JoinHandle};
use utxo::utxo_core::UTXO;
use zkvm::{
@ -25,10 +26,12 @@ use zkvm::{
pub const BLOCK_GEN_DELAY_SECS: u64 = 20;
pub mod chain_storage;
pub mod config;
pub mod executions;
///Module, which includes pre start setup helperfunctions
pub mod pre_start;
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
@ -97,6 +100,8 @@ impl NodeCore {
let mut storage = NodeChainStore::new_with_genesis(&config.home, genesis_block);
pre_start::setup_empty_sc_states(&storage).await?;
let mut chain_height = genesis_id.genesis_id;
//Chain update loop
@ -211,12 +216,21 @@ impl NodeCore {
let comm = generate_commitments(&vec![utxo]);
// TODO: fix address when correspoding method will be added
let sc_addr = "";
let mint_utxo_addr_bytes: Vec<u8> = zkvm::test_methods::MINT_UTXO_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let sc_addr = hex::encode(mint_utxo_addr_bytes);
//Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
let sc_state = acc_map_read_guard
.block_store
.get_sc_sc_state(sc_addr)
.get_sc_sc_state(&sc_addr)
.map_err(ExecutionFailureKind::db_error)?;
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
@ -254,6 +268,8 @@ impl NodeCore {
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
}
.into(),
result_hash,
@ -296,12 +312,22 @@ impl NodeCore {
let comm = generate_commitments(&utxos);
// TODO: fix address when correspoding method will be added
let sc_addr = "";
let mint_multiple_utxo_addr_bytes: Vec<u8> =
zkvm::test_methods::MINT_UTXO_MULTIPLE_ASSETS_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let sc_addr = hex::encode(mint_multiple_utxo_addr_bytes);
//Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
let sc_state = acc_map_read_guard
.block_store
.get_sc_sc_state(sc_addr)
.get_sc_sc_state(&sc_addr)
.map_err(ExecutionFailureKind::db_error)?;
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
@ -339,6 +365,8 @@ impl NodeCore {
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
}
.into(),
result_hashes,
@ -401,12 +429,21 @@ impl NodeCore {
let commitments = generate_commitments(&utxos);
// TODO: fix address when correspoding method will be added
let sc_addr = "";
let send_utxo_addr_bytes: Vec<u8> = zkvm::test_methods::SEND_UTXO_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let sc_addr = hex::encode(send_utxo_addr_bytes);
//Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
let sc_state = acc_map_read_guard
.block_store
.get_sc_sc_state(sc_addr)
.get_sc_sc_state(&sc_addr)
.map_err(ExecutionFailureKind::db_error)?;
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
@ -444,6 +481,8 @@ impl NodeCore {
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
}
.into(),
utxo_hashes,
@ -534,12 +573,22 @@ impl NodeCore {
commitments.extend(commitments_1);
// TODO: fix address when correspoding method will be added
let sc_addr = "";
let send_multiple_utxo_addr_bytes: Vec<u8> =
zkvm::test_methods::SEND_UTXO_MULTIPLE_ASSETS_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let sc_addr = hex::encode(send_multiple_utxo_addr_bytes);
//Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
let sc_state = acc_map_read_guard
.block_store
.get_sc_sc_state(sc_addr)
.get_sc_sc_state(&sc_addr)
.map_err(ExecutionFailureKind::db_error)?;
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
@ -577,6 +626,8 @@ impl NodeCore {
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
}
.into(),
utxo_hashes_receiver,
@ -646,12 +697,21 @@ impl NodeCore {
let commitments = generate_commitments(&utxos);
// TODO: fix address when correspoding method will be added
let sc_addr = "";
let mint_utxo_addr_bytes: Vec<u8> = zkvm::test_methods::SEND_UTXO_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let sc_addr = hex::encode(mint_utxo_addr_bytes);
//Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
let sc_state = acc_map_read_guard
.block_store
.get_sc_sc_state(sc_addr)
.get_sc_sc_state(&sc_addr)
.map_err(ExecutionFailureKind::db_error)?;
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
@ -695,6 +755,8 @@ impl NodeCore {
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
}
.into(),
utxo_hashes,
@ -729,12 +791,21 @@ 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 send_utxo_addr_bytes: Vec<u8> = zkvm::test_methods::SEND_UTXO_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let sc_addr = hex::encode(send_utxo_addr_bytes);
//Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
let sc_state = acc_map_read_guard
.block_store
.get_sc_sc_state(sc_addr)
.get_sc_sc_state(&sc_addr)
.map_err(ExecutionFailureKind::db_error)?;
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
@ -771,6 +842,8 @@ impl NodeCore {
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
}
.into())
}
@ -847,6 +920,13 @@ impl NodeCore {
public_context.produce_u64_list_from_context().unwrap(),
);
let sc_addr = hex::encode([0; 32]);
//Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
let tx: Transaction =
sc_core::transaction_payloads_tools::create_public_transaction_payload(
serde_json::to_vec(&ActionData::MintMoneyPublicTx(MintMoneyPublicTx {
@ -857,6 +937,8 @@ impl NodeCore {
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
)
.into();
tx.log();
@ -1048,7 +1130,6 @@ impl NodeCore {
pub async fn operate_account_send_deshielded_one_receiver(
&mut self,
acc_addr_sender: AccountAddress,
acc_addr_rec: AccountAddress,
utxo: UTXO,
comm_gen_hash: [u8; 32],
@ -1079,7 +1160,7 @@ impl NodeCore {
let new_balance = {
let acc_map_read_guard = self.storage.read().await;
let acc = acc_map_read_guard.acc_map.get(&acc_addr_sender).unwrap();
let acc = acc_map_read_guard.acc_map.get(&acc_addr_rec).unwrap();
acc.balance
};
@ -1353,12 +1434,21 @@ impl NodeCore {
.collect(),
});
// TODO: fix address when correspoding method will be added
let sc_addr = "";
let send_utxo_addr_bytes: Vec<u8> = zkvm::test_methods::SEND_UTXO_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let sc_addr = hex::encode(send_utxo_addr_bytes);
//Sc does not change its state
let state_changes: Vec<DataBlobChangeVariant> = vec![];
let new_len = 0;
let state_changes = (serde_json::to_value(state_changes).unwrap(), new_len);
let sc_state = acc_map_read_guard
.block_store
.get_sc_sc_state(sc_addr)
.get_sc_sc_state(&sc_addr)
.map_err(ExecutionFailureKind::db_error)?;
let mut vec_values_u64: Vec<Vec<u64>> = sc_state
@ -1397,6 +1487,8 @@ impl NodeCore {
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
}
.into(),
utxo_hashes,
@ -1497,13 +1589,8 @@ impl NodeCore {
let (new_utxo, comm_gen_hash) = self.operate_account_mint_private(acc_addr, 100).await?;
self.operate_account_send_deshielded_one_receiver(
acc_addr,
acc_addr,
new_utxo,
comm_gen_hash,
)
.await?;
self.operate_account_send_deshielded_one_receiver(acc_addr, new_utxo, comm_gen_hash)
.await?;
Ok(())
}
@ -1553,13 +1640,8 @@ impl NodeCore {
let (new_utxo, comm_gen_hash) = self.operate_account_mint_private(acc_addr, 100).await?;
self.operate_account_send_deshielded_one_receiver(
acc_addr,
acc_addr_rec,
new_utxo,
comm_gen_hash,
)
.await?;
self.operate_account_send_deshielded_one_receiver(acc_addr_rec, new_utxo, comm_gen_hash)
.await?;
Ok(())
}
@ -1596,7 +1678,6 @@ impl NodeCore {
.await?;
self.operate_account_send_deshielded_one_receiver(
addrs_receivers[publication_index],
addrs_receivers[publication_index],
new_utxos[publication_index].clone(),
comm_gen_hashes[publication_index],

View File

@ -0,0 +1,75 @@
use anyhow::Result;
use log::info;
use crate::chain_storage::NodeChainStore;
///Addres of public fund transfer account, as no such binary exists for zkVM
pub const PUBLIC_DEPOSIT_ID: [u8; 32] = [0; 32];
///Setups public states of default smart conracts as empty
pub async fn setup_empty_sc_states(node: &NodeChainStore) -> Result<()> {
info!("Filling up public states of default smart contracts");
let empty_state = vec![];
let public_deposit_addr = hex::encode(PUBLIC_DEPOSIT_ID);
node.block_store.put_sc_sc_state(
&public_deposit_addr,
empty_state.len(),
empty_state.clone(),
)?;
info!("Public transfer state set");
let mint_utxo_addr_bytes: Vec<u8> = zkvm::test_methods::MINT_UTXO_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let mint_utxo_addr = hex::encode(mint_utxo_addr_bytes);
node.block_store
.put_sc_sc_state(&mint_utxo_addr, empty_state.len(), empty_state.clone())?;
info!("Mint UTXO state set");
let single_utxo_transfer_addr_bytes: Vec<u8> = zkvm::test_methods::SEND_UTXO_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let single_utxo_transfer_addr = hex::encode(single_utxo_transfer_addr_bytes);
node.block_store.put_sc_sc_state(
&single_utxo_transfer_addr,
empty_state.len(),
empty_state.clone(),
)?;
info!("Single UTXO transfer state set");
let mint_utxo_multiple_assets_addr_bytes: Vec<u8> =
zkvm::test_methods::MINT_UTXO_MULTIPLE_ASSETS_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let mint_utxo_multiple_assets_addr = hex::encode(mint_utxo_multiple_assets_addr_bytes);
node.block_store.put_sc_sc_state(
&mint_utxo_multiple_assets_addr,
empty_state.len(),
empty_state.clone(),
)?;
info!("Mint UTXO multiple assets state set");
let multiple_assets_utxo_transfer_addr_bytes: Vec<u8> =
zkvm::test_methods::SEND_UTXO_MULTIPLE_ASSETS_ID
.iter()
.map(|num| num.to_le_bytes())
.flatten()
.collect();
let multiple_assets_utxo_transfer_addr = hex::encode(multiple_assets_utxo_transfer_addr_bytes);
node.block_store.put_sc_sc_state(
&multiple_assets_utxo_transfer_addr,
empty_state.len(),
empty_state.clone(),
)?;
info!("Multiple_assets UTXO transfer state set");
Ok(())
}

View File

@ -660,12 +660,7 @@ impl JsonHandler {
};
cover_guard
.operate_account_send_deshielded_one_receiver(
acc_addr_sender,
acc_addr,
utxo_to_send,
comm_hash,
)
.operate_account_send_deshielded_one_receiver(acc_addr, utxo_to_send, comm_hash)
.await
.map_err(cast_common_execution_error_into_rpc_error)?
};

View File

@ -4,6 +4,7 @@ version = "0.1.0"
edition = "2021"
[dependencies]
hex.workspace = true
anyhow.workspace = true
serde_json.workspace = true
env_logger.workspace = true

View File

@ -13,6 +13,8 @@ pub fn create_public_transaction_payload(
commitment: Vec<PedersenCommitment>,
tweak: Tweak,
secret_r: [u8; 32],
sc_addr: String,
state_changes: (serde_json::Value, usize),
) -> TransactionPayload {
TransactionPayload {
tx_kind: TxKind::Public,
@ -27,6 +29,8 @@ pub fn create_public_transaction_payload(
commitment,
tweak,
secret_r,
sc_addr,
state_changes,
}
}

View File

@ -306,6 +306,8 @@ mod tests {
commitment: vec![],
tweak: Tweak::new(&mut rng),
secret_r: [0; 32],
sc_addr: "sc_addr".to_string(),
state_changes: (serde_json::Value::Null, 0),
}
}

View File

@ -280,7 +280,9 @@ impl RocksDBIO {
///Push additional contract into list of known contracts in a DB
pub fn put_meta_sc(&self, sc_addr: String) -> DbResult<()> {
let mut sc_list = self.get_meta_sc_list()?;
sc_list.push(sc_addr);
if !sc_list.contains(&sc_addr) {
sc_list.push(sc_addr);
}
self.put_meta_sc_list(sc_list)?;
Ok(())
}

View File

@ -1,10 +1,55 @@
use serde::Serialize;
use serde::{de::Error, Deserialize, Serialize};
use crate::SC_DATA_BLOB_SIZE;
pub type DataBlob = [u8; SC_DATA_BLOB_SIZE];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct DataBlob(pub [u8; SC_DATA_BLOB_SIZE]);
#[derive(Debug, Clone, Copy)]
impl From<[u8; SC_DATA_BLOB_SIZE]> for DataBlob {
fn from(value: [u8; SC_DATA_BLOB_SIZE]) -> Self {
Self(value)
}
}
impl Serialize for DataBlob {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let data_vec = self.0.to_vec();
data_vec.serialize(serializer)
}
}
impl AsRef<[u8]> for DataBlob {
fn as_ref(&self) -> &[u8] {
self.0.as_ref()
}
}
impl<'de> Deserialize<'de> for DataBlob {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let data_vec = Vec::<u8>::deserialize(deserializer)?;
let chunk: [u8; SC_DATA_BLOB_SIZE] = data_vec
.try_into()
.map_err(|data| {
anyhow::anyhow!("failed to fit vec {data:?} to {:?}", SC_DATA_BLOB_SIZE)
})
.map_err(D::Error::custom)?;
Ok(Self(chunk))
}
}
impl DataBlob {
pub fn to_vec(&self) -> Vec<u8> {
self.0.to_vec()
}
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum DataBlobChangeVariant {
Created {
id: usize,
@ -29,10 +74,10 @@ pub fn produce_blob_from_fit_vec(data: Vec<u8>) -> DataBlob {
let data_len = data.len();
assert!(data_len <= SC_DATA_BLOB_SIZE);
let mut blob: DataBlob = [0; SC_DATA_BLOB_SIZE];
let mut blob: DataBlob = [0; SC_DATA_BLOB_SIZE].into();
for (idx, item) in data.into_iter().enumerate() {
blob[idx] = item
blob.0[idx] = item
}
blob
@ -129,7 +174,7 @@ mod tests {
fn test_produce_blob_from_fit_vec() {
let data = (0..0 + 255).collect();
let blob = produce_blob_from_fit_vec(data);
assert_eq!(blob[..4], [0, 1, 2, 3]);
assert_eq!(blob.0[..4], [0, 1, 2, 3]);
}
#[test]
@ -155,7 +200,7 @@ mod tests {
#[test]
fn test_compare_blob_lists_created() {
let old_list: Vec<DataBlob> = vec![];
let new_list: Vec<DataBlob> = vec![[1; SC_DATA_BLOB_SIZE]];
let new_list: Vec<DataBlob> = vec![[1; SC_DATA_BLOB_SIZE].into()];
let changes = compare_blob_lists(&old_list, &new_list);
assert_eq!(changes.len(), 1);
@ -164,7 +209,7 @@ mod tests {
#[test]
fn test_compare_blob_lists_deleted() {
let old_list: Vec<DataBlob> = vec![[1; SC_DATA_BLOB_SIZE]];
let old_list: Vec<DataBlob> = vec![[1; SC_DATA_BLOB_SIZE].into()];
let new_list: Vec<DataBlob> = vec![];
let changes = compare_blob_lists(&old_list, &new_list);
@ -174,8 +219,8 @@ mod tests {
#[test]
fn test_compare_blob_lists_modified() {
let old_list: Vec<DataBlob> = vec![[1; SC_DATA_BLOB_SIZE]];
let new_list: Vec<DataBlob> = vec![[2; SC_DATA_BLOB_SIZE]];
let old_list: Vec<DataBlob> = vec![[1; SC_DATA_BLOB_SIZE].into()];
let new_list: Vec<DataBlob> = vec![[2; SC_DATA_BLOB_SIZE].into()];
let changes = compare_blob_lists(&old_list, &new_list);
assert_eq!(changes.len(), 1);

View File

@ -6,6 +6,8 @@ use utxo::utxo_core::{UTXOPayload, UTXO};
pub mod gas_calculator;
pub use test_methods;
pub fn gas_limits_check<INP: Serialize>(
input_buffer: INP,
elf: &[u8],