psbt/
lib.rs

1// Modern, minimalistic & standard-compliant cold wallet library.
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5// Written in 2020-2024 by
6//     Dr Maxim Orlovsky <orlovsky@lnp-bp.org>
7//
8// Copyright (C) 2020-2024 LNP/BP Standards Association. All rights reserved.
9// Copyright (C) 2020-2024 Dr Maxim Orlovsky. All rights reserved.
10//
11// Licensed under the Apache License, Version 2.0 (the "License");
12// you may not use this file except in compliance with the License.
13// You may obtain a copy of the License at
14//
15//     http://www.apache.org/licenses/LICENSE-2.0
16//
17// Unless required by applicable law or agreed to in writing, software
18// distributed under the License is distributed on an "AS IS" BASIS,
19// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20// See the License for the specific language governing permissions and
21// limitations under the License.
22
23#[macro_use]
24extern crate amplify;
25#[cfg(feature = "strict_encoding")]
26#[macro_use]
27extern crate strict_encoding;
28#[cfg(feature = "serde")]
29#[macro_use]
30extern crate serde_crate as serde;
31
32mod data;
33mod keys;
34mod maps;
35mod coders;
36#[cfg(feature = "client-side-validation")]
37mod csval;
38pub mod constructor;
39mod sign;
40#[cfg(feature = "serde")]
41mod serde_utils;
42
43pub use coders::{Decode, DecodeError, Encode, PsbtError};
44pub use constructor::{
45    Beneficiary, BeneficiaryParseError, ConstructionError, Payment, PsbtConstructor, PsbtMeta,
46    TxParams, Utxo,
47};
48#[cfg(feature = "client-side-validation")]
49pub use csval::*;
50pub use data::{
51    Input, ModifiableFlags, Output, Prevout, Psbt, PsbtParseError, UnfinalizedInputs, UnsignedTx,
52    UnsignedTxIn,
53};
54pub use keys::{GlobalKey, InputKey, KeyPair, KeyType, OutputKey, PropKey};
55pub use maps::{KeyAlreadyPresent, KeyData, KeyMap, Map, MapName, ValueData};
56pub use sign::{Rejected, SignError, Signer};
57
58#[cfg(feature = "strict_encoding")]
59pub const LIB_NAME_PSBT: &str = "Psbt";
60
61#[derive(Copy, Clone, Eq, PartialEq, Debug, Display, Error)]
62#[display("unsupported version of PSBT v{0}")]
63pub struct PsbtUnsupportedVer(u32);
64
65#[derive(Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Display)]
66#[cfg_attr(
67    feature = "serde",
68    derive(Serialize, Deserialize),
69    serde(crate = "serde_crate", rename_all = "camelCase")
70)]
71pub enum PsbtVer {
72    #[display("v0")]
73    V0 = 0,
74    #[display("v2")]
75    V2 = 2,
76}
77
78impl PsbtVer {
79    pub const fn try_from_standard_u32(v: u32) -> Result<Self, PsbtUnsupportedVer> {
80        Ok(match v {
81            0 => Self::V0,
82            2 => Self::V2,
83            wrong => return Err(PsbtUnsupportedVer(wrong)),
84        })
85    }
86
87    pub const fn to_standard_u32(&self) -> u32 { *self as u32 }
88
89    pub const fn max() -> Self {
90        // this is a special syntax construct to get compiler error each time we add a new version
91        // and not to forget upgrade the result of this method
92        match Self::V0 {
93            PsbtVer::V0 | PsbtVer::V2 => PsbtVer::V2,
94        }
95    }
96}
97
98impl TryFrom<usize> for PsbtVer {
99    type Error = PsbtUnsupportedVer;
100
101    fn try_from(value: usize) -> Result<Self, Self::Error> {
102        match value {
103            0 => Ok(Self::V0),
104            2 => Ok(Self::V2),
105            _ => Err(PsbtUnsupportedVer(value as u32)),
106        }
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn psbt_try_from_numbers() {
116        assert_eq!(PsbtVer::try_from(0), Ok(PsbtVer::V0));
117        assert_eq!(PsbtVer::try_from(2), Ok(PsbtVer::V2));
118        assert_eq!(PsbtVer::try_from(1), Err(PsbtUnsupportedVer(1)));
119    }
120}