-
Notifications
You must be signed in to change notification settings - Fork 37
Improve types on AssetIssuance struct
#289
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
f3094b5
426dfc0
c081826
02122be
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||
| // Rust Elements Library | ||||||
| // Rust Elements Libraryss | ||||||
| // Written in 2019 by | ||||||
| // The Elements developers | ||||||
| // | ||||||
|
|
@@ -14,8 +14,10 @@ | |||||
|
|
||||||
| //! Asset Issuance | ||||||
|
|
||||||
| use core::fmt; | ||||||
| use std::io; | ||||||
|
|
||||||
| use crate::confidential::AssetBlindingFactor; | ||||||
| use crate::encode::{self, Encodable, Decodable}; | ||||||
| use crate::hashes::{hash_newtype, sha256, sha256d}; | ||||||
| use crate::fast_merkle_root::fast_merkle_root; | ||||||
|
|
@@ -51,6 +53,158 @@ impl_sha256_midstate_wrapper! { | |||||
| pub struct AssetEntropy([u8; 32]); | ||||||
| } | ||||||
|
|
||||||
| impl AssetEntropy { | ||||||
| /// The all-zeroes "entropy" used for new issuances (vs reissuances). | ||||||
| pub const NEW_ISSUANCE: Self = Self([0; 32]); | ||||||
|
|
||||||
| /// Re-interpret the asset entropy as a contract hash. | ||||||
| pub fn into_contract_hash(self) -> ContractHash { | ||||||
| ContractHash::from_byte_array(self.0) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| impl Encodable for AssetEntropy { | ||||||
| fn consensus_encode<W: io::Write>(&self, e: W) -> Result<usize, encode::Error> { | ||||||
| self.0.consensus_encode(e) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| impl Decodable for AssetEntropy { | ||||||
| fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> { | ||||||
| <[u8; 32]>::consensus_decode(d).map(Self) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| encoding::encoder_newtype_exact! { | ||||||
| /// Encoder for the [`OutPoint`] type. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| #[derive(Clone, Debug)] | ||||||
| pub struct AssetEntropyEncoder<'e>(encoding::ArrayRefEncoder<'e, 32>); | ||||||
| } | ||||||
|
|
||||||
| impl encoding::Encode for AssetEntropy { | ||||||
| type Encoder<'e> = AssetEntropyEncoder<'e>; | ||||||
|
|
||||||
| fn encoder(&self) -> Self::Encoder<'_> { | ||||||
| AssetEntropyEncoder::new(encoding::ArrayRefEncoder::without_length_prefix(&self.0)) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| decoder_newtype! { | ||||||
| /// Decoder for the [`AssetEntropy`] type. | ||||||
| #[derive(Default)] | ||||||
| pub struct AssetEntropyDecoder(encoding::ArrayDecoder<32>); | ||||||
|
|
||||||
| /// Decoder error for the [`AssetEntropy`] type. | ||||||
| #[derive(Clone, PartialEq, Eq, Debug)] | ||||||
| pub struct AssetEntropyDecoderError(encoding::UnexpectedEofError); | ||||||
| const ERROR_DISPLAY = "error decoding asset entropy"; | ||||||
|
|
||||||
| impl Decode for AssetEntropy { | ||||||
| fn convert_inner(bytes) -> Result<_, UnexpectedEofError> { | ||||||
| Ok(AssetEntropy::from_byte_array(bytes)) | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| /// The blinding factor used to derive an asset commitment from an asset. | ||||||
| /// | ||||||
| /// This type represents either [`Self::NEW_ISSUANCE`], indicating that an asset | ||||||
| /// issuance is of a new asset, or for a reissuance, the [`AssetBlindingFactor`] | ||||||
| /// used to blind the reissuance token (which must be blinded in order to be | ||||||
| /// spent, due to a quirk in the Elements consensus code.) | ||||||
| /// | ||||||
| /// Conceputally this can be thought of as an `Option<AssetBlindingFactor>`, except | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| /// that there are no invalid values; [`AssetBlindingNonce::from_byte_array`] will | ||||||
| /// always succeed. However, if an out-of-range value is used, the transaction will | ||||||
| /// fail validation no matter what reissuance token is used. | ||||||
| /// | ||||||
| /// Also, **unlike [`AssetBlindingFactor`], this type represents public data**. You | ||||||
| /// can convert a blinding factor into a "blinding nonce", and while this conversion | ||||||
| /// is technically a no-op, conceptually it represents choosing to make the blinding | ||||||
| /// factor public. | ||||||
| #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord, Default)] | ||||||
| pub struct AssetBlindingNonce([u8; 32]); | ||||||
|
|
||||||
| impl AssetBlindingNonce { | ||||||
| /// A null blinding nonce, representing a new issuance (vs a reissuance). | ||||||
| pub const NEW_ISSUANCE: Self = Self([0; 32]); | ||||||
|
|
||||||
| /// Constructs this wrapper struct from raw bytes. | ||||||
| pub const fn from_byte_array(inner: [u8; 32]) -> Self { | ||||||
| Self(inner) | ||||||
| } | ||||||
|
|
||||||
| /// The raw bytes within the wrapper type. | ||||||
| pub const fn as_byte_array(&self) -> &[u8; 32] { | ||||||
| &self.0 | ||||||
| } | ||||||
|
|
||||||
| /// The raw bytes within the wrapper type. | ||||||
| pub const fn to_byte_array(self) -> [u8; 32] { | ||||||
| self.0 | ||||||
| } | ||||||
|
|
||||||
| /// Whether this is the null "new issuance" blinding nonce. | ||||||
| pub fn is_null(&self) -> bool { | ||||||
| // This is surprisingly annoying to make into a constfn, so we don't | ||||||
| // bother for now. | ||||||
| *self == Self::NEW_ISSUANCE | ||||||
| } | ||||||
|
|
||||||
| /// Reinterpret an asset blinding factor as a [`AssetBlindingNonce`]. | ||||||
| /// | ||||||
| /// This is something of a dangerous function, since in general blinding factors should | ||||||
| /// be considered secret data, while blinding nonces are public (they are encoded on | ||||||
| /// the blockchain). So callers of this function should be sure that this is a blinding | ||||||
| /// factor that they intend to reveal.) | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| pub fn from_blinding_factor(bf: AssetBlindingFactor) -> Self { | ||||||
| Self(*bf.into_inner().as_ref()) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| impl Encodable for AssetBlindingNonce { | ||||||
| fn consensus_encode<W: io::Write>(&self, e: W) -> Result<usize, encode::Error> { | ||||||
| self.0.consensus_encode(e) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| impl Decodable for AssetBlindingNonce { | ||||||
| fn consensus_decode<D: io::Read>(d: D) -> Result<Self, encode::Error> { | ||||||
| <[u8; 32]>::consensus_decode(d).map(Self) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| encoding::encoder_newtype_exact! { | ||||||
| /// Encoder for the [`OutPoint`] type. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| #[derive(Clone, Debug)] | ||||||
| pub struct AssetBlindingNonceEncoder<'e>(encoding::ArrayRefEncoder<'e, 32>); | ||||||
| } | ||||||
|
|
||||||
| impl encoding::Encode for AssetBlindingNonce { | ||||||
| type Encoder<'e> = AssetBlindingNonceEncoder<'e>; | ||||||
|
|
||||||
| fn encoder(&self) -> Self::Encoder<'_> { | ||||||
| AssetBlindingNonceEncoder::new(encoding::ArrayRefEncoder::without_length_prefix(&self.0)) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| decoder_newtype! { | ||||||
| /// Decoder for the [`AssetBlindingNonce`] type. | ||||||
| #[derive(Default)] | ||||||
| pub struct AssetBlindingNonceDecoder(encoding::ArrayDecoder<32>); | ||||||
|
|
||||||
| /// Decoder error for the [`AssetBlindingNonce`] type. | ||||||
| #[derive(Clone, PartialEq, Eq, Debug)] | ||||||
| pub struct AssetBlindingNonceDecoderError(encoding::UnexpectedEofError); | ||||||
| const ERROR_DISPLAY = "error decoding asset blinding nonce"; | ||||||
|
|
||||||
| impl Decode for AssetBlindingNonce { | ||||||
| fn convert_inner(bytes) -> Result<_, UnexpectedEofError> { | ||||||
| Ok(AssetBlindingNonce::from_byte_array(bytes)) | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| impl_sha256_midstate_wrapper! { | ||||||
| /// An issued asset ID. | ||||||
| pub struct AssetId([u8; 32]); | ||||||
|
|
@@ -189,6 +343,37 @@ impl Decodable for AssetId { | |||||
| } | ||||||
| } | ||||||
|
|
||||||
| encoding::encoder_newtype_exact! { | ||||||
| /// Encoder for the [`OutPoint`] type. | ||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| #[derive(Clone, Debug)] | ||||||
| pub struct AssetIdEncoder<'e>(encoding::ArrayRefEncoder<'e, 32>); | ||||||
| } | ||||||
|
|
||||||
| impl encoding::Encode for AssetId { | ||||||
| type Encoder<'e> = AssetIdEncoder<'e>; | ||||||
|
|
||||||
| fn encoder(&self) -> Self::Encoder<'_> { | ||||||
| AssetIdEncoder::new(encoding::ArrayRefEncoder::without_length_prefix(&self.0)) | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| decoder_newtype! { | ||||||
| /// Decoder for the [`AssetId`] type. | ||||||
| #[derive(Default)] | ||||||
| pub struct AssetIdDecoder(encoding::ArrayDecoder<32>); | ||||||
|
|
||||||
| /// Decoder error for the [`AssetId`] type. | ||||||
| #[derive(Clone, PartialEq, Eq, Debug)] | ||||||
| pub struct AssetIdDecoderError(encoding::UnexpectedEofError); | ||||||
| const ERROR_DISPLAY = "error decoding asset ID"; | ||||||
|
|
||||||
| impl Decode for AssetId { | ||||||
| fn convert_inner(bytes) -> Result<_, UnexpectedEofError> { | ||||||
| Ok(AssetId::from_byte_array(bytes)) | ||||||
| } | ||||||
| } | ||||||
| } | ||||||
|
|
||||||
| #[cfg(test)] | ||||||
| mod test { | ||||||
| use super::*; | ||||||
|
|
||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo