Compare commits
No commits in common. "master" and "0.13" have entirely different histories.
55
.travis.yml
55
.travis.yml
|
@ -1,46 +1,17 @@
|
||||||
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 &&
|
- if [ "$(rustup show | grep default | grep stable)" != "" ]; then cd fuzz && cargo test --verbose && ./travis-fuzz.sh; fi
|
||||||
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
|
|
||||||
|
|
192
CHANGELOG.md
192
CHANGELOG.md
|
@ -1,192 +0,0 @@
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
* Add serde support for `Address`
|
|
||||||
|
|
||||||
# 0.14.1 - 2018-08-28
|
|
||||||
|
|
||||||
* Reject non-compact `VarInt`s on various types
|
|
||||||
* Expose many types at the top level of the crate
|
|
||||||
* Add `Ord`, `PartialOrd` impls for `Script`
|
|
||||||
|
|
||||||
# 0.14.0 - 2018-08-22
|
|
||||||
|
|
||||||
* Add [regtest network](https://github.com/rust-bitcoin/rust-bitcoin/pull/84) to `Network` enum
|
|
||||||
* Add [`Script::is_op_return()`](https://github.com/rust-bitcoin/rust-bitcoin/pull/101/) which is more specific than
|
|
||||||
`Script::is_provably_unspendable()`
|
|
||||||
* Update to bech32 0.8.0; [add Regtest bech32 address support](https://github.com/rust-bitcoin/rust-bitcoin/pull/110)
|
|
||||||
* [Replace rustc-serialize dependency with hex](https://github.com/rust-bitcoin/rust-bitcoin/pull/107) as a stopgap
|
|
||||||
toward eliminating any extra dependencies for this; clean up the many independent hex encoders and decoders
|
|
||||||
throughout the codebase.
|
|
||||||
* [Add conversions between `ChildNumber` and `u32`](https://github.com/rust-bitcoin/rust-bitcoin/pull/126); make
|
|
||||||
representation non-public; fix documentation
|
|
||||||
* [Add several derivation convenience](https://github.com/rust-bitcoin/rust-bitcoin/pull/129) to `bip32` extended keys
|
|
||||||
* Make `deserialize::deserialize()` [enforce no trailing bytes](https://github.com/rust-bitcoin/rust-bitcoin/pull/129)
|
|
||||||
* Replace `TxOutRef` with `OutPoint`; use it in `TxIn` struct.
|
|
||||||
* Use modern `as_` `to_` `into_` conventions for array-wrapping types; impl `Display` rather than `ToString` for most types
|
|
||||||
* Change `script::Instructions` iterator [to allow rejecting non-minimal pushes](https://github.com/rust-bitcoin/rust-bitcoin/pull/136);
|
|
||||||
fix bug where errors would iterate forever.
|
|
||||||
* Overhaul `util::Error`; introduce `serialize::Error` [and use it for `SimpleDecoder` and `SimpleDecoder` rather
|
|
||||||
than parameterizing these over their error type](https://github.com/rust-bitcoin/rust-bitcoin/pull/137).
|
|
||||||
* Overhaul `UDecimal` and `Decimal` serialization and parsing [and fix many lingering parsing bugs](https://github.com/rust-bitcoin/rust-bitcoin/pull/142)
|
|
||||||
* [Update to serde 1.0 and strason 0.4](https://github.com/rust-bitcoin/rust-bitcoin/pull/125)
|
|
||||||
* Update to secp256k1 0.11.0
|
|
||||||
* 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`.
|
|
||||||
|
|
34
Cargo.toml
34
Cargo.toml
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "bitcoin"
|
name = "bitcoin"
|
||||||
version = "0.23.0"
|
version = "0.13.0"
|
||||||
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,19 @@ name = "bitcoin"
|
||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
fuzztarget = ["secp256k1/fuzztarget", "bitcoin_hashes/fuzztarget"]
|
bitcoinconsenus = ["bitcoinconsensus"]
|
||||||
unstable = []
|
fuzztarget = ["secp256k1/fuzztarget"]
|
||||||
rand = ["secp256k1/rand-std"]
|
|
||||||
use-serde = ["serde", "bitcoin_hashes/serde", "secp256k1/serde"]
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bech32 = "0.7.2"
|
bitcoin-bech32 = "0.5.1"
|
||||||
bitcoin_hashes = "0.7.3"
|
byteorder = "1.1"
|
||||||
secp256k1 = "0.17.1"
|
rand = "0.3"
|
||||||
|
rust-crypto = "0.2"
|
||||||
|
rustc-serialize = "0.3"
|
||||||
|
serde = "0.6"
|
||||||
|
strason = "0.3"
|
||||||
|
bitcoinconsensus = { version = "0.16", optional=true }
|
||||||
|
|
||||||
bitcoinconsensus = { version = "0.19.0-1", optional = true }
|
[dependencies.secp256k1]
|
||||||
serde = { version = "1", optional = true }
|
version = "0.9"
|
||||||
|
features = [ "rand" ]
|
||||||
[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"
|
|
||||||
|
|
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,20 @@ 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.
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
To use rust-bitcoin, just add the following to your Cargo.toml.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[dependencies]
|
||||||
|
bitcoin = "0.12"
|
||||||
|
```
|
||||||
|
|
||||||
# Known limitations
|
# Known limitations
|
||||||
|
|
||||||
|
@ -38,54 +47,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 +66,39 @@ 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 "bitcoinconsenus" 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
|
||||||
|
|
||||||
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,
|
|
||||||
))
|
|
||||||
}
|
|
|
@ -13,7 +13,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.3", optional = true }
|
||||||
bitcoin = { path = "..", features = ["fuzztarget"] }
|
bitcoin = { path = "..", features = ["fuzztarget"] }
|
||||||
|
|
||||||
# Prevent this from interfering with workspaces
|
# Prevent this from interfering with workspaces
|
||||||
|
@ -35,23 +35,3 @@ path = "fuzz_targets/deserialize_transaction.rs"
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "deserialize_address"
|
name = "deserialize_address"
|
||||||
path = "fuzz_targets/deserialize_address.rs"
|
path = "fuzz_targets/deserialize_address.rs"
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "deserialize_amount"
|
|
||||||
path = "fuzz_targets/deserialize_amount.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,52 +0,0 @@
|
||||||
extern crate bitcoin;
|
|
||||||
|
|
||||||
fn do_test(data: &[u8]) {
|
|
||||||
let _: Result<bitcoin::network::message::RawNetworkMessage, _> = bitcoin::consensus::encode::deserialize(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -10,10 +10,10 @@ fn do_test(data: &[u8]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
#[macro_use] extern crate afl;
|
extern crate afl;
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
fn main() {
|
fn main() {
|
||||||
fuzz!(|data| {
|
afl::read_stdio_bytes(|data| {
|
||||||
do_test(&data);
|
do_test(&data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,74 +0,0 @@
|
||||||
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,
|
|
||||||
Err(_) => return,
|
|
||||||
};
|
|
||||||
let samt_roundtrip = match bitcoin::util::amount::SignedAmount::from_str(&samt.to_string()) {
|
|
||||||
Ok(amt) => amt,
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[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("00000000", &mut a);
|
|
||||||
super::do_test(&a);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +1,14 @@
|
||||||
extern crate bitcoin;
|
extern crate bitcoin;
|
||||||
|
type BResult = Result<bitcoin::blockdata::block::Block, bitcoin::util::Error>;
|
||||||
fn do_test(data: &[u8]) {
|
fn do_test(data: &[u8]) {
|
||||||
let _: Result<bitcoin::blockdata::block::Block, _>= bitcoin::consensus::encode::deserialize(data);
|
let _: BResult = bitcoin::network::serialize::deserialize(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
#[macro_use] extern crate afl;
|
extern crate afl;
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
fn main() {
|
fn main() {
|
||||||
fuzz!(|data| {
|
afl::read_stdio_bytes(|data| {
|
||||||
do_test(&data);
|
do_test(&data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,52 +1,14 @@
|
||||||
extern crate bitcoin;
|
extern crate bitcoin;
|
||||||
|
type BResult = Result<bitcoin::blockdata::script::Script, bitcoin::util::Error>;
|
||||||
use bitcoin::util::address::Address;
|
|
||||||
use bitcoin::network::constants::Network;
|
|
||||||
use bitcoin::blockdata::script;
|
|
||||||
use bitcoin::consensus::encode;
|
|
||||||
|
|
||||||
fn do_test(data: &[u8]) {
|
fn do_test(data: &[u8]) {
|
||||||
let s: Result<script::Script, _> = encode::deserialize(data);
|
let _: BResult = bitcoin::network::serialize::deserialize(data);
|
||||||
if let Ok(script) = s {
|
|
||||||
let _: Vec<script::Instruction> = script.iter(false).collect();
|
|
||||||
let enforce_min: Vec<script::Instruction> = script.iter(true).collect();
|
|
||||||
|
|
||||||
let mut b = script::Builder::new();
|
|
||||||
for ins in enforce_min {
|
|
||||||
match ins {
|
|
||||||
script::Instruction::Error(_) => return,
|
|
||||||
script::Instruction::Op(op) => { b = b.push_opcode(op); }
|
|
||||||
script::Instruction::PushBytes(bytes) => {
|
|
||||||
// Any one-byte pushes, except -0, which can be interpreted as numbers, should be
|
|
||||||
// reserialized as numbers. (For -1 through 16, this will use special ops; for
|
|
||||||
// others it'll just reserialize them as pushes.)
|
|
||||||
if bytes.len() == 1 && bytes[0] != 0x80 && bytes[0] != 0x00 {
|
|
||||||
if let Ok(num) = script::read_scriptint(bytes) {
|
|
||||||
b = b.push_int(num);
|
|
||||||
} else {
|
|
||||||
b = b.push_slice(bytes);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
b = b.push_slice(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
#[macro_use] extern crate afl;
|
extern crate afl;
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
fn main() {
|
fn main() {
|
||||||
fuzz!(|data| {
|
afl::read_stdio_bytes(|data| {
|
||||||
do_test(&data);
|
do_test(&data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,35 +1,26 @@
|
||||||
extern crate bitcoin;
|
extern crate bitcoin;
|
||||||
|
type BResult = Result<bitcoin::blockdata::transaction::Transaction, bitcoin::util::Error>;
|
||||||
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: BResult = 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);
|
||||||
}
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
#[macro_use] extern crate afl;
|
extern crate afl;
|
||||||
#[cfg(feature = "afl")]
|
#[cfg(feature = "afl")]
|
||||||
fn main() {
|
fn main() {
|
||||||
fuzz!(|data| {
|
afl::read_stdio_bytes(|data| {
|
||||||
do_test(&data);
|
do_test(&data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
tb1218755mmmmmmlmmm9
|
|
|
@ -1 +0,0 @@
|
||||||
tb1q1qヌtb1fァqo
|
|
|
@ -1 +0,0 @@
|
||||||
tb1270kt564
|
|
|
@ -1 +0,0 @@
|
||||||
BC1A[01z--546
|
|
|
@ -1 +0,0 @@
|
||||||
1111W
|
|
|
@ -1 +0,0 @@
|
||||||
BC1-81003971758255
|
|
|
@ -1 +0,0 @@
|
||||||
9119<EFBFBD>
|
|
|
@ -1 +0,0 @@
|
||||||
bc1{)2<>31cc<63><63>
|
|
|
@ -1 +0,0 @@
|
||||||
BC1п<EFBFBD>в?ї~<7E>:
|
|
|
@ -1 +0,0 @@
|
||||||
BC1A2Q𐐀:
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C1Tュワ
|
|
|
@ -1 +0,0 @@
|
||||||
BC10VWWW0VWWWy
|
|
|
@ -1 +0,0 @@
|
||||||
BC1MMMMMMMMMMMMMMMMMMMMMMMMM6
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
bc1
|
|
|
@ -1 +0,0 @@
|
||||||
tb1118755mmmmmmmmmm9264mmmmmmm932772648
|
|
|
@ -1 +0,0 @@
|
||||||
7t44V
|
|
|
@ -1 +0,0 @@
|
||||||
1111
|
|
|
@ -1 +0,0 @@
|
||||||
zSSSSSSSSSS
|
|
|
@ -1 +0,0 @@
|
||||||
BC1A063-+
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
f<EFBFBD>
|
|
|
@ -1 +0,0 @@
|
||||||
漁
|
|
|
@ -1 +0,0 @@
|
||||||
BC1A2Z4Y8J9
|
|
|
@ -1 +0,0 @@
|
||||||
Y
|
|
|
@ -1 +0,0 @@
|
||||||
tb1p25316484708
|
|
|
@ -1 +0,0 @@
|
||||||
BCRT1Cャ1ャッ
|
|
|
@ -1 +0,0 @@
|
||||||
BC10m7tK!
|
|
|
@ -1 +0,0 @@
|
||||||
uu
|
|
|
@ -1 +0,0 @@
|
||||||
BC108<EFBFBD>4
|
|
|
@ -1 +0,0 @@
|
||||||
TB1
|
|
|
@ -1 +0,0 @@
|
||||||
BC188<EFBFBD>
|
|
|
@ -1 +0,0 @@
|
||||||
tb1
|
|
|
@ -1 +0,0 @@
|
||||||
111111111
|
|
|
@ -1 +0,0 @@
|
||||||
yB!
|
|
|
@ -1 +0,0 @@
|
||||||
1111111111111111111111111
|
|
|
@ -1 +0,0 @@
|
||||||
BC1-7111544E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
BC10WWWW4
|
|
|
@ -1 +0,0 @@
|
||||||
o161
|
|
|
@ -1 +0,0 @@
|
||||||
1
|
|
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
111
|
|
|
@ -1 +0,0 @@
|
||||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
|
|
@ -1 +0,0 @@
|
||||||
11YYYYYYYYYYYY1961
|
|
|
@ -1 +0,0 @@
|
||||||
1Y666161
|
|
|
@ -1 +0,0 @@
|
||||||
11111111111111
|
|
|
@ -1 +0,0 @@
|
||||||
BC1-71110837GGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGGWGGGG
|
|
|
@ -1 +0,0 @@
|
||||||
1111111
|
|
|
@ -1 +0,0 @@
|
||||||
BC1-711154444444444444444444444444444E083dU
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C1;71;711-7111544E083'1-71115111111O1111144E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
11111111111111111111111111111111111111111111
|
|
|
@ -1 +0,0 @@
|
||||||
11111161
|
|
|
@ -1 +0,0 @@
|
||||||
BC1-71115(4E0831-7111544E0837U7U
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C11111111111111111111111111~~~~~~~~~~~~~~~~~1111E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
BC111544E083'1-711154C1;71@711-7111544E083'1-7111544E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
tb1r70kt564
|
|
|
@ -1 +0,0 @@
|
||||||
tb1170kt564
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C1;XXXXXXXXXXXXXXXXXXXXXXXXAXXX114E544E0<544E7111544E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C1;71;711-7111544E083'711-711154-7117'11-71115440837U
|
|
|
@ -1 +0,0 @@
|
||||||
BC11544E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C1;71;711-7111544E083'1-7111544E08377-7111544E0837UU
|
|
|
@ -1 +0,0 @@
|
||||||
22
|
|
|
@ -1 +0,0 @@
|
||||||
BC1-3711LLLLLLLLLLLLLL,LLLLLLLLLLLLLLLLL1544E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
tb127kkkkkkkkkkkkkkkkkkkkkkkkkkkkkk0kt56
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C1;71;711-44E083'1-711154SA0837111544E083'1-7111544E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
hhhhhhhhhhhhhhhhRhhhhhhhThhhhhhhhhhhhhhRhhhhhhhh
|
|
|
@ -1 +0,0 @@
|
||||||
BC1EC1-7111544E0A37+111544E0A37U
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C1;71;.11-7111544-7*1'1-7*115C17*1'1-7*115C1CA;71;1C1;71;711-711-7111514E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
tb1118755mmmmmmmmmm9264mmmmmmm132772648
|
|
|
@ -1 +0,0 @@
|
||||||
BC1C1;71;711-710154C1C1;71;711-4E083'1-7111544E0837U
|
|
|
@ -1 +0,0 @@
|
||||||
tb1118755mmmnmmmmmm9264mmb1mmmmm93277264
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue