put generics onto GenericScript and GenericScriptBuf
What changed, and why it matters
This commit is a purely internal refactoring of the Rust Bitcoin library's script types. It adds a generic type parameter to the existing GenericScript and GenericScriptBuf types so that future commits can distinguish different kinds of Bitcoin scripts (for example, redeem scripts versus witness scripts). The public-facing Script and ScriptBuf type aliases are unchanged, so ordinary users of the library should not notice any difference. There is no security fix or vulnerability here.
No security action needed. Treat as normal code-review/merge for a refactoring commit.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change introduces a phantom generic tag T to GenericScript
Changed components
primitives/src/script/borrowed.rsprimitives/src/script/owned.rsprimitives/src/script/mod.rsprimitives/src/script/tag.rsbitcoin/src/blockdata/script/mod.rsInspect captured patch +133 / −106
diff --git a/bitcoin/src/blockdata/script/mod.rs b/bitcoin/src/blockdata/script/mod.rs
index 61527106..c6fbe44f 100644
--- a/bitcoin/src/blockdata/script/mod.rs
+++ b/bitcoin/src/blockdata/script/mod.rs
@@ -82,7 +82,8 @@ pub use self::{
};
#[doc(inline)]
pub use primitives::script::{
- RedeemScriptSizeError, Script, ScriptBuf, ScriptHash, WScriptHash, WitnessScriptSizeError,
+ RedeemScriptSizeError, Script, ScriptBuf, ScriptHash, Tag, WScriptHash, Whatever,
+ WitnessScriptSizeError,
};
pub(crate) use self::borrowed::ScriptExtPriv;
diff --git a/primitives/src/script/borrowed.rs b/primitives/src/script/borrowed.rs
index adeb5579..1a2f9c1d 100644
--- a/primitives/src/script/borrowed.rs
+++ b/primitives/src/script/borrowed.rs
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: CC0-1.0
+use core::marker::PhantomData;
use core::ops::{
Bound, Index, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive,
};
@@ -62,9 +63,9 @@ internals::transparent_newtype! {
/// * [CScript definition](https://github.com/bitcoin/bitcoin/blob/d492dc1cdaabdc52b0766bf4cba4bd73178325d0/src/script/script.h#L410)
///
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
- pub struct GenericScript([u8]);
+ pub struct GenericScript<T>(PhantomData<T>, [u8]);
- impl GenericScript {
+ impl<T> GenericScript<T> {
/// Treat byte slice as `GenericScript`
pub const fn from_bytes(bytes: &_) -> &Self;
@@ -77,19 +78,19 @@ internals::transparent_newtype! {
}
}
-impl Default for &GenericScript {
+impl<T: 'static> Default for &GenericScript<T> {
#[inline]
fn default() -> Self { GenericScript::new() }
}
-impl ToOwned for GenericScript {
- type Owned = GenericScriptBuf;
+impl<T> ToOwned for GenericScript<T> {
+ type Owned = GenericScriptBuf<T>;
#[inline]
fn to_owned(&self) -> Self::Owned { GenericScriptBuf::from_bytes(self.to_vec()) }
}
-impl GenericScript {
+impl<T> GenericScript<T> {
/// Constructs a new empty script.
#[inline]
pub const fn new() -> &'static Self { Self::from_bytes(&[]) }
@@ -98,13 +99,13 @@ impl GenericScript {
///
/// This is just the script bytes **not** consensus encoding (which includes a length prefix).
#[inline]
- pub const fn as_bytes(&self) -> &[u8] { &self.0 }
+ pub const fn as_bytes(&self) -> &[u8] { &self.1 }
/// Returns the script data as a mutable byte slice.
///
/// This is just the script bytes **not** consensus encoding (which includes a length prefix).
#[inline]
- pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.0 }
+ pub fn as_mut_bytes(&mut self) -> &mut [u8] { &mut self.1 }
/// Returns a copy of the script data.
///
@@ -128,7 +129,7 @@ impl GenericScript {
/// Converts a [`Box<GenericScript>`](Box) into a [`GenericScriptBuf`] without copying or allocating.
#[must_use]
#[inline]
- pub fn into_script_buf(self: Box<Self>) -> GenericScriptBuf {
+ pub fn into_script_buf(self: Box<Self>) -> GenericScriptBuf<T> {
let rw = Box::into_raw(self) as *mut [u8];
// SAFETY: copied from `std`
// The pointer was just created from a box without deallocating
@@ -152,7 +153,7 @@ impl GenericScript {
}
#[cfg(feature = "arbitrary")]
-impl<'a> Arbitrary<'a> for &'a GenericScript {
+impl<'a, T> Arbitrary<'a> for &'a GenericScript<T> {
#[inline]
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let v = <&'a [u8]>::arbitrary(u)?;
@@ -164,7 +165,7 @@ macro_rules! delegate_index {
($($type:ty),* $(,)?) => {
$(
/// [`GenericScript`] subslicing operation - read [slicing safety](#slicing-safety)!
- impl Index<$type> for GenericScript {
+ impl<T> Index<$type> for GenericScript<T> {
type Output = Self;
#[inline]
diff --git a/primitives/src/script/mod.rs b/primitives/src/script/mod.rs
index d985b402..1e2110b0 100644
--- a/primitives/src/script/mod.rs
+++ b/primitives/src/script/mod.rs
@@ -4,10 +4,13 @@
mod borrowed;
mod owned;
+mod tag;
use core::cmp::Ordering;
use core::convert::Infallible;
use core::fmt;
+#[cfg(feature = "serde")]
+use core::marker::PhantomData;
use hashes::{hash160, sha256};
#[cfg(feature = "hex")]
@@ -27,13 +30,14 @@ use crate::prelude::{Borrow, BorrowMut, Box, Cow, ToOwned, Vec};
pub use self::{
borrowed::GenericScript,
owned::GenericScriptBuf,
+ tag::{Tag, Whatever},
};
/// Placeholder doc (will be replaced in later commit)
-pub type Script = GenericScript;
+pub type Script = GenericScript<Whatever>;
/// Placeholder doc (will be replaced in later commit)
-pub type ScriptBuf = GenericScriptBuf;
+pub type ScriptBuf = GenericScriptBuf<Whatever>;
/// The maximum allowed redeem script size for a P2SH output.
pub const MAX_REDEEM_SCRIPT_SIZE: usize = 520;
@@ -237,19 +241,19 @@ impl std::error::Error for WitnessScriptSizeError {}
// We keep all the `GenericScript` and `GenericScriptBuf` impls together since it's easier to see side-by-side.
-impl From<GenericScriptBuf> for Box<GenericScript> {
+impl<T> From<GenericScriptBuf<T>> for Box<GenericScript<T>> {
#[inline]
- fn from(v: GenericScriptBuf) -> Self { v.into_boxed_script() }
+ fn from(v: GenericScriptBuf<T>) -> Self { v.into_boxed_script() }
}
-impl From<GenericScriptBuf> for Cow<'_, GenericScript> {
+impl<T> From<GenericScriptBuf<T>> for Cow<'_, GenericScript<T>> {
#[inline]
- fn from(value: GenericScriptBuf) -> Self { Cow::Owned(value) }
+ fn from(value: GenericScriptBuf<T>) -> Self { Cow::Owned(value) }
}
-impl<'a> From<Cow<'a, GenericScript>> for GenericScriptBuf {
+impl<'a, T> From<Cow<'a, GenericScript<T>>> for GenericScriptBuf<T> {
#[inline]
- fn from(value: Cow<'a, GenericScript>) -> Self {
+ fn from(value: Cow<'a, GenericScript<T>>) -> Self {
match value {
Cow::Owned(owned) => owned,
Cow::Borrowed(borrowed) => borrowed.into(),
@@ -257,9 +261,9 @@ impl<'a> From<Cow<'a, GenericScript>> for GenericScriptBuf {
}
}
-impl<'a> From<Cow<'a, GenericScript>> for Box<GenericScript> {
+impl<'a, T> From<Cow<'a, GenericScript<T>>> for Box<GenericScript<T>> {
#[inline]
- fn from(value: Cow<'a, GenericScript>) -> Self {
+ fn from(value: Cow<'a, GenericScript<T>>) -> Self {
match value {
Cow::Owned(owned) => owned.into(),
Cow::Borrowed(borrowed) => borrowed.into(),
@@ -267,88 +271,88 @@ impl<'a> From<Cow<'a, GenericScript>> for Box<GenericScript> {
}
}
-impl<'a> From<&'a GenericScript> for Box<GenericScript> {
+impl<'a, T> From<&'a GenericScript<T>> for Box<GenericScript<T>> {
#[inline]
- fn from(value: &'a GenericScript) -> Self { value.to_owned().into() }
+ fn from(value: &'a GenericScript<T>) -> Self { value.to_owned().into() }
}
-impl<'a> From<&'a GenericScript> for GenericScriptBuf {
+impl<'a, T> From<&'a GenericScript<T>> for GenericScriptBuf<T> {
#[inline]
- fn from(value: &'a GenericScript) -> Self { value.to_owned() }
+ fn from(value: &'a GenericScript<T>) -> Self { value.to_owned() }
}
-impl<'a> From<&'a GenericScript> for Cow<'a, GenericScript> {
+impl<'a, T> From<&'a GenericScript<T>> for Cow<'a, GenericScript<T>> {
#[inline]
- fn from(value: &'a GenericScript) -> Self { Cow::Borrowed(value) }
+ fn from(value: &'a GenericScript<T>) -> Self { Cow::Borrowed(value) }
}
/// Note: This will fail to compile on old Rust for targets that don't support atomics
#[cfg(target_has_atomic = "ptr")]
-impl<'a> From<&'a GenericScript> for Arc<GenericScript> {
+impl<'a, T> From<&'a GenericScript<T>> for Arc<GenericScript<T>> {
#[inline]
- fn from(value: &'a GenericScript) -> Self {
+ fn from(value: &'a GenericScript<T>) -> Self {
GenericScript::from_arc_bytes(Arc::from(value.as_bytes()))
}
}
-impl<'a> From<&'a GenericScript> for Rc<GenericScript> {
+impl<'a, T> From<&'a GenericScript<T>> for Rc<GenericScript<T>> {
#[inline]
- fn from(value: &'a GenericScript) -> Self {
+ fn from(value: &'a GenericScript<T>) -> Self {
GenericScript::from_rc_bytes(Rc::from(value.as_bytes()))
}
}
-impl From<Vec<u8>> for GenericScriptBuf {
+impl<T> From<Vec<u8>> for GenericScriptBuf<T> {
#[inline]
- fn from(v: Vec<u8>) -> Self { GenericScriptBuf::from_bytes(v) }
+ fn from(v: Vec<u8>) -> Self { Self::from_bytes(v) }
}
-impl From<GenericScriptBuf> for Vec<u8> {
+impl<T> From<GenericScriptBuf<T>> for Vec<u8> {
#[inline]
- fn from(v: GenericScriptBuf) -> Self { v.into_bytes() }
+ fn from(v: GenericScriptBuf<T>) -> Self { v.into_bytes() }
}
-impl AsRef<GenericScript> for GenericScript {
+impl<T> AsRef<GenericScript<T>> for GenericScript<T> {
#[inline]
fn as_ref(&self) -> &Self { self }
}
-impl AsRef<GenericScript> for GenericScriptBuf {
+impl<T> AsRef<GenericScript<T>> for GenericScriptBuf<T> {
#[inline]
- fn as_ref(&self) -> &GenericScript { self }
+ fn as_ref(&self) -> &GenericScript<T> { self }
}
-impl AsRef<[u8]> for GenericScript {
+impl<T> AsRef<[u8]> for GenericScript<T> {
#[inline]
fn as_ref(&self) -> &[u8] { self.as_bytes() }
}
-impl AsRef<[u8]> for GenericScriptBuf {
+impl<T> AsRef<[u8]> for GenericScriptBuf<T> {
#[inline]
fn as_ref(&self) -> &[u8] { self.as_bytes() }
}
-impl AsMut<GenericScript> for GenericScript {
+impl<T> AsMut<GenericScript<T>> for GenericScript<T> {
#[inline]
fn as_mut(&mut self) -> &mut Self { self }
}
-impl AsMut<GenericScript> for GenericScriptBuf {
+impl<T> AsMut<GenericScript<T>> for GenericScriptBuf<T> {
#[inline]
- fn as_mut(&mut self) -> &mut GenericScript { self }
+ fn as_mut(&mut self) -> &mut GenericScript<T> { self }
}
-impl AsMut<[u8]> for GenericScript {
+impl<T> AsMut<[u8]> for GenericScript<T> {
#[inline]
fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
}
-impl AsMut<[u8]> for GenericScriptBuf {
+impl<T> AsMut<[u8]> for GenericScriptBuf<T> {
#[inline]
fn as_mut(&mut self) -> &mut [u8] { self.as_mut_bytes() }
}
-impl fmt::Debug for GenericScript {
+impl<T> fmt::Debug for GenericScript<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("GenericScript(")?;
fmt::Display::fmt(self, f)?;
@@ -356,12 +360,12 @@ impl fmt::Debug for GenericScript {
}
}
-impl fmt::Debug for GenericScriptBuf {
+impl<T> fmt::Debug for GenericScriptBuf<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Debug::fmt(self.as_script(), f) }
}
-impl fmt::Display for GenericScript {
+impl<T> fmt::Display for GenericScript<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// This has to be a macro because it needs to break the loop
macro_rules! read_push_data_len {
@@ -434,13 +438,13 @@ impl fmt::Display for GenericScript {
}
}
-impl fmt::Display for GenericScriptBuf {
+impl<T> fmt::Display for GenericScriptBuf<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(self.as_script(), f) }
}
#[cfg(feature = "hex")]
-impl fmt::LowerHex for GenericScript {
+impl<T> fmt::LowerHex for GenericScript<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::LowerHex::fmt(&self.as_bytes().as_hex(), f)
@@ -448,13 +452,13 @@ impl fmt::LowerHex for GenericScript {
}
#[cfg(feature = "hex")]
-impl fmt::LowerHex for GenericScriptBuf {
+impl<T> fmt::LowerHex for GenericScriptBuf<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(self.as_script(), f) }
}
#[cfg(feature = "hex")]
-impl fmt::UpperHex for GenericScript {
+impl<T> fmt::UpperHex for GenericScript<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::UpperHex::fmt(&self.as_bytes().as_hex(), f)
@@ -462,47 +466,47 @@ impl fmt::UpperHex for GenericScript {
}
#[cfg(feature = "hex")]
-impl fmt::UpperHex for GenericScriptBuf {
+impl<T> fmt::UpperHex for GenericScriptBuf<T> {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::UpperHex::fmt(self.as_script(), f) }
}
-impl Borrow<GenericScript> for GenericScriptBuf {
+impl<T> Borrow<GenericScript<T>> for GenericScriptBuf<T> {
#[inline]
- fn borrow(&self) -> &GenericScript { self }
+ fn borrow(&self) -> &GenericScript<T> { self }
}
-impl BorrowMut<GenericScript> for GenericScriptBuf {
+impl<T> BorrowMut<GenericScript<T>> for GenericScriptBuf<T> {
#[inline]
- fn borrow_mut(&mut self) -> &mut GenericScript { self }
+ fn borrow_mut(&mut self) -> &mut GenericScript<T> { self }
}
-impl PartialEq<GenericScriptBuf> for GenericScript {
+impl<T: PartialEq> PartialEq<GenericScriptBuf<T>> for GenericScript<T> {
#[inline]
- fn eq(&self, other: &GenericScriptBuf) -> bool { self.eq(other.as_script()) }
+ fn eq(&self, other: &GenericScriptBuf<T>) -> bool { self.eq(other.as_script()) }
}
-impl PartialEq<GenericScript> for GenericScriptBuf {
+impl<T: PartialEq> PartialEq<GenericScript<T>> for GenericScriptBuf<T> {
#[inline]
- fn eq(&self, other: &GenericScript) -> bool { self.as_script().eq(other) }
+ fn eq(&self, other: &GenericScript<T>) -> bool { self.as_script().eq(other) }
}
-impl PartialOrd<GenericScript> for GenericScriptBuf {
+impl<T: PartialOrd> PartialOrd<GenericScript<T>> for GenericScriptBuf<T> {
#[inline]
- fn partial_cmp(&self, other: &GenericScript) -> Option<Ordering> {
+ fn partial_cmp(&self, other: &GenericScript<T>) -> Option<Ordering> {
self.as_script().partial_cmp(other)
}
}
-impl PartialOrd<GenericScriptBuf> for GenericScript {
+impl<T: PartialOrd> PartialOrd<GenericScriptBuf<T>> for GenericScript<T> {
#[inline]
- fn partial_cmp(&self, other: &GenericScriptBuf) -> Option<Ordering> {
+ fn partial_cmp(&self, other: &GenericScriptBuf<T>) -> Option<Ordering> {
self.partial_cmp(other.as_script())
}
}
#[cfg(feature = "serde")]
-impl serde::Serialize for GenericScript {
+impl<T> serde::Serialize for GenericScript<T> {
/// User-facing serialization for `GenericScript`.
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -518,14 +522,14 @@ impl serde::Serialize for GenericScript {
/// Can only deserialize borrowed bytes.
#[cfg(feature = "serde")]
-impl<'de> serde::Deserialize<'de> for &'de GenericScript {
+impl<'de, T> serde::Deserialize<'de> for &'de GenericScript<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
- struct Visitor;
- impl<'de> serde::de::Visitor<'de> for Visitor {
- type Value = &'de GenericScript;
+ struct Visitor<T>(PhantomData<T>);
+ impl<'de, T: 'de> serde::de::Visitor<'de> for Visitor<T> {
+ type Value = &'de GenericScript<T>;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("borrowed bytes")
@@ -547,12 +551,12 @@ impl<'de> serde::Deserialize<'de> for &'de GenericScript {
));
}
- deserializer.deserialize_bytes(Visitor)
+ deserializer.deserialize_bytes(Visitor(PhantomData))
}
}
#[cfg(feature = "serde")]
-impl serde::Serialize for GenericScriptBuf {
+impl<T> serde::Serialize for GenericScriptBuf<T> {
/// User-facing serialization for `GenericScript`.
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
@@ -563,7 +567,7 @@ impl serde::Serialize for GenericScriptBuf {
}
#[cfg(feature = "serde")]
-impl<'de> serde::Deserialize<'de> for GenericScriptBuf {
+impl<'de, T> serde::Deserialize<'de> for GenericScriptBuf<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
@@ -573,9 +577,9 @@ impl<'de> serde::Deserialize<'de> for GenericScriptBuf {
use hex::FromHex;
if deserializer.is_human_readable() {
- struct Visitor;
- impl serde::de::Visitor<'_> for Visitor {
- type Value = GenericScriptBuf;
+ struct Visitor<T>(PhantomData<T>);
+ impl<T> serde::de::Visitor<'_> for Visitor<T> {
+ type Value = GenericScriptBuf<T>;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("a script hex")
@@ -589,12 +593,12 @@ impl<'de> serde::Deserialize<'de> for GenericScriptBuf {
Ok(GenericScriptBuf::from(v))
}
}
- deserializer.deserialize_str(Visitor)
+ deserializer.deserialize_str(Visitor(PhantomData))
} else {
- struct BytesVisitor;
+ struct BytesVisitor<T>(PhantomData<T>);
- impl serde::de::Visitor<'_> for BytesVisitor {
- type Value = GenericScriptBuf;
+ impl<T> serde::de::Visitor<'_> for BytesVisitor<T> {
+ type Value = GenericScriptBuf<T>;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str("a script Vec<u8>")
@@ -614,7 +618,7 @@ impl<'de> serde::Deserialize<'de> for GenericScriptBuf {
Ok(GenericScriptBuf::from(v))
}
}
- deserializer.deserialize_byte_buf(BytesVisitor)
+ deserializer.deserialize_byte_buf(BytesVisitor(PhantomData))
}
}
}
diff --git a/primitives/src/script/owned.rs b/primitives/src/script/owned.rs
index 4eac2651..769535bb 100644
--- a/primitives/src/script/owned.rs
+++ b/primitives/src/script/owned.rs
@@ -1,20 +1,21 @@
// SPDX-License-Identifier: CC0-1.0
+use core::marker::PhantomData;
use core::ops::{Deref, DerefMut};
#[cfg(feature = "arbitrary")]
use arbitrary::{Arbitrary, Unstructured};
-use super::Script;
+use super::GenericScript;
use crate::prelude::{Box, Vec};
/// An owned, growable script.
///
/// `GenericScriptBuf` is the most common script type that has the ownership over the contents of the
-/// script. It has a close relationship with its borrowed counterpart, [`Script`].
+/// script. It has a close relationship with its borrowed counterpart, [`GenericScript`].
///
/// Just as other similar types, this implements [`Deref`], so [deref coercions] apply. Also note
-/// that all the safety/validity restrictions that apply to [`Script`] apply to `GenericScriptBuf` as well.
+/// that all the safety/validity restrictions that apply to [`GenericScript`] apply to `GenericScriptBuf` as well.
///
/// # Hexadecimal strings
///
@@ -26,10 +27,10 @@ use crate::prelude::{Box, Vec};
///
/// [`examples/script.rs`]: <https://github.com/rust-bitcoin/rust-bitcoin/blob/master/bitcoin/examples/script.rs>
/// [deref coercions]: https://doc.rust-lang.org/std/ops/trait.Deref.html#more-on-deref-coercion
-#[derive(Default, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
-pub struct GenericScriptBuf(Vec<u8>);
+#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
+pub struct GenericScriptBuf<T>(PhantomData<T>, Vec<u8>);
-impl GenericScriptBuf {
+impl<T> GenericScriptBuf<T> {
/// Constructs a new empty script.
#[inline]
pub const fn new() -> Self { Self::from_bytes(Vec::new()) }
@@ -39,15 +40,17 @@ impl GenericScriptBuf {
/// This method doesn't (re)allocate. `bytes` is just the script bytes **not** consensus
/// encoding (i.e no length prefix).
#[inline]
- pub const fn from_bytes(bytes: Vec<u8>) -> Self { Self(bytes) }
+ pub const fn from_bytes(bytes: Vec<u8>) -> Self { Self(PhantomData, bytes) }
/// Returns a reference to unsized script.
#[inline]
- pub fn as_script(&self) -> &Script { Script::from_bytes(&self.0) }
+ pub fn as_script(&self) -> &GenericScript<T> { GenericScript::from_bytes(&self.1) }
/// Returns a mutable reference to unsized script.
#[inline]
- pub fn as_mut_script(&mut self) -> &mut Script { Script::from_bytes_mut(&mut self.0) }
+ pub fn as_mut_script(&mut self) -> &mut GenericScript<T> {
+ GenericScript::from_bytes_mut(&mut self.1)
+ }
/// Converts the script into a byte vector.
///
@@ -57,9 +60,9 @@ impl GenericScriptBuf {
///
/// Just the script bytes **not** consensus encoding (which includes a length prefix).
#[inline]
- pub fn into_bytes(self) -> Vec<u8> { self.0 }
+ pub fn into_bytes(self) -> Vec<u8> { self.1 }
- /// Converts this `GenericScriptBuf` into a [boxed](Box) [`Script`].
+ /// Converts this `GenericScriptBuf` into a [boxed](Box) [`GenericScript`].
///
/// This method reallocates if the capacity is greater than length of the script but should not
/// when they are equal. If you know beforehand that you need to create a script of exact size
@@ -67,15 +70,13 @@ impl GenericScriptBuf {
/// reallocation can be avoided.
#[must_use]
#[inline]
- pub fn into_boxed_script(self) -> Box<Script> {
- Script::from_boxed_bytes(self.into_bytes().into_boxed_slice())
+ pub fn into_boxed_script(self) -> Box<GenericScript<T>> {
+ GenericScript::from_boxed_bytes(self.into_bytes().into_boxed_slice())
}
/// Constructs a new empty script with at least the specified capacity.
#[inline]
- pub fn with_capacity(capacity: usize) -> Self {
- GenericScriptBuf::from_bytes(Vec::with_capacity(capacity))
- }
+ pub fn with_capacity(capacity: usize) -> Self { Self::from_bytes(Vec::with_capacity(capacity)) }
/// Pre-allocates at least `additional_len` bytes if needed.
///
@@ -88,7 +89,7 @@ impl GenericScriptBuf {
///
/// Panics if the new capacity exceeds `isize::MAX bytes`.
#[inline]
- pub fn reserve(&mut self, additional_len: usize) { self.0.reserve(additional_len); }
+ pub fn reserve(&mut self, additional_len: usize) { self.1.reserve(additional_len); }
/// Pre-allocates exactly `additional_len` bytes if needed.
///
@@ -104,13 +105,13 @@ impl GenericScriptBuf {
///
/// Panics if the new capacity exceeds `isize::MAX bytes`.
#[inline]
- pub fn reserve_exact(&mut self, additional_len: usize) { self.0.reserve_exact(additional_len); }
+ pub fn reserve_exact(&mut self, additional_len: usize) { self.1.reserve_exact(additional_len); }
/// Returns the number of **bytes** available for writing without reallocation.
///
/// It is guaranteed that `script.capacity() >= script.len()` always holds.
#[inline]
- pub fn capacity(&self) -> usize { self.0.capacity() }
+ pub fn capacity(&self) -> usize { self.1.capacity() }
/// Gets the hex representation of this script.
///
@@ -125,24 +126,29 @@ impl GenericScriptBuf {
pub fn to_hex(&self) -> alloc::string::String { alloc::format!("{:x}", self) }
}
-impl Deref for GenericScriptBuf {
- type Target = Script;
+// Cannot derive due to generics.
+impl<T> Default for GenericScriptBuf<T> {
+ fn default() -> Self { Self(PhantomData, Vec::new()) }
+}
+
+impl<T> Deref for GenericScriptBuf<T> {
+ type Target = GenericScript<T>;
#[inline]
fn deref(&self) -> &Self::Target { self.as_script() }
}
-impl DerefMut for GenericScriptBuf {
+impl<T> DerefMut for GenericScriptBuf<T> {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target { self.as_mut_script() }
}
#[cfg(feature = "arbitrary")]
-impl<'a> Arbitrary<'a> for GenericScriptBuf {
+impl<'a, T> Arbitrary<'a> for GenericScriptBuf<T> {
#[inline]
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
let v = Vec::<u8>::arbitrary(u)?;
- Ok(GenericScriptBuf::from_bytes(v))
+ Ok(Self::from_bytes(v))
}
}
diff --git a/primitives/src/script/tag.rs b/primitives/src/script/tag.rs
new file mode 100644
index 00000000..6383c026
--- /dev/null
+++ b/primitives/src/script/tag.rs
@@ -0,0 +1,15 @@
+// SPDX-License-Identifier: CC0-1.0
+
+//! Script tags.
+//!
+//! Tags are used to differentiate the different kinds of scripts that appear
+//! in Bitcoin transactions.
+
+/// Sealed trait representing a type of script.
+pub trait Tag {}
+
+/// Placeholder tag.
+#[derive(Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
+pub enum Whatever {}
+
+impl Tag for Whatever {}
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.