From df3366d910c2b1ddab986264bc186ca79ba65c4e Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 18 Dec 2014 11:39:24 +0100 Subject: [PATCH 1/5] Rlp shouldn't write null bytes --- ethutil/rlp.go | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/ethutil/rlp.go b/ethutil/rlp.go index 157dd4dd9..1bc1a58a7 100644 --- a/ethutil/rlp.go +++ b/ethutil/rlp.go @@ -2,7 +2,6 @@ package ethutil import ( "bytes" - "encoding/binary" "fmt" "math/big" "reflect" @@ -193,8 +192,13 @@ func Encode(object interface{}) []byte { if blen < 56 { buff.WriteByte(byte(blen) + 0xc0) } else { - buff.WriteByte(byte(intlen(int64(blen))) + 0xf7) - binary.Write(&buff, binary.BigEndian, int64(blen)) + ilen := byte(intlen(int64(blen))) + buff.WriteByte(ilen + 0xf7) + t := make([]byte, ilen) + for i := byte(0); i < ilen; i++ { + t[ilen-i-1] = byte(blen >> (i * 8)) + } + buff.Write(t) } buff.ReadFrom(&b) } From 4b2f1f76282069007f2bc6d91a90924ac29fd238 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 18 Dec 2014 11:55:46 +0100 Subject: [PATCH 2/5] idx should return -1 --- ethutil/value.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ethutil/value.go b/ethutil/value.go index 6417b0008..7d4a7d98c 100644 --- a/ethutil/value.go +++ b/ethutil/value.go @@ -397,5 +397,5 @@ func (it *ValueIterator) Value() *Value { } func (it *ValueIterator) Idx() int { - return it.idx + return it.idx - 1 } From 590aace88dce9922d40fca71e87905383a71d12b Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 18 Dec 2014 12:18:19 +0100 Subject: [PATCH 3/5] Removed ethereum as dependency --- core/block_manager.go | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/core/block_manager.go b/core/block_manager.go index f6c73bc2c..98c6d006d 100644 --- a/core/block_manager.go +++ b/core/block_manager.go @@ -58,8 +58,8 @@ type BlockManager struct { mem map[string]*big.Int // Proof of work used for validating Pow pow.PoW - // The ethereum manager interface - eth EthManager + + txpool *TxPool // The last attempted block is mainly used for debugging purposes // This does not have to be a valid block and will be set during @@ -71,13 +71,13 @@ type BlockManager struct { eventMux *event.TypeMux } -func NewBlockManager(ethereum EthManager) *BlockManager { +func NewBlockManager(txpool *TxPool, chainManager *ChainManager, eventMux *event.TypeMux) *BlockManager { sm := &BlockManager{ mem: make(map[string]*big.Int), Pow: ezp.New(), - eth: ethereum, - bc: ethereum.ChainManager(), - eventMux: ethereum.EventMux(), + bc: chainManager, + eventMux: eventMux, + txpool: txpool, } return sm @@ -240,7 +240,7 @@ func (sm *BlockManager) ProcessWithParent(block, parent *types.Block) (td *big.I chainlogger.Infof("Processed block #%d (%x...)\n", block.Number, block.Hash()[0:4]) - sm.eth.TxPool().RemoveSet(block.Transactions()) + sm.txpool.RemoveSet(block.Transactions()) return td, messages, nil } else { From 49e0267fe76cfd13eaf3e5e26caa637b93dbdd29 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 18 Dec 2014 13:12:54 +0100 Subject: [PATCH 4/5] Locks, refactor, tests * Added additional chain tests * Added proper mutex' on chain * Removed ethereum dependencies --- _data/chain1 | Bin 0 -> 175331 bytes _data/chain2 | Bin 0 -> 28118 bytes core/block_manager.go | 6 +- core/chain_manager.go | 115 +++++++++++++++++++++++++------------ core/chain_manager_test.go | 66 +++++++++++++++++++-- core/filter.go | 4 +- core/filter_test.go | 6 -- core/transaction_pool.go | 26 +++++---- core/types/block.go | 2 +- core/types/common.go | 5 ++ ethereum.go | 4 +- pow/ezp/pow.go | 2 +- 12 files changed, 169 insertions(+), 67 deletions(-) create mode 100755 _data/chain1 create mode 100755 _data/chain2 diff --git a/_data/chain1 b/_data/chain1 new file mode 100755 index 0000000000000000000000000000000000000000..ef392e001ebe06696541a637ab993565bda9d485 GIT binary patch literal 175331 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 MZa$GB3Jnea1NmrF+yDRo literal 0 HcmV?d00001 diff --git a/_data/chain2 b/_data/chain2 new file mode 100755 index 0000000000000000000000000000000000000000..48ed4d5ea9e7eb28dffea79a515762c9e457fce4 GIT binary patch literal 28118 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 literal 0 HcmV?d00001 diff --git a/core/block_manager.go b/core/block_manager.go index 98c6d006d..794c87f52 100644 --- a/core/block_manager.go +++ b/core/block_manager.go @@ -256,12 +256,12 @@ func (sm *BlockManager) CalculateTD(block *types.Block) (*big.Int, bool) { // TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty td := new(big.Int) - td = td.Add(sm.bc.TD, uncleDiff) + td = td.Add(sm.bc.Td(), uncleDiff) td = td.Add(td, block.Difficulty) // The new TD will only be accepted if the new difficulty is // is greater than the previous. - if td.Cmp(sm.bc.TD) > 0 { + if td.Cmp(sm.bc.Td()) > 0 { return td, true } @@ -279,7 +279,7 @@ func (sm *BlockManager) ValidateBlock(block, parent *types.Block) error { diff := block.Time - parent.Time if diff < 0 { - return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Time, sm.bc.CurrentBlock.Time) + return ValidationError("Block timestamp less then prev block %v (%v - %v)", diff, block.Time, sm.bc.CurrentBlock().Time) } /* XXX diff --git a/core/chain_manager.go b/core/chain_manager.go index 3e48579b9..c81552b5d 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -3,6 +3,7 @@ package core import ( "fmt" "math/big" + "sync" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethutil" @@ -50,16 +51,36 @@ type ChainManager struct { eventMux *event.TypeMux genesisBlock *types.Block // Last known total difficulty - TD *big.Int - - LastBlockNumber uint64 - - CurrentBlock *types.Block - LastBlockHash []byte + mu sync.RWMutex + td *big.Int + lastBlockNumber uint64 + currentBlock *types.Block + lastBlockHash []byte transState *state.StateDB } +func (self *ChainManager) Td() *big.Int { + self.mu.RLock() + defer self.mu.RUnlock() + + return self.td +} + +func (self *ChainManager) LastBlockNumber() uint64 { + self.mu.RLock() + defer self.mu.RUnlock() + + return self.lastBlockNumber +} + +func (self *ChainManager) CurrentBlock() *types.Block { + self.mu.RLock() + defer self.mu.RUnlock() + + return self.currentBlock +} + func NewChainManager(mux *event.TypeMux) *ChainManager { bc := &ChainManager{} bc.genesisBlock = types.NewBlockFromBytes(ethutil.Encode(Genesis)) @@ -77,7 +98,7 @@ func (self *ChainManager) SetProcessor(proc types.BlockProcessor) { } func (self *ChainManager) State() *state.StateDB { - return self.CurrentBlock.State() + return self.CurrentBlock().State() } func (self *ChainManager) TransState() *state.StateDB { @@ -91,27 +112,30 @@ func (bc *ChainManager) setLastBlock() { AddTestNetFunds(bc.genesisBlock) block := types.NewBlockFromBytes(data) - bc.CurrentBlock = block - bc.LastBlockHash = block.Hash() - bc.LastBlockNumber = block.Number.Uint64() + bc.currentBlock = block + bc.lastBlockHash = block.Hash() + bc.lastBlockNumber = block.Number.Uint64() // Set the last know difficulty (might be 0x0 as initial value, Genesis) - bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) + bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) } else { bc.Reset() } - chainlogger.Infof("Last block (#%d) %x\n", bc.LastBlockNumber, bc.CurrentBlock.Hash()) + chainlogger.Infof("Last block (#%d) %x\n", bc.lastBlockNumber, bc.currentBlock.Hash()) } // Block creation & chain handling func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { + bc.mu.RLock() + defer bc.mu.RUnlock() + var root interface{} hash := ZeroHash256 if bc.CurrentBlock != nil { - root = bc.CurrentBlock.Root() - hash = bc.LastBlockHash + root = bc.currentBlock.Root() + hash = bc.lastBlockHash } block := types.CreateBlock( @@ -122,11 +146,11 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { nil, "") - parent := bc.CurrentBlock + parent := bc.currentBlock if parent != nil { block.Difficulty = CalcDifficulty(block, parent) - block.Number = new(big.Int).Add(bc.CurrentBlock.Number, ethutil.Big1) - block.GasLimit = block.CalcGasLimit(bc.CurrentBlock) + block.Number = new(big.Int).Add(bc.currentBlock.Number, ethutil.Big1) + block.GasLimit = block.CalcGasLimit(bc.currentBlock) } @@ -134,35 +158,42 @@ func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block { } func (bc *ChainManager) Reset() { + bc.mu.Lock() + defer bc.mu.Unlock() + AddTestNetFunds(bc.genesisBlock) bc.genesisBlock.Trie().Sync() // Prepare the genesis block bc.write(bc.genesisBlock) bc.insert(bc.genesisBlock) - bc.CurrentBlock = bc.genesisBlock + bc.currentBlock = bc.genesisBlock - bc.SetTotalDifficulty(ethutil.Big("0")) + bc.setTotalDifficulty(ethutil.Big("0")) // Set the last know difficulty (might be 0x0 as initial value, Genesis) - bc.TD = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) + bc.td = ethutil.BigD(ethutil.Config.Db.LastKnownTD()) } func (self *ChainManager) Export() []byte { - chainlogger.Infoln("exporting", self.CurrentBlock.Number, "blocks") + self.mu.RLock() + defer self.mu.RUnlock() - blocks := make(types.Blocks, int(self.CurrentBlock.Number.Int64())+1) - for block := self.CurrentBlock; block != nil; block = self.GetBlock(block.PrevHash) { + chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Number) + + blocks := make([]*types.Block, int(self.currentBlock.Number.Int64())+1) + for block := self.currentBlock; block != nil; block = self.GetBlock(block.PrevHash) { blocks[block.Number.Int64()] = block } + return ethutil.Encode(blocks) } func (bc *ChainManager) insert(block *types.Block) { encodedBlock := block.RlpEncode() ethutil.Config.Db.Put([]byte("LastBlock"), encodedBlock) - bc.CurrentBlock = block - bc.LastBlockHash = block.Hash() + bc.currentBlock = block + bc.lastBlockHash = block.Hash() } func (bc *ChainManager) write(block *types.Block) { @@ -213,7 +244,10 @@ func (self *ChainManager) GetBlock(hash []byte) *types.Block { } func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { - block := self.CurrentBlock + self.mu.RLock() + defer self.mu.RUnlock() + + block := self.currentBlock for ; block != nil; block = self.GetBlock(block.PrevHash) { if block.Number.Uint64() == num { break @@ -227,9 +261,9 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { return block } -func (bc *ChainManager) SetTotalDifficulty(td *big.Int) { +func (bc *ChainManager) setTotalDifficulty(td *big.Int) { ethutil.Config.Db.Put([]byte("LTD"), td.Bytes()) - bc.TD = td + bc.td = td } func (self *ChainManager) CalcTotalDiff(block *types.Block) (*big.Int, error) { @@ -262,8 +296,8 @@ func (bc *ChainManager) BlockInfo(block *types.Block) types.BlockInfo { // Unexported method for writing extra non-essential block info to the db func (bc *ChainManager) writeBlockInfo(block *types.Block) { - bc.LastBlockNumber++ - bi := types.BlockInfo{Number: bc.LastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash, TD: bc.TD} + bc.lastBlockNumber++ + bi := types.BlockInfo{Number: bc.lastBlockNumber, Hash: block.Hash(), Parent: block.PrevHash, TD: bc.td} // For now we use the block hash with the words "info" appended as key ethutil.Config.Db.Put(append(block.Hash(), []byte("Info")...), bi.RlpEncode()) @@ -289,17 +323,22 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { return err } - self.write(block) - if td.Cmp(self.TD) > 0 { - if block.Number.Cmp(new(big.Int).Add(self.CurrentBlock.Number, ethutil.Big1)) < 0 { - chainlogger.Infof("Split detected. New head #%v (%x), was #%v (%x)\n", block.Number, block.Hash()[:4], self.CurrentBlock.Number, self.CurrentBlock.Hash()[:4]) + self.mu.Lock() + { + + self.write(block) + if td.Cmp(self.td) > 0 { + if block.Number.Cmp(new(big.Int).Add(self.currentBlock.Number, ethutil.Big1)) < 0 { + chainlogger.Infof("Split detected. New head #%v (%x), was #%v (%x)\n", block.Number, block.Hash()[:4], self.currentBlock.Number, self.currentBlock.Hash()[:4]) + } + + self.setTotalDifficulty(td) + self.insert(block) + self.transState = self.currentBlock.State().Copy() } - self.SetTotalDifficulty(td) - self.insert(block) - self.transState = self.State().Copy() - //sm.eth.TxPool().RemoveSet(block.Transactions()) } + self.mu.Unlock() self.eventMux.Post(NewBlockEvent{block}) self.eventMux.Post(messages) diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index a84e3ff3b..52be8b0ea 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -3,17 +3,75 @@ package core import ( "fmt" "path" + "runtime" "testing" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/event" + //logpkg "github.com/ethereum/go-ethereum/logger" ) -func TestChainInsertions(t *testing.T) { - c1, err := ethutil.ReadAllFile(path.Join("..", "_data", "chain1")) +//var Logger logpkg.LogSystem +//var Log = logpkg.NewLogger("TEST") + +func init() { + runtime.GOMAXPROCS(runtime.NumCPU()) + //Logger = logpkg.NewStdLogSystem(os.Stdout, log.LstdFlags, logpkg.InfoLevel) + //logpkg.AddLogSystem(Logger) + + ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH") + + db, err := ethdb.NewMemDatabase() + if err != nil { + panic("Could not create mem-db, failing") + } + ethutil.Config.Db = db +} + +func loadChain(fn string, t *testing.T) types.Blocks { + c1, err := ethutil.ReadAllFile(path.Join("..", "_data", fn)) if err != nil { fmt.Println(err) t.FailNow() } - data1, _ := ethutil.Decode([]byte(c1), 0) - fmt.Println(data1) + value := ethutil.NewValueFromBytes([]byte(c1)) + blocks := make(types.Blocks, value.Len()) + it := value.NewIterator() + for it.Next() { + blocks[it.Idx()] = types.NewBlockFromRlpValue(it.Value()) + } + + return blocks +} + +func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) { + err := chainMan.InsertChain(chain) + if err != nil { + fmt.Println(err) + t.FailNow() + } + done <- true +} + +func TestChainInsertions(t *testing.T) { + chain1 := loadChain("chain1", t) + chain2 := loadChain("chain2", t) + var eventMux event.TypeMux + chainMan := NewChainManager(&eventMux) + txPool := NewTxPool(chainMan, nil, &eventMux) + blockMan := NewBlockManager(txPool, chainMan, &eventMux) + chainMan.SetProcessor(blockMan) + + const max = 2 + done := make(chan bool, max) + + go insertChain(done, chainMan, chain1, t) + go insertChain(done, chainMan, chain2, t) + + for i := 0; i < max; i++ { + <-done + } + fmt.Println(chainMan.CurrentBlock()) } diff --git a/core/filter.go b/core/filter.go index fe3665bf3..fb992782d 100644 --- a/core/filter.go +++ b/core/filter.go @@ -78,11 +78,11 @@ func (self *Filter) SetSkip(skip int) { func (self *Filter) Find() []*state.Message { var earliestBlockNo uint64 = uint64(self.earliest) if self.earliest == -1 { - earliestBlockNo = self.eth.ChainManager().CurrentBlock.Number.Uint64() + earliestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64() } var latestBlockNo uint64 = uint64(self.latest) if self.latest == -1 { - latestBlockNo = self.eth.ChainManager().CurrentBlock.Number.Uint64() + latestBlockNo = self.eth.ChainManager().CurrentBlock().Number.Uint64() } var ( diff --git a/core/filter_test.go b/core/filter_test.go index d53b835b7..9a8bc9592 100644 --- a/core/filter_test.go +++ b/core/filter_test.go @@ -1,7 +1 @@ package core - -// import "testing" - -// func TestFilter(t *testing.T) { -// NewFilter(NewTestManager()) -// } diff --git a/core/transaction_pool.go b/core/transaction_pool.go index 7166d35e8..36b0beb28 100644 --- a/core/transaction_pool.go +++ b/core/transaction_pool.go @@ -8,6 +8,7 @@ import ( "sync" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/logger" "github.com/ethereum/go-ethereum/state" "github.com/ethereum/go-ethereum/wire" @@ -61,7 +62,6 @@ type TxProcessor interface { // pool is being drained or synced for whatever reason the transactions // will simple queue up and handled when the mutex is freed. type TxPool struct { - Ethereum EthManager // The mutex for accessing the Tx pool. mutex sync.Mutex // Queueing channel for reading and writing incoming @@ -75,14 +75,20 @@ type TxPool struct { SecondaryProcessor TxProcessor subscribers []chan TxMsg + + broadcaster types.Broadcaster + chainManager *ChainManager + eventMux *event.TypeMux } -func NewTxPool(ethereum EthManager) *TxPool { +func NewTxPool(chainManager *ChainManager, broadcaster types.Broadcaster, eventMux *event.TypeMux) *TxPool { return &TxPool{ - pool: list.New(), - queueChan: make(chan *types.Transaction, txPoolQueueSize), - quit: make(chan bool), - Ethereum: ethereum, + pool: list.New(), + queueChan: make(chan *types.Transaction, txPoolQueueSize), + quit: make(chan bool), + chainManager: chainManager, + eventMux: eventMux, + broadcaster: broadcaster, } } @@ -94,13 +100,13 @@ func (pool *TxPool) addTransaction(tx *types.Transaction) { pool.pool.PushBack(tx) // Broadcast the transaction to the rest of the peers - pool.Ethereum.Broadcast(wire.MsgTxTy, []interface{}{tx.RlpData()}) + pool.broadcaster.Broadcast(wire.MsgTxTy, []interface{}{tx.RlpData()}) } func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { // Get the last block so we can retrieve the sender and receiver from // the merkle trie - block := pool.Ethereum.ChainManager().CurrentBlock + block := pool.chainManager.CurrentBlock // Something has gone horribly wrong if this happens if block == nil { return fmt.Errorf("No last block on the block chain") @@ -116,7 +122,7 @@ func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error { } // Get the sender - sender := pool.Ethereum.ChainManager().State().GetAccount(tx.Sender()) + sender := pool.chainManager.State().GetAccount(tx.Sender()) totAmount := new(big.Int).Set(tx.Value) // Make sure there's enough in the sender's account. Having insufficient @@ -160,7 +166,7 @@ func (self *TxPool) Add(tx *types.Transaction) error { txplogger.Debugf("(t) %x => %x (%v) %x\n", tx.Sender()[:4], tmp, tx.Value, tx.Hash()) // Notify the subscribers - go self.Ethereum.EventMux().Post(TxPreEvent{tx}) + go self.eventMux.Post(TxPreEvent{tx}) return nil } diff --git a/core/types/block.go b/core/types/block.go index 0108bd586..2d889f35f 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -409,7 +409,7 @@ func (self *Block) Size() ethutil.StorageSize { // Implement RlpEncodable func (self *Block) RlpData() interface{} { - return self.Value().Val + return []interface{}{self.header(), self.transactions, self.rlpUncles()} } // Implement pow.Block diff --git a/core/types/common.go b/core/types/common.go index ba88b77e1..89cb5f498 100644 --- a/core/types/common.go +++ b/core/types/common.go @@ -4,8 +4,13 @@ import ( "math/big" "github.com/ethereum/go-ethereum/state" + "github.com/ethereum/go-ethereum/wire" ) type BlockProcessor interface { Process(*Block) (*big.Int, state.Messages, error) } + +type Broadcaster interface { + Broadcast(wire.MsgType, []interface{}) +} diff --git a/ethereum.go b/ethereum.go index e8b1a9500..5d74e28e9 100644 --- a/ethereum.go +++ b/ethereum.go @@ -128,9 +128,9 @@ func New(db ethutil.Database, clientIdentity wire.ClientIdentity, keyManager *cr } ethereum.blockPool = NewBlockPool(ethereum) - ethereum.txPool = core.NewTxPool(ethereum) ethereum.blockChain = core.NewChainManager(ethereum.EventMux()) - ethereum.blockManager = core.NewBlockManager(ethereum) + ethereum.txPool = core.NewTxPool(ethereum.blockChain, ethereum, ethereum.EventMux()) + ethereum.blockManager = core.NewBlockManager(ethereum.txPool, ethereum.blockChain, ethereum.EventMux()) ethereum.blockChain.SetProcessor(ethereum.blockManager) // Start the tx pool diff --git a/pow/ezp/pow.go b/pow/ezp/pow.go index cdf89950f..bfe3ea098 100644 --- a/pow/ezp/pow.go +++ b/pow/ezp/pow.go @@ -21,7 +21,7 @@ type EasyPow struct { } func New() *EasyPow { - return &EasyPow{} + return &EasyPow{turbo: true} } func (pow *EasyPow) GetHashrate() int64 { From 2d09e67713757e2a80eb614562c97f962af36cf7 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 18 Dec 2014 13:17:24 +0100 Subject: [PATCH 5/5] Updated to new methods --- block_pool.go | 2 +- cmd/ethereum/main.go | 2 +- cmd/mist/debugger.go | 2 +- cmd/mist/gui.go | 4 ++-- core/chain_manager.go | 7 +++++++ peer.go | 4 ++-- xeth/hexface.go | 2 +- xeth/pipe.go | 2 +- 8 files changed, 16 insertions(+), 9 deletions(-) diff --git a/block_pool.go b/block_pool.go index 803927f21..c618f6993 100644 --- a/block_pool.go +++ b/block_pool.go @@ -66,7 +66,7 @@ func (self *BlockPool) HasLatestHash() bool { self.mut.Lock() defer self.mut.Unlock() - return self.pool[string(self.eth.ChainManager().CurrentBlock.Hash())] != nil + return self.pool[string(self.eth.ChainManager().CurrentBlock().Hash())] != nil } func (self *BlockPool) HasCommonHash(hash []byte) bool { diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go index 43551fb3a..9efc8e9dc 100644 --- a/cmd/ethereum/main.go +++ b/cmd/ethereum/main.go @@ -77,7 +77,7 @@ func main() { var block *types.Block if len(DumpHash) == 0 && DumpNumber == -1 { - block = ethereum.ChainManager().CurrentBlock + block = ethereum.ChainManager().CurrentBlock() } else if len(DumpHash) > 0 { block = ethereum.ChainManager().GetBlock(ethutil.Hex2Bytes(DumpHash)) } else { diff --git a/cmd/mist/debugger.go b/cmd/mist/debugger.go index d7c584eab..a7a286e23 100644 --- a/cmd/mist/debugger.go +++ b/cmd/mist/debugger.go @@ -149,7 +149,7 @@ func (self *DebuggerWindow) Debug(valueStr, gasStr, gasPriceStr, scriptStr, data self.SetAsm(script) - block := self.lib.eth.ChainManager().CurrentBlock + block := self.lib.eth.ChainManager().CurrentBlock() env := utils.NewEnv(statedb, block, account.Address(), value) diff --git a/cmd/mist/gui.go b/cmd/mist/gui.go index fe066e994..773688ffc 100644 --- a/cmd/mist/gui.go +++ b/cmd/mist/gui.go @@ -246,7 +246,7 @@ func (gui *Gui) CreateAndSetPrivKey() (string, string, string, string) { } func (gui *Gui) setInitialChain(ancientBlocks bool) { - sBlk := gui.eth.ChainManager().LastBlockHash + sBlk := gui.eth.ChainManager().LastBlockHash() blk := gui.eth.ChainManager().GetBlock(sBlk) for ; blk != nil; blk = gui.eth.ChainManager().GetBlock(sBlk) { sBlk = blk.PrevHash @@ -468,7 +468,7 @@ func (gui *Gui) update() { case <-peerUpdateTicker.C: gui.setPeerInfo() case <-generalUpdateTicker.C: - statusText := "#" + gui.eth.ChainManager().CurrentBlock.Number.String() + statusText := "#" + gui.eth.ChainManager().CurrentBlock().Number.String() lastBlockLabel.Set("text", statusText) miningLabel.Set("text", "Mining @ "+strconv.FormatInt(gui.uiLib.miner.GetPow().GetHashrate(), 10)+"Khash") diff --git a/core/chain_manager.go b/core/chain_manager.go index c81552b5d..794ae0011 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -74,6 +74,13 @@ func (self *ChainManager) LastBlockNumber() uint64 { return self.lastBlockNumber } +func (self *ChainManager) LastBlockHash() []byte { + self.mu.RLock() + defer self.mu.RUnlock() + + return self.lastBlockHash +} + func (self *ChainManager) CurrentBlock() *types.Block { self.mu.RLock() defer self.mu.RUnlock() diff --git a/peer.go b/peer.go index 331e9de37..13f0239d4 100644 --- a/peer.go +++ b/peer.go @@ -666,8 +666,8 @@ func (self *Peer) pushStatus() { msg := wire.NewMessage(wire.MsgStatusTy, []interface{}{ uint32(ProtocolVersion), uint32(NetVersion), - self.ethereum.ChainManager().TD, - self.ethereum.ChainManager().CurrentBlock.Hash(), + self.ethereum.ChainManager().Td(), + self.ethereum.ChainManager().CurrentBlock().Hash(), self.ethereum.ChainManager().Genesis().Hash(), }) diff --git a/xeth/hexface.go b/xeth/hexface.go index c1f49453d..75ec5f43d 100644 --- a/xeth/hexface.go +++ b/xeth/hexface.go @@ -29,7 +29,7 @@ func (self *JSXEth) BlockByHash(strHash string) *JSBlock { func (self *JSXEth) BlockByNumber(num int32) *JSBlock { if num == -1 { - return NewJSBlock(self.obj.ChainManager().CurrentBlock) + return NewJSBlock(self.obj.ChainManager().CurrentBlock()) } return NewJSBlock(self.obj.ChainManager().GetBlockByNumber(uint64(num))) diff --git a/xeth/pipe.go b/xeth/pipe.go index a8d8ed999..1e4d0ec60 100644 --- a/xeth/pipe.go +++ b/xeth/pipe.go @@ -82,7 +82,7 @@ func (self *XEth) Execute(addr []byte, data []byte, value, gas, price *ethutil.V func (self *XEth) ExecuteObject(object *Object, data []byte, value, gas, price *ethutil.Value) ([]byte, error) { var ( initiator = state.NewStateObject(self.obj.KeyManager().KeyPair().Address()) - block = self.chainManager.CurrentBlock + block = self.chainManager.CurrentBlock() ) self.Vm.State = self.World().State().Copy()