aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/block_processor.go6
-rw-r--r--state/managed_state.go50
-rw-r--r--state/managed_state_test.go54
-rw-r--r--xeth/xeth.go4
4 files changed, 90 insertions, 24 deletions
diff --git a/core/block_processor.go b/core/block_processor.go
index 9fe74ef0a..f421c3539 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -79,12 +79,10 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
statedb.EmptyLogs()
cb := statedb.GetStateObject(coinbase.Address())
- /*
- 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 the account is managed, remove the invalid nonce.
+ self.bc.TxState().RemoveNonce(tx.From(), tx.Nonce())
return nil, nil, err
}
diff --git a/state/managed_state.go b/state/managed_state.go
index b0a129af0..1914e977a 100644
--- a/state/managed_state.go
+++ b/state/managed_state.go
@@ -2,44 +2,53 @@ package state
import "sync"
+type account struct {
+ stateObject *StateObject
+ nstart uint64
+ nonces []bool
+}
+
type ManagedState struct {
*StateDB
mu sync.RWMutex
- accounts map[string]*StateObject
+ accounts map[string]*account
}
func ManageState(statedb *StateDB) *ManagedState {
return &ManagedState{
StateDB: statedb,
- accounts: make(map[string]*StateObject),
+ accounts: make(map[string]*account),
}
}
-func (ms *ManagedState) IncrementNonce(addr []byte) {
- ms.mu.Lock()
- defer ms.mu.Unlock()
-
- ms.getAccount(addr).nonce++
-}
-
-func (ms *ManagedState) DecrementNonce(addr []byte) {
- // Decrementing a nonce does not mean we are interested in the account
- // incrementing only happens if you control the account, therefor
- // incrementing behaves differently from decrementing
+func (ms *ManagedState) RemoveNonce(addr []byte, n uint64) {
if ms.hasAccount(addr) {
ms.mu.Lock()
defer ms.mu.Unlock()
- ms.getAccount(addr).nonce--
+ account := ms.getAccount(addr)
+ if n-account.nstart < uint64(len(account.nonces)) {
+ reslice := make([]bool, n-account.nstart)
+ copy(reslice, account.nonces[:n-account.nstart])
+ account.nonces = reslice
+ }
}
}
-func (ms *ManagedState) GetNonce(addr []byte) uint64 {
+func (ms *ManagedState) NewNonce(addr []byte) uint64 {
ms.mu.RLock()
defer ms.mu.RUnlock()
- return ms.getAccount(addr).nonce
+
+ account := ms.getAccount(addr)
+ for i, nonce := range account.nonces {
+ if !nonce {
+ return account.nstart + uint64(i)
+ }
+ }
+ account.nonces = append(account.nonces, false)
+ return uint64(len(account.nonces)) + account.nstart
}
func (ms *ManagedState) hasAccount(addr []byte) bool {
@@ -47,10 +56,15 @@ func (ms *ManagedState) hasAccount(addr []byte) bool {
return ok
}
-func (ms *ManagedState) getAccount(addr []byte) *StateObject {
+func (ms *ManagedState) getAccount(addr []byte) *account {
if _, ok := ms.accounts[string(addr)]; !ok {
- ms.accounts[string(addr)] = ms.GetOrNewStateObject(addr)
+ so := ms.GetOrNewStateObject(addr)
+ ms.accounts[string(addr)] = newAccount(so)
}
return ms.accounts[string(addr)]
}
+
+func newAccount(so *StateObject) *account {
+ return &account{so, so.nonce - 1, nil}
+}
diff --git a/state/managed_state_test.go b/state/managed_state_test.go
new file mode 100644
index 000000000..ae374f728
--- /dev/null
+++ b/state/managed_state_test.go
@@ -0,0 +1,54 @@
+package state
+
+import "testing"
+
+var addr = []byte("test")
+
+func create() (*ManagedState, *account) {
+ ms := ManageState(nil)
+ ms.accounts[string(addr)] = newAccount(&StateObject{nonce: 100})
+
+ return ms, ms.accounts[string(addr)]
+}
+
+func TestNewNonce(t *testing.T) {
+ ms, _ := create()
+
+ nonce := ms.NewNonce(addr)
+ if nonce != 100 {
+ t.Error("expected nonce 101. got", nonce)
+ }
+}
+
+func TestRemove(t *testing.T) {
+ ms, account := create()
+
+ nn := make([]bool, 10)
+ for i, _ := range nn {
+ nn[i] = true
+ }
+ account.nonces = append(account.nonces, nn...)
+
+ i := uint64(5)
+ ms.RemoveNonce(addr, account.nstart+i)
+ if len(account.nonces) != 5 {
+ t.Error("expected", i, "'th index to be false")
+ }
+}
+
+func TestReuse(t *testing.T) {
+ ms, account := create()
+
+ nn := make([]bool, 10)
+ for i, _ := range nn {
+ nn[i] = true
+ }
+ account.nonces = append(account.nonces, nn...)
+
+ i := uint64(5)
+ ms.RemoveNonce(addr, account.nstart+i)
+ nonce := ms.NewNonce(addr)
+ if nonce != 105 {
+ t.Error("expected nonce to be 105. got", nonce)
+ }
+}
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 4ce1ee6a5..3e8c544c6 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -353,7 +353,7 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
}
state := self.chainManager.TxState()
- nonce := state.GetNonce(from)
+ nonce := state.NewNonce(from) //state.GetNonce(from)
tx.SetNonce(nonce)
if err := self.sign(tx, from, false); err != nil {
@@ -362,7 +362,7 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
if err := self.eth.TxPool().Add(tx); err != nil {
return "", err
}
- state.IncrementNonce(from)
+ //state.IncrementNonce(from)
if contractCreation {
addr := core.AddressFromMessage(tx)