diff --git a/packages/unbreakable_consensus/consensus_test.go b/packages/unbreakable_consensus/consensus_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8c0703c31def5278046ad0dbd2b7b118f6f2d004 --- /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 48c5440c419da495bcb5a626b589773ec0a590cc..e60d5042b64ebd533470633cb9f6a0f402332e84 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 5a62dd9a7bcea6beaee60e13357530dcc2292e28..9a52dbabb30697addffd71ea41701120b4adbb66 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 0000000000000000000000000000000000000000..8a251de0fa661555f8e70f22bd3fe910679b6158 --- /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 0000000000000000000000000000000000000000..baff5910b6c73762ba9b6e1234f204865c27fb98 --- /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 0000000000000000000000000000000000000000..0fa24d240429287d63eb4f35da15fd4f54cd40bd --- /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 0000000000000000000000000000000000000000..2367a21adc4fdf098097bbd56ad6b0adb6620194 --- /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), + ) +}