aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/block_processor.go6
-rw-r--r--core/chain_manager.go44
-rw-r--r--core/filter.go2
-rw-r--r--core/state/managed_state.go20
-rw-r--r--core/types/bloom9.go8
5 files changed, 69 insertions, 11 deletions
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..7e792864a 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
}
@@ -470,6 +473,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
@@ -486,21 +490,24 @@ 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)
// 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()
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++
@@ -549,6 +556,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)
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
}
diff --git a/core/state/managed_state.go b/core/state/managed_state.go
index 9d2fc48e7..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()
@@ -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 {
@@ -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
}
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
}