Skip to main content

paralock_core/zcash/
mod.rs

1//! Zcash: transparent addresses, scripts, the Paralock HTLC and 2-of-2 templates, v5 transactions, ZIP 244 and
2//! ZIP 317, and the transaction builders. A port of `@paralock/zcash` (plus the ZIP 244 shielded digests of
3//! `@paralock/lightwalletd`), byte for byte.
4//!
5//! Conventions:
6//! - Amounts are zatoshi. Builder inputs are `u64` and are checked against [`MAX_MONEY`]; the wire value of a
7//!   [`TxOut`] is the consensus `i64`.
8//! - Txids are [`Txid`] values (internal byte order) that display byte-reversed, like every Zcash tool.
9//! - The consensus branch id is always an input: read it from the node (`getblockchaininfo.consensus.nextblock`).
10//!   Nothing here defaults or hardcodes one.
11//! - Fundings (every P2PKH spend) require an expiry height (`tip + FUNDING_EXPIRY_DELTA`); spends of a lock (claims,
12//!   refunds, 2-of-2 spends) always use expiry 0, because they are often signed long before they are broadcast.
13//! - Outputs are paid to [`TransparentAddress`]es (a lock through its P2SH address), never to raw scripts, and every
14//!   address is checked against the network.
15
16mod address;
17mod builder;
18mod fee;
19mod htlc;
20mod multisig;
21mod network;
22mod script;
23mod sighash;
24mod tx;
25mod zip244;
26
27pub use address::{AddressKind, TransparentAddress, is_transparent_address, script_pubkey_for_address};
28pub use builder::{
29    DUST_LIMIT, FUNDING_EXPIRY_DELTA, FundingRequest, MAX_MONEY, MIN_CHANGE, Payment, SignedTx, TxOptions, Utxo,
30    assert_expiry_height, assert_funding_expiry_height, assert_output_value, build_htlc_claim, build_htlc_funding,
31    build_htlc_refund, build_p2pkh_spend, sign_digest,
32};
33pub use fee::{GRACE_ACTIONS, MARGINAL_FEE, P2PKH_STANDARD_INPUT_SIZE, P2PKH_STANDARD_OUTPUT_SIZE, zip317_fee};
34pub use htlc::{
35    Htlc, HtlcParams, claim_script_sig, extract_preimage, htlc_redeem_script, parse_htlc_redeem_script,
36    refund_script_sig,
37};
38pub use multisig::{
39    Multisig2of2, MultisigSpend, build_multisig_spend, finalize_multisig_spend, multisig_signatures_from_script_sig,
40    sign_multisig_spend, verify_multisig_signature,
41};
42pub use network::Network;
43pub use script::{
44    MAX_SCRIPT_ELEMENT_SIZE, MAX_STANDARD_SCRIPTSIG_SIZE, PREIMAGE_SIZE, ScriptItem, assert_p2sh_sizes, decompile,
45    hash160, op, p2pkh_script, p2sh_script, push_data, push_number, script_num,
46};
47pub use sighash::{PrevOut, SighashType, transparent_sighash};
48pub use tx::{
49    DecodedTx, LOCKTIME_THRESHOLD, OVERWINTERED_FLAG, OutPoint, ParsedTx, RawInput, SEQUENCE_ENABLE_LOCKTIME,
50    SEQUENCE_FINAL, TX_VERSION_5, TransparentTx, TxIn, TxOut, Txid, V5_VERSION_GROUP_ID, decode_tx, parse_tx,
51    transparent_txid,
52};
53pub use zip244::{
54    ShieldedDigests, blake2b256, header_digest, outputs_digest, prevouts_digest, sequence_digest, shielded_digests,
55    transparent_txid_digest, txid_digest, txid_personalization,
56};
57
58use crate::encoding::EncodingError;
59use crate::keys::KeyError;
60
61/// A Zcash address, script, transaction or builder error. Messages match the TypeScript reference where it has one.
62#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
63#[non_exhaustive]
64pub enum Error {
65    /// Malformed bytes or hex (including truncated transactions).
66    #[error(transparent)]
67    Encoding(#[from] EncodingError),
68    /// An invalid key or signature encoding.
69    #[error(transparent)]
70    Key(#[from] KeyError),
71
72    // Addresses -------------------------------------------------------------------------------------------------
73    /// Not a transparent address: not Base58, or a payload that is not 22 bytes.
74    #[error("not a transparent address: {0}")]
75    InvalidAddress(String),
76    /// A Base58 string whose checksum is wrong (or too short to have one).
77    #[error("Invalid checksum")]
78    InvalidChecksum,
79    /// A well-formed Base58Check string with an unknown version prefix.
80    #[error("unknown address prefix: {0}")]
81    UnknownAddressPrefix(String),
82    /// The address belongs to another network.
83    #[error("{address} is a {actual} address, expected {expected}")]
84    WrongNetwork {
85        /// The address.
86        address: String,
87        /// Its network (`mainnet` or `testnet`; regtest addresses decode as testnet).
88        actual: Network,
89        /// The network required.
90        expected: Network,
91    },
92
93    // Scripts ---------------------------------------------------------------------------------------------------
94    /// A data push larger than 65 535 bytes.
95    #[error("push too large")]
96    PushTooLarge,
97    /// A push runs past the end of the script.
98    #[error("push past end of script")]
99    PushPastEnd,
100    /// A script number item that is not a number.
101    #[error("expected a number")]
102    ExpectedNumber,
103    /// The script is not the Paralock HTLC template, byte for byte.
104    #[error("not a Paralock HTLC script")]
105    NotHtlcScript,
106    /// The script has the HTLC template's shape, but a key is not a point on secp256k1.
107    #[error("not a Paralock HTLC script: a key is not a curve point")]
108    HtlcKeyNotOnCurve,
109    /// The script is not the 2-of-2 multisig template.
110    #[error("not a 2-of-2 multisig script")]
111    NotMultisigScript,
112    /// The 2-of-2 keys are not in sorted (BIP 67) order.
113    #[error("multisig keys are not sorted")]
114    MultisigKeysNotSorted,
115    /// The script sig is not a 2-of-2 spend (`OP_0 <sig> <sig> …`).
116    #[error("not a 2-of-2 spend")]
117    NotMultisigSpend,
118    /// Two keys that must differ are equal.
119    #[error("{0}")]
120    IdenticalKeys(&'static str),
121    /// A key that is not a compressed secp256k1 point (`what` is `claim pubkey`, `refund pubkey` or
122    /// `multisig pubkey`; `shown` is its hex, cut to 80 characters).
123    #[error("{what} is not a compressed secp256k1 point: {shown}")]
124    InvalidPubkey {
125        /// Which key.
126        what: &'static str,
127        /// Its hex (at most 80 characters).
128        shown: String,
129    },
130    /// A 33-byte HTLC key push without a `02`/`03` prefix.
131    #[error("pubkeys must be 33-byte compressed keys")]
132    PubkeysNotCompressed,
133    /// A hashlock that is not 32 bytes.
134    #[error("hashlock must be 32 bytes")]
135    InvalidHashlockLength,
136    /// An HTLC refund height outside `[1, 500_000_000)`.
137    #[error("refundHeight must be a block height")]
138    InvalidRefundHeight,
139    /// A 2-of-2 refund lock time outside `[1, 500_000_000)` (`adaptorSpends`): 0 would make the refund valid at once.
140    #[error("refundHeight must be a block height in [1, 500000000), got {0}")]
141    RefundHeightOutOfRange(u32),
142    /// A redeem script above the 520-byte consensus limit.
143    #[error("redeem script is {0} bytes; the limit is 520")]
144    RedeemScriptTooLarge(usize),
145    /// A scriptSig above the 1 650-byte standardness limit.
146    #[error("scriptSig is {0} bytes; the standard limit is 1650")]
147    ScriptSigTooLarge(usize),
148    /// A preimage that is not 32 bytes.
149    #[error("preimage must be 32 bytes")]
150    InvalidPreimageLength,
151
152    // Transactions ----------------------------------------------------------------------------------------------
153    /// Not a v5 (`0x80000005`) transaction.
154    #[error("only v5 transactions are supported")]
155    UnsupportedVersion,
156    /// A transaction version this crate cannot hash (v6 or later, or not a transaction).
157    #[error("unsupported transaction version {0}")]
158    UnsupportedTxVersion(u32),
159    /// The v5 version group id is wrong.
160    #[error("bad version group id")]
161    BadVersionGroupId,
162    /// Bytes after the end of the transaction.
163    #[error("unexpected data after the Orchard bundle")]
164    TrailingData,
165    /// Bytes after the end of a v1–v4 transaction (its txid would hash them).
166    #[error("unexpected data after the v{0} transaction")]
167    TrailingTxData(u32),
168    /// A v1/v2 transaction with the fOverwintered bit set, or a v3/v4 transaction without it.
169    #[error("a v{version} transaction must have fOverwintered {}", if *.set { "set" } else { "clear" })]
170    OverwinteredFlag {
171        /// The transaction version.
172        version: u32,
173        /// Whether the bit must be set.
174        set: bool,
175    },
176    /// The version group id of a v3/v4 transaction is wrong.
177    #[error("bad version group id for a v{0} transaction")]
178    BadPreV5VersionGroupId(u32),
179    /// A txid that is not 64 hex characters.
180    #[error("txid must be 32 bytes of hex")]
181    InvalidTxid,
182
183    // Signature hashes ------------------------------------------------------------------------------------------
184    /// A sighash type other than the six ZIP 244 allows.
185    #[error("invalid sighash type {0}: v5 allows only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83")]
186    InvalidSighashType(u8),
187    /// The prevouts don't match the inputs one to one.
188    #[error("need one prevout per input")]
189    PrevoutCountMismatch,
190    /// No input at this index.
191    #[error("no input {0}")]
192    NoSuchInput(usize),
193
194    // Builders --------------------------------------------------------------------------------------------------
195    /// Nothing to spend.
196    #[error("no UTXOs to spend")]
197    NoUtxos,
198    /// Nothing to pay.
199    #[error("no outputs")]
200    NoOutputs,
201    /// A UTXO that the signing key does not own.
202    #[error("UTXO {0} is not owned by this key")]
203    UtxoNotOwned(OutPoint),
204    /// A UTXO with value 0 or above `MAX_MONEY`.
205    #[error("UTXO {0} has an invalid value")]
206    InvalidUtxoValue(OutPoint),
207    /// The same outpoint listed twice.
208    #[error("UTXO {0} is listed twice")]
209    DuplicateUtxo(OutPoint),
210    /// An output below the dust limit.
211    #[error("output of {0} zat is below the dust limit (1000)")]
212    Dust(u64),
213    /// An amount above `MAX_MONEY`.
214    #[error("{what} of {value} zat exceeds MAX_MONEY")]
215    ExceedsMaxMoney {
216        /// What was too large.
217        what: &'static str,
218        /// The amount.
219        value: u64,
220    },
221    /// The UTXOs don't cover the outputs plus the fee.
222    #[error("insufficient funds: have {have}, need {need}")]
223    InsufficientFunds {
224        /// Total of the UTXOs.
225        have: u64,
226        /// Outputs plus fee.
227        need: u64,
228    },
229    /// A lock's value minus the fee is below the dust limit.
230    #[error("{0}")]
231    AmountDoesNotCoverFee(&'static str),
232    /// The UTXO's scriptPubKey is not the lock's.
233    #[error("{0}")]
234    UtxoScriptMismatch(&'static str),
235    /// The key is not the one this spend needs.
236    #[error("{0}")]
237    WrongKey(&'static str),
238    /// The preimage does not hash to the HTLC's hashlock.
239    #[error("preimage does not match the HTLC hashlock")]
240    WrongPreimage,
241    /// An expiry height outside `[0, 500_000_000)`.
242    #[error("invalid expiry height {0}")]
243    InvalidExpiryHeight(u32),
244    /// A funding without an expiry height (0 never expires).
245    #[error("a funding needs an expiry height (tip + FUNDING_EXPIRY_DELTA); 0 never expires")]
246    ExpiryHeightRequired,
247    /// A consensus branch id of 0 (there is no default branch id).
248    #[error("branchId must be the next block's consensus branch id (a non-zero 32-bit integer from the node), got {0}")]
249    InvalidBranchId(u32),
250    /// A fee (override) that is not below the value spent.
251    #[error("fee of {fee} zat is not below the {spent} zat spent")]
252    FeeNotBelowSpent {
253        /// The fee.
254        fee: u64,
255        /// The value of the inputs.
256        spent: u64,
257    },
258    /// A lock time that is not a block height.
259    #[error("lockTime must be a block height")]
260    InvalidLockTime,
261    /// A 2-of-2 spend is missing a key's signature.
262    #[error("need a signature for both multisig keys")]
263    MissingSignature,
264    /// A 2-of-2 signature does not verify.
265    #[error("invalid signature for multisig key {0}")]
266    InvalidSignature(String),
267}