Skip to content
Open
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
938 changes: 858 additions & 80 deletions bark-cpp/Cargo.lock

Large diffs are not rendered by default.

10 changes: 8 additions & 2 deletions bark-cpp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ version = "0.1.0"
edition = "2021"

[dependencies]
bark-client = { git = "https://codeberg.org/ark-bitcoin/bark.git", tag = "bark-0.0.0-alpha.17", features = [
# bark-client = { git = "https://codeberg.org/ark-bitcoin/bark.git", tag = "bark-0.0.0-alpha.17", features = [
# "tls-webpki-roots",
# ], default-features = false }
bark-client = { path = "/Users/niteshchowdharybalusu/Documents/bark/bark", features = [
"tls-webpki-roots",
], default-features = false }

bark-bitcoin-ext = { git = "https://codeberg.org/ark-bitcoin/bark.git", tag = "bark-0.0.0-alpha.17", default-features = false }
bark-bitcoin-ext = { path = "/Users/niteshchowdharybalusu/Documents/bark/bitcoin-ext", default-features = false }

bdk_wallet = { version = "2.0.0", features = [ "rusqlite" ]}

tokio = { version = "1", default-features = false, features = [
"rt-multi-thread",
Expand All @@ -26,6 +31,7 @@ tonic = { version = "0.13.1", default-features = false, features = [
] }
serde_json = "1.0.140"
cxx = "1.0"
libsql = "0.9.17"

[build-dependencies]
cxx-build = "1.0"
Expand Down
6 changes: 4 additions & 2 deletions bark-cpp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,16 @@ use bark::lnurllib::lightning_address::LightningAddress;
use bark::vtxo_selection::VtxoFilter;
use bark::Config;
use bark::Offboard;
use bark::SqliteClient;
use bark::UtxoInfo;
use bark::Wallet;
use tokio::runtime::Runtime;
use tokio::sync::Mutex;
mod cxx;
mod libsql;
mod utils;

pub use libsql::LibsqlClient;

use bip39::Mnemonic;
use logger::log::{debug, info, warn};
use std::path::Path;
Expand Down Expand Up @@ -171,7 +173,7 @@ pub async fn offchain_balance() -> anyhow::Result<Amount> {
pub async fn open_wallet(datadir: &Path, mnemonic: Mnemonic) -> anyhow::Result<Wallet> {
debug!("Opening bark wallet in {}", datadir.display());

let db = SqliteClient::open(datadir.join(DB_FILE))?;
let db = LibsqlClient::open(datadir.join(DB_FILE))?;

Wallet::open(&mnemonic, db).await
}
Expand Down
30 changes: 30 additions & 0 deletions bark-cpp/src/libsql/convert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use bark::ark::bitcoin::Amount;
use bark::movement::{Movement, MovementRecipient, VtxoSubset};
use bark::persist::OffchainBoard;
use libsql::Row;

pub(crate) fn row_to_movement(row: &Row) -> anyhow::Result<Movement> {
let fees: Amount = Amount::from_sat(row.get(2)?);

let spends = serde_json::from_str::<Vec<VtxoSubset>>(&row.get::<String>(3)?)?;
let receives = serde_json::from_str::<Vec<VtxoSubset>>(&row.get::<String>(4)?)?;
let recipients = serde_json::from_str::<Vec<MovementRecipient>>(&row.get::<String>(5)?)?;

Ok(Movement {
id: row.get(0)?,
fees,
spends,
receives,
recipients,
created_at: row.get(1)?,
})
}

pub(crate) fn row_to_offchain_board(row: &Row) -> anyhow::Result<OffchainBoard> {
let raw_payment = row.get::<Vec<u8>>(2)?;
Ok(OffchainBoard {
payment_hash: row.get(0)?,
payment_preimage: row.get(1)?,
payment: serde_json::from_slice(&raw_payment)?,
})
}
92 changes: 92 additions & 0 deletions bark-cpp/src/libsql/migrations/m0001_initial_version.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use anyhow::Context;

use libsql::Transaction;

use super::Migration;

pub struct Migration0001 {}

impl Migration for Migration0001 {
fn name(&self) -> &str {
"Create initial tables"
}

fn to_version(&self) -> i64 {
1
}

fn do_migration<'a>(
&self,
conn: &'a Transaction,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = anyhow::Result<()>> + Send + 'a>> {
let summary = self.summary();
Box::pin(async move {
let queries = [
"CREATE TABLE IF NOT EXISTS bark_vtxo (
id TEXT PRIMARY KEY,
expiry_height INTEGER,
amount_sat INTEGER,
raw_vtxo BLOB,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now'))
);",
"CREATE TABLE IF NOT EXISTS bark_vtxo_key (
public_key TEXT NOT NULL PRIMARY KEY,
keychain INTEGER NOT NULL,
idx INTEGER NOT NULL,
-- each index must be unique in a keychain
UNIQUE (keychain, idx)
);",
"CREATE TABLE IF NOT EXISTS bark_vtxo_state (
id INTEGER PRIMARY KEY,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),
vtxo_id TEXT REFERENCES bark_vtxo(id),
state_kind TEXT NOT NULL,
state BLOB NOT NULL
);",
"CREATE TABLE IF NOT EXISTS bark_ark_sync (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sync_height INTEGER,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now'))
);",
"CREATE TABLE IF NOT EXISTS bark_exit (
id INTEGER PRIMARY KEY AUTOINCREMENT,
exit BLOB
)",
"CREATE VIEW IF NOT EXISTS most_recent_vtxo_state
(id, last_updated_at, vtxo_id, state_kind, state)
AS
WITH most_recent AS (SELECT MAX(id) as id FROM bark_vtxo_state GROUP BY vtxo_id)
SELECT
most_recent.id,
vs.created_at,
vs.vtxo_id,
vs.state_kind,
vs.state
FROM most_recent JOIN bark_vtxo_state as vs
ON vs.id = most_recent.id;
",
"CREATE VIEW IF NOT EXISTS vtxo_view
AS SELECT
v.id,
v.expiry_height,
v.amount_sat,
vs.state_kind,
vs.state,
v.raw_vtxo,
v.created_at,
vs.last_updated_at
FROM bark_vtxo as v
JOIN most_recent_vtxo_state as vs
ON v.id = vs.vtxo_id;
",
];

for query in queries {
conn.execute(query, ())
.await
.with_context(|| format!("Failed to execute migration: {}", summary))?;
}
Ok(())
})
}
}
54 changes: 54 additions & 0 deletions bark-cpp/src/libsql/migrations/m0002_config.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
use anyhow::Context;

