#public-key #proptest #bitcoin #generate

bitcoin-proptest

Proptest strategies for Bitcoin-related code

3 releases

0.0.1-alpha.3 Jul 1, 2024
0.0.1-alpha.2 Apr 28, 2024
0.0.1-alpha.1 Apr 27, 2024

#10 in #proptest

Apache-2.0 OR MIT

57KB
1K SLoC

Rust Bitcoin Proptest Strategies

Proptest strategies for Bitcoin-related code.

This collection of generators (called strategies in proptest's terminology) helps developers of Bitcoin-related software written in Rust supply random data – both valid and invalid – to their property-based tests.

Visit documentation for details.

Example

#[cfg(test)]
mod tests {
  proptest! {
     #[test]
     // generates valid hex-encoded public keys, both compressed and uncompressed
     fn pubkey_parsing(s in prop::secp256k1::public_key::valid::hex()) {
        prop_assert!(s.len() == 66 || s.len() == 130);
        prop_assert!(my_parser(s).is_ok());
     }
  }
}

lib.rs:

Rust Bitcoin Proptest Strategies

Proptest strategies for Bitcoin-related code.

This collection of generators (called strategies in proptest's terminology) helps developers of Bitcoin-related software written in Rust supply random data – both valid and invalid – to their property-based tests.

Basic rules

  1. unless documentation specifies, the strategy generates anything, i. e. all possible variants, both valid and invalid, as long as type permits, for example:
  • “Generates descriptors” means any type, both valid and invalid
  • “Generates valid descriptors” means any type, all valid
  1. every strategy also has an adjacent strategy called build where inputs (in form of strategies) can be specified, for example:

Organization

All strategies are placed in module prop sorted by category. Inside each category, there is typically a nested set of modules that further specify properties of the strategies. The modules are usually organized as prop::category::what::what::what::how() where how() is the strategy returning a specific format of what, for example: prop::secp256k1::public_key::invalid::compressed::vec().

If a strategy (in form of function) is placed at the same level as other modules, they typically generate mix of all modules at that level. For example prop::secp256k1::public_key::valid::vec() will generate byte vectors of both compressed an uncompressed public keys and prop::secp256k1::public_key::vec() will generate valid and invalid, compressed as well as uncompressed public keys.

Example

#[cfg(test)]
mod tests {
proptest! {
#[test]
// generates valid hex-encoded public keys, both compressed and uncompressed
fn pubkey_parsing(s in prop::secp256k1::public_key::valid::hex()) {
prop_assert!(s.len() == 66 || s.len() == 130);
prop_assert!(my_parser(s).is_ok());
}
}
}

Binary

An accompanying binary (in form of an example) allows to print samples of strategies with textual outputs. By default 10 samples are printed, their number can be modified by passing argument -n. Description of all arguments can be displayed using --help.

$> cargo run --example samples -- --list

bitcoin/address
bitcoin/address/p2pkh
bitcoin/address/p2wpkh
bitcoin/address/p2sh
bitcoin/address/p2shwpkh
bitcoin/bip32/xpriv
bitcoin/bip32/xpub
bitcoin/descriptor/pkh
bitcoin/descriptor/pkh/valid
bitcoin/descriptor/pkh/invalid
[…]

$> cargo run --example samples -- bitcoin/address

mgV22Th8EoBjK3F8gkq12darpYKfZhRVVC
2N4H6BHitgp1X3XxBJchXDC7Js8vuwn9nLR
2NEWWVbyXiFEJy1rijrqWAYWsKuPfgq4iSG
2MwBxE5uhRjMn6oQCVDCibtxgLq5eYmai4Y
1FS9MqvDR5e23TmmkG3UgxWhHwmxChkTAd
3AmhvjgGiqpUX8bDNGiv75cr1oF9j5sEp1
2MvdWb16UVVzJg1BatV7UHR1paKH2TVdX79
mhss96DFw9FsdqBx2kWN4w1irRixh1f2Me
mtodi2dJnPP4GBbTqsbRD9Z4JdHc9mMwMW
19WsVuhxY2h9czLcgrhvW5a5hUAUsDNjB6

Dependencies

~16MB
~222K SLoC