Compare commits
No commits in common. "master" and "0.14.2" have entirely different histories.
59
.travis.yml
59
.travis.yml
|
@ -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
|
|
||||||
|
|
157
CHANGELOG.md
157
CHANGELOG.md
|
@ -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`.
|
|
||||||
|
|
||||||
|
|
41
Cargo.toml
41
Cargo.toml
|
@ -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
106
README.md
|
@ -1,10 +1,10 @@
|
||||||
[](https://travis-ci.org/rust-bitcoin/rust-bitcoin)
|
[](https://travis-ci.org/rust-bitcoin/rust-bitcoin)
|
||||||
[](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).
|
|
||||||
|
|
|
@ -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]
|
[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"
|
|
||||||
|
|
|
@ -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")]
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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,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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")]
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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