aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2014-01-12 08:51:52 +0800
committerobscuren <geffobscura@gmail.com>2014-01-12 08:51:52 +0800
commitbee05d52bfb9f555b7f9c7b625524594bff97826 (patch)
tree7a556673ea5b2c604fe9b2259ddbc08b1ae91f20
parentdfb8e65ca74e566345ca40d63b1f359d922f0b9e (diff)
downloadgo-tangerine-bee05d52bfb9f555b7f9c7b625524594bff97826.tar
go-tangerine-bee05d52bfb9f555b7f9c7b625524594bff97826.tar.gz
go-tangerine-bee05d52bfb9f555b7f9c7b625524594bff97826.tar.bz2
go-tangerine-bee05d52bfb9f555b7f9c7b625524594bff97826.tar.lz
go-tangerine-bee05d52bfb9f555b7f9c7b625524594bff97826.tar.xz
go-tangerine-bee05d52bfb9f555b7f9c7b625524594bff97826.tar.zst
go-tangerine-bee05d52bfb9f555b7f9c7b625524594bff97826.zip
Block verification, TD calculations and overall block processing
-rw-r--r--block_manager.go103
1 files changed, 98 insertions, 5 deletions
diff --git a/block_manager.go b/block_manager.go
index 968d9a139..04d45f434 100644
--- a/block_manager.go
+++ b/block_manager.go
@@ -3,40 +3,63 @@ package main
import (
"fmt"
"github.com/ethereum/ethutil-go"
+ "errors"
+ "log"
+ "math/big"
)
type BlockChain struct {
- lastBlock *ethutil.Block
+ LastBlock *ethutil.Block
genesisBlock *ethutil.Block
+
+ TD *big.Int
}
func NewBlockChain() *BlockChain {
bc := &BlockChain{}
bc.genesisBlock = ethutil.NewBlock(ethutil.Encode(ethutil.Genesis))
+ // Set the last know difficulty (might be 0x0 as initial value, Genesis)
+ bc.TD = new(big.Int)
+ bc.TD.SetBytes(ethutil.Config.Db.LastKnownTD())
+
return bc
}
+func (bc *BlockChain) HasBlock(hash string) bool {
+ return bc.LastBlock.State().Get(hash) != ""
+}
+
type BlockManager struct {
+ // Ethereum virtual machine for processing contracts
vm *Vm
-
- blockChain *BlockChain
+ // The block chain :)
+ bc *BlockChain
}
func NewBlockManager() *BlockManager {
- bm := &BlockManager{vm: NewVm()}
+ bm := &BlockManager{
+ vm: NewVm(),
+ bc: NewBlockChain(),
+ }
return bm
}
// Process a block.
func (bm *BlockManager) ProcessBlock(block *ethutil.Block) error {
- // TODO Validation (Or move to other part of the application)
+ // Block validation
if err := bm.ValidateBlock(block); err != nil {
return err
}
+ // I'm not sure, but I don't know if there should be thrown
+ // any errors at this time.
+ if err := bm.AccumelateRewards(block); err != nil {
+ return err
+ }
+
// Get the tx count. Used to create enough channels to 'join' the go routines
txCount := len(block.Transactions())
// Locking channel. When it has been fully buffered this method will return
@@ -58,10 +81,80 @@ func (bm *BlockManager) ProcessBlock(block *ethutil.Block) error {
<-lockChan
}
+ if bm.CalculateTD(block) {
+ ethutil.Config.Db.Put(block.Hash(), block.MarshalRlp())
+ bm.bc.LastBlock = block
+ }
+
return nil
}
+func (bm *BlockManager) CalculateTD(block *ethutil.Block) bool {
+ uncleDiff := new(big.Int)
+ for _, uncle := range block.Uncles {
+ uncleDiff = uncleDiff.Add(uncleDiff, uncle.Difficulty)
+ }
+
+ // TD(genesis_block) = 0 and TD(B) = TD(B.parent) + sum(u.difficulty for u in B.uncles) + B.difficulty
+ td := new(big.Int)
+ td = td.Add(bm.bc.TD, uncleDiff)
+ td = td.Add(td, block.Difficulty)
+
+ // The new TD will only be accepted if the new difficulty is
+ // is greater than the previous.
+ if td.Cmp(bm.bc.TD) > 0 {
+ bm.bc.LastBlock = block
+ // Set the new total difficulty back to the block chain
+ bm.bc.TD = td
+
+ return true
+ }
+
+ return false
+}
+
+// Validates the current block. Returns an error if the block was invalid,
+// an uncle or anything that isn't on the current block chain
func (bm *BlockManager) ValidateBlock(block *ethutil.Block) error {
+ // TODO
+ // 1. Check if the nonce of the block is valid
+ // 2. Check if the difficulty is correct
+
+ // Check if we have the parent hash, if it isn't known we discard it
+ // Reasons might be catching up or simply an invalid block
+ if bm.bc.HasBlock(block.PrevHash) {
+ // Check each uncle's previous hash. In order for it to be valid
+ // is if it has the same block hash as the current
+ for _, uncle := range block.Uncles {
+ if uncle.PrevHash != block.PrevHash {
+ if Debug {
+ log.Printf("Uncle prvhash mismatch %x %x\n", block.PrevHash, uncle.PrevHash)
+ }
+
+ return errors.New("Mismatching Prvhash from uncle")
+ }
+ }
+ } else {
+ return errors.New("Block's parent unknown")
+ }
+
+
+ return nil
+}
+
+func (bm *BlockManager) AccumelateRewards(block *ethutil.Block) error {
+ // Get the coinbase rlp data
+ d := block.State().Get(block.Coinbase)
+
+ ether := ethutil.NewEtherFromData([]byte(d))
+
+ // Reward amount of ether to the coinbase address
+ ether.AddFee(ethutil.CalculateBlockReward(block, len(block.Uncles)))
+ block.State().Update(block.Coinbase, string(ether.MarshalRlp()))
+
+ // TODO Reward each uncle
+
+
return nil
}