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-11 Pay to Public Key #48

Merged
merged 2 commits into from
Aug 14, 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
44 changes: 0 additions & 44 deletions cashu/cashu.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,6 @@ import (
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)

type SecretKind int

const (
Random SecretKind = iota
P2PK
)

// Cashu BlindedMessage. See https://github.com/cashubtc/nuts/blob/main/00.md#blindedmessage
type BlindedMessage struct {
Amount uint64 `json:"amount"`
Expand Down Expand Up @@ -80,43 +73,6 @@ type Proof struct {
Witness string `json:"witness,omitempty"`
}

func (p Proof) IsSecretP2PK() bool {
return p.SecretType() == P2PK
}

func (p Proof) SecretType() SecretKind {
var rawJsonSecret []json.RawMessage
// if not valid json, assume it is random secret
if err := json.Unmarshal([]byte(p.Secret), &rawJsonSecret); err != nil {
return Random
}

// Well-known secret should have a length of at least 2
if len(rawJsonSecret) < 2 {
return Random
}

var kind string
if err := json.Unmarshal(rawJsonSecret[0], &kind); err != nil {
return Random
}

if kind == "P2PK" {
return P2PK
}

return Random
}

func (kind SecretKind) String() string {
switch kind {
case P2PK:
return "P2PK"
default:
return "random"
}
}

type Proofs []Proof

// Amount returns the total amount from
Expand Down
38 changes: 0 additions & 38 deletions cashu/cashu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,41 +121,3 @@ 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)
}
}
}
42 changes: 41 additions & 1 deletion cashu/nuts/nut10/nut10.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,54 @@ import (
"github.com/elnosh/gonuts/cashu"
)

type SecretKind int

const (
AnyoneCanSpend SecretKind = iota
P2PK
)

func SecretType(proof cashu.Proof) SecretKind {
var rawJsonSecret []json.RawMessage
// if not valid json, assume it is random secret
if err := json.Unmarshal([]byte(proof.Secret), &rawJsonSecret); err != nil {
return AnyoneCanSpend
}

// Well-known secret should have a length of at least 2
if len(rawJsonSecret) < 2 {
return AnyoneCanSpend
}

var kind string
if err := json.Unmarshal(rawJsonSecret[0], &kind); err != nil {
return AnyoneCanSpend
}

if kind == "P2PK" {
return P2PK
}

return AnyoneCanSpend
}

func (kind SecretKind) String() string {
switch kind {
case P2PK:
return "P2PK"
default:
return "anyonecanspend"
}
}

type WellKnownSecret struct {
Nonce string `json:"nonce"`
Data string `json:"data"`
Tags [][]string `json:"tags"`
}

// SerializeSecret returns the json string to be put in the secret field of a proof
func SerializeSecret(kind cashu.SecretKind, secretData WellKnownSecret) (string, error) {
func SerializeSecret(kind SecretKind, secretData WellKnownSecret) (string, error) {
jsonSecret, err := json.Marshal(secretData)
if err != nil {
return "", err
Expand Down
40 changes: 39 additions & 1 deletion cashu/nuts/nut10/nut10_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,44 @@ import (
"github.com/elnosh/gonuts/cashu"
)

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

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

{
proof: cashu.Proof{Secret: `someranadomsecret`},
expectedKind: AnyoneCanSpend,
expectedIsP2PK: false,
},
}

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

isP2PK := kind == P2PK
if isP2PK != test.expectedIsP2PK {
t.Fatalf("expected '%v' but got '%v' instead", test.expectedIsP2PK, isP2PK)
}
}
}

func TestSerializeSecret(t *testing.T) {
secretData := WellKnownSecret{
Nonce: "da62796403af76c80cd6ce9153ed3746",
Expand All @@ -16,7 +54,7 @@ func TestSerializeSecret(t *testing.T) {
},
}

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