Kako izraditi blockchain od ogrebotina s Goom

Uvod

S obzirom na to da Web 3.0 i blockchain postaju svakodnevniji, znate li što je blockchain? Znate li njegove tehničke prednosti i slučajeve upotrebe?

Cilj ovog vodiča je predstaviti blockchain tehnologiju iz tehničke perspektive gradeći je od nule.

Zaboravite sve što ste o blockchainu čuli s društvenih mreža. Sada ćete izgraditi blockchain sustav od nule da biste stvarno razumjeli sitnice i komentare ove peer-to-peer, distribuirane tehnologije.

Poslije se odlučite za njegovu budućnost i prednosti. Upozorenje o spojleru: zaljubit ćete se u programiranje blockchain softvera.

Kako?

Slijedit ćete priču o programeru koji želi revolucionirati svoj lokalni bar primjenjujući blockchain tehnologiju za svoj sustav plaćanja.

Iako blockchain ima nekoliko neporecivih slučajeva korištenja, trenutno su broj jedan aplikacije plaćanja. To je zato što banke još uvijek rade na neučinkovitoj, 40 godina staroj infrastrukturi koju pokreću CSV datoteke i FTP.

Priča dolazi s puno zabavnih i intrigantnih činjenica o cjelokupnom blockchain ekosustavu i različitim protokolima poput Bitcoina, Ethereuma i XRP-a.

Što ćete graditi, učiti i raditi u ovom vodiču?

  • Postavit ćete Go projekt na svom lokalnom računalu bez prethodnog iskustva s GoLangom
  • Generirat ćete i distribuirati svoje prve blockchain tokene
  • U Go-u ćete od početka razviti CLI kontroliranu bazu podataka
  • Saznat ćete koliko malo prava korisnici imaju na svoje omiljene aplikacije
  • Otkrit ćete prijedlog glavne vrijednosti blockchaina
  • Učinit ćete svoj DB nepromjenjivim pomoću sigurne kriptografske hash funkcije

Pa krenimo i uskočimo u našu priču.

⭐ Upoznajte glavnog junaka Andreja.

Andrej je noću vlasnik bara, a danju programer softvera u malom slovačkom gradu Bardejovu.

Andreju je dosta:

  • Programiranje solidnih, staromodnih PHP / Java / Javascript aplikacija
  • Zaboravljajući koliko mu novca duguju prijatelji i klijenti za sve neplaćene votke u petak navečer
  • Trošenje vremena na prikupljanje i brojanje kovanica, vraćanje kusura i općenito dodirivanje bankovnih računa izloženih COVID-19
  • Održavanje različitih plastičnih žetona za stolni nogomet, pikado, bilijar i poker

Andrej bi volio:

  • Imati savršenu povijest provjere djelatnosti i prodaje bara kako bi njegov bar bio u skladu s poreznim propisima
  • Pretvorite njegovu traku u autonomno, isplativo učinkovito, decentralizirano i sigurno okruženje kojem njegovi kupci mogu vjerovati i iz kojeg mogu profitirati

Cilj mu je napisati jednostavan program i zadržati sve bilance svojih klijenata u virtualnom obliku.

Andrej ovdje iznosi svoja razmišljanja:

"Svaki novi kupac dat će mi gotovinu, a ja ću im dodijeliti ekvivalentnu količinu svojih digitalnih tokena (kovanice / kriptovalute). Tokeni će predstavljati novčanu jedinicu unutar i izvan šanka.

Korisnici će koristiti tokene za sve funkcije bara, od plaćanja pića, posudbe i posudbe prijateljima te igranja stolnog tenisa, pokera i kicker-a.

Imati traku koju pokreću blockchain tokeni generirat će tone vrijednosti za moje kupce. Suprotno mojoj konkurenciji i ostalim barovima u ovoj ulici, gdje kupci troše samo novac i dobivaju mamurluk u zamjenu, kupci mojih barova koji imaju tokene bara imat će prava dioničara.

Slično posjedovanju velikog dijela dionica u tvrtki poput Applea ili Microsofta, kupci koji drže ove žetone moći će odlučiti kako će lokal raditi, glasanjem i odlučivanjem:

  • cijene pića
  • Radno vrijeme
  • nove značajke (TV, Jukebox ...)
  • dizajn interijera i eksterijera
  • raspodjela dobiti
  • itd.

Oh, ovo će biti programski san!

Nazvat ću tokene: The Blockchain Bar tokeni, TBB! "

Sad kad je Andrej podijelio svoj san, započet ćemo.

Sadržaj

  • Zahtjevi
  • Postavite projekt
  • 01 | Baza podataka MVP-a
  • 02 | Mutiranje globalnog stanja DB-a
  • 03 | Monolitni događaj vs transakcija
  • 04 | Ljudi su pohlepni
  • 05 | Zašto nam treba Blockchain
  • 06 | L'Hash de Nepromjenjiv
  • Sljedeći koraci

Zahtjevi

Zaronimo u naš vodič. Preporučujem 2+ godine programskog iskustva na Javi / PHP / Javascriptu ili nekom drugom jeziku sličnom Go-u.

Ako se želite dobro upoznati, evo besplatnog tečaja koji će vas pokrenuti.

Također možete završiti službenih 17 predavanja A Tour Of Go kako biste se upoznali sa sintaksom jezika i osnovnim konceptima (~ 20 minuta).

Zašto ići?

Jer poput blockchaina, to je fantastična tehnologija za vašu cjelokupnu programsku karijeru. Go je moderan jezik, a razvojni programeri Go bolje su plaćeni od prosječnih Java / PHP / Javascript pozicija.

Go je optimiziran za višejezgrenu CPU arhitekturu. Možete stvoriti tisuće laganih niti (Go-rutine) bez problema. Izuzetno je praktičan za paralelni i istodobni softver poput blockchain mreža.

Pisanjem softvera u programu Go postižete gotovo C ++ razinu performansi, a da se pritom ne ubijete jer ste jednom zaboravili osloboditi memoriju.

Go također kompajlira u binarnu datoteku što ga čini vrlo prenosivim.

Postavite projekt

Ovaj članak ima posebno spremište Github otvorenog koda s punim izvornim kodom, tako da možete kompajlirati kôd i pokrenuti program na vlastitom lokalnom računalu.

Ako zapnete u bilo kojem poglavlju ili određenom retku koda, stvorite Github Issue u ovom spremištu koji opisuje vaš problem i ja ću vam pomoći što prije!

↓ Posjetite spremište Github i slijedite upute za instalaciju ↓

web3coach / the-blockchain-bar-newsletter-edition Izvorni kod za prvih 7 poglavlja: e-knjige "Blockchain Way of Programming". - web3coach / the-blockchain-bar-bilten-izdanje web3coach GitHub

01 | Baza podataka MVP-a

git checkout c1_genesis_json

Andrej je svladao relacijske SQL baze podataka 90-ih. Zna kako izraditi napredne podatkovne modele i kako optimizirati SQL upite.

Vrijeme je da Andrej uhvati korak s inovacijama i počne graditi softver Web 3.0.

Srećom, nakon što je prošli tjedan pročitao knjigu "The Lean Startup", Andrej osjeća kao da još uvijek ne bi trebao previše dizajnirati rješenje. Stoga odabire jednostavnu, ali učinkovitu JSON datoteku za MVP bazu.

U početku je postojala primitivna centralizirana baza podataka.

? Sažetak

Blockchain je baza podataka.

Korisnik 1, Andrej

Ponedjeljak, 18. ožujka.

Andrej generira 1M uslužnih tokena.

U svijetu blockchaina, tokeni su jedinice unutar blockchain baze podataka. Njihova stvarna vrijednost u dolarima ili eurima oscilira ovisno o potražnji i popularnosti.

Svaki blockchain ima datoteku "Genesis" . Datoteka Genesis koristi se za distribuciju prvih tokena ranim sudionicima blockchaina.

Sve započinje jednostavnim, glupim genesis.json .

Andrej stvara datoteku u ./database/genesis.jsonkojoj definira da će baza podataka The Blockchain Bar imati 1M žetona i svi će pripadati Andreju:

{ "genesis_time": "2019-03-18T00:00:00.000000000Z", "chain_id": "the-blockchain-bar-ledger", "balances": { "andrej": 1000000 } } 

Žetoni moraju imati stvarnu "uslužnu uslugu", to je slučaj upotrebe. Korisnici bi trebali moći plaćati s njima od 1. dana!

Andrej se mora pridržavati zakonskih regulatora (DIP). Nezakonito je izdavanje neregistrirane vrijednosnice. S druge strane, uslužni tokeni su u redu, pa odmah ispisuje i na vrata bara lijepi novi bijeli p̶a̶p̶e̶r̶ poster s cijenom.

Andrej svojim tokenima dodjeljuje početnu novčanu vrijednost kako bi ih mogao zamijeniti za euro, dolare ili drugu fiat valutu.

1 TBB token = 1€ | Item | Price | | ------------------------- | ------- | | Vodka shot | 1 TBB | | Orange juice | 5 TBB | | Burger | 2 TBB | | Crystal Head Vodka Bottle | 950 TBB | 

Andrej također odlučuje da bi trebao dobiti 100 žetona dnevno za održavanje baze podataka i tako sjajnu ometajuću ideju.

?Zabavne činjenice

Prvi genesis Ether (ETH) na Ethereum blockchainu stvoren je i distribuiran ranim investitorima i programerima na isti način kao i Andrejev komunalni token. 2017. godine, tijekom procvata ICO-a (početne ponude novčića) na Ethereum blockchain mreži, osnivači projekta su napisali i je investitorima predstavio tehničke dokumente. Priručnik je tehnički dokument koji opisuje složeno pitanje i moguće rješenje namijenjen obrazovanju i rasvjetljavanju određenog pitanja. U svijetu blockchains, bijeli papir služi ocrtati specifikacije kako se to posebno blockchain će izgledati i ponašati kada je developed.Blockchain projekte podignuta između 10 milijuna eura za € 300 po Whitepaperidea.u zamjenu za novac (ICO "financiranje") imena ulagača bila bi uključena u početne "bilance geneze", slično onome kako je to učinio Andrej. Nade investitora putem ICO-a postaju da vrijednosti geneza novčića rastu i da timovi isporučuju istaknuti blockchain. Prirodno, ne dolaze sve ideje o bijeloj knjizi. Ogromna ulaganja izgubljena zbog nejasnih ili nepotpunih ideja razlog su zašto je blockchain dobio negativnu medijsku pokrivenost tijekom ovih ICO-a i zašto su ga neki još uvijek smatrali hypeom. Ali temeljna tehnologija blockchaina fantastična je i korisna, kao što ćete dalje naučiti u ovoj knjizi. Samo su je zlostavljali neki loši glumci.

