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

Feat: started adding value tangle

parent 0a204629
No related branches found
No related tags found
No related merge requests found
Showing
with 533 additions and 76 deletions
package main package main
import ( import (
"fmt"
"net/http"
_ "net/http/pprof" _ "net/http/pprof"
"github.com/mr-tron/base58"
"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction"
"github.com/iotaledger/goshimmer/plugins/analysis" "github.com/iotaledger/goshimmer/plugins/analysis"
"github.com/iotaledger/goshimmer/plugins/autopeering" "github.com/iotaledger/goshimmer/plugins/autopeering"
"github.com/iotaledger/goshimmer/plugins/banner" "github.com/iotaledger/goshimmer/plugins/banner"
...@@ -31,14 +26,7 @@ import ( ...@@ -31,14 +26,7 @@ import (
) )
func main() { func main() {
go http.ListenAndServe("localhost:6061", nil) // pprof Server for Debbuging Mutexes //go http.ListenAndServe("localhost:6061", nil) // pprof Server for Debbuging Mutexes
testTxId := transaction.NewId([]byte("Test"))
fmt.Println(len(base58.Encode(transaction.EmptyId[:])))
fmt.Println(base58.Encode(transaction.EmptyId[:]))
fmt.Println(len(base58.Encode(testTxId[:])))
fmt.Println(base58.Encode(testTxId[:]))
node.Run( node.Run(
node.Plugins( node.Plugins(
...@@ -47,12 +35,12 @@ func main() { ...@@ -47,12 +35,12 @@ func main() {
logger.PLUGIN, logger.PLUGIN,
cli.PLUGIN, cli.PLUGIN,
remotelog.PLUGIN, remotelog.PLUGIN,
gracefulshutdown.PLUGIN,
autopeering.PLUGIN, autopeering.PLUGIN,
tangle.PLUGIN, tangle.PLUGIN,
gossip.PLUGIN, gossip.PLUGIN,
portcheck.PLUGIN, portcheck.PLUGIN,
gracefulshutdown.PLUGIN,
analysis.PLUGIN, analysis.PLUGIN,
metrics.PLUGIN, metrics.PLUGIN,
......
package marshalutil
func (util *MarshalUtil) WriteBytes(bytes []byte) {
writeEndOffset := util.expandWriteCapacity(len(bytes))
copy(util.bytes[util.writeOffset:writeEndOffset], bytes)
util.WriteSeek(writeEndOffset)
}
func (util *MarshalUtil) ReadBytes(length int) ([]byte, error) {
readEndOffset, err := util.checkReadCapacity(length)
if err != nil {
return nil, err
}
defer util.ReadSeek(readEndOffset)
return util.bytes[util.readOffset:readEndOffset], nil
}
func (util *MarshalUtil) ReadRemainingBytes() []byte {
defer util.ReadSeek(util.size)
return util.bytes[util.readOffset:]
}
package marshalutil
import (
"fmt"
)
type MarshalUtil struct {
bytes []byte
readOffset int
writeOffset int
size int
}
func New(args ...interface{}) *MarshalUtil {
switch argsCount := len(args); argsCount {
case 0:
return &MarshalUtil{
bytes: make([]byte, 1024),
size: 0,
}
case 1:
switch param := args[0].(type) {
case int:
return &MarshalUtil{
bytes: make([]byte, param),
size: param,
}
case []byte:
return &MarshalUtil{
bytes: param,
size: len(param),
}
default:
panic(fmt.Errorf("illegal argument type %T in marshalutil.New(...)", param))
}
default:
panic(fmt.Errorf("illegal argument count %d in marshalutil.New(...)", argsCount))
}
}
func (util *MarshalUtil) WriteSeek(offset int) {
util.writeOffset = offset
}
func (util *MarshalUtil) ReadSeek(offset int) {
util.readOffset = offset
}
func (util *MarshalUtil) Bytes() []byte {
return util.bytes[:util.size]
}
func (util *MarshalUtil) checkReadCapacity(length int) (readEndOffset int, err error) {
readEndOffset = util.readOffset + length
if readEndOffset > util.size {
err = fmt.Errorf("tried to read %d bytes from %d bytes input", readEndOffset, util.size)
}
return
}
func (util *MarshalUtil) expandWriteCapacity(length int) (writeEndOffset int) {
writeEndOffset = util.writeOffset + length
if writeEndOffset > util.size {
extendedBytes := make([]byte, writeEndOffset-util.size)
util.bytes = append(util.bytes, extendedBytes...)
util.size = writeEndOffset
}
return
}
package marshalutil
import (
"encoding/binary"
)
const INT64_SIZE = 8
func (util *MarshalUtil) WriteInt64(value int64) {
writeEndOffset := util.expandWriteCapacity(INT64_SIZE)
binary.LittleEndian.PutUint64(util.bytes[util.writeOffset:writeEndOffset], uint64(value))
util.WriteSeek(writeEndOffset)
}
func (util *MarshalUtil) ReadInt64() (int64, error) {
readEndOffset, err := util.checkReadCapacity(INT64_SIZE)
if err != nil {
return 0, err
}
defer util.ReadSeek(readEndOffset)
return int64(binary.LittleEndian.Uint64(util.bytes[util.readOffset:readEndOffset])), nil
}
package marshalutil
import "encoding/binary"
const UINT64_SIZE = 8
func (util *MarshalUtil) WriteUint64(value uint64) {
writeEndOffset := util.expandWriteCapacity(UINT64_SIZE)
binary.LittleEndian.PutUint64(util.bytes[util.writeOffset:writeEndOffset], value)
util.WriteSeek(writeEndOffset)
}
func (util *MarshalUtil) ReadUint64() (uint64, error) {
readEndOffset, err := util.checkReadCapacity(UINT64_SIZE)
if err != nil {
return 0, err
}
defer util.ReadSeek(readEndOffset)
return binary.LittleEndian.Uint64(util.bytes[util.readOffset:readEndOffset]), nil
}
package marshalutil
import (
"fmt"
"testing"
)
func Test(t *testing.T) {
util := New(1)
util.WriteBytes(make([]byte, UINT64_SIZE))
util.WriteInt64(-12)
util.WriteUint64(38)
fmt.Println(util.ReadBytes(UINT64_SIZE))
fmt.Println(util.ReadInt64())
fmt.Println(util.ReadUint64())
fmt.Println(util.ReadUint64())
fmt.Println(util)
}
package spammer package spammer
import ( import (
"sync" "fmt"
"sync/atomic"
"time" "time"
"github.com/iotaledger/hive.go/types" "github.com/iotaledger/hive.go/types"
...@@ -17,8 +18,7 @@ type Spammer struct { ...@@ -17,8 +18,7 @@ type Spammer struct {
transactionParser *transactionparser.TransactionParser transactionParser *transactionparser.TransactionParser
tipSelector *tipselector.TipSelector tipSelector *tipselector.TipSelector
running bool processId int64
startStopMutex sync.Mutex
shutdownSignal chan types.Empty shutdownSignal chan types.Empty
} }
...@@ -31,49 +31,27 @@ func New(transactionParser *transactionparser.TransactionParser, tipSelector *ti ...@@ -31,49 +31,27 @@ func New(transactionParser *transactionparser.TransactionParser, tipSelector *ti
} }
func (spammer *Spammer) Start(tps int) { func (spammer *Spammer) Start(tps int) {
spammer.startStopMutex.Lock() go spammer.run(tps, atomic.AddInt64(&spammer.processId, 1))
defer spammer.startStopMutex.Unlock()
if !spammer.running {
spammer.running = true
go spammer.run(tps)
}
} }
func (spammer *Spammer) Burst(transactions int) { func (spammer *Spammer) Burst(transactions int) {
spammer.startStopMutex.Lock() go spammer.sendBurst(transactions, atomic.AddInt64(&spammer.processId, 1))
defer spammer.startStopMutex.Unlock()
if !spammer.running {
spammer.running = true
go spammer.sendBurst(transactions)
}
} }
func (spammer *Spammer) Shutdown() { func (spammer *Spammer) Shutdown() {
spammer.startStopMutex.Lock() atomic.AddInt64(&spammer.processId, 1)
defer spammer.startStopMutex.Unlock()
if spammer.running {
spammer.running = false
spammer.shutdownSignal <- types.Void
}
} }
func (spammer *Spammer) run(tps int) { func (spammer *Spammer) run(tps int, processId int64) {
fmt.Println(processId)
currentSentCounter := 0 currentSentCounter := 0
start := time.Now() start := time.Now()
for { for {
if atomic.LoadInt64(&spammer.processId) != processId {
select {
case <-spammer.shutdownSignal:
return return
}
default:
trunkTransactionId, branchTransactionId := spammer.tipSelector.GetTips() trunkTransactionId, branchTransactionId := spammer.tipSelector.GetTips()
spammer.transactionParser.Parse( spammer.transactionParser.Parse(
transaction.New(trunkTransactionId, branchTransactionId, identity.Generate(), data.New([]byte("SPAM"))).GetBytes(), transaction.New(trunkTransactionId, branchTransactionId, identity.Generate(), data.New([]byte("SPAM"))).GetBytes(),
...@@ -94,33 +72,28 @@ func (spammer *Spammer) run(tps int) { ...@@ -94,33 +72,28 @@ func (spammer *Spammer) run(tps int) {
} }
} }
} }
}
func (spammer *Spammer) sendBurst(transactions int) { func (spammer *Spammer) sendBurst(transactions int, processId int64) {
spammingIdentity := identity.Generate() spammingIdentity := identity.Generate()
previousTransactionId := transaction.EmptyId previousTransactionId := transaction.EmptyId
burstBuffer := make([][]byte, transactions) burstBuffer := make([][]byte, transactions)
for i := 0; i < transactions; i++ { for i := 0; i < transactions; i++ {
select { if atomic.LoadInt64(&spammer.processId) != processId {
case <-spammer.shutdownSignal:
return return
}
default:
spamTransaction := transaction.New(previousTransactionId, previousTransactionId, spammingIdentity, data.New([]byte("SPAM"))) spamTransaction := transaction.New(previousTransactionId, previousTransactionId, spammingIdentity, data.New([]byte("SPAM")))
previousTransactionId = spamTransaction.GetId() previousTransactionId = spamTransaction.GetId()
burstBuffer[i] = spamTransaction.GetBytes() burstBuffer[i] = spamTransaction.GetBytes()
} }
}
for i := 0; i < transactions; i++ { for i := 0; i < transactions; i++ {
select { if atomic.LoadInt64(&spammer.processId) != processId {
case <-spammer.shutdownSignal:
return return
}
default:
spammer.transactionParser.Parse(burstBuffer[i], nil) spammer.transactionParser.Parse(burstBuffer[i], nil)
} }
} }
}
package valuetangle
import (
"sync"
"github.com/iotaledger/hive.go/objectstorage"
"golang.org/x/crypto/blake2b"
"github.com/iotaledger/goshimmer/packages/binary/marshalutil"
"github.com/iotaledger/goshimmer/packages/binary/tangle/model/transaction/payload"
)
type Payload struct {
objectstorage.StorableObjectFlags
id *PayloadId
trunkPayloadId PayloadId
branchPayloadId PayloadId
transfer *Transfer
bytes []byte
idMutex sync.RWMutex
bytesMutex sync.RWMutex
}
func NewPayload(trunkPayloadId, branchPayloadId PayloadId, valueTransfer *Transfer) *Payload {
return &Payload{
trunkPayloadId: trunkPayloadId,
branchPayloadId: branchPayloadId,
transfer: valueTransfer,
}
}
func (payload *Payload) GetId() PayloadId {
// acquire lock for reading id
payload.idMutex.RLock()
// return if id has been calculated already
if payload.id != nil {
defer payload.idMutex.RUnlock()
return *payload.id
}
// switch to write lock
payload.idMutex.RUnlock()
payload.idMutex.Lock()
defer payload.idMutex.Unlock()
// return if id has been calculated in the mean time
if payload.id != nil {
return *payload.id
}
// otherwise calculate the id
transferId := payload.GetTransfer().GetId()
marshalUtil := marshalutil.New(PayloadIdLength + PayloadIdLength + TransferIdLength)
marshalUtil.WriteBytes(payload.trunkPayloadId[:])
marshalUtil.WriteBytes(payload.branchPayloadId[:])
marshalUtil.WriteBytes(transferId[:])
var id PayloadId = blake2b.Sum256(marshalUtil.Bytes())
payload.id = &id
return id
}
func (payload *Payload) GetTrunkPayloadId() PayloadId {
return payload.trunkPayloadId
}
func (payload *Payload) GetBranchPayloadId() PayloadId {
return payload.branchPayloadId
}
func (payload *Payload) GetTransfer() *Transfer {
return payload.transfer
}
// region Payload implementation ///////////////////////////////////////////////////////////////////////////////////////
var Type = payload.Type(1)
func (payload *Payload) GetType() payload.Type {
return Type
}
func (payload *Payload) MarshalBinary() (bytes []byte, err error) {
// acquire lock for reading bytes
payload.bytesMutex.RLock()
// return if bytes have been determined already
if bytes = payload.bytes; bytes != nil {
defer payload.bytesMutex.RUnlock()
return
}
// switch to write lock
payload.bytesMutex.RUnlock()
payload.bytesMutex.Lock()
defer payload.bytesMutex.Unlock()
// return if bytes have been determined in the mean time
if bytes = payload.bytes; bytes != nil {
return
}
// retrieve bytes of transfer
transferBytes, err := payload.GetTransfer().MarshalBinary()
if err != nil {
return
}
// marshal fields
marshalUtil := marshalutil.New(PayloadIdLength + PayloadIdLength + TransferIdLength)
marshalUtil.WriteBytes(payload.trunkPayloadId[:])
marshalUtil.WriteBytes(payload.branchPayloadId[:])
marshalUtil.WriteBytes(transferBytes)
bytes = marshalUtil.Bytes()
// store result
payload.bytes = bytes
return
}
func (payload *Payload) UnmarshalBinary(data []byte) (err error) {
marshalUtil := marshalutil.New(data)
trunkTransactionIdBytes, err := marshalUtil.ReadBytes(PayloadIdLength)
if err != nil {
return
}
branchTransactionIdBytes, err := marshalUtil.ReadBytes(PayloadIdLength)
if err != nil {
return
}
valueTransfer := &Transfer{}
if err = valueTransfer.UnmarshalBinary(marshalUtil.ReadRemainingBytes()); err != nil {
return
}
payload.trunkPayloadId = NewPayloadId(trunkTransactionIdBytes)
payload.branchPayloadId = NewPayloadId(branchTransactionIdBytes)
payload.transfer = valueTransfer
payload.bytes = data
return
}
func init() {
payload.RegisterType(Type, func(data []byte) (payload payload.Payload, err error) {
payload = &Payload{}
err = payload.UnmarshalBinary(data)
return
})
}
// define contract (ensure that the struct fulfills the corresponding interface)
var _ payload.Payload = &Payload{}
// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
// region StorableObject implementation ////////////////////////////////////////////////////////////////////////////////
// MarshalBinary() (bytes []byte, err error) already implemented by Payload
// UnmarshalBinary(data []byte) (err error) already implemented by Payload
func (payload *Payload) GetStorageKey() []byte {
id := payload.GetId()
return id[:]
}
func (payload *Payload) Update(other objectstorage.StorableObject) {
panic("a Payload should never be updated")
}
// define contract (ensure that the struct fulfills the corresponding interface)
var _ objectstorage.StorableObject = &Payload{}
// endregion ///////////////////////////////////////////////////////////////////////////////////////////////////////////
package valuetangle
import (
"github.com/mr-tron/base58"
)
type PayloadId [PayloadIdLength]byte
func NewPayloadId(idBytes []byte) (result PayloadId) {
copy(result[:], idBytes)
return
}
func (id PayloadId) String() string {
return base58.Encode(id[:])
}
var EmptyPayloadId PayloadId
const PayloadIdLength = 32
package test
import (
"fmt"
"testing"
"github.com/iotaledger/goshimmer/packages/binary/valuetangle"
)
func TestPayload(t *testing.T) {
transfer := valuetangle.NewTransfer()
fmt.Println(transfer.GetId())
payload := valuetangle.NewPayload(valuetangle.EmptyPayloadId, valuetangle.EmptyPayloadId, transfer)
fmt.Println(payload.GetId())
}
package valuetangle
import (
"sync"
"github.com/iotaledger/hive.go/objectstorage"
"golang.org/x/crypto/blake2b"
)
type Transfer struct {
objectstorage.StorableObjectFlags
id *TransferId
bytes []byte
idMutex sync.RWMutex
bytesMutex sync.RWMutex
}
func NewTransfer() *Transfer {
return &Transfer{}
}
func FromStorage(key []byte) *Transfer {
id := NewTransferId(key)
return &Transfer{
id: &id,
}
}
func (transfer *Transfer) GetId() TransferId {
// acquire lock for reading id
transfer.idMutex.RLock()
// return if id has been calculated already
if transfer.id != nil {
defer transfer.idMutex.RUnlock()
return *transfer.id
}
// switch to write lock
transfer.idMutex.RUnlock()
transfer.idMutex.Lock()
defer transfer.idMutex.Unlock()
// return if id has been calculated in the mean time
if transfer.id != nil {
return *transfer.id
}
// otherwise calculate the PayloadId
transfer.id = transfer.calculateId()
return *transfer.id
}
func (transfer *Transfer) calculateId() *TransferId {
bytes, _ := transfer.MarshalBinary()
id := blake2b.Sum256(bytes)
result := NewTransferId(id[:])
return &result
}
func (transfer *Transfer) Update(other objectstorage.StorableObject) {
panic("implement me")
}
func (transfer *Transfer) GetStorageKey() []byte {
panic("implement me")
}
func (transfer *Transfer) MarshalBinary() ([]byte, error) {
return nil, nil
}
func (transfer *Transfer) UnmarshalBinary(data []byte) error {
panic("implement me")
}
// define contracts (ensure that the struct fulfills the corresponding interfaces
var _ objectstorage.StorableObject = &Transfer{}
package valuetangle
import (
"github.com/mr-tron/base58"
)
type TransferId [TransferIdLength]byte
func NewTransferId(idBytes []byte) (result TransferId) {
copy(result[:], idBytes)
return
}
func (id TransferId) String() string {
return base58.Encode(id[:])
}
const TransferIdLength = 32
...@@ -42,7 +42,6 @@ func configure(*node.Plugin) { ...@@ -42,7 +42,6 @@ func configure(*node.Plugin) {
// setup TransactionParser // setup TransactionParser
TransactionParser.Events.TransactionParsed.Attach(events.NewClosure(func(transaction *transaction.Transaction, peer *peer.Peer) { TransactionParser.Events.TransactionParsed.Attach(events.NewClosure(func(transaction *transaction.Transaction, peer *peer.Peer) {
peer.PublicKey()
// TODO: ADD PEER // TODO: ADD PEER
Instance.AttachTransaction(transaction) Instance.AttachTransaction(transaction)
......
...@@ -17,7 +17,6 @@ var PLUGIN = node.NewPlugin("Spammer", node.Disabled, configure, run) ...@@ -17,7 +17,6 @@ var PLUGIN = node.NewPlugin("Spammer", node.Disabled, configure, run)
func configure(plugin *node.Plugin) { func configure(plugin *node.Plugin) {
transactionSpammer = spammer.New(tangle.TransactionParser, tangle.TipSelector) transactionSpammer = spammer.New(tangle.TransactionParser, tangle.TipSelector)
webapi.Server.GET("spammer", handleRequest) webapi.Server.GET("spammer", handleRequest)
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment