diff --git a/core/state_processor.go b/core/state_processor.go index c568e7d7b..9df48f285 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -17,6 +17,11 @@ package core import ( + "math" + "math/big" + "strings" + + "github.com/ethereum/go-ethereum/accounts/abi" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc" @@ -24,6 +29,7 @@ import ( "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/log" "github.com/ethereum/go-ethereum/params" ) @@ -87,6 +93,11 @@ func (p *StateProcessor) Process(block *types.Block, statedb, privateState *stat allLogs = append(allLogs, privateReceipt.Logs...) } } + + if p.config.BlockReward != nil { + CallBlockReward(statedb, p.bc, header, p.config) + } + // Finalize the block, applying any consensus engine specific extras (e.g. block rewards) p.engine.Finalize(p.bc, header, statedb, block.Transactions(), block.Uncles()) @@ -171,3 +182,30 @@ func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author *common return receipt, privateReceipt, err } + +func CallBlockReward(state *state.StateDB, bc *BlockChain, header *types.Header, config *params.ChainConfig) { + var from = common.HexToAddress("0x0") + var to common.Address = config.BlockReward.Contract + var bigZero = big.NewInt(0) + var gas uint64 = math.MaxUint64 + log.Trace("Call to block reward contract", "address", to) + abi, _ := abi.JSON(strings.NewReader(`[{"type":"function","name":"reward","constant":false,"inputs":[{"name":"benefactors","type":"address[]"},{"name":"kind","type":"uint16[]"}],"outputs":[{"name":"receivers","type":"address[]"},{"name":"values","type":"uint256[]"}]}]`)) + calldata, _ := abi.Pack("reward", [0]common.Address{}, [0]uint16{}) + msg := types.NewMessage(from, &to, 0, bigZero, gas, bigZero, calldata, false) + evmContext := NewEVMContext(msg, header, bc, nil) + // Create a new environment which holds all relevant information + // about the transaction and calling mechanisms. + evm := vm.NewEVM(evmContext, state, state, config, vm.Config{}) + gaspool := new(GasPool).AddGas(gas) + ret, _, _, _ := NewStateTransition(evm, msg, gaspool).TransitionDb() + + receivers := make([]common.Address, 0, 1) + values := make([]*big.Int, 0, 1) + _ = abi.Unpack(&[]interface{}{&receivers, &values}, "reward", ret) + + state.SetNonce(from, 0) + for i, receiver := range receivers { + log.Trace("Minting coins", "receiver", receiver, "values", *values[i]) + state.AddBalance(receiver, values[i]) + } +} diff --git a/miner/worker.go b/miner/worker.go index 12802cfb2..e25f82ab5 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1048,6 +1048,11 @@ func (w *worker) commit(uncles []*types.Header, interval func(), update bool, st s := w.current.state.Copy() ps := w.current.privateState.Copy() + + if w.chainConfig.BlockReward != nil { + core.CallBlockReward(s, w.chain, w.current.header, w.chainConfig) + } + block, err := w.engine.FinalizeAndAssemble(w.chain, w.current.header, s, w.current.txs, uncles, w.current.receipts) if err != nil { return err diff --git a/params/config.go b/params/config.go index bcc8313ab..0bd19d02c 100644 --- a/params/config.go +++ b/params/config.go @@ -214,19 +214,19 @@ var ( // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, false, 32, 32, big.NewInt(0), big.NewInt(0), nil} + AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, false, 32, 32, big.NewInt(0), big.NewInt(0), nil, nil} // AllCliqueProtocolChanges contains every protocol change (EIPs) introduced // and accepted by the Ethereum core developers into the Clique consensus. // // This configuration is intentionally not using keyed fields to force anyone // adding flags to the config to also have to set these fields. - AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, false, 32, 32, big.NewInt(0), big.NewInt(0), nil} + AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil, false, 32, 32, big.NewInt(0), big.NewInt(0), nil, nil} - TestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, false, 32, 32, big.NewInt(0), big.NewInt(0), nil} + TestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, false, 32, 32, big.NewInt(0), big.NewInt(0), nil, nil} TestRules = TestChainConfig.Rules(new(big.Int)) - QuorumTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, true, 64, 32, big.NewInt(0), big.NewInt(0), nil} + QuorumTestChainConfig = &ChainConfig{big.NewInt(10), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, new(EthashConfig), nil, nil, true, 64, 32, big.NewInt(0), big.NewInt(0), nil, nil} ) // TrustedCheckpoint represents a set of post-processed trie roots (CHT and @@ -318,6 +318,12 @@ type ChainConfig struct { // to track multiple changes to maxCodeSize MaxCodeSizeConfig []MaxCodeConfigStruct `json:"maxCodeSizeConfig,omitempty"` // Quorum + + BlockReward *BlockRewardConfig `json:"blockRewardConfig,omitempty"` +} + +type BlockRewardConfig struct { + Contract common.Address `json:"contract,omitempty"` // Block reward contract address } // EthashConfig is the consensus engine configs for proof-of-work based sealing.