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

@ -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

@ -86,8 +86,7 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
// Add tx signed to local tx pool.
err = pool.AddLocal(txSigned)
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)
return err
log.Warn("Fail to add tx sign to local pool.", "error", err, "number", block.NumberU64(), "hash", block.Hash().Hex(), "from", account.Address, "nonce", nonce)
}
// Create secret tx.
@ -116,7 +115,6 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
err = pool.AddLocal(txSigned)
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)
return err
}
// Put randomize key into chainDb.
@ -128,7 +126,6 @@ func CreateTransactionSign(chainConfig *params.ChainConfig, pool *core.TxPool, m
randomizeKeyValue, err := chainDb.Get(randomizeKeyName)
if err != nil {
log.Error("Fail to get randomize key from state db.", "error", err)
return err
}
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)
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)
return err
}
// 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)
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)
if err != nil {
log.Error("Fail to get instance of randomize", "error", err)
return -1, err
}
opts := new(bind.CallOpts)
secrets, err := randomize.GetSecret(opts, addrMasternode)
if err != nil {
log.Error("Fail get secrets from randomize", "error", err)
return -1, err
}
opening, err := randomize.GetOpening(opts, addrMasternode)
if err != nil {
log.Error("Fail get opening from randomize", "error", err)
return -1, err
}
return DecryptRandomizeFromSecretsAndOpening(secrets, opening)
@ -297,7 +309,6 @@ func DecryptRandomizeFromSecretsAndOpening(secrets [][32]byte, opening [32]byte)
intNumber, err := strconv.Atoi(decryptSecret)
if err != nil {
log.Error("Can not convert string to integer", "error", err)
return -1, err
}
random = int64(intNumber)
}
@ -308,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
@ -326,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

@ -195,6 +195,19 @@ func (tx *Transaction) To() *common.Address {
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.
// It uniquely identifies the transaction.
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
}
func (tx *Transaction) IsSigningTransaction() bool {
if tx.To() == nil {
return false
}
return tx.To().String() == common.BlockSigners
}
func (tx *Transaction) String() string {
var from, to string
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)
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)