Skip to content

Commit db2e40a

Browse files
committed
Store ChainstateStorageVersion
1 parent 702936c commit db2e40a

File tree

11 files changed

+95
-70
lines changed

11 files changed

+95
-70
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

chainstate/launcher/src/storage_compatibility.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@ fn check_storage_version(
3636
.get_storage_version()
3737
.map_err(StorageCompatibilityCheckError::StorageError)?
3838
.ok_or(StorageCompatibilityCheckError::StorageVersionMissing)?;
39-
let storage_version = ChainstateStorageVersion::new(storage_version)
40-
.ok_or(StorageCompatibilityCheckError::StorageVersionConversionError)?;
4139

4240
ensure!(
4341
storage_version == ChainstateStorageVersion::CURRENT,

chainstate/src/detail/error.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,8 +217,6 @@ pub enum StorageCompatibilityCheckError {
217217
StorageError(#[from] chainstate_storage::Error),
218218
#[error("Storage version is missing in the db")]
219219
StorageVersionMissing,
220-
#[error("Failed to convert storage error")]
221-
StorageVersionConversionError,
222220
#[error("Magic bytes are missing in the db")]
223221
MagicBytesMissing,
224222
#[error("Chain type is missing in the db")]

chainstate/storage/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ utxo = { path = '../../utxo' }
1717

1818
mockall = { workspace = true, optional = true }
1919

20+
parity-scale-codec.workspace = true
21+
2022
[dev-dependencies]
2123
crypto = { path = '../../crypto' }
2224
test-utils = {path = '../../test-utils'}

chainstate/storage/src/internal/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl<B: storage::Backend> Store<B> {
5656
// Set defaults if missing
5757

5858
if storage.get_storage_version()?.is_none() {
59-
storage.set_storage_version(ChainstateStorageVersion::CURRENT as u32)?;
59+
storage.set_storage_version(ChainstateStorageVersion::CURRENT)?;
6060
}
6161

6262
if storage.get_magic_bytes()?.is_none() {
@@ -224,7 +224,7 @@ macro_rules! delegate_to_transaction {
224224

225225
impl<B: storage::Backend> BlockchainStorageRead for Store<B> {
226226
delegate_to_transaction! {
227-
fn get_storage_version(&self) -> crate::Result<Option<u32>>;
227+
fn get_storage_version(&self) -> crate::Result<Option<ChainstateStorageVersion>>;
228228
fn get_magic_bytes(&self) -> crate::Result<Option<[u8; 4]>>;
229229
fn get_chain_type(&self) -> crate::Result<Option<String>>;
230230
fn get_best_block_id(&self) -> crate::Result<Option<Id<GenBlock>>>;
@@ -379,7 +379,7 @@ impl<B: storage::Backend> PoSAccountingStorageRead<SealedStorageTag> for Store<B
379379

380380
impl<B: storage::Backend> BlockchainStorageWrite for Store<B> {
381381
delegate_to_transaction! {
382-
fn set_storage_version(&mut self, version: u32) -> crate::Result<()>;
382+
fn set_storage_version(&mut self, version: ChainstateStorageVersion) -> crate::Result<()>;
383383
fn set_magic_bytes(&mut self, bytes: &[u8; 4]) -> crate::Result<()>;
384384
fn set_chain_type(&mut self, chain: &str) -> crate::Result<()>;
385385
fn set_best_block_id(&mut self, id: &Id<GenBlock>) -> crate::Result<()>;

chainstate/storage/src/internal/store_tx.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,12 @@ use utxo::{Utxo, UtxosBlockUndo, UtxosStorageRead, UtxosStorageWrite};
3737

3838
use crate::{
3939
schema::{self as db, Schema},
40-
BlockchainStorageRead, BlockchainStorageWrite, SealedStorageTag, TipStorageTag,
40+
BlockchainStorageRead, BlockchainStorageWrite, ChainstateStorageVersion, SealedStorageTag,
41+
TipStorageTag,
4142
};
4243

4344
mod well_known {
44-
use super::{Codec, GenBlock, Id};
45+
use super::{ChainstateStorageVersion, Codec, GenBlock, Id};
4546

4647
/// Pre-defined database keys
4748
pub trait Entry {
@@ -61,7 +62,7 @@ mod well_known {
6162
};
6263
}
6364

64-
declare_entry!(StoreVersion: u32);
65+
declare_entry!(StoreVersion: ChainstateStorageVersion);
6566
declare_entry!(BestBlockId: Id<GenBlock>);
6667
declare_entry!(UtxosBestBlockId: Id<GenBlock>);
6768
declare_entry!(TxIndexEnabled: bool);
@@ -79,7 +80,7 @@ macro_rules! impl_read_ops {
7980
($TxType:ident) => {
8081
/// Blockchain data storage transaction
8182
impl<'st, B: storage::Backend> BlockchainStorageRead for $TxType<'st, B> {
82-
fn get_storage_version(&self) -> crate::Result<Option<u32>> {
83+
fn get_storage_version(&self) -> crate::Result<Option<ChainstateStorageVersion>> {
8384
self.read_value::<well_known::StoreVersion>()
8485
}
8586

@@ -394,7 +395,7 @@ impl_read_ops!(StoreTxRo);
394395
impl_read_ops!(StoreTxRw);
395396

396397
impl<'st, B: storage::Backend> BlockchainStorageWrite for StoreTxRw<'st, B> {
397-
fn set_storage_version(&mut self, version: u32) -> crate::Result<()> {
398+
fn set_storage_version(&mut self, version: ChainstateStorageVersion) -> crate::Result<()> {
398399
self.write_value::<well_known::StoreVersion>(&version)
399400
}
400401

chainstate/storage/src/internal/test.rs

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,14 @@ fn test_storage_manipulation() {
7474

7575
// Storage version manipulation
7676
assert_eq!(store.get_storage_version(), Ok(None));
77-
assert_eq!(store.set_storage_version(2), Ok(()));
78-
assert_eq!(store.get_storage_version(), Ok(Some(2)));
77+
assert_eq!(
78+
store.set_storage_version(ChainstateStorageVersion::V0),
79+
Ok(())
80+
);
81+
assert_eq!(
82+
store.get_storage_version(),
83+
Ok(Some(ChainstateStorageVersion::V0))
84+
);
7985

8086
// Store is now empty, the block is not there
8187
assert_eq!(store.get_block(block0.get_id()), Ok(None));
@@ -150,17 +156,19 @@ fn test_storage_manipulation() {
150156
#[test]
151157
fn get_set_transactions() {
152158
utils::concurrency::model(|| {
153-
// Set up the store and initialize the version to 2
159+
// Set up the store and initialize the version to 0
154160
let mut store = TestStore::new_empty().unwrap();
155-
assert_eq!(store.set_storage_version(2), Ok(()));
161+
assert_eq!(
162+
store.set_storage_version(ChainstateStorageVersion::V0),
163+
Ok(())
164+
);
156165

157166
// Concurrently bump version and run a transaction that reads the version twice.
158167
let thr1 = {
159168
let store = Store::clone(&store);
160169
utils::thread::spawn(move || {
161170
let mut tx = store.transaction_rw(None).unwrap();
162-
let v = tx.get_storage_version().unwrap().unwrap();
163-
tx.set_storage_version(v + 1).unwrap();
171+
tx.set_storage_version(ChainstateStorageVersion::V1).unwrap();
164172
tx.commit().unwrap();
165173
})
166174
};
@@ -170,80 +178,101 @@ fn get_set_transactions() {
170178
let tx = store.transaction_ro().unwrap();
171179
let v1 = tx.get_storage_version().unwrap().unwrap();
172180
let v2 = tx.get_storage_version().unwrap().unwrap();
173-
assert!([2, 3].contains(&v1));
181+
assert!([ChainstateStorageVersion::V0, ChainstateStorageVersion::V1].contains(&v1));
174182
assert_eq!(v1, v2, "Version query in a transaction inconsistent");
175183
})
176184
};
177185

178186
let _ = thr0.join();
179187
let _ = thr1.join();
180-
assert_eq!(store.get_storage_version(), Ok(Some(3)));
188+
assert_eq!(
189+
store.get_storage_version(),
190+
Ok(Some(ChainstateStorageVersion::V1))
191+
);
181192
})
182193
}
183194

184-
#[test]
185-
fn test_storage_transactions() {
186-
utils::concurrency::model(|| {
187-
// Set up the store and initialize the version to 2
188-
let mut store = TestStore::new_empty().unwrap();
189-
assert_eq!(store.set_storage_version(2), Ok(()));
195+
#[rstest]
196+
#[trace]
197+
#[case(Seed::from_entropy())]
198+
fn test_storage_transactions(#[case] seed: Seed) {
199+
utils::concurrency::model(move || {
200+
// Set up the store with empty utxo set
201+
let mut rng = make_seedable_rng(seed);
202+
let store = TestStore::new_empty().unwrap();
203+
assert!(store.read_utxo_set().unwrap().is_empty());
190204

191-
// Concurrently bump version by 3 and 5 in two separate threads
205+
let (utxo1, outpoint1) = create_rand_utxo(&mut rng, 1);
206+
let (utxo2, outpoint2) = create_rand_utxo(&mut rng, 1);
207+
208+
let expected_utxo_set = BTreeMap::from_iter([
209+
(outpoint1.clone(), utxo1.clone()),
210+
(outpoint2.clone(), utxo2.clone()),
211+
]);
212+
213+
// Concurrently insert 2 utxo in two separate threads
192214
let thr0 = {
193215
let store = Store::clone(&store);
194216
utils::thread::spawn(move || {
195217
let mut tx = store.transaction_rw(None).unwrap();
196-
let v = tx.get_storage_version().unwrap().unwrap();
197-
tx.set_storage_version(v + 3).unwrap();
218+
tx.set_utxo(&outpoint1, utxo1).unwrap();
198219
tx.commit().unwrap();
199220
})
200221
};
201222
let thr1 = {
202223
let store = Store::clone(&store);
203224
utils::thread::spawn(move || {
204225
let mut tx = store.transaction_rw(None).unwrap();
205-
let v = tx.get_storage_version().unwrap().unwrap();
206-
tx.set_storage_version(v + 5).unwrap();
226+
tx.set_utxo(&outpoint2, utxo2).unwrap();
207227
tx.commit().unwrap();
208228
})
209229
};
210230

211231
let _ = thr0.join();
212232
let _ = thr1.join();
213-
assert_eq!(store.get_storage_version(), Ok(Some(10)));
233+
assert_eq!(store.read_utxo_set(), Ok(expected_utxo_set));
214234
})
215235
}
216236

217-
#[test]
218-
fn test_storage_transactions_with_result_check() {
219-
utils::concurrency::model(|| {
220-
// Set up the store and initialize the version to 2
221-
let mut store = TestStore::new_empty().unwrap();
222-
assert_eq!(store.set_storage_version(2), Ok(()));
237+
#[rstest]
238+
#[trace]
239+
#[case(Seed::from_entropy())]
240+
fn test_storage_transactions_with_result_check(#[case] seed: Seed) {
241+
utils::concurrency::model(move || {
242+
// Set up the store with empty utxo set
243+
let mut rng = make_seedable_rng(seed);
244+
let store = TestStore::new_empty().unwrap();
245+
assert!(store.read_utxo_set().unwrap().is_empty());
246+
247+
let (utxo1, outpoint1) = create_rand_utxo(&mut rng, 1);
248+
let (utxo2, outpoint2) = create_rand_utxo(&mut rng, 1);
249+
250+
let expected_utxo_set = BTreeMap::from_iter([
251+
(outpoint1.clone(), utxo1.clone()),
252+
(outpoint2.clone(), utxo2.clone()),
253+
]);
223254

224-
// Concurrently bump version by 3 and 5 in two separate threads
255+
// Concurrently insert 2 utxo in two separate threads
225256
let thr0 = {
226257
let store = Store::clone(&store);
227258
utils::thread::spawn(move || {
228259
let mut tx = store.transaction_rw(None).unwrap();
229-
let v = tx.get_storage_version().unwrap().unwrap();
230-
assert!(tx.set_storage_version(v + 3).is_ok());
260+
assert!(tx.set_utxo(&outpoint1, utxo1).is_ok());
231261
assert!(tx.commit().is_ok());
232262
})
233263
};
234264
let thr1 = {
235265
let store = Store::clone(&store);
236266
utils::thread::spawn(move || {
237267
let mut tx = store.transaction_rw(None).unwrap();
238-
let v = tx.get_storage_version().unwrap().unwrap();
239-
assert!(tx.set_storage_version(v + 5).is_ok());
268+
assert!(tx.set_utxo(&outpoint2, utxo2).is_ok());
240269
assert!(tx.commit().is_ok());
241270
})
242271
};
243272

244273
let _ = thr0.join();
245274
let _ = thr1.join();
246-
assert_eq!(store.get_storage_version(), Ok(Some(10)));
275+
assert_eq!(store.read_utxo_set(), Ok(expected_utxo_set));
247276
})
248277
}
249278

chainstate/storage/src/internal/version.rs

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,14 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16-
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
17-
#[repr(u32)]
16+
use serialization::{Decode, Encode};
17+
18+
#[derive(Debug, Encode, Decode, Clone, Copy, Eq, PartialEq)]
1819
pub enum ChainstateStorageVersion {
19-
// skipping 0 for historical reasons
20-
V1 = 1,
20+
V0,
21+
V1,
2122
}
2223

2324
impl ChainstateStorageVersion {
2425
pub const CURRENT: Self = Self::V1;
25-
26-
pub fn new(value: u32) -> Option<Self> {
27-
match value {
28-
1 => Some(ChainstateStorageVersion::V1),
29-
_ => None,
30-
}
31-
}
3226
}

chainstate/storage/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ pub trait BlockchainStorageRead:
6161
+ EpochStorageRead
6262
{
6363
/// Get storage version
64-
fn get_storage_version(&self) -> crate::Result<Option<u32>>;
64+
fn get_storage_version(&self) -> crate::Result<Option<ChainstateStorageVersion>>;
6565

6666
/// Get magic bytes
6767
fn get_magic_bytes(&self) -> crate::Result<Option<[u8; 4]>>;
@@ -138,7 +138,7 @@ pub trait BlockchainStorageWrite:
138138
+ EpochStorageWrite
139139
{
140140
/// Set storage version
141-
fn set_storage_version(&mut self, version: u32) -> Result<()>;
141+
fn set_storage_version(&mut self, version: ChainstateStorageVersion) -> Result<()>;
142142

143143
/// Set magic bytes
144144
fn set_magic_bytes(&mut self, bytes: &[u8; 4]) -> Result<()>;

chainstate/storage/src/mock/mock_impl.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,14 @@ use super::mock_impl_accounting::{
3939
PoSAccountingStorageWriteTip,
4040
};
4141

42+
use crate::ChainstateStorageVersion;
43+
4244
mockall::mock! {
4345
/// A mock object for blockchain storage
4446
pub Store {}
4547

4648
impl crate::BlockchainStorageRead for Store {
47-
fn get_storage_version(&self) -> crate::Result<Option<u32>>;
49+
fn get_storage_version(&self) -> crate::Result<Option<ChainstateStorageVersion>>;
4850
fn get_magic_bytes(&self) -> crate::Result<Option<[u8; 4]>>;
4951
fn get_chain_type(&self) -> crate::Result<Option<String>>;
5052
fn get_best_block_id(&self) -> crate::Result<Option<Id<GenBlock>>>;
@@ -149,7 +151,7 @@ mockall::mock! {
149151
}
150152

151153
impl crate::BlockchainStorageWrite for Store {
152-
fn set_storage_version(&mut self, version: u32) -> crate::Result<()>;
154+
fn set_storage_version(&mut self, version: ChainstateStorageVersion) -> crate::Result<()>;
153155
fn set_magic_bytes(&mut self, bytes: &[u8; 4]) -> crate::Result<()>;
154156
fn set_chain_type(&mut self, chain: &str) -> crate::Result<()>;
155157
fn set_best_block_id(&mut self, id: &Id<GenBlock>) -> crate::Result<()>;
@@ -300,7 +302,7 @@ mockall::mock! {
300302
pub StoreTxRo {}
301303

302304
impl crate::BlockchainStorageRead for StoreTxRo {
303-
fn get_storage_version(&self) -> crate::Result<Option<u32>>;
305+
fn get_storage_version(&self) -> crate::Result<Option<ChainstateStorageVersion>>;
304306
fn get_magic_bytes(&self) -> crate::Result<Option<[u8; 4]>>;
305307
fn get_chain_type(&self) -> crate::Result<Option<String>>;
306308
fn get_best_block_id(&self) -> crate::Result<Option<Id<GenBlock>>>;
@@ -414,7 +416,7 @@ mockall::mock! {
414416
pub StoreTxRw {}
415417

416418
impl crate::BlockchainStorageRead for StoreTxRw {
417-
fn get_storage_version(&self) -> crate::Result<Option<u32>>;
419+
fn get_storage_version(&self) -> crate::Result<Option<ChainstateStorageVersion>>;
418420
fn get_magic_bytes(&self) -> crate::Result<Option<[u8; 4]>>;
419421
fn get_chain_type(&self) -> crate::Result<Option<String>>;
420422
fn get_best_block_id(&self) -> crate::Result<Option<Id<GenBlock>>>;
@@ -518,7 +520,7 @@ mockall::mock! {
518520
}
519521

520522
impl crate::BlockchainStorageWrite for StoreTxRw {
521-
fn set_storage_version(&mut self, version: u32) -> crate::Result<()>;
523+
fn set_storage_version(&mut self, version: ChainstateStorageVersion) -> crate::Result<()>;
522524
fn set_magic_bytes(&mut self, bytes: &[u8; 4]) -> crate::Result<()>;
523525
fn set_chain_type(&mut self, chain: &str) -> crate::Result<()>;
524526
fn set_best_block_id(&mut self, id: &Id<GenBlock>) -> crate::Result<()>;

0 commit comments

Comments
 (0)