create new func penalties for hard fork

This commit is contained in:
Nguyen Ba Tam 2019-02-22 17:05:03 +07:00
parent e90141a3ba
commit ba55451142
12 changed files with 173 additions and 213 deletions

View file

@ -25,9 +25,12 @@ import (
var ( var (
dir = flag.String("dir", "", "dir to mainet chain data") dir = flag.String("dir", "", "dir to mainet chain data")
cacheSize = flag.Int("size", 1000000, "dir to mainet chain data") cacheSize = flag.Int("size", 1000000, "dir to mainet chain data")
file = flag.String("file", "", "dir to mainet chain data")
) )
type TrieRoot struct {
trie *trie.SecureTrie
number uint64
}
type StateNode struct { type StateNode struct {
node trie.Node node trie.Node
path []byte path []byte
@ -45,7 +48,7 @@ var cleanAddress = []common.Address{common.HexToAddress(common.BlockSigners)}
var cache *lru.Cache var cache *lru.Cache
var finish = int32(0) var finish = int32(0)
var running = true var running = true
var stateRoots = make(chan *trie.SecureTrie) var stateRoots = make(chan TrieRoot)
func main() { func main() {
flag.Parse() flag.Parse()
@ -63,9 +66,8 @@ func main() {
if err != nil { if err != nil {
continue continue
} }
fmt.Println(time.Now().Format(time.RFC3339), "Found a trie state root at block ", i, "state root ", root.Hex())
if running { if running {
stateRoots <- trieRoot stateRoots <- TrieRoot{trieRoot, i}
} else { } else {
break break
} }
@ -78,22 +80,24 @@ func main() {
atomic.StoreInt32(&finish, 1) atomic.StoreInt32(&finish, 1)
if running { if running {
for _, address := range cleanAddress { for _, address := range cleanAddress {
enc := trieRoot.Get(address.Bytes()) enc := trieRoot.trie.Get(address.Bytes())
var data state.Account var data state.Account
rlp.DecodeBytes(enc, &data) rlp.DecodeBytes(enc, &data)
fmt.Println(time.Now().Format(time.RFC3339), "Start clean state address ", address.Hex(), " at state root ", common.Bytes2Hex(trieRoot.Root()), "state address root", data.Root.Hex()) fmt.Println(time.Now().Format(time.RFC3339), "Start clean state address ", address.Hex(), " at block ", trieRoot.number)
signerRoot, err := resolveHash(data.Root[:], lddb.LDB()) signerRoot, err := resolveHash(data.Root[:], lddb.LDB())
if err != nil { if err != nil {
fmt.Println(time.Now().Format(time.RFC3339), "Not found clean state address ", address.Hex(), " at state root ", common.Bytes2Hex(trieRoot.Root()), "state address root", data.Root.Hex()) fmt.Println(time.Now().Format(time.RFC3339), "Not found clean state address ", address.Hex(), " at block ", trieRoot.number)
continue continue
} }
batch := new(leveldb.Batch) batch := new(leveldb.Batch)
list := []*StateNode{&StateNode{node: signerRoot}} count := 1
list := []*StateNode{{node: signerRoot}}
for len(list) > 0 { for len(list) > 0 {
newList, total := findNewNodes(list, lddb.LDB(), batch) newList, total := findNewNodes(list, lddb.LDB(), batch)
count = count + 17*len(newList)
list = removeNodesNil(newList, total) list = removeNodesNil(newList, total)
} }
fmt.Println(time.Now().Format(time.RFC3339), "Finish clean state address ", address.Hex(), " at state root ", common.Bytes2Hex(trieRoot.Root()), "state address root", data.Root.Hex()) fmt.Println(time.Now().Format(time.RFC3339), "Finish clean state address ", address.Hex(), " at block ", trieRoot.number, " keys ", count)
err = lddb.LDB().Write(batch, nil) err = lddb.LDB().Write(batch, nil)
if err != nil { if err != nil {
fmt.Println(time.Now().Format(time.RFC3339), "Write batch leveldb error", err) fmt.Println(time.Now().Format(time.RFC3339), "Write batch leveldb error", err)
@ -133,10 +137,7 @@ func catchEventInterupt(db *leveldb.DB) {
running = false running = false
if atomic.LoadInt32(&finish) == 0 { if atomic.LoadInt32(&finish) == 0 {
close(stateRoots) close(stateRoots)
fmt.Println(time.Now(), "interrupt compact")
db.CompactRange(util.Range{})
db.Close() db.Close()
fmt.Println(time.Now(), "interrupt end")
os.Exit(1) os.Exit(1)
} }
} }
@ -169,7 +170,7 @@ func getAllChilds(n StateNode, db *leveldb.DB) ([17]*StateNode, error) {
if err == nil { if err == nil {
childs[i] = &StateNode{node: childNode, path: append(n.path, byte(i))} childs[i] = &StateNode{node: childNode, path: append(n.path, byte(i))}
} else if err != nil { } else if err != nil {
_, ok := err.(*trie.MissingNodeError); _, ok := err.(*trie.MissingNodeError)
if !ok { if !ok {
return childs, err return childs, err
} }
@ -186,7 +187,7 @@ func getAllChilds(n StateNode, db *leveldb.DB) ([17]*StateNode, error) {
if err == nil { if err == nil {
childs[0] = &StateNode{node: childNode, path: append(n.path, node.Key...)} childs[0] = &StateNode{node: childNode, path: append(n.path, node.Key...)}
} else if err != nil { } else if err != nil {
_, ok := err.(*trie.MissingNodeError); _, ok := err.(*trie.MissingNodeError)
if !ok { if !ok {
return childs, err return childs, err
} }
@ -234,8 +235,7 @@ func findNewNodes(nodes []*StateNode, db *leveldb.DB, batchlvdb *leveldb.Batch)
childNodes := make([][17]*StateNode, length) childNodes := make([][17]*StateNode, length)
results := make(chan ResultProcessNode) results := make(chan ResultProcessNode)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
wgResults := sync.WaitGroup{} wg.Add(length)
wg.Add(nWorker)
for i := 0; i < nWorker; i++ { for i := 0; i < nWorker; i++ {
from := i * chunkSize from := i * chunkSize
to := from + chunkSize to := from + chunkSize
@ -245,15 +245,12 @@ func findNewNodes(nodes []*StateNode, db *leveldb.DB, batchlvdb *leveldb.Batch)
go func(from int, to int) { go func(from int, to int) {
for j := from; j < to; j++ { for j := from; j < to; j++ {
childs, keys, number := processNodes(*nodes[j], db) childs, keys, number := processNodes(*nodes[j], db)
wgResults.Add(1)
go func(result ResultProcessNode) { go func(result ResultProcessNode) {
results <- result results <- result
}(ResultProcessNode{j, number, childs, keys}) }(ResultProcessNode{j, number, childs, keys})
} }
wg.Done()
}(from, to) }(from, to)
} }
wg.Wait()
total := 0 total := 0
go func() { go func() {
for result := range results { for result := range results {
@ -264,10 +261,10 @@ func findNewNodes(nodes []*StateNode, db *leveldb.DB, batchlvdb *leveldb.Batch)
batchlvdb.Delete(*key) batchlvdb.Delete(*key)
} }
} }
wgResults.Done() wg.Done()
} }
}() }()
wgResults.Wait() wg.Wait()
close(results) close(results)
return childNodes, total return childNodes, total
} }

View file

@ -18,11 +18,12 @@ const (
LimitThresholdNonceInQueue = 10 LimitThresholdNonceInQueue = 10
DefaultMinGasPrice = 2500 DefaultMinGasPrice = 2500
MergeSignRange = 15 MergeSignRange = 15
RangeReturnSigner = 90 RangeReturnSigner = 150
MinimunMinerBlockPerEpoch = 1
) )
var TIP2019Block = big.NewInt(1050000) var TIP2019Block = big.NewInt(1050000)
var TIPEVMSignerBlock = big.NewInt(2500000) var TIPSigning = big.NewInt(3000000)
var IsTestnet bool = false var IsTestnet bool = false
var StoreRewardFolder string var StoreRewardFolder string
var RollbackHash Hash var RollbackHash Hash

View file

@ -228,7 +228,7 @@ type Posv struct {
BlockSigners *lru.Cache BlockSigners *lru.Cache
HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{})
HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) HookPenalty func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error)
HookPenaltyTIPEVM func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) HookPenaltyTIPSigning func(chain consensus.ChainReader, header *types.Header, candidate []common.Address) ([]common.Address, error)
HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) HookValidator func(header *types.Header, signers []common.Address) ([]byte, error)
HookVerifyMNs func(header *types.Header, signers []common.Address) error HookVerifyMNs func(header *types.Header, signers []common.Address) error
} }
@ -398,12 +398,12 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.
} }
// If the block is a checkpoint block, verify the signer list // If the block is a checkpoint block, verify the signer list
if number%c.config.Epoch == 0 { if number%c.config.Epoch == 0 {
signers := snap.GetSigners()
penPenalties := []common.Address{} penPenalties := []common.Address{}
if c.HookPenalty != nil || c.HookPenaltyTIPEVM != nil { if c.HookPenalty != nil || c.HookPenaltyTIPSigning != nil {
var penPenalties []common.Address = nil
var err error = nil var err error = nil
if chain.Config().IsTIPEVMSigner(header.Number) { if chain.Config().IsTIPSigning(header.Number) {
penPenalties, err = c.HookPenaltyTIPEVM(chain, number) penPenalties, err = c.HookPenaltyTIPSigning(chain, header, signers)
} else { } else {
penPenalties, err = c.HookPenalty(chain, number) penPenalties, err = c.HookPenalty(chain, number)
} }
@ -418,7 +418,6 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types.
return errInvalidCheckpointPenalties return errInvalidCheckpointPenalties
} }
} }
signers := snap.GetSigners()
signers = common.RemoveItemFromArray(signers, penPenalties) signers = common.RemoveItemFromArray(signers, penPenalties)
for i := 1; i <= common.LimitPenaltyEpoch; i++ { for i := 1; i <= common.LimitPenaltyEpoch; i++ {
if number > uint64(i)*c.config.Epoch { if number > uint64(i)*c.config.Epoch {
@ -795,11 +794,11 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
header.Extra = header.Extra[:extraVanity] header.Extra = header.Extra[:extraVanity]
masternodes := snap.GetSigners() masternodes := snap.GetSigners()
if number >= c.config.Epoch && number%c.config.Epoch == 0 { if number >= c.config.Epoch && number%c.config.Epoch == 0 {
if c.HookPenalty != nil || c.HookPenaltyTIPEVM != nil { if c.HookPenalty != nil || c.HookPenaltyTIPSigning != nil {
var penMasternodes []common.Address = nil var penMasternodes []common.Address = nil
var err error = nil var err error = nil
if chain.Config().IsTIPEVMSigner(header.Number) { if chain.Config().IsTIPSigning(header.Number) {
penMasternodes, err = c.HookPenaltyTIPEVM(chain, number) penMasternodes, err = c.HookPenaltyTIPSigning(chain, header, masternodes)
} else { } else {
penMasternodes, err = c.HookPenalty(chain, number) penMasternodes, err = c.HookPenalty(chain, number)
} }
@ -810,7 +809,7 @@ func (c *Posv) Prepare(chain consensus.ChainReader, header *types.Header) error
// penalize bad masternode(s) // penalize bad masternode(s)
masternodes = common.RemoveItemFromArray(masternodes, penMasternodes) masternodes = common.RemoveItemFromArray(masternodes, penMasternodes)
for _, address := range penMasternodes { for _, address := range penMasternodes {
log.Debug("Penalty status", "address", address, "block number", number) log.Debug("Penalty status", "address", address, "number", number)
} }
header.Penalties = common.ExtractAddressToBytes(penMasternodes) header.Penalties = common.ExtractAddressToBytes(penMasternodes)
} }
@ -1079,15 +1078,15 @@ func (c *Posv) CacheData(header *types.Header, txs []*types.Transaction, receipt
return signTxs return signTxs
} }
func (c *Posv) CacheSigner(header *types.Header, txs []*types.Transaction) []*types.Transaction { func (c *Posv) CacheSigner(hash common.Hash, txs []*types.Transaction) []*types.Transaction {
signTxs := []*types.Transaction{} signTxs := []*types.Transaction{}
for _, tx := range txs { for _, tx := range txs {
if tx.IsSigningTransaction() { if tx.IsSigningTransaction() {
signTxs = append(signTxs, tx) signTxs = append(signTxs, tx)
} }
} }
log.Debug("Save tx signers to cache", "hash", header.Hash().String(), "number", header.Number, "len(txs)", len(signTxs)) log.Debug("Save tx signers to cache", "hash", hash.String(), "len(txs)", len(signTxs))
c.BlockSigners.Add(header.Hash(), signTxs) c.BlockSigners.Add(hash, signTxs)
return signTxs return signTxs
} }

View file

@ -306,62 +306,6 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte)
return random, nil return random, nil
} }
// Get txw signed for block using cache or block body inside.
func GetSignersSignedAtBlockHash(c *posv.Posv, chain consensus.ChainReader, data map[common.Hash][]common.Address, header *types.Header, curNumber uint64) map[common.Hash][]common.Address {
if signData, ok := c.BlockSigners.Get(header.Hash()); ok {
txs := signData.([]*types.Transaction)
for _, tx := range txs {
blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:])
from := *tx.From()
data[blkHash] = append(data[blkHash], from)
}
} else {
log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", curNumber)
block := chain.GetBlock(header.Hash(), curNumber)
txs := block.Transactions()
receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), curNumber)
var signTxs []*types.Transaction
for _, tx := range txs {
if tx.IsSigningTransaction() {
var b uint
for _, r := range receipts {
if r.TxHash == tx.Hash() {
if len(r.PostState) > 0 {
b = types.ReceiptStatusSuccessful
} else {
b = r.Status
}
break
}
}
if b == types.ReceiptStatusFailed {
continue
}
signTxs = append(signTxs, tx)
blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:])
from := *tx.From()
data[blkHash] = append(data[blkHash], from)
}
}
c.BlockSigners.Add(header.Hash(), signTxs)
}
return data
}
// Get signers list from bytes.
func GetSignersFromBytes(byteHeader []byte) []common.Address {
signers := make([]common.Address, len(byteHeader)/common.AddressLength)
for i := 0; i < len(signers); i++ {
copy(signers[i][:], byteHeader[i*common.AddressLength:])
}
return signers
}
// Calculate reward for reward checkpoint. // Calculate reward for reward checkpoint.
func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, header *types.Header, rCheckpoint uint64, totalSigner *uint64) (map[common.Address]*rewardLog, error) { func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, header *types.Header, rCheckpoint uint64, totalSigner *uint64) (map[common.Address]*rewardLog, error) {
// Not reward for singer of genesis block and only calculate reward at checkpoint block. // Not reward for singer of genesis block and only calculate reward at checkpoint block.
@ -381,11 +325,11 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, header *t
log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i) log.Debug("Failed get from cached", "hash", header.Hash().String(), "number", i)
block := chain.GetBlock(header.Hash(), i) block := chain.GetBlock(header.Hash(), i)
txs := block.Transactions() txs := block.Transactions()
if !chain.Config().IsTIPEVMSigner(header.Number) { if !chain.Config().IsTIPSigning(header.Number) {
receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i) receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i)
signData = c.CacheData(header, txs, receipts); signData = c.CacheData(header, txs, receipts)
} else { } else {
signData = c.CacheSigner(header, txs); signData = c.CacheSigner(header.Hash(), txs)
} }
} }
txs := signData.([]*types.Transaction) txs := signData.([]*types.Transaction)

