Removed some of that gas pre pay magic

pull/481/head
obscuren 10 years ago
parent 2ae90e1eba
commit 310ca62285
  1. 17
      core/block_processor.go
  2. 47
      core/state_transition.go
  3. 1
      miner/worker.go
  4. 33
      state/state_object.go
  5. 3
      tests/helper/vm.go
  6. 8
      vm/vm.go

@ -78,21 +78,20 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
// If we are mining this block and validating we want to set the logs back to 0 // If we are mining this block and validating we want to set the logs back to 0
statedb.EmptyLogs() statedb.EmptyLogs()
txGas := new(big.Int).Set(tx.Gas())
cb := statedb.GetStateObject(coinbase.Address()) cb := statedb.GetStateObject(coinbase.Address())
st := NewStateTransition(NewEnv(statedb, self.bc, tx, block), tx, cb) /*
_, err := st.TransitionState() st := NewStateTransition(NewEnv(statedb, self.bc, tx, block), tx, cb)
_, err := st.TransitionState()
*/
_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb)
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) { if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, nil, err return nil, nil, err
} }
txGas.Sub(txGas, st.gas)
// Update the state with pending changes // Update the state with pending changes
statedb.Update(txGas) statedb.Update(nil)
cumulative := new(big.Int).Set(usedGas.Add(usedGas, txGas)) cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas))
receipt := types.NewReceipt(statedb.Root(), cumulative) receipt := types.NewReceipt(statedb.Root(), cumulative)
receipt.SetLogs(statedb.Logs()) receipt.SetLogs(statedb.Logs())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt}) receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
@ -105,7 +104,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
go self.eventMux.Post(logs) go self.eventMux.Post(logs)
} }
return receipt, txGas, err return receipt, gas, err
} }
func (self *BlockProcessor) ChainManager() *ChainManager { func (self *BlockProcessor) ChainManager() *ChainManager {
return self.bc return self.bc

@ -69,6 +69,10 @@ func MessageGasValue(msg Message) *big.Int {
return new(big.Int).Mul(msg.Gas(), msg.GasPrice()) return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
} }
func ApplyMessage(env vm.Environment, msg Message, coinbase *state.StateObject) ([]byte, *big.Int, error) {
return NewStateTransition(env, msg, coinbase).transitionState()
}
func NewStateTransition(env vm.Environment, msg Message, coinbase *state.StateObject) *StateTransition { func NewStateTransition(env vm.Environment, msg Message, coinbase *state.StateObject) *StateTransition {
return &StateTransition{ return &StateTransition{
coinbase: coinbase.Address(), coinbase: coinbase.Address(),
@ -150,7 +154,7 @@ func (self *StateTransition) preCheck() (err error) {
return nil return nil
} }
func (self *StateTransition) TransitionState() (ret []byte, err error) { func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, err error) {
// statelogger.Debugf("(~) %x\n", self.msg.Hash()) // statelogger.Debugf("(~) %x\n", self.msg.Hash())
// XXX Transactions after this point are considered valid. // XXX Transactions after this point are considered valid.
@ -163,11 +167,9 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
sender = self.From() sender = self.From()
) )
defer self.RefundGas()
// Transaction gas // Transaction gas
if err = self.UseGas(vm.GasTx); err != nil { if err = self.UseGas(vm.GasTx); err != nil {
return nil, InvalidTxError(err) return nil, nil, InvalidTxError(err)
} }
// Increment the nonce for the next transaction // Increment the nonce for the next transaction
@ -184,15 +186,13 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
} }
} }
if err = self.UseGas(big.NewInt(dgas)); err != nil { if err = self.UseGas(big.NewInt(dgas)); err != nil {
println("2") return nil, nil, InvalidTxError(err)
return nil, InvalidTxError(err)
} }
//stateCopy := self.env.State().Copy()
vmenv := self.env vmenv := self.env
var ref vm.ContextRef var ref vm.ContextRef
if MessageCreatesContract(msg) { if MessageCreatesContract(msg) {
contract := MakeContract(msg, self.state) contract := makeContract(msg, self.state)
ret, err, ref = vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value) ret, err, ref = vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
if err == nil { if err == nil {
dataGas := big.NewInt(int64(len(ret))) dataGas := big.NewInt(int64(len(ret)))
@ -208,29 +208,22 @@ func (self *StateTransition) TransitionState() (ret []byte, err error) {
} }
if err != nil && IsValueTransferErr(err) { if err != nil && IsValueTransferErr(err) {
return nil, InvalidTxError(err) return nil, nil, InvalidTxError(err)
} }
return self.refundGas()
} self.state.AddBalance(self.coinbase, new(big.Int).Mul(self.gasUsed(), self.gasPrice))
// Converts an transaction in to a state object
func MakeContract(msg Message, state *state.StateDB) *state.StateObject {
addr := AddressFromMessage(msg)
contract := state.GetOrNewStateObject(addr)
contract.SetInitCode(msg.Data())
return contract return ret, self.gasUsed(), err
} }
func (self *StateTransition) RefundGas() { func (self *StateTransition) refundGas() {
coinbase, sender := self.Coinbase(), self.From() coinbase, sender := self.Coinbase(), self.From()
// Return remaining gas // Return remaining gas
remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice()) remaining := new(big.Int).Mul(self.gas, self.msg.GasPrice())
sender.AddBalance(remaining) sender.AddBalance(remaining)
uhalf := new(big.Int).Div(self.GasUsed(), ethutil.Big2) uhalf := new(big.Int).Div(self.gasUsed(), ethutil.Big2)
for addr, ref := range self.state.Refunds() { for addr, ref := range self.state.Refunds() {
refund := ethutil.BigMin(uhalf, ref) refund := ethutil.BigMin(uhalf, ref)
self.gas.Add(self.gas, refund) self.gas.Add(self.gas, refund)
@ -240,6 +233,16 @@ func (self *StateTransition) RefundGas() {
coinbase.RefundGas(self.gas, self.msg.GasPrice()) coinbase.RefundGas(self.gas, self.msg.GasPrice())
} }
func (self *StateTransition) GasUsed() *big.Int { func (self *StateTransition) gasUsed() *big.Int {
return new(big.Int).Sub(self.initialGas, self.gas) return new(big.Int).Sub(self.initialGas, self.gas)
} }
// Converts an message in to a state object
func makeContract(msg Message, state *state.StateDB) *state.StateObject {
addr := AddressFromMessage(msg)
contract := state.GetOrNewStateObject(addr)
contract.SetInitCode(msg.Data())
return contract
}

@ -261,7 +261,6 @@ func (self *worker) commitUncle(uncle *types.Header) error {
func (self *worker) commitTransaction(tx *types.Transaction) error { func (self *worker) commitTransaction(tx *types.Transaction) error {
snap := self.current.state.Copy() snap := self.current.state.Copy()
//fmt.Printf("proc %x %v\n", tx.Hash()[:3], tx.Nonce())
receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true) receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true)
if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err) || core.IsInvalidTxErr(err)) { if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err) || core.IsInvalidTxErr(err)) {
self.current.state.Set(snap) self.current.state.Set(snap)

@ -38,19 +38,27 @@ func (self Storage) Copy() Storage {
} }
type StateObject struct { type StateObject struct {
// State database for storing state changes
db ethutil.Database db ethutil.Database
// Address of the object // The state object
State *StateDB
// Address belonging to this account
address []byte address []byte
// Shared attributes // The balance of the account
balance *big.Int balance *big.Int
// The nonce of the account
nonce uint64
// The code hash if code is present (i.e. a contract)
codeHash []byte codeHash []byte
nonce uint64 // The code for this account
// Contract related attributes code Code
State *StateDB // Temporarily initialisation code
code Code
initCode Code initCode Code
// Cached storage (flushed when updated)
storage Storage storage Storage
// Temporary prepaid gas, reward after transition
prepaid *big.Int
// Total gas pool is the total amount of gas currently // Total gas pool is the total amount of gas currently
// left if this object is the coinbase. Gas is directly // left if this object is the coinbase. Gas is directly
@ -77,6 +85,7 @@ func NewStateObject(addr []byte, db ethutil.Database) *StateObject {
object.State = New(nil, db) //New(trie.New(ethutil.Config.Db, "")) object.State = New(nil, db) //New(trie.New(ethutil.Config.Db, ""))
object.storage = make(Storage) object.storage = make(Storage)
object.gasPool = new(big.Int) object.gasPool = new(big.Int)
object.prepaid = new(big.Int)
return object return object
} }
@ -103,6 +112,7 @@ func NewStateObjectFromBytes(address, data []byte, db ethutil.Database) *StateOb
object.State = New(extobject.Root, db) object.State = New(extobject.Root, db)
object.storage = make(map[string]*ethutil.Value) object.storage = make(map[string]*ethutil.Value)
object.gasPool = new(big.Int) object.gasPool = new(big.Int)
object.prepaid = new(big.Int)
object.code, _ = db.Get(extobject.CodeHash) object.code, _ = db.Get(extobject.CodeHash)
return object return object
@ -230,8 +240,6 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error {
rGas := new(big.Int).Set(gas) rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price) rGas.Mul(rGas, price)
self.AddBalance(rGas)
self.dirty = true self.dirty = true
return nil return nil
@ -239,11 +247,6 @@ func (self *StateObject) BuyGas(gas, price *big.Int) error {
func (self *StateObject) RefundGas(gas, price *big.Int) { func (self *StateObject) RefundGas(gas, price *big.Int) {
self.gasPool.Add(self.gasPool, gas) self.gasPool.Add(self.gasPool, gas)
rGas := new(big.Int).Set(gas)
rGas.Mul(rGas, price)
self.balance.Sub(self.balance, rGas)
} }
func (self *StateObject) Copy() *StateObject { func (self *StateObject) Copy() *StateObject {

@ -173,9 +173,8 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
message := NewMessage(keyPair.Address(), to, data, value, gas, price) message := NewMessage(keyPair.Address(), to, data, value, gas, price)
vmenv := NewEnvFromMap(statedb, env, tx) vmenv := NewEnvFromMap(statedb, env, tx)
st := core.NewStateTransition(vmenv, message, coinbase)
vmenv.origin = keyPair.Address() vmenv.origin = keyPair.Address()
ret, err := st.TransitionState() ret, _, err := core.ApplyMessage(vmenv, message, coinbase)
if core.IsNonceErr(err) || core.IsInvalidTxErr(err) { if core.IsNonceErr(err) || core.IsInvalidTxErr(err) {
statedb.Set(snapshot) statedb.Set(snapshot)
} }

@ -392,14 +392,8 @@ func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.I
self.Printf(" => %x", context.Address()) self.Printf(" => %x", context.Address())
case BALANCE: case BALANCE:
addr := stack.pop().Bytes() addr := stack.pop().Bytes()
var balance *big.Int balance := statedb.GetBalance(addr)
if statedb.GetStateObject(addr) != nil {
balance = statedb.GetBalance(addr)
} else {
balance = base
}
stack.push(balance) stack.push(balance)

Loading…
Cancel
Save