You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
2.7 KiB

  1. package main
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "time"
  9. "github.com/fatih/color"
  10. )
  11. type Block struct {
  12. Hash string `json:"hash"`
  13. Height int64 `json:"height"`
  14. Date time.Time `json:"date"`
  15. PreviousHash string `json:"previoushash"`
  16. NextHash string `json:"nexthash"`
  17. Data []Address `json:"data"`
  18. Emitter string `json:"emitter"` //the ID of the peer that has emmited the block
  19. }
  20. type Blockchain struct {
  21. GenesisBlock string `json:"genesisblock"`
  22. LastUpdate time.Time `json:"lastupdate"`
  23. Blocks []Block `json:"blocks"`
  24. }
  25. var blockchain Blockchain
  26. func (bc *Blockchain) getBlockByHash(hash string) (Block, error) {
  27. for _, block := range bc.Blocks {
  28. if block.Hash == hash {
  29. return block, nil
  30. }
  31. }
  32. var b Block
  33. return b, errors.New("Block Hash not found")
  34. }
  35. func (bc *Blockchain) blockExists(block Block) bool {
  36. for _, b := range bc.Blocks {
  37. if b.Hash == block.Hash {
  38. return true
  39. }
  40. }
  41. return false
  42. }
  43. func (bc *Blockchain) addBlock(block Block) error {
  44. if blockchain.blockExists(block) {
  45. return errors.New("[Error adding Block]: Block already exists in the Blockchain")
  46. }
  47. if len(bc.Blocks) > 0 {
  48. bc.Blocks[len(bc.Blocks)-1].NextHash = block.Hash
  49. } else {
  50. bc.GenesisBlock = block.Hash
  51. }
  52. bc.Blocks = append(bc.Blocks, block)
  53. return nil
  54. }
  55. func reconstructBlockchainFromBlock(urlAPI string, h string) {
  56. color.Yellow("reconstructing the blockchain from last block in memory")
  57. var block Block
  58. var err error
  59. block, err = blockchain.getBlockByHash(h)
  60. if err != nil {
  61. fmt.Println("reconstructBlockFromBlock: block with " + h + " not found. Getting genesis block")
  62. }
  63. if h == "" {
  64. //no genesis block yet
  65. color.Green(urlAPI + "/blocks/genesis")
  66. res, err := http.Get(urlAPI + "/blocks/genesis")
  67. check(err)
  68. body, err := ioutil.ReadAll(res.Body)
  69. check(err)
  70. err = json.Unmarshal(body, &block)
  71. check(err)
  72. color.Yellow("[New Block]: " + block.Hash)
  73. err = blockchain.addBlock(block)
  74. check(err)
  75. } else {
  76. block.NextHash = h
  77. }
  78. for block.NextHash != "" && block.Hash != "" {
  79. res, err := http.Get(urlAPI + "/blocks/next/" + block.Hash)
  80. check(err)
  81. body, err := ioutil.ReadAll(res.Body)
  82. check(err)
  83. err = json.Unmarshal(body, &block)
  84. check(err)
  85. if block.Hash != "" {
  86. color.Yellow("[New Block]: " + block.Hash)
  87. err = blockchain.addBlock(block)
  88. check(err)
  89. }
  90. }
  91. blockchain.print()
  92. }
  93. func (bc *Blockchain) print() {
  94. color.Green("Printing Blockchain stored in memory")
  95. color.Green("Genesis Block: " + bc.GenesisBlock)
  96. for _, b := range bc.Blocks {
  97. color.Green("Block height:")
  98. fmt.Println(b.Height)
  99. color.Green("Hash: " + b.Hash)
  100. color.Green("Date: " + b.Date.String())
  101. color.Green("---")
  102. }
  103. }