-
Notifications
You must be signed in to change notification settings - Fork 199
/
status.go
115 lines (95 loc) · 3.64 KB
/
status.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package transaction
import (
"bytes"
logger "github.com/ElrondNetwork/elrond-go-logger"
"github.com/ElrondNetwork/elrond-go/core"
"github.com/ElrondNetwork/elrond-go/data/block"
"github.com/ElrondNetwork/elrond-go/data/typeConverters"
"github.com/ElrondNetwork/elrond-go/dataRetriever"
)
// TxStatus is the status of a transaction
type TxStatus string
var log = logger.GetOrCreate("data/transaction")
const (
// TxStatusPending = received and maybe executed on source shard, but not on destination shard
TxStatusPending TxStatus = "pending"
// TxStatusSuccess = received and executed
TxStatusSuccess TxStatus = "success"
// TxStatusFail = received and executed with error
TxStatusFail TxStatus = "fail"
// TxStatusInvalid = considered invalid
TxStatusInvalid TxStatus = "invalid"
// TxStatusRewardReverted represents the identifier for a reverted reward transaction
TxStatusRewardReverted TxStatus = "reward-reverted"
)
// String returns the string representation of the status
func (tx TxStatus) String() string {
return string(tx)
}
// StatusComputer computes a transaction status
type StatusComputer struct {
MiniblockType block.Type
IsMiniblockFinalized bool
SourceShard uint32
DestinationShard uint32
Receiver []byte
TransactionData []byte
SelfShard uint32
HeaderNonce uint64
HeaderHash []byte
Uint64ByteSliceConverter typeConverters.Uint64ByteSliceConverter
Store dataRetriever.StorageService
}
// ComputeStatusWhenInStorageKnowingMiniblock computes the transaction status for a historical transaction
func (sc *StatusComputer) ComputeStatusWhenInStorageKnowingMiniblock() TxStatus {
if sc.isMiniblockInvalid() {
return TxStatusInvalid
}
if sc.IsMiniblockFinalized || sc.isDestinationMe() || sc.isContractDeploy() {
return TxStatusSuccess
}
return TxStatusPending
}
// ComputeStatusWhenInStorageNotKnowingMiniblock computes the transaction status when transaction is in current epoch's storage
// Limitation: in this case, since we do not know the miniblock type, we cannot know if a transaction is actually, "invalid".
// However, when "dblookupext" indexing is enabled, this function is not used.
func (sc *StatusComputer) ComputeStatusWhenInStorageNotKnowingMiniblock() TxStatus {
if sc.isDestinationMe() || sc.isContractDeploy() {
return TxStatusSuccess
}
// At least partially executed (since in source's storage)
return TxStatusPending
}
func (sc *StatusComputer) isMiniblockInvalid() bool {
return sc.MiniblockType == block.InvalidBlock
}
func (sc *StatusComputer) isDestinationMe() bool {
return sc.SelfShard == sc.DestinationShard
}
func (sc *StatusComputer) isContractDeploy() bool {
return core.IsEmptyAddress(sc.Receiver) && len(sc.TransactionData) > 0
}
// SetStatusIfIsRewardReverted will compute and set status for a reverted reward transaction
func (sc *StatusComputer) SetStatusIfIsRewardReverted(tx *ApiTransactionResult) bool {
if sc.MiniblockType != block.RewardsBlock {
return false
}
var storerUnit dataRetriever.UnitType
selfShardID := sc.SelfShard
if selfShardID == core.MetachainShardId {
storerUnit = dataRetriever.MetaHdrNonceHashDataUnit
} else {
storerUnit = dataRetriever.ShardHdrNonceHashDataUnit + dataRetriever.UnitType(selfShardID)
}
nonceToByteSlice := sc.Uint64ByteSliceConverter.ToByteSlice(sc.HeaderNonce)
headerHash, err := sc.Store.Get(storerUnit, nonceToByteSlice)
if err != nil {
log.Warn("cannot get header hash by nonce", "error", err.Error())
return false
}
if bytes.Equal(headerHash, sc.HeaderHash) {
return false
}
tx.Status = TxStatusRewardReverted
return true
}