Skip to content

Commit 16fa999

Browse files
authored
Merge pull request #104 from datachainlab/specify-client-id-externally
Allow client ID to be specified externally in `init_client` Signed-off-by: Jun Kimura <jun.kimura@datachain.jp>
2 parents a680eab + 162ad24 commit 16fa999

File tree

16 files changed

+168
-77
lines changed

16 files changed

+168
-77
lines changed

enclave-modules/ecall-handler/src/light_client/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ define_error! {
1515
SealedEnclaveKeyNotFound
1616
|_| { "Sealed EnclaveKey not found" },
1717

18+
ClientAlreadyExists
19+
{
20+
client_id: String
21+
}
22+
|e| {
23+
format_args!("client already exists: client_id={}", e.client_id)
24+
},
25+
1826
LightClient
1927
[light_client::Error]
2028
|_| { "LightClient error" },

enclave-modules/ecall-handler/src/light_client/init_client.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,24 +21,22 @@ pub fn init_client<R: LightClientResolver, S: KVStore, K: Signer>(
2121
let ek = ctx.get_enclave_key();
2222
let res = lc.create_client(ctx, any_client_state.clone(), any_consensus_state.clone())?;
2323
let client_type = lc.client_type();
24-
let client_id = gen_client_id(client_type.clone(), ctx.client_counter()?)?;
24+
let client_id = ClientId::from_str(&input.client_id)?;
25+
client_id.validate(&client_type)?;
2526

27+
if ctx.client_exists(&client_id) {
28+
return Err(Error::client_already_exists(client_id.to_string()));
29+
}
2630
ctx.store_client_type(client_id.clone(), client_type)?;
2731
ctx.store_any_client_state(client_id.clone(), any_client_state)?;
2832
ctx.store_any_consensus_state(client_id.clone(), res.height, any_consensus_state)?;
29-
ctx.increase_client_counter();
3033

3134
let proof = if res.prove {
3235
prove_commitment(ek, input.signer, res.message)?
3336
} else {
3437
CommitmentProof::new_with_no_signature(res.message.to_bytes())
3538
};
3639
Ok(LightClientResponse::InitClient(InitClientResponse {
37-
client_id,
3840
proof,
3941
}))
4042
}
41-
42-
fn gen_client_id(client_type: String, counter: u64) -> Result<ClientId, Error> {
43-
Ok(ClientId::from_str(&format!("{}-{}", client_type, counter))?)
44-
}

enclave-modules/ecall-handler/src/light_client/query.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,21 @@ pub fn query_client<R: LightClientResolver, S: KVStore, K: Signer>(
1010
ctx: &mut Context<R, S, K>,
1111
input: QueryClientInput,
1212
) -> Result<LightClientResponse, Error> {
13-
let lc = get_light_client_by_client_id(ctx, &input.client_id)?;
14-
let any_client_state = ctx.client_state(&input.client_id)?;
15-
let any_consensus_state =
16-
ctx.consensus_state(&input.client_id, &lc.latest_height(ctx, &input.client_id)?)?;
17-
18-
Ok(LightClientResponse::QueryClient(QueryClientResponse {
19-
any_client_state,
20-
any_consensus_state,
21-
}))
13+
if ctx.client_exists(&input.client_id) {
14+
let lc = get_light_client_by_client_id(ctx, &input.client_id)?;
15+
let any_client_state = ctx.client_state(&input.client_id)?;
16+
let any_consensus_state =
17+
ctx.consensus_state(&input.client_id, &lc.latest_height(ctx, &input.client_id)?)?;
18+
Ok(LightClientResponse::QueryClient(QueryClientResponse {
19+
found: true,
20+
any_client_state: Some(any_client_state),
21+
any_consensus_state: Some(any_consensus_state),
22+
}))
23+
} else {
24+
Ok(LightClientResponse::QueryClient(QueryClientResponse {
25+
found: false,
26+
any_client_state: None,
27+
any_consensus_state: None,
28+
}))
29+
}
2230
}

modules/ecall-commands/src/light_client.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ impl EnclaveKeySelector for LightClientCommand {
4141

4242
#[derive(Serialize, Deserialize, Debug)]
4343
pub struct InitClientInput {
44+
pub client_id: String,
4445
pub any_client_state: Any,
4546
pub any_consensus_state: Any,
4647
pub current_timestamp: Time,
@@ -105,7 +106,6 @@ pub enum LightClientResponse {
105106

106107
#[derive(Serialize, Deserialize, Debug)]
107108
pub struct InitClientResponse {
108-
pub client_id: ClientId,
109109
pub proof: CommitmentProof,
110110
}
111111

@@ -123,6 +123,7 @@ pub struct VerifyNonMembershipResponse(pub CommitmentProof);
123123

124124
#[derive(Serialize, Deserialize, Debug)]
125125
pub struct QueryClientResponse {
126-
pub any_client_state: Any,
127-
pub any_consensus_state: Any,
126+
pub found: bool,
127+
pub any_client_state: Option<Any>,
128+
pub any_consensus_state: Option<Any>,
128129
}

modules/ecall-commands/src/msgs.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ impl TryFrom<MsgCreateClient> for InitClientInput {
2323
.ok_or_else(|| Error::invalid_argument("consensus_state must be non-nil".into()))?
2424
.into();
2525
Ok(Self {
26+
client_id: msg.client_id,
2627
any_client_state,
2728
any_consensus_state,
2829
current_timestamp: Time::now(),
@@ -116,7 +117,6 @@ impl TryFrom<MsgQueryClientRequest> for QueryClientInput {
116117
impl From<InitClientResponse> for MsgCreateClientResponse {
117118
fn from(res: InitClientResponse) -> Self {
118119
Self {
119-
client_id: res.client_id.to_string(),
120120
message: res.proof.message,
121121
signer: res.proof.signer.into(),
122122
signature: res.proof.signature,
@@ -167,8 +167,9 @@ impl From<VerifyNonMembershipResponse> for MsgVerifyNonMembershipResponse {
167167
impl From<QueryClientResponse> for MsgQueryClientResponse {
168168
fn from(res: QueryClientResponse) -> Self {
169169
Self {
170-
client_state: Some(res.any_client_state.into()),
171-
consensus_state: Some(res.any_consensus_state.into()),
170+
found: res.found,
171+
client_state: res.any_client_state.map(Into::into),
172+
consensus_state: res.any_consensus_state.map(Into::into),
172173
}
173174
}
174175
}

modules/enclave-api/src/api/proto.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ use store::transaction::CommitStore;
1111

1212
pub trait EnclaveProtoAPI<S: CommitStore>: EnclaveCommandAPI<S> {
1313
fn proto_create_client(&self, msg: MsgCreateClient) -> Result<MsgCreateClientResponse> {
14+
let client_id = msg.client_id.clone();
1415
let res = self.init_client(msg.try_into()?)?;
1516
info!(
1617
"create_client: client_id={} message={{{}}}",
17-
res.client_id,
18+
client_id,
1819
res.proof.message()?
1920
);
2021
Ok(res.into())

modules/light-client/src/context.rs

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::types::{Any, ClientId, Height, Time};
22
use crate::{
33
errors::Error,
4-
path::{ClientConsensusStatePath, ClientStatePath, ClientTypePath, NEXT_CLIENT_SEQUENCE},
4+
path::{ClientConsensusStatePath, ClientStatePath, ClientTypePath},
55
prelude::*,
66
};
77
use store::KVStore;
@@ -12,6 +12,12 @@ pub trait HostContext {
1212
}
1313

1414
pub trait ClientReader: KVStore {
15+
/// Returns `true` if the client exists in the store.
16+
fn client_exists(&self, client_id: &ClientId) -> bool {
17+
self.get(format!("{}", ClientTypePath::new(client_id)).as_bytes())
18+
.is_some()
19+
}
20+
1521
/// Returns the ClientType for the given identifier `client_id`.
1622
fn client_type(&self, client_id: &ClientId) -> Result<String, Error> {
1723
let value = self.get(format!("{}", ClientTypePath::new(client_id)).as_bytes());
@@ -54,19 +60,6 @@ pub trait ClientReader: KVStore {
5460
.0,
5561
)
5662
}
57-
58-
/// Returns a natural number, counting how many clients have been created thus far.
59-
/// The value of this counter should increase only via method `ClientKeeper::increase_client_counter`.
60-
fn client_counter(&self) -> Result<u64, Error> {
61-
match self.get(NEXT_CLIENT_SEQUENCE.as_bytes()) {
62-
Some(bz) => {
63-
let mut b: [u8; 8] = Default::default();
64-
b.copy_from_slice(&bz);
65-
Ok(u64::from_be_bytes(b))
66-
}
67-
None => Ok(0),
68-
}
69-
}
7063
}
7164

7265
pub trait ClientKeeper: ClientReader {
@@ -106,17 +99,6 @@ pub trait ClientKeeper: ClientReader {
10699
self.set(format!("{}", path).into_bytes(), bz);
107100
Ok(())
108101
}
109-
110-
/// Called upon client creation.
111-
/// Increases the counter which keeps track of how many clients have been created.
112-
/// Should never fail.
113-
fn increase_client_counter(&mut self) {
114-
let next_counter = <Self as ClientReader>::client_counter(self).unwrap() + 1;
115-
self.set(
116-
NEXT_CLIENT_SEQUENCE.as_bytes().to_vec(),
117-
next_counter.to_be_bytes().to_vec(),
118-
);
119-
}
120102
}
121103

122104
pub trait HostClientReader: HostContext + ClientReader {}

modules/light-client/src/ibc.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,7 @@ impl<'a, ClientState: Ics02ClientState, ConsensusState: Ics02ConsensusState> Val
138138
}
139139

140140
fn client_counter(&self) -> Result<u64, ibc::core::ContextError> {
141-
self.parent.client_counter().map_err(|e| {
142-
ContextError::ClientError(ClientError::ClientSpecific {
143-
description: e.to_string(),
144-
})
145-
})
141+
unimplemented!()
146142
}
147143

148144
fn connection_end(

modules/light-client/src/path.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
use crate::types::{ClientId, Height};
22
use derive_more::Display;
33

4-
pub static NEXT_CLIENT_SEQUENCE: &str = "nextClientSequence";
5-
64
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Display)]
75
#[display(fmt = "clients/{_0}/clientType")]
86
pub struct ClientTypePath(pub ClientId);

modules/types/src/errors.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,26 @@ define_error! {
4646
|_| {
4747
"identifier cannot be empty"
4848
},
49+
ClientIdInvalidFormat
50+
{ id: String }
51+
|e| {
52+
format_args!("identifier `{}` must be in the format `{{client_type}}-{{counter}}`", e.id)
53+
},
54+
ClientIdInvalidClientType
55+
{ id: String, client_type: String }
56+
|e| {
57+
format_args!("identifier `{}` must have client type `{}`", e.id, e.client_type)
58+
},
59+
ClientIdInvalidCounter
60+
{ id: String }
61+
|e| {
62+
format_args!("identifier `{}` must have a valid counter", e.id)
63+
},
64+
ClientIdInvalidCounterParseIntError
65+
{ id: String, e: core::num::ParseIntError }
66+
|e| {
67+
format_args!("identifier `{}` counter parse error: {}", e.id, e.e)
68+
},
4969
MrenclaveBytesConversion
5070
{
5171
bz: Vec<u8>,

0 commit comments

Comments
 (0)