Skip to content

Commit

Permalink
tests P2PK nut
Browse files Browse the repository at this point in the history
  • Loading branch information
elnosh committed Jul 9, 2024
1 parent b9c1d56 commit a75d5a6
Show file tree
Hide file tree
Showing 5 changed files with 288 additions and 31 deletions.
38 changes: 38 additions & 0 deletions cashu/cashu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,41 @@ func TestTokenToString(t *testing.T) {
}
}
}

func TestSecretType(t *testing.T) {
tests := []struct {
proof Proof
expectedKind SecretKind
expectedIsP2PK bool
}{
{
proof: Proof{Secret: `["P2PK", {"nonce":"da62796403af76c80cd6ce9153ed3746","data":"033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e","tags":[["sigflag","SIG_ALL"]]}]`},
expectedKind: P2PK,
expectedIsP2PK: true,
},

{
proof: Proof{Secret: `["DIFFERENT", {"nonce":"da62796403af76c80cd6ce9153ed3746","data":"033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e","tags":[]}]`},
expectedKind: Random,
expectedIsP2PK: false,
},

{
proof: Proof{Secret: `someranadomsecret`},
expectedKind: Random,
expectedIsP2PK: false,
},
}

for _, test := range tests {
kind := test.proof.SecretType()
if kind != test.expectedKind {
t.Fatalf("expected '%v' but got '%v' instead", test.expectedKind.String(), kind.String())
}

isP2PK := test.proof.IsSecretP2PK()
if isP2PK != test.expectedIsP2PK {
t.Fatalf("expected '%v' but got '%v' instead", test.expectedIsP2PK, isP2PK)
}
}
}
54 changes: 54 additions & 0 deletions cashu/nuts/nut10/nut10_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package nut10

import (
"reflect"
"testing"

"github.com/elnosh/gonuts/cashu"
)

func TestSerializeSecret(t *testing.T) {
secretData := WellKnownSecret{
Nonce: "da62796403af76c80cd6ce9153ed3746",
Data: "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e",
Tags: [][]string{
{"sigflag", "SIG_ALL"},
},
}

serialized, err := SerializeSecret(cashu.P2PK, secretData)
if err != nil {
t.Fatalf("got unexpected error: %v", err)
}

expected := `["P2PK", {"nonce":"da62796403af76c80cd6ce9153ed3746","data":"033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e","tags":[["sigflag","SIG_ALL"]]}]`

if serialized != expected {
t.Fatalf("expected secret:\n%v\n\n but got:\n%v", expected, serialized)
}
}

func TestDeserializeSecret(t *testing.T) {
secret := `["P2PK", {"nonce":"da62796403af76c80cd6ce9153ed3746","data":"033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e","tags":[["sigflag","SIG_ALL"]]}]`
secretData, err := DeserializeSecret(secret)
if err != nil {
t.Fatalf("got unexpected error: %v", err)
}

expectedNonce := "da62796403af76c80cd6ce9153ed3746"
if secretData.Nonce != expectedNonce {
t.Fatalf("expected nonce '%v' but got '%v' instead", expectedNonce, secretData.Nonce)
}

expectedData := "033281c37677ea273eb7183b783067f5244933ef78d8c3f15b1a77cb246099c26e"
if secretData.Data != expectedData {
t.Fatalf("expected data '%v' but got '%v' instead", expectedData, secretData.Data)
}

expectedTags := [][]string{
{"sigflag", "SIG_ALL"},
}
if !reflect.DeepEqual(secretData.Tags, expectedTags) {
t.Fatalf("expected tags '%v' but got '%v' instead", expectedTags, secretData.Tags)
}
}
84 changes: 84 additions & 0 deletions cashu/nuts/nut11/nut11_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package nut11

import (
"encoding/hex"
"testing"

"github.com/btcsuite/btcd/btcec/v2"
"github.com/elnosh/gonuts/cashu/nuts/nut10"
)

func TestIsSigAll(t *testing.T) {
tests := []struct {
p2pkSecretData nut10.WellKnownSecret
expected bool
}{
{
p2pkSecretData: nut10.WellKnownSecret{
Tags: [][]string{},
},
expected: false,
},
{
p2pkSecretData: nut10.WellKnownSecret{
Tags: [][]string{{"sigflag", "SIG_INPUTS"}},
},
expected: false,
},
{
p2pkSecretData: nut10.WellKnownSecret{
Tags: [][]string{
{"locktime", "882912379"},
{"refund", "refundkey"},
{"sigflag", "SIG_ALL"},
},
},
expected: true,
},
}

for _, test := range tests {
result := IsSigAll(test.p2pkSecretData)
if result != test.expected {
t.Fatalf("expected '%v' but got '%v' instead", test.expected, result)
}
}
}

func TestCanSign(t *testing.T) {
privateKey, _ := btcec.NewPrivateKey()
publicKey := hex.EncodeToString(privateKey.PubKey().SerializeCompressed())

tests := []struct {
p2pkSecretData nut10.WellKnownSecret
expected bool
}{
{
p2pkSecretData: nut10.WellKnownSecret{
Data: publicKey,
},
expected: true,
},

{
p2pkSecretData: nut10.WellKnownSecret{
Data: "somerandomkey",
},
expected: false,
},

{
p2pkSecretData: nut10.WellKnownSecret{
Data: "sdjflksjdflsdjfd",
},
expected: false,
},
}

for _, test := range tests {
result := CanSign(test.p2pkSecretData, privateKey)
if result != test.expected {
t.Fatalf("expected '%v' but got '%v' instead", test.expected, result)
}
}
}
52 changes: 22 additions & 30 deletions wallet/wallet.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,40 +487,33 @@ func (w *Wallet) swap(proofsToSwap cashu.Proofs, mintURL string) (cashu.Proofs,
}
}

var activeSatKeyset crypto.WalletKeyset
var outputs cashu.BlindedMessages
var secrets []string
var rs []*secp256k1.PrivateKey
var err error
var activeKeysets map[string]crypto.WalletKeyset
walletMint, trustedMint := w.mints[mintURL]
if !trustedMint {
activeKeysets, err := GetMintActiveKeysets(mintURL)
// get keys if mint not trusted
var err error
activeKeysets, err = GetMintActiveKeysets(mintURL)
if err != nil {
return nil, err
}
for _, k := range activeKeysets {
activeSatKeyset = k
break
}

// create blinded messages
outputs, secrets, rs, err = w.createBlindedMessages(proofsToSwap.Amount(), activeSatKeyset.Id, nil)
if err != nil {
return nil, fmt.Errorf("createBlindedMessages: %v", err)
}
} else {
for _, k := range walletMint.activeKeysets {
activeSatKeyset = k
break
}
activeKeysets = walletMint.activeKeysets
}

counter := w.counterForKeyset(activeSatKeyset.Id)
var activeSatKeyset crypto.WalletKeyset
for _, k := range activeKeysets {
activeSatKeyset = k
break
}
var counter *uint32 = nil
if trustedMint {
keysetCounter := w.counterForKeyset(activeSatKeyset.Id)
counter = &keysetCounter
}

// create blinded messages
outputs, secrets, rs, err = w.createBlindedMessages(proofsToSwap.Amount(), activeSatKeyset.Id, &counter)
if err != nil {
return nil, fmt.Errorf("createBlindedMessages: %v", err)
}
outputs, secrets, rs, err := w.createBlindedMessages(proofsToSwap.Amount(), activeSatKeyset.Id, counter)
if err != nil {
return nil, fmt.Errorf("createBlindedMessages: %v", err)
}

// if P2PK locked ecash has `SIG_ALL` flag, sign outputs
Expand Down Expand Up @@ -611,8 +604,8 @@ func (w *Wallet) swapToTrusted(token cashu.Token) (cashu.Proofs, error) {
if err != nil {
return nil, err
}
} else { // if not sig all, can just sign inputs and no need to do a swap first
// check that public key in data is one wallet can sign for
} else {
// if not sig all, can just sign inputs and no need to do a swap first
if !nut11.CanSign(nut10secret, w.privateKey) {
return nil, fmt.Errorf("cannot sign locked proofs")
}
Expand Down Expand Up @@ -788,8 +781,7 @@ func (w *Wallet) getProofsForAmount(amount uint64, mintURL string, pubkeyLock *b
var secrets []string
var rs []*secp256k1.PrivateKey
var counter, incrementCounterBy uint32
// check here if lock is present and if so, use it to generate blinded messages
// instead of generating from counter

if pubkeyLock == nil {
counter = w.counterForKeyset(activeSatKeyset.Id)
var err error
Expand Down
91 changes: 90 additions & 1 deletion wallet/wallet_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -377,20 +377,109 @@ func TestWalletBalance(t *testing.T) {
}
}

func TestWalletRestore(t *testing.T) {
func TestSendToPubkey(t *testing.T) {
nutshellMint, err := testutils.CreateNutshellMintContainer(ctx)
if err != nil {
t.Fatalf("error starting nutshell mint: %v", err)
}
defer nutshellMint.Terminate(ctx)
nutshellURL := nutshellMint.Host

nutshellMint2, err := testutils.CreateNutshellMintContainer(ctx)
if err != nil {
t.Fatalf("error starting nutshell mint: %v", err)
}
defer nutshellMint2.Terminate(ctx)

testWalletPath := filepath.Join(".", "/testwalletp2pk")
testWallet, err := testutils.CreateTestWallet(testWalletPath, nutshellURL)
if err != nil {
t.Fatal(err)
}
defer func() {
os.RemoveAll(testWalletPath)
}()

testWalletPath2 := filepath.Join(".", "/testwalletp2pk2")
testWallet2, err := testutils.CreateTestWallet(testWalletPath2, nutshellMint2.Host)
if err != nil {
t.Fatal(err)
}
defer func() {
os.RemoveAll(testWalletPath2)
}()

mintRequest, err := testWallet.RequestMint(20000)
if err != nil {
t.Fatalf("unexpected error in mint request: %v", err)
}
_, err = testWallet.MintTokens(mintRequest.Quote)
if err != nil {
t.Fatalf("unexpected error in mint tokens: %v", err)
}

receiverPubkey := testWallet2.GetReceivePubkey()

lockedEcash, err := testWallet.SendToPubkey(500, nutshellURL, receiverPubkey)
if err != nil {
t.Fatalf("unexpected error generating locked ecash: %v", err)
}

// try receiving invalid
_, err = testWallet.Receive(*lockedEcash, true)
if err == nil {
t.Fatal("expected error trying to redeem locked ecash")
}

// this should unlock ecash and swap to trusted mint
amountReceived, err := testWallet2.Receive(*lockedEcash, true)
if err != nil {
t.Fatalf("unexpected error receiving locked ecash: %v", err)
}

trustedMints := testWallet2.TrustedMints()
if len(trustedMints) != 1 {
t.Fatalf("expected len of trusted mints '%v' but got '%v' instead", 1, len(trustedMints))
}

balance := testWallet2.GetBalance()
if balance != amountReceived {
t.Fatalf("expected balance of '%v' but got '%v' instead", amountReceived, balance)
}

lockedEcash, err = testWallet.SendToPubkey(500, nutshellURL, receiverPubkey)
if err != nil {
t.Fatalf("unexpected error generating locked ecash: %v", err)
}

// unlock ecash and trust mint
amountReceived, err = testWallet2.Receive(*lockedEcash, false)
if err != nil {
t.Fatalf("unexpected error receiving locked ecash: %v", err)
}

trustedMints = testWallet2.TrustedMints()
if len(trustedMints) != 2 {
t.Fatalf("expected len of trusted mints '%v' but got '%v' instead", 2, len(trustedMints))
}
}

func TestWalletRestore(t *testing.T) {
nutshellMint, err := testutils.CreateNutshellMintContainer(ctx)
if err != nil {
t.Fatalf("error starting nutshell mint: %v", err)
}
defer nutshellMint.Terminate(ctx)
mintURL := nutshellMint.Host

testWalletPath := filepath.Join(".", "/testrestorewallet")
testWallet, err := testutils.CreateTestWallet(testWalletPath, mintURL)
if err != nil {
t.Fatal(err)
}
defer func() {
os.RemoveAll(testWalletPath)
}()

testWalletPath2 := filepath.Join(".", "/testrestorewallet2")
testWallet2, err := testutils.CreateTestWallet(testWalletPath2, mintURL)
Expand Down

0 comments on commit a75d5a6

Please sign in to comment.