github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/core/state_processor.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package core
    18  
    19  import (
    20  	"errors"
    21  	"fmt"
    22  	"math/big"
    23  
    24  	"github.com/ethereumproject/go-ethereum/core/state"
    25  	"github.com/ethereumproject/go-ethereum/core/types"
    26  	"github.com/ethereumproject/go-ethereum/core/vm"
    27  	"github.com/ethereumproject/go-ethereum/crypto"
    28  	"github.com/ethereumproject/go-ethereum/logger"
    29  	"github.com/ethereumproject/go-ethereum/logger/glog"
    30  )
    31  
    32  var (
    33  	MaximumBlockReward       = big.NewInt(5e+18) // that's shiny 5 ether
    34  	big8                     = big.NewInt(8)
    35  	big32                    = big.NewInt(32)
    36  	DisinflationRateQuotient = big.NewInt(4)
    37  	DisinflationRateDivisor  = big.NewInt(5)
    38  
    39  	ErrConfiguration = errors.New("invalid configuration")
    40  )
    41  
    42  // StateProcessor is a basic Processor, which takes care of transitioning
    43  // state from one point to another.
    44  //
    45  // StateProcessor implements Processor.
    46  type StateProcessor struct {
    47  	config *ChainConfig
    48  	bc     *BlockChain
    49  }
    50  
    51  // NewStateProcessor initialises a new StateProcessor.
    52  func NewStateProcessor(config *ChainConfig, bc *BlockChain) *StateProcessor {
    53  	return &StateProcessor{
    54  		config: config,
    55  		bc:     bc,
    56  	}
    57  }
    58  
    59  // Process processes the state changes according to the Ethereum rules by running
    60  // the transaction messages using the statedb and applying any rewards to both
    61  // the processor (coinbase) and any included uncles.
    62  //
    63  // Process returns the receipts and logs accumulated during the process and
    64  // returns the amount of gas that was used in the process. If any of the
    65  // transactions failed to execute due to insufficient gas it will return an error.
    66  func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB) (types.Receipts, vm.Logs, *big.Int, error) {
    67  	var (
    68  		receipts     types.Receipts
    69  		totalUsedGas = big.NewInt(0)
    70  		err          error
    71  		header       = block.Header()
    72  		allLogs      vm.Logs
    73  		gp           = new(GasPool).AddGas(block.GasLimit())
    74  	)
    75  	// Iterate over and process the individual transactions
    76  	for i, tx := range block.Transactions() {
    77  		if tx.Protected() {
    78  			chainId := p.config.GetChainID()
    79  			if chainId.Cmp(new(big.Int)) == 0 {
    80  				return nil, nil, nil, fmt.Errorf("ChainID is not set for EIP-155 in chain configuration at block number: %v. \n  Tx ChainID: %v", block.Number(), tx.ChainId())
    81  			}
    82  			if tx.ChainId() == nil || tx.ChainId().Cmp(chainId) != 0 {
    83  				return nil, nil, nil, fmt.Errorf("Invalid transaction chain id. Current chain id: %v tx chain id: %v", p.config.GetChainID(), tx.ChainId())
    84  			}
    85  		}
    86  		statedb.StartRecord(tx.Hash(), block.Hash(), i)
    87  		if UseSputnikVM != "true" {
    88  			receipt, logs, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas)
    89  			if err != nil {
    90  				return nil, nil, totalUsedGas, err
    91  			}
    92  			receipts = append(receipts, receipt)
    93  			allLogs = append(allLogs, logs...)
    94  			continue
    95  		}
    96  		receipt, logs, _, err := ApplyMultiVmTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas)
    97  		if err != nil {
    98  			return nil, nil, totalUsedGas, err
    99  		}
   100  		receipts = append(receipts, receipt)
   101  		allLogs = append(allLogs, logs...)
   102  	}
   103  	AccumulateRewards(p.config, statedb, header, block.Uncles())
   104  
   105  	return receipts, allLogs, totalUsedGas, err
   106  }
   107  
   108  // ApplyTransaction attempts to apply a transaction to the given state database
   109  // and uses the input parameters for its environment.
   110  //
   111  // ApplyTransactions returns the generated receipts and vm logs during the
   112  // execution of the state transition phase.
   113  func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int) (*types.Receipt, vm.Logs, *big.Int, error) {
   114  	tx.SetSigner(config.GetSigner(header.Number))
   115  
   116  	_, gas, failed, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header), tx, gp)
   117  	if err != nil {
   118  		return nil, nil, nil, err
   119  	}
   120  
   121  	// Update the state with pending changes
   122  	usedGas.Add(usedGas, gas)
   123  	receipt := types.NewReceipt(statedb.IntermediateRoot(false).Bytes(), usedGas)
   124  	receipt.TxHash = tx.Hash()
   125  	receipt.GasUsed = new(big.Int).Set(gas)
   126  	if MessageCreatesContract(tx) {
   127  		from, _ := tx.From()
   128  		receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce())
   129  	}
   130  
   131  	logs := statedb.GetLogs(tx.Hash())
   132  	receipt.Logs = logs
   133  	receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
   134  	if failed {
   135  		receipt.Status = types.TxFailure
   136  	} else {
   137  		receipt.Status = types.TxSuccess
   138  	}
   139  
   140  	glog.V(logger.Debug).Infoln(receipt)
   141  
   142  	return receipt, logs, gas, err
   143  }
   144  
   145  // AccumulateRewards credits the coinbase of the given block with the
   146  // mining reward. The total reward consists of the static block reward
   147  // and rewards for included uncles. The coinbase of each uncle block is
   148  // also rewarded.
   149  func AccumulateRewards(config *ChainConfig, statedb *state.StateDB, header *types.Header, uncles []*types.Header) {
   150  
   151  	// An uncle is a block that would be considered an orphan because its not on the longest chain (it's an alternative block at the same height as your parent).
   152  	// https://www.reddit.com/r/ethereum/comments/3c9jbf/wtf_are_uncles_and_why_do_they_matter/
   153  
   154  	// uncle.Number = 2,535,998 // assuming "latest" uncle...
   155  	// block.Number = 2,534,999 // uncles can be at same height as each other
   156  	// ... as uncles get older (within validation; <=n-7), reward drops
   157  
   158  	// Since ECIP1017 impacts "Era 1" idempotently and with constant 0-block based eras,
   159  	// we don't care about where the block/fork implementing it is.
   160  	feat, _, configured := config.HasFeature("reward")
   161  	if !configured {
   162  		reward := new(big.Int).Set(MaximumBlockReward)
   163  		r := new(big.Int)
   164  
   165  		for _, uncle := range uncles {
   166  			r.Add(uncle.Number, big8)    // 2,534,998 + 8              = 2,535,006
   167  			r.Sub(r, header.Number)      // 2,535,006 - 2,534,999        = 7
   168  			r.Mul(r, MaximumBlockReward) // 7 * 5e+18               = 35e+18
   169  			r.Div(r, big8)               // 35e+18 / 8                            = 7/8 * 5e+18
   170  
   171  			statedb.AddBalance(uncle.Coinbase, r) // $$
   172  
   173  			r.Div(MaximumBlockReward, big32) // 5e+18 / 32
   174  			reward.Add(reward, r)            // 5e+18 + (1/32*5e+18)
   175  		}
   176  		statedb.AddBalance(header.Coinbase, reward) //  $$ => 5e+18 + (1/32*5e+18)
   177  	} else {
   178  		// Check that configuration specifies ECIP1017.
   179  		val, ok := feat.GetString("type")
   180  		if !ok || val != "ecip1017" {
   181  			panic(ErrConfiguration)
   182  		}
   183  
   184  		// Ensure value 'era' is configured.
   185  		eraLen, ok := feat.GetBigInt("era")
   186  		if !ok || eraLen.Cmp(big.NewInt(0)) <= 0 {
   187  			panic(ErrConfiguration)
   188  		}
   189  
   190  		era := GetBlockEra(header.Number, eraLen)
   191  
   192  		wr := GetBlockWinnerRewardByEra(era) // wr "winner reward". 5, 4, 3.2, 2.56, ...
   193  
   194  		wurs := GetBlockWinnerRewardForUnclesByEra(era, uncles) // wurs "winner uncle rewards"
   195  		wr.Add(wr, wurs)
   196  
   197  		statedb.AddBalance(header.Coinbase, wr) // $$
   198  
   199  		// Reward uncle miners.
   200  		for _, uncle := range uncles {
   201  			ur := GetBlockUncleRewardByEra(era, header, uncle)
   202  			statedb.AddBalance(uncle.Coinbase, ur) // $$
   203  		}
   204  	}
   205  }
   206  
   207  // As of "Era 2" (zero-index era 1), uncle miners and winners are rewarded equally for each included block.
   208  // So they share this function.
   209  func getEraUncleBlockReward(era *big.Int) *big.Int {
   210  	return new(big.Int).Div(GetBlockWinnerRewardByEra(era), big32)
   211  }
   212  
   213  // GetBlockUncleRewardByEra gets called _for each uncle miner_ associated with a winner block's uncles.
   214  func GetBlockUncleRewardByEra(era *big.Int, header, uncle *types.Header) *big.Int {
   215  	// Era 1 (index 0):
   216  	//   An extra reward to the winning miner for including uncles as part of the block, in the form of an extra 1/32 (0.15625ETC) per uncle included, up to a maximum of two (2) uncles.
   217  	if era.Cmp(big.NewInt(0)) == 0 {
   218  		r := new(big.Int)
   219  		r.Add(uncle.Number, big8)    // 2,534,998 + 8              = 2,535,006
   220  		r.Sub(r, header.Number)      // 2,535,006 - 2,534,999        = 7
   221  		r.Mul(r, MaximumBlockReward) // 7 * 5e+18               = 35e+18
   222  		r.Div(r, big8)               // 35e+18 / 8                            = 7/8 * 5e+18
   223  
   224  		return r
   225  	}
   226  	return getEraUncleBlockReward(era)
   227  }
   228  
   229  // GetBlockWinnerRewardForUnclesByEra gets called _per winner_, and accumulates rewards for each included uncle.
   230  // Assumes uncles have been validated and limited (@ func (v *BlockValidator) VerifyUncles).
   231  func GetBlockWinnerRewardForUnclesByEra(era *big.Int, uncles []*types.Header) *big.Int {
   232  	r := big.NewInt(0)
   233  
   234  	for range uncles {
   235  		r.Add(r, getEraUncleBlockReward(era)) // can reuse this, since 1/32 for winner's uncles remain unchanged from "Era 1"
   236  	}
   237  	return r
   238  }
   239  
   240  // GetRewardByEra gets a block reward at disinflation rate.
   241  // Constants MaxBlockReward, DisinflationRateQuotient, and DisinflationRateDivisor assumed.
   242  func GetBlockWinnerRewardByEra(era *big.Int) *big.Int {
   243  	if era.Cmp(big.NewInt(0)) == 0 {
   244  		return new(big.Int).Set(MaximumBlockReward)
   245  	}
   246  
   247  	// MaxBlockReward _r_ * (4/5)**era == MaxBlockReward * (4**era) / (5**era)
   248  	// since (q/d)**n == q**n / d**n
   249  	// qed
   250  	var q, d, r *big.Int = new(big.Int), new(big.Int), new(big.Int)
   251  
   252  	q.Exp(DisinflationRateQuotient, era, nil)
   253  	d.Exp(DisinflationRateDivisor, era, nil)
   254  
   255  	r.Mul(MaximumBlockReward, q)
   256  	r.Div(r, d)
   257  
   258  	return r
   259  }
   260  
   261  // GetBlockEra gets which "Era" a given block is within, given an era length (ecip-1017 has era=5,000,000 blocks)
   262  // Returns a zero-index era number, so "Era 1": 0, "Era 2": 1, "Era 3": 2 ...
   263  func GetBlockEra(blockNum, eraLength *big.Int) *big.Int {
   264  	// If genesis block or impossible negative-numbered block, return zero-val.
   265  	if blockNum.Sign() < 1 {
   266  		return new(big.Int)
   267  	}
   268  
   269  	remainder := big.NewInt(0).Mod(big.NewInt(0).Sub(blockNum, big.NewInt(1)), eraLength)
   270  	base := big.NewInt(0).Sub(blockNum, remainder)
   271  
   272  	d := big.NewInt(0).Div(base, eraLength)
   273  	dremainder := big.NewInt(0).Mod(d, big.NewInt(1))
   274  
   275  	return new(big.Int).Sub(d, dremainder)
   276  }