Skip to content

Commit d8aa390

Browse files
authored
Merge branch 'feat/supernova-async-exec' into supernova-bon
2 parents 88ad346 + 85f502b commit d8aa390

27 files changed

Lines changed: 563 additions & 52 deletions

common/common.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ func PrepareOrderedTxHashesKey(headerHash []byte) []byte {
4848
return append([]byte("execution"), headerHash...)
4949
}
5050

51+
// PrepareUnexecutableTxHashesKey will prepare unexecutable transaction hashes key for cacher
52+
func PrepareUnexecutableTxHashesKey(headerHash []byte) []byte {
53+
return append([]byte("unexecutable"), headerHash...)
54+
}
55+
5156
// IsValidRelayedTxV3 returns true if the provided transaction is a valid transaction of type relayed v3
5257
func IsValidRelayedTxV3(tx data.TransactionHandler) bool {
5358
relayedTx, isRelayedV3 := tx.(data.RelayedTransactionHandler)

common/commonCachedData.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,23 @@ func GetCachedOrderedTxHashes(cache storage.Cacher, headerHash []byte) ([][]byte
6363
return cachedDataSlice, nil
6464
}
6565

66+
// GetCachedUnexecutableTxHashes will return the cached unexecutable tx hashes from the provided cache
67+
func GetCachedUnexecutableTxHashes(cache storage.Cacher, headerHash []byte) ([][]byte, error) {
68+
unexecutableTxHashesKey := PrepareUnexecutableTxHashesKey(headerHash)
69+
cachedData, ok := cache.Get(unexecutableTxHashesKey)
70+
if !ok {
71+
log.Warn("unexecutableTxHashes not found in dataPool", "hash", headerHash)
72+
return nil, fmt.Errorf("%w for header %s", ErrMissingUnexecutableTxHash, hex.EncodeToString(headerHash))
73+
}
74+
75+
cachedDataSlice, ok := cachedData.([][]byte)
76+
if !ok {
77+
return nil, fmt.Errorf("%w for cached unexecutable txs %s", ErrWrongTypeAssertion, hex.EncodeToString(headerHash))
78+
}
79+
80+
return cachedDataSlice, nil
81+
}
82+
6683
// GetCachedMbs will return the cached miniblocks from provided cache
6784
func GetCachedMbs(cache storage.Cacher, marshaller marshal.Marshalizer, headerHash []byte) ([]*block.MiniBlock, error) {
6885
cachedIntraMBs, ok := cache.Get(headerHash)

common/commonCachedData_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,41 @@ func TestGetCachedOrderedTxHashes(t *testing.T) {
301301
require.Equal(t, hashes, res)
302302
})
303303
}
304+
305+
func TestGetCachedUnexecutableTxHashes(t *testing.T) {
306+
t.Parallel()
307+
308+
t.Run("cannot find in cache should error", func(t *testing.T) {
309+
t.Parallel()
310+
311+
cacher := cache.NewCacherMock()
312+
313+
headerHash := []byte("h")
314+
315+
_, err := GetCachedUnexecutableTxHashes(cacher, headerHash)
316+
require.True(t, errors.Is(err, ErrMissingUnexecutableTxHash))
317+
})
318+
319+
t.Run("wrong type in cache should error", func(t *testing.T) {
320+
cacher := cache.NewCacherMock()
321+
322+
headerHash := []byte("h")
323+
cacher.Put(PrepareUnexecutableTxHashesKey(headerHash), []byte("a"), 0)
324+
325+
_, err := GetCachedUnexecutableTxHashes(cacher, headerHash)
326+
require.True(t, errors.Is(err, ErrWrongTypeAssertion))
327+
})
328+
329+
t.Run("should work", func(t *testing.T) {
330+
cacher := cache.NewCacherMock()
331+
332+
headerHash := []byte("h")
333+
hashes := [][]byte{[]byte("a"), []byte("b"), []byte("c")}
334+
cacher.Put(PrepareUnexecutableTxHashesKey(headerHash), hashes, 0)
335+
336+
res, err := GetCachedUnexecutableTxHashes(cacher, headerHash)
337+
require.Nil(t, err)
338+
require.Equal(t, hashes, res)
339+
})
340+
341+
}

common/common_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1282,3 +1282,10 @@ func TestGetDeveloperFeesInEpoch(t *testing.T) {
12821282
require.Equal(t, big.NewInt(0), result)
12831283
})
12841284
}
1285+
1286+
func TestPrepareUnexecutableTxHashesKey(t *testing.T) {
1287+
t.Parallel()
1288+
1289+
hash := []byte("hash")
1290+
require.Equal(t, []byte("unexecutablehash"), common.PrepareUnexecutableTxHashesKey(hash))
1291+
}

