Skip to content

Commit

Permalink
Update ledger soft batch rpc tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ercecan committed Apr 2, 2024
1 parent 72fb8d6 commit 171e5d3
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 20 deletions.
136 changes: 124 additions & 12 deletions bin/citrea/src/test_rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ use proptest::{prop_compose, proptest};
use reqwest::header::CONTENT_TYPE;
use serde_json::json;
use sov_db::ledger_db::{LedgerDB, SlotCommit};
use sov_mock_da::MockDaSpec;
#[cfg(test)]
use sov_mock_da::{MockBlock, MockBlockHeader, MockHash};
use sov_modules_api::DaSpec;
use sov_rollup_interface::da::Time;
use sov_rollup_interface::services::da::SlotData;
use sov_rollup_interface::stf::fuzzing::BatchReceiptStrategyArgs;
use sov_rollup_interface::stf::{BatchReceipt, Event, TransactionReceipt};
use sov_rollup_interface::stf::{BatchReceipt, Event, SoftBatchReceipt, TransactionReceipt};
#[cfg(test)]
use sov_stf_runner::RpcConfig;
use tendermint::crypto::Sha256;
Expand Down Expand Up @@ -46,13 +48,28 @@ async fn queries_test_runner(test_queries: Vec<TestExpect>, rpc_config: RpcConfi
}
}

fn populate_ledger(ledger_db: &mut LedgerDB, slots: Vec<SlotCommit<MockBlock, u32, u32>>) {
fn populate_ledger(
ledger_db: &mut LedgerDB,
slots: Vec<SlotCommit<MockBlock, u32, u32>>,
soft_batch_receipts: Option<Vec<SoftBatchReceipt<u64, u32, MockDaSpec>>>,
) {
for slot in slots {
ledger_db.commit_slot(slot).unwrap();
}
if let Some(soft_batch_receipts) = soft_batch_receipts {
for soft_batch_receipt in soft_batch_receipts {
ledger_db
.commit_soft_batch(soft_batch_receipt, true)
.unwrap();
}
}
}

fn test_helper(test_queries: Vec<TestExpect>, slots: Vec<SlotCommit<MockBlock, u32, u32>>) {
fn test_helper(
test_queries: Vec<TestExpect>,
slots: Vec<SlotCommit<MockBlock, u32, u32>>,
soft_batch_receipts: Option<Vec<SoftBatchReceipt<u64, u32, MockDaSpec>>>,
) {
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_io()
.enable_time()
Expand All @@ -63,7 +80,7 @@ fn test_helper(test_queries: Vec<TestExpect>, slots: Vec<SlotCommit<MockBlock, u
// Initialize the ledger database, which stores blocks, transactions, events, etc.
let tmpdir = tempfile::tempdir().unwrap();
let mut ledger_db = LedgerDB::with_path(tmpdir.path()).unwrap();
populate_ledger(&mut ledger_db, slots);
populate_ledger(&mut ledger_db, slots, soft_batch_receipts);
let server = jsonrpsee::server::ServerBuilder::default()
.build("127.0.0.1:0")
.await
Expand Down Expand Up @@ -106,6 +123,51 @@ fn regular_test_helper(payload: serde_json::Value, expected: &serde_json::Value)
blobs: Default::default(),
})];

let soft_batch_receipts = vec![
SoftBatchReceipt {
da_slot_height: 0,
da_slot_hash: <MockDaSpec as DaSpec>::SlotHash::from([0u8; 32]),
da_slot_txs_commitment: <MockDaSpec as DaSpec>::SlotHash::from([1u8; 32]),
pre_state_root: vec![],
post_state_root: vec![],
soft_confirmation_signature: vec![],
batch_hash: ::sha2::Sha256::digest(b"batch_receipt"),
tx_receipts: vec![
TransactionReceipt::<u32> {
tx_hash: ::sha2::Sha256::digest(b"tx1"),
body_to_save: Some(b"tx1 body".to_vec()),
events: vec![],
receipt: 0,
},
TransactionReceipt::<u32> {
tx_hash: ::sha2::Sha256::digest(b"tx2"),
body_to_save: Some(b"tx2 body".to_vec()),
events: vec![
Event::new("event1_key", "event1_value"),
Event::new("event2_key", "event2_value"),
],
receipt: 1,
},
],
phantom_data: PhantomData,
pub_key: vec![],
l1_fee_rate: 0,
},
SoftBatchReceipt {
da_slot_height: 1,
da_slot_hash: <MockDaSpec as DaSpec>::SlotHash::from([2; 32]),
da_slot_txs_commitment: <MockDaSpec as DaSpec>::SlotHash::from([3; 32]),
pre_state_root: vec![],
post_state_root: vec![],
soft_confirmation_signature: vec![],
batch_hash: ::sha2::Sha256::digest(b"batch_receipt2"),
tx_receipts: batch2_tx_receipts(),
phantom_data: PhantomData,
pub_key: vec![],
l1_fee_rate: 0,
},
];

let batches = vec![
BatchReceipt {
batch_hash: ::sha2::Sha256::digest(b"batch_receipt"),
Expand Down Expand Up @@ -145,6 +207,7 @@ fn regular_test_helper(payload: serde_json::Value, expected: &serde_json::Value)
expected: expected.clone(),
}],
slots,
Some(soft_batch_receipts),
)
}

Expand Down Expand Up @@ -247,6 +310,43 @@ fn test_get_batches() {
regular_test_helper(payload, &expected);
}

#[test]
fn test_get_soft_batch() {
// Get the first soft batch by number
let payload = jsonrpc_req!("ledger_getSoftBatchByNumber", [1]);
let expected = jsonrpc_result!({"da_slot_height":0,"da_slot_hash":"0000000000000000000000000000000000000000000000000000000000000000","da_slot_txs_commitment":"0101010101010101010101010101010101010101010101010101010101010101","hash":"b5515a80204963f7db40e98af11aedb49a394b1c7e3d8b5b7a33346b8627444f","txs":[[116,120,49,32,98,111,100,121],[116,120,50,32,98,111,100,121]],"pre_state_root":"","post_state_root":"","soft_confirmation_signature":"","pub_key":"","l1_fee_rate":0});
regular_test_helper(payload, &expected);

// Get the first soft batch by hash
let payload = jsonrpc_req!(
"ledger_getSoftBatchByHash",
["b5515a80204963f7db40e98af11aedb49a394b1c7e3d8b5b7a33346b8627444f"]
);
regular_test_helper(payload, &expected);

// Get the second soft batch by number
let payload = jsonrpc_req!("ledger_getSoftBatchByNumber", [2]);
let expected = jsonrpc_result!(
{"da_slot_height":1,"da_slot_hash":"0202020202020202020202020202020202020202020202020202020202020202","da_slot_txs_commitment":"0303030303030303030303030303030303030303030303030303030303030303","hash":"f85fe0cb36fdaeca571c896ed476b49bb3c8eff00d935293a8967e1e9a62071e","txs": batch2_tx_receipts().into_iter().map(|tx_receipt| tx_receipt.body_to_save.unwrap()).collect::<Vec<_>>(), "pre_state_root":"","post_state_root":"","soft_confirmation_signature":"","pub_key":"","l1_fee_rate":0}
);
regular_test_helper(payload, &expected);

// Get the second soft batch by hash
let payload = jsonrpc_req!(
"ledger_getSoftBatchByHash",
["f85fe0cb36fdaeca571c896ed476b49bb3c8eff00d935293a8967e1e9a62071e"]
);
regular_test_helper(payload, &expected);

// Get range of soft batches
let payload = jsonrpc_req!("ledger_getSoftBatchRange", [1, 2]);
let expected = jsonrpc_result!(
[{"da_slot_height":0,"da_slot_hash":"0000000000000000000000000000000000000000000000000000000000000000","da_slot_txs_commitment":"0101010101010101010101010101010101010101010101010101010101010101","hash":"b5515a80204963f7db40e98af11aedb49a394b1c7e3d8b5b7a33346b8627444f","txs":[[116,120,49,32,98,111,100,121],[116,120,50,32,98,111,100,121]],"pre_state_root":"","post_state_root":"","soft_confirmation_signature":"","pub_key":"","l1_fee_rate":0},{"da_slot_height":1,"da_slot_hash":"0202020202020202020202020202020202020202020202020202020202020202","da_slot_txs_commitment":"0303030303030303030303030303030303030303030303030303030303030303","hash":"f85fe0cb36fdaeca571c896ed476b49bb3c8eff00d935293a8967e1e9a62071e","txs": batch2_tx_receipts().into_iter().map(|tx_receipt| tx_receipt.body_to_save.unwrap()).collect::<Vec<_>>(), "pre_state_root":"","post_state_root":"","soft_confirmation_signature":"","pub_key":"","l1_fee_rate":0}
]
);
regular_test_helper(payload, &expected);
}

#[test]
fn test_get_events() {
let payload = jsonrpc_req!("ledger_getEvents", [1]);
Expand All @@ -262,8 +362,20 @@ fn test_get_events() {
"value":[101,118,101,110,116,50,95,118,97,108,117,101]
}]);
regular_test_helper(payload, &expected);