use libsql::Transaction;

use super::Migration;

pub struct Migration0002 {}

impl Migration for Migration0002 {
fn name(&self) -> &str {
"Create wallet meta tables"
}

fn to_version(&self) -> i64 {
2
}

fn do_migration<'a>(
&self,
conn: &'a Transaction,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = anyhow::Result<()>> + Send + 'a>> {
let summary = self.summary();
Box::pin(async move {
let queries = [
"CREATE TABLE IF NOT EXISTS bark_config (
id TEXT PRIMARY KEY,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),

asp_address TEXT NOT NULL,
esplora_address ,
bitcoind_address ,
bitcoind_cookiefile ,
bitcoind_user ,
bitcoind_pass ,
vtxo_refresh_threshold INTEGER NOT NULL
);",
"CREATE TABLE IF NOT EXISTS bark_properties (
id TEXT PRIMARY KEY,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now')),

network TEXT NOT NULL,
fingerprint TEXT NOT NULL
);",
];

for query in queries {
conn.execute(query, ())
.await
.with_context(|| format!("Failed to execute migration: {}", summary))?;
}
Ok(())
})
}
}
72 changes: 72 additions & 0 deletions bark-cpp/src/libsql/migrations/m0003_payment_history.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use anyhow::Context;

use libsql::Transaction;

use super::Migration;

pub struct Migration0003 {}