common/errors.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,6 @@ var ErrMissingOrderedTxHashes = errors.New("missing ordered tx hashes")
6767

6868
// ErrInvalidHeader signals that an invalid header has been provided
6969
var ErrInvalidHeader = errors.New("invalid header")
70+
71+
// ErrMissingUnexecutableTxHash signals that unexecutable tx hashes are missing
72+
var ErrMissingUnexecutableTxHash = errors.New("missing unexecutable tx hash")

epochStart/metachain/rewardsV2.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ func (rc *rewardsCreatorV2) createRewardsMiniBlocks(
161161
rc.clean()
162162
rc.flagDelegationSystemSCEnabled.SetValue(args.newEpoch >= rc.enableEpochsHandler.GetActivationEpoch(common.StakingV2Flag))
163163

164-
protRwdTx, protRwdShardId, err := rc.createProtocolSustainabilityRewardTransaction(args.newEpoch, args.round, args.computedEconomics.GetRewardsForProtocolSustainability())
164+
protRwdTx, protRwdShardId, err := rc.createProtocolSustainabilityRewardTransaction(args.newEpoch, args.round, rc.economicsDataProvider.RewardsForProtocolSustainability())
165165
if err != nil {
166166
return nil, err
167167
}

factory/disabled/txCoordinator.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ func (txCoordinator *TxCoordinator) CreatePostProcessMiniBlocks() block.MiniBloc
2020
return make(block.MiniBlockSlice, 0)
2121
}
2222

