Skip to content

Commit

Permalink
feat: safe watcher migration (#326)
Browse files Browse the repository at this point in the history
  • Loading branch information
crisdut authored Aug 8, 2023
1 parent ea010b4 commit 656de08
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 6 deletions.
38 changes: 33 additions & 5 deletions src/rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use bitcoin_scripts::address::AddressNetwork;
use garde::Validate;
use miniscript_crate::DescriptorPublicKey;
use rand::{rngs::StdRng, Rng, SeedableRng};
use rgb::TerminalPath;
use rgb::{RgbDescr, TerminalPath};
use rgbstd::{
containers::BindleContent,
contract::ContractId,
Expand Down Expand Up @@ -1480,6 +1480,14 @@ pub async fn import(sk: &str, request: ImportRequest) -> Result<ContractResponse
pub enum WatcherError {
/// Some request data is missing. {0}
Validation(String),
/// Occurs an error in parse descriptor step. {0}
WrongDesc(String),
/// Occurs an error in parse xpub step. {0}
WrongXPub(String),
/// Occurs an error in create watcher step. {0}
Create(String),
/// Occurs an error in migrate watcher step. {0}
Legacy(String),
/// Retrieve I/O or connectivity error. {1} in {0}
Retrive(String, String),
/// Write I/O or connectivity error. {1} in {0}
Expand All @@ -1502,12 +1510,31 @@ pub async fn create_watcher(
rgb_account.wallets.remove(&name);
}

let mut migrate = false;
if let Some(current_wallet) = rgb_account.wallets.get(&name) {
let current_wallet = current_wallet.clone();
let RgbDescr::Tapret(tapret_desc) = current_wallet.clone().descr;

if xpub != tapret_desc.xpub.to_string() {
rgb_account
.wallets
.insert("legacy".to_string(), current_wallet);
rgb_account.wallets.remove(&name);
migrate = true;
}
}

if !rgb_account.wallets.contains_key(&name) {
let xdesc = DescriptorPublicKey::from_str(&xpub).expect("");
let xdesc = DescriptorPublicKey::from_str(&xpub)
.map_err(|err| WatcherError::WrongDesc(err.to_string()))?;
if let DescriptorPublicKey::XPub(xpub) = xdesc {
let xpub = xpub.xkey;
let xpub = ExtendedPubKey::from_str(&xpub.to_string()).expect("");
create_wallet(&name, xpub, &mut rgb_account.wallets).expect("");
let xpub = ExtendedPubKey::from_str(&xpub.to_string())
.map_err(|err| WatcherError::WrongXPub(err.to_string()))?;
create_wallet(&name, xpub, &mut rgb_account.wallets)
.map_err(|err| WatcherError::Create(err.to_string()))?;
} else {
return Err(WatcherError::WrongXPub("invalid xpub type".to_string()));
}
}

Expand All @@ -1519,7 +1546,7 @@ pub async fn create_watcher(
WALLET_UNAVAILABLE.to_string(),
)
})?;
Ok(WatcherResponse { name })
Ok(WatcherResponse { name, migrate })
}

pub async fn clear_watcher(sk: &str, name: &str) -> Result<WatcherResponse> {
Expand All @@ -1532,6 +1559,7 @@ pub async fn clear_watcher(sk: &str, name: &str) -> Result<WatcherResponse> {
store_wallets(sk, ASSETS_WALLETS, &rgb_account).await?;
Ok(WatcherResponse {
name: name.to_string(),
migrate: false,
})
}

Expand Down
2 changes: 2 additions & 0 deletions src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,8 @@ pub struct WatcherRequest {
pub struct WatcherResponse {
/// The watcher name
pub name: String,
/// migrate?
pub migrate: bool,
}

#[derive(Serialize, Deserialize, Debug, Clone, Default)]
Expand Down
39 changes: 38 additions & 1 deletion tests/rgb/integration/watcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use bitmask_core::{
structs::{SecretString, WatcherRequest},
};

use crate::rgb::integration::utils::{send_some_coins, ISSUER_MNEMONIC};
use crate::rgb::integration::utils::{send_some_coins, ISSUER_MNEMONIC, OWNER_MNEMONIC};

#[tokio::test]
async fn allow_monitoring_address() -> anyhow::Result<()> {
Expand Down Expand Up @@ -156,3 +156,40 @@ async fn allow_monitoring_valid_utxo() -> anyhow::Result<()> {
assert!(!resp?.utxos.is_empty());
Ok(())
}

#[tokio::test]
async fn allow_migrate_watcher() -> anyhow::Result<()> {
let issuer_keys = &save_mnemonic(
&SecretString(ISSUER_MNEMONIC.to_string()),
&SecretString("".to_string()),
)
.await?;

let owner_keys = &save_mnemonic(
&SecretString(OWNER_MNEMONIC.to_string()),
&SecretString("".to_string()),
)
.await?;

// Create Watcher (Wrong Key)
let watcher_name = "default";
let sk = issuer_keys.private.nostr_prv.clone();
let create_watch_req = WatcherRequest {
name: watcher_name.to_string(),
xpub: owner_keys.public.watcher_xpub.clone(),
force: false,
};

create_watcher(&sk, create_watch_req.clone()).await?;

// Create Watcher (Correct Key)
let create_watch_req = WatcherRequest {
name: watcher_name.to_string(),
xpub: issuer_keys.public.watcher_xpub.clone(),
force: false,
};

let resp = create_watcher(&sk, create_watch_req.clone()).await?;
assert!(resp.migrate);
Ok(())
}

0 comments on commit 656de08

Please sign in to comment.