mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-17 10:20:44 +00:00
Add penalty feature for prevent signer without sign in epoc make slow…
This commit is contained in:
parent
b8cb600964
commit
f5152bf0cf
4 changed files with 92 additions and 111 deletions
|
|
@ -690,7 +690,7 @@ func (bc *BlockChain) procFutureBlocks() {
|
||||||
|
|
||||||
// Insert one by one as chain insertion needs contiguous ancestry between blocks
|
// Insert one by one as chain insertion needs contiguous ancestry between blocks
|
||||||
for i := range 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
|
type WriteStatus byte
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NonStatTy WriteStatus = iota
|
NonStatTy WriteStatus = iota
|
||||||
CanonStatTy
|
CanonStatTy
|
||||||
SideStatTy
|
SideStatTy
|
||||||
)
|
)
|
||||||
|
|
||||||
// Rollback is designed to remove a chain of links from the database that aren't
|
// 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 {
|
if index == len(chain)-1 || elapsed >= statsReportLimit {
|
||||||
var (
|
var (
|
||||||
end = chain[index]
|
end = chain[index]
|
||||||
txs = countTransactions(chain[st.lastIndex : index+1])
|
txs = countTransactions(chain[st.lastIndex: index+1])
|
||||||
)
|
)
|
||||||
context := []interface{}{
|
context := []interface{}{
|
||||||
"blocks", st.processed, "txs", txs, "mgas", float64(st.usedGas) / 1000000,
|
"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()})
|
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 {
|
if len(ms) == 0 {
|
||||||
log.Info("No masternode candidates found. Keep the current masternodes set for the next epoch")
|
log.Info("No masternode candidates found. Keep the current masternodes set for the next epoch")
|
||||||
} else {
|
} else {
|
||||||
sort.Slice(ms, func(i, j int) bool {
|
sort.Slice(ms, func(i, j int) bool {
|
||||||
return ms[i].Stake >= ms[j].Stake
|
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
|
// update masternodes
|
||||||
log.Info("Updating new set of masternodes")
|
log.Info("Updating new set of masternodes")
|
||||||
if len(ms) > common.MaxMasternodes {
|
if len(ms) > common.MaxMasternodes {
|
||||||
|
|
|
||||||
|
|
@ -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) }
|
||||||
|
|
||||||
|
|
|
||||||
181
eth/backend.go
181
eth/backend.go
|
|
@ -51,7 +51,6 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rlp"
|
"github.com/ethereum/go-ethereum/rlp"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const NumOfMasternodes = 99
|
const NumOfMasternodes = 99
|
||||||
|
|
@ -202,60 +201,92 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, authorized := snap.Signers[eth.etherbase]; authorized {
|
if _, authorized := snap.Signers[eth.etherbase]; authorized {
|
||||||
// double validation
|
if err := contracts.CreateTransactionSign(chainConfig, eth.txPool, eth.accountManager, block, chainDb); err != nil {
|
||||||
m2, err := getM2(snap, eth, block)
|
log.Error("Fail to create tx sign for imported block", "error", err)
|
||||||
if err != nil {
|
|
||||||
log.Error("Fail to validate M2 condition for imported block", "error", err)
|
|
||||||
return
|
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)
|
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.
|
// Hook reward for XDPoS 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 {
|
||||||
client, err := eth.blockchain.GetClient()
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -339,25 +337,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
||||||
return eth, nil
|
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 {
|
func makeExtraData(extra []byte) []byte {
|
||||||
if len(extra) == 0 {
|
if len(extra) == 0 {
|
||||||
// create default extradata
|
// create default extradata
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue