Skip to content

Commit

Permalink
Merge pull request #7 from FindoraNetwork/dev-versioning
Browse files Browse the repository at this point in the history
FO-284: Save and Prune versions automatically on commit
  • Loading branch information
kevinssgh committed Sep 15, 2021
2 parents d6317a2 + 74662d5 commit f29d0ae
Show file tree
Hide file tree
Showing 5 changed files with 681 additions and 81 deletions.
96 changes: 60 additions & 36 deletions README.md
Expand Up @@ -6,53 +6,77 @@ The crate was designed to be the blockchain state database. It provides persiste

### FEATURES:
- Key-value updates(in a transaction) applied to storage can be reverted if transaction fails.
- Key-value updates(in a block) applied to storage can be reverted if block failes to commit.
- Prefix-based key-value iteration on commited state.
- Key-value updates(in a block) applied to storage can be reverted if block fails to commit.
- Prefix-based key-value iteration on committed state.
- Prefix-based key-value iteration on latest state.
- Versioned key-value pairs available for queries.
- Entire chain-state available as a batch of key-value pairs at any height within version window.
- Root hash calculation.

**Example:**
```toml
[dependencies]
storage = { git = "ssh://git@github.com/FindoraNetwork/storage.git", branch = "master" }
parking_lot = "0.11.1"
```
```rust
extern crate storage;
use storage::state::ChainState;
use storage::state::{ChainState, State};
use storage::db::FinDB;
use storage::store::PrefixedStore;
use parking_lot::RwLock;
use std::sync::Arc;
use std::thread;
use storage::store::traits::{Stated, Store};

// This window is used to determine how many versions of each KV pair are to be kept in the
// auxiliary db.
const VER_WINDOW:u64 = 100;

fn main() {
println!("Testing Prefixed Store!");
prefixed_store();
}

fn prefixed_store() {
// create store
let path = thread::current().name().unwrap().to_owned();
let fdb = FinDB::open(path).expect("failed to open db");
let cs = Arc::new(RwLock::new(ChainState::new(fdb, "test_db".to_string())));
let mut state = State::new(cs);
let mut store = PrefixedStore::new("my_store", &mut state);
let hash0 = store.state().root_hash();

// set kv pairs and commit
store.set(b"k10", b"v10".to_vec());
store.set(b"k20", b"v20".to_vec());
let (hash1, _height) = store.state_mut().commit(1).unwrap();

// verify
assert_eq!(store.get(b"k10").unwrap(), Some(b"v10".to_vec()));
assert_eq!(store.get(b"k20").unwrap(), Some(b"v20".to_vec()));
assert_ne!(hash0, hash1);

// add, delete and update
store.set(b"k10", b"v15".to_vec());
store.delete(b"k20").unwrap();
store.set(b"k30", b"v30".to_vec());

// verify
assert_eq!(store.get(b"k10").unwrap(), Some(b"v15".to_vec()));
assert_eq!(store.get(b"k20").unwrap(), None);
assert_eq!(store.get(b"k30").unwrap(), Some(b"v30".to_vec()));

// rollback and verify
store.state_mut().discard_session();
assert_eq!(store.get(b"k10").unwrap(), Some(b"v10".to_vec()));
assert_eq!(store.get(b"k20").unwrap(), Some(b"v20".to_vec()));
assert_eq!(store.get(b"k30").unwrap(), None);
// create store
let path = thread::current().name().unwrap().to_owned();
let fdb = FinDB::open(path).expect("failed to open db");
let cs = Arc::new(RwLock::new(ChainState::new(fdb, "test_db".to_string(), VER_WINDOW)));
let mut state = State::new(cs);
let mut store = PrefixedStore::new("my_store", &mut state);
let hash0 = store.state().root_hash();

// set kv pairs and commit
store.set(b"k10", b"v10".to_vec());
store.set(b"k20", b"v20".to_vec());
let (hash1, _height) = store.state_mut().commit(1).unwrap();

// verify
assert_eq!(store.get(b"k10").unwrap(), Some(b"v10".to_vec()));
assert_eq!(store.get(b"k20").unwrap(), Some(b"v20".to_vec()));
assert_ne!(hash0, hash1);

// add, delete and update
store.set(b"k10", b"v15".to_vec());
store.delete(b"k20").unwrap();
store.set(b"k30", b"v30".to_vec());

// verify
assert_eq!(store.get(b"k10").unwrap(), Some(b"v15".to_vec()));
assert_eq!(store.get(b"k20").unwrap(), None);
assert_eq!(store.get(b"k30").unwrap(), Some(b"v30".to_vec()));

// rollback and verify
store.state_mut().discard_session();
assert_eq!(store.get(b"k10").unwrap(), Some(b"v10".to_vec()));
assert_eq!(store.get(b"k20").unwrap(), Some(b"v20".to_vec()));
assert_eq!(store.get(b"k30").unwrap(), None);

// get previous version of a key value pair
store.set(b"k10", b"v25".to_vec());
let _ = store.state_mut().commit(2);
assert_eq!(store.get(b"k10").unwrap(), Some(b"v25".to_vec()));
assert_eq!(store.get_v(b"k10", 1).unwrap(), Some(b"v10".to_vec()));
}
```

0 comments on commit f29d0ae

Please sign in to comment.