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
|
// createVinList returns a slice of JSON objects for the inputs of the passed
|
||||||
// transaction.
|
// transaction.
|
||||||
func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.Params, vinExtra int, filterAddrMap map[string]struct{}) []btcjson.VinPrevOut {
|
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))
|
vinList := make([]btcjson.VinPrevOut, 0, len(mtx.TxIn))
|
||||||
|
|
||||||
// Coinbase transactions only have a single txin by definition.
|
// Coinbase transactions only have a single txin by definition.
|
||||||
if blockchain.IsCoinBaseTx(mtx) {
|
if blockchain.IsCoinBaseTx(mtx) {
|
||||||
// include tx only if filterAddrMap is empty because coinbase has no address
|
// Include tx only if filterAddrMap is empty because coinbase
|
||||||
// and so would never match a non-empty filter.
|
// has no address and so would never match a non-empty filter.
|
||||||
if len(filterAddrMap) != 0 {
|
if len(filterAddrMap) != 0 {
|
||||||
return vinList
|
return vinList
|
||||||
}
|
}
|
||||||
|
|
||||||
var vinEntry btcjson.VinPrevOut
|
var vinEntry btcjson.VinPrevOut
|
||||||
txIn := mtx.TxIn[0]
|
txIn := mtx.TxIn[0]
|
||||||
vinEntry.Coinbase = hex.EncodeToString(txIn.SignatureScript)
|
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 {
|
for _, txIn := range mtx.TxIn {
|
||||||
// reset filter flag for each.
|
|
||||||
passesFilter := len(filterAddrMap) == 0
|
|
||||||
|
|
||||||
// The disassembled string will contain [error] inline
|
// The disassembled string will contain [error] inline
|
||||||
// if the script doesn't fully parse, so ignore the
|
// if the script doesn't fully parse, so ignore the
|
||||||
// error here.
|
// error here.
|
||||||
|
@ -729,14 +727,21 @@ func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.P
|
||||||
_, addrs, _, _ := txscript.ExtractPkScriptAddrs(
|
_, addrs, _, _ := txscript.ExtractPkScriptAddrs(
|
||||||
originTxOut.PkScript, chainParams)
|
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))
|
encodedAddrs := make([]string, len(addrs))
|
||||||
for j, addr := range addrs {
|
for j, addr := range addrs {
|
||||||
encodedAddrs[j] = addr.EncodeAddress()
|
encodedAddr := addr.EncodeAddress()
|
||||||
|
encodedAddrs[j] = encodedAddr
|
||||||
|
|
||||||
if len(filterAddrMap) > 0 {
|
// No need to check the map again if the filter already
|
||||||
if _, exists := filterAddrMap[encodedAddrs[j]]; exists {
|
// passes.
|
||||||
passesFilter = true
|
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 {
|
func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap map[string]struct{}) []btcjson.Vout {
|
||||||
voutList := make([]btcjson.Vout, 0, len(mtx.TxOut))
|
voutList := make([]btcjson.Vout, 0, len(mtx.TxOut))
|
||||||
for i, v := range 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
|
// The disassembled string will contain [error] inline if the
|
||||||
// script doesn't fully parse, so ignore the error here.
|
// script doesn't fully parse, so ignore the error here.
|
||||||
disbuf, _ := txscript.DisasmString(v.PkScript)
|
disbuf, _ := txscript.DisasmString(v.PkScript)
|
||||||
|
@ -785,14 +787,21 @@ func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap
|
||||||
scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(
|
scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(
|
||||||
v.PkScript, chainParams)
|
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))
|
encodedAddrs := make([]string, len(addrs))
|
||||||
for j, addr := range addrs {
|
for j, addr := range addrs {
|
||||||
encodedAddrs[j] = addr.EncodeAddress()
|
encodedAddr := addr.EncodeAddress()
|
||||||
|
encodedAddrs[j] = encodedAddr
|
||||||
|
|
||||||
if len(filterAddrMap) > 0 {
|
// No need to check the map again if the filter already
|
||||||
if _, exists := filterAddrMap[encodedAddrs[j]]; exists {
|
// passes.
|
||||||
passesFilter = true
|
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)
|
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))
|
rawTxns := make([]btcjson.SearchRawTransactionsResult, len(addressTxs), len(addressTxs))
|
||||||
for i, txReply := range addressTxs {
|
for i, txReply := range addressTxs {
|
||||||
txHash := txReply.Sha.String()
|
txHash := txReply.Sha.String()
|
||||||
|
@ -3224,15 +3242,6 @@ func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan
|
||||||
blkHeight = txReply.Height
|
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,
|
rawTxn, err := createSearchRawTransactionsResult(s, s.server.chainParams, mtx,
|
||||||
txHash, blkHeader, blkHashStr, blkHeight, maxIdx, *c.VinExtra, filterAddrMap)
|
txHash, blkHeader, blkHashStr, blkHeight, maxIdx, *c.VinExtra, filterAddrMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue