You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: block.go
    path of file: ./repos/go-ibax/packages/rollback
    
    the code of the file until where you have to start completion: /*---------------------------------------------------------------------------------------------
 *  Copyright (c) IBAX. All rights reserved.
 *  See LICENSE in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
package rollback

import (
	"bytes"
	"errors"
	"fmt"
	"strconv"
	"strings"

	"github.com/IBAX-io/go-ibax/packages/block"
	"github.com/IBAX-io/go-ibax/packages/consts"
	"github.com/IBAX-io/go-ibax/packages/storage/sqldb"
	"github.com/IBAX-io/go-ibax/packages/transaction"
	log "github.com/sirupsen/logrus"
)

var (
	ErrLastBlock = errors.New("block is not the last")
)

// RollbackBlock is blocking rollback
func 
    
func rollbackBlock(dbTx *sqldb.DbTransaction, block *block.Block) error {
	// rollback transactions in reverse order
	logger := block.GetLogger()
	var transferSelfHashes = make([]string, 0)
	for i := len(block.Transactions) - 1; i >= 0; i-- {
		t := block.Transactions[i]
		t.DbTransaction = dbTx

		_, err := sqldb.MarkTransactionUnusedAndUnverified(dbTx, t.Hash())
		if err != nil {
			logger.WithFields(log.Fields{"type": consts.DBError, "error": err}).Error("starting transaction")
			return err
		}
		_, err = sqldb.DeleteLogTransactionsByHash(dbTx, t.Hash())
		if err != nil {
			logger.WithFields(log.Fields{"type": consts.DBError, "error": err}).Error("deleting log transactions by hash")
			return err
		}

		ts := &sqldb.TransactionStatus{}
		err = ts.UpdateBlockID(dbTx, 0, t.Hash())
		if err != nil {
			logger.WithFields(log.Fields{"type": consts.DBError, "error": err}).Error("updating block id in transaction status")
			return err
		}

		_, err = sqldb.DeleteQueueTxByHash(dbTx, t.Hash())
		if err != nil {
			logger.WithFields(log.Fields{"type": consts.DBError, "error": err}).Error("deleting transacion from queue by hash")
			return err
		}

		switch t.Inner.(type) {
		case *transaction.SmartTransactionParser:
			t.Inner.(*transaction.SmartTransactionParser).DbTransaction = t.DbTransaction
			if err = rollbackTransaction(t.Hash(), t.DbTransaction, logger); err != nil {
				return err
			}
			transferSelf := t.Inner.(*transaction.SmartTransactionParser).TxSmart.TransferSelf
			if transferSelf != nil {
				if strings.EqualFold("UTXO", transferSelf.Source) && strings.EqualFold("Account", transferSelf.Target) {
					transferSelfHashes = append(transferSelfHashes, fmt.Sprintf("%x", t.Hash()))
				}
			}
		}
		err = t.Inner.TxRollback()
		if err != nil {
			return err
		}
	}

	err := sqldb.RollbackOutputs(block.Header.BlockId, dbTx, transferSelfHashes, logger)
	if err != nil {
		logger.WithFields(log.Fields{"type": consts.DBError, "error": err}).Error("updating outputs by block id")
		return err
	}

	return nil
}