From 7bf2ae0b116fff0fede5b1455c5fda20caf98252 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 15 May 2014 14:05:15 +0200 Subject: [PATCH 01/21] Removed old tx pool notification system. Fixes #19 --- ethchain/block_chain.go | 3 ++- ethchain/transaction_pool.go | 19 +++---------------- ethminer/miner.go | 4 ++-- ethutil/reactor.go | 3 ++- 4 files changed, 9 insertions(+), 20 deletions(-) diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index 2be4cd92b2..11fbc77957 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -260,7 +260,7 @@ func AddTestNetFunds(block *Block) { "e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey "1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex - "2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran + //"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran } { //log.Println("2^200 Wei to", addr) codedAddr := ethutil.FromHex(addr) @@ -268,6 +268,7 @@ func AddTestNetFunds(block *Block) { account.Amount = ethutil.BigPow(2, 200) block.state.UpdateStateObject(account) } + log.Printf("%x\n", block.RlpEncode()) } func (bc *BlockChain) setLastBlock() { diff --git a/ethchain/transaction_pool.go b/ethchain/transaction_pool.go index 6c0282dc60..21ce8cdc1e 100644 --- a/ethchain/transaction_pool.go +++ b/ethchain/transaction_pool.go @@ -133,7 +133,8 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract log.Printf("[TXPL] Processed Tx %x\n", tx.Hash()) - pool.notifySubscribers(TxPost, tx) + // Notify all subscribers + pool.Ethereum.Reactor().Post("newTx:post", tx) return } @@ -188,10 +189,7 @@ out: pool.addTransaction(tx) // Notify the subscribers - pool.Ethereum.Reactor().Post("newTx", tx) - - // Notify the subscribers - pool.notifySubscribers(TxPre, tx) + pool.Ethereum.Reactor().Post("newTx:pre", tx) } case <-pool.quit: break out @@ -252,14 +250,3 @@ func (pool *TxPool) Stop() { log.Println("[TXP] Stopped") } - -func (pool *TxPool) Subscribe(channel chan TxMsg) { - pool.subscribers = append(pool.subscribers, channel) -} - -func (pool *TxPool) notifySubscribers(ty TxMsgTy, tx *Transaction) { - msg := TxMsg{Type: ty, Tx: tx} - for _, subscriber := range pool.subscribers { - subscriber <- msg - } -} diff --git a/ethminer/miner.go b/ethminer/miner.go index 3796c873ed..f1d0caae9d 100644 --- a/ethminer/miner.go +++ b/ethminer/miner.go @@ -26,7 +26,7 @@ func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner { quitChan := make(chan ethutil.React, 1) // This is the channel that can exit the miner thread ethereum.Reactor().Subscribe("newBlock", reactChan) - ethereum.Reactor().Subscribe("newTx", reactChan) + ethereum.Reactor().Subscribe("newTx:post", reactChan) // We need the quit chan to be a Reactor event. // The POW search method is actually blocking and if we don't @@ -34,7 +34,7 @@ func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner { // The miner overseer will never get the reactor events themselves // Only after the miner will find the sha ethereum.Reactor().Subscribe("newBlock", quitChan) - ethereum.Reactor().Subscribe("newTx", quitChan) + ethereum.Reactor().Subscribe("newTx:post", quitChan) miner := Miner{ pow: ðchain.EasyPow{}, diff --git a/ethutil/reactor.go b/ethutil/reactor.go index f8084986c3..7cf1452456 100644 --- a/ethutil/reactor.go +++ b/ethutil/reactor.go @@ -46,6 +46,7 @@ func (e *ReactorEvent) Remove(ch chan React) { // Basic reactor resource type React struct { Resource interface{} + Event string } // The reactor basic engine. Acts as bridge @@ -81,6 +82,6 @@ func (reactor *ReactorEngine) Unsubscribe(event string, ch chan React) { func (reactor *ReactorEngine) Post(event string, resource interface{}) { ev := reactor.patterns[event] if ev != nil { - ev.Post(React{Resource: resource}) + ev.Post(React{Resource: resource, Event: event}) } } From f95993e326567555d0a2e1f96974c34e7b3a214f Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 15 May 2014 14:54:07 +0200 Subject: [PATCH 02/21] M --- ethchain/block_chain.go | 2 +- ethchain/state_manager.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index 11fbc77957..1848b9ddb4 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -260,7 +260,7 @@ func AddTestNetFunds(block *Block) { "e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey "1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex - //"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran + "2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran } { //log.Println("2^200 Wei to", addr) codedAddr := ethutil.FromHex(addr) diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index 57d56469b2..143d9d6471 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -193,11 +193,11 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error { if dontReact == false { sm.Ethereum.Reactor().Post("newBlock", block) - sm.notifyChanges() - sm.procState.manifest.Reset() } + sm.notifyChanges() + sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val}) sm.Ethereum.TxPool().RemoveInvalid(sm.procState) From 88686cbed27ad2e7d5c111051e06c270b1b352a3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 15 May 2014 15:00:25 +0200 Subject: [PATCH 03/21] listen to pre instead of post --- ethminer/miner.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ethminer/miner.go b/ethminer/miner.go index f1d0caae9d..bc29b2588c 100644 --- a/ethminer/miner.go +++ b/ethminer/miner.go @@ -26,7 +26,7 @@ func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner { quitChan := make(chan ethutil.React, 1) // This is the channel that can exit the miner thread ethereum.Reactor().Subscribe("newBlock", reactChan) - ethereum.Reactor().Subscribe("newTx:post", reactChan) + ethereum.Reactor().Subscribe("newTx:pre", reactChan) // We need the quit chan to be a Reactor event. // The POW search method is actually blocking and if we don't @@ -34,7 +34,7 @@ func NewDefaultMiner(coinbase []byte, ethereum ethchain.EthManager) Miner { // The miner overseer will never get the reactor events themselves // Only after the miner will find the sha ethereum.Reactor().Subscribe("newBlock", quitChan) - ethereum.Reactor().Subscribe("newTx:post", quitChan) + ethereum.Reactor().Subscribe("newTx:pre", quitChan) miner := Miner{ pow: ðchain.EasyPow{}, From 8730dfdcc2e2b40410a57385e4864d15f2f0336b Mon Sep 17 00:00:00 2001 From: obscuren Date: Sat, 17 May 2014 14:07:52 +0200 Subject: [PATCH 04/21] Changed how changes are being applied to states --- ethchain/block_chain.go | 4 +- ethchain/block_chain_test.go | 17 +++++- ethchain/state_manager.go | 109 ++++++++++++++++------------------- ethchain/transaction_pool.go | 3 +- ethchain/vm_test.go | 2 +- ethereum.go | 2 +- ethminer/miner.go | 24 ++------ ethpub/pub.go | 2 +- ethutil/config.go | 12 +--- peer.go | 5 +- 10 files changed, 82 insertions(+), 98 deletions(-) diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index 1848b9ddb4..6c3b15a6a3 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 30eb622660..4e4bb9dd40 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 143d9d6471..28570775ba 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 21ce8cdc1e..da77f32b3a 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 b919b496f1..5d03ccf0cf 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 83a74f3021..14418023e1 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 bc29b2588c..233a8bc32f 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 daacb9d782..2513f83ed1 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 b4bd9158ec..296b72d9ee 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)") } diff --git a/peer.go b/peer.go index 4093a4902b..45ff0a795a 100644 --- a/peer.go +++ b/peer.go @@ -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 { From bd48690f63d07d9a0568f0d8092006ebaa12af5f Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 19 May 2014 11:25:27 +0200 Subject: [PATCH 05/21] Testing different mining state --- ethchain/dagger.go | 4 ++-- ethchain/transaction_pool.go | 2 +- ethminer/miner.go | 19 +++++++++---------- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/ethchain/dagger.go b/ethchain/dagger.go index 9d2df40694..18e53d3a8c 100644 --- a/ethchain/dagger.go +++ b/ethchain/dagger.go @@ -29,14 +29,14 @@ func (pow *EasyPow) Search(block *Block, reactChan chan ethutil.React) []byte { for { select { case <-reactChan: - log.Println("[POW] Received reactor event; breaking out.") + ethutil.Config.Log.Infoln("[POW] Received reactor event; breaking out.") return nil default: i++ if i%1234567 == 0 { elapsed := time.Now().UnixNano() - start hashes := ((float64(1e9) / float64(elapsed)) * float64(i)) / 1000 - log.Println("[POW] Hashing @", int64(hashes), "khash") + ethutil.Config.Log.Infoln("[POW] Hashing @", int64(hashes), "khash") } sha := ethutil.Sha3Bin(big.NewInt(r.Int63()).Bytes()) diff --git a/ethchain/transaction_pool.go b/ethchain/transaction_pool.go index da77f32b3a..796ec7c9a6 100644 --- a/ethchain/transaction_pool.go +++ b/ethchain/transaction_pool.go @@ -131,7 +131,7 @@ func (pool *TxPool) ProcessTransaction(tx *Transaction, block *Block, toContract block.state.UpdateStateObject(sender) - log.Printf("[TXPL] Processed Tx %x\n", tx.Hash()) + ethutil.Config.Log.Infof("[TXPL] Processed Tx %x\n", tx.Hash()) // Notify all subscribers pool.Ethereum.Reactor().Post("newTx:post", tx) diff --git a/ethminer/miner.go b/ethminer/miner.go index 233a8bc32f..294bc7b3d2 100644 --- a/ethminer/miner.go +++ b/ethminer/miner.go @@ -5,7 +5,6 @@ import ( "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" "github.com/ethereum/eth-go/ethwire" - "log" ) type Miner struct { @@ -61,10 +60,10 @@ func (miner *Miner) listener() { select { case chanMessage := <-miner.reactChan: if block, ok := chanMessage.Resource.(*ethchain.Block); ok { - log.Println("[MINER] Got new block via Reactor") + ethutil.Config.Log.Infoln("[MINER] Got new block via Reactor") if bytes.Compare(miner.ethereum.BlockChain().CurrentBlock.Hash(), block.Hash()) == 0 { // TODO: Perhaps continue mining to get some uncle rewards - log.Println("[MINER] New top block found resetting state") + ethutil.Config.Log.Infoln("[MINER] New top block found resetting state") // Filter out which Transactions we have that were not in this block var newtxs []*ethchain.Transaction @@ -86,7 +85,7 @@ func (miner *Miner) listener() { } else { if bytes.Compare(block.PrevHash, miner.ethereum.BlockChain().CurrentBlock.PrevHash) == 0 { - log.Println("[MINER] Adding uncle block") + ethutil.Config.Log.Infoln("[MINER] Adding uncle block") miner.uncles = append(miner.uncles, block) //miner.ethereum.StateManager().Prepare(miner.block.State(), miner.block.State()) } @@ -94,7 +93,7 @@ func (miner *Miner) listener() { } if tx, ok := chanMessage.Resource.(*ethchain.Transaction); ok { - //log.Println("[MINER] Got new transaction from Reactor", tx) + //log.Infoln("[MINER] Got new transaction from Reactor", tx) found := false for _, ctx := range miner.txs { if found = bytes.Compare(ctx.Hash(), tx.Hash()) == 0; found { @@ -103,16 +102,16 @@ func (miner *Miner) listener() { } if found == false { - //log.Println("[MINER] We did not know about this transaction, adding") + //log.Infoln("[MINER] We did not know about this transaction, adding") miner.txs = append(miner.txs, tx) miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs) miner.block.SetTransactions(miner.txs) } else { - //log.Println("[MINER] We already had this transaction, ignoring") + //log.Infoln("[MINER] We already had this transaction, ignoring") } } default: - log.Println("[MINER] Mining on block. Includes", len(miner.txs), "transactions") + ethutil.Config.Log.Infoln("[MINER] Mining on block. Includes", len(miner.txs), "transactions") // Apply uncles if len(miner.uncles) > 0 { @@ -128,12 +127,12 @@ func (miner *Miner) listener() { if miner.block.Nonce != nil { err := miner.ethereum.StateManager().ProcessBlock(miner.ethereum.StateManager().CurrentState(), miner.block, true) if err != nil { - log.Println(err) + ethutil.Config.Log.Infoln(err) miner.txs = []*ethchain.Transaction{} // Move this somewhere neat miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs) } else { miner.ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{miner.block.Value().Val}) - log.Printf("[MINER] 🔨 Mined block %x\n", miner.block.Hash()) + ethutil.Config.Log.Infof("[MINER] 🔨 Mined block %x\n", miner.block.Hash()) miner.txs = []*ethchain.Transaction{} // Move this somewhere neat miner.block = miner.ethereum.BlockChain().NewBlock(miner.coinbase, miner.txs) From b8034f4d9ed7eea29a219a2d894ae22041a906a7 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 19 May 2014 12:14:04 +0200 Subject: [PATCH 06/21] Increment nonce in the public api --- ethchain/vm.go | 1 - ethpub/pub.go | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/ethchain/vm.go b/ethchain/vm.go index 584c666112..6579830ecb 100644 --- a/ethchain/vm.go +++ b/ethchain/vm.go @@ -95,7 +95,6 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro if ethutil.Config.Debug { ethutil.Config.Log.Debugf("# op\n") } - fmt.Println(closure.Script) for { // The base for all big integer arithmetic diff --git a/ethpub/pub.go b/ethpub/pub.go index 2513f83ed1..8c9a0666c0 100644 --- a/ethpub/pub.go +++ b/ethpub/pub.go @@ -162,6 +162,7 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in acc := lib.stateManager.TransState().GetStateObject(keyPair.Address()) //acc := lib.stateManager.GetAddrState(keyPair.Address()) tx.Nonce = acc.Nonce + acc.Nonce += 1 lib.stateManager.TransState().SetStateObject(acc) tx.Sign(keyPair.PrivateKey) From a2fb265563a3a6eb80efc5720bb0c6f3fec6f397 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 19 May 2014 17:02:16 +0200 Subject: [PATCH 07/21] Added a fatal method --- ethutil/config.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ethutil/config.go b/ethutil/config.go index 296b72d9ee..fd590fbdb8 100644 --- a/ethutil/config.go +++ b/ethutil/config.go @@ -130,7 +130,6 @@ func (log *Logger) Infoln(v ...interface{}) { return } - //fmt.Println(len(log.logSys)) for _, logger := range log.logSys { logger.Println(v...) } @@ -145,3 +144,15 @@ func (log *Logger) Infof(format string, v ...interface{}) { logger.Printf(format, v...) } } + +func (log *Logger) Fatal(v ...interface{}) { + if log.logLevel > LogLevelInfo { + return + } + + for _, logger := range log.logSys { + logger.Println(v...) + } + + os.Exit(1) +} From fd19142c0db3d2b6651989f5389944f3e211d84f Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 11:19:07 +0200 Subject: [PATCH 08/21] No longer store script directly in the state tree --- ethchain/block.go | 2 +- ethchain/block_chain.go | 2 +- ethchain/state.go | 49 +++++++++++------------------------ ethchain/state_manager.go | 5 ++-- ethchain/state_object.go | 21 ++++++++------- ethchain/state_object_test.go | 25 ++++++++++++++++++ ethchain/transaction.go | 2 +- ethchain/vm.go | 2 +- ethpub/pub.go | 3 +-- ethpub/types.go | 9 +++++++ peer.go | 2 +- 11 files changed, 70 insertions(+), 52 deletions(-) create mode 100644 ethchain/state_object_test.go diff --git a/ethchain/block.go b/ethchain/block.go index aac50ccb14..ca84dc19cf 100644 --- a/ethchain/block.go +++ b/ethchain/block.go @@ -122,7 +122,7 @@ func (block *Block) Transactions() []*Transaction { } func (block *Block) PayFee(addr []byte, fee *big.Int) bool { - contract := block.state.GetContract(addr) + contract := block.state.GetStateObject(addr) // If we can't pay the fee return if contract == nil || contract.Amount.Cmp(fee) < 0 /* amount < fee */ { fmt.Println("Contract has insufficient funds", contract.Amount, fee) diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index 6c3b15a6a3..99e17727c3 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -260,7 +260,7 @@ func AddTestNetFunds(block *Block) { "e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey "1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex - "2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran + //"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran } { //log.Println("2^200 Wei to", addr) codedAddr := ethutil.FromHex(addr) diff --git a/ethchain/state.go b/ethchain/state.go index d02584d679..63c4a32a63 100644 --- a/ethchain/state.go +++ b/ethchain/state.go @@ -49,28 +49,6 @@ func (s *State) Purge() int { return s.trie.NewIterator().Purge() } -// XXX Deprecated -func (s *State) GetContract(addr []byte) *StateObject { - data := s.trie.Get(string(addr)) - if data == "" { - return nil - } - - // build contract - contract := NewStateObjectFromBytes(addr, []byte(data)) - - // Check if there's a cached state for this contract - cachedState := s.states[string(addr)] - if cachedState != nil { - contract.state = cachedState - } else { - // If it isn't cached, cache the state - s.states[string(addr)] = contract.state - } - - return contract -} - func (s *State) GetStateObject(addr []byte) *StateObject { data := s.trie.Get(string(addr)) if data == "" { @@ -91,6 +69,21 @@ func (s *State) GetStateObject(addr []byte) *StateObject { return stateObject } +// Updates any given state object +func (s *State) UpdateStateObject(object *StateObject) { + addr := object.Address() + + if object.state != nil { + s.states[string(addr)] = object.state + } + + ethutil.Config.Db.Put(ethutil.Sha3Bin(object.Script()), object.Script()) + + s.trie.Update(string(addr), string(object.RlpEncode())) + + s.manifest.AddObjectChange(object) +} + func (s *State) SetStateObject(stateObject *StateObject) { s.states[string(stateObject.address)] = stateObject.state @@ -116,18 +109,6 @@ func (s *State) Copy() *State { return NewState(s.trie.Copy()) } -// Updates any given state object -func (s *State) UpdateStateObject(object *StateObject) { - addr := object.Address() - - if object.state != nil { - s.states[string(addr)] = object.state - } - - s.trie.Update(string(addr), string(object.RlpEncode())) - s.manifest.AddObjectChange(object) -} - func (s *State) Put(key, object []byte) { s.trie.Update(string(key), string(object)) } diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index 28570775ba..098263e8ad 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -87,7 +87,7 @@ func (sm *StateManager) BlockChain() *BlockChain { func (sm *StateManager) MakeContract(state *State, tx *Transaction) *StateObject { contract := MakeContract(tx, state) if contract != nil { - state.states[string(tx.Hash()[12:])] = contract.state + state.states[string(tx.CreationAddress())] = contract.state return contract } @@ -117,7 +117,8 @@ func (sm *StateManager) ApplyTransactions(state *State, block *Block, txs []*Tra } } else { err := sm.Ethereum.TxPool().ProcessTransaction(tx, block, false) - contract := state.GetContract(tx.Recipient) + contract := state.GetStateObject(tx.Recipient) + ethutil.Config.Log.Debugf("contract recip %x\n", tx.Recipient) if err == nil && len(contract.Script()) > 0 { sm.EvalScript(state, contract.Script(), contract, tx, block) } else if err != nil { diff --git a/ethchain/state_object.go b/ethchain/state_object.go index 7a11a11522..cb6211ea61 100644 --- a/ethchain/state_object.go +++ b/ethchain/state_object.go @@ -10,8 +10,9 @@ type StateObject struct { // Address of the object address []byte // Shared attributes - Amount *big.Int - Nonce uint64 + Amount *big.Int + ScriptHash []byte + Nonce uint64 // Contract related attributes state *State script []byte @@ -22,12 +23,10 @@ type StateObject struct { func MakeContract(tx *Transaction, state *State) *StateObject { // Create contract if there's no recipient if tx.IsContract() { - // FIXME - addr := tx.Hash()[12:] + addr := tx.CreationAddress() value := tx.Value - contract := NewContract(addr, value, []byte("")) - state.UpdateStateObject(contract) + contract := NewContract(addr, value, ZeroHash256) contract.script = tx.Data contract.initScript = tx.Init @@ -146,9 +145,10 @@ func (c *StateObject) RlpEncode() []byte { if c.state != nil { root = c.state.trie.Root } else { - root = nil + root = ZeroHash256 } - return ethutil.Encode([]interface{}{c.Amount, c.Nonce, root, c.script}) + + return ethutil.Encode([]interface{}{c.Amount, c.Nonce, root, ethutil.Sha3Bin(c.script)}) } func (c *StateObject) RlpDecode(data []byte) { @@ -157,7 +157,10 @@ func (c *StateObject) RlpDecode(data []byte) { c.Amount = decoder.Get(0).BigInt() c.Nonce = decoder.Get(1).Uint() c.state = NewState(ethutil.NewTrie(ethutil.Config.Db, decoder.Get(2).Interface())) - c.script = decoder.Get(3).Bytes() + + c.ScriptHash = decoder.Get(3).Bytes() + + c.script, _ = ethutil.Config.Db.Get(c.ScriptHash) } // Storage change object. Used by the manifest for notifying changes to diff --git a/ethchain/state_object_test.go b/ethchain/state_object_test.go new file mode 100644 index 0000000000..1db01a5373 --- /dev/null +++ b/ethchain/state_object_test.go @@ -0,0 +1,25 @@ +package ethchain + +import ( + "fmt" + "github.com/ethereum/eth-go/ethdb" + "github.com/ethereum/eth-go/ethutil" + "testing" +) + +func TestSync(t *testing.T) { + ethutil.ReadConfig("", ethutil.LogStd) + + db, _ := ethdb.NewMemDatabase() + state := NewState(ethutil.NewTrie(db, "")) + + contract := NewContract([]byte("aa"), ethutil.Big1, ZeroHash256) + + contract.script = []byte{42} + + state.UpdateStateObject(contract) + state.Sync() + + object := state.GetStateObject([]byte("aa")) + fmt.Printf("%x\n", object.Script()) +} diff --git a/ethchain/transaction.go b/ethchain/transaction.go index e93e610be5..8ea4704cb6 100644 --- a/ethchain/transaction.go +++ b/ethchain/transaction.go @@ -60,7 +60,7 @@ func (tx *Transaction) IsContract() bool { } func (tx *Transaction) CreationAddress() []byte { - return tx.Hash()[12:] + return ethutil.Sha3Bin(ethutil.NewValue([]interface{}{tx.Sender(), tx.Nonce}).Encode())[12:] } func (tx *Transaction) Signature(key []byte) []byte { diff --git a/ethchain/vm.go b/ethchain/vm.go index 6579830ecb..e732d22a42 100644 --- a/ethchain/vm.go +++ b/ethchain/vm.go @@ -471,7 +471,7 @@ func (vm *Vm) RunClosure(closure *Closure, hook DebugHook) (ret []byte, err erro args := mem.Get(inOffset.Int64(), inSize.Int64()) // Fetch the contract which will serve as the closure body - contract := vm.state.GetContract(addr.Bytes()) + contract := vm.state.GetStateObject(addr.Bytes()) if contract != nil { // Prepay for the gas diff --git a/ethpub/pub.go b/ethpub/pub.go index 8c9a0666c0..fb1018d471 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.CurrentState().GetContract(ethutil.FromHex(address)) + stateObject := lib.stateManager.CurrentState().GetStateObject(ethutil.FromHex(address)) if stateObject != nil { return NewPStateObject(stateObject) } @@ -160,7 +160,6 @@ func (lib *PEthereum) createTx(key, recipient, valueStr, gasStr, gasPriceStr, in } acc := lib.stateManager.TransState().GetStateObject(keyPair.Address()) - //acc := lib.stateManager.GetAddrState(keyPair.Address()) tx.Nonce = acc.Nonce acc.Nonce += 1 lib.stateManager.TransState().SetStateObject(acc) diff --git a/ethpub/types.go b/ethpub/types.go index c902afc564..75115f4e87 100644 --- a/ethpub/types.go +++ b/ethpub/types.go @@ -2,6 +2,7 @@ package ethpub import ( "encoding/hex" + "fmt" "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" ) @@ -112,6 +113,14 @@ func (c *PStateObject) IsContract() bool { return false } +func (c *PStateObject) Script() string { + if c.object != nil { + return ethutil.Hex(c.object.Script()) + } + + return "" +} + type PStorageState struct { StateAddress string Address string diff --git a/peer.go b/peer.go index 45ff0a795a..f84b4d472a 100644 --- a/peer.go +++ b/peer.go @@ -18,7 +18,7 @@ const ( // The size of the output buffer for writing messages outputBufferSize = 50 // Current protocol version - ProtocolVersion = 8 + ProtocolVersion = 9 ) type DiscReason byte From 12f30e6220354c4a8b08ecf41bb53444143f3660 Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 20 May 2014 11:50:34 +0200 Subject: [PATCH 09/21] Refactored a lot of the chain catchup/reorg. --- ethchain/block_chain.go | 2 +- ethereum.go | 4 +- peer.go | 131 +++++++++++++++++++++++----------------- 3 files changed, 79 insertions(+), 58 deletions(-) diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index 6c3b15a6a3..2ce0f90a6b 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -127,7 +127,6 @@ func (bc *BlockChain) FindCanonicalChain(blocks []*Block, commonBlockHash []byte log.Println("[CHAIN] We have found the common parent block, breaking") break } - log.Println("Checking incoming blocks:") chainDifficulty.Add(chainDifficulty, bc.CalculateBlockTD(block)) } @@ -182,6 +181,7 @@ func (bc *BlockChain) ResetTillBlockHash(hash []byte) error { // XXX Why are we resetting? This is the block chain, it has nothing to do with states //bc.Ethereum.StateManager().PrepareDefault(returnTo) + // Manually reset the last sync block err := ethutil.Config.Db.Delete(lastBlock.Hash()) if err != nil { return err diff --git a/ethereum.go b/ethereum.go index 14418023e1..3a7202d535 100644 --- a/ethereum.go +++ b/ethereum.go @@ -222,7 +222,7 @@ func (s *Ethereum) ConnectToPeer(addr string) error { if phost == chost { alreadyConnected = true - ethutil.Config.Log.Debugf("[SERV] Peer %s already added.\n", chost) + //ethutil.Config.Log.Debugf("[SERV] Peer %s already added.\n", chost) return } }) @@ -235,7 +235,7 @@ func (s *Ethereum) ConnectToPeer(addr string) error { s.peers.PushBack(peer) - ethutil.Config.Log.Infof("[SERV] Adding peer %d / %d\n", s.peers.Len(), s.MaxPeers) + ethutil.Config.Log.Infof("[SERV] Adding peer (%s) %d / %d\n", addr, s.peers.Len(), s.MaxPeers) } return nil diff --git a/peer.go b/peer.go index 45ff0a795a..879361b2b4 100644 --- a/peer.go +++ b/peer.go @@ -127,6 +127,7 @@ type Peer struct { // Indicated whether the node is catching up or not catchingUp bool + diverted bool blocksRequested int Version string @@ -190,7 +191,6 @@ func (p *Peer) QueueMessage(msg *ethwire.Msg) { if atomic.LoadInt32(&p.connected) != 1 { return } - p.outputQueue <- msg } @@ -268,7 +268,6 @@ func (p *Peer) HandleInbound() { for atomic.LoadInt32(&p.disconnect) == 0 { // HMM? time.Sleep(500 * time.Millisecond) - // Wait for a message from the peer msgs, err := ethwire.ReadMessages(p.conn) if err != nil { @@ -300,32 +299,36 @@ func (p *Peer) HandleInbound() { var err error // Make sure we are actually receiving anything - if msg.Data.Len()-1 > 1 && p.catchingUp { + if msg.Data.Len()-1 > 1 && p.diverted { // We requested blocks and now we need to make sure we have a common ancestor somewhere in these blocks so we can find // common ground to start syncing from lastBlock = ethchain.NewBlockFromRlpValue(msg.Data.Get(msg.Data.Len() - 1)) - if !p.ethereum.StateManager().BlockChain().HasBlock(lastBlock.Hash()) { - // If we can't find a common ancenstor we need to request more blocks. - // FIXME: At one point this won't scale anymore since we are not asking for an offset - // we just keep increasing the amount of blocks. - //fmt.Println("[PEER] No common ancestor found, requesting more blocks.") - p.blocksRequested = p.blocksRequested * 2 - p.catchingUp = false - p.SyncWithBlocks() - } - + ethutil.Config.Log.Infof("[PEER] Last block: %x. Checking if we have it locally.\n", lastBlock.Hash()) for i := msg.Data.Len() - 1; i >= 0; i-- { block = ethchain.NewBlockFromRlpValue(msg.Data.Get(i)) // Do we have this block on our chain? If so we can continue if !p.ethereum.StateManager().BlockChain().HasBlock(block.Hash()) { // We don't have this block, but we do have a block with the same prevHash, diversion time! if p.ethereum.StateManager().BlockChain().HasBlockWithPrevHash(block.PrevHash) { - if p.ethereum.StateManager().BlockChain().FindCanonicalChainFromMsg(msg, block.PrevHash) { - return + p.diverted = false + if !p.ethereum.StateManager().BlockChain().FindCanonicalChainFromMsg(msg, block.PrevHash) { + p.SyncWithPeerToLastKnown() } + break } } } + if !p.ethereum.StateManager().BlockChain().HasBlock(lastBlock.Hash()) { + // If we can't find a common ancenstor we need to request more blocks. + // FIXME: At one point this won't scale anymore since we are not asking for an offset + // we just keep increasing the amount of blocks. + p.blocksRequested = p.blocksRequested * 2 + + ethutil.Config.Log.Infof("[PEER] No common ancestor found, requesting %d more blocks.\n", p.blocksRequested) + p.catchingUp = false + p.FindCommonParentBlock() + break + } } for i := msg.Data.Len() - 1; i >= 0; i-- { @@ -346,23 +349,28 @@ func (p *Peer) HandleInbound() { } } + if msg.Data.Len() == 0 { + // Set catching up to false if + // the peer has nothing left to give + p.catchingUp = false + } + if err != nil { // If the parent is unknown try to catch up with this peer if ethchain.IsParentErr(err) { - ethutil.Config.Log.Infoln("Attempting to catch up") + ethutil.Config.Log.Infoln("Attempting to catch up since we don't know the parent") p.catchingUp = false p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash()) } else if ethchain.IsValidationErr(err) { - fmt.Println(err) + fmt.Println("Err:", err) p.catchingUp = false } } else { - // XXX Do we want to catch up if there were errors? // If we're catching up, try to catch up further. if p.catchingUp && msg.Data.Len() > 1 { - if ethutil.Config.Debug && lastBlock != nil { + if lastBlock != nil { blockInfo := lastBlock.BlockInfo() - ethutil.Config.Log.Infof("Synced to block height #%d %x %x\n", blockInfo.Number, lastBlock.Hash(), blockInfo.Hash) + ethutil.Config.Log.Debugf("Synced to block height #%d %x %x\n", blockInfo.Number, lastBlock.Hash(), blockInfo.Hash) } p.catchingUp = false @@ -372,11 +380,6 @@ func (p *Peer) HandleInbound() { } } - if msg.Data.Len() == 0 { - // Set catching up to false if - // the peer has nothing left to give - p.catchingUp = false - } case ethwire.MsgTxTy: // If the message was a transaction queue the transaction // in the TxPool where it will undergo validation and @@ -444,7 +447,7 @@ func (p *Peer) HandleInbound() { } } else { - ethutil.Config.Log.Debugf("[PEER] Could not find a similar block") + //ethutil.Config.Log.Debugf("[PEER] Could not find a similar block") // If no blocks are found we send back a reply with msg not in chain // and the last hash from get chain lastHash := msg.Data.Get(l - 1) @@ -452,8 +455,14 @@ func (p *Peer) HandleInbound() { p.QueueMessage(ethwire.NewMessage(ethwire.MsgNotInChainTy, []interface{}{lastHash.Raw()})) } case ethwire.MsgNotInChainTy: - ethutil.Config.Log.Debugf("Not in chain %x\n", msg.Data) - // TODO + ethutil.Config.Log.Debugf("Not in chain: %x\n", msg.Data.Get(0).Bytes()) + if p.diverted == true { + // If were already looking for a common parent and we get here again we need to go deeper + p.blocksRequested = p.blocksRequested * 2 + } + p.diverted = true + p.catchingUp = false + p.FindCommonParentBlock() case ethwire.MsgGetTxsTy: // Get the current transactions of the pool txs := p.ethereum.TxPool().CurrentTransactions() @@ -471,7 +480,6 @@ func (p *Peer) HandleInbound() { } } } - p.Stop() } @@ -581,14 +589,18 @@ func (p *Peer) handleHandshake(msg *ethwire.Msg) { } - // Catch up with the connected peer - p.SyncWithBlocks() - // Set the peer's caps p.caps = Caps(c.Get(3).Byte()) // Get a reference to the peers version p.Version = c.Get(2).Str() + // Catch up with the connected peer + if !p.ethereum.IsUpToDate() { + ethutil.Config.Log.Debugln("Already syncing up with a peer; sleeping") + time.Sleep(10 * time.Second) + } + p.SyncWithPeerToLastKnown() + ethutil.Config.Log.Debugln("[PEER]", p) } @@ -609,38 +621,47 @@ func (p *Peer) String() string { return fmt.Sprintf("[%s] (%s) %v %s [%s]", strConnectType, strBoundType, p.conn.RemoteAddr(), p.Version, p.caps) } -func (p *Peer) SyncWithBlocks() { - if !p.catchingUp { - p.catchingUp = true - // FIXME: THIS SHOULD NOT BE NEEDED - if p.blocksRequested == 0 { - p.blocksRequested = 10 - } - blocks := p.ethereum.BlockChain().GetChain(p.ethereum.BlockChain().CurrentBlock.Hash(), p.blocksRequested) - - var hashes []interface{} - for _, block := range blocks { - hashes = append(hashes, block.Hash()) - } - - msgInfo := append(hashes, uint64(50)) - - msg := ethwire.NewMessage(ethwire.MsgGetChainTy, msgInfo) - p.QueueMessage(msg) - } +func (p *Peer) SyncWithPeerToLastKnown() { + p.catchingUp = false + p.CatchupWithPeer(p.ethereum.BlockChain().CurrentBlock.Hash()) } +func (p *Peer) FindCommonParentBlock() { + if p.catchingUp { + return + } + + p.catchingUp = true + if p.blocksRequested == 0 { + p.blocksRequested = 20 + } + blocks := p.ethereum.BlockChain().GetChain(p.ethereum.BlockChain().CurrentBlock.Hash(), p.blocksRequested) + + var hashes []interface{} + for _, block := range blocks { + hashes = append(hashes, block.Hash()) + } + + msgInfo := append(hashes, uint64(len(hashes))) + + ethutil.Config.Log.Infof("Asking for block from %x (%d total) from %s\n", p.ethereum.BlockChain().CurrentBlock.Hash(), len(hashes), p.conn.RemoteAddr().String()) + + msg := ethwire.NewMessage(ethwire.MsgGetChainTy, msgInfo) + p.QueueMessage(msg) +} func (p *Peer) CatchupWithPeer(blockHash []byte) { if !p.catchingUp { + // Make sure nobody else is catching up when you want to do this p.catchingUp = true msg := ethwire.NewMessage(ethwire.MsgGetChainTy, []interface{}{blockHash, uint64(50)}) p.QueueMessage(msg) - ethutil.Config.Log.Debugf("Requesting blockchain %x...\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4]) + ethutil.Config.Log.Debugf("Requesting blockchain %x... from peer %s\n", p.ethereum.BlockChain().CurrentBlock.Hash()[:4], p.conn.RemoteAddr()) - msg = ethwire.NewMessage(ethwire.MsgGetTxsTy, []interface{}{}) - p.QueueMessage(msg) - ethutil.Config.Log.Debugln("Requested transactions") + /* + msg = ethwire.NewMessage(ethwire.MsgGetTxsTy, []interface{}{}) + p.QueueMessage(msg) + */ } } From 2450398862e8ac55b39dd88a3af169985e1727f3 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 12:19:21 +0200 Subject: [PATCH 10/21] Added Maran to premine --- ethchain/block_chain.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index 99e17727c3..9926354bde 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -260,9 +260,8 @@ func AddTestNetFunds(block *Block) { "e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey "1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex - //"2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran + "2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran } { - //log.Println("2^200 Wei to", addr) codedAddr := ethutil.FromHex(addr) account := block.state.GetAccount(codedAddr) account.Amount = ethutil.BigPow(2, 200) From fafdd21e4fb18c9714c4f784d443e9592ec3ff69 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 12:23:49 +0200 Subject: [PATCH 11/21] unused --- ethpub/types.go | 1 - 1 file changed, 1 deletion(-) diff --git a/ethpub/types.go b/ethpub/types.go index 75115f4e87..5d3bfcaaad 100644 --- a/ethpub/types.go +++ b/ethpub/types.go @@ -2,7 +2,6 @@ package ethpub import ( "encoding/hex" - "fmt" "github.com/ethereum/eth-go/ethchain" "github.com/ethereum/eth-go/ethutil" ) From 530ab6b8fc9e7ea2b784dbd3f16d0272d227f6d6 Mon Sep 17 00:00:00 2001 From: Nick Savers Date: Tue, 20 May 2014 13:02:37 +0200 Subject: [PATCH 12/21] Re-arranged transaction RLP encoding... According to latest Yellow Paper specs and conform other clients https://github.com/ethereum/latexpaper/commit/4794642e51ac1884e5e1af8a18ebc83aca115d64 --- ethchain/transaction.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/ethchain/transaction.go b/ethchain/transaction.go index 8ea4704cb6..c18ff7c53d 100644 --- a/ethchain/transaction.go +++ b/ethchain/transaction.go @@ -109,10 +109,10 @@ func (tx *Transaction) Sign(privk []byte) error { return nil } -// [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ] -// [ NONCE, VALUE, GASPRICE, GAS, 0, CODE, INIT, V, R, S ] +// [ NONCE, GASPRICE, GAS, TO, VALUE, DATA, V, R, S ] +// [ NONCE, GASPRICE, GAS, 0, VALUE, CODE, INIT, V, R, S ] func (tx *Transaction) RlpData() interface{} { - data := []interface{}{tx.Nonce, tx.Value, tx.GasPrice, tx.Gas, tx.Recipient, tx.Data} + data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} if tx.contractCreation { data = append(data, tx.Init) @@ -135,10 +135,10 @@ func (tx *Transaction) RlpDecode(data []byte) { func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) { tx.Nonce = decoder.Get(0).Uint() - tx.Value = decoder.Get(1).BigInt() - tx.GasPrice = decoder.Get(2).BigInt() - tx.Gas = decoder.Get(3).BigInt() - tx.Recipient = decoder.Get(4).Bytes() + tx.GasPrice = decoder.Get(1).BigInt() + tx.Gas = decoder.Get(2).BigInt() + tx.Recipient = decoder.Get(3).Bytes() + tx.Value = decoder.Get(4).BigInt() tx.Data = decoder.Get(5).Bytes() // If the list is of length 10 it's a contract creation tx From 378815ee62b21cec60aceeafc7bc8a2a479290b5 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 13:06:47 +0200 Subject: [PATCH 13/21] Rearranged according to YP --- ethchain/transaction.go | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/ethchain/transaction.go b/ethchain/transaction.go index 8ea4704cb6..bd7a0e424c 100644 --- a/ethchain/transaction.go +++ b/ethchain/transaction.go @@ -109,10 +109,8 @@ func (tx *Transaction) Sign(privk []byte) error { return nil } -// [ NONCE, VALUE, GASPRICE, GAS, TO, DATA, V, R, S ] -// [ NONCE, VALUE, GASPRICE, GAS, 0, CODE, INIT, V, R, S ] func (tx *Transaction) RlpData() interface{} { - data := []interface{}{tx.Nonce, tx.Value, tx.GasPrice, tx.Gas, tx.Recipient, tx.Data} + data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} if tx.contractCreation { data = append(data, tx.Init) @@ -135,10 +133,10 @@ func (tx *Transaction) RlpDecode(data []byte) { func (tx *Transaction) RlpValueDecode(decoder *ethutil.Value) { tx.Nonce = decoder.Get(0).Uint() - tx.Value = decoder.Get(1).BigInt() - tx.GasPrice = decoder.Get(2).BigInt() - tx.Gas = decoder.Get(3).BigInt() - tx.Recipient = decoder.Get(4).Bytes() + tx.GasPrice = decoder.Get(1).BigInt() + tx.Gas = decoder.Get(2).BigInt() + tx.Recipient = decoder.Get(3).Bytes() + tx.Value = decoder.Get(4).BigInt() tx.Data = decoder.Get(5).Bytes() // If the list is of length 10 it's a contract creation tx From 45b810450fc75ef47964b1b53197114d1bf6db3d Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 13:09:44 +0200 Subject: [PATCH 14/21] ... --- ethchain/transaction.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ethchain/transaction.go b/ethchain/transaction.go index a36286e86e..bd7a0e424c 100644 --- a/ethchain/transaction.go +++ b/ethchain/transaction.go @@ -109,11 +109,6 @@ func (tx *Transaction) Sign(privk []byte) error { return nil } -<<<<<<< HEAD -======= -// [ NONCE, GASPRICE, GAS, TO, VALUE, DATA, V, R, S ] -// [ NONCE, GASPRICE, GAS, 0, VALUE, CODE, INIT, V, R, S ] ->>>>>>> 38b4dc2cdf23380532a25240760273dd07b9dff6 func (tx *Transaction) RlpData() interface{} { data := []interface{}{tx.Nonce, tx.GasPrice, tx.Gas, tx.Recipient, tx.Value, tx.Data} From 6a31d55b2e2d95dd64e3d56b0c12e9ffb7c1c373 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 13:29:21 +0200 Subject: [PATCH 15/21] added roman --- ethchain/block_chain.go | 1 + 1 file changed, 1 insertion(+) diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index 457aed714f..eb25bd3f40 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -261,6 +261,7 @@ func AddTestNetFunds(block *Block) { "1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit "1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex "2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran + "cd2a3d9f938e13cd947ec05abc7fe734df8dd826", // Roman } { codedAddr := ethutil.FromHex(addr) account := block.state.GetAccount(codedAddr) From b4e156e1d723fe53eff238a634f6e83cb9d80492 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 13:29:46 +0200 Subject: [PATCH 16/21] Up protocol version --- peer.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peer.go b/peer.go index 4a390f015c..993f48d20b 100644 --- a/peer.go +++ b/peer.go @@ -18,7 +18,7 @@ const ( // The size of the output buffer for writing messages outputBufferSize = 50 // Current protocol version - ProtocolVersion = 9 + ProtocolVersion = 10 ) type DiscReason byte From 7d3e99a2abcef6011714a7e6e515aa8e2bc738cc Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 14:29:52 +0200 Subject: [PATCH 17/21] Fixed genesis and block data --- ethchain/block.go | 69 ++++++++++++++++++++++++++++++++++++++++----- ethchain/genesis.go | 17 +++++++---- 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/ethchain/block.go b/ethchain/block.go index ca84dc19cf..beb2bc14ca 100644 --- a/ethchain/block.go +++ b/ethchain/block.go @@ -40,6 +40,14 @@ type Block struct { Difficulty *big.Int // Creation time Time int64 + // The block number + Number *big.Int + // Minimum Gas Price + MinGasPrice *big.Int + // Gas limit + GasLimit *big.Int + // Gas used + GasUsed *big.Int // Extra data Extra string // Block Nonce for verification @@ -233,9 +241,13 @@ func (block *Block) RlpValueDecode(decoder *ethutil.Value) { block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, header.Get(3).Val)) block.TxSha = header.Get(4).Bytes() block.Difficulty = header.Get(5).BigInt() - block.Time = int64(header.Get(6).BigInt().Uint64()) - block.Extra = header.Get(7).Str() - block.Nonce = header.Get(8).Bytes() + block.Number = header.Get(6).BigInt() + block.MinGasPrice = header.Get(7).BigInt() + block.GasLimit = header.Get(8).BigInt() + block.GasUsed = header.Get(9).BigInt() + block.Time = int64(header.Get(10).BigInt().Uint64()) + block.Extra = header.Get(11).Str() + block.Nonce = header.Get(12).Bytes() block.contractStates = make(map[string]*ethutil.Trie) // Tx list might be empty if this is an uncle. Uncles only have their @@ -270,16 +282,51 @@ func NewUncleBlockFromValue(header *ethutil.Value) *Block { block.state = NewState(ethutil.NewTrie(ethutil.Config.Db, header.Get(3).Val)) block.TxSha = header.Get(4).Bytes() block.Difficulty = header.Get(5).BigInt() - block.Time = int64(header.Get(6).BigInt().Uint64()) - block.Extra = header.Get(7).Str() - block.Nonce = header.Get(8).Bytes() + block.Number = header.Get(6).BigInt() + block.MinGasPrice = header.Get(7).BigInt() + block.GasLimit = header.Get(8).BigInt() + block.GasUsed = header.Get(9).BigInt() + block.Time = int64(header.Get(10).BigInt().Uint64()) + block.Extra = header.Get(11).Str() + block.Nonce = header.Get(12).Bytes() return block } func (block *Block) String() string { - return fmt.Sprintf("Block(%x):\nPrevHash:%x\nUncleSha:%x\nCoinbase:%x\nRoot:%x\nTxSha:%x\nDiff:%v\nTime:%d\nNonce:%x\nTxs:%d\n", block.Hash(), block.PrevHash, block.UncleSha, block.Coinbase, block.state.trie.Root, block.TxSha, block.Difficulty, block.Time, block.Nonce, len(block.transactions)) + //return fmt.Sprintf("Block(%x):\nPrevHash:%x\nUncleSha:%x\nCoinbase:%x\nRoot:%x\nTxSha:%x\nDiff:%v\nNonce:%x\nTxs:%d\n", block.Hash(), block.PrevHash, block.UncleSha, block.Coinbase, block.state.trie.Root, block.TxSha, block.Difficulty, block.Time, block.Nonce, len(block.transactions)) + return fmt.Sprintf(` + Block(%x): + PrevHash: %x + UncleSha: %x + Coinbase: %x + Root: %x + TxSha: %x + Difficulty: %v + Number: %v + MinGas: %v + MaxLimit: %v + GasUsed: %v + Time: %v + Extra: %v + Nonce: %x +`, + block.Hash(), + block.PrevHash, + block.UncleSha, + block.Coinbase, + block.state.trie.Root, + block.TxSha, + block.Difficulty, + block.Number, + block.MinGasPrice, + block.GasLimit, + block.GasUsed, + block.Time, + block.Extra, + block.Nonce) } + func (block *Block) GetRoot() interface{} { return block.state.trie.Root } @@ -299,6 +346,14 @@ func (block *Block) header() []interface{} { block.TxSha, // Current block Difficulty block.Difficulty, + // The block number + block.Number, + // Block minimum gas price + block.MinGasPrice, + // Block upper gas bound + block.GasLimit, + // Block gas used + block.GasUsed, // Time the block was found? block.Time, // Extra data diff --git a/ethchain/genesis.go b/ethchain/genesis.go index 935978a69e..7e145ef533 100644 --- a/ethchain/genesis.go +++ b/ethchain/genesis.go @@ -15,7 +15,6 @@ var EmptyShaList = ethutil.Sha3Bin(ethutil.Encode([]interface{}{})) var GenesisHeader = []interface{}{ // Previous hash (none) - //"", ZeroHash256, // Sha of uncles ethutil.Sha3Bin(ethutil.Encode([]interface{}{})), @@ -23,15 +22,23 @@ var GenesisHeader = []interface{}{ ZeroHash160, // Root state "", - // Sha of transactions //EmptyShaList, - ethutil.Sha3Bin(ethutil.Encode([]interface{}{})), + ZeroHash256, + //ethutil.Sha3Bin(ethutil.Encode(ZeroHash256)), // Difficulty ethutil.BigPow(2, 22), + // Number + ethutil.Big0, + // Block minimum gas price + ethutil.Big0, + // Block upper gas bound + big.NewInt(1000000), + // Block gas used + ethutil.Big0, // Time - int64(0), + ethutil.Big0, // Extra - "", + nil, // Nonce ethutil.Sha3Bin(big.NewInt(42).Bytes()), } From f5d441473499428964b75924845cf0c7bcaaa5ca Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 20 May 2014 14:41:35 +0200 Subject: [PATCH 18/21] Fix notification when processing block that didn't have this client as origin --- ethchain/state_manager.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go index 098263e8ad..c7c6857d83 100644 --- a/ethchain/state_manager.go +++ b/ethchain/state_manager.go @@ -180,6 +180,7 @@ func (sm *StateManager) ProcessBlock(state *State, block *Block, dontReact bool) // Add the block to the chain sm.bc.Add(block) + sm.notifyChanges(state) ethutil.Config.Log.Infof("[STATE] Added block #%d (%x)\n", block.BlockInfo().Number, block.Hash()) if dontReact == false { @@ -188,8 +189,6 @@ func (sm *StateManager) ProcessBlock(state *State, block *Block, dontReact bool) state.manifest.Reset() } - sm.notifyChanges(state) - sm.Ethereum.Broadcast(ethwire.MsgBlockTy, []interface{}{block.Value().Val}) sm.Ethereum.TxPool().RemoveInvalid(state) From 31e44c2ab959124cbcf2de45385373b9898727bc Mon Sep 17 00:00:00 2001 From: Maran Date: Tue, 20 May 2014 14:53:34 +0200 Subject: [PATCH 19/21] Change shorthands --- ethutil/common.go | 26 +++++++++++++------------- ethutil/common_test.go | 6 +++--- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ethutil/common.go b/ethutil/common.go index 983ea5d1bc..771dfc723c 100644 --- a/ethutil/common.go +++ b/ethutil/common.go @@ -7,13 +7,13 @@ import ( // The different number of units var ( - Ether = BigPow(10, 18) - Finney = BigPow(10, 15) - Szabo = BigPow(10, 12) - Vita = BigPow(10, 9) - Turing = BigPow(10, 6) - Eins = BigPow(10, 3) - Wei = big.NewInt(1) + Ether = BigPow(10, 18) + Finney = BigPow(10, 15) + Szabo = BigPow(10, 12) + Shannon = BigPow(10, 9) + Babbage = BigPow(10, 6) + Ada = BigPow(10, 3) + Wei = big.NewInt(1) ) // Currency to string @@ -27,12 +27,12 @@ func CurrencyToString(num *big.Int) string { return fmt.Sprintf("%v Finney", new(big.Int).Div(num, Finney)) case num.Cmp(Szabo) >= 0: return fmt.Sprintf("%v Szabo", new(big.Int).Div(num, Szabo)) - case num.Cmp(Vita) >= 0: - return fmt.Sprintf("%v Vita", new(big.Int).Div(num, Vita)) - case num.Cmp(Turing) >= 0: - return fmt.Sprintf("%v Turing", new(big.Int).Div(num, Turing)) - case num.Cmp(Eins) >= 0: - return fmt.Sprintf("%v Eins", new(big.Int).Div(num, Eins)) + case num.Cmp(Shannon) >= 0: + return fmt.Sprintf("%v Shannon", new(big.Int).Div(num, Shannon)) + case num.Cmp(Babbage) >= 0: + return fmt.Sprintf("%v Babbage", new(big.Int).Div(num, Babbage)) + case num.Cmp(Ada) >= 0: + return fmt.Sprintf("%v Ada", new(big.Int).Div(num, Ada)) } return fmt.Sprintf("%v Wei", num) diff --git a/ethutil/common_test.go b/ethutil/common_test.go index 8031f08ab5..2667eaf3af 100644 --- a/ethutil/common_test.go +++ b/ethutil/common_test.go @@ -26,15 +26,15 @@ func TestCommon(t *testing.T) { t.Error("Got", szabo) } - if vito != "10 Vita" { + if vito != "10 Shannon" { t.Error("Got", vito) } - if turing != "10 Turing" { + if turing != "10 Babbage" { t.Error("Got", turing) } - if eins != "10 Eins" { + if eins != "10 Ada" { t.Error("Got", eins) } From 2bd377a3de54652923558b63cc8756531269e36e Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 15:02:46 +0200 Subject: [PATCH 20/21] Changed transaction hash for poc 5 --- ethchain/block.go | 76 ++++++++++++++++++++++------------------- ethchain/block_chain.go | 16 +++++++++ ethchain/genesis.go | 3 +- 3 files changed, 57 insertions(+), 38 deletions(-) diff --git a/ethchain/block.go b/ethchain/block.go index beb2bc14ca..c6c2c1226c 100644 --- a/ethchain/block.go +++ b/ethchain/block.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/ethereum/eth-go/ethutil" "math/big" + "strconv" "time" ) @@ -214,7 +215,12 @@ func (block *Block) SetUncles(uncles []*Block) { func (block *Block) SetTransactions(txs []*Transaction) { block.transactions = txs - block.TxSha = ethutil.Sha3Bin(ethutil.Encode(block.rlpTxs())) + trie := ethutil.NewTrie(ethutil.Config.Db, "") + for i, tx := range txs { + trie.Update(strconv.Itoa(i), string(tx.RlpEncode())) + } + + block.TxSha = trie.Root.([]byte) } func (block *Block) Value() *ethutil.Value { @@ -293,45 +299,10 @@ func NewUncleBlockFromValue(header *ethutil.Value) *Block { return block } -func (block *Block) String() string { - //return fmt.Sprintf("Block(%x):\nPrevHash:%x\nUncleSha:%x\nCoinbase:%x\nRoot:%x\nTxSha:%x\nDiff:%v\nNonce:%x\nTxs:%d\n", block.Hash(), block.PrevHash, block.UncleSha, block.Coinbase, block.state.trie.Root, block.TxSha, block.Difficulty, block.Time, block.Nonce, len(block.transactions)) - return fmt.Sprintf(` - Block(%x): - PrevHash: %x - UncleSha: %x - Coinbase: %x - Root: %x - TxSha: %x - Difficulty: %v - Number: %v - MinGas: %v - MaxLimit: %v - GasUsed: %v - Time: %v - Extra: %v - Nonce: %x -`, - block.Hash(), - block.PrevHash, - block.UncleSha, - block.Coinbase, - block.state.trie.Root, - block.TxSha, - block.Difficulty, - block.Number, - block.MinGasPrice, - block.GasLimit, - block.GasUsed, - block.Time, - block.Extra, - block.Nonce) -} - func (block *Block) GetRoot() interface{} { return block.state.trie.Root } -//////////// UNEXPORTED ///////////////// func (block *Block) header() []interface{} { return []interface{}{ // Sha of the previous block @@ -362,3 +333,36 @@ func (block *Block) header() []interface{} { block.Nonce, } } + +func (block *Block) String() string { + return fmt.Sprintf(` + BLOCK(%x): + PrevHash: %x + UncleSha: %x + Coinbase: %x + Root: %x + TxSha: %x + Difficulty: %v + Number: %v + MinGas: %v + MaxLimit: %v + GasUsed: %v + Time: %v + Extra: %v + Nonce: %x +`, + block.Hash(), + block.PrevHash, + block.UncleSha, + block.Coinbase, + block.state.trie.Root, + block.TxSha, + block.Difficulty, + block.Number, + block.MinGasPrice, + block.GasLimit, + block.GasUsed, + block.Time, + block.Extra, + block.Nonce) +} diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go index eb25bd3f40..2865336fbc 100644 --- a/ethchain/block_chain.go +++ b/ethchain/block_chain.go @@ -70,6 +70,22 @@ func (bc *BlockChain) NewBlock(coinbase []byte, txs []*Transaction) *Block { diff.Mul(diff, mul) diff.Add(diff, bc.CurrentBlock.Difficulty) block.Difficulty = diff + + block.Number = new(big.Int).Add(bc.CurrentBlock.Number, ethutil.Big1) + + // max(10000, (parent gas limit * (1024 - 1) + (parent gas used * 6 / 5)) / 1024) + base := new(big.Int) + base2 := new(big.Int) + parentGL := bc.CurrentBlock.GasLimit + parentUsed := bc.CurrentBlock.GasUsed + + base.Mul(parentGL, big.NewInt(1024-1)) + base2.Mul(parentUsed, big.NewInt(6)) + base2.Div(base2, big.NewInt(5)) + base.Add(base, base2) + base.Div(base, big.NewInt(1024)) + + block.GasLimit = ethutil.BigMax(big.NewInt(10000), base) } return block diff --git a/ethchain/genesis.go b/ethchain/genesis.go index 7e145ef533..b8f9f865a3 100644 --- a/ethchain/genesis.go +++ b/ethchain/genesis.go @@ -22,9 +22,8 @@ var GenesisHeader = []interface{}{ ZeroHash160, // Root state "", - //EmptyShaList, + // tx sha ZeroHash256, - //ethutil.Sha3Bin(ethutil.Encode(ZeroHash256)), // Difficulty ethutil.BigPow(2, 22), // Number From c37b3cef7dc465832761b1da6761eeaa47e368d1 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 20 May 2014 17:08:53 +0200 Subject: [PATCH 21/21] Bump --- README.md | 2 +- ethutil/config.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2627bc85e2..f6bcaad288 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Ethereum Ethereum Go Development package (C) Jeffrey Wilcke Ethereum is currently in its testing phase. The current state is "Proof -of Concept 5.0 RC6". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). +of Concept 5.0 RC7". For build instructions see the [Wiki](https://github.com/ethereum/go-ethereum/wiki/Building-Ethereum(Go)). Ethereum Go is split up in several sub packages Please refer to each individual package for more information. diff --git a/ethutil/config.go b/ethutil/config.go index fd590fbdb8..abe86babe3 100644 --- a/ethutil/config.go +++ b/ethutil/config.go @@ -42,7 +42,7 @@ func ReadConfig(base string, logTypes LoggerType) *config { } } - Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC6"} + Config = &config{ExecPath: path, Debug: true, Ver: "0.5.0 RC7"} Config.Log = NewLogger(logTypes, LogLevelDebug) Config.SetClientString("/Ethereum(G)") }