From 73efc02259ff9d1ae0bed8a5cc9a228ba1757f60 Mon Sep 17 00:00:00 2001 From: Nguyen Sy Thanh Son <thanhson1085@gmail.com> Date: Thu, 10 Jan 2019 09:50:45 +0000 Subject: [PATCH 1/7] refactor cache BlockSigners --- consensus/posv/posv.go | 50 ++++++------ contracts/utils.go | 108 +++++++++----------------- contracts/validator/validator_test.go | 2 +- eth/backend.go | 2 +- internal/ethapi/api.go | 2 +- 5 files changed, 63 insertions(+), 101 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index f38fb6932e11..d30a4f2b32c2 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -50,7 +50,6 @@ import ( const ( inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory blockSignersCacheLimit = 36000 - votingCacheLimit = 1500000 M2ByteLength = 4 ) @@ -245,7 +244,6 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv { } // Allocate the snapshot caches and create the engine BlockSigners, _ := lru.New(blockSignersCacheLimit) - Votes, _ := lru.New(votingCacheLimit) recents, _ := lru.NewARC(inmemorySnapshots) signatures, _ := lru.NewARC(inmemorySnapshots) validatorSignatures, _ := lru.NewARC(inmemorySnapshots) @@ -255,7 +253,6 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv { db: db, EnableCache: false, BlockSigners: BlockSigners, - Votes: Votes, recents: recents, signatures: signatures, verifiedHeaders: verifiedHeaders, @@ -880,7 +877,7 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state } } - _ = c.cacheData(txs, receipts) + _ = c.cacheData(header, txs, receipts) // the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) @@ -1036,12 +1033,10 @@ func (c *Posv) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Hea return masternodes } -func (c *Posv) cacheData(txs []*types.Transaction, receipts []*types.Receipt) error { +func (c *Posv) cacheData(header *types.Header, txs []*types.Transaction, receipts []*types.Receipt) error { + var signTxs []*types.Transaction for _, tx := range txs { if tx.IsSigningTransaction() { - blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) - from := *tx.From() - var b uint for _, r := range receipts { if r.TxHash == tx.Hash() { @@ -1054,29 +1049,32 @@ func (c *Posv) cacheData(txs []*types.Transaction, receipts []*types.Receipt) er continue } - var lAddr []common.Address - if cached, ok := c.BlockSigners.Get(blkHash); ok { - lAddr = cached.([]common.Address) - lAddr = append(lAddr, from) - } else { - lAddr = []common.Address{from} - } - c.BlockSigners.Add(blkHash, lAddr) - } else { + signTxs = append(signTxs, tx) + } + } - b, addr := tx.IsVotingTransaction() - if b && addr != nil { - var vote common.Vote - vote.Masternode = *addr - vote.Voter = *tx.From() + c.BlockSigners.Add(header.Hash(), signTxs) - log.Debug("Remove from Votes cache ", "Masternode", vote.Masternode.String(), "Voter", vote.Voter.String()) - c.Votes.Remove(vote) + return nil +} + +func (c *Posv) GetSignData(chain consensus.ChainReader, startBlockNumber uint64, endBlockNumber uint64) (map[common.Hash][]common.Address, error) { + data := make(map[common.Hash][]common.Address) + for i := startBlockNumber; i < chain.CurrentHeader().Number.Uint64(); i++ { + block := chain.GetHeaderByNumber(i) + + if signData, ok := c.BlockSigners.Get(block.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 { + return nil, errors.New("Failed get blocksigners from cache") } } - - return nil + return data, nil } // Extract validators from byte array. diff --git a/contracts/utils.go b/contracts/utils.go index d40ab6945f38..078a0b69beba 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -199,23 +199,19 @@ func BuildTxOpeningRandomize(nonce uint64, randomizeAddr common.Address, randomi } // Get signers signed for blockNumber from blockSigner contract. -func GetSignersFromContract(c *posv.Posv, addrBlockSigner common.Address, client bind.ContractBackend, blockHash common.Hash) ([]common.Address, error) { +func GetSignersFromContract(addrBlockSigner common.Address, client bind.ContractBackend, blockHash common.Hash) ([]common.Address, error) { blockSigner, err := contract.NewBlockSigner(addrBlockSigner, client) if err != nil { log.Error("Fail get instance of blockSigner", "error", err) return nil, err } - if caddrs, ok := c.BlockSigners.Get(blockHash); !ok || !c.EnableCache { - opts := new(bind.CallOpts) - addrs, err := blockSigner.GetSigners(opts, blockHash) - if err != nil { - log.Error("Fail get block signers", "error", err) - return nil, err - } - return addrs, nil - } else { - return caddrs.([]common.Address), nil + opts := new(bind.CallOpts) + addrs, err := blockSigner.GetSigners(opts, blockHash) + if err != nil { + log.Error("Fail get block signers", "error", err) + return nil, err } + return addrs, nil } // Get random from randomize contract. @@ -324,7 +320,7 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, blockSign if !c.EnableCache { for i := startBlockNumber; i <= endBlockNumber; i++ { block := chain.GetHeaderByNumber(i) - addrs, err := GetSignersFromContract(c, blockSignerAddr, client, block.Hash()) + addrs, err := GetSignersFromContract(blockSignerAddr, client, block.Hash()) if err != nil { log.Error("Fail to get signers from smartcontract.", "error", err, "blockNumber", i) return nil, err @@ -355,54 +351,39 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, blockSign } } } else { - var wg sync.WaitGroup - squeue := make(chan []common.Address, 1) - wg.Add(int(rCheckpoint)) - - for i := startBlockNumber; i <= endBlockNumber; i++ { - go func(i uint64) { - block := chain.GetHeaderByNumber(i) - addrs, err := GetSignersFromContract(c, blockSignerAddr, client, block.Hash()) - if err != nil { - log.Crit("Fail to get signers from smartcontract.", "error", err, "blockNumber", i) - } - squeue <- addrs - }(i) + data, err := c.GetSignData(chain, startBlockNumber, endBlockNumber) + if err != nil { + log.Crit("Fail to get signers from cache.", "endBlockNumber", startBlockNumber, "startBlockNumber", endBlockNumber) } - fsigner := func() { - for addrs := range squeue { - // Filter duplicate address. - if len(addrs) > 0 { - addrSigners := make(map[common.Address]bool) - for _, masternode := range masternodes { - for _, addr := range addrs { - if addr == masternode { - if _, ok := addrSigners[addr]; !ok { - addrSigners[addr] = true - } - break + for i := startBlockNumber; i <= endBlockNumber; i++ { + block := chain.GetHeaderByNumber(i) + addrs := data[block.Hash()] + // Filter duplicate address. + if len(addrs) > 0 { + addrSigners := make(map[common.Address]bool) + for _, masternode := range masternodes { + for _, addr := range addrs { + if addr == masternode { + if _, ok := addrSigners[addr]; !ok { + addrSigners[addr] = true } + break } } + } - for addr := range addrSigners { - _, exist := signers[addr] - if exist { - signers[addr].Sign++ - } else { - signers[addr] = &rewardLog{1, new(big.Int)} - } - *totalSigner++ + for addr := range addrSigners { + _, exist := signers[addr] + if exist { + signers[addr].Sign++ + } else { + signers[addr] = &rewardLog{1, new(big.Int)} } + *totalSigner++ } - wg.Done() } } - - go fsigner() - - wg.Wait() } } @@ -450,7 +431,7 @@ func GetCandidatesOwnerBySigner(validator *contractValidator.TomoValidator, sign // Calculate reward for holders. func CalculateRewardForHolders(c *posv.Posv, foudationWalletAddr common.Address, validator *contractValidator.TomoValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) (error, map[common.Address]*big.Int) { - rewards, err := GetRewardBalancesRate(c, foudationWalletAddr, signer, calcReward, validator) + rewards, err := GetRewardBalancesRate(foudationWalletAddr, signer, calcReward, validator) if err != nil { return err, nil } @@ -463,7 +444,7 @@ func CalculateRewardForHolders(c *posv.Posv, foudationWalletAddr common.Address, } // Get reward balance rates for master node, founder and holders. -func GetRewardBalancesRate(c *posv.Posv, foudationWalletAddr common.Address, masterAddr common.Address, totalReward *big.Int, validator *contractValidator.TomoValidator) (map[common.Address]*big.Int, error) { +func GetRewardBalancesRate(foudationWalletAddr common.Address, masterAddr common.Address, totalReward *big.Int, validator *contractValidator.TomoValidator) (map[common.Address]*big.Int, error) { owner := GetCandidatesOwnerBySigner(validator, masterAddr) balances := make(map[common.Address]*big.Int) rewardMaster := new(big.Int).Mul(totalReward, new(big.Int).SetInt64(common.RewardMasterPercent)) @@ -484,28 +465,11 @@ func GetRewardBalancesRate(c *posv.Posv, foudationWalletAddr common.Address, mas // Get voters capacities. voterCaps := make(map[common.Address]*big.Int) for _, voteAddr := range voters { - var vote common.Vote var voterCap *big.Int - vote.Masternode = masterAddr - vote.Voter = voteAddr - - if c != nil { - if vCap, ok := c.Votes.Get(vote); ok { - voterCap = vCap.(*big.Int) - } else { - voterCap, err = validator.GetVoterCap(opts, masterAddr, voteAddr) - if err != nil { - log.Crit("Fail to get vote capacity", "error", err) - } - log.Debug("Add to Votes cache ", "vote.Masternode", vote.Masternode.String(), "vote.Voter", vote.Voter.String(), "voterCap", voterCap.String()) - c.Votes.Add(vote, voterCap) - } - } else { - voterCap, err = validator.GetVoterCap(opts, masterAddr, voteAddr) - if err != nil { - log.Crit("Fail to get vote capacity", "error", err) - } + voterCap, err = validator.GetVoterCap(opts, masterAddr, voteAddr) + if err != nil { + log.Crit("Fail to get vote capacity", "error", err) } totalCap.Add(totalCap, voterCap) diff --git a/contracts/validator/validator_test.go b/contracts/validator/validator_test.go index e5df78d42f62..f3896db4b8fa 100644 --- a/contracts/validator/validator_test.go +++ b/contracts/validator/validator_test.go @@ -144,7 +144,7 @@ func TestRewardBalance(t *testing.T) { foundationAddr := common.HexToAddress(common.FoudationAddr) totalReward := new(big.Int).SetInt64(15 * 1000) - rewards, err := contracts.GetRewardBalancesRate(nil, foundationAddr, acc3Addr, totalReward, baseValidator) + rewards, err := contracts.GetRewardBalancesRate(foundationAddr, acc3Addr, totalReward, baseValidator) if err != nil { t.Error("Fail to get reward balances rate.", err) } diff --git a/eth/backend.go b/eth/backend.go index e28231d2fb9f..c3fe173fadc8 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -259,7 +259,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { for i := prevEpoc; i < blockNumberEpoc; i++ { blockHeader := chain.GetHeaderByNumber(i) if len(penSigners) > 0 { - signedMasternodes, err := contracts.GetSignersFromContract(c, blockSignerAddr, client, blockHeader.Hash()) + signedMasternodes, err := contracts.GetSignersFromContract(blockSignerAddr, client, blockHeader.Hash()) if err != nil { return nil, err } diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 2c009c5b90f4..a9a4c816fbcc 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -867,7 +867,7 @@ func (s *PublicBlockChainAPI) rpcOutputBlock(b *types.Block, inclTx bool, fullTx if b.Number().Int64() > 0 { engine := s.b.GetEngine() addrBlockSigner := common.HexToAddress(common.BlockSigners) - signers, err = contracts.GetSignersFromContract(engine.(*posv.Posv), addrBlockSigner, client, b.Hash()) + signers, err = contracts.GetSignersFromContract(addrBlockSigner, client, b.Hash()) if err != nil { log.Error("Fail to get signers from block signer SC.", "error", err) return nil, err From e50c789c77eb28d06815b77a45c225e85d745d0f Mon Sep 17 00:00:00 2001 From: Nguyen Sy Thanh Son <thanhson1085@gmail.com> Date: Fri, 11 Jan 2019 04:58:10 +0000 Subject: [PATCH 2/7] move cache data to insert func --- consensus/posv/posv.go | 7 ++++--- contracts/utils.go | 2 +- core/blockchain.go | 4 ++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index d30a4f2b32c2..893edca3e83a 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -877,7 +877,7 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state } } - _ = c.cacheData(header, txs, receipts) + // _ = c.cacheData(header, txs, receipts) // the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) @@ -1033,7 +1033,7 @@ func (c *Posv) GetMasternodesFromCheckpointHeader(preCheckpointHeader *types.Hea return masternodes } -func (c *Posv) cacheData(header *types.Header, txs []*types.Transaction, receipts []*types.Receipt) error { +func (c *Posv) CacheData(header *types.Header, txs []*types.Transaction, receipts []*types.Receipt) error { var signTxs []*types.Transaction for _, tx := range txs { if tx.IsSigningTransaction() { @@ -1054,6 +1054,7 @@ func (c *Posv) cacheData(header *types.Header, txs []*types.Transaction, receipt } c.BlockSigners.Add(header.Hash(), signTxs) + fmt.Println("Add cache BLockSigners", header.Hash().String(), len(signTxs), c.BlockSigners.Len()) return nil } @@ -1071,7 +1072,7 @@ func (c *Posv) GetSignData(chain consensus.ChainReader, startBlockNumber uint64, data[blkHash] = append(data[blkHash], from) } } else { - return nil, errors.New("Failed get blocksigners from cache") + return nil, errors.New("Failed get blocksigners from cache " + block.Hash().String() + " " + block.Number.String()) } } return data, nil diff --git a/contracts/utils.go b/contracts/utils.go index 078a0b69beba..f085c7b8f39f 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -353,7 +353,7 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, blockSign } else { data, err := c.GetSignData(chain, startBlockNumber, endBlockNumber) if err != nil { - log.Crit("Fail to get signers from cache.", "endBlockNumber", startBlockNumber, "startBlockNumber", endBlockNumber) + log.Crit("Fail to get signers from cache.", "startBlockNumber", startBlockNumber, "endBlockNumber", endBlockNumber, "error", err) } for i := startBlockNumber; i <= endBlockNumber; i++ { diff --git a/core/blockchain.go b/core/blockchain.go index 4d6c2cc01187..5bd0a709be5f 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -506,6 +506,10 @@ func (bc *BlockChain) insert(block *types.Block) { } bc.currentBlock.Store(block) + // save cache BlockSigners + engine := bc.Engine().(*posv.Posv) + engine.CacheData(block.Header(), block.Transactions(), bc.GetReceiptsByHash(block.Hash())) + // If the block is better than our head or is on a different chain, force update heads if updateHeads { bc.hc.SetCurrentHeader(block.Header()) From 5e8df83303eaeb7987e16b6ce05e7958e4df3759 Mon Sep 17 00:00:00 2001 From: Nguyen Sy Thanh Son <thanhson1085@gmail.com> Date: Fri, 11 Jan 2019 07:00:46 +0000 Subject: [PATCH 3/7] read signing data from blocks --- consensus/posv/posv.go | 19 +------- contracts/utils.go | 100 ++++++++++++++++++++--------------------- 2 files changed, 52 insertions(+), 67 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index 893edca3e83a..fcf7d367faee 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -1059,23 +1059,8 @@ func (c *Posv) CacheData(header *types.Header, txs []*types.Transaction, receipt return nil } -func (c *Posv) GetSignData(chain consensus.ChainReader, startBlockNumber uint64, endBlockNumber uint64) (map[common.Hash][]common.Address, error) { - data := make(map[common.Hash][]common.Address) - for i := startBlockNumber; i < chain.CurrentHeader().Number.Uint64(); i++ { - block := chain.GetHeaderByNumber(i) - - if signData, ok := c.BlockSigners.Get(block.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 { - return nil, errors.New("Failed get blocksigners from cache " + block.Hash().String() + " " + block.Number.String()) - } - } - return data, nil +func (c *Posv) GetDb() ethdb.Database { + return c.db } // Extract validators from byte array. diff --git a/contracts/utils.go b/contracts/utils.go index f085c7b8f39f..e554caa65940 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -317,71 +317,71 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, blockSign if len(masternodes) > 0 { - if !c.EnableCache { - for i := startBlockNumber; i <= endBlockNumber; i++ { - block := chain.GetHeaderByNumber(i) - addrs, err := GetSignersFromContract(blockSignerAddr, client, block.Hash()) - if err != nil { - log.Error("Fail to get signers from smartcontract.", "error", err, "blockNumber", i) - return nil, err + data := make(map[common.Hash][]common.Address) + for i := startBlockNumber; i <= chain.CurrentHeader().Number.Uint64(); i++ { + header := chain.GetHeaderByNumber(i) + + 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) } - // Filter duplicate address. - if len(addrs) > 0 { - addrSigners := make(map[common.Address]bool) - for _, masternode := range masternodes { - for _, addr := range addrs { - if addr == masternode { - if _, ok := addrSigners[addr]; !ok { - addrSigners[addr] = true - } + } else { + log.Info("Failed get from cached", "startBlock", startBlockNumber, "endBlock", endBlockNumber) + block := chain.GetBlock(header.Hash(), i) + txs := block.Transactions() + receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i) + + for _, tx := range txs { + if tx.IsSigningTransaction() { + var b uint + for _, r := range receipts { + if r.TxHash == tx.Hash() { + b = r.Status break } } - } - for addr := range addrSigners { - _, exist := signers[addr] - if exist { - signers[addr].Sign++ - } else { - signers[addr] = &rewardLog{1, new(big.Int)} + if b == types.ReceiptStatusFailed { + continue } - *totalSigner++ + + blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) + from := *tx.From() + data[blkHash] = append(data[blkHash], from) } } + } - } else { - data, err := c.GetSignData(chain, startBlockNumber, endBlockNumber) - if err != nil { - log.Crit("Fail to get signers from cache.", "startBlockNumber", startBlockNumber, "endBlockNumber", endBlockNumber, "error", err) - } + } - for i := startBlockNumber; i <= endBlockNumber; i++ { - block := chain.GetHeaderByNumber(i) - addrs := data[block.Hash()] - // Filter duplicate address. - if len(addrs) > 0 { - addrSigners := make(map[common.Address]bool) - for _, masternode := range masternodes { - for _, addr := range addrs { - if addr == masternode { - if _, ok := addrSigners[addr]; !ok { - addrSigners[addr] = true - } - break + for i := startBlockNumber; i <= endBlockNumber; i++ { + block := chain.GetHeaderByNumber(i) + addrs := data[block.Hash()] + // Filter duplicate address. + if len(addrs) > 0 { + addrSigners := make(map[common.Address]bool) + for _, masternode := range masternodes { + for _, addr := range addrs { + if addr == masternode { + if _, ok := addrSigners[addr]; !ok { + addrSigners[addr] = true } + break } } + } - for addr := range addrSigners { - _, exist := signers[addr] - if exist { - signers[addr].Sign++ - } else { - signers[addr] = &rewardLog{1, new(big.Int)} - } - *totalSigner++ + for addr := range addrSigners { + _, exist := signers[addr] + if exist { + signers[addr].Sign++ + } else { + signers[addr] = &rewardLog{1, new(big.Int)} } + *totalSigner++ } } } From f9ae05c5d5b78a067f163a291e2c51e11a4a26d6 Mon Sep 17 00:00:00 2001 From: Nguyen Sy Thanh Son <thanhson1085@gmail.com> Date: Fri, 11 Jan 2019 07:42:30 +0000 Subject: [PATCH 4/7] cache all after 1 epoch --- consensus/posv/posv.go | 12 ++---------- contracts/utils.go | 9 ++++++--- core/blockchain.go | 4 ---- eth/backend.go | 4 +--- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index fcf7d367faee..dd740ce6b584 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -225,7 +225,6 @@ type Posv struct { signFn clique.SignerFn // Signer function to authorize hashes with lock sync.RWMutex // Protects the signer fields - EnableCache bool BlockSigners *lru.Cache Votes *lru.Cache HookReward func(chain consensus.ChainReader, state *state.StateDB, header *types.Header) (error, map[string]interface{}) @@ -251,7 +250,6 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv { return &Posv{ config: &conf, db: db, - EnableCache: false, BlockSigners: BlockSigners, recents: recents, signatures: signatures, @@ -856,12 +854,9 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state number := header.Number.Uint64() rCheckpoint := chain.Config().Posv.RewardCheckpoint - if c.HookReward != nil && number%rCheckpoint == 0 { - if !c.EnableCache && int(c.BlockSigners.Len()) >= int(rCheckpoint*3) { - log.Debug("EnableCache true c.BlockSigners.Len() ", "BlockSigners.Len", c.BlockSigners.Len()) - c.EnableCache = true - } + _ = c.CacheData(header, txs, receipts) + if c.HookReward != nil && number%rCheckpoint == 0 { err, rewards := c.HookReward(chain, state, header) if err != nil { return nil, err @@ -877,8 +872,6 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state } } - // _ = c.cacheData(header, txs, receipts) - // the state remains as is and uncles are dropped header.Root = state.IntermediateRoot(chain.Config().IsEIP158(header.Number)) header.UncleHash = types.CalcUncleHash(nil) @@ -1054,7 +1047,6 @@ func (c *Posv) CacheData(header *types.Header, txs []*types.Transaction, receipt } c.BlockSigners.Add(header.Hash(), signTxs) - fmt.Println("Add cache BLockSigners", header.Hash().String(), len(signTxs), c.BlockSigners.Len()) return nil } diff --git a/contracts/utils.go b/contracts/utils.go index e554caa65940..9fb2203be366 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -306,7 +306,7 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte) } // Calculate reward for reward checkpoint. -func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, blockSignerAddr common.Address, number uint64, rCheckpoint uint64, client bind.ContractBackend, totalSigner *uint64) (map[common.Address]*rewardLog, error) { +func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, number uint64, rCheckpoint uint64, totalSigner *uint64) (map[common.Address]*rewardLog, error) { // Not reward for singer of genesis block and only calculate reward at checkpoint block. prevCheckpoint := number - (rCheckpoint * 2) startBlockNumber := prevCheckpoint + 1 @@ -318,7 +318,7 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, blockSign if len(masternodes) > 0 { data := make(map[common.Hash][]common.Address) - for i := startBlockNumber; i <= chain.CurrentHeader().Number.Uint64(); i++ { + for i := startBlockNumber; i <= prevCheckpoint+(rCheckpoint*2)-1; i++ { header := chain.GetHeaderByNumber(i) if signData, ok := c.BlockSigners.Get(header.Hash()); ok { @@ -329,11 +329,12 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, blockSign data[blkHash] = append(data[blkHash], from) } } else { - log.Info("Failed get from cached", "startBlock", startBlockNumber, "endBlock", endBlockNumber) + log.Info("Failed get from cached", "hash", header.Hash().String(), "number", i) block := chain.GetBlock(header.Hash(), i) txs := block.Transactions() receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i) + var signTxs []*types.Transaction for _, tx := range txs { if tx.IsSigningTransaction() { var b uint @@ -348,11 +349,13 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, blockSign 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) } } diff --git a/core/blockchain.go b/core/blockchain.go index 5bd0a709be5f..4d6c2cc01187 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -506,10 +506,6 @@ func (bc *BlockChain) insert(block *types.Block) { } bc.currentBlock.Store(block) - // save cache BlockSigners - engine := bc.Engine().(*posv.Posv) - engine.CacheData(block.Header(), block.Transactions(), bc.GetReceiptsByHash(block.Hash())) - // If the block is better than our head or is on a different chain, force update heads if updateHeads { bc.hc.SetCurrentHeader(block.Header()) diff --git a/eth/backend.go b/eth/backend.go index c3fe173fadc8..6fb12e08979e 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -300,14 +300,12 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { rewards := make(map[string]interface{}) if number > 0 && number-rCheckpoint > 0 && foudationWalletAddr != (common.Address{}) { start := time.Now() - // Get signers in blockSigner smartcontract. - addr := common.HexToAddress(common.BlockSigners) // Get reward inflation. chainReward := new(big.Int).Mul(new(big.Int).SetUint64(chain.Config().Posv.Reward), new(big.Int).SetUint64(params.Ether)) chainReward = rewardInflation(chainReward, number, common.BlocksPerYear) totalSigner := new(uint64) - signers, err := contracts.GetRewardForCheckpoint(c, chain, addr, number, rCheckpoint, client, totalSigner) + signers, err := contracts.GetRewardForCheckpoint(c, chain, number, rCheckpoint, totalSigner) log.Debug("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start))) if err != nil { log.Crit("Fail to get signers for reward checkpoint", "error", err) From 46c96249bf3b9d8cb806762319f723cf7247c249 Mon Sep 17 00:00:00 2001 From: Nguyen Sy Thanh Son <thanhson1085@gmail.com> Date: Fri, 11 Jan 2019 10:55:02 +0000 Subject: [PATCH 5/7] cache only blocksigners --- consensus/posv/posv.go | 1 - contracts/utils.go | 32 +++++++++++++++----------------- eth/backend.go | 2 +- 3 files changed, 16 insertions(+), 19 deletions(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index dd740ce6b584..ef4b2ae1d0c6 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -226,7 +226,6 @@ type Posv struct { lock sync.RWMutex // Protects the signer fields BlockSigners *lru.Cache - Votes *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) HookValidator func(header *types.Header, signers []common.Address) ([]byte, error) diff --git a/contracts/utils.go b/contracts/utils.go index 9fb2203be366..bdfde9828c31 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -329,31 +329,29 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, number ui data[blkHash] = append(data[blkHash], from) } } else { - log.Info("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) txs := block.Transactions() receipts := core.GetBlockReceipts(c.GetDb(), header.Hash(), i) var signTxs []*types.Transaction for _, tx := range txs { - if tx.IsSigningTransaction() { - var b uint - for _, r := range receipts { - if r.TxHash == tx.Hash() { - b = r.Status - break - } - } - - if b == types.ReceiptStatusFailed { - continue + var b uint + for _, r := range receipts { + if r.TxHash == tx.Hash() { + b = r.Status + break } + } - signTxs = append(signTxs, tx) - blkHash := common.BytesToHash(tx.Data()[len(tx.Data())-32:]) - from := *tx.From() - data[blkHash] = append(data[blkHash], from) + 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) @@ -433,7 +431,7 @@ func GetCandidatesOwnerBySigner(validator *contractValidator.TomoValidator, sign } // Calculate reward for holders. -func CalculateRewardForHolders(c *posv.Posv, foudationWalletAddr common.Address, validator *contractValidator.TomoValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) (error, map[common.Address]*big.Int) { +func CalculateRewardForHolders(foudationWalletAddr common.Address, validator *contractValidator.TomoValidator, state *state.StateDB, signer common.Address, calcReward *big.Int) (error, map[common.Address]*big.Int) { rewards, err := GetRewardBalancesRate(foudationWalletAddr, signer, calcReward, validator) if err != nil { return err, nil diff --git a/eth/backend.go b/eth/backend.go index 6fb12e08979e..e990093a89b0 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -324,7 +324,7 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) { voterResults := make(map[common.Address]interface{}) if len(signers) > 0 { for signer, calcReward := range rewardSigners { - err, rewards := contracts.CalculateRewardForHolders(c, foudationWalletAddr, validator, state, signer, calcReward) + err, rewards := contracts.CalculateRewardForHolders(foudationWalletAddr, validator, state, signer, calcReward) if err != nil { log.Crit("Fail to calculate reward for holders.", "error", err) } From cd81c5c8b6d7d38dc13117260b7a390a25595a63 Mon Sep 17 00:00:00 2001 From: Nguyen Sy Thanh Son <thanhson1085@gmail.com> Date: Fri, 11 Jan 2019 15:32:48 +0000 Subject: [PATCH 6/7] move cache to insert func --- consensus/posv/posv.go | 3 ++- core/blockchain.go | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/consensus/posv/posv.go b/consensus/posv/posv.go index ef4b2ae1d0c6..2dccf1cd3709 100644 --- a/consensus/posv/posv.go +++ b/consensus/posv/posv.go @@ -853,7 +853,7 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state number := header.Number.Uint64() rCheckpoint := chain.Config().Posv.RewardCheckpoint - _ = c.CacheData(header, txs, receipts) + // _ = c.CacheData(header, txs, receipts) if c.HookReward != nil && number%rCheckpoint == 0 { err, rewards := c.HookReward(chain, state, header) @@ -1045,6 +1045,7 @@ func (c *Posv) CacheData(header *types.Header, txs []*types.Transaction, receipt } } + log.Debug("Save tx signers to cache", "hash", header.Hash().String(), "number", header.Number, "len(txs)", len(signTxs)) c.BlockSigners.Add(header.Hash(), signTxs) return nil diff --git a/core/blockchain.go b/core/blockchain.go index 4d6c2cc01187..5bd0a709be5f 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -506,6 +506,10 @@ func (bc *BlockChain) insert(block *types.Block) { } bc.currentBlock.Store(block) + // save cache BlockSigners + engine := bc.Engine().(*posv.Posv) + engine.CacheData(block.Header(), block.Transactions(), bc.GetReceiptsByHash(block.Hash())) + // If the block is better than our head or is on a different chain, force update heads if updateHeads { bc.hc.SetCurrentHeader(block.Header()) From 381864d869a2c53f9f2d01ab810db4a757692e32 Mon Sep 17 00:00:00 2001 From: Nguyen Sy Thanh Son <thanhson1085@gmail.com> Date: Fri, 11 Jan 2019 17:14:12 +0000 Subject: [PATCH 7/7] verify signing tx --- common/types.go | 1 + contracts/utils.go | 28 +++++++++++++++------------- core/types/transaction.go | 17 ++++++++++++++++- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/common/types.go b/common/types.go index ad06240675af..6a7be73c98d9 100644 --- a/common/types.go +++ b/common/types.go @@ -39,6 +39,7 @@ const ( UnvoteMethod = "0x02aa9be2" ProposeMethod = "0x01267951" ResignMethod = "0xae6e43f5" + SignMethod = "0xe341eaa4" ) var ( diff --git a/contracts/utils.go b/contracts/utils.go index bdfde9828c31..d48207e2003a 100644 --- a/contracts/utils.go +++ b/contracts/utils.go @@ -336,22 +336,24 @@ func GetRewardForCheckpoint(c *posv.Posv, chain consensus.ChainReader, number ui var signTxs []*types.Transaction for _, tx := range txs { - var b uint - for _, r := range receipts { - if r.TxHash == tx.Hash() { - b = r.Status - break + if tx.IsSigningTransaction() { + var b uint + for _, r := range receipts { + if r.TxHash == tx.Hash() { + b = r.Status + break + } } - } - if b == types.ReceiptStatusFailed { - continue - } + 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) + 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) diff --git a/core/types/transaction.go b/core/types/transaction.go index 9bc42013b0a4..339e3562f52f 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -291,7 +291,22 @@ func (tx *Transaction) IsSigningTransaction() bool { if tx.To() == nil { return false } - return tx.To().String() == common.BlockSigners + + if tx.To().String() != common.BlockSigners { + return false + } + + method := common.ToHex(tx.Data()[0:4]) + + if method != common.SignMethod { + return false + } + + if len(tx.Data()) != (32*2 + 4) { + return false + } + + return true } func (tx *Transaction) IsVotingTransaction() (bool, *common.Address) {