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
}
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 (
receipts Receipts
handled, unhandled Transactions
@ -177,9 +177,12 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
}
fmt.Println(block.Receipts())
coinbase := state.GetOrNewStateObject(block.Coinbase)
coinbase.gasPool = block.CalcGasLimit(parent)
// Process the transactions on to current block
//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
if err := sm.ValidateBlock(block); err != nil {
@ -194,7 +197,6 @@ func (sm *StateManager) ProcessBlock(state *State, parent, block *Block, dontRea
return err
}
//if !sm.compState.Cmp(state) {
if !block.State().Cmp(state) {
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
script []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
@ -139,14 +144,22 @@ func (c *StateObject) ConvertGas(gas, price *big.Int) error {
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 {
if self.gasPool.Cmp(gas) < 0 {
return GasLimitError(self.gasPool, gas)
}
rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price)
self.AddAmount(rGas)
// TODO Do sub from TotalGasPool
// and check if enough left
return nil
}
@ -158,7 +171,9 @@ func (self *StateObject) Copy() *StateObject {
stCopy.ScriptHash = make([]byte, len(self.ScriptHash))
copy(stCopy.ScriptHash, self.ScriptHash)
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))
copy(stCopy.script, self.script)
stCopy.initScript = make([]byte, len(self.initScript))

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

@ -169,7 +169,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
case CALL:
require(7)
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()
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)
}
case CALL:
// TODO RE-WRITE
require(7)
// Closure addr
addr := stack.Pop()
@ -538,46 +539,44 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro
inSize, inOffset := stack.Popn()
// Pop return size and offset
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
args := mem.Get(inOffset.Int64(), inSize.Int64())
snapshot := vm.state.Snapshot()
// Fetch the contract which will serve as the closure body
contract := vm.state.GetStateObject(addr.Bytes())
if contract != nil {
// Prepay for the gas
//closure.UseGas(gas)
closure.object.Nonce += 1
if closure.object.Amount.Cmp(value) < 0 {
ethutil.Config.Log.Debugf("Insufficient funds to transfer value. Req %v, has %v", value, closure.object.Amount)
// Add the value to the state object
contract.AddAmount(value)
// Create a new callable closure
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)
stack.Push(ethutil.BigFalse)
} else {
// Fetch the contract which will serve as the closure body
contract := vm.state.GetStateObject(addr.Bytes())
if contract != nil {
// Add the value to the state object
contract.AddAmount(value)
// Create a new callable closure
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 {
stack.Push(ethutil.BigTrue)
vm.state.UpdateStateObject(contract)
mem.Set(retOffset.Int64(), retSize.Int64(), ret)
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes())
stack.Push(ethutil.BigFalse)
}
} else {
ethutil.Config.Log.Debugf("Contract %x not found\n", addr.Bytes())
stack.Push(ethutil.BigFalse)
}
case RETURN:
require(2)

@ -139,7 +139,8 @@ func (self *Miner) mineNewBlock() {
// Accumulate all valid transaction and apply them to the new state
// 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 {
ethutil.Config.Log.Debugln("[MINER]", err)
}

Loading…
Cancel
Save