示例#1
0
func (self *StateTransition) TransitionState() (err error) {
	statelogger.Infof("(~) %x\n", self.tx.Hash())

	/*
		defer func() {
			if r := recover(); r != nil {
				logger.Infoln(r)
				err = fmt.Errorf("state transition err %v", r)
			}
		}()
	*/

	// XXX Transactions after this point are considered valid.
	if err = self.preCheck(); err != nil {
		return
	}

	var (
		tx       = self.tx
		sender   = self.Sender()
		receiver *ethstate.StateObject
	)

	defer self.RefundGas()

	// Increment the nonce for the next transaction
	sender.Nonce += 1

	// Transaction gas
	if err = self.UseGas(ethvm.GasTx); err != nil {
		return
	}

	// Pay data gas
	dataPrice := big.NewInt(int64(len(self.data)))
	dataPrice.Mul(dataPrice, ethvm.GasData)
	if err = self.UseGas(dataPrice); err != nil {
		return
	}

	if sender.Balance.Cmp(self.value) < 0 {
		return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Balance)
	}

	var snapshot *ethstate.State
	// If the receiver is nil it's a contract (\0*32).
	if tx.CreatesContract() {
		// Subtract the (irreversible) amount from the senders account
		sender.SubAmount(self.value)

		snapshot = self.state.Copy()

		// Create a new state object for the contract
		receiver = self.MakeStateObject(self.state, tx)
		self.rec = receiver
		if receiver == nil {
			return fmt.Errorf("Unable to create contract")
		}

		// Add the amount to receivers account which should conclude this transaction
		receiver.AddAmount(self.value)
	} else {
		receiver = self.Receiver()

		// Subtract the amount from the senders account
		sender.SubAmount(self.value)
		// Add the amount to receivers account which should conclude this transaction
		receiver.AddAmount(self.value)

		snapshot = self.state.Copy()
	}

	msg := self.state.Manifest().AddMessage(&ethstate.Message{
		To: receiver.Address(), From: sender.Address(),
		Input:  self.tx.Data,
		Origin: sender.Address(),
		Block:  self.block.Hash(), Timestamp: self.block.Time, Coinbase: self.block.Coinbase, Number: self.block.Number,
		Value: self.value,
	})

	// Process the init code and create 'valid' contract
	if IsContractAddr(self.receiver) {
		// Evaluate the initialization script
		// and use the return value as the
		// script section for the state object.
		self.data = nil

		code, err := self.Eval(msg, receiver.Init(), receiver, "init")
		if err != nil {
			self.state.Set(snapshot)

			return fmt.Errorf("Error during init execution %v", err)
		}

		receiver.Code = code
		msg.Output = code
	} else {
		if len(receiver.Code) > 0 {
			ret, err := self.Eval(msg, receiver.Code, receiver, "code")
			if err != nil {
				self.state.Set(snapshot)

				return fmt.Errorf("Error during code execution %v", err)
			}

			msg.Output = ret
		}
	}

	return
}