From 8ac150efb2f6b3dcc69b8f5cd072b397285ef95b Mon Sep 17 00:00:00 2001 From: Hans Moog <hm@mkjc.net> Date: Sun, 5 Jan 2020 17:07:43 +0100 Subject: [PATCH] Feat: added a transactionparser module To separate the logic of validating transactions from the rest of the code (the tangle + ledger) and further modularize the codebase, I have introduced a separate module that supports the filtering of transactions as early as possible. It supports to be "extended" by additional filters that can the be used to implement the mana based rate control. --- packages/binary/bytesfilter/bytes_filter.go | 58 ++++++++ .../binary/bytesfilter/bytes_filter_test.go | 47 ++++++ packages/binary/tangle/events.go | 4 +- packages/binary/tangle/tangle.go | 16 +- .../recently_seen_bytes_filter.go | 69 +++++++++ .../transaction_signature_filter.go | 66 +++++++++ .../value_transaction_signature_filter.go | 71 +++++++++ .../binary/transactionparser/bytes_filter.go | 8 + packages/binary/transactionparser/events.go | 9 ++ .../transactionparser/transaction_filter.go | 12 ++ .../transactionparser/transactionparser.go | 139 ++++++++++++++++++ .../transactionparser_test.go | 56 +++++++ packages/filter/byte_array_filter.go | 7 +- 13 files changed, 557 insertions(+), 5 deletions(-) create mode 100644 packages/binary/bytesfilter/bytes_filter.go create mode 100644 packages/binary/bytesfilter/bytes_filter_test.go create mode 100644 packages/binary/transactionparser/builtinfilters/recently_seen_bytes_filter.go create mode 100644 packages/binary/transactionparser/builtinfilters/transaction_signature_filter.go create mode 100644 packages/binary/transactionparser/builtinfilters/value_transaction_signature_filter.go create mode 100644 packages/binary/transactionparser/bytes_filter.go create mode 100644 packages/binary/transactionparser/events.go create mode 100644 packages/binary/transactionparser/transaction_filter.go create mode 100644 packages/binary/transactionparser/transactionparser.go create mode 100644 packages/binary/transactionparser/transactionparser_test.go diff --git a/packages/binary/bytesfilter/bytes_filter.go b/packages/binary/bytesfilter/bytes_filter.go new file mode 100644 index 00000000..e434eef8 --- /dev/null +++ b/packages/binary/bytesfilter/bytes_filter.go @@ -0,0 +1,58 @@ +package bytesfilter + +import ( + "sync" + + "github.com/iotaledger/hive.go/typeutils" + + "github.com/iotaledger/goshimmer/packages/binary/types" +) + +type BytesFilter struct { + byteArrays [][]byte + bytesByKey map[string]types.Empty + size int + mutex sync.RWMutex +} + +func New(size int) *BytesFilter { + return &BytesFilter{ + byteArrays: make([][]byte, 0, size), + bytesByKey: make(map[string]types.Empty, size), + size: size, + } +} + +func (bytesFilter *BytesFilter) Add(bytes []byte) bool { + key := typeutils.BytesToString(bytes) + + bytesFilter.mutex.Lock() + + if _, exists := bytesFilter.bytesByKey[key]; !exists { + if len(bytesFilter.byteArrays) == bytesFilter.size { + delete(bytesFilter.bytesByKey, typeutils.BytesToString(bytesFilter.byteArrays[0])) + + bytesFilter.byteArrays = append(bytesFilter.byteArrays[1:], bytes) + } else { + bytesFilter.byteArrays = append(bytesFilter.byteArrays, bytes) + } + + bytesFilter.bytesByKey[key] = types.Void + + bytesFilter.mutex.Unlock() + + return true + } else { + bytesFilter.mutex.Unlock() + + return false + } +} + +func (bytesFilter *BytesFilter) Contains(byteArray []byte) (exists bool) { + bytesFilter.mutex.RLock() + _, exists = bytesFilter.bytesByKey[typeutils.BytesToString(byteArray)] + bytesFilter.mutex.RUnlock() + + return +} diff --git a/packages/binary/bytesfilter/bytes_filter_test.go b/packages/binary/bytesfilter/bytes_filter_test.go new file mode 100644 index 00000000..1b928ffe --- /dev/null +++ b/packages/binary/bytesfilter/bytes_filter_test.go @@ -0,0 +1,47 @@ +package bytesfilter + +import ( + "testing" +) + +func BenchmarkAdd(b *testing.B) { + filter, bytesFilter := setupTest(15000, 1604) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + filter.Add(bytesFilter) + } +} + +func BenchmarkContains(b *testing.B) { + filter, bytesFilter := setupTest(15000, 1604) + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + filter.Contains(bytesFilter) + } +} + +func setupTest(filterSize int, byteArraySize int) (*BytesFilter, []byte) { + filter := New(filterSize) + + for j := 0; j < filterSize; j++ { + byteArray := make([]byte, byteArraySize) + + for i := 0; i < len(byteArray); i++ { + byteArray[(i+j)%byteArraySize] = byte((i + j) % 128) + } + + filter.Add(byteArray) + } + + byteArray := make([]byte, byteArraySize) + + for i := 0; i < len(byteArray); i++ { + byteArray[i] = byte(i % 128) + } + + return filter, byteArray +} diff --git a/packages/binary/tangle/events.go b/packages/binary/tangle/events.go index 0f4a24eb..5afba278 100644 --- a/packages/binary/tangle/events.go +++ b/packages/binary/tangle/events.go @@ -5,5 +5,7 @@ import ( ) type tangleEvents struct { - TransactionSolid *events.Event + TransactionSolid *events.Event + TransactionAttached *events.Event + Error *events.Event } diff --git a/packages/binary/tangle/tangle.go b/packages/binary/tangle/tangle.go index edaf55e1..e584a442 100644 --- a/packages/binary/tangle/tangle.go +++ b/packages/binary/tangle/tangle.go @@ -5,9 +5,11 @@ import ( "github.com/iotaledger/goshimmer/packages/binary/transaction" "github.com/iotaledger/goshimmer/packages/binary/transactionmetadata" "github.com/iotaledger/goshimmer/packages/storageprefix" + "github.com/iotaledger/goshimmer/packages/stringify" "github.com/iotaledger/hive.go/async" "github.com/iotaledger/hive.go/events" "github.com/iotaledger/hive.go/objectstorage" + "github.com/pkg/errors" ) type Tangle struct { @@ -29,6 +31,15 @@ func New(storageId []byte) (result *Tangle) { approversStorage: objectstorage.New(append(storageId, storageprefix.TangleApprovers...), approversFactory), Events: tangleEvents{ + TransactionAttached: events.NewEvent(func(handler interface{}, params ...interface{}) { + cachedTransaction := params[0].(*objectstorage.CachedObject) + cachedTransactionMetadata := params[1].(*objectstorage.CachedObject) + + cachedTransaction.RegisterConsumer() + cachedTransactionMetadata.RegisterConsumer() + + handler.(func(*objectstorage.CachedObject, *objectstorage.CachedObject))(cachedTransaction, cachedTransactionMetadata) + }), TransactionSolid: events.NewEvent(func(handler interface{}, params ...interface{}) { cachedTransaction := params[0].(*objectstorage.CachedObject) cachedTransactionMetadata := params[1].(*objectstorage.CachedObject) @@ -38,6 +49,9 @@ func New(storageId []byte) (result *Tangle) { handler.(func(*objectstorage.CachedObject, *objectstorage.CachedObject))(cachedTransaction, cachedTransactionMetadata) }), + Error: events.NewEvent(func(handler interface{}, params ...interface{}) { + handler.(func(error))(params[0].(error)) + }), }, } @@ -80,7 +94,7 @@ func (tangle *Tangle) GetApprovers(transactionId transaction.Id) *objectstorage. func (tangle *Tangle) verifyTransaction(transaction *transaction.Transaction) { if !transaction.VerifySignature() { - // err = errors.New("transaction has invalid signature") + tangle.Events.Error.Trigger(errors.New("transaction with id " + stringify.Interface(transaction.GetId()) + " has an invalid signature")) return } diff --git a/packages/binary/transactionparser/builtinfilters/recently_seen_bytes_filter.go b/packages/binary/transactionparser/builtinfilters/recently_seen_bytes_filter.go new file mode 100644 index 00000000..1e8f93c0 --- /dev/null +++ b/packages/binary/transactionparser/builtinfilters/recently_seen_bytes_filter.go @@ -0,0 +1,69 @@ +package builtinfilters + +import ( + "sync" + + "github.com/iotaledger/hive.go/async" + + "github.com/iotaledger/goshimmer/packages/binary/bytesfilter" +) + +type RecentlySeenBytesFilter struct { + bytesFilter *bytesfilter.BytesFilter + onAcceptCallback func(bytes []byte) + onRejectCallback func(bytes []byte) + workerPool async.WorkerPool + + onAcceptCallbackMutex sync.RWMutex + onRejectCallbackMutex sync.RWMutex +} + +func NewRecentlySeenBytesFilter() (result *RecentlySeenBytesFilter) { + result = &RecentlySeenBytesFilter{ + bytesFilter: bytesfilter.New(100000), + } + + return +} + +func (filter *RecentlySeenBytesFilter) Filter(bytes []byte) { + filter.workerPool.Submit(func() { + if filter.bytesFilter.Add(bytes) { + filter.getAcceptCallback()(bytes) + } else { + filter.getRejectCallback()(bytes) + } + }) +} + +func (filter *RecentlySeenBytesFilter) OnAccept(callback func(bytes []byte)) { + filter.onAcceptCallbackMutex.Lock() + filter.onAcceptCallback = callback + filter.onAcceptCallbackMutex.Unlock() +} + +func (filter *RecentlySeenBytesFilter) OnReject(callback func(bytes []byte)) { + filter.onRejectCallbackMutex.Lock() + filter.onRejectCallback = callback + filter.onRejectCallbackMutex.Unlock() +} + +func (filter *RecentlySeenBytesFilter) getAcceptCallback() (result func(bytes []byte)) { + filter.onAcceptCallbackMutex.Lock() + result = filter.onAcceptCallback + filter.onAcceptCallbackMutex.Unlock() + + return +} + +func (filter *RecentlySeenBytesFilter) getRejectCallback() (result func(bytes []byte)) { + filter.onRejectCallbackMutex.Lock() + result = filter.onRejectCallback + filter.onRejectCallbackMutex.Unlock() + + return +} + +func (filter *RecentlySeenBytesFilter) Shutdown() { + filter.workerPool.ShutdownGracefully() +} diff --git a/packages/binary/transactionparser/builtinfilters/transaction_signature_filter.go b/packages/binary/transactionparser/builtinfilters/transaction_signature_filter.go new file mode 100644 index 00000000..6862426c --- /dev/null +++ b/packages/binary/transactionparser/builtinfilters/transaction_signature_filter.go @@ -0,0 +1,66 @@ +package builtinfilters + +import ( + "sync" + + "github.com/iotaledger/goshimmer/packages/binary/transaction" + + "github.com/iotaledger/hive.go/async" +) + +type TransactionSignatureFilter struct { + onAcceptCallback func(tx *transaction.Transaction) + onRejectCallback func(tx *transaction.Transaction) + workerPool async.WorkerPool + + onAcceptCallbackMutex sync.RWMutex + onRejectCallbackMutex sync.RWMutex +} + +func NewTransactionSignatureFilter() (result *TransactionSignatureFilter) { + result = &TransactionSignatureFilter{} + + return +} + +func (filter *TransactionSignatureFilter) Filter(tx *transaction.Transaction) { + filter.workerPool.Submit(func() { + if tx.VerifySignature() { + filter.getAcceptCallback()(tx) + } else { + filter.getRejectCallback()(tx) + } + }) +} + +func (filter *TransactionSignatureFilter) OnAccept(callback func(tx *transaction.Transaction)) { + filter.onAcceptCallbackMutex.Lock() + filter.onAcceptCallback = callback + filter.onAcceptCallbackMutex.Unlock() +} + +func (filter *TransactionSignatureFilter) OnReject(callback func(tx *transaction.Transaction)) { + filter.onRejectCallbackMutex.Lock() + filter.onRejectCallback = callback + filter.onRejectCallbackMutex.Unlock() +} + +func (filter *TransactionSignatureFilter) Shutdown() { + filter.workerPool.ShutdownGracefully() +} + +func (filter *TransactionSignatureFilter) getAcceptCallback() (result func(tx *transaction.Transaction)) { + filter.onAcceptCallbackMutex.RLock() + result = filter.onAcceptCallback + filter.onAcceptCallbackMutex.RUnlock() + + return +} + +func (filter *TransactionSignatureFilter) getRejectCallback() (result func(tx *transaction.Transaction)) { + filter.onRejectCallbackMutex.RLock() + result = filter.onRejectCallback + filter.onRejectCallbackMutex.RUnlock() + + return +} diff --git a/packages/binary/transactionparser/builtinfilters/value_transaction_signature_filter.go b/packages/binary/transactionparser/builtinfilters/value_transaction_signature_filter.go new file mode 100644 index 00000000..4a0b0cdb --- /dev/null +++ b/packages/binary/transactionparser/builtinfilters/value_transaction_signature_filter.go @@ -0,0 +1,71 @@ +package builtinfilters + +import ( + "sync" + + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload/valuetransfer" + + "github.com/iotaledger/goshimmer/packages/binary/transaction" + "github.com/iotaledger/hive.go/async" +) + +type ValueTransactionSignatureFilter struct { + onAcceptCallback func(tx *transaction.Transaction) + onRejectCallback func(tx *transaction.Transaction) + workerPool async.WorkerPool + + onAcceptCallbackMutex sync.RWMutex + onRejectCallbackMutex sync.RWMutex +} + +func NewValueTransactionSignatureFilter() (result *ValueTransactionSignatureFilter) { + result = &ValueTransactionSignatureFilter{} + + return +} + +func (filter *ValueTransactionSignatureFilter) Filter(tx *transaction.Transaction) { + filter.workerPool.Submit(func() { + if payload := tx.GetPayload(); payload.GetType() == valuetransfer.Type { + if valueTransfer, ok := payload.(*valuetransfer.ValueTransfer); ok && valueTransfer.VerifySignatures() { + filter.getAcceptCallback()(tx) + } else { + filter.getRejectCallback()(tx) + } + } else { + filter.getAcceptCallback()(tx) + } + }) +} + +func (filter *ValueTransactionSignatureFilter) OnAccept(callback func(tx *transaction.Transaction)) { + filter.onAcceptCallbackMutex.Lock() + filter.onAcceptCallback = callback + filter.onAcceptCallbackMutex.Unlock() +} + +func (filter *ValueTransactionSignatureFilter) OnReject(callback func(tx *transaction.Transaction)) { + filter.onRejectCallbackMutex.Lock() + filter.onRejectCallback = callback + filter.onRejectCallbackMutex.Unlock() +} + +func (filter *ValueTransactionSignatureFilter) Shutdown() { + filter.workerPool.ShutdownGracefully() +} + +func (filter *ValueTransactionSignatureFilter) getAcceptCallback() (result func(tx *transaction.Transaction)) { + filter.onAcceptCallbackMutex.RLock() + result = filter.onAcceptCallback + filter.onAcceptCallbackMutex.RUnlock() + + return +} + +func (filter *ValueTransactionSignatureFilter) getRejectCallback() (result func(tx *transaction.Transaction)) { + filter.onRejectCallbackMutex.RLock() + result = filter.onRejectCallback + filter.onRejectCallbackMutex.RUnlock() + + return +} diff --git a/packages/binary/transactionparser/bytes_filter.go b/packages/binary/transactionparser/bytes_filter.go new file mode 100644 index 00000000..c8e2bab6 --- /dev/null +++ b/packages/binary/transactionparser/bytes_filter.go @@ -0,0 +1,8 @@ +package transactionparser + +type BytesFilter interface { + Filter(bytes []byte) + OnAccept(callback func(bytes []byte)) + OnReject(callback func(bytes []byte)) + Shutdown() +} diff --git a/packages/binary/transactionparser/events.go b/packages/binary/transactionparser/events.go new file mode 100644 index 00000000..9bde1a04 --- /dev/null +++ b/packages/binary/transactionparser/events.go @@ -0,0 +1,9 @@ +package transactionparser + +import "github.com/iotaledger/hive.go/events" + +type transactionParserEvents struct { + BytesRejected *events.Event + TransactionParsed *events.Event + TransactionRejected *events.Event +} diff --git a/packages/binary/transactionparser/transaction_filter.go b/packages/binary/transactionparser/transaction_filter.go new file mode 100644 index 00000000..39f15788 --- /dev/null +++ b/packages/binary/transactionparser/transaction_filter.go @@ -0,0 +1,12 @@ +package transactionparser + +import ( + "github.com/iotaledger/goshimmer/packages/binary/transaction" +) + +type TransactionFilter interface { + Filter(tx *transaction.Transaction) + OnAccept(callback func(tx *transaction.Transaction)) + OnReject(callback func(tx *transaction.Transaction)) + Shutdown() +} diff --git a/packages/binary/transactionparser/transactionparser.go b/packages/binary/transactionparser/transactionparser.go new file mode 100644 index 00000000..3e937f32 --- /dev/null +++ b/packages/binary/transactionparser/transactionparser.go @@ -0,0 +1,139 @@ +package transactionparser + +import ( + "sync" + + "github.com/iotaledger/goshimmer/packages/binary/transactionparser/builtinfilters" + + "github.com/iotaledger/hive.go/events" + "github.com/iotaledger/hive.go/typeutils" + + "github.com/iotaledger/goshimmer/packages/binary/transaction" +) + +type TransactionParser struct { + bytesFilters []BytesFilter + transactionFilters []TransactionFilter + Events transactionParserEvents + + byteFiltersModified typeutils.AtomicBool + transactionFiltersModified typeutils.AtomicBool + bytesFiltersMutex sync.Mutex + transactionFiltersMutex sync.Mutex +} + +func New() (result *TransactionParser) { + result = &TransactionParser{ + bytesFilters: make([]BytesFilter, 0), + transactionFilters: make([]TransactionFilter, 0), + + Events: transactionParserEvents{ + BytesRejected: events.NewEvent(func(handler interface{}, params ...interface{}) { + handler.(func([]byte))(params[0].([]byte)) + }), + TransactionParsed: events.NewEvent(func(handler interface{}, params ...interface{}) { + handler.(func(*transaction.Transaction))(params[0].(*transaction.Transaction)) + }), + TransactionRejected: events.NewEvent(func(handler interface{}, params ...interface{}) { + handler.(func(*transaction.Transaction))(params[0].(*transaction.Transaction)) + }), + }, + } + + // add builtin filters + result.AddBytesFilter(builtinfilters.NewRecentlySeenBytesFilter()) + result.AddTransactionsFilter(builtinfilters.NewTransactionSignatureFilter()) + result.AddTransactionsFilter(builtinfilters.NewValueTransactionSignatureFilter()) + + return +} + +func (transactionParser *TransactionParser) Parse(transactionBytes []byte) { + transactionParser.setupBytesFilterDataFlow() + transactionParser.setupTransactionsFilterDataFlow() + + transactionParser.bytesFilters[0].Filter(transactionBytes) +} + +func (transactionParser *TransactionParser) AddBytesFilter(filter BytesFilter) { + transactionParser.bytesFiltersMutex.Lock() + transactionParser.bytesFilters = append(transactionParser.bytesFilters, filter) + transactionParser.bytesFiltersMutex.Unlock() + + transactionParser.byteFiltersModified.Set() +} + +func (transactionParser *TransactionParser) AddTransactionsFilter(filter TransactionFilter) { + transactionParser.transactionFiltersMutex.Lock() + transactionParser.transactionFilters = append(transactionParser.transactionFilters, filter) + transactionParser.transactionFiltersMutex.Unlock() + + transactionParser.transactionFiltersModified.Set() +} + +func (transactionParser *TransactionParser) Shutdown() { + transactionParser.bytesFiltersMutex.Lock() + for _, bytesFilter := range transactionParser.bytesFilters { + bytesFilter.Shutdown() + } + transactionParser.bytesFiltersMutex.Unlock() + + transactionParser.transactionFiltersMutex.Lock() + for _, transactionFilter := range transactionParser.transactionFilters { + transactionFilter.Shutdown() + } + transactionParser.transactionFiltersMutex.Unlock() +} + +func (transactionParser *TransactionParser) setupBytesFilterDataFlow() { + if !transactionParser.byteFiltersModified.IsSet() { + return + } + + transactionParser.bytesFiltersMutex.Lock() + if transactionParser.byteFiltersModified.IsSet() { + transactionParser.byteFiltersModified.SetTo(false) + + numberOfBytesFilters := len(transactionParser.bytesFilters) + for i := 0; i < numberOfBytesFilters; i++ { + if i == numberOfBytesFilters-1 { + transactionParser.bytesFilters[i].OnAccept(transactionParser.parseTransaction) + } else { + transactionParser.bytesFilters[i].OnAccept(transactionParser.bytesFilters[i+1].Filter) + } + transactionParser.bytesFilters[i].OnReject(func(bytes []byte) { transactionParser.Events.BytesRejected.Trigger(bytes) }) + } + } + transactionParser.bytesFiltersMutex.Unlock() +} + +func (transactionParser *TransactionParser) setupTransactionsFilterDataFlow() { + if !transactionParser.transactionFiltersModified.IsSet() { + return + } + + transactionParser.transactionFiltersMutex.Lock() + if transactionParser.transactionFiltersModified.IsSet() { + transactionParser.transactionFiltersModified.SetTo(false) + + numberOfTransactionFilters := len(transactionParser.transactionFilters) + for i := 0; i < numberOfTransactionFilters; i++ { + if i == numberOfTransactionFilters-1 { + transactionParser.transactionFilters[i].OnAccept(func(tx *transaction.Transaction) { transactionParser.Events.TransactionParsed.Trigger(tx) }) + } else { + transactionParser.transactionFilters[i].OnAccept(transactionParser.transactionFilters[i+1].Filter) + } + transactionParser.transactionFilters[i].OnReject(func(tx *transaction.Transaction) { transactionParser.Events.TransactionRejected.Trigger(tx) }) + } + } + transactionParser.transactionFiltersMutex.Unlock() +} + +func (transactionParser *TransactionParser) parseTransaction(bytes []byte) { + if parsedTransaction, err := transaction.FromBytes(bytes); err != nil { + // trigger parsingError + panic(err) + } else { + transactionParser.transactionFilters[0].Filter(parsedTransaction) + } +} diff --git a/packages/binary/transactionparser/transactionparser_test.go b/packages/binary/transactionparser/transactionparser_test.go new file mode 100644 index 00000000..8043fc59 --- /dev/null +++ b/packages/binary/transactionparser/transactionparser_test.go @@ -0,0 +1,56 @@ +package transactionparser + +import ( + "fmt" + "strconv" + "testing" + + "github.com/iotaledger/hive.go/events" + + "github.com/iotaledger/goshimmer/packages/binary/identity" + "github.com/iotaledger/goshimmer/packages/binary/transaction" + "github.com/iotaledger/goshimmer/packages/binary/transaction/payload/data" +) + +func BenchmarkTransactionParser_ParseBytesSame(b *testing.B) { + txBytes := transaction.New(transaction.EmptyId, transaction.EmptyId, identity.Generate(), data.New([]byte("Test"))).GetBytes() + txParser := New() + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + txParser.Parse(txBytes) + } + + txParser.Shutdown() +} + +func BenchmarkTransactionParser_ParseBytesDifferent(b *testing.B) { + transactionBytes := make([][]byte, b.N) + for i := 0; i < b.N; i++ { + transactionBytes[i] = transaction.New(transaction.EmptyId, transaction.EmptyId, identity.Generate(), data.New([]byte("Test"+strconv.Itoa(i)))).GetBytes() + } + + txParser := New() + + b.ResetTimer() + + for i := 0; i < b.N; i++ { + txParser.Parse(transactionBytes[i]) + } + + txParser.Shutdown() +} + +func TestTransactionParser_ParseTransaction(t *testing.T) { + tx := transaction.New(transaction.EmptyId, transaction.EmptyId, identity.Generate(), data.New([]byte("Test"))) + + txParser := New() + txParser.Parse(tx.GetBytes()) + + txParser.Events.TransactionParsed.Attach(events.NewClosure(func(tx *transaction.Transaction) { + fmt.Println("PARSED!!!") + })) + + txParser.Shutdown() +} diff --git a/packages/filter/byte_array_filter.go b/packages/filter/byte_array_filter.go index d8cb89fe..87260362 100644 --- a/packages/filter/byte_array_filter.go +++ b/packages/filter/byte_array_filter.go @@ -3,12 +3,13 @@ package filter import ( "sync" + "github.com/iotaledger/goshimmer/packages/binary/types" "github.com/iotaledger/goshimmer/packages/typeutils" ) type ByteArrayFilter struct { byteArrays [][]byte - byteArraysByKey map[string]bool + byteArraysByKey map[string]types.Empty size int mutex sync.RWMutex } @@ -16,7 +17,7 @@ type ByteArrayFilter struct { func NewByteArrayFilter(size int) *ByteArrayFilter { return &ByteArrayFilter{ byteArrays: make([][]byte, 0, size), - byteArraysByKey: make(map[string]bool, size), + byteArraysByKey: make(map[string]types.Empty, size), size: size, } } @@ -45,7 +46,7 @@ func (filter *ByteArrayFilter) Add(byteArray []byte) bool { filter.byteArrays = append(filter.byteArrays, byteArray) } - filter.byteArraysByKey[key] = true + filter.byteArraysByKey[key] = types.Void return true } else { -- GitLab