What changed, and why it matters
This commit simply moves the project's coding-style policy guide from CONTRIBUTING.md into a new docs/policy.md file. It is a documentation reorganization with no code changes, no functional changes, and no security relevance.
No security action needed. Treat as routine documentation maintenance.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The diff is a pure documentation move: ~268 lines of policy text (import style, error conventions, rustdoc style, derives, attributes, licensing) are removed from CONTRIBUTING.md and added to docs/policy.md, with a one-line link added in CONTRIBUTING.md. No Rust source files, build scripts, CI workflows, or dependencies are modified.
Changed components
CONTRIBUTING.mddocs/policy.mdInspect captured patch +267 / −268
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 8e4cb090..3b579ca1 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -42,6 +42,7 @@ money. That being said, we deeply welcome people contributing for the first time
to an open source project or pick up Rust while contributing. Don't be shy,
you'll learn.
+For a more in depth discussion of our coding policy see [policy.md](./docs/policy.md)
## Communication channels
@@ -225,274 +226,6 @@ way that is not backwards compatible, the PR will be flagged as a breaking chang
Please check the [`semver-checks` workflow](.github/workflows/semver-checks.yml).
Under the hood we use [`cargo-semver-checks`](https://github.com/obi1kenobi/cargo-semver-checks).
-
-### Policy
-
-We have various `rust-bitcoin` specific coding styles and conventions that are
-grouped here loosely under the term 'policy'. These are things we try to adhere
-to but that you should not need to worry too much about if you are a new
-contributor. Think of this as a place to collect group knowledge that exists in
-the various PRs over the last few years.
-
-#### Import statements
-
-We use the following style for import statements, see
-(https://github.com/rust-bitcoin/rust-bitcoin/discussions/2088) for the discussion that led to this.
-
-```rust
-// Modules first, as they are part of the project's structure.
-pub mod aa_this;
-mod bb_private;
-pub mod cc_that;
-
-// Private imports, rustfmt will sort and merge them correctly.
-use crate::aa_this::{This, That};
-use crate::bb_that;
-
-// Public re-exports.
-#[rustfmt::skip] // Keeps public re-exports separate, because of this we have to sort manually.
-pub use {
- crate::aa_aa_this,
- crate::bb_bb::That,
-}
-
-// Avoid wildcard imports, except for 3 rules:
-
-// Rule 1 - test modules.
-#[cfg(test)]
-mod tests {
- use super::*; // OK
-}
-
-// Rule 2 - enum variants.
-use LockTime::*; // OK
-
-// Rule 3 - opcodes.
-use opcodes::all::*; // OK
-
-// Finally here is an example where we don't allow wildcard imports:
-use crate::prelude::*; // *NOT* OK
-use crate::prelude::{DisplayHex, String, Vec} // OK
-```
-
-#### Return `Self`
-
-Use `Self` as the return type instead of naming the type. When constructing the return value use
-`Self` or the type name, whichever you prefer.
-
-```rust
-/// A counter that is always smaller than 100.
-pub struct Counter(u32);
-
-impl Counter {
- /// Constructs a new `Counter`.
- pub fn new() -> Self { Self(0) }
-
- /// Returns a counter if it is possible to create one from x.
- pub fn maybe(x: u32) -> Option<Self> {
- match x {
- x if x >= 100 => None,
- c => Some(Counter(c)),
- }
- }
-}
-
-impl TryFrom<u32> for Counter {
- type Error = TooBigError;
-
- fn try_from(x: u32) -> Result<Self, Self::Error> {
- if x >= 100 {
- return Err(TooBigError);
- }
- Ok(Counter(x))
- }
-}
-```
-
-When constructing the return value for error enums use `Self`.
-
-```rust
-impl From<foo::Error> for LongDescriptiveError {
- fn from(e: foo::Error) -> Self { Self::Foo(e) }
-}
-```
-
-
-#### Errors
-
-Return as much context as possible with errors e.g., if an error was encountered parsing a string
-include the string in the returned error type. If a function consumes costly-to-compute input
-(allocations are also considered costly) it should return the input back in the error type.
-
-More specifically an error should
-
-- be `non_exhaustive` unless we _really_ never want to change it.
-- have private fields unless we are very confident they won't change.
-- derive `Debug, Clone, PartialEq, Eq` (and `Copy` if and only if not `non_exhaustive`).
-- implement Display using `write_err!()` macro if a variant contains an inner error source.
-- have `Error` suffix on error types (structs and enums).
-- not have `Error` suffix on enum variants.
-- call `internals::impl_from_infallible!`.
-- implement `std::error::Error` if they are public (feature gated on "std").
-- have messages in lower case, except for proper nouns and variable names.
-
-```rust
-/// Documentation for the `Error` type.
-#[derive(Debug, Clone, PartialEq, Eq)]
-#[non_exhaustive] // Add liberally; if the error type may ever have new variants added.
-pub enum Error {
- /// Documentation for variant A.
- A,
- /// Documentation for variant B.
- B,
-}
-
-internals::impl_from_infallible!(Error);
-
-```
-
-All errors that live in an `error` module (eg, `foo/error.rs`) and appear in a public function in
-`foo` module should be available from `foo` i.e., should be re-exported from `foo/mod.rs`.
-
-##### `expect` messages
-
-With respect to `expect` messages, they should follow the
-[Rust standard library guidelines](https://doc.rust-lang.org/std/option/enum.Option.html#recommended-message-style).
-More specifically, `expect` messages should be used to describe the reason
-you expect the operation to succeed.
-For example, this `expect` message clearly states why the operation should succeed:
-
-```rust
-/// Serializes the public key to bytes.
-pub fn to_bytes(self) -> Vec<u8> {
- let mut buf = Vec::new();
- self.write_into(&mut buf).expect("vecs don't error");
- buf
-}
-```
-
-Also note that `expect` messages, as with all error messages, should be lower
-case, except for proper nouns and variable names.
-
-<details>
-<summary>The details on why we chose this style</summary>
-
-According to the [Rust standard library](https://doc.rust-lang.org/std/error/index.html#common-message-styles),
-there are two common styles for how to write `expect` messages:
-
-- using the message to present information to users encountering a panic
- ("expect as error message"); and
-- using the message to present information to developers debugging the panic
- ("expect as precondition").
-
-We opted to use the "expect as precondition" since it clearly states why the
-operation should succeed.
-This may be better for communicating with developers, since they are the target
-audience for the error message and `rust-bitcoin`.
-
-If you want to know more about the decision error messages and expect messages,
-please check:
-
-- https://github.com/rust-bitcoin/rust-bitcoin/issues/2913
-- https://github.com/rust-bitcoin/rust-bitcoin/issues/3053
-- https://github.com/rust-bitcoin/rust-bitcoin/pull/3019
-</details>
-
-#### Rustdocs
-
-Be liberal with references to BIPs or other documentation; the aim is that devs can learn about
-Bitcoin by hacking on this codebase as opposed to having to learn about Bitcoin first and then start
-hacking on this codebase. Consider the following format, not all sections will be required for all types.
-
-
-```rust
-/// The Bitcoin foobar.
-///
-/// Contains all the data used when passing a foobar around the Bitcoin network.
-///
-/// <details>
-/// <summary>FooBar Original Design</summary>
-///
-/// The foobar was introduced in Bitcoin x.y.z to increase the amount of foo in bar.
-///
-/// </details>
-///
-/// ### Relevant BIPs
-///
-/// * [BIP X - FooBar in Bitcoin](https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki)
-pub struct FooBar {
- /// The version in use.
- pub version: Version
-}
-```
-
-Do use rustdoc subheadings. Do put an empty newline below each heading e.g.,
-
-```rust
-impl FooBar {
- /// Constructs a `FooBar` from a [`Baz`].
- ///
- /// # Errors
- ///
- /// Returns an error if `Baz` is not ...
- ///
- /// # Panics
- ///
- /// If the `Baz`, converted to a `usize`, is out of bounds.
- pub fn from_baz(baz: Baz) -> Result<Self, Error> {
- ...
- }
-}
-```
-
-Add Panics section if any input to the function can trigger a panic.
-
-Generally we prefer to have non-panicking APIs but it is impractical in some cases. If you're not
-sure, feel free to ask. If we determine panicking is more practical it must be documented. Internal
-panics that could theoretically occur because of bugs in our code must not be documented.
-
-Example code within the rustdocs should compile and lint with `just lint` without any errors or
-warnings.
-
-#### Derives
-
-We try to use standard set of derives if it makes sense:
-
-```
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-enum Foo {
- Bar,
- Baz,
-}
-```
-
-For types that do should not form a total or partial order, or that technically do but it does not
-make sense to compare them, we use the `Ordered` trait from the
-[`ordered`](https://crates.io/crates/ordered) crate. See `absolute::LockTime` for an example.
-
-For error types you likely want to use `#[derive(Debug, Clone, PartialEq, Eq)]`.
-
-See [Errors](#errors) section.
-
-
-#### Attributes
-
-- `#[track_caller]`: Used on functions that panic on invalid arguments
- (see https://rustc-dev-guide.rust-lang.org/backend/implicit-caller-location.html)
-
-- `#[cfg(rust_v_1_60)]`: Used to guard code that should only be built in if the toolchain is
- compatible. These configuration conditionals are set at build time in `bitcoin/build.rs`. New
- version attributes may be added as needed.
-
-
-#### Licensing
-
-We use SPDX license tags, all files should start with
-
-```
-// SPDX-License-Identifier: CC0-1.0
-```
-
## Security
Security is the primary focus for this library; disclosure of security
diff --git a/docs/policy.md b/docs/policy.md
new file mode 100644
index 00000000..f38a50a9
--- /dev/null
+++ b/docs/policy.md
@@ -0,0 +1,266 @@
+# Coding policy for the rust-bitcoin repository
+
+We have various `rust-bitcoin` specific coding styles and conventions that are
+grouped here loosely under the term 'policy'. These are things we try to adhere
+to but that you should not need to worry too much about if you are a new
+contributor. Think of this as a place to collect group knowledge that exists in
+the various PRs over the last few years.
+
+## Import statements
+
+We use the following style for import statements, see
+(https://github.com/rust-bitcoin/rust-bitcoin/discussions/2088) for the discussion that led to this.
+
+```rust
+// Modules first, as they are part of the project's structure.
+pub mod aa_this;
+mod bb_private;
+pub mod cc_that;
+
+// Private imports, rustfmt will sort and merge them correctly.
+use crate::aa_this::{This, That};
+use crate::bb_that;
+
+// Public re-exports.
+#[rustfmt::skip] // Keeps public re-exports separate, because of this we have to sort manually.
+pub use {
+ crate::aa_aa_this,
+ crate::bb_bb::That,
+}
+
+// Avoid wildcard imports, except for 3 rules:
+
+// Rule 1 - test modules.
+#[cfg(test)]
+mod tests {
+ use super::*; // OK
+}
+
+// Rule 2 - enum variants.
+use LockTime::*; // OK
+
+// Rule 3 - opcodes.
+use opcodes::all::*; // OK
+
+// Finally here is an example where we don't allow wildcard imports:
+use crate::prelude::*; // *NOT* OK
+use crate::prelude::{DisplayHex, String, Vec} // OK
+```
+
+## Return `Self`
+
+Use `Self` as the return type instead of naming the type. When constructing the return value use
+`Self` or the type name, whichever you prefer.
+
+```rust
+/// A counter that is always smaller than 100.
+pub struct Counter(u32);
+
+impl Counter {
+ /// Constructs a new `Counter`.
+ pub fn new() -> Self { Self(0) }
+
+ /// Returns a counter if it is possible to create one from x.
+ pub fn maybe(x: u32) -> Option<Self> {
+ match x {
+ x if x >= 100 => None,
+ c => Some(Counter(c)),
+ }
+ }
+}
+
+impl TryFrom<u32> for Counter {
+ type Error = TooBigError;
+
+ fn try_from(x: u32) -> Result<Self, Self::Error> {
+ if x >= 100 {
+ return Err(TooBigError);
+ }
+ Ok(Counter(x))
+ }
+}
+```
+
+When constructing the return value for error enums use `Self`.
+
+```rust
+impl From<foo::Error> for LongDescriptiveError {
+ fn from(e: foo::Error) -> Self { Self::Foo(e) }
+}
+```
+
+
+## Errors
+
+Return as much context as possible with errors e.g., if an error was encountered parsing a string
+include the string in the returned error type. If a function consumes costly-to-compute input
+(allocations are also considered costly) it should return the input back in the error type.
+
+More specifically an error should
+
+- be `non_exhaustive` unless we _really_ never want to change it.
+- have private fields unless we are very confident they won't change.
+- derive `Debug, Clone, PartialEq, Eq` (and `Copy` if and only if not `non_exhaustive`).
+- implement Display using `write_err!()` macro if a variant contains an inner error source.
+- have `Error` suffix on error types (structs and enums).
+- not have `Error` suffix on enum variants.
+- call `internals::impl_from_infallible!`.
+- implement `std::error::Error` if they are public (feature gated on "std").
+- have messages in lower case, except for proper nouns and variable names.
+
+```rust
+/// Documentation for the `Error` type.
+#[derive(Debug, Clone, PartialEq, Eq)]
+#[non_exhaustive] // Add liberally; if the error type may ever have new variants added.
+pub enum Error {
+ /// Documentation for variant A.
+ A,
+ /// Documentation for variant B.
+ B,
+}
+
+internals::impl_from_infallible!(Error);
+
+```
+
+All errors that live in an `error` module (eg, `foo/error.rs`) and appear in a public function in
+`foo` module should be available from `foo` i.e., should be re-exported from `foo/mod.rs`.
+
+## `expect` messages
+
+With respect to `expect` messages, they should follow the
+[Rust standard library guidelines](https://doc.rust-lang.org/std/option/enum.Option.html#recommended-message-style).
+More specifically, `expect` messages should be used to describe the reason
+you expect the operation to succeed.
+For example, this `expect` message clearly states why the operation should succeed:
+
+```rust
+/// Serializes the public key to bytes.
+pub fn to_bytes(self) -> Vec<u8> {
+ let mut buf = Vec::new();
+ self.write_into(&mut buf).expect("vecs don't error");
+ buf
+}
+```
+
+Also note that `expect` messages, as with all error messages, should be lower
+case, except for proper nouns and variable names.
+
+<details>
+<summary>The details on why we chose this style</summary>
+
+According to the [Rust standard library](https://doc.rust-lang.org/std/error/index.html#common-message-styles),
+there are two common styles for how to write `expect` messages:
+
+- using the message to present information to users encountering a panic
+ ("expect as error message"); and
+- using the message to present information to developers debugging the panic
+ ("expect as precondition").
+
+We opted to use the "expect as precondition" since it clearly states why the
+operation should succeed.
+This may be better for communicating with developers, since they are the target
+audience for the error message and `rust-bitcoin`.
+
+If you want to know more about the decision error messages and expect messages,
+please check:
+
+- https://github.com/rust-bitcoin/rust-bitcoin/issues/2913
+- https://github.com/rust-bitcoin/rust-bitcoin/issues/3053
+- https://github.com/rust-bitcoin/rust-bitcoin/pull/3019
+</details>
+
+## Rustdocs
+
+Be liberal with references to BIPs or other documentation; the aim is that devs can learn about
+Bitcoin by hacking on this codebase as opposed to having to learn about Bitcoin first and then start
+hacking on this codebase. Consider the following format, not all sections will be required for all types.
+
+
+```rust
+/// The Bitcoin foobar.
+///
+/// Contains all the data used when passing a foobar around the Bitcoin network.
+///
+/// <details>
+/// <summary>FooBar Original Design</summary>
+///
+/// The foobar was introduced in Bitcoin x.y.z to increase the amount of foo in bar.
+///
+/// </details>
+///
+/// ### Relevant BIPs
+///
+/// * [BIP X - FooBar in Bitcoin](https://github.com/bitcoin/bips/blob/master/bip-0001.mediawiki)
+pub struct FooBar {
+ /// The version in use.
+ pub version: Version
+}
+```
+
+Do use rustdoc subheadings. Do put an empty newline below each heading e.g.,
+
+```rust
+impl FooBar {
+ /// Constructs a `FooBar` from a [`Baz`].
+ ///
+ /// # Errors
+ ///
+ /// Returns an error if `Baz` is not ...
+ ///
+ /// # Panics
+ ///
+ /// If the `Baz`, converted to a `usize`, is out of bounds.
+ pub fn from_baz(baz: Baz) -> Result<Self, Error> {
+ ...
+ }
+}
+```
+
+Add Panics section if any input to the function can trigger a panic.
+
+Generally we prefer to have non-panicking APIs but it is impractical in some cases. If you're not
+sure, feel free to ask. If we determine panicking is more practical it must be documented. Internal
+panics that could theoretically occur because of bugs in our code must not be documented.
+
+Example code within the rustdocs should compile and lint with `just lint` without any errors or
+warnings.
+
+## Derives
+
+We try to use standard set of derives if it makes sense:
+
+```
+#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+enum Foo {
+ Bar,
+ Baz,
+}
+```
+
+For types that do should not form a total or partial order, or that technically do but it does not
+make sense to compare them, we use the `Ordered` trait from the
+[`ordered`](https://crates.io/crates/ordered) crate. See `absolute::LockTime` for an example.
+
+For error types you likely want to use `#[derive(Debug, Clone, PartialEq, Eq)]`.
+
+See [Errors](#errors) section.
+
+
+## Attributes
+
+- `#[track_caller]`: Used on functions that panic on invalid arguments
+ (see https://rustc-dev-guide.rust-lang.org/backend/implicit-caller-location.html)
+
+- `#[cfg(rust_v_1_60)]`: Used to guard code that should only be built in if the toolchain is
+ compatible. These configuration conditionals are set at build time in `bitcoin/build.rs`. New
+ version attributes may be added as needed.
+
+
+## Licensing
+
+We use SPDX license tags, all files should start with
+
+```
+// SPDX-License-Identifier: CC0-1.0
+```
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.