Skip to content

Commit e8c30e8

Browse files
committed
core: remove stray account creations in state transition
The 'from' and 'to' methods on StateTransitions are reader methods and shouldn't have inadvertent side effects on state. It is safe to remove the check in 'from' because account existence is implicitly checked by the nonce and balance checks. If the account has non-zero balance or nonce, it must exist. Even if the sender account has nonce zero at the start of the state transition or no balance, the nonce is incremented before execution and the account will be created at that time. It is safe to remove the check in 'to' because the EVM creates the account if necessary. Fixes #15119
1 parent 39f4c80 commit e8c30e8

File tree

2 files changed

+16
-43
lines changed

2 files changed

+16
-43
lines changed

core/state_transition.go

+16-42
Original file line numberDiff line numberDiff line change
@@ -132,28 +132,12 @@ func ApplyMessage(evm *vm.EVM, msg Message, gp *GasPool) ([]byte, uint64, bool,
132132
return NewStateTransition(evm, msg, gp).TransitionDb()
133133
}
134134

135-
func (st *StateTransition) from() vm.AccountRef {
136-
f := st.msg.From()
137-
if !st.state.Exist(f) {
138-
st.state.CreateAccount(f)
135+
// to returns the recipient of the message.
136+
func (st *StateTransition) to() common.Address {
137+
if st.msg == nil || st.msg.To() == nil /* contract creation */ {
138+
return common.Address{}
139139
}
140-
return vm.AccountRef(f)
141-
}
142-
143-
func (st *StateTransition) to() vm.AccountRef {
144-
if st.msg == nil {
145-
return vm.AccountRef{}
146-
}
147-
to := st.msg.To()
148-
if to == nil {
149-
return vm.AccountRef{} // contract creation
150-
}
151-
152-
reference := vm.AccountRef(*to)
153-
if !st.state.Exist(*to) {
154-
st.state.CreateAccount(*to)
155-
}
156-
return reference
140+
return *st.msg.To()
157141
}
158142

159143
func (st *StateTransition) useGas(amount uint64) error {
@@ -166,12 +150,8 @@ func (st *StateTransition) useGas(amount uint64) error {
166150
}
167151

168152
func (st *StateTransition) buyGas() error {
169-
var (
170-
state = st.state
171-
sender = st.from()
172-
)
173153
mgval := new(big.Int).Mul(new(big.Int).SetUint64(st.msg.Gas()), st.gasPrice)
174-
if state.GetBalance(sender.Address()).Cmp(mgval) < 0 {
154+
if st.state.GetBalance(st.msg.From()).Cmp(mgval) < 0 {
175155
return errInsufficientBalanceForGas
176156
}
177157
if err := st.gp.SubGas(st.msg.Gas()); err != nil {
@@ -180,20 +160,17 @@ func (st *StateTransition) buyGas() error {
180160
st.gas += st.msg.Gas()
181161

182162
st.initialGas = st.msg.Gas()
183-
state.SubBalance(sender.Address(), mgval)
163+
st.state.SubBalance(st.msg.From(), mgval)
184164
return nil
185165
}
186166

187167
func (st *StateTransition) preCheck() error {
188-
msg := st.msg
189-
sender := st.from()
190-
191-
// Make sure this transaction's nonce is correct
192-
if msg.CheckNonce() {
193-
nonce := st.state.GetNonce(sender.Address())
194-
if nonce < msg.Nonce() {
168+
// Make sure this transaction's nonce is correct.
169+
if st.msg.CheckNonce() {
170+
nonce := st.state.GetNonce(st.msg.From())
171+
if nonce < st.msg.Nonce() {
195172
return ErrNonceTooHigh
196-
} else if nonce > msg.Nonce() {
173+
} else if nonce > st.msg.Nonce() {
197174
return ErrNonceTooLow
198175
}
199176
}
@@ -208,8 +185,7 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
208185
return
209186
}
210187
msg := st.msg
211-
sender := st.from() // err checked in preCheck
212-
188+
sender := vm.AccountRef(msg.From())
213189
homestead := st.evm.ChainConfig().IsHomestead(st.evm.BlockNumber)
214190
contractCreation := msg.To() == nil
215191

@@ -233,8 +209,8 @@ func (st *StateTransition) TransitionDb() (ret []byte, usedGas uint64, failed bo
233209
ret, _, st.gas, vmerr = evm.Create(sender, st.data, st.gas, st.value)
234210
} else {
235211
// Increment the nonce for the next transaction
236-
st.state.SetNonce(sender.Address(), st.state.GetNonce(sender.Address())+1)
237-
ret, st.gas, vmerr = evm.Call(sender, st.to().Address(), st.data, st.gas, st.value)
212+
st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
213+
ret, st.gas, vmerr = evm.Call(sender, st.to(), st.data, st.gas, st.value)
238214
}
239215
if vmerr != nil {
240216
log.Debug("VM returned with error", "err", vmerr)
@@ -260,10 +236,8 @@ func (st *StateTransition) refundGas() {
260236
st.gas += refund
261237

262238
// Return ETH for remaining gas, exchanged at the original rate.
263-
sender := st.from()
264-
265239
remaining := new(big.Int).Mul(new(big.Int).SetUint64(st.gas), st.gasPrice)
266-
st.state.AddBalance(sender.Address(), remaining)
240+
st.state.AddBalance(st.msg.From(), remaining)
267241

268242
// Also return remaining gas to the block gas counter so it is
269243
// available for the next transaction.

tests/state_test.go

-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ func TestState(t *testing.T) {
3737
// Expected failures:
3838
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/EIP158`, "bug in test")
3939
st.fails(`^stRevertTest/RevertPrecompiledTouch\.json/Byzantium`, "bug in test")
40-
st.fails(`^stRandom2/randomStatetest64[45]\.json/(EIP150|Frontier|Homestead)/.*`, "known bug #15119")
4140

4241
st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) {
4342
for _, subtest := range test.Subtests() {

0 commit comments

Comments
 (0)