| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | package state | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | import ( | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | type account struct { | 
					
						
							|  |  |  | 	stateObject *StateObject | 
					
						
							|  |  |  | 	nstart      uint64 | 
					
						
							|  |  |  | 	nonces      []bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | type ManagedState struct { | 
					
						
							|  |  |  | 	*StateDB | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mu sync.RWMutex | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 	accounts map[string]*account | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func ManageState(statedb *StateDB) *ManagedState { | 
					
						
							|  |  |  | 	return &ManagedState{ | 
					
						
							|  |  |  | 		StateDB:  statedb, | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 		accounts: make(map[string]*account), | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 17:47:00 +01:00
										 |  |  | func (ms *ManagedState) SetState(statedb *StateDB) { | 
					
						
							|  |  |  | 	ms.mu.Lock() | 
					
						
							|  |  |  | 	defer ms.mu.Unlock() | 
					
						
							|  |  |  | 	ms.StateDB = statedb | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) { | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	if ms.hasAccount(addr) { | 
					
						
							|  |  |  | 		ms.mu.Lock() | 
					
						
							|  |  |  | 		defer ms.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 		account := ms.getAccount(addr) | 
					
						
							| 
									
										
										
										
											2015-03-13 17:47:00 +01:00
										 |  |  | 		if n-account.nstart <= uint64(len(account.nonces)) { | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 			reslice := make([]bool, n-account.nstart) | 
					
						
							|  |  |  | 			copy(reslice, account.nonces[:n-account.nstart]) | 
					
						
							|  |  |  | 			account.nonces = reslice | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | func (ms *ManagedState) NewNonce(addr common.Address) uint64 { | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	ms.mu.RLock() | 
					
						
							|  |  |  | 	defer ms.mu.RUnlock() | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	account := ms.getAccount(addr) | 
					
						
							|  |  |  | 	for i, nonce := range account.nonces { | 
					
						
							|  |  |  | 		if !nonce { | 
					
						
							|  |  |  | 			return account.nstart + uint64(i) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-13 17:47:00 +01:00
										 |  |  | 	account.nonces = append(account.nonces, true) | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 	return uint64(len(account.nonces)) + account.nstart | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | func (ms *ManagedState) hasAccount(addr common.Address) bool { | 
					
						
							|  |  |  | 	_, ok := ms.accounts[addr.Str()] | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	return ok | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | func (ms *ManagedState) getAccount(addr common.Address) *account { | 
					
						
							|  |  |  | 	straddr := addr.Str() | 
					
						
							|  |  |  | 	if account, ok := ms.accounts[straddr]; !ok { | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 		so := ms.GetOrNewStateObject(addr) | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | 		ms.accounts[straddr] = newAccount(so) | 
					
						
							| 
									
										
										
										
											2015-03-13 17:47:00 +01:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		// Always make sure the state account nonce isn't actually higher | 
					
						
							|  |  |  | 		// than the tracked one. | 
					
						
							|  |  |  | 		so := ms.StateDB.GetStateObject(addr) | 
					
						
							|  |  |  | 		if so != nil && uint64(len(account.nonces))+account.nstart < so.nonce { | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | 			ms.accounts[straddr] = newAccount(so) | 
					
						
							| 
									
										
										
										
											2015-03-13 17:47:00 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | 	return ms.accounts[straddr] | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func newAccount(so *StateObject) *account { | 
					
						
							|  |  |  | 	return &account{so, so.nonce - 1, nil} | 
					
						
							|  |  |  | } |