let payload = jsonrpc_req!("ledger_getEvents", [3]);
let expected = jsonrpc_result!([{
"key":[101,118,101,110,116,49,95,107,101,121],
"value":[101,118,101,110,116,49,95,118,97,108,117,101]
}]);
regular_test_helper(payload, &expected);
let payload = jsonrpc_req!("ledger_getEvents", [4]);
let expected = jsonrpc_result!([{
"key":[101,118,101,110,116,50,95,107,101,121],
"value":[101,118,101,110,116,50,95,118,97,108,117,101]
}]);
regular_test_helper(payload, &expected);

let payload = jsonrpc_req!("ledger_getEvents", [5]);
let expected = jsonrpc_result!([null]);
regular_test_helper(payload, &expected);
}
Expand Down Expand Up @@ -384,7 +496,7 @@ proptest!(
"end": last_slot_end_batch
}
});
test_helper(vec![TestExpect{ payload, expected }], slots);
test_helper(vec![TestExpect{ payload, expected }], slots, None);
}


Expand Down Expand Up @@ -442,7 +554,7 @@ proptest!(
expected:
jsonrpc_result!([{"hash":format!("0x{batch_hash}"),"tx_range":{"start":first_tx_num,"end":last_tx_num},"txs":full_txs}])},
],
slots);
slots, None);
return Ok(());
}

Expand All @@ -454,7 +566,7 @@ proptest!(

let payload = jsonrpc_req!("ledger_getBatches", [[random_batch_num], "Compact"]);
let expected = jsonrpc_result!([null]);
test_helper(vec![TestExpect{payload, expected}], slots);
test_helper(vec![TestExpect{payload, expected}], slots, None);
}

#[test]
Expand Down Expand Up @@ -501,7 +613,7 @@ proptest!(
expected:
jsonrpc_result!([tx_formatted])},
]
, slots);
, slots, None);

return Ok(());
}
Expand All @@ -512,7 +624,7 @@ proptest!(

let payload = jsonrpc_req!("ledger_getTransactions", [[random_tx_num]]);
let expected = jsonrpc_result!([null]);
test_helper(vec![TestExpect{payload, expected}], slots);
test_helper(vec![TestExpect{payload, expected}], slots, None);

}

Expand Down Expand Up @@ -543,7 +655,7 @@ proptest!(
jsonrpc_req!("ledger_getEvents", [random_event_num_usize]),
expected:
jsonrpc_result!([event_json])}]
, slots);
, slots, None);

