Skip to content

Commit

Permalink
Multi Quark Replays
Browse files Browse the repository at this point in the history
This patch fixes the function names of and tests replaying multi-quark operations. By and large, nothing changed and this works out of the box more or less for free, but we want to make sure we test the behavior to ensure there's no gotchas and that storage is correct, etc. So far, so good.
  • Loading branch information
hayesgm committed Sep 11, 2024
1 parent 3ebfc51 commit 72d6883
Show file tree
Hide file tree
Showing 3 changed files with 358 additions and 12 deletions.
12 changes: 6 additions & 6 deletions src/quark-core/src/QuarkWallet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -220,23 +220,23 @@ contract QuarkWallet is IERC1271 {
bytes32 r,
bytes32 s
) public returns (bytes memory) {
return executeMultiQuarkOperationWithReplayToken(op, op.nonce, opDigests, v, r, s);
return executeMultiQuarkOperationWithSubmissionToken(op, op.nonce, opDigests, v, r, s);
}

/**
* @notice Executes a first play or a replay of a QuarkOperation that is part of a MultiQuarkOperation via signature
* @dev Can only be called with signatures from the wallet's signer
* @param op A QuarkOperation struct
* @param replayToken A replay token. For replayables, initial value should be `replayToken = op.nonce`, for non-replayables, `replayToken = bytes32(type(uint256).max)`
* @param submissionToken The submission token for the replayable quark operation for QuarkNonceManager. This is initially the `op.nonce`, and for replayable operations, it is the next token in the nonce chain.
* @param opDigests A list of EIP-712 digests for the operations in a MultiQuarkOperation
* @param v EIP-712 signature v value
* @param r EIP-712 signature r value
* @param s EIP-712 signature s value
* @return Return value from the executed operation
*/
function executeMultiQuarkOperationWithReplayToken(
function executeMultiQuarkOperationWithSubmissionToken(
QuarkOperation calldata op,
bytes32 replayToken,
bytes32 submissionToken,
bytes32[] memory opDigests,
uint8 v,
bytes32 r,
Expand All @@ -256,13 +256,13 @@ contract QuarkWallet is IERC1271 {
}
bytes32 multiOpDigest = getDigestForMultiQuarkOperation(opDigests);

return verifySigAndExecuteQuarkOperation(op, replayToken, multiOpDigest, v, r, s);
return verifySigAndExecuteQuarkOperation(op, submissionToken, multiOpDigest, v, r, s);
}

/**
* @notice Verify a signature and execute a replayable QuarkOperation
* @param op A QuarkOperation struct
* @param submissionToken The submission token for the replayable quark operation for QuarkNonceManager. For the first submission, this is generally the `rootHash` of a chain.
* @param submissionToken The submission token for the replayable quark operation for QuarkNonceManager. This is initially the `op.nonce`, and for replayable operations, it is the next token in the nonce chain.
* @param digest A EIP-712 digest for either a QuarkOperation or MultiQuarkOperation to verify the signature against
* @param v EIP-712 signature v value
* @param r EIP-712 signature r value
Expand Down
47 changes: 43 additions & 4 deletions test/lib/QuarkOperationHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,27 @@ contract QuarkOperationHelper is Test {
bytes memory scriptCalldata,
bytes[] memory ensureScripts,
ScriptType scriptType
) public returns (QuarkWallet.QuarkOperation memory) {
return newBasicOpWithCalldata(
wallet, scriptSource, scriptCalldata, ensureScripts, scriptType, semiRandomNonce(wallet)
);
}

function newBasicOpWithCalldata(
QuarkWallet wallet,
bytes memory scriptSource,
bytes memory scriptCalldata,
bytes[] memory ensureScripts,
ScriptType scriptType,
bytes32 nonce
) public returns (QuarkWallet.QuarkOperation memory) {
address scriptAddress = wallet.codeJar().saveCode(scriptSource);
if (scriptType == ScriptType.ScriptAddress) {
return QuarkWallet.QuarkOperation({
scriptAddress: scriptAddress,
scriptSources: ensureScripts,
scriptCalldata: scriptCalldata,
nonce: semiRandomNonce(wallet),
nonce: nonce,
isReplayable: false,
expiry: block.timestamp + 1000
});
Expand All @@ -54,7 +67,7 @@ contract QuarkOperationHelper is Test {
scriptAddress: scriptAddress,
scriptSources: ensureScripts,
scriptCalldata: scriptCalldata,
nonce: semiRandomNonce(wallet),
nonce: nonce,
isReplayable: false,
expiry: block.timestamp + 1000
});
Expand All @@ -71,17 +84,43 @@ contract QuarkOperationHelper is Test {
return newReplayableOpWithCalldata(wallet, scriptSource, scriptCalldata, new bytes[](0), scriptType, replays);
}

function newReplayableOpWithCalldata(
QuarkWallet wallet,
bytes memory scriptSource,
bytes memory scriptCalldata,
ScriptType scriptType,
uint256 replays,
bytes32 nonce
) public returns (QuarkWallet.QuarkOperation memory, bytes32[] memory submissionTokens) {
return newReplayableOpWithCalldata(
wallet, scriptSource, scriptCalldata, new bytes[](0), scriptType, replays, nonce
);
}

function newReplayableOpWithCalldata(
QuarkWallet wallet,
bytes memory scriptSource,
bytes memory scriptCalldata,
bytes[] memory ensureScripts,
ScriptType scriptType,
uint256 replays
) public returns (QuarkWallet.QuarkOperation memory, bytes32[] memory submissionTokens) {
return newReplayableOpWithCalldata(
wallet, scriptSource, scriptCalldata, ensureScripts, scriptType, replays, semiRandomNonce(wallet)
);
}

function newReplayableOpWithCalldata(
QuarkWallet wallet,
bytes memory scriptSource,
bytes memory scriptCalldata,
bytes[] memory ensureScripts,
ScriptType scriptType,
uint256 replays,
bytes32 nonce
) public returns (QuarkWallet.QuarkOperation memory, bytes32[] memory submissionTokens) {
QuarkWallet.QuarkOperation memory operation =
newBasicOpWithCalldata(wallet, scriptSource, scriptCalldata, ensureScripts, scriptType);
bytes32 nonce = operation.nonce;
newBasicOpWithCalldata(wallet, scriptSource, scriptCalldata, ensureScripts, scriptType, nonce);
submissionTokens = new bytes32[](replays + 1);
submissionTokens[replays] = nonce;
for (uint256 i = 0; i < replays; i++) {
Expand Down
Loading

0 comments on commit 72d6883

Please sign in to comment.