Skip to content

Commit bf066e2

Browse files
committed
Merge #286: refactor confidential.rs and clean up code
e9ffc69 confidential: directly use Read/Write in Encodable/Decodable (Andrew Poelstra) c92694b confidential: add a bunch of consts and type aliases (Andrew Poelstra) 2a4ce2d confidential: enable use_self lint (Andrew Poelstra) 9a4c8b8 run rustfmt on src/confidential/* tree (Andrew Poelstra) 8cc6e02 confidential: move commitment types into their own modules (Andrew Poelstra) 278ad33 confidential: improve unit tests by defining constants (Andrew Poelstra) 273ed15 confidential: encapsulate SurjectionProof (Andrew Poelstra) de00948 confidential: encapsulate RangeProof (Andrew Poelstra) 06f4575 pset: add unit test from Claude (Andrew Poelstra) 9b949f4 rename confidential.rs to confidential/mod.rs (Andrew Poelstra) 4336802 remove Encodable/Decodable impls for PedersenCommitment/Generator/PublicKey (Andrew Poelstra) f3a0afe fuzz: fix typo in generate-files.sh (Andrew Poelstra) ad4788e rustfmt src/lib.rs (Andrew Poelstra) Pull request description: This is a lot of commits but hopefully should be straightforward to review. Two are formatting, one is a rename-only, at least one is code-move-only, and a few others just enable lints. The big changes are: 1. We encapsulate `RangeProof` and `SurjectionProof` into dedicated types, rather than using `Option<Box<secp256k1_zkp::RangeProof>>` everywhere. This fixes a type confusion in the PSET code and overall greatly simplifies all our interactions with rangeproofs and surjection proofs. 2. We break apart the three confidential commitment types into their own modules and refactor the code a bunch to try to minimize the text-diff between the modules. This hopefully will prevent divergence between these three basically-the-same objects. But there is no user-visible effect to this change. 3. We remove `Encodable/Decodable` for secp256k1_zkp objects, since these should never appear "bare" in rust-elements code. Instead we implement these only on rust-elements wrapper types. We also simplify these implementations a bit to e.g. directly encode big-endian integers for confidential values rather than calling `u64::consensus_encode` then `u64::swap_bytes`. The next PR will introduce the rust-bitcoin 0.32.100 series, which have new `Encode`/`Decode` traits with much better error handling, no more `bitcoin-io`, and fewer allocations. This PR helps set the stage for that by cleaning up the existing `Encodable/Decodable` impls and improving the overall type safety of the library. ACKs for top commit: delta1: ACK e9ffc69; tested locally Tree-SHA512: 2faf30de7131aafcc67a6b8d3ca44d2e39292632b778460f6c7e887dabd14e88bef986a1fd646e6c4a4e0e4127fad4373600ac891f21e1f156ce582f3d466595
2 parents 12441ee + e9ffc69 commit bf066e2

19 files changed

Lines changed: 2086 additions & 1760 deletions

.github/workflows/cron-daily-fuzz.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
######
2-
## DO NOT EDIT THIS FILE DIRECTLY. It is generated by generate-fuzz.sh.
2+
## DO NOT EDIT THIS FILE DIRECTLY. It is generated by generate-files.sh.
33
## Edit that script instead and re-run it.
44
######
55
name: Fuzz

fuzz/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
######
2-
## DO NOT EDIT THIS FILE DIRECTLY. It is generated by generate-fuzz.sh.
2+
## DO NOT EDIT THIS FILE DIRECTLY. It is generated by generate-files.sh.
33
## Edit that script instead and re-run it.
44
######
55
[package]

fuzz/generate-files.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ source "$REPO_DIR/fuzz/fuzz-util.sh"
1111
# 1. Generate fuzz/Cargo.toml
1212
cat > "$REPO_DIR/fuzz/Cargo.toml" <<EOF
1313
######
14-
## DO NOT EDIT THIS FILE DIRECTLY. It is generated by generate-fuzz.sh.
14+
## DO NOT EDIT THIS FILE DIRECTLY. It is generated by generate-files.sh.
1515
## Edit that script instead and re-run it.
1616
######
1717
[package]
@@ -38,6 +38,7 @@ use_self = "warn"
3838
3939
[package.metadata.rbmt.lint]
4040
allowed_duplicates = [
41+
"bitcoin_hashes",
4142
"bitcoin-internals",
4243
"hex-conservative",
4344
"getrandom",
@@ -61,7 +62,7 @@ done
6162
# 2. Generate .github/workflows/cron-daily-fuzz.yml
6263
cat > "$REPO_DIR/.github/workflows/cron-daily-fuzz.yml" <<EOF
6364
######
64-
## DO NOT EDIT THIS FILE DIRECTLY. It is generated by generate-fuzz.sh.
65+
## DO NOT EDIT THIS FILE DIRECTLY. It is generated by generate-files.sh.
6566
## Edit that script instead and re-run it.
6667
######
6768
name: Fuzz

rustfmt.toml

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
ignore = [
2+
"/",
3+
"!/src/lib.rs",
4+
"!/src/confidential/*.rs",
5+
]
6+
hard_tabs = false
7+
tab_spaces = 4
8+
newline_style = "Auto"
9+
indent_style = "Block"
10+
11+
max_width = 100 # This is the number of characters.
12+
# `use_small_heuristics` is ignored if the granular width config values are explicitly set.
13+
use_small_heuristics = "Max" # "Max" == All granular width settings same as `max_width`.
14+
# # Granular width configuration settings. These are percentages of `max_width`.
15+
# fn_call_width = 60
16+
# attr_fn_like_width = 70
17+
# struct_lit_width = 18
18+
# struct_variant_width = 35
19+
# array_width = 60
20+
# chain_width = 60
21+
# single_line_if_else_max_width = 50
22+
23+
wrap_comments = false
24+
format_code_in_doc_comments = false
25+
comment_width = 100 # Default 80
26+
normalize_comments = false
27+
normalize_doc_attributes = false
28+
format_strings = false
29+
format_macro_matchers = false
30+
format_macro_bodies = true
31+
hex_literal_case = "Preserve"
32+
empty_item_single_line = true
33+
struct_lit_single_line = true
34+
fn_single_line = true # Default false
35+
where_single_line = false
36+
imports_indent = "Block"
37+
imports_layout = "Mixed"
38+
imports_granularity = "Module" # Default "Preserve"
39+
group_imports = "StdExternalCrate" # Default "Preserve"
40+
reorder_imports = true
41+
reorder_modules = true
42+
reorder_impl_items = false
43+
type_punctuation_density = "Wide"
44+
space_before_colon = false
45+
space_after_colon = true
46+
spaces_around_ranges = false
47+
binop_separator = "Front"
48+
remove_nested_parens = true
49+
combine_control_expr = true
50+
overflow_delimited_expr = false
51+
struct_field_align_threshold = 0
52+
enum_discrim_align_threshold = 0
53+
match_arm_blocks = false # Default true
54+
match_arm_leading_pipes = "Never"
55+
force_multiline_blocks = false
56+
fn_params_layout = "Tall"
57+
brace_style = "SameLineWhere"
58+
control_brace_style = "AlwaysSameLine"
59+
trailing_semicolon = true
60+
trailing_comma = "Vertical"
61+
match_block_trailing_comma = false
62+
blank_lines_upper_bound = 1
63+
blank_lines_lower_bound = 0
64+
edition = "2021"
65+
style_edition = "2021"
66+
inline_attribute_width = 0
67+
format_generated_files = true
68+
merge_derives = true
69+
use_try_shorthand = false
70+
use_field_init_shorthand = false
71+
force_explicit_abi = true
72+
condense_wildcard_suffixes = false
73+
color = "Auto"
74+
unstable_features = false
75+
disable_all_formatting = false
76+
skip_children = false
77+
show_parse_errors = true
78+
error_on_line_overflow = false
79+
error_on_unformatted = false
80+
emit_mode = "Files"
81+
make_backup = false

src/blind.rs

Lines changed: 8 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ use secp256k1_zkp::{
2323
rand::{CryptoRng, RngCore},
2424
PedersenCommitment, SecretKey, Tag, Tweak, Verification, ZERO_TWEAK,
2525
};
26-
use secp256k1_zkp::{Generator, RangeProof, Secp256k1, Signing, SurjectionProof};
26+
use secp256k1_zkp::{Generator, Secp256k1, Signing};
2727

28-
use crate::{AddressParams, Script, TxIn};
28+
use crate::{AddressParams, RangeProof, Script, TxIn, SurjectionProof};
2929

3030
use crate::{
3131
confidential::{Asset, AssetBlindingFactor, Nonce, Value, ValueBlindingFactor},
@@ -497,13 +497,7 @@ impl Asset {
497497
})
498498
.collect::<Result<Vec<_>, _>>()?;
499499

500-
let surjection_proof = SurjectionProof::new(
501-
secp,
502-
rng,
503-
asset.into_tag(),
504-
asset_bf.into_inner(),
505-
inputs.as_ref(),
506-
)?;
500+
let surjection_proof = SurjectionProof::new(secp, rng, asset, asset_bf, inputs)?;
507501

508502
Ok((out_asset, surjection_proof))
509503
}
@@ -657,7 +651,7 @@ impl TxOut {
657651
out_secrets.asset_bf,
658652
);
659653
let exp_value = Value::Explicit(out_secrets.value);
660-
let (out_value, nonce, range_proof) = exp_value.blind(
654+
let (out_value, nonce, rangeproof) = exp_value.blind(
661655
secp,
662656
out_secrets.value_bf,
663657
receiver_blinding_pk,
@@ -672,8 +666,8 @@ impl TxOut {
672666
nonce,
673667
script_pubkey: spk,
674668
witness: TxOutWitness {
675-
surjection_proof: Some(Box::new(surjection_proof)),
676-
rangeproof: Some(Box::new(range_proof)),
669+
surjection_proof,
670+
rangeproof,
677671
},
678672
};
679673
Ok(txout)
@@ -977,10 +971,10 @@ impl TxIn {
977971
let (comm, prf) = v.blind_with_shared_secret(secp, bf, blind_sk, &spk, &msg)?;
978972
if i == 0 {
979973
self.asset_issuance.amount = comm;
980-
self.witness.amount_rangeproof = Some(Box::new(prf));
974+
self.witness.amount_rangeproof = prf;
981975
} else {
982976
self.asset_issuance.inflation_keys = comm;
983-
self.witness.inflation_keys_rangeproof = Some(Box::new(prf));
977+
self.witness.inflation_keys_rangeproof = prf;
984978
}
985979
}
986980
Ok(())
@@ -1365,122 +1359,6 @@ impl From<ConfidentialTxOutError> for BlindError {
13651359
}
13661360
}
13671361

1368-
/// A trait to create and verify explicit rangeproofs
1369-
pub trait BlindValueProofs: Sized {
1370-
/// Outputs a `[RangeProof]` that blinded value
1371-
/// corresponfs to unblinded explicit value
1372-
fn blind_value_proof<C: secp256k1_zkp::Signing, R: RngCore + CryptoRng>(
1373-
rng: &mut R,
1374-
secp: &Secp256k1<C>,
1375-
explicit_val: u64,
1376-
value_commit: PedersenCommitment,
1377-
asset_gen: Generator,
1378-
vbf: ValueBlindingFactor,
1379-
) -> Result<Self, secp256k1_zkp::Error>;
1380-
1381-
/// Verify that the Rangeproof proves that commitment
1382-
/// is actually bound to the explicit value
1383-
fn blind_value_proof_verify<C: secp256k1_zkp::Verification>(
1384-
&self,
1385-
secp: &Secp256k1<C>,
1386-
explicit_val: u64,
1387-
asset_gen: Generator,
1388-
value_commit: PedersenCommitment,
1389-
) -> bool;
1390-
}
1391-
1392-
impl BlindValueProofs for RangeProof {
1393-
/// Outputs a [`RangeProof`] that blinded `value_commit`
1394-
/// corresponds to explicit value
1395-
fn blind_value_proof<C: secp256k1_zkp::Signing, R: RngCore + CryptoRng>(
1396-
rng: &mut R,
1397-
secp: &Secp256k1<C>,
1398-
explicit_val: u64,
1399-
value_commit: PedersenCommitment,
1400-
asset_gen: Generator,
1401-
vbf: ValueBlindingFactor,
1402-
) -> Result<Self, secp256k1_zkp::Error> {
1403-
RangeProof::new(
1404-
secp,
1405-
explicit_val, // min_value
1406-
value_commit, // value_commit
1407-
explicit_val, // value
1408-
vbf.into_inner(), // blinding factor
1409-
&[], // message
1410-
&[], // add commitment
1411-
SecretKey::new(rng), // nonce
1412-
-1, // exp
1413-
0, // min bits
1414-
asset_gen, // additional gen
1415-
)
1416-
}
1417-
1418-
/// Verify that the Rangeproof proves that commitment
1419-
/// is actually bound to the explicit value
1420-
fn blind_value_proof_verify<C: secp256k1_zkp::Verification>(
1421-
&self,
1422-
secp: &Secp256k1<C>,
1423-
explicit_val: u64,
1424-
asset_gen: Generator,
1425-
value_commit: PedersenCommitment,
1426-
) -> bool {
1427-
let r = self.verify(secp, value_commit, &[], asset_gen);
1428-
match r {
1429-
Ok(e) => e.start == explicit_val && e.end - 1 == explicit_val,
1430-
Err(..) => false,
1431-
}
1432-
}
1433-
}
1434-
1435-
/// A trait to create and verify explicit surjection proofs
1436-
pub trait BlindAssetProofs: Sized {
1437-
/// Outputs a `[SurjectionProof]` that blinded asset
1438-
/// corresponfs to unblinded explicit asset
1439-
fn blind_asset_proof<C: secp256k1_zkp::Signing, R: RngCore + CryptoRng>(
1440-
rng: &mut R,
1441-
secp: &Secp256k1<C>,
1442-
asset: AssetId,
1443-
abf: AssetBlindingFactor,
1444-
) -> Result<Self, secp256k1_zkp::Error>;
1445-
1446-
/// Verify that the Surjection proves that asset commitment
1447-
/// is actually bound to the explicit asset
1448-
fn blind_asset_proof_verify(
1449-
&self,
1450-
secp: &Secp256k1<secp256k1_zkp::All>,
1451-
asset: AssetId,
1452-
asset_commit: Generator,
1453-
) -> bool;
1454-
}
1455-
1456-
impl BlindAssetProofs for SurjectionProof {
1457-
fn blind_asset_proof<C: secp256k1_zkp::Signing, R: RngCore + CryptoRng>(
1458-
rng: &mut R,
1459-
secp: &Secp256k1<C>,
1460-
asset: AssetId,
1461-
abf: AssetBlindingFactor,
1462-
) -> Result<Self, secp256k1_zkp::Error> {
1463-
let gen = Generator::new_unblinded(secp, asset.into_tag());
1464-
SurjectionProof::new(
1465-
secp,
1466-
rng,
1467-
asset.into_tag(),
1468-
abf.into_inner(),
1469-
&[(gen, asset.into_tag(), ZERO_TWEAK)],
1470-
)
1471-
}
1472-
1473-
fn blind_asset_proof_verify(
1474-
&self,
1475-
secp: &Secp256k1<secp256k1_zkp::All>,
1476-
asset: AssetId,
1477-
asset_commit: Generator,
1478-
) -> bool {
1479-
let gen = Generator::new_unblinded(secp, asset.into_tag());
1480-
self.verify(secp, asset_commit, &[gen])
1481-
}
1482-
}
1483-
14841362
#[cfg(test)]
14851363
mod tests {
14861364
use super::*;

0 commit comments

Comments
 (0)