impl Migration for Migration0003 {
fn name(&self) -> &str {
"Create tables for movement history"
}

fn to_version(&self) -> i64 {
3
}

fn do_migration<'a>(
&self,
conn: &'a Transaction,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = anyhow::Result<()>> + Send + 'a>> {
let summary = self.summary();
Box::pin(async move {
let queries = [
"CREATE TABLE IF NOT EXISTS bark_movement (
id INTEGER PRIMARY KEY,
fees_sat INTEGER NOT NULL,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now'))
);",
"CREATE TABLE IF NOT EXISTS bark_recipient (
id INTEGER PRIMARY KEY,
movement REFERENCES bark_movement(id),
recipient TEXT NOT NULL,
amount_sat INTEGER NOT NULL
);",
"ALTER TABLE bark_vtxo ADD received_in TEXT NOT NULL REFERENCES bark_movement(id);",
"ALTER TABLE bark_vtxo ADD spent_in TEXT REFERENCES bark_movement(id);",
"CREATE VIEW IF NOT EXISTS movement_view AS
SELECT
*,
(
SELECT JSON_GROUP_ARRAY(JSON_OBJECT(
'id', bark_vtxo.id,
'amount_sat', bark_vtxo.amount_sat
)) FROM bark_vtxo WHERE bark_vtxo.spent_in = bark_movement.id
) AS spends,
(
SELECT JSON_GROUP_ARRAY(JSON_OBJECT(
'id', bark_vtxo.id,
'amount_sat', bark_vtxo.amount_sat
)) FROM bark_vtxo WHERE bark_vtxo.received_in = bark_movement.id
) AS receives,
(
SELECT JSON_GROUP_ARRAY(JSON_OBJECT(
'recipient', bark_recipient.recipient,
'amount_sat', bark_recipient.amount_sat
)) FROM bark_recipient WHERE bark_recipient.movement = bark_movement.id
) AS recipients
FROM bark_movement
;",
];

for query in queries {
conn.execute(query, ())
.await
.with_context(|| format!("Failed to execute migration: {}", summary))?;
}

Ok(())
})
}
}
33 changes: 33 additions & 0 deletions bark-cpp/src/libsql/migrations/m0004_unregistered_board.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use anyhow::Context;

use libsql::Transaction;

use super::Migration;

pub struct Migration0004 {}

impl Migration for Migration0004 {
fn name(&self) -> &str {
"Updating the VtxoState"
}

fn to_version(&self) -> i64 {
4
}

fn do_migration<'a>(
&self,
conn: &'a Transaction,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = anyhow::Result<()>> + Send + 'a>> {
let summary = self.summary();
Box::pin(async move {
// Rename Ready to Spendable
let query = "UPDATE bark_vtxo_state SET state = 'Spendable' WHERE state = 'Ready'";

conn.execute(query, ())
.await
.with_context(|| format!("Failed to execute migration: {}", summary))?;
Ok(())
})
}
}
38 changes: 38 additions & 0 deletions bark-cpp/src/libsql/migrations/m0005_offchain_boards.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use anyhow::Context;

use libsql::Transaction;

use super::Migration;

pub struct Migration0005 {}

impl Migration for Migration0005 {
fn name(&self) -> &str {
"Add table to support offchain boards with HTLCs"
}

fn to_version(&self) -> i64 {
5
}

fn do_migration<'a>(
&self,
conn: &'a Transaction,
) -> std::pin::Pin<Box<dyn std::future::Future<Output = anyhow::Result<()>> + Send + 'a>> {
let summary = self.summary();
Box::pin(async move {
// Rename Ready to Spendable
let query = "CREATE TABLE bark_offchain_board (
payment_hash BLOB NOT NULL PRIMARY KEY,
preimage BLOB NOT NULL UNIQUE,
serialised_payment BLOB,
created_at DATETIME NOT NULL DEFAULT (strftime('%Y-%m-%d %H:%M:%f', 'now'))
)";

conn.execute(query, ())
.await
.with_context(|| format!("Failed to execute migration: {}", summary))?;
Ok(())
})
}
}
Loading
Loading