Commit Graph

2238 Commits

Author SHA1 Message Date
Tobin C. Harding d362e6286a base58: Improve rustdocs
Improve the rustdocs by doing:

- Use full sentences
- Use typical project line length
- Use third person tense for functions
2022-10-29 10:35:08 +11:00
Tobin C. Harding a43234e7ab base58: Make SmallVec methods private
The `SmallVec` type is private, it does not need public methods.
2022-10-29 10:35:08 +11:00
Tobin C. Harding 27f2cba623 base58: Use alternate form to print hex
Currently we are manually adding `0x` in calls to `write!`, this is
unnecessary since the alternate form already adds the `0x`.

Was verified with
```
    #[test]
    fn bad_checksum_error_hex_format() {
        let want = "invalid base58 character 0xab";
        let got = format!("{}", Error::BadByte(0xAB));
        assert_eq!(got, want)
    }
```

Use alternate form to print hex.
2022-10-29 10:35:08 +11:00
Tobin C. Harding f659a7aca3 base58: Remove key related errors
The key related errors are incorrect because they are circular, we have
a base58 error variant in `key::Error` and two key error variants in
`base58::Error`.

Remove the key errors from the `base58::Error` type.
2022-10-29 10:33:14 +11:00
Andrew Poelstra bbf89dd5a4
Merge rust-bitcoin/rust-bitcoin#1223: Remove the endian module
2674327c93 Remove the endian module (Tobin C. Harding)

Pull request description:

  Now we have MSRV of 1.41.1 we can use the `from_le_bytes` and `to_be_bytes` methods implemented on standard integer types, these became available in Rust 1.32.

  Remove the `endian` module replacing its logic with calls to methods on the respective stdlib integer types.

ACKs for top commit:
  Kixunil:
    ACK 2674327c93
  apoelstra:
    ACK 2674327c93

