Compare commits
No commits in common. "master" and "0.16.0" have entirely different histories.
59
.travis.yml
59
.travis.yml
|
@ -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
|
||||
|
|
102
CHANGELOG.md
102
CHANGELOG.md
|
@ -1,106 +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
|
||||
|
|
39
Cargo.toml
39
Cargo.toml
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "bitcoin"
|
||||
version = "0.23.0"
|
||||
version = "0.16.0"
|
||||
authors = ["Andrew Poelstra <apoelstra@wpsoftware.net>"]
|
||||
license = "CC0-1.0"
|
||||
homepage = "https://github.com/rust-bitcoin/rust-bitcoin/"
|
||||
|
@ -15,24 +15,29 @@ name = "bitcoin"
|
|||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
fuzztarget = ["secp256k1/fuzztarget", "bitcoin_hashes/fuzztarget"]
|
||||
fuzztarget = ["secp256k1/fuzztarget"]
|
||||
serde-decimal = ["serde", "strason"]
|
||||
unstable = []
|
||||
rand = ["secp256k1/rand-std"]
|
||||
use-serde = ["serde", "bitcoin_hashes/serde", "secp256k1/serde"]
|
||||
|
||||
[dependencies]
|
||||
bech32 = "0.7.2"
|
||||
bitcoin_hashes = "0.7.3"
|
||||
secp256k1 = "0.17.1"
|
||||
bitcoin-bech32 = "0.8.0"
|
||||
byteorder = "1.2"
|
||||
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.12"
|
||||
features = [ "rand" ]
|
||||
|
|
70
README.md
70
README.md
|
@ -1,10 +1,10 @@
|
|||
[](https://travis-ci.org/rust-bitcoin/rust-bitcoin)
|
||||
[](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).
|
||||
|
|
|
@ -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
|
|
@ -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,
|
||||
))
|
||||
}
|
|
@ -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,13 @@ 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 = "deserialize_udecimal"
|
||||
path = "fuzz_targets/deserialize_udecimal.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"
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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")]
|
|
@ -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
Loading…
Reference in New Issue