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 }