-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4ad1074
commit d00f276
Showing
15 changed files
with
497 additions
and
3 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
[package] | ||
name = "mock-dapp-multi" | ||
version = "0.0.0" | ||
edition = "2021" | ||
publish = false | ||
|
||
[lib] | ||
crate-type = ["cdylib"] | ||
doctest = false | ||
|
||
[dependencies] | ||
soroban-sdk = { workspace = true, features = ["alloc"] } | ||
soroban-rlp = { path = "../../libs/soroban-rlp" } | ||
xcall = { path = "../xcall" } | ||
|
||
[dev-dependencies] | ||
soroban-sdk = { workspace = true, features = ["testutils"] } |
146 changes: 146 additions & 0 deletions
146
contracts/soroban/contracts/mock-dapp-multi/src/contract.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
use soroban_rlp::decoder; | ||
use soroban_sdk::{ | ||
bytes, contract, contractimpl, panic_with_error, Address, Bytes, Env, String, Vec, | ||
}; | ||
|
||
use xcall::{ | ||
messages::{ | ||
call_message::CallMessage, call_message_persisted::CallMessagePersisted, | ||
call_message_rollback::CallMessageWithRollback, envelope::Envelope, AnyMessage, | ||
}, | ||
types::{message::MessageType, network_address::NetworkAddress}, | ||
}; | ||
|
||
use crate::{errors::ContractError, types::Connection}; | ||
|
||
#[contract] | ||
pub struct MockDapp; | ||
|
||
#[contractimpl] | ||
impl MockDapp { | ||
pub fn init(env: Env, xcall_address: Address) -> Result<(), ContractError> { | ||
let sn = u128::default(); | ||
Self::store_sn_no(&env, &sn); | ||
Self::store_xcall_address(&env, &xcall_address); | ||
|
||
Ok(()) | ||
} | ||
|
||
pub fn send_call_message( | ||
env: Env, | ||
to: NetworkAddress, | ||
data: Bytes, | ||
msg_type: u32, | ||
rollback: Option<Bytes>, | ||
fee: u128, | ||
) -> Result<(), ContractError> { | ||
let network_id = to.nid(&env); | ||
let message = Self::process_message(msg_type, data, rollback)?; | ||
let (sources, destinations) = Self::get_network_connections(&env, network_id)?; | ||
|
||
let envelope = Envelope { | ||
message, | ||
sources, | ||
destinations, | ||
}; | ||
|
||
let xcall_address = Self::get_xcall_address(&env)?; | ||
Self::xcall_send_call(&env, &to, &envelope, &fee, &xcall_address); | ||
|
||
Ok(()) | ||
} | ||
|
||
pub fn handle_call_message( | ||
env: Env, | ||
sender: Address, | ||
from: NetworkAddress, | ||
data: Bytes, | ||
_protocols: Option<Vec<String>>, | ||
) { | ||
let (nid, account) = from.parse_network_address(&env); | ||
if sender.to_string() == account { | ||
return; | ||
} | ||
|
||
let msg_data = decoder::decode_string(&env, data); | ||
if msg_data == String::from_str(&env, "rollback") { | ||
panic_with_error!(&env, ContractError::RevertFromDapp) | ||
} else { | ||
if msg_data == String::from_str(&env, "reply-response") { | ||
let message = AnyMessage::CallMessage(CallMessage { | ||
data: bytes!(&env, 0xabc), | ||
}); | ||
|
||
let xcall_address = Self::get_xcall_address(&env).ok(); | ||
if xcall_address.is_none() { | ||
panic_with_error!(&env, ContractError::Uninitialized) | ||
} | ||
|
||
let (sources, destinations) = Self::get_network_connections(&env, nid) | ||
.unwrap_or_else(|error| panic_with_error!(&env, error)); | ||
|
||
let envelope = Envelope { | ||
message, | ||
sources, | ||
destinations, | ||
}; | ||
Self::xcall_send_call(&env, &from, &envelope, &100_u128, &xcall_address.unwrap()); | ||
} | ||
} | ||
} | ||
|
||
pub fn add_connection( | ||
env: Env, | ||
src_endpoint: String, | ||
dst_endpoint: String, | ||
network_id: String, | ||
) { | ||
Self::add_new_connection( | ||
&env, | ||
network_id, | ||
Connection::new(src_endpoint, dst_endpoint), | ||
) | ||
} | ||
|
||
pub fn get_sequence(env: Env) -> Result<u128, ContractError> { | ||
Self::get_sn(&env) | ||
} | ||
|
||
fn process_message( | ||
message_type: u32, | ||
data: Bytes, | ||
rollback: Option<Bytes>, | ||
) -> Result<AnyMessage, ContractError> { | ||
let msg_type: MessageType = message_type.into(); | ||
|
||
let message = if msg_type == MessageType::CallMessagePersisted { | ||
AnyMessage::CallMessagePersisted(CallMessagePersisted { data }) | ||
} else if msg_type == MessageType::CallMessageWithRollback { | ||
if let Some(rollback) = rollback { | ||
AnyMessage::CallMessageWithRollback(CallMessageWithRollback { data, rollback }) | ||
} else { | ||
return Err(ContractError::InvalidRollbackMessage); | ||
} | ||
} else { | ||
AnyMessage::CallMessage(CallMessage { data }) | ||
}; | ||
|
||
Ok(message) | ||
} | ||
|
||
fn get_network_connections( | ||
env: &Env, | ||
network_id: String, | ||
) -> Result<(Vec<String>, Vec<String>), ContractError> { | ||
let connections = Self::get_connections(&env, network_id)?; | ||
|
||
let mut sources = Vec::new(&env); | ||
let mut destinations = Vec::new(&env); | ||
for conn in connections { | ||
sources.push_back(conn.src_endpoint); | ||
destinations.push_back(conn.dst_endpoint); | ||
} | ||
|
||
Ok((sources, destinations)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
use soroban_sdk::contracterror; | ||
|
||
#[contracterror] | ||
#[derive(Clone, Copy, PartialEq, Eq, Debug, PartialOrd, Ord)] | ||
#[repr(u32)] | ||
pub enum ContractError { | ||
OnlyAdmin = 1, | ||
Uninitialized = 2, | ||
AlreadyInitialized = 3, | ||
ConnectionNotFound = 4, | ||
InvalidRollbackMessage = 5, | ||
RevertFromDapp = 6, | ||
} |
15 changes: 15 additions & 0 deletions
15
contracts/soroban/contracts/mock-dapp-multi/src/interfaces/interface_xcall.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
use soroban_sdk::{contractclient, Address, Env}; | ||
|
||
use crate::errors::ContractError; | ||
use xcall::{messages::envelope::Envelope, types::network_address::NetworkAddress}; | ||
|
||
#[contractclient(name = "XcallClient")] | ||
pub trait IXcall { | ||
fn send_call( | ||
env: Env, | ||
envelope: Envelope, | ||
to: NetworkAddress, | ||
fee: u128, | ||
sender: Address, | ||
) -> Result<u128, ContractError>; | ||
} |
1 change: 1 addition & 0 deletions
1
contracts/soroban/contracts/mock-dapp-multi/src/interfaces/mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pub mod interface_xcall; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
#![no_std] | ||
|
||
pub mod contract; | ||
pub mod errors; | ||
pub mod interfaces; | ||
pub mod state; | ||
pub mod types; | ||
pub mod xcall; | ||
|
||
mod test; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
use soroban_sdk::{Address, Bytes, Env, String, Vec}; | ||
|
||
use crate::errors::ContractError; | ||
use crate::{ | ||
contract::MockDapp, | ||
types::{Connection, StorageKey}, | ||
}; | ||
|
||
impl MockDapp { | ||
pub fn is_initialized(e: &Env) -> Result<(), ContractError> { | ||
let initialized = e.storage().instance().has(&StorageKey::XcallAddress); | ||
if initialized { | ||
Err(ContractError::AlreadyInitialized) | ||
} else { | ||
Ok(()) | ||
} | ||
} | ||
|
||
pub fn store_xcall_address(e: &Env, address: &Address) { | ||
e.storage() | ||
.instance() | ||
.set(&StorageKey::XcallAddress, address); | ||
} | ||
|
||
pub fn store_sn_no(e: &Env, sn: &u128) { | ||
e.storage().instance().set(&StorageKey::Sn, sn) | ||
} | ||
|
||
pub fn store_rollback(e: &Env, sn: &u128, bytes: &Bytes) { | ||
e.storage() | ||
.instance() | ||
.set(&StorageKey::Rollback(*sn), bytes) | ||
} | ||
|
||
pub fn add_new_connection(e: &Env, network_id: String, conn: Connection) { | ||
let mut connections: Vec<Connection> = e | ||
.storage() | ||
.instance() | ||
.get(&StorageKey::Connections(network_id.clone())) | ||
.unwrap_or(Vec::new(&e)); | ||
|
||
connections.push_back(conn); | ||
e.storage() | ||
.instance() | ||
.set(&StorageKey::Connections(network_id), &connections); | ||
} | ||
|
||
pub fn get_connections(e: &Env, network_id: String) -> Result<Vec<Connection>, ContractError> { | ||
if let Some(connections) = e | ||
.storage() | ||
.instance() | ||
.get(&StorageKey::Connections(network_id)) | ||
{ | ||
Ok(connections) | ||
} else { | ||
Err(ContractError::ConnectionNotFound) | ||
} | ||
} | ||
|
||
pub fn get_xcall_address(e: &Env) -> Result<Address, ContractError> { | ||
if let Some(xcall) = e.storage().instance().get(&StorageKey::XcallAddress) { | ||
Ok(xcall) | ||
} else { | ||
Err(ContractError::Uninitialized) | ||
} | ||
} | ||
|
||
pub fn get_sn(e: &Env) -> Result<u128, ContractError> { | ||
if let Some(sn) = e.storage().instance().get(&StorageKey::Sn) { | ||
Ok(sn) | ||
} else { | ||
Err(ContractError::Uninitialized) | ||
} | ||
} | ||
|
||
pub fn get_next_sn(e: &Env) -> Result<u128, ContractError> { | ||
let mut sn = Self::get_sn(&e)?; | ||
sn += 1; | ||
e.storage().instance().set(&StorageKey::Sn, &sn); | ||
|
||
Ok(sn) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
#![cfg(test)] | ||
|
||
mod contract; | ||
pub mod setup; |
Oops, something went wrong.