CBFilter -> CFilter, discussed with davec@
This commit is contained in:
parent
a77b1e00d5
commit
6e5f650be9
15 changed files with 114 additions and 113 deletions
|
@ -19,24 +19,24 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// cbfIndexName is the human-readable name for the index.
|
// cfIndexName is the human-readable name for the index.
|
||||||
cbfIndexName = "committed bloom filter index"
|
cfIndexName = "committed bloom filter index"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// cbfIndexKey is the name of the db bucket used to house the
|
// cfIndexKey is the name of the db bucket used to house the
|
||||||
// block hash -> CBF index.
|
// block hash -> CF index.
|
||||||
cbfIndexKey = []byte("cbfbyhashidx")
|
cfIndexKey = []byte("cfbyhashidx")
|
||||||
|
|
||||||
// errNoCBFEntry is an error that indicates a requested entry does
|
// errNoCFEntry is an error that indicates a requested entry does
|
||||||
// not exist in the CBF index.
|
// not exist in the CF index.
|
||||||
errCBFEntry = errors.New("no entry in the block ID index")
|
errCFEntry = errors.New("no entry in the block ID index")
|
||||||
)
|
)
|
||||||
|
|
||||||
func dbFetchCBFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte,
|
func dbFetchCFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte,
|
||||||
error) {
|
error) {
|
||||||
// Load the record from the database and return now if it doesn't exist.
|
// Load the record from the database and return now if it doesn't exist.
|
||||||
index := dbTx.Metadata().Bucket(cbfIndexKey)
|
index := dbTx.Metadata().Bucket(cfIndexKey)
|
||||||
serializedFilter := index.Get(blockHash[:])
|
serializedFilter := index.Get(blockHash[:])
|
||||||
if len(serializedFilter) == 0 {
|
if len(serializedFilter) == 0 {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
|
@ -45,52 +45,52 @@ func dbFetchCBFIndexEntry(dbTx database.Tx, blockHash *chainhash.Hash) ([]byte,
|
||||||
return serializedFilter, nil
|
return serializedFilter, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// The serialized format for keys and values in the block hash to CBF bucket is:
|
// The serialized format for keys and values in the block hash to CF bucket is:
|
||||||
// <hash> = <CBF>
|
// <hash> = <CF>
|
||||||
//
|
//
|
||||||
// Field Type Size
|
// Field Type Size
|
||||||
// hash chainhash.Hash 32 bytes
|
// hash chainhash.Hash 32 bytes
|
||||||
// CBF []byte variable
|
// CF []byte variable
|
||||||
// -----
|
// -----
|
||||||
// Total: > 32 bytes
|
// Total: > 32 bytes
|
||||||
|
|
||||||
// CBFIndex implements a CBF by hash index.
|
// CFIndex implements a CF by hash index.
|
||||||
type CBFIndex struct {
|
type CFIndex struct {
|
||||||
db database.DB
|
db database.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure the CBFIndex type implements the Indexer interface.
|
// Ensure the CFIndex type implements the Indexer interface.
|
||||||
var _ Indexer = (*CBFIndex)(nil)
|
var _ Indexer = (*CFIndex)(nil)
|
||||||
|
|
||||||
// Init initializes the hash-based CBF index.
|
// Init initializes the hash-based CF index.
|
||||||
//
|
//
|
||||||
// This is part of the Indexer interface.
|
// This is part of the Indexer interface.
|
||||||
func (idx *CBFIndex) Init() error {
|
func (idx *CFIndex) Init() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Key returns the database key to use for the index as a byte slice.
|
// Key returns the database key to use for the index as a byte slice.
|
||||||
//
|
//
|
||||||
// This is part of the Indexer interface.
|
// This is part of the Indexer interface.
|
||||||
func (idx *CBFIndex) Key() []byte {
|
func (idx *CFIndex) Key() []byte {
|
||||||
return cbfIndexKey
|
return cfIndexKey
|
||||||
}
|
}
|
||||||
|
|
||||||
// Name returns the human-readable name of the index.
|
// Name returns the human-readable name of the index.
|
||||||
//
|
//
|
||||||
// This is part of the Indexer interface.
|
// This is part of the Indexer interface.
|
||||||
func (idx *CBFIndex) Name() string {
|
func (idx *CFIndex) Name() string {
|
||||||
return cbfIndexName
|
return cfIndexName
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create is invoked when the indexer manager determines the index needs
|
// Create is invoked when the indexer manager determines the index needs
|
||||||
// to be created for the first time. It creates the buckets for the hash-based
|
// to be created for the first time. It creates the buckets for the hash-based
|
||||||
// CBF index.
|
// CF index.
|
||||||
//
|
//
|
||||||
// This is part of the Indexer interface.
|
// This is part of the Indexer interface.
|
||||||
func (idx *CBFIndex) Create(dbTx database.Tx) error {
|
func (idx *CFIndex) Create(dbTx database.Tx) error {
|
||||||
meta := dbTx.Metadata()
|
meta := dbTx.Metadata()
|
||||||
_, err := meta.CreateBucket(cbfIndexKey)
|
_, err := meta.CreateBucket(cfIndexKey)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,17 +118,17 @@ func generateFilterForBlock(block *btcutil.Block) ([]byte, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "Generated CBF for block %v", block.Hash())
|
fmt.Fprintf(os.Stderr, "Generated CF for block %v", block.Hash())
|
||||||
|
|
||||||
return filter.Bytes(), nil
|
return filter.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConnectBlock is invoked by the index manager when a new block has been
|
// ConnectBlock is invoked by the index manager when a new block has been
|
||||||
// connected to the main chain. This indexer adds a hash-to-CBF mapping for
|
// connected to the main chain. This indexer adds a hash-to-CF mapping for
|
||||||
// every passed block.
|
// every passed block.
|
||||||
//
|
//
|
||||||
// This is part of the Indexer interface.
|
// This is part of the Indexer interface.
|
||||||
func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block,
|
func (idx *CFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block,
|
||||||
view *blockchain.UtxoViewpoint) error {
|
view *blockchain.UtxoViewpoint) error {
|
||||||
filterBytes, err := generateFilterForBlock(block)
|
filterBytes, err := generateFilterForBlock(block)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -136,55 +136,55 @@ func (idx *CBFIndex) ConnectBlock(dbTx database.Tx, block *btcutil.Block,
|
||||||
}
|
}
|
||||||
|
|
||||||
meta := dbTx.Metadata()
|
meta := dbTx.Metadata()
|
||||||
index := meta.Bucket(cbfIndexKey)
|
index := meta.Bucket(cfIndexKey)
|
||||||
err = index.Put(block.Hash()[:], filterBytes)
|
err = index.Put(block.Hash()[:], filterBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(os.Stderr, "Stored CBF for block %v", block.Hash())
|
fmt.Fprintf(os.Stderr, "Stored CF for block %v", block.Hash())
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisconnectBlock is invoked by the index manager when a block has been
|
// DisconnectBlock is invoked by the index manager when a block has been
|
||||||
// disconnected from the main chain. This indexer removes the hash-to-CBF
|
// disconnected from the main chain. This indexer removes the hash-to-CF
|
||||||
// mapping for every passed block.
|
// mapping for every passed block.
|
||||||
//
|
//
|
||||||
// This is part of the Indexer interface.
|
// This is part of the Indexer interface.
|
||||||
func (idx *CBFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block,
|
func (idx *CFIndex) DisconnectBlock(dbTx database.Tx, block *btcutil.Block,
|
||||||
view *blockchain.UtxoViewpoint) error {
|
view *blockchain.UtxoViewpoint) error {
|
||||||
index := dbTx.Metadata().Bucket(cbfIndexKey)
|
index := dbTx.Metadata().Bucket(cfIndexKey)
|
||||||
filterBytes := index.Get(block.Hash()[:])
|
filterBytes := index.Get(block.Hash()[:])
|
||||||
if len(filterBytes) == 0 {
|
if len(filterBytes) == 0 {
|
||||||
return fmt.Errorf("can't remove non-existent filter %s from " +
|
return fmt.Errorf("can't remove non-existent filter %s from " +
|
||||||
"the cbfilter index", block.Hash())
|
"the cfilter index", block.Hash())
|
||||||
}
|
}
|
||||||
return index.Delete(block.Hash()[:])
|
return index.Delete(block.Hash()[:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (idx *CBFIndex) FilterByBlockHash(hash *chainhash.Hash) ([]byte, error) {
|
func (idx *CFIndex) FilterByBlockHash(hash *chainhash.Hash) ([]byte, error) {
|
||||||
var filterBytes []byte
|
var filterBytes []byte
|
||||||
err := idx.db.View(func(dbTx database.Tx) error {
|
err := idx.db.View(func(dbTx database.Tx) error {
|
||||||
var err error
|
var err error
|
||||||
filterBytes, err = dbFetchCBFIndexEntry(dbTx, hash)
|
filterBytes, err = dbFetchCFIndexEntry(dbTx, hash)
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
return filterBytes, err
|
return filterBytes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCBFIndex returns a new instance of an indexer that is used to create a
|
// NewCFIndex returns a new instance of an indexer that is used to create a
|
||||||
// mapping of the hashes of all blocks in the blockchain to their respective
|
// mapping of the hashes of all blocks in the blockchain to their respective
|
||||||
// committed bloom filters.
|
// committed bloom filters.
|
||||||
//
|
//
|
||||||
// It implements the Indexer interface which plugs into the IndexManager that in
|
// It implements the Indexer interface which plugs into the IndexManager that in
|
||||||
// turn is used by the blockchain package. This allows the index to be
|
// turn is used by the blockchain package. This allows the index to be
|
||||||
// seamlessly maintained along with the chain.
|
// seamlessly maintained along with the chain.
|
||||||
func NewCBFIndex(db database.DB) *CBFIndex {
|
func NewCFIndex(db database.DB) *CFIndex {
|
||||||
return &CBFIndex{db: db}
|
return &CFIndex{db: db}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DropCBFIndex drops the CBF index from the provided database if exists.
|
// DropCFIndex drops the CF index from the provided database if exists.
|
||||||
func DropCBFIndex(db database.DB) error {
|
func DropCFIndex(db database.DB) error {
|
||||||
return dropIndex(db, cbfIndexKey, cbfIndexName)
|
return dropIndex(db, cfIndexKey, cfIndexName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,15 +278,15 @@ func NewGetBlockTemplateCmd(request *TemplateRequest) *GetBlockTemplateCmd {
|
||||||
Request: request,
|
Request: request,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// GetCBFilterCmd defines the getcbfilter JSON-RPC command.
|
// GetCFilterCmd defines the getcfilter JSON-RPC command.
|
||||||
type GetCBFilterCmd struct {
|
type GetCFilterCmd struct {
|
||||||
Hash string
|
Hash string
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewGetCBFilterCmd returns a new instance which can be used to issue a
|
// NewGetCFilterCmd returns a new instance which can be used to issue a
|
||||||
// getcbfilter JSON-RPC command.
|
// getcfilter JSON-RPC command.
|
||||||
func NewGetCBFilterCmd(hash string) *GetCBFilterCmd {
|
func NewGetCFilterCmd(hash string) *GetCFilterCmd {
|
||||||
return &GetCBFilterCmd{
|
return &GetCFilterCmd{
|
||||||
Hash: hash,
|
Hash: hash,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -768,7 +768,7 @@ func init() {
|
||||||
MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags)
|
MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags)
|
||||||
MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags)
|
MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags)
|
||||||
MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags)
|
MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags)
|
||||||
MustRegisterCmd("getcbfilter", (*GetCBFilterCmd)(nil), flags)
|
MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags)
|
||||||
MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags)
|
MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags)
|
||||||
MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags)
|
MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags)
|
||||||
MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags)
|
MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags)
|
||||||
|
|
|
@ -318,15 +318,15 @@ func TestChainSvrCmds(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "getcbfilter",
|
name: "getcfilter",
|
||||||
newCmd: func() (interface{}, error) {
|
newCmd: func() (interface{}, error) {
|
||||||
return btcjson.NewCmd("getcbfilter", "123")
|
return btcjson.NewCmd("getcfilter", "123")
|
||||||
},
|
},
|
||||||
staticCmd: func() interface{} {
|
staticCmd: func() interface{} {
|
||||||
return btcjson.NewGetCBFilterCmd("123")
|
return btcjson.NewGetCFilterCmd("123")
|
||||||
},
|
},
|
||||||
marshalled: `{"jsonrpc":"1.0","method":"getcbfilter","params":["123"],"id":1}`,
|
marshalled: `{"jsonrpc":"1.0","method":"getcfilter","params":["123"],"id":1}`,
|
||||||
unmarshalled: &btcjson.GetCBFilterCmd{
|
unmarshalled: &btcjson.GetCFilterCmd{
|
||||||
Hash: "123",
|
Hash: "123",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -150,7 +150,7 @@ type config struct {
|
||||||
BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"`
|
BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"`
|
||||||
UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."`
|
UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."`
|
||||||
NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"`
|
NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"`
|
||||||
NoCBFilters bool `long:"nocbfilters" description:"Disable committed bloom filtering (CBF) support"`
|
NoCFilters bool `long:"nocfilters" description:"Disable committed filtering (CF) support"`
|
||||||
SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"`
|
SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"`
|
||||||
BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."`
|
BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."`
|
||||||
TxIndex bool `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"`
|
TxIndex bool `long:"txindex" description:"Maintain a full hash-based transaction index which makes all transactions available via the getrawtransaction RPC"`
|
||||||
|
|
2
doc.go
2
doc.go
|
@ -112,7 +112,7 @@ Application Options:
|
||||||
--blockprioritysize= Size in bytes for high-priority/low-fee transactions
|
--blockprioritysize= Size in bytes for high-priority/low-fee transactions
|
||||||
when creating a block (50000)
|
when creating a block (50000)
|
||||||
--nopeerbloomfilters Disable bloom filtering support.
|
--nopeerbloomfilters Disable bloom filtering support.
|
||||||
--nocbfilters Disable committed bloom filtering (CBF) support.
|
--nocfilters Disable committed filtering (CF) support.
|
||||||
--sigcachemaxsize= The maximum number of entries in the signature
|
--sigcachemaxsize= The maximum number of entries in the signature
|
||||||
verification cache.
|
verification cache.
|
||||||
--blocksonly Do not accept transactions from remote peers.
|
--blocksonly Do not accept transactions from remote peers.
|
||||||
|
|
12
peer/peer.go
12
peer/peer.go
|
@ -144,9 +144,9 @@ type MessageListeners struct {
|
||||||
// message.
|
// message.
|
||||||
OnGetHeaders func(p *Peer, msg *wire.MsgGetHeaders)
|
OnGetHeaders func(p *Peer, msg *wire.MsgGetHeaders)
|
||||||
|
|
||||||
// OnGetCBFilter is invoked when a peer receives a getcbfilter bitcoin
|
// OnGetCFilter is invoked when a peer receives a getcfilter bitcoin
|
||||||
// message.
|
// message.
|
||||||
OnGetCBFilter func(p *Peer, msg *wire.MsgGetCBFilter)
|
OnGetCFilter func(p *Peer, msg *wire.MsgGetCFilter)
|
||||||
|
|
||||||
// OnFeeFilter is invoked when a peer receives a feefilter bitcoin message.
|
// OnFeeFilter is invoked when a peer receives a feefilter bitcoin message.
|
||||||
OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter)
|
OnFeeFilter func(p *Peer, msg *wire.MsgFeeFilter)
|
||||||
|
@ -1285,7 +1285,7 @@ func (p *Peer) maybeAddDeadline(pendingResponses map[string]time.Time, msgCmd st
|
||||||
deadline = time.Now().Add(stallResponseTimeout * 3)
|
deadline = time.Now().Add(stallResponseTimeout * 3)
|
||||||
pendingResponses[wire.CmdHeaders] = deadline
|
pendingResponses[wire.CmdHeaders] = deadline
|
||||||
|
|
||||||
// XXX pedro: we may need to handle OnCBFilter here depending on the
|
// XXX pedro: we may need to handle OnCFilter here depending on the
|
||||||
// protocol behaviour defined.
|
// protocol behaviour defined.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1586,9 +1586,9 @@ out:
|
||||||
p.cfg.Listeners.OnGetHeaders(p, msg)
|
p.cfg.Listeners.OnGetHeaders(p, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *wire.MsgGetCBFilter:
|
case *wire.MsgGetCFilter:
|
||||||
if p.cfg.Listeners.OnGetCBFilter != nil {
|
if p.cfg.Listeners.OnGetCFilter != nil {
|
||||||
p.cfg.Listeners.OnGetCBFilter(p, msg)
|
p.cfg.Listeners.OnGetCFilter(p, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *wire.MsgFeeFilter:
|
case *wire.MsgFeeFilter:
|
||||||
|
|
|
@ -399,7 +399,7 @@ func TestPeerListeners(t *testing.T) {
|
||||||
OnGetHeaders: func(p *peer.Peer, msg *wire.MsgGetHeaders) {
|
OnGetHeaders: func(p *peer.Peer, msg *wire.MsgGetHeaders) {
|
||||||
ok <- msg
|
ok <- msg
|
||||||
},
|
},
|
||||||
OnGetCBFilter: func(p *peer.Peer, msg *wire.MsgGetCBFilter) {
|
OnGetCFilter: func(p *peer.Peer, msg *wire.MsgGetCFilter) {
|
||||||
ok <- msg
|
ok <- msg
|
||||||
},
|
},
|
||||||
OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) {
|
OnFeeFilter: func(p *peer.Peer, msg *wire.MsgFeeFilter) {
|
||||||
|
@ -526,8 +526,8 @@ func TestPeerListeners(t *testing.T) {
|
||||||
wire.NewMsgGetHeaders(),
|
wire.NewMsgGetHeaders(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"OnGetCBFilter",
|
"OnGetCFilter",
|
||||||
wire.NewMsgGetCBFilter(&chainhash.Hash{}),
|
wire.NewMsgGetCFilter(&chainhash.Hash{}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"OnFeeFilter",
|
"OnFeeFilter",
|
||||||
|
|
17
rpcserver.go
17
rpcserver.go
|
@ -142,7 +142,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
|
||||||
"getblockhash": handleGetBlockHash,
|
"getblockhash": handleGetBlockHash,
|
||||||
"getblockheader": handleGetBlockHeader,
|
"getblockheader": handleGetBlockHeader,
|
||||||
"getblocktemplate": handleGetBlockTemplate,
|
"getblocktemplate": handleGetBlockTemplate,
|
||||||
"getcbfilter": handleGetCBFilter,
|
"getcfilter": handleGetCFilter,
|
||||||
"getconnectioncount": handleGetConnectionCount,
|
"getconnectioncount": handleGetConnectionCount,
|
||||||
"getcurrentnet": handleGetCurrentNet,
|
"getcurrentnet": handleGetCurrentNet,
|
||||||
"getdifficulty": handleGetDifficulty,
|
"getdifficulty": handleGetDifficulty,
|
||||||
|
@ -259,7 +259,7 @@ var rpcLimited = map[string]struct{}{
|
||||||
"getblockcount": {},
|
"getblockcount": {},
|
||||||
"getblockhash": {},
|
"getblockhash": {},
|
||||||
"getblockheader": {},
|
"getblockheader": {},
|
||||||
"getcbfilter": {},
|
"getcfilter": {},
|
||||||
"getcurrentnet": {},
|
"getcurrentnet": {},
|
||||||
"getdifficulty": {},
|
"getdifficulty": {},
|
||||||
"getheaders": {},
|
"getheaders": {},
|
||||||
|
@ -2146,19 +2146,20 @@ func handleGetBlockTemplate(s *rpcServer, cmd interface{}, closeChan <-chan stru
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleGetCBFilter implements the getcbfilter command.
|
// handleGetCFilter implements the getcfilter command.
|
||||||
func handleGetCBFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
|
||||||
c := cmd.(*btcjson.GetCBFilterCmd)
|
c := cmd.(*btcjson.GetCFilterCmd)
|
||||||
hash, err := chainhash.NewHashFromStr(c.Hash)
|
hash, err := chainhash.NewHashFromStr(c.Hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, rpcDecodeHexError(c.Hash)
|
return nil, rpcDecodeHexError(c.Hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
filterBytes, err := s.server.cbfIndex.FilterByBlockHash(hash)
|
filterBytes, err := s.server.cfIndex.FilterByBlockHash(hash)
|
||||||
if len(filterBytes) > 0 {
|
if len(filterBytes) > 0 {
|
||||||
rpcsLog.Debugf("Found CB filter for %v", hash)
|
rpcsLog.Debugf("Found committed filter for %v", hash)
|
||||||
} else {
|
} else {
|
||||||
rpcsLog.Debugf("Could not find CB filter for %v: %v", hash, err)
|
rpcsLog.Debugf("Could not find committed filter for %v: %v",
|
||||||
|
hash, err)
|
||||||
return nil, &btcjson.RPCError{
|
return nil, &btcjson.RPCError{
|
||||||
Code: btcjson.ErrRPCBlockNotFound,
|
Code: btcjson.ErrRPCBlockNotFound,
|
||||||
Message: "Block not found",
|
Message: "Block not found",
|
||||||
|
|
|
@ -323,10 +323,10 @@ var helpDescsEnUS = map[string]string{
|
||||||
"getblocktemplate--condition2": "mode=proposal, accepted",
|
"getblocktemplate--condition2": "mode=proposal, accepted",
|
||||||
"getblocktemplate--result1": "An error string which represents why the proposal was rejected or nothing if accepted",
|
"getblocktemplate--result1": "An error string which represents why the proposal was rejected or nothing if accepted",
|
||||||
|
|
||||||
// GetCBFilterCmd help.
|
// GetCFilterCmd help.
|
||||||
"getcbfilter--synopsis": "Returns a block's committed bloom filter given its hash.",
|
"getcfilter--synopsis": "Returns a block's committed filter given its hash.",
|
||||||
"getcbfilter-hash": "The hash of the block",
|
"getcfilter-hash": "The hash of the block",
|
||||||
"getcbfilter--result0": "The block's committed bloom filter",
|
"getcfilter--result0": "The block's committed filter",
|
||||||
|
|
||||||
// GetConnectionCountCmd help.
|
// GetConnectionCountCmd help.
|
||||||
"getconnectioncount--synopsis": "Returns the number of active connections to other peers.",
|
"getconnectioncount--synopsis": "Returns the number of active connections to other peers.",
|
||||||
|
@ -673,7 +673,7 @@ var rpcResultTypes = map[string][]interface{}{
|
||||||
"getblockheader": {(*string)(nil), (*btcjson.GetBlockHeaderVerboseResult)(nil)},
|
"getblockheader": {(*string)(nil), (*btcjson.GetBlockHeaderVerboseResult)(nil)},
|
||||||
"getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil},
|
"getblocktemplate": {(*btcjson.GetBlockTemplateResult)(nil), (*string)(nil), nil},
|
||||||
"getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)},
|
"getblockchaininfo": {(*btcjson.GetBlockChainInfoResult)(nil)},
|
||||||
"getcbfilter": {(*string)(nil)},
|
"getcfilter": {(*string)(nil)},
|
||||||
"getconnectioncount": {(*int32)(nil)},
|
"getconnectioncount": {(*int32)(nil)},
|
||||||
"getcurrentnet": {(*uint32)(nil)},
|
"getcurrentnet": {(*uint32)(nil)},
|
||||||
"getdifficulty": {(*float64)(nil)},
|
"getdifficulty": {(*float64)(nil)},
|
||||||
|
|
|
@ -167,8 +167,8 @@
|
||||||
; Must not include characters '/', ':', '(' and ')'.
|
; Must not include characters '/', ':', '(' and ')'.
|
||||||
; uacomment=
|
; uacomment=
|
||||||
|
|
||||||
; Disable committed peer bloom filtering (CBF).
|
; Disable committed peer filtering (CF).
|
||||||
; nocbfilters=1
|
; nocfilters=1
|
||||||
|
|
||||||
; ------------------------------------------------------------------------------
|
; ------------------------------------------------------------------------------
|
||||||
; RPC server options - The following options control the built-in RPC server
|
; RPC server options - The following options control the built-in RPC server
|
||||||
|
|
24
server.go
24
server.go
|
@ -229,7 +229,7 @@ type server struct {
|
||||||
// do not need to be protected for concurrent access.
|
// do not need to be protected for concurrent access.
|
||||||
txIndex *indexers.TxIndex
|
txIndex *indexers.TxIndex
|
||||||
addrIndex *indexers.AddrIndex
|
addrIndex *indexers.AddrIndex
|
||||||
cbfIndex *indexers.CBFIndex
|
cfIndex *indexers.CFIndex
|
||||||
}
|
}
|
||||||
|
|
||||||
// serverPeer extends the peer to maintain state shared by the server and
|
// serverPeer extends the peer to maintain state shared by the server and
|
||||||
|
@ -739,14 +739,14 @@ func (sp *serverPeer) OnGetHeaders(_ *peer.Peer, msg *wire.MsgGetHeaders) {
|
||||||
sp.QueueMessage(&wire.MsgHeaders{Headers: blockHeaders}, nil)
|
sp.QueueMessage(&wire.MsgHeaders{Headers: blockHeaders}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// OnGetCBFilter is invoked when a peer receives a getcbfilter bitcoin message.
|
// OnGetCFilter is invoked when a peer receives a getcfilter bitcoin message.
|
||||||
func (sp *serverPeer) OnGetCBFilter(_ *peer.Peer, msg *wire.MsgGetCBFilter) {
|
func (sp *serverPeer) OnGetCFilter(_ *peer.Peer, msg *wire.MsgGetCFilter) {
|
||||||
// Ignore getcbfilter requests if not in sync.
|
// Ignore getcfilter requests if not in sync.
|
||||||
if !sp.server.blockManager.IsCurrent() {
|
if !sp.server.blockManager.IsCurrent() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filterBytes, err := sp.server.cbfIndex.FilterByBlockHash(&msg.BlockHash)
|
filterBytes, err := sp.server.cfIndex.FilterByBlockHash(&msg.BlockHash)
|
||||||
|
|
||||||
if len(filterBytes) > 0 {
|
if len(filterBytes) > 0 {
|
||||||
peerLog.Infof("Obtained CB filter for %v", msg.BlockHash)
|
peerLog.Infof("Obtained CB filter for %v", msg.BlockHash)
|
||||||
|
@ -1603,7 +1603,7 @@ func newPeerConfig(sp *serverPeer) *peer.Config {
|
||||||
OnGetData: sp.OnGetData,
|
OnGetData: sp.OnGetData,
|
||||||
OnGetBlocks: sp.OnGetBlocks,
|
OnGetBlocks: sp.OnGetBlocks,
|
||||||
OnGetHeaders: sp.OnGetHeaders,
|
OnGetHeaders: sp.OnGetHeaders,
|
||||||
OnGetCBFilter: sp.OnGetCBFilter,
|
OnGetCFilter: sp.OnGetCFilter,
|
||||||
OnFeeFilter: sp.OnFeeFilter,
|
OnFeeFilter: sp.OnFeeFilter,
|
||||||
OnFilterAdd: sp.OnFilterAdd,
|
OnFilterAdd: sp.OnFilterAdd,
|
||||||
OnFilterClear: sp.OnFilterClear,
|
OnFilterClear: sp.OnFilterClear,
|
||||||
|
@ -2178,8 +2178,8 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
||||||
if cfg.NoPeerBloomFilters {
|
if cfg.NoPeerBloomFilters {
|
||||||
services &^= wire.SFNodeBloom
|
services &^= wire.SFNodeBloom
|
||||||
}
|
}
|
||||||
if cfg.NoCBFilters {
|
if cfg.NoCFilters {
|
||||||
services &^= wire.SFNodeCBF
|
services &^= wire.SFNodeCF
|
||||||
}
|
}
|
||||||
|
|
||||||
amgr := addrmgr.New(cfg.DataDir, btcdLookup)
|
amgr := addrmgr.New(cfg.DataDir, btcdLookup)
|
||||||
|
@ -2243,10 +2243,10 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
|
||||||
s.addrIndex = indexers.NewAddrIndex(db, chainParams)
|
s.addrIndex = indexers.NewAddrIndex(db, chainParams)
|
||||||
indexes = append(indexes, s.addrIndex)
|
indexes = append(indexes, s.addrIndex)
|
||||||
}
|
}
|
||||||
if !cfg.NoCBFilters {
|
if !cfg.NoCFilters {
|
||||||
indxLog.Info("CBF index is enabled")
|
indxLog.Info("CF index is enabled")
|
||||||
s.cbfIndex = indexers.NewCBFIndex(db)
|
s.cfIndex = indexers.NewCFIndex(db)
|
||||||
indexes = append(indexes, s.cbfIndex)
|
indexes = append(indexes, s.cfIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an index manager if any of the optional indexes are enabled.
|
// Create an index manager if any of the optional indexes are enabled.
|
||||||
|
|
|
@ -51,7 +51,7 @@ const (
|
||||||
CmdReject = "reject"
|
CmdReject = "reject"
|
||||||
CmdSendHeaders = "sendheaders"
|
CmdSendHeaders = "sendheaders"
|
||||||
CmdFeeFilter = "feefilter"
|
CmdFeeFilter = "feefilter"
|
||||||
CmdGetCBFilter = "getcbfilter"
|
CmdGetCFilter = "getcfilter"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MessageEncoding represents the wire message encoding format to be used.
|
// MessageEncoding represents the wire message encoding format to be used.
|
||||||
|
@ -157,8 +157,8 @@ func makeEmptyMessage(command string) (Message, error) {
|
||||||
case CmdFeeFilter:
|
case CmdFeeFilter:
|
||||||
msg = &MsgFeeFilter{}
|
msg = &MsgFeeFilter{}
|
||||||
|
|
||||||
case CmdGetCBFilter:
|
case CmdGetCFilter:
|
||||||
msg = &MsgGetCBFilter{}
|
msg = &MsgGetCFilter{}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unhandled command [%s]", command)
|
return nil, fmt.Errorf("unhandled command [%s]", command)
|
||||||
|
|
|
@ -10,39 +10,39 @@ import (
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MsgGetCBFilter struct {
|
type MsgGetCFilter struct {
|
||||||
ProtocolVersion uint32
|
ProtocolVersion uint32
|
||||||
BlockHash chainhash.Hash
|
BlockHash chainhash.Hash
|
||||||
}
|
}
|
||||||
|
|
||||||
func (msg *MsgGetCBFilter) BtcDecode(r io.Reader, pver uint32) error {
|
func (msg *MsgGetCFilter) BtcDecode(r io.Reader, pver uint32) error {
|
||||||
return readElement(r, &msg.BlockHash)
|
return readElement(r, &msg.BlockHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
// BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
|
||||||
// This is part of the Message interface implementation.
|
// This is part of the Message interface implementation.
|
||||||
func (msg *MsgGetCBFilter) BtcEncode(w io.Writer, pver uint32) error {
|
func (msg *MsgGetCFilter) BtcEncode(w io.Writer, pver uint32) error {
|
||||||
return writeElement(w, &msg.BlockHash)
|
return writeElement(w, &msg.BlockHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Command returns the protocol command string for the message. This is part
|
// Command returns the protocol command string for the message. This is part
|
||||||
// of the Message interface implementation.
|
// of the Message interface implementation.
|
||||||
func (msg *MsgGetCBFilter) Command() string {
|
func (msg *MsgGetCFilter) Command() string {
|
||||||
return CmdGetCBFilter
|
return CmdGetCFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
// MaxPayloadLength returns the maximum length the payload can be for the
|
// MaxPayloadLength returns the maximum length the payload can be for the
|
||||||
// receiver. This is part of the Message interface implementation.
|
// receiver. This is part of the Message interface implementation.
|
||||||
func (msg *MsgGetCBFilter) MaxPayloadLength(pver uint32) uint32 {
|
func (msg *MsgGetCFilter) MaxPayloadLength(pver uint32) uint32 {
|
||||||
// Protocol version 4 bytes + block hash.
|
// Protocol version 4 bytes + block hash.
|
||||||
return 4 + chainhash.HashSize
|
return 4 + chainhash.HashSize
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMsgGetCBFilter returns a new bitcoin getblocks message that conforms to
|
// NewMsgGetCFilter returns a new bitcoin getblocks message that conforms to
|
||||||
// the Message interface using the passed parameters and defaults for the
|
// the Message interface using the passed parameters and defaults for the
|
||||||
// remaining fields.
|
// remaining fields.
|
||||||
func NewMsgGetCBFilter(blockHash *chainhash.Hash) *MsgGetCBFilter {
|
func NewMsgGetCFilter(blockHash *chainhash.Hash) *MsgGetCFilter {
|
||||||
return &MsgGetCBFilter{
|
return &MsgGetCFilter{
|
||||||
ProtocolVersion: ProtocolVersion,
|
ProtocolVersion: ProtocolVersion,
|
||||||
BlockHash: *blockHash,
|
BlockHash: *blockHash,
|
||||||
}
|
}
|
|
@ -72,9 +72,9 @@ const (
|
||||||
// and transactions including witness data (BIP0144).
|
// and transactions including witness data (BIP0144).
|
||||||
SFNodeWitness
|
SFNodeWitness
|
||||||
|
|
||||||
// SFNNodeCBF is a flag used to indicate a peer supports committed
|
// SFNodeCF is a flag used to indicate a peer supports committed
|
||||||
// bloom filters (CBFs).
|
// filters (CFs).
|
||||||
SFNodeCBF
|
SFNodeCF
|
||||||
)
|
)
|
||||||
|
|
||||||
// Map of service flags back to their constant names for pretty printing.
|
// Map of service flags back to their constant names for pretty printing.
|
||||||
|
@ -83,7 +83,7 @@ var sfStrings = map[ServiceFlag]string{
|
||||||
SFNodeGetUTXO: "SFNodeGetUTXO",
|
SFNodeGetUTXO: "SFNodeGetUTXO",
|
||||||
SFNodeBloom: "SFNodeBloom",
|
SFNodeBloom: "SFNodeBloom",
|
||||||
SFNodeWitness: "SFNodeWitness",
|
SFNodeWitness: "SFNodeWitness",
|
||||||
SFNodeCBF: "SFNodeCBF",
|
SFNodeCF: "SFNodeCF",
|
||||||
}
|
}
|
||||||
|
|
||||||
// orderedSFStrings is an ordered list of service flags from highest to
|
// orderedSFStrings is an ordered list of service flags from highest to
|
||||||
|
@ -93,7 +93,7 @@ var orderedSFStrings = []ServiceFlag{
|
||||||
SFNodeGetUTXO,
|
SFNodeGetUTXO,
|
||||||
SFNodeBloom,
|
SFNodeBloom,
|
||||||
SFNodeWitness,
|
SFNodeWitness,
|
||||||
SFNodeCBF,
|
SFNodeCF,
|
||||||
}
|
}
|
||||||
|
|
||||||
// String returns the ServiceFlag in human-readable form.
|
// String returns the ServiceFlag in human-readable form.
|
||||||
|
|
|
@ -18,8 +18,8 @@ func TestServiceFlagStringer(t *testing.T) {
|
||||||
{SFNodeBloom, "SFNodeBloom"},
|
{SFNodeBloom, "SFNodeBloom"},
|
||||||
{SFNodeWitness, "SFNodeWitness"},
|
{SFNodeWitness, "SFNodeWitness"},
|
||||||
{0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|0xfffffff0"},
|
{0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeWitness|0xfffffff0"},
|
||||||
{SFNodeCBF, "SFNodeCBF"},
|
{SFNodeCF, "SFNodeCF"},
|
||||||
{0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeCBF|0xfffffff0"},
|
{0xffffffff, "SFNodeNetwork|SFNodeGetUTXO|SFNodeBloom|SFNodeCF|0xfffffff0"},
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Logf("Running %d tests", len(tests))
|
t.Logf("Running %d tests", len(tests))
|
||||||
|
|
Loading…
Add table
Reference in a new issue