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:
DinhLN 2018-10-04 15:15:32 +07:00 committed by Nguyen Ba Tam
parent 589e71fe31
commit d1df0c5786
5 changed files with 116 additions and 7 deletions

View file

@ -213,6 +213,7 @@ type Posv struct {
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error
HookPrepare func(header *types.Header, signers []common.Address) 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 // 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] header.Extra = header.Extra[:extraVanity]
if number%c.config.Epoch == 0 { 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[:]...) header.Extra = append(header.Extra, signer[:]...)
} }
} }

View file

@ -85,6 +85,7 @@ type Header struct {
MixDigest common.Hash `json:"mixHash" gencodec:"required"` MixDigest common.Hash `json:"mixHash" gencodec:"required"`
Nonce BlockNonce `json:"nonce" gencodec:"required"` Nonce BlockNonce `json:"nonce" gencodec:"required"`
Validators []byte `json:"validators" gencodec:"required"` Validators []byte `json:"validators" gencodec:"required"`
Penalties []byte `json:"penalties" gencodec:"required"`
} }
// field type overrides for gencodec // 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) ReceiptHash() common.Hash { return b.header.ReceiptHash }
func (b *Block) UncleHash() common.Hash { return b.header.UncleHash } func (b *Block) UncleHash() common.Hash { return b.header.UncleHash }
func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) } 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) } func (b *Block) Header() *Header { return CopyHeader(b.header) }

View file

@ -241,9 +241,51 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
} }
} }
} }
return nil 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. // Hook reward for posv validator.
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error { c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error {

View file

@ -817,6 +817,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx
"transactionsRoot": head.TxHash, "transactionsRoot": head.TxHash,
"receiptsRoot": head.ReceiptHash, "receiptsRoot": head.ReceiptHash,
"validators": hexutil.Bytes(head.Validators), "validators": hexutil.Bytes(head.Validators),
"penalties": hexutil.Bytes(head.Penalties),
} }
if inclTx { if inclTx {