Skip to content

Commit

Permalink
fix(witness-generator): Witness generator oracle with cached storage …
Browse files Browse the repository at this point in the history
…refunds (#274)

# What ❔

During VM run in state keeper we save all storage refunds that are
returned by oracle. Later in basic witness generation these refunds are
reused.
Also, `zk_evm` is updated so that it now passes correct timestamps for
`estimate_refunds_for_write` queries. Correct timestamps are necessary
for VM storage oracle to rollback `returned_refunds`

## Why ❔

With new VM, pubdata tracer mutates oracle affecting storage refunds. As
this tracer is only run in state keeper and not in witness generator we
must save refunds from state keeper and use them in wit-gen.

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted via `zk fmt` and `zk lint`.
  • Loading branch information
perekopskiy authored Oct 23, 2023
1 parent 33e3192 commit 8928a41
Showing 27 changed files with 207 additions and 66 deletions.
10 changes: 5 additions & 5 deletions Cargo.lock

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

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE l1_batches
DROP COLUMN IF EXISTS storage_refunds;
2 changes: 2 additions & 0 deletions core/lib/dal/migrations/20231019125310_storage-refunds.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
ALTER TABLE l1_batches
ADD COLUMN IF NOT EXISTS storage_refunds BIGINT[];
85 changes: 53 additions & 32 deletions core/lib/dal/sqlx-data.json
Original file line number Diff line number Diff line change
@@ -5400,38 +5400,6 @@
},
"query": "\n SELECT l1_batch_number, basic_circuits_blob_url, basic_circuits_inputs_blob_url FROM leaf_aggregation_witness_jobs\n WHERE status='successful' AND is_blob_cleaned=FALSE\n AND basic_circuits_blob_url is NOT NULL\n AND basic_circuits_inputs_blob_url is NOT NULL\n AND updated_at < NOW() - INTERVAL '30 days'\n LIMIT $1;\n "
},
"73f0e672ff1a5e144b3034beb18271f1164e95029998d6750c6a8953f7344db5": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Left": [
"Int8",
"Int4",
"Int4",
"Int8",
"Bool",
"Bytea",
"ByteaArray",
"ByteaArray",
"Bytea",
"ByteaArray",
"Int8",
"Int8",
"Int8",
"Jsonb",
"Jsonb",
"Numeric",
"Int8",
"Int8",
"Bytea",
"Bytea",
"Int4"
]
}
},
"query": "INSERT INTO l1_batches (number, l1_tx_count, l2_tx_count, timestamp, is_finished, fee_account_address, l2_to_l1_logs, l2_to_l1_messages, bloom, priority_ops_onchain_data, predicted_commit_gas_cost, predicted_prove_gas_cost, predicted_execute_gas_cost, initial_bootloader_heap_content, used_contract_hashes, base_fee_per_gas, l1_gas_price, l2_fair_gas_price, bootloader_code_hash, default_aa_code_hash, protocol_version, created_at, updated_at ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, now(), now())"
},
"741b13b0a4769a30186c650a4a1b24855806a27ccd8d5a50594741842dde44ec": {
"describe": {
"columns": [
@@ -9122,6 +9090,26 @@
},
"query": "\n INSERT INTO call_traces (tx_hash, call_trace)\n SELECT u.tx_hash, u.call_trace\n FROM UNNEST($1::bytea[], $2::bytea[])\n AS u(tx_hash, call_trace)\n "
},
"c3724d96ed4e1c31dd575b911b254ed5a4af4d5b6ad1243c812b37ebde0f6090": {
"describe": {
"columns": [
{
"name": "storage_refunds",
"ordinal": 0,
"type_info": "Int8Array"
}
],
"nullable": [
true
],
"parameters": {
"Left": [
"Int8"
]
}
},
"query": "SELECT storage_refunds FROM l1_batches WHERE number = $1"
},
"c49a6925e9462cc85a6e1cc850f2e147e0a5d990efed56f27792698e6cf9ff0c": {
"describe": {
"columns": [
@@ -9994,6 +9982,39 @@
},
"query": "\n UPDATE node_aggregation_witness_jobs_fri\n SET status = 'queued', attempts = attempts + 1, updated_at = now(), processing_started_at = now()\n WHERE (status = 'in_progress' AND processing_started_at <= now() - $1::interval AND attempts < $2)\n OR (status = 'failed' AND attempts < $2)\n RETURNING id, status, attempts\n "
},
"dce6cfa8b3f4e3c93864d95a0c746a4df31a601cc22e59eb2c2fd747ecbb7c8a": {
"describe": {
"columns": [],
"nullable": [],
"parameters": {
"Left": [
"Int8",
"Int4",
"Int4",
"Int8",
"Bool",
"Bytea",
"ByteaArray",
"ByteaArray",
"Bytea",
"ByteaArray",
"Int8",
"Int8",
"Int8",
"Jsonb",
"Jsonb",
"Numeric",
"Int8",
"Int8",
"Bytea",
"Bytea",
"Int4",
"Int8Array"
]
}
},
"query": "INSERT INTO l1_batches (number, l1_tx_count, l2_tx_count, timestamp, is_finished, fee_account_address, l2_to_l1_logs, l2_to_l1_messages, bloom, priority_ops_onchain_data, predicted_commit_gas_cost, predicted_prove_gas_cost, predicted_execute_gas_cost, initial_bootloader_heap_content, used_contract_hashes, base_fee_per_gas, l1_gas_price, l2_fair_gas_price, bootloader_code_hash, default_aa_code_hash, protocol_version, storage_refunds, created_at, updated_at ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, now(), now())"
},
"dd330bc075a163974c59ec55ecfddd769d05801963b3e0e840e7f11e7bc6d3e9": {
"describe": {
"columns": [
37 changes: 32 additions & 5 deletions core/lib/dal/src/blocks_dal.rs
Original file line number Diff line number Diff line change
@@ -241,6 +241,30 @@ impl BlocksDal<'_, '_> {
Ok(Some(heap))
}

pub async fn get_storage_refunds(
&mut self,
number: L1BatchNumber,
) -> anyhow::Result<Option<Vec<u32>>> {
let Some(row) = sqlx::query!(
"SELECT storage_refunds FROM l1_batches WHERE number = $1",
number.0 as i64
)
.instrument("get_storage_refunds")
.report_latency()
.with_arg("number", &number)
.fetch_optional(self.storage.conn())
.await?
else {
return Ok(None);
};
let Some(storage_refunds) = row.storage_refunds else {
return Ok(None);
};

let storage_refunds: Vec<_> = storage_refunds.into_iter().map(|n| n as u32).collect();
Ok(Some(storage_refunds))
}

pub async fn get_events_queue(
&mut self,
number: L1BatchNumber,
@@ -316,6 +340,7 @@ impl BlocksDal<'_, '_> {
initial_bootloader_contents: &[(usize, U256)],
predicted_block_gas: BlockGasCount,
events_queue: &[LogQuery],
storage_refunds: &[u32],
) -> anyhow::Result<()> {
let priority_onchain_data: Vec<Vec<u8>> = header
.priority_ops_onchain_data
@@ -338,6 +363,7 @@ impl BlocksDal<'_, '_> {
.expect("failed to serialize used_contract_hashes to JSON value");
let base_fee_per_gas = BigDecimal::from_u64(header.base_fee_per_gas)
.context("block.base_fee_per_gas should fit in u64")?;
let storage_refunds: Vec<_> = storage_refunds.iter().map(|n| *n as i64).collect();

let mut transaction = self.storage.start_transaction().await?;
sqlx::query!(
@@ -347,9 +373,9 @@ impl BlocksDal<'_, '_> {
bloom, priority_ops_onchain_data, \
predicted_commit_gas_cost, predicted_prove_gas_cost, predicted_execute_gas_cost, \
initial_bootloader_heap_content, used_contract_hashes, base_fee_per_gas, \
l1_gas_price, l2_fair_gas_price, bootloader_code_hash, default_aa_code_hash, protocol_version, \
l1_gas_price, l2_fair_gas_price, bootloader_code_hash, default_aa_code_hash, protocol_version, storage_refunds, \
created_at, updated_at \
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, now(), now())",
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, now(), now())",
header.number.0 as i64,
header.l1_tx_count as i32,
header.l2_tx_count as i32,
@@ -377,6 +403,7 @@ impl BlocksDal<'_, '_> {
.default_aa
.as_bytes(),
header.protocol_version.map(|v| v as i32),
&storage_refunds,
)
.execute(transaction.conn())
.await?;
@@ -1471,7 +1498,7 @@ mod tests {
header.l2_to_l1_messages.push(vec![33; 33]);

conn.blocks_dal()
.insert_l1_batch(&header, &[], BlockGasCount::default(), &[])
.insert_l1_batch(&header, &[], BlockGasCount::default(), &[], &[])
.await
.unwrap();

@@ -1519,15 +1546,15 @@ mod tests {
execute: 10,
};
conn.blocks_dal()
.insert_l1_batch(&header, &[], predicted_gas, &[])
.insert_l1_batch(&header, &[], predicted_gas, &[], &[])
.await
.unwrap();

header.number = L1BatchNumber(2);
header.timestamp += 100;
predicted_gas += predicted_gas;
conn.blocks_dal()
.insert_l1_batch(&header, &[], predicted_gas, &[])
.insert_l1_batch(&header, &[], predicted_gas, &[], &[])
.await
.unwrap();

2 changes: 1 addition & 1 deletion core/lib/dal/src/storage_logs_dal.rs
Original file line number Diff line number Diff line change
@@ -548,7 +548,7 @@ mod tests {
);
header.is_finished = true;
conn.blocks_dal()
.insert_l1_batch(&header, &[], BlockGasCount::default(), &[])
.insert_l1_batch(&header, &[], BlockGasCount::default(), &[], &[])
.await
.unwrap();
conn.blocks_dal()
10 changes: 5 additions & 5 deletions core/lib/dal/src/tests/mod.rs
Original file line number Diff line number Diff line change
@@ -290,7 +290,7 @@ async fn test_duplicate_insert_prover_jobs(connection_pool: ConnectionPool) {
);
storage
.blocks_dal()
.insert_l1_batch(&header, &[], Default::default(), &[])
.insert_l1_batch(&header, &[], Default::default(), &[], &[])
.await
.unwrap();

@@ -352,7 +352,7 @@ async fn test_requeue_prover_jobs(connection_pool: ConnectionPool) {
);
storage
.blocks_dal()
.insert_l1_batch(&header, &[], Default::default(), &[])
.insert_l1_batch(&header, &[], Default::default(), &[], &[])
.await
.unwrap();

@@ -415,7 +415,7 @@ async fn test_move_leaf_aggregation_jobs_from_waiting_to_queued(connection_pool:
);
storage
.blocks_dal()
.insert_l1_batch(&header, &[], Default::default(), &[])
.insert_l1_batch(&header, &[], Default::default(), &[], &[])
.await
.unwrap();

@@ -495,7 +495,7 @@ async fn test_move_node_aggregation_jobs_from_waiting_to_queued(connection_pool:
);
storage
.blocks_dal()
.insert_l1_batch(&header, &[], Default::default(), &[])
.insert_l1_batch(&header, &[], Default::default(), &[], &[])
.await
.unwrap();

@@ -582,7 +582,7 @@ async fn test_move_scheduler_jobs_from_waiting_to_queued(connection_pool: Connec
);
storage
.blocks_dal()
.insert_l1_batch(&header, &[], Default::default(), &[])
.insert_l1_batch(&header, &[], Default::default(), &[], &[])
.await
.unwrap();

2 changes: 1 addition & 1 deletion core/lib/multivm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ keywords = ["blockchain", "zksync"]
categories = ["cryptography"]

[dependencies]
zk_evm_1_3_3 = { package = "zk_evm", git = "https://github.com/matter-labs/era-zk_evm.git", tag= "v1.3.3-rc1" }
zk_evm_1_3_3 = { package = "zk_evm", git = "https://github.com/matter-labs/era-zk_evm.git", tag= "v1.3.3-rc2" }
zk_evm_1_3_1 = { package = "zk_evm", git = "https://github.com/matter-labs/era-zk_evm.git", tag= "v1.3.1-rc2" }

zksync_types = { path = "../types" }
3 changes: 3 additions & 0 deletions core/lib/multivm/src/glue/types/vm/vm_block_result.rs
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@ impl GlueFrom<crate::vm_m5::vm::VmBlockResult> for crate::interface::FinishedL1B
l2_to_l1_logs: value.full_result.l2_to_l1_logs,
total_log_queries: value.full_result.total_log_queries,
cycles_used: value.full_result.cycles_used,
storage_refunds: Vec::new(),
},
final_bootloader_memory: None,
}
@@ -70,6 +71,7 @@ impl GlueFrom<crate::vm_m6::vm::VmBlockResult> for crate::interface::FinishedL1B
l2_to_l1_logs: value.full_result.l2_to_l1_logs,
total_log_queries: value.full_result.total_log_queries,
cycles_used: value.full_result.cycles_used,
storage_refunds: Vec::new(),
},
final_bootloader_memory: None,
}
@@ -103,6 +105,7 @@ impl GlueFrom<crate::vm_1_3_2::vm::VmBlockResult> for crate::interface::Finished
l2_to_l1_logs: value.full_result.l2_to_l1_logs,
total_log_queries: value.full_result.total_log_queries,
cycles_used: value.full_result.cycles_used,
storage_refunds: Vec::new(),
},
final_bootloader_memory: None,
}
Original file line number Diff line number Diff line change
@@ -16,6 +16,8 @@ pub struct CurrentExecutionState {
pub total_log_queries: usize,
/// Number of cycles used by the VM.
pub cycles_used: u32,
/// Refunds returned by `StorageOracle`.
pub storage_refunds: Vec<u32>,
}

/// Bootloader Memory of the VM.
Loading

0 comments on commit 8928a41

Please sign in to comment.