Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add walletAddress endpoint #39

Merged
merged 4 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
17 changes: 17 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions example.env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
WALLET_ADDRESS="0x"
2 changes: 2 additions & 0 deletions xps-gateway/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ jsonrpsee = { version = "0.21", features = ["macros", "server", "client-core"] }
anyhow = "1"
thiserror = "1"
ctor = "0.2"
dotenvy = "0.15.7"
envy = "0.4.2"

[dev-dependencies]
jsonrpsee = { version = "0.21", features = ["macros", "server", "client"] }
Expand Down
26 changes: 25 additions & 1 deletion xps-gateway/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,43 @@

use anyhow::Result;
use jsonrpsee::server::Server;
use serde::Deserialize;

pub use crate::rpc::{XpsMethods, XpsServer};

pub const SERVER_HOST: &str = "127.0.0.1:0";
pub const DEFAULT_WALLET_ADDRESS: &str = "0x0000000000000000000000000000000000000000";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should generate a new hot wallet, known only to this process.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe unrelated - how do we make sure these is fund in the wallet in order to send txs?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this issue issues/23 describes the mechanism for transparency for the wallet balance. Then anyone can transfer funds to the wallet to maintain the desired level of funding for the process.

Copy link
Contributor Author

@37ng 37ng Jan 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok 👍
In that case, do walletAddress and balance RPC need authentication according to the issue requirements?
I don't think they need it since all data are public on blockchain anyways.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, you are absolutely correct these methods are safe in the sense that anyone can observe the address without exposing any risk to the internal wallet. It would be fine to implement the first version without any authentication and to update the documentation.

We still need to design the authentication and that may be a form of 'blanket authentication' such as an API key that applies to the whole server via a proxy on aws. You can ignore these considerations for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One proviso attached to the above statement however is that the wallet must be generated from a secure source of cryptographic randomness as stated in the ticket. Also the generation should be essentially constant time, using the services provided in ethers. Otherwise a hacker may be able to deduce information about the private key by observing the public one.

As an interesting aside, recently the rust RSA module was broken in this way because researchers were able to break the key generation by observing the key generation times. It turned out the algorithm they were using for key generation was not safe.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, 100% agree with you and thanks for the info!


#[derive(Deserialize)]

Check warning on line 14 in xps-gateway/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/lib.rs#L14

Added line #L14 was not covered by tests
struct XpsGatewayOptions {
/// wallet address
#[serde(default = "default_wallet_address")]
wallet_address: String,
}

fn default_wallet_address() -> String {
DEFAULT_WALLET_ADDRESS.to_string()
}

Check warning on line 23 in xps-gateway/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/lib.rs#L21-L23

Added lines #L21 - L23 were not covered by tests

/// Entrypoint for the xps Gateway
pub async fn run() -> Result<()> {
crate::util::init_logging();
match dotenvy::dotenv() {
Ok(path) => {

Check warning on line 29 in xps-gateway/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/lib.rs#L28-L29

Added lines #L28 - L29 were not covered by tests
// .env file successfully loaded.
log::debug!("Env file {} was loaded successfully", path.display());

Check warning on line 31 in xps-gateway/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/lib.rs#L31

Added line #L31 was not covered by tests
}
Err(err) => {

Check warning on line 33 in xps-gateway/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/lib.rs#L33

Added line #L33 was not covered by tests
// Error handling for the case where dotenv() fails
log::info!("Unable to load env file(s) : {err}");

Check warning on line 35 in xps-gateway/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/lib.rs#L35

Added line #L35 was not covered by tests
}
}
let opts: XpsGatewayOptions = envy::from_env()?;

Check warning on line 38 in xps-gateway/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/lib.rs#L38

Added line #L38 was not covered by tests

// a port of 0 allows the OS to choose an open port
let server = Server::builder().build(SERVER_HOST).await?;
let addr = server.local_addr()?;
let handle = server.start(rpc::XpsMethods.into_rpc());
let handle = server.start(XpsMethods::new(opts.wallet_address.as_str()).into_rpc());

Check warning on line 43 in xps-gateway/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/lib.rs#L43

Added line #L43 was not covered by tests

log::info!("Server Started at {addr}");
handle.stopped().await;
Expand Down
3 changes: 3 additions & 0 deletions xps-gateway/src/rpc/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,7 @@ pub trait Xps {
/// - The system should have proper error handling to deal with invalid requests, unauthorized access, and other potential issues.
#[method(name = "status")]
async fn status(&self) -> Result<String, ErrorObjectOwned>;

#[method(name = "walletAddress")]
async fn wallet_address(&self) -> Result<String, ErrorObjectOwned>;
}
17 changes: 13 additions & 4 deletions xps-gateway/src/rpc/methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,29 @@
use super::api::*;
use jsonrpsee::types::error::ErrorCode;

use super::super::DEFAULT_WALLET_ADDRESS;
use async_trait::async_trait;
use jsonrpsee::types::ErrorObjectOwned;

use crate::types::Message;

/// Gateway Methods for XPS
pub struct XpsMethods;
pub struct XpsMethods {
pub wallet_address: String,
}

impl XpsMethods {
/// Create a new instance of the XpsMethods struct
pub fn new() -> Self {
Self {}
pub fn new(wallet_address: &str) -> Self {
Self {
wallet_address: wallet_address.to_string(),
}
}
}

impl Default for XpsMethods {
fn default() -> Self {
Self::new()
Self::new(DEFAULT_WALLET_ADDRESS)

Check warning on line 28 in xps-gateway/src/rpc/methods.rs

View check run for this annotation

Codecov / codecov/patch

xps-gateway/src/rpc/methods.rs#L28

Added line #L28 was not covered by tests
}
}

Expand All @@ -36,4 +41,8 @@
log::debug!("xps_status called");
Ok("OK".to_string())
}

async fn wallet_address(&self) -> Result<String, ErrorObjectOwned> {
Ok(self.wallet_address.clone())
}
}
13 changes: 12 additions & 1 deletion xps-gateway/tests/integration_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use tokio::time::timeout as timeout_tokio;
use xps_gateway::{rpc::XpsClient, types::Message, XpsMethods, XpsServer, SERVER_HOST};

const TEST_TIMEOUT: Duration = Duration::from_secs(10);
const TEST_WALLET_ADDRESS: &str = "0x000000000000000000000000000000000000dEaD";

#[cfg(test)]
mod it {
Expand Down Expand Up @@ -42,6 +43,16 @@ mod it {
})
.await
}

#[tokio::test]
async fn test_wallet_address() -> Result<(), Error> {
with_xps_client(None, |client| async move {
let result = client.wallet_address().await?;
assert_eq!(result, TEST_WALLET_ADDRESS);
Ok(())
})
.await
}
}

async fn with_xps_client<F, R, T>(timeout: Option<Duration>, f: F) -> Result<T, Error>
Expand All @@ -51,7 +62,7 @@ where
{
let server = Server::builder().build(SERVER_HOST).await.unwrap();
let addr = server.local_addr().unwrap();
let handle = server.start(XpsMethods::new().into_rpc());
let handle = server.start(XpsMethods::new(TEST_WALLET_ADDRESS).into_rpc());
let client = WsClientBuilder::default()
.build(&format!("ws://{addr}"))
.await
Expand Down
Loading