From 33cb0e94ea9652278ccc9a10d854da89224d5a32 Mon Sep 17 00:00:00 2001 From: Hans Moog <hm@mkjc.net> Date: Mon, 6 Jan 2020 01:54:31 +0100 Subject: [PATCH] Feat: added solidification login --- go.mod | 2 +- go.sum | 4 + .../tangle/approvers/cached_approvers.go | 21 ++ .../cached_missingtransaction.go | 21 ++ .../missingtransaction/missingtransaction.go | 60 ++++++ packages/binary/tangle/solidifier.go | 128 ------------ packages/binary/tangle/tangle.go | 182 ++++++++++++++---- packages/binary/tangle/tangle_test.go | 5 +- .../binary/transaction/cached_transaction.go | 21 ++ .../cached_transactionmetadata.go | 21 ++ .../value_transaction_signature_filter.go | 18 +- .../transactionparser/transactionparser.go | 2 +- 12 files changed, 305 insertions(+), 180 deletions(-) create mode 100644 packages/binary/tangle/approvers/cached_approvers.go create mode 100644 packages/binary/tangle/missingtransaction/cached_missingtransaction.go create mode 100644 packages/binary/tangle/missingtransaction/missingtransaction.go delete mode 100644 packages/binary/tangle/solidifier.go create mode 100644 packages/binary/transaction/cached_transaction.go create mode 100644 packages/binary/transactionmetadata/cached_transactionmetadata.go diff --git a/go.mod b/go.mod index 6f415327..9c32ac67 100644 --- a/go.mod +++ b/go.mod @@ -15,7 +15,7 @@ require ( github.com/golang/protobuf v1.3.2 // indirect github.com/google/open-location-code/go v0.0.0-20190903173953-119bc96a3a51 github.com/gorilla/websocket v1.4.1 - github.com/iotaledger/hive.go v0.0.0-20200101211541-ea7950f4c2f2 + github.com/iotaledger/hive.go v0.0.0-20200106003337-d78637b86bf2 github.com/iotaledger/iota.go v1.0.0-beta.9 github.com/kr/text v0.1.0 github.com/labstack/echo v3.3.10+incompatible diff --git a/go.sum b/go.sum index 87df5300..88cdee3f 100644 --- a/go.sum +++ b/go.sum @@ -101,6 +101,10 @@ github.com/iotaledger/hive.go v0.0.0-20200101185538-ae70241fee7f h1:vxfLVJOsHHEb github.com/iotaledger/hive.go v0.0.0-20200101185538-ae70241fee7f/go.mod h1:vrZrvGaWT1o5kz3Jj2B/PcUtqsFzZnLWrO3zEsGSuwk= github.com/iotaledger/hive.go v0.0.0-20200101211541-ea7950f4c2f2 h1:S84ohGcHKq6NFOY77HUXLvqYfOveJhzzphSeimTUtTw= github.com/iotaledger/hive.go v0.0.0-20200101211541-ea7950f4c2f2/go.mod h1:vrZrvGaWT1o5kz3Jj2B/PcUtqsFzZnLWrO3zEsGSuwk= +github.com/iotaledger/hive.go v0.0.0-20200105155739-b36b4405762f h1:HqEFrjhbUB4uAOl9a9tTj78hYZ2bQLP9qLUlYwanPPY= +github.com/iotaledger/hive.go v0.0.0-20200105155739-b36b4405762f/go.mod h1:vrZrvGaWT1o5kz3Jj2B/PcUtqsFzZnLWrO3zEsGSuwk= +github.com/iotaledger/hive.go v0.0.0-20200106003337-d78637b86bf2 h1:HBQKEP6PnaEhG7j3HNjZTkpALvek8QYPeoJXyDzBDpo= +github.com/iotaledger/hive.go v0.0.0-20200106003337-d78637b86bf2/go.mod h1:vrZrvGaWT1o5kz3Jj2B/PcUtqsFzZnLWrO3zEsGSuwk= github.com/iotaledger/iota.go v1.0.0-beta.9 h1:c654s9pkdhMBkABUvWg+6k91MEBbdtmZXP1xDfQpajg= github.com/iotaledger/iota.go v1.0.0-beta.9/go.mod h1:F6WBmYd98mVjAmmPVYhnxg8NNIWCjjH8VWT9qvv3Rc8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= diff --git a/packages/binary/tangle/approvers/cached_approvers.go b/packages/binary/tangle/approvers/cached_approvers.go new file mode 100644 index 00000000..99ed8ad0 --- /dev/null +++ b/packages/binary/tangle/approvers/cached_approvers.go @@ -0,0 +1,21 @@ +package approvers + +import ( + "github.com/iotaledger/hive.go/objectstorage" +) + +type CachedApprovers struct { + *objectstorage.CachedObject +} + +func (cachedObject *CachedApprovers) Unwrap() *Approvers { + if untypedObject := cachedObject.Get(); untypedObject == nil { + return nil + } else { + if typedObject := untypedObject.(*Approvers); typedObject == nil || typedObject.IsDeleted() { + return nil + } else { + return typedObject + } + } +} diff --git a/packages/binary/tangle/missingtransaction/cached_missingtransaction.go b/packages/binary/tangle/missingtransaction/cached_missingtransaction.go new file mode 100644 index 00000000..c64e3df3 --- /dev/null +++ b/packages/binary/tangle/missingtransaction/cached_missingtransaction.go @@ -0,0 +1,21 @@ +package missingtransaction + +import ( + "github.com/iotaledger/hive.go/objectstorage" +) + +type CachedMissingTransaction struct { + *objectstorage.CachedObject +} + +func (cachedObject *CachedMissingTransaction) Unwrap() *MissingTransaction { + if untypedObject := cachedObject.Get(); untypedObject == nil { + return nil + } else { + if typedObject := untypedObject.(*MissingTransaction); typedObject == nil || typedObject.IsDeleted() { + return nil + } else { + return typedObject + } + } +} diff --git a/packages/binary/tangle/missingtransaction/missingtransaction.go b/packages/binary/tangle/missingtransaction/missingtransaction.go new file mode 100644 index 00000000..783017eb --- /dev/null +++ b/packages/binary/tangle/missingtransaction/missingtransaction.go @@ -0,0 +1,60 @@ +package missingtransaction + +import ( + "time" + + "github.com/iotaledger/goshimmer/packages/binary/transaction" + + "github.com/iotaledger/hive.go/objectstorage" +) + +type MissingTransaction struct { + objectstorage.StorableObjectFlags + storageKey []byte + + id transaction.Id + missingSince time.Time +} + +func New(id transaction.Id) *MissingTransaction { + return &MissingTransaction{ + storageKey: id[:], + id: id, + missingSince: time.Now(), + } +} + +func FromStorage(key []byte) objectstorage.StorableObject { + result := &MissingTransaction{ + storageKey: make([]byte, len(key)), + } + copy(result.storageKey, key) + + return result +} + +func (missingTransaction *MissingTransaction) GetId() transaction.Id { + return missingTransaction.id +} + +func (missingTransaction *MissingTransaction) GetMissingSince() time.Time { + return missingTransaction.missingSince +} + +func (missingTransaction *MissingTransaction) GetStorageKey() []byte { + return missingTransaction.storageKey +} + +func (missingTransaction *MissingTransaction) Update(other objectstorage.StorableObject) { + panic("missing transactions should never be overwritten and only stored once to optimize IO") +} + +func (missingTransaction *MissingTransaction) MarshalBinary() (result []byte, err error) { + return missingTransaction.missingSince.MarshalBinary() +} + +func (missingTransaction *MissingTransaction) UnmarshalBinary(data []byte) (err error) { + copy(missingTransaction.id[:], missingTransaction.storageKey) + + return missingTransaction.missingSince.UnmarshalBinary(data) +} diff --git a/packages/binary/tangle/solidifier.go b/packages/binary/tangle/solidifier.go deleted file mode 100644 index 14e0f0bc..00000000 --- a/packages/binary/tangle/solidifier.go +++ /dev/null @@ -1,128 +0,0 @@ -package tangle - -import ( - "container/list" - - "github.com/iotaledger/goshimmer/packages/binary/tangle/approvers" - "github.com/iotaledger/goshimmer/packages/binary/transaction" - "github.com/iotaledger/goshimmer/packages/binary/transactionmetadata" - "github.com/iotaledger/hive.go/async" - "github.com/iotaledger/hive.go/objectstorage" -) - -type solidifier struct { - tangle *Tangle - - workerPool async.WorkerPool -} - -func newSolidifier(tangle *Tangle) (result *solidifier) { - result = &solidifier{ - tangle: tangle, - } - - result.workerPool.Tune(1024) - - return -} - -func (solidifier *solidifier) Shutdown() { - solidifier.workerPool.ShutdownGracefully() -} - -func (solidifier *solidifier) Solidify(cachedTransaction *objectstorage.CachedObject, cachedTransactionMetadata *objectstorage.CachedObject) { - solidifier.workerPool.Submit(func() { solidifier.solidify(cachedTransaction, cachedTransactionMetadata) }) -} - -func (solidifier *solidifier) solidify(cachedTransaction *objectstorage.CachedObject, cachedTransactionMetadata *objectstorage.CachedObject) { - // initialize the stack - solidificationStack := list.New() - solidificationStack.PushBack([2]*objectstorage.CachedObject{cachedTransaction, cachedTransactionMetadata}) - - // process transactions that are supposed to be checked for solidity recursively - for solidificationStack.Len() > 0 { - // pop first element from stack - currentSolidificationEntry := solidificationStack.Front() - currentCachedTransaction := currentSolidificationEntry.Value.([2]*objectstorage.CachedObject)[0] - currentCachedTransactionMetadata := currentSolidificationEntry.Value.([2]*objectstorage.CachedObject)[1] - solidificationStack.Remove(currentSolidificationEntry) - - // retrieve transaction from cached result - var currentTransaction *transaction.Transaction - if _tmp := currentCachedTransaction.Get(); _tmp != nil { - currentTransaction = _tmp.(*transaction.Transaction) - } else { - currentCachedTransaction.Release() - currentCachedTransactionMetadata.Release() - - continue - } - - // retrieve metadata from cached result - var currentTransactionMetadata *transactionmetadata.TransactionMetadata - if _tmp := currentCachedTransactionMetadata.Get(); _tmp != nil { - currentTransactionMetadata = _tmp.(*transactionmetadata.TransactionMetadata) - } else { - currentCachedTransaction.Release() - currentCachedTransactionMetadata.Release() - - continue - } - - // if current transaction is solid and was not marked as solid before: mark as solid and propagate - if solidifier.isTransactionSolid(currentTransaction, currentTransactionMetadata) && currentTransactionMetadata.SetSolid(true) { - solidifier.tangle.Events.TransactionSolid.Trigger(currentCachedTransaction, currentCachedTransactionMetadata) - - solidifier.tangle.GetApprovers(currentTransaction.GetId()).Consume(func(object objectstorage.StorableObject) { - for approverTransactionId := range object.(*approvers.Approvers).Get() { - solidificationStack.PushBack([2]*objectstorage.CachedObject{ - solidifier.tangle.GetTransaction(approverTransactionId), - solidifier.tangle.GetTransactionMetadata(approverTransactionId), - }) - } - }) - } - - // release cached results - currentCachedTransaction.Release() - currentCachedTransactionMetadata.Release() - } -} - -func (solidifier *solidifier) isTransactionSolid(transaction *transaction.Transaction, transactionMetadata *transactionmetadata.TransactionMetadata) bool { - if transaction == nil || transaction.IsDeleted() { - return false - } - - if transactionMetadata == nil || transactionMetadata.IsDeleted() { - return false - } - - if transactionMetadata.IsSolid() { - return true - } - - // 1. check tangle solidity - if solidifier.isTransactionSolidInTangle(transaction.GetTrunkTransactionId()) && solidifier.isTransactionSolidInTangle(transaction.GetBranchTransactionId()) { - // 2. check payload solidity - return true - } - - return false -} - -func (solidifier *solidifier) isTransactionSolidInTangle(transactionId transaction.Id) bool { - if transactionId != transaction.EmptyId { - cachedTransactionMetadata := solidifier.tangle.GetTransactionMetadata(transactionId) - - if transactionMetadata := cachedTransactionMetadata.Get().(*transactionmetadata.TransactionMetadata); transactionMetadata == nil || transactionMetadata.IsDeleted() || !transactionMetadata.IsSolid() { - cachedTransactionMetadata.Release() - - return false - } - - cachedTransactionMetadata.Release() - } - - return true -} diff --git a/packages/binary/tangle/tangle.go b/packages/binary/tangle/tangle.go index e584a442..a8dd7e60 100644 --- a/packages/binary/tangle/tangle.go +++ b/packages/binary/tangle/tangle.go @@ -1,27 +1,29 @@ package tangle import ( + "container/list" + "fmt" + "github.com/iotaledger/goshimmer/packages/binary/tangle/approvers" + "github.com/iotaledger/goshimmer/packages/binary/tangle/missingtransaction" "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 { - solidifier *solidifier transactionStorage *objectstorage.ObjectStorage transactionMetadataStorage *objectstorage.ObjectStorage approversStorage *objectstorage.ObjectStorage + missingTransactionsStorage *objectstorage.ObjectStorage Events tangleEvents - verifyTransactionsWorkerPool async.WorkerPool - storeTransactionsWorkerPool async.WorkerPool + storeTransactionsWorkerPool async.WorkerPool + solidifierWorkerPool async.WorkerPool } func New(storageId []byte) (result *Tangle) { @@ -29,25 +31,26 @@ func New(storageId []byte) (result *Tangle) { transactionStorage: objectstorage.New(append(storageId, storageprefix.TangleTransaction...), transactionFactory), transactionMetadataStorage: objectstorage.New(append(storageId, storageprefix.TangleTransactionMetadata...), transactionFactory), approversStorage: objectstorage.New(append(storageId, storageprefix.TangleApprovers...), approversFactory), + missingTransactionsStorage: objectstorage.New(append(storageId, storageprefix.TangleTransaction...), missingtransaction.FromStorage), Events: tangleEvents{ TransactionAttached: events.NewEvent(func(handler interface{}, params ...interface{}) { - cachedTransaction := params[0].(*objectstorage.CachedObject) - cachedTransactionMetadata := params[1].(*objectstorage.CachedObject) + cachedTransaction := params[0].(*transaction.CachedTransaction) + cachedTransactionMetadata := params[1].(*transactionmetadata.CachedTransactionMetadata) cachedTransaction.RegisterConsumer() cachedTransactionMetadata.RegisterConsumer() - handler.(func(*objectstorage.CachedObject, *objectstorage.CachedObject))(cachedTransaction, cachedTransactionMetadata) + handler.(func(*transaction.CachedTransaction, *transactionmetadata.CachedTransactionMetadata))(cachedTransaction, cachedTransactionMetadata) }), TransactionSolid: events.NewEvent(func(handler interface{}, params ...interface{}) { - cachedTransaction := params[0].(*objectstorage.CachedObject) - cachedTransactionMetadata := params[1].(*objectstorage.CachedObject) + cachedTransaction := params[0].(*transaction.CachedTransaction) + cachedTransactionMetadata := params[1].(*transactionmetadata.CachedTransactionMetadata) cachedTransaction.RegisterConsumer() cachedTransactionMetadata.RegisterConsumer() - handler.(func(*objectstorage.CachedObject, *objectstorage.CachedObject))(cachedTransaction, cachedTransactionMetadata) + handler.(func(*transaction.CachedTransaction, *transactionmetadata.CachedTransactionMetadata))(cachedTransaction, cachedTransactionMetadata) }), Error: events.NewEvent(func(handler interface{}, params ...interface{}) { handler.(func(error))(params[0].(error)) @@ -55,7 +58,7 @@ func New(storageId []byte) (result *Tangle) { }, } - result.solidifier = newSolidifier(result) + result.solidifierWorkerPool.Tune(1024) return } @@ -77,60 +80,159 @@ func (tangle *Tangle) Prune() error { } func (tangle *Tangle) AttachTransaction(transaction *transaction.Transaction) { - tangle.verifyTransactionsWorkerPool.Submit(func() { tangle.verifyTransaction(transaction) }) + tangle.storeTransactionsWorkerPool.Submit(func() { tangle.storeTransaction(transaction) }) } -func (tangle *Tangle) GetTransaction(transactionId transaction.Id) *objectstorage.CachedObject { - return tangle.transactionStorage.Load(transactionId[:]) +func (tangle *Tangle) GetTransaction(transactionId transaction.Id) *transaction.CachedTransaction { + return &transaction.CachedTransaction{CachedObject: tangle.transactionStorage.Load(transactionId[:])} } -func (tangle *Tangle) GetTransactionMetadata(transactionId transaction.Id) *objectstorage.CachedObject { - return tangle.transactionMetadataStorage.Load(transactionId[:]) +func (tangle *Tangle) GetTransactionMetadata(transactionId transaction.Id) *transactionmetadata.CachedTransactionMetadata { + return &transactionmetadata.CachedTransactionMetadata{CachedObject: tangle.transactionMetadataStorage.Load(transactionId[:])} } -func (tangle *Tangle) GetApprovers(transactionId transaction.Id) *objectstorage.CachedObject { - return tangle.approversStorage.Load(transactionId[:]) +func (tangle *Tangle) GetApprovers(transactionId transaction.Id) *approvers.CachedApprovers { + return &approvers.CachedApprovers{CachedObject: tangle.approversStorage.Load(transactionId[:])} } -func (tangle *Tangle) verifyTransaction(transaction *transaction.Transaction) { - if !transaction.VerifySignature() { - tangle.Events.Error.Trigger(errors.New("transaction with id " + stringify.Interface(transaction.GetId()) + " has an invalid signature")) +// Marks the tangle as stopped, so it will not accept any new transactions, and then waits for all backgroundTasks to +// finish. +func (tangle *Tangle) Shutdown() *Tangle { + tangle.storeTransactionsWorkerPool.ShutdownGracefully() + tangle.solidifierWorkerPool.ShutdownGracefully() + + return tangle +} +func (tangle *Tangle) storeTransaction(tx *transaction.Transaction) { + cachedTransaction, transactionIsNew := tangle.transactionStorage.StoreIfAbsent(tx.GetStorageKey(), tx) + if !transactionIsNew { return } - tangle.storeTransactionsWorkerPool.Submit(func() { tangle.storeTransaction(transaction) }) + cachedTransactionMetadata := tangle.createTransactionMetadata(tx) + tangle.addTransactionToApprovers(tx, tx.GetTrunkTransactionId()) + tangle.addTransactionToApprovers(tx, tx.GetBranchTransactionId()) + + transactionId := tx.GetId() + if tangle.missingTransactionsStorage.DeleteIfPresent(transactionId[:]) { + fmt.Println("MISSING TRANSACTION RECEIVED") + } + + tangle.solidifierWorkerPool.Submit(func() { + tangle.solidify(&transaction.CachedTransaction{CachedObject: cachedTransaction}, cachedTransactionMetadata) + }) } -func (tangle *Tangle) storeTransaction(transaction *transaction.Transaction) { - cachedTransaction, transactionIsNew := tangle.transactionStorage.StoreIfAbsent(transaction.GetStorageKey(), transaction) - if !transactionIsNew { - return +// Payloads can have different solidification rules and it might happen, that an external process needs to "manually +// trigger" the solidification checks of a transaction (to update it's solidification status). +func (tangle *Tangle) Solidify(transactionId transaction.Id) { + tangle.solidifierWorkerPool.Submit(func() { + tangle.solidify(tangle.GetTransaction(transactionId), tangle.GetTransactionMetadata(transactionId)) + }) +} + +func (tangle *Tangle) solidify(cachedTransaction *transaction.CachedTransaction, cachedTransactionMetadata *transactionmetadata.CachedTransactionMetadata) { + popElementsFromStack := func(stack *list.List) (*transaction.CachedTransaction, *transactionmetadata.CachedTransactionMetadata) { + currentSolidificationEntry := stack.Front() + currentCachedTransaction := currentSolidificationEntry.Value.([2]interface{})[0] + currentCachedTransactionMetadata := currentSolidificationEntry.Value.([2]interface{})[1] + stack.Remove(currentSolidificationEntry) + + return currentCachedTransaction.(*transaction.CachedTransaction), currentCachedTransactionMetadata.(*transactionmetadata.CachedTransactionMetadata) + } + + // initialize the stack + solidificationStack := list.New() + solidificationStack.PushBack([2]interface{}{cachedTransaction, cachedTransactionMetadata}) + + // process transactions that are supposed to be checked for solidity recursively + for solidificationStack.Len() > 0 { + currentCachedTransaction, currentCachedTransactionMetadata := popElementsFromStack(solidificationStack) + + currentTransaction := currentCachedTransaction.Unwrap() + currentTransactionMetadata := currentCachedTransactionMetadata.Unwrap() + if currentTransaction == nil || currentTransactionMetadata == nil { + currentCachedTransaction.Release() + currentCachedTransactionMetadata.Release() + + continue + } + + // if current transaction is solid and was not marked as solid before: mark as solid and propagate + if tangle.isTransactionSolid(currentTransaction, currentTransactionMetadata) && currentTransactionMetadata.SetSolid(true) { + tangle.Events.TransactionSolid.Trigger(currentCachedTransaction, currentCachedTransactionMetadata) + + tangle.GetApprovers(currentTransaction.GetId()).Consume(func(object objectstorage.StorableObject) { + for approverTransactionId := range object.(*approvers.Approvers).Get() { + solidificationStack.PushBack([2]interface{}{ + tangle.GetTransaction(approverTransactionId), + tangle.GetTransactionMetadata(approverTransactionId), + }) + } + }) + } + + // release cached results + currentCachedTransaction.Release() + currentCachedTransactionMetadata.Release() + } +} + +func (tangle *Tangle) isTransactionSolid(transaction *transaction.Transaction, transactionMetadata *transactionmetadata.TransactionMetadata) bool { + if transaction == nil || transaction.IsDeleted() { + return false } - cachedTransactionMetadata := tangle.createTransactionMetadata(transaction) + if transactionMetadata == nil || transactionMetadata.IsDeleted() { + return false + } - tangle.addTransactionToApprovers(transaction, transaction.GetTrunkTransactionId()) - tangle.addTransactionToApprovers(transaction, transaction.GetBranchTransactionId()) + if transactionMetadata.IsSolid() { + return true + } + + // 1. check tangle solidity + isTrunkSolid := tangle.isTransactionMarkedAsSolid(transaction.GetTrunkTransactionId()) + isBranchSolid := tangle.isTransactionMarkedAsSolid(transaction.GetBranchTransactionId()) + if isTrunkSolid && isBranchSolid { + // 2. check payload solidity + return true + } - tangle.solidifier.Solidify(cachedTransaction, cachedTransactionMetadata) + return false } -// Marks the tangle as stopped, so it will not accept any new transactions, and then waits for all backgroundTasks to -// finish. -func (tangle *Tangle) Shutdown() *Tangle { - tangle.verifyTransactionsWorkerPool.ShutdownGracefully() - tangle.storeTransactionsWorkerPool.ShutdownGracefully() +func (tangle *Tangle) isTransactionMarkedAsSolid(transactionId transaction.Id) bool { + if transactionId == transaction.EmptyId { + return true + } - tangle.solidifier.Shutdown() + cachedTransactionMetadata := tangle.GetTransactionMetadata(transactionId) + if transactionMetadata := cachedTransactionMetadata.Unwrap(); transactionMetadata == nil { + cachedTransactionMetadata.Release() - return tangle + if _, missingTransactionStored := tangle.missingTransactionsStorage.StoreIfAbsent(transactionId[:], &missingtransaction.MissingTransaction{}); missingTransactionStored { + // Trigger + fmt.Println("MISSING TX EVENT") + } + // transaction is missing -> add to solidifier + + return false + } else if !transactionMetadata.IsSolid() { + cachedTransactionMetadata.Release() + + return false + } + cachedTransactionMetadata.Release() + + return true } -func (tangle *Tangle) createTransactionMetadata(transaction *transaction.Transaction) *objectstorage.CachedObject { +func (tangle *Tangle) createTransactionMetadata(transaction *transaction.Transaction) *transactionmetadata.CachedTransactionMetadata { transactionMetadata := transactionmetadata.New(transaction.GetId()) - return tangle.transactionMetadataStorage.Store(transactionMetadata) + return &transactionmetadata.CachedTransactionMetadata{CachedObject: tangle.transactionMetadataStorage.Store(transactionMetadata)} } func (tangle *Tangle) addTransactionToApprovers(transaction *transaction.Transaction, trunkTransactionId transaction.Id) { diff --git a/packages/binary/tangle/tangle_test.go b/packages/binary/tangle/tangle_test.go index a0b7d51c..71dc0198 100644 --- a/packages/binary/tangle/tangle_test.go +++ b/packages/binary/tangle/tangle_test.go @@ -3,6 +3,7 @@ package tangle import ( "fmt" "testing" + "time" "github.com/iotaledger/goshimmer/packages/binary/identity" "github.com/iotaledger/goshimmer/packages/binary/transaction" @@ -48,11 +49,13 @@ func TestTangle_AttachTransaction(t *testing.T) { } newTransaction1 := transaction.New(transaction.EmptyId, transaction.EmptyId, identity.Generate(), data.New([]byte("some data"))) - newTransaction2 := transaction.New(newTransaction1.GetId(), transaction.EmptyId, identity.Generate(), data.New([]byte("some other data"))) + newTransaction2 := transaction.New(newTransaction1.GetId(), newTransaction1.GetId(), identity.Generate(), data.New([]byte("some other data"))) fmt.Println("ATTACH", newTransaction2.GetId()) tangle.AttachTransaction(newTransaction2) + time.Sleep(1 * time.Second) + fmt.Println("ATTACH", newTransaction1.GetId()) tangle.AttachTransaction(newTransaction1) diff --git a/packages/binary/transaction/cached_transaction.go b/packages/binary/transaction/cached_transaction.go new file mode 100644 index 00000000..63a61f7e --- /dev/null +++ b/packages/binary/transaction/cached_transaction.go @@ -0,0 +1,21 @@ +package transaction + +import ( + "github.com/iotaledger/hive.go/objectstorage" +) + +type CachedTransaction struct { + *objectstorage.CachedObject +} + +func (cachedTransaction *CachedTransaction) Unwrap() *Transaction { + if untypedTransaction := cachedTransaction.Get(); untypedTransaction == nil { + return nil + } else { + if typeCastedTransaction := untypedTransaction.(*Transaction); typeCastedTransaction == nil || typeCastedTransaction.IsDeleted() { + return nil + } else { + return typeCastedTransaction + } + } +} diff --git a/packages/binary/transactionmetadata/cached_transactionmetadata.go b/packages/binary/transactionmetadata/cached_transactionmetadata.go new file mode 100644 index 00000000..83912b7c --- /dev/null +++ b/packages/binary/transactionmetadata/cached_transactionmetadata.go @@ -0,0 +1,21 @@ +package transactionmetadata + +import ( + "github.com/iotaledger/hive.go/objectstorage" +) + +type CachedTransactionMetadata struct { + *objectstorage.CachedObject +} + +func (cachedObject *CachedTransactionMetadata) Unwrap() *TransactionMetadata { + if untypedObject := cachedObject.Get(); untypedObject == nil { + return nil + } else { + if typedObject := untypedObject.(*TransactionMetadata); typedObject == nil || typedObject.IsDeleted() { + return nil + } else { + return typedObject + } + } +} diff --git a/packages/binary/transactionparser/builtinfilters/value_transaction_signature_filter.go b/packages/binary/transactionparser/builtinfilters/value_transaction_signature_filter.go index 4a0b0cdb..5c8cc14c 100644 --- a/packages/binary/transactionparser/builtinfilters/value_transaction_signature_filter.go +++ b/packages/binary/transactionparser/builtinfilters/value_transaction_signature_filter.go @@ -9,7 +9,7 @@ import ( "github.com/iotaledger/hive.go/async" ) -type ValueTransactionSignatureFilter struct { +type ValueTransferSignatureFilter struct { onAcceptCallback func(tx *transaction.Transaction) onRejectCallback func(tx *transaction.Transaction) workerPool async.WorkerPool @@ -18,13 +18,13 @@ type ValueTransactionSignatureFilter struct { onRejectCallbackMutex sync.RWMutex } -func NewValueTransactionSignatureFilter() (result *ValueTransactionSignatureFilter) { - result = &ValueTransactionSignatureFilter{} +func NewValueTransferSignatureFilter() (result *ValueTransferSignatureFilter) { + result = &ValueTransferSignatureFilter{} return } -func (filter *ValueTransactionSignatureFilter) Filter(tx *transaction.Transaction) { +func (filter *ValueTransferSignatureFilter) 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() { @@ -38,23 +38,23 @@ func (filter *ValueTransactionSignatureFilter) Filter(tx *transaction.Transactio }) } -func (filter *ValueTransactionSignatureFilter) OnAccept(callback func(tx *transaction.Transaction)) { +func (filter *ValueTransferSignatureFilter) OnAccept(callback func(tx *transaction.Transaction)) { filter.onAcceptCallbackMutex.Lock() filter.onAcceptCallback = callback filter.onAcceptCallbackMutex.Unlock() } -func (filter *ValueTransactionSignatureFilter) OnReject(callback func(tx *transaction.Transaction)) { +func (filter *ValueTransferSignatureFilter) OnReject(callback func(tx *transaction.Transaction)) { filter.onRejectCallbackMutex.Lock() filter.onRejectCallback = callback filter.onRejectCallbackMutex.Unlock() } -func (filter *ValueTransactionSignatureFilter) Shutdown() { +func (filter *ValueTransferSignatureFilter) Shutdown() { filter.workerPool.ShutdownGracefully() } -func (filter *ValueTransactionSignatureFilter) getAcceptCallback() (result func(tx *transaction.Transaction)) { +func (filter *ValueTransferSignatureFilter) getAcceptCallback() (result func(tx *transaction.Transaction)) { filter.onAcceptCallbackMutex.RLock() result = filter.onAcceptCallback filter.onAcceptCallbackMutex.RUnlock() @@ -62,7 +62,7 @@ func (filter *ValueTransactionSignatureFilter) getAcceptCallback() (result func( return } -func (filter *ValueTransactionSignatureFilter) getRejectCallback() (result func(tx *transaction.Transaction)) { +func (filter *ValueTransferSignatureFilter) getRejectCallback() (result func(tx *transaction.Transaction)) { filter.onRejectCallbackMutex.RLock() result = filter.onRejectCallback filter.onRejectCallbackMutex.RUnlock() diff --git a/packages/binary/transactionparser/transactionparser.go b/packages/binary/transactionparser/transactionparser.go index 3e937f32..66e3bb3a 100644 --- a/packages/binary/transactionparser/transactionparser.go +++ b/packages/binary/transactionparser/transactionparser.go @@ -43,7 +43,7 @@ func New() (result *TransactionParser) { // add builtin filters result.AddBytesFilter(builtinfilters.NewRecentlySeenBytesFilter()) result.AddTransactionsFilter(builtinfilters.NewTransactionSignatureFilter()) - result.AddTransactionsFilter(builtinfilters.NewValueTransactionSignatureFilter()) + result.AddTransactionsFilter(builtinfilters.NewValueTransferSignatureFilter()) return } -- GitLab