Skip to content

Commit

Permalink
Fix minor errors regarding IN_TRANSFER status
Browse files Browse the repository at this point in the history
  • Loading branch information
ssantos21 committed May 22, 2024
1 parent 6eb2cfa commit 815a904
Show file tree
Hide file tree
Showing 24 changed files with 152 additions and 31 deletions.
2 changes: 0 additions & 2 deletions clients/kotlin/src/main/kotlin/TransferSend.kt
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,6 @@ class TransferSend: CliktCommand(help = "Send the specified coin to an statechai
blindingFactor = coin.blindingFactor ?: throw Exception("blindingFactor is null")
)

coin.locktime = getBlockheight(backupTx);

backupTxs = backupTxs.plus(backupTx)

val inputTxid = coin.utxoTxid!!
Expand Down
20 changes: 8 additions & 12 deletions clients/nodejs/broadcast_backup_tx.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,7 @@ const execute = async (electrumClient, db, walletName, statechainId, toAddress,
feeRate = parseInt(feeRate, 10);
}

// console.log("feeRate: ", feeRate);

let backupTxs = await sqlite_manager.getBackupTxs(db, statechainId);

const backupTx = backupTxs.length === 0 ? null : backupTxs.reduce((prev, current) => (prev.tx_n > current.tx_n) ? prev : current);

if (!backupTx) {
throw new Error(`There is no backup transaction for the statechain id ${statechainId}`);
}

// console.log("backupTx", backupTx);

