add test to demonstrate pair of "half" kernels sharing same public excess (#3314)
* cleanup how we handle key splitting for transaction offset add test to demonstrate a pair of transaction halves sharing same kernel excess * cleanup * cleanup
This commit is contained in:
+35
-24
@@ -199,47 +199,58 @@ where
|
||||
}
|
||||
|
||||
/// Builds a complete transaction.
|
||||
/// NOTE: We only use this in tests (for convenience).
|
||||
/// In the real world we use signature aggregation across multiple participants.
|
||||
pub fn transaction<K, B>(
|
||||
features: KernelFeatures,
|
||||
elems: Vec<Box<Append<K, B>>>,
|
||||
keychain: &K,
|
||||
builder: &B,
|
||||
) -> Result<Transaction, Error>
|
||||
where
|
||||
K: Keychain,
|
||||
B: ProofBuild,
|
||||
{
|
||||
let mut kernel = TxKernel::with_features(features);
|
||||
|
||||
// Construct the message to be signed.
|
||||
let msg = kernel.msg_to_sign()?;
|
||||
|
||||
// Generate kernel public excess and associated signature.
|
||||
let excess = BlindingFactor::rand(&keychain.secp());
|
||||
let skey = excess.secret_key(&keychain.secp())?;
|
||||
kernel.excess = keychain.secp().commit(0, skey)?;
|
||||
let pubkey = &kernel.excess.to_pubkey(&keychain.secp())?;
|
||||
kernel.excess_sig = aggsig::sign_with_blinding(&keychain.secp(), &msg, &excess, Some(&pubkey))?;
|
||||
kernel.verify()?;
|
||||
transaction_with_kernel(elems, kernel, excess, keychain, builder)
|
||||
}
|
||||
|
||||
/// Build a complete transaction with the provided kernel and corresponding private excess.
|
||||
/// NOTE: Only used in tests (for convenience).
|
||||
/// Cannot recommend passing private excess around like this in the real world.
|
||||
pub fn transaction_with_kernel<K, B>(
|
||||
elems: Vec<Box<Append<K, B>>>,
|
||||
kernel: TxKernel,
|
||||
excess: BlindingFactor,
|
||||
keychain: &K,
|
||||
builder: &B,
|
||||
) -> Result<Transaction, Error>
|
||||
where
|
||||
K: Keychain,
|
||||
B: ProofBuild,
|
||||
{
|
||||
let mut ctx = Context { keychain, builder };
|
||||
let (mut tx, sum) = elems
|
||||
let (tx, sum) = elems
|
||||
.iter()
|
||||
.fold(Ok((Transaction::empty(), BlindSum::new())), |acc, elem| {
|
||||
elem(&mut ctx, acc)
|
||||
})?;
|
||||
let blind_sum = ctx.keychain.blind_sum(&sum)?;
|
||||
|
||||
// Split the key so we can generate an offset for the tx.
|
||||
let split = blind_sum.split(&keychain.secp())?;
|
||||
let k1 = split.blind_1;
|
||||
let k2 = split.blind_2;
|
||||
|
||||
let mut kern = TxKernel::with_features(features);
|
||||
|
||||
// Construct the message to be signed.
|
||||
let msg = kern.msg_to_sign()?;
|
||||
|
||||
// Generate kernel excess and excess_sig using the split key k1.
|
||||
let skey = k1.secret_key(&keychain.secp())?;
|
||||
kern.excess = ctx.keychain.secp().commit(0, skey)?;
|
||||
let pubkey = &kern.excess.to_pubkey(&keychain.secp())?;
|
||||
kern.excess_sig = aggsig::sign_with_blinding(&keychain.secp(), &msg, &k1, Some(&pubkey))?;
|
||||
|
||||
// Store the kernel offset (k2) on the tx.
|
||||
// Commitments will sum correctly when accounting for the offset.
|
||||
tx.offset = k2;
|
||||
|
||||
// Set the kernel on the tx.
|
||||
let tx = tx.replace_kernel(kern);
|
||||
|
||||
// Update tx with new kernel and offset.
|
||||
let mut tx = tx.replace_kernel(kernel);
|
||||
tx.offset = blind_sum.split(&excess, &keychain.secp())?;
|
||||
Ok(tx)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user