Skip to content

Commit

Permalink
Merge pull request ethereum#6 from CortexFoundation/ucwong
Browse files Browse the repository at this point in the history
Ucwong
  • Loading branch information
ucwong authored May 26, 2018
2 parents 90fd2a2 + 3c050ab commit c1016a6
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 66 deletions.
20 changes: 18 additions & 2 deletions accounts/abi/bind/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ func DeployModelMetaContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, b
if err != nil {
return common.Address{}, nil, nil, err
}
tx, err := c.transact(opts, nil, append(make([]byte{0, 0, 0, 0, 0, 0, 0, 0}), bytecode, input...))
tx, err := c.transact(opts, nil, append([]byte{'0','1'},append(bytecode, input...)...))
if err != nil {
return common.Address{}, nil, nil, err
}
Expand All @@ -137,7 +137,23 @@ func DeployInputMetaContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, b
if err != nil {
return common.Address{}, nil, nil, err
}
tx, err := c.transact(opts, nil, append(make([]byte{1, 1, 1, 1, 1, 1, 1, 1}), bytecode, input...))
tx, err := c.transact(opts, nil, append([]byte{'0','2'},append(bytecode, input...)...))
if err != nil {
return common.Address{}, nil, nil, err
}
c.address = crypto.CreateAddress(opts.From, tx.Nonce())
return c.address, tx, c, nil
}

func DeployCodeContract(opts *TransactOpts, abi abi.ABI, bytecode []byte, backend ContractBackend, params ...interface{}) (common.Address, *types.Transaction, *BoundContract, error) {
// Otherwise try to deploy the contract
c := NewBoundContract(common.Address{}, abi, backend, backend, backend)

input, err := c.abi.Pack("", params...)
if err != nil {
return common.Address{}, nil, nil, err
}
tx, err := c.transact(opts, nil, append([]byte{'0','0'},append(bytecode, input...)...))
if err != nil {
return common.Address{}, nil, nil, err
}
Expand Down
6 changes: 5 additions & 1 deletion core/state_transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ type StateTransition struct {
data []byte
state vm.StateDB
evm *vm.EVM
modelGas map[common.Address]uint64
}

// Message represents a message sent to a contract.
Expand Down Expand Up @@ -210,7 +211,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
} else {
// Increment the nonce for the next transaction
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
ret, st.gas, st.modelGas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
}
if vmerr != nil {
log.Debug("VM returned with error", "err", vmerr)
Expand All @@ -223,6 +224,9 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
}
st.refundGas()
st.state.AddBalance(st.evm.Coinbase, new(big.Int).Mul(new(big.Int).SetUint64(st.gasUsed()), st.gasPrice))
for addr, mgas := range st.modelGas {
st.state.AddBalance(addr, new(big.Int).Mul(new(big.Int).SetUint64(mgas), st.gasPrice))
}

return ret, st.gasUsed(), vmerr != nil, err
}
Expand Down
13 changes: 12 additions & 1 deletion core/vm/contract.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ type Contract struct {
Args []byte

DelegateCall bool
ModelGas map[common.Address]uint64
}

// NewContract returns a new contract environment for the execution of EVM.
func NewContract(caller ContractRef, object ContractRef, value *big.Int, gas uint64) *Contract {
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil}
c := &Contract{CallerAddress: caller.Address(), caller: caller, self: object, Args: nil, ModelGas:make(map[common.Address]uint64)}

