added tests for cmpctblock
This commit is contained in:
parent
c460a43d84
commit
bf7368e719
|
@ -19,6 +19,7 @@ pub fn build_compact_block(block: IndexedBlock, prefilled_transactions_indexes:
|
||||||
let mut prefilled_transactions: Vec<PrefilledTransaction> = Vec::with_capacity(prefilled_transactions_len);
|
let mut prefilled_transactions: Vec<PrefilledTransaction> = Vec::with_capacity(prefilled_transactions_len);
|
||||||
let mut prefilled_transactions_size: usize = 0;
|
let mut prefilled_transactions_size: usize = 0;
|
||||||
|
|
||||||
|
let (key0, key1) = short_transaction_id_keys(nonce, block.header());
|
||||||
for (transaction_index, (transaction_hash, transaction)) in block.transactions().enumerate() {
|
for (transaction_index, (transaction_hash, transaction)) in block.transactions().enumerate() {
|
||||||
let transaction_size = transaction.serialized_size();
|
let transaction_size = transaction.serialized_size();
|
||||||
if prefilled_transactions_size + transaction_size < MAX_COMPACT_BLOCK_PREFILLED_SIZE
|
if prefilled_transactions_size + transaction_size < MAX_COMPACT_BLOCK_PREFILLED_SIZE
|
||||||
|
@ -29,7 +30,7 @@ pub fn build_compact_block(block: IndexedBlock, prefilled_transactions_indexes:
|
||||||
transaction: transaction.clone(),
|
transaction: transaction.clone(),
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
short_ids.push(short_transaction_id(nonce, block.header(), transaction_hash));
|
short_ids.push(short_transaction_id(key0, key1, transaction_hash));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +42,7 @@ pub fn build_compact_block(block: IndexedBlock, prefilled_transactions_indexes:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn short_transaction_id(nonce: u64, block_header: &BlockHeader, transaction_hash: &H256) -> ShortTransactionID {
|
pub fn short_transaction_id_keys(nonce: u64, block_header: &BlockHeader) -> (u64, u64) {
|
||||||
// Short transaction IDs are used to represent a transaction without sending a full 256-bit hash. They are calculated by:
|
// Short transaction IDs are used to represent a transaction without sending a full 256-bit hash. They are calculated by:
|
||||||
// 1) single-SHA256 hashing the block header with the nonce appended (in little-endian)
|
// 1) single-SHA256 hashing the block header with the nonce appended (in little-endian)
|
||||||
let mut stream = Stream::new();
|
let mut stream = Stream::new();
|
||||||
|
@ -53,24 +54,68 @@ fn short_transaction_id(nonce: u64, block_header: &BlockHeader, transaction_hash
|
||||||
// 64-bit integers from the above hash, respectively.
|
// 64-bit integers from the above hash, respectively.
|
||||||
let key0 = LittleEndian::read_u64(&block_header_with_nonce_hash[0..8]);
|
let key0 = LittleEndian::read_u64(&block_header_with_nonce_hash[0..8]);
|
||||||
let key1 = LittleEndian::read_u64(&block_header_with_nonce_hash[8..16]);
|
let key1 = LittleEndian::read_u64(&block_header_with_nonce_hash[8..16]);
|
||||||
|
|
||||||
|
(key0, key1)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn short_transaction_id(key0: u64, key1: u64, transaction_hash: &H256) -> ShortTransactionID {
|
||||||
|
// 2) Running SipHash-2-4 with the input being the transaction ID and the keys (k0/k1) set to the first two little-endian
|
||||||
|
// 64-bit integers from the above hash, respectively.
|
||||||
let siphash_transaction_hash = siphash24(key0, key1, &**transaction_hash);
|
let siphash_transaction_hash = siphash24(key0, key1, &**transaction_hash);
|
||||||
|
|
||||||
// 3) Dropping the 2 most significant bytes from the SipHash output to make it 6 bytes.
|
// 3) Dropping the 2 most significant bytes from the SipHash output to make it 6 bytes.
|
||||||
let mut siphash_transaction_hash_bytes = [0u8; 8];
|
let mut siphash_transaction_hash_bytes = [0u8; 8];
|
||||||
LittleEndian::write_u64(&mut siphash_transaction_hash_bytes, siphash_transaction_hash);
|
LittleEndian::write_u64(&mut siphash_transaction_hash_bytes, siphash_transaction_hash);
|
||||||
|
|
||||||
siphash_transaction_hash_bytes[2..8].into()
|
siphash_transaction_hash_bytes[0..6].into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use chain::{BlockHeader, Transaction, ShortTransactionID};
|
||||||
|
use message::common::{BlockHeaderAndIDs, PrefilledTransaction};
|
||||||
|
use test_data;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn short_transaction_id_is_correct() {
|
fn short_transaction_id_is_correct() {
|
||||||
// TODO
|
// https://webbtc.com/tx/fa755807ab9f3ca8a9b25982570700f3f94bb0627f373893c3cfe79b5cf16def
|
||||||
|
let transaction: Transaction = "01000000015fe01688dd8ae4428e21835c0e1b7af571c4223658d94da0c123e6fd7399862a010000006b483045022100f9e6d1bd3c9f54dcc72405994ec9ac2795878dd0b3cfbdc52bed28c2737fbecc02201fd68deab17bfaef1626e232cc4488dc273ba6fa5d807712b111d017cb96e0990121021fff64d1a21ede90d77cafa35fe7621db8aa433d947267980b395c35d23bd87fffffffff021ea56f72000000001976a9146fae1c8e7a648fff905dfdac9b019d3e887d7e8f88ac80f0fa02000000001976a9147f29b567c7dd9fc59cd3a7f716914966cc91ffa188ac00000000".into();
|
||||||
|
let transaction_hash = transaction.hash();
|
||||||
|
// https://webbtc.com/block/000000000000000001582cb2307ac43f3b4b268f2a75d3581d0babd48df1c300
|
||||||
|
let block_header: BlockHeader = "000000205a54771c6a1a2bcc8f3412184f319dc02f7258b56fd5060100000000000000001de7a03cefe565d11cdfa369f6ffe59b9368a257203726c9cc363d31b4e3c2ebca4f3c58d4e6031830ccfd80".into();
|
||||||
|
let nonce = 13450019974716797918_u64;
|
||||||
|
let (key0, key1) = short_transaction_id_keys(nonce, &block_header);
|
||||||
|
let actual_id = short_transaction_id(key0, key1, &transaction_hash);
|
||||||
|
let expected_id: ShortTransactionID = "036e8b8b8f00".into();
|
||||||
|
assert_eq!(expected_id, actual_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compact_block_is_built_correctly() {
|
fn compact_block_is_built_correctly() {
|
||||||
// TODO
|
let block = test_data::block_builder().header().parent(test_data::genesis().hash()).build()
|
||||||
|
.transaction().output().value(10).build().build()
|
||||||
|
.transaction().output().value(20).build().build()
|
||||||
|
.transaction().output().value(30).build().build()
|
||||||
|
.build(); // genesis -> block
|
||||||
|
let prefilled: HashSet<_> = vec![1].into_iter().collect();
|
||||||
|
let compact_block = build_compact_block(block.clone().into(), prefilled);
|
||||||
|
let (key0, key1) = short_transaction_id_keys(compact_block.nonce, &block.block_header);
|
||||||
|
let short_ids = vec![
|
||||||
|
short_transaction_id(key0, key1, &block.transactions[0].hash()),
|
||||||
|
short_transaction_id(key0, key1, &block.transactions[2].hash()),
|
||||||
|
];
|
||||||
|
assert_eq!(compact_block, BlockHeaderAndIDs {
|
||||||
|
header: block.block_header.clone(),
|
||||||
|
nonce: compact_block.nonce,
|
||||||
|
short_ids: short_ids,
|
||||||
|
prefilled_transactions: vec![
|
||||||
|
PrefilledTransaction {
|
||||||
|
index: 1,
|
||||||
|
transaction: block.transactions[1].clone(),
|
||||||
|
}
|
||||||
|
],
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue