package chain import ( "bytes" "encoding/gob" "fmt" "golang.org/x/crypto/sha3" "log" "math/rand" ) type block struct { Transactions []transaction HashPrevious []byte Nonce []byte } func NewBlock(hashPrevious []byte) block { return block{ Transactions: nil, HashPrevious: hashPrevious, } } func (b *block) AddTransaction(t transaction) { b.Transactions = append(b.Transactions, t) } func (b block) GenerateHash(difficulty int) []byte { found := false var compBytes []byte for i := 0; i < difficulty; i++ { compBytes = append(compBytes, []byte("0x00")...) } for !found { random := make([]byte, 64) rand.Read(random) b.Nonce = random var buf bytes.Buffer err := gob.NewEncoder(&buf).Encode(b.Nonce) if err != nil { log.Fatal(err) } hasher := sha3.New512() hasher.Write(b.ToBytes()) hash := hasher.Sum(nil) fmt.Printf("\033[2K\r%x\n", hash) if checkAllZero(XorSlice(hash[:difficulty], compBytes)) { return hash } } return nil } func (b block) ToBytes() []byte { var bytes []byte for i := 0; i < len(b.Transactions); i++ { bytes = append(bytes, b.Transactions[i].ToBytes()...) } bytes = append(bytes, b.Nonce...) return bytes } func XorSlice(a []byte, b []byte) []byte { for i, _ := range a { a[i] = a[i] ^ b[i] } return a } func checkAllZero(a []byte) bool { fmt.Printf("Checking if all zero: %x\n", a) for i, _ := range a { if a[i] != 0x00 { return false } } return true }