Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mint: NUT-12 DLEQ proofs #61

Merged
merged 2 commits into from
Sep 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 14 additions & 4 deletions mint/mint.go
Original file line number Diff line number Diff line change
Expand Up @@ -831,12 +831,22 @@ func (m *Mint) signBlindedMessages(blindedMessages cashu.BlindedMessages) (cashu
C_ := crypto.SignBlindedMessage(B_, k)
C_hex := hex.EncodeToString(C_.SerializeCompressed())

blindedSignature := cashu.BlindedSignature{Amount: msg.Amount,
C_: C_hex, Id: keyset.Id}
// DLEQ proof
e, s := crypto.GenerateDLEQ(k, B_, C_)

blindedSignature := cashu.BlindedSignature{
Amount: msg.Amount,
C_: C_hex,
Id: keyset.Id,
DLEQ: &cashu.DLEQProof{
E: hex.EncodeToString(e.Serialize()),
S: hex.EncodeToString(s.Serialize()),
},
}

blindedSignatures[i] = blindedSignature

if err := m.db.SaveBlindSignature(msg.B_, C_hex, msg.Id, msg.Amount); err != nil {
if err := m.db.SaveBlindSignature(msg.B_, blindedSignature); err != nil {
msg := fmt.Sprintf("error saving signatures: %v", err)
return nil, cashu.BuildCashuError(msg, cashu.DBErrCode)
}
Expand All @@ -845,7 +855,7 @@ func (m *Mint) signBlindedMessages(blindedMessages cashu.BlindedMessages) (cashu
return blindedSignatures, nil
}

// requestInvoices requests an invoice from the Lightning backend
// requestInvoice requests an invoice from the Lightning backend
// for the given amount
func (m *Mint) requestInvoice(amount uint64) (*lightning.Invoice, error) {
invoice, err := m.lightningClient.CreateInvoice(amount)
Expand Down
42 changes: 42 additions & 0 deletions mint/mint_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/elnosh/gonuts/cashu/nuts/nut05"
"github.com/elnosh/gonuts/cashu/nuts/nut07"
"github.com/elnosh/gonuts/cashu/nuts/nut11"
"github.com/elnosh/gonuts/cashu/nuts/nut12"
"github.com/elnosh/gonuts/crypto"
"github.com/elnosh/gonuts/mint"
"github.com/elnosh/gonuts/testutils"
Expand Down Expand Up @@ -959,3 +960,44 @@ func TestNUT11P2PK(t *testing.T) {
t.Fatalf("expected error '%v' but got '%v' instead", nut11.SigAllOnlySwap, err)
}
}

func TestDLEQProofs(t *testing.T) {
var amount uint64 = 5000
proofs, err := testutils.GetValidProofsForAmount(amount, testMint, lnd2)
if err != nil {
t.Fatalf("error generating valid proofs: %v", err)
}

keyset := testMint.GetActiveKeyset()

// check proofs minted from testMint have valid DLEQ proofs
for _, proof := range proofs {
if proof.DLEQ == nil {
t.Fatal("mint returned nil DLEQ proof")
}

if !nut12.VerifyProofDLEQ(proof, keyset.Keys[proof.Amount].PublicKey) {
t.Fatal("generated invalid DLEQ proof from MintTokens")
}
}

blindedMessages, _, _, err := testutils.CreateBlindedMessages(amount, keyset)
blindSignatures, err := testMint.Swap(proofs, blindedMessages)
if err != nil {
t.Fatalf("unexpected error in swap: %v", err)
}

for i, sig := range blindSignatures {
if sig.DLEQ == nil {
t.Fatal("mint returned nil DLEQ proof from swap")
}
if !nut12.VerifyBlindSignatureDLEQ(
*sig.DLEQ,
keyset.Keys[sig.Amount].PublicKey,
blindedMessages[i].B_,
sig.C_,
) {
t.Fatal("mint generated invalid DLEQ proof in swap")
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

ALTER TABLE blind_signatures DROP COLUMN e;
ALTER TABLE blind_signatures DROP COLUMN s;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

ALTER TABLE blind_signatures ADD COLUMN e TEXT;
ALTER TABLE blind_signatures ADD COLUMN s TEXT;
54 changes: 46 additions & 8 deletions mint/storage/sqlite/sqlite.go
Original file line number Diff line number Diff line change
Expand Up @@ -320,33 +320,52 @@ func (sqlite *SQLiteDB) UpdateMeltQuote(quoteId, preimage string, state nut05.St
return nil
}

func (sqlite *SQLiteDB) SaveBlindSignature(B_, C_, keysetId string, amount uint64) error {
func (sqlite *SQLiteDB) SaveBlindSignature(B_ string, blindSignature cashu.BlindedSignature) error {
_, err := sqlite.db.Exec(`
INSERT INTO blind_signatures (b_, c_, keyset_id, amount) VALUES (?, ?, ?, ?)`,
B_, C_, keysetId, amount,
INSERT INTO blind_signatures (b_, c_, keyset_id, amount, e, s) VALUES (?, ?, ?, ?, ?, ?)`,
B_,
blindSignature.C_,
blindSignature.Id,
blindSignature.Amount,
blindSignature.DLEQ.E,
blindSignature.DLEQ.S,
)
return err
}

func (sqlite *SQLiteDB) GetBlindSignature(B_ string) (cashu.BlindedSignature, error) {
row := sqlite.db.QueryRow("SELECT amount, c_, keyset_id FROM blind_signatures WHERE b_ = ?", B_)
row := sqlite.db.QueryRow("SELECT amount, c_, keyset_id, e, s FROM blind_signatures WHERE b_ = ?", B_)

var signature cashu.BlindedSignature
var e sql.NullString
var s sql.NullString

err := row.Scan(
&signature.Amount,
&signature.C_,
&signature.Id,
&e,
&s,
)
if err != nil {
return cashu.BlindedSignature{}, err
}

if !e.Valid || !s.Valid {
signature.DLEQ = nil
} else {
signature.DLEQ = &cashu.DLEQProof{
E: e.String,
S: s.String,
}
}

return signature, nil
}

func (sqlite *SQLiteDB) GetBlindSignatures(B_s []string) (cashu.BlindedSignatures, error) {
signatures := cashu.BlindedSignatures{}
query := `SELECT amount, c_, keyset_id FROM blind_signatures WHERE b_ in (?` + strings.Repeat(",?", len(B_s)-1) + `)`
query := `SELECT amount, c_, keyset_id, e, s FROM blind_signatures WHERE b_ in (?` + strings.Repeat(",?", len(B_s)-1) + `)`

args := make([]any, len(B_s))
for i, B_ := range B_s {
Expand All @@ -360,12 +379,31 @@ func (sqlite *SQLiteDB) GetBlindSignatures(B_s []string) (cashu.BlindedSignature
defer rows.Close()

for rows.Next() {
var blindSignature cashu.BlindedSignature
err := rows.Scan(&blindSignature.Amount, &blindSignature.C_, &blindSignature.Id)
var signature cashu.BlindedSignature
var e sql.NullString
var s sql.NullString

err := rows.Scan(
&signature.Amount,
&signature.C_,
&signature.Id,
&e,
&s,
)
if err != nil {
return nil, err
}
signatures = append(signatures, blindSignature)

if !e.Valid || !s.Valid {
signature.DLEQ = nil
} else {
signature.DLEQ = &cashu.DLEQProof{
E: e.String,
S: s.String,
}
}

signatures = append(signatures, signature)
}

return signatures, nil
Expand Down
2 changes: 1 addition & 1 deletion mint/storage/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ type MintDB interface {
GetMeltQuote(string) (MeltQuote, error)
UpdateMeltQuote(quoteId string, preimage string, state nut05.State) error

SaveBlindSignature(B_, C_, keysetId string, amount uint64) error
SaveBlindSignature(B_ string, blindSignature cashu.BlindedSignature) error
GetBlindSignature(B_ string) (cashu.BlindedSignature, error)
GetBlindSignatures(B_s []string) (cashu.BlindedSignatures, error)

Expand Down
14 changes: 12 additions & 2 deletions testutils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,18 @@ func ConstructProofs(blindedSignatures cashu.BlindedSignatures,
C := crypto.UnblindSignature(C_, rs[i], keyp.PublicKey)
Cstr := hex.EncodeToString(C.SerializeCompressed())

proof := cashu.Proof{Amount: blindedSignature.Amount,
Secret: secrets[i], C: Cstr, Id: blindedSignature.Id}
r := hex.EncodeToString(rs[i].Serialize())
proof := cashu.Proof{
Amount: blindedSignature.Amount,
Secret: secrets[i],
C: Cstr,
Id: blindedSignature.Id,
DLEQ: &cashu.DLEQProof{
E: blindedSignature.DLEQ.E,
S: blindedSignature.DLEQ.S,
R: r,
},
}

proofs[i] = proof
}
Expand Down
Loading