diff --git a/chain/block_manager.go b/chain/block_manager.go index efe9e0862..fdb221cc3 100644 --- a/chain/block_manager.go +++ b/chain/block_manager.go @@ -154,10 +154,11 @@ done: } } - // Update the state with pending changes - state.Update() - txGas.Sub(txGas, st.gas) + + // Update the state with pending changes + state.Update(txGas) + cumulative := new(big.Int).Set(totalUsedGas.Add(totalUsedGas, txGas)) receipt := &Receipt{ethutil.CopyBytes(state.Root()), cumulative, nil /*bloom*/, state.Logs()} receipt.Bloom = CreateBloom(Receipts{receipt}) @@ -245,7 +246,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *Block) (td *big.Int, me return } - state.Update() + state.Update(nil) if !block.State().Cmp(state) { err = fmt.Errorf("invalid merkle root. received=%x got=%x", block.Root(), state.Root()) diff --git a/miner/miner.go b/miner/miner.go index e3435f5a6..9152d532b 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -203,7 +203,7 @@ func (self *Miner) mine() { // Accumulate the rewards included for this block blockManager.AccumelateRewards(block.State(), block, parent) - block.State().Update() + block.State().Update(nil) minerlogger.Infof("Mining on block. Includes %v transactions", len(transactions)) diff --git a/state/state.go b/state/state.go index 3abf1545b..0a7f717fe 100644 --- a/state/state.go +++ b/state/state.go @@ -23,14 +23,14 @@ type State struct { manifest *Manifest - refund map[string]*big.Int + refund map[string][]refund logs Logs } // Create a new state from a given trie func New(trie *trie.Trie) *State { - return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string]*big.Int)} + return &State{Trie: trie, stateObjects: make(map[string]*StateObject), manifest: NewManifest(), refund: make(map[string][]refund)} } func (self *State) EmptyLogs() { @@ -55,14 +55,12 @@ func (self *State) GetBalance(addr []byte) *big.Int { return ethutil.Big0 } +type refund struct { + gas, price *big.Int +} + func (self *State) Refund(addr []byte, gas, price *big.Int) { - amount := new(big.Int).Mul(gas, price) - - if self.refund[string(addr)] == nil { - self.refund[string(addr)] = new(big.Int) - } - - self.refund[string(addr)].Add(self.refund[string(addr)], amount) + self.refund[string(addr)] = append(self.refund[string(addr)], refund{gas, price}) } func (self *State) AddBalance(addr []byte, amount *big.Int) { @@ -276,15 +274,20 @@ func (s *State) Sync() { func (self *State) Empty() { self.stateObjects = make(map[string]*StateObject) - self.refund = make(map[string]*big.Int) + self.refund = make(map[string][]refund) } -func (self *State) Update() { +func (self *State) Update(gasUsed *big.Int) { var deleted bool // Refund any gas that's left - for addr, amount := range self.refund { - self.GetStateObject([]byte(addr)).AddBalance(amount) + uhalf := new(big.Int).Div(gasUsed, ethutil.Big2) + for addr, refs := range self.refund { + for _, ref := range refs { + refund := ethutil.BigMin(uhalf, ref.gas) + + self.GetStateObject([]byte(addr)).AddBalance(refund.Mul(refund, ref.price)) + } } for _, stateObject := range self.stateObjects {