From ba554511429b54b287a17e90bb98c18d02edfee6 Mon Sep 17 00:00:00 2001 From: Nguyen Ba Tam Date: Fri, 22 Feb 2019 17:05:03 +0700 Subject: [PATCH] create new func penalties for hard fork --- cmd/tomoclean/main.go | 43 ++++---- common/constants.go | 5 +- consensus/posv/posv.go | 31 +++--- contracts/utils.go | 62 +----------- core/blockchain.go | 6 +- core/state_processor.go | 6 +- core/tx_pool.go | 8 +- eth/backend.go | 211 ++++++++++++++++++++++------------------ internal/ethapi/api.go | 4 +- miner/worker.go | 4 +- params/config.go | 4 +- trie/node.go | 2 +- 12 files changed, 173 insertions(+), 213 deletions(-) diff --git a/cmd/tomoclean/main.go b/cmd/tomoclean/main.go index 991339ee66..bd41f9234c 100644 --- a/cmd/tomoclean/main.go +++ b/cmd/tomoclean/main.go @@ -25,9 +25,12 @@ import ( var ( dir = flag.String("dir", "", "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 { node trie.Node path []byte @@ -45,7 +48,7 @@ var cleanAddress = []common.Address{common.HexToAddress(common.BlockSigners)} var cache *lru.Cache var finish = int32(0) var running = true -var stateRoots = make(chan *trie.SecureTrie) +var stateRoots = make(chan TrieRoot) func main() { flag.Parse() @@ -63,10 +66,9 @@ func main() { if err != nil { continue } - fmt.Println(time.Now().Format(time.RFC3339), "Found a trie state root at block ", i, "state root ", root.Hex()) if running { - stateRoots <- trieRoot - }else { + stateRoots <- TrieRoot{trieRoot, i} + } else { break } } @@ -78,29 +80,31 @@ func main() { atomic.StoreInt32(&finish, 1) if running { for _, address := range cleanAddress { - enc := trieRoot.Get(address.Bytes()) + enc := trieRoot.trie.Get(address.Bytes()) var data state.Account 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()) 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 } batch := new(leveldb.Batch) - list := []*StateNode{&StateNode{node: signerRoot}} + count := 1 + list := []*StateNode{{node: signerRoot}} for len(list) > 0 { newList, total := findNewNodes(list, lddb.LDB(), batch) + count = count + 17*len(newList) 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) if err != nil { fmt.Println(time.Now().Format(time.RFC3339), "Write batch leveldb error", err) os.Exit(1) } } - }else { + } else { break } atomic.StoreInt32(&finish, 0) @@ -133,10 +137,7 @@ func catchEventInterupt(db *leveldb.DB) { running = false if atomic.LoadInt32(&finish) == 0 { close(stateRoots) - fmt.Println(time.Now(), "interrupt compact") - db.CompactRange(util.Range{}) db.Close() - fmt.Println(time.Now(), "interrupt end") os.Exit(1) } } @@ -169,7 +170,7 @@ func getAllChilds(n StateNode, db *leveldb.DB) ([17]*StateNode, error) { if err == nil { childs[i] = &StateNode{node: childNode, path: append(n.path, byte(i))} } else if err != nil { - _, ok := err.(*trie.MissingNodeError); + _, ok := err.(*trie.MissingNodeError) if !ok { return childs, err } @@ -186,7 +187,7 @@ func getAllChilds(n StateNode, db *leveldb.DB) ([17]*StateNode, error) { if err == nil { childs[0] = &StateNode{node: childNode, path: append(n.path, node.Key...)} } else if err != nil { - _, ok := err.(*trie.MissingNodeError); + _, ok := err.(*trie.MissingNodeError) if !ok { return childs, err } @@ -234,8 +235,7 @@ func findNewNodes(nodes []*StateNode, db *leveldb.DB, batchlvdb *leveldb.Batch) childNodes := make([][17]*StateNode, length) results := make(chan ResultProcessNode) wg := sync.WaitGroup{} - wgResults := sync.WaitGroup{} - wg.Add(nWorker) + wg.Add(length) for i := 0; i < nWorker; i++ { from := i * chunkSize to := from + chunkSize @@ -245,15 +245,12 @@ func findNewNodes(nodes []*StateNode, db *leveldb.DB, batchlvdb *leveldb.Batch) go func(from int, to int) { for j := from; j < to; j++ { childs, keys, number := processNodes(*nodes[j], db) - wgResults.Add(1) go func(result ResultProcessNode) { results <- result }(ResultProcessNode{j, number, childs, keys}) } - wg.Done() }(from, to) } - wg.Wait() total := 0 go func() { for result := range results { @@ -264,10 +261,10 @@ func findNewNodes(nodes []*StateNode, db *leveldb.DB, batchlvdb *leveldb.Batch) batchlvdb.Delete(*key) } } - wgResults.Done() + wg.Done() } }() - wgResults.Wait() + wg.Wait() close(results) return childNodes, total } diff --git a/common/constants.go b/common/constants.go index 701a252eb9..7c66a44368 100644 --- a/common/constants.go +++ b/common/constants.go @@ -18,11 +18,12 @@ const ( LimitThresholdNonceInQueue = 10 DefaultMinGasPrice = 2500 MergeSignRange = 15 - RangeReturnSigner = 90 + RangeReturnSigner = 150 + MinimunMinerBlockPerEpoch = 1 ) var TIP2019Block = big.NewInt(1050000) -var TIPEVMSignerBlock = big.NewInt(2500000) +var TIPSigning = big.NewInt(3000000) var IsTestnet bool = false var StoreRewardFolder string var RollbackHash Hash diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index 3ccdb81419..f11e8b3455 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -227,10 +227,10 @@ type Posv struct { BlockSigners *lru.Cache 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) - HookPenaltyTIPEVM func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) - HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) - HookVerifyMNs func(header *types.Header, signers []common.Address) error + HookPenalty 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) + HookVerifyMNs func(header *types.Header, signers []common.Address) error } // New creates a PoSV proof-of-stake-voting consensus engine with the initial @@ -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 number%c.config.Epoch == 0 { + signers := snap.GetSigners() penPenalties := []common.Address{} - if c.HookPenalty != nil || c.HookPenaltyTIPEVM != nil { - var penPenalties []common.Address = nil + if c.HookPenalty != nil || c.HookPenaltyTIPSigning != nil { var err error = nil - if chain.Config().IsTIPEVMSigner(header.Number) { - penPenalties, err = c.HookPenaltyTIPEVM(chain, number) + if chain.Config().IsTIPSigning(header.Number) { + penPenalties, err = c.HookPenaltyTIPSigning(chain, header, signers) } else { penPenalties, err = c.HookPenalty(chain, number) } @@ -418,7 +418,6 @@ func (c *Posv) verifyCascadingFields(chain consensus.ChainReader, header *types. return errInvalidCheckpointPenalties } } - signers := snap.GetSigners() signers = common.RemoveItemFromArray(signers, penPenalties) for i := 1; i <= common.LimitPenaltyEpoch; i++ { 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] masternodes := snap.GetSigners() 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 err error = nil - if chain.Config().IsTIPEVMSigner(header.Number) { - penMasternodes, err = c.HookPenaltyTIPEVM(chain, number) + if chain.Config().IsTIPSigning(header.Number) { + penMasternodes, err = c.HookPenaltyTIPSigning(chain, header, masternodes) } else { 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) masternodes = common.RemoveItemFromArray(masternodes, 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) } @@ -1079,15 +1078,15 @@ func (c *Posv) CacheData(header *types.Header, txs []*types.Transaction, receipt 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{} for _, tx := range txs { if tx.IsSigningTransaction() { signTxs = append(signTxs, tx) } } - log.Debug("Save tx signers to cache", "hash", header.Hash().String(), "number", header.Number, "len(txs)", len(signTxs)) - c.BlockSigners.Add(header.Hash(), signTxs) + log.Debug("Save tx signers to cache", "hash", hash.String(), "len(txs)", len(signTxs)) + c.BlockSigners.Add(hash, signTxs) return signTxs } diff --git a/contracts/utils.go b/contracts/utils.go index dfe20de790..b60a6b95de 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -306,62 +306,6 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte) 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. 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. @@ -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) block := chain.GetBlock(header.Hash(), i) txs := block.Transactions() - if !chain.Config().IsTIPEVMSigner(header.Number) { + if !chain.Config().IsTIPSigning(header.Number) { receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i) - signData = c.CacheData(header, txs, receipts); + signData = c.CacheData(header, txs, receipts) } else { - signData = c.CacheSigner(header, txs); + signData = c.CacheSigner(header.Hash(), txs) } } txs := signData.([]*types.Transaction) diff --git a/core/blockchain.go b/core/blockchain.go index ae4536bcaf..ac5518fb08 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -507,7 +507,7 @@ func (bc *BlockChain) insert(block *types.Block) { bc.currentBlock.Store(block) // 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.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) } // 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.CacheSigner(block.Header(), block.Transactions()) + engine.CacheSigner(block.Header().Hash(), block.Transactions()) } bc.futureBlocks.Remove(block.Hash()) return status, nil diff --git a/core/state_processor.go b/core/state_processor.go index d21ecd70f4..c2df09f994 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -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 { misc.ApplyDAOHardFork(statedb) } - if p.config.IsTIPEVMSigner(header.Number) { + if common.TIPSigning.Cmp(header.Number) == 0 { statedb.DeleteAddress(common.HexToAddress(common.BlockSigners)) } 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 { misc.ApplyDAOHardFork(statedb) } - if p.config.IsTIPEVMSigner(header.Number) { + if common.TIPSigning.Cmp(header.Number) == 0 { statedb.DeleteAddress(common.HexToAddress(common.BlockSigners)) } 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, // 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) { - 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) } msg, err := tx.AsMessage(types.MakeSigner(config, header.Number)) diff --git a/core/tx_pool.go b/core/tx_pool.go index c4a777a0fb..3d7be4c11d 100644 --- a/core/tx_pool.go +++ b/core/tx_pool.go @@ -218,8 +218,8 @@ type TxPool struct { wg sync.WaitGroup // for shutdown sync - homestead bool - IsMasterNode func(address common.Address) bool + homestead bool + IsSigner func(address common.Address) bool } // 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 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 !tx.IsSpecialTransaction() || (pool.IsMasterNode != nil && !pool.IsMasterNode(from)) { + if !tx.IsSpecialTransaction() || (pool.IsSigner != nil && !pool.IsSigner(from)) { return ErrUnderpriced } } @@ -661,7 +661,7 @@ func (pool *TxPool) add(tx *types.Transaction, local bool) (bool, error) { return false, err } 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) } // If the transaction pool is full, discard underpriced transactions diff --git a/eth/backend.go b/eth/backend.go index 87896b32cf..16b360978f 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -20,7 +20,10 @@ package eth import ( "errors" "fmt" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/eth/filters" + "github.com/ethereum/go-ethereum/rlp" "math/big" "runtime" "sync" @@ -30,7 +33,6 @@ import ( "bytes" "github.com/ethereum/go-ethereum/accounts" "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/ethash" "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/vm" "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/ethdb" "github.com/ethereum/go-ethereum/event" @@ -51,7 +52,6 @@ import ( "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/rlp" "github.com/ethereum/go-ethereum/rpc" ) @@ -208,12 +208,13 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { if eth.chainConfig.Posv != nil { c := eth.engine.(*posv.Posv) signHook := func(block *types.Block) error { - ok, err := eth.ValidateMasternode() + eb, err := eth.Etherbase() 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 { - // silently return as this node doesn't have masternode permission to sign block return nil } 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() prevHeader := chain.GetHeaderByNumber(prevEpoc) penSigners := c.GetMasternodes(chain, prevHeader) - signedSigners := make(map[common.Address]*big.Int) if len(penSigners) > 0 { // Loop for each block to check missing sign. for i := prevEpoc; i < blockNumberEpoc; i++ { @@ -283,64 +283,27 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { bhash := bheader.Hash() block := chain.GetBlock(bhash, i) if len(penSigners) > 0 { - signer, err := c.RecoverSigner(block.Header()) + signedMasternodes, err := contracts.GetSignersFromContract(canonicalState, block) if err != nil { return nil, err } - for _, addr := range penSigners { - if signer == addr { - signedSigners[signer] = signedSigners[signer].Add(signedSigners[signer], big.NewInt(1)) + 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:]...) + } + } } } } else { 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))) return penSigners, nil } @@ -348,54 +311,108 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { } // Hook scans for bad masternodes and decide to penalty them - c.HookPenaltyTIPEVM = func(chain consensus.ChainReader, blockNumberEpoc uint64) ([]common.Address, error) { - canonicalState, err := eth.blockchain.State() - if canonicalState == nil || err != nil { - log.Crit("Can't get state at head of canonical chain", "head number", eth.blockchain.CurrentHeader().Number.Uint64(), "err", err) + c.HookPenaltyTIPSigning = func(chain consensus.ChainReader, header *types.Header, candidates []common.Address) ([]common.Address, error) { + prevEpoc := header.Number.Uint64() - chain.Config().Posv.Epoch + combackEpoch := uint64(0) + 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 { 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) - penSigners := c.GetMasternodes(chain, prevHeader) - if len(penSigners) > 0 { - // Loop for each block to check missing sign. - blockHash := map[common.Hash]bool{} - for i := prevEpoc; i < blockNumberEpoc; i++ { - if len(penSigners) > 0 { - bheader := chain.GetHeaderByNumber(i) - bhash := bheader.Hash() - if i%common.MergeSignRange == 0 { - blockHash[bhash] = true + preMasternodes := c.GetMasternodes(chain, prevHeader) + penalties := []common.Address{} + for miner, total := range statMiners { + if total < common.MinimunMinerBlockPerEpoch { + log.Debug("Find a node not enough requirement create block", "addr", miner.Hex(), "total", total) + penalties = append(penalties, miner) + } + } + for _, addr := range preMasternodes { + 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) } - signData, ok := c.BlockSigners.Get(bhash) - if !ok { - block := chain.GetBlock(bhash, i) - txs := block.Transactions() - signData = c.CacheSigner(bheader, txs); - } - txs := signData.([]*types.Transaction) - // Check signer signed? - for _, tx := range txs { - blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) - from := *tx.From() - if blockHash[blkHash] == true { - for j, addr := range penSigners { - if from == addr { - // Remove it from dupSigners. - penSigners = append(penSigners[:j], penSigners[j+1:]...) - break - } - } - } - } - } else { - break } } } - log.Debug("Time Calculated HookPenaltyTIPEVM ", "block", blockNumberEpoc, "time", common.PrettyDuration(time.Since(start))) - return penSigners, nil + + // 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) + if !ok { + block := chain.GetBlock(bhash, blockNumber) + txs := block.Transactions() + signData = c.CacheSigner(bhash, txs) + } + txs := signData.([]*types.Transaction) + // Check signer signed? + for _, tx := range txs { + blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) + from := *tx.From() + if mapBlockHash[blkHash] { + for j, addr := range penComebacks { + if from == addr { + // Remove it from dupSigners. + penComebacks = append(penComebacks[:j], penComebacks[j+1:]...) + break + } + } + } + } + } else { + break + } + } + + 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))) + penalties = append(penalties, penComebacks...) + return penComebacks, nil + } return []common.Address{}, nil } @@ -473,7 +490,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { return nil } - eth.txPool.IsMasterNode = func(address common.Address) bool { + eth.txPool.IsSigner = func(address common.Address) bool { currentHeader := eth.blockchain.CurrentHeader() header := currentHeader // Sometimes, the latest block hasn't been inserted to chain yet @@ -721,7 +738,9 @@ func (s *Ethereum) StartStaking(local bool) error { 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) Miner() *miner.Miner { return s.miner } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index dd9928d47b..06827f4834 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -963,7 +963,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlockSigners(b *types.Block, ctx context. if prevCheckpointBlock != nil { masternodes := engine.GetMasternodesFromCheckpointHeader(prevCheckpointBlock.Header(), blockNumber, s.b.ChainConfig().Posv.Epoch) 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) } else { 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 { blkHash := common.BytesToHash(signtx.Data()[len(signtx.Data())-32:]) from := *signtx.From() - if blkHash == blockHash && mapMN[from] == true { + if blkHash == blockHash && mapMN[from] { addrs = append(addrs, from) delete(mapMN, from) } diff --git a/miner/worker.go b/miner/worker.go index 91ee30df56..b3b67b03a1 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -584,7 +584,7 @@ func (self *worker) commitNewWork() { if self.config.DAOForkSupport && self.config.DAOForkBlock != nil && self.config.DAOForkBlock.Cmp(header.Number) == 0 { misc.ApplyDAOHardFork(work.state) } - if self.config.IsTIPEVMSigner(header.Number) { + if common.TIPSigning.Cmp(header.Number) == 0 { work.state.DeleteAddress(common.HexToAddress(common.BlockSigners)) } // 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 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 } blkNumber := binary.BigEndian.Uint64(tx.Data()[8:40]) diff --git a/params/config.go b/params/config.go index a8f4027109..2d275c61f7 100644 --- a/params/config.go +++ b/params/config.go @@ -217,8 +217,8 @@ func (c *ChainConfig) IsTIP2019(num *big.Int) bool { return isForked(common.TIP2019Block, num) } -func (c *ChainConfig) IsTIPEVMSigner(num *big.Int) bool { - return isForked(common.TIPEVMSignerBlock, num) +func (c *ChainConfig) IsTIPSigning(num *big.Int) bool { + return isForked(common.TIPSigning, num) } // GasTable returns the gas table corresponding to the current phase (homestead or homestead reprice). diff --git a/trie/node.go b/trie/node.go index 4b76f2b559..2b70d75314 100644 --- a/trie/node.go +++ b/trie/node.go @@ -43,7 +43,7 @@ type ( Val Node flags nodeFlag } - HashNode []byte + HashNode []byte ValueNode []byte )