mirror of
https://github.com/uqbar-dao/nectar.git
synced 2024-12-23 16:43:24 +03:00
WIP WIP
This commit is contained in:
parent
6206ad50bf
commit
31309454e9
24
Cargo.lock
generated
24
Cargo.lock
generated
@ -407,7 +407,7 @@ dependencies = [
|
|||||||
"alloy-sol-types",
|
"alloy-sol-types",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
"kinode_process_lib 0.6.0 (git+https://github.com/kinode-dao/process_lib?rev=3232423)",
|
"kinode_process_lib 0.6.0",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
@ -2631,6 +2631,26 @@ dependencies = [
|
|||||||
"lib",
|
"lib",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kinode_process_lib"
|
||||||
|
version = "0.6.0"
|
||||||
|
dependencies = [
|
||||||
|
"alloy-json-rpc",
|
||||||
|
"alloy-primitives",
|
||||||
|
"alloy-rpc-types",
|
||||||
|
"alloy-transport",
|
||||||
|
"anyhow",
|
||||||
|
"bincode",
|
||||||
|
"http 1.0.0",
|
||||||
|
"mime_guess",
|
||||||
|
"rand 0.8.5",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"thiserror",
|
||||||
|
"url",
|
||||||
|
"wit-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kinode_process_lib"
|
name = "kinode_process_lib"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@ -2724,7 +2744,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"bincode",
|
"bincode",
|
||||||
"hex",
|
"hex",
|
||||||
"kinode_process_lib 0.6.0 (git+https://github.com/kinode-dao/process_lib?rev=3232423)",
|
"kinode_process_lib 0.6.0",
|
||||||
"rmp-serde",
|
"rmp-serde",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -9,7 +9,8 @@ alloy-primitives = "0.6.2"
|
|||||||
alloy-sol-types = "0.6.2"
|
alloy-sol-types = "0.6.2"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "3232423" }
|
# kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "3232423" }
|
||||||
|
kinode_process_lib = { path = "../../../../../process_lib" }
|
||||||
rand = "0.8"
|
rand = "0.8"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -10,7 +10,8 @@ alloy-primitives = "0.6.2"
|
|||||||
alloy-sol-types = "0.6.2"
|
alloy-sol-types = "0.6.2"
|
||||||
bincode = "1.3.3"
|
bincode = "1.3.3"
|
||||||
hex = "0.4.3"
|
hex = "0.4.3"
|
||||||
kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "3232423" }
|
# kinode_process_lib = { git = "https://github.com/kinode-dao/process_lib", rev = "3232423" }
|
||||||
|
kinode_process_lib = { path = "../../../../../process_lib" }
|
||||||
rmp-serde = "1.1.2"
|
rmp-serde = "1.1.2"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -130,7 +130,7 @@ impl Guest for Component {
|
|||||||
|
|
||||||
fn main(our: Address, mut state: State) -> anyhow::Result<()> {
|
fn main(our: Address, mut state: State) -> anyhow::Result<()> {
|
||||||
// first, await a message from the kernel which will contain the
|
// first, await a message from the kernel which will contain the
|
||||||
// contract address for the KNS version we want to track.
|
// chain ID and contract address for the KNS version we want to track.
|
||||||
let mut contract_address: Option<String> = None;
|
let mut contract_address: Option<String> = None;
|
||||||
loop {
|
loop {
|
||||||
let Ok(Message::Request { source, body, .. }) = await_message() else {
|
let Ok(Message::Request { source, body, .. }) = await_message() else {
|
||||||
|
@ -5,6 +5,7 @@ use alloy_rpc_types::pubsub::SubscriptionResult;
|
|||||||
use alloy_transport_ws::WsConnect;
|
use alloy_transport_ws::WsConnect;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use dashmap::DashMap;
|
use dashmap::DashMap;
|
||||||
|
use futures::Future;
|
||||||
use lib::types::core::*;
|
use lib::types::core::*;
|
||||||
use lib::types::eth::*;
|
use lib::types::eth::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -17,17 +18,20 @@ use url::Url;
|
|||||||
/// mapping of chain id to ordered lists of providers
|
/// mapping of chain id to ordered lists of providers
|
||||||
type Providers = Arc<DashMap<u64, ActiveProviders>>;
|
type Providers = Arc<DashMap<u64, ActiveProviders>>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct ActiveProviders {
|
struct ActiveProviders {
|
||||||
pub urls: Vec<UrlProvider>,
|
pub urls: Vec<UrlProvider>,
|
||||||
pub nodes: Vec<NodeProvider>,
|
pub nodes: Vec<NodeProvider>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct UrlProvider {
|
struct UrlProvider {
|
||||||
pub trusted: bool,
|
pub trusted: bool,
|
||||||
pub url: String,
|
pub url: String,
|
||||||
pub pubsub: Option<Provider<PubSubFrontend>>,
|
pub pubsub: Option<Provider<PubSubFrontend>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
struct NodeProvider {
|
struct NodeProvider {
|
||||||
pub trusted: bool,
|
pub trusted: bool,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -36,6 +40,7 @@ struct NodeProvider {
|
|||||||
/// existing subscriptions held by local processes
|
/// existing subscriptions held by local processes
|
||||||
type ActiveSubscriptions = Arc<DashMap<ProcessId, HashMap<u64, ActiveSub>>>;
|
type ActiveSubscriptions = Arc<DashMap<ProcessId, HashMap<u64, ActiveSub>>>;
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
enum ActiveSub {
|
enum ActiveSub {
|
||||||
Local(JoinHandle<()>),
|
Local(JoinHandle<()>),
|
||||||
Remote(String), // name of node providing this subscription for us
|
Remote(String), // name of node providing this subscription for us
|
||||||
@ -112,6 +117,8 @@ pub async fn provider(
|
|||||||
ap.add_provider_config(entry);
|
ap.add_provider_config(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("providers: {providers:?}\r");
|
||||||
|
|
||||||
// handles of longrunning subscriptions.
|
// handles of longrunning subscriptions.
|
||||||
let mut active_subscriptions: ActiveSubscriptions = Arc::new(DashMap::new());
|
let mut active_subscriptions: ActiveSubscriptions = Arc::new(DashMap::new());
|
||||||
|
|
||||||
@ -149,6 +156,7 @@ async fn handle_message(
|
|||||||
providers: &mut Providers,
|
providers: &mut Providers,
|
||||||
active_subscriptions: &mut ActiveSubscriptions,
|
active_subscriptions: &mut ActiveSubscriptions,
|
||||||
) -> Result<(), EthError> {
|
) -> Result<(), EthError> {
|
||||||
|
println!("provider: handle_message\r");
|
||||||
match &km.message {
|
match &km.message {
|
||||||
Message::Response(_) => handle_passthrough_response(our, send_to_loop, km).await,
|
Message::Response(_) => handle_passthrough_response(our, send_to_loop, km).await,
|
||||||
Message::Request(req) => {
|
Message::Request(req) => {
|
||||||
@ -187,6 +195,7 @@ async fn handle_passthrough_response(
|
|||||||
send_to_loop: &MessageSender,
|
send_to_loop: &MessageSender,
|
||||||
km: KernelMessage,
|
km: KernelMessage,
|
||||||
) -> Result<(), EthError> {
|
) -> Result<(), EthError> {
|
||||||
|
println!("provider: handle_passthrough_response\r");
|
||||||
send_to_loop
|
send_to_loop
|
||||||
.send(KernelMessage {
|
.send(KernelMessage {
|
||||||
id: rand::random(),
|
id: rand::random(),
|
||||||
@ -213,6 +222,7 @@ async fn handle_eth_action(
|
|||||||
providers: &mut Providers,
|
providers: &mut Providers,
|
||||||
active_subscriptions: &mut ActiveSubscriptions,
|
active_subscriptions: &mut ActiveSubscriptions,
|
||||||
) -> Result<(), EthError> {
|
) -> Result<(), EthError> {
|
||||||
|
println!("provider: handle_eth_action\r");
|
||||||
// check our access settings if the request is from a remote node
|
// check our access settings if the request is from a remote node
|
||||||
if km.source.node != our {
|
if km.source.node != our {
|
||||||
if !access_settings.deny.contains(&km.source.node) {
|
if !access_settings.deny.contains(&km.source.node) {
|
||||||
@ -245,6 +255,7 @@ async fn handle_eth_action(
|
|||||||
send_to_loop.clone(),
|
send_to_loop.clone(),
|
||||||
eth_action,
|
eth_action,
|
||||||
providers.clone(),
|
providers.clone(),
|
||||||
|
active_subscriptions.clone(),
|
||||||
)));
|
)));
|
||||||
let mut subs = active_subscriptions
|
let mut subs = active_subscriptions
|
||||||
.entry(km.source.process)
|
.entry(km.source.process)
|
||||||
@ -279,6 +290,7 @@ async fn handle_eth_action(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// spawned as a task
|
/// spawned as a task
|
||||||
|
/// cleans itself up when the subscription is closed or fails.
|
||||||
async fn create_new_subscription(
|
async fn create_new_subscription(
|
||||||
our: String,
|
our: String,
|
||||||
km_id: u64,
|
km_id: u64,
|
||||||
@ -287,7 +299,76 @@ async fn create_new_subscription(
|
|||||||
send_to_loop: MessageSender,
|
send_to_loop: MessageSender,
|
||||||
eth_action: EthAction,
|
eth_action: EthAction,
|
||||||
providers: Providers,
|
providers: Providers,
|
||||||
|
active_subscriptions: ActiveSubscriptions,
|
||||||
) {
|
) {
|
||||||
|
println!("provider: create_new_subscription\r");
|
||||||
|
match build_subscription(
|
||||||
|
our.clone(),
|
||||||
|
km_id,
|
||||||
|
target.clone(),
|
||||||
|
rsvp.clone(),
|
||||||
|
send_to_loop.clone(),
|
||||||
|
ð_action,
|
||||||
|
providers,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
Ok(future) => {
|
||||||
|
// send a response to the target that the subscription was successful
|
||||||
|
send_to_loop
|
||||||
|
.send(KernelMessage {
|
||||||
|
id: km_id,
|
||||||
|
source: Address {
|
||||||
|
node: our.to_string(),
|
||||||
|
process: ETH_PROCESS_ID.clone(),
|
||||||
|
},
|
||||||
|
target: target.clone(),
|
||||||
|
rsvp: rsvp.clone(),
|
||||||
|
message: Message::Response((
|
||||||
|
Response {
|
||||||
|
inherit: false,
|
||||||
|
body: serde_json::to_vec(&EthResponse::Ok).unwrap(),
|
||||||
|
metadata: None,
|
||||||
|
capabilities: vec![],
|
||||||
|
},
|
||||||
|
None,
|
||||||
|
)),
|
||||||
|
lazy_load_blob: None,
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.expect("eth: sender died!");
|
||||||
|
// await the subscription error and kill it if so
|
||||||
|
if let Err(e) = future.await {
|
||||||
|
send_to_loop
|
||||||
|
.send(make_error_message(&our, km_id, target.clone(), e))
|
||||||
|
.await
|
||||||
|
.expect("eth: kernel sender died!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
send_to_loop
|
||||||
|
.send(make_error_message(&our, km_id, target.clone(), e))
|
||||||
|
.await
|
||||||
|
.expect("eth: kernel sender died!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
active_subscriptions
|
||||||
|
.entry(target.process)
|
||||||
|
.and_modify(|sub_map| {
|
||||||
|
sub_map.remove(&km_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn build_subscription(
|
||||||
|
our: String,
|
||||||
|
km_id: u64,
|
||||||
|
target: Address,
|
||||||
|
rsvp: Option<Address>,
|
||||||
|
send_to_loop: MessageSender,
|
||||||
|
eth_action: &EthAction,
|
||||||
|
providers: Providers,
|
||||||
|
) -> Result<impl Future<Output = Result<(), EthError>>, EthError> {
|
||||||
|
println!("provider: build_subscription\r");
|
||||||
let EthAction::SubscribeLogs {
|
let EthAction::SubscribeLogs {
|
||||||
sub_id,
|
sub_id,
|
||||||
chain_id,
|
chain_id,
|
||||||
@ -295,19 +376,12 @@ async fn create_new_subscription(
|
|||||||
params,
|
params,
|
||||||
} = eth_action
|
} = eth_action
|
||||||
else {
|
else {
|
||||||
return;
|
return Err(EthError::InvalidMethod(
|
||||||
|
"eth: only accepts subscribe logs requests".to_string(),
|
||||||
|
));
|
||||||
};
|
};
|
||||||
let Some(aps) = providers.get_mut(&chain_id) else {
|
let Some(aps) = providers.get_mut(&chain_id) else {
|
||||||
send_to_loop
|
return Err(EthError::NoRpcForChain);
|
||||||
.send(make_error_message(
|
|
||||||
&our,
|
|
||||||
sub_id,
|
|
||||||
target,
|
|
||||||
EthError::NoRpcForChain,
|
|
||||||
))
|
|
||||||
.await
|
|
||||||
.expect("eth: kernel sender died!");
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
// first, try any url providers we have for this chain,
|
// first, try any url providers we have for this chain,
|
||||||
// then if we have none or they all fail, go to node providers.
|
// then if we have none or they all fail, go to node providers.
|
||||||
@ -322,31 +396,21 @@ async fn create_new_subscription(
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
let rx = pubsub.inner().get_raw_subscription(id).await;
|
let rx = pubsub.inner().get_raw_subscription(id).await;
|
||||||
if let Err(e) =
|
return Ok(maintain_subscription(
|
||||||
handle_subscription_stream(&our, sub_id, rx, &target, &rsvp, &send_to_loop)
|
our,
|
||||||
.await
|
*sub_id,
|
||||||
{
|
rx,
|
||||||
send_to_loop
|
target,
|
||||||
.send(make_error_message(&our, sub_id, target, e))
|
rsvp,
|
||||||
.await
|
send_to_loop,
|
||||||
.expect("eth: kernel sender died!");
|
));
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for node_provider in &aps.nodes {
|
for node_provider in &aps.nodes {
|
||||||
// todo
|
// todo
|
||||||
}
|
}
|
||||||
send_to_loop
|
return Err(EthError::NoRpcForChain);
|
||||||
.send(make_error_message(
|
|
||||||
&our,
|
|
||||||
sub_id,
|
|
||||||
target,
|
|
||||||
EthError::NoRpcForChain,
|
|
||||||
))
|
|
||||||
.await
|
|
||||||
.expect("eth: kernel sender died!");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_eth_config_action(
|
async fn handle_eth_config_action(
|
||||||
@ -357,6 +421,7 @@ async fn handle_eth_config_action(
|
|||||||
eth_config_action: EthConfigAction,
|
eth_config_action: EthConfigAction,
|
||||||
providers: &mut Providers,
|
providers: &mut Providers,
|
||||||
) -> Result<(), EthError> {
|
) -> Result<(), EthError> {
|
||||||
|
println!("provider: handle_eth_config_action\r");
|
||||||
if km.source.node != our {
|
if km.source.node != our {
|
||||||
return Err(EthError::PermissionDenied);
|
return Err(EthError::PermissionDenied);
|
||||||
}
|
}
|
||||||
@ -611,14 +676,15 @@ async fn handle_eth_config_action(
|
|||||||
/// Executed as a long-lived task. The JoinHandle is stored in the `connections` map.
|
/// Executed as a long-lived task. The JoinHandle is stored in the `connections` map.
|
||||||
/// This task is responsible for connecting to the ETH RPC provider and streaming logs
|
/// This task is responsible for connecting to the ETH RPC provider and streaming logs
|
||||||
/// for a specific subscription made by a process.
|
/// for a specific subscription made by a process.
|
||||||
async fn handle_subscription_stream(
|
async fn maintain_subscription(
|
||||||
our: &str,
|
our: String,
|
||||||
sub_id: u64,
|
sub_id: u64,
|
||||||
mut rx: RawSubscription,
|
mut rx: RawSubscription,
|
||||||
target: &Address,
|
target: Address,
|
||||||
rsvp: &Option<Address>,
|
rsvp: Option<Address>,
|
||||||
send_to_loop: &MessageSender,
|
send_to_loop: MessageSender,
|
||||||
) -> Result<(), EthError> {
|
) -> Result<(), EthError> {
|
||||||
|
println!("provider: maintain_subscription\r");
|
||||||
loop {
|
loop {
|
||||||
match rx.recv().await {
|
match rx.recv().await {
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -660,9 +726,10 @@ async fn handle_subscription_stream(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_error_message(our: &str, id: u64, target: Address, error: EthError) -> KernelMessage {
|
fn make_error_message(our: &str, km_id: u64, target: Address, error: EthError) -> KernelMessage {
|
||||||
|
println!("provider: make_error_message\r");
|
||||||
KernelMessage {
|
KernelMessage {
|
||||||
id,
|
id: km_id,
|
||||||
source: Address {
|
source: Address {
|
||||||
node: our.to_string(),
|
node: our.to_string(),
|
||||||
process: ETH_PROCESS_ID.clone(),
|
process: ETH_PROCESS_ID.clone(),
|
||||||
|
@ -548,7 +548,6 @@ async fn main() {
|
|||||||
timer_service_receiver,
|
timer_service_receiver,
|
||||||
print_sender.clone(),
|
print_sender.clone(),
|
||||||
));
|
));
|
||||||
#[cfg(not(feature = "simulation-mode"))]
|
|
||||||
tasks.spawn(eth::provider::provider(
|
tasks.spawn(eth::provider::provider(
|
||||||
our.name.clone(),
|
our.name.clone(),
|
||||||
eth_provider_config,
|
eth_provider_config,
|
||||||
@ -557,17 +556,6 @@ async fn main() {
|
|||||||
caps_oracle_sender.clone(),
|
caps_oracle_sender.clone(),
|
||||||
print_sender.clone(),
|
print_sender.clone(),
|
||||||
));
|
));
|
||||||
#[cfg(feature = "simulation-mode")]
|
|
||||||
if let Some(ref rpc_url) = rpc_url {
|
|
||||||
tasks.spawn(eth::provider::provider(
|
|
||||||
our.name.clone(),
|
|
||||||
eth_provider,
|
|
||||||
public,
|
|
||||||
kernel_message_sender.clone(),
|
|
||||||
eth_provider_receiver,
|
|
||||||
print_sender.clone(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
tasks.spawn(vfs::vfs(
|
tasks.spawn(vfs::vfs(
|
||||||
our.name.clone(),
|
our.name.clone(),
|
||||||
kernel_message_sender.clone(),
|
kernel_message_sender.clone(),
|
||||||
|
@ -391,11 +391,11 @@ async fn bootstrap(
|
|||||||
|
|
||||||
for (package_metadata, mut package) in packages.clone() {
|
for (package_metadata, mut package) in packages.clone() {
|
||||||
let package_name = package_metadata.properties.package_name.as_str();
|
let package_name = package_metadata.properties.package_name.as_str();
|
||||||
// special case tester: only load it in if in simulation mode
|
// // special case tester: only load it in if in simulation mode
|
||||||
if package_name == "tester" {
|
// if package_name == "tester" {
|
||||||
#[cfg(not(feature = "simulation-mode"))]
|
// #[cfg(not(feature = "simulation-mode"))]
|
||||||
continue;
|
// continue;
|
||||||
}
|
// }
|
||||||
|
|
||||||
println!("fs: handling package {package_name}...\r");
|
println!("fs: handling package {package_name}...\r");
|
||||||
let package_publisher = package_metadata.properties.publisher.as_str();
|
let package_publisher = package_metadata.properties.publisher.as_str();
|
||||||
|
Loading…
Reference in New Issue
Block a user