Skip to content

Commit

Permalink
Block adjustments (zkapps) (#82)
Browse files Browse the repository at this point in the history
  • Loading branch information
piotr-iohk authored Dec 11, 2024
1 parent 6597a57 commit 009514b
Show file tree
Hide file tree
Showing 15 changed files with 226 additions and 196 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions sql/queries/zkapp_commands.sql
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ SELECT
WHERE
zauf.id=ANY (bzc.failure_reasons_ids)
) AS failure_reasons,
zaub.balance_change,
pk_update_body.value AS pk_update_body,
token_update_body.value AS token
zaub.balance_change AS "balance_change?",
pk_update_body.value AS "pk_update_body?",
token_update_body.value AS "token?"
FROM
blocks_zkapp_commands AS bzc
INNER JOIN zkapp_commands AS zc ON bzc.zkapp_command_id=zc.id
Expand Down
2 changes: 1 addition & 1 deletion src/api/account_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ impl MinaMesh {
let block = sqlx::query_file!("sql/queries/maybe_block.sql", index)
.fetch_optional(&self.pg_pool)
.await?
.ok_or(MinaMeshError::BlockMissing(index.unwrap().to_string()))?;
.ok_or(MinaMeshError::BlockMissing(index, None))?;
// has canonical height / do we really need to do a different query?
let maybe_account_balance_info = sqlx::query_file!(
"sql/queries/maybe_account_balance_info.sql",
Expand Down
58 changes: 19 additions & 39 deletions src/api/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use sqlx::FromRow;

use crate::{
generate_internal_command_transaction_identifier, generate_operations_internal_command,
generate_operations_user_command, generate_transaction_metadata, sql_to_mesh::zkapp_commands_to_transactions,
generate_operations_user_command, generate_operations_zkapp_command, generate_transaction_metadata,
util::DEFAULT_TOKEN_ID, ChainStatus, InternalCommandMetadata, InternalCommandType, MinaMesh, MinaMeshError,
TransactionStatus, UserCommandMetadata, UserCommandType, ZkAppCommand,
};
Expand All @@ -20,7 +20,7 @@ impl MinaMesh {
let partial_block_identifier = *request.block_identifier;
let metadata = match self.block_metadata(&partial_block_identifier).await? {
Some(metadata) => metadata,
None => return Err(MinaMeshError::BlockMissing(serde_json::to_string(&partial_block_identifier)?)),
None => return Err(MinaMeshError::BlockMissing(partial_block_identifier.index, partial_block_identifier.hash)),
};
let parent_block_metadata = match &metadata.parent_id {
Some(parent_id) => {
Expand Down Expand Up @@ -149,7 +149,7 @@ pub struct BlockMetadata {
state_hash: String,
sub_window_densities: Vec<i64>,
timestamp: String,
total_currency: String,
total_currency: Option<String>,
parent_hash: String,
parent_id: Option<i32>,
proposed_protocol_version_id: Option<i32>,
Expand All @@ -160,41 +160,21 @@ pub struct BlockMetadata {
winner: String,
}

#[derive(Debug, PartialEq, Eq, FromRow, Serialize)]
pub struct ZkappCommandMetadata {
id: i64,
memo: Option<String>,
hash: String,
fee_payer: String,
fee: String,
valid_until: Option<i64>,
nonce: i64,
sequence_no: i64,
status: TransactionStatus,
failure_reasons: Option<Vec<String>>,
balance_change: String,
account: String,
token: String,
}
pub fn zkapp_commands_to_transactions(commands: Vec<ZkAppCommand>) -> Vec<Transaction> {
let block_map = generate_operations_zkapp_command(commands);

#[derive(Debug, PartialEq, Eq, FromRow, Serialize)]
pub struct ZkappAccountUpdateMetadata {
account_identifier_id: i32,
update_id: i32,
balance_change: String,
increment_nonce: bool,
events_id: i32,
actions_id: i32,
call_data_id: i32,
call_depth: i32,
zkapp_network_precondition_id: i32,
zkapp_account_precondition_id: i32,
zkapp_valid_while_precondition_id: Option<i32>,
use_full_commitment: bool,
implicit_account_creation_fee: bool,
may_use_token: String,
authorization_kind: String,
verification_key_hash_id: Option<i32>,
account: String,
token: String,
let mut result = Vec::new();
for (_, tx_map) in block_map {
for (tx_hash, operations) in tx_map {
let transaction = Transaction {
transaction_identifier: Box::new(TransactionIdentifier { hash: tx_hash }),
operations,
metadata: None,
related_transactions: None,
};
result.push(transaction);
}
}

result
}
69 changes: 10 additions & 59 deletions src/api/search_transactions.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
use std::collections::BTreeMap;

use coinbase_mesh::models::{
AccountIdentifier, BlockIdentifier, BlockTransaction, Operation, SearchTransactionsRequest,
SearchTransactionsResponse, Transaction, TransactionIdentifier,
BlockIdentifier, BlockTransaction, SearchTransactionsRequest, SearchTransactionsResponse, Transaction,
TransactionIdentifier,
};
use serde_json::json;

use crate::{
generate_internal_command_transaction_identifier, generate_operations_internal_command,
generate_operations_user_command, generate_transaction_metadata, operation, util::DEFAULT_TOKEN_ID, ChainStatus,
InternalCommand, InternalCommandType, MinaMesh, MinaMeshError, OperationType, TransactionStatus, UserCommand,
UserCommandType, ZkAppCommand,
generate_operations_user_command, generate_operations_zkapp_command, generate_transaction_metadata, ChainStatus,
InternalCommand, InternalCommandType, MinaMesh, MinaMeshError, TransactionStatus, UserCommand, UserCommandType,
ZkAppCommand,
};

impl MinaMesh {
Expand Down Expand Up @@ -220,63 +217,17 @@ impl MinaMesh {
}

pub fn zkapp_commands_to_block_transactions(commands: Vec<ZkAppCommand>) -> Vec<BlockTransaction> {
let mut block_map: BTreeMap<(i64, String), BTreeMap<String, Vec<Operation>>> = BTreeMap::new();

for command in commands {
// Group by block identifier (block index and block hash)
let block_key = (command.height.unwrap_or(0), command.state_hash.clone().unwrap_or_default());
let tx_hash = command.hash;

// Initialize or update the operation list for this transaction
let operations = block_map.entry(block_key).or_default().entry(tx_hash.clone()).or_default();

// Add fee operation (zkapp_fee_payer_dec)
if operations.is_empty() {
operations.push(operation(
0,
Some(&format!("-{}", command.fee)),
&AccountIdentifier {
address: command.fee_payer.clone(),
metadata: Some(json!({ "token_id": DEFAULT_TOKEN_ID })),
sub_account: None,
},
OperationType::ZkappFeePayerDec,
Some(&TransactionStatus::Applied),
None,
None,
None,
));
}

// Add zkapp balance update operation
operations.push(operation(
0,
Some(&command.balance_change),
&AccountIdentifier {
address: command.pk_update_body.clone(),
metadata: Some(json!({ "token_id": command.token })),
sub_account: None,
},
OperationType::ZkappBalanceUpdate,
Some(&command.status),
None,
None,
command.token.as_ref(),
));
}
let block_map = generate_operations_zkapp_command(commands);

let mut result = Vec::new();
for ((block_index, block_hash), tx_map) in block_map {
for (tx_hash, mut operations) in tx_map {
// Ensure the operations are correctly indexed
for (i, operation) in operations.iter_mut().enumerate() {
operation.operation_identifier.index = i as i64;
}

let block_index = block_index.unwrap_or(0);
let block_hash = block_hash.unwrap_or_default();
for (tx_hash, operations) in tx_map {
let transaction = BlockTransaction {
block_identifier: Box::new(BlockIdentifier { index: block_index, hash: block_hash.clone() }),
transaction: Box::new(Transaction {
transaction_identifier: Box::new(TransactionIdentifier { hash: tx_hash.clone() }),
transaction_identifier: Box::new(TransactionIdentifier { hash: tx_hash }),
operations,
metadata: None,
related_transactions: None,
Expand Down
31 changes: 25 additions & 6 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub enum MinaMeshError {
TransactionNotFound(String),

#[error("Block not found")]
BlockMissing(String),
BlockMissing(Option<i64>, Option<String>),

#[error("Malformed public key")]
MalformedPublicKey,
Expand Down Expand Up @@ -118,7 +118,7 @@ impl MinaMeshError {
MinaMeshError::AccountNotFound("Account ID".to_string()),
MinaMeshError::InvariantViolation,
MinaMeshError::TransactionNotFound("Transaction ID".to_string()),
MinaMeshError::BlockMissing("Block ID".to_string()),
MinaMeshError::BlockMissing(Some(-1), Some("test_hash".to_string())),
MinaMeshError::MalformedPublicKey,
MinaMeshError::OperationsNotValid(vec![]),
MinaMeshError::UnsupportedOperationForConstruction,
Expand Down Expand Up @@ -150,7 +150,7 @@ impl MinaMeshError {
MinaMeshError::AccountNotFound(_) => 6,
MinaMeshError::InvariantViolation => 7,
MinaMeshError::TransactionNotFound(_) => 8,
MinaMeshError::BlockMissing(_) => 9,
MinaMeshError::BlockMissing(_, _) => 9,
MinaMeshError::MalformedPublicKey => 10,
MinaMeshError::OperationsNotValid(_) => 11,
MinaMeshError::UnsupportedOperationForConstruction => 12,
Expand Down Expand Up @@ -179,7 +179,7 @@ impl MinaMeshError {
| MinaMeshError::TransactionSubmitNoSender
| MinaMeshError::AccountNotFound(_)
| MinaMeshError::TransactionNotFound(_)
| MinaMeshError::BlockMissing(_)
| MinaMeshError::BlockMissing(_, _)
| MinaMeshError::ChainInfoMissing
)
}
Expand Down Expand Up @@ -218,6 +218,25 @@ impl MinaMeshError {
),
"transaction": tx,
}),
MinaMeshError::BlockMissing(index, hash) => {
let block_identifier = match (index, hash) {
(Some(idx), Some(hsh)) => format!("index={}, hash={}", idx, hsh),
(Some(idx), None) => format!("index={}", idx),
(None, Some(hsh)) => format!("hash={}", hsh),
(None, None) => "no identifying information (index or hash)".to_string(),
};

let error_message =
format!("We couldn't find the block in the archive node, specified by {}.", block_identifier);
json!({
"error": error_message,
"block": {
"index": index,
"hash": hash,
},
})
}

_ => json!(""),
}
}
Expand All @@ -244,7 +263,7 @@ impl MinaMeshError {
MinaMeshError::AccountNotFound(_) => "The specified account could not be found.".to_string(),
MinaMeshError::InvariantViolation => "An internal invariant was violated.".to_string(),
MinaMeshError::TransactionNotFound(_) => "The specified transaction could not be found.".to_string(),
MinaMeshError::BlockMissing(_) => "The specified block could not be found.".to_string(),
MinaMeshError::BlockMissing(_, _) => "The specified block could not be found.".to_string(),
MinaMeshError::MalformedPublicKey => "The provided public key is malformed.".to_string(),
MinaMeshError::OperationsNotValid(_) => {
"We could not convert those operations to a valid transaction.".to_string()
Expand Down Expand Up @@ -290,7 +309,7 @@ impl IntoResponse for MinaMeshError {
MinaMeshError::AccountNotFound(_) => StatusCode::NOT_FOUND,
MinaMeshError::InvariantViolation => StatusCode::INTERNAL_SERVER_ERROR,
MinaMeshError::TransactionNotFound(_) => StatusCode::NOT_FOUND,
MinaMeshError::BlockMissing(_) => StatusCode::NOT_FOUND,
MinaMeshError::BlockMissing(_, _) => StatusCode::NOT_FOUND,
MinaMeshError::MalformedPublicKey => StatusCode::BAD_REQUEST,
MinaMeshError::OperationsNotValid(_) => StatusCode::BAD_REQUEST,
MinaMeshError::UnsupportedOperationForConstruction => StatusCode::BAD_REQUEST,
Expand Down
1 change: 0 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ mod create_router;
mod error;
mod graphql;
mod playground;
mod sql_to_mesh;
pub mod test;
mod transaction_operations;
mod types;
Expand Down
69 changes: 0 additions & 69 deletions src/sql_to_mesh.rs

This file was deleted.

Loading

0 comments on commit 009514b

Please sign in to comment.