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

[gh-407] add web socket relay for bitcoin and nostr protocols. #408

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
34 changes: 31 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ members = [
"crates/rooch-open-rpc",
"crates/rooch-open-rpc-spec",
"crates/rooch-open-rpc-macros",
"crates/rooch-store"
"crates/rooch-store",
"crates/rooch-ws-relay"
]

default-members = [
Expand Down Expand Up @@ -82,6 +83,7 @@ rooch-open-rpc = { path = "crates/rooch-open-rpc" }
rooch-open-rpc-spec = { path = "crates/rooch-open-rpc-spec" }
rooch-open-rpc-macros = { path = "crates/rooch-open-rpc-macros" }
rooch-store = { path = "crates/rooch-store" }
rooch-ws-relay = { path = "crates/rooch-ws-relay" }

# External crate dependencies.
# Please do not add any test features here: they should be declared by the individual crate.
Expand Down Expand Up @@ -150,7 +152,7 @@ thiserror = "1.0.34"
tiny-keccak = { version = "2", features = ["keccak", "sha3"] }
tiny-bip39 = "1.0.0"
tokio = { version = "1", features = ["full"] }
tonic = { version = "0.8", features = ["gzip"] }
tonic = { version = "0.8.3", features = ["gzip"] }
tracing = "0.1"
tracing-subscriber = "0.3"
codespan-reporting = "0.11.1"
Expand All @@ -166,7 +168,33 @@ unescape = "0.1.0"
tempfile = "3.2.0"
regex = "1.8.4"
walkdir = "2.3.3"

futures-util = "0.3"
tracing-appender = "0.2.2"
console-subscriber = "0.1.8"
tokio-tungstenite = "0.17"
tungstenite = "0.17"
uuid = { version = "1.1.2", features = ["v4"] }
config = { version = "0.12", features = ["toml"] }
bitcoin_hashes = { version = "0.10", features = ["serde"] }
secp256k1 = {version = "0.21", features = ["rand", "rand-std", "serde", "bitcoin_hashes"] }
rusqlite = { version = "0.26", features = ["limits","bundled","modern_sqlite", "trace"]}
r2d2 = "0.8"
r2d2_sqlite = "0.19"
governor = "0.4"
nonzero_ext = "0.3"
hyper = { version="0.14", features=["client", "server","http1","http2","tcp"] }
hyper-tls = "0.5"
http = { version = "0.2" }
parse_duration = "2"
const_format = "0.2.28"
async-std = "1.12.0"
sqlx = { version ="0.6.2", features=["runtime-tokio-rustls", "postgres", "chrono"]}
prometheus = "0.13.3"
indicatif = "0.17.3"
url = "2.3.1"
qrcode = { version = "0.12.0", default-features = false, features = ["svg"] }
nostr = { version = "0.18.0", default-features = false, features = ["base", "nip04", "nip19"] }
tonic-build = { version="0.8.3", features = ["prost"] }

# Note: the BEGIN and END comments below are required for external tooling. Do not remove.
# BEGIN MOVE DEPENDENCIES
Expand Down
2 changes: 2 additions & 0 deletions crates/rooch-config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

pub mod rpc;
pub mod ws;

use anyhow::{Context, Result};
use serde::{de::DeserializeOwned, Serialize};
Expand All @@ -11,6 +12,7 @@ pub const ROOCH_DIR: &str = ".rooch";
pub const ROOCH_CONFIG_DIR: &str = "rooch_config";
pub const ROOCH_CLIENT_CONFIG: &str = "rooch.yaml";
pub const ROOCH_SERVER_CONFIG: &str = "server.yaml";
pub const ROOCH_RELAY_CONFIG: &str = "relay.yaml";
pub const ROOCH_KEYSTORE_FILENAME: &str = "rooch.keystore";

pub fn rooch_config_dir() -> anyhow::Result<PathBuf, anyhow::Error> {
Expand Down
4 changes: 2 additions & 2 deletions crates/rooch-config/src/rpc/server_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub struct ServerConfig {
}

impl ServerConfig {
pub fn url(&self, https: bool) -> String {
pub fn rpc_url(&self, https: bool) -> String {
let schema = if https { "https" } else { "http" };

format!("{}://{}:{}", schema, self.host, self.port)
Expand All @@ -37,7 +37,7 @@ impl Display for ServerConfig {
impl Default for ServerConfig {
fn default() -> Self {
Self {
host: "0.0.0.0".to_string(),
host: "0.0.0.0".to_owned(),
port: 50051,
proposer_address: None,
sequencer_address: None,
Expand Down
4 changes: 4 additions & 0 deletions crates/rooch-config/src/ws/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

pub mod relay_config;
44 changes: 44 additions & 0 deletions crates/rooch-config/src/ws/relay_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) RoochNetwork
// SPDX-License-Identifier: Apache-2.0

use serde::Deserialize;
use serde::Serialize;
use std::fmt::{Display, Formatter, Result, Write};

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq, Eq, Hash)]
pub struct RelayConfig {
pub host: String,
pub port: u16,
pub remote_ip_header: Option<String>,
pub ping_interval_seconds: u32,
}

impl RelayConfig {
pub fn ws_url(&self, https: bool) -> String {
let schema = if https { "wss" } else { "ws" };

format!("{}://{}:{}", schema, self.host, self.port)
}
}

impl Display for RelayConfig {
fn fmt(&self, f: &mut Formatter<'_>) -> Result {
let mut writer = String::new();

writeln!(writer, "host : {}", self.host)?;
writeln!(writer, "port : {}", self.port)?;

write!(f, "{}", writer)
}
}

impl Default for RelayConfig {
fn default() -> Self {
Self {
host: "0.0.0.0".to_owned(),
port: 8080,
remote_ip_header: None,
ping_interval_seconds: 300,
}
}
}
7 changes: 4 additions & 3 deletions crates/rooch-rpc-client/src/client_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
use crate::{Client, ClientBuilder};
use anyhow::anyhow;
use rooch_config::rpc::server_config::ServerConfig;
use rooch_config::ws::relay_config::RelayConfig;
use rooch_config::Config;
use rooch_key::keystore::{AccountKeystore, Keystore};
use rooch_types::address::RoochAddress;
Expand Down Expand Up @@ -91,9 +92,9 @@ impl Env {
impl Default for Env {
fn default() -> Self {
Env {
alias: "default".to_string(),
rpc: ServerConfig::default().url(false),
ws: None,
alias: "default".to_owned(),
rpc: ServerConfig::default().rpc_url(false),
ws: Some(RelayConfig::default().ws_url(false)),
}
}
}
Expand Down
1 change: 1 addition & 0 deletions crates/rooch-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ pub mod error;
pub mod transaction;

pub use ethers::types::{H160, H256, H512};
pub use bitcoin::secp256k1::{XOnlyPublicKey, SecretKey, KeyPair};
83 changes: 83 additions & 0 deletions crates/rooch-ws-relay/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
[package]
name = "rooch-ws-relay"
version = "0.1.0"

# Workspace inherited keys
authors = { workspace = true }
edition = { workspace = true }
homepage = { workspace = true }
license = { workspace = true }
publish = { workspace = true }
repository = { workspace = true }
rust-version = { workspace = true }

[dependencies]
clap = { workspace = true }
tracing = { workspace = true }
tracing-appender = { workspace = true }
tracing-subscriber = { workspace = true }
tokio = { workspace = true }
prost = { workspace = true }
tonic = { workspace = true }
console-subscriber = { workspace = true }
futures = { workspace = true }
futures-util = { workspace = true }
tokio-tungstenite = { workspace = true }
tungstenite = { workspace = true }
thiserror = { workspace = true }
uuid = { workspace = true }
config = { workspace = true }
bitcoin_hashes = { workspace = true }
secp256k1 = { workspace = true }
serde = { workspace = true }
serde_json = { workspace = true }
hex = { workspace = true }
rusqlite = { workspace = true }
r2d2 = { workspace = true }
r2d2_sqlite = { workspace = true }
lazy_static = { workspace = true }
governor = { workspace = true }
nonzero_ext = { workspace = true }
hyper = { workspace = true }
hyper-tls = { workspace = true }
http = { workspace = true }
parse_duration = { workspace = true }
rand = { workspace = true }
const_format = { workspace = true }
regex = { workspace = true }
async-trait = { workspace = true }
async-std = { workspace = true }
sqlx = { workspace = true }
chrono = { workspace = true }
prometheus = { workspace = true }
indicatif = { workspace = true }
bech32 = { workspace = true }
url = { workspace = true }
qrcode = { workspace = true }
nostr = { workspace = true }
anyhow = { workspace = true }
sha3 = { workspace = true }
jsonrpsee = { workspace = true }
coerce = { workspace = true }

move-core-types = { workspace = true }
move-resource-viewer = { workspace = true }
move-binary-format = { workspace = true }

moveos-store = { workspace = true }
moveos-types = { workspace = true }
move-bytecode-utils = { workspace = true }

rooch-config = { workspace = true }
rooch-types = { workspace = true }
rooch-executor = { workspace = true }
rooch-sequencer = { workspace = true }
rooch-proposer = { workspace = true }
rooch-key = { workspace = true }
rooch-open-rpc = { workspace = true }
rooch-open-rpc-macros = { workspace = true }
rooch-store = { workspace = true }
rooch-rpc-api = { workspace = true }

[build-dependencies]
tonic-build = { workspace = true }
7 changes: 7 additions & 0 deletions crates/rooch-ws-relay/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
fn main() -> Result<(), Box<dyn std::error::Error>> {
tonic_build::configure()
.build_server(false)
.protoc_arg("--experimental_allow_proto3_optional")
.compile(&["proto/nauthz.proto"], &["proto"])?;
Ok(())
}
60 changes: 60 additions & 0 deletions crates/rooch-ws-relay/proto/nauthz.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
syntax = "proto3";

// Nostr Authorization Services
package nauthz;

// Authorization for actions against a relay
service Authorization {
// Determine if an event should be admitted to the relay
rpc EventAdmit(EventRequest) returns (EventReply) {}
}

message Event {
bytes id = 1; // 32-byte SHA256 hash of serialized event
bytes pubkey = 2; // 32-byte public key of event creator
fixed64 created_at = 3; // UNIX timestamp provided by event creator
uint64 kind = 4; // event kind
string content = 5; // arbitrary event contents
repeated TagEntry tags = 6; // event tag array
bytes sig = 7; // 32-byte signature of the event id
// Individual values for a single tag
message TagEntry {
repeated string values = 1;
}
}

// Event data and metadata for authorization decisions
message EventRequest {
Event event =
1; // the event to be admitted for further relay processing
optional string ip_addr =
2; // IP address of the client that submitted the event
optional string origin =
3; // HTTP origin header from the client, if one exists
optional string user_agent =
4; // HTTP user-agent header from the client, if one exists
optional bytes auth_pubkey =
5; // the public key associated with a NIP-42 AUTH'd session, if
// authentication occurred
optional Nip05Name nip05 =
6; // NIP-05 address associated with the event pubkey, if it is
// known and has been validated by the relay
// A NIP_05 verification record
message Nip05Name {
string local = 1;
string domain = 2;
}
}

// A permit or deny decision
enum Decision {
DECISION_UNSPECIFIED = 0;
DECISION_PERMIT = 1; // Admit this event for further processing
DECISION_DENY = 2; // Deny persisting or propagating this event
}

// Response to a event authorization request
message EventReply {
Decision decision = 1; // decision to enforce
optional string message = 2; // informative message for the client
}
Loading