Tree-SHA512: 7cdaf278c9d162cb0080bb6b9ea80ab55f881bfcd389f8b968f8cfaeebb0d27d3b5b46e9677a376bc6b7d4068cf094f50560ed4ae7bc817c50da688f70a7af25
2022-10-28 19:04:59 +00:00
sanket1729 21ae79bed4
Merge rust-bitcoin/rust-bitcoin#935: Add psbt BIP174 test vectors tests
b8bd31d5a8 Promote rust-miniscript finalizer (DanGould)
16bf6f68dd Test PSBT integration (DanGould)
6b6ef528a4 Add OP_0 alias for OP_PUSHBYTES_0 (DanGould)
72935a0f6e Move test_data/* tests/data (Tobin Harding)

Pull request description:

  resolves #892

  *  Initial patch adds OP_0 alias for OP_PUSHBYTES_0 as [approved here](https://github.com/rust-bitcoin/rust-bitcoin/pull/935#discussion_r854539416)
  * Second patch is the bulk of this work. It tests BIP 174 PSBT integration defined at [The BIP's Test Vectors Section](https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#test-vectors) using #957
  * Third patch points users to rust-miniscript for a more useful finalizer

ACKs for top commit:
  tcharding:
    ACK b8bd31d5a8
  sanket1729:
    ACK b8bd31d5a8. Thanks for sticking with this PR. This looks awesome after #957

Tree-SHA512: dc68e524d4349530b082baf5032460fa56593b0ef192125c0b7d7e00954e5593f386b7f1984fc00106b4b9eafbf29cc80ab368dbd26b710eba0962dbd89e0013
2022-10-27 22:28:00 -07:00
Tobin C. Harding 2674327c93 Remove the endian module
Now we have MSRV of 1.41.1 we can use the `from_le_bytes` and
`to_be_bytes` methods, these became available in Rust 1.32.

Remove the `endian` module replacing its logic with calls to methods on
the respective stdlib integer types.
2022-10-28 11:01:57 +11:00
DanGould b8bd31d5a8
Promote rust-miniscript finalizer 2022-10-27 10:40:45 -04:00
DanGould 16bf6f68dd
Test PSBT integration
Implement Test Vectors from BIP 174

Co-authored-by: Tobin Harding <me@tobin.cc>
Co-authored-by: Armin Sabouri <armins88@gmail.com>
2022-10-27 10:40:45 -04:00
DanGould 6b6ef528a4
Add OP_0 alias for OP_PUSHBYTES_0 2022-10-27 10:40:45 -04:00
Tobin Harding 72935a0f6e
Move test_data/* tests/data
In preparation for adding integration tests in the standard Rust
`tests/` directroy; move the contents of `test_data` to `tests/data`.
2022-10-27 10:40:44 -04:00
sanket1729 bd80ecd92d
Merge rust-bitcoin/rust-bitcoin#1345: Fix broken build due to conflict between #1340 and #999
c4084b91fb Fix broken build due to conflict between #1340 and #999 (Andrew Poelstra)

Pull request description:

  I will test merge commits more thoroughly before signing off on them in future, sorry.

ACKs for top commit:
  DanGould:
    tACK c4084b91fb
  tcharding:
    ACK c4084b91fb
  sanket1729:
    ACK c4084b91fb

Tree-SHA512: 51ece3aa43045e81138d21b8402b1ec1559a0b37bdfc4c5246ff46fd085364517449a2e20e625934cbc0c96f18eb2fc6121a6e993fd5b9535ae54c863d032a0b
2022-10-27 02:06:55 -07:00
Andrew Poelstra c4084b91fb
Fix broken build due to conflict between #1340 and #999
I will test merge commits more thoroughly before signing off on them in future, sorry.
2022-10-25 22:04:38 +00:00
Andrew Poelstra 391cfd67bd
Merge rust-bitcoin/rust-bitcoin#1342: Re-export base64 when enabled
dea9b1d1e0 Re-export base64 when enabled (Alekos Filini)

Pull request description:

  `base64` used to be exported until commit 23ee0930c7 which removed the `pub extern crate` declaration.

ACKs for top commit:
  Kixunil:
    ACK dea9b1d1e0
  apoelstra:
    ACK dea9b1d1e0

Tree-SHA512: 2f32b6676aab9881bab9eb0ae61910ec0d4b60cb17c8a7bf8155ec4a13e50abce0061b52f4e81b106b938e99cb68329d027291c1702213cfa2a46734ebadb488
2022-10-25 19:33:51 +00:00
Andrew Poelstra 9fb8c21f79
Merge rust-bitcoin/rust-bitcoin#999: examples: Add taproot PSBT example workflow
1a89d5230c examples: Add taproot-psbt workflow example (Duncan Dean)

Pull request description:

  Will address #893.

  Currently includes a BIP86 example (no spendable script path)

  Working on script path and key path spending when both are possible spending paths.

ACKs for top commit:
  tcharding:
    ACK 1a89d5230c
  apoelstra:
    ACK 1a89d5230c

Tree-SHA512: 31d23914faedb2632d517f9a827075f1bf387df6d98f151000f70546d1e67ac332e698c6a01bda40a9baf5b25bff0114928edc0879c5e01753ecfc6ad182fe26
2022-10-25 16:47:18 +00:00
Alekos Filini dea9b1d1e0
Re-export base64 when enabled 2022-10-25 11:02:02 +02:00
Andrew Poelstra 03d67dd1da
Merge rust-bitcoin/rust-bitcoin#1340: Move sighash module to crate root
fd7f8daeff Move sighash module to crate root (Tobin C. Harding)

Pull request description:

  Done as part of the effort to flatten the `util` module.

  The `sighash` module can stand alone in the crate root, it provides a discreet set of functionality - the `SighashCache` and associated types.

  Marking as high priority because this is part of flattening `util` which is a required step before we start crate smashing.

ACKs for top commit:
  Kixunil:
    ACK fd7f8daeff
  apoelstra:
    ACK fd7f8daeff

Tree-SHA512: e812ca903f7dccfa5a06084e23f93f617d016583bdf082d7a36ca8e67e49f1d140a3e138b93939e816861460ff2c04d49d5e37a555dd853dca1c76dbccd910bf
2022-10-25 00:57:43 +00:00
Andrew Poelstra f9146d0391
Merge rust-bitcoin/rust-bitcoin#1341: ci: Remove serde version pinning
b05ba16a05 ci: Remove serde version pinning (Tobin C. Harding)

Pull request description:

  The MSRV break in serde is fixed now, remove the serde version pinning.

  Fix: #1256

ACKs for top commit:
  Kixunil:
    ACK b05ba16a05 if CI passes.
  apoelstra:
    ACK b05ba16a05

Tree-SHA512: 2046b443500a848cb7b22576473f3b09ece4538dd3d30d7a06b09b28d6fe26f5c4d482f70ec0ec1b79469c221dc9c09e8b05b83debb71fd27f7dc30571cbbcfe
2022-10-25 00:20:04 +00:00
Andrew Poelstra 29d3bc0108
Merge rust-bitcoin/rust-bitcoin#1338: Implement PartiallySignedTransaction::fee
c34d5f8f85 Implement PartiallySignedTransaction::fee (hashmap)

Pull request description:

  to calculate fee if previous outputs are available.
  Closes https://github.com/rust-bitcoin/rust-bitcoin/issues/1220

ACKs for top commit:
  Kixunil:
    ACK c34d5f8f85 if CI passes
  tcharding:
    ACK c34d5f8f85
  apoelstra:
    ACK c34d5f8f85

Tree-SHA512: 697b837de2fb21bbd5d489c524c06a56bb35b73c0f32cc5b0500f5508f3c539b21d327cd556a04ee847ccf8d98829da994d90c19e80c457ddba2cd9d3469476e
2022-10-24 23:32:25 +00:00
Tobin C. Harding b05ba16a05 ci: Remove serde version pinning
The MSRV break in serde is fixed now, remove the serde version pinning.
2022-10-25 09:32:01 +11:00
Tobin C. Harding fd7f8daeff Move sighash module to crate root
Done as part of the effort to flatten the `util` module.

The `sighash` module can stand alone in the crate root, it provides a
discreet set of functionality - the `SighashCache` and associated types.
2022-10-25 09:14:01 +11:00
Andrew Poelstra afcdfa4a59
Merge rust-bitcoin/rust-bitcoin#1295: Remove usage of `opcodes::all`
c3e4399519 Remove usage of opcodes::all (Tobin C. Harding)

Pull request description:

  We have all of the opcodes defined in a submodule called `all`, this allows wildcard imports without bringing in the other types in the `opcodes` module.

  Use wildcard import `use crate::blockdata::opcodes::all::*` instead of fully qualifying the path to opcodes.

  ### Original PR description (left here so the thread of discussion below makes sense)

  The `all` module adds no value, we can remove it without loss of meaning or clarity, doing so makes the code less verbose.

  EDIT: After review, now includes importing with wildcard and removing the `opcodes::` path from any type starting with `OP_`.

  Idea stolen from: https://github.com/rust-bitcoin/rust-bitcoin/pull/525 (patch 7)

ACKs for top commit:
  Kixunil:
    ACK c3e4399519
  apoelstra:
    ACK c3e4399519

Tree-SHA512: 300511d909a25e82c563b18da1b52bcf65653cd3efd8ff32dd5b9e839dacd57924953c1745dfb5e9301fa4f9fc0cd61a075f3a3fd94f6a5a9730bca5155dfd96
2022-10-24 13:32:14 +00:00
hashmap c34d5f8f85
Implement PartiallySignedTransaction::fee
to calculate fee if previous outputs are available.
2022-10-24 14:39:32 +02:00
Tobin C. Harding c3e4399519 Remove usage of opcodes::all
We have all of the opcodes defined in a submodule called `all`, this
allows wildcard imports without bringing in the other types in the
`opcodes` module.

Use wildcard import `use crate::blockdata::opcodes::all::*` instead of
fully qualifying the path to opcodes.
2022-10-24 13:08:47 +11:00
Andrew Poelstra 1d0b721e5e
Merge rust-bitcoin/rust-bitcoin#1335: Improve doc of `Script::push_verify`
7e39082eec Improve doc of `Script::push_verify` (Martin Habovštiak)

Pull request description:

  This rewords the doc to have a reasonable summary, adds a little background explaining the opcode behavior and the effect of the function when called multiple times.

  Closes #1154

ACKs for top commit:
  tcharding:
    ACK 7e39082eec
  apoelstra:
    ACK 7e39082eec

Tree-SHA512: 7f0142c9fcec8ef5b30779f1d22922219180aa103ce2f3039412b1d6b46aa7ee2522181e23a76f9ba5fd84720ef3ff3daa8233d71cf10008f5e3b805b5a5c470
2022-10-21 22:22:59 +00:00
Andrew Poelstra 01d5129d79
Merge rust-bitcoin/rust-bitcoin#1293: Move a bunch of stuff out of `internal_macros`
7d851b42ee Move serde_string_* macros to the serde_utils module (Tobin C. Harding)
53b681b838 Move const_assert to bitcoin_internals (Tobin C. Harding)
5a8a5ff6c9 Move debug_from_display to bitcoin_internals (Tobin C. Harding)
a2f08f2bc6 Improve docs on impl_array_newtype macro (Tobin C. Harding)
771cdde282 Move impl_array_newtype to bitcoin_internals (Tobin C. Harding)

Pull request description:

  Move macros out of `internal_macros`, done in an effort to work towards removing the `internal_macros` module since we have `bitcoin_internals` now.

ACKs for top commit:
  apoelstra:
    ACK 7d851b42ee
  Kixunil:
    ACK 7d851b42ee

Tree-SHA512: b31b3a5b4d18a2dbe3f358bff62ae6ca4041d432c755e9c45b0241d48903e02c95e79ec72a7478b9d2a53486ce9eef19bfe3b8905aba19036e59c0719f193ce7
2022-10-21 22:07:44 +00:00
Martin Habovštiak 7e39082eec Improve doc of `Script::push_verify`
This rewords the doc to have a reasonable summary, adds a little background explaining the opcode behavior and the effect of the function when called multiple times.

Closes ##1154
2022-10-21 21:14:17 +02:00
Andrew Poelstra c5277a8ed7
Merge rust-bitcoin/rust-bitcoin#1331: add some comments to `Transaction::weight`
17f0d29d08 add some comments to `Transaction::weight` (Andrew Poelstra)

Pull request description:

  FIxes #1159

ACKs for top commit:
  tcharding:
    ACK 17f0d29d08

Tree-SHA512: ddef69377a7208dfa2794c09f418fb98820b9fc55a32a29f26cd4fc3126bbc8e6c4085e679601330e1225a8404c6eb2b19c6bf374e327cced343197c631b4930
2022-10-21 14:29:47 +00:00
sanket1729 fcf9bd07bc
Merge rust-bitcoin/rust-bitcoin#957: Add API to PSBT to enable signing inputs
dd8730e14f Use new PSBT signing API in example (Tobin C. Harding)
d2367fb187 Add PSBT sign functionality (Tobin C. Harding)
b80e5aeaab Re-order import statements (Tobin C. Harding)

Pull request description:

  Add an API for signing inputs to the `PSBT` struct. This is work based on code in `rust-miniscript` and the API design suggestions below from @sanket1729 and @Kixunil.

  Please note, this adds an `unimplemented!` call for taproot inputs. ECDSA signing is complete.

  Includes a patch adding the psbt example from https://github.com/rust-bitcoin/rust-bitcoin/pull/940 updated to use this new api. Run `cargo run --example psbt --features=bitcoinconsensus` to test it out.

ACKs for top commit:
  dunxen:
    ACK dd8730e
  apoelstra:
    ACK dd8730e14f
  sanket1729:
    reACK dd8730e14f

Tree-SHA512: 6345571e53cd3aa4b7ad962536da47ae03ab7c0b088107dc4104676bdb64fcf892e8fa60e0b716f3ef158d88d7058938bf267046721ccf74b2d1b092e9b9aaaa
2022-10-20 12:51:28 -07:00
Andrew Poelstra 17f0d29d08
add some comments to `Transaction::weight`
FIxes #1159
2022-10-20 15:24:17 +00:00
Tobin C. Harding 7d851b42ee Move serde_string_* macros to the serde_utils module
In preparation for emptying the `internal_macros` module move the
`serde_string_impl` and `serde_struct_human_string_imp` macros to the
`serde_utils` module.

Rationale: `internal_macros` stuff can go over in the `internals` crate
now that we have one. The serde macros could go over there but we have a
`serde_utils` module that holds code for implementing serde traits,
these two macros are exactly that.
2022-10-20 06:15:57 +11:00
Tobin C. Harding 53b681b838 Move const_assert to bitcoin_internals
This is an internal macro, now that we have the `internals` crate put
`const_assert` in it.
2022-10-20 06:15:44 +11:00
Tobin C. Harding 5a8a5ff6c9 Move debug_from_display to bitcoin_internals
This is an internal macro, now that we have the `internals` crate put
`debug_from_display` in it.
2022-10-20 06:15:23 +11:00
Tobin C. Harding a2f08f2bc6 Improve docs on impl_array_newtype macro
Trivial cleanup of docs.
2022-10-20 06:15:13 +11:00
Tobin C. Harding 771cdde282 Move impl_array_newtype to bitcoin_internals
`impl_array_newtype` is an internal macro, move it to a new, ever so
meaningfully named, `macros` module.

Use `#[macro_export]`, no other changes to the macro.
2022-10-20 06:14:59 +11:00
Tobin C. Harding dd8730e14f Use new PSBT signing API in example
We have a PSBT example that includes a custom signing module, we can
remove that now and use the new PSBT signing API.
2022-10-20 06:07:53 +11:00
Tobin C. Harding d2367fb187 Add PSBT sign functionality
Signing a PSBT requires no knowledge other than what we have here in
this library and the PSBT ready to be signed.

This code was pulled out of `rust-miniscript`.

Add a `sign` method to the `PartiallySignedTransaction`.
2022-10-20 06:07:35 +11:00
Tobin C. Harding b80e5aeaab Re-order import statements
The import statements in `psbt/mod.rs` are a bit of a mess, re-order
them in an attempt to group like things and separate out things that are
different (e.g. `pub use` from `use`).

Refactor only, no logic changes.
2022-10-20 05:59:43 +11:00
Andrew Poelstra 938b61bf66
Merge rust-bitcoin/rust-bitcoin#1210: Move bip152 module to crate root
4057c26829 Run formmater on bip152 (Tobin C. Harding)
facd8ba556 Move bip152 module to crate root (Tobin C. Harding)

Pull request description:

  We are attempting to flatten the `util` module.

  Move the `bip152` module to the crate root out of `util`.

  Currently `src/util/` is ignored by the formatter so this move requires `bip152` module to be formatted. Formatting is done as a separate patch so reviewers can run `cargo +nightly fmt` and compare the diffs if so desired.

ACKs for top commit:
  apoelstra:
    ACK 4057c26829
  sanket1729:
    code review ACK 4057c26829

Tree-SHA512: 889d78817f60b8d038d631059432b37940e97299b9fd3f0055b2ede61b5f87cce4824ac0be239fc3897ff6da8068749c8504aa0714aab35cc0faf519606771bf
2022-10-19 12:32:41 +00:00
Tobin C. Harding 4057c26829 Run formmater on bip152
Run the formmater on the newly moved `bip152` module. No changes other
than those introduced by `cargo +nightly fmt`.
2022-10-19 06:41:10 +11:00
Tobin C. Harding facd8ba556 Move bip152 module to crate root
We are attempting to flatten the `util` module; move the `bip152` module
to the crate root out of `util`.

Currently `src/util/` is ignored by the formatter so this move causes
the `bip152` module to be formatted.
2022-10-19 06:40:33 +11:00
Andrew Poelstra e10aa552f6
Merge rust-bitcoin/rust-bitcoin#1314: Return custom error from `Network::from_str`
d1b7dff094 return custom error from `Network::from_str` (Noah)

Pull request description:

  Fix #1292

  Had some time so got this out of the way.

ACKs for top commit:
  apoelstra:
    ACK d1b7dff094
  tcharding:
    ACK d1b7dff094

Tree-SHA512: f6566f4df74c697cc3d84eca4e4c45bb5da9e86fe32e5f6e257a3e8c3e22fc375f5f307c7f96edd4536a80c1d1c13535f6073a1a093911468abb015040c2888b
2022-10-18 19:31:19 +00:00
Andrew Poelstra 121db506fa
Merge rust-bitcoin/rust-bitcoin#1197: Add `Target` and `Work` types
02a2b43b2b Remove Default impl for Target and Work (Tobin C. Harding)
cb9893c4a9 Add Target and Difficulty types (Tobin C. Harding)

Pull request description:

  Ugh! 1600 lines of green and 1100 of red - my apologies.

  Currently we use the `Uint256` type for proof-of-work calculations. It was observed in #1181 that providing a public 256 bit integer type like this implies that it is a general  purpose integer type. We do not want to provide a general purpose integer type (see the 1000 arithmetic functions on stdlib integer types for why not :)

  Add two new opaque integer types `Target` and `Work`. These are the inverse of each other, both conceptually and mathematically.

  There is a lot of code in this PR, sorry about that. At a high level the PR does:

  - Add a `pow` module.
  - Put a modified version of  `Uint256` in `pow`, making it private.
  - Add two new wrapper types `Target` and `Work` that provide a very limited API specific to their use case. In particular there are methods on each to convert to the other.
  - Only implement methods that we use on each type.

  ### Note

  During development I got mixed up with the word "difficulty", I have discovered this has a very specific meaning in Bitcoin. Please see rustdocs on the `Target::difficulty` function for explanation of this term. For this reason we use the type `Work` defined as the inverse of target, and reserve "difficulty" for the Bitcoin concept.

ACKs for top commit:
  apoelstra:
    ACK 02a2b43b2b
  Kixunil:
    ACK 02a2b43b2b

Tree-SHA512: 4d701756a42b832f03b8d542f3a5278b4ca1d5983ffd7d4630577ebd4cc8f47029719f9018185e01fa459d8fb32426b5cb4d6b8d8b588ebbb7b65e4aeee94412
2022-10-17 18:24:11 +00:00
Riccardo Casatta be4a27a1f3
Merge rust-bitcoin/rust-bitcoin#1309: Add script to launch fuzzing continuosly
9eca3c58c5 Add script to launch fuzzing continuosly (Riccardo Casatta)

Pull request description:

  Continuosly cycle over fuzz targets running each for 1 hour.

  I use this script on a server of mine and maybe sharing the script incentives other doing the same

ACKs for top commit:
  apoelstra:
    ACK 9eca3c58c5
  sanket1729:
    ACK 9eca3c58c5. I do have the resources to actually run it, but I successfully ran it locally with 5 sec cycle for testing.

Tree-SHA512: 23f24039bc32c091ea287ada9335e13bb81ae286cd8d42ab1a2b551c3dd8ba55c6d0c0051d9032baa169354786e77d257d6471f7255981a160bfd1695300201c
2022-10-13 11:59:53 +02:00
Riccardo Casatta abc1d473b1
Merge rust-bitcoin/rust-bitcoin#1315: Fix `test_data` dir exclusion
13e9a133df fix test_data dir exclusion (Riccardo Casatta)

Pull request description:

  I noted our released crate `0.29.1` was bigger than expected and noted with `cargo package --list` that even with our exclude the `test_data` dir was included. I am also going to backport this.

  As specified in the doc:

  `foo/` matches any directory with the name `foo` anywhere in the package.

ACKs for top commit:
  apoelstra:
    ACK 13e9a133df
  sanket1729:
    ACK 13e9a133df

Tree-SHA512: 298c1a50f3914dec19600529daee1978f47dc47ce288fdb5c575cd67a5c24421990dcf379b81b3637917d2d17b8585b853092e9970803959b22f36c0133e1b19
2022-10-13 11:59:11 +02:00
Riccardo Casatta 13e9a133df
fix test_data dir exclusion
As specified in the doc:

`foo/` matches any directory with the name `foo` anywhere in the package.
2022-10-11 12:18:37 +02:00
Riccardo Casatta 9eca3c58c5
Add script to launch fuzzing continuosly 2022-10-10 11:45:54 +02:00
Noah d1b7dff094 return custom error from `Network::from_str` 2022-10-10 19:37:14 +11:00
Andrew Poelstra b6e3028ccf
Merge rust-bitcoin/rust-bitcoin#1312: Add `Script::builder` convenience function
2bae74688e Add `Script::builder` convenience function (Casey Rodarmor)

Pull request description:

  Add a convenience function to `Script` to create a new builder, so that `Builder` doesn't need to be imported. This is a pretty common pattern in Rust for types which have associated builders.

ACKs for top commit:
  sanket1729:
    reACK 2bae74688e
  apoelstra:
    ACK 2bae74688e

Tree-SHA512: 8ae8e6bbd2f078d2bd1727296633ee8beb0af2ebf5d333f24a1bacf6993f86a1f860cfe7f5ec91236d1b30eeb5df53719df4841f462a19ff86a63a037889f17c
2022-10-08 13:21:32 +00:00
Casey Rodarmor 2bae74688e Add `Script::builder` convenience function 2022-10-07 15:37:56 -07:00