Skip to content

Commit 85e5d25

Browse files
committed
Merge branch 'angelo/claim-digest' into ec2/bitvm
2 parents 7dd797c + 25c7b42 commit 85e5d25

File tree

24 files changed

+347
-131
lines changed

24 files changed

+347
-131
lines changed
Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,43 @@
11
{
22
"ERC20 approve: required for depositStake": "45966",
3-
"bytecode size implementation": "24381",
3+
"bytecode size implementation": "24287",
44
"bytecode size proxy": "89",
55
"deposit: first ever deposit": "50920",
66
"deposit: second deposit": "33820",
7-
"depositStake: 1 HP (tops up market account)": "59400",
8-
"depositStake: full (drains testProver account)": "49800",
9-
"depositStakeWithPermit: 1 HP (tops up market account)": "72272",
10-
"depositStakeWithPermit: full (drains testProver account)": "72262",
11-
"fulfill: a batch of 8": "402078",
12-
"fulfill: a locked request": "90511",
13-
"fulfill: a locked request (locked via prover signature)": "90511",
14-
"fulfill: a locked request with 10kB journal": "427539",
15-
"fulfill: another prover fulfills without payment": "85473",
16-
"fulfill: fulfilled by the locked prover for payment (request already fulfilled by another prover)": "80772",
17-
"fulfillAndWithdraw: a batch of 8": "414256",
18-
"fulfillAndWithdraw: a locked request": "102689",
19-
"lockinRequest: base case": "146877",
20-
"lockinRequest: with prover signature": "156522",
21-
"priceAndFulfill: a single request": "108760",
22-
"priceAndFulfill: a single request (smart contract signature)": "118938",
23-
"priceAndFulfill: a single request (with selector)": "111059",
24-
"priceAndFulfill: a single request that was not locked": "108760",
25-
"priceAndFulfill: a single request that was not locked fulfilled by prover not in allow-list": "108760",
26-
"priceAndFulfill: fulfill already fulfilled was locked request": "102475",
7+
"depositStake: 1 HP (tops up market account)": "59378",
8+
"depositStake: full (drains testProver account)": "49778",
9+
"depositStakeWithPermit: 1 HP (tops up market account)": "72254",
10+
"depositStakeWithPermit: full (drains testProver account)": "72244",
11+
"fulfill (no journal): a batch of 8": "386163",
12+
"fulfill: a batch of 8": "414107",
13+
"fulfill: a locked request": "92348",
14+
"fulfill: a locked request (locked via prover signature)": "92348",
15+
"fulfill: a locked request with 10kB journal": "429399",
16+
"fulfill: another prover fulfills without payment": "87299",
17+
"fulfill: fulfilled by the locked prover for payment (request already fulfilled by another prover)": "82252",
18+
"fulfillAndWithdraw: a batch of 8": "426461",
19+
"fulfillAndWithdraw: a locked request": "104702",
20+
"lockinRequest: base case": "146921",
21+
"lockinRequest: with prover signature": "156628",
22+
"priceAndFulfill: a single request": "110408",
23+
"priceAndFulfill: a single request (smart contract signature)": "120598",
24+
"priceAndFulfill: a single request (with selector)": "112710",
25+
"priceAndFulfill: a single request that was not locked": "110408",
26+
"priceAndFulfill: a single request that was not locked fulfilled by prover not in allow-list": "110408",
27+
"priceAndFulfill: fulfill already fulfilled was locked request": "103766",
2728
"slash: base case": "100967",
2829
"slash: fulfilled request after lock deadline": "80532",
29-
"submitRequest: with maxPrice ether": "51904",
30-
"submitRequest: without ether": "45061",
31-
"submitRootAndFulfill: a batch of 2 requests": "168676",
32-
"submitRootAndFulfill: a locked request": "124555",
33-
"submitRootAndFulfill: a locked request (locked via prover signature)": "124555",
34-
"submitRootAndFulfillAndWithdraw: a locked request": "136476",
35-
"submitRootAndPriceAndFulfill: a single request": "141098",
36-
"submitRootAndPriceAndFulfill: a single request that was not locked": "141110",
37-
"submitRootAndPriceAndFulfill: a single request that was not locked fulfilled by prover not in allow-list": "141110",
38-
"withdraw: 1 ether": "40314",
39-
"withdraw: full balance": "40326",
40-
"withdrawStake: 1 HP balance": "68743",
41-
"withdrawStake: full balance": "51739"
30+
"submitRequest: with maxPrice ether": "51888",
31+
"submitRequest: without ether": "45045",
32+
"submitRootAndFulfill: a batch of 2 requests": "171268",
33+
"submitRootAndFulfill: a locked request": "126392",
34+
"submitRootAndFulfill: a locked request (locked via prover signature)": "126392",
35+
"submitRootAndFulfillAndWithdraw: a locked request": "138702",
36+
"submitRootAndPriceAndFulfill: a single request": "142990",
37+
"submitRootAndPriceAndFulfill: a single request that was not locked": "142990",
38+
"submitRootAndPriceAndFulfill: a single request that was not locked fulfilled by prover not in allow-list": "142990",
39+
"withdraw: 1 ether": "40336",
40+
"withdraw: full balance": "40348",
41+
"withdrawStake: 1 HP balance": "68765",
42+
"withdrawStake: full balance": "51761"
4243
}
Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
{
2-
"fulfill (with callback): batch of 001": "132142",
3-
"fulfill (with callback): batch of 002": "218443",
4-
"fulfill (with callback): batch of 004": "392147",
5-
"fulfill (with callback): batch of 008": "739579",
6-
"fulfill (with callback): batch of 016": "1272464",
7-
"fulfill (with callback): batch of 032": "2373148",
8-
"fulfill (with selector): batch of 001": "92745",
9-
"fulfill (with selector): batch of 002": "139726",
10-
"fulfill (with selector): batch of 004": "236258",
11-
"fulfill (with selector): batch of 008": "420231",
12-
"fulfill (with selector): batch of 016": "790425",
13-
"fulfill (with selector): batch of 032": "1558877",
14-
"fulfill: batch of 001": "90487",
15-
"fulfill: batch of 002": "135232",
16-
"fulfill: batch of 004": "227181",
17-
"fulfill: batch of 008": "402117",
18-
"fulfill: batch of 016": "754179",
19-
"fulfill: batch of 032": "1485129",
20-
"fulfill: batch of 064": "3014348",
21-
"fulfill: batch of 128": "6255291"
2+
"fulfill (with callback): batch of 001": "133995",
3+
"fulfill (with callback): batch of 002": "221718",
4+
"fulfill (with callback): batch of 004": "398391",
5+
"fulfill (with callback): batch of 008": "751743",
6+
"fulfill (with callback): batch of 016": "1295941",
7+
"fulfill (with callback): batch of 032": "2421367",
8+
"fulfill (with selector): batch of 001": "94586",
9+
"fulfill (with selector): batch of 002": "143005",
10+
"fulfill (with selector): batch of 004": "242410",
11+
"fulfill (with selector): batch of 008": "432298",
12+
"fulfill (with selector): batch of 016": "814329",
13+
"fulfill (with selector): batch of 032": "1606225",
14+
"fulfill: batch of 001": "92324",
15+
"fulfill: batch of 002": "138490",
16+
"fulfill: batch of 004": "233365",
17+
"fulfill: batch of 008": "414155",
18+
"fulfill: batch of 016": "777861",
19+
"fulfill: batch of 032": "1532332",
20+
"fulfill: batch of 064": "3109582",
21+
"fulfill: batch of 128": "6452336"
2222
}

