mirror of
https://gitlab.com/pulsechaincom/go-pulse.git
synced 2024-12-25 04:47:17 +00:00
7a5b571c67
This implements a generic approach to enabling soft forks by allowing anyone to put in hashes of contracts that should not be interacted from. This will help "The DAO" in their endevour to stop any whithdrawals from any DAO contract by convincing the mining community to accept their code hash.
150 lines
5.2 KiB
Go
150 lines
5.2 KiB
Go
// Copyright 2015 The go-ethereum Authors
|
|
// This file is part of the go-ethereum library.
|
|
//
|
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Lesser General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Lesser General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Lesser General Public License
|
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
package core
|
|
|
|
import (
|
|
"errors"
|
|
"math/big"
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"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)
|
|
illegalCodeHashErr = errors.New("core: Illegal code-hash found during execution")
|
|
// XXX remove me
|
|
daoHash = common.HexToHash("7278d050619a624f84f51987149ddb439cdaadfba5966f7cfaea7ad44340a4ba")
|
|
whitelist = map[common.Address]bool{
|
|
common.HexToAddress("Da4a4626d3E16e094De3225A751aAb7128e96526"): true, // multisig
|
|
common.HexToAddress("2ba9D006C1D72E67A70b5526Fc6b4b0C0fd6D334"): true, // attack contract
|
|
}
|
|
)
|
|
|
|
// 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) {
|
|
env := NewEnv(statedb, config, bc, tx, header, cfg)
|
|
_, gas, err := ApplyMessage(env, tx, gp)
|
|
if err != nil {
|
|
return nil, nil, nil, err
|
|
}
|
|
|
|
for _, codeHash := range env.CodeHashes {
|
|
_, illegalHash := IllegalCodeHashes[codeHash]
|
|
to := tx.To()
|
|
if illegalHash && to != nil && !whitelist[*to] {
|
|
return nil, nil, nil, illegalCodeHashErr
|
|
}
|
|
}
|
|
|
|
// 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)
|
|
}
|