func (self *StateTransition) transferValue(sender, receiver *ethstate.StateObject) error { if sender.Balance.Cmp(self.value) < 0 { return fmt.Errorf("Insufficient funds to transfer value. Req %v, has %v", self.value, sender.Balance) } // 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) return nil }
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(ðstate.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 }