Skip to content
Closed
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
6 changes: 4 additions & 2 deletions bond/bond_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,14 @@ func (cbi *BondInfo) RemoveBondAtIndex(index uint32) error {
}

// PostBondReqFromBondInfo converts the provided bond info into a post bond request.
func PostBondReqFromBondInfo(info *BondInfo) (*protocolsPb.PostBondRequest, error) {
func PostBondReqFromBondInfo(info *BondInfo, accountID []byte) (*protocolsPb.PostBondRequest, error) {
if len(info.bondParams) == 0 {
return nil, fmt.Errorf("no bonds provided")
}

req := &protocolsPb.PostBondRequest{}
req := &protocolsPb.PostBondRequest{
AccountID: accountID,
}
for _, bp := range info.bondParams {
req.Bonds = append(req.Bonds, &protocolsPb.Bond{BondID: []byte(bp.ID)})
}
Expand Down
7 changes: 6 additions & 1 deletion bond/bond_info_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,16 @@ func TestBondInfo(t *testing.T) {
// Ensure a post bond request can be created from a bond info.
bInfo.AddBonds([]*BondParams{bond1}, mockTime)

bondReq, err := PostBondReqFromBondInfo(bInfo)
testAccountID := []byte("test-account-id")
bondReq, err := PostBondReqFromBondInfo(bInfo, testAccountID)
if err != nil {
t.Fatalf("Unexpected error creating a post bond request from bond info")
}

if string(bondReq.AccountID) != string(testAccountID) {
t.Errorf("Expected account ID %s, got %s", string(testAccountID), string(bondReq.AccountID))
}

if string(bondReq.Bonds[0].BondID) != bond1.ID {
t.Fatalf("Expected bond id %s in request, got %s", bond1.ID, string(bondReq.Bonds[0].BondID))
}
Expand Down
27 changes: 26 additions & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"time"

"github.com/decred/dcrd/crypto/blake256"
"github.com/decred/slog"
"github.com/libp2p/go-libp2p"
"github.com/libp2p/go-libp2p/core/crypto"
Expand Down Expand Up @@ -44,6 +45,7 @@ type Config struct {
// Client represents a tatanka client.
type Client struct {
cfg *Config
accountID []byte
host host.Host
topicRegistry *topicRegistry
bondInfo *bond.BondInfo
Expand All @@ -61,6 +63,11 @@ func (c *Client) PeerID() peer.ID {
return c.host.ID()
}

// AccountID returns the account ID of the client.
func (c *Client) AccountID() []byte {
return c.accountID
}

// ConnectedTatankaNodePeerID returns the peer ID of the currently connected
// tatanka node. If no tatanka node connection is active, an empty string
// is returned.
Expand All @@ -72,10 +79,28 @@ func (c *Client) ConnectedTatankaNodePeerID() string {
return mc.remotePeerID().String()
}

// accountIDFromPublicKey generates an account ID from a public key using BLAKE256 hash.
func accountIDFromPublicKey(privKey crypto.PrivKey) ([]byte, error) {
pubKey := privKey.GetPublic()
pubKeyBytes, err := crypto.MarshalPublicKey(pubKey)
if err != nil {
return nil, fmt.Errorf("failed to marshal public key: %w", err)
}

hash := blake256.Sum256(pubKeyBytes)
return hash[:], nil
}

// NewClient initializes a new tatanka client.
func NewClient(cfg *Config) (*Client, error) {
accountID, err := accountIDFromPublicKey(cfg.PrivateKey)
if err != nil {
return nil, fmt.Errorf("failed to generate account ID: %w", err)
}

c := &Client{
cfg: cfg,
accountID: accountID,
topicRegistry: newTopicRegistry(),
bondInfo: bond.NewBondInfo(),
log: cfg.Logger,
Expand Down Expand Up @@ -286,7 +311,7 @@ func (c *Client) Run(ctx context.Context, bonds []*bond.BondParams) error {
// Set default connection factory if not already set (tests may override).
if c.connFactory == nil {
c.connFactory = func(peerID peer.ID) meshConn {
return newMeshConnection(c.host, peerID, c.log, c.bondInfo, c.topicRegistry.fetchTopics, c.handlePushMessage)
return newMeshConnection(c.host, peerID, c.log, c.bondInfo, c.accountID, c.topicRegistry.fetchTopics, c.handlePushMessage)
}
}

Expand Down
6 changes: 4 additions & 2 deletions client/mesh_connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type meshConnection struct {
handleMessage func(*protocolsPb.PushMessage)
fetchTopics func() []string
bondInfo *bond.BondInfo
accountID []byte
log slog.Logger

cancelFuncMtx sync.RWMutex
Expand All @@ -45,14 +46,15 @@ type meshConnection struct {

var _ meshConn = (*meshConnection)(nil)

func newMeshConnection(host host.Host, peerID peer.ID, logger slog.Logger, bondInfo *bond.BondInfo, fetchTopics func() []string, handleMessage func(*protocolsPb.PushMessage)) *meshConnection {
func newMeshConnection(host host.Host, peerID peer.ID, logger slog.Logger, bondInfo *bond.BondInfo, accountID []byte, fetchTopics func() []string, handleMessage func(*protocolsPb.PushMessage)) *meshConnection {
return &meshConnection{
host: host,
peerID: peerID,
log: logger,
handleMessage: handleMessage,
fetchTopics: fetchTopics,
bondInfo: bondInfo,
accountID: accountID,
readyCh: make(chan struct{}, 1),
}
}
Expand Down Expand Up @@ -210,7 +212,7 @@ func (m *meshConnection) postBondInternal(ctx context.Context, req *protocolsPb.
func (m *meshConnection) postBond(ctx context.Context) error {
hostID := m.host.ID()
for range maxPostBondRetries {
req, err := bond.PostBondReqFromBondInfo(m.bondInfo)
req, err := bond.PostBondReqFromBondInfo(m.bondInfo, m.accountID)
if err != nil {
return fmt.Errorf("failed to create post bond request: %w", err)
}
Expand Down
3 changes: 2 additions & 1 deletion client/mesh_connection_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ func newMeshConnHarness(t *testing.T, topics []string) *meshConnHarness {
h.tatankaHost.ID(),
h.logger,
bondInfo,
[]byte("test-account-id"),
func() []string { return topics },
func(msg *protocolsPb.PushMessage) {
h.clientReceived <- msg
Expand Down Expand Up @@ -514,7 +515,7 @@ func TestMeshConnection_PostBondWithRetries(t *testing.T) {
},
}

bondReq, err := bond.PostBondReqFromBondInfo(h.meshConn.bondInfo)
bondReq, err := bond.PostBondReqFromBondInfo(h.meshConn.bondInfo, h.meshConn.accountID)
if err != nil {
t.Fatalf("Unexpected error creating post bond request: %v", err)
}
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/martonp/tatanka-mesh
go 1.24.9

require (
github.com/decred/dcrd/crypto/blake256 v1.1.0
github.com/decred/slog v1.2.0
github.com/go-chi/chi/v5 v5.2.3
github.com/go-chi/cors v1.2.2
Expand Down
17 changes: 13 additions & 4 deletions protocols/pb/protocols.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion protocols/pb/protocols.proto
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,8 @@ message Bond {
}

message PostBondRequest {
repeated Bond bonds = 1;
bytes accountID = 1;
repeated Bond bonds = 2;
}


Expand Down