Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions consensus/XDPoS/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -769,3 +769,81 @@ func (api *API) GetBlockInfoByEpochNum(epochNumber uint64) (*utils.EpochNumInfo,
}
return api.GetBlockInfoByV2EpochNum(epochNumber)
}

// GetSigningTxCountByEpoch returns the signing transaction count for ALL masternodes
// (including non-active ones) in the epoch that immediately precedes the epoch
// that starts at epochBlockNum. In other words, it walks blocks from
// epochBlockNum-1 backwards to the previous epoch-switch block (inclusive).
// epochBlockNum must be an epoch-switch block number that marks the start of an epoch.
func (api *API) GetSigningTxCountByEpoch(epochBlockNum rpc.BlockNumber) (map[common.Address]uint64, error) {
header, err := api.getHeaderFromApiBlockNum(&epochBlockNum)
if err != nil {
return nil, err
}
if header == nil {
return nil, fmt.Errorf("block %d not found", epochBlockNum)
}

isEpochSwitch, _, err := api.XDPoS.IsEpochSwitch(header)
if err != nil {
return nil, err
}
if !isEpochSwitch {
return nil, fmt.Errorf("block %d is not an epoch switch block", epochBlockNum)
}

// Walk backwards from epochBlockNum-1 to the previous epoch switch block,
// collecting signing txs from every block.
mapBlkHash := map[uint64]common.Hash{}
// sigData maps blockHash -> list of signers who signed for that block
sigData := make(map[common.Hash][]common.Address)

h := header
for i := header.Number.Uint64() - 1; ; i-- {
parentHash := h.ParentHash
h = api.chain.GetHeader(parentHash, i)
if h == nil {
return nil, fmt.Errorf("failed to get header at number %d hash %s", i, parentHash.Hex())
}

mapBlkHash[i] = h.Hash()

signingTxs, ok := api.XDPoS.GetCachedSigningTxs(h.Hash())
if !ok {
block := api.chain.GetBlock(h.Hash(), i)
if block == nil {
return nil, fmt.Errorf("failed to get block at number %d hash %s", i, h.Hash().Hex())
}
signingTxs = api.XDPoS.CacheSigningTxs(h.Hash(), block.Transactions())
}
for _, tx := range signingTxs {
blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:])
from := *tx.From()
sigData[blkHash] = append(sigData[blkHash], from)
}

prevIsEpochSwitch, _, err := api.XDPoS.IsEpochSwitch(h)
if err != nil {
return nil, err
}
if prevIsEpochSwitch || i == 0 {
break
}
}

// Count signings: for each block at MergeSignRange boundary, tally unique signers.
result := make(map[common.Address]uint64)
for blockNum, blkHash := range mapBlkHash {
if blockNum%common.MergeSignRange != 0 {
continue
}
seen := make(map[common.Address]bool)
for _, addr := range sigData[blkHash] {
if !seen[addr] {
seen[addr] = true
result[addr]++
}
}
}
return result, nil
}
4 changes: 2 additions & 2 deletions consensus/XDPoS/engines/engine_v2/timeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutRound type
Round: epochRound,
Number: epochSwitchInfo.EpochSwitchBlockInfo.Number,
}
log.Info("[getTCEpochInfo] Init epochInfo", "number", epochBlockInfo.Number, "round", epochRound, "tcRound", timeoutRound, "tcEpoch", tempTCEpoch)
log.Debug("[getTCEpochInfo] Init epochInfo", "number", epochBlockInfo.Number, "round", epochRound, "tcRound", timeoutRound, "tcEpoch", tempTCEpoch)
for epochBlockInfo.Round > timeoutRound && tempTCEpoch > 0 {
tempTCEpoch--
epochBlockInfo, err = x.GetBlockByEpochNumber(chain, tempTCEpoch)
Expand All @@ -135,7 +135,7 @@ func (x *XDPoS_v2) getTCEpochInfo(chain consensus.ChainReader, timeoutRound type
log.Debug("[getTCEpochInfo] Loop to get right epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutRound, "tcEpoch", tempTCEpoch)
}
tcEpoch := tempTCEpoch
log.Info("[getTCEpochInfo] Final TC epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutRound, "tcEpoch", tcEpoch)
log.Debug("[getTCEpochInfo] Final TC epochInfo", "number", epochBlockInfo.Number, "round", epochBlockInfo.Round, "tcRound", timeoutRound, "tcEpoch", tcEpoch)

epochInfo, err := x.getEpochSwitchInfo(chain, nil, epochBlockInfo.Hash)
if err != nil {
Expand Down
6 changes: 6 additions & 0 deletions internal/web3ext/web3ext.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ web3._extend({
params: 3,
inputFormatter: [null, web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter]
}),
new web3._extend.Method({
name: 'getSigningTxCountByEpoch',
call: 'XDPoS_getSigningTxCountByEpoch',
params: 1,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
}),
],
properties: [
new web3._extend.Property({
Expand Down
Loading