mirror of
https://github.com/aljazceru/nutshell.git
synced 2025-12-20 18:44:20 +01:00
Coalesce all witness fields to Proof.witness (#342)
* call proofs field witness * test p2pk sig_all=True * outputs also use witness field
This commit is contained in:
@@ -9,7 +9,6 @@ from pydantic import BaseModel
|
|||||||
from .crypto.keys import derive_keys, derive_keyset_id, derive_pubkeys
|
from .crypto.keys import derive_keys, derive_keyset_id, derive_pubkeys
|
||||||
from .crypto.secp import PrivateKey, PublicKey
|
from .crypto.secp import PrivateKey, PublicKey
|
||||||
from .legacy import derive_keys_backwards_compatible_insecure_pre_0_12
|
from .legacy import derive_keys_backwards_compatible_insecure_pre_0_12
|
||||||
from .p2pk import P2SHScript
|
|
||||||
|
|
||||||
|
|
||||||
class DLEQ(BaseModel):
|
class DLEQ(BaseModel):
|
||||||
@@ -34,6 +33,41 @@ class DLEQWallet(BaseModel):
|
|||||||
# ------- PROOFS -------
|
# ------- PROOFS -------
|
||||||
|
|
||||||
|
|
||||||
|
class HTLCWitness(BaseModel):
|
||||||
|
preimage: Optional[str] = None
|
||||||
|
signature: Optional[str] = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_witness(cls, witness: str):
|
||||||
|
return cls(**json.loads(witness))
|
||||||
|
|
||||||
|
|
||||||
|
class P2SHWitness(BaseModel):
|
||||||
|
"""
|
||||||
|
Unlocks P2SH spending condition of a Proof
|
||||||
|
"""
|
||||||
|
|
||||||
|
script: str
|
||||||
|
signature: str
|
||||||
|
address: Union[str, None] = None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_witness(cls, witness: str):
|
||||||
|
return cls(**json.loads(witness))
|
||||||
|
|
||||||
|
|
||||||
|
class P2PKWitness(BaseModel):
|
||||||
|
"""
|
||||||
|
Unlocks P2PK spending condition of a Proof
|
||||||
|
"""
|
||||||
|
|
||||||
|
signatures: List[str]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def from_witness(cls, witness: str):
|
||||||
|
return cls(**json.loads(witness))
|
||||||
|
|
||||||
|
|
||||||
class Proof(BaseModel):
|
class Proof(BaseModel):
|
||||||
"""
|
"""
|
||||||
Value token
|
Value token
|
||||||
@@ -46,10 +80,11 @@ class Proof(BaseModel):
|
|||||||
C: str = "" # signature on secret, unblinded by wallet
|
C: str = "" # signature on secret, unblinded by wallet
|
||||||
dleq: Union[DLEQWallet, None] = None # DLEQ proof
|
dleq: Union[DLEQWallet, None] = None # DLEQ proof
|
||||||
|
|
||||||
p2pksigs: Union[List[str], None] = [] # P2PK signature
|
witness: Union[None, str] = "" # witness for spending condition
|
||||||
p2shscript: Union[P2SHScript, None] = None # P2SH spending condition
|
# p2pksigs: Union[List[str], None] = [] # P2PK signature
|
||||||
htlcpreimage: Union[str, None] = None # HTLC unlocking preimage
|
# p2shscript: Union[P2SHWitness, None] = None # P2SH spending condition
|
||||||
htlcsignature: Union[str, None] = None # HTLC unlocking signature
|
# htlcpreimage: Union[str, None] = None # HTLC unlocking preimage
|
||||||
|
# htlcsignature: Union[str, None] = None # HTLC unlocking signature
|
||||||
# whether this proof is reserved for sending, used for coin management in the wallet
|
# whether this proof is reserved for sending, used for coin management in the wallet
|
||||||
reserved: Union[None, bool] = False
|
reserved: Union[None, bool] = False
|
||||||
# unique ID of send attempt, used for grouping pending tokens in the wallet
|
# unique ID of send attempt, used for grouping pending tokens in the wallet
|
||||||
@@ -93,6 +128,21 @@ class Proof(BaseModel):
|
|||||||
def __setitem__(self, key, val):
|
def __setitem__(self, key, val):
|
||||||
self.__setattr__(key, val)
|
self.__setattr__(key, val)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def p2pksigs(self) -> List[str]:
|
||||||
|
assert self.witness, "Witness is missing"
|
||||||
|
return P2PKWitness.from_witness(self.witness).signatures
|
||||||
|
|
||||||
|
@property
|
||||||
|
def p2shscript(self) -> P2SHWitness:
|
||||||
|
assert self.witness, "Witness is missing"
|
||||||
|
return P2SHWitness.from_witness(self.witness)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def htlcpreimage(self) -> Union[str, None]:
|
||||||
|
assert self.witness, "Witness is missing"
|
||||||
|
return HTLCWitness.from_witness(self.witness).preimage
|
||||||
|
|
||||||
|
|
||||||
class Proofs(BaseModel):
|
class Proofs(BaseModel):
|
||||||
# NOTE: not used in Pydantic validation
|
# NOTE: not used in Pydantic validation
|
||||||
@@ -106,7 +156,12 @@ class BlindedMessage(BaseModel):
|
|||||||
|
|
||||||
amount: int
|
amount: int
|
||||||
B_: str # Hex-encoded blinded message
|
B_: str # Hex-encoded blinded message
|
||||||
p2pksigs: Union[List[str], None] = None # signature for p2pk with SIG_ALL
|
witness: Union[str, None] = None # witnesses (used for P2PK with SIG_ALL)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def p2pksigs(self) -> List[str]:
|
||||||
|
assert self.witness, "Witness is missing"
|
||||||
|
return P2PKWitness.from_witness(self.witness).signatures
|
||||||
|
|
||||||
|
|
||||||
class BlindedSignature(BaseModel):
|
class BlindedSignature(BaseModel):
|
||||||
@@ -206,19 +261,6 @@ class PostSplitRequest(BaseModel):
|
|||||||
proofs: List[Proof]
|
proofs: List[Proof]
|
||||||
amount: Optional[int] = None # deprecated since 0.13.0
|
amount: Optional[int] = None # deprecated since 0.13.0
|
||||||
outputs: List[BlindedMessage]
|
outputs: List[BlindedMessage]
|
||||||
# signature: Optional[str] = None
|
|
||||||
|
|
||||||
# def sign(self, private_key: PrivateKey):
|
|
||||||
# """
|
|
||||||
# Create a signed split request. The signature is over the `proofs` and `outputs` fields.
|
|
||||||
# """
|
|
||||||
# # message = json.dumps(self.proofs).encode("utf-8") + json.dumps(
|
|
||||||
# # self.outputs
|
|
||||||
# # ).encode("utf-8")
|
|
||||||
# message = json.dumps(self.dict(include={"proofs": ..., "outputs": ...})).encode(
|
|
||||||
# "utf-8"
|
|
||||||
# )
|
|
||||||
# self.signature = sign_p2pk_sign(message, private_key)
|
|
||||||
|
|
||||||
|
|
||||||
class PostSplitResponse(BaseModel):
|
class PostSplitResponse(BaseModel):
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import time
|
|||||||
from typing import List, Union
|
from typing import List, Union
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
from .crypto.secp import PrivateKey, PublicKey
|
from .crypto.secp import PrivateKey, PublicKey
|
||||||
from .secret import Secret, SecretKind
|
from .secret import Secret, SecretKind
|
||||||
@@ -64,16 +63,6 @@ class P2PKSecret(Secret):
|
|||||||
return int(n_sigs) if n_sigs else None
|
return int(n_sigs) if n_sigs else None
|
||||||
|
|
||||||
|
|
||||||
class P2SHScript(BaseModel):
|
|
||||||
"""
|
|
||||||
Unlocks P2SH spending condition of a Proof
|
|
||||||
"""
|
|
||||||
|
|
||||||
script: str
|
|
||||||
signature: str
|
|
||||||
address: Union[str, None] = None
|
|
||||||
|
|
||||||
|
|
||||||
def sign_p2pk_sign(message: bytes, private_key: PrivateKey):
|
def sign_p2pk_sign(message: bytes, private_key: PrivateKey):
|
||||||
# ecdsa version
|
# ecdsa version
|
||||||
# signature = private_key.ecdsa_serialize(private_key.ecdsa_sign(message))
|
# signature = private_key.ecdsa_serialize(private_key.ecdsa_sign(message))
|
||||||
|
|||||||
@@ -4,10 +4,7 @@ from typing import List
|
|||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
from ..core.base import (
|
from ..core.base import BlindedMessage, HTLCWitness, Proof
|
||||||
BlindedMessage,
|
|
||||||
Proof,
|
|
||||||
)
|
|
||||||
from ..core.crypto.secp import PublicKey
|
from ..core.crypto.secp import PublicKey
|
||||||
from ..core.errors import (
|
from ..core.errors import (
|
||||||
TransactionError,
|
TransactionError,
|
||||||
@@ -149,14 +146,16 @@ class LedgerSpendingConditions:
|
|||||||
if htlc_secret.locktime and htlc_secret.locktime < time.time():
|
if htlc_secret.locktime and htlc_secret.locktime < time.time():
|
||||||
refund_pubkeys = htlc_secret.tags.get_tag_all("refund")
|
refund_pubkeys = htlc_secret.tags.get_tag_all("refund")
|
||||||
if refund_pubkeys:
|
if refund_pubkeys:
|
||||||
assert proof.htlcsignature, TransactionError(
|
assert proof.witness, TransactionError("no HTLC refund signature.")
|
||||||
|
signature = HTLCWitness.from_witness(proof.witness).signature
|
||||||
|
assert signature, TransactionError(
|
||||||
"no HTLC refund signature provided"
|
"no HTLC refund signature provided"
|
||||||
)
|
)
|
||||||
for pubkey in refund_pubkeys:
|
for pubkey in refund_pubkeys:
|
||||||
if verify_p2pk_signature(
|
if verify_p2pk_signature(
|
||||||
message=htlc_secret.serialize().encode("utf-8"),
|
message=htlc_secret.serialize().encode("utf-8"),
|
||||||
pubkey=PublicKey(bytes.fromhex(pubkey), raw=True),
|
pubkey=PublicKey(bytes.fromhex(pubkey), raw=True),
|
||||||
signature=bytes.fromhex(proof.htlcsignature),
|
signature=bytes.fromhex(signature),
|
||||||
):
|
):
|
||||||
# a signature matches
|
# a signature matches
|
||||||
return True
|
return True
|
||||||
@@ -176,14 +175,16 @@ class LedgerSpendingConditions:
|
|||||||
# then we check whether a signature is required
|
# then we check whether a signature is required
|
||||||
hashlock_pubkeys = htlc_secret.tags.get_tag_all("pubkeys")
|
hashlock_pubkeys = htlc_secret.tags.get_tag_all("pubkeys")
|
||||||
if hashlock_pubkeys:
|
if hashlock_pubkeys:
|
||||||
assert proof.htlcsignature, TransactionError(
|
assert proof.witness, TransactionError("no HTLC hash lock signature.")
|
||||||
|
signature = HTLCWitness.from_witness(proof.witness).signature
|
||||||
|
assert signature, TransactionError(
|
||||||
"HTLC no hash lock signatures provided."
|
"HTLC no hash lock signatures provided."
|
||||||
)
|
)
|
||||||
for pubkey in hashlock_pubkeys:
|
for pubkey in hashlock_pubkeys:
|
||||||
if verify_p2pk_signature(
|
if verify_p2pk_signature(
|
||||||
message=htlc_secret.serialize().encode("utf-8"),
|
message=htlc_secret.serialize().encode("utf-8"),
|
||||||
pubkey=PublicKey(bytes.fromhex(pubkey), raw=True),
|
pubkey=PublicKey(bytes.fromhex(pubkey), raw=True),
|
||||||
signature=bytes.fromhex(proof.htlcsignature),
|
signature=bytes.fromhex(signature),
|
||||||
):
|
):
|
||||||
# a signature matches
|
# a signature matches
|
||||||
return True
|
return True
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ from typing import Dict, List, Optional
|
|||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
from ...core.base import Invoice, P2SHScript
|
from ...core.base import Invoice, P2SHWitness
|
||||||
|
|
||||||
|
|
||||||
class PayResponse(BaseModel):
|
class PayResponse(BaseModel):
|
||||||
@@ -54,7 +54,7 @@ class LockResponse(BaseModel):
|
|||||||
|
|
||||||
|
|
||||||
class LocksResponse(BaseModel):
|
class LocksResponse(BaseModel):
|
||||||
locks: List[P2SHScript]
|
locks: List[P2SHWitness]
|
||||||
|
|
||||||
|
|
||||||
class InvoicesResponse(BaseModel):
|
class InvoicesResponse(BaseModel):
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import json
|
|||||||
import time
|
import time
|
||||||
from typing import Any, List, Optional, Tuple
|
from typing import Any, List, Optional, Tuple
|
||||||
|
|
||||||
from ..core.base import Invoice, P2SHScript, Proof, WalletKeyset
|
from ..core.base import Invoice, P2SHWitness, Proof, WalletKeyset
|
||||||
from ..core.db import Connection, Database
|
from ..core.db import Connection, Database
|
||||||
|
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ async def secret_used(
|
|||||||
|
|
||||||
|
|
||||||
async def store_p2sh(
|
async def store_p2sh(
|
||||||
p2sh: P2SHScript,
|
p2sh: P2SHWitness,
|
||||||
db: Database,
|
db: Database,
|
||||||
conn: Optional[Connection] = None,
|
conn: Optional[Connection] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
@@ -146,7 +146,7 @@ async def get_unused_locks(
|
|||||||
address: str = "",
|
address: str = "",
|
||||||
db: Optional[Database] = None,
|
db: Optional[Database] = None,
|
||||||
conn: Optional[Connection] = None,
|
conn: Optional[Connection] = None,
|
||||||
) -> List[P2SHScript]:
|
) -> List[P2SHWitness]:
|
||||||
clause: List[str] = []
|
clause: List[str] = []
|
||||||
args: List[str] = []
|
args: List[str] = []
|
||||||
|
|
||||||
@@ -167,11 +167,11 @@ async def get_unused_locks(
|
|||||||
""",
|
""",
|
||||||
tuple(args),
|
tuple(args),
|
||||||
)
|
)
|
||||||
return [P2SHScript(**r) for r in rows]
|
return [P2SHWitness(**r) for r in rows]
|
||||||
|
|
||||||
|
|
||||||
async def update_p2sh_used(
|
async def update_p2sh_used(
|
||||||
p2sh: P2SHScript,
|
p2sh: P2SHWitness,
|
||||||
used: bool,
|
used: bool,
|
||||||
db: Optional[Database] = None,
|
db: Optional[Database] = None,
|
||||||
conn: Optional[Connection] = None,
|
conn: Optional[Connection] = None,
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ from datetime import datetime, timedelta
|
|||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
from ..core import bolt11 as bolt11
|
from ..core import bolt11 as bolt11
|
||||||
from ..core.base import (
|
from ..core.base import HTLCWitness, Proof
|
||||||
Proof,
|
|
||||||
)
|
|
||||||
from ..core.db import Database
|
from ..core.db import Database
|
||||||
from ..core.htlc import (
|
from ..core.htlc import (
|
||||||
HTLCSecret,
|
HTLCSecret,
|
||||||
@@ -51,6 +49,6 @@ class WalletHTLC(SupportsDb):
|
|||||||
async def add_htlc_preimage_to_proofs(
|
async def add_htlc_preimage_to_proofs(
|
||||||
self, proofs: List[Proof], preimage: str
|
self, proofs: List[Proof], preimage: str
|
||||||
) -> List[Proof]:
|
) -> List[Proof]:
|
||||||
for p, s in zip(proofs, preimage):
|
for p in proofs:
|
||||||
p.htlcpreimage = s
|
p.witness = HTLCWitness(preimage=preimage).json()
|
||||||
return proofs
|
return proofs
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ from loguru import logger
|
|||||||
from ..core import bolt11 as bolt11
|
from ..core import bolt11 as bolt11
|
||||||
from ..core.base import (
|
from ..core.base import (
|
||||||
BlindedMessage,
|
BlindedMessage,
|
||||||
|
P2PKWitness,
|
||||||
|
P2SHWitness,
|
||||||
Proof,
|
Proof,
|
||||||
)
|
)
|
||||||
from ..core.crypto.secp import PrivateKey
|
from ..core.crypto.secp import PrivateKey
|
||||||
from ..core.db import Database
|
from ..core.db import Database
|
||||||
from ..core.p2pk import (
|
from ..core.p2pk import (
|
||||||
P2PKSecret,
|
P2PKSecret,
|
||||||
P2SHScript,
|
|
||||||
SigFlags,
|
SigFlags,
|
||||||
sign_p2pk_sign,
|
sign_p2pk_sign,
|
||||||
)
|
)
|
||||||
@@ -44,7 +45,7 @@ class WalletP2PK(SupportsPrivateKey, SupportsDb):
|
|||||||
txin_signature = step2_carol_sign_tx(txin_redeemScript, alice_privkey).scriptSig
|
txin_signature = step2_carol_sign_tx(txin_redeemScript, alice_privkey).scriptSig
|
||||||
txin_redeemScript_b64 = base64.urlsafe_b64encode(txin_redeemScript).decode()
|
txin_redeemScript_b64 = base64.urlsafe_b64encode(txin_redeemScript).decode()
|
||||||
txin_signature_b64 = base64.urlsafe_b64encode(txin_signature).decode()
|
txin_signature_b64 = base64.urlsafe_b64encode(txin_signature).decode()
|
||||||
p2shScript = P2SHScript(
|
p2shScript = P2SHWitness(
|
||||||
script=txin_redeemScript_b64,
|
script=txin_redeemScript_b64,
|
||||||
signature=txin_signature_b64,
|
signature=txin_signature_b64,
|
||||||
address=str(txin_p2sh_address),
|
address=str(txin_p2sh_address),
|
||||||
@@ -154,7 +155,7 @@ class WalletP2PK(SupportsPrivateKey, SupportsDb):
|
|||||||
"""
|
"""
|
||||||
p2pk_signatures = await self.sign_p2pk_outputs(outputs)
|
p2pk_signatures = await self.sign_p2pk_outputs(outputs)
|
||||||
for o, s in zip(outputs, p2pk_signatures):
|
for o, s in zip(outputs, p2pk_signatures):
|
||||||
o.p2pksigs = [s]
|
o.witness = P2PKWitness(signatures=[s]).json()
|
||||||
return outputs
|
return outputs
|
||||||
|
|
||||||
async def add_witnesses_to_outputs(
|
async def add_witnesses_to_outputs(
|
||||||
@@ -201,7 +202,7 @@ class WalletP2PK(SupportsPrivateKey, SupportsDb):
|
|||||||
|
|
||||||
# attach unlock scripts to proofs
|
# attach unlock scripts to proofs
|
||||||
for p in proofs:
|
for p in proofs:
|
||||||
p.p2shscript = P2SHScript(script=p2sh_script, signature=p2sh_signature)
|
p.witness = P2SHWitness(script=p2sh_script, signature=p2sh_signature).json()
|
||||||
return proofs
|
return proofs
|
||||||
|
|
||||||
async def add_p2pk_witnesses_to_proofs(self, proofs: List[Proof]) -> List[Proof]:
|
async def add_p2pk_witnesses_to_proofs(self, proofs: List[Proof]) -> List[Proof]:
|
||||||
@@ -211,10 +212,12 @@ class WalletP2PK(SupportsPrivateKey, SupportsDb):
|
|||||||
# attach unlock signatures to proofs
|
# attach unlock signatures to proofs
|
||||||
assert len(proofs) == len(p2pk_signatures), "wrong number of signatures"
|
assert len(proofs) == len(p2pk_signatures), "wrong number of signatures"
|
||||||
for p, s in zip(proofs, p2pk_signatures):
|
for p, s in zip(proofs, p2pk_signatures):
|
||||||
if p.p2pksigs:
|
# if there are already signatures, append
|
||||||
p.p2pksigs.append(s)
|
if p.witness and P2PKWitness.from_witness(p.witness).signatures:
|
||||||
|
signatures = P2PKWitness.from_witness(p.witness).signatures
|
||||||
|
p.witness = P2PKWitness(signatures=signatures + [s]).json()
|
||||||
else:
|
else:
|
||||||
p.p2pksigs = [s]
|
p.witness = P2PKWitness(signatures=[s]).json()
|
||||||
return proofs
|
return proofs
|
||||||
|
|
||||||
async def add_witnesses_to_proofs(self, proofs: List[Proof]) -> List[Proof]:
|
async def add_witnesses_to_proofs(self, proofs: List[Proof]) -> List[Proof]:
|
||||||
|
|||||||
@@ -400,10 +400,7 @@ class LedgerAPI(object):
|
|||||||
"amount",
|
"amount",
|
||||||
"secret",
|
"secret",
|
||||||
"C",
|
"C",
|
||||||
"p2shscript",
|
"witness",
|
||||||
"p2pksigs",
|
|
||||||
"htlcpreimage",
|
|
||||||
"htlcsignature",
|
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
"outputs": ...,
|
"outputs": ...,
|
||||||
@@ -472,7 +469,7 @@ class LedgerAPI(object):
|
|||||||
|
|
||||||
def _meltrequest_include_fields(proofs: List[Proof]):
|
def _meltrequest_include_fields(proofs: List[Proof]):
|
||||||
"""strips away fields from the model that aren't necessary for the /melt"""
|
"""strips away fields from the model that aren't necessary for the /melt"""
|
||||||
proofs_include = {"id", "amount", "secret", "C", "script"}
|
proofs_include = {"id", "amount", "secret", "C", "witness"}
|
||||||
return {
|
return {
|
||||||
"proofs": {i: proofs_include for i in range(len(proofs))},
|
"proofs": {i: proofs_include for i in range(len(proofs))},
|
||||||
"pr": ...,
|
"pr": ...,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from typing import List
|
|||||||
import pytest
|
import pytest
|
||||||
import pytest_asyncio
|
import pytest_asyncio
|
||||||
|
|
||||||
from cashu.core.base import Proof
|
from cashu.core.base import HTLCWitness, Proof
|
||||||
from cashu.core.crypto.secp import PrivateKey
|
from cashu.core.crypto.secp import PrivateKey
|
||||||
from cashu.core.htlc import HTLCSecret
|
from cashu.core.htlc import HTLCSecret
|
||||||
from cashu.core.migrations import migrate_databases
|
from cashu.core.migrations import migrate_databases
|
||||||
@@ -89,7 +89,7 @@ async def test_htlc_redeem_with_preimage(wallet1: Wallet, wallet2: Wallet):
|
|||||||
# p2pk test
|
# p2pk test
|
||||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||||
for p in send_proofs:
|
for p in send_proofs:
|
||||||
p.htlcpreimage = preimage
|
p.witness = HTLCWitness(preimage=preimage).json()
|
||||||
await wallet2.redeem(send_proofs)
|
await wallet2.redeem(send_proofs)
|
||||||
|
|
||||||
|
|
||||||
@@ -99,11 +99,13 @@ async def test_htlc_redeem_with_wrong_preimage(wallet1: Wallet, wallet2: Wallet)
|
|||||||
await wallet1.mint(64, hash=invoice.hash)
|
await wallet1.mint(64, hash=invoice.hash)
|
||||||
preimage = "00000000000000000000000000000000"
|
preimage = "00000000000000000000000000000000"
|
||||||
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
# preimage_hash = hashlib.sha256(bytes.fromhex(preimage)).hexdigest()
|
||||||
secret = await wallet1.create_htlc_lock(preimage=preimage[:-5] + "11111")
|
secret = await wallet1.create_htlc_lock(
|
||||||
|
preimage=preimage[:-5] + "11111"
|
||||||
|
) # wrong preimage
|
||||||
# p2pk test
|
# p2pk test
|
||||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||||
for p in send_proofs:
|
for p in send_proofs:
|
||||||
p.htlcpreimage = preimage
|
p.witness = HTLCWitness(preimage=preimage).json()
|
||||||
await assert_err(
|
await assert_err(
|
||||||
wallet2.redeem(send_proofs), "Mint Error: HTLC preimage does not match"
|
wallet2.redeem(send_proofs), "Mint Error: HTLC preimage does not match"
|
||||||
)
|
)
|
||||||
@@ -122,7 +124,7 @@ async def test_htlc_redeem_with_no_signature(wallet1: Wallet, wallet2: Wallet):
|
|||||||
# p2pk test
|
# p2pk test
|
||||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||||
for p in send_proofs:
|
for p in send_proofs:
|
||||||
p.htlcpreimage = preimage
|
p.witness = HTLCWitness(preimage=preimage).json()
|
||||||
await assert_err(
|
await assert_err(
|
||||||
wallet2.redeem(send_proofs),
|
wallet2.redeem(send_proofs),
|
||||||
"Mint Error: HTLC no hash lock signatures provided.",
|
"Mint Error: HTLC no hash lock signatures provided.",
|
||||||
@@ -144,8 +146,9 @@ async def test_htlc_redeem_with_wrong_signature(wallet1: Wallet, wallet2: Wallet
|
|||||||
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
_, send_proofs = await wallet1.split_to_send(wallet1.proofs, 8, secret_lock=secret)
|
||||||
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
||||||
for p, s in zip(send_proofs, signatures):
|
for p, s in zip(send_proofs, signatures):
|
||||||
p.htlcpreimage = preimage
|
p.witness = HTLCWitness(
|
||||||
p.htlcsignature = s[:-5] + "11111" # wrong signature
|
preimage=preimage, signature=s[:-5] + "11111"
|
||||||
|
).json() # wrong signature
|
||||||
|
|
||||||
await assert_err(
|
await assert_err(
|
||||||
wallet2.redeem(send_proofs),
|
wallet2.redeem(send_proofs),
|
||||||
@@ -168,8 +171,7 @@ async def test_htlc_redeem_with_correct_signature(wallet1: Wallet, wallet2: Wall
|
|||||||
|
|
||||||
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
||||||
for p, s in zip(send_proofs, signatures):
|
for p, s in zip(send_proofs, signatures):
|
||||||
p.htlcpreimage = preimage
|
p.witness = HTLCWitness(preimage=preimage, signature=s).json()
|
||||||
p.htlcsignature = s
|
|
||||||
|
|
||||||
await wallet2.redeem(send_proofs)
|
await wallet2.redeem(send_proofs)
|
||||||
|
|
||||||
@@ -195,8 +197,7 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_correct_signature(
|
|||||||
|
|
||||||
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
||||||
for p, s in zip(send_proofs, signatures):
|
for p, s in zip(send_proofs, signatures):
|
||||||
p.htlcpreimage = preimage
|
p.witness = HTLCWitness(preimage=preimage, signature=s).json()
|
||||||
p.htlcsignature = s
|
|
||||||
|
|
||||||
# should error because we used wallet2 signatures for the hash lock
|
# should error because we used wallet2 signatures for the hash lock
|
||||||
await assert_err(
|
await assert_err(
|
||||||
@@ -230,8 +231,9 @@ async def test_htlc_redeem_hashlock_wrong_signature_timelock_wrong_signature(
|
|||||||
|
|
||||||
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
signatures = await wallet1.sign_p2pk_proofs(send_proofs)
|
||||||
for p, s in zip(send_proofs, signatures):
|
for p, s in zip(send_proofs, signatures):
|
||||||
p.htlcpreimage = preimage
|
p.witness = HTLCWitness(
|
||||||
p.htlcsignature = s[:-5] + "11111" # wrong signature
|
preimage=preimage, signature=s[:-5] + "11111"
|
||||||
|
).json() # wrong signature
|
||||||
|
|
||||||
# should error because we used wallet2 signatures for the hash lock
|
# should error because we used wallet2 signatures for the hash lock
|
||||||
await assert_err(
|
await assert_err(
|
||||||
|
|||||||
@@ -78,6 +78,21 @@ async def test_p2pk(wallet1: Wallet, wallet2: Wallet):
|
|||||||
await wallet2.redeem(send_proofs)
|
await wallet2.redeem(send_proofs)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_p2pk_sig_all(wallet1: Wallet, wallet2: Wallet):
|
||||||
|
invoice = await wallet1.request_mint(64)
|
||||||
|
await wallet1.mint(64, hash=invoice.hash)
|
||||||
|
pubkey_wallet2 = await wallet2.create_p2pk_pubkey()
|
||||||
|
# p2pk test
|
||||||
|
secret_lock = await wallet1.create_p2pk_lock(
|
||||||
|
pubkey_wallet2, sig_all=True
|
||||||
|
) # sender side
|
||||||
|
_, send_proofs = await wallet1.split_to_send(
|
||||||
|
wallet1.proofs, 8, secret_lock=secret_lock
|
||||||
|
)
|
||||||
|
await wallet2.redeem(send_proofs)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wallet):
|
async def test_p2pk_receive_with_wrong_private_key(wallet1: Wallet, wallet2: Wallet):
|
||||||
invoice = await wallet1.request_mint(64)
|
invoice = await wallet1.request_mint(64)
|
||||||
|
|||||||
Reference in New Issue
Block a user