package main
import (
"crypto/sha256"
"encoding/hex"
"flag"
"fmt"
"time"
)
// Block represents a single block in the blockchain
type Block struct {
Index int
Timestamp string
Data string
PrevHash string
Hash string
}
// Blockchain is a slice of blocks
type Blockchain struct {
Blocks []Block
}
// calculateHash creates a SHA-256 hash of a block's contents
func calculateHash(block Block) string {
record := fmt.Sprintf("%d%s%s%s", block.Index, block.Timestamp, block.Data, block.PrevHash)
hash := sha256.Sum256([]byte(record))
return hex.EncodeToString(hash[:])
}
// generateGenesisBlock creates the first block in the chain
func generateGenesisBlock() Block {
block := Block{
Index: 0,
Timestamp: time.Now().Format(time.RFC3339),
Data: "Genesis Block",
PrevHash: "",
}
block.Hash = calculateHash(block)
return block
}
// generateBlock creates a new block from the previous one
func generateBlock(prevBlock Block, data string) Block {
newBlock := Block{
Index: prevBlock.Index + 1,
Timestamp: time.Now().Format(time.RFC3339),
Data: data,
PrevHash: prevBlock.Hash,
}
newBlock.Hash = calculateHash(newBlock)
return newBlock
}
// verifyBlockchain checks that the blockchain is valid
func verifyBlockchain(chain []Block) bool {
for i := 1; i < len(chain); i++ {
if chain[i].PrevHash != chain[i-1].Hash {
return false
}
if chain[i].Hash != calculateHash(chain[i]) {
return false
}
}
return true
}
func main() {
// CLI flags
list := flag.Bool("list", false, "List all blocks")
blockIndex := flag.Int("block", -1, "Show a block by index")
verify := flag.Bool("verify", false, "Verify the integrity of the blockchain")
flag.Parse()
// Simulate a blockchain with 3 blocks
chain := Blockchain{Blocks: []Block{generateGenesisBlock()}}
chain.Blocks = append(chain.Blocks, generateBlock(chain.Blocks[len(chain.Blocks)-1], "Alice pays Bob 5 BTC"))
chain.Blocks = append(chain.Blocks, generateBlock(chain.Blocks[len(chain.Blocks)-1], "Bob pays Carol 2 BTC"))
// CLI logic
if *list {
fmt.Println("Blockchain:")
for _, b := range chain.Blocks {
fmt.Printf("Index: %d | Data: %s | Hash: %.10s...\n", b.Index, b.Data, b.Hash)
}
} else if *blockIndex >= 0 && *blockIndex < len(chain.Blocks) {
b := chain.Blocks[*blockIndex]
fmt.Printf("Block %d\n", b.Index)
fmt.Printf("Timestamp: %s\nData: %s\nHash: %s\nPrevHash: %s\n", b.Timestamp, b.Data, b.Hash, b.PrevHash)
} else if *verify {
if verifyBlockchain(chain.Blocks) {
fmt.Println("✅ Blockchain is valid.")
} else {
fmt.Println("❌ Blockchain is INVALID.")
}
} else {
fmt.Println("Usage:")
fmt.Println(" -list List all blocks")
fmt.Println(" -block Show details of a block")
fmt.Println(" -verify Check chain integrity")
}
}
Example of usage:
$ go run explorer.go -list
Blockchain:
Index: 0 | Data: Genesis Block | Hash: 1a2b3c4d...
Index: 1 | Data: Alice pays Bob 5 BTC | Hash: 2b3c4d5e...
Index: 2 | Data: Bob pays Carol 2 BTC | Hash: 3c4d5e6f...
$ go run explorer.go -block 1
Block 1
Timestamp: 2025-04-14T17:00:00Z
Data: Alice pays Bob 5 BTC
Hash: ...
PrevHash: ...
$ go run explorer.go -verify
✅ Blockchain is valid.