New "staging" api (StageBlocks, StageTransactions, ApplyStaged)

Also remove the initial block load (all blocks will come from the
Staging APIs), but there is still more to do (this does not even
start up correctly) but darkside.proto is correct, we believe.
This commit is contained in:
Larry Ruane 2020-05-12 23:41:47 -06:00 committed by Larry Ruane
parent c8ee805933
commit 52ac837370
10 changed files with 834 additions and 354 deletions

View File

@ -35,7 +35,7 @@ GENERATED_FILES := docs/rtd/index.html walletrpc/compact_formats.pb.go walletrpc
PWD := $(shell pwd)
.PHONY: all dep build clean test coverage lint doc simpledoc
.PHONY: all dep build clean test coverage lint doc simpledoc proto
all: first-make-timestamp build $(GENERATED_FILES)
@ -85,6 +85,8 @@ doc: docs/rtd/index.html
docs/rtd/index.html: walletrpc/compact_formats.proto walletrpc/service.proto walletrpc/darkside.proto
docker run --rm -v $(PWD)/docs/rtd:/out -v $(PWD)/walletrpc:/protos pseudomuto/protoc-gen-doc
proto: walletrpc/service.pb.go walletrpc/darkside.pb.go
walletrpc/service.pb.go: walletrpc/service.proto
cd walletrpc && protoc service.proto --go_out=plugins=grpc:.

View File

