 9bdcbe0447
			
		
	
	9bdcbe0447
	
	
	
		
			
			Major integrations and fixes: - Added BACKBEAT SDK integration for P2P operation timing - Implemented beat-aware status tracking for distributed operations - Added Docker secrets support for secure license management - Resolved KACHING license validation via HTTPS/TLS - Updated docker-compose configuration for clean stack deployment - Disabled rollback policies to prevent deployment failures - Added license credential storage (CHORUS-DEV-MULTI-001) Technical improvements: - BACKBEAT P2P operation tracking with phase management - Enhanced configuration system with file-based secrets - Improved error handling for license validation - Clean separation of KACHING and CHORUS deployment stacks 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
		
			
				
	
	
		
			233 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			233 lines
		
	
	
		
			5.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package blankhost
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"io"
 | |
| 
 | |
| 	"github.com/libp2p/go-libp2p/core/connmgr"
 | |
| 	"github.com/libp2p/go-libp2p/core/event"
 | |
| 	"github.com/libp2p/go-libp2p/core/host"
 | |
| 	"github.com/libp2p/go-libp2p/core/network"
 | |
| 	"github.com/libp2p/go-libp2p/core/peer"
 | |
| 	"github.com/libp2p/go-libp2p/core/peerstore"
 | |
| 	"github.com/libp2p/go-libp2p/core/protocol"
 | |
| 	"github.com/libp2p/go-libp2p/core/record"
 | |
| 	"github.com/libp2p/go-libp2p/p2p/host/eventbus"
 | |
| 
 | |
| 	logging "github.com/ipfs/go-log/v2"
 | |
| 
 | |
| 	ma "github.com/multiformats/go-multiaddr"
 | |
| 	mstream "github.com/multiformats/go-multistream"
 | |
| )
 | |
| 
 | |
| var log = logging.Logger("blankhost")
 | |
| 
 | |
| // BlankHost is the thinnest implementation of the host.Host interface
 | |
| type BlankHost struct {
 | |
| 	n        network.Network
 | |
| 	mux      *mstream.MultistreamMuxer[protocol.ID]
 | |
| 	cmgr     connmgr.ConnManager
 | |
| 	eventbus event.Bus
 | |
| 	emitters struct {
 | |
| 		evtLocalProtocolsUpdated event.Emitter
 | |
| 	}
 | |
| }
 | |
| 
 | |
| type config struct {
 | |
| 	cmgr     connmgr.ConnManager
 | |
| 	eventBus event.Bus
 | |
| }
 | |
| 
 | |
| type Option = func(cfg *config)
 | |
| 
 | |
