Skip to content

Commit f5d7ef8

Browse files
committed
64bit arith cscriptnum no new opcodes
1 parent e6c1026 commit f5d7ef8

File tree

16 files changed

+428
-56
lines changed

16 files changed

+428
-56
lines changed

src/policy/policy.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
#include <consensus/validation.h>
1414
#include <policy/feerate.h>
1515
#include <primitives/transaction.h>
16-
#include <script/interpreter.h>
16+
#include <script/sigversion.h>
1717
#include <script/script.h>
1818
#include <script/solver.h>
1919
#include <serialize.h>

src/rpc/util.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include <pow.h>
1818
#include <rpc/util.h>
1919
#include <script/descriptor.h>
20-
#include <script/interpreter.h>
20+
#include <script/sigversion.h>
2121
#include <script/signingprovider.h>
2222
#include <script/solver.h>
2323
#include <tinyformat.h>

src/script/interpreter.cpp

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <crypto/sha256.h>
1111
#include <pubkey.h>
1212
#include <script/script.h>
13+
#include <script/sigversion.h>
1314
#include <uint256.h>
1415

1516
typedef std::vector<unsigned char> valtype;
@@ -253,6 +254,20 @@ int FindAndDelete(CScript& script, const CScript& b)
253254
return nFound;
254255
}
255256

