From 3ffca789a4eb17d7b7db2c5d4c12c3cf2a0d7ebf Mon Sep 17 00:00:00 2001 From: Jude Nelson Date: Fri, 11 Aug 2023 14:40:01 -0400 Subject: [PATCH] feat: test for stackerdb reconfigure --- stackslib/src/net/stackerdb/tests/db.rs | 158 +++++++++++++++++++++++- 1 file changed, 155 insertions(+), 3 deletions(-) diff --git a/stackslib/src/net/stackerdb/tests/db.rs b/stackslib/src/net/stackerdb/tests/db.rs index a0a0d265b..0e6b41003 100644 --- a/stackslib/src/net/stackerdb/tests/db.rs +++ b/stackslib/src/net/stackerdb/tests/db.rs @@ -348,7 +348,7 @@ fn test_stackerdb_prepare_clear_slots() { if slot_id < 2 { // belongs to 0x02 assert_eq!( - slot_validation.stacker, + slot_validation.signer, StacksAddress { version: 0x02, bytes: Hash160([0x02; 20]) @@ -357,7 +357,7 @@ fn test_stackerdb_prepare_clear_slots() { } else if slot_id >= 2 && slot_id < 2 + 3 { // belongs to 0x03 assert_eq!( - slot_validation.stacker, + slot_validation.signer, StacksAddress { version: 0x03, bytes: Hash160([0x03; 20]) @@ -366,7 +366,7 @@ fn test_stackerdb_prepare_clear_slots() { } else if slot_id >= 2 + 3 && slot_id < 2 + 3 + 4 { // belongs to 0x03 assert_eq!( - slot_validation.stacker, + slot_validation.signer, StacksAddress { version: 0x04, bytes: Hash160([0x04; 20]) @@ -562,3 +562,155 @@ fn test_stackerdb_insert_query_chunks() { assert!(ts > 0); } } + +/// Verify that we can reconfigure the database by changing its slots +#[test] +fn test_reconfigure_stackerdb() { + let path = "/tmp/test_stackerdb_reconfigure.sqlite"; + setup_test_path(path); + + let sc = ContractId::from_parts( + StacksAddress { + version: 0x01, + bytes: Hash160([0x01; 20]), + }, + ContractName::try_from("db1").unwrap(), + ); + + let mut db = StackerDBs::connect(path, true).unwrap(); + + let mut db_config = StackerDBConfig::noop(); + db_config.max_writes = 3; + db_config.write_freq = 120; + + let tx = db.tx_begin(db_config.clone()).unwrap(); + + let pks: Vec<_> = (0..10).map(|_| StacksPrivateKey::new()).collect(); + let addrs: Vec<_> = pks + .iter() + .map(|pk| { + StacksAddress::from_public_keys( + C32_ADDRESS_VERSION_MAINNET_SINGLESIG, + &AddressHashMode::SerializeP2PKH, + 1, + &vec![StacksPublicKey::from_private(&pk)], + ) + .unwrap() + }) + .collect(); + + tx.create_stackerdb( + &sc, + &addrs + .clone() + .into_iter() + .map(|addr| (addr, 1)) + .collect::>(), + ) + .unwrap(); + + // store some data + let mut initial_metadata = vec![]; + for (i, pk) in pks.iter().enumerate() { + let mut chunk_data = StackerDBChunkData { + slot_id: i as u32, + slot_version: 1, + sig: MessageSignature::empty(), + data: vec![i as u8; 128], + }; + + chunk_data.sign(&pk).unwrap(); + + let slot_metadata = tx.get_slot_metadata(&sc, i as u32).unwrap().unwrap(); + assert_eq!(slot_metadata.slot_id, i as u32); + assert_eq!(slot_metadata.slot_version, 0); + assert_eq!(slot_metadata.data_hash, Sha512Trunc256Sum([0x00; 32])); + assert_eq!(slot_metadata.signature, MessageSignature::empty()); + + // should succeed + tx.try_replace_chunk(&sc, &chunk_data.get_slot_metadata(), &chunk_data.data) + .unwrap(); + + let slot_metadata = tx.get_slot_metadata(&sc, i as u32).unwrap().unwrap(); + assert_eq!(slot_metadata.slot_id, i as u32); + assert_eq!(slot_metadata.slot_version, chunk_data.slot_version); + assert_eq!(slot_metadata.data_hash, chunk_data.data_hash()); + assert_eq!(slot_metadata.signature, chunk_data.sig); + + initial_metadata.push((slot_metadata, chunk_data)); + } + + let new_pks: Vec<_> = (0..10).map(|_| StacksPrivateKey::new()).collect(); + let reconfigured_pks = vec![ + // first five slots are unchanged + pks[0], pks[1], pks[2], pks[3], pks[4], + // next five slots are different, so their contents will be dropped and versions and write + // timestamps reset + new_pks[0], new_pks[1], new_pks[2], new_pks[3], new_pks[4], + // next five slots are now, so they'll be uninitialized + new_pks[5], new_pks[6], new_pks[7], new_pks[8], new_pks[9], + ]; + let reconfigured_addrs: Vec<_> = reconfigured_pks + .iter() + .map(|pk| { + StacksAddress::from_public_keys( + C32_ADDRESS_VERSION_MAINNET_SINGLESIG, + &AddressHashMode::SerializeP2PKH, + 1, + &vec![StacksPublicKey::from_private(&pk)], + ) + .unwrap() + }) + .collect(); + + // reconfigure + tx.reconfigure_stackerdb( + &sc, + &reconfigured_addrs + .clone() + .into_iter() + .map(|addr| (addr, 1)) + .collect::>(), + ) + .unwrap(); + + tx.commit().unwrap(); + + for (i, pk) in new_pks.iter().enumerate() { + if i < 5 { + // first five are unchanged + let chunk_data = StackerDBChunkData { + slot_id: i as u32, + slot_version: 1, + sig: MessageSignature::empty(), + data: vec![i as u8; 128], + }; + + let slot_metadata = db.get_slot_metadata(&sc, i as u32).unwrap().unwrap(); + let chunk = db.get_latest_chunk(&sc, i as u32).unwrap().unwrap(); + + assert_eq!(initial_metadata[i].0, slot_metadata); + assert_eq!(initial_metadata[i].1.data, chunk); + } else if i < 10 { + // next five are wiped + let slot_metadata = db.get_slot_metadata(&sc, i as u32).unwrap().unwrap(); + assert_eq!(slot_metadata.slot_id, i as u32); + assert_eq!(slot_metadata.slot_version, 0); + assert_eq!(slot_metadata.data_hash, Sha512Trunc256Sum([0x00; 32])); + assert_eq!(slot_metadata.signature, MessageSignature::empty()); + + let chunk = db.get_latest_chunk(&sc, i as u32).unwrap().unwrap(); + assert_eq!(chunk.len(), 0); + } else { + // final five are new + let slot_metadata = db.get_slot_metadata(&sc, i as u32).unwrap().unwrap(); + assert_eq!(slot_metadata.slot_id, i as u32); + assert_eq!(slot_metadata.slot_version, 0); + assert_eq!(slot_metadata.data_hash, Sha512Trunc256Sum([0x00; 32])); + assert_eq!(slot_metadata.signature, MessageSignature::empty()); + + let chunk = db.get_latest_chunk(&sc, i as u32).unwrap().unwrap(); + assert_eq!(chunk.len(), 0); + } + } +}