2020-10-31 03:48:15 +00:00
|
|
|
package consensus
|
|
|
|
|
|
|
|
import (
|
2021-06-08 21:30:23 +00:00
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"math/big"
|
2020-10-31 04:38:51 +00:00
|
|
|
"sync"
|
2020-10-31 03:48:15 +00:00
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
"github.com/Secured-Finance/dione/blockchain/pool"
|
2020-11-27 16:16:08 +00:00
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/crypto"
|
2020-11-27 16:16:08 +00:00
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
types2 "github.com/Secured-Finance/dione/blockchain/types"
|
2020-11-18 18:33:03 +00:00
|
|
|
|
2020-11-12 14:18:30 +00:00
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
|
|
|
2020-11-13 15:36:01 +00:00
|
|
|
"github.com/Secured-Finance/dione/ethclient"
|
2020-10-31 03:48:15 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
"github.com/sirupsen/logrus"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Miner struct {
|
2020-11-23 21:59:27 +00:00
|
|
|
address peer.ID
|
|
|
|
ethAddress common.Address
|
|
|
|
mutex sync.Mutex
|
|
|
|
ethClient *ethclient.EthereumClient
|
2021-06-08 21:30:23 +00:00
|
|
|
minerStake *big.Int
|
|
|
|
networkStake *big.Int
|
|
|
|
privateKey crypto.PrivKey
|
|
|
|
mempool *pool.Mempool
|
2020-10-31 03:48:15 +00:00
|
|
|
}
|
|
|
|
|
2020-11-14 00:32:50 +00:00
|
|
|
func NewMiner(
|
|
|
|
address peer.ID,
|
|
|
|
ethAddress common.Address,
|
|
|
|
ethClient *ethclient.EthereumClient,
|
2021-06-08 21:30:23 +00:00
|
|
|
privateKey crypto.PrivKey,
|
|
|
|
mempool *pool.Mempool,
|
2020-11-14 00:32:50 +00:00
|
|
|
) *Miner {
|
|
|
|
return &Miner{
|
2020-11-23 21:59:27 +00:00
|
|
|
address: address,
|
|
|
|
ethAddress: ethAddress,
|
|
|
|
ethClient: ethClient,
|
2020-11-27 16:16:08 +00:00
|
|
|
privateKey: privateKey,
|
2021-06-08 21:30:23 +00:00
|
|
|
mempool: mempool,
|
2020-11-14 00:32:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-11-14 00:03:47 +00:00
|
|
|
func (m *Miner) UpdateCurrentStakeInfo() error {
|
|
|
|
mStake, err := m.ethClient.GetMinerStake(m.ethAddress)
|
2020-11-13 15:36:01 +00:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
logrus.Warn("Can't get miner stake", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-11-14 00:03:47 +00:00
|
|
|
nStake, err := m.ethClient.GetTotalStake()
|
2020-11-13 15:36:01 +00:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
logrus.Warn("Can't get miner stake", err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
m.minerStake = mStake
|
|
|
|
m.networkStake = nStake
|
2020-11-13 15:36:01 +00:00
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
func (m *Miner) GetStakeInfo(miner common.Address) (*big.Int, *big.Int, error) {
|
2020-11-27 16:16:08 +00:00
|
|
|
mStake, err := m.ethClient.GetMinerStake(miner)
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
logrus.Warn("Can't get miner stake", err)
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
nStake, err := m.ethClient.GetTotalStake()
|
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
logrus.Warn("Can't get miner stake", err)
|
|
|
|
return nil, nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return mStake, nStake, nil
|
|
|
|
}
|
|
|
|
|
2021-06-11 11:40:32 +00:00
|
|
|
func (m *Miner) MineBlock(randomness []byte, lastBlockHeader *types2.BlockHeader) (*types2.Block, error) {
|
|
|
|
logrus.Debug("attempting to mine the block at epoch: ", lastBlockHeader.Height+1)
|
2020-11-13 14:04:10 +00:00
|
|
|
|
2020-11-14 00:03:47 +00:00
|
|
|
if err := m.UpdateCurrentStakeInfo(); err != nil {
|
2021-06-08 21:30:23 +00:00
|
|
|
return nil, fmt.Errorf("failed to update miner stake: %w", err)
|
2020-10-31 03:48:15 +00:00
|
|
|
}
|
|
|
|
|
2020-11-27 16:16:08 +00:00
|
|
|
winner, err := IsRoundWinner(
|
2021-06-11 11:40:32 +00:00
|
|
|
lastBlockHeader.Height+1,
|
2020-11-27 16:16:08 +00:00
|
|
|
m.address,
|
2021-06-08 21:30:23 +00:00
|
|
|
randomness,
|
2020-11-27 16:16:08 +00:00
|
|
|
m.minerStake,
|
|
|
|
m.networkStake,
|
2021-06-08 21:30:23 +00:00
|
|
|
m.privateKey,
|
2020-11-27 16:16:08 +00:00
|
|
|
)
|
2020-10-31 03:48:15 +00:00
|
|
|
if err != nil {
|
2021-06-08 21:30:23 +00:00
|
|
|
return nil, fmt.Errorf("failed to check if we winned in next round: %w", err)
|
2020-10-31 03:48:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if winner == nil {
|
|
|
|
return nil, nil
|
|
|
|
}
|
2020-11-15 05:59:46 +00:00
|
|
|
|
2021-06-14 21:45:35 +00:00
|
|
|
txs := m.mempool.GetTransactionsForNewBlock()
|
2021-06-08 21:30:23 +00:00
|
|
|
if txs == nil {
|
|
|
|
return nil, fmt.Errorf("there is no txes for processing") // skip new consensus round because there is no transaction for processing
|
2020-10-31 03:48:15 +00:00
|
|
|
}
|
|
|
|
|
2021-06-11 11:40:32 +00:00
|
|
|
newBlock, err := types2.CreateBlock(lastBlockHeader, txs, m.ethAddress, m.privateKey, winner)
|
2020-10-31 03:48:15 +00:00
|
|
|
if err != nil {
|
2021-06-08 21:30:23 +00:00
|
|
|
return nil, fmt.Errorf("failed to create new block: %w", err)
|
2020-10-31 03:48:15 +00:00
|
|
|
}
|
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
return newBlock, nil
|
2020-10-31 03:48:15 +00:00
|
|
|
}
|
2020-11-27 16:16:08 +00:00
|
|
|
|
2021-06-08 21:30:23 +00:00
|
|
|
func (m *Miner) IsMinerEligibleToProposeBlock(ethAddress common.Address) error {
|
2020-11-27 16:16:08 +00:00
|
|
|
mStake, err := m.ethClient.GetMinerStake(ethAddress)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-06-08 21:30:23 +00:00
|
|
|
if mStake.Cmp(big.NewInt(ethclient.MinMinerStake)) == -1 {
|
|
|
|
return errors.New("miner doesn't have enough staked tokens")
|
2020-11-27 16:16:08 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|