try use cache for blocksigners

This commit is contained in:
Nguyen Sy Thanh Son 2019-01-02 12:50:05 +00:00
parent c00d2dc9aa
commit d3ad6c39f2
3 changed files with 43 additions and 6 deletions

View file

@ -49,6 +49,7 @@ import (
const (
inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory
blockSignersCacheLimit = 1800
M2ByteLength = 4
)
@ -224,6 +225,7 @@ type Posv struct {
signFn clique.SignerFn // Signer function to authorize hashes with
lock sync.RWMutex // Protects the signer fields
BlockSigners *lru.ARCCache
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)
@ -239,6 +241,7 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv {
conf.Epoch = epochLength
}
// Allocate the snapshot caches and create the engine
BlockSigners, _ := lru.NewARC(blockSignersCacheLimit)
recents, _ := lru.NewARC(inmemorySnapshots)
signatures, _ := lru.NewARC(inmemorySnapshots)
validatorSignatures, _ := lru.NewARC(inmemorySnapshots)
@ -246,6 +249,7 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv {
return &Posv{
config: &conf,
db: db,
BlockSigners: BlockSigners,
recents: recents,
signatures: signatures,
verifiedHeaders: verifiedHeaders,
@ -254,6 +258,10 @@ func New(config *params.PosvConfig, db ethdb.Database) *Posv {
}
}
func (c *Posv) GetBlockSigners() *lru.ARCCache {
return c.BlockSigners
}
// Author implements consensus.Engine, returning the Ethereum address recovered
// from the signature in the header's extra-data section.
func (c *Posv) Author(header *types.Header) (common.Address, error) {
@ -849,6 +857,14 @@ func (c *Posv) Finalize(chain consensus.ChainReader, header *types.Header, state
number := header.Number.Uint64()
rCheckpoint := chain.Config().Posv.RewardCheckpoint
var lAddr []common.Address
for _, tx := range txs {
if tx.IsSigningTransaction() {
lAddr = append(lAddr, *tx.From())
}
}
c.BlockSigners.Add(header.Hash(), lAddr)
if c.HookReward != nil && number%rCheckpoint == 0 {
err, rewards := c.HookReward(chain, state, header)
if err != nil {

View file

@ -208,10 +208,29 @@ func GetSignersFromContract(addrBlockSigner common.Address, client bind.Contract
log.Error("Fail get block signers", "error", err)
return nil, err
}
return addrs, nil
}
func GetSignersFromContract2(c *posv.Posv, 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
}
opts := new(bind.CallOpts)
if caddrs, ok := c.GetBlockSigners().Get(blockHash); !ok {
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
}
return nil, nil
}
// Get random from randomize contract.
func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common.Address) (int64, error) {
randomize, err := randomizeContract.NewTomoRandomize(common.HexToAddress(common.RandomizeSMC), client)
@ -300,7 +319,7 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte)
}
// Calculate reward for reward checkpoint.
func GetRewardForCheckpoint(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, blockSignerAddr common.Address, number uint64, rCheckpoint uint64, client bind.ContractBackend, 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 +337,8 @@ func GetRewardForCheckpoint(chain consensus.ChainReader, blockSignerAddr common.
for i := startBlockNumber; i <= endBlockNumber; i++ {
go func(i uint64) {
block := chain.GetHeaderByNumber(i)
addrs, err := GetSignersFromContract(blockSignerAddr, client, block.Hash())
addrs, err := GetSignersFromContract2(c, blockSignerAddr, client, block.Hash())
// addrs, err := GetSignersFromContract2(c, blockSignerAddr, client, block.Hash())
if err != nil {
log.Crit("Fail to get signers from smartcontract.", "error", err, "blockNumber", i)
// return nil, err

View file

@ -307,7 +307,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
chainReward = rewardInflation(chainReward, number, common.BlocksPerYear)
totalSigner := new(uint64)
signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner)
signers, err := contracts.GetRewardForCheckpoint(c, chain, addr, number, rCheckpoint, client, totalSigner)
// signers, err := contracts.GetRewardForCheckpoint(chain, addr, number, rCheckpoint, client, totalSigner)
fmt.Println("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)