| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | package ethchain | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"github.com/ethereum/eth-go/ethutil" | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 	"github.com/ethereum/eth-go/ethwire" | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	"math/big" | 
					
						
							|  |  |  | 	"sync" | 
					
						
							|  |  |  | 	"time" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type BlockProcessor interface { | 
					
						
							|  |  |  | 	ProcessBlock(block *Block) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | type EthManager interface { | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	StateManager() *StateManager | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 	BlockChain() *BlockChain | 
					
						
							|  |  |  | 	TxPool() *TxPool | 
					
						
							|  |  |  | 	Broadcast(msgType ethwire.MsgType, data []interface{}) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | type StateManager struct { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Mutex for locking the block processor. Blocks can only be handled one at a time | 
					
						
							|  |  |  | 	mutex sync.Mutex | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 	// Canonical block chain | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	bc *BlockChain | 
					
						
							| 
									
										
										
										
											2014-02-23 01:56:48 +01:00
										 |  |  | 	// States for addresses. You can watch any address | 
					
						
							|  |  |  | 	// at any given time | 
					
						
							|  |  |  | 	addrStateStore *AddrStateStore | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Stack for processing contracts | 
					
						
							|  |  |  | 	stack *Stack | 
					
						
							|  |  |  | 	// non-persistent key/value memory storage | 
					
						
							|  |  |  | 	mem map[string]*big.Int | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Pow PoW | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 	Ethereum EthManager | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	SecondaryBlockProcessor BlockProcessor | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 	// The managed states | 
					
						
							|  |  |  | 	// Processor state. Anything processed will be applied to this | 
					
						
							|  |  |  | 	// state | 
					
						
							|  |  |  | 	procState *State | 
					
						
							|  |  |  | 	// Comparative state it used for comparing and validating end | 
					
						
							|  |  |  | 	// results | 
					
						
							|  |  |  | 	compState *State | 
					
						
							| 
									
										
										
										
											2014-03-06 13:06:54 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	miningState *State | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func NewStateManager(ethereum EthManager) *StateManager { | 
					
						
							|  |  |  | 	sm := &StateManager{ | 
					
						
							| 
									
										
										
										
											2014-02-23 01:56:48 +01:00
										 |  |  | 		stack:          NewStack(), | 
					
						
							|  |  |  | 		mem:            make(map[string]*big.Int), | 
					
						
							|  |  |  | 		Pow:            &EasyPow{}, | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 		Ethereum:       ethereum, | 
					
						
							| 
									
										
										
										
											2014-02-23 01:56:48 +01:00
										 |  |  | 		addrStateStore: NewAddrStateStore(), | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 		bc:             ethereum.BlockChain(), | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 	sm.procState = ethereum.BlockChain().CurrentBlock.State() | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	return sm | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) ProcState() *State { | 
					
						
							|  |  |  | 	return sm.procState | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-23 01:56:48 +01:00
										 |  |  | // Watches any given address and puts it in the address state store | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) WatchAddr(addr []byte) *AccountState { | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 	//XXX account := sm.bc.CurrentBlock.state.GetAccount(addr) | 
					
						
							|  |  |  | 	account := sm.procState.GetAccount(addr) | 
					
						
							| 
									
										
										
										
											2014-02-23 01:56:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	return sm.addrStateStore.Add(addr, account) | 
					
						
							| 
									
										
										
										
											2014-02-23 01:56:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) GetAddrState(addr []byte) *AccountState { | 
					
						
							|  |  |  | 	account := sm.addrStateStore.Get(addr) | 
					
						
							| 
									
										
										
										
											2014-02-25 11:21:49 +01:00
										 |  |  | 	if account == nil { | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 		a := sm.bc.CurrentBlock.state.GetAccount(addr) | 
					
						
							| 
									
										
										
										
											2014-03-03 11:05:12 +01:00
										 |  |  | 		account = &AccountState{Nonce: a.Nonce, Account: a} | 
					
						
							| 
									
										
										
										
											2014-02-23 01:56:48 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-25 11:21:49 +01:00
										 |  |  | 	return account | 
					
						
							| 
									
										
										
										
											2014-02-23 01:56:48 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) BlockChain() *BlockChain { | 
					
						
							|  |  |  | 	return sm.bc | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) MakeContract(tx *Transaction) { | 
					
						
							|  |  |  | 	contract := MakeContract(tx, sm.procState) | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 	if contract != nil { | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 		sm.procState.states[string(tx.Hash()[12:])] = contract.state | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Process each transaction/contract | 
					
						
							|  |  |  | 	for _, tx := range txs { | 
					
						
							|  |  |  | 		// If there's no recipient, it's a contract | 
					
						
							|  |  |  | 		if tx.IsContract() { | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 			sm.MakeContract(tx) | 
					
						
							|  |  |  | 			//XXX block.MakeContract(tx) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 			if contract := sm.procState.GetContract(tx.Recipient); contract != nil { | 
					
						
							|  |  |  | 				//XXX if contract := block.state.GetContract(tx.Recipient); contract != nil { | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 				sm.ProcessContract(contract, tx, block) | 
					
						
							| 
									
										
										
										
											2014-02-24 12:44:29 +01:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 				err := sm.Ethereum.TxPool().ProcessTransaction(tx, block) | 
					
						
							| 
									
										
										
										
											2014-02-25 11:21:49 +01:00
										 |  |  | 				if err != nil { | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 					ethutil.Config.Log.Infoln("[STATE]", err) | 
					
						
							| 
									
										
										
										
											2014-02-25 11:21:49 +01:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-02-24 12:44:29 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | // The prepare function, prepares the state manager for the next | 
					
						
							|  |  |  | // "ProcessBlock" action. | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) Prepare(processer *State, comparative *State) { | 
					
						
							|  |  |  | 	sm.compState = comparative | 
					
						
							|  |  |  | 	sm.procState = processer | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Default prepare function | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) PrepareDefault(block *Block) { | 
					
						
							|  |  |  | 	sm.Prepare(sm.BlockChain().CurrentBlock.State(), block.State()) | 
					
						
							| 
									
										
										
										
											2014-03-05 10:42:51 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | // Block processing and validating with a given (temporarily) state | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) ProcessBlock(block *Block) error { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Processing a blocks may never happen simultaneously | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	sm.mutex.Lock() | 
					
						
							|  |  |  | 	defer sm.mutex.Unlock() | 
					
						
							| 
									
										
										
										
											2014-02-16 20:30:21 +01:00
										 |  |  | 	// Defer the Undo on the Trie. If the block processing happened | 
					
						
							|  |  |  | 	// we don't want to undo but since undo only happens on dirty | 
					
						
							|  |  |  | 	// nodes this won't happen because Commit would have been called | 
					
						
							|  |  |  | 	// before that. | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	defer sm.bc.CurrentBlock.Undo() | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	hash := block.Hash() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	if sm.bc.HasBlock(hash) { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check if we have the parent hash, if it isn't known we discard it | 
					
						
							|  |  |  | 	// Reasons might be catching up or simply an invalid block | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	if !sm.bc.HasBlock(block.PrevHash) && sm.bc.CurrentBlock != nil { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		return ParentError(block.PrevHash) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Process the transactions on to current block | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	sm.ApplyTransactions(sm.bc.CurrentBlock, block.Transactions()) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Block validation | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	if err := sm.ValidateBlock(block); err != nil { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// I'm not sure, but I don't know if there should be thrown | 
					
						
							|  |  |  | 	// any errors at this time. | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 	if err := sm.AccumelateRewards(block); err != nil { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		return err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	// if !sm.compState.Cmp(sm.procState) | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 	if !sm.compState.Cmp(sm.procState) { | 
					
						
							|  |  |  | 		//XXX return fmt.Errorf("Invalid merkle root. Expected %x, got %x", block.State().trie.Root, sm.bc.CurrentBlock.State().trie.Root) | 
					
						
							|  |  |  | 		return fmt.Errorf("Invalid merkle root. Expected %x, got %x", sm.compState.trie.Root, sm.procState.trie.Root) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Calculate the new total difficulty and sync back to the db | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	if sm.CalculateTD(block) { | 
					
						
							| 
									
										
										
										
											2014-02-18 01:33:26 +01:00
										 |  |  | 		// Sync the current block's state to the database and cancelling out the deferred Undo | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 		//XXX sm.bc.CurrentBlock.Sync() | 
					
						
							|  |  |  | 		sm.procState.Sync() | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		// Broadcast the valid block back to the wire | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 		//sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val}) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-24 13:50:52 +01:00
										 |  |  | 		// Add the block to the chain | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 		sm.bc.Add(block) | 
					
						
							| 
									
										
										
										
											2014-02-24 13:50:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		// If there's a block processor present, pass in the block for further | 
					
						
							|  |  |  | 		// processing | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 		if sm.SecondaryBlockProcessor != nil { | 
					
						
							|  |  |  | 			sm.SecondaryBlockProcessor.ProcessBlock(block) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 		ethutil.Config.Log.Infof("[STATE] Added block #%d (%x)\n", block.BlockInfo().Number, block.Hash()) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} else { | 
					
						
							|  |  |  | 		fmt.Println("total diff failed") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) CalculateTD(block *Block) bool { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	uncleDiff := new(big.Int) | 
					
						
							|  |  |  | 	for _, uncle := range block.Uncles { | 
					
						
							|  |  |  | 		uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty | 
					
						
							|  |  |  | 	td := new(big.Int) | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	td = td.Add(sm.bc.TD, uncleDiff) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	td = td.Add(td, block.Difficulty) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// The new TD will only be accepted if the new difficulty is | 
					
						
							|  |  |  | 	// is greater than the previous. | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	if td.Cmp(sm.bc.TD) > 0 { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 		// Set the new total difficulty back to the block chain | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 		sm.bc.SetTotalDifficulty(td) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		return true | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Validates the current block. Returns an error if the block was invalid, | 
					
						
							|  |  |  | // an uncle or anything that isn't on the current block chain. | 
					
						
							|  |  |  | // Validation validates easy over difficult (dagger takes longer time = difficult) | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) ValidateBlock(block *Block) error { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// TODO | 
					
						
							|  |  |  | 	// 2. Check if the difficulty is correct | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Check each uncle's previous hash. In order for it to be valid | 
					
						
							|  |  |  | 	// is if it has the same block hash as the current | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	previousBlock := sm.bc.GetBlock(block.PrevHash) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	for _, uncle := range block.Uncles { | 
					
						
							|  |  |  | 		if bytes.Compare(uncle.PrevHash, previousBlock.PrevHash) != 0 { | 
					
						
							|  |  |  | 			return ValidationError("Mismatch uncle's previous hash. Expected %x, got %x", previousBlock.PrevHash, uncle.PrevHash) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	diff := block.Time - sm.bc.CurrentBlock.Time | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	if diff < 0 { | 
					
						
							|  |  |  | 		return ValidationError("Block timestamp less then prev block %v", diff) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// New blocks must be within the 15 minute range of the last block. | 
					
						
							|  |  |  | 	if diff > int64(15*time.Minute) { | 
					
						
							|  |  |  | 		return ValidationError("Block is too far in the future of last block (> 15 minutes)") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Verify the nonce of the block. Return an error if it's not valid | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | 	if !sm.Pow.Verify(block.HashNoNonce(), block.Difficulty, block.Nonce) { | 
					
						
							| 
									
										
										
										
											2014-03-17 11:13:35 +01:00
										 |  |  | 		return ValidationError("Block's nonce is invalid (= %v)", ethutil.Hex(block.Nonce)) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 01:33:26 +01:00
										 |  |  | func CalculateBlockReward(block *Block, uncleLength int) *big.Int { | 
					
						
							|  |  |  | 	base := new(big.Int) | 
					
						
							|  |  |  | 	for i := 0; i < uncleLength; i++ { | 
					
						
							|  |  |  | 		base.Add(base, UncleInclusionReward) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return base.Add(base, BlockReward) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func CalculateUncleReward(block *Block) *big.Int { | 
					
						
							|  |  |  | 	return UncleReward | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | func (sm *StateManager) AccumelateRewards(block *Block) error { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Get the coinbase rlp data | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 	//XXX addr := processor.state.GetAccount(block.Coinbase) | 
					
						
							|  |  |  | 	addr := sm.procState.GetAccount(block.Coinbase) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Reward amount of ether to the coinbase address | 
					
						
							|  |  |  | 	addr.AddFee(CalculateBlockReward(block, len(block.Uncles))) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 	//XXX processor.state.UpdateAccount(block.Coinbase, addr) | 
					
						
							|  |  |  | 	sm.procState.UpdateAccount(block.Coinbase, addr) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-18 01:33:26 +01:00
										 |  |  | 	for _, uncle := range block.Uncles { | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 		uncleAddr := sm.procState.GetAccount(uncle.Coinbase) | 
					
						
							| 
									
										
										
										
											2014-02-18 01:33:26 +01:00
										 |  |  | 		uncleAddr.AddFee(CalculateUncleReward(uncle)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-17 10:33:03 +01:00
										 |  |  | 		//processor.state.UpdateAccount(uncle.Coinbase, uncleAddr) | 
					
						
							|  |  |  | 		sm.procState.UpdateAccount(uncle.Coinbase, uncleAddr) | 
					
						
							| 
									
										
										
										
											2014-02-18 01:33:26 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) Stop() { | 
					
						
							|  |  |  | 	sm.bc.Stop() | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-03-05 10:57:32 +01:00
										 |  |  | func (sm *StateManager) ProcessContract(contract *Contract, tx *Transaction, block *Block) { | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	// Recovering function in case the VM had any errors | 
					
						
							| 
									
										
										
										
											2014-02-19 11:35:17 +01:00
										 |  |  | 	/* | 
					
						
							|  |  |  | 		defer func() { | 
					
						
							|  |  |  | 			if r := recover(); r != nil { | 
					
						
							|  |  |  | 				fmt.Println("Recovered from VM execution with err =", r) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		}() | 
					
						
							|  |  |  | 	*/ | 
					
						
							| 
									
										
										
										
											2014-03-21 00:04:31 +01:00
										 |  |  | 	caller := sm.procState.GetAccount(tx.Sender()) | 
					
						
							|  |  |  | 	closure := NewClosure(caller, contract, sm.procState, tx.Gas, tx.Value) | 
					
						
							|  |  |  | 	vm := NewVm(sm.procState, RuntimeVars{ | 
					
						
							| 
									
										
										
										
											2014-03-21 14:47:55 +01:00
										 |  |  | 		origin:      caller.Address(), | 
					
						
							| 
									
										
										
										
											2014-02-24 12:44:29 +01:00
										 |  |  | 		blockNumber: block.BlockInfo().Number, | 
					
						
							|  |  |  | 		prevHash:    block.PrevHash, | 
					
						
							|  |  |  | 		coinbase:    block.Coinbase, | 
					
						
							|  |  |  | 		time:        block.Time, | 
					
						
							|  |  |  | 		diff:        block.Difficulty, | 
					
						
							| 
									
										
										
										
											2014-03-21 00:04:31 +01:00
										 |  |  | 		// XXX Tx data? Could be just an argument to the closure instead | 
					
						
							|  |  |  | 		txData: nil, | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2014-03-21 00:04:31 +01:00
										 |  |  | 	closure.Call(vm, nil) | 
					
						
							| 
									
										
										
										
											2014-02-14 23:56:09 +01:00
										 |  |  | } |