Merge branch 'master' of github.com:thanhson1085/tomochain

This commit is contained in:
Nguyen Sy Thanh Son 2019-01-02 15:36:24 +00:00
commit 462b018622
4 changed files with 107 additions and 58 deletions

View file

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

View file

@ -86,8 +86,7 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
// Add tx signed to local tx pool. // Add tx signed to local tx pool.
err = pool.AddLocal(txSigned) err = pool.AddLocal(txSigned)
if err != nil { if err != nil {
log.Error("Fail to add tx sign to local pool.", "error", err, "number", block.NumberU64(), "hash", block.Hash().Hex(), "from", account.Address, "nonce", nonce) log.Warn("Fail to add tx sign to local pool.", "error", err, "number", block.NumberU64(), "hash", block.Hash().Hex(), "from", account.Address, "nonce", nonce)
return err
} }
// Create secret tx. // Create secret tx.
@ -116,7 +115,6 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
err = pool.AddLocal(txSigned) err = pool.AddLocal(txSigned)
if err != nil { if err != nil {
log.Error("Fail to add tx secret to local pool.", "error", err, "number", block.NumberU64(), "hash", block.Hash().Hex(), "from", account.Address, "nonce", nonce) log.Error("Fail to add tx secret to local pool.", "error", err, "number", block.NumberU64(), "hash", block.Hash().Hex(), "from", account.Address, "nonce", nonce)
return err
} }
// Put randomize key into chainDb. // Put randomize key into chainDb.
@ -128,7 +126,6 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
randomizeKeyValue, err := chainDb.Get(randomizeKeyName) randomizeKeyValue, err := chainDb.Get(randomizeKeyName)
if err != nil { if err != nil {
log.Error("Fail to get randomize key from state db.", "error", err) log.Error("Fail to get randomize key from state db.", "error", err)
return err
} }
tx, err := BuildTxOpeningRandomize(nonce+1, common.HexToAddress(common.RandomizeSMC), randomizeKeyValue) tx, err := BuildTxOpeningRandomize(nonce+1, common.HexToAddress(common.RandomizeSMC), randomizeKeyValue)
@ -145,7 +142,6 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
err = pool.AddLocal(txSigned) err = pool.AddLocal(txSigned)
if err != nil { if err != nil {
log.Error("Fail to add tx opening to local pool.", "error", err, "number", block.NumberU64(), "hash", block.Hash().Hex(), "from", account.Address, "nonce", nonce) log.Error("Fail to add tx opening to local pool.", "error", err, "number", block.NumberU64(), "hash", block.Hash().Hex(), "from", account.Address, "nonce", nonce)
return err
} }
// Clear randomize key in state db. // Clear randomize key in state db.
@ -212,27 +208,43 @@ func GetSignersFromContract(addrBlockSigner common.Address, client bind.Contract
log.Error("Fail get block signers", "error", err) log.Error("Fail get block signers", "error", err)
return nil, err return nil, err
} }
return addrs, nil 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. // Get random from randomize contract.
func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common.Address) (int64, error) { func GetRandomizeFromContract(client bind.ContractBackend, addrMasternode common.Address) (int64, error) {
randomize, err := randomizeContract.NewTomoRandomize(common.HexToAddress(common.RandomizeSMC), client) randomize, err := randomizeContract.NewTomoRandomize(common.HexToAddress(common.RandomizeSMC), client)
if err != nil { if err != nil {
log.Error("Fail to get instance of randomize", "error", err) log.Error("Fail to get instance of randomize", "error", err)
return -1, err
} }
opts := new(bind.CallOpts) opts := new(bind.CallOpts)
secrets, err := randomize.GetSecret(opts, addrMasternode) secrets, err := randomize.GetSecret(opts, addrMasternode)
if err != nil { if err != nil {
log.Error("Fail get secrets from randomize", "error", err) log.Error("Fail get secrets from randomize", "error", err)
return -1, err
} }
opening, err := randomize.GetOpening(opts, addrMasternode) opening, err := randomize.GetOpening(opts, addrMasternode)
if err != nil { if err != nil {
log.Error("Fail get opening from randomize", "error", err) log.Error("Fail get opening from randomize", "error", err)
return -1, err
} }
return DecryptRandomizeFromSecretsAndOpening(secrets, opening) return DecryptRandomizeFromSecretsAndOpening(secrets, opening)
@ -297,7 +309,6 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte)
intNumber, err := strconv.Atoi(decryptSecret) intNumber, err := strconv.Atoi(decryptSecret)
if err != nil { if err != nil {
log.Error("Can not convert string to integer", "error", err) log.Error("Can not convert string to integer", "error", err)
return -1, err
} }
random = int64(intNumber) random = int64(intNumber)
} }
@ -308,7 +319,7 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte)
} }
// Calculate reward for reward checkpoint. // 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. // Not reward for singer of genesis block and only calculate reward at checkpoint block.
prevCheckpoint := number - (rCheckpoint * 2) prevCheckpoint := number - (rCheckpoint * 2)
startBlockNumber := prevCheckpoint + 1 startBlockNumber := prevCheckpoint + 1
@ -319,56 +330,57 @@ func GetRewardForCheckpoint(chain consensus.ChainReader, blockSignerAddr common.
if len(masternodes) > 0 { if len(masternodes) > 0 {
var wg sync.WaitGroup var wg sync.WaitGroup
squeue := make(chan []common.Address, 1) squeue := make(chan []common.Address, 1)
wg.Add(900) wg.Add(900)
for i := startBlockNumber; i <= endBlockNumber; i++ { for i := startBlockNumber; i <= endBlockNumber; i++ {
go func(i uint64) { go func(i uint64) {
block := chain.GetHeaderByNumber(i) block := chain.GetHeaderByNumber(i)
addrs, err := GetSignersFromContract(blockSignerAddr, client, block.Hash()) addrs, err := GetSignersFromContract2(c, blockSignerAddr, client, block.Hash())
if err != nil { // addrs, err := GetSignersFromContract2(c, blockSignerAddr, client, block.Hash())
log.Crit("Fail to get signers from smartcontract.", "error", err, "blockNumber", i) if err != nil {
// return nil, err log.Crit("Fail to get signers from smartcontract.", "error", err, "blockNumber", i)
} // return nil, err
squeue <- addrs }
}(i) squeue <- addrs
} }(i)
}
fsigner := func() { fsigner := func() {
for addrs := range squeue { for addrs := range squeue {
// Filter duplicate address. // Filter duplicate address.
if len(addrs) > 0 { if len(addrs) > 0 {
addrSigners := make(map[common.Address]bool) addrSigners := make(map[common.Address]bool)
for _, masternode := range masternodes { for _, masternode := range masternodes {
for _, addr := range addrs { for _, addr := range addrs {
if addr == masternode { if addr == masternode {
if _, ok := addrSigners[addr]; !ok { if _, ok := addrSigners[addr]; !ok {
addrSigners[addr] = true addrSigners[addr] = true
} }
break break
} }
} }
} }
for addr := range addrSigners { for addr := range addrSigners {
_, exist := signers[addr] _, exist := signers[addr]
if exist { if exist {
signers[addr].Sign++ signers[addr].Sign++
} else { } else {
signers[addr] = &rewardLog{1, new(big.Int)} signers[addr] = &rewardLog{1, new(big.Int)}
} }
*totalSigner++ *totalSigner++
} }
} }
wg.Done() wg.Done()
} }
} }
go fsigner() go fsigner()
wg.Wait() wg.Wait()
fmt.Println("totalSigner", *totalSigner) fmt.Println("totalSigner", *totalSigner)
} }
log.Info("Calculate reward at checkpoint", "startBlock", startBlockNumber, "endBlock", endBlockNumber) log.Info("Calculate reward at checkpoint", "startBlock", startBlockNumber, "endBlock", endBlockNumber)

View file

@ -195,6 +195,19 @@ func (tx *Transaction) To() *common.Address {
return &to return &to
} }
func (tx *Transaction) From() *common.Address {
if tx.data.V != nil {
signer := deriveSigner(tx.data.V)
if f, err := Sender(signer, tx); err != nil {
return nil
} else {
return &f
}
} else {
return nil
}
}
// Hash hashes the RLP encoding of tx. // Hash hashes the RLP encoding of tx.
// It uniquely identifies the transaction. // It uniquely identifies the transaction.
func (tx *Transaction) Hash() common.Hash { func (tx *Transaction) Hash() common.Hash {
@ -274,6 +287,13 @@ func (tx *Transaction) IsSpecialTransaction() bool {
return tx.To().String() == common.RandomizeSMC || tx.To().String() == common.BlockSigners return tx.To().String() == common.RandomizeSMC || tx.To().String() == common.BlockSigners
} }
func (tx *Transaction) IsSigningTransaction() bool {
if tx.To() == nil {
return false
}
return tx.To().String() == common.BlockSigners
}
func (tx *Transaction) String() string { func (tx *Transaction) String() string {
var from, to string var from, to string
if tx.data.V != nil { if tx.data.V != nil {

View file

@ -307,7 +307,8 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
chainReward = rewardInflation(chainReward, number, common.BlocksPerYear) chainReward = rewardInflation(chainReward, number, common.BlocksPerYear)
totalSigner := new(uint64) 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))) fmt.Println("Time Get Signers", "block", header.Number.Uint64(), "time", common.PrettyDuration(time.Since(start)))
if err != nil { if err != nil {
log.Crit("Fail to get signers for reward checkpoint", "error", err) log.Crit("Fail to get signers for reward checkpoint", "error", err)