func merkleRoot(data [][]byte) (types.Hash, error) { if len(data) == 1 { // FIXME: a workaround for trees with one element data = append(data, []byte{}) } tree := merkle.NewTree() err := tree.Generate(data, fastsha256.New()) if err != nil { return types.EmptyHash(), err } return types.NewHash(tree.Root().Hash), err }
func listener() { var msg transaction.T var blk *block.Block blockChannel := make(chan *block.Block) var transactionsPool []transaction.T var previousBlockHash types.Hash miningEmpty := false initPool: transactionsPool = make([]transaction.T, 0) loop: select { case msg = <-ch: miningEmpty = false env.DB.PutTransaction(msg) transactionsPool = append(transactionsPool, msg) if blk, _ = env.DB.GetLastBlock(); blk == nil { previousBlockHash = types.EmptyHash() } else { previousBlockHash = types.NewHash(blk.Hash()) } if bat := prepareBAT(); bat != nil { transactionsPool = append(transactionsPool, bat) } blk, err := block.NewBlock(previousBlockHash, targetBits(), transactionsPool) if err != nil { log.Printf("Error while creating a new block: %v", err) } else { miningFactoryRequests <- MiningFactoryInstantiationRequest{Block: blk, ResponseChannel: blockChannel} } case blk = <-blockChannel: miningEmpty = false if lastBlk, _ := env.DB.GetLastBlock(); lastBlk == nil { previousBlockHash = types.EmptyHash() } else { previousBlockHash = types.NewHash(blk.Hash()) } isLastBlock := bytes.Compare(blk.PreviousBlockHash[:], previousBlockHash[:]) == 0 env.DB.PutBlock(blk, isLastBlock) goto initPool default: if len(transactionsPool) == 0 && !miningEmpty { // if there are no transactions to be included into a block, try mining an empty/BAT-only block if blk, _ = env.DB.GetLastBlock(); blk == nil { previousBlockHash = types.EmptyHash() } else { previousBlockHash = types.NewHash(blk.Hash()) } if bat := prepareBAT(); bat != nil { transactionsPool = append(transactionsPool, bat) } blk, err := block.NewBlock(previousBlockHash, targetBits(), transactionsPool) if err != nil { log.Printf("Error while creating a new block: %v", err) } else { miningFactoryRequests <- MiningFactoryInstantiationRequest{Block: blk, ResponseChannel: blockChannel} miningEmpty = true } } } goto loop }