quorum/block_manager.go

91 lines
2.0 KiB
Go
Raw Normal View History

2013-12-26 03:45:52 -08:00
package main
import (
2014-01-11 06:27:08 -08:00
"fmt"
"github.com/ethereum/ethutil-go"
2013-12-26 03:45:52 -08:00
)
2014-01-08 14:43:07 -08:00
type BlockChain struct {
2014-01-11 06:27:08 -08:00
lastBlock *ethutil.Block
2014-01-08 14:43:07 -08:00
2014-01-11 06:27:08 -08:00
genesisBlock *ethutil.Block
2014-01-08 14:43:07 -08:00
}
func NewBlockChain() *BlockChain {
2014-01-11 06:27:08 -08:00
bc := &BlockChain{}
bc.genesisBlock = ethutil.NewBlock(ethutil.Encode(ethutil.Genesis))
2014-01-08 14:43:07 -08:00
2014-01-11 06:27:08 -08:00
return bc
2014-01-08 14:43:07 -08:00
}
2013-12-26 03:45:52 -08:00
type BlockManager struct {
2014-01-11 06:27:08 -08:00
vm *Vm
2014-01-08 14:43:07 -08:00
2014-01-11 06:27:08 -08:00
blockChain *BlockChain
2013-12-26 03:45:52 -08:00
}
func NewBlockManager() *BlockManager {
2014-01-11 06:27:08 -08:00
bm := &BlockManager{vm: NewVm()}
2013-12-26 03:45:52 -08:00
2014-01-11 06:27:08 -08:00
return bm
2013-12-26 03:45:52 -08:00
}
// Process a block.
func (bm *BlockManager) ProcessBlock(block *ethutil.Block) error {
2014-01-11 06:27:08 -08:00
// TODO Validation (Or move to other part of the application)
if err := bm.ValidateBlock(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
lockChan := make(chan bool, txCount)
// Process each transaction/contract
for _, tx := range block.Transactions() {
// If there's no recipient, it's a contract
if tx.IsContract() {
go bm.ProcessContract(tx, block, lockChan)
} else {
// "finish" tx which isn't a contract
lockChan <- true
}
}
// Wait for all Tx to finish processing
for i := 0; i < txCount; i++ {
<-lockChan
}
return nil
2013-12-26 03:45:52 -08:00
}
func (bm *BlockManager) ValidateBlock(block *ethutil.Block) error {
2014-01-11 06:27:08 -08:00
return nil
2014-01-08 14:43:07 -08:00
}
func (bm *BlockManager) ProcessContract(tx *ethutil.Transaction, block *ethutil.Block, lockChan chan bool) {
2014-01-11 06:27:08 -08:00
// Recovering function in case the VM had any errors
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from VM execution with err =", r)
// Let the channel know where done even though it failed (so the execution may resume normally)
lockChan <- true
}
}()
// Process contract
bm.vm.ProcContract(tx, block, func(opType OpType) bool {
// TODO turn on once big ints are in place
//if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
// return false
//}
return true // Continue
})
// Broadcast we're done
lockChan <- true
2013-12-26 03:45:52 -08:00
}