mirror of
https://github.com/basicswap/basicswap.git
synced 2025-03-12 09:38:03 +00:00
Disable duplicate (proof of funds) balance check when sending offer.
Fix for blinded Particl offers. Add fee to reverse offer balance check.
This commit is contained in:
parent
73ab5e7391
commit
681122bcca
5 changed files with 95 additions and 32 deletions
|
@ -140,7 +140,6 @@ from .basicswap_util import (
|
|||
canAcceptBidState,
|
||||
describeEventEntry,
|
||||
getLastBidState,
|
||||
getOfferProofOfFundsHash,
|
||||
getVoutByAddress,
|
||||
getVoutByScriptPubKey,
|
||||
inactive_states,
|
||||
|
@ -2117,21 +2116,27 @@ class BasicSwap(BaseApp):
|
|||
msg_buf.fee_rate_to
|
||||
) # Unused: TODO - Set priority?
|
||||
|
||||
ensure_balance: int = int(amount)
|
||||
if coin_from in self.scriptless_coins:
|
||||
ci_from.ensureFunds(msg_buf.amount_from)
|
||||
# TODO: Better tx size estimate, xmr_swap_b_lock_tx_vsize could be larger than xmr_swap_b_lock_spend_tx_vsize
|
||||
estimated_fee: int = (
|
||||
msg_buf.fee_rate_from
|
||||
* ci_from.xmr_swap_b_lock_spend_tx_vsize()
|
||||
/ 1000
|
||||
)
|
||||
ci_from.ensureFunds(msg_buf.amount_from + estimated_fee)
|
||||
else:
|
||||
proof_of_funds_hash = getOfferProofOfFundsHash(msg_buf, offer_addr)
|
||||
ensure_balance: int = int(amount)
|
||||
# If a prefunded txn is not used, check that the wallet balance can cover the tx fee.
|
||||
if "prefunded_itx" not in extra_options:
|
||||
pi = self.pi(SwapTypes.XMR_SWAP)
|
||||
_ = pi.getFundedInitiateTxTemplate(ci_from, ensure_balance, False)
|
||||
# TODO: Save the prefunded tx so the fee can't change, complicates multiple offers at the same time.
|
||||
|
||||
proof_addr, proof_sig, proof_utxos = self.getProofOfFunds(
|
||||
coin_from_t, ensure_balance, proof_of_funds_hash
|
||||
)
|
||||
# TODO: For now proof_of_funds is just a client side check, may need to be sent with offers in future however.
|
||||
# TODO: Send proof of funds with offer
|
||||
# proof_of_funds_hash = getOfferProofOfFundsHash(msg_buf, offer_addr)
|
||||
# proof_addr, proof_sig, proof_utxos = self.getProofOfFunds(
|
||||
# coin_from_t, ensure_balance, proof_of_funds_hash
|
||||
# )
|
||||
|
||||
offer_bytes = msg_buf.to_bytes()
|
||||
payload_hex = str.format("{:02x}", MessageTypes.OFFER) + offer_bytes.hex()
|
||||
|
|
|
@ -261,9 +261,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
]
|
||||
params = [inputs, outputs]
|
||||
rv = self.rpc_wallet("createrawparttransaction", params)
|
||||
|
||||
tx_bytes = bytes.fromhex(rv["hex"])
|
||||
return tx_bytes
|
||||
return bytes.fromhex(rv["hex"])
|
||||
|
||||
def fundSCLockTx(self, tx_bytes: bytes, feerate: int, vkbv: bytes) -> bytes:
|
||||
feerate_str = self.format_amount(feerate)
|
||||
|
@ -292,7 +290,7 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
"lockUnspents": True,
|
||||
"feeRate": feerate_str,
|
||||
}
|
||||
rv = self.rpc(
|
||||
rv = self.rpc_wallet(
|
||||
"fundrawtransactionfrom", ["blind", tx_hex, {}, outputs_info, options]
|
||||
)
|
||||
return bytes.fromhex(rv["hex"])
|
||||
|
@ -1162,10 +1160,44 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
sub_fee: bool = False,
|
||||
lock_unspents: bool = True,
|
||||
) -> str:
|
||||
txn = self.rpc_wallet(
|
||||
"createrawtransaction", [[], {addr_to: self.format_amount(amount)}]
|
||||
# Estimate lock tx size / fee
|
||||
|
||||
# self.createSCLockTx
|
||||
vkbv = self.getNewRandomKey()
|
||||
ephemeral_key = self.getNewRandomKey()
|
||||
ephemeral_pubkey = self.getPubkey(ephemeral_key)
|
||||
assert len(ephemeral_pubkey) == 33
|
||||
nonce = self.getScriptLockTxNonce(vkbv)
|
||||
inputs = []
|
||||
outputs = [
|
||||
{
|
||||
"type": "blind",
|
||||
"amount": self.format_amount(amount),
|
||||
"address": addr_to,
|
||||
"nonce": nonce.hex(),
|
||||
"data": ephemeral_pubkey.hex(),
|
||||
}
|
||||
]
|
||||
params = [inputs, outputs]
|
||||
tx_hex = self.rpc_wallet("createrawparttransaction", params)["hex"]
|
||||
|
||||
# self.fundSCLockTx
|
||||
tx_obj = self.rpc("decoderawtransaction", [tx_hex])
|
||||
|
||||
assert len(tx_obj["vout"]) == 1
|
||||
txo = tx_obj["vout"][0]
|
||||
blinded_info = self.rpc(
|
||||
"rewindrangeproof", [txo["rangeproof"], txo["valueCommitment"], nonce.hex()]
|
||||
)
|
||||
|
||||
outputs_info = {
|
||||
0: {
|
||||
"value": blinded_info["amount"],
|
||||
"blind": blinded_info["blind"],
|
||||
"nonce": nonce.hex(),
|
||||
}
|
||||
}
|
||||
|
||||
options = {
|
||||
"lockUnspents": lock_unspents,
|
||||
"conf_target": self._conf_target,
|
||||
|
@ -1174,7 +1206,9 @@ class PARTInterfaceBlind(PARTInterface):
|
|||
options["subtractFeeFromOutputs"] = [
|
||||
0,
|
||||
]
|
||||
return self.rpc_wallet("fundrawtransactionfrom", ["blind", txn, options])["hex"]
|
||||
return self.rpc_wallet(
|
||||
"fundrawtransactionfrom", ["blind", tx_hex, {}, outputs_info, options]
|
||||
)["hex"]
|
||||
|
||||
|
||||
class PARTInterfaceAnon(PARTInterface):
|
||||
|
|
|
@ -841,7 +841,7 @@ def js_getcoinseed(self, url_split, post_string, is_json) -> bytes:
|
|||
key_spend = swap_client.getWalletKey(coin, 2, for_ed25519=True)
|
||||
address = ci.getAddressFromKeys(key_view, key_spend)
|
||||
|
||||
expect_address = self.getCachedMainWalletAddress(ci)
|
||||
expect_address = swap_client.getCachedMainWalletAddress(ci)
|
||||
rv.update(
|
||||
{
|
||||
"key_view": ci.encodeKey(key_view),
|
||||
|
|
|
@ -1734,6 +1734,22 @@ class BasicSwapTest(TestFunctions):
|
|||
|
||||
amt_swap: int = ci_from.make_int(balance_from_before, r=1)
|
||||
rate_swap: int = ci_to.make_int(2.0, r=1)
|
||||
|
||||
try:
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from,
|
||||
coin_to,
|
||||
amt_swap,
|
||||
rate_swap,
|
||||
amt_swap,
|
||||
SwapTypes.XMR_SWAP,
|
||||
auto_accept_bids=True,
|
||||
)
|
||||
except Exception as e:
|
||||
assert "Insufficient funds" in str(e)
|
||||
else:
|
||||
assert False, "Should fail"
|
||||
amt_swap -= ci_from.make_int(1)
|
||||
offer_id = swap_clients[id_offerer].postOffer(
|
||||
coin_from,
|
||||
coin_to,
|
||||
|
@ -1745,26 +1761,32 @@ class BasicSwapTest(TestFunctions):
|
|||
)
|
||||
wait_for_offer(test_delay_event, swap_clients[id_bidder], offer_id)
|
||||
|
||||
# First bid should work
|
||||
bid_id = swap_clients[id_bidder].postXmrBid(offer_id, amt_swap)
|
||||
|
||||
event = wait_for_event(
|
||||
test_delay_event,
|
||||
swap_clients[id_offerer],
|
||||
Concepts.BID,
|
||||
bid_id,
|
||||
event_type=EventLogTypes.ERROR,
|
||||
wait_for=60,
|
||||
)
|
||||
assert "Insufficient funds" in event.event_msg
|
||||
|
||||
wait_for_bid(
|
||||
test_delay_event,
|
||||
swap_clients[id_offerer],
|
||||
bid_id,
|
||||
BidStates.BID_RECEIVED,
|
||||
wait_for=20,
|
||||
(BidStates.BID_ACCEPTED, BidStates.XMR_SWAP_SCRIPT_COIN_LOCKED),
|
||||
wait_for=40,
|
||||
)
|
||||
|
||||
# Should be out of funds for second bid (over remaining offer value causes a hard auto accept fail)
|
||||
bid_id = swap_clients[id_bidder].postXmrBid(offer_id, amt_swap)
|
||||
wait_for_bid(
|
||||
test_delay_event,
|
||||
swap_clients[id_offerer],
|
||||
bid_id,
|
||||
BidStates.BID_AACCEPT_FAIL,
|
||||
wait_for=40,
|
||||
)
|
||||
try:
|
||||
swap_clients[id_offerer].acceptBid(bid_id)
|
||||
except Exception as e:
|
||||
assert "Insufficient funds" in str(e)
|
||||
else:
|
||||
assert False, "Should fail"
|
||||
|
||||
def test_08_insufficient_funds_rev(self):
|
||||
tla_from = self.test_coin_from.name
|
||||
logging.info("---------- Test {} Insufficient Funds (reverse)".format(tla_from))
|
||||
|
|
|
@ -1793,7 +1793,9 @@ class Test(BaseTest):
|
|||
self.prepare_balance(Coins.XMR, 20.0, 1800, 1801)
|
||||
js_w1_before = read_json_api(1801, "wallets")
|
||||
ci1_btc = swap_clients[1].ci(Coins.BTC)
|
||||
btc_total = ci1_btc.make_int(js_w1_before["BTC"]["balance"]) + ci1_btc.make_int(js_w1_before["BTC"]["unconfirmed"])
|
||||
btc_total = ci1_btc.make_int(js_w1_before["BTC"]["balance"]) + ci1_btc.make_int(
|
||||
js_w1_before["BTC"]["unconfirmed"]
|
||||
)
|
||||
|
||||
try:
|
||||
offer_id = swap_clients[1].postOffer(
|
||||
|
@ -1803,7 +1805,7 @@ class Test(BaseTest):
|
|||
0,
|
||||
10 * COIN,
|
||||
SwapTypes.XMR_SWAP,
|
||||
extra_options={"amount_to": 10 * XMR_COIN}
|
||||
extra_options={"amount_to": 10 * XMR_COIN},
|
||||
)
|
||||
except Exception as e:
|
||||
assert "Insufficient funds" in str(e)
|
||||
|
@ -1817,7 +1819,7 @@ class Test(BaseTest):
|
|||
0,
|
||||
10 * COIN,
|
||||
SwapTypes.XMR_SWAP,
|
||||
extra_options={"amount_to": 10 * XMR_COIN}
|
||||
extra_options={"amount_to": 10 * XMR_COIN},
|
||||
)
|
||||
|
||||
wait_for_offer(test_delay_event, swap_clients[0], offer_id)
|
||||
|
|
Loading…
Reference in a new issue