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
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[:]...)
}
}

View file

@ -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])
}
}
}
@ -699,9 +699,9 @@ func (bc *BlockChain) procFutureBlocks() {
type WriteStatus byte
const (
NonStatTy WriteStatus = iota
CanonStatTy
SideStatTy
NonStatTy WriteStatus = iota
CanonStatTy
SideStatTy
)
// Rollback is designed to remove a chain of links from the database that aren't
@ -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,

View file

@ -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) }

View file

@ -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 {

View file

@ -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 {