Serializable trair extended with serialized_size function

This commit is contained in:
debris 2016-10-17 11:17:00 +02:00
parent 9596e64b99
commit d87626884d
6 changed files with 115 additions and 11 deletions

View File

@ -6,7 +6,7 @@ use hex::FromHex;
use bytes::Bytes; use bytes::Bytes;
use ser::{ use ser::{
Deserializable, Reader, Error as ReaderError, deserialize, Deserializable, Reader, Error as ReaderError, deserialize,
Serializable, Stream, serialize Serializable, Stream, serialize, serialized_list_size
}; };
use crypto::dhash256; use crypto::dhash256;
use hash::H256; use hash::H256;
@ -42,6 +42,11 @@ impl Serializable for OutPoint {
.append(&self.hash) .append(&self.hash)
.append(&self.index); .append(&self.index);
} }
#[inline]
fn serialized_size(&self) -> usize {
self.hash.serialized_size() + self.index.serialized_size()
}
} }
impl Deserializable for OutPoint { impl Deserializable for OutPoint {
@ -79,6 +84,13 @@ impl Serializable for TransactionInput {
.append(&self.script_sig) .append(&self.script_sig)
.append(&self.sequence); .append(&self.sequence);
} }
#[inline]
fn serialized_size(&self) -> usize {
self.previous_output.serialized_size() +
self.script_sig.serialized_size() +
self.sequence.serialized_size()
}
} }
impl Deserializable for TransactionInput { impl Deserializable for TransactionInput {
@ -119,6 +131,12 @@ impl Serializable for TransactionOutput {
.append(&self.value) .append(&self.value)
.append(&self.script_pubkey); .append(&self.script_pubkey);
} }
#[inline]
fn serialized_size(&self) -> usize {
self.value.serialized_size() +
self.script_pubkey.serialized_size()
}
} }
impl Deserializable for TransactionOutput { impl Deserializable for TransactionOutput {
@ -167,6 +185,14 @@ impl Serializable for Transaction {
.append_list(&self.outputs) .append_list(&self.outputs)
.append(&self.lock_time); .append(&self.lock_time);
} }
#[inline]
fn serialized_size(&self) -> usize {
self.version.serialized_size() +
serialized_list_size(&self.inputs) +
serialized_list_size(&self.outputs) +
self.lock_time.serialized_size()
}
} }
impl Deserializable for Transaction { impl Deserializable for Transaction {
@ -205,6 +231,7 @@ impl Transaction {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use hash::H256; use hash::H256;
use ser::Serializable;
use super::Transaction; use super::Transaction;
// real transaction from block 80000 // real transaction from block 80000
@ -231,4 +258,11 @@ mod tests {
let hash = H256::from_reversed_str("5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2"); let hash = H256::from_reversed_str("5a4ebf66822b0b2d56bd9dc64ece0bc38ee7844a23ff1d7320a88c5fdb2ad3e2");
assert_eq!(t.hash(), hash); assert_eq!(t.hash(), hash);
} }
#[test]
fn test_transaction_serialized_len() {
let raw_tx: &'static str = "0100000001a6b97044d03da79c005b20ea9c0e1a6d9dc12d9f7b91a5911c9030a439eed8f5000000004948304502206e21798a42fae0e854281abd38bacd1aeed3ee3738d9e1446618c4571d1090db022100e2ac980643b0b82c0e88ffdfec6b64e3e6ba35e7ba5fdd7d5d6cc8d25c6b241501ffffffff0100f2052a010000001976a914404371705fa9bd789a2fcd52d2c580b65d35549d88ac00000000";
let tx: Transaction = raw_tx.into();
assert_eq!(tx.serialized_size(), raw_tx.len() / 2);
}
} }

View File

@ -5,12 +5,12 @@
//! transactions. //! transactions.
//! It also guarantees that ancestor-descendant relation won't break during ordered removal (ancestors always removed //! It also guarantees that ancestor-descendant relation won't break during ordered removal (ancestors always removed
//! before descendants). Removal using remove_by_hash can break this rule. //! before descendants). Removal using remove_by_hash can break this rule.
use std::rc::Rc; use std::rc::Rc;
use hash::H256; use hash::H256;
use chain::Transaction; use chain::Transaction;
use std::collections::HashMap; use std::collections::HashMap;
use std::collections::HashSet; use std::collections::HashSet;
use ser::stream::serialize; use ser::Serializable;
/// Transactions ordering strategy /// Transactions ordering strategy
#[derive(Debug)] #[derive(Debug)]
@ -26,7 +26,7 @@ pub enum OrderingStrategy {
pub struct Information { pub struct Information {
/// The number of transactions currently in the `MemoryPool` /// The number of transactions currently in the `MemoryPool`
pub transactions_count: usize, pub transactions_count: usize,
/// The total number of bytes in the transactions in the `MemoryPool` /// The total number of bytes in the transactions in the `MemoryPool`
pub transactions_size_in_bytes: usize, pub transactions_size_in_bytes: usize,
} }
@ -52,7 +52,7 @@ pub struct Entry {
timestamp: u64, timestamp: u64,
/// Transaction fee (stored for efficiency) /// Transaction fee (stored for efficiency)
miner_fee: i64, miner_fee: i64,
/// Virtual transaction fee (a way to prioritize/penalize transaction) /// Virtual transaction fee (a way to prioritize/penalize transaction)
miner_virtual_fee: i64, miner_virtual_fee: i64,
} }
@ -108,7 +108,7 @@ macro_rules! ordering_strategy {
fn partial_cmp(&self, other: &OrderedEntry) -> Option<Ordering> { fn partial_cmp(&self, other: &OrderedEntry) -> Option<Ordering> {
Some(self.cmp(other)) Some(self.cmp(other))
} }
} }
impl Ord for OrderedEntry { impl Ord for OrderedEntry {
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
@ -414,8 +414,7 @@ impl MemoryPool {
} }
fn get_transaction_size(&self, t: &Transaction) -> usize { fn get_transaction_size(&self, t: &Transaction) -> usize {
// TODO: the only correct way now? t.serialized_size()
serialize(t).len()
} }
fn get_transaction_miner_fee(&self, t: &Transaction) -> i64 { fn get_transaction_miner_fee(&self, t: &Transaction) -> i64 {
@ -487,7 +486,7 @@ mod tests {
assert_eq!(pool_transactions.len(), 4); assert_eq!(pool_transactions.len(), 4);
// check pool transactions // check pool transactions
let ref hash_to_remove = pool_transactions[0]; let ref hash_to_remove = pool_transactions[0];
assert!(*hash_to_remove == RAW_TRANSACTION1_HASH.into() assert!(*hash_to_remove == RAW_TRANSACTION1_HASH.into()
|| *hash_to_remove == RAW_TRANSACTION2_HASH.into() || *hash_to_remove == RAW_TRANSACTION2_HASH.into()
|| *hash_to_remove == RAW_TRANSACTION3_HASH.into() || *hash_to_remove == RAW_TRANSACTION3_HASH.into()
@ -593,7 +592,7 @@ mod tests {
if expected_pool_size != 0 { if expected_pool_size != 0 {
pool.remove_by_hash(&removals[i].into()); pool.remove_by_hash(&removals[i].into());
} }
} }
} }

View File

@ -82,6 +82,15 @@ impl Serializable for CompactInteger {
} }
} }
} }
fn serialized_size(&self) -> usize {
match self.0 {
0...0xfc => 1,
0xfd...0xffff => 3,
0x10000...0xffff_ffff => 5,
_ => 9,
}
}
} }
impl Deserializable for CompactInteger { impl Deserializable for CompactInteger {

View File

@ -9,6 +9,11 @@ impl Serializable for bool {
fn serialize(&self, s: &mut Stream) { fn serialize(&self, s: &mut Stream) {
s.write_u8(*self as u8).unwrap(); s.write_u8(*self as u8).unwrap();
} }
#[inline]
fn serialized_size(&self) -> usize {
1
}
} }
impl Serializable for i32 { impl Serializable for i32 {
@ -16,6 +21,11 @@ impl Serializable for i32 {
fn serialize(&self, s: &mut Stream) { fn serialize(&self, s: &mut Stream) {
s.write_i32::<LittleEndian>(*self).unwrap(); s.write_i32::<LittleEndian>(*self).unwrap();
} }
#[inline]
fn serialized_size(&self) -> usize {
4
}
} }
impl Serializable for i64 { impl Serializable for i64 {
@ -23,6 +33,11 @@ impl Serializable for i64 {
fn serialize(&self, s: &mut Stream) { fn serialize(&self, s: &mut Stream) {
s.write_i64::<LittleEndian>(*self).unwrap(); s.write_i64::<LittleEndian>(*self).unwrap();
} }
#[inline]
fn serialized_size(&self) -> usize {
8
}
} }
impl Serializable for u8 { impl Serializable for u8 {
@ -30,6 +45,11 @@ impl Serializable for u8 {
fn serialize(&self, s: &mut Stream) { fn serialize(&self, s: &mut Stream) {
s.write_u8(*self).unwrap(); s.write_u8(*self).unwrap();
} }
#[inline]
fn serialized_size(&self) -> usize {
1
}
} }
impl Serializable for u16 { impl Serializable for u16 {
@ -37,6 +57,11 @@ impl Serializable for u16 {
fn serialize(&self, s: &mut Stream) { fn serialize(&self, s: &mut Stream) {
s.write_u16::<LittleEndian>(*self).unwrap(); s.write_u16::<LittleEndian>(*self).unwrap();
} }
#[inline]
fn serialized_size(&self) -> usize {
2
}
} }
impl Serializable for u32 { impl Serializable for u32 {
@ -44,6 +69,11 @@ impl Serializable for u32 {
fn serialize(&self, s: &mut Stream) { fn serialize(&self, s: &mut Stream) {
s.write_u32::<LittleEndian>(*self).unwrap(); s.write_u32::<LittleEndian>(*self).unwrap();
} }
#[inline]
fn serialized_size(&self) -> usize {
4
}
} }
impl Serializable for u64 { impl Serializable for u64 {
@ -51,6 +81,11 @@ impl Serializable for u64 {
fn serialize(&self, s: &mut Stream) { fn serialize(&self, s: &mut Stream) {
s.write_u64::<LittleEndian>(*self).unwrap(); s.write_u64::<LittleEndian>(*self).unwrap();
} }
#[inline]
fn serialized_size(&self) -> usize {
8
}
} }
impl Deserializable for bool { impl Deserializable for bool {
@ -114,6 +149,12 @@ impl Serializable for String {
.append(&CompactInteger::from(bytes.len())) .append(&CompactInteger::from(bytes.len()))
.append_slice(bytes); .append_slice(bytes);
} }
#[inline]
fn serialized_size(&self) -> usize {
let bytes: &[u8] = self.as_ref();
CompactInteger::from(bytes.len()).serialized_size() + bytes.len()
}
} }
impl Deserializable for String { impl Deserializable for String {
@ -129,6 +170,11 @@ macro_rules! impl_ser_for_hash {
fn serialize(&self, stream: &mut Stream) { fn serialize(&self, stream: &mut Stream) {
stream.append_slice(&**self); stream.append_slice(&**self);
} }
#[inline]
fn serialized_size(&self) -> usize {
$size
}
} }
impl Deserializable for $name { impl Deserializable for $name {
@ -157,6 +203,11 @@ impl Serializable for Bytes {
.append(&CompactInteger::from(self.len())) .append(&CompactInteger::from(self.len()))
.append_slice(&self); .append_slice(&self);
} }
#[inline]
fn serialized_size(&self) -> usize {
CompactInteger::from(self.len()).serialized_size() + self.len()
}
} }
impl Deserializable for Bytes { impl Deserializable for Bytes {

View File

@ -10,4 +10,4 @@ pub use primitives::{hash, bytes};
pub use compact_integer::CompactInteger; pub use compact_integer::CompactInteger;
pub use self::reader::{Reader, Deserializable, deserialize, Error}; pub use self::reader::{Reader, Deserializable, deserialize, Error};
pub use self::stream::{Stream, Serializable, serialize}; pub use self::stream::{Stream, Serializable, serialize, serialized_list_size};

View File

@ -9,9 +9,20 @@ pub fn serialize(t: &Serializable) -> Bytes {
stream.out() stream.out()
} }
pub fn serialized_list_size<T>(t: &[T]) -> usize where T: Serializable {
CompactInteger::from(t.len()).serialized_size() +
t.iter().map(Serializable::serialized_size).sum::<usize>()
}
pub trait Serializable { pub trait Serializable {
/// Serialize the struct and appends it to the end of stream. /// Serialize the struct and appends it to the end of stream.
fn serialize(&self, s: &mut Stream); fn serialize(&self, s: &mut Stream);
/// Hint about the size of serialized struct.
fn serialized_size(&self) -> usize where Self: Sized {
// fallback implementation
serialize(self).len()
}
} }
/// Stream used for serialization. /// Stream used for serialization.