if parent, ok := caller.(*Contract); ok {
// Reuse JUMPDEST analysis from parent context if available.
Expand Down Expand Up @@ -128,6 +129,16 @@ func (c *Contract) UseGas(gas uint64) (ok bool) {
return true
}

// Use model Gas attempts the use gas and subtracts it and returns true on success
func (c *Contract) UseModelGas(address common.Address, gas uint64) (ok bool) {
if c.Gas < gas {
return false
}
c.ModelGas[address] += gas
//c.Gas -= gas
return true
}

// Address returns the contracts address
func (c *Contract) Address() common.Address {
return c.self.Address()
Expand Down
24 changes: 12 additions & 12 deletions core/vm/evm.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,18 +136,18 @@ func (evm *EVM) Cancel() {
// parameters. It also handles any necessary value transfer required and takes
// the necessary steps to create accounts and reverses the state in case of an
// execution error or failed value transfer.
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, err error) {
func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas uint64, value *big.Int) (ret []byte, leftOverGas uint64, modelGas map[common.Address]uint64, err error) {
if evm.vmConfig.NoRecursion && evm.depth > 0 {
return nil, gas, nil
return nil, gas, nil, nil
}

// Fail if we're trying to execute above the call depth limit
if evm.depth > int(params.CallCreateDepth) {
return nil, gas, ErrDepth
return nil, gas, nil, ErrDepth
}
// Fail if we're trying to transfer more than the available balance
if !evm.Context.CanTransfer(evm.StateDB, caller.Address(), value) {
return nil, gas, ErrInsufficientBalance
return nil, gas, nil, ErrInsufficientBalance
}

var (
Expand All @@ -160,7 +160,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
precompiles = PrecompiledContractsByzantium
}
if precompiles[addr] == nil && evm.ChainConfig().IsEIP158(evm.BlockNumber) && value.Sign() == 0 {
return nil, gas, nil
return nil, gas, nil, nil
}
evm.StateDB.CreateAccount(addr)
}
Expand Down Expand Up @@ -193,13 +193,13 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
}
}

if evm.interpreter.IsModelMeta(ret) {
//only if model is exist from ipfs, swarm or libtorrent ext, load model to memory
//todo if ret is model meta, pay some fee to model owner depends on set in meta data
// if exist
//evm.Transfer(evm.StateDB, caller.Address(), model.Owner,model.Fee)
}
return ret, contract.Gas, err
//if evm.interpreter.IsModelMeta(ret) {
//only if model is exist from ipfs, swarm or libtorrent ext, load model to memory
//todo if ret is model meta, pay some fee to model owner depends on set in meta data
// if exist
//evm.Transfer(evm.StateDB, caller.Address(), model.Owner,model.Fee)
//}
return ret, contract.Gas, contract.ModelGas, err
}

