Skip to content

Commit ad39471

Browse files
committed
Generalize transaction generation
1 parent 9dd4945 commit ad39471

File tree

2 files changed

+171
-4
lines changed

2 files changed

+171
-4
lines changed

contracts/test/ProtocolAdapterMock.t.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ contract ProtocolAdapterMockVerifierTest is Test {
240240
_mockPa.execute(txn);
241241
}
242242

243+
function test_random_transactions_execute(TxGen.TransactionParams memory params) public {
244+
_mockPa.execute(vm.transaction(_mockVerifier, params));
245+
}
246+
243247
function testFuzz_execute_reverts_on_pre_existing_nullifier(bool aggregated) public {
244248
TxGen.ActionConfig[] memory configs = TxGen.generateActionConfigs({actionCount: 1, complianceUnitCount: 1});
245249

contracts/test/libs/TxGen.sol

Lines changed: 167 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ library TxGen {
2121
using Logic for Logic.VerifierInput[];
2222
using Logic for Logic.VerifierInput;
2323

24+
uint256 public constant MAX_ACTIONS = 4;
25+
uint256 public constant MAX_RESOURCES = 5;
26+
2427
struct ActionConfig {
2528
uint256 complianceUnitCount;
2629
}
@@ -35,6 +38,18 @@ library TxGen {
3538
ResourceAndAppData[] created;
3639
}
3740

41+
struct ActionParams {
42+
Resource[2][MAX_RESOURCES] resources;
43+
uint256[MAX_RESOURCES] bijection;
44+
uint256 targetResourcesLen;
45+
uint256[2][MAX_RESOURCES] valueCommitmentRandomness;
46+
}
47+
48+
struct TransactionParams {
49+
ActionParams[MAX_ACTIONS] actionParams;
50+
uint256 targetActionsLen;
51+
}
52+
3853
error ConsumedCreatedCountMismatch(uint256 nConsumed, uint256 nCreated);
3954
error NonExistingTag(bytes32 tag);
4055
error TransactionTagCountMismatch();
@@ -44,7 +59,9 @@ library TxGen {
4459
RiscZeroMockVerifier mockVerifier,
4560
bytes32 commitmentTreeRoot, // historical root
4661
Resource memory consumed,
47-
Resource memory created
62+
uint256 consumedValueCommitmentRandomness,
63+
Resource memory created,
64+
uint256 createdValueCommitmentRandomness
4865
) internal returns (Compliance.VerifierInput memory unit) {
4966
bytes32 nf = nullifier(consumed, 0);
5067
bytes32 cm = commitment(created);
@@ -56,7 +73,7 @@ library TxGen {
5673
kind: kind(consumed),
5774
quantity: consumed.quantity,
5875
consumed: true,
59-
valueCommitmentRandomness: 1
76+
valueCommitmentRandomness: consumedValueCommitmentRandomness
6077
})
6178
);
6279
// Construct the delta for creation based on kind and quantity
@@ -68,7 +85,7 @@ library TxGen {
6885
kind: kind(created),
6986
quantity: created.quantity,
7087
consumed: false,
71-
valueCommitmentRandomness: 1
88+
valueCommitmentRandomness: createdValueCommitmentRandomness
7289
})
7390
)
7491
);
@@ -139,7 +156,9 @@ library TxGen {
139156
mockVerifier: mockVerifier,
140157
commitmentTreeRoot: initialRoot(),
141158
consumed: consumed[i].resource,
142-
created: created[i].resource
159+
consumedValueCommitmentRandomness: 1,
160+
created: created[i].resource,
161+
createdValueCommitmentRandomness: 1
143162
});
144163
}
145164
action = Action({logicVerifierInputs: logicVerifierInputs, complianceVerifierInputs: complianceVerifierInputs});
@@ -287,6 +306,111 @@ library TxGen {
287306
}).seal;
288307
}
289308

