Merge 'upstream/master'
This commit is contained in:
commit
994e8a05f2
|
@ -9,3 +9,4 @@ lwd-api.html
|
||||||
*.orig
|
*.orig
|
||||||
__debug_bin
|
__debug_bin
|
||||||
.vscode
|
.vscode
|
||||||
|
frontend/unittestcache/
|
||||||
|
|
22
cmd/root.go
22
cmd/root.go
|
@ -60,6 +60,7 @@ var rootCmd = &cobra.Command{
|
||||||
GenCertVeryInsecure: viper.GetBool("gen-cert-very-insecure"),
|
GenCertVeryInsecure: viper.GetBool("gen-cert-very-insecure"),
|
||||||
DataDir: viper.GetString("data-dir"),
|
DataDir: viper.GetString("data-dir"),
|
||||||
Redownload: viper.GetBool("redownload"),
|
Redownload: viper.GetBool("redownload"),
|
||||||
|
SyncFromHeight: viper.GetInt("sync-from-height"),
|
||||||
PingEnable: viper.GetBool("ping-very-insecure"),
|
PingEnable: viper.GetBool("ping-very-insecure"),
|
||||||
Darkside: viper.GetBool("darkside-very-insecure"),
|
Darkside: viper.GetBool("darkside-very-insecure"),
|
||||||
DarksideTimeout: viper.GetUint64("darkside-timeout"),
|
DarksideTimeout: viper.GetUint64("darkside-timeout"),
|
||||||
|
@ -255,7 +256,11 @@ func startServer(opts *common.Options) error {
|
||||||
os.Stderr.WriteString(fmt.Sprintf("\n ** Can't create db directory: %s\n\n", dbPath))
|
os.Stderr.WriteString(fmt.Sprintf("\n ** Can't create db directory: %s\n\n", dbPath))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
cache := common.NewBlockCache(dbPath, chainName, saplingHeight, opts.Redownload)
|
syncFromHeight := opts.SyncFromHeight
|
||||||
|
if opts.Redownload {
|
||||||
|
syncFromHeight = 0
|
||||||
|
}
|
||||||
|
cache := common.NewBlockCache(dbPath, chainName, saplingHeight, syncFromHeight)
|
||||||
if !opts.Darkside {
|
if !opts.Darkside {
|
||||||
go common.BlockIngestor(cache, 0 /*loop forever*/)
|
go common.BlockIngestor(cache, 0 /*loop forever*/)
|
||||||
} else {
|
} else {
|
||||||
|
@ -286,10 +291,6 @@ func startServer(opts *common.Options) error {
|
||||||
// Initialize price fetcher
|
// Initialize price fetcher
|
||||||
common.StartPriceFetcher(dbPath, chainName)
|
common.StartPriceFetcher(dbPath, chainName)
|
||||||
|
|
||||||
// Initialize mempool monitor
|
|
||||||
exitMempool := make(chan bool)
|
|
||||||
common.StartMempoolMonitor(cache, exitMempool)
|
|
||||||
|
|
||||||
// Start listening
|
// Start listening
|
||||||
listener, err := net.Listen("tcp", opts.GRPCBindAddr)
|
listener, err := net.Listen("tcp", opts.GRPCBindAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -309,7 +310,6 @@ func startServer(opts *common.Options) error {
|
||||||
"signal": s.String(),
|
"signal": s.String(),
|
||||||
}).Info("caught signal, stopping gRPC server")
|
}).Info("caught signal, stopping gRPC server")
|
||||||
|
|
||||||
exitMempool <- true
|
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -350,6 +350,7 @@ func init() {
|
||||||
rootCmd.Flags().Bool("no-tls-very-insecure", false, "run without the required TLS certificate, only for debugging, DO NOT use in production")
|
rootCmd.Flags().Bool("no-tls-very-insecure", false, "run without the required TLS certificate, only for debugging, DO NOT use in production")
|
||||||
rootCmd.Flags().Bool("gen-cert-very-insecure", false, "run with self-signed TLS certificate, only for debugging, DO NOT use in production")
|
rootCmd.Flags().Bool("gen-cert-very-insecure", false, "run with self-signed TLS certificate, only for debugging, DO NOT use in production")
|
||||||
rootCmd.Flags().Bool("redownload", false, "re-fetch all blocks from zcashd; reinitialize local cache files")
|
rootCmd.Flags().Bool("redownload", false, "re-fetch all blocks from zcashd; reinitialize local cache files")
|
||||||
|
rootCmd.Flags().Int("sync-from-height", -1, "re-fetch blocks from zcashd start at this height")
|
||||||
rootCmd.Flags().String("data-dir", "/var/lib/lightwalletd", "data directory (such as db)")
|
rootCmd.Flags().String("data-dir", "/var/lib/lightwalletd", "data directory (such as db)")
|
||||||
rootCmd.Flags().Bool("ping-very-insecure", false, "allow Ping GRPC for testing")
|
rootCmd.Flags().Bool("ping-very-insecure", false, "allow Ping GRPC for testing")
|
||||||
rootCmd.Flags().Bool("darkside-very-insecure", false, "run with GRPC-controllable mock zcashd for integration testing (shuts down after 30 minutes)")
|
rootCmd.Flags().Bool("darkside-very-insecure", false, "run with GRPC-controllable mock zcashd for integration testing (shuts down after 30 minutes)")
|
||||||
|
@ -381,6 +382,8 @@ func init() {
|
||||||
viper.SetDefault("gen-cert-very-insecure", false)
|
viper.SetDefault("gen-cert-very-insecure", false)
|
||||||
viper.BindPFlag("redownload", rootCmd.Flags().Lookup("redownload"))
|
viper.BindPFlag("redownload", rootCmd.Flags().Lookup("redownload"))
|
||||||
viper.SetDefault("redownload", false)
|
viper.SetDefault("redownload", false)
|
||||||
|
viper.BindPFlag("sync-from-height", rootCmd.Flags().Lookup("sync-from-height"))
|
||||||
|
viper.SetDefault("sync-from-height", -1)
|
||||||
viper.BindPFlag("data-dir", rootCmd.Flags().Lookup("data-dir"))
|
viper.BindPFlag("data-dir", rootCmd.Flags().Lookup("data-dir"))
|
||||||
viper.SetDefault("data-dir", "/var/lib/lightwalletd")
|
viper.SetDefault("data-dir", "/var/lib/lightwalletd")
|
||||||
viper.BindPFlag("ping-very-insecure", rootCmd.Flags().Lookup("ping-very-insecure"))
|
viper.BindPFlag("ping-very-insecure", rootCmd.Flags().Lookup("ping-very-insecure"))
|
||||||
|
@ -409,8 +412,9 @@ func init() {
|
||||||
|
|
||||||
logrus.RegisterExitHandler(onexit)
|
logrus.RegisterExitHandler(onexit)
|
||||||
|
|
||||||
// Indirect function for test mocking (so unit tests can talk to stub functions)
|
// Indirect functions for test mocking (so unit tests can talk to stub functions)
|
||||||
common.Sleep = time.Sleep
|
common.Time.Sleep = time.Sleep
|
||||||
|
common.Time.Now = time.Now
|
||||||
}
|
}
|
||||||
|
|
||||||
// initConfig reads in config file and ENV variables if set.
|
// initConfig reads in config file and ENV variables if set.
|
||||||
|
@ -421,7 +425,7 @@ func initConfig() {
|
||||||
} else {
|
} else {
|
||||||
// Look in the current directory for a configuration file
|
// Look in the current directory for a configuration file
|
||||||
viper.AddConfigPath(".")
|
viper.AddConfigPath(".")
|
||||||
// Viper auto appends extention to this config name
|
// Viper auto appends extension to this config name
|
||||||
// For example, lightwalletd.yml
|
// For example, lightwalletd.yml
|
||||||
viper.SetConfigName("lightwalletd")
|
viper.SetConfigName("lightwalletd")
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,12 +51,12 @@ func (c *BlockCache) GetLatestHash() []byte {
|
||||||
return c.latestHash
|
return c.latestHash
|
||||||
}
|
}
|
||||||
|
|
||||||
// HashMismatch indicates if the given prev-hash doesn't match the most recent block's hash
|
// HashMatch indicates if the given prev-hash matches the most recent block's hash
|
||||||
// so reorgs can be detected.
|
// so reorgs can be detected.
|
||||||
func (c *BlockCache) HashMismatch(prevhash []byte) bool {
|
func (c *BlockCache) HashMatch(prevhash []byte) bool {
|
||||||
c.mutex.RLock()
|
c.mutex.RLock()
|
||||||
defer c.mutex.RUnlock()
|
defer c.mutex.RUnlock()
|
||||||
return c.latestHash != nil && !bytes.Equal(c.latestHash, prevhash)
|
return c.latestHash == nil || bytes.Equal(c.latestHash, prevhash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make the block at the given height the lowest height that we don't have.
|
// Make the block at the given height the lowest height that we don't have.
|
||||||
|
@ -191,7 +191,8 @@ func (c *BlockCache) Reset(startHeight int) {
|
||||||
|
|
||||||
// NewBlockCache returns an instance of a block cache object.
|
// NewBlockCache returns an instance of a block cache object.
|
||||||
// (No locking here, we assume this is single-threaded.)
|
// (No locking here, we assume this is single-threaded.)
|
||||||
func NewBlockCache(dbPath string, chainName string, startHeight int, redownload bool) *BlockCache {
|
// syncFromHeight < 0 means latest (tip) height.
|
||||||
|
func NewBlockCache(dbPath string, chainName string, startHeight int, syncFromHeight int) *BlockCache {
|
||||||
c := &BlockCache{}
|
c := &BlockCache{}
|
||||||
c.firstBlock = startHeight
|
c.firstBlock = startHeight
|
||||||
c.nextBlock = startHeight
|
c.nextBlock = startHeight
|
||||||
|
@ -208,18 +209,20 @@ func NewBlockCache(dbPath string, chainName string, startHeight int, redownload
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log.Fatal("open ", c.lengthsName, " failed: ", err)
|
Log.Fatal("open ", c.lengthsName, " failed: ", err)
|
||||||
}
|
}
|
||||||
if redownload {
|
|
||||||
if err := c.lengthsFile.Truncate(0); err != nil {
|
|
||||||
Log.Fatal("truncate lengths file failed: ", err)
|
|
||||||
}
|
|
||||||
if err := c.blocksFile.Truncate(0); err != nil {
|
|
||||||
Log.Fatal("truncate blocks file failed: ", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lengths, err := ioutil.ReadFile(c.lengthsName)
|
lengths, err := ioutil.ReadFile(c.lengthsName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log.Fatal("read ", c.lengthsName, " failed: ", err)
|
Log.Fatal("read ", c.lengthsName, " failed: ", err)
|
||||||
}
|
}
|
||||||
|
// 4 bytes per lengths[] value (block length)
|
||||||
|
if syncFromHeight >= 0 {
|
||||||
|
if syncFromHeight < startHeight {
|
||||||
|
syncFromHeight = startHeight
|
||||||
|
}
|
||||||
|
if (syncFromHeight-startHeight)*4 < len(lengths) {
|
||||||
|
// discard the entries at and beyond (newer than) the specified height
|
||||||
|
lengths = lengths[:(syncFromHeight-startHeight)*4]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The last entry in starts[] is where to write the next block.
|
// The last entry in starts[] is where to write the next block.
|
||||||
var offset int64
|
var offset int64
|
||||||
|
|
|
@ -58,7 +58,7 @@ func TestCache(t *testing.T) {
|
||||||
|
|
||||||
// Pretend Sapling starts at 289460.
|
// Pretend Sapling starts at 289460.
|
||||||
os.RemoveAll(unitTestPath)
|
os.RemoveAll(unitTestPath)
|
||||||
cache = NewBlockCache(unitTestPath, unitTestChain, 289460, true)
|
cache = NewBlockCache(unitTestPath, unitTestChain, 289460, 0)
|
||||||
|
|
||||||
// Initially cache is empty.
|
// Initially cache is empty.
|
||||||
if cache.GetLatestHeight() != -1 {
|
if cache.GetLatestHeight() != -1 {
|
||||||
|
@ -75,7 +75,7 @@ func TestCache(t *testing.T) {
|
||||||
fillCache(t)
|
fillCache(t)
|
||||||
|
|
||||||
// Simulate a restart to ensure the db files are read correctly.
|
// Simulate a restart to ensure the db files are read correctly.
|
||||||
cache = NewBlockCache(unitTestPath, unitTestChain, 289460, false)
|
cache = NewBlockCache(unitTestPath, unitTestChain, 289460, -1)
|
||||||
|
|
||||||
// Should still be 6 blocks.
|
// Should still be 6 blocks.
|
||||||
if cache.nextBlock != 289466 {
|
if cache.nextBlock != 289466 {
|
||||||
|
|
201
common/common.go
201
common/common.go
|
@ -42,6 +42,7 @@ type Options struct {
|
||||||
NoTLSVeryInsecure bool `json:"no_tls_very_insecure,omitempty"`
|
NoTLSVeryInsecure bool `json:"no_tls_very_insecure,omitempty"`
|
||||||
GenCertVeryInsecure bool `json:"gen_cert_very_insecure,omitempty"`
|
GenCertVeryInsecure bool `json:"gen_cert_very_insecure,omitempty"`
|
||||||
Redownload bool `json:"redownload"`
|
Redownload bool `json:"redownload"`
|
||||||
|
SyncFromHeight int `json:"sync_from_height"`
|
||||||
DataDir string `json:"data_dir"`
|
DataDir string `json:"data_dir"`
|
||||||
PingEnable bool `json:"ping_enable"`
|
PingEnable bool `json:"ping_enable"`
|
||||||
Darkside bool `json:"darkside"`
|
Darkside bool `json:"darkside"`
|
||||||
|
@ -53,10 +54,16 @@ type Options struct {
|
||||||
// in unit tests it points to a function to mock RPCs to zcashd.
|
// in unit tests it points to a function to mock RPCs to zcashd.
|
||||||
var RawRequest func(method string, params []json.RawMessage) (json.RawMessage, error)
|
var RawRequest func(method string, params []json.RawMessage) (json.RawMessage, error)
|
||||||
|
|
||||||
// Sleep allows a request to time.Sleep() to be mocked for testing;
|
// Time allows time-related functions to be mocked for testing,
|
||||||
// in production, it points to the standard library time.Sleep();
|
// so that tests can be deterministic and so they don't require
|
||||||
// in unit tests it points to a mock function.
|
// real time to elapse. In production, these point to the standard
|
||||||
var Sleep func(d time.Duration)
|
// library `time` functions; in unit tests they point to mock
|
||||||
|
// functions (set by the specific test as required).
|
||||||
|
// More functions can be added later.
|
||||||
|
var Time struct {
|
||||||
|
Sleep func(d time.Duration)
|
||||||
|
Now func() time.Time
|
||||||
|
}
|
||||||
|
|
||||||
// Log as a global variable simplifies logging
|
// Log as a global variable simplifies logging
|
||||||
var Log *logrus.Entry
|
var Log *logrus.Entry
|
||||||
|
@ -109,9 +116,16 @@ type (
|
||||||
}
|
}
|
||||||
SkipHash string
|
SkipHash string
|
||||||
}
|
}
|
||||||
|
Orchard struct {
|
||||||
|
Commitments struct {
|
||||||
|
FinalState string
|
||||||
|
}
|
||||||
|
SkipHash string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// zcashd rpc "getrawtransaction"
|
// zcashd rpc "getrawtransaction txid 1" (1 means verbose), there are
|
||||||
|
// many more fields but these are the only ones we current need.
|
||||||
ZcashdRpcReplyGetrawtransaction struct {
|
ZcashdRpcReplyGetrawtransaction struct {
|
||||||
Hex string
|
Hex string
|
||||||
Height int
|
Height int
|
||||||
|
@ -129,7 +143,7 @@ type (
|
||||||
ZcashdRpcRequestGetaddressutxos struct {
|
ZcashdRpcRequestGetaddressutxos struct {
|
||||||
Addresses []string `json:"addresses"`
|
Addresses []string `json:"addresses"`
|
||||||
}
|
}
|
||||||
ZcashdRpcReplyGetaddressutxos []struct {
|
ZcashdRpcReplyGetaddressutxos struct {
|
||||||
Address string
|
Address string
|
||||||
Txid string
|
Txid string
|
||||||
OutputIndex int64
|
OutputIndex int64
|
||||||
|
@ -137,6 +151,11 @@ type (
|
||||||
Satoshis uint64
|
Satoshis uint64
|
||||||
Height int
|
Height int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reply to getblock verbose=1 (json includes txid list)
|
||||||
|
ZcashRpcReplyGetblock1 struct {
|
||||||
|
Tx []string
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// FirstRPC tests that we can successfully reach zcashd through the RPC
|
// FirstRPC tests that we can successfully reach zcashd through the RPC
|
||||||
|
@ -166,7 +185,7 @@ func FirstRPC() {
|
||||||
"error": rpcErr.Error(),
|
"error": rpcErr.Error(),
|
||||||
"retry": retryCount,
|
"retry": retryCount,
|
||||||
}).Warn("error with getblockchaininfo rpc, retrying...")
|
}).Warn("error with getblockchaininfo rpc, retrying...")
|
||||||
Sleep(time.Duration(10+retryCount*5) * time.Second) // backoff
|
Time.Sleep(time.Duration(10+retryCount*5) * time.Second) // backoff
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +259,7 @@ func getBlockFromRPC(height int) (*walletrpc.CompactBlock, error) {
|
||||||
params := make([]json.RawMessage, 2)
|
params := make([]json.RawMessage, 2)
|
||||||
heightJSON, err := json.Marshal(strconv.Itoa(height))
|
heightJSON, err := json.Marshal(strconv.Itoa(height))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "error marshaling height")
|
Log.Fatal("getBlockFromRPC bad height argument", height, err)
|
||||||
}
|
}
|
||||||
params[0] = heightJSON
|
params[0] = heightJSON
|
||||||
params[1] = json.RawMessage("0") // non-verbose (raw hex)
|
params[1] = json.RawMessage("0") // non-verbose (raw hex)
|
||||||
|
@ -279,6 +298,31 @@ func getBlockFromRPC(height int) (*walletrpc.CompactBlock, error) {
|
||||||
return nil, errors.New("received unexpected height block")
|
return nil, errors.New("received unexpected height block")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// `block.ParseFromSlice` correctly parses blocks containing v5 transactions, but
|
||||||
|
// incorrectly computes the IDs of the v5 transactions. We temporarily paper over this
|
||||||
|
// bug by fetching the correct txids via a second getblock RPC call.
|
||||||
|
// https://github.com/zcash/lightwalletd/issues/392
|
||||||
|
{
|
||||||
|
params[1] = json.RawMessage("1") // JSON with list of txids
|
||||||
|
result, rpcErr := RawRequest("getblock", params)
|
||||||
|
if rpcErr != nil {
|
||||||
|
return nil, errors.Wrap(rpcErr, "error requesting verbose block")
|
||||||
|
}
|
||||||
|
var block1 ZcashRpcReplyGetblock1
|
||||||
|
err = json.Unmarshal(result, &block1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for i, t := range block.Transactions() {
|
||||||
|
txid, err := hex.DecodeString(block1.Tx[i])
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "error decoding getblock txid")
|
||||||
|
}
|
||||||
|
// convert from big-endian
|
||||||
|
t.SetTxID(parser.Reverse(txid))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return block.ToCompact(), nil
|
return block.ToCompact(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -303,11 +347,8 @@ func stopIngestor() {
|
||||||
// BlockIngestor runs as a goroutine and polls zcashd for new blocks, adding them
|
// BlockIngestor runs as a goroutine and polls zcashd for new blocks, adding them
|
||||||
// to the cache. The repetition count, rep, is nonzero only for unit-testing.
|
// to the cache. The repetition count, rep, is nonzero only for unit-testing.
|
||||||
func BlockIngestor(c *BlockCache, rep int) {
|
func BlockIngestor(c *BlockCache, rep int) {
|
||||||
lastLog := time.Now()
|
lastLog := Time.Now()
|
||||||
reorgCount := 0
|
|
||||||
lastHeightLogged := 0
|
lastHeightLogged := 0
|
||||||
retryCount := 0
|
|
||||||
wait := true
|
|
||||||
|
|
||||||
// Start listening for new blocks
|
// Start listening for new blocks
|
||||||
for i := 0; rep == 0 || i < rep; i++ {
|
for i := 0; rep == 0 || i < rep; i++ {
|
||||||
|
@ -318,110 +359,60 @@ func BlockIngestor(c *BlockCache, rep int) {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
height := c.GetNextHeight()
|
result, err := RawRequest("getbestblockhash", []json.RawMessage{})
|
||||||
block, err := getBlockFromRPC(height)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Log.WithFields(logrus.Fields{
|
Log.WithFields(logrus.Fields{
|
||||||
"height": height,
|
"error": err,
|
||||||
"error": err,
|
}).Fatal("error zcashd getbestblockhash rpc")
|
||||||
}).Warn("error zcashd getblock rpc")
|
}
|
||||||
retryCount++
|
var hashHex string
|
||||||
if retryCount > 10 {
|
err = json.Unmarshal(result, &hashHex)
|
||||||
Log.WithFields(logrus.Fields{
|
if err != nil {
|
||||||
"timeouts": retryCount,
|
Log.Fatal("bad getbestblockhash return:", err, result)
|
||||||
}).Fatal("unable to issue RPC call to zcashd node")
|
}
|
||||||
}
|
lastBestBlockHash := []byte{}
|
||||||
// Delay then retry the same height.
|
lastBestBlockHash, err = hex.DecodeString(hashHex)
|
||||||
|
if err != nil {
|
||||||
|
Log.Fatal("error decoding getbestblockhash", err, hashHex)
|
||||||
|
}
|
||||||
|
|
||||||
|
height := c.GetNextHeight()
|
||||||
|
if string(lastBestBlockHash) == string(parser.Reverse(c.GetLatestHash())) {
|
||||||
|
// Synced
|
||||||
c.Sync()
|
c.Sync()
|
||||||
Sleep(10 * time.Second)
|
if lastHeightLogged != height-1 {
|
||||||
wait = true
|
lastHeightLogged = height - 1
|
||||||
|
Log.Info("Waiting for block: ", height)
|
||||||
|
}
|
||||||
|
Time.Sleep(2 * time.Second)
|
||||||
|
lastLog = Time.Now()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
retryCount = 0
|
var block *walletrpc.CompactBlock
|
||||||
if block == nil {
|
block, err = getBlockFromRPC(height)
|
||||||
// No block at this height.
|
if err != nil {
|
||||||
if height == c.GetFirstHeight() {
|
Log.Fatal("getblock failed, will retry", err)
|
||||||
Log.Info("Waiting for zcashd height to reach Sapling activation height ",
|
|
||||||
"(", c.GetFirstHeight(), ")...")
|
|
||||||
reorgCount = 0
|
|
||||||
Sleep(20 * time.Second)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the current top block to see if there's a hash mismatch (i.e., a 1-block reorg)
|
|
||||||
curhash, err := getBestBlockHash()
|
|
||||||
if err != nil {
|
|
||||||
Log.WithFields(logrus.Fields{
|
|
||||||
"height": height,
|
|
||||||
"error": err,
|
|
||||||
}).Warn("error zcashd getblock rpc")
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if c.HashMismatch(curhash) {
|
|
||||||
// Current block has a hash mismatch
|
|
||||||
Log.WithFields(logrus.Fields{
|
|
||||||
"height": height - 1,
|
|
||||||
"hash": displayHash(curhash),
|
|
||||||
"phash": displayHash(c.GetLatestHash()),
|
|
||||||
"reorg": reorgCount,
|
|
||||||
}).Warn("REORG/Current Block")
|
|
||||||
c.Reorg(height - 1)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if wait {
|
|
||||||
// Wait a bit then retry the same height.
|
|
||||||
c.Sync()
|
|
||||||
if lastHeightLogged+1 != height {
|
|
||||||
Log.Info("Ingestor waiting for block: ", height)
|
|
||||||
lastHeightLogged = height - 1
|
|
||||||
}
|
|
||||||
Sleep(2 * time.Second)
|
|
||||||
wait = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if block == nil || c.HashMismatch(block.PrevHash) {
|
if block != nil && c.HashMatch(block.PrevHash) {
|
||||||
// This may not be a reorg; it may be we're at the tip
|
if err = c.Add(height, block); err != nil {
|
||||||
// and there's no new block yet, but we want to back up
|
Log.Fatal("Cache add failed:", err)
|
||||||
// so we detect a reorg in which the new chain is the
|
|
||||||
// same length or shorter.
|
|
||||||
reorgCount++
|
|
||||||
if reorgCount > 100 {
|
|
||||||
Log.Fatal("Reorg exceeded max of 100 blocks! Help!")
|
|
||||||
}
|
}
|
||||||
// Print the hash of the block that is getting reorg-ed away
|
// Don't log these too often.
|
||||||
// as 'phash', not the prevhash of the block we just received.
|
if DarksideEnabled || Time.Now().Sub(lastLog).Seconds() >= 4 {
|
||||||
if block != nil {
|
lastLog = Time.Now()
|
||||||
Log.WithFields(logrus.Fields{
|
Log.Info("Adding block to cache ", height, " ", displayHash(block.Hash))
|
||||||
"height": height,
|
|
||||||
"hash": displayHash(block.Hash),
|
|
||||||
"phash": displayHash(c.GetLatestHash()),
|
|
||||||
"reorg": reorgCount,
|
|
||||||
}).Warn("REORG")
|
|
||||||
} else if reorgCount > 1 {
|
|
||||||
Log.WithFields(logrus.Fields{
|
|
||||||
"height": height,
|
|
||||||
"phash": displayHash(c.GetLatestHash()),
|
|
||||||
"reorg": reorgCount,
|
|
||||||
}).Warn("REORG")
|
|
||||||
}
|
}
|
||||||
// Try backing up
|
|
||||||
c.Reorg(height - 1)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// We have a valid block to add.
|
if height == c.GetFirstHeight() {
|
||||||
wait = true
|
c.Sync()
|
||||||
reorgCount = 0
|
Log.Info("Waiting for zcashd height to reach Sapling activation height ",
|
||||||
if err := c.Add(height, block); err != nil {
|
"(", c.GetFirstHeight(), ")...")
|
||||||
Log.Fatal("Cache add failed:", err)
|
Time.Sleep(20 * time.Second)
|
||||||
}
|
return
|
||||||
// Don't log these too often.
|
|
||||||
if time.Since(lastLog).Seconds() >= 4 && c.GetNextHeight() == height+1 && height != lastHeightLogged {
|
|
||||||
lastLog = time.Now()
|
|
||||||
lastHeightLogged = height
|
|
||||||
Log.Info("Ingestor adding block to cache: ", height)
|
|
||||||
}
|
}
|
||||||
|
Log.Info("REORG: dropping block ", height-1, " ", displayHash(c.GetLatestHash()))
|
||||||
|
c.Reorg(height - 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -33,6 +34,8 @@ var (
|
||||||
logger = logrus.New()
|
logger = logrus.New()
|
||||||
|
|
||||||
blocks [][]byte // four test blocks
|
blocks [][]byte // four test blocks
|
||||||
|
|
||||||
|
testcache *BlockCache
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestMain does common setup that's shared across multiple tests
|
// TestMain does common setup that's shared across multiple tests
|
||||||
|
@ -59,6 +62,7 @@ func TestMain(m *testing.M) {
|
||||||
blockJSON, _ := json.Marshal(scan.Text())
|
blockJSON, _ := json.Marshal(scan.Text())
|
||||||
blocks = append(blocks, blockJSON)
|
blocks = append(blocks, blockJSON)
|
||||||
}
|
}
|
||||||
|
testcache = NewBlockCache(unitTestPath, unitTestChain, 380640, 0)
|
||||||
|
|
||||||
// Setup is done; run all tests.
|
// Setup is done; run all tests.
|
||||||
exitcode := m.Run()
|
exitcode := m.Run()
|
||||||
|
@ -77,6 +81,10 @@ func sleepStub(d time.Duration) {
|
||||||
sleepCount++
|
sleepCount++
|
||||||
sleepDuration += d
|
sleepDuration += d
|
||||||
}
|
}
|
||||||
|
func nowStub() time.Time {
|
||||||
|
start := time.Time{}
|
||||||
|
return start.Add(sleepDuration)
|
||||||
|
}
|
||||||
|
|
||||||
// ------------------------------------------ GetLightdInfo()
|
// ------------------------------------------ GetLightdInfo()
|
||||||
|
|
||||||
|
@ -110,7 +118,7 @@ func getLightdInfoStub(method string, params []json.RawMessage) (json.RawMessage
|
||||||
func TestGetLightdInfo(t *testing.T) {
|
func TestGetLightdInfo(t *testing.T) {
|
||||||
testT = t
|
testT = t
|
||||||
RawRequest = getLightdInfoStub
|
RawRequest = getLightdInfoStub
|
||||||
Sleep = sleepStub
|
Time.Sleep = sleepStub
|
||||||
// This calls the getblockchaininfo rpc just to establish connectivity with zcashd
|
// This calls the getblockchaininfo rpc just to establish connectivity with zcashd
|
||||||
FirstRPC()
|
FirstRPC()
|
||||||
|
|
||||||
|
@ -155,8 +163,217 @@ func TestGetLightdInfo(t *testing.T) {
|
||||||
|
|
||||||
// ------------------------------------------ BlockIngestor()
|
// ------------------------------------------ BlockIngestor()
|
||||||
|
|
||||||
|
func checkSleepMethod(count int, duration time.Duration, expected string, method string) {
|
||||||
|
if sleepCount != count {
|
||||||
|
testT.Fatal("unexpected sleep count")
|
||||||
|
}
|
||||||
|
if sleepDuration != duration*time.Second {
|
||||||
|
testT.Fatal("unexpected sleep duration")
|
||||||
|
}
|
||||||
|
if method != expected {
|
||||||
|
testT.Error("unexpected method")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// There are four test blocks, 0..3
|
// There are four test blocks, 0..3
|
||||||
|
func blockIngestorStub(method string, params []json.RawMessage) (json.RawMessage, error) {
|
||||||
|
step++
|
||||||
|
// request the first two blocks very quickly (syncing),
|
||||||
|
// then next block isn't yet available
|
||||||
|
switch step {
|
||||||
|
case 1:
|
||||||
|
checkSleepMethod(0, 0, "getbestblockhash", method)
|
||||||
|
// This hash doesn't matter, won't match anything
|
||||||
|
r, _ := json.Marshal("010101")
|
||||||
|
return r, nil
|
||||||
|
case 2:
|
||||||
|
checkSleepMethod(0, 0, "getblock", method)
|
||||||
|
var height string
|
||||||
|
err := json.Unmarshal(params[0], &height)
|
||||||
|
if err != nil {
|
||||||
|
testT.Fatal("could not unmarshal height")
|
||||||
|
}
|
||||||
|
if height != "380640" {
|
||||||
|
testT.Fatal("incorrect height requested")
|
||||||
|
}
|
||||||
|
// height 380640
|
||||||
|
return blocks[0], nil
|
||||||
|
case 3:
|
||||||
|
checkSleepMethod(0, 0, "getbestblockhash", method)
|
||||||
|
// This hash doesn't matter, won't match anything
|
||||||
|
r, _ := json.Marshal("010101")
|
||||||
|
return r, nil
|
||||||
|
case 4:
|
||||||
|
checkSleepMethod(0, 0, "getblock", method)
|
||||||
|
var height string
|
||||||
|
err := json.Unmarshal(params[0], &height)
|
||||||
|
if err != nil {
|
||||||
|
testT.Fatal("could not unmarshal height")
|
||||||
|
}
|
||||||
|
if height != "380641" {
|
||||||
|
testT.Fatal("incorrect height requested")
|
||||||
|
}
|
||||||
|
// height 380641
|
||||||
|
return blocks[1], nil
|
||||||
|
case 5:
|
||||||
|
// Return the expected block hash, so we're synced, should
|
||||||
|
// then sleep for 2 seconds, then another getbestblockhash
|
||||||
|
checkSleepMethod(0, 0, "getbestblockhash", method)
|
||||||
|
r, _ := json.Marshal(displayHash(testcache.GetLatestHash()))
|
||||||
|
return r, nil
|
||||||
|
case 6:
|
||||||
|
// Simulate still no new block, still synced, should
|
||||||
|
// sleep for 2 seconds, then another getbestblockhash
|
||||||
|
checkSleepMethod(1, 2, "getbestblockhash", method)
|
||||||
|
r, _ := json.Marshal(displayHash(testcache.GetLatestHash()))
|
||||||
|
return r, nil
|
||||||
|
case 7:
|
||||||
|
// Simulate new block (any non-matching hash will do)
|
||||||
|
checkSleepMethod(2, 4, "getbestblockhash", method)
|
||||||
|
r, _ := json.Marshal("aabb")
|
||||||
|
return r, nil
|
||||||
|
case 8:
|
||||||
|
checkSleepMethod(2, 4, "getblock", method)
|
||||||
|
var height string
|
||||||
|
err := json.Unmarshal(params[0], &height)
|
||||||
|
if err != nil {
|
||||||
|
testT.Fatal("could not unmarshal height")
|
||||||
|
}
|
||||||
|
if height != "380642" {
|
||||||
|
testT.Fatal("incorrect height requested")
|
||||||
|
}
|
||||||
|
// height 380642
|
||||||
|
return blocks[2], nil
|
||||||
|
case 9:
|
||||||
|
// Simulate still no new block, still synced, should
|
||||||
|
// sleep for 2 seconds, then another getbestblockhash
|
||||||
|
checkSleepMethod(2, 4, "getbestblockhash", method)
|
||||||
|
r, _ := json.Marshal(displayHash(testcache.GetLatestHash()))
|
||||||
|
return r, nil
|
||||||
|
case 10:
|
||||||
|
// There are 3 blocks in the cache (380640-642), so let's
|
||||||
|
// simulate a 1-block reorg, new version (replacement) of 380642
|
||||||
|
checkSleepMethod(3, 6, "getbestblockhash", method)
|
||||||
|
// hash doesn't matter, just something that doesn't match
|
||||||
|
r, _ := json.Marshal("4545")
|
||||||
|
return r, nil
|
||||||
|
case 11:
|
||||||
|
// It thinks there may simply be a new block, but we'll say
|
||||||
|
// there is no block at this height (380642 was replaced).
|
||||||
|
checkSleepMethod(3, 6, "getblock", method)
|
||||||
|
var height string
|
||||||
|
err := json.Unmarshal(params[0], &height)
|
||||||
|
if err != nil {
|
||||||
|
testT.Fatal("could not unmarshal height")
|
||||||
|
}
|
||||||
|
if height != "380643" {
|
||||||
|
testT.Fatal("incorrect height requested")
|
||||||
|
}
|
||||||
|
return nil, errors.New("-8: Block height out of range")
|
||||||
|
case 12:
|
||||||
|
// It will re-ask the best hash (let's make no change)
|
||||||
|
checkSleepMethod(3, 6, "getbestblockhash", method)
|
||||||
|
// hash doesn't matter, just something that doesn't match
|
||||||
|
r, _ := json.Marshal("4545")
|
||||||
|
return r, nil
|
||||||
|
case 13:
|
||||||
|
// It should have backed up one block
|
||||||
|
checkSleepMethod(3, 6, "getblock", method)
|
||||||
|
var height string
|
||||||
|
err := json.Unmarshal(params[0], &height)
|
||||||
|
if err != nil {
|
||||||
|
testT.Fatal("could not unmarshal height")
|
||||||
|
}
|
||||||
|
if height != "380642" {
|
||||||
|
testT.Fatal("incorrect height requested")
|
||||||
|
}
|
||||||
|
// height 380642
|
||||||
|
return blocks[2], nil
|
||||||
|
case 14:
|
||||||
|
// We're back to the same state as case 9, and this time
|
||||||
|
// we'll make it back up 2 blocks (rather than one)
|
||||||
|
checkSleepMethod(3, 6, "getbestblockhash", method) // XXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXX
|
||||||
|
// hash doesn't matter, just something that doesn't match
|
||||||
|
r, _ := json.Marshal("5656")
|
||||||
|
return r, nil
|
||||||
|
case 15:
|
||||||
|
// It thinks there may simply be a new block, but we'll say
|
||||||
|
// there is no block at this height (380642 was replaced).
|
||||||
|
checkSleepMethod(3, 6, "getblock", method)
|
||||||
|
var height string
|
||||||
|
err := json.Unmarshal(params[0], &height)
|
||||||
|
if err != nil {
|
||||||
|
testT.Fatal("could not unmarshal height")
|
||||||
|
}
|
||||||
|
if height != "380643" {
|
||||||
|
testT.Fatal("incorrect height requested")
|
||||||
|
}
|
||||||
|
return nil, errors.New("-8: Block height out of range")
|
||||||
|
case 16:
|
||||||
|
checkSleepMethod(3, 6, "getbestblockhash", method)
|
||||||
|
// hash doesn't matter, just something that doesn't match
|
||||||
|
r, _ := json.Marshal("5656")
|
||||||
|
return r, nil
|
||||||
|
case 17:
|
||||||
|
// Like case 13, it should have backed up one block, but
|
||||||
|
// this time we'll make it back up one more
|
||||||
|
checkSleepMethod(3, 6, "getblock", method)
|
||||||
|
var height string
|
||||||
|
err := json.Unmarshal(params[0], &height)
|
||||||
|
if err != nil {
|
||||||
|
testT.Fatal("could not unmarshal height")
|
||||||
|
}
|
||||||
|
if height != "380642" {
|
||||||
|
testT.Fatal("incorrect height requested")
|
||||||
|
}
|
||||||
|
return nil, errors.New("-8: Block height out of range")
|
||||||
|
case 18:
|
||||||
|
checkSleepMethod(3, 6, "getbestblockhash", method)
|
||||||
|
// hash doesn't matter, just something that doesn't match
|
||||||
|
r, _ := json.Marshal("5656")
|
||||||
|
return r, nil
|
||||||
|
case 19:
|
||||||
|
// It should have backed up one more
|
||||||
|
checkSleepMethod(3, 6, "getblock", method)
|
||||||
|
var height string
|
||||||
|
err := json.Unmarshal(params[0], &height)
|
||||||
|
if err != nil {
|
||||||
|
testT.Fatal("could not unmarshal height")
|
||||||
|
}
|
||||||
|
if height != "380641" {
|
||||||
|
testT.Fatal("incorrect height requested")
|
||||||
|
}
|
||||||
|
return blocks[1], nil
|
||||||
|
}
|
||||||
|
testT.Error("blockIngestorStub called too many times")
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestBlockIngestor(t *testing.T) {
|
||||||
|
testT = t
|
||||||
|
RawRequest = blockIngestorStub
|
||||||
|
Time.Sleep = sleepStub
|
||||||
|
Time.Now = nowStub
|
||||||
|
os.RemoveAll(unitTestPath)
|
||||||
|
testcache = NewBlockCache(unitTestPath, unitTestChain, 380640, -1)
|
||||||
|
BlockIngestor(testcache, 11)
|
||||||
|
if step != 19 {
|
||||||
|
t.Error("unexpected final step", step)
|
||||||
|
}
|
||||||
|
step = 0
|
||||||
|
sleepCount = 0
|
||||||
|
sleepDuration = 0
|
||||||
|
os.RemoveAll(unitTestPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------ GetBlockRange()
|
||||||
|
|
||||||
|
// There are four test blocks, 0..3
|
||||||
|
// (probably don't need all these cases)
|
||||||
func getblockStub(method string, params []json.RawMessage) (json.RawMessage, error) {
|
func getblockStub(method string, params []json.RawMessage) (json.RawMessage, error) {
|
||||||
|
if method != "getblock" {
|
||||||
|
testT.Error("unexpected method")
|
||||||
|
}
|
||||||
var height string
|
var height string
|
||||||
err := json.Unmarshal(params[0], &height)
|
err := json.Unmarshal(params[0], &height)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -267,27 +484,11 @@ func getblockStub(method string, params []json.RawMessage) (json.RawMessage, err
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBlockIngestor(t *testing.T) {
|
|
||||||
testT = t
|
|
||||||
RawRequest = getblockStub
|
|
||||||
Sleep = sleepStub
|
|
||||||
os.RemoveAll(unitTestPath)
|
|
||||||
testcache := NewBlockCache(unitTestPath, unitTestChain, 380640, false)
|
|
||||||
BlockIngestor(testcache, 11)
|
|
||||||
if step != 11 {
|
|
||||||
t.Error("unexpected final step", step)
|
|
||||||
}
|
|
||||||
step = 0
|
|
||||||
sleepCount = 0
|
|
||||||
sleepDuration = 0
|
|
||||||
os.RemoveAll(unitTestPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetBlockRange(t *testing.T) {
|
func TestGetBlockRange(t *testing.T) {
|
||||||
testT = t
|
testT = t
|
||||||
RawRequest = getblockStub
|
RawRequest = getblockStub
|
||||||
os.RemoveAll(unitTestPath)
|
os.RemoveAll(unitTestPath)
|
||||||
testcache := NewBlockCache(unitTestPath, unitTestChain, 380640, true)
|
testcache = NewBlockCache(unitTestPath, unitTestChain, 380640, 0)
|
||||||
blockChan := make(chan *walletrpc.CompactBlock)
|
blockChan := make(chan *walletrpc.CompactBlock)
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
go GetBlockRange(testcache, blockChan, errChan, 380640, 380642)
|
go GetBlockRange(testcache, blockChan, errChan, 380640, 380642)
|
||||||
|
@ -366,7 +567,7 @@ func TestGetBlockRangeReverse(t *testing.T) {
|
||||||
testT = t
|
testT = t
|
||||||
RawRequest = getblockStubReverse
|
RawRequest = getblockStubReverse
|
||||||
os.RemoveAll(unitTestPath)
|
os.RemoveAll(unitTestPath)
|
||||||
testcache := NewBlockCache(unitTestPath, unitTestChain, 380640, true)
|
testcache = NewBlockCache(unitTestPath, unitTestChain, 380640, 0)
|
||||||
blockChan := make(chan *walletrpc.CompactBlock)
|
blockChan := make(chan *walletrpc.CompactBlock)
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
|
|
||||||
|
@ -414,3 +615,158 @@ func TestGenerateCerts(t *testing.T) {
|
||||||
t.Fatal("GenerateCerts returned nil")
|
t.Fatal("GenerateCerts returned nil")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ------------------------------------------ GetMempoolStream
|
||||||
|
|
||||||
|
// Note that in mocking zcashd's RPC replies here, we don't really need
|
||||||
|
// actual txids or transactions, or even strings with the correct format
|
||||||
|
// for those, except that a transaction must be a hex string.
|
||||||
|
func mempoolStub(method string, params []json.RawMessage) (json.RawMessage, error) {
|
||||||
|
step++
|
||||||
|
switch step {
|
||||||
|
case 1:
|
||||||
|
// This will be a getblockchaininfo request
|
||||||
|
if method != "getblockchaininfo" {
|
||||||
|
testT.Fatal("expecting blockchaininfo")
|
||||||
|
}
|
||||||
|
r, _ := json.Marshal(&ZcashdRpcReplyGetblockchaininfo{
|
||||||
|
BestBlockHash: "010203",
|
||||||
|
Blocks: 200,
|
||||||
|
})
|
||||||
|
return r, nil
|
||||||
|
case 2:
|
||||||
|
// No new block has arrived.
|
||||||
|
if method != "getblockchaininfo" {
|
||||||
|
testT.Fatal("expecting blockchaininfo")
|
||||||
|
}
|
||||||
|
r, _ := json.Marshal(&ZcashdRpcReplyGetblockchaininfo{
|
||||||
|
BestBlockHash: "010203",
|
||||||
|
Blocks: 200,
|
||||||
|
})
|
||||||
|
return r, nil
|
||||||
|
case 3:
|
||||||
|
// Expect a getrawmempool next.
|
||||||
|
if method != "getrawmempool" {
|
||||||
|
testT.Fatal("expecting getrawmempool")
|
||||||
|
}
|
||||||
|
// In reality, this would be a hex txid
|
||||||
|
r, _ := json.Marshal([]string{
|
||||||
|
"mempooltxid-1",
|
||||||
|
})
|
||||||
|
return r, nil
|
||||||
|
case 4:
|
||||||
|
// Next, it should ask for this transaction (non-verbose).
|
||||||
|
if method != "getrawtransaction" {
|
||||||
|
testT.Fatal("expecting getrawtransaction")
|
||||||
|
}
|
||||||
|
var txid string
|
||||||
|
json.Unmarshal(params[0], &txid)
|
||||||
|
if txid != "mempooltxid-1" {
|
||||||
|
testT.Fatal("unexpected txid")
|
||||||
|
}
|
||||||
|
r, _ := json.Marshal("aabb")
|
||||||
|
return r, nil
|
||||||
|
case 5:
|
||||||
|
// Simulate that still no new block has arrived ...
|
||||||
|
if method != "getblockchaininfo" {
|
||||||
|
testT.Fatal("expecting blockchaininfo")
|
||||||
|
}
|
||||||
|
r, _ := json.Marshal(&ZcashdRpcReplyGetblockchaininfo{
|
||||||
|
BestBlockHash: "010203",
|
||||||
|
Blocks: 200,
|
||||||
|
})
|
||||||
|
return r, nil
|
||||||
|
case 6:
|
||||||
|
// ... but there a second tx has arrived in the mempool
|
||||||
|
if method != "getrawmempool" {
|
||||||
|
testT.Fatal("expecting getrawmempool")
|
||||||
|
}
|
||||||
|
// In reality, this would be a hex txid
|
||||||
|
r, _ := json.Marshal([]string{
|
||||||
|
"mempooltxid-2",
|
||||||
|
"mempooltxid-1"})
|
||||||
|
return r, nil
|
||||||
|
case 7:
|
||||||
|
// The new mempool tx (and only that one) gets fetched
|
||||||
|
if method != "getrawtransaction" {
|
||||||
|
testT.Fatal("expecting getrawtransaction")
|
||||||
|
}
|
||||||
|
var txid string
|
||||||
|
json.Unmarshal(params[0], &txid)
|
||||||
|
if txid != "mempooltxid-2" {
|
||||||
|
testT.Fatal("unexpected txid")
|
||||||
|
}
|
||||||
|
r, _ := json.Marshal("ccdd")
|
||||||
|
return r, nil
|
||||||
|
case 8:
|
||||||
|
// A new block arrives, this will cause these two tx to be returned
|
||||||
|
if method != "getblockchaininfo" {
|
||||||
|
testT.Fatal("expecting blockchaininfo")
|
||||||
|
}
|
||||||
|
r, _ := json.Marshal(&ZcashdRpcReplyGetblockchaininfo{
|
||||||
|
BestBlockHash: "d1d2d3",
|
||||||
|
Blocks: 201,
|
||||||
|
})
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
testT.Fatal("ran out of cases")
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMempoolStream(t *testing.T) {
|
||||||
|
testT = t
|
||||||
|
RawRequest = mempoolStub
|
||||||
|
Time.Sleep = sleepStub
|
||||||
|
Time.Now = nowStub
|
||||||
|
// In real life, wall time is not close to zero, simulate that.
|
||||||
|
sleepDuration = 1000 * time.Second
|
||||||
|
|
||||||
|
var replies []*walletrpc.RawTransaction
|
||||||
|
// The first request after startup immediately returns an empty list.
|
||||||
|
err := GetMempool(func(tx *walletrpc.RawTransaction) error {
|
||||||
|
t.Fatal("send to client function called on initial GetMempool call")
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("GetMempool failed")
|
||||||
|
}
|
||||||
|
|
||||||
|
// This should return two transactions.
|
||||||
|
err = GetMempool(func(tx *walletrpc.RawTransaction) error {
|
||||||
|
replies = append(replies, tx)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal("GetMempool failed")
|
||||||
|
}
|
||||||
|
if len(replies) != 2 {
|
||||||
|
t.Fatal("unexpected number of tx")
|
||||||
|
}
|
||||||
|
// The interface guarantees that the transactions will be returned
|
||||||
|
// in the order they entered the mempool.
|
||||||
|
if !bytes.Equal([]byte(replies[0].GetData()), []byte{0xaa, 0xbb}) {
|
||||||
|
t.Fatal("unexpected tx contents")
|
||||||
|
}
|
||||||
|
if replies[0].GetHeight() != 200 {
|
||||||
|
t.Fatal("unexpected tx height")
|
||||||
|
}
|
||||||
|
if !bytes.Equal([]byte(replies[1].GetData()), []byte{0xcc, 0xdd}) {
|
||||||
|
t.Fatal("unexpected tx contents")
|
||||||
|
}
|
||||||
|
if replies[1].GetHeight() != 200 {
|
||||||
|
t.Fatal("unexpected tx height")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time started at 1000 seconds (since 1970), and just over 4 seconds
|
||||||
|
// should have elapsed. The units here are nanoseconds.
|
||||||
|
if sleepDuration != 1004400000000 {
|
||||||
|
t.Fatal("unexpected end time")
|
||||||
|
}
|
||||||
|
if step != 8 {
|
||||||
|
t.Fatal("unexpected number of zcashd RPCs")
|
||||||
|
}
|
||||||
|
|
||||||
|
step = 0
|
||||||
|
sleepCount = 0
|
||||||
|
sleepDuration = 0
|
||||||
|
}
|
||||||
|
|
|
@ -46,6 +46,9 @@ type darksideState struct {
|
||||||
// These transactions come from StageTransactions(); they will be merged into
|
// These transactions come from StageTransactions(); they will be merged into
|
||||||
// activeBlocks by ApplyStaged() (and this list then cleared).
|
// activeBlocks by ApplyStaged() (and this list then cleared).
|
||||||
stagedTransactions []stagedTx
|
stagedTransactions []stagedTx
|
||||||
|
|
||||||
|
// Unordered list of replies
|
||||||
|
getAddressUtxos []ZcashdRpcReplyGetaddressutxos
|
||||||
}
|
}
|
||||||
|
|
||||||
var state darksideState
|
var state darksideState
|
||||||
|
@ -74,7 +77,7 @@ func DarksideInit(c *BlockCache, timeout int) {
|
||||||
// DarksideReset allows the wallet test code to specify values
|
// DarksideReset allows the wallet test code to specify values
|
||||||
// that are returned by GetLightdInfo().
|
// that are returned by GetLightdInfo().
|
||||||
func DarksideReset(sa int, bi, cn string) error {
|
func DarksideReset(sa int, bi, cn string) error {
|
||||||
Log.Info("Reset(saplingActivation=", sa, ")")
|
Log.Info("DarksideReset(saplingActivation=", sa, ")")
|
||||||
stopIngestor()
|
stopIngestor()
|
||||||
state = darksideState{
|
state = darksideState{
|
||||||
resetted: true,
|
resetted: true,
|
||||||
|
@ -135,7 +138,7 @@ func setPrevhash() {
|
||||||
copy(blockBytes[4:4+32], prevhash)
|
copy(blockBytes[4:4+32], prevhash)
|
||||||
}
|
}
|
||||||
prevhash = block.GetEncodableHash()
|
prevhash = block.GetEncodableHash()
|
||||||
Log.Info("active block height ", block.GetHeight(), " hash ",
|
Log.Info("Darkside active block height ", block.GetHeight(), " hash ",
|
||||||
hex.EncodeToString(block.GetDisplayHash()),
|
hex.EncodeToString(block.GetDisplayHash()),
|
||||||
" txcount ", block.GetTxCount())
|
" txcount ", block.GetTxCount())
|
||||||
}
|
}
|
||||||
|
@ -150,7 +153,7 @@ func DarksideApplyStaged(height int) error {
|
||||||
if !state.resetted {
|
if !state.resetted {
|
||||||
return errors.New("please call Reset first")
|
return errors.New("please call Reset first")
|
||||||
}
|
}
|
||||||
Log.Info("ApplyStaged(height=", height, ")")
|
Log.Info("DarksideApplyStaged(height=", height, ")")
|
||||||
if height < state.startHeight {
|
if height < state.startHeight {
|
||||||
return errors.New(fmt.Sprint("height ", height,
|
return errors.New(fmt.Sprint("height ", height,
|
||||||
" is less than sapling activation height ", state.startHeight))
|
" is less than sapling activation height ", state.startHeight))
|
||||||
|
@ -209,9 +212,13 @@ func DarksideApplyStaged(height int) error {
|
||||||
block = append(block, tx.bytes...)
|
block = append(block, tx.bytes...)
|
||||||
state.activeBlocks[tx.height-state.startHeight] = block
|
state.activeBlocks[tx.height-state.startHeight] = block
|
||||||
}
|
}
|
||||||
|
maxHeight := state.startHeight + len(state.activeBlocks) - 1
|
||||||
|
if height > maxHeight {
|
||||||
|
height = maxHeight
|
||||||
|
}
|
||||||
setPrevhash()
|
setPrevhash()
|
||||||
state.latestHeight = height
|
state.latestHeight = height
|
||||||
Log.Info("active blocks from ", state.startHeight,
|
Log.Info("darkside: active blocks from ", state.startHeight,
|
||||||
" to ", state.startHeight+len(state.activeBlocks)-1,
|
" to ", state.startHeight+len(state.activeBlocks)-1,
|
||||||
", latest presented height ", state.latestHeight)
|
", latest presented height ", state.latestHeight)
|
||||||
|
|
||||||
|
@ -241,7 +248,7 @@ func darksideStageBlock(caller string, b []byte) error {
|
||||||
if len(rest) != 0 {
|
if len(rest) != 0 {
|
||||||
return errors.New("block serialization is too long")
|
return errors.New("block serialization is too long")
|
||||||
}
|
}
|
||||||
Log.Info(caller, "(height=", block.GetHeight(), ")")
|
Log.Info(caller, "DarksideStageBlock(height=", block.GetHeight(), ")")
|
||||||
if block.GetHeight() < state.startHeight {
|
if block.GetHeight() < state.startHeight {
|
||||||
return errors.New(fmt.Sprint("block height ", block.GetHeight(),
|
return errors.New(fmt.Sprint("block height ", block.GetHeight(),
|
||||||
" is less than sapling activation height ", state.startHeight))
|
" is less than sapling activation height ", state.startHeight))
|
||||||
|
@ -256,7 +263,7 @@ func DarksideStageBlocks(url string) error {
|
||||||
if !state.resetted {
|
if !state.resetted {
|
||||||
return errors.New("please call Reset first")
|
return errors.New("please call Reset first")
|
||||||
}
|
}
|
||||||
Log.Info("StageBlocks(url=", url, ")")
|
Log.Info("DarksideStageBlocks(url=", url, ")")
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -289,7 +296,7 @@ func DarksideStageBlockStream(blockHex string) error {
|
||||||
if !state.resetted {
|
if !state.resetted {
|
||||||
return errors.New("please call Reset first")
|
return errors.New("please call Reset first")
|
||||||
}
|
}
|
||||||
Log.Info("StageBlocksStream()")
|
Log.Info("DarksideStageBlocksStream()")
|
||||||
blockBytes, err := hex.DecodeString(blockHex)
|
blockBytes, err := hex.DecodeString(blockHex)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -305,7 +312,7 @@ func DarksideStageBlocksCreate(height int32, nonce int32, count int32) error {
|
||||||
if !state.resetted {
|
if !state.resetted {
|
||||||
return errors.New("please call Reset first")
|
return errors.New("please call Reset first")
|
||||||
}
|
}
|
||||||
Log.Info("StageBlocksCreate(height=", height, ", nonce=", nonce, ", count=", count, ")")
|
Log.Info("DarksideStageBlocksCreate(height=", height, ", nonce=", nonce, ", count=", count, ")")
|
||||||
for i := 0; i < int(count); i++ {
|
for i := 0; i < int(count); i++ {
|
||||||
|
|
||||||
fakeCoinbase := "0400008085202f890100000000000000000000000000000000000000000000000000" +
|
fakeCoinbase := "0400008085202f890100000000000000000000000000000000000000000000000000" +
|
||||||
|
@ -410,6 +417,18 @@ func darksideRawRequest(method string, params []json.RawMessage) (json.RawMessag
|
||||||
}
|
}
|
||||||
return json.Marshal(hex.EncodeToString(state.activeBlocks[index]))
|
return json.Marshal(hex.EncodeToString(state.activeBlocks[index]))
|
||||||
|
|
||||||
|
case "getbestblockhash":
|
||||||
|
state.mutex.RLock()
|
||||||
|
defer state.mutex.RUnlock()
|
||||||
|
if len(state.activeBlocks) == 0 {
|
||||||
|
Log.Fatal("getbestblockhash: no blocks")
|
||||||
|
}
|
||||||
|
index := state.latestHeight - state.startHeight
|
||||||
|
block := parser.NewBlock()
|
||||||
|
block.ParseFromSlice(state.activeBlocks[index])
|
||||||
|
hash := hex.EncodeToString(block.GetDisplayHash())
|
||||||
|
return json.Marshal(hash)
|
||||||
|
|
||||||
case "getaddresstxids":
|
case "getaddresstxids":
|
||||||
// Not required for minimal reorg testing.
|
// Not required for minimal reorg testing.
|
||||||
return nil, errors.New("not implemented yet")
|
return nil, errors.New("not implemented yet")
|
||||||
|
@ -459,6 +478,23 @@ func darksideRawRequest(method string, params []json.RawMessage) (json.RawMessag
|
||||||
}
|
}
|
||||||
return json.Marshal(reply)
|
return json.Marshal(reply)
|
||||||
|
|
||||||
|
case "getaddressutxos":
|
||||||
|
var req ZcashdRpcRequestGetaddressutxos
|
||||||
|
err := json.Unmarshal(params[0], &req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.New("failed to parse getaddressutxos JSON")
|
||||||
|
}
|
||||||
|
utxosReply := make([]ZcashdRpcReplyGetaddressutxos, 0)
|
||||||
|
for _, utxo := range state.getAddressUtxos {
|
||||||
|
for _, a := range req.Addresses {
|
||||||
|
if a == utxo.Address {
|
||||||
|
utxosReply = append(utxosReply, utxo)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return json.Marshal(utxosReply)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("there was an attempt to call an unsupported RPC")
|
return nil, errors.New("there was an attempt to call an unsupported RPC")
|
||||||
}
|
}
|
||||||
|
@ -557,7 +593,7 @@ func DarksideStageTransactionsURL(height int, url string) error {
|
||||||
if !state.resetted {
|
if !state.resetted {
|
||||||
return errors.New("please call Reset first")
|
return errors.New("please call Reset first")
|
||||||
}
|
}
|
||||||
Log.Info("StageTransactionsURL(height=", height, ", url=", url, ")")
|
Log.Info("DarksideStageTransactionsURL(height=", height, ", url=", url, ")")
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -585,3 +621,13 @@ func DarksideStageTransactionsURL(height int, url string) error {
|
||||||
return scan.Err()
|
return scan.Err()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DarksideAddAddressUtxo(arg ZcashdRpcReplyGetaddressutxos) error {
|
||||||
|
state.getAddressUtxos = append(state.getAddressUtxos, arg)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func DarksideClearAddressUtxos() error {
|
||||||
|
state.getAddressUtxos = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -1,183 +1,156 @@
|
||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/adityapk00/lightwalletd/walletrpc"
|
"github.com/adityapk00/lightwalletd/walletrpc"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type txid string
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// List of all mempool transactions
|
// Set of mempool txids that have been seen during the current block interval.
|
||||||
txns map[string]*walletrpc.RawTransaction = make(map[string]*walletrpc.RawTransaction)
|
// The zcashd RPC `getrawmempool` returns the entire mempool each time, so
|
||||||
|
// this allows us to ignore the txids that we've already seen.
|
||||||
|
g_txidSeen map[txid]struct{} = map[txid]struct{}{}
|
||||||
|
|
||||||
// List of all clients waiting to recieve mempool txns
|
// List of transactions during current block interval, in order received. Each
|
||||||
clients []chan<- *walletrpc.RawTransaction
|
// client thread can keep an index into this slice to record which transactions
|
||||||
|
// it's sent back to the client (everything before that index). The g_txidSeen
|
||||||
|
// map allows this list to not contain duplicates.
|
||||||
|
g_txList []*walletrpc.RawTransaction
|
||||||
|
|
||||||
// Latest hash of the blocks. If this changes, then close all the clients and flush the mempool
|
// The most recent absolute time that we fetched the mempool and the latest
|
||||||
lastHash []byte
|
// (tip) block hash (so we know when a new block has been mined).
|
||||||
|
g_lastTime time.Time
|
||||||
|
|
||||||
// A pointer to the blockcache
|
// The most recent zcashd getblockchaininfo reply, for height and best block
|
||||||
blockcache *BlockCache
|
// hash (tip) which is used to detect when a new block arrives.
|
||||||
|
g_lastBlockChainInfo *ZcashdRpcReplyGetblockchaininfo = &ZcashdRpcReplyGetblockchaininfo{}
|
||||||
|
|
||||||
// Mutex to lock the above 2 structs
|
// Mutex to protect the above variables.
|
||||||
lock sync.Mutex
|
g_lock sync.Mutex
|
||||||
|
|
||||||
// Since the mutex doesn't have a "try_lock" method, we'll have to improvize with this
|
|
||||||
refreshing int32 = 0
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddNewClient adds a new client to the list of clients to notify for mempool txns
|
func GetMempool(sendToClient func(*walletrpc.RawTransaction) error) error {
|
||||||
func AddNewClient(client chan<- *walletrpc.RawTransaction) {
|
g_lock.Lock()
|
||||||
|
index := 0
|
||||||
|
// Stay in this function until the tip block hash changes.
|
||||||
|
stayHash := g_lastBlockChainInfo.BestBlockHash
|
||||||
|
|
||||||
// Log.Infoln("Adding new client, sending ", len(txns), " transactions")
|
// Wait for more transactions to be added to the list
|
||||||
|
for {
|
||||||
// Copy map locally
|
// Don't fetch the mempool more often than every 2 seconds.
|
||||||
lock.Lock()
|
now := Time.Now()
|
||||||
localmap := make(map[string]*walletrpc.RawTransaction)
|
if now.After(g_lastTime.Add(2 * time.Second)) {
|
||||||
|
blockChainInfo, err := getLatestBlockChainInfo()
|
||||||
for k, rtx := range txns {
|
if err != nil {
|
||||||
localmap[k] = rtx
|
g_lock.Unlock()
|
||||||
}
|
return err
|
||||||
lock.Unlock()
|
}
|
||||||
|
if g_lastBlockChainInfo.BestBlockHash != blockChainInfo.BestBlockHash {
|
||||||
// Also send all pending mempool txns
|
// A new block has arrived
|
||||||
for _, rtx := range localmap {
|
g_lastBlockChainInfo = blockChainInfo
|
||||||
if client != nil {
|
Log.Infoln("Latest Block changed, clearing everything")
|
||||||
client <- rtx
|
// We're the first thread to notice, clear cached state.
|
||||||
|
g_txidSeen = map[txid]struct{}{}
|
||||||
|
g_txList = []*walletrpc.RawTransaction{}
|
||||||
|
g_lastTime = time.Time{}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err = refreshMempoolTxns(); err != nil {
|
||||||
|
g_lock.Unlock()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
g_lastTime = now
|
||||||
|
}
|
||||||
|
// Send transactions we haven't sent yet, best to not do so while
|
||||||
|
// holding the mutex, since this call may get flow-controlled.
|
||||||
|
toSend := g_txList[index:]
|
||||||
|
index = len(g_txList)
|
||||||
|
g_lock.Unlock()
|
||||||
|
for _, tx := range toSend {
|
||||||
|
if err := sendToClient(tx); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Time.Sleep(200 * time.Millisecond)
|
||||||
|
g_lock.Lock()
|
||||||
|
if g_lastBlockChainInfo.BestBlockHash != stayHash {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
g_lock.Unlock()
|
||||||
lock.Lock()
|
return nil
|
||||||
if client != nil {
|
|
||||||
clients = append(clients, client)
|
|
||||||
}
|
|
||||||
lock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// RefreshMempoolTxns gets all new mempool txns and sends any new ones to waiting clients
|
// RefreshMempoolTxns gets all new mempool txns and sends any new ones to waiting clients
|
||||||
func refreshMempoolTxns() error {
|
func refreshMempoolTxns() error {
|
||||||
// First check if another refresh is running, if it is, just return
|
Log.Infoln("Refreshing mempool")
|
||||||
if !atomic.CompareAndSwapInt32(&refreshing, 0, 1) {
|
|
||||||
Log.Warnln("Another refresh in progress, returning")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set refreshing to 0 when we exit
|
params := []json.RawMessage{}
|
||||||
defer atomic.StoreInt32(&refreshing, 0)
|
|
||||||
|
|
||||||
// Check if the blockchain has changed, and if it has, then clear everything
|
|
||||||
|
|
||||||
lock.Lock()
|
|
||||||
defer lock.Unlock()
|
|
||||||
|
|
||||||
if !bytes.Equal(lastHash, blockcache.GetLatestHash()) {
|
|
||||||
Log.Infoln("Block hash changed, clearing mempool clients")
|
|
||||||
|
|
||||||
// Flush all the clients
|
|
||||||
for _, client := range clients {
|
|
||||||
if client != nil {
|
|
||||||
close(client)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
clients = make([]chan<- *walletrpc.RawTransaction, 0)
|
|
||||||
|
|
||||||
// Clear txns
|
|
||||||
txns = make(map[string]*walletrpc.RawTransaction)
|
|
||||||
|
|
||||||
lastHash = blockcache.GetLatestHash()
|
|
||||||
}
|
|
||||||
|
|
||||||
var mempoolList []string
|
|
||||||
params := make([]json.RawMessage, 0)
|
|
||||||
result, rpcErr := RawRequest("getrawmempool", params)
|
result, rpcErr := RawRequest("getrawmempool", params)
|
||||||
if rpcErr != nil {
|
if rpcErr != nil {
|
||||||
return rpcErr
|
return rpcErr
|
||||||
}
|
}
|
||||||
|
var mempoolList []string
|
||||||
err := json.Unmarshal(result, &mempoolList)
|
err := json.Unmarshal(result, &mempoolList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//println("getrawmempool size ", len(mempoolList))
|
|
||||||
|
|
||||||
// Fetch all new mempool txns and add them into `newTxns`
|
// Fetch all new mempool txns and add them into `newTxns`
|
||||||
for _, txidstr := range mempoolList {
|
for _, txidstr := range mempoolList {
|
||||||
if _, ok := txns[txidstr]; !ok {
|
if _, ok := g_txidSeen[txid(txidstr)]; ok {
|
||||||
txidJSON, err := json.Marshal(txidstr)
|
// We've already fetched this transaction
|
||||||
if err != nil {
|
continue
|
||||||
return err
|
|
||||||
}
|
|
||||||
// The "0" is because we only need the raw hex, which is returned as
|
|
||||||
// just a hex string, and not even a json string (with quotes).
|
|
||||||
params := []json.RawMessage{txidJSON, json.RawMessage("0")}
|
|
||||||
result, rpcErr := RawRequest("getrawtransaction", params)
|
|
||||||
if rpcErr != nil {
|
|
||||||
// Not an error; mempool transactions can disappear
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
// strip the quotes
|
|
||||||
var txStr string
|
|
||||||
err = json.Unmarshal(result, &txStr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// conver to binary
|
|
||||||
txBytes, err := hex.DecodeString(txStr)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
newRtx := &walletrpc.RawTransaction{
|
|
||||||
Data: txBytes,
|
|
||||||
Height: uint64(blockcache.GetLatestHeight()),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify waiting clients
|
|
||||||
for _, client := range clients {
|
|
||||||
if client != nil {
|
|
||||||
client <- newRtx
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.Infoln("Adding new mempool txid", txidstr, " sending to ", len(clients), " clients")
|
|
||||||
txns[txidstr] = newRtx
|
|
||||||
}
|
}
|
||||||
|
g_txidSeen[txid(txidstr)] = struct{}{}
|
||||||
|
// We haven't fetched this transaction already.
|
||||||
|
txidJSON, err := json.Marshal(txidstr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
// The "0" is because we only need the raw hex, which is returned as
|
||||||
|
// just a hex string, and not even a json string (with quotes).
|
||||||
|
params := []json.RawMessage{txidJSON, json.RawMessage("0")}
|
||||||
|
result, rpcErr := RawRequest("getrawtransaction", params)
|
||||||
|
if rpcErr != nil {
|
||||||
|
// Not an error; mempool transactions can disappear
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// strip the quotes
|
||||||
|
var txStr string
|
||||||
|
err = json.Unmarshal(result, &txStr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
txBytes, err := hex.DecodeString(txStr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
Log.Infoln("appending", txidstr)
|
||||||
|
newRtx := &walletrpc.RawTransaction{
|
||||||
|
Data: txBytes,
|
||||||
|
Height: uint64(g_lastBlockChainInfo.Blocks),
|
||||||
|
}
|
||||||
|
g_txList = append(g_txList, newRtx)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// StartMempoolMonitor starts monitoring the mempool
|
func getLatestBlockChainInfo() (*ZcashdRpcReplyGetblockchaininfo, error) {
|
||||||
func StartMempoolMonitor(cache *BlockCache, done <-chan bool) {
|
result, rpcErr := RawRequest("getblockchaininfo", []json.RawMessage{})
|
||||||
go func() {
|
if rpcErr != nil {
|
||||||
ticker := time.NewTicker(5 * time.Second)
|
return nil, rpcErr
|
||||||
blockcache = cache
|
}
|
||||||
lastHash = blockcache.GetLatestHash()
|
var getblockchaininfoReply ZcashdRpcReplyGetblockchaininfo
|
||||||
|
err := json.Unmarshal(result, &getblockchaininfoReply)
|
||||||
for {
|
if err != nil {
|
||||||
select {
|
return nil, err
|
||||||
case <-ticker.C:
|
}
|
||||||
go func() {
|
return &getblockchaininfoReply, nil
|
||||||
//Log.Infoln("Ticker triggered")
|
|
||||||
err := refreshMempoolTxns()
|
|
||||||
if err != nil {
|
|
||||||
Log.Errorln("Mempool refresh error:", err.Error())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
case <-done:
|
|
||||||
for _, client := range clients {
|
|
||||||
close(client)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,6 +94,16 @@ block height to another. This happens in two parts, first we create and apply
|
||||||
the "before reorg" state. Then we create the "after reorg" stage and apply
|
the "before reorg" state. Then we create the "after reorg" stage and apply
|
||||||
it, which makes the reorg happen.
|
it, which makes the reorg happen.
|
||||||
|
|
||||||
|
Here's a quick-start guide to simulating a reorg:
|
||||||
|
```
|
||||||
|
grpcurl -plaintext -d '{"saplingActivation": 663150,"branchID": "bad", "chainName":"x"}' localhost:9067 cash.z.wallet.sdk.rpc.DarksideStreamer/Reset
|
||||||
|
grpcurl -plaintext -d '{"url": "https://raw.githubusercontent.com/zcash-hackworks/darksidewalletd-test-data/master/basic-reorg/663150.txt"}' localhost:9067 cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocks
|
||||||
|
grpcurl -plaintext -d '{"height":663151,"count":10}' localhost:9067 cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksCreate
|
||||||
|
grpcurl -plaintext -d '{"height":663160}' localhost:9067 cash.z.wallet.sdk.rpc.DarksideStreamer/ApplyStaged
|
||||||
|
grpcurl -plaintext -d '{"height":663155,"count":10,"nonce":44}' localhost:9067 cash.z.wallet.sdk.rpc.DarksideStreamer/StageBlocksCreate
|
||||||
|
grpcurl -plaintext -d '{"height":663164}' localhost:9067 cash.z.wallet.sdk.rpc.DarksideStreamer/ApplyStaged
|
||||||
|
```
|
||||||
|
|
||||||
#### Creating the Before-Reorg State
|
#### Creating the Before-Reorg State
|
||||||
|
|
||||||
If you haven't already started darksidewalletd, please start it:
|
If you haven't already started darksidewalletd, please start it:
|
||||||
|
|
|
@ -10,16 +10,17 @@ docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all
|
||||||
|
|
||||||
## Setup .env file
|
## Setup .env file
|
||||||
|
|
||||||
Copy `.env.example` to `.env` and change any required paramaters.
|
Copy `.env.example` to `.env` and change any required parameters.
|
||||||
|
|
||||||
| Variable | Usage |
|
| Variable | Usage |
|
||||||
| ------------- |:-------------:|
|
| ------------- |:-------------:|
|
||||||
| `GF_SECURITY_ADMIN_USER` | Grafana admin user name |
|
| `GF_SECURITY_ADMIN_USER` | Grafana admin user name |
|
||||||
| `ZCASHD_RPCUSER` | zcashd rpc user |
|
| `ZCASHD_RPCUSER` | zcashd rpc user |
|
||||||
|
| `ZCASHD_RPCPASSWORD` | zcashd rpc password |
|
||||||
| `ZCASHD_RPCPORT` | zcashd rpc port |
|
| `ZCASHD_RPCPORT` | zcashd rpc port |
|
||||||
|`ZCASHD_ALLOWIP`| zcashd rpc allowed IPs (don't |change unless you know what you're doing)|
|
|`ZCASHD_ALLOWIP`| zcashd rpc allowed IPs (don't change unless you know what you're doing)|
|
||||||
|`ZCASHD_DATADIR`| local location of zcasd data directory. `uid` 2001 needs write access|
|
|`ZCASHD_DATADIR`| local location of zcashd data directory. `uid` 2001 needs write access|
|
||||||
|`ZCASHD_PARMDIR`| local location of zcasd data directory. `uid` 2001 needs read access|
|
|`ZCASHD_PARMDIR`| local location of zcashd data directory. `uid` 2001 needs read access|
|
||||||
|`ZCASHD_NETWORK`| zcashd network to use, `testnet` or `mainnet`|
|
|`ZCASHD_NETWORK`| zcashd network to use, `testnet` or `mainnet`|
|
||||||
|`ZCASHD_GEN`| should zcashd mine? `0` or `1`
|
|`ZCASHD_GEN`| should zcashd mine? `0` or `1`
|
||||||
|`LWD_PORT`| port for lightwalletd to bind to|
|
|`LWD_PORT`| port for lightwalletd to bind to|
|
||||||
|
@ -32,6 +33,28 @@ Copy `.env.example` to `.env` and change any required paramaters.
|
||||||
./buildenv.sh | tee .env
|
./buildenv.sh | tee .env
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Edit the two zcash.conf files
|
||||||
|
There are two zcash.conf files; one read by zcashd, one read by lightwalletd.
|
||||||
|
|
||||||
|
### `$ZCASHD_DATADIR/zcash.conf`—read by zcashd
|
||||||
|
The zcashd's `zcash.conf` needs to look like:
|
||||||
|
```
|
||||||
|
rpcuser=zcashrpc
|
||||||
|
rpcpassword=TODO INSERT A RANDOM PASSWORD HERE
|
||||||
|
experimentalfeatures=1
|
||||||
|
lightwalletd=1
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `TODO INSERT A RANDOM PASSWORD HERE` with a random password, e.g. the output of `head -c 16 /dev/urandom | base64`.
|
||||||
|
|
||||||
|
`rpcuser` and `rpcpassword` must be set, as lightwalletd doesn't work with RPC cookies (see the [rpcpassword](https://zcash.readthedocs.io/en/latest/rtd_pages/zcash_conf_guide.html) documentation) for authentication.
|
||||||
|
|
||||||
|
`rpcuser` and `rpcpassword` in `.env` are only used by zcashd_exporter, but they also must be the same values as in `$ZCASHD_DATADIR/zcash.conf`
|
||||||
|
|
||||||
|
### `lightwalletd/docker/zcash.conf`—read by lightwalletd
|
||||||
|
The other `zcashd.conf`—the one read by lightwalletd—needs to have `rpcbind` (the address of the zcashd it will connect to) set to `zcashd`, and then docker-compose networking will make it resolve to the right IP address. Also, it needs to have the same `rpcuser` and `rpcpassword` values that are listed in `$ZCASHD_DATADIR/zcash.conf` to be able to authenticate.
|
||||||
|
|
||||||
|
|
||||||
## Build initial local docker image
|
## Build initial local docker image
|
||||||
|
|
||||||
`docker-compose build`
|
`docker-compose build`
|
||||||
|
@ -77,7 +100,7 @@ This should then be taken to the `Zcashd node exporter` dashboard.
|
||||||
|
|
||||||
If all goes as planned, the dashboard should start populating data from the container services.
|
If all goes as planned, the dashboard should start populating data from the container services.
|
||||||
|
|
||||||
If there are an issues, you can view all the `docker-compose` services under the `Explore` section.
|
If there are any issues, you can view all the `docker-compose` services under the `Explore` section.
|
||||||
|
|
||||||
# Viewing container logs
|
# Viewing container logs
|
||||||
|
|
||||||
|
@ -98,3 +121,18 @@ Loki as a rich query syntax to help with log in many ways, for example combine 2
|
||||||

|

|
||||||
|
|
||||||
See more here: https://github.com/grafana/loki/blob/master/docs/logql.md
|
See more here: https://github.com/grafana/loki/blob/master/docs/logql.md
|
||||||
|
|
||||||
|
|
||||||
|
# Exposing `lightwalletd` to the network
|
||||||
|
|
||||||
|
Edit `docker-compose.yml` to look like
|
||||||
|
|
||||||
|
```
|
||||||
|
ports:
|
||||||
|
#- "127.0.0.1:$LWD_GRPC_PORT:$LWD_GRPC_PORT"
|
||||||
|
#- "127.0.0.1:$LWD_HTTP_PORT:$LWD_HTTP_PORT"
|
||||||
|
- "0.0.0.0:$LWD_GRPC_PORT:$LWD_GRPC_PORT"
|
||||||
|
- "0.0.0.0:$LWD_HTTP_PORT:$LWD_HTTP_PORT"
|
||||||
|
```
|
||||||
|
|
||||||
|
When you edit these lines in `docker-compose.yml`, stopping/starting the individual `lightwalletd` container doesn't actually make the changes happen—you have to stop/start the whole `docker-compose` ensemble of containers because the ports/network config stuff lives at that level and doesn't seem to be affected by individual container stop/starts. Also if you want to expose `lightwalletd` to the whole internet, you don't need to specify an IP address, `0.0.0.0` works as it should.
|
||||||
|
|
|
@ -183,11 +183,15 @@
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="#cash.z.wallet.sdk.rpc.CompactOutput"><span class="badge">M</span>CompactOutput</a>
|
<a href="#cash.z.wallet.sdk.rpc.CompactOrchardAction"><span class="badge">M</span>CompactOrchardAction</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="#cash.z.wallet.sdk.rpc.CompactSpend"><span class="badge">M</span>CompactSpend</a>
|
<a href="#cash.z.wallet.sdk.rpc.CompactSaplingOutput"><span class="badge">M</span>CompactSaplingOutput</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="#cash.z.wallet.sdk.rpc.CompactSaplingSpend"><span class="badge">M</span>CompactSaplingSpend</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
|
@ -408,7 +412,52 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="cash.z.wallet.sdk.rpc.CompactOutput">CompactOutput</h3>
|
<h3 id="cash.z.wallet.sdk.rpc.CompactOrchardAction">CompactOrchardAction</h3>
|
||||||
|
<p>https://github.com/zcash/zips/blob/main/zip-0225.rst#orchard-action-description-orchardaction</p><p>(but not all fields are needed)</p>
|
||||||
|
|
||||||
|
|
||||||
|
<table class="field-table">
|
||||||
|
<thead>
|
||||||
|
<tr><td>Field</td><td>Type</td><td>Label</td><td>Description</td></tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>nullifier</td>
|
||||||
|
<td><a href="#bytes">bytes</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td><p>[32] The nullifier of the input note </p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>cmx</td>
|
||||||
|
<td><a href="#bytes">bytes</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td><p>[32] The x-coordinate of the note commitment for the output note </p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>ephemeralKey</td>
|
||||||
|
<td><a href="#bytes">bytes</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td><p>[32] An encoding of an ephemeral Pallas public key </p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>ciphertext</td>
|
||||||
|
<td><a href="#bytes">bytes</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td><p>[52] The note plaintext component of the encCiphertext field </p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h3 id="cash.z.wallet.sdk.rpc.CompactSaplingOutput">CompactSaplingOutput</h3>
|
||||||
<p>output is a Sapling Output Description as described in section 7.4 of the</p><p>Zcash protocol spec. Total size is 948.</p>
|
<p>output is a Sapling Output Description as described in section 7.4 of the</p><p>Zcash protocol spec. Total size is 948.</p>
|
||||||
|
|
||||||
|
|
||||||
|
@ -436,7 +485,7 @@
|
||||||
<td>ciphertext</td>
|
<td>ciphertext</td>
|
||||||
<td><a href="#bytes">bytes</a></td>
|
<td><a href="#bytes">bytes</a></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><p>ciphertext and zkproof </p></td>
|
<td><p>first 52 bytes of ciphertext </p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
|
@ -446,8 +495,8 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="cash.z.wallet.sdk.rpc.CompactSpend">CompactSpend</h3>
|
<h3 id="cash.z.wallet.sdk.rpc.CompactSaplingSpend">CompactSaplingSpend</h3>
|
||||||
<p>CompactSpend is a Sapling Spend Description as described in 7.3 of the Zcash</p><p>protocol specification.</p>
|
<p>CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash</p><p>protocol specification.</p>
|
||||||
|
|
||||||
|
|
||||||
<table class="field-table">
|
<table class="field-table">
|
||||||
|
@ -507,18 +556,25 @@ in a pure-Sapling context, the fee will be calculable as:
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>spends</td>
|
<td>spends</td>
|
||||||
<td><a href="#cash.z.wallet.sdk.rpc.CompactSpend">CompactSpend</a></td>
|
<td><a href="#cash.z.wallet.sdk.rpc.CompactSaplingSpend">CompactSaplingSpend</a></td>
|
||||||
<td>repeated</td>
|
<td>repeated</td>
|
||||||
<td><p>inputs </p></td>
|
<td><p>inputs </p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>outputs</td>
|
<td>outputs</td>
|
||||||
<td><a href="#cash.z.wallet.sdk.rpc.CompactOutput">CompactOutput</a></td>
|
<td><a href="#cash.z.wallet.sdk.rpc.CompactSaplingOutput">CompactSaplingOutput</a></td>
|
||||||
<td>repeated</td>
|
<td>repeated</td>
|
||||||
<td><p>outputs </p></td>
|
<td><p>outputs </p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>actions</td>
|
||||||
|
<td><a href="#cash.z.wallet.sdk.rpc.CompactOrchardAction">CompactOrchardAction</a></td>
|
||||||
|
<td>repeated</td>
|
||||||
|
<td><p> </p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -836,6 +892,21 @@ into a specified block on the next ApplyStaged().</p></td>
|
||||||
<td><p>Clear the incoming transaction pool.</p></td>
|
<td><p>Clear the incoming transaction pool.</p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>AddAddressUtxo</td>
|
||||||
|
<td><a href="#cash.z.wallet.sdk.rpc.GetAddressUtxosReply">GetAddressUtxosReply</a></td>
|
||||||
|
<td><a href="#cash.z.wallet.sdk.rpc.Empty">Empty</a></td>
|
||||||
|
<td><p>Add a GetAddressUtxosReply entry to be returned by GetAddressUtxos().
|
||||||
|
There is no staging or applying for these, very simple.</p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>ClearAddressUtxo</td>
|
||||||
|
<td><a href="#cash.z.wallet.sdk.rpc.Empty">Empty</a></td>
|
||||||
|
<td><a href="#cash.z.wallet.sdk.rpc.Empty">Empty</a></td>
|
||||||
|
<td><p>Clear the list of GetAddressUtxos entries (can't fail)</p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -1045,7 +1116,7 @@ into a specified block on the next ApplyStaged().</p></td>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="cash.z.wallet.sdk.rpc.GetAddressUtxosArg">GetAddressUtxosArg</h3>
|
<h3 id="cash.z.wallet.sdk.rpc.GetAddressUtxosArg">GetAddressUtxosArg</h3>
|
||||||
<p></p>
|
<p>Results are sorted by height, which makes it easy to issue another</p><p>request that picks up from where the previous left off.</p>
|
||||||
|
|
||||||
|
|
||||||
<table class="field-table">
|
<table class="field-table">
|
||||||
|
@ -1055,9 +1126,9 @@ into a specified block on the next ApplyStaged().</p></td>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>address</td>
|
<td>addresses</td>
|
||||||
<td><a href="#string">string</a></td>
|
<td><a href="#string">string</a></td>
|
||||||
<td></td>
|
<td>repeated</td>
|
||||||
<td><p> </p></td>
|
<td><p> </p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
@ -1092,6 +1163,13 @@ into a specified block on the next ApplyStaged().</p></td>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>address</td>
|
||||||
|
<td><a href="#string">string</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td><p> </p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>txid</td>
|
<td>txid</td>
|
||||||
<td><a href="#bytes">bytes</a></td>
|
<td><a href="#bytes">bytes</a></td>
|
||||||
|
@ -1305,7 +1383,7 @@ into a specified block on the next ApplyStaged().</p></td>
|
||||||
|
|
||||||
|
|
||||||
<h3 id="cash.z.wallet.sdk.rpc.RawTransaction">RawTransaction</h3>
|
<h3 id="cash.z.wallet.sdk.rpc.RawTransaction">RawTransaction</h3>
|
||||||
<p>RawTransaction contains the complete transaction data. It also optionally includes </p><p>the block height in which the transaction was included.</p>
|
<p>RawTransaction contains the complete transaction data. It also optionally includes </p><p>the block height in which the transaction was included, or, when returned</p><p>by GetMempoolStream(), the latest block height.</p>
|
||||||
|
|
||||||
|
|
||||||
<table class="field-table">
|
<table class="field-table">
|
||||||
|
@ -1418,7 +1496,7 @@ into a specified block on the next ApplyStaged().</p></td>
|
||||||
<td>height</td>
|
<td>height</td>
|
||||||
<td><a href="#uint64">uint64</a></td>
|
<td><a href="#uint64">uint64</a></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><p> </p></td>
|
<td><p>block height </p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -1436,12 +1514,19 @@ into a specified block on the next ApplyStaged().</p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>tree</td>
|
<td>saplingTree</td>
|
||||||
<td><a href="#string">string</a></td>
|
<td><a href="#string">string</a></td>
|
||||||
<td></td>
|
<td></td>
|
||||||
<td><p>sapling commitment tree state </p></td>
|
<td><p>sapling commitment tree state </p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>orchardTree</td>
|
||||||
|
<td><a href="#string">string</a></td>
|
||||||
|
<td></td>
|
||||||
|
<td><p>orchard commitment tree state </p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
@ -1572,6 +1657,14 @@ match a shortened txid, they are all sent (none is excluded). Transactions
|
||||||
in the exclude list that don't exist in the mempool are ignored.</p></td>
|
in the exclude list that don't exist in the mempool are ignored.</p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>GetMempoolStream</td>
|
||||||
|
<td><a href="#cash.z.wallet.sdk.rpc.Empty">Empty</a></td>
|
||||||
|
<td><a href="#cash.z.wallet.sdk.rpc.RawTransaction">RawTransaction</a> stream</td>
|
||||||
|
<td><p>Return a stream of current Mempool transactions. This will keep the output stream open while
|
||||||
|
there are mempool transactions. It will close the returned stream when a new block is mined.</p></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>GetTreeState</td>
|
<td>GetTreeState</td>
|
||||||
<td><a href="#cash.z.wallet.sdk.rpc.BlockID">BlockID</a></td>
|
<td><a href="#cash.z.wallet.sdk.rpc.BlockID">BlockID</a></td>
|
||||||
|
@ -1607,7 +1700,7 @@ The block can be specified by either height or hash.</p></td>
|
||||||
<td>Ping</td>
|
<td>Ping</td>
|
||||||
<td><a href="#cash.z.wallet.sdk.rpc.Duration">Duration</a></td>
|
<td><a href="#cash.z.wallet.sdk.rpc.Duration">Duration</a></td>
|
||||||
<td><a href="#cash.z.wallet.sdk.rpc.PingResponse">PingResponse</a></td>
|
<td><a href="#cash.z.wallet.sdk.rpc.PingResponse">PingResponse</a></td>
|
||||||
<td><p>Testing-only</p></td>
|
<td><p>Testing-only, requires lightwalletd --ping-very-insecure (do not enable in production)</p></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
|
@ -36,7 +36,7 @@ const (
|
||||||
|
|
||||||
func testsetup() (walletrpc.CompactTxStreamerServer, *common.BlockCache) {
|
func testsetup() (walletrpc.CompactTxStreamerServer, *common.BlockCache) {
|
||||||
os.RemoveAll(unitTestPath)
|
os.RemoveAll(unitTestPath)
|
||||||
cache := common.NewBlockCache(unitTestPath, unitTestChain, 380640, true)
|
cache := common.NewBlockCache(unitTestPath, unitTestChain, 380640, 0)
|
||||||
lwd, err := NewLwdStreamer(cache, "main", false /* enablePing */)
|
lwd, err := NewLwdStreamer(cache, "main", false /* enablePing */)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
os.Stderr.WriteString(fmt.Sprint("NewLwdStreamer failed:", err))
|
os.Stderr.WriteString(fmt.Sprint("NewLwdStreamer failed:", err))
|
||||||
|
@ -191,6 +191,9 @@ func TestGetLatestBlock(t *testing.T) {
|
||||||
if blockID.Height != 380640 {
|
if blockID.Height != 380640 {
|
||||||
t.Fatal("unexpected blockID.height")
|
t.Fatal("unexpected blockID.height")
|
||||||
}
|
}
|
||||||
|
if string(blockID.Hash) != string(block.Hash) {
|
||||||
|
t.Fatal("unexpected blockID.hash")
|
||||||
|
}
|
||||||
step = 0
|
step = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -139,23 +139,14 @@ func (s *lwdStreamer) GetCurrentZECPrice(ctx context.Context, in *walletrpc.Empt
|
||||||
|
|
||||||
// GetLatestBlock returns the height of the best chain, according to zcashd.
|
// GetLatestBlock returns the height of the best chain, according to zcashd.
|
||||||
func (s *lwdStreamer) GetLatestBlock(ctx context.Context, placeholder *walletrpc.ChainSpec) (*walletrpc.BlockID, error) {
|
func (s *lwdStreamer) GetLatestBlock(ctx context.Context, placeholder *walletrpc.ChainSpec) (*walletrpc.BlockID, error) {
|
||||||
result, rpcErr := common.RawRequest("getblockchaininfo", []json.RawMessage{})
|
latestBlock := s.cache.GetLatestHeight()
|
||||||
if rpcErr != nil {
|
latestHash := s.cache.GetLatestHash()
|
||||||
return nil, rpcErr
|
|
||||||
}
|
if latestBlock == -1 {
|
||||||
var getblockchaininfoReply common.ZcashdRpcReplyGetblockchaininfo
|
return nil, errors.New("Cache is empty. Server is probably not yet ready")
|
||||||
err := json.Unmarshal(result, &getblockchaininfoReply)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hash, err := hex.DecodeString(getblockchaininfoReply.BestBlockHash)
|
return &walletrpc.BlockID{Height: uint64(latestBlock), Hash: latestHash}, nil
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
common.Metrics.LatestBlockCounter.Inc()
|
|
||||||
return &walletrpc.BlockID{Height: uint64(getblockchaininfoReply.Blocks), Hash: parser.Reverse(hash)}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetTaddressTxids is a streaming RPC that returns transaction IDs that have
|
// GetTaddressTxids is a streaming RPC that returns transaction IDs that have
|
||||||
|
@ -397,11 +388,12 @@ func (s *lwdStreamer) GetTreeState(ctx context.Context, id *walletrpc.BlockID) (
|
||||||
return nil, errors.New("zcashd did not return treestate")
|
return nil, errors.New("zcashd did not return treestate")
|
||||||
}
|
}
|
||||||
return &walletrpc.TreeState{
|
return &walletrpc.TreeState{
|
||||||
Network: s.chainName,
|
Network: s.chainName,
|
||||||
Height: uint64(gettreestateReply.Height),
|
Height: uint64(gettreestateReply.Height),
|
||||||
Hash: gettreestateReply.Hash,
|
Hash: gettreestateReply.Hash,
|
||||||
Time: gettreestateReply.Time,
|
Time: gettreestateReply.Time,
|
||||||
Tree: gettreestateReply.Sapling.Commitments.FinalState,
|
SaplingTree: gettreestateReply.Sapling.Commitments.FinalState,
|
||||||
|
OrchardTree: gettreestateReply.Orchard.Commitments.FinalState,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,8 +455,9 @@ func (s *lwdStreamer) SendTransaction(ctx context.Context, rawtx *walletrpc.RawT
|
||||||
// Result:
|
// Result:
|
||||||
// "hex" (string) The transaction hash in hex
|
// "hex" (string) The transaction hash in hex
|
||||||
|
|
||||||
|
// Verify rawtx
|
||||||
if rawtx == nil || rawtx.Data == nil {
|
if rawtx == nil || rawtx.Data == nil {
|
||||||
return nil, errors.New("Bad Transaction or Data")
|
return nil, errors.New("Bad transaction data")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Construct raw JSON-RPC params
|
// Construct raw JSON-RPC params
|
||||||
|
@ -562,6 +555,13 @@ func (s *lwdStreamer) GetTaddressBalanceStream(addresses walletrpc.CompactTxStre
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *lwdStreamer) GetMempoolStream(_empty *walletrpc.Empty, resp walletrpc.CompactTxStreamer_GetMempoolStreamServer) error {
|
||||||
|
err := common.GetMempool(func(tx *walletrpc.RawTransaction) error {
|
||||||
|
return resp.Send(tx)
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Key is 32-byte txid (as a 64-character string), data is pointer to compact tx.
|
// Key is 32-byte txid (as a 64-character string), data is pointer to compact tx.
|
||||||
var mempoolMap *map[string]*walletrpc.CompactTx
|
var mempoolMap *map[string]*walletrpc.CompactTx
|
||||||
var mempoolList []string
|
var mempoolList []string
|
||||||
|
@ -622,7 +622,7 @@ func (s *lwdStreamer) GetMempoolTx(exclude *walletrpc.Exclude, resp walletrpc.Co
|
||||||
return errors.New("extra data deserializing transaction")
|
return errors.New("extra data deserializing transaction")
|
||||||
}
|
}
|
||||||
newmempoolMap[txidstr] = &walletrpc.CompactTx{}
|
newmempoolMap[txidstr] = &walletrpc.CompactTx{}
|
||||||
if tx.HasSaplingElements() {
|
if tx.HasShieldedElements() {
|
||||||
newmempoolMap[txidstr] = tx.ToCompact( /* height */ 0)
|
newmempoolMap[txidstr] = tx.ToCompact( /* height */ 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -644,27 +644,6 @@ func (s *lwdStreamer) GetMempoolTx(exclude *walletrpc.Exclude, resp walletrpc.Co
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *lwdStreamer) GetMempoolStream(_empty *walletrpc.Empty, resp walletrpc.CompactTxStreamer_GetMempoolStreamServer) error {
|
|
||||||
ch := make(chan *walletrpc.RawTransaction, 200)
|
|
||||||
go common.AddNewClient(ch)
|
|
||||||
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case rtx, more := <-ch:
|
|
||||||
if !more || rtx == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.Send(rtx) != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Timeout after 5 mins
|
|
||||||
case <-time.After(5 * time.Minute):
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Return the subset of items that aren't excluded, but
|
// Return the subset of items that aren't excluded, but
|
||||||
// if more than one item matches an exclude entry, return
|
// if more than one item matches an exclude entry, return
|
||||||
// all those items.
|
// all those items.
|
||||||
|
@ -730,7 +709,7 @@ func getAddressUtxos(arg *walletrpc.GetAddressUtxosArg, f func(*walletrpc.GetAdd
|
||||||
if rpcErr != nil {
|
if rpcErr != nil {
|
||||||
return rpcErr
|
return rpcErr
|
||||||
}
|
}
|
||||||
var utxosReply common.ZcashdRpcReplyGetaddressutxos
|
var utxosReply []common.ZcashdRpcReplyGetaddressutxos
|
||||||
err = json.Unmarshal(result, &utxosReply)
|
err = json.Unmarshal(result, &utxosReply)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -909,3 +888,23 @@ func (s *DarksideStreamer) ClearIncomingTransactions(ctx context.Context, e *wal
|
||||||
common.DarksideClearIncomingTransactions()
|
common.DarksideClearIncomingTransactions()
|
||||||
return &walletrpc.Empty{}, nil
|
return &walletrpc.Empty{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AddAddressUtxo adds a UTXO which will be returned by GetAddressUtxos() (above)
|
||||||
|
func (s *DarksideStreamer) AddAddressUtxo(ctx context.Context, arg *walletrpc.GetAddressUtxosReply) (*walletrpc.Empty, error) {
|
||||||
|
utxosReply := common.ZcashdRpcReplyGetaddressutxos{
|
||||||
|
Address: arg.Address,
|
||||||
|
Txid: hex.EncodeToString(parser.Reverse(arg.Txid)),
|
||||||
|
OutputIndex: int64(arg.Index),
|
||||||
|
Script: hex.EncodeToString(arg.Script),
|
||||||
|
Satoshis: uint64(arg.ValueZat),
|
||||||
|
Height: int(arg.Height),
|
||||||
|
}
|
||||||
|
err := common.DarksideAddAddressUtxo(utxosReply)
|
||||||
|
return &walletrpc.Empty{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// ClearAddressUtxo removes the list of cached utxo entries
|
||||||
|
func (s *DarksideStreamer) ClearAddressUtxo(ctx context.Context, arg *walletrpc.Empty) (*walletrpc.Empty, error) {
|
||||||
|
err := common.DarksideClearAddressUtxos()
|
||||||
|
return &walletrpc.Empty{}, err
|
||||||
|
}
|
||||||
|
|
18
go.mod
18
go.mod
|
@ -5,27 +5,15 @@ go 1.12
|
||||||
require (
|
require (
|
||||||
github.com/btcsuite/btcd v0.20.1-beta
|
github.com/btcsuite/btcd v0.20.1-beta
|
||||||
github.com/golang/protobuf v1.5.2
|
github.com/golang/protobuf v1.5.2
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de // indirect
|
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect
|
|
||||||
github.com/kr/text v0.2.0 // indirect
|
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/client_golang v1.5.1
|
github.com/prometheus/client_golang v1.5.1
|
||||||
github.com/sirupsen/logrus v1.4.2
|
github.com/sirupsen/logrus v1.4.2
|
||||||
github.com/smartystreets/assertions v1.0.1 // indirect
|
|
||||||
github.com/spf13/afero v1.5.1 // indirect
|
|
||||||
github.com/spf13/cobra v1.0.0
|
github.com/spf13/cobra v1.0.0
|
||||||
github.com/spf13/viper v1.6.2
|
github.com/spf13/viper v1.6.2
|
||||||
github.com/stretchr/testify v1.6.1 // indirect
|
github.com/zcash/lightwalletd v0.4.12
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect
|
google.golang.org/grpc v1.44.0
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 // indirect
|
google.golang.org/protobuf v1.27.1
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 // indirect
|
|
||||||
golang.org/x/text v0.3.6 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20210406143921-e86de6bf7a46 // indirect
|
|
||||||
google.golang.org/grpc v1.37.0
|
|
||||||
google.golang.org/protobuf v1.26.0
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
gopkg.in/ini.v1 v1.51.0
|
gopkg.in/ini.v1 v1.51.0
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210105161348-2e78108cf5f8 // indirect
|
|
||||||
)
|
)
|
||||||
|
|
321
go.sum
321
go.sum
|
@ -1,18 +1,36 @@
|
||||||
cloud.google.com/go v0.26.0 h1:e0WKqKTd5BnrG8aKH3J3h+QvEIQtSUcf2n5UZ5ZgLtQ=
|
|
||||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
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 v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
|
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
|
||||||
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
|
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
|
||||||
|
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 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
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/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg=
|
|
||||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
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-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
|
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6 h1:G1bPvciwNyF7IUmKXNt9Ak3m6u9DE1rF+RmtIkBpVdA=
|
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
|
@ -26,77 +44,74 @@ github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6
|
||||||
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
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 h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw=
|
||||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd h1:qdGvebPBDuYDPGi1WCPjy1tGyMpmDK8IEapSsszn7HE=
|
|
||||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
||||||
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723 h1:ZA/jbKoGcVAnER6pCHPEkGdZOV7U1oLUedErBHCUMs0=
|
|
||||||
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/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 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc=
|
||||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||||
github.com/btcsuite/winsvc v1.0.0 h1:J9B4L7e3oqhXOcm+2IuNApwzQec85lE+QaikUcCs+dk=
|
|
||||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
|
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
|
||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI=
|
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||||
|
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||||
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403 h1:cqQfy1jclcSy/FwLjemeg3SR1yaINm74aQyupQ0Bl8M=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||||
github.com/coreos/bbolt v1.3.2 h1:wZwiHHUieZCquLkDL0B8UhzreNWsPHooDAG3q34zk0s=
|
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
|
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible h1:jFneRYjIvLMLhDLCzuTuU4rSJUjRplcJQ7pD7MnhC04=
|
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
github.com/coreos/go-semver v0.2.0 h1:3Jm3tLmsgAYcjC+4Up7hJrFBPr+n7rAqYeSw/SZazuY=
|
|
||||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e h1:Wf6HqHfScWJN9/ZjdUKyjop4mf3Qdd+1TvvltAvM3m8=
|
|
||||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
|
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
|
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
|
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
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 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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954 h1:RMLoZVzv4GliuWafOuPuQDKSm1SJph7uCRnnS61JAn4=
|
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d h1:QyzYnTnPE15SQyUeqU6qLbWxMkwyAyu+vGksa0b7j00=
|
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
|
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
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/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
github.com/fullstorydev/grpcurl v1.8.6/go.mod h1:WhP7fRQdhxz2TkL97u+TCb505sxfH78W1usyoB3tepw=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
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-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
|
|
||||||
github.com/go-kit/kit v0.9.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=
|
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||||
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
|
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
|
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
|
|
||||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||||
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/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef h1:veQD95Isof8w9/WXiA+pa3tz3fJXkt5B7QaRBrM62gk=
|
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1 h1:G5FRp8JnTd7RQH5kemVNlMeyXQAztQ3mOWV95KxsXH8=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
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/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
|
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
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=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
@ -104,10 +119,11 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
|
||||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
|
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
|
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/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
@ -116,57 +132,58 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
|
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-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
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-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de h1:F7WD09S8QB4LrkEpka0dFPLSotH11HRpCsLIbIcJ7sU=
|
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/gopherjs/gopherjs v0.0.0-20191106031601-ce3c9ade29de/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0 h1:Iju5GlWwrvL6UBg4zJJt3btmonfrMlCDdsejg4CZE7c=
|
||||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
|
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/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0 h1:bM6ZAFZmc/wPFaRDi0d5L7hGEZEx/2u+Tmr2evNHDiI=
|
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
|
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||||
|
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/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
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/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89 h1:12K8AlpT0/6QUXSfV0yi4Q0jkbq8NDtIKFtF61AoqV0=
|
|
||||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
github.com/jhump/protoreflect v1.10.3/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/jrick/logrotate v1.0.0 h1:lQ1bL/n9mBNeIXoTUoYRlK4dHuNJVofX9oWqBtPnSzI=
|
|
||||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
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.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
|
||||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
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.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
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/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||||
github.com/julienschmidt/httprouter v1.2.0 h1:TDTW5Yz1mjftljbcKqRcrYhd4XeOoI98t+9HbQbYf7g=
|
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/kisielk/errcheck v1.1.0 h1:ZqfnKyx9KGpRcW04j5nnPDgRgoXUeLh2YFBeFzphcA0=
|
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/gotool v1.0.0 h1:AV2c/EiW3KqPNT9ZKl07ehoAGi4C5/01Cfbblndcapg=
|
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23 h1:FOOIBWrEkLgmlgGfMuZT83xIwfPDxEI2OHu6xUmJMFE=
|
|
||||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||||
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.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
|
||||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515 h1:T+h1c/A9Gawja4Y9mFVWj2vyii2bbUNDw3kt9VxK2EY=
|
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
@ -176,24 +193,18 @@ github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzR
|
||||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
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/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
|
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223 h1:F9x/1yl3T2AeKLr2AMdilSD8+f9bvMnNN8VS5iDtovc=
|
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/oklog/ulid v1.3.1 h1:EGfNDEx6MqHz8B3uNV6QAib1UR2Lm97sHi3ocA6ESJ4=
|
github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
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.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
|
|
||||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
|
|
||||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
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/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||||
|
@ -201,7 +212,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.10.1 h1:VasscCm72135zRysgrJDKsntdmPN+OuU3+nnHYA9wyc=
|
|
||||||
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
@ -225,13 +235,11 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
|
github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8=
|
||||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||||
github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
|
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af h1:gu+uRPtBe88sKxUCEXRoeCvVG90TJmwhiqRpvdhQFng=
|
|
||||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
|
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
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=
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
|
@ -241,16 +249,13 @@ github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHei
|
||||||
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
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/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||||
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
|
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||||
github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg=
|
github.com/spf13/afero v1.5.1 h1:VHu76Lk0LSP1x254maIu2bplkWpfBWI+B+6fdoZprcg=
|
||||||
github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
github.com/spf13/afero v1.5.1/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
|
||||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||||
github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs=
|
|
||||||
github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||||
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
github.com/spf13/cobra v1.0.0 h1:6m/oheQuQ13N9ks4hubMG6BnvwOeaJrqSPLahSnczz8=
|
||||||
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
|
||||||
|
@ -262,75 +267,116 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y
|
||||||
github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E=
|
github.com/spf13/viper v1.6.2 h1:7aKfF+e8/k68gda3LOjo5RxiUqddoFxVq4BKBPrxk5E=
|
||||||
github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
|
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.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5 h1:LnC5Kc/wtumK+WB441p7ynQJzVuNRJiqddSIE3IlSEQ=
|
|
||||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||||
github.com/ugorji/go v1.1.4 h1:j4s+tAvLfL3bZyefP2SEWmhBzmuIlH/eqNuPdFPgngw=
|
|
||||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5Qo6v2eYzo7kUS51QINcR5jNpbZS8=
|
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77 h1:ESFSdwYZvkeru3RtdrYueztKhOBCSAAzS4Gf+k0tEow=
|
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
github.com/yuin/goldmark v1.2.1 h1:ruQGxdhGHe7FWOJPT0mKs5+pD2Xs1Bm/kdGlHO04FmM=
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
|
github.com/zcash/lightwalletd v0.4.12 h1:PAPB3GpHw3LCf30SskHw1sXKcRZq5bjmKH1Awkm9U+I=
|
||||||
|
github.com/zcash/lightwalletd v0.4.12/go.mod h1:KsNsRWUATRvWuhsW/h0thygNtT7JIEJQFNW0r2wXIuA=
|
||||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||||
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
|
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.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
|
|
||||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||||
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
|
|
||||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
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-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-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-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-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY=
|
||||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4 h1:c2HOrn5iMezYjSlGPncknSEr/8x5LELb/ilJbXi9DEA=
|
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
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-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
|
||||||
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
|
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
|
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/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
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-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-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
|
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/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
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/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/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/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-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-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-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-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-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-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-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-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-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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
|
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
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-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/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
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-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-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-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/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
|
@ -338,10 +384,25 @@ 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-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-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-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-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-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-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
@ -351,47 +412,110 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
|
||||||
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
|
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-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/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-20180221164845-07fd8470d635/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-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-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-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-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-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-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-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
|
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
|
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
|
golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/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.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
|
|
||||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
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/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
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-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-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/genproto v0.0.0-20210406143921-e86de6bf7a46 h1:f4STrQZf8jaowsiUitigvrqMCCM4QJH1A2JCSI7U1ow=
|
google.golang.org/genproto v0.0.0-20210406143921-e86de6bf7a46 h1:f4STrQZf8jaowsiUitigvrqMCCM4QJH1A2JCSI7U1ow=
|
||||||
google.golang.org/genproto v0.0.0-20210406143921-e86de6bf7a46/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
google.golang.org/genproto v0.0.0-20210406143921-e86de6bf7a46/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
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.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.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||||
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
|
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||||
|
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||||
google.golang.org/grpc v1.37.0 h1:uSZWeQJX5j11bIQ4AJoj+McDBo29cY1MCoC1wO3ts+c=
|
google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg=
|
||||||
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
@ -401,27 +525,27 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
|
google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||||
|
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
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/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/resty.v1 v1.12.0 h1:CuXP0Pjfw9rOuY6EP+UvtNvt5DSqHpIxILZKT/quCZI=
|
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
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 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
|
||||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
@ -429,5 +553,12 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210105161348-2e78108cf5f8 h1:tH9C0MON9YI3/KuD+u5+tQrQQ8px0MrcJ/avzeALw7o=
|
gopkg.in/yaml.v3 v3.0.0-20210105161348-2e78108cf5f8 h1:tH9C0MON9YI3/KuD+u5+tQrQQ8px0MrcJ/avzeALw7o=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210105161348-2e78108cf5f8/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210105161348-2e78108cf5f8/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/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-20190523083050-ea95bdfd59fc h1:/hemPrYIhOhy8zYrNj+069zDB68us2sMGsfkFJO0iZs=
|
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.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
|
|
@ -62,7 +62,7 @@ func (b *Block) GetDisplayPrevHash() []byte {
|
||||||
// HasSaplingTransactions indicates if the block contains any Sapling tx.
|
// HasSaplingTransactions indicates if the block contains any Sapling tx.
|
||||||
func (b *Block) HasSaplingTransactions() bool {
|
func (b *Block) HasSaplingTransactions() bool {
|
||||||
for _, tx := range b.vtx {
|
for _, tx := range b.vtx {
|
||||||
if tx.HasSaplingElements() {
|
if tx.HasShieldedElements() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ func (b *Block) ToCompact() *walletrpc.CompactBlock {
|
||||||
// Only Sapling transactions have a meaningful compact encoding
|
// Only Sapling transactions have a meaningful compact encoding
|
||||||
saplingTxns := make([]*walletrpc.CompactTx, 0, len(b.vtx))
|
saplingTxns := make([]*walletrpc.CompactTx, 0, len(b.vtx))
|
||||||
for idx, tx := range b.vtx {
|
for idx, tx := range b.vtx {
|
||||||
if tx.HasSaplingElements() {
|
if tx.HasShieldedElements() {
|
||||||
saplingTxns = append(saplingTxns, tx.ToCompact(idx))
|
saplingTxns = append(saplingTxns, tx.ToCompact(idx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -134,7 +134,7 @@ func TestBlockHeader(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is not necessarily true for anything but our current test cases.
|
// This is not necessarily true for anything but our current test cases.
|
||||||
for _, b := range hash[:4] {
|
for _, b := range hash[:1] {
|
||||||
if b != 0 {
|
if b != 0 {
|
||||||
t.Errorf("Hash lacked leading zeros: %x", hash)
|
t.Errorf("Hash lacked leading zeros: %x", hash)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,11 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -18,200 +16,6 @@ import (
|
||||||
protobuf "github.com/golang/protobuf/proto"
|
protobuf "github.com/golang/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBlockParser(t *testing.T) {
|
|
||||||
// These (valid on testnet) correspond to the transactions in testdata/blocks;
|
|
||||||
// for each block, the hashes for the tx within that block.
|
|
||||||
var txhashes = [][]string{
|
|
||||||
{
|
|
||||||
"81096ff101a4f01d25ffd34a446bee4368bd46c233a59ac0faf101e1861c6b22",
|
|
||||||
}, {
|
|
||||||
"921dc41bef3a0d887c615abac60a29979efc8b4bbd3d887caeb6bb93501bde8e",
|
|
||||||
}, {
|
|
||||||
"d8e4c336ffa69dacaa4e0b4eaf8e3ae46897f1930a573c10b53837a03318c980",
|
|
||||||
"4d5ccbfc6984680c481ff5ce145b8a93d59dfea90c150dfa45c938ab076ee5b2",
|
|
||||||
}, {
|
|
||||||
"df2b03619d441ce3d347e9278d87618e975079d0e235dfb3b3d8271510f707aa",
|
|
||||||
"8d2593edfc328fa637b4ac91c7d569ee922bb9a6fda7cea230e92deb3ae4b634",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
testBlocks, err := os.Open("../testdata/blocks")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer testBlocks.Close()
|
|
||||||
|
|
||||||
scan := bufio.NewScanner(testBlocks)
|
|
||||||
for blockindex := 0; scan.Scan(); blockindex++ {
|
|
||||||
blockDataHex := scan.Text()
|
|
||||||
blockData, err := hex.DecodeString(blockDataHex)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is just a sanity check of the test:
|
|
||||||
if int(blockData[1487]) != len(txhashes[blockindex]) {
|
|
||||||
t.Error("wrong number of transactions, test broken?")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make a copy of just the transactions alone, which,
|
|
||||||
// for these blocks, start just beyond the header and
|
|
||||||
// the one-byte nTx value, which is offset 1488.
|
|
||||||
transactions := make([]byte, len(blockData[1488:]))
|
|
||||||
copy(transactions, blockData[1488:])
|
|
||||||
|
|
||||||
// Each iteration of this loop appends the block's original
|
|
||||||
// transactions, so we build an ever-larger block. The loop
|
|
||||||
// limit is arbitrary, but make sure we get into double-digit
|
|
||||||
// transaction counts (compact integer).
|
|
||||||
for i := 0; i < 264; i++ {
|
|
||||||
b := blockData
|
|
||||||
block := NewBlock()
|
|
||||||
b, err = block.ParseFromSlice(b)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(errors.Wrap(err, fmt.Sprintf("parsing block %d", i)))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(b) > 0 {
|
|
||||||
t.Error("Extra data remaining")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some basic sanity checks
|
|
||||||
if block.hdr.Version != 4 {
|
|
||||||
t.Error("Read wrong version in a test block.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if block.GetVersion() != 4 {
|
|
||||||
t.Error("Read wrong version in a test block.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if block.GetTxCount() < 1 {
|
|
||||||
t.Error("No transactions in block")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if len(block.Transactions()) != block.GetTxCount() {
|
|
||||||
t.Error("Number of transactions mismatch")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if block.GetTxCount() != len(txhashes[blockindex])*(i+1) {
|
|
||||||
t.Error("Unexpected number of transactions")
|
|
||||||
}
|
|
||||||
if block.HasSaplingTransactions() {
|
|
||||||
t.Error("Unexpected Sapling tx")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
for txindex, tx := range block.Transactions() {
|
|
||||||
if tx.HasSaplingElements() {
|
|
||||||
t.Error("Unexpected Sapling tx")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
expectedHash := txhashes[blockindex][txindex%len(txhashes[blockindex])]
|
|
||||||
if hex.EncodeToString(tx.GetDisplayHash()) != expectedHash {
|
|
||||||
t.Error("incorrect tx hash")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Keep appending the original transactions, which is unrealistic
|
|
||||||
// because the coinbase is being replicated, but it works; first do
|
|
||||||
// some surgery to the transaction count (see DarksideApplyStaged()).
|
|
||||||
for j := 0; j < len(txhashes[blockindex]); j++ {
|
|
||||||
nTxFirstByte := blockData[1487]
|
|
||||||
switch {
|
|
||||||
case nTxFirstByte < 252:
|
|
||||||
blockData[1487]++
|
|
||||||
case nTxFirstByte == 252:
|
|
||||||
// incrementing to 253, requires "253" followed by 2-byte length,
|
|
||||||
// extend the block by two bytes, shift existing transaction bytes
|
|
||||||
blockData = append(blockData, 0, 0)
|
|
||||||
copy(blockData[1490:], blockData[1488:len(blockData)-2])
|
|
||||||
blockData[1487] = 253
|
|
||||||
blockData[1488] = 253
|
|
||||||
blockData[1489] = 0
|
|
||||||
case nTxFirstByte == 253:
|
|
||||||
blockData[1488]++
|
|
||||||
if blockData[1488] == 0 {
|
|
||||||
// wrapped around
|
|
||||||
blockData[1489]++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
blockData = append(blockData, transactions...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestBlockParserFail(t *testing.T) {
|
|
||||||
testBlocks, err := os.Open("../testdata/badblocks")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer testBlocks.Close()
|
|
||||||
|
|
||||||
scan := bufio.NewScanner(testBlocks)
|
|
||||||
|
|
||||||
// the first "block" contains an illegal hex character
|
|
||||||
{
|
|
||||||
scan.Scan()
|
|
||||||
blockDataHex := scan.Text()
|
|
||||||
_, err := hex.DecodeString(blockDataHex)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("unexpected success parsing illegal hex bad block")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; scan.Scan(); i++ {
|
|
||||||
blockDataHex := scan.Text()
|
|
||||||
blockData, err := hex.DecodeString(blockDataHex)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
block := NewBlock()
|
|
||||||
blockData, err = block.ParseFromSlice(blockData)
|
|
||||||
if err == nil {
|
|
||||||
t.Error("unexpected success parsing bad block")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Checks on the first 20 blocks from mainnet genesis.
|
|
||||||
func TestGenesisBlockParser(t *testing.T) {
|
|
||||||
blockFile, err := os.Open("../testdata/mainnet_genesis")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
defer blockFile.Close()
|
|
||||||
|
|
||||||
scan := bufio.NewScanner(blockFile)
|
|
||||||
for i := 0; scan.Scan(); i++ {
|
|
||||||
blockDataHex := scan.Text()
|
|
||||||
blockData, err := hex.DecodeString(blockDataHex)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
block := NewBlock()
|
|
||||||
blockData, err = block.ParseFromSlice(blockData)
|
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if len(blockData) > 0 {
|
|
||||||
t.Error("Extra data remaining")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Some basic sanity checks
|
|
||||||
if block.hdr.Version != 4 {
|
|
||||||
t.Error("Read wrong version in genesis block.")
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if block.GetHeight() != i {
|
|
||||||
t.Errorf("Got wrong height for block %d: %d", i, block.GetHeight())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCompactBlocks(t *testing.T) {
|
func TestCompactBlocks(t *testing.T) {
|
||||||
type compactTest struct {
|
type compactTest struct {
|
||||||
BlockHeight int `json:"block"`
|
BlockHeight int `json:"block"`
|
||||||
|
|
|
@ -154,6 +154,16 @@ func (s *String) ReadCompactLengthPrefixed(out *String) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SkipCompactLengthPrefixed skips a CompactSize-encoded
|
||||||
|
// length field.
|
||||||
|
func (s *String) SkipCompactLengthPrefixed() bool {
|
||||||
|
var length int
|
||||||
|
if !s.ReadCompactSize(&length) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return s.Skip(length)
|
||||||
|
}
|
||||||
|
|
||||||
// ReadInt32 decodes a little-endian 32-bit value into out, treating it as
|
// ReadInt32 decodes a little-endian 32-bit value into out, treating it as
|
||||||
// signed, and advances over it. It reports whether the read was successful.
|
// signed, and advances over it. It reports whether the read was successful.
|
||||||
func (s *String) ReadInt32(out *int32) bool {
|
func (s *String) ReadInt32(out *int32) bool {
|
||||||
|
|
|
@ -261,6 +261,38 @@ func TestString_ReadCompactLengthPrefixed(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestString_SkipCompactLengthPrefixed(t *testing.T) {
|
||||||
|
// a stream of 3 bytes followed by 2 bytes into the value variable, v
|
||||||
|
s := String{3, 55, 66, 77, 2, 88, 99}
|
||||||
|
|
||||||
|
// read the 3 and thus the following 3 bytes
|
||||||
|
if !s.SkipCompactLengthPrefixed() {
|
||||||
|
t.Fatalf("SkipCompactLengthPrefix failed")
|
||||||
|
}
|
||||||
|
if len(s) != 3 {
|
||||||
|
t.Fatalf("SkipCompactLengthPrefix incorrect remaining length")
|
||||||
|
}
|
||||||
|
|
||||||
|
// read the 2 and then two bytes
|
||||||
|
if !s.SkipCompactLengthPrefixed() {
|
||||||
|
t.Fatalf("SkipCompactLengthPrefix failed")
|
||||||
|
}
|
||||||
|
if len(s) != 0 {
|
||||||
|
t.Fatalf("SkipCompactLengthPrefix incorrect remaining length")
|
||||||
|
}
|
||||||
|
|
||||||
|
// at the end of the String, another read should return false
|
||||||
|
if s.SkipCompactLengthPrefixed() {
|
||||||
|
t.Fatalf("SkipCompactLengthPrefix unexpected success")
|
||||||
|
}
|
||||||
|
|
||||||
|
// this string is too short (less than 2 bytes of data)
|
||||||
|
s = String{3, 55, 66}
|
||||||
|
if s.SkipCompactLengthPrefixed() {
|
||||||
|
t.Fatalf("SkipdCompactLengthPrefix unexpected success")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var readInt32Tests = []struct {
|
var readInt32Tests = []struct {
|
||||||
s String
|
s String
|
||||||
expected int32
|
expected int32
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/adityapk00/lightwalletd/parser/internal/bytestring"
|
"github.com/adityapk00/lightwalletd/parser/internal/bytestring"
|
||||||
|
@ -17,51 +17,53 @@ type rawTransaction struct {
|
||||||
fOverwintered bool
|
fOverwintered bool
|
||||||
version uint32
|
version uint32
|
||||||
nVersionGroupID uint32
|
nVersionGroupID uint32
|
||||||
transparentInputs []*txIn
|
consensusBranchID uint32
|
||||||
transparentOutputs []*txOut
|
transparentInputs []txIn
|
||||||
nLockTime uint32
|
transparentOutputs []txOut
|
||||||
nExpiryHeight uint32
|
//nLockTime uint32
|
||||||
valueBalance int64
|
//nExpiryHeight uint32
|
||||||
shieldedSpends []*spend
|
//valueBalanceSapling int64
|
||||||
shieldedOutputs []*output
|
shieldedSpends []spend
|
||||||
joinSplits []*joinSplit
|
shieldedOutputs []output
|
||||||
joinSplitPubKey []byte
|
joinSplits []joinSplit
|
||||||
joinSplitSig []byte
|
//joinSplitPubKey []byte
|
||||||
bindingSig []byte
|
//joinSplitSig []byte
|
||||||
|
//bindingSigSapling []byte
|
||||||
|
orchardActions []action
|
||||||
}
|
}
|
||||||
|
|
||||||
// Txin format as described in https://en.bitcoin.it/wiki/Transaction
|
// Txin format as described in https://en.bitcoin.it/wiki/Transaction
|
||||||
type txIn struct {
|
type txIn struct {
|
||||||
// SHA256d of a previous (to-be-used) transaction
|
// SHA256d of a previous (to-be-used) transaction
|
||||||
PrevTxHash []byte
|
//PrevTxHash []byte
|
||||||
|
|
||||||
// Index of the to-be-used output in the previous tx
|
// Index of the to-be-used output in the previous tx
|
||||||
PrevTxOutIndex uint32
|
//PrevTxOutIndex uint32
|
||||||
|
|
||||||
// CompactSize-prefixed, could be a pubkey or a script
|
// CompactSize-prefixed, could be a pubkey or a script
|
||||||
ScriptSig []byte
|
ScriptSig []byte
|
||||||
|
|
||||||
// Bitcoin: "normally 0xFFFFFFFF; irrelevant unless transaction's lock_time > 0"
|
// Bitcoin: "normally 0xFFFFFFFF; irrelevant unless transaction's lock_time > 0"
|
||||||
SequenceNumber uint32
|
//SequenceNumber uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *txIn) ParseFromSlice(data []byte) ([]byte, error) {
|
func (tx *txIn) ParseFromSlice(data []byte) ([]byte, error) {
|
||||||
s := bytestring.String(data)
|
s := bytestring.String(data)
|
||||||
|
|
||||||
if !s.ReadBytes(&tx.PrevTxHash, 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read PrevTxHash")
|
return nil, errors.New("could not skip PrevTxHash")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadUint32(&tx.PrevTxOutIndex) {
|
if !s.Skip(4) {
|
||||||
return nil, errors.New("could not read PrevTxOutIndex")
|
return nil, errors.New("could not skip PrevTxOutIndex")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadCompactLengthPrefixed((*bytestring.String)(&tx.ScriptSig)) {
|
if !s.ReadCompactLengthPrefixed((*bytestring.String)(&tx.ScriptSig)) {
|
||||||
return nil, errors.New("could not read ScriptSig")
|
return nil, errors.New("could not read ScriptSig")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadUint32(&tx.SequenceNumber) {
|
if !s.Skip(4) {
|
||||||
return nil, errors.New("could not read SequenceNumber")
|
return nil, errors.New("could not skip SequenceNumber")
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(s), nil
|
return []byte(s), nil
|
||||||
|
@ -73,86 +75,118 @@ type txOut struct {
|
||||||
Value uint64
|
Value uint64
|
||||||
|
|
||||||
// Script. CompactSize-prefixed.
|
// Script. CompactSize-prefixed.
|
||||||
Script []byte
|
//Script []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tx *txOut) ParseFromSlice(data []byte) ([]byte, error) {
|
func (tx *txOut) ParseFromSlice(data []byte) ([]byte, error) {
|
||||||
s := bytestring.String(data)
|
s := bytestring.String(data)
|
||||||
|
|
||||||
if !s.ReadUint64(&tx.Value) {
|
if !s.Skip(8) {
|
||||||
return nil, errors.New("could not read txOut value")
|
return nil, errors.New("could not skip txOut value")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadCompactLengthPrefixed((*bytestring.String)(&tx.Script)) {
|
if !s.SkipCompactLengthPrefixed() {
|
||||||
return nil, errors.New("could not read txOut script")
|
return nil, errors.New("could not skip txOut script")
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(s), nil
|
return []byte(s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// spend is a Sapling Spend Description as described in 7.3 of the Zcash
|
// parse the transparent parts of the transaction
|
||||||
// protocol spec. Total size is 384 bytes.
|
func (tx *Transaction) ParseTransparent(data []byte) ([]byte, error) {
|
||||||
type spend struct {
|
|
||||||
cv []byte // 32
|
|
||||||
anchor []byte // 32
|
|
||||||
nullifier []byte // 32
|
|
||||||
rk []byte // 32
|
|
||||||
zkproof []byte // 192
|
|
||||||
spendAuthSig []byte // 64
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *spend) ParseFromSlice(data []byte) ([]byte, error) {
|
|
||||||
s := bytestring.String(data)
|
s := bytestring.String(data)
|
||||||
|
var txInCount int
|
||||||
if !s.ReadBytes(&p.cv, 32) {
|
if !s.ReadCompactSize(&txInCount) {
|
||||||
return nil, errors.New("could not read cv")
|
return nil, errors.New("could not read tx_in_count")
|
||||||
|
}
|
||||||
|
var err error
|
||||||
|
tx.transparentInputs = make([]txIn, txInCount)
|
||||||
|
for i := 0; i < txInCount; i++ {
|
||||||
|
ti := &tx.transparentInputs[i]
|
||||||
|
s, err = ti.ParseFromSlice([]byte(s))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "while parsing transparent input")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.anchor, 32) {
|
var txOutCount int
|
||||||
return nil, errors.New("could not read anchor")
|
if !s.ReadCompactSize(&txOutCount) {
|
||||||
|
return nil, errors.New("could not read tx_out_count")
|
||||||
|
}
|
||||||
|
tx.transparentOutputs = make([]txOut, txOutCount)
|
||||||
|
for i := 0; i < txOutCount; i++ {
|
||||||
|
to := &tx.transparentOutputs[i]
|
||||||
|
s, err = to.ParseFromSlice([]byte(s))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "while parsing transparent output")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return []byte(s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// spend is a Sapling Spend Description as described in 7.3 of the Zcash
|
||||||
|
// protocol specification.
|
||||||
|
type spend struct {
|
||||||
|
//cv []byte // 32
|
||||||
|
//anchor []byte // 32
|
||||||
|
nullifier []byte // 32
|
||||||
|
//rk []byte // 32
|
||||||
|
//zkproof []byte // 192
|
||||||
|
//spendAuthSig []byte // 64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *spend) ParseFromSlice(data []byte, version uint32) ([]byte, error) {
|
||||||
|
s := bytestring.String(data)
|
||||||
|
|
||||||
|
if !s.Skip(32) {
|
||||||
|
return nil, errors.New("could not skip cv")
|
||||||
|
}
|
||||||
|
|
||||||
|
if version <= 4 && !s.Skip(32) {
|
||||||
|
return nil, errors.New("could not skip anchor")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.nullifier, 32) {
|
if !s.ReadBytes(&p.nullifier, 32) {
|
||||||
return nil, errors.New("could not read nullifier")
|
return nil, errors.New("could not read nullifier")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.rk, 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read rk")
|
return nil, errors.New("could not skip rk")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.zkproof, 192) {
|
if version <= 4 && !s.Skip(192) {
|
||||||
return nil, errors.New("could not read zkproof")
|
return nil, errors.New("could not skip zkproof")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.spendAuthSig, 64) {
|
if version <= 4 && !s.Skip(64) {
|
||||||
return nil, errors.New("could not read spendAuthSig")
|
return nil, errors.New("could not skip spendAuthSig")
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(s), nil
|
return []byte(s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *spend) ToCompact() *walletrpc.CompactSpend {
|
func (p *spend) ToCompact() *walletrpc.CompactSaplingSpend {
|
||||||
return &walletrpc.CompactSpend{
|
return &walletrpc.CompactSaplingSpend{
|
||||||
Nf: p.nullifier,
|
Nf: p.nullifier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// output is a Sapling Output Description as described in section 7.4 of the
|
// output is a Sapling Output Description as described in section 7.4 of the
|
||||||
// Zcash protocol spec. Total size is 948.
|
// Zcash protocol spec.
|
||||||
type output struct {
|
type output struct {
|
||||||
cv []byte // 32
|
//cv []byte // 32
|
||||||
cmu []byte // 32
|
cmu []byte // 32
|
||||||
ephemeralKey []byte // 32
|
ephemeralKey []byte // 32
|
||||||
encCiphertext []byte // 580
|
encCiphertext []byte // 580
|
||||||
outCiphertext []byte // 80
|
//outCiphertext []byte // 80
|
||||||
zkproof []byte // 192
|
//zkproof []byte // 192
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *output) ParseFromSlice(data []byte) ([]byte, error) {
|
func (p *output) ParseFromSlice(data []byte, version uint32) ([]byte, error) {
|
||||||
s := bytestring.String(data)
|
s := bytestring.String(data)
|
||||||
|
|
||||||
if !s.ReadBytes(&p.cv, 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read cv")
|
return nil, errors.New("could not skip cv")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.cmu, 32) {
|
if !s.ReadBytes(&p.cmu, 32) {
|
||||||
|
@ -167,19 +201,19 @@ func (p *output) ParseFromSlice(data []byte) ([]byte, error) {
|
||||||
return nil, errors.New("could not read encCiphertext")
|
return nil, errors.New("could not read encCiphertext")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.outCiphertext, 80) {
|
if !s.Skip(80) {
|
||||||
return nil, errors.New("could not read outCiphertext")
|
return nil, errors.New("could not skip outCiphertext")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.zkproof, 192) {
|
if version <= 4 && !s.Skip(192) {
|
||||||
return nil, errors.New("could not read zkproof")
|
return nil, errors.New("could not skip zkproof")
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(s), nil
|
return []byte(s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *output) ToCompact() *walletrpc.CompactOutput {
|
func (p *output) ToCompact() *walletrpc.CompactSaplingOutput {
|
||||||
return &walletrpc.CompactOutput{
|
return &walletrpc.CompactSaplingOutput{
|
||||||
Cmu: p.cmu,
|
Cmu: p.cmu,
|
||||||
Epk: p.ephemeralKey,
|
Epk: p.ephemeralKey,
|
||||||
Ciphertext: p.encCiphertext[:52],
|
Ciphertext: p.encCiphertext[:52],
|
||||||
|
@ -188,112 +222,139 @@ func (p *output) ToCompact() *walletrpc.CompactOutput {
|
||||||
|
|
||||||
// joinSplit is a JoinSplit description as described in 7.2 of the Zcash
|
// joinSplit is a JoinSplit description as described in 7.2 of the Zcash
|
||||||
// protocol spec. Its exact contents differ by transaction version and network
|
// protocol spec. Its exact contents differ by transaction version and network
|
||||||
// upgrade level.
|
// upgrade level. Only version 4 is supported, no need for proofPHGR13.
|
||||||
type joinSplit struct {
|
type joinSplit struct {
|
||||||
vpubOld uint64
|
//vpubOld uint64
|
||||||
vpubNew uint64
|
//vpubNew uint64
|
||||||
anchor []byte // 32
|
//anchor []byte // 32
|
||||||
nullifiers [2][]byte // 64 [N_old][32]byte
|
//nullifiers [2][]byte // 64 [N_old][32]byte
|
||||||
commitments [2][]byte // 64 [N_new][32]byte
|
//commitments [2][]byte // 64 [N_new][32]byte
|
||||||
ephemeralKey []byte // 32
|
//ephemeralKey []byte // 32
|
||||||
randomSeed []byte // 32
|
//randomSeed []byte // 32
|
||||||
vmacs [2][]byte // 64 [N_old][32]byte
|
//vmacs [2][]byte // 64 [N_old][32]byte
|
||||||
proofPHGR13 []byte // 296
|
//proofGroth16 []byte // 192 (version 4 only)
|
||||||
proofGroth16 []byte // 192
|
//encCiphertexts [2][]byte // 1202 [N_new][601]byte
|
||||||
encCiphertexts [2][]byte // 1202 [N_new][601]byte
|
|
||||||
|
|
||||||
// not actually in the format, but needed for parsing
|
|
||||||
version uint32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *joinSplit) ParseFromSlice(data []byte) ([]byte, error) {
|
func (p *joinSplit) ParseFromSlice(data []byte) ([]byte, error) {
|
||||||
s := bytestring.String(data)
|
s := bytestring.String(data)
|
||||||
|
|
||||||
if !s.ReadUint64(&p.vpubOld) {
|
if !s.Skip(8) {
|
||||||
return nil, errors.New("could not read vpubOld")
|
return nil, errors.New("could not skip vpubOld")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadUint64(&p.vpubNew) {
|
if !s.Skip(8) {
|
||||||
return nil, errors.New("could not read vpubNew")
|
return nil, errors.New("could not skip vpubNew")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.anchor, 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read anchor")
|
return nil, errors.New("could not skip anchor")
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
if !s.ReadBytes(&p.nullifiers[i], 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read a nullifier")
|
return nil, errors.New("could not skip a nullifier")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
if !s.ReadBytes(&p.commitments[i], 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read a commitment")
|
return nil, errors.New("could not skip a commitment")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.ephemeralKey, 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read ephemeralKey")
|
return nil, errors.New("could not skip ephemeralKey")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.ReadBytes(&p.randomSeed, 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read randomSeed")
|
return nil, errors.New("could not skip randomSeed")
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
if !s.ReadBytes(&p.vmacs[i], 32) {
|
if !s.Skip(32) {
|
||||||
return nil, errors.New("could not read a vmac")
|
return nil, errors.New("could not skip a vmac")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if p.version == 2 || p.version == 3 {
|
if !s.Skip(192) {
|
||||||
if !s.ReadBytes(&p.proofPHGR13, 296) {
|
return nil, errors.New("could not skip Groth16 proof")
|
||||||
return nil, errors.New("could not read PHGR13 proof")
|
|
||||||
}
|
|
||||||
} else if p.version >= 4 {
|
|
||||||
if !s.ReadBytes(&p.proofGroth16, 192) {
|
|
||||||
return nil, errors.New("could not read Groth16 proof")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("unexpected transaction version")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < 2; i++ {
|
for i := 0; i < 2; i++ {
|
||||||
if !s.ReadBytes(&p.encCiphertexts[i], 601) {
|
if !s.Skip(601) {
|
||||||
return nil, errors.New("could not read an encCiphertext")
|
return nil, errors.New("could not skip an encCiphertext")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return []byte(s), nil
|
return []byte(s), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type action struct {
|
||||||
|
//cv []byte // 32
|
||||||
|
nullifier []byte // 32
|
||||||
|
//rk []byte // 32
|
||||||
|
cmx []byte // 32
|
||||||
|
ephemeralKey []byte // 32
|
||||||
|
encCiphertext []byte // 580
|
||||||
|
//outCiphertext []byte // 80
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *action) ParseFromSlice(data []byte) ([]byte, error) {
|
||||||
|
s := bytestring.String(data)
|
||||||
|
if !s.Skip(32) {
|
||||||
|
return nil, errors.New("could not read action cv")
|
||||||
|
}
|
||||||
|
if !s.ReadBytes(&a.nullifier, 32) {
|
||||||
|
return nil, errors.New("could not read action nullifier")
|
||||||
|
}
|
||||||
|
if !s.Skip(32) {
|
||||||
|
return nil, errors.New("could not read action rk")
|
||||||
|
}
|
||||||
|
if !s.ReadBytes(&a.cmx, 32) {
|
||||||
|
return nil, errors.New("could not read action cmx")
|
||||||
|
}
|
||||||
|
if !s.ReadBytes(&a.ephemeralKey, 32) {
|
||||||
|
return nil, errors.New("could not read action ephemeralKey")
|
||||||
|
}
|
||||||
|
if !s.ReadBytes(&a.encCiphertext, 580) {
|
||||||
|
return nil, errors.New("could not read action encCiphertext")
|
||||||
|
}
|
||||||
|
if !s.Skip(80) {
|
||||||
|
return nil, errors.New("could not read action outCiphertext")
|
||||||
|
}
|
||||||
|
return []byte(s), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *action) ToCompact() *walletrpc.CompactOrchardAction {
|
||||||
|
return &walletrpc.CompactOrchardAction{
|
||||||
|
Nullifier: p.nullifier,
|
||||||
|
Cmx: p.cmx,
|
||||||
|
EphemeralKey: p.ephemeralKey,
|
||||||
|
Ciphertext: p.encCiphertext[:52],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Transaction encodes a full (zcashd) transaction.
|
// Transaction encodes a full (zcashd) transaction.
|
||||||
type Transaction struct {
|
type Transaction struct {
|
||||||
*rawTransaction
|
*rawTransaction
|
||||||
rawBytes []byte
|
rawBytes []byte
|
||||||
cachedTxID []byte // cached for performance
|
txID []byte // from getblock verbose=1
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tx *Transaction) SetTxID(txid []byte) {
|
||||||
|
tx.txID = txid
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetDisplayHash returns the transaction hash in big-endian display order.
|
// GetDisplayHash returns the transaction hash in big-endian display order.
|
||||||
func (tx *Transaction) GetDisplayHash() []byte {
|
func (tx *Transaction) GetDisplayHash() []byte {
|
||||||
if tx.cachedTxID != nil {
|
|
||||||
return tx.cachedTxID
|
|
||||||
}
|
|
||||||
|
|
||||||
// SHA256d
|
|
||||||
digest := sha256.Sum256(tx.rawBytes)
|
|
||||||
digest = sha256.Sum256(digest[:])
|
|
||||||
// Convert to big-endian
|
// Convert to big-endian
|
||||||
tx.cachedTxID = Reverse(digest[:])
|
return Reverse(tx.txID[:])
|
||||||
return tx.cachedTxID
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetEncodableHash returns the transaction hash in little-endian wire format order.
|
// GetEncodableHash returns the transaction hash in little-endian wire format order.
|
||||||
func (tx *Transaction) GetEncodableHash() []byte {
|
func (tx *Transaction) GetEncodableHash() []byte {
|
||||||
digest := sha256.Sum256(tx.rawBytes)
|
return tx.txID
|
||||||
digest = sha256.Sum256(digest[:])
|
|
||||||
return digest[:]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bytes returns a full transaction's raw bytes.
|
// Bytes returns a full transaction's raw bytes.
|
||||||
|
@ -301,10 +362,11 @@ func (tx *Transaction) Bytes() []byte {
|
||||||
return tx.rawBytes
|
return tx.rawBytes
|
||||||
}
|
}
|
||||||
|
|
||||||
// HasSaplingElements indicates whether a transaction has
|
// HasShieldedElements indicates whether a transaction has
|
||||||
// at least one shielded input or output.
|
// at least one shielded input or output.
|
||||||
func (tx *Transaction) HasSaplingElements() bool {
|
func (tx *Transaction) HasShieldedElements() bool {
|
||||||
return tx.version >= 4 && (len(tx.shieldedSpends)+len(tx.shieldedOutputs)) > 0
|
nshielded := len(tx.shieldedSpends) + len(tx.shieldedOutputs) + len(tx.orchardActions)
|
||||||
|
return tx.version >= 4 && nshielded > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToCompact converts the given (full) transaction to compact format.
|
// ToCompact converts the given (full) transaction to compact format.
|
||||||
|
@ -313,8 +375,9 @@ func (tx *Transaction) ToCompact(index int) *walletrpc.CompactTx {
|
||||||
Index: uint64(index), // index is contextual
|
Index: uint64(index), // index is contextual
|
||||||
Hash: tx.GetEncodableHash(),
|
Hash: tx.GetEncodableHash(),
|
||||||
//Fee: 0, // TODO: calculate fees
|
//Fee: 0, // TODO: calculate fees
|
||||||
Spends: make([]*walletrpc.CompactSpend, len(tx.shieldedSpends)),
|
Spends: make([]*walletrpc.CompactSaplingSpend, len(tx.shieldedSpends)),
|
||||||
Outputs: make([]*walletrpc.CompactOutput, len(tx.shieldedOutputs)),
|
Outputs: make([]*walletrpc.CompactSaplingOutput, len(tx.shieldedOutputs)),
|
||||||
|
Actions: make([]*walletrpc.CompactOrchardAction, len(tx.orchardActions)),
|
||||||
}
|
}
|
||||||
for i, spend := range tx.shieldedSpends {
|
for i, spend := range tx.shieldedSpends {
|
||||||
ctx.Spends[i] = spend.ToCompact()
|
ctx.Spends[i] = spend.ToCompact()
|
||||||
|
@ -322,9 +385,197 @@ func (tx *Transaction) ToCompact(index int) *walletrpc.CompactTx {
|
||||||
for i, output := range tx.shieldedOutputs {
|
for i, output := range tx.shieldedOutputs {
|
||||||
ctx.Outputs[i] = output.ToCompact()
|
ctx.Outputs[i] = output.ToCompact()
|
||||||
}
|
}
|
||||||
|
for i, a := range tx.orchardActions {
|
||||||
|
ctx.Actions[i] = a.ToCompact()
|
||||||
|
}
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse version 4 transaction data after the nVersionGroupId field.
|
||||||
|
func (tx *Transaction) parseV4(data []byte) ([]byte, error) {
|
||||||
|
s := bytestring.String(data)
|
||||||
|
var err error
|
||||||
|
if tx.nVersionGroupID != 0x892F2085 {
|
||||||
|
return nil, errors.New(fmt.Sprintf("version group ID %x must be 0x892F2085", tx.nVersionGroupID))
|
||||||
|
}
|
||||||
|
s, err = tx.ParseTransparent([]byte(s))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if !s.Skip(4) {
|
||||||
|
return nil, errors.New("could not skip nLockTime")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.Skip(4) {
|
||||||
|
return nil, errors.New("could not skip nExpiryHeight")
|
||||||
|
}
|
||||||
|
|
||||||
|
var spendCount, outputCount int
|
||||||
|
|
||||||
|
if !s.Skip(8) {
|
||||||
|
return nil, errors.New("could not skip valueBalance")
|
||||||
|
}
|
||||||
|
if !s.ReadCompactSize(&spendCount) {
|
||||||
|
return nil, errors.New("could not read nShieldedSpend")
|
||||||
|
}
|
||||||
|
tx.shieldedSpends = make([]spend, spendCount)
|
||||||
|
for i := 0; i < spendCount; i++ {
|
||||||
|
newSpend := &tx.shieldedSpends[i]
|
||||||
|
s, err = newSpend.ParseFromSlice([]byte(s), 4)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "while parsing shielded Spend")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !s.ReadCompactSize(&outputCount) {
|
||||||
|
return nil, errors.New("could not read nShieldedOutput")
|
||||||
|
}
|
||||||
|
tx.shieldedOutputs = make([]output, outputCount)
|
||||||
|
for i := 0; i < outputCount; i++ {
|
||||||
|
newOutput := &tx.shieldedOutputs[i]
|
||||||
|
s, err = newOutput.ParseFromSlice([]byte(s), 4)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "while parsing shielded Output")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var joinSplitCount int
|
||||||
|
if !s.ReadCompactSize(&joinSplitCount) {
|
||||||
|
return nil, errors.New("could not read nJoinSplit")
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.joinSplits = make([]joinSplit, joinSplitCount)
|
||||||
|
if joinSplitCount > 0 {
|
||||||
|
for i := 0; i < joinSplitCount; i++ {
|
||||||
|
js := &tx.joinSplits[i]
|
||||||
|
s, err = js.ParseFromSlice([]byte(s))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "while parsing JoinSplit")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.Skip(32) {
|
||||||
|
return nil, errors.New("could not skip joinSplitPubKey")
|
||||||
|
}
|
||||||
|
|
||||||
|
if !s.Skip(64) {
|
||||||
|
return nil, errors.New("could not skip joinSplitSig")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if spendCount+outputCount > 0 && !s.Skip(64) {
|
||||||
|
return nil, errors.New("could not skip bindingSigSapling")
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse version 5 transaction data after the nVersionGroupId field.
|
||||||
|
func (tx *Transaction) parseV5(data []byte) ([]byte, error) {
|
||||||
|
s := bytestring.String(data)
|
||||||
|
var err error
|
||||||
|
if !s.ReadUint32(&tx.consensusBranchID) {
|
||||||
|
return nil, errors.New("could not read nVersionGroupId")
|
||||||
|
}
|
||||||
|
if tx.nVersionGroupID != 0x26A7270A {
|
||||||
|
return nil, errors.New(fmt.Sprintf("version group ID %d must be 0x26A7270A", tx.nVersionGroupID))
|
||||||
|
}
|
||||||
|
if !s.Skip(4) {
|
||||||
|
return nil, errors.New("could not skip nLockTime")
|
||||||
|
}
|
||||||
|
if !s.Skip(4) {
|
||||||
|
return nil, errors.New("could not skip nExpiryHeight")
|
||||||
|
}
|
||||||
|
s, err = tx.ParseTransparent([]byte(s))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var spendCount, outputCount int
|
||||||
|
if !s.ReadCompactSize(&spendCount) {
|
||||||
|
return nil, errors.New("could not read nShieldedSpend")
|
||||||
|
}
|
||||||
|
if spendCount >= (1 << 16) {
|
||||||
|
return nil, errors.New(fmt.Sprintf("spentCount (%d) must be less than 2^16", spendCount))
|
||||||
|
}
|
||||||
|
tx.shieldedSpends = make([]spend, spendCount)
|
||||||
|
for i := 0; i < spendCount; i++ {
|
||||||
|
newSpend := &tx.shieldedSpends[i]
|
||||||
|
s, err = newSpend.ParseFromSlice([]byte(s), tx.version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "while parsing shielded Spend")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !s.ReadCompactSize(&outputCount) {
|
||||||
|
return nil, errors.New("could not read nShieldedOutput")
|
||||||
|
}
|
||||||
|
if outputCount >= (1 << 16) {
|
||||||
|
return nil, errors.New(fmt.Sprintf("outputCount (%d) must be less than 2^16", outputCount))
|
||||||
|
}
|
||||||
|
tx.shieldedOutputs = make([]output, outputCount)
|
||||||
|
for i := 0; i < outputCount; i++ {
|
||||||
|
newOutput := &tx.shieldedOutputs[i]
|
||||||
|
s, err = newOutput.ParseFromSlice([]byte(s), tx.version)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "while parsing shielded Output")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if spendCount+outputCount > 0 && !s.Skip(8) {
|
||||||
|
return nil, errors.New("could not read valueBalance")
|
||||||
|
}
|
||||||
|
if spendCount > 0 && !s.Skip(32) {
|
||||||
|
return nil, errors.New("could not skip anchorSapling")
|
||||||
|
}
|
||||||
|
if !s.Skip(192 * spendCount) {
|
||||||
|
return nil, errors.New("could not skip vSpendProofsSapling")
|
||||||
|
}
|
||||||
|
if !s.Skip(64 * spendCount) {
|
||||||
|
return nil, errors.New("could not skip vSpendAuthSigsSapling")
|
||||||
|
}
|
||||||
|
if !s.Skip(192 * outputCount) {
|
||||||
|
return nil, errors.New("could not skip vOutputProofsSapling")
|
||||||
|
}
|
||||||
|
if spendCount+outputCount > 0 && !s.Skip(64) {
|
||||||
|
return nil, errors.New("could not skip bindingSigSapling")
|
||||||
|
}
|
||||||
|
var actionsCount int
|
||||||
|
if !s.ReadCompactSize(&actionsCount) {
|
||||||
|
return nil, errors.New("could not read nActionsOrchard")
|
||||||
|
}
|
||||||
|
if actionsCount >= (1 << 16) {
|
||||||
|
return nil, errors.New(fmt.Sprintf("actionsCount (%d) must be less than 2^16", actionsCount))
|
||||||
|
}
|
||||||
|
tx.orchardActions = make([]action, actionsCount)
|
||||||
|
for i := 0; i < actionsCount; i++ {
|
||||||
|
a := &tx.orchardActions[i]
|
||||||
|
s, err = a.ParseFromSlice([]byte(s))
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "while parsing orchard action")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if actionsCount > 0 {
|
||||||
|
if !s.Skip(1) {
|
||||||
|
return nil, errors.New("could not skip flagsOrchard")
|
||||||
|
}
|
||||||
|
if !s.Skip(8) {
|
||||||
|
return nil, errors.New("could not skip valueBalanceOrchard")
|
||||||
|
}
|
||||||
|
if !s.Skip(32) {
|
||||||
|
return nil, errors.New("could not skip anchorOrchard")
|
||||||
|
}
|
||||||
|
var proofsCount int
|
||||||
|
if !s.ReadCompactSize(&proofsCount) {
|
||||||
|
return nil, errors.New("could not read sizeProofsOrchard")
|
||||||
|
}
|
||||||
|
if !s.Skip(proofsCount) {
|
||||||
|
return nil, errors.New("could not skip proofsOrchard")
|
||||||
|
}
|
||||||
|
if !s.Skip(64 * actionsCount) {
|
||||||
|
return nil, errors.New("could not skip vSpendAuthSigsOrchard")
|
||||||
|
}
|
||||||
|
if !s.Skip(64) {
|
||||||
|
return nil, errors.New("could not skip bindingSigOrchard")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ParseFromSlice deserializes a single transaction from the given data.
|
// ParseFromSlice deserializes a single transaction from the given data.
|
||||||
func (tx *Transaction) ParseFromSlice(data []byte) ([]byte, error) {
|
func (tx *Transaction) ParseFromSlice(data []byte) ([]byte, error) {
|
||||||
s := bytestring.String(data)
|
s := bytestring.String(data)
|
||||||
|
@ -338,135 +589,26 @@ func (tx *Transaction) ParseFromSlice(data []byte) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
tx.fOverwintered = (header >> 31) == 1
|
tx.fOverwintered = (header >> 31) == 1
|
||||||
|
if !tx.fOverwintered {
|
||||||
|
return nil, errors.New("fOverwinter flag must be set")
|
||||||
|
}
|
||||||
tx.version = header & 0x7FFFFFFF
|
tx.version = header & 0x7FFFFFFF
|
||||||
|
if tx.version < 4 {
|
||||||
if tx.version >= 3 {
|
return nil, errors.New(fmt.Sprintf("version number %d must be greater or equal to 4", tx.version))
|
||||||
if !s.ReadUint32(&tx.nVersionGroupID) {
|
|
||||||
return nil, errors.New("could not read nVersionGroupId")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var txInCount int
|
if !s.ReadUint32(&tx.nVersionGroupID) {
|
||||||
if !s.ReadCompactSize(&txInCount) {
|
return nil, errors.New("could not read nVersionGroupId")
|
||||||
return nil, errors.New("could not read tx_in_count")
|
|
||||||
}
|
}
|
||||||
|
// parse the main part of the transaction
|
||||||
// TODO: Duplicate/otherwise-too-many transactions are a possible DoS
|
if tx.version <= 4 {
|
||||||
// TODO: vector. At the moment we're assuming trusted input.
|
s, err = tx.parseV4([]byte(s))
|
||||||
// See https://nvd.nist.gov/vuln/detail/CVE-2018-17144 for an example.
|
} else {
|
||||||
|
s, err = tx.parseV5([]byte(s))
|
||||||
if txInCount > 0 {
|
|
||||||
tx.transparentInputs = make([]*txIn, txInCount)
|
|
||||||
for i := 0; i < txInCount; i++ {
|
|
||||||
ti := &txIn{}
|
|
||||||
s, err = ti.ParseFromSlice([]byte(s))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "while parsing transparent input")
|
|
||||||
}
|
|
||||||
tx.transparentInputs[i] = ti
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if err != nil {
|
||||||
var txOutCount int
|
return nil, err
|
||||||
if !s.ReadCompactSize(&txOutCount) {
|
|
||||||
return nil, errors.New("could not read tx_out_count")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if txOutCount > 0 {
|
|
||||||
tx.transparentOutputs = make([]*txOut, txOutCount)
|
|
||||||
for i := 0; i < txOutCount; i++ {
|
|
||||||
to := &txOut{}
|
|
||||||
s, err = to.ParseFromSlice([]byte(s))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "while parsing transparent output")
|
|
||||||
}
|
|
||||||
tx.transparentOutputs[i] = to
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.ReadUint32(&tx.nLockTime) {
|
|
||||||
return nil, errors.New("could not read nLockTime")
|
|
||||||
}
|
|
||||||
|
|
||||||
if tx.fOverwintered {
|
|
||||||
if !s.ReadUint32(&tx.nExpiryHeight) {
|
|
||||||
return nil, errors.New("could not read nExpiryHeight")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var spendCount, outputCount int
|
|
||||||
|
|
||||||
if tx.version >= 4 {
|
|
||||||
if !s.ReadInt64(&tx.valueBalance) {
|
|
||||||
return nil, errors.New("could not read valueBalance")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.ReadCompactSize(&spendCount) {
|
|
||||||
return nil, errors.New("could not read nShieldedSpend")
|
|
||||||
}
|
|
||||||
|
|
||||||
if spendCount > 0 {
|
|
||||||
tx.shieldedSpends = make([]*spend, spendCount)
|
|
||||||
for i := 0; i < spendCount; i++ {
|
|
||||||
newSpend := &spend{}
|
|
||||||
s, err = newSpend.ParseFromSlice([]byte(s))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "while parsing shielded Spend")
|
|
||||||
}
|
|
||||||
tx.shieldedSpends[i] = newSpend
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.ReadCompactSize(&outputCount) {
|
|
||||||
return nil, errors.New("could not read nShieldedOutput")
|
|
||||||
}
|
|
||||||
|
|
||||||
if outputCount > 0 {
|
|
||||||
tx.shieldedOutputs = make([]*output, outputCount)
|
|
||||||
for i := 0; i < outputCount; i++ {
|
|
||||||
newOutput := &output{}
|
|
||||||
s, err = newOutput.ParseFromSlice([]byte(s))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "while parsing shielded Output")
|
|
||||||
}
|
|
||||||
tx.shieldedOutputs[i] = newOutput
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tx.version >= 2 {
|
|
||||||
var joinSplitCount int
|
|
||||||
if !s.ReadCompactSize(&joinSplitCount) {
|
|
||||||
return nil, errors.New("could not read nJoinSplit")
|
|
||||||
}
|
|
||||||
|
|
||||||
if joinSplitCount > 0 {
|
|
||||||
tx.joinSplits = make([]*joinSplit, joinSplitCount)
|
|
||||||
for i := 0; i < joinSplitCount; i++ {
|
|
||||||
js := &joinSplit{version: tx.version}
|
|
||||||
s, err = js.ParseFromSlice([]byte(s))
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "while parsing JoinSplit")
|
|
||||||
}
|
|
||||||
tx.joinSplits[i] = js
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.ReadBytes(&tx.joinSplitPubKey, 32) {
|
|
||||||
return nil, errors.New("could not read joinSplitPubKey")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !s.ReadBytes(&tx.joinSplitSig, 64) {
|
|
||||||
return nil, errors.New("could not read joinSplitSig")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tx.version >= 4 && (spendCount+outputCount > 0) {
|
|
||||||
if !s.ReadBytes(&tx.bindingSig, 64) {
|
|
||||||
return nil, errors.New("could not read bindingSig")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: implement rawBytes with MarshalBinary() instead
|
// TODO: implement rawBytes with MarshalBinary() instead
|
||||||
txLen := len(data) - len(s)
|
txLen := len(data) - len(s)
|
||||||
tx.rawBytes = data[:txLen]
|
tx.rawBytes = data[:txLen]
|
||||||
|
|
|
@ -4,880 +4,112 @@
|
||||||
package parser
|
package parser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
|
"encoding/json"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/adityapk00/lightwalletd/parser/internal/bytestring"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// "Human-readable" version of joinSplit struct defined in transaction.go.
|
// Some of these values may be "null" (which translates to nil in Go) in
|
||||||
// Remember to update this if the format ever changes.
|
// the test data, so we have *_set variables to indicate if the corresponding
|
||||||
type joinSplitTestVector struct {
|
// variable is non-null. (There is an "optional" package we could use for
|
||||||
vpubOld uint64
|
// these but it doesn't seem worth pulling it in.)
|
||||||
vpubNew uint64
|
type TxTestData struct {
|
||||||
anchor string // 32
|
Tx string
|
||||||
nullifiers []string // 64 [N_old][32]byte
|
Txid string
|
||||||
commitments []string // 64 [N_new][32]byte
|
Version int
|
||||||
ephemeralKey string // 32
|
NVersionGroupId int
|
||||||
randomSeed string // 32
|
NConsensusBranchId int
|
||||||
vmacs []string // 64 [N_old][32]byte
|
Tx_in_count int
|
||||||
proofPHGR13 string // 296
|
Tx_out_count int
|
||||||
proofGroth16 string // 192
|
NSpendsSapling int
|
||||||
encCiphertexts []string // 1202 [N_new][601]byte
|
NoutputsSapling int
|
||||||
|
NActionsOrchard int
|
||||||
}
|
}
|
||||||
|
|
||||||
type spendTestVector struct {
|
// https://jhall.io/posts/go-json-tricks-array-as-structs/
|
||||||
cv string // 32
|
func (r *TxTestData) UnmarshalJSON(p []byte) error {
|
||||||
anchor string // 32
|
var t []interface{}
|
||||||
nullifier string // 32
|
if err := json.Unmarshal(p, &t); err != nil {
|
||||||
rk string // 32
|
return err
|
||||||
zkproof string // 192
|
}
|
||||||
spendAuthSig string // 64
|
r.Tx = t[0].(string)
|
||||||
|
r.Txid = t[1].(string)
|
||||||
|
r.Version = int(t[2].(float64))
|
||||||
|
r.NVersionGroupId = int(t[3].(float64))
|
||||||
|
r.NConsensusBranchId = int(t[4].(float64))
|
||||||
|
r.Tx_in_count = int(t[7].(float64))
|
||||||
|
r.Tx_out_count = int(t[8].(float64))
|
||||||
|
r.NSpendsSapling = int(t[9].(float64))
|
||||||
|
r.NoutputsSapling = int(t[10].(float64))
|
||||||
|
r.NActionsOrchard = int(t[14].(float64))
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type outputTestVector struct {
|
func TestV5TransactionParser(t *testing.T) {
|
||||||
cv string // 32
|
|
||||||
cmu string // 32
|
|
||||||
ephemeralKey string // 32
|
|
||||||
encCiphertext string // 580
|
|
||||||
outCiphertext string // 80
|
|
||||||
zkproof string // 192
|
|
||||||
}
|
|
||||||
|
|
||||||
type txTestVector struct {
|
|
||||||
// Sprout and Sapling
|
|
||||||
txid, header, nVersionGroupID, nLockTime, nExpiryHeight string
|
|
||||||
vin, vout [][]string
|
|
||||||
vJoinSplits []joinSplitTestVector
|
|
||||||
joinSplitPubKey, joinSplitSig string
|
|
||||||
|
|
||||||
// Sapling-only
|
|
||||||
valueBalance string // encoded int64
|
|
||||||
spends []spendTestVector
|
|
||||||
outputs []outputTestVector
|
|
||||||
bindingSig string
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/zcash/zips/blob/master/zip-0143.rst
|
|
||||||
var zip143tests = []txTestVector{
|
|
||||||
{
|
|
||||||
// Test vector 1
|
|
||||||
txid: "f0b22277ac851b5f4df590fe6a128aad9d0ce8063235eb2b328c2dc6a23c1ec5",
|
|
||||||
header: "03000080",
|
|
||||||
nVersionGroupID: "7082c403",
|
|
||||||
nLockTime: "481cdd86",
|
|
||||||
nExpiryHeight: "b3cc4318",
|
|
||||||
vin: nil,
|
|
||||||
vout: [][]string{
|
|
||||||
{"8f739811893e0000", "095200ac6551ac636565"},
|
|
||||||
{"b1a45a0805750200", "025151"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Test vector 2
|
|
||||||
//raw: "we have some raw data for this tx, which this comment is too small to contain",
|
|
||||||
txid: "39fe585a56b005f568c3171d22afa916e946e2a8aff5971d58ee8a6fc1482059",
|
|
||||||
header: "03000080",
|
|
||||||
nVersionGroupID: "7082c403",
|
|
||||||
nLockTime: "97b0e4e4",
|
|
||||||
nExpiryHeight: "c705fc05",
|
|
||||||
vin: [][]string{
|
|
||||||
{"4201cfb1cd8dbf69b8250c18ef41294ca97993db546c1fe01f7e9c8e36d6a5e2", "9d4e30a7", "03ac6a00", "98421c69"},
|
|
||||||
{"378af1e40f64e125946f62c2fa7b2fecbcb64b6968912a6381ce3dc166d56a1d", "62f5a8d7", "056363635353", "e8c7203d"},
|
|
||||||
},
|
|
||||||
vout: [][]string{
|
|
||||||
{"6af786387ae60100", "080063656a63ac5200"},
|
|
||||||
{"23752997f4ff0400", "0751510053536565"},
|
|
||||||
},
|
|
||||||
vJoinSplits: []joinSplitTestVector{
|
|
||||||
{
|
|
||||||
vpubOld: uint64(0),
|
|
||||||
vpubNew: uint64(0),
|
|
||||||
anchor: "76495c222f7fba1e31defa3d5a57efc2e1e9b01a035587d5fb1a38e01d94903d",
|
|
||||||
nullifiers: []string{
|
|
||||||
"3c3e0ad3360c1d3710acd20b183e31d49f25c9a138f49b1a537edcf04be34a98",
|
|
||||||
"51a7af9db6990ed83dd64af3597c04323ea51b0052ad8084a8b9da948d320dad",
|
|
||||||
},
|
|
||||||
commitments: []string{
|
|
||||||
"d64f5431e61ddf658d24ae67c22c8d1309131fc00fe7f235734276d38d47f1e1",
|
|
||||||
"91e00c7a1d48af046827591e9733a97fa6b679f3dc601d008285edcbdae69ce8",
|
|
||||||
},
|
|
||||||
ephemeralKey: "fc1be4aac00ff2711ebd931de518856878f73476f21a482ec9378365c8f7393c",
|
|
||||||
randomSeed: "94e2885315eb4671098b79535e790fe53e29fef2b3766697ac32b4f473f468a0",
|
|
||||||
vmacs: []string{
|
|
||||||
"08e72389fc03880d780cb07fcfaabe3f1a84b27db59a4a153d882d2b21035965",
|
|
||||||
"55ed9494c6ac893c49723833ec8926c1039586a7afcf4a0d9c731e985d99589c",
|
|
||||||
},
|
|
||||||
proofPHGR13: "03b838e8aaf745533ed9e8ae3a1cd074a51a20da8aba18d1dbebbc862ded42435e02476930d069896cff30eb414f727b89e001afa2fb8dc3436d75a4a6f26572504b0b2232ecb9f0c02411e52596bc5e90457e745939ffedbd12863ce71a02af117d417adb3d15cc54dcb1fce467500c6b8fb86b12b56da9c382857deecc40a98d5f2903395ee4762dd21afdbb5d47fa9a6dd984d567db2857b927b7fae2db587105415d0242789d38f50b8dbcc129cab3d17d19f3355bcf73cecb8cb8a5da01307152f13902a270572670dc82d39026c6cb4cd4b0f7f5aa2a4f5a5341ec5dd715406f2fdd2a02733f5f641c8c21862a1bafce2609d9eecfa158cfb5cd79f88008e315dc7d8388036c1782fd2795d18a763624c25fa959cc97489ce75745824b77868c53239cfbdf",
|
|
||||||
encCiphertexts: []string{
|
|
||||||
"73caec65604037314faaceb56218c6bd30f8374ac13386793f21a9fb80ad03bc0cda4a44946c00e1b1a1df0e5b87b5bece477a709649e950060591394812951e1fe3895b8cc3d14d2cf6556df6ed4b4ddd3d9a69f53357d7767f4f5ccbdbc596631277f8fecd08cb056b95e3025b9792fff7f244fc716269b926d62e9596fa825c6bf21aff9e68625a192440ea06828123d97884806f15fa08da52754a1095e3ff1abd5ce4fddfccfc3a6128aef784a64610a89d1a7099216d0814d3a2d452431c32d411ac1cce82ad0229407bbc48985675e3f874a4533f1d63a84dfa3e0f460fe2f57e34fbc75423c3737f5b2a0615f5722db041a3ef66fa483afd3c2e19e59444a64add6df1d963f5dd5b5010d3d025f0287c4cf19c75f33d51ddddba5d657b43ee8da645443814cc7329f3e9b4e54c236c29af3923101756d9fa4bd0f7d2ddaacb6b0f86a2658e0a07a05ac5b950051cd24c47a88d13d659ba2a46ca1830816d09cd7646f76f716abec5de07fe9b523410806ea6f288f8736c23357c85f45791e1708029d9824d90704607f387a03e49bf9836574431345a7877efaa8a08e73081ef8d62cb780ab6883a50a0d470190dfba10a857f82842d3825b3d6da0573d316eb160dc0b716c48fbd467f75b780149ae8808f4e68f50c0536acddf6f1aeab016b6bc1ec144b4e553acfd670f77e755fc88e0677e31ba459b44e307768958fe3789d41c2b1ff434cb30e15914f01bc6bc2307b488d2556d7b7380ea4ffd712f6b02fe806b94569cd4059f396bf29b99d0a40e5e1711ca944f72d436a102fca4b97693da0b086fe9d2e7162470d02e0f05d4bec9512bf",
|
|
||||||
"b3f38327296efaa74328b118c27402c70c3a90b49ad4bbc68e37c0aa7d9b3fe17799d73b841e751713a02943905aae0803fd69442eb7681ec2a05600054e92eed555028f21b6a155268a2dd6640a69301a52a38d4d9f9f957ae35af7167118141ce4c9be0a6a492fe79f1581a155fa3a2b9dafd82e650b386ad3a08cb6b83131ac300b0846354a7eef9c410e4b62c47c5426907dfc6685c5c99b7141ac626ab4761fd3f41e728e1a28f89db89ffdeca364dd2f0f0739f0534556483199c71f189341ac9b78a269164206a0ea1ce73bfb2a942e7370b247c046f8e75ef8e3f8bd821cf577491864e20e6d08fd2e32b555c92c661f19588b72a89599710a88061253ca285b6304b37da2b5294f5cb354a894322848ccbdc7c2545b7da568afac87ffa005c312241c2d57f4b45d6419f0d2e2c5af33ae243785b325cdab95404fc7aed70525cddb41872cfcc214b13232edc78609753dbff930eb0dc156612b9cb434bc4b693392deb87c530435312edcedc6a961133338d786c4a3e103f60110a16b1337129704bf4754ff6ba9fbe65951e610620f71cda8fc877625f2c5bb04cbe1228b1e886f4050afd8fe94e97d2e9e85c6bb748c0042d3249abb1342bb0eebf62058bf3de080d94611a3750915b5dc6c0b3899d41222bace760ee9c8818ded599e34c56d7372af1eb86852f2a732104bdb750739de6c2c6e0f9eb7cb17f1942bfc9f4fd6ebb6b4cdd4da2bca26fac4578e9f543405acc7d86ff59158bd0cba3aef6f4a8472d144d99f8b8d1dedaa9077d4f01d4bb27bbe31d88fbefac3dcd4797563a26b1d61fcd9a464ab21ed550fe6fa09695ba0b2f10e",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
vpubOld: uint64(0),
|
|
||||||
vpubNew: uint64(0),
|
|
||||||
anchor: "ea6468cc6e20a66f826e3d14c5006f0563887f5e1289be1b2004caca8d3f34d6",
|
|
||||||
nullifiers: []string{
|
|
||||||
"e84bf59c1e04619a7c23a996941d889e4622a9b9b1d59d5e319094318cd405ba",
|
|
||||||
"27b7e2c084762d31453ec4549a4d97729d033460fcf89d6494f2ffd789e98082",
|
|
||||||
},
|
|
||||||
commitments: []string{
|
|
||||||
"ea5ce9534b3acd60fe49e37e4f666931677319ed89f85588741b3128901a93bd",
|
|
||||||
"78e4be0225a9e2692c77c969ed0176bdf9555948cbd5a332d045de6ba6bf4490",
|
|
||||||
},
|
|
||||||
ephemeralKey: "adfe7444cd467a09075417fcc0062e49f008c51ad4227439c1b4476ccd8e9786",
|
|
||||||
randomSeed: "2dab7be1e8d399c05ef27c6e22ee273e15786e394c8f1be31682a30147963ac8",
|
|
||||||
vmacs: []string{
|
|
||||||
"da8d41d804258426a3f70289b8ad19d8de13be4eebe3bd4c8a6f55d6e0c373d4",
|
|
||||||
"56851879f5fbc282db9e134806bff71e11bc33ab75dd6ca067fb73a043b646a7",
|
|
||||||
},
|
|
||||||
proofPHGR13: "0339cab4928386786d2f24141ee120fdc34d6764eafc66880ee0204f53cc1167ed02b43a52dea3ca7cff8ef35cd8e6d7c111a68ef44bcd0c1513ad47ca61c659cc5d0a5b440f6b9f59aff66879bb6688fd2859362b182f207b3175961f6411a493bffd048e7d0d87d82fe6f990a2b0a25f5aa0111a6e68f37bf6f3ac2d26b84686e569038d99c1383597fad81193c4c1b16e6a90e2d507cdfe6fbdaa86163e9cf5de310003ca7e8da047b090db9f37952fbfee76af61668190bd52ed490e677b515d0143840307219c7c0ee7fc7bfc79f325644e4df4c0d7db08e9f0bd024943c705abff899403a605cfbc7ed746a7d3f7c37d9e8bdc433b7d79e08a12f738a8f0dbddfef2f26502f3e47d1b0fd11e6a13311fb799c79c641d9da43b33e7ad012e28255398789262",
|
|
||||||
encCiphertexts: []string{
|
|
||||||
"275f1175be8462c01491c4d842406d0ec4282c9526174a09878fe8fdde33a29604e5e5e7b2a025d6650b97dbb52befb59b1d30a57433b0a351474444099daa371046613260cf3354cfcdada663ece824ffd7e44393886a86165ddddf2b4c41773554c86995269408b11e6737a4c447586f69173446d8e48bf84cbc000a807899973eb93c5e819aad669413f8387933ad1584aa35e43f4ecd1e2d0407c0b1b89920ffdfdb9bea51ac95b557af71b89f903f5d9848f14fcbeb1837570f544d6359eb23faf38a0822da36ce426c4a2fbeffeb0a8a2e297a9d19ba15024590e3329d9fa9261f9938a4032dd34606c9cf9f3dd33e576f05cd1dd6811c6298757d77d9e810abdb226afcaa4346a6560f8932b3181fd355d5d391976183f8d99388839632d6354f666d09d3e5629ea19737388613d38a34fd0f6e50ee5a0cc9677177f50028c141378187bd2819403fc534f80076e9380cb4964d3b6b45819d3b8e9caf54f051852d671bf8c1ffde2d1510756418cb4810936aa57e6965d6fb656a760b7f19adf96c173488552193b147ee58858033dac7cd0eb204c06490bbdedf5f7571acb2ebe76acef3f2a01ee987486dfe6c3f0a5e234c127258f97a28fb5d164a8176be946b8097d0e317287f33bf9c16f9a545409ce29b1f4273725fc0df02a04ebae178b3414fb0a82d50deb09fcf4e6ee9d180ff4f56ff3bc1d3601fc2dc90d814c3256f4967d3a8d64c83fea339c51f5a8e5801fbb97835581b602465dee04b5922c2761b54245bec0c9eef2db97d22b2b3556cc969fbb13d06509765a52b3fac54b93f421bf08e18d52ddd52cc1c8ca8adfaccab7e5cc2",
|
|
||||||
"f4573fbbf8239bb0b8aedbf8dad16282da5c9125dba1c059d0df8abf621078f02d6c4bc86d40845ac1d59710c45f07d585eb48b32fc0167ba256e73ca3b9311c62d109497957d8dbe10aa3e866b40c0baa2bc492c19ad1e6372d9622bf163fbffeaeee796a3cd9b6fbbfa4d792f34d7fd6e763cd5859dd26833d21d9bc5452bd19515dff9f4995b35bc0c1f876e6ad11f2452dc9ae85aec01fc56f8cbfda75a7727b75ebbd6bbffb43b63a3b1b671e40feb0db002974a3c3b1a788567231bf6399ff89236981149d423802d2341a3bedb9ddcbac1fe7b6435e1479c72e7089d029e7fbbaf3cf37e9b9a6b776791e4c5e6fda57e8d5f14c8c35a2d270846b9dbe005cda16af4408f3ab06a916eeeb9c9594b70424a4c1d171295b6763b22f47f80b53ccbb904bd68fd65fbd3fbdea1035e98c21a7dbc91a9b5bc7690f05ec317c97f8764eb48e911d428ec8d861b708e8298acb62155145155ae95f0a1d1501034753146e22d05f586d7f6b4fe12dad9a17f5db70b1db96b8d9a83edadc966c8a5466b61fc998c31f1070d9a5c9a6d268d304fe6b8fd3b4010348611abdcbd49fe4f85b623c7828c71382e1034ea67bc8ae97404b0c50b2a04f559e49950afcb0ef462a2ae024b0f0224dfd73684b88c7fbe92d02b68f759c4752663cd7b97a14943649305521326bde085630864629291bae25ff8822a14c4b666a9259ad0dc42a8290ac7bc7f53a16f379f758e5de750f04fd7cad47701c8597f97888bea6fa0bf2999956fbfd0ee68ec36e4688809ae231eb8bc4369f5fe1573f57e099d9c09901bf39caac48dc11956a8ae905ead86954547c448ae43d31",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
|
|
||||||
joinSplitPubKey: "5e669c4242da565938f417bf43ce7b2b30b1cd4018388e1a910f0fc41fb0877a",
|
|
||||||
// This joinSplitSig is (intentionally) invalid random data.
|
|
||||||
joinSplitSig: "5925e466819d375b0a912d4fe843b76ef6f223f0f7c894f38f7ab780dfd75f669c8c06cffa43eb47565a50e3b1fa45ad61ce9a1c4727b7aaa53562f523e73952",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSproutTransactionParser(t *testing.T) {
|
|
||||||
// The raw data are stored in a separate file because they're large enough
|
// The raw data are stored in a separate file because they're large enough
|
||||||
// to make the test table difficult to scroll through. They are in the same
|
// to make the test table difficult to scroll through. They are in the same
|
||||||
// order as the test table above. If you update the test table without
|
// order as the test table above. If you update the test table without
|
||||||
// adding a line to the raw file, this test will panic due to index
|
// adding a line to the raw file, this test will panic due to index
|
||||||
// misalignment.
|
// misalignment.
|
||||||
testData, err := os.Open("../testdata/zip143_raw_tx")
|
s, err := os.ReadFile("../testdata/tx_v5.json")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer testData.Close()
|
|
||||||
|
|
||||||
// Parse the raw transactions file
|
var testdata []json.RawMessage
|
||||||
rawTxData := [][]byte{}
|
err = json.Unmarshal(s, &testdata)
|
||||||
scan := bufio.NewScanner(testData)
|
|
||||||
for scan.Scan() {
|
|
||||||
dataLine := scan.Text()
|
|
||||||
// Skip the comments
|
|
||||||
if strings.HasPrefix(dataLine, "#") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
txData, err := hex.DecodeString(dataLine)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
rawTxData = append(rawTxData, txData)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, tt := range zip143tests {
|
|
||||||
tx := NewTransaction()
|
|
||||||
|
|
||||||
rest, err := tx.ParseFromSlice(rawTxData[i])
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("Test %d: %v", i, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(rest) != 0 {
|
|
||||||
t.Errorf("Test %d: did not consume entire buffer", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transaction metadata
|
|
||||||
if !subTestCommonBlockMeta(&tt, tx, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transparent inputs and outputs
|
|
||||||
if !subTestTransparentInputs(tt.vin, tx.transparentInputs, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !subTestTransparentOutputs(tt.vout, tx.transparentOutputs, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// JoinSplits
|
|
||||||
if !subTestJoinSplits(tt.vJoinSplits, tx.joinSplits, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
testJSPubKey, _ := hex.DecodeString(tt.joinSplitPubKey)
|
|
||||||
if !bytes.Equal(testJSPubKey, tx.joinSplitPubKey) {
|
|
||||||
t.Errorf("Test %d: jsPubKey mismatch %x %x", i, testJSPubKey, tx.joinSplitPubKey)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
testJSSig, _ := hex.DecodeString(tt.joinSplitSig)
|
|
||||||
if !bytes.Equal(testJSSig, tx.joinSplitSig) {
|
|
||||||
t.Errorf("Test %d: jsSig mismatch %x %x", i, testJSSig, tx.joinSplitSig)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if hex.EncodeToString(tx.GetDisplayHash()) != tt.txid {
|
|
||||||
t.Errorf("Test %d: incorrect txid", i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func subTestCommonBlockMeta(tt *txTestVector, tx *Transaction, t *testing.T, caseNum int) bool {
|
|
||||||
headerBytes, _ := hex.DecodeString(tt.header)
|
|
||||||
header := binary.LittleEndian.Uint32(headerBytes)
|
|
||||||
if (header >> 31) == 1 != tx.fOverwintered {
|
|
||||||
t.Errorf("Test %d: unexpected fOverwintered", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if (header & 0x7FFFFFFF) != tx.version {
|
|
||||||
t.Errorf("Test %d: unexpected tx version", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
versionGroupBytes, _ := hex.DecodeString(tt.nVersionGroupID)
|
|
||||||
versionGroup := binary.LittleEndian.Uint32(versionGroupBytes)
|
|
||||||
if versionGroup != tx.nVersionGroupID {
|
|
||||||
t.Errorf("Test %d: unexpected versionGroupId", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
lockTimeBytes, _ := hex.DecodeString(tt.nLockTime)
|
|
||||||
lockTime := binary.LittleEndian.Uint32(lockTimeBytes)
|
|
||||||
if lockTime != tx.nLockTime {
|
|
||||||
t.Errorf("Test %d: unexpected nLockTime", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
expiryHeightBytes, _ := hex.DecodeString(tt.nExpiryHeight)
|
|
||||||
expiryHeight := binary.LittleEndian.Uint32(expiryHeightBytes)
|
|
||||||
if expiryHeight != tx.nExpiryHeight {
|
|
||||||
t.Errorf("Test %d: unexpected nExpiryHeight", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func subTestJoinSplits(testJoinSplits []joinSplitTestVector, txJoinSplits []*joinSplit, t *testing.T, caseNum int) bool {
|
|
||||||
if testJoinSplits == nil && txJoinSplits != nil {
|
|
||||||
t.Errorf("Test %d: non-zero joinSplits when expected empty vector", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(testJoinSplits) != len(txJoinSplits) {
|
|
||||||
t.Errorf("Test %d: joinSplit vector lengths mismatch", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
success := true
|
|
||||||
|
|
||||||
JoinSplitLoop:
|
|
||||||
for idx, test := range testJoinSplits {
|
|
||||||
tx := txJoinSplits[idx]
|
|
||||||
|
|
||||||
if test.vpubOld != tx.vpubOld {
|
|
||||||
t.Errorf("Test %d js %d: vpubOld %d %d", caseNum, idx, test.vpubOld, tx.vpubOld)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if test.vpubNew != tx.vpubNew {
|
|
||||||
t.Errorf("Test %d js %d: vpubNew %d %d", caseNum, idx, test.vpubNew, tx.vpubNew)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
anchor, _ := hex.DecodeString(test.anchor)
|
|
||||||
if !bytes.Equal(anchor, tx.anchor) {
|
|
||||||
t.Errorf("Test %d js %d: anchor %x %x", caseNum, idx, anchor, tx.anchor)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(test.nullifiers) != len(tx.nullifiers) {
|
|
||||||
t.Errorf("Test %d js %d: nf len mismatch %d %d", caseNum, idx, len(test.nullifiers), len(tx.nullifiers))
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for j := 0; j < len(test.nullifiers); j++ {
|
|
||||||
nf, _ := hex.DecodeString(test.nullifiers[j])
|
|
||||||
if !bytes.Equal(nf, tx.nullifiers[j]) {
|
|
||||||
t.Errorf("Test %d js %d: nf mismatch %x %x", caseNum, idx, nf, tx.nullifiers[j])
|
|
||||||
success = false
|
|
||||||
continue JoinSplitLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(test.commitments) != len(tx.commitments) {
|
|
||||||
t.Errorf("Test %d js %d: cm len mismatch %d %d", caseNum, idx, len(test.commitments), len(tx.commitments))
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for j := 0; j < len(test.commitments); j++ {
|
|
||||||
cm, _ := hex.DecodeString(test.commitments[j])
|
|
||||||
if !bytes.Equal(cm, tx.commitments[j]) {
|
|
||||||
t.Errorf("Test %d js %d: commit mismatch %x %x", caseNum, idx, cm, tx.commitments[j])
|
|
||||||
success = false
|
|
||||||
continue JoinSplitLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ephemeralKey, _ := hex.DecodeString(test.ephemeralKey)
|
|
||||||
if !bytes.Equal(ephemeralKey, tx.ephemeralKey) {
|
|
||||||
t.Errorf("Test %d js %d: ephemeralKey %x %x", caseNum, idx, ephemeralKey, tx.ephemeralKey)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
randomSeed, _ := hex.DecodeString(test.randomSeed)
|
|
||||||
if !bytes.Equal(randomSeed, tx.randomSeed) {
|
|
||||||
t.Errorf("Test %d js %d: randomSeed %x %x", caseNum, idx, randomSeed, tx.randomSeed)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(test.vmacs) != len(tx.vmacs) {
|
|
||||||
t.Errorf("Test %d js %d: mac len mismatch %d %d", caseNum, idx, len(test.vmacs), len(tx.vmacs))
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for j := 0; j < len(test.vmacs); j++ {
|
|
||||||
mac, _ := hex.DecodeString(test.vmacs[j])
|
|
||||||
if !bytes.Equal(mac, tx.vmacs[j]) {
|
|
||||||
t.Errorf("Test %d js %d: mac mismatch %x %x", caseNum, idx, mac, tx.vmacs[j])
|
|
||||||
success = false
|
|
||||||
continue JoinSplitLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This should not be possible.
|
|
||||||
if tx.proofPHGR13 != nil && tx.proofGroth16 != nil {
|
|
||||||
t.Errorf("Test %d js %d: parsed tx had both PHGR and Groth proofs defined", caseNum, idx)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if test.proofPHGR13 != "" {
|
|
||||||
zkproof, _ := hex.DecodeString(test.proofPHGR13)
|
|
||||||
if !bytes.Equal(zkproof, tx.proofPHGR13) {
|
|
||||||
t.Errorf("Test %d js %d: zkproof %x %x", caseNum, idx, zkproof, tx.proofPHGR13)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if test.proofGroth16 != "" {
|
|
||||||
zkproof, _ := hex.DecodeString(test.proofGroth16)
|
|
||||||
if !bytes.Equal(zkproof, tx.proofGroth16) {
|
|
||||||
t.Errorf("Test %d js %d: zkproof %x %x", caseNum, idx, zkproof, tx.proofGroth16)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(test.encCiphertexts) != len(tx.encCiphertexts) {
|
|
||||||
t.Errorf("Test %d js %d: enc len mismatch %d %d", caseNum, idx, len(test.encCiphertexts), len(tx.encCiphertexts))
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for j := 0; j < len(test.encCiphertexts); j++ {
|
|
||||||
ct, _ := hex.DecodeString(test.encCiphertexts[j])
|
|
||||||
if !bytes.Equal(ct, tx.encCiphertexts[j]) {
|
|
||||||
t.Errorf("Test %d js %d: ct mismatch %x %x", caseNum, idx, ct, tx.encCiphertexts[j])
|
|
||||||
success = false
|
|
||||||
continue JoinSplitLoop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success
|
|
||||||
}
|
|
||||||
|
|
||||||
func subTestTransparentInputs(testInputs [][]string, txInputs []*txIn, t *testing.T, caseNum int) bool {
|
|
||||||
if testInputs == nil && txInputs != nil {
|
|
||||||
t.Errorf("Test %d: non-zero vin when expected zero", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(testInputs) != len(txInputs) {
|
|
||||||
t.Errorf("Test %d: vins have mismatched lengths", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
success := true
|
|
||||||
le := binary.LittleEndian
|
|
||||||
|
|
||||||
// 4201cfb1cd8dbf69b8250c18ef41294ca97993db546c1fe01f7e9c8e36d6a5e2 9d4e30a7 03ac6a00 98421c69
|
|
||||||
for idx, ti := range testInputs {
|
|
||||||
txInput := txInputs[idx]
|
|
||||||
|
|
||||||
testPrevTxHash, _ := hex.DecodeString(ti[0])
|
|
||||||
if eq := bytes.Equal(testPrevTxHash, txInput.PrevTxHash); !eq {
|
|
||||||
t.Errorf("Test %d tin %d: prevhash mismatch %x %x", caseNum, idx, testPrevTxHash, txInput.PrevTxHash)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
testPrevTxOutIndexBytes, _ := hex.DecodeString(ti[1])
|
|
||||||
testPrevTxOutIndex := le.Uint32(testPrevTxOutIndexBytes)
|
|
||||||
if testPrevTxOutIndex != txInput.PrevTxOutIndex {
|
|
||||||
t.Errorf("Test %d tin %d: prevout index mismatch %d %d", caseNum, idx, testPrevTxOutIndex, txInput.PrevTxOutIndex)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decode scriptSig and correctly consume own CompactSize field
|
|
||||||
testScriptSig, _ := hex.DecodeString(ti[2])
|
|
||||||
ok := (*bytestring.String)(&testScriptSig).ReadCompactLengthPrefixed((*bytestring.String)(&testScriptSig))
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("Test %d, tin %d: couldn't strip size from script", caseNum, idx)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if eq := bytes.Equal(testScriptSig, txInput.ScriptSig); !eq {
|
|
||||||
t.Errorf("Test %d tin %d: scriptsig mismatch %x %x", caseNum, idx, testScriptSig, txInput.ScriptSig)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
testSeqNumBytes, _ := hex.DecodeString(ti[3])
|
|
||||||
testSeqNum := le.Uint32(testSeqNumBytes)
|
|
||||||
if testSeqNum != txInput.SequenceNumber {
|
|
||||||
t.Errorf("Test %d tin %d: seq mismatch %d %d", caseNum, idx, testSeqNum, txInput.SequenceNumber)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return success
|
|
||||||
}
|
|
||||||
|
|
||||||
func subTestTransparentOutputs(testOutputs [][]string, txOutputs []*txOut, t *testing.T, caseNum int) bool {
|
|
||||||
if testOutputs == nil && txOutputs != nil {
|
|
||||||
t.Errorf("Test %d: non-zero vout when expected zero", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(testOutputs) != len(txOutputs) {
|
|
||||||
t.Errorf("Test %d: vout have mismatched lengths", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
success := true
|
|
||||||
le := binary.LittleEndian
|
|
||||||
|
|
||||||
for idx, testOutput := range testOutputs {
|
|
||||||
txOutput := txOutputs[idx]
|
|
||||||
|
|
||||||
// Parse tx out value from test
|
|
||||||
testValueBytes, _ := hex.DecodeString(testOutput[0])
|
|
||||||
testValue := le.Uint64(testValueBytes)
|
|
||||||
|
|
||||||
if testValue != txOutput.Value {
|
|
||||||
t.Errorf("Test %d, tout %d: value mismatch %d %d", caseNum, idx, testValue, txOutput.Value)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse script from test
|
|
||||||
testScript, _ := hex.DecodeString(testOutput[1])
|
|
||||||
// Correctly consume own CompactSize field
|
|
||||||
ok := (*bytestring.String)(&testScript).ReadCompactLengthPrefixed((*bytestring.String)(&testScript))
|
|
||||||
if !ok {
|
|
||||||
t.Errorf("Test %d, tout %d: couldn't strip size from script", caseNum, idx)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !bytes.Equal(testScript, txOutput.Script) {
|
|
||||||
t.Errorf("Test %d, tout %d: script mismatch %x %x", caseNum, idx, testScript, txOutput.Script)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return success
|
|
||||||
}
|
|
||||||
|
|
||||||
// https://github.com/zcash/zips/blob/master/zip-0243.rst
|
|
||||||
var zip243tests = []txTestVector{
|
|
||||||
// Test vector 1
|
|
||||||
{
|
|
||||||
txid: "5fc4867a1b8bd5ab709799adf322a85d10607e053726d5f5ab4b1c9ab897e6bc",
|
|
||||||
header: "04000080",
|
|
||||||
nVersionGroupID: "85202f89",
|
|
||||||
vin: nil,
|
|
||||||
vout: [][]string{
|
|
||||||
{"e7719811893e0000", "095200ac6551ac636565"},
|
|
||||||
{"b2835a0805750200", "025151"},
|
|
||||||
},
|
|
||||||
nLockTime: "481cdd86",
|
|
||||||
nExpiryHeight: "b3cc4318",
|
|
||||||
valueBalance: "442117623ceb0500",
|
|
||||||
spends: []spendTestVector{
|
|
||||||
{
|
|
||||||
cv: "1b3d1a027c2c40590958b7eb13d742a997738c46a458965baf276ba92f272c72",
|
|
||||||
anchor: "1fe01f7e9c8e36d6a5e29d4e30a73594bf5098421c69378af1e40f64e125946f",
|
|
||||||
nullifier: "62c2fa7b2fecbcb64b6968912a6381ce3dc166d56a1d62f5a8d7551db5fd9313",
|
|
||||||
rk: "e8c7203d996af7d477083756d59af80d06a745f44ab023752cb5b406ed8985e1",
|
|
||||||
zkproof: "8130ab33362697b0e4e4c763ccb8f676495c222f7fba1e31defa3d5a57efc2e1e9b01a035587d5fb1a38e01d94903d3c3e0ad3360c1d3710acd20b183e31d49f25c9a138f49b1a537edcf04be34a9851a7af9db6990ed83dd64af3597c04323ea51b0052ad8084a8b9da948d320dadd64f5431e61ddf658d24ae67c22c8d1309131fc00fe7f235734276d38d47f1e191e00c7a1d48af046827591e9733a97fa6b679f3dc601d008285edcbdae69ce8fc1be4aac00ff2711ebd931de518856878",
|
|
||||||
spendAuthSig: "f73476f21a482ec9378365c8f7393c94e2885315eb4671098b79535e790fe53e29fef2b3766697ac32b4f473f468a008e72389fc03880d780cb07fcfaabe3f1a",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cv: "15825b7acb4d6b57a61bc68f242b52e4fbf85cf1a09cc45b6d6bb3a391578f49",
|
|
||||||
anchor: "9486a7afd04a0d9c74c2995d96b4de37b36046a1ef6d190b916b1111c9288731",
|
|
||||||
nullifier: "1a20da8aba18d1dbebbc862ded42435e92476930d069896cff30eb414f727b89",
|
|
||||||
rk: "e001afa2fb8dc3436d75a4a6f26572504b192232ecb9f0c02411e52596bc5e90",
|
|
||||||
zkproof: "457e745939ffedbd12863ce71a02af117d417adb3d15cc54dcb1fce467500c6b8fb86b12b56da9c382857deecc40a98d5f2935395ee4762dd21afdbb5d47fa9a6dd984d567db2857b927b7fae2db587105415d4642789d38f50b8dbcc129cab3d17d19f3355bcf73cecb8cb8a5da01307152f13936a270572670dc82d39026c6cb4cd4b0f7f5aa2a4f5a5341ec5dd715406f2fdd2afa733f5f641c8c21862a1bafce2609d9eecfa158cfb5cd79f88008e315dc7d8388e76c1782fd2795d18a76",
|
|
||||||
spendAuthSig: "3624c25fa959cc97489ce75745824b77868c53239cfbdf73caec65604037314faaceb56218c6bd30f8374ac13386793f21a9fb80ad03bc0cda4a44946c00e1b1",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cv: "02c78f11876b7065212183199fb5979ca77d2c24c738fe5145f02602053bb4c2",
|
|
||||||
anchor: "f6556df6ed4b4ddd3d9a69f53357d7767f4f5ccbdbc596631277f8fecd08cb05",
|
|
||||||
nullifier: "6b95e3025b9792fff7f244fc716269b926d62e9596fa825c6bf21aff9e68625a",
|
|
||||||
rk: "192440ea06828123d97884806f15fa08da52754a1095e3ff1abd5ce4fddfccfc",
|
|
||||||
zkproof: "3a6128aef784a64610a89d1a7099216d0814d3a2d452431c32d411ac1cce82ad0229407bbc48985675e3f874a4533f1d63a84dfa3e0f460fe2f57e34fbc75423c3737f5b2a0615f5722db041a3ef66fa483afd3c2e19e59444a64add6df1d963f5dd5b5010d3d025f0287c4cf19c75f33d51ddddba5d657b43ee8da645443814cc7329f3e9b4e54c236c29af3923101756d9fa4bd0f7d2ddaacb6b0f86a2658e0a07a05ac5b950051cd24c47a88d13d659ba2a46ca1830816d09cd7646f76f71",
|
|
||||||
spendAuthSig: "6abec5de07fe9b523410806ea6f288f8736c23357c85f45791e1708029d9824d90704607f387a03e49bf9836574431345a7877efaa8a08e73081ef8d62cb780a",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
outputs: []outputTestVector{
|
|
||||||
{
|
|
||||||
cv: "0fa3207ee2f0408097d563da1b2146819edf88d33e7753664fb71d122a6e3699",
|
|
||||||
cmu: "8fbd467f75b780149ae8808f4e68f50c0536acddf6f1aeab016b6bc1ec144b4e",
|
|
||||||
ephemeralKey: "59aeb77eef49d00e5fbb67101cdd41e6bc9cf641a52fca98be915f8440a410d7",
|
|
||||||
encCiphertext: "4cb30e15914f01bc6bc2307b488d2556d7b7380ea4ffd712f6b02fe806b94569cd4059f396bf29b99d0a40e5e1711ca944f72d436a102fca4b97693da0b086fe9d2e7162470d02e0f05d4bec9512bfb3f38327296efaa74328b118c27402c70c3a90b49ad4bbc68e37c0aa7d9b3fe17799d73b841e751713a02943905aae0803fd69442eb7681ec2a05600054e92eed555028f21b6a155268a2dd6640a69301a52a38d4d9f9f957ae35af7167118141ce4c9be0a6a492fe79f1581a155fa3a2b9dafd82e650b386ad3a08cb6b83131ac300b0846354a7eef9c410e4b62c47c5426907dfc6685c5c99b7141ac626ab4761fd3f41e728e1a28f89db89ffdeca364dd2f0f0739f0534556483199c71f189341ac9b78a269164206a0ea1ce73bfb2a942e7370b247c046f8e75ef8e3f8bd821cf577491864e20e6d08fd2e32b555c92c661f19588b72a89599710a88061253ca285b6304b37da2b5294f5cb354a894322848ccbdc7c2545b7da568afac87ffa005c312241c2d57f4b45d6419f0d2e2c5af33ae243785b325cdab95404fc7aed70525cddb41872cfcc214b13232edc78609753dbff930eb0dc156612b9cb434bc4b693392deb87c530435312edcedc6a961133338d786c4a3e103f60110a16b1337129704bf4754ff6ba9fbe65951e610620f71cda8fc877625f2c5bb04cbe1228b1e886f4050afd8fe94e97d2e9e85c6bb748c0042d3249abb1342bb0eebf62058bf3de080d94611a3750915b5dc6c0b3899d41222bace760ee9c8818ded599e34c56d7372af1eb86852f2a732104bdb750739",
|
|
||||||
outCiphertext: "de6c2c6e0f9eb7cb17f1942bfc9f4fd6ebb6b4cdd4da2bca26fac4578e9f543405acc7d86ff59158bd0cba3aef6f4a8472d144d99f8b8d1dedaa9077d4f01d4bb27bbe31d88fbefac3dcd4797563a26b",
|
|
||||||
zkproof: "1d61fcd9a464ab21ed550fe6fa09695ba0b2f10eea6468cc6e20a66f826e3d14c5006f0563887f5e1289be1b2004caca8d3f34d6e84bf59c1e04619a7c23a996941d889e4622a9b9b1d59d5e319094318cd405ba27b7e2c084762d31453ec4549a4d97729d033460fcf89d6494f2ffd789e98082ea5ce9534b3acd60fe49e37e4f666931677319ed89f85588741b3128901a93bd78e4be0225a9e2692c77c969ed0176bdf9555948cbd5a332d045de6ba6bf4490adfe7444cd467a09075417fc",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
vJoinSplits: []joinSplitTestVector{
|
|
||||||
{
|
|
||||||
vpubOld: uint64(0),
|
|
||||||
vpubNew: uint64(0),
|
|
||||||
anchor: "062e49f008c51ad4227439c1b4476ccd8e97862dab7be1e8d399c05ef27c6e22",
|
|
||||||
nullifiers: []string{
|
|
||||||
"ee273e15786e394c8f1be31682a30147963ac8da8d41d804258426a3f70289b8",
|
|
||||||
"ad19d8de13be4eebe3bd4c8a6f55d6e0c373d456851879f5fbc282db9e134806",
|
|
||||||
},
|
|
||||||
commitments: []string{
|
|
||||||
"bff71e11bc33ab75dd6ca067fb73a043b646a7cf39cab4928386786d2f24141e",
|
|
||||||
"e120fdc34d6764eafc66880ee0204f53cc1167ed20b43a52dea3ca7cff8ef35c",
|
|
||||||
},
|
|
||||||
ephemeralKey: "d8e6d7c111a68ef44bcd0c1513ad47ca61c659cc5d325b440f6b9f59aff66879",
|
|
||||||
randomSeed: "bb6688fd2859362b182f207b3175961f6411a493bffd048e7d0d87d82fe6f990",
|
|
||||||
vmacs: []string{
|
|
||||||
"a2b0a25f5aa0111a6e68f37bf6f3ac2d26b84686e569d58d99c1383597fad811",
|
|
||||||
"93c4c1b16e6a90e2d507cdfe6fbdaa86163e9cf5de3100fbca7e8da047b090db",
|
|
||||||
},
|
|
||||||
proofGroth16: "9f37952fbfee76af61668190bd52ed490e677b515d014384af07219c7c0ee7fc7bfc79f325644e4df4c0d7db08e9f0bd024943c705abff8994bfa605cfbc7ed746a7d3f7c37d9e8bdc433b7d79e08a12f738a8f0dbddfef2f2657ef3e47d1b0fd11e6a13311fb799c79c641d9da43b33e7ad012e28255398789262275f1175be8462c01491c4d842406d0ec4282c9526174a09878fe8fdde33a29604e5e5e7b2a025d6650b97dbb52befb59b1d30a57433b0a351474444099daa371046613260",
|
|
||||||
encCiphertexts: []string{
|
|
||||||
"cf3354cfcdada663ece824ffd7e44393886a86165ddddf2b4c41773554c86995269408b11e6737a4c447586f69173446d8e48bf84cbc000a807899973eb93c5e819aad669413f8387933ad1584aa35e43f4ecd1e2d0407c0b1b89920ffdfdb9bea51ac95b557af71b89f903f5d9848f14fcbeb1837570f544d6359eb23faf38a0822da36ce426c4a2fbeffeb0a8a2e297a9d19ba15024590e3329d9fa9261f9938a4032dd34606c9cf9f3dd33e576f05cd1dd6811c6298757d77d9e810abdb226afcaa4346a6560f8932b3181fd355d5d391976183f8d99388839632d6354f666d09d3e5629ea19737388613d38a34fd0f6e50ee5a0cc9677177f50028c141378187bd2819403fc534f80076e9380cb4964d3b6b45819d3b8e9caf54f051852d671bf8c1ffde2d1510756418cb4810936aa57e6965d6fb656a760b7f19adf96c173488552193b147ee58858033dac7cd0eb204c06490bbdedf5f7571acb2ebe76acef3f2a01ee987486dfe6c3f0a5e234c127258f97a28fb5d164a8176be946b8097d0e317287f33bf9c16f9a545409ce29b1f4273725fc0df02a04ebae178b3414fb0a82d50deb09fcf4e6ee9d180ff4f56ff3bc1d3601fc2dc90d814c3256f4967d3a8d64c83fea339c51f5a8e5801fbb97835581b602465dee04b5922c2761b54245bec0c9eef2db97d22b2b3556cc969fbb13d06509765a52b3fac54b93f421bf08e18d52ddd52cc1c8ca8adfaccab7e5cc2f4573fbbf8239bb0b8aedbf8dad16282da5c9125dba1c059d0df8abf621078f02d6c4bc86d40845ac1d59710c45f07d585eb48b32fc0167ba256e73ca3b9311c62d1094979",
|
|
||||||
"57d8dbe10aa3e866b40c0baa2bc492c19ad1e6372d9622bf163fbffeaeee796a3cd9b6fbbfa4d792f34d7fd6e763cd5859dd26833d21d9bc5452bd19515dff9f4995b35bc0c1f876e6ad11f2452dc9ae85aec01fc56f8cbfda75a7727b75ebbd6bbffb43b63a3b1b671e40feb0db002974a3c3b1a788567231bf6399ff89236981149d423802d2341a3bedb9ddcbac1fe7b6435e1479c72e7089d029e7fbbaf3cf37e9b9a6b776791e4c5e6fda57e8d5f14c8c35a2d270846b9dbe005cda16af4408f3ab06a916eeeb9c9594b70424a4c1d171295b6763b22f47f80b53ccbb904bd68fd65fbd3fbdea1035e98c21a7dbc91a9b5bc7690f05ec317c97f8764eb48e911d428ec8d861b708e8298acb62155145155ae95f0a1d1501034753146e22d05f586d7f6b4fe12dad9a17f5db70b1db96b8d9a83edadc966c8a5466b61fc998c31f1070d9a5c9a6d268d304fe6b8fd3b4010348611abdcbd49fe4f85b623c7828c71382e1034ea67bc8ae97404b0c50b2a04f559e49950afcb0ef462a2ae024b0f0224dfd73684b88c7fbe92d02b68f759c4752663cd7b97a14943649305521326bde085630864629291bae25ff8822a14c4b666a9259ad0dc42a8290ac7bc7f53a16f379f758e5de750f04fd7cad47701c8597f97888bea6fa0bf2999956fbfd0ee68ec36e4688809ae231eb8bc4369f5fe1573f57e099d9c09901bf39caac48dc11956a8ae905ead86954547c448ae43d315e669c4242da565938f417bf43ce7b2b30b1cd4018388e1a910f0fc41fb0877a5925e466819d375b0a912d4fe843b76ef6f223f0f7c894f38f7ab780dfd75f669c8c06cffa",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
vpubOld: uint64(0),
|
|
||||||
vpubNew: uint64(0),
|
|
||||||
anchor: "43eb47565a50e3b1fa45ad61ce9a1c4727b7aaa53562f523e73952bbf33d8a41",
|
|
||||||
nullifiers: []string{
|
|
||||||
"04078ade3eaaa49699a69fdf1c5ac7732146ee5e1d6b6ca9b9180f964cc9d087",
|
|
||||||
"8ae1373524d7d510e58227df6de9d30d271867640177b0f1856e28d5c8afb095",
|
|
||||||
},
|
|
||||||
commitments: []string{
|
|
||||||
"ef6184fed651589022eeaea4c0ce1fa6f085092b04979489172b3ef8194a798d",
|
|
||||||
"f5724d6b05f1ae000013a08d612bca8a8c31443c10346dbf61de8475c0bbec51",
|
|
||||||
},
|
|
||||||
ephemeralKey: "04b47556af3d514458e2321d146071789d2335934a680614e83562f82dfd405b",
|
|
||||||
randomSeed: "54a45eb32c165448d4d5d61ca2859585369f53f1a137e9e82b67b8fdaf01bda5",
|
|
||||||
vmacs: []string{
|
|
||||||
"4a317311896ae10280a032440c420a421e944d1e952b70d5826cd3b08b7db963",
|
|
||||||
"0fe4fd5f22125de840fcc40b98038af11d55be25432597b4b65b9ec1c7a8bbfd",
|
|
||||||
},
|
|
||||||
proofGroth16: "052cbf7e1c1785314934b262d5853754f1f17771cfb7503072655753fa3f54ecc587e9f83b581916092df26e63e18994cb0db91a0bbdc7b6119b32222adf5e61d8d8ae89dae4954b54813bb33f08d562ba513fee1b09c0fcd516055419474dd7fda038a89c84ea7b9468287f0eb0c10c4b132520194d3d8d5351fc10d09c15c8cc101aa1663bbf17b84111f38bb439f07353bdea3596d15e713e1e2e7d3f1c383135b47fa7f81f46df7a902a404699ec912f5656c35b85763e4de583aecaa1df",
|
|
||||||
encCiphertexts: []string{
|
|
||||||
"d5d2677d9c8ffee877f63f40a5ca0d67f6e554124739f805af876aeede53aa8b0f8e5604a73c30cbd09dad963d6f8a5dcc40def40797342113ba206fae8ebe4f3bc3caf69259e462eff9ba8b3f4bfaa1300c26925a8729cd32915bfc966086f0d5560bbe32a598c22adfb48cef72ba5d4287c0cefbacfd8ce195b4963c34a94bba7a175dae4bbe3ef4863d53708915090f47a068e227433f9e49d3aa09e356d8d66d0c0121e91a3c4aa3f27fa1b63396e2b41db908fdab8b18cc7304e94e970568f9421c0dbbbaf84598d972b0534f48a5e52670436aaa776ed2482ad703430201e53443c36dcfd34a0cb6637876105e79bf3bd58ec148cb64970e3223a91f71dfcfd5a04b667fbaf3d4b3b908b9828820dfecdd753750b5f9d2216e56c615272f854464c0ca4b1e85aedd038292c4e1a57744ebba010b9ebfbb011bd6f0b78805025d27f3c17746bae116c15d9f471f0f6288a150647b2afe9df7cccf01f5cde5f04680bbfed87f6cf429fb27ad6babe791766611cf5bc20e48bef119259b9b8a0e39c3df28cb9582ea338601cdc481b32fb82adeebb3dade25d1a3df20c37e712506b5d996c49a9f0f30ddcb91fe9004e1e83294a6c9203d94e8dc2cbb449de4155032604e47997016b304fd437d8235045e255a19b743a0a9f2e336b44cae307bb3987bd3e4e777fbb34c0ab8cc3d67466c0a88dd4ccad18a07a8d1068df5b629e5718d0f6df5c957cf71bb00a5178f175caca944e635c5159f738e2402a2d21aa081e10e456afb00b9f62416c8b9c0f7228f510729e0be3f305313d77f7379dc2af24869c6c74ee4471498861d192f0ff0f508285dab6b",
|
|
||||||
"6a36ccf7d12256cc76b95503720ac672d08268d2cf7773b6ba2a5f664847bf707f2fc10c98f2f006ec22ccb5a8c8b7c40c7c2d49a6639b9f2ce33c25c04bc461e744dfa536b00d94baddf4f4d14044c695a33881477df124f0fcf206a9fb2e65e304cdbf0c4d2390170c130ab849c2f22b5cdd3921640c8cf1976ae1010b0dfd9cb2543e45f99749cc4d61f2e8aabfe98bd905fa39951b33ea769c45ab9531c57209862ad12fd76ba4807e65417b6cd12fa8ec916f013ebb8706a96effeda06c4be24b04846392e9d1e6930eae01fa21fbd700583fb598b92c8f4eb8a61aa6235db60f2841cf3a1c6ab54c67066844711d091eb931a1bd6281aedf2a0e8fab18817202a9be06402ed9cc720c16bfe881e4df4255e87afb7fc62f38116bbe03cd8a3cb11a27d568414782f47b1a44c97c680467694bc9709d32916c97e8006cbb07ba0e4180a3738038c374c4cce8f32959afb25f303f5815c4533124acf9d18940e77522ac5dc4b9570aae8f47b7f57fd8767bea1a24ae7bed65b4afdc8f1278c30e2db98fd172730ac6bbed4f1127cd32b04a95b205526cfcb4c4e1cc955175b3e8de1f5d81b18669692350aaa1a1d797617582e54d7a5b57a683b32fb1098062dad7b0c2eb518f6862e83db25e3dbaf7aed504de932acb99d735992ce62bae9ef893ff6acc0ffcf8e3483e146b9d49dd8c7835f43a37dca0787e3ec9f6605223d5ba7ae0ab9025b73bc03f7fac36c009a56d4d95d1e81d3b3ebca7e54cc1a12d127b57c8138976e791013b015f06a624f521b6ee04ec980893c7e5e01a336203594094f82833d7445fe2d09130f63511da54832de9136b39",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
joinSplitPubKey: "f4599f5aa5dfbb45da60cdceab7eefde89be63f3f7c0d2324847cce1405def7c",
|
|
||||||
joinSplitSig: "469b0e272494e5df54f568656cb9c8818d92b72b8bc34db7bb3112487e746eefe4e808bbb287d99bf07d00dabededc5e5f074ffeae0cba7da3a516c173be1c51",
|
|
||||||
bindingSig: "3323e119f635e8209a074b216b7023fadc2d25949c90037e71e3e550726d210a2c688342e52440635e9cc14afe10102621a9c9accb782e9e4a5fa87f0a956f5b",
|
|
||||||
},
|
|
||||||
// Test vector 2
|
|
||||||
{
|
|
||||||
txid: "6732cf8d67aac5b82a2a0f0217a7d4aa245b2adb0b97fd2d923dfc674415e221",
|
|
||||||
header: "04000080",
|
|
||||||
nVersionGroupID: "85202f89",
|
|
||||||
vin: [][]string{
|
|
||||||
{"56e551406a7ee8355656a21e43e38ce129fdadb759eddfa08f00fc8e567cef93", "c6792d01", "0763656300ac63ac", "8df04245"},
|
|
||||||
{"1a33590d3e8cf49b2627218f0c292fa66ada945fa55bb23548e33a83a562957a", "3149a993", "086a5352516a65006a", "78d97ce4"},
|
|
||||||
},
|
|
||||||
vout: [][]string{
|
|
||||||
{"e91cb65a63b70100", "09516a6a656aac636565"},
|
|
||||||
{"5cc7c9aae5bd0300", "02636a"},
|
|
||||||
},
|
|
||||||
nLockTime: "675cb83e",
|
|
||||||
nExpiryHeight: "43e29c17",
|
|
||||||
valueBalance: "44b8b5b99ce30500",
|
|
||||||
spends: []spendTestVector{
|
|
||||||
{
|
|
||||||
cv: "b0f5b874a6ecabe6c56ee58b67d02f5d47db8cc3458435d5088d69b2240c28f3",
|
|
||||||
anchor: "71c012c415d2382a6eebc8b3db07ea1cbf28288daaa91538de4552eeeef72c24",
|
|
||||||
nullifier: "c85d83db20efad48be8996fb1bff591efff360fe1199056c56e5feec61a7b8b9",
|
|
||||||
rk: "f699d6012c2849232f329fef95c7af370098ffe4918e0ca1df47f275867b739e",
|
|
||||||
zkproof: "0a514d3209325e217045927b479c1ce2e5d54f25488cad1513e3f44a21266cfd841633327dee6cf810fbf7393e317d9e53d1be1d5ae7839b66b943b9ed18f2c530e975422332c3439cce49a29f2a336a4851263c5e9bd13d731109e844b7f8c392a5c1dcaa2ae5f50ff63fab9765e016702c35a67cd7364d3fab552fb349e35c15c50250453fd18f7b855992632e2c76c0fbf1ef963ea80e3223de3277bc559251725829ec03f213ba8955cab2822ff21a9b0a4904d668fcd77224bde3dd01f6",
|
|
||||||
spendAuthSig: "ffc4828f6b64230b35c6a049873494276ea1d7ed5e92cb4f90ba83a9e49601b194042f2900d99d312d7b70508cf176066d154dbe96ef9d4367e4c840e4a17b5e",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
|
|
||||||
cv: "26bca7fdd7cc43201c56f468fadc42cff0d81a966417ad8f097ebf3b25879e55",
|
|
||||||
anchor: "c23e34da91c816d8d1790dfe34bdce040db1727af24d59ef78d3f4aac2b59822",
|
|
||||||
nullifier: "d6f12f24fd364496b3be0871ca3dd9625348a614b59bde45885649bae36de34d",
|
|
||||||
rk: "ef8fcec85343475d976ae1e9b27829ce2ac5efd0b399a8b448be6504294ee6b3",
|
|
||||||
zkproof: "c1c6a5342d7c01ae9d8ad3070c2b1a91573af5e0c5e4cbbf4acdc6b54c9272200d9970250c17c1036f06085c41858ed3a0c48150bc697e4a695fef335f7ad07e1a46dc767ff822db70e6669080b9816b2232c81a4c66cc586abfe1eaa8ca6cf41fc3c3e6c7b886fb6dac9f4822b4fc6fff9d0513d61a21c80a377671d135a668a0ae2bb934c82c4142da69d12ca7de9a7df706400ec79878d868e17e8f71ea31495af819a016cc419e07c501aa8309b2e6c85b79b2763733a37bbc0420d42537",
|
|
||||||
spendAuthSig: "b871b4294a65d3e055ff718dd9dc8c75e7e5b2efe442637371b7c48f6ee99e3ea38a4b0f2f67fc2b908cda657eae754e037e262e9a9f9bd7ec4267ed8e96930e",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
cv: "eb89a85980f97d7faaed78d8f38beb624b774c73a46ced614be219b3d94873b6",
|
|
||||||
anchor: "0df7fc90b579abf62037975edd6aacc442190a0ba55b15f81f86bade794ace2a",
|
|
||||||
nullifier: "9d9a816baf728a955b960b7701fa626687dc3c9cba646337b53e29816e9482dd",
|
|
||||||
rk: "f5578a8768aae477fce410ac2d5de6095861c111d7feb3e6bb4fbb5a54955495",
|
|
||||||
zkproof: "972798350a253f05f66c2ecfcbc0ed43f5ec2e6d8dba15a51254d97b1821107c07dd9a16ef8406f943e282b95d4b362530c913d6ba421df6027de5af1e4745d5868106954be6c1962780a2941072e95131b1679df0637625042c37d48ffb152e5ebc185c8a2b7d4385f1c95af937df78dfd8757fab434968b0b57c66574468f160b447ac8221e5060676a842a1c6b7172dd3340f764070ab1fe091c5c74c95a5dc043390723a4c127da14cdde1dc2675a62340b3e6afd0522a31de26e7d1ec3a",
|
|
||||||
spendAuthSig: "9c8a091ffdc75b7ecfdc7c12995a5e37ce3488bd29f8629d68f696492448dd526697476dc061346ebe3f677217ff9c60efce943af28dfd3f9e59692598a6047c",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
outputs: nil,
|
|
||||||
vJoinSplits: nil,
|
|
||||||
joinSplitPubKey: "",
|
|
||||||
joinSplitSig: "",
|
|
||||||
bindingSig: "c01400f1ab5730eac0ae8d5843d5051c376240172af218d7a1ecfe65b4f75100638983c14de4974755dade8018c9b8f4543fb095961513e67c61dbc59c607f9b",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSaplingTransactionParser(t *testing.T) {
|
|
||||||
testData, err := os.Open("../testdata/zip243_raw_tx")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer testData.Close()
|
if len(testdata) < 3 {
|
||||||
|
t.Fatal("tx_vt.json has too few lines")
|
||||||
|
}
|
||||||
|
testdata = testdata[2:]
|
||||||
|
for _, onetx := range testdata {
|
||||||
|
var txtestdata TxTestData
|
||||||
|
|
||||||
// Parse the raw transactions file
|
err = json.Unmarshal(onetx, &txtestdata)
|
||||||
rawTxData := [][]byte{}
|
|
||||||
scan := bufio.NewScanner(testData)
|
|
||||||
for scan.Scan() {
|
|
||||||
dataLine := scan.Text()
|
|
||||||
// Skip the comments
|
|
||||||
if strings.HasPrefix(dataLine, "#") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
txData, err := hex.DecodeString(dataLine)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
rawTxData = append(rawTxData, txData)
|
t.Logf("txid %s", txtestdata.Txid)
|
||||||
}
|
rawTxData, _ := hex.DecodeString(txtestdata.Tx)
|
||||||
|
|
||||||
for i, tt := range zip243tests {
|
|
||||||
tx := NewTransaction()
|
tx := NewTransaction()
|
||||||
|
rest, err := tx.ParseFromSlice(rawTxData)
|
||||||
rest, err := tx.ParseFromSlice(rawTxData[i])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Test %d: %v", i, err)
|
t.Fatalf("%v", err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(rest) != 0 {
|
if len(rest) != 0 {
|
||||||
t.Errorf("Test %d: did not consume entire buffer", i)
|
t.Fatalf("Test did not consume entire buffer, %d remaining", len(rest))
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
// Currently, we can't check the txid because we get that from
|
||||||
// If the transaction is shorter than it should be, parsing
|
// zcashd (getblock rpc) rather than computing it ourselves.
|
||||||
// should fail gracefully
|
// https://github.com/zcash/lightwalletd/issues/392
|
||||||
for j := 0; j < len(rawTxData[i]); j++ {
|
if tx.version != uint32(txtestdata.Version) {
|
||||||
_, err := tx.ParseFromSlice(rawTxData[i][0:j])
|
t.Fatal("version miscompare")
|
||||||
if err == nil {
|
|
||||||
t.Errorf("Test %d: Parsing transaction unexpected succeeded", i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if len(rest) > 0 {
|
|
||||||
t.Errorf("Test %d: Parsing transaction unexpected rest", i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if tx.nVersionGroupID != uint32(txtestdata.NVersionGroupId) {
|
||||||
// Transaction metadata
|
t.Fatal("nVersionGroupId miscompare")
|
||||||
if !subTestCommonBlockMeta(&tt, tx, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
if tx.consensusBranchID != uint32(txtestdata.NConsensusBranchId) {
|
||||||
// Transparent inputs and outputs
|
t.Fatal("consensusBranchID miscompare")
|
||||||
if !subTestTransparentInputs(tt.vin, tx.transparentInputs, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
if !subTestTransparentOutputs(tt.vout, tx.transparentOutputs, t, i) {
|
if len(tx.transparentInputs) != int(txtestdata.Tx_in_count) {
|
||||||
continue
|
t.Fatal("tx_in_count miscompare")
|
||||||
}
|
}
|
||||||
|
if len(tx.transparentOutputs) != int(txtestdata.Tx_out_count) {
|
||||||
// JoinSplits
|
t.Fatal("tx_out_count miscompare")
|
||||||
if !subTestJoinSplits(tt.vJoinSplits, tx.joinSplits, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
if len(tx.shieldedSpends) != int(txtestdata.NSpendsSapling) {
|
||||||
testJSPubKey, _ := hex.DecodeString(tt.joinSplitPubKey)
|
t.Fatal("NSpendsSapling miscompare")
|
||||||
if !bytes.Equal(testJSPubKey, tx.joinSplitPubKey) {
|
|
||||||
t.Errorf("Test %d: jsPubKey mismatch %x %x", i, testJSPubKey, tx.joinSplitPubKey)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
if len(tx.shieldedOutputs) != int(txtestdata.NoutputsSapling) {
|
||||||
testJSSig, _ := hex.DecodeString(tt.joinSplitSig)
|
t.Fatal("NOutputsSapling miscompare")
|
||||||
if !bytes.Equal(testJSSig, tx.joinSplitSig) {
|
|
||||||
t.Errorf("Test %d: jsSig mismatch %x %x", i, testJSSig, tx.joinSplitSig)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
if len(tx.orchardActions) != int(txtestdata.NActionsOrchard) {
|
||||||
// Begin Sapling-specific tests
|
t.Fatal("NActionsOrchard miscompare")
|
||||||
testValueBalanceBytes, _ := hex.DecodeString(tt.valueBalance)
|
|
||||||
testValueBalance := int64(binary.LittleEndian.Uint64(testValueBalanceBytes))
|
|
||||||
if testValueBalance != tx.valueBalance {
|
|
||||||
t.Errorf("Test %d: valueBalance mismatch %d %d", i, testValueBalance, tx.valueBalance)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !subTestShieldedSpends(tt.spends, tx.shieldedSpends, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if !subTestShieldedOutputs(tt.outputs, tx.shieldedOutputs, t, i) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
testBinding, _ := hex.DecodeString(tt.bindingSig)
|
|
||||||
if !bytes.Equal(testBinding, tx.bindingSig) {
|
|
||||||
t.Errorf("Test %d: bindingSig %x %x", i, testBinding, tx.bindingSig)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if hex.EncodeToString(tx.GetDisplayHash()) != tt.txid {
|
|
||||||
t.Errorf("Test %d: incorrect txid", i)
|
|
||||||
}
|
|
||||||
// test caching
|
|
||||||
if hex.EncodeToString(tx.GetDisplayHash()) != tt.txid {
|
|
||||||
t.Errorf("Test %d: incorrect cached txid", i)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func subTestShieldedSpends(testSpends []spendTestVector, txSpends []*spend, t *testing.T, caseNum int) bool {
|
|
||||||
if testSpends == nil && txSpends != nil {
|
|
||||||
t.Errorf("Test %d: non-zero Spends when expected empty vector", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(testSpends) != len(txSpends) {
|
|
||||||
t.Errorf("Test %d: Spend vector lengths mismatch", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
success := true
|
|
||||||
for j, tt := range testSpends {
|
|
||||||
tx := txSpends[j]
|
|
||||||
|
|
||||||
testCV, _ := hex.DecodeString(tt.cv)
|
|
||||||
if !bytes.Equal(testCV, tx.cv) {
|
|
||||||
t.Errorf("Test %d spend %d: cv %x %x", caseNum, j, testCV, tx.cv)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testAnchor, _ := hex.DecodeString(tt.anchor)
|
|
||||||
if !bytes.Equal(testAnchor, tx.anchor) {
|
|
||||||
t.Errorf("Test %d spend %d: anchor %x %x", caseNum, j, testAnchor, tx.anchor)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testNullifier, _ := hex.DecodeString(tt.nullifier)
|
|
||||||
if !bytes.Equal(testNullifier, tx.nullifier) {
|
|
||||||
t.Errorf("Test %d spend %d: nullifier %x %x", caseNum, j, testNullifier, tx.nullifier)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testrk, _ := hex.DecodeString(tt.rk)
|
|
||||||
if !bytes.Equal(testrk, tx.rk) {
|
|
||||||
t.Errorf("Test %d spend %d: rk %x %x", caseNum, j, testrk, tx.rk)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testzkproof, _ := hex.DecodeString(tt.zkproof)
|
|
||||||
if !bytes.Equal(testzkproof, tx.zkproof) {
|
|
||||||
t.Errorf("Test %d spend %d: zkproof %x %x", caseNum, j, testzkproof, tx.zkproof)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testspendAuthSig, _ := hex.DecodeString(tt.spendAuthSig)
|
|
||||||
if !bytes.Equal(testspendAuthSig, tx.spendAuthSig) {
|
|
||||||
t.Errorf("Test %d spend %d: spendAuthSig %x %x", caseNum, j, testspendAuthSig, tx.spendAuthSig)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success
|
|
||||||
}
|
|
||||||
|
|
||||||
func subTestShieldedOutputs(testOutputs []outputTestVector, txOutputs []*output, t *testing.T, caseNum int) bool {
|
|
||||||
if testOutputs == nil && txOutputs != nil {
|
|
||||||
t.Errorf("Test %d: non-zero Outputs when expected empty vector", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if len(testOutputs) != len(txOutputs) {
|
|
||||||
t.Errorf("Test %d: Output vector lengths mismatch", caseNum)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
success := true
|
|
||||||
for j, tt := range testOutputs {
|
|
||||||
tx := txOutputs[j]
|
|
||||||
|
|
||||||
testCV, _ := hex.DecodeString(tt.cv)
|
|
||||||
if !bytes.Equal(testCV, tx.cv) {
|
|
||||||
t.Errorf("Test %d output %d: cv %x %x", caseNum, j, testCV, tx.cv)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testcmu, _ := hex.DecodeString(tt.cmu)
|
|
||||||
if !bytes.Equal(testcmu, tx.cmu) {
|
|
||||||
t.Errorf("Test %d output %d: cmu %x %x", caseNum, j, testcmu, tx.cmu)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testEphemeralKey, _ := hex.DecodeString(tt.ephemeralKey)
|
|
||||||
if !bytes.Equal(testEphemeralKey, tx.ephemeralKey) {
|
|
||||||
t.Errorf("Test %d output %d: ephemeralKey %x %x", caseNum, j, testEphemeralKey, tx.ephemeralKey)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testencCiphertext, _ := hex.DecodeString(tt.encCiphertext)
|
|
||||||
if !bytes.Equal(testencCiphertext, tx.encCiphertext) {
|
|
||||||
t.Errorf("Test %d output %d: encCiphertext %x %x", caseNum, j, testencCiphertext, tx.encCiphertext)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
testzkproof, _ := hex.DecodeString(tt.zkproof)
|
|
||||||
if !bytes.Equal(testzkproof, tx.zkproof) {
|
|
||||||
t.Errorf("Test %d output %d: zkproof %x %x", caseNum, j, testzkproof, tx.zkproof)
|
|
||||||
success = false
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return success
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
040000008a024cebb99e30ff83d5b9f50cc5303351923da95a8dc7fda3e0160900000000226b1c86e101f1fac09aa533c246bd6843ee6b444ad3ff251df0a401f16f0981000000000000000000000000000000000000000000000000000000000000000069cb7d5b0f1d0a1c0000000000000000004d6cdd939a4900000000000000000000000000310c50b3fd4005008f78a11b4b81126dec31cba6ede2e131ab376a8611237b04d20cd8bb4253f1e8721e0941970e0f58c206f09c8c86c70b2f73b3b5994571c389a90fadf6b812cebba5afe622b3e4aab20a88c805e1f3925e31300df11c09e3d4b7acebbfb156b75e213e36f65d88f023feae5d37ab2f13a1215299155b7d9a1f4cbb333212e8ef9959785adfcd2506d33ac1021207fc32584022080f4a7ba67157ea99f6fc645737a2a5c6f5d99700ff0c1a92f2845dba3b022d24de26691c0b56977b13e94d5f93ebe423d3d422a478f2e6d9f0b113b3fa0434fe432c173013b1a641e884f74922a3e6fc6cde4dedcd8c2458be13fb91f5285ffbf8a5dd207dad3b011b832444a85e27da43c1f94864ad7b066559d5210bf495565005f9297f6204ad7b4c395d5faa19c2530427ad4889555aefd272185f825564525f6d3e0bb62b18cce8ca120a6f636ee36f18612fede045bae81403752f8154e7c3bf4fef7134591379389155360cd15328c731c1ed3b57f439994b0350799e91f91f53e30ce9bed6ea9ce01b3f74f6041b739d85965d789b9c43ba65cf4f99808ef03c2ac46461ba0eedc05e77400815af9d8049027bb7fef6646142d86ef35adcca060e8a656c6c6cc811f65231b4ac531fa2083ddffbab26d19409cc357b89ed7da3d25476cb9d9a9c939c343d23fa35a09c52d593fb03f609dafcc28579fdd35e044168e33e747757bfdf5123080b6799d2527368f90de7f126304610765670214b6e9b6f497a491650db139129da19964461c368e2524aa1524248ed92561b3e94aec38d5ff4adcab5f73565dc7626477b1d56620ad1bb49000d1cd915a260c0913960c493edb9770d2fefae76dae63963e147331a51b1c66d5ff3ecf87f141306d575e60ca3b34fd26cb0b1d735dbbb1977db519a7a9d345ccc77121b688c7470975ee9dbfc489800f25a41d406ccbcbe1f01c629dfcbd59ea5dcd00334cc6af8718e08631c3a83d5e6395b4acc3afab48b145b73a064904176c30c2cd9a876ebab5f333b6ebd17c10e31ce6f009daad792c31fce13dd6d401120eb08d66348c13735ffc667e653ccf80bda54d0773473177433406a0c2001ec9f534c54e667c5a3cff3bca72625b5fee94a51dfc2b5b3fc73353b2b2f3a9e708932003e771dd21441e9cd075765e33ab5fe0db05b4b087bb04608d5fe5bd32f8272752cb1e59f856eab0e366a935a9651be4584f8886649c66bb6bff29ac82e0bf749c94e46cc6a42988196c15d3b2a6376185b990e653cbc8a77e56fd3e74378bcd54f4540afdf39650950fd18192198bd743708fcd948ec57aab07d71211157758ca83509cbc0094158b75bd840810fb266f91565df4f4013aaa4e414b3a56bf8442938189441ae24f8e2417b7bb729f9cf27a2ee5da291fed793afcf09a1c63f14af0dab7aa6b34b1be3d545356653f14a2d31173cf50fa6aed549933a5743cd46809bf6e64824111cb5032130536943f359ffe5cc7ad5b4dcce3f2d078f7ca751fb08f8a5d9ac3970cb9f2cf31ed1a713cec3e8bac8586ce10c74e215c3d691c58e176b39382da1fe4ff0edc7f23373f594ab00c987c772f92317575d4d199e79f5b95fe1986ff0dd4d4a339a797b3b366e737bf8befbf80fe58f0d5b6f35c831d00ebd0c47ddcec914cf879ca685c0724b9036f98abacd96102657148a55e6e7896f33d51daa97190a233a4d68278b51c2bd26dd23916c54e605b6578a8e3657359c36a9ee2e4c0f650a95a3f4b61c4133ddaa901154d20c807a6ab85211bda537f26a4fe4b53a4a64f5522d13eb75cd2bab7669ef47d1c7fd43416182bcde9370105383fa2c0c574d4895d2fea59889068e66f83c8f15118c7ce7adb41fd8de61c2afd7277d6ac31346aa01030000807082c403010000000000000000000000000000000000000000000000000000000000000000ffffffff0503e0ce0500ffffffff0200ca9a3b000000001976a914361683f47d7dfc6a8d17f8f7b9413ff1a27ec62988ac80b2e60e0000000017a91414c884180589f6d0fdc7c400181afb1bb10c9fe487000000000000000000
|
0400000006785624481f381e68b4506ba5d6cc53ddd6dc876cbc97e45e3c7c4a626a19008c450aa9112b2e900eba30c2e3b8428c23fb2a30bb7fa34a853c97f02fb1a2200d86a7943df2dc92fb8b131b0698db24dd01a12d19696c20443f5f639df3ab5aecdc295c172c191f870000790c975f8c9f0a77f12ef1e021c6045c3c9acb7c432c2aa7ed42ad0000fd4005005db35c547608bbf32bd1b90369e6e0bc1e275a0d064f092b235835cb6dfc9158c6146a0e5cfbdf2d2f04f71478f7d9212bdeeb938029a5cc217ebf1f517711dbc7cb35d084328b8f7613e878f69e27b2b40e8103292cb87845006943b761bbbe43d94cfbf971011617965a7de1e846a586ad81f2ad138eb0fd74729efc04720badc95a1f1383cc70e890db91c143591ab96526263ec6b8a6186568dda29b9015078d19e87cbb2c00b26edee3e4b227ad6fa090db2d290191ef1043e2037fc0bd225e6a1364d16223b0234311e8c5ff455a0cc2e0c1f84944dfab49864f57e5ec2a2b5e91df5229449ee399b4c721abab63c534602abdf64d37f60905bea71cd59be759bae5967f6f3e1bf732753d4d9c1c11dcb5b6949bc4f63a06a3b0db5c2deebab040c70fc55fc648bb2559fe2da2b4a4bd53ccbca7aaf03262cdf31c5bab90cdc151b686d3e5f8a29103b9346602b5394b245dc9655116d33c2ed9d31563bb74950d0927895a024c119d30d4f2c760c346b11108ab29db2931123aa36937cbd152756758e3d341ec40db1d1b539fcbefa2e76af9827f575025c58569fbec1f806607e03a6eabc228a900a18144e310ab608a930ee6a10d5e6fc7ecc9934fb42b51f0a6552e2a1ba1d627b51df2d27889e14b87f093452b79bce3e2a74398f4b748eda48495b30437bef13527a231ce724f24d5bcf4040cc77f56dab50ff30ce12039ca968eef3c5ab44b2cdd8f7fecb36ed39bc624807a4da49d5b2f53abeb1a027676fb500fb89d7092eef849f254dfd3a7325e4b810687b8567d7db8e796480836bbeab2efff44bb0421f4e3d5d1493bedc2c331f75b7ba931e93495dc379fa22404a2e60919fb2644ee4e5c3bc2025fb17540dce5dede2fdc4fc6b87494ae26ae89bbe954ee8458740601a665126129c9962052683661efcfffce8303211fe3bf0adac14936927ce2f4b30a22227c39b4128616dfbfcaeae8f4a3b30255d215d1b9ccd9bff2173b5a94ffa5473bc49097030e782d81c1dc4f8c4a25803c6dd9a9e775646084ed2bbbf7457386ece058032128bc87c7b7772be513f79176241de701580b5c04f88ee81e231583528b514f0c478382e60d5741bd0b5582c2ece2767931f538d050498886814c5b27541764bda9734d5c46f2b3c80f2649d40374e45c053c050e33e83ed578f6d5c19435b7f495261e7e522d5225eaead374497fed7c30e322d6acbf512751b58417120bf8d97fcfdaa5e3be842fc7beab85235ff7e9ee459b03ef2ae01ceff42e0621ddce403e65521505ed0b25fca1a0747263e44c72c5e1e95d85119a7956852c629fcb903b9589e768a6bcbec5358a5332368a6913ffb9b9880e8d3701c6a366bec102bab8c6d9e57b2287ede4774d69fe81af83dbd423c905f666170bfc03f360314edf3098fe2036634ad90f326a71faa5b70f245acbdf8f7d4481283819d8dae7823ac31bafef129b94822a4d94b8ea5773b7477269be9dbe3bc8c11886a2d2a8176658fe30e1ba1bdcf320873d1d2325096223af6e142818a2c370b8447db8e6e865fef2074596bc9e679b8c37c51e99c4f35ac8431303fac507193d1d162d309a3d8d6e57cf4cd429b34ce69f69ef2f1e728d7b9347051b46d4ba5a7e7f9d43963e960d0bbaf63eeb69396dc75b325f08e9243db0c678aa192eb3db32d9cf65a0a38bd5726e31380f2de23ea9a019d8496ab511df2d955978fcee6e331aeea5df0a1826639323180b87bbbf6a039e34f482a5e4eabc6d9a139c40e2840b40eb53dea3d549b54405ba7e1b392f308df2abfd6e97a3eb44f540b272a6d97c085be2142445ea27349bc7a5493397ceee4c8016a38457480f4de263cd2c2416296a2d86c19ded93cf431bfdd1e3010400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff0603e0ce050103ffffffff0200ca9a3b000000001976a914f4fbba801ad64c6539e64a1478392c57c9a5e7a688ac80b2e60e0000000017a91466a04fe5f6f1b5bb1149e6cd0079167f570880148700000000000000000000000000000000000000
|
||||||
0400000015bea7ff6272a28e0dd187b5160d8fae6f2ad6316d652fdd26b92204000000008ede1b5093bbb6ae7c883dbd4b8bfc9e97290ac6ba5a617c880d3aef1bc41d9200000000000000000000000000000000000000000000000000000000000000009bcb7d5ba51e0a1c0000000000000000002c476f1d2c08000000000000000000000000002c27173bfd4005001a40fe9c1795f9617212aa1ade76cd93f85db2e5254a8ffd5aab68218adb36065f6947477a423c26c719803ba9c01555a1d81ef1cbd4ab0e7a7c9c7aeba622c7c1614f16409f5b0f757a93d12923027fbe875e01d4003525150ba313f43148bf39e7836a3d5fae611de2de0eebd8a3d1b163e4ad7b3ad0bbc00a3f4b8d029ee0e23f6354cbc381711eec9df770f31149ac1e0eb55229d10d7ba106edb12834296cfd241f5a62a6014ac0726dc4543f05a88138ad2d7654b707aa799115886e467957d5f195fda7a0a0d7908e084b974a1e0565e222acc9670f4f7191b4052f84595457315647468f532773a0755b0b3c7649aad0ce1e9da9597819022f7c951ddf47978c5985bb3f4350b1b91f2eff7f149ba3992316712d0bb2a3b6fbb3dee54b516d22b21f60c23f87e3513d2ae3447191b55b17f3671f9e3629da0eb3b8261cb7eccc675761f95452435bf6b6f800a4e5a2deeee86b8ae3d026a11eaed463373c378b079a68b51eed25b596fd519a2530f9414684d71dfa427c461ab170137fcd343af2fef3122bb037df784e647b6386823340abffa60668eb7a5729fdda35d42602729b2fa822d11da41c304ce27530bc17e717fdd10a2f221cf793e4db842ee2f6f04b2a74d3945214ec0d1819005f0e42f68c8183e9a0a87011180ed87eb3205e7f01d7a760d95b874ae2d17e915b267cbd0e4e06e99982744e7473f74af2ff766730ee01f7528478116633f7d2eebd87d8e134429e4d29b92144fd0ffb1628add40f98c4df2856632055a3d2c70a2abf69851929b6aa5a9de2af2148ea564a7520f6d95e5724b40c2a3c9d39c995b2f3e131795f2299029c215b07cd14bce9e10fd05296a8a646302ff4c45e85a4bc3bec12fedc1d1f60da8f6aac22f746d43a11bd08be8e52153c60ab71061d35284872c427e3aaff0d8a3a82af016db8d42937f04be1ccb021e7152aa82a068b0a1b04cbe51b904ffc00f3bd46cedc3c58ba378355360e11982c9981c6a5ae7c6d21fa3b2e54b8e01d49a0f618df191ffbd3274b7ac3c5f066623a15c1e07eb64e1db18f37cf4d4452c441c63b8075ca220d0131a2d022da9305700b8e0d236ab4dfd17c2f453c3f17fd722925de3cdfac190bdec92340db74ad46ff693f79c92bad961d021e3a01dcf16445d66713e53bc37b89720c887088d26831e5a4a7011366eb3b6920df10a3316eb41dfbe9ef6f697bfb673be8bce2a64c16baa1ed1cce0a0bc32595bbc22f42ba8d2dbdba3f6097cf7b27cf4717d7187bab684e364a17c69e29c49ff3aab10d8f9d3002149c72d90cf115723ca3aee3c8b8014918896bf63a2746d7a486a496b274b21765dcdeb83b387252b876129b65ce91e613783f55aa1ca85c07a448b4eb36d95681c1851f7532a47e8056eacbd8c45d01b61dda489c744f267111294fef34a98c5391d6ff31491f974fdcbee1cfcd740c714abd9a616878d604076dc376afd53826da95c4b81ad0f991642a6bd3d518feec5a021e20a73be5924147203586c75b3fa9c51111119bd39061fdeedbc1a1a92aeafe834dff67071438f21b247a5713e66bf156ab70f04995ba70f4f0129da42ee3d5ca8da38c35c2b8d33d19e79618a0061ac8fdae6a58250725ab51dbda4a6541d7fe1cd31403ad8d6cfde6badbb85ff162bc1f08b109866f8aaa1688b2de068fa272a3a6371f3876101a37191dc9c308eff5bbe41512b7a749668f2a35f43e2dc67c91ed13e39bc4ce5783b795d1a16ba03886ca053dbd6a4006e0f5091e6955d7abdc154373d10d4d60ecee597c0a8d71dfbb2e3b4fa83554d459c0a68d655c9b28ff0cdd2ace655bdd8dc2322394a34255b1d5373dc39c310244fa0fa1c557d7caa3d029ad36966d0d7606e301030000807082c403010000000000000000000000000000000000000000000000000000000000000000ffffffff0503e1ce0500ffffffff0200ca9a3b000000001976a9146d17c0ca63e020d639f5fba181ca4f5da48b8f7088ac80b2e60e0000000017a91414c884180589f6d0fdc7c400181afb1bb10c9fe487000000000000000000
|
04000000913b07faeb835a29bd3a1727876fe1c65aaeb10c7cde36ccd038b2b3445e0a001e1ecc75a33e350c7763ccf055402a3082f28209c643810a2ef17df4b14486cb0d86a7943df2dc92fb8b131b0698db24dd01a12d19696c20443f5f639df3ab5a15dd295c21c8181f15000813d02ae5e889354eb9b7b62cca4f139ca6364fb63646ff32f2b4700000fd400500356a828c88fb46eaaa21d759e99109375d79b61557348f830c71fd4dabb126ae794d403af814bfd3fc01b76c2fc110525507f6728bec686ea9a432eda0ef1c8fc97d912923a9ab0d06f8aeef2ba272a3b7125e0e5079f131e4706d59c4f34a2775cfed3fca2cba4a23795351a38abfacf67ae7772e6fd14326efde46192105f2c3b0989a15aedfd22063529005723c8c8ea756ea876e0ae7846d4556e57fdb4b7ae1d2125456130653604eff1a6e632e20350a88b0fece49fa57079818d28c0064764979ed2e75766767a7ddce8578a23712274fac056571619b9ef4371f6924068fd5dcf25112da1ffe4255fe60b851e50b704eef0577967a867a0fbd7ed06f0d93f0f0ae31830ab5eaee5b20757e96233c21f96d6eb8f5b5ff03e88d7a31ced8037a52d94ce82fb719764841c06016ba82e29acb9d521cf9d74e1a1a90175c19ff365b763db1d3fbb6332499a5f90903d26af753812bca3eb2b142992bbd87140c3a0c29732d648c650e6bdfda63a56c6184570bf2bb4d700ba30d7800cecac92f67647bbb282d85228fedbdae1e1e3d56e9cb7743a58f02df45f658cb3b627f6bb311618d1697a217ede3f763d8fbf1fba96f697a62b321d397d492594b477029b23565f8ee80e3df1a74d81be2eaf203e3c9215c72c5fa6ec5f0d20cff3f151d7131ff6a3021f489f87819245d6af34f12dc5d1bd70d2a692be0da4827ed3f81a4b63ee58223bcb53474471a4bfcab99ca08d7dfc6c1cefda57f836d1e58731b4eccbea60c0606dc42945b26b17a3599be385b0b64519f6160adb65fd1da795cf27ea25e9884783834130be24ec10d549eb21ca32188f4221d3ee358f2894099930d165ca4d78985e6c13ceb9ea340ad5c116118c6a2d7851781e554a0e1b968540151e3715513f5476ff6618a5de0498e4f5632a6d5ffea8579ddd0be010b10204499c82540d521397b9a39a079acccaaae32add4d7991db22dcfcb04f86730cbef5b8abb0fa31137abab148457325eb161fd0ebe033094c324f6da261fc31476619753fe95c63a326fd14dbe6e7f83c501b77d4ce5602877b5164973dd55c04f7a891e6f3b423ee425b992d73bdf7e2735e4f52cbedceed9afde086f923208dc1abf1ddce86f9e7c467a8b0b79740510900bef0351faffdda005bd35e5a819b96c1622ca06399cc62f01d08d64c4236970e6c119380df5c48d11d57a8908e76b6d8ac3517f459ec83af139986abf135ea4be1886054eeb0087996aff4ace796b765175166f46af49d6ba10f8b5a455f7bc04ad82a53ac8d71529a6d0dd138642b68a518b61be13761b33bf60133cf97c9c2a0fab6cbfaf3601c0642b6d918b142caf1da2da75d52523739a62984f34f3016ed17cfe03522e71e332079920eb33c0b41de3c3f41e92c0382f7804195e251c0db4d2b6db83566cb4a767a9a85d4d674b226732bbe298ab5df3d5fe2239b82dca3fef254d1a7e3fa9c3545a23eb49136fcd21308280715c7d26601eb40fc49e025b33a6f676b16ae215bce5d6281e0bee2d779549ca7fe32811335e404c10e142ec50c5442afbb03ce0f179848765998ef1a3b60062fd187733919a34999d8bc5724d354421e699e25c39d416c74eb3e2c79229656b54af9a3cb0e71a52e8a9fefd08043f69ad8a8e536b0728e2a039ee80c999d4bd86340c97dea3cb2be33ff333e11dddf0ddd482d99844df08f7bc2ac351987b71e802aec4266b372f2a1e86780b89be04b444801e52c2a4cbf0cc2049e2b3d2c6180e7a28ba0e459de1ddbd016e0c3538f137dc98e2ee1729d5d5b0879073eb421183da7b55866ba8b79c911792a4a6b80b9ed15dfc4249d4c88cf229bc16491f5b8f1afcf272622bf782396aa55fe527a5a67d6327010400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff0603e1ce050103ffffffff0200ca9a3b000000001976a91403e105ea5dbb243cddada1ec31cebd92266cd22588ac80b2e60e0000000017a91466a04fe5f6f1b5bb1149e6cd0079167f570880148700000000000000000000000000000000000000
|
||||||
040000003723935953489b860d1de1b8fc8240ced04625f0ffd23f16519b8e0700000000f066ce1a8f2b97d05dc15ee51e1eedac93ba6057a953eb81d3f856e9f4b7ae270000000000000000000000000000000000000000000000000000000000000000c8cb7d5b13520a1c00000000020ff5b32c230200000000000000000000000000000000000d5e39cefd4005003eed282b472cfdcb0540b4f4245ed479c5357ff11989ef70be9700eff5987318f727dafa0b467302aa016e5e956c5a5d23f0f9e4a5623b9dda30e0f1b3c47e8c3d151e686cabd4ac89fc627e5cded736d707780c3dc341370bf7af4cb291878a1c4236cc207f39f081ef26b50fe099bdb90c8a9462663d1aaf079fefa010c2a8c29211f08b8debf2f90e4afade29bc53d74253c3fbdf265759fee75e1ab46adc90f38bba5f73e80e518def9b61e8b714d6e6a1dd585539ebd1f5f2040e8e73498455bec4fd333747f96823c66fb859177d13f3ba05868918255bb022cc32dd0a099438fdb1b31b15e2de9acc341066d6b20e4c1d18f56397dfe97919a2eb988e114e3cc015c1c209d906e494c46b9dac34a99ad0595868b4f84a1474ff532202149ef12acc1db1f9307213f49efcb0a408fcc1cc6124e637adb22ee4368da8d0a78b696956e7e4c9feea5d2e198f0e00bdd16ca49956c32ff793e3ff6e635efe57788fbf11a8b2a771d1981aeed6462fdd74a6a9f5d813d86616923f5add19a41d507ba22b69a0caf4a608f8b7673bd605d7f2b022b3d8436448aeb34e491c12addc3911564ecf5de8b1355f1762dc402e37915c35cb69de2a9d575a765737ff92c653eed1eb871270589c2dff15f827ba45b19ab3d25da28fe3176895a8cc32a943391276625d991492ed315ab22a7192fbcc5f5eb01611640c96585ac4db590777a87444c3dadc653bc2bb279474ad76ac00d5972b92e026d45fdd0ed84b099a13d08c00eea952c5a2a78218e06ff989f85b52801d203f82d395310f67e80f4646f3f29c5b0c2f9c3ce31530b766c12f3253a6f3e2aed5b66efd9dcdb6f1de1e601a36b00fa2b7c4d6241e46afc746cfb73f1b2f19c60f81472bd15bdaff21afb0c44514915bfbdb5a20172209c4c9c281ba14950b07b22d097bc0cce5fa017ef344aec83bca60db20f4241ab3e1d29f7f200a24b801aa1e2c638d77ac13c0732da3561e3e1bcc6f2ac78fcf21e7f113b56d83c0343a1cb6d8b69eb12975891c1bb27885f1efc8c97a0af71176f716fe36b61262e23b48e7266f6551821948e4c44d48153df60a1a921faa5766e4a99239c2f36231bdadc93e749db715ff7e8ced9ef6cb28e7a5a8aa7603de56e73ea5fd1d79be8974a4c071ed1b969382da51d68b11f4722303d74f82849cb05d07c0c313d9a0d5eccbb853f85f0c7002c67eeb93737060180a3f557582d3849b73bf13807ff3f4065faacd7562487fc96a20fcf2cc892e16ad74b813caed4f72f11293243912c976a9f2035b099b9b9debc968aec54031bb9f4eb7815ddb3bffc128d6be34814fbec58b17c6dfab6c812a5eb3fd15d60fe3fa55128466cb80bae5579b71025e6a9c34b7f818eb11cdb029eff94fa465e419b9aef2e8679f12ce02b780aba2c17313bb375033beda50e90be5fd949002fbb85634d42598b62d21e346d13c99e4b6364354136f828f972a7b2fd8c4464defb82629ffdddea6355afcf76a5b6a1f797b2a46b51cee7f95f812d926d00436f98711c6f6a1e374a5f8a6f73f39b70150ae7315988b1a2c88174e9bad58c2e0f82476bb1c9ebd03079970441810e5c7c1b8d3a5b8eb21750f29eb92f348d5ccd2dd13fc68b063c754564f490e33ba1bc71b111eb14500d1dfcd883be26a8952aed912f4a999831b80a94d1f994c69558334e165513fbe129a9348922d6205d0bdb3fed3d0fec41a8f7dac2a46f2f9bdd837d6fa791bd25ea3bedf454b7fcf8907000a78d4e911bc798c6d261817400572cea0a26e9e2f5b16cd7129e92738be52b4832c2a072e2c7db3c2b889fa089b1284a3ae2ec654da817e15e0b26856be1caa1c7c0b3446158365a0992bc01fc67c19d5444ad8c6be044902030000807082c403010000000000000000000000000000000000000000000000000000000000000000ffffffff4903e2ce050004c8cb7d5b598c2ba5c7f0b4587e7d60e62e08985aee803a179dda187d2f0c5284df7da7482f4f76657277696e7465722f5361706c696e672f706f6f6c696e2e636f6d2fffffffff02d0eb9a3b000000001976a914de2757e612dee78a681ace9b8e623570dce776f588ac80b2e60e0000000017a91414c884180589f6d0fdc7c400181afb1bb10c9fe487000000000000000000030000807082c403012263eb14eca399ec05b64be85325e2c5ab93e5d70d7dc49b4e8b8dcb52ff0f7b680200006a47304402207ade36a404000f4d5cebed5c28e28c57a539b7985b66aa4c014e0c59a43fde3a02201bd61f0a998301241d83fc9370654e0acda7cc6602258b954af6bf06605dffaf0121026e88bf2ad6aa4fdc21b2636583184a589fcddb3c1ed40b4e3613cf61601fad54feffffff01bc131600000000001976a9142f592f81575c361e91397dccc60772b9335f432588accfce0500f4ce050000
|
040000003893091e180992ed3ddbdca17b69bb32636fa24e139463cc3fcc390f72f00100152337b21d88dbabe7993aeda34e575edc0a10d8425ebf675ebc4a83b3ebc20c0d86a7943df2dc92fb8b131b0698db24dd01a12d19696c20443f5f639df3ab5a39dd295c4699181f1e007d867f82f93d39b4107a1265900058b7565dd1b2945241a4ef63bc690000fd4005004b556303cc38ed6fccb33b93a81c0f8f05dd0e8006d64e34868ac9fe5c22863eff3928f6f2831b502400bed03b98c17215ca8a50612273461d43f857d192154f4ad5db69f067aa48d19503523a2f0602fbccbc01bceeeeb256d5690efa33a583efbf397481afaa5745976f397bd7c0cd270674f2de48ded99778fb0da11068c770ac303637c1ecb1b53e6f1be4f89130a7b45a49edcf081959f37121190d42d668b6bd5c1d353609479c1a598c2c43dd0661c9d51222bda25437f3fd1e952aea271a02c0f19a92f4a11faa20ccef67046f1a4036f38b299e73692e61aa67d526f1b7251da0914ac33d1cddd7a4bfeefada21c8f38ceedc1557d0710bbba0f4932c839177bac34abcf402e168303ed8021dc449b3ca0940448bff3217c0bc2730b19190c6811c420629a1878f6e7021171e9359002e4bc636a5322b8056733e3299bdf0c0f4545aba5372ca4a5b337300f3e8c43e89819a563df0e385229405479e1c12a50b57cc1b8e8e2f8b1db9b3aeca20724244f21c2997270e316e37528f7f302d95d9a2b71d7f0319fb4afc4cb25ea17f1a6fc3b7fbf68d71b65139fbee9997c404c2c76611cbb97750d7e5aae23d2ac26de83ec81d2774caf7279e40737f7b1502a4e8ad15f88a7bcc660a148b1c8c68fe4d891514a7a0d7b6b9e9e4561cf510a9c10bdd586fa57a9683afc9db809d93777c435e0780404f5e05a91ab84d6a63abd77e33e1881f2e341c6a7cae0b8d0507dd6bab56ba688cef5910ff18a816a3bb38fa5c6307eea5221569cdc90cde855083b12e189c39cc9052c328d1e654a3ea11371a6f5ad6ad07d396227464e23b4ae1e1aa1956567e000558473a29f34c53dcd8d4b8d3df0410d8af663de3f177565409f30a2ee236d6edbffc355609b4a60643f6f7db0b30a111d9269d6df96d1d487a6ae2d672ce37fbe0ef02ef64ea5793778f67af238fe45ff15ad1609bdead8fe39d445b2644254cf0acc5effc84ff8786fcbd041b7d3a42085d5c2f1cea86f2817d9b1e21c252e6f02404c7699ed8c6c14b979371d1a726451599fe312b10653fa69fc6c132e30bc299af2e92f9fb4495229f1e49ce927fadcbb19ebee2cb5ceae56981201d7b73168997bde9b287abb25d86d43562839a0b30be80f02c4ee3d2021afb990364264e78cf5b07097dfe860a047191ece343378f63d88136a6509c511f4b785b48187e1bde4f8fcabec22451c19eb9af4a6b743c289426cbc2b508bd4bf9ebb382fe131928292ed0d5113f3e86c3dd8656638f4c0ee5b500ef57d19aaa4e00ab17dcf7950954d017f648aa09bbd5a87aab8c9f42a01c810bc93790ed6791d3a2462a571320bae636632b2d3d77611c6cdff96afff421a534df351910f3ffe92eaae18fc6d4a50908be160ffc5dca626d2777625205d07f18eae60d9fe1b9e32f56fd3e92f98a1aa5c728130249a24cb47556d2c40f2029b17217807e3b3a11afbf8d981df73122d61199854f2414b9ec3f687a2a021fec118b38e6756e67aec56eb726fcab9b69ae09d77d3b55559c10d8afd242836bab39f8a93d1a5f16ba0e0c76565a2731a467af0a490a8e3baa3b3bcd36fba75c7d5c3985355dc38f2ff73f9728903f02274126e39301b1ee8599ccb9fd9955696f08f79a035f09d9ac570225ad05666a2900b56c97cfaa985f3a5814c46ad2a5d998c7f18be2dc1e23c540cd208b3a11124de8965dd8b645746cf351544d0371cc798ec6552d329980050c2a04812f66219677507591470d9a5d103d011b901f2a234395f363a59cc8d18561f7807f1d26e0fe5d2bd38365c174b2886758eeccb73f958c1550df9016863c87aa5a94daabb03dc34208bd682854ebaebe90954ddfc2a4974a02566c15fc5976d38c010400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff0603e2ce050101ffffffff0200ca9a3b000000001976a9141fb09ecb821dd7ce9cc8ee1ed54df0d1863f824188ac80b2e60e0000000017a91466a04fe5f6f1b5bb1149e6cd0079167f570880148700000000000000000000000000000000000000
|
||||||
04000000c848f5a041f4406004243ecf645ef91f303f6766f5615e4cd2c7ab08000000002c46ffced042e210ec98759ee1bf5792b62c3a3c56f24667422350dcf3c84e070000000000000000000000000000000000000000000000000000000000000000d4cb7d5b7beb091cf18a4fa59e6d1400000000000000000000000000000000000000000038d0a613fd400500572cbab31dea47dc52529819b5b80cce7fa6ff4f0c1e8f09d50bee7b5012813826948828c3d5e6f14505a4f7ab54884cb7b8f1a49675b99f820d219567d72695fc14f74a26554ad3c346123852669bd29e50eb056cda5e176bd065ccbbf2663f3a12a11f7773a0847c09059fddb09a37908e1a8240f29dd6eaec78f92b1f67e2a1cd27c2b1d6f9c5c7d0c8545dedb6f949c93507838d4525606b73d176ed8ddfa2a20d93ba4d4303512f8fa4c96efcc084329bad15f9997edef03fc90edcd1e7f943c95b5c7123d66a4d0ec9012ab2578e1d9bbcb47bdf56e9eb72e3c82dcfb14ed9785c860522791bb3bde200f76db5e907555c27ef91489cc4410b4129e4aa08b800c00952b451cf3640c326b690e719d92cd2a87799d1dd63b36984c30a6582bdb1fc6d16b323c2ef33b23deaf2325763f8b1fe7b21dd7c801ffc7df2c4d68511aff3b2059e681bb1afaa19090d03592df27c452350d040718758902afcaee5fa48a00e9fffbd3ec4222973c2686fb3e7beee6c5ebe0ecc130b8981d00adfcd464832b625d7cd82adb99e02f71c4b3d9ec6ce5812cb5075cd70cffd967e73b9f08c04c97c728e02efa88b18f318423ce212fca69c05b743289eb18912bdbcde1bc5fb507286baccb1b8937438092c5418a86fe56bdf441637ac4a49e172f491f743a694bc0516e02ebb1e36ec3b4a460e5f45bf6d2c055924c396c9546f9839b696785fdc09f99ddc7e701a3f0f61b7cb90d6de292400b8423f45bdb6d11d921711cc0a5316d200c220f70e80cda935f6b911e34d1aed9769d40ab973a6aaf1bbbc33ecf57f60d93a490d5835583ca4b70de9218510784caaf2d28c1b3dfe1af1e47ea3c96ddd46e27343ea5b80d175c3ef69b5387d2bfae8d026c765d2f5ec7ec7dacdca63dfbae85974e5a57e636edd68754664b56b9421a009ed09d7007b72db75980945b9f8e0da56d03cdcd8cdb9ce8a6d21336a8ab946fdeb59472585584a85e59e31152f0a9e03da924877854e93d5f6fbcff21a4165bbc4b60c8a195bd46761499fe1a28eb464c0957203d337cd0781d1e385308017999260c8da0933ee3b751d3ce92015b3e67393dc98d883d70113d24f72c4b73a885f1cea47062e88aba3983f192c69dc10db68b95fb3e021363ba87ad938bf97077263a7aeca4f769dfd54370194582d31d7c632c60833fa9346814b26ce1d7c451d6fbd6c309de603780185f499b963a7310abc42450445a2f2840f25350d38f2140b3904fd636ff5016334e2c234d72eff0d8096588c71ffdcde3569b3914f02acbe1938957135acc6d10f2d5bf56885c177e6ca778f7ce431225fd535a15949fdfd2e8ab0c47fd8251e294c02cf98d91340afb5812950c46d9b8dadba902fc70ea73c2c26b5a4d0d59410da46018486d9ec5a0a9b89422190afb7e72b7150f97b359d70841170ae23bacf915f10a019c601f48017472dd2b7c7b89bf0128dfd4a01e450adf17071ded02a3ae13eb7f8fec54510955a305256b2be2d97994140f36222d5ba55ec0ea35749fc894289af4454e944c1dbb1d7d40f1e72276651c4e3542bfd9f145500d9295eab83c6fc92362875620cd0159b7b53ff530d66b25adde2187438045c5fc4b8bdaff93dfb65b85c71753846bfa91f6ac60c9db561423b6109feef932486ece2cdc3c539112318c79ecc7e08ddda73ce663c3d4e9b9a7c743955330f1ca702b8a5673f82328b5f637dfa3743bcbe07583bfecf731cab93abc8d4a5dbfcdbf3536db25f1fff0d71175b744d561eecd1a89fe0484d466d2c5a68d61abba2dd9e8786211482b2b50218eec505f94c67971242a67a93872681ac81e1f541ecbf95a8bd7f5d8c1e60d95a76138bab40da3455b5a36549920d7f4d0102030000807082c403010000000000000000000000000000000000000000000000000000000000000000ffffffff1a03e3ce05152f5669614254432f48656c6c6f20776f726c64212fffffffff0288f19a3b000000001976a914fb8a6a4c11cb216ce21f9f371dfc9271a469bd6d88ac80b2e60e0000000017a91414c884180589f6d0fdc7c400181afb1bb10c9fe487000000000000000000030000807082c403016f4029430669c709d041c579c8e9469446f1159064613e6cd47514691b93b8ff000000006a47304402204ff60fca23a36026d374850bc018e7c714de78d8560d4188fa247b1a4ee4dcee02206538b475265173915662465b4a8554a111003701371d553134047bf185c98ba20121029ba2dc5033c7c17f06274b85c0f8e51ad518f34235713ffee4705867162819fafeffffff0208672302000000001976a9140ed9a32475fa7214939a6705fd790a74976bab0388ac3e926c01000000001976a914d752bedc09529fb3719004407dd6b5f29000e3e688acd7ce0500f6ce050000
|
04000000d91995f491c208a7a8c1d358417120e91451158db34ab4ef30a1c026e2d6070094eda3d052afd42b6d45e541a1d97184636bb767ccbb7d8f91584693a80233250d86a7943df2dc92fb8b131b0698db24dd01a12d19696c20443f5f639df3ab5ab4dd295ca942181f1a0006ea1556b0c6c73177cd09700bb72e6b2457fed3174f1d69d4e6e3190000fd4005002f434e5adb994d86d3d45d4fc9584f3d70dba6ee34005bbd47169aa751d4c4d06bf9476a26cfb2fdc905c663c77186e370765413a5d0d25be15e4d50746c232c0fde2d09e01c5cf1e53b70db14c9d889fcd1ad128add562edc91339d81d1a4a78e3eed31d4d16d5b3209ae0571569d590114f68e85fd37b26b0c7724531d14a72bbacd02a309cf039521ce4d5537069326fd1fec07eda692ff09f941a8f8c0f543372ec8fa85c20416161dd719e3f4d3f0e663eeefc4da0feb31eace0e54f9df1fd5714aebb4d306636d0b61357e343e9c04c7f60402a9066bdf11b6817ced3f39e539ff98e4282b63ead466a6e15d5c85b76affa63a4e8e935f060a074f30cf9bcc89ef3872f80268ffb4cdc5aa67fb10b745e3b856fbb4b95d439fe8c8933b50eb5dc0091ec9c41c5ddc998b477c5302c0aede64eecf70b35c1f7d7983e1e052039dea18529752ea7e5ae67f4f51009908fd530968726e0fc9dd79d71022d2eb5749f1055e96fa98b35b79e7e32a92de750036c29bbaf38c0d30587b1f87653bcbb979142b658396d4cb7c2496566154d160ba44dbe97165f909c0c5c2e99077bb71041313603d852e22f0c560ab1f0738ddf74f105aa13e26ad8baa139f98f29ed71b85c80085f324f7db0b0a6e9e1d4584af6c592483254378654903adf6b4b70b77be24e817b053ac55016f29ac78a218095509e902936166f7923ceaabda692442ce1da6fd8e3a6b860cf8ecf7770ad2d77afbb0d15de5fc6084ff491a370baeb547171415e1be7f38e5edcc1283bc573f5522286f3d92208d568896dcf51c1566cdb583f1f0d87902e8fc27c6d1c43b1b3bb051cf568e426b551608cc1d27aa72fc9ff34f2479e609a8fc68a6899598f2d713065789f95983f78a3b746798bb19a989381ae0a531178d735c11e1cfa856b40d05b1f959115608e66800e95c067be6ebbd6ac008193ced38e24bc6db67a210d9a6ed0eddbbcdfb0f8439ab66cd4e27ca32f01a095212f36cd6b1c13c17c4ad3327c255b770dc66e03c797b1d39177365c08af59e723825596f024c7dba0a6a71657f84ab7ef5b345c11ad19191bd25d725cd1660d4e0e793c453bf9aac0494f4942f75481f577d0fe5860ffe6c776fbbb801bc6794c11c9d81ec91d32a2e162c69651c8deb52d2bd4bcdf9e0f18254549c041230266cadaf43cb09f113967492286faa3ce2c50a261ec8e847956ddce763e1df446b4164f2594bc40a1c6a756a451022381fd618bb432b9dbfbcb92d79865e3e9beee8a7277359188b6ef0956b59b47e023c06cd3f99c002fed0fb9a7cb63578a4ab4be39d24981caf13d1d4d580e4d48183aca7ae8a3230011b83d1097b33d5b7a3cf89f61d6702f5ec79e66fcd93e5bd4a5183189fae5123cb56791bcf64b9425e473cfdd2073b30e551703823d848e4adcf32673270b7d4b91511b38efd3a60937f2b90c7accaf7102e0b3c5e12c907b62acf098fe2abe7d073f4a4ba248623757adcd12f27ec2cedb749c7e280452b7f2cc085beceb495040cdb00ef434bc9ab78f8b0f79e8bb90cfaf7f8577743dd5a96c8264aa9b19ca5b7e46ed1a74b3d3fa1f02eb0164b62297b61e6bd951bea4562fdf8b3355ea95ad9a72ad0a35affe08f683bf77f781212cb53f9130b672e7e6a5ed3b31bf0a1089f2e694ed7875b9b5d11bc2c6ce1db7dc770d3b6a4e872a572285bfaff5c1f7a2202d8891b3ee2f6bbe4bd633ab700815c6ed9229e19b49856d72da66f865b9bcda32e5af81fd54c122c79ca1fd7a666ea4ef38b5a668b9532e675d8c0561aeba9c5f29a8f9cfc66918bda81e63ecf792705298699e526a10d4bdcc293e93b21513b8cb7dd486030145c81942a84038001873665f93d8ef80bf942f0020400008085202f89010000000000000000000000000000000000000000000000000000000000000000ffffffff0603e3ce050104ffffffff0208d99a3b000000001976a9142943b34e1bbdefc6f6a5c501264404eac228ba5b88ac80b2e60e0000000017a91466a04fe5f6f1b5bb1149e6cd0079167f5708801487000000000000000000000000000000000000000400008085202f8901bd114c7474dc9bddc943f99e3cd8af97332b4c899fbdebc44f105fe6b760bf41010000006b483045022100b73c1baacf61e8b4bd915ee1c007a51366a7cc718c5469de9f035aec7f92fdda0220595ad4cadd2617be7ce65ca5aa10b6d86ae27fb86c960686d7e1c668469afe12012103f9e72f0713a4d4a980309a14a2ba563e0b1125ad067818e77553a1eefbfc5be7ffffffff02f0ba0400000000001976a914d78f41784821c3d9929fa56e85267eae0bb09ffd88ac486e1500000000001976a9144faeeb51bcd0b49f238b323e5f1c6c8bf11ae02a88ac00000000e6ce05000000000000000000000000
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -744,9 +744,6 @@ func (d decoder) skipValue() error {
|
||||||
// Skip items. This will not validate whether skipped values are
|
// Skip items. This will not validate whether skipped values are
|
||||||
// of the same type or not, same behavior as C++
|
// of the same type or not, same behavior as C++
|
||||||
// TextFormat::Parser::AllowUnknownField(true) version 3.8.0.
|
// TextFormat::Parser::AllowUnknownField(true) version 3.8.0.
|
||||||
if err := d.skipValue(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,3 +263,8 @@ func (e *Encoder) Snapshot() encoderState {
|
||||||
func (e *Encoder) Reset(es encoderState) {
|
func (e *Encoder) Reset(es encoderState) {
|
||||||
e.encoderState = es
|
e.encoderState = es
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// AppendString appends the escaped form of the input string to b.
|
||||||
|
func AppendString(b []byte, s string) []byte {
|
||||||
|
return appendString(b, s, false)
|
||||||
|
}
|
||||||
|
|
|
@ -440,6 +440,13 @@ func legacyMerge(in piface.MergeInput) piface.MergeOutput {
|
||||||
if !ok {
|
if !ok {
|
||||||
return piface.MergeOutput{}
|
return piface.MergeOutput{}
|
||||||
}
|
}
|
||||||
|
if !in.Source.IsValid() {
|
||||||
|
// Legacy Marshal methods may not function on nil messages.
|
||||||
|
// Check for a typed nil source only after we confirm that
|
||||||
|
// legacy Marshal/Unmarshal methods are present, for
|
||||||
|
// consistency.
|
||||||
|
return piface.MergeOutput{Flags: piface.MergeComplete}
|
||||||
|
}
|
||||||
b, err := marshaler.Marshal()
|
b, err := marshaler.Marshal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return piface.MergeOutput{}
|
return piface.MergeOutput{}
|
||||||
|
|
|
@ -52,8 +52,8 @@ import (
|
||||||
// 10. Send out the CL for review and submit it.
|
// 10. Send out the CL for review and submit it.
|
||||||
const (
|
const (
|
||||||
Major = 1
|
Major = 1
|
||||||
Minor = 26
|
Minor = 27
|
||||||
Patch = 0
|
Patch = 1
|
||||||
PreRelease = ""
|
PreRelease = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -94,7 +94,8 @@ type Files struct {
|
||||||
// Note that enum values are in the top-level since that are in the same
|
// Note that enum values are in the top-level since that are in the same
|
||||||
// scope as the parent enum.
|
// scope as the parent enum.
|
||||||
descsByName map[protoreflect.FullName]interface{}
|
descsByName map[protoreflect.FullName]interface{}
|
||||||
filesByPath map[string]protoreflect.FileDescriptor
|
filesByPath map[string][]protoreflect.FileDescriptor
|
||||||
|
numFiles int
|
||||||
}
|
}
|
||||||
|
|
||||||
type packageDescriptor struct {
|
type packageDescriptor struct {
|
||||||
|
@ -117,17 +118,16 @@ func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error {
|
||||||
r.descsByName = map[protoreflect.FullName]interface{}{
|
r.descsByName = map[protoreflect.FullName]interface{}{
|
||||||
"": &packageDescriptor{},
|
"": &packageDescriptor{},
|
||||||
}
|
}
|
||||||
r.filesByPath = make(map[string]protoreflect.FileDescriptor)
|
r.filesByPath = make(map[string][]protoreflect.FileDescriptor)
|
||||||
}
|
}
|
||||||
path := file.Path()
|
path := file.Path()
|
||||||
if prev := r.filesByPath[path]; prev != nil {
|
if prev := r.filesByPath[path]; len(prev) > 0 {
|
||||||
r.checkGenProtoConflict(path)
|
r.checkGenProtoConflict(path)
|
||||||
err := errors.New("file %q is already registered", file.Path())
|
err := errors.New("file %q is already registered", file.Path())
|
||||||
err = amendErrorWithCaller(err, prev, file)
|
err = amendErrorWithCaller(err, prev[0], file)
|
||||||
if r == GlobalFiles && ignoreConflict(file, err) {
|
if !(r == GlobalFiles && ignoreConflict(file, err)) {
|
||||||
err = nil
|
return err
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for name := file.Package(); name != ""; name = name.Parent() {
|
for name := file.Package(); name != ""; name = name.Parent() {
|
||||||
|
@ -168,7 +168,8 @@ func (r *Files) RegisterFile(file protoreflect.FileDescriptor) error {
|
||||||
rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) {
|
rangeTopLevelDescriptors(file, func(d protoreflect.Descriptor) {
|
||||||
r.descsByName[d.FullName()] = d
|
r.descsByName[d.FullName()] = d
|
||||||
})
|
})
|
||||||
r.filesByPath[path] = file
|
r.filesByPath[path] = append(r.filesByPath[path], file)
|
||||||
|
r.numFiles++
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +309,7 @@ func (s *nameSuffix) Pop() (name protoreflect.Name) {
|
||||||
// FindFileByPath looks up a file by the path.
|
// FindFileByPath looks up a file by the path.
|
||||||
//
|
//
|
||||||
// This returns (nil, NotFound) if not found.
|
// This returns (nil, NotFound) if not found.
|
||||||
|
// This returns an error if multiple files have the same path.
|
||||||
func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
|
func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error) {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return nil, NotFound
|
return nil, NotFound
|
||||||
|
@ -316,13 +318,19 @@ func (r *Files) FindFileByPath(path string) (protoreflect.FileDescriptor, error)
|
||||||
globalMutex.RLock()
|
globalMutex.RLock()
|
||||||
defer globalMutex.RUnlock()
|
defer globalMutex.RUnlock()
|
||||||
}
|
}
|
||||||
if fd, ok := r.filesByPath[path]; ok {
|
fds := r.filesByPath[path]
|
||||||
return fd, nil
|
switch len(fds) {
|
||||||
|
case 0:
|
||||||
|
return nil, NotFound
|
||||||
|
case 1:
|
||||||
|
return fds[0], nil
|
||||||
|
default:
|
||||||
|
return nil, errors.New("multiple files named %q", path)
|
||||||
}
|
}
|
||||||
return nil, NotFound
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumFiles reports the number of registered files.
|
// NumFiles reports the number of registered files,
|
||||||
|
// including duplicate files with the same name.
|
||||||
func (r *Files) NumFiles() int {
|
func (r *Files) NumFiles() int {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
return 0
|
return 0
|
||||||
|
@ -331,10 +339,11 @@ func (r *Files) NumFiles() int {
|
||||||
globalMutex.RLock()
|
globalMutex.RLock()
|
||||||
defer globalMutex.RUnlock()
|
defer globalMutex.RUnlock()
|
||||||
}
|
}
|
||||||
return len(r.filesByPath)
|
return r.numFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
// RangeFiles iterates over all registered files while f returns true.
|
// RangeFiles iterates over all registered files while f returns true.
|
||||||
|
// If multiple files have the same name, RangeFiles iterates over all of them.
|
||||||
// The iteration order is undefined.
|
// The iteration order is undefined.
|
||||||
func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) {
|
func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) {
|
||||||
if r == nil {
|
if r == nil {
|
||||||
|
@ -344,9 +353,11 @@ func (r *Files) RangeFiles(f func(protoreflect.FileDescriptor) bool) {
|
||||||
globalMutex.RLock()
|
globalMutex.RLock()
|
||||||
defer globalMutex.RUnlock()
|
defer globalMutex.RUnlock()
|
||||||
}
|
}
|
||||||
for _, file := range r.filesByPath {
|
for _, files := range r.filesByPath {
|
||||||
if !f(file) {
|
for _, file := range files {
|
||||||
return
|
if !f(file) {
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,7 +43,6 @@ package descriptorpb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||||
protoiface "google.golang.org/protobuf/runtime/protoiface"
|
|
||||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||||
reflect "reflect"
|
reflect "reflect"
|
||||||
sync "sync"
|
sync "sync"
|
||||||
|
@ -829,15 +828,6 @@ func (*ExtensionRangeOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{3}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_ExtensionRangeOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use ExtensionRangeOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*ExtensionRangeOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_ExtensionRangeOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption {
|
func (x *ExtensionRangeOptions) GetUninterpretedOption() []*UninterpretedOption {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.UninterpretedOption
|
return x.UninterpretedOption
|
||||||
|
@ -1520,15 +1510,6 @@ func (*FileOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{10}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{10}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_FileOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use FileOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*FileOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_FileOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *FileOptions) GetJavaPackage() string {
|
func (x *FileOptions) GetJavaPackage() string {
|
||||||
if x != nil && x.JavaPackage != nil {
|
if x != nil && x.JavaPackage != nil {
|
||||||
return *x.JavaPackage
|
return *x.JavaPackage
|
||||||
|
@ -1776,15 +1757,6 @@ func (*MessageOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{11}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{11}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_MessageOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use MessageOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*MessageOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_MessageOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *MessageOptions) GetMessageSetWireFormat() bool {
|
func (x *MessageOptions) GetMessageSetWireFormat() bool {
|
||||||
if x != nil && x.MessageSetWireFormat != nil {
|
if x != nil && x.MessageSetWireFormat != nil {
|
||||||
return *x.MessageSetWireFormat
|
return *x.MessageSetWireFormat
|
||||||
|
@ -1930,15 +1902,6 @@ func (*FieldOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{12}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_FieldOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use FieldOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*FieldOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_FieldOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *FieldOptions) GetCtype() FieldOptions_CType {
|
func (x *FieldOptions) GetCtype() FieldOptions_CType {
|
||||||
if x != nil && x.Ctype != nil {
|
if x != nil && x.Ctype != nil {
|
||||||
return *x.Ctype
|
return *x.Ctype
|
||||||
|
@ -2030,15 +1993,6 @@ func (*OneofOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{13}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{13}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_OneofOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use OneofOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*OneofOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_OneofOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *OneofOptions) GetUninterpretedOption() []*UninterpretedOption {
|
func (x *OneofOptions) GetUninterpretedOption() []*UninterpretedOption {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.UninterpretedOption
|
return x.UninterpretedOption
|
||||||
|
@ -2101,15 +2055,6 @@ func (*EnumOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{14}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{14}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_EnumOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use EnumOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*EnumOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_EnumOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *EnumOptions) GetAllowAlias() bool {
|
func (x *EnumOptions) GetAllowAlias() bool {
|
||||||
if x != nil && x.AllowAlias != nil {
|
if x != nil && x.AllowAlias != nil {
|
||||||
return *x.AllowAlias
|
return *x.AllowAlias
|
||||||
|
@ -2183,15 +2128,6 @@ func (*EnumValueOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{15}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{15}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_EnumValueOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use EnumValueOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*EnumValueOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_EnumValueOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *EnumValueOptions) GetDeprecated() bool {
|
func (x *EnumValueOptions) GetDeprecated() bool {
|
||||||
if x != nil && x.Deprecated != nil {
|
if x != nil && x.Deprecated != nil {
|
||||||
return *x.Deprecated
|
return *x.Deprecated
|
||||||
|
@ -2258,15 +2194,6 @@ func (*ServiceOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{16}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{16}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_ServiceOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use ServiceOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*ServiceOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_ServiceOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *ServiceOptions) GetDeprecated() bool {
|
func (x *ServiceOptions) GetDeprecated() bool {
|
||||||
if x != nil && x.Deprecated != nil {
|
if x != nil && x.Deprecated != nil {
|
||||||
return *x.Deprecated
|
return *x.Deprecated
|
||||||
|
@ -2335,15 +2262,6 @@ func (*MethodOptions) Descriptor() ([]byte, []int) {
|
||||||
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{17}
|
return file_google_protobuf_descriptor_proto_rawDescGZIP(), []int{17}
|
||||||
}
|
}
|
||||||
|
|
||||||
var extRange_MethodOptions = []protoiface.ExtensionRangeV1{
|
|
||||||
{Start: 1000, End: 536870911},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use MethodOptions.ProtoReflect.Descriptor.ExtensionRanges instead.
|
|
||||||
func (*MethodOptions) ExtensionRangeArray() []protoiface.ExtensionRangeV1 {
|
|
||||||
return extRange_MethodOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *MethodOptions) GetDeprecated() bool {
|
func (x *MethodOptions) GetDeprecated() bool {
|
||||||
if x != nil && x.Deprecated != nil {
|
if x != nil && x.Deprecated != nil {
|
||||||
return *x.Deprecated
|
return *x.Deprecated
|
||||||
|
|
|
@ -156,7 +156,7 @@ google.golang.org/grpc/serviceconfig
|
||||||
google.golang.org/grpc/stats
|
google.golang.org/grpc/stats
|
||||||
google.golang.org/grpc/status
|
google.golang.org/grpc/status
|
||||||
google.golang.org/grpc/tap
|
google.golang.org/grpc/tap
|
||||||
# google.golang.org/protobuf v1.26.0
|
# google.golang.org/protobuf v1.27.1
|
||||||
google.golang.org/protobuf/encoding/prototext
|
google.golang.org/protobuf/encoding/prototext
|
||||||
google.golang.org/protobuf/encoding/protowire
|
google.golang.org/protobuf/encoding/protowire
|
||||||
google.golang.org/protobuf/internal/descfmt
|
google.golang.org/protobuf/internal/descfmt
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.28.0
|
||||||
// protoc v3.6.1
|
// protoc v3.6.1
|
||||||
// source: compact_formats.proto
|
// source: compact_formats.proto
|
||||||
|
|
||||||
|
@ -138,9 +138,10 @@ type CompactTx struct {
|
||||||
// unset because the calculation requires reference to prior transactions.
|
// unset because the calculation requires reference to prior transactions.
|
||||||
// in a pure-Sapling context, the fee will be calculable as:
|
// in a pure-Sapling context, the fee will be calculable as:
|
||||||
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
|
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
|
||||||
Fee uint32 `protobuf:"varint,3,opt,name=fee,proto3" json:"fee,omitempty"`
|
Fee uint32 `protobuf:"varint,3,opt,name=fee,proto3" json:"fee,omitempty"`
|
||||||
Spends []*CompactSpend `protobuf:"bytes,4,rep,name=spends,proto3" json:"spends,omitempty"` // inputs
|
Spends []*CompactSaplingSpend `protobuf:"bytes,4,rep,name=spends,proto3" json:"spends,omitempty"` // inputs
|
||||||
Outputs []*CompactOutput `protobuf:"bytes,5,rep,name=outputs,proto3" json:"outputs,omitempty"` // outputs
|
Outputs []*CompactSaplingOutput `protobuf:"bytes,5,rep,name=outputs,proto3" json:"outputs,omitempty"` // outputs
|
||||||
|
Actions []*CompactOrchardAction `protobuf:"bytes,6,rep,name=actions,proto3" json:"actions,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactTx) Reset() {
|
func (x *CompactTx) Reset() {
|
||||||
|
@ -196,23 +197,30 @@ func (x *CompactTx) GetFee() uint32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactTx) GetSpends() []*CompactSpend {
|
func (x *CompactTx) GetSpends() []*CompactSaplingSpend {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Spends
|
return x.Spends
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactTx) GetOutputs() []*CompactOutput {
|
func (x *CompactTx) GetOutputs() []*CompactSaplingOutput {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Outputs
|
return x.Outputs
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompactSpend is a Sapling Spend Description as described in 7.3 of the Zcash
|
func (x *CompactTx) GetActions() []*CompactOrchardAction {
|
||||||
|
if x != nil {
|
||||||
|
return x.Actions
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash
|
||||||
// protocol specification.
|
// protocol specification.
|
||||||
type CompactSpend struct {
|
type CompactSaplingSpend struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
@ -220,8 +228,8 @@ type CompactSpend struct {
|
||||||
Nf []byte `protobuf:"bytes,1,opt,name=nf,proto3" json:"nf,omitempty"` // nullifier (see the Zcash protocol specification)
|
Nf []byte `protobuf:"bytes,1,opt,name=nf,proto3" json:"nf,omitempty"` // nullifier (see the Zcash protocol specification)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactSpend) Reset() {
|
func (x *CompactSaplingSpend) Reset() {
|
||||||
*x = CompactSpend{}
|
*x = CompactSaplingSpend{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_compact_formats_proto_msgTypes[2]
|
mi := &file_compact_formats_proto_msgTypes[2]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
@ -229,13 +237,13 @@ func (x *CompactSpend) Reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactSpend) String() string {
|
func (x *CompactSaplingSpend) String() string {
|
||||||
return protoimpl.X.MessageStringOf(x)
|
return protoimpl.X.MessageStringOf(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*CompactSpend) ProtoMessage() {}
|
func (*CompactSaplingSpend) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CompactSpend) ProtoReflect() protoreflect.Message {
|
func (x *CompactSaplingSpend) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_compact_formats_proto_msgTypes[2]
|
mi := &file_compact_formats_proto_msgTypes[2]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
@ -247,12 +255,12 @@ func (x *CompactSpend) ProtoReflect() protoreflect.Message {
|
||||||
return mi.MessageOf(x)
|
return mi.MessageOf(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use CompactSpend.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CompactSaplingSpend.ProtoReflect.Descriptor instead.
|
||||||
func (*CompactSpend) Descriptor() ([]byte, []int) {
|
func (*CompactSaplingSpend) Descriptor() ([]byte, []int) {
|
||||||
return file_compact_formats_proto_rawDescGZIP(), []int{2}
|
return file_compact_formats_proto_rawDescGZIP(), []int{2}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactSpend) GetNf() []byte {
|
func (x *CompactSaplingSpend) GetNf() []byte {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Nf
|
return x.Nf
|
||||||
}
|
}
|
||||||
|
@ -261,18 +269,18 @@ func (x *CompactSpend) GetNf() []byte {
|
||||||
|
|
||||||
// output is a Sapling Output Description as described in section 7.4 of the
|
// output is a Sapling Output Description as described in section 7.4 of the
|
||||||
// Zcash protocol spec. Total size is 948.
|
// Zcash protocol spec. Total size is 948.
|
||||||
type CompactOutput struct {
|
type CompactSaplingOutput struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Cmu []byte `protobuf:"bytes,1,opt,name=cmu,proto3" json:"cmu,omitempty"` // note commitment u-coordinate
|
Cmu []byte `protobuf:"bytes,1,opt,name=cmu,proto3" json:"cmu,omitempty"` // note commitment u-coordinate
|
||||||
Epk []byte `protobuf:"bytes,2,opt,name=epk,proto3" json:"epk,omitempty"` // ephemeral public key
|
Epk []byte `protobuf:"bytes,2,opt,name=epk,proto3" json:"epk,omitempty"` // ephemeral public key
|
||||||
Ciphertext []byte `protobuf:"bytes,3,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` // ciphertext and zkproof
|
Ciphertext []byte `protobuf:"bytes,3,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` // first 52 bytes of ciphertext
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactOutput) Reset() {
|
func (x *CompactSaplingOutput) Reset() {
|
||||||
*x = CompactOutput{}
|
*x = CompactSaplingOutput{}
|
||||||
if protoimpl.UnsafeEnabled {
|
if protoimpl.UnsafeEnabled {
|
||||||
mi := &file_compact_formats_proto_msgTypes[3]
|
mi := &file_compact_formats_proto_msgTypes[3]
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
@ -280,13 +288,13 @@ func (x *CompactOutput) Reset() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactOutput) String() string {
|
func (x *CompactSaplingOutput) String() string {
|
||||||
return protoimpl.X.MessageStringOf(x)
|
return protoimpl.X.MessageStringOf(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*CompactOutput) ProtoMessage() {}
|
func (*CompactSaplingOutput) ProtoMessage() {}
|
||||||
|
|
||||||
func (x *CompactOutput) ProtoReflect() protoreflect.Message {
|
func (x *CompactSaplingOutput) ProtoReflect() protoreflect.Message {
|
||||||
mi := &file_compact_formats_proto_msgTypes[3]
|
mi := &file_compact_formats_proto_msgTypes[3]
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
if protoimpl.UnsafeEnabled && x != nil {
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
@ -298,26 +306,99 @@ func (x *CompactOutput) ProtoReflect() protoreflect.Message {
|
||||||
return mi.MessageOf(x)
|
return mi.MessageOf(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use CompactOutput.ProtoReflect.Descriptor instead.
|
// Deprecated: Use CompactSaplingOutput.ProtoReflect.Descriptor instead.
|
||||||
func (*CompactOutput) Descriptor() ([]byte, []int) {
|
func (*CompactSaplingOutput) Descriptor() ([]byte, []int) {
|
||||||
return file_compact_formats_proto_rawDescGZIP(), []int{3}
|
return file_compact_formats_proto_rawDescGZIP(), []int{3}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactOutput) GetCmu() []byte {
|
func (x *CompactSaplingOutput) GetCmu() []byte {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Cmu
|
return x.Cmu
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactOutput) GetEpk() []byte {
|
func (x *CompactSaplingOutput) GetEpk() []byte {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Epk
|
return x.Epk
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CompactOutput) GetCiphertext() []byte {
|
func (x *CompactSaplingOutput) GetCiphertext() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Ciphertext
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/zcash/zips/blob/main/zip-0225.rst#orchard-action-description-orchardaction
|
||||||
|
// (but not all fields are needed)
|
||||||
|
type CompactOrchardAction struct {
|
||||||
|
state protoimpl.MessageState
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
|
Nullifier []byte `protobuf:"bytes,1,opt,name=nullifier,proto3" json:"nullifier,omitempty"` // [32] The nullifier of the input note
|
||||||
|
Cmx []byte `protobuf:"bytes,2,opt,name=cmx,proto3" json:"cmx,omitempty"` // [32] The x-coordinate of the note commitment for the output note
|
||||||
|
EphemeralKey []byte `protobuf:"bytes,3,opt,name=ephemeralKey,proto3" json:"ephemeralKey,omitempty"` // [32] An encoding of an ephemeral Pallas public key
|
||||||
|
Ciphertext []byte `protobuf:"bytes,4,opt,name=ciphertext,proto3" json:"ciphertext,omitempty"` // [52] The note plaintext component of the encCiphertext field
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CompactOrchardAction) Reset() {
|
||||||
|
*x = CompactOrchardAction{}
|
||||||
|
if protoimpl.UnsafeEnabled {
|
||||||
|
mi := &file_compact_formats_proto_msgTypes[4]
|
||||||
|
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||||
|
ms.StoreMessageInfo(mi)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CompactOrchardAction) String() string {
|
||||||
|
return protoimpl.X.MessageStringOf(x)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*CompactOrchardAction) ProtoMessage() {}
|
||||||
|
|
||||||
|
func (x *CompactOrchardAction) ProtoReflect() protoreflect.Message {
|
||||||
|
mi := &file_compact_formats_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 CompactOrchardAction.ProtoReflect.Descriptor instead.
|
||||||
|
func (*CompactOrchardAction) Descriptor() ([]byte, []int) {
|
||||||
|
return file_compact_formats_proto_rawDescGZIP(), []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CompactOrchardAction) GetNullifier() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Nullifier
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CompactOrchardAction) GetCmx() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.Cmx
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CompactOrchardAction) GetEphemeralKey() []byte {
|
||||||
|
if x != nil {
|
||||||
|
return x.EphemeralKey
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *CompactOrchardAction) GetCiphertext() []byte {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Ciphertext
|
return x.Ciphertext
|
||||||
}
|
}
|
||||||
|
@ -343,26 +424,41 @@ var file_compact_formats_proto_rawDesc = []byte{
|
||||||
0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x03, 0x76, 0x74, 0x78, 0x18, 0x07,
|
0x06, 0x68, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x32, 0x0a, 0x03, 0x76, 0x74, 0x78, 0x18, 0x07,
|
||||||
0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61,
|
0x20, 0x03, 0x28, 0x0b, 0x32, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61,
|
||||||
0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d,
|
0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d,
|
||||||
0x70, 0x61, 0x63, 0x74, 0x54, 0x78, 0x52, 0x03, 0x76, 0x74, 0x78, 0x22, 0xc4, 0x01, 0x0a, 0x09,
|
0x70, 0x61, 0x63, 0x74, 0x54, 0x78, 0x52, 0x03, 0x76, 0x74, 0x78, 0x22, 0x99, 0x02, 0x0a, 0x09,
|
||||||
0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x54, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64,
|
0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x54, 0x78, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x64,
|
||||||
0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12,
|
0x65, 0x78, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x12,
|
||||||
0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68,
|
0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68,
|
||||||
0x61, 0x73, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
|
0x61, 0x73, 0x68, 0x12, 0x10, 0x0a, 0x03, 0x66, 0x65, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d,
|
||||||
0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x3b, 0x0a, 0x06, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x73, 0x18,
|
0x52, 0x03, 0x66, 0x65, 0x65, 0x12, 0x42, 0x0a, 0x06, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x73, 0x18,
|
||||||
0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77,
|
0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77,
|
||||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f,
|
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f,
|
||||||
0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x52, 0x06, 0x73, 0x70, 0x65, 0x6e,
|
0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x61, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x70, 0x65, 0x6e,
|
||||||
0x64, 0x73, 0x12, 0x3e, 0x0a, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73, 0x18, 0x05, 0x20,
|
0x64, 0x52, 0x06, 0x73, 0x70, 0x65, 0x6e, 0x64, 0x73, 0x12, 0x45, 0x0a, 0x07, 0x6f, 0x75, 0x74,
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
0x70, 0x75, 0x74, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x61, 0x73,
|
||||||
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70,
|
0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72,
|
||||||
0x61, 0x63, 0x74, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75,
|
0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x61, 0x70, 0x6c, 0x69, 0x6e,
|
||||||
0x74, 0x73, 0x22, 0x1e, 0x0a, 0x0c, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x70, 0x65,
|
0x67, 0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x52, 0x07, 0x6f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x73,
|
||||||
0x6e, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x6e, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02,
|
0x12, 0x45, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28,
|
||||||
0x6e, 0x66, 0x22, 0x53, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x4f, 0x75, 0x74,
|
0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65,
|
||||||
0x70, 0x75, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x75, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
|
0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63,
|
||||||
0x52, 0x03, 0x63, 0x6d, 0x75, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x70, 0x6b, 0x18, 0x02, 0x20, 0x01,
|
0x74, 0x4f, 0x72, 0x63, 0x68, 0x61, 0x72, 0x64, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07,
|
||||||
0x28, 0x0c, 0x52, 0x03, 0x65, 0x70, 0x6b, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65,
|
0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x25, 0x0a, 0x13, 0x43, 0x6f, 0x6d, 0x70, 0x61,
|
||||||
0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70,
|
0x63, 0x74, 0x53, 0x61, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x53, 0x70, 0x65, 0x6e, 0x64, 0x12, 0x0e,
|
||||||
|
0x0a, 0x02, 0x6e, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x02, 0x6e, 0x66, 0x22, 0x5a,
|
||||||
|
0x0a, 0x14, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x53, 0x61, 0x70, 0x6c, 0x69, 0x6e, 0x67,
|
||||||
|
0x4f, 0x75, 0x74, 0x70, 0x75, 0x74, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x75, 0x18, 0x01, 0x20,
|
||||||
|
0x01, 0x28, 0x0c, 0x52, 0x03, 0x63, 0x6d, 0x75, 0x12, 0x10, 0x0a, 0x03, 0x65, 0x70, 0x6b, 0x18,
|
||||||
|
0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03, 0x65, 0x70, 0x6b, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69,
|
||||||
|
0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a,
|
||||||
|
0x63, 0x69, 0x70, 0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x22, 0x8a, 0x01, 0x0a, 0x14, 0x43,
|
||||||
|
0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x4f, 0x72, 0x63, 0x68, 0x61, 0x72, 0x64, 0x41, 0x63, 0x74,
|
||||||
|
0x69, 0x6f, 0x6e, 0x12, 0x1c, 0x0a, 0x09, 0x6e, 0x75, 0x6c, 0x6c, 0x69, 0x66, 0x69, 0x65, 0x72,
|
||||||
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x6e, 0x75, 0x6c, 0x6c, 0x69, 0x66, 0x69, 0x65,
|
||||||
|
0x72, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x03,
|
||||||
|
0x63, 0x6d, 0x78, 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x70, 0x68, 0x65, 0x6d, 0x65, 0x72, 0x61, 0x6c,
|
||||||
|
0x4b, 0x65, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0c, 0x65, 0x70, 0x68, 0x65, 0x6d,
|
||||||
|
0x65, 0x72, 0x61, 0x6c, 0x4b, 0x65, 0x79, 0x12, 0x1e, 0x0a, 0x0a, 0x63, 0x69, 0x70, 0x68, 0x65,
|
||||||
|
0x72, 0x74, 0x65, 0x78, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x69, 0x70,
|
||||||
0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x42, 0x1b, 0x5a, 0x16, 0x6c, 0x69, 0x67, 0x68, 0x74,
|
0x68, 0x65, 0x72, 0x74, 0x65, 0x78, 0x74, 0x42, 0x1b, 0x5a, 0x16, 0x6c, 0x69, 0x67, 0x68, 0x74,
|
||||||
0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70,
|
0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72, 0x70,
|
||||||
0x63, 0xba, 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x63, 0xba, 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
|
@ -380,22 +476,24 @@ func file_compact_formats_proto_rawDescGZIP() []byte {
|
||||||
return file_compact_formats_proto_rawDescData
|
return file_compact_formats_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_compact_formats_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
var file_compact_formats_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
var file_compact_formats_proto_goTypes = []interface{}{
|
var file_compact_formats_proto_goTypes = []interface{}{
|
||||||
(*CompactBlock)(nil), // 0: cash.z.wallet.sdk.rpc.CompactBlock
|
(*CompactBlock)(nil), // 0: cash.z.wallet.sdk.rpc.CompactBlock
|
||||||
(*CompactTx)(nil), // 1: cash.z.wallet.sdk.rpc.CompactTx
|
(*CompactTx)(nil), // 1: cash.z.wallet.sdk.rpc.CompactTx
|
||||||
(*CompactSpend)(nil), // 2: cash.z.wallet.sdk.rpc.CompactSpend
|
(*CompactSaplingSpend)(nil), // 2: cash.z.wallet.sdk.rpc.CompactSaplingSpend
|
||||||
(*CompactOutput)(nil), // 3: cash.z.wallet.sdk.rpc.CompactOutput
|
(*CompactSaplingOutput)(nil), // 3: cash.z.wallet.sdk.rpc.CompactSaplingOutput
|
||||||
|
(*CompactOrchardAction)(nil), // 4: cash.z.wallet.sdk.rpc.CompactOrchardAction
|
||||||
}
|
}
|
||||||
var file_compact_formats_proto_depIdxs = []int32{
|
var file_compact_formats_proto_depIdxs = []int32{
|
||||||
1, // 0: cash.z.wallet.sdk.rpc.CompactBlock.vtx:type_name -> cash.z.wallet.sdk.rpc.CompactTx
|
1, // 0: cash.z.wallet.sdk.rpc.CompactBlock.vtx:type_name -> cash.z.wallet.sdk.rpc.CompactTx
|
||||||
2, // 1: cash.z.wallet.sdk.rpc.CompactTx.spends:type_name -> cash.z.wallet.sdk.rpc.CompactSpend
|
2, // 1: cash.z.wallet.sdk.rpc.CompactTx.spends:type_name -> cash.z.wallet.sdk.rpc.CompactSaplingSpend
|
||||||
3, // 2: cash.z.wallet.sdk.rpc.CompactTx.outputs:type_name -> cash.z.wallet.sdk.rpc.CompactOutput
|
3, // 2: cash.z.wallet.sdk.rpc.CompactTx.outputs:type_name -> cash.z.wallet.sdk.rpc.CompactSaplingOutput
|
||||||
3, // [3:3] is the sub-list for method output_type
|
4, // 3: cash.z.wallet.sdk.rpc.CompactTx.actions:type_name -> cash.z.wallet.sdk.rpc.CompactOrchardAction
|
||||||
3, // [3:3] is the sub-list for method input_type
|
4, // [4:4] is the sub-list for method output_type
|
||||||
3, // [3:3] is the sub-list for extension type_name
|
4, // [4:4] is the sub-list for method input_type
|
||||||
3, // [3:3] is the sub-list for extension extendee
|
4, // [4:4] is the sub-list for extension type_name
|
||||||
0, // [0:3] is the sub-list for field type_name
|
4, // [4:4] is the sub-list for extension extendee
|
||||||
|
0, // [0:4] is the sub-list for field type_name
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_compact_formats_proto_init() }
|
func init() { file_compact_formats_proto_init() }
|
||||||
|
@ -429,7 +527,7 @@ func file_compact_formats_proto_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_compact_formats_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
file_compact_formats_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*CompactSpend); i {
|
switch v := v.(*CompactSaplingSpend); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -441,7 +539,19 @@ func file_compact_formats_proto_init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_compact_formats_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
file_compact_formats_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||||
switch v := v.(*CompactOutput); i {
|
switch v := v.(*CompactSaplingOutput); i {
|
||||||
|
case 0:
|
||||||
|
return &v.state
|
||||||
|
case 1:
|
||||||
|
return &v.sizeCache
|
||||||
|
case 2:
|
||||||
|
return &v.unknownFields
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file_compact_formats_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||||
|
switch v := v.(*CompactOrchardAction); i {
|
||||||
case 0:
|
case 0:
|
||||||
return &v.state
|
return &v.state
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -459,7 +569,7 @@ func file_compact_formats_proto_init() {
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_compact_formats_proto_rawDesc,
|
RawDescriptor: file_compact_formats_proto_rawDesc,
|
||||||
NumEnums: 0,
|
NumEnums: 0,
|
||||||
NumMessages: 4,
|
NumMessages: 5,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
|
|
@ -37,20 +37,30 @@ message CompactTx {
|
||||||
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
|
// valueBalance + (sum(vPubNew) - sum(vPubOld) - sum(tOut))
|
||||||
uint32 fee = 3;
|
uint32 fee = 3;
|
||||||
|
|
||||||
repeated CompactSpend spends = 4; // inputs
|
repeated CompactSaplingSpend spends = 4; // inputs
|
||||||
repeated CompactOutput outputs = 5; // outputs
|
repeated CompactSaplingOutput outputs = 5; // outputs
|
||||||
|
repeated CompactOrchardAction actions = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompactSpend is a Sapling Spend Description as described in 7.3 of the Zcash
|
// CompactSaplingSpend is a Sapling Spend Description as described in 7.3 of the Zcash
|
||||||
// protocol specification.
|
// protocol specification.
|
||||||
message CompactSpend {
|
message CompactSaplingSpend {
|
||||||
bytes nf = 1; // nullifier (see the Zcash protocol specification)
|
bytes nf = 1; // nullifier (see the Zcash protocol specification)
|
||||||
}
|
}
|
||||||
|
|
||||||
// output is a Sapling Output Description as described in section 7.4 of the
|
// output is a Sapling Output Description as described in section 7.4 of the
|
||||||
// Zcash protocol spec. Total size is 948.
|
// Zcash protocol spec. Total size is 948.
|
||||||
message CompactOutput {
|
message CompactSaplingOutput {
|
||||||
bytes cmu = 1; // note commitment u-coordinate
|
bytes cmu = 1; // note commitment u-coordinate
|
||||||
bytes epk = 2; // ephemeral public key
|
bytes epk = 2; // ephemeral public key
|
||||||
bytes ciphertext = 3; // ciphertext and zkproof
|
bytes ciphertext = 3; // first 52 bytes of ciphertext
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://github.com/zcash/zips/blob/main/zip-0225.rst#orchard-action-description-orchardaction
|
||||||
|
// (but not all fields are needed)
|
||||||
|
message CompactOrchardAction {
|
||||||
|
bytes nullifier = 1; // [32] The nullifier of the input note
|
||||||
|
bytes cmx = 2; // [32] The x-coordinate of the note commitment for the output note
|
||||||
|
bytes ephemeralKey = 3; // [32] An encoding of an ephemeral Pallas public key
|
||||||
|
bytes ciphertext = 4; // [52] The note plaintext component of the encCiphertext field
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.27.1
|
||||||
// protoc v3.15.7
|
// protoc v3.19.4
|
||||||
// source: darkside.proto
|
// source: darkside.proto
|
||||||
|
|
||||||
package walletrpc
|
package walletrpc
|
||||||
|
@ -383,7 +383,7 @@ var file_darkside_proto_rawDesc = []byte{
|
||||||
0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12,
|
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,
|
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,
|
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, 0xda, 0x06, 0x0a, 0x10,
|
0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x32, 0x8b, 0x08, 0x0a, 0x10,
|
||||||
0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72,
|
0x44, 0x61, 0x72, 0x6b, 0x73, 0x69, 0x64, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72,
|
||||||
0x12, 0x51, 0x0a, 0x05, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x28, 0x2e, 0x63, 0x61, 0x73, 0x68,
|
0x12, 0x51, 0x0a, 0x05, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x28, 0x2e, 0x63, 0x61, 0x73, 0x68,
|
||||||
0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70,
|
0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70,
|
||||||
|
@ -437,9 +437,20 @@ var file_darkside_proto_rawDesc = []byte{
|
||||||
0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72,
|
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,
|
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,
|
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
|
||||||
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x1b, 0x5a, 0x16, 0x6c, 0x69, 0x67, 0x68,
|
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x5d, 0x0a, 0x0e, 0x41, 0x64, 0x64, 0x41,
|
||||||
0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x72,
|
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x12, 0x2b, 0x2e, 0x63, 0x61, 0x73,
|
||||||
0x70, 0x63, 0xba, 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72,
|
||||||
|
0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78,
|
||||||
|
0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 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, 0x50, 0x0a, 0x10, 0x43, 0x6c, 0x65, 0x61, 0x72,
|
||||||
|
0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 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, 0x42, 0x1b, 0x5a, 0x16, 0x6c, 0x69, 0x67,
|
||||||
|
0x68, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74,
|
||||||
|
0x72, 0x70, 0x63, 0xba, 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -464,31 +475,36 @@ var file_darkside_proto_goTypes = []interface{}{
|
||||||
(*DarksideEmptyBlocks)(nil), // 5: cash.z.wallet.sdk.rpc.DarksideEmptyBlocks
|
(*DarksideEmptyBlocks)(nil), // 5: cash.z.wallet.sdk.rpc.DarksideEmptyBlocks
|
||||||
(*RawTransaction)(nil), // 6: cash.z.wallet.sdk.rpc.RawTransaction
|
(*RawTransaction)(nil), // 6: cash.z.wallet.sdk.rpc.RawTransaction
|
||||||
(*Empty)(nil), // 7: cash.z.wallet.sdk.rpc.Empty
|
(*Empty)(nil), // 7: cash.z.wallet.sdk.rpc.Empty
|
||||||
|
(*GetAddressUtxosReply)(nil), // 8: cash.z.wallet.sdk.rpc.GetAddressUtxosReply
|
||||||
}
|
}
|
||||||
var file_darkside_proto_depIdxs = []int32{
|
var file_darkside_proto_depIdxs = []int32{
|
||||||
0, // 0: cash.z.wallet.sdk.rpc.DarksideStreamer.Reset:input_type -> cash.z.wallet.sdk.rpc.DarksideMetaState
|
0, // 0: cash.z.wallet.sdk.rpc.DarksideStreamer.Reset:input_type -> cash.z.wallet.sdk.rpc.DarksideMetaState
|
||||||
1, // 1: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocksStream:input_type -> cash.z.wallet.sdk.rpc.DarksideBlock
|
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
|
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
|
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.StageTransactionsStream:input_type -> cash.z.wallet.sdk.rpc.RawTransaction
|
6, // 4: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactionsStream:input_type -> cash.z.wallet.sdk.rpc.RawTransaction
|
||||||
3, // 5: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactions:input_type -> cash.z.wallet.sdk.rpc.DarksideTransactionsURL
|
3, // 5: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactions:input_type -> cash.z.wallet.sdk.rpc.DarksideTransactionsURL
|
||||||
4, // 6: cash.z.wallet.sdk.rpc.DarksideStreamer.ApplyStaged:input_type -> cash.z.wallet.sdk.rpc.DarksideHeight
|
4, // 6: cash.z.wallet.sdk.rpc.DarksideStreamer.ApplyStaged:input_type -> cash.z.wallet.sdk.rpc.DarksideHeight
|
||||||
7, // 7: cash.z.wallet.sdk.rpc.DarksideStreamer.GetIncomingTransactions:input_type -> cash.z.wallet.sdk.rpc.Empty
|
7, // 7: cash.z.wallet.sdk.rpc.DarksideStreamer.GetIncomingTransactions:input_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
7, // 8: cash.z.wallet.sdk.rpc.DarksideStreamer.ClearIncomingTransactions:input_type -> cash.z.wallet.sdk.rpc.Empty
|
7, // 8: cash.z.wallet.sdk.rpc.DarksideStreamer.ClearIncomingTransactions:input_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
7, // 9: cash.z.wallet.sdk.rpc.DarksideStreamer.Reset:output_type -> cash.z.wallet.sdk.rpc.Empty
|
8, // 9: cash.z.wallet.sdk.rpc.DarksideStreamer.AddAddressUtxo:input_type -> cash.z.wallet.sdk.rpc.GetAddressUtxosReply
|
||||||
7, // 10: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocksStream:output_type -> cash.z.wallet.sdk.rpc.Empty
|
7, // 10: cash.z.wallet.sdk.rpc.DarksideStreamer.ClearAddressUtxo:input_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, // 11: cash.z.wallet.sdk.rpc.DarksideStreamer.Reset: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, // 12: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocksStream:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
7, // 13: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactionsStream:output_type -> cash.z.wallet.sdk.rpc.Empty
|
7, // 13: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocks:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
7, // 14: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactions:output_type -> cash.z.wallet.sdk.rpc.Empty
|
7, // 14: cash.z.wallet.sdk.rpc.DarksideStreamer.StageBlocksCreate:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
7, // 15: cash.z.wallet.sdk.rpc.DarksideStreamer.ApplyStaged:output_type -> cash.z.wallet.sdk.rpc.Empty
|
7, // 15: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactionsStream:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
6, // 16: cash.z.wallet.sdk.rpc.DarksideStreamer.GetIncomingTransactions:output_type -> cash.z.wallet.sdk.rpc.RawTransaction
|
7, // 16: cash.z.wallet.sdk.rpc.DarksideStreamer.StageTransactions:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
7, // 17: cash.z.wallet.sdk.rpc.DarksideStreamer.ClearIncomingTransactions:output_type -> cash.z.wallet.sdk.rpc.Empty
|
7, // 17: cash.z.wallet.sdk.rpc.DarksideStreamer.ApplyStaged:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
9, // [9:18] is the sub-list for method output_type
|
6, // 18: cash.z.wallet.sdk.rpc.DarksideStreamer.GetIncomingTransactions:output_type -> cash.z.wallet.sdk.rpc.RawTransaction
|
||||||
0, // [0:9] is the sub-list for method input_type
|
7, // 19: cash.z.wallet.sdk.rpc.DarksideStreamer.ClearIncomingTransactions:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
0, // [0:0] is the sub-list for extension type_name
|
7, // 20: cash.z.wallet.sdk.rpc.DarksideStreamer.AddAddressUtxo:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
0, // [0:0] is the sub-list for extension extendee
|
7, // 21: cash.z.wallet.sdk.rpc.DarksideStreamer.ClearAddressUtxo:output_type -> cash.z.wallet.sdk.rpc.Empty
|
||||||
0, // [0:0] is the sub-list for field type_name
|
11, // [11:22] is the sub-list for method output_type
|
||||||
|
0, // [0:11] 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
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_darkside_proto_init() }
|
func init() { file_darkside_proto_init() }
|
||||||
|
|
|
@ -114,4 +114,11 @@ service DarksideStreamer {
|
||||||
|
|
||||||
// Clear the incoming transaction pool.
|
// Clear the incoming transaction pool.
|
||||||
rpc ClearIncomingTransactions(Empty) returns (Empty) {}
|
rpc ClearIncomingTransactions(Empty) returns (Empty) {}
|
||||||
|
|
||||||
|
// Add a GetAddressUtxosReply entry to be returned by GetAddressUtxos().
|
||||||
|
// There is no staging or applying for these, very simple.
|
||||||
|
rpc AddAddressUtxo(GetAddressUtxosReply) returns (Empty) {}
|
||||||
|
|
||||||
|
// Clear the list of GetAddressUtxos entries (can't fail)
|
||||||
|
rpc ClearAddressUtxo(Empty) returns (Empty) {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.2.0
|
||||||
|
// - protoc v3.19.4
|
||||||
|
// source: darkside.proto
|
||||||
|
|
||||||
package walletrpc
|
package walletrpc
|
||||||
|
|
||||||
|
@ -76,6 +80,11 @@ type DarksideStreamerClient interface {
|
||||||
GetIncomingTransactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (DarksideStreamer_GetIncomingTransactionsClient, error)
|
GetIncomingTransactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (DarksideStreamer_GetIncomingTransactionsClient, error)
|
||||||
// Clear the incoming transaction pool.
|
// Clear the incoming transaction pool.
|
||||||
ClearIncomingTransactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
|
ClearIncomingTransactions(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
|
||||||
|
// Add a GetAddressUtxosReply entry to be returned by GetAddressUtxos().
|
||||||
|
// There is no staging or applying for these, very simple.
|
||||||
|
AddAddressUtxo(ctx context.Context, in *GetAddressUtxosReply, opts ...grpc.CallOption) (*Empty, error)
|
||||||
|
// Clear the list of GetAddressUtxos entries (can't fail)
|
||||||
|
ClearAddressUtxo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type darksideStreamerClient struct {
|
type darksideStreamerClient struct {
|
||||||
|
@ -240,6 +249,24 @@ func (c *darksideStreamerClient) ClearIncomingTransactions(ctx context.Context,
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *darksideStreamerClient) AddAddressUtxo(ctx context.Context, in *GetAddressUtxosReply, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
out := new(Empty)
|
||||||
|
err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.DarksideStreamer/AddAddressUtxo", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *darksideStreamerClient) ClearAddressUtxo(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*Empty, error) {
|
||||||
|
out := new(Empty)
|
||||||
|
err := c.cc.Invoke(ctx, "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearAddressUtxo", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
// DarksideStreamerServer is the server API for DarksideStreamer service.
|
// DarksideStreamerServer is the server API for DarksideStreamer service.
|
||||||
// All implementations must embed UnimplementedDarksideStreamerServer
|
// All implementations must embed UnimplementedDarksideStreamerServer
|
||||||
// for forward compatibility
|
// for forward compatibility
|
||||||
|
@ -302,6 +329,11 @@ type DarksideStreamerServer interface {
|
||||||
GetIncomingTransactions(*Empty, DarksideStreamer_GetIncomingTransactionsServer) error
|
GetIncomingTransactions(*Empty, DarksideStreamer_GetIncomingTransactionsServer) error
|
||||||
// Clear the incoming transaction pool.
|
// Clear the incoming transaction pool.
|
||||||
ClearIncomingTransactions(context.Context, *Empty) (*Empty, error)
|
ClearIncomingTransactions(context.Context, *Empty) (*Empty, error)
|
||||||
|
// Add a GetAddressUtxosReply entry to be returned by GetAddressUtxos().
|
||||||
|
// There is no staging or applying for these, very simple.
|
||||||
|
AddAddressUtxo(context.Context, *GetAddressUtxosReply) (*Empty, error)
|
||||||
|
// Clear the list of GetAddressUtxos entries (can't fail)
|
||||||
|
ClearAddressUtxo(context.Context, *Empty) (*Empty, error)
|
||||||
mustEmbedUnimplementedDarksideStreamerServer()
|
mustEmbedUnimplementedDarksideStreamerServer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +368,12 @@ func (UnimplementedDarksideStreamerServer) GetIncomingTransactions(*Empty, Darks
|
||||||
func (UnimplementedDarksideStreamerServer) ClearIncomingTransactions(context.Context, *Empty) (*Empty, error) {
|
func (UnimplementedDarksideStreamerServer) ClearIncomingTransactions(context.Context, *Empty) (*Empty, error) {
|
||||||
return nil, status.Errorf(codes.Unimplemented, "method ClearIncomingTransactions not implemented")
|
return nil, status.Errorf(codes.Unimplemented, "method ClearIncomingTransactions not implemented")
|
||||||
}
|
}
|
||||||
|
func (UnimplementedDarksideStreamerServer) AddAddressUtxo(context.Context, *GetAddressUtxosReply) (*Empty, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method AddAddressUtxo not implemented")
|
||||||
|
}
|
||||||
|
func (UnimplementedDarksideStreamerServer) ClearAddressUtxo(context.Context, *Empty) (*Empty, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method ClearAddressUtxo not implemented")
|
||||||
|
}
|
||||||
func (UnimplementedDarksideStreamerServer) mustEmbedUnimplementedDarksideStreamerServer() {}
|
func (UnimplementedDarksideStreamerServer) mustEmbedUnimplementedDarksideStreamerServer() {}
|
||||||
|
|
||||||
// UnsafeDarksideStreamerServer may be embedded to opt out of forward compatibility for this service.
|
// UnsafeDarksideStreamerServer may be embedded to opt out of forward compatibility for this service.
|
||||||
|
@ -530,6 +568,42 @@ func _DarksideStreamer_ClearIncomingTransactions_Handler(srv interface{}, ctx co
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _DarksideStreamer_AddAddressUtxo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(GetAddressUtxosReply)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(DarksideStreamerServer).AddAddressUtxo(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/cash.z.wallet.sdk.rpc.DarksideStreamer/AddAddressUtxo",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DarksideStreamerServer).AddAddressUtxo(ctx, req.(*GetAddressUtxosReply))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _DarksideStreamer_ClearAddressUtxo_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).ClearAddressUtxo(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/cash.z.wallet.sdk.rpc.DarksideStreamer/ClearAddressUtxo",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(DarksideStreamerServer).ClearAddressUtxo(ctx, req.(*Empty))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
// DarksideStreamer_ServiceDesc is the grpc.ServiceDesc for DarksideStreamer service.
|
// DarksideStreamer_ServiceDesc is the grpc.ServiceDesc for DarksideStreamer service.
|
||||||
// It's only intended for direct use with grpc.RegisterService,
|
// It's only intended for direct use with grpc.RegisterService,
|
||||||
// and not to be introspected or modified (even as a copy)
|
// and not to be introspected or modified (even as a copy)
|
||||||
|
@ -561,6 +635,14 @@ var DarksideStreamer_ServiceDesc = grpc.ServiceDesc{
|
||||||
MethodName: "ClearIncomingTransactions",
|
MethodName: "ClearIncomingTransactions",
|
||||||
Handler: _DarksideStreamer_ClearIncomingTransactions_Handler,
|
Handler: _DarksideStreamer_ClearIncomingTransactions_Handler,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
MethodName: "AddAddressUtxo",
|
||||||
|
Handler: _DarksideStreamer_AddAddressUtxo_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "ClearAddressUtxo",
|
||||||
|
Handler: _DarksideStreamer_ClearAddressUtxo_Handler,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{
|
Streams: []grpc.StreamDesc{
|
||||||
{
|
{
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.26.0
|
// protoc-gen-go v1.28.0
|
||||||
// protoc v3.6.1
|
// protoc v3.6.1
|
||||||
// source: service.proto
|
// source: service.proto
|
||||||
|
|
||||||
|
@ -205,7 +205,8 @@ func (x *TxFilter) GetHash() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawTransaction contains the complete transaction data. It also optionally includes
|
// RawTransaction contains the complete transaction data. It also optionally includes
|
||||||
// the block height in which the transaction was included.
|
// the block height in which the transaction was included, or, when returned
|
||||||
|
// by GetMempoolStream(), the latest block height.
|
||||||
type RawTransaction struct {
|
type RawTransaction struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
|
@ -909,11 +910,12 @@ type TreeState struct {
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Network string `protobuf:"bytes,1,opt,name=network,proto3" json:"network,omitempty"` // "main" or "test"
|
Network string `protobuf:"bytes,1,opt,name=network,proto3" json:"network,omitempty"` // "main" or "test"
|
||||||
Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"`
|
Height uint64 `protobuf:"varint,2,opt,name=height,proto3" json:"height,omitempty"` // block height
|
||||||
Hash string `protobuf:"bytes,3,opt,name=hash,proto3" json:"hash,omitempty"` // block id
|
Hash string `protobuf:"bytes,3,opt,name=hash,proto3" json:"hash,omitempty"` // block id
|
||||||
Time uint32 `protobuf:"varint,4,opt,name=time,proto3" json:"time,omitempty"` // Unix epoch time when the block was mined
|
Time uint32 `protobuf:"varint,4,opt,name=time,proto3" json:"time,omitempty"` // Unix epoch time when the block was mined
|
||||||
Tree string `protobuf:"bytes,5,opt,name=tree,proto3" json:"tree,omitempty"` // sapling commitment tree state
|
SaplingTree string `protobuf:"bytes,5,opt,name=saplingTree,proto3" json:"saplingTree,omitempty"` // sapling commitment tree state
|
||||||
|
OrchardTree string `protobuf:"bytes,6,opt,name=orchardTree,proto3" json:"orchardTree,omitempty"` // orchard commitment tree state
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TreeState) Reset() {
|
func (x *TreeState) Reset() {
|
||||||
|
@ -976,9 +978,16 @@ func (x *TreeState) GetTime() uint32 {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TreeState) GetTree() string {
|
func (x *TreeState) GetSaplingTree() string {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Tree
|
return x.SaplingTree
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *TreeState) GetOrchardTree() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.OrchardTree
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -1395,153 +1404,156 @@ var file_service_proto_rawDesc = []byte{
|
||||||
0x6c, 0x75, 0x65, 0x5a, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x76, 0x61,
|
0x6c, 0x75, 0x65, 0x5a, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x76, 0x61,
|
||||||
0x6c, 0x75, 0x65, 0x5a, 0x61, 0x74, 0x22, 0x1d, 0x0a, 0x07, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64,
|
0x6c, 0x75, 0x65, 0x5a, 0x61, 0x74, 0x22, 0x1d, 0x0a, 0x07, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64,
|
||||||
0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52,
|
0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69, 0x64, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0c, 0x52,
|
||||||
0x04, 0x74, 0x78, 0x69, 0x64, 0x22, 0x79, 0x0a, 0x09, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61,
|
0x04, 0x74, 0x78, 0x69, 0x64, 0x22, 0xa9, 0x01, 0x0a, 0x09, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74,
|
||||||
0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01, 0x20,
|
0x61, 0x74, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x01,
|
||||||
0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x16, 0x0a, 0x06,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x16, 0x0a,
|
||||||
0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65,
|
0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68,
|
||||||
0x69, 0x67, 0x68, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01,
|
0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20,
|
||||||
0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d, 0x65,
|
0x01, 0x28, 0x09, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x69, 0x6d,
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04,
|
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x04, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x20, 0x0a,
|
||||||
0x74, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x74, 0x72, 0x65, 0x65,
|
0x0b, 0x73, 0x61, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01,
|
||||||
0x22, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74,
|
0x28, 0x09, 0x52, 0x0b, 0x73, 0x61, 0x70, 0x6c, 0x69, 0x6e, 0x67, 0x54, 0x72, 0x65, 0x65, 0x12,
|
||||||
0x78, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73,
|
0x20, 0x0a, 0x0b, 0x6f, 0x72, 0x63, 0x68, 0x61, 0x72, 0x64, 0x54, 0x72, 0x65, 0x65, 0x18, 0x06,
|
||||||
0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65,
|
0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x72, 0x63, 0x68, 0x61, 0x72, 0x64, 0x54, 0x72, 0x65,
|
||||||
0x73, 0x73, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x65, 0x69,
|
0x65, 0x22, 0x74, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55,
|
||||||
0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74,
|
0x74, 0x78, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x12, 0x1c, 0x0a, 0x09, 0x61, 0x64, 0x64, 0x72, 0x65,
|
||||||
0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x45, 0x6e, 0x74,
|
0x73, 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x61, 0x64, 0x64, 0x72,
|
||||||
0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6d, 0x61, 0x78, 0x45,
|
0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x20, 0x0a, 0x0b, 0x73, 0x74, 0x61, 0x72, 0x74, 0x48, 0x65,
|
||||||
0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0xa6, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x64,
|
0x69, 0x67, 0x68, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0b, 0x73, 0x74, 0x61, 0x72,
|
||||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12,
|
0x74, 0x48, 0x65, 0x69, 0x67, 0x68, 0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x6d, 0x61, 0x78, 0x45, 0x6e,
|
||||||
0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09,
|
0x74, 0x72, 0x69, 0x65, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0a, 0x6d, 0x61, 0x78,
|
||||||
0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78, 0x69,
|
0x45, 0x6e, 0x74, 0x72, 0x69, 0x65, 0x73, 0x22, 0xa6, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41,
|
||||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x14, 0x0a,
|
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79,
|
||||||
0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69, 0x6e,
|
0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||||
0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x03, 0x20,
|
0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x78,
|
||||||
0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x76,
|
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x74, 0x78, 0x69, 0x64, 0x12, 0x14,
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x5a, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x76,
|
0x0a, 0x05, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x69,
|
||||||
0x61, 0x6c, 0x75, 0x65, 0x5a, 0x61, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68,
|
0x6e, 0x64, 0x65, 0x78, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x18, 0x03,
|
||||||
0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74, 0x22,
|
0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x12, 0x1a, 0x0a, 0x08,
|
||||||
0x6b, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78,
|
0x76, 0x61, 0x6c, 0x75, 0x65, 0x5a, 0x61, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08,
|
||||||
0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0c, 0x61,
|
0x76, 0x61, 0x6c, 0x75, 0x65, 0x5a, 0x61, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x68, 0x65, 0x69, 0x67,
|
||||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28,
|
0x68, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x06, 0x68, 0x65, 0x69, 0x67, 0x68, 0x74,
|
||||||
0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65,
|
0x22, 0x6b, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74,
|
||||||
0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64,
|
0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x4f, 0x0a, 0x0c,
|
||||||
0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x52, 0x0c,
|
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x18, 0x01, 0x20, 0x03,
|
||||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x48, 0x0a, 0x0c,
|
0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c,
|
||||||
0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09,
|
0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64,
|
||||||
0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04, 0x52,
|
0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x52,
|
||||||
0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75,
|
0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x22, 0x48, 0x0a,
|
||||||
0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75,
|
0x0c, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1c, 0x0a,
|
||||||
0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x5f, 0x0a, 0x0d, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52,
|
0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x04,
|
||||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73,
|
0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x63,
|
||||||
0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63,
|
||||||
0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
|
0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x22, 0x5f, 0x0a, 0x0d, 0x50, 0x72, 0x69, 0x63, 0x65,
|
||||||
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63,
|
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65,
|
||||||
0x79, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01,
|
0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d,
|
||||||
0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x32, 0xd0, 0x0c, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70,
|
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
||||||
0x61, 0x63, 0x74, 0x54, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72, 0x12, 0x54, 0x0a,
|
0x63, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e,
|
||||||
0x0e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12,
|
0x63, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||||
0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e,
|
0x01, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x32, 0xd0, 0x0c, 0x0a, 0x11, 0x43, 0x6f, 0x6d,
|
||||||
0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x70, 0x65,
|
0x70, 0x61, 0x63, 0x74, 0x54, 0x78, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x65, 0x72, 0x12, 0x54,
|
||||||
0x63, 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65,
|
0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4c, 0x61, 0x74, 0x65, 0x73, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
|
||||||
0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49,
|
0x12, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74,
|
||||||
0x44, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x12,
|
0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x68, 0x61, 0x69, 0x6e, 0x53, 0x70,
|
||||||
0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e,
|
0x65, 0x63, 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c,
|
||||||
0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x1a,
|
0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
|
||||||
0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e,
|
0x49, 0x44, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
|
||||||
0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x42,
|
0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74,
|
||||||
0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c, 0x6f,
|
0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44,
|
||||||
0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a,
|
0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74,
|
||||||
0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e,
|
0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74,
|
||||||
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73,
|
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x5b, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x42, 0x6c,
|
||||||
0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72,
|
0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x21, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e,
|
||||||
0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x22,
|
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
|
||||||
0x00, 0x30, 0x01, 0x12, 0x5a, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x5a, 0x45, 0x43, 0x50, 0x72, 0x69,
|
0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0x23, 0x2e, 0x63, 0x61,
|
||||||
0x63, 0x65, 0x12, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c,
|
0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e,
|
||||||
0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x69, 0x63, 0x65,
|
0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b,
|
||||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a,
|
0x22, 0x00, 0x30, 0x01, 0x12, 0x5a, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x5a, 0x45, 0x43, 0x50, 0x72,
|
||||||
0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e,
|
0x69, 0x63, 0x65, 0x12, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
||||||
0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
|
|
||||||
0x5a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5a, 0x45, 0x43,
|
|
||||||
0x50, 0x72, 0x69, 0x63, 0x65, 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, 0x24, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
|
||||||
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x69, 0x63,
|
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x69, 0x63,
|
||||||
0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0e, 0x47,
|
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e,
|
||||||
0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x2e,
|
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
|
||||||
|
0x2e, 0x50, 0x72, 0x69, 0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00,
|
||||||
|
0x12, 0x5a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5a, 0x45,
|
||||||
|
0x43, 0x50, 0x72, 0x69, 0x63, 0x65, 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, 0x24, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61,
|
||||||
|
0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x72, 0x69,
|
||||||
|
0x63, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x0e,
|
||||||
|
0x47, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f,
|
||||||
|
0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73,
|
||||||
|
0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x78, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 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, 0x12, 0x5f, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64,
|
||||||
|
0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 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, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c,
|
||||||
|
0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52,
|
||||||
|
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, 0x74,
|
||||||
|
0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x78, 0x69, 0x64, 0x73, 0x12, 0x34, 0x2e,
|
||||||
0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64,
|
0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64,
|
||||||
0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x78, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x1a, 0x25,
|
0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e,
|
||||||
0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73,
|
0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6c,
|
||||||
0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61,
|
0x74, 0x65, 0x72, 0x1a, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
||||||
0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x12, 0x5f, 0x0a, 0x0f, 0x53, 0x65, 0x6e, 0x64, 0x54,
|
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, 0x12, 0x25, 0x2e, 0x63, 0x61, 0x73,
|
0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x30, 0x01, 0x12, 0x5a,
|
||||||
|
0x0a, 0x12, 0x47, 0x65, 0x74, 0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x61, 0x6c,
|
||||||
|
0x61, 0x6e, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61,
|
||||||
|
0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64,
|
||||||
|
0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e,
|
||||||
|
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
|
||||||
|
0x2e, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x18, 0x47, 0x65,
|
||||||
|
0x74, 0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65,
|
||||||
|
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e,
|
||||||
|
0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x41,
|
||||||
|
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e,
|
||||||
|
0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42,
|
||||||
|
0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x54, 0x0a, 0x0c, 0x47, 0x65,
|
||||||
|
0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x54, 0x78, 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73,
|
||||||
0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72,
|
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,
|
0x70, 0x63, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x1a, 0x20, 0x2e, 0x63, 0x61, 0x73,
|
||||||
0x6e, 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65,
|
0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72,
|
||||||
0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x52, 0x65,
|
0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x54, 0x78, 0x22, 0x00, 0x30, 0x01,
|
||||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x73, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x54,
|
0x12, 0x5b, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x74,
|
||||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x54, 0x78, 0x69, 0x64, 0x73, 0x12, 0x34, 0x2e, 0x63,
|
0x72, 0x65, 0x61, 0x6d, 0x12, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61,
|
||||||
0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b,
|
0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70,
|
||||||
0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74,
|
0x74, 0x79, 0x1a, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c,
|
||||||
0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x46, 0x69, 0x6c, 0x74,
|
|
||||||
0x65, 0x72, 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,
|
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, 0x5a, 0x0a,
|
0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a,
|
||||||
0x12, 0x47, 0x65, 0x74, 0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x61, 0x6c, 0x61,
|
0x0c, 0x47, 0x65, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x2e,
|
||||||
0x6e, 0x63, 0x65, 0x12, 0x22, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64,
|
||||||
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x72,
|
0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x1a, 0x20, 0x2e,
|
||||||
0x65, 0x73, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a,
|
0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64,
|
||||||
0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e,
|
0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22,
|
||||||
0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x18, 0x47, 0x65, 0x74,
|
0x00, 0x12, 0x6f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55,
|
||||||
0x54, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x53,
|
0x74, 0x78, 0x6f, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61,
|
||||||
0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77,
|
0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74,
|
||||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64,
|
0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x1a,
|
||||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x1a, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77,
|
0x2f, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e,
|
||||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x61,
|
0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65,
|
||||||
0x6c, 0x61, 0x6e, 0x63, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x54, 0x0a, 0x0c, 0x47, 0x65, 0x74,
|
0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x4c, 0x69, 0x73, 0x74,
|
||||||
0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x54, 0x78, 0x12, 0x1e, 0x2e, 0x63, 0x61, 0x73, 0x68,
|
0x22, 0x00, 0x12, 0x73, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73,
|
||||||
0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70,
|
0x55, 0x74, 0x78, 0x6f, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x29, 0x2e, 0x63, 0x61,
|
||||||
0x63, 0x2e, 0x45, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x1a, 0x20, 0x2e, 0x63, 0x61, 0x73, 0x68,
|
0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e,
|
||||||
0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70,
|
0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74,
|
||||||
0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x63, 0x74, 0x54, 0x78, 0x22, 0x00, 0x30, 0x01, 0x12,
|
0x78, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x1a, 0x2b, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e,
|
||||||
0x5b, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x70, 0x6f, 0x6f, 0x6c, 0x53, 0x74, 0x72,
|
0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47,
|
||||||
0x65, 0x61, 0x6d, 0x12, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65,
|
||||||
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x6d, 0x70, 0x74,
|
0x70, 0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x69,
|
||||||
0x79, 0x1a, 0x25, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65,
|
0x67, 0x68, 0x74, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e,
|
||||||
0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x61, 0x77, 0x54, 0x72, 0x61,
|
0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63,
|
||||||
0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0c,
|
0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x21, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e,
|
||||||
0x47, 0x65, 0x74, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1e, 0x2e, 0x63,
|
0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c,
|
||||||
0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b,
|
0x69, 0x67, 0x68, 0x74, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x04, 0x50,
|
||||||
0x2e, 0x72, 0x70, 0x63, 0x2e, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x49, 0x44, 0x1a, 0x20, 0x2e, 0x63,
|
0x69, 0x6e, 0x67, 0x12, 0x1f, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
||||||
0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b,
|
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x75, 0x72, 0x61,
|
||||||
0x2e, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x72, 0x65, 0x65, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x00,
|
0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61,
|
||||||
0x12, 0x6f, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74,
|
0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x69, 0x6e,
|
||||||
0x78, 0x6f, 0x73, 0x12, 0x29, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
0x67, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x1b, 0x5a, 0x16, 0x6c,
|
||||||
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41,
|
0x69, 0x67, 0x68, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2f, 0x77, 0x61, 0x6c, 0x6c,
|
||||||
0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x41, 0x72, 0x67, 0x1a, 0x2f,
|
0x65, 0x74, 0x72, 0x70, 0x63, 0xba, 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73,
|
|
||||||
0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73,
|
|
||||||
0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x4c, 0x69, 0x73, 0x74, 0x22,
|
|
||||||
0x00, 0x12, 0x73, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55,
|
|
||||||
0x74, 0x78, 0x6f, 0x73, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x29, 0x2e, 0x63, 0x61, 0x73,
|
|
||||||
0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72,
|
|
||||||
0x70, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78,
|
|
||||||
0x6f, 0x73, 0x41, 0x72, 0x67, 0x1a, 0x2b, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77,
|
|
||||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x65,
|
|
||||||
0x74, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x55, 0x74, 0x78, 0x6f, 0x73, 0x52, 0x65, 0x70,
|
|
||||||
0x6c, 0x79, 0x22, 0x00, 0x30, 0x01, 0x12, 0x52, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4c, 0x69, 0x67,
|
|
||||||
0x68, 0x74, 0x64, 0x49, 0x6e, 0x66, 0x6f, 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, 0x21, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77,
|
|
||||||
0x61, 0x6c, 0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x69,
|
|
||||||
0x67, 0x68, 0x74, 0x64, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x04, 0x50, 0x69,
|
|
||||||
0x6e, 0x67, 0x12, 0x1f, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c, 0x6c,
|
|
||||||
0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74,
|
|
||||||
0x69, 0x6f, 0x6e, 0x1a, 0x23, 0x2e, 0x63, 0x61, 0x73, 0x68, 0x2e, 0x7a, 0x2e, 0x77, 0x61, 0x6c,
|
|
||||||
0x6c, 0x65, 0x74, 0x2e, 0x73, 0x64, 0x6b, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x50, 0x69, 0x6e, 0x67,
|
|
||||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x1b, 0x5a, 0x16, 0x6c, 0x69,
|
|
||||||
0x67, 0x68, 0x74, 0x77, 0x61, 0x6c, 0x6c, 0x65, 0x74, 0x64, 0x2f, 0x77, 0x61, 0x6c, 0x6c, 0x65,
|
|
||||||
0x74, 0x72, 0x70, 0x63, 0xba, 0x02, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -32,7 +32,8 @@ message TxFilter {
|
||||||
}
|
}
|
||||||
|
|
||||||
// RawTransaction contains the complete transaction data. It also optionally includes
|
// RawTransaction contains the complete transaction data. It also optionally includes
|
||||||
// the block height in which the transaction was included.
|
// the block height in which the transaction was included, or, when returned
|
||||||
|
// by GetMempoolStream(), the latest block height.
|
||||||
message RawTransaction {
|
message RawTransaction {
|
||||||
bytes data = 1; // exact data returned by Zcash 'getrawtransaction'
|
bytes data = 1; // exact data returned by Zcash 'getrawtransaction'
|
||||||
uint64 height = 2; // height that the transaction was mined (or -1)
|
uint64 height = 2; // height that the transaction was mined (or -1)
|
||||||
|
@ -109,11 +110,12 @@ message Exclude {
|
||||||
|
|
||||||
// The TreeState is derived from the Zcash z_gettreestate rpc.
|
// The TreeState is derived from the Zcash z_gettreestate rpc.
|
||||||
message TreeState {
|
message TreeState {
|
||||||
string network = 1; // "main" or "test"
|
string network = 1; // "main" or "test"
|
||||||
uint64 height = 2;
|
uint64 height = 2; // block height
|
||||||
string hash = 3; // block id
|
string hash = 3; // block id
|
||||||
uint32 time = 4; // Unix epoch time when the block was mined
|
uint32 time = 4; // Unix epoch time when the block was mined
|
||||||
string tree = 5; // sapling commitment tree state
|
string saplingTree = 5; // sapling commitment tree state
|
||||||
|
string orchardTree = 6; // orchard commitment tree state
|
||||||
}
|
}
|
||||||
|
|
||||||
// Results are sorted by height, which makes it easy to issue another
|
// Results are sorted by height, which makes it easy to issue another
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
|
||||||
|
// versions:
|
||||||
|
// - protoc-gen-go-grpc v1.2.0
|
||||||
|
// - protoc v3.6.1
|
||||||
|
// source: service.proto
|
||||||
|
|
||||||
package walletrpc
|
package walletrpc
|
||||||
|
|
||||||
|
@ -45,6 +49,8 @@ type CompactTxStreamerClient interface {
|
||||||
// match a shortened txid, they are all sent (none is excluded). Transactions
|
// match a shortened txid, they are all sent (none is excluded). Transactions
|
||||||
// in the exclude list that don't exist in the mempool are ignored.
|
// in the exclude list that don't exist in the mempool are ignored.
|
||||||
GetMempoolTx(ctx context.Context, in *Exclude, opts ...grpc.CallOption) (CompactTxStreamer_GetMempoolTxClient, error)
|
GetMempoolTx(ctx context.Context, in *Exclude, opts ...grpc.CallOption) (CompactTxStreamer_GetMempoolTxClient, error)
|
||||||
|
// Return a stream of current Mempool transactions. This will keep the output stream open while
|
||||||
|
// there are mempool transactions. It will close the returned stream when a new block is mined.
|
||||||
GetMempoolStream(ctx context.Context, in *Empty, opts ...grpc.CallOption) (CompactTxStreamer_GetMempoolStreamClient, error)
|
GetMempoolStream(ctx context.Context, in *Empty, opts ...grpc.CallOption) (CompactTxStreamer_GetMempoolStreamClient, error)
|
||||||
// GetTreeState returns the note commitment tree state corresponding to the given block.
|
// GetTreeState returns the note commitment tree state corresponding to the given block.
|
||||||
// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
||||||
|
@ -391,6 +397,8 @@ type CompactTxStreamerServer interface {
|
||||||
// match a shortened txid, they are all sent (none is excluded). Transactions
|
// match a shortened txid, they are all sent (none is excluded). Transactions
|
||||||
// in the exclude list that don't exist in the mempool are ignored.
|
// in the exclude list that don't exist in the mempool are ignored.
|
||||||
GetMempoolTx(*Exclude, CompactTxStreamer_GetMempoolTxServer) error
|
GetMempoolTx(*Exclude, CompactTxStreamer_GetMempoolTxServer) error
|
||||||
|
// Return a stream of current Mempool transactions. This will keep the output stream open while
|
||||||
|
// there are mempool transactions. It will close the returned stream when a new block is mined.
|
||||||
GetMempoolStream(*Empty, CompactTxStreamer_GetMempoolStreamServer) error
|
GetMempoolStream(*Empty, CompactTxStreamer_GetMempoolStreamServer) error
|
||||||
// GetTreeState returns the note commitment tree state corresponding to the given block.
|
// GetTreeState returns the note commitment tree state corresponding to the given block.
|
||||||
// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
// See section 3.7 of the Zcash protocol specification. It returns several other useful
|
||||||
|
|
Loading…
Reference in New Issue