? Sažetak

Blockchain je baza podataka.

Opskrba tokenima, početna stanja korisnika i postavke globalnog blockchaina koje definirate u datoteci Genesis.

02 | Mutiranje globalnog stanja DB-a

git checkout c2_db_changes_txt

Mrtva stranka

Ponedjeljak, 25. ožujka.

Nakon tjedan dana rada, lokali su spremni za prihvat žetona. Nažalost, nitko se ne pojavljuje, pa Andrej naručio tri injekcije votke za sebe i zapisao promjene na bazi podataka na papir:

andrej-3; // 3 shots of vodka andrej+3; // technically purchasing from his own bar andrej+700; // Reward for a week of work (7x100 per day) 

Da bi izbjegao ponovni izračun najnovijeg stanja salda svakog kupca, Andrej stvara ./database/state.jsondatoteku koja sprema stanja u agregiranom formatu.

Novo stanje DB-a:

{ "balances": { "andrej": 1000700 } } 

Bonus za BabaYagu

Utorak, 26. ožujka.

Da bi doveo promet u svoj bar, Andrej najavljuje ekskluzivni 100% bonus za sve koji u sljedeća 24 sata kupe TBB tokene.

Bing! Dobija svog prvog kupca koji se zove BabaYaga . BabaYaga unaprijed kupuje tokene u vrijednosti od 1000 eura, a kako bi proslavila, odmah potroši 1 TBB na čašu votke. Ima problema s pićem.

DB transakcije napisane na papiru:

andrej-2000; // transfer to BabaYaga babayaga+2000; // pre-purchase with 100% bonus babayaga-1; andrej+1; andrej+100; // 1 day of sun coming up 

Novo stanje DB-a:

{ "balances": { "andrej": 998801, "babayaga": 1999 } } 

?Zabavne činjenice

Blockchain ICO projekti (početne ponude novčića temeljene na bijelim papirima) često distribuiraju genesis tokene s različitim bonusima, ovisno o tome koliko ih kupite i koliko rano to učinite. Timovi nude u prosjeku 10-40% bonusa ranim "sudionicima". Riječ "investitor" izbjegava se, pa zakonski regulatori tokene neće smatrati vrijednosnim papirima. Projekti bi smatrali da njihov glavni proizvod, blockchain tokeni, funkcioniraju kao "leteći bodovi lojalnosti." "Sudionici" su kasnije zaradili čak 1000% od svoje investicije prodajom javnosti putem razmjene nekoliko mjeseci kasnije.

?Sažetak

Blockchain je baza podataka.

Opskrba tokenima, početna stanja korisnika i postavke globalnog blockchaina koje definirate u datoteci Genesis.

Genesis bilance ukazuju na izvorno stanje blockchaina i nikad se kasnije ne ažuriraju.

The database state changes are called Transactions (TX).

03 | Monolithic Event vs Transaction

git checkout c3_state_blockchain_component

Developers used to event-sourcing architecture must have immediately recognized the familiar principles behind transactions. They are correct.

Blockchain transactions represent a series of events, and the database is a final aggregated, calculated state after replaying all the transactions in a specific sequence.

Andrej Programming

Tuesday evening, March 26.

It's a relaxing Tuesday evening for Andrej. Celebrating his first client, he decides to play some Starcraft and clean up his local development machine by removing some old pictures.

Unfortunately, he prematurely pressed enter when typing a removal command path in terminal sudo rm -rf /. Oops.

All his files, including the bar's genesis.json and state.json are gone.

Andrej, being a senior developer, repeatedly shouted some f* words very loudly for a few seconds, but he didn't panic!

While he didn't have a backup, he had something better — a piece of paper with all the database transactions. The only thing he needs to do is replay all the transactions one by one, and his database state will get recovered.

Impressed by the advantages of event-based architecture, he decides to extend his MVP database solution. Every bar's activity, such as individual drink purchases, MUST be recorded inside the blockchain database.

Each customer will be represented in DB using an Account Struct:

type Account string 

Each Transaction (TX - a database change) will have the following four attributes: from, to, value and data.

The data attribute with one possible value (reward) captures Andrej's bonus for inventing the blockchain and increases the initial TBB tokens total supply artificially (inflation).

type Tx struct { From Account `json:"from"` To Account `json:"to"` Value uint `json:"value"` Data string `json:"data"` } func (t Tx) IsReward() bool { return t.Data == "reward" } 

The Genesis DB will remain a JSON file:

{ "genesis_time": "2019-03-18T00:00:00.000000000Z", "chain_id": "the-blockchain-bar-ledger", "balances": { "andrej": 1000000 } } 

All the transactions, previously written on a piece of paper, will be stored in a local text-file database called tx.db, serialized in JSON format and separated by line-break character:

{"from":"andrej","to":"andrej","value":3,"data":""} {"from":"andrej","to":"andrej","value":700,"data":"reward"} {"from":"andrej","to":"babayaga","value":2000,"data":""} {"from":"andrej","to":"andrej","value":100,"data":"reward"} {"from":"babayaga","to":"andrej","value":1,"data":""} 

The most crucial database component encapsulating all the business logic will be State:

type State struct { Balances map[Account]uint txMempool []Tx dbFile *os.File } 

The State struct will know about all user balances and who transferred TBB tokens to whom, and how many were transferred.

It's constructed by reading the initial user balances from genesis.json file:

func NewStateFromDisk() (*State, error) { // get current working directory cwd, err := os.Getwd() if err != nil { return nil, err } genFilePath := filepath.Join(cwd, "database", "genesis.json") gen, err := loadGenesis(genFilePath) if err != nil { return nil, err } balances := make(map[Account]uint) for account, balance := range gen.Balances { balances[account] = balance } 

Afterwards, the genesis State balances are updated by sequentially replaying all the database events from tx.db:

 txDbFilePath := filepath.Join(cwd, "database", "tx.db") f, err := os.OpenFile(txDbFilePath, os.O_APPEND|os.O_RDWR, 0600) if err != nil { return nil, err } scanner := bufio.NewScanner(f) state := &State{balances, make([]Tx, 0), f} // Iterate over each the tx.db file's line for scanner.Scan() { if err := scanner.Err(); err != nil { return nil, err } // Convert JSON encoded TX into an object (struct) var tx Tx json.Unmarshal(scanner.Bytes(), &tx) // Rebuild the state (user balances), // as a series of events if err := state.apply(tx); err != nil { return nil, err } } return state, nil } 

The State component is responsible for:

  • Adding new transactions to Mempool
  • Validating transactions against the current State (sufficient sender balance)
  • Changing the state
  • Persisting transactions to disk
  • Calculating accounts balances by replaying all transactions since Genesis in a sequence

Adding new transactions to Mempool:

func (s *State) Add(tx Tx) error { if err := s.apply(tx); err != nil { return err } s.txMempool = append(s.txMempool, tx) return nil } 

Persisting the transactions to disk:

func (s *State) Persist() error { // Make a copy of mempool because the s.txMempool will be modified // in the loop below mempool := make([]Tx, len(s.txMempool)) copy(mempool, s.txMempool) for i := 0; i < len(mempool); i++ { txJson, err := json.Marshal(s.txMempool[i]) if err != nil { return err } if _, err = s.dbFile.Write(append(txJson, '\n')); err != nil { return err } // Remove the TX written to a file from the mempool // Yes... this particular Go syntax is a bit weird s.txMempool = append(s.txMempool[:i], s.txMempool[i+1:]...) } return nil }

Changing, Validating the state:

func (s *State) apply(tx Tx) error { if tx.IsReward() { s.Balances[tx.To] += tx.Value return nil } if tx.Value > s.Balances[tx.From] { return fmt.Errorf("insufficient balance") } s.Balances[tx.From] -= tx.Value s.Balances[tx.To] += tx.Value return nil } 

Building a Command-Line-Interface (CLI)

Tuesday evening, March 26.

Andrej wants to have a convenient way to add new transactions to his DB and list the latest balances of his customers. Because Go programs compile to binary, he builds a CLI for his program.

The easiest way to develop CLI based programs in Go is by using the third party github.com/spf13/cobra library.

Andrej initializes Go's built-in dependency manager for his project, called go modules:

cd $GOPATH/src/github.com/web3coach/the-blockchain-way-of-programming-newsletter-edition

go mod init github.com/web3coach/the-blockchain-way-of-programming-newsletter-edition

The Go modules command will automatically fetch any library you reference within your Go files.

Andrej creates a new directory called: cmd with a subdirectory tbb:

mkdir -p ./cmd/tbb

Inside he creates a main.go file, serving as the program's CLI entry point:

package main import ( "github.com/spf13/cobra" "os" "fmt" ) func main() { var tbbCmd = &cobra.Command{ Use: "tbb", Short: "The Blockchain Bar CLI", Run: func(cmd *cobra.Command, args []string) { }, } err := tbbCmd.Execute() if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } } 

The Go programs are compiled using the install cmd:

go install ./cmd/tbb/...

go: finding github.com/spf13/cobra v1.0.0 go: downloading github.com/spf13/cobra v1.0.0 go: extracting github.com/spf13/cobra v1.0.0

Go will detect missing libraries and automatically fetch them before compiling the program. Depending on your $GOPATH the resulting program will be saved in the $GOPATH/bin folder.

echo $GOPATH

/home/web3coach/go

which tbb

/home/web3coach/go/bin/tbb

You can run tbb from your terminal now, but it will not do anything because the Run function inside the main.go file is empty.

The first thing Andrej needs is versioning support for his tbb CLI program.

Next to the main.go file, he creates a version.go command:

package main import ( "fmt" "github.com/spf13/cobra" ) const Major = "0" const Minor = "1" const Fix = "0" const Verbal = "TX Add && Balances List" var versionCmd = &cobra.Command{ Use: "version", Short: "Describes version.", Run: func(cmd *cobra.Command, args []string) { fmt.Printf("Version: %s.%s.%s-beta %s", Major, Minor, Fix, Verbal) }, } 

Compiles and runs it:

go install ./cmd/tbb/...

tbb version

Version: 0.1.0-beta TX Add && Balances List

Perfect.

Identically to the version.go file, he creates a balances.go file:

func balancesCmd() *cobra.Command { var balancesCmd = &cobra.Command{ Use: "balances", Short: "Interact with balances (list...).", PreRunE: func(cmd *cobra.Command, args []string) error { return incorrectUsageErr() }, Run: func(cmd *cobra.Command, args []string) { }, } balancesCmd.AddCommand(balancesListCmd) return balancesCmd } 

The balances command will be responsible for loading the latest DB State and printing it to the standard output:

var balancesListCmd = &cobra.Command{ Use: "list", Short: "Lists all balances.", Run: func(cmd *cobra.Command, args []string) { state, err := database.NewStateFromDisk() if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } defer state.Close() fmt.Println("Accounts balances:") fmt.Println("__________________") fmt.Println("") for account, balance := range state.Balances { fmt.Println(fmt.Sprintf("%s: %d", account, balance)) } }, } 

Andrej verifies if the cmd works as expected. It should print the exact balances defined in the Genesis file because the tx.db file is still empty.

go install ./cmd/tbb/...

tbb balances list

Accounts balances: __________________ andrej: 1000000 

Works well! Now he only needs a cmd for recording the bar's activity.

Andrej creates ./cmd/tbb/tx.go cmd:

func txCmd() *cobra.Command { var txsCmd = &cobra.Command{ Use: "tx", Short: "Interact with txs (add...).", PreRunE: func(cmd *cobra.Command, args []string) error { return incorrectUsageErr() }, Run: func(cmd *cobra.Command, args []string) { }, } txsCmd.AddCommand(txAddCmd()) return txsCmd } 

The tbb tx add cmd uses State.Add(tx) function for persisting the bar's events into the file system:

func txAddCmd() *cobra.Command { var cmd = &cobra.Command{ Use: "add", Short: "Adds new TX to database.", Run: func(cmd *cobra.Command, args []string) { from, _ := cmd.Flags().GetString(flagFrom) to, _ := cmd.Flags().GetString(flagTo) value, _ := cmd.Flags().GetUint(flagValue) fromAcc := database.NewAccount(from) toAcc := database.NewAccount(to) tx := database.NewTx(fromAcc, toAcc, value, "") state, err := database.NewStateFromDisk() if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } // defer means, at the end of this function execution, // execute the following statement (close DB file with all TXs) defer state.Close() // Add the TX to an in-memory array (pool) err = state.Add(tx) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } // Flush the mempool TXs to disk err = state.Persist() if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } fmt.Println("TX successfully added to the ledger.") }, } 

The tbb tx add cmd has 3 mandatory flags: --from, --to and --value.

cmd.Flags().String(flagFrom, "", "From what account to send tokens") cmd.MarkFlagRequired(flagFrom) cmd.Flags().String(flagTo, "", "To what account to send tokens") cmd.MarkFlagRequired(flagTo) cmd.Flags().Uint(flagValue, 0, "How many tokens to send") cmd.MarkFlagRequired(flagValue) return cmd 

The CLI is done!

Andrej migrates all transactions from paper to his new DB:

tbb tx add --from=andrej --to=andrej --value=3

tbb tx add --from=andrej --to=andrej --value=700

tbb tx add --from=babayaga --to=andrej --value=2000

tbb tx add --from=andrej --to=andrej --value=100 --data=reward

tbb tx add --from=babayaga --to=andrej --value=1

Read all TXs from disk and calculate the latest state:

tbb balances list

Accounts balances: __________________ andrej: 998801 babayaga: 1999 

Bar data successfully restored! Phew, what a night!

About the Cobra CLI library

The good thing about the Cobra lib for CLI programming is the additional features it comes with. For example, you can now run: tbb help cmd and it will print out all TBB registered sub-commands with instructions on how to use them.

 tbb help The Blockchain Bar CLI Usage: tbb [flags] tbb [command] Available Commands: balances Interact with balances (list...). help Help about any command tx Interact with txs (add...). version Describes version. Flags: -h, --help help for tbb Use "tbb [command] --help" for more information about a command. 

?Fun Facts

Slučajno gubljenje podataka o kupcima danas je uobičajena subota u korporacijskom svijetu. Blockchain to popravlja decentraliziranjem pohrane podataka. Trik koji je Andrej ubacio u program preskačući provjeru stanja za TX označene kao nagrade. Bitcoin i Ethereum djeluju na isti način. Stanje računa koji je iskopao blok povećava se nenadano kao predmet ukupne inflacije opskrbe tokena koja utječe na cijeli lanac. Ukupna ponuda bitcoina ograničena je na 21 milion BTC. O "rudarstvu" i "blokovima" naučit ćete više u poglavljima 7 i 10. Komponente State i Mempoolnisu jedinstveni za ovaj program. Andrej je odabrao imena i dizajne kako bi odgovarao pojednostavljenom go-Ethereum modelu, tako da imate pogled unutar osnovnog izvornog koda Ethereuma.

? Sažetak

Blockchain je baza podataka.

Opskrba tokenima, početna stanja korisnika i postavke globalnog blockchaina definirani su u datoteci Genesis.

Genesis bilance ukazuju na izvorno stanje blockchaina i nikad se kasnije ne ažuriraju.

Promjene stanja baze podataka nazivaju se Transakcije (TX).

Transakcije su stari modni događaji koji predstavljaju radnje unutar sustava.

Code Šifra studija

Zareži: 5d4b0b

Razgovarajmo o pohlepi.

04 | Ljudi su pohlepni

git checkout c4_caesar_transfer

Tipična poslovna pohlepa

Srijeda, 27. ožujka.

BabaYaga je malo previše uložio. Zaboravila je da je plaćanje stanarine odmah iza ugla, a nema novca. BabaYaga naziva svog vlasnika stana, Cezara.

BabaYaga: Hey Caesar, I am sorry, but I don't have the cash to pay you the rent this month…

Caesar: Why not?

BabaYaga: The Blockchain Bar ICO offered a massive bonus, and I purchased 2000€ worth of tokens for just 1000€. It was a great deal!

Caesar: What the heck are you talking about? What is an ICO? What on earth are tokens? Can you pay me in some other way?

BabaYaga: Oh, not again. I can give you 1000 TBB tokens worth 1000€, and you can use them in the bar to pay for your drinks! Let me call the bar owner, Andrej, and make the transfer!

Caesar: All right... I will take it.

Andrej performs the transfer, but decides to charge an extra 50 TBB tokens for his troubles. He doesn't want to, BUT the bar shareholders who invested in him a few years ago are forcing him to generate profit as soon as possible.

BabaYaga won't notice this relatively small fee most likely anyway, Andrej tells himself. In the end, only he has the DB access.

// Rent payment

tbb tx add --from=babayaga --to=caesar --value=1000

// hidden fee charge

tbb tx add --from=babayaga --to=andrej --value=50

// new reward for another day of maintaining the DB

tbb tx add --from=andrej --to=andrej --value=100 --data=reward

?Fun Facts

Primjer blockchaina broj jedan je bankarstvo. Mnogi blockchain projekti imaju za cilj optimizirati domaću i međunarodnu razmjenu novca kroz različite valutne koridore (XRP). Ostali projekti usredotočeni su na slobodu i samo-suvereni identitet (SSI) - digitalni pokret koji prepoznaje da pojedinac treba posjedovati i kontrolirati svoj identitet i novac bez intervenirajućih upravnih vlasti ili drugih centraliziranih posrednika. SSI omogućuje ljudima interakciju u digitalnom svijetu s jednakom slobodom i sposobnošću za povjerenje kao i u izvanmrežnom svijetu. (Bitcoin / Ethereum) Evo nekoliko zabavnih činjenica zašto je blockchain savršeno pogodan za zamjenu trenutne bankarske infrastrukture vaše banke. Dobra stvar kod virtualnih tokena je njihova zamjenjivost - tj. Sposobnost trgovanja, pri čemu je svaka jedinica korisna koliko i Sljedeći.Izvršenje prijenosa s računa na račun može se izvršiti jednostavnom promjenom stanja baze podataka. Kriptovalute se mogu trgovati 24 sata na dan. Ne možete izravno trgovati dionicama. Morate proći posrednika koji uzima dio naknade od ukupne transakcije kao naknadu (1-3% do 7% prosječne godišnje dobiti). Međunarodni bankovni transfer traje između 3-10 radnih dana i može koštati čak 5% prenesene vrijednosti! Ako šaljete 10.000 USD, možda ćete morati platiti do 500 USD. Tehnologija koja stoji iza posljednjih 40 godina? FTP + CSV datoteke. Mislite li da je tržište dionica pošteno? Banke, indeksi i dionice visoko su centralizirani i pod nadzorom vlada i privatnih grupa s Wall Streeta. Slobodno tržište? Wall Street kontrolira koliko cijene mogu skočiti / pasti u jednom danu. Kao primjer, Wall Street je zaustavio trgovanje indeksom "S&P 500"nakon pada od 7% kako bi zaštitili svoje investitore i hedge fondove od gubitka novca od ljudi koji prodaju njihove dionice tijekom ožujka 2020. nakon vijesti COVID. Nakon toga, FED je za sebe tiskao bilijune dolara kako bi podržao cijenu dionica. Ako ste programer koji voli štedjeti novac i izbjegavati dugove, vaša je ušteđevina preko noći izgubila vrijednost za još nepoznat postotak. Mnoge zemlje idu u negativne prinose, neistraženi teritorij s nepoznatim posljedicama. Što to znači? Uskoro ćete morati platiti banci da zadržite ušteđevinu. Inflacija u najboljem slučaju. Prisiljeni ste trošiti novac kako biste podržali sustav koji ne kontrolirate.FED je za sebe tiskao bilijune dolara kako bi podržao cijenu dionica. Ako ste programer koji voli štedjeti novac i izbjegavati dugove, vaša je ušteđevina preko noći izgubila vrijednost za još nepoznat postotak. Mnoge zemlje idu u negativne prinose, neistraženi teritorij s nepoznatim posljedicama. Što to znači? Uskoro ćete morati platiti banci da zadržite ušteđevinu. Inflacija u najboljem slučaju. Prisiljeni ste trošiti novac kako biste podržali sustav koji ne kontrolirate.FED je za sebe tiskao bilijune dolara kako bi podržao cijenu dionica. Ako ste programer koji voli uštedjeti novac i izbjeći dug, vaša je ušteđevina preko noći izgubila vrijednost za još nepoznat postotak. Mnoge zemlje idu u negativne prinose, neistraženi teritorij s nepoznatim posljedicama. Što to znači? Uskoro ćete morati platiti banci da zadržite ušteđevinu. Inflacija u najboljem slučaju. Prisiljeni ste trošiti novac kako biste podržali sustav koji ne kontrolirate.Prisiljeni ste trošiti novac kako biste podržali sustav koji ne kontrolirate.Prisiljeni ste trošiti novac kako biste podržali sustav koji ne kontrolirate.

⚒ Study Code

Commit: 00d6ed

05 | Why We Need Blockchain

git checkout c5_broken_trust

BabaYaga Seeks Justice

Thursday, March 28.

BabaYaga enters the bar for her birthday.

BabaYaga: Hey, Andrej! Today is my birthday! Get me your most expensive bottle!

Andrej: Happy birthday! Here you go: Crystal Head Vodka. But you need to purchase one additional TBB token. The bottle costs 950 tokens, and your balance is 949.

BabaYaga: What?! My balance is supposed to be 999 TBB!

Andrej: The funds transfer to Caesar you requested last week cost you 50 tokens.

BabaYaga: This is unacceptable! I would never agree to such a high fee. You can't do this, Andrej. I trusted your system, but you are as unreliable as every other business owner. Things must change!

Andrej: All right, look. You are my most loyal customer, and I didn't want to charge you, but my shareholders forced me.

Let me re-program my system and make it completely transparent and decentralized. After all, if everyone were able to interact with the bar without going through me, it would significantly improve the bar's efficiency and balance the level of trust!

  • Ordering drinks would take seconds instead of minutes
  • The customers who forgot their wallets at home could borrow or lend tokens to each other
  • I wouldn't have to worry about losing the clients data (again) as everyone would have a copy of it
  • The database would be immutable, so once everyone would agree on a specific state, no one else can change it or maliciously modify the history. Immutability would help with yearly tax audits as well!
  • If shareholders wanted to introduce new fees or raise the current ones, everyone involved in the blockchain system would notice and have to agree with it. The users and business owners would even have to engage in some decentralized governance system together, based on voting, probably. In case of a disagreement, the users walk away with all their data!

BabaYaga: Well, it certainly sounds good, but is this even possible?

Andrej: Yes, I think so. With a bit of hashing, linked lists, immutable data structure, distributed replication, and asymmetric cryptography!

BabaYaga: Nemam pojma što si rekao, ali idi i radi svoju geeky stvar, Andrej!

?Zabavne činjenice

Rudari Bitcoin i Ethereum također primaju nagrade svakih ~ 15 minuta za pokretanje blockchain poslužitelja (čvorovi) i provjeru valjanosti transakcija. Svakih 15 minuta jedan Bitcoin rudar prima 12,5 BTC (100 000 USD u trenutku pisanja ove stranice) za pokrivanje troškova svojih poslužitelja + ostvariti određenu zaradu.Mreža Bitcoin troši jednako električne energije kao i cijela austrijska država. Na njega otpada 0,29% godišnje svjetske potrošnje električne energije. Godišnje potroši 76,84 TWh, što stvara 36,50 Mt CO2 ugljičnog otiska (Novi Zeland). Izvor.Zašto? Kasnije ćete saznati više (u poglavlju 11) gdje ćete od nule programirati algoritam za iskopavanje bitkoina! PS: Naš algoritam trošit će malo manje električne energije :)

? Sažetak

Closed software with centralized access to private data allows for just a handful of people to have a lot of power. Users don’t have a choice, and shareholders are in business to make money.

Blockchain developers aim to develop protocols where applications' entrepreneurs and users synergize in a transparent, auditable relationship. Specifications of the blockchain system should be well-defined from the beginning and only change if its users support it.

Blockchain is a database. The token supply, initial user balances, and global blockchain settings are defined in a Genesis file. The Genesis balances indicate what was the original blockchain state and are never updated afterwards.

The database state changes are called Transactions (TX). Transactions are old fashion Events representing actions within the system.

⚒ Study Code

Commit: 642045

06 | L'Hash de Immutable

git checkout c6_immutable_hash

The technical difficulty starts with this section! The concepts will only get more challenging but at the same time, very exciting. Buckle up :)