let coinsWithStatechainId = wallet.coins.filter(c => {
return c.statechain_id === statechainId
Expand All @@ -43,8 +33,14 @@ const execute = async (electrumClient, db, walletName, statechainId, toAddress,
// Sort the coins by locktime in ascending order and pick the first one
let coin = coinsWithStatechainId.sort((a, b) => a.locktime - b.locktime)[0];

if (coin.status != CoinStatus.CONFIRMED) {
throw new Error(`Coin status must be CONFIRMED to broadcast the backup transaction. The current status is ${coin.status}`);
if (coin.status != CoinStatus.CONFIRMED && coin.status != CoinStatus.IN_TRANSFER) {
throw new Error(`Coin status must be CONFIRMED or IN_TRANSFER to transfer it. The current status is ${coin.status}`);
}

const backupTx = mercury_wasm.latestBackuptxPaysToUserpubkey(backupTxs, coin, wallet.network);

if (!backupTx) {
throw new Error(`There is no backup transaction for the statechain id ${statechainId}`);
}

const CpfpTx = mercury_wasm.createCpfpTx(backupTx, coin, toAddress, feeRate, wallet.network);
Expand Down
2 changes: 0 additions & 2 deletions clients/nodejs/transfer_send.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,6 @@ const execute = async (electrumClient, db, walletName, statechainId, toAddress,
blinding_factor: coin.blinding_factor
};

coin.locktime = mercury_wasm.getBlockheight(backup_tx);

backupTxs.push(backup_tx);

const input_txid = coin.utxo_txid;
Expand Down
4 changes: 2 additions & 2 deletions clients/nodejs/withdraw.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,8 @@ const execute = async (electrumClient, db, walletName, statechainId, toAddress,
// Sort the coins by locktime in ascending order and pick the first one
let coin = coinsWithStatechainId.sort((a, b) => a.locktime - b.locktime)[0];

if (coin.status != CoinStatus.CONFIRMED) {
throw new Error(`Coin status must be CONFIRMED to withdraw it. The current status is ${coin.status}`);
if (coin.status != CoinStatus.CONFIRMED && coin.status != CoinStatus.IN_TRANSFER) {
throw new Error(`Coin status must be CONFIRMED or IN_TRANSFER to transfer it. The current status is ${coin.status}`);
}

const isWithdrawal = true;
Expand Down
14 changes: 4 additions & 10 deletions clients/rust/src/broadcast_backup_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,6 @@ pub async fn execute(client_config: &ClientConfig, wallet_name: &str, statechain

let backup_txs = get_backup_txs(&client_config.pool, &statechain_id).await?;

let backup_tx = backup_txs.iter().max_by_key(|tx| tx.tx_n);

if backup_tx.is_none() {
return Err(anyhow!("No backup transaction associated with this statechain ID were found"));
}

let backup_tx = backup_tx.unwrap();

// If the user sends to himself, he will have two coins with same statechain_id
// In this case, we need to find the one with the lowest locktime
let coin = wallet.coins
Expand All @@ -36,10 +28,12 @@ pub async fn execute(client_config: &ClientConfig, wallet_name: &str, statechain

let coin = coin.unwrap();

if coin.status != CoinStatus::CONFIRMED {
return Err(anyhow::anyhow!("Coin status must be CONFIRMED to broadcast the backup transaction. The current status is {}", coin.status));
if coin.status != CoinStatus::CONFIRMED && coin.status != CoinStatus::IN_TRANSFER {
return Err(anyhow::anyhow!("Coin status must be CONFIRMED or IN_TRANSFER to transfer it. The current status is {}", coin.status));
}

let backup_tx = cpfp_tx::latest_backup_tx_pays_to_user_pubkey(&backup_txs, &coin, &wallet.network)?;

let fee_rate = match fee_rate {
Some(fee_rate) => fee_rate,
None => {
Expand Down
4 changes: 1 addition & 3 deletions clients/rust/src/transfer_sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub async fn execute(
let coin = wallet.coins
.iter_mut()
.filter(|tx| tx.statechain_id == Some(statechain_id.to_string())) // Filter coins with the specified statechain_id
.min_by_key(|tx| tx.locktime); // Find the one with the lowest locktime
.min_by_key(|tx| tx.locktime.unwrap_or(u32::MAX)); // Find the one with the lowest locktime

if coin.is_none() {
return Err(anyhow!("No coins associated with this statechain ID were found"));
Expand Down Expand Up @@ -84,8 +84,6 @@ pub async fn execute(
blinding_factor: coin.blinding_factor.as_ref().unwrap().to_string(),
};

coin.locktime = Some(get_blockheight(&backup_tx)?);

backup_transactions.push(backup_tx);

let input_txid = coin.utxo_txid.as_ref().unwrap();
Expand Down
36 changes: 36 additions & 0 deletions lib/src/wallet/cpfp_tx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,42 @@ use super::{BackupTx, Coin};
use bitcoin::{Transaction, Address, TxOut, Txid, OutPoint, TxIn, ScriptBuf, Witness, absolute, psbt::{Psbt, Input, PsbtSighashType, self}, bip32::{Fingerprint, DerivationPath}, Amount, Network, sighash::{TapSighashType, SighashCache, self, TapSighash}, taproot::{TapLeafHash, self}, secp256k1, key::TapTweak, PrivateKey};
use secp256k1_zkp::{Secp256k1, SecretKey, PublicKey, XOnlyPublicKey};

#[cfg_attr(feature = "bindings", uniffi::export)]
pub fn latest_backup_tx_pays_to_user_pubkey(backup_txs: &Vec<BackupTx>, coin: &Coin, network: &str) -> Result<BackupTx, MercuryError> {

let network = get_network(network)?;

let backup_address = Address::from_str(coin.backup_address.as_str())?.require_network(network)?;

let backup_tx = backup_txs.iter()
.filter_map(|bkp_tx| {
let tx_bytes = hex::decode(&bkp_tx.tx).ok()?;
let tx: Transaction = bitcoin::consensus::deserialize(&tx_bytes).ok()?;

if tx.output.len() != 1 {
return None;
}

let output: &TxOut = tx.output.get(0)?;
if backup_address.script_pubkey() == output.script_pubkey {
Some(bkp_tx)
} else {
None
}
})
.max_by_key(|bkp_tx| bkp_tx.tx_n);

match backup_tx {
Some(tx) => {
return Ok(tx.clone());
},
None => {
return Err(MercuryError::NoBackupTransactionFound);
}
}
}


#[cfg_attr(feature = "bindings", uniffi::export)]
pub fn create_cpfp_tx(backup_tx: &BackupTx, coin: &Coin, to_address: &str, fee_rate_sats_per_byte: u64, network: &str) -> Result<String, MercuryError> {

Expand Down
7 changes: 7 additions & 0 deletions wasm/node_pkg/debug/mercury_wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ export function signMessage(statechain_id: string, coin: any): string;
*/
export function isEnclavePubkeyPartOfCoin(coin: any, enclave_pubkey: string): boolean;
/**
* @param {any} backup_transactions
* @param {any} coin
* @param {string} network
* @returns {any}
*/
export function latestBackuptxPaysToUserpubkey(backup_transactions: any, coin: any, network: string): any;
/**
* @returns {any}
*/
export function getMockWallet(): any;
13 changes: 13 additions & 0 deletions wasm/node_pkg/debug/mercury_wasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,19 @@ module.exports.isEnclavePubkeyPartOfCoin = function(coin, enclave_pubkey) {
return ret !== 0;
};

/**
* @param {any} backup_transactions
* @param {any} coin
* @param {string} network
* @returns {any}
*/
module.exports.latestBackuptxPaysToUserpubkey = function(backup_transactions, coin, network) {
const ptr0 = passStringToWasm0(network, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.latestBackuptxPaysToUserpubkey(addHeapObject(backup_transactions), addHeapObject(coin), ptr0, len0);
return takeObject(ret);
};

/**
* @returns {any}
*/
Expand Down
Binary file modified wasm/node_pkg/debug/mercury_wasm_bg.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions wasm/node_pkg/debug/mercury_wasm_bg.wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function getNewKeyInfo(a: number, b: number, c: number, d: number, e: num
export function validateAddress(a: number, b: number, c: number, d: number): number;
export function signMessage(a: number, b: number, c: number, d: number): void;
export function isEnclavePubkeyPartOfCoin(a: number, b: number, c: number): number;
export function latestBackuptxPaysToUserpubkey(a: number, b: number, c: number, d: number): number;
export function getMockWallet(): number;
export function rustsecp256k1zkp_v0_8_1_default_illegal_callback_fn(a: number, b: number): void;
export function rustsecp256k1zkp_v0_8_1_default_error_callback_fn(a: number, b: number): void;
Expand Down
7 changes: 7 additions & 0 deletions wasm/node_pkg/release/mercury_wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ export function signMessage(statechain_id: string, coin: any): string;
*/
export function isEnclavePubkeyPartOfCoin(coin: any, enclave_pubkey: string): boolean;
/**
* @param {any} backup_transactions
* @param {any} coin
* @param {string} network
* @returns {any}
*/
export function latestBackuptxPaysToUserpubkey(backup_transactions: any, coin: any, network: string): any;
/**
* @returns {any}
*/
export function getMockWallet(): any;
13 changes: 13 additions & 0 deletions wasm/node_pkg/release/mercury_wasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,19 @@ module.exports.isEnclavePubkeyPartOfCoin = function(coin, enclave_pubkey) {
return ret !== 0;
};

/**
* @param {any} backup_transactions
* @param {any} coin
* @param {string} network
* @returns {any}
*/
module.exports.latestBackuptxPaysToUserpubkey = function(backup_transactions, coin, network) {
const ptr0 = passStringToWasm0(network, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.latestBackuptxPaysToUserpubkey(addHeapObject(backup_transactions), addHeapObject(coin), ptr0, len0);
return takeObject(ret);
};

/**
* @returns {any}
*/
Expand Down
Binary file modified wasm/node_pkg/release/mercury_wasm_bg.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions wasm/node_pkg/release/mercury_wasm_bg.wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function getNewKeyInfo(a: number, b: number, c: number, d: number, e: num
export function validateAddress(a: number, b: number, c: number, d: number): number;
export function signMessage(a: number, b: number, c: number, d: number): void;
export function isEnclavePubkeyPartOfCoin(a: number, b: number, c: number): number;
export function latestBackuptxPaysToUserpubkey(a: number, b: number, c: number, d: number): number;
export function getMockWallet(): number;
export function rustsecp256k1zkp_v0_8_1_default_illegal_callback_fn(a: number, b: number): void;
export function rustsecp256k1zkp_v0_8_1_default_error_callback_fn(a: number, b: number): void;
Expand Down
15 changes: 15 additions & 0 deletions wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,21 @@ pub fn isEnclavePubkeyPartOfCoin(coin: JsValue, enclave_pubkey: String) -> bool
mercurylib::utils::is_enclave_pubkey_part_of_coin(&coin, &enclave_pubkey).unwrap()
}

#[wasm_bindgen]
pub fn latestBackuptxPaysToUserpubkey(backup_transactions: JsValue, coin: JsValue, network: String) -> JsValue {

let backup_transactions: Vec<BackupTx> = serde_wasm_bindgen::from_value(backup_transactions).unwrap();
let coin: Coin = serde_wasm_bindgen::from_value(coin).unwrap();

let backup_transaction = mercurylib::wallet::cpfp_tx::latest_backup_tx_pays_to_user_pubkey(&backup_transactions, &coin, &network);

if backup_transaction.is_err() {
return JsValue::NULL;
} else {
serde_wasm_bindgen::to_value(&backup_transaction.unwrap()).unwrap()
}
}

#[wasm_bindgen]
pub fn getMockWallet() -> JsValue {
let tokens = vec![
Expand Down
8 changes: 8 additions & 0 deletions wasm/web_pkg/debug/mercury_wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ export function signMessage(statechain_id: string, coin: any): string;
*/
export function isEnclavePubkeyPartOfCoin(coin: any, enclave_pubkey: string): boolean;
/**
* @param {any} backup_transactions
* @param {any} coin
* @param {string} network
* @returns {any}
*/
export function latestBackuptxPaysToUserpubkey(backup_transactions: any, coin: any, network: string): any;
/**
* @returns {any}
*/
export function getMockWallet(): any;
Expand Down Expand Up @@ -297,6 +304,7 @@ export interface InitOutput {
readonly validateAddress: (a: number, b: number, c: number, d: number) => number;
readonly signMessage: (a: number, b: number, c: number, d: number) => void;
readonly isEnclavePubkeyPartOfCoin: (a: number, b: number, c: number) => number;
readonly latestBackuptxPaysToUserpubkey: (a: number, b: number, c: number, d: number) => number;
readonly getMockWallet: () => number;
readonly rustsecp256k1zkp_v0_8_1_default_illegal_callback_fn: (a: number, b: number) => void;
readonly rustsecp256k1zkp_v0_8_1_default_error_callback_fn: (a: number, b: number) => void;
Expand Down
13 changes: 13 additions & 0 deletions wasm/web_pkg/debug/mercury_wasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,19 @@ export function isEnclavePubkeyPartOfCoin(coin, enclave_pubkey) {
return ret !== 0;
}

/**
* @param {any} backup_transactions
* @param {any} coin
* @param {string} network
* @returns {any}
*/
export function latestBackuptxPaysToUserpubkey(backup_transactions, coin, network) {
const ptr0 = passStringToWasm0(network, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.latestBackuptxPaysToUserpubkey(addHeapObject(backup_transactions), addHeapObject(coin), ptr0, len0);
return takeObject(ret);
}

/**
* @returns {any}
*/
Expand Down
Binary file modified wasm/web_pkg/debug/mercury_wasm_bg.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions wasm/web_pkg/debug/mercury_wasm_bg.wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function getNewKeyInfo(a: number, b: number, c: number, d: number, e: num
export function validateAddress(a: number, b: number, c: number, d: number): number;
export function signMessage(a: number, b: number, c: number, d: number): void;
export function isEnclavePubkeyPartOfCoin(a: number, b: number, c: number): number;
export function latestBackuptxPaysToUserpubkey(a: number, b: number, c: number, d: number): number;
export function getMockWallet(): number;
export function rustsecp256k1zkp_v0_8_1_default_illegal_callback_fn(a: number, b: number): void;
export function rustsecp256k1zkp_v0_8_1_default_error_callback_fn(a: number, b: number): void;
Expand Down
8 changes: 8 additions & 0 deletions wasm/web_pkg/release/mercury_wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ export function signMessage(statechain_id: string, coin: any): string;
*/
export function isEnclavePubkeyPartOfCoin(coin: any, enclave_pubkey: string): boolean;
/**
* @param {any} backup_transactions
* @param {any} coin
* @param {string} network
* @returns {any}
*/
export function latestBackuptxPaysToUserpubkey(backup_transactions: any, coin: any, network: string): any;
/**
* @returns {any}
*/
export function getMockWallet(): any;
Expand Down Expand Up @@ -297,6 +304,7 @@ export interface InitOutput {
readonly validateAddress: (a: number, b: number, c: number, d: number) => number;
readonly signMessage: (a: number, b: number, c: number, d: number) => void;
readonly isEnclavePubkeyPartOfCoin: (a: number, b: number, c: number) => number;
readonly latestBackuptxPaysToUserpubkey: (a: number, b: number, c: number, d: number) => number;
readonly getMockWallet: () => number;
readonly rustsecp256k1zkp_v0_8_1_default_illegal_callback_fn: (a: number, b: number) => void;
readonly rustsecp256k1zkp_v0_8_1_default_error_callback_fn: (a: number, b: number) => void;
Expand Down
13 changes: 13 additions & 0 deletions wasm/web_pkg/release/mercury_wasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -790,6 +790,19 @@ export function isEnclavePubkeyPartOfCoin(coin, enclave_pubkey) {
return ret !== 0;
}

/**
* @param {any} backup_transactions
* @param {any} coin
* @param {string} network
* @returns {any}
*/
export function latestBackuptxPaysToUserpubkey(backup_transactions, coin, network) {
const ptr0 = passStringToWasm0(network, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
const len0 = WASM_VECTOR_LEN;
const ret = wasm.latestBackuptxPaysToUserpubkey(addHeapObject(backup_transactions), addHeapObject(coin), ptr0, len0);
return takeObject(ret);
}

/**
* @returns {any}
*/
Expand Down
Binary file modified wasm/web_pkg/release/mercury_wasm_bg.wasm
Binary file not shown.
1 change: 1 addition & 0 deletions wasm/web_pkg/release/mercury_wasm_bg.wasm.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export function getNewKeyInfo(a: number, b: number, c: number, d: number, e: num
export function validateAddress(a: number, b: number, c: number, d: number): number;
export function signMessage(a: number, b: number, c: number, d: number): void;
export function isEnclavePubkeyPartOfCoin(a: number, b: number, c: number): number;
export function latestBackuptxPaysToUserpubkey(a: number, b: number, c: number, d: number): number;
export function getMockWallet(): number;
export function rustsecp256k1zkp_v0_8_1_default_illegal_callback_fn(a: number, b: number): void;
export function rustsecp256k1zkp_v0_8_1_default_error_callback_fn(a: number, b: number): void;
Expand Down

0 comments on commit 815a904

Please sign in to comment.