-
Notifications
You must be signed in to change notification settings - Fork 199
/
printDoubleTransactionsDetector.go
127 lines (105 loc) · 4.53 KB
/
printDoubleTransactionsDetector.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
116
117
118
119
120
121
122
123
124
125
126
127
package coordinator
import (
"encoding/hex"
"fmt"
"strings"
"github.com/ElrondNetwork/elrond-go-core/core"
"github.com/ElrondNetwork/elrond-go-core/core/atomic"
"github.com/ElrondNetwork/elrond-go-core/core/check"
"github.com/ElrondNetwork/elrond-go-core/data/block"
"github.com/ElrondNetwork/elrond-go-core/hashing"
"github.com/ElrondNetwork/elrond-go-core/marshal"
logger "github.com/ElrondNetwork/elrond-go-logger"
"github.com/ElrondNetwork/elrond-go/process"
)
const printReportHeader = "double transactions found (this is not critical, thus)\nshowing the whole block body:\n"
const nilBlockBodyMessage = "nil block body in printDoubleTransactionsDetector.ProcessBlockBody"
const noDoubledTransactionsFoundMessage = "no double transactions found"
const doubledTransactionsFoundButFlagActive = "double transactions found but this is expected until the AddFailedRelayedTxToInvalidMBsDisableEpoch is deactivated"
// ArgsPrintDoubleTransactionsDetector is the argument DTO structure used in the NewPrintDoubleTransactionsDetector function
type ArgsPrintDoubleTransactionsDetector struct {
Marshaller marshal.Marshalizer
Hasher hashing.Hasher
EpochNotifier process.EpochNotifier
AddFailedRelayedTxToInvalidMBsDisableEpoch uint32
}
type printDoubleTransactionsDetector struct {
marshaller marshal.Marshalizer
hasher hashing.Hasher
logger logger.Logger
addFailedRelayedTxToInvalidMBsDisableEpoch uint32
flagAddFailedRelayedTxToInvalidMBs atomic.Flag
}
// NewPrintDoubleTransactionsDetector creates a new instance of printDoubleTransactionsDetector
func NewPrintDoubleTransactionsDetector(args ArgsPrintDoubleTransactionsDetector) (*printDoubleTransactionsDetector, error) {
err := checkArgsPrintDoubleTransactionsDetector(args)
if err != nil {
return nil, err
}
detector := &printDoubleTransactionsDetector{
marshaller: args.Marshaller,
hasher: args.Hasher,
addFailedRelayedTxToInvalidMBsDisableEpoch: args.AddFailedRelayedTxToInvalidMBsDisableEpoch,
logger: log,
}
args.EpochNotifier.RegisterNotifyHandler(detector)
return detector, nil
}
func checkArgsPrintDoubleTransactionsDetector(args ArgsPrintDoubleTransactionsDetector) error {
if check.IfNil(args.Marshaller) {
return process.ErrNilMarshalizer
}
if check.IfNil(args.Hasher) {
return process.ErrNilHasher
}
if check.IfNil(args.EpochNotifier) {
return process.ErrNilEpochNotifier
}
return nil
}
// ProcessBlockBody processes the block body provided in search of doubled transactions. If there are doubled transactions,
// this method will log as error the event providing as much information as possible
func (detector *printDoubleTransactionsDetector) ProcessBlockBody(body *block.Body) {
if body == nil {
detector.logger.Error(nilBlockBodyMessage)
return
}
transactions := make(map[string]int)
doubleTransactionsExist := false
printReport := strings.Builder{}
for _, miniBlock := range body.MiniBlocks {
mbHash, _ := core.CalculateHash(detector.marshaller, detector.hasher, miniBlock)
log.Debug("checking for double transactions: miniblock",
"sender shard", miniBlock.SenderShardID,
"receiver shard", miniBlock.ReceiverShardID,
"type", miniBlock.Type,
"num txs", len(miniBlock.TxHashes),
"hash", mbHash)
printReport.WriteString(fmt.Sprintf(" miniblock hash %s, type %s, %d -> %d\n",
hex.EncodeToString(mbHash), miniBlock.Type.String(), miniBlock.SenderShardID, miniBlock.ReceiverShardID))
for _, txHash := range miniBlock.TxHashes {
transactions[string(txHash)]++
printReport.WriteString(fmt.Sprintf(" tx hash %s\n", hex.EncodeToString(txHash)))
doubleTransactionsExist = doubleTransactionsExist || transactions[string(txHash)] > 1
}
}
if !doubleTransactionsExist {
detector.logger.Debug(noDoubledTransactionsFoundMessage)
return
}
if detector.flagAddFailedRelayedTxToInvalidMBs.IsSet() {
detector.logger.Debug(doubledTransactionsFoundButFlagActive)
return
}
detector.logger.Error(printReportHeader + printReport.String())
}
// EpochConfirmed is called whenever a new epoch is confirmed
func (detector *printDoubleTransactionsDetector) EpochConfirmed(epoch uint32, _ uint64) {
detector.flagAddFailedRelayedTxToInvalidMBs.SetValue(epoch < detector.addFailedRelayedTxToInvalidMBsDisableEpoch)
log.Debug("printDoubleTransactionsDetector: add failed relayed tx to invalid miniblocks",
"enabled", detector.flagAddFailedRelayedTxToInvalidMBs.IsSet())
}
// IsInterfaceNil returns true if there is no value under the interface
func (detector *printDoubleTransactionsDetector) IsInterfaceNil() bool {
return detector == nil
}