From cc690fac2b49d5b0ab7618a1e506ba7d29ebec0a Mon Sep 17 00:00:00 2001
From: Hans Moog <hm@mkjc.net>
Date: Tue, 17 Sep 2019 20:10:35 +0200
Subject: [PATCH] Feat: added society and elders + refactored some code

---
 .../unbreakable_consensus/consensus_test.go   | 55 +++++++++++++++++++
 packages/unbreakable_consensus/epoch.go       | 24 ++++++++
 .../unbreakable_consensus/epoch_register.go   | 17 +++++-
 .../social_consensus/elder_mask.go            | 19 +++++++
 .../social_consensus/node.go                  | 48 ++++++++++++++++
 .../social_consensus/society.go               | 50 +++++++++++++++++
 packages/unbreakable_consensus/transaction.go | 31 +++++++++++
 7 files changed, 243 insertions(+), 1 deletion(-)
 create mode 100644 packages/unbreakable_consensus/consensus_test.go
 create mode 100644 packages/unbreakable_consensus/social_consensus/elder_mask.go
 create mode 100644 packages/unbreakable_consensus/social_consensus/node.go
 create mode 100644 packages/unbreakable_consensus/social_consensus/society.go
 create mode 100644 packages/unbreakable_consensus/transaction.go

diff --git a/packages/unbreakable_consensus/consensus_test.go b/packages/unbreakable_consensus/consensus_test.go
new file mode 100644
index 00000000..8c0703c3
--- /dev/null
+++ b/packages/unbreakable_consensus/consensus_test.go
@@ -0,0 +1,55 @@
+package unbreakable_consensus
+
+import (
+	"fmt"
+	"math/rand"
+	"strconv"
+	"testing"
+	"time"
+
+	"github.com/iotaledger/goshimmer/packages/unbreakable_consensus/social_consensus"
+)
+
+func generateElders(totalMana int, nodeCount int) []*social_consensus.Node {
+	result := make([]*social_consensus.Node, nodeCount)
+
+	for i := 0; i < nodeCount; i++ {
+		newNode := social_consensus.NewNode("elder" + strconv.Itoa(i))
+		newNode.SetReputation(uint64(totalMana / nodeCount))
+
+		result[i] = newNode
+	}
+
+	return result
+}
+
+func TestConsensus(t *testing.T) {
+	rand.Seed(time.Now().Unix())
+
+	elders := generateElders(100, 10)
+
+	society := social_consensus.NewSociety(elders)
+
+	fmt.Println(society.GetReferencedElderReputation(social_consensus.ElderMask(1).Union(social_consensus.ElderMask(1))))
+
+	fmt.Println(society.GetRandomElder().GetElderMask())
+
+	/*
+
+		selectRandomElder := func() elder.Elder {
+			return nodes[rand.Intn(len(nodes))]
+		}
+
+		epochRegister := NewEpochRegister()
+
+		genesis := NewTransaction("GENESIS")
+
+		//selectRandomNode().Attach(genesis)
+
+		fmt.Println(selectRandomElder())
+
+		fmt.Println(genesis)
+
+		fmt.Println(epochRegister.GetEpoch(0))
+	*/
+}
diff --git a/packages/unbreakable_consensus/epoch.go b/packages/unbreakable_consensus/epoch.go
index 48c5440c..e60d5042 100644
--- a/packages/unbreakable_consensus/epoch.go
+++ b/packages/unbreakable_consensus/epoch.go
@@ -1,4 +1,28 @@
 package unbreakable_consensus
 
+import (
+	"github.com/iotaledger/goshimmer/packages/stringify"
+	"github.com/iotaledger/goshimmer/packages/unbreakable_consensus/social_consensus"
+)
+
 type Epoch struct {
+	onlineMana map[string]*social_consensus.Node
+	number     int
+}
+
+func NewEpoch(number int) *Epoch {
+	return &Epoch{
+		onlineMana: make(map[string]*social_consensus.Node),
+		number:     number,
+	}
+}
+
+func (epoch *Epoch) GetNumber() int {
+	return epoch.number
+}
+
+func (epoch *Epoch) String() string {
+	return stringify.Struct("Epoch",
+		stringify.StructField("number", epoch.number),
+	)
 }
diff --git a/packages/unbreakable_consensus/epoch_register.go b/packages/unbreakable_consensus/epoch_register.go
index 5a62dd9a..9a52dbab 100644
--- a/packages/unbreakable_consensus/epoch_register.go
+++ b/packages/unbreakable_consensus/epoch_register.go
@@ -1,8 +1,23 @@
 package unbreakable_consensus
 
 type EpochRegister struct {
+	epochs map[int]*Epoch
 }
 
 func NewEpochRegister() *EpochRegister {
-	return &EpochRegister{}
+	return &EpochRegister{
+		epochs: make(map[int]*Epoch),
+	}
+}
+
+func (epochRegister *EpochRegister) GetEpoch(number int) *Epoch {
+	if epoch, exists := epochRegister.epochs[number]; exists {
+		return epoch
+	} else {
+		epoch := NewEpoch(number)
+
+		epochRegister.epochs[number] = epoch
+
+		return epoch
+	}
 }
diff --git a/packages/unbreakable_consensus/social_consensus/elder_mask.go b/packages/unbreakable_consensus/social_consensus/elder_mask.go
new file mode 100644
index 00000000..8a251de0
--- /dev/null
+++ b/packages/unbreakable_consensus/social_consensus/elder_mask.go
@@ -0,0 +1,19 @@
+package social_consensus
+
+import (
+	"fmt"
+)
+
+type ElderMask uint64
+
+func (elderMask ElderMask) Union(otherElderMask ElderMask) ElderMask {
+	return elderMask | otherElderMask
+}
+
+func (elderMask ElderMask) Contains(otherMask ElderMask) bool {
+	return elderMask&otherMask != 0
+}
+
+func (elderMask ElderMask) String() string {
+	return "ElderMask(" + fmt.Sprintf("%064b", elderMask) + ")"
+}
diff --git a/packages/unbreakable_consensus/social_consensus/node.go b/packages/unbreakable_consensus/social_consensus/node.go
new file mode 100644
index 00000000..baff5910
--- /dev/null
+++ b/packages/unbreakable_consensus/social_consensus/node.go
@@ -0,0 +1,48 @@
+package social_consensus
+
+import (
+	"github.com/iotaledger/goshimmer/packages/stringify"
+)
+
+type Node struct {
+	id         string
+	reputation uint64
+	elderMask  ElderMask
+}
+
+func NewNode(id string) *Node {
+	return &Node{
+		id: id,
+	}
+}
+
+func (node *Node) GetElderMask() ElderMask {
+	return node.elderMask
+}
+
+func (node *Node) SetElderMask(mask ElderMask) {
+	node.elderMask = mask
+}
+
+func (node *Node) IsElder() bool {
+	return node.elderMask != 0
+}
+
+func (node *Node) GetId() string {
+	return node.id
+}
+
+func (node *Node) GetReputation() uint64 {
+	return node.reputation
+}
+
+func (node *Node) SetReputation(reputation uint64) {
+	node.reputation = reputation
+}
+
+func (node *Node) String() string {
+	return stringify.Struct("Node",
+		stringify.StructField("id", node.id),
+		stringify.StructField("reputation", node.reputation),
+	)
+}
diff --git a/packages/unbreakable_consensus/social_consensus/society.go b/packages/unbreakable_consensus/social_consensus/society.go
new file mode 100644
index 00000000..0fa24d24
--- /dev/null
+++ b/packages/unbreakable_consensus/social_consensus/society.go
@@ -0,0 +1,50 @@
+package social_consensus
+
+import (
+	"math/rand"
+)
+
+type Society struct {
+	elders               []*Node
+	totalElderReputation uint64
+}
+
+func NewSociety(elders []*Node) (result *Society) {
+	result = &Society{}
+	result.SetElders(elders)
+
+	return
+}
+
+func (society *Society) GetElders() []*Node {
+	return society.elders
+}
+
+func (society *Society) SetElders(newElders []*Node) {
+	society.elders = newElders
+
+	society.totalElderReputation = 0
+	for i, elder := range newElders {
+		elder.SetElderMask(1 << uint(i))
+
+		society.totalElderReputation += elder.GetReputation()
+	}
+}
+
+func (society *Society) GetReferencedElderReputation(elderMask ElderMask) (result uint64) {
+	for i, elder := range society.GetElders() {
+		if elderMask&(1<<uint(i)) > 0 {
+			result += elder.GetReputation()
+		}
+	}
+
+	return
+}
+
+func (society *Society) GetTotalElderReputation() uint64 {
+	return society.totalElderReputation
+}
+
+func (society *Society) GetRandomElder() *Node {
+	return society.elders[rand.Intn(len(society.elders))]
+}
diff --git a/packages/unbreakable_consensus/transaction.go b/packages/unbreakable_consensus/transaction.go
new file mode 100644
index 00000000..2367a21a
--- /dev/null
+++ b/packages/unbreakable_consensus/transaction.go
@@ -0,0 +1,31 @@
+package unbreakable_consensus
+
+import (
+	"github.com/iotaledger/goshimmer/packages/stringify"
+)
+
+type Transaction struct {
+	id           string
+	claimedEpoch int
+}
+
+func NewTransaction(id string) *Transaction {
+	return &Transaction{
+		id: id,
+	}
+}
+
+func (transaction *Transaction) GetId() string {
+	return transaction.id
+}
+
+func (transaction *Transaction) GetClaimedEpoch() int {
+	return transaction.claimedEpoch
+}
+
+func (transaction *Transaction) String() string {
+	return stringify.Struct("Transaction",
+		stringify.StructField("id", transaction.id),
+		stringify.StructField("claimedEpoch", transaction.claimedEpoch),
+	)
+}
-- 
GitLab