func (d *Debugger) halting(pc int, op ethvm.OpCode, mem *ethvm.Memory, stack *ethvm.Stack, stateObject *ethstate.StateObject) bool { d.win.Root().Call("setInstruction", pc) d.win.Root().Call("clearMem") d.win.Root().Call("clearStack") d.win.Root().Call("clearStorage") addr := 0 for i := 0; i+32 <= mem.Len(); i += 32 { d.win.Root().Call("setMem", memAddr{fmt.Sprintf("%03d", addr), fmt.Sprintf("% x", mem.Data()[i:i+32])}) addr++ } for _, val := range stack.Data() { d.win.Root().Call("setStack", val.String()) } stateObject.EachStorage(func(key string, node *ethutil.Value) { d.win.Root().Call("setStorage", storeVal{fmt.Sprintf("% x", key), fmt.Sprintf("% x", node.Str())}) }) out: for { select { case <-d.N: break out case <-d.Q: d.interrupt = true d.clearBuffers() return false } } return true }
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 *StateManager) ProcessTransactions(coinbase *ethstate.StateObject, state *ethstate.State, block, parent *Block, txs Transactions) (Receipts, Transactions, Transactions, error) { var ( receipts Receipts handled, unhandled Transactions totalUsedGas = big.NewInt(0) err error ) done: for i, tx := range txs { txGas := new(big.Int).Set(tx.Gas) cb := state.GetStateObject(coinbase.Address()) st := NewStateTransition(cb, tx, state, block) err = st.TransitionState() if err != nil { statelogger.Infoln(err) switch { case IsNonceErr(err): err = nil // ignore error continue case IsGasLimitErr(err): unhandled = txs[i:] break done default: statelogger.Infoln(err) err = nil //return nil, nil, nil, err } } // Notify all subscribers self.Ethereum.Reactor().Post("newTx:post", tx) // Update the state with pending changes state.Update() txGas.Sub(txGas, st.gas) accumelative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas)) receipt := &Receipt{tx, ethutil.CopyBytes(state.Root().([]byte)), accumelative} if i < len(block.Receipts()) { original := block.Receipts()[i] if !original.Cmp(receipt) { return nil, nil, nil, fmt.Errorf("err diff #%d (r) %v ~ %x <=> (c) %v ~ %x (%x)\n", i+1, original.CumulativeGasUsed, original.PostState[0:4], receipt.CumulativeGasUsed, receipt.PostState[0:4], receipt.Tx.Hash()) } } receipts = append(receipts, receipt) handled = append(handled, tx) if ethutil.Config.Diff && ethutil.Config.DiffType == "all" { state.CreateOutputForDiff() } } parent.GasUsed = totalUsedGas return receipts, handled, unhandled, err }
func NewStateTransition(coinbase *ethstate.StateObject, tx *Transaction, state *ethstate.State, block *Block) *StateTransition { return &StateTransition{coinbase.Address(), tx.Recipient, tx, new(big.Int), new(big.Int).Set(tx.GasPrice), tx.Value, tx.Data, state, block, coinbase, nil, 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 }