Skip to content

Commit d0be2e3

Browse files
authored
Merge branch 'feat/supernova-async-exec' into fix-referenced-gaps
2 parents 2baac51 + de11a01 commit d0be2e3

File tree

8 files changed

+90
-10
lines changed

8 files changed

+90
-10
lines changed

cmd/node/config/external.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
Password = ""
1414
# EnabledIndexes represents a slice of indexes that will be enabled for indexing. Full list is:
1515
# ["rating", "transactions", "blocks", "validators", "miniblocks", "rounds", "accounts", "accountshistory", "receipts", "scresults", "accountsesdt", "accountsesdthistory", "epochinfo", "scdeploys", "tokens", "tags", "logs", "delegators", "operations", "esdts", "events"]
16-
EnabledIndexes = ["rating", "transactions", "blocks", "validators", "miniblocks", "rounds", "accounts", "accountshistory", "receipts", "scresults", "accountsesdt", "accountsesdthistory", "epochinfo", "scdeploys", "tokens", "tags", "logs", "delegators", "operations", "esdts", "events"]
16+
EnabledIndexes = ["rating", "transactions", "blocks", "validators", "miniblocks", "rounds", "accounts", "accountshistory", "receipts", "scresults", "accountsesdt", "accountsesdthistory", "epochinfo", "scdeploys", "tokens", "tags", "logs", "delegators", "operations", "esdts", "events", "executionresults"]
1717

