Rename Hash->Uint functions to denote endianness

This commit is contained in:
Andrew Poelstra 2014-08-24 12:28:02 -07:00
parent 3a921e6b9c
commit 688a77ef38
6 changed files with 53 additions and 35 deletions

View File

@ -101,7 +101,7 @@ impl BlockHeader {
if target != required_target {
return Err(SpvBadTarget);
}
let ref hash = self.bitcoin_hash().into_uint256();
let ref hash = self.bitcoin_hash().into_le();
if hash <= target { Ok(()) } else { Err(SpvBadProofOfWork) }
}

View File

@ -141,20 +141,20 @@ impl<D:SimpleDecoder<E>, E> ConsensusDecodable<D, E> for Blockchain {
let genesis_hash: Sha256dHash = try!(ConsensusDecodable::consensus_decode(d));
// Lookup best tip
let best = match tree.lookup(&best_hash.into_uint256(), 256) {
let best = match tree.lookup(&best_hash.into_le(), 256) {
Some(node) => &**node as NodePtr,
None => {
return Err(d.error(format!("best tip {:x} not in tree", best_hash).as_slice()));
}
};
// Lookup genesis
if tree.lookup(&genesis_hash.into_uint256(), 256).is_none() {
if tree.lookup(&genesis_hash.into_le(), 256).is_none() {
return Err(d.error(format!("genesis {:x} not in tree", genesis_hash).as_slice()));
}
// Reconnect all prev pointers
let raw_tree = &tree as *const _;
for node in tree.mut_iter() {
let hash = node.block.header.prev_blockhash.into_uint256();
let hash = node.block.header.prev_blockhash.into_le();
let prevptr =
match unsafe { (*raw_tree).lookup(&hash, 256) } {
Some(node) => &**node as NodePtr,
@ -355,7 +355,7 @@ impl Blockchain {
network: network,
tree: {
let mut pat = PatriciaTree::new();
pat.insert(&genhash.into_uint256(), 256, new_node);
pat.insert(&genhash.into_le(), 256, new_node);
pat
},
best_hash: genhash,
@ -400,17 +400,17 @@ impl Blockchain {
/// Looks up a block in the chain and returns the BlockchainNode containing it
pub fn get_block<'a>(&'a self, hash: Sha256dHash) -> Option<&'a BlockchainNode> {
self.tree.lookup(&hash.into_uint256(), 256).map(|node| &**node)
self.tree.lookup(&hash.into_le(), 256).map(|node| &**node)
}
/// Locates a block in the chain and overwrites its txdata
pub fn add_txdata(&mut self, block: Block) -> BitcoinResult<()> {
self.replace_txdata(&block.header.bitcoin_hash().into_uint256(), block.txdata, true)
self.replace_txdata(&block.header.bitcoin_hash().into_le(), block.txdata, true)
}
/// Locates a block in the chain and removes its txdata
pub fn remove_txdata(&mut self, hash: Sha256dHash) -> BitcoinResult<()> {
self.replace_txdata(&hash.into_uint256(), vec![], false)
self.replace_txdata(&hash.into_le(), vec![], false)
}
/// Adds a block header to the chain
@ -430,13 +430,13 @@ impl Blockchain {
if hash == chain.best_hash {
Some(chain.best_tip)
} else {
chain.tree.lookup(&hash.into_uint256(), 256).map(|boxptr| &**boxptr as NodePtr)
chain.tree.lookup(&hash.into_le(), 256).map(|boxptr| &**boxptr as NodePtr)
}
}
// Check for multiple inserts (bitcoind from c9a09183 to 3c85d2ec doesn't
// handle locator hashes properly and may return blocks multiple times,
// and this may also happen in case of a reorg.
if self.tree.lookup(&block.header.bitcoin_hash().into_uint256(), 256).is_some() {
if self.tree.lookup(&block.header.bitcoin_hash().into_le(), 256).is_some() {
return Err(DuplicateHash);
}
// Construct node, if possible
@ -515,7 +515,7 @@ impl Blockchain {
// Insert the new block
let raw_ptr = &*new_block as NodePtr;
self.tree.insert(&new_block.block.header.bitcoin_hash().into_uint256(), 256, new_block);
self.tree.insert(&new_block.block.header.bitcoin_hash().into_le(), 256, new_block);
// Replace the best tip if necessary
if unsafe { (*raw_ptr).total_work > (*self.best_tip).total_work } {
self.set_best_tip(raw_ptr);
@ -565,7 +565,7 @@ impl Blockchain {
/// An iterator over all blocks in the chain starting from `start_hash`
pub fn iter<'a>(&'a self, start_hash: Sha256dHash) -> BlockIter<'a> {
let start = match self.tree.lookup(&start_hash.into_uint256(), 256) {
let start = match self.tree.lookup(&start_hash.into_le(), 256) {
Some(boxptr) => &**boxptr as NodePtr,
None => RawPtr::null()
};
@ -577,7 +577,7 @@ impl Blockchain {
/// An iterator over all blocks in reverse order to the genesis, starting with `start_hash`
pub fn rev_iter<'a>(&'a self, start_hash: Sha256dHash) -> RevBlockIter<'a> {
let start = match self.tree.lookup(&start_hash.into_uint256(), 256) {
let start = match self.tree.lookup(&start_hash.into_le(), 256) {
Some(boxptr) => &**boxptr as NodePtr,
None => RawPtr::null()
};
@ -589,7 +589,7 @@ impl Blockchain {
/// An iterator over all blocks -not- in the best chain, in reverse order, starting from `start_hash`
pub fn rev_stale_iter<'a>(&'a self, start_hash: Sha256dHash) -> RevStaleBlockIter<'a> {
let start = match self.tree.lookup(&start_hash.into_uint256(), 256) {
let start = match self.tree.lookup(&start_hash.into_le(), 256) {
Some(boxptr) => {
// If we are already on the main chain, we have a dead iterator
if boxptr.is_on_main_chain(self) {

View File

@ -112,7 +112,7 @@ impl UtxoSet {
};
// Get the old value, if any (this is suprisingly possible, c.f. BIP30
// and the other comments in this file referring to it)
let ret = self.table.swap(txid.into_uint128(), new_node);
let ret = self.table.swap(txid.into_le().low_128(), new_node);
if ret.is_none() {
self.n_utxos += tx.output.len() as u64;
}
@ -124,7 +124,7 @@ impl UtxoSet {
// This whole function has awkward scoping thx to lexical borrow scoping :(
let (ret, should_delete) = {
// Locate the UTXO, failing if not found
let node = match self.table.find_mut(&txid.into_uint128()) {
let node = match self.table.find_mut(&txid.into_le().low_128()) {
Some(node) => node,
None => return None
};
@ -142,7 +142,7 @@ impl UtxoSet {
// Delete the whole node if it is no longer being used
if should_delete {
self.table.remove(&txid.into_uint128());
self.table.remove(&txid.into_le().low_128());
}
self.n_utxos -= if ret.is_some() { 1 } else { 0 };
@ -152,7 +152,7 @@ impl UtxoSet {
/// Get a reference to a UTXO in the set
pub fn get_utxo<'a>(&'a self, txid: Sha256dHash, vout: u32) -> Option<&'a TxOut> {
// Locate the UTXO, failing if not found
let node = match self.table.find(&txid.into_uint128()) {
let node = match self.table.find(&txid.into_le().low_128()) {
Some(node) => node,
None => return None
};
@ -317,7 +317,7 @@ impl UtxoSet {
for ((txid, n), txo) in extract_vec.move_iter() {
// Remove the tx's utxo list and patch the txo into place
let new_node =
match self.table.pop(&txid.into_uint128()) {
match self.table.pop(&txid.into_le().low_128()) {
Some(mut thinvec) => {
let old_len = thinvec.len() as u32;
if old_len < n + 1 {
@ -343,7 +343,7 @@ impl UtxoSet {
}
};
// Ram it back into the tree
self.table.insert(txid.into_uint128(), new_node);
self.table.insert(txid.into_le().low_128(), new_node);
}
}
skipped_genesis = true;

View File

@ -145,20 +145,21 @@ impl Sha256dHash {
/// Converts a hash to a little-endian Uint256
#[inline]
pub fn into_uint256(self) -> Uint256 {
pub fn into_le(self) -> Uint256 {
let Sha256dHash(data) = self;
unsafe { Uint256(transmute(data)) }
let mut ret: [u64, ..4] = unsafe { transmute(data) };
for x in ret.as_mut_slice().mut_iter() { *x = x.to_le(); }
Uint256(ret)
}
/// Converts a hash to a little-endian Uint128, using only the "low" bytes
/// Converts a hash to a big-endian Uint256
#[inline]
pub fn into_uint128(self) -> Uint128 {
let Sha256dHash(data) = self;
// TODO: this function won't work correctly on big-endian machines
unsafe { Uint128(transmute([data[16], data[17], data[18], data[19], data[20],
data[21], data[22], data[23], data[24], data[25],
data[26], data[27], data[28], data[29], data[30],
data[31]])) }
pub fn into_be(self) -> Uint256 {
let Sha256dHash(mut data) = self;
data.reverse();
let mut ret: [u64, ..4] = unsafe { transmute(data) };
for x in ret.mut_iter() { *x = x.to_be(); }
Uint256(ret)
}
/// Converts a hash to a Hash32 by truncation
@ -384,5 +385,15 @@ mod tests {
"\"56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d\"".as_bytes());
assert_eq!(json::decode(from_utf8(res.as_slice()).unwrap()), Ok(hash));
}
#[test]
fn test_sighash_single_vec() {
let one = Sha256dHash([1, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0]);
assert_eq!(Some(one.into_le()), FromPrimitive::from_u64(1));
assert_eq!(Some(one.into_le().low_128()), FromPrimitive::from_u64(1));
}
}

View File

@ -553,7 +553,7 @@ mod tests {
let mut tree = PatriciaTree::new();
let mut hashes = vec![];
for i in range(0u32, 5000) {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_uint128();
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 250, i);
hashes.push(hash);
}
@ -594,7 +594,7 @@ mod tests {
let mut hashes = vec![];
// Start by inserting a bunch of chunder
for i in range(1u32, 500) {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_uint128();
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 128, i * 1000);
hashes.push(hash);
}
@ -626,7 +626,7 @@ mod tests {
let mut data = Vec::from_elem(n_elems, None);
// Start by inserting a bunch of stuff
for i in range(0, n_elems) {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_uint128();
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 128, i);
*data.get_mut(i) = Some(());
}
@ -648,7 +648,7 @@ mod tests {
let mut data = Vec::from_elem(n_elems, None);
// Start by inserting a bunch of stuff
for i in range(0, n_elems) {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_uint128();
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 128, i);
*data.get_mut(i) = Some(());
}
@ -674,7 +674,7 @@ mod tests {
let mut tree = PatriciaTree::new();
let mut hashes = vec![];
for i in range(0u32, 5000) {
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_uint128();
let hash = Sha256dHash::from_data(&[(i / 0x100) as u8, (i % 0x100) as u8]).into_le().low_128();
tree.insert(&hash, 250, i);
hashes.push(hash);
}

View File

@ -367,6 +367,13 @@ impl Uint256 {
}
}
}
/// Decay to a uint128
#[inline]
pub fn low_128(&self) -> Uint128 {
let &Uint256(data) = self;
Uint128([data[0], data[1]])
}
}
#[cfg(test)]