Skip to content

Commit

Permalink
Merge pull request #48 from elnosh/mint-nut11
Browse files Browse the repository at this point in the history
mint: NUT-11 Pay to Public Key
  • Loading branch information
elnosh authored Aug 14, 2024
2 parents 267ebb7 + 3ade5a8 commit ccee4d2
Show file tree
Hide file tree
Showing 9 changed files with 778 additions and 100 deletions.
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

0 comments on commit ccee4d2

Please sign in to comment.