aboutsummaryrefslogtreecommitdiffstats
path: root/ethchain/block_chain.go
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-05-05 21:55:43 +0800
committerobscuren <geffobscura@gmail.com>2014-05-05 21:55:43 +0800
commit2096b3a9edb3289a8f30da81704181dec7b39917 (patch)
tree1a38e845f32ecfc94a73546ec4cfdb971b740830 /ethchain/block_chain.go
parent6a86c517c4f4b372cad0ae1d92e926a482eac5ba (diff)
parentfedd4c906ff9f6139cb2d88e4f1adefbf6ea81a6 (diff)
downloadgo-tangerine-2096b3a9edb3289a8f30da81704181dec7b39917.tar
go-tangerine-2096b3a9edb3289a8f30da81704181dec7b39917.tar.gz
go-tangerine-2096b3a9edb3289a8f30da81704181dec7b39917.tar.bz2
go-tangerine-2096b3a9edb3289a8f30da81704181dec7b39917.tar.lz
go-tangerine-2096b3a9edb3289a8f30da81704181dec7b39917.tar.xz
go-tangerine-2096b3a9edb3289a8f30da81704181dec7b39917.tar.zst
go-tangerine-2096b3a9edb3289a8f30da81704181dec7b39917.zip
Merge branch 'release/poc5-rc1'
Diffstat (limited to 'ethchain/block_chain.go')
-rw-r--r--ethchain/block_chain.go137
1 files changed, 131 insertions, 6 deletions
diff --git a/ethchain/block_chain.go b/ethchain/block_chain.go
index 2865e0a21..2be4cd92b 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"
@@ -23,7 +24,8 @@ type BlockChain struct {
func NewBlockChain(ethereum EthManager) *BlockChain {
bc := &BlockChain{}
- bc.genesisBlock = NewBlockFromData(ethutil.Encode(Genesis))
+ bc.genesisBlock = NewBlockFromBytes(ethutil.Encode(Genesis))
+ bc.Ethereum = ethereum
bc.setLastBlock()
@@ -78,6 +80,128 @@ 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
+}
+func (bc *BlockChain) FindCanonicalChainFromMsg(msg *ethwire.Msg, commonBlockHash []byte) bool {
+ var blocks []*Block
+ for i := 0; i < (msg.Data.Len() - 1); i++ {
+ block := NewBlockFromRlpValue(msg.Data.Get(i))
+ blocks = append(blocks, block)
+ }
+ return bc.FindCanonicalChain(blocks, commonBlockHash)
+}
+
+// Is tasked by finding the CanonicalChain and resetting the chain if we are not the Conical one
+// Return true if we are the using the canonical chain false if not
+func (bc *BlockChain) FindCanonicalChain(blocks []*Block, commonBlockHash []byte) bool {
+ // 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 _, block := range blocks {
+ if bytes.Compare(block.Hash(), commonBlockHash) == 0 {
+ log.Println("[CHAIN] We have found the common parent block, breaking")
+ break
+ }
+ log.Println("Checking incoming blocks:")
+ chainDifficulty.Add(chainDifficulty, bc.CalculateBlockTD(block))
+ }
+
+ log.Println("[CHAIN] Incoming chain difficulty:", chainDifficulty)
+
+ curChainDifficulty := new(big.Int)
+ block := bc.CurrentBlock
+ for i := 0; block != nil; block = bc.GetBlock(block.PrevHash) {
+ i++
+ if bytes.Compare(block.Hash(), commonBlockHash) == 0 {
+ log.Println("[CHAIN] We have found the common parent block, breaking")
+ break
+ }
+ anOtherBlock := bc.GetBlock(block.PrevHash)
+ if anOtherBlock == nil {
+ // We do not want to count the genesis block for difficulty since that's not being sent
+ log.Println("[CHAIN] At genesis block, breaking")
+ break
+ }
+ curChainDifficulty.Add(curChainDifficulty, bc.CalculateBlockTD(block))
+ }
+
+ log.Println("[CHAIN] Current chain difficulty:", curChainDifficulty)
+ if chainDifficulty.Cmp(curChainDifficulty) == 1 {
+ log.Printf("[CHAIN] The incoming Chain beat our asses, resetting to block: %x", commonBlockHash)
+ bc.ResetTillBlockHash(commonBlockHash)
+ return false
+ } else {
+ log.Println("[CHAIN] Our chain showed the incoming chain who is boss. Ignoring.")
+ return true
+ }
+}
+func (bc *BlockChain) ResetTillBlockHash(hash []byte) error {
+ lastBlock := bc.CurrentBlock
+ var returnTo *Block
+ // Reset to Genesis if that's all the origin there is.
+ if bytes.Compare(hash, bc.genesisBlock.Hash()) == 0 {
+ returnTo = bc.genesisBlock
+ bc.CurrentBlock = bc.genesisBlock
+ bc.LastBlockHash = bc.genesisBlock.Hash()
+ bc.LastBlockNumber = 1
+ } else {
+ // TODO: Somehow this doesn't really give the right numbers, double check.
+ // TODO: Change logs into debug lines
+ returnTo = bc.GetBlock(hash)
+ bc.CurrentBlock = returnTo
+ bc.LastBlockHash = returnTo.Hash()
+ info := bc.BlockInfo(returnTo)
+ bc.LastBlockNumber = info.Number
+ }
+
+ // XXX Why are we resetting? This is the block chain, it has nothing to do with states
+ //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
}
@@ -136,12 +260,13 @@ func AddTestNetFunds(block *Block) {
"e6716f9544a56c530d868e4bfbacb172315bdead", // Jeffrey
"1e12515ce3e0f817a4ddef9ca55788a1d66bd2df", // Vit
"1a26338f0d905e295fccb71fa9ea849ffa12aaf4", // Alex
+ "2ef47100e0787b915105fd5e3f4ff6752079d5cb", // Maran
} {
//log.Println("2^200 Wei to", addr)
codedAddr := ethutil.FromHex(addr)
- addr := block.state.GetAccount(codedAddr)
- addr.Amount = ethutil.BigPow(2, 200)
- block.state.UpdateAccount(codedAddr, addr)
+ account := block.state.GetAccount(codedAddr)
+ account.Amount = ethutil.BigPow(2, 200)
+ block.state.UpdateStateObject(account)
}
}
@@ -180,8 +305,8 @@ func (bc *BlockChain) SetTotalDifficulty(td *big.Int) {
// Add a block to the chain and record addition information
func (bc *BlockChain) Add(block *Block) {
bc.writeBlockInfo(block)
-
// Prepare the genesis block
+
bc.CurrentBlock = block
bc.LastBlockHash = block.Hash()
@@ -196,7 +321,7 @@ func (bc *BlockChain) GetBlock(hash []byte) *Block {
return nil
}
- return NewBlockFromData(data)
+ return NewBlockFromBytes(data)
}
func (bc *BlockChain) BlockInfoByHash(hash []byte) BlockInfo {