@@ -101,7 +101,7 @@ contract DeltaProofTest is Test {
101
101
function test_verify_inconsistent_delta_fails2 (DeltaProofInputs memory deltaInputs1 , DeltaInstanceInputs memory deltaInputs2 ) public {
102
102
deltaInputs2.quantity = 0 ;
103
103
// 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) );
105
105
// Generate a delta proof and instance from the above tags and preimage
106
106
bytes memory proof1 = generateDeltaProof (deltaInputs1);
107
107
uint256 [2 ] memory instance2 = generateDeltaInstance (deltaInputs2);
@@ -124,17 +124,18 @@ contract DeltaProofTest is Test {
124
124
Delta.verify ({proof: proof1, instance: instance2, verifyingKey: verifyingKey});
125
125
}
126
126
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 ) {
129
130
// Grab the kind to use for all deltas
130
131
uint128 kind = deltaInputs.length > 0 ? deltaInputs[0 ].kind : 0 ;
131
132
// Compute the window into which the deltas should sum
132
133
int128 half_max = type (int128 ).max >> 1 ;
133
134
int128 half_min = type (int128 ).min >> 1 ;
134
135
// Track the current quantity and value commitment randomness
135
- int128 quantity_acc = 0 ;
136
+ quantity_acc = 0 ;
136
137
rcv_acc = 0 ;
137
- // Balance out the deltas
138
+ // Wrap the deltas
138
139
for (uint i = 0 ; i < deltaInputs.length ; i++ ) {
139
140
// Ensure that all the deltas have the same kind
140
141
deltaInputs[i].kind = kind;
@@ -151,12 +152,8 @@ contract DeltaProofTest is Test {
151
152
// Finally, accumulate the adjusted quantity
152
153
quantity_acc += deltaInputs[i].quantity;
153
154
}
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;
160
157
}
161
158
162
159
/// @notice Grab the first length elements from deltaInputs
@@ -173,11 +170,15 @@ contract DeltaProofTest is Test {
173
170
// Truncate the delta inputs to improve test performance
174
171
uint MAX_DELTA_LEN = 10 ;
175
172
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++ ) {
179
180
// Compute the delta instance and accumulate it
180
- uint256 [2 ] memory instance = generateDeltaInstance (balancedDeltaInputs [i]);
181
+ uint256 [2 ] memory instance = generateDeltaInstance (wrappedDeltaInputs [i]);
181
182
deltaAcc = Delta.add (deltaAcc, instance);
182
183
}
183
184
// Compute the proof for the balanced transaction
@@ -190,6 +191,32 @@ contract DeltaProofTest is Test {
190
191
Delta.verify ({proof: proof, instance: deltaAcc, verifyingKey: verifyingKey});
191
192
}
192
193
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
+
193
220
function test_signatureIntegrity () public pure {
194
221
(uint8 v , bytes32 r , bytes32 s ) = vm.sign (MockDelta.SIGNER_PRIVATE_KEY, MockDelta.MESSAGE_HASH);
195
222
assertEq (r, MockDelta.R);
0 commit comments