Compare commits

..

No commits in common. "master" and "0.15.0" have entirely different histories.

749 changed files with 3873 additions and 10936 deletions

View File

@ -1,46 +1,21 @@
language: rust
cache: cargo
rust:
- stable
- beta
- nightly
- 1.14.0
addons:
apt:
update: true
packages:
- binutils-dev
- libunwind8-dev
- libcurl4-openssl-dev
- libelf-dev
- libdw-dev
- cmake
- gcc
- libiberty-dev
matrix:
include:
- rust: stable
env: DO_FUZZ=true DO_COV=true AS_DEPENDENCY=true
- rust: beta
env: AS_DEPENDENCY=true
- rust: nightly
env: DO_BENCH=true AS_DEPENDENCY=true
- rust: 1.22.0
env: AS_DEPENDENCY=true
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y binutils-dev libunwind8-dev
script:
- ./contrib/test.sh
after_success: |
if [ "$DO_COV" = true ]; then
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz &&
tar xzf master.tar.gz &&
cd kcov-master &&
mkdir build &&
cd build &&
cmake .. &&
make &&
make install DESTDIR=../../kcov-build &&
cd ../.. &&
rm -rf kcov-master &&
for file in target/debug/bitcoin-*; do [ -x "${file}" ] || continue; mkdir -p "target/cov/$(basename $file)"; ./kcov-build/usr/local/bin/kcov --exclude-pattern=/.cargo,/usr/lib --verify "target/cov/$(basename $file)" "$file"; done &&
bash <(curl -s https://codecov.io/bash) &&
echo "Uploaded code coverage"; fi
- cargo build --verbose
- cargo test --verbose
- cargo build --verbose --features=bitcoinconsensus
- cargo test --verbose --features=bitcoinconsensus
- cargo build --verbose --features=serde
- cargo test --verbose --features=serde
- cargo build --verbose --features=serde-decimal
- cargo test --verbose --features=serde-decimal
- if [ "$(rustup show | grep default | grep stable)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; fi

View File

@ -1,118 +1,4 @@
# 0.23.0 - 2020-01-07
- Update `secp256k1` dependency to `0.17.1`.
- Update `bitcoinconsensus` dependency to `0.19.0-1`.
- Update `bech32` dependency to `0.7.2`.
# 0.22.0 - 2020-01-07
- Add `ServiceFlags` type.
- Add `NetworkMessage::command`.
- Add `key::Error`.
- Add newtypes for specific hashes:
- `Txid`
- `Wtxid`
- `BlockHash`
- `SigHash`
- `PubkeyHash`
- `ScriptHash`
- `WPubkeyHash`
- `WScriptHash`
- `TxMerkleNode`
- `WitnessMerkleNode`
- `WitnessCommitment`
- `XpubIdentifier`
- `FilterHash`
- Refactor `CommandString`.
- Refactor `Reject` message.
- Rename `RejectReason` enum variants.
- Refactor `encode::Error`.
- Implement `Default` for `TxIn`.
- Implement `std::hash::Hash` for `Inventory`.
- Implement `Copy` for `InvType` enum.
- Use `psbt::Error` in `PartiallySignedTransaction::from_unsigned_tx`.
- Drop message decode max length to 4_000_000.
- Drop `hex` and `byteorder` dependencies.
# 0.21.0 - 2019-10-02
* Add [serde to `BlockHeader` and `Block`](https://github.com/rust-bitcoin/rust-bitcoin/pull/321)
* [Clean up `StreamReader` API](https://github.com/rust-bitcoin/rust-bitcoin/pull/318) (breaking change)
* Add [reject message](https://github.com/rust-bitcoin/rust-bitcoin/pull/323) to p2p messages
# 0.20.0 - 2019-08-23
* Update `secp256k1` 0.15 and `bitcoinconsensus` 0.17
# 0.19.0 - 2019-08-16
* Add `Amount` and `SignedAmount` types.
* Add BIP-158 support with `BlockFilter` and related types.
* Add `util::misc::signed_msg_hash()` for signing messages.
* Add `MerkleBlock` and `PartialMerkleTree` types.
* bip32: Support serde serializaton for types and add some utility methods:
* `ChildNumber::increment`
* `DerivationPath::children_from`
* `DerivationPath::normal_children`
* `DerivationPath::hardened_children`
* Add `blockdata::script::Builder::push_verify` to verify-ify an opcode.
* Add `sendheaders` network message.
* Add `OutPoint::new()` method and JSON-serialize as `<txid>:<vout>`.
* Refactor `Address` type:
* Now supports segwit addresses with version >0.
* Add `Address::from_script` constructor.
* Add `Address::address_type` inspector.
* Parsing now returns an `address::Error` instead of `encode::Error`.
* Removed `bitcoin_bech32` dependency for bech32 payloads.
* bip143: Rename `witness_script` to `script_code`
* Rename `BlockHeader::spv_validate` to `validate_pow`
* Rename `OP_NOP2` and `OP_NOP3` to `OP_CLTV` and `OP_CSV`
* psbt: Use `BTreeMap` instead of `HashMap` to ensure serialization roundtrips.
* Drop `Decimal` type.
* Drop `LoneHeaders` type.
* Replace `strason` dependency with (optional) `serde_json`.
* Export the `bitcoin_hashes` and `secp256k1` dependent crates.
* Updated `bitcoin_hashes` dependency to v0.7.
* Removed `rand` and `serde_test` dependencies.
* Internal improvements to consensus encoding logic.
# 0.18.0 - 2019-03-21
* Update `bitcoin-bech32` version to 0.9
* add `to_bytes` method for `util::key` types
* add serde impls for `util::key` types
* contracthash: minor cleanups, use `util::key` types instead of `secp256k1` types
# 0.17.1 - 2019-03-04
* Add some trait impls to `PublicKey` for miniscript interoperability
# 0.17.0 - 2019-02-28 - ``The PSBT Release''
* **Update minimum rustc version to 1.22**.
* [Replace `rust-crypto` with `bitcoin_hashes`; refactor hash types](https://github.com/rust-bitcoin/rust-bitcoin/pull/215)
* [Remove `Address::p2pk`](https://github.com/rust-bitcoin/rust-bitcoin/pull/222/)
* Remove misleading blanket `MerkleRoot` implementation; [it is now only defined for `Block`](https://github.com/rust-bitcoin/rust-bitcoin/pull/218)
* [Add BIP157](https://github.com/rust-bitcoin/rust-bitcoin/pull/215) (client-side block filtering messages)
* Allow network messages [to be deserialized even across multiple packets](https://github.com/rust-bitcoin/rust-bitcoin/pull/231)
* [Replace all key types](https://github.com/rust-bitcoin/rust-bitcoin/pull/183) to better match abstractions needed for PSBT
* [Clean up BIP32](https://github.com/rust-bitcoin/rust-bitcoin/pull/233) in preparation for PSBT; [use new native key types rather than `secp256k1` ones](https://github.com/rust-bitcoin/rust-bitcoin/pull/238/)
* Remove [apparently-used `Option` serialization](https://github.com/rust-bitcoin/rust-bitcoin/pull/236#event-2158116421) code
* Finally merge [PSBT](https://github.com/rust-bitcoin/rust-bitcoin/pull/103) after nearly nine months
# 0.16.0 - 2019-01-15
* Reorganize opcode types to eliminate unsafe code
* Un-expose some macros that were unintentionally exported
* Update rust-secp256k1 dependency to 0.12
* Remove `util::iter::Pair` type which does not belong in this library
* Minor bugfixes and optimizations
# 0.15.1 - 2018-11-08
* [Detect p2pk addresses with compressed keys](https://github.com/rust-bitcoin/rust-bitcoin/pull/189)
# 0.15.0 - 2018-11-03
* [Significant API overhaul](https://github.com/rust-bitcoin/rust-bitcoin/pull/156):

View File

@ -1,6 +1,7 @@
[package]
name = "bitcoin"
version = "0.23.0"
version = "0.15.0"
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>"]
license = "CC0-1.0"
homepage = "https://github.com/rust-bitcoin/rust-bitcoin/"
@ -15,24 +16,28 @@ name = "bitcoin"
path = "src/lib.rs"
[features]
fuzztarget = ["secp256k1/fuzztarget", "bitcoin_hashes/fuzztarget"]
unstable = []
rand = ["secp256k1/rand-std"]
use-serde = ["serde", "bitcoin_hashes/serde", "secp256k1/serde"]
fuzztarget = ["secp256k1/fuzztarget"]
serde-decimal = ["serde", "strason"]
[dependencies]
bech32 = "0.7.2"
bitcoin_hashes = "0.7.3"
secp256k1 = "0.17.1"
bitcoin-bech32 = "0.8.0"
byteorder = "1.1"
rand = "0.3"
rust-crypto = "0.2"
bitcoinconsensus = { version = "0.16", optional = true }
bitcoinconsensus = { version = "0.19.0-1", optional = true }
serde = { version = "1", optional = true }
[dependencies.serde]
version = "1"
optional = true
[dev-dependencies]
hex = "=0.3.2"
serde_derive = "<1.0.99"
serde_json = "<1.0.45"
serde_test = "1"
secp256k1 = { version = "0.17.1", features = ["rand-std"] }
# We need to pin ryu (transitive dep from serde_json) to stay compatible with Rust 1.22.0
ryu = "<1.0.5"
[dependencies.strason]
version = "0.4"
optional = true
default-features = false
[dependencies.hex]
version = "=0.3.2"
[dependencies.secp256k1]
version = "0.11"
features = [ "rand" ]

View File

@ -1,10 +1,10 @@
[![Status](https://travis-ci.org/rust-bitcoin/rust-bitcoin.png?branch=master)](https://travis-ci.org/rust-bitcoin/rust-bitcoin)
[![Safety Dance](https://img.shields.io/badge/unsafe-forbidden-success.svg)](https://github.com/rust-secure-code/safety-dance/)
# Rust Bitcoin Library
Library with support for de/serialization, parsing and executing on data
structures and network messages related to Bitcoin.
structures and network messages related to Bitcoin and other blockchain-based
currencies.
[Documentation](https://docs.rs/bitcoin/)
@ -14,11 +14,12 @@ Supports (or should support)
* De/serialization of blocks and transactions
* Script de/serialization
* Private keys and address creation, de/serialization and validation (including full BIP32 support)
* PSBT creation, manipulation, merging and finalization
* Pay-to-contract support as in Appendix A of the [Blockstream sidechains whitepaper](https://www.blockstream.com/sidechains.pdf)
For JSONRPC interaction with Bitcoin Core, it is recommended to use
[rust-bitcoincore-rpc](https://github.com/rust-bitcoin/rust-bitcoincore-rpc).
For JSONRPC interaction with Bitcoin Core, it is recommended to use [rust-jsonrpc](https://github.com/apoelstra/rust-jsonrpc)
which uses the underlying [strason library](https://github.com/apoelstra/strason)
which parses decimal numbers as strings, preventing precision errors.
# Known limitations
@ -38,54 +39,12 @@ fix specific consensus incompatibilities are welcome.
## Documentation
Currently can be found on [docs.rs/bitcoin](https://docs.rs/bitcoin/).
Patches to add usage examples and to expand on existing docs would be extremely
appreciated.
Currently the [documentation](https://www.wpsoftware.net/rustdoc/bitcoin/)
is very sparse. Patches to add usage examples and to expand on existing
docs would be extremely appreciated.
# Contributing
Contributions are generally welcome. If you intend to make larger changes please
discuss them in an issue before PRing them to avoid duplicate work and
architectural mismatches. If you have any questions or ideas you want to discuss
please join us in
[#rust-bitcoin](http://webchat.freenode.net/?channels=%23rust-bitcoin) on
freenode.
## Minimum Supported Rust Version (MSRV)
This library should always compile with any combination of features on **Rust 1.22**.
## Installing Rust
Rust can be installed using your package manager of choice or
[rustup.rs](https://rustup.rs). The former way is considered more secure since
it typically doesn't involve trust in the CA system. But you should be aware
that the version of Rust shipped by your distribution might be out of date.
Generally this isn't a problem for `rust-bitcoin` since we support much older
versions (>=1.22) than the current stable one.
## Building
The library can be built and tested using [`cargo`](https://github.com/rust-lang/cargo/):
```
git clone git@github.com:rust-bitcoin/rust-bitcoin.git
cd rust-bitcoin
cargo build
```
You can run tests with:
```
cargo test
```
Please refer to the [`cargo` documentation](https://doc.rust-lang.org/stable/cargo/) for more detailed instructions.
## Pull Requests
Every PR needs at least two reviews to get merged. During the review phase
maintainers and contributors are likely to leave comments and request changes.
Please try to address them, otherwise your PR might get closed without merging
after a longer time of inactivity. If your PR isn't ready for review yet please
mark it by prefixing the title with `WIP: `.
## Policy on Altcoins/Altchains
# Policy on Altcoins/Altchains
Patches which add support for non-Bitcoin cryptocurrencies by adding constants
to existing enums (e.g. to set the network message magic-byte sequence) are
@ -99,12 +58,7 @@ cross-chain atomic swaps) are more likely to be accepted than things which
support only a single blockchain.
# Release Notes
## Release Notes
See [CHANGELOG.md](CHANGELOG.md).
See CHANGELOG.md
# Licensing
The code in this project is licensed under the [Creative Commons CC0 1.0
Universal license](LICENSE).

View File

@ -1,49 +0,0 @@
#!/bin/sh -ex
FEATURES="bitcoinconsensus use-serde rand"
if [ "$DO_COV" = true ]
then
export RUSTFLAGS="-C link-dead-code"
fi
# Use toolchain if explicitly specified
if [ -n "$TOOLCHAIN" ]
then
alias cargo="cargo +$TOOLCHAIN"
fi
# Test without any features first
cargo test --verbose
# Test each feature
for feature in ${FEATURES}
do
cargo test --verbose --features="$feature"
done
# Fuzz if told to
if [ "$DO_FUZZ" = true ]
then
(
cd fuzz
cargo test --verbose
./travis-fuzz.sh
)
fi
# Bench if told to
if [ "$DO_BENCH" = true ]
then
cargo bench --features unstable
fi
# Use as dependency if told to
if [ -n "$AS_DEPENDENCY" ]
then
cargo new dep_test
cd dep_test
echo 'bitcoin = { path = "..", features = ["use-serde"] }' >> Cargo.toml
cargo test --verbose
fi

View File

@ -1,114 +0,0 @@
extern crate bitcoin;
use std::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, TcpStream};
use std::time::{SystemTime, UNIX_EPOCH};
use std::{env, process};
use std::io::Write;
use bitcoin::consensus::encode;
use bitcoin::network::{address, constants, message, message_network};
use bitcoin::network::stream_reader::StreamReader;
use bitcoin::secp256k1;
use bitcoin::secp256k1::rand::Rng;
fn main() {
// This example establishes a connection to a Bitcoin node, sends the intial
// "version" message, waits for the reply, and finally closes the connection.
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("not enough arguments");
process::exit(1);
}
let str_address = &args[1];
let address: SocketAddr = str_address.parse().unwrap_or_else(|error| {
eprintln!("Error parsing address: {:?}", error);
process::exit(1);
});
let version_message = build_version_message(address);
let first_message = message::RawNetworkMessage {
magic: constants::Network::Bitcoin.magic(),
payload: version_message,
};
if let Ok(mut stream) = TcpStream::connect(address) {
// Send the message
let _ = stream.write_all(encode::serialize(&first_message).as_slice());
println!("Sent version message");
// Setup StreamReader
let read_stream = stream.try_clone().unwrap();
let mut stream_reader = StreamReader::new(read_stream, None);
loop {
// Loop an retrieve new messages
let reply: message::RawNetworkMessage = stream_reader.read_next().unwrap();
match reply.payload {
message::NetworkMessage::Version(_) => {
println!("Received version message: {:?}", reply.payload);
let second_message = message::RawNetworkMessage {
magic: constants::Network::Bitcoin.magic(),
payload: message::NetworkMessage::Verack,
};
let _ = stream.write_all(encode::serialize(&second_message).as_slice());
println!("Sent verack message");
}
message::NetworkMessage::Verack => {
println!("Received verack message: {:?}", reply.payload);
break;
}
_ => {
println!("Received unknown message: {:?}", reply.payload);
break;
}
}
}
let _ = stream.shutdown(Shutdown::Both);
} else {
eprintln!("Failed to open connection");
}
}
fn build_version_message(address: SocketAddr) -> message::NetworkMessage {
// Building version message, see https://en.bitcoin.it/wiki/Protocol_documentation#version
let my_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), 0);
// "bitfield of features to be enabled for this connection"
let services = constants::ServiceFlags::NONE;
// "standard UNIX timestamp in seconds"
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time error")
.as_secs();
// "The network address of the node receiving this message"
let addr_recv = address::Address::new(&address, constants::ServiceFlags::NONE);
// "The network address of the node emitting this message"
let addr_from = address::Address::new(&my_address, constants::ServiceFlags::NONE);
// "Node random nonce, randomly generated every time a version packet is sent. This nonce is used to detect connections to self."
let nonce: u64 = secp256k1::rand::thread_rng().gen();
// "User Agent (0x00 if string is 0 bytes long)"
let user_agent = String::from("rust-example");
// "The last block received by the emitting node"
let start_height: i32 = 0;
// Construct the message
message::NetworkMessage::Version(message_network::VersionMessage::new(
services,
timestamp as i64,
addr_recv,
addr_from,
nonce,
user_agent,
start_height,
))
}

View File

@ -14,7 +14,7 @@ honggfuzz_fuzz = ["honggfuzz"]
[dependencies]
honggfuzz = { version = "0.5", optional = true }
afl = { version = "0.4", optional = true }
bitcoin = { path = "..", features = ["fuzztarget"] }
bitcoin = { path = "..", features = ["fuzztarget", "serde-decimal"] }
# Prevent this from interfering with workspaces
[workspace]
@ -37,21 +37,9 @@ name = "deserialize_address"
path = "fuzz_targets/deserialize_address.rs"
[[bin]]
name = "deserialize_amount"
path = "fuzz_targets/deserialize_amount.rs"
name = "deserialize_decimal"
path = "fuzz_targets/deserialize_decimal.rs"
[[bin]]
name = "outpoint_string"
path = "fuzz_targets/outpoint_string.rs"
[[bin]]
name = "deserialize_psbt"
path = "fuzz_targets/deserialize_psbt.rs"
[[bin]]
name = "deser_net_msg"
path = "fuzz_targets/deser_net_msg.rs"
[[bin]]
name = "uint128_fuzz"
path = "fuzz_targets/uint128_fuzz.rs"
name = "deserialize_udecimal"
path = "fuzz_targets/deserialize_udecimal.rs"

View File

@ -1,7 +1,16 @@
extern crate bitcoin;
use std::str::FromStr;
fn do_test(data: &[u8]) {
let _: Result<bitcoin::network::message::RawNetworkMessage, _> = bitcoin::consensus::encode::deserialize(data);
let data_str = String::from_utf8_lossy(data);
let dec = match bitcoin::util::decimal::Decimal::from_str(&data_str) {
Ok(dec) => dec,
Err(_) => return,
};
let dec_roundtrip = match bitcoin::util::decimal::Decimal::from_str(&dec.to_string()) {
Ok(dec) => dec,
Err(_) => return,
};
assert_eq!(dec, dec_roundtrip);
}
#[cfg(feature = "afl")]
@ -46,7 +55,7 @@ mod tests {
#[test]
fn duplicate_crash() {
let mut a = Vec::new();
extend_vec_from_hex("00", &mut a);
extend_vec_from_hex("00000000", &mut a);
super::do_test(&a);
}
}

View File

@ -1,61 +0,0 @@
extern crate bitcoin;
fn do_test(data: &[u8]) {
let psbt: Result<bitcoin::util::psbt::PartiallySignedTransaction, _> = bitcoin::consensus::encode::deserialize(data);
match psbt {
Err(_) => {},
Ok(psbt) => {
let ser = bitcoin::consensus::encode::serialize(&psbt);
let deser: bitcoin::util::psbt::PartiallySignedTransaction = bitcoin::consensus::encode::deserialize(&ser).unwrap();
// Since the fuzz data could order psbt fields differently, we compare to our deser/ser instead of data
assert_eq!(ser, bitcoin::consensus::encode::serialize(&deser));
}
}
}
#[cfg(feature = "afl")]
#[macro_use] extern crate afl;
#[cfg(feature = "afl")]
fn main() {
fuzz!(|data| {
do_test(&data);
});
}
#[cfg(feature = "honggfuzz")]
#[macro_use] extern crate honggfuzz;
#[cfg(feature = "honggfuzz")]
fn main() {
loop {
fuzz!(|data| {
do_test(data);
});
}
}
#[cfg(test)]
mod tests {
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
let mut b = 0;
for (idx, c) in hex.as_bytes().iter().enumerate() {
b <<= 4;
match *c {
b'A'...b'F' => b |= c - b'A' + 10,
b'a'...b'f' => b |= c - b'a' + 10,
b'0'...b'9' => b |= c - b'0',
_ => panic!("Bad hex"),
}
if (idx & 1) == 1 {
out.push(b);
b = 0;
}
}
}
#[test]
fn duplicate_crash() {
let mut a = Vec::new();
extend_vec_from_hex("00", &mut a);
super::do_test(&a);
}
}

View File

@ -1,7 +1,5 @@
extern crate bitcoin;
use bitcoin::util::address::Address;
use bitcoin::network::constants::Network;
use bitcoin::blockdata::script;
use bitcoin::consensus::encode;
@ -34,11 +32,6 @@ fn do_test(data: &[u8]) {
}
assert_eq!(b.into_script(), script);
assert_eq!(data, &encode::serialize(&script)[..]);
// Check if valid address and if that address roundtrips.
if let Some(addr) = Address::from_script(&script, Network::Bitcoin) {
assert_eq!(addr.script_pubkey(), script);
}
}
}

View File

@ -7,12 +7,12 @@ fn do_test(data: &[u8]) {
Ok(mut tx) => {
let ser = bitcoin::consensus::encode::serialize(&tx);
assert_eq!(&ser[..], data);
let len = ser.len();
let len = ser.len() as u64;
let calculated_weight = tx.get_weight();
for input in &mut tx.input {
input.witness = vec![];
}
let no_witness_len = bitcoin::consensus::encode::serialize(&tx).len();
let no_witness_len = bitcoin::consensus::encode::serialize(&tx).len() as u64;
// For 0-input transactions, `no_witness_len` will be incorrect because
// we serialize as segwit even after "stripping the witnesses". We need
// to drop two bytes (i.e. eight weight)

View File

@ -2,28 +2,15 @@ extern crate bitcoin;
use std::str::FromStr;
fn do_test(data: &[u8]) {
let data_str = String::from_utf8_lossy(data);
// signed
let samt = match bitcoin::util::amount::SignedAmount::from_str(&data_str) {
Ok(amt) => amt,
let dec = match bitcoin::util::decimal::UDecimal::from_str(&data_str) {
Ok(dec) => dec,
Err(_) => return,
};
let samt_roundtrip = match bitcoin::util::amount::SignedAmount::from_str(&samt.to_string()) {
Ok(amt) => amt,
let dec_roundtrip = match bitcoin::util::decimal::UDecimal::from_str(&dec.to_string()) {
Ok(dec) => dec,
Err(_) => return,
};
assert_eq!(samt, samt_roundtrip);
// unsigned
let amt = match bitcoin::util::amount::Amount::from_str(&data_str) {
Ok(amt) => amt,
Err(_) => return,
};
let amt_roundtrip = match bitcoin::util::amount::Amount::from_str(&amt.to_string()) {
Ok(amt) => amt,
Err(_) => return,
};
assert_eq!(amt, amt_roundtrip);
assert_eq!(dec, dec_roundtrip);
}
#[cfg(feature = "afl")]

View File

@ -1,88 +0,0 @@
extern crate bitcoin;
use bitcoin::blockdata::transaction::OutPoint;
use bitcoin::consensus::encode;
use std::str::FromStr;
fn do_test(data: &[u8]) {
let lowercase: Vec<u8> = data.iter().map(|c| match *c {
b'A' => b'a',
b'B' => b'b',
b'C' => b'c',
b'D' => b'd',
b'E' => b'e',
b'F' => b'f',
x => x
}).collect();
let data_str = match String::from_utf8(lowercase) {
Err(_) => return,
Ok(s) => s,
};
match OutPoint::from_str(&data_str) {
Ok(op) => {
assert_eq!(op.to_string().as_bytes(), data_str.as_bytes());
}
Err(_) => {
// If we can't deserialize as a string, try consensus deserializing
let res: Result<OutPoint, _> = encode::deserialize(data);
if let Ok(deser) = res {
let ser = encode::serialize(&deser);
assert_eq!(ser, data);
let string = deser.to_string();
match OutPoint::from_str(&string) {
Ok(destring) => assert_eq!(destring, deser),
Err(_) => panic!()
}
}
}
}
}
#[cfg(feature = "afl")]
#[macro_use] extern crate afl;
#[cfg(feature = "afl")]
fn main() {
fuzz!(|data| {
do_test(&data);
});
}
#[cfg(feature = "honggfuzz")]
#[macro_use] extern crate honggfuzz;
#[cfg(feature = "honggfuzz")]
fn main() {
loop {
fuzz!(|data| {
do_test(data);
});
}
}
#[cfg(test)]
mod tests {
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
let mut b = 0;
for (idx, c) in hex.as_bytes().iter().enumerate() {
b <<= 4;
match *c {
b'A'...b'F' => b |= c - b'A' + 10,
b'a'...b'f' => b |= c - b'a' + 10,
b'0'...b'9' => b |= c - b'0',
_ => panic!("Bad hex"),
}
if (idx & 1) == 1 {
out.push(b);
b = 0;
}
}
}
#[test]
fn duplicate_crash() {
let mut a = Vec::new();
extend_vec_from_hex("00", &mut a);
super::do_test(&a);
}
}

View File

@ -1,101 +0,0 @@
extern crate bitcoin;
use std::str::FromStr;
fn do_test(data: &[u8]) {
macro_rules! read_ints {
($start: expr) => { {
let mut native = 0;
for c in data[$start..$start + 16].iter() {
native <<= 8;
native |= (*c) as u128;
}
// Note BE:
let uint128 = bitcoin::util::uint::Uint128::from(&[native as u64, (native >> 8*8) as u64][..]);
(native, uint128)
} }
}
macro_rules! check_eq {
($native: expr, $uint: expr) => { {
assert_eq!(&[$native as u64, ($native >> 8*8) as u64], $uint.as_bytes());
} }
}
if data.len() != 16*2 + 1 { return; }
let (a_native, a) = read_ints!(0);
// Checks using only a:
for i in 0..128 {
check_eq!(a_native << i, a << i);
check_eq!(a_native >> i, a >> i);
}
assert_eq!(a_native as u64, a.low_u64());
assert_eq!(a_native as u32, a.low_u32());
assert_eq!(128 - a_native.leading_zeros() as usize, a.bits());
assert_eq!(a_native as u64, bitcoin::util::uint::Uint128::from_u64(a_native as u64).unwrap().low_u64());
// Checks with two numbers:
let (b_native, b) = read_ints!(16);
check_eq!(a_native.wrapping_add(b_native), a + b);
check_eq!(a_native.wrapping_sub(b_native), a - b);
if b_native != 0 {
check_eq!(a_native.wrapping_div(b_native), a / b);
}
check_eq!(a_native.wrapping_mul(b_native), a * b);
check_eq!(a_native & b_native, a & b);
check_eq!(a_native | b_native, a | b);
check_eq!(a_native ^ b_native, a ^ b);
check_eq!(a_native.wrapping_mul((b_native as u32) as u128), a.mul_u32(b.low_u32()));
assert_eq!(a_native > b_native, a > b);
assert_eq!(a_native >= b_native, a >= b);
assert_eq!(a_native < b_native, a < b);
assert_eq!(a_native <= b_native, a <= b);
}
#[cfg(feature = "afl")]
#[macro_use] extern crate afl;
#[cfg(feature = "afl")]
fn main() {
fuzz!(|data| {
do_test(&data);
});
}
#[cfg(feature = "honggfuzz")]
#[macro_use] extern crate honggfuzz;
#[cfg(feature = "honggfuzz")]
fn main() {
loop {
fuzz!(|data| {
do_test(data);
});
}
}
#[cfg(test)]
mod tests {
fn extend_vec_from_hex(hex: &str, out: &mut Vec<u8>) {
let mut b = 0;
for (idx, c) in hex.as_bytes().iter().enumerate() {
b <<= 4;
match *c {
b'A'...b'F' => b |= c - b'A' + 10,
b'a'...b'f' => b |= c - b'a' + 10,
b'0'...b'9' => b |= c - b'0',
_ => panic!("Bad hex"),
}
if (idx & 1) == 1 {
out.push(b);
b = 0;
}
}
}
#[test]
fn duplicate_crash() {
let mut a = Vec::new();
extend_vec_from_hex("100000a70000000000000000000000000000000000000000000000000000000054", &mut a);
super::do_test(&a);
}
}

Some files were not shown because too many files have changed in this diff Show More