grin/chain/src/store.rs

93 lines
2.7 KiB
Rust
Raw Normal View History

// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
2016-10-21 03:06:12 +03:00
//! Implements storage primitives required by the chain
use byteorder::{WriteBytesExt, BigEndian};
use types::*;
use core::core::hash::Hash;
use core::core::{Block, BlockHeader};
2016-10-21 03:06:12 +03:00
use grin_store;
const STORE_SUBPATH: &'static str = "chain";
2016-10-21 03:06:12 +03:00
const SEP: u8 = ':' as u8;
const BLOCK_HEADER_PREFIX: u8 = 'h' as u8;
const BLOCK_PREFIX: u8 = 'b' as u8;
2016-10-21 03:06:12 +03:00
const HEAD_PREFIX: u8 = 'H' as u8;
/// An implementation of the ChainStore trait backed by a simple key-value
/// store.
pub struct ChainKVStore {
db: grin_store::Store,
}
impl ChainKVStore {
pub fn new(root_path: String) -> Result<ChainKVStore, Error> {
let db = try!(grin_store::Store::open(format!("{}/{}", root_path, STORE_SUBPATH).as_str())
.map_err(to_store_err));
2016-10-21 03:06:12 +03:00
Ok(ChainKVStore { db: db })
}
}
impl ChainStore for ChainKVStore {
fn head(&self) -> Result<Tip, Error> {
option_to_not_found(self.db.get_ser(&vec![HEAD_PREFIX]))
}
fn head_header(&self) -> Result<BlockHeader, Error> {
let head: Tip = try!(option_to_not_found(self.db.get_ser(&vec![HEAD_PREFIX])));
self.get_block_header(&head.last_block_h)
}
fn save_block(&self, b: &Block) -> Result<(), Error> {
try!(self.db
.put_ser(&to_key(BLOCK_PREFIX, &mut b.hash().to_vec())[..], b)
.map_err(&to_store_err));
self.db
.put_ser(&to_key(BLOCK_HEADER_PREFIX, &mut b.hash().to_vec())[..],
&b.header)
.map_err(&to_store_err)
}
fn get_block_header(&self, h: &Hash) -> Result<BlockHeader, Error> {
option_to_not_found(self.db.get_ser(&to_key(BLOCK_HEADER_PREFIX, &mut h.to_vec())))
2016-10-21 03:06:12 +03:00
}
fn save_head(&self, t: &Tip) -> Result<(), Error> {
self.db.put_ser(&vec![HEAD_PREFIX], t).map_err(&to_store_err)
2016-10-21 03:06:12 +03:00
}
}
fn to_key(prefix: u8, val: &mut Vec<u8>) -> &mut Vec<u8> {
val.insert(0, SEP);
val.insert(0, prefix);
val
}
fn to_store_err(e: grin_store::Error) -> Error {
Error::StorageErr(format!("{:?}", e))
}
/// unwraps the inner option by converting the none case to a not found error
fn option_to_not_found<T>(res: Result<Option<T>, grin_store::Error>) -> Result<T, Error> {
match res {
Ok(None) => Err(Error::NotFoundErr),
Ok(Some(o)) => Ok(o),
Err(e) => Err(to_store_err(e)),
}
}