Merge pull request #3 from darkrenaissance/bitcoin

Cashier with bitcoin
This commit is contained in:
zkjanus
2021-07-21 11:12:48 -04:00
committed by GitHub
15 changed files with 740 additions and 8 deletions

43
Cargo.lock generated
View File

@@ -401,6 +401,12 @@ version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bech32"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2dabbe35f96fb9507f7330793dc490461b2962659ac5d427181e451a623751d1"
[[package]]
name = "bellman"
version = "0.8.1"
@@ -446,6 +452,23 @@ dependencies = [
"shlex",
]
[[package]]
name = "bitcoin"
version = "0.26.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6742ec672d3f12506f4ac5c0d853926ff1f94e675f60ffd3224039972bf663f1"
dependencies = [
"bech32",
"bitcoin_hashes",
"secp256k1",
]
[[package]]
name = "bitcoin_hashes"
version = "0.9.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ce18265ec2324ad075345d5814fbeed4f41f0a660055dc78840b74d19b874b1"
[[package]]
name = "bitflags"
version = "1.2.1"
@@ -961,6 +984,7 @@ dependencies = [
"async-trait",
"bellman",
"bimap",
"bitcoin",
"bitvec",
"blake2b_simd",
"blake2s_simd",
@@ -992,6 +1016,7 @@ dependencies = [
"regex",
"rocksdb",
"rusqlite",
"secp256k1",
"serde",
"serde_json",
"sha2",
@@ -2426,6 +2451,24 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "secp256k1"
version = "0.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97d03ceae636d0fed5bae6a7f4f664354c5f4fcedf6eef053fef17e49f837d0a"
dependencies = [
"secp256k1-sys",
]
[[package]]
name = "secp256k1-sys"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "827cb7cce42533829c792fc51b82fbf18b125b45a702ef2c8be77fce65463a7b"
dependencies = [
"cc",
]
[[package]]
name = "security-framework"
version = "2.3.1"

View File

@@ -15,7 +15,7 @@ bls12_381 = "0.3.1"
jubjub = "0.5.1"
zcash_primitives = "0.5.0"
zcash_proofs = "0.5.0"
zcash_proofs = "0.5.0"
# zcash_primitives = { git = "https://github.com/zcash/librustzcash" }
#zcash_proofs = { git = "https://github.com/zcash/librustzcash" }
#zcash_proofs = { git = "https://github.com/narodnik/librustzcash" }
@@ -77,6 +77,9 @@ bytes = "1.0.1"
rocksdb = "0.16.0"
dirs = "3.0.2"
bitcoin = "0.26.2"
secp256k1 = "0.20.3"
[dependencies.rusqlite]
version = "0.25.1"
features = ["bundled", "sqlcipher"]
@@ -109,13 +112,17 @@ path = "src/bin/tx.rs"
name = "gatewayd"
path = "src/bin/gatewayd.rs"
[[bin]]
name = "cashierd"
path = "src/bin/cashierd.rs"
[[bin]]
name = "darkfid"
path = "src/bin/darkfid.rs"
[[bin]]
name = "drk"
path = "src/bin/drk.rs"
[profile.release]
debug = 1

101
src/bin/cashierd.rs Normal file
View File

@@ -0,0 +1,101 @@
use std::net::SocketAddr;
use std::str;
use std::sync::Arc;
use std::fs::OpenOptions;
use std::io::Read;
use std::{fs, path::Path, path::PathBuf};
use toml;
use drk::blockchain::{rocks::columns, Rocks, RocksColumn};
use drk::cli::{CashierdCli, CashierdConfig};
use drk::wallet::{WalletDb, WalletPtr};
use drk::service::CashierService;
use drk::util::join_config_path;
use drk::Result;
use async_executor::Executor;
use easy_parallel::Parallel;
fn setup_addr(address: Option<SocketAddr>, default: SocketAddr) -> SocketAddr {
match address {
Some(addr) => addr,
None => default,
}
}
async fn start(executor: Arc<Executor<'_>>, config: Arc<&CashierdConfig>) -> Result<()> {
let accept_addr: SocketAddr = config.accept_url.parse()?;
let database_path = config.database_path.clone();
let database_path = join_config_path(&PathBuf::from(database_path))?;
let rocks = Rocks::new(&database_path)?;
let rocks_cashierstore_column = RocksColumn::<columns::CashierKeys>::new(rocks);
// Use pw: PASSWORD for now
//let cashier_wallet = Arc::new(WalletDB::new("cashier.db", "PASSWORD")?);
let wallet = Arc::new(WalletDb::new("cashier.db", config.password.clone())?);
let cashier = CashierService::new(accept_addr, rocks_cashierstore_column, wallet)?;
cashier.start(executor.clone()).await?;
Ok(())
}
fn main() -> Result<()> {
use simplelog::*;
let ex = Arc::new(Executor::new());
let (signal, shutdown) = async_channel::unbounded::<()>();
let path = join_config_path(&PathBuf::from("cashierd.toml")).unwrap();
let config: CashierdConfig = if Path::new(&path).exists() {
CashierdConfig::load(path)?
} else {
CashierdConfig::load_default(path)?
};
let config_ptr = Arc::new(&config);
let options = CashierdCli::load()?;
let logger_config = ConfigBuilder::new().set_time_format_str("%T%.6f").build();
let debug_level = if options.verbose {
LevelFilter::Debug
} else {
LevelFilter::Off
};
let log_path = config.log_path.clone();
CombinedLogger::init(vec![
TermLogger::new(debug_level, logger_config, TerminalMode::Mixed).unwrap(),
WriteLogger::new(
LevelFilter::Debug,
Config::default(),
std::fs::File::create(log_path).unwrap(),
),
])
.unwrap();
let ex2 = ex.clone();
let (_, result) = Parallel::new()
// Run four executor threads.
.each(0..3, |_| smol::future::block_on(ex.run(shutdown.recv())))
// Run the main future on the current thread.
.finish(|| {
smol::future::block_on(async move {
start(ex2, config_ptr).await?;
drop(signal);
Ok::<(), drk::Error>(())
})
});
result
}

View File

@@ -0,0 +1,44 @@
use crate::serial::{Decodable, Encodable};
use crate::Result;
#[derive(Clone, Debug)]
pub struct CashierKeypair {
zk_public: jubjub::SubgroupPoint,
payload: Vec<u8>,
}
impl CashierKeypair {
pub fn new(zk_public: jubjub::SubgroupPoint, payload: Vec<u8>) -> Self {
CashierKeypair { zk_public, payload }
}
pub fn set_index(&mut self, index: jubjub::SubgroupPoint) {
self.zk_public = index;
}
pub fn get_index(&self) -> jubjub::SubgroupPoint {
self.zk_public
}
pub fn get_payload(&self) -> Vec<u8> {
self.payload.clone()
}
}
impl Encodable for CashierKeypair {
fn encode<S: std::io::Write>(&self, mut s: S) -> Result<usize> {
let mut len = 0;
len += self.zk_public.encode(&mut s)?;
len += self.payload.encode(&mut s)?;
Ok(len)
}
}
impl Decodable for CashierKeypair {
fn decode<D: std::io::Read>(mut d: D) -> Result<Self> {
Ok(Self {
zk_public: Decodable::decode(&mut d)?,
payload: Decodable::decode(&mut d)?,
})
}
}

View File

@@ -0,0 +1,55 @@
use std::sync::Arc;
use crate::serial::{deserialize, serialize};
use crate::Result;
use super::rocks::{columns, IteratorMode, RocksColumn};
use super::cashier_keypair::CashierKeypair;
pub struct CashierStore {
rocks: RocksColumn<columns::CashierKeys>,
}
impl CashierStore {
pub fn new(rocks: RocksColumn<columns::CashierKeys>) -> Result<Arc<Self>> {
Ok(Arc::new(CashierStore { rocks }))
}
pub fn get(&self, key: jubjub::SubgroupPoint) -> Result<Option<Vec<u8>>> {
let value = self.rocks.get(key)?;
Ok(value)
}
pub fn put(&self, keypair: CashierKeypair) -> Result<Option<jubjub::SubgroupPoint>> {
let index = keypair.get_index();
let check = self.get(index);
match self.get(index) {
Ok(_v) => Ok(None),
Err(_e) => {
self.rocks.put(index.clone(), keypair)?;
Ok(Some(index))
},
}
}
pub fn get_value_deserialized(&self, key: Vec<u8>) -> Result<Option<CashierKeypair>> {
self.rocks.get_value_deserialized::<CashierKeypair>(key)
}
// Fix this
// pub fn get_last_index(&self) -> Result<jubjub::SubgroupPoint> {
// let last_index = self.rocks.iterator(IteratorMode::End)?.next();
// match last_index {
// Some((index, _)) => Ok(deserialize(&index)?),
// None => Ok()
// }
// }
pub fn get_last_index_as_bytes(&self) -> Result<Vec<u8>> {
let last_index = self.rocks.iterator(IteratorMode::End)?.next();
match last_index {
Some((index, _)) => Ok(index.to_vec()),
None => Ok(serialize::<u64>(&0)),
}
}
}

View File

@@ -1,7 +1,11 @@
pub mod rocks;
pub mod slab;
pub mod slabstore;
pub mod cashier_keypair;
pub mod cashierstore;
pub use rocks::{Rocks, RocksColumn};
pub use slab::Slab;
pub use slabstore::SlabStore;
pub use cashier_keypair::CashierKeypair;
pub use cashierstore::CashierStore;

View File

@@ -20,6 +20,7 @@ pub mod columns {
pub struct Slabs;
pub struct Nullifiers;
pub struct MerkleRoots;
pub struct CashierKeys;
}
impl Column for columns::Slabs {
@@ -33,7 +34,9 @@ impl Column for columns::Nullifiers {
impl Column for columns::MerkleRoots {
const NAME: &'static str = "merkleroots";
}
impl Column for columns::CashierKeys {
const NAME: &'static str = "cashierkeys";
}
pub struct Rocks {
db: DB,
}
@@ -51,10 +54,12 @@ impl Rocks {
// nullifiers column family
let nullifiers_cf = ColumnFamilyDescriptor::new(columns::Nullifiers::NAME, cf_opts.clone());
// merkleroots column family
let merkleroots_cf = ColumnFamilyDescriptor::new(columns::MerkleRoots::NAME, cf_opts);
let merkleroots_cf = ColumnFamilyDescriptor::new(columns::MerkleRoots::NAME, cf_opts.clone());
// cashierkeypair column family
let cashierkeys_cf = ColumnFamilyDescriptor::new(columns::CashierKeys::NAME, cf_opts);
// column families
let cfs = vec![default_cf, slab_cf, nullifiers_cf, merkleroots_cf];
let cfs = vec![default_cf, slab_cf, nullifiers_cf, merkleroots_cf, cashierkeys_cf];
// database options
let mut opt = Options::default();

23
src/cli/cashierd_cli.rs Normal file
View File

@@ -0,0 +1,23 @@
use crate::Result;
pub struct CashierdCli {
pub verbose: bool,
}
impl CashierdCli {
pub fn load() -> Result<Self> {
let app = clap_app!(dfi =>
(version: "0.1.0")
(author: "Amir Taaki <amir@dyne.org>")
(about: "run service daemon")
(@arg VERBOSE: -v --verbose "Increase verbosity")
)
.get_matches();
let verbose = app.is_present("VERBOSE");
Ok(Self {
verbose,
})
}
}

View File

@@ -160,3 +160,48 @@ impl Default for GatewaydConfig {
}
}
}
#[derive(Serialize, Deserialize, Debug)]
pub struct CashierdConfig {
#[serde(default)]
#[serde(rename = "connect_url")]
pub accept_url: String,
#[serde(default)]
#[serde(rename = "database_path")]
pub database_path: String,
#[serde(default)]
#[serde(rename = "log_path")]
pub log_path: String,
#[serde(default)]
#[serde(rename = "password")]
pub password: String,
}
impl CashierdConfig {
pub fn load(path: PathBuf) -> Result<Self> {
let toml = fs::read(&path)?;
let str_buff = str::from_utf8(&toml)?;
let config: Self = toml::from_str(str_buff)?;
Ok(config)
}
pub fn load_default(path: PathBuf) -> Result<Self> {
let toml = Self::default();
let config_file = toml::to_string(&toml)?;
fs::write(&path, &config_file)?;
let config = Self::load(path)?;
Ok(config)
}
}
impl Default for CashierdConfig {
fn default() -> Self {
let accept_url = String::from("127.0.0.1:7777");
let database_path = String::from("cashierd.db");
let log_path = String::from("/tmp/cashierd.log");
let password = String::new();
Self { accept_url, database_path, log_path, password }
}
}

View File

@@ -0,0 +1,146 @@
//use crate::serial::{deserialize, serialize, Decodable, Encodable};
//use toml::{map::Map, Value};
use crate::util::join_config_path;
//use crate::Result;
use serde::{Deserialize, Serialize};
//use log::*;
use std::{fs::OpenOptions, io::prelude::*, path::PathBuf};
//pub trait ClientConfig: Default + Deserialize {
// fn load(path: PathBuf) -> Result<Self> {
// let path = join_config_path(&path)?;
// let mut file = OpenOptions::new()
// .read(true)
// .write(true)
// .create(true)
// .open(path)?;
//
// //let mut toml_map = Map::new();
// let mut buffer = String::new();
// file.read_to_string(&mut buffer)?;
// //let buffer: &'static str = buffer;
//
// //let tomlstring = toml::to_string(&file).expect("Could not encode TTOML value");
// if !buffer.is_empty() {
// let config: Self = toml::from_str(&buffer)?;
// //let config = toml::to_string(&buffer).unwrap();
// //let config: Self = deserialize(&buffer)?;
// //Ok(config)
// Ok(config)
// } else {
// Ok(Self::default())
// }
// }
// fn save(&self, path: PathBuf) -> Result<()> {
// //let path = join_config_path(&path)?;
// //let mut file = OpenOptions::new().write(true).create(true).open(&path)?;
// //let serialized = serialize(self);
// //file.write_all(&serialized)?;
// Ok(())
// }
//}
//
//impl ClientConfig for DrkConfig {}
//impl ClientConfig for DarkfidConfig {}
#[derive(Serialize, Default, Deserialize, Debug)]
pub struct DrkConfig {
#[serde(rename = "rpc_url")]
pub rpc_url: String,
#[serde(rename = "log_path")]
pub log_path: String,
}
#[derive(Serialize, Default, Deserialize, Debug)]
pub struct DarkfidConfig {
#[serde(rename = "connect_url")]
pub connect_url: String,
#[serde(rename = "subscriber_url")]
pub subscriber_url: String,
#[serde(rename = "rpc_url")]
pub rpc_url: String,
#[serde(rename = "database_path")]
pub database_path: String,
#[serde(rename = "log_path")]
pub log_path: String,
#[serde(rename = "password")]
pub password: String,
}
#[derive(Serialize, Default, Deserialize, Debug)]
pub struct GatewaydConfig {
#[serde(rename = "connect_url")]
pub accept_url: String,
#[serde(rename = "subscriber_url")]
pub publisher_url: String,
#[serde(rename = "database_path")]
pub database_path: String,
#[serde(rename = "log_path")]
pub log_path: String,
}
#[derive(Serialize, Default, Deserialize, Debug)]
pub struct CashierdConfig {
#[serde(rename = "connect_url")]
pub accept_url: String,
#[serde(rename = "database_path")]
pub database_path: String,
#[serde(rename = "log_path")]
pub log_path: String,
}
//impl Default for DrkCliConfig {
// // default toml file
// fn default() -> Self {
// let rpc_url = String::from("http://127.0.0.1:8000");
// let log_path = String::from("/tmp/drk_cli.log");
// Self {
// rpc_url,
// log_path,
// }
// }
//}
//impl Default for DarkfidCliConfig {
// // create default config file
// fn default() -> Self {
// //toml::toml! {
// // connect-url = "127.0.0.1:3333"
// //};
// let connect_url = String::from("127.0.0.1:3333");
// let subscriber_url = String::from("127.0.0.1:4444");
// let rpc_url = String::from("127.0.0.1:8000");
//
// let database_path = String::from("database_client.db");
// let database_path = join_config_path(&PathBuf::from(database_path))
// .expect("error during join database_path to config path");
// let database_path = String::from(
// database_path
// .to_str()
// .expect("error convert Path to String"),
// );
// let log_path = String::from("/tmp/darkfid_service_daemon.log");
//
// let password = String::new();
// Self {
// connect_url,
// subscriber_url,
// rpc_url,
// database_path,
// log_path,
// password,
// }
// }
//}

View File

@@ -2,9 +2,11 @@ pub mod cli_config;
pub mod darkfid_cli;
pub mod drk_cli;
pub mod gatewayd_cli;
pub mod cashierd_cli;
pub use cli_config::{DarkfidConfig, DrkConfig, GatewaydConfig};
pub use cli_config::{DarkfidConfig, DrkConfig, CashierdConfig, GatewaydConfig};
pub use darkfid_cli::DarkfidCli;
pub use drk_cli::DrkCli;
pub use drk_cli::Transfer;
pub use gatewayd_cli::GatewaydCli;
pub use cashierd_cli::CashierdCli;

View File

@@ -39,7 +39,7 @@ impl RpcAdapter {
pub fn cash_key_gen(&self) -> Result<()> {
debug!(target: "adapter", "key_gen() [START]");
let (public, private) = self.wallet.key_gen();
let (public, private) = self.wallet.cash_key_gen();
self.wallet.put_keypair(public, private)?;
Ok(())
}

View File

@@ -0,0 +1,254 @@
use rand::{thread_rng, Rng};
use rand::distributions::Alphanumeric;
use secp256k1::key::{SecretKey, PublicKey};
use bitcoin::util::ecdsa::{PrivateKey, PublicKey as BitcoinPubKey};
use bitcoin::util::{address::Payload, address::Address};
// Use p2pkh for 1st iteration
use bitcoin::hash_types::PubkeyHash;
use bitcoin::network::constants::Network;
use super::reqrep::{PeerId, RepProtocol, Reply, ReqProtocol, Request};
use crate::blockchain::{rocks::columns, RocksColumn, CashierKeypair, CashierStore};
use crate::{serial::deserialize, serial::serialize, Error, Result};
use crate::wallet::{WalletDb, WalletPtr};
use std::net::SocketAddr;
use async_std::sync::Arc;
use async_executor::Executor;
use log::*;
#[repr(u8)]
enum CashierError {
NoError,
UpdateIndex,
}
#[repr(u8)]
enum CashierCommand {
GetDBTC,
GetBTC,
}
pub struct BitcoinKeys {
secret_key: SecretKey,
bitcoin_private_key: PrivateKey,
pub bitcoin_public_key: BitcoinPubKey,
pub pub_address: Address,
}
impl BitcoinKeys {
pub fn new(
) -> Result<BitcoinKeys> {
let context = secp256k1::Secp256k1::new();
// Probably not good enough for release
let rand: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(32)
.map(char::from)
.collect();
let rand_hex = hex::encode(rand);
// Generate simple byte array from rand
let data_slice: &[u8] = rand_hex.as_bytes();
let secret_key = SecretKey::from_slice(&hex::decode(data_slice).unwrap()).unwrap();
//let public_key = PublicKey::from_secret_key(&context, &secret_key);
// Use Testnet
let bitcoin_private_key = PrivateKey::new(secret_key, Network::Testnet);
let bitcoin_public_key = BitcoinPubKey::from_private_key(&context, &bitcoin_private_key);
let pub_address = Address::p2pkh(&bitcoin_public_key, Network::Testnet);
Ok(Self {
secret_key,
bitcoin_private_key,
bitcoin_public_key,
pub_address,
})
}
pub fn get_deposit_address(&self) -> &Address {
&self.pub_address
}
}
pub struct CashierService {
addr: SocketAddr,
cashierstore: Arc<CashierStore>,
wallet: Arc<WalletDb>,
}
impl CashierService {
pub fn new(
addr: SocketAddr,
rocks: RocksColumn<columns::CashierKeys>,
wallet: Arc<WalletDb>,
)-> Result<Arc<CashierService>> {
let cashierstore = CashierStore::new(rocks)?;
Ok(Arc::new(CashierService {
cashierstore,
addr,
wallet,
}))
}
pub async fn start(self: Arc<Self>, executor: Arc<Executor<'_>>) -> Result<()> {
let service_name = String::from("CASHIER DAEMON");
let mut protocol = RepProtocol::new(self.addr.clone(), service_name.clone());
let (send, recv) = protocol.start().await?;
let handle_request_task = executor.spawn(self.handle_request_loop(
send.clone(),
recv.clone(),
executor.clone(),
));
protocol.run(executor.clone()).await?;
let _ = handle_request_task.cancel().await;
Ok(())
}
async fn handle_request_loop(
self: Arc<Self>,
send_queue: async_channel::Sender<(PeerId, Reply)>,
recv_queue: async_channel::Receiver<(PeerId, Request)>,
executor: Arc<Executor<'_>>,
) -> Result<()> {
loop {
match recv_queue.recv().await {
Ok(msg) => {
let cashierstore = self.cashierstore.clone();
let _ = executor
.spawn(Self::handle_request(
msg,
cashierstore,
send_queue.clone(),
))
.detach();
}
Err(_) => {
break;
}
}
}
Ok(())
}
async fn handle_request(
msg: (PeerId, Request),
cashierstore: Arc<CashierStore>,
send_queue: async_channel::Sender<(PeerId, Reply)>,
) -> Result<()> {
let request = msg.1;
let peer = msg.0;
match request.get_command() {
0 => {
// Exchange zk_pubkey for bitcoin address
let zkpub = request.get_payload();
// Generate bitcoin Address
let btc_keys = BitcoinKeys::new().unwrap();
let deposit_address = btc_keys.get_deposit_address();
let mut reply = Reply::from(&request, CashierError::NoError as u32, vec![]);
// if let None = error {
// reply.set_error(CashierError::UpdateIndex as u32);
// }
// send reply
send_queue.send((peer, reply)).await?;
}
1 => {
// Withdraw
}
_ => {
return Err(Error::ServicesError("received wrong command"));
}
}
Ok(())
}
}
pub struct CashierClient {
protocol: ReqProtocol,
cashierstore: Arc<CashierStore>,
}
impl CashierClient {
pub fn new(addr: SocketAddr, rocks: RocksColumn<columns::CashierKeys>) -> Result<Self> {
let protocol = ReqProtocol::new(addr, String::from("CASHIER CLIENT"));
let cashierstore = CashierStore::new(rocks)?;
Ok(CashierClient {
protocol,
cashierstore,
})
}
pub async fn start(&mut self) -> Result<()> {
self.protocol.start().await?;
//self.sync().await?;
Ok(())
}
pub async fn get_keys(&mut self, index: jubjub::SubgroupPoint) -> Result<Option<CashierKeypair>> {
let rep = self
.protocol
.request(
CashierCommand::GetDBTC as u8,
serialize(&index),
&handle_error,
)
.await?;
if let Some(keys) = rep {
let keys: CashierKeypair = deserialize(&keys)?;
//self.gateway_slabs_sub_s.send(slab.clone()).await?;
self.cashierstore.put(keys.clone())?;
return Ok(Some(keys));
}
Ok(None)
}
// pub async fn put_keys(&mut self, mut keys: CashierKeys) -> Result<()> {
// loop {
// let last_index = self.sync().await?;
// //keys.set_index(last_index + 1);
// let keys = serialize(&keys);
// let rep = self
// .protocol
// .request(CashierCommand::PutSlab as u8, slab.clone(), &handle_error)
// .await?;
// if let Some(_) = rep {
// break;
// }
// }
// Ok(())
// }
pub fn get_cashierstore(&self) -> Arc<CashierStore> {
self.cashierstore.clone()
}
}
fn handle_error(status_code: u32) {
match status_code {
1 => {
warn!("Reply has an Error: Index is not updated");
}
2 => {
warn!("Reply has an Error: Index Not Exist");
}
_ => {}
}
}

View File

@@ -1,4 +1,7 @@
pub mod gateway;
pub mod reqrep;
pub mod bitcoin_bridge;
pub use gateway::{GatewayClient, GatewayService, GatewaySlabsSubscriber};
pub use bitcoin_bridge::{BitcoinKeys, CashierService, CashierClient};

View File

@@ -68,7 +68,7 @@ impl WalletDb {
pub fn init_cashier_db(&self) -> Result<()> {
let conn = Connection::open(&self.path)?;
debug!(target: "walletdb", "OPENED CONNECTION AT PATH {:?}", self.path);
debug!(target: "cashierdb", "OPENED CONNECTION AT PATH {:?}", self.path);
let contents = include_str!("../../res/schema.sql");
conn.execute_batch(&contents)?;
Ok(())