Skip to content

Commit a968711

Browse files
committed
add latest_tcb_eval_data_num and allow_non_latest_tcb_eval_data_num to client state
Signed-off-by: Jun Kimura <[email protected]>
1 parent c2e7084 commit a968711

File tree

5 files changed

+127
-22
lines changed

5 files changed

+127
-22
lines changed

contracts/DCAPValidator.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ library DCAPValidator {
4848
*/
4949
struct Output {
5050
string tcbStatus;
51+
uint32 minTcbEvaluationDataNumber;
5152
bytes32 sgxIntelRootCAHash;
5253
uint64 validityNotBeforeMax;
5354
uint64 validityNotAfterMin;
@@ -70,6 +71,7 @@ library DCAPValidator {
7071

7172
Output memory output;
7273
output.tcbStatus = tcbStatusToString(uint8(outputBytes[8]));
74+
output.minTcbEvaluationDataNumber = uint32(bytes4(outputBytes[9:13]));
7375
output.sgxIntelRootCAHash = bytes32(outputBytes[19:51]);
7476
output.validityNotBeforeMax = uint64(bytes8(outputBytes[51:59]));
7577
output.validityNotAfterMin = uint64(bytes8(outputBytes[59:67]));

contracts/ILCPClientErrors.sol

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ interface ILCPClientErrors {
6262
error LCPClientZKDCAPInvalidConstructorParams();
6363
error LCPClientZKDCAPOutputNotValid();
6464
error LCPClientZKDCAPUnrecognizedTCBStatus();
65+
error LCPClientZKDCAPLatestTcbEvaluationDataNumberNotSet();
6566
error LCPClientZKDCAPInvalidVerifierInfos();
6667
error LCPClientZKDCAPInvalidVerifierInfoLength();
6768
error LCPClientZKDCAPInvalidVerifierInfoZKVMType();
@@ -72,4 +73,5 @@ interface ILCPClientErrors {
7273
error LCPClientZKDCAPDisallowedTCBStatus();
7374
error LCPClientZKDCAPDisallowedAdvisoryID();
7475
error LCPClientZKDCAPUnexpectedEnclaveDebugMode();
76+
error LCPClientZKDCAPUnexpectedTcbEvaluationDataNumber();
7577
}

contracts/LCPClientZKDCAPBase.sol

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ abstract contract LCPClientZKDCAPBase is LCPClientBase {
2424

2525
event ZKDCAPRegisteredEnclaveKey(string clientId, address enclaveKey, uint256 expiredAt, address operator);
2626

27+
event ZKDCAPBumpLatestTcbEvaluationDataNumber(string clientId, uint32 tcbEvaluationDataNumber);
28+
2729
// --------------------- Immutable fields ---------------------
2830

2931
/// @dev if developmentMode is true, the client allows the target enclave which is debug mode enabled.
@@ -74,6 +76,9 @@ abstract contract LCPClientZKDCAPBase is LCPClientBase {
7476
ClientStorage storage clientStorage = clientStorages[clientId];
7577
(ProtoClientState.Data memory clientState,) =
7678
_initializeClient(clientStorage, protoClientState, protoConsensusState);
79+
if (clientState.latest_tcb_evalulation_data_number == 0) {
80+
revert LCPClientZKDCAPLatestTcbEvaluationDataNumberNotSet();
81+
}
7782
if (clientState.zkdcap_verifier_infos.length != 1) {
7883
revert LCPClientZKDCAPInvalidVerifierInfos();
7984
}
@@ -131,6 +136,7 @@ abstract contract LCPClientZKDCAPBase is LCPClientBase {
131136
if (clientStorage.zkDCAPRisc0ImageId == bytes32(0)) {
132137
revert LCPClientZKDCAPRisc0ImageIdNotSet();
133138
}
139+
ProtoClientState.Data storage clientState = clientStorage.clientState;
134140
// NOTE: the client must revert if the proof is invalid
135141
riscZeroVerifier.verify(
136142
message.proof, clientStorage.zkDCAPRisc0ImageId, sha256(message.quote_verification_output)
@@ -139,7 +145,7 @@ abstract contract LCPClientZKDCAPBase is LCPClientBase {
139145
if (output.sgxIntelRootCAHash != intelRootCAHash) {
140146
revert LCPClientZKDCAPUnexpectedIntelRootCAHash();
141147
}
142-
if (output.mrenclave != bytes32(clientStorage.clientState.mrenclave)) {
148+
if (output.mrenclave != bytes32(clientState.mrenclave)) {
143149
revert LCPClientClientStateUnexpectedMrenclave();
144150
}
145151

@@ -167,6 +173,18 @@ abstract contract LCPClientZKDCAPBase is LCPClientBase {
167173
revert LCPClientZKDCAPUnexpectedEnclaveDebugMode();
168174
}
169175

176+
if (clientState.latest_tcb_evalulation_data_number < output.minTcbEvaluationDataNumber) {
177+
clientState.latest_tcb_evalulation_data_number = output.minTcbEvaluationDataNumber;
178+
emit ZKDCAPBumpLatestTcbEvaluationDataNumber(clientId, output.minTcbEvaluationDataNumber);
179+
} else if (clientState.latest_tcb_evalulation_data_number > output.minTcbEvaluationDataNumber) {
180+
if (!clientState.allow_previous_tcb_evalulation_data_number) {
181+
revert LCPClientZKDCAPUnexpectedTcbEvaluationDataNumber();
182+
} else if (clientState.latest_tcb_evalulation_data_number != output.minTcbEvaluationDataNumber + 1) {
183+
// NOTE: if the client allows previous TCB evaluation data number, the client should only accept the previous number
184+
revert LCPClientZKDCAPUnexpectedTcbEvaluationDataNumber();
185+
}
186+
}
187+
170188
// check if the validity period of the output is valid at the current block timestamp
171189
if (block.timestamp < output.validityNotBeforeMax || block.timestamp > output.validityNotAfterMin) {
172190
revert LCPClientZKDCAPOutputNotValid();
@@ -178,7 +196,7 @@ abstract contract LCPClientZKDCAPBase is LCPClientBase {
178196
operator = verifyECDSASignature(
179197
keccak256(
180198
LCPOperator.computeEIP712ZKDCAPRegisterEnclaveKey(
181-
clientStorage.clientState.zkdcap_verifier_infos[0], keccak256(message.quote_verification_output)
199+
clientState.zkdcap_verifier_infos[0], keccak256(message.quote_verification_output)
182200
)
183201
),
184202
message.operator_signature

contracts/proto/ibc/lightclients/lcp/v1/LCP.sol

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1440,6 +1440,8 @@ library IbcLightclientsLcpV1ClientState {
14401440
uint64 operators_nonce;
14411441
uint64 operators_threshold_numerator;
14421442
uint64 operators_threshold_denominator;
1443+
uint32 latest_tcb_evalulation_data_number;
1444+
bool allow_previous_tcb_evalulation_data_number;
14431445
bytes[] zkdcap_verifier_infos;
14441446
}
14451447

@@ -1480,7 +1482,7 @@ library IbcLightclientsLcpV1ClientState {
14801482
returns (Data memory, uint)
14811483
{
14821484
Data memory r;
1483-
uint[12] memory counters;
1485+
uint[15] memory counters;
14841486
uint256 fieldId;
14851487
ProtoBufRuntime.WireType wireType;
14861488
uint256 bytesRead;
@@ -1520,6 +1522,12 @@ library IbcLightclientsLcpV1ClientState {
15201522
pointer += _read_operators_threshold_denominator(pointer, bs, r);
15211523
} else
15221524
if (fieldId == 11) {
1525+
pointer += _read_latest_tcb_evalulation_data_number(pointer, bs, r);
1526+
} else
1527+
if (fieldId == 12) {
1528+
pointer += _read_allow_previous_tcb_evalulation_data_number(pointer, bs, r);
1529+
} else
1530+
if (fieldId == 14) {
15231531
pointer += _read_unpacked_repeated_zkdcap_verifier_infos(pointer, bs, nil(), counters);
15241532
} else
15251533
{
@@ -1540,9 +1548,9 @@ library IbcLightclientsLcpV1ClientState {
15401548
require(r.operators.length == 0);
15411549
r.operators = new bytes[](counters[7]);
15421550
}
1543-
if (counters[11] > 0) {
1551+
if (counters[14] > 0) {
15441552
require(r.zkdcap_verifier_infos.length == 0);
1545-
r.zkdcap_verifier_infos = new bytes[](counters[11]);
1553+
r.zkdcap_verifier_infos = new bytes[](counters[14]);
15461554
}
15471555

15481556
while (pointer < offset + sz) {
@@ -1557,7 +1565,7 @@ library IbcLightclientsLcpV1ClientState {
15571565
if (fieldId == 7) {
15581566
pointer += _read_unpacked_repeated_operators(pointer, bs, r, counters);
15591567
} else
1560-
if (fieldId == 11) {
1568+
if (fieldId == 14) {
15611569
pointer += _read_unpacked_repeated_zkdcap_verifier_infos(pointer, bs, r, counters);
15621570
} else
15631571
{
@@ -1649,7 +1657,7 @@ library IbcLightclientsLcpV1ClientState {
16491657
uint256 p,
16501658
bytes memory bs,
16511659
Data memory r,
1652-
uint[12] memory counters
1660+
uint[15] memory counters
16531661
) internal pure returns (uint) {
16541662
/**
16551663
* if `r` is NULL, then only counting the number of fields.
@@ -1676,7 +1684,7 @@ library IbcLightclientsLcpV1ClientState {
16761684
uint256 p,
16771685
bytes memory bs,
16781686
Data memory r,
1679-
uint[12] memory counters
1687+
uint[15] memory counters
16801688
) internal pure returns (uint) {
16811689
/**
16821690
* if `r` is NULL, then only counting the number of fields.
@@ -1703,7 +1711,7 @@ library IbcLightclientsLcpV1ClientState {
17031711
uint256 p,
17041712
bytes memory bs,
17051713
Data memory r,
1706-
uint[12] memory counters
1714+
uint[15] memory counters
17071715
) internal pure returns (uint) {
17081716
/**
17091717
* if `r` is NULL, then only counting the number of fields.
@@ -1769,6 +1777,40 @@ library IbcLightclientsLcpV1ClientState {
17691777
return sz;
17701778
}
17711779

1780+
/**
1781+
* @dev The decoder for reading a field
1782+
* @param p The offset of bytes array to start decode
1783+
* @param bs The bytes array to be decoded
1784+
* @param r The in-memory struct
1785+
* @return The number of bytes decoded
1786+
*/
1787+
function _read_latest_tcb_evalulation_data_number(
1788+
uint256 p,
1789+
bytes memory bs,
1790+
Data memory r
1791+
) internal pure returns (uint) {
1792+
(uint32 x, uint256 sz) = ProtoBufRuntime._decode_uint32(p, bs);
1793+
r.latest_tcb_evalulation_data_number = x;
1794+
return sz;
1795+
}
1796+
1797+
/**
1798+
* @dev The decoder for reading a field
1799+
* @param p The offset of bytes array to start decode
1800+
* @param bs The bytes array to be decoded
1801+
* @param r The in-memory struct
1802+
* @return The number of bytes decoded
1803+
*/
1804+
function _read_allow_previous_tcb_evalulation_data_number(
1805+
uint256 p,
1806+
bytes memory bs,
1807+
Data memory r
1808+
) internal pure returns (uint) {
1809+
(bool x, uint256 sz) = ProtoBufRuntime._decode_bool(p, bs);
1810+
r.allow_previous_tcb_evalulation_data_number = x;
1811+
return sz;
1812+
}
1813+
17721814
/**
17731815
* @dev The decoder for reading a field
17741816
* @param p The offset of bytes array to start decode
@@ -1781,17 +1823,17 @@ library IbcLightclientsLcpV1ClientState {
17811823
uint256 p,
17821824
bytes memory bs,
17831825
Data memory r,
1784-
uint[12] memory counters
1826+
uint[15] memory counters
17851827
) internal pure returns (uint) {
17861828
/**
17871829
* if `r` is NULL, then only counting the number of fields.
17881830
*/
17891831
(bytes memory x, uint256 sz) = ProtoBufRuntime._decode_bytes(p, bs);
17901832
if (isNil(r)) {
1791-
counters[11] += 1;
1833+
counters[14] += 1;
17921834
} else {
1793-
r.zkdcap_verifier_infos[r.zkdcap_verifier_infos.length - counters[11]] = x;
1794-
counters[11] -= 1;
1835+
r.zkdcap_verifier_infos[r.zkdcap_verifier_infos.length - counters[14]] = x;
1836+
counters[14] -= 1;
17951837
}
17961838
return sz;
17971839
}
@@ -1945,10 +1987,28 @@ library IbcLightclientsLcpV1ClientState {
19451987
);
19461988
pointer += ProtoBufRuntime._encode_uint64(r.operators_threshold_denominator, pointer, bs);
19471989
}
1990+
if (r.latest_tcb_evalulation_data_number != 0) {
1991+
pointer += ProtoBufRuntime._encode_key(
1992+
11,
1993+
ProtoBufRuntime.WireType.Varint,
1994+
pointer,
1995+
bs
1996+
);
1997+
pointer += ProtoBufRuntime._encode_uint32(r.latest_tcb_evalulation_data_number, pointer, bs);
1998+
}
1999+
if (r.allow_previous_tcb_evalulation_data_number != false) {
2000+
pointer += ProtoBufRuntime._encode_key(
2001+
12,
2002+
ProtoBufRuntime.WireType.Varint,
2003+
pointer,
2004+
bs
2005+
);
2006+
pointer += ProtoBufRuntime._encode_bool(r.allow_previous_tcb_evalulation_data_number, pointer, bs);
2007+
}
19482008
if (r.zkdcap_verifier_infos.length != 0) {
19492009
for(i = 0; i < r.zkdcap_verifier_infos.length; i++) {
19502010
pointer += ProtoBufRuntime._encode_key(
1951-
11,
2011+
14,
19522012
ProtoBufRuntime.WireType.LengthDelim,
19532013
pointer,
19542014
bs)
@@ -2015,6 +2075,8 @@ library IbcLightclientsLcpV1ClientState {
20152075
e += 1 + ProtoBufRuntime._sz_uint64(r.operators_nonce);
20162076
e += 1 + ProtoBufRuntime._sz_uint64(r.operators_threshold_numerator);
20172077
e += 1 + ProtoBufRuntime._sz_uint64(r.operators_threshold_denominator);
2078+
e += 1 + ProtoBufRuntime._sz_uint32(r.latest_tcb_evalulation_data_number);
2079+
e += 1 + 1;
20182080
for(i = 0; i < r.zkdcap_verifier_infos.length; i++) {
20192081
e += 1 + ProtoBufRuntime._sz_lendelim(r.zkdcap_verifier_infos[i].length);
20202082
}
@@ -2062,6 +2124,14 @@ library IbcLightclientsLcpV1ClientState {
20622124
return false;
20632125
}
20642126

2127+
if (r.latest_tcb_evalulation_data_number != 0) {
2128+
return false;
2129+
}
2130+
2131+
if (r.allow_previous_tcb_evalulation_data_number != false) {
2132+
return false;
2133+
}
2134+
20652135
if (r.zkdcap_verifier_infos.length != 0) {
20662136
return false;
20672137
}
@@ -2087,6 +2157,8 @@ library IbcLightclientsLcpV1ClientState {
20872157
output.operators_nonce = input.operators_nonce;
20882158
output.operators_threshold_numerator = input.operators_threshold_numerator;
20892159
output.operators_threshold_denominator = input.operators_threshold_denominator;
2160+
output.latest_tcb_evalulation_data_number = input.latest_tcb_evalulation_data_number;
2161+
output.allow_previous_tcb_evalulation_data_number = input.allow_previous_tcb_evalulation_data_number;
20902162
output.zkdcap_verifier_infos = input.zkdcap_verifier_infos;
20912163

20922164
}

proto/ibc/lightclients/lcp/v1/LCP.proto

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,26 @@ message ClientState {
4848
uint64 operators_nonce = 8;
4949
uint64 operators_threshold_numerator = 9;
5050
uint64 operators_threshold_denominator = 10;
51-
// An optional field to store the verifier info for zkDCAP
51+
52+
// The latest TCB evaluation data number
53+
//
54+
// The client updates the number when receiving TCB evaluation data whose number is greater than the current number.
55+
uint32 latest_tcb_evalulation_data_number = 11;
56+
// Whether to allow the previous TCB evaluation data number
57+
//
58+
// If this is true, the client will accept the previous TCB evaluation data number (i.e., `latest_tcb_evalulation_data_number` - 1).
59+
// Otherwise, the client will only accept the latest TCB evaluation data number or greater.
60+
bool allow_previous_tcb_evalulation_data_number = 12;
61+
// The verifier info for zkDCAP
62+
//
63+
// The format is as follows:
64+
// 0: zkVM type
65+
// 1-N: arbitrary data for each zkVM type
5266
//
53-
// if empty, the zkDCAP is not enabled
54-
// otherwise, the zkDCAP is enabled
55-
// The layout of each element is as follows:
56-
// 0: zkVM type (e.g. 1 for risc0)
57-
// 1-31: reserved
58-
// 32-64: guest program identifier
59-
repeated bytes zkdcap_verifier_infos = 11;
67+
// zkVM type:
68+
// 0: unspecified
69+
// 1: risc0
70+
repeated bytes zkdcap_verifier_infos = 14;
6071
}
6172

6273
message ConsensusState {

0 commit comments

Comments
 (0)