mirror of
https://github.com/aljazceru/nutshell.git
synced 2026-02-03 15:54:20 +01:00
fst_ to frst_ and snd_ to scnd_
This commit is contained in:
@@ -126,10 +126,10 @@ class Ledger:
|
||||
|
||||
def _verify_outputs(self, total: int, amount: int, outputs: List[BlindedMessage]):
|
||||
"""Verifies the expected split was correctly computed"""
|
||||
fst_amt, snd_amt = total - amount, amount # we have two amounts to split to
|
||||
fst_outputs = amount_split(fst_amt)
|
||||
snd_outputs = amount_split(snd_amt)
|
||||
expected = fst_outputs + snd_outputs
|
||||
frst_amt, scnd_amt = total - amount, amount # we have two amounts to split to
|
||||
frst_outputs = amount_split(frst_amt)
|
||||
scnd_outputs = amount_split(scnd_amt)
|
||||
expected = frst_outputs + scnd_outputs
|
||||
given = [o.amount for o in outputs]
|
||||
return given == expected
|
||||
|
||||
|
||||
@@ -87,6 +87,6 @@ async def split(payload: SplitRequest):
|
||||
return CashuError(error=str(exc))
|
||||
if not split_return:
|
||||
return {"error": "there was a problem with the split."}
|
||||
fst_promises, snd_promises = split_return
|
||||
resp = PostSplitResponse(fst=fst_promises, snd=snd_promises)
|
||||
frst_promises, scnd_promises = split_return
|
||||
resp = PostSplitResponse(fst=frst_promises, snd=scnd_promises)
|
||||
return resp
|
||||
|
||||
@@ -195,7 +195,7 @@ async def receive(ctx, coin: str, lock: str):
|
||||
else:
|
||||
script, signature = None, None
|
||||
proofs = [Proof.from_dict(p) for p in json.loads(base64.urlsafe_b64decode(coin))]
|
||||
_, _ = await wallet.redeem(proofs, snd_script=script, snd_siganture=signature)
|
||||
_, _ = await wallet.redeem(proofs, scnd_script=script, scnd_siganture=signature)
|
||||
wallet.status()
|
||||
|
||||
|
||||
|
||||
@@ -142,32 +142,32 @@ class LedgerAPI:
|
||||
promises = [BlindedSignature.from_dict(p) for p in promises_list]
|
||||
return self._construct_proofs(promises, secrets, rs)
|
||||
|
||||
async def split(self, proofs, amount, snd_secret: str = None):
|
||||
async def split(self, proofs, amount, scnd_secret: str = None):
|
||||
"""Consume proofs and create new promises based on amount split.
|
||||
If snd_secret is None, random secrets will be generated for the tokens to keep (fst_outputs)
|
||||
and the promises to send (snd_outputs).
|
||||
If scnd_secret is None, random secrets will be generated for the tokens to keep (frst_outputs)
|
||||
and the promises to send (scnd_outputs).
|
||||
|
||||
If snd_secret is provided, the wallet will create blinded secrets with those to attach a
|
||||
If scnd_secret is provided, the wallet will create blinded secrets with those to attach a
|
||||
predefined spending condition to the tokens they want to send."""
|
||||
|
||||
total = sum([p["amount"] for p in proofs])
|
||||
fst_amt, snd_amt = total - amount, amount
|
||||
fst_outputs = amount_split(fst_amt)
|
||||
snd_outputs = amount_split(snd_amt)
|
||||
frst_amt, scnd_amt = total - amount, amount
|
||||
frst_outputs = amount_split(frst_amt)
|
||||
scnd_outputs = amount_split(scnd_amt)
|
||||
|
||||
amounts = fst_outputs + snd_outputs
|
||||
if snd_secret is None:
|
||||
amounts = frst_outputs + scnd_outputs
|
||||
if scnd_secret is None:
|
||||
secrets = [self._generate_secret() for _ in range(len(amounts))]
|
||||
else:
|
||||
snd_secrets = self.generate_secrets(snd_secret, len(snd_outputs))
|
||||
logger.debug(f"Creating proofs with custom secrets: {snd_secrets}")
|
||||
assert len(snd_secrets) == len(
|
||||
snd_outputs
|
||||
), "number of snd_secrets does not match number of ouptus."
|
||||
scnd_secrets = self.generate_secrets(scnd_secret, len(scnd_outputs))
|
||||
logger.debug(f"Creating proofs with custom secrets: {scnd_secrets}")
|
||||
assert len(scnd_secrets) == len(
|
||||
scnd_outputs
|
||||
), "number of scnd_secrets does not match number of ouptus."
|
||||
# append predefined secrets (to send) to random secrets (to keep)
|
||||
secrets = [
|
||||
self._generate_secret() for s in range(len(fst_outputs))
|
||||
] + snd_secrets
|
||||
self._generate_secret() for s in range(len(frst_outputs))
|
||||
] + scnd_secrets
|
||||
|
||||
assert len(secrets) == len(
|
||||
amounts
|
||||
@@ -192,14 +192,14 @@ class LedgerAPI:
|
||||
promises_fst = [BlindedSignature.from_dict(p) for p in promises_dict["fst"]]
|
||||
promises_snd = [BlindedSignature.from_dict(p) for p in promises_dict["snd"]]
|
||||
# Construct proofs from promises (i.e., unblind signatures)
|
||||
fst_proofs = self._construct_proofs(
|
||||
frst_proofs = self._construct_proofs(
|
||||
promises_fst, secrets[: len(promises_fst)], rs[: len(promises_fst)]
|
||||
)
|
||||
snd_proofs = self._construct_proofs(
|
||||
scnd_proofs = self._construct_proofs(
|
||||
promises_snd, secrets[len(promises_fst) :], rs[len(promises_fst) :]
|
||||
)
|
||||
|
||||
return fst_proofs, snd_proofs
|
||||
return frst_proofs, scnd_proofs
|
||||
|
||||
async def check_spendable(self, proofs: List[Proof]):
|
||||
payload = CheckRequest(proofs=proofs)
|
||||
@@ -253,35 +253,35 @@ class Wallet(LedgerAPI):
|
||||
async def redeem(
|
||||
self,
|
||||
proofs: List[Proof],
|
||||
snd_script: str = None,
|
||||
snd_siganture: str = None,
|
||||
scnd_script: str = None,
|
||||
scnd_siganture: str = None,
|
||||
):
|
||||
if snd_script and snd_siganture:
|
||||
logger.debug(f"Unlock script: {snd_script}")
|
||||
if scnd_script and scnd_siganture:
|
||||
logger.debug(f"Unlock script: {scnd_script}")
|
||||
# attach unlock scripts to proofs
|
||||
for p in proofs:
|
||||
p.script = P2SHScript(script=snd_script, signature=snd_siganture)
|
||||
p.script = P2SHScript(script=scnd_script, signature=scnd_siganture)
|
||||
return await self.split(proofs, sum(p["amount"] for p in proofs))
|
||||
|
||||
async def split(
|
||||
self,
|
||||
proofs: List[Proof],
|
||||
amount: int,
|
||||
snd_secret: str = None,
|
||||
scnd_secret: str = None,
|
||||
):
|
||||
assert len(proofs) > 0, ValueError("no proofs provided.")
|
||||
fst_proofs, snd_proofs = await super().split(proofs, amount, snd_secret)
|
||||
if len(fst_proofs) == 0 and len(snd_proofs) == 0:
|
||||
frst_proofs, scnd_proofs = await super().split(proofs, amount, scnd_secret)
|
||||
if len(frst_proofs) == 0 and len(scnd_proofs) == 0:
|
||||
raise Exception("received no splits.")
|
||||
used_secrets = [p["secret"] for p in proofs]
|
||||
self.proofs = list(
|
||||
filter(lambda p: p["secret"] not in used_secrets, self.proofs)
|
||||
)
|
||||
self.proofs += fst_proofs + snd_proofs
|
||||
await self._store_proofs(fst_proofs + snd_proofs)
|
||||
self.proofs += frst_proofs + scnd_proofs
|
||||
await self._store_proofs(frst_proofs + scnd_proofs)
|
||||
for proof in proofs:
|
||||
await invalidate_proof(proof, db=self.db)
|
||||
return fst_proofs, snd_proofs
|
||||
return frst_proofs, scnd_proofs
|
||||
|
||||
async def pay_lightning(self, proofs: List[Proof], amount: int, invoice: str):
|
||||
"""Pays a lightning invoice"""
|
||||
@@ -303,14 +303,14 @@ class Wallet(LedgerAPI):
|
||||
).decode()
|
||||
return token
|
||||
|
||||
async def split_to_send(self, proofs: List[Proof], amount, snd_secret: str = None):
|
||||
async def split_to_send(self, proofs: List[Proof], amount, scnd_secret: str = None):
|
||||
"""Like self.split but only considers non-reserved tokens."""
|
||||
if snd_secret:
|
||||
logger.debug(f"Spending conditions: {snd_secret}")
|
||||
if scnd_secret:
|
||||
logger.debug(f"Spending conditions: {scnd_secret}")
|
||||
if len([p for p in proofs if not p.reserved]) <= 0:
|
||||
raise Exception("balance too low.")
|
||||
return await self.split(
|
||||
[p for p in proofs if not p.reserved], amount, snd_secret
|
||||
[p for p in proofs if not p.reserved], amount, scnd_secret
|
||||
)
|
||||
|
||||
async def set_reserved(self, proofs: List[Proof], reserved: bool):
|
||||
|
||||
@@ -48,7 +48,7 @@ async def run_test():
|
||||
proofs += await wallet1.mint(63)
|
||||
assert wallet1.balance == 64 + 63
|
||||
|
||||
w1_fst_proofs, w1_snd_proofs = await wallet1.split(wallet1.proofs, 65)
|
||||
w1_frst_proofs, w1_scnd_proofs = await wallet1.split(wallet1.proofs, 65)
|
||||
assert wallet1.balance == 63 + 64
|
||||
wallet1.status()
|
||||
|
||||
@@ -60,12 +60,12 @@ async def run_test():
|
||||
assert wallet1.balance == 63 + 64
|
||||
wallet1.status()
|
||||
|
||||
w1_fst_proofs, w1_snd_proofs = await wallet1.split(wallet1.proofs, 20)
|
||||
w1_frst_proofs, w1_scnd_proofs = await wallet1.split(wallet1.proofs, 20)
|
||||
# we expect 44 and 20 -> [4, 8, 32], [4, 16]
|
||||
print(w1_fst_proofs)
|
||||
print(w1_snd_proofs)
|
||||
# assert [p["amount"] for p in w1_fst_proofs] == [4, 8, 32]
|
||||
assert [p["amount"] for p in w1_snd_proofs] == [4, 16]
|
||||
print(w1_frst_proofs)
|
||||
print(w1_scnd_proofs)
|
||||
# assert [p["amount"] for p in w1_frst_proofs] == [4, 8, 32]
|
||||
assert [p["amount"] for p in w1_scnd_proofs] == [4, 16]
|
||||
assert wallet1.balance == 63 + 64
|
||||
wallet1.status()
|
||||
|
||||
@@ -79,29 +79,29 @@ async def run_test():
|
||||
wallet1.status()
|
||||
|
||||
# Redeem the tokens in wallet2
|
||||
w2_fst_proofs, w2_snd_proofs = await wallet2.redeem(w1_snd_proofs)
|
||||
print(w2_fst_proofs)
|
||||
print(w2_snd_proofs)
|
||||
w2_frst_proofs, w2_scnd_proofs = await wallet2.redeem(w1_scnd_proofs)
|
||||
print(w2_frst_proofs)
|
||||
print(w2_scnd_proofs)
|
||||
assert wallet1.balance == 63 + 64
|
||||
assert wallet2.balance == 20
|
||||
wallet2.status()
|
||||
|
||||
# wallet1 invalidates his proofs
|
||||
await wallet1.invalidate(w1_snd_proofs)
|
||||
await wallet1.invalidate(w1_scnd_proofs)
|
||||
assert wallet1.balance == 63 + 64 - 20
|
||||
wallet1.status()
|
||||
|
||||
w1_fst_proofs2, w1_snd_proofs2 = await wallet1.split(w1_fst_proofs, 5)
|
||||
w1_frst_proofs2, w1_scnd_proofs2 = await wallet1.split(w1_frst_proofs, 5)
|
||||
# we expect 15 and 5 -> [1, 2, 4, 8], [1, 4]
|
||||
print(w1_fst_proofs2)
|
||||
print(w1_snd_proofs2)
|
||||
print(w1_frst_proofs2)
|
||||
print(w1_scnd_proofs2)
|
||||
assert wallet1.balance == 63 + 64 - 20
|
||||
wallet1.status()
|
||||
|
||||
# Error: We try to double-spend and it fails
|
||||
await assert_err(
|
||||
wallet1.split(w1_snd_proofs, 5),
|
||||
f"Mint Error: tokens already spent. Secret: {w1_snd_proofs[0]['secret']}",
|
||||
wallet1.split(w1_scnd_proofs, 5),
|
||||
f"Mint Error: tokens already spent. Secret: {w1_scnd_proofs[0]['secret']}",
|
||||
)
|
||||
|
||||
assert wallet1.balance == 63 + 64 - 20
|
||||
@@ -111,23 +111,23 @@ async def run_test():
|
||||
assert wallet2.proof_amounts() == [4, 16]
|
||||
|
||||
# manipulate the proof amount
|
||||
# w1_fst_proofs2_manipulated = w1_fst_proofs2.copy()
|
||||
# w1_fst_proofs2_manipulated[0]["amount"] = 123
|
||||
# w1_frst_proofs2_manipulated = w1_frst_proofs2.copy()
|
||||
# w1_frst_proofs2_manipulated[0]["amount"] = 123
|
||||
# await assert_err(
|
||||
# wallet1.split(w1_fst_proofs2_manipulated, 20),
|
||||
# wallet1.split(w1_frst_proofs2_manipulated, 20),
|
||||
# "Error: 123",
|
||||
# )
|
||||
|
||||
# try to split an invalid amount
|
||||
await assert_err(
|
||||
wallet1.split(w1_snd_proofs, -500),
|
||||
wallet1.split(w1_scnd_proofs, -500),
|
||||
"Mint Error: invalid split amount: -500",
|
||||
)
|
||||
|
||||
# mint with secrets
|
||||
secret = f"asdasd_{time.time()}"
|
||||
w1_fst_proofs, w1_snd_proofs = await wallet1.split(
|
||||
wallet1.proofs, 65, snd_secret=secret
|
||||
w1_frst_proofs, w1_scnd_proofs = await wallet1.split(
|
||||
wallet1.proofs, 65, scnd_secret=secret
|
||||
)
|
||||
|
||||
# p2sh test
|
||||
@@ -136,15 +136,15 @@ async def run_test():
|
||||
lock = f"P2SH:{txin_p2sh_address}"
|
||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, lock)
|
||||
_, _ = await wallet2.redeem(
|
||||
send_proofs, snd_script=p2shscript.script, snd_siganture=p2shscript.signature
|
||||
send_proofs, scnd_script=p2shscript.script, scnd_siganture=p2shscript.signature
|
||||
)
|
||||
|
||||
# strip away the secrets
|
||||
w1_snd_proofs_manipulated = w1_snd_proofs.copy()
|
||||
for p in w1_snd_proofs_manipulated:
|
||||
w1_scnd_proofs_manipulated = w1_scnd_proofs.copy()
|
||||
for p in w1_scnd_proofs_manipulated:
|
||||
p.secret = ""
|
||||
await assert_err(
|
||||
wallet2.redeem(w1_snd_proofs_manipulated),
|
||||
wallet2.redeem(w1_scnd_proofs_manipulated),
|
||||
"Mint Error: no secret in proof.",
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user