Skip to content

Commit d34a848

Browse files
authored
Merge pull request #22 from b-open-io/opl-335-strings
OPL-335 Wallet string types
2 parents 589f967 + bf91de0 commit d34a848

File tree

126 files changed

+4805
-1134
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

126 files changed

+4805
-1134
lines changed

auth/clients/authhttp/authhttp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ func (a *AuthFetch) handlePaymentAndRetry(ctx context.Context, urlStr string, co
759759
Outputs: []wallet.CreateActionOutput{
760760
{
761761
Satoshis: satoshisRequired,
762-
LockingScript: fmt.Sprintf("P2PKH:%s", derivedKey.PublicKey.ToDERHex()),
762+
LockingScript: derivedKey.PublicKey.ToDER(),
763763
CustomInstructions: fmt.Sprintf(`{"derivationPrefix":"%s","derivationSuffix":"%s","payee":"%s"}`,
764764
derivationPrefix, derivationSuffix, serverIdentityKey),
765765
OutputDescription: "HTTP request payment",

auth/clients/authhttp/authhttp_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func TestNew(t *testing.T) {
5353
mockWallet := wallet.NewMockWallet(t)
5454
mockSessionManager := NewMockSessionManager()
5555
requestedCerts := &utils.RequestedCertificateSet{
56-
Certifiers: []string{},
56+
Certifiers: []wallet.HexBytes33{},
5757
CertificateTypes: make(utils.RequestedCertificateTypeIDAndFieldList),
5858
}
5959

@@ -74,7 +74,7 @@ func TestNewWithNilSessionManager(t *testing.T) {
7474
// Set up dependencies
7575
mockWallet := wallet.NewMockWallet(t)
7676
requestedCerts := &utils.RequestedCertificateSet{
77-
Certifiers: []string{},
77+
Certifiers: []wallet.HexBytes33{},
7878
CertificateTypes: make(utils.RequestedCertificateTypeIDAndFieldList),
7979
}
8080

auth/peer.go

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,22 @@ const AUTH_PROTOCOL_ID = "authrite message signature"
2121
// AUTH_VERSION is the version of the auth protocol
2222
const AUTH_VERSION = "0.1"
2323

24+
// OnGeneralMessageReceivedCallback is called when a general message is received from a peer.
25+
// The callback receives the sender's public key and the message payload.
2426
type OnGeneralMessageReceivedCallback func(senderPublicKey *ec.PublicKey, payload []byte) error
27+
28+
// OnCertificateReceivedCallback is called when certificates are received from a peer.
29+
// The callback receives the sender's public key and the list of certificates.
2530
type OnCertificateReceivedCallback func(senderPublicKey *ec.PublicKey, certs []*certificates.VerifiableCertificate) error
31+
32+
// OnCertificateRequestReceivedCallback is called when a certificate request is received from a peer.
33+
// The callback receives the sender's public key and the requested certificate set.
2634
type OnCertificateRequestReceivedCallback func(senderPublicKey *ec.PublicKey, requestedCertificates utils.RequestedCertificateSet) error
2735

36+
// Peer represents a peer capable of performing mutual authentication.
37+
// It manages sessions, handles authentication handshakes, certificate requests and responses,
38+
// and sending and receiving general messages over a transport layer.
39+
// This implementation supports multiple concurrent sessions per peer identity key.
2840
type Peer struct {
2941
sessionManager SessionManager
3042
transport Transport
@@ -43,6 +55,7 @@ type Peer struct {
4355
logger *log.Logger // Logger for debug messages
4456
}
4557

58+
// PeerOptions contains configuration options for creating a new Peer instance.
4659
type PeerOptions struct {
4760
Wallet wallet.Interface
4861
Transport Transport
@@ -85,7 +98,7 @@ func NewPeer(cfg *PeerOptions) *Peer {
8598
peer.CertificatesToRequest = cfg.CertificatesToRequest
8699
} else {
87100
peer.CertificatesToRequest = &utils.RequestedCertificateSet{
88-
Certifiers: []string{},
101+
Certifiers: []wallet.HexBytes33{},
89102
CertificateTypes: make(utils.RequestedCertificateTypeIDAndFieldList),
90103
}
91104
}

auth/peer_test.go

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"github.com/bsv-blockchain/go-sdk/auth/certificates"
1515
"github.com/bsv-blockchain/go-sdk/auth/utils"
1616
ec "github.com/bsv-blockchain/go-sdk/primitives/ec"
17+
tu "github.com/bsv-blockchain/go-sdk/util/test_util"
1718
"github.com/bsv-blockchain/go-sdk/wallet"
1819
"github.com/stretchr/testify/require"
1920
)
@@ -404,7 +405,7 @@ func (t *LoggingMockTransport) OnData(callback func(context.Context, *AuthMessag
404405

405406
// TestPeerCertificateExchange tests certificate request and exchange
406407
func TestPeerCertificateExchange(t *testing.T) {
407-
certType := "testCertType"
408+
var certType = tu.GetByte32FromString("testCertType")
408409
requiredField := "testField"
409410

410411
// Setup logging
@@ -451,20 +452,20 @@ func TestPeerCertificateExchange(t *testing.T) {
451452
// Create raw certificates with proper base64 encoding using our helper
452453
aliceCertRaw := wallet.Certificate{
453454
Type: certType,
454-
SerialNumber: "serial1",
455+
SerialNumber: tu.GetByte32FromString("serial1"),
455456
Subject: aliceSubject,
456457
Certifier: bobSubject,
457458
Fields: map[string]string{requiredField: "fieldValue"},
458-
RevocationOutpoint: "abcd1234:0",
459+
RevocationOutpoint: tu.OutpointFromString(t, "a755810c21e17183ff6db6685f0de239fd3a0a3c0d4ba7773b0b0d1748541e2b.0"),
459460
}
460461

461462
bobCertRaw := wallet.Certificate{
462463
Type: certType,
463-
SerialNumber: "serial2",
464+
SerialNumber: tu.GetByte32FromString("serial2"),
464465
Subject: bobSubject,
465466
Certifier: aliceSubject,
466467
Fields: map[string]string{requiredField: "fieldValue"},
467-
RevocationOutpoint: "abcd1234:1",
468+
RevocationOutpoint: tu.OutpointFromString(t, "a755810c21e17183ff6db6685f0de239fd3a0a3c0d4ba7773b0b0d1748541e2b.1"),
468469
}
469470

470471
// Sign the certificates properly
@@ -504,8 +505,8 @@ func TestPeerCertificateExchange(t *testing.T) {
504505
}
505506

506507
// Debug certificate signatures
507-
logger.Printf("DEBUG: Alice cert signature: %s", aliceCert.Signature)
508-
logger.Printf("DEBUG: Bob cert signature: %s", bobCert.Signature)
508+
logger.Printf("DEBUG: Alice cert signature: %x", aliceCert.Signature)
509+
logger.Printf("DEBUG: Bob cert signature: %x", bobCert.Signature)
509510

510511
// Create mock keyring results - also properly encoded
511512
fieldValueBase64 := base64.StdEncoding.EncodeToString([]byte("key-for-field"))
@@ -620,14 +621,14 @@ func TestPeerCertificateExchange(t *testing.T) {
620621

621622
// Set certificate requirements - We need to use the RAW type string here, not base64 encoded
622623
aliceCertReqs := &utils.RequestedCertificateSet{
623-
Certifiers: []string{"any"}, // "any" is special value that accepts any certifier
624+
Certifiers: []wallet.HexBytes33{tu.GetByte33FromString("any")}, // "any" is special value that accepts any certifier
624625
CertificateTypes: utils.RequestedCertificateTypeIDAndFieldList{
625626
certType: []string{requiredField},
626627
},
627628
}
628629

629630
bobCertReqs := &utils.RequestedCertificateSet{
630-
Certifiers: []string{"any"}, // "any" is special value that accepts any certifier
631+
Certifiers: []wallet.HexBytes33{tu.GetByte33FromString("any")}, // "any" is special value that accepts any certifier
631632
CertificateTypes: utils.RequestedCertificateTypeIDAndFieldList{
632633
certType: []string{requiredField},
633634
},
@@ -907,7 +908,8 @@ func TestPeerMultiDeviceAuthentication(t *testing.T) {
907908
// if at least one required field is present
908909
func TestPartialCertificateAcceptance(t *testing.T) {
909910
// Create a mock function to intercept certificate requests
910-
certType := "identityCert"
911+
var certType [32]byte
912+
copy(certType[:], "identityCert")
911913

912914
// Create test wallets with recognizable identities
913915
aliceKey, err := ec.NewPrivateKey()
@@ -941,20 +943,20 @@ func TestPartialCertificateAcceptance(t *testing.T) {
941943
// Create raw certificates
942944
aliceCertRaw := wallet.Certificate{
943945
Type: certType,
944-
SerialNumber: "alice-serial",
946+
SerialNumber: tu.GetByte32FromString("alice-serial"),
945947
Subject: aliceKey.PubKey(),
946948
Certifier: bobKey.PubKey(),
947949
Fields: map[string]string{"name": "Alice"},
948-
RevocationOutpoint: "abcd1234:0",
950+
RevocationOutpoint: tu.OutpointFromString(t, "a755810c21e17183ff6db6685f0de239fd3a0a3c0d4ba7773b0b0d1748541e2b.0"),
949951
}
950952

951953
bobCertRaw := wallet.Certificate{
952954
Type: certType,
953-
SerialNumber: "bob-serial",
955+
SerialNumber: tu.GetByte32FromString("bob-serial"),
954956
Subject: bobKey.PubKey(),
955957
Certifier: aliceKey.PubKey(),
956958
Fields: map[string]string{"name": "Bob"},
957-
RevocationOutpoint: "abcd1234:1",
959+
RevocationOutpoint: tu.OutpointFromString(t, "a755810c21e17183ff6db6685f0de239fd3a0a3c0d4ba7773b0b0d1748541e2b.1"),
958960
}
959961

960962
// Sign the certificates properly
@@ -1112,7 +1114,7 @@ func TestPartialCertificateAcceptance(t *testing.T) {
11121114

11131115
// Setup certificate requirements - requesting two fields but accepting partial matches
11141116
requestedCertificates := &utils.RequestedCertificateSet{
1115-
Certifiers: []string{"any"},
1117+
Certifiers: []wallet.HexBytes33{tu.GetByte33FromString("any")},
11161118
CertificateTypes: utils.RequestedCertificateTypeIDAndFieldList{
11171119
certType: []string{"name", "email"},
11181120
},
@@ -1221,7 +1223,8 @@ func TestLibraryCardVerification(t *testing.T) {
12211223
t.Skip("Temporarily skipping until we fix signature verification issue")
12221224

12231225
// Create a mock function to intercept certificate requests
1224-
certType := "libraryCard"
1226+
var certType [32]byte
1227+
copy(certType[:], "libraryCard")
12251228

12261229
// Create test wallets with recognizable identities
12271230
aliceKey, err := ec.NewPrivateKey()
@@ -1255,11 +1258,11 @@ func TestLibraryCardVerification(t *testing.T) {
12551258
// Bob has a library card - first create raw
12561259
bobCertRaw := wallet.Certificate{
12571260
Type: certType,
1258-
SerialNumber: "lib-123456",
1261+
SerialNumber: tu.GetByte32FromString("lib-123456"),
12591262
Subject: bobKey.PubKey(),
12601263
Certifier: aliceKey.PubKey(),
12611264
Fields: map[string]string{"name": "Bob", "cardNumber": "123456"},
1262-
RevocationOutpoint: "abcd1234:1",
1265+
RevocationOutpoint: tu.OutpointFromString(t, "a755810c21e17183ff6db6685f0de239fd3a0a3c0d4ba7773b0b0d1748541e2b.1"),
12631266
}
12641267

12651268
// Sign the certificate properly
@@ -1380,7 +1383,7 @@ func TestLibraryCardVerification(t *testing.T) {
13801383

13811384
// Setup certificate requirements - Alice requires Bob's library card number
13821385
alice.CertificatesToRequest = &utils.RequestedCertificateSet{
1383-
Certifiers: []string{"any"},
1386+
Certifiers: []wallet.HexBytes33{tu.GetByte33FromString("any")},
13841387
CertificateTypes: utils.RequestedCertificateTypeIDAndFieldList{
13851388
certType: []string{"cardNumber"},
13861389
},
@@ -1400,7 +1403,7 @@ func TestLibraryCardVerification(t *testing.T) {
14001403

14011404
// Alice explicitly requests Bob's certificate
14021405
err = alice.RequestCertificates(ctx, bobPubKey.PublicKey, utils.RequestedCertificateSet{
1403-
Certifiers: []string{"any"},
1406+
Certifiers: []wallet.HexBytes33{tu.GetByte33FromString("any")},
14041407
CertificateTypes: utils.RequestedCertificateTypeIDAndFieldList{
14051408
certType: []string{"cardNumber"},
14061409
},
@@ -1575,24 +1578,29 @@ func TestNonmatchingCertificateRejection(t *testing.T) {
15751578
return &wallet.VerifySignatureResult{Valid: true}, nil
15761579
}
15771580

1581+
var certTypeA [32]byte
1582+
copy(certTypeA[:], "partnerA")
1583+
var certTypeB [32]byte
1584+
copy(certTypeB[:], "partnerB")
1585+
15781586
// Alice has "partnerA" certificate, Bob has "partnerB" certificate
15791587
// They shouldn't accept each other's certificates
15801588
aliceCertRaw := wallet.Certificate{
1581-
Type: "partnerA",
1582-
SerialNumber: "alice-serial",
1589+
Type: certTypeA,
1590+
SerialNumber: tu.GetByte32FromString("alice-serial"),
15831591
Subject: aliceKey.PubKey(),
15841592
Certifier: bobKey.PubKey(),
15851593
Fields: map[string]string{"name": "Alice"},
1586-
RevocationOutpoint: "abcd1234:0",
1594+
RevocationOutpoint: tu.OutpointFromString(t, "a755810c21e17183ff6db6685f0de239fd3a0a3c0d4ba7773b0b0d1748541e2b.0"),
15871595
}
15881596

15891597
bobCertRaw := wallet.Certificate{
1590-
Type: "partnerB",
1591-
SerialNumber: "bob-serial",
1598+
Type: certTypeB,
1599+
SerialNumber: tu.GetByte32FromString("bob-serial"),
15921600
Subject: bobKey.PubKey(),
15931601
Certifier: aliceKey.PubKey(),
15941602
Fields: map[string]string{"name": "Bob"},
1595-
RevocationOutpoint: "abcd1234:1",
1603+
RevocationOutpoint: tu.OutpointFromString(t, "a755810c21e17183ff6db6685f0de239fd3a0a3c0d4ba7773b0b0d1748541e2b.1"),
15961604
}
15971605

15981606
// Sign certificates properly
@@ -1653,16 +1661,16 @@ func TestNonmatchingCertificateRejection(t *testing.T) {
16531661

16541662
// Create peers with different certificate requirements
16551663
aliceRequiredCerts := utils.RequestedCertificateSet{
1656-
Certifiers: []string{"any"},
1664+
Certifiers: []wallet.HexBytes33{tu.GetByte33FromString("any")},
16571665
CertificateTypes: utils.RequestedCertificateTypeIDAndFieldList{
1658-
"partnerA": []string{"name"}, // Alice only accepts partnerA certs
1666+
certTypeA: []string{"name"}, // Alice only accepts partnerA certs
16591667
},
16601668
}
16611669

16621670
bobRequiredCerts := utils.RequestedCertificateSet{
1663-
Certifiers: []string{"any"},
1671+
Certifiers: []wallet.HexBytes33{tu.GetByte33FromString("any")},
16641672
CertificateTypes: utils.RequestedCertificateTypeIDAndFieldList{
1665-
"partnerB": []string{"name"}, // Bob only accepts partnerB certs
1673+
certTypeB: []string{"name"}, // Bob only accepts partnerB certs
16661674
},
16671675
}
16681676

auth/transports/simplified_http_transport.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ func (t *SimplifiedHTTPTransport) Send(ctx context.Context, message *auth.AuthMe
142142
return nil
143143
}
144144

145+
// GetRegisteredOnData returns the first registered callback function for handling incoming AuthMessages.
146+
// Returns an error if no handlers are registered.
145147
func (t *SimplifiedHTTPTransport) GetRegisteredOnData() (func(context.Context, *auth.AuthMessage) error, error) {
146148
t.mu.Lock()
147149
defer t.mu.Unlock()

auth/transports/websocket_transport.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,15 @@ type WebSocketTransport struct {
2525
readDeadline time.Duration
2626
}
2727

28+
// WebSocketTransportOptions contains configuration options for the WebSocketTransport.
2829
type WebSocketTransportOptions struct {
2930
BaseURL string
3031
ReadDeadline int // seconds, default 30
3132
}
3233

34+
// NewWebSocketTransport creates a new WebSocket transport instance with the given options.
35+
// The BaseURL is required and must be a valid WebSocket URL.
36+
// If ReadDeadline is not specified or is zero, it defaults to 30 seconds.
3337
func NewWebSocketTransport(options *WebSocketTransportOptions) (*WebSocketTransport, error) {
3438
if options.BaseURL == "" {
3539
return nil, errors.New("BaseURL is required for WebSocket transport")

auth/types.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"encoding/base64"
77
"encoding/json"
88
"fmt"
9-
"slices"
109
"sync"
1110

1211
"github.com/bsv-blockchain/go-sdk/auth/certificates"
@@ -109,18 +108,24 @@ func ValidateCertificates(
109108
types := certificatesRequested.CertificateTypes
110109

111110
// Check certifier matches
112-
certifierKey := cert.Certifier.ToDERHex()
113-
if !slices.Contains(certifiers, certifierKey) {
111+
certifierKey := cert.Certifier.ToDER()
112+
if !wallet.BytesInHex33Slice(certifiers, certifierKey) {
114113
errCh <- fmt.Errorf(
115-
"certificate with serial number %s has an unrequested certifier: %s",
114+
"certificate with serial number %s has an unrequested certifier: %x",
116115
cert.SerialNumber,
117116
certifierKey,
118117
)
119118
return
120119
}
121120

121+
certType, err := cert.Type.ToArray()
122+
if err != nil {
123+
errCh <- fmt.Errorf("failed to convert certificate type to byte array: %v", err)
124+
return
125+
}
126+
122127
// Check type match
123-
_, typeExists := types[string(cert.Type)]
128+
_, typeExists := types[certType]
124129
if !typeExists {
125130
errCh <- fmt.Errorf("certificate with type %s was not requested", cert.Type)
126131
return
@@ -191,6 +196,8 @@ type CertificateQuery struct {
191196
Subject string
192197
}
193198

199+
// MarshalJSON customizes the JSON marshaling for AuthMessage to ensure proper formatting
200+
// of identity keys, payload, and signature fields as base64-encoded strings.
194201
func (m *AuthMessage) MarshalJSON() ([]byte, error) {
195202
type Alias AuthMessage
196203

@@ -232,6 +239,8 @@ func (m *AuthMessage) MarshalJSON() ([]byte, error) {
232239
})
233240
}
234241

242+
// UnmarshalJSON customizes the JSON unmarshaling for AuthMessage to properly decode
243+
// base64-encoded fields and reconstruct the public key from the hex-encoded identity key.
235244
func (m *AuthMessage) UnmarshalJSON(data []byte) error {
236245
type Alias AuthMessage
237246

0 commit comments

Comments
 (0)