From ee6fae76c095fda8135bbfff7244aaba1236c944 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 20 Mar 2024 20:52:56 +0800 Subject: [PATCH 1/6] Hook to OnTransactionAttached in submitBlockAndAwaitEvent --- pkg/requesthandler/blockissuance.go | 39 +++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/pkg/requesthandler/blockissuance.go b/pkg/requesthandler/blockissuance.go index c7b65aa76..d7e2d97b9 100644 --- a/pkg/requesthandler/blockissuance.go +++ b/pkg/requesthandler/blockissuance.go @@ -11,6 +11,7 @@ import ( "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" "github.com/iotaledger/iota-core/pkg/protocol/engine/filter/postsolidfilter" "github.com/iotaledger/iota-core/pkg/protocol/engine/filter/presolidfilter" + "github.com/iotaledger/iota-core/pkg/protocol/engine/mempool" iotago "github.com/iotaledger/iota.go/v4" ) @@ -36,15 +37,33 @@ func (r *RequestHandler) submitBlockAndAwaitEvent(ctx context.Context, block *mo defer processingCtxCancel() // Calculate the blockID so that we don't capture the block pointer in the event handlers. blockID := block.ID() - evtUnhook := evt.Hook(func(eventBlock *blocks.Block) { - if blockID != eventBlock.ID() { - return - } - select { - case filtered <- nil: - case <-exit: - } - }, event.WithWorkerPool(r.workerPool)).Unhook + + var successUnhook func() + // Hook to TransactionAttached event if the block contains a transaction. + signedTx, isTx := block.SignedTransaction() + if isTx { + txID := signedTx.Transaction.MustID() + successUnhook = r.protocol.Engines.Main.Get().Ledger.MemPool().OnTransactionAttached(func(transactionMetadata mempool.TransactionMetadata) { + if transactionMetadata.ID() != txID { + return + } + select { + case filtered <- nil: + case <-exit: + } + }, event.WithWorkerPool(r.workerPool)).Unhook + } else { + successUnhook = evt.Hook(func(eventBlock *blocks.Block) { + if blockID != eventBlock.ID() { + return + } + select { + case filtered <- nil: + case <-exit: + } + }, event.WithWorkerPool(r.workerPool)).Unhook + } + prefilteredUnhook := r.protocol.Events.Engine.PreSolidFilter.BlockPreFiltered.Hook(func(event *presolidfilter.BlockPreFilteredEvent) { if blockID != event.Block.ID() { return @@ -65,7 +84,7 @@ func (r *RequestHandler) submitBlockAndAwaitEvent(ctx context.Context, block *mo } }, event.WithWorkerPool(r.workerPool)).Unhook - defer lo.BatchReverse(evtUnhook, prefilteredUnhook, postfilteredUnhook)() + defer lo.BatchReverse(successUnhook, prefilteredUnhook, postfilteredUnhook)() if err := r.submitBlock(block); err != nil { return ierrors.Wrapf(err, "failed to issue block %s", blockID) From 240536c2d5012bd1339b63b77ac30ad0425273eb Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 20 Mar 2024 21:35:42 +0800 Subject: [PATCH 2/6] Check transaction metadata with core API in AssertTransactionMetadataByTransactionID --- tools/docker-network/tests/eventapiframework.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/docker-network/tests/eventapiframework.go b/tools/docker-network/tests/eventapiframework.go index 2886d8dfa..b05b70502 100644 --- a/tools/docker-network/tests/eventapiframework.go +++ b/tools/docker-network/tests/eventapiframework.go @@ -284,7 +284,13 @@ func (e *EventAPIDockerTestFramework) AssertTransactionMetadataByTransactionID(c select { case metadata := <-acceptedChan: if txID.Compare(metadata.TransactionID) == 0 { + // make sure the transaction state is available from the core API + resp, err := eventClt.Client.TransactionMetadata(ctx, txID) + require.NoError(e.Testing, err) + require.NotNil(e.Testing, resp) + e.finishChan <- struct{}{} + return } From a4ac821f9ddf92019e036a2a343855be4d05bec9 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Thu, 21 Mar 2024 17:40:59 +0800 Subject: [PATCH 3/6] Remove await event in submitBlock and wait for retainer instead --- components/inx/server_blocks.go | 2 +- components/restapi/core/blocks.go | 2 +- pkg/requesthandler/blockissuance.go | 10 +++++----- pkg/testsuite/mock/client.go | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/inx/server_blocks.go b/components/inx/server_blocks.go index 81315beb7..1471e29df 100644 --- a/components/inx/server_blocks.go +++ b/components/inx/server_blocks.go @@ -186,7 +186,7 @@ func (s *Server) attachBlock(ctx context.Context, block *iotago.Block) (*inx.Blo mergedCtx, mergedCtxCancel := contextutils.MergeContexts(ctx, Component.Daemon().ContextStopped()) defer mergedCtxCancel() - blockID, err := deps.RequestHandler.SubmitBlockAndAwaitBooking(mergedCtx, block) + blockID, err := deps.RequestHandler.SubmitBlockAndAwaitRetainer(mergedCtx, block) if err != nil { return nil, status.Errorf(codes.Internal, "failed to attach block: %s", err.Error()) } diff --git a/components/restapi/core/blocks.go b/components/restapi/core/blocks.go index d91d965b5..4eb3d93a8 100644 --- a/components/restapi/core/blocks.go +++ b/components/restapi/core/blocks.go @@ -42,7 +42,7 @@ func sendBlock(c echo.Context) (*api.BlockCreatedResponse, error) { return nil, err } - blockID, err := deps.RequestHandler.SubmitBlockAndAwaitBooking(c.Request().Context(), iotaBlock) + blockID, err := deps.RequestHandler.SubmitBlockAndAwaitRetainer(c.Request().Context(), iotaBlock) if err != nil { return nil, ierrors.WithMessagef(echo.ErrInternalServerError, "failed to attach block: %w", err) } diff --git a/pkg/requesthandler/blockissuance.go b/pkg/requesthandler/blockissuance.go index d7e2d97b9..5b00db456 100644 --- a/pkg/requesthandler/blockissuance.go +++ b/pkg/requesthandler/blockissuance.go @@ -25,8 +25,8 @@ func (r *RequestHandler) SubmitBlockWithoutAwaitingBooking(block *model.Block) e return r.submitBlock(block) } -// submitBlockAndAwaitEvent submits a block to be processed and waits for the event to be triggered. -func (r *RequestHandler) submitBlockAndAwaitEvent(ctx context.Context, block *model.Block, evt *event.Event1[*blocks.Block]) error { +// submitBlockAndAwaitRetainer submits a block to be processed and waits for the block gets retained. +func (r *RequestHandler) submitBlockAndAwaitRetainer(ctx context.Context, block *model.Block) error { filtered := make(chan error, 1) exit := make(chan struct{}) defer close(exit) @@ -53,7 +53,7 @@ func (r *RequestHandler) submitBlockAndAwaitEvent(ctx context.Context, block *mo } }, event.WithWorkerPool(r.workerPool)).Unhook } else { - successUnhook = evt.Hook(func(eventBlock *blocks.Block) { + successUnhook = r.protocol.Events.Engine.Retainer.BlockRetained.Hook(func(eventBlock *blocks.Block) { if blockID != eventBlock.ID() { return } @@ -101,13 +101,13 @@ func (r *RequestHandler) submitBlockAndAwaitEvent(ctx context.Context, block *mo } } -func (r *RequestHandler) SubmitBlockAndAwaitBooking(ctx context.Context, iotaBlock *iotago.Block) (iotago.BlockID, error) { +func (r *RequestHandler) SubmitBlockAndAwaitRetainer(ctx context.Context, iotaBlock *iotago.Block) (iotago.BlockID, error) { modelBlock, err := model.BlockFromBlock(iotaBlock) if err != nil { return iotago.EmptyBlockID, ierrors.Wrap(err, "error serializing block to model block") } - if err = r.submitBlockAndAwaitEvent(ctx, modelBlock, r.protocol.Events.Engine.Retainer.BlockRetained); err != nil { + if err = r.submitBlockAndAwaitRetainer(ctx, modelBlock); err != nil { return iotago.EmptyBlockID, ierrors.Wrap(err, "error issuing model block") } diff --git a/pkg/testsuite/mock/client.go b/pkg/testsuite/mock/client.go index 96416ad41..e6f533459 100644 --- a/pkg/testsuite/mock/client.go +++ b/pkg/testsuite/mock/client.go @@ -241,7 +241,7 @@ func (c *TestSuiteClient) Routes(_ context.Context) (*api.RoutesResponse, error) } func (c *TestSuiteClient) SubmitBlock(ctx context.Context, block *iotago.Block) (iotago.BlockID, error) { - return c.Node.RequestHandler.SubmitBlockAndAwaitBooking(ctx, block) + return c.Node.RequestHandler.SubmitBlockAndAwaitRetainer(ctx, block) } func (c *TestSuiteClient) TransactionIncludedBlock(_ context.Context, txID iotago.TransactionID) (*iotago.Block, error) { From 4993dc025206a43f43750c1d54c3923a9ab46dde Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Thu, 21 Mar 2024 20:07:47 +0800 Subject: [PATCH 4/6] Hook to OnTransactionAttached only if the tx is not in the retainer --- pkg/requesthandler/blockissuance.go | 32 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/pkg/requesthandler/blockissuance.go b/pkg/requesthandler/blockissuance.go index 5b00db456..0cbb54292 100644 --- a/pkg/requesthandler/blockissuance.go +++ b/pkg/requesthandler/blockissuance.go @@ -12,6 +12,7 @@ import ( "github.com/iotaledger/iota-core/pkg/protocol/engine/filter/postsolidfilter" "github.com/iotaledger/iota-core/pkg/protocol/engine/filter/presolidfilter" "github.com/iotaledger/iota-core/pkg/protocol/engine/mempool" + "github.com/iotaledger/iota-core/pkg/retainer/txretainer" iotago "github.com/iotaledger/iota.go/v4" ) @@ -33,7 +34,7 @@ func (r *RequestHandler) submitBlockAndAwaitRetainer(ctx context.Context, block // Make sure we don't wait forever here. If the block is not dispatched to the main engine, // it will never trigger one of the below events. - processingCtx, processingCtxCancel := context.WithTimeout(ctx, 5*time.Second) + processingCtx, processingCtxCancel := context.WithTimeout(ctx, 10*time.Second) defer processingCtxCancel() // Calculate the blockID so that we don't capture the block pointer in the event handlers. blockID := block.ID() @@ -43,16 +44,25 @@ func (r *RequestHandler) submitBlockAndAwaitRetainer(ctx context.Context, block signedTx, isTx := block.SignedTransaction() if isTx { txID := signedTx.Transaction.MustID() - successUnhook = r.protocol.Engines.Main.Get().Ledger.MemPool().OnTransactionAttached(func(transactionMetadata mempool.TransactionMetadata) { - if transactionMetadata.ID() != txID { - return - } - select { - case filtered <- nil: - case <-exit: - } - }, event.WithWorkerPool(r.workerPool)).Unhook - } else { + // Check if the transaction is already retained. The onTransactionAttached event is only triggered if it's a new transaction. + // If the transaction is already retained, we hook to the BlockRetained event. + _, err := r.protocol.Engines.Main.Get().TxRetainer.TransactionMetadata(txID) + if ierrors.Is(err, txretainer.ErrEntryNotFound) { + // SignedTransactionAttached is triggered for new transactions and for reattachment. + successUnhook = r.protocol.Engines.Main.Get().Ledger.MemPool().OnTransactionAttached(func(transactionMetadata mempool.TransactionMetadata) { + if transactionMetadata.ID() != txID { + return + } + select { + case filtered <- nil: + case <-exit: + } + }, event.WithWorkerPool(r.workerPool)).Unhook + } + } + + // if no hook was set, hook to the block retained event. + if successUnhook == nil { successUnhook = r.protocol.Events.Engine.Retainer.BlockRetained.Hook(func(eventBlock *blocks.Block) { if blockID != eventBlock.ID() { return From a2f777b1fa3b5531f8f406aae54ff91a0d1f5eb5 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Thu, 21 Mar 2024 20:31:26 +0800 Subject: [PATCH 5/6] Add TransactionRetained event in TransactionRetainer --- components/debugapi/component.go | 2 +- pkg/protocol/chains.go | 6 +++- pkg/protocol/engine/events.go | 38 ++++++++++---------- pkg/requesthandler/blockissuance.go | 8 ++--- pkg/retainer/blockretainer/block_retainer.go | 6 ++-- pkg/retainer/events.go | 28 +++++++++++---- pkg/retainer/txretainer/tx_retainer.go | 8 +++++ 7 files changed, 62 insertions(+), 34 deletions(-) diff --git a/components/debugapi/component.go b/components/debugapi/component.go index 23d861959..fdceedb34 100644 --- a/components/debugapi/component.go +++ b/components/debugapi/component.go @@ -86,7 +86,7 @@ func configure() error { debugAPIWorkerPool := workerpool.NewGroup("DebugAPI").CreatePool("DebugAPI", workerpool.WithWorkerCount(1)) - deps.Protocol.Events.Engine.Retainer.BlockRetained.Hook(func(block *blocks.Block) { + deps.Protocol.Events.Engine.BlockRetainer.BlockRetained.Hook(func(block *blocks.Block) { blocksPerSlot.Set(block.ID().Slot(), append(lo.Return1(blocksPerSlot.GetOrCreate(block.ID().Slot(), func() []*blocks.Block { return make([]*blocks.Block, 0) })), block)) diff --git a/pkg/protocol/chains.go b/pkg/protocol/chains.go index 9430d7e20..e6cdabec4 100644 --- a/pkg/protocol/chains.go +++ b/pkg/protocol/chains.go @@ -176,10 +176,14 @@ func attachEngineLogs(instance *engine.Engine) func() { instance.LogTrace("BlockProcessed", "block", blockID) }).Unhook, - events.Retainer.BlockRetained.Hook(func(block *blocks.Block) { + events.BlockRetainer.BlockRetained.Hook(func(block *blocks.Block) { instance.LogTrace("Retainer.BlockRetained", "block", block.ID()) }).Unhook, + events.TransactionRetainer.TransactionRetained.Hook(func(txID iotago.TransactionID) { + instance.LogTrace("Retainer.TransactionRetained", "transaction", txID) + }).Unhook, + events.Notarization.SlotCommitted.Hook(func(details *notarization.SlotCommittedDetails) { instance.LogTrace("NotarizationManager.SlotCommitted", "commitment", details.Commitment.ID(), "acceptedBlocks count", details.AcceptedBlocks.Size(), "accepted transactions", len(details.Mutations)) }).Unhook, diff --git a/pkg/protocol/engine/events.go b/pkg/protocol/engine/events.go index 7d302d877..805f6be9c 100644 --- a/pkg/protocol/engine/events.go +++ b/pkg/protocol/engine/events.go @@ -29,23 +29,24 @@ type Events struct { AcceptedBlockProcessed *event.Event1[*blocks.Block] Evict *event.Event1[iotago.SlotIndex] - PreSolidFilter *presolidfilter.Events - PostSolidFilter *postsolidfilter.Events - BlockRequester *eventticker.Events[iotago.SlotIndex, iotago.BlockID] - TipManager *tipmanager.Events - BlockDAG *blockdag.Events - Booker *booker.Events - Clock *clock.Events - BlockGadget *blockgadget.Events - SlotGadget *slotgadget.Events - SybilProtection *sybilprotection.Events - Ledger *ledger.Events - Notarization *notarization.Events - SpendDAG *spenddag.Events[iotago.TransactionID, mempool.StateID] - Scheduler *scheduler.Events - SeatManager *seatmanager.Events - SyncManager *syncmanager.Events - Retainer *retainer.Events + PreSolidFilter *presolidfilter.Events + PostSolidFilter *postsolidfilter.Events + BlockRequester *eventticker.Events[iotago.SlotIndex, iotago.BlockID] + TipManager *tipmanager.Events + BlockDAG *blockdag.Events + Booker *booker.Events + Clock *clock.Events + BlockGadget *blockgadget.Events + SlotGadget *slotgadget.Events + SybilProtection *sybilprotection.Events + Ledger *ledger.Events + Notarization *notarization.Events + SpendDAG *spenddag.Events[iotago.TransactionID, mempool.StateID] + Scheduler *scheduler.Events + SeatManager *seatmanager.Events + SyncManager *syncmanager.Events + BlockRetainer *retainer.BlockRetainerEvents + TransactionRetainer *retainer.TransactionRetainerEvents event.Group[Events, *Events] } @@ -71,6 +72,7 @@ var NewEvents = event.CreateGroupConstructor(func() (newEvents *Events) { Scheduler: scheduler.NewEvents(), SeatManager: seatmanager.NewEvents(), SyncManager: syncmanager.NewEvents(), - Retainer: retainer.NewEvents(), + BlockRetainer: retainer.NewBlockRetainerEvents(), + TransactionRetainer: retainer.NewTransactionRetainerEvents(), } }) diff --git a/pkg/requesthandler/blockissuance.go b/pkg/requesthandler/blockissuance.go index 0cbb54292..4bb949bd4 100644 --- a/pkg/requesthandler/blockissuance.go +++ b/pkg/requesthandler/blockissuance.go @@ -11,7 +11,6 @@ import ( "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" "github.com/iotaledger/iota-core/pkg/protocol/engine/filter/postsolidfilter" "github.com/iotaledger/iota-core/pkg/protocol/engine/filter/presolidfilter" - "github.com/iotaledger/iota-core/pkg/protocol/engine/mempool" "github.com/iotaledger/iota-core/pkg/retainer/txretainer" iotago "github.com/iotaledger/iota.go/v4" ) @@ -48,9 +47,8 @@ func (r *RequestHandler) submitBlockAndAwaitRetainer(ctx context.Context, block // If the transaction is already retained, we hook to the BlockRetained event. _, err := r.protocol.Engines.Main.Get().TxRetainer.TransactionMetadata(txID) if ierrors.Is(err, txretainer.ErrEntryNotFound) { - // SignedTransactionAttached is triggered for new transactions and for reattachment. - successUnhook = r.protocol.Engines.Main.Get().Ledger.MemPool().OnTransactionAttached(func(transactionMetadata mempool.TransactionMetadata) { - if transactionMetadata.ID() != txID { + successUnhook = r.protocol.Events.Engine.TransactionRetainer.TransactionRetained.Hook(func(transactionID iotago.TransactionID) { + if transactionID != txID { return } select { @@ -63,7 +61,7 @@ func (r *RequestHandler) submitBlockAndAwaitRetainer(ctx context.Context, block // if no hook was set, hook to the block retained event. if successUnhook == nil { - successUnhook = r.protocol.Events.Engine.Retainer.BlockRetained.Hook(func(eventBlock *blocks.Block) { + successUnhook = r.protocol.Events.Engine.BlockRetainer.BlockRetained.Hook(func(eventBlock *blocks.Block) { if blockID != eventBlock.ID() { return } diff --git a/pkg/retainer/blockretainer/block_retainer.go b/pkg/retainer/blockretainer/block_retainer.go index 5f648e320..5e75cbf5d 100644 --- a/pkg/retainer/blockretainer/block_retainer.go +++ b/pkg/retainer/blockretainer/block_retainer.go @@ -23,7 +23,7 @@ type ( ) type BlockRetainer struct { - events *retainer.Events + events *retainer.BlockRetainerEvents store StoreFunc cache *cache @@ -39,7 +39,7 @@ type BlockRetainer struct { func New(module module.Module, workersGroup *workerpool.Group, retainerStoreFunc StoreFunc, finalizedSlotFunc FinalizedSlotFunc, errorHandler func(error)) *BlockRetainer { b := &BlockRetainer{ Module: module, - events: retainer.NewEvents(), + events: retainer.NewBlockRetainerEvents(), workerPool: workersGroup.CreatePool("Retainer", workerpool.WithWorkerCount(1)), store: retainerStoreFunc, cache: newCache(), @@ -99,7 +99,7 @@ func NewProvider() module.Provider[*engine.Engine, retainer.BlockRetainer] { } }, asyncOpt) - e.Events.Retainer.BlockRetained.LinkTo(r.events.BlockRetained) + e.Events.BlockRetainer.BlockRetained.LinkTo(r.events.BlockRetained) r.InitializedEvent().Trigger() diff --git a/pkg/retainer/events.go b/pkg/retainer/events.go index 52dff40f5..0147f9d76 100644 --- a/pkg/retainer/events.go +++ b/pkg/retainer/events.go @@ -3,19 +3,35 @@ package retainer import ( "github.com/iotaledger/hive.go/runtime/event" "github.com/iotaledger/iota-core/pkg/protocol/engine/blocks" + iotago "github.com/iotaledger/iota.go/v4" ) -// Events is a collection of Retainer related Events. -type Events struct { +// BlockRetainerEvents is a collection of Retainer related BlockRetainerEvents. +type BlockRetainerEvents struct { // BlockRetained is triggered when a block is stored in the retainer. BlockRetained *event.Event1[*blocks.Block] - event.Group[Events, *Events] + event.Group[BlockRetainerEvents, *BlockRetainerEvents] } -// NewEvents contains the constructor of the Events object (it is generated by a generic factory). -var NewEvents = event.CreateGroupConstructor(func() (newEvents *Events) { - return &Events{ +// NewBlockRetainerEvents contains the constructor of the Events object (it is generated by a generic factory). +var NewBlockRetainerEvents = event.CreateGroupConstructor(func() (newEvents *BlockRetainerEvents) { + return &BlockRetainerEvents{ BlockRetained: event.New1[*blocks.Block](), } }) + +// TransactionRetainerEvents is a collection of Retainer related TransactionRetainerEvents. +type TransactionRetainerEvents struct { + // TransactionRetained is triggered when a transaction is stored in the retainer. + TransactionRetained *event.Event1[iotago.TransactionID] + + event.Group[TransactionRetainerEvents, *TransactionRetainerEvents] +} + +// NewTransactionRetainerEvents contains the constructor of the Events object (it is generated by a generic factory). +var NewTransactionRetainerEvents = event.CreateGroupConstructor(func() (newEvents *TransactionRetainerEvents) { + return &TransactionRetainerEvents{ + TransactionRetained: event.New1[iotago.TransactionID](), + } +}) diff --git a/pkg/retainer/txretainer/tx_retainer.go b/pkg/retainer/txretainer/tx_retainer.go index 0be555a88..d6dbb7999 100644 --- a/pkg/retainer/txretainer/tx_retainer.go +++ b/pkg/retainer/txretainer/tx_retainer.go @@ -90,6 +90,7 @@ type ( // TransactionRetainer keeps and resolves all the transaction-related metadata needed in the API and INX. type TransactionRetainer struct { + events *retainer.TransactionRetainerEvents workerPool *workerpool.WorkerPool txRetainerDatabase *transactionRetainerDatabase latestCommittedSlotFunc SlotFunc @@ -113,6 +114,7 @@ func WithDebugStoreErrorMessages(store bool) options.Option[TransactionRetainer] func New(parentModule module.Module, workersGroup *workerpool.Group, dbExecFunc storage.SQLDatabaseExecFunc, latestCommittedSlotFunc SlotFunc, finalizedSlotFunc SlotFunc, errorHandler func(error), opts ...options.Option[TransactionRetainer]) *TransactionRetainer { return module.InitSimpleLifecycle(options.Apply(&TransactionRetainer{ Module: parentModule.NewSubModule("TransactionRetainer"), + events: retainer.NewTransactionRetainerEvents(), workerPool: workersGroup.CreatePool("TxRetainer", workerpool.WithWorkerCount(1)), txRetainerCache: NewTransactionRetainerCache(), txRetainerDatabase: NewTransactionRetainerDB(dbExecFunc), @@ -158,6 +160,8 @@ func NewProvider(opts ...options.Option[TransactionRetainer]) module.Provider[*e // therefore we use false for the "validSignature" argument. r.UpdateTransactionMetadata(transactionMetadata.ID(), false, transactionMetadata.EarliestIncludedAttachment().Slot(), api.TransactionStatePending, nil) + r.events.TransactionRetained.Trigger(transactionMetadata.ID()) + // the transaction was accepted transactionMetadata.OnAccepted(func() { e.LogTrace("TxRetainer.TransactionAccepted", "tx", transactionMetadata.ID()) @@ -243,6 +247,10 @@ func NewProvider(opts ...options.Option[TransactionRetainer]) module.Provider[*e }, asyncOpt) }) + e.Events.TransactionRetainer.TransactionRetained.LinkTo(r.events.TransactionRetained) + + r.InitializedEvent().Trigger() + return r }) } From c307b3c505a6eba6fc37714e1255b5b18f5bdbd3 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Fri, 22 Mar 2024 15:04:52 +0800 Subject: [PATCH 6/6] Fix Test_Account_StakeAmountCalculation --- pkg/tests/reward_test.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/tests/reward_test.go b/pkg/tests/reward_test.go index a82fa3736..37ed42c3c 100644 --- a/pkg/tests/reward_test.go +++ b/pkg/tests/reward_test.go @@ -373,10 +373,13 @@ func Test_Account_StakeAmountCalculation(t *testing.T) { ) block7 := lo.PanicOnErr(ts.IssueBasicBlockWithOptions("block7", ts.DefaultWallet(), tx7, mock.WithStrongParents(latestParents...))) + latestParents = ts.CommitUntilSlot(block7_8Slot, block7.ID()) + tx8 := ts.DefaultWallet().ClaimDelegatorRewards("TX8", "TX7:0") - block8 := lo.PanicOnErr(ts.IssueBasicBlockWithOptions("block8", ts.DefaultWallet(), tx8, mock.WithStrongParents(block7.ID()))) + block8 := lo.PanicOnErr(ts.IssueBasicBlockWithOptions("block8", ts.DefaultWallet(), tx8, mock.WithStrongParents(latestParents...))) - latestParents = ts.CommitUntilSlot(block7_8Slot, block8.ID()) + block8Slot := ts.CurrentSlot() + latestParents = ts.CommitUntilSlot(block8Slot, block8.ID()) // Delegated Stake should be unaffected since no new delegation was effectively added in that slot. ts.AssertAccountStake(accountID, stakedAmount, deleg1+deleg2, ts.Nodes()...)