diff options
-rw-r--r-- | ethchain/block_chain.go | 4 | ||||
-rw-r--r-- | ethchain/block_chain_test.go | 17 | ||||
-rw-r--r-- | ethchain/state_manager.go | 109 | ||||
-rw-r--r-- | ethchain/transaction_pool.go | 3 | ||||
-rw-r--r-- | ethchain/vm_test.go | 2 | ||||
-rw-r--r-- | ethereum.go | 2 | ||||
-rw-r--r-- | ethminer/miner.go | 24 | ||||
-rw-r--r-- | ethpub/pub.go | 2 | ||||
-rw-r--r-- | ethutil/config.go | 12 | ||||
-rw-r--r-- | peer.go | 5 |
10 files changed, 82 insertions, 98 deletions
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index 1848b9ddb..6c3b15a6a 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -280,7 +280,7 @@ func (bc *BlockChain) setLastBlock() { bc.LastBlockHash = block.Hash() bc.LastBlockNumber = info.Number - log.Printf("[CHAIN] Last known block height #%d\n", bc.LastBlockNumber) + ethutil.Config.Log.Infof("[CHAIN] Last known block height #%d\n", bc.LastBlockNumber) } else { AddTestNetFunds(bc.genesisBlock) @@ -295,7 +295,7 @@ func (bc *BlockChain) setLastBlock() { // Set the last know difficulty (might be 0x0 as initial value, Genesis) bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) - log.Printf("Last block: %x\n", bc.CurrentBlock.Hash()) + ethutil.Config.Log.Infof("Last block: %x\n", bc.CurrentBlock.Hash()) } func (bc *BlockChain) SetTotalDifficulty(td *big.Int) { diff --git a/ethchain/block_chain_test.go b/ethchain/block_chain_test.go index 30eb62266..4e4bb9dd4 100644 --- a/ethchain/block_chain_test.go +++ b/ethchain/block_chain_test.go @@ -18,6 +18,18 @@ type TestManager struct { Blocks []*Block } +func (s *TestManager) IsListening() bool { + return false +} + +func (s *TestManager) IsMining() bool { + return false +} + +func (s *TestManager) PeerCount() int { + return 0 +} + func (s *TestManager) BlockChain() *BlockChain { return s.blockChain } @@ -38,7 +50,7 @@ func (tm *TestManager) Broadcast(msgType ethwire.MsgType, data []interface{}) { } func NewTestManager() *TestManager { - ethutil.ReadConfig(".ethtest") + ethutil.ReadConfig(".ethtest", ethutil.LogStd) db, err := ethdb.NewMemDatabase() if err != nil { @@ -62,8 +74,7 @@ func NewTestManager() *TestManager { func (tm *TestManager) AddFakeBlock(blk []byte) error { block := NewBlockFromBytes(blk) tm.Blocks = append(tm.Blocks, block) - tm.StateManager().PrepareDefault(block) - err := tm.StateManager().ProcessBlock(block, false) + err := tm.StateManager().ProcessBlock(tm.StateManager().CurrentState(), block, false) return err } func (tm *TestManager) CreateChain1() error { diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index 143d9d647..28570775b 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -39,20 +39,13 @@ type StateManager struct { // The ethereum manager interface Ethereum EthManager // 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 // Transiently state. The trans state isn't ever saved, validated and // it could be used for setting account nonces without effecting // the main states. transState *State - // Manifest for keeping changes regarding state objects. See `notify` - // XXX Should we move the manifest to the State object. Benefit: - // * All states can keep their own local changes - //manifest *Manifest + // Mining state. The mining state is used purely and solely by the mining + // operation. + miningState *State } func NewStateManager(ethereum EthManager) *StateManager { @@ -62,30 +55,39 @@ func NewStateManager(ethereum EthManager) *StateManager { Pow: &EasyPow{}, Ethereum: ethereum, bc: ethereum.BlockChain(), - //manifest: NewManifest(), } - sm.procState = ethereum.BlockChain().CurrentBlock.State() - sm.transState = sm.procState.Copy() + sm.transState = ethereum.BlockChain().CurrentBlock.State().Copy() + sm.miningState = ethereum.BlockChain().CurrentBlock.State().Copy() return sm } -func (sm *StateManager) ProcState() *State { - return sm.procState +func (sm *StateManager) CurrentState() *State { + return sm.Ethereum.BlockChain().CurrentBlock.State() } func (sm *StateManager) TransState() *State { return sm.transState } +func (sm *StateManager) MiningState() *State { + return sm.miningState +} + +func (sm *StateManager) NewMiningState() *State { + sm.miningState = sm.Ethereum.BlockChain().CurrentBlock.State().Copy() + + return sm.miningState +} + func (sm *StateManager) BlockChain() *BlockChain { return sm.bc } -func (sm *StateManager) MakeContract(tx *Transaction) *StateObject { - contract := MakeContract(tx, sm.procState) +func (sm *StateManager) MakeContract(state *State, tx *Transaction) *StateObject { + contract := MakeContract(tx, state) if contract != nil { - sm.procState.states[string(tx.Hash()[12:])] = contract.state + state.states[string(tx.Hash()[12:])] = contract.state return contract } @@ -95,7 +97,7 @@ func (sm *StateManager) MakeContract(tx *Transaction) *StateObject { // Apply transactions uses the transaction passed to it and applies them onto // the current processing state. -func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) { +func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Transaction) { // Process each transaction/contract for _, tx := range txs { // If there's no recipient, it's a contract @@ -104,9 +106,9 @@ func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) { if tx.IsContract() { err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false) if err == nil { - contract := sm.MakeContract(tx) + contract := sm.MakeContract(state, tx) if contract != nil { - sm.EvalScript(contract.Init(), contract, tx, block) + sm.EvalScript(state, contract.Init(), contract, tx, block) } else { ethutil.Config.Log.Infoln("[STATE] Unable to create contract") } @@ -115,9 +117,9 @@ func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) { } } else { err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false) - contract := sm.procState.GetContract(tx.Recipient) + contract := state.GetContract(tx.Recipient) if err == nil && len(contract.Script()) > 0 { - sm.EvalScript(contract.Script(), contract, tx, block) + sm.EvalScript(state, contract.Script(), contract, tx, block) } else if err != nil { ethutil.Config.Log.Infoln("[STATE] process:", err) } @@ -125,20 +127,8 @@ func (sm *StateManager) ApplyTransactions(block *Block, txs []*Transaction) { } } -// The prepare function, prepares the state manager for the next -// "ProcessBlock" action. -func (sm *StateManager) Prepare(processor *State, comparative *State) { - sm.compState = comparative - sm.procState = processor -} - -// Default prepare function -func (sm *StateManager) PrepareDefault(block *Block) { - sm.Prepare(sm.BlockChain().CurrentBlock.State(), block.State()) -} - // Block processing and validating with a given (temporarily) state -func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error { +func (sm *StateManager) ProcessBlock(state *State, block *Block, dontReact bool) error { // Processing a blocks may never happen simultaneously sm.mutex.Lock() defer sm.mutex.Unlock() @@ -153,7 +143,7 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error { // 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. - defer sm.bc.CurrentBlock.Undo() + defer state.Reset() // 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 @@ -162,7 +152,7 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error { } // Process the transactions on to current block - sm.ApplyTransactions(sm.bc.CurrentBlock, block.Transactions()) + sm.ApplyTransactions(state, sm.bc.CurrentBlock, block.Transactions()) // Block validation if err := sm.ValidateBlock(block); err != nil { @@ -172,19 +162,20 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error { // I'm not sure, but I don't know if there should be thrown // any errors at this time. - if err := sm.AccumelateRewards(block); err != nil { + if err := sm.AccumelateRewards(state, block); err != nil { fmt.Println("[SM] Error accumulating reward", err) return err } - if !sm.compState.Cmp(sm.procState) { - return fmt.Errorf("Invalid merkle root. Expected %x, got %x", sm.compState.trie.Root, sm.procState.trie.Root) + //if !sm.compState.Cmp(state) { + if !block.State().Cmp(state) { + return fmt.Errorf("Invalid merkle root. Expected %x, got %x", block.State().trie.Root, state.trie.Root) } // Calculate the new total difficulty and sync back to the db if sm.CalculateTD(block) { // Sync the current block's state to the database and cancelling out the deferred Undo - sm.procState.Sync() + state.Sync() // Add the block to the chain sm.bc.Add(block) @@ -193,14 +184,14 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error { if dontReact == false { sm.Ethereum.Reactor().Post("newBlock", block) - sm.procState.manifest.Reset() + state.manifest.Reset() } - sm.notifyChanges() + sm.notifyChanges(state) sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val}) - sm.Ethereum.TxPool().RemoveInvalid(sm.procState) + sm.Ethereum.TxPool().RemoveInvalid(state) } else { fmt.Println("total diff failed") } @@ -276,21 +267,21 @@ func CalculateUncleReward(block *Block) *big.Int { return UncleReward } -func (sm *StateManager) AccumelateRewards(block *Block) error { +func (sm *StateManager) AccumelateRewards(state *State, block *Block) error { // Get the account associated with the coinbase - account := sm.procState.GetAccount(block.Coinbase) + account := state.GetAccount(block.Coinbase) // Reward amount of ether to the coinbase address account.AddAmount(CalculateBlockReward(block, len(block.Uncles))) addr := make([]byte, len(block.Coinbase)) copy(addr, block.Coinbase) - sm.procState.UpdateStateObject(account) + state.UpdateStateObject(account) for _, uncle := range block.Uncles { - uncleAccount := sm.procState.GetAccount(uncle.Coinbase) + uncleAccount := state.GetAccount(uncle.Coinbase) uncleAccount.AddAmount(CalculateUncleReward(uncle)) - sm.procState.UpdateStateObject(uncleAccount) + state.UpdateStateObject(uncleAccount) } return nil @@ -300,8 +291,8 @@ func (sm *StateManager) Stop() { sm.bc.Stop() } -func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Transaction, block *Block) { - account := sm.procState.GetAccount(tx.Sender()) +func (sm *StateManager) EvalScript(state *State, script []byte, object *StateObject, tx *Transaction, block *Block) { + account := state.GetAccount(tx.Sender()) err := account.ConvertGas(tx.Gas, tx.GasPrice) if err != nil { @@ -309,8 +300,8 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans return } - closure := NewClosure(account, object, script, sm.procState, tx.Gas, tx.GasPrice) - vm := NewVm(sm.procState, sm, RuntimeVars{ + closure := NewClosure(account, object, script, state, tx.Gas, tx.GasPrice) + vm := NewVm(state, sm, RuntimeVars{ Origin: account.Address(), BlockNumber: block.BlockInfo().Number, PrevHash: block.PrevHash, @@ -323,16 +314,16 @@ func (sm *StateManager) EvalScript(script []byte, object *StateObject, tx *Trans closure.Call(vm, tx.Data, nil) // Update the account (refunds) - sm.procState.UpdateStateObject(account) - sm.procState.UpdateStateObject(object) + state.UpdateStateObject(account) + state.UpdateStateObject(object) } -func (sm *StateManager) notifyChanges() { - for addr, stateObject := range sm.procState.manifest.objectChanges { +func (sm *StateManager) notifyChanges(state *State) { + for addr, stateObject := range state.manifest.objectChanges { sm.Ethereum.Reactor().Post("object:"+addr, stateObject) } - for stateObjectAddr, mappedObjects := range sm.procState.manifest.storageChanges { + for stateObjectAddr, mappedObjects := range state.manifest.storageChanges { for addr, value := range mappedObjects { sm.Ethereum.Reactor().Post("storage:"+stateObjectAddr+":"+addr, &StorageState{[]byte(stateObjectAddr), []byte(addr), value}) } diff --git a/ethchain/transaction_pool.go b/ethchain/transaction_pool.go index 21ce8cdc1..da77f32b3 100644 --- a/ethchain/transaction_pool.go +++ b/ethchain/transaction_pool.go @@ -149,7 +149,8 @@ func (pool *TxPool) ValidateTransaction(tx *Transaction) error { } // Get the sender - sender := pool.Ethereum.StateManager().procState.GetAccount(tx.Sender()) + //sender := pool.Ethereum.StateManager().procState.GetAccount(tx.Sender()) + sender := pool.Ethereum.StateManager().CurrentState().GetAccount(tx.Sender()) totAmount := new(big.Int).Add(tx.Value, new(big.Int).Mul(TxFee, TxFeeRat)) // Make sure there's enough in the sender's account. Having insufficient diff --git a/ethchain/vm_test.go b/ethchain/vm_test.go index b919b496f..5d03ccf0c 100644 --- a/ethchain/vm_test.go +++ b/ethchain/vm_test.go @@ -12,7 +12,7 @@ import ( ) func TestRun4(t *testing.T) { - ethutil.ReadConfig("") + ethutil.ReadConfig("", ethutil.LogStd) db, _ := ethdb.NewMemDatabase() state := NewState(ethutil.NewTrie(db, "")) diff --git a/ethereum.go b/ethereum.go index 83a74f302..14418023e 100644 --- a/ethereum.go +++ b/ethereum.go @@ -235,7 +235,7 @@ func (s *Ethereum) ConnectToPeer(addr string) error { s.peers.PushBack(peer) - log.Printf("[SERV] Adding peer %d / %d\n", s.peers.Len(), s.MaxPeers) + ethutil.Config.Log.Infof("[SERV] Adding peer %d / %d\n", s.peers.Len(), s.MaxPeers) } return nil diff --git a/ethminer/miner.go b/ethminer/miner.go index bc29b2588..233a8bc32 100644 --- a/ethminer/miner.go +++ b/ethminer/miner.go @@ -53,8 +53,8 @@ func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner { } func (miner *Miner) Start() { // Prepare inital block - miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State()) - go func() { miner.listener() }() + //miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State()) + go miner.listener() } func (miner *Miner) listener() { for { @@ -88,7 +88,7 @@ func (miner *Miner) listener() { if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 { log.Println("[MINER] Adding uncle block") miner.uncles = append(miner.uncles, block) - miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State()) + //miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State()) } } } @@ -119,31 +119,19 @@ func (miner *Miner) listener() { miner.block.SetUncles(miner.uncles) } - // FIXME @ maranh, first block doesn't need this. Everything after the first block does. - // Please check and fix - miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State()) // Apply all transactions to the block - miner.ethereum.StateManager().ApplyTransactions(miner.block, miner.block.Transactions()) - miner.ethereum.StateManager().AccumelateRewards(miner.block) + miner.ethereum.StateManager().ApplyTransactions(miner.block.State(), miner.block, miner.block.Transactions()) + miner.ethereum.StateManager().AccumelateRewards(miner.block.State(), miner.block) // Search the nonce - //log.Println("[MINER] Initialision complete, starting mining") miner.block.Nonce = miner.pow.Search(miner.block, miner.quitChan) if miner.block.Nonce != nil { - miner.ethereum.StateManager().PrepareDefault(miner.block) - err := miner.ethereum.StateManager().ProcessBlock(miner.block, true) + err := miner.ethereum.StateManager().ProcessBlock(miner.ethereum.StateManager().CurrentState(), miner.block, true) if err != nil { log.Println(err) miner.txs = []*ethchain.Transaction{} // Move this somewhere neat miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs) } else { - - /* - // XXX @maranh This is already done in the state manager, why a 2nd time? - if !miner.ethereum.StateManager().Pow.Verify(miner.block.HashNoNonce(), miner.block.Difficulty, miner.block.Nonce) { - log.Printf("Second stage verification error: Block's nonce is invalid (= %v)\n", ethutil.Hex(miner.block.Nonce)) - } - */ miner.ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{miner.block.Value().Val}) log.Printf("[MINER] 🔨 Mined block %x\n", miner.block.Hash()) diff --git a/ethpub/pub.go b/ethpub/pub.go index daacb9d78..2513f83ed 100644 --- a/ethpub/pub.go +++ b/ethpub/pub.go @@ -45,7 +45,7 @@ func (lib *PEthereum) GetKey() *PKey { } func (lib *PEthereum) GetStateObject(address string) *PStateObject { - stateObject := lib.stateManager.ProcState().GetContract(ethutil.FromHex(address)) + stateObject := lib.stateManager.CurrentState().GetContract(ethutil.FromHex(address)) if stateObject != nil { return NewPStateObject(stateObject) } diff --git a/ethutil/config.go b/ethutil/config.go index b4bd9158e..296b72d9e 100644 --- a/ethutil/config.go +++ b/ethutil/config.go @@ -9,14 +9,6 @@ import ( "runtime" ) -// Log types available -type LogType byte - -const ( - LogTypeStdIn = 1 - LogTypeFile = 2 -) - // Config struct type config struct { Db Database @@ -34,7 +26,7 @@ var Config *config // Read config // // Initialize the global Config variable with default settings -func ReadConfig(base string) *config { +func ReadConfig(base string, logTypes LoggerType) *config { if Config == nil { usr, _ := user.Current() path := path.Join(usr.HomeDir, base) @@ -51,7 +43,7 @@ func ReadConfig(base string) *config { } Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC6"} - Config.Log = NewLogger(LogFile|LogStd, LogLevelDebug) + Config.Log = NewLogger(logTypes, LogLevelDebug) Config.SetClientString("/Ethereum(G)") } @@ -331,8 +331,9 @@ func (p *Peer) HandleInbound() { for i := msg.Data.Len() - 1; i >= 0; i-- { block = ethchain.NewBlockFromRlpValue(msg.Data.Get(i)) - p.ethereum.StateManager().PrepareDefault(block) - err = p.ethereum.StateManager().ProcessBlock(block, false) + //p.ethereum.StateManager().PrepareDefault(block) + state := p.ethereum.StateManager().CurrentState() + err = p.ethereum.StateManager().ProcessBlock(state, block, false) if err != nil { if ethutil.Config.Debug { |