Skip to content

Commit

Permalink
Feat: started implementing global collection types
Browse files Browse the repository at this point in the history
  • Loading branch information
hmoog committed Mar 29, 2022
1 parent 8573265 commit e4f0de6
Show file tree
Hide file tree
Showing 16 changed files with 707 additions and 656 deletions.
96 changes: 51 additions & 45 deletions packages/refactored/ledger/booker.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ import (
"github.com/iotaledger/hive.go/generics/objectstorage"
"github.com/iotaledger/hive.go/generics/walker"

lo "github.com/iotaledger/goshimmer/packages/refactored/generics"
"github.com/iotaledger/goshimmer/packages/refactored/generics/filter"
"github.com/iotaledger/goshimmer/packages/refactored/ledger/branchdag"
"github.com/iotaledger/goshimmer/packages/refactored/utxo"
)

type Booker struct {
Expand All @@ -25,115 +22,124 @@ func (b *Booker) bookTransactionCommand(params *params, next dataflow.Next[*para
cachedOutputsMetadata := b.bookTransaction(params.Transaction.ID(), params.TransactionMetadata, params.InputsMetadata, params.Outputs)
defer cachedOutputsMetadata.Release()

params.OutputsMetadata = lo.KeyBy(cachedOutputsMetadata.Unwrap(), (*OutputMetadata).ID)
params.OutputsMetadata = NewOutputsMetadata(cachedOutputsMetadata.Unwrap()...)

return next(params)
}

func (b *Booker) bookTransaction(txID utxo.TransactionID, txMetadata *TransactionMetadata, inputsMetadata map[utxo.OutputID]*OutputMetadata, outputs []*Output) (cachedOutputsMetadata objectstorage.CachedObjects[*OutputMetadata]) {
func (b *Booker) bookTransaction(txID TransactionID, txMetadata *TransactionMetadata, inputsMetadata OutputsMetadata, outputs Outputs) (cachedOutputsMetadata objectstorage.CachedObjects[*OutputMetadata]) {
inheritedBranchIDs := b.inheritBranchIDsFromInputs(txID, inputsMetadata)

txMetadata.SetBranchIDs(inheritedBranchIDs)

return b.bookOutputs(outputs, inheritedBranchIDs)
return b.bookOutputs(txMetadata, outputs, inheritedBranchIDs)
}

func (b *Booker) inheritBranchIDsFromInputs(txID utxo.TransactionID, inputsMetadata map[utxo.OutputID]*OutputMetadata) (inheritedBranchIDs branchdag.BranchIDs) {
pendingParentBranchIDs := b.RemoveConfirmedBranches(lo.ReduceProperty(lo.Values(inputsMetadata), (*OutputMetadata).BranchIDs, branchdag.BranchIDs.AddAll, branchdag.NewBranchIDs()))

func (b *Booker) inheritBranchIDsFromInputs(txID TransactionID, inputsMetadata OutputsMetadata) (inheritedBranchIDs branchdag.BranchIDs) {
conflictingInputIDs, consumersToFork := b.determineConflictDetails(txID, inputsMetadata)
if len(conflictingInputIDs) == 0 {
return pendingParentBranchIDs
if conflictingInputIDs.Size() == 0 {
return b.RemoveConfirmedBranches(inputsMetadata.BranchIDs())
}

forkedBranchID := b.CreateBranch(txID, pendingParentBranchIDs, conflictingInputIDs)
b.CreateBranch(txID, b.RemoveConfirmedBranches(inputsMetadata.BranchIDs()), conflictingInputIDs)

for consumerToFork := range consumersToFork {
b.WithTransactionAndMetadata(consumerToFork, func(tx *Transaction, txMetadata *TransactionMetadata) {
_ = consumersToFork.ForEach(func(transactionID TransactionID) (err error) {
b.WithTransactionAndMetadata(transactionID, func(tx *Transaction, txMetadata *TransactionMetadata) {
b.forkTransaction(tx, txMetadata, conflictingInputIDs)
})
}

return branchdag.NewBranchIDs(forkedBranchID)
return nil
})

return branchdag.NewBranchIDs(txID)
}

func (b *Booker) determineConflictDetails(txID utxo.TransactionID, inputsMetadata map[utxo.OutputID]*OutputMetadata) (conflictingInputIDs map[utxo.OutputID]bool, consumersToFork map[utxo.TransactionID]bool) {
conflictingInputIDs = make(map[utxo.OutputID]bool)
consumersToFork = make(map[utxo.TransactionID]bool)
func (b *Booker) determineConflictDetails(txID TransactionID, inputsMetadata OutputsMetadata) (conflictingInputIDs OutputIDs, consumersToFork TransactionIDs) {
conflictingInputIDs = NewOutputIDs()
consumersToFork = NewTransactionIDs()

for outputID, outputMetadata := range inputsMetadata {
_ = inputsMetadata.ForEach(func(outputMetadata *OutputMetadata) error {
isConflicting, consumerToFork := outputMetadata.RegisterProcessedConsumer(txID)
if isConflicting {
conflictingInputIDs[outputID] = true
conflictingInputIDs.Add(outputMetadata.ID())
}

if consumerToFork != utxo.EmptyTransactionID {
consumersToFork[consumerToFork] = true
if consumerToFork != EmptyTransactionID {
consumersToFork.Add(consumerToFork)
}
}

return nil
})

return conflictingInputIDs, consumersToFork
}

func (b *Booker) bookOutputs(outputs []*Output, branchIDs branchdag.BranchIDs) (cachedOutputsMetadata objectstorage.CachedObjects[*OutputMetadata]) {
cachedOutputsMetadata = make(objectstorage.CachedObjects[*OutputMetadata], len(outputs))
for index, output := range outputs {
func (b *Booker) bookOutputs(txMetadata *TransactionMetadata, outputs Outputs, branchIDs branchdag.BranchIDs) (cachedOutputsMetadata objectstorage.CachedObjects[*OutputMetadata]) {
cachedOutputsMetadata = make(objectstorage.CachedObjects[*OutputMetadata], 0)

_ = outputs.ForEach(func(output *Output) (err error) {
outputMetadata := NewOutputMetadata(output.ID())
outputMetadata.SetBranchIDs(branchIDs)

cachedOutputsMetadata[index] = b.outputMetadataStorage.Store(outputMetadata)
cachedOutputsMetadata = append(cachedOutputsMetadata, b.outputMetadataStorage.Store(outputMetadata))
b.outputStorage.Store(output).Release()
}
return nil
})

txMetadata.SetOutputIDs(outputs.IDs())

return cachedOutputsMetadata
}

func (b *Booker) forkTransaction(tx utxo.Transaction, txMetadata *TransactionMetadata, outputsSpentByConflictingTx map[utxo.OutputID]bool) {
func (b *Booker) forkTransaction(tx *Transaction, txMetadata *TransactionMetadata, outputsSpentByConflictingTx OutputIDs) {
b.Lock(txMetadata.ID())
defer b.Unlock(txMetadata.ID())

conflictingInputs := lo.Filter(b.outputIDsFromInputs(tx.Inputs()), filter.MapHasKey(outputsSpentByConflictingTx))
conflictingInputs := b.resolveInputs(tx.Inputs()).Intersect(outputsSpentByConflictingTx)
previousParentBranches := txMetadata.BranchIDs()

// TODO: RETURN
forkedBranchID := b.CreateBranch(txMetadata.ID(), previousParentBranches, branchdag.NewConflictIDs(lo.Map(conflictingInputs, branchdag.NewConflictID)...))

if !b.updateBranchesAfterFork(txMetadata, forkedBranchID, previousParentBranches) {
if !b.CreateBranch(txMetadata.ID(), previousParentBranches, conflictingInputs) || !b.updateBranchesAfterFork(txMetadata, txMetadata.ID(), previousParentBranches) {
b.Unlock(txMetadata.ID())
return
}
b.Unlock(txMetadata.ID())

b.TransactionForkedEvent.Trigger()
// b.TransactionForkedEvent.Trigger()
// trigger forked event

b.propagateForkedBranchToFutureCone(txMetadata, forkedBranchID, previousParentBranches)
b.propagateForkedBranchToFutureCone(txMetadata, previousParentBranches)

return
}

func (b *Booker) propagateForkedBranchToFutureCone(txMetadata *TransactionMetadata, forkedBranchID branchdag.BranchID, previousParentBranches branchdag.BranchIDs) {
b.WalkConsumingTransactionMetadata(txMetadata.OutputIDs(), func(consumingTxMetadata *TransactionMetadata, walker *walker.Walker[utxo.OutputID]) {
func (b *Booker) propagateForkedBranchToFutureCone(txMetadata *TransactionMetadata, previousParentBranches branchdag.BranchIDs) {
b.WalkConsumingTransactionMetadata(txMetadata.OutputIDs(), func(consumingTxMetadata *TransactionMetadata, walker *walker.Walker[OutputID]) {
b.Lock(consumingTxMetadata.ID())
defer b.Unlock(consumingTxMetadata.ID())

if !b.updateBranchesAfterFork(consumingTxMetadata, forkedBranchID, previousParentBranches) {
if !b.updateBranchesAfterFork(consumingTxMetadata, txMetadata.ID(), previousParentBranches) {
return
}

// Trigger propagated event

walker.PushAll(consumingTxMetadata.OutputIDs()...)
walker.PushAll(consumingTxMetadata.OutputIDs().Slice()...)
})
}

func (b *Booker) updateBranchesAfterFork(txMetadata *TransactionMetadata, forkedBranchID branchdag.BranchID, previousParents branchdag.BranchIDs) bool {
if txMetadata.BranchIDs().Contains(forkedBranchID) {
if txMetadata.BranchIDs().Has(forkedBranchID) {
return false
}

newBranches := b.RemoveConfirmedBranches(txMetadata.BranchIDs().Subtract(previousParents).Add(forkedBranchID))
objectstorage.CachedObjects[*OutputMetadata](lo.Map(txMetadata.OutputIDs(), b.CachedOutputMetadata)).Consume(func(outputMetadata *OutputMetadata) {
newBranchIDs := txMetadata.BranchIDs().Clone()
newBranchIDs.DeleteAll(previousParents)
newBranchIDs.Add(forkedBranchID)
newBranches := b.RemoveConfirmedBranches(newBranchIDs)

b.CachedOutputsMetadata(txMetadata.OutputIDs()).Consume(func(outputMetadata *OutputMetadata) {
outputMetadata.SetBranchIDs(newBranches)
})

txMetadata.SetBranchIDs(newBranches)

return true
Expand Down
Loading

0 comments on commit e4f0de6

Please sign in to comment.