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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user