diff --git a/common/common.go b/common/common.go
index 6ba25ec9..310381ec 100644
--- a/common/common.go
+++ b/common/common.go
@@ -147,6 +147,11 @@ type (
 		Satoshis    uint64
 		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
@@ -271,6 +276,31 @@ func getBlockFromRPC(height int) (*walletrpc.CompactBlock, error) {
 		return nil, errors.New("received unexpected height block")
 	}
 
+	// Get the txids; it would be more efficient to implement a
+	// getblock verbose level that returns both raw hex and the txid list
+	// so that this second rpc wouldn't be needed.
+	{
+		params[0] = heightJSON
+		params[1] = json.RawMessage("1") // non-verbose (raw hex)
+		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
 }
 
diff --git a/parser/transaction.go b/parser/transaction.go
index e59367ed..5c3fb24b 100644
--- a/parser/transaction.go
+++ b/parser/transaction.go
@@ -6,7 +6,6 @@
 package parser
 
 import (
-	"crypto/sha256"
 	"fmt"
 
 	"github.com/pkg/errors"
@@ -339,29 +338,23 @@ func (p *action) ToCompact() *walletrpc.CompactOrchardAction {
 // Transaction encodes a full (zcashd) transaction.
 type Transaction struct {
 	*rawTransaction
-	rawBytes   []byte
-	cachedTxID []byte // cached for performance
+	rawBytes []byte
+	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.
 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
-	tx.cachedTxID = Reverse(digest[:])
-	return tx.cachedTxID
+	return Reverse(tx.txID[:])
 }
 
 // GetEncodableHash returns the transaction hash in little-endian wire format order.
 func (tx *Transaction) GetEncodableHash() []byte {
-	digest := sha256.Sum256(tx.rawBytes)
-	digest = sha256.Sum256(digest[:])
-	return digest[:]
+	return tx.txID
 }
 
 // Bytes returns a full transaction's raw bytes.
diff --git a/parser/transaction_test.go b/parser/transaction_test.go
index dd9498a2..114a1193 100644
--- a/parser/transaction_test.go
+++ b/parser/transaction_test.go
@@ -4,7 +4,6 @@
 package parser
 
 import (
-	"bytes"
 	"encoding/hex"
 	"encoding/json"
 	"os"
@@ -85,9 +84,8 @@ func TestV5TransactionParser(t *testing.T) {
 		if len(rest) != 0 {
 			t.Fatalf("Test did not consume entire buffer, %d remaining", len(rest))
 		}
-		if bytes.Equal(tx.cachedTxID, []byte(txtestdata.Txid)) {
-			t.Fatal("txid")
-		}
+		// Currently, we can't check the txid because we get that from
+		// zcashd (getblock rpc) rather than computing it ourselves.
 		if tx.version != uint32(txtestdata.Version) {
 			t.Fatal("version miscompare")
 		}