read.cash Log in
@sploit more from that month

Quickstart BCHD gRPC API for Golang Developers

Quickstart BCHD gRPC API for Golang Developers The recently announced protobuf gRPC API on BCHD provides developers with easy access to an indexing blockchain server. Simplifying the infrastructure back-end by integrating the indexing server into the BCHD bitcoin node. Read the announcement for more details on all the advantages of using gRPC over a JSON REST API. https://medium.com/@bchd.cash/announcing-the-bchd-grpc-api-16b3a833292e Alright, lets jump right into it. 1. Connection Prerequisites Read the client usage example for detailed information on how to set up a connection. https://github.com/gcash/bchd/blob/master/bchrpc/documentation/client_usage.md All you need is a URI (and the corresponding certificate if self-signed). In this example we'll be using a public node provided by @zquestz. https://twitter.com/zquestz `bchd.greyh.at:8335` If you are using a self-signed certificate on a locally hosted BCHD node, you need to copy the cert to your local `.bchd` folder or get the certificate by using a browser and surf to `https://your.bchd.node:8335`. Click the lock, view certificate and export it.

2. Setting up the connection We'll create a new TLSClient and use that to set up the gRPC connection. const grpcServer = "bchd.greyh.at:8335" func initGRPC() (*grpc.ClientConn, error) { conn, err := grpc.Dial(grpcServer, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, ""))) if err != nil { return nil, err } return conn, nil } 3. Making a request func main() { conn, err := initGRPC() if err != nil { fmt.Println(err) } defer conn.Close() c := pb.NewBchrpcClient(conn) blockchainInfoResp, err := c.GetBlockchainInfo(context.Background(), &pb.GetBlockchainInfoRequest{}) if err != nil { fmt.Println(err) } bestHeight := blockchainInfoResp.GetBestHeight() bestBlockHash := blockchainInfoResp.GetBestBlockHash() fmt.Printf("%d - %x\n", bestHeight, bestBlockHash) fmt.Printf("%v\n", bestBlockHash) fmt.Printf("%#v\n", bestBlockHash) } Output: > go run honest1.go 581802 - 05b8671c385c73d2214009b9fdfbf4ea3465eaa6b39901030000000000000000 [5 184 103 28 56 92 115 210 33 64 9 185 253 251 244 234 52 101 234 166 179 153 1 3 0 0 0 0 0 0 0 0] []byte{0x5, 0xb8, 0x67, 0x1c, 0x38, 0x5c, 0x73, 0xd2, 0x21, 0x40, 0x9, 0xb9, 0xfd, 0xfb, 0xf4, 0xea, 0x34, 0x65, 0xea, 0xa6, 0xb3, 0x99, 0x1, 0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} As you can see here, the block hash looks a bit different from what we are expecting, it ends in zeroes instead of starting with zeroes. There is a pretty good reason for this according to Chris Pacia and Mark B. Lundeberg: https://twitter.com/ChrisPacia https://twitter.com/MarkLundeberg **Chris Pacia:** The entire (BCHD) codebase treats all byte arrays as little endian (I believe the c++ code does as well?). Only when you go to string does it convert to big endian for display purposes. So given that, this is just continuing the rule that if it's a byte array it should be little endian. In our Go libraries there's an object called `chainhash` that holds the hash representation. The constructors look like this: NewHash(newHash []byte) (*Hash, error) // expects little endian byte array. NewHashFromStr(hash string) (*Hash, error) // expects big endian hex string. So at least in Go we use the bytes directly from the protobuf object into a chainhash without doing any reversal. I realize that might not be the case in other languages. I'm open to hearing other opinions. But if we changed it, it would be the only place in the codebase were we have to reverse the bytes before using them… both when writing to the wire and also when reading from the wire. **Mark B. Lundeberg:** Another way to say it: if you take double-sha256 of a block header it *ends* in a bunch of zero bytes, not starts. The bytestrings usually just get reversed when converting to hex. We have to take this into account when we want to print the string encoded representation of the hash. **First reverse the byteslice.** Let's see how this works. 4. Printing hashes Define the reverse function. func reverse(slice []byte) []byte { for i := len(slice)/2 - 1; i >= 0; i-- { opp := len(slice) - 1 - i slice[i], slice[opp] = slice[opp], slice[i] } return slice } That should clear things up. package main import ( "fmt" pb "github.com/gcash/bchd/bchrpc/pb" "golang.org/x/net/context" "google.golang.org/grpc" "google.golang.org/grpc/credentials" ) const grpcServer = "bchd.greyh.at:8335" func main() { conn, err := initGRPC() if err != nil { fmt.Println(err) } defer conn.Close() c := pb.NewBchrpcClient(conn) blockchainInfoResp, err := c.GetBlockchainInfo(context.Background(), &pb.GetBlockchainInfoRequest{}) if err != nil { fmt.Println(err) } bestHeight := blockchainInfoResp.GetBestHeight() bestBlockHash := blockchainInfoResp.GetBestBlockHash() fmt.Printf("%d - %x\n", bestHeight, bestBlockHash) fmt.Println("GRPC RESPONSE:") fmt.Printf("%v\n", bestBlockHash) fmt.Printf("%#v\n", bestBlockHash) fmt.Printf("%x\n", bestBlockHash) bestBlockHash = reverse(bestBlockHash) fmt.Println("REVERSED:") fmt.Printf("%v\n", bestBlockHash) fmt.Printf("%#v\n", bestBlockHash) fmt.Printf("%x\n", bestBlockHash) } func initGRPC() (*grpc.ClientConn, error) { conn, err := grpc.Dial(grpcServer, grpc.WithTransportCredentials(credentials.NewClientTLSFromCert(nil, ""))) if err != nil { return nil, err } return conn, nil } func reverse(slice []byte) []byte { for i := len(slice)/2 - 1; i >= 0; i-- { opp := len(slice) - 1 - i slice[i], slice[opp] = slice[opp], slice[i] } return slice } Output: > go run honest2.go 581806 - 9789862a9eea7216892e6c5b0ef8224344440d4c3a9d35010000000000000000 GRPC RESPONSE: [151 137 134 42 158 234 114 22 137 46 108 91 14 248 34 67 68 68 13 76 58 157 53 1 0 0 0 0 0 0 0 0] []byte{0x97, 0x89, 0x86, 0x2a, 0x9e, 0xea, 0x72, 0x16, 0x89, 0x2e, 0x6c, 0x5b, 0xe, 0xf8, 0x22, 0x43, 0x44, 0x44, 0xd, 0x4c, 0x3a, 0x9d, 0x35, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0} 9789862a9eea7216892e6c5b0ef8224344440d4c3a9d35010000000000000000 REVERSED: [0 0 0 0 0 0 0 0 1 53 157 58 76 13 68 68 67 34 248 14 91 108 46 137 22 114 234 158 42 134 137 151] []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x35, 0x9d, 0x3a, 0x4c, 0xd, 0x44, 0x44, 0x43, 0x22, 0xf8, 0xe, 0x5b, 0x6c, 0x2e, 0x89, 0x16, 0x72, 0xea, 0x9e, 0x2a, 0x86, 0x89, 0x97} 000000000000000001359d3a4c0d44444322f80e5b6c2e891672ea9e2a868997

No comments yet

Log in to join in Reading is open to everyone. Replying needs an account.