// CallCode executes the contract associated with the addr with the given input
Expand Down
2 changes: 1 addition & 1 deletion core/vm/instructions.go
Original file line number Diff line number Diff line change
Expand Up @@ -679,7 +679,7 @@ func opCall(pc *uint64, evm *EVM, contract *Contract, memory *Memory, stack *Sta
if value.Sign() != 0 {
gas += params.CallStipend
}
ret, returnGas, err := evm.Call(contract, toAddr, args, gas, value)
ret, returnGas, _, err := evm.Call(contract, toAddr, args, gas, value)
if err != nil {
stack.push(evm.interpreter.intPool.getZero())
} else {
Expand Down
105 changes: 60 additions & 45 deletions core/vm/interpreter.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,23 +96,28 @@ func (in *Interpreter) enforceRestrictions(op OpCode, operation operation, stack
}
return nil
}

func IsCode(code []byte) bool {
if code[0] == 0 && code[1] == 0 {
return true
}
return false
}
func IsModelMeta(code []byte) bool {
for i := 0; i < 8; i++ {
if code[i] != 0 {
return false
}
if code[0] == 0 && code[1] == 1 {
return true
}
return true
return false
}

func IsInputMeta(code []byte) bool {
for i := 0; i < 8; i++ {
if code[i] != 1 {
return false
}
if code[0] == 0 && code[1] == 0 {
return true
}
return true
return false
}

func IsInfer(op *operation) bool {
return false
}

// Run loops and evaluates the contract's code with the given input data and returns
Expand All @@ -136,10 +141,12 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er
}

if IsModelMeta(contract.Code) {
//todo
return contract.Code, nil
}

if IsInputMeta(contract.Code) {
//todo
return contract.Code, nil
}

Expand Down Expand Up @@ -174,6 +181,10 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er
// explicit STOP, RETURN or SELFDESTRUCT is executed, an error occurred during
// the execution of one of the operations or until the done flag is set by the
// parent context.
if IsCode(contract.Code) {
contract.Code = contract.Code[2:]
}

for atomic.LoadInt32(&in.evm.abort) == 0 {
if in.cfg.Debug {
// Capture pre-execution values for tracing.
Expand Down Expand Up @@ -209,43 +220,47 @@ func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err er
return nil, errGasUintOverflow
}
}
// consume the gas and return an error if not enough gas is available.
// cost is explicitly set so that the capture state defer method can get the proper cost
cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize)
if err != nil || !contract.UseGas(cost) {
return nil, ErrOutOfGas
}
if memorySize > 0 {
mem.Resize(memorySize)
}
if IsInfer(&operation) {
//todo
} else {
// consume the gas and return an error if not enough gas is available.
// cost is explicitly set so that the capture state defer method can get the proper cost
cost, err = operation.gasCost(in.gasTable, in.evm, contract, stack, mem, memorySize)

if in.cfg.Debug {
in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err)
logged = true
}
if err != nil || !contract.UseGas(cost) {
return nil, ErrOutOfGas
}
if memorySize > 0 {
mem.Resize(memorySize)
}

// execute the operation
res, err := operation.execute(&pc, in.evm, contract, mem, stack)
// verifyPool is a build flag. Pool verification makes sure the integrity
// of the integer pool by comparing values to a default value.
if verifyPool {
verifyIntegerPool(in.intPool)
}
// if the operation clears the return data (e.g. it has returning data)
// set the last return to the result of the operation.
if operation.returns {
in.returnData = res
}
if in.cfg.Debug {
in.cfg.Tracer.CaptureState(in.evm, pc, op, gasCopy, cost, mem, stack, contract, in.evm.depth, err)
logged = true
}

switch {
case err != nil:
return nil, err
case operation.reverts:
return res, errExecutionReverted
case operation.halts:
return res, nil
case !operation.jumps:
pc++
// execute the operation
res, err := operation.execute(&pc, in.evm, contract, mem, stack)
// verifyPool is a build flag. Pool verification makes sure the integrity
// of the integer pool by comparing values to a default value.
if verifyPool {
verifyIntegerPool(in.intPool)
}
// if the operation clears the return data (e.g. it has returning data)
// set the last return to the result of the operation.
if operation.returns {
in.returnData = res
}
switch {
case err != nil:
return nil, err
case operation.reverts:
return res, errExecutionReverted
case operation.halts:
return res, nil
case !operation.jumps:
pc++
}
}
}
return nil, nil
Expand Down
4 changes: 2 additions & 2 deletions core/vm/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ func Execute(code, input []byte, cfg *Config) ([]byte, *state.StateDB, error) {
// set the receiver's (the executing contract) code for execution.
cfg.State.SetCode(address, code)
// Call the code with the given configuration.
ret, _, err := vmenv.Call(
ret, _,_, err := vmenv.Call(
sender,
common.BytesToAddress([]byte("contract")),
input,
Expand Down Expand Up @@ -160,7 +160,7 @@ func Call(address common.Address, input []byte, cfg *Config) ([]byte, uint64, er

sender := cfg.State.GetOrNewStateObject(cfg.Origin)
// Call the code with the given configuration.
ret, leftOverGas, err := vmenv.Call(
ret, leftOverGas,_, err := vmenv.Call(
sender,
address,
input,
Expand Down
4 changes: 2 additions & 2 deletions tests/vm_test_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ type vmExecMarshaling struct {
func (t *VMTest) Run(vmconfig vm.Config) error {
db, _ := ethdb.NewMemDatabase()
statedb := MakePreState(db, t.json.Pre)
ret, gasRemaining, err := t.exec(statedb, vmconfig)
ret, gasRemaining,_, err := t.exec(statedb, vmconfig)

if t.json.GasRemaining == nil {
if err == nil {
Expand Down Expand Up @@ -115,7 +115,7 @@ func (t *VMTest) Run(vmconfig vm.Config) error {
return nil
}

func (t *VMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint64, error) {
func (t *VMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint64, map[common.Address]uint64, error) {
evm := t.newEVM(statedb, vmconfig)
e := t.json.Exec
return evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, e.Value)
Expand Down

0 comments on commit c1016a6

Please sign in to comment.