Actually, it’s possible to avoid the copy still by just making it mutable, and using your idea of a wrapper to provide a default:
0diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp
1index 9d25ec156a..f4cf24fee5 100644
2--- a/src/script/interpreter.cpp
3+++ b/src/script/interpreter.cpp
4@@ -428,8 +428,7 @@ static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::con
5 assert(false);
6 }
7
8-
9-bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror, ScriptExecutionData execdata)
10+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* serror)
11 {
12 static const CScriptNum bnZero(0);
13 static const CScriptNum bnOne(1);
14@@ -1257,6 +1256,12 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
15 return set_success(serror);
16 }
17
18+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
19+{
20+ ScriptExecutionData execdata;
21+ return EvalScript(stack, script, flags, checker, sigversion, execdata, serror);
22+}
23+
24 namespace {
25
26 /**
27@@ -1776,7 +1781,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSequence(const CScriptNum& nSeq
28 template class GenericTransactionSignatureChecker<CTransaction>;
29 template class GenericTransactionSignatureChecker<CMutableTransaction>;
30
31-static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CScript& scriptPubKey, unsigned int flags, SigVersion sigversion, const BaseSignatureChecker& checker, const ScriptExecutionData& execdata, ScriptError* serror)
32+static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CScript& scriptPubKey, unsigned int flags, SigVersion sigversion, const BaseSignatureChecker& checker, ScriptExecutionData& execdata, ScriptError* serror)
33 {
34 std::vector<valtype> stack{stack_span.begin(), stack_span.end()};
35
36@@ -1810,7 +1815,7 @@ static bool ExecuteWitnessScript(const Span<const valtype>& stack_span, const CS
37 }
38
39 // Run the script interpreter.
40- if (!EvalScript(stack, scriptPubKey, flags, checker, sigversion, serror, execdata)) return false;
41+ if (!EvalScript(stack, scriptPubKey, flags, checker, sigversion, execdata, serror)) return false;
42
43 // Scripts inside witness implicitly require cleanstack behaviour
44 if (stack.size() != 1) return set_error(serror, SCRIPT_ERR_CLEANSTACK);
45diff --git a/src/script/interpreter.h b/src/script/interpreter.h
46index c71a125e73..1050ed1550 100644
47--- a/src/script/interpreter.h
48+++ b/src/script/interpreter.h
49@@ -272,7 +272,8 @@ public:
50 using TransactionSignatureChecker = GenericTransactionSignatureChecker<CTransaction>;
51 using MutableTransactionSignatureChecker = GenericTransactionSignatureChecker<CMutableTransaction>;
52
53-bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr, ScriptExecutionData execdata = {});
54+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptExecutionData& execdata, ScriptError* error = nullptr);
55+bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = nullptr);
56 bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = nullptr);
57
58 size_t CountWitnessSigOps(const CScript& scriptSig, const CScript& scriptPubKey, const CScriptWitness* witness, unsigned int flags);