View file

@ -507,7 +507,7 @@ func (bc *BlockChain) insert(block *types.Block) {
bc.currentBlock.Store(block) bc.currentBlock.Store(block)
// save cache BlockSigners // save cache BlockSigners
if bc.chainConfig.Posv != nil && !bc.chainConfig.IsTIPEVMSigner(block.Number()) { if bc.chainConfig.Posv != nil && !bc.chainConfig.IsTIPSigning(block.Number()) {
engine := bc.Engine().(*posv.Posv) engine := bc.Engine().(*posv.Posv)
engine.CacheData(block.Header(), block.Transactions(), bc.GetReceiptsByHash(block.Hash())) engine.CacheData(block.Header(), block.Transactions(), bc.GetReceiptsByHash(block.Hash()))
} }
@ -1020,9 +1020,9 @@ func (bc *BlockChain) WriteBlockWithState(block *types.Block, receipts []*types.
bc.insert(block) bc.insert(block)
} }
// save cache BlockSigners // save cache BlockSigners
if bc.chainConfig.Posv != nil && bc.chainConfig.IsTIPEVMSigner(block.Number()) { if bc.chainConfig.Posv != nil && bc.chainConfig.IsTIPSigning(block.Number()) {
engine := bc.Engine().(*posv.Posv) engine := bc.Engine().(*posv.Posv)
engine.CacheSigner(block.Header(), block.Transactions()) engine.CacheSigner(block.Header().Hash(), block.Transactions())
} }
bc.futureBlocks.Remove(block.Hash()) bc.futureBlocks.Remove(block.Hash())
return status, nil return status, nil