contracts/src/BoundlessMarket.sol

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import {AssessorCallback} from "./types/AssessorCallback.sol";
2626
import {AssessorCommitment} from "./types/AssessorCommitment.sol";
2727
import {Fulfillment} from "./types/Fulfillment.sol";
2828
import {AssessorReceipt} from "./types/AssessorReceipt.sol";
29+
import {PredicateType} from "./types/Predicate.sol";
2930
import {ProofRequest} from "./types/ProofRequest.sol";
3031
import {LockRequest, LockRequestLibrary} from "./types/LockRequest.sol";
3132
import {RequestId} from "./types/RequestId.sol";
@@ -239,6 +240,7 @@ contract BoundlessMarket is
239240
}
240241
bytes32[] memory leaves = new bytes32[](fills.length);
241242
bool[] memory hasSelector = new bool[](fills.length);
243+
PredicateType[] memory predicateTypes = new PredicateType[](fills.length);
242244

243245
// Check the selector constraints.
244246
// NOTE: The assessor guest adds non-zero selector values to the list.
@@ -255,9 +257,14 @@ contract BoundlessMarket is
255257
// Verify the application receipts.
256258
for (uint256 i = 0; i < fills.length; i++) {
257259
Fulfillment calldata fill = fills[i];
258-
bytes32 claimDigest = fill.imageId;
259-
if (!fill.isClaimDigest) {
260-
claimDigest = ReceiptClaimLib.ok(fill.imageId, sha256(fill.journal)).digest();
260+
predicateTypes[i] = fill.predicateType;
261+
262+
bytes32 claimDigest;
263+
if (fill.predicateType == PredicateType.ClaimDigestMatch) {
264+
claimDigest = fill.imageIdOrClaimDigest;
265+
} else {
266+
// The requestor requested a journal, so we compute the claim digest from the journal.
267+
claimDigest = ReceiptClaimLib.ok(fill.imageIdOrClaimDigest, sha256(fill.journal)).digest();
261268
}
262269
leaves[i] = AssessorCommitment(i, fill.id, fill.requestDigest, claimDigest).eip712Digest();
263270

@@ -280,6 +287,7 @@ contract BoundlessMarket is
280287
root: batchRoot,
281288
callbacks: assessorReceipt.callbacks,
282289
selectors: assessorReceipt.selectors,
290+
predicateTypes: predicateTypes,
283291
prover: assessorReceipt.prover
284292
})
285293
)
@@ -335,9 +343,9 @@ contract BoundlessMarket is
335343
}
336344

337345
uint256 callbackIndexPlusOne = fillToCallbackIndexPlusOne[i];
338-
if (callbackIndexPlusOne > 0) {
346+
if ((fill.predicateType != PredicateType.ClaimDigestMatch) && (callbackIndexPlusOne > 0)) {
339347
AssessorCallback calldata callback = assessorReceipt.callbacks[callbackIndexPlusOne - 1];
340-
_executeCallback(fill.id, callback.addr, callback.gasLimit, fill.imageId, fill.journal, fill.seal);
348+
_executeCallback(fill.id, callback.addr, callback.gasLimit, fill.imageIdOrClaimDigest, fill.journal, fill.seal);
341349
}
342350
}
343351
}

contracts/src/types/AssessorJournal.sol

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
pragma solidity ^0.8.20;
66

77
import {AssessorCallback} from "./AssessorCallback.sol";
8+
import {PredicateType} from "./Predicate.sol";
89
import {Selector} from "./Selector.sol";
910

1011
/// @title Assessor Journal Struct
@@ -17,6 +18,8 @@ struct AssessorJournal {
1718
/// @notice The (optional) selectors for the requests committed by the assessor.
1819
/// @dev This is used to verify the fulfillment of the request against its selector's seal.
1920
Selector[] selectors;
21+
/// @notice The list of `PredicateType` for each request.
22+
PredicateType[] predicateTypes;
2023
/// @notice Root of the Merkle tree committing to the set of proven claims.
2124
/// @dev In the case of a batch of size one, this may simply be the eip712Digest of the `AssessorCommitment`.
2225
bytes32 root;

contracts/src/types/Fulfillment.sol

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
pragma solidity ^0.8.20;
66

77
import {RequestId} from "./RequestId.sol";
8+
import {PredicateType} from "./Predicate.sol";
89

910
using FulfillmentLibrary for Fulfillment global;
1011

@@ -15,22 +16,21 @@ struct Fulfillment {
1516
RequestId id;
1617
/// @notice EIP-712 digest of request struct.
1718
bytes32 requestDigest;
18-
/// @notice Image ID of the guest that was verifiably executed to satisfy the request.
19-
/// @dev Must match the value in the request's requirements.
20-
bytes32 imageId;
21-
// TODO: Add a flag in the request to decide whether to post the journal. Note that
22-
// if the journal and journal digest do not need to be delivered to the client, imageId will
23-
// be replaced with claim digest, since it is captured in the requirements on the request,
24-
// checked by the Assessor guest.
19+
/// @notice The `PredicateType` of the request that is being fulfilled.
20+
/// @dev When the `PredicateType` is `ClaimDigestMatch`, the imageIdOrClaimDigest field is the claim digest,
21+
/// and otherwise it is the image ID of the guest that was executed.
22+
PredicateType predicateType;
23+
/// @notice Image ID of the guest that was verifiably executed to satisfy the request or claim digest.
24+
/// @dev Must match the value in the request's requirements. If the journal and journal digest do not need
25+
/// to be delivered to the client, imageId is replaced with claim digest, since it is captured in the
26+
/// requirements on the request, checked by the Assessor guest.
27+
bytes32 imageIdOrClaimDigest;
2528
/// @notice Journal committed by the guest program execution.
2629
/// @dev The journal is checked to satisfy the predicate specified on the request's requirements.
2730
bytes journal;
2831
/// @notice Cryptographic proof for the validity of the execution results.
2932
/// @dev This will be sent to the `IRiscZeroVerifier` associated with this contract.
3033
bytes seal;
31-
/// @notice Flag to indicate that the imageID is a claim digest.
32-
/// @dev If true, the imageId is a claim digest instead of an image ID.
33-
bool isClaimDigest;
3434
}
3535

3636
library FulfillmentLibrary {}

contracts/src/types/Predicate.sol

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,10 @@
55
// SPDX-License-Identifier: BUSL-1.1
66
pragma solidity ^0.8.24;
77

8+
import {ReceiptClaim, ReceiptClaimLib} from "risc0/IRiscZeroVerifier.sol";
9+
810
using PredicateLibrary for Predicate global;
11+
using ReceiptClaimLib for ReceiptClaim;
912

1013
/// @title Predicate Struct and Library
1114
/// @notice Represents a predicate and provides functions to create and evaluate predicates.
@@ -16,7 +19,8 @@ struct Predicate {
1619

1720
enum PredicateType {
1821
DigestMatch,
19-
PrefixMatch
22+
PrefixMatch,
23+
ClaimDigestMatch
2024
}
2125

2226
library PredicateLibrary {
@@ -37,12 +41,19 @@ library PredicateLibrary {
3741
return Predicate({predicateType: PredicateType.PrefixMatch, data: prefix});
3842
}
3943

44+
/// @notice Creates a claim digest match predicate.
45+
/// @param claimDigest The claimDigest to match.
46+
/// @return A Predicate struct with type ClaimDigestMatch and the provided claimDigest.
47+
function createClaimDigestMatchPredicate(bytes32 claimDigest) internal pure returns (Predicate memory) {
48+
return Predicate({predicateType: PredicateType.ClaimDigestMatch, data: abi.encode(claimDigest)});
49+
}
50+
4051
/// @notice Evaluates the predicate against the given journal and journal digest.
4152
/// @param predicate The predicate to evaluate.
4253
/// @param journal The journal to evaluate against.
4354
/// @param journalDigest The digest of the journal.
4455
/// @return True if the predicate is satisfied, false otherwise.
45-
function eval(Predicate memory predicate, bytes memory journal, bytes32 journalDigest)
56+
function eval(Predicate memory predicate, bytes32 imageId, bytes memory journal, bytes32 journalDigest)
4657
internal
4758
pure
4859
returns (bool)
@@ -51,6 +62,8 @@ library PredicateLibrary {
5162
return bytes32(predicate.data) == journalDigest;
5263
} else if (predicate.predicateType == PredicateType.PrefixMatch) {
5364
return startsWith(journal, predicate.data);
65+
} else if (predicate.predicateType == PredicateType.ClaimDigestMatch) {
66+
return bytes32(predicate.data) == ReceiptClaimLib.ok(imageId, journalDigest).digest();
5467
} else {
5568
revert("Unreachable code");
5669
}

0 commit comments

Comments
 (0)