From 143a80c7fbe6bb191fc77199e62e1635e87bbdbd Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Fri, 13 Mar 2020 14:35:08 -0700 Subject: [PATCH] zcash light wallet stats, also support for getblock --- api.go | 21 +++++++++- examples/lightwalletstats/main.go | 67 +++++++++++++++++++++++++++++++ go.mod | 2 + go.sum | 10 +++++ zcash_client.go | 12 ++++++ 5 files changed, 110 insertions(+), 2 deletions(-) create mode 100644 examples/lightwalletstats/main.go diff --git a/api.go b/api.go index ea326c0..05b28e8 100644 --- a/api.go +++ b/api.go @@ -2,6 +2,7 @@ package zcashrpc import ( "encoding/json" + "strconv" ) // Method restricts method definitions to constants @@ -9,6 +10,7 @@ type Method string // Constant block of Method assignments const ( + GetBlock Method = "getblock" GetTransaction Method = "gettransaction" ZListReceivedByAddress = "z_listreceivedbyaddress" @@ -29,14 +31,24 @@ func setupZcashRequest() zcashRequest { } // NewGetTransaction constructs a properly formatted gettransaction request -func NewGetTransaction(is string) []byte { +func NewGetTransaction(id string) []byte { request := setupZcashRequest() request.Method = GetTransaction - request.Params = append(request.Params, is) + request.Params = append(request.Params, id) data, _ := json.Marshal(request) return data } +// NewGetBlock constructs a properly formatted getblock request +func NewGetBlock(is int) []byte { + request := setupZcashRequest() + request.Method = GetBlock + request.Params = append(request.Params, strconv.Itoa(is)) + data, _ := json.Marshal(request) + return data +} + + // NewZValidateAddress constructs a properly formatted z_validateaddress request func NewZValidateAddress(address string) []byte { request := setupZcashRequest() @@ -83,6 +95,11 @@ type Transaction struct { Time int `json:"time"` } +// Block +type Block struct { + Transactions []string `json:"tx"` +} + // ZcashTransaction defines a transaction received to a zaddress type ZcashTransaction struct { TransactionID string `json:"txid"` diff --git a/examples/lightwalletstats/main.go b/examples/lightwalletstats/main.go new file mode 100644 index 0000000..7978011 --- /dev/null +++ b/examples/lightwalletstats/main.go @@ -0,0 +1,67 @@ +package main + +import ( + "encoding/json" + "fmt" + "git.openprivacy.ca/openprivacy/libricochet-go/log" + "git.openprivacy.ca/openprivacy/zcashrpc" + "io/ioutil" + "time" +) + +type zcashConfig struct { + Username string `json:"username"` + Password string `json:"password"` + Onion string `json:"onion"` + ZAddress string `json:"zaddress"` +} + +type transaction struct { + time time.Time + transaction zcashrpc.ZcashTransaction +} + +type timeSlice []transaction + +func (p timeSlice) Len() int { + return len(p) +} + +func (p timeSlice) Less(i, j int) bool { + return p[i].time.Before(p[j].time) +} + +func (p timeSlice) Swap(i, j int) { + p[i], p[j] = p[j], p[i] +} + +func main() { + log.SetLevel(log.LevelInfo) + configFile, _ := ioutil.ReadFile("local.json") + config := zcashConfig{} + _ = json.Unmarshal([]byte(configFile), &config) + zc := zcashrpc.NewLocalClient(config.Username, config.Password) + + + txcount := make(map[int]int) + for i:=760161-((86400*60)/150);i<760161;i++ { + block, err := zc.GetBlock(i) + if err != nil { + log.Errorf("Error fetching zcash transactions: %v", err) + } + _,exists := txcount[len(block.Transactions)] + if !exists { + txcount[len(block.Transactions)] = 0 + } + txcount[len(block.Transactions)]++ + if i % 1000 == 0 { + log.Infof("Processing Block %v", i) + } + } + for txs:=0;txs<5000;txs++ { + if txcount[txs] > 0 { + fmt.Printf("%v,%v\n", txs, txcount[txs]) + } + } + +} diff --git a/go.mod b/go.mod index 63aace8..3c9363f 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,8 @@ go 1.12 require ( git.openprivacy.ca/openprivacy/libricochet-go v1.0.6 github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dghubble/go-twitter v0.0.0-20190719072343-39e5462e111f + github.com/dghubble/oauth1 v0.6.0 github.com/golang/protobuf v1.3.2 // indirect github.com/kr/pretty v0.1.0 // indirect github.com/stretchr/testify v1.4.0 // indirect diff --git a/go.sum b/go.sum index c9950fd..e010540 100644 --- a/go.sum +++ b/go.sum @@ -2,16 +2,26 @@ git.openprivacy.ca/openprivacy/libricochet-go v1.0.6 h1:5o4K2qn3otEE1InC5v5CzU0y git.openprivacy.ca/openprivacy/libricochet-go v1.0.6/go.mod h1:yMSG1gBaP4f1U+RMZXN85d29D39OK5s8aTpyVRoH5FY= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412 h1:w1UutsfOrms1J05zt7ISrnJIXKzwaspym5BTKGx93EI= github.com/agl/ed25519 v0.0.0-20170116200512-5312a6153412/go.mod h1:WPjqKcmVOxf0XSf3YxCJs6N6AOSrOx3obionmG7T0y0= +github.com/cenkalti/backoff v2.1.1+incompatible h1:tKJnvO2kl0zmb/jA5UKAt4VoEVw1qxKWjE/Bpp46npY= +github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= github.com/cretz/bine v0.1.0 h1:1/fvhLE+fk0bPzjdO5Ci+0ComYxEMuB1JhM4X5skT3g= github.com/cretz/bine v0.1.0/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dghubble/go-twitter v0.0.0-20190719072343-39e5462e111f h1:M2wB039zeS1/LZtN/3A7tWyfctiOBL4ty5PURBmDdWU= +github.com/dghubble/go-twitter v0.0.0-20190719072343-39e5462e111f/go.mod h1:xfg4uS5LEzOj8PgZV7SQYRHbG7jPUnelEiaAVJxmhJE= +github.com/dghubble/oauth1 v0.6.0 h1:m1yC01Ohc/eF38jwZ8JUjL1a+XHHXtGQgK+MxQbmSx0= +github.com/dghubble/oauth1 v0.6.0/go.mod h1:8pFdfPkv/jr8mkChVbNVuJ0suiHe278BtWI4Tk1ujxk= +github.com/dghubble/sling v1.3.0 h1:pZHjCJq4zJvc6qVQ5wN1jo5oNZlNE0+8T/h0XeXBUKU= +github.com/dghubble/sling v1.3.0/go.mod h1:XXShWaBWKzNLhu2OxikSNFrlsvowtz4kyRuXUG7oQKY= github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= diff --git a/zcash_client.go b/zcash_client.go index 1300f29..6efdc15 100644 --- a/zcash_client.go +++ b/zcash_client.go @@ -15,6 +15,7 @@ import ( type ZcashClient interface { ListReceivedTransactionsByAddress(string) ([]ZcashTransaction, error) GetTransaction(string) (Transaction, error) + GetBlock(int) (Block, error) SendOne(string, string, string, float64) ([]byte, error) ValidateAddress(address string) (ZValidateAddressResponse, error) } @@ -57,6 +58,17 @@ func NewOnionClient(onion string, username, password string, acn connectivity.AC return zc } +// GetTransaction returns a specific transaction given an id +func (zc *zcashClient) GetBlock(id int) (Block, error) { + body, err := zc.sendRequest(NewGetBlock(id)) + block := Block{} + if err == nil { + result := &ZcashResult{Result: &block} + err = json.Unmarshal(body, &result) + } + return block, err +} + // GetTransaction returns a specific transaction given an id func (zc *zcashClient) GetTransaction(id string) (Transaction, error) { body, err := zc.sendRequest(NewGetTransaction(id))