예제 #1
0
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
}
예제 #2
0
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
}