309+
function generateAction(VmSafe vm, RiscZeroMockVerifier mockVerifier, ActionParams memory params)
310+
internal
311+
returns (Action memory action, uint256 totalValueCommitmentRandomness)
312+
{
313+
Resource[2][] memory truncatedResources =
314+
truncateResources(params.resources, params.targetResourcesLen % MAX_RESOURCES);
315+
action.logicVerifierInputs = new Logic.VerifierInput[](truncatedResources.length * 2);
316+
action.complianceVerifierInputs = new Compliance.VerifierInput[](truncatedResources.length);
317+
// Created empty app data for all the resources
318+
Logic.AppData memory appData = Logic.AppData({
319+
resourcePayload: new Logic.ExpirableBlob[](0),
320+
discoveryPayload: new Logic.ExpirableBlob[](0),
321+
externalPayload: new Logic.ExpirableBlob[](0),
322+
applicationPayload: new Logic.ExpirableBlob[](0)
323+
});
324+
// Match the created and consumed resources
325+
uint256[] memory bijection = generateBijection(params.bijection, truncatedResources.length);
326+
for (uint256 i = 0; i < truncatedResources.length; ++i) {
327+
truncatedResources[bijection[i]][1].quantity = truncatedResources[i][0].quantity;
328+
truncatedResources[bijection[i]][1].logicRef = truncatedResources[i][0].logicRef;
329+
truncatedResources[bijection[i]][1].labelRef = truncatedResources[i][0].labelRef;
330+
}
331+
// Compute action tree tags and action tree root
332+
bytes32[] memory actionTreeTags = new bytes32[](2 * truncatedResources.length);
333+
totalValueCommitmentRandomness = 0;
334+
for (uint256 i = 0; i < truncatedResources.length; ++i) {
335+
uint256 index = (i * 2);
336+
337+
actionTreeTags[index] = nullifier(truncatedResources[i][0], 0);
338+
actionTreeTags[index + 1] = commitment(truncatedResources[i][1]);
339+
// Adjust and accumulate the value randomness commitments
340+
params.valueCommitmentRandomness[i][0] =
341+
1 + (params.valueCommitmentRandomness[i][0] % (DeltaGen.SECP256K1_ORDER - 1));
342+
params.valueCommitmentRandomness[i][1] =
343+
1 + (params.valueCommitmentRandomness[i][1] % (DeltaGen.SECP256K1_ORDER - 1));
344+
totalValueCommitmentRandomness =
345+
addmod(totalValueCommitmentRandomness, params.valueCommitmentRandomness[i][0], DeltaGen.SECP256K1_ORDER);
346+
totalValueCommitmentRandomness =
347+
addmod(totalValueCommitmentRandomness, params.valueCommitmentRandomness[i][1], DeltaGen.SECP256K1_ORDER);
348+
}
349+
bytes32 actionTreeRoot = actionTreeTags.computeRoot();
350+
// Create logic and compliance verifier inputs
351+
for (uint256 i = 0; i < truncatedResources.length; i++) {
352+
uint256 index = (i * 2);
353+
354+
Resource memory consumedResource = truncatedResources[i][0];
355+
Resource memory createdResource = truncatedResources[i][1];
356+
// Created logic verifier input for a consumed resource
357+
action.logicVerifierInputs[index] = logicVerifierInput({
358+
mockVerifier: mockVerifier,
359+
actionTreeRoot: actionTreeRoot,
360+
resource: consumedResource,
361+
isConsumed: true,
362+
appData: appData
363+
});
364+
// Create logic verifier input for a created resource
365+
action.logicVerifierInputs[index + 1] = logicVerifierInput({
366+
mockVerifier: mockVerifier,
367+
actionTreeRoot: actionTreeRoot,
368+
resource: createdResource,
369+
isConsumed: false,
370+
appData: appData
371+
});
372+
// Create compliance verifier input for the resource pairs
373+
action.complianceVerifierInputs[i] = complianceVerifierInput({
374+
vm: vm,
375+
mockVerifier: mockVerifier,
376+
commitmentTreeRoot: initialRoot(),
377+
consumed: consumedResource,
378+
consumedValueCommitmentRandomness: params.valueCommitmentRandomness[i][0],
379+
created: createdResource,
380+
createdValueCommitmentRandomness: params.valueCommitmentRandomness[i][1]
381+
});
382+
}
383+
}
384+
385+
function transaction(VmSafe vm, RiscZeroMockVerifier mockVerifier, TransactionParams memory params)
386+
internal
387+
returns (Transaction memory txn)
388+
{
389+
// Generate actions
390+
Action[] memory actions = new Action[](params.targetActionsLen % MAX_ACTIONS);
391+
uint256 totalValueCommitmentRandomness = 0;
392+
for (uint256 i = 0; i < actions.length; i++) {
393+
uint256 valueCommitmentRandomness;
394+
(actions[i], valueCommitmentRandomness) = generateAction(vm, mockVerifier, params.actionParams[i]);
395+
totalValueCommitmentRandomness =
396+
addmod(totalValueCommitmentRandomness, valueCommitmentRandomness, DeltaGen.SECP256K1_ORDER);
397+
}
398+
// Generate delta proof
399+
bytes memory proof = "";
400+
bytes32[] memory tags = TxGen.collectTags(actions);
401+
if (tags.length != 0) {
402+
proof = DeltaGen.generateProof(
403+
vm,
404+
DeltaGen.ProofInputs({
405+
valueCommitmentRandomness: totalValueCommitmentRandomness,
406+
verifyingKey: Delta.computeVerifyingKey(tags)
407+
})
408+
);
409+
}
410+
// Generate transaction
411+
txn = Transaction({actions: actions, deltaProof: proof, aggregationProof: ""});
412+
}
413+
290414
function logicVerifierInput(
291415
RiscZeroMockVerifier mockVerifier,
292416
bytes32 actionTreeRoot,
@@ -479,4 +603,43 @@ library TxGen {
479603

480604
root = actionTreeTags.computeRoot();
481605
}
606+
607+
function truncateResources(Resource[2][MAX_RESOURCES] memory resources, uint256 len)
608+
internal
609+
pure
610+
returns (Resource[2][] memory truncatedResources)
611+
{
612+
truncatedResources = new Resource[2][](len);
613+
for (uint256 i = 0; i < len; i++) {
614+
truncatedResources[i][0] = resources[i][0];
615+
truncatedResources[i][1] = resources[i][1];
616+
}
617+
}
618+
619+
function generateBijection(uint256[MAX_RESOURCES] memory input, uint256 len)
620+
internal
621+
pure
622+
returns (uint256[] memory output)
623+
{
624+
output = new uint256[](len);
625+
uint256[] memory duplicates = new uint256[](len);
626+
uint256 duplicateCount = 0;
627+
for (uint256 i = 0; i < len; i++) {
628+
output[i] = duplicates[i] = len;
629+
input[i] %= len;
630+
}
631+
for (uint256 i = 0; i < len; i++) {
632+
if (output[input[i]] == len) {
633+
output[input[i]] = i;
634+
} else {
635+
duplicates[duplicateCount++] = i;
636+
}
637+
}
638+
duplicateCount = 0;
639+
for (uint256 i = 0; i < len; i++) {
640+
if (output[i] == len) {
641+
output[i] = duplicates[duplicateCount++];
642+
}
643+
}
644+
}
482645
}

0 commit comments

Comments
 (0)