u32 everywhere

This commit is contained in:
NikVolf 2016-10-26 23:58:19 +03:00
parent 1457d9d056
commit 93b765d8ea
7 changed files with 123 additions and 30 deletions

7
Cargo.lock generated
View File

@ -51,6 +51,11 @@ name = "base58"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bit-vec"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitcrypto"
version = "0.1.0"
@ -115,6 +120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
name = "db"
version = "0.1.0"
dependencies = [
"bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
"byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"chain 0.1.0",
"elastic-array 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -705,6 +711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
"checksum arrayvec 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d89f1b0e242270b5b797778af0c8d182a1a2ccac5d8d6fadf414223cc0fab096"
"checksum base58 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5024ee8015f02155eee35c711107ddd9a9bf3cb689cf2a9089c97e79b6e1ae83"
"checksum bit-vec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5b97c2c8e8bbb4251754f559df8af22fb264853c7d009084a576cdf12565089d"
"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855"

View File

@ -13,6 +13,7 @@ chain = { path = "../chain" }
serialization = { path = "../serialization" }
parking_lot = "0.3"
test-data = { path = "../test-data" }
bit-vec = "0.4"
[features]
dev = []

View File

@ -9,6 +9,7 @@ use rocksdb::{DB, Writable, WriteBatch, WriteOptions, IteratorMode, DBIterator,
use elastic_array::ElasticArray32;
use parking_lot::RwLock;
use primitives::bytes::Bytes;
use byteorder::{LittleEndian, ByteOrder};
/// Database error
pub enum Error {
@ -89,6 +90,20 @@ impl DBTransaction {
key: ekey,
});
}
/// Write u64
pub fn write_u64(&mut self, col: Option<u32>, key: &[u8], value: u64) {
let mut val = [0u8; 8];
LittleEndian::write_u64(&mut val, value);
self.put(col, key, &val);
}
/// Write u32
pub fn write_u32(&mut self, col: Option<u32>, key: &[u8], value: u32) {
let mut val = [0u8; 4];
LittleEndian::write_u32(&mut val, value);
self.put(col, key, &val);
}
}
enum KeyState {

View File

@ -7,6 +7,7 @@ extern crate primitives;
extern crate byteorder;
extern crate chain;
extern crate serialization;
extern crate bit_vec;
#[cfg(test)]
extern crate ethcore_devtools as devtools;
@ -17,9 +18,10 @@ mod kvdb;
mod storage;
#[cfg(feature="dev")]
mod test_storage;
mod transaction_meta;
pub enum BlockRef {
Number(u64),
Number(u32),
Hash(primitives::hash::H256),
}

View File

@ -9,6 +9,7 @@ use primitives::bytes::Bytes;
use super::BlockRef;
use serialization;
use chain::{self, RepresentH256};
use parking_lot::RwLock;
const COL_COUNT: u32 = 10;
const COL_META: u32 = 0;
@ -28,10 +29,10 @@ const DB_VERSION: u32 = 1;
/// Blockchain storage interface
pub trait Store : Send + Sync {
/// get best block number
fn best_block_number(&self) -> Option<u64>;
fn best_block_number(&self) -> Option<u32>;
/// resolves hash by block number
fn block_hash(&self, number: u64) -> Option<H256>;
fn block_hash(&self, number: u32) -> Option<H256>;
/// resolves header bytes by block reference (number/hash)
fn block_header_bytes(&self, block_ref: BlockRef) -> Option<Bytes>;
@ -63,6 +64,8 @@ pub trait Store : Send + Sync {
/// Blockchain storage with rocksdb database
pub struct Storage {
database: Database,
best_block_number: RwLock<Option<u32>>,
best_block_hash: RwLock<Option<H256>>,
}
#[derive(Debug)]
@ -93,13 +96,15 @@ impl From<std::io::Error> for Error {
}
}
fn u64_key(num: u64) -> [u8; 8] {
let mut result = [0u8; 8];
LittleEndian::write_u64(&mut result, num);
fn u32_key(num: u32) -> [u8; 4] {
let mut result = [0u8; 4];
LittleEndian::write_u32(&mut result, num);
result
}
const KEY_VERSION: &'static[u8] = b"version";
const KEY_BEST_BLOCK_NUMBER: &'static[u8] = b"best_block_number";
const KEY_BEST_BLOCK_HASH: &'static[u8] = b"best_block_hash";
impl Storage {
@ -110,25 +115,41 @@ impl Storage {
let cfg = DatabaseConfig::with_columns(Some(COL_COUNT));
let db = try!(Database::open(&cfg, &*path.as_ref().to_string_lossy()));
match try!(db.get(Some(COL_META), KEY_VERSION)) {
Some(val) => {
let ver = LittleEndian::read_u32(&val);
if ver == DB_VERSION {
Ok(Storage { database: db, })
}
else {
Err(Error::Meta(MetaError::UnsupportedVersion))
let storage = Storage {
database: db,
best_block_number: RwLock::default(),
best_block_hash: RwLock::default(),
};
match storage.read_meta_u32(KEY_VERSION) {
Some(ver) => {
if ver != DB_VERSION {
return Err(Error::Meta(MetaError::UnsupportedVersion))
}
},
_ => {
let mut meta_transaction = db.transaction();
let mut ver_val = [0u8; 4];
LittleEndian::write_u32(&mut ver_val, DB_VERSION);
meta_transaction.put(Some(COL_META), KEY_VERSION, &ver_val);
try!(db.write(meta_transaction));
Ok(Storage { database: db, })
}
}
let mut meta_transaction = storage.database.transaction();
meta_transaction.write_u32(Some(COL_META), KEY_VERSION, DB_VERSION);
try!(storage.database.write(meta_transaction));
},
};
*storage.best_block_number.write() = storage.read_meta_u32(KEY_BEST_BLOCK_NUMBER);
*storage.best_block_hash.write() = storage.get(COL_META, KEY_BEST_BLOCK_HASH).map(|val| H256::from(&**val));
Ok(storage)
}
fn read_meta(&self, key: &[u8]) -> Option<Bytes> {
self.get(COL_META, key)
}
fn read_meta_u64(&self, key: &[u8]) -> Option<u64> {
self.read_meta(key).map(|val| LittleEndian::read_u64(&val))
}
fn read_meta_u32(&self, key: &[u8]) -> Option<u32> {
self.read_meta(key).map(|val| LittleEndian::read_u32(&val))
}
/// is invoked on database non-fatal query errors
@ -186,12 +207,12 @@ impl Storage {
}
impl Store for Storage {
fn best_block_number(&self) -> Option<u64> {
unimplemented!()
fn best_block_number(&self) -> Option<u32> {
*self.best_block_number.read()
}
fn block_hash(&self, number: u64) -> Option<H256> {
self.get(COL_BLOCK_HASHES, &u64_key(number))
fn block_hash(&self, number: u32) -> Option<H256> {
self.get(COL_BLOCK_HASHES, &u32_key(number))
.map(|val| H256::from(&**val))
}
@ -233,6 +254,8 @@ impl Store for Storage {
}
fn insert_block(&self, block: &chain::Block) -> Result<(), Error> {
let best_block_number = self.best_block_number.write();
let mut transaction = self.database.transaction();
let tx_space = block.transactions().len() * 32;
@ -308,7 +331,6 @@ mod tests {
let loaded_transaction = store.transaction(&tx1).unwrap();
assert_eq!(loaded_transaction.hash(), block.transactions()[0].hash());
}
}

View File

@ -54,11 +54,11 @@ impl TestStorage {
}
impl Store for TestStorage {
fn best_block_number(&self) -> Option<u64> {
self.data.read().best_block_number.map(|b| b as u64)
fn best_block_number(&self) -> Option<u32> {
self.data.read().best_block_number.map(|b| b as u32)
}
fn block_hash(&self, number: u64) -> Option<H256> {
fn block_hash(&self, number: u32) -> Option<H256> {
let data = self.data.read();
data.heights.get(&(number as usize)).cloned()
}

View File

@ -0,0 +1,46 @@
//! Transaction index
use bit_vec::BitVec;
use byteorder::{LittleEndian, ByteOrder};
/// structure for indexing transaction info
pub struct TransactionMeta {
block_height: u32,
spent: BitVec,
}
pub enum Error {
KeyTooShort(usize),
}
impl TransactionMeta {
/// new transaction description for indexing
pub fn new(block_height: u32, outputs: usize) -> Self {
TransactionMeta {
block_height: block_height,
spent: BitVec::from_elem(outputs, false),
}
}
/// note that particular output has been used
pub fn note_used(&mut self, index: usize) {
self.spent.set(index, true);
}
pub fn to_bytes(self) -> Vec<u8> {
let mut result = vec![0u8; 4];
LittleEndian::write_u32(&mut result[0..4], self.block_height);
result.extend(self.spent.to_bytes());
result
}
pub fn from_bytes(bytes: &[u8]) -> Result<TransactionMeta, Error> {
if bytes.len() <= 4 { return Err(Error::KeyTooShort(bytes.len())); }
Ok(TransactionMeta {
block_height: LittleEndian::read_u32(&bytes[0..4]),
spent: BitVec::from_bytes(&bytes[5..]),
})
}
}