diff --git a/packages/refactored/ledger/booker.go b/packages/refactored/ledger/booker.go index 77f725be75..aec9c70725 100644 --- a/packages/refactored/ledger/booker.go +++ b/packages/refactored/ledger/booker.go @@ -8,6 +8,7 @@ import ( "github.com/iotaledger/goshimmer/packages/refactored/branchdag" "github.com/iotaledger/goshimmer/packages/refactored/generics" + "github.com/iotaledger/goshimmer/packages/refactored/utxo" ) type Booker struct { @@ -60,7 +61,7 @@ func (b *Booker) bookTransaction(txMetadata *TransactionMetadata, inputsMetadata b.TransactionBookedEvent.Trigger(txMetadata.ID()) } -func (b *Booker) inheritBranchIDs(txID TransactionID, inputsMetadata OutputsMetadata) (inheritedBranchIDs branchdag.BranchIDs) { +func (b *Booker) inheritBranchIDs(txID utxo.TransactionID, inputsMetadata OutputsMetadata) (inheritedBranchIDs branchdag.BranchIDs) { conflictingInputIDs, consumersToFork := b.determineConflictDetails(txID, inputsMetadata) if conflictingInputIDs.Size() == 0 { return b.RemoveConfirmedBranches(inputsMetadata.BranchIDs()) @@ -68,7 +69,7 @@ func (b *Booker) inheritBranchIDs(txID TransactionID, inputsMetadata OutputsMeta b.CreateBranch(txID, b.RemoveConfirmedBranches(inputsMetadata.BranchIDs()), conflictingInputIDs) - _ = consumersToFork.ForEach(func(transactionID TransactionID) (err error) { + _ = consumersToFork.ForEach(func(transactionID utxo.TransactionID) (err error) { b.WithTransactionAndMetadata(transactionID, func(tx *Transaction, txMetadata *TransactionMetadata) { b.forkTransaction(tx, txMetadata, conflictingInputIDs) }) @@ -91,9 +92,9 @@ func (b *Booker) storeOutputs(outputs Outputs, branchIDs branchdag.BranchIDs) { }) } -func (b *Booker) determineConflictDetails(txID TransactionID, inputsMetadata OutputsMetadata) (conflictingInputIDs OutputIDs, consumersToFork TransactionIDs) { - conflictingInputIDs = NewOutputIDs() - consumersToFork = NewTransactionIDs() +func (b *Booker) determineConflictDetails(txID utxo.TransactionID, inputsMetadata OutputsMetadata) (conflictingInputIDs utxo.OutputIDs, consumersToFork utxo.TransactionIDs) { + conflictingInputIDs = utxo.NewOutputIDs() + consumersToFork = utxo.NewTransactionIDs() _ = inputsMetadata.ForEach(func(outputMetadata *OutputMetadata) error { isConflicting, consumerToFork := outputMetadata.RegisterProcessedConsumer(txID) @@ -101,7 +102,7 @@ func (b *Booker) determineConflictDetails(txID TransactionID, inputsMetadata Out conflictingInputIDs.Add(outputMetadata.ID()) } - if consumerToFork != EmptyTransactionID { + if consumerToFork != utxo.EmptyTransactionID { consumersToFork.Add(consumerToFork) } @@ -111,7 +112,7 @@ func (b *Booker) determineConflictDetails(txID TransactionID, inputsMetadata Out return conflictingInputIDs, consumersToFork } -func (b *Booker) forkTransaction(tx *Transaction, txMetadata *TransactionMetadata, outputsSpentByConflictingTx OutputIDs) { +func (b *Booker) forkTransaction(tx *Transaction, txMetadata *TransactionMetadata, outputsSpentByConflictingTx utxo.OutputIDs) { b.Lock(txMetadata.ID()) conflictingInputs := b.resolveInputs(tx.Inputs()).Intersect(outputsSpentByConflictingTx) @@ -132,7 +133,7 @@ func (b *Booker) forkTransaction(tx *Transaction, txMetadata *TransactionMetadat } func (b *Booker) propagateForkedBranchToFutureCone(txMetadata *TransactionMetadata, forkedBranchID branchdag.BranchID, previousParentBranches branchdag.BranchIDs) { - b.WalkConsumingTransactionMetadata(txMetadata.OutputIDs(), func(consumingTxMetadata *TransactionMetadata, walker *walker.Walker[OutputID]) { + b.WalkConsumingTransactionMetadata(txMetadata.OutputIDs(), func(consumingTxMetadata *TransactionMetadata, walker *walker.Walker[utxo.OutputID]) { b.Lock(consumingTxMetadata.ID()) defer b.Unlock(consumingTxMetadata.ID()) diff --git a/packages/refactored/ledger/dataflow.go b/packages/refactored/ledger/dataflow.go index ba3a22f008..8da2f51c67 100644 --- a/packages/refactored/ledger/dataflow.go +++ b/packages/refactored/ledger/dataflow.go @@ -3,6 +3,8 @@ package ledger import ( "github.com/iotaledger/hive.go/generics/dataflow" "github.com/iotaledger/hive.go/generics/event" + + "github.com/iotaledger/goshimmer/packages/refactored/utxo" ) type DataFlow struct { @@ -16,7 +18,7 @@ func NewDataFlow(ledger *Ledger) *DataFlow { } func (d *DataFlow) Setup() { - d.TransactionBookedEvent.Attach(event.NewClosure[TransactionID](func(txID TransactionID) { + d.TransactionBookedEvent.Attach(event.NewClosure[utxo.TransactionID](func(txID utxo.TransactionID) { d.CachedTransaction(txID).Consume(func(tx *Transaction) { _ = d.Ledger.processTransaction(tx) }) @@ -46,14 +48,14 @@ func (d *DataFlow) checkTransaction() *dataflow.DataFlow[*dataFlowParams] { return dataflow.New[*dataFlowParams]( d.checkSolidityCommand, d.checkOutputsCausallyRelatedCommand, - d.executeTransactionCommand, + d.checkTransactionExecutionCommand, ) } type dataFlowParams struct { Transaction *Transaction TransactionMetadata *TransactionMetadata - InputIDs OutputIDs + InputIDs utxo.OutputIDs Inputs Outputs InputsMetadata OutputsMetadata Consumers []*Consumer diff --git a/packages/refactored/ledger/ledger.go b/packages/refactored/ledger/ledger.go index 0804c68334..18890473a8 100644 --- a/packages/refactored/ledger/ledger.go +++ b/packages/refactored/ledger/ledger.go @@ -14,14 +14,12 @@ import ( // region Ledger /////////////////////////////////////////////////////////////////////////////////////////////////////// type Ledger struct { - TransactionStoredEvent *event.Event[TransactionID] - TransactionBookedEvent *event.Event[TransactionID] + TransactionStoredEvent *event.Event[utxo.TransactionID] + TransactionBookedEvent *event.Event[utxo.TransactionID] ErrorEvent *event.Event[error] *Storage - *Solidifier *Validator - *VM *Booker *DataFlow @@ -34,8 +32,8 @@ type Ledger struct { func New(store kvstore.KVStore, vm utxo.VM, options ...Option) (ledger *Ledger) { ledger = &Ledger{ - TransactionStoredEvent: event.New[TransactionID](), - TransactionBookedEvent: event.New[TransactionID](), + TransactionStoredEvent: event.New[utxo.TransactionID](), + TransactionBookedEvent: event.New[utxo.TransactionID](), ErrorEvent: event.New[error](), BranchDAG: branchdag.NewBranchDAG(store, database.NewCacheTimeProvider(0)), @@ -46,9 +44,7 @@ func New(store kvstore.KVStore, vm utxo.VM, options ...Option) (ledger *Ledger) ledger.DataFlow = NewDataFlow(ledger) ledger.Storage = NewStorage(ledger) - ledger.Solidifier = NewSolidifier(ledger) - ledger.Validator = NewValidator(ledger) - ledger.VM = NewVM(ledger, vm) + ledger.Validator = NewValidator(ledger, vm) ledger.Booker = NewBooker(ledger) ledger.Utils = NewUtils(ledger) @@ -88,3 +84,41 @@ func (l *Ledger) processTransaction(tx *Transaction) (err error) { } // endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// region Options ////////////////////////////////////////////////////////////////////////////////////////////////////// + +// Option represents the return type of optional parameters that can be handed into the constructor of the Ledger +// to configure its behavior. +type Option func(*Options) + +// Options is a container for all configurable parameters of the Ledger. +type Options struct { + Store kvstore.KVStore + CacheTimeProvider *database.CacheTimeProvider + LazyBookingEnabled bool +} + +// Store is an Option for the Ledger that allows to specify which storage layer is supposed to be used to persist +// data. +func Store(store kvstore.KVStore) Option { + return func(options *Options) { + options.Store = store + } +} + +// CacheTimeProvider is an Option for the Tangle that allows to override hard coded cache time. +func CacheTimeProvider(cacheTimeProvider *database.CacheTimeProvider) Option { + return func(options *Options) { + options.CacheTimeProvider = cacheTimeProvider + } +} + +// LazyBookingEnabled is an Option for the Ledger that allows to specify if the ledger state should lazy book +// conflicts that look like they have been decided already. +func LazyBookingEnabled(enabled bool) Option { + return func(options *Options) { + options.LazyBookingEnabled = enabled + } +} + +// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/packages/refactored/ledger/models.go b/packages/refactored/ledger/models.go index 50d0307fe1..f3b6402219 100644 --- a/packages/refactored/ledger/models.go +++ b/packages/refactored/ledger/models.go @@ -61,7 +61,7 @@ type TransactionMetadata struct { solidificationTimeMutex sync.RWMutex lazyBooked bool lazyBookedMutex sync.RWMutex - outputIDs OutputIDs + outputIDs utxo.OutputIDs outputIDsMutex sync.RWMutex gradeOfFinality gof.GradeOfFinality gradeOfFinalityTime time.Time @@ -247,7 +247,7 @@ func (t *TransactionMetadata) SetLazyBooked(lazyBooked bool) (modified bool) { } // OutputIDs returns the OutputIDs that this Transaction created. -func (t *TransactionMetadata) OutputIDs() OutputIDs { +func (t *TransactionMetadata) OutputIDs() utxo.OutputIDs { t.outputIDsMutex.RLock() defer t.outputIDsMutex.RUnlock() @@ -255,7 +255,7 @@ func (t *TransactionMetadata) OutputIDs() OutputIDs { } // SetOutputIDs sets the OutputIDs that this Transaction created. -func (t *TransactionMetadata) SetOutputIDs(outputIDs OutputIDs) { +func (t *TransactionMetadata) SetOutputIDs(outputIDs utxo.OutputIDs) { t.outputIDsMutex.RLock() defer t.outputIDsMutex.RUnlock() @@ -385,11 +385,11 @@ var _ objectstorage.StorableObject = new(Output) // region Outputs ////////////////////////////////////////////////////////////////////////////////////////////////////// type Outputs struct { - *orderedmap.OrderedMap[OutputID, *Output] + *orderedmap.OrderedMap[utxo.OutputID, *Output] } func NewOutputs(outputs ...*Output) (new Outputs) { - new = Outputs{orderedmap.New[OutputID, *Output]()} + new = Outputs{orderedmap.New[utxo.OutputID, *Output]()} for _, output := range outputs { new.Set(output.ID(), output) } @@ -397,18 +397,18 @@ func NewOutputs(outputs ...*Output) (new Outputs) { return new } -func (o Outputs) IDs() (ids OutputIDs) { - outputIDs := make([]OutputID, 0) - o.OrderedMap.ForEach(func(id OutputID, _ *Output) bool { +func (o Outputs) IDs() (ids utxo.OutputIDs) { + outputIDs := make([]utxo.OutputID, 0) + o.OrderedMap.ForEach(func(id utxo.OutputID, _ *Output) bool { outputIDs = append(outputIDs, id) return true }) - return NewOutputIDs(outputIDs...) + return utxo.NewOutputIDs(outputIDs...) } func (o Outputs) ForEach(callback func(output *Output) (err error)) (err error) { - o.OrderedMap.ForEach(func(_ OutputID, output *Output) bool { + o.OrderedMap.ForEach(func(_ utxo.OutputID, output *Output) bool { if err = callback(output); err != nil { return false } @@ -708,11 +708,11 @@ var _ objectstorage.StorableObject = new(OutputMetadata) // region OutputsMetadata ////////////////////////////////////////////////////////////////////////////////////////////// type OutputsMetadata struct { - *orderedmap.OrderedMap[OutputID, *OutputMetadata] + *orderedmap.OrderedMap[utxo.OutputID, *OutputMetadata] } func NewOutputsMetadata(outputsMetadata ...*OutputMetadata) (new OutputsMetadata) { - new = OutputsMetadata{orderedmap.New[OutputID, *OutputMetadata]()} + new = OutputsMetadata{orderedmap.New[utxo.OutputID, *OutputMetadata]()} for _, outputMetadata := range outputsMetadata { new.Set(outputMetadata.ID(), outputMetadata) } @@ -733,8 +733,8 @@ func (o OutputsMetadata) Filter(predicate func(outputMetadata *OutputMetadata) b return filtered } -func (o OutputsMetadata) IDs() (ids OutputIDs) { - ids = NewOutputIDs() +func (o OutputsMetadata) IDs() (ids utxo.OutputIDs) { + ids = utxo.NewOutputIDs() _ = o.ForEach(func(outputMetadata *OutputMetadata) (err error) { ids.Add(outputMetadata.ID()) return nil @@ -754,7 +754,7 @@ func (o OutputsMetadata) BranchIDs() (branchIDs branchdag.BranchIDs) { } func (o OutputsMetadata) ForEach(callback func(outputMetadata *OutputMetadata) (err error)) (err error) { - o.OrderedMap.ForEach(func(_ OutputID, outputMetadata *OutputMetadata) bool { + o.OrderedMap.ForEach(func(_ utxo.OutputID, outputMetadata *OutputMetadata) bool { if err = callback(outputMetadata); err != nil { return false } diff --git a/packages/refactored/ledger/options.go b/packages/refactored/ledger/options.go deleted file mode 100644 index f33f86229e..0000000000 --- a/packages/refactored/ledger/options.go +++ /dev/null @@ -1,45 +0,0 @@ -package ledger - -import ( - "github.com/iotaledger/hive.go/kvstore" - - "github.com/iotaledger/goshimmer/packages/database" -) - -// region Options ////////////////////////////////////////////////////////////////////////////////////////////////////// - -// Option represents the return type of optional parameters that can be handed into the constructor of the Ledger -// to configure its behavior. -type Option func(*Options) - -// Options is a container for all configurable parameters of the Ledger. -type Options struct { - Store kvstore.KVStore - CacheTimeProvider *database.CacheTimeProvider - LazyBookingEnabled bool -} - -// Store is an Option for the Ledger that allows to specify which storage layer is supposed to be used to persist -// data. -func Store(store kvstore.KVStore) Option { - return func(options *Options) { - options.Store = store - } -} - -// CacheTimeProvider is an Option for the Tangle that allows to override hard coded cache time. -func CacheTimeProvider(cacheTimeProvider *database.CacheTimeProvider) Option { - return func(options *Options) { - options.CacheTimeProvider = cacheTimeProvider - } -} - -// LazyBookingEnabled is an Option for the Ledger that allows to specify if the ledger state should lazy book -// conflicts that look like they have been decided already. -func LazyBookingEnabled(enabled bool) Option { - return func(options *Options) { - options.LazyBookingEnabled = enabled - } -} - -// endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/packages/refactored/ledger/solidifier.go b/packages/refactored/ledger/solidifier.go deleted file mode 100644 index b09117e454..0000000000 --- a/packages/refactored/ledger/solidifier.go +++ /dev/null @@ -1,43 +0,0 @@ -package ledger - -import ( - "github.com/cockroachdb/errors" - "github.com/iotaledger/hive.go/generics/dataflow" - "github.com/iotaledger/hive.go/generics/objectstorage" - - "github.com/iotaledger/goshimmer/packages/refactored/utxo" -) - -type Solidifier struct { - *Ledger -} - -func NewSolidifier(ledger *Ledger) (new *Solidifier) { - return &Solidifier{ - Ledger: ledger, - } -} - -func (s *Solidifier) checkSolidityCommand(params *dataFlowParams, next dataflow.Next[*dataFlowParams]) (err error) { - if params.InputIDs.IsEmpty() { - params.InputIDs = s.resolveInputs(params.Transaction.Inputs()) - } - - cachedInputs := s.CachedOutputs(params.InputIDs) - defer cachedInputs.Release() - if params.Inputs = NewOutputs(cachedInputs.Unwrap(true)...); params.Inputs.Size() != len(cachedInputs) { - return errors.Errorf("not all outputs of %s available: %w", params.Transaction.ID(), ErrTransactionUnsolid) - } - - return next(params) -} - -func (s *Solidifier) initConsumers(outputIDs OutputIDs, txID TransactionID) (cachedConsumers objectstorage.CachedObjects[*Consumer]) { - cachedConsumers = make(objectstorage.CachedObjects[*Consumer], 0) - _ = outputIDs.ForEach(func(outputID utxo.OutputID) (err error) { - cachedConsumers = append(cachedConsumers, s.CachedConsumer(outputID, txID, NewConsumer)) - return nil - }) - - return cachedConsumers -} diff --git a/packages/refactored/ledger/storage.go b/packages/refactored/ledger/storage.go index 708c4fa10b..3a8222113b 100644 --- a/packages/refactored/ledger/storage.go +++ b/packages/refactored/ledger/storage.go @@ -10,6 +10,7 @@ import ( "github.com/iotaledger/goshimmer/packages/database" "github.com/iotaledger/goshimmer/packages/refactored/txvm" + "github.com/iotaledger/goshimmer/packages/refactored/utxo" ) // region Storage ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -62,7 +63,7 @@ func NewStorage(ledger *Ledger) (newStorage *Storage) { func (s *Storage) storeTransactionCommand(params *dataFlowParams, next dataflow.Next[*dataFlowParams]) (err error) { created := false - cachedTransactionMetadata := s.CachedTransactionMetadata(params.Transaction.ID(), func(txID TransactionID) *TransactionMetadata { + cachedTransactionMetadata := s.CachedTransactionMetadata(params.Transaction.ID(), func(txID utxo.TransactionID) *TransactionMetadata { s.transactionStorage.Store(params.Transaction).Release() created = true return NewTransactionMetadata(txID) @@ -90,13 +91,23 @@ func (s *Storage) storeTransactionCommand(params *dataFlowParams, next dataflow. return next(params) } +func (s *Storage) initConsumers(outputIDs utxo.OutputIDs, txID utxo.TransactionID) (cachedConsumers objectstorage.CachedObjects[*Consumer]) { + cachedConsumers = make(objectstorage.CachedObjects[*Consumer], 0) + _ = outputIDs.ForEach(func(outputID utxo.OutputID) (err error) { + cachedConsumers = append(cachedConsumers, s.CachedConsumer(outputID, txID, NewConsumer)) + return nil + }) + + return cachedConsumers +} + // CachedTransaction retrieves the Transaction with the given TransactionID from the object storage. -func (s *Storage) CachedTransaction(transactionID TransactionID) (cachedTransaction *objectstorage.CachedObject[*Transaction]) { +func (s *Storage) CachedTransaction(transactionID utxo.TransactionID) (cachedTransaction *objectstorage.CachedObject[*Transaction]) { return s.transactionStorage.Load(transactionID.Bytes()) } // CachedTransactionMetadata retrieves the TransactionMetadata with the given TransactionID from the object storage. -func (s *Storage) CachedTransactionMetadata(transactionID TransactionID, computeIfAbsentCallback ...func(transactionID TransactionID) *TransactionMetadata) (cachedTransactionMetadata *objectstorage.CachedObject[*TransactionMetadata]) { +func (s *Storage) CachedTransactionMetadata(transactionID utxo.TransactionID, computeIfAbsentCallback ...func(transactionID utxo.TransactionID) *TransactionMetadata) (cachedTransactionMetadata *objectstorage.CachedObject[*TransactionMetadata]) { if len(computeIfAbsentCallback) >= 1 { return s.transactionMetadataStorage.ComputeIfAbsent(transactionID.Bytes(), func(key []byte) *TransactionMetadata { return computeIfAbsentCallback[0](transactionID) @@ -107,13 +118,13 @@ func (s *Storage) CachedTransactionMetadata(transactionID TransactionID, compute } // CachedOutput retrieves the Output with the given OutputID from the object storage. -func (s *Storage) CachedOutput(outputID OutputID) (cachedOutput CachedOutput) { +func (s *Storage) CachedOutput(outputID utxo.OutputID) (cachedOutput *objectstorage.CachedObject[*Output]) { return s.outputStorage.Load(outputID.Bytes()) } -func (s *Storage) CachedOutputs(outputIDs OutputIDs) (cachedOutputs CachedOutputs) { - cachedOutputs = make(CachedOutputs, 0) - _ = outputIDs.ForEach(func(outputID OutputID) error { +func (s *Storage) CachedOutputs(outputIDs utxo.OutputIDs) (cachedOutputs objectstorage.CachedObjects[*Output]) { + cachedOutputs = make(objectstorage.CachedObjects[*Output], 0) + _ = outputIDs.ForEach(func(outputID utxo.OutputID) error { cachedOutputs = append(cachedOutputs, s.CachedOutput(outputID)) return nil }) @@ -122,13 +133,13 @@ func (s *Storage) CachedOutputs(outputIDs OutputIDs) (cachedOutputs CachedOutput } // CachedOutputMetadata retrieves the OutputMetadata with the given OutputID from the object storage. -func (s *Storage) CachedOutputMetadata(outputID OutputID) (cachedOutputMetadata *objectstorage.CachedObject[*OutputMetadata]) { +func (s *Storage) CachedOutputMetadata(outputID utxo.OutputID) (cachedOutputMetadata *objectstorage.CachedObject[*OutputMetadata]) { return s.outputMetadataStorage.Load(outputID.Bytes()) } -func (s *Storage) CachedOutputsMetadata(outputIDs OutputIDs) (cachedOutputsMetadata objectstorage.CachedObjects[*OutputMetadata]) { +func (s *Storage) CachedOutputsMetadata(outputIDs utxo.OutputIDs) (cachedOutputsMetadata objectstorage.CachedObjects[*OutputMetadata]) { cachedOutputsMetadata = make(objectstorage.CachedObjects[*OutputMetadata], 0) - _ = outputIDs.ForEach(func(outputID OutputID) error { + _ = outputIDs.ForEach(func(outputID utxo.OutputID) error { cachedOutputsMetadata = append(cachedOutputsMetadata, s.CachedOutputMetadata(outputID)) return nil }) @@ -137,7 +148,7 @@ func (s *Storage) CachedOutputsMetadata(outputIDs OutputIDs) (cachedOutputsMetad } // CachedConsumer retrieves the OutputMetadata with the given OutputID from the object storage. -func (s *Storage) CachedConsumer(outputID OutputID, txID TransactionID, computeIfAbsentCallback ...func(outputID OutputID, txID TransactionID) *Consumer) (cachedOutput *objectstorage.CachedObject[*Consumer]) { +func (s *Storage) CachedConsumer(outputID utxo.OutputID, txID utxo.TransactionID, computeIfAbsentCallback ...func(outputID utxo.OutputID, txID utxo.TransactionID) *Consumer) (cachedOutput *objectstorage.CachedObject[*Consumer]) { if len(computeIfAbsentCallback) >= 1 { return s.consumerStorage.ComputeIfAbsent(byteutils.ConcatBytes(outputID.Bytes(), txID.Bytes()), func(key []byte) *Consumer { return computeIfAbsentCallback[0](outputID, txID) @@ -148,7 +159,7 @@ func (s *Storage) CachedConsumer(outputID OutputID, txID TransactionID, computeI } // CachedConsumers retrieves the Consumers of the given OutputID from the object storage. -func (s *Storage) CachedConsumers(outputID OutputID) (cachedConsumers objectstorage.CachedObjects[*Consumer]) { +func (s *Storage) CachedConsumers(outputID utxo.OutputID) (cachedConsumers objectstorage.CachedObjects[*Consumer]) { cachedConsumers = make(objectstorage.CachedObjects[*Consumer], 0) s.consumerStorage.ForEach(func(key []byte, cachedObject *objectstorage.CachedObject[*Consumer]) bool { cachedConsumers = append(cachedConsumers, cachedObject) diff --git a/packages/refactored/ledger/testframework.go b/packages/refactored/ledger/testframework.go index 9a4b802cbe..2edd774bb5 100644 --- a/packages/refactored/ledger/testframework.go +++ b/packages/refactored/ledger/testframework.go @@ -25,7 +25,7 @@ type TestFramework struct { Ledger *Ledger transactionsByAlias map[string]*MockedTransaction - outputIDsByAlias map[string]OutputID + outputIDsByAlias map[string]utxo.OutputID } func NewTestFramework(options ...Option) (new *TestFramework) { @@ -33,7 +33,7 @@ func NewTestFramework(options ...Option) (new *TestFramework) { Ledger: New(mapdb.NewMapDB(), NewMockedVM(), options...), transactionsByAlias: make(map[string]*MockedTransaction), - outputIDsByAlias: make(map[string]OutputID), + outputIDsByAlias: make(map[string]utxo.OutputID), } genesisOutput := NewOutput(NewMockedOutput(utxo.EmptyTransactionID, 0)) @@ -95,7 +95,7 @@ func (t *TestFramework) AssertBranchDAG(testing *testing.T, expectedParents map[ } } -func (t *TestFramework) TransactionIDs(txAliases ...string) (txIDs TransactionIDs) { +func (t *TestFramework) TransactionIDs(txAliases ...string) (txIDs utxo.TransactionIDs) { txIDs = branchdag.NewBranchIDs() for _, expectedBranchAlias := range txAliases { if expectedBranchAlias == "MasterBranch" { @@ -337,12 +337,12 @@ func (m *MockedTransaction) Bytes() []byte { } func (m *MockedTransaction) String() (humanReadable string) { - inputIDs := NewOutputIDs() + inputIDs := utxo.NewOutputIDs() for _, input := range m.Inputs() { inputIDs.Add(input.(*MockedInput).outputID) } - outputIDs := NewOutputIDs() + outputIDs := utxo.NewOutputIDs() for i := uint16(0); i < m.outputCount; i++ { outputIDs.Add(utxo.NewOutputID(m.ID(), i, []byte(""))) } diff --git a/packages/refactored/ledger/types.go b/packages/refactored/ledger/types.go deleted file mode 100644 index 9cab63d1f4..0000000000 --- a/packages/refactored/ledger/types.go +++ /dev/null @@ -1,39 +0,0 @@ -package ledger - -import ( - "github.com/iotaledger/hive.go/generics/objectstorage" - - "github.com/iotaledger/goshimmer/packages/refactored/utxo" -) - -type CachedOutputs = objectstorage.CachedObjects[*Output] - -type CachedOutput = *objectstorage.CachedObject[*Output] - -type CachedOutputMetadata = *objectstorage.CachedObject[*OutputMetadata] - -type CachedOutputsMetadata = objectstorage.CachedObjects[*OutputMetadata] - -type CachedConsumer = *objectstorage.CachedObject[*Consumer] - -type CachedConsumers = objectstorage.CachedObjects[*Consumer] - -type CachedTransaction = *objectstorage.CachedObject[*Transaction] - -type CachedTransactions = *objectstorage.CachedObjects[*Transaction] - -type Input = utxo.Input - -type TransactionID = utxo.TransactionID - -type TransactionIDs = utxo.TransactionIDs - -type OutputID = utxo.OutputID - -type OutputIDs = utxo.OutputIDs - -var NewOutputIDs = utxo.NewOutputIDs - -var NewTransactionIDs = utxo.NewTransactionIDs - -var EmptyTransactionID = utxo.EmptyTransactionID diff --git a/packages/refactored/ledger/utils.go b/packages/refactored/ledger/utils.go index 693a6bfc16..9b3848704c 100644 --- a/packages/refactored/ledger/utils.go +++ b/packages/refactored/ledger/utils.go @@ -3,6 +3,8 @@ package ledger import ( "github.com/iotaledger/hive.go/generics/set" "github.com/iotaledger/hive.go/generics/walker" + + "github.com/iotaledger/goshimmer/packages/refactored/utxo" ) type Utils struct { @@ -15,13 +17,13 @@ func NewUtils(ledger *Ledger) (new *Utils) { } } -func (u *Utils) WalkConsumingTransactionID(entryPoints OutputIDs, callback func(consumingTxID TransactionID, walker *walker.Walker[OutputID])) { +func (u *Utils) WalkConsumingTransactionID(entryPoints utxo.OutputIDs, callback func(consumingTxID utxo.TransactionID, walker *walker.Walker[utxo.OutputID])) { if entryPoints.Size() == 0 { return } - seenTransactions := set.New[TransactionID](false) - futureConeWalker := walker.New[OutputID](false).PushAll(entryPoints.Slice()...) + seenTransactions := set.New[utxo.TransactionID](false) + futureConeWalker := walker.New[utxo.OutputID](false).PushAll(entryPoints.Slice()...) for futureConeWalker.HasNext() { u.CachedConsumers(futureConeWalker.Next()).Consume(func(consumer *Consumer) { if futureConeWalker.WalkStopped() || !seenTransactions.Add(consumer.TransactionID()) { @@ -33,16 +35,16 @@ func (u *Utils) WalkConsumingTransactionID(entryPoints OutputIDs, callback func( } } -func (u *Utils) WalkConsumingTransactionMetadata(entryPoints OutputIDs, callback func(txMetadata *TransactionMetadata, walker *walker.Walker[OutputID])) { - u.WalkConsumingTransactionID(entryPoints, func(consumingTxID TransactionID, walker *walker.Walker[OutputID]) { +func (u *Utils) WalkConsumingTransactionMetadata(entryPoints utxo.OutputIDs, callback func(txMetadata *TransactionMetadata, walker *walker.Walker[utxo.OutputID])) { + u.WalkConsumingTransactionID(entryPoints, func(consumingTxID utxo.TransactionID, walker *walker.Walker[utxo.OutputID]) { u.CachedTransactionMetadata(consumingTxID).Consume(func(txMetadata *TransactionMetadata) { callback(txMetadata, walker) }) }) } -func (u *Utils) WalkConsumingTransactionAndMetadata(entryPoints OutputIDs, callback func(tx *Transaction, txMetadata *TransactionMetadata, walker *walker.Walker[OutputID])) { - u.WalkConsumingTransactionID(entryPoints, func(consumingTxID TransactionID, walker *walker.Walker[OutputID]) { +func (u *Utils) WalkConsumingTransactionAndMetadata(entryPoints utxo.OutputIDs, callback func(tx *Transaction, txMetadata *TransactionMetadata, walker *walker.Walker[utxo.OutputID])) { + u.WalkConsumingTransactionID(entryPoints, func(consumingTxID utxo.TransactionID, walker *walker.Walker[utxo.OutputID]) { u.CachedTransactionMetadata(consumingTxID).Consume(func(txMetadata *TransactionMetadata) { u.CachedTransaction(consumingTxID).Consume(func(tx *Transaction) { callback(tx, txMetadata, walker) @@ -51,7 +53,7 @@ func (u *Utils) WalkConsumingTransactionAndMetadata(entryPoints OutputIDs, callb }) } -func (u *Utils) WithTransactionAndMetadata(txID TransactionID, callback func(tx *Transaction, txMetadata *TransactionMetadata)) { +func (u *Utils) WithTransactionAndMetadata(txID utxo.TransactionID, callback func(tx *Transaction, txMetadata *TransactionMetadata)) { u.CachedTransaction(txID).Consume(func(tx *Transaction) { u.CachedTransactionMetadata(txID).Consume(func(txMetadata *TransactionMetadata) { callback(tx, txMetadata) diff --git a/packages/refactored/ledger/validator.go b/packages/refactored/ledger/validator.go index 2d41cf3acf..a637eeb193 100644 --- a/packages/refactored/ledger/validator.go +++ b/packages/refactored/ledger/validator.go @@ -6,17 +6,35 @@ import ( "github.com/iotaledger/hive.go/generics/dataflow" "github.com/iotaledger/hive.go/generics/walker" + "github.com/iotaledger/goshimmer/packages/refactored/generics" "github.com/iotaledger/goshimmer/packages/refactored/utxo" ) type Validator struct { *Ledger + + vm utxo.VM } -func NewValidator(ledger *Ledger) (new *Validator) { +func NewValidator(ledger *Ledger, vm utxo.VM) (new *Validator) { return &Validator{ Ledger: ledger, + vm: vm, + } +} + +func (v *Validator) checkSolidityCommand(params *dataFlowParams, next dataflow.Next[*dataFlowParams]) (err error) { + if params.InputIDs.IsEmpty() { + params.InputIDs = v.resolveInputs(params.Transaction.Inputs()) } + + cachedInputs := v.CachedOutputs(params.InputIDs) + defer cachedInputs.Release() + if params.Inputs = NewOutputs(cachedInputs.Unwrap(true)...); params.Inputs.Size() != len(cachedInputs) { + return errors.Errorf("not all outputs of %s available: %w", params.Transaction.ID(), ErrTransactionUnsolid) + } + + return next(params) } func (v *Validator) checkOutputsCausallyRelatedCommand(params *dataFlowParams, next dataflow.Next[*dataFlowParams]) (err error) { @@ -35,6 +53,21 @@ func (v *Validator) checkOutputsCausallyRelatedCommand(params *dataFlowParams, n return next(params) } +func (v *Validator) checkTransactionExecutionCommand(params *dataFlowParams, next dataflow.Next[*dataFlowParams]) (err error) { + utxoOutputs, err := v.vm.ExecuteTransaction(params.Transaction.Transaction, params.Inputs.UTXOOutputs()) + if err != nil { + return errors.Errorf("failed to execute transaction with %s: %w", params.Transaction.ID(), ErrTransactionInvalid) + } + + params.Outputs = NewOutputs(generics.Map(utxoOutputs, NewOutput)...) + + return next(params) +} + +func (v *Validator) resolveInputs(inputs []utxo.Input) (outputIDs utxo.OutputIDs) { + return utxo.NewOutputIDs(generics.Map(inputs, v.vm.ResolveInput)...) +} + func (v *Validator) outputsCausallyRelated(outputsMetadata OutputsMetadata) (related bool) { spentOutputIDs := outputsMetadata.Filter((*OutputMetadata).Spent).IDs() if spentOutputIDs.Size() == 0 { diff --git a/packages/refactored/ledger/vm.go b/packages/refactored/ledger/vm.go deleted file mode 100644 index 847e9fca00..0000000000 --- a/packages/refactored/ledger/vm.go +++ /dev/null @@ -1,37 +0,0 @@ -package ledger - -import ( - "github.com/cockroachdb/errors" - "github.com/iotaledger/hive.go/generics/dataflow" - - "github.com/iotaledger/goshimmer/packages/refactored/generics" - "github.com/iotaledger/goshimmer/packages/refactored/utxo" -) - -type VM struct { - *Ledger - - vm utxo.VM -} - -func NewVM(ledger *Ledger, vm utxo.VM) (new *VM) { - return &VM{ - Ledger: ledger, - vm: vm, - } -} - -func (v *VM) executeTransactionCommand(params *dataFlowParams, next dataflow.Next[*dataFlowParams]) (err error) { - utxoOutputs, err := v.vm.ExecuteTransaction(params.Transaction.Transaction, params.Inputs.UTXOOutputs()) - if err != nil { - return errors.Errorf("failed to execute transaction with %s: %w", params.Transaction.ID(), ErrTransactionInvalid) - } - - params.Outputs = NewOutputs(generics.Map(utxoOutputs, NewOutput)...) - - return next(params) -} - -func (v *VM) resolveInputs(inputs []Input) (outputIDs OutputIDs) { - return NewOutputIDs(generics.Map(inputs, v.vm.ResolveInput)...) -}