Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions core/src/ibc/connection_03/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::ibc::connection_03::types::{ConnectionEnd, ConnectionIdentifiersInCli
use crate::ibc::{Identifier, IdentifierSlice};
use ibc::client_02::Manager as ClientManager;
use primitives::Bytes;
use rlp::{Encodable, Rlp};
use rlp::Encodable;

pub struct Manager<'a> {
ctx: &'a mut dyn ibc::Context,
Expand Down Expand Up @@ -221,16 +221,30 @@ impl<'a> Manager<'a> {
Some(connection_end)
}

fn query_client_connections(&self, identifier: &str) -> ConnectionIdentifiersInClient {
let kv_store = self.ctx.get_kv_store();
let path = client_connections_path(identifier);
kv_store.get(&path).map(|bytes| rlp::decode(&bytes).expect("data from DB")).unwrap_or_default()
}

fn add_connection_to_client(
&mut self,
client_identifier: Identifier,
connection_identifier: Identifier,
) -> Result<(), String> {
let kv_store = self.ctx.get_kv_store_mut();
let bytes =
kv_store.get(&client_connections_path(&client_identifier)).ok_or_else(|| "Connection exist".to_owned())?;
let rlp = Rlp::new(&bytes);
let mut conns: ConnectionIdentifiersInClient = rlp.as_val().expect("data from DB");
if kv_store.contains_key(&connection_path(&connection_identifier)) {
return Err("Connection exist".to_owned())
}

let path = client_connections_path(&client_identifier);
let mut conns: ConnectionIdentifiersInClient = kv_store
.get(&path)
.map(|bytes| {
rlp::decode::<ConnectionIdentifiersInClient>(&bytes)
.expect("Only the connection code can save the code")
})
.unwrap_or_default();

conns.add(connection_identifier);

Expand Down
3 changes: 3 additions & 0 deletions core/src/ibc/connection_03/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ pub fn client_connections_path(client_id: &str) -> String {
}

pub use manager::Manager;
pub use types::ConnectionEnd;
pub use types::ConnectionIdentifiersInClient;
pub use types::ConnectionState;
10 changes: 9 additions & 1 deletion core/src/ibc/connection_03/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,21 @@ pub struct ConnectionEnd {
// FIXME: implement version
}

#[derive(RlpEncodableWrapper, RlpDecodableWrapper, PartialEq, Debug)]
#[derive(RlpEncodableWrapper, RlpDecodableWrapper, PartialEq, Debug, Default)]
pub struct ConnectionIdentifiersInClient(Vec<Identifier>);

impl ConnectionIdentifiersInClient {
pub fn new() -> Self {
Self(Vec::new())
}

pub fn add(&mut self, identifier: Identifier) {
self.0.push(identifier);
}

pub fn into_vec(self) -> Vec<Identifier> {
self.0
}
}

#[cfg(test)]
Expand Down
12 changes: 12 additions & 0 deletions core/src/ibc/querier/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ impl DebugName for ibc::client_02::types::ConsensusState {
}
}

impl DebugName for ibc::connection_03::types::ConnectionIdentifiersInClient {
fn debug_name() -> &'static str {
"ConnectionIdentifiersInClient"
}
}

/// Queries the path and returns the result in decoded struct
pub fn query<T>(ctx: &dyn ibc::Context, path: &CommitmentPath) -> Option<T>
where
Expand Down Expand Up @@ -89,3 +95,9 @@ pub fn path_connection_end(id: IdentifierSlice) -> CommitmentPath {
raw: ibc::connection_03::path(id),
}
}

pub fn path_connection_identifiers(client_id: IdentifierSlice) -> CommitmentPath {
CommitmentPath {
raw: ibc::connection_03::client_connections_path(client_id),
}
}
52 changes: 51 additions & 1 deletion rpc/src/v1/impls/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

use super::super::errors;
use super::super::traits::IBC;
use super::super::types::{ClientState, ConsensusState, IBCQuery};
use super::super::types::{ClientState, ConnectionEnd, ConnectionIdentifiersInClient, ConsensusState, IBCQuery};
use ccore::ibc;
use ccore::ibc::querier;
use ccore::{BlockChainClient, BlockId, StateInfo};
Expand Down Expand Up @@ -126,4 +126,54 @@ where
};
Ok(Some(rlp::encode(&header)))
}

fn query_connection(
&self,
identifier: String,
block_number: Option<u64>,
) -> Result<Option<IBCQuery<ConnectionEnd>>> {
let block_id = block_number.map(BlockId::Number).unwrap_or(BlockId::Latest);
let mut state = self.client.state_at(block_id).ok_or_else(errors::state_not_exist)?;
let block_number = match self.client.block_number(&block_id) {
None => return Ok(None),
Some(block_number) => block_number,
};

let context = ibc::context::TopLevelContext::new(&mut state, block_number);

let path = querier::path_connection_end(&identifier);
let connection_end: Option<ibc::connection_03::ConnectionEnd> = querier::query(&context, &path);

let response = IBCQuery {
number: block_number,
data: connection_end.map(ConnectionEnd::from_core),
proof: querier::make_proof(&context, &path),
};
Ok(Some(response))
}

