// makeCurrent creates a new environment for the current cycle. func (self *worker) makeCurrent(parent *types.Block, header *types.Header) { state := state.New(parent.Root(), self.eth.ChainDb()) work := &Work{ state: state, ancestors: set.New(), family: set.New(), uncles: set.New(), header: header, coinbase: state.GetOrNewStateObject(self.coinbase), createdAt: time.Now(), } // when 08 is processed ancestors contain 07 (quick block) for _, ancestor := range self.chain.GetBlocksFromHash(parent.Hash(), 7) { for _, uncle := range ancestor.Uncles() { work.family.Add(uncle.Hash()) } work.family.Add(ancestor.Hash()) work.ancestors.Add(ancestor.Hash()) } accounts, _ := self.eth.AccountManager().Accounts() // Keep track of transactions which return errors so they can be removed work.remove = set.New() work.tcount = 0 work.ignoredTransactors = set.New() work.lowGasTransactors = set.New() work.ownedAccounts = accountAddressesSet(accounts) if self.current != nil { work.localMinedBlocks = self.current.localMinedBlocks } self.current = work }
func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) { // TODO: depth is increased but never checked by VM. VM should not know about it at all. self.env.SetDepth(self.env.Depth() + 1) // TODO: Move it to Env.Call() or sth if Precompiled[string(me.Address())] != nil { // if it's address of precopiled contract // fallback to standard VM stdVm := New(self.env) return stdVm.Run(me, caller, code, value, gas, price, callData) } if self.me != nil { panic("JitVm.Run() can be called only once per JitVm instance") } self.me = me self.callerAddr = caller.Address() self.price = price self.data.gas = gas.Int64() self.data.gasPrice = price.Int64() self.data.callData = getDataPtr(callData) self.data.callDataSize = uint64(len(callData)) self.data.address = address2llvm(self.me.Address()) self.data.caller = address2llvm(caller.Address()) self.data.origin = address2llvm(self.env.Origin()) self.data.callValue = big2llvm(value) self.data.coinBase = address2llvm(self.env.Coinbase()) self.data.difficulty = big2llvm(self.env.Difficulty()) self.data.gasLimit = big2llvm(self.env.GasLimit()) self.data.number = self.env.BlockNumber().Uint64() self.data.timestamp = self.env.Time() self.data.code = getDataPtr(code) self.data.codeSize = uint64(len(code)) self.data.codeHash = hash2llvm(crypto.Sha3(code)) // TODO: Get already computed hash? jit := C.evmjit_create() retCode := C.evmjit_run(jit, unsafe.Pointer(&self.data), unsafe.Pointer(self)) if retCode < 0 { err = errors.New("OOG from JIT") gas.SetInt64(0) // Set gas to 0, JIT does not bother } else { gas.SetInt64(self.data.gas) if retCode == 1 { // RETURN ret = C.GoBytes(unsafe.Pointer(self.data.callData), C.int(self.data.callDataSize)) } else if retCode == 2 { // SUICIDE // TODO: Suicide support logic should be moved to Env to be shared by VM implementations state := self.Env().State() receiverAddr := llvm2hashRef(bswap(&self.data.address)) receiver := state.GetOrNewStateObject(receiverAddr) balance := state.GetBalance(me.Address()) receiver.AddBalance(balance) state.Delete(me.Address()) } } C.evmjit_destroy(jit) return }