| func WithConnectionManager(cmgr connmgr.ConnManager) Option {
 | |
| 	return func(cfg *config) {
 | |
| 		cfg.cmgr = cmgr
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func WithEventBus(eventBus event.Bus) Option {
 | |
| 	return func(cfg *config) {
 | |
| 		cfg.eventBus = eventBus
 | |
| 	}
 | |
| }
 | |
| 
 | |
| func NewBlankHost(n network.Network, options ...Option) *BlankHost {
 | |
| 	cfg := config{
 | |
| 		cmgr: &connmgr.NullConnMgr{},
 | |
| 	}
 | |
| 	for _, opt := range options {
 | |
| 		opt(&cfg)
 | |
| 	}
 | |
| 
 | |
| 	bh := &BlankHost{
 | |
| 		n:    n,
 | |
| 		cmgr: cfg.cmgr,
 | |
| 		mux:  mstream.NewMultistreamMuxer[protocol.ID](),
 | |
| 	}
 | |
| 	if bh.eventbus == nil {
 | |
| 		bh.eventbus = eventbus.NewBus(eventbus.WithMetricsTracer(eventbus.NewMetricsTracer()))
 | |
| 	}
 | |
| 
 | |
| 	// subscribe the connection manager to network notifications (has no effect with NullConnMgr)
 | |
| 	n.Notify(bh.cmgr.Notifee())
 | |
| 
 | |
| 	var err error
 | |
| 	if bh.emitters.evtLocalProtocolsUpdated, err = bh.eventbus.Emitter(&event.EvtLocalProtocolsUpdated{}); err != nil {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	n.SetStreamHandler(bh.newStreamHandler)
 | |
| 
 | |
| 	// persist a signed peer record for self to the peerstore.
 | |
| 	if err := bh.initSignedRecord(); err != nil {
 | |
| 		log.Errorf("error creating blank host, err=%s", err)
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return bh
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) initSignedRecord() error {
 | |
| 	cab, ok := peerstore.GetCertifiedAddrBook(bh.n.Peerstore())
 | |
| 	if !ok {
 | |
| 		log.Error("peerstore does not support signed records")
 | |
| 		return errors.New("peerstore does not support signed records")
 | |
| 	}
 | |
| 	rec := peer.PeerRecordFromAddrInfo(peer.AddrInfo{ID: bh.ID(), Addrs: bh.Addrs()})
 | |
| 	ev, err := record.Seal(rec, bh.Peerstore().PrivKey(bh.ID()))
 | |
| 	if err != nil {
 | |
| 		log.Errorf("failed to create signed record for self, err=%s", err)
 | |
| 		return fmt.Errorf("failed to create signed record for self, err=%s", err)
 | |
| 	}
 | |
| 	_, err = cab.ConsumePeerRecord(ev, peerstore.PermanentAddrTTL)
 | |
| 	if err != nil {
 | |
| 		log.Errorf("failed to persist signed record to peerstore,err=%s", err)
 | |
| 		return fmt.Errorf("failed to persist signed record for self, err=%s", err)
 | |
| 	}
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| var _ host.Host = (*BlankHost)(nil)
 | |
| 
 | |
| func (bh *BlankHost) Addrs() []ma.Multiaddr {
 | |
| 	addrs, err := bh.n.InterfaceListenAddresses()
 | |
| 	if err != nil {
 | |
| 		log.Debug("error retrieving network interface addrs: ", err)
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	return addrs
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) Close() error {
 | |
| 	return bh.n.Close()
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) Connect(ctx context.Context, ai peer.AddrInfo) error {
 | |
| 	// absorb addresses into peerstore
 | |
| 	bh.Peerstore().AddAddrs(ai.ID, ai.Addrs, peerstore.TempAddrTTL)
 | |
| 
 | |
| 	cs := bh.n.ConnsToPeer(ai.ID)
 | |
| 	if len(cs) > 0 {
 | |
| 		return nil
 | |
| 	}
 | |
| 
 | |
| 	_, err := bh.Network().DialPeer(ctx, ai.ID)
 | |
| 	if err != nil {
 | |
| 		return fmt.Errorf("failed to dial: %w", err)
 | |
| 	}
 | |
| 	return err
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) Peerstore() peerstore.Peerstore {
 | |
| 	return bh.n.Peerstore()
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) ID() peer.ID {
 | |
| 	return bh.n.LocalPeer()
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) NewStream(ctx context.Context, p peer.ID, protos ...protocol.ID) (network.Stream, error) {
 | |
| 	s, err := bh.n.NewStream(ctx, p)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to open stream: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	selected, err := mstream.SelectOneOf(protos, s)
 | |
| 	if err != nil {
 | |
| 		s.Reset()
 | |
| 		return nil, fmt.Errorf("failed to negotiate protocol: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	s.SetProtocol(selected)
 | |
| 	bh.Peerstore().AddProtocols(p, selected)
 | |
| 
 | |
| 	return s, nil
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) RemoveStreamHandler(pid protocol.ID) {
 | |
| 	bh.Mux().RemoveHandler(pid)
 | |
| 	bh.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{
 | |
| 		Removed: []protocol.ID{pid},
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) SetStreamHandler(pid protocol.ID, handler network.StreamHandler) {
 | |
| 	bh.Mux().AddHandler(pid, func(p protocol.ID, rwc io.ReadWriteCloser) error {
 | |
| 		is := rwc.(network.Stream)
 | |
| 		is.SetProtocol(p)
 | |
| 		handler(is)
 | |
| 		return nil
 | |
| 	})
 | |
| 	bh.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{
 | |
| 		Added: []protocol.ID{pid},
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) SetStreamHandlerMatch(pid protocol.ID, m func(protocol.ID) bool, handler network.StreamHandler) {
 | |
| 	bh.Mux().AddHandlerWithFunc(pid, m, func(p protocol.ID, rwc io.ReadWriteCloser) error {
 | |
| 		is := rwc.(network.Stream)
 | |
| 		is.SetProtocol(p)
 | |
| 		handler(is)
 | |
| 		return nil
 | |
| 	})
 | |
| 	bh.emitters.evtLocalProtocolsUpdated.Emit(event.EvtLocalProtocolsUpdated{
 | |
| 		Added: []protocol.ID{pid},
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // newStreamHandler is the remote-opened stream handler for network.Network
 | |
| func (bh *BlankHost) newStreamHandler(s network.Stream) {
 | |
| 	protoID, handle, err := bh.Mux().Negotiate(s)
 | |
| 	if err != nil {
 | |
| 		log.Infow("protocol negotiation failed", "error", err)
 | |
| 		s.Reset()
 | |
| 		return
 | |
| 	}
 | |
| 
 | |
| 	s.SetProtocol(protoID)
 | |
| 
 | |
| 	handle(protoID, s)
 | |
| }
 | |
| 
 | |
| // TODO: i'm not sure this really needs to be here
 | |
| func (bh *BlankHost) Mux() protocol.Switch {
 | |
| 	return bh.mux
 | |
| }
 | |
| 
 | |
| // TODO: also not sure this fits... Might be better ways around this (leaky abstractions)
 | |
| func (bh *BlankHost) Network() network.Network {
 | |
| 	return bh.n
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) ConnManager() connmgr.ConnManager {
 | |
| 	return bh.cmgr
 | |
| }
 | |
| 
 | |
| func (bh *BlankHost) EventBus() event.Bus {
 | |
| 	return bh.eventbus
 | |
| }
 |