github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/raft/raft.go (about)

     1  package raft
     2  
     3  import (
     4  	"crypto/ecdsa"
     5  	"math/big"
     6  
     7  	"github.com/bigzoro/my_simplechain/common"
     8  	"github.com/bigzoro/my_simplechain/common/hexutil"
     9  	"github.com/bigzoro/my_simplechain/consensus"
    10  	"github.com/bigzoro/my_simplechain/consensus/ethash"
    11  	"github.com/bigzoro/my_simplechain/core/state"
    12  	"github.com/bigzoro/my_simplechain/core/types"
    13  	"github.com/bigzoro/my_simplechain/crypto"
    14  	"github.com/bigzoro/my_simplechain/log"
    15  	"github.com/bigzoro/my_simplechain/params"
    16  	"github.com/bigzoro/my_simplechain/rlp"
    17  )
    18  
    19  type Raft struct {
    20  	*ethash.Ethash
    21  	raftId  uint16
    22  	nodeKey *ecdsa.PrivateKey
    23  }
    24  
    25  func New(nodeKey *ecdsa.PrivateKey) *Raft {
    26  	return &Raft{
    27  		Ethash:  ethash.NewFullFaker(),
    28  		nodeKey: nodeKey,
    29  	}
    30  }
    31  
    32  func (r *Raft) SetId(raftId uint16) {
    33  	r.raftId = raftId
    34  }
    35  
    36  var ExtraVanity = 32 // Fixed number of extra-data prefix bytes reserved for arbitrary signer vanity
    37  
    38  type ExtraSeal struct {
    39  	RaftId    []byte // RaftID of the block RaftMinter
    40  	Signature []byte // Signature of the block RaftMinter
    41  }
    42  
    43  func (r *Raft) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, _ []*types.Receipt) error {
    44  	// Accumulate any block and uncle rewards and commit the final state root
    45  	accumulateRewards(state, header)
    46  	header.Root = state.IntermediateRoot(true)
    47  	return nil
    48  }
    49  
    50  func (r *Raft) FinalizeAndAssemble(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction,
    51  	uncles []*types.Header, receipts []*types.Receipt) (*types.Block, error) {
    52  	// commit state root after all state transitions.
    53  	accumulateRewards(state, header)
    54  	header.Root = state.IntermediateRoot(true)
    55  	header.Bloom = types.CreateBloom(receipts)
    56  
    57  	// update block hash since it is now available, but was not when the
    58  	// receipt/log of individual transactions were created:
    59  	headerHash := header.Hash()
    60  	for _, r := range receipts {
    61  		for _, l := range r.Logs {
    62  			l.BlockHash = headerHash
    63  		}
    64  	}
    65  
    66  	//Sign the block and build the extraSeal struct
    67  	extraSealBytes := r.buildExtraSeal(headerHash)
    68  
    69  	// add vanity and seal to header
    70  	// NOTE: leaving vanity blank for now as a space for any future data
    71  	header.Extra = make([]byte, ExtraVanity+len(extraSealBytes))
    72  	copy(header.Extra[ExtraVanity:], extraSealBytes)
    73  
    74  	block := types.NewBlock(header, txs, nil, receipts)
    75  
    76  	if _, err := state.Commit(true); err != nil {
    77  		return nil, err
    78  	}
    79  
    80  	return block, nil
    81  }
    82  
    83  func (r *Raft) buildExtraSeal(headerHash common.Hash) []byte {
    84  	//Sign the headerHash
    85  	sig, err := crypto.Sign(headerHash.Bytes(), r.nodeKey)
    86  	if err != nil {
    87  		log.Warn("Block sealing failed", "err", err)
    88  	}
    89  
    90  	//build the extraSeal struct
    91  	raftIdString := hexutil.EncodeUint64(uint64(r.raftId))
    92  
    93  	extra := ExtraSeal{
    94  		RaftId:    []byte(raftIdString[2:]), //remove the 0x prefix
    95  		Signature: sig,
    96  	}
    97  
    98  	//encode to byte array for storage
    99  	extraDataBytes, err := rlp.EncodeToBytes(extra)
   100  	if err != nil {
   101  		log.Warn("Header.Extra Data Encoding failed", "err", err)
   102  	}
   103  
   104  	return extraDataBytes
   105  }
   106  
   107  var (
   108  	BlockReward      *big.Int = new(big.Int).Mul(big.NewInt(1e+18), big.NewInt(20))
   109  	BlockAttenuation *big.Int = big.NewInt(2500000)
   110  	big5             *big.Int = big.NewInt(5)
   111  	big100           *big.Int = big.NewInt(100)
   112  )
   113  
   114  // accumulateRewards credits the coinbase of the given block with the mining reward.
   115  func accumulateRewards(state *state.StateDB, header *types.Header) {
   116  	blockReward := calculateFixedRewards(header.Number)
   117  	foundation := calculateFoundationRewards(header.Number, blockReward)
   118  	blockReward.Sub(blockReward, foundation)
   119  	state.AddBalance(header.Coinbase, blockReward)
   120  	state.AddBalance(params.FoundationAddress, foundation)
   121  }
   122  
   123  func calculateFixedRewards(blockNumber *big.Int) *big.Int {
   124  	reward := new(big.Int).Set(BlockReward)
   125  	number := new(big.Int).Set(blockNumber)
   126  	if number.Sign() == 1 {
   127  		number.Div(number, BlockAttenuation)
   128  		base := big.NewInt(0)
   129  		base.Exp(big.NewInt(2), number, big.NewInt(0))
   130  		reward.Div(reward, base)
   131  	}
   132  	return reward
   133  }
   134  
   135  func calculateFoundationRewards(blockNumber *big.Int, blockReward *big.Int) *big.Int {
   136  	foundation := new(big.Int).Set(blockReward)
   137  	foundation.Mul(foundation, big5)
   138  	number := new(big.Int).Set(blockNumber)
   139  	if number.Sign() == 1 {
   140  		number.Div(number, BlockAttenuation)
   141  		base := big.NewInt(0)
   142  		base.Exp(big.NewInt(2), number, big.NewInt(0))
   143  		foundation.Div(foundation, base)
   144  	}
   145  	foundation.Div(foundation, big100)
   146  	return foundation
   147  }