Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,28 @@ fn build_bundle<B, R: RngCore>(
// as we can estimate the vector size beforehand.
let mut indexed_spends_outputs = Vec::with_capacity(num_actions);

let spends_outputs_by_asset = partition_by_asset(&spends, &outputs);
let mut spends_outputs_by_asset = partition_by_asset(&spends, &outputs);

// For zatoshi-only bundles, pad spends and outputs to num_actions
// before per-asset processing, so that dummies are created before the shuffle —
// matching vanilla Orchard RNG consumption order.
if spends_outputs_by_asset
.keys()
.all(|asset| asset == &AssetBase::zatoshi())
{
let (asset_spends, asset_outputs) = spends_outputs_by_asset
.entry(AssetBase::zatoshi())
.or_insert_with(|| (vec![], vec![]));
asset_spends.extend(
iter::repeat_with(|| (SpendInfo::dummy(AssetBase::zatoshi(), &mut rng), None))
.take(num_actions.saturating_sub(asset_spends.len())),
);
asset_outputs.extend(
iter::repeat_with(|| (OutputInfo::dummy(&mut rng, AssetBase::zatoshi()), None))
.take(num_actions.saturating_sub(asset_outputs.len())),
);
}
let asset_count = spends_outputs_by_asset.len();

indexed_spends_outputs.extend(spends_outputs_by_asset.into_iter().flat_map(
|(asset, (spends, outputs))| {
Expand Down Expand Up @@ -1009,6 +1030,9 @@ fn build_bundle<B, R: RngCore>(
},
));

// Pad total actions to num_actions.
// This covers the edge case of a single non-zatoshi asset with fewer than
// MIN_ACTIONS spends/outputs (e.g. a bundle that only burns a custom asset).
indexed_spends_outputs.extend(
iter::repeat_with(|| {
(
Expand All @@ -1021,7 +1045,9 @@ fn build_bundle<B, R: RngCore>(

// We shuffled the spends and outputs within each `AssetBase` above; now we
// shuffle the actions to achieve a similar property across `AssetBase`s.
indexed_spends_outputs.shuffle(&mut rng);
if asset_count > 1 {
indexed_spends_outputs.shuffle(&mut rng);
}

let mut bundle_meta = BundleMetadata::new(num_requested_spends, num_requested_outputs);
let pre_actions = indexed_spends_outputs
Expand Down
12 changes: 8 additions & 4 deletions src/bundle/commitments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,9 @@ mod tests {
let sighash = hash_bundle_txid_data(&bundle);
assert_eq!(
sighash.to_hex().as_str(),
"f3ea89ea2b1e17b3313a6f2f9e4e47c21eec1574902f5ea6961227e1eaed2327"
// Bundle hash for Orchard (vanilla) generated using
// Zcash/Orchard commit: 9d89b504
"0ac1e319f6761a8561b7bd3fc0907a5c73ed5590a6c210c4d39ffae1d5741875"
);
}

Expand All @@ -184,7 +186,7 @@ mod tests {
let sighash = hash_bundle_txid_data(&bundle);
assert_eq!(
sighash.to_hex().as_str(),
"a0d843b7278788e3b47dc9fe1e1da227a94898b7111d76514a87df486d32773c"
"f84871d872081fa7744cbaf575e342cf81951a9b17818264170243d1551a99ea"
);
}

Expand Down Expand Up @@ -213,7 +215,9 @@ mod tests {
let orchard_auth_digest = hash_bundle_auth_data(&bundle, test_sighash_info_for_kind);
assert_eq!(
orchard_auth_digest.to_hex().as_str(),
"c99aa5a33fd4e7b78de0ee846397e2eb0da3a5d176e6df57d0401c49f51d7295"
// Bundle hash for Orchard (vanilla) generated using
// Zcash/Orchard commit: 9d89b504
"5f3bcf759cddf19170ec47a882a470b5767d66c95fc72ffc360f31324474a06b"
);
}

Expand All @@ -230,7 +234,7 @@ mod tests {
let orchard_auth_digest = hash_bundle_auth_data(&bundle, test_sighash_info_for_kind);
assert_eq!(
orchard_auth_digest.to_hex().as_str(),
"9d47819082f2323b30ceabe0fea993b39541cc0e62a8be6e1bc2a19840b0d9ab"
"0c29408a07863016f5b4c5c0ccc5b944f24c686d06035945c5514f8b8c195a99"
);
}

Expand Down
16 changes: 8 additions & 8 deletions tests/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,16 @@ fn bundle_chain_vanilla() {
orchard_digest_1,
// Locks the `orchard_digest` for OrchardVanilla
[
25, 143, 25, 148, 146, 133, 196, 243, 163, 122, 136, 217, 179, 122, 70, 233, 4, 4, 26,
170, 152, 243, 177, 199, 226, 241, 63, 143, 104, 77, 149, 254
165, 242, 106, 135, 168, 224, 110, 252, 175, 110, 63, 29, 78, 243, 33, 14, 152, 202,
209, 47, 68, 32, 138, 96, 79, 213, 218, 93, 45, 87, 221, 174
]
);
assert_eq!(
orchard_digest_2,
// Locks the `orchard_digest` for OrchardVanilla
[
164, 197, 26, 212, 108, 232, 219, 47, 64, 35, 3, 171, 77, 191, 253, 173, 173, 0, 148,
119, 98, 210, 134, 196, 201, 205, 117, 10, 37, 72, 234, 3
74, 174, 42, 41, 68, 92, 171, 110, 10, 148, 217, 61, 68, 50, 49, 1, 1, 180, 221, 210,
97, 237, 25, 198, 195, 77, 19, 160, 186, 172, 8, 26
]
);
}
Expand All @@ -234,16 +234,16 @@ fn bundle_chain_zsa() {
orchard_digest_1,
// Locks the `orchard_digest` for OrchardZSA
[
47, 247, 30, 9, 58, 47, 181, 208, 48, 162, 133, 51, 186, 54, 13, 82, 207, 227, 33, 48,
223, 31, 90, 129, 96, 166, 247, 156, 122, 125, 100, 190
176, 24, 152, 89, 60, 222, 215, 240, 176, 197, 147, 81, 4, 84, 61, 189, 163, 117, 43,
201, 63, 140, 116, 211, 133, 186, 54, 58, 171, 124, 192, 215
]
);
assert_eq!(
orchard_digest_2,
// Locks the `orchard_digest` for OrchardZSA
[
40, 249, 161, 168, 11, 100, 205, 146, 11, 203, 210, 239, 51, 73, 208, 236, 47, 110, 49,
18, 132, 199, 179, 63, 140, 28, 106, 34, 155, 93, 111, 254
161, 158, 107, 122, 89, 77, 236, 178, 130, 85, 148, 101, 237, 1, 67, 119, 76, 126, 233,
123, 94, 240, 183, 227, 9, 245, 74, 51, 16, 12, 157, 60
]
);
}
Loading