return Ok(());
}
Expand All @@ -554,6 +666,6 @@ proptest!(

let payload = jsonrpc_req!("ledger_getEvents", [random_event_num]);
let expected = jsonrpc_result!([null]);
test_helper(vec![TestExpect{payload, expected}], slots);
test_helper(vec![TestExpect{payload, expected}], slots, None);
}
);
4 changes: 2 additions & 2 deletions crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use sov_schema_db::{Schema, SchemaBatch, SeekKeyEncoder, DB};
use crate::rocks_db_config::gen_rocksdb_options;
use crate::schema::tables::{
BatchByHash, BatchByNumber, EventByKey, EventByNumber, L2RangeByL1Height,
LastSequencerCommitmentSent, SlotByHash, SlotByNumber, SoftBatchByNumber,
LastSequencerCommitmentSent, SlotByHash, SlotByNumber, SoftBatchByHash, SoftBatchByNumber,
SoftConfirmationStatus, TxByHash, TxByNumber, LEDGER_TABLES,
};
use crate::schema::types::{
Expand Down Expand Up @@ -207,7 +207,7 @@ impl LedgerDB {
schema_batch: &mut SchemaBatch,
) -> Result<(), anyhow::Error> {
schema_batch.put::<SoftBatchByNumber>(batch_number, batch)?;
schema_batch.put::<BatchByHash>(&batch.hash, batch_number)
schema_batch.put::<SoftBatchByHash>(&batch.hash, batch_number)
}

fn put_batch(
Expand Down
52 changes: 47 additions & 5 deletions crates/sovereign-sdk/full-node/db/sov-db/src/ledger_db/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ use crate::schema::types::{
const MAX_SLOTS_PER_REQUEST: u64 = 10;
/// The maximum number of batches that can be requested in a single RPC range query
const MAX_BATCHES_PER_REQUEST: u64 = 20;
/// The maximum number of soft batches that can be requested in a single RPC range query
const MAX_SOFT_BATCHES_PER_REQUEST: u64 = 20;
/// The maximum number of transactions that can be requested in a single RPC range query
const MAX_TRANSACTIONS_PER_REQUEST: u64 = 100;
/// The maximum number of events that can be requested in a single RPC range query
Expand Down Expand Up @@ -59,9 +61,9 @@ impl LedgerRpcProvider for LedgerDB {

fn get_soft_batch(
&self,
batch_id: SoftBatchIdentifier,
batch_id: &SoftBatchIdentifier,
) -> Result<Option<SoftBatchResponse>, anyhow::Error> {
let batch_num = self.resolve_soft_batch_identifier(&batch_id)?;
let batch_num = self.resolve_soft_batch_identifier(batch_id)?;
Ok(match batch_num {
Some(num) => {
if let Some(stored_batch) = self.db.get::<SoftBatchByNumber>(&num)? {
Expand Down Expand Up @@ -193,7 +195,7 @@ impl LedgerRpcProvider for LedgerDB {
&self,
hash: &[u8; 32],
) -> Result<Option<SoftBatchResponse>, anyhow::Error> {
self.get_soft_batch(SoftBatchIdentifier::Hash(*hash))
self.get_soft_batch(&SoftBatchIdentifier::Hash(*hash))
}

fn get_batch_by_hash<B: DeserializeOwned, T: DeserializeOwned>(
Expand Down Expand Up @@ -228,7 +230,7 @@ impl LedgerRpcProvider for LedgerDB {
&self,
number: u64,
) -> Result<Option<SoftBatchResponse>, anyhow::Error> {
self.get_soft_batch(SoftBatchIdentifier::Number(number))
self.get_soft_batch(&SoftBatchIdentifier::Number(number))
}

fn get_batch_by_number<B: DeserializeOwned, T: DeserializeOwned>(
Expand Down Expand Up @@ -286,6 +288,43 @@ impl LedgerRpcProvider for LedgerDB {
self.get_batches(&ids, query_mode)
}

fn get_soft_batches(
&self,
soft_batch_ids: &Vec<SoftBatchIdentifier>,
) -> Result<Vec<Option<SoftBatchResponse>>, anyhow::Error> {
anyhow::ensure!(
soft_batch_ids.len() <= MAX_SOFT_BATCHES_PER_REQUEST as usize,
"requested too many soft batches. Requested: {}. Max: {}",
soft_batch_ids.len(),
MAX_BATCHES_PER_REQUEST
);

let mut out = Vec::with_capacity(soft_batch_ids.len());
for soft_batch_id in soft_batch_ids {
if let Some(soft_batch) = self.get_soft_batch(soft_batch_id)? {
out.push(Some(soft_batch));
} else {
out.push(None);
}
}
Ok(out)
}

fn get_soft_batches_range(
&self,
start: u64,
end: u64,
) -> Result<Vec<Option<SoftBatchResponse>>, anyhow::Error> {
anyhow::ensure!(start <= end, "start must be <= end");
anyhow::ensure!(
end - start <= MAX_BATCHES_PER_REQUEST,
"requested batch range too large. Max: {}",
MAX_BATCHES_PER_REQUEST
);
let ids: Vec<_> = (start..=end).map(SoftBatchIdentifier::Number).collect();
self.get_soft_batches(&ids)
}

fn get_transactions_range<T: DeserializeOwned>(
&self,
start: u64,
Expand Down Expand Up @@ -347,7 +386,10 @@ impl LedgerDB {
batch_id: &SoftBatchIdentifier,
) -> Result<Option<BatchNumber>, anyhow::Error> {
match batch_id {
SoftBatchIdentifier::Hash(hash) => self.db.get::<SoftBatchByHash>(hash),
SoftBatchIdentifier::Hash(hash) => {
println!("Hash: {:?}", hash);
self.db.get::<SoftBatchByHash>(hash)
}
SoftBatchIdentifier::Number(num) => Ok(Some(BatchNumber(*num))),
}
}
Expand Down
6 changes: 6 additions & 0 deletions crates/sovereign-sdk/full-node/sov-ledger-rpc/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,12 @@ where
.get_batches_range::<B, Tx>(args.0, args.1, args.2)
.map_err(|e| to_jsonrpsee_error_object(e, LEDGER_RPC_ERROR))
})?;
rpc.register_method("ledger_getSoftBatchRange", move |params, ledger| {
let args: (u64, u64) = params.parse()?;
ledger
.get_soft_batches_range(args.0, args.1)
.map_err(|e| to_jsonrpsee_error_object(e, LEDGER_RPC_ERROR))
})?;
rpc.register_method("ledger_getTransactionsRange", move |params, ledger| {
let args: RangeArgs = params.parse()?;
ledger
Expand Down
Loading

0 comments on commit 171e5d3

Please sign in to comment.