mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2025-01-18 13:27:20 +01:00
Fix/cashu update protocol (#1433)
* updates NOTE: fix pyproject and requirements * revert GET to POST * update cashu on pip and change name of models * adjust client to spendable * refactor spendable
This commit is contained in:
parent
bdfbbb779e
commit
80a94aa9ce
2
.gitignore
vendored
2
.gitignore
vendored
@ -40,6 +40,4 @@ docker
|
||||
# Nix
|
||||
*result*
|
||||
|
||||
# Ignore extensions (post installable extension PR)
|
||||
extensions/
|
||||
upgrades/
|
@ -1,17 +1,11 @@
|
||||
async function hashToCurve(secretMessage) {
|
||||
console.log(
|
||||
'### secretMessage',
|
||||
nobleSecp256k1.utils.bytesToHex(secretMessage)
|
||||
)
|
||||
let point
|
||||
while (!point) {
|
||||
const hash = await nobleSecp256k1.utils.sha256(secretMessage)
|
||||
const hashHex = nobleSecp256k1.utils.bytesToHex(hash)
|
||||
const pointX = '02' + hashHex
|
||||
console.log('### pointX', pointX)
|
||||
try {
|
||||
point = nobleSecp256k1.Point.fromHex(pointX)
|
||||
console.log('### point', point.toHex())
|
||||
} catch (error) {
|
||||
secretMessage = await nobleSecp256k1.utils.sha256(secretMessage)
|
||||
}
|
||||
@ -20,19 +14,17 @@ async function hashToCurve(secretMessage) {
|
||||
}
|
||||
|
||||
async function step1Alice(secretMessage) {
|
||||
// todo: document & validate `secretMessage` format
|
||||
secretMessage = uint8ToBase64.encode(secretMessage)
|
||||
secretMessage = new TextEncoder().encode(secretMessage)
|
||||
const Y = await hashToCurve(secretMessage)
|
||||
const rpk = nobleSecp256k1.utils.randomPrivateKey()
|
||||
const r = bytesToNumber(rpk)
|
||||
const r_bytes = nobleSecp256k1.utils.randomPrivateKey()
|
||||
const r = bytesToNumber(r_bytes)
|
||||
const P = nobleSecp256k1.Point.fromPrivateKey(r)
|
||||
const B_ = Y.add(P)
|
||||
return {B_: B_.toHex(true), r: nobleSecp256k1.utils.bytesToHex(rpk)}
|
||||
return {B_: B_.toHex(true), r: nobleSecp256k1.utils.bytesToHex(r_bytes)}
|
||||
}
|
||||
|
||||
function step3Alice(C_, r, A) {
|
||||
// const rInt = BigInt(r)
|
||||
const rInt = bytesToNumber(r)
|
||||
const C = C_.subtract(A.multiply(rInt))
|
||||
return C
|
||||
|
@ -1690,8 +1690,6 @@ page_container %}
|
||||
outputs
|
||||
}
|
||||
|
||||
console.log('payload', JSON.stringify(payload))
|
||||
|
||||
const {data} = await LNbits.api.request(
|
||||
'POST',
|
||||
`/cashu/api/v1/${this.mintId}/split`,
|
||||
@ -1885,7 +1883,7 @@ page_container %}
|
||||
const payload = {
|
||||
proofs: scndProofs.flat(),
|
||||
amount,
|
||||
invoice: this.payInvoiceData.data.request
|
||||
pr: this.payInvoiceData.data.request
|
||||
}
|
||||
console.log('#### payload', JSON.stringify(payload))
|
||||
try {
|
||||
@ -1959,8 +1957,13 @@ page_container %}
|
||||
checks with the mint whether an array of proofs is still
|
||||
spendable or already invalidated
|
||||
*/
|
||||
if (proofs.length == 0) {
|
||||
return
|
||||
}
|
||||
const payload = {
|
||||
proofs: proofs.flat()
|
||||
proofs: proofs.map(p => {
|
||||
return {secret: p.secret}
|
||||
})
|
||||
}
|
||||
console.log('#### payload', JSON.stringify(payload))
|
||||
try {
|
||||
@ -1972,7 +1975,7 @@ page_container %}
|
||||
)
|
||||
|
||||
// delete proofs from database if it is spent
|
||||
let spentProofs = proofs.filter((p, pidx) => !data[pidx])
|
||||
let spentProofs = proofs.filter((p, pidx) => !data.spendable[pidx])
|
||||
if (spentProofs.length) {
|
||||
this.deleteProofs(spentProofs)
|
||||
|
||||
@ -1990,7 +1993,7 @@ page_container %}
|
||||
}
|
||||
}
|
||||
|
||||
return data
|
||||
return data.spendable
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
LNbits.utils.notifyApiError(error)
|
||||
@ -2033,6 +2036,9 @@ page_container %}
|
||||
JSON.stringify(data)
|
||||
)
|
||||
},
|
||||
|
||||
////////////// UI HELPERS //////////////
|
||||
|
||||
setInvoicePaid: async function (payment_hash) {
|
||||
const invoice = this.invoicesCashu.find(i => i.hash === payment_hash)
|
||||
invoice.status = 'paid'
|
||||
@ -2077,15 +2083,11 @@ page_container %}
|
||||
*/
|
||||
const tokenJson = atob(token)
|
||||
const proofs = JSON.parse(tokenJson)
|
||||
let data = await this.checkProofsSpendable(proofs)
|
||||
|
||||
// iterate through response of form {0: true, 1: false, ...}
|
||||
const spendable = await this.checkProofsSpendable(proofs)
|
||||
let paid = false
|
||||
for (const [key, spendable] of Object.entries(data)) {
|
||||
if (!spendable) {
|
||||
this.setTokenPaid(token)
|
||||
paid = true
|
||||
}
|
||||
if (spendable.includes(true)) {
|
||||
this.setTokenPaid(token)
|
||||
paid = true
|
||||
}
|
||||
if (paid) {
|
||||
console.log('### token paid')
|
||||
@ -2126,6 +2128,7 @@ page_container %}
|
||||
},
|
||||
|
||||
findTokenForAmount: function (amount) {
|
||||
// unused coin selection
|
||||
for (const token of this.proofs) {
|
||||
const index = token.promises?.findIndex(p => p.amount === amount)
|
||||
if (index >= 0) {
|
||||
|
@ -4,18 +4,18 @@ from typing import Dict, List, Union
|
||||
|
||||
# -------- cashu imports
|
||||
from cashu.core.base import (
|
||||
BlindedSignature,
|
||||
CheckFeesRequest,
|
||||
CheckFeesResponse,
|
||||
CheckRequest,
|
||||
CheckSpendableRequest,
|
||||
CheckSpendableResponse,
|
||||
GetMeltResponse,
|
||||
GetMintResponse,
|
||||
Invoice,
|
||||
MeltRequest,
|
||||
PostMeltRequest,
|
||||
PostMintRequest,
|
||||
PostMintResponse,
|
||||
PostSplitRequest,
|
||||
PostSplitResponse,
|
||||
SplitRequest,
|
||||
)
|
||||
from fastapi import Depends, Query
|
||||
from loguru import logger
|
||||
@ -279,7 +279,7 @@ async def mint(
|
||||
|
||||
@cashu_ext.post("/api/v1/{cashu_id}/melt")
|
||||
async def melt_coins(
|
||||
payload: MeltRequest, cashu_id: str = Query(None)
|
||||
payload: PostMeltRequest, cashu_id: str = Query(None)
|
||||
) -> GetMeltResponse:
|
||||
"""Invalidates proofs and pays a Lightning invoice."""
|
||||
cashu: Union[None, Cashu] = await get_cashu(cashu_id)
|
||||
@ -288,7 +288,7 @@ async def melt_coins(
|
||||
status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist."
|
||||
)
|
||||
proofs = payload.proofs
|
||||
invoice = payload.invoice
|
||||
invoice = payload.pr
|
||||
|
||||
# !!!!!!! MAKE SURE THAT PROOFS ARE ONLY FROM THIS CASHU KEYSET ID
|
||||
# THIS IS NECESSARY BECAUSE THE CASHU BACKEND WILL ACCEPT ANY VALID
|
||||
@ -358,7 +358,7 @@ async def melt_coins(
|
||||
|
||||
@cashu_ext.post("/api/v1/{cashu_id}/check")
|
||||
async def check_spendable(
|
||||
payload: CheckRequest, cashu_id: str = Query(None)
|
||||
payload: CheckSpendableRequest, cashu_id: str = Query(None)
|
||||
) -> Dict[int, bool]:
|
||||
"""Check whether a secret has been spent already or not."""
|
||||
cashu: Union[None, Cashu] = await get_cashu(cashu_id)
|
||||
@ -366,7 +366,8 @@ async def check_spendable(
|
||||
raise HTTPException(
|
||||
status_code=HTTPStatus.NOT_FOUND, detail="Mint does not exist."
|
||||
)
|
||||
return await ledger.check_spendable(payload.proofs)
|
||||
spendableList = await ledger.check_spendable(payload.proofs)
|
||||
return CheckSpendableResponse(spendable=spendableList)
|
||||
|
||||
|
||||
@cashu_ext.post("/api/v1/{cashu_id}/checkfees")
|
||||
@ -395,7 +396,7 @@ async def check_fees(
|
||||
|
||||
@cashu_ext.post("/api/v1/{cashu_id}/split")
|
||||
async def split(
|
||||
payload: SplitRequest, cashu_id: str = Query(None)
|
||||
payload: PostSplitRequest, cashu_id: str = Query(None)
|
||||
) -> PostSplitResponse:
|
||||
"""
|
||||
Requetst a set of tokens with amount "total" to be split into two
|
||||
|
8
poetry.lock
generated
8
poetry.lock
generated
@ -195,14 +195,14 @@ websockets = ">=10"
|
||||
|
||||
[[package]]
|
||||
name = "cashu"
|
||||
version = "0.8.2"
|
||||
version = "0.9.0"
|
||||
description = "Ecash wallet and mint for Bitcoin Lightning"
|
||||
category = "main"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "cashu-0.8.2-py3-none-any.whl", hash = "sha256:53893911763c424255bc7112aaba356e0a265e850d770338c70b2d282f67bf99"},
|
||||
{file = "cashu-0.8.2.tar.gz", hash = "sha256:4cdd34a50d14960d2dcc6f5b6120f462688090dd084387860f7a59d16aa102ff"},
|
||||
{file = "cashu-0.9.0-py3-none-any.whl", hash = "sha256:73dde901c8ea75d223f0cb37ea214028c17b798f9189b88968884c4a9c2e32a8"},
|
||||
{file = "cashu-0.9.0.tar.gz", hash = "sha256:5d5087b3b80ecd8350ea2b098605581a746fc377c0bf9f1e3a97fa5c6d06d9f2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -2112,4 +2112,4 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools"
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10 | ^3.9 | ^3.8 | ^3.7"
|
||||
content-hash = "bbbe4d958160a1e5c596c09af3c402964a7e68d9da1491e787649cee278c5eac"
|
||||
content-hash = "e3ac1dcb6e10cc8fd7ee1ae88698ca6d2d412efe353578d9f2134adc512a523b"
|
||||
|
@ -62,8 +62,8 @@ protobuf = "4.21.12"
|
||||
Cerberus = "1.3.4"
|
||||
async-timeout = "4.0.2"
|
||||
pyln-client = "0.11.1"
|
||||
cashu = "0.8.2"
|
||||
boltz-client = "0.1.3"
|
||||
cashu = "0.9.0"
|
||||
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
|
@ -8,7 +8,7 @@ base58==2.1.1 ; python_version >= "3.7" and python_version < "4.0"
|
||||
bech32==1.2.0 ; python_version >= "3.7" and python_version < "4.0"
|
||||
bitstring==3.1.9 ; python_version >= "3.7" and python_version < "4.0"
|
||||
boltz-client==0.1.3 ; python_version >= "3.7" and python_version < "4.0"
|
||||
cashu==0.8.2 ; python_version >= "3.7" and python_version < "4.0"
|
||||
cashu==0.9.0 ; python_version >= "3.7" and python_version < "4.0"
|
||||
cerberus==1.3.4 ; python_version >= "3.7" and python_version < "4.0"
|
||||
certifi==2022.12.7 ; python_version >= "3.7" and python_version < "4.0"
|
||||
cffi==1.15.1 ; python_version >= "3.7" and python_version < "4.0"
|
||||
|
Loading…
Reference in New Issue
Block a user