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

Add database migration #315

Draft
wants to merge 16 commits into
base: main
Choose a base branch
from
Draft
49 changes: 49 additions & 0 deletions Cargo.lock

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

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ ckb-jsonrpc-types = "0.118.0"
ckb-chain-spec = "0.118.0"
ckb-resource = "0.118.0"
rocksdb = { package = "ckb-rocksdb", version = "=0.21.1", features = [
"snappy",
"lz4"
], default-features = false }
serde_with = { version = "3.7.0", features = ["macros", "base64"] }
hex = "0.4.3"
Expand Down Expand Up @@ -60,6 +60,9 @@ tokio = { version = "1", features = [
"time",
"signal",
] }
indicatif = "0.16"
console = "0.15.8"
bincode = "1.3.3"

[profile.release]
panic = "abort"
Expand Down
28 changes: 20 additions & 8 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,14 @@ struct Args {
/// config for ckb
#[command(flatten)]
pub ckb: <CkbConfig as ClapSerde>::Opt,

/// option to run database migration
#[arg(
short = 'm',
long = "migrate",
help = "run database migration, default: false"
)]
pub migrate: bool,
}

#[derive(Deserialize)]
Expand Down Expand Up @@ -119,7 +127,7 @@ pub(crate) fn print_help_and_exit(code: i32) {
}

