diff --git a/packages/ca/heartbeat/opinion_statement.go b/packages/ca/heartbeat/opinion_statement.go index 95819a4843dd4085a311abe778f0795fc972b292..5442749ca92efd95e346a9ed279688137445c2ea 100644 --- a/packages/ca/heartbeat/opinion_statement.go +++ b/packages/ca/heartbeat/opinion_statement.go @@ -3,6 +3,8 @@ package heartbeat import ( "sync" + "golang.org/x/crypto/blake2b" + "github.com/iotaledger/goshimmer/packages/stringify" "github.com/iotaledger/goshimmer/packages/errors" @@ -106,6 +108,17 @@ func (opinionStatement *OpinionStatement) GetHash() []byte { opinionStatement.hashMutex.RLock() defer opinionStatement.hashMutex.RUnlock() + if opinionStatement.hash == nil { + marshaledStatement, marshalErr := opinionStatement.MarshalBinary() + if marshalErr != nil { + panic(marshalErr) + } + + hash := blake2b.Sum256(marshaledStatement) + + opinionStatement.hash = hash[:] + } + return opinionStatement.hash } diff --git a/packages/ca/heartbeat_manager.go b/packages/ca/heartbeat_manager.go index a1d8d64e3499e6bac7b6ec330501dcffec479e63..3f0ef5b7495bc136e95614c76a061b6434497d1e 100644 --- a/packages/ca/heartbeat_manager.go +++ b/packages/ca/heartbeat_manager.go @@ -16,7 +16,7 @@ type HeartbeatManager struct { options *HeartbeatManagerOptions statementChain *StatementChain neighborManagers map[string]*NeighborManager - initialOpinions map[string][]byte + initialOpinions map[string]bool neighborManagersMutex sync.RWMutex } @@ -28,23 +28,29 @@ func NewHeartbeatManager(identity *identity.Identity, options ...HeartbeatManage statementChain: NewStatementChain(), neighborManagers: make(map[string]*NeighborManager), - initialOpinions: make(map[string][]byte), + initialOpinions: make(map[string]bool), } } -func (heartbeatManager *HeartbeatManager) SetInitialOpinion(transactionId []byte) { - heartbeatManager.initialOpinions[string(transactionId)] = transactionId +func (heartbeatManager *HeartbeatManager) InitialDislike(transactionId []byte) { + heartbeatManager.initialOpinions[string(transactionId)] = false +} + +func (heartbeatManager *HeartbeatManager) InitialLike(transactionId []byte) { + heartbeatManager.initialOpinions[string(transactionId)] = true } func (heartbeatManager *HeartbeatManager) GenerateMainStatement() (result *heartbeat.OpinionStatement, err errors.IdentifiableError) { toggledTransactions := make([]*heartbeat.ToggledTransaction, 0) - for _, transactionId := range heartbeatManager.initialOpinions { - newToggledTransaction := heartbeat.NewToggledTransaction() - newToggledTransaction.SetInitialStatement(true) - newToggledTransaction.SetFinalStatement(false) - newToggledTransaction.SetTransactionId(transactionId) - - toggledTransactions = append(toggledTransactions, newToggledTransaction) + for transactionId, liked := range heartbeatManager.initialOpinions { + if !liked { + newToggledTransaction := heartbeat.NewToggledTransaction() + newToggledTransaction.SetInitialStatement(true) + newToggledTransaction.SetFinalStatement(false) + newToggledTransaction.SetTransactionId([]byte(transactionId)) + + toggledTransactions = append(toggledTransactions, newToggledTransaction) + } } mainStatement := heartbeat.NewOpinionStatement() @@ -66,15 +72,24 @@ func (heartbeatManager *HeartbeatManager) GenerateMainStatement() (result *heart signature, signingErr := heartbeatManager.identity.Sign(marshaledStatement) if signingErr != nil { err = ErrMalformedHeartbeat.Derive(signingErr.Error()) + + return } mainStatement.SetSignature(signature) result = mainStatement + heartbeatManager.ResetInitialStatements() + heartbeatManager.statementChain.lastAppliedStatement = mainStatement + return } +func (heartbeatManager *HeartbeatManager) ResetInitialStatements() { + heartbeatManager.initialOpinions = make(map[string]bool) +} + func (heartbeatManager *HeartbeatManager) GenerateHeartbeat() (result *heartbeat.Heartbeat, err errors.IdentifiableError) { mainStatement, mainStatementErr := heartbeatManager.GenerateMainStatement() if mainStatementErr != nil { @@ -87,7 +102,20 @@ func (heartbeatManager *HeartbeatManager) GenerateHeartbeat() (result *heartbeat generatedHeartbeat.SetNodeId(heartbeatManager.identity.StringIdentifier) generatedHeartbeat.SetMainStatement(mainStatement) generatedHeartbeat.SetNeighborStatements(nil) - generatedHeartbeat.SetSignature(nil) + + marshaledHeartbeat, marshalErr := generatedHeartbeat.MarshalBinary() + if marshalErr != nil { + err = marshalErr + + return + } + signature, signingErr := heartbeatManager.identity.Sign(marshaledHeartbeat) + if signingErr != nil { + err = ErrMalformedHeartbeat.Derive(signingErr.Error()) + + return + } + generatedHeartbeat.SetSignature(signature) result = generatedHeartbeat diff --git a/packages/ca/heartbeat_manager_test.go b/packages/ca/heartbeat_manager_test.go index 42b82105018dc1cea245f5994aa36e9ccdf0397f..9a6d2a9a7d3a1f3f879e82dc896af1dacfac5ca1 100644 --- a/packages/ca/heartbeat_manager_test.go +++ b/packages/ca/heartbeat_manager_test.go @@ -8,16 +8,22 @@ import ( "github.com/iotaledger/goshimmer/packages/identity" ) -func TestHeartbeatManager_GenerateHeartbeat(t *testing.T) { - transactionId1 := make([]byte, 50) - rand.Read(transactionId1) +func generateRandomTransactionId() (result []byte) { + result = make([]byte, 50) + rand.Read(result) + + return +} - transactionId2 := make([]byte, 50) - rand.Read(transactionId2) +func TestHeartbeatManager_GenerateHeartbeat(t *testing.T) { + transactionId1 := generateRandomTransactionId() + transactionId2 := generateRandomTransactionId() heartbeatManager := NewHeartbeatManager(identity.GenerateRandomIdentity()) - heartbeatManager.SetInitialOpinion(transactionId1) - heartbeatManager.SetInitialOpinion(transactionId2) + heartbeatManager.InitialDislike(transactionId1) + heartbeatManager.InitialDislike(transactionId2) + + heartbeatManager.InitialLike(generateRandomTransactionId()) result, err := heartbeatManager.GenerateHeartbeat() if err != nil { @@ -27,4 +33,13 @@ func TestHeartbeatManager_GenerateHeartbeat(t *testing.T) { } fmt.Println(result) + + result, err = heartbeatManager.GenerateHeartbeat() + if err != nil { + t.Error(err) + + return + } + + fmt.Println(result) } diff --git a/packages/stringify/slice.go b/packages/stringify/slice.go index 21c5ffb938a0193256c5094ac2ebbf1f1c971e80..346e48143b2b3238424e738e59274b602ce66cdb 100644 --- a/packages/stringify/slice.go +++ b/packages/stringify/slice.go @@ -31,7 +31,7 @@ func sliceReflect(value reflect.Value) (result string) { } } - if !newLineVersion { + if !newLineVersion && len(result) >= 2 { result = result[:len(result)-2] }