aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain
diff options
context:
space:
mode:
Diffstat (limited to 'ethchain')
-rw-r--r--ethchain/block_chain.go97
-rw-r--r--ethchain/state_manager.go4
2 files changed, 100 insertions, 1 deletions
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index 90ad4516a..6eea14652 100644
--- a/ethchain/block_chain.go
+++ b/ethchain/block_chain.go
@@ -3,6 +3,7 @@ package ethchain
import (
"bytes"
"github.com/ethereum/eth-go/ethutil"
+ "github.com/ethereum/eth-go/ethwire"
"log"
"math"
"math/big"
@@ -24,6 +25,7 @@ type BlockChain struct {
func NewBlockChain(ethereum EthManager) *BlockChain {
bc := &BlockChain{}
bc.genesisBlock = NewBlockFromData(ethutil.Encode(Genesis))
+ bc.Ethereum = ethereum
bc.setLastBlock()
@@ -77,6 +79,101 @@ func (bc *BlockChain) HasBlock(hash []byte) bool {
return len(data) != 0
}
+// TODO: At one point we might want to save a block by prevHash in the db to optimise this...
+func (bc *BlockChain) HasBlockWithPrevHash(hash []byte) bool {
+ block := bc.CurrentBlock
+
+ for ; block != nil; block = bc.GetBlock(block.PrevHash) {
+ if bytes.Compare(hash, block.PrevHash) == 0 {
+ return true
+ }
+ }
+ return false
+}
+
+func (bc *BlockChain) CalculateBlockTD(block *Block) *big.Int {
+ blockDiff := new(big.Int)
+
+ for _, uncle := range block.Uncles {
+ blockDiff = blockDiff.Add(blockDiff, uncle.Difficulty)
+ }
+ blockDiff = blockDiff.Add(blockDiff, block.Difficulty)
+
+ return blockDiff
+}
+
+// Is tasked by finding the CanonicalChain and resetting the chain if we are not the Conical one
+func (bc *BlockChain) FindCanonicalChain(msg *ethwire.Msg, commonBlockHash []byte) {
+ // 1. Calculate TD of the current chain
+ // 2. Calculate TD of the new chain
+ // Reset state to the correct one
+
+ chainDifficulty := new(big.Int)
+
+ // Calculate the entire chain until the block we both have
+ // Start with the newest block we got, all the way back to the common block we both know
+ for i := 0; i < (msg.Data.Len() - 1); i++ {
+ block := NewBlockFromRlpValue(msg.Data.Get(i))
+ if bytes.Compare(block.Hash(), commonBlockHash) == 0 {
+ log.Println("[BCHAIN] We have found the common parent block, breaking")
+ break
+ }
+ chainDifficulty.Add(chainDifficulty, bc.CalculateBlockTD(block))
+ }
+
+ log.Println("[BCHAIN] Incoming chain difficulty:", chainDifficulty)
+
+ curChainDifficulty := new(big.Int)
+ block := bc.CurrentBlock
+
+ for ; block != nil; block = bc.GetBlock(block.PrevHash) {
+ if bytes.Compare(block.Hash(), commonBlockHash) == 0 {
+ log.Println("[BCHAIN] We have found the common parent block, breaking")
+ break
+ }
+ curChainDifficulty.Add(curChainDifficulty, bc.CalculateBlockTD(block))
+ }
+
+ log.Println("[BCHAIN] Current chain difficulty:", curChainDifficulty)
+ if chainDifficulty.Cmp(curChainDifficulty) == 1 {
+ log.Println("[BCHAIN] The incoming Chain beat our asses, resetting")
+ bc.ResetTillBlockHash(commonBlockHash)
+ } else {
+ log.Println("[BCHAIN] Our chain showed the incoming chain who is boss. Ignoring.")
+ }
+}
+func (bc *BlockChain) ResetTillBlockHash(hash []byte) error {
+ lastBlock := bc.CurrentBlock
+ returnTo := bc.GetBlock(hash)
+
+ // TODO: REFACTOR TO FUNCTION, Used multiple times
+ bc.CurrentBlock = returnTo
+ bc.LastBlockHash = returnTo.Hash()
+ info := bc.BlockInfo(returnTo)
+ bc.LastBlockNumber = info.Number
+ // END TODO
+
+ bc.Ethereum.StateManager().PrepareDefault(returnTo)
+ err := ethutil.Config.Db.Delete(lastBlock.Hash())
+ if err != nil {
+ return err
+ }
+
+ var block *Block
+ for ; block != nil; block = bc.GetBlock(block.PrevHash) {
+ if bytes.Compare(block.Hash(), hash) == 0 {
+ log.Println("[CHAIN] We have arrived at the the common parent block, breaking")
+ break
+ }
+ err = ethutil.Config.Db.Delete(block.Hash())
+ if err != nil {
+ return err
+ }
+ }
+ log.Println("[CHAIN] Split chain deleted and reverted to common parent block.")
+ return nil
+}
+
func (bc *BlockChain) GenesisBlock() *Block {
return bc.genesisBlock
}
diff --git a/ethchain/state_manager.go b/ethchain/state_manager.go
index 46d8228d9..9118db211 100644
--- a/ethchain/state_manager.go
+++ b/ethchain/state_manager.go
@@ -201,7 +201,6 @@ func (sm *StateManager) ProcessBlock(block *Block, dontReact bool) error {
return nil
}
-
func (sm *StateManager) CalculateTD(block *Block) bool {
uncleDiff := new(big.Int)
for _, uncle := range block.Uncles {
@@ -215,6 +214,9 @@ func (sm *StateManager) CalculateTD(block *Block) bool {
// The new TD will only be accepted if the new difficulty is
// is greater than the previous.
+ fmt.Println("new block td:", td)
+ fmt.Println("cur block td:", sm.bc.TD)
+
if td.Cmp(sm.bc.TD) > 0 {
// Set the new total difficulty back to the block chain
sm.bc.SetTotalDifficulty(td)