block.go 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. // Copyright © 2021 Ettore Di Giacinto <[email protected]>
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License along
  14. // with this program; if not, see <http://www.gnu.org/licenses/>.
  15. package blockchain
  16. import (
  17. "crypto/sha256"
  18. "encoding/hex"
  19. "fmt"
  20. "time"
  21. )
  22. type DataString string
  23. // Block represents each 'item' in the blockchain
  24. type Block struct {
  25. Index int
  26. Timestamp string
  27. Storage map[string]map[string]Data
  28. Hash string
  29. PrevHash string
  30. }
  31. // Blockchain is a series of validated Blocks
  32. type Blockchain []Block
  33. // make sure block is valid by checking index, and comparing the hash of the previous block
  34. func (newBlock Block) IsValid(oldBlock Block) bool {
  35. if oldBlock.Index+1 != newBlock.Index {
  36. return false
  37. }
  38. if oldBlock.Hash != newBlock.PrevHash {
  39. return false
  40. }
  41. if newBlock.Checksum() != newBlock.Hash {
  42. return false
  43. }
  44. return true
  45. }
  46. // Checksum does SHA256 hashing of the block
  47. func (b Block) Checksum() string {
  48. record := fmt.Sprint(b.Index, b.Timestamp, b.Storage, b.PrevHash)
  49. h := sha256.New()
  50. h.Write([]byte(record))
  51. hashed := h.Sum(nil)
  52. return hex.EncodeToString(hashed)
  53. }
  54. // create a new block using previous block's hash
  55. func (oldBlock Block) NewBlock(s map[string]map[string]Data) Block {
  56. var newBlock Block
  57. t := time.Now().UTC()
  58. newBlock.Index = oldBlock.Index + 1
  59. newBlock.Timestamp = t.String()
  60. newBlock.Storage = s
  61. newBlock.PrevHash = oldBlock.Hash
  62. newBlock.Hash = newBlock.Checksum()
  63. return newBlock
  64. }