f0cbebb19f
Added chain configuration options and write out during genesis database insertion. If no "config" was found, nothing is written to the database. Configurations are written on a per genesis base. This means that any chain (which is identified by it's genesis hash) can have their own chain settings.
116 lines
3.7 KiB
Go
116 lines
3.7 KiB
Go
package core
|
|
|
|
import (
|
|
"math/big"
|
|
|
|
"github.com/ethereum/go-ethereum/core/state"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/ethereum/go-ethereum/core/vm"
|
|
"github.com/ethereum/go-ethereum/crypto"
|
|
"github.com/ethereum/go-ethereum/logger"
|
|
"github.com/ethereum/go-ethereum/logger/glog"
|
|
)
|
|
|
|
var (
|
|
big8 = big.NewInt(8)
|
|
big32 = big.NewInt(32)
|
|
)
|
|
|
|
// StateProcessor is a basic Processor, which takes care of transitioning
|
|
// state from one point to another.
|
|
//
|
|
// StateProcessor implements Processor.
|
|
type StateProcessor struct {
|
|
config *ChainConfig
|
|
bc *BlockChain
|
|
}
|
|
|
|
// NewStateProcessor initialises a new StateProcessor.
|
|
func NewStateProcessor(config *ChainConfig, bc *BlockChain) *StateProcessor {
|
|
return &StateProcessor{
|
|
config: config,
|
|
bc: bc,
|
|
}
|
|
}
|
|
|
|
// Process processes the state changes according to the Ethereum rules by running
|
|
// the transaction messages using the statedb and applying any rewards to both
|
|
// the processor (coinbase) and any included uncles.
|
|
//
|
|
// Process returns the receipts and logs accumulated during the process and
|
|
// returns the amount of gas that was used in the process. If any of the
|
|
// transactions failed to execute due to insufficient gas it will return an error.
|
|
func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg vm.Config) (types.Receipts, vm.Logs, *big.Int, error) {
|
|
var (
|
|
receipts types.Receipts
|
|
totalUsedGas = big.NewInt(0)
|
|
err error
|
|
header = block.Header()
|
|
allLogs vm.Logs
|
|
gp = new(GasPool).AddGas(block.GasLimit())
|
|
)
|
|
|
|
for i, tx := range block.Transactions() {
|
|
statedb.StartRecord(tx.Hash(), block.Hash(), i)
|
|
receipt, logs, _, err := ApplyTransaction(p.config, p.bc, gp, statedb, header, tx, totalUsedGas, cfg)
|
|
if err != nil {
|
|
return nil, nil, totalUsedGas, err
|
|
}
|
|
receipts = append(receipts, receipt)
|
|
allLogs = append(allLogs, logs...)
|
|
}
|
|
AccumulateRewards(statedb, header, block.Uncles())
|
|
|
|
return receipts, allLogs, totalUsedGas, err
|
|
}
|
|
|
|
// ApplyTransaction attempts to apply a transaction to the given state database
|
|
// and uses the input parameters for its environment.
|
|
//
|
|
// ApplyTransactions returns the generated receipts and vm logs during the
|
|
// execution of the state transition phase.
|
|
func ApplyTransaction(config *ChainConfig, bc *BlockChain, gp *GasPool, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, cfg vm.Config) (*types.Receipt, vm.Logs, *big.Int, error) {
|
|
_, gas, err := ApplyMessage(NewEnv(statedb, config, bc, tx, header, cfg), tx, gp)
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
// Update the state with pending changes
|
|
usedGas.Add(usedGas, gas)
|
|
receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas)
|
|
receipt.TxHash = tx.Hash()
|
|
receipt.GasUsed = new(big.Int).Set(gas)
|
|
if MessageCreatesContract(tx) {
|
|
from, _ := tx.From()
|
|
receipt.ContractAddress = crypto.CreateAddress(from, tx.Nonce())
|
|
}
|
|
|
|
logs := statedb.GetLogs(tx.Hash())
|
|
receipt.Logs = logs
|
|
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
|
|
|
|
glog.V(logger.Debug).Infoln(receipt)
|
|
|
|
return receipt, logs, gas, err
|
|
}
|
|
|
|
// AccumulateRewards credits the coinbase of the given block with the
|
|
// mining reward. The total reward consists of the static block reward
|
|
// and rewards for included uncles. The coinbase of each uncle block is
|
|
// also rewarded.
|
|
func AccumulateRewards(statedb *state.StateDB, header *types.Header, uncles []*types.Header) {
|
|
reward := new(big.Int).Set(BlockReward)
|
|
r := new(big.Int)
|
|
for _, uncle := range uncles {
|
|
r.Add(uncle.Number, big8)
|
|
r.Sub(r, header.Number)
|
|
r.Mul(r, BlockReward)
|
|
r.Div(r, big8)
|
|
statedb.AddBalance(uncle.Coinbase, r)
|
|
|
|
r.Div(BlockReward, big32)
|
|
reward.Add(reward, r)
|
|
}
|
|
statedb.AddBalance(header.Coinbase, reward)
|
|
}
|