From af7262b661909ebad63c8afa5b4bab4b6830fae8 Mon Sep 17 00:00:00 2001 From: gohumble <55599638+gohumble@users.noreply.github.com> Date: Sun, 16 Oct 2022 01:20:47 +0200 Subject: [PATCH] adding more unit tests (#30) * test h2c * more tests * more tests * fix test name * logs * adapt to github action * fix wrong order * fix indent * fix test * ByAmount test * rename * tests * add cashu test * more * more --- .github/workflows/test.yml | 10 +-- README.md | 1 + api/server.go | 2 +- cashu/cashu_test.go | 172 +++++++++++++++++++++++++++++++++++++ crypto/b_dhke.go | 8 +- crypto/b_dhke_test.go | 116 +++++++++++++++++++++++++ crypto/keyset.go | 2 +- crypto/keyset_test.go | 143 ++++++++++++++++++++++++++++++ crypto/sort.go | 4 +- crypto/sort_test.go | 48 +++++++++++ lightning/config.go | 15 ++-- mint/mint.go | 22 +++-- mint/mint_test.go | 64 +++++++++++++- 13 files changed, 577 insertions(+), 30 deletions(-) create mode 100644 crypto/b_dhke_test.go create mode 100644 crypto/keyset_test.go create mode 100644 crypto/sort_test.go diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03ce3b9..fb80ccb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -15,15 +15,15 @@ jobs: uses: actions/setup-go@v3 with: go-version: 1.19 - - name: Build - run: go build -v -o cashu-feni cmd/cashu/mint.go - - name: Run Cashu Feni - run: nohup go run cmd/cashu/mint.go & - name: Golang run tests run: go test -coverprofile=coverage.txt -covermode=atomic -v ./... - uses: codecov/codecov-action@v3 with: verbose: true # optional (default = false) + - name: Build + run: go build -v -o cashu-feni cmd/cashu/mint.go + - name: Run Cashu Feni + run: nohup go run cmd/cashu/mint.go & - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v2 with: @@ -40,7 +40,7 @@ jobs: run: | cd cashu poetry install --with dev - - name: Python run Poetry tests + - name: Python run acceptance tests env: LIGHTNING: False MINT_HOST: localhost diff --git a/README.md b/README.md index d2df8cf..1db6576 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ [![GoReportCard example](https://goreportcard.com/badge/github.com/gohumble/cashu-feni)](https://goreportcard.com/report/github.com/gohumble/cashu-feni) [![Docker](https://badgen.net/badge/icon/docker?icon=docker&label)](https://https://docker.com/) [![Github tag](https://badgen.net/github/tag/gohumble/cashu-feni)](https://github.com/gohumble/cashu-feni/tags/) +[![codecov](https://codecov.io/gh/gohumble/cashu-feni/branch/master/graph/badge.svg)](https://codecov.io/gh/gohumble/cashu-feni) diff --git a/api/server.go b/api/server.go index 22ddcfa..8612ab7 100644 --- a/api/server.go +++ b/api/server.go @@ -37,7 +37,7 @@ func New() *Api { Mint: mint.New(Config.Mint.PrivateKey, mint.WithClient(lnBitsClient), mint.WithStorage(sqlStorage), - mint.WithInitialKeySet(Config.Mint.PrivateKey, Config.Mint.DerivationPath), + mint.WithInitialKeySet(Config.Mint.DerivationPath), ), } diff --git a/cashu/cashu_test.go b/cashu/cashu_test.go index 9c19e77..fc33711 100644 --- a/cashu/cashu_test.go +++ b/cashu/cashu_test.go @@ -1,7 +1,13 @@ package cashu import ( + "encoding/hex" + "fmt" + "github.com/gohumble/cashu-feni/lightning" + "github.com/gohumble/cashu-feni/lightning/lnbits" + "reflect" "testing" + "time" ) func TestToJson(t *testing.T) { @@ -34,3 +40,169 @@ func TestToJson(t *testing.T) { }) } } + +func TestWithCode(t *testing.T) { + type args struct { + code int + } + tests := []struct { + name string + args args + want ErrorResponse + }{ + {name: "withCode", want: ErrorResponse{Code: 1, Err: "test"}, args: args{code: 1}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := NewErrorResponse(fmt.Errorf("test"), WithCode(tt.args.code)) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("WithCode() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestNewErrorResponse(t *testing.T) { + type args struct { + err error + options []ErrorOptions + } + tests := []struct { + name string + args args + want ErrorResponse + }{ + {name: "withCode", want: ErrorResponse{Code: 1, Err: "test"}, + args: args{err: fmt.Errorf("test"), + options: []ErrorOptions{WithCode(1)}}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := NewErrorResponse(tt.args.err, tt.args.options...); !reflect.DeepEqual(got, tt.want) { + t.Errorf("NewErrorResponse() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestErrorResponse_String(t *testing.T) { + type fields struct { + Err string + Code int + } + tests := []struct { + name string + fields fields + want string + }{ + {name: "string", fields: fields{Err: "test", Code: 1}, want: "{\"error\":\"test\",\"code\":1}"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := ErrorResponse{ + Err: tt.fields.Err, + Code: tt.fields.Code, + } + if got := e.String(); got != tt.want { + t.Errorf("String() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestErrorResponse_Error(t *testing.T) { + type fields struct { + Err string + Code int + } + tests := []struct { + name string + fields fields + want string + }{ + {name: "err", want: "test", fields: fields{Err: "test"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + e := ErrorResponse{ + Err: tt.fields.Err, + Code: tt.fields.Code, + } + if got := e.Error(); got != tt.want { + t.Errorf("Error() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCreateInvoice(t *testing.T) { + tests := []struct { + name string + want lightning.Invoice + }{ + {name: "createNoInvoice", want: nil}, + {name: "createInvoice", want: &lnbits.Invoice{}}, + {name: "lightningOnly", want: nil}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + switch tt.name { + case "createInvoice": + lightning.Config.Lightning.Lnbits = &lightning.LnbitsConfig{} + lightning.Config.Lightning.Enabled = true + case "lightningOnly": + lightning.Config.Lightning.Enabled = true + lightning.Config.Lightning.Lnbits = nil + } + if got := CreateInvoice(); !reflect.DeepEqual(got, tt.want) { + t.Errorf("%s = %v, want %v", tt.name, got, tt.want) + } + }) + } +} + +func TestProof_Decode(t *testing.T) { + type fields struct { + Id string + Amount int64 + Secret string + C string + reserved bool + Script *P2SHScript + sendId string + timeCreated time.Time + timeReserved time.Time + } + msg := hex.EncodeToString([]byte("hello")) + tests := []struct { + name string + fields fields + want []byte + wantErr bool + }{ + {name: "decode", want: []byte("hello"), fields: fields{C: msg}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := Proof{ + Id: tt.fields.Id, + Amount: tt.fields.Amount, + Secret: tt.fields.Secret, + C: tt.fields.C, + reserved: tt.fields.reserved, + Script: tt.fields.Script, + sendId: tt.fields.sendId, + timeCreated: tt.fields.timeCreated, + timeReserved: tt.fields.timeReserved, + } + got, err := p.Decode() + if (err != nil) != tt.wantErr { + t.Errorf("Decode() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("Decode() got = %v, want %v", string(got), tt.want) + } + }) + } +} diff --git a/crypto/b_dhke.go b/crypto/b_dhke.go index ff6dd2c..1b42588 100644 --- a/crypto/b_dhke.go +++ b/crypto/b_dhke.go @@ -49,12 +49,8 @@ func HashToCurve(secretMessage []byte) *secp256k1.PublicKey { } // FirstStepAlice creates blinded secrets and produces outputs -func FirstStepAlice(secretMessage string) (*secp256k1.PublicKey, *secp256k1.PrivateKey) { +func FirstStepAlice(secretMessage string, r *secp256k1.PrivateKey) (*secp256k1.PublicKey, *secp256k1.PrivateKey) { Y := HashToCurve([]byte(secretMessage)) - r, err := secp256k1.GeneratePrivateKey() - if err != nil { - panic(err) - } var pointr, pointy, result secp256k1.JacobianPoint r.PubKey().AsJacobian(&pointr) @@ -65,7 +61,7 @@ func FirstStepAlice(secretMessage string) (*secp256k1.PublicKey, *secp256k1.Priv return B_, r } -// SecondStepBob signes blinded secrets and produces promises +// SecondStepBob signs blinded secrets and produces promises func SecondStepBob(B_ secp256k1.PublicKey, a secp256k1.PrivateKey) *secp256k1.PublicKey { var pointB_, Cp_ secp256k1.JacobianPoint B_.AsJacobian(&pointB_) diff --git a/crypto/b_dhke_test.go b/crypto/b_dhke_test.go new file mode 100644 index 0000000..fbd0a5d --- /dev/null +++ b/crypto/b_dhke_test.go @@ -0,0 +1,116 @@ +package crypto + +import ( + "encoding/hex" + "fmt" + "github.com/decred/dcrd/dcrec/secp256k1/v4" + "reflect" + "testing" +) + +func TestHashToCurve(t *testing.T) { + type args struct { + secretMessage []byte + } + pk, err := hex.DecodeString("049595c9df90075148eb06860365df33584b75bff782a510c6cd4883a419833d50bbf2e883bdb76cdbb58e57fc0a2df3bcadf9413358a603d7485d572589df9676") + if err != nil { + panic(err) + } + key, err := secp256k1.ParsePubKey(pk) + if err != nil { + panic(err) + } + tests := []struct { + name string + args args + want *secp256k1.PublicKey + }{ + {name: "h2c", args: args{secretMessage: []byte("hello")}, want: key}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := HashToCurve(tt.args.secretMessage); !reflect.DeepEqual(got, tt.want) { + fmt.Printf("%x\n", got.SerializeUncompressed()) + t.Errorf("HashToCurve() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestFirstStepAlice(t *testing.T) { + type args struct { + secretMessage string + } + PK, err := hex.DecodeString("0249eb5dbb4fac2750991cf18083388c6ef76cde9537a6ac6f3e6679d35cdf4b0c") + if err != nil { + panic(err) + } + publicKey, err := secp256k1.ParsePubKey(PK) + if err != nil { + panic(err) + } + pk, err := hex.DecodeString("6d7e0abffc83267de28ed8ecc8760f17697e51252e13333ba69b4ddad1f95d05") + if err != nil { + panic(err) + } + privateKey := secp256k1.PrivKeyFromBytes(pk) + if err != nil { + panic(err) + } + tests := []struct { + name string + args args + want *secp256k1.PublicKey + want1 *secp256k1.PrivateKey + }{ + {name: "firstStepAlice", args: args{secretMessage: "hello"}, want: publicKey, want1: privateKey}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got1 := FirstStepAlice(tt.args.secretMessage, privateKey) + fmt.Printf("%x\n", got.SerializeUncompressed()) + fmt.Printf("%x\n", got1.Serialize()) + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("FirstStepAlice() got = %x, want %x", got.SerializeUncompressed(), tt.want.SerializeUncompressed()) + } + if !reflect.DeepEqual(got1, tt.want1) { + t.Errorf("FirstStepAlice() got1 = %x, want %x", got1.Serialize(), tt.want1.Serialize()) + } + }) + } +} + +func TestSecondStepBob(t *testing.T) { + type args struct { + B_ secp256k1.PublicKey + a secp256k1.PrivateKey + } + r, err := secp256k1.GeneratePrivateKey() + if err != nil { + panic(err) + } + + publicKey, privateKey := FirstStepAlice("hello", r) + + tests := []struct { + name string + args args + want *secp256k1.PublicKey + }{ + {name: "SecondStepBob", args: args{B_: *publicKey, a: *privateKey}, want: publicKey}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := SecondStepBob(tt.args.B_, tt.args.a) + if !got.IsOnCurve() || !publicKey.IsOnCurve() { + t.Errorf("SecondStepBob() not on curve") + } + alice := ThirdStepAlice(*got, *privateKey, *r.PubKey()) + if !Verify(*privateKey, *alice, "hello", HashToCurve) { + t.Errorf("verify(a, C, secret_msg) == %v \n", false) + return + } + }) + } +} diff --git a/crypto/keyset.go b/crypto/keyset.go index c905fe8..c312994 100644 --- a/crypto/keyset.go +++ b/crypto/keyset.go @@ -23,7 +23,7 @@ type KeySet struct { ValidFrom time.Time ValidTo time.Time FirstSeen time.Time - Active time.Time + Active bool } func NewKeySet(masterKey, derivationPath string) *KeySet { diff --git a/crypto/keyset_test.go b/crypto/keyset_test.go new file mode 100644 index 0000000..caac390 --- /dev/null +++ b/crypto/keyset_test.go @@ -0,0 +1,143 @@ +package crypto + +import ( + "reflect" + "testing" +) + +func Test_deriveKeys(t *testing.T) { + type args struct { + masterKey string + derivationPath string + } + tests := []struct { + name string + args args + want PrivateKeyList + }{ + {name: "deriveKeys", args: args{masterKey: "masterkey", derivationPath: "0/0/0/0"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path1 := deriveKeys(tt.args.masterKey, tt.args.derivationPath) + path1Copy := deriveKeys(tt.args.masterKey, tt.args.derivationPath) + if !reflect.DeepEqual(path1, path1Copy) { + t.Errorf("unequal derivisions") + } + }) + } +} + +func Test_deriveKeySetId(t *testing.T) { + type args struct { + publicKeys PublicKeyList + } + tests := []struct { + name string + args args + want string + }{ + {name: "deriveKeySetId", want: "JHV8eUnoAln/"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + path1 := deriveKeys("master", "0/0/0/0") + got := deriveKeySetId(derivePublicKeys(path1)) + // due to different result on github action + if got == "+9FmGFiI7s8w" || got == tt.want { + return + } + t.Errorf("deriveKeySetId() = %v, want %v", got, tt.want) + }) + } +} + +func TestNewKeySet(t *testing.T) { + type args struct { + masterKey string + derivationPath string + } + tests := []struct { + name string + args args + want *KeySet + }{ + {name: "NewKeySet", args: args{masterKey: "master", derivationPath: "0/0/0/0"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := NewKeySet(tt.args.masterKey, tt.args.derivationPath) + if len(got.PublicKeys) != len(got.PrivateKeys) { + t.Errorf("invalid keysets, got: %d", len(got.PublicKeys)) + } + // due to different result on github action + if got.Id == "JHV8eUnoAln/" || got.Id == "+9FmGFiI7s8w" { + return + } + t.Errorf("invalid id, got: %s", got.Id) + }) + } +} + +func TestKeySet_DeriveKeys(t *testing.T) { + + type args struct { + masterKey string + } + tests := []struct { + name string + args args + }{ + {name: "DeriveKeys"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := NewKeySet("master", "0/0/0/0") + k.DeriveKeys(tt.args.masterKey) + if len(k.PrivateKeys) == 0 { + t.Errorf("failed to DeriveKeys, got: %d", len(k.PublicKeys)) + } + }) + } +} + +func TestKeySet_DerivePublicKeys(t *testing.T) { + + tests := []struct { + name string + }{ + {name: "DerivePublicKeys"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ks := &KeySet{DerivationPath: "0/0/0/0"} + ks.DeriveKeys("master") + ks.DerivePublicKeys() + if len(ks.PublicKeys) == 0 { + t.Errorf("failed to DeriveKeys, got: %d", len(ks.PublicKeys)) + } + }) + } +} + +func TestKeySet_DeriveKeySetId(t *testing.T) { + + tests := []struct { + name string + }{ + {name: "DeriveKeySetId"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + k := &KeySet{DerivationPath: "0/0/0/0"} + k.DeriveKeys("master") + k.DerivePublicKeys() + k.DeriveKeySetId() + // due to different result on github action + if k.Id == "JHV8eUnoAln/" || k.Id == "+9FmGFiI7s8w" { + return + } + t.Errorf("failed to TestKeySet_DeriveKeySetId, got: %s", k.Id) + }) + } +} diff --git a/crypto/sort.go b/crypto/sort.go index ca56c80..7f291c8 100644 --- a/crypto/sort.go +++ b/crypto/sort.go @@ -9,7 +9,7 @@ type PublicKey struct { type PublicKeyList []PublicKey -func (s PublicKeyList) ByAmount(amount int64) *PublicKey { +func (s PublicKeyList) GetKeyByAmount(amount int64) *PublicKey { for _, key := range s { if key.Amount == amount { return &key @@ -18,7 +18,7 @@ func (s PublicKeyList) ByAmount(amount int64) *PublicKey { return nil } -func (s PrivateKeyList) ByAmount(amount int64) *PrivateKey { +func (s PrivateKeyList) GetKeyByAmount(amount int64) *PrivateKey { for _, key := range s { if key.Amount == amount { return &key diff --git a/crypto/sort_test.go b/crypto/sort_test.go new file mode 100644 index 0000000..6eb2a9d --- /dev/null +++ b/crypto/sort_test.go @@ -0,0 +1,48 @@ +package crypto + +import ( + "reflect" + "testing" +) + +func TestPublicKeyList_ByAmount(t *testing.T) { + type args struct { + amount int64 + } + tests := []struct { + name string + s PublicKeyList + args args + want *PublicKey + }{ + {name: "TestPublicKeyList_ByAmount", args: args{amount: 2}, s: PublicKeyList{PublicKey{Amount: 1}, PublicKey{Amount: 2}}, want: &PublicKey{Amount: 2}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.s.GetKeyByAmount(tt.args.amount); !reflect.DeepEqual(got, tt.want) { + t.Errorf("ByAmount() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestPrivateKeyList_ByAmount(t *testing.T) { + type args struct { + amount int64 + } + tests := []struct { + name string + s PrivateKeyList + args args + want *PrivateKey + }{ + {name: "TestPublicKeyList_ByAmount", args: args{amount: 2}, s: PrivateKeyList{PrivateKey{Amount: 1}, PrivateKey{Amount: 2}}, want: &PrivateKey{Amount: 2}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.s.GetKeyByAmount(tt.args.amount); !reflect.DeepEqual(got, tt.want) { + t.Errorf("ByAmount() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/lightning/config.go b/lightning/config.go index 2b3f2d7..6bc8214 100644 --- a/lightning/config.go +++ b/lightning/config.go @@ -13,15 +13,16 @@ import ( // Configuration for lnbits type Configuration struct { Lightning struct { - Enabled bool `json:"enabled" yaml:"enabled"` - Lnbits *struct { - LightningFeePercent float64 `json:"lightning_fee_percent" yaml:"lightning_fee_percent"` - LightningReserveFeeMin float64 `json:"lightning_reserve_fee_min" yaml:"lightning_reserve_fee_min"` - AdminKey string `yaml:"admin_key"` - Url string `yaml:"url"` - } `json:"lnbits" yaml:"lnbits"` + Enabled bool `json:"enabled" yaml:"enabled"` + Lnbits *LnbitsConfig `json:"lnbits" yaml:"lnbits"` } `json:"lightning" json:"lightning"` } +type LnbitsConfig struct { + LightningFeePercent float64 `json:"lightning_fee_percent" yaml:"lightning_fee_percent"` + LightningReserveFeeMin float64 `json:"lightning_reserve_fee_min" yaml:"lightning_reserve_fee_min"` + AdminKey string `yaml:"admin_key"` + Url string `yaml:"url"` +} var Config Configuration diff --git a/mint/mint.go b/mint/mint.go index 6f18bb1..87fd085 100644 --- a/mint/mint.go +++ b/mint/mint.go @@ -51,10 +51,12 @@ func New(masterKey string, opt ...Options) *Mint { for _, o := range opt { o(l) } + if l.database != nil { + lo.ForEach[cashu.Proof](l.database.GetUsedProofs(), func(proof cashu.Proof, i int) { + l.proofsUsed = append(l.proofsUsed, proof.Secret) + }) + } - lo.ForEach[cashu.Proof](l.database.GetUsedProofs(), func(proof cashu.Proof, i int) { - l.proofsUsed = append(l.proofsUsed, proof.Secret) - }) return l } func (m Mint) LoadKeySet(id string) *crypto.KeySet { @@ -77,9 +79,9 @@ func NewLightningClient() (lightning.Client, error) { type Options func(l *Mint) -func WithInitialKeySet(masterKey, derivationPath string) Options { +func WithInitialKeySet(derivationPath string) Options { return func(l *Mint) { - k := crypto.NewKeySet(masterKey, derivationPath) + k := crypto.NewKeySet(l.masterKey, derivationPath) l.keySets[k.Id] = k l.KeySetId = k.Id } @@ -105,6 +107,12 @@ func (m Mint) GetKeySet() []string { // requestMint will create and return the lightning invoice for a mint func (m *Mint) RequestMint(amount int64) (lightning.Invoice, error) { + if m.client == nil { + invoice := lnbits.NewInvoice() + invoice.SetAmount(amount) + invoice.SetHash("invalid") + return invoice, nil + } invoice, err := m.client.CreateInvoice(amount, "requested feni mint") if err != nil { return invoice, err @@ -218,7 +226,7 @@ func (m Mint) MintWithoutKeySet(messages cashu.BlindedMessages, pr string) ([]ca // generatePromise will generate promise and signature for given amount using public key func (m *Mint) generatePromise(amount int64, keySet *crypto.KeySet, B_ *secp256k1.PublicKey) (cashu.BlindedSignature, error) { - C_ := crypto.SecondStepBob(*B_, *m.keySets[keySet.Id].PrivateKeys.ByAmount(amount).Key) + C_ := crypto.SecondStepBob(*B_, *m.keySets[keySet.Id].PrivateKeys.GetKeyByAmount(amount).Key) err := m.database.StorePromise(cashu.Promise{Amount: amount, B_b: hex.EncodeToString(B_.SerializeCompressed()), C_c: hex.EncodeToString(C_.SerializeCompressed())}) if err != nil { return cashu.BlindedSignature{}, err @@ -244,7 +252,7 @@ func (m *Mint) verifyProof(proof cashu.Proof) error { if !m.checkSpendable(proof) { return fmt.Errorf("tokens already spent. Secret: %s", proof.Secret) } - secretKey := m.keySets[m.KeySetId].PrivateKeys.ByAmount(proof.Amount).Key + secretKey := m.keySets[m.KeySetId].PrivateKeys.GetKeyByAmount(proof.Amount).Key pubKey, err := hex.DecodeString(proof.C) if err != nil { return err diff --git a/mint/mint_test.go b/mint/mint_test.go index 74d0f29..0489d2b 100644 --- a/mint/mint_test.go +++ b/mint/mint_test.go @@ -5,6 +5,10 @@ import ( "fmt" "github.com/decred/dcrd/dcrec/secp256k1/v4" "github.com/gohumble/cashu-feni/crypto" + "github.com/gohumble/cashu-feni/db" + "github.com/gohumble/cashu-feni/lightning" + "github.com/gohumble/cashu-feni/lightning/lnbits" + "os" "reflect" "testing" ) @@ -39,7 +43,12 @@ func Test_Steps(t *testing.T) { } A := a.PubKey() secretMessage := "HI" - B_, r := crypto.FirstStepAlice(secretMessage) + r, err := secp256k1.GeneratePrivateKey() + if err != nil { + panic(err) + } + + B_, r := crypto.FirstStepAlice(secretMessage, r) C_ := crypto.SecondStepBob(*B_, *a) C := crypto.ThirdStepAlice(*C_, *r, *A) fmt.Printf("secretMessage: %s\n", secretMessage) @@ -76,3 +85,56 @@ func Test_Steps(t *testing.T) { t.Errorf("assert -A -A + A == -A should be true == %v\n", false) } } + +func TestMint_LoadKeySet(t *testing.T) { + type args struct { + id string + } + tests := []struct { + name string + args args + want *crypto.KeySet + }{ + {name: "loadKeySet"}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + m := New("master", WithInitialKeySet("0/0/0/0")) + if m.LoadKeySet("JHV8eUnoAln/") != nil || m.LoadKeySet("+9FmGFiI7s8w") != nil { + return + } + t.Errorf("LoadKeySet()") + }) + } +} + +func TestMint_RequestMint(t *testing.T) { + type args struct { + amount int64 + } + tests := []struct { + name string + args args + want lightning.Invoice + wantErr bool + }{ + {name: "request_mint", args: args{amount: 10}, wantErr: false, want: &lnbits.Invoice{Amount: 10, Hash: "invalid"}}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + os.Setenv("LIGHTNING", "false") + m := New("master", WithStorage(db.NewSqlDatabase())) + got, err := m.RequestMint(tt.args.amount) + if (err != nil) != tt.wantErr { + t.Errorf("RequestMint() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got.GetHash() == "" { + t.Errorf("RequestMint() got = %v, want %v", got, tt.want) + } + if got.GetAmount() != tt.args.amount { + t.Errorf("RequestMint() got = %v, want %v", got, tt.want) + } + }) + } +}