Skip to content
Snippets Groups Projects
Commit 8dcb5906 authored by Hans Moog's avatar Hans Moog
Browse files

Feat: started implementing serialization for mana objects

parent b26a2aa1
No related branches found
No related tags found
No related merge requests found
......@@ -161,12 +161,17 @@ func (balance *Balance) applyTransfer(transfer *Transfer) {
}
// calculate mana gains
gainedMana, roundingError := balance.calculator.GenerateMana(transfer.movedCoins, transfer.spentTime-transfer.receivedTime)
var gainedMana uint64
for _, input := range transfer.inputs {
generatedMana, _ := balance.calculator.GenerateMana(input.coinAmount, transfer.spentTime-input.receivedTime)
gainedMana += generatedMana
}
// store results
balance.transferHistory.AddLast(&BalanceHistoryEntry{
transfer: transfer,
balance: currentBalance + gainedMana - transfer.burnedMana,
accumulatedRoundingError: roundingError,
accumulatedRoundingError: 0, // TODO: remove
})
}
......@@ -13,22 +13,28 @@ func TestBalance_CleanupTransferHistory(t *testing.T) {
// fill transfer history
balance1 := NewBalance(calculator)
balance1.BookTransfer(&Transfer{
movedCoins: 1000,
burnedMana: 10,
receivedTime: 1000,
spentTime: 1700,
inputs: []*Input{{
coinAmount: 1000,
receivedTime: 1000,
}},
spentTime: 1700,
burnedMana: 10,
})
balance1.BookTransfer(&Transfer{
movedCoins: 1000,
burnedMana: 0,
receivedTime: 700,
spentTime: 1000,
inputs: []*Input{{
coinAmount: 1000,
receivedTime: 700,
}},
spentTime: 1000,
burnedMana: 0,
})
balance1.BookTransfer(&Transfer{
movedCoins: 1000,
burnedMana: 0,
receivedTime: 0,
spentTime: 700,
inputs: []*Input{{
coinAmount: 1000,
receivedTime: 0,
}},
spentTime: 700,
burnedMana: 0,
})
// cleanup transfer history
......@@ -56,31 +62,39 @@ func TestBalance_AddTransfer(t *testing.T) {
// spend coins multiple times
balance1 := NewBalance(calculator)
balance1.BookTransfer(&Transfer{
movedCoins: 1000,
burnedMana: 10,
receivedTime: 1000,
spentTime: 1700,
inputs: []*Input{{
coinAmount: 1000,
receivedTime: 1000,
}},
spentTime: 1700,
burnedMana: 10,
})
balance1.BookTransfer(&Transfer{
movedCoins: 1000,
burnedMana: 0,
receivedTime: 700,
spentTime: 1000,
inputs: []*Input{{
coinAmount: 1000,
receivedTime: 700,
}},
spentTime: 1000,
burnedMana: 0,
})
balance1.BookTransfer(&Transfer{
movedCoins: 1000,
burnedMana: 0,
receivedTime: 0,
spentTime: 700,
inputs: []*Input{{
coinAmount: 1000,
receivedTime: 0,
}},
spentTime: 700,
burnedMana: 0,
})
// hold coins for the full time
balance2 := NewBalance(calculator)
balance2.BookTransfer(&Transfer{
movedCoins: 1000,
burnedMana: 10,
receivedTime: 0,
spentTime: 1700,
inputs: []*Input{{
coinAmount: 1000,
receivedTime: 0,
}},
spentTime: 1700,
burnedMana: 10,
})
// check result
......
package mana
import (
"github.com/iotaledger/goshimmer/packages/errors"
)
var (
ErrUnmarshalFailed = errors.New("unmarshal failed")
)
package mana
import (
"encoding/binary"
"fmt"
"github.com/iotaledger/goshimmer/packages/marshal"
"github.com/iotaledger/goshimmer/packages/errors"
)
type Input struct {
coinAmount uint64
receivedTime uint64
}
func (input *Input) MarshalBinary() (data []byte, err errors.IdentifiableError) {
data = inputSchema.Marshal(input)
return
}
func (input *Input) UnmarshalBinary(data []byte) (err errors.IdentifiableError) {
if len(data) < INPUT_TOTAL_MARSHALED_SIZE {
err = ErrUnmarshalFailed.Derive("byte sequence of marshaled input is not long enough")
}
input.coinAmount = binary.BigEndian.Uint64(data[INPUT_COIN_AMOUNT_BYTE_OFFSET_START:INPUT_COIN_AMOUNT_BYTE_OFFSET_END])
input.receivedTime = binary.BigEndian.Uint64(data[INPUT_RECEIVED_TIME_BYTE_OFFSET_START:INPUT_RECEIVED_TIME_BYTE_OFFSET_END])
return
}
func (input *Input) GetCoinAmount() uint64 {
return input_getCoinAmount(input)
}
func input_getCoinAmount(input interface{}) uint64 {
return input.(*Input).coinAmount
}
func input_setCoinAmount(input interface{}, coinAmount uint64) {
input.(*Input).coinAmount = coinAmount
}
func input_getReceivedTime(input interface{}) uint64 {
return input.(*Input).receivedTime
}
func input_setReceivedTime(input interface{}, receivedTime uint64) {
input.(*Input).coinAmount = receivedTime
}
var inputSchema = marshal.Schema(
marshal.Uint64(input_getCoinAmount, input_setCoinAmount),
marshal.Uint64(input_getReceivedTime, input_setReceivedTime),
)
func init() {
fmt.Println((&Input{
coinAmount: 10,
receivedTime: 20,
}).MarshalBinary())
}
const (
INPUT_COIN_AMOUNT_BYTE_OFFSET_START = 0
INPUT_COIN_AMOUNT_BYTE_OFFSET_LENGTH = 8
INPUT_COIN_AMOUNT_BYTE_OFFSET_END = INPUT_COIN_AMOUNT_BYTE_OFFSET_START + INPUT_COIN_AMOUNT_BYTE_OFFSET_LENGTH
INPUT_RECEIVED_TIME_BYTE_OFFSET_START = INPUT_COIN_AMOUNT_BYTE_OFFSET_END
INPUT_RECEIVED_TIME_BYTE_OFFSET_LENGTH = 8
INPUT_RECEIVED_TIME_BYTE_OFFSET_END = INPUT_RECEIVED_TIME_BYTE_OFFSET_START + INPUT_RECEIVED_TIME_BYTE_OFFSET_LENGTH
INPUT_TOTAL_MARSHALED_SIZE = INPUT_RECEIVED_TIME_BYTE_OFFSET_END
)
package mana
import (
"testing"
)
func BenchmarkDirectReceiver(b *testing.B) {
input := &Input{
coinAmount: 10,
receivedTime: 0,
}
for i := 0; i < b.N; i++ {
input.GetCoinAmount()
}
}
func BenchmarkManualReceiver(b *testing.B) {
input := &Input{
coinAmount: 10,
receivedTime: 0,
}
for i := 0; i < b.N; i++ {
input_getCoinAmount(input)
}
}
package mana
import (
"github.com/iotaledger/goshimmer/packages/errors"
)
type Transfer struct {
movedCoins uint64
burnedMana uint64
receivedTime uint64
spentTime uint64
inputs []*Input
spentTime uint64
burnedMana uint64
}
func (transfer *Transfer) MarshalBinary() (data []byte, err errors.IdentifiableError) {
data = make([]byte, INPUT_TOTAL_MARSHALED_SIZE)
return
}
func (transfer *Transfer) UnmarshalBinary(data []byte) (err errors.IdentifiableError) {
return
}
const (
TRANSFER_SPENT_TIME_BYTE_OFFSET_START = 0
TRANSFER_SPENT_TIME_BYTE_OFFSET_LENGTH = 8
TRANSFER_SPENT_TIME_BYTE_OFFSET_END = TRANSFER_SPENT_TIME_BYTE_OFFSET_START + TRANSFER_SPENT_TIME_BYTE_OFFSET_LENGTH
TRANSFER_BURNED_MANA_BYTE_OFFSET_START = INPUT_COIN_AMOUNT_BYTE_OFFSET_END
TRANSFER_BURNED_MANA_BYTE_OFFSET_LENGTH = 8
TRANSFER_BURNED_MANA_BYTE_OFFSET_END = INPUT_RECEIVED_TIME_BYTE_OFFSET_START + INPUT_RECEIVED_TIME_BYTE_OFFSET_LENGTH
)
package marshal
type Field interface {
Get(obj interface{}) interface{}
Marshal(obj interface{}, data []byte) []byte
}
type encoder struct {
fields []Field
}
func Schema(fields ...Field) *encoder {
return &encoder{
fields: fields,
}
}
func (encoder *encoder) Marshal(obj interface{}) []byte {
result := make([]byte, 0)
for _, field := range encoder.fields {
result = append(result, field.Marshal(field.Get(obj), result)...)
}
return result
}
package marshal
import (
"encoding/binary"
)
func Uint64(getter uint64Getter, setter uint64Setter) *uint64Field {
return &uint64Field{
getter: getter,
setter: setter,
}
}
type uint64Getter func(receiver interface{}) uint64
type uint64Setter func(receiver interface{}, val uint64)
type uint64Field struct {
getter uint64Getter
setter uint64Setter
}
func (uint64Field *uint64Field) Marshal(obj interface{}, data []byte) (result []byte) {
result = make([]byte, 8)
binary.BigEndian.PutUint64(result, obj.(uint64))
return
}
func (uint64Field *uint64Field) Get(obj interface{}) interface{} {
return uint64Field.getter(obj)
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment