aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-06-16 17:14:01 +0800
committerobscuren <geffobscura@gmail.com>2014-06-16 17:14:01 +0800
commit9f62d441a7c785b88f89d52643a9deaa822af15e (patch)
tree66510d5afe5d931e50e652a9cdc135fbc3fc9e3f /ethchain
parentb836267401b731a2cd17c4866a9727b4a05ec124 (diff)
downloaddexon-9f62d441a7c785b88f89d52643a9deaa822af15e.tar.gz
dexon-9f62d441a7c785b88f89d52643a9deaa822af15e.tar.zst
dexon-9f62d441a7c785b88f89d52643a9deaa822af15e.zip
Moved gas limit err check to buy gas
Diffstat (limited to 'ethchain')
-rw-r--r--ethchain/state_manager.go8
-rw-r--r--ethchain/state_object.go21
-rw-r--r--ethchain/state_transition.go4
-rw-r--r--ethchain/vm.go63
4 files changed, 56 insertions, 40 deletions
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index c68d5e001..4b1b872cc 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.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)
}
diff --git a/ethchain/state_object.go b/ethchain/state_object.go
index 3775d436c..03f4c9219 100644
--- a/ethchain/state_object.go
+++ b/ethchain/state_object.go
@@ -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))
diff --git a/ethchain/state_transition.go b/ethchain/state_transition.go
index 94546e556..76936aa7c 100644
--- a/ethchain/state_transition.go
+++ b/ethchain/state_transition.go
@@ -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 {
diff --git a/ethchain/vm.go b/ethchain/vm.go
index f0059f6ac..2ba0e2ef3 100644
--- a/ethchain/vm.go
+++ b/ethchain/vm.go
@@ -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)