Skip to content

Commit

Permalink
Rebuild ievmh (ethereum#317)
Browse files Browse the repository at this point in the history
Rebuild contract_communication interfaces as pure functions
  • Loading branch information
kevjue authored and jarmg committed Jul 31, 2019
1 parent c99c3ed commit 230af6c
Show file tree
Hide file tree
Showing 46 changed files with 884 additions and 1,158 deletions.
8 changes: 7 additions & 1 deletion accounts/abi/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,11 @@ package abi
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"

"github.com/ethereum/go-ethereum/log"
)

// The ABI holds information about a contract's context and available
Expand All @@ -32,6 +35,8 @@ type ABI struct {
Events map[string]Event
}

var ErrEmptyOutput = errors.New("abi: unmarshalling empty output")

// JSON returns a parsed ABI interface and error if it failed.
func JSON(reader io.Reader) (ABI, error) {
dec := json.NewDecoder(reader)
Expand Down Expand Up @@ -74,7 +79,8 @@ func (abi ABI) Pack(name string, args ...interface{}) ([]byte, error) {
// Unpack output in v according to the abi specification
func (abi ABI) Unpack(v interface{}, name string, output []byte) (err error) {
if len(output) == 0 {
return fmt.Errorf("abi: unmarshalling empty output")
log.Trace("Returning empty output error from abi unpacking")
return ErrEmptyOutput
}
// since there can't be naming collisions with contracts and events,
// we need to decide whether we're calling a method or an event
Expand Down
4 changes: 2 additions & 2 deletions accounts/abi/bind/backends/simulated.go
Original file line number Diff line number Diff line change
Expand Up @@ -282,13 +282,13 @@ func (b *SimulatedBackend) callContract(ctx context.Context, call ethereum.CallM
// Execute the call.
msg := callmsg{call}

evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil, nil)
evmContext := core.NewEVMContext(msg, block.Header(), b.blockchain, nil)
// Create a new environment which holds all relevant information
// about the transaction and calling mechanisms.
vmenv := vm.NewEVM(evmContext, statedb, b.config, vm.Config{})
gaspool := new(core.GasPool).AddGas(math.MaxUint64)

return core.NewStateTransition(vmenv, msg, gaspool, nil, core.FallbackGasPriceMinimum, core.FallbackInfraFraction, nil).TransitionDb()
return core.NewStateTransition(vmenv, msg, gaspool).TransitionDb()
}

// SendTransaction updates the pending block to include the given transaction.
Expand Down
23 changes: 0 additions & 23 deletions consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ package consensus
import (
"math/big"

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -51,21 +50,6 @@ type ChainReader interface {
GetBlock(hash common.Hash, number uint64) *types.Block
}

type ConsensusIEvmH interface {
MakeStaticCall(scAddress common.Address, abi abi.ABI, funcName string, args []interface{}, returnObj interface{}, gas uint64, header *types.Header, state *state.StateDB) (uint64, error)
MakeCall(scAddress common.Address, abi abi.ABI, funcName string, args []interface{}, returnObj interface{}, gas uint64, value *big.Int, header *types.Header, state *state.StateDB) (uint64, error)
}

type ConsensusRegAdd interface {
GetRegisteredAddressAtStateAndHeader(registryId string, state *state.StateDB, header *types.Header) (*common.Address, error)
GetRegisteredAddressAtCurrentHeader(registryId string) (*common.Address, error)
GetRegisteredAddressMapAtStateAndHeader(state *state.StateDB, header *types.Header) map[string]*common.Address
}

type ConsensusGasPriceMinimum interface {
UpdateGasPriceMinimum(header *types.Header, state *state.StateDB) (*big.Int, error)
}

// Engine is an algorithm agnostic consensus engine.
type Engine interface {
// Author retrieves the Ethereum address of the account that minted the given
Expand Down Expand Up @@ -150,13 +134,6 @@ type PoW interface {
type Istanbul interface {
Engine

// Setter functions
SetInternalEVMHandler(iEvmH ConsensusIEvmH)

SetRegisteredAddresses(regAdd ConsensusRegAdd)

SetGasPriceMinimum(gpm ConsensusGasPriceMinimum)

SetChain(chain ChainReader, currentBlock func() *types.Block)

// Start starts the engine
Expand Down
4 changes: 0 additions & 4 deletions consensus/istanbul/backend/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,6 @@ type Backend struct {
recentMessages *lru.ARCCache // the cache of peer's messages
knownMessages *lru.ARCCache // the cache of self messages

iEvmH consensus.ConsensusIEvmH
regAdd consensus.ConsensusRegAdd
gpm consensus.ConsensusGasPriceMinimum

lastAnnounceGossiped map[common.Address]*AnnounceGossipTimestamp

valEnodeTable *validatorEnodeTable
Expand Down
55 changes: 22 additions & 33 deletions consensus/istanbul/backend/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ import (
"github.com/ethereum/go-ethereum/consensus/istanbul"
istanbulCore "github.com/ethereum/go-ethereum/consensus/istanbul/core"
"github.com/ethereum/go-ethereum/consensus/istanbul/validator"
"github.com/ethereum/go-ethereum/contract_comm"
contract_errors "github.com/ethereum/go-ethereum/contract_comm/errors"
gpm "github.com/ethereum/go-ethereum/contract_comm/gasprice_minimum"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -423,20 +426,19 @@ func (sb *Backend) Prepare(chain consensus.ChainReader, header *types.Header) er

func (sb *Backend) getValSet(header *types.Header, state *state.StateDB) ([]common.Address, error) {
var newValSet []common.Address
validatorsAddress, err := sb.regAdd.GetRegisteredAddressAtStateAndHeader(params.ValidatorsRegistryId, state, header)
if err == core.ErrSmartContractNotDeployed {
log.Warn("Registry address lookup failed", "err", err)
// Get the new epoch's validator set
maxGasForGetValidators := uint64(1000000)
// TODO(asa) - Once the validator election smart contract is completed, then a more accurate gas value should be used.
_, err := contract_comm.MakeStaticCall(params.ValidatorsRegistryId, getValidatorsFuncABI, "getValidators", []interface{}{}, &newValSet, maxGasForGetValidators, header, state)

if err == contract_errors.ErrSmartContractNotDeployed {
log.Warn("Registry address lookup failed", "err", err, "contract id", params.ValidatorsRegistryId)
return newValSet, errValidatorsContractNotRegistered
} else if err != nil {
log.Error(err.Error())
return newValSet, err
} else {
// Get the new epoch's validator set
maxGasForGetValidators := uint64(10000000)
// TODO(asa) - Once the validator election smart contract is completed, then a more accurate gas value should be used.
_, err := sb.iEvmH.MakeStaticCall(*validatorsAddress, getValidatorsFuncABI, "getValidators", []interface{}{}, &newValSet, maxGasForGetValidators, header, state)
return newValSet, err
}
return newValSet, err
}

// UpdateValSetDiff will update the validator set diff in the header, if the mined header is the last block of the epoch
Expand Down Expand Up @@ -484,14 +486,14 @@ func (sb *Backend) IsLastBlockOfEpoch(header *types.Header) bool {
// consensus rules that happen at finalization (e.g. block rewards).
func (sb *Backend) Finalize(chain consensus.ChainReader, header *types.Header, state *state.StateDB, txs []*types.Transaction, uncles []*types.Header, receipts []*types.Receipt, randomness *types.Randomness) (*types.Block, error) {
// Trigger an update to the gas price minimum in the GasPriceMinimum contract based on block congestion
updatedGasPriceMinimum, err := sb.gpm.UpdateGasPriceMinimum(header, state)
updatedGasPriceMinimum, err := gpm.UpdateGasPriceMinimum(header, state)

if err != nil {
log.Error("Error in updating gas price minimum", "error", err, "updatedGasPriceMinimum", updatedGasPriceMinimum)
}

goldTokenAddress, err := sb.regAdd.GetRegisteredAddressAtStateAndHeader(params.GoldTokenRegistryId, state, header)
if err == core.ErrSmartContractNotDeployed {
goldTokenAddress, err := contract_comm.GetRegisteredAddress(params.GoldTokenRegistryId, header, state)
if err == contract_errors.ErrSmartContractNotDeployed {
log.Warn("Registry address lookup failed", "err", err)
} else if err != nil {
log.Error(err.Error())
Expand All @@ -501,8 +503,8 @@ func (sb *Backend) Finalize(chain consensus.ChainReader, header *types.Header, s
totalBlockRewards := big.NewInt(0)

infrastructureBlockReward := big.NewInt(params.Ether)
governanceAddress, err := sb.regAdd.GetRegisteredAddressAtStateAndHeader(params.GovernanceRegistryId, state, header)
if err == core.ErrSmartContractNotDeployed {
governanceAddress, err := contract_comm.GetRegisteredAddress(params.GovernanceRegistryId, header, state)
if err == contract_errors.ErrSmartContractNotDeployed {
log.Warn("Registry address lookup failed", "err", err)
} else if err != nil {
log.Error(err.Error())
Expand All @@ -514,17 +516,17 @@ func (sb *Backend) Finalize(chain consensus.ChainReader, header *types.Header, s
}

stakerBlockReward := big.NewInt(params.Ether)
bondedDepositsAddress, err := sb.regAdd.GetRegisteredAddressAtStateAndHeader(params.BondedDepositsRegistryId, state, header)
if err == core.ErrSmartContractNotDeployed {
log.Warn("Registry address lookup failed", "err", err)
bondedDepositsAddress, err := contract_comm.GetRegisteredAddress(params.BondedDepositsRegistryId, header, state)
if err == contract_errors.ErrSmartContractNotDeployed {
log.Warn("Registry address lookup failed", "err", err, "contract id", params.BondedDepositsRegistryId)
} else if err != nil {
log.Error(err.Error())
}

if bondedDepositsAddress != nil {
state.AddBalance(*bondedDepositsAddress, stakerBlockReward)
totalBlockRewards.Add(totalBlockRewards, stakerBlockReward)
_, err := sb.iEvmH.MakeCall(*bondedDepositsAddress, setCumulativeRewardWeightFuncABI, "setCumulativeRewardWeight", []interface{}{stakerBlockReward}, nil, 1000000, common.Big0, header, state)
_, err := contract_comm.MakeCallWithAddress(*bondedDepositsAddress, setCumulativeRewardWeightFuncABI, "setCumulativeRewardWeight", []interface{}{stakerBlockReward}, nil, 1000000, common.Big0, header, state)
if err != nil {
log.Error("Unable to send block rewards to bonded deposits", "err", err)
return nil, err
Expand All @@ -534,7 +536,7 @@ func (sb *Backend) Finalize(chain consensus.ChainReader, header *types.Header, s
// Update totalSupply of GoldToken.
if totalBlockRewards.Cmp(common.Big0) > 0 {
var totalSupply *big.Int
if _, err := sb.iEvmH.MakeStaticCall(*goldTokenAddress, totalSupplyFuncABI, "totalSupply", []interface{}{}, &totalSupply, 1000000, header, state); err != nil || totalSupply == nil {
if _, err := contract_comm.MakeStaticCallWithAddress(*goldTokenAddress, totalSupplyFuncABI, "totalSupply", []interface{}{}, &totalSupply, 1000000, header, state); err != nil || totalSupply == nil {
log.Error("Unable to retrieve total supply from the Gold token smart contract", "err", err)
return nil, err
}
Expand All @@ -548,7 +550,7 @@ func (sb *Backend) Finalize(chain consensus.ChainReader, header *types.Header, s
genesisSupply.SetBytes(data)
totalBlockRewards.Add(totalBlockRewards, genesisSupply)
}
if _, err := sb.iEvmH.MakeCall(*goldTokenAddress, increaseSupplyFuncABI, "increaseSupply", []interface{}{totalBlockRewards}, nil, 1000000, common.Big0, header, state); err != nil {
if _, err := contract_comm.MakeCallWithAddress(*goldTokenAddress, increaseSupplyFuncABI, "increaseSupply", []interface{}{totalBlockRewards}, nil, 1000000, common.Big0, header, state); err != nil {
log.Error("Unable to increment goldTotalSupply for block reward", "err", err)
return nil, err
}
Expand Down Expand Up @@ -667,19 +669,6 @@ func (sb *Backend) APIs(chain consensus.ChainReader) []rpc.API {
}}
}

// Setter functions
func (sb *Backend) SetInternalEVMHandler(iEvmH consensus.ConsensusIEvmH) {
sb.iEvmH = iEvmH
}

func (sb *Backend) SetRegisteredAddresses(regAdd consensus.ConsensusRegAdd) {
sb.regAdd = regAdd
}

func (sb *Backend) SetGasPriceMinimum(gpm consensus.ConsensusGasPriceMinimum) {
sb.gpm = gpm
}

func (sb *Backend) SetChain(chain consensus.ChainReader, currentBlock func() *types.Block) {
sb.chain = chain
sb.currentBlock = currentBlock
Expand Down
11 changes: 3 additions & 8 deletions consensus/istanbul/backend/engine_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/istanbul"
"github.com/ethereum/go-ethereum/contract_comm"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
Expand Down Expand Up @@ -61,14 +62,6 @@ func newBlockChain(n int, isFullChain bool) (*core.BlockChain, *Backend) {
panic(err)
}

iEvmH := core.NewInternalEVMHandler(blockchain)
regAdd := core.NewRegisteredAddresses(iEvmH)
gpm := core.NewGasPriceMinimum(iEvmH, regAdd)
iEvmH.SetRegisteredAddresses(regAdd)

b.SetInternalEVMHandler(iEvmH)
b.SetRegisteredAddresses(regAdd)
b.SetGasPriceMinimum(gpm)
b.SetChain(blockchain, blockchain.CurrentBlock)

b.Start(blockchain.HasBadBlock,
Expand Down Expand Up @@ -102,6 +95,8 @@ func newBlockChain(n int, isFullChain bool) (*core.BlockChain, *Backend) {
}
}

contract_comm.SetInternalEVMHandler(blockchain)

return blockchain, b
}

Expand Down
14 changes: 5 additions & 9 deletions consensus/istanbul/backend/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/contract_comm"
"github.com/ethereum/go-ethereum/params"
)

Expand Down Expand Up @@ -50,15 +51,10 @@ var (
func (sb *Backend) retrieveRegisteredValidators() (map[common.Address]bool, error) {
var regVals []common.Address

validatorAddress, _ := sb.regAdd.GetRegisteredAddressAtCurrentHeader(params.ValidatorsRegistryId)
if validatorAddress == nil {
return nil, errValidatorsContractNotRegistered
} else {
// Get the new epoch's validator set
maxGasForGetRegisteredValidators := uint64(1000000)
if _, err := sb.iEvmH.MakeStaticCall(*validatorAddress, getRegisteredValidatorsFuncABI, "getRegisteredValidators", []interface{}{}, &regVals, maxGasForGetRegisteredValidators, nil, nil); err != nil {
return nil, err
}
// Get the new epoch's validator set
maxGasForGetRegisteredValidators := uint64(1000000)
if _, err := contract_comm.MakeStaticCall(params.ValidatorsRegistryId, getRegisteredValidatorsFuncABI, "getRegisteredValidators", []interface{}{}, &regVals, maxGasForGetRegisteredValidators, nil, nil); err != nil {
return nil, err
}

returnMap := make(map[common.Address]bool)
Expand Down
Loading

0 comments on commit 230af6c

Please sign in to comment.