神刀安全网

Golang, cryptocurrency… and Kate

How I have rewritten my cryptocurrency from PHP to Go in 8 months. Part 1

Golang, cryptocurrency... and Kate

“Don’t call or text me ever!!!” — got a text from my girlfriend Kate. In a few hours I realized, lots of time had been freed up and I decided to rewrite Dcoin in Go.

Introduction

4,5 years ago I had the imprudence to start writing my cryptocurrency in the least suitable language – PHP. Eventually, of course, I finished it (I’m stubborn), but it turned out to be a total kludge, and the fact that it worked was just magic. I want to warn you from the very beginning, that I’m a self-taught programmer, and my code is not quite ideal.

For those who are interested in the story about Kate, I’ve made some spoilers, and if you are not, just skip it.

8 months result: the app works on Win (64 / 32), OS X, Linux (64 / 32), FreeBSD (64 / 32) , Android , IOS

There are about 73k code lines. A few hundred lines for various OS:

  • 40k — block/ trajectory processing/generation
  • 17.5k — interface controllers
  • 15.5k — templates.
  • PostgreSQL, MySQL, SQLite are supported

If you are about to test what I’ve done, you are very welcome. There may be some bugs, so please tell me about them:

email me todarwin@dcoin.club or PM. Any advices and concerns are welcome.

So this is my story how I wrote it, what I came to know. Hope you’ll find something useful in it.

Start

A few hours later after Kate’s message the decision to rewrite Dcoin was already made. I had to find out start point. I googled how to learn Go from scratch. It took me 2-3 days to get through http://golang-book.ru/ and https://tour.golang.org/ , then I downloaded this book , I spent 2 weeks doing only examples and skipping self-study. It was challenging but interesting.

I was eager to start rewriting my PHP-source. I haven’t been studying anything new for a long time by then. I bought some medicines for my memory. I got better when used to take them, but maybe it’s just self-induced hypnotism.

I finished the last chapter. Finally, I could start the juicy part.The task was clear: rewrite a few dozen thousands of PHP code lines. But it was totally unclear what to start from. I decided to begin with the simplest thing – web-server.

Let me tell you how it’s started. I met her Online; on a dating website at the beginning of 2015. I fell in love almost immediately. She is absolutely my type. We went for a walk to a park, laughed, joked, had fun, then it became cold, we didn’t want to part. We caught a taxi and went to my place to watch some Russian cartoons, lied in the bed and laugh till we cry

Revel

I didn’t really understand what it’s for after the description. I installed it, experimented and understood that it didn’t suit. Revel is for websites.

Beego

Works on modules. There are a few nice docs . I took 2 modules – config and session.

Gorilla

mux — is a good thing but I didn’t find where to apply it.

So I chose to use go packages from the standard library net/http + html/template

It is really easy to get a server up in Go. This is an example of a file server:

package main import "net/http" func main() {  changeHeaderThenServe := func(h http.Handler) http.HandlerFunc {   return func(w http.ResponseWriter, r *http.Request) {    h.ServeHTTP(w, r)   }  }  http.Handle("/", changeHeaderThenServe(http.FileServer(http.Dir("."))))  http.ListenAndServe(":8000", nil) }   

I took out error handling to make it clearer. On the port :8000 in the root you will have the directory listing where the application runs with a possibility to download any file.

Call a controller by the passed name

So I made 170 controllers . Each controller is called via one of the 6 HandleFunc, for instance content.go . Controller’s name in HandleFunc is taken from POST or GET query like tplName := r.FormValue(“tpl_name”). Then CallController(c, tplName) is called that calls one of 170 controllers that in turn gives you ready html-code, and content.go after HTML is received writes it down through w.Write([]byte(html)) and gives it back to the browser. Something like that.

Sessions

Thanks to session module from beego, it makes it easy

 // I save sessions in memory but they can be saved in files or BD  globalSessions, _ = session.NewManager("memory", `{"cookieName":"gosessionid","gclifetime":86400}`) go globalSessions.GC() // Write to the session    sess.Set("username", 1000) sess, _ := globalSessions.SessionStart(w, r) defer sess.SessionRelease(w) // Read from the session username := sess.Get("username")

File processing

I take a file in

upload_video.go controller.

// Allocate memory for the file. 32Mb  r.ParseMultipartForm(32 << 20) // Receive the file to multipart.File  file, _, _ := r.FormFile("file") buffer := new(bytes.Buffer) // Copy to buffer   _, err = io.Copy(buffer, file) defer file.Close() // The file itself   binaryFile = buffer.Bytes() // Name of the file   fileName := r.MultipartForm.File["file"][0].Filename // Content-Type contentType := r.MultipartForm.File["file"][0].Header.Get("Content-Type")   

Server code that receives a 3gp from the client and gives an mp4 back (in case it might be useful for anyone)

Converting Base64 into an image

In crop_photo.go I receive an image in base64 and convert into a regular PNG

b64, _ := base64.StdEncoding.DecodeString(r.FormValue("b64Img")) img, _, _ := image.Decode(bytes.NewReader(b64)) out, _ := os.Create("img.png") // our image is saved in img.png png.Encode(out, img)

Bindata

When I compiled the Web server and moved to one of the nods, nothing worked. I figured out that all templates, images etc. do not go to bin on default.

I googled and found https://github.com/jteeuwen/go-bindata

The tool is very comfortable and easy to use, it generates a go-file that has templates, images etc. written through variables as a bite set. Thus after the compilation I got a bin-file. If it is required to get files from the disk, parameter “-debug=true” must be added. I use a simple bash-script not to enter the path for go-file every time.

#!/bin/bash if [ $# -gt 0 ] && [ $1 = "debug" ]  then   DEBUG="-debug=true" fi go-bindata -o="packages/static/static.go" -pkg="static" $DEBUG static/... 

Then I needed to receive files from the static directory via localhost :8089/static/img.png. go-bindata-assetfs is used for it. Here is an example of static directory:

http.Handle("/static/", http.FileServer(&assetfs.AssetFS{Asset: static.Asset, AssetDir: static.AssetDir, Prefix: ""})) 

Conclusion

In the next articles I’ll tell you about html/template, DB, smooth app shutdown through signals, block processing from blockchain, Go encryption and JS transcript, and how I changed gomobile by adding notifications and background mode for IOS and Android apps.

转载本站任何文章请注明:转载至神刀安全网,谢谢神刀安全网 » Golang, cryptocurrency… and Kate

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
分享按钮