From 51d65fd15e4684a792363cf413711451816f843e Mon Sep 17 00:00:00 2001
From: Reckless_Satoshi
Date: Mon, 24 Jan 2022 09:54:44 -0800
Subject: [PATCH] Implement CLTV_expiries for each hold invoice duration.
Invoice expiry matches status time to lock it.
---
.env-sample | 2 +-
api/lightning/node.py | 10 +++++++---
api/logics.py | 15 ++++++++++++---
api/management/commands/clean_orders.py | 2 +-
api/management/commands/follow_invoices.py | 6 +++---
frontend/src/components/InfoDialog.js | 10 +++++-----
frontend/src/components/OrderPage.js | 4 ++--
frontend/src/components/TradeBox.js | 4 ++--
.../sounds/{sucessful.mp3 => successful.mp3} | Bin
9 files changed, 33 insertions(+), 20 deletions(-)
rename frontend/static/assets/sounds/{sucessful.mp3 => successful.mp3} (100%)
diff --git a/.env-sample b/.env-sample
index cfbb7a7a..d2045839 100644
--- a/.env-sample
+++ b/.env-sample
@@ -28,7 +28,7 @@ RETRY_TIME = 5
MIN_TRADE = 10000
MAX_TRADE = 500000
-# Expiration time for HODL invoices and returning collateral in HOURS
+# Expiration (CLTV_expiry) time for HODL invoices in HOURS // 7 min/block assumed
BOND_EXPIRY = 14
ESCROW_EXPIRY = 8
diff --git a/api/lightning/node.py b/api/lightning/node.py
index 4f6cb348..8ba82abd 100644
--- a/api/lightning/node.py
+++ b/api/lightning/node.py
@@ -64,7 +64,7 @@ class LNNode():
return str(response)=="" # True if no response, false otherwise.
@classmethod
- def gen_hold_invoice(cls, num_satoshis, description, expiry):
+ def gen_hold_invoice(cls, num_satoshis, description, invoice_expiry, cltv_expiry_secs):
'''Generates hold invoice'''
hold_payment = {}
@@ -73,12 +73,16 @@ class LNNode():
# Its hash is used to generate the hold invoice
r_hash = hashlib.sha256(preimage).digest()
-
+
+ # timelock expiry for the last hop, computed based on a 10 minutes block with 30% padding (~7 min block)
+ cltv_expiry_blocks = int(cltv_expiry_secs / (7*60))
request = invoicesrpc.AddHoldInvoiceRequest(
memo=description,
value=num_satoshis,
hash=r_hash,
- expiry=expiry)
+ expiry=invoice_expiry,
+ cltv_expiry=cltv_expiry_blocks,
+ )
response = cls.invoicesstub.AddHoldInvoice(request, metadata=[('macaroon', MACAROON.hex())])
hold_payment['invoice'] = response.payment_request
diff --git a/api/logics.py b/api/logics.py
index c553ab4e..e21c88dc 100644
--- a/api/logics.py
+++ b/api/logics.py
@@ -500,7 +500,10 @@ class Logics():
description = f"RoboSats - Publishing '{str(order)}' - This is a maker bond, it will freeze in your wallet temporarily and automatically return. It will be charged if you cheat or cancel."
# Gen hold Invoice
- hold_payment = LNNode.gen_hold_invoice(bond_satoshis, description, BOND_EXPIRY*3600)
+ hold_payment = LNNode.gen_hold_invoice(bond_satoshis,
+ description,
+ invoice_expiry=Order.t_to_expire[Order.Status.WFB],
+ cltv_expiry_secs=BOND_EXPIRY*3600)
order.maker_bond = LNPayment.objects.create(
concept = LNPayment.Concepts.MAKEBOND,
@@ -577,7 +580,10 @@ class Logics():
+ " - This is a taker bond, it will freeze in your wallet temporarily and automatically return. It will be charged if you cheat or cancel.")
# Gen hold Invoice
- hold_payment = LNNode.gen_hold_invoice(bond_satoshis, description, BOND_EXPIRY*3600)
+ hold_payment = LNNode.gen_hold_invoice(bond_satoshis,
+ description,
+ invoice_expiry=Order.t_to_expire[Order.Status.TAK],
+ cltv_expiry_secs=BOND_EXPIRY*3600)
order.taker_bond = LNPayment.objects.create(
concept = LNPayment.Concepts.TAKEBOND,
@@ -640,7 +646,10 @@ class Logics():
description = f"RoboSats - Escrow amount for '{str(order)}' - The escrow will be released to the buyer once you confirm you received the fiat. It will automatically return if buyer does not confirm the payment."
# Gen hold Invoice
- hold_payment = LNNode.gen_hold_invoice(escrow_satoshis, description, ESCROW_EXPIRY*3600)
+ hold_payment = LNNode.gen_hold_invoice(escrow_satoshis,
+ description,
+ invoice_expiry=Order.t_to_expire[Order.Status.WF2],
+ cltv_expiry_secs=ESCROW_EXPIRY*3600)
order.trade_escrow = LNPayment.objects.create(
concept = LNPayment.Concepts.TRESCROW,
diff --git a/api/management/commands/clean_orders.py b/api/management/commands/clean_orders.py
index 845a2c8b..9c814b3b 100644
--- a/api/management/commands/clean_orders.py
+++ b/api/management/commands/clean_orders.py
@@ -62,4 +62,4 @@ class Command(BaseCommand):
if 'database is locked' in str(e):
self.stdout.write('database is locked')
- self.stdout.write(e)
+ self.stdout.write(str(e))
diff --git a/api/management/commands/follow_invoices.py b/api/management/commands/follow_invoices.py
index eaa36601..878445e7 100644
--- a/api/management/commands/follow_invoices.py
+++ b/api/management/commands/follow_invoices.py
@@ -62,8 +62,8 @@ class Command(BaseCommand):
hold_lnpayment.status = lnd_state_to_lnpayment_status[response.state]
except Exception as e:
- # If it fails at finding the invoice it has been canceled.
- # On RoboSats DB we make a distinction between cancelled and returned (LND does not)
+ # If it fails at finding the invoice: it has been canceled.
+ # In RoboSats DB we make a distinction between cancelled and returned (LND does not)
if 'unable to locate invoice' in str(e):
self.stdout.write(str(e))
hold_lnpayment.status = LNPayment.Status.CANCEL
@@ -140,4 +140,4 @@ class Command(BaseCommand):
if 'database is locked' in str(e):
self.stdout.write('database is locked')
- self.stdout.write(e)
\ No newline at end of file
+ self.stdout.write(str(e))
\ No newline at end of file
diff --git a/frontend/src/components/InfoDialog.js b/frontend/src/components/InfoDialog.js
index a49f06e4..9e5afdd2 100644
--- a/frontend/src/components/InfoDialog.js
+++ b/frontend/src/components/InfoDialog.js
@@ -79,10 +79,10 @@ export default class InfoDialog extends Component {
In addition, disputes are solved by the RoboSats staff.
- Trust requirements are minimal, however there is still one way RoboSats
- could run away with your satoshis: by not releasing
- the satoshis to the buyer. It could be argued that such move is not on RoboSats
- interest as it would damage the reputation for a small payout.
+
To be totally clear. Trust requirements are minimized. However, there is still
+ one way RoboSats could run away with your satoshis: by not releasing
+ the satoshis to the buyer. It could be argued that such move is not in RoboSats'
+ as it would damage the reputation for a small payout.
However, you should hesitate and only trade small quantities at a
time. For large amounts use an onchain escrow service such as Bisq
@@ -98,7 +98,7 @@ export default class InfoDialog extends Component {
forever. This is true for both, locked bonds and trading escrows. However,
there is a small window between the seller confirms FIAT RECEIVED and the moment
the buyer receives the satoshis when the funds could be permanentely lost if
- RoboSats disappears. This window is about 1 second long. Make sure to have enough
+ RoboSats disappears. This window is about 1 second long. Make sure to have enough
inbound liquidity to avoid routing failures. If you have any problem, reach out
trough the RoboSats public channels.
diff --git a/frontend/src/components/OrderPage.js b/frontend/src/components/OrderPage.js
index 1791cf48..951060d4 100644
--- a/frontend/src/components/OrderPage.js
+++ b/frontend/src/components/OrderPage.js
@@ -52,7 +52,7 @@ export default class OrderPage extends Component {
// Refresh delays according to Order status
this.statusToDelay = {
"0": 2000, //'Waiting for maker bond'
- "1": 15000, //'Public'
+ "1": 45000, //'Public'
"2": 9999999, //'Deleted'
"3": 2000, //'Waiting for taker bond'
"4": 9999999, //'Cancelled'
@@ -87,7 +87,7 @@ export default class OrderPage extends Component {
delay: this.setDelay(newStateVars.status),
currencyCode: this.getCurrencyCode(newStateVars.currency),
};
-
+
var completeStateVars = Object.assign({}, newStateVars, otherStateVars);
this.setState(completeStateVars);
}
diff --git a/frontend/src/components/TradeBox.js b/frontend/src/components/TradeBox.js
index 79f86a2c..35df69c1 100644
--- a/frontend/src/components/TradeBox.js
+++ b/frontend/src/components/TradeBox.js
@@ -147,7 +147,7 @@ export default class TradeBox extends Component {
- Robosats show commitment to their peers
+ Robots show commitment to their peers
@@ -665,7 +665,7 @@ handleRatingChange=(e)=>{
showRoutingFailed(){
// TODO If it has failed 3 times, ask for a new invoice.
-
+
return(
diff --git a/frontend/static/assets/sounds/sucessful.mp3 b/frontend/static/assets/sounds/successful.mp3
similarity index 100%
rename from frontend/static/assets/sounds/sucessful.mp3
rename to frontend/static/assets/sounds/successful.mp3