Skip to content

Commit 128f6cf

Browse files
committed
Add test checking that imbalanced deltas fail verification.
1 parent 5df9cef commit 128f6cf

File tree

1 file changed

+42
-15
lines changed

1 file changed

+42
-15
lines changed

contracts/test/proofs/DeltaProof.t.sol

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ contract DeltaProofTest is Test {
101101
function test_verify_inconsistent_delta_fails2(DeltaProofInputs memory deltaInputs1, DeltaInstanceInputs memory deltaInputs2) public {
102102
deltaInputs2.quantity = 0;
103103
// Filter out inadmissible private keys or equal keys
104-
vm.assume(deltaInputs1.rcv != deltaInputs2.rcv);
104+
vm.assume((deltaInputs1.rcv % SECP256K1_ORDER) != (deltaInputs2.rcv % SECP256K1_ORDER));
105105
// Generate a delta proof and instance from the above tags and preimage
106106
bytes memory proof1 = generateDeltaProof(deltaInputs1);
107107
uint256[2] memory instance2 = generateDeltaInstance(deltaInputs2);
@@ -124,17 +124,18 @@ contract DeltaProofTest is Test {
124124
Delta.verify({proof: proof1, instance: instance2, verifyingKey: verifyingKey});
125125
}
126126

127-
/// @notice Balance the delta inputs and also return the total value commitment randomness
128-
function balanceDeltaInputs(DeltaInstanceInputs[] memory deltaInputs) public pure returns (DeltaInstanceInputs[] memory balancedDeltaInputs, uint256 rcv_acc) {
127+
/// @notice Wrap the delta inputs in such a way that they can be balanced
128+
/// and also return the total quantity and value commitment randomness
129+
function wrapDeltaInputs(DeltaInstanceInputs[] memory deltaInputs) public pure returns (DeltaInstanceInputs[] memory wrappedDeltaInputs, int128 quantity_acc, uint256 rcv_acc) {
129130
// Grab the kind to use for all deltas
130131
uint128 kind = deltaInputs.length > 0 ? deltaInputs[0].kind : 0;
131132
// Compute the window into which the deltas should sum
132133
int128 half_max = type(int128).max >> 1;
133134
int128 half_min = type(int128).min >> 1;
134135
// Track the current quantity and value commitment randomness
135-
int128 quantity_acc = 0;
136+
quantity_acc = 0;
136137
rcv_acc = 0;
137-
// Balance out the deltas
138+
// Wrap the deltas
138139
for(uint i = 0; i < deltaInputs.length; i++) {
139140
// Ensure that all the deltas have the same kind
140141
deltaInputs[i].kind = kind;
@@ -151,12 +152,8 @@ contract DeltaProofTest is Test {
151152
// Finally, accumulate the adjusted quantity
152153
quantity_acc += deltaInputs[i].quantity;
153154
}
154-
// Adjust the last delta so that the full sum is zero
155-
if(quantity_acc != 0) {
156-
deltaInputs[deltaInputs.length - 1].quantity -= quantity_acc;
157-
}
158-
// Finally, return tbe balanced deltas
159-
balancedDeltaInputs = deltaInputs;
155+
// Finally, return tbe wrapped deltas
156+
wrappedDeltaInputs = deltaInputs;
160157
}
161158

162159
/// @notice Grab the first length elements from deltaInputs
@@ -173,11 +170,15 @@ contract DeltaProofTest is Test {
173170
// Truncate the delta inputs to improve test performance
174171
uint MAX_DELTA_LEN = 10;
175172
deltaInputs = truncateDeltaInputs(deltaInputs, deltaInputs.length % MAX_DELTA_LEN);
176-
// Make sure that the delta qquantities balance out
177-
(DeltaInstanceInputs[] memory balancedDeltaInputs, uint256 rcv) = balanceDeltaInputs(deltaInputs);
178-
for(uint i = 0; i < balancedDeltaInputs.length; i++) {
173+
// Make sure that the delta quantities balance out
174+
(DeltaInstanceInputs[] memory wrappedDeltaInputs, int128 quantity, uint256 rcv) = wrapDeltaInputs(deltaInputs);
175+
// Adjust the last delta so that the full sum is zero
176+
if(quantity != 0) {
177+
wrappedDeltaInputs[wrappedDeltaInputs.length - 1].quantity -= quantity;
178+
}
179+
for(uint i = 0; i < wrappedDeltaInputs.length; i++) {
179180
// Compute the delta instance and accumulate it
180-
uint256[2] memory instance = generateDeltaInstance(balancedDeltaInputs[i]);
181+
uint256[2] memory instance = generateDeltaInstance(wrappedDeltaInputs[i]);
181182
deltaAcc = Delta.add(deltaAcc, instance);
182183
}
183184
// Compute the proof for the balanced transaction
@@ -190,6 +191,32 @@ contract DeltaProofTest is Test {
190191
Delta.verify({proof: proof, instance: deltaAcc, verifyingKey: verifyingKey});
191192
}
192193

194+
/// @notice Check that an imbalanced transaction fails verification
195+
function test_verify_imbalanced_delta_fails(DeltaInstanceInputs[] memory deltaInputs, bytes32 verifyingKey) public {
196+
uint256[2] memory deltaAcc = [uint256(0), uint256(0)];
197+
// Truncate the delta inputs to improve test performance
198+
uint MAX_DELTA_LEN = 10;
199+
deltaInputs = truncateDeltaInputs(deltaInputs, deltaInputs.length % MAX_DELTA_LEN);
200+
// Accumulate the total quantity and randomness commitment
201+
(DeltaInstanceInputs[] memory wrappedDeltaInputs, int128 quantity, uint256 rcv) = wrapDeltaInputs(deltaInputs);
202+
// Assume that the deltas are imbalanced
203+
vm.assume(quantity != 0);
204+
for(uint i = 0; i < wrappedDeltaInputs.length; i++) {
205+
// Compute the delta instance and accumulate it
206+
uint256[2] memory instance = generateDeltaInstance(wrappedDeltaInputs[i]);
207+
deltaAcc = Delta.add(deltaAcc, instance);
208+
}
209+
// Compute the proof for the balanced transaction
210+
DeltaProofInputs memory sumDeltaInputs = DeltaProofInputs({
211+
rcv: rcv,
212+
verifyingKey: verifyingKey
213+
});
214+
bytes memory proof = generateDeltaProof(sumDeltaInputs);
215+
// Verify that the imbalanced transaction proof fails
216+
vm.expectPartialRevert(Delta.DeltaMismatch.selector);
217+
Delta.verify({proof: proof, instance: deltaAcc, verifyingKey: verifyingKey});
218+
}
219+
193220
function test_signatureIntegrity() public pure {
194221
(uint8 v, bytes32 r, bytes32 s) = vm.sign(MockDelta.SIGNER_PRIVATE_KEY, MockDelta.MESSAGE_HASH);
195222
assertEq(r, MockDelta.R);

0 commit comments

Comments
 (0)