mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-19 10:22:23 +00:00
Add penalty feature for prevent signer without sign in epoc make slow down chain.
Fixed duplicate nonce value for randomize and sign txs Fixed prevent signers penaltied return in 4 epocs sequent.
This commit is contained in:
parent
589e71fe31
commit
d1df0c5786
5 changed files with 116 additions and 7 deletions
|
|
@ -213,6 +213,7 @@ type Posv struct {
|
|||
|
||||
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error
|
||||
HookPrepare func(header *types.Header, signers []common.Address) error
|
||||
HookPenalty func(chain consensus.ChainReader, signers []common.Address, blockNumberEpoc uint64) ([]common.Address, error)
|
||||
}
|
||||
|
||||
// New creates a Posv proof-of-stake-voting consensus engine with the initial
|
||||
|
|
@ -637,7 +638,70 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
|
|||
header.Extra = header.Extra[:extraVanity]
|
||||
|
||||
if number%c.config.Epoch == 0 {
|
||||
for _, signer := range snap.signers() {
|
||||
signers := snap.signers()
|
||||
|
||||
if c.HookPenalty != nil {
|
||||
penSigners, _ := c.HookPenalty(chain, signers, number)
|
||||
|
||||
if len(penSigners) > 0 {
|
||||
// Keep remove penalty signer out of signer list.
|
||||
for i, signer := range signers {
|
||||
for _, penSigner := range penSigners {
|
||||
if signer == penSigner {
|
||||
signers = append(signers[:i], signers[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var penBytes []byte
|
||||
for _, penSigner := range penSigners {
|
||||
log.Error("penSigner", "penSigner", penSigner.String())
|
||||
// Convert number to byte.
|
||||
penByte := common.LeftPadBytes([]byte(fmt.Sprintf("%d", penSigner)), common.AddressLength)
|
||||
penBytes = append(penBytes, penByte...)
|
||||
}
|
||||
if len(penBytes) > 0 {
|
||||
header.Penalties = penBytes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent penaltied signer in 4 epocs ago jump into signer list.
|
||||
var preventSigners []common.Address
|
||||
for i := 1; i <= 4; i++ {
|
||||
checkEpoc := uint64(i) * c.config.Epoch
|
||||
if number > checkEpoc {
|
||||
prevEpoc := number - checkEpoc
|
||||
log.Error("prevEpoc", "prevEpoc", prevEpoc, "checkEpoc", checkEpoc, "number", number)
|
||||
prevHeader := chain.GetHeaderByNumber(prevEpoc)
|
||||
prevEpocBlock := chain.GetBlock(prevHeader.Hash(), prevEpoc)
|
||||
penalties := prevEpocBlock.Penalties()
|
||||
if penalties != nil {
|
||||
prevSigners := make([]common.Address, len(penalties)/common.AddressLength)
|
||||
if len(prevSigners) > 0 {
|
||||
for _, signer := range prevSigners {
|
||||
for _, prevSigner := range prevSigners {
|
||||
if signer == prevSigner {
|
||||
log.Error("preventSigner", "preventSigner", signer.String())
|
||||
preventSigners = append(preventSigners, signer)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(preventSigners) > 0 {
|
||||
for i, signer := range signers {
|
||||
for _, preventSigner := range preventSigners {
|
||||
if signer == preventSigner {
|
||||
signers = append(signers[:i], signers[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, signer := range signers {
|
||||
header.Extra = append(header.Extra, signer[:]...)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -690,7 +690,7 @@ func (bc *BlockChain) procFutureBlocks() {
|
|||
|
||||
// Insert one by one as chain insertion needs contiguous ancestry between blocks
|
||||
for i := range blocks {
|
||||
bc.InsertChain(blocks[i : i+1])
|
||||
bc.InsertChain(blocks[i: i+1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1243,7 +1243,7 @@ func (st *insertStats) report(chain []*types.Block, index int, cache common.Stor
|
|||
if index == len(chain)-1 || elapsed >= statsReportLimit {
|
||||
var (
|
||||
end = chain[index]
|
||||
txs = countTransactions(chain[st.lastIndex : index+1])
|
||||
txs = countTransactions(chain[st.lastIndex: index+1])
|
||||
)
|
||||
context := []interface{}{
|
||||
"blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000,
|
||||
|
|
|
|||
|
|
@ -85,6 +85,7 @@ type Header struct {
|
|||
MixDigest common.Hash `json:"mixHash" gencodec:"required"`
|
||||
Nonce BlockNonce `json:"nonce" gencodec:"required"`
|
||||
Validators []byte `json:"validators" gencodec:"required"`
|
||||
Penalties []byte `json:"penalties" gencodec:"required"`
|
||||
}
|
||||
|
||||
// field type overrides for gencodec
|
||||
|
|
@ -320,6 +321,7 @@ func (b *Block) TxHash() common.Hash { return b.header.TxHash }
|
|||
func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash }
|
||||
func (b *Block) UncleHash() common.Hash { return b.header.UncleHash }
|
||||
func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) }
|
||||
func (b *Block) Penalties() []byte { return common.CopyBytes(b.header.Penalties) }
|
||||
|
||||
func (b *Block) Header() *Header { return CopyHeader(b.header) }
|
||||
|
||||
|
|
|
|||
|
|
@ -241,9 +241,51 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
// Hook penalty.
|
||||
c.HookPenalty = func(chain consensus.ChainReader, signers []common.Address, blockNumberEpoc uint64) ([]common.Address, error) {
|
||||
client, err := eth.blockchain.GetClient()
|
||||
if err != nil {
|
||||
log.Error("Fail to connect IPC client for blockSigner", "error", err)
|
||||
}
|
||||
prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch
|
||||
var penSigners []common.Address
|
||||
if prevEpoc > 0 {
|
||||
prevHeader := chain.GetHeaderByNumber(prevEpoc)
|
||||
prevSigners := c.GetMasternodes(chain, prevHeader)
|
||||
for _, signer := range signers {
|
||||
for _, prevSigner := range prevSigners {
|
||||
if signer == prevSigner {
|
||||
penSigners = append(penSigners, signer)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(penSigners) > 0 {
|
||||
blockSignerAddr := common.HexToAddress(common.BlockSigners)
|
||||
// Loop for each block to check missing sign.
|
||||
for i := prevEpoc; i <= blockNumberEpoc; i++ {
|
||||
blockHeader := chain.GetHeaderByNumber(i)
|
||||
if len(penSigners) > 0 {
|
||||
signedMasternodes, _ := contracts.GetSignersFromContract(blockSignerAddr, client, blockHeader.Hash())
|
||||
if len(signedMasternodes) > 0 {
|
||||
// Check signer signed?
|
||||
for _, signed := range signedMasternodes {
|
||||
for j, addr := range penSigners {
|
||||
if signed == addr {
|
||||
// Remove it from dupSigners.
|
||||
penSigners = append(penSigners[:j], penSigners[j+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return penSigners, nil
|
||||
}
|
||||
|
||||
// Hook reward for posv validator.
|
||||
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error {
|
||||
|
|
|
|||
|
|
@ -817,6 +817,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
|
|||
"transactionsRoot": head.TxHash,
|
||||
"receiptsRoot": head.ReceiptHash,
|
||||
"validators": hexutil.Bytes(head.Validators),
|
||||
"penalties": hexutil.Bytes(head.Penalties),
|
||||
}
|
||||
|
||||
if inclTx {
|
||||
|
|
|
|||
Loading…
Reference in a new issue