Skip to content

Commit e989537

Browse files
committed
Finalization of PSBT DBC-related API
1 parent 293a054 commit e989537

File tree

5 files changed

+47
-9
lines changed

5 files changed

+47
-9
lines changed

Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

psbt/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "psbt"
3-
version = "0.8.1"
3+
version = "0.8.4"
44
license = "Apache-2.0"
55
authors = ["Dr. Maxim Orlovsky <[email protected]>"]
66
description = "Partially signed bitcoin transaction v0-2 library (bip174, bip370, bip371)"

psbt/src/commit/lnpbp4.rs

+19
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
// If not, see <https://opensource.org/licenses/Apache-2.0>.
1515

1616
use amplify::Slice32;
17+
use bitcoin::hashes::Hash;
18+
use commit_verify::lnpbp4;
1719
use commit_verify::lnpbp4::{Message, ProtocolId};
1820
use strict_encoding::{StrictDecode, StrictEncode};
1921

@@ -160,6 +162,23 @@ impl Psbt {
160162
/// Extension trait for [`Output`] for working with proprietary LNPBP4
161163
/// keys.
162164
impl Output {
165+
/// Returns [`lnpbp4::MessageMap`] constructed from the proprietary key
166+
/// data.
167+
pub fn lnpbp4_message_map(&self) -> Result<lnpbp4::MessageMap, Lnpbp4KeyError> {
168+
self.proprietary
169+
.iter()
170+
.filter(|(key, _)| {
171+
key.prefix == PSBT_LNPBP4_PREFIX && key.subtype == PSBT_OUT_LNPBP4_MESSAGE
172+
})
173+
.map(|(key, val)| {
174+
Ok((
175+
ProtocolId::from_slice(&key.key).ok_or(Lnpbp4KeyError::InvalidKeyValue)?,
176+
Message::from_slice(val).map_err(|_| Lnpbp4KeyError::InvalidKeyValue)?,
177+
))
178+
})
179+
.collect()
180+
}
181+
163182
/// Returns a valid LNPBP-4 [`Message`] associated with the given
164183
/// [`ProtocolId`], if any.
165184
///

psbt/src/commit/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212
// along with this software.
1313
// If not, see <https://opensource.org/licenses/Apache-2.0>.
1414

15+
// TODO: Relocate to BP DBC library
16+
1517
//! Managing commitment-related proprietary keys inside PSBT.
1618
//!
1719
//! Supports Tapret, Opret, P2C and S2C commitments and LNPBP4 structures used

psbt/src/commit/tapret.rs

+24-7
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
//! commitments.
2626
2727
use amplify::Slice32;
28-
use bitcoin::util::taproot::TaprootMerkleBranch;
2928
use bitcoin_scripts::taproot::DfsPath;
3029
use strict_encoding::{StrictDecode, StrictEncode};
3130

@@ -93,7 +92,7 @@ impl ProprietaryKeyTapret for ProprietaryKey {}
9392

9493
/// Errors processing tapret-related proprietary PSBT keys and their values.
9594
#[derive(
96-
Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error
95+
Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display, Error, From
9796
)]
9897
#[display(doc_comments)]
9998
pub enum TapretKeyError {
@@ -104,6 +103,10 @@ pub enum TapretKeyError {
104103
/// the output is not marked to host tapret commitments. Please first set
105104
/// PSBT_OUT_TAPRET_HOST flag.
106105
TapretProhibited,
106+
107+
/// The key contains invalid value
108+
#[from(strict_encoding::Error)]
109+
InvalidKeyValue,
107110
}
108111

109112
/// Error decoding [`DfsPath`] inside PSBT data
@@ -189,8 +192,8 @@ impl Output {
189192
}
190193

191194
/// Assigns value of the tapreturn commitment to this PSBT output, by
192-
/// adding [`PSBT_OUT_TAPRET_COMMITMENT`] proprietary key containing the
193-
/// 32-byte commitment as its value.
195+
/// adding [`PSBT_OUT_TAPRET_COMMITMENT`] and [`PSBT_OUT_TAPRET_PROOF`]
196+
/// proprietary keys containing the 32-byte commitment as its proof.
194197
///
195198
/// # Errors
196199
///
@@ -201,6 +204,7 @@ impl Output {
201204
pub fn set_tapret_commitment(
202205
&mut self,
203206
commitment: impl Into<[u8; 32]>,
207+
proof: &impl StrictEncode,
204208
) -> Result<(), TapretKeyError> {
205209
if !self.is_tapret_host() {
206210
return Err(TapretKeyError::TapretProhibited);
@@ -215,6 +219,9 @@ impl Output {
215219
commitment.into().to_vec(),
216220
);
217221

222+
self.proprietary
223+
.insert(ProprietaryKey::tapret_proof(), proof.strict_serialize()?);
224+
218225
Ok(())
219226
}
220227

@@ -238,8 +245,18 @@ impl Output {
238245
/// commitments (having non-32 bytes) will be filtered at the moment of PSBT
239246
/// deserialization and this function will return `None` only in situations
240247
/// when the commitment is absent.
241-
pub fn tapret_proof(&self) -> Option<TaprootMerkleBranch> {
242-
let proof = self.proprietary.get(&ProprietaryKey::tapret_proof())?;
243-
TaprootMerkleBranch::from_slice(proof).ok()
248+
///
249+
/// Function returns generic type since the real type will create dependency
250+
/// on `bp-dpc` crate, which will result in circular dependency with the
251+
/// current crate.
252+
pub fn tapret_proof<T>(&self) -> Result<Option<T>, TapretKeyError>
253+
where
254+
T: StrictDecode,
255+
{
256+
self.proprietary
257+
.get(&ProprietaryKey::tapret_proof())
258+
.map(T::strict_deserialize)
259+
.transpose()
260+
.map_err(TapretKeyError::from)
244261
}
245262
}

0 commit comments

Comments
 (0)