Implemented managed state
* Reimplemented nonce management for known accounts.
This commit is contained in:
		
							parent
							
								
									cda88ce31a
								
							
						
					
					
						commit
						f1fcda4f2f
					
				| @ -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 | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -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} | ||||
| } | ||||
|  | ||||
							
								
								
									
										54
									
								
								state/managed_state_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								state/managed_state_test.go
									
									
									
									
									
										Normal file
									
								
							| @ -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) | ||||
| 	} | ||||
| } | ||||
| @ -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) | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user