Skip to content

Instantly share code, notes, and snippets.

@cuixin
Created February 6, 2018 05:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cuixin/0b839e3110b1303db08e0f60b305efe8 to your computer and use it in GitHub Desktop.
Save cuixin/0b839e3110b1303db08e0f60b305efe8 to your computer and use it in GitHub Desktop.
naive chain written in golang.
#!/bin/bash
curl -v "http://localhost:8080/"
curl -v --data-urlencode "value=1" "http://localhost:10888"
curl -v --data-urlencode "value=2" "http://localhost:10888"
curl -v --data-urlencode "value=3" "http://localhost:10888"
curl -v --data-urlencode "value=4" "http://localhost:10888"
curl -v --data-urlencode "value=5" "http://localhost:10888"
curl -v "http://localhost:8080/"
package main
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"io"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
)
type Block struct {
Index int
Timestamp string
Payload []byte
Hash string
PreHash string
}
func calcHash(block Block) string {
record := string(block.Index) + block.Timestamp + string(block.Payload)
h := sha256.New()
h.Write([]byte(record))
hashed := h.Sum(nil)
return hex.EncodeToString(hashed)
}
func genBlock(preBlock Block, payload []byte) (Block, error) {
var newBlock Block
t := time.Now()
newBlock.Index = preBlock.Index + 1
newBlock.Timestamp = t.String()
newBlock.Payload = payload
newBlock.PreHash = preBlock.Hash
newBlock.Hash = calcHash(newBlock)
return newBlock, nil
}
func isBlockValid(preBlock, block Block) bool {
if preBlock.Index+1 != block.Index {
return false
}
if block.PreHash != preBlock.Hash {
return false
}
if calcHash(block) != block.Hash {
return false
}
return true
}
var BlockChain []Block
func replaceChain(newBlocks []Block) {
if len(newBlocks) > len(BlockChain) {
BlockChain = newBlocks
}
}
func makeMuxRouter() http.Handler {
muxRouter := mux.NewRouter()
muxRouter.HandleFunc("/", handleGetBlockchain).Methods("GET")
muxRouter.HandleFunc("/", handleWriteBlock).Methods("POST")
return muxRouter
}
func run(port string) error {
mux := makeMuxRouter()
log.Println("Listening on ", port)
s := &http.Server{
Addr: port,
Handler: mux,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
if err := s.ListenAndServe(); err != nil {
return err
}
return nil
}
func handleGetBlockchain(w http.ResponseWriter, r *http.Request) {
bytes, err := json.MarshalIndent(BlockChain, "", " ")
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
io.WriteString(w, string(bytes))
}
func handleWriteBlock(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
payload := r.Form.Get("value")
newBlock, err := genBlock(BlockChain[len(BlockChain)-1], []byte(payload))
if err != nil {
respondWithJSON(w, r, http.StatusInternalServerError, err)
return
}
if isBlockValid(BlockChain[len(BlockChain)-1], newBlock) {
newBlockchain := append(BlockChain, newBlock)
replaceChain(newBlockchain)
}
respondWithJSON(w, r, http.StatusCreated, newBlock)
}
func respondWithJSON(w http.ResponseWriter, r *http.Request, code int, payload interface{}) {
response, err := json.MarshalIndent(payload, "", " ")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("HTTP 500: Internal Server Error"))
return
}
w.WriteHeader(code)
w.Write(response)
}
func main() {
BlockChain = append(BlockChain, Block{0, time.Now().String(), []byte{}, "", ""})
log.Fatal(run(":1080"))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment