Add penalty feature for prevent signer without sign in epoc make slow…

This commit is contained in:
AnilChinchwale 2018-11-07 10:26:28 +05:30
parent b8cb600964
commit f5152bf0cf
4 changed files with 92 additions and 111 deletions

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,
@ -1633,17 +1633,16 @@ func (bc *BlockChain) UpdateM1() error {
ms = append(ms, XDPoS.Masternode{Address: candidate, Stake: v.Uint64()})
}
}
log.Info("Ordered list of masternode candidates")
for _, m := range ms {
log.Info("", "address", m.Address.String(), "stake", m.Stake)
}
if len(ms) == 0 {
log.Info("No masternode candidates found. Keep the current masternodes set for the next epoch")
} else {
sort.Slice(ms, func(i, j int) bool {
return ms[i].Stake >= ms[j].Stake
})
log.Info("Ordered list of masternode candidates")
for _, m := range ms {
log.Info("", "address", m.Address.String(), "stake", m.Stake)
}
// update masternodes
log.Info("Updating new set of masternodes")
if len(ms) > common.MaxMasternodes {

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

@ -51,7 +51,6 @@ import (
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"time"
)
const NumOfMasternodes = 99
@ -202,60 +201,92 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
return
}
if _, authorized := snap.Signers[eth.etherbase]; authorized {
// double validation
m2, err := getM2(snap, eth, block)
if err != nil {
log.Error("Fail to validate M2 condition for imported block", "error", err)
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
log.Error("Fail to create tx sign for imported block", "error", err)
return
}
if eth.etherbase != m2 {
// firstly, look into txPool
pendingMap, err := eth.txPool.Pending()
if err != nil {
log.Error("Fail to get txPool pending", "err", err)
//reset pendingMap
pendingMap = map[common.Address]types.Transactions{}
}
txsSentFromM2 := pendingMap[m2]
if len(txsSentFromM2) > 0 {
for _, tx := range txsSentFromM2 {
if tx.To().String() == common.BlockSigners {
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
log.Error("Fail to create tx sign for imported block", "error", err)
return
}
return
}
}
}
//then wait until signTx from m2 comes into txPool
txCh := make(chan core.TxPreEvent, txChanSize)
subEvent := eth.txPool.SubscribeTxPreEvent(txCh)
G:
select {
case event := <-txCh:
from, err := eth.txPool.GetSender(event.Tx)
if (err == nil) && (event.Tx.To().String() == common.BlockSigners) && (from == m2) {
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
log.Error("Fail to create tx sign for imported block", "error", err)
return
}
}
//timeout 10s
case <-time.After(time.Duration(10) * time.Second):
break G
}
subEvent.Unsubscribe()
} else if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
log.Error("Fail to create tx sign for imported block", "error", err)
return
}
// end of double validation
}
}
eth.protocolManager.fetcher.SetImportedHook(importedHook)
// Hook will process when preparing block.
c.HookPrepare = func(header *types.Header, signers []common.Address) error {
client, err := eth.blockchain.GetClient()
if err != nil {
log.Error("Fail to connect IPC client for penalty.", "error", err)
}
number := header.Number.Int64()
// Check m2 exists on chaindb.
// Get secrets and opening at epoc block checkpoint.
if number > 0 && number%common.EpocBlockRandomize == 0 {
var candidates []int64
lenSigners := int64(len(signers))
if lenSigners > 0 {
for _, addr := range signers {
random, err := contracts.GetRandomizeFromContract(client, addr)
if err != nil {
log.Error("Fail to get random m2 from contract.", "error", err)
}
candidates = append(candidates, random)
}
// Get randomize m2 list.
m2, err := contracts.GenM2FromRandomize(candidates, lenSigners)
if err != nil {
log.Error("Can not get m2 from randomize SC", "error", err)
}
if len(m2) > 0 {
header.Validators = contracts.BuildValidatorFromM2(m2)
}
}
}
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().XDPoS.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 XDPoS validator.
c.HookReward = func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) error {
client, err := eth.blockchain.GetClient()
@ -298,39 +329,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}
}
}
// Check m2 exists on chaindb.
// Get secrets and opening at epoc block checkpoint.
if number > 0 && number%common.EpocBlockRandomize == 0 {
var candidates []int64
// Get signers from snapshot.
snap, err := c.GetSnapshot(eth.blockchain, chain.CurrentHeader())
if err != nil {
log.Error("Fail to get snapshot for get secret and opening.", "error", err)
return err
}
signers := snap.Signers
lenSigners := int64(len(signers))
if lenSigners > 0 {
for addr := range signers {
random, err := contracts.GetRandomizeFromContract(client, addr)
if err != nil {
log.Error("Fail to get random m2 from contract.", "error", err)
}
candidates = append(candidates, random)
}
// Get randomize m2 list.
m2, err := contracts.GenM2FromRandomize(candidates, lenSigners)
if err != nil {
log.Error("Can not get m2 from randomize SC", "error", err)
}
if len(m2) > 0 {
header.Validators = contracts.BuildValidatorFromM2(m2)
}
}
}
return nil
}
@ -339,25 +337,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
return eth, nil
}
func getM2(snap *XDPoS.Snapshot, eth *Ethereum, block *types.Block) (common.Address, error) {
epoch := eth.chainConfig.XDPoS.Epoch
no := block.NumberU64()
cpNo := no
if no%epoch != 0 {
cpNo = no - (no % epoch)
}
cpBlk := eth.blockchain.GetBlockByNumber(cpNo)
m, err := contracts.GetM1M2FromCheckpointBlock(cpBlk)
if err != nil {
return common.Address{}, err
}
m1, err := XDPoS.WhoIsCreator(snap, block.Header())
if err != nil {
return common.Address{}, err
}
return m[m1], nil
}
func makeExtraData(extra []byte) []byte {
if len(extra) == 0 {
// create default extradata

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 {