Skip to content

Commit

Permalink
refactor: invoice rpc
Browse files Browse the repository at this point in the history
  • Loading branch information
quake committed Jun 9, 2024
1 parent 2dcb280 commit f07ea99
Show file tree
Hide file tree
Showing 16 changed files with 280 additions and 424 deletions.
5 changes: 5 additions & 0 deletions src/invoice/invoice_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use super::errors::VerificationError;
use super::utils::*;
use crate::ckb::gen::invoice::{self as gen_invoice, *};
use crate::ckb::serde_utils::EntityHex;
use crate::ckb::serde_utils::U128Hex;
use crate::ckb::types::Hash256;
use crate::invoice::InvoiceError;
use bech32::{encode, u5, FromBase32, ToBase32, Variant, WriteBase32};
Expand Down Expand Up @@ -143,8 +144,10 @@ pub enum Attribute {
Feature(u64),
}

#[serde_as]
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct InvoiceData {
#[serde_as(as = "U128Hex")]
pub timestamp: u128,
pub payment_hash: Hash256,
pub attrs: Vec<Attribute>,
Expand All @@ -171,9 +174,11 @@ macro_rules! attr_getter {
/// 1. using [`CkbInvoiceBuilder`]
/// 2. using `str::parse::<CkbInvoice>(&str)` (see [`CkbInvoice::from_str`])
///
#[serde_as]
#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct CkbInvoice {
pub currency: Currency,
#[serde_as(as = "Option<U128Hex>")]
pub amount: Option<u128>,
pub prefix: Option<SiPrefix>,
pub signature: Option<InvoiceSignature>,
Expand Down
2 changes: 0 additions & 2 deletions src/invoice/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
mod command;
mod errors;
mod invoice_impl;
mod service;
mod store;
mod utils;

pub use command::*;
pub use errors::InvoiceError;
pub use invoice_impl::{CkbInvoice, Currency, InvoiceBuilder, InvoiceSignature};
pub use service::*;
pub use store::*;
127 changes: 0 additions & 127 deletions src/invoice/service.rs

This file was deleted.

32 changes: 3 additions & 29 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use ckb_pcn_node::ckb_chain::contracts::init_contracts_context;
use ckb_pcn_node::invoice::start_invoice;
use ckb_pcn_node::rpc::InvoiceCommandWithReply;
use ckb_pcn_node::store::Store;
use log::{debug, error, info};
use ractor::Actor;
Expand Down Expand Up @@ -133,40 +131,16 @@ pub async fn main() {
None => None,
};

let invoice_command_sender = {
const CHANNEL_SIZE: usize = 4000;
let (command_sender, command_receiver) =
mpsc::channel::<InvoiceCommandWithReply>(CHANNEL_SIZE);
info!("Starting cch");
start_invoice(
command_receiver,
new_tokio_cancellation_token(),
new_tokio_task_tracker(),
store,
)
.await;
Some(command_sender)
};

// Start rpc service
let rpc_server_handle = match config.rpc {
Some(rpc_config) => {
if ckb_command_sender.is_none()
&& cch_command_sender.is_none()
&& invoice_command_sender.is_none()
{
error!("Rpc service requires ckb, chh and invoice service to be started. Exiting.");
if ckb_command_sender.is_none() && cch_command_sender.is_none() {
error!("Rpc service requires ckb and cch service to be started. Exiting.");
return;
}

info!("Starting rpc");
let handle = start_rpc(
rpc_config,
ckb_command_sender,
cch_command_sender,
invoice_command_sender,
)
.await;
let handle = start_rpc(rpc_config, ckb_command_sender, cch_command_sender, store).await;
Some(handle)
}
None => None,
Expand Down
114 changes: 78 additions & 36 deletions src/rpc/invoice.rs
Original file line number Diff line number Diff line change
@@ -1,69 +1,111 @@
use super::InvoiceCommandWithReply;
use std::time::Duration;

use crate::ckb::types::Hash256;
use crate::invoice::{Currency, InvoiceCommand};
use crate::invoice::{CkbInvoice, Currency, InvoiceBuilder, InvoiceStore};
use crate::ckb::serde_utils::{U128Hex, U64Hex};
use jsonrpsee::types::error::CALL_EXECUTION_FAILED_CODE;
use jsonrpsee::{core::async_trait, proc_macros::rpc, types::ErrorObjectOwned};
use serde::{Deserialize, Serialize};
use tokio::sync::mpsc::{channel, Sender};
use serde_with::serde_as;

#[serde_as]
#[derive(Serialize, Deserialize)]
pub struct NewInvoiceParams {
#[serde_as(as = "U128Hex")]
pub amount: u128,
pub description: Option<String>,
pub currency: Currency,
pub payment_preimage: Hash256,
#[serde_as(as = "Option<U64Hex>")]
pub expiry: Option<u64>,
pub fallback_address: Option<String>,
#[serde_as(as = "Option<U64Hex>")]
pub final_cltv: Option<u64>,
#[serde_as(as = "Option<U64Hex>")]
pub final_htlc_timeout: Option<u64>,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct NewInvoiceResult {
pub invoice_string: String,
pub invoice: CkbInvoice,
}

#[derive(Serialize, Deserialize)]
pub struct ParseInvoiceParams {
pub invoice: String,
}

#[derive(Clone, Serialize, Deserialize)]
pub struct ParseInvoiceResult {
pub invoice: CkbInvoice,
}

#[rpc(server)]
pub trait InvoiceRpc {
#[method(name = "new_invoice")]
async fn new_invoice(&self, params: NewInvoiceParams) -> Result<String, ErrorObjectOwned>;
async fn new_invoice(
&self,
params: NewInvoiceParams,
) -> Result<NewInvoiceResult, ErrorObjectOwned>;

#[method(name = "parse_invoice")]
async fn parse_invoice(&self, params: ParseInvoiceParams) -> Result<String, ErrorObjectOwned>;
async fn parse_invoice(
&self,
params: ParseInvoiceParams,
) -> Result<ParseInvoiceResult, ErrorObjectOwned>;
}

pub struct InvoiceRpcServerImpl {
pub invoice_command_sender: Sender<InvoiceCommandWithReply>,
pub struct InvoiceRpcServerImpl<S> {
pub store: S,
}

impl InvoiceRpcServerImpl {
pub fn new(invoice_command_sender: Sender<InvoiceCommandWithReply>) -> Self {
InvoiceRpcServerImpl {
invoice_command_sender,
}
impl<S> InvoiceRpcServerImpl<S> {
pub fn new(store: S) -> Self {
Self { store }
}
}

#[async_trait]
impl InvoiceRpcServer for InvoiceRpcServerImpl {
async fn new_invoice(&self, params: NewInvoiceParams) -> Result<String, ErrorObjectOwned> {
let command = InvoiceCommand::NewInvoice(crate::invoice::NewInvoiceParams {
amount: params.amount,
description: params.description.clone(),
currency: params.currency,
payment_hash: None,
payment_preimage: Some(params.payment_preimage),
expiry: params.expiry,
fallback_address: params.fallback_address.clone(),
final_cltv: params.final_cltv,
final_htlc_timeout: params.final_htlc_timeout,
});
impl<S> InvoiceRpcServer for InvoiceRpcServerImpl<S>
where
S: InvoiceStore + Send + Sync + 'static,
{
async fn new_invoice(
&self,
params: NewInvoiceParams,
) -> Result<NewInvoiceResult, ErrorObjectOwned> {
let mut invoice_builder = InvoiceBuilder::new(params.currency)
.amount(Some(params.amount))
.payment_preimage(params.payment_preimage);
if let Some(description) = params.description.clone() {
invoice_builder = invoice_builder.description(description);
};
if let Some(expiry) = params.expiry {
let duration: Duration = Duration::from_secs(expiry);
invoice_builder = invoice_builder.expiry_time(duration);
};
if let Some(fallback_address) = params.fallback_address.clone() {
invoice_builder = invoice_builder.fallback_address(fallback_address);
};
if let Some(final_cltv) = params.final_cltv {
invoice_builder = invoice_builder.final_cltv(final_cltv);
};

let (sender, mut receiver) = channel(1);
let _ = self.invoice_command_sender.send((command, sender)).await;
let result = receiver.recv().await.expect("channel should not be closed");
match result {
Ok(data) => Ok(data),
match invoice_builder.build() {
Ok(invoice) => match self.store.insert_invoice(invoice.clone()) {
Ok(_) => Ok(NewInvoiceResult {
invoice_string: invoice.to_string(),
invoice,
}),
Err(e) => {
return Err(ErrorObjectOwned::owned(
CALL_EXECUTION_FAILED_CODE,
e.to_string(),
Some(params),
))
}
},
Err(e) => Err(ErrorObjectOwned::owned(
CALL_EXECUTION_FAILED_CODE,
e.to_string(),
Expand All @@ -72,13 +114,13 @@ impl InvoiceRpcServer for InvoiceRpcServerImpl {
}
}

async fn parse_invoice(&self, params: ParseInvoiceParams) -> Result<String, ErrorObjectOwned> {
let command = InvoiceCommand::ParseInvoice(params.invoice.clone());
let (sender, mut receiver) = channel(1);
let _ = self.invoice_command_sender.send((command, sender)).await;
let result = receiver.recv().await.expect("channel should not be closed");
async fn parse_invoice(
&self,
params: ParseInvoiceParams,
) -> Result<ParseInvoiceResult, ErrorObjectOwned> {
let result: Result<CkbInvoice, _> = params.invoice.parse();
match result {
Ok(data) => Ok(data),
Ok(invoice) => Ok(ParseInvoiceResult { invoice }),
Err(e) => Err(ErrorObjectOwned::owned(
CALL_EXECUTION_FAILED_CODE,
e.to_string(),
Expand Down
Loading

0 comments on commit f07ea99

Please sign in to comment.