How to Program an Immutable Database?

Friday, March 29.

If Andrej wants to figure out how to program an immutable DB, he has to realize why other database systems are mutable by design.

He decides to analyze an all-mighty MySQL DB Table:

| id | name | balance | | -- | -------- | ------- | | 1 | Andrej | 998951 | | 2 | BabaYaga | 949 | | 3 | Caesar | 1000 |

In MySQL DB, anyone with access and a good enough reason can perform a table update such as:

UPDATE user_balance SET balance = balance + 100 WHERE id > 1 

Updating values across different rows is possible because the table rows are independent, mutable, and the latest state is not apparent.

Koja je najnovija promjena DB-a? Zadnji stupac promijenjen? Zadnji redak umetnut? Ako da, kako Andrej može znati koji je red nedavno izbrisan? Da su retci i stanje tablice čvrsto povezani, ovisni, odnosno, ažuriranje retka 1 generiralo bi potpuno novu, drugačiju tablicu, Andrej bi postigao svoju nepromjenjivost.

Kako možete znati je li se bilo koji bajt u bazi podataka promijenio?

Nepromjenjivost putem hash funkcija

Hashing je postupak uzimanja niza proizvoljne duljine i stvaranja hash niza fiksne duljine. Svaka promjena u unosu rezultirat će novim, drugačijim raspršivanjem.

package main import ( "crypto/sha256" "fmt" ) func main()  99896  

Isprobajte: //play.golang.org/p/FTPUa7IhOCE

Andrej također zahtijeva određenu razinu sigurnosti za svoju bazu podataka, pa se odlučio za kriptografsku heš funkciju sa sljedećim svojstvima:

  • ona je deterministička - ista poruka uvijek rezultira istim hashom
  • it is quick to compute the hash value for any given message
  • it is infeasible to generate a message from its hash value except by trying all possible messages
  • a small change to a message should change the hash value so extensively that the new hash value appears uncorrelated with the old hash value
  • it is infeasible to find two different messages with the same hash value

Implementing the DB Content Hashing

Saturday Evening, March 30.

Andrej modifies the Persist() function to return a new content hash, Snapshot, every time a new transaction is persisted.

type Snapshot [32]byte 

The Snapshot is produced by this new sha256 secure hashing function:

func (s *State) doSnapshot() error { // Re-read the whole file from the first byte _, err := s.dbFile.Seek(0, 0) if err != nil { return err } txsData, err := ioutil.ReadAll(s.dbFile) if err != nil { return err } s.snapshot = sha256.Sum256(txsData) return nil } 

The doSnapshot() is called by the modified Persist() function. When a new transaction is written into the tx.db file, the Persist() hashes the entire file content and returns its 32 bytes "fingerprint" hash.

From this moment, everyone can 100% confidently and securely refer to any particular database state (set of data) with a specific snapshot hash.

⚓Practice time

1/4 Run the tbb balances list cmd and check the balances are matching.

tbb balances list

Account balances at 7d4a360f465d... | id | name | balance | | -- | -------- | ------- | | 1 | Andrej | 999251 | | 2 | BabaYaga | 949 | | 3 | Caesar | 1000 |

2/4 Remove the last 2 rows from ./database/tx.db and check the balances again.

tbb balances list

Account balances at 841770dcd3... | id | name | balance | | -- | -------- | ------- | | 1 | Andrej | 999051 | | 2 | BabaYaga | 949 | | 3 | Caesar | 1000 | 

3/4 Reward Andrej for the last 2 days (from 28th to 30th of March):

Reward Transaction 1:

tbb tx add --from=andrej --to=andrej --value=100 --data=reward

Persisting new TX to disk: {"from":"andrej","to":"andrej","value":100,"data":"reward"} New DB Snapshot: ff2470c7043f5a34169b5dd38921ba6825b03b3facb83e426 TX successfully persisted to the ledger. 

Reward Transaction 2:

tbb tx add --from=andrej --to=andrej --value=100 --data=reward

Persisting new TX to disk: {"from":"andrej","to":"andrej","value":100,"data":"reward"} New DB Snapshot: 7d4a360f468b837b662816bcdc52c1869f99327d53ab4a9ca TX successfully persisted to the ledger. 

4/4 Run the tbb balances list cmd and ensure the balances and the snapshot hash is the same as at the beginning.

tbb balances list

Account balances at 7d4a360f465d... | id | name | balance | | -- | -------- | ------- | | 1 | Andrej | 999251 | | 2 | BabaYaga | 949 | | 3 | Caesar | 1000 | 

Done!

Because the cryptographic hash function sha256 produces the same output (given the same inputs (current tx.db and 2x tbb tx add)), if you follow the exact steps on your own computer, you will generate the exact same database state and hashes!

? Summary

Closed software with centralized access to private data puts only a few people to the position of power. Users don’t have a choice, and shareholders are in business to make money.

Blockchain developers aim to develop protocols where applications' entrepreneurs and users synergize in a transparent, auditable relation. Specifications of the blockchain system should be well defined from the beginning and only change if its users support it.

Blockchain is an immutable database. The token supply, initial user balances, and global blockchain settings you define in a Genesis file. The Genesis balances indicate what was the original blockchain state and are never updated afterwards.

The database state changes are called Transactions (TX). Transactions are old fashion Events representing actions within the system.

The database content is hashed by a secure cryptographic hash function. The blockchain participants use the resulted hash to reference a specific database state.

⚒ Study Code

Commit: b99e51

Next steps

You finished the first few chapters! Congratulations!

█▒▒▒▒▒▒▒▒▒ 10%

But this was just a quick warm-up. Blockchain is a very challenging and extensive technology, and you would need an entire book explaining how to build the full system and all of its components from scratch - so I wrote one.

You can continue reading in the next free chapter in my newsletter version of "The Blockchain Way of Programming" eBook.

07 | The Blockchain Programming Model

  • Improving Performance of an Immutable DB
  • Batch + Hash + Linked List ⇒ Blocks
  • Migrating from TX.db to BLOCKS.db

Learning: You redesign and refactor your MVP database into a blockchain architecture.

Continue in the tutorial: //web3.coach#book

Thanks for reading!