1818
# EventNotifierConnector defines settings needed to configure and launch the event notifier component
1919
# HTTP event notifier connector integration will be DEPRECATED in the following iterations

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ require (
1919
github.com/multiversx/mx-chain-communication-go v1.3.0
2020
github.com/multiversx/mx-chain-core-go v1.4.2-0.20251216155248-bcbea61e6f31
2121
github.com/multiversx/mx-chain-crypto-go v1.3.0
22-
github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251209110302-3b451942b7f9
22+
github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20260112102658-97d6a0ceb5f6
2323
github.com/multiversx/mx-chain-logger-go v1.1.0
2424
github.com/multiversx/mx-chain-scenario-go v1.6.0
2525
github.com/multiversx/mx-chain-storage-go v1.1.0

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,8 @@ github.com/multiversx/mx-chain-core-go v1.4.2-0.20251216155248-bcbea61e6f31 h1:M
405405
github.com/multiversx/mx-chain-core-go v1.4.2-0.20251216155248-bcbea61e6f31/go.mod h1:IO+vspNan+gT0WOHnJ95uvWygiziHZvfXpff6KnxV7g=
406406
github.com/multiversx/mx-chain-crypto-go v1.3.0 h1:0eK2bkDOMi8VbSPrB1/vGJSYT81IBtfL4zw+C4sWe/k=
407407
github.com/multiversx/mx-chain-crypto-go v1.3.0/go.mod h1:nPIkxxzyTP8IquWKds+22Q2OJ9W7LtusC7cAosz7ojM=
408-
github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251209110302-3b451942b7f9 h1:lywsKESTxcEC+RnmXzF/6T444DVyhl/ft52Rh4JMPyQ=
409-
github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20251209110302-3b451942b7f9/go.mod h1:F/BpaYVPuHN7POJN6gwvJfZ22diYtvz2576a+PWiPvw=
408+
github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20260112102658-97d6a0ceb5f6 h1:ywYAthnCkytgSGfMBTBvojlBJh9o5zUmottZwaVYTd8=
409+
github.com/multiversx/mx-chain-es-indexer-go v1.9.3-0.20260112102658-97d6a0ceb5f6/go.mod h1:F/BpaYVPuHN7POJN6gwvJfZ22diYtvz2576a+PWiPvw=
410410
github.com/multiversx/mx-chain-logger-go v1.1.0 h1:97x84A6L4RfCa6YOx1HpAFxZp1cf/WI0Qh112whgZNM=
411411
github.com/multiversx/mx-chain-logger-go v1.1.0/go.mod h1:K9XgiohLwOsNACETMNL0LItJMREuEvTH6NsoXWXWg7g=
412412
github.com/multiversx/mx-chain-scenario-go v1.6.0 h1:cwDFuS1pSc4YXnfiKKDTEb+QDY4fulPQaiRgIebnKxI=

node/chainSimulator/components/coreComponents.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ func CreateCoreComponents(args ArgsCoreComponentsHolder) (*coreComponentsHolder,
243243
RoundDuration: roundDuration,
244244
SupernovaRoundDuration: time.Duration(chainParamsForSupernova.RoundDuration) * time.Millisecond,
245245
InitialRound: args.InitialRound,
246+
SupernovaStartRound: int64(supernovaRound),
246247
}
247248
instance.roundHandler, err = NewManualRoundHandler(argsManualRoundHandler)
248249
if err != nil {

node/chainSimulator/components/manualRoundHandler.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ type ArgManualRoundHandler struct {
1919
RoundDuration time.Duration
2020
SupernovaRoundDuration time.Duration
2121
InitialRound int64
22+
SupernovaStartRound int64
2223
}
2324

2425
type manualRoundHandler struct {
@@ -29,6 +30,7 @@ type manualRoundHandler struct {
2930
supernovaRoundDuration time.Duration
3031
initialRound int64
3132
enableRoundsHandler common.EnableRoundsHandler
33+
supernovaStartRound int64
3234
}
3335

3436
// NewManualRoundHandler returns a manual round handler instance
@@ -44,6 +46,7 @@ func NewManualRoundHandler(args ArgManualRoundHandler) (*manualRoundHandler, err
4446
enableRoundsHandler: args.EnableRoundsHandler,
4547
supernovaGenesisTimeStamp: args.SupernovaGenesisTimeStamp,
4648
supernovaRoundDuration: args.SupernovaRoundDuration,
49+
supernovaStartRound: args.SupernovaStartRound,
4750
}, nil
4851
}
4952

@@ -109,9 +112,16 @@ func (handler *manualRoundHandler) RemainingTime(_ time.Time, maxTime time.Durat
109112

110113
// GetTimeStampForRound returns the timestamp for round
111114
func (handler *manualRoundHandler) GetTimeStampForRound(round uint64) uint64 {
112-
timeFromGenesis := handler.roundDuration * time.Duration(round)
113-
timestamp := time.Unix(handler.genesisTimeStamp, 0).Add(timeFromGenesis)
114-
return uint64(timestamp.UnixMilli())
115+
if int64(round) <= handler.supernovaStartRound {
116+
genesisTimestamp := time.UnixMilli(handler.genesisTimeStamp)
117+
roundTimeStampMs := genesisTimestamp.Add(time.Duration(int64(round)-handler.initialRound) * handler.roundDuration).UnixMilli()
118+
return uint64(roundTimeStampMs)
119+
}
120+
121+
genesisTimestamp := time.UnixMilli(handler.supernovaGenesisTimeStamp)
122+
roundTimeStampMs := genesisTimestamp.Add(time.Duration(int64(round)-handler.supernovaStartRound) * handler.supernovaRoundDuration).UnixMilli()
123+
return uint64(roundTimeStampMs)
124+
115125
}
116126

117127
// IsInterfaceNil returns true if there is no value under the interface

node/chainSimulator/components/manualRoundHandler_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,3 +94,25 @@ func TestManualRoundHandler_Operations(t *testing.T) {
9494
require.Equal(t, args.SupernovaGenesisTimeStamp, handler.TimeStamp().UnixMilli())
9595
require.Equal(t, args.SupernovaRoundDuration.Milliseconds(), handler.TimeDuration().Milliseconds())
9696
}
97+
98+
func TestManualRoundHandler_GetTimeStampForRound(t *testing.T) {
99+
t.Parallel()
100+
101+
arg := ArgManualRoundHandler{
102+
EnableRoundsHandler: &testscommon.EnableRoundsHandlerStub{},
103+
GenesisTimeStamp: 1000,
104+
SupernovaGenesisTimeStamp: 1500,
105+
RoundDuration: time.Second,
106+
SupernovaRoundDuration: time.Millisecond * 500,
107+
InitialRound: 0,
108+
SupernovaStartRound: 100,
109+
}
110+
handler, err := NewManualRoundHandler(arg)
111+
require.NoError(t, err)
112+
113+
res := handler.GetTimeStampForRound(10)
114+
require.Equal(t, uint64(11000), res)
115+
116+
res = handler.GetTimeStampForRound(120)
117+
require.Equal(t, uint64(11500), res)
118+
}

node/external/transactionAPI/apiTransactionProcessor.go

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,23 @@ func (atp *apiTransactionProcessor) GetTransaction(txHash string, withResults bo
177177
}
178178

179179
func (atp *apiTransactionProcessor) doGetTransaction(hash []byte, withResults bool) (*transaction.ApiTransactionResult, error) {
180-
tx := atp.optionallyGetTransactionFromPool(hash)
181-
if tx != nil {
182-
return tx, nil
180+
txFromPool := atp.optionallyGetTransactionFromPool(hash)
181+
if txFromPool != nil {
182+
// we don't return immediately because storage/history takes priority if it succeeds
183+
txFromStorage, err := atp.fetchFromStorageOrHistory(hash, withResults)
184+
if err == nil {
185+
return txFromStorage, nil
186+
}
187+
188+
// storage/history failed, but pool has it
189+
return txFromPool, nil
183190
}
184191

192+
// no pool entry — just return storage/history result
193+
return atp.fetchFromStorageOrHistory(hash, withResults)
194+
}
195+
196+
func (atp *apiTransactionProcessor) fetchFromStorageOrHistory(hash []byte, withResults bool) (*transaction.ApiTransactionResult, error) {
185197
if atp.historyRepository.IsEnabled() {
186198
return atp.lookupHistoricalTransaction(hash, withResults)
187199
}
@@ -736,12 +748,33 @@ func (atp *apiTransactionProcessor) computeTimestampForRoundAsMs(round uint64) i
736748
return timestamp.UnixMilli()
737749
}
738750

751+
func (atp *apiTransactionProcessor) checkExecutionResult(miniblockMetadata *dblookupext.MiniblockMetadata) error {
752+
isSupernovaEnabled := atp.enableRoundsHandler.IsFlagEnabledInRound(common.SupernovaRoundFlag, miniblockMetadata.Round)
753+
if !isSupernovaEnabled {
754+
return nil
755+
}
756+
757+
headerHash := miniblockMetadata.GetHeaderHash()
758+
executionResultsStorer, errG := atp.storageService.GetStorer(dataRetriever.ExecutionResultsUnit)
759+
if errG != nil {
760+
return errG
761+
}
762+
763+
_, err := executionResultsStorer.GetFromEpoch(headerHash, miniblockMetadata.GetEpoch())
764+
return err
765+
}
766+
739767
func (atp *apiTransactionProcessor) lookupHistoricalTransaction(hash []byte, withResults bool) (*transaction.ApiTransactionResult, error) {
740768
miniblockMetadata, err := atp.historyRepository.GetMiniblockMetadataByTxHash(hash)
741769
if err != nil {
742770
return nil, fmt.Errorf("%s: %w", ErrTransactionNotFound.Error(), err)
743771
}
744772

773+
err = atp.checkExecutionResult(miniblockMetadata)
774+
if err != nil {
775+
return nil, fmt.Errorf("%s: %w", ErrTransactionNotFound.Error(), err)
776+
}
777+
745778
txBytes, txType, found := atp.getTxBytesFromStorageByEpoch(hash, miniblockMetadata.Epoch)
746779
if !found {
747780
log.Warn("lookupHistoricalTransaction(): unexpected condition, cannot find transaction in storage")

node/external/transactionAPI/apiTransactionProcessor_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,20 @@ func TestNode_GetTransactionInvalidHashShouldErr(t *testing.T) {
237237
assert.Error(t, err)
238238
}
239239

240+
func TestNode_GetTransactionFoundInPoolAndStorageShouldReturnFromStorage(t *testing.T) {
241+
n, chainStorer, dataPool, _ := createAPITransactionProc(t, 42, false)
242+
243+
txA := &transaction.Transaction{Nonce: 7, SndAddr: []byte("bob"), RcvAddr: []byte("alice")}
244+
dataPool.Transactions().AddData([]byte("a"), txA, 42, "1")
245+
246+
internalMarshalizer := &mock.MarshalizerFake{}
247+
_ = chainStorer.Transactions.PutWithMarshalizer([]byte("a"), txA, internalMarshalizer)
248+
249+
actualA, err := n.GetTransaction(hex.EncodeToString([]byte("a")), false)
250+
require.Nil(t, err)
251+
require.Equal(t, transaction.TxStatusSuccess, actualA.Status)
252+
}
253+
240254
func TestNode_GetTransactionFromPool(t *testing.T) {
241255
t.Parallel()
242256

0 commit comments

Comments
 (0)