Compare commits

..

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

754 changed files with 4965 additions and 11906 deletions

View File

@ -1,46 +1,21 @@
language: rust language: rust
cache: cargo rust:
- stable
- beta
- nightly
- 1.14.0
addons: before_install:
apt: - sudo apt-get -qq update
update: true - sudo apt-get install -y binutils-dev libunwind8-dev
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
script: script:
- ./contrib/test.sh - cargo build --verbose
- cargo test --verbose
after_success: | - cargo build --verbose --features=bitcoinconsensus
if [ "$DO_COV" = true ]; then - cargo test --verbose --features=bitcoinconsensus
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz && - cargo build --verbose --features=serde
tar xzf master.tar.gz && - cargo test --verbose --features=serde
cd kcov-master && - cargo build --verbose --features=serde-decimal
mkdir build && - cargo test --verbose --features=serde-decimal
cd build && - if [ "$(rustup show | grep default | grep stable)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; fi
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

View File

@ -1,132 +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):
* Remove `nu_select` macro and low-level networking support
* Move `network::consensus_params` to `consensus::params`
* Move many other things into `consensus::params`
* Move `BitcoinHash` from `network::serialize` to `util::hash`; remove impl for `Vec<u8>`
* Rename/restructure error types
* Rename `Consensus{De,En}coder` to `consensus::{De,En}coder`
* Replace `Raw{De,En}coder` with blanket impls of `consensus::{De,En}coder` on `io::Read` and `io::Write`
* make `serialize` and `serialize_hex` infallible
* Make 0-input transaction de/serialization [always use segwit](https://github.com/rust-bitcoin/rust-bitcoin/pull/153)
* Implement `FromStr` and `Display` for many more types
# 0.14.2 - 2018-09-11 # 0.14.2 - 2018-09-11
* Add serde support for `Address` * Add serde support for `Address`
@ -161,32 +33,3 @@
* Update to secp256k1 0.11.0 * Update to secp256k1 0.11.0
* Many, many documentation and test improvements. * Many, many documentation and test improvements.
# 0.13.1
* Add `Display` trait to uints, `FromStr` trait to `Network` enum
* Add witness inv types to inv enum, constants for Bitcoin regtest network, `is_coin_base` accessor for tx inputs
* Expose `merkleroot(Vec<Sha256dHash>)`
# 0.13
* Move witnesses inside the `TxIn` structure
* Add `Transaction::get_weight()`
* Update bip143 `sighash_all` API to be more ergonomic
# 0.12
* The in-memory blockchain was moved into a dedicated project rust-bitcoin-chain.
* Removed old script interpreter
* A new optional feature "bitcoinconsensus" lets this library use Bitcoin Core's native
script verifier, wrappend into Rust by the rust-bitcoinconsenus project.
See `Transaction::verify` and `Script::verify` methods.
* Replaced Base58 traits with `encode_slice`, `check_encode_slice`, from and `from_check` functions in the base58 module.
* Un-reversed the Debug output for Sha256dHash
* Add bech32 support
* Support segwit address types
### 0.11
* Remove `num` dependency at Matt's request; agree this is obnoxious to require all
downstream users to also have a `num` dependency just so they can use `Uint256::from_u64`.

View File

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

106
README.md
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) [![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 # Rust Bitcoin Library
Library with support for de/serialization, parsing and executing on data 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/) [Documentation](https://docs.rs/bitcoin/)
@ -14,11 +14,12 @@ Supports (or should support)
* De/serialization of blocks and transactions * De/serialization of blocks and transactions
* Script de/serialization * Script de/serialization
* Private keys and address creation, de/serialization and validation (including full BIP32 support) * 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) * 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 For JSONRPC interaction with Bitcoin Core, it is recommended to use [rust-jsonrpc](https://github.com/apoelstra/rust-jsonrpc)
[rust-bitcoincore-rpc](https://github.com/rust-bitcoin/rust-bitcoincore-rpc). which uses the underlying [strason library](https://github.com/apoelstra/strason)
which parses decimal numbers as strings, preventing precision errors.
# Known limitations # Known limitations
@ -38,54 +39,12 @@ fix specific consensus incompatibilities are welcome.
## Documentation ## Documentation
Currently can be found on [docs.rs/bitcoin](https://docs.rs/bitcoin/). Currently the [documentation](https://www.wpsoftware.net/rustdoc/bitcoin/)
Patches to add usage examples and to expand on existing docs would be extremely is very sparse. Patches to add usage examples and to expand on existing
appreciated. 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) # Policy on Altcoins/Altchains
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
Patches which add support for non-Bitcoin cryptocurrencies by adding constants 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 to existing enums (e.g. to set the network message magic-byte sequence) are
@ -99,12 +58,47 @@ cross-chain atomic swaps) are more likely to be accepted than things which
support only a single blockchain. support only a single blockchain.
# Release Notes ## Release Notes
See [CHANGELOG.md](CHANGELOG.md). I will try to document all breaking changes here so that people upgrading will know
what they need to change.
### 0.11
# Licensing Remove `num` dependency at Matt's request; agree this is obnoxious to require all
downstream users to also have a `num` dependency just so they can use `Uint256::from_u64`.
### 0.12
* The in-memory blockchain was moved into a dedicated project rust-bitcoin-chain.
* Removed old script interpreter
* A new optional feature "bitcoinconsensus" lets this library use Bitcoin Core's native
script verifier, wrappend into Rust by the rust-bitcoinconsenus project.
See `Transaction::verify` and `Script::verify` methods.
* Replaced Base58 traits with `encode_slice`, `check_encode_slice`, from and `from_check` functions in the base58 module.
* Un-reversed the Debug output for Sha256dHash
* Add bech32 support
* Support segwit address types
### 0.13
* Move witnesses inside the `TxIn` structure
* Add `Transaction::get_weight()`
* Update bip143 `sighash_all` API to be more ergonomic
#### 0.13.1
* Add `Display` trait to uints, `FromStr` trait to `Network` enum
* Add witness inv types to inv enum, constants for Bitcoin regtest network, `is_coin_base` accessor for tx inputs
* Expose `merkleroot(Vec<Sha256dHash>)`
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] [dependencies]
honggfuzz = { version = "0.5", optional = true } honggfuzz = { version = "0.5", optional = true }
afl = { version = "0.4", optional = true } afl = { version = "0.4", optional = true }
bitcoin = { path = "..", features = ["fuzztarget"] } bitcoin = { path = "..", features = ["fuzztarget", "serde-decimal"] }
# Prevent this from interfering with workspaces # Prevent this from interfering with workspaces
[workspace] [workspace]
@ -37,21 +37,9 @@ name = "deserialize_address"
path = "fuzz_targets/deserialize_address.rs" path = "fuzz_targets/deserialize_address.rs"
[[bin]] [[bin]]
name = "deserialize_amount" name = "deserialize_decimal"
path = "fuzz_targets/deserialize_amount.rs" path = "fuzz_targets/deserialize_decimal.rs"
[[bin]] [[bin]]
name = "outpoint_string" name = "deserialize_udecimal"
path = "fuzz_targets/outpoint_string.rs" path = "fuzz_targets/deserialize_udecimal.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"

View File

@ -1,7 +1,7 @@
extern crate bitcoin; extern crate bitcoin;
fn do_test(data: &[u8]) { fn do_test(data: &[u8]) {
let _: Result<bitcoin::blockdata::block::Block, _>= bitcoin::consensus::encode::deserialize(data); let _: Result<bitcoin::blockdata::block::Block, _>= bitcoin::network::serialize::deserialize(data);
} }
#[cfg(feature = "afl")] #[cfg(feature = "afl")]

View File

@ -1,7 +1,16 @@
extern crate bitcoin; extern crate bitcoin;
use std::str::FromStr;
fn do_test(data: &[u8]) { 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")] #[cfg(feature = "afl")]
@ -46,7 +55,7 @@ mod tests {
#[test] #[test]
fn duplicate_crash() { fn duplicate_crash() {
let mut a = Vec::new(); let mut a = Vec::new();
extend_vec_from_hex("00", &mut a); extend_vec_from_hex("00000000", &mut a);
super::do_test(&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,12 +1,10 @@
extern crate bitcoin; extern crate bitcoin;
use bitcoin::util::address::Address;
use bitcoin::network::constants::Network;
use bitcoin::blockdata::script; use bitcoin::blockdata::script;
use bitcoin::consensus::encode; use bitcoin::network::serialize;
fn do_test(data: &[u8]) { fn do_test(data: &[u8]) {
let s: Result<script::Script, _> = encode::deserialize(data); let s: Result<script::Script, _> = serialize::deserialize(data);
if let Ok(script) = s { if let Ok(script) = s {
let _: Vec<script::Instruction> = script.iter(false).collect(); let _: Vec<script::Instruction> = script.iter(false).collect();
let enforce_min: Vec<script::Instruction> = script.iter(true).collect(); let enforce_min: Vec<script::Instruction> = script.iter(true).collect();
@ -33,12 +31,7 @@ fn do_test(data: &[u8]) {
} }
} }
assert_eq!(b.into_script(), script); assert_eq!(b.into_script(), script);
assert_eq!(data, &encode::serialize(&script)[..]); assert_eq!(data, &serialize::serialize(&script).unwrap()[..]);
// 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

@ -1,26 +1,17 @@
extern crate bitcoin; extern crate bitcoin;
fn do_test(data: &[u8]) { fn do_test(data: &[u8]) {
let tx_result: Result<bitcoin::blockdata::transaction::Transaction, _> = bitcoin::consensus::encode::deserialize(data); let tx_result: Result<bitcoin::blockdata::transaction::Transaction, _> = bitcoin::network::serialize::deserialize(data);
match tx_result { match tx_result {
Err(_) => {}, Err(_) => {},
Ok(mut tx) => { Ok(mut tx) => {
let ser = bitcoin::consensus::encode::serialize(&tx); let len = bitcoin::network::serialize::serialize(&tx).unwrap().len() as u64;
assert_eq!(&ser[..], data);
let len = ser.len();
let calculated_weight = tx.get_weight(); let calculated_weight = tx.get_weight();
for input in &mut tx.input { for input in &mut tx.input {
input.witness = vec![]; input.witness = vec![];
} }
let no_witness_len = bitcoin::consensus::encode::serialize(&tx).len(); let no_witness_len = bitcoin::network::serialize::serialize(&tx).unwrap().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)
if tx.input.is_empty() {
assert_eq!(no_witness_len * 3 + len - 8, calculated_weight);
} else {
assert_eq!(no_witness_len * 3 + len, calculated_weight); assert_eq!(no_witness_len * 3 + len, calculated_weight);
}
}, },
} }
} }
@ -67,7 +58,7 @@ mod tests {
#[test] #[test]
fn duplicate_crash() { fn duplicate_crash() {
let mut a = Vec::new(); let mut a = Vec::new();
extend_vec_from_hex("000700000001000000010000", &mut a); extend_vec_from_hex("00", &mut a);
super::do_test(&a); super::do_test(&a);
} }
} }

View File

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