Merge pull request #436 from LNP-BP/feat-u256u8

Big integers (Uint*) from byte slice array with `from_be_bytes`
This commit is contained in:
Andrew Poelstra 2020-09-09 16:42:32 +00:00 committed by GitHub
commit c8633b5bce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 1 deletions

View File

@ -1,5 +1,6 @@
extern crate bitcoin; extern crate bitcoin;
use std::str::FromStr; use std::str::FromStr;
use std::convert::Into;
fn do_test(data: &[u8]) { fn do_test(data: &[u8]) {
macro_rules! read_ints { macro_rules! read_ints {
@ -11,6 +12,12 @@ fn do_test(data: &[u8]) {
} }
// Note BE: // Note BE:
let uint128 = bitcoin::util::uint::Uint128::from(&[native as u64, (native >> 8*8) as u64][..]); let uint128 = bitcoin::util::uint::Uint128::from(&[native as u64, (native >> 8*8) as u64][..]);
// Checking two conversion methods against each other
let mut slice = [0u8; 16];
slice.copy_from_slice(&data[$start..$start + 16]);
assert_eq!(uint128, bitcoin::util::uint::Uint128::from_be_bytes(slice));
(native, uint128) (native, uint128)
} } } }
} }

View File

@ -52,6 +52,7 @@ macro_rules! define_le_to_array {
} }
define_slice_to_be!(slice_to_u32_be, u32); define_slice_to_be!(slice_to_u32_be, u32);
define_slice_to_be!(slice_to_u64_be, u64);
define_be_to_array!(u32_to_array_be, u32, 4); define_be_to_array!(u32_to_array_be, u32, 4);
define_slice_to_le!(slice_to_u16_le, u16); define_slice_to_le!(slice_to_u16_le, u16);
define_slice_to_le!(slice_to_u32_le, u32); define_slice_to_le!(slice_to_u32_le, u32);
@ -105,6 +106,7 @@ mod tests {
#[test] #[test]
fn endianness_test() { fn endianness_test() {
assert_eq!(slice_to_u32_be(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef); assert_eq!(slice_to_u32_be(&[0xde, 0xad, 0xbe, 0xef]), 0xdeadbeef);
assert_eq!(slice_to_u64_be(&[0xde, 0xad, 0xbe, 0xef, 0x1b, 0xad, 0xca, 0xfe]), 0xdeadbeef1badcafe);
assert_eq!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]); assert_eq!(u32_to_array_be(0xdeadbeef), [0xde, 0xad, 0xbe, 0xef]);
assert_eq!(slice_to_u16_le(&[0xad, 0xde]), 0xdead); assert_eq!(slice_to_u16_le(&[0xad, 0xde]), 0xdead);

View File

@ -73,6 +73,7 @@ macro_rules! construct_uint {
} }
/// Create an object from a given unsigned 64-bit integer /// Create an object from a given unsigned 64-bit integer
#[inline]
pub fn from_u64(init: u64) -> Option<$name> { pub fn from_u64(init: u64) -> Option<$name> {
let mut ret = [0; $n_words]; let mut ret = [0; $n_words];
ret[0] = init; ret[0] = init;
@ -80,11 +81,24 @@ macro_rules! construct_uint {
} }
/// Create an object from a given signed 64-bit integer /// Create an object from a given signed 64-bit integer
#[inline]
pub fn from_i64(init: i64) -> Option<$name> { pub fn from_i64(init: i64) -> Option<$name> {
assert!(init >= 0); assert!(init >= 0);
$name::from_u64(init as u64) $name::from_u64(init as u64)
} }
/// Creates big integer value from a byte slice array using
/// big-endian encoding
pub fn from_be_bytes(bytes: [u8; $n_words * 8]) -> $name {
use super::endian::slice_to_u64_be;
let mut slice = [0u64; $n_words];
slice.iter_mut()
.rev()
.zip(bytes.chunks(8))
.for_each(|(word, bytes)| *word = slice_to_u64_be(bytes));
$name(slice)
}
// divmod like operation, returns (quotient, remainder) // divmod like operation, returns (quotient, remainder)
#[inline] #[inline]
fn div_rem(self, other: Self) -> (Self, Self) { fn div_rem(self, other: Self) -> (Self, Self) {
@ -409,7 +423,7 @@ impl Uint256 {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use consensus::{deserialize, serialize}; use consensus::{deserialize, serialize};
use util::uint::Uint256; use util::uint::{Uint256, Uint128};
use util::BitArray; use util::BitArray;
#[test] #[test]
@ -467,6 +481,16 @@ mod tests {
assert!(small <= small); assert!(small <= small);
} }
#[test]
pub fn uint_from_be_bytes() {
assert_eq!(Uint128::from_be_bytes([0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed]),
Uint128([0xdeafbabe2bedfeed, 0x1badcafedeadbeef]));
assert_eq!(Uint256::from_be_bytes([0x1b, 0xad, 0xca, 0xfe, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xaf, 0xba, 0xbe, 0x2b, 0xed, 0xfe, 0xed,
0xba, 0xad, 0xf0, 0x0d, 0xde, 0xfa, 0xce, 0xda, 0x11, 0xfe, 0xd2, 0xba, 0xd1, 0xc0, 0xff, 0xe0]),
Uint256([0x11fed2bad1c0ffe0, 0xbaadf00ddefaceda, 0xdeafbabe2bedfeed, 0x1badcafedeadbeef]));
}
#[test] #[test]
pub fn uint256_arithmetic_test() { pub fn uint256_arithmetic_test() {
let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap(); let init = Uint256::from_u64(0xDEADBEEFDEADBEEF).unwrap();