From 49a513bdebd7c4402b3a7f2f169a31c34f2ca9df Mon Sep 17 00:00:00 2001 From: Bas van Kervel Date: Mon, 13 Apr 2015 10:13:52 +0200 Subject: Added blockchain DB versioning support, closes #650 --- core/block_processor.go | 6 ++++++ core/chain_manager.go | 7 +++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/block_processor.go b/core/block_processor.go index 7aded346a..d5a29b258 100644 --- a/core/block_processor.go +++ b/core/block_processor.go @@ -18,6 +18,12 @@ import ( "gopkg.in/fatih/set.v0" ) +const ( + // must be bumped when consensus algorithm is changed, this forces the upgradedb + // command to be run (forces the blocks to be imported again using the new algorithm) + BlockChainVersion = 1 +) + var statelogger = logger.NewLogger("BLOCK") type BlockProcessor struct { diff --git a/core/chain_manager.go b/core/chain_manager.go index 5ad1dda83..25ee0eeef 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -284,11 +284,14 @@ func (self *ChainManager) Export(w io.Writer) error { defer self.mu.RUnlock() glog.V(logger.Info).Infof("exporting %v blocks...\n", self.currentBlock.Header().Number) - for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) { - if err := block.EncodeRLP(w); err != nil { + last := self.currentBlock.NumberU64() + + for nr := uint64(0); nr <= last; nr++ { + if err := self.GetBlockByNumber(nr).EncodeRLP(w); err != nil { return err } } + return nil } -- cgit v1.2.3 From 3d57e377a4e95941fd3f572b42e073b40d10d27c Mon Sep 17 00:00:00 2001 From: zelig Date: Sun, 12 Apr 2015 20:25:09 +0100 Subject: blockpool stability fixes: - follow up locks and fix them - chainManager: call SetQueued for parentErr future blocks, uncomment TD checks, unskip test - make ErrIncorrectTD non-fatal to be forgiving to genuine mistaken nodes (temp) but demote them to guard against stuck best peers. - add purging to bounded nodeCache (config nodeCacheSize) - use nodeCache when creating blockpool entries and let non-best peers add blocks (performance boost) - minor error in addError - reduce idleBestPeerTimeout to 1 minute - correct status counts and unskip status passing status test - glogified logging --- core/chain_manager.go | 1 + 1 file changed, 1 insertion(+) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index 5ad1dda83..676db405e 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -470,6 +470,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { } if IsParentErr(err) && self.futureBlocks.Has(block.ParentHash()) { + block.SetQueued(true) self.futureBlocks.Push(block) stats.queued++ continue -- cgit v1.2.3 From d423305f07fe5390ca957a9f08c93b5e6a3cbef2 Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 13 Apr 2015 22:57:03 +0200 Subject: state: fixed nonce issue in managed state Rlock => Lock when creating a new nonce --- core/state/managed_state.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/state/managed_state.go b/core/state/managed_state.go index 9d2fc48e7..97d098039 100644 --- a/core/state/managed_state.go +++ b/core/state/managed_state.go @@ -52,8 +52,8 @@ func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) { // NewNonce returns the new canonical nonce for the managed account func (ms *ManagedState) NewNonce(addr common.Address) uint64 { - ms.mu.RLock() - defer ms.mu.RUnlock() + ms.mu.Lock() + defer ms.mu.Unlock() account := ms.getAccount(addr) for i, nonce := range account.nonces { -- cgit v1.2.3 From 333d4e0f278166455f9261f795aa0a8c5ce5d534 Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 14 Apr 2015 00:18:38 +0200 Subject: core: during split properly insert parent blocks During a split parent and grand parent were included in the database but not in the canonical chain (numbered chain). Added a `merge` function which finds the common ancestor of the chains and reinserts the missing blocks. --- core/chain_manager.go | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index 721c008bc..ade922217 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -490,8 +490,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { block.Td = td self.mu.Lock() - cblock := self.currentBlock { + cblock := self.currentBlock // Write block to database. Eventually we'll have to improve on this and throw away blocks that are // not in the canonical chain. self.write(block) @@ -505,6 +505,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { if glog.V(logger.Info) { glog.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, hash[:4], td, cblock.Header().Number, chash[:4], self.td) } + // during split we merge two different chains and create the new canonical chain + self.merge(cblock, block) queue[i] = ChainSplitEvent{block, logs} queueEvent.splitCount++ @@ -553,6 +555,35 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { return nil } +// merge takes two blocks, an old chain and a new chain and will reconstruct the blocks and inserts them +// to be part of the new canonical chain. +func (self *ChainManager) merge(oldBlock, newBlock *types.Block) { + glog.V(logger.Debug).Infof("Applying diff to %x & %x\n", oldBlock.Hash().Bytes()[:4], newBlock.Hash().Bytes()[:4]) + + var oldChain, newChain types.Blocks + // First find the split (common ancestor) so we can perform an adequate merge + for { + oldBlock, newBlock = self.GetBlock(oldBlock.ParentHash()), self.GetBlock(newBlock.ParentHash()) + if oldBlock.Hash() == newBlock.Hash() { + break + } + oldChain = append(oldChain, oldBlock) + newChain = append(newChain, newBlock) + } + + // insert blocks + for _, block := range newChain { + self.insert(block) + } + + if glog.V(logger.Detail) { + for i, oldBlock := range oldChain { + glog.Infof("- %.10v = %x\n", oldBlock.Number(), oldBlock.Hash()) + glog.Infof("+ %.10v = %x\n", newChain[i].Number(), newChain[i].Hash()) + } + } +} + func (self *ChainManager) update() { events := self.eventMux.Subscribe(queueEvent{}) futureTimer := time.NewTicker(5 * time.Second) -- cgit v1.2.3 From 8310bcda6100cc703f5c1e22e0122ad7476d689d Mon Sep 17 00:00:00 2001 From: obscuren Date: Tue, 14 Apr 2015 12:47:54 +0200 Subject: state: fixed mutex lockes --- core/state/managed_state.go | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/state/managed_state.go b/core/state/managed_state.go index 97d098039..9e6be9980 100644 --- a/core/state/managed_state.go +++ b/core/state/managed_state.go @@ -37,7 +37,7 @@ func (ms *ManagedState) SetState(statedb *StateDB) { // RemoveNonce removed the nonce from the managed state and all future pending nonces func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) { - if ms.HasAccount(addr) { + if ms.hasAccount(addr) { ms.mu.Lock() defer ms.mu.Unlock() @@ -67,7 +67,10 @@ func (ms *ManagedState) NewNonce(addr common.Address) uint64 { // GetNonce returns the canonical nonce for the managed or unmanged account func (ms *ManagedState) GetNonce(addr common.Address) uint64 { - if ms.HasAccount(addr) { + ms.mu.RLock() + defer ms.mu.RUnlock() + + if ms.hasAccount(addr) { account := ms.getAccount(addr) return uint64(len(account.nonces)) + account.nstart } else { @@ -77,6 +80,9 @@ func (ms *ManagedState) GetNonce(addr common.Address) uint64 { // SetNonce sets the new canonical nonce for the managed state func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) { + ms.mu.Lock() + defer ms.mu.Unlock() + so := ms.GetOrNewStateObject(addr) so.SetNonce(nonce) @@ -85,6 +91,12 @@ func (ms *ManagedState) SetNonce(addr common.Address, nonce uint64) { // HasAccount returns whether the given address is managed or not func (ms *ManagedState) HasAccount(addr common.Address) bool { + ms.mu.RLock() + defer ms.mu.RUnlock() + return ms.hasAccount(addr) +} + +func (ms *ManagedState) hasAccount(addr common.Address) bool { _, ok := ms.accounts[addr.Str()] return ok } -- cgit v1.2.3 From ccb4722a593aff7be5a2a5998534faf58a277139 Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 15 Apr 2015 11:58:45 +0200 Subject: core/types: Changed bloom lookup to take anything bytes backed --- core/types/bloom9.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'core') diff --git a/core/types/bloom9.go b/core/types/bloom9.go index 0d37cb19f..aa76a2e9d 100644 --- a/core/types/bloom9.go +++ b/core/types/bloom9.go @@ -8,6 +8,10 @@ import ( "github.com/ethereum/go-ethereum/crypto" ) +type bytesBacked interface { + Bytes() []byte +} + func CreateBloom(receipts Receipts) Bloom { bin := new(big.Int) for _, receipt := range receipts { @@ -51,9 +55,9 @@ func bloom9(b []byte) *big.Int { var Bloom9 = bloom9 -func BloomLookup(bin Bloom, topic common.Hash) bool { +func BloomLookup(bin Bloom, topic bytesBacked) bool { bloom := bin.Big() - cmp := bloom9(topic[:]) + cmp := bloom9(topic.Bytes()[:]) return bloom.And(bloom, cmp).Cmp(cmp) == 0 } -- cgit v1.2.3 From 5d2138a2b23ff410767fa7d26d4ab5777db6fcde Mon Sep 17 00:00:00 2001 From: obscuren Date: Wed, 15 Apr 2015 11:59:30 +0200 Subject: core: fixed issue for logs filter. Closes #629 Log filter `Address` field was cast to a Hash which causes it to always fail. --- core/filter.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'core') diff --git a/core/filter.go b/core/filter.go index dd15db27d..4508b35b3 100644 --- a/core/filter.go +++ b/core/filter.go @@ -153,7 +153,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool { if len(self.address) > 0 { var included bool for _, addr := range self.address { - if types.BloomLookup(block.Bloom(), addr.Hash()) { + if types.BloomLookup(block.Bloom(), addr) { included = true break } -- cgit v1.2.3 From dff39553d4e731fcfbac21fccf11974e98478176 Mon Sep 17 00:00:00 2001 From: obscuren Date: Thu, 16 Apr 2015 00:11:40 +0200 Subject: core: changed split detection to also account for number less than --- core/chain_manager.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'core') diff --git a/core/chain_manager.go b/core/chain_manager.go index ade922217..7e792864a 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -498,7 +498,8 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error { // Compare the TD of the last known block in the canonical chain to make sure it's greater. // At this point it's possible that a different chain (fork) becomes the new canonical chain. if td.Cmp(self.td) > 0 { - if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, common.Big1)) < 0 { + //if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, common.Big1)) < 0 { + if block.Number().Cmp(cblock.Number()) <= 0 { chash := cblock.Hash() hash := block.Hash() -- cgit v1.2.3