u32 everywhere
This commit is contained in:
parent
1457d9d056
commit
93b765d8ea
|
@ -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"
|
||||
|
|
|
@ -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 = []
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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..]),
|
||||
})
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue