diff options
author | obscuren <geffobscura@gmail.com> | 2014-05-05 21:55:43 +0800 |
---|---|---|
committer | obscuren <geffobscura@gmail.com> | 2014-05-05 21:55:43 +0800 |
commit | 2096b3a9edb3289a8f30da81704181dec7b39917 (patch) | |
tree | 1a38e845f32ecfc94a73546ec4cfdb971b740830 /ethchain/block_chain.go | |
parent | 6a86c517c4f4b372cad0ae1d92e926a482eac5ba (diff) | |
parent | fedd4c906ff9f6139cb2d88e4f1adefbf6ea81a6 (diff) | |
download | go-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.go | 137 |
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 { |