23+
// GetUnExecutableTransactions does nothing as it is disabled
24+
func (txCoordinator *TxCoordinator) GetUnExecutableTransactions() map[string]struct{} {
25+
return make(map[string]struct{})
26+
}
27+
2328
// CreateReceiptsHash does nothing as it is disabled
2429
func (txCoordinator *TxCoordinator) CreateReceiptsHash() ([]byte, error) {
2530
return nil, nil

integrationTests/mock/transactionCoordinatorMock.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type TransactionCoordinatorMock struct {
4040
AddTxsFromMiniBlocksCalled func(miniBlocks block.MiniBlockSlice)
4141
AddTransactionsCalled func(txHandlers []data.TransactionHandler, blockType block.Type)
4242
ComputeTransactionTypeInEpochCalled func(tx data.TransactionHandler, epoch uint32) (process.TransactionType, process.TransactionType, bool)
43+
GetUnExecutableTransactionsCalled func() map[string]struct{}
4344
}
4445

4546
// GetAllCurrentLogs -
@@ -114,6 +115,15 @@ func (tcm *TransactionCoordinatorMock) SaveTxsToStorage(body *block.Body) {
114115
tcm.SaveTxsToStorageCalled(body)
115116
}
116117

118+
// GetUnExecutableTransactions -
119+
func (tcm *TransactionCoordinatorMock) GetUnExecutableTransactions() map[string]struct{} {
120+
if tcm.GetUnExecutableTransactionsCalled != nil {
121+
return tcm.GetUnExecutableTransactionsCalled()
122+
}
123+
124+
return nil
125+
}
126+
117127
// RestoreBlockDataFromStorage -
118128
func (tcm *TransactionCoordinatorMock) RestoreBlockDataFromStorage(body *block.Body) (int, error) {
119129
if tcm.RestoreBlockDataFromStorageCalled == nil {

node/chainSimulator/process/processor.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ import (
77
"github.com/multiversx/mx-chain-core-go/core/check"
88
"github.com/multiversx/mx-chain-core-go/data"
99
dataBlock "github.com/multiversx/mx-chain-core-go/data/block"
10-
"github.com/multiversx/mx-chain-go/node/chainSimulator/dtos"
1110
logger "github.com/multiversx/mx-chain-logger-go"
1211

1312
"github.com/multiversx/mx-chain-go/common"
1413
heartbeatData "github.com/multiversx/mx-chain-go/heartbeat/data"
1514
"github.com/multiversx/mx-chain-go/node/chainSimulator/configs"
15+
"github.com/multiversx/mx-chain-go/node/chainSimulator/dtos"
1616
"github.com/multiversx/mx-chain-go/process/asyncExecution/queue"
1717
"github.com/multiversx/mx-chain-go/sharding/nodesCoordinator"
1818
)
@@ -127,6 +127,11 @@ func (creator *blocksCreator) CreateNewBlock() (*dtos.BroadcastData, error) {
127127
return nil, err
128128
}
129129

130+
log.Debug("Leader in current block",
131+
"shardID", newHeader.GetShardID(),
132+
"round", newHeader.GetRound(),
133+
"leader", leader.PubKey())
134+
130135
pubKeyBitmap := GeneratePubKeyBitmap(len(validators))
131136
for idx, validator := range validators {
132137
isManaged := cryptoComponents.KeysHandler().IsKeyManagedByCurrentNode(validator.PubKey())

node/external/transactionAPI/apiTransactionProcessor.go

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package transactionAPI
22

33
import (
4+
"bytes"
45
"encoding/hex"
56
"errors"
67
"fmt"
@@ -748,20 +749,53 @@ func (atp *apiTransactionProcessor) computeTimestampForRoundAsMs(round uint64) i
748749
return timestamp.UnixMilli()
749750
}
750751

751-
func (atp *apiTransactionProcessor) checkExecutionResult(miniblockMetadata *dblookupext.MiniblockMetadata) error {
752+
func (atp *apiTransactionProcessor) checkExecutionResultAndTx(miniblockMetadata *dblookupext.MiniblockMetadata) (bool, error) {
752753
isSupernovaEnabled := atp.enableRoundsHandler.IsFlagEnabledInRound(common.SupernovaRoundFlag, miniblockMetadata.Round)
753754
if !isSupernovaEnabled {
754-
return nil
755+
return true, nil
755756
}
756757

757758
headerHash := miniblockMetadata.GetHeaderHash()
758759
executionResultsStorer, errG := atp.storageService.GetStorer(dataRetriever.ExecutionResultsUnit)
759760
if errG != nil {
760-
return errG
761+
return false, errG
762+
}
763+
764+
executionResultsBytes, err := executionResultsStorer.GetFromEpoch(headerHash, miniblockMetadata.GetEpoch())
765+
if err != nil {
766+
return false, err
767+
}
768+
769+
if atp.shardCoordinator.SelfId() == core.MetachainShardId {
770+
// we cannot have unexecutable txs on metachain
771+
return true, nil
772+
}
773+
mbHeaders, err := atp.getMbHeadersFromExecutionResultBytes(executionResultsBytes)
774+
if err != nil {
775+
return false, err
761776
}
762777

763-
_, err := executionResultsStorer.GetFromEpoch(headerHash, miniblockMetadata.GetEpoch())
764-
return err
778+
// check if the transaction miniblock metadata has a mb header on execution result
779+
// if yes - the transaction was executed
780+
// if no - the transaction was proposed but not executed
781+
currentTxIsExecuted := false
782+
for _, mbHeader := range mbHeaders {
783+
if bytes.Equal(mbHeader.Hash, miniblockMetadata.MiniblockHash) {
784+
currentTxIsExecuted = true
785+
break
786+
}
787+
}
788+
return currentTxIsExecuted, nil
789+
}
790+
791+
func (atp *apiTransactionProcessor) getMbHeadersFromExecutionResultBytes(executionResultBytes []byte) ([]block.MiniBlockHeader, error) {
792+
executResult := &block.ExecutionResult{}
793+
err := atp.marshalizer.Unmarshal(executResult, executionResultBytes)
794+
if err != nil {
795+
return nil, err
796+
}
797+
798+
return executResult.GetMiniBlockHeaders(), nil
765799
}
766800

767801
func (atp *apiTransactionProcessor) lookupHistoricalTransaction(hash []byte, withResults bool) (*transaction.ApiTransactionResult, error) {
@@ -770,7 +804,7 @@ func (atp *apiTransactionProcessor) lookupHistoricalTransaction(hash []byte, wit
770804
return nil, fmt.Errorf("%s: %w", ErrTransactionNotFound.Error(), err)
771805
}
772806

773-
err = atp.checkExecutionResult(miniblockMetadata)
807+
isExecuted, err := atp.checkExecutionResultAndTx(miniblockMetadata)
774808
if err != nil {
775809
return nil, fmt.Errorf("%s: %w", ErrTransactionNotFound.Error(), err)
776810
}
@@ -802,6 +836,11 @@ func (atp *apiTransactionProcessor) lookupHistoricalTransaction(hash []byte, wit
802836
return nil, fmt.Errorf("%s: %w", ErrNilStatusComputer.Error(), err)
803837
}
804838

839+
if !isExecuted {
840+
tx.Status = transaction.TxStatusNotExecutable
841+
return tx, nil
842+
}
843+
805844
if ok, _ := statusComputer.SetStatusIfIsRewardReverted(
806845
tx,
807846
block.Type(miniblockMetadata.Type),

0 commit comments

Comments
 (0)