-
-
Save LordGhostX/bb92b907731ee8ebe465a28c5c431cb4 to your computer and use it in GitHub Desktop.
| package main | |
| import ( | |
| "crypto/sha256" | |
| "encoding/json" | |
| "fmt" | |
| "strconv" | |
| "strings" | |
| "time" | |
| ) | |
| type Block struct { | |
| data map[string]interface{} | |
| hash string | |
| previousHash string | |
| timestamp time.Time | |
| pow int | |
| } | |
| type Blockchain struct { | |
| genesisBlock Block | |
| chain []Block | |
| difficulty int | |
| } | |
| func (b Block) calculateHash() string { | |
| data, _ := json.Marshal(b.data) | |
| blockData := b.previousHash + string(data) + b.timestamp.String() + strconv.Itoa(b.pow) | |
| blockHash := sha256.Sum256([]byte(blockData)) | |
| return fmt.Sprintf("%x", blockHash) | |
| } | |
| func (b *Block) mine(difficulty int) { | |
| for !strings.HasPrefix(b.hash, strings.Repeat("0", difficulty)) { | |
| b.pow++ | |
| b.hash = b.calculateHash() | |
| } | |
| } | |
| func CreateBlockchain(difficulty int) Blockchain { | |
| genesisBlock := Block{ | |
| hash: "0", | |
| timestamp: time.Now(), | |
| } | |
| return Blockchain{ | |
| genesisBlock, | |
| []Block{genesisBlock}, | |
| difficulty, | |
| } | |
| } | |
| func (b *Blockchain) addBlock(from, to string, amount float64) { | |
| blockData := map[string]interface{}{ | |
| "from": from, | |
| "to": to, | |
| "amount": amount, | |
| } | |
| lastBlock := b.chain[len(b.chain)-1] | |
| newBlock := Block{ | |
| data: blockData, | |
| previousHash: lastBlock.hash, | |
| timestamp: time.Now(), | |
| } | |
| newBlock.mine(b.difficulty) | |
| b.chain = append(b.chain, newBlock) | |
| } | |
| func (b Blockchain) isValid() bool { | |
| for i := range b.chain[1:] { | |
| previousBlock := b.chain[i] | |
| currentBlock := b.chain[i+1] | |
| if currentBlock.hash != currentBlock.calculateHash() || currentBlock.previousHash != previousBlock.hash { | |
| return false | |
| } | |
| } | |
| return true | |
| } | |
| func main() { | |
| // create a new blockchain instance with a mining difficulty of 2 | |
| blockchain := CreateBlockchain(2) | |
| // record transactions on the blockchain for Alice, Bob, and John | |
| blockchain.addBlock("Alice", "Bob", 5) | |
| blockchain.addBlock("John", "Bob", 2) | |
| // check if the blockchain is valid; expecting true | |
| fmt.Println(blockchain.isValid()) | |
| } |
No it is not, feel free to use it as you wish.
Awesome, thanks!
I have hesitation learning Go since I am comfortable with PHP and Node. This is a nice intro though. Thanks
@LordGhostX Any recommended tutorial?
Great to learn the basics of blockchain while improving in Go! Thanks.
@LordGhostX How would I read the data of a block? Would I just do fmt.Println(blockchain.blockData)?
@ekpono gobyexample.com is a very good resource. Also, learnxinyminutes if you're a speed learner.
@LordGhostX how do i learn the concepts taught in this tutorial per se about the concepts of building a blockchain from scratch
@LordGhostX How would I get save data from blockchain. when I try to use this fmt.Println(blockchain.blockData) I will get error in our terminal.


@Alinawaz-786 You need to add methods for that. For example you can use the following:
// Method to get data of a single block by index
func (bc Blockchain) GetBlockData(index int) (map[string]interface{}, error) {
if index < 0 || index >= len(bc.chain) {
return nil, fmt.Errorf("index out of range")
}
return bc.chain[index].data, nil
}
// Method to get data of all blocks
func (bc Blockchain) GetAllBlockData() []map[string]interface{} {
var allData []map[string]interface{}
for _, block := range bc.chain {
allData = append(allData, block.data)
}
return allData
}
@LordGhostX Found this from through the LogRocket blog, is this code under any license?