From 1735f291d2662fd8a2488dab6075b76a05de3810 Mon Sep 17 00:00:00 2001
From: Hans Moog <hm@mkjc.net>
Date: Fri, 9 Aug 2019 00:36:03 +0200
Subject: [PATCH] Feat: added mana burn foundation for spam prevention

---
 packages/mana/balance.go      | 29 ++++++++++++++++++++++++-----
 packages/mana/balance_test.go | 34 ++++++++++++++++++++++++++++------
 packages/mana/errors.go       |  1 +
 packages/mana/transfer.go     |  4 +++-
 4 files changed, 56 insertions(+), 12 deletions(-)
 create mode 100644 packages/mana/errors.go

diff --git a/packages/mana/balance.go b/packages/mana/balance.go
index 95e6e857..8c36a628 100644
--- a/packages/mana/balance.go
+++ b/packages/mana/balance.go
@@ -2,6 +2,7 @@ package mana
 
 import (
 	"github.com/iotaledger/goshimmer/packages/datastructure"
+	"github.com/iotaledger/goshimmer/packages/errors"
 )
 
 type Balance struct {
@@ -17,12 +18,30 @@ func NewBalance(calculator *Calculator) *Balance {
 }
 
 // Returns the current mana balance.
-func (balance *Balance) GetValue() uint64 {
-	if lastBalanceHistoryEntry, err := balance.transferHistory.GetLast(); datastructure.ErrNoSuchElement.Equals(err) {
-		return 0
+func (balance *Balance) GetValue(now ...uint64) (result uint64, err errors.IdentifiableError) {
+	if lastBalanceHistoryEntry, historyErr := balance.transferHistory.GetLast(); historyErr != nil {
+		if !datastructure.ErrNoSuchElement.Equals(historyErr) {
+			err = historyErr
+		}
 	} else {
-		return lastBalanceHistoryEntry.(*BalanceHistoryEntry).balance
+		switch len(now) {
+		case 0:
+			result = lastBalanceHistoryEntry.(*BalanceHistoryEntry).balance
+
+		case 1:
+			lastErosionTime := lastBalanceHistoryEntry.(*BalanceHistoryEntry).transfer.spentTime
+			if lastErosionTime > now[0] {
+				panic("watt")
+			} else {
+				result, _ = balance.calculator.ErodeMana(lastBalanceHistoryEntry.(*BalanceHistoryEntry).balance, now[0]-lastErosionTime)
+			}
+
+		default:
+			err = errors.New("Test")
+		}
 	}
+
+	return
 }
 
 // Returns the timestamp of the last mana erosion.
@@ -109,7 +128,7 @@ func (balance *Balance) applyTransfer(transfer *Transfer) {
 	// store results
 	balance.transferHistory.AddLast(&BalanceHistoryEntry{
 		transfer:                 transfer,
-		balance:                  currentBalance + gainedMana,
+		balance:                  currentBalance + gainedMana - transfer.burnedMana,
 		accumulatedRoundingError: roundingError,
 	})
 }
diff --git a/packages/mana/balance_test.go b/packages/mana/balance_test.go
index 5aa0b3f1..e38b1515 100644
--- a/packages/mana/balance_test.go
+++ b/packages/mana/balance_test.go
@@ -11,15 +11,37 @@ func TestBalance_AddTransfer(t *testing.T) {
 
 	// spend coins multiple times
 	balance1 := NewBalance(calculator)
-	balance1.AddTransfer(NewTransfer(1000, 1000, 1700))
-	balance1.AddTransfer(NewTransfer(1000, 700, 1000))
-	balance1.AddTransfer(NewTransfer(1000, 0, 700))
+	balance1.AddTransfer(&Transfer{
+		movedCoins:   1000,
+		burnedMana:   10,
+		receivedTime: 1000,
+		spentTime:    1700,
+	})
+	balance1.AddTransfer(&Transfer{
+		movedCoins:   1000,
+		burnedMana:   0,
+		receivedTime: 700,
+		spentTime:    1000,
+	})
+	balance1.AddTransfer(&Transfer{
+		movedCoins:   1000,
+		burnedMana:   0,
+		receivedTime: 0,
+		spentTime:    700,
+	})
 
 	// hold coins for the full time
 	balance2 := NewBalance(calculator)
-	balance2.AddTransfer(NewTransfer(1000, 0, 1700))
+	balance2.AddTransfer(&Transfer{
+		movedCoins:   1000,
+		burnedMana:   10,
+		receivedTime: 0,
+		spentTime:    1700,
+	})
 
 	// check result
-	assert.Equal(t, balance1.GetValue(), uint64(301))
-	assert.Equal(t, balance2.GetValue(), uint64(301))
+	val1, _ := balance1.GetValue()
+	assert.Equal(t, val1, uint64(291))
+	val2, _ := balance2.GetValue()
+	assert.Equal(t, val2, uint64(291))
 }
diff --git a/packages/mana/errors.go b/packages/mana/errors.go
new file mode 100644
index 00000000..e462aad4
--- /dev/null
+++ b/packages/mana/errors.go
@@ -0,0 +1 @@
+package mana
diff --git a/packages/mana/transfer.go b/packages/mana/transfer.go
index eae37e0d..cb8da44d 100644
--- a/packages/mana/transfer.go
+++ b/packages/mana/transfer.go
@@ -2,13 +2,15 @@ package mana
 
 type Transfer struct {
 	movedCoins   uint64
+	burnedMana   uint64
 	receivedTime uint64
 	spentTime    uint64
 }
 
-func NewTransfer(movedCoins uint64, receivedTime uint64, spentTime uint64) *Transfer {
+func NewTransfer(movedCoins uint64, burnedMana uint64, receivedTime uint64, spentTime uint64) *Transfer {
 	return &Transfer{
 		movedCoins:   movedCoins,
+		burnedMana:   burnedMana,
 		receivedTime: receivedTime,
 		spentTime:    spentTime,
 	}
-- 
GitLab