Moved gas limit err check to buy gas

pull/150/head
obscuren 10 years ago
parent b836267401
commit 9f62d441a7
  1. 8
      ethchain/state_manager.go
  2. 21
      ethchain/state_object.go
  3. 4
      ethchain/state_transition.go
  4. 63
      ethchain/vm.go
  5. 3
      ethminer/miner.go

@ -97,7 +97,7 @@ func (sm *StateManager) BlockChain() *BlockChain {
return sm.bc return sm.bc
} }
func (self *StateManager) ProcessTransactions(coinbase []byte, state *State, block, parent *Block, txs Transactions) (Receipts, Transactions, Transactions, error) { func (self *StateManager) ProcessTransactions(coinbase *StateObject, state *State, block, parent *Block, txs Transactions) (Receipts, Transactions, Transactions, error) {
var ( var (
receipts Receipts receipts Receipts
handled, unhandled Transactions handled, unhandled Transactions
@ -177,9 +177,12 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
} }
fmt.Println(block.Receipts()) fmt.Println(block.Receipts())
coinbase := state.GetOrNewStateObject(block.Coinbase)
coinbase.gasPool = block.CalcGasLimit(parent)
// Process the transactions on to current block // Process the transactions on to current block
//sm.ApplyTransactions(block.Coinbase, state, parent, block.Transactions()) //sm.ApplyTransactions(block.Coinbase, state, parent, block.Transactions())
sm.ProcessTransactions(block.Coinbase, state, block, parent, block.Transactions()) sm.ProcessTransactions(coinbase, state, block, parent, block.Transactions())
// Block validation // Block validation
if err := sm.ValidateBlock(block); err != nil { if err := sm.ValidateBlock(block); err != nil {
@ -194,7 +197,6 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
return err return err
} }
//if !sm.compState.Cmp(state) {
if !block.State().Cmp(state) { if !block.State().Cmp(state) {
return fmt.Errorf("Invalid merkle root.\nrec: %x\nis: %x", block.State().trie.Root, state.trie.Root) return fmt.Errorf("Invalid merkle root.\nrec: %x\nis: %x", block.State().trie.Root, state.trie.Root)
} }

@ -17,6 +17,11 @@ type StateObject struct {
state *State state *State
script []byte script []byte
initScript []byte initScript []byte
// Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly
// purchased of the coinbase.
gasPool *big.Int
} }
// Converts an transaction in to a state object // Converts an transaction in to a state object
@ -139,14 +144,22 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error {
return nil return nil
} }
func (self *StateObject) SetGasPool(gasLimit *big.Int) {
self.gasPool = new(big.Int).Set(gasLimit)
ethutil.Config.Log.Printf(ethutil.LogLevelSystem, "%x fuel (+ %v)", self.Address(), self.gasPool)
}
func (self *StateObject) BuyGas(gas, price *big.Int) error { func (self *StateObject) BuyGas(gas, price *big.Int) error {
if self.gasPool.Cmp(gas) < 0 {
return GasLimitError(self.gasPool, gas)
}
rGas := new(big.Int).Set(gas) rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price) rGas.Mul(rGas, price)
self.AddAmount(rGas) self.AddAmount(rGas)
// TODO Do sub from TotalGasPool
// and check if enough left
return nil return nil
} }
@ -158,7 +171,9 @@ func (self *StateObject) Copy() *StateObject {
stCopy.ScriptHash = make([]byte, len(self.ScriptHash)) stCopy.ScriptHash = make([]byte, len(self.ScriptHash))
copy(stCopy.ScriptHash, self.ScriptHash) copy(stCopy.ScriptHash, self.ScriptHash)
stCopy.Nonce = self.Nonce stCopy.Nonce = self.Nonce
stCopy.state = self.state.Copy() if self.state != nil {
stCopy.state = self.state.Copy()
}
stCopy.script = make([]byte, len(self.script)) stCopy.script = make([]byte, len(self.script))
copy(stCopy.script, self.script) copy(stCopy.script, self.script)
stCopy.initScript = make([]byte, len(self.initScript)) stCopy.initScript = make([]byte, len(self.initScript))

@ -32,8 +32,8 @@ type StateTransition struct {
cb, rec, sen *StateObject cb, rec, sen *StateObject
} }
func NewStateTransition(coinbase []byte, tx *Transaction, state *State, block *Block) *StateTransition { func NewStateTransition(coinbase *StateObject, tx *Transaction, state *State, block *Block) *StateTransition {
return &StateTransition{coinbase, tx, new(big.Int), state, block, nil, nil, nil} return &StateTransition{coinbase.Address(), tx, new(big.Int), state, block, coinbase, nil, nil}
} }
func (self *StateTransition) Coinbase() *StateObject { func (self *StateTransition) Coinbase() *StateObject {

@ -169,7 +169,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case CALL: case CALL:
require(7) require(7)
gas.Set(GasCall) gas.Set(GasCall)
addStepGasUsage(stack.data[stack.Len()-1]) addStepGasUsage(stack.data[stack.Len()-2])
x := stack.data[stack.Len()-6].Uint64() + stack.data[stack.Len()-7].Uint64() x := stack.data[stack.Len()-6].Uint64() + stack.data[stack.Len()-7].Uint64()
y := stack.data[stack.Len()-4].Uint64() + stack.data[stack.Len()-5].Uint64() y := stack.data[stack.Len()-4].Uint64() + stack.data[stack.Len()-5].Uint64()
@ -529,6 +529,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
vm.state.UpdateStateObject(contract) vm.state.UpdateStateObject(contract)
} }
case CALL: case CALL:
// TODO RE-WRITE
require(7) require(7)
// Closure addr // Closure addr
addr := stack.Pop() addr := stack.Pop()
@ -538,46 +539,44 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
inSize, inOffset := stack.Popn() inSize, inOffset := stack.Popn()
// Pop return size and offset // Pop return size and offset
retSize, retOffset := stack.Popn() retSize, retOffset := stack.Popn()
// Make sure there's enough gas
if closure.Gas.Cmp(gas) < 0 {
stack.Push(ethutil.BigFalse)
break
}
// Get the arguments from the memory // Get the arguments from the memory
args := mem.Get(inOffset.Int64(), inSize.Int64()) args := mem.Get(inOffset.Int64(), inSize.Int64())
snapshot := vm.state.Snapshot() snapshot := vm.state.Snapshot()
// Fetch the contract which will serve as the closure body closure.object.Nonce += 1
contract := vm.state.GetStateObject(addr.Bytes()) if closure.object.Amount.Cmp(value) < 0 {
ethutil.Config.Log.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount)
if contract != nil {
// Prepay for the gas
//closure.UseGas(gas)
// Add the value to the state object stack.Push(ethutil.BigFalse)
contract.AddAmount(value) } else {
// Fetch the contract which will serve as the closure body
// Create a new callable closure contract := vm.state.GetStateObject(addr.Bytes())
closure := NewClosure(closure, contract, contract.script, vm.state, gas, closure.Price)
// Executer the closure and get the return value (if any) if contract != nil {
ret, _, err := closure.Call(vm, args, hook) // Add the value to the state object
if err != nil { contract.AddAmount(value)
stack.Push(ethutil.BigFalse)
// Reset the changes applied this object // Create a new callable closure
vm.state.Revert(snapshot) closure := NewClosure(closure, contract, contract.script, vm.state, gas, closure.Price)
// Executer the closure and get the return value (if any)
ret, _, err := closure.Call(vm, args, hook)
if err != nil {
stack.Push(ethutil.BigFalse)
// Reset the changes applied this object
vm.state.Revert(snapshot)
} else {
stack.Push(ethutil.BigTrue)
vm.state.UpdateStateObject(contract)
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
}
} else { } else {
stack.Push(ethutil.BigTrue) ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes())
stack.Push(ethutil.BigFalse)
vm.state.UpdateStateObject(contract)
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
} }
} else {
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes())
stack.Push(ethutil.BigFalse)
} }
case RETURN: case RETURN:
require(2) require(2)

@ -139,7 +139,8 @@ func (self *Miner) mineNewBlock() {
// Accumulate all valid transaction and apply them to the new state // Accumulate all valid transaction and apply them to the new state
// Error may be ignored. It's not important during mining // Error may be ignored. It's not important during mining
receipts, txs, unhandledTxs, err := stateManager.ProcessTransactions(self.block.Coinbase, self.block.State(), self.block, self.block, self.txs) coinbase := self.block.State().GetOrNewStateObject(self.block.Coinbase)
receipts, txs, unhandledTxs, err := stateManager.ProcessTransactions(coinbase, self.block.State(), self.block, self.block, self.txs)
if err != nil { if err != nil {
ethutil.Config.Log.Debugln("[MINER]", err) ethutil.Config.Log.Debugln("[MINER]", err)
} }

Loading…
Cancel
Save