---
bip: 375
title: "Sending Silent Payments with PSBTs"
status: Draft
type: Specification
layer: "Applications"
authors: ["Andrew Toth","Ava Chow","josibake"]
assigned: 2025-01-08
last_modified: 2026-09-27
requires: [352,370,374]
topics: ["wallets"]
license: "BSD-2-Clause"
url: https://bipexplorer.com/bip/375
source: https://github.com/bitcoin/bips/blob/master/bip-0375.mediawiki
---

# BIP 375: Sending Silent Payments with PSBTs

> **In plain English:** Adds fields and rules to the version 2 Partially Signed Bitcoin Transaction (PSBT) format so wallets can send to Silent Payment addresses. Since a Silent Payment's final address depends on the sender's inputs, this lets multiple devices or parties safely work out and verify that address together.

## Introduction

### Abstract

This document proposes additional fields and updated role responsibilities for BIP370 PSBTv2 which adds support for sending to silent payments as described in BIP352.

### Copyright

This BIP is licensed under the 2-clause BSD license.

### Motivation

Partially Signed Bitcoin Transaction Version 2 as described in BIP370 is not compatible with sending to silent payments as described in BIP352. In particular, the output script of a silent payment cannot be computed until after all transaction inputs have been added. Additionally, the silent payment outputs computed by a signer must be verifiable by other entities, otherwise funds could be sent to an incorrect output script. Therefore, new fields and role responsibilities must be added to carry, compute, and verify the silent payment data.

## Specification

This document specifies new fields and new field inclusion/exclusion requirements.

The new global types are defined as follows:

| Name | `<keytype>` | `<keydata>` | `<keydata>` Description | `<valuedata>` | `<valuedata>` Description | Versions Requiring Inclusion | Versions Requiring Exclusion | Versions Allowing Inclusion |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Silent Payment Global ECDH Share | `PSBT_GLOBAL_SP_ECDH_SHARE = 0x07` | `<33 byte scan key>` | The scan key that this ECDH share is for. | `<33 byte share>` | An ECDH share for a scan key. The ECDH shared is computed with _a \* B\_scan_, where _a_ is the sum of all private keys of all eligible inputs, and _B\_scan_ is the scan key of a recipient. |  | 0 | 2 |
| Silent Payment Global DLEQ Proof | `PSBT_GLOBAL_SP_DLEQ = 0x08` | `<33 byte scan key>` | The scan key that this proof covers. | `<64-byte proof>` | A BIP374 DLEQ proof computed for the matching ECDH share. |  | 0 | 2 |

The new per-input types are defined as follows:

| Name | `<keytype>` | `<keydata>` | `<keydata>` Description | `<valuedata>` | `<valuedata>` Description | Versions Requiring Inclusion | Versions Requiring Exclusion | Versions Allowing Inclusion |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Silent Payment Input ECDH Share | `PSBT_IN_SP_ECDH_SHARE = 0x1d` | `<33 byte scan key>` | The scan key that this ECDH share is for. | `<33 byte share>` | An ECDH share for a scan key. The ECDH shared is computed with _a \* B\_scan_, where _a_ is the private key of the corresponding prevout public key, and _B\_scan_ is the scan key of a recipient. |  | 0 | 2 |
| Silent Payment Input DLEQ Proof | `PSBT_IN_SP_DLEQ = 0x1e` | `<33 byte scan key>` | The scan key that this proof covers. | `<64-byte proof>` | A BIP374 DLEQ proof computed for the matching ECDH share. |  | 0 | 2 |

The new per-output types are defined as follows:

