plugeth/block_manager.go

76 lines
2.1 KiB
Go
Raw Normal View History

2013-12-26 11:45:52 +00:00
// Blocks, blocks will have transactions.
// Transactions/contracts are updated in goroutines
// Each contract should send a message on a channel with usage statistics
// The statics can be used for fee calculation within the block update method
// Statistics{transaction, /* integers */ normal_ops, store_load, extro_balance, crypto, steps}
// The block updater will wait for all goroutines to be finished and update the block accordingly
// in one go and should use minimal IO overhead.
// The actual block updating will happen within a goroutine as well so normal operation may continue
package main
import (
2014-01-03 12:40:25 +00:00
"fmt"
2013-12-26 11:45:52 +00:00
)
type BlockManager struct {
vm *Vm
}
func NewBlockManager() *BlockManager {
bm := &BlockManager{vm: NewVm()}
return bm
}
// Process a block.
func (bm *BlockManager) ProcessBlock(block *Block) error {
2013-12-29 00:36:59 +00:00
// Get the tx count. Used to create enough channels to 'join' the go routines
2013-12-26 11:45:52 +00:00
txCount := len(block.transactions)
2013-12-29 00:36:59 +00:00
// Locking channel. When it has been fully buffered this method will return
2013-12-26 11:45:52 +00:00
lockChan := make(chan bool, txCount)
2013-12-29 00:36:59 +00:00
// Process each transaction/contract
2013-12-26 11:45:52 +00:00
for _, tx := range block.transactions {
2014-01-03 12:40:25 +00:00
// If there's no recipient, it's a contract
if tx.recipient == "" {
go bm.ProcessContract(tx, block, lockChan)
} else {
// "finish" tx which isn't a contract
lockChan <- true
}
2013-12-26 11:45:52 +00:00
}
// Wait for all Tx to finish processing
for i := 0; i < txCount; i++ {
<- lockChan
}
return nil
}
2014-01-03 12:40:25 +00:00
func (bm *BlockManager) ProcessContract(tx *Transaction, block *Block, lockChan chan bool) {
// 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 {
2014-01-03 23:31:42 +00:00
// TODO turn on once big ints are in place
//if !block.PayFee(tx.Hash(), StepFee.Uint64()) {
// return false
//}
2013-12-26 11:45:52 +00:00
2014-01-02 23:43:49 +00:00
return true // Continue
})
2013-12-26 11:45:52 +00:00
// Broadcast we're done
lockChan <- true
}