@ -3,13 +3,15 @@ package common
import (
"bufio"
"bytes"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
"os"
"strconv"
"strings"
"time"
"github.com/zcash/lightwalletd/parser"
@ -23,7 +25,9 @@ type darksideState struct {
chainName string
// Should always be nonempty. Index 0 is the block at height start_height.
blocks [][]byte // full blocks, binary, as from zcashd getblock rpc
stagedBlocks [][]byte
incomingTransactions [][]byte // full transactions, binary, zcashd getrawtransaction txid
stagedTransactions [][]byte
}
var state darksideState
@ -40,18 +44,11 @@ func DarksideInit() {
branchID: "2bb40e60", // Blossom
chainName: "darkside",
blocks: make([][]byte, 0),
stagedBlocks: make([][]byte, 0),
incomingTransactions: make([][]byte, 0),
stagedTransactions: make([][]byte, 0),
}
RawRequest = darksideRawRequest
f := "testdata/darkside/init-blocks"
testBlocks, err := os.Open(f)
if err != nil {
Log.Warn("Error opening default darksidewalletd blocks file", f)
return
}
if err = readBlocks(testBlocks); err != nil {
Log.Warn("Error loading default darksidewalletd blocks")
}
go func() {
time.Sleep(30 * time.Minute)
Log.Fatal("Shutting down darksidewalletd to prevent accidental deployment in production.")
@ -92,9 +89,6 @@ func DarksideAddBlock(blockHex string) error {
if len(state.blocks) == 0 {
state.startHeight = blockHeight
}
if state.saplingActivation < 0 {
state.saplingActivation = blockHeight
}
state.blocks = append(state.blocks, blockData)
return nil
}
@ -116,6 +110,8 @@ func readBlocks(src io.Reader) error {
return nil
}
// DarksideSetMetaState allows the wallet test code to specify values
// that are returned by GetLightdInfo().
func DarksideSetMetaState(sa int32, bi, cn string) error {
state.saplingActivation = int(sa)
state.branchID = bi
@ -123,11 +119,15 @@ func DarksideSetMetaState(sa int32, bi, cn string) error {
return nil
}
// DarksideGetIncomingTransactions returns all transactions we're
// received via SendTransaction().
func DarksideGetIncomingTransactions() [][]byte {
return state.incomingTransactions
}
func DarksideSetBlocksURL(url string) error {
// DarksideStageBlocks opens and reads blocks from the given URL and
// adds them to the staging area.
func DarksideStageBlocks(url string) error {
resp, err := http.Get(url)
if err != nil {
return err
@ -141,6 +141,64 @@ func DarksideSetBlocksURL(url string) error {
return nil
}
// DarksideStageBlocksCreate creates empty blocks and adds them to the staging area.
func DarksideStageBlocksCreate(height int32, nonce int32, count int32) error {
for i := int32(0); i < count; i++ {
fakeCoinbase := "0400008085202f890100000000000000000000000000000000000000000000000000" +
"00000000000000ffffffff2a03d12c0c00043855975e464b8896790758f824ceac97836" +
"22c17ed38f1669b8a45ce1da857dbbe7950e2ffffffff02a0ebce1d000000001976a914" +
"7ed15946ec14ae0cd8fa8991eb6084452eb3f77c88ac405973070000000017a914e445cf" +
"a944b6f2bdacefbda904a81d5fdd26d77f8700000000000000000000000000000000000000"
// This coinbase transaction was pulled from block 797905, whose
// little-endian encoding is 0xD12C0C00. Replace it with the block
// number we want.
fakeCoinbase = strings.Replace(fakeCoinbase, "d12c0c00",
fmt.Sprintf("%02x", height&0xFF)+
fmt.Sprintf("%02x", (height>>8)&0xFF)+
fmt.Sprintf("%02x", (height>>16)&0xFF)+
fmt.Sprintf("%02x", (height>>24)&0xFF), 1)
fakeCoinbaseBytes, err := hex.DecodeString(fakeCoinbase)
if err != nil {
Log.Fatal(err)
}
hash_of_txns_and_height := sha256.Sum256([]byte(string(nonce) + string(height)))
blockHeader := &parser.BlockHeader{
RawBlockHeader: &parser.RawBlockHeader{
Version: 4,
HashPrevBlock: make([]byte, 32),
HashMerkleRoot: hash_of_txns_and_height[:],
HashFinalSaplingRoot: make([]byte, 32),
Time: 1,
NBitsBytes: make([]byte, 4),
Nonce: make([]byte, 32),
Solution: make([]byte, 1344),
},
}
headerBytes, err := blockHeader.MarshalBinary()
if err != nil {
Log.Fatal(err)
}
newBlockData := make([]byte, 0)
newBlockData = append(newBlockData, headerBytes...)
newBlockData = append(newBlockData, byte(1))
newBlockData = append(newBlockData, fakeCoinbaseBytes...)
state.stagedBlocks = append(state.stagedBlocks, newBlockData)
}
return nil
}
// DarksideClearIncomingTransactions empties the incoming transaction list.
func DarksideClearIncomingTransactions() {
state.incomingTransactions = make([][]byte, 0)
}
// DarksideSendTransaction is the handler for the SendTransaction gRPC.
// Save the transaction in the incoming transactions list.
func DarksideSendTransaction(txHex []byte) ([]byte, error) {
// Need to parse the transaction to return its hash, plus it's
// good error checking.

View File

@ -195,7 +195,7 @@ func (s *LwdStreamer) GetTransaction(ctx context.Context, txf *walletrpc.TxFilte
// GetLightdInfo gets the LightWalletD (this server) info, and includes information
// it gets from its backend zcashd.
func (s *LwdStreamer) GetLightdInfo(ctx context.Context, in *walletrpc.Empty) (*walletrpc.LightdInfo, error) {
saplingHeight, blockHeight, chainName, consensusBranchId := common.GetSaplingInfo()
saplingHeight, blockHeight, chainName, consensusBranchID := common.GetSaplingInfo()
return &walletrpc.LightdInfo{
Version: common.Version,
@ -203,7 +203,7 @@ func (s *LwdStreamer) GetLightdInfo(ctx context.Context, in *walletrpc.Empty) (*
TaddrSupport: true,
ChainName: chainName,
SaplingActivationHeight: uint64(saplingHeight),
ConsensusBranchId: consensusBranchId,
ConsensusBranchId: consensusBranchID,
BlockHeight: uint64(blockHeight),
}, nil
}
@ -212,13 +212,7 @@ func (s *LwdStreamer) GetLightdInfo(ctx context.Context, in *walletrpc.Empty) (*
func (s *LwdStreamer) SendTransaction(ctx context.Context, rawtx *walletrpc.RawTransaction) (*walletrpc.SendResponse, error) {
// sendrawtransaction "hexstring" ( allowhighfees )
//
// Submits raw transaction (serialized, hex-encoded) to local node and network.
//
// Also see createrawtransaction and signrawtransaction calls.
//
// Arguments:
// 1. "hexstring" (string, required) The hex string of the raw transaction)
// 2. allowhighfees (boolean, optional, default=false) Allow high fees
// Submits raw transaction (binary) to local node and network.
//
// Result:
// "hex" (string) The transaction hash in hex
@ -293,7 +287,9 @@ func (s *DarksideStreamer) SetMetaState(ctx context.Context, ms *walletrpc.Darks
return &walletrpc.Empty{}, nil
}
func (s *DarksideStreamer) SetBlocks(blocks walletrpc.DarksideStreamer_SetBlocksServer) error {
// StageBlocksStream accepts a list of blocks from the wallet test code,
// and makes them available to present from the mock zcashd's GetBlock rpc.
func (s *DarksideStreamer) StageBlocksStream(blocks walletrpc.DarksideStreamer_StageBlocksStreamServer) error {
for {
b, err := blocks.Recv()
if err == io.EOF {
@ -307,26 +303,54 @@ func (s *DarksideStreamer) SetBlocks(blocks walletrpc.DarksideStreamer_SetBlocks
}
}
func (s *DarksideStreamer) SetBlocksURL(ctx context.Context, u *walletrpc.DarksideBlocksURL) (*walletrpc.Empty, error) {
if err := common.DarksideSetBlocksURL(u.Url); err != nil {
// StageBlocks loads blocks from the given URL to the staging area.
func (s *DarksideStreamer) StageBlocks(ctx context.Context, u *walletrpc.DarksideBlocksURL) (*walletrpc.Empty, error) {
if err := common.DarksideStageBlocks(u.Url); err != nil {
return nil, err
}
return &walletrpc.Empty{}, nil
}
func (s *DarksideStreamer) SetTx(tx walletrpc.DarksideStreamer_SetTxServer) error {
// StageBlocksCreate stages a set of synthetic (manufactured on the fly) blocks.
func (s *DarksideStreamer) StageBlocksCreate(ctx context.Context, e *walletrpc.DarksideEmptyBlocks) (*walletrpc.Empty, error) {
if err := common.DarksideStageBlocksCreate(e.Height, e.Nonce, e.Count); err != nil {
return nil, err
}
return &walletrpc.Empty{}, nil
}
// StageTransactions adds the given transactions to the staging area.
func (s *DarksideStreamer) StageTransactions(tx walletrpc.DarksideStreamer_StageTransactionsServer) error {
// My current thinking is that this should take a JSON array of {height, txid}, store them,
// then DarksideAddBlock() would "inject" transactions into blocks as its storing
// them (remembering to update the header so the block hash changes).
return errors.New("SetTx is not yet implemented")
return errors.New("StageTransactions is not yet implemented")
}
// ApplyStaged merges all staged transactions into staged blocks and all staged blocks into the active blockchain.
func (s *DarksideStreamer) ApplyStaged(ctx context.Context, h *walletrpc.DarksideHeight) (*walletrpc.Empty, error) {
return &walletrpc.Empty{}, nil
}
// GetIncomingTransactions returns the transactions that were submitted via SendTransaction().
func (s *DarksideStreamer) GetIncomingTransactions(in *walletrpc.Empty, resp walletrpc.DarksideStreamer_GetIncomingTransactionsServer) error {
// Get all of the incoming transactions we're received via SendTransaction()
for _, tx_bytes := range common.DarksideGetIncomingTransactions() {
err := resp.Send(&walletrpc.RawTransaction{Data: tx_bytes, Height: 0})
for _, txBytes := range common.DarksideGetIncomingTransactions() {
err := resp.Send(&walletrpc.RawTransaction{Data: txBytes, Height: 0})
if err != nil {
return err
}
}
return nil
}
// ClearIncomingTransactions empties the incoming transaction list.
func (s *DarksideStreamer) ClearIncomingTransactions(ctx context.Context, e *walletrpc.Empty) (*walletrpc.Empty, error) {
common.DarksideClearIncomingTransactions()
return &walletrpc.Empty{}, nil
}
// Reset clears all the state from both darksidewalletd and lightwalletd.
func (s *DarksideStreamer) Reset(ctx context.Context, e *walletrpc.Empty) (*walletrpc.Empty, error) {
return &walletrpc.Empty{}, nil
}

1
go.mod
View File

@ -3,6 +3,7 @@ module github.com/zcash/lightwalletd
go 1.12
require (
github.com/adityapk00/lightwalletd v0.0.0-20200504192708-32ea32f06cdc
github.com/btcsuite/btcd v0.20.1-beta
github.com/golang/protobuf v1.4.1
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect

139
go.sum
View File

@ -1,7 +1,20 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/adityapk00/lightwalletd v0.0.0-20200504192708-32ea32f06cdc h1:EA7BLbBN2t18ba1ZvGYvP+n4XCz52B7dtF4VlMSJaKw=
github.com/adityapk00/lightwalletd v0.0.0-20200504192708-32ea32f06cdc/go.mod h1:lTMqw9SVAxIi4hjHda8HEuswF8uCa97e5FagQmpi/T0=
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
@ -13,16 +26,21 @@ github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
github.com/btcsuite/btcd v0.0.0-20190926002857-ba530c4abb35/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.20.1-beta h1:Ik4hyJqN8Jfyv3S4AGBOmyouMsYE3EdYODkMbQjwPGw=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I=
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
@ -39,6 +57,8 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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=
@ -52,6 +72,7 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
@ -62,8 +83,12 @@ github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zV
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191002201903-404acd9df4cc/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
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.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -78,6 +103,7 @@ github.com/golang/protobuf v1.4.0 h1:oOuy+ugB+P/kBdUnG5QaMXSIyJ1q38wWSojYCb3z5VQ
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@ -86,7 +112,16 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190930153522-6ce02741cba3/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190915194858-d3ddacdb130f/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de h1:F7WD09S8QB4LrkEpka0dFPLSotH11HRpCsLIbIcJ7sU=
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
@ -95,22 +130,30 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmg
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
@ -119,11 +162,14 @@ github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFB
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=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@ -137,7 +183,11 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.2/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pebbe/zmq4 v1.0.0/go.mod h1:7N4y5R18zBiu3l0vajMUWQgZyjv464prE8RCyBcmnZM=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -171,6 +221,8 @@ github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLk
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.5.0/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@ -178,8 +230,11 @@ github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@ -199,6 +254,7 @@ github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E=
github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
@ -210,37 +266,71 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/zcash-hackworks/lightwalletd v0.0.0-20191007195656-ac5aa8e42f09/go.mod h1:hSyp0zSIqYe3SdSRkKchLeccOW7vgOgZy1/Igldmr8o=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.1/go.mod h1:Ap50jQcDJrx6rB6VgeeFPtuPIf3wMRvRfrfYDO6+BmA=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c h1:/nJuwDLoL/zrqY6gf57vxC+Pi+pZ8bfhpPkicO5H7W4=
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191002040644-a1355ae1e2c3/go.mod h1:NOZ3BPKG0ec/BKJQgnvsSFpcKLM5xXVWnvZS97DWHgE=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20191002175909-6d0d39b2ca82/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5 h1:WQ8q63x+f/zpC8Ac1s9wLElVoHhm32p6tudrU72n1QA=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be h1:vEDujvNQGv4jgYKudGeI/+DAX4Jffq6hpD55MmoEvKs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -250,8 +340,13 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -259,28 +354,64 @@ golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3 h1:5B6i6EAiSYyejWfvc5Rc9BbI3
golang.org/x/sys v0.0.0-20200501145240-bc7a7d42d5c3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190921001708-c4c64cad1fd0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190909214602-067311248421/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190927191325-030b2cf1153e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191007185444-6536af71d98a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.10.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8 h1:Nw54tB0rB7hY/N0NQvRW8DG4Yk3Q6T9cu9RcFQDu1tc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191007204434-a023cd5227bd/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84 h1:pSLkPbrjnPyLDYUO2VM9mDLqo2V6CFBY84lFSZAfoi4=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.24.0/go.mod h1:XDChyiUovWa60DnaeDeZmSW86xtLtjtZbwvSiRnRtcA=
google.golang.org/grpc v1.25.1 h1:wdKvqQk7IttEw92GoRyKG2IDrUIpgpj6H6m81yfeMW0=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
@ -299,7 +430,10 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/ini.v1 v1.41.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.48.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
@ -311,5 +445,10 @@ gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=

View File

@ -19,7 +19,7 @@ const (
)
// A block header as defined in version 2018.0-beta-29 of the Zcash Protocol Spec.
type rawBlockHeader struct {
type RawBlockHeader struct {
// The block version number indicates which set of block validation rules
// to follow. The current and only defined block version number for Zcash
// is 4.
@ -59,9 +59,8 @@ type rawBlockHeader struct {
}
type BlockHeader struct {
*rawBlockHeader
cachedHash []byte
targetThreshold *big.Int
*RawBlockHeader
cachedHash []byte
}
// CompactLengthPrefixedLen calculates the total number of bytes needed to
@ -99,11 +98,11 @@ func WriteCompactLengthPrefixed(buf *bytes.Buffer, val []byte) {
binary.Write(buf, binary.LittleEndian, val)
}
func (hdr *rawBlockHeader) GetSize() int {
func (hdr *RawBlockHeader) GetSize() int {
return serBlockHeaderMinusEquihashSize + CompactLengthPrefixedLen(len(hdr.Solution))
}
func (hdr *rawBlockHeader) MarshalBinary() ([]byte, error) {
func (hdr *RawBlockHeader) MarshalBinary() ([]byte, error) {
headerSize := hdr.GetSize()
backing := make([]byte, 0, headerSize)
buf := bytes.NewBuffer(backing)
@ -120,13 +119,13 @@ func (hdr *rawBlockHeader) MarshalBinary() ([]byte, error) {
func NewBlockHeader() *BlockHeader {
return &BlockHeader{
rawBlockHeader: new(rawBlockHeader),
RawBlockHeader: new(RawBlockHeader),
}
}
func BlockHeaderFromParts(version int32, prevhash []byte, merkleroot []byte, saplingroot []byte, time uint32, nbitsbytes []byte, nonce []byte, solution []byte) *BlockHeader {
return &BlockHeader{
rawBlockHeader: &rawBlockHeader{
RawBlockHeader: &RawBlockHeader{
Version: version,
HashPrevBlock: prevhash,
HashMerkleRoot: merkleroot,

File diff suppressed because one or more lines are too long

View File

@ -96,6 +96,7 @@ func (x *DarksideMetaState) GetChainName() string {
return ""
}
// A block is a hex-encoded string.
type DarksideBlock struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -246,6 +247,116 @@ func (x *DarksideTx) GetTransaction() string {
return ""
}
type DarksideHeight struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Height int32 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"`
}
func (x *DarksideHeight) Reset() {
*x = DarksideHeight{}
if protoimpl.UnsafeEnabled {
mi := &file_darkside_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DarksideHeight) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DarksideHeight) ProtoMessage() {}
func (x *DarksideHeight) ProtoReflect() protoreflect.Message {
mi := &file_darkside_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DarksideHeight.ProtoReflect.Descriptor instead.
func (*DarksideHeight) Descriptor() ([]byte, []int) {
return file_darkside_proto_rawDescGZIP(), []int{4}
}
func (x *DarksideHeight) GetHeight() int32 {
if x != nil {
return x.Height
}
return 0
}
type DarksideEmptyBlocks struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Height int32 `protobuf:"varint,1,opt,name=height,proto3" json:"height,omitempty"`
Nonce int32 `protobuf:"varint,2,opt,name=nonce,proto3" json:"nonce,omitempty"`
Count int32 `protobuf:"varint,3,opt,name=count,proto3" json:"count,omitempty"`
}
func (x *DarksideEmptyBlocks) Reset() {
*x = DarksideEmptyBlocks{}
if protoimpl.UnsafeEnabled {
mi := &file_darkside_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DarksideEmptyBlocks) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DarksideEmptyBlocks) ProtoMessage() {}
func (x *DarksideEmptyBlocks) ProtoReflect() protoreflect.Message {
mi := &file_darkside_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DarksideEmptyBlocks.ProtoReflect.Descriptor instead.
func (*DarksideEmptyBlocks) Descriptor() ([]byte, []int) {
return file_darkside_proto_rawDescGZIP(), []int{5}
}
func (x *DarksideEmptyBlocks) GetHeight() int32 {
if x != nil {
return x.Height
}
return 0
}
func (x *DarksideEmptyBlocks) GetNonce() int32 {
if x != nil {
return x.Nonce
}
return 0
}
func (x *DarksideEmptyBlocks) GetCount() int32 {
if x != nil {
return x.Count
}
return 0
}
var File_darkside_proto protoreflect.FileDescriptor
var file_darkside_proto_rawDesc = []byte{
@ -269,38 +380,69 @@ var file_darkside_proto_rawDesc = []byte{
0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52,
0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x20, 0x0a, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73,
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x74, 0x72,
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x32, 0xcd, 0x03, 0x0a, 0x10, 0x44, 0x61,
0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72, 0x12, 0x58,
0x0a, 0x0c, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x28,
0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73,
0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x4d,
0x65, 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e,
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x53, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x42,
0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x24, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77,
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61,
0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x1a, 0x1c, 0x2e, 0x63, 0x61,
0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e,
0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x58, 0x0a,
0x0c, 0x53, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x55, 0x52, 0x4c, 0x12, 0x28, 0x2e,
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x28, 0x0a, 0x0e, 0x44, 0x61, 0x72,
0x6b, 0x73, 0x69, 0x64, 0x65, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68,
0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x68, 0x65, 0x69,
0x67, 0x68, 0x74, 0x22, 0x59, 0x0a, 0x13, 0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x45,
0x6d, 0x70, 0x74, 0x79, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65,
0x69, 0x67, 0x68, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67,
0x68, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
0x05, 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e,
0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0xbd,
0x06, 0x0a, 0x10, 0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61,
0x6d, 0x65, 0x72, 0x12, 0x58, 0x0a, 0x0c, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x74, 0x61, 0x53, 0x74,
0x61, 0x74, 0x65, 0x12, 0x28, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x72, 0x6b,
0x73, 0x69, 0x64, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x53, 0x74, 0x61, 0x74, 0x65, 0x1a, 0x1c, 0x2e,
0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64,
0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x73, 0x55, 0x52, 0x4c, 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a,
0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x05, 0x53, 0x65, 0x74, 0x54, 0x78,
0x12, 0x21, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74,
0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64,
0x65, 0x54, 0x78, 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x5b, 0x0a,
0x11, 0x53, 0x74, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x53, 0x74, 0x72, 0x65,
0x61, 0x6d, 0x12, 0x24, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c,
0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x72, 0x6b, 0x73,
0x69, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e,
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x57, 0x0a, 0x0b, 0x53, 0x74,
0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x28, 0x2e, 0x63, 0x61, 0x73, 0x68,
0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x73,
0x55, 0x52, 0x4c, 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x22, 0x00, 0x28, 0x01, 0x12, 0x62, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x49, 0x6e, 0x63, 0x6f,
0x6d, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x79, 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x11, 0x53, 0x74, 0x61, 0x67, 0x65, 0x42, 0x6c, 0x6f, 0x63,
0x6b, 0x73, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e,
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x6c,
0x6f, 0x63, 0x6b, 0x73, 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61,
0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70,
0x74, 0x79, 0x22, 0x00, 0x12, 0x5c, 0x0a, 0x11, 0x53, 0x74, 0x61, 0x67, 0x65, 0x54, 0x72, 0x61,
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68,
0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e,
0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74,
0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00,
0x28, 0x01, 0x12, 0x54, 0x0a, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x53, 0x74, 0x61, 0x67, 0x65,
0x64, 0x12, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65,
0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x61, 0x72, 0x6b, 0x73, 0x69,
0x64, 0x65, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e,
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x62, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x49,
0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69,
0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x1a, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65,
0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61,
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x30, 0x01, 0x12, 0x59, 0x0a, 0x19,
0x43, 0x6c, 0x65, 0x61, 0x72, 0x49, 0x6e, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x61,
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68,
0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70,
0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a,
0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e,
0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x05, 0x52, 0x65, 0x73, 0x65, 0x74,
0x12, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74,
0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x25,
0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c,
0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73,
0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x30, 0x01, 0x42, 0x10, 0x5a, 0x0b, 0x2e, 0x3b, 0x77,
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0xba, 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x33,
0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x10,
0x5a, 0x0b, 0x2e, 0x3b, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70, 0x63, 0xba, 0x02, 0x00,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@ -315,28 +457,38 @@ func file_darkside_proto_rawDescGZIP() []byte {
return file_darkside_proto_rawDescData
}
var file_darkside_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
var file_darkside_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_darkside_proto_goTypes = []interface{}{
(*DarksideMetaState)(nil), // 0: cash.z.wallet.sdk.rpc.DarksideMetaState
(*DarksideBlock)(nil), // 1: cash.z.wallet.sdk.rpc.DarksideBlock
(*DarksideBlocksURL)(nil), // 2: cash.z.wallet.sdk.rpc.DarksideBlocksURL
(*DarksideTx)(nil), // 3: cash.z.wallet.sdk.rpc.DarksideTx
(*Empty)(nil), // 4: cash.z.wallet.sdk.rpc.Empty
(*RawTransaction)(nil), // 5: cash.z.wallet.sdk.rpc.RawTransaction
(*DarksideMetaState)(nil), // 0: cash.z.wallet.sdk.rpc.DarksideMetaState
(*DarksideBlock)(nil), // 1: cash.z.wallet.sdk.rpc.DarksideBlock
(*DarksideBlocksURL)(nil), // 2: cash.z.wallet.sdk.rpc.DarksideBlocksURL
(*DarksideTx)(nil), // 3: cash.z.wallet.sdk.rpc.DarksideTx
(*DarksideHeight)(nil), // 4: cash.z.wallet.sdk.rpc.DarksideHeight
(*DarksideEmptyBlocks)(nil), // 5: cash.z.wallet.sdk.rpc.DarksideEmptyBlocks
(*RawTransaction)(nil), // 6: cash.z.wallet.sdk.rpc.RawTransaction
(*Empty)(nil), // 7: cash.z.wallet.sdk.rpc.Empty
}
var file_darkside_proto_depIdxs = []int32{
0, // 0: cash.z.wallet.sdk.rpc.DarksideStreamer.SetMetaState:input_type -> cash.z.wallet.sdk.rpc.DarksideMetaState
1, // 1: cash.z.wallet.sdk.rpc.DarksideStreamer.SetBlocks:input_type -> cash.z.wallet.sdk.rpc.DarksideBlock
2, // 2: cash.z.wallet.sdk.rpc.DarksideStreamer.SetBlocksURL:input_type -> cash.z.wallet.sdk.rpc.DarksideBlocksURL
3, // 3: cash.z.wallet.sdk.rpc.DarksideStreamer.SetTx:input_type -> cash.z.wallet.sdk.rpc.DarksideTx
4, // 4: cash.z.wallet.sdk.rpc.DarksideStreamer.GetIncomingTransactions:input_type -> cash.z.wallet.sdk.rpc.Empty
4, // 5: cash.z.wallet.sdk.rpc.DarksideStreamer.SetMetaState:output_type -> cash.z.wallet.sdk.rpc.Empty
4, // 6: cash.z.wallet.sdk.rpc.DarksideStreamer.SetBlocks:output_type -> cash.z.wallet.sdk.rpc.Empty
4, // 7: cash.z.wallet.sdk.rpc.DarksideStreamer.SetBlocksURL:output_type -> cash.z.wallet.sdk.rpc.Empty
4, // 8: cash.z.wallet.sdk.rpc.DarksideStreamer.SetTx:output_type -> cash.z.wallet.sdk.rpc.Empty
5, // 9: cash.z.wallet.sdk.rpc.DarksideStreamer.GetIncomingTransactions:output_type -> cash.z.wallet.sdk.rpc.RawTransaction
5, // [5:10] is the sub-list for method output_type
0, // [0:5] is the sub-list for method input_type
1, // 1: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocksStream:input_type -> cash.z.wallet.sdk.rpc.DarksideBlock
2, // 2: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocks:input_type -> cash.z.wallet.sdk.rpc.DarksideBlocksURL
5, // 3: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocksCreate:input_type -> cash.z.wallet.sdk.rpc.DarksideEmptyBlocks
6, // 4: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactions:input_type -> cash.z.wallet.sdk.rpc.RawTransaction
4, // 5: cash.z.wallet.sdk.rpc.DarksideStreamer.ApplyStaged:input_type -> cash.z.wallet.sdk.rpc.DarksideHeight
7, // 6: cash.z.wallet.sdk.rpc.DarksideStreamer.GetIncomingTransactions:input_type -> cash.z.wallet.sdk.rpc.Empty
7, // 7: cash.z.wallet.sdk.rpc.DarksideStreamer.ClearIncomingTransactions:input_type -> cash.z.wallet.sdk.rpc.Empty
7, // 8: cash.z.wallet.sdk.rpc.DarksideStreamer.Reset:input_type -> cash.z.wallet.sdk.rpc.Empty
7, // 9: cash.z.wallet.sdk.rpc.DarksideStreamer.SetMetaState:output_type -> cash.z.wallet.sdk.rpc.Empty
7, // 10: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocksStream:output_type -> cash.z.wallet.sdk.rpc.Empty
7, // 11: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocks:output_type -> cash.z.wallet.sdk.rpc.Empty
7, // 12: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocksCreate:output_type -> cash.z.wallet.sdk.rpc.Empty
7, // 13: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactions:output_type -> cash.z.wallet.sdk.rpc.Empty
7, // 14: cash.z.wallet.sdk.rpc.DarksideStreamer.ApplyStaged:output_type -> cash.z.wallet.sdk.rpc.Empty
6, // 15: cash.z.wallet.sdk.rpc.DarksideStreamer.GetIncomingTransactions:output_type -> cash.z.wallet.sdk.rpc.RawTransaction
7, // 16: cash.z.wallet.sdk.rpc.DarksideStreamer.ClearIncomingTransactions:output_type -> cash.z.wallet.sdk.rpc.Empty
7, // 17: cash.z.wallet.sdk.rpc.DarksideStreamer.Reset:output_type -> cash.z.wallet.sdk.rpc.Empty
9, // [9:18] is the sub-list for method output_type
0, // [0:9] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
@ -397,6 +549,30 @@ func file_darkside_proto_init() {
return nil
}
}
file_darkside_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DarksideHeight); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_darkside_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DarksideEmptyBlocks); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@ -404,7 +580,7 @@ func file_darkside_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_darkside_proto_rawDesc,
NumEnums: 0,
NumMessages: 4,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
@ -430,47 +606,58 @@ const _ = grpc.SupportPackageIsVersion6
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type DarksideStreamerClient interface {
// Set (some of) the values that should be returned by GetLightdInfo()
// Set (some of) the values returned by GetLightdInfo()
SetMetaState(ctx context.Context, in *DarksideMetaState, opts ...grpc.CallOption) (*Empty, error)
// SetBlocks() replaces the specified range of blocks (gaps not allowed);
// for example, you can set blocks 1000-1006, do some tests, then set blocks
// 1003-1004. This preserves blocks 1000-1002, replaces blocks 1003-1004,
// and removes blocks 1005-1006. This can be used to simulate a chain reorg.
// Blocks are hex-encoded.
SetBlocks(ctx context.Context, opts ...grpc.CallOption) (DarksideStreamer_SetBlocksClient, error)
// This is the same as SetBlocks(), except the blocks are fetched
// StageBlocksStream accepts a list of blocks and saves them into the blocks
// staging area until ApplyStaged() is called; there is no immediate effect on
// the mock zcashd. Blocks are hex-encoded.
StageBlocksStream(ctx context.Context, opts ...grpc.CallOption) (DarksideStreamer_StageBlocksStreamClient, error)
// StageBlocks is the same as StageBlocksStream() except the blocks are fetched
// from the given URL. Blocks are one per line, hex-encoded (not JSON).
// SetBlocksURL("file:testdata/darkside/init-blocks") is done at startup.
SetBlocksURL(ctx context.Context, in *DarksideBlocksURL, opts ...grpc.CallOption) (*Empty, error)
// SetTx() allows the test coordinator to submit a list of transactions and
// for each indicate in which block it should appear.
// For example,
// tx1, block=1001
// tx2, block=1002
// tx3, block=1002
// Then use Setblocks(1000-1005): block 1001 will include tx1 (plus
// any transactions were part of that block to begin with); tx2 and tx3
// will appear in block 1002. Blocks 1003-1005 will be returned as submitted.
//
// If you first set a range of blocks, then submit transactions within that
// range, it's too late for them to be included in those blocks. If blocks
// are resubmitted, then those transactions are included in those blocks.
//
// Calling GetTransaction() on tx1-3 will return those transactions, and
// GetTransaction() will also return any transactions that were part of
// the submitted blocks.
//
// Each call to SetTx() completely replaces the stored transaction set.
SetTx(ctx context.Context, opts ...grpc.CallOption) (DarksideStreamer_SetTxClient, error)
// Calls to SendTransaction() are accepted and stored; this method returns
// all transactions that were previously submitted. This enables the
// following kind of test, for example:
// 1. wallet submits a transaction
// 2. Test coordinator retrives the transaction using this interface
// 3. Test coordinator submits the transaction using SetTx()
// 4. Darksidewalletd simulates the transaction appearing in a mined block
StageBlocks(ctx context.Context, in *DarksideBlocksURL, opts ...grpc.CallOption) (*Empty, error)
// StageBlocksCreate is like the previous two, except it creates 'count'
// empty blocks at consecutive heights starting at height 'height'. The
// 'nonce' is part of the header, so it contributes to the block hash; this
// lets you create two fake blocks with the same transactions (or no
// transactions) and same height, with two different hashes.
StageBlocksCreate(ctx context.Context, in *DarksideEmptyBlocks, opts ...grpc.CallOption) (*Empty, error)
// StageTransactions stores the given transaction-height pairs in the
// staging area until ApplyStaged() is called. Note that these transactions
// are not returned by the production GetTransaction() gRPC until they
// appear in a "mined" block (contained in the active blockchain presented
// by the mock zcashd).
StageTransactions(ctx context.Context, opts ...grpc.CallOption) (DarksideStreamer_StageTransactionsClient, error)
// ApplyStaged iterates the list of blocks that were staged by the
// StageBlocks*() gRPCs, in the order they were staged, and "merges" each
// into the active, working blocks list that the mock zcashd is presenting
// to lightwalletd. The resulting working block list can't have gaps; if the
// working block range is 1000-1006, and the staged block range is 1003-1004,
// the resulting range is 1000-1004, with 1000-1002 unchanged, blocks
// 1003-1004 from the new range, and 1005-1006 dropped. After merging all
// blocks, ApplyStaged() appends staged transactions (in the order received)
// into each one's corresponding block. The staging area is then cleared.
//
// The argument specifies the latest block height that mock zcashd reports
// (i.e. what's returned by GetLatestBlock). Note that ApplyStaged() can
// also be used to simply advance the latest block height presented by mock
// zcashd. That is, there doesn't need to be anything in the staging area.
ApplyStaged(ctx context.Context, in *DarksideHeight, opts ...grpc.CallOption) (*Empty, error)
// Calls to the production gRPC SendTransaction() store the transaction in
// a separate area (not the staging area); this method returns all transactions
// in this separate area, which is then cleared. The height returned
// with each transaction is -1 (invalid) since these transactions haven't
// been mined yet. The intention is that the transactions returned here can
// then, for example, be given to StageTransactions() to get them "mined"
// into a specified block on the next ApplyStaged().
GetIncomingTransactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (DarksideStreamer_GetIncomingTransactionsClient, error)
// Clear the incoming transaction pool.
ClearIncomingTransactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
// Reset reverts all darksidewalletd state (active block range, latest height,
// staged blocks and transactions) and lightwalletd state (cache) to empty,
// the same as the initial state. This occurs synchronously and instantaneously;
// no reorg happens in lightwalletd. This is good to do before each independent
// test so that no state leaks from one test to another.
Reset(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
}
type darksideStreamerClient struct {
@ -490,30 +677,30 @@ func (c *darksideStreamerClient) SetMetaState(ctx context.Context, in *DarksideM
return out, nil
}
func (c *darksideStreamerClient) SetBlocks(ctx context.Context, opts ...grpc.CallOption) (DarksideStreamer_SetBlocksClient, error) {
stream, err := c.cc.NewStream(ctx, &_DarksideStreamer_serviceDesc.Streams[0], "/cash.z.wallet.sdk.rpc.DarksideStreamer/SetBlocks", opts...)
func (c *darksideStreamerClient) StageBlocksStream(ctx context.Context, opts ...grpc.CallOption) (DarksideStreamer_StageBlocksStreamClient, error) {
stream, err := c.cc.NewStream(ctx, &_DarksideStreamer_serviceDesc.Streams[0], "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksStream", opts...)
if err != nil {
return nil, err
}
x := &darksideStreamerSetBlocksClient{stream}
x := &darksideStreamerStageBlocksStreamClient{stream}
return x, nil
}
type DarksideStreamer_SetBlocksClient interface {
type DarksideStreamer_StageBlocksStreamClient interface {
Send(*DarksideBlock) error
CloseAndRecv() (*Empty, error)
grpc.ClientStream
}
type darksideStreamerSetBlocksClient struct {
type darksideStreamerStageBlocksStreamClient struct {
grpc.ClientStream
}
func (x *darksideStreamerSetBlocksClient) Send(m *DarksideBlock) error {
func (x *darksideStreamerStageBlocksStreamClient) Send(m *DarksideBlock) error {
return x.ClientStream.SendMsg(m)
}
func (x *darksideStreamerSetBlocksClient) CloseAndRecv() (*Empty, error) {
func (x *darksideStreamerStageBlocksStreamClient) CloseAndRecv() (*Empty, error) {
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
@ -524,39 +711,48 @@ func (x *darksideStreamerSetBlocksClient) CloseAndRecv() (*Empty, error) {
return m, nil
}
func (c *darksideStreamerClient) SetBlocksURL(ctx context.Context, in *DarksideBlocksURL, opts ...grpc.CallOption) (*Empty, error) {
func (c *darksideStreamerClient) StageBlocks(ctx context.Context, in *DarksideBlocksURL, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.DarksideStreamer/SetBlocksURL", in, out, opts...)
err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocks", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *darksideStreamerClient) SetTx(ctx context.Context, opts ...grpc.CallOption) (DarksideStreamer_SetTxClient, error) {
stream, err := c.cc.NewStream(ctx, &_DarksideStreamer_serviceDesc.Streams[1], "/cash.z.wallet.sdk.rpc.DarksideStreamer/SetTx", opts...)
func (c *darksideStreamerClient) StageBlocksCreate(ctx context.Context, in *DarksideEmptyBlocks, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksCreate", in, out, opts...)
if err != nil {
return nil, err
}
x := &darksideStreamerSetTxClient{stream}
return out, nil
}
func (c *darksideStreamerClient) StageTransactions(ctx context.Context, opts ...grpc.CallOption) (DarksideStreamer_StageTransactionsClient, error) {
stream, err := c.cc.NewStream(ctx, &_DarksideStreamer_serviceDesc.Streams[1], "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageTransactions", opts...)
if err != nil {
return nil, err
}
x := &darksideStreamerStageTransactionsClient{stream}
return x, nil
}
type DarksideStreamer_SetTxClient interface {
Send(*DarksideTx) error
type DarksideStreamer_StageTransactionsClient interface {
Send(*RawTransaction) error
CloseAndRecv() (*Empty, error)
grpc.ClientStream
}
type darksideStreamerSetTxClient struct {
type darksideStreamerStageTransactionsClient struct {
grpc.ClientStream
}
func (x *darksideStreamerSetTxClient) Send(m *DarksideTx) error {
func (x *darksideStreamerStageTransactionsClient) Send(m *RawTransaction) error {
return x.ClientStream.SendMsg(m)
}
func (x *darksideStreamerSetTxClient) CloseAndRecv() (*Empty, error) {
func (x *darksideStreamerStageTransactionsClient) CloseAndRecv() (*Empty, error) {
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
@ -567,6 +763,15 @@ func (x *darksideStreamerSetTxClient) CloseAndRecv() (*Empty, error) {
return m, nil
}
func (c *darksideStreamerClient) ApplyStaged(ctx context.Context, in *DarksideHeight, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.DarksideStreamer/ApplyStaged", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *darksideStreamerClient) GetIncomingTransactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (DarksideStreamer_GetIncomingTransactionsClient, error) {
stream, err := c.cc.NewStream(ctx, &_DarksideStreamer_serviceDesc.Streams[2], "/cash.z.wallet.sdk.rpc.DarksideStreamer/GetIncomingTransactions", opts...)
if err != nil {
@ -599,49 +804,78 @@ func (x *darksideStreamerGetIncomingTransactionsClient) Recv() (*RawTransaction,
return m, nil
}
func (c *darksideStreamerClient) ClearIncomingTransactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearIncomingTransactions", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *darksideStreamerClient) Reset(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
out := new(Empty)
err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.DarksideStreamer/Reset", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// DarksideStreamerServer is the server API for DarksideStreamer service.
type DarksideStreamerServer interface {
// Set (some of) the values that should be returned by GetLightdInfo()
// Set (some of) the values returned by GetLightdInfo()
SetMetaState(context.Context, *DarksideMetaState) (*Empty, error)
// SetBlocks() replaces the specified range of blocks (gaps not allowed);
// for example, you can set blocks 1000-1006, do some tests, then set blocks
// 1003-1004. This preserves blocks 1000-1002, replaces blocks 1003-1004,
// and removes blocks 1005-1006. This can be used to simulate a chain reorg.
// Blocks are hex-encoded.
SetBlocks(DarksideStreamer_SetBlocksServer) error
// This is the same as SetBlocks(), except the blocks are fetched
// StageBlocksStream accepts a list of blocks and saves them into the blocks
// staging area until ApplyStaged() is called; there is no immediate effect on
// the mock zcashd. Blocks are hex-encoded.
StageBlocksStream(DarksideStreamer_StageBlocksStreamServer) error
// StageBlocks is the same as StageBlocksStream() except the blocks are fetched
// from the given URL. Blocks are one per line, hex-encoded (not JSON).
// SetBlocksURL("file:testdata/darkside/init-blocks") is done at startup.
SetBlocksURL(context.Context, *DarksideBlocksURL) (*Empty, error)
// SetTx() allows the test coordinator to submit a list of transactions and
// for each indicate in which block it should appear.
// For example,
// tx1, block=1001
// tx2, block=1002
// tx3, block=1002
// Then use Setblocks(1000-1005): block 1001 will include tx1 (plus
// any transactions were part of that block to begin with); tx2 and tx3
// will appear in block 1002. Blocks 1003-1005 will be returned as submitted.
//
// If you first set a range of blocks, then submit transactions within that
// range, it's too late for them to be included in those blocks. If blocks
// are resubmitted, then those transactions are included in those blocks.
//
// Calling GetTransaction() on tx1-3 will return those transactions, and
// GetTransaction() will also return any transactions that were part of
// the submitted blocks.
//
// Each call to SetTx() completely replaces the stored transaction set.
SetTx(DarksideStreamer_SetTxServer) error
// Calls to SendTransaction() are accepted and stored; this method returns
// all transactions that were previously submitted. This enables the
// following kind of test, for example:
// 1. wallet submits a transaction
// 2. Test coordinator retrives the transaction using this interface
// 3. Test coordinator submits the transaction using SetTx()
// 4. Darksidewalletd simulates the transaction appearing in a mined block
StageBlocks(context.Context, *DarksideBlocksURL) (*Empty, error)
// StageBlocksCreate is like the previous two, except it creates 'count'
// empty blocks at consecutive heights starting at height 'height'. The
// 'nonce' is part of the header, so it contributes to the block hash; this
// lets you create two fake blocks with the same transactions (or no
// transactions) and same height, with two different hashes.
StageBlocksCreate(context.Context, *DarksideEmptyBlocks) (*Empty, error)
// StageTransactions stores the given transaction-height pairs in the
// staging area until ApplyStaged() is called. Note that these transactions
// are not returned by the production GetTransaction() gRPC until they
// appear in a "mined" block (contained in the active blockchain presented
// by the mock zcashd).
StageTransactions(DarksideStreamer_StageTransactionsServer) error
// ApplyStaged iterates the list of blocks that were staged by the
// StageBlocks*() gRPCs, in the order they were staged, and "merges" each
// into the active, working blocks list that the mock zcashd is presenting
// to lightwalletd. The resulting working block list can't have gaps; if the
// working block range is 1000-1006, and the staged block range is 1003-1004,
// the resulting range is 1000-1004, with 1000-1002 unchanged, blocks
// 1003-1004 from the new range, and 1005-1006 dropped. After merging all
// blocks, ApplyStaged() appends staged transactions (in the order received)
// into each one's corresponding block. The staging area is then cleared.
//
// The argument specifies the latest block height that mock zcashd reports
// (i.e. what's returned by GetLatestBlock). Note that ApplyStaged() can
// also be used to simply advance the latest block height presented by mock
// zcashd. That is, there doesn't need to be anything in the staging area.
ApplyStaged(context.Context, *DarksideHeight) (*Empty, error)
// Calls to the production gRPC SendTransaction() store the transaction in
// a separate area (not the staging area); this method returns all transactions
// in this separate area, which is then cleared. The height returned
// with each transaction is -1 (invalid) since these transactions haven't
// been mined yet. The intention is that the transactions returned here can
// then, for example, be given to StageTransactions() to get them "mined"
// into a specified block on the next ApplyStaged().
GetIncomingTransactions(*Empty, DarksideStreamer_GetIncomingTransactionsServer) error
// Clear the incoming transaction pool.
ClearIncomingTransactions(context.Context, *Empty) (*Empty, error)
// Reset reverts all darksidewalletd state (active block range, latest height,
// staged blocks and transactions) and lightwalletd state (cache) to empty,
// the same as the initial state. This occurs synchronously and instantaneously;
// no reorg happens in lightwalletd. This is good to do before each independent
// test so that no state leaks from one test to another.
Reset(context.Context, *Empty) (*Empty, error)
}
// UnimplementedDarksideStreamerServer can be embedded to have forward compatible implementations.
@ -651,18 +885,30 @@ type UnimplementedDarksideStreamerServer struct {
func (*UnimplementedDarksideStreamerServer) SetMetaState(context.Context, *DarksideMetaState) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetMetaState not implemented")
}
func (*UnimplementedDarksideStreamerServer) SetBlocks(DarksideStreamer_SetBlocksServer) error {
return status.Errorf(codes.Unimplemented, "method SetBlocks not implemented")
func (*UnimplementedDarksideStreamerServer) StageBlocksStream(DarksideStreamer_StageBlocksStreamServer) error {
return status.Errorf(codes.Unimplemented, "method StageBlocksStream not implemented")
}
func (*UnimplementedDarksideStreamerServer) SetBlocksURL(context.Context, *DarksideBlocksURL) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method SetBlocksURL not implemented")
func (*UnimplementedDarksideStreamerServer) StageBlocks(context.Context, *DarksideBlocksURL) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method StageBlocks not implemented")
}
func (*UnimplementedDarksideStreamerServer) SetTx(DarksideStreamer_SetTxServer) error {
return status.Errorf(codes.Unimplemented, "method SetTx not implemented")
func (*UnimplementedDarksideStreamerServer) StageBlocksCreate(context.Context, *DarksideEmptyBlocks) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method StageBlocksCreate not implemented")
}
func (*UnimplementedDarksideStreamerServer) StageTransactions(DarksideStreamer_StageTransactionsServer) error {
return status.Errorf(codes.Unimplemented, "method StageTransactions not implemented")
}
func (*UnimplementedDarksideStreamerServer) ApplyStaged(context.Context, *DarksideHeight) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method ApplyStaged not implemented")
}
func (*UnimplementedDarksideStreamerServer) GetIncomingTransactions(*Empty, DarksideStreamer_GetIncomingTransactionsServer) error {
return status.Errorf(codes.Unimplemented, "method GetIncomingTransactions not implemented")
}
func (*UnimplementedDarksideStreamerServer) ClearIncomingTransactions(context.Context, *Empty) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method ClearIncomingTransactions not implemented")
}
func (*UnimplementedDarksideStreamerServer) Reset(context.Context, *Empty) (*Empty, error) {
return nil, status.Errorf(codes.Unimplemented, "method Reset not implemented")
}
func RegisterDarksideStreamerServer(s *grpc.Server, srv DarksideStreamerServer) {
s.RegisterService(&_DarksideStreamer_serviceDesc, srv)
@ -686,25 +932,25 @@ func _DarksideStreamer_SetMetaState_Handler(srv interface{}, ctx context.Context
return interceptor(ctx, in, info, handler)
}
func _DarksideStreamer_SetBlocks_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(DarksideStreamerServer).SetBlocks(&darksideStreamerSetBlocksServer{stream})
func _DarksideStreamer_StageBlocksStream_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(DarksideStreamerServer).StageBlocksStream(&darksideStreamerStageBlocksStreamServer{stream})
}
type DarksideStreamer_SetBlocksServer interface {
type DarksideStreamer_StageBlocksStreamServer interface {
SendAndClose(*Empty) error
Recv() (*DarksideBlock, error)
grpc.ServerStream
}
type darksideStreamerSetBlocksServer struct {
type darksideStreamerStageBlocksStreamServer struct {
grpc.ServerStream
}
func (x *darksideStreamerSetBlocksServer) SendAndClose(m *Empty) error {
func (x *darksideStreamerStageBlocksStreamServer) SendAndClose(m *Empty) error {
return x.ServerStream.SendMsg(m)
}
func (x *darksideStreamerSetBlocksServer) Recv() (*DarksideBlock, error) {
func (x *darksideStreamerStageBlocksStreamServer) Recv() (*DarksideBlock, error) {
m := new(DarksideBlock)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
@ -712,50 +958,86 @@ func (x *darksideStreamerSetBlocksServer) Recv() (*DarksideBlock, error) {
return m, nil
}
func _DarksideStreamer_SetBlocksURL_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
func _DarksideStreamer_StageBlocks_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DarksideBlocksURL)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DarksideStreamerServer).SetBlocksURL(ctx, in)
return srv.(DarksideStreamerServer).StageBlocks(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cash.z.wallet.sdk.rpc.DarksideStreamer/SetBlocksURL",
FullMethod: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocks",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DarksideStreamerServer).SetBlocksURL(ctx, req.(*DarksideBlocksURL))
return srv.(DarksideStreamerServer).StageBlocks(ctx, req.(*DarksideBlocksURL))
}
return interceptor(ctx, in, info, handler)
}
func _DarksideStreamer_SetTx_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(DarksideStreamerServer).SetTx(&darksideStreamerSetTxServer{stream})
func _DarksideStreamer_StageBlocksCreate_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DarksideEmptyBlocks)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DarksideStreamerServer).StageBlocksCreate(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksCreate",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DarksideStreamerServer).StageBlocksCreate(ctx, req.(*DarksideEmptyBlocks))
}
return interceptor(ctx, in, info, handler)
}
type DarksideStreamer_SetTxServer interface {
func _DarksideStreamer_StageTransactions_Handler(srv interface{}, stream grpc.ServerStream) error {
return srv.(DarksideStreamerServer).StageTransactions(&darksideStreamerStageTransactionsServer{stream})
}
type DarksideStreamer_StageTransactionsServer interface {
SendAndClose(*Empty) error
Recv() (*DarksideTx, error)
Recv() (*RawTransaction, error)
grpc.ServerStream
}
type darksideStreamerSetTxServer struct {
type darksideStreamerStageTransactionsServer struct {
grpc.ServerStream
}
func (x *darksideStreamerSetTxServer) SendAndClose(m *Empty) error {
func (x *darksideStreamerStageTransactionsServer) SendAndClose(m *Empty) error {
return x.ServerStream.SendMsg(m)
}
func (x *darksideStreamerSetTxServer) Recv() (*DarksideTx, error) {
m := new(DarksideTx)
func (x *darksideStreamerStageTransactionsServer) Recv() (*RawTransaction, error) {
m := new(RawTransaction)
if err := x.ServerStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func _DarksideStreamer_ApplyStaged_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(DarksideHeight)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DarksideStreamerServer).ApplyStaged(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ApplyStaged",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DarksideStreamerServer).ApplyStaged(ctx, req.(*DarksideHeight))
}
return interceptor(ctx, in, info, handler)
}
func _DarksideStreamer_GetIncomingTransactions_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(Empty)
if err := stream.RecvMsg(m); err != nil {
@ -777,6 +1059,42 @@ func (x *darksideStreamerGetIncomingTransactionsServer) Send(m *RawTransaction)
return x.ServerStream.SendMsg(m)
}
func _DarksideStreamer_ClearIncomingTransactions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DarksideStreamerServer).ClearIncomingTransactions(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearIncomingTransactions",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DarksideStreamerServer).ClearIncomingTransactions(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
func _DarksideStreamer_Reset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(Empty)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(DarksideStreamerServer).Reset(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cash.z.wallet.sdk.rpc.DarksideStreamer/Reset",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(DarksideStreamerServer).Reset(ctx, req.(*Empty))
}
return interceptor(ctx, in, info, handler)
}
var _DarksideStreamer_serviceDesc = grpc.ServiceDesc{
ServiceName: "cash.z.wallet.sdk.rpc.DarksideStreamer",
HandlerType: (*DarksideStreamerServer)(nil),
@ -786,19 +1104,35 @@ var _DarksideStreamer_serviceDesc = grpc.ServiceDesc{
Handler: _DarksideStreamer_SetMetaState_Handler,
},
{
MethodName: "SetBlocksURL",
Handler: _DarksideStreamer_SetBlocksURL_Handler,
MethodName: "StageBlocks",
Handler: _DarksideStreamer_StageBlocks_Handler,
},
{
MethodName: "StageBlocksCreate",
Handler: _DarksideStreamer_StageBlocksCreate_Handler,
},
{
MethodName: "ApplyStaged",
Handler: _DarksideStreamer_ApplyStaged_Handler,
},
{
MethodName: "ClearIncomingTransactions",
Handler: _DarksideStreamer_ClearIncomingTransactions_Handler,
},
{
MethodName: "Reset",
Handler: _DarksideStreamer_Reset_Handler,
},
},
Streams: []grpc.StreamDesc{
{
StreamName: "SetBlocks",
Handler: _DarksideStreamer_SetBlocks_Handler,
StreamName: "StageBlocksStream",
Handler: _DarksideStreamer_StageBlocksStream_Handler,
ClientStreams: true,
},
{
StreamName: "SetTx",
Handler: _DarksideStreamer_SetTx_Handler,
StreamName: "StageTransactions",
Handler: _DarksideStreamer_StageTransactions_Handler,
ClientStreams: true,
},
{

View File

@ -14,6 +14,7 @@ message DarksideMetaState {
string chainName = 3;
}
// A block is a hex-encoded string.
message DarksideBlock {
string block = 1;
}
@ -28,57 +29,79 @@ message DarksideTx {
string transaction = 2;
}
// This service implements the following rpc methods:
// SetMetaState
// SetBlocks
// SetBlocksURL
// SetTx
// GetIncomingTransactions
//
message DarksideHeight {
int32 height = 1;
}
message DarksideEmptyBlocks {
int32 height = 1;
int32 nonce = 2;
int32 count = 3;
}
// Darksidewalletd maintains two staging areas, blocks and transactions. The
// Stage*() gRPCs add items to the staging area; ApplyStaged() "applies" everything
// in the staging area to the working (operational) state that the mock zcashd
// serves; transactions are placed into their corresponding blocks (by height).
service DarksideStreamer {
// Set (some of) the values that should be returned by GetLightdInfo()
// Set (some of) the values returned by GetLightdInfo()
rpc SetMetaState(DarksideMetaState) returns (Empty) {}
// SetBlocks() replaces the specified range of blocks (gaps not allowed);
// for example, you can set blocks 1000-1006, do some tests, then set blocks
// 1003-1004. This preserves blocks 1000-1002, replaces blocks 1003-1004,
// and removes blocks 1005-1006. This can be used to simulate a chain reorg.
// Blocks are hex-encoded.
rpc SetBlocks(stream DarksideBlock) returns (Empty) {}
// StageBlocksStream accepts a list of blocks and saves them into the blocks
// staging area until ApplyStaged() is called; there is no immediate effect on
// the mock zcashd. Blocks are hex-encoded.
rpc StageBlocksStream(stream DarksideBlock) returns (Empty) {}
// This is the same as SetBlocks(), except the blocks are fetched
// StageBlocks is the same as StageBlocksStream() except the blocks are fetched
// from the given URL. Blocks are one per line, hex-encoded (not JSON).
// SetBlocksURL("file:testdata/darkside/init-blocks") is done at startup.
rpc SetBlocksURL(DarksideBlocksURL) returns (Empty) {}
rpc StageBlocks(DarksideBlocksURL) returns (Empty) {}
// SetTx() allows the test coordinator to submit a list of transactions and
// for each indicate in which block it should appear.
// For example,
// tx1, block=1001
// tx2, block=1002
// tx3, block=1002
// Then use Setblocks(1000-1005): block 1001 will include tx1 (plus
// any transactions were part of that block to begin with); tx2 and tx3
// will appear in block 1002. Blocks 1003-1005 will be returned as submitted.
//
// If you first set a range of blocks, then submit transactions within that
// range, it's too late for them to be included in those blocks. If blocks
// are resubmitted, then those transactions are included in those blocks.
//
// Calling GetTransaction() on tx1-3 will return those transactions, and
// GetTransaction() will also return any transactions that were part of
// the submitted blocks.
//
// Each call to SetTx() completely replaces the stored transaction set.
rpc SetTx(stream DarksideTx) returns (Empty) {}
// StageBlocksCreate is like the previous two, except it creates 'count'
// empty blocks at consecutive heights starting at height 'height'. The
// 'nonce' is part of the header, so it contributes to the block hash; this
// lets you create two fake blocks with the same transactions (or no
// transactions) and same height, with two different hashes.
rpc StageBlocksCreate(DarksideEmptyBlocks) returns (Empty) {}
// Calls to SendTransaction() are accepted and stored; this method returns
// all transactions that were previously submitted. This enables the
// following kind of test, for example:
// 1. wallet submits a transaction
// 2. Test coordinator retrives the transaction using this interface
// 3. Test coordinator submits the transaction using SetTx()
// 4. Darksidewalletd simulates the transaction appearing in a mined block
// StageTransactions stores the given transaction-height pairs in the
// staging area until ApplyStaged() is called. Note that these transactions
// are not returned by the production GetTransaction() gRPC until they
// appear in a "mined" block (contained in the active blockchain presented
// by the mock zcashd).
rpc StageTransactions(stream RawTransaction) returns (Empty) {}
// ApplyStaged iterates the list of blocks that were staged by the
// StageBlocks*() gRPCs, in the order they were staged, and "merges" each
// into the active, working blocks list that the mock zcashd is presenting
// to lightwalletd. The resulting working block list can't have gaps; if the
// working block range is 1000-1006, and the staged block range is 1003-1004,
// the resulting range is 1000-1004, with 1000-1002 unchanged, blocks
// 1003-1004 from the new range, and 1005-1006 dropped. After merging all
// blocks, ApplyStaged() appends staged transactions (in the order received)
// into each one's corresponding block. The staging area is then cleared.
//
// The argument specifies the latest block height that mock zcashd reports
// (i.e. what's returned by GetLatestBlock). Note that ApplyStaged() can
// also be used to simply advance the latest block height presented by mock
// zcashd. That is, there doesn't need to be anything in the staging area.
rpc ApplyStaged(DarksideHeight) returns (Empty) {}
// Calls to the production gRPC SendTransaction() store the transaction in
// a separate area (not the staging area); this method returns all transactions
// in this separate area, which is then cleared. The height returned
// with each transaction is -1 (invalid) since these transactions haven't
// been mined yet. The intention is that the transactions returned here can
// then, for example, be given to StageTransactions() to get them "mined"
// into a specified block on the next ApplyStaged().
rpc GetIncomingTransactions(Empty) returns (stream RawTransaction) {}
// Clear the incoming transaction pool.
rpc ClearIncomingTransactions(Empty) returns (Empty) {}
// Reset reverts all darksidewalletd state (active block range, latest height,
// staged blocks and transactions) and lightwalletd state (cache) to empty,
// the same as the initial state. This occurs synchronously and instantaneously;
// no reorg happens in lightwalletd. This is good to do before each independent
// test so that no state leaks from one test to another.
rpc Reset(Empty) returns (Empty) {};
}

View File

@ -12,14 +12,15 @@ package walletrpc
import (
context "context"
reflect "reflect"
sync "sync"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (