Skip to content

Commit 8506022

Browse files
committed
Move IBC transactions to toplevel
1 parent b27f0ab commit 8506022

File tree

4 files changed

+181
-5
lines changed

4 files changed

+181
-5
lines changed

core/src/client/client.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::client::{ConsensusClient, SnapshotClient, TermInfo};
2626
use crate::consensus::{CodeChainEngine, EngineError};
2727
use crate::encoded;
2828
use crate::error::{BlockImportError, Error, ImportError, SchemeError};
29+
use crate::ibc;
2930
use crate::miner::{Miner, MinerService};
3031
use crate::scheme::Scheme;
3132
use crate::service::ClientIoMessage;
@@ -862,11 +863,11 @@ impl SnapshotClient for Client {
862863
impl IBCTransactionExecutor for Client {
863864
fn execute(
864865
&self,
865-
_bytes: &[u8],
866-
_state: &mut TopLevelState,
867-
_fee_payer: &Address,
868-
_sender_pubkey: &Public,
866+
bytes: &[u8],
867+
state: &mut TopLevelState,
868+
fee_payer: &Address,
869+
sender_pubkey: &Public,
869870
) -> StateResult<()> {
870-
unimplemented!()
871+
ibc::execute_transaction(bytes, state, fee_payer, sender_pubkey)
871872
}
872873
}

core/src/ibc/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ pub mod context;
2323
#[allow(unused_variables)]
2424
pub mod custom_action_handler;
2525
mod kv_store;
26+
mod transaction_handler;
2627

2728
pub use self::client_02 as client;
2829
pub use self::context::Context;
2930
pub use self::kv_store::KVStore;
31+
pub use transaction_handler::execute as execute_transaction;
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2019-2020 Kodebox, Inc.
2+
// This file is part of CodeChain.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as
6+
// published by the Free Software Foundation, either version 3 of the
7+
// License, or (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
use rlp::{Decodable, DecoderError, Encodable, Rlp, RlpStream};
18+
19+
const ACTION_CREATE_CLIENT: u8 = 1;
20+
const ACTION_UPDATE_CLIENT: u8 = 2;
21+
22+
#[derive(Debug, PartialEq)]
23+
pub enum Action {
24+
CreateClient {
25+
id: String,
26+
kind: u8,
27+
consensus_state: Vec<u8>,
28+
},
29+
UpdateClient {
30+
id: String,
31+
header: Vec<u8>,
32+
},
33+
}
34+
35+
impl Encodable for Action {
36+
fn rlp_append(&self, s: &mut RlpStream) {
37+
match self {
38+
Action::CreateClient {
39+
id,
40+
kind,
41+
consensus_state,
42+
} => {
43+
s.begin_list(4).append(&ACTION_CREATE_CLIENT).append(id).append(kind).append(consensus_state);
44+
}
45+
Action::UpdateClient {
46+
id,
47+
header,
48+
} => {
49+
s.begin_list(3).append(&ACTION_UPDATE_CLIENT).append(id).append(header);
50+
}
51+
};
52+
}
53+
}
54+
55+
impl Decodable for Action {
56+
fn decode(rlp: &Rlp) -> Result<Self, DecoderError> {
57+
let tag = rlp.val_at(0)?;
58+
match tag {
59+
ACTION_CREATE_CLIENT => {
60+
let item_count = rlp.item_count()?;
61+
if item_count != 4 {
62+
return Err(DecoderError::RlpInvalidLength {
63+
expected: 4,
64+
got: item_count,
65+
})
66+
}
67+
Ok(Action::CreateClient {
68+
id: rlp.val_at(1)?,
69+
kind: rlp.val_at(2)?,
70+
consensus_state: rlp.val_at(3)?,
71+
})
72+
}
73+
ACTION_UPDATE_CLIENT => {
74+
let item_count = rlp.item_count()?;
75+
if item_count != 3 {
76+
return Err(DecoderError::RlpInvalidLength {
77+
expected: 3,
78+
got: item_count,
79+
})
80+
}
81+
Ok(Action::UpdateClient {
82+
id: rlp.val_at(1)?,
83+
header: rlp.val_at(2)?,
84+
})
85+
}
86+
_ => Err(DecoderError::Custom("Unexpected IBC Action Type")),
87+
}
88+
}
89+
}
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2020 Kodebox, Inc.
2+
// This file is part of CodeChain.
3+
//
4+
// This program is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Affero General Public License as
6+
// published by the Free Software Foundation, either version 3 of the
7+
// License, or (at your option) any later version.
8+
//
9+
// This program is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Affero General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Affero General Public License
15+
// along with this program. If not, see <https://www.gnu.org/licenses/>.
16+
17+
mod actions;
18+
19+
use self::actions::Action;
20+
use crate::ibc;
21+
use ckey::{Address, Public};
22+
use cstate::{StateResult, TopLevelState};
23+
use ctypes::errors::RuntimeError;
24+
use ibc::client_02 as ibc_client;
25+
use ibc::client_02::foundry as ibc_foundry;
26+
use ibc::context as ibc_context;
27+
use rlp::{Decodable, Rlp};
28+
29+
pub fn execute(
30+
bytes: &[u8],
31+
state: &mut TopLevelState,
32+
fee_payer: &Address,
33+
_sender_public: &Public,
34+
) -> StateResult<()> {
35+
let action = Action::decode(&Rlp::new(bytes)).expect("Verification passed");
36+
match action {
37+
Action::CreateClient {
38+
id,
39+
kind,
40+
consensus_state,
41+
} => create_client(state, fee_payer, &id, kind, &consensus_state),
42+
Action::UpdateClient {
43+
id,
44+
header,
45+
} => update_client(state, &id, &header),
46+
}
47+
}
48+
49+
50+
fn create_client(
51+
state: &mut TopLevelState,
52+
_fee_payer: &Address,
53+
id: &str,
54+
kind: ibc_client::Kind,
55+
consensus_state: &[u8],
56+
) -> StateResult<()> {
57+
let mut context = ibc_context::TopLevelContext::new(state);
58+
let client_manager = ibc_client::Manager::new();
59+
if kind != ibc_client::KIND_FOUNDRY {
60+
return Err(RuntimeError::IBC(format!("CreateClient has invalid type {}", kind)).into())
61+
}
62+
let rlp = rlp::Rlp::new(consensus_state);
63+
let foundry_consensus_state: ibc_foundry::ConsensusState = match rlp.as_val() {
64+
Ok(cs) => cs,
65+
Err(err) => {
66+
return Err(RuntimeError::IBC(format!("CreateClient failed to decode consensus state {}", err)).into())
67+
}
68+
};
69+
70+
client_manager
71+
.create(&mut context, id, &foundry_consensus_state)
72+
.map_err(|err| RuntimeError::IBC(format!("CreateClient: {:?}", err)))?;
73+
Ok(())
74+
}
75+
76+
fn update_client(state: &mut TopLevelState, id: &str, header: &[u8]) -> StateResult<()> {
77+
let mut context = ibc_context::TopLevelContext::new(state);
78+
let client_manager = ibc_client::Manager::new();
79+
let client_state = client_manager.query(&mut context, id).map_err(RuntimeError::IBC)?;
80+
81+
client_state.update(&mut context, header).map_err(RuntimeError::IBC)?;
82+
83+
Ok(())
84+
}

0 commit comments

Comments
 (0)