| Name | `<keytype>` | `<keydata>` | `<keydata>` Description | `<valuedata>` | `<valuedata>` Description | Versions Requiring Inclusion | Versions Requiring Exclusion | Versions Allowing Inclusion |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Silent Payment Data | `PSBT_OUT_SP_V0_INFO = 0x09` | None | No key data | `<33 byte scan key> <33 byte spend key>` | The scan and spend public keys from the silent payments address. |  | 0 | 2 |
| Silent Payment Label | `PSBT_OUT_SP_V0_LABEL = 0x0a` | None | No key data | `<32-bit little endian uint label>` | The label to use to compute the spend key of the silent payments address to verify change. |  | 0 | 2 |

`PSBT_OUT_SCRIPT` is modified to be optional for outputs in silent payments capable PSBTs. If this field is not included in the output, then the field PSBT\_OUT\_SP\_V0\_INFO must be included. If a PSBT\_OUT\_SCRIPT is not present for an output, then that output is being sent to a silent payment address represented by PSBT\_OUT\_SP\_V0\_INFO but the script has not yet been computed. If both PSBT\_OUT\_SCRIPT and PSBT\_OUT\_SP\_V0\_INFO are present for an output, then the PSBT\_OUT\_SCRIPT is the computed output script corresponding to the silent payment address in PSBT\_OUT\_SP\_V0\_INFO. If only PSBT\_OUT\_SCRIPT is present for an output, then the output is not being sent to a silent payment address.

### Unique Identification

Silent payment capable PSBTs can be uniquely identified the same way as PSBTv2s, except when including silent payment outputs. If an output contains the PSBT\_OUT\_SP\_V0\_INFO field, it must use that field instead of PSBT\_OUT\_SCRIPT as the output script when creating the unsigned transaction used for unique identification.[1] The PSBT\_OUT\_SP\_V0\_INFO should be serialized as a zero byte for the version, followed by the 33 bytes of the scan key and then 33 bytes for the spend key.

## Roles

This document modifies some existing roles.

### Constructor

All rules must be followed from PSBTv2 for this role, with the following exception: When an output is added, it must have either PSBT\_OUT\_SCRIPT or PSBT\_OUT\_SP\_V0\_INFO, or both, set.

Additionally to PSBTv2, the Constructor must also follow additional rules:

Inputs spending an output with script using Segwit version > 1 may only be added if there are no outputs with PSBT\_OUT\_SP\_V0\_INFO set. Outputs with PSBT\_OUT\_SP\_V0\_INFO set may only be added if there are no inputs spending an output script using Segwit version > 1.

### Updater

The updater should add a PSBT\_IN\_BIP32\_DERIVATION for any p2wpkh, p2sh-p2wpkh, or p2pkh input so the public key is available for creating the ecdh\_shared\_secret when the private key is not known. If the updater does not want to reveal the fingerprint or derivation path, it can set the value of the field to zero.

#### Change Detection

Updaters may add two PSBT\_OUT\_BIP32\_DERIVATION key-value-pairs with the corresponding derivation path of both the scan and spend keys. A label can be specified in PSBT\_OUT\_SP\_V0\_LABEL. The Signer can then use these fields to verify that the silent payment code is change.

### Signer

All rules must be followed from PSBTv2 for this role. If there are any outputs with PSBT\_OUT\_SP\_V0\_INFO set, then the following additional rules must also be adhered to:

If any input is spending an output with script using Segwit version > 1, the Signer must fail.

For each output with PSBT\_OUT\_SP\_V0\_INFO set, the Signer should:

-   Compute and set an ECDH share and DLEQ proof for each eligible input it has the private key for, or set a global ECDH share and DLEQ proof if it has private keys for all eligible inputs.

-   Verify the DLEQ proofs for all inputs it does not have the private keys for, or the global DLEQ proof if it is set.

-   If all eligible inputs have an ECDH share or the global ECDH share is set, compute and set the PSBT\_OUT\_SCRIPT.

If the Signer sets any missing PSBT\_OUT\_SCRIPTs, it must set the Inputs Modifiable and Outputs Modifiable flags to False.

If any output does not have PSBT\_OUT\_SCRIPT set, the Signer must not yet add a signature.

The Signer should additionally compute the silent payment addresses, optionally showing this data to the user instead of the computed segwit v1 addresses.

If a sighash type is provided and there are silent payment outputs present, the signer must fail if the sighash type is not SIGHASH\_ALL. If a sighash type is not provided and there are silent payment outputs present, the signer must sign using SIGHASH\_ALL.[2]

#### Computing the ECDH Shares and DLEQ Proofs

For each output with PSBT\_OUT\_SP\_V0\_INFO set, the Signer may generate a proof for other entities to generate the output scripts and verify that the output scripts were generated correctly.

If the Signer has the private keys for all eligible inputs, the Signer should generate a global ECDH share for each scan key _Bscan_ as follows:

Using the notation from [BIP352](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#specification)

-   Let _an_ be the sum of the private keys _a_ of all eligible inputs

-   Let _C = an·Bscan_

Set the key as _Bscan_ and the value as _C_ for the PSBT\_GLOBAL\_SP\_ECDH\_SHARE field.

Compute the DLEQ proof for _C_ using [BIP374 GenerateProof](https://github.com/bitcoin/bips/blob/master/bip-0374.mediawiki#dleq-proof-generation) and passing _an_ as _a_ and _Bscan_ as _B_. Set the key as _Bscan_ and the value as the proof for the PSBT\_GLOBAL\_SP\_DLEQ field.

If the Signer has the private keys for some eligible inputs or does not want to create a global ECDH share, the Signer should generate a per-input ECDH share for each scan key _Bscan_ as follows:

Using the notation from [BIP352](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#specification), for each eligible input:

-   Let _a_ be the private key of the input

-   Let _C = a·Bscan_

Set the key as _Bscan_ and the value as _C_ for the PSBT\_IN\_SP\_ECDH\_SHARE field of the input.

Compute the DLEQ proof for _C_ using [BIP374 GenerateProof](https://github.com/bitcoin/bips/blob/master/bip-0374.mediawiki#dleq-proof-generation) and passing _Bscan_ as _B_. Set the key as _Bscan_ and the value as the proof for the PSBT\_IN\_SP\_DLEQ field of the input.

#### Verifying the DLEQ Proof

For each output with PSBT\_OUT\_SP\_V0\_INFO set, the Signer should verify the ECDH shares for all eligible inputs it does not have the private key for using the proofs provided by other Signers.

If PSBT\_GLOBAL\_SP\_ECDH\_SHARE and PSBT\_GLOBAL\_SP\_DLEQ are set, verify as follows:

-   Let _An_ be the sum of the public keys _A_ of all eligible inputs

Using [BIP374 VerifyProof](https://github.com/bitcoin/bips/blob/master/bip-0374.mediawiki#dleq-proof-verification) and passing _A_ as _An_, _B_ as _Bscan_, _C_ as the value of PSBT\_GLOBAL\_SP\_ECDH\_SHARE, and _proof_ as the value of PSBT\_GLOBAL\_SP\_DLEQ.

If PSBT\_IN\_SP\_ECDH\_SHARE and PSBT\_IN\_SP\_DLEQ are set for a particular input, verify as follows:

Using [BIP374 VerifyProof](https://github.com/bitcoin/bips/blob/master/bip-0374.mediawiki#dleq-proof-verification) and passing _A_ as the public key of the input, _B_ as _Bscan_, _C_ as the value of PSBT\_IN\_SP\_ECDH\_SHARE, and _proof_ as the value of PSBT\_IN\_SP\_DLEQ.

#### Computing the Output Scripts

Compute the PSBT\_OUT\_SCRIPT using the procedure in [BIP352](https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#creating-outputs) but substituting _a·Bscan_ with the PSBT\_GLOBAL\_SP\_ECDH\_SHARE for that scan key if available, or the sum of all PSBT\_IN\_SP\_ECDH\_SHAREs from eligible inputs for that scan key. If there are multiple silent payment codes with the same scan key, sort the codes lexicographically in ascending order to determine the ordering of the _k_ value. If there are multiple silent payment codes with both the same scan and spend keys, sort the subgroup by output index in ascending order.

### Transaction Extractor

For silent payment capable PSBTs, the transaction extractor should compute all output scripts for silent payment codes and verify they are correct using the ECDH shares and DLEQ proofs, otherwise fail.

## Backwards Compatibility

Silent payment capable PSBTs are backwards compatible with PSBTv2 once all outputs have PSBT\_OUT\_SCRIPT set. Otherwise they are not backwards compatible.

## Test Vectors

A [collection of test vectors in JSON format](https://github.com/bitcoin/bips/blob/master/bip-0375/bip375_test_vectors.json) is provided. Each test vector contains a base64-encoded PSBT string, which alone can be used to verify sending Silent Payments with PSBTs. Validation is performed in 4 sequential checks. This [Python implementation](https://github.com/bitcoin/bips/blob/master/bip-0375/validator/validate_psbt.py) demonstrates the validation logic for each:

1.  **PSBT Structure** - Verify BIP375 field requirements

1.  **ECDH Coverage** - Verify ECDH share presence and correctness using BIP374 DLEQ

1.  **Input Eligibility** - Verify input constraints when silent payment outputs are present

1.  **Output Scripts** - Verify output scripts match silent payment derivation

Valid PSBTs are organized into 2 categories:

1.  **Can Finalize** - Signed and ready to finalize

1.  **In Progress** - Incomplete but valid

Use the provided [test runner](https://github.com/bitcoin/bips/blob/master/bip-0375/test_runner.py) to validate each test vector. See the [README](https://github.com/bitcoin/bips/blob/master/bip-0375/README.md) for more details.

### Invalid PSBTs

| Category | Description |
| --- | --- |
| PSBT Structure | missing PSBT\_OUT\_SP\_V0\_INFO field when PSBT\_OUT\_SP\_V0\_LABEL set |
| PSBT Structure | incorrect byte length for PSBT\_OUT\_SP\_V0\_LABEL field |
| PSBT Structure | incorrect byte length for PSBT\_OUT\_SP\_V0\_INFO field |
| PSBT Structure | incorrect byte length for PSBT\_IN\_SP\_ECDH\_SHARE field |
| PSBT Structure | incorrect byte length for PSBT\_IN\_SP\_DLEQ field |
| PSBT Structure | PSBT\_GLOBAL\_TX\_MODIFIABLE field is non-zero when PSBT\_OUT\_SCRIPT set for sp output |
| PSBT Structure | missing PSBT\_OUT\_SCRIPT field when sending to non-sp output |
| ECDH Coverage | only one ineligible P2SH multisig input when PSBT\_OUT\_SCRIPT set for sp output |
| ECDH Coverage | missing PSBT\_IN\_SP\_ECDH\_SHARE field for input 0 when PSBT\_OUT\_SCRIPT set for sp output |
| ECDH Coverage | missing PSBT\_IN\_SP\_DLEQ field for input when PSBT\_IN\_SP\_ECDH\_SHARE set |
| ECDH Coverage | missing PSBT\_GLOBAL\_SP\_DLEQ field when PSBT\_GLOBAL\_SP\_ECDH\_SHARE set |
| ECDH Coverage | invalid proof in PSBT\_IN\_SP\_DLEQ field |
| ECDH Coverage | invalid proof in PSBT\_GLOBAL\_SP\_DLEQ field |
| ECDH Coverage | missing PSBT\_IN\_BIP32\_DERIVATION field for input when PSBT\_IN\_SP\_DLEQ set |
| ECDH Coverage | output 1 missing ECDH share for scan key with one input / three sp outputs (different scan keys) |
| ECDH Coverage | input 1 missing ECDH share for output 1 with two inputs / two sp outputs (different scan keys) |
| ECDH Coverage | input 1 missing ECDH share for scan key with two inputs / one sp output |
| Input Eligibility | segwit version greater than 1 in transaction inputs with sp output |
| Input Eligibility | non-SIGHASH\_ALL signature on input with sp output |
| Output Scripts | P2TR input with NUMS internal key cannot derive sp output |
| Output Scripts | PSBT\_OUT\_SCRIPT does not match derived sp output |
| Output Scripts | two sp outputs (same scan / different spend keys) not sorted lexicographically by spend key |
| Output Scripts | k values assigned to wrong output indices with three sp outputs (same scan / spend keys) |

### Valid PSBTs

| State | Description |
| --- | --- |
| Can Finalize | one P2PKH input single-signer |
| Can Finalize | two inputs single-signer using global ECDH share |
| Can Finalize | two inputs single-signer using per-input ECDH shares |
| Can Finalize | two inputs / two sp outputs with mixed global and per-input ECDH shares |
| Can Finalize | one input / one sp output with both global and per-input ECDH shares |
| Can Finalize | three sp outputs (different scan keys) with multiple global ECDH shares |
| Can Finalize | one P2WPKH input / two mixed outputs - labeled sp output and BIP 32 change |
| Can Finalize | one input / two sp outputs - output 0 has no label / output 1 uses label=0 convention for sp change |
| Can Finalize | two sp outputs - output 0 uses label=3 / output 1 uses label=1 |
| Can Finalize | two inputs using per-input ECDH shares - only eligible inputs contribute shares (P2SH excluded) |
| Can Finalize | two inputs using global ECDH share - only eligible inputs contribute shares (P2SH excluded) |
| Can Finalize | two mixed input types - only eligible inputs contribute ECDH shares (NUMS internal key excluded) |
| Can Finalize | three sp outputs (same scan key) - each output has distinct k value |
| Can Finalize | three sp outputs (same scan key) / two regular outputs - k values assigned independently of output index |
| In Progress | two P2TR inputs, neither is signed |
| In Progress | one P2TR input / one sp output with no ECDH shares when PSBT\_OUT\_SCRIPT field is not set |
| In Progress | two inputs / one sp output, input 1 missing ECDH share when PSBT\_OUT\_SCRIPT field is not set |
| In Progress | one input / two sp outputs, input 0 missing ECDH share for output 0 when PSBT\_OUT\_SCRIPT field is not set |
| In Progress | large PSBT with nine mixed inputs / six outputs - some inputs signed |

## Changelog

-   **0.1.2** (2026-09-27):
    -   Validate PSBT\_OUT\_SP\_V0\_LABEL is exactly 4 bytes; add invalid test vector for wrong length.
-   **0.1.1** (2026-04-16):
    -   Add test vectors and reference for validating Sending Silent Payments with PSBTs.
-   **0.1.0** (2025-01-13):
    -   Initial version, merged as BIP-375.

## Rationale

1.  **Why use PSBT\_OUT\_SP\_V0\_INFO when serializing for a unique identifier?** Since the same silent payment capable PSBT is valid whether or not a PSBT\_OUT\_SCRIPT is included in an output that has PSBT\_OUT\_SP\_V0\_INFO set, using the PSBT\_OUT\_SCRIPT if present for the unique identifier will cause malleability. The identifier will be different depending on whether PSBT\_OUT\_SCRIPT is present, so always using PSBT\_OUT\_SP\_V0\_INFO if it exists makes sure the PSBT is always identified uniquely. 
2.  **Why use only SIGHASH\_ALL?** BIP352 allows signing with SIGHASH\_NONE and SIGHASH\_SINGLE. However, silent payment capable PSBTs compute the output scripts deterministically based on the number and position of silent payment codes with the same scan key. SIGHASH\_NONE and SIGHASH\_SINGLE allow changing the amount or position of silent payment codes with the same scan and spend keys, which would invalidate computed output scripts. 

## Reference implementation

Todo