257+
CScriptNum GetCScriptNum(const valtype& num, const bool fRequireMinimal, const SigVersion& sigversion)
258+
{
259+
switch (sigversion)
260+
{
261+
case SigVersion::BASE:
262+
case SigVersion::WITNESS_V0:
263+
case SigVersion::TAPROOT:
264+
case SigVersion::TAPSCRIPT:
265+
return CScriptNum(num,fRequireMinimal,/*nMaximumSize=*/4);
266+
case SigVersion::TAPSCRIPT_64BIT:
267+
return CScriptNum(num,fRequireMinimal,/*nMaximumSize=*/8);
268+
}
269+
}
270+
256271
namespace {
257272
/** A data type to abstract out the condition stack during script execution.
258273
*
@@ -395,6 +410,7 @@ static bool EvalChecksig(const valtype& sig, const valtype& pubkey, CScript::con
395410
case SigVersion::WITNESS_V0:
396411
return EvalChecksigPreTapscript(sig, pubkey, pbegincodehash, pend, flags, checker, sigversion, serror, success);
397412
case SigVersion::TAPSCRIPT:
413+
case SigVersion::TAPSCRIPT_64BIT:
398414
return EvalChecksigTapscript(sig, pubkey, execdata, flags, checker, sigversion, serror, success);
399415
case SigVersion::TAPROOT:
400416
// Key path spending in Taproot has no script, so this is unreachable.
@@ -414,7 +430,7 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
414430
static const valtype vchTrue(1, 1);
415431

416432
// sigversion cannot be TAPROOT here, as it admits no script execution.
417-
assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0 || sigversion == SigVersion::TAPSCRIPT);
433+
assert(sigversion == SigVersion::BASE || sigversion == SigVersion::WITNESS_V0 || sigversion == SigVersion::TAPSCRIPT || sigversion == SigVersion::TAPSCRIPT_64BIT);
418434

419435
CScript::const_iterator pc = script.begin();
420436
CScript::const_iterator pend = script.end();
@@ -925,7 +941,8 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
925941
// (in -- out)
926942
if (stack.size() < 1)
927943
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
928-
CScriptNum bn(stacktop(-1), fRequireMinimal);
944+
945+
CScriptNum bn = GetCScriptNum(stacktop(-1), fRequireMinimal, sigversion);
929946
switch (opcode)
930947
{
931948
case OP_1ADD: bn += bnOne; break;
@@ -958,19 +975,17 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
958975
// (x1 x2 -- out)
959976
if (stack.size() < 2)
960977
return set_error(serror, SCRIPT_ERR_INVALID_STACK_OPERATION);
961-
CScriptNum bn1(stacktop(-2), fRequireMinimal);
962-
CScriptNum bn2(stacktop(-1), fRequireMinimal);
978+
CScriptNum bn1 = GetCScriptNum(stacktop(-2), fRequireMinimal, sigversion);
979+
CScriptNum bn2 = GetCScriptNum(stacktop(-1), fRequireMinimal, sigversion);
963980
CScriptNum bn(0);
964981
switch (opcode)
965982
{
966983
case OP_ADD:
967984
bn = bn1 + bn2;
968985
break;
969-
970986
case OP_SUB:
971987
bn = bn1 - bn2;
972988
break;
973-
974989
case OP_BOOLAND: bn = (bn1 != bnZero && bn2 != bnZero); break;
975990
case OP_BOOLOR: bn = (bn1 != bnZero || bn2 != bnZero); break;
976991
case OP_NUMEQUAL: bn = (bn1 == bn2); break;
@@ -987,7 +1002,6 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
9871002
popstack(stack);
9881003
popstack(stack);
9891004
stack.push_back(bn.getvch());
990-
9911005
if (opcode == OP_NUMEQUALVERIFY)
9921006
{
9931007
if (CastToBool(stacktop(-1)))
@@ -1938,6 +1952,13 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
19381952
execdata.m_validation_weight_left_init = true;
19391953
return ExecuteWitnessScript(stack, exec_script, flags, SigVersion::TAPSCRIPT, checker, execdata, serror);
19401954
}
1955+
if ((control[0] & TAPROOT_LEAF_MASK) == TAPROOT_LEAF_TAPSCRIPT_64BIT) {
1956+
// Tapscript (leaf version 0x66)
1957+
exec_script = CScript(script.begin(), script.end());
1958+
execdata.m_validation_weight_left = ::GetSerializeSize(witness.stack) + VALIDATION_WEIGHT_OFFSET;
1959+
execdata.m_validation_weight_left_init = true;
1960+
return ExecuteWitnessScript(stack, exec_script, flags, SigVersion::TAPSCRIPT_64BIT, checker, execdata, serror);
1961+
}
19411962
if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION) {
19421963
return set_error(serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION);
19431964
}

src/script/interpreter.h

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -187,14 +187,6 @@ struct PrecomputedTransactionData
187187
explicit PrecomputedTransactionData(const T& tx);
188188
};
189189

190-
enum class SigVersion
191-
{
192-
BASE = 0, //!< Bare scripts and BIP16 P2SH-wrapped redeemscripts
193-
WITNESS_V0 = 1, //!< Witness v0 (P2WPKH and P2WSH); see BIP 141
194-
TAPROOT = 2, //!< Witness v1 with 32-byte program, not BIP16 P2SH-wrapped, key path spending; see BIP 341
195-
TAPSCRIPT = 3, //!< Witness v1 with 32-byte program, not BIP16 P2SH-wrapped, script path spending, leaf version 0xc0; see BIP 342
196-
};
197-
198190
struct ScriptExecutionData
199191
{
200192
//! Whether m_tapleaf_hash is initialized.
@@ -230,6 +222,7 @@ static constexpr size_t WITNESS_V1_TAPROOT_SIZE = 32;
230222

231223
static constexpr uint8_t TAPROOT_LEAF_MASK = 0xfe;
232224
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT = 0xc0;
225+
static constexpr uint8_t TAPROOT_LEAF_TAPSCRIPT_64BIT = 0x66;
233226
static constexpr size_t TAPROOT_CONTROL_BASE_SIZE = 33;
234227
static constexpr size_t TAPROOT_CONTROL_NODE_SIZE = 32;
235228
static constexpr size_t TAPROOT_CONTROL_MAX_NODE_COUNT = 128;
@@ -240,7 +233,7 @@ extern const HashWriter HASHER_TAPLEAF; //!< Hasher with tag "TapLeaf" pre-fe
240233
extern const HashWriter HASHER_TAPBRANCH; //!< Hasher with tag "TapBranch" pre-fed to it.
241234

242235
template <class T>
243-
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int32_t nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr);
236+
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr);
244237

245238
class BaseSignatureChecker
246239
{

src/script/script.h

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,7 @@
1313
#include <uint256.h>
1414
#include <util/hash_type.h>
1515

16-
#include <cassert>
17-
#include <cstdint>
18-
#include <cstring>
19-
#include <limits>
20-
#include <span>
21-
#include <stdexcept>
22-
#include <string>
23-
#include <type_traits>
24-
#include <utility>
25-
#include <vector>
16+
enum class SigVersion;
2617

2718
// Maximum number of bytes pushable to the stack
2819
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
@@ -235,7 +226,7 @@ class CScriptNum
235226
*/
236227
public:
237228

238-
explicit CScriptNum(const int64_t& n)
229+
explicit CScriptNum(const __int128_t& n)
239230
{
240231
m_value = n;
241232
}
@@ -296,9 +287,15 @@ class CScriptNum
296287

297288
inline CScriptNum& operator&=( const CScriptNum& rhs) { return operator&=(rhs.m_value); }
298289

290+
inline CScriptNum operator*(const __int128_t& rhs) const { return CScriptNum(m_value * rhs);}
291+
inline CScriptNum operator*(const CScriptNum& rhs) const { return operator*(rhs.m_value);}
292+
293+
inline CScriptNum operator/(const __int128_t& rhs) const { return CScriptNum(m_value / rhs);}
294+
inline CScriptNum operator/(const CScriptNum& rhs) const { return operator/(rhs.m_value);}
295+
299296
inline CScriptNum operator-() const
300297
{
301-
assert(m_value != std::numeric_limits<int64_t>::min());
298+
assert(m_value != std::numeric_limits<__int128_t>::min());
302299
return CScriptNum(-m_value);
303300
}
304301

@@ -310,16 +307,16 @@ class CScriptNum
310307

311308
inline CScriptNum& operator+=( const int64_t& rhs)
312309
{
313-
assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
314-
(rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
310+
assert(rhs == 0 || (rhs > 0 && m_value <= std::numeric_limits<__int128_t>::max() - rhs) ||
311+
(rhs < 0 && m_value >= std::numeric_limits<__int128_t>::min() - rhs));
315312
m_value += rhs;
316313
return *this;
317314
}
318315

319316
inline CScriptNum& operator-=( const int64_t& rhs)
320317
{
321-
assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
322-
(rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
318+
assert(rhs == 0 || (rhs > 0 && m_value >= std::numeric_limits<__int128_t>::min() + rhs) ||
319+
(rhs < 0 && m_value <= std::numeric_limits<__int128_t>::max() + rhs));
323320
m_value -= rhs;
324321
return *this;
325322
}
@@ -340,20 +337,21 @@ class CScriptNum
340337
}
341338

342339
int64_t GetInt64() const { return m_value; }
343-
340+
__int128_t GetInt128() const {return m_value; }
344341
std::vector<unsigned char> getvch() const
345342
{
346343
return serialize(m_value);
347344
}
348345

349-
static std::vector<unsigned char> serialize(const int64_t& value)
346+
static std::vector<unsigned char> serialize(const __int128_t& value)
350347
{
351-
if(value == 0)
348+
if(value == 0) {
352349
return std::vector<unsigned char>();
350+
}
353351

354352
std::vector<unsigned char> result;
355353
const bool neg = value < 0;
356-
uint64_t absvalue = neg ? ~static_cast<uint64_t>(value) + 1 : static_cast<uint64_t>(value);
354+
__uint128_t absvalue = neg ? ~static_cast<__uint128_t>(value) + 1 : static_cast<__uint128_t>(value);
357355

358356
while(absvalue)
359357
{
@@ -371,33 +369,35 @@ class CScriptNum
371369
// 0x80 to it, since it will be subtracted and interpreted as a negative when
372370
// converting to an integral.
373371

374-
if (result.back() & 0x80)
372+
if (result.back() & 0x80) {
375373
result.push_back(neg ? 0x80 : 0);
376-
else if (neg)
374+
}
375+
else if (neg) {
377376
result.back() |= 0x80;
377+
}
378378

379379
return result;
380380
}
381381

382382
private:
383-
static int64_t set_vch(const std::vector<unsigned char>& vch)
383+
static __int128_t set_vch(const std::vector<unsigned char>& vch)
384384
{
385385
if (vch.empty())
386386
return 0;
387387

388-
int64_t result = 0;
388+
__int128_t result = 0;
389389
for (size_t i = 0; i != vch.size(); ++i)
390-
result |= static_cast<int64_t>(vch[i]) << 8*i;
390+
result |= static_cast<__int128_t>(vch[i]) << 8*i;
391391

392392
// If the input vector's most significant byte is 0x80, remove it from
393393
// the result's msb and return a negative.
394394
if (vch.back() & 0x80)
395-
return -((int64_t)(result & ~(0x80ULL << (8 * (vch.size() - 1)))));
395+
return -((__int128_t)(result & ~(0x80ULL << (8 * (vch.size() - 1)))));
396396

397397
return result;
398398
}
399399

400-
int64_t m_value;
400+
__int128_t m_value;
401401
};
402402

403403
/**

src/script/script_error.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ std::string ScriptErrorString(const ScriptError serror)
115115
return "Using OP_CODESEPARATOR in non-witness script";
116116
case SCRIPT_ERR_SIG_FINDANDDELETE:
117117
return "Signature is found in scriptCode";
118+
case SCRIPT_ERR_ARITHMETIC64:
119+
return "Arithmetic opcode error";
118120
case SCRIPT_ERR_UNKNOWN_ERROR:
119121
case SCRIPT_ERR_ERROR_COUNT:
120122
default: break;

src/script/script_error.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,11 @@ typedef enum ScriptError_t
8282
SCRIPT_ERR_OP_CODESEPARATOR,
8383
SCRIPT_ERR_SIG_FINDANDDELETE,
8484

85-
SCRIPT_ERR_ERROR_COUNT
85+
SCRIPT_ERR_ERROR_COUNT,
86+
87+
/* 64bit arithmetic opcode errors */
88+
SCRIPT_ERR_ARITHMETIC64
89+
8690
} ScriptError;
8791

8892
#define SCRIPT_ERR_LAST SCRIPT_ERR_ERROR_COUNT

src/script/sign.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <script/interpreter.h>
1414
#include <script/keyorigin.h>
1515
#include <script/signingprovider.h>
16+
#include <script/sigversion.h>
1617
#include <uint256.h>
1718

1819
class CKey;

src/script/sigversion.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#ifndef BITCOIN_SCRIPT_SIGVERSION_H
2+
#define BITCOIN_SCRIPT_SIGVERSION_H
3+
enum class SigVersion
4+
{
5+
BASE = 0, //!< Bare scripts and BIP16 P2SH-wrapped redeemscripts
6+
WITNESS_V0 = 1, //!< Witness v0 (P2WPKH and P2WSH); see BIP 141
7+
TAPROOT = 2, //!< Witness v1 with 32-byte program, not BIP16 P2SH-wrapped, key path spending; see BIP 341
8+
TAPSCRIPT = 3, //!< Witness v1 with 32-byte program, not BIP16 P2SH-wrapped, script path spending, leaf version 0xc0; see BIP 342
9+
TAPSCRIPT_64BIT = 4, //!< Witness v1 with 32 byte program script path spending with 64bit arithmetic
10+
};
11+
#endif // BITCOIN_SCRIPT_SIGVERSION_H

src/test/script_tests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1700,8 +1700,9 @@ BOOST_AUTO_TEST_CASE(bip341_keypath_test_vectors)
17001700
BOOST_CHECK_EQUAL(HexStr(sighash), input["intermediary"]["sigHash"].get_str());
17011701

17021702
// To verify the sigmsg, hash the expected sigmsg, and compare it with the (expected) sighash.
1703-
BOOST_CHECK_EQUAL(HexStr((HashWriter{HASHER_TAPSIGHASH} << std::span<const uint8_t>{ParseHex(input["intermediary"]["sigMsg"].get_str())}).GetSHA256()), input["intermediary"]["sigHash"].get_str());
1703+
BOOST_CHECK_EQUAL(HexStr((HashWriter{HASHER_TAPSIGHASH} << Span{ParseHex(input["intermediary"]["sigMsg"].get_str())}).GetSHA256()), input["intermediary"]["sigHash"].get_str());
17041704
}
1705+
17051706
}
17061707
}
17071708

0 commit comments

Comments
 (0)