fn query_client_connections(
&self,
client_identifier: String,
block_number: Option<u64>,
) -> Result<Option<IBCQuery<ConnectionIdentifiersInClient>>> {
let block_id = block_number.map(BlockId::Number).unwrap_or(BlockId::Latest);
let mut state = self.client.state_at(block_id).ok_or_else(errors::state_not_exist)?;
let block_number = match self.client.block_number(&block_id) {
None => return Ok(None),
Some(block_number) => block_number,
};

let context = ibc::context::TopLevelContext::new(&mut state, block_number);
let path = querier::path_connection_identifiers(&client_identifier);
let connections_in_client: Option<ibc::connection_03::ConnectionIdentifiersInClient> =
querier::query(&context, &path);

let response = IBCQuery {
number: block_number,
data: connections_in_client.map(|from_core| from_core.into_vec()),
proof: querier::make_proof(&context, &path),
};
Ok(Some(response))
}
}
16 changes: 15 additions & 1 deletion rpc/src/v1/traits/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use super::super::types::IBCQuery;
use super::super::types::{ClientState, ConsensusState};
use super::super::types::{ClientState, ConnectionEnd, ConnectionIdentifiersInClient, ConsensusState};
use jsonrpc_core::Result;
use primitives::Bytes;

Expand All @@ -39,4 +39,18 @@ pub trait IBC {
/// from block_number-1 to block_number. It will stay opaque until it gets finally delieverd to Foundry light client.
#[rpc(name = "ibc_compose_header")]
fn compose_header(&self, block_number: u64) -> Result<Option<Bytes>>;

#[rpc(name = "ibc_query_connection")]
fn query_connection(
&self,
identifier: String,
block_number: Option<u64>,
) -> Result<Option<IBCQuery<ConnectionEnd>>>;

#[rpc(name = "ibc_query_client_connections")]
fn query_client_connections(
&self,
client_identifier: String,
block_number: Option<u64>,
) -> Result<Option<IBCQuery<ConnectionIdentifiersInClient>>>;
}
47 changes: 47 additions & 0 deletions rpc/src/v1/types/ibc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,15 @@
// along with this program. If not, see <https://www.gnu.org/licenses/>.

use codechain_core::ibc::client_02::types::{ClientState as CoreClientState, ConsensusState as CoreConsensusState};
use codechain_core::ibc::connection_03::types::{
ConnectionEnd as CoreConnectionEnd, ConnectionState as CoreConnectionState,
};
use primitives::{Bytes, H256};
use serde::Serialize;

type Identifier = String;
type CommitmentPrefix = String;

/// Many of RPC responses will be expressed with this
/// Because of the nature of IBC, they commonly
/// 1. Requires a block number for which proof stands
Expand Down Expand Up @@ -68,3 +74,44 @@ impl ConsensusState {
}
}
}

#[derive(Debug, Serialize)]
pub enum ConnectionState {
INIT,
TRYOPEN,
OPEN,
}

impl ConnectionState {
pub fn from_core(core_connection_state: CoreConnectionState) -> Self {
match core_connection_state {
CoreConnectionState::INIT => ConnectionState::INIT,
CoreConnectionState::TRYOPEN => ConnectionState::TRYOPEN,
CoreConnectionState::OPEN => ConnectionState::OPEN,
}
}
}

#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct ConnectionEnd {
pub state: ConnectionState,
pub counterparty_connection_identifier: Identifier,
pub counterparty_prefix: CommitmentPrefix,
pub client_identifier: Identifier,
pub counterparty_client_identifier: Identifier,
}

impl ConnectionEnd {
pub fn from_core(core_connection_end: CoreConnectionEnd) -> Self {
ConnectionEnd {
state: ConnectionState::from_core(core_connection_end.state),
counterparty_connection_identifier: core_connection_end.counterparty_connection_identifier,
counterparty_prefix: core_connection_end.counterparty_prefix.raw,
client_identifier: core_connection_end.client_identifier,
counterparty_client_identifier: core_connection_end.counterparty_client_identifier,
}
}
}

pub type ConnectionIdentifiersInClient = Vec<String>;
2 changes: 1 addition & 1 deletion rpc/src/v1/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ mod work;
pub use self::action::{Action, ActionWithTracker};
pub use self::block::Block;
pub use self::block::BlockNumberAndHash;
pub use self::ibc::{ClientState, ConsensusState, IBCQuery};
pub use self::ibc::{ClientState, ConnectionEnd, ConnectionIdentifiersInClient, ConsensusState, IBCQuery};
pub use self::mem_pool::MemPoolMinFees;
pub use self::transaction::{PendingTransactions, Transaction};
pub use self::unsigned_transaction::UnsignedTransaction;
Expand Down