Browse Source

Recover wallet from 256bit string through REST endpoint

The choice of using a 256 bit string is temporary. This will be replaced
in favour of a 24 word seed phrase which will be used to create the
seed (BIP39).
update-blockstream-electrum-server-url
rishflab 3 years ago
parent
commit
0a027c8367
  1. 11
      daemon/src/lib.rs
  2. 22
      daemon/src/routes_taker.rs
  3. 1
      daemon/src/taker.rs
  4. 42
      daemon/src/wallet.rs
  5. 7
      daemon/tests/harness/mocks/wallet.rs

11
daemon/src/lib.rs

@ -332,7 +332,8 @@ where
W: xtra::Handler<wallet::BuildPartyParams>
+ xtra::Handler<wallet::Sign>
+ xtra::Handler<wallet::TryBroadcastTransaction>
+ xtra::Handler<wallet::Withdraw>,
+ xtra::Handler<wallet::Withdraw>
+ xtra::Handler<wallet::Reinitialise>,
{
#[allow(clippy::too_many_arguments)]
pub async fn new<FM, FO>(
@ -456,4 +457,12 @@ where
})
.await?
}
pub async fn reinitialise_wallet(&self, seed_words: &str) -> Result<()> {
self.wallet_actor_addr
.send(wallet::Reinitialise {
seed_words: seed_words.to_string(),
})
.await?
}
}

22
daemon/src/routes_taker.rs

@ -158,6 +158,28 @@ pub async fn post_cfd_action(
Ok(status::Accepted(None))
}
#[derive(Debug, Clone, Deserialize)]
pub struct WalletReinitialiseRequest {
pub seed_words: String,
}
#[rocket::post("/wallet/reinitialise", data = "<wallet_reinitialise_request>")]
pub async fn post_wallet_reinitialise(
wallet_reinitialise_request: Json<WalletReinitialiseRequest>,
taker: &State<Taker>,
) -> Result<status::Accepted<()>, HttpApiProblem> {
taker
.reinitialise_wallet(&wallet_reinitialise_request.seed_words)
.await
.map_err(|e| {
HttpApiProblem::new(StatusCode::INTERNAL_SERVER_ERROR)
.title("Wallet recover request failed")
.detail(e.to_string())
})?;
Ok(status::Accepted(None))
}
#[rocket::get("/alive")]
pub fn get_health_check() {}

1
daemon/src/taker.rs

@ -289,6 +289,7 @@ async fn main() -> Result<()> {
routes_taker::margin_calc,
routes_taker::post_cfd_action,
routes_taker::post_withdraw_request,
routes_taker::post_wallet_reinitialise,
],
)
.mount(

42
daemon/src/wallet.rs

@ -1,5 +1,6 @@
use crate::model::Timestamp;
use crate::model::WalletInfo;
use crate::tokio_ext::spawn_fallible;
use crate::Tasks;
use anyhow::bail;
use anyhow::Context;
@ -40,6 +41,7 @@ pub struct Actor {
used_utxos: HashSet<OutPoint>,
tasks: Tasks,
sender: watch::Sender<Option<WalletInfo>>,
electrum_rpc_url: String,
}
#[derive(thiserror::Error, Debug, Clone, Copy)]
@ -70,6 +72,7 @@ impl Actor {
tasks: Tasks::default(),
sender,
used_utxos: HashSet::default(),
electrum_rpc_url: electrum_rpc_url.to_string(),
};
Ok((actor, receiver))
@ -131,6 +134,41 @@ impl Actor {
#[xtra_productivity]
impl Actor {
pub fn handle_reinitialise(
&mut self,
msg: Reinitialise,
ctx: &mut xtra::Context<Self>,
) -> Result<()> {
let client = bdk::electrum_client::Client::new(&self.electrum_rpc_url)
.context("Failed to initialize Electrum RPC client")?;
let ext_priv_key =
ExtendedPrivKey::new_master(self.wallet.network(), msg.seed_words.as_bytes())?;
let db = bdk::database::MemoryDatabase::new();
let wallet = bdk::Wallet::new(
bdk::template::Bip84(ext_priv_key, KeychainKind::External),
Some(bdk::template::Bip84(ext_priv_key, KeychainKind::Internal)),
ext_priv_key.network,
db,
ElectrumBlockchain::from(client),
)?;
self.wallet = wallet;
self.used_utxos.clear();
let this = ctx.address().expect("self to be alive");
spawn_fallible::<_, anyhow::Error>(async move {
let _ = this.send(Sync).await?;
Ok(())
});
Ok(())
}
pub fn handle_sync(&mut self, _msg: Sync) -> Result<()> {
let wallet_info_update = match self.sync_internal() {
Ok(wallet_info) => Some(wallet_info),
@ -304,6 +342,10 @@ pub struct BuildPartyParams {
/// Private message to trigger a sync.
struct Sync;
pub struct Reinitialise {
pub seed_words: String,
}
pub struct Sign {
pub psbt: PartiallySignedTransaction,
}

7
daemon/tests/harness/mocks/wallet.rs

@ -41,6 +41,9 @@ impl WalletActor {
async fn handle(&mut self, msg: wallet::Withdraw) -> Result<Txid> {
self.mock.lock().await.withdraw(msg)
}
async fn handle(&mut self, msg: wallet::Reinitialise) -> Result<()> {
self.mock.lock().await.reinitialise(msg)
}
}
#[automock]
@ -60,6 +63,10 @@ pub trait Wallet {
fn withdraw(&mut self, _msg: wallet::Withdraw) -> Result<Txid> {
unreachable!("mockall will reimplement this method")
}
fn reinitialise(&mut self, _msg: wallet::Reinitialise) -> Result<()> {
unreachable!("mockall will reimplement this method")
}
}
#[allow(dead_code)]

Loading…
Cancel
Save