| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // Copyright 2015 The go-ethereum Authors | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // This file is part of the go-ethereum library. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-23 18:35:11 +02:00
										 |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // The go-ethereum library is distributed in the hope that it will be useful, | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | // GNU Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							| 
									
										
										
										
											2015-07-22 18:48:40 +02:00
										 |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							| 
									
										
										
										
											2015-07-07 02:54:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	accounts map[common.Address]*account | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 13:04:23 +02:00
										 |  |  | // ManagedState returns a new managed state with the statedb as it's backing layer | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | func ManageState(statedb *StateDB) *ManagedState { | 
					
						
							|  |  |  | 	return &ManagedState{ | 
					
						
							| 
									
										
										
										
											2015-06-09 18:14:46 +02:00
										 |  |  | 		StateDB:  statedb.Copy(), | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		accounts: make(map[common.Address]*account), | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 13:04:23 +02:00
										 |  |  | // SetState sets the backing layer of the managed state | 
					
						
							| 
									
										
										
										
											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-04-08 13:04:23 +02:00
										 |  |  | // RemoveNonce removed the nonce from the managed state and all future pending nonces | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) { | 
					
						
							| 
									
										
										
										
											2015-04-14 12:47:54 +02:00
										 |  |  | 	if ms.hasAccount(addr) { | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 		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-04-08 13:04:23 +02:00
										 |  |  | // NewNonce returns the new canonical nonce for the managed account | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | func (ms *ManagedState) NewNonce(addr common.Address) uint64 { | 
					
						
							| 
									
										
										
										
											2015-04-13 22:57:03 +02:00
										 |  |  | 	ms.mu.Lock() | 
					
						
							|  |  |  | 	defer ms.mu.Unlock() | 
					
						
							| 
									
										
										
										
											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-04-21 11:27:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 23:30:07 +02:00
										 |  |  | 	return uint64(len(account.nonces)-1) + account.nstart | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-03-15 11:08:18 -07:00
										 |  |  | // GetNonce returns the canonical nonce for the managed or unmanaged account | 
					
						
							| 
									
										
										
										
											2015-04-08 13:04:23 +02:00
										 |  |  | func (ms *ManagedState) GetNonce(addr common.Address) uint64 { | 
					
						
							| 
									
										
										
										
											2015-04-14 12:47:54 +02:00
										 |  |  | 	ms.mu.RLock() | 
					
						
							|  |  |  | 	defer ms.mu.RUnlock() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if ms.hasAccount(addr) { | 
					
						
							| 
									
										
										
										
											2015-04-08 13:04:23 +02:00
										 |  |  | 		account := ms.getAccount(addr) | 
					
						
							|  |  |  | 		return uint64(len(account.nonces)) + account.nstart | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		return ms.StateDB.GetNonce(addr) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // SetNonce sets the new canonical nonce for the managed state | 
					
						
							|  |  |  | func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) { | 
					
						
							| 
									
										
										
										
											2015-04-14 12:47:54 +02:00
										 |  |  | 	ms.mu.Lock() | 
					
						
							|  |  |  | 	defer ms.mu.Unlock() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 13:04:23 +02:00
										 |  |  | 	so := ms.GetOrNewStateObject(addr) | 
					
						
							|  |  |  | 	so.SetNonce(nonce) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	ms.accounts[addr] = newAccount(so) | 
					
						
							| 
									
										
										
										
											2015-04-08 13:04:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // HasAccount returns whether the given address is managed or not | 
					
						
							|  |  |  | func (ms *ManagedState) HasAccount(addr common.Address) bool { | 
					
						
							| 
									
										
										
										
											2015-04-14 12:47:54 +02:00
										 |  |  | 	ms.mu.RLock() | 
					
						
							|  |  |  | 	defer ms.mu.RUnlock() | 
					
						
							|  |  |  | 	return ms.hasAccount(addr) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (ms *ManagedState) hasAccount(addr common.Address) bool { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	_, ok := ms.accounts[addr] | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	return ok | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-08 13:04:23 +02:00
										 |  |  | // populate the managed state | 
					
						
							| 
									
										
										
										
											2015-03-16 11:59:52 +01:00
										 |  |  | func (ms *ManagedState) getAccount(addr common.Address) *account { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	if account, ok := ms.accounts[addr]; !ok { | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 		so := ms.GetOrNewStateObject(addr) | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		ms.accounts[addr] = 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) | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 		if so != nil && uint64(len(account.nonces))+account.nstart < so.Nonce() { | 
					
						
							|  |  |  | 			ms.accounts[addr] = newAccount(so) | 
					
						
							| 
									
										
										
										
											2015-03-13 17:47:00 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	return ms.accounts[addr] | 
					
						
							| 
									
										
										
										
											2015-03-13 14:37:54 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func newAccount(so *StateObject) *account { | 
					
						
							| 
									
										
										
										
											2016-09-22 21:04:58 +02:00
										 |  |  | 	return &account{so, so.Nonce(), nil} | 
					
						
							| 
									
										
										
										
											2015-03-13 16:29:04 +01:00
										 |  |  | } |