impl Config {
pub fn parse() -> Self {
pub fn parse() -> (Self, bool) {
// Parse whole args with clap
let mut args = Args::parse();

Expand Down Expand Up @@ -193,12 +201,16 @@ impl Config {
let cch = services.contains(&Service::CCH).then_some(cch);
let rpc = services.contains(&Service::RPC).then_some(rpc);
let ckb = services.contains(&Service::CkbChain).then_some(ckb);
Self {
fiber,
cch,
rpc,
ckb,
base_dir,
}

(
Self {
fiber,
cch,
rpc,
ckb,
base_dir,
},
args.migrate,
)
}
}
2 changes: 2 additions & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ pub enum Error {
InvalidPeerMessage(String),
#[error("Onion packet error: {0}")]
InvalidOnionPacket(crate::fiber::types::Error),
#[error("Database error: {0}")]
DBInternalError(String),
}

pub type Result<T> = std::result::Result<T, Error>;
13 changes: 7 additions & 6 deletions src/fiber/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::{
fiber::{
fee::calculate_tlc_forward_fee,
network::{get_chain_hash, SendOnionPacketCommand},
serde_utils::PubNonceAsBytes,
types::{ChannelUpdate, TlcErr, TlcErrPacket, TlcErrorCode},
},
invoice::{CkbInvoice, CkbInvoiceStatus, InvoiceStore},
Expand Down Expand Up @@ -2084,7 +2085,9 @@ pub struct ChannelActorState {
#[serde_as(as = "Option<EntityHex>")]
pub local_shutdown_script: Option<Script>,

#[serde_as(as = "Option<PubNonceAsBytes>")]
pub previous_remote_nonce: Option<PubNonce>,
#[serde_as(as = "Option<PubNonceAsBytes>")]
pub remote_nonce: Option<PubNonce>,

// The latest commitment transaction we're holding
Expand All @@ -2107,7 +2110,7 @@ pub struct ChannelActorState {
}

#[serde_as]
#[derive(Clone, Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize, Eq, PartialEq, Debug)]
pub struct ShutdownInfo {
#[serde_as(as = "EntityHex")]
pub close_script: Script,
Expand All @@ -2121,6 +2124,7 @@ pub struct ShutdownInfo {
// For ChannelUpdate config, only information on our side are saved here because we have no
// control to the config on the counterparty side. And they will publish
// the config to the network via another ChannelUpdate message.
#[serde_as]
#[derive(Default, Clone, Debug, Serialize, Deserialize)]
pub struct PublicChannelInfo {
pub enabled: bool,
Expand All @@ -2140,6 +2144,8 @@ pub struct PublicChannelInfo {
// Channel announcement signatures, may be empty for private channel.
pub local_channel_announcement_signature: Option<(EcdsaSignature, PartialSignature)>,
pub remote_channel_announcement_signature: Option<(EcdsaSignature, PartialSignature)>,

#[serde_as(as = "Option<PubNonceAsBytes>")]
pub remote_channel_announcement_nonce: Option<PubNonce>,

pub channel_announcement: Option<ChannelAnnouncement>,
Expand Down Expand Up @@ -2297,11 +2303,6 @@ enum CommitmentSignedFlags {
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(
rename_all = "SCREAMING_SNAKE_CASE",
tag = "state_name",
content = "state_flags"
)]
pub enum ChannelState {
/// We are negotiating the parameters required for the channel prior to funding it.
NegotiatingFunding(NegotiatingFundingFlags),
Expand Down
2 changes: 1 addition & 1 deletion src/fiber/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ pub trait NetworkGraphStateStore {
fn get_payment_session(&self, payment_hash: Hash256) -> Option<PaymentSession>;
fn insert_payment_session(&self, session: PaymentSession);
fn insert_payment_history_result(&mut self, from: Pubkey, target: Pubkey, result: TimedResult);
fn get_payment_history_result(&self) -> Vec<(Pubkey, Pubkey, TimedResult)>;
fn get_payment_history_results(&self) -> Vec<(Pubkey, Pubkey, TimedResult)>;
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
Expand Down
2 changes: 1 addition & 1 deletion src/fiber/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ where
}

pub(crate) fn load_from_store(&mut self) {
let results = self.store.get_payment_history_result();
let results = self.store.get_payment_history_results();
for (from, target, result) in results.into_iter() {
self.inner.entry(from).or_default().insert(target, result);
}
Expand Down
53 changes: 53 additions & 0 deletions src/fiber/serde_utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use molecule::prelude::Entity;
use musig2::{BinaryEncoding, CompactSignature, PubNonce, SCHNORR_SIGNATURE_SIZE};
use serde::{de::Error, Deserialize, Deserializer, Serializer};
use serde_with::{serde_conv, DeserializeAs, SerializeAs};

Expand Down Expand Up @@ -110,3 +111,55 @@ uint_as_hex!(U128Hex, u128);
uint_as_hex!(U64Hex, u64);
uint_as_hex!(U32Hex, u32);
uint_as_hex!(U16Hex, u16);

pub struct CompactSignatureAsBytes;

impl SerializeAs<CompactSignature> for CompactSignatureAsBytes {
fn serialize_as<S>(signature: &CompactSignature, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(&signature.to_bytes())
}
}

impl<'de> DeserializeAs<'de, CompactSignature> for CompactSignatureAsBytes {
fn deserialize_as<D>(deserializer: D) -> Result<CompactSignature, D::Error>
where
D: Deserializer<'de>,
{
let bytes: &[u8] = Deserialize::deserialize(deserializer)?;
if bytes.len() != SCHNORR_SIGNATURE_SIZE {
return Err(serde::de::Error::custom("expected 64 bytes"));
}
let mut array = [0u8; SCHNORR_SIGNATURE_SIZE];
array.copy_from_slice(bytes);
CompactSignature::from_bytes(&array).map_err(serde::de::Error::custom)
}
}

pub struct PubNonceAsBytes;

impl SerializeAs<PubNonce> for PubNonceAsBytes {
fn serialize_as<S>(nonce: &PubNonce, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_bytes(&nonce.to_bytes())
}
}

impl<'de> DeserializeAs<'de, PubNonce> for PubNonceAsBytes {
fn deserialize_as<D>(deserializer: D) -> Result<PubNonce, D::Error>
where
D: Deserializer<'de>,
{
let bytes: &[u8] = Deserialize::deserialize(deserializer)?;
if bytes.len() != 66 {
return Err(serde::de::Error::custom("expected 66 bytes"));
}
let mut array = [0u8; 66];
array.copy_from_slice(bytes);
PubNonce::from_bytes(&array).map_err(serde::de::Error::custom)
}
}
2 changes: 1 addition & 1 deletion src/fiber/tests/graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct MockNetworkGraph {
impl MockNetworkGraph {
pub fn new(node_num: usize) -> Self {
let temp_path = tempfile::tempdir().unwrap();
let store = Store::new(temp_path.path());
let store = Store::new(temp_path.path()).expect("create store failed");
let keypairs = generate_key_pairs(node_num + 1);
let (secret_key1, public_key1) = keypairs[0];
let mut graph = NetworkGraph::new(store, public_key1.into());
Expand Down
2 changes: 1 addition & 1 deletion src/fiber/tests/history.rs
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ fn test_history_eval_probability_range() {
fn test_history_load_store() {
let dir = tempdir().unwrap();
let path = dir.path().join("test_history_load_store");
let store = Store::new(path);
let store = Store::new(path).expect("created store failed");
let mut history = PaymentHistory::new(generate_pubkey().into(), None, store.clone());
let from = generate_pubkey();
let target = generate_pubkey();
Expand Down
38 changes: 38 additions & 0 deletions src/fiber/tests/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::fiber::tests::test_utils::generate_pubkey;
use crate::invoice::InvoiceBuilder;
use crate::{
fiber::{
channel::ShutdownInfo,
graph::{ChannelInfo, NetworkGraphStateStore},
network::{get_chain_hash, NetworkActorStateStore, SendPaymentCommand},
tests::test_utils::NetworkNodeConfigBuilder,
Expand All @@ -27,6 +28,7 @@ use ckb_types::{
prelude::{Builder, Entity, Pack},
};
use core::time::Duration;
use musig2::PartialSignature;
use std::{borrow::Cow, str::FromStr};
use tentacle::{
multiaddr::{MultiAddr, Protocol},
Expand Down Expand Up @@ -648,6 +650,42 @@ async fn test_saving_and_connecting_to_node() {
.await;
}

#[test]
fn test_announcement_message_serialize() {
let capacity = 42;
let priv_key: Privkey = get_test_priv_key();
let pubkey = priv_key.x_only_pub_key().serialize();
let pubkey_hash = &blake2b_256(pubkey.as_slice())[0..20];
let tx = TransactionView::new_advanced_builder()
.output(
CellOutput::new_builder()
.capacity(capacity.pack())
.lock(ScriptBuilder::default().args(pubkey_hash.pack()).build())
.build(),
)
.output_data(vec![0u8; 8].pack())
.build();
let outpoint = tx.output_pts()[0].clone();
let mut channel_announcement =
create_fake_channel_announcement_mesage(priv_key, capacity, outpoint);

channel_announcement.udt_type_script = Some(ScriptBuilder::default().build());

eprintln!("channel_announcement: {:#?}", channel_announcement);
let serialized = bincode::serialize(&channel_announcement).unwrap();
let deserialized: ChannelAnnouncement = bincode::deserialize(&serialized).unwrap();
assert_eq!(channel_announcement, deserialized);

let shutdown_info = ShutdownInfo {
close_script: ScriptBuilder::default().build(),
fee_rate: 100 as u64,
signature: Some(PartialSignature::max()),
};
let serialized = bincode::serialize(&shutdown_info).unwrap();
let deserialized: ShutdownInfo = bincode::deserialize(&serialized).unwrap();
assert_eq!(shutdown_info, deserialized);
}

#[test]
fn test_send_payment_validate_payment_hash() {
let send_command = SendPaymentCommand {
Expand Down
Loading
Loading