diff --git a/packages/ca/heartbeat/errors.go b/packages/ca/heartbeat/errors.go
index a472a252c023cff0df75efa012b7e0cf35810e17..e93c8d37ffccf4ab229c3fcaa90f43c1f430d1e6 100644
--- a/packages/ca/heartbeat/errors.go
+++ b/packages/ca/heartbeat/errors.go
@@ -5,5 +5,6 @@ import (
 )
 
 var (
-	ErrSigningFailed = errors.Wrap(errors.New("failed to sign"), "failed to sign")
+	ErrSigningFailed    = errors.Wrap(errors.New("failed to sign"), "failed to sign")
+	ErrSignatureCorrupt = errors.Wrap(errors.New("failed to sign"), "failed to sign")
 )
diff --git a/packages/ca/heartbeat/heartbeat.go b/packages/ca/heartbeat/heartbeat.go
index 0b95910096868c4a9c5dfc860d8accd3a32da308..0873ff994f7176bd383ed29e53e0c6bde60fb04c 100644
--- a/packages/ca/heartbeat/heartbeat.go
+++ b/packages/ca/heartbeat/heartbeat.go
@@ -17,7 +17,7 @@ import (
 type Heartbeat struct {
 	nodeId             string
 	mainStatement      *OpinionStatement
-	neighborStatements map[string]*OpinionStatement
+	neighborStatements map[string][]*OpinionStatement
 	signature          []byte
 
 	nodeIdMutex             sync.RWMutex
@@ -58,14 +58,14 @@ func (heartbeat *Heartbeat) SetMainStatement(mainStatement *OpinionStatement) {
 	heartbeat.mainStatement = mainStatement
 }
 
-func (heartbeat *Heartbeat) GetNeighborStatements() map[string]*OpinionStatement {
+func (heartbeat *Heartbeat) GetNeighborStatements() map[string][]*OpinionStatement {
 	heartbeat.neighborStatementsMutex.RLock()
 	defer heartbeat.neighborStatementsMutex.RUnlock()
 
 	return heartbeat.neighborStatements
 }
 
-func (heartbeat *Heartbeat) SetNeighborStatements(neighborStatements map[string]*OpinionStatement) {
+func (heartbeat *Heartbeat) SetNeighborStatements(neighborStatements map[string][]*OpinionStatement) {
 	heartbeat.neighborStatementsMutex.Lock()
 	defer heartbeat.neighborStatementsMutex.Unlock()
 
@@ -79,6 +79,13 @@ func (heartbeat *Heartbeat) GetSignature() []byte {
 	return heartbeat.signature
 }
 
+func (heartbeat *Heartbeat) SetSignature(signature []byte) {
+	heartbeat.signatureMutex.Lock()
+	defer heartbeat.signatureMutex.Unlock()
+
+	heartbeat.signature = signature
+}
+
 func (heartbeat *Heartbeat) Sign(identity *identity.Identity) (err errors.IdentifiableError) {
 	if marshaledHeartbeat, marshalErr := heartbeat.MarshalBinary(); marshalErr == nil {
 		if signature, signingErr := identity.Sign(marshaledHeartbeat); signingErr == nil {
@@ -93,11 +100,25 @@ func (heartbeat *Heartbeat) Sign(identity *identity.Identity) (err errors.Identi
 	return
 }
 
-func (heartbeat *Heartbeat) SetSignature(signature []byte) {
-	heartbeat.signatureMutex.Lock()
-	defer heartbeat.signatureMutex.Unlock()
+func (heartbeat *Heartbeat) VerifySignature() (result bool, err errors.IdentifiableError) {
+	signature := heartbeat.GetSignature()
+	heartbeat.SetSignature(nil)
 
-	heartbeat.signature = signature
+	if marshaledHeartbeat, marshalErr := heartbeat.MarshalBinary(); marshalErr != nil {
+		heartbeat.SetSignature(signature)
+
+		err = marshalErr
+	} else {
+		heartbeat.SetSignature(signature)
+
+		if identity, identityErr := identity.FromSignedData(marshaledHeartbeat, signature); identityErr != nil {
+			err = ErrSignatureCorrupt.Derive(identityErr, "failed to retrieve identity from signature of heartbeat")
+		} else {
+			result = identity.StringIdentifier == heartbeat.GetNodeId()
+		}
+	}
+
+	return
 }
 
 func (heartbeat *Heartbeat) FromProto(proto proto.Message) {
@@ -106,12 +127,16 @@ func (heartbeat *Heartbeat) FromProto(proto proto.Message) {
 	var mainStatement OpinionStatement
 	mainStatement.FromProto(protoHeartbeat.MainStatement)
 
-	neighborStatements := make(map[string]*OpinionStatement, len(protoHeartbeat.NeighborStatements))
+	neighborStatements := make(map[string][]*OpinionStatement, len(protoHeartbeat.NeighborStatements))
 	for _, neighborStatement := range protoHeartbeat.NeighborStatements {
 		var newNeighborStatement OpinionStatement
 		newNeighborStatement.FromProto(neighborStatement)
 
-		neighborStatements[neighborStatement.NodeId] = &newNeighborStatement
+		if _, exists := neighborStatements[neighborStatement.NodeId]; !exists {
+			neighborStatements[neighborStatement.NodeId] = make([]*OpinionStatement, 0)
+		}
+
+		neighborStatements[neighborStatement.NodeId] = append(neighborStatements[neighborStatement.NodeId], &newNeighborStatement)
 	}
 
 	heartbeat.nodeId = protoHeartbeat.NodeId
@@ -123,10 +148,12 @@ func (heartbeat *Heartbeat) FromProto(proto proto.Message) {
 func (heartbeat *Heartbeat) ToProto() proto.Message {
 	neighborStatements := make([]*heartbeatProto.OpinionStatement, len(heartbeat.neighborStatements))
 	i := 0
-	for _, neighborStatement := range heartbeat.neighborStatements {
-		neighborStatements[i] = neighborStatement.ToProto().(*heartbeatProto.OpinionStatement)
+	for _, statementsOfNeighbor := range heartbeat.neighborStatements {
+		for _, neighborStatement := range statementsOfNeighbor {
+			neighborStatements[i] = neighborStatement.ToProto().(*heartbeatProto.OpinionStatement)
 
-		i++
+			i++
+		}
 	}
 
 	return &heartbeatProto.HeartBeat{
diff --git a/packages/ca/heartbeat_manager.go b/packages/ca/heartbeat_manager.go
index bda2408cc96ae6dba52fa9ad1ec18b3c124f61ba..c00fd126708a47b7fda5082d4fd133a00bdd0a3c 100644
--- a/packages/ca/heartbeat_manager.go
+++ b/packages/ca/heartbeat_manager.go
@@ -32,6 +32,12 @@ func NewHeartbeatManager(identity *identity.Identity, options ...HeartbeatManage
 	}
 }
 
+func (heartbeatManager *HeartbeatManager) AddNeighbor(neighborIdentity *identity.Identity) {
+	if _, exists := heartbeatManager.neighborManagers[neighborIdentity.StringIdentifier]; !exists {
+		heartbeatManager.neighborManagers[neighborIdentity.StringIdentifier] = NewNeighborManager()
+	}
+}
+
 func (heartbeatManager *HeartbeatManager) InitialDislike(transactionId []byte) {
 	heartbeatManager.initialOpinions[string(transactionId)] = false
 }
@@ -41,16 +47,20 @@ func (heartbeatManager *HeartbeatManager) InitialLike(transactionId []byte) {
 }
 
 func (heartbeatManager *HeartbeatManager) GenerateHeartbeat() (result *heartbeat.Heartbeat, err errors.IdentifiableError) {
-	if mainStatement, mainStatementErr := heartbeatManager.GenerateMainStatement(); mainStatementErr == nil {
-		generatedHeartbeat := heartbeat.NewHeartbeat()
-		generatedHeartbeat.SetNodeId(heartbeatManager.identity.StringIdentifier)
-		generatedHeartbeat.SetMainStatement(mainStatement)
-		generatedHeartbeat.SetNeighborStatements(nil)
-
-		if signingErr := generatedHeartbeat.Sign(heartbeatManager.identity); signingErr == nil {
-			result = generatedHeartbeat
+	if mainStatement, mainStatementErr := heartbeatManager.generateMainStatement(); mainStatementErr == nil {
+		if neighborStatements, neighborStatementErr := heartbeatManager.generateNeighborStatements(); neighborStatementErr == nil {
+			generatedHeartbeat := heartbeat.NewHeartbeat()
+			generatedHeartbeat.SetNodeId(heartbeatManager.identity.StringIdentifier)
+			generatedHeartbeat.SetMainStatement(mainStatement)
+			generatedHeartbeat.SetNeighborStatements(neighborStatements)
+
+			if signingErr := generatedHeartbeat.Sign(heartbeatManager.identity); signingErr == nil {
+				result = generatedHeartbeat
+			} else {
+				err = signingErr
+			}
 		} else {
-			err = signingErr
+			err = neighborStatementErr
 		}
 	} else {
 		err = mainStatementErr
@@ -59,11 +69,35 @@ func (heartbeatManager *HeartbeatManager) GenerateHeartbeat() (result *heartbeat
 	return
 }
 
-func (heartbeatManager *HeartbeatManager) GenerateMainStatement() (result *heartbeat.OpinionStatement, err errors.IdentifiableError) {
+func (heartbeatManager *HeartbeatManager) ApplyHeartbeat(heartbeat *heartbeat.Heartbeat) (err errors.IdentifiableError) {
+	heartbeatManager.neighborManagersMutex.RLock()
+	defer heartbeatManager.neighborManagersMutex.RUnlock()
+
+	if signatureValid, signatureErr := heartbeat.VerifySignature(); signatureErr == nil {
+		if signatureValid {
+			issuerId := heartbeat.GetNodeId()
+
+			neighborManager, neighborExists := heartbeatManager.neighborManagers[issuerId]
+			if !neighborExists {
+				err = ErrUnknownNeighbor.Derive("unknown neighbor: " + issuerId)
+			} else {
+				err = neighborManager.ApplyHeartbeat(heartbeat)
+			}
+		} else {
+			err = ErrMalformedHeartbeat.Derive("the heartbeat has an invalid signature")
+		}
+	} else {
+		err = signatureErr
+	}
+
+	return
+}
+
+func (heartbeatManager *HeartbeatManager) generateMainStatement() (result *heartbeat.OpinionStatement, err errors.IdentifiableError) {
 	mainStatement := heartbeat.NewOpinionStatement()
 	mainStatement.SetNodeId(heartbeatManager.identity.StringIdentifier)
 	mainStatement.SetTime(uint64(time.Now().Unix()))
-	mainStatement.SetToggledTransactions(heartbeatManager.GenerateToggledTransactions())
+	mainStatement.SetToggledTransactions(heartbeatManager.generateToggledTransactions())
 
 	if lastAppliedStatement := heartbeatManager.statementChain.lastAppliedStatement; lastAppliedStatement != nil {
 		mainStatement.SetPreviousStatementHash(lastAppliedStatement.GetHash())
@@ -72,7 +106,7 @@ func (heartbeatManager *HeartbeatManager) GenerateMainStatement() (result *heart
 	if signingErr := mainStatement.Sign(heartbeatManager.identity); signingErr == nil {
 		result = mainStatement
 
-		heartbeatManager.ResetInitialOpinions()
+		heartbeatManager.resetInitialOpinions()
 		heartbeatManager.statementChain.lastAppliedStatement = mainStatement
 	} else {
 		err = signingErr
@@ -81,7 +115,11 @@ func (heartbeatManager *HeartbeatManager) GenerateMainStatement() (result *heart
 	return
 }
 
-func (heartbeatManager *HeartbeatManager) GenerateToggledTransactions() []*heartbeat.ToggledTransaction {
+func (heartbeatManager *HeartbeatManager) generateNeighborStatements() (result map[string][]*heartbeat.OpinionStatement, err errors.IdentifiableError) {
+	return
+}
+
+func (heartbeatManager *HeartbeatManager) generateToggledTransactions() []*heartbeat.ToggledTransaction {
 	toggledTransactions := make([]*heartbeat.ToggledTransaction, 0)
 	for transactionId, liked := range heartbeatManager.initialOpinions {
 		if !liked {
@@ -97,22 +135,6 @@ func (heartbeatManager *HeartbeatManager) GenerateToggledTransactions() []*heart
 	return toggledTransactions
 }
 
-func (heartbeatManager *HeartbeatManager) ResetInitialOpinions() {
+func (heartbeatManager *HeartbeatManager) resetInitialOpinions() {
 	heartbeatManager.initialOpinions = make(map[string]bool)
 }
-
-func (heartbeatManager *HeartbeatManager) ApplyHeartbeat(heartbeat *heartbeat.Heartbeat) (err errors.IdentifiableError) {
-	heartbeatManager.neighborManagersMutex.RLock()
-	defer heartbeatManager.neighborManagersMutex.RUnlock()
-
-	issuerId := heartbeat.GetNodeId()
-
-	neighborManager, neighborExists := heartbeatManager.neighborManagers[issuerId]
-	if !neighborExists {
-		err = ErrUnknownNeighbor.Derive("unknown neighbor: " + issuerId)
-	} else {
-		err = neighborManager.ApplyHeartbeat(heartbeat)
-	}
-
-	return
-}
diff --git a/packages/ca/heartbeat_manager_test.go b/packages/ca/heartbeat_manager_test.go
index 9a6d2a9a7d3a1f3f879e82dc896af1dacfac5ca1..077b9ab9f2603a76848f7cb98de661e053bc0688 100644
--- a/packages/ca/heartbeat_manager_test.go
+++ b/packages/ca/heartbeat_manager_test.go
@@ -16,30 +16,41 @@ func generateRandomTransactionId() (result []byte) {
 }
 
 func TestHeartbeatManager_GenerateHeartbeat(t *testing.T) {
-	transactionId1 := generateRandomTransactionId()
-	transactionId2 := generateRandomTransactionId()
+	ownIdentity := identity.GenerateRandomIdentity()
+	neighborIdentity := identity.GenerateRandomIdentity()
 
-	heartbeatManager := NewHeartbeatManager(identity.GenerateRandomIdentity())
-	heartbeatManager.InitialDislike(transactionId1)
-	heartbeatManager.InitialDislike(transactionId2)
+	// generate first heartbeat ////////////////////////////////////////////////////////////////////////////////////////
 
-	heartbeatManager.InitialLike(generateRandomTransactionId())
+	heartbeatManager1 := NewHeartbeatManager(ownIdentity)
+	heartbeatManager1.AddNeighbor(neighborIdentity)
+	heartbeatManager1.InitialDislike(generateRandomTransactionId())
+	heartbeatManager1.InitialDislike(generateRandomTransactionId())
+	heartbeatManager1.InitialLike(generateRandomTransactionId())
 
-	result, err := heartbeatManager.GenerateHeartbeat()
+	heartbeat1, err := heartbeatManager1.GenerateHeartbeat()
 	if err != nil {
 		t.Error(err)
 
 		return
 	}
 
-	fmt.Println(result)
+	fmt.Println(heartbeat1)
 
-	result, err = heartbeatManager.GenerateHeartbeat()
+	heartbeatManager2 := NewHeartbeatManager(neighborIdentity)
+	heartbeatManager2.AddNeighbor(ownIdentity)
+	err = heartbeatManager2.ApplyHeartbeat(heartbeat1)
 	if err != nil {
 		t.Error(err)
 
 		return
 	}
 
-	fmt.Println(result)
+	heartbeat2, err := heartbeatManager2.GenerateHeartbeat()
+	if err != nil {
+		t.Error(err)
+
+		return
+	}
+
+	fmt.Println(heartbeat2)
 }
diff --git a/packages/ca/neighbor_manager.go b/packages/ca/neighbor_manager.go
index b9a03aa6c608f44f5538eaa674dd4ab794e0f075..afea44bc99a4927dc46b6a4028bf6ef48b6be228 100644
--- a/packages/ca/neighbor_manager.go
+++ b/packages/ca/neighbor_manager.go
@@ -63,13 +63,17 @@ func (neighborManager *NeighborManager) ApplyHeartbeat(heartbeat *heartbeat.Hear
 	}
 
 	// check if referenced neighbor statements are missing
-	for neighborId, neighborStatement := range neighborStatements {
+	for neighborId, statementsOfNeighbor := range neighborStatements {
 		neighborChain, exists := neighborManager.neighborChains[neighborId]
 		if exists {
-			lastAppliedNeighborStatement := neighborChain.GetLastAppliedStatement()
-			if lastAppliedNeighborStatement != nil && !bytes.Equal(lastAppliedNeighborStatement.GetHash(), neighborStatement.GetPreviousStatementHash()) {
-				return ErrMalformedHeartbeat.Derive("missing neighbor statement")
+			for _, neighborStatement := range statementsOfNeighbor {
+				lastAppliedNeighborStatement := neighborChain.GetLastAppliedStatement()
+				if lastAppliedNeighborStatement != nil && !bytes.Equal(lastAppliedNeighborStatement.GetHash(), neighborStatement.GetPreviousStatementHash()) {
+					return ErrMalformedHeartbeat.Derive("missing neighbor statement")
+				}
 			}
+		} else {
+			// 1. check if new slot is available (not full || statement of neighbor with last connection)
 		}
 	}