Implement a Golang program that simulates a basic blockchain with functionality for adding blocks containing transaction data, validating the chain integrity, and displaying the current state of the chain. The program should use a simple proof-of-work consensus algorithm and store the blockchain data in a SQLite database.
PLAINFORMAT
package main

import (
	"crypto/sha256"
	"database/sql"
	"encoding/hex"
	"fmt"
	"log"
	"math/rand"
	"os"
	"strconv"
	"time"

	_ "github.com/mattn/go-sqlite3"
)

type Block struct {
	Index        int
	Timestamp    string
	Data         string
	PreviousHash string
	Hash         string
}

func calculateHash(block Block) string {
	record := strconv.Itoa(block.Index) + block.Timestamp + block.Data + block.PreviousHash
	h := sha256.New()
	h.Write([]byte(record))
	hashed := h.Sum(nil)
	return hex.EncodeToString(hashed)
}

func createBlock(prevBlock Block, data string) Block {
	var newBlock Block
	newBlock.Index = prevBlock.Index + 1
	newBlock.Timestamp = time.Now().String()
	newBlock.Data = data
	newBlock.PreviousHash = prevBlock.Hash
	newBlock.Hash = calculateHash(newBlock)

	return newBlock
}

func isChainValid(chain []Block) bool {
	for i := 1; i < len(chain); i++ {
		currentBlock := chain[i]
		prevBlock := chain[i-1]

		if currentBlock.Hash != calculateHash(currentBlock) {
			return false
		}

		if currentBlock.PreviousHash != prevBlock.Hash {
			return false
		}
	}

	return true
}

func printChain(chain []Block) {
	for _, block := range chain {
		fmt.Printf("Index: %d\n", block.Index)
		fmt.Printf("Timestamp: %s\n", block.Timestamp)
		fmt.Printf("Data: %s\n", block.Data)
		fmt.Printf("Previous Hash: %s\n", block.PreviousHash)
		fmt.Printf("Hash: %s\n\n", block.Hash)
	}
}

func main() {
	db, err := sql.Open("sqlite3", "./blockchain.db")
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	sqlStmt := `
	CREATE TABLE IF NOT EXISTS blockchain (index INTEGER PRIMARY KEY, timestamp TEXT, data TEXT, previous_hash TEXT, hash TEXT);
	`
	_, err = db.Exec(sqlStmt)
	if err != nil {
		log.Fatalf("%q: %s\n", err, sqlStmt)
		os.Exit(1)
	}

	genesisBlock := Block{0, time.Now().String(), "Genesis Block", "", ""}
	genesisBlock.Hash = calculateHash(genesisBlock)

	tx1 := "Alice sends 10 coins to Bob"
	tx2 := "Bob sends 5 coins to Charlie"

	block1 := createBlock(genesisBlock, tx1)
	block2 := createBlock(block1, tx2)

	blockchain := []Block{genesisBlock, block1, block2}

	for _, block := range blockchain {
		_, err = db.Exec("INSERT INTO blockchain (index, timestamp, data, previous_hash, hash) VALUES (?, ?, ?, ?, ?)", block.Index, block.Timestamp, block.Data, block.PreviousHash, block.Hash)
		if err != nil {
			log.Fatal(err)
		}
	}

	rows, err := db.Query("SELECT index, timestamp, data, previous_hash, hash FROM blockchain")
	if err != nil {
		log.Fatal(err)
	}
	defer rows.Close()

	var chainFromDB []Block
	for rows.Next() {
		var b Block
		err = rows.Scan(&b.Index, &b.Timestamp, &b.Data, &b.PreviousHash, &b.Hash)
		if err != nil {
			log.Fatal(err)
		}
		chainFromDB = append(chainFromDB, b)
	}

	printChain(chainFromDB)

	fmt.Println("Is the chain valid?", isChainValid(chainFromDB))
}