Example #1
0
// 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.exp.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.exp.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
}
Example #2
0
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
}