From 709fdb882b1214aeebd6cb32ff6aba79d16e67a9 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 17 Jan 2019 17:03:45 -0800 Subject: [PATCH] txscript: optimize IsUnspendable by removing all allocations During my work to optimize the IBD of btcd, I've been profiling heavily. I've noticed that this call `IsUnspendable` shows up in several hot spots during block validation, as we need to know if we should add a UTXO to the view/cache, etc. The current version uses `parseScript` to parse out all the pops and such. This is nice when we want to be able to easily manipulate things like data pushes, but for this simple check, it's unnecessary. The new version simply makes checks against the raw script which saves us a ton of allocations and CPU cycles. --- txscript/script.go | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/txscript/script.go b/txscript/script.go index aac3d4aaaa..a3710a698b 100644 --- a/txscript/script.go +++ b/txscript/script.go @@ -847,14 +847,10 @@ func getWitnessSigOps(pkScript []byte, witness wire.TxWitness) int { return 0 } -// IsUnspendable returns whether the passed public key script is unspendable, or -// guaranteed to fail at execution. This allows inputs to be pruned instantly -// when entering the UTXO set. +// IsUnspendable returns whether the passed public key script is unspendable, +// or guaranteed to fail at execution. This allows outputs to be pruned +// instantly when entering the UTXO set. func IsUnspendable(pkScript []byte) bool { - pops, err := parseScript(pkScript) - if err != nil { - return true - } - - return len(pops) > 0 && pops[0].opcode.value == OP_RETURN + return (len(pkScript) > 0 && pkScript[0] == OP_RETURN) || + (len(pkScript) > MaxScriptSize) }