diff --git a/common/constants.go b/common/constants.go index 6b483d9b2c..8ca2ec3eca 100644 --- a/common/constants.go +++ b/common/constants.go @@ -18,6 +18,7 @@ const ( LimitThresholdNonceInQueue = 10 DefaultMinGasPrice = 2500 MergeSignRange = 15 + RangeReturnSigner = 90 ) var TIP2019Block = big.NewInt(1050000) diff --git a/contracts/utils.go b/contracts/utils.go index 1146f4208c..7dbf205a53 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -306,6 +306,62 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte) return random, nil } +// Get txw signed for block using cache or block body inside. +func GetSignersSignedAtBlockHash(c *posv.Posv, chain consensus.ChainReader, data map[common.Hash][]common.Address, header *types.Header, curNumber uint64) map[common.Hash][]common.Address { + if signData, ok := c.BlockSigners.Get(header.Hash()); ok { + txs := signData.([]*types.Transaction) + for _, tx := range txs { + blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) + from := *tx.From() + data[blkHash] = append(data[blkHash], from) + } + } else { + log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", curNumber) + block := chain.GetBlock(header.Hash(), curNumber) + txs := block.Transactions() + receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), curNumber) + + var signTxs []*types.Transaction + for _, tx := range txs { + if tx.IsSigningTransaction() { + var b uint + for _, r := range receipts { + if r.TxHash == tx.Hash() { + if len(r.PostState) > 0 { + b = types.ReceiptStatusSuccessful + } else { + b = r.Status + } + break + } + } + + if b == types.ReceiptStatusFailed { + continue + } + + signTxs = append(signTxs, tx) + blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) + from := *tx.From() + data[blkHash] = append(data[blkHash], from) + } + } + c.BlockSigners.Add(header.Hash(), signTxs) + } + + return data +} + +// Get signers list from bytes. +func GetSignersFromBytes(byteHeader []byte) []common.Address { + signers := make([]common.Address, len(byteHeader)/common.AddressLength) + for i := 0; i < len(masternodes); i++ { + copy(signers[i][:], byteHeader[i*common.AddressLength:]) + } + + return signers +} + // Calculate reward for reward checkpoint. func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, header *types.Header, rCheckpoint uint64, totalSigner *uint64) (map[common.Address]*rewardLog, error) { // Not reward for singer of genesis block and only calculate reward at checkpoint block. @@ -317,49 +373,10 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, header *t mapBlkHash := map[uint64]common.Hash{} data := make(map[common.Hash][]common.Address) - for i := prevCheckpoint + (rCheckpoint * 2) - 1; i >= startBlockNumber; i-- { - header = chain.GetHeader(header.ParentHash, i) - mapBlkHash[i] = header.Hash() - if signData, ok := c.BlockSigners.Get(header.Hash()); ok { - txs := signData.([]*types.Transaction) - for _, tx := range txs { - blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) - from := *tx.From() - data[blkHash] = append(data[blkHash], from) - } - } else { - log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i) - block := chain.GetBlock(header.Hash(), i) - txs := block.Transactions() - receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i) - - var signTxs []*types.Transaction - for _, tx := range txs { - if tx.IsSigningTransaction() { - var b uint - for _, r := range receipts { - if r.TxHash == tx.Hash() { - if len(r.PostState) > 0 { - b = types.ReceiptStatusSuccessful - } else { - b = r.Status - } - break - } - } - - if b == types.ReceiptStatusFailed { - continue - } - - signTxs = append(signTxs, tx) - blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) - from := *tx.From() - data[blkHash] = append(data[blkHash], from) - } - } - c.BlockSigners.Add(header.Hash(), signTxs) - } + for curNumber := prevCheckpoint + (rCheckpoint * 2) - 1; curNumber >= startBlockNumber; curNumber-- { + header = chain.GetHeader(header.ParentHash, curNumber) + mapBlkHash[curNumber] = header.Hash() + data = GetSignersSignedAtBlockHash(c, chain, data, header, curNumber) } header = chain.GetHeader(header.ParentHash, prevCheckpoint) masternodes := posv.GetMasternodesFromCheckpointHeader(header) diff --git a/eth/backend.go b/eth/backend.go index 7a649d9c53..9a2f121394 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -274,7 +274,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { start := time.Now() prevHeader := chain.GetHeaderByNumber(prevEpoc) penSigners := c.GetMasternodes(chain, prevHeader) - goodSigners := make(map[common.Address]*big.Int) + signedSigners := make(map[common.Address]*big.Int) if len(penSigners) > 0 { // Loop for each block to check missing sign. for i := prevEpoc; i < blockNumberEpoc; i++ { @@ -289,8 +289,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } for _, addr := range penSigners { if signer == addr { - // Remove it from dupSigners. - goodSigners[signer] = goodSigners[signer].Add(goodSigners[signer], big.NewInt(1)) + signedSigners[signer] = signedSigners[signer].Add(signedSigners[signer], big.NewInt(1)) } } } else { @@ -298,12 +297,12 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } } - if len(goodSigners) > 0 { - for signer, totalSign := range goodSigners { + if len(signedSigners) > 0 { + for signer, totalSign := range signedSigners { if totalSign.Cmp(big.NewInt(4)) >= 0 { for j, addr := range penSigners { if signer == addr { - // Remove it from dupSigners. + // If create block above 4 times then remove it from penSigners. penSigners = append(penSigners[:j], penSigners[j+1:]...) } } @@ -312,6 +311,38 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } } } + + // Check penalty signer return chain. + prevSigners := contracts.GetSignersFromBytes(prevHeader.Penalties) + if len(prevSigners) > 0 { + startCheck := blockNumberEpoc - common.RangeReturnSigner + data := make(map[common.Hash][]common.Address) + mapBlkHash := map[uint64]common.Hash{} + for curNumber := startCheck; curNumber < blockNumberEpoc; curNumber++ { + signers := make(map[common.Hash][]common.Address) + header := chain.GetHeaderByNumber(curNumber) + mapBlkHash[curNumber] = header.Hash() + data = contracts.GetSignersSignedAtBlockHash(c, chain, signers, header, curNumber) + } + + for _, blkHash := range mapBlkHash { + signers := data[blkHash] + for j, addr := range prevSigners { + for _, signer := range signers { + if signer == addr { + // If create block above 4 times then remove it from penSigners. + prevSigners = append(prevSigners[:j], prevSigners[j+1:]...) + } + } + } + } + if len(prevSigners) > 0 { + for _, signer := range prevSigners { + penSigners = append(penSigners, signer) + } + } + } + log.Debug("Time Calculated HookPenalty ", "block", blockNumberEpoc, "time", common.PrettyDuration(time.Since(start))) return penSigners, nil }