Skip to content

Commit

Permalink
return correct gRPC error codes
Browse files Browse the repository at this point in the history
  • Loading branch information
Larry Ruane committed Oct 30, 2024
1 parent 1e63bee commit 4cacf9e
Show file tree
Hide file tree
Showing 6 changed files with 421 additions and 300 deletions.
5 changes: 5 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ func startServer(opts *common.Options) error {
"error": err,
}).Fatal("getting initial information from zebrad or zcashd")
}
// Zebrad always supports lightwalletd (no special configuration needed);
// zcashd needs the lightwalletd=1 configuration option, so check that here.
if getLightdInfo.LightwalletdDisabled && !strings.Contains(getLightdInfo.ZcashdSubversion, "Zebra") {
common.Log.Fatal("zcashd is not configured as a lightwalletd server")
}
common.Log.Info("Got sapling height ", getLightdInfo.SaplingActivationHeight,
" block height ", getLightdInfo.BlockHeight,
" chain ", getLightdInfo.ChainName,
Expand Down
66 changes: 37 additions & 29 deletions common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import (
"github.com/sirupsen/logrus"
"github.com/zcash/lightwalletd/parser"
"github.com/zcash/lightwalletd/walletrpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

// 'make build' will overwrite this string with the output of git-describe (tag)
Expand Down Expand Up @@ -93,9 +95,13 @@ type (
}

// zcashd rpc "getinfo"
// If we're connected to an old version of zcashd that doesn't return
// LightwalletdDisabled, it will be false (the default bool value),
// and that will let us start up.
ZcashdRpcReplyGetinfo struct {
Build string
Subversion string
Build string
Subversion string
LightwalletdDisabled bool
}

// zcashd rpc "getaddresstxids"
Expand Down Expand Up @@ -294,6 +300,7 @@ func GetLightdInfo() (*walletrpc.LightdInfo, error) {
EstimatedHeight: uint64(getblockchaininfoReply.EstimatedHeight),
ZcashdBuild: getinfoReply.Build,
ZcashdSubversion: getinfoReply.Subversion,
LightwalletdDisabled: getinfoReply.LightwalletdDisabled,
}, nil
}

Expand All @@ -311,15 +318,13 @@ func getBlockFromRPC(height int) (*walletrpc.CompactBlock, error) {
if err != nil {
Log.Fatal("getBlockFromRPC bad height argument", height, err)
}
params := make([]json.RawMessage, 2)
params[0] = heightJSON
// Fetch the block using the verbose option ("1") because it provides
// both the list of txids, which we're not yet able to compute for
// Orchard (V5) transactions, and the block hash (block ID), which
// we need to fetch the raw data format of the same block. Don't fetch
// by height in case a reorg occurs between the two getblock calls;
// using block hash ensures that we're fetching the same block.
params[1] = json.RawMessage("1")
params := []json.RawMessage{heightJSON, json.RawMessage("1")}
result, rpcErr := RawRequest("getblock", params)
if rpcErr != nil {
// Check to see if we are requesting a height the zcashd doesn't have yet
Expand All @@ -331,14 +336,14 @@ func getBlockFromRPC(height int) (*walletrpc.CompactBlock, error) {
var block1 ZcashRpcReplyGetblock1
err = json.Unmarshal(result, &block1)
if err != nil {
return nil, err
Log.Fatal("getBlockFromRPC: Can't unmarshal block:", err)
}
blockHash, err := json.Marshal(block1.Hash)
if err != nil {
Log.Fatal("getBlockFromRPC bad block hash", block1.Hash)
}
params[0] = blockHash
params[1] = json.RawMessage("0") // non-verbose (raw hex)
// non-verbose (raw hex) version of block
params = []json.RawMessage{blockHash, json.RawMessage("0")}
result, rpcErr = RawRequest("getblock", params)

// For some reason, the error responses are not JSON
Expand Down Expand Up @@ -476,6 +481,7 @@ func BlockIngestor(c *BlockCache, rep int) {
// GetBlock returns the compact block at the requested height, first by querying
// the cache, then, if not found, will request the block from zcashd. It returns
// nil if no block exists at this height.
// This returns gRPC-compatible errors.
func GetBlock(cache *BlockCache, height int) (*walletrpc.CompactBlock, error) {
// First, check the cache to see if we have the block
var block *walletrpc.CompactBlock
Expand All @@ -489,11 +495,13 @@ func GetBlock(cache *BlockCache, height int) (*walletrpc.CompactBlock, error) {
// Not in the cache
block, err := getBlockFromRPC(height)
if err != nil {
return nil, err
return nil, status.Errorf(codes.InvalidArgument,
"GetBlock: getblock failed, error: %s", err.Error())
}
if block == nil {
// Block height is too large
return nil, errors.New("block requested is newer than latest block")
return nil, status.Errorf(codes.OutOfRange,
"GetBlock: block requested is newer than latest block: %d", height)
}
return block, nil
}
Expand Down Expand Up @@ -537,27 +545,27 @@ func GetBlockRange(cache *BlockCache, blockOut chan<- *walletrpc.CompactBlock, e
// the meanings of the `Height` field of the `RawTransaction` type are as
// follows:
//
// * height 0: the transaction is in the mempool
// * height 0xffffffffffffffff: the transaction has been mined on a fork that
// is not currently the main chain
// * any other height: the transaction has been mined in the main chain at the
// given height
// - height 0: the transaction is in the mempool
// - height 0xffffffffffffffff: the transaction has been mined on a fork that
// is not currently the main chain
// - any other height: the transaction has been mined in the main chain at the
// given height
func ParseRawTransaction(message json.RawMessage) (*walletrpc.RawTransaction, error) {
// Many other fields are returned, but we need only these two.
var txinfo ZcashdRpcReplyGetrawtransaction
err := json.Unmarshal(message, &txinfo)
if err != nil {
return nil, err
}
txBytes, err := hex.DecodeString(txinfo.Hex)
if err != nil {
return nil, err
}
// Many other fields are returned, but we need only these two.
var txinfo ZcashdRpcReplyGetrawtransaction
err := json.Unmarshal(message, &txinfo)
if err != nil {
return nil, err
}
txBytes, err := hex.DecodeString(txinfo.Hex)
if err != nil {
return nil, err
}

return &walletrpc.RawTransaction{
Data: txBytes,
Height: uint64(txinfo.Height),
}, nil
return &walletrpc.RawTransaction{
Data: txBytes,
Height: uint64(txinfo.Height),
}, nil
}

func displayHash(hash []byte) string {
Expand Down
7 changes: 7 additions & 0 deletions docs/rtd/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1525,6 +1525,13 @@ <h3 id="cash.z.wallet.sdk.rpc.LightdInfo">LightdInfo</h3>
<td><p>example: &#34;/MagicBean:4.1.1/&#34; </p></td>
</tr>

<tr>
<td>lightwalletdDisabled</td>
<td><a href="#bool">bool</a></td>
<td></td>
<td><p>whether zcashd is configured as a lwd server </p></td>
</tr>

</tbody>
</table>

Expand Down
Loading

0 comments on commit 4cacf9e

Please sign in to comment.