View file

@ -73,7 +73,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
if p.config.IsTIPEVMSigner(header.Number) { if common.TIPSigning.Cmp(header.Number) == 0 {
statedb.DeleteAddress(common.HexToAddress(common.BlockSigners)) statedb.DeleteAddress(common.HexToAddress(common.BlockSigners))
} }
InitSignerInTransactions(p.config, header, block.Transactions()) InitSignerInTransactions(p.config, header, block.Transactions())
@ -104,7 +104,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 { if p.config.DAOForkSupport && p.config.DAOForkBlock != nil && p.config.DAOForkBlock.Cmp(block.Number()) == 0 {
misc.ApplyDAOHardFork(statedb) misc.ApplyDAOHardFork(statedb)
} }
if p.config.IsTIPEVMSigner(header.Number) { if common.TIPSigning.Cmp(header.Number) == 0 {
statedb.DeleteAddress(common.HexToAddress(common.BlockSigners)) statedb.DeleteAddress(common.HexToAddress(common.BlockSigners))
} }
if cBlock.stop { if cBlock.stop {
@ -138,7 +138,7 @@ func (p *StateProcessor) ProcessBlockNoValidator(cBlock *CalculatedBlock, stated
// for the transaction, gas used and an error if the transaction failed, // for the transaction, gas used and an error if the transaction failed,
// indicating the block was invalid. // indicating the block was invalid.
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) { func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error) {
if tx.To() != nil && tx.To().String() == common.BlockSigners && config.IsTIPEVMSigner(header.Number) { if tx.To() != nil && tx.To().String() == common.BlockSigners && config.IsTIPSigning(header.Number) {
return ApplySignTransaction(config, statedb, header, tx, usedGas) return ApplySignTransaction(config, statedb, header, tx, usedGas)
} }
msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) msg, err := tx.AsMessage(types.MakeSigner(config, header.Number))

View file

@ -219,7 +219,7 @@ type TxPool struct {
wg sync.WaitGroup // for shutdown sync wg sync.WaitGroup // for shutdown sync
homestead bool homestead bool
IsMasterNode func(address common.Address) bool IsSigner func(address common.Address) bool
} }
// NewTxPool creates a new transaction pool to gather, sort and filter inbound // NewTxPool creates a new transaction pool to gather, sort and filter inbound
@ -592,7 +592,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction, local bool) error {
// Drop non-local transactions under our own minimal accepted gas price // Drop non-local transactions under our own minimal accepted gas price
local = local || pool.locals.contains(from) // account may be local even if the transaction arrived from the network local = local || pool.locals.contains(from) // account may be local even if the transaction arrived from the network
if !local && pool.gasPrice.Cmp(tx.GasPrice()) > 0 { if !local && pool.gasPrice.Cmp(tx.GasPrice()) > 0 {
if !tx.IsSpecialTransaction() || (pool.IsMasterNode != nil && !pool.IsMasterNode(from)) { if !tx.IsSpecialTransaction() || (pool.IsSigner != nil && !pool.IsSigner(from)) {
return ErrUnderpriced return ErrUnderpriced
} }
} }
@ -661,7 +661,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) {
return false, err return false, err
} }
from, _ := types.Sender(pool.signer, tx) // already validated from, _ := types.Sender(pool.signer, tx) // already validated
if tx.IsSpecialTransaction() && pool.IsMasterNode != nil && pool.IsMasterNode(from) && pool.pendingState.GetNonce(from) == tx.Nonce() { if tx.IsSpecialTransaction() && pool.IsSigner != nil && pool.IsSigner(from) && pool.pendingState.GetNonce(from) == tx.Nonce() {
return pool.promoteSpecialTx(from, tx) return pool.promoteSpecialTx(from, tx)
} }
// If the transaction pool is full, discard underpriced transactions // If the transaction pool is full, discard underpriced transactions

View file

@ -20,7 +20,10 @@ package eth
import ( import (
"errors" "errors"
"fmt" "fmt"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/rlp"
"math/big" "math/big"
"runtime" "runtime"
"sync" "sync"
@ -30,7 +33,6 @@ import (
"bytes" "bytes"
"github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/ethash" "github.com/ethereum/go-ethereum/consensus/ethash"
"github.com/ethereum/go-ethereum/consensus/posv" "github.com/ethereum/go-ethereum/consensus/posv"
@ -41,7 +43,6 @@ import (
"github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice" "github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/event"
@ -51,7 +52,6 @@ import (
"github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc" "github.com/ethereum/go-ethereum/rpc"
) )
@ -208,12 +208,13 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
if eth.chainConfig.Posv != nil { if eth.chainConfig.Posv != nil {
c := eth.engine.(*posv.Posv) c := eth.engine.(*posv.Posv)
signHook := func(block *types.Block) error { signHook := func(block *types.Block) error {
ok, err := eth.ValidateMasternode() eb, err := eth.Etherbase()
if err != nil { if err != nil {
return fmt.Errorf("Can't verify masternode permission: %v", err) log.Error("Cannot get etherbase for append m2 header", "err", err)
return fmt.Errorf("etherbase missing: %v", err)
} }
ok := eth.txPool.IsSigner != nil && eth.txPool.IsSigner(eb)
if !ok { if !ok {
// silently return as this node doesn't have masternode permission to sign block
return nil return nil
} }
if block.NumberU64()%common.MergeSignRange == 0 || !eth.chainConfig.IsTIP2019(block.Number()) { if block.NumberU64()%common.MergeSignRange == 0 || !eth.chainConfig.IsTIP2019(block.Number()) {
@ -274,7 +275,6 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
start := time.Now() start := time.Now()
prevHeader := chain.GetHeaderByNumber(prevEpoc) prevHeader := chain.GetHeaderByNumber(prevEpoc)
penSigners := c.GetMasternodes(chain, prevHeader) penSigners := c.GetMasternodes(chain, prevHeader)
signedSigners := make(map[common.Address]*big.Int)
if len(penSigners) > 0 { if len(penSigners) > 0 {
// Loop for each block to check missing sign. // Loop for each block to check missing sign.
for i := prevEpoc; i < blockNumberEpoc; i++ { for i := prevEpoc; i < blockNumberEpoc; i++ {
@ -283,64 +283,27 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
bhash := bheader.Hash() bhash := bheader.Hash()
block := chain.GetBlock(bhash, i) block := chain.GetBlock(bhash, i)
if len(penSigners) > 0 { if len(penSigners) > 0 {
signer, err := c.RecoverSigner(block.Header()) signedMasternodes, err := contracts.GetSignersFromContract(canonicalState, block)
if err != nil { if err != nil {
return nil, err return nil, err
} }
for _, addr := range penSigners { if len(signedMasternodes) > 0 {
if signer == addr { // Check signer signed?
signedSigners[signer] = signedSigners[signer].Add(signedSigners[signer], big.NewInt(1)) for _, signed := range signedMasternodes {
for j, addr := range penSigners {
if signed == addr {
// Remove it from dupSigners.
penSigners = append(penSigners[:j], penSigners[j+1:]...)
}
}
} }
} }
} else { } else {
break break
} }
} }
if len(signedSigners) > 0 {
for signer, totalSign := range signedSigners {
if totalSign.Cmp(big.NewInt(4)) >= 0 {
for j, addr := range penSigners {
if signer == addr {
// If create block above 4 times then remove it from penSigners.
penSigners = append(penSigners[:j], penSigners[j+1:]...)
} }
} }
}
}
}
}
}
// Check penalty signer return chain.
prevSigners := contracts.GetSignersFromBytes(prevHeader.Penalties)
if len(prevSigners) > 0 {
startCheck := blockNumberEpoc - common.RangeReturnSigner
data := make(map[common.Hash][]common.Address)
mapBlkHash := map[uint64]common.Hash{}
for curNumber := startCheck; curNumber < blockNumberEpoc; curNumber++ {
signers := make(map[common.Hash][]common.Address)
header := chain.GetHeaderByNumber(curNumber)
mapBlkHash[curNumber] = header.Hash()
data = contracts.GetSignersSignedAtBlockHash(c, chain, signers, header, curNumber)
}
for _, blkHash := range mapBlkHash {
signers := data[blkHash]
for j, addr := range prevSigners {
for _, signer := range signers {
if signer == addr {
// If create block above 4 times then remove it from penSigners.
prevSigners = append(prevSigners[:j], prevSigners[j+1:]...)
}
}
}
}
if len(prevSigners) > 0 {
penSigners = append(penSigners, prevSigners...)
}
}
log.Debug("Time Calculated HookPenalty ", "block", blockNumberEpoc, "time", common.PrettyDuration(time.Since(start))) log.Debug("Time Calculated HookPenalty ", "block", blockNumberEpoc, "time", common.PrettyDuration(time.Since(start)))
return penSigners, nil return penSigners, nil
} }
@ -348,42 +311,94 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
} }
// Hook scans for bad masternodes and decide to penalty them // Hook scans for bad masternodes and decide to penalty them
c.HookPenaltyTIPEVM = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) { c.HookPenaltyTIPSigning = func(chain consensus.ChainReader, header *types.Header, candidates []common.Address) ([]common.Address, error) {
canonicalState, err := eth.blockchain.State() prevEpoc := header.Number.Uint64() - chain.Config().Posv.Epoch
if canonicalState == nil || err != nil { combackEpoch := uint64(0)
log.Crit("Can't get state at head of canonical chain", "head number", eth.blockchain.CurrentHeader().Number.Uint64(), "err", err) comebackLength := uint64((common.LimitPenaltyEpoch + 1) * chain.Config().Posv.Epoch)
if header.Number.Uint64() > comebackLength {
combackEpoch = header.Number.Uint64() - comebackLength
} }
prevEpoc := blockNumberEpoc - chain.Config().Posv.Epoch
if prevEpoc >= 0 { if prevEpoc >= 0 {
start := time.Now() start := time.Now()
listBlockHash := make([]common.Hash, chain.Config().Posv.Epoch)
// get list block hash & stats total created block
statMiners := make(map[common.Address]int)
listBlockHash[0] = header.ParentHash
parentnumber := header.Number.Uint64() - 1
parentHash := header.ParentHash
for i := uint64(1); i < chain.Config().Posv.Epoch; i++ {
parentHeader := chain.GetHeader(parentHash, parentnumber)
miner, _ := c.RecoverSigner(parentHeader)
value, exist := statMiners[miner]
if exist {
value = value + 1
} else {
value = 1
}
statMiners[miner] = value
parentHash = parentHeader.ParentHash
parentnumber--
listBlockHash[i] = parentHash
}
// add list not miner to penalties
prevHeader := chain.GetHeaderByNumber(prevEpoc) prevHeader := chain.GetHeaderByNumber(prevEpoc)
penSigners := c.GetMasternodes(chain, prevHeader) preMasternodes := c.GetMasternodes(chain, prevHeader)
if len(penSigners) > 0 { penalties := []common.Address{}
// Loop for each block to check missing sign. for miner, total := range statMiners {
blockHash := map[common.Hash]bool{} if total < common.MinimunMinerBlockPerEpoch {
for i := prevEpoc; i < blockNumberEpoc; i++ { log.Debug("Find a node not enough requirement create block", "addr", miner.Hex(), "total", total)
if len(penSigners) > 0 { penalties = append(penalties, miner)
bheader := chain.GetHeaderByNumber(i) }
bhash := bheader.Hash() }
if i%common.MergeSignRange == 0 { for _, addr := range preMasternodes {
blockHash[bhash] = true if _, exist := statMiners[addr]; !exist {
log.Debug("Find a node don't create block", "addr", addr.Hex())
penalties = append(penalties, addr)
}
}
// get list check penalties signing block & list master nodes wil comeback
penComebacks := []common.Address{}
if combackEpoch > 0 {
combackHeader := chain.GetHeaderByNumber(combackEpoch)
penalties := common.ExtractAddressFromBytes(combackHeader.Penalties)
for _, penaltie := range penalties {
for _, addr := range candidates {
if penaltie == addr {
penComebacks = append(penComebacks, penaltie)
}
}
}
}
// Loop for each block to check missing sign. with comeback nodes
mapBlockHash := map[common.Hash]bool{}
for i := common.RangeReturnSigner - 1; i >= 0; i-- {
if len(penComebacks) > 0 {
blockNumber := header.Number.Uint64() - uint64(i) - 1
bhash := listBlockHash[i]
if blockNumber%common.MergeSignRange == 0 {
mapBlockHash[bhash] = true
} }
signData, ok := c.BlockSigners.Get(bhash) signData, ok := c.BlockSigners.Get(bhash)
if !ok { if !ok {
block := chain.GetBlock(bhash, i) block := chain.GetBlock(bhash, blockNumber)
txs := block.Transactions() txs := block.Transactions()
signData = c.CacheSigner(bheader, txs); signData = c.CacheSigner(bhash, txs)
} }
txs := signData.([]*types.Transaction) txs := signData.([]*types.Transaction)
// Check signer signed? // Check signer signed?
for _, tx := range txs { for _, tx := range txs {
blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:])
from := *tx.From() from := *tx.From()
if blockHash[blkHash] == true { if mapBlockHash[blkHash] {
for j, addr := range penSigners { for j, addr := range penComebacks {
if from == addr { if from == addr {
// Remove it from dupSigners. // Remove it from dupSigners.
penSigners = append(penSigners[:j], penSigners[j+1:]...) penComebacks = append(penComebacks[:j], penComebacks[j+1:]...)
break break
} }
} }
@ -393,9 +408,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
break break
} }
} }
}
log.Debug("Time Calculated HookPenaltyTIPEVM ", "block", blockNumberEpoc, "time", common.PrettyDuration(time.Since(start))) log.Debug("Time Calculated HookPenaltyTIPSigning ", "block", header.Number, "hash", header.Hash().Hex(), "pen comeback nodes", len(penComebacks), "not enough miner", len(penalties), "time", common.PrettyDuration(time.Since(start)))
return penSigners, nil penalties = append(penalties, penComebacks...)
return penComebacks, nil
} }
return []common.Address{}, nil return []common.Address{}, nil
} }
@ -473,7 +490,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
return nil return nil
} }
eth.txPool.IsMasterNode = func(address common.Address) bool { eth.txPool.IsSigner = func(address common.Address) bool {
currentHeader := eth.blockchain.CurrentHeader() currentHeader := eth.blockchain.CurrentHeader()
header := currentHeader header := currentHeader
// Sometimes, the latest block hasn't been inserted to chain yet // Sometimes, the latest block hasn't been inserted to chain yet
@ -721,7 +738,9 @@ func (s *Ethereum) StartStaking(local bool) error {
return nil return nil
} }
func (s *Ethereum) StopStaking() { s.miner.Stop() } func (s *Ethereum) StopStaking() {
s.miner.Stop()
}
func (s *Ethereum) IsStaking() bool { return s.miner.Mining() } func (s *Ethereum) IsStaking() bool { return s.miner.Mining() }
func (s *Ethereum) Miner() *miner.Miner { return s.miner } func (s *Ethereum) Miner() *miner.Miner { return s.miner }

View file

@ -963,7 +963,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlockSigners(b *types.Block, ctx context.
if prevCheckpointBlock != nil { if prevCheckpointBlock != nil {
masternodes := engine.GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header(), blockNumber, s.b.ChainConfig().Posv.Epoch) masternodes := engine.GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header(), blockNumber, s.b.ChainConfig().Posv.Epoch)
signedBlock, _ := s.b.BlockByNumber(ctx, rpc.BlockNumber(signedBlockNumber)) signedBlock, _ := s.b.BlockByNumber(ctx, rpc.BlockNumber(signedBlockNumber))
if s.b.ChainConfig().IsTIPEVMSigner(latestBlockNumber) { if s.b.ChainConfig().IsTIPSigning(latestBlockNumber) {
signers, err = GetSignersFromBlocks(s.b, signedBlock.NumberU64(), signedBlock.Hash(), masternodes) signers, err = GetSignersFromBlocks(s.b, signedBlock.NumberU64(), signedBlock.Hash(), masternodes)
} else { } else {
signers, err = contracts.GetSignersByExecutingEVM(common.HexToAddress(common.BlockSigners), client, signedBlock.Hash()) signers, err = contracts.GetSignersByExecutingEVM(common.HexToAddress(common.BlockSigners), client, signedBlock.Hash())
@ -1662,7 +1662,7 @@ func GetSignersFromBlocks(b Backend, blockNumber uint64, blockHash common.Hash,
for _, signtx := range signTxs { for _, signtx := range signTxs {
blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:]) blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:])
from := *signtx.From() from := *signtx.From()
if blkHash == blockHash && mapMN[from] == true { if blkHash == blockHash && mapMN[from] {
addrs = append(addrs, from) addrs = append(addrs, from)
delete(mapMN, from) delete(mapMN, from)
} }

View file

@ -584,7 +584,7 @@ func (self *worker) commitNewWork() {
if self.config.DAOForkSupport && self.config.DAOForkBlock != nil && self.config.DAOForkBlock.Cmp(header.Number) == 0 { if self.config.DAOForkSupport && self.config.DAOForkBlock != nil && self.config.DAOForkBlock.Cmp(header.Number) == 0 {
misc.ApplyDAOHardFork(work.state) misc.ApplyDAOHardFork(work.state)
} }
if self.config.IsTIPEVMSigner(header.Number) { if common.TIPSigning.Cmp(header.Number) == 0 {
work.state.DeleteAddress(common.HexToAddress(common.BlockSigners)) work.state.DeleteAddress(common.HexToAddress(common.BlockSigners))
} }
// won't grasp txs at checkpoint // won't grasp txs at checkpoint
@ -677,7 +677,7 @@ func (env *Work) commitTransactions(mux *event.TypeMux, txs *types.TransactionsB
} }
if tx.To().Hex() == common.BlockSigners { if tx.To().Hex() == common.BlockSigners {
if len(tx.Data()) < 68 { if len(tx.Data()) < 68 {
log.Trace("Data special transaction invalid lenght", "hash", tx.Hash(), "data", len(tx.Data())) log.Trace("Data special transaction invalid length", "hash", tx.Hash(), "data", len(tx.Data()))
continue continue
} }
blkNumber := binary.BigEndian.Uint64(tx.Data()[8:40]) blkNumber := binary.BigEndian.Uint64(tx.Data()[8:40])

View file

@ -217,8 +217,8 @@ func (c *ChainConfig) IsTIP2019(num *big.Int) bool {
return isForked(common.TIP2019Block, num) return isForked(common.TIP2019Block, num)
} }
func (c *ChainConfig) IsTIPEVMSigner(num *big.Int) bool { func (c *ChainConfig) IsTIPSigning(num *big.Int) bool {
return isForked(common.TIPEVMSignerBlock, num) return isForked(common.TIPSigning, num)
} }
// GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice). // GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice).