github.com/piotrnar/gocoin@v0.0.0-20240512203912-faa0448c5e96/lib/others/utils/fetchbl.go (about) 1 package utils 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "fmt" 7 "github.com/piotrnar/gocoin/lib/btc" 8 "io" 9 "net/http" 10 ) 11 12 // https://blockchain.info/block/000000000000000000871f4f01a389bda59e568ead8d0fd45fc7cc1919d2666e?format=hex 13 // https://webbtc.com/block/0000000000000000000cdc0d2a9b33c2d4b34b4d4fa8920f074338d0dc1164dc.bin 14 // https://blockexplorer.com/api/rawblock/0000000000000000000cdc0d2a9b33c2d4b34b4d4fa8920f074338d0dc1164dc 15 16 // GetBlockFromExplorer downloads (and re-assembles) a raw block from blockexplorer.com. 17 func GetBlockFromExplorer(hash *btc.Uint256) (rawtx []byte) { 18 url := "http://blockexplorer.com/api/rawblock/" + hash.String() 19 r, er := http.Get(url) 20 if er == nil { 21 if r.StatusCode == 200 { 22 defer r.Body.Close() 23 c, _ := io.ReadAll(r.Body) 24 var txx struct { 25 Raw string `json:"rawblock"` 26 } 27 er = json.Unmarshal(c[:], &txx) 28 if er == nil { 29 rawtx, er = hex.DecodeString(txx.Raw) 30 } 31 } else { 32 fmt.Println("blockexplorer.com StatusCode=", r.StatusCode) 33 } 34 } 35 if er != nil { 36 fmt.Println("blockexplorer.com:", er.Error()) 37 } 38 return 39 } 40 41 // GetBlockFromWebBTC downloads a raw block from webbtc.com. 42 func GetBlockFromWebBTC(hash *btc.Uint256) (raw []byte) { 43 url := "https://webbtc.com/block/" + hash.String() + ".bin" 44 r, er := http.Get(url) 45 if er == nil { 46 if r.StatusCode == 200 { 47 raw, _ = io.ReadAll(r.Body) 48 r.Body.Close() 49 } else { 50 fmt.Println("webbtc.com StatusCode=", r.StatusCode) 51 } 52 } 53 if er != nil { 54 fmt.Println("webbtc.com:", er.Error()) 55 } 56 return 57 } 58 59 // GetBlockFromBlockchainInfo downloads a raw block from blockchain.info. 60 func GetBlockFromBlockchainInfo(hash *btc.Uint256) (rawtx []byte) { 61 url := "https://blockchain.info/block/" + hash.String() + "?format=hex" 62 r, er := http.Get(url) 63 if er == nil { 64 if r.StatusCode == 200 { 65 defer r.Body.Close() 66 rawhex, _ := io.ReadAll(r.Body) 67 rawtx, er = hex.DecodeString(string(rawhex)) 68 } else { 69 fmt.Println("blockchain.info StatusCode=", r.StatusCode) 70 } 71 } 72 if er != nil { 73 fmt.Println("blockchain.info:", er.Error()) 74 } 75 return 76 } 77 78 // GetBlockFromBlockstream downloads a raw block from blockstream 79 func GetBlockFromBlockstream(hash *btc.Uint256, api_url string) (raw []byte) { 80 url := api_url + hash.String() + "/raw" 81 r, er := http.Get(url) 82 if er == nil { 83 if r.StatusCode == 200 { 84 raw, _ = io.ReadAll(r.Body) 85 r.Body.Close() 86 } else { 87 fmt.Println("blockstream block StatusCode=", r.StatusCode) 88 } 89 } 90 if er != nil { 91 fmt.Println("blockstream block:", er.Error()) 92 } 93 return 94 } 95 96 func IsBlockOK(raw []byte, hash *btc.Uint256) (bl *btc.Block) { 97 var er error 98 bl, er = btc.NewBlock(raw) 99 if er != nil { 100 return 101 } 102 if !bl.Hash.Equal(hash) { 103 return nil 104 } 105 er = bl.BuildTxList() 106 if er != nil { 107 return nil 108 } 109 if !bl.MerkleRootMatch() { 110 return nil 111 } 112 return 113 } 114 115 // GetBlockFromWeb downloads a raw block from a web server (try one after another). 116 func GetBlockFromWeb(hash *btc.Uint256) (bl *btc.Block) { 117 var raw []byte 118 119 raw = GetBlockFromBlockstream(hash, "https://blockstream.info/api/block/") 120 if bl = IsBlockOK(raw, hash); bl != nil { 121 //println("GetTxFromBlockstream - OK") 122 return 123 } 124 125 raw = GetBlockFromBlockchainInfo(hash) 126 if bl = IsBlockOK(raw, hash); bl != nil { 127 //println("GetTxFromBlockchainInfo - OK") 128 return 129 } 130 131 raw = GetBlockFromExplorer(hash) 132 if bl = IsBlockOK(raw, hash); bl != nil { 133 //println("GetTxFromExplorer - OK") 134 return 135 } 136 137 raw = GetBlockFromWebBTC(hash) 138 if bl = IsBlockOK(raw, hash); bl != nil { 139 //println("GetTxFromWebBTC - OK") 140 return 141 } 142 143 return 144 }