rpcserver: Optimize filteraddr code.
This optimizes the filter address handling code in the RPC server handleSearchRawTransasctions path in a few ways: - Only normalize the filter addresses provided in the command once rather than for every transaction being returned - Reset the passes filter flag just before it's used - Use a local for the encoded address to avoid the bounds checking overhead of accessing it from the slice - Avoiding subsequent map lookups once the filter has already passed Also, while here, modify a few of the related comments to match code style and consistency.
This commit is contained in:
parent
c7e6c1e88f
commit
16582789c3
1 changed files with 37 additions and 28 deletions
65
rpcserver.go
65
rpcserver.go
|
@ -678,16 +678,17 @@ func stringInSlice(a string, list []string) bool {
|
|||
// createVinList returns a slice of JSON objects for the inputs of the passed
|
||||
// transaction.
|
||||
func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.Params, vinExtra int, filterAddrMap map[string]struct{}) []btcjson.VinPrevOut {
|
||||
// We use a dynamically sized list to accomodate address filter.
|
||||
// Use a dynamically sized list to accomodate the address filter.
|
||||
vinList := make([]btcjson.VinPrevOut, 0, len(mtx.TxIn))
|
||||
|
||||
// Coinbase transactions only have a single txin by definition.
|
||||
if blockchain.IsCoinBaseTx(mtx) {
|
||||
// include tx only if filterAddrMap is empty because coinbase has no address
|
||||
// and so would never match a non-empty filter.
|
||||
// Include tx only if filterAddrMap is empty because coinbase
|
||||
// has no address and so would never match a non-empty filter.
|
||||
if len(filterAddrMap) != 0 {
|
||||
return vinList
|
||||
}
|
||||
|
||||
var vinEntry btcjson.VinPrevOut
|
||||
txIn := mtx.TxIn[0]
|
||||
vinEntry.Coinbase = hex.EncodeToString(txIn.SignatureScript)
|
||||
|
@ -708,9 +709,6 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
|||
}
|
||||
|
||||
for _, txIn := range mtx.TxIn {
|
||||
// reset filter flag for each.
|
||||
passesFilter := len(filterAddrMap) == 0
|
||||
|
||||
// The disassembled string will contain [error] inline
|
||||
// if the script doesn't fully parse, so ignore the
|
||||
// error here.
|
||||
|
@ -729,14 +727,21 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
|||
_, addrs, _, _ := txscript.ExtractPkScriptAddrs(
|
||||
originTxOut.PkScript, chainParams)
|
||||
|
||||
// Encode the addresses while checking if the address passes the
|
||||
// filter when needed.
|
||||
passesFilter := len(filterAddrMap) == 0
|
||||
encodedAddrs := make([]string, len(addrs))
|
||||
for j, addr := range addrs {
|
||||
encodedAddrs[j] = addr.EncodeAddress()
|
||||
encodedAddr := addr.EncodeAddress()
|
||||
encodedAddrs[j] = encodedAddr
|
||||
|
||||
if len(filterAddrMap) > 0 {
|
||||
if _, exists := filterAddrMap[encodedAddrs[j]]; exists {
|
||||
passesFilter = true
|
||||
}
|
||||
// No need to check the map again if the filter already
|
||||
// passes.
|
||||
if passesFilter {
|
||||
continue
|
||||
}
|
||||
if _, exists := filterAddrMap[encodedAddr]; exists {
|
||||
passesFilter = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -772,9 +777,6 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
|||
func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap map[string]struct{}) []btcjson.Vout {
|
||||
voutList := make([]btcjson.Vout, 0, len(mtx.TxOut))
|
||||
for i, v := range mtx.TxOut {
|
||||
// reset filter flag for each.
|
||||
passesFilter := len(filterAddrMap) == 0
|
||||
|
||||
// The disassembled string will contain [error] inline if the
|
||||
// script doesn't fully parse, so ignore the error here.
|
||||
disbuf, _ := txscript.DisasmString(v.PkScript)
|
||||
|
@ -785,14 +787,21 @@ func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap
|
|||
scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(
|
||||
v.PkScript, chainParams)
|
||||
|
||||
// Encode the addresses while checking if the address passes the
|
||||
// filter when needed.
|
||||
passesFilter := len(filterAddrMap) == 0
|
||||
encodedAddrs := make([]string, len(addrs))
|
||||
for j, addr := range addrs {
|
||||
encodedAddrs[j] = addr.EncodeAddress()
|
||||
encodedAddr := addr.EncodeAddress()
|
||||
encodedAddrs[j] = encodedAddr
|
||||
|
||||
if len(filterAddrMap) > 0 {
|
||||
if _, exists := filterAddrMap[encodedAddrs[j]]; exists {
|
||||
passesFilter = true
|
||||
}
|
||||
// No need to check the map again if the filter already
|
||||
// passes.
|
||||
if passesFilter {
|
||||
continue
|
||||
}
|
||||
if _, exists := filterAddrMap[encodedAddr]; exists {
|
||||
passesFilter = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3199,6 +3208,15 @@ func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan
|
|||
return nil, internalRPCError(err.Error(), context)
|
||||
}
|
||||
|
||||
// Normalize the provided filter addresses (if any) to ensure there are
|
||||
// no duplicates.
|
||||
filterAddrMap := make(map[string]struct{})
|
||||
if c.FilterAddrs != nil && len(*c.FilterAddrs) > 0 {
|
||||
for _, addr := range *c.FilterAddrs {
|
||||
filterAddrMap[addr] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
rawTxns := make([]btcjson.SearchRawTransactionsResult, len(addressTxs), len(addressTxs))
|
||||
for i, txReply := range addressTxs {
|
||||
txHash := txReply.Sha.String()
|
||||
|
@ -3224,15 +3242,6 @@ func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan
|
|||
blkHeight = txReply.Height
|
||||
}
|
||||
|
||||
// c.FilterAddrs can be nil, empty or non-empty. Here we normalize that
|
||||
// to a non-nil array (empty or non-empty) to avoid future nil checks.
|
||||
filterAddrMap := make(map[string]struct{})
|
||||
if c.FilterAddrs != nil && len(*c.FilterAddrs) > 0 {
|
||||
for _, addr := range *c.FilterAddrs {
|
||||
filterAddrMap[addr] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
rawTxn, err := createSearchRawTransactionsResult(s, s.server.chainParams, mtx,
|
||||
txHash, blkHeader, blkHashStr, blkHeight, maxIdx, *c.VinExtra, filterAddrMap)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in a new issue