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  }