Make rescan faster by avoiding hash copies.
Copying the RIPEMD160 after SHA256 hash result into a new stack array to be used as a map lookup key can be quite expensive, and this should be avoided if possible on intensive tasks such as rescans. This change takes advantage of the new Hash160 methods of the AddressPubKeyHash and AddressScriptHash types to use the address's underlying hash array directly, rather than creating a copy from the ScriptAddress result. Unfortunately, for AddressPubKey, ScriptAddress may return either a byte slice of len 33 or 65 depending on whether the pubkey is compressed or not, so no such straightforward optimization is possible. As a result of this change, I have seen rescans perform roughly 3.5x faster than before.
This commit is contained in:
parent
1e75ccc9b9
commit
f88db561f1
1 changed files with 8 additions and 12 deletions
|
@ -1479,9 +1479,10 @@ type rescanKeys struct {
|
|||
// rescanBlock rescans all transactions in a single block. This is a helper
|
||||
// function for handleRescan.
|
||||
func rescanBlock(wsc *wsClient, lookups *rescanKeys, blk *btcutil.Block) {
|
||||
// Vars used for map keys. The item being checked is copied into
|
||||
// these and then used as the lookup key. Saves on GC.
|
||||
var ripemd160Hash [ripemd160.Size]byte
|
||||
// Vars used for map keys. If necessary, the byte slice for each
|
||||
// checked item is copied into and then used as the lookup key.
|
||||
// This is quite a bit more efficient than creating an address
|
||||
// string as it saves on GC and performs less copying.
|
||||
var compressedPubkey [33]byte
|
||||
var uncompressedPubkey [65]byte
|
||||
var outpoint btcwire.OutPoint
|
||||
|
@ -1532,14 +1533,12 @@ func rescanBlock(wsc *wsClient, lookups *rescanKeys, blk *btcutil.Block) {
|
|||
for _, addr := range addrs {
|
||||
switch a := addr.(type) {
|
||||
case *btcutil.AddressPubKeyHash:
|
||||
copy(ripemd160Hash[:], a.ScriptAddress())
|
||||
if _, ok := lookups.pubKeyHashes[ripemd160Hash]; !ok {
|
||||
if _, ok := lookups.pubKeyHashes[*a.Hash160()]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
case *btcutil.AddressScriptHash:
|
||||
copy(ripemd160Hash[:], a.ScriptAddress())
|
||||
if _, ok := lookups.scriptHashes[ripemd160Hash]; !ok {
|
||||
if _, ok := lookups.scriptHashes[*a.Hash160()]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -1642,7 +1641,6 @@ func handleRescan(wsc *wsClient, icmd btcjson.Cmd) (interface{}, *btcjson.Error)
|
|||
uncompressedPubkeys: map[[65]byte]struct{}{},
|
||||
unspent: map[btcwire.OutPoint]struct{}{},
|
||||
}
|
||||
var ripemd160Hash [ripemd160.Size]byte
|
||||
var compressedPubkey [33]byte
|
||||
var uncompressedPubkey [65]byte
|
||||
for _, addrStr := range cmd.Addresses {
|
||||
|
@ -1656,12 +1654,10 @@ func handleRescan(wsc *wsClient, icmd btcjson.Cmd) (interface{}, *btcjson.Error)
|
|||
}
|
||||
switch a := addr.(type) {
|
||||
case *btcutil.AddressPubKeyHash:
|
||||
copy(ripemd160Hash[:], a.ScriptAddress())
|
||||
lookups.pubKeyHashes[ripemd160Hash] = struct{}{}
|
||||
lookups.pubKeyHashes[*a.Hash160()] = struct{}{}
|
||||
|
||||
case *btcutil.AddressScriptHash:
|
||||
copy(ripemd160Hash[:], a.ScriptAddress())
|
||||
lookups.scriptHashes[ripemd160Hash] = struct{}{}
|
||||
lookups.scriptHashes[*a.Hash160()] = struct{}{}
|
||||
|
||||
case *btcutil.AddressPubKey:
|
||||
pubkeyBytes := a.ScriptAddress()
|
||||
|
|
Loading…
Reference in a new issue