-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
bitcoin: add silent payments crate to support sending to SP addresses
BIP-352: https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki A silent payment address contains two pubkeys, B_scan and B_spend. From that, Taproot outputs can be created by using a ECDH shared secret - see the BIP Overview section. The created output is returned to the host along with a DLEQ proof the host can use to independently verify the output was created correctly. This mitigates bugs, potential memory corruption (bit-flips), etc. in the firmware leading to catastrophic failure. The added vendored deps serde/serde_json etc. are dev-dependencies to run the tests in the new crate, not used for firmware builds. **A note about multiple silent payment outputs per transaction:** In general, a transaction can send to an arbitrary amount of silent payment addresses. If there are multiple, then for each unique B_scan (multiple outputs to the same recipient/B_scan), a counter `k` is incremented. See https://github.com/bitcoin/bips/blob/master/bip-0352.mediawiki#creating-outputs. To be able to verify the silent payment address, we need to derive the output and check that it matches the provided output. For each SP output, we'd then need to know the SP address and the counter `k`. The problem with this is that we also need to check, per B_scan, that each `k=0, 1, ...` is used starting at zero with no holes. This requires non-constant memory. We could still do it and support a limited (but likely high) number of SP outputs per transaction, but that complicates the code. For this reason, we restrict to only one SP output per transaction.
- Loading branch information
Showing
188 changed files
with
57,918 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Copyright 2024 Shift Crypto AG | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
[package] | ||
name = "streaming-silent-payments" | ||
version = "0.1.0" | ||
authors = ["Shift Crypto AG <[email protected]>"] | ||
edition = "2021" | ||
license = "Apache-2.0" | ||
|
||
[dependencies] | ||
bitcoin = { workspace = true } | ||
bech32 = { workspace = true } | ||
bitbox02 = { path = "../bitbox02" } | ||
|
||
[dev-dependencies] | ||
serde = { version = "1.0", features = ["derive"] } | ||
hex = { workspace = true } | ||
serde_json = "1.0" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// File copied and adapted from: | ||
// https://github.com/cygnet3/rust-silentpayments/blob/395b153b6d98ea33a59306c1a8a189d4ca152571/src/utils/hash.rs | ||
|
||
#![allow(non_snake_case)] | ||
|
||
use bitcoin::hashes::{sha256t_hash_newtype, Hash, HashEngine}; | ||
use bitcoin::secp256k1::{PublicKey, Scalar}; | ||
|
||
sha256t_hash_newtype! { | ||
struct InputsTag = hash_str("BIP0352/Inputs"); | ||
|
||
/// BIP0352-tagged hash with tag \"Inputs\". | ||
/// | ||
/// This is used for computing the inputs hash. | ||
#[hash_newtype(forward)] | ||
struct InputsHash(_); | ||
|
||
pub(crate) struct SharedSecretTag = hash_str("BIP0352/SharedSecret"); | ||
|
||
/// BIP0352-tagged hash with tag \"SharedSecret\". | ||
/// | ||
/// This hash type is for computing the shared secret. | ||
#[hash_newtype(forward)] | ||
pub(crate) struct SharedSecretHash(_); | ||
} | ||
|
||
impl InputsHash { | ||
pub(crate) fn from_outpoint_and_A_sum( | ||
smallest_outpoint: &bitcoin::OutPoint, | ||
A_sum: PublicKey, | ||
) -> InputsHash { | ||
let mut eng = InputsHash::engine(); | ||
eng.input(&bitcoin::consensus::serialize(smallest_outpoint)); | ||
eng.input(&A_sum.serialize()); | ||
InputsHash::from_engine(eng) | ||
} | ||
pub(crate) fn to_scalar(self) -> Scalar { | ||
// This is statistically extremely unlikely to panic. | ||
Scalar::from_be_bytes(self.to_byte_array()).unwrap() | ||
} | ||
} | ||
|
||
impl SharedSecretHash { | ||
pub(crate) fn from_ecdh_and_k(ecdh: &PublicKey, k: u32) -> SharedSecretHash { | ||
let mut eng = SharedSecretHash::engine(); | ||
eng.input(&ecdh.serialize()); | ||
eng.input(&k.to_be_bytes()); | ||
SharedSecretHash::from_engine(eng) | ||
} | ||
} | ||
|
||
pub(crate) fn calculate_input_hash(outpoint: &bitcoin::OutPoint, A_sum: PublicKey) -> Scalar { | ||
InputsHash::from_outpoint_and_A_sum(outpoint, A_sum).to_scalar() | ||
} |
Oops, something went wrong.