decred.org/dcrwallet/v3@v3.1.0/wallet/udb/cfilters.go (about)

     1  // Copyright (c) 2018 The Decred developers
     2  // Use of this source code is governed by an ISC
     3  // license that can be found in the LICENSE file.
     4  
     5  package udb
     6  
     7  import (
     8  	"decred.org/dcrwallet/v3/errors"
     9  	"decred.org/dcrwallet/v3/wallet/walletdb"
    10  	"github.com/decred/dcrd/chaincfg/chainhash"
    11  	gcs2 "github.com/decred/dcrd/gcs/v4"
    12  	"github.com/decred/dcrd/gcs/v4/blockcf2"
    13  )
    14  
    15  // CFilterV2 returns the saved regular compact filter v2 for a block along with
    16  // the key necessary to query it for matches.
    17  func (s *Store) CFilterV2(dbtx walletdb.ReadTx, blockHash *chainhash.Hash) ([gcs2.KeySize]byte, *gcs2.FilterV2, error) {
    18  	ns := dbtx.ReadBucket(wtxmgrBucketKey)
    19  	k, v, err := fetchRawCFilter2(ns, blockHash[:])
    20  	if err != nil {
    21  		return [16]byte{}, nil, err
    22  	}
    23  	vc := make([]byte, len(v)) // Copy for FromBytesV2 which stores passed slice
    24  	copy(vc, v)
    25  	filter, err := gcs2.FromBytesV2(blockcf2.B, blockcf2.M, vc)
    26  	if err != nil {
    27  		return k, nil, err
    28  	}
    29  	return k, filter, err
    30  }
    31  
    32  // ImportCFiltersV2 imports the given list of cfilters into the wallet,
    33  // starting at the provided block height.
    34  func (s *Store) ImportCFiltersV2(dbtx walletdb.ReadWriteTx, startHeight int32, filterData [][]byte) error {
    35  	ns := dbtx.ReadWriteBucket(wtxmgrBucketKey)
    36  	blockIter := makeReadBlockIterator(ns, startHeight)
    37  	for i, fd := range filterData {
    38  		if !blockIter.next() {
    39  			return errors.E(errors.NotExist, errors.Errorf("block height of %d unknown", startHeight+int32(i)))
    40  		}
    41  
    42  		// Ensure this is actually a valid slice of cfilter data.
    43  		_, err := gcs2.FromBytesV2(blockcf2.B, blockcf2.M, fd)
    44  		if err != nil {
    45  			return err
    46  		}
    47  
    48  		// Find out the key for this filter based on the underlying
    49  		// block header.
    50  		bh := blockIter.elem.Hash
    51  		header, err := fetchRawBlockHeader(ns, keyBlockHeader(&bh))
    52  		if err != nil {
    53  			return err
    54  		}
    55  		merkleRoot := extractBlockHeaderMerkleRoot(header)
    56  		var bcf2Key [gcs2.KeySize]byte
    57  		copy(bcf2Key[:], merkleRoot)
    58  
    59  		// Store the cfilter data and query key.
    60  		err = putRawCFilter(ns, bh[:], valueRawCFilter2(bcf2Key, fd))
    61  		if err != nil {
    62  			return err
    63  		}
    64  	